Skip to content

Commit

Permalink
docs: Fixed docs to reflect current implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
huyenngn committed Mar 6, 2024
1 parent df3059c commit d0c65ed
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 119 deletions.
5 changes: 3 additions & 2 deletions capella_ros_tools/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def import_msgs(
def export_capella(
model: capellambse.MelodyModel,
layer: str,
msg_path: pathlib.Path,
messages: pathlib.Path,
):
"""Export Capella data package to ROS messages.
Expand All @@ -94,7 +94,8 @@ def export_capella(
"""
from capella_ros_tools.scripts import export_capella as exporter

exporter.Exporter(model, layer, msg_path)()
current_pkg = getattr(model, layer).data_package
exporter.export(current_pkg, messages)


if __name__ == "__main__":
Expand Down
122 changes: 55 additions & 67 deletions capella_ros_tools/scripts/export_capella.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import pathlib
import re

import capellambse
from capellambse.model.crosslayer import information

from capella_ros_tools import data_model
Expand All @@ -17,75 +16,64 @@ def _clean_name(name: str) -> str:
return re.sub(r"\W", "", name)


class Exporter:
"""Class for exporting a Capella data package as ROS messages."""

def __init__(
self,
model: capellambse.MelodyModel,
layer: str,
output_path: pathlib.Path,
):
self._data_package = getattr(model, layer).data_package
output_path.mkdir(parents=True, exist_ok=True)
self._output_path = output_path

def _handle_pkg(
self,
current_pkg: information.DataPkg,
current_path: pathlib.Path,
):
for cls_obj in current_pkg.classes:
cls_def = data_model.MessageDef(
cls_obj.name, [], [], cls_obj.description
def export(current_pkg: information.DataPkg, current_path: pathlib.Path):
"""Export a Capella data package to ROS messages."""
for cls_obj in current_pkg.classes:
fields = []
for prop_obj in cls_obj.owned_properties:
type_def = data_model.TypeDef(
name=prop_obj.type.name,
card=data_model.Range(
prop_obj.min_card.value, prop_obj.max_card.value
),
)
for prop_obj in cls_obj.owned_properties:
type_def = data_model.TypeDef(
prop_obj.type.name,
data_model.Range(
prop_obj.min_card.value, prop_obj.max_card.value
),
)
prop_def = data_model.FieldDef(
type_def, prop_obj.name, prop_obj.description
)
cls_def.fields.append(prop_def)
(current_path / f"{_clean_name(cls_obj.name)}.msg").write_text(
str(cls_def)
prop_def = data_model.FieldDef(
type=type_def,
name=prop_obj.name,
description=prop_obj.description,
)
fields.append(prop_def)
cls_def = data_model.MessageDef(
name=cls_obj.name,
fields=fields,
enums=[],
description=cls_obj.description,
)
(current_path / f"{_clean_name(cls_obj.name)}.msg").write_text(
str(cls_def)
)

for enum_obj in current_pkg.enumerations:
enum_def = data_model.EnumDef(
enum_obj.name, [], enum_obj.description
for enum_obj in current_pkg.enumerations:
literals = []
for i, lit_obj in enumerate(enum_obj.owned_literals):
try:
type_name = lit_obj.value.type.name
except AttributeError:
type_name = "uint8"
try:
literal_value = lit_obj.value.value
except AttributeError:
literal_value = i
type_def = data_model.TypeDef(
type_name, data_model.Range("1", "1")
)
for i, lit_obj in enumerate(enum_obj.owned_literals):
try:
type_name = lit_obj.value.type.name
except AttributeError:
type_name = "uint8"
try:
literal_value = lit_obj.value.value
except AttributeError:
literal_value = i
type_def = data_model.TypeDef(
type_name, data_model.Range("1", "1")
)
lit_def = data_model.ConstantDef(
type_def,
lit_obj.name,
literal_value,
lit_obj.description,
)
enum_def.literals.append(lit_def)
(current_path / f"{_clean_name(enum_obj.name)}.msg").write_text(
str(enum_def)
lit_def = data_model.ConstantDef(
type=type_def,
name=lit_obj.name,
value=literal_value,
description=lit_obj.description,
)
literals.append(lit_def)
enum_def = data_model.EnumDef(
name=enum_obj.name,
literals=literals,
description=enum_obj.description,
)
(current_path / f"{_clean_name(enum_obj.name)}.msg").write_text(
str(enum_def)
)

for pkg_obj in current_pkg.packages:
pkg_path = current_path / _clean_name(pkg_obj.name)
pkg_path.mkdir(parents=True, exist_ok=True)
self._handle_pkg(pkg_obj, pkg_path)

def __call__(self):
"""Export the Capella data package as ROS messages."""
self._handle_pkg(self._data_package, self._output_path)
for pkg_obj in current_pkg.packages:
pkg_path = current_path / _clean_name(pkg_obj.name)
pkg_path.mkdir(parents=True, exist_ok=True)
export(pkg_obj, pkg_path)
21 changes: 16 additions & 5 deletions docs/source/howtos.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,35 @@ Import ROS2 Messages:
---------------------
.. code-block:: bash
$ python -m capella_ros_tools import tests/data/example_msgs tests/data/empty_model la --exists-action=skip --port=5000 --no-deps
$ python -m capella_ros_tools import \
tests/data/data_model/example_msgs \
tests/data/empty_project_52 la \
--port=5000 --no-deps
Import ROS2 Messages from Git Repository:
-----------------------------------------
.. code-block:: bash
$ python -m capella_ros_tools import git+https://github.com/DSD-DBS/dsd-ros-msg-definitions-oss tests/data/empty_model la --exists-action=skip --port=5000
$ python -m capella_ros_tools import \
git+https://github.com/DSD-DBS/dsd-ros-msg-definitions-oss \
tests/data/empty_project_52 la \
--port=5000
Export Capella data package:
------------------------------------
.. code-block:: bash
$ python -m capella_ros_tools export tests/data/melody_model_60 la tests/data/melody_msgs
$ python -m capella_ros_tools export \
tests/data/melody_model_60 la \
tests/data/melody_msgs
Export Capella data package from Git Repository:
--------------------------------------------------------
.. code-block:: bash
$ python -m capella_ros_tools export git+https://github.com/DSD-DBS/coffee-machine oa tests/data/coffee_msgs
$ python -m capella_ros_tools export \
git+https://github.com/DSD-DBS/coffee-machine oa \
tests/data/coffee_msgs
Note: When exporting Capella enumerations, if the enumeration values are not defined in the Capella model, the values will be set to 0, 1, 2, 3, etc. and the datatype will be set to unit8.
.. note::
When exporting Capella enumerations, if the enumeration literal values are not defined in the Capella model, the values will be set to 0, 1, 2, 3, etc. and the value's type will be set to unit8.
27 changes: 4 additions & 23 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,22 @@ Overview

Capella ROS Tools is a command-line application written in Python, designed to facilitate the seamless integration of ROS2 and Capella MBSE tools. Key features include:

* generate ROS2 message files (.msg) from Capella models
* generate Capella elements and objects from ROS2 message files
* support input sources through both local file paths and Git repositories
* display snapshots of Capella model elements in a tree structure

If you want a quickstart at how to use this tool, head right into the
:ref:`Usage section <usage>`.
* Export Capella model elements as ROS2 message (.msg) files.
* Import ROS2 message (.msg) files as Capella model elements.
* Works with local and remote message files/Capella projects.


.. toctree::
:maxdepth: 2
:caption: Contents:

.. toctree::
:maxdepth: 2
:caption: Usage

usage


.. toctree::
:maxdepth: 2
:caption: Examples

howtos

.. toctree::
:maxdepth: 2
:caption: ROS2 Messages Layout

messages

.. toctree::
:maxdepth: 3
:caption: API reference
:caption: API reference:

code/modules

Expand Down
12 changes: 6 additions & 6 deletions docs/source/messages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Class Definition
* **Indented Comment Lines:** Comments on a line of their own but indented are added to the description of the last encountered property.
* **Block Comments:** Comments on a line of their own and not indented are added to the description of the next properties until an empty line and the block comment has been used.

.. literalinclude:: ../../tests/data/example_msgs/msg/SampleClass.msg
.. literalinclude:: ../../tests/data/data_model/example_msgs/package1/msg/SampleClass.msg
:language: python


Expand All @@ -33,7 +33,7 @@ Enum definition
* **Indented Comment Lines:** Comments on a line of their own but indented are added to the description of the last encountered enum literal.
* **Block Comments:** Comments on a line of their own and not indented are added to the description of the next/current enum definition until an empty line and the block comment has been used.

.. literalinclude:: ../../tests/data/example_msgs/msg/SampleEnum.msg
.. literalinclude:: ../../tests/data/data_model/example_msgs/package1/msg/SampleEnum.msg
:language: python

Enum and Class Definition
Expand All @@ -46,7 +46,7 @@ Enum and Class Definition
* **Indented Comment Lines:** Comments on a line of their own but indented are added to the description of the last encountered property or enum literal.
* **Block Comments:** Comments on a line of their own and not indented are added to the descriptions of the next properties or added to the descriptions of the next/current enum until an empty line and the block comment has been used.

.. literalinclude:: ../../tests/data/example_msgs/msg/SampleClassEnum.msg
.. literalinclude:: ../../tests/data/data_model/example_msgs/package2/msg/SampleClassEnum.msg
:language: python

Referencing enums
Expand All @@ -61,7 +61,7 @@ In the Same File

* Name matching takes precedence over type matching.

.. literalinclude:: ../../tests/data/example_msgs/msg/SampleClassEnum.msg
.. literalinclude:: ../../tests/data/data_model/example_msgs/package2/msg/SampleClassEnum.msg
:language: python

In another file
Expand All @@ -72,8 +72,8 @@ In another file
* **cf. <File Name>:** The enum name was derived from the file name (excluding the extension).
* **cf. <File Name>, <Common Prefix>_XXX:** The enum name was derived from the longest common prefix of all enum literals in the definition.

.. literalinclude:: ../../tests/data/example_msgs/msg/SampleEnum.msg
.. literalinclude:: ../../tests/data/data_model/example_msgs/package1/msg/SampleEnum.msg
:language: python

.. literalinclude:: ../../tests/data/example_msgs/msg/SampleClass.msg
.. literalinclude:: ../../tests/data/data_model/example_msgs/package1/msg/SampleClass.msg
:language: python
25 changes: 12 additions & 13 deletions docs/source/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,31 @@ Import ROS2 Messages:
----------------------
.. code-block:: bash
$ python -m capella_ros_tools import <ROS_MESSAGES_PATH> <CAPELLA_MODEL_PATH> <CAPELLA_MODEL_LAYER> --port=<PORT> --exists-action=<EXISTS_ACTION> --no-deps
$ python -m capella_ros_tools import \
<ROS_MESSAGES_PATH> \
<CAPELLA_MODEL_PATH> \
<CAPELLA_MODEL_LAYER> \
--port=<PORT> \
--no-deps
* **<ROS_MESSAGES_PATH>**, import ROS2 messages from <ROS_MESSAGES_PATH>
* **<CAPELLA_MODEL_PATH>**, export to Capella model <CAPELLA_MODEL_PATH>
* **<CAPELLA_MODEL_LAYER>**, use Capella model layer <CAPELLA_MODEL_LAYER>
* **--port=<PORT>**, start Capella model viewer at <PORT> (optional)
* **--exists-action=<EXISTS_ACTION>**, action to take if a Capella element already exists (optional)

* **skip**, skip elements
* **replace**, replace elements
* **abort**, abort import
* **ask**, ask the user (default)

* **--no-deps**, do not import ROS2 dependencies (e.g. std_msgs)

Tip: Use the `--port` option to start the Capella model viewer at a specific port. The Capella model viewer can then be downloaded to be viewed at a later time using the following command:
.. code-block:: bash
$ wget http://localhost:<PORT> -E -r
.. note::
The `--port` option can be used to start the Capella model explorer on a specific port. The Capella model viewer can then be downloaded to be viewed at a later time using `wget` eg. `wget http://localhost:<PORT> -E -r`.


Export Capella Model (experimental):
------------------------------------
.. code-block:: bash
$ python -m capella_ros_tools export <CAPELLA_MODEL_PATH> <CAPELLA_MODEL_LAYER> <ROS_MESSAGES_PATH>
$ python -m capella_ros_tools export \
<CAPELLA_MODEL_PATH> \
<CAPELLA_MODEL_LAYER> \
<ROS_MESSAGES_PATH>
* **<CAPELLA_MODEL_PATH>**, import Capella model from <CAPELLA_MODEL_PATH>
* **<CAPELLA_MODEL_LAYER>**, use Capella model layer <CAPELLA_MODEL_LAYER>
Expand Down
3 changes: 0 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ classifiers = [
dependencies = [
"click",
"capellambse@ git+https://github.com/DSD-DBS/py-capellambse.git@decl-sync",
"capellambse_context_diagrams",
"fastapi",
"uvicorn[standard]",
]

[project.urls]
Expand Down

0 comments on commit d0c65ed

Please sign in to comment.