|
| 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