Use Cyclone DDS
Needs first: Pick and configure the RMW
Use Cyclone DDS when an image should talk to ROS 2 nodes directly, with no router or agent running beside it.
The Cyclone DDS backend is Eclipse Cyclone DDS, the same DDS implementation
ROS 2 uses through rmw_cyclonedds_cpp, pinned to the version ROS 2 ships.
An image on it speaks RTPS and discovers its peers itself, so a stock
rmw_cyclonedds_cpp node sees it with nothing in between.
Where it runs
Which boards build and run a Cyclone DDS image is generated from the board registry, not written here:
- Supported boards: each board’s evidence page lists, under Breadth, the RMWs its tests run.
- Per-RMW feature matrix: what the backend implements (services, status events, QoS policies) next to zenoh and XRCE-DDS.
- Support status: the pinned Cyclone version and the ROS 2 release it pairs with.
Before you start
- A workspace, such as the host one from Run a talker.
- ROS 2 Humble with
ros-humble-rmw-cyclonedds-cppon the same network, to see the image from ROS 2.
Steps
-
Provision the backend for your board.
--rmw cycloneddsadds Cyclone’s sources and the message tools its type support needs;nros buildthen builds Cyclone itself, with no separate step:nros setup linux --rmw cyclonedds -
Select it. Set
rmwin the bringup’ssystem.toml, for every image:[system] rmw = "cyclonedds"Check what the bringup resolved:
nros config show[system] rmw = cyclonedds # system.toml [system]To change one image only, put
rmw = "cyclonedds"in its[image.<id>]block instead; see Switch the RMW per image. -
Run it. No router starts, because Cyclone DDS needs none:
nros run host_node --expect 'Publishing:' --timeout 120Publishing: 'Hello World: 1' nros run: matched after -
See it from ROS 2, in a second terminal:
source /opt/ros/humble/setup.bash export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp ros2 topic echo /chatter std_msgs/msg/String --qos-reliability best_effortdata: 'Hello World: 4' -
Pick the DDS domain. The image runs on
[system] domain_id, and Cyclone’s own domain follows it. A ROS 2 peer must use the same number:[system] domain_id = 5ROS_DOMAIN_ID=5 ros2 topic echo /chatter std_msgs/msg/String --qos-reliability best_effort -
Configure Cyclone itself, if the defaults do not fit your network: which interface to use, whether to multicast, tracing. Write Cyclone’s own XML, the document
CYCLONEDDS_URInames on a ROS 2 host, asrmw/cyclonedds.xmlbesidesystem.toml:<CycloneDDS xmlns="https://cdds.io/config"> <Domain id="any"> <General> <Interfaces> <NetworkInterface autodetermine="true" priority="default" multicast="default" /> </Interfaces> <AllowMulticast>default</AllowMulticast> </General> </Domain> </CycloneDDS>The build copies the file into the image and hands it to Cyclone’s own parser, so it reaches a target that has no file system. Use
<Domain id="any">, or the image’sdomain_id:nros buildrefuses any other id. On a host image,CYCLONEDDS_URIstill replaces the file at run time. -
On an RTOS image, give the network stack what RTPS discovery needs: multicast (IGMP), enough network buffers for the burst of discovery traffic, and a heap, since Cyclone allocates with
malloc. On Zephyr, start from the fragment the shipped examples use and name it in the image:[image.zephyr_cyclonedds] board = "zephyr" rmw = "cyclonedds" os_config = ["prj-cyclonedds.conf"]Copy
examples/zephyr/rust/talker/prj-cyclonedds.confbesidesystem.toml. Its lines that matter for Cyclone areCONFIG_NET_IPV4_IGMP=y, theCONFIG_NET_PKT_*andCONFIG_NET_BUF_*counts, andCONFIG_HEAP_MEM_POOL_SIZE. The settings for the other platforms are listed in Pick and configure the RMW.
Example
A host talker on DDS domain 5 with its own Cyclone configuration. This is
the bringup nros new host_ws --board linux --template talker --rmw cyclonedds
writes, with domain_id changed:
# src/host_node_bringup/system.toml
[system]
name = "host_node"
rmw = "cyclonedds"
ros_edition = "humble"
domain_id = 5
[[component]]
pkg = "host_node"
class = "host_node::Talker"
name = "host_node"
[image.posix]
board = "linux"
with src/host_node_bringup/rmw/cyclonedds.xml as in step 6. Run the image
and the listener:
nros run host_node
source /opt/ros/humble/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp ROS_DOMAIN_ID=5
ros2 topic echo /chatter std_msgs/msg/String --qos-reliability best_effort
If it doesn’t work
- The build stops on
<Domain id>. The XML names a domain other thananyor the image’sdomain_id. Change it toany. ros2 topic echoshows nothing. Check that both sides use the sameROS_DOMAIN_IDand that the ROS 2 side runsrmw_cyclonedds_cpp. On a network without multicast, list the peers in the XML instead.- Two Zephyr
native_simimages never discover each other. Its offloaded sockets do not pass multicast to the host; see Troubleshoot. - An RTOS image stalls during discovery. The network buffer counts or the heap are too small for the discovery burst. Raise them in the image’s fragment.
See also
- Configure an image: the middleware’s own file, and one file per image.
- Configuration surface: where
rmwanddomain_idare set and what they become on Zephyr. - Bridge between backends: Cyclone DDS beside zenoh or XRCE-DDS in one image.
- How nano-ros differs from ROS 2.