mrs_lib
Various reusable classes, functions and utilities for use in MRS projects
Loading...
Searching...
No Matches
dynparam_mgr.hpp
Go to the documentation of this file.
1// clang: MatousFormat
6#pragma once
7
9#include <any>
10
11namespace mrs_lib
12{
13
14 /* register_param() method //{ */
15 template <typename MemT>
16 bool DynparamMgr::register_param(const std::string& name, MemT* param_var, const update_cbk_t<MemT>& update_cbk)
17 {
18 return register_param_impl<MemT>(name, param_var, std::nullopt, std::nullopt, update_cbk);
19 }
20
21 template <typename MemT>
22 bool DynparamMgr::register_param(const std::string& name, MemT* param_var, const MemT& default_value, const update_cbk_t<MemT>& update_cbk)
23 {
24 return register_param_impl<MemT>(name, param_var, default_value, std::nullopt, update_cbk);
25 }
26
27 template <typename MemT>
28 bool DynparamMgr::register_param(const std::string& name, MemT* param_var, const range_t<MemT>& valid_range, const update_cbk_t<MemT>& update_cbk)
29 requires(numeric<MemT>)
30 {
31 return register_param_impl<MemT>(name, param_var, std::nullopt, valid_range, update_cbk);
32 }
33
34 template <typename MemT>
35 bool DynparamMgr::register_param(const std::string& name, MemT* param_var, const MemT& default_value, const range_t<MemT>& valid_range, const update_cbk_t<MemT>& update_cbk)
36 requires(numeric<MemT>)
37 {
38 return register_param_impl<MemT>(name, param_var, default_value, valid_range, update_cbk);
39 }
40
41 template <typename MemT>
42 bool DynparamMgr::register_param_impl(const std::string& name, MemT* param_var, const std::optional<MemT>& default_value, const std::optional<range_t<MemT>>& valid_range, const update_cbk_t<MemT>& update_cbk)
43 {
44 const auto resolved_name = m_pp.resolveName(name);
45
47 opts.always_declare = true;
48 opts.declare_options.reconfigurable = true;
49 opts.declare_options.default_value = default_value;
50 opts.declare_options.range = valid_range;
51
52 // load the current value of the parameter
53 MemT current_value;
54 const bool get_success = m_pp.getParam(resolved_name, current_value, opts);
55 if (!get_success)
56 {
57 m_load_successful = false;
58 RCLCPP_ERROR_STREAM(m_node->get_logger(), "[" << m_node->get_name() << "]: Could not register dynamic parameter '" << name << "'");
59 return false;
60 }
61
62 // only assign the default value if everything is OK, otherwise leave param_var untouched
63 *param_var = current_value;
64
65 // remember the registered parameter, the corresponding variable, etc.
66 RCLCPP_INFO_STREAM(m_node->get_logger(), "[" << m_node->get_name() << "]: Dynamic parameter '" << name << "':\t" << *param_var);
67
68 m_registered_params.emplace_back(
69 *m_node,
70 resolved_name,
71 to_param_type<MemT>(),
72 param_var,
73 update_cbk
74 );
75 return true;
76 }
77 //}
78
79 /* registered_param_t struct //{ */
80
82 {
83 // | --------------------- Metaprogramming -------------------- |
84 // some metaprogramming tooling to generate a variant of pointers from a tuple of types
85 template <typename ... Types>
86 using variant_of_pointers_t = std::variant<std::add_pointer_t<Types>...>;
87
88 template <typename Type>
90
91 template <typename ... Types>
92 struct pointer_variant_from_list_t<std::tuple<Types...>>
93 {
94 using type = variant_of_pointers_t<Types...>;
95 };
96
97 // the same tooling for creating a variant of functions with the types as const-ref arguments
98 template <typename Type>
99 using add_function_cref_t = std::function<void(const Type&)>;
100
101 template <typename ... Types>
102 using variant_of_functions_t = std::variant<add_function_cref_t<Types>...>;
103
104 template <typename Type>
106
107 template <typename ... Types>
108 struct function_variant_from_list_t<std::tuple<Types...>>
109 {
110 using type = variant_of_functions_t<Types...>;
111 };
112
113 // define the std::variant of pointers-to the types from valid_types_t
114 using param_ptr_variant_t = pointer_variant_from_list_t<valid_types_t>::type;
115
116 // define the std::variant of std::functions taking a const-ref of the types from valid_types_t
117 using update_cbk_variant_t = function_variant_from_list_t<valid_types_t>::type;
118
119 // | ------------------------- Members ------------------------ |
120 rclcpp::Node& node; // non-owning reference (the memory is share-owned by the DynparamMgr)
121 ParamProvider::resolved_name_t resolved_name;
122 rclcpp::ParameterType type;
123 param_ptr_variant_t param_ptr;
124 update_cbk_variant_t update_cbk;
125
126 // | ------------------------- Methods ------------------------ |
127 template <typename T>
128 bool try_cast(T& out)
129 {
130 try
131 {
132 out = std::get<T>(param_ptr);
133 return true;
134 }
135 catch (const std::bad_any_cast& e)
136 {
137 return false;
138 }
139 }
140
141 template <typename NewValueT>
142 bool update_value(const NewValueT& new_value)
143 {
144 // if there is an update callback registered, try to call it
145 std::visit([&new_value, this](auto arg)
146 {
147 using CbkT = decltype(arg);
148 if constexpr (std::is_invocable_v<CbkT, NewValueT>)
149 {
150 if (arg)
151 // actually call the callback
152 arg(new_value);
153 }
154 else
155 {
156 RCLCPP_ERROR_STREAM_THROTTLE(node.get_logger(), *node.get_clock(), 1000, "Cannot call update callback for parameter \"" << resolved_name.str << "\" - incompatible callback type!");
157 }
158 }, update_cbk);
159
160 return std::visit([&new_value](auto arg)
161 {
162 using ParamT = std::remove_pointer_t<decltype(arg)>;
163 if constexpr (std::is_convertible_v<NewValueT, ParamT>)
164 {
165 *arg = static_cast<ParamT>(new_value);
166 return true;
167 }
168 else
169 return false;
170 }, param_ptr);
171 }
172
173 rclcpp::ParameterValue to_param_val() const;
174 };
175
176 //}
177
178};
std::function< void(const T &)> update_cbk_t
A convenience alias defining the update callback function type.
Definition dynparam_mgr.h:52
bool register_param(const std::string &name, MemT *param_var, const update_cbk_t< MemT > &update_cbk={})
Registers a ROS parameter and a corresponding variable.
Definition dynparam_mgr.hpp:16
resolved_name_t resolveName(const std::string &param_name) const
Returns the parameter name with prefixes and subnode namespaces.
Definition param_provider.cpp:148
bool getParam(const std::string &param_name, T &value_out) const
Gets the value of a parameter.
Definition param_provider.hpp:78
Convenience concept of a numeric value (i.e. either integral or floating point, and not bool).
Definition param_provider.h:58
Defines DynparamMgr - a convenience class for managing dynamic ROS parameters.
All mrs_lib functions, classes, variables and definitions are contained in this namespace.
Definition attitude_converter.h:24
Definition dynparam_mgr.hpp:82
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
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
Helper struct for a numeric range with named members to make the code a bit more readable.
Definition param_provider.h:87
Definition param_provider.hpp:42