15 #include "rclcpp/node_interfaces/node_parameters.hpp"
17 #include <rcl_yaml_param_parser/parser.h>
32 #include "rcl_interfaces/srv/list_parameters.hpp"
33 #include "rclcpp/create_publisher.hpp"
34 #include "rclcpp/parameter_map.hpp"
35 #include "rcutils/logging_macros.h"
36 #include "rmw/qos_profiles.h"
38 #include "../detail/resolve_parameter_overrides.hpp"
44 local_perform_automatically_declare_parameters_from_overrides(
45 const std::map<std::string, rclcpp::ParameterValue> & parameter_overrides,
46 std::function<
bool(
const std::string &)> has_parameter,
50 const rcl_interfaces::msg::ParameterDescriptor &,
54 rcl_interfaces::msg::ParameterDescriptor descriptor;
55 descriptor.dynamic_typing =
true;
56 for (
const auto & pair : parameter_overrides) {
57 if (!has_parameter(pair.first)) {
67 NodeParameters::NodeParameters(
68 const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
69 const rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
70 rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
71 const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services,
72 const rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock,
73 const std::vector<rclcpp::Parameter> & parameter_overrides,
74 bool start_parameter_services,
75 bool start_parameter_event_publisher,
78 bool allow_undeclared_parameters,
79 bool automatically_declare_parameters_from_overrides)
80 : allow_undeclared_(allow_undeclared_parameters),
81 events_publisher_(nullptr),
82 node_logging_(node_logging),
83 node_clock_(node_clock)
85 using MessageT = rcl_interfaces::msg::ParameterEvent;
87 using AllocatorT = std::allocator<void>;
90 parameter_event_publisher_options);
91 publisher_options.
allocator = std::make_shared<AllocatorT>();
93 if (start_parameter_services) {
94 parameter_service_ = std::make_shared<ParameterService>(node_base, node_services,
this);
97 if (start_parameter_event_publisher) {
99 events_publisher_ = rclcpp::create_publisher<MessageT, AllocatorT, PublisherT>(
107 const rcl_node_t * node = node_base->get_rcl_node_handle();
108 if (
nullptr == node) {
109 throw std::runtime_error(
"Need valid node handle in NodeParameters");
112 if (
nullptr == options) {
113 throw std::runtime_error(
"Need valid node options in NodeParameters");
118 auto context_ptr = node_base->get_context()->get_rcl_context();
119 global_args = &(context_ptr->global_arguments);
121 combined_name_ = node_base->get_fully_qualified_name();
123 parameter_overrides_ = rclcpp::detail::resolve_parameter_overrides(
124 combined_name_, parameter_overrides, &options->
arguments, global_args);
128 if (automatically_declare_parameters_from_overrides) {
129 using namespace std::placeholders;
130 local_perform_automatically_declare_parameters_from_overrides(
134 const std::string & name,
136 const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
137 bool ignore_override)
140 name, default_value, parameter_descriptor, ignore_override);
147 NodeParameters::perform_automatically_declare_parameters_from_overrides()
149 local_perform_automatically_declare_parameters_from_overrides(
151 [
this](
const std::string & name) {
155 const std::string & name,
157 const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
158 bool ignore_override)
161 name, default_value, parameter_descriptor, ignore_override);
166 NodeParameters::~NodeParameters()
171 __lockless_has_parameter(
172 const std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameters,
173 const std::string & name)
175 return parameters.find(name) != parameters.end();
181 __are_doubles_equal(
double x,
double y,
double ulp = 100.0)
183 return std::abs(x - y) <= std::numeric_limits<double>::epsilon() * std::abs(x + y) * ulp;
188 format_range_reason(
const std::string & name,
const char * range_type)
190 std::ostringstream ss;
191 ss <<
"Parameter {" << name <<
"} doesn't comply with " << range_type <<
" range.";
196 rcl_interfaces::msg::SetParametersResult
197 __check_integer_range(
198 const rcl_interfaces::msg::ParameterDescriptor & descriptor,
201 rcl_interfaces::msg::SetParametersResult result;
202 result.successful =
true;
203 auto integer_range = descriptor.integer_range.at(0);
204 if (value == integer_range.from_value || value == integer_range.to_value) {
207 if ((value < integer_range.from_value) || (value > integer_range.to_value)) {
208 result.successful =
false;
209 result.reason = format_range_reason(descriptor.name,
"integer");
212 if (integer_range.step == 0) {
215 if (((value - integer_range.from_value) % integer_range.step) == 0) {
218 result.successful =
false;
219 result.reason = format_range_reason(descriptor.name,
"integer");
224 rcl_interfaces::msg::SetParametersResult
225 __check_double_range(
226 const rcl_interfaces::msg::ParameterDescriptor & descriptor,
229 rcl_interfaces::msg::SetParametersResult result;
230 result.successful =
true;
231 auto fp_range = descriptor.floating_point_range.at(0);
232 if (__are_doubles_equal(value, fp_range.from_value) || __are_doubles_equal(value,
237 if ((value < fp_range.from_value) || (value > fp_range.to_value)) {
238 result.successful =
false;
239 result.reason = format_range_reason(descriptor.name,
"floating point");
242 if (fp_range.step == 0.0) {
245 double rounded_div = std::round((value - fp_range.from_value) / fp_range.step);
246 if (__are_doubles_equal(value, fp_range.from_value + rounded_div * fp_range.step)) {
249 result.successful =
false;
250 result.reason = format_range_reason(descriptor.name,
"floating point");
255 rcl_interfaces::msg::SetParametersResult
256 __check_parameter_value_in_range(
257 const rcl_interfaces::msg::ParameterDescriptor & descriptor,
260 rcl_interfaces::msg::SetParametersResult result;
261 result.successful =
true;
262 if (!descriptor.integer_range.empty() && value.
get_type() == rclcpp::PARAMETER_INTEGER) {
263 result = __check_integer_range(descriptor, value.get<int64_t>());
267 if (!descriptor.integer_range.empty() && value.
get_type() == rclcpp::PARAMETER_INTEGER_ARRAY) {
268 std::vector<int64_t> val_array = value.get<std::vector<int64_t>>();
269 for (
const int64_t & val : val_array) {
270 result = __check_integer_range(descriptor, val);
271 if (!result.successful) {
278 if (!descriptor.floating_point_range.empty() && value.
get_type() == rclcpp::PARAMETER_DOUBLE) {
279 result = __check_double_range(descriptor, value.get<
double>());
283 if (!descriptor.floating_point_range.empty() &&
284 value.
get_type() == rclcpp::PARAMETER_DOUBLE_ARRAY)
286 std::vector<double> val_array = value.get<std::vector<double>>();
287 for (
const double & val : val_array) {
288 result = __check_double_range(descriptor, val);
289 if (!result.successful) {
302 const std::string & name,
const std::string & old_type,
const std::string & new_type)
304 std::ostringstream ss;
307 ss <<
"Wrong parameter type, parameter {" << name <<
"} is of type {" << old_type <<
308 "}, setting it to {" << new_type <<
"} is not allowed.";
314 rcl_interfaces::msg::SetParametersResult
316 std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameter_infos,
317 const std::vector<rclcpp::Parameter> & parameters,
318 bool allow_undeclared)
320 rcl_interfaces::msg::SetParametersResult result;
321 result.successful =
true;
323 std::string name = parameter.get_name();
324 rcl_interfaces::msg::ParameterDescriptor descriptor;
325 if (allow_undeclared) {
326 auto it = parameter_infos.find(name);
327 if (it != parameter_infos.cend()) {
328 descriptor = it->second.descriptor;
331 descriptor.dynamic_typing =
true;
334 descriptor = parameter_infos[name].descriptor;
336 if (descriptor.name.empty()) {
337 descriptor.name = name;
339 const auto new_type = parameter.get_type();
340 const auto specified_type =
static_cast<rclcpp::ParameterType
>(descriptor.type);
341 result.successful = descriptor.dynamic_typing || specified_type == new_type;
342 if (!result.successful) {
343 result.reason = format_type_reason(
347 result = __check_parameter_value_in_range(
349 parameter.get_parameter_value());
350 if (!result.successful) {
357 using PreSetParametersCallbackType =
358 rclcpp::node_interfaces::NodeParametersInterface::PreSetParametersCallbackType;
361 using PreSetCallbacksHandleContainer =
362 rclcpp::node_interfaces::NodeParameters::PreSetCallbacksHandleContainer;
364 using OnSetParametersCallbackType =
365 rclcpp::node_interfaces::NodeParametersInterface::OnSetParametersCallbackType;
368 using OnSetCallbacksHandleContainer =
369 rclcpp::node_interfaces::NodeParameters::OnSetCallbacksHandleContainer;
371 using PostSetParametersCallbackType =
372 rclcpp::node_interfaces::NodeParametersInterface::PostSetParametersCallbackType;
375 using PostSetCallbacksHandleContainer =
376 rclcpp::node_interfaces::NodeParameters::PostSetCallbacksHandleContainer;
380 __call_pre_set_parameters_callbacks(
381 std::vector<rclcpp::Parameter> & parameters,
382 PreSetCallbacksHandleContainer & callback_container)
384 if (callback_container.empty()) {
388 auto it = callback_container.begin();
389 while (it != callback_container.end()) {
390 auto shared_handle = it->lock();
391 if (
nullptr != shared_handle) {
392 shared_handle->callback(parameters);
395 it = callback_container.erase(it);
401 rcl_interfaces::msg::SetParametersResult
402 __call_on_set_parameters_callbacks(
403 const std::vector<rclcpp::Parameter> & parameters,
404 OnSetCallbacksHandleContainer & callback_container)
406 rcl_interfaces::msg::SetParametersResult result;
407 result.successful =
true;
408 auto it = callback_container.begin();
409 while (it != callback_container.end()) {
410 auto shared_handle = it->lock();
411 if (
nullptr != shared_handle) {
412 result = shared_handle->callback(parameters);
413 if (!result.successful) {
418 it = callback_container.erase(it);
425 void __call_post_set_parameters_callbacks(
426 const std::vector<rclcpp::Parameter> & parameters,
427 PostSetCallbacksHandleContainer & callback_container)
429 if (callback_container.empty()) {
433 auto it = callback_container.begin();
434 while (it != callback_container.end()) {
435 auto shared_handle = it->lock();
436 if (
nullptr != shared_handle) {
437 shared_handle->callback(parameters);
440 it = callback_container.erase(it);
446 rcl_interfaces::msg::SetParametersResult
447 __set_parameters_atomically_common(
448 const std::vector<rclcpp::Parameter> & parameters,
449 std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameter_infos,
450 OnSetCallbacksHandleContainer & on_set_callback_container,
451 PostSetCallbacksHandleContainer & post_set_callback_container,
452 bool allow_undeclared =
false)
455 rcl_interfaces::msg::SetParametersResult result = __check_parameters(
456 parameter_infos, parameters, allow_undeclared);
457 if (!result.successful) {
462 __call_on_set_parameters_callbacks(parameters, on_set_callback_container);
463 if (!result.successful) {
467 if (result.successful) {
468 for (
size_t i = 0; i < parameters.size(); ++i) {
469 const std::string & name = parameters[i].get_name();
470 parameter_infos[name].descriptor.name = parameters[i].get_name();
471 parameter_infos[name].descriptor.type = parameters[i].get_type();
472 parameter_infos[name].value = parameters[i].get_parameter_value();
475 __call_post_set_parameters_callbacks(parameters, post_set_callback_container);
483 rcl_interfaces::msg::SetParametersResult
484 __declare_parameter_common(
485 const std::string & name,
487 const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
488 std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameters_out,
489 const std::map<std::string, rclcpp::ParameterValue> & overrides,
490 OnSetCallbacksHandleContainer & on_set_callback_container,
491 PostSetCallbacksHandleContainer & post_set_callback_container,
492 rcl_interfaces::msg::ParameterEvent * parameter_event_out,
493 bool ignore_override =
false)
496 std::map<std::string, ParameterInfo> parameter_infos {{name, ParameterInfo()}};
497 parameter_infos.at(name).
descriptor = parameter_descriptor;
501 auto overrides_it = overrides.find(name);
502 if (!ignore_override && overrides_it != overrides.end()) {
503 initial_value = &overrides_it->second;
507 if (initial_value->
get_type() == rclcpp::PARAMETER_NOT_SET) {
509 parameter_infos[name].descriptor.name = name;
510 if (parameter_descriptor.dynamic_typing) {
511 parameter_infos[name].descriptor.type = rclcpp::PARAMETER_NOT_SET;
513 parameter_infos[name].descriptor.type = parameter_descriptor.type;
515 parameters_out[name] = parameter_infos.at(name);
516 rcl_interfaces::msg::SetParametersResult result;
517 result.successful =
true;
522 std::vector<rclcpp::Parameter> parameter_wrappers {
rclcpp::Parameter(name, *initial_value)};
524 auto result = __set_parameters_atomically_common(
527 on_set_callback_container,
528 post_set_callback_container
531 if (!result.successful) {
536 parameters_out[name] = parameter_infos.at(name);
539 if (parameter_event_out) {
540 parameter_event_out->new_parameters.push_back(parameter_wrappers[0].to_parameter_msg());
548 declare_parameter_helper(
549 const std::string & name,
550 rclcpp::ParameterType type,
552 rcl_interfaces::msg::ParameterDescriptor parameter_descriptor,
553 bool ignore_override,
554 std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameters,
555 const std::map<std::string, rclcpp::ParameterValue> & overrides,
556 OnSetCallbacksHandleContainer & on_set_callback_container,
557 PostSetCallbacksHandleContainer & post_set_callback_container,
559 const std::string & combined_name,
568 if (__lockless_has_parameter(parameters, name)) {
570 "parameter '" + name +
"' has already been declared");
573 if (!parameter_descriptor.dynamic_typing) {
574 if (rclcpp::PARAMETER_NOT_SET == type) {
577 if (rclcpp::PARAMETER_NOT_SET == type) {
580 "cannot declare a statically typed parameter with an uninitialized value"
583 parameter_descriptor.type =
static_cast<uint8_t
>(type);
586 rcl_interfaces::msg::ParameterEvent parameter_event;
587 auto result = __declare_parameter_common(
590 parameter_descriptor,
593 on_set_callback_container,
594 post_set_callback_container,
599 if (!result.successful) {
600 constexpr
const char type_error_msg_start[] =
"Wrong parameter type";
603 result.reason.c_str(), type_error_msg_start,
sizeof(type_error_msg_start) - 1))
610 "parameter '" + name +
"' could not be set: " + result.reason);
614 if (
nullptr != events_publisher) {
615 parameter_event.node = combined_name;
616 parameter_event.stamp = node_clock.
get_clock()->now();
617 events_publisher->
publish(parameter_event);
620 return parameters.at(name).value;
625 const std::string & name,
627 const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
628 bool ignore_override)
630 std::lock_guard<std::recursive_mutex> lock(mutex_);
633 return declare_parameter_helper(
635 rclcpp::PARAMETER_NOT_SET,
637 parameter_descriptor,
640 parameter_overrides_,
641 on_set_parameters_callback_container_,
642 post_set_parameters_callback_container_,
643 events_publisher_.get(),
650 const std::string & name,
651 rclcpp::ParameterType type,
652 const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
653 bool ignore_override)
655 std::lock_guard<std::recursive_mutex> lock(mutex_);
658 if (rclcpp::PARAMETER_NOT_SET == type) {
659 throw std::invalid_argument{
660 "declare_parameter(): the provided parameter type cannot be rclcpp::PARAMETER_NOT_SET"};
663 if (parameter_descriptor.dynamic_typing ==
true) {
664 throw std::invalid_argument{
665 "declare_parameter(): cannot declare parameter of specific type and pass descriptor"
666 "with `dynamic_typing=true`"};
669 return declare_parameter_helper(
673 parameter_descriptor,
676 parameter_overrides_,
677 on_set_parameters_callback_container_,
678 post_set_parameters_callback_container_,
679 events_publisher_.get(),
687 std::lock_guard<std::recursive_mutex> lock(mutex_);
691 auto parameter_info = parameters_.find(name);
692 if (parameter_info == parameters_.end()) {
694 "cannot undeclare parameter '" + name +
"' which has not yet been declared");
697 if (parameter_info->second.descriptor.read_only) {
699 "cannot undeclare parameter '" + name +
"' because it is read-only");
701 if (!parameter_info->second.descriptor.dynamic_typing) {
703 name,
"cannot undeclare a statically typed parameter"};
706 parameters_.erase(parameter_info);
712 std::lock_guard<std::recursive_mutex> lock(mutex_);
714 return __lockless_has_parameter(parameters_, name);
717 std::vector<rcl_interfaces::msg::SetParametersResult>
720 std::vector<rcl_interfaces::msg::SetParametersResult> results;
721 results.reserve(parameters.size());
723 for (
const auto & p : parameters) {
725 results.push_back(result);
731 template<
typename ParameterVectorType>
733 __find_parameter_by_name(
734 ParameterVectorType & parameters,
735 const std::string & name)
740 [&](
auto parameter) {return parameter.get_name() == name;});
743 rcl_interfaces::msg::SetParametersResult
746 std::lock_guard<std::recursive_mutex> lock(mutex_);
750 rcl_interfaces::msg::SetParametersResult result;
755 std::vector<rclcpp::Parameter> parameters_after_pre_set_callback(parameters);
756 __call_pre_set_parameters_callbacks(
757 parameters_after_pre_set_callback,
758 pre_set_parameters_callback_container_);
760 if (parameters_after_pre_set_callback.empty()) {
761 result.successful =
false;
762 result.reason =
"parameter list cannot be empty, this might be due to "
763 "pre_set_parameters_callback modifying the original parameters list.";
771 std::vector<const rclcpp::Parameter *> parameters_to_be_declared;
772 for (
const auto & parameter : parameters_after_pre_set_callback) {
773 const std::string & name = parameter.get_name();
781 auto parameter_info = parameters_.find(name);
782 if (parameter_info == parameters_.end()) {
784 if (allow_undeclared_) {
786 parameters_to_be_declared.push_back(¶meter);
793 "parameter '" + name +
"' cannot be set because it was not declared");
798 if (parameter_info->second.descriptor.read_only) {
799 result.successful =
false;
800 result.reason =
"parameter '" + name +
"' cannot be set because it is read-only";
809 std::map<std::string, rclcpp::node_interfaces::ParameterInfo> staged_parameter_changes;
810 rcl_interfaces::msg::ParameterEvent parameter_event_msg;
811 parameter_event_msg.node = combined_name_;
812 OnSetCallbacksHandleContainer empty_on_set_callback_container;
813 PostSetCallbacksHandleContainer empty_post_set_callback_container;
816 rcl_interfaces::msg::ParameterDescriptor descriptor;
817 descriptor.dynamic_typing =
true;
818 for (
auto parameter_to_be_declared : parameters_to_be_declared) {
821 result = __declare_parameter_common(
822 parameter_to_be_declared->get_name(),
823 parameter_to_be_declared->get_parameter_value(),
825 staged_parameter_changes,
826 parameter_overrides_,
828 empty_on_set_callback_container,
829 empty_post_set_callback_container,
830 ¶meter_event_msg,
832 if (!result.successful) {
842 const std::vector<rclcpp::Parameter> * parameters_to_be_set = ¶meters_after_pre_set_callback;
843 std::vector<rclcpp::Parameter> parameters_copy;
844 if (0 != staged_parameter_changes.size()) {
845 bool any_initial_values_used =
false;
846 for (
const auto & staged_parameter_change : staged_parameter_changes) {
847 auto it = __find_parameter_by_name(
848 parameters_after_pre_set_callback,
849 staged_parameter_change.first);
850 if (it->get_parameter_value() != staged_parameter_change.second.value) {
853 any_initial_values_used =
true;
858 if (any_initial_values_used) {
859 parameters_copy = parameters_after_pre_set_callback;
860 for (
const auto & staged_parameter_change : staged_parameter_changes) {
861 auto it = __find_parameter_by_name(parameters_copy, staged_parameter_change.first);
862 *it =
Parameter(staged_parameter_change.first, staged_parameter_change.second.value);
864 parameters_to_be_set = ¶meters_copy;
870 std::vector<const rclcpp::Parameter *> parameters_to_be_undeclared;
871 for (
const auto & parameter : *parameters_to_be_set) {
872 if (rclcpp::PARAMETER_NOT_SET == parameter.get_type()) {
873 auto it = parameters_.find(parameter.get_name());
874 if (it != parameters_.end() && rclcpp::PARAMETER_NOT_SET != it->second.value.get_type()) {
875 if (!it->second.descriptor.dynamic_typing) {
876 result.reason =
"cannot undeclare a statically typed parameter";
877 result.successful =
false;
880 parameters_to_be_undeclared.push_back(¶meter);
886 result = __set_parameters_atomically_common(
888 *parameters_to_be_set,
893 on_set_parameters_callback_container_,
894 post_set_parameters_callback_container_,
898 if (!result.successful) {
903 for (
const auto & kv_pair : staged_parameter_changes) {
905 assert(__lockless_has_parameter(parameters_, kv_pair.first));
907 assert(parameters_[kv_pair.first].value == kv_pair.second.value);
910 parameters_[kv_pair.first] = kv_pair.second;
914 for (
auto parameter_to_undeclare : parameters_to_be_undeclared) {
915 auto it = parameters_.find(parameter_to_undeclare->get_name());
917 assert(it != parameters_.end());
918 if (it != parameters_.end()) {
920 parameter_event_msg.deleted_parameters.push_back(
922 parameters_.erase(it);
928 for (
const auto & parameter : *parameters_to_be_set) {
929 if (staged_parameter_changes.find(parameter.get_name()) != staged_parameter_changes.end()) {
933 auto it = std::find_if(
934 parameters_to_be_undeclared.begin(),
935 parameters_to_be_undeclared.end(),
936 [¶meter](
const auto & p) {return p->get_name() == parameter.get_name();});
937 if (it != parameters_to_be_undeclared.end()) {
942 parameter_event_msg.changed_parameters.push_back(parameter.to_parameter_msg());
946 if (
nullptr != events_publisher_) {
947 parameter_event_msg.stamp = node_clock_->get_clock()->now();
948 events_publisher_->
publish(parameter_event_msg);
953 std::vector<rclcpp::Parameter>
956 std::vector<rclcpp::Parameter> results;
957 results.reserve(names.size());
959 std::lock_guard<std::recursive_mutex> lock(mutex_);
960 for (
auto & name : names) {
969 std::lock_guard<std::recursive_mutex> lock(mutex_);
971 auto param_iter = parameters_.find(name);
972 if (parameters_.end() != param_iter) {
974 param_iter->second.value.get_type() != rclcpp::ParameterType::PARAMETER_NOT_SET ||
975 param_iter->second.descriptor.dynamic_typing)
980 }
else if (this->allow_undeclared_) {
989 const std::string & name,
992 std::lock_guard<std::recursive_mutex> lock(mutex_);
994 auto param_iter = parameters_.find(name);
996 parameters_.end() != param_iter &&
997 param_iter->second.value.get_type() != rclcpp::ParameterType::PARAMETER_NOT_SET)
999 parameter = {name, param_iter->second.value};
1008 const std::string & prefix,
1009 std::map<std::string, rclcpp::Parameter> & parameters)
const
1011 std::lock_guard<std::recursive_mutex> lock(mutex_);
1013 std::string prefix_with_dot = prefix.empty() ? prefix : prefix +
".";
1016 for (
const auto & param : parameters_) {
1017 if (param.first.find(prefix_with_dot) == 0 && param.first.length() > prefix_with_dot.length()) {
1019 parameters[param.first.substr(prefix_with_dot.length())] =
rclcpp::Parameter(param.second);
1027 std::vector<rcl_interfaces::msg::ParameterDescriptor>
1028 NodeParameters::describe_parameters(
const std::vector<std::string> & names)
const
1030 std::lock_guard<std::recursive_mutex> lock(mutex_);
1031 std::vector<rcl_interfaces::msg::ParameterDescriptor> results;
1032 results.reserve(names.size());
1034 for (
const auto & name : names) {
1035 auto it = parameters_.find(name);
1036 if (it != parameters_.cend()) {
1037 results.push_back(it->second.descriptor);
1038 }
else if (allow_undeclared_) {
1040 rcl_interfaces::msg::ParameterDescriptor default_description;
1041 default_description.name = name;
1042 results.push_back(default_description);
1048 if (results.size() != names.size()) {
1049 throw std::runtime_error(
"results and names unexpectedly different sizes");
1055 std::vector<uint8_t>
1056 NodeParameters::get_parameter_types(
const std::vector<std::string> & names)
const
1058 std::lock_guard<std::recursive_mutex> lock(mutex_);
1059 std::vector<uint8_t> results;
1060 results.reserve(names.size());
1062 for (
const auto & name : names) {
1063 auto it = parameters_.find(name);
1064 if (it != parameters_.cend()) {
1065 results.push_back(it->second.value.get_type());
1066 }
else if (allow_undeclared_) {
1068 results.push_back(rcl_interfaces::msg::ParameterType::PARAMETER_NOT_SET);
1074 if (results.size() != names.size()) {
1075 throw std::runtime_error(
"results and names unexpectedly different sizes");
1081 rcl_interfaces::msg::ListParametersResult
1082 NodeParameters::list_parameters(
const std::vector<std::string> & prefixes, uint64_t depth)
const
1084 std::lock_guard<std::recursive_mutex> lock(mutex_);
1085 rcl_interfaces::msg::ListParametersResult result;
1089 const char * separator =
".";
1091 auto separators_less_than_depth = [&depth, &separator](
const std::string & str) ->
bool {
1092 return static_cast<uint64_t
>(std::count(str.begin(), str.end(), *separator)) < depth;
1095 bool recursive = (prefixes.size() == 0) &&
1096 (depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE);
1098 for (
const std::pair<const std::string, ParameterInfo> & kv : parameters_) {
1100 bool get_all = (prefixes.size() == 0) && separators_less_than_depth(kv.first);
1102 bool prefix_matches = std::any_of(
1103 prefixes.cbegin(), prefixes.cend(),
1104 [&kv, &depth, &separator, &separators_less_than_depth](
const std::string & prefix) {
1105 if (kv.first == prefix) {
1107 }
else if (kv.first.find(prefix + separator) == 0) {
1108 if (depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) {
1111 std::string substr = kv.first.substr(prefix.length() + 1);
1112 return separators_less_than_depth(substr);
1117 if (!prefix_matches) {
1123 result.names.push_back(kv.first);
1124 size_t last_separator = kv.first.find_last_of(separator);
1125 if (std::string::npos != last_separator) {
1126 std::string prefix = kv.first.substr(0, last_separator);
1128 std::find(result.prefixes.cbegin(), result.prefixes.cend(), prefix) ==
1129 result.prefixes.cend())
1131 result.prefixes.push_back(prefix);
1142 std::lock_guard<std::recursive_mutex> lock(mutex_);
1145 auto it = std::find_if(
1146 pre_set_parameters_callback_container_.begin(),
1147 pre_set_parameters_callback_container_.end(),
1148 [handle](
const auto & weak_handle) {
1149 return handle == weak_handle.lock().get();
1151 if (it != pre_set_parameters_callback_container_.end()) {
1152 pre_set_parameters_callback_container_.erase(it);
1154 throw std::runtime_error(
"Pre set parameter callback doesn't exist");
1162 std::lock_guard<std::recursive_mutex> lock(mutex_);
1165 auto it = std::find_if(
1166 on_set_parameters_callback_container_.begin(),
1167 on_set_parameters_callback_container_.end(),
1168 [handle](
const auto & weak_handle) {
1169 return handle == weak_handle.lock().get();
1171 if (it != on_set_parameters_callback_container_.end()) {
1172 on_set_parameters_callback_container_.erase(it);
1174 throw std::runtime_error(
"On set parameter callback doesn't exist");
1182 std::lock_guard<std::recursive_mutex> lock(mutex_);
1185 auto it = std::find_if(
1186 post_set_parameters_callback_container_.begin(),
1187 post_set_parameters_callback_container_.end(),
1188 [handle](
const auto & weak_handle) {
1189 return handle == weak_handle.lock().get();
1191 if (it != post_set_parameters_callback_container_.end()) {
1192 post_set_parameters_callback_container_.erase(it);
1194 throw std::runtime_error(
"Post set parameter callback doesn't exist");
1198 PreSetParametersCallbackHandle::SharedPtr
1201 std::lock_guard<std::recursive_mutex> lock(mutex_);
1204 auto handle = std::make_shared<PreSetParametersCallbackHandle>();
1205 handle->callback = callback;
1207 pre_set_parameters_callback_container_.emplace_front(handle);
1211 OnSetParametersCallbackHandle::SharedPtr
1214 std::lock_guard<std::recursive_mutex> lock(mutex_);
1217 auto handle = std::make_shared<OnSetParametersCallbackHandle>();
1218 handle->callback = callback;
1220 on_set_parameters_callback_container_.emplace_front(handle);
1224 PostSetParametersCallbackHandle::SharedPtr
1226 PostSetParametersCallbackType callback)
1228 std::lock_guard<std::recursive_mutex> lock(mutex_);
1231 auto handle = std::make_shared<PostSetParametersCallbackHandle>();
1232 handle->callback = callback;
1234 post_set_parameters_callback_container_.emplace_front(handle);
1238 const std::map<std::string, rclcpp::ParameterValue> &
1241 return parameter_overrides_;
1247 std::lock_guard<std::recursive_mutex> lock(mutex_);
1248 parameter_modification_enabled_ =
true;
Store the type and value of a parameter.
RCLCPP_PUBLIC ParameterType get_type() const
Return an enum indicating the type of the set value.
Structure to store an arbitrary parameter with templated get/set methods.
RCLCPP_PUBLIC rcl_interfaces::msg::Parameter to_parameter_msg() const
Convert the class in a parameter message.
A publisher publishes messages of any type to a topic.
std::enable_if_t< rosidl_generator_traits::is_message< T >::value &&std::is_same< T, ROSMessageType >::value > publish(std::unique_ptr< T, ROSMessageTypeDeleter > msg)
Publish a message on the topic.
Encapsulation of Quality of Service settings.
Thrown if requested parameter type is invalid.
Thrown if passed parameter value is invalid.
Thrown if passed parameters are inconsistent or invalid.
Thrown if parameter is already declared.
Thrown if parameter is immutable and therefore cannot be undeclared.
Thrown if parameter is not declared, e.g. either set or get was called without first declaring.
Thrown when an uninitialized parameter is accessed.
Pure virtual interface class for the NodeClock part of the Node API.
virtual RCLCPP_PUBLIC rclcpp::Clock::SharedPtr get_clock()=0
Get a ROS clock which will be kept up to date by the node.
Implementation of the NodeParameters part of the Node API.
RCLCPP_PUBLIC RCUTILS_WARN_UNUSED PostSetParametersCallbackHandle::SharedPtr add_post_set_parameters_callback(PostSetParametersCallbackType callback) override
Add a callback that gets triggered after parameters are set successfully.
RCLCPP_PUBLIC const std::map< std::string, rclcpp::ParameterValue > & get_parameter_overrides() const override
Return the initial parameter values used by the NodeParameters to override default values.
RCLCPP_PUBLIC void remove_on_set_parameters_callback(const OnSetParametersCallbackHandle *const handler) override
Remove a callback registered with add_on_set_parameters_callback.
RCLCPP_PUBLIC std::vector< rclcpp::Parameter > get_parameters(const std::vector< std::string > &names) const override
Get descriptions of parameters given their names.
RCLCPP_PUBLIC void undeclare_parameter(const std::string &name) override
Undeclare a parameter.
RCLCPP_PUBLIC const rclcpp::ParameterValue & declare_parameter(const std::string &name, const rclcpp::ParameterValue &default_value, const rcl_interfaces::msg::ParameterDescriptor ¶meter_descriptor=rcl_interfaces::msg::ParameterDescriptor{}, bool ignore_override=false) override
Declare and initialize a parameter.
RCLCPP_PUBLIC RCUTILS_WARN_UNUSED OnSetParametersCallbackHandle::SharedPtr add_on_set_parameters_callback(OnSetParametersCallbackType callback) override
Add a callback to validate parameters before they are set.
RCLCPP_PUBLIC bool get_parameters_by_prefix(const std::string &prefix, std::map< std::string, rclcpp::Parameter > ¶meters) const override
Get all parameters that have the specified prefix into the parameters map.
RCLCPP_PUBLIC std::vector< rcl_interfaces::msg::SetParametersResult > set_parameters(const std::vector< rclcpp::Parameter > ¶meters) override
Set one or more parameters, one at a time.
RCLCPP_PUBLIC void remove_pre_set_parameters_callback(const PreSetParametersCallbackHandle *const handler) override
Remove a callback registered with add_pre_set_parameters_callback.
RCLCPP_PUBLIC void enable_parameter_modification() override
Enable parameter modification recursively during parameter callbacks.
RCLCPP_PUBLIC rcl_interfaces::msg::SetParametersResult set_parameters_atomically(const std::vector< rclcpp::Parameter > ¶meters) override
Set one or more parameters, all at once.
RCLCPP_PUBLIC RCUTILS_WARN_UNUSED PreSetParametersCallbackHandle::SharedPtr add_pre_set_parameters_callback(PreSetParametersCallbackType callback) override
Add a callback that gets triggered before parameters are validated.
RCLCPP_PUBLIC rclcpp::Parameter get_parameter(const std::string &name) const override
Get the description of one parameter given a name.
RCLCPP_PUBLIC void remove_post_set_parameters_callback(const PostSetParametersCallbackHandle *const handler) override
Remove a callback registered with add_post_set_parameters_callback.
RCLCPP_PUBLIC bool has_parameter(const std::string &name) const override
Return true if the parameter has been declared, otherwise false.
RCLCPP_PUBLIC std::string to_string(const FutureReturnCode &future_return_code)
String conversion function for FutureReturnCode.
RCL_PUBLIC RCL_WARN_UNUSED const rcl_node_options_t * rcl_node_get_options(const rcl_node_t *node)
Return the rcl node options.
Hold output of parsing command line arguments.
Structure which encapsulates the options for creating a rcl_node_t.
bool use_global_arguments
If false then only use arguments in this struct, otherwise use global arguments also.
rcl_arguments_t arguments
Command line arguments that apply only to this node.
Structure which encapsulates a ROS Node.
Non-templated part of PublisherOptionsWithAllocator<Allocator>.
Structure containing optional configuration for Publishers.
std::shared_ptr< Allocator > allocator
Optional custom allocator.
rcl_interfaces::msg::ParameterDescriptor descriptor
A description of the parameter.