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 if (!std::isfinite(x) || !std::isfinite(y)) {
186 return std::abs(x - y) <= std::numeric_limits<double>::epsilon() * std::abs(x + y) * ulp;
191 format_range_reason(
const std::string & name,
const char * range_type)
193 std::ostringstream ss;
194 ss <<
"Parameter {" << name <<
"} doesn't comply with " << range_type <<
" range.";
199 rcl_interfaces::msg::SetParametersResult
200 __check_integer_range(
201 const rcl_interfaces::msg::ParameterDescriptor & descriptor,
204 rcl_interfaces::msg::SetParametersResult result;
205 result.successful =
true;
206 auto integer_range = descriptor.integer_range.at(0);
207 if (value == integer_range.from_value || value == integer_range.to_value) {
210 if ((value < integer_range.from_value) || (value > integer_range.to_value)) {
211 result.successful =
false;
212 result.reason = format_range_reason(descriptor.name,
"integer");
215 if (integer_range.step == 0) {
218 if (((value - integer_range.from_value) % integer_range.step) == 0) {
221 result.successful =
false;
222 result.reason = format_range_reason(descriptor.name,
"integer");
227 rcl_interfaces::msg::SetParametersResult
228 __check_double_range(
229 const rcl_interfaces::msg::ParameterDescriptor & descriptor,
232 rcl_interfaces::msg::SetParametersResult result;
233 result.successful =
true;
234 auto fp_range = descriptor.floating_point_range.at(0);
235 if (__are_doubles_equal(value, fp_range.from_value) || __are_doubles_equal(value,
240 if (!(value >= fp_range.from_value && value <= fp_range.to_value)) {
241 result.successful =
false;
242 result.reason = format_range_reason(descriptor.name,
"floating point");
245 if (fp_range.step == 0.0) {
248 double rounded_div = std::round((value - fp_range.from_value) / fp_range.step);
249 if (__are_doubles_equal(value, fp_range.from_value + rounded_div * fp_range.step)) {
252 result.successful =
false;
253 result.reason = format_range_reason(descriptor.name,
"floating point");
258 rcl_interfaces::msg::SetParametersResult
259 __check_parameter_value_in_range(
260 const rcl_interfaces::msg::ParameterDescriptor & descriptor,
263 rcl_interfaces::msg::SetParametersResult result;
264 result.successful =
true;
265 if (!descriptor.integer_range.empty() && value.
get_type() == rclcpp::PARAMETER_INTEGER) {
266 result = __check_integer_range(descriptor, value.get<int64_t>());
270 if (!descriptor.integer_range.empty() && value.
get_type() == rclcpp::PARAMETER_INTEGER_ARRAY) {
271 std::vector<int64_t> val_array = value.get<std::vector<int64_t>>();
272 for (
const int64_t & val : val_array) {
273 result = __check_integer_range(descriptor, val);
274 if (!result.successful) {
281 if (!descriptor.floating_point_range.empty() && value.
get_type() == rclcpp::PARAMETER_DOUBLE) {
282 result = __check_double_range(descriptor, value.get<
double>());
286 if (!descriptor.floating_point_range.empty() &&
287 value.
get_type() == rclcpp::PARAMETER_DOUBLE_ARRAY)
289 std::vector<double> val_array = value.get<std::vector<double>>();
290 for (
const double & val : val_array) {
291 result = __check_double_range(descriptor, val);
292 if (!result.successful) {
305 const std::string & name,
const std::string & old_type,
const std::string & new_type)
307 std::ostringstream ss;
310 ss <<
"Wrong parameter type, parameter {" << name <<
"} is of type {" << old_type <<
311 "}, setting it to {" << new_type <<
"} is not allowed.";
317 rcl_interfaces::msg::SetParametersResult
319 std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameter_infos,
320 const std::vector<rclcpp::Parameter> & parameters,
321 bool allow_undeclared)
323 rcl_interfaces::msg::SetParametersResult result;
324 result.successful =
true;
326 std::string name = parameter.get_name();
327 rcl_interfaces::msg::ParameterDescriptor descriptor;
328 if (allow_undeclared) {
329 auto it = parameter_infos.find(name);
330 if (it != parameter_infos.cend()) {
331 descriptor = it->second.descriptor;
334 descriptor.dynamic_typing =
true;
337 descriptor = parameter_infos[name].descriptor;
339 if (descriptor.name.empty()) {
340 descriptor.name = name;
342 const auto new_type = parameter.get_type();
343 const auto specified_type =
static_cast<rclcpp::ParameterType
>(descriptor.type);
344 result.successful = descriptor.dynamic_typing || specified_type == new_type;
345 if (!result.successful) {
346 result.reason = format_type_reason(
350 result = __check_parameter_value_in_range(
352 parameter.get_parameter_value());
353 if (!result.successful) {
360 using PreSetParametersCallbackType =
361 rclcpp::node_interfaces::NodeParametersInterface::PreSetParametersCallbackType;
364 using PreSetCallbacksHandleContainer =
365 rclcpp::node_interfaces::NodeParameters::PreSetCallbacksHandleContainer;
367 using OnSetParametersCallbackType =
368 rclcpp::node_interfaces::NodeParametersInterface::OnSetParametersCallbackType;
371 using OnSetCallbacksHandleContainer =
372 rclcpp::node_interfaces::NodeParameters::OnSetCallbacksHandleContainer;
374 using PostSetParametersCallbackType =
375 rclcpp::node_interfaces::NodeParametersInterface::PostSetParametersCallbackType;
378 using PostSetCallbacksHandleContainer =
379 rclcpp::node_interfaces::NodeParameters::PostSetCallbacksHandleContainer;
383 __call_pre_set_parameters_callbacks(
384 std::vector<rclcpp::Parameter> & parameters,
385 PreSetCallbacksHandleContainer & callback_container)
387 if (callback_container.empty()) {
391 auto it = callback_container.begin();
392 while (it != callback_container.end()) {
393 auto shared_handle = it->lock();
394 if (
nullptr != shared_handle) {
395 shared_handle->callback(parameters);
398 it = callback_container.erase(it);
404 rcl_interfaces::msg::SetParametersResult
405 __call_on_set_parameters_callbacks(
406 const std::vector<rclcpp::Parameter> & parameters,
407 OnSetCallbacksHandleContainer & callback_container)
409 rcl_interfaces::msg::SetParametersResult result;
410 result.successful =
true;
411 auto it = callback_container.begin();
412 while (it != callback_container.end()) {
413 auto shared_handle = it->lock();
414 if (
nullptr != shared_handle) {
415 result = shared_handle->callback(parameters);
416 if (!result.successful) {
421 it = callback_container.erase(it);
428 void __call_post_set_parameters_callbacks(
429 const std::vector<rclcpp::Parameter> & parameters,
430 PostSetCallbacksHandleContainer & callback_container)
432 if (callback_container.empty()) {
436 auto it = callback_container.begin();
437 while (it != callback_container.end()) {
438 auto shared_handle = it->lock();
439 if (
nullptr != shared_handle) {
440 shared_handle->callback(parameters);
443 it = callback_container.erase(it);
449 rcl_interfaces::msg::SetParametersResult
450 __set_parameters_atomically_common(
451 const std::vector<rclcpp::Parameter> & parameters,
452 std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameter_infos,
453 OnSetCallbacksHandleContainer & on_set_callback_container,
454 PostSetCallbacksHandleContainer & post_set_callback_container,
455 bool allow_undeclared =
false)
458 rcl_interfaces::msg::SetParametersResult result = __check_parameters(
459 parameter_infos, parameters, allow_undeclared);
460 if (!result.successful) {
465 __call_on_set_parameters_callbacks(parameters, on_set_callback_container);
466 if (!result.successful) {
470 if (result.successful) {
471 for (
size_t i = 0; i < parameters.size(); ++i) {
472 const std::string & name = parameters[i].get_name();
473 parameter_infos[name].descriptor.name = parameters[i].get_name();
474 parameter_infos[name].descriptor.type = parameters[i].get_type();
475 parameter_infos[name].value = parameters[i].get_parameter_value();
478 __call_post_set_parameters_callbacks(parameters, post_set_callback_container);
486 rcl_interfaces::msg::SetParametersResult
487 __declare_parameter_common(
488 const std::string & name,
490 const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
491 std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameters_out,
492 const std::map<std::string, rclcpp::ParameterValue> & overrides,
493 OnSetCallbacksHandleContainer & on_set_callback_container,
494 PostSetCallbacksHandleContainer & post_set_callback_container,
495 rcl_interfaces::msg::ParameterEvent * parameter_event_out,
496 bool ignore_override =
false)
499 std::map<std::string, ParameterInfo> parameter_infos {{name, ParameterInfo()}};
500 parameter_infos.at(name).
descriptor = parameter_descriptor;
504 auto overrides_it = overrides.find(name);
505 if (!ignore_override && overrides_it != overrides.end()) {
506 initial_value = &overrides_it->second;
510 if (initial_value->
get_type() == rclcpp::PARAMETER_NOT_SET) {
512 parameter_infos[name].descriptor.name = name;
513 if (parameter_descriptor.dynamic_typing) {
514 parameter_infos[name].descriptor.type = rclcpp::PARAMETER_NOT_SET;
516 parameter_infos[name].descriptor.type = parameter_descriptor.type;
518 parameters_out[name] = parameter_infos.at(name);
519 rcl_interfaces::msg::SetParametersResult result;
520 result.successful =
true;
525 std::vector<rclcpp::Parameter> parameter_wrappers {
rclcpp::Parameter(name, *initial_value)};
527 auto result = __set_parameters_atomically_common(
530 on_set_callback_container,
531 post_set_callback_container
534 if (!result.successful) {
539 parameters_out[name] = parameter_infos.at(name);
542 if (parameter_event_out) {
543 parameter_event_out->new_parameters.push_back(parameter_wrappers[0].to_parameter_msg());
551 declare_parameter_helper(
552 const std::string & name,
553 rclcpp::ParameterType type,
555 rcl_interfaces::msg::ParameterDescriptor parameter_descriptor,
556 bool ignore_override,
557 std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameters,
558 const std::map<std::string, rclcpp::ParameterValue> & overrides,
559 OnSetCallbacksHandleContainer & on_set_callback_container,
560 PostSetCallbacksHandleContainer & post_set_callback_container,
562 const std::string & combined_name,
571 if (__lockless_has_parameter(parameters, name)) {
573 "parameter '" + name +
"' has already been declared");
576 if (!parameter_descriptor.dynamic_typing) {
577 if (rclcpp::PARAMETER_NOT_SET == type) {
580 if (rclcpp::PARAMETER_NOT_SET == type) {
583 "cannot declare a statically typed parameter with an uninitialized value"
586 parameter_descriptor.type =
static_cast<uint8_t
>(type);
589 rcl_interfaces::msg::ParameterEvent parameter_event;
590 auto result = __declare_parameter_common(
593 parameter_descriptor,
596 on_set_callback_container,
597 post_set_callback_container,
602 if (!result.successful) {
603 constexpr
const char type_error_msg_start[] =
"Wrong parameter type";
606 result.reason.c_str(), type_error_msg_start,
sizeof(type_error_msg_start) - 1))
613 "parameter '" + name +
"' could not be set: " + result.reason);
617 if (
nullptr != events_publisher) {
618 parameter_event.node = combined_name;
619 parameter_event.stamp = node_clock.
get_clock()->now();
620 events_publisher->
publish(parameter_event);
623 return parameters.at(name).value;
628 const std::string & name,
630 const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
631 bool ignore_override)
633 std::lock_guard<std::recursive_mutex> lock(mutex_);
636 return declare_parameter_helper(
638 rclcpp::PARAMETER_NOT_SET,
640 parameter_descriptor,
643 parameter_overrides_,
644 on_set_parameters_callback_container_,
645 post_set_parameters_callback_container_,
646 events_publisher_.get(),
653 const std::string & name,
654 rclcpp::ParameterType type,
655 const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
656 bool ignore_override)
658 std::lock_guard<std::recursive_mutex> lock(mutex_);
661 if (rclcpp::PARAMETER_NOT_SET == type) {
662 throw std::invalid_argument{
663 "declare_parameter(): the provided parameter type cannot be rclcpp::PARAMETER_NOT_SET"};
666 if (parameter_descriptor.dynamic_typing ==
true) {
667 throw std::invalid_argument{
668 "declare_parameter(): cannot declare parameter of specific type and pass descriptor"
669 "with `dynamic_typing=true`"};
672 return declare_parameter_helper(
676 parameter_descriptor,
679 parameter_overrides_,
680 on_set_parameters_callback_container_,
681 post_set_parameters_callback_container_,
682 events_publisher_.get(),
690 std::lock_guard<std::recursive_mutex> lock(mutex_);
694 auto parameter_info = parameters_.find(name);
695 if (parameter_info == parameters_.end()) {
697 "cannot undeclare parameter '" + name +
"' which has not yet been declared");
700 if (parameter_info->second.descriptor.read_only) {
702 "cannot undeclare parameter '" + name +
"' because it is read-only");
704 if (!parameter_info->second.descriptor.dynamic_typing) {
706 name,
"cannot undeclare a statically typed parameter"};
709 parameters_.erase(parameter_info);
715 std::lock_guard<std::recursive_mutex> lock(mutex_);
717 return __lockless_has_parameter(parameters_, name);
720 std::vector<rcl_interfaces::msg::SetParametersResult>
723 std::vector<rcl_interfaces::msg::SetParametersResult> results;
724 results.reserve(parameters.size());
726 for (
const auto & p : parameters) {
728 results.push_back(result);
734 template<
typename ParameterVectorType>
736 __find_parameter_by_name(
737 ParameterVectorType & parameters,
738 const std::string & name)
743 [&](
auto parameter) {return parameter.get_name() == name;});
746 rcl_interfaces::msg::SetParametersResult
749 std::lock_guard<std::recursive_mutex> lock(mutex_);
753 rcl_interfaces::msg::SetParametersResult result;
758 std::vector<rclcpp::Parameter> parameters_after_pre_set_callback(parameters);
759 __call_pre_set_parameters_callbacks(
760 parameters_after_pre_set_callback,
761 pre_set_parameters_callback_container_);
763 if (parameters_after_pre_set_callback.empty()) {
764 result.successful =
false;
765 result.reason =
"parameter list cannot be empty, this might be due to "
766 "pre_set_parameters_callback modifying the original parameters list.";
774 std::vector<const rclcpp::Parameter *> parameters_to_be_declared;
775 for (
const auto & parameter : parameters_after_pre_set_callback) {
776 const std::string & name = parameter.get_name();
784 auto parameter_info = parameters_.find(name);
785 if (parameter_info == parameters_.end()) {
787 if (allow_undeclared_) {
789 parameters_to_be_declared.push_back(¶meter);
796 "parameter '" + name +
"' cannot be set because it was not declared");
801 if (parameter_info->second.descriptor.read_only) {
802 result.successful =
false;
803 result.reason =
"parameter '" + name +
"' cannot be set because it is read-only";
812 std::map<std::string, rclcpp::node_interfaces::ParameterInfo> staged_parameter_changes;
813 rcl_interfaces::msg::ParameterEvent parameter_event_msg;
814 parameter_event_msg.node = combined_name_;
815 OnSetCallbacksHandleContainer empty_on_set_callback_container;
816 PostSetCallbacksHandleContainer empty_post_set_callback_container;
819 rcl_interfaces::msg::ParameterDescriptor descriptor;
820 descriptor.dynamic_typing =
true;
821 for (
auto parameter_to_be_declared : parameters_to_be_declared) {
824 result = __declare_parameter_common(
825 parameter_to_be_declared->get_name(),
826 parameter_to_be_declared->get_parameter_value(),
828 staged_parameter_changes,
829 parameter_overrides_,
831 empty_on_set_callback_container,
832 empty_post_set_callback_container,
833 ¶meter_event_msg,
835 if (!result.successful) {
845 const std::vector<rclcpp::Parameter> * parameters_to_be_set = ¶meters_after_pre_set_callback;
846 std::vector<rclcpp::Parameter> parameters_copy;
847 if (0 != staged_parameter_changes.size()) {
848 bool any_initial_values_used =
false;
849 for (
const auto & staged_parameter_change : staged_parameter_changes) {
850 auto it = __find_parameter_by_name(
851 parameters_after_pre_set_callback,
852 staged_parameter_change.first);
853 if (it->get_parameter_value() != staged_parameter_change.second.value) {
856 any_initial_values_used =
true;
861 if (any_initial_values_used) {
862 parameters_copy = parameters_after_pre_set_callback;
863 for (
const auto & staged_parameter_change : staged_parameter_changes) {
864 auto it = __find_parameter_by_name(parameters_copy, staged_parameter_change.first);
865 *it =
Parameter(staged_parameter_change.first, staged_parameter_change.second.value);
867 parameters_to_be_set = ¶meters_copy;
873 std::vector<const rclcpp::Parameter *> parameters_to_be_undeclared;
874 for (
const auto & parameter : *parameters_to_be_set) {
875 if (rclcpp::PARAMETER_NOT_SET == parameter.get_type()) {
876 auto it = parameters_.find(parameter.get_name());
877 if (it != parameters_.end() && rclcpp::PARAMETER_NOT_SET != it->second.value.get_type()) {
878 if (!it->second.descriptor.dynamic_typing) {
879 result.reason =
"cannot undeclare a statically typed parameter";
880 result.successful =
false;
883 parameters_to_be_undeclared.push_back(¶meter);
889 result = __set_parameters_atomically_common(
891 *parameters_to_be_set,
896 on_set_parameters_callback_container_,
897 post_set_parameters_callback_container_,
901 if (!result.successful) {
906 for (
const auto & kv_pair : staged_parameter_changes) {
908 assert(__lockless_has_parameter(parameters_, kv_pair.first));
910 assert(parameters_[kv_pair.first].value == kv_pair.second.value);
913 parameters_[kv_pair.first] = kv_pair.second;
917 for (
auto parameter_to_undeclare : parameters_to_be_undeclared) {
918 auto it = parameters_.find(parameter_to_undeclare->get_name());
920 assert(it != parameters_.end());
921 if (it != parameters_.end()) {
923 parameter_event_msg.deleted_parameters.push_back(
925 parameters_.erase(it);
931 for (
const auto & parameter : *parameters_to_be_set) {
932 if (staged_parameter_changes.find(parameter.get_name()) != staged_parameter_changes.end()) {
936 auto it = std::find_if(
937 parameters_to_be_undeclared.begin(),
938 parameters_to_be_undeclared.end(),
939 [¶meter](
const auto & p) {return p->get_name() == parameter.get_name();});
940 if (it != parameters_to_be_undeclared.end()) {
945 parameter_event_msg.changed_parameters.push_back(parameter.to_parameter_msg());
949 if (
nullptr != events_publisher_) {
950 parameter_event_msg.stamp = node_clock_->get_clock()->now();
951 events_publisher_->
publish(parameter_event_msg);
956 std::vector<rclcpp::Parameter>
959 std::vector<rclcpp::Parameter> results;
960 results.reserve(names.size());
962 std::lock_guard<std::recursive_mutex> lock(mutex_);
963 for (
auto & name : names) {
972 std::lock_guard<std::recursive_mutex> lock(mutex_);
974 auto param_iter = parameters_.find(name);
975 if (parameters_.end() != param_iter) {
977 param_iter->second.value.get_type() != rclcpp::ParameterType::PARAMETER_NOT_SET ||
978 param_iter->second.descriptor.dynamic_typing)
983 }
else if (this->allow_undeclared_) {
992 const std::string & name,
995 std::lock_guard<std::recursive_mutex> lock(mutex_);
997 auto param_iter = parameters_.find(name);
999 parameters_.end() != param_iter &&
1000 param_iter->second.value.get_type() != rclcpp::ParameterType::PARAMETER_NOT_SET)
1002 parameter = {name, param_iter->second.value};
1011 const std::string & prefix,
1012 std::map<std::string, rclcpp::Parameter> & parameters)
const
1014 std::lock_guard<std::recursive_mutex> lock(mutex_);
1016 std::string prefix_with_dot = prefix.empty() ? prefix : prefix +
".";
1019 for (
const auto & param : parameters_) {
1020 if (param.first.find(prefix_with_dot) == 0 && param.first.length() > prefix_with_dot.length()) {
1022 parameters[param.first.substr(prefix_with_dot.length())] =
rclcpp::Parameter(param.second);
1030 std::vector<rcl_interfaces::msg::ParameterDescriptor>
1031 NodeParameters::describe_parameters(
const std::vector<std::string> & names)
const
1033 std::lock_guard<std::recursive_mutex> lock(mutex_);
1034 std::vector<rcl_interfaces::msg::ParameterDescriptor> results;
1035 results.reserve(names.size());
1037 for (
const auto & name : names) {
1038 auto it = parameters_.find(name);
1039 if (it != parameters_.cend()) {
1040 results.push_back(it->second.descriptor);
1041 }
else if (allow_undeclared_) {
1043 rcl_interfaces::msg::ParameterDescriptor default_description;
1044 default_description.name = name;
1045 results.push_back(default_description);
1051 if (results.size() != names.size()) {
1052 throw std::runtime_error(
"results and names unexpectedly different sizes");
1058 std::vector<uint8_t>
1059 NodeParameters::get_parameter_types(
const std::vector<std::string> & names)
const
1061 std::lock_guard<std::recursive_mutex> lock(mutex_);
1062 std::vector<uint8_t> results;
1063 results.reserve(names.size());
1065 for (
const auto & name : names) {
1066 auto it = parameters_.find(name);
1067 if (it != parameters_.cend()) {
1068 results.push_back(it->second.value.get_type());
1069 }
else if (allow_undeclared_) {
1071 results.push_back(rcl_interfaces::msg::ParameterType::PARAMETER_NOT_SET);
1077 if (results.size() != names.size()) {
1078 throw std::runtime_error(
"results and names unexpectedly different sizes");
1084 rcl_interfaces::msg::ListParametersResult
1085 NodeParameters::list_parameters(
const std::vector<std::string> & prefixes, uint64_t depth)
const
1087 std::lock_guard<std::recursive_mutex> lock(mutex_);
1088 rcl_interfaces::msg::ListParametersResult result;
1092 const char * separator =
".";
1094 auto separators_less_than_depth = [&depth, &separator](
const std::string & str) ->
bool {
1095 return static_cast<uint64_t
>(std::count(str.begin(), str.end(), *separator)) < depth;
1098 bool recursive = (prefixes.size() == 0) &&
1099 (depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE);
1101 for (
const std::pair<const std::string, ParameterInfo> & kv : parameters_) {
1103 bool get_all = (prefixes.size() == 0) && separators_less_than_depth(kv.first);
1105 bool prefix_matches = std::any_of(
1106 prefixes.cbegin(), prefixes.cend(),
1107 [&kv, &depth, &separator, &separators_less_than_depth](
const std::string & prefix) {
1108 if (kv.first == prefix) {
1110 }
else if (kv.first.find(prefix + separator) == 0) {
1111 if (depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) {
1114 std::string substr = kv.first.substr(prefix.length() + 1);
1115 return separators_less_than_depth(substr);
1120 if (!prefix_matches) {
1126 result.names.push_back(kv.first);
1127 size_t last_separator = kv.first.find_last_of(separator);
1128 if (std::string::npos != last_separator) {
1129 std::string prefix = kv.first.substr(0, last_separator);
1131 std::find(result.prefixes.cbegin(), result.prefixes.cend(), prefix) ==
1132 result.prefixes.cend())
1134 result.prefixes.push_back(prefix);
1145 std::lock_guard<std::recursive_mutex> lock(mutex_);
1148 auto it = std::find_if(
1149 pre_set_parameters_callback_container_.begin(),
1150 pre_set_parameters_callback_container_.end(),
1151 [handle](
const auto & weak_handle) {
1152 return handle == weak_handle.lock().get();
1154 if (it != pre_set_parameters_callback_container_.end()) {
1155 pre_set_parameters_callback_container_.erase(it);
1157 throw std::runtime_error(
"Pre set parameter callback doesn't exist");
1165 std::lock_guard<std::recursive_mutex> lock(mutex_);
1168 auto it = std::find_if(
1169 on_set_parameters_callback_container_.begin(),
1170 on_set_parameters_callback_container_.end(),
1171 [handle](
const auto & weak_handle) {
1172 return handle == weak_handle.lock().get();
1174 if (it != on_set_parameters_callback_container_.end()) {
1175 on_set_parameters_callback_container_.erase(it);
1177 throw std::runtime_error(
"On set parameter callback doesn't exist");
1185 std::lock_guard<std::recursive_mutex> lock(mutex_);
1188 auto it = std::find_if(
1189 post_set_parameters_callback_container_.begin(),
1190 post_set_parameters_callback_container_.end(),
1191 [handle](
const auto & weak_handle) {
1192 return handle == weak_handle.lock().get();
1194 if (it != post_set_parameters_callback_container_.end()) {
1195 post_set_parameters_callback_container_.erase(it);
1197 throw std::runtime_error(
"Post set parameter callback doesn't exist");
1201 PreSetParametersCallbackHandle::SharedPtr
1204 std::lock_guard<std::recursive_mutex> lock(mutex_);
1207 auto handle = std::make_shared<PreSetParametersCallbackHandle>();
1208 handle->callback = callback;
1210 pre_set_parameters_callback_container_.emplace_front(handle);
1214 OnSetParametersCallbackHandle::SharedPtr
1217 std::lock_guard<std::recursive_mutex> lock(mutex_);
1220 auto handle = std::make_shared<OnSetParametersCallbackHandle>();
1221 handle->callback = callback;
1223 on_set_parameters_callback_container_.emplace_front(handle);
1227 PostSetParametersCallbackHandle::SharedPtr
1229 PostSetParametersCallbackType callback)
1231 std::lock_guard<std::recursive_mutex> lock(mutex_);
1234 auto handle = std::make_shared<PostSetParametersCallbackHandle>();
1235 handle->callback = callback;
1237 post_set_parameters_callback_container_.emplace_front(handle);
1241 const std::map<std::string, rclcpp::ParameterValue> &
1244 return parameter_overrides_;
1250 std::lock_guard<std::recursive_mutex> lock(mutex_);
1251 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.