15 std::ostream&
operator<<(std::ostream& os,
const std::vector<T>& var)
17 for (
size_t it = 0; it < var.size(); it++)
20 if (it < var.size() - 1)
26 template <
typename Key,
typename Value>
27 std::ostream&
operator<<(std::ostream& os,
const std::map<Key, Value>& var)
30 for (
const auto& pair : var)
32 os << pair.first <<
": " << pair.second;
33 if (it < var.size() - 1)
55 explicit operator std::string()
const
60 friend std::ostream& operator<<(std::ostream& os,
const resolved_name_t& r)
67 return lhs.str == rhs.str;
77 return rclcpp::ParameterValue{T{}}.get_type();
91 bool use_rosparam = m_use_rosparam;
97 if (opts.
use_yaml && loadFromYaml(resolved_name, value_out, opts))
101 if (use_rosparam && loadFromROS(resolved_name, value_out, opts))
107 const auto& default_value = opts.
declare_options.default_value.value();
111 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"Failed to declare parameter \"" << resolved_name <<
"\".");
115 value_out = default_value;
120 std::stringstream ss;
121 ss <<
"Param '" << resolved_name <<
"' not found:";
123 ss <<
" in YAML files,";
126 ss <<
" no default value provided.";
127 RCLCPP_ERROR_STREAM(m_node->get_logger(), ss.str());
133 template <
typename T>
139 template <
typename T>
143 if (!m_node->has_parameter(resolved_name.str))
146 declare_opts_local.default_value = value;
147 const auto result = declareParam<T>(resolved_name, declare_opts_local);
149 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"Could not declare and set param '" << resolved_name <<
"'!");
157 rcl_interfaces::msg::SetParametersResult res = m_node->set_parameter({resolved_name.str, value});
160 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"Could not set param '" << resolved_name <<
"': " << res.reason);
165 catch (
const rclcpp::exceptions::ParameterNotDeclaredException& e)
167 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"Could not set param '" << resolved_name <<
"': " << e.what());
175 template <
typename T>
178 return declareParam<T>(
resolveName(param_name), {});
181 template <
typename T>
184 return declareParam<T>(
resolveName(param_name), {.default_value = default_value});
187 template <
typename T>
192 rcl_interfaces::msg::ParameterDescriptor descriptor;
196 if (opts.
range.has_value())
198 const auto& opt_range = opts.
range.value();
203 RCLCPP_ERROR_STREAM(m_node->get_logger(),
204 "Error when declaring parameter \"" << resolved_name <<
"\": Range cannot be set for non-numerical values! Ignoring range.");
206 }
else if constexpr (std::integral<T>)
209 rcl_interfaces::msg::IntegerRange range;
210 range.from_value = opt_range.minimum;
211 range.to_value = opt_range.maximum;
212 descriptor.integer_range.push_back(range);
213 }
else if constexpr (std::floating_point<T>)
216 rcl_interfaces::msg::FloatingPointRange range;
217 range.from_value = opt_range.minimum;
218 range.to_value = opt_range.maximum;
219 descriptor.floating_point_range.push_back(range);
226 m_node->declare_parameter(resolved_name.str, opts.
default_value.value(), descriptor);
232 const rclcpp::ParameterType type = to_param_type<T>();
233 descriptor.type = type;
234 m_node->declare_parameter(resolved_name.str, type, descriptor);
237 catch (
const std::exception& e)
245 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"Could not declare param '" << resolved_name <<
"': " << e.what());
254 template <
typename T>
255 bool ParamProvider::loadFromYaml(
const resolved_name_t& resolved_name, T& value_out,
const get_options_t<T>& opts)
const
259 const auto found_node_opt = findYamlNode(resolved_name);
260 if (!found_node_opt.has_value())
265 const auto& found_node = found_node_opt.value();
269 loaded_value = applyTag<T>(found_node);
271 catch (
const YAML::BadConversion& e)
273 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"[" << m_node_name <<
"]: The YAML-loaded parameter has a wrong type: " << e.what());
276 catch (
const YAML::Exception& e)
278 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"[" << m_node_name <<
"]: YAML-CPP threw an unknown exception: " << e.what());
283 if (opts.always_declare)
285 auto declare_opts_local = opts.declare_options;
286 declare_opts_local.default_value = loaded_value;
289 if (!m_node->has_parameter(resolved_name.str) && !declareParam<T>(resolved_name, declare_opts_local))
291 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"Failed to declare parameter \"" << resolved_name <<
"\".");
297 value_out = loaded_value;
304 template <
typename T>
305 inline T ParamProvider::degrees2radians(
const T
degrees)
307 return degrees / T(180) * T(M_PI);
312 template <
typename T>
313 T ParamProvider::applyTag(
const YAML::Node& node)
const
315 if constexpr (std::is_floating_point_v<T>)
317 if (node.Tag() ==
"!degrees")
318 return degrees2radians(node.as<T>());
325 template <
typename T>
326 bool ParamProvider::ranges_match(
const rcl_interfaces::msg::ParameterDescriptor& descriptor,
const range_t<T>& declare_range)
const
328 if constexpr (numeric<T>)
330 if (!descriptor.floating_point_range.empty())
332 const auto& desc_range = descriptor.floating_point_range.front();
333 if (desc_range.from_value != declare_range.
minimum || desc_range.to_value != declare_range.
maximum)
337 if (!descriptor.integer_range.empty())
339 const auto& desc_range = descriptor.integer_range.front();
340 if (desc_range.from_value != declare_range.
minimum || desc_range.to_value != declare_range.
maximum)
352 template <
typename T>
353 bool ParamProvider::loadFromROS(
const resolved_name_t& resolved_name, T& value_out,
const get_options_t<T>& opts)
const
355 std::optional<T> loaded_value;
356 const bool was_declared = m_node->has_parameter(resolved_name.str);
361 const auto descriptor = m_node->describe_parameter(resolved_name.str);
362 if (descriptor.read_only && opts.declare_options.reconfigurable)
364 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"Parameter \"" << resolved_name <<
"\" already declared as read-only, cannot re-declare as reconfigurable!");
368 if (opts.declare_options.range.has_value() && !ranges_match(descriptor, opts.declare_options.range.value()))
370 RCLCPP_ERROR_STREAM(m_node->get_logger(),
371 "Parameter \"" << resolved_name <<
"\" already declared with a range, cannot re-declare with a different one!");
379 rcl_interfaces::msg::ParameterDescriptor descriptor;
380 descriptor.read_only =
false;
381 descriptor.dynamic_typing =
true;
384 m_node->declare_parameter(resolved_name.str, rclcpp::ParameterValue(), descriptor);
386 catch (
const std::exception& e)
389 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"Failed to declare parameter \"" << resolved_name <<
"\": " << e.what());
398 rclcpp::Parameter param;
399 if (m_node->get_parameter(resolved_name.str, param))
400 loaded_value = param.get_value<T>();
403 catch (
const rclcpp::exceptions::InvalidParameterTypeException& e)
405 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"Could not get param '" << resolved_name <<
"' from ROS: " << e.what());
412 m_node->undeclare_parameter(resolved_name.str);
415 if (!loaded_value.has_value())
421 auto declare_opts_local = opts.declare_options;
422 declare_opts_local.default_value = value_out;
423 if (!declareParam<T>(resolved_name, declare_opts_local))
425 RCLCPP_ERROR_STREAM(m_node->get_logger(),
"Failed to declare parameter \"" << resolved_name <<
"\".");
431 value_out = std::move(loaded_value.value());
441 struct hash<
mrs_lib::ParamProvider::resolved_name_t>
445 return std::hash<std::string>{}(r.str);
resolved_name_t resolveName(const std::string ¶m_name) const
Returns the parameter name with prefixes and subnode namespaces.
Definition param_provider.cpp:160
bool getParam(const std::string ¶m_name, T &value_out) const
Gets the value of a parameter.
Definition param_provider.hpp:83
bool declareParam(const std::string ¶m_name) const
Defines a parameter.
Definition param_provider.hpp:176
bool setParam(const std::string ¶m_name, const T &value) const
Sets the value of a parameter to ROS.
Definition param_provider.hpp:134
Convenience concept of a numeric value (i.e. either integral or floating point, and not bool).
Definition param_provider.h:58
All mrs_lib functions, classes, variables and definitions are contained in this namespace.
Definition attitude_converter.h:24
std::ostream & operator<<(std::ostream &os, const Eigen::MatrixX< T > &var)
Helper overload for printing of Eigen matrices.
Definition param_loader.hpp:21
rclcpp::ParameterType to_param_type()
Convenince function to get the corresponding rclcpp::ParamType from a C++ type.
Definition param_provider.hpp:75
Defines ParamProvider - a convenience class for seamlessly loading parameters from YAML or ROS.
Definition cyclic_example.cpp:23
Struct of options when declaring a parameter to ROS.
Definition param_provider.h:102
bool reconfigurable
If true, the parameter will be dynamically reconfigurable, otherwise it will be declared as read-only...
Definition param_provider.h:104
std::optional< T > default_value
An optional default value to initialize the parameter with.
Definition param_provider.h:106
std::optional< range_t< T > > range
An optional range of valid values of the parameter (only for numerical types).
Definition param_provider.h:108
Struct of options when getting a parameter from ROS.
Definition param_provider.h:118
declare_options_t< T > declare_options
Options when declaring a parameter to ROS (see the declare_options_t<T> documentation).
Definition param_provider.h:128
std::optional< bool > use_rosparam
Specifies whether the parameter should be attempted to be loaded from ROS if it cannot be loaded from...
Definition param_provider.h:124
bool always_declare
Iff true, the parameter will be declared to ROS even if it's value was loaded from a YAML.
Definition param_provider.h:120
bool use_yaml
Iff false, loading from YAML will be skipped even if some YAML files were specified.
Definition param_provider.h:122
Helper struct for a numeric range with named members to make the code a bit more readable.
Definition param_provider.h:87
T maximum
Maximal value of a parameter.
Definition param_provider.h:91
T minimum
Minimal value of a parameter.
Definition param_provider.h:89
Definition param_provider.hpp:43
Struct of options when setting a parameter to ROS.
Definition param_provider.h:138
declare_options_t< T > declare_options
Options when declaring a parameter to ROS (see the declare_options_t<T> documentation).
Definition param_provider.h:142