ros2 / rclcpp

rclcpp (ROS Client Library for C++)
Apache License 2.0
559 stars 422 forks source link

Automatic/adaptive subscription QoS #1868

Open emersonknapp opened 2 years ago

emersonknapp commented 2 years ago

Feature request

Feature description

Provide the ability for a subscription to automatically choose a QoS based on detected QoS of publishers in the graph. Most times for the business logic of robot applications, we want to explicitly specify QoS policies to clearly lay out communication behavior requirements.

However, some tooling and infrastructure by design does not care about the exact behavior and just wants to match with publishers no matter what, at as high a level of fidelity/service as possible. Three use cases come to mind up front:

This feature API might be:

Behavior considerations:

Implementation considerations

Will need this in both rclpy and rclcpp. Python is necessary to expose to ros2cli and some topic_tools. Given that, maybe this feature belongs in rcl or maybe even in some RMW utility package.

There are two current implementations that I know of for this feature, in rosbag2 and in topic_tools. Using those as a starting point for a "core" implementation makes sense to me.

See https://github.com/ros2/rosbag2/blob/master/rosbag2_transport/src/rosbag2_transport/qos.cpp for rosbag2 logic - those tools used around https://github.com/ros2/rosbag2/blob/master/rosbag2_transport/src/rosbag2_transport/recorder.cpp#L238

jacobperron commented 2 years ago

As another pointer, there's another implementation of this in domain_bridge (inspired by the rosbag2 logic).

Here are other threads discussing this feature:

I think it makes sense to have two functions in rcl (and maybe implemented inrmw): one for getting the best possible QoS for a given publisher and a second function for a given subscription. We can then provide rclcpp and rclpy wrappers for the rcl functions.

@emersonknapp I think these functions could easily satisfy your second and third behavioral considerations: get the highest possible QoS and account for multiple entities with different QoS. However, doing something like re-adapting to new pub/subs on the graph sounds difficult.

We considered re-adapting QoS during runtime for the domain_bridge, but it is not clear how to achieve this without recreating the publisher or subscription in question. If we recreate a subscription, then it becomes difficult to deal with messages that may be lost (or duplicated) during the transition. I'd like to hear from others about how this kind of feature might best be achieved. IMO, it seems like it is not worth the effort.

fujitatomoya commented 2 years ago

@jacobperron

However, doing something like re-adapting to new pub/subs on the graph sounds difficult. but it is not clear how to achieve this without recreating the publisher or subscription in question.

I think we do need to have new RMW interface to reset the QoS for publisher and subscriber at runtime to achieve this re-adapting QoS? if i am not mistaken, it can be done with DDS. CC: @MiguelCompany @eboasson

eboasson commented 2 years ago

You're opening a can of worms here ... the very short answer is that in DDS it is impossible to make a data reader that will "reliably" get data from all writers for the same topic without getting duplicates:

Furthermore, some of the QoS settings that do this problematic request-offered (RxO) matching and that are supported by ROS 2 cannot be changed: reliability, durability and liveliness are fixed at creation time of a reader/writer. If you really want to go ahead with this, I'd suggest recreating the publisher/subscription, make sure that the new one is discovered before deleting the old one and deal with any double arrivals separately.

The only alternative would be DDS spec changes or vendor-specific extensions to implement different matching rules, which could be done in such a way that there'd be no need to adapt anything. Sadly, vendor-specific will get messy if interoperability is desired and the spec changes more slowly than a glacier melts in an ice age ...

fujitatomoya commented 2 years ago

@eboasson appreciate for your quick and informative comments.

I'd suggest recreating the publisher/subscription, make sure that the new one is discovered before deleting the old one and deal with any double arrivals separately.

i see. at least i do not have any other ways to achieve this. and it seems like it is not worth the effort...

emersonknapp commented 2 years ago

@jacobperron (and others) I think it makes sense to provide the utilities to adapt a subscription to a known set of publisher qos profiles. We could skip re-adapting to newly discovered publishers, in the requirements for this particular ticket - and revisit that as its own feature, if desired, later.

akash-roboticist commented 2 years ago

With the assumption that publishers exist at subscription creation time and not adapt to new publishers, listing here a couple of approaches to this. My thought was to add the detection logic in rcl and update/add wrapper to the subscription initialization interface rcl_subscription_init() to use this and adapt to the publisher QoS.

Approach 1

Pros:

Approach 2

Pros:

jacobperron commented 2 years ago

After some iteration, I've proposed adding new policy enum values at the RMW layer for selecting the 'best available' policy (ie. the policy that will match the most endpoints while maintaining the highest level of service). Feedback is welcome: https://github.com/ros2/rmw/pull/320

This delegates to the middleware for how to implement the matching logic. For DDS implementations, we provide a common implementation that will query discovered endpoints at the time of creating a subscription/publisher and use that information to adapt the QoS policies: https://github.com/ros2/rmw_dds_common/pull/60