18 #include <unordered_map>
22 #include "rclcpp/parameter_event_handler.hpp"
23 #include "rcpputils/join.hpp"
28 ParameterEventCallbackHandle::SharedPtr
30 const ParameterEventCallbackType & callback)
32 std::lock_guard<std::recursive_mutex> lock(callbacks_->mutex_);
33 auto handle = std::make_shared<ParameterEventCallbackHandle>();
34 handle->callback = callback;
35 callbacks_->event_callbacks_.emplace_front(handle);
42 const ParameterEventCallbackHandle::SharedPtr & callback_handle)
44 std::lock_guard<std::recursive_mutex> lock(callbacks_->mutex_);
45 auto it = std::find_if(
46 callbacks_->event_callbacks_.begin(),
47 callbacks_->event_callbacks_.end(),
48 [callback_handle](
const auto & weak_handle) {
49 return callback_handle.get() == weak_handle.lock().get();
51 if (it != callbacks_->event_callbacks_.end()) {
52 callbacks_->event_callbacks_.erase(it);
54 throw std::runtime_error(
"Callback doesn't exist");
58 ParameterCallbackHandle::SharedPtr
60 const std::string & parameter_name,
61 const ParameterCallbackType & callback,
62 const std::string & node_name)
64 std::lock_guard<std::recursive_mutex> lock(callbacks_->mutex_);
65 auto full_node_name = resolve_path(node_name);
67 auto handle = std::make_shared<ParameterCallbackHandle>();
68 handle->callback = callback;
69 handle->parameter_name = parameter_name;
70 handle->node_name = full_node_name;
72 callbacks_->parameter_callbacks_[{parameter_name, full_node_name}].emplace_front(handle);
84 if (node_names.empty()) {
93 std::string filter_expression;
94 size_t total = node_names.size();
95 for (
size_t i = 0; i < total; ++i) {
96 filter_expression +=
"node = %" + std::to_string(i);
98 filter_expression +=
" OR ";
103 std::vector<std::string> quoted_node_names;
104 const std::string delim(
"'");
105 for (
const auto & name : node_names) {
106 quoted_node_names.push_back(delim + resolve_path(name) + delim);
116 const ParameterCallbackHandle::SharedPtr & callback_handle)
118 std::lock_guard<std::recursive_mutex> lock(callbacks_->mutex_);
119 auto handle = callback_handle.get();
120 auto & container = callbacks_->parameter_callbacks_[{handle->parameter_name, handle->node_name}];
121 auto it = std::find_if(
124 [handle](
const auto & weak_handle) {
125 return handle == weak_handle.lock().get();
127 if (it != container.end()) {
129 if (container.empty()) {
130 callbacks_->parameter_callbacks_.erase({handle->parameter_name, handle->node_name});
133 throw std::runtime_error(
"Callback doesn't exist");
139 const rcl_interfaces::msg::ParameterEvent & event,
141 const std::string & parameter_name,
142 const std::string & node_name)
144 if (event.node != node_name) {
148 for (
auto & new_parameter : event.new_parameters) {
149 if (new_parameter.name == parameter_name) {
155 for (
auto & changed_parameter : event.changed_parameters) {
156 if (changed_parameter.name == parameter_name) {
167 const rcl_interfaces::msg::ParameterEvent & event,
168 const std::string & parameter_name,
169 const std::string & node_name)
173 if (event.node == node_name) {
176 throw std::runtime_error(
177 "The node name '" + node_name +
"' of parameter '" + parameter_name +
178 +
"' doesn't match the node name '" + event.node +
"' in parameter event");
184 std::vector<rclcpp::Parameter>
186 const rcl_interfaces::msg::ParameterEvent & event)
188 std::vector<rclcpp::Parameter> params;
190 for (
auto & new_parameter : event.new_parameters) {
194 for (
auto & changed_parameter : event.changed_parameters) {
204 std::lock_guard<std::recursive_mutex> lock(mutex_);
206 for (
auto it = parameter_callbacks_.begin(); it != parameter_callbacks_.end(); ++it) {
209 for (
auto cb = it->second.begin(); cb != it->second.end(); ++cb) {
210 auto shared_handle = cb->lock();
211 if (
nullptr != shared_handle) {
212 shared_handle->callback(p);
214 cb = it->second.erase(cb);
220 for (
auto event_cb = event_callbacks_.begin(); event_cb != event_callbacks_.end(); ++event_cb) {
221 auto shared_event_handle = event_cb->lock();
222 if (
nullptr != shared_event_handle) {
223 shared_event_handle->callback(event);
225 event_cb = event_callbacks_.erase(event_cb);
231 ParameterEventHandler::resolve_path(
const std::string & path)
234 return node_base_->get_fully_qualified_name();
237 if (*path.begin() !=
'/') {
238 auto ns = node_base_->get_namespace();
239 const std::vector<std::string> paths{ns, path};
240 if(ns == std::string(
"/")) {
244 return rcpputils::join(paths,
"/");
static RCLCPP_PUBLIC bool get_parameter_from_event(const rcl_interfaces::msg::ParameterEvent &event, rclcpp::Parameter ¶meter, const std::string ¶meter_name, const std::string &node_name="")
Get an rclcpp::Parameter from a parameter event.
static RCLCPP_PUBLIC std::vector< rclcpp::Parameter > get_parameters_from_event(const rcl_interfaces::msg::ParameterEvent &event)
Get all rclcpp::Parameter values from a parameter event.
RCLCPP_PUBLIC RCUTILS_WARN_UNUSED ParameterCallbackHandle::SharedPtr add_parameter_callback(const std::string ¶meter_name, const ParameterCallbackType &callback, const std::string &node_name="")
Add a callback for a specified parameter.
RCLCPP_PUBLIC void remove_parameter_callback(const ParameterCallbackHandle::SharedPtr &callback_handle)
Remove a parameter callback registered with add_parameter_callback.
RCLCPP_PUBLIC bool configure_nodes_filter(const std::vector< std::string > &node_names)
Configure which node parameter events will be received.
RCLCPP_PUBLIC void remove_parameter_event_callback(const ParameterEventCallbackHandle::SharedPtr &callback_handle)
Remove parameter event callback registered with add_parameter_event_callback.
RCLCPP_PUBLIC RCUTILS_WARN_UNUSED ParameterEventCallbackHandle::SharedPtr add_parameter_event_callback(const ParameterEventCallbackType &callback)
Set a callback for all parameter events.
Structure to store an arbitrary parameter with templated get/set methods.
static RCLCPP_PUBLIC Parameter from_parameter_msg(const rcl_interfaces::msg::Parameter ¶meter)
Convert a parameter message in a Parameter class object.
RCLCPP_PUBLIC bool is_cft_supported() const
Check if content filtered topic feature of the subscription instance is supported.
RCLCPP_PUBLIC void set_content_filter(const std::string &filter_expression, const std::vector< std::string > &expression_parameters={})
Set the filter expression and expression parameters for the subscription.
RCLCPP_PUBLIC bool is_cft_enabled() const
Check if content filtered topic feature of the subscription instance is enabled.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
RCLCPP_PUBLIC void event_callback(const rcl_interfaces::msg::ParameterEvent &event)
Callback for parameter events subscriptions.