diff --git a/README.md b/README.md index da7b591e..14dac861 100644 --- a/README.md +++ b/README.md @@ -140,11 +140,12 @@ variables. - [RMW_CONNEXT_CYCLONE_COMPATIBILITY_MODE](#RMW_CONNEXT_CYCLONE_COMPATIBILITY_MODE) - [RMW_CONNEXT_DISABLE_FAST_ENDPOINT_DISCOVERY](#RMW_CONNEXT_DISABLE_FAST_ENDPOINT_DISCOVERY) -- [RMW_CONNEXT_USE_DEFAULT_PUBLISH_MODE](#RMW_CONNEXT_USE_DEFAULT_PUBLISH_MODE) +- [RMW_CONNEXT_ENDPOINT_QOS_OVERRIDE_POLICY](#RMW_CONNEXT_ENDPOINT_QOS_OVERRIDE_POLICY) - [RMW_CONNEXT_INITIAL_PEERS](#RMW_CONNEXT_INITIAL_PEERS) - [RMW_CONNEXT_LEGACY_RMW_COMPATIBILITY_MODE](#RMW_CONNEXT_LEGACY_RMW_COMPATIBILITY_MODE) - [RMW_CONNEXT_REQUEST_REPLY_MAPPING](#RMW_CONNEXT_REQUEST_REPLY_MAPPING) - [RMW_CONNEXT_UDP_INTERFACE](#RMW_CONNEXT_UDP_INTERFACE) +- [RMW_CONNEXT_USE_DEFAULT_PUBLISH_MODE](#RMW_CONNEXT_USE_DEFAULT_PUBLISH_MODE) ### RMW_CONNEXT_CYCLONE_COMPATIBILITY_MODE @@ -176,17 +177,24 @@ Variable `RMW_CONNEXT_DISABLE_FAST_ENDPOINT_DISCOVERY` may be used to disable these automatic optimizations, and to leave the DomainParticipant's QoS to its defaults. -### RMW_CONNEXT_USE_DEFAULT_PUBLISH_MODE +### RMW_CONNEXT_ENDPOINT_QOS_OVERRIDE_POLICY -`rmw_connextdds` will always set `DDS_DataWriterQos::publish_mode::kind` of -any DataWriter it creates to `DDS_ASYNCHRONOUS_PUBLISH_MODE_QOS`, in order to -enable out of the box support for "large data". +When this variable is not set or set to `always`, the qos settings specified in the default profile will be used and the ros qos profile will be applied on top of it. +You can use topic filters in XML profile files to have different defaults for different topics, but you have to use the mangled topic names (see [ROS topic mangling conventions](#ros-topic-mangling-conventions)). -This behavior might not be always desirable, and it can be disabled by setting -`RMW_CONNEXT_USE_DEFAULT_PUBLISH_MODE` to a non-empty value. +In case this variable is set to `never`, the qos settings will be loaded from the default profile as before but the ros qos profile will be ignored. +Be aware of configuring the qos of rcl topics (rt/rosout, rt/parameter_events, etc) and the rmw internal topic `ros_discovery_info` correctly. -This variable is not used by `rmw_connextddsmicro`, since it doesn't -automatically override `DDS_DataWriterQos::publish_mode::kind`. +This variable can also be set to `dds_topics: `, e.g.: `dds_topics: rt/my_topic|rt/my_ns/another_topic`. +In that case, qos settings for topics matching the provided regex will be loaded in the same way as the `never` policy, and the ones that don't match will be loaded in the same way as the `always` policy. + +#### ROS topic mangling conventions + +ROS mangles topic names in the following way: + +- Topics are prefixed with `rt`. e.g.: `/my/fully/qualified/ros/topic` is converted to `rt/my/fully/qualified/ros/topic`. +- The service request topics are prefixed with `rq` and suffixed with `Request`. e.g.: `/my/fully/qualified/ros/service` request topic is `rq/my/fully/qualified/ros/serviceRequest`. +- The service response topics are prefixed with `rr` and suffixed with `Response`. e.g.: `/my/fully/qualified/ros/service` response topic is `rr/my/fully/qualified/ros/serviceResponse`. ### RMW_CONNEXT_INITIAL_PEERS @@ -309,3 +317,15 @@ RMW_CONNEXT_UDP_INTERFACE=eth0 \ ``` This variable is not used by `rmw_connextdds`. + +### RMW_CONNEXT_USE_DEFAULT_PUBLISH_MODE + +`rmw_connextdds` will always set `DDS_DataWriterQos::publish_mode::kind` of +any DataWriter it creates to `DDS_ASYNCHRONOUS_PUBLISH_MODE_QOS`, in order to +enable out of the box support for "large data". + +This behavior might not be always desirable, and it can be disabled by setting +`RMW_CONNEXT_USE_DEFAULT_PUBLISH_MODE` to a non-empty value. + +This variable is not used by `rmw_connextddsmicro`, since it doesn't +automatically override `DDS_DataWriterQos::publish_mode::kind`. diff --git a/rmw_connextdds_common/include/rmw_connextdds/context.hpp b/rmw_connextdds_common/include/rmw_connextdds/context.hpp index 90f65259..3763d0b9 100644 --- a/rmw_connextdds_common/include/rmw_connextdds/context.hpp +++ b/rmw_connextdds_common/include/rmw_connextdds/context.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "rmw_connextdds/dds_api.hpp" @@ -92,7 +93,6 @@ struct rmw_context_impl_t bool localhost_only; /* Global configuration for QoS profiles */ - std::string qos_library; std::string qos_ctx_name; std::string qos_ctx_namespace; bool use_default_publish_mode; @@ -104,6 +104,24 @@ struct rmw_context_impl_t #if RMW_CONNEXT_FAST_ENDPOINT_DISCOVERY bool fast_endp_discovery{true}; #endif /* RMW_CONNEXT_FAST_ENDPOINT_DISCOVERY */ + + enum class endpoint_qos_override_policy_t + { + // Use default QoS policy got from the DDS qos profile file applying topic filters + // and apply the ROS settings on top of it. + Always, + // Use default QoS policy got from the DDS qos profile file applying topic filters + // without any changes for the topics that matches the provided regex expressions. + // Apply the ROS settings on top of it for the ones that doesn't match. + DDSTopics, + // Use default QoS policy got from the DDS qos profile file applying topic filters + // without any changes. + Never, + }; + + endpoint_qos_override_policy_t endpoint_qos_override_policy; + std::regex endpoint_qos_override_policy_topics_regex; + /* Participant reference count*/ size_t node_count{0}; std::mutex initialization_mutex; diff --git a/rmw_connextdds_common/include/rmw_connextdds/dds_api_rtime.hpp b/rmw_connextdds_common/include/rmw_connextdds/dds_api_rtime.hpp index dfaef450..44c4ef0f 100644 --- a/rmw_connextdds_common/include/rmw_connextdds/dds_api_rtime.hpp +++ b/rmw_connextdds_common/include/rmw_connextdds/dds_api_rtime.hpp @@ -35,6 +35,10 @@ typedef DDS_UntypedSampleSeq RMW_Connext_UntypedSampleSeq; (DDS_PropertySeq_assert_property(&(p_)->value, (n_), (v_), (pr_)) ? \ DDS_RETCODE_OK : DDS_RETCODE_ERROR) +#define DDS_DomainParticipantFactory_get_qos_profiles(dpf, profiles, library_name) DDS_RETCODE_OK + +#define DDS_DomainParticipantFactory_get_qos_profile_libraries(dpf, libraries) DDS_RETCODE_OK + // Forward declaration for DDS_LifespanQosPolicy, since it is not supported by Micro. struct DDS_LifespanQosPolicy; diff --git a/rmw_connextdds_common/include/rmw_connextdds/rmw_impl.hpp b/rmw_connextdds_common/include/rmw_connextdds/rmw_impl.hpp index 86cb1315..527a03e9 100644 --- a/rmw_connextdds_common/include/rmw_connextdds/rmw_impl.hpp +++ b/rmw_connextdds_common/include/rmw_connextdds/rmw_impl.hpp @@ -1486,37 +1486,6 @@ rmw_ret_t #endif /* RMW_CONNEXT_HAVE_LIFESPAN_QOS */ rmw_qos_profile_t * const qos_policies); -rmw_ret_t -rmw_connextdds_list_context_qos_profiles( - rmw_context_impl_t * const ctx, - std::vector & profiles); - -rmw_ret_t -rmw_connextdds_list_publisher_qos_profiles( - rmw_context_impl_t * const ctx, - const char * const topic_name, - std::vector & profiles); - -rmw_ret_t -rmw_connextdds_list_subscription_qos_profiles( - rmw_context_impl_t * const ctx, - const char * const topic_name, - std::vector & profiles); - -rmw_ret_t -rmw_connextdds_list_client_qos_profiles( - rmw_context_impl_t * const ctx, - const char * const service_name, - std::vector & req_profiles, - std::vector & rep_profiles); - -rmw_ret_t -rmw_connextdds_list_service_qos_profiles( - rmw_context_impl_t * const ctx, - const char * const service_name, - std::vector & req_profiles, - std::vector & rep_profiles); - /****************************************************************************** * Security Helpers ******************************************************************************/ diff --git a/rmw_connextdds_common/include/rmw_connextdds/static_config.hpp b/rmw_connextdds_common/include/rmw_connextdds/static_config.hpp index 7e89b4db..627a7445 100644 --- a/rmw_connextdds_common/include/rmw_connextdds/static_config.hpp +++ b/rmw_connextdds_common/include/rmw_connextdds/static_config.hpp @@ -87,6 +87,11 @@ #define RMW_CONNEXT_ENV_SECURITY_LOG_VERBOSITY "ROS_SECURITY_LOG_VERBOSITY" #endif /* RMW_CONNEXT_ENV_SECURITY_LOG_VERBOSITY */ +#ifndef RMW_CONNEXT_ENV_ENDPOINT_QOS_OVERRIDE_POLICY +#define RMW_CONNEXT_ENV_ENDPOINT_QOS_OVERRIDE_POLICY "RMW_CONNEXT_ENDPOINT_QOS_OVERRIDE_POLICY" +#endif /* RMW_CONNEXT_ENV_ALLOW_TOPIC_QOS_PROFILES */ + + /****************************************************************************** * DDS Implementation * Select the DDS implementation used to build the RMW library. diff --git a/rmw_connextdds_common/src/common/rmw_context.cpp b/rmw_connextdds_common/src/common/rmw_context.cpp index 2993fa10..08cb5449 100644 --- a/rmw_connextdds_common/src/common/rmw_context.cpp +++ b/rmw_connextdds_common/src/common/rmw_context.cpp @@ -181,13 +181,58 @@ rmw_context_impl_t::initialize_participant(const bool localhost_only) { RMW_CONNEXT_LOG_DEBUG("initializing DDS DomainParticipant") + this->localhost_only = localhost_only; + + /* Lookup RMW_CONNEXT_ENV_ALLOW_TOPIC_QOS_PROFILES env variable.*/ + const char * endpoint_qos_policy = nullptr; + const char * lookup_rc = rcutils_get_env( + RMW_CONNEXT_ENV_ENDPOINT_QOS_OVERRIDE_POLICY, &endpoint_qos_policy); + + if (nullptr != lookup_rc || nullptr == endpoint_qos_policy) { + RMW_CONNEXT_LOG_ERROR_A_SET( + "failed to lookup from environment: " + "var=%s, " + "rc=%s ", + RMW_CONNEXT_ENV_ENDPOINT_QOS_OVERRIDE_POLICY, + lookup_rc) + return RMW_RET_ERROR; + } + + this->endpoint_qos_override_policy = rmw_context_impl_t::endpoint_qos_override_policy_t::Always; + const char dds_topic_policy_prefix[] = "dds_topics: "; + const char never_policy[] = "never"; + const char always_policy[] = "always"; + if ( + 0 == strncmp( + endpoint_qos_policy, dds_topic_policy_prefix, sizeof(dds_topic_policy_prefix) - 1u)) + { + this->endpoint_qos_override_policy = + rmw_context_impl_t::endpoint_qos_override_policy_t::DDSTopics; + try { + this->endpoint_qos_override_policy_topics_regex = &endpoint_qos_policy[sizeof(dds_topic_policy_prefix) - 1u]; + } catch (std::regex_error & err) { + RMW_CONNEXT_LOG_ERROR_A_SET( + "regex expression provided in {%s} environment variable is invalid: %s\n", + RMW_CONNEXT_ENV_ENDPOINT_QOS_OVERRIDE_POLICY, + err.what()); + return RMW_RET_ERROR; + } + } else if (0 == strcmp(endpoint_qos_policy, never_policy)) { + this->endpoint_qos_override_policy = rmw_context_impl_t::endpoint_qos_override_policy_t::Never; + } else if (endpoint_qos_policy[0] != '\0' && strcmp(endpoint_qos_policy, always_policy) != 0) { + RMW_CONNEXT_LOG_ERROR_A_SET( + "Environment variable {%s} has an unexpected value {%s}. " + "Allowed values are {always}, {never} or {dds_topics: }.\n", + RMW_CONNEXT_ENV_ENDPOINT_QOS_OVERRIDE_POLICY, + endpoint_qos_policy); + return RMW_RET_ERROR; + } + if (nullptr == RMW_Connext_gv_DomainParticipantFactory) { RMW_CONNEXT_LOG_ERROR("DDS DomainParticipantFactory not initialized") return RMW_RET_ERROR; } - this->localhost_only = localhost_only; - DDS_DomainId_t domain_id = static_cast(this->domain_id); @@ -779,27 +824,10 @@ rmw_api_connextdds_init( // context->actual_domain_id in rmw_context_impl_t::initialize_node() ctx->domain_id = actual_domain_id; - /* Lookup name of custom QoS library - NOT USED FOR ANYTHING YET */ - const char * qos_library = nullptr; - const char * lookup_rc = - rcutils_get_env(RMW_CONNEXT_ENV_QOS_LIBRARY, &qos_library); - - if (nullptr != lookup_rc || nullptr == qos_library) { - RMW_CONNEXT_LOG_ERROR_A_SET( - "failed to lookup from environment: " - "var=%s, " - "rc=%s ", - RMW_CONNEXT_ENV_QOS_LIBRARY, - lookup_rc) - return RMW_RET_ERROR; - } - - ctx->qos_library = qos_library; - // All publishers will use asynchronous publish mode unless // RMW_CONNEXT_ENV_USE_DEFAULT_PUBLISH_MODE is set. const char * use_default_publish_mode_env = nullptr; - lookup_rc = rcutils_get_env( + const char * lookup_rc = rcutils_get_env( RMW_CONNEXT_ENV_USE_DEFAULT_PUBLISH_MODE, &use_default_publish_mode_env); if (nullptr != lookup_rc || nullptr == use_default_publish_mode_env) { diff --git a/rmw_connextdds_common/src/common/rmw_impl.cpp b/rmw_connextdds_common/src/common/rmw_impl.cpp index d2ca7c74..96e376ef 100644 --- a/rmw_connextdds_common/src/common/rmw_impl.cpp +++ b/rmw_connextdds_common/src/common/rmw_impl.cpp @@ -617,611 +617,6 @@ rmw_connextdds_datareader_qos_to_ros( qos_policies); } -#define RMW_CONNEXT_QOS_TAG_NODE "[node]" -#define RMW_CONNEXT_QOS_TAG_PUBLISHER "[pub]" -#define RMW_CONNEXT_QOS_TAG_SUBSCRIPTION "[sub]" -#define RMW_CONNEXT_QOS_TAG_CLIENT "[client]" -#define RMW_CONNEXT_QOS_TAG_SERVICE "[service]" -#define RMW_CONNEXT_QOS_TAG_REQUEST "[request]" -#define RMW_CONNEXT_QOS_TAG_REPLY "[reply]" - -rmw_ret_t -rmw_connextdds_list_context_qos_profiles( - rmw_context_impl_t * const ctx, - std::vector & profiles) -{ - const bool has_lib = ctx->qos_library.size() > 0; - try { - std::ostringstream ss; - - if (has_lib) { - // e.g. "my_lib::/foo/bar/my_ctx", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_ctx" - ss << ctx->qos_library << "::" << ctx->qos_ctx_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::/foo/bar/[node]", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_namespace << RMW_CONNEXT_QOS_TAG_NODE; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::[node]" - ss << ctx->qos_library << "::" << RMW_CONNEXT_QOS_TAG_NODE; - profiles.push_back(ss.str()); - ss.str(""); - } - - // e.g. "/foo/bar/my_ctx::[node]" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << RMW_CONNEXT_QOS_TAG_NODE; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/::[node]" - ss << ctx->qos_ctx_namespace << "::" << RMW_CONNEXT_QOS_TAG_NODE; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/foo/bar/my_ctx" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_ctx" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << ctx->qos_ctx_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/foo/bar/[node]", - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_namespace << RMW_CONNEXT_QOS_TAG_NODE; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::[node]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << RMW_CONNEXT_QOS_TAG_NODE; - profiles.push_back(ss.str()); - } catch (const std::exception & e) { - UNUSED_ARG(e); - return RMW_RET_ERROR; - } - - return RMW_RET_OK; -} - -static -rmw_ret_t -rmw_connextdds_list_pubsub_qos_profiles( - rmw_context_impl_t * const ctx, - const char * const topic_name, - const char * const type_tag, - std::vector & profiles) -{ - const bool has_lib = ctx->qos_library.size() > 0; - try { - std::ostringstream ss; - - if (has_lib) { - // e.g. "my_lib::/foo/bar/my_ctx/my_topic[pub]", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << - topic_name << type_tag; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::/foo/bar/my_ctx/my_topic", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << topic_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_ctx/my_topic[pub]", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_name << topic_name << type_tag; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_ctx/my_topic", - ss << ctx->qos_library << "::" << ctx->qos_ctx_name << topic_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::/my_topic[pub]", - ss << ctx->qos_library << "::" << type_tag << topic_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::/my_topic", - ss << ctx->qos_library << "::" << topic_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::[pub]" - ss << ctx->qos_library << "::" << type_tag; - profiles.push_back(ss.str()); - ss.str(""); - } - - // e.g. "/foo/bar/my_ctx::/my_topic[pub]" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << - topic_name << type_tag; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/my_ctx::/my_topic" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << topic_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/my_ctx::[pub]" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << - type_tag; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar::my_ctx/my_topic[pub]" - ss << ctx->qos_ctx_namespace << "::" << ctx->qos_ctx_name << - topic_name << type_tag; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar::my_ctx/my_topic" - ss << ctx->qos_ctx_namespace << "::" << ctx->qos_ctx_name << topic_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar::my_ctx[pub]" - ss << ctx->qos_ctx_namespace << "::" << ctx->qos_ctx_name << type_tag; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar::/my_topic[pub]" - ss << ctx->qos_ctx_namespace << "::" << topic_name << type_tag; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar::/my_topic" - ss << ctx->qos_ctx_namespace << "::" << topic_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/::[pub]" - ss << ctx->qos_ctx_namespace << "::" << type_tag; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/foo/bar/my_ctx/my_topic[pub]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << - topic_name << type_tag; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/foo/bar/my_ctx/my_topic" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << topic_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_ctx/my_topic[pub]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_name << topic_name << type_tag; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_ctx/my_topic" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_name << topic_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/my_topic[pub]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - topic_name << type_tag; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/my_topic" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << topic_name; - profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::[pub]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << type_tag; - profiles.push_back(ss.str()); - } catch (const std::exception & e) { - UNUSED_ARG(e); - return RMW_RET_ERROR; - } - - return RMW_RET_OK; -} - -rmw_ret_t -rmw_connextdds_list_publisher_qos_profiles( - rmw_context_impl_t * const ctx, - const char * const topic_name, - std::vector & profiles) -{ - return rmw_connextdds_list_pubsub_qos_profiles( - ctx, topic_name, RMW_CONNEXT_QOS_TAG_PUBLISHER, profiles); -} - -rmw_ret_t -rmw_connextdds_list_subscription_qos_profiles( - rmw_context_impl_t * const ctx, - const char * const topic_name, - std::vector & profiles) -{ - return rmw_connextdds_list_pubsub_qos_profiles( - ctx, topic_name, RMW_CONNEXT_QOS_TAG_SUBSCRIPTION, profiles); -} - -static -rmw_ret_t -rmw_connextdds_list_clientservice_qos_profiles( - rmw_context_impl_t * const ctx, - const char * const service_name, - const char * const type_tag, - std::vector & req_profiles, - std::vector & rep_profiles) -{ - const bool has_lib = ctx->qos_library.size() > 0; - try { - std::ostringstream ss; - - if (has_lib) { - // e.g. "my_lib::/foo/bar/my_ctx/my_service[client][request]", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << - "/" << service_name << type_tag << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::/foo/bar/my_ctx/my_service[client][reply]", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << - "/" << service_name << type_tag << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::/foo/bar/my_ctx/my_service[client]", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << - "/" << service_name << type_tag; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::/foo/bar/my_ctx/my_service[request]", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << "/" << - service_name << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::/foo/bar/my_ctx/my_service[reply]", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << "/" << - service_name << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::/foo/bar/my_ctx/my_service", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << "/" << service_name; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_ctx/my_service[client][request]", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_name << "/" << service_name << - type_tag << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_ctx/my_service[client][reply]", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_name << "/" << service_name << - type_tag << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_ctx/my_service[client]", - ss << ctx->qos_library << "::" << - ctx->qos_ctx_name << "/" << service_name << type_tag; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_ctx/my_service", - ss << ctx->qos_library << "::" << ctx->qos_ctx_name << "/" << service_name; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_service[client][request]", - ss << ctx->qos_library << "::" << - service_name << type_tag << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_service[client][reply]", - ss << ctx->qos_library << "::" << - service_name << type_tag << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_service[client]", - ss << ctx->qos_library << "::" << service_name << type_tag; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_service[request]", - ss << ctx->qos_library << "::" << - service_name << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_service[reply]", - ss << ctx->qos_library << "::" << - service_name << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::my_service", - ss << ctx->qos_library << "::" << service_name; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::[client][request]" - ss << ctx->qos_library << "::" << type_tag << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::[client][reply]" - ss << ctx->qos_library << "::" << type_tag << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "my_lib::[client]" - ss << ctx->qos_library << "::" << type_tag; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - } - - // e.g. "/foo/bar/my_ctx::my_service[client][request]" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << - service_name << type_tag << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/my_ctx::my_service[client][reply]" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << - service_name << type_tag << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/my_ctx::my_service[client]" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << - service_name << type_tag; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/my_ctx::my_service[request]" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << - service_name << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/my_ctx::my_service[reply]" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << - service_name << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/my_ctx::my_service" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << service_name; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/my_ctx::[client][request]" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << - type_tag << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/my_ctx::[client][reply]" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << - type_tag << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "/foo/bar/my_ctx::[client]" - ss << ctx->qos_ctx_namespace << ctx->qos_ctx_name << "::" << type_tag; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/foo/bar/my_ctx/my_service[client][request]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << - "/" << service_name << type_tag << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/foo/bar/my_ctx/my_service[client][reply]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << - "/" << service_name << type_tag << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/foo/bar/my_ctx/my_service[client]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << - "/" << service_name << type_tag; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/foo/bar/my_ctx/my_service[request]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << "/" << - service_name << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/foo/bar/my_ctx/my_service[reply]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << "/" << - service_name << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::/foo/bar/my_ctx/my_service" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_namespace << ctx->qos_ctx_name << "/" << service_name; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_ctx/my_service[client][request]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_name << "/" << service_name << - type_tag << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_ctx/my_service[client][reply]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_name << "/" << service_name << - type_tag << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_ctx/my_service[client]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_name << "/" << service_name << type_tag; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_ctx/my_service[request]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_name << service_name << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_ctx/my_service[reply]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_name << service_name << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_ctx/my_service" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - ctx->qos_ctx_name << service_name; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_service[client][request]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << service_name << - type_tag << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_service[client][reply]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << service_name << - type_tag << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_service[client]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << service_name << type_tag; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_service[request]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - service_name << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_service[reply]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - service_name << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::my_service" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << service_name; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::[client][request]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - type_tag << RMW_CONNEXT_QOS_TAG_REQUEST; - req_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::[client][reply]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << - type_tag << RMW_CONNEXT_QOS_TAG_REPLY; - rep_profiles.push_back(ss.str()); - ss.str(""); - - // e.g. "ros::[client]" - ss << RMW_CONNEXT_DEFAULT_QOS_LIBRARY << "::" << type_tag; - req_profiles.push_back(ss.str()); - rep_profiles.push_back(ss.str()); - } catch (const std::exception & e) { - UNUSED_ARG(e); - return RMW_RET_ERROR; - } - - return RMW_RET_OK; -} - - -rmw_ret_t -rmw_connextdds_list_client_qos_profiles( - rmw_context_impl_t * const ctx, - const char * const service_name, - std::vector & req_profiles, - std::vector & rep_profiles) -{ - return rmw_connextdds_list_clientservice_qos_profiles( - ctx, service_name, RMW_CONNEXT_QOS_TAG_CLIENT, req_profiles, rep_profiles); -} - -rmw_ret_t -rmw_connextdds_list_service_qos_profiles( - rmw_context_impl_t * const ctx, - const char * const service_name, - std::vector & req_profiles, - std::vector & rep_profiles) -{ - return rmw_connextdds_list_clientservice_qos_profiles( - ctx, service_name, RMW_CONNEXT_QOS_TAG_SERVICE, req_profiles, rep_profiles); -} - /****************************************************************************** * Node support ******************************************************************************/ @@ -1383,7 +778,7 @@ RMW_Connext_Publisher::create( }); if (DDS_RETCODE_OK != - DDS_Publisher_get_default_datawriter_qos(pub, &dw_qos)) + DDS_Publisher_get_default_datawriter_qos_w_topic_name(pub, &dw_qos, fqtopic_name.c_str())) { RMW_CONNEXT_LOG_ERROR_SET("failed to get default writer QoS") return nullptr; @@ -1901,7 +1296,7 @@ RMW_Connext_Subscriber::create( }); if (DDS_RETCODE_OK != - DDS_Subscriber_get_default_datareader_qos(sub, &dr_qos)) + DDS_Subscriber_get_default_datareader_qos_w_topic_name(sub, &dr_qos, fqtopic_name.c_str())) { RMW_CONNEXT_LOG_ERROR_SET("failed to get default reader QoS") return nullptr; diff --git a/rmw_connextdds_common/src/ndds/dds_api_ndds.cpp b/rmw_connextdds_common/src/ndds/dds_api_ndds.cpp index bc44e31b..a4bc3324 100644 --- a/rmw_connextdds_common/src/ndds/dds_api_ndds.cpp +++ b/rmw_connextdds_common/src/ndds/dds_api_ndds.cpp @@ -225,8 +225,7 @@ rmw_connextdds_create_contentfilteredtopic( RMW_CONNEXT_ASSERT(nullptr != cft_name) RMW_CONNEXT_ASSERT(nullptr != cft_filter) - struct DDS_StringSeq cft_parameters; - DDS_StringSeq_initialize(&cft_parameters); + struct DDS_StringSeq cft_parameters = DDS_SEQUENCE_INITIALIZER; DDS_StringSeq_ensure_length(&cft_parameters, 0, 0); *cft_out = nullptr; @@ -325,30 +324,41 @@ rmw_connextdds_get_datawriter_qos( { UNUSED_ARG(topic); - if (RMW_RET_OK != - rmw_connextdds_get_readerwriter_qos( - true /* writer_qos */, - type_support, - &qos->history, - &qos->reliability, - &qos->durability, - &qos->deadline, - &qos->liveliness, - &qos->resource_limits, - // TODO(asorbini) this value is not actually used, remove it - &qos->publish_mode, -#if RMW_CONNEXT_HAVE_LIFESPAN_QOS - &qos->lifespan, -#endif /* RMW_CONNEXT_HAVE_LIFESPAN_QOS */ - qos_policies -#if RMW_CONNEXT_HAVE_OPTIONS_PUBSUB - , - pub_options, - nullptr /* sub_options */ -#endif /* RMW_CONNEXT_HAVE_OPTIONS_PUBSUB */ - )) - { - return RMW_RET_ERROR; + bool ignore_ros_profile = ( + ctx->endpoint_qos_override_policy == + rmw_context_impl_t::endpoint_qos_override_policy_t::Never); + + const char * topic_name = DDS_TopicDescription_get_name(DDS_Topic_as_topicdescription(topic)); + ignore_ros_profile = ignore_ros_profile || (ctx->endpoint_qos_override_policy == + rmw_context_impl_t::endpoint_qos_override_policy_t::DDSTopics && + std::regex_match(topic_name, ctx->endpoint_qos_override_policy_topics_regex)); + + if (!ignore_ros_profile) { + if (RMW_RET_OK != + rmw_connextdds_get_readerwriter_qos( + true /* writer_qos */, + type_support, + &qos->history, + &qos->reliability, + &qos->durability, + &qos->deadline, + &qos->liveliness, + &qos->resource_limits, + // TODO(asorbini) this value is not actually used, remove it + &qos->publish_mode, + #if RMW_CONNEXT_HAVE_LIFESPAN_QOS + &qos->lifespan, + #endif /* RMW_CONNEXT_HAVE_LIFESPAN_QOS */ + qos_policies + #if RMW_CONNEXT_HAVE_OPTIONS_PUBSUB + , + pub_options, + nullptr /* sub_options */ + #endif /* RMW_CONNEXT_HAVE_OPTIONS_PUBSUB */ + )) + { + return RMW_RET_ERROR; + } } if (!ctx->use_default_publish_mode) { @@ -383,29 +393,40 @@ rmw_connextdds_get_datareader_qos( UNUSED_ARG(ctx); UNUSED_ARG(topic_desc); - if (RMW_RET_OK != - rmw_connextdds_get_readerwriter_qos( - false /* writer_qos */, - type_support, - &qos->history, - &qos->reliability, - &qos->durability, - &qos->deadline, - &qos->liveliness, - &qos->resource_limits, - nullptr /* publish_mode */, -#if RMW_CONNEXT_HAVE_LIFESPAN_QOS - nullptr /* Lifespan is a writer-only qos policy */, -#endif /* RMW_CONNEXT_HAVE_LIFESPAN_QOS */ - qos_policies -#if RMW_CONNEXT_HAVE_OPTIONS_PUBSUB - , - nullptr /* pub_options */, - sub_options -#endif /* RMW_CONNEXT_HAVE_OPTIONS_PUBSUB */ - )) - { - return RMW_RET_ERROR; + bool ignore_ros_profile = ( + ctx->endpoint_qos_override_policy == + rmw_context_impl_t::endpoint_qos_override_policy_t::Never); + + const char * topic_name = DDS_TopicDescription_get_name(topic_desc); + ignore_ros_profile = ignore_ros_profile || (ctx->endpoint_qos_override_policy == + rmw_context_impl_t::endpoint_qos_override_policy_t::DDSTopics && + std::regex_match(topic_name, ctx->endpoint_qos_override_policy_topics_regex)); + + if (!ignore_ros_profile) { + if (RMW_RET_OK != + rmw_connextdds_get_readerwriter_qos( + false /* writer_qos */, + type_support, + &qos->history, + &qos->reliability, + &qos->durability, + &qos->deadline, + &qos->liveliness, + &qos->resource_limits, + nullptr /* publish_mode */, + #if RMW_CONNEXT_HAVE_LIFESPAN_QOS + nullptr /* Lifespan is a writer-only qos policy */, + #endif /* RMW_CONNEXT_HAVE_LIFESPAN_QOS */ + qos_policies + #if RMW_CONNEXT_HAVE_OPTIONS_PUBSUB + , + nullptr /* pub_options */, + sub_options + #endif /* RMW_CONNEXT_HAVE_OPTIONS_PUBSUB */ + )) + { + return RMW_RET_ERROR; + } } return rmw_connextdds_get_qos_policies( false /* writer_qos */,