From d11d9e10a4f014605d7951952ded356e88c2a6ab Mon Sep 17 00:00:00 2001 From: Jacob Perron Date: Fri, 19 Feb 2021 14:40:35 -0800 Subject: [PATCH 1/5] Add API for checking QoS profile compatibility Depends on https://github.com/ros2/rmw/pull/299 Signed-off-by: Jacob Perron --- .../include/rclcpp/exceptions/exceptions.hpp | 7 ++ rclcpp/include/rclcpp/qos.hpp | 33 ++++++++ rclcpp/src/rclcpp/qos.cpp | 43 +++++++++++ rclcpp/test/rclcpp/test_qos.cpp | 76 +++++++++++++++++++ 4 files changed, 159 insertions(+) diff --git a/rclcpp/include/rclcpp/exceptions/exceptions.hpp b/rclcpp/include/rclcpp/exceptions/exceptions.hpp index 630e2d846f..b99c9a45a0 100644 --- a/rclcpp/include/rclcpp/exceptions/exceptions.hpp +++ b/rclcpp/include/rclcpp/exceptions/exceptions.hpp @@ -289,6 +289,13 @@ class InvalidQosOverridesException : public std::runtime_error using std::runtime_error::runtime_error; }; +/// Thrown if a QoS compatibility check fails. +class QoSCheckCompatibleException : public std::runtime_error +{ + // Inherit constructors from runtime_error. + using std::runtime_error::runtime_error; +}; + } // namespace exceptions } // namespace rclcpp diff --git a/rclcpp/include/rclcpp/qos.hpp b/rclcpp/include/rclcpp/qos.hpp index edc3a58bbe..2c6cb6ba31 100644 --- a/rclcpp/include/rclcpp/qos.hpp +++ b/rclcpp/include/rclcpp/qos.hpp @@ -18,6 +18,7 @@ #include #include "rclcpp/duration.hpp" +#include "rclcpp/exceptions.hpp" #include "rclcpp/visibility_control.hpp" #include "rcl/logging_rosout.h" #include "rmw/incompatible_qos_events_statuses.h" @@ -62,6 +63,13 @@ enum class LivelinessPolicy Unknown = RMW_QOS_POLICY_LIVELINESS_UNKNOWN, }; +enum class QoSProfileCompatibility +{ + Ok = RMW_QOS_COMPATIBILITY_OK, + Warning = RMW_QOS_COMPATIBILITY_WARNING, + Error = RMW_QOS_COMPATIBILITY_ERROR, +}; + /// QoS initialization values, cannot be created directly, use KeepAll or KeepLast instead. struct RCLCPP_PUBLIC QoSInitialization { @@ -140,6 +148,31 @@ class RCLCPP_PUBLIC QoS const rmw_qos_profile_t & get_rmw_qos_profile() const; + /// Check if this QoS profile is compatible with another. + /** + * Two QoS profiles are compatible if a publisher and subcription + * using the QoS policies can communicate with each other. + * + * This QoS profile is assumed to be for a subscription. + * + * If there is an unknown policy value in either profile, then an exception is thrown. + * + * \param[in] publisher_qos: The QoS profile for a publisher. + * \param[out] reason: An explanation for any incompatibility. + * Set if the return value is QoSProfileCompatibility::Warning or + * QoSProfileCompatibility::Error. + * Not set if the QoS profiles are compatible. + * This parameter is optional. + * \return QoSProfileCompatibility::Ok if the QoS profiles are compatible, or + * \return QoSProfileCompatibility::Warning if there is a chance the QoS profiles are not + * compatible (this can happen if some policies are set ot "system default"), or + * \return QoSProfileCompatibility::Error if the QoS profiles are not compatible. + * \throws rclcpp::exceptions::QoSCheckCompatibilityException if any policy value is "unknown", + * or if an unexpected error occurs. + */ + QoSProfileCompatibility + compatible(const QoS & publisher_qos, std::string * reason = nullptr); + /// Set the history policy. QoS & history(HistoryPolicy history); diff --git a/rclcpp/src/rclcpp/qos.cpp b/rclcpp/src/rclcpp/qos.cpp index d0f47cd01e..8e72d7a516 100644 --- a/rclcpp/src/rclcpp/qos.cpp +++ b/rclcpp/src/rclcpp/qos.cpp @@ -16,7 +16,9 @@ #include +#include "rmw/error_handling.h" #include "rmw/types.h" +#include "rmw/qos_profiles.h" namespace rclcpp { @@ -92,6 +94,47 @@ QoS::get_rmw_qos_profile() const return rmw_qos_profile_; } +QoSProfileCompatibility +QoS::compatible(const QoS & publisher_qos, std::string * reason) +{ + rmw_qos_compatibility_type_t compatible; + const size_t reason_size = 2048u; + char reason_c_str[reason_size] = ""; + rmw_ret_t ret = rmw_qos_profile_check_compatible( + publisher_qos.get_rmw_qos_profile(), + this->rmw_qos_profile_, + &compatible, + reason_c_str, + reason_size); + if (RMW_RET_OK != ret) { + auto error_str = rmw_get_error_string().str; + rmw_reset_error(); + throw rclcpp::exceptions::QoSCheckCompatibleException{error_str}; + } + + if (reason) { + *reason = std::string(reason_c_str); + } + + QoSProfileCompatibility compatibility; + switch (compatible) { + case RMW_QOS_COMPATIBILITY_OK: + compatibility = QoSProfileCompatibility::Ok; + break; + case RMW_QOS_COMPATIBILITY_WARNING: + compatibility = QoSProfileCompatibility::Warning; + break; + case RMW_QOS_COMPATIBILITY_ERROR: + compatibility = QoSProfileCompatibility::Error; + break; + default: + throw rclcpp::exceptions::QoSCheckCompatibleException{ + "Unexpected compatibility value returned by rmw '" + std::to_string(compatible) + + "'"}; + } + return compatibility; +} + QoS & QoS::history(rmw_qos_history_policy_t history) { diff --git a/rclcpp/test/rclcpp/test_qos.cpp b/rclcpp/test/rclcpp/test_qos.cpp index 6786750ed4..581538b00e 100644 --- a/rclcpp/test/rclcpp/test_qos.cpp +++ b/rclcpp/test/rclcpp/test_qos.cpp @@ -14,6 +14,8 @@ #include +#include + #include "rclcpp/qos.hpp" #include "rmw/types.h" @@ -208,3 +210,77 @@ TEST(TestQoS, policy_name_from_kind) { "LIFESPAN_QOS_POLICY", rclcpp::qos_policy_name_from_kind(RMW_QOS_POLICY_LIFESPAN)); } + +TEST(TestQoS, compatible) +{ + // Compatible + { + rclcpp::SensorDataQoS pub_qos; + rclcpp::SensorDataQoS sub_qos; + rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos); + EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Ok); + } + + // Compatible with reason + { + rclcpp::SensorDataQoS pub_qos; + rclcpp::SensorDataQoS sub_qos; + std::string reason; + rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos, &reason); + EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Ok); + EXPECT_TRUE(reason.empty()); + } + + // Error on "unknown" in pub + { + rclcpp::QoS pub_qos(rclcpp::KeepLast(1), rmw_qos_profile_unknown); + rclcpp::QoS sub_qos(1); + EXPECT_THROW(sub_qos.compatible(pub_qos), rclcpp::exceptions::QoSCheckCompatibleException); + } + + // Error on "unknown" in sub + { + rclcpp::QoS pub_qos(1); + rclcpp::QoS sub_qos(rclcpp::KeepLast(1), rmw_qos_profile_unknown); + EXPECT_THROW(sub_qos.compatible(pub_qos), rclcpp::exceptions::QoSCheckCompatibleException); + } + + // Note, the following incompatible tests assume we are using a DDS middleware, + // and may not be valid for other RMWs. + + // Incompatible + { + rclcpp::QoS pub_qos = rclcpp::QoS(1).best_effort(); + rclcpp::QoS sub_qos = rclcpp::QoS(1).reliable(); + rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos); + EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Error); + } + + // Incompatible with reason + { + rclcpp::QoS pub_qos = rclcpp::QoS(1).best_effort(); + rclcpp::QoS sub_qos = rclcpp::QoS(1).reliable(); + std::string reason; + rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos, &reason); + EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Error); + EXPECT_FALSE(reason.empty()); + } + + // Warn of possible incompatibility + { + rclcpp::SystemDefaultsQoS pub_qos; + rclcpp::QoS sub_qos = rclcpp::QoS(1).reliable(); + rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos); + EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Warning); + } + + // Warn of possible incompatibility with reason + { + rclcpp::QoS pub_qos = rclcpp::QoS(1).best_effort(); + rclcpp::SystemDefaultsQoS sub_qos; + std::string reason; + rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos, &reason); + EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Warning); + EXPECT_FALSE(reason.empty()); + } +} From 92a1cef3478708ccf384bf8a0350c99ba6ab7531 Mon Sep 17 00:00:00 2001 From: Jacob Perron Date: Tue, 23 Feb 2021 18:12:39 -0800 Subject: [PATCH 2/5] Refactor as free function Returns a struct containing the compatibility enum value and string for the reason. Updated tests to reflect behavior changes upstream. Signed-off-by: Jacob Perron --- rclcpp/include/rclcpp/node.hpp | 2 +- rclcpp/include/rclcpp/qos.hpp | 82 ++++++++++++++++++++++----------- rclcpp/src/rclcpp/qos.cpp | 80 ++++++++++++++++---------------- rclcpp/test/rclcpp/test_qos.cpp | 72 ++++++++--------------------- 4 files changed, 115 insertions(+), 121 deletions(-) diff --git a/rclcpp/include/rclcpp/node.hpp b/rclcpp/include/rclcpp/node.hpp index f2247b59a1..2e40301eeb 100644 --- a/rclcpp/include/rclcpp/node.hpp +++ b/rclcpp/include/rclcpp/node.hpp @@ -163,7 +163,7 @@ class Node : public std::enable_shared_from_this * pub = node->create_publisher("chatter", QoS(10)); // implicitly KeepLast * pub = node->create_publisher("chatter", QoS(KeepLast(10))); * pub = node->create_publisher("chatter", QoS(KeepAll())); - * pub = node->create_publisher("chatter", QoS(1).best_effort().volatile()); + * pub = node->create_publisher("chatter", QoS(1).best_effort().durability_volatile()); * { * rclcpp::QoS custom_qos(KeepLast(10), rmw_qos_profile_sensor_data); * pub = node->create_publisher("chatter", custom_qos); diff --git a/rclcpp/include/rclcpp/qos.hpp b/rclcpp/include/rclcpp/qos.hpp index 2c6cb6ba31..c13338eb92 100644 --- a/rclcpp/include/rclcpp/qos.hpp +++ b/rclcpp/include/rclcpp/qos.hpp @@ -63,7 +63,7 @@ enum class LivelinessPolicy Unknown = RMW_QOS_POLICY_LIVELINESS_UNKNOWN, }; -enum class QoSProfileCompatibility +enum class QoSCompatibility { Ok = RMW_QOS_COMPATIBILITY_OK, Warning = RMW_QOS_COMPATIBILITY_WARNING, @@ -148,31 +148,6 @@ class RCLCPP_PUBLIC QoS const rmw_qos_profile_t & get_rmw_qos_profile() const; - /// Check if this QoS profile is compatible with another. - /** - * Two QoS profiles are compatible if a publisher and subcription - * using the QoS policies can communicate with each other. - * - * This QoS profile is assumed to be for a subscription. - * - * If there is an unknown policy value in either profile, then an exception is thrown. - * - * \param[in] publisher_qos: The QoS profile for a publisher. - * \param[out] reason: An explanation for any incompatibility. - * Set if the return value is QoSProfileCompatibility::Warning or - * QoSProfileCompatibility::Error. - * Not set if the QoS profiles are compatible. - * This parameter is optional. - * \return QoSProfileCompatibility::Ok if the QoS profiles are compatible, or - * \return QoSProfileCompatibility::Warning if there is a chance the QoS profiles are not - * compatible (this can happen if some policies are set ot "system default"), or - * \return QoSProfileCompatibility::Error if the QoS profiles are not compatible. - * \throws rclcpp::exceptions::QoSCheckCompatibilityException if any policy value is "unknown", - * or if an unexpected error occurs. - */ - QoSProfileCompatibility - compatible(const QoS & publisher_qos, std::string * reason = nullptr); - /// Set the history policy. QoS & history(HistoryPolicy history); @@ -306,6 +281,61 @@ bool operator==(const QoS & left, const QoS & right); RCLCPP_PUBLIC bool operator!=(const QoS & left, const QoS & right); +/// Result type for checking QoS compatibility +/** + * \see rclcpp::qos_check_compatible() + */ +struct RCLCPP_PUBLIC QoSCheckCompatibleResult +{ + /// Compatibility result. + QoSCompatibility compatibility; + + /// Reason for a (possible) incompatibility. + /** + * Set if compatiblity is QoSCompatibility::Warning or QoSCompatiblity::Error. + * Not set if the QoS profiles are compatible. + */ + std::string reason; +}; + +/// Check if two QoS profiles are compatible. +/** + * Two QoS profiles are compatible if a publisher and subcription + * using the QoS policies can communicate with each other. + * + * If any policies have value "system default" or "unknown" then it is possible that + * compatiblity cannot be determined. + * In this case, the value QoSCompatility::Warning is set as part of + * the returned structure. + * + * Example usage: + * + * ```cpp + * rclcpp::QoSCheckCompatibleResult result = rclcpp::qos_check_compatible( + * publisher_qos, subscription_qos); + * if (rclcpp::QoSCompatibility::Error != result.compatibility) { + * // QoS not compatible ... + * // result.reason contains info about the incompatibility + * } else if (rclcpp::QoSCompatibility::Warning != result.compatibility) { + * // QoS may not be compatible ... + * // result.reason contains info about the possible incompatibility + * } + * ``` + * + * \param[in] publisher_qos: The QoS profile for a publisher. + * \param[in] subscription_qos: The QoS profile for a subscription. + * \return Struct with compatiblity set to QoSCompatibility::Ok if the QoS profiles are + * compatible, or + * \return Struct with compatibility set to QoSCompatibility::Warning if there is a chance + * the QoS profiles are not compatible, or + * \return Struct with compatibility set to QoSCompatibility::Error if the QoS profiles are + * not compatible. + * \throws rclcpp::exceptions::QoSCheckCompatibilityException if an unexpected error occurs. + */ +RCLCPP_PUBLIC +QoSCheckCompatibleResult +qos_check_compatible(const QoS & publisher_qos, const QoS & subscription_qos); + /** * Clock QoS class * - History: Keep last, diff --git a/rclcpp/src/rclcpp/qos.cpp b/rclcpp/src/rclcpp/qos.cpp index 8e72d7a516..2b6f4c63d3 100644 --- a/rclcpp/src/rclcpp/qos.cpp +++ b/rclcpp/src/rclcpp/qos.cpp @@ -94,47 +94,6 @@ QoS::get_rmw_qos_profile() const return rmw_qos_profile_; } -QoSProfileCompatibility -QoS::compatible(const QoS & publisher_qos, std::string * reason) -{ - rmw_qos_compatibility_type_t compatible; - const size_t reason_size = 2048u; - char reason_c_str[reason_size] = ""; - rmw_ret_t ret = rmw_qos_profile_check_compatible( - publisher_qos.get_rmw_qos_profile(), - this->rmw_qos_profile_, - &compatible, - reason_c_str, - reason_size); - if (RMW_RET_OK != ret) { - auto error_str = rmw_get_error_string().str; - rmw_reset_error(); - throw rclcpp::exceptions::QoSCheckCompatibleException{error_str}; - } - - if (reason) { - *reason = std::string(reason_c_str); - } - - QoSProfileCompatibility compatibility; - switch (compatible) { - case RMW_QOS_COMPATIBILITY_OK: - compatibility = QoSProfileCompatibility::Ok; - break; - case RMW_QOS_COMPATIBILITY_WARNING: - compatibility = QoSProfileCompatibility::Warning; - break; - case RMW_QOS_COMPATIBILITY_ERROR: - compatibility = QoSProfileCompatibility::Error; - break; - default: - throw rclcpp::exceptions::QoSCheckCompatibleException{ - "Unexpected compatibility value returned by rmw '" + std::to_string(compatible) + - "'"}; - } - return compatibility; -} - QoS & QoS::history(rmw_qos_history_policy_t history) { @@ -352,6 +311,45 @@ bool operator!=(const QoS & left, const QoS & right) return !(left == right); } +QoSCheckCompatibleResult +qos_check_compatible(const QoS & publisher_qos, const QoS & subscription_qos) +{ + rmw_qos_compatibility_type_t compatible; + const size_t reason_size = 2048u; + char reason_c_str[reason_size] = ""; + rmw_ret_t ret = rmw_qos_profile_check_compatible( + publisher_qos.get_rmw_qos_profile(), + subscription_qos.get_rmw_qos_profile(), + &compatible, + reason_c_str, + reason_size); + if (RMW_RET_OK != ret) { + auto error_str = rmw_get_error_string().str; + rmw_reset_error(); + throw rclcpp::exceptions::QoSCheckCompatibleException{error_str}; + } + + QoSCheckCompatibleResult result; + result.reason = std::string(reason_c_str); + + switch (compatible) { + case RMW_QOS_COMPATIBILITY_OK: + result.compatibility = QoSCompatibility::Ok; + break; + case RMW_QOS_COMPATIBILITY_WARNING: + result.compatibility = QoSCompatibility::Warning; + break; + case RMW_QOS_COMPATIBILITY_ERROR: + result.compatibility = QoSCompatibility::Error; + break; + default: + throw rclcpp::exceptions::QoSCheckCompatibleException{ + "Unexpected compatibility value returned by rmw '" + std::to_string(compatible) + + "'"}; + } + return result; +} + ClockQoS::ClockQoS(const QoSInitialization & qos_initialization) // Using `rmw_qos_profile_sensor_data` intentionally. // It's best effort and `qos_initialization` is overriding the depth to 1. diff --git a/rclcpp/test/rclcpp/test_qos.cpp b/rclcpp/test/rclcpp/test_qos.cpp index 581538b00e..47d1d10b07 100644 --- a/rclcpp/test/rclcpp/test_qos.cpp +++ b/rclcpp/test/rclcpp/test_qos.cpp @@ -211,76 +211,42 @@ TEST(TestQoS, policy_name_from_kind) { rclcpp::qos_policy_name_from_kind(RMW_QOS_POLICY_LIFESPAN)); } -TEST(TestQoS, compatible) +TEST(TestQoS, qos_check_compatible) { // Compatible { - rclcpp::SensorDataQoS pub_qos; - rclcpp::SensorDataQoS sub_qos; - rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos); - EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Ok); - } - - // Compatible with reason - { - rclcpp::SensorDataQoS pub_qos; - rclcpp::SensorDataQoS sub_qos; - std::string reason; - rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos, &reason); - EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Ok); - EXPECT_TRUE(reason.empty()); - } - - // Error on "unknown" in pub - { - rclcpp::QoS pub_qos(rclcpp::KeepLast(1), rmw_qos_profile_unknown); - rclcpp::QoS sub_qos(1); - EXPECT_THROW(sub_qos.compatible(pub_qos), rclcpp::exceptions::QoSCheckCompatibleException); - } - - // Error on "unknown" in sub - { - rclcpp::QoS pub_qos(1); - rclcpp::QoS sub_qos(rclcpp::KeepLast(1), rmw_qos_profile_unknown); - EXPECT_THROW(sub_qos.compatible(pub_qos), rclcpp::exceptions::QoSCheckCompatibleException); + rclcpp::QoS qos = rclcpp::QoS(1) + .reliable() + .durability_volatile() + .deadline(rclcpp::Duration(1, 0u)) + .lifespan(rclcpp::Duration(1, 0u)) + .liveliness(rclcpp::LivelinessPolicy::Automatic) + .liveliness_lease_duration(rclcpp::Duration(1, 0u)); + rclcpp::QoSCheckCompatibleResult ret = rclcpp::qos_check_compatible(qos, qos); + EXPECT_EQ(ret.compatibility, rclcpp::QoSCompatibility::Ok); + EXPECT_EQ(ret.reason, std::string("")); } // Note, the following incompatible tests assume we are using a DDS middleware, // and may not be valid for other RMWs. + // TODO(jacobperron): programmatically check if current RMW is one of the officially + // supported DDS middlewares before running the following tests // Incompatible { rclcpp::QoS pub_qos = rclcpp::QoS(1).best_effort(); rclcpp::QoS sub_qos = rclcpp::QoS(1).reliable(); - rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos); - EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Error); - } - - // Incompatible with reason - { - rclcpp::QoS pub_qos = rclcpp::QoS(1).best_effort(); - rclcpp::QoS sub_qos = rclcpp::QoS(1).reliable(); - std::string reason; - rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos, &reason); - EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Error); - EXPECT_FALSE(reason.empty()); + rclcpp::QoSCheckCompatibleResult ret = rclcpp::qos_check_compatible(pub_qos, sub_qos); + EXPECT_EQ(ret.compatibility, rclcpp::QoSCompatibility::Error); + EXPECT_FALSE(ret.reason.empty()); } // Warn of possible incompatibility { rclcpp::SystemDefaultsQoS pub_qos; rclcpp::QoS sub_qos = rclcpp::QoS(1).reliable(); - rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos); - EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Warning); - } - - // Warn of possible incompatibility with reason - { - rclcpp::QoS pub_qos = rclcpp::QoS(1).best_effort(); - rclcpp::SystemDefaultsQoS sub_qos; - std::string reason; - rclcpp::QoSProfileCompatibility ret = sub_qos.compatible(pub_qos, &reason); - EXPECT_EQ(ret, rclcpp::QoSProfileCompatibility::Warning); - EXPECT_FALSE(reason.empty()); + rclcpp::QoSCheckCompatibleResult ret = rclcpp::qos_check_compatible(pub_qos, sub_qos); + EXPECT_EQ(ret.compatibility, rclcpp::QoSCompatibility::Warning); + EXPECT_FALSE(ret.reason.empty()); } } From ac8d296565f018a105fbd08810717b1d66fa8bae Mon Sep 17 00:00:00 2001 From: Jacob Perron Date: Wed, 24 Feb 2021 09:12:27 -0800 Subject: [PATCH 3/5] undo unrelated doc change Signed-off-by: Jacob Perron --- rclcpp/include/rclcpp/node.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rclcpp/include/rclcpp/node.hpp b/rclcpp/include/rclcpp/node.hpp index 2e40301eeb..f2247b59a1 100644 --- a/rclcpp/include/rclcpp/node.hpp +++ b/rclcpp/include/rclcpp/node.hpp @@ -163,7 +163,7 @@ class Node : public std::enable_shared_from_this * pub = node->create_publisher("chatter", QoS(10)); // implicitly KeepLast * pub = node->create_publisher("chatter", QoS(KeepLast(10))); * pub = node->create_publisher("chatter", QoS(KeepAll())); - * pub = node->create_publisher("chatter", QoS(1).best_effort().durability_volatile()); + * pub = node->create_publisher("chatter", QoS(1).best_effort().volatile()); * { * rclcpp::QoS custom_qos(KeepLast(10), rmw_qos_profile_sensor_data); * pub = node->create_publisher("chatter", custom_qos); From 2855bc64815b1056f0ea76b3f1ce23ecad6790cd Mon Sep 17 00:00:00 2001 From: Jacob Perron Date: Mon, 22 Mar 2021 15:03:48 -0700 Subject: [PATCH 4/5] Fix dangling reference warning Signed-off-by: Jacob Perron --- rclcpp/src/rclcpp/qos.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rclcpp/src/rclcpp/qos.cpp b/rclcpp/src/rclcpp/qos.cpp index 2b6f4c63d3..8b912de07f 100644 --- a/rclcpp/src/rclcpp/qos.cpp +++ b/rclcpp/src/rclcpp/qos.cpp @@ -324,7 +324,7 @@ qos_check_compatible(const QoS & publisher_qos, const QoS & subscription_qos) reason_c_str, reason_size); if (RMW_RET_OK != ret) { - auto error_str = rmw_get_error_string().str; + std::string error_str(rmw_get_error_string().str); rmw_reset_error(); throw rclcpp::exceptions::QoSCheckCompatibleException{error_str}; } From 046dc6ad509e9391fe8c747d2a20c19f0f921456 Mon Sep 17 00:00:00 2001 From: Jacob Perron Date: Mon, 22 Mar 2021 15:09:32 -0700 Subject: [PATCH 5/5] Remove visibility macro It is not required as the struct has no methods. Signed-off-by: Jacob Perron --- rclcpp/include/rclcpp/qos.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rclcpp/include/rclcpp/qos.hpp b/rclcpp/include/rclcpp/qos.hpp index c13338eb92..4160360756 100644 --- a/rclcpp/include/rclcpp/qos.hpp +++ b/rclcpp/include/rclcpp/qos.hpp @@ -285,7 +285,7 @@ bool operator!=(const QoS & left, const QoS & right); /** * \see rclcpp::qos_check_compatible() */ -struct RCLCPP_PUBLIC QoSCheckCompatibleResult +struct QoSCheckCompatibleResult { /// Compatibility result. QoSCompatibility compatibility;