jhelovuo / ros2-client

ROS2 client library based on RustDDS
66 stars 14 forks source link

Issue with `async_listener` example: mismatch between advertised QoS profile and actual QoS profile #31

Closed showier-drastic closed 3 days ago

showier-drastic commented 2 months ago

In the async_listener example, QoS reliability of "Reliable" is effective as per reliable_qos, which is passed to create_subscription. So, you are not able to get messages from publishers with "Best Effort" reliability.

We can test this by running ros2 topic pub --qos-reliability best_effort /topic std_msgs/msg/String "data: 'asdfasdf'", and the message will not received by this listener. Only when best_effort is changed to reliable, the message can be received.

However, the advertised subscriber QoS settings is from the 3rd argument of create_topic (DEFAULT_SUBSCRIPTION_QOS), which says "Best Effort". The following is the output of ros2 topic info /topic --verbose:

Node name: rustdds_listener
Node namespace: /rustdds
Topic type: std_msgs/msg/String
Endpoint type: SUBSCRIPTION
GID: 01.12.61.e7.39.90.67.49.a8.4d.5f.87.00.00.03.04.00.00.00.00.00.00.00.00
QoS profile:
  Reliability: RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT
  Durability: RMW_QOS_POLICY_DURABILITY_VOLATILE
  Lifespan: 2147483651294967295 nanoseconds
  Deadline: 2147483651294967295 nanoseconds
  Liveliness: RMW_QOS_POLICY_LIVELINESS_AUTOMATIC
  Liveliness lease duration: 2147483651294967295 nanoseconds

This indicates a subscription reliability of "Best Effort", but the effective reliability is "Reliable". This inconsistency is misleading e.g. when we are debugging the issue that messages are not received.

In other ROS2 libraries suchs as rclpy or rclcpp, there's typically only one place to specify reliability settings, such as rclcpp::node::Node::create_subscription . I'm not sure why we have two places of specifying QoS profile (and this possibility of incoherence) in ros2-client.

jhelovuo commented 1 month ago

Hello @showier-drastic ,

Sorry for the delayed response, but it has been summer vacation season just now.

Turns out that your observation is correct, and this is exactly what happens. The advertised QoS policies for the Reader are from the call create_topic, and not from create_subscription, like they should be. That was exactly the bug found in RustDDS's Discovery module.

This is now fixed in the latest master commit of RustDDS.

Thank you for bringing this up.

You also wonder why ros2-client is different from rclpy or rclcpp so that there are two places for the QoS policies: Topic and Subscription (or Publisher) creation. This is simply because that is how the DDS API (as per the OMG spec) underneath works. Now that this bug is fixed, there should be no great chance of incoherence. If a Subscription specifies some QoS, then that overrides the Topic QoS, but the Topic QoS policies are used as a default, in case none is otherwise provided.

The Topic intermediate object is a bit more cumbersome to use than in e.g. rclcpp, but if you are creating both a Subscription and a Publisher to the same Topic, then using a shared Topic object for both ensures that the topic name and type string are coherent. Otherwise, you could accidentally connect into two different topics, or cause a type conflict in a topic. rclcpp ensures topic type coherence by using code generated from IDL or ROS2 .msg spec.

jhelovuo commented 3 days ago

Fix included in Release 0.7.5.