When a node uses SystemDefaultsQoS() (or leaves any policy to *_SYSTEM_DEFAULT), the intent is clear: delegate QoS
resolution to the underlying middleware. In theory, this is the right hook for system-wide QoS configuration without touching
node code.
In practice, the behavior is inconsistent across RMW implementations:
- FastDDS: supports full XML-based QoS override via
FASTDDS_DEFAULT_PROFILES_FILE+RMW_FASTRTPS_USE_QOS_FROM_XML=1.
Works as expected forSYSTEM_DEFAULTpolicies. - CycloneDDS:
CYCLONEDDS_URIcontrols participant-level settings (network, threads), not endpoint QoS (reliability,
durability, depth). No equivalent mechanism exists. - Zenoh (
rmw_zenoh): end-to-end reliability forRELIABLE+VOLATILE+KEEP_LASTis not yet fully implemented
(ros2/rmw_zenoh#457), and there is no external configuration mechanism for
endpoint QoS defaults.
The consequence is that a node written with SystemDefaultsQoS() — which is arguably the correct way to write portable,
externally-configurable nodes — behaves differently depending on which RMW is in use, and is only truly configurable on one of
them.
Root cause
All predefined QoS profiles (SensorDataQoS, ParametersQoS, ServicesQoS, etc.) are defined as static const in
rmw/qos_profiles.h — hardcoded values with no indirection layer:
| Profile | Reliability | Durability | Depth |
|---|---|---|---|
QoS(n) / default |
RELIABLE | VOLATILE | 10 |
SensorDataQoS() |
BEST_EFFORT | VOLATILE | 5 |
ParametersQoS() |
RELIABLE | VOLATILE | 1000 |
ServicesQoS() |
RELIABLE | VOLATILE | 10 |
RosoutQoS() |
RELIABLE | TRANSIENT_LOCAL | 1000 |
SystemDefaultsQoS() |
SYSTEM_DEFAULT | SYSTEM_DEFAULT | SYSTEM_DEFAULT |
A node calling SensorDataQoS() gets BEST_EFFORT with depth 5, unconditionally. The only escape hatch is
SystemDefaultsQoS(), but its resolution is RMW-specific and undocumented as a standard contract.
Proposal
Define a minimal standardized mechanism at the rcl or rmw interface level for resolving SYSTEM_DEFAULT QoS policies. This
could be:
- A well-defined env var (e.g.
RCL_DEFAULT_QOS_PROFILE) pointing to a vendor-neutral config file (YAML or similar), parsed by
rclbefore handing off to the RMW. - Or alternatively, a formal contract in the RMW interface spec requiring each implementation to document how it resolves
SYSTEM_DEFAULTpolicies and what configuration mechanism it exposes.
This would make SystemDefaultsQoS() actually useful as a portability and deployment tool — especially relevant as more RMW
implementations (Zenoh, Eclipse Cyclone, proprietary) diverge from the DDS XML model.
Interested in hearing whether others have hit this in practice, and whether there is appetite for a REP or a design doc to
formalize this.