Compare commits

...

23 Commits

Author SHA1 Message Date
Scott K Logan
6c95d10cca 29.5.2 2025-07-07 16:06:10 -05:00
mergify[bot]
a5a7febb60 Shutdown deadlock fix jazzy (#2887) (#2888)
* fix: Don't deadlock if removing shutdown callbacks in a shutdown callback



* refactor: Made fix API compatible



---------



(cherry picked from commit 7aab9b6f99)

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Janosch Machowinski <jmachowinski@users.noreply.github.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
2025-07-03 08:30:37 +02:00
mergify[bot]
7373669455 fix test_publisher_with_system_default_qos. (#2881) (#2884)
(cherry picked from commit e6577c6792)

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-06-26 22:58:08 +02:00
Alejandro Hernandez Cordero
ae930aa2e5 29.5.1 2025-06-23 16:45:44 +02:00
Alejandro Hernandez Cordero
24846c3109 Changelog
Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
2025-06-23 16:45:40 +02:00
mergify[bot]
160da7b432 Removed warning test_qos (#2859) (#2873)
(cherry picked from commit df3a303a17)

Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
2025-06-13 08:59:48 +02:00
mergify[bot]
22939ddf9b Fix for memory leaks in rclcpp::SerializedMessage (#2861) (#2863)
(cherry picked from commit 8d44b95d8b)

Signed-off-by: Michael Orlov <morlovmr@gmail.com>
Signed-off-by: Michael Orlov <michael.orlov@apex.ai>
Co-authored-by: Michael Orlov <morlovmr@gmail.com>
Co-authored-by: kylemarcey <marcey.kyle@gmail.com>
2025-05-30 22:17:14 +02:00
mergify[bot]
ea1d764f42 Replace std::default_random_engine with std::mt19937 (rolling) (#2843) (#2866)
(cherry picked from commit db8d917a12)

Signed-off-by: keeponoiro <keeeeeeep@gmail.com>
Co-authored-by: keeponoiro <keeeeeeep@gmail.com>
2025-05-30 10:49:59 +02:00
mergify[bot]
82666affcd get_all_data_impl() does not handle null pointers properly, causing segmentation fault (backport #2840) (#2850)
Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
2025-05-26 18:29:37 +02:00
mergify[bot]
0be3acf32f Added missing chrono includes (#2854) (#2855)
(cherry picked from commit 373a63c5e6)

Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
2025-05-26 13:25:57 +02:00
mergify[bot]
34005e903f QoSInitialization::from_rmw does not validate invalid history policy values, leading to silent failures (#2841) (#2846)
(cherry picked from commit 73e9bfb62b)

Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
2025-05-19 08:57:33 +02:00
mergify[bot]
288be9c981 Add missing 's' to 'NodeParametersInterface' in doc/comment (#2831) (#2833)
(cherry picked from commit b1ec85df16)

Signed-off-by: Christophe Bedard <bedard.christophe@gmail.com>
Co-authored-by: Christophe Bedard <bedard.christophe@gmail.com>
2025-04-30 10:10:19 -07:00
mergify[bot]
93028ff38d subordinate node consistent behavior and update docstring. (#2822) (#2830)
* subordinate node consistent behavior and update docstring.



* add subnode_parameter_operation test.



* typo fixes.



---------


(cherry picked from commit c89a2b1013)

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-04-29 20:26:22 -07:00
Tomoya Fujita
8b9691f42d throws std::invalid_argument if ParameterEvent is NULL. (#2814)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-04-24 10:30:20 -07:00
Alejandro Hernández Cordero
40e3fb78db Removed clang warnings (#2823)
Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
2025-04-24 19:24:29 +02:00
Scott K Logan
11afffad50 29.5.0 2025-04-18 16:01:12 -05:00
Pedro de Azeredo
8e49befce9 Fix race condition (#2819)
Signed-off-by: pedroazeredo04 <pedro_azeredo@usp.br>
Signed-off-by: Pedro Nogueira <pedro_azeredo@usp.br>
2025-04-18 22:31:36 +02:00
Tanishq Chaudhary
f78ed952b2 remove redundant typesupport check in serialization module (#2808)
Signed-off-by: Tanishq Chaudhary <tanishqchaudhary101010@gmail.com>
2025-04-14 23:37:54 +02:00
Tomoya Fujita
2420c48514 remove get_typesupport_handle implementation. (#2806)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-04-13 21:47:18 -07:00
Tomoya Fujita
c01602f7a6 use NodeParameterInterface instead of /parameter_event to update "use… (#2378)
* use NodeParameterInterface instead of /parameter_event to update "use_sim_time"

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

* re-enable ParameterMutationRecursionGuard.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

* adjust test cases.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

---------

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-04-11 09:01:48 -07:00
Tomoya Fujita
6ad551a5cc use std::recursive_mutex for action requests. (#2798)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-04-10 20:43:47 -07:00
Tomoya Fujita
0162861fa1 remove cancel_clock_executor_promise_. (#2797)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
2025-04-10 14:26:34 -07:00
Tomoya Fujita
6040228d13 enable parameter update recursively only when QoS override parameters. (#2742)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-04-09 11:32:11 +02:00
50 changed files with 461 additions and 121 deletions

View File

@@ -2,6 +2,35 @@
Changelog for package rclcpp
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29.5.2 (2025-07-07)
-------------------
* Shutdown deadlock fix jazzy (`#2887 <https://github.com/ros2/rclcpp/issues/2887>`_) (`#2888 <https://github.com/ros2/rclcpp/issues/2888>`_)
* Fix test_publisher_with_system_default_qos (`#2881 <https://github.com/ros2/rclcpp/issues/2881>`_) (`#2884 <https://github.com/ros2/rclcpp/issues/2884>`_)
* Contributors: Tomoya Fujita, Janosch Machowinski
29.5.1 (2025-06-23)
-------------------
* Removed warning test_qos (`#2859 <https://github.com/ros2/rclcpp/issues/2859>`_) (`#2873 <https://github.com/ros2/rclcpp/issues/2873>`_)
* Fix for memory leaks in rclcpp::SerializedMessage (`#2861 <https://github.com/ros2/rclcpp/issues/2861>`_) (`#2863 <https://github.com/ros2/rclcpp/issues/2863>`_)
* get_all_data_impl() does not handle null pointers properly, causing segmentation fault (backport `#2840 <https://github.com/ros2/rclcpp/issues/2840>`_) (`#2850 <https://github.com/ros2/rclcpp/issues/2850>`_)
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
* QoSInitialization::from_rmw does not validate invalid history policy values, leading to silent failures (`#2841 <https://github.com/ros2/rclcpp/issues/2841>`_) (`#2846 <https://github.com/ros2/rclcpp/issues/2846>`_)
* Add missing 's' to 'NodeParametersInterface' in doc/comment (`#2831 <https://github.com/ros2/rclcpp/issues/2831>`_) (`#2833 <https://github.com/ros2/rclcpp/issues/2833>`_)
* subordinate node consistent behavior and update docstring. (`#2822 <https://github.com/ros2/rclcpp/issues/2822>`_) (`#2830 <https://github.com/ros2/rclcpp/issues/2830>`_)
* throws std::invalid_argument if ParameterEvent is NULL. (`#2814 <https://github.com/ros2/rclcpp/issues/2814>`_)
* Removed clang warnings (`#2823 <https://github.com/ros2/rclcpp/issues/2823>`_)
* Contributors: Alejandro Hernández Cordero, Tomoya Fujita, mergify[bot]
29.5.0 (2025-04-18)
-------------------
* Fix a race condition (`#2819 <https://github.com/ros2/rclcpp/issues/2819>`_)
* Remove redundant typesupport check in serialization module (`#2808 <https://github.com/ros2/rclcpp/issues/2808>`_)
* Remove get_typesupport_handle implementation. (`#2806 <https://github.com/ros2/rclcpp/issues/2806>`_)
* Use NodeParameterInterface instead of /parameter_event to update "use_sim_time" (`#2378 <https://github.com/ros2/rclcpp/issues/2378>`_)
* Remove cancel_clock_executor_promise\_. (`#2797 <https://github.com/ros2/rclcpp/issues/2797>`_)
* Enable parameter update recursively only when QoS override parameters. (`#2742 <https://github.com/ros2/rclcpp/issues/2742>`_)
* Contributors: Pedro de Azeredo, Tanishq Chaudhary, Tomoya Fujita
29.4.0 (2025-04-04)
-------------------
* Removed trailing whitespace from the codebase. (`#2791 <https://github.com/ros2/rclcpp/issues/2791>`_)

View File

@@ -97,6 +97,9 @@ declare_parameter_or_get(
rcl_interfaces::msg::ParameterDescriptor descriptor)
{
try {
// enable parameter modification to make it possible
// to declare QoS override parameters during parameter callbacks.
parameters_interface.enable_parameter_modification();
return parameters_interface.declare_parameter(
param_name, param_value, descriptor);
} catch (const rclcpp::exceptions::ParameterAlreadyDeclaredException &) {

View File

@@ -255,9 +255,13 @@ private:
std::vector<BufferT> result_vtr;
result_vtr.reserve(size_);
for (size_t id = 0; id < size_; ++id) {
result_vtr.emplace_back(
new typename is_std_unique_ptr<T>::Ptr_type(
*(ring_buffer_[(read_index_ + id) % capacity_])));
const auto & elem(ring_buffer_[(read_index_ + id) % capacity_]);
if (elem != nullptr) {
result_vtr.emplace_back(new typename is_std_unique_ptr<T>::Ptr_type(
*elem));
} else {
result_vtr.emplace_back(nullptr);
}
}
return result_vtr;
}

View File

@@ -1559,6 +1559,10 @@ public:
* which has been created using an existing instance of this class, but which
* has an additional sub-namespace (short for subordinate namespace)
* associated with it.
* A subordinate node and an instance of this class share all the node interfaces
* such as `rclcpp::node_interfaces::NodeParametersInterface`.
* Subordinate nodes are primarily used to organize namespaces and provide a
* hierarchical structure, but they are not meant to be completely independent nodes.
* The sub-namespace will extend the node's namespace for the purpose of
* creating additional entities, such as Publishers, Subscriptions, Service
* Clients and Servers, and so on.

View File

@@ -323,11 +323,9 @@ template<typename ParameterT>
bool
Node::get_parameter(const std::string & name, ParameterT & parameter) const
{
std::string sub_name = extend_name_with_sub_namespace(name, this->get_sub_namespace());
rclcpp::Parameter parameter_variant;
bool result = get_parameter(sub_name, parameter_variant);
bool result = get_parameter(name, parameter_variant);
if (result) {
parameter = static_cast<ParameterT>(parameter_variant.get_value<ParameterT>());
}
@@ -342,9 +340,7 @@ Node::get_parameter_or(
ParameterT & parameter,
const ParameterT & alternative_value) const
{
std::string sub_name = extend_name_with_sub_namespace(name, this->get_sub_namespace());
bool got_parameter = get_parameter(sub_name, parameter);
bool got_parameter = get_parameter(name, parameter);
if (!got_parameter) {
parameter = alternative_value;
}

View File

@@ -214,6 +214,10 @@ public:
const std::map<std::string, rclcpp::ParameterValue> &
get_parameter_overrides() const override;
RCLCPP_PUBLIC
void
enable_parameter_modification() override;
using PreSetCallbacksHandleContainer = std::list<PreSetParametersCallbackHandle::WeakPtr>;
using OnSetCallbacksHandleContainer = std::list<OnSetParametersCallbackHandle::WeakPtr>;
using PostSetCallbacksHandleContainer = std::list<PostSetParametersCallbackHandle::WeakPtr>;

View File

@@ -270,6 +270,26 @@ public:
virtual
const std::map<std::string, rclcpp::ParameterValue> &
get_parameter_overrides() const = 0;
/// Enable parameter modification recursively during parameter callbacks.
/**
* This function is used to enable parameter modification during parameter callbacks.
*
* There are times when it does not allow parameter modification, such as when the parameter
* callbacks are being called and tries to modify the parameters with set_parameter and
* declare_parameter to avoid recursive parameter modification.
* This is protected by rclcpp::node_interfaces::ParameterMutationRecursionGuard.
*
* This function is explicitly called to allow the recursive parameter operation during
* parameter callbacks by the application.
* Once it is enabled, the next parameter operation set/declare/undeclare_parameter are
* allowed to execute in the parameter callback. But, no more further recursive operation
* is allowed, unless user application calls this API again.
*/
RCLCPP_PUBLIC
virtual
void
enable_parameter_modification() = 0;
};
} // namespace node_interfaces

View File

@@ -45,6 +45,7 @@ public:
* \param[in] names A list of parameter names of interest.
* \param[in] types A list of the types of parameter events of iterest.
* EventType NEW, DELETED, or CHANGED
* \throws std::invalid_argument if event is NULL.
*
* Example Usage:
*

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>29.4.0</version>
<version>29.5.2</version>
<description>The ROS client library in C++.</description>
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>

View File

@@ -14,6 +14,7 @@
#include "rclcpp/context.hpp"
#include <map>
#include <memory>
#include <mutex>
#include <sstream>
@@ -142,11 +143,52 @@ rclcpp_logging_output_handler(
}
} // extern "C"
/**
* Global storage for pre and post shutdown recursive mutexes.
* Note, this is a ABI compatibility hack.
*/
class MutexLookup
{
std::mutex m;
struct MutexHolder
{
std::recursive_mutex on_shutdown_callbacks_mutex_;
std::recursive_mutex pre_shutdown_callbacks_mutex_;
};
std::map<const Context *, std::unique_ptr<MutexHolder>> mutexMap;
public:
MutexHolder & getMutexes(const Context *forContext)
{
auto it = mutexMap.find(forContext);
if(it == mutexMap.end()) {
it = mutexMap.emplace(forContext, std::make_unique<MutexHolder>()).first;
}
return *(it->second);
}
/**
* Only supposed to be called on deletion of context
*/
void removeMutexes(const Context *forContext)
{
mutexMap.erase(forContext);
}
};
MutexLookup mutexStorage;
Context::Context()
: rcl_context_(nullptr),
shutdown_reason_(""),
logging_mutex_(nullptr)
{}
{
// allocate mutexes
mutexStorage.getMutexes(this);
}
Context::~Context()
{
@@ -165,6 +207,9 @@ Context::~Context()
} catch (...) {
RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "unhandled exception in ~Context()");
}
// delete mutexes
mutexStorage.removeMutexes(this);
}
RCLCPP_LOCAL
@@ -310,9 +355,17 @@ Context::shutdown(const std::string & reason)
// call each pre-shutdown callback
{
std::lock_guard<std::mutex> lock{pre_shutdown_callbacks_mutex_};
for (const auto & callback : pre_shutdown_callbacks_) {
(*callback)();
std::lock_guard<std::recursive_mutex> lock{mutexStorage.getMutexes(
this).pre_shutdown_callbacks_mutex_};
// callbacks may delete other callbacks during the execution,
// therefore we need to save a copy and check before execution
// if the next callback is still present
auto cpy = pre_shutdown_callbacks_;
for (const auto & callback : cpy) {
auto it = std::find(pre_shutdown_callbacks_.begin(), pre_shutdown_callbacks_.end(), callback);
if(it != pre_shutdown_callbacks_.end()) {
(*callback)();
}
}
}
@@ -325,9 +378,17 @@ Context::shutdown(const std::string & reason)
shutdown_reason_ = reason;
// call each shutdown callback
{
std::lock_guard<std::mutex> lock(on_shutdown_callbacks_mutex_);
for (const auto & callback : on_shutdown_callbacks_) {
(*callback)();
std::lock_guard<std::recursive_mutex> lock(mutexStorage.getMutexes(
this).on_shutdown_callbacks_mutex_);
// callbacks may delete other callbacks during the execution,
// therefore we need to save a copy and check before execution
// if the next callback is still present
auto cpy = on_shutdown_callbacks_;
for (const auto & callback : cpy) {
auto it = std::find(on_shutdown_callbacks_.begin(), on_shutdown_callbacks_.end(), callback);
if(it != on_shutdown_callbacks_.end()) {
(*callback)();
}
}
}
@@ -398,10 +459,12 @@ Context::add_shutdown_callback(
shutdown_type == ShutdownType::pre_shutdown || shutdown_type == ShutdownType::on_shutdown);
if constexpr (shutdown_type == ShutdownType::pre_shutdown) {
std::lock_guard<std::mutex> lock(pre_shutdown_callbacks_mutex_);
std::lock_guard<std::recursive_mutex> lock(mutexStorage.getMutexes(
this).pre_shutdown_callbacks_mutex_);
pre_shutdown_callbacks_.emplace_back(callback_shared_ptr);
} else {
std::lock_guard<std::mutex> lock(on_shutdown_callbacks_mutex_);
std::lock_guard<std::recursive_mutex> lock(mutexStorage.getMutexes(
this).on_shutdown_callbacks_mutex_);
on_shutdown_callbacks_.emplace_back(callback_shared_ptr);
}
@@ -421,7 +484,7 @@ Context::remove_shutdown_callback(
}
const auto remove_callback = [&callback_shared_ptr](auto & mutex, auto & callback_vector) {
const std::lock_guard<std::mutex> lock(mutex);
const std::lock_guard<std::recursive_mutex> lock(mutex);
auto iter = callback_vector.begin();
for (; iter != callback_vector.end(); iter++) {
if ((*iter).get() == callback_shared_ptr.get()) {
@@ -432,6 +495,7 @@ Context::remove_shutdown_callback(
return false;
}
callback_vector.erase(iter);
return true;
};
@@ -439,9 +503,11 @@ Context::remove_shutdown_callback(
shutdown_type == ShutdownType::pre_shutdown || shutdown_type == ShutdownType::on_shutdown);
if constexpr (shutdown_type == ShutdownType::pre_shutdown) {
return remove_callback(pre_shutdown_callbacks_mutex_, pre_shutdown_callbacks_);
return remove_callback(mutexStorage.getMutexes(this).pre_shutdown_callbacks_mutex_,
pre_shutdown_callbacks_);
} else {
return remove_callback(on_shutdown_callbacks_mutex_, on_shutdown_callbacks_);
return remove_callback(mutexStorage.getMutexes(this).on_shutdown_callbacks_mutex_,
on_shutdown_callbacks_);
}
}
@@ -462,7 +528,7 @@ std::vector<rclcpp::Context::ShutdownCallback>
Context::get_shutdown_callback() const
{
const auto get_callback_vector = [](auto & mutex, auto & callback_set) {
const std::lock_guard<std::mutex> lock(mutex);
const std::lock_guard<std::recursive_mutex> lock(mutex);
std::vector<rclcpp::Context::ShutdownCallback> callbacks;
for (auto & callback : callback_set) {
callbacks.push_back(*callback);
@@ -474,9 +540,11 @@ Context::get_shutdown_callback() const
shutdown_type == ShutdownType::pre_shutdown || shutdown_type == ShutdownType::on_shutdown);
if constexpr (shutdown_type == ShutdownType::pre_shutdown) {
return get_callback_vector(pre_shutdown_callbacks_mutex_, pre_shutdown_callbacks_);
return get_callback_vector(mutexStorage.getMutexes(this).pre_shutdown_callbacks_mutex_,
pre_shutdown_callbacks_);
} else {
return get_callback_vector(on_shutdown_callbacks_mutex_, on_shutdown_callbacks_);
return get_callback_vector(mutexStorage.getMutexes(this).on_shutdown_callbacks_mutex_,
on_shutdown_callbacks_);
}
}

View File

@@ -689,7 +689,7 @@ Node::create_generic_client(
node_base_,
node_graph_,
node_services_,
service_name,
extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
service_type,
qos,
group);

View File

@@ -1191,3 +1191,10 @@ NodeParameters::get_parameter_overrides() const
{
return parameter_overrides_;
}
void
NodeParameters::enable_parameter_modification()
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
parameter_modification_enabled_ = true;
}

View File

@@ -28,6 +28,9 @@ ParameterEventsFilter::ParameterEventsFilter(
const std::vector<EventType> & types)
: event_(event)
{
if (!event) {
throw std::invalid_argument("event cannot be null");
}
if (std::find(types.begin(), types.end(), EventType::NEW) != types.end()) {
for (auto & new_parameter : event->new_parameters) {
if (std::find(names.begin(), names.end(), new_parameter.name) != names.end()) {

View File

@@ -69,8 +69,10 @@ QoSInitialization::from_rmw(const rmw_qos_profile_t & rmw_qos)
return KeepLast(rmw_qos.depth, false);
case RMW_QOS_POLICY_HISTORY_KEEP_LAST:
case RMW_QOS_POLICY_HISTORY_UNKNOWN:
default:
return KeepLast(rmw_qos.depth);
default:
throw std::invalid_argument(
"Invalid history policy enum value passed to QoSInitialization::from_rmw");
}
}

View File

@@ -36,7 +36,6 @@ SerializationBase::SerializationBase(const rosidl_message_type_support_t * type_
void SerializationBase::serialize_message(
const void * ros_message, SerializedMessage * serialized_message) const
{
rcpputils::check_true(nullptr != type_support_, "Typesupport is nullpointer.");
rcpputils::check_true(nullptr != ros_message, "ROS message is nullpointer.");
rcpputils::check_true(nullptr != serialized_message, "Serialized message is nullpointer.");
@@ -52,7 +51,6 @@ void SerializationBase::serialize_message(
void SerializationBase::deserialize_message(
const SerializedMessage * serialized_message, void * ros_message) const
{
rcpputils::check_true(nullptr != type_support_, "Typesupport is nullpointer.");
rcpputils::check_true(nullptr != serialized_message, "Serialized message is nullpointer.");
rcpputils::check_true(
0u != serialized_message->capacity(),

View File

@@ -26,8 +26,13 @@ namespace rclcpp
inline void copy_rcl_message(const rcl_serialized_message_t & from, rcl_serialized_message_t & to)
{
const auto ret = rmw_serialized_message_init(
&to, from.buffer_capacity, &from.allocator);
auto ret = RCL_RET_ERROR;
if (nullptr == to.buffer) {
ret = rmw_serialized_message_init(&to, from.buffer_capacity, &from.allocator);
} else {
ret = rmw_serialized_message_resize(&to, from.buffer_capacity);
}
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret);
}
@@ -78,7 +83,6 @@ SerializedMessage::SerializedMessage(rcl_serialized_message_t && other)
SerializedMessage & SerializedMessage::operator=(const SerializedMessage & other)
{
if (this != &other) {
serialized_message_ = rmw_get_zero_initialized_serialized_message();
copy_rcl_message(other.serialized_message_, serialized_message_);
}
@@ -88,7 +92,6 @@ SerializedMessage & SerializedMessage::operator=(const SerializedMessage & other
SerializedMessage & SerializedMessage::operator=(const rcl_serialized_message_t & other)
{
if (&serialized_message_ != &other) {
serialized_message_ = rmw_get_zero_initialized_serialized_message();
copy_rcl_message(other, serialized_message_);
}
@@ -98,6 +101,14 @@ SerializedMessage & SerializedMessage::operator=(const rcl_serialized_message_t
SerializedMessage & SerializedMessage::operator=(SerializedMessage && other)
{
if (this != &other) {
if (nullptr != serialized_message_.buffer) {
const auto fini_ret = rmw_serialized_message_fini(&serialized_message_);
if (RCL_RET_OK != fini_ret) {
RCLCPP_ERROR(
get_logger("rclcpp"),
"Failed to destroy serialized message: %s", rcl_get_error_string().str);
}
}
serialized_message_ =
std::exchange(other.serialized_message_, rmw_get_zero_initialized_serialized_message());
}
@@ -108,6 +119,14 @@ SerializedMessage & SerializedMessage::operator=(SerializedMessage && other)
SerializedMessage & SerializedMessage::operator=(rcl_serialized_message_t && other)
{
if (&serialized_message_ != &other) {
if (nullptr != serialized_message_.buffer) {
const auto fini_ret = rmw_serialized_message_fini(&serialized_message_);
if (RCL_RET_OK != fini_ret) {
RCLCPP_ERROR(
get_logger("rclcpp"),
"Failed to destroy serialized message: %s", rcl_get_error_string().str);
}
}
serialized_message_ =
std::exchange(other, rmw_get_zero_initialized_serialized_message());
}

View File

@@ -276,13 +276,8 @@ public:
on_set_parameters_callback_ = node_parameters_->add_on_set_parameters_callback(
std::bind(&TimeSource::NodeState::on_set_parameters, this, std::placeholders::_1));
// TODO(tfoote) use parameters interface not subscribe to events via topic ticketed #609
parameter_subscription_ = rclcpp::AsyncParametersClient::on_parameter_event(
node_topics_,
[this](std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event) {
this->on_parameter_event(event);
});
post_set_parameters_callback_ = node_parameters_->add_post_set_parameters_callback(
std::bind(&TimeSource::NodeState::post_set_parameters, this, std::placeholders::_1));
}
// Detach the attached node
@@ -296,8 +291,11 @@ public:
if (on_set_parameters_callback_) {
node_parameters_->remove_on_set_parameters_callback(on_set_parameters_callback_.get());
}
if (post_set_parameters_callback_) {
node_parameters_->remove_post_set_parameters_callback(post_set_parameters_callback_.get());
}
on_set_parameters_callback_.reset();
parameter_subscription_.reset();
post_set_parameters_callback_.reset();
node_base_.reset();
node_topics_.reset();
node_graph_.reset();
@@ -346,7 +344,6 @@ private:
std::mutex clock_sub_lock_;
rclcpp::CallbackGroup::SharedPtr clock_callback_group_;
rclcpp::executors::SingleThreadedExecutor::SharedPtr clock_executor_;
std::promise<void> cancel_clock_executor_promise_;
// The clock callback itself
void clock_cb(std::shared_ptr<const rosgraph_msgs::msg::Clock> msg)
@@ -392,12 +389,10 @@ private:
clock_executor_ =
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(exec_options);
if (!clock_executor_thread_.joinable()) {
cancel_clock_executor_promise_ = std::promise<void>{};
clock_executor_thread_ = std::thread(
[this]() {
auto future = cancel_clock_executor_promise_.get_future();
clock_executor_->add_callback_group(clock_callback_group_, node_base_);
clock_executor_->spin_until_future_complete(future);
clock_executor_->spin();
}
);
}
@@ -429,7 +424,6 @@ private:
{
std::lock_guard<std::mutex> guard(clock_sub_lock_);
if (clock_executor_thread_.joinable()) {
cancel_clock_executor_promise_.set_value();
clock_executor_->cancel();
clock_executor_thread_.join();
clock_executor_->remove_callback_group(clock_callback_group_);
@@ -440,9 +434,9 @@ private:
// On set Parameters callback handle
node_interfaces::OnSetParametersCallbackHandle::SharedPtr on_set_parameters_callback_{nullptr};
// Parameter Event subscription
using ParamSubscriptionT = rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>;
std::shared_ptr<ParamSubscriptionT> parameter_subscription_;
// Post set Parameters callback handle
node_interfaces::PostSetParametersCallbackHandle::SharedPtr
post_set_parameters_callback_{nullptr};
// Callback for parameter settings
rcl_interfaces::msg::SetParametersResult on_set_parameters(
@@ -465,52 +459,27 @@ private:
return result;
}
// Callback for parameter updates
void on_parameter_event(std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event)
// Callback for post parameter updates
void post_set_parameters(const std::vector<rclcpp::Parameter> & parameters)
{
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;
}
// Filter for only 'use_sim_time' being added or changed.
rclcpp::ParameterEventsFilter filter(event, {"use_sim_time"},
{rclcpp::ParameterEventsFilter::EventType::NEW,
rclcpp::ParameterEventsFilter::EventType::CHANGED});
for (auto & it : filter.get_events()) {
if (it.second->value.type != ParameterType::PARAMETER_BOOL) {
RCLCPP_ERROR(logger_, "use_sim_time parameter cannot be set to anything but a bool");
continue;
// "use_sim_time" has been set, so just applys it to internal states
for (const auto & param : parameters) {
if (param.get_name() == "use_sim_time") {
if (param.as_bool()) {
parameter_state_ = SET_TRUE;
clocks_state_.enable_ros_time();
create_clock_sub();
} else {
parameter_state_ = SET_FALSE;
destroy_clock_sub();
clocks_state_.disable_ros_time();
}
}
if (it.second->value.bool_value) {
parameter_state_ = SET_TRUE;
clocks_state_.enable_ros_time();
create_clock_sub();
} else {
parameter_state_ = SET_FALSE;
destroy_clock_sub();
clocks_state_.disable_ros_time();
}
}
// Handle the case that use_sim_time was deleted.
rclcpp::ParameterEventsFilter deleted(event, {"use_sim_time"},
{rclcpp::ParameterEventsFilter::EventType::DELETED});
for (auto & it : deleted.get_events()) {
(void) it; // if there is a match it's already matched, don't bother reading it.
// If the parameter is deleted mark it as unset but don't change state.
parameter_state_ = UNSET;
}
}
// An enum to hold the parameter state
enum UseSimTimeParameterState {UNSET, SET_TRUE, SET_FALSE};
enum UseSimTimeParameterState {SET_TRUE, SET_FALSE};
UseSimTimeParameterState parameter_state_;
};

View File

@@ -139,14 +139,6 @@ get_typesupport_library(const std::string & type, const std::string & typesuppor
return std::make_shared<rcpputils::SharedLibrary>(library_path);
}
const rosidl_message_type_support_t * get_typesupport_handle(
const std::string & type,
const std::string & typesupport_identifier,
rcpputils::SharedLibrary & library)
{
return get_message_typesupport_handle(type, typesupport_identifier, library);
}
const rosidl_message_type_support_t * get_message_typesupport_handle(
const std::string & type,
const std::string & typesupport_identifier,

View File

@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <chrono>
#include <memory>
#include <string>
#include <utility>

View File

@@ -196,7 +196,7 @@ ament_add_gtest(test_node_interfaces__node_parameters
node_interfaces/test_node_parameters.cpp)
ament_add_test_label(test_node_interfaces__node_parameters mimick)
if(TARGET test_node_interfaces__node_parameters)
target_link_libraries(test_node_interfaces__node_parameters ${PROJECT_NAME} mimick rcpputils::rcpputils)
target_link_libraries(test_node_interfaces__node_parameters ${PROJECT_NAME} mimick rcpputils::rcpputils ${test_msgs_TARGETS})
endif()
ament_add_gtest(test_node_interfaces__node_services
node_interfaces/test_node_services.cpp)

View File

@@ -14,6 +14,7 @@
#include <gtest/gtest.h>
#include <chrono>
#include <memory>
#include "rclcpp/experimental/executors/events_executor/events_executor_event_types.hpp"

View File

@@ -13,6 +13,7 @@
// limitations under the License.
#include <atomic>
#include <chrono>
#include <functional>
#include <memory>
#include <thread>

View File

@@ -29,6 +29,8 @@
#include "rclcpp/node.hpp"
#include "rclcpp/node_interfaces/node_parameters.hpp"
#include "test_msgs/msg/empty.hpp"
#include "../../mocking_utils/patch.hpp"
#include "../../utils/rclcpp_gtest_macros.hpp"
@@ -329,6 +331,89 @@ TEST_F(TestNodeParameters, add_remove_post_set_parameters_callback) {
std::runtime_error("Post set parameter callback doesn't exist"));
}
TEST_F(TestNodeParameters, set_param_recursive_in_post_set_parameters_callback) {
rclcpp::Subscription<test_msgs::msg::Empty>::SharedPtr subscription_;
rclcpp::Publisher<test_msgs::msg::Empty>::SharedPtr publisher_;
rcl_interfaces::msg::ParameterDescriptor param_descriptor;
param_descriptor.name = "create_entities";
param_descriptor.type = rcl_interfaces::msg::ParameterType::PARAMETER_BOOL;
param_descriptor.read_only = false;
bool result = node_parameters->declare_parameter(
"create_entities", rclcpp::ParameterValue(false), param_descriptor, false).get<bool>();
EXPECT_EQ(result, false);
// Register a callback to create/delete publisher and subscription with
// QoS override parameter options. This will call declare_parameter recursively
// during this callback.
auto sub_callback = [](test_msgs::msg::Empty::ConstSharedPtr) {};
auto callback = [&](const std::vector<rclcpp::Parameter> & parameters) {
for (const auto & parameter : parameters) {
if (parameter.get_name() == "create_entities" &&
parameter.get_type() == rclcpp::ParameterType::PARAMETER_BOOL)
{
if (parameter.as_bool()) {
ASSERT_EQ(subscription_, nullptr);
rclcpp::SubscriptionOptions sub_options;
// This will declare the QoS override parameters in this callback.
sub_options.qos_overriding_options =
rclcpp::QosOverridingOptions::with_default_policies();
subscription_ = node->create_subscription<test_msgs::msg::Empty>(
"empty",
rclcpp::QoS(10),
sub_callback,
sub_options);
ASSERT_NE(subscription_, nullptr);
ASSERT_EQ(publisher_, nullptr);
rclcpp::PublisherOptions pub_options;
// This will declare the QoS override parameters in this callback.
pub_options.qos_overriding_options =
rclcpp::QosOverridingOptions::with_default_policies();
publisher_ = node->create_publisher<test_msgs::msg::Empty>(
"empty",
rclcpp::QoS(10),
pub_options);
ASSERT_NE(publisher_, nullptr);
} else {
ASSERT_NE(subscription_, nullptr);
subscription_.reset();
ASSERT_EQ(subscription_, nullptr);
ASSERT_NE(publisher_, nullptr);
publisher_.reset();
ASSERT_EQ(publisher_, nullptr);
}
}
}
};
auto handle = node_parameters->add_post_set_parameters_callback(callback);
ASSERT_NE(handle, nullptr);
EXPECT_TRUE(node_parameters->has_parameter("create_entities"));
EXPECT_EQ(node_parameters->get_parameter("create_entities").get_value<bool>(), false);
// This will call the registered callback, that will create endpoints with
// declaring the QoS override parameters recursively.
auto results = node_parameters->set_parameters({rclcpp::Parameter("create_entities", true)});
EXPECT_TRUE(!results.empty() && results[0].successful);
EXPECT_TRUE(node_parameters->has_parameter("create_entities"));
EXPECT_EQ(node_parameters->get_parameter("create_entities").get_value<bool>(), true);
// Destroy publisher and subscription endpoints.
results = node_parameters->set_parameters({rclcpp::Parameter("create_entities", false)});
EXPECT_TRUE(!results.empty() && results[0].successful);
EXPECT_TRUE(node_parameters->has_parameter("create_entities"));
EXPECT_EQ(node_parameters->get_parameter("create_entities").get_value<bool>(), false);
// Make sure recreation can also work without any exception.
results = node_parameters->set_parameters({rclcpp::Parameter("create_entities", true)});
EXPECT_TRUE(!results.empty() && results[0].successful);
EXPECT_NO_THROW(node_parameters->remove_post_set_parameters_callback(handle.get()));
}
TEST_F(TestNodeParameters, wildcard_with_namespace)
{
rclcpp::NodeOptions opts;

View File

@@ -184,7 +184,10 @@ TEST_F(TestClockWakeup, no_wakeup_on_sim_time) {
TEST_F(TestClockWakeup, multiple_threads_wait_on_one_clock) {
auto clock = std::make_shared<rclcpp::Clock>(RCL_ROS_TIME);
std::vector<bool> thread_finished(10, false);
std::vector<std::atomic_bool> thread_finished(10);
for (std::atomic_bool & finished : thread_finished) {
finished = false;
}
std::vector<std::thread> threads;
@@ -202,7 +205,7 @@ TEST_F(TestClockWakeup, multiple_threads_wait_on_one_clock) {
// wait a bit so all threads can execute the sleep_until
std::this_thread::sleep_for(std::chrono::milliseconds(500));
for (const bool & finished : thread_finished) {
for (const std::atomic_bool & finished : thread_finished) {
EXPECT_FALSE(finished);
}
@@ -213,7 +216,7 @@ TEST_F(TestClockWakeup, multiple_threads_wait_on_one_clock) {
bool threads_finished = false;
while (!threads_finished && start_time + std::chrono::seconds(1) > cur_time) {
threads_finished = true;
for (const bool finished : thread_finished) {
for (const std::atomic_bool & finished : thread_finished) {
if (!finished) {
threads_finished = false;
}
@@ -223,7 +226,7 @@ TEST_F(TestClockWakeup, multiple_threads_wait_on_one_clock) {
cur_time = std::chrono::steady_clock::now();
}
for (const bool finished : thread_finished) {
for (const std::atomic_bool & finished : thread_finished) {
EXPECT_TRUE(finished);
}

View File

@@ -19,11 +19,16 @@
#include <stdexcept>
#include <string>
#include "rcl_interfaces/msg/parameter_event.hpp"
#include "rclcpp/executor.hpp"
#include "rclcpp/memory_strategy.hpp"
#include "rclcpp/executors/single_threaded_executor.hpp"
#include "rclcpp/rclcpp.hpp"
#include "rclcpp/strategies/allocator_memory_strategy.hpp"
#include "test_msgs/msg/empty.hpp"
#include "../mocking_utils/patch.hpp"
#include "../utils/rclcpp_gtest_macros.hpp"
@@ -331,8 +336,17 @@ TEST_F(TestExecutor, spin_all_fail_wait_set_clear) {
node->create_wall_timer(std::chrono::milliseconds(1), [&]() {});
dummy.add_node(node);
auto callback = [](test_msgs::msg::Empty::ConstSharedPtr) {};
rclcpp::Subscription<test_msgs::msg::Empty>::SharedPtr subscription;
auto node_topics = node->get_node_topics_interface();
subscription =
rclcpp::create_subscription<test_msgs::msg::Empty>(
node_topics, "test", rclcpp::QoS(10), std::move(callback));
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_wait_set_clear, RCL_RET_ERROR);
dummy.spin_all(std::chrono::milliseconds(1));
// second spin_all triggers rcl_wait_set_clear that should be called
// whenever a waitset gets rebuild and it was not changed in size.
RCLCPP_EXPECT_THROW_EQ(
dummy.spin_all(std::chrono::milliseconds(1)),
std::runtime_error("Couldn't clear the wait set: error not set"));
@@ -354,8 +368,14 @@ TEST_F(TestExecutor, spin_some_fail_wait_set_resize) {
TEST_F(TestExecutor, spin_some_fail_add_handles_to_wait_set) {
DummyExecutor dummy;
auto node = std::make_shared<rclcpp::Node>("node", "ns");
auto timer =
node->create_wall_timer(std::chrono::milliseconds(1), [&]() {});
// create subscription explicitly, because we do not create subscription
// on /parameter_events for 'use_sim_time' parameter anymore.
auto callback = [](test_msgs::msg::Empty::ConstSharedPtr) {};
rclcpp::Subscription<test_msgs::msg::Empty>::SharedPtr subscription;
subscription =
node->create_subscription<test_msgs::msg::Empty>(
"test", rclcpp::QoS(10), std::move(callback));
dummy.add_node(node);
auto mock = mocking_utils::patch_and_return(

View File

@@ -221,7 +221,7 @@ TEST_F(TestGenericClient, wait_for_service) {
TEST_F(TestGenericClientSub, construction_and_destruction) {
{
auto client = subnode->create_generic_client("test_service", "test_msgs/srv/Empty");
EXPECT_STREQ(client->get_service_name(), "/ns/test_service");
EXPECT_STREQ(client->get_service_name(), "/ns/sub_ns/test_service");
}
{

View File

@@ -15,6 +15,7 @@
#include <gmock/gmock.h>
#include <chrono>
#include <future>
#include <memory>
#include <string>

View File

@@ -14,6 +14,7 @@
#include <gtest/gtest.h>
#include <chrono>
#include <memory>
#include <string>
#include <vector>

View File

@@ -306,6 +306,39 @@ TEST_F(TestNode, subnode_get_name_and_namespace) {
}, rclcpp::exceptions::NameValidationError);
}
}
TEST_F(TestNode, subnode_parameter_operation) {
auto node = std::make_shared<rclcpp::Node>("my_node", "ns");
auto subnode = node->create_sub_node("sub_ns");
auto value = subnode->declare_parameter("param", 5);
EXPECT_EQ(value, 5);
// node and sub-node shares NodeParametersInterface, so expecting the exception.
EXPECT_THROW(
node->declare_parameter("param", 0),
rclcpp::exceptions::ParameterAlreadyDeclaredException);
rclcpp::Parameter param;
node->get_parameter("param", param);
EXPECT_EQ(param.get_value<int>(), 5);
subnode->get_parameter("param", param);
EXPECT_EQ(param.get_value<int>(), 5);
int param_int;
node->get_parameter("param", param_int);
EXPECT_EQ(param_int, 5);
subnode->get_parameter("param", param_int);
EXPECT_EQ(param_int, 5);
EXPECT_EQ(node->get_parameter_or("param", 333), 5);
EXPECT_EQ(subnode->get_parameter_or("param", 666), 5);
node->get_parameter_or("param", param_int, 333);
EXPECT_EQ(param_int, 5);
subnode->get_parameter_or("param", param_int, 666);
EXPECT_EQ(param_int, 5);
}
/*
Testing node construction and destruction.
*/

View File

@@ -72,6 +72,13 @@ protected:
/*
Testing filters.
*/
TEST_F(TestParameterEventFilter, invalide_arguments) {
EXPECT_THROW(
rclcpp::ParameterEventsFilter(nullptr, {"new"}, {nt}),
std::invalid_argument
);
}
TEST_F(TestParameterEventFilter, full_by_type) {
auto res = rclcpp::ParameterEventsFilter(
full,

View File

@@ -14,6 +14,7 @@
#include <gtest/gtest.h>
#include <chrono>
#include <memory>
#include <string>
#include <utility>

View File

@@ -199,7 +199,7 @@ TEST_F(TestPublisher, test_publisher_with_system_default_qos) {
using test_msgs::msg::Empty;
ASSERT_NO_THROW(
{
auto publisher = node->create_publisher<Empty>("topic", rclcpp::SystemDefaultsQoS());
auto publisher = node->create_publisher<Empty>("topic", rclcpp::SystemDefaultsQoS(), options);
});
}

View File

@@ -272,3 +272,15 @@ TEST(TestQoS, qos_check_compatible)
}
}
}
TEST(TestQoS, from_rmw_validity)
{
rmw_qos_profile_t invalid_qos;
memset(&invalid_qos, 0, sizeof(invalid_qos));
unsigned int n = 999;
memcpy(&invalid_qos.history, &n, sizeof(n));
EXPECT_THROW({
rclcpp::QoSInitialization::from_rmw(invalid_qos);
}, std::invalid_argument);
}

View File

@@ -139,3 +139,15 @@ TEST(TestRingBufferImplementation, basic_usage_unique_ptr) {
EXPECT_EQ(false, rb.has_data());
EXPECT_EQ(false, rb.is_full());
}
TEST(TestRingBufferImplementation, handle_nullptr_deletion) {
rclcpp::experimental::buffers::RingBufferImplementation<std::unique_ptr<int>> rb(3);
rb.enqueue(std::make_unique<int>(42));
rb.enqueue(nullptr); // intentionally enqueuing nullptr
rb.enqueue(std::make_unique<int>(84));
auto all_data = rb.get_all_data();
EXPECT_EQ(3u, all_data.size());
EXPECT_EQ(42, *(all_data[0]));
EXPECT_EQ(nullptr, all_data[1]);
EXPECT_EQ(84, *(all_data[2]));
}

View File

@@ -14,6 +14,7 @@
#include <gtest/gtest.h>
#include <chrono>
#include <string>
#include <memory>
#include <utility>

View File

@@ -15,6 +15,7 @@
#include <rcl/service_introspection.h>
#include <rmw/rmw.h>
#include <chrono>
#include <map>
#include <string>

View File

@@ -14,6 +14,7 @@
#include <gtest/gtest.h>
#include <chrono>
#include <memory>
#include <string>
#include <vector>

View File

@@ -3,6 +3,20 @@ Changelog for package rclcpp_action
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29.5.2 (2025-07-07)
-------------------
29.5.1 (2025-06-23)
-------------------
* Replace std::default_random_engine with std::mt19937 (rolling) (`#2843 <https://github.com/ros2/rclcpp/issues/2843>`_) (`#2866 <https://github.com/ros2/rclcpp/issues/2866>`_)
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
* Contributors: mergify[bot]
29.5.0 (2025-04-18)
-------------------
* Use std::recursive_mutex for action requests. (`#2798 <https://github.com/ros2/rclcpp/issues/2798>`_)
* Contributors: Tomoya Fujita
29.4.0 (2025-04-04)
-------------------
* Remove warning (`#2790 <https://github.com/ros2/rclcpp/issues/2790>`_)

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>29.4.0</version>
<version>29.5.2</version>
<description>Adds action APIs for C++.</description>
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>

View File

@@ -172,16 +172,16 @@ public:
using ResponseCallback = std::function<void (std::shared_ptr<void> response)>;
std::map<int64_t, ResponseCallback> pending_goal_responses;
std::mutex goal_requests_mutex;
std::recursive_mutex goal_requests_mutex;
std::map<int64_t, ResponseCallback> pending_result_responses;
std::mutex result_requests_mutex;
std::recursive_mutex result_requests_mutex;
std::map<int64_t, ResponseCallback> pending_cancel_responses;
std::mutex cancel_requests_mutex;
std::recursive_mutex cancel_requests_mutex;
std::independent_bits_engine<
std::default_random_engine, 8, unsigned int> random_bytes_generator;
std::mt19937, 8, unsigned int> random_bytes_generator;
};
ClientBase::ClientBase(
@@ -386,7 +386,7 @@ ClientBase::handle_goal_response(
const rmw_request_id_t & response_header,
std::shared_ptr<void> response)
{
std::lock_guard<std::mutex> guard(pimpl_->goal_requests_mutex);
std::lock_guard<std::recursive_mutex> guard(pimpl_->goal_requests_mutex);
const int64_t & sequence_number = response_header.sequence_number;
if (pimpl_->pending_goal_responses.count(sequence_number) == 0) {
RCLCPP_ERROR(pimpl_->logger, "unknown goal response, ignoring...");
@@ -399,7 +399,7 @@ ClientBase::handle_goal_response(
void
ClientBase::send_goal_request(std::shared_ptr<void> request, ResponseCallback callback)
{
std::unique_lock<std::mutex> guard(pimpl_->goal_requests_mutex);
std::lock_guard<std::recursive_mutex> guard(pimpl_->goal_requests_mutex);
int64_t sequence_number;
rcl_ret_t ret = rcl_action_send_goal_request(
pimpl_->client_handle.get(), request.get(), &sequence_number);
@@ -417,7 +417,7 @@ ClientBase::handle_result_response(
{
std::map<int64_t, ResponseCallback>::node_type pending_result_response;
{
std::lock_guard<std::mutex> guard(pimpl_->result_requests_mutex);
std::lock_guard<std::recursive_mutex> guard(pimpl_->result_requests_mutex);
const int64_t & sequence_number = response_header.sequence_number;
if (pimpl_->pending_result_responses.count(sequence_number) == 0) {
RCLCPP_ERROR(pimpl_->logger, "unknown result response, ignoring...");
@@ -433,7 +433,7 @@ ClientBase::handle_result_response(
void
ClientBase::send_result_request(std::shared_ptr<void> request, ResponseCallback callback)
{
std::lock_guard<std::mutex> guard(pimpl_->result_requests_mutex);
std::lock_guard<std::recursive_mutex> guard(pimpl_->result_requests_mutex);
int64_t sequence_number;
rcl_ret_t ret = rcl_action_send_result_request(
pimpl_->client_handle.get(), request.get(), &sequence_number);
@@ -449,7 +449,7 @@ ClientBase::handle_cancel_response(
const rmw_request_id_t & response_header,
std::shared_ptr<void> response)
{
std::lock_guard<std::mutex> guard(pimpl_->cancel_requests_mutex);
std::lock_guard<std::recursive_mutex> guard(pimpl_->cancel_requests_mutex);
const int64_t & sequence_number = response_header.sequence_number;
if (pimpl_->pending_cancel_responses.count(sequence_number) == 0) {
RCLCPP_ERROR(pimpl_->logger, "unknown cancel response, ignoring...");
@@ -462,7 +462,7 @@ ClientBase::handle_cancel_response(
void
ClientBase::send_cancel_request(std::shared_ptr<void> request, ResponseCallback callback)
{
std::lock_guard<std::mutex> guard(pimpl_->cancel_requests_mutex);
std::lock_guard<std::recursive_mutex> guard(pimpl_->cancel_requests_mutex);
int64_t sequence_number;
rcl_ret_t ret = rcl_action_send_cancel_request(
pimpl_->client_handle.get(), request.get(), &sequence_number);

View File

@@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <chrono>
#include <future>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <thread>
#include <chrono>
#include "gtest/gtest.h"

View File

@@ -67,7 +67,7 @@ TEST(TestActionTypes, goal_uuid_to_hashed_uuid_random) {
// Use std::random_device to seed the generator of goal IDs.
std::random_device rd;
std::independent_bits_engine<
std::default_random_engine, 8, decltype(rd())> random_bytes_generator(rd());
std::mt19937, 8, decltype(rd())> random_bytes_generator(rd());
std::vector<size_t> hashed_guuids;
constexpr size_t iterations = 1000;

View File

@@ -2,6 +2,17 @@
Changelog for package rclcpp_components
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29.5.2 (2025-07-07)
-------------------
29.5.1 (2025-06-23)
-------------------
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
* Contributors: mergify[bot]
29.5.0 (2025-04-18)
-------------------
29.4.0 (2025-04-04)
-------------------
* Removed trailing whitespace from the codebase. (`#2791 <https://github.com/ros2/rclcpp/issues/2791>`_)

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>29.4.0</version>
<version>29.5.2</version>
<description>Package containing tools for dynamically loadable components</description>
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>

View File

@@ -14,6 +14,7 @@
#include <gtest/gtest.h>
#include <chrono>
#include <memory>
#include <string>

View File

@@ -3,6 +3,17 @@ Changelog for package rclcpp_lifecycle
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29.5.2 (2025-07-07)
-------------------
29.5.1 (2025-06-23)
-------------------
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
* Contributors: mergify[bot]
29.5.0 (2025-04-18)
-------------------
29.4.0 (2025-04-04)
-------------------
* should pull valid transition before trying to change the state. (`#2774 <https://github.com/ros2/rclcpp/issues/2774>`_)

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>29.4.0</version>
<version>29.5.2</version>
<description>Package containing a prototype for lifecycle implementation</description>
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>

View File

@@ -14,6 +14,7 @@
#include <benchmark/benchmark.h>
#include <chrono>
#include <memory>
#include <string>
#include <vector>

View File

@@ -14,6 +14,7 @@
#include <gtest/gtest.h>
#include <chrono>
#include <map>
#include <memory>
#include <set>

View File

@@ -14,6 +14,7 @@
#include <gtest/gtest.h>
#include <chrono>
#include <string>
#include <memory>
#include <utility>