From 32afa96212c17ff24158b59603c792f9567fb4d9 Mon Sep 17 00:00:00 2001 From: Eduardo Ponz Segrelles Date: Tue, 22 Dec 2020 08:11:49 +0100 Subject: [PATCH] Load profiles based on topic names (#335) * Refs #6715: Load profiles based on node and topic names * For ROS2 nodes: If a participant profiles with profile_name=node_name exists in FASTRTPS_DEFAULT_PROFILES_FILE, then load it. Else use default. * For ROS2 publishers/subscriptions: If a publisher/subscriber with profile_name=topic_name exists in FASTRTPS_DEFAULT_PROFILES_FILE, then load it. Else use default. * For ROS2 services: if a publisher/subscriber with profile_name=topic_name (or service) exists in FASTRTPS_DEFAULT_PROFILES_FILE, then load it. Else use default. * For ROS2 clients: if a publisher/subscriber with profile_name=topic_name (or client) exists in FASTRTPS_DEFAULT_PROFILES_FILE, then load it. Else use default. Signed-off-by: EduPonz * Uncrustify compliance and log_error=false on loading profiles Signed-off-by: EduPonz * Correct line length Signed-off-by: EduPonz * Keep linters happy Signed-off-by: EduPonz * Document configuration of entities using XML Signed-off-by: EduPonz --- README.md | 87 +++++++++++++++---- rmw_fastrtps_cpp/src/publisher.cpp | 11 ++- rmw_fastrtps_cpp/src/rmw_client.cpp | 39 +++++++-- rmw_fastrtps_cpp/src/rmw_service.cpp | 39 +++++++-- rmw_fastrtps_cpp/src/subscription.cpp | 10 ++- rmw_fastrtps_dynamic_cpp/src/publisher.cpp | 14 ++- rmw_fastrtps_dynamic_cpp/src/rmw_client.cpp | 40 ++++++++- rmw_fastrtps_dynamic_cpp/src/rmw_service.cpp | 42 +++++++-- rmw_fastrtps_dynamic_cpp/src/subscription.cpp | 10 ++- 9 files changed, 243 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 7f881d528..ad5495017 100644 --- a/README.md +++ b/README.md @@ -28,28 +28,25 @@ You can however set it to `rmw_fastrtps_dynamic_cpp` using the environment varia ## Advance usage -`rmw_fastrtps` sets some of the Fast DDS configurable parameters: +[`rclcpp`](https://github.com/ros2/rclcpp) and [`rclpy`](https://github.com/ros2/rclpy) only allow for the configuration of certain middleware QoS (see [ROS 2 QoS policies](https://index.ros.org/doc/ros2/Concepts/About-Quality-of-Service-Settings/#qos-policies)). +In addition to ROS 2 QoS policies, `rmw_fastrtps` sets two more Fast DDS configurable parameters: + * History memory policy: `PREALLOCATED_WITH_REALLOC_MEMORY_MODE` * Publication mode: `ASYNCHRONOUS_PUBLISH_MODE` -However, it is possible to fully configure Fast DDS (including the history memory policy and the publication mode) using an XML file as described in [Fast DDS documentation](https://fast-dds.docs.eprosima.com/en/latest/fastdds/xml_configuration/xml_configuration.html). -Bear in mind that if you want to modify the history memory policy or the publication mode you must set environment variable `RMW_FASTRTPS_USE_QOS_FROM_XML` to 1 (it is set to 0 by default) besides defining the XML file. -This tells `rmw_fastrtps` that it should override both the history memory policy and the publication mode using the XML. -Bear in mind that if you set this environment variable but do not give a value to either of these policies, defaults will be used. -Current Fast-DDS defaults are: -* [History memory policy](https://fast-dds.docs.eprosima.com/en/latest/fastdds/dds_layer/core/policy/eprosimaExtensions.html#rtpsendpointqos): `PREALLOCATED_MEMORY_MODE`. -* [Publication mode](https://fast-dds.docs.eprosima.com/en/latest/fastdds/dds_layer/core/policy/eprosimaExtensions.html#publishmodeqospolicy): `SYNCHRONOUS_PUBLISH_MODE`. +However, `rmw_fastrtps` offers the possibility to further configure Fast DDS: -You have two ways of telling you ROS 2 application which XML to use: -1. Placing your XML file in the running directory under the name `DEFAULT_FASTRTPS_PROFILES.xml`. -2. Setting environment variable `FASTRTPS_DEFAULT_PROFILES_FILE` to your XML file. +* [Change publication mode](#change-publication-mode) +* [Full QoS configuration](#full-qos-configuration) ### Change publication mode -Another way to change easily the publication mode without the need of defining a XML file is to use the environment variable `RMW_FASTRTPS_PUBLICATION_MODE`. -This variable has lower precedence than `RMW_FASTRTPS_USE_QOS_FROM_XML`. -Therefore, it is only taken into account when `RMW_FASTRTPS_USE_QOS_FROM_XML` is not set (or given a value different than `1`). +Fast DDS feats two different [publication modes](https://fast-dds.docs.eprosima.com/en/v2.1.0/fastdds/dds_layer/core/policy/eprosimaExtensions.html?highlight=synchronous#publishmodeqospolicykind): synchronous and asynchronous. +To learn more about the implications of choosing one mode over the other, please refer to [DDS: Asynchronous vs Synchronous Publishing](https://www.eprosima.com/index.php/resources-all/performance/dds-asynchronous-vs-synchronous-publishing): + +`rmw_fastrtps` offers an easy way to change Fast DDS' publication mode without the need of defining a XML file. That is environment variable `RMW_FASTRTPS_PUBLICATION_MODE`. The admissible values are: + * `ASYNCHRONOUS`: asynchronous publication mode. Setting this mode implies that when the publisher invokes the write operation, the data is copied into a queue, a notification about the addition to the queue is performed, and control of the thread is returned to the user before the data is actually sent. A background thread (asynchronous thread) is in turn in charge of consuming the queue and sending the data to every matched reader. @@ -59,9 +56,65 @@ This entails that any blocking call occurring during the write operation would b It is important to note that this mode typically yields higher throughput rates at lower latencies, since the notification and context switching between threads is not present. * `AUTO`: let Fast DDS select the publication mode. This implies using the publication mode set in the XML file or, failing that, the default value set in Fast DDS (which currently is set to `SYNCHRONOUS`). -If `RMW_FASTRTPS_PUBLICATION_MODE` is not set, then `rmw_fastrtps_cpp` and `rmw_fastrtps_dynamic_cpp` behave as if it were set to `ASYNCHRONOUS`. +If `RMW_FASTRTPS_PUBLICATION_MODE` is not set, then both `rmw_fastrtps_cpp` and `rmw_fastrtps_dynamic_cpp` behave as if it were set to `ASYNCHRONOUS`. + +### Full QoS configuration + +With `rmw_fastrtps`, it is possible to fully configure Fast DDS using an XML file as described in [Fast DDS documentation](https://fast-dds.docs.eprosima.com/en/latest/fastdds/xml_configuration/xml_configuration.html). +When configuring the middleware using XML files, there are certain points that have to be taken into account: + +1. QoS set by `rclcpp`/`rclpy` are always honored. +This means that setting any of them in the XML files has no effect, since they do not override what was used to create the publisher, subscription, service, or client. +1. In order to modify the history memory policy or publication mode using XML files, environment variable `RMW_FASTRTPS_USE_QOS_FROM_XML` must be set to 1 (it is set to 0 by default). +This tells `rmw_fastrtps` that it should override both the history memory policy and the publication mode using the XML. +Bear in mind that setting this environment variable but not setting either of these policies in the XML results in Fast DDS' defaults configurations being used. +Current Fast-DDS defaults are: + + * [History memory policy](https://fast-dds.docs.eprosima.com/en/latest/fastdds/dds_layer/core/policy/eprosimaExtensions.html#rtpsendpointqos): `PREALLOCATED_MEMORY_MODE`. + * [Publication mode](https://fast-dds.docs.eprosima.com/en/latest/fastdds/dds_layer/core/policy/eprosimaExtensions.html#publishmodeqospolicy): `SYNCHRONOUS_PUBLISH_MODE`. + +1. Setting `RMW_FASTRTPS_USE_QOS_FROM_XML` effectively overrides whatever configuration was set with `RMW_FASTRTPS_PUBLICATION_MODE`, setting the publication mode to Fast DDS' default publication mode unless specified otherwise using an XML file. + +There are two ways of telling a ROS 2 application which XML to use: + +1. Placing your XML file in the running directory under the name `DEFAULT_FASTRTPS_PROFILES.xml`. +1. Setting environment variable `FASTRTPS_DEFAULT_PROFILES_FILE` to contain the path to your XML file (relative to the working directory). + +#### Applying different profiles to different entities + +`rmw_fastrtps` allows for the configuration of different entities with different QoS using the same XML file. +For doing so, `rmw_fastrtps` locates profiles in the XML based on topic names abiding to the following rules: + +##### Creating publishers/subscriptions with different profiles + +To configure a publisher/subscription, define a ``/`` profile with attribute `profile_name=topic_name`. +If such profile is not defined, `rmw_fastrtps` attempts to load the ``/`` profile with attribute `is_default_profile="true"`. + +##### Creating services with different profiles + +ROS 2 services contain a subscription for receiving requests, and a publisher to reply to them. +`rmw_fastrtps` allows for configuring each of these endpoints separately in the following manner: + +1. To configure the request subscription, define a `` profile with attribute `profile_name=topic_name`, where topic name is the name of the service after mangling. +If such profile is not defined, `rmw_fastrtps` attempts to load a `` profile with attribute `profile_name="service"`. +If neither of the previous profiles exist, `rmw_fastrtps` attempts to load the `` profile with attribute `is_default_profile="true"`. +1. To configure the reply publisher, define a `` profile with attribute `profile_name=topic_name`, where topic name is the name of the service after mangling. +If such profile is not defined, `rmw_fastrtps` attempts to load a `` profile with attribute `profile_name="service"`. +If neither of the previous profiles exist, `rmw_fastrtps` attempts to load the `` profile with attribute `is_default_profile="true"`. + +##### Creating clients with different profiles + +ROS 2 clients contain a publisher to send requests, and a subscription to receive the service's replies. +`rmw_fastrtps` allows for configuring each of these endpoints separately in the following manner: + +1. To configure the requests publisher, define a `` profile with attribute `profile_name=topic_name`, where topic name is the name of the service after mangling. +If such profile is not defined, `rmw_fastrtps` attempts to load a `` profile with attribute `profile_name="client"`. +If neither of the previous profiles exist, `rmw_fastrtps` attempts to load the `` profile with attribute `is_default_profile="true"`. +1. To configure the reply subscription, define a `` profile with attribute `profile_name=topic_name`, where topic name is the name of the service after mangling. +If such profile is not defined, `rmw_fastrtps` attempts to load a `` profile with attribute `profile_name="client"`. +If neither of the previous profiles exist, `rmw_fastrtps` attempts to load the `` profile with attribute `is_default_profile="true"`. -## Example +#### Example The following example configures Fast DDS to publish synchronously, and to have a pre-allocated history that can be expanded whenever it gets filled. @@ -112,4 +165,4 @@ Quality Declarations for the external dependencies of these packages can be foun * [Fast DDS Quality Declaration](https://github.com/eProsima/Fast-DDS/blob/master/QUALITY.md) * [Fast CDR Quality Declaration](https://github.com/eProsima/Fast-CDR/blob/master/QUALITY.md) -* [`foonathan_memory` Quality Declaration](https://github.com/eProsima/Fast-DDS/blob/master/Quality_Declaration_foonathan_memory.md) +* [`foonathan_memory` Quality Declaration](https://github.com/eProsima/Fast-DDS/blob/master/Quality_Declaration_foonathan_memory.md) diff --git a/rmw_fastrtps_cpp/src/publisher.cpp b/rmw_fastrtps_cpp/src/publisher.cpp index 9cb259a26..845cd825d 100644 --- a/rmw_fastrtps_cpp/src/publisher.cpp +++ b/rmw_fastrtps_cpp/src/publisher.cpp @@ -17,6 +17,7 @@ #include "fastrtps/Domain.h" #include "fastrtps/participant/Participant.h" +#include "fastrtps/xmlparser/XMLProfileManager.h" #include "rcutils/error_handling.h" #include "rcutils/macros.h" @@ -44,6 +45,7 @@ using Domain = eprosima::fastrtps::Domain; using Participant = eprosima::fastrtps::Participant; using TopicDataType = eprosima::fastrtps::TopicDataType; +using XMLProfileManager = eprosima::fastrtps::xmlparser::XMLProfileManager; rmw_publisher_t * rmw_fastrtps_cpp::create_publisher( @@ -104,14 +106,17 @@ rmw_fastrtps_cpp::create_publisher( CustomPublisherInfo * info = nullptr; rmw_publisher_t * rmw_publisher = nullptr; - eprosima::fastrtps::PublisherAttributes publisherParam; if (!is_valid_qos(*qos_policies)) { return nullptr; } - // Load default XML profile. - Domain::getDefaultPublisherAttributes(publisherParam); + // If the user defined an XML file via env "FASTRTPS_DEFAULT_PROFILES_FILE", try to load + // publisher which profile name matches with topic_name. If such profile does not exist, + // then use the default attributes. + eprosima::fastrtps::PublisherAttributes publisherParam; + Domain::getDefaultPublisherAttributes(publisherParam); // Loads the XML file if not loaded + XMLProfileManager::fillPublisherAttributes(topic_name, publisherParam, false); info = new (std::nothrow) CustomPublisherInfo(); if (!info) { diff --git a/rmw_fastrtps_cpp/src/rmw_client.cpp b/rmw_fastrtps_cpp/src/rmw_client.cpp index 356f3afc6..18f364c84 100644 --- a/rmw_fastrtps_cpp/src/rmw_client.cpp +++ b/rmw_fastrtps_cpp/src/rmw_client.cpp @@ -36,9 +36,13 @@ #include "./type_support_common.hpp" +#include "fastrtps/xmlparser/XMLProfileManager.h" + using Domain = eprosima::fastrtps::Domain; using Participant = eprosima::fastrtps::Participant; using TopicDataType = eprosima::fastrtps::TopicDataType; +using XMLProfileManager = eprosima::fastrtps::xmlparser::XMLProfileManager; +using XMLP_ret = eprosima::fastrtps::xmlparser::XMLP_ret; extern "C" { @@ -114,6 +118,7 @@ rmw_create_client( } delete info; }); + info->participant_ = participant; info->typesupport_identifier_ = type_support->typesupport_identifier; info->request_publisher_matched_count_ = 0; @@ -161,8 +166,20 @@ rmw_create_client( _register_type(participant, info->response_type_support_); } + // If FASTRTPS_DEFAULT_PROFILES_FILE defined, fill subscriber attributes with a subscriber profile + // located based of topic name defined by _create_topic_name(). If no profile is found, a search + // with profile_name "client" is attempted. Else, use the default attributes. + std::string topic_name_fallback = "client"; eprosima::fastrtps::SubscriberAttributes subscriberParam; - eprosima::fastrtps::PublisherAttributes publisherParam; + eprosima::fastrtps::fixed_string<255> sub_topic_name = _create_topic_name( + qos_policies, ros_service_response_prefix, service_name, "Reply"); + Domain::getDefaultSubscriberAttributes(subscriberParam); + + if (XMLProfileManager::fillSubscriberAttributes( + sub_topic_name.to_string(), subscriberParam, false) != XMLP_ret::XML_OK) + { + XMLProfileManager::fillSubscriberAttributes(topic_name_fallback, subscriberParam, false); + } if (!participant_info->leave_middleware_default_qos) { subscriberParam.historyMemoryPolicy = @@ -171,8 +188,21 @@ rmw_create_client( subscriberParam.topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; subscriberParam.topic.topicDataType = response_type_name; - subscriberParam.topic.topicName = _create_topic_name( - qos_policies, ros_service_response_prefix, service_name, "Reply"); + subscriberParam.topic.topicName = sub_topic_name; + + // If FASTRTPS_DEFAULT_PROFILES_FILE defined, fill publisher attributes with a publisher profile + // located based of topic name defined by _create_topic_name(). If no profile is found, a search + // with profile_name "client" is attempted. Else, use the default attributes. + eprosima::fastrtps::fixed_string<255> pub_topic_name = _create_topic_name( + qos_policies, ros_service_requester_prefix, service_name, "Request"); + eprosima::fastrtps::PublisherAttributes publisherParam; + Domain::getDefaultPublisherAttributes(publisherParam); + + if (XMLProfileManager::fillPublisherAttributes( + pub_topic_name.to_string(), publisherParam, false) != XMLP_ret::XML_OK) + { + XMLProfileManager::fillPublisherAttributes(topic_name_fallback, publisherParam, false); + } if (!participant_info->leave_middleware_default_qos) { publisherParam.historyMemoryPolicy = @@ -186,8 +216,7 @@ rmw_create_client( publisherParam.topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; publisherParam.topic.topicDataType = request_type_name; - publisherParam.topic.topicName = _create_topic_name( - qos_policies, ros_service_requester_prefix, service_name, "Request"); + publisherParam.topic.topicName = pub_topic_name; RCUTILS_LOG_DEBUG_NAMED( "rmw_fastrtps_cpp", diff --git a/rmw_fastrtps_cpp/src/rmw_service.cpp b/rmw_fastrtps_cpp/src/rmw_service.cpp index d5eb1d290..e36e791ee 100644 --- a/rmw_fastrtps_cpp/src/rmw_service.cpp +++ b/rmw_fastrtps_cpp/src/rmw_service.cpp @@ -47,10 +47,14 @@ #include "type_support_common.hpp" +#include "fastrtps/xmlparser/XMLProfileManager.h" + using Domain = eprosima::fastrtps::Domain; using Participant = eprosima::fastrtps::Participant; using TopicDataType = eprosima::fastrtps::TopicDataType; using CustomParticipantInfo = CustomParticipantInfo; +using XMLProfileManager = eprosima::fastrtps::xmlparser::XMLProfileManager; +using XMLP_ret = eprosima::fastrtps::xmlparser::XMLP_ret; extern "C" { @@ -126,6 +130,7 @@ rmw_create_service( } delete info; }); + info->participant_ = participant; info->typesupport_identifier_ = type_support->typesupport_identifier; @@ -171,8 +176,20 @@ rmw_create_service( _register_type(participant, info->response_type_support_); } + // If FASTRTPS_DEFAULT_PROFILES_FILE defined, fill subscriber attributes with a subscriber profile + // located based of topic name defined by _create_topic_name(). If no profile is found, a search + // with profile_name "service" is attempted. Else, use the default attributes. + std::string topic_name_fallback = "service"; eprosima::fastrtps::SubscriberAttributes subscriberParam; - eprosima::fastrtps::PublisherAttributes publisherParam; + eprosima::fastrtps::fixed_string<255> sub_topic_name = _create_topic_name( + qos_policies, ros_service_requester_prefix, service_name, "Request"); + Domain::getDefaultSubscriberAttributes(subscriberParam); + + if (XMLProfileManager::fillSubscriberAttributes( + sub_topic_name.to_string(), subscriberParam, false) != XMLP_ret::XML_OK) + { + XMLProfileManager::fillSubscriberAttributes(topic_name_fallback, subscriberParam, false); + } if (!impl->leave_middleware_default_qos) { subscriberParam.historyMemoryPolicy = @@ -180,8 +197,21 @@ rmw_create_service( } subscriberParam.topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; subscriberParam.topic.topicDataType = request_type_name; - subscriberParam.topic.topicName = _create_topic_name( - qos_policies, ros_service_requester_prefix, service_name, "Request"); + subscriberParam.topic.topicName = sub_topic_name; + + // If FASTRTPS_DEFAULT_PROFILES_FILE defined, fill publisher attributes with a publisher profile + // located based of topic name defined by _create_topic_name(). If no profile is found, a search + // with profile_name "service" is attempted. Else, use the default attributes. + eprosima::fastrtps::fixed_string<255> pub_topic_name = _create_topic_name( + qos_policies, ros_service_response_prefix, service_name, "Reply"); + eprosima::fastrtps::PublisherAttributes publisherParam; + Domain::getDefaultPublisherAttributes(publisherParam); + + if (XMLProfileManager::fillPublisherAttributes( + pub_topic_name.to_string(), publisherParam, false) != XMLP_ret::XML_OK) + { + XMLProfileManager::fillPublisherAttributes(topic_name_fallback, publisherParam, false); + } if (!impl->leave_middleware_default_qos) { publisherParam.historyMemoryPolicy = @@ -195,8 +225,7 @@ rmw_create_service( publisherParam.topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; publisherParam.topic.topicDataType = response_type_name; - publisherParam.topic.topicName = _create_topic_name( - qos_policies, ros_service_response_prefix, service_name, "Reply"); + publisherParam.topic.topicName = pub_topic_name; RCUTILS_LOG_DEBUG_NAMED( "rmw_fastrtps_cpp", diff --git a/rmw_fastrtps_cpp/src/subscription.cpp b/rmw_fastrtps_cpp/src/subscription.cpp index 7f7ed9c49..c8f69488e 100644 --- a/rmw_fastrtps_cpp/src/subscription.cpp +++ b/rmw_fastrtps_cpp/src/subscription.cpp @@ -36,6 +36,7 @@ #include "fastrtps/participant/Participant.h" #include "fastrtps/subscriber/Subscriber.h" +#include "fastrtps/xmlparser/XMLProfileManager.h" #include "rmw_fastrtps_cpp/identifier.hpp" #include "rmw_fastrtps_cpp/subscription.hpp" @@ -45,7 +46,7 @@ using Domain = eprosima::fastrtps::Domain; using Participant = eprosima::fastrtps::Participant; using TopicDataType = eprosima::fastrtps::TopicDataType; - +using XMLProfileManager = eprosima::fastrtps::xmlparser::XMLProfileManager; namespace rmw_fastrtps_cpp { @@ -109,9 +110,12 @@ create_subscription( return nullptr; } - // Load default XML profile. + // If the user defined an XML file via env "FASTRTPS_DEFAULT_PROFILES_FILE", try to load + // subscriber which profile name matches with topic_name. If such profile does not exist, then use + // the default attributes. eprosima::fastrtps::SubscriberAttributes subscriberParam; - Domain::getDefaultSubscriberAttributes(subscriberParam); + Domain::getDefaultSubscriberAttributes(subscriberParam); // Loads the XML file if not loaded + XMLProfileManager::fillSubscriberAttributes(topic_name, subscriberParam, false); CustomSubscriberInfo * info = new (std::nothrow) CustomSubscriberInfo(); if (!info) { diff --git a/rmw_fastrtps_dynamic_cpp/src/publisher.cpp b/rmw_fastrtps_dynamic_cpp/src/publisher.cpp index 74327cad6..f6cfde1a1 100644 --- a/rmw_fastrtps_dynamic_cpp/src/publisher.cpp +++ b/rmw_fastrtps_dynamic_cpp/src/publisher.cpp @@ -15,6 +15,8 @@ #include +#include "fastrtps/xmlparser/XMLProfileManager.h" + #include "rcutils/error_handling.h" #include "rmw/allocators.h" @@ -42,6 +44,7 @@ using Domain = eprosima::fastrtps::Domain; using Participant = eprosima::fastrtps::Participant; using TopicDataType = eprosima::fastrtps::TopicDataType; using TypeSupportProxy = rmw_fastrtps_dynamic_cpp::TypeSupportProxy; +using XMLProfileManager = eprosima::fastrtps::xmlparser::XMLProfileManager; rmw_publisher_t * rmw_fastrtps_dynamic_cpp::create_publisher( @@ -105,12 +108,15 @@ rmw_fastrtps_dynamic_cpp::create_publisher( return nullptr; } - CustomPublisherInfo * info = nullptr; - rmw_publisher_t * rmw_publisher = nullptr; + // If the user defined an XML file via env "FASTRTPS_DEFAULT_PROFILES_FILE", try to load + // publisher which profile name matches with topic_name. If such profile does not exist, + // then use the default attributes. eprosima::fastrtps::PublisherAttributes publisherParam; + Domain::getDefaultPublisherAttributes(publisherParam); // Loads the XML file if not loaded + XMLProfileManager::fillPublisherAttributes(topic_name, publisherParam, false); - // Load default XML profile. - Domain::getDefaultPublisherAttributes(publisherParam); + CustomPublisherInfo * info = nullptr; + rmw_publisher_t * rmw_publisher = nullptr; info = new (std::nothrow) CustomPublisherInfo(); if (!info) { diff --git a/rmw_fastrtps_dynamic_cpp/src/rmw_client.cpp b/rmw_fastrtps_dynamic_cpp/src/rmw_client.cpp index ed9572504..ebc4412a9 100644 --- a/rmw_fastrtps_dynamic_cpp/src/rmw_client.cpp +++ b/rmw_fastrtps_dynamic_cpp/src/rmw_client.cpp @@ -40,11 +40,15 @@ #include "type_support_common.hpp" #include "type_support_registry.hpp" +#include "fastrtps/xmlparser/XMLProfileManager.h" + using BaseTypeSupport = rmw_fastrtps_dynamic_cpp::BaseTypeSupport; using Domain = eprosima::fastrtps::Domain; using Participant = eprosima::fastrtps::Participant; using TopicDataType = eprosima::fastrtps::TopicDataType; using TypeSupportProxy = rmw_fastrtps_dynamic_cpp::TypeSupportProxy; +using XMLProfileManager = eprosima::fastrtps::xmlparser::XMLProfileManager; +using XMLP_ret = eprosima::fastrtps::xmlparser::XMLP_ret; extern "C" { @@ -118,6 +122,9 @@ rmw_create_client( eprosima::fastrtps::SubscriberAttributes subscriberParam; eprosima::fastrtps::PublisherAttributes publisherParam; rmw_client_t * rmw_client = nullptr; + eprosima::fastrtps::fixed_string<255> sub_topic_name; + eprosima::fastrtps::fixed_string<255> pub_topic_name; + std::string topic_name_fallback; info = new CustomClientInfo(); info->participant_ = participant; @@ -181,6 +188,20 @@ rmw_create_client( _register_type(participant, info->response_type_support_); } + // If FASTRTPS_DEFAULT_PROFILES_FILE defined, fill subscriber attributes with a subscriber profile + // located based of topic name defined by _create_topic_name(). If no profile is found, a search + // with profile_name "client" is attempted. Else, use the default attributes. + topic_name_fallback = "client"; + sub_topic_name = _create_topic_name( + qos_policies, ros_service_response_prefix, service_name, "Reply"); + Domain::getDefaultSubscriberAttributes(subscriberParam); + + if (XMLProfileManager::fillSubscriberAttributes( + sub_topic_name.to_string(), subscriberParam, false) != XMLP_ret::XML_OK) + { + XMLProfileManager::fillSubscriberAttributes(topic_name_fallback, subscriberParam, false); + } + if (!participant_info->leave_middleware_default_qos) { subscriberParam.historyMemoryPolicy = eprosima::fastrtps::rtps::PREALLOCATED_WITH_REALLOC_MEMORY_MODE; @@ -188,8 +209,20 @@ rmw_create_client( subscriberParam.topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; subscriberParam.topic.topicDataType = response_type_name; - subscriberParam.topic.topicName = _create_topic_name( - qos_policies, ros_service_response_prefix, service_name, "Reply"); + subscriberParam.topic.topicName = sub_topic_name; + + // If FASTRTPS_DEFAULT_PROFILES_FILE defined, fill publisher attributes with a publisher profile + // located based of topic name defined by _create_topic_name(). If no profile is found, a search + // with profile_name "client" is attempted. Else, use the default attributes. + pub_topic_name = _create_topic_name( + qos_policies, ros_service_requester_prefix, service_name, "Request"); + Domain::getDefaultPublisherAttributes(publisherParam); + + if (XMLProfileManager::fillPublisherAttributes( + pub_topic_name.to_string(), publisherParam, false) != XMLP_ret::XML_OK) + { + XMLProfileManager::fillPublisherAttributes(topic_name_fallback, publisherParam, false); + } if (!participant_info->leave_middleware_default_qos) { publisherParam.historyMemoryPolicy = @@ -203,8 +236,7 @@ rmw_create_client( publisherParam.topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; publisherParam.topic.topicDataType = request_type_name; - publisherParam.topic.topicName = _create_topic_name( - qos_policies, ros_service_requester_prefix, service_name, "Request"); + publisherParam.topic.topicName = pub_topic_name; RCUTILS_LOG_DEBUG_NAMED( "rmw_fastrtps_dynamic_cpp", diff --git a/rmw_fastrtps_dynamic_cpp/src/rmw_service.cpp b/rmw_fastrtps_dynamic_cpp/src/rmw_service.cpp index ff948533b..85ecddbc0 100644 --- a/rmw_fastrtps_dynamic_cpp/src/rmw_service.cpp +++ b/rmw_fastrtps_dynamic_cpp/src/rmw_service.cpp @@ -52,11 +52,15 @@ #include "type_support_common.hpp" #include "type_support_registry.hpp" +#include "fastrtps/xmlparser/XMLProfileManager.h" + using BaseTypeSupport = rmw_fastrtps_dynamic_cpp::BaseTypeSupport; using Domain = eprosima::fastrtps::Domain; using Participant = eprosima::fastrtps::Participant; using TopicDataType = eprosima::fastrtps::TopicDataType; using TypeSupportProxy = rmw_fastrtps_dynamic_cpp::TypeSupportProxy; +using XMLProfileManager = eprosima::fastrtps::xmlparser::XMLProfileManager; +using XMLP_ret = eprosima::fastrtps::xmlparser::XMLP_ret; extern "C" { @@ -130,6 +134,10 @@ rmw_create_service( eprosima::fastrtps::SubscriberAttributes subscriberParam; eprosima::fastrtps::PublisherAttributes publisherParam; rmw_service_t * rmw_service = nullptr; + eprosima::fastrtps::fixed_string<255> sub_topic_name; + eprosima::fastrtps::fixed_string<255> pub_topic_name; + std::string topic_name_fallback; + info = new CustomServiceInfo(); info->participant_ = participant; @@ -191,15 +199,40 @@ rmw_create_service( _register_type(participant, info->response_type_support_); } + // If FASTRTPS_DEFAULT_PROFILES_FILE defined, fill subscriber attributes with a subscriber profile + // located based of topic name defined by _create_topic_name(). If no profile is found, a search + // with profile_name "service" is attempted. Else, use the default attributes. + topic_name_fallback = "service"; + sub_topic_name = _create_topic_name( + qos_policies, ros_service_requester_prefix, service_name, "Request"); + Domain::getDefaultSubscriberAttributes(subscriberParam); + + if (XMLProfileManager::fillSubscriberAttributes( + sub_topic_name.to_string(), subscriberParam, false) != XMLP_ret::XML_OK) + { + XMLProfileManager::fillSubscriberAttributes(topic_name_fallback, subscriberParam, false); + } + if (!impl->leave_middleware_default_qos) { subscriberParam.historyMemoryPolicy = eprosima::fastrtps::rtps::PREALLOCATED_WITH_REALLOC_MEMORY_MODE; } - subscriberParam.topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; subscriberParam.topic.topicDataType = request_type_name; - subscriberParam.topic.topicName = _create_topic_name( - qos_policies, ros_service_requester_prefix, service_name, "Request"); + subscriberParam.topic.topicName = sub_topic_name; + + // If FASTRTPS_DEFAULT_PROFILES_FILE defined, fill publisher attributes with a publisher profile + // located based of topic name defined by _create_topic_name(). If no profile is found, a search + // with profile_name "service" is attempted. Else, use the default attributes. + pub_topic_name = _create_topic_name( + qos_policies, ros_service_response_prefix, service_name, "Reply"); + Domain::getDefaultPublisherAttributes(publisherParam); + + if (XMLProfileManager::fillPublisherAttributes( + pub_topic_name.to_string(), publisherParam, false) != XMLP_ret::XML_OK) + { + XMLProfileManager::fillPublisherAttributes(topic_name_fallback, publisherParam, false); + } if (!impl->leave_middleware_default_qos) { publisherParam.historyMemoryPolicy = @@ -213,8 +246,7 @@ rmw_create_service( publisherParam.topic.topicKind = eprosima::fastrtps::rtps::NO_KEY; publisherParam.topic.topicDataType = response_type_name; - publisherParam.topic.topicName = _create_topic_name( - qos_policies, ros_service_response_prefix, service_name, "Reply"); + publisherParam.topic.topicName = pub_topic_name; RCUTILS_LOG_DEBUG_NAMED( "rmw_fastrtps_dynamic_cpp", diff --git a/rmw_fastrtps_dynamic_cpp/src/subscription.cpp b/rmw_fastrtps_dynamic_cpp/src/subscription.cpp index 1a716294f..156fc6ece 100644 --- a/rmw_fastrtps_dynamic_cpp/src/subscription.cpp +++ b/rmw_fastrtps_dynamic_cpp/src/subscription.cpp @@ -33,6 +33,7 @@ #include "fastrtps/participant/Participant.h" #include "fastrtps/subscriber/Subscriber.h" +#include "fastrtps/xmlparser/XMLProfileManager.h" #include "rmw_fastrtps_dynamic_cpp/identifier.hpp" #include "rmw_fastrtps_dynamic_cpp/subscription.hpp" @@ -45,7 +46,7 @@ using Domain = eprosima::fastrtps::Domain; using Participant = eprosima::fastrtps::Participant; using TopicDataType = eprosima::fastrtps::TopicDataType; using TypeSupportProxy = rmw_fastrtps_dynamic_cpp::TypeSupportProxy; - +using XMLProfileManager = eprosima::fastrtps::xmlparser::XMLProfileManager; namespace rmw_fastrtps_dynamic_cpp { @@ -111,9 +112,12 @@ create_subscription( return nullptr; } - // Load default XML profile. + // If the user defined an XML file via env "FASTRTPS_DEFAULT_PROFILES_FILE", try to load + // subscriber which profile name matches with topic_name. If such profile does not exist, then use + // the default attributes. eprosima::fastrtps::SubscriberAttributes subscriberParam; - Domain::getDefaultSubscriberAttributes(subscriberParam); + Domain::getDefaultSubscriberAttributes(subscriberParam); // Loads the XML file if not loaded + XMLProfileManager::fillSubscriberAttributes(topic_name, subscriberParam, false); CustomSubscriberInfo * info = new (std::nothrow) CustomSubscriberInfo(); if (!info) {