Skip to content

Adding support for ON_REQUESTED_INCOMPATIBLE_QOS and ON_OFFERED_INCOMPATIBLE_QOS event callbacks in ROS2.  #822

@jaisontj

Description

@jaisontj

Feature description

Currently, it is possible for ROS2 users to create publishers and subscriptions to a topic with incompatible QoS policies; for example: subscription to a topic with a deadline smaller than the deadline for a publisher to the topic. This results in the subscription not receiving any data even though the publisher is publishing to the topic. These scenarios are difficult to debug and hence the user needs to be notified/warned when they create publishers/subscriptions with incompatible QoS Policies.

Thankfully, the DDS spec has callbacks in place which help with this, namely on_requested_incompatible_qos and on_offered_incompatible_qos.

Implementation considerations

The implementation can follow the same procedure as the existing event callbacks (on_offered_deadline_missed, on_requested_deadline_missed, on_liveliness_lost and on_liveliness_changed).

Listing out briefly the work required in each package:

  • ros2/rmw
    • Add the RMW_EVENT_REQUESTED_INCOMPATIBLE_QOS and RMW_EVENT_OFFERED_INCOMPATIBLE_QOS values to the enum rmw_event_type_t
    • Define two new structures to hold data regarding the status of these events: rmw_requested_incompatible_qos_status_t and rmw_offered_incompatible_qos_status_t.

Something like this:

struct  rmw_requested_incompatible_qos_status_t
{
   int32_t total_count;
   int32_t total_count_change;
   int32_t last_policy_id;
} ;

Note: QosPolicyCountSeq policies is something that I have skipped and would like to add as an enhancement once this is completed and merged. This is because we need to figure out how memory allocation for the policies array would work. For now these would alone provide a non zero enhancement to the system as users will be notified when creating incompatible qos policies between publishers and subscribers

  • ros2/rcl

    • Add RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS and RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS to enums rcl_publisher_event_type_t and rcl_subscription_event_type_t respectively.
    • Handle event types of RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS and RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS inside of rmw_publisher_event_init and rmw_subscriber_event_init
    • Unit tests similar to these
  • ros2/rclpy

    • Add RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS and RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS to enums QoSPublisherEventType and QoSSubscriptionEventType
    • Define two new payloads that mirror rmw_requested_incompatible_qos_status_t and rmw_offered_incompatible_qos_status_t that were defined in the rmw package. These are defined as follows:
QoSRequestedIncompatibleQoSInfo = NamedTuple(
 'QoSRequestedIncompatibleQoSInfo', [
 ('total_count', 'int'),
 ('total_count_change', 'int'),
 ('last_policy_id', 'int'),
 ])
 
 QoSOfferedIncompatibleQoSInfo = NamedTuple(
 'QoSOfferedIncompatibleQoSInfo', [
 ('total_count', 'int'),
 ('total_count_change', 'int'),
 ('last_policy_id', 'int'),
 ])
  • Enhance the SubscriptionEventCallbacks and PublisherEventCallbacks classes to support the new incompatible_qos callback.
    • define new member incompatible_qos
    • handle it in the create_event_handlers function
  • In _rclpy_qos_event.c
    • Add two entries of type rmw_requested_incompatible_qos_status_t and rmw_offered_incompatible_qos_status_t to the union _qos_event_callback_data
    • Define and implement two functions which convert rmw_requested_incompatible_qos_status_t and rmw_offered_incompatible_qos_status_t to PyObject and return these in the _get_qos_event_data_filler_function_for function
  • Unit tests similar to the ones here
  • ros2/rclcpp

    • Modify the PublisherEventCallbacks and SubscriptionEventCallbacks structs to include a new incompatible_qos_callback. These callback members should be of type std::function<void (rmw_offered_incompatible_qos_status_t &)> and std::function<void (rmw_requested_incompatible_qos_status_t &)> respectively.
    • Handle the above defined callbacks inside the constructor for Publisher and Subscription
  • ros2/demos

    • Add an example showcasing this feature in the quality_of_service_demo package; using both rclpy and rclcpp

DDS Implementations

  • ros2/rmw_fastrtps: Unfortunately, Fastrtps does not have this implemented. I have raised an issue regarding this here.

  • ros2/rmw_opensplice: Opensplice does have this feature implemented and the work on the rmw_implementation package would be:

    • There is a variable called mask_map which holds the mapping between rmw_event_type_t to its equivalent opensplice type. Add a mapping from RMW_EVENT_REQUESTED_INCOMPATIBLE_QOS -> DDS::REQUESTED_INCOMPATIBLE_QOS_STATUS and RMW_EVENT_OFFERED_INCOMPATIBLE_QOS -> DDS::OFFERED_INCOMPATIBLE_QOS_STATUS
    • Handle cases for DDS::OFFERED_INCOMPATIBLE_QOS_STATUS and DDS::REQUESTED_INCOMPATIBLE_QOS_STATUS in OpenSpliceStaticPublisherInfo::get_status and OpenSpliceStaticSubscriberInfo::get_status respectively.
  • ros2/rmw_connext: Research pending; but from this, I reckon that it is implemented.

List of PRs to be tracked towards this:

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions