Compare commits

...

14 Commits

Author SHA1 Message Date
Chris Lalancette
13abc1beed 23.2.0 2023-10-09 15:31:54 +00:00
Chris Lalancette
e77c1fe550 Changelog.
Signed-off-by: Chris Lalancette <clalancette@gmail.com>
2023-10-09 15:31:47 +00:00
Minju, Lee
00b9d0a018 add clients & services count (#2072)
* add clients & services count

* add count clients,services tests

Signed-off-by: leeminju531 <dlalswn531@naver.com>
2023-10-09 10:36:00 -04:00
Tomoya Fujita
77c7aaf917 remove invalid sized allocation test for SerializedMessage. (#2330)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2023-10-06 15:15:34 -07:00
Steve Macenski
9019a8d9b7 Adding API to copy all parameters from one node to another (#2304)
Signed-off-by: stevemacenski <stevenmacenski@gmail.com>
2023-10-05 13:00:16 -07:00
Chris Lalancette
0644f220a2 23.1.0 2023-10-04 13:09:05 +00:00
Chris Lalancette
32438a6a67 Changelog.
Signed-off-by: Chris Lalancette <clalancette@gmail.com>
2023-10-04 13:08:56 +00:00
Ignacio Vizzo
d6bd8baac5 Add missing header required by the rclcpp::NodeOptions type (#2324)
Signed-off-by: Ignacio Vizzo <ignacio@dexory.com>
2023-10-04 08:18:21 -04:00
Chris Lalancette
623c3eb874 Add locking to protect the TimeSource::NodeState::node_base_ (#2320)
We need this because it is possible for one thread to
be handling the on_parameter_event callback while another
one is detaching the node.  This lock will protect that
from happening.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
2023-10-03 14:16:49 -04:00
Tully Foote
7c1143dc15 Update SignalHandler get_global_signal_handler to avoid complex types in static memory (#2316)
* Update SignalHandler get_global_signal_handler to avoid complex types in static memory

This was flagged by msan as a problem.

There's a description of why this is a potential problem here: https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables

Signed-off-by: Tully Foote <tullyfoote@intrinsic.ai>
Co-authored-by: William Woodall <william+github@osrfoundation.org>
2023-09-29 16:13:43 -07:00
Lucas Wendland
9ff864c6ae Removing Old Connext Tests (#2313)
* Removing Old Connext Tests

Signed-off-by: CursedRock17 <mtglucas1@gmail.com>
2023-09-28 08:29:47 -04:00
Lucas Wendland
13182b5aad Documentation for list_parameters (#2315)
* list_parameters documentation

Signed-off-by: CursedRock17 <mtglucas1@gmail.com>
2023-09-27 17:14:53 -04:00
Tomoya Fujita
9284d7cefa Decouple rosout publisher init from node init. (#2174)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2023-09-21 18:44:13 -07:00
Minju, Lee
c42745c5ba fix the depth to relative in list_parameters (#2300)
* fix the depth to relative in list_parameters

Signed-off-by: leeminju531 <dlalswn531@naver.com>
2023-09-18 17:13:11 -04:00
29 changed files with 453 additions and 45 deletions

View File

@@ -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>`_)

View 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_

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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"

View File

@@ -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>

View File

@@ -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
{

View File

@@ -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",

View File

@@ -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
{

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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());

View File

@@ -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)

View 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));
}

View File

@@ -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(

View File

@@ -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) {

View File

@@ -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>`_)

View File

@@ -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>

View File

@@ -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>`_)

View File

@@ -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

View File

@@ -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>

View File

@@ -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>`_)

View File

@@ -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

View File

@@ -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>

View File

@@ -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
{

View File

@@ -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) {