Quality of Service (QoS)

Quality of service is the description or measurement of the overall performance of a service, such as a telephony or computer network, or a cloud computing service, particularly the performance seen by the users of the network.

DDS controls the parameters of reliability through QoS.

“With the right set of Quality of Service policies, ROS 2 can be as reliable as TCP or as best-effort as UDP, with many, many possible states in between.”


Reliability and Durability

There are two different settings for reliability (best effort and reliable), and two different settings for durability (volatile and transient local).

Different Defaults using different RMWs

Different RMW implementations have different defaults. When I was first looking at this, there were actually defaults.

QoS Settings

The base QoS profile currently includes settings for the following policies (source):

  • History (two options)
    • Keep last (DEFAULT): only store up to N samples, configurable via the queue depth option.
    • Keep all: store all samples, subject to the configured resource limits of the underlying middleware.
  • Depth
    • Queue size (DEFAULT=10): only honoured if the “history” policy was set to “keep last”.
  • Reliability (2 options)
    • Best effort: attempt to deliver samples, but may lose them if the network is not robust.
    • Reliable (DEFAULT): guarantee that samples are delivered, may retry multiple times.
  • Durability (2 options)
    • Transient local: the publisher becomes responsible for persisting samples for “late-joining” subscriptions.
    • Volatile (DEFAULT): no attempt is made to persist samples.
  • Deadline
    • Duration: the expected maximum amount of time between subsequent messages being published to a topic
  • Lifespan
    • Duration: the maximum amount of time between the publishing and the reception of a message without the message being considered stale or expired (expired messages are silently dropped and are effectively never received).
  • Liveliness (2 options)
    • Automatic: the system will consider all of the node’s publishers to be alive for another “lease duration” when any one of its publishers has published a message.
    • Manual by topic: the system will consider the publisher to be alive for another “lease duration” if it manually asserts that it is still alive (via a call to the publisher API).
  • Lease Duration
    • Duration: the maximum period of time a publisher has to indicate that it is alive before the system considers it to have lost liveliness (losing liveliness could be an indication of a failure).

For example

dmin@c07e6b4-lcelt:/workspaces/isaac_ros-dev$ ros2 topic info -v /camera/front_left/image
Type: sensor_msgs/msg/Image

Publisher count: 1

Node name: rosbag2_player
Node namespace: /
Topic type: sensor_msgs/msg/Image
Endpoint type: PUBLISHER
QoS profile:
  Reliability: BEST_EFFORT
  History (Depth): UNKNOWN
  Durability: VOLATILE
  Lifespan: Infinite
  Deadline: Infinite
  Liveliness: AUTOMATIC
  Liveliness lease duration: Infinite

Subscription count: 1

Node name: front_left_encoder_node
Node namespace: /
Topic type: sensor_msgs/msg/Image
Endpoint type: SUBSCRIPTION
QoS profile:
  Reliability: RELIABLE
  History (Depth): UNKNOWN
  Durability: VOLATILE
  Lifespan: Infinite
  Deadline: Infinite
  Liveliness: AUTOMATIC
  Liveliness lease duration: Infinite

Compatibility of reliability QoS policies:

Under the hood

If you understand how TCP and UDP works, and how things work under the hood, then you should be able to build this table on your own.

Best effortBest effortYes
Best effortReliableNo
ReliableBest effortYes

Compatibility of durability QoS policies:

VolatileVolatileYesNew messages only
VolatileTransient localNoNo communication
Transient localVolatileYesNew messages only
Transient localTransient localYesNew and old messages

refer to for compatibility settings for deadline QoS, liveliness and lease duration.


I see this in ROS2.

[async_slam_toolbox_node-1] [WARN] [1677776750.617279018] [slam_toolbox]: New subscription discovered on topic '/slam_toolbox/scan_visualization', requesting incompatible QoS. No messages will be sent to it. Last incompatible policy: DURABILITY_QOS_POLICY

This is because in another node, I specified another qos_profile…? No, it’s because I was using Foxglove. The issue is this:

from rclpy.qos import QoSProfile, QoSReliabilityPolicy, QoSHistoryPolicy
qos_profile = QoSProfile(

To get the information, do

ros2 topic info /odom -v

Connection to DDS

I REALLY REALLY need to understand this.


Suppose you recorded a rosbag with a particular QoS. You can remap it to a new QoS with a override.yaml file.