diff --git a/README.md b/README.md deleted file mode 100644 index 0e1c0b8..0000000 --- a/README.md +++ /dev/null @@ -1,74 +0,0 @@ -## RosTooling - -Welcome to the RosTooling documentation page! :) - -The RosTooling aims to bridge the advantages of ROS with those of model-driven software development. At its core are a set of models that describe "every day" code developed by ROS developers, both at the component and system levels. These models are supported with different types of tools including model extractors from code, validators and code generators. - -We invite you to take a look at the tutorials to learn more about this tooling and its uses. - -The [source code](https://github.com/ipa320/RosTooling) of the entire implementation of the tooling is completely open-source, contributions, feedback and suggestions are always welcome. - -### Installation - -- [From Release](docu/Installation.md#option-1-using-the-release-version-recommended) -- [Setup](docu/Environment_setup.md#1-switch-to-the-ros-developer-perspective) - -### Models Review - -The RosTooling divides the ROS concepts into three layers of models: - -- Ros objects models: they represent the interface types. In ROS world the message, services and action types. This file has the .ros extension and allows a yaml format similar to the ROS .msgs, .srvs and .action files. -- Ros packages (component) models: they represent the filesystem level of ROS packages, as well as the computational graph. In other words, the package description, the implemented artifacts and the communication ports the nodes offer. They have two different implementations, for ROS (1) (.ros1 extension) or for ROS 2 (.ros2 extension files.) -- Ros System models: they represent the ROS nodes as components present in a system and the connections among them. The file extension of this type of model is .rossystem. - -#### Components (.ros1, .ros2) - -- [How to describe ROS nodes using models](docu/RosModelDescription.md) -- [Parameters API reference and examples](docu/ParametersAPI.md) - -#### Communication objects (.ros) -- [Messages, services and actions generator](docu/NewCommunicationObjects.md) - -#### Systems (.rossystem) -- [How to describe ROS systems using model](docu/RosSystemModelDescription.md) - -### Tutorials - -![](docu/images/Attention.png) All tutorials were created on Linux. In addition, some of them require a local installation of ROS 2, whose are marked with the logo (![](docu/images/Ros2_logo_mini.png)). The modeling part should run on other OS so far Eclipse is properly installed and also the required Java packages (jre and jdk), the current version of the RosTooling requires Java 19 or higher. - -In case you have already installed the RosTooling, we recommend to pull always the latest version, go to "Help"->"Check for Updates", in case a new version is available it will be proposed to be updated. - -If you get issues during the execution of these tutorials please report them under the following [https://github.com/ipa320/RosTooling.github.io/issues](https://github.com/ipa320/RosTooling.github.io/issues/new?assignees=&labels=&projects=&template=bug_report.md&title=). In case you don't have a GitHub account, please just send an email to nhg@ipa.fhg.de. - -Also, we will be very thankful if once you complete the tutorials you take 15 minutes to fulfill our survey, this will help us to improve our solution: [Survey link](https://forms.office.com/e/2V5pPwcY7V). - -Many thanks for your help :) - - - - -#### Components - -- [Review models and use of textual editor](docu/LearnRosModels.md) -- ~~(Optional) [Create your own model](docu/CreateYourModel.md)~~ -- [Generate code from model description](docu/rossdl.md) (![](docu/images/Ros2_logo_mini.png)) -- [Extract models using static code analysis](docu/StaticCodeAnalyis.md) (![](docu/images/docker_logo.png)) -- [Extract component models using introspection at runtime](docu/ros2model.md) (![](docu/images/Ros2_logo_mini.png)) - -#### Systems - -- [Review models and use of textual editor](docu/LearnRosSystemModels.md) -- [Other ways to define a system](docu/LearnRosSystemModels2.md) - -- [Code generator review](docu/CodeGeneration.md) -- [System Models visualization](docu/SystemModelsVisualization.md) -- Real use cases execution: - - [Turtlesim](docu/Example_Turtlesim.md) (![](docu/images/Ros2_logo_mini.png)) - - [Beginner - Mobile base on simulation](docu/MobileBase_beginner.md) (![](docu/images/Ros2_logo_mini.png)) - - ~~[TBD - Advanced - Manipulation](docu/Manipulation_advanced.md)~~ (![](docu/images/Ros2_logo_mini.png)) - -### Extra material - -- [Eclipse known issues](docu/eclipse_issues.md) -- [RosTooling Known issues](docu/RosTooling_issues.md) -- [Create your own model from nodes](docu/Example_PubSub.md) \ No newline at end of file diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..4e9bed3 --- /dev/null +++ b/README.rst @@ -0,0 +1,98 @@ +RosTooling +========== + +Welcome to the RosTooling documentation page! :) + +The RosTooling aims to bridge the advantages of ROS with those of model-driven software development. At its core are a set of models that describe "every day" code developed by ROS developers, both at the component and system levels. These models are supported with different types of tools including model extractors from code, validators, and code generators. + +We invite you to take a look at the tutorials to learn more about this tooling and its uses. + +The `source code `_ of the entire implementation of the tooling is completely open-source. Contributions, feedback, and suggestions are always welcome. + +Installation +------------ + +- `From Release `_ +- `Setup `_ + +Models Review +------------- + +The RosTooling divides the ROS concepts into three layers of models: + +- **Ros objects models**: They represent the interface types. In ROS world, these are the message, services, and action types. This file has the `.ros` extension and allows a YAML format similar to the ROS `.msgs`, `.srvs`, and `.action` files. +- **Ros packages (component) models**: They represent the filesystem level of ROS packages, as well as the computational graph. In other words, the package description, the implemented artifacts, and the communication ports the nodes offer. They have two different implementations, for ROS (1) (`.ros1` extension) or for ROS 2 (`.ros2` extension files.) +- **Ros System models**: They represent the ROS nodes as components present in a system and the connections among them. The file extension of this type of model is `.rossystem`. + +Components (.ros1, .ros2) +~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `How to describe ROS nodes using models `_ +- `Parameters API reference and examples `_ + +Communication objects (.ros) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `Messages, services and actions generator `_ + +Systems (.rossystem) +~~~~~~~~~~~~~~~~~~~~ + +- `How to describe ROS systems using model `_ + +Tutorials +--------- + +.. image:: docu/images/Attention.png + :alt: Attention + +All tutorials were created on Linux. In addition, some of them require a local installation of ROS 2, which are marked with the logo: + +.. image:: docu/images/Ros2_logo_mini.png + :alt: ROS 2 logo + +The modeling part should run on other OS as long as Eclipse is properly installed and also the required Java packages (JRE and JDK). The current version of the RosTooling requires Java 19 or higher. + +In case you have already installed the RosTooling, we recommend always pulling the latest version. Go to "Help" -> "Check for Updates", and in case a new version is available, it will be proposed to be updated. + +If you encounter issues during the execution of these tutorials, please report them under the following `GitHub Issues `_. If you don't have a GitHub account, please just send an email to nhg@ipa.fhg.de. + +Also, we would be very thankful if once you complete the tutorials, you take 15 minutes to fill out our survey. This will help us to improve our solution: `Survey link `_. + +Many thanks for your help :) + +Components +~~~~~~~~~~ + +- `Review models and use of textual editor `_ +- (Optional) `Create your own model `_ +- `Generate code from model description `_ .. image:: docu/images/Ros2_logo_mini.png +- `Extract models using static code analysis `_ .. image:: docu/images/docker_logo.png +- `Extract component models using introspection at runtime `_ .. image:: docu/images/Ros2_logo_mini.png + +Systems +~~~~~~~ + +- `Review models and use of textual editor `_ +- `Other ways to define a system `_ +- `Code generator review `_ +- `System Models visualization `_ +- Real use cases execution: + + - `Turtlesim `_ + + - `Beginner - Mobile base on simulation `_ + + - `TBD - Advanced - Manipulation `_ + +.. |ros2| image:: docu/images/Ros2_logo_mini.png + :alt: ROS2 logo + :scale: 100% + :background: white + +Extra material +-------------- + +- `Eclipse known issues `_ +- `RosTooling Known issues `_ +- `Create your own model from nodes `_ diff --git a/docu/CodeGeneration.md b/docu/CodeGeneration.md deleted file mode 100644 index f0eb1e1..0000000 --- a/docu/CodeGeneration.md +++ /dev/null @@ -1,17 +0,0 @@ -## Systems code generator review - -For the System model, the generation of code is automatic, which means if your model is correct and follows the connection rules, Xtext will automatically generate into the *src-gen* folder a ROS package which has the typical structure of a python package meant to hold launch file artifacts. More concretely: - -* README file: this file will always be generated even in the cases of a system that only points to an existing launch file. The README contains information about the design of the system. But also how to install the dependencies, set up the workspace to hold the created implementation and start the generated artifact. -* setup.py script: it is just the standard script required by a Python package which is specifically created for the structure of this package. -* package.xml file: a template for the package.xml of the package which contains the specification of all the required dependencies to start the package. The user should complete the type of the license, the maintainer and owner and the description of the package. -* CMakeLists.txt: a template of the package.xml which includes the required tags to install the newly created files. -* launch/NameOfTheSystem.launch.py script: This is the core of the generator. This is a **ready-to-execute** file that based on the .rossystem description: - * Add includes to all the defined nodes as components - * Define and set the value of the parameters. For packages containing more than 5 parameters the .yaml file under the "config" folder will be loaded and launched. - * Remap topics to force connections. This is only working for nodes that are part of the system as components, not for subsystems. See [known issues](RosTooling_issues.md#code-generators) - * Include other launch files from subsystems. -* resource/NameOfTheSystem.puml: [An example of a PlantUML implementation of the described system](SystemModelsVisualization.md#open-the-plantuml-auto-generated-description) -* config/NameOfTheSystem.yaml: this file contains the configuration of the parameters. It will only be used in case of the set of 5 parameters or more. - -With the current implementation of RosTooling adding new code generators to the .rossystem representation is very easy, please report on our survey on the open-ended questions your wishes like for example, the generation of install scripts and/or Docker container configuration or ROS1-ROS2 bridges. diff --git a/docu/CodeGeneration.rst b/docu/CodeGeneration.rst new file mode 100644 index 0000000..9705f77 --- /dev/null +++ b/docu/CodeGeneration.rst @@ -0,0 +1,24 @@ +Systems code generator review +============================= + +For the System model, the generation of code is automatic. This means if your model is correct and follows the connection rules, Xtext will automatically generate a ROS package into the *src-gen* folder, which has the typical structure of a Python package meant to hold launch file artifacts. More concretely: + +- **README file**: This file will always be generated, even in cases of a system that only points to an existing launch file. The README contains information about the design of the system, as well as how to install the dependencies, set up the workspace to hold the created implementation, and start the generated artifact. + +- **setup.py script**: This is the standard script required for a Python package, specifically created for the structure of this package. + +- **package.xml file**: A template for the `package.xml` of the package, which contains the specification of all the required dependencies to start the package. The user should complete the type of license, maintainer, owner, and description of the package. + +- **CMakeLists.txt**: A template of the `package.xml`, which includes the required tags to install the newly created files. + +- **launch/NameOfTheSystem.launch.py script**: This is the core of the generator. It is a **ready-to-execute** file based on the `.rossystem` description: + - Add includes for all the defined nodes as components + - Define and set the values of the parameters. For packages containing more than 5 parameters, the `.yaml` file under the "config" folder will be loaded and launched. + - Remap topics to force connections (only working for nodes that are part of the system as components, not for subsystems). See `known issues `_. + - Include other launch files from subsystems. + +- **resource/NameOfTheSystem.puml**: `An example of a PlantUML implementation of the described system `_. + +- **config/NameOfTheSystem.yaml**: This file contains the configuration of the parameters. It will only be used if there are 5 or more parameters. + +With the current implementation of RosTooling, adding new code generators to the `.rossystem` representation is very easy. Please report on our survey's open-ended questions regarding your wishes, such as the generation of install scripts, Docker container configuration, or ROS1-ROS2 bridges. diff --git a/docu/CreateYourModel.md b/docu/CreateYourModel.md deleted file mode 100644 index 5562c78..0000000 --- a/docu/CreateYourModel.md +++ /dev/null @@ -1,7 +0,0 @@ -# Create your model - -You can create a new file with the extension .ros2 in the rosnodes folder from the previously created [project](LearnRosModels.md) by right-clicking in the folder and selecting New -> File. - -This will create an empty file where you can create your model. As a helper, you can use the [reference documentation](RosModelDescription.md) and press Ctrl + Space bar to use the auto-complete functionality. - -If auto-complete or the grammar highlighting is not working, check that the file is open with the "Ros 2 Editor" with a right-click on the file and under "Open with..". \ No newline at end of file diff --git a/docu/CreateYourModel.rst b/docu/CreateYourModel.rst new file mode 100644 index 0000000..2d21d95 --- /dev/null +++ b/docu/CreateYourModel.rst @@ -0,0 +1,8 @@ +Create your model +================= + +You can create a new file with the extension `.ros2` in the `rosnodes` folder from the previously created `project `_ by right-clicking on the folder and selecting **New -> File**. + +This will create an empty file where you can create your model. As a helper, you can use the `reference documentation `_ and press **Ctrl + Space** to use the auto-complete functionality. + +If auto-complete or the grammar highlighting is not working, check that the file is opened with the "Ros 2 Editor" by right-clicking on the file and selecting **Open with...**. diff --git a/docu/Environment_setup.md b/docu/Environment_setup.md deleted file mode 100644 index 6607b9a..0000000 --- a/docu/Environment_setup.md +++ /dev/null @@ -1,34 +0,0 @@ -# Setup the environment and start the Eclipse application - - - -### Switch to the ROS Developer perspective - -Go to Menu Window -> Perspective -> Open Perspective -> Other... -> ROS developer. Your application toolbar will be automatically configured. - -### Import the common communication objects project - -import the project located under the "ROSCommonObjects" folder of this repository to the workbench of your application: -``` -de.fraunhofer.ipa.ros.communication.objects -``` - -If you have internet a button can clone from GitHub the objects to your workspace and import them automatically: - -![alt text](images/clone_and_import.png) - -![](images/Attention.png) This button will only work on Linux machines. Alternatively, you can clone manually the [repository](https://github.com/ipa320/RosCommonObjects) and import the project by File -> Import -> General -> Existing Projects into Workspace. Then select the container folder of the cloned repository. - -### Import the catalog - -Also, you can download and import a pre-existing catalog of examples. The catalog is publicly available on GitHub [ipa-nhg/RosModelsCatalog](https://github.com/ipa-nhg/RosModelsCatalog). - -Please clone the repository and import it to your Eclipse workspace. This can be easily done by File -> Import -> General -> Existing Projects into Workspace. Then select the container folder of the cloned repository. - -![alt text](images/01_mobile_base_b.gif) \ No newline at end of file diff --git a/docu/Environment_setup.rst b/docu/Environment_setup.rst new file mode 100644 index 0000000..4108708 --- /dev/null +++ b/docu/Environment_setup.rst @@ -0,0 +1,35 @@ +Setup the environment and start the Eclipse application +======================================================= + +Switch to the ROS Developer perspective +--------------------------------------- + +Go to Menu *Window* -> *Perspective* -> *Open Perspective* -> *Other...* -> *ROS developer*. Your application toolbar will be automatically configured. + +Import the common communication objects project +----------------------------------------------- + +Import the project located under the "ROSCommonObjects" folder of this repository to the workbench of your application: + +.. code-block:: none + + de.fraunhofer.ipa.ros.communication.objects + +If you have an internet connection, you can use the button that clones the objects from GitHub into your workspace and imports them automatically: + +.. image:: images/clone_and_import.png + +.. image:: images/Attention.png + +This button will only work on Linux machines. Alternatively, you can manually clone the `repository `_ and import the project by navigating to *File* -> *Import* -> *General* -> *Existing Projects into Workspace*. +Then select the container folder of the cloned repository. + +Import the catalog +------------------ + +You can also download and import a pre-existing catalog of examples. The catalog is publicly available on GitHub: `ipa-nhg/RosModelsCatalog `_. + +Please clone the repository and import it into your Eclipse workspace. This can be easily done by navigating to *File* -> *Import* -> *General* -> *Existing Projects into Workspace*. +Then select the container folder of the cloned repository. + +.. image:: images/01_mobile_base_b.gif diff --git a/docu/Example_PubSub.md b/docu/Example_PubSub.md deleted file mode 100644 index 820475f..0000000 --- a/docu/Example_PubSub.md +++ /dev/null @@ -1,132 +0,0 @@ -# Tutorial: How to create a simple Publisher-Subscriber example. -In this tutorial, we just want to show how the models can be used to define ROS nodes. For this, we will see how two simple nodes can be defined, one that acts as a publisher of a "Hello World!" message and another that receives it as a subscriber. - -This tutorial is fictitious, it is not based on any existing ROS node. The ROS example is reflected in the models of the example [pub_sub_ros2](https://github.com/ipa-nhg/ros-model-examples/tree/main/pub_sub_ros2). - -The first step is to create a project to hold the models. - -To import this as a project in the RosTooling you can create a new modeling project. By File -> New -> Project -> General -> Project. Then you must give a name to the project, for example "Example" press next, and add as project reference "de.fraunhofer.ipa.ros.communication.objects". We recommend creating a folder called "rosnodes" within the project. - -![alt text](images/pubsub_tutorial1.gif) - -Once the project is created, you can create a new file my File -> New -> Other -> File. The file shall be created under the folder "rosnodes" and it must have the extension ".ros2", for example **publisher.ros2**. By creating a file type .ros2, Eclipse will convert the project to a Xtext project. Then copy the previous content to the new file. - -![alt text](images/pubsub_tutorial2.gif) - -Following the format of the [Ros model](RosModelDescription.md) we can now create a new Ros package, that contains a node with a publisher. - -The first line of the model must contain the name of the package, as part of the grammar of the model ":" will close the name definition line: - -``` -publisher_package: - -``` - -Then we need the artifact, a runnable to execute the node. As every YAML format file, we have to add indentation to the second line. Then pressing the keys "Ctrl"+Space bar the menu will suggest as an option the text "artifacts:". We select it and go to the next line. - -In the third line we must add a double indentation, we will create an object under artifacts. The next object will be a name for the artifact, for example, "pub_artifact": - -``` -publisher: - artifacts: - pub_artifact: -``` - -Similar to the artifact creation, we need to create a node, with the grammar "node: **NODENAME**": - -``` -publisher: - artifacts: - pub_artifact: - node: pub_node -``` -Now that we have the node, we can define the interfaces that offer this node as inputs and output to connect to it. In our case, we want to create a publisher, which is the type **String**** . - -![alt text](images/pubsub_tutorial3.gif) - - -The models will look similar to: - -``` -publisher: - artifacts: - pub_artifact: - node: pub_node - publishers: - my_pub: - type: "std_msgs/msg/String" -``` - -In the same way we can create a subscriber: - -![alt text](images/pubsub_tutorial4.gif) - -This new subscriber model will look like this: - -``` -subscriber: - artifacts: - sub_artifact: - node: sub_node - subscribers: - my_sub: - type: "std_msgs/msg/String" -``` - -Now that we have already the components we can compose them. For that, we have to create a new .rossystem file. Again go to File -> New -> Other -> File. The new file must have as extension .rossystem. - -In [RosSystem description](RosSystemModelDescription.md) we explain the format of a system and the editor will support you to write the model properly. - -The first that must be given is a name and then a ":" is required. In the next line, you must add indentation and you can press the keys "Ctrl" + Space bar for help. -Then we will define the nodes that compose the system. Here under "from" we will link our previously created nodes, the grammar for the references is **PackageName.NodeName**. - -![alt text](images/pubsub_tutorial5.gif) - -So far our file looks like this: -``` -my_system: - nodes: - publisher: - from: "publisher.pub_node" - subscriber: - from: "subscriber.sub_node" -``` - -Now, we want to expose the ports to be connected. For that, we have to define the interfaces under the nodes. And again we have to reference the created interfaces, with the grammar **NodeName::InterfaceName**. - -![alt text](images/pubsub_tutorial6.gif) - -And the model is updated to: -``` -my_system: - nodes: - publisher: - from: "publisher.pub_node" - interfaces: - - HelloWorldPublisher: pub-> "pub_artifact::my_pub" - subscriber: - from: "subscriber.sub_node" - interfaces: - - HelloWorldSubscriber: sub-> "sub_artifact::my_sub" -``` -The last step is to create a connection between the two components. For that, we will use the connections description, under the system description. The connections must be done between interfaces instances described within the models, otherwise, the model validator will give an error. - -![alt text](images/pubsub_tutorial7.gif) - -And the model is updated to: -``` -my_system: - nodes: - publisher: - from: "publisher.pub_node" - interfaces: - - HelloWorldPublisher: pub-> "pub_artifact::my_pub" - subscriber: - from: "subscriber.sub_node" - interfaces: - - HelloWorldSubscriber: sub-> "sub_artifact::my_sub" - connections: - -[ HelloWorldPublisher, HelloWorldSubscriber] -``` - -With this very basic example we hope you have understood how the models can be used and what kind of attributes they allow to represent. \ No newline at end of file diff --git a/docu/Example_PubSub.rst b/docu/Example_PubSub.rst new file mode 100644 index 0000000..d539bbc --- /dev/null +++ b/docu/Example_PubSub.rst @@ -0,0 +1,143 @@ +Tutorial: How to create a simple Publisher-Subscriber example +============================================================= + +In this tutorial, we demonstrate how the models can be used to define ROS nodes. We will define two simple nodes: one that acts as a publisher of a "Hello World!" message and another that receives it as a subscriber. + +This tutorial is fictitious and not based on any existing ROS node. The ROS example is reflected in the models of the example `pub_sub_ros2 `_. + +The first step is to create a project to hold the models. + +To import this as a project in the RosTooling, create a new modeling project by selecting **File -> New -> Project -> General -> Project**. Then, give the project a name (e.g., "Example"), press next, and add "de.fraunhofer.ipa.ros.communication.objects" as a project reference. We recommend creating a folder called "rosnodes" within the project. + +.. image:: images/pubsub_tutorial1.gif + :alt: Create new project + +Once the project is created, you can create a new file by selecting **File -> New -> Other -> File**. The file should be created under the "rosnodes" folder and must have the extension `.ros2` (e.g., **publisher.ros2**). By creating a file with the `.ros2` extension, Eclipse will convert the project to an Xtext project. Then, copy the provided content into the new file. + +.. image:: images/pubsub_tutorial2.gif + :alt: Create new file + +Following the format of the `Ros model `_, we can now create a new ROS package that contains a node with a publisher. + +The first line of the model must contain the name of the package. As part of the model's grammar, a colon `:` will close the name definition line: + +.. code-block:: yaml + + publisher_package: + +Next, we need the artifact, a runnable to execute the node. As in every YAML format file, we must add indentation to the second line. Then, by pressing **Ctrl + Space**, the menu will suggest the text "artifacts:". We select it and proceed to the next line. + +On the third line, we add double indentation and create an object under artifacts. The next object will be a name for the artifact, for example, "pub_artifact": + +.. code-block:: yaml + + publisher: + artifacts: + pub_artifact: + +Similarly, we create a node with the grammar `node: **NODENAME**`: + +.. code-block:: yaml + + publisher: + artifacts: + pub_artifact: + node: pub_node + +Now that we have the node, we can define the interfaces that offer this node as inputs and outputs to connect to it. In our case, we want to create a publisher, which is of type **String**. + +.. image:: images/pubsub_tutorial3.gif + :alt: Define publisher interface + +The models will look like this: + +.. code-block:: yaml + + publisher: + artifacts: + pub_artifact: + node: pub_node + publishers: + my_pub: + type: "std_msgs/msg/String" + +In the same way, we can create a subscriber: + +.. image:: images/pubsub_tutorial4.gif + :alt: Define subscriber interface + +The subscriber model will look like this: + +.. code-block:: yaml + + subscriber: + artifacts: + sub_artifact: + node: sub_node + subscribers: + my_sub: + type: "std_msgs/msg/String" + +Now that we have the components, we can compose them. For that, we need to create a new `.rossystem` file. Again, go to **File -> New -> Other -> File**. The new file must have the `.rossystem` extension. + +In the `RosSystem description `_, we explain the format of a system, and the editor will assist you in writing the model correctly. + +First, a name must be provided followed by a colon `:`. Then, add indentation, and press **Ctrl + Space** for help. Next, define the nodes that compose the system. Under "from", we link our previously created nodes using the grammar **PackageName.NodeName**. + +.. image:: images/pubsub_tutorial5.gif + :alt: Link nodes + +So far, our file looks like this: + +.. code-block:: yaml + + my_system: + nodes: + publisher: + from: "publisher.pub_node" + subscriber: + from: "subscriber.sub_node" + +Next, we expose the ports to be connected. To do this, define the interfaces under the nodes, using the grammar **NodeName::InterfaceName**. + +.. image:: images/pubsub_tutorial6.gif + :alt: Expose ports + +The model is updated to: + +.. code-block:: yaml + + my_system: + nodes: + publisher: + from: "publisher.pub_node" + interfaces: + - HelloWorldPublisher: pub-> "pub_artifact::my_pub" + subscriber: + from: "subscriber.sub_node" + interfaces: + - HelloWorldSubscriber: sub-> "sub_artifact::my_sub" + +The last step is to create a connection between the two components. We use the `connections` description under the system description. Connections must be made between interface instances described within the models, otherwise, the model validator will generate an error. + +.. image:: images/pubsub_tutorial7.gif + :alt: Create connections + +The final model looks like this: + +.. code-block:: yaml + + my_system: + nodes: + publisher: + from: "publisher.pub_node" + interfaces: + - HelloWorldPublisher: pub-> "pub_artifact::my_pub" + subscriber: + from: "subscriber.sub_node" + interfaces: + - HelloWorldSubscriber: sub-> "sub_artifact::my_sub" + connections: + - [ HelloWorldPublisher, HelloWorldSubscriber ] + +With this basic example, we hope you have understood how the models can be used and what kind of attributes they can represent. diff --git a/docu/Example_Turtlesim.md b/docu/Example_Turtlesim.md deleted file mode 100644 index e5c9ca4..0000000 --- a/docu/Example_Turtlesim.md +++ /dev/null @@ -1,142 +0,0 @@ -## Hands-on example for the Turtlesim node [![](images/Ros2_logo.png)] - -To learn ROS one of the first tutorials that everyone does is turtlesim. - -Basically, it is a small graphical interface where a turtle can be moved using the speed commands of any robotic base in ROS. [Official TurtleSim tutorial](https://docs.ros.org/en/foxy/Tutorials/Beginner-CLI-Tools/Introducing-Turtlesim/Introducing-Turtlesim.html) - -We will use it as an example to show the models. Let's imagine that we want to create a system in which we have two nodes, one of them is the turtlesim and the other is the node to teleoperate it. -The first thing we need to do is to create the models for both components. Both nodes are implemented in the [turtlesim](https://github.com/ros/ros_tutorials/tree/humble/turtlesim) package in the [ros_tutorials](https://github.com/ros/ros_tutorials/tree/humble) repository. - -We can create the component models manually or use our static code [analysis tools](https://github.com/ipa320/ros-model-extractors) to get them automatically. Using the second method we obtained the following models. - -``` -turtlesim: - fromGitRepo: "https://github.com/ros/ros_tutorials/" - artifacts: - turtle_teleop_key: - node: turtle_teleop_key - publishers: - cmd_vel: - type: "geometry_msgs/msg/Twist" - parameters: - scale_angular: - type: Double - default: 2.0 - scale_linear: - type: Double - default: 2.0 - turtlesim_node: - node: turtlesim_node - publishers: - color_sensor: - type: "turtlesim/msg/Color" - pose: - type: "turtlesim/msg/Pose" - subscribers: - cmd_vel: - type: "geometry_msgs/msg/Twist" - serviceservers: - teleport_absolute: - type: "turtlesim/srv/TeleportAbsolute" - spawn: - type: 'turtlesim/srv/Spawn' - set_pen: - type: 'turtlesim/srv/SetPen' - reset: - type: "std_srvs/srv/Empty" - kill: - type: 'turtlesim/srv/Kill' - teleport_relative: - type: 'turtlesim/srv/TeleportRelative' - clear: - type: 'std_srvs/srv/Empty' -``` - -To import this as a project in the RosTooling you can create a new modeling project. This can be done by pressing the icon "Add new ROS Project". - -![alt text](images/create_new_RosProject.png) - -If the button doesn't work you can also create it manually using the Eclipse menu File -> New -> Other.. and searching for "Ros Model Project". - -![alt text](images/first_project_tutorial.gif) - -By default, a new project with a reference to the content of the "de.fraunhofer.ipa.ros.communication.objects" will be created. This new project contains a folder called "rosnodes" to hold the nodes description and a file with the extension .ros2 which will have an error because it is empty. This can be removed for this case. - -Once the project is created, you can create a new file my File -> New -> Other -> File. We recommend giving as name to the file the name of the package and it must have the extension .ros2, this means the new file should be called **turtlesim.ros2**. By creating a file type .ros2, Eclipse will convert the project to an Xtext project. Then copy the previous model content to the new file. - -Now that we have already the components we can compose them. For that, we have to create a new .rossystem file. Again go to File -> New -> Other -> File. The new file must have an extension .rossystem. - -In [RosSystem description](RosSystemModelDescription.md) we explain the format of a system and the editor will support you to write the model properly. - -The first that must be given is a name and then a ":" is required. In the next line, you must add indentation and you can press the keys "Ctrl" + Space bar for help. -Firstly, we will add the 2 nodes that compose our system. - -![alt text](images/turtlesim_tutorial1.gif) - -So far our file looks like this: -``` -turtlesim_system: - nodes: - turtlesim: - from: "turtlesim.turtlesim_node" - key_teleop: - from: "turtlesim.turtle_teleop_key" -``` - -The "from" attributes are references to the previous **turtlesim.ros2** file nodes. If you change the name of them, the references must also be updated. - -Now, we want to expose the ports to be connected. This means the subscriber of the velocity command of the turtle and the publisher from the keyboard teleop: - -![alt text](images/turtlesim_tutorial2.gif) - -And the model is updated to: -``` -turtlesim_system: - nodes: - turtlesim: - from: "turtlesim.turtlesim_node" - interfaces: - - cmd_subscriber: sub-> "turtlesim_node::cmd_vel" - key_teleop: - from: "turtlesim.turtle_teleop_key" - interfaces: - - cmd_publisher: pub-> "turtle_teleop_key::cmd_vel" -``` - -Again, the interfaces are references to the ones already defined in the **turtlesim.ros2** file. In ROS terms, we can only create instantiate topics that are described on my original ROS code (cpp or python). - -The last step is to create a connection between the two components. - -![alt text](images/turtlesim_tutorial3.gif) - -And the model is updated to: -``` -turtlesim_system: - nodes: - turtlesim: - from: "turtlesim.turtlesim_node" - interfaces: - - cmd_subscriber: sub-> "turtlesim_node::cmd_vel" - key_teleop: - from: "turtlesim.turtle_teleop_key" - interfaces: - - cmd_publisher: pub-> "turtle_teleop_key::cmd_vel" - connections: - -[ cmd_publisher , cmd_subscriber] -``` - -If you save (Ctrl+S) after the last modifications a new folder "src-gen" will be automatically created. This folder contains a ROS 2 package ready to be executed with a launch file to start the designed system. - -For a quick check, if you source a valid ROS installation and call the launch command the turtlesim example will be launched: - -``` -source /opt/ros/ROSDISTRO/setup.bash -ros2 launch PATH_TO_LAUNCH_PY_FILE -``` - -Using the terminal of the keyboard node you can use the arrows to send new commands to the turtle. - -![alt text](images/turtlesim_tutorial4.gif) - - -The autogenerated README file of the package will show you how to create the new workspace and call the launch file. diff --git a/docu/Example_Turtlesim.rst b/docu/Example_Turtlesim.rst new file mode 100644 index 0000000..c763117 --- /dev/null +++ b/docu/Example_Turtlesim.rst @@ -0,0 +1,149 @@ +Hands-on example for the Turtlesim node ![](images/Ros2_logo.png) +================================================================ + +To learn ROS, one of the first tutorials everyone does is Turtlesim. It is a small graphical interface where a turtle can be moved using the speed commands of any robotic base in ROS. `Official TurtleSim tutorial `_ + +We will use it as an example to show the models. Let's imagine that we want to create a system in which we have two nodes, one of them is the Turtlesim and the other is a node to teleoperate it. +The first step is to create the models for both components. Both nodes are implemented in the `turtlesim `_ package in the `ros_tutorials `_ repository. + +We can create the component models manually or use our static code `analysis tools `_ to get them automatically. Using the second method, we obtained the following models: + +.. code-block:: yaml + + turtlesim: + fromGitRepo: "https://github.com/ros/ros_tutorials/" + artifacts: + turtle_teleop_key: + node: turtle_teleop_key + publishers: + cmd_vel: + type: "geometry_msgs/msg/Twist" + parameters: + scale_angular: + type: Double + default: 2.0 + scale_linear: + type: Double + default: 2.0 + turtlesim_node: + node: turtlesim_node + publishers: + color_sensor: + type: "turtlesim/msg/Color" + pose: + type: "turtlesim/msg/Pose" + subscribers: + cmd_vel: + type: "geometry_msgs/msg/Twist" + serviceservers: + teleport_absolute: + type: "turtlesim/srv/TeleportAbsolute" + spawn: + type: 'turtlesim/srv/Spawn' + set_pen: + type: 'turtlesim/srv/SetPen' + reset: + type: "std_srvs/srv/Empty" + kill: + type: 'turtlesim/srv/Kill' + teleport_relative: + type: 'turtlesim/srv/TeleportRelative' + clear: + type: 'std_srvs/srv/Empty' + +To import this as a project in the RosTooling, create a new modeling project by pressing the icon "Add new ROS Project". + +.. image:: images/create_new_RosProject.png + :alt: Add new ROS Project + +If the button doesn't work, you can also create it manually using the Eclipse menu **File -> New -> Other...** and searching for "Ros Model Project". + +.. image:: images/first_project_tutorial.gif + :alt: First project tutorial + +By default, a new project with a reference to the content of "de.fraunhofer.ipa.ros.communication.objects" will be created. This new project contains a folder called "rosnodes" to hold the node descriptions and a file with the `.ros2` extension, which will have an error because it is empty. This file can be removed for this example. + +Once the project is created, you can create a new file by selecting **File -> New -> Other -> File**. We recommend giving the file the same name as the package, with the extension `.ros2`. This means the new file should be called **turtlesim.ros2**. By creating a file of type `.ros2`, Eclipse will convert the project to an Xtext project. Then copy the model content from above into the new file. + +Now that we have the components, we can compose them. To do this, we need to create a new `.rossystem` file. Again, go to **File -> New -> Other -> File**. The new file must have the `.rossystem` extension. + +In the `RosSystem description `_, we explain the format of a system, and the editor will assist you in writing the model correctly. + +First, give a name followed by a colon `:`, then add indentation. You can press **Ctrl + Space** for help. +Firstly, we will add the two nodes that compose our system. + +.. image:: images/turtlesim_tutorial1.gif + :alt: Add nodes + +So far, our file looks like this: + +.. code-block:: yaml + + turtlesim_system: + nodes: + turtlesim: + from: "turtlesim.turtlesim_node" + key_teleop: + from: "turtlesim.turtle_teleop_key" + +The "from" attributes reference the previously defined nodes in the **turtlesim.ros2** file. If you change the node names, the references must also be updated. + +Next, we want to expose the ports to be connected. This means exposing the subscriber of the velocity command of the turtle and the publisher from the keyboard teleop: + +.. image:: images/turtlesim_tutorial2.gif + :alt: Expose ports + +The model is updated to: + +.. code-block:: yaml + + turtlesim_system: + nodes: + turtlesim: + from: "turtlesim.turtlesim_node" + interfaces: + - cmd_subscriber: sub-> "turtlesim_node::cmd_vel" + key_teleop: + from: "turtlesim.turtle_teleop_key" + interfaces: + - cmd_publisher: pub-> "turtle_teleop_key::cmd_vel" + +Again, the interfaces are references to the ones already defined in the **turtlesim.ros2** file. In ROS terms, we can only instantiate topics that are described in the original ROS code (C++ or Python). + +The last step is to create a connection between the two components. + +.. image:: images/turtlesim_tutorial3.gif + :alt: Create connections + +The model is updated to: + +.. code-block:: yaml + + turtlesim_system: + nodes: + turtlesim: + from: "turtlesim.turtlesim_node" + interfaces: + - cmd_subscriber: sub-> "turtlesim_node::cmd_vel" + key_teleop: + from: "turtlesim.turtle_teleop_key" + interfaces: + - cmd_publisher: pub-> "turtle_teleop_key::cmd_vel" + connections: + - [ cmd_publisher, cmd_subscriber ] + +After saving (Ctrl+S), a new folder "src-gen" will be automatically created. This folder contains a ROS 2 package ready to be executed with a launch file to start the designed system. + +For a quick check, source a valid ROS installation and run the launch command to start the Turtlesim example: + +.. code-block:: bash + + source /opt/ros/ROSDISTRO/setup.bash + ros2 launch PATH_TO_LAUNCH_PY_FILE + +Using the terminal of the keyboard node, you can use the arrow keys to send new commands to the turtle. + +.. image:: images/turtlesim_tutorial4.gif + :alt: Send commands to the turtle + +The autogenerated README file of the package will show you how to create the new workspace and run the launch file. diff --git a/docu/Installation.md b/docu/Installation.md deleted file mode 100644 index 482b3f5..0000000 --- a/docu/Installation.md +++ /dev/null @@ -1,65 +0,0 @@ -# Installation and setup - -### Option 1: Using the Release version (Recommended) - -First, the Java environment has to be set. For Linux it can be installed with the following command: - -``` -sudo apt-get install openjdk-19-jre -``` - -Then Eclipse can be installed. Please download the installer from the official Eclipse [website](https://www.eclipse.org/downloads/packages/installer). After unpacking the downloaded file, the installer can be run by calling the command *./eclipse-inst* from the console. - -Once you start the installer, select the package "Eclipse Modeling Tools". You can find it just by scrolling or using the searching tool: - -![alt text](images/install_eclipse_modeling.png) - -Press next, and then pick the Java version 19 and the folder where you would like to install Eclipse. - -![alt text](images/install_eclipse_jdk_version.png) - -Continue the installation, accepting the license, as usual. - -Once the installation is completed, go to *Help* > *Install New Software...*. To install the latest version of the ROS tooling, add the update site URL [https://raw.githubusercontent.com/ipa320/RosTooling-update-site/main](https://raw.githubusercontent.com/ipa320/RosTooling-update-site/main) in the *Work with* section. - -![alt text](images/install_updatesite.png) - -If no package is listed, please uncheck the option *Group items by category*. The category *ROS Model* appears in the *Name* area. Check the box in front of *ROS model* and click *Next* to review the list of items to be installed. Click *Next* again to read and accept the terms of the license agreements and afterwards click *Finish*. Eclipse will then start to install the ROS tooling and its dependencies. If you get a security warning about the authenticity, click OK. Finally, when asked, restart Eclipse to complete the installation process. - -To start using the ROS tooling continue with [step 1](Environment_setup.md/#1-switch-to-the-ros-developer-perspective) - - -## Alternative installations - -### Option 2: Using the Eclipse Installer - Source installation (ROS tooling developers) - -First, the Java environment has to be set: -``` -sudo apt-get install openjdk-19-jre -``` -Download the official [Eclipse Installer](https://www.eclipse.org/downloads/packages/installer) for your preferred operating system. Execute the installer and choose the advanced mode (menu on the right-up corner). Select the Product *Eclipse Modeling tools* package. And then pick the Java version 19. - -![alt text](images/eclipse_installer1.png) - -Press *Next* and add a new _User project_ by pressing the green button *+*: -``` -Catalog: Github Projects -Resource URIs: https://raw.githubusercontent.com/ipa320/RosTooling/main/EclipseInstaller/ROSModel.setup -``` -Sometimes Eclipse is not able to find the file, for those cases, we recommend downloading the file to the local memory of the machine and importing it: - -``` -wget https://raw.githubusercontent.com/ipa320/RosTooling/main/EclipseInstaller/ROSModel.setup -``` - -![alt text](images/eclipse_installer2.png) - -Select the ROS Model project (under GitHub Projects -> ) and press next. - -By default, the ROS tooling installation will be saved under the folder *ros-model-master* in your home directory. To ensure that you have access to get the source code from GitHub, select the check box *Show all variable* and change the *Ros model GitHub repository* to the *HTTPs(read-write)* option, verify that the option *Github user ID* is set to "anonymous". - -![alt text](images/eclipse_installer3.png) - -Follow the installation instructions of the Oompth installer dialog, after the installation eclipse will be restarted to launch the ROS tooling configuration. Finally, when all the startup tasks are finished press "Workbench". - -To start using the ROS tooling continue with [step 0](Environment_setup.md/#0-start-the-ros-tooling-application) diff --git a/docu/Installation.rst b/docu/Installation.rst new file mode 100644 index 0000000..d13f944 --- /dev/null +++ b/docu/Installation.rst @@ -0,0 +1,80 @@ +Installation and setup +====================== + +Option 1: Using the Release version (Recommended) +------------------------------------------------- + +First, the Java environment has to be set. For Linux it can be installed with the following command: + +.. code-block:: bash + + sudo apt-get install openjdk-19-jre + +Then Eclipse can be installed. Please download the installer from the official Eclipse `website `_. +After unpacking the downloaded file, the installer can be run by calling the command ``./eclipse-inst`` from the console. + +Once you start the installer, select the package "Eclipse Modeling Tools". You can find it just by scrolling or using the search tool: + +.. image:: images/install_eclipse_modeling.png + +Press next, and then pick Java version 19 and the folder where you would like to install Eclipse. + +.. image:: images/install_eclipse_jdk_version.png + +Continue the installation, accepting the license, as usual. + +Once the installation is completed, go to *Help* > *Install New Software...*. To install the latest version of the ROS tooling, add the update site URL `https://raw.githubusercontent.com/ipa320/RosTooling-update-site/main `_ in the *Work with* section. + +.. image:: images/install_updatesite.png + +If no package is listed, please uncheck the option *Group items by category*. The category *ROS Model* appears in the *Name* area. +Check the box in front of *ROS model* and click *Next* to review the list of items to be installed. Click *Next* again to read and accept the terms of the license agreements, and afterward, click *Finish*. +Eclipse will then start to install the ROS tooling and its dependencies. If you get a security warning about authenticity, click OK. +Finally, when asked, restart Eclipse to complete the installation process. + +To start using the ROS tooling continue with `step 1 `_. + + +Alternative installations +========================= + +Option 2: Using the Eclipse Installer - Source installation (ROS tooling developers) +------------------------------------------------------------------------------------ + +First, the Java environment has to be set: + +.. code-block:: bash + + sudo apt-get install openjdk-19-jre + +Download the official `Eclipse Installer `_ for your preferred operating system. +Execute the installer and choose the advanced mode (menu on the right-upper corner). Select the Product *Eclipse Modeling tools* package, and then pick Java version 19. + +.. image:: images/eclipse_installer1.png + +Press *Next* and add a new *User project* by pressing the green button *+*: + +.. code-block:: none + + Catalog: Github Projects + Resource URIs: https://raw.githubusercontent.com/ipa320/RosTooling/main/EclipseInstaller/ROSModel.setup + +Sometimes Eclipse is not able to find the file. In such cases, we recommend downloading the file locally and importing it: + +.. code-block:: bash + + wget https://raw.githubusercontent.com/ipa320/RosTooling/main/EclipseInstaller/ROSModel.setup + +.. image:: images/eclipse_installer2.png + +Select the ROS Model project (under GitHub Projects -> ) and press *Next*. + +By default, the ROS tooling installation will be saved under the folder *ros-model-master* in your home directory. To ensure access to the source code from GitHub, +select the check box *Show all variables* and change the *Ros model GitHub repository* to the *HTTPs (read-write)* option. Verify that the option *Github user ID* is set to "anonymous". + +.. image:: images/eclipse_installer3.png + +Follow the installation instructions of the Oomph installer dialog. After the installation, Eclipse will be restarted to launch the ROS tooling configuration. +Finally, when all the startup tasks are finished, press "Workbench." + +To start using the ROS tooling continue with `step 0 `_. diff --git a/docu/IntrospectionNode.md b/docu/IntrospectionNode.md deleted file mode 100644 index c54368d..0000000 --- a/docu/IntrospectionNode.md +++ /dev/null @@ -1,31 +0,0 @@ -## Create a ROS model from a deployed robot using our introspection at runtime tool (for ROS 2 systems) - -Please be sure that the tool is installed and your workspace setup, see the [installation guide](../README.md) for further details. - -The tools documented here were conceived as a simple way to obtain models of systems already developed during their execution. This series of scripts uses the popular ROS rosgraph library to obtain a list of the interfaces present in the system at runtime. - -You can install the tools directly on your workspace using the following command: - -``` -cd YourRos2WS/src -git clone git@github.com:ipa-nhg/ros2model.git -cd YourRos2WS -colcon build -``` - -To ask the monitoring module to capture all the nodes running on the system, please use the following command: - -``` -ros2 model running_node -ga -d ~/PathToModelsFolderOutput -``` - -The folder **PathToModelsFolderOutput** will contain all the model files. - -For a single node, the following command can be called: -``` -ros2 model running_node [-o Outputfile] -``` - -For further information please check the [ros2model](https://github.com/ipa-cmh/ros2model) repository. - -The models you will see during the rest of the tutorials were auto-generated mostly using this method. \ No newline at end of file diff --git a/docu/IntrospectionNode.rst b/docu/IntrospectionNode.rst new file mode 100644 index 0000000..685c423 --- /dev/null +++ b/docu/IntrospectionNode.rst @@ -0,0 +1,33 @@ +Create a ROS model from a deployed robot using our introspection at runtime tool (for ROS 2 systems) +=================================================================================================== + +Please ensure that the tool is installed and your workspace is set up. See the `installation guide <../README.rst>`_ for further details. + +The tools documented here were conceived as a simple way to obtain models of systems that are already developed during their execution. This series of scripts uses the popular ROS `rosgraph` library to obtain a list of the interfaces present in the system at runtime. + +You can install the tools directly in your workspace using the following command: + +.. code-block:: bash + + cd YourRos2WS/src + git clone git@github.com:ipa-nhg/ros2model.git + cd YourRos2WS + colcon build + +To ask the monitoring module to capture all the nodes running on the system, use the following command: + +.. code-block:: bash + + ros2 model running_node -ga -d ~/PathToModelsFolderOutput + +The folder **PathToModelsFolderOutput** will contain all the model files. + +For a single node, use the following command: + +.. code-block:: bash + + ros2 model running_node [-o Outputfile] + +For further information, please check the `ros2model `_ repository. + +The models you will see during the rest of the tutorials were mostly auto-generated using this method. diff --git a/docu/LearnRosModels.md b/docu/LearnRosModels.md deleted file mode 100644 index 488d013..0000000 --- a/docu/LearnRosModels.md +++ /dev/null @@ -1,74 +0,0 @@ -# Review models and the use of the textual editors for Ros nodes - -To complete this tutorial the project "de.fraunhofer.ipa.ros.communication.objects" must be imported. See instructions under [setup](Environment_setup.md). If the automatic clone doesn't work for you, please clone the repository [RosCommonObjects](https://github.com/ipa320/RosCommonObjects) manually and import it to your Eclipse workspace. - -The first step is to create a new Project to contain the examples. This can be done by pressing the icon "Add new ROS Project". - -![alt text](images/create_new_RosProject.png) - -If the button doesn't work you can also create it manually using the Eclipse menu File -> New -> Other.. and searching for "Ros Model Project". - -![alt text](images/first_project_tutorial.gif) - -By default, a new project with a reference to the content of the "de.fraunhofer.ipa.ros.communication.objects" will be created. This new project contains a folder called "rosnodes" to hold the nodes description and a file with the extension .ros2 which will have an error because it is empty. - -You can open the file and copy the following content: - -``` -my_Component: - artifacts: - Component: - node: Test -``` - -This model will report an error and two issues. By moving the mouse to the error icon, the ROS model editor will point out the issue, in this case, "The name of a package has to follow the ROS naming conventions: Capital letters are not allowed". The ROS models compiler includes the ROS naming conventions based on the [REP 144](https://ros.org/reps/rep-0144.html), where it is established that a name must "only consist of lowercase alphanumerics and _ separators and start with an alphabetic character." - -![alt text](images/01_learn_rosmodels.gif ) - -Similar rules, but not mandatory, apply to the names of the artifacts and the nodes. Both issues are shown as warnings by the RosTooling. - -The next case to check is the definition of a non-existent message type as a communication object for an interface. For example: - -``` -my_component: - artifacts: - component: - node: test - publishers: - string_pub: - type: "my_msgs_package/msg/String" -``` - -By pasting the previous text to a .ros2 file the editor will point the following error: "Couldn't resolve reference to TopicSpec 'my_msgs_package/msg/String'." - -This means the type "my_msgs_package/msg/String" is not defined. You can easily use an existing type by removing the incorrect value a pressing Ctrl + Space bar. Then you can select for example "std_msgs/msg/String" and the error will disappear. - -![alt text](images/02_learn_rosmodels.gif) - -To review the definition of the referenced object, you should press F2 while you have the mouse pointer pointing to the object. - -![alt text](images/03_learn_rosmodels.gif) - -Last, let's check the output when a grammar error is introduced. For example by creating a parameter without a defined type. If you copy the following text to the .ros2 file: - -``` -my_component: - artifacts: - component: - node: test - publishers: - string_pub: - type: "std_msgs/msg/String" - parameters: - my_bool: -``` - -In this case, the helper will say "The required feature 'type' of 'ros.impl.ParameterImpl@37c1c0b8{platform:/resource/my_first_project/rosnodes/my_first_project.ros2#//@artifact.0/@node/@parameter.0}' must be set". - -To solve it, add a new element under my_bool to describe the type. The autocomplete function (Ctrl + Space bar) can help you to use the correct grammar. - -![alt text](images/04_learn_rosmodels.gif) - -Now that you understand how the textual editor and the model's validator work, you can check one of the extended examples. The project "de.fraunhofer.ipa.ros.communication.objects" under "BasicSpecs/Components" contains some examples. We strongly recommend taking a look at "ros_component_template.ros2". - -Also, [clone and check the Catalog](Environment_setup.md#3-import-the-catalog) with many real examples of ROS 2 components. \ No newline at end of file diff --git a/docu/LearnRosModels.rst b/docu/LearnRosModels.rst new file mode 100644 index 0000000..84b8844 --- /dev/null +++ b/docu/LearnRosModels.rst @@ -0,0 +1,81 @@ +Review models and the use of the textual editors for Ros nodes +============================================================== + +To complete this tutorial, the project "de.fraunhofer.ipa.ros.communication.objects" must be imported. See instructions under `setup `_. If the automatic clone doesn't work for you, please clone the repository `RosCommonObjects `_ manually and import it to your Eclipse workspace. + +The first step is to create a new Project to contain the examples. This can be done by pressing the icon "Add new ROS Project". + +.. image:: images/create_new_RosProject.png + :alt: Add new ROS Project + +If the button doesn't work, you can also create it manually using the Eclipse menu **File -> New -> Other...** and searching for "Ros Model Project". + +.. image:: images/first_project_tutorial.gif + :alt: First Project Tutorial + +By default, a new project with a reference to the content of the "de.fraunhofer.ipa.ros.communication.objects" will be created. This new project contains a folder called "rosnodes" to hold the nodes description and a file with the extension `.ros2`, which will show an error because it is empty. + +You can open the file and copy the following content: + +.. code-block:: yaml + + my_Component: + artifacts: + Component: + node: Test + +This model will report an error and two issues. By moving the mouse to the error icon, the ROS model editor will point out the issue, in this case, "The name of a package has to follow the ROS naming conventions: Capital letters are not allowed." The ROS models compiler includes the ROS naming conventions based on the `REP 144 `_, where it is established that a name must "only consist of lowercase alphanumerics and _ separators and start with an alphabetic character." + +.. image:: images/01_learn_rosmodels.gif + :alt: Learn ROS Models + +Similar rules, though not mandatory, apply to the names of the artifacts and the nodes. Both issues are shown as warnings by RosTooling. + +The next case to check is the definition of a non-existent message type as a communication object for an interface. For example: + +.. code-block:: yaml + + my_component: + artifacts: + component: + node: test + publishers: + string_pub: + type: "my_msgs_package/msg/String" + +By pasting the previous text into a `.ros2` file, the editor will point out the following error: "Couldn't resolve reference to TopicSpec 'my_msgs_package/msg/String'." + +This means the type "my_msgs_package/msg/String" is not defined. You can easily use an existing type by removing the incorrect value and pressing **Ctrl + Space**. Then you can select, for example, "std_msgs/msg/String" and the error will disappear. + +.. image:: images/02_learn_rosmodels.gif + :alt: Learn ROS Models Autocomplete + +To review the definition of the referenced object, press **F2** while pointing the mouse to the object. + +.. image:: images/03_learn_rosmodels.gif + :alt: F2 to view object definition + +Lastly, let's check the output when a grammar error is introduced, for example by creating a parameter without a defined type. If you copy the following text into the `.ros2` file: + +.. code-block:: yaml + + my_component: + artifacts: + component: + node: test + publishers: + string_pub: + type: "std_msgs/msg/String" + parameters: + my_bool: + +In this case, the helper will say "The required feature 'type' of 'ros.impl.ParameterImpl@37c1c0b8{platform:/resource/my_first_project/rosnodes/my_first_project.ros2#//@artifact.0/@node/@parameter.0}' must be set." + +To solve it, add a new element under `my_bool` to describe the type. The autocomplete function (**Ctrl + Space**) can help you use the correct grammar. + +.. image:: images/04_learn_rosmodels.gif + :alt: Learn ROS Models Grammar Check + +Now that you understand how the textual editor and the model validator work, you can check one of the extended examples. The project "de.fraunhofer.ipa.ros.communication.objects" under "BasicSpecs/Components" contains some examples. We strongly recommend taking a look at "ros_component_template.ros2". + +Also, `clone and check the Catalog `_ with many real examples of ROS 2 components. diff --git a/docu/LearnRosSystemModels.md b/docu/LearnRosSystemModels.md deleted file mode 100644 index 60b1e8d..0000000 --- a/docu/LearnRosSystemModels.md +++ /dev/null @@ -1,190 +0,0 @@ -# Review models and the use of the textual editors for Ros Systems - -To complete this tutorial the project "de.fraunhofer.ipa.ros.communication.objects" must be imported. See instructions under [setup](Environment_setup.md). If the automatic clone doesn't work for you, please clone the repository [RosCommonObjects](https://github.com/ipa320/RosCommonObjects) manually and import it to your Eclipse workspace. - -The first step is to create a new Project to contain the examples, in case you completed the previous [tutorials](LearnRosModels.md) you can just use the same package. Otherwise, as usual you can create a new project by pressing the icon "Add new ROS Project". - -![alt text](images/create_new_RosProject.png) - -If the button doesn't work you can also create it manually using the Eclipse menu File -> New -> Other.. and searching for "Ros Model Project". - -![alt text](images/first_project_tutorial.gif) - -By default, a new project with a reference to the content of the "de.fraunhofer.ipa.ros.communication.objects" will be created. This new project contains a folder called "rosnodes" to hold the nodes description and a file with the extension .ros2 which will have an error because it is empty. The folder "rosnodes" can be removed for this example. - -As a system creation requires component models, you can use existing .ros2 files for the composition. Under "de.fraunhofer.ipa.ros.communication.objects/BasicSpecs/Components" you can find the **ros_component_template.ros2** and the **ros_component2_template.ros2** files. Both represent fictitious nodes with all the possible interfaces and parameters. Please open both files and take a look at them. - -Now we have to create a file to contain our system model. For that, you can go to File -> New -> Other -> General -> File. The new file must have the extension .rossystem. - -As reference, in [RosSystem description](RosSystemModelDescription.md) we explain the format of a system and the editor will support you in writing the model properly. - -The first that must be given is a name and then a ":" is required. In the next line, you must add indentation and you can press the keys "Ctrl" + Space bar for help. -Then we will define the nodes that compose the system. Here under "from" we will link the previous referenced nodes, the grammar for the references is **PackageName.NodeName**. - -![alt text](images/01_learn_rossystemmodels.gif) - - -So far our file looks like this: - -``` -my_awesome_system: - nodes: - node1: - from: "my_awesome_pkg.awesome_node" - node2: - from: "my_awesome2_pkg.awesome2_node" -``` - -This model is basically creating a system composed of two nodes. While saving the model automatically a folder "src-gen" will be created. The folder contains a new ROS package whose structure corresponds to a python launch package. - -![alt text](images/launchstructure_01.png) - -The CMakeLists.txt and package.xml list the required dependencies and tags to compile the package. Then under launch the python file starts both nodes. See the [Code generator review tutorial](docu/CodeGeneration.md) for further details. - -Now, we want to expose the ports to be connected. For that, we have to define the interfaces under the nodes. And again we have to reference the created interfaces, with the grammar **NodeName::InterfaceName**. Although in ROS all the interfaces will be automatically exposed, the RosSystem model requires this step to clearly design the system and the ports that are intentionally opened by the architect of the system. - -![alt text](images/02_learn_rossystemmodels.gif) - -``` -my_awesome_system: - nodes: - node1: - from: "my_awesome_pkg.awesome_node" - interfaces: - - my_pub: pub-> "awesome::awesome_pub" - node2: - from: "my_awesome2_pkg.awesome2_node" - interfaces: - - my_sub: sub-> "awesome2::awesome2_sub" -``` - -The next step is to create a connection between the two components. For that, we will use the connections attribute, under the system description. The connections must be made between interface instances described within the models, otherwise, the model validator will give an error. - -![alt text](images/03_learn_rossystemmodels.gif) - - -Currently, our model looks like this: - -``` -my_awesome_system: - nodes: - node1: - from: "my_awesome_pkg.awesome_node" - interfaces: - - my_pub: pub-> "awesome::awesome_pub" - node2: - from: "my_awesome2_pkg.awesome2_node" - interfaces: - - my_sub: sub-> "awesome2::awesome2_sub" - connections: - - [ my_pub, my_sub ] - ``` - -We invite you to try different combinations and debug the validator for connections. For example: - -``` -my_awesome_system: - nodes: - node1: - from: "my_awesome_pkg.awesome_node" - interfaces: - - my_pub: pub-> "awesome::awesome_pub" - - string_pub: pub-> "awesome::hello_world_pub" - node2: - from: "my_awesome2_pkg.awesome2_node" - interfaces: - - my_sub: sub-> "awesome2::awesome2_sub" - - connections: - - [string_pub, my_sub] -``` - -This file will give a compilation error, and therefore the launch file will not be generated, because you are trying to connect ports with a different message type. The same will happen in case we try to connect different types of ports, like a topic with a service. - -Also, another attribute that can be set and the generator will take into account is the namespace: - -![alt text](images/04_learn_rossystemmodels.gif) - -Lastly, we can check the set of parameter values. A valid example of this would be: - -``` -my_awesome_system: - nodes: - node1: - from: "my_awesome_pkg.awesome_node" - namespace: "my_ns" - interfaces: - - my_pub: pub-> "awesome::awesome_pub" - node2: - from: "my_awesome2_pkg.awesome2_node" - interfaces: - - my_sub: sub-> "awesome2::awesome2_sub" - parameters: - - string_example: "awesome2::awesome2_string_param" - value: "hello" - connections: - - [ my_pub, my_sub ] -``` - -![alt text](images/05_learn_rossystemmodels.gif) - -Where we give a string value to the parameter "awesome2_string_param". In case we try to give a wrong value, for example: - -``` -my_awesome_system: - nodes: - node1: - from: "my_awesome_pkg.awesome_node" - namespace: "my_ns" - interfaces: - - my_pub: pub-> "awesome::awesome_pub" - node2: - from: "my_awesome2_pkg.awesome2_node" - interfaces: - - my_sub: sub-> "awesome2::awesome2_sub" - parameters: - - string_example: "awesome2::awesome2_string_param" - value: 5 - connections: - - [ my_pub, my_sub ] -``` - -The compiler will give an error of mismatched type. -![](images/Attention.png) The validator has some parts not fully implemented, check the [Known issues](RosTooling_issues.md) site in case you have problems by following this tutorial. - -Another feature included as part of the code generator is the generator of parameter files. This will be automatically done and the launch file will by default load it by the set of more than 5 parameters, for example for this case: - -``` -my_awesome_system: - nodes: - node1: - from: "my_awesome_pkg.awesome_node" - namespace: "my_ns" - interfaces: - - my_pub: pub-> "awesome::awesome_pub" - node2: - from: "my_awesome2_pkg.awesome2_node" - interfaces: - - my_sub: sub-> "awesome2::awesome2_sub" - parameters: - - array_example: "awesome::awesome_array_param" - value: ["hello", "hallo"] - - bool_example: "awesome::awesome_bool_param" - value: true - - double_example: "awesome::awesome_double_param" - value: 1.2 - - integer_example : "awesome::awesome_integer_param" - value: 2 - - string_param : "awesome::awesome_string_param" - value: "hallo" - - struct_param: "awesome::awesome_struct_param" - value: [ - first: 2 - second: true] - connections: - - [ my_pub, my_sub ] -``` - -In this case, a new file will be created under "src-gen/PackageName/config/" and it will contain the configuration of the node2. The launch file will be adapted to launch the configuration from a file. - -With this very basic example, we hope you have understood how the models can be used and what kind of attributes they allow to represent. diff --git a/docu/LearnRosSystemModels.rst b/docu/LearnRosSystemModels.rst new file mode 100644 index 0000000..05d554f --- /dev/null +++ b/docu/LearnRosSystemModels.rst @@ -0,0 +1,199 @@ +Review models and the use of the textual editors for Ros Systems +================================================================ + +To complete this tutorial, the project "de.fraunhofer.ipa.ros.communication.objects" must be imported. See instructions under `setup `_. If the automatic clone doesn't work for you, please clone the repository `RosCommonObjects `_ manually and import it to your Eclipse workspace. + +The first step is to create a new project to contain the examples. If you completed the previous `tutorials `_, you can use the same package. Otherwise, you can create a new project by pressing the "Add new ROS Project" icon. + +.. image:: images/create_new_RosProject.png + :alt: Add new ROS Project + +If the button doesn't work, you can also create it manually using the Eclipse menu **File -> New -> Other...** and searching for "Ros Model Project." + +.. image:: images/first_project_tutorial.gif + :alt: First Project Tutorial + +By default, a new project with a reference to the content of the "de.fraunhofer.ipa.ros.communication.objects" will be created. This new project contains a folder called "rosnodes" to hold the nodes description and a file with the extension `.ros2`, which will have an error because it is empty. The "rosnodes" folder can be removed for this example. + +As system creation requires component models, you can use existing `.ros2` files for the composition. Under "de.fraunhofer.ipa.ros.communication.objects/BasicSpecs/Components", you can find the **ros_component_template.ros2** and **ros_component2_template.ros2** files. Both represent fictitious nodes with all possible interfaces and parameters. Please open both files and take a look at them. + +Now we have to create a file to contain our system model. For that, go to **File -> New -> Other -> General -> File**. The new file must have the `.rossystem` extension. + +As a reference, in the `RosSystem description `_, we explain the format of a system, and the editor will support you in writing the model properly. + +First, a name must be given followed by a colon `:`. On the next line, add indentation and press the keys **Ctrl + Space** for help. Then we define the nodes that compose the system. Under "from", we link the previously referenced nodes, and the grammar for the references is **PackageName.NodeName**. + +.. image:: images/01_learn_rossystemmodels.gif + :alt: Learn ROS System Models + +So far, our file looks like this: + +.. code-block:: yaml + + my_awesome_system: + nodes: + node1: + from: "my_awesome_pkg.awesome_node" + node2: + from: "my_awesome2_pkg.awesome2_node" + +This model is basically creating a system composed of two nodes. Upon saving the model, a folder "src-gen" will be created automatically. This folder contains a new ROS package whose structure corresponds to a Python launch package. + +.. image:: images/launchstructure_01.png + :alt: Launch Structure + +The `CMakeLists.txt` and `package.xml` list the required dependencies and tags to compile the package. Under the "launch" folder, the Python file starts both nodes. See the `Code generator review tutorial `_ for further details. + +Next, we want to expose the ports to be connected. For that, we define the interfaces under the nodes. Again, we must reference the created interfaces using the grammar **NodeName::InterfaceName**. Although in ROS all interfaces are automatically exposed, the RosSystem model requires this step to clearly design the system and the ports that are intentionally opened by the system architect. + +.. image:: images/02_learn_rossystemmodels.gif + :alt: Expose Ports + +.. code-block:: yaml + + my_awesome_system: + nodes: + node1: + from: "my_awesome_pkg.awesome_node" + interfaces: + - my_pub: pub-> "awesome::awesome_pub" + node2: + from: "my_awesome2_pkg.awesome2_node" + interfaces: + - my_sub: sub-> "awesome2::awesome2_sub" + +The next step is to create a connection between the two components. For that, we use the `connections` attribute under the system description. The connections must be made between interface instances described within the models; otherwise, the model validator will give an error. + +.. image:: images/03_learn_rossystemmodels.gif + :alt: Connections Between Components + +Currently, our model looks like this: + +.. code-block:: yaml + + my_awesome_system: + nodes: + node1: + from: "my_awesome_pkg.awesome_node" + interfaces: + - my_pub: pub-> "awesome::awesome_pub" + node2: + from: "my_awesome2_pkg.awesome2_node" + interfaces: + - my_sub: sub-> "awesome2::awesome2_sub" + connections: + - [ my_pub, my_sub ] + +We invite you to try different combinations and debug the validator for connections. For example: + +.. code-block:: yaml + + my_awesome_system: + nodes: + node1: + from: "my_awesome_pkg.awesome_node" + interfaces: + - my_pub: pub-> "awesome::awesome_pub" + - string_pub: pub-> "awesome::hello_world_pub" + node2: + from: "my_awesome2_pkg.awesome2_node" + interfaces: + - my_sub: sub-> "awesome2::awesome2_sub" + connections: + - [string_pub, my_sub] + +This file will give a compilation error, and therefore the launch file will not be generated, because you are trying to connect ports with different message types. The same will happen if we try to connect different types of ports, like a topic with a service. + +Another attribute that can be set, and the generator will take into account, is the `namespace`: + +.. image:: images/04_learn_rossystemmodels.gif + :alt: Namespace Attribute + +Lastly, we can check the set of parameter values. A valid example of this would be: + +.. code-block:: yaml + + my_awesome_system: + nodes: + node1: + from: "my_awesome_pkg.awesome_node" + namespace: "my_ns" + interfaces: + - my_pub: pub-> "awesome::awesome_pub" + node2: + from: "my_awesome2_pkg.awesome2_node" + interfaces: + - my_sub: sub-> "awesome2::awesome2_sub" + parameters: + - string_example: "awesome2::awesome2_string_param" + value: "hello" + connections: + - [ my_pub, my_sub ] + +.. image:: images/05_learn_rossystemmodels.gif + :alt: Parameters Example + +Here, we assign a string value to the parameter `awesome2_string_param`. If we attempt to give a wrong value, for example: + +.. code-block:: yaml + + my_awesome_system: + nodes: + node1: + from: "my_awesome_pkg.awesome_node" + namespace: "my_ns" + interfaces: + - my_pub: pub-> "awesome::awesome_pub" + node2: + from: "my_awesome2_pkg.awesome2_node" + interfaces: + - my_sub: sub-> "awesome2::awesome2_sub" + parameters: + - string_example: "awesome2::awesome2_string_param" + value: 5 + connections: + - [ my_pub, my_sub ] + +The compiler will give a type mismatch error. + +.. image:: images/Attention.png + :alt: Attention + +The validator has some parts that are not fully implemented. Check the `Known issues `_ page if you encounter problems while following this tutorial. + +Another feature included as part of the code generator is the generation of parameter files. This will be done automatically, and the launch file will, by default, load it when more than 5 parameters are set. For example, in this case: + +.. code-block:: yaml + + my_awesome_system: + nodes: + node1: + from: "my_awesome_pkg.awesome_node" + namespace: "my_ns" + interfaces: + - my_pub: pub-> "awesome::awesome_pub" + node2: + from: "my_awesome2_pkg.awesome2_node" + interfaces: + - my_sub: sub-> "awesome2::awesome2_sub" + parameters: + - array_example: "awesome::awesome_array_param" + value: ["hello", "hallo"] + - bool_example: "awesome::awesome_bool_param" + value: true + - double_example: "awesome::awesome_double_param" + value: 1.2 + - integer_example: "awesome::awesome_integer_param" + value: 2 + - string_param: "awesome::awesome_string_param" + value: "hallo" + - struct_param: "awesome::awesome_struct_param" + value: [ + first: 2 + second: true] + connections: + - [ my_pub, my_sub ] + +In this case, a new file will be created under `src-gen/PackageName/config/`, containing the configuration of `node2`. The launch file will be adapted to launch the configuration from a file. + +With this very basic example, we hope you have understood how the models can be used and what kind of attributes they allow you to represent. diff --git a/docu/LearnRosSystemModels2.md b/docu/LearnRosSystemModels2.md deleted file mode 100644 index 0e71da8..0000000 --- a/docu/LearnRosSystemModels2.md +++ /dev/null @@ -1,91 +0,0 @@ -# Other ways to define a system - -The [previous tutorial](LearnRosSystemModels.md) shows the description of typical systems created by composing nodes. But with the RosTooling it is also allowed the composition of subsystems. -Again, you have the site [RosSystem description](RosSystemModelDescription.md) as reference. - - -## Subsystems from model - -Under "de.fraunhofer.ipa.ros.communication.objects/BasicSpecs/Systems" some other examples of subsystems can be found. To compose them, imagine we have the file created within the [previous tutorial](LearnRosSystemModels.md), we can easily add the subsystems definition. - -``` -my_awesome_system: - subSystems: - my_subsystem - nodes: - node1: - from: "my_awesome_pkg.awesome_node" - namespace: "my_ns" - interfaces: - - my_pub: pub-> "awesome::awesome_pub" - node2: - from: "my_awesome2_pkg.awesome2_node" - interfaces: - - my_sub: sub-> "awesome2::awesome2_sub" - parameters: - - array_example: "awesome::awesome_array_param" - value: ["hello", "hallo"] - - bool_example: "awesome::awesome_bool_param" - value: true - - double_example: "awesome::awesome_double_param" - value: 1.2 - - integer_example : "awesome::awesome_integer_param" - value: 2 - - string_param : "awesome::awesome_string_param" - value: "hallo" - - struct_param: "awesome::awesome_struct_param" - value: [ - first: 2 - second: true] - connections: - - [ my_pub, my_sub ] -``` - -![alt text](images/06_learn_rossystemmodels.gif) - -The code generator will update not only the launch file but also the package.xml to add the dependency to the package that contains the subsystem definition. - -## Subsystems from launch files (existing ROS systems) - - -As the RosTooling pretends to support the ROS developers in the way they work, therefore it allows also the use of systems for whose a launch file is already available and does not re-generate or duplicate code that already exists. This is the reason for having the attribute "fromFile". - -![alt text](images/07_learn_rossystemmodels.gif) - -The compiler expects the package name followed by the relative path to the file. The file must be given with the extension. An example looks like: - -``` -my_awesome_system: - fromFile: "pkg_name/launch/my_file.launch.py" - nodes: - node1: - from: "my_awesome_pkg.awesome_node" - namespace: "my_ns" - interfaces: - - my_pub: pub-> "awesome::awesome_pub" - node2: - from: "my_awesome2_pkg.awesome2_node" - interfaces: - - my_sub: sub-> "awesome2::awesome2_sub" - parameters: - - array_example: "awesome::awesome_array_param" - value: ["hello", "hallo"] - - bool_example: "awesome::awesome_bool_param" - value: true - - double_example: "awesome::awesome_double_param" - value: 1.2 - - integer_example : "awesome::awesome_integer_param" - value: 2 - - string_param : "awesome::awesome_string_param" - value: "hallo" - - struct_param: "awesome::awesome_struct_param" - value: [ - first: 2 - second: true] - connections: - - [ my_pub, my_sub ] -``` - -The code generator for these cases, will not create the launch but update the README file to give instructions about how to install and start the defined file. - -It is strongly recommended to give also information about the components and interfaces within the system. This will help with the documentation and be taken into consideration for the visualization of the system. \ No newline at end of file diff --git a/docu/LearnRosSystemModels2.rst b/docu/LearnRosSystemModels2.rst new file mode 100644 index 0000000..caea50f --- /dev/null +++ b/docu/LearnRosSystemModels2.rst @@ -0,0 +1,94 @@ +Other ways to define a system +============================= + +The `previous tutorial `_ shows the description of typical systems created by composing nodes. With RosTooling, it is also possible to compose subsystems. +Again, you can refer to the `RosSystem description `_ as a reference. + +Subsystems from model +---------------------- + +Under "de.fraunhofer.ipa.ros.communication.objects/BasicSpecs/Systems", you can find some other examples of subsystems. To compose them, let's imagine we have the file created within the `previous tutorial `_, we can easily add the subsystems definition: + +.. code-block:: yaml + + my_awesome_system: + subSystems: + my_subsystem + nodes: + node1: + from: "my_awesome_pkg.awesome_node" + namespace: "my_ns" + interfaces: + - my_pub: pub-> "awesome::awesome_pub" + node2: + from: "my_awesome2_pkg.awesome2_node" + interfaces: + - my_sub: sub-> "awesome2::awesome2_sub" + parameters: + - array_example: "awesome::awesome_array_param" + value: ["hello", "hallo"] + - bool_example: "awesome::awesome_bool_param" + value: true + - double_example: "awesome::awesome_double_param" + value: 1.2 + - integer_example : "awesome::awesome_integer_param" + value: 2 + - string_param : "awesome::awesome_string_param" + value: "hallo" + - struct_param: "awesome::awesome_struct_param" + value: [ + first: 2 + second: true] + connections: + - [ my_pub, my_sub ] + +.. image:: images/06_learn_rossystemmodels.gif + :alt: Subsystems composition + +The code generator will update not only the launch file but also the `package.xml` to add the dependency to the package that contains the subsystem definition. + +Subsystems from launch files (existing ROS systems) +--------------------------------------------------- + +As RosTooling aims to support ROS developers in their typical workflow, it also allows the use of systems where a launch file already exists. It does not re-generate or duplicate code that already exists. This is the purpose of the "fromFile" attribute. + +.. image:: images/07_learn_rossystemmodels.gif + :alt: Subsystems from launch files + +The compiler expects the package name followed by the relative path to the file, including the file extension. An example looks like this: + +.. code-block:: yaml + + my_awesome_system: + fromFile: "pkg_name/launch/my_file.launch.py" + nodes: + node1: + from: "my_awesome_pkg.awesome_node" + namespace: "my_ns" + interfaces: + - my_pub: pub-> "awesome::awesome_pub" + node2: + from: "my_awesome2_pkg.awesome2_node" + interfaces: + - my_sub: sub-> "awesome2::awesome2_sub" + parameters: + - array_example: "awesome::awesome_array_param" + value: ["hello", "hallo"] + - bool_example: "awesome::awesome_bool_param" + value: true + - double_example: "awesome::awesome_double_param" + value: 1.2 + - integer_example : "awesome::awesome_integer_param" + value: 2 + - string_param : "awesome::awesome_string_param" + value: "hallo" + - struct_param: "awesome::awesome_struct_param" + value: [ + first: 2 + second: true] + connections: + - [ my_pub, my_sub ] + +The code generator will not create the launch file in these cases, but it will update the README file with instructions on how to install and start the defined file. + +It is strongly recommended to provide information about the components and interfaces within the system. This will help with the documentation and be considered in the system's visualization. diff --git a/docu/MobileBase_beginner.md b/docu/MobileBase_beginner.md deleted file mode 100644 index c9213c3..0000000 --- a/docu/MobileBase_beginner.md +++ /dev/null @@ -1,176 +0,0 @@ -## Hands-on example using common ROS systems (beginner) [![](images/Ros2_logo.png)] - -The execution part of this tutorial will only work for people with a local ROS 2 installation. - -In this tutorial, we are going to see how you can compose existing systems or add a new component to them. For this, we will use the turtlebot in simulation. - -First of all, we need the turtlebot model, this and other models are available in our catalog of components and subsystems. The catalog is publicly available on GitHub [ipa-nhg/RosModelsCatalog](https://github.com/ipa-nhg/RosModelsCatalog). - -Please clone the repository and import it to your Eclipse workspace. This can be easily done by File -> Import -> General -> Existing Projects into Workspace. Then select the container folder of the cloned repository. - -![alt text](images/01_mobile_base_b.gif) - -For this tutorial, we will use the gazebo subsystem. The model is available under **RosModelsCatalog/robots/turtlebot3/simulation/turtlebot_gazebo.rossystem**. This model summarizes the set of nodes that are started in recursive including through the [launch file of the turtlebot_gazebo package](https://github.com/ROBOTIS-GIT/turtlebot3_simulations/blob/master/turtlebot3_gazebo/launch/turtlebot3_world.launch). - -The proposed model looks like this: - -``` -turtlebot_gazebo: - fromFile: "turtlebot3_gazebo/launch/turtlebot3_world.launch.py" - nodes: - gazebo: - from: "gazebo.gazebo" - robot_state_publisher: - from: "robot_state_publisher.robot_state_publisher" - interfaces: - - joint_states: sub-> "robot_state_publisher::joint_states" - - tf: pub-> "robot_state_publisher::tf" - - tf_static: pub-> "robot_state_publisher::tf_static" - turtlebot3_joint_state: - from: "turtlebot3_joint_state.turtlebot3_joint_state" - interfaces: - - joint_states: pub-> "turtlebot3_joint_state::joint_states" - turtlebot3_diff_drive: - from: "turtlebot3_diff_drive.turtlebot3_diff_drive" - interfaces: - - cmd_vel: sub->"turtlebot3_diff_drive::cmd_vel" - - tf: pub->"turtlebot3_diff_drive::tf" - - odom: pub->"turtlebot3_diff_drive::odom" - turtlebot3_imu: - from: "turtlebot3_imu.turtlebot3_imu" - interfaces: - - imu: pub-> "turtlebot3_imu::imu" - camera_driver: - from: "camera_driver.camera_driver" - interfaces: - - camera_info: pub-> "camera_driver::camera/camera_info" - - image_raw: pub-> "camera_driver::camera/image_raw" - - set_camera_info: ss-> "camera_driver::set_camera_info" - turtlebot3_laserscan: - from: "turtlebot3_laserscan.turtlebot3_laserscan" - interfaces: - - scan: pub-> "turtlebot3_laserscan::scan" -``` - -Where the "fromFile" attribute points to the launch file that must be started to run the (sub-)system. - -Then, we added the most relevant nodes and interfaces that we wanted to expose for the integration with higher-level components. In this case robot_state_publisher, turtlebot3_joint_state, turtlebot3_diff_drive, turtlebot3_imu, camera_driver, turtlebot3_laserscan. The granularity of the description and its completeness is a decision that the developer can take. For the RosTooling a file containing only the first two lines: - -``` -turtlebot_gazebo: - fromFile: "turtlebot3_gazebo/launch/turtlebot3_world.launch.py" -``` - -is fully valid. However, for documentation and composability reasons, it is highly recommended the addition of, at least, the most prominent components and their interfaces. All of this information will be taken into account to generate the README.md file. - -### Compose the turtlebot simulation with the teleop keyboard node [![](images/Ros2_logo.png)] - -As a traditional and basic case in mobile base in robotics, we can combine the simulator with the teleop node. - -The catalog repository includes also a keyboard teleop component, it can be found under **RosModelsCatalog/common/teleop_twist_keyboard.ros2**. - -It basically contains one node that takes the commands from the keyboard and transforms them into velocity commands using the common ROS message **geometry_msgs/Twist**. - -The new system can be easily designed by creating a [new .rossystem file](LearnRosSystemModels.md) and adding the two modules we want to compose. First the turtlebot_gazebo as subsystem: - -``` -turtlebot_with_teleop: - subSystems: - turtlebot_gazebo -``` - -And secondly, the teleop keyboard node: -``` -turtlebot_with_teleop: - subSystems: - turtlebot_gazebo - nodes: - teleop_key: - from: "teleop_twist_keyboard.teleop_twist_keyboard" -``` - -![alt text](images/02_mobile_base_b.gif) - -The file will be validated by the RosSystem compiler and the **turtlebot_with_teleop** package created under the src-gen folder. - -The autogenerated README file explains how to install the dependencies and start the system. -![](images/Attention.png) One instruction, particularly for the turtlebot is missed, the robot name has to be set as an environment variable. This means, that before you call the launch command you have to export the following variable: - -``` -export TURTLEBOT3_MODEL=waffle_pi -``` - -![alt text](images/03_mobile_base_b.gif) - -Another nice feature of the RosTooling at this stage of the development, during the design phase, is that makes very easy the testing of alternative components. For example, we can use another implementation of a teleop keyboard node. The catalog contains the description of the package turtlebot_keyboard under **RosModelsCatalog/robots/turtlebot3/turtlebot3_teleop.ros2**. - -By the modification of one line on the model: - -``` -turtlebot_with_teleop: - subSystems: - turtlebot_gazebo - nodes: - teleop: - from: "turtlebot3_teleop.teleop_keyboard" -``` - -![alt text](images/04_mobile_base_b.gif) - -The new package will be fully auto-generated. Contain the dependency on the new implementation of the teleop node and launch it together with the simulation. - -### Compose the turtlebot simulation with the cartographer node [![](images/Ros2_logo.png)] - -Similarly to the previous example, the system can be made more complex. An example of this is to add the [cartographer node](https://google-cartographer-ros.readthedocs.io/en/latest/ros_api.html) to the system. - -The description of the cartographer node is available as part of the catalog, under the folder **navigation**. Also, for the specific case of the turtlebot there is an available configuration, we can basically reuse it as a subsystem with the following model: - -``` -turtlebot_with_teleop_and_cartographer: - subSystems: - turtlebot_gazebo - cartographer - nodes: - teleop: - from: "turtlebot3_teleop.teleop_keyboard" -``` - -![alt text](images/05_mobile_base_b.gif) - - -Then basically, you have to follow the information in the README file. By launching the system you will be able to move the robot using the teleop and in RVIZ visualise the map. To save it, [the common ROS command can be called](https://ros2-industrial-workshop.readthedocs.io/en/latest/_source/navigation/ROS2-Cartographer.html): - -``` -ros2 run nav2_map_server map_saver_cli -f my_map -``` - -### (Optional) Extra notes, and consideration - -By following the previous examples you show that the RosTooling intend to support the ROS developers in the way they usually work. However, at the same time, we aim to promote the follow-up of software quality processes aided by modeling techniques. - -In the previous system, we have not needed an explicit definition of the ports to be connected. However, it has worked because ROS allows it, i.e. whenever a subscriber and a publisher have the same name and type in runtime they will connect automatically. Nevertheless, this is not seen during the design time, and therefore it is not validated by the designer. If we visualize the model we created, we will see the following diagram: - -![alt text](images/turtlebot_with_teleop_and_cartographer_diagram1.jpg) - -As documentation this image is incomplete, also to communicate or give the complete picture of the system to third parties or people without technical knowledge, this is insufficient. Therefore it is convenient to be as explicit as possible, for a better system design, a clean validation process and an understanding of the system before deployment, and to have better-documented software. - -For example in this case it would be: -``` -turtlebot_with_teleop_and_cartographer: - subSystems: - turtlebot_gazebo - cartographer - nodes: - teleop: - from: "turtlebot3_teleop.teleop_keyboard" - interfaces: - - cmd_vel: pub-> "teleop_keyboard::cmd_vel" - connections: - - [cmd_vel, cmd_vel_diff] - - [scan_turtlebot, scan_cart] - - [odom_diff, odom_cart] -``` - -The corresponding visualization would be in that case: - -![alt text](images/turtlebot_with_teleop_and_cartographer_diagram2.jpg) diff --git a/docu/MobileBase_beginner.rst b/docu/MobileBase_beginner.rst new file mode 100644 index 0000000..416ba29 --- /dev/null +++ b/docu/MobileBase_beginner.rst @@ -0,0 +1,184 @@ +Hands-on example using common ROS systems (beginner) +==================================================== + +.. image:: images/Ros2_logo.png + +The execution part of this tutorial will only work for people with a local ROS 2 installation. + +In this tutorial, we are going to see how you can compose existing systems or add a new component to them. For this, we will use the turtlebot in simulation. + +First of all, we need the turtlebot model. This and other models are available in our catalog of components and subsystems. The catalog is publicly available on GitHub `ipa-nhg/RosModelsCatalog `_. + +Please clone the repository and import it to your Eclipse workspace. This can be easily done by navigating to ``File -> Import -> General -> Existing Projects into Workspace``. Then select the container folder of the cloned repository. + +.. image:: images/01_mobile_base_b.gif + +For this tutorial, we will use the gazebo subsystem. The model is available under **RosModelsCatalog/robots/turtlebot3/simulation/turtlebot_gazebo.rossystem**. This model summarizes the set of nodes that are started recursively through the `launch file of the turtlebot_gazebo package `_. + +The proposed model looks like this: + +.. code-block:: yaml + + turtlebot_gazebo: + fromFile: "turtlebot3_gazebo/launch/turtlebot3_world.launch.py" + nodes: + gazebo: + from: "gazebo.gazebo" + robot_state_publisher: + from: "robot_state_publisher.robot_state_publisher" + interfaces: + - joint_states: sub-> "robot_state_publisher::joint_states" + - tf: pub-> "robot_state_publisher::tf" + - tf_static: pub-> "robot_state_publisher::tf_static" + turtlebot3_joint_state: + from: "turtlebot3_joint_state.turtlebot3_joint_state" + interfaces: + - joint_states: pub-> "turtlebot3_joint_state::joint_states" + turtlebot3_diff_drive: + from: "turtlebot3_diff_drive.turtlebot3_diff_drive" + interfaces: + - cmd_vel: sub->"turtlebot3_diff_drive::cmd_vel" + - tf: pub->"turtlebot3_diff_drive::tf" + - odom: pub->"turtlebot3_diff_drive::odom" + turtlebot3_imu: + from: "turtlebot3_imu.turtlebot3_imu" + interfaces: + - imu: pub-> "turtlebot3_imu::imu" + camera_driver: + from: "camera_driver.camera_driver" + interfaces: + - camera_info: pub-> "camera_driver::camera/camera_info" + - image_raw: pub-> "camera_driver::camera/image_raw" + - set_camera_info: ss-> "camera_driver::set_camera_info" + turtlebot3_laserscan: + from: "turtlebot3_laserscan.turtlebot3_laserscan" + interfaces: + - scan: pub-> "turtlebot3_laserscan::scan" + +Where the ``fromFile`` attribute points to the launch file that must be started to run the (sub-)system. + +We then added the most relevant nodes and interfaces that we wanted to expose for integration with higher-level components. In this case, `robot_state_publisher`, `turtlebot3_joint_state`, `turtlebot3_diff_drive`, `turtlebot3_imu`, `camera_driver`, and `turtlebot3_laserscan`. The granularity of the description and its completeness is a decision the developer can take. For the RosTooling, a file containing only the first two lines: + +.. code-block:: yaml + + turtlebot_gazebo: + fromFile: "turtlebot3_gazebo/launch/turtlebot3_world.launch.py" + +is fully valid. However, for documentation and composability reasons, it is highly recommended to add at least the most prominent components and their interfaces. All of this information will be taken into account to generate the ``README.rst`` file. + +Compose the turtlebot simulation with the teleop keyboard node +============================================================= + +.. image:: images/Ros2_logo.png + +As a traditional and basic case in mobile robotics, we can combine the simulator with the teleop node. + +The catalog repository also includes a keyboard teleop component. It can be found under **RosModelsCatalog/common/teleop_twist_keyboard.ros2**. + +It basically contains one node that takes commands from the keyboard and transforms them into velocity commands using the common ROS message ``geometry_msgs/Twist``. + +The new system can be easily designed by creating a `new .rossystem file `_ and adding the two modules we want to compose. First, the turtlebot_gazebo as a subsystem: + +.. code-block:: yaml + + turtlebot_with_teleop: + subSystems: + turtlebot_gazebo + +And secondly, the teleop keyboard node: + +.. code-block:: yaml + + turtlebot_with_teleop: + subSystems: + turtlebot_gazebo + nodes: + teleop_key: + from: "teleop_twist_keyboard.teleop_twist_keyboard" + +.. image:: images/02_mobile_base_b.gif + +The file will be validated by the RosSystem compiler and the **turtlebot_with_teleop** package created under the ``src-gen`` folder. + +The autogenerated ``README`` file explains how to install the dependencies and start the system. + +.. image:: images/Attention.png + +One instruction, particularly for the turtlebot, is missed. The robot name has to be set as an environment variable. This means, before you call the launch command, you have to export the following variable: + +.. code-block:: bash + + export TURTLEBOT3_MODEL=waffle_pi + +.. image:: images/03_mobile_base_b.gif + +Another nice feature of the RosTooling at this stage of development is that it makes testing alternative components easy. For example, we can use another implementation of a teleop keyboard node. The catalog contains the description of the ``turtlebot_keyboard`` package under **RosModelsCatalog/robots/turtlebot3/turtlebot3_teleop.ros2**. + +By modifying one line of the model: + +.. code-block:: yaml + + turtlebot_with_teleop: + subSystems: + turtlebot_gazebo + nodes: + teleop: + from: "turtlebot3_teleop.teleop_keyboard" + +.. image:: images/04_mobile_base_b.gif + +The new package will be fully auto-generated. It will contain the dependency on the new implementation of the teleop node and launch it together with the simulation. + +Compose the turtlebot simulation with the cartographer node +============================================================ + +Similarly to the previous example, the system can be made more complex. An example of this is to add the `cartographer node `_ to the system. + +The description of the cartographer node is available as part of the catalog, under the folder **navigation**. Also, for the specific case of the turtlebot, there is an available configuration. We can reuse it as a subsystem with the following model: + +.. code-block:: yaml + + turtlebot_with_teleop_and_cartographer: + subSystems: + turtlebot_gazebo + cartographer + nodes: + teleop: + from: "turtlebot3_teleop.teleop_keyboard" + +.. image:: images/05_mobile_base_b.gif + +Then, you have to follow the information in the ``README`` file. By launching the system, you will be able to move the robot using the teleop and visualize the map in RVIZ. To save it, `the common ROS command can be called `_: + +.. code-block:: bash + + ros2 run nav2_map_server map_saver_cli -f my_map + +(Optional) Extra notes and considerations +========================================= + +By following the previous examples, you show that the RosTooling intends to support ROS developers in the way they usually work. However, we also aim to promote the follow-up of software quality processes aided by modeling techniques. + +In the previous system, we have not needed an explicit definition of the ports to be connected. However, it worked because ROS allows it. When a subscriber and a publisher have the same name and type in runtime, they connect automatically. Nevertheless, this is not seen during design time, and therefore it is not validated by the designer. If we visualize the model we created, we will see the following diagram: + +.. image:: images/turtlebot_with_teleop_and_cartographer_diagram1.jpg + +As documentation, this image is incomplete. To communicate or give the complete picture of the system to third parties or people without technical knowledge, this is insufficient. Therefore, it is convenient to be as explicit as possible for a better system design, clean validation process, understanding of the system before deployment, and better-documented software. + +For example, in this case, it would be: + +.. code-block:: yaml + + turtlebot_with_teleop_and_cartographer: + subSystems: + turtlebot_gazebo + cartographer + nodes: + teleop: + from: "turtlebot3_teleop.teleop_keyboard" + interfaces: + - cmd_vel: pub-> "tele + +The corresponding visualization would be in that case: + +.. image:: images/turtlebot_with_teleop_and_cartographer_diagram2.jpg diff --git a/docu/NewCommunicationObjects.md b/docu/NewCommunicationObjects.md deleted file mode 100644 index 23bc8ec..0000000 --- a/docu/NewCommunicationObjects.md +++ /dev/null @@ -1,217 +0,0 @@ -# Messages, services and actions generator - -### Autogeneration tools [![](images/Ros2_logo.png)] - - -For the autogeneration of model objects we facilitate a bash: - -``` -source /your_ROS_workspace -wget https://raw.githubusercontent.com/ipa320/RosCommonObjects/main/de.fraunhofer.ipa.ros.communication.objects/basic_msgs/generate_messages_model_helper.sh -chmod +x generate_messages_model_helper.sh -./generate_messages_model_helper.sh ROS_PACKAGE_NAME > ROS_PACKAGE_NAME.ros -``` - -The file generated, independently of the method, will have a *.ros* extension and can be copied to the folder "basic_msgs" of the "de.fraunhofer.ipa.ros.communication.objects" project, please send us a pull request to our [repository](https://github.com/ipa320/RosCommonObjects.git) with your models to include them to the base dictionary automatically. Alternatively, for cases where the messages types are specific for a concrete component (like the ur_msgs for ur_driver or messages types defined within the same repository that the node). We recommended following the same approach that ROS does, define the communication object models together with the node description, for our tooling that means copying the file to the project that will be created on the next step for your node description. - -![](images/Attention.png) The autogenerator script doesn't support actions. - -### ROS communication objects model language grammar - -To modify the ROS models (.ros) manually the ROS tooling provides a customized editor which should be the default option to open the .ros extension files, otherwise, it can be selected manually by a right click on the *MyFile.ros* file and choosing _"Open_ with.."* and *"ROS Editor"*). - -This editor contains an autocomplete function (by pressing Ctrl+Space) and will report any error made by editing. The first step is to define a PackageSet (that corresponds to a metapackage for ROS, this definition is optional and its name can be kept empty). Then, the ROS package which contains the msgs has to be defined and within it, the option "spec" has to be selected to write down the objects. In practice, that means that the initial *.ros file that describes ROS objects looks: - -``` -ros_package_name: - msgs: - msg_name - message - type name -``` - -The grammar supports 3 types of communication objects messages, services and actions, and consequentially each of these 3 types supports different specifications types: - -- ROS msgs - -``` -ros_package_name: - **msgs:** - msg_name - **message** - ElementType ElementName -``` - -For example: -``` -std_msgs: - msgs: - ColorRGBA - message - float32 r - float32 g - float32 b - float32 a -``` - -- ROS srvs - -``` -ros_package_name: - **srvs:** - srv_name - **request** - ElementType ElementName - **response** - ElementType ElementName -``` - -For example: -``` -std_srvs: - srvs: - SetBool - request - bool data - response - bool success - string message -``` - - -- ROS actions - -``` -ros_package_name: - **actions:** - action_name - **goal** - ElementType ElementName - **result** - ElementType ElementName - **feedback** - ElementType ElementName -``` - -For example: -``` -control_msgs: - actions: - PointHead - goal - 'geometry_msgs/msg/PointStamped'[] target - 'geometry_msgs/msg/Vector3'[] pointing_axis - string pointing_frame - 'builtin_interfaces/msg/Duration'[] min_duration - float64 max_velocity - result - feedback - float64 pointing_angle_error -``` - -Where, quite similar to ROS, the allowed element types are: - -- Primitives: - - bool - - int8 - - uint8 - - int16 - - uint16 - - int32 - - uint32 - - int64 - - uint64 - - float32 - - float64 - - string - - time - - Header - -- Relative reference to another object: - - NameOftheObject (if it is described within the same ROS package) -> for example **Point32** - - 'ROSPackage_name/NameOftheObject' (if it is described in another ROS package) -> for example **'geometry_msgs/Point32'** - -- Arrays of element types: - - ElementType[] -> for example **string[]** or **Point32[]** or **'geometry_msgs/Point32'[]** - - -Additionally, the definition of constants with their value is also supported and follows a pattern very similar to the ROS one: ```constanttype1 CONSTANTNAME1=constantvalue1```, for example, ```byte OK=0 byte WARN=1 byte ERROR=2 byte STALE=3```. - -The following extract shows the ROS model description correspondent to the [nav_msgs](http://wiki.ros.org/nav_msgs) package: - -``` -nav_msgs: - msgs: - Path - message - 'std_msgs/msg/Header'[] header - 'geometry_msgs/msg/PoseStamped'[] poses - OccupancyGrid - message - 'std_msgs/msg/Header'[] header - 'nav_msgs/msg/MapMetaData'[] info - int8[] data - Odometry - message - 'std_msgs/msg/Header'[] header - string child_frame_id - 'geometry_msgs/msg/PoseWithCovariance'[] pose - 'geometry_msgs/msg/TwistWithCovariance'[] twist - GridCells - message - 'std_msgs/msg/Header'[] header - float32 cell_width - float32 cell_height - 'geometry_msgs/msg/Point'[] cells - MapMetaData - message - 'builtin_interfaces/msg/Time'[] map_load_time - float32 resolution - uint32 width - uint32 height - 'geometry_msgs/msg/Pose'[] origin - srvs: - SetMap - request - 'nav_msgs/msg/OccupancyGrid'[] map - 'geometry_msgs/msg/PoseWithCovarianceStamped'[] initial_pose - response - bool success - LoadMap - request - string map_url - response - 'nav_msgs/msg/OccupancyGrid'[] map - uint8 result - GetPlan - request - 'geometry_msgs/msg/PoseStamped'[] start - 'geometry_msgs/msg/PoseStamped'[] goal - float32 tolerance - response - 'nav_msgs/msg/Path'[] plan - GetMap - request - response - 'nav_msgs/msg/OccupancyGrid'[] map -``` - -### Known-issues - -![](images/Attention.png) This model doesn't allow the creation of 2 specifications with the same name, although they have different types. That means a ROS model like the following one is not allowed: - -``` -my_msgs: - msgs: - hello: - message - String data - srvs: - hello - request - response - String data -``` -The reason is that when one of these objects has to be referenced during the definition of a node it will be impossible for the model to distinguish which is the correct one (both are defined as my_msgs/Hello and within the dame model file). For these cases, we recommend splitting the objects into two different model files. - -The repository [RosCommonObjects](https://github.com/ipa320/RosCommonObjects) holds further examples. \ No newline at end of file diff --git a/docu/NewCommunicationObjects.rst b/docu/NewCommunicationObjects.rst new file mode 100644 index 0000000..74d2df2 --- /dev/null +++ b/docu/NewCommunicationObjects.rst @@ -0,0 +1,241 @@ +Messages, services and actions generator +======================================== + +Autogeneration tools ![](images/Ros2_logo.png) +---------------------------------------------- + +For the autogeneration of model objects, we provide a bash script: + +.. code-block:: bash + + source /your_ROS_workspace + wget https://raw.githubusercontent.com/ipa320/RosCommonObjects/main/de.fraunhofer.ipa.ros.communication.objects/basic_msgs/generate_messages_model_helper.sh + chmod +x generate_messages_model_helper.sh + ./generate_messages_model_helper.sh ROS_PACKAGE_NAME > ROS_PACKAGE_NAME.ros + +The file generated, independently of the method, will have a `.ros` extension and can be copied to the folder "basic_msgs" of the "de.fraunhofer.ipa.ros.communication.objects" project. Please send us a pull request to our `repository `_ with your models to include them in the base dictionary automatically. + +Alternatively, for cases where the message types are specific to a particular component (like `ur_msgs` for `ur_driver` or message types defined within the same repository as the node), we recommend following the same approach as ROS does: define the communication object models together with the node description. For our tooling, that means copying the file to the project created in the next step for your node description. + +.. image:: images/Attention.png + :alt: Attention + :scale: 50% + +The autogenerator script does not support actions. + +ROS communication objects model language grammar +------------------------------------------------ + +To modify the ROS models (`.ros`) manually, the ROS tooling provides a customized editor, which should be the default option to open the `.ros` extension files. Otherwise, it can be selected manually by right-clicking on the *MyFile.ros* file and choosing _"Open with.."_ and selecting *"ROS Editor"*. + +This editor contains an autocomplete function (by pressing **Ctrl+Space**) and will report any errors made during editing. The first step is to define a **PackageSet** (this corresponds to a metapackage for ROS; this definition is optional, and its name can be kept empty). Then, the ROS package which contains the messages has to be defined, and within it, the option "spec" has to be selected to write down the objects. In practice, this means that the initial `.ros` file that describes ROS objects looks like: + +.. code-block:: yaml + + ros_package_name: + msgs: + msg_name + message + type name + +The grammar supports three types of communication objects: messages, services, and actions. Consequently, each of these three types supports different specification types: + +- ROS messages (msgs) + +.. code-block:: yaml + + ros_package_name: + msgs: + msg_name + message + ElementType ElementName + +For example: + +.. code-block:: yaml + + std_msgs: + msgs: + ColorRGBA + message + float32 r + float32 g + float32 b + float32 a + +- ROS services (srvs) + +.. code-block:: yaml + + ros_package_name: + srvs: + srv_name + request + ElementType ElementName + response + ElementType ElementName + +For example: + +.. code-block:: yaml + + std_srvs: + srvs: + SetBool + request + bool data + response + bool success + string message + +- ROS actions + +.. code-block:: yaml + + ros_package_name: + actions: + action_name + goal + ElementType ElementName + result + feedback + ElementType ElementName + +For example: + +.. code-block:: yaml + + control_msgs: + actions: + PointHead + goal + 'geometry_msgs/msg/PointStamped'[] target + 'geometry_msgs/msg/Vector3'[] pointing_axis + string pointing_frame + 'builtin_interfaces/msg/Duration'[] min_duration + float64 max_velocity + result + feedback + float64 pointing_angle_error + +As in ROS, the allowed element types are: + +- **Primitives:** + - bool + - int8 + - uint8 + - int16 + - uint16 + - int32 + - uint32 + - int64 + - uint64 + - float32 + - float64 + - string + - time + - Header + +- **Relative reference to another object:** + - `NameOftheObject` (if it is described within the same ROS package) -> e.g., **Point32** + - `'ROSPackage_name/NameOftheObject'` (if it is described in another ROS package) -> e.g., **'geometry_msgs/Point32'** + +- **Arrays of element types:** + - `ElementType[]` -> e.g., **string[]** or **Point32[]** or **'geometry_msgs/Point32'[]** + +Additionally, the definition of constants with their values is supported and follows a pattern very similar to ROS: + +.. code-block:: yaml + + constanttype1 CONSTANTNAME1=constantvalue1 + +For example: + +.. code-block:: yaml + + byte OK=0 byte WARN=1 byte ERROR=2 byte STALE=3 + +The following extract shows the ROS model description corresponding to the `nav_msgs `_ package: + +.. code-block:: yaml + + nav_msgs: + msgs: + Path + message + 'std_msgs/msg/Header'[] header + 'geometry_msgs/msg/PoseStamped'[] poses + OccupancyGrid + message + 'std_msgs/msg/Header'[] header + 'nav_msgs/msg/MapMetaData'[] info + int8[] data + Odometry + message + 'std_msgs/msg/Header'[] header + string child_frame_id + 'geometry_msgs/msg/PoseWithCovariance'[] pose + 'geometry_msgs/msg/TwistWithCovariance'[] twist + GridCells + message + 'std_msgs/msg/Header'[] header + float32 cell_width + float32 cell_height + 'geometry_msgs/msg/Point'[] cells + MapMetaData + message + 'builtin_interfaces/msg/Time'[] map_load_time + float32 resolution + uint32 width + uint32 height + 'geometry_msgs/msg/Pose'[] origin + srvs: + SetMap + request + 'nav_msgs/msg/OccupancyGrid'[] map + 'geometry_msgs/msg/PoseWithCovarianceStamped'[] initial_pose + response + bool success + LoadMap + request + string map_url + response + 'nav_msgs/msg/OccupancyGrid'[] map + uint8 result + GetPlan + request + 'geometry_msgs/msg/PoseStamped'[] start + 'geometry_msgs/msg/PoseStamped'[] goal + float32 tolerance + response + 'nav_msgs/msg/Path'[] plan + GetMap + request + response + 'nav_msgs/msg/OccupancyGrid'[] map + +Known issues +------------ + +.. image:: images/Attention.png + :alt: Attention + :scale: 50% + +This model does not allow the creation of two specifications with the same name, even if they have different types. For example, the following ROS model is not allowed: + +.. code-block:: yaml + + my_msgs: + msgs: + hello: + message + String data + srvs: + hello + request + response + String data + +The reason is that when one of these objects has to be referenced during the definition of a node, it will be impossible for the model to distinguish which one is correct (both are defined as `my_msgs/Hello` and within the same model file). For these cases, we recommend splitting the objects into two different model files. + +The repository `RosCommonObjects `_ holds further examples. diff --git a/docu/NewRosModel.md b/docu/NewRosModel.md deleted file mode 100644 index fee838c..0000000 --- a/docu/NewRosModel.md +++ /dev/null @@ -1,34 +0,0 @@ -:bangbang::bangbang::bangbang::bangbang: This tutorial is only working for previous versions of the RosTooling (v2) - - -## Create a ROS model from your code - -Please be sure that the tool is installed and your workspace setup, see the [installation guide](../README.md) for further details. - -To extract your model from ROS code ou have 2 options: -- [Call our docker container configuration for the extraction from a GitHub hosted repository (requires only the installation of Docker)](#docker-container) -- [Use a local build of your ROS package (requires the local installation of HAROS)](#local-ros-workspace) - -### Docker container - -Clone the repository [ros-model-extractors](https://github.com/ipa320/ros-model-extractors) and follow its [documentation instructions](https://github.com/ipa320/ros-model-extractors#ros-model-extractors). - -Save the result content of the extraction as a ".ros" file in your tooling workspace. You can also contribute by sending us your generated files to be added to our database of models [RosCommonModels](https://github.com/ipa320/RosCommonModels). - -To check the created model open the file representation.aird with the Aird editor and in the menu representations choose the "component" option and press "New.." then choose the Artifact entity of your "*.ros" model and press finish. - -### Local ROS workspace - -:bangbang::bangbang: this section requires a local ROS installation - -To extract the model we use static code analysis techniques, concretely the framework HAROS. To analyze a local ROS package you have first to install and setup [HAROS](../tools/README.md#model-extractor-using-static-code-analysis). - -Once HAROS is installed and your workspace built you can invoke the extractor of ROS models from the tooling, by pressing the icon "Import ROS model": - -![alt text](images/import_ros_model.png) - -Choose the directory that should hold your model and press "Next >" a new dialog window will ask you for the name of the ROS package that contains your node and the name of the node. Finally, you have to specify the workspace where it was built by choosing the *compile_commands.json* file. This file is always located under your *catkin_ws/build* directory when you build your workspace using the make command option *-DCMAKE_EXPORT_COMPILE_COMMANDS=1*. - -![alt text](images/compile_commands.png) - -To check the created model open the file representation.aird with the Aird editor and in the menu representations choose the "component" option and press "New.." then choose the Artifact entity of your "*.ros" model and press finish. diff --git a/docu/NewRosModel.rst b/docu/NewRosModel.rst new file mode 100644 index 0000000..c8b8772 --- /dev/null +++ b/docu/NewRosModel.rst @@ -0,0 +1,69 @@ +:bangbang::bangbang::bangbang::bangbang: This tutorial is only working +for previous versions of the RosTooling (v2) + +Create a ROS model from your code +--------------------------------- + +Please be sure that the tool is installed and your workspace setup, see +the `installation guide <../README.rst>`__ for further details. + +To extract your model from ROS code ou have 2 options: - `Call our +docker container configuration for the extraction from a GitHub hosted +repository (requires only the installation of +Docker) <#docker-container>`__ - `Use a local build of your ROS package +(requires the local installation of HAROS) <#local-ros-workspace>`__ + +Docker container +~~~~~~~~~~~~~~~~ + +Clone the repository +`ros-model-extractors `__ +and follow its `documentation +instructions `__. + +Save the result content of the extraction as a “.ros” file in your +tooling workspace. You can also contribute by sending us your generated +files to be added to our database of models +`RosCommonModels `__. + +To check the created model open the file representation.aird with the +Aird editor and in the menu representations choose the “component” +option and press “New..” then choose the Artifact entity of your +“\*.ros” model and press finish. + +Local ROS workspace +~~~~~~~~~~~~~~~~~~~ + +:bangbang::bangbang: this section requires a local ROS installation + +To extract the model we use static code analysis techniques, concretely +the framework HAROS. To analyze a local ROS package you have first to +install and setup +`HAROS <../tools/README.rst#model-extractor-using-static-code-analysis>`__. + +Once HAROS is installed and your workspace built you can invoke the +extractor of ROS models from the tooling, by pressing the icon “Import +ROS model”: + +.. figure:: images/import_ros_model.png + :alt: alt text + + alt text + +Choose the directory that should hold your model and press “Next >” a +new dialog window will ask you for the name of the ROS package that +contains your node and the name of the node. Finally, you have to +specify the workspace where it was built by choosing the +*compile_commands.json* file. This file is always located under your +*catkin_ws/build* directory when you build your workspace using the make +command option *-DCMAKE_EXPORT_COMPILE_COMMANDS=1*. + +.. figure:: images/compile_commands.png + :alt: alt text + + alt text + +To check the created model open the file representation.aird with the +Aird editor and in the menu representations choose the “component” +option and press “New..” then choose the Artifact entity of your +“\*.ros” model and press finish. diff --git a/docu/ParametersAPI.md b/docu/ParametersAPI.md deleted file mode 100644 index 768d5f6..0000000 --- a/docu/ParametersAPI.md +++ /dev/null @@ -1,85 +0,0 @@ -## Parameters API - -The types of parameters supported by the ROS tooling are the following: - -* Boolean (true or false) -* Integer -* Double -* String -* Base64 -* List -* Array -* Struct - -and their description is allowed at ROS and ROSSystem model level. - -For the complete definition of parameters, the user has to open the ROS model editor, where the language format is the following: -``` -**parameters:** - ParameterName: - **type:** ParameterType - **value:** ParameterValue -``` - -For example (for a .ros2 file): - -``` -test_parameters: - artifacts: - test_parameters: - node: params_example - parameters: - string_test: - type: String - bool_test: - type: Boolean - array_test: - type: Array [String] - base64_test: - type: Base64 - double_test: - type: Double - integer_test: - type: Integer - list_test: - type: List [Integer,Integer,String] - array_test: - type: Array [String] - struct_test: - type: Struct [hello Integer, what String] -``` - -These parameters can be re-set at Rossystem level (that means for ROS developers, the case of the set of a new parameter value within a node included on a ROS launch file). For the tooling, the format is the following: - -``` -- ParameterName : ParameterReferenceInRos2File - **value:** ParameterValue -``` - -Continuing the previous example, the parameters redefinition looks: - -``` -test: - nodes: - params_node: - from: "test_parameters.params_example" - parameters: - - test_s : "test_parameters::string_test" - value: "hello" - - test_b : "test_parameters::bool_test" - value: true - - test_d : "test_parameters::double_test" - value: 1.1 - - test_i : "test_parameters::integer_test" - value: 1 - - test_l: "test_parameters::list_test" - value: [1,1,"hello"] - - test_a: "test_parameters::array_test" - value: ["hello", "hola", "hallo"] - - test_st: "test_parameters::struct_test" - value: [ - hello: 1 - what: "test"] -``` -The model definition of parameters is also considered for the autogeneration of launch files. -Complementarily, and because of the complexity of the format, the .ros1, .ros2, and the .rossystem language validators contain rules to check that the value given to the parameter has the correct type and also help messages that together with the auto-complete function (Ctrl+Space) facilitate the user the creation of parameters. \ No newline at end of file diff --git a/docu/ParametersAPI.rst b/docu/ParametersAPI.rst new file mode 100644 index 0000000..334b271 --- /dev/null +++ b/docu/ParametersAPI.rst @@ -0,0 +1,90 @@ +Parameters API +============== + +The types of parameters supported by the ROS tooling are the following: + +- Boolean (true or false) +- Integer +- Double +- String +- Base64 +- List +- Array +- Struct + +Their description is allowed at both the ROS and ROSSystem model levels. + +For the complete definition of parameters, the user has to open the ROS model editor, where the language format is the following: + +.. code-block:: none + + **parameters:** + ParameterName: + **type:** ParameterType + **value:** ParameterValue + +For example (for a ``.ros2`` file): + +.. code-block:: yaml + + test_parameters: + artifacts: + test_parameters: + node: params_example + parameters: + string_test: + type: String + bool_test: + type: Boolean + array_test: + type: Array [String] + base64_test: + type: Base64 + double_test: + type: Double + integer_test: + type: Integer + list_test: + type: List [Integer,Integer,String] + array_test: + type: Array [String] + struct_test: + type: Struct [hello Integer, what String] + +These parameters can be re-set at the ROSSystem level (for ROS developers, this means setting a new parameter value within a node included in a ROS launch file). +For the tooling, the format is the following: + +.. code-block:: none + + - ParameterName : ParameterReferenceInRos2File + **value:** ParameterValue + +Continuing with the previous example, the parameters redefinition looks like this: + +.. code-block:: yaml + + test: + nodes: + params_node: + from: "test_parameters.params_example" + parameters: + - test_s : "test_parameters::string_test" + value: "hello" + - test_b : "test_parameters::bool_test" + value: true + - test_d : "test_parameters::double_test" + value: 1.1 + - test_i : "test_parameters::integer_test" + value: 1 + - test_l: "test_parameters::list_test" + value: [1,1,"hello"] + - test_a: "test_parameters::array_test" + value: ["hello", "hola", "hallo"] + - test_st: "test_parameters::struct_test" + value: [ + hello: 1 + what: "test"] + +The model definition of parameters is also considered for the auto-generation of launch files. +Additionally, due to the complexity of the format, the ``.ros1``, ``.ros2``, and ``.rossystem`` language validators contain rules to ensure that the value given to the parameter has the correct type. +These validators also provide helpful messages, and, along with the auto-complete function (**Ctrl+Space**), they assist the user in creating parameters. diff --git a/docu/Release.md b/docu/Release.md deleted file mode 100644 index c1f26d2..0000000 --- a/docu/Release.md +++ /dev/null @@ -1,39 +0,0 @@ -# Update Release versions (only for administrators) - -### 1. Update version - -Run the command: - -``` -mvn versions:set -DnewVersion=X.Y.Z-SNAPSHOT -f plugins/de.fraunhofer.ipa.ros.parent/pom.xml -``` - -This will upgrade the *pom.xml* and *MANIFEST.MF* of all the repositories. - -### 2. Synchronize the ROS fetuare - -Open in eclipse the file *de.fraunhofer.ipa.ros.feature/feature.xml* and under *Overview* press the button *Synchronize* and choose the second option *Copy versions from plug-in, feature and fragment manifest* - -![alt text](images/sync_feature.png) - - -Push to this GitHub repository the status - -### 3. Export the updated feature - -From the menu *File* select *Export* and choose the option *Deployable features* from *Plug-in Development* category. Select the *de.fraunhofer.ipa.ros.feature* Feature and give a path for destination (e.g. ~/Desktop/export) - -The resulted folders and files have to be copied to the *updatesite/latest* folder fo the [Update Site server](http://ros-model.seronet-project.de/updatesite/latest/) and the [site.xml](http://ros-model.seronet-project.de/updatesite/latest/site.xml) file updated to point the new version. - -### 4. Add a new release on GitHub - -Tag the current point of the history with the release number previously given (X.Y.0). Optionally upgrade the [exported files](#3-export-the-updated-feature) as a zip. - -# Create a new .jar file as release - -In the folder *plugins/de.fraunhofer.ipa.ros.parent* execute the command: -``` -mvn package -``` - -The generated .jar file will be automatically generated under *plugins/de.fraunhofer.ipa.ros.plugin/target/de.fraunhofer.ipa.ros.plugin-X.Y.Z-SNAPSHOT.jar*. diff --git a/docu/Release.rst b/docu/Release.rst new file mode 100644 index 0000000..fd7b14e --- /dev/null +++ b/docu/Release.rst @@ -0,0 +1,63 @@ +Update Release versions (only for administrators) +================================================= + +1. Update version +~~~~~~~~~~~~~~~~~ + +Run the command: + +:: + + mvn versions:set -DnewVersion=X.Y.Z-SNAPSHOT -f plugins/de.fraunhofer.ipa.ros.parent/pom.xml + +This will upgrade the *pom.xml* and *MANIFEST.MF* of all the +repositories. + +2. Synchronize the ROS fetuare +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Open in eclipse the file *de.fraunhofer.ipa.ros.feature/feature.xml* and +under *Overview* press the button *Synchronize* and choose the second +option *Copy versions from plug-in, feature and fragment manifest* + +.. figure:: images/sync_feature.png + :alt: alt text + + alt text + +Push to this GitHub repository the status + +3. Export the updated feature +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +From the menu *File* select *Export* and choose the option *Deployable +features* from *Plug-in Development* category. Select the +*de.fraunhofer.ipa.ros.feature* Feature and give a path for destination +(e.g. ~/Desktop/export) + +The resulted folders and files have to be copied to the +*updatesite/latest* folder fo the `Update Site +server `__ and +the +`site.xml `__ +file updated to point the new version. + +4. Add a new release on GitHub +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Tag the current point of the history with the release number previously +given (X.Y.0). Optionally upgrade the `exported +files <#3-export-the-updated-feature>`__ as a zip. + +Create a new .jar file as release +================================= + +In the folder *plugins/de.fraunhofer.ipa.ros.parent* execute the +command: + +:: + + mvn package + +The generated .jar file will be automatically generated under +*plugins/de.fraunhofer.ipa.ros.plugin/target/de.fraunhofer.ipa.ros.plugin-X.Y.Z-SNAPSHOT.jar*. diff --git a/docu/RosModelDescription.md b/docu/RosModelDescription.md deleted file mode 100644 index 38b24c3..0000000 --- a/docu/RosModelDescription.md +++ /dev/null @@ -1,202 +0,0 @@ -# HOW TO DESCRIBE ROS NODES USING THE LANGUAGE - -Component models have two types of extensions, either .ros1 for ROS version 1 packages and .ros2 for ROS 2 packages. In both cases the language allows to describe package that contains ROS nodes and their interfaces. -To create a new model, you can easily just create a new file with the correct extension, the RosTooling environment will automatically recognize it and make use of its related features for the textual editor. - -## ROS (1) - -In ros1 the grammar is as follows: -``` -my_awesome_pkg: #Name of the package - **fromGitRepo: ** "http://github.com/MyAccount/RepoName:BranchName" # Optional, Git reopsitory path that contains the source code - **artifacts:** - awesome: # Name of the artifact (as it is named in the CMakeLists) - **node:** awesome_node # Name of the node - **publishers:** # (Optional) List of publishers - awesome_pub: - **type:** "std_msgs/msg/Bool" - **subscribers:** # (Optional) List of subscribers - awesome_sub: - **type:** "std_msgs/msg/Bool" - **serviceclients:** # (Optional) List of service clients - awesome_client: - **type:** "std_srvs/srv/Empty" - **serviceservers:** # (Optional) List of service servers - awesome_server: - **type:** "std_srvs/srv/Empty" - **actionclients:** # (Optional) List of action clients - awesome_action: - **type:** "control_msgs/action/JointTrajectory" - **actionservers:** # (Optional) List of action servers - awesome_action: - **type:** "control_msgs/action/JointTrajectory" - **parameters:** # (Optional) List of parameters - awesome_param: - **type:** String - **default:** "Hello" -``` - - -The format is based on YAML. All the words marked in the template with '**' are keywords that compose the model, they can't be modified. - - -See the following model example for the known teleop ROS package: - -``` -teleop: - artifacts: - teleop_twist_joy_node: - node: teleop_twist_joy_node - publishers: - cmd_vel: - type: "geometry_msgs/msg/Twist" - subscribers: - joy: - type:"sensor_msgs/msg/Joy" -``` - -## ROS 2 - -The ros2 grammar is as follows: -``` -my_awesome_pkg: - **fromGitRepo: ** "http://github.com/MyAccount/RepoName:BranchName" - **artifacts:** - awesome: - **node:** awesome_node - **publishers:** - awesome_pub: - **type:** "std_msgs/msg/Bool" - **qos:** - **depth:** 10 - **durability:** volatile - **history:** keep_all - **profile:** default_qos - **reliability:** best_effort - **subscribers:** - awesome_sub: - **type:** "std_msgs/msg/Bool" - **qos:** - **depth:** 10 - **durability:** transient_local - **history:** keep_last - **profile:** sensor_qos - **reliability:** reliable - **serviceclients:** - awesome_client: - **type:** "std_srvs/srv/Empty" - **qos:** - **depth:** 10 - **durability:** volatile - **history:** keep_all - **profile:** services_qos - **reliability:** best_effort - **serviceservers:** - awesome_server: - **type:** "std_srvs/srv/Empty" - **qos:** - **depth:** 10 - **durability:** volatile - **history:** keep_all - **profile:** services_qos - **reliability:** best_effort - **actionclients:** - awesome_action: - **type:** "control_msgs/action/JointTrajectory" - **qos:** - **depth:** 10 - **durability:** volatile - **history:** keep_all - **profile:** default_qos - **reliability:** best_effort - **actionservers:** - awesome_action: - **type:** "control_msgs/action/JointTrajectory" - **qos:** - **depth:** 10 - **durability:** volatile - **history:** keep_all - **profile:** default_qos - **reliability:** best_effort - **parameters:** - awesome_param: - **type:** String - **default:** "Hello" - **qos:** - **depth:** 10 - **durability:** volatile - **history:** keep_all - **profile:** parameter_qos - **reliability:** best_effort -``` - -The only remarkable difference with the ROS 1 model is that the quality of service can be defined for all the interfaces. The quality of service attributes are optional and they allow the following options: - -- depth: it must be an integer. -- durability: volatile / transient_local -- history: keep_all / keep_last -- profile: default_qos / sensor_qos / services_qos/ parameter_qos -- reliability: best_effort / reliable - -The type of supported parameters are: -- Boolean -- Double -- String -- Integer -- Base64 -- List [Type, Type] -- Array [Type] -- Struct [Name Type, Name Type] - -For more details about parameters, please check the [site about the parameters definition](ParametersAPI.md). - -See the following example for the [arucos_ros](https://github.com/pal-robotics/aruco_ros) driver: - -``` -aruco_ros: - fromGitRepo: "https://github.com/pal-robotics/aruco_ros.git:humble-devel" - artifacts: - marker_publisher: - node: marker_publisher - subscribers: - image_raw: - type: "sensor_msgs/msg/Image" - publishers: - debug: - type: "sensor_msgs/msg/Image" - markers: - type: "aruco_msgs/msg/MarkerArray" - markers_list: - type: "std_msgs/msg/UInt32MultiArray" - result: - type: "sensor_msgs/msg/Image" - parameters: - camera_frame: - type: String - image_is_rectified: - type: Boolean - marker_size: - type: Double - reference_frame: - type: String - raw_image_topic: - type: String - use_camera_info: - type: Boolean - use_sim_time: - type: Boolean - camera_info_topic: - type: String -``` - -## Textual model editor - -The textual editor contains a checker embedded, for example: - -![alt text](images/RosModelEmbededChecker.gif) - -It incorporates also the auto-complete function. This is available by pressing **Ctrl** + the space bar: - -![alt text](images/RosModelAutocomplete.gif) - -In the [tutorials](LearnRosModels.md) you will be guided to try all of these features. \ No newline at end of file diff --git a/docu/RosModelDescription.rst b/docu/RosModelDescription.rst new file mode 100644 index 0000000..eb26f76 --- /dev/null +++ b/docu/RosModelDescription.rst @@ -0,0 +1,206 @@ +HOW TO DESCRIBE ROS NODES USING THE LANGUAGE +============================================ + +Component models have two types of extensions, either ``.ros1`` for ROS version 1 packages or ``.ros2`` for ROS 2 packages. In both cases, the language allows describing a package that contains ROS nodes and their interfaces. +To create a new model, you can easily create a new file with the correct extension, and the RosTooling environment will automatically recognize it and make use of its related features for the textual editor. + +ROS (1) +------- + +In ROS 1, the grammar is as follows: + +.. code-block:: yaml + + my_awesome_pkg: # Name of the package + **fromGitRepo: ** "http://github.com/MyAccount/RepoName:BranchName" # Optional, Git repository path that contains the source code + **artifacts:** + awesome: # Name of the artifact (as it is named in the CMakeLists) + **node:** awesome_node # Name of the node + **publishers:** # (Optional) List of publishers + awesome_pub: + **type:** "std_msgs/msg/Bool" + **subscribers:** # (Optional) List of subscribers + awesome_sub: + **type:** "std_msgs/msg/Bool" + **serviceclients:** # (Optional) List of service clients + awesome_client: + **type:** "std_srvs/srv/Empty" + **serviceservers:** # (Optional) List of service servers + awesome_server: + **type:** "std_srvs/srv/Empty" + **actionclients:** # (Optional) List of action clients + awesome_action: + **type:** "control_msgs/action/JointTrajectory" + **actionservers:** # (Optional) List of action servers + awesome_action: + **type:** "control_msgs/action/JointTrajectory" + **parameters:** # (Optional) List of parameters + awesome_param: + **type:** String + **default:** "Hello" + +The format is based on YAML. All the words marked in the template with '**' are keywords that compose the model and cannot be modified. + +See the following model example for the known teleop ROS package: + +.. code-block:: yaml + + teleop: + artifacts: + teleop_twist_joy_node: + node: teleop_twist_joy_node + publishers: + cmd_vel: + type: "geometry_msgs/msg/Twist" + subscribers: + joy: + type:"sensor_msgs/msg/Joy" + +ROS 2 +----- + +The ROS 2 grammar is as follows: + +.. code-block:: yaml + + my_awesome_pkg: + **fromGitRepo: ** "http://github.com/MyAccount/RepoName:BranchName" + **artifacts:** + awesome: + **node:** awesome_node + **publishers:** + awesome_pub: + **type:** "std_msgs/msg/Bool" + **qos:** + **depth:** 10 + **durability:** volatile + **history:** keep_all + **profile:** default_qos + **reliability:** best_effort + **subscribers:** + awesome_sub: + **type:** "std_msgs/msg/Bool" + **qos:** + **depth:** 10 + **durability:** transient_local + **history:** keep_last + **profile:** sensor_qos + **reliability:** reliable + **serviceclients:** + awesome_client: + **type:** "std_srvs/srv/Empty" + **qos:** + **depth:** 10 + **durability:** volatile + **history:** keep_all + **profile:** services_qos + **reliability:** best_effort + **serviceservers:** + awesome_server: + **type:** "std_srvs/srv/Empty" + **qos:** + **depth:** 10 + **durability:** volatile + **history:** keep_all + **profile:** services_qos + **reliability:** best_effort + **actionclients:** + awesome_action: + **type:** "control_msgs/action/JointTrajectory" + **qos:** + **depth:** 10 + **durability:** volatile + **history:** keep_all + **profile:** default_qos + **reliability:** best_effort + **actionservers:** + awesome_action: + **type:** "control_msgs/action/JointTrajectory" + **qos:** + **depth:** 10 + **durability:** volatile + **history:** keep_all + **profile:** default_qos + **reliability:** best_effort + **parameters:** + awesome_param: + **type:** String + **default:** "Hello" + **qos:** + **depth:** 10 + **durability:** volatile + **history:** keep_all + **profile:** parameter_qos + **reliability:** best_effort + +The main difference with the ROS 1 model is that the quality of service can be defined for all the interfaces. The quality of service attributes are optional and they allow the following options: + +- **depth:** must be an integer. +- **durability:** volatile / transient_local +- **history:** keep_all / keep_last +- **profile:** default_qos / sensor_qos / services_qos/ parameter_qos +- **reliability:** best_effort / reliable + +The types of supported parameters are: +- Boolean +- Double +- String +- Integer +- Base64 +- List [Type, Type] +- Array [Type] +- Struct [Name Type, Name Type] + +For more details about parameters, please check the `site about the parameters definition `_. + +See the following example for the `aruco_ros `_ driver: + +.. code-block:: yaml + + aruco_ros: + fromGitRepo: "https://github.com/pal-robotics/aruco_ros.git:humble-devel" + artifacts: + marker_publisher: + node: marker_publisher + subscribers: + image_raw: + type: "sensor_msgs/msg/Image" + publishers: + debug: + type: "sensor_msgs/msg/Image" + markers: + type: "aruco_msgs/msg/MarkerArray" + markers_list: + type: "std_msgs/msg/UInt32MultiArray" + result: + type: "sensor_msgs/msg/Image" + parameters: + camera_frame: + type: String + image_is_rectified: + type: Boolean + marker_size: + type: Double + reference_frame: + type: String + raw_image_topic: + type: String + use_camera_info: + type: Boolean + use_sim_time: + type: Boolean + camera_info_topic: + type: String + +Textual model editor +-------------------- + +The textual editor contains an embedded checker. For example: + +.. image:: images/RosModelEmbededChecker.gif + +It also incorporates the auto-complete function, which is available by pressing **Ctrl** + the space bar: + +.. image:: images/RosModelAutocomplete.gif + +In the `tutorials `_, you will be guided to try all of these features. diff --git a/docu/RosSystemModelDescription.md b/docu/RosSystemModelDescription.md deleted file mode 100644 index e517ce5..0000000 --- a/docu/RosSystemModelDescription.md +++ /dev/null @@ -1,54 +0,0 @@ -# HOW TO DESCRIBE ROS SYSTEMS USING THE LANGUAGE - -In our case we consider a system to be a combination of nodes running at the same time. Basically, we use the typical component-based system concept, where each ROS node could be considered a component. Therefore the .rossystem file allows us to describe a series of nodes and the connections that are created between them using topics, services or actions. It also allows us to give values to the parameters. - -The structure of the system description is as shown in the following diagram: - -![alt text](images/system_class_diagram.jpg) - -The format of a system is as follows: -``` -my_awesome_system: - fromFile: 'pkg_name/launch/file.launch.py' - subSystems: - another_awesome_system # From another .rossystem file - processes: - process1: - nodes: [ node1 , node2 ] - threads: 2 - nodes: - node1: - from: "my_awesome_pkg.awesome_node_provider" #From .ros2 file - interfaces: - - awesome_pub: pub-> "awesome::awesome_pub" # From .ros2 file - parameters: - - ParamName: "awesome::awesome_param" - value: "Label" - node2: - from: "my_awesome_pkg.awesome_node_consumer" #From .ros2 file - interfaces: - - awesome_sub: sub-> "awesome::awesome_sub" - connections: - -[awesome_pub, awesome_sub] -``` - -Below we analyze each part that makes up the system and how it is formed: - -- (Optional) Processes: describes all system processes. Each process is determined by a name (process1 in the example), a set of nodes given as a list and the number of threads. The nodes must be defined within the system nodes. - -- (Optional) fromFile: this attribute can be used for those systems that already have a launch file where all the nodes are composed. It expects a string with the name of the package followed by the relative path to the launch file. - -- (Optional) subSystems: list of all the systems that compose the new systems as subsystems. The name of the system must correspond to the name given to the system in another .rossystem file. - -- Nodes: describes all nodes in the system. Nodes are described as a reference to an existing package (and described in a .ros2 file) and have the following attributes: - - name: A name that must be unique in the file (in the example node1). - - from: reference to the instantiated node description. It is given by the name of the package that contains it and the name of the original node. - - interfaces: list of all the interfaces of the node. Here it is not mandatory to list the interfaces (again) as they are already on the .ros2 file. Only the renamed interfaces must be added, as well as, interfaces that will form a connection with other components. A referenced interface is given by: **NewName: Type -> ref_artifact_name::ref_interface_name** where `ref_artifact_name` and `ref_artifact_name` come from the ros2 file. And the Type can be pub, sub, sc, ss, ac, or as. - - parameters: it is used to pass a value to a parameter. Every parameter shall have a name (my_param) in the example, and the reference to an existing parameter, given by 'artifact_name::param_name' from a .ros2 file. Then under value, a new value can be given to the parameter. - -- (Optional) Connections: describe the connections between the nodes. They are given by `[name_of_the_output, name_of_the_input]` the outputs and inputs must be previously created, they must have the same communication pattern (topic, service or action) and the same type of communication object (for example std_msgs/String). Otherwise, the validator will give an error. - -The Editor of the models contains validators and the auto-complete function, which can be called with the combination of the keys `Ctrl` and space bar. - - -In the [tutorials](LearnRosSystemModels.md) you will be guided to try all of these features. \ No newline at end of file diff --git a/docu/RosSystemModelDescription.rst b/docu/RosSystemModelDescription.rst new file mode 100644 index 0000000..584afd4 --- /dev/null +++ b/docu/RosSystemModelDescription.rst @@ -0,0 +1,56 @@ +HOW TO DESCRIBE ROS SYSTEMS USING THE LANGUAGE +============================================== + +In our case, we consider a system to be a combination of nodes running at the same time. Basically, we use the typical component-based system concept, where each ROS node could be considered a component. Therefore, the `.rossystem` file allows us to describe a series of nodes and the connections that are created between them using topics, services, or actions. It also allows us to assign values to the parameters. + +The structure of the system description is as shown in the following diagram: + +.. image:: images/system_class_diagram.jpg + :alt: System Class Diagram + +The format of a system is as follows: + +.. code-block:: yaml + + my_awesome_system: + fromFile: 'pkg_name/launch/file.launch.py' + subSystems: + another_awesome_system # From another .rossystem file + processes: + process1: + nodes: [ node1 , node2 ] + threads: 2 + nodes: + node1: + from: "my_awesome_pkg.awesome_node_provider" # From .ros2 file + interfaces: + - awesome_pub: pub-> "awesome::awesome_pub" # From .ros2 file + parameters: + - ParamName: "awesome::awesome_param" + value: "Label" + node2: + from: "my_awesome_pkg.awesome_node_consumer" # From .ros2 file + interfaces: + - awesome_sub: sub-> "awesome::awesome_sub" + connections: + - [awesome_pub, awesome_sub] + +Below we analyze each part that makes up the system and how it is formed: + +- **(Optional) Processes**: Describes all system processes. Each process is determined by a name (`process1` in the example), a set of nodes given as a list, and the number of threads. The nodes must be defined within the system nodes. + +- **(Optional) fromFile**: This attribute can be used for those systems that already have a launch file where all the nodes are composed. It expects a string with the name of the package followed by the relative path to the launch file. + +- **(Optional) subSystems**: List of all the systems that compose the new system as subsystems. The name of the system must correspond to the name given to the system in another `.rossystem` file. + +- **Nodes**: Describes all nodes in the system. Nodes are described as a reference to an existing package (and described in a `.ros2` file) and have the following attributes: + - **name**: A name that must be unique in the file (in the example `node1`). + - **from**: Reference to the instantiated node description. It is given by the name of the package that contains it and the name of the original node. + - **interfaces**: List of all the interfaces of the node. Here it is not mandatory to list the interfaces (again) as they are already in the `.ros2` file. Only the renamed interfaces must be added, as well as interfaces that will form a connection with other components. A referenced interface is given by: **NewName: Type -> ref_artifact_name::ref_interface_name** where `ref_artifact_name` and `ref_interface_name` come from the `.ros2` file. The Type can be `pub`, `sub`, `sc`, `ss`, `ac`, or `as`. + - **parameters**: This is used to pass a value to a parameter. Every parameter must have a name (e.g., `my_param`), and the reference to an existing parameter is given by `artifact_name::param_name` from a `.ros2` file. Under `value`, a new value can be assigned to the parameter. + +- **(Optional) Connections**: Describes the connections between the nodes. They are given by `[name_of_the_output, name_of_the_input]`. The outputs and inputs must be previously created, have the same communication pattern (topic, service, or action), and use the same type of communication object (for example, `std_msgs/String`). Otherwise, the validator will raise an error. + +The editor of the models contains validators and an autocomplete function, which can be called with the combination of the keys `Ctrl` and the space bar. + +In the `tutorials `_, you will be guided to try all of these features. diff --git a/docu/RosTooling_issues.md b/docu/RosTooling_issues.md deleted file mode 100644 index c71357f..0000000 --- a/docu/RosTooling_issues.md +++ /dev/null @@ -1,40 +0,0 @@ -# RosTooling Known Issues - -Some of the features of the RosTooling are not yet fully developed or robust enough. - -## System validators - -### Instantiation of interfaces from other nodes - -Right now when you create a system and add a node, the tooling allows you to add ports to that node that are not in its original definition. Any topic of any node in your workspace can be referenced. For example the following example: - -![alt text](images/RosTooling_issues_1.png) - -The test system includes the node camera from the node "usb_cam.usbcam" (right-bottom model), but the reference interface is a scanner output from the node "hls_lfcd_lds_driver.hlds_laser_publisher". This is not giving a compilation error but it is wrong. The user of the RosTooling has to take care of defining the interfaces correctly. - -This issue will be fixed for the next release. - -### Ports with the same name to form connections - -For simplicity, we shorten the reference on the connections to the single name of the interfaces. However, this produces errors at the moment that both interfaces (input and output) have the same name. Like the following example: - -![alt text](images/RosTooling_issues_2.png) - - -The screenshot example is correct but the compiler couldn't distinguish if the input is the scan topic defined as publisher or as subscriber. - -To solve this, the user must change the name of the instance. This can produce a remap of the topics: - -![alt text](images/RosTooling_issues_3.png) - -This issue will be fixed for the next release. - -## Code generators - -The launch file generator is not taking into account: -* Connections related to subsystems, the remap of the topic will not be autogenerated - - -## Issues with components - -- [Objects definition (.ros)](NewCommunicationObjects.md#known-issues) \ No newline at end of file diff --git a/docu/RosTooling_issues.rst b/docu/RosTooling_issues.rst new file mode 100644 index 0000000..bf7c9d9 --- /dev/null +++ b/docu/RosTooling_issues.rst @@ -0,0 +1,67 @@ +RosTooling Known Issues +======================= + +Some of the features of the RosTooling are not yet fully developed or +robust enough. + +System validators +----------------- + +Instantiation of interfaces from other nodes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Right now when you create a system and add a node, the tooling allows +you to add ports to that node that are not in its original definition. +Any topic of any node in your workspace can be referenced. For example +the following example: + +.. figure:: images/RosTooling_issues_1.png + :alt: alt text + + alt text + +The test system includes the node camera from the node “usb_cam.usbcam” +(right-bottom model), but the reference interface is a scanner output +from the node “hls_lfcd_lds_driver.hlds_laser_publisher”. This is not +giving a compilation error but it is wrong. The user of the RosTooling +has to take care of defining the interfaces correctly. + +This issue will be fixed for the next release. + +Ports with the same name to form connections +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For simplicity, we shorten the reference on the connections to the +single name of the interfaces. However, this produces errors at the +moment that both interfaces (input and output) have the same name. Like +the following example: + +.. figure:: images/RosTooling_issues_2.png + :alt: alt text + + alt text + +The screenshot example is correct but the compiler couldn’t distinguish +if the input is the scan topic defined as publisher or as subscriber. + +To solve this, the user must change the name of the instance. This can +produce a remap of the topics: + +.. figure:: images/RosTooling_issues_3.png + :alt: alt text + + alt text + +This issue will be fixed for the next release. + +Code generators +--------------- + +The launch file generator is not taking into account: \* Connections +related to subsystems, the remap of the topic will not be autogenerated + +Issues with components +---------------------- + +- `Objects definition + (.ros) `__ diff --git a/docu/StaticCodeAnalyis.md b/docu/StaticCodeAnalyis.md deleted file mode 100644 index fe355e9..0000000 --- a/docu/StaticCodeAnalyis.md +++ /dev/null @@ -1,82 +0,0 @@ -# Extract models using static code analysis [![](images/docker_logo.png)] - -This tutorial requires the [Docker](https://docs.docker.com/install/linux/docker-ce/ubuntu/) installation. - -As the RosTooling leverages existing ROS code, one of the techniques to create models is to extract them from existing code. For this purpose, we created a plugin based on [HAROS](https://github.com/git-afsantos/haros) that generates automatically ROS models. - -The code of the extractor is publicly available under [ros-model-extractors](https://github.com/ipa320/ros-model-extractors). - -Imagine we want to use the extractors to analyze the following ROS 2 package that contains code for two simple ROS nodes: [cpp_basic_ros2](https://github.com/ipa-nhg/cpp_basic_ros2). - -Following the instructions of the extractor repository, the commands to be run to build the Docker container are: - -``` -git clone https://github.com/ipa320/ros-model-extractors -cd ros-model-extractors -[sudo] docker build --tag=haros_humble -f docker/humble/Dockerfile . -``` - -Once it finishes, we can then call HAROS and the model generator. The command is: - -``` -[sudo] docker run -it haros_humble:latest /haros_runner.sh *package_name* *node_name* *type* *path_to_resulted_model* *workspace_path* "*github_repositoryA -b branch*" "*github_repositoryB*"... -``` - -For the case of the package we want to analyze it will be: -``` -[sudo] docker run -it haros_humble:latest /haros_runner.sh cpp_basic --all node . /home/extractor/ws "https://github.com/ipa-nhg/cpp_basic_ros2" -``` - -The output of this command will be the content for the models corresponding to the artifacts found on the CMakeLists of the ROS2 package, in this case, **basic_pub_node** and **basic_sub_node**. - -``` -## Call the HAROS plugin to extract the ros-models ## -~~~~~~~~~~~ -Extraction finished. See the following report: -INFO: Found artifact: basic_pub_node -INFO: Found artifact: basic_sub_node -~~~~~~~~~~~ -########### -~~~~~~~~~~~ -Print of the model: ./basic_pub_node.ros2: -~~~~~~~~~~~ -cpp_basic: - artifacts: - basic_pub_node: - node: basic_pub_node - publishers: - 'my_awesome_pub': - type: 'std_msgs/msg/String' - -~~~~~~~~~~~ -########### -~~~~~~~~~~~ -Print of the model: ./basic_sub_node.ros2: -~~~~~~~~~~~ -cpp_basic: - artifacts: - basic_sub_node: - node: basic_sub_node - subscribers: - 'my_awesome_sub': - type: 'std_msgs/msg/String' - -~~~~~~~~~~~ -########### -``` - -If you copy the output in a .ros2 file on the RosTooling the models and their attributes will be parsed and interpreted. For simplification, both artifacts can also be merged into a single file. - -![alt text](images/importHAROSOutput.png) - -Another nice example to test is the [aruco_ros](https://github.com/pal-robotics/aruco_ros) package, its corresponding command is: - -``` -[sudo] docker run -it haros_humble:latest /haros_runner.sh aruco_ros --all node . /home/extractor/ws "https://github.com/pal-robotics/aruco_ros" -``` - -![](images/Attention.png) This is a very basic example. The extraction technologies have a huge potential, unfortunately since the ROS 2 Humble distro the extractor works only for simple Cpp code. Unfortunately, some changes on the colcon build infrastructure and how it calls the clang compiler broke our extraction tools. With ROS (1) and previous ROS 2 distros we reached a 70% of efficiency. - -We are looking for help and collaboration to fix the current issues we are facing. If you are interested please contact Nadia (mailto: [nhg@ipa.fhg.de](nhg@ipa.fhg.de)). THANKS!! :) - -Many of the models you will see during the rest of the tutorials were auto-generated using this method. \ No newline at end of file diff --git a/docu/StaticCodeAnalyis.rst b/docu/StaticCodeAnalyis.rst new file mode 100644 index 0000000..fc29471 --- /dev/null +++ b/docu/StaticCodeAnalyis.rst @@ -0,0 +1,115 @@ +Extract models using static code analysis [|image1|] +==================================================== + +This tutorial requires the +`Docker `__ +installation. + +As the RosTooling leverages existing ROS code, one of the techniques to +create models is to extract them from existing code. For this purpose, +we created a plugin based on +`HAROS `__ that generates +automatically ROS models. + +The code of the extractor is publicly available under +`ros-model-extractors `__. + +Imagine we want to use the extractors to analyze the following ROS 2 +package that contains code for two simple ROS nodes: +`cpp_basic_ros2 `__. + +Following the instructions of the extractor repository, the commands to +be run to build the Docker container are: + +:: + + git clone https://github.com/ipa320/ros-model-extractors + cd ros-model-extractors + [sudo] docker build --tag=haros_humble -f docker/humble/Dockerfile . + +Once it finishes, we can then call HAROS and the model generator. The +command is: + +:: + + [sudo] docker run -it haros_humble:latest /haros_runner.sh *package_name* *node_name* *type* *path_to_resulted_model* *workspace_path* "*github_repositoryA -b branch*" "*github_repositoryB*"... + +For the case of the package we want to analyze it will be: + +:: + + [sudo] docker run -it haros_humble:latest /haros_runner.sh cpp_basic --all node . /home/extractor/ws "https://github.com/ipa-nhg/cpp_basic_ros2" + +The output of this command will be the content for the models +corresponding to the artifacts found on the CMakeLists of the ROS2 +package, in this case, **basic_pub_node** and **basic_sub_node**. + +:: + + ## Call the HAROS plugin to extract the ros-models ## + ~~~~~~~~~~~ + Extraction finished. See the following report: + INFO: Found artifact: basic_pub_node + INFO: Found artifact: basic_sub_node + ~~~~~~~~~~~ + ########### + ~~~~~~~~~~~ + Print of the model: ./basic_pub_node.ros2: + ~~~~~~~~~~~ + cpp_basic: + artifacts: + basic_pub_node: + node: basic_pub_node + publishers: + 'my_awesome_pub': + type: 'std_msgs/msg/String' + + ~~~~~~~~~~~ + ########### + ~~~~~~~~~~~ + Print of the model: ./basic_sub_node.ros2: + ~~~~~~~~~~~ + cpp_basic: + artifacts: + basic_sub_node: + node: basic_sub_node + subscribers: + 'my_awesome_sub': + type: 'std_msgs/msg/String' + + ~~~~~~~~~~~ + ########### + +If you copy the output in a .ros2 file on the RosTooling the models and +their attributes will be parsed and interpreted. For simplification, +both artifacts can also be merged into a single file. + +.. figure:: images/importHAROSOutput.png + :alt: alt text + + alt text + +Another nice example to test is the +`aruco_ros `__ package, its +corresponding command is: + +:: + + [sudo] docker run -it haros_humble:latest /haros_runner.sh aruco_ros --all node . /home/extractor/ws "https://github.com/pal-robotics/aruco_ros" + +|image2| This is a very basic example. The extraction technologies have +a huge potential, unfortunately since the ROS 2 Humble distro the +extractor works only for simple Cpp code. Unfortunately, some changes on +the colcon build infrastructure and how it calls the clang compiler +broke our extraction tools. With ROS (1) and previous ROS 2 distros we +reached a 70% of efficiency. + +We are looking for help and collaboration to fix the current issues we +are facing. If you are interested please contact Nadia (mailto: +`nhg@ipa.fhg.de `__). THANKS!! :) + +Many of the models you will see during the rest of the tutorials were +auto-generated using this method. + +.. |image1| image:: images/docker_logo.png +.. |image2| image:: images/Attention.png diff --git a/docu/SystemModelsVisualization.md b/docu/SystemModelsVisualization.md deleted file mode 100644 index 7898a5d..0000000 --- a/docu/SystemModelsVisualization.md +++ /dev/null @@ -1,73 +0,0 @@ -# System visualization -The RosTooling offers two visualization options: -* By the generation of [PlantUML](https://plantuml.com/) diagrams -* By using a [Sirius](https://eclipse.dev/sirius/) implementation as Eclipse plugin. - -## PlantUML compiler - -### Embedded the viewer on the Eclipse environment - -The Eclipse Marketplace includes a PlantUML plugin. To install it go to Eclipse to Help -> Eclipse Marketplace.. and search for "PlantUML". Select the Plugin and let Eclipse install it. - -![alt text](images/PlantUMLInstaller.gif) - -Once the installation is completed, Eclipse must be restarted. - -To open the visualizer in Eclipse you can easily go to "Window"-> "Show view" -> Other and select "PlantUML". - -![alt text](images/PlantUMLView.gif) - - -### Open the PlantUML auto-generated description - -For this example we will use a template model available under the default project "de.fraunhofer.ipa.ros.communication.objects". See instructions under [setup](Environment_setup.md). If the automatic clone doesn't work for you, please clone the repository [RosCommonObjects](https://github.com/ipa320/RosCommonObjects) manually and import it to your Eclipse workspace. - -The example we will show is under "BasicSpecs/Systems/ros_system_template.rossystem". - -By default, the RosTooling will automatically generate a PlantUML file description of every valid RosSystem model. It will be held in the "src-gen" folder of the corresponding ROS package. The folder "resources" contains a file with the .puml extension. By opening it with a text editor and having the PlantUML visualizer open the diagram will appear. - -![alt text](images/PlantUMLViewSystemExample.png) - - -Alternatively, you can copy the content of the generated file to an online PlantUML editor tool like [PlantText](https://www.planttext.com/). - -#### Known Issues -![](images/Attention.png) Unfortunately, PlantUML, specifically the template here generated is not supporting large systems. They show cut. Also sometimes the generated file has issues because of duplicated ports. We are considering the reimplementation of the template. - -## Sirius visualizer - -### Install Sirius on Eclipse - -Sirius can be easily installed using the Eclipse Marketplace. Go in Eclipse to Help -> Eclipse Marketplace.. and search for "Sirius". Select the Plugin and let Eclipse install it. - -![alt text](images/SiriusInstaller.gif) - -Once the installation is completed, Eclipse must be restarted. - -### Create a representation view of your system - -For this example we will use a template model available under the default project "de.fraunhofer.ipa.ros.communication.objects". See instructions under [setup](Environment_setup.md). If the automatic clone doesn't work for you, please clone the repository [RosCommonObjects](https://github.com/ipa320/RosCommonObjects) manually and import it to your Eclipse workspace. - -The example we will show is under "BasicSpecs/Systems/ros_system_template.rossystem". - -A representation file is a file in which Sirius stores all information related to which representations you created, what appears on them, the positions and colors of the elements, etc. These files have a .aird extension (typically representations.aird). Representation files reference the semantic model(s) for which they contain representations, but your semantic models themselves are kept unaware (and unpolluted) of any Sirius-specific data. - -To create this file you can go to File -> New -> Other and then navigate or search for "Representations File". - -We recommend selecting the initialization method "Initialization from a semantic resource" and using the helper to navigate and select the .rossystem file you would like to open, for example "ros_system_template.rossystem". - -![alt text](images/SiriusCreateRepresentationFile.gif) - -While opening the representation file with an "Aird Editor", which should be the default option. - -In the menu Representations (it should be the menu in the middle) choose the "RosSystem" option and press "New.." then choose the RosSystem entity of your "*.rossystem" model and press finish. - -![alt text](images/SiriusOpenSystemView.gif) - -Then you can use the mouse to move labels and components, interfaces or labels to the desired position. - -![alt text](images/SiriusView.png) - -For complex systems, a nice feature of Sirius is the option to hide some elements. For that purpose, you can use the tools panel or make a right click in the Representation view and select "Show/Hide". It also allows to generate a JPG image of the system view. - -![alt text](images/SiriusFeatures.gif) diff --git a/docu/SystemModelsVisualization.rst b/docu/SystemModelsVisualization.rst new file mode 100644 index 0000000..2ca3c61 --- /dev/null +++ b/docu/SystemModelsVisualization.rst @@ -0,0 +1,152 @@ +System visualization +==================== + +The RosTooling offers two visualization options: \* By the generation of +`PlantUML `__ diagrams \* By using a +`Sirius `__ implementation as Eclipse +plugin. + +PlantUML compiler +----------------- + +Embedded the viewer on the Eclipse environment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Eclipse Marketplace includes a PlantUML plugin. To install it go to +Eclipse to Help -> Eclipse Marketplace.. and search for “PlantUML”. +Select the Plugin and let Eclipse install it. + +.. figure:: images/PlantUMLInstaller.gif + :alt: alt text + + alt text + +Once the installation is completed, Eclipse must be restarted. + +To open the visualizer in Eclipse you can easily go to “Window”-> “Show +view” -> Other and select “PlantUML”. + +.. figure:: images/PlantUMLView.gif + :alt: alt text + + alt text + +Open the PlantUML auto-generated description +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For this example we will use a template model available under the +default project “de.fraunhofer.ipa.ros.communication.objects”. See +instructions under `setup `__. If the automatic +clone doesn’t work for you, please clone the repository +`RosCommonObjects `__ +manually and import it to your Eclipse workspace. + +The example we will show is under +“BasicSpecs/Systems/ros_system_template.rossystem”. + +By default, the RosTooling will automatically generate a PlantUML file +description of every valid RosSystem model. It will be held in the +“src-gen” folder of the corresponding ROS package. The folder +“resources” contains a file with the .puml extension. By opening it with +a text editor and having the PlantUML visualizer open the diagram will +appear. + +.. figure:: images/PlantUMLViewSystemExample.png + :alt: alt text + + alt text + +Alternatively, you can copy the content of the generated file to an +online PlantUML editor tool like +`PlantText `__. + +Known Issues +^^^^^^^^^^^^ + +|image1| Unfortunately, PlantUML, specifically the template here +generated is not supporting large systems. They show cut. Also sometimes +the generated file has issues because of duplicated ports. We are +considering the reimplementation of the template. + +Sirius visualizer +----------------- + +Install Sirius on Eclipse +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sirius can be easily installed using the Eclipse Marketplace. Go in +Eclipse to Help -> Eclipse Marketplace.. and search for “Sirius”. Select +the Plugin and let Eclipse install it. + +.. figure:: images/SiriusInstaller.gif + :alt: alt text + + alt text + +Once the installation is completed, Eclipse must be restarted. + +Create a representation view of your system +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For this example we will use a template model available under the +default project “de.fraunhofer.ipa.ros.communication.objects”. See +instructions under `setup `__. If the automatic +clone doesn’t work for you, please clone the repository +`RosCommonObjects `__ +manually and import it to your Eclipse workspace. + +The example we will show is under +“BasicSpecs/Systems/ros_system_template.rossystem”. + +A representation file is a file in which Sirius stores all information +related to which representations you created, what appears on them, the +positions and colors of the elements, etc. These files have a .aird +extension (typically representations.aird). Representation files +reference the semantic model(s) for which they contain representations, +but your semantic models themselves are kept unaware (and unpolluted) of +any Sirius-specific data. + +To create this file you can go to File -> New -> Other and then navigate +or search for “Representations File”. + +We recommend selecting the initialization method “Initialization from a +semantic resource” and using the helper to navigate and select the +.rossystem file you would like to open, for example +“ros_system_template.rossystem”. + +.. figure:: images/SiriusCreateRepresentationFile.gif + :alt: alt text + + alt text + +While opening the representation file with an “Aird Editor”, which +should be the default option. + +In the menu Representations (it should be the menu in the middle) choose +the “RosSystem” option and press “New..” then choose the RosSystem +entity of your “\*.rossystem” model and press finish. + +.. figure:: images/SiriusOpenSystemView.gif + :alt: alt text + + alt text + +Then you can use the mouse to move labels and components, interfaces or +labels to the desired position. + +.. figure:: images/SiriusView.png + :alt: alt text + + alt text + +For complex systems, a nice feature of Sirius is the option to hide some +elements. For that purpose, you can use the tools panel or make a right +click in the Representation view and select “Show/Hide”. It also allows +to generate a JPG image of the system view. + +.. figure:: images/SiriusFeatures.gif + :alt: alt text + + alt text + +.. |image1| image:: images/Attention.png diff --git a/docu/eclipse_issues.md b/docu/eclipse_issues.md deleted file mode 100644 index fba21bd..0000000 --- a/docu/eclipse_issues.md +++ /dev/null @@ -1,9 +0,0 @@ -# Eclipse "issues" - -The current version of the RosTooling is built on top of Eclipse. Some issues related to this IDE can appear during the execution of these tutorials. - -Before you start editing the models you must be sure that Eclipse is building automatically your workspace by every change you make. This means you must have enabled the option "Build automatically" under the menu "Project". - -The most common issue is problems in compiling the models because of not-found references. - -The .ros2 models have dependencies to .ros, and the .rossystem models to both of them and sometimes these references are defined on a different project that must be compiled in the correct order and sometimes the automatic build can't deal with it. For those cases, you can trigger a new build, for the full Workspace or only for the project with errors. This helps in the majority of the cases. This option is available under "Project" -> "Clean..". \ No newline at end of file diff --git a/docu/eclipse_issues.rst b/docu/eclipse_issues.rst new file mode 100644 index 0000000..2163f78 --- /dev/null +++ b/docu/eclipse_issues.rst @@ -0,0 +1,10 @@ +Eclipse "issues" +================= + +The current version of the RosTooling is built on top of Eclipse. Some issues related to this IDE may appear during the execution of these tutorials. + +Before you start editing the models, ensure that Eclipse is automatically building your workspace with every change you make. To do this, you must enable the "Build automatically" option under the "Project" menu. + +The most common issue is problems with compiling the models due to not-found references. + +The `.ros2` models have dependencies on `.ros`, and the `.rossystem` models depend on both of them. Sometimes these references are defined in a different project, which must be compiled in the correct order, and occasionally the automatic build fails to manage this correctly. In such cases, you can trigger a new build for the full workspace or just for the project with errors. This helps in the majority of cases. The option is available under **Project -> Clean...**. diff --git a/docu/ros2model.md b/docu/ros2model.md deleted file mode 100644 index 5fdae22..0000000 --- a/docu/ros2model.md +++ /dev/null @@ -1,56 +0,0 @@ -# Extract component models using introspection at runtime [![](images/Ros2_logo.png)] - -This tutorial requires a local ROS installation. - -For the auto-generation of models another strategy, parallel to [static code analysis techniques](StaticCodeAnalyis.md) is the introspection of a running system. - -The tool [ros2model](https://github.com/ipa320/ros2model) was created for that purpose. It can be installed as every common ROS 2 package by: - -1. clone this repository into the source folder in your workspace, such as: - ``` - ws/src/ros2model - ``` -2. Source ROS workspace - ``` - source /opt/ros/humble/setup.bash - ``` -3. Back to the folder "ws", create and active venv - ``` - python3 -m venv venv --system-site-packages --symlinks - source venv/bin/activate - ``` -4. Install poetry and install dependencies - run - ``` - pip install poetry - poetry install -C src/ros2model/ - ``` -5. compile it as ROS package - ``` - python -m colcon build --packages-select ros2model --symlink-install - ``` - ``` - source install/local_setup.bash - ``` -6. config python path - in this case we are using python3.10 in venv - ``` - export PYTHONPATH=$PYTHONPATH:$(pwd)/venv/lib/python3.10/site-packages/ - ``` - -Then you can start the nodes you want to analyze. For example the common turtlesim tutorial: -``` -ros2 launch turtlesim multisim.launch.py -``` - -And then just call the extractor to generate the models: -``` -ros2 model node -o turtlesim/nodes -``` -This command will create automatically under the selected folder (in this case turtlesim/nodes) the .ros2 files corresponding to all the running nodes. - -You can copy the files to the ROS project in Eclipse to verify the models. - -Please note that some information can be wrong as from the runtime system we can not get the filesystem information like the name of the package and the name of the artifacts. This information must be reviewed by the user. - -Many of the models you will see during the rest of the tutorials were auto-generated using this method. \ No newline at end of file diff --git a/docu/ros2model.rst b/docu/ros2model.rst new file mode 100644 index 0000000..7606230 --- /dev/null +++ b/docu/ros2model.rst @@ -0,0 +1,84 @@ +Extract component models using introspection at runtime [|image1|] +================================================================== + +This tutorial requires a local ROS installation. + +For the auto-generation of models another strategy, parallel to `static +code analysis techniques `__ is the introspection +of a running system. + +The tool `ros2model `__ was created +for that purpose. It can be installed as every common ROS 2 package by: + +1. clone this repository into the source folder in your workspace, such + as: + + :: + + ws/src/ros2model + +2. Source ROS workspace + + :: + + source /opt/ros/humble/setup.bash + +3. Back to the folder “ws”, create and active venv + + :: + + python3 -m venv venv --system-site-packages --symlinks + source venv/bin/activate + +4. Install poetry and install dependencies run + + :: + + pip install poetry + poetry install -C src/ros2model/ + +5. compile it as ROS package + + :: + + python -m colcon build --packages-select ros2model --symlink-install + + :: + + source install/local_setup.bash + +6. config python path in this case we are using python3.10 in venv + + :: + + export PYTHONPATH=$PYTHONPATH:$(pwd)/venv/lib/python3.10/site-packages/ + +Then you can start the nodes you want to analyze. For example the common +turtlesim tutorial: + +:: + + ros2 launch turtlesim multisim.launch.py + +And then just call the extractor to generate the models: + +:: + + ros2 model node -o turtlesim/nodes + +This command will create automatically under the selected folder (in +this case turtlesim/nodes) the .ros2 files corresponding to all the +running nodes. + +You can copy the files to the ROS project in Eclipse to verify the +models. + +Please note that some information can be wrong as from the runtime +system we can not get the filesystem information like the name of the +package and the name of the artifacts. This information must be reviewed +by the user. + +Many of the models you will see during the rest of the tutorials were +auto-generated using this method. + +.. |image1| image:: images/Ros2_logo.png diff --git a/docu/rossdl.md b/docu/rossdl.md deleted file mode 100644 index 0dd2dc0..0000000 --- a/docu/rossdl.md +++ /dev/null @@ -1,218 +0,0 @@ -# Generate code from model description [![](images/Ros2_logo.png)] - -This tutorial requires a local ROS 2 installation and some experience with ROS 2. It is based on the package [rossdl](https://github.com/CoreSenseEU/rossdl). - -## Installation [![](images/Ros2_logo.png)] - -Firstly, you have to create your ROS2 workspace, clone and compile the rossdl package: - -``` -mkdir -p ros2/ws/src -git clone https://github.com/CoreSenseEU/rossdl ros2/ws/src/rossdl -source /opt/ros/humble/setup.bash -cd ros2/ws -rosdep install --from-path src/ -i -y -colcon build -source install/setup.bash -``` - -## Code template [![](images/Ros2_logo.png)] - - -The rossdl repository contains some examples. The use of the rossdl package starts by creating a clean ROS package that contains a ros2 description model. Let's use the basic template available on [GitHub](https://github.com/ipa-nhg/rossdl/tree/BasicExampleNHG/rossdl_tests/basic_template). - -The template is a common ROS package where the CMakeLists includes the generator command to be executed while building the package. - -The line that enables the generator is the following one: - -``` -rossdl_generate_code( - "rosnodes/node.ros2" - ${dependencies} -) -``` - -Where the first argument is the relative path to the .ros2 model file that contains the description of the ROS 2 node. - -Imagine we have the description of an image filter node, which model looks like this: -``` -basic_template: - artifacts: - image_filter: - node: image_filter - publishers: - image_out: - type: "sensor_msgs/msg/Image" - description_out: - type: "std_msgs/msg/String" - subscribers: - image_in: - type: "sensor_msgs/msg/Image" - laser_in: - type: "sensor_msgs/msg/LaserScan" -``` - -Apart from that the user must add the dependencies to the required packages to both files, the package.xml and the CMakeLists. For this concrete case, the only extra dependencies for the node are "std_msgs" and "sensor_msgs". This means the CMakeLists.txt looks like: - -``` -cmake_minimum_required(VERSION 3.8) -project(basic_template) - -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic) -endif() - -# find dependencies -find_package(ament_cmake REQUIRED) -find_package(rossdl_cmake REQUIRED) -find_package(rclcpp REQUIRED) -find_package(rclcpp_components REQUIRED) -find_package(backward_ros REQUIRED) -# Add here further dependencies -find_package(std_msgs REQUIRED) -find_package(sensor_msgs REQUIRED) - -set(dependencies - rclcpp - rclcpp_components - backward_ros - # Add here further dependencies - std_msgs - sensor_msgs -) - -rossdl_generate_code( - "rosnodes/node.ros2" - ${dependencies} -) - -ament_package() -``` - -While the package.xml contains the following text: -``` - - - - basic_template - 0.0.0 - This is a basic template for rossdl - fmrico - nhg - Apache 2.0 - - ament_cmake - - rclcpp - rclcpp_components - rossdl_cmake - backward_ros - - std_msgs - sensor_msgs - - ament_lint_auto - ament_lint_common - - - ament_cmake - - -``` - -By having this package structure and the ros2 file completed, you can easily compile the package with the common colcon command: -``` -colcon build --symlink-install --packages-select rossdl_cmake basic_template -``` - -As result, automatically, in the build folder of your workspace, it will appear the code corresponding headers for the new node. In this case in **build/basic_template/include/basic_template**. For this basic example, the code will contain: - -``` -// generated from rossdl_cmake/resource/nodes.hpp.em -// generated code does not contain a copyright notice - -#ifndef BASIC_TEMPLATE__NODES_HPP_ -#define BASIC_TEMPLATE__NODES_HPP_ - -#include -#include -#include - -#include "sensor_msgs/msg/laser_scan.hpp" -#include "std_msgs/msg/string.hpp" -#include "sensor_msgs/msg/image.hpp" - -#include "rclcpp/rclcpp.hpp" - -namespace basic_template -{ - -class ImageFilterBase : public rclcpp::Node -{ -public: - explicit ImageFilterBase(const rclcpp::NodeOptions & options); - -protected: - rclcpp::Publisher::SharedPtr image_out_; - rclcpp::Publisher::SharedPtr description_out_; - rclcpp::Subscription::SharedPtr image_in_; - rclcpp::Subscription::SharedPtr laser_in_; - - virtual void image_in_callback(sensor_msgs::msg::Image::SharedPtr msg) = 0; - virtual void laser_in_callback(sensor_msgs::msg::LaserScan::SharedPtr msg) = 0; - - template - typename rclcpp::Publisher::SharedPtr - get_publisher(const std::string & id) - { - auto ret_pub = std::dynamic_pointer_cast>( - get_publisher_base(id)); - return ret_pub; - } - - template - typename rclcpp::Subscription::SharedPtr - get_subscription(const std::string & id) - { - auto ret_sub = std::dynamic_pointer_cast>( - get_subscription_base(id)); - return ret_sub; - } - - typename rclcpp::PublisherBase::SharedPtr - get_publisher_base(const std::string & id) - { - if (id == "image_out") { - return image_out_; - } - if (id == "description_out") { - return description_out_; - } - RCLCPP_ERROR(get_logger(), "Publisher [%s] not found", id.c_str()); - return nullptr; - } - - typename rclcpp::SubscriptionBase::SharedPtr - get_subscription_base(const std::string & id) - { - if (id == "image_in") { - return image_in_; - } - if (id == "laser_in") { - return laser_in_; - } - RCLCPP_ERROR(get_logger(), "Subscriber [%s] not found", id.c_str()); - return nullptr; - } -}; - - -} // namespace basic_template - -#endif // BASIC_TEMPLATE__NODES_HPP_ - -``` - -This is a base class that can be used as interface to create your node under "ros2/ws/src/rossdl/basic_template/src". This method apart from saving effort by auto-generating code, drives the developer to create a code that corresponds to the model representation. - -An implementation of a Cpp package using this class is publicly available under [rossdl_tests/rossdl_simple_test/src/rossdl_simple_test/ImageFilter.cpp](https://github.com/CoreSenseEU/rossdl/blob/main/rossdl_tests/rossdl_simple_test/src/rossdl_simple_test/ImageFilter.cpp#L26). \ No newline at end of file diff --git a/docu/rossdl.rst b/docu/rossdl.rst new file mode 100644 index 0000000..8d0b2ab --- /dev/null +++ b/docu/rossdl.rst @@ -0,0 +1,247 @@ +Generate code from model description [|image1|] +=============================================== + +This tutorial requires a local ROS 2 installation and some experience +with ROS 2. It is based on the package +`rossdl `__. + +Installation [|image2|] +----------------------- + +Firstly, you have to create your ROS2 workspace, clone and compile the +rossdl package: + +:: + + mkdir -p ros2/ws/src + git clone https://github.com/CoreSenseEU/rossdl ros2/ws/src/rossdl + source /opt/ros/humble/setup.bash + cd ros2/ws + rosdep install --from-path src/ -i -y + colcon build + source install/setup.bash + +Code template [|image3|] +------------------------ + +The rossdl repository contains some examples. The use of the rossdl +package starts by creating a clean ROS package that contains a ros2 +description model. Let’s use the basic template available on +`GitHub `__. + +The template is a common ROS package where the CMakeLists includes the +generator command to be executed while building the package. + +The line that enables the generator is the following one: + +:: + + rossdl_generate_code( + "rosnodes/node.ros2" + ${dependencies} + ) + +Where the first argument is the relative path to the .ros2 model file +that contains the description of the ROS 2 node. + +Imagine we have the description of an image filter node, which model +looks like this: + +:: + + basic_template: + artifacts: + image_filter: + node: image_filter + publishers: + image_out: + type: "sensor_msgs/msg/Image" + description_out: + type: "std_msgs/msg/String" + subscribers: + image_in: + type: "sensor_msgs/msg/Image" + laser_in: + type: "sensor_msgs/msg/LaserScan" + +Apart from that the user must add the dependencies to the required +packages to both files, the package.xml and the CMakeLists. For this +concrete case, the only extra dependencies for the node are “std_msgs” +and “sensor_msgs”. This means the CMakeLists.txt looks like: + +:: + + cmake_minimum_required(VERSION 3.8) + project(basic_template) + + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + + # find dependencies + find_package(ament_cmake REQUIRED) + find_package(rossdl_cmake REQUIRED) + find_package(rclcpp REQUIRED) + find_package(rclcpp_components REQUIRED) + find_package(backward_ros REQUIRED) + # Add here further dependencies + find_package(std_msgs REQUIRED) + find_package(sensor_msgs REQUIRED) + + set(dependencies + rclcpp + rclcpp_components + backward_ros + # Add here further dependencies + std_msgs + sensor_msgs + ) + + rossdl_generate_code( + "rosnodes/node.ros2" + ${dependencies} + ) + + ament_package() + +While the package.xml contains the following text: + +:: + + + + + basic_template + 0.0.0 + This is a basic template for rossdl + fmrico + nhg + Apache 2.0 + + ament_cmake + + rclcpp + rclcpp_components + rossdl_cmake + backward_ros + + std_msgs + sensor_msgs + + ament_lint_auto + ament_lint_common + + + ament_cmake + + + +By having this package structure and the ros2 file completed, you can +easily compile the package with the common colcon command: + +:: + + colcon build --symlink-install --packages-select rossdl_cmake basic_template + +As result, automatically, in the build folder of your workspace, it will +appear the code corresponding headers for the new node. In this case in +**build/basic_template/include/basic_template**. For this basic example, +the code will contain: + +:: + + // generated from rossdl_cmake/resource/nodes.hpp.em + // generated code does not contain a copyright notice + + #ifndef BASIC_TEMPLATE__NODES_HPP_ + #define BASIC_TEMPLATE__NODES_HPP_ + + #include + #include + #include + + #include "sensor_msgs/msg/laser_scan.hpp" + #include "std_msgs/msg/string.hpp" + #include "sensor_msgs/msg/image.hpp" + + #include "rclcpp/rclcpp.hpp" + + namespace basic_template + { + + class ImageFilterBase : public rclcpp::Node + { + public: + explicit ImageFilterBase(const rclcpp::NodeOptions & options); + + protected: + rclcpp::Publisher::SharedPtr image_out_; + rclcpp::Publisher::SharedPtr description_out_; + rclcpp::Subscription::SharedPtr image_in_; + rclcpp::Subscription::SharedPtr laser_in_; + + virtual void image_in_callback(sensor_msgs::msg::Image::SharedPtr msg) = 0; + virtual void laser_in_callback(sensor_msgs::msg::LaserScan::SharedPtr msg) = 0; + + template + typename rclcpp::Publisher::SharedPtr + get_publisher(const std::string & id) + { + auto ret_pub = std::dynamic_pointer_cast>( + get_publisher_base(id)); + return ret_pub; + } + + template + typename rclcpp::Subscription::SharedPtr + get_subscription(const std::string & id) + { + auto ret_sub = std::dynamic_pointer_cast>( + get_subscription_base(id)); + return ret_sub; + } + + typename rclcpp::PublisherBase::SharedPtr + get_publisher_base(const std::string & id) + { + if (id == "image_out") { + return image_out_; + } + if (id == "description_out") { + return description_out_; + } + RCLCPP_ERROR(get_logger(), "Publisher [%s] not found", id.c_str()); + return nullptr; + } + + typename rclcpp::SubscriptionBase::SharedPtr + get_subscription_base(const std::string & id) + { + if (id == "image_in") { + return image_in_; + } + if (id == "laser_in") { + return laser_in_; + } + RCLCPP_ERROR(get_logger(), "Subscriber [%s] not found", id.c_str()); + return nullptr; + } + }; + + + } // namespace basic_template + + #endif // BASIC_TEMPLATE__NODES_HPP_ + +This is a base class that can be used as interface to create your node +under “ros2/ws/src/rossdl/basic_template/src”. This method apart from +saving effort by auto-generating code, drives the developer to create a +code that corresponds to the model representation. + +An implementation of a Cpp package using this class is publicly +available under +`rossdl_tests/rossdl_simple_test/src/rossdl_simple_test/ImageFilter.cpp `__. + +.. |image1| image:: images/Ros2_logo.png +.. |image2| image:: images/Ros2_logo.png +.. |image3| image:: images/Ros2_logo.png