Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13abc1beed | ||
|
|
e77c1fe550 | ||
|
|
00b9d0a018 | ||
|
|
77c7aaf917 | ||
|
|
9019a8d9b7 | ||
|
|
0644f220a2 | ||
|
|
32438a6a67 | ||
|
|
d6bd8baac5 | ||
|
|
623c3eb874 | ||
|
|
7c1143dc15 | ||
|
|
9ff864c6ae | ||
|
|
13182b5aad | ||
|
|
9284d7cefa | ||
|
|
c42745c5ba |
@@ -2,6 +2,23 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
23.2.0 (2023-10-09)
|
||||
-------------------
|
||||
* add clients & services count (`#2072 <https://github.com/ros2/rclcpp/issues/2072>`_)
|
||||
* remove invalid sized allocation test for SerializedMessage. (`#2330 <https://github.com/ros2/rclcpp/issues/2330>`_)
|
||||
* Adding API to copy all parameters from one node to another (`#2304 <https://github.com/ros2/rclcpp/issues/2304>`_)
|
||||
* Contributors: Minju, Lee, Steve Macenski, Tomoya Fujita
|
||||
|
||||
23.1.0 (2023-10-04)
|
||||
-------------------
|
||||
* Add locking to protect the TimeSource::NodeState::node_base\_ (`#2320 <https://github.com/ros2/rclcpp/issues/2320>`_)
|
||||
* Update SignalHandler get_global_signal_handler to avoid complex types in static memory (`#2316 <https://github.com/ros2/rclcpp/issues/2316>`_)
|
||||
* Removing Old Connext Tests (`#2313 <https://github.com/ros2/rclcpp/issues/2313>`_)
|
||||
* Documentation for list_parameters (`#2315 <https://github.com/ros2/rclcpp/issues/2315>`_)
|
||||
* Decouple rosout publisher init from node init. (`#2174 <https://github.com/ros2/rclcpp/issues/2174>`_)
|
||||
* fix the depth to relative in list_parameters (`#2300 <https://github.com/ros2/rclcpp/issues/2300>`_)
|
||||
* Contributors: Chris Lalancette, Lucas Wendland, Minju, Lee, Tomoya Fujita, Tully Foote
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Fix the return type of Rate::period. (`#2301 <https://github.com/ros2/rclcpp/issues/2301>`_)
|
||||
|
||||
82
rclcpp/include/rclcpp/copy_all_parameter_values.hpp
Normal file
82
rclcpp/include/rclcpp/copy_all_parameter_values.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright 2023 Open Navigation LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__COPY_ALL_PARAMETER_VALUES_HPP_
|
||||
#define RCLCPP__COPY_ALL_PARAMETER_VALUES_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl_interfaces/srv/list_parameters.hpp"
|
||||
#include "rcl_interfaces/msg/parameter_descriptor.hpp"
|
||||
#include "rcl_interfaces/msg/set_parameters_result.hpp"
|
||||
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* Copy all parameters from one source node to another destination node.
|
||||
* May throw exceptions if parameters from source are uninitialized or undeclared.
|
||||
* \param source Node to copy parameters from
|
||||
* \param destination Node to copy parameters to
|
||||
* \param override_existing_params Default false. Whether to override existing destination params
|
||||
* if both the source and destination contain the same parameter.
|
||||
*/
|
||||
template<typename NodeT1, typename NodeT2>
|
||||
void
|
||||
copy_all_parameter_values(
|
||||
const NodeT1 & source, const NodeT2 & destination, const bool override_existing_params = false)
|
||||
{
|
||||
using Parameters = std::vector<rclcpp::Parameter>;
|
||||
using Descriptions = std::vector<rcl_interfaces::msg::ParameterDescriptor>;
|
||||
auto source_params = source->get_node_parameters_interface();
|
||||
auto dest_params = destination->get_node_parameters_interface();
|
||||
rclcpp::Logger logger = destination->get_node_logging_interface()->get_logger();
|
||||
|
||||
std::vector<std::string> param_names = source_params->list_parameters({}, 0).names;
|
||||
Parameters params = source_params->get_parameters(param_names);
|
||||
Descriptions descriptions = source_params->describe_parameters(param_names);
|
||||
|
||||
for (unsigned int idx = 0; idx != params.size(); idx++) {
|
||||
if (!dest_params->has_parameter(params[idx].get_name())) {
|
||||
dest_params->declare_parameter(
|
||||
params[idx].get_name(), params[idx].get_parameter_value(), descriptions[idx]);
|
||||
} else if (override_existing_params) {
|
||||
try {
|
||||
rcl_interfaces::msg::SetParametersResult result =
|
||||
dest_params->set_parameters_atomically({params[idx]});
|
||||
if (!result.successful) {
|
||||
// Parameter update rejected or read-only
|
||||
RCLCPP_WARN(
|
||||
logger,
|
||||
"Unable to set parameter (%s): %s!",
|
||||
params[idx].get_name().c_str(), result.reason.c_str());
|
||||
}
|
||||
} catch (const rclcpp::exceptions::InvalidParameterTypeException & e) {
|
||||
RCLCPP_WARN(
|
||||
logger,
|
||||
"Unable to set parameter (%s): incompatable parameter type (%s)!",
|
||||
params[idx].get_name().c_str(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__COPY_ALL_PARAMETER_VALUES_HPP_
|
||||
@@ -972,7 +972,16 @@ public:
|
||||
|
||||
/// Return a list of parameters with any of the given prefixes, up to the given depth.
|
||||
/**
|
||||
* \todo: properly document and test this method.
|
||||
* Parameters are separated into a hierarchy using the "." (dot) character.
|
||||
* The "prefixes" argument is a way to select only particular parts of the hierarchy.
|
||||
*
|
||||
* \param[in] prefixes The list of prefixes that should be searched for within the
|
||||
* current parameters. If this vector of prefixes is empty, then list_parameters
|
||||
* will return all parameters.
|
||||
* \param[in] depth An unsigned integer that represents the recursive depth to search.
|
||||
* If this depth = 0, then all parameters that fit the prefixes will be returned.
|
||||
* \returns A ListParametersResult message which contains both an array of unique prefixes
|
||||
* and an array of names that were matched to the prefixes given.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
@@ -1305,6 +1314,26 @@ public:
|
||||
size_t
|
||||
count_subscribers(const std::string & topic_name) const;
|
||||
|
||||
/// Return the number of clients created for a given service.
|
||||
/**
|
||||
* \param[in] service_name the actual service name used; it will not be automatically remapped.
|
||||
* \return number of clients that have been created for the given service.
|
||||
* \throws std::runtime_error if clients could not be counted
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_clients(const std::string & service_name) const;
|
||||
|
||||
/// Return the number of services created for a given service.
|
||||
/**
|
||||
* \param[in] service_name the actual service name used; it will not be automatically remapped.
|
||||
* \return number of services that have been created for the given service.
|
||||
* \throws std::runtime_error if services could not be counted
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_services(const std::string & service_name) const;
|
||||
|
||||
/// Return the topic endpoint information about publishers on a given topic.
|
||||
/**
|
||||
* The returned parameter is a list of topic endpoint information, where each item will contain
|
||||
|
||||
@@ -113,6 +113,14 @@ public:
|
||||
size_t
|
||||
count_subscribers(const std::string & topic_name) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_clients(const std::string & service_name) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_services(const std::string & service_name) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rcl_guard_condition_t *
|
||||
get_graph_guard_condition() const override;
|
||||
|
||||
@@ -305,6 +305,24 @@ public:
|
||||
size_t
|
||||
count_subscribers(const std::string & topic_name) const = 0;
|
||||
|
||||
/// Return the number of clients created for a given service.
|
||||
/*
|
||||
* \param[in] service_name the actual service name used; it will not be automatically remapped.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
size_t
|
||||
count_clients(const std::string & service_name) const = 0;
|
||||
|
||||
/// Return the number of services created for a given service.
|
||||
/*
|
||||
* \param[in] service_name the actual service name used; it will not be automatically remapped.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
size_t
|
||||
count_services(const std::string & service_name) const = 0;
|
||||
|
||||
/// Return the rcl guard condition which is triggered when the ROS graph changes.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
* - rclcpp::ParameterValue
|
||||
* - rclcpp::AsyncParametersClient
|
||||
* - rclcpp::SyncParametersClient
|
||||
* - rclcpp::copy_all_parameter_values()
|
||||
* - rclcpp/parameter.hpp
|
||||
* - rclcpp/parameter_value.hpp
|
||||
* - rclcpp/parameter_client.hpp
|
||||
@@ -95,6 +96,9 @@
|
||||
* - Get the number of publishers or subscribers on a topic:
|
||||
* - rclcpp::Node::count_publishers()
|
||||
* - rclcpp::Node::count_subscribers()
|
||||
* - Get the number of clients or servers on a service:
|
||||
* - rclcpp::Node::count_clients()
|
||||
* - rclcpp::Node::count_services()
|
||||
*
|
||||
* And components related to logging:
|
||||
*
|
||||
@@ -164,6 +168,7 @@
|
||||
#include <csignal>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/copy_all_parameter_values.hpp"
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rclcpp/guard_condition.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="2">
|
||||
<name>rclcpp</name>
|
||||
<version>23.0.0</version>
|
||||
<version>23.2.0</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -522,6 +522,18 @@ Node::count_subscribers(const std::string & topic_name) const
|
||||
return node_graph_->count_subscribers(topic_name);
|
||||
}
|
||||
|
||||
size_t
|
||||
Node::count_clients(const std::string & service_name) const
|
||||
{
|
||||
return node_graph_->count_clients(service_name);
|
||||
}
|
||||
|
||||
size_t
|
||||
Node::count_services(const std::string & service_name) const
|
||||
{
|
||||
return node_graph_->count_services(service_name);
|
||||
}
|
||||
|
||||
std::vector<rclcpp::TopicEndpointInfo>
|
||||
Node::get_publishers_info_by_topic(const std::string & topic_name, bool no_mangle) const
|
||||
{
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "rcl/arguments.h"
|
||||
#include "rcl/node_type_cache.h"
|
||||
#include "rcl/logging.h"
|
||||
#include "rcl/logging_rosout.h"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rcutils/logging_macros.h"
|
||||
#include "rmw/validate_namespace.h"
|
||||
@@ -55,17 +57,12 @@ NodeBase::NodeBase(
|
||||
std::shared_ptr<std::recursive_mutex> logging_mutex = get_global_logging_mutex();
|
||||
|
||||
rcl_ret_t ret;
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(*logging_mutex);
|
||||
// TODO(ivanpauno): /rosout Qos should be reconfigurable.
|
||||
// TODO(ivanpauno): Instead of mutually excluding rcl_node_init with the global logger mutex,
|
||||
// rcl_logging_rosout_init_publisher_for_node could be decoupled from there and be called
|
||||
// here directly.
|
||||
ret = rcl_node_init(
|
||||
rcl_node.get(),
|
||||
node_name.c_str(), namespace_.c_str(),
|
||||
context_->get_rcl_context().get(), &rcl_node_options);
|
||||
}
|
||||
|
||||
// TODO(ivanpauno): /rosout Qos should be reconfigurable.
|
||||
ret = rcl_node_init(
|
||||
rcl_node.get(),
|
||||
node_name.c_str(), namespace_.c_str(),
|
||||
context_->get_rcl_context().get(), &rcl_node_options);
|
||||
if (ret != RCL_RET_OK) {
|
||||
if (ret == RCL_RET_NODE_INVALID_NAME) {
|
||||
rcl_reset_error(); // discard rcl_node_init error
|
||||
@@ -115,13 +112,29 @@ NodeBase::NodeBase(
|
||||
throw_from_rcl_error(ret, "failed to initialize rcl node");
|
||||
}
|
||||
|
||||
// The initialization for the rosout publisher
|
||||
if (rcl_logging_rosout_enabled() && rcl_node_options.enable_rosout) {
|
||||
std::lock_guard<std::recursive_mutex> guard(*logging_mutex);
|
||||
ret = rcl_logging_rosout_init_publisher_for_node(rcl_node.get());
|
||||
if (ret != RCL_RET_OK) {
|
||||
throw_from_rcl_error(ret, "failed to initialize rosout publisher");
|
||||
}
|
||||
}
|
||||
|
||||
node_handle_.reset(
|
||||
rcl_node.release(),
|
||||
[logging_mutex](rcl_node_t * node) -> void {
|
||||
std::lock_guard<std::recursive_mutex> guard(*logging_mutex);
|
||||
// TODO(ivanpauno): Instead of mutually excluding rcl_node_fini with the global logger mutex,
|
||||
// rcl_logging_rosout_fini_publisher_for_node could be decoupled from there and be called
|
||||
// here directly.
|
||||
[logging_mutex, rcl_node_options](rcl_node_t * node) -> void {
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(*logging_mutex);
|
||||
if (rcl_logging_rosout_enabled() && rcl_node_options.enable_rosout) {
|
||||
rcl_ret_t ret = rcl_logging_rosout_fini_publisher_for_node(node);
|
||||
if (ret != RCL_RET_OK) {
|
||||
RCUTILS_LOG_ERROR_NAMED(
|
||||
"rclcpp",
|
||||
"Error in destruction of rosout publisher: %s", rcl_get_error_string().str);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rcl_node_fini(node) != RCL_RET_OK) {
|
||||
RCUTILS_LOG_ERROR_NAMED(
|
||||
"rclcpp",
|
||||
|
||||
@@ -498,6 +498,50 @@ NodeGraph::count_subscribers(const std::string & topic_name) const
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t
|
||||
NodeGraph::count_clients(const std::string & service_name) const
|
||||
{
|
||||
auto rcl_node_handle = node_base_->get_rcl_node_handle();
|
||||
|
||||
auto fqdn = rclcpp::expand_topic_or_service_name(
|
||||
service_name,
|
||||
rcl_node_get_name(rcl_node_handle),
|
||||
rcl_node_get_namespace(rcl_node_handle),
|
||||
true);
|
||||
|
||||
size_t count;
|
||||
auto ret = rcl_count_clients(rcl_node_handle, fqdn.c_str(), &count);
|
||||
if (ret != RMW_RET_OK) {
|
||||
// *INDENT-OFF*
|
||||
throw std::runtime_error(
|
||||
std::string("could not count clients: ") + rmw_get_error_string().str);
|
||||
// *INDENT-ON*
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t
|
||||
NodeGraph::count_services(const std::string & service_name) const
|
||||
{
|
||||
auto rcl_node_handle = node_base_->get_rcl_node_handle();
|
||||
|
||||
auto fqdn = rclcpp::expand_topic_or_service_name(
|
||||
service_name,
|
||||
rcl_node_get_name(rcl_node_handle),
|
||||
rcl_node_get_namespace(rcl_node_handle),
|
||||
true);
|
||||
|
||||
size_t count;
|
||||
auto ret = rcl_count_services(rcl_node_handle, fqdn.c_str(), &count);
|
||||
if (ret != RMW_RET_OK) {
|
||||
// *INDENT-OFF*
|
||||
throw std::runtime_error(
|
||||
std::string("could not count services: ") + rmw_get_error_string().str);
|
||||
// *INDENT-ON*
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
const rcl_guard_condition_t *
|
||||
NodeGraph::get_graph_guard_condition() const
|
||||
{
|
||||
|
||||
@@ -1059,7 +1059,7 @@ NodeParameters::list_parameters(const std::vector<std::string> & prefixes, uint6
|
||||
if (depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) {
|
||||
return true;
|
||||
}
|
||||
std::string substr = kv.first.substr(prefix.length());
|
||||
std::string substr = kv.first.substr(prefix.length() + 1);
|
||||
return separators_less_than_depth(substr);
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -113,7 +113,7 @@ SignalHandler::get_logger()
|
||||
SignalHandler &
|
||||
SignalHandler::get_global_signal_handler()
|
||||
{
|
||||
static SignalHandler signal_handler;
|
||||
static SignalHandler & signal_handler = *new SignalHandler();
|
||||
return signal_handler;
|
||||
}
|
||||
|
||||
|
||||
@@ -236,6 +236,7 @@ public:
|
||||
rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock_interface,
|
||||
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters_interface)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(node_base_lock_);
|
||||
node_base_ = node_base_interface;
|
||||
node_topics_ = node_topics_interface;
|
||||
node_graph_ = node_graph_interface;
|
||||
@@ -280,17 +281,14 @@ public:
|
||||
parameter_subscription_ = rclcpp::AsyncParametersClient::on_parameter_event(
|
||||
node_topics_,
|
||||
[this](std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event) {
|
||||
if (node_base_ != nullptr) {
|
||||
this->on_parameter_event(event);
|
||||
}
|
||||
// Do nothing if node_base_ is nullptr because it means the TimeSource is now
|
||||
// without an attached node
|
||||
this->on_parameter_event(event);
|
||||
});
|
||||
}
|
||||
|
||||
// Detach the attached node
|
||||
void detachNode()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(node_base_lock_);
|
||||
// destroy_clock_sub() *must* be first here, to ensure that the executor
|
||||
// can't possibly call any of the callbacks as we are cleaning up.
|
||||
destroy_clock_sub();
|
||||
@@ -327,6 +325,7 @@ private:
|
||||
std::thread clock_executor_thread_;
|
||||
|
||||
// Preserve the node reference
|
||||
std::mutex node_base_lock_;
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_{nullptr};
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_{nullptr};
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_{nullptr};
|
||||
@@ -464,6 +463,14 @@ private:
|
||||
// Callback for parameter updates
|
||||
void on_parameter_event(std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(node_base_lock_);
|
||||
|
||||
if (node_base_ == nullptr) {
|
||||
// Do nothing if node_base_ is nullptr because it means the TimeSource is now
|
||||
// without an attached node
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter out events on 'use_sim_time' parameter instances in other nodes.
|
||||
if (event->node != node_base_->get_fully_qualified_name()) {
|
||||
return;
|
||||
|
||||
@@ -34,13 +34,7 @@ if(TARGET test_exceptions)
|
||||
target_link_libraries(test_exceptions ${PROJECT_NAME} mimick)
|
||||
endif()
|
||||
|
||||
# Increasing timeout because connext can take a long time to destroy nodes
|
||||
# TODO(brawner) remove when destroying Node for Connext is resolved. See:
|
||||
# https://github.com/ros2/rclcpp/issues/1250
|
||||
ament_add_gtest(
|
||||
test_allocator_memory_strategy
|
||||
strategies/test_allocator_memory_strategy.cpp
|
||||
TIMEOUT 360)
|
||||
ament_add_gtest(test_allocator_memory_strategy strategies/test_allocator_memory_strategy.cpp)
|
||||
if(TARGET test_allocator_memory_strategy)
|
||||
ament_target_dependencies(test_allocator_memory_strategy
|
||||
"rcl"
|
||||
@@ -81,6 +75,13 @@ if(TARGET test_client)
|
||||
)
|
||||
target_link_libraries(test_client ${PROJECT_NAME} mimick)
|
||||
endif()
|
||||
ament_add_gtest(test_copy_all_parameter_values test_copy_all_parameter_values.cpp)
|
||||
if(TARGET test_copy_all_parameter_values)
|
||||
ament_target_dependencies(test_copy_all_parameter_values
|
||||
"rcl_interfaces"
|
||||
)
|
||||
target_link_libraries(test_copy_all_parameter_values ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_create_timer test_create_timer.cpp)
|
||||
if(TARGET test_create_timer)
|
||||
ament_target_dependencies(test_create_timer
|
||||
@@ -669,8 +670,6 @@ if(TARGET test_interface_traits)
|
||||
target_link_libraries(test_interface_traits ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
# TODO(brawner) remove when destroying Node for Connext is resolved. See:
|
||||
# https://github.com/ros2/rclcpp/issues/1250
|
||||
ament_add_gtest(
|
||||
test_executors
|
||||
executors/test_executors.cpp
|
||||
|
||||
@@ -129,6 +129,9 @@ TEST_F(TestNodeGraph, construct_from_node)
|
||||
|
||||
EXPECT_EQ(0u, node_graph()->count_publishers("not_a_topic"));
|
||||
EXPECT_EQ(0u, node_graph()->count_subscribers("not_a_topic"));
|
||||
EXPECT_EQ(0u, node_graph()->count_clients("not_a_service"));
|
||||
EXPECT_EQ(0u, node_graph()->count_services("not_a_service"));
|
||||
|
||||
EXPECT_NE(nullptr, node_graph()->get_graph_guard_condition());
|
||||
|
||||
// get_graph_event is non-const
|
||||
@@ -534,6 +537,22 @@ TEST_F(TestNodeGraph, count_subscribers_rcl_error)
|
||||
std::runtime_error("could not count subscribers: error not set"));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, count_clients_rcl_error)
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_count_clients, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
node_graph()->count_clients("service"),
|
||||
std::runtime_error("could not count clients: error not set"));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, count_services_rcl_error)
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_count_services, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
node_graph()->count_services("service"),
|
||||
std::runtime_error("could not count services: error not set"));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, notify_shutdown)
|
||||
{
|
||||
EXPECT_NO_THROW(node()->get_node_graph_interface()->notify_shutdown());
|
||||
|
||||
@@ -95,15 +95,15 @@ TEST_F(TestNodeParameters, list_parameters)
|
||||
std::find(list_result2.names.begin(), list_result2.names.end(), parameter_name),
|
||||
list_result2.names.end());
|
||||
|
||||
// Check prefixes
|
||||
// Check prefixes and the depth relative to the given prefixes
|
||||
const std::string parameter_name2 = "prefix.new_parameter";
|
||||
const rclcpp::ParameterValue value2(true);
|
||||
const rcl_interfaces::msg::ParameterDescriptor descriptor2;
|
||||
const auto added_parameter_value2 =
|
||||
node_parameters->declare_parameter(parameter_name2, value2, descriptor2, false);
|
||||
EXPECT_EQ(value.get<bool>(), added_parameter_value.get<bool>());
|
||||
EXPECT_EQ(value2.get<bool>(), added_parameter_value2.get<bool>());
|
||||
prefixes = {"prefix"};
|
||||
auto list_result3 = node_parameters->list_parameters(prefixes, 2u);
|
||||
auto list_result3 = node_parameters->list_parameters(prefixes, 1u);
|
||||
EXPECT_EQ(1u, list_result3.names.size());
|
||||
EXPECT_NE(
|
||||
std::find(list_result3.names.begin(), list_result3.names.end(), parameter_name2),
|
||||
@@ -116,6 +116,13 @@ TEST_F(TestNodeParameters, list_parameters)
|
||||
EXPECT_NE(
|
||||
std::find(list_result4.names.begin(), list_result4.names.end(), parameter_name),
|
||||
list_result4.names.end());
|
||||
|
||||
// Return all parameters when the depth = 0
|
||||
auto list_result5 = node_parameters->list_parameters(prefixes, 0u);
|
||||
EXPECT_EQ(1u, list_result5.names.size());
|
||||
EXPECT_NE(
|
||||
std::find(list_result5.names.begin(), list_result5.names.end(), parameter_name),
|
||||
list_result5.names.end());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, parameter_overrides)
|
||||
|
||||
88
rclcpp/test/rclcpp/test_copy_all_parameter_values.cpp
Normal file
88
rclcpp/test/rclcpp/test_copy_all_parameter_values.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2023 Open Navigation LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "rclcpp/copy_all_parameter_values.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
class TestNode : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestNode, TestParamCopying)
|
||||
{
|
||||
auto node1 = std::make_shared<rclcpp::Node>("test_node1");
|
||||
auto node2 = std::make_shared<rclcpp::Node>("test_node2");
|
||||
|
||||
// Tests for (1) multiple types, (2) recursion, (3) overriding values
|
||||
node1->declare_parameter("Foo1", rclcpp::ParameterValue(std::string(("bar1"))));
|
||||
node1->declare_parameter("Foo2", rclcpp::ParameterValue(0.123));
|
||||
node1->declare_parameter("Foo", rclcpp::ParameterValue(std::string(("bar"))));
|
||||
node1->declare_parameter("Foo.bar", rclcpp::ParameterValue(std::string(("steve"))));
|
||||
node2->declare_parameter("Foo", rclcpp::ParameterValue(std::string(("barz2"))));
|
||||
|
||||
// Show Node2 is empty of Node1's parameters, but contains its own
|
||||
EXPECT_FALSE(node2->has_parameter("Foo1"));
|
||||
EXPECT_FALSE(node2->has_parameter("Foo2"));
|
||||
EXPECT_FALSE(node2->has_parameter("Foo.bar"));
|
||||
EXPECT_TRUE(node2->has_parameter("Foo"));
|
||||
EXPECT_EQ(node2->get_parameter("Foo").as_string(), std::string("barz2"));
|
||||
|
||||
bool override = false;
|
||||
rclcpp::copy_all_parameter_values(node1, node2, override);
|
||||
|
||||
// Test new parameters exist, of expected value, and original param is not overridden
|
||||
EXPECT_TRUE(node2->has_parameter("Foo1"));
|
||||
EXPECT_EQ(node2->get_parameter("Foo1").as_string(), std::string("bar1"));
|
||||
EXPECT_TRUE(node2->has_parameter("Foo2"));
|
||||
EXPECT_EQ(node2->get_parameter("Foo2").as_double(), 0.123);
|
||||
EXPECT_TRUE(node2->has_parameter("Foo.bar"));
|
||||
EXPECT_EQ(node2->get_parameter("Foo.bar").as_string(), std::string("steve"));
|
||||
EXPECT_TRUE(node2->has_parameter("Foo"));
|
||||
EXPECT_EQ(node2->get_parameter("Foo").as_string(), std::string("barz2"));
|
||||
|
||||
// Test if parameter overrides are permissible that Node2's value is overridden
|
||||
override = true;
|
||||
rclcpp::copy_all_parameter_values(node1, node2, override);
|
||||
EXPECT_EQ(node2->get_parameter("Foo").as_string(), std::string("bar"));
|
||||
}
|
||||
|
||||
TEST_F(TestNode, TestParamCopyingExceptions)
|
||||
{
|
||||
auto node1 = std::make_shared<rclcpp::Node>("test_node1");
|
||||
auto node2 = std::make_shared<rclcpp::Node>("test_node2");
|
||||
|
||||
// Tests for Parameter value conflicts handled
|
||||
node1->declare_parameter("Foo", rclcpp::ParameterValue(std::string(("bar"))));
|
||||
node2->declare_parameter("Foo", rclcpp::ParameterValue(0.123));
|
||||
|
||||
bool override = true;
|
||||
EXPECT_NO_THROW(
|
||||
rclcpp::copy_all_parameter_values(node1, node2, override));
|
||||
|
||||
// Tests for Parameter read-only handled
|
||||
node1->declare_parameter("Foo1", rclcpp::ParameterValue(std::string(("bar"))));
|
||||
node2->declare_parameter("Foo1", rclcpp::ParameterValue(0.123));
|
||||
EXPECT_NO_THROW(rclcpp::copy_all_parameter_values(node1, node2, override));
|
||||
}
|
||||
@@ -3311,6 +3311,9 @@ TEST_F(TestNode, get_entity_names) {
|
||||
const auto service_names_and_types = node->get_service_names_and_types();
|
||||
EXPECT_EQ(service_names_and_types.end(), service_names_and_types.find("service"));
|
||||
|
||||
EXPECT_EQ(0u, node->count_clients("service"));
|
||||
EXPECT_EQ(0u, node->count_services("service"));
|
||||
|
||||
const auto service_names_and_types_by_node =
|
||||
node->get_service_names_and_types_by_node("node", "/ns");
|
||||
EXPECT_EQ(
|
||||
|
||||
@@ -145,11 +145,6 @@ TEST(TestSerializedMessage, reserve) {
|
||||
// Resize using reserve method
|
||||
serialized_msg.reserve(15);
|
||||
EXPECT_EQ(15u, serialized_msg.capacity());
|
||||
|
||||
// Use invalid value throws exception
|
||||
EXPECT_THROW(
|
||||
{serialized_msg.reserve(-1);},
|
||||
rclcpp::exceptions::RCLBadAlloc);
|
||||
}
|
||||
|
||||
TEST(TestSerializedMessage, serialization) {
|
||||
|
||||
@@ -3,6 +3,12 @@ Changelog for package rclcpp_action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
23.2.0 (2023-10-09)
|
||||
-------------------
|
||||
|
||||
23.1.0 (2023-10-04)
|
||||
-------------------
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Update API docs links in package READMEs (`#2302 <https://github.com/ros2/rclcpp/issues/2302>`_)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="2">
|
||||
<name>rclcpp_action</name>
|
||||
<version>23.0.0</version>
|
||||
<version>23.2.0</version>
|
||||
<description>Adds action APIs for C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
Changelog for package rclcpp_components
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
23.2.0 (2023-10-09)
|
||||
-------------------
|
||||
|
||||
23.1.0 (2023-10-04)
|
||||
-------------------
|
||||
* Add missing header required by the rclcpp::NodeOptions type (`#2324 <https://github.com/ros2/rclcpp/issues/2324>`_)
|
||||
* Contributors: Ignacio Vizzo
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Update API docs links in package READMEs (`#2302 <https://github.com/ros2/rclcpp/issues/2302>`_)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#ifndef RCLCPP_COMPONENTS__NODE_FACTORY_HPP__
|
||||
#define RCLCPP_COMPONENTS__NODE_FACTORY_HPP__
|
||||
|
||||
#include "rclcpp/node_options.hpp"
|
||||
#include "rclcpp_components/node_instance_wrapper.hpp"
|
||||
|
||||
namespace rclcpp_components
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="2">
|
||||
<name>rclcpp_components</name>
|
||||
<version>23.0.0</version>
|
||||
<version>23.2.0</version>
|
||||
<description>Package containing tools for dynamically loadable components</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -3,6 +3,14 @@ Changelog for package rclcpp_lifecycle
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
23.2.0 (2023-10-09)
|
||||
-------------------
|
||||
* add clients & services count (`#2072 <https://github.com/ros2/rclcpp/issues/2072>`_)
|
||||
* Contributors: Minju, Lee
|
||||
|
||||
23.1.0 (2023-10-04)
|
||||
-------------------
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Update API docs links in package READMEs (`#2302 <https://github.com/ros2/rclcpp/issues/2302>`_)
|
||||
|
||||
@@ -690,6 +690,22 @@ public:
|
||||
size_t
|
||||
count_subscribers(const std::string & topic_name) const;
|
||||
|
||||
/// Return the number of clients created for a given service.
|
||||
/**
|
||||
* \sa rclcpp::Node::count_clients
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
size_t
|
||||
count_clients(const std::string & service_name) const;
|
||||
|
||||
/// Return the number of services created for a given service.
|
||||
/**
|
||||
* \sa rclcpp::Node::count_services
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
size_t
|
||||
count_services(const std::string & service_name) const;
|
||||
|
||||
/// Return the topic endpoint information about publishers on a given topic.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_publishers_info_by_topic
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="2">
|
||||
<name>rclcpp_lifecycle</name>
|
||||
<version>23.0.0</version>
|
||||
<version>23.2.0</version>
|
||||
<description>Package containing a prototype for lifecycle implementation</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -386,6 +386,18 @@ LifecycleNode::count_subscribers(const std::string & topic_name) const
|
||||
return node_graph_->count_subscribers(topic_name);
|
||||
}
|
||||
|
||||
size_t
|
||||
LifecycleNode::count_clients(const std::string & service_name) const
|
||||
{
|
||||
return node_graph_->count_clients(service_name);
|
||||
}
|
||||
|
||||
size_t
|
||||
LifecycleNode::count_services(const std::string & service_name) const
|
||||
{
|
||||
return node_graph_->count_services(service_name);
|
||||
}
|
||||
|
||||
std::vector<rclcpp::TopicEndpointInfo>
|
||||
LifecycleNode::get_publishers_info_by_topic(const std::string & topic_name, bool no_mangle) const
|
||||
{
|
||||
|
||||
@@ -726,6 +726,17 @@ TEST_F(TestDefaultStateMachine, test_graph_services) {
|
||||
EXPECT_STREQ(
|
||||
service_names_and_types["/testnode/get_transition_graph"][0].c_str(),
|
||||
"lifecycle_msgs/srv/GetAvailableTransitions");
|
||||
|
||||
EXPECT_EQ(0u, test_node->count_clients("/testnode/change_state"));
|
||||
EXPECT_EQ(0u, test_node->count_clients("/testnode/get_available_states"));
|
||||
EXPECT_EQ(0u, test_node->count_clients("/testnode/get_available_transitions"));
|
||||
EXPECT_EQ(0u, test_node->count_clients("/testnode/get_state"));
|
||||
EXPECT_EQ(0u, test_node->count_clients("/testnode/get_transition_graph"));
|
||||
EXPECT_EQ(1u, test_node->count_services("/testnode/change_state"));
|
||||
EXPECT_EQ(1u, test_node->count_services("/testnode/get_available_states"));
|
||||
EXPECT_EQ(1u, test_node->count_services("/testnode/get_available_transitions"));
|
||||
EXPECT_EQ(1u, test_node->count_services("/testnode/get_state"));
|
||||
EXPECT_EQ(1u, test_node->count_services("/testnode/get_transition_graph"));
|
||||
}
|
||||
|
||||
TEST_F(TestDefaultStateMachine, test_graph_services_by_node) {
|
||||
|
||||
Reference in New Issue
Block a user