diff --git a/README.md b/README.md index f91ef6e..9767447 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ Parameters are provided to configure the behavior of the bridge. These parameter * (ROS 2) __num_threads__: The number of threads to use for the ROS node executor. This controls the number of subscriptions that can be processed in parallel. 0 means one thread per CPU core. Defaults to `0`. * (ROS 2) __min_qos_depth__: Minimum depth used for the QoS profile of subscriptions. Defaults to `1`. This is to set a lower limit for a subscriber's QoS depth which is computed by summing up depths of all publishers. See also [#208](https://github.com/foxglove/ros-foxglove-bridge/issues/208). * (ROS 2) __max_qos_depth__: Maximum depth used for the QoS profile of subscriptions. Defaults to `25`. + * (ROS 2) __qos_reliability__: The default QoS reliability setting for subscriptions the bridge creates. Can be 'reliable', 'best_effort', or 'automatic'. Defaults to `automatic`. * (ROS 2) __include_hidden__: Include hidden topics and services. Defaults to `false`. * (ROS 2) __disable_load_message__: Do not publish as loaned message when publishing a client message. Defaults to `true`. diff --git a/ros2_foxglove_bridge/include/foxglove_bridge/param_utils.hpp b/ros2_foxglove_bridge/include/foxglove_bridge/param_utils.hpp index cbb4cdf..b513ac5 100644 --- a/ros2_foxglove_bridge/include/foxglove_bridge/param_utils.hpp +++ b/ros2_foxglove_bridge/include/foxglove_bridge/param_utils.hpp @@ -16,6 +16,7 @@ constexpr char PARAM_CERTFILE[] = "certfile"; constexpr char PARAM_KEYFILE[] = "keyfile"; constexpr char PARAM_MIN_QOS_DEPTH[] = "min_qos_depth"; constexpr char PARAM_MAX_QOS_DEPTH[] = "max_qos_depth"; +constexpr char PARAM_QOS_RELIABILITY[] = "qos_reliability"; constexpr char PARAM_TOPIC_WHITELIST[] = "topic_whitelist"; constexpr char PARAM_SERVICE_WHITELIST[] = "service_whitelist"; constexpr char PARAM_PARAMETER_WHITELIST[] = "param_whitelist"; @@ -31,6 +32,7 @@ constexpr char DEFAULT_ADDRESS[] = "0.0.0.0"; constexpr int64_t DEFAULT_SEND_BUFFER_LIMIT = 10000000; constexpr int64_t DEFAULT_MIN_QOS_DEPTH = 1; constexpr int64_t DEFAULT_MAX_QOS_DEPTH = 25; +constexpr char DEFAULT_QOS_RELIABILITY[] = "automatic"; void declareParameters(rclcpp::Node* node); diff --git a/ros2_foxglove_bridge/include/foxglove_bridge/ros2_foxglove_bridge.hpp b/ros2_foxglove_bridge/include/foxglove_bridge/ros2_foxglove_bridge.hpp index dcbd1a2..55b0c67 100644 --- a/ros2_foxglove_bridge/include/foxglove_bridge/ros2_foxglove_bridge.hpp +++ b/ros2_foxglove_bridge/include/foxglove_bridge/ros2_foxglove_bridge.hpp @@ -77,6 +77,7 @@ class FoxgloveBridge : public rclcpp::Node { std::unique_ptr _rosgraphPollThread; size_t _minQosDepth = DEFAULT_MIN_QOS_DEPTH; size_t _maxQosDepth = DEFAULT_MAX_QOS_DEPTH; + std::string _qosReliability = DEFAULT_QOS_RELIABILITY; std::shared_ptr> _clockSubscription; bool _useSimTime = false; std::vector _capabilities; diff --git a/ros2_foxglove_bridge/src/param_utils.cpp b/ros2_foxglove_bridge/src/param_utils.cpp index f15fb26..4158707 100644 --- a/ros2_foxglove_bridge/src/param_utils.cpp +++ b/ros2_foxglove_bridge/src/param_utils.cpp @@ -84,6 +84,15 @@ void declareParameters(rclcpp::Node* node) { maxQosDepthDescription.integer_range[0].step = 1; node->declare_parameter(PARAM_MAX_QOS_DEPTH, DEFAULT_MAX_QOS_DEPTH, maxQosDepthDescription); + auto qosReliabilityDescription = rcl_interfaces::msg::ParameterDescriptor{}; + qosReliabilityDescription.name = PARAM_QOS_RELIABILITY; + qosReliabilityDescription.type = rcl_interfaces::msg::ParameterType::PARAMETER_STRING; + qosReliabilityDescription.description = + "The default QoS reliability setting for subscriptions the bridge " + "creates. Can be 'reliable', 'best_effort', or 'automatic'."; + qosReliabilityDescription.read_only = true; + node->declare_parameter(PARAM_QOS_RELIABILITY, DEFAULT_QOS_RELIABILITY, + qosReliabilityDescription); auto topicWhiteListDescription = rcl_interfaces::msg::ParameterDescriptor{}; topicWhiteListDescription.name = PARAM_TOPIC_WHITELIST; topicWhiteListDescription.type = rcl_interfaces::msg::ParameterType::PARAMETER_STRING_ARRAY; diff --git a/ros2_foxglove_bridge/src/ros2_foxglove_bridge.cpp b/ros2_foxglove_bridge/src/ros2_foxglove_bridge.cpp index 1e37963..1e76db8 100644 --- a/ros2_foxglove_bridge/src/ros2_foxglove_bridge.cpp +++ b/ros2_foxglove_bridge/src/ros2_foxglove_bridge.cpp @@ -36,6 +36,7 @@ FoxgloveBridge::FoxgloveBridge(const rclcpp::NodeOptions& options) const auto keyfile = this->get_parameter(PARAM_KEYFILE).as_string(); _minQosDepth = static_cast(this->get_parameter(PARAM_MIN_QOS_DEPTH).as_int()); _maxQosDepth = static_cast(this->get_parameter(PARAM_MAX_QOS_DEPTH).as_int()); + _qosReliability = this->get_parameter(PARAM_QOS_RELIABILITY).as_string(); const auto topicWhiteList = this->get_parameter(PARAM_TOPIC_WHITELIST).as_string_array(); _topicWhitelistPatterns = parseRegexStrings(this, topicWhiteList); const auto serviceWhiteList = this->get_parameter(PARAM_SERVICE_WHITELIST).as_string_array(); @@ -495,18 +496,25 @@ void FoxgloveBridge::subscribe(foxglove::ChannelId channelId, ConnectionHandle c rclcpp::QoS qos{rclcpp::KeepLast(depth)}; - // If all endpoints are reliable, ask for reliable - if (!publisherInfo.empty() && reliabilityReliableEndpointsCount == publisherInfo.size()) { + // Handle the QoS reliability setting + if (_qosReliability == "reliable") { qos.reliable(); + } else if (_qosReliability == "best_effort") { + qos.best_effort(); } else { - if (reliabilityReliableEndpointsCount > 0) { - RCLCPP_WARN( - this->get_logger(), - "Some, but not all, publishers on topic '%s' are offering QoSReliabilityPolicy.RELIABLE. " - "Falling back to QoSReliabilityPolicy.BEST_EFFORT as it will connect to all publishers", - topic.c_str()); + // If all endpoints are reliable, ask for reliable + if (!publisherInfo.empty() && reliabilityReliableEndpointsCount == publisherInfo.size()) { + qos.reliable(); + } else { + if (reliabilityReliableEndpointsCount > 0) { + RCLCPP_WARN( + this->get_logger(), + "Some, but not all, publishers on topic '%s' are offering QoSReliabilityPolicy.RELIABLE. " + "Falling back to QoSReliabilityPolicy.BEST_EFFORT as it will connect to all publishers", + topic.c_str()); + } + qos.best_effort(); } - qos.best_effort(); } // If all endpoints are transient_local, ask for transient_local