Compare commits
5 Commits
runtime_in
...
16.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae8b033ae0 | ||
|
|
4fa3489cfd | ||
|
|
7f575103d8 | ||
|
|
166007dde3 | ||
|
|
cf2a27805e |
@@ -2,6 +2,14 @@
|
|||||||
Changelog for package rclcpp
|
Changelog for package rclcpp
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
16.0.2 (2022-11-07)
|
||||||
|
-------------------
|
||||||
|
* fix mismatched issue if using zero_allocate (`#1995 <https://github.com/ros2/rclcpp/issues/1995>`_) (`#2026 <https://github.com/ros2/rclcpp/issues/2026>`_)
|
||||||
|
* use regex for wildcard matching (backport `#1839 <https://github.com/ros2/rclcpp/issues/1839>`_) (`#1986 <https://github.com/ros2/rclcpp/issues/1986>`_)
|
||||||
|
* Drop wrong template specialization (`#1926 <https://github.com/ros2/rclcpp/issues/1926>`_) (`#1937 <https://github.com/ros2/rclcpp/issues/1937>`_)
|
||||||
|
* Add statistics for handle_loaned_message (`#1927 <https://github.com/ros2/rclcpp/issues/1927>`_) (`#1932 <https://github.com/ros2/rclcpp/issues/1932>`_)
|
||||||
|
* Contributors: mergify[bot]
|
||||||
|
|
||||||
16.0.1 (2022-04-13)
|
16.0.1 (2022-04-13)
|
||||||
-------------------
|
-------------------
|
||||||
* remove DEFINE_CONTENT_FILTER cmake option (`#1914 <https://github.com/ros2/rclcpp/issues/1914>`_)
|
* remove DEFINE_CONTENT_FILTER cmake option (`#1914 <https://github.com/ros2/rclcpp/issues/1914>`_)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#ifndef RCLCPP__ALLOCATOR__ALLOCATOR_COMMON_HPP_
|
#ifndef RCLCPP__ALLOCATOR__ALLOCATOR_COMMON_HPP_
|
||||||
#define RCLCPP__ALLOCATOR__ALLOCATOR_COMMON_HPP_
|
#define RCLCPP__ALLOCATOR__ALLOCATOR_COMMON_HPP_
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "rcl/allocator.h"
|
#include "rcl/allocator.h"
|
||||||
@@ -39,6 +40,22 @@ void * retyped_allocate(size_t size, void * untyped_allocator)
|
|||||||
return std::allocator_traits<Alloc>::allocate(*typed_allocator, size);
|
return std::allocator_traits<Alloc>::allocate(*typed_allocator, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Alloc>
|
||||||
|
void * retyped_zero_allocate(size_t number_of_elem, size_t size_of_elem, void * untyped_allocator)
|
||||||
|
{
|
||||||
|
auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
|
||||||
|
if (!typed_allocator) {
|
||||||
|
throw std::runtime_error("Received incorrect allocator type");
|
||||||
|
}
|
||||||
|
size_t size = number_of_elem * size_of_elem;
|
||||||
|
void * allocated_memory =
|
||||||
|
std::allocator_traits<Alloc>::allocate(*typed_allocator, size);
|
||||||
|
if (allocated_memory) {
|
||||||
|
std::memset(allocated_memory, 0, size);
|
||||||
|
}
|
||||||
|
return allocated_memory;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T, typename Alloc>
|
template<typename T, typename Alloc>
|
||||||
void retyped_deallocate(void * untyped_pointer, void * untyped_allocator)
|
void retyped_deallocate(void * untyped_pointer, void * untyped_allocator)
|
||||||
{
|
{
|
||||||
@@ -73,6 +90,7 @@ rcl_allocator_t get_rcl_allocator(Alloc & allocator)
|
|||||||
rcl_allocator_t rcl_allocator = rcl_get_default_allocator();
|
rcl_allocator_t rcl_allocator = rcl_get_default_allocator();
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
rcl_allocator.allocate = &retyped_allocate<Alloc>;
|
rcl_allocator.allocate = &retyped_allocate<Alloc>;
|
||||||
|
rcl_allocator.zero_allocate = &retyped_zero_allocate<Alloc>;
|
||||||
rcl_allocator.deallocate = &retyped_deallocate<T, Alloc>;
|
rcl_allocator.deallocate = &retyped_deallocate<T, Alloc>;
|
||||||
rcl_allocator.reallocate = &retyped_reallocate<T, Alloc>;
|
rcl_allocator.reallocate = &retyped_reallocate<T, Alloc>;
|
||||||
rcl_allocator.state = &allocator;
|
rcl_allocator.state = &allocator;
|
||||||
|
|||||||
@@ -41,6 +41,16 @@ RCLCPP_PUBLIC
|
|||||||
ParameterMap
|
ParameterMap
|
||||||
parameter_map_from(const rcl_params_t * const c_params);
|
parameter_map_from(const rcl_params_t * const c_params);
|
||||||
|
|
||||||
|
/// Convert parameters from rcl_yaml_param_parser into C++ class instances.
|
||||||
|
/// \param[in] c_params C structures containing parameters for multiple nodes.
|
||||||
|
/// \param[in] node_fqn a Fully Qualified Name of node, default value is nullptr.
|
||||||
|
/// If it's not nullptr, return the relative node parameters belonging to this node_fqn.
|
||||||
|
/// \returns a map where the keys are fully qualified node names and values a list of parameters.
|
||||||
|
/// \throws InvalidParametersException if the `rcl_params_t` is inconsistent or invalid.
|
||||||
|
RCLCPP_PUBLIC
|
||||||
|
ParameterMap
|
||||||
|
parameter_map_from(const rcl_params_t * const c_params, const char * node_fqn);
|
||||||
|
|
||||||
/// Convert parameter value from rcl_yaml_param_parser into a C++ class instance.
|
/// Convert parameter value from rcl_yaml_param_parser into a C++ class instance.
|
||||||
/// \param[in] c_value C structure containing a value of a parameter.
|
/// \param[in] c_value C structure containing a value of a parameter.
|
||||||
/// \returns an instance of a parameter value
|
/// \returns an instance of a parameter value
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ struct PublisherOptionsWithAllocator : public PublisherOptionsBase
|
|||||||
/// Optional custom allocator.
|
/// Optional custom allocator.
|
||||||
std::shared_ptr<Allocator> allocator = nullptr;
|
std::shared_ptr<Allocator> allocator = nullptr;
|
||||||
|
|
||||||
PublisherOptionsWithAllocator<Allocator>() {}
|
PublisherOptionsWithAllocator() {}
|
||||||
|
|
||||||
/// Constructor using base class as input.
|
/// Constructor using base class as input.
|
||||||
explicit PublisherOptionsWithAllocator(const PublisherOptionsBase & publisher_options_base)
|
explicit PublisherOptionsWithAllocator(const PublisherOptionsBase & publisher_options_base)
|
||||||
|
|||||||
@@ -363,11 +363,31 @@ public:
|
|||||||
void * loaned_message,
|
void * loaned_message,
|
||||||
const rclcpp::MessageInfo & message_info) override
|
const rclcpp::MessageInfo & message_info) override
|
||||||
{
|
{
|
||||||
|
if (matches_any_intra_process_publishers(&message_info.get_rmw_message_info().publisher_gid)) {
|
||||||
|
// In this case, the message will be delivered via intra process and
|
||||||
|
// we should ignore this copy of the message.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto typed_message = static_cast<ROSMessageType *>(loaned_message);
|
auto typed_message = static_cast<ROSMessageType *>(loaned_message);
|
||||||
// message is loaned, so we have to make sure that the deleter does not deallocate the message
|
// message is loaned, so we have to make sure that the deleter does not deallocate the message
|
||||||
auto sptr = std::shared_ptr<ROSMessageType>(
|
auto sptr = std::shared_ptr<ROSMessageType>(
|
||||||
typed_message, [](ROSMessageType * msg) {(void) msg;});
|
typed_message, [](ROSMessageType * msg) {(void) msg;});
|
||||||
|
|
||||||
|
std::chrono::time_point<std::chrono::system_clock> now;
|
||||||
|
if (subscription_topic_statistics_) {
|
||||||
|
// get current time before executing callback to
|
||||||
|
// exclude callback duration from topic statistics result.
|
||||||
|
now = std::chrono::system_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
any_callback_.dispatch(sptr, message_info);
|
any_callback_.dispatch(sptr, message_info);
|
||||||
|
|
||||||
|
if (subscription_topic_statistics_) {
|
||||||
|
const auto nanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(now);
|
||||||
|
const auto time = rclcpp::Time(nanos.time_since_epoch().count());
|
||||||
|
subscription_topic_statistics_->handle_message(*typed_message, time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the borrowed message.
|
/// Return the borrowed message.
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ struct SubscriptionOptionsWithAllocator : public SubscriptionOptionsBase
|
|||||||
/// Optional custom allocator.
|
/// Optional custom allocator.
|
||||||
std::shared_ptr<Allocator> allocator = nullptr;
|
std::shared_ptr<Allocator> allocator = nullptr;
|
||||||
|
|
||||||
SubscriptionOptionsWithAllocator<Allocator>() {}
|
SubscriptionOptionsWithAllocator() {}
|
||||||
|
|
||||||
/// Constructor using base class as input.
|
/// Constructor using base class as input.
|
||||||
explicit SubscriptionOptionsWithAllocator(
|
explicit SubscriptionOptionsWithAllocator(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||||
<package format="2">
|
<package format="2">
|
||||||
<name>rclcpp</name>
|
<name>rclcpp</name>
|
||||||
<version>16.0.1</version>
|
<version>16.0.2</version>
|
||||||
<description>The ROS client library in C++.</description>
|
<description>The ROS client library in C++.</description>
|
||||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||||
|
|||||||
@@ -51,18 +51,13 @@ rclcpp::detail::resolve_parameter_overrides(
|
|||||||
[params]() {
|
[params]() {
|
||||||
rcl_yaml_node_struct_fini(params);
|
rcl_yaml_node_struct_fini(params);
|
||||||
});
|
});
|
||||||
rclcpp::ParameterMap initial_map = rclcpp::parameter_map_from(params);
|
rclcpp::ParameterMap initial_map = rclcpp::parameter_map_from(params, node_fqn.c_str());
|
||||||
|
|
||||||
// Enforce wildcard matching precedence
|
if (initial_map.count(node_fqn) > 0) {
|
||||||
// TODO(cottsay) implement further wildcard matching
|
// Combine parameter yaml files, overwriting values in older ones
|
||||||
const std::array<std::string, 2> node_matching_names{"/**", node_fqn};
|
for (const rclcpp::Parameter & param : initial_map.at(node_fqn)) {
|
||||||
for (const auto & node_name : node_matching_names) {
|
result[param.get_name()] =
|
||||||
if (initial_map.count(node_name) > 0) {
|
rclcpp::ParameterValue(param.get_value_message());
|
||||||
// Combine parameter yaml files, overwriting values in older ones
|
|
||||||
for (const rclcpp::Parameter & param : initial_map.at(node_name)) {
|
|
||||||
result[param.get_name()] =
|
|
||||||
rclcpp::ParameterValue(param.get_value_message());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,10 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "rcpputils/find_and_replace.hpp"
|
||||||
#include "rclcpp/parameter_map.hpp"
|
#include "rclcpp/parameter_map.hpp"
|
||||||
|
|
||||||
using rclcpp::exceptions::InvalidParametersException;
|
using rclcpp::exceptions::InvalidParametersException;
|
||||||
@@ -24,6 +26,12 @@ using rclcpp::ParameterValue;
|
|||||||
|
|
||||||
ParameterMap
|
ParameterMap
|
||||||
rclcpp::parameter_map_from(const rcl_params_t * const c_params)
|
rclcpp::parameter_map_from(const rcl_params_t * const c_params)
|
||||||
|
{
|
||||||
|
return parameter_map_from(c_params, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterMap
|
||||||
|
rclcpp::parameter_map_from(const rcl_params_t * const c_params, const char * node_fqn)
|
||||||
{
|
{
|
||||||
if (NULL == c_params) {
|
if (NULL == c_params) {
|
||||||
throw InvalidParametersException("parameters struct is NULL");
|
throw InvalidParametersException("parameters struct is NULL");
|
||||||
@@ -49,6 +57,17 @@ rclcpp::parameter_map_from(const rcl_params_t * const c_params)
|
|||||||
node_name = c_node_name;
|
node_name = c_node_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node_fqn) {
|
||||||
|
// Update the regular expression ["/*" -> "(/\\w+)" and "/**" -> "(/\\w+)*"]
|
||||||
|
std::string regex = rcpputils::find_and_replace(node_name, "/*", "(/\\w+)");
|
||||||
|
if (!std::regex_match(node_fqn, std::regex(regex))) {
|
||||||
|
// No need to parse the items because the user just care about node_fqn
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_name = node_fqn;
|
||||||
|
}
|
||||||
|
|
||||||
const rcl_node_params_t * const c_params_node = &(c_params->params[n]);
|
const rcl_node_params_t * const c_params_node = &(c_params->params[n]);
|
||||||
|
|
||||||
std::vector<Parameter> & params_node = parameters[node_name];
|
std::vector<Parameter> & params_node = parameters[node_name];
|
||||||
@@ -65,6 +84,7 @@ rclcpp::parameter_map_from(const rcl_params_t * const c_params)
|
|||||||
params_node.emplace_back(c_param_name, parameter_value_from(c_param_value));
|
params_node.emplace_back(c_param_name, parameter_value_from(c_param_value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,53 @@ TEST(TestAllocatorCommon, retyped_allocate) {
|
|||||||
EXPECT_NO_THROW(code2());
|
EXPECT_NO_THROW(code2());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(TestAllocatorCommon, retyped_zero_allocate_basic) {
|
||||||
|
std::allocator<int> allocator;
|
||||||
|
void * untyped_allocator = &allocator;
|
||||||
|
void * allocated_mem =
|
||||||
|
rclcpp::allocator::retyped_zero_allocate<std::allocator<char>>(20u, 1u, untyped_allocator);
|
||||||
|
ASSERT_TRUE(nullptr != allocated_mem);
|
||||||
|
|
||||||
|
auto code = [&untyped_allocator, allocated_mem]() {
|
||||||
|
rclcpp::allocator::retyped_deallocate<char, std::allocator<char>>(
|
||||||
|
allocated_mem, untyped_allocator);
|
||||||
|
};
|
||||||
|
EXPECT_NO_THROW(code());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestAllocatorCommon, retyped_zero_allocate) {
|
||||||
|
std::allocator<int> allocator;
|
||||||
|
void * untyped_allocator = &allocator;
|
||||||
|
void * allocated_mem =
|
||||||
|
rclcpp::allocator::retyped_zero_allocate<std::allocator<char>>(20u, 1u, untyped_allocator);
|
||||||
|
// The more natural check here is ASSERT_NE(nullptr, ptr), but clang static
|
||||||
|
// analysis throws a false-positive memory leak warning. Use ASSERT_TRUE instead.
|
||||||
|
ASSERT_TRUE(nullptr != allocated_mem);
|
||||||
|
|
||||||
|
auto code = [&untyped_allocator, allocated_mem]() {
|
||||||
|
rclcpp::allocator::retyped_deallocate<int, std::allocator<int>>(
|
||||||
|
allocated_mem, untyped_allocator);
|
||||||
|
};
|
||||||
|
EXPECT_NO_THROW(code());
|
||||||
|
|
||||||
|
allocated_mem = allocator.allocate(1);
|
||||||
|
// The more natural check here is ASSERT_NE(nullptr, ptr), but clang static
|
||||||
|
// analysis throws a false-positive memory leak warning. Use ASSERT_TRUE instead.
|
||||||
|
ASSERT_TRUE(nullptr != allocated_mem);
|
||||||
|
void * reallocated_mem =
|
||||||
|
rclcpp::allocator::retyped_reallocate<int, std::allocator<int>>(
|
||||||
|
allocated_mem, 2u, untyped_allocator);
|
||||||
|
// The more natural check here is ASSERT_NE(nullptr, ptr), but clang static
|
||||||
|
// analysis throws a false-positive memory leak warning. Use ASSERT_TRUE instead.
|
||||||
|
ASSERT_TRUE(nullptr != reallocated_mem);
|
||||||
|
|
||||||
|
auto code2 = [&untyped_allocator, reallocated_mem]() {
|
||||||
|
rclcpp::allocator::retyped_deallocate<int, std::allocator<int>>(
|
||||||
|
reallocated_mem, untyped_allocator);
|
||||||
|
};
|
||||||
|
EXPECT_NO_THROW(code2());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(TestAllocatorCommon, get_rcl_allocator) {
|
TEST(TestAllocatorCommon, get_rcl_allocator) {
|
||||||
std::allocator<int> allocator;
|
std::allocator<int> allocator;
|
||||||
auto rcl_allocator = rclcpp::allocator::get_rcl_allocator<int>(allocator);
|
auto rcl_allocator = rclcpp::allocator::get_rcl_allocator<int>(allocator);
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
#include "../../mocking_utils/patch.hpp"
|
#include "../../mocking_utils/patch.hpp"
|
||||||
#include "../../utils/rclcpp_gtest_macros.hpp"
|
#include "../../utils/rclcpp_gtest_macros.hpp"
|
||||||
|
|
||||||
|
#include "rcpputils/filesystem_helper.hpp"
|
||||||
|
|
||||||
class TestNodeParameters : public ::testing::Test
|
class TestNodeParameters : public ::testing::Test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -47,6 +49,7 @@ public:
|
|||||||
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||||
node->get_node_parameters_interface().get());
|
node->get_node_parameters_interface().get());
|
||||||
ASSERT_NE(nullptr, node_parameters);
|
ASSERT_NE(nullptr, node_parameters);
|
||||||
|
test_resources_path /= "test_node_parameters";
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown()
|
void TearDown()
|
||||||
@@ -57,6 +60,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
std::shared_ptr<rclcpp::Node> node;
|
std::shared_ptr<rclcpp::Node> node;
|
||||||
rclcpp::node_interfaces::NodeParameters * node_parameters;
|
rclcpp::node_interfaces::NodeParameters * node_parameters;
|
||||||
|
|
||||||
|
rcpputils::fs::path test_resources_path{TEST_RESOURCES_DIRECTORY};
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(TestNodeParameters, construct_destruct_rcl_errors) {
|
TEST_F(TestNodeParameters, construct_destruct_rcl_errors) {
|
||||||
@@ -199,3 +204,130 @@ TEST_F(TestNodeParameters, add_remove_parameters_callback) {
|
|||||||
node_parameters->remove_on_set_parameters_callback(handle.get()),
|
node_parameters->remove_on_set_parameters_callback(handle.get()),
|
||||||
std::runtime_error("Callback doesn't exist"));
|
std::runtime_error("Callback doesn't exist"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(TestNodeParameters, wildcard_with_namespace)
|
||||||
|
{
|
||||||
|
rclcpp::NodeOptions opts;
|
||||||
|
opts.arguments(
|
||||||
|
{
|
||||||
|
"--ros-args",
|
||||||
|
"--params-file", (test_resources_path / "wildcards.yaml").string()
|
||||||
|
});
|
||||||
|
|
||||||
|
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node2", "ns", opts);
|
||||||
|
|
||||||
|
auto * node_parameters =
|
||||||
|
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||||
|
node->get_node_parameters_interface().get());
|
||||||
|
ASSERT_NE(nullptr, node_parameters);
|
||||||
|
|
||||||
|
const auto & parameter_overrides = node_parameters->get_parameter_overrides();
|
||||||
|
EXPECT_EQ(7u, parameter_overrides.size());
|
||||||
|
EXPECT_EQ(parameter_overrides.at("full_wild").get<std::string>(), "full_wild");
|
||||||
|
EXPECT_EQ(parameter_overrides.at("namespace_wild").get<std::string>(), "namespace_wild");
|
||||||
|
EXPECT_EQ(
|
||||||
|
parameter_overrides.at("namespace_wild_another").get<std::string>(),
|
||||||
|
"namespace_wild_another");
|
||||||
|
EXPECT_EQ(
|
||||||
|
parameter_overrides.at("namespace_wild_one_star").get<std::string>(),
|
||||||
|
"namespace_wild_one_star");
|
||||||
|
EXPECT_EQ(parameter_overrides.at("node_wild_in_ns").get<std::string>(), "node_wild_in_ns");
|
||||||
|
EXPECT_EQ(
|
||||||
|
parameter_overrides.at("node_wild_in_ns_another").get<std::string>(),
|
||||||
|
"node_wild_in_ns_another");
|
||||||
|
EXPECT_EQ(parameter_overrides.at("explicit_in_ns").get<std::string>(), "explicit_in_ns");
|
||||||
|
EXPECT_EQ(parameter_overrides.count("should_not_appear"), 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TestNodeParameters, wildcard_no_namespace)
|
||||||
|
{
|
||||||
|
rclcpp::NodeOptions opts;
|
||||||
|
opts.arguments(
|
||||||
|
{
|
||||||
|
"--ros-args",
|
||||||
|
"--params-file", (test_resources_path / "wildcards.yaml").string()
|
||||||
|
});
|
||||||
|
|
||||||
|
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node2", opts);
|
||||||
|
|
||||||
|
auto * node_parameters =
|
||||||
|
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||||
|
node->get_node_parameters_interface().get());
|
||||||
|
ASSERT_NE(nullptr, node_parameters);
|
||||||
|
|
||||||
|
const auto & parameter_overrides = node_parameters->get_parameter_overrides();
|
||||||
|
EXPECT_EQ(5u, parameter_overrides.size());
|
||||||
|
EXPECT_EQ(parameter_overrides.at("full_wild").get<std::string>(), "full_wild");
|
||||||
|
EXPECT_EQ(parameter_overrides.at("namespace_wild").get<std::string>(), "namespace_wild");
|
||||||
|
EXPECT_EQ(
|
||||||
|
parameter_overrides.at("namespace_wild_another").get<std::string>(),
|
||||||
|
"namespace_wild_another");
|
||||||
|
EXPECT_EQ(parameter_overrides.at("node_wild_no_ns").get<std::string>(), "node_wild_no_ns");
|
||||||
|
EXPECT_EQ(parameter_overrides.at("explicit_no_ns").get<std::string>(), "explicit_no_ns");
|
||||||
|
EXPECT_EQ(parameter_overrides.count("should_not_appear"), 0u);
|
||||||
|
// "/*" match exactly one token, not expect to get `namespace_wild_one_star`
|
||||||
|
EXPECT_EQ(parameter_overrides.count("namespace_wild_one_star"), 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TestNodeParameters, params_by_order)
|
||||||
|
{
|
||||||
|
rclcpp::NodeOptions opts;
|
||||||
|
opts.arguments(
|
||||||
|
{
|
||||||
|
"--ros-args",
|
||||||
|
"--params-file", (test_resources_path / "params_by_order.yaml").string()
|
||||||
|
});
|
||||||
|
|
||||||
|
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node2", "ns", opts);
|
||||||
|
|
||||||
|
auto * node_parameters =
|
||||||
|
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||||
|
node->get_node_parameters_interface().get());
|
||||||
|
ASSERT_NE(nullptr, node_parameters);
|
||||||
|
|
||||||
|
const auto & parameter_overrides = node_parameters->get_parameter_overrides();
|
||||||
|
EXPECT_EQ(3u, parameter_overrides.size());
|
||||||
|
EXPECT_EQ(parameter_overrides.at("a_value").get<std::string>(), "last_one_win");
|
||||||
|
EXPECT_EQ(parameter_overrides.at("foo").get<std::string>(), "foo");
|
||||||
|
EXPECT_EQ(parameter_overrides.at("bar").get<std::string>(), "bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TestNodeParameters, complicated_wildcards)
|
||||||
|
{
|
||||||
|
rclcpp::NodeOptions opts;
|
||||||
|
opts.arguments(
|
||||||
|
{
|
||||||
|
"--ros-args",
|
||||||
|
"--params-file", (test_resources_path / "complicated_wildcards.yaml").string()
|
||||||
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
// regex matched: /**/foo/*/bar
|
||||||
|
std::shared_ptr<rclcpp::Node> node =
|
||||||
|
std::make_shared<rclcpp::Node>("node2", "/a/b/c/foo/d/bar", opts);
|
||||||
|
|
||||||
|
auto * node_parameters =
|
||||||
|
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||||
|
node->get_node_parameters_interface().get());
|
||||||
|
ASSERT_NE(nullptr, node_parameters);
|
||||||
|
|
||||||
|
const auto & parameter_overrides = node_parameters->get_parameter_overrides();
|
||||||
|
EXPECT_EQ(2u, parameter_overrides.size());
|
||||||
|
EXPECT_EQ(parameter_overrides.at("foo").get<std::string>(), "foo");
|
||||||
|
EXPECT_EQ(parameter_overrides.at("bar").get<std::string>(), "bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// regex not matched: /**/foo/*/bar
|
||||||
|
std::shared_ptr<rclcpp::Node> node =
|
||||||
|
std::make_shared<rclcpp::Node>("node2", "/a/b/c/foo/bar", opts);
|
||||||
|
|
||||||
|
auto * node_parameters =
|
||||||
|
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||||
|
node->get_node_parameters_interface().get());
|
||||||
|
ASSERT_NE(nullptr, node_parameters);
|
||||||
|
|
||||||
|
const auto & parameter_overrides = node_parameters->get_parameter_overrides();
|
||||||
|
EXPECT_EQ(0u, parameter_overrides.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "rclcpp/parameter_map.hpp"
|
#include "rclcpp/parameter_map.hpp"
|
||||||
@@ -353,3 +354,132 @@ TEST(Test_parameter_map_from, string_array_param_value)
|
|||||||
c_params->params[0].parameter_values[0].string_array_value = NULL;
|
c_params->params[0].parameter_values[0].string_array_value = NULL;
|
||||||
rcl_yaml_node_struct_fini(c_params);
|
rcl_yaml_node_struct_fini(c_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Test_parameter_map_from, one_node_one_param_by_node_fqn)
|
||||||
|
{
|
||||||
|
rcl_params_t * c_params = make_params({"foo"});
|
||||||
|
make_node_params(c_params, 0, {"string_param"});
|
||||||
|
|
||||||
|
std::string hello_world = "hello world";
|
||||||
|
char * c_hello_world = new char[hello_world.length() + 1];
|
||||||
|
std::snprintf(c_hello_world, hello_world.size() + 1, "%s", hello_world.c_str());
|
||||||
|
c_params->params[0].parameter_values[0].string_value = c_hello_world;
|
||||||
|
|
||||||
|
rclcpp::ParameterMap map = rclcpp::parameter_map_from(c_params, "/foo");
|
||||||
|
const std::vector<rclcpp::Parameter> & params = map.at("/foo");
|
||||||
|
EXPECT_STREQ("string_param", params.at(0).get_name().c_str());
|
||||||
|
EXPECT_STREQ(hello_world.c_str(), params.at(0).get_value<std::string>().c_str());
|
||||||
|
|
||||||
|
c_params->params[0].parameter_values[0].string_value = NULL;
|
||||||
|
delete[] c_hello_world;
|
||||||
|
rcl_yaml_node_struct_fini(c_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Test_parameter_map_from, multi_nodes_same_param_name_by_node_fqn)
|
||||||
|
{
|
||||||
|
std::vector<std::string> node_names_keys = {
|
||||||
|
"/**", // index: 0
|
||||||
|
"/*", // index: 1
|
||||||
|
"/**/node", // index: 2
|
||||||
|
"/*/node", // index: 3
|
||||||
|
"/ns/node" // index: 4
|
||||||
|
};
|
||||||
|
|
||||||
|
rcl_params_t * c_params = make_params(node_names_keys);
|
||||||
|
|
||||||
|
std::vector<char *> param_values;
|
||||||
|
for (size_t i = 0; i < node_names_keys.size(); ++i) {
|
||||||
|
make_node_params(c_params, i, {"string_param"});
|
||||||
|
std::string hello_world = "hello world" + std::to_string(i);
|
||||||
|
char * c_hello_world = new char[hello_world.length() + 1];
|
||||||
|
std::snprintf(c_hello_world, hello_world.size() + 1, "%s", hello_world.c_str());
|
||||||
|
c_params->params[i].parameter_values[0].string_value = c_hello_world;
|
||||||
|
param_values.push_back(c_hello_world);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::vector<size_t>> node_fqn_expected = {
|
||||||
|
{"/ns/foo/another_node", {0}},
|
||||||
|
{"/another", {0, 1}},
|
||||||
|
{"/node", {0, 1, 2}},
|
||||||
|
{"/another_ns/node", {0, 2, 3}},
|
||||||
|
{"/ns/node", {0, 2, 3, 4}},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto & kv : node_fqn_expected) {
|
||||||
|
rclcpp::ParameterMap map = rclcpp::parameter_map_from(c_params, kv.first.c_str());
|
||||||
|
const std::vector<rclcpp::Parameter> & params = map.at(kv.first);
|
||||||
|
|
||||||
|
EXPECT_EQ(kv.second.size(), params.size());
|
||||||
|
for (size_t i = 0; i < params.size(); ++i) {
|
||||||
|
std::string param_value = "hello world" + std::to_string(kv.second[i]);
|
||||||
|
EXPECT_STREQ("string_param", params.at(i).get_name().c_str());
|
||||||
|
EXPECT_STREQ(param_value.c_str(), params.at(i).get_value<std::string>().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < node_names_keys.size(); ++i) {
|
||||||
|
c_params->params[i].parameter_values[0].string_value = NULL;
|
||||||
|
}
|
||||||
|
for (auto c_hello_world : param_values) {
|
||||||
|
delete[] c_hello_world;
|
||||||
|
}
|
||||||
|
rcl_yaml_node_struct_fini(c_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Test_parameter_map_from, multi_nodes_diff_param_name_by_node_fqn)
|
||||||
|
{
|
||||||
|
std::vector<std::string> node_names_keys = {
|
||||||
|
"/**", // index: 0
|
||||||
|
"/*", // index: 1
|
||||||
|
"/**/node", // index: 2
|
||||||
|
"/*/node", // index: 3
|
||||||
|
"/ns/**", // index: 4
|
||||||
|
"/ns/*", // index: 5
|
||||||
|
"/ns/**/node", // index: 6
|
||||||
|
"/ns/*/node", // index: 7
|
||||||
|
"/ns/**/a/*/node", // index: 8
|
||||||
|
"/ns/node" // index: 9
|
||||||
|
};
|
||||||
|
|
||||||
|
rcl_params_t * c_params = make_params(node_names_keys);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < node_names_keys.size(); ++i) {
|
||||||
|
std::string param_name = "string_param" + std::to_string(i);
|
||||||
|
make_node_params(c_params, i, {param_name});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string hello_world = "hello world";
|
||||||
|
char * c_hello_world = new char[hello_world.length() + 1];
|
||||||
|
std::snprintf(c_hello_world, hello_world.size() + 1, "%s", hello_world.c_str());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < node_names_keys.size(); ++i) {
|
||||||
|
c_params->params[i].parameter_values[0].string_value = c_hello_world;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::vector<size_t>> node_fqn_expected = {
|
||||||
|
{"/ns/node", {0, 2, 3, 4, 5, 6, 9}},
|
||||||
|
{"/node", {0, 1, 2}},
|
||||||
|
{"/ns/foo/node", {0, 2, 4, 6, 7}},
|
||||||
|
{"/ns/foo/a/node", {0, 2, 4, 6}},
|
||||||
|
{"/ns/foo/a/bar/node", {0, 2, 4, 6, 8}},
|
||||||
|
{"/ns/a/bar/node", {0, 2, 4, 6, 8}},
|
||||||
|
{"/ns/foo/zoo/a/bar/node", {0, 2, 4, 6, 8}},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto & kv : node_fqn_expected) {
|
||||||
|
rclcpp::ParameterMap map = rclcpp::parameter_map_from(c_params, kv.first.c_str());
|
||||||
|
const std::vector<rclcpp::Parameter> & params = map.at(kv.first);
|
||||||
|
EXPECT_EQ(kv.second.size(), params.size());
|
||||||
|
for (size_t i = 0; i < params.size(); ++i) {
|
||||||
|
std::string param_name = "string_param" + std::to_string(kv.second[i]);
|
||||||
|
EXPECT_STREQ(param_name.c_str(), params.at(i).get_name().c_str());
|
||||||
|
EXPECT_STREQ(hello_world.c_str(), params.at(i).get_value<std::string>().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < node_names_keys.size(); ++i) {
|
||||||
|
c_params->params[i].parameter_values[0].string_value = NULL;
|
||||||
|
}
|
||||||
|
delete[] c_hello_world;
|
||||||
|
rcl_yaml_node_struct_fini(c_params);
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/**/foo/*/bar:
|
||||||
|
node2:
|
||||||
|
ros__parameters:
|
||||||
|
foo: "foo"
|
||||||
|
bar: "bar"
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/**:
|
||||||
|
node2:
|
||||||
|
ros__parameters:
|
||||||
|
a_value: "first"
|
||||||
|
foo: "foo"
|
||||||
|
|
||||||
|
/ns:
|
||||||
|
node2:
|
||||||
|
ros__parameters:
|
||||||
|
a_value: "second"
|
||||||
|
bar: "bar"
|
||||||
|
|
||||||
|
/*:
|
||||||
|
node2:
|
||||||
|
ros__parameters:
|
||||||
|
a_value: "last_one_win"
|
||||||
57
rclcpp/test/resources/test_node_parameters/wildcards.yaml
Normal file
57
rclcpp/test/resources/test_node_parameters/wildcards.yaml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/**:
|
||||||
|
ros__parameters:
|
||||||
|
full_wild: "full_wild"
|
||||||
|
|
||||||
|
/**:
|
||||||
|
node2:
|
||||||
|
ros__parameters:
|
||||||
|
namespace_wild: "namespace_wild"
|
||||||
|
|
||||||
|
/**/node2:
|
||||||
|
ros__parameters:
|
||||||
|
namespace_wild_another: "namespace_wild_another"
|
||||||
|
|
||||||
|
/*:
|
||||||
|
node2:
|
||||||
|
ros__parameters:
|
||||||
|
namespace_wild_one_star: "namespace_wild_one_star"
|
||||||
|
|
||||||
|
ns:
|
||||||
|
"*":
|
||||||
|
ros__parameters:
|
||||||
|
node_wild_in_ns: "node_wild_in_ns"
|
||||||
|
|
||||||
|
/ns/*:
|
||||||
|
ros__parameters:
|
||||||
|
node_wild_in_ns_another: "node_wild_in_ns_another"
|
||||||
|
|
||||||
|
ns:
|
||||||
|
node2:
|
||||||
|
ros__parameters:
|
||||||
|
explicit_in_ns: "explicit_in_ns"
|
||||||
|
|
||||||
|
"*":
|
||||||
|
ros__parameters:
|
||||||
|
node_wild_no_ns: "node_wild_no_ns"
|
||||||
|
|
||||||
|
node2:
|
||||||
|
ros__parameters:
|
||||||
|
explicit_no_ns: "explicit_no_ns"
|
||||||
|
|
||||||
|
ns:
|
||||||
|
nodeX:
|
||||||
|
ros__parameters:
|
||||||
|
should_not_appear: "incorrect_node_name"
|
||||||
|
|
||||||
|
/**/nodeX:
|
||||||
|
ros__parameters:
|
||||||
|
should_not_appear: "incorrect_node_name"
|
||||||
|
|
||||||
|
nsX:
|
||||||
|
node2:
|
||||||
|
ros__parameters:
|
||||||
|
should_not_appear: "incorrect_namespace"
|
||||||
|
|
||||||
|
/nsX/*:
|
||||||
|
ros__parameters:
|
||||||
|
should_not_appear: "incorrect_namespace"
|
||||||
@@ -3,6 +3,9 @@ Changelog for package rclcpp_action
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
||||||
|
16.0.2 (2022-11-07)
|
||||||
|
-------------------
|
||||||
|
|
||||||
16.0.1 (2022-04-13)
|
16.0.1 (2022-04-13)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||||
<package format="2">
|
<package format="2">
|
||||||
<name>rclcpp_action</name>
|
<name>rclcpp_action</name>
|
||||||
<version>16.0.1</version>
|
<version>16.0.2</version>
|
||||||
<description>Adds action APIs for C++.</description>
|
<description>Adds action APIs for C++.</description>
|
||||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
Changelog for package rclcpp_components
|
Changelog for package rclcpp_components
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
16.0.2 (2022-11-07)
|
||||||
|
-------------------
|
||||||
|
|
||||||
16.0.1 (2022-04-13)
|
16.0.1 (2022-04-13)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||||
<package format="2">
|
<package format="2">
|
||||||
<name>rclcpp_components</name>
|
<name>rclcpp_components</name>
|
||||||
<version>16.0.1</version>
|
<version>16.0.2</version>
|
||||||
<description>Package containing tools for dynamically loadable components</description>
|
<description>Package containing tools for dynamically loadable components</description>
|
||||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ Changelog for package rclcpp_lifecycle
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
||||||
|
16.0.2 (2022-11-07)
|
||||||
|
-------------------
|
||||||
|
|
||||||
16.0.1 (2022-04-13)
|
16.0.1 (2022-04-13)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||||
<package format="2">
|
<package format="2">
|
||||||
<name>rclcpp_lifecycle</name>
|
<name>rclcpp_lifecycle</name>
|
||||||
<version>16.0.1</version>
|
<version>16.0.2</version>
|
||||||
<description>Package containing a prototype for lifecycle implementation</description>
|
<description>Package containing a prototype for lifecycle implementation</description>
|
||||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||||
|
|||||||
Reference in New Issue
Block a user