ROS Middleware

Data Distribution Service (DDS)

Data Distribution Service (DDS) is a Middleware standard for data-centric systems, which allows different parts of a system to share data in a seamless and efficient way.

3 ways to transport data:

  1. UDP Transport
  2. TCP Transport
  3. Shared Memory Transport

How do ROS nodes know about the DDS?

Like is DDS decided at runtime or compile time? “The Data Distribution Service (DDS) in ROS (Robot Operating System) is typically initialized at runtime. It is not a compile-time component, although you must link against the DDS libraries during compilation.”

ROS2 uses DDS for message transport.

Default RMW?

The default DDS vendor is eProsima’s Fast DDS, i.e. FastRTPS.

  • ROS2 uses Fast DDS by default now since Humble (but it’s called FastRTPS..??), galactic default was CycloneDDS

DDS is at the core of ROS

It is really important that you understand this. Everything, from the way different topics are discovered, to how messages are defined and transported, are tightly coupled with the DDS implementation, but made agnostic through the middleware interface.

ConnextDDS will have a different implementation than CycloneDDS.

Multiple Middleware Implementations

Source 1, Source 2

If a ROS 2 workspace has multiple RMW implementations, the default RMW implementation since Galactic is selected as Cyclone DDS if it’s available. If the Cyclone DDS RMW implementation is not installed, the RMW implementation with the first RMW implementation identifier in alphabetical order will be used. The implementation identifier is the name of the ROS package that provides the RMW implementation, e.g. rmw_cyclonedds_cpp. For example, if both rmw_fastrtps_cpp and rmw_connext_cpp ROS packages are installed, rmw_connext_cpp would be the default. If rmw_cyclonedds_cpp is ever installed, it would be the default.c

FastRTPS is actually FastDDS for historical reasons

Note that Fast RTPS is now known as Fast DDS, but for historical reasons this report will continue to refer to it as Fast RTPS. Source: https://osrf.github.io/TSC-RMW-Reports/humble

DDS is an end-to-end middleware that provides features which are relevant to ROS systems, such as distributed discovery (not centralized like in ROS 1) and control over different “Quality of Service” options for the transportation.

I first encountered this while working at Enlighted, because I was running into communication issues, but I think if I really want to be a good engineer, I need to understand how ROS actually works under the hood.

Will also be super useful working at NVIDIA. Tie together High-Level Low-Level Thinking.

Links

DDS Discovery

Source There is no rosmaster like in ROS1. Node discovery is peer-to-peer with nodes announcing their topics on startup and periodically after that. By default, any machines on the same network will see each other if they have the same ROS_DOMAIN_ID.

“The advantage of the DDS discovery system is that, by default, it is completely distributed, so there is no central point of failure which is required for parts of the system to communicate with each other.”

DDS History

Why does ROS have all these DDS options?

Like why didn’t they just choose a single one? To understand why, we need to understand how DDS came about.

DDS was originally several similar middlewares which eventually became so close to one another that writing a standard to unify them made sense.

DDS specification is written by a committee, it has evolved to its current form by reacting to the needs of its users.

Now, there are DDS vendors. OMG maintains a list of DDS vendors that you can find here.

Compatibility of DDS

Okay, so I just started to better understand what rosidl is about. The ROS messages need to be converted on some standard format, and the middleware takes care of converting from .msg to .idl format.

Supported RMW Implementations

  • eProsima Fast DDS rmw_fastrtps_cpp
  • Eclipse Cyclone DDS rmw_cyclonedds_cpp
  • RTI Connext rmw_connext_cpp
  • GurumNetworks GurumDDS rmw_gurumdds_cpp

For many cases you will find that nodes using different RMW implementations are able to communicate, however this is not true under all circumstances. Here is a list of inter-vendor communication configurations that are not supported:

Here are the 3 communications between different DDS that doesn’t work:

  • Fast DDS <→ Connext
    • WString published by Fast DDS can’t be received correctly by Connext on macOS
  • Connext <→ Cyclone DDS
    • does not support pub/sub communication for WString
  • Connext Dynamic <→ Connext Dynamic
    • does not support C services

Different types of DDS

CycloneDDS

https://cyclonedds.io/docs/cyclonedds/latest/config/discovery-config.html

The options: https://github.com/eclipse-cyclonedds/cyclonedds/blob/master/docs/manual/options.md

ConnextDDS

Source By default, RTI Connext DDS uses the UDPv4 and Shared Memory transport to communicate with other DDS applications. In some circumstances, the TCP protocol might be needed for discovery and data exchange.

Go to ConnextDDS.

Node to Participant Mapping

https://design.ros2.org/articles/Node_to_Participant_mapping.html