Skip to content

Commit ec5c590

Browse files
gramssFlorian Gramßasyncapi-botfmvilasderberg
authored
feat: initial ROS2 AsyncAPI contribution by SIEMENS AG (#270)
Co-authored-by: Florian Gramß <florian@gramss.de> Co-authored-by: Chan <bot+chan@asyncapi.io> Co-authored-by: Florian Gramß <6034322+gramss@users.noreply.github.com> Co-authored-by: Fran Méndez <fmvilas@gmail.com> Co-authored-by: Lukasz Gornicki <lpgornicki@gmail.com>
1 parent 5d4209d commit ec5c590

File tree

3 files changed

+332
-0
lines changed

3 files changed

+332
-0
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@
1717
/pulsar/ @VisualBean
1818
/sns/ @dpwdec @iancooper
1919
/sqs/ @dpwdec @iancooper
20+
/ros2/ @amparosancho @gramss

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This repository contains the specifications for each AsyncAPI protocol binding.
1616
* [NATS binding](./nats)
1717
* [Pulsar](./pulsar)
1818
* [Redis binding](./redis)
19+
* [ROS 2](./ros2)
1920
* [SNS binding](./sns)
2021
* [Solace binding](./solace)
2122
* [SQS binding](./sqs)

ros2/README.md

Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
# ROS 2 Bindings
2+
3+
This document defines how to describe ROS 2-specific information in AsyncAPI.
4+
5+
It applies to all [distributions of ROS 2](https://docs.ros.org/en/rolling/Releases.html).
6+
7+
<a name="version"></a>
8+
9+
## Version
10+
11+
Current version is `0.1.0`.
12+
13+
<a name="server"></a>
14+
15+
## Server Binding Object
16+
17+
This object contains information about the server representation in ROS 2.
18+
ROS 2 can use a vast variety of [middleware implementations](https://docs.ros.org/en/rolling/Installation/RMW-Implementations.html). This document focuses on DDS and Zenoh middleware implementations.
19+
DDS-based ROS 2 implementations are per default decentralized with no central server, so the field `host` can be set to `none`.
20+
For more information on DDS tuning, you can visit the [DDS Tuning Guide](https://docs.ros.org/en/rolling/How-To-Guides/DDS-tuning.html).
21+
When using Zenoh, the `host` field specifies the Zenoh Router IP address.
22+
23+
###### Fixed Fields
24+
25+
Field Name | Type | Description
26+
---|:---:|---|
27+
`rmwImplementation` | string | Specifies the ROS 2 middleware implementation to be used. Valid values include the different [ROS 2 middleware vendors (RMW)](https://docs.ros.org/en/rolling/Concepts/Intermediate/About-Different-Middleware-Vendors.html) like `rmw_fastrtps_cpp` (Fast DDS) or `rmw_zenoh_cpp` (Zenoh). This determines the underlying middleware implementation that handles communication.
28+
`domainId` | integer | All ROS 2 nodes use domain ID 0 by default. To prevent interference between different groups of computers running ROS 2 on the same network, a group can be set with a unique domain ID. [Must be a non-negative integer less than 232](https://docs.ros.org/en/rolling/Concepts/Intermediate/About-Domain-ID.html).
29+
30+
### Examples
31+
32+
```yaml
33+
servers:
34+
ros2:
35+
host: none
36+
protocol: ros2
37+
protocolVersion: humble
38+
bindings:
39+
ros2:
40+
rmwImplementation: rmw_fastrtps_cpp
41+
domainId: 0
42+
```
43+
44+
45+
<a name="channel"></a>
46+
47+
## Channel Binding Object
48+
49+
This object MUST NOT contain any properties. Its name is reserved for future use.
50+
51+
<a name="operation"></a>
52+
53+
## Operation Binding Object
54+
55+
This object contains information about the ROS 2 node.
56+
57+
###### Fixed Fields
58+
59+
Field Name | Type | Description
60+
---|:---:|---|
61+
`role` | string | Specifies the ROS 2 type of the node for this operation. If the action is `send`, valid values for the role are: `publisher`, `action_client`, `service_client`. If the action is `receive`, valid values for the role are: `subscriber`, `action_server`, `service_server`. This defines how the node will interact with the associated topic, service or action.
62+
`node` | string | The name of the ROS 2 node that implements this operation.
63+
`qosPolicies` | [Quality of Service Policy Object](#QoSPolicyObject) | Quality of Service (QoS) for the topic.
64+
65+
<a name="QoSPolicyObject"></a>
66+
67+
### Quality of Service Object
68+
This object contains ROS 2 specific information about the Quality of Service policies.
69+
More information here: https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies
70+
71+
Field Name | Type | Description
72+
---|:---:|---|
73+
`reliability` | string | One of `best_effort` or `reliable`. More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies)
74+
`history` | string | One of `keep_last`, `keep_all` or `unknown`. More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies)
75+
`durability` | string | One of `transient_local` or `volatile`. More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies)
76+
`lifespan` | integer | The maximum amount of time between the publishing and the reception of a message without the message being considered stale or expired. `-1` means infinite.
77+
`deadline` | integer | The expected maximum amount of time between subsequent messages being published to a topic. `-1` means infinite.
78+
`liveliness` | string | One of `automatic` or `manual`. More information here: [ROS 2 QoS](https://docs.ros.org/en/jazzy/Concepts/Intermediate/About-Quality-of-Service-Settings.html#qos-policies)
79+
`leaseDuration` | integer | The maximum period of time a publisher has to indicate that it is alive before the system considers it to have lost liveliness. `-1` means infinite.
80+
81+
### Examples
82+
83+
ROS 2 subscriber example:
84+
85+
```yaml
86+
receiveCmdVel:
87+
action: receive
88+
channel:
89+
$ref: "#/channels/CmdVel"
90+
bindings:
91+
ros2:
92+
role: subscriber
93+
node: /turtlesim
94+
qosPolicies:
95+
history: unknown
96+
reliability: reliable
97+
durability: volatile
98+
lifespan: -1
99+
deadline: -1
100+
liveliness: automatic
101+
leaseDuration: -1
102+
```
103+
104+
ROS 2 publisher example:
105+
```yaml
106+
Pose:
107+
action: receive
108+
channel:
109+
$ref: "#/channels/Pose"
110+
bindings:
111+
ros2:
112+
role: publisher
113+
node: /turtlesim
114+
```
115+
116+
ROS 2 service server example:
117+
```yaml
118+
SetPen:
119+
action: receive
120+
channel:
121+
$ref: "#/channels/SetPenRequest"
122+
reply:
123+
channel:
124+
$ref: "#/channels/SetPenReply"
125+
bindings:
126+
ros2:
127+
role: service_server
128+
node: /turtlesim
129+
```
130+
131+
ROS 2 service client example:
132+
```yaml
133+
SetPen:
134+
action: send
135+
channel:
136+
$ref: "#/channels/SetPenRequest"
137+
reply:
138+
channel:
139+
$ref: "#/channels/SetPenReply"
140+
bindings:
141+
ros2:
142+
role: service_client
143+
node: /node_client
144+
```
145+
146+
ROS 2 action server example:
147+
```yaml
148+
receiveRotateAbsolute:
149+
action: receive
150+
channel:
151+
$ref: "#/channels/RotateAbsoluteRequest"
152+
reply:
153+
channel:
154+
$ref: "#/channels/RotateAbsoluteReply"
155+
bindings:
156+
ros2:
157+
role: action_server
158+
node: /turtlesim
159+
```
160+
161+
ROS 2 action client example:
162+
```yaml
163+
RotateAbsolute:
164+
action: send
165+
channel:
166+
$ref: "#/channels/RotateAbsoluteRequest"
167+
reply:
168+
channel:
169+
$ref: "#/channels/RotateAbsoluteReply"
170+
bindings:
171+
ros2:
172+
role: action_client
173+
node: /teleop_turtle
174+
```
175+
176+
<a name="message"></a>
177+
178+
## Message Binding Object
179+
180+
While this object DOES NOT contain any ROS 2 specific properties, it is important to understand how to express the different [ROS 2 data types](https://design.ros2.org/articles/legacy_interface_definition.html#:~:text=to%20IDL%20types-,ROS%20type,string,-The%20mapping%20of) in [AsyncAPI message types and formats](https://www.asyncapi.com/docs/reference/specification/v3.0.0#dataTypeFormat:~:text=The%20formats%20defined%20by%20the%20AsyncAPI%20Specification%20are%3A).
181+
182+
ROS 2 Type | AsyncAPI Type | AsyncAPI Format |
183+
---|:---:|---|
184+
bool | boolean | boolean
185+
byte | string | octet
186+
char | integer | uint8
187+
float32 | number | float
188+
float64 | number | double
189+
int8 | integer | int8
190+
uint8 | integer | uint8
191+
int16 | integer | int16
192+
uint16 | integer | uint16
193+
int32 | integer | int32
194+
uint32 | integer | uint32
195+
int64 | integer | int64
196+
uint64 | integer | uint64
197+
string | string | string
198+
array | array | --
199+
200+
It is important to understand that the message header of the AsyncAPI specification does not map with the message header in ROS 2.
201+
For this reason, the AsyncAPI message header will be ignored. If you want to define the header of a message in ROS 2, you should put in the payload of the message. [Example](https://docs.ros.org/en/ros2_packages/rolling/api/point_cloud_interfaces/msg/CompressedPointCloud2.html):
202+
203+
```yaml
204+
channels:
205+
PointCloud:
206+
address: /pointCloud
207+
messages:
208+
CompressedPointCloud2:
209+
$ref: "#/components/messages/CompressedPointCloud2"
210+
components:
211+
CompressedPointCloud2:
212+
tags:
213+
- name: msg
214+
payload:
215+
type: object
216+
properties:
217+
header:
218+
$ref: "#/components/messages/std_msgs/header/payload"
219+
height:
220+
$ref: "#/components/messages/uint32/payload"
221+
width:
222+
$ref: "#/components/messages/uint32/payload"
223+
fields:
224+
$ref: "#/components/messages/sensor_msgs/PointField/payload"
225+
is_bigendian:
226+
$ref: "#/components/messages/bool/payload"
227+
point_step:
228+
$ref: "#/components/messages/uint32/payload"
229+
row_step:
230+
$ref: "#/components/messages/uint32/payload"
231+
compressed_data:
232+
$ref: "#/components/messages/uint8/payload"
233+
is_dense:
234+
$ref: "#/components/messages/bool/payload"
235+
format:
236+
$ref: "#/components/messages/string/payload"
237+
```
238+
239+
## Complete example:
240+
From the AsyncAPI specification example it could be extracted that:
241+
- It consist on a ROS 2 Jazzy application running with Fast DDS as RMW.
242+
- `/turtlesim` node is a subscriber of the `/turtle1/cmd_vel` topic and its qos policies.
243+
- The interface of the `/turtle1/cmd_vel` topic is `Twist` that has a nested type: `Vector3`. Both of them are part of the standard package `geometry_msgs`.
244+
- `Vector3` has already the types converted to AsyncAPI types and formats (number and double), instead of using the ROS 2 types.
245+
- There is one file (head-asyncapi.yaml) that references the different standard/custom packages. This packages contains the strucute of its messages.
246+
247+
```
248+
├── interfaces
249+
│ ├── geometry_msgs.yaml
250+
│ ├── std_msgs.yaml
251+
│ ├── <custom_pkg_msgs>.yaml
252+
│ └── ....
253+
└── head-asyncapi.yaml
254+
```
255+
256+
head-asyncapi.yaml
257+
258+
```yaml
259+
asyncapi: 3.0.0
260+
info:
261+
title: Turtlesim example for ROS 2
262+
version: 1.0.0
263+
264+
servers:
265+
ros2:
266+
host: none
267+
protocol: ros2
268+
protocolVersion: jazzy
269+
bindings:
270+
ros2:
271+
rmwImplementation: rmw_fastrtps_cpp
272+
domainId: 0
273+
274+
channels:
275+
CmdVel:
276+
address: /turtle1/cmd_vel
277+
messages:
278+
Twist:
279+
$ref: ./interfaces/geometry_msgs.yaml#/components/messages/Twist
280+
281+
operations:
282+
CmdVel:
283+
action: receive
284+
channel:
285+
$ref: "#/channels/CmdVel"
286+
bindings:
287+
ros2:
288+
role: subscriber
289+
node: /turtlesim
290+
qosPolicies:
291+
history: unknown
292+
reliability: reliable
293+
durability: volatile
294+
lifespan: -1
295+
deadline: -1
296+
liveliness: automatic
297+
leaseDuration: -1
298+
```
299+
300+
./interfaces/geometry_msgs.yaml
301+
```yaml
302+
asyncapi: 3.0.0
303+
info:
304+
title: geometry_msgs
305+
version: 1.0.0
306+
components:
307+
messages:
308+
Twist:
309+
tags:
310+
- name: msg
311+
payload:
312+
type: object
313+
properties:
314+
linear:
315+
$ref: "#/components/messages/Vector3/payload"
316+
angular:
317+
$ref: "#/components/messages/Vector3/payload"
318+
Vector3:
319+
payload:
320+
properties:
321+
x:
322+
type: number
323+
format: double
324+
y:
325+
type: number
326+
format: double
327+
z:
328+
type: number
329+
format: double
330+
```

0 commit comments

Comments
 (0)