Fine‑Tuning ROS 2 DDS QoS: Reliability, Durability, and Cross‑Node Compatibility
Learn how to adjust ROS 2 DDS Quality‑of‑Service (QoS) settings to balance latency and message reliability, verify correct profiles across nodes, and recover from common mis‑configurations.
07 Jan 2026, 04:34 UTC

Desired Outcome
Ensure that ROS 2 nodes exchange data reliably while keeping latency within acceptable limits. The goal is to configure Reliability and Durability QoS policies so that publishers and subscribers agree, and to verify that the settings are in effect on the running system.
Prerequisites
- ROS 2 distribution installed (Humble, Iron, or Jazzy). The default DDS vendor may be Cyclone DDS, Fast DDS, or OpenDDS.
- Basic familiarity with ROS 2 launch files and YAML syntax.
- Access to the target nodes’ launch files or a working ROS 2 workspace.
- Command‑line tools:
ros2,ros2wtf, andros2 interface show.
Choosing a QoS Profile
ROS 2’s default QoS is Reliability=Best‑Effort and Durability=Volatile. This is ideal for high‑throughput pipelines where occasional loss is tolerable. When you need guaranteed delivery (e.g., sensor data that must not be dropped), switch to Reliability=Reliable. However, this adds acknowledgment traffic and can increase latency, especially with large history.depth values.
Durability determines whether late‑joining subscribers receive past samples. Volatile discards history; Transient‑Local keeps a buffer that new subscribers can replay.
Configuring QoS in Launch Files
Define a custom QoS profile in a YAML file and reference it in your launch script. Example: qos_profiles.yaml
my_reliable_qos:
reliability: reliable
durability: transient_local
history: keep_last
depth: 10
deadline: { period: 1.0 }
lifespan: { duration: 5.0 }
In your launch file, load this profile and attach it to a publisher or subscriber:
from launch import LaunchDescription
from launch_ros.actions import Node
qos = {'qos_profile': 'my_reliable_qos'}
publisher = Node(
package='my_pkg',
executable='talker',
name='talker_node',
parameters=[qos],
)
subscriber = Node(
package='my_pkg',
executable='listener',
name='listener_node',
parameters=[qos],
)
return LaunchDescription([publisher, subscriber])
Replace talker and listener with your actual executables. The parameters field passes the QoS map to the node; the ROS 2 runtime expands it into the DDS QoS settings.
Verifying QoS Settings at Runtime
After launching, confirm the advertised QoS profile:
ros2 topic info /my_topic
The output contains a qos.profile section. Verify that Reliability, Durability, History, and depth match the intended values.
For a deeper check, run:
ros2 interface show /my_topic
This command prints the full QoS profile for the topic, including any vendor‑specific extensions. If the publisher and subscriber show different values, ROS 2 emits a warning at runtime: QoS profile mismatch.
Monitoring for Mismatches
- Check node logs for
QoS profile mismatchmessages. These indicate that the DDS vendor silently accepted the mismatched profiles, which may lead to message loss. - Use
ros2wtfto generate a quick diagnostic report. The tool lists all topics, their QoS settings, and any warnings. - On embedded systems, monitor RAM usage. A
Reliablepublisher with a largehistory.depthcan consume significant memory; if the node starts thrashing, reduce the depth.
Recovering from Misconfigurations
- Identify the offending node: Look at the log timestamp and node name in the mismatch warning.
- Align the QoS: Either change the publisher to
Reliableor the subscriber toBest‑Effort, ensuring both share the same reliability and durability values. - Restart the nodes: A QoS change requires a node restart to re‑advertise the topic with the new profile.
- Re‑verify: Run
ros2 topic infoagain to confirm the updated settings.
Practical Example: Reliable Sensor Data
Suppose a LiDAR node publishes /scan messages that must not be lost. We want Reliable delivery and Transient‑Local durability so that a late‑joining mapping node can replay the last 5 scans.
lidar_qos:
reliability: reliable
durability: transient_local
history: keep_last
depth: 5
In the LiDAR launch file:
Node(
package='lidar_pkg',
executable='lidar_driver',
name='lidar_node',
parameters=[{'qos_profile': 'lidar_qos'}],
)
In the mapping node’s launch file, reference the same QoS:
Node(
package='mapping_pkg',
executable='mapper',
name='mapper_node',
parameters=[{'qos_profile': 'lidar_qos'}],
)
After deployment, run ros2 topic info /scan on both nodes. The output should show matching Reliability=Reliable and Durability=Transient‑Local entries.
Limitations and Practical Checks
- Different DDS vendors may interpret the same QoS values slightly differently. Test on the target vendor before production.
- Large
history.depthvalues inReliablemode can exhaust memory on small robots. Usekeep_lastwith a modest depth orkeep_allonly when necessary. - Some ROS 2 distributions expose additional QoS parameters (e.g.,
latency_budget,liveliness). Useros2 interface showto discover them.
Summary
By explicitly defining QoS profiles, attaching them to publishers and subscribers, and verifying the alignment at runtime, you can control the trade‑off between latency and reliability in ROS 2. Remember that mismatched profiles trigger warnings and may silently cause data loss, especially on certain DDS implementations. Use the provided commands to audit your system and adjust settings before deployment to avoid hard‑to‑debug communication issues.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.