Skip to content

Conversation

@pavansai018
Copy link

Fix liveliness BEST_AVAILABLE handling in rclpy

Summary

This PR resolves an inconsistency in how rclpy handles LivelinessPolicy.BEST_AVAILABLE.
The Python QoS API exposes this enum value, but the rmw layer does not implement a corresponding liveliness policy. As a result, rclpy forwarded an unsupported enum value into rmw_qos_profile_t, causing incorrect introspection and QoS incompatibility warnings.

This patch maps LivelinessPolicy.BEST_AVAILABLE to LivelinessPolicy.AUTOMATIC, aligning with how the rmw-defined qos_profile_best_available behaves.

Problem

When both publisher and subscription use:

QoSProfile(depth=10, liveliness=LivelinessPolicy.BEST_AVAILABLE)

the following issues occur:

  • ros2 topic info shows AUTOMATIC instead of BEST_AVAILABLE
  • QoS compatibility check reports LIVELINESS incompatibility
  • Publisher and subscription cannot communicate despite matching QoS settings

Root cause:
BEST_AVAILABLE (raw value 5) is not a valid rmw liveliness policy and must be resolved to a supported value before constructing the rmw QoS profile.

Solution

  • Detect LivelinessPolicy.BEST_AVAILABLE in the QoSProfile setter
  • Resolve it to LivelinessPolicy.AUTOMATIC before sending it to rmw

This restores correct QoS negotiation and ensures consistent behavior across publisher/subscription endpoints.

Impact

  • Fixes LIVELINESS incompatibility warnings
  • Ensures introspection reflects the correct resolved policy
  • Does not break existing user code
  • Makes rclpy consistent with rmw QoS semantics

Future Considerations

A future ROS 2 release may choose to deprecate liveliness BEST_AVAILABLE or extend rmw to support a formal best-available liveliness policy. This patch provides safe and deterministic behavior for current ROS 2 distributions.

Related Issue

Fixes: ros2/ros2#1722

…ing to AUTOMATIC

The Python QoS API exposes , but the underlying
rmw layer does not define or support a “best available” liveliness enum value.
As a result, rclpy forwarded the raw enum value (5) into rmw_qos_profile_t,
leading to inconsistent behavior:

-  reports liveliness as AUTOMATIC
- rclpy_qos_check_compatible reports LIVELINESS incompatibility
- publisher and subscription using identical QoS settings cannot communicate

This patch resolves the inconsistency by explicitly mapping
 to  when building
the rmw QoS profile. This matches how the best_available preset QoS profile is
defined in rmw, and restores compatibility between endpoints.

A deprecation warning may be added in a future release to clarify that
BEST_AVAILABLE for liveliness is not a standalone rmw policy.

Fixes: ros2/ros2#1722
Signed-off-by: pavansai018 <[email protected]>
rmw layer does not define or support a “best available” liveliness enum value.
As a result, rclpy forwarded the raw enum value (5) into rmw_qos_profile_t,
leading to inconsistent behavior:

-  reports liveliness as AUTOMATIC
- rclpy_qos_check_compatible reports LIVELINESS incompatibility
- publisher and subscription using identical QoS settings cannot communicate

This patch resolves the inconsistency by explicitly mapping
 to  when building
the rmw QoS profile. This matches how the best_available preset QoS profile is
defined in rmw, and restores compatibility between endpoints.

A deprecation warning may be added in a future release to clarify that
BEST_AVAILABLE for liveliness is not a standalone rmw policy.

Fixes: ros2/ros2#1722
Signed-off-by: pavansai018 <[email protected]>
rmw layer does not define or support a “best available” liveliness enum value.
As a result, rclpy forwarded the raw enum value (5) into rmw_qos_profile_t,
leading to inconsistent behavior:

-  reports liveliness as AUTOMATIC
- rclpy_qos_check_compatible reports LIVELINESS incompatibility
- publisher and subscription using identical QoS settings cannot communicate

This patch resolves the inconsistency by explicitly mapping
 to  when building
the rmw QoS profile. This matches how the best_available preset QoS profile is
defined in rmw, and restores compatibility between endpoints.

A deprecation warning may be added in a future release to clarify that
BEST_AVAILABLE for liveliness is not a standalone rmw policy.

Fixes: ros2/ros2#1722
Signed-off-by: pavansai018 <[email protected]>
Comment on lines +260 to +265
# Resolve BEST_AVAILABLE liveliness before passing it to rmw.
liveliness = self.liveliness
if liveliness == QoSLivelinessPolicy.BEST_AVAILABLE:
# Map BEST_AVAILABLE to AUTOMATIC for rmw, since rmw doesn't define a
# separate BEST_AVAILABLE liveliness policy.
liveliness = QoSLivelinessPolicy.AUTOMATIC
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i do not think this fixes the ros2/ros2#1722, because rmw_dds_common already does this. (the same process is done for publisher as well.)

https://github.com/ros2/rmw_dds_common/blob/be02253b7b872bb9223e783421c5deee3269abfe/rmw_dds_common/src/qos.cpp#L459-L465

@pavansai018 can you reproduce the issue ros2/ros2#1722 on jazzy distro? that i cannot reproduce it with the following.

root@tomoyafujita:/# ros2 topic pub --qos-depth 10 --qos-liveliness best_available /chatter std_msgs/msg/String "{data: \"Hello from command line\"}"
publisher: beginning loop
publishing #1: std_msgs.msg.String(data='Hello from command line')

publishing #2: std_msgs.msg.String(data='Hello from command line')

publishing #3: std_msgs.msg.String(data='Hello from command line')

publishing #4: std_msgs.msg.String(data='Hello from command line')

publishing #5: std_msgs.msg.String(data='Hello from command line')

...

root@tomoyafujita:/# ros2 topic echo --qos-depth 10 --qos-liveliness best_available /chatter
data: Hello from command line
---
data: Hello from command line
---
data: Hello from command line
---
data: Hello from command line
---

root@tomoyafujita:/# ros2 topic info /chatter -v
Type: std_msgs/msg/String

Publisher count: 1

Node name: _ros2cli_1177
Node namespace: /
Topic type: std_msgs/msg/String
Topic type hash: RIHS01_df668c740482bbd48fb39d76a70dfd4bd59db1288021743503259e948f6b1a18
Endpoint type: PUBLISHER
GID: 01.0f.76.65.99.04.46.41.00.00.00.00.00.00.07.03
QoS profile:
  Reliability: RELIABLE
  History (Depth): UNKNOWN
  Durability: VOLATILE
  Lifespan: Infinite
  Deadline: Infinite
  Liveliness: AUTOMATIC
  Liveliness lease duration: Infinite

Subscription count: 1

Node name: _ros2cli_1192
Node namespace: /
Topic type: std_msgs/msg/String
Topic type hash: RIHS01_df668c740482bbd48fb39d76a70dfd4bd59db1288021743503259e948f6b1a18
Endpoint type: SUBSCRIPTION
GID: 01.0f.76.65.a8.04.20.ed.00.00.00.00.00.00.07.04
QoS profile:
  Reliability: BEST_EFFORT
  History (Depth): UNKNOWN
  Durability: VOLATILE
  Lifespan: Infinite
  Deadline: Infinite
  Liveliness: AUTOMATIC
  Liveliness lease duration: Infinite

Copy link
Author

@pavansai018 pavansai018 Dec 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the review. I have performed a clean test using the provided pub.py and sub.py files, both of which explicitly set the Liveliness QoS to LivelinessPolicy.BEST_AVAILABLE.

I can reproduce the error, and the log output below confirms a fatal QoS incompatibility on the LIVELINESS policy.

Reproduction Logs

The following logs confirm that communication fails immediately due to a QoS mismatch between the publisher and the subscriber:

Publisher Log:

The publisher detects the subscriber but warns that it cannot send data:
image

Subscriber Log:

The subscriber detects the publisher but warns that it cannot receive data:
image

Code Origin and Impact

pub.py
image

sub.py
image

The provided pub.py and sub.py files are heavily inspired by the official ROS 2 beginner tutorial code (https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Publisher-And-Subscriber.html).

Note

I am using jazzy distro on Linux Mint (based on Ubuntu Noble)
But I am unable to reproduce same issue using ros2 topic pub --qos-depth 10 --qos-liveliness best_available /chatter std_msgs/msg/String "{data: \"Hello from command line\"}" and ros2 topic echo --qos-depth 10 --qos-liveliness best_available /chatter. Everything seems fine here. But rclpy is having an issue I guess.

Please let me know if you need any additional information.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the problem is in rmw layer, so probably client interfaces are not related to this problem. i can reproduce the issue with samples with rolling, only with rmw_fastrtps_cpp.

  • rmw_cyclonedds_cpp, rmw_connextdds and rmw_zenoh_cpp does not have this problem. (the following is the example output from rmw_cyclonedds_cpp)
$ RMW_IMPLEMENTATION=rmw_cyclonedds_cpp ros2 run prover_rclpy ros2_1722_pub
...

$ RMW_IMPLEMENTATION=rmw_cyclonedds_cpp ros2 run prover_rclpy ros2_1722_sub
...

$ RMW_IMPLEMENTATION=rmw_cyclonedds_cpp ros2 topic info -v /topic
Type: std_msgs/msg/String

Publisher count: 1

Node name: minimal_publisher
Node namespace: /
Topic type: std_msgs/msg/String
Topic type hash: RIHS01_df668c740482bbd48fb39d76a70dfd4bd59db1288021743503259e948f6b1a18
Endpoint type: PUBLISHER
GID: 01.10.12.d1.01.99.9d.bd.f6.c7.f7.20.00.00.16.03
QoS profile:
  Reliability: RELIABLE
  History (Depth): KEEP_LAST (10)
  Durability: VOLATILE
  Lifespan: Infinite
  Deadline: Infinite
  Liveliness: AUTOMATIC
  Liveliness lease duration: Infinite

Subscription count: 1

Node name: minimal_subscriber
Node namespace: /
Topic type: std_msgs/msg/String
Topic type hash: RIHS01_df668c740482bbd48fb39d76a70dfd4bd59db1288021743503259e948f6b1a18
Endpoint type: SUBSCRIPTION
GID: 01.10.b8.52.54.3f.20.b0.d8.6d.19.37.00.00.16.04
QoS profile:
  Reliability: RELIABLE
  History (Depth): KEEP_LAST (10)
  Durability: VOLATILE
  Lifespan: Infinite
  Deadline: Infinite
  Liveliness: AUTOMATIC
  Liveliness lease duration: Infinite

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with rmw_fastrtps, we can see that liveliness policy falls to MANUAL_BY_TOPIC.

```console
$ ros2 topic info -v /topic
Type: std_msgs/msg/String

Publisher count: 1

Node name: minimal_publisher
Node namespace: /
Topic type: std_msgs/msg/String
Topic type hash: RIHS01_df668c740482bbd48fb39d76a70dfd4bd59db1288021743503259e948f6b1a18
Endpoint type: PUBLISHER
GID: 01.0f.9c.7b.4c.05.68.7f.00.00.00.00.00.00.13.03
QoS profile:
  Reliability: RELIABLE
  History (Depth): KEEP_LAST (10)
  Durability: VOLATILE
  Lifespan: Infinite
  Deadline: Infinite
  Liveliness: AUTOMATIC
  Liveliness lease duration: Infinite

Subscription count: 1

Node name: minimal_subscriber
Node namespace: /
Topic type: std_msgs/msg/String
Topic type hash: RIHS01_df668c740482bbd48fb39d76a70dfd4bd59db1288021743503259e948f6b1a18
Endpoint type: SUBSCRIPTION
GID: 01.0f.9c.7b.61.05.71.92.00.00.00.00.00.00.13.04
QoS profile:
  Reliability: RELIABLE
  History (Depth): KEEP_LAST (10)
  Durability: VOLATILE
  Lifespan: Infinite
  Deadline: Infinite
  Liveliness: MANUAL_BY_TOPIC
  Liveliness lease duration: Infinite

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Jazzy][Python] QoS compatibility issue when setting the liveliness of pub/sub to BEST_AVAILABLE

2 participants