Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Papyrus/customizations/robotics/ros2"

(ROS2)
(4 intermediate revisions by the same user not shown)
Line 4: Line 4:
  
 
The work on Papyrus for Robotics in general is supported by the RobMoSys project. The ROS2 support is supported by the project ROSIN FTP (focused-technical project) [https://rosin-project.eu/ftp/ros-mdd ROS MDD]
 
The work on Papyrus for Robotics in general is supported by the RobMoSys project. The ROS2 support is supported by the project ROSIN FTP (focused-technical project) [https://rosin-project.eu/ftp/ros-mdd ROS MDD]
 +
 +
[[Image:Papyrus-customizations-robotics-rosin_ack_logo_wide.png|220px]]
 +
 +
Supported by ROSIN - ROS-Industrial Quality-Assured Robot Software Components.
 +
More information: [https://rosin-project.eu rosin-project.eu]
 +
 +
[[Image:Papyrus-customizations-robotics-rosin_eu_flag.jpg|87px]]
 +
This project has received funding from the European Union’s Horizon 2020
 +
research and innovation programme under grant agreement No. 732287.
  
 
== Mapping RobMoSys concepts to ROS2 ==
 
== Mapping RobMoSys concepts to ROS2 ==
Line 27: Line 36:
 
==== SEND pattern ====
 
==== SEND pattern ====
  
The SEND pattern in RobMoSys is an asynchronous service request without expecting a response. While it seems conceptually close to service requests, it cannot be mapped to ROS2 services that always require a response (while either request or response may be empty, a server always has to send a response, even if empty).
+
The SEND pattern in RobMoSys is an asynchronous service request without expecting a response. One or more (n) clients can send a communication object to a server. This is mapped to ROS2 publish/subscribe with messages, as these support n:m relation between publishers and subscribers.
  
 
<center>
 
<center>
Line 36: Line 45:
 
==== PUSH pattern ====
 
==== PUSH pattern ====
  
The PUSH pattern in RobMoSys is an asynchronous message publication with one publisher and n subscribers. This is directly mapped to ROS2 publish/subscribe with messages. A publisher can directly push messages without queuing to subscribed consumers.
+
The PUSH pattern in RobMoSys is an asynchronous message publication with one publisher and n subscribers. This is directly mapped to ROS2 publish/subscribe with messages. A publisher can directly push messages without queuing to subscribed consumers. Compared to the Send pattern, the role of client and servers are inverted: The Publisher is the server (port providing a service), the subscriber is a client (port requiring a service).  
  
 
<center>
 
<center>
Line 49: Line 58:
 
== Component lifecycle ==
 
== Component lifecycle ==
  
As RobMoSys component have a lifecycle (see [https://robmosys.eu/wiki/composition:component-activities:start RobMoSys wiki], a RobMoSys component is mapped to a ROS2 lifecycle node. By default, a component cycles from an initial state to a configured and then to an activate state. Periodic tasks are started when the component enters the activate state.
+
As RobMoSys component have a lifecycle (see [https://robmosys.eu/wiki/composition:component-activities:start RobMoSys wiki], a RobMoSys component is mapped to a ROS2 lifecycle node. By default, a component cycles from an initial state to a configured and then to an activate state. Periodic tasks are started when the component enters the "active" state.
  
 
== ROS2 code generation ==
 
== ROS2 code generation ==
Line 126: Line 135:
 
     ... idem for Dummy_laser, Dummy_map_server, Robot_state_publisher and rviz
 
     ... idem for Dummy_laser, Dummy_map_server, Robot_state_publisher and rviz
  
The following text-box outlines the structure of the generated artefacts for a component definition:
+
The following text-box outlines the structure of the generated artefacts for a component definition. The folder contains a launch.py file that starts all component-instances of a system, as well as an additional file for each instance that starts only the specific instance. In addition, there is an activate.py file that launches the component(s) and in the sequel configures and activates them.
  
 
   folder (this corresponds RobMoSys system-component-architecture)
 
   folder (this corresponds RobMoSys system-component-architecture)
 
     launch.py
 
     launch.py
 +
    activate.py
 +
    for each instance: launch.<instance-name>.py
 +
    for each instance: activate.<instance-name>.py
 
     cfg - subfolder for parameters
 
     cfg - subfolder for parameters
 
       params.yaml - generated parameter file containing the (non-default) parameter values defined at system-level
 
       params.yaml - generated parameter file containing the (non-default) parameter values defined at system-level
Line 137: Line 149:
 
The following page describes shipped test models, in particular how to generate code, compile and run these models: [[Papyrus/customizations/robotics/ros2examples|ROS2 test models for code generation]]
 
The following page describes shipped test models, in particular how to generate code, compile and run these models: [[Papyrus/customizations/robotics/ros2examples|ROS2 test models for code generation]]
  
== ROS2 reverse ==
+
== Reverse engineering ==
  
In order to start creating ROS2 compatible components with Papyrus for Robotics, it is important to enable referencing standard ROS2 messages. These have been made available in a model library in form of RobMoSys compliant communication objects and service definitions. This library has been obtained by a reverse functionality within Papyrus for robotics that scans the available list of ros messages and services. If the message is not already existing, it will be created.
+
see [[Papyrus/customizations/robotics/reverse|ROS2 reverse]]
 
+
It is also possible to create a set of component definitions from the currently running ROS nodes. This reverse mechanism is currently limited to the structural part of a component, i.e. its ports along with the provided or required service definitions.
+
 
+
The following screenshots shows the context menus for starting reverse engineering.
+
 
+
<center>
+
[[Image:Papyrus-customizations-robotics-menu-reverse.png]]<br/>
+
Context menu for generating code
+
</center>
+

Revision as of 05:52, 28 April 2020

ROS2

Acknowledgements

The work on Papyrus for Robotics in general is supported by the RobMoSys project. The ROS2 support is supported by the project ROSIN FTP (focused-technical project) ROS MDD

Papyrus-customizations-robotics-rosin ack logo wide.png

Supported by ROSIN - ROS-Industrial Quality-Assured Robot Software Components. More information: rosin-project.eu

Papyrus-customizations-robotics-rosin eu flag.jpg This project has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement No. 732287.

Mapping RobMoSys concepts to ROS2

Communication patterns

One of the primary issues in mapping RobMoSys concepts to ROS2 is how to map RobMoSys interaction patterns to ROS2 . In the sequel, we outline this for each [communication pattern] in RobMoSys.

QUERY pattern

The QUERY pattern is a classical client/server pattern with one server and n clients. The clients execute a request and expect a response. There are two ways, how a client can handle responses: either with a blocking wait or by receiving a callback with the response (this option primarily affects the activity definition within a component). Both options are supported by ROS2 services. On the server side, a service request is executed within a handler. In case of ROS2, requests are always executed by a ROS2 multi-threaded executor that calls the request handler.

Papyrus-customizations-robotics-commpatternQueryAsync.png
Asynchronous variant of the query pattern

Papyrus-customizations-robotics-commpatternQuerySync.png
Synchronous variant of the query pattern

SEND pattern

The SEND pattern in RobMoSys is an asynchronous service request without expecting a response. One or more (n) clients can send a communication object to a server. This is mapped to ROS2 publish/subscribe with messages, as these support n:m relation between publishers and subscribers.

Papyrus-customizations-robotics-commpatternSend.png
Asynchronous variant of the query pattern

PUSH pattern

The PUSH pattern in RobMoSys is an asynchronous message publication with one publisher and n subscribers. This is directly mapped to ROS2 publish/subscribe with messages. A publisher can directly push messages without queuing to subscribed consumers. Compared to the Send pattern, the role of client and servers are inverted: The Publisher is the server (port providing a service), the subscriber is a client (port requiring a service).

Papyrus-customizations-robotics-commpatternPush.png
Asynchronous variant of the query pattern

EVENT pattern

The EVENT patterns enables asynchronous, filtered event handling. It is currently not supported by the ROS2 mapping.

Component lifecycle

As RobMoSys component have a lifecycle (see RobMoSys wiki, a RobMoSys component is mapped to a ROS2 lifecycle node. By default, a component cycles from an initial state to a configured and then to an activate state. Periodic tasks are started when the component enters the "active" state.

ROS2 code generation

Message package generation

A RobMoSys ServiceDefinition model is mapped a set of ROS2 packages containing messages and services. As for the other code generation artifacts, a message package will be generated in its own Eclipse CDT project. This CDT project is configured to use colcon as build command, options can be configured in the preferences (type "ROS2" in the filter to see the associated preference page).

It is only necessary to create a new ROS2 message/service package, if that does not already exist. Service generation is not invoked directly from a service definition model, but will be invoked automatically during component generation, if that component references non standard messages or services. The generator uses a preference dialog below (see below) in order to detemine what a standard message is.

Papyrus-customizations-robotics-ros2prefs.png
ROS2 preference dialog

The following text-box outlines the structure of the generated artefacts for a message package:

 folder (corresponds to a message package, i.e. a sub-packages within a RobMoSys service definition module)
   CMakeLists.txt - Makefile
   package.xml - Meta-data/build info
   msg - folder with message definitions
   srv - folder with service definitions

Component code generation

Papyrus for robotics supports the generation of (C++) code for ROS2. The code generation can be triggered via the "Robotics" context menu when a component definition or a system (component assembly) is selected.

Let's look at an example, the dummy_joint_states component that is part of the standard ROS2 demos. The following figure shows the RobMoSys view of this component. As the source code creates a publisher with the topic "joint_states" and the message type "JointState", the RobMoSys model of this components contains a provided PUSH port with the respective name and type.

Papyrus-customizations-robotics-dummy joint states.compdef.png
dummy_joint_states component, modeled with Papyrus for Robotics

The original source code performs an initialization of a message and then enters a loop. In this loop, it modifies an entry of the message and performs a wait. The mapping to RobMoSys implies splitting this code into two parts, the initialization of the message and the periodic publication of the modified message. The result is an Activity with two functions that take over the respective part. The period length is modeled via a periodic timer.

Compared to the monolithic source code that contained the creation of a publisher port, the initialization of a message and then a periodic loop with a hard-coded period, the corresponding model separates these aspects into a modeled port and two reusable (composable) functions.

If a component is selected, a ROS2 package can be generated for this component, as shown in the following dialog.

Papyrus-customizations-robotics-menu-gencode.png
Context menu for generating code

Currently, each RobMoSys component is mapped to a dedicated ROS2 package containing the code for a node. The generated package contains generated build files (package.xml and CMakeLists.txt), as well as a src-gen folder with the C++ code that instantiates a ROS2 node when executed. On the RobMoSys level, the behavior of a component is described by activities which in turn are broken down into functions. The code of these functions can be embedded into the model and will be copied into the generated code.

The ROS2 demos contain examples that establish the connection between two nodes by using the same topic name. While this is fine for an example, a component must not "know" to which component it will be connected in a system. This assures its re-usability on source and binary level. The code generator uses the port names as topics. Topic re-mapping (see below) enables the connection on the system level.

The following text-box outlines the structure of the generated artefacts for a component definition:

 folder (corresponds to RobMoSys component-definition-module)
   src-gen - generated source and include files
   CMakeLists.txt - Makefile
   package.xml - Meta-data/build info

System code generation

If a system is selected, code is generated for all components within the system. In addition, a python launch script that brings-up the robotic system is generated. It references a yaml file that contains port/topic remappings and references a yaml file taking into account parameter values that override the default ones for the component. The topic remappings establish the connection between the component instances (see topics above).

Papyrus-customizations-robotics-dummy robot.system.png
dummy_robot system, modeled with Papyrus for Robotics

The script below shows the generated launch file for the dummy_robot system

 def generate_launch_description():
   ld = launch.LaunchDescription()
   ld.add_entity(LifecycleNode(
     node_name='ComponentInstance1',
     package='dummy_joint_statescompdef', node_executable='Dummy_joint_states',
     remappings=[
       ('joint_states', 'ComponentInstance1/JointState/joint_states')
     ],
     parameters=['cfg/param.yaml']
   ))
   ... idem for Dummy_laser, Dummy_map_server, Robot_state_publisher and rviz

The following text-box outlines the structure of the generated artefacts for a component definition. The folder contains a launch.py file that starts all component-instances of a system, as well as an additional file for each instance that starts only the specific instance. In addition, there is an activate.py file that launches the component(s) and in the sequel configures and activates them.

 folder (this corresponds RobMoSys system-component-architecture)
   launch.py
   activate.py
   for each instance: launch.<instance-name>.py
   for each instance: activate.<instance-name>.py
   cfg - subfolder for parameters
      params.yaml - generated parameter file containing the (non-default) parameter values defined at system-level

ROS2 test models

The following page describes shipped test models, in particular how to generate code, compile and run these models: ROS2 test models for code generation

Reverse engineering

see ROS2 reverse

Back to the top