diff --git a/rclcpp/include/rclcpp/publisher_base.hpp b/rclcpp/include/rclcpp/publisher_base.hpp index 6327a99443..2f65b21af9 100644 --- a/rclcpp/include/rclcpp/publisher_base.hpp +++ b/rclcpp/include/rclcpp/publisher_base.hpp @@ -85,6 +85,21 @@ class PublisherBase : public std::enable_shared_from_this RCLCPP_PUBLIC virtual ~PublisherBase(); + /// Check if a publisher event type is supported by the active RMW implementation. + /** + * This API allows application code to introspect at runtime whether a + * particular publisher event type is supported by the currently loaded + * RMW implementation, enabling portable code that adapts gracefully + * when switching between RMW implementations. + * + * \param[in] event_type the publisher event type to check + * \return `true` if the event type is supported, `false` otherwise + */ + RCLCPP_PUBLIC + static + bool + event_type_is_supported(const rcl_publisher_event_type_t event_type); + /// Add event handlers for passed in event_callbacks. RCLCPP_PUBLIC void diff --git a/rclcpp/include/rclcpp/subscription_base.hpp b/rclcpp/include/rclcpp/subscription_base.hpp index 178d677eb1..ccf5cca1d5 100644 --- a/rclcpp/include/rclcpp/subscription_base.hpp +++ b/rclcpp/include/rclcpp/subscription_base.hpp @@ -117,6 +117,21 @@ class SubscriptionBase : public std::enable_shared_from_this RCLCPP_PUBLIC virtual ~SubscriptionBase(); + /// Check if a subscription event type is supported by the active RMW implementation. + /** + * This API allows application code to introspect at runtime whether a + * particular subscription event type is supported by the currently loaded + * RMW implementation, enabling portable code that adapts gracefully + * when switching between RMW implementations. + * + * \param[in] event_type the subscription event type to check + * \return `true` if the event type is supported, `false` otherwise + */ + RCLCPP_PUBLIC + static + bool + event_type_is_supported(const rcl_subscription_event_type_t event_type); + /// Add event handlers for passed in event_callbacks. RCLCPP_PUBLIC void diff --git a/rclcpp/src/rclcpp/publisher_base.cpp b/rclcpp/src/rclcpp/publisher_base.cpp index 01d1384b33..fa92180e46 100644 --- a/rclcpp/src/rclcpp/publisher_base.cpp +++ b/rclcpp/src/rclcpp/publisher_base.cpp @@ -25,6 +25,7 @@ #include #include +#include "rcl/event.h" #include "rcutils/logging_macros.h" #include "rmw/impl/cpp/demangle.hpp" @@ -131,6 +132,12 @@ PublisherBase::get_topic_name() const return rcl_publisher_get_topic_name(publisher_handle_.get()); } +bool +PublisherBase::event_type_is_supported(const rcl_publisher_event_type_t event_type) +{ + return rcl_publisher_event_type_is_supported(event_type); +} + void PublisherBase::bind_event_callbacks( const PublisherEventCallbacks & event_callbacks, bool use_default_callbacks) diff --git a/rclcpp/src/rclcpp/subscription_base.cpp b/rclcpp/src/rclcpp/subscription_base.cpp index 35188477d2..d286358cfb 100644 --- a/rclcpp/src/rclcpp/subscription_base.cpp +++ b/rclcpp/src/rclcpp/subscription_base.cpp @@ -30,6 +30,7 @@ #include "rclcpp/node_interfaces/node_base_interface.hpp" #include "rclcpp/event_handler.hpp" +#include "rcl/event.h" #include "rmw/error_handling.h" #include "rmw/rmw.h" @@ -108,6 +109,12 @@ SubscriptionBase::~SubscriptionBase() ipm->remove_subscription(intra_process_subscription_id_); } +bool +SubscriptionBase::event_type_is_supported(const rcl_subscription_event_type_t event_type) +{ + return rcl_subscription_event_type_is_supported(event_type); +} + void SubscriptionBase::bind_event_callbacks( const SubscriptionEventCallbacks & event_callbacks, bool use_default_callbacks) diff --git a/rclcpp/test/rclcpp/test_qos_event.cpp b/rclcpp/test/rclcpp/test_qos_event.cpp index 1b0d7a328c..5cfa6b4d60 100644 --- a/rclcpp/test/rclcpp/test_qos_event.cpp +++ b/rclcpp/test/rclcpp/test_qos_event.cpp @@ -22,6 +22,7 @@ #include #include "rclcpp/rclcpp.hpp" +#include "rcl/event.h" #include "rcutils/logging.h" #include "rmw/rmw.h" #include "test_msgs/msg/empty.hpp" @@ -73,8 +74,8 @@ TEST_F(TestQosEvent, test_publisher_constructor) auto publisher = node->create_publisher( topic_name, 10, options); - if (rmw_event_type_is_supported(RMW_EVENT_OFFERED_DEADLINE_MISSED) && - rmw_event_type_is_supported(RMW_EVENT_LIVELINESS_LOST)) + if (rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED) && + rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_LIVELINESS_LOST)) { // options arg with one of the callbacks options.event_callbacks.deadline_callback = @@ -123,8 +124,9 @@ TEST_F(TestQosEvent, test_subscription_constructor) auto subscription = node->create_subscription( topic_name, 10, message_callback, options); - if (rmw_event_type_is_supported(RMW_EVENT_REQUESTED_DEADLINE_MISSED) && - rmw_event_type_is_supported(RMW_EVENT_LIVELINESS_CHANGED)) + if (rclcpp::SubscriptionBase::event_type_is_supported( + RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED) && + rclcpp::SubscriptionBase::event_type_is_supported(RCL_SUBSCRIPTION_LIVELINESS_CHANGED)) { // options arg with one of the callbacks options.event_callbacks.deadline_callback = @@ -239,7 +241,7 @@ TEST_F(TestQosEvent, construct_destruct_rcl_error) { // This callback requires some type of parameter, but it could be anything auto callback = [](int) {}; const rcl_publisher_event_type_t event_type = - !rmw_event_type_is_supported(RMW_EVENT_OFFERED_DEADLINE_MISSED) ? + !rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED) ? RCL_PUBLISHER_MATCHED : RCL_PUBLISHER_OFFERED_DEADLINE_MISSED; { @@ -277,7 +279,7 @@ TEST_F(TestQosEvent, construct_destruct_rcl_error) { } TEST_F(TestQosEvent, execute) { - if (!rmw_event_type_is_supported(RMW_EVENT_OFFERED_DEADLINE_MISSED)) { + if (!rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED)) { GTEST_SKIP(); } @@ -314,7 +316,7 @@ TEST_F(TestQosEvent, add_to_wait_set) { auto callback = [](int) {}; const rcl_publisher_event_type_t event_type = - !rmw_event_type_is_supported(RMW_EVENT_OFFERED_DEADLINE_MISSED) ? + !rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED) ? RCL_PUBLISHER_MATCHED : RCL_PUBLISHER_OFFERED_DEADLINE_MISSED; rclcpp::EventHandler handler( @@ -338,8 +340,9 @@ TEST_F(TestQosEvent, add_to_wait_set) { TEST_F(TestQosEvent, test_on_new_event_callback) { - if (!rmw_event_type_is_supported(RMW_EVENT_REQUESTED_DEADLINE_MISSED) || - !rmw_event_type_is_supported(RMW_EVENT_OFFERED_DEADLINE_MISSED)) + if (!rclcpp::SubscriptionBase::event_type_is_supported( + RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED) || + !rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED)) { GTEST_SKIP(); } @@ -389,8 +392,8 @@ TEST_F(TestQosEvent, test_invalid_on_new_event_callback) auto sub = node->create_subscription(topic_name, 10, message_callback); auto dummy_cb = [](size_t count_events) {(void)count_events;}; - if (rmw_event_type_is_supported(RMW_EVENT_OFFERED_DEADLINE_MISSED) && - rmw_event_type_is_supported(RMW_EVENT_LIVELINESS_LOST)) + if (rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED) && + rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_LIVELINESS_LOST)) { EXPECT_NO_THROW( pub->set_on_new_qos_event_callback(dummy_cb, RCL_PUBLISHER_OFFERED_DEADLINE_MISSED)); @@ -416,8 +419,9 @@ TEST_F(TestQosEvent, test_invalid_on_new_event_callback) EXPECT_NO_THROW( pub->clear_on_new_qos_event_callback(RCL_PUBLISHER_MATCHED)); - if (rmw_event_type_is_supported(RMW_EVENT_REQUESTED_DEADLINE_MISSED) && - rmw_event_type_is_supported(RMW_EVENT_LIVELINESS_CHANGED)) + if (rclcpp::SubscriptionBase::event_type_is_supported( + RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED) && + rclcpp::SubscriptionBase::event_type_is_supported(RCL_SUBSCRIPTION_LIVELINESS_CHANGED)) { EXPECT_NO_THROW( sub->set_on_new_qos_event_callback(dummy_cb, RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED)); @@ -443,8 +447,9 @@ TEST_F(TestQosEvent, test_invalid_on_new_event_callback) EXPECT_NO_THROW( sub->clear_on_new_qos_event_callback(RCL_SUBSCRIPTION_MATCHED)); - if (rmw_event_type_is_supported(RMW_EVENT_REQUESTED_DEADLINE_MISSED) && - rmw_event_type_is_supported(RMW_EVENT_OFFERED_DEADLINE_MISSED)) + if (rclcpp::SubscriptionBase::event_type_is_supported( + RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED) && + rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED)) { std::function invalid_cb; @@ -639,3 +644,54 @@ TEST_F(TestQosEvent, test_sub_matched_event_by_option_event_callback) } ex.spin_until_future_complete(prom.get_future(), timeout); } + +/* + * Test rclcpp::PublisherBase::event_type_is_supported + */ +TEST_F(TestQosEvent, test_publisher_event_type_is_supported) +{ + // Verify rclcpp results are consistent with the underlying rcl results + EXPECT_EQ( + rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED), + rcl_publisher_event_type_is_supported(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED)); + EXPECT_EQ( + rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_LIVELINESS_LOST), + rcl_publisher_event_type_is_supported(RCL_PUBLISHER_LIVELINESS_LOST)); + EXPECT_EQ( + rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS), + rcl_publisher_event_type_is_supported(RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS)); + EXPECT_EQ( + rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_INCOMPATIBLE_TYPE), + rcl_publisher_event_type_is_supported(RCL_PUBLISHER_INCOMPATIBLE_TYPE)); + EXPECT_EQ( + rclcpp::PublisherBase::event_type_is_supported(RCL_PUBLISHER_MATCHED), + rcl_publisher_event_type_is_supported(RCL_PUBLISHER_MATCHED)); +} + +/* + * Test rclcpp::SubscriptionBase::event_type_is_supported + */ +TEST_F(TestQosEvent, test_subscription_event_type_is_supported) +{ + // Verify rclcpp results are consistent with the underlying rcl results + EXPECT_EQ( + rclcpp::SubscriptionBase::event_type_is_supported( + RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED), + rcl_subscription_event_type_is_supported(RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED)); + EXPECT_EQ( + rclcpp::SubscriptionBase::event_type_is_supported(RCL_SUBSCRIPTION_LIVELINESS_CHANGED), + rcl_subscription_event_type_is_supported(RCL_SUBSCRIPTION_LIVELINESS_CHANGED)); + EXPECT_EQ( + rclcpp::SubscriptionBase::event_type_is_supported( + RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS), + rcl_subscription_event_type_is_supported(RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS)); + EXPECT_EQ( + rclcpp::SubscriptionBase::event_type_is_supported(RCL_SUBSCRIPTION_MESSAGE_LOST), + rcl_subscription_event_type_is_supported(RCL_SUBSCRIPTION_MESSAGE_LOST)); + EXPECT_EQ( + rclcpp::SubscriptionBase::event_type_is_supported(RCL_SUBSCRIPTION_INCOMPATIBLE_TYPE), + rcl_subscription_event_type_is_supported(RCL_SUBSCRIPTION_INCOMPATIBLE_TYPE)); + EXPECT_EQ( + rclcpp::SubscriptionBase::event_type_is_supported(RCL_SUBSCRIPTION_MATCHED), + rcl_subscription_event_type_is_supported(RCL_SUBSCRIPTION_MATCHED)); +}