Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
parameters_handler.hpp
1 // Copyright (c) 2022 Samsung Research America, @artofnothingness Alexey Budyakov
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef NAV2_MPPI_CONTROLLER__TOOLS__PARAMETERS_HANDLER_HPP_
16 #define NAV2_MPPI_CONTROLLER__TOOLS__PARAMETERS_HANDLER_HPP_
17 
18 #include <functional>
19 #include <string>
20 #include <type_traits>
21 #include <unordered_map>
22 #include <utility>
23 #include <vector>
24 
25 #include "nav2_ros_common/lifecycle_node.hpp"
26 #include "nav2_ros_common/node_utils.hpp"
27 #include "rclcpp/logger.hpp"
28 #include "rclcpp/logging.hpp"
29 #include "rclcpp/node_interfaces/node_parameters_interface.hpp"
30 #include "rclcpp/parameter.hpp"
31 #include "rclcpp/parameter_value.hpp"
32 #include "rclcpp_lifecycle/lifecycle_node.hpp"
33 
34 namespace mppi
35 {
39 enum class ParameterType { Dynamic, Static };
40 
46 {
47 public:
48  using get_param_func_t = void (const rclcpp::Parameter & param,
49  rcl_interfaces::msg::SetParametersResult & result);
50  using post_callback_t = void ();
51  using pre_callback_t = void ();
55  ParametersHandler() = default;
56 
61  explicit ParametersHandler(
62  const nav2::LifecycleNode::WeakPtr & parent, std::string & name);
63 
68 
72  void start();
73 
82  rcl_interfaces::msg::SetParametersResult validateParameterUpdatesCallback(
83  const std::vector<rclcpp::Parameter> & parameters);
84 
91  void updateParametersCallback(const std::vector<rclcpp::Parameter> & parameters);
92 
98  inline auto getParamGetter(const std::string & ns);
99 
104  template<typename T>
105  void addPostCallback(T && callback);
106 
111  template<typename T>
112  void addPreCallback(const std::string & name, T && callback);
113 
120  template<typename T>
121  void setParamCallback(
122  T & setting, const std::string & name, ParameterType param_type = ParameterType::Dynamic);
123 
128  std::mutex * getLock()
129  {
130  return &parameters_change_mutex_;
131  }
132 
146  template<typename T>
147  void addParamCallback(const std::string & name, T && callback);
148 
149 protected:
157  template<typename SettingT, typename ParamT>
158  void getParam(
159  SettingT & setting, const std::string & name, ParamT default_value,
160  ParameterType param_type = ParameterType::Dynamic);
161 
168  template<typename ParamT, typename SettingT>
169  void setParam(
170  SettingT & setting,
171  const std::string & name,
172  nav2::LifecycleNode::SharedPtr node) const;
173 
179  template<typename T>
180  static auto as(const rclcpp::Parameter & parameter);
181 
182  std::mutex parameters_change_mutex_;
183  rclcpp::Logger logger_{rclcpp::get_logger("MPPIController")};
184  rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr
185  on_set_param_handler_;
186  rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtr
187  post_set_param_handler_;
188  nav2::LifecycleNode::WeakPtr node_;
189  std::string node_name_;
190  std::string name_;
191 
192  bool verbose_{false};
193 
194  std::unordered_map<std::string,
195  std::function<void(const rclcpp::Parameter &)>> get_param_callbacks_;
196  std::unordered_map<std::string, std::function<get_param_func_t>> get_pre_callbacks_;
197 
198  std::vector<std::function<post_callback_t>> post_callbacks_;
199 };
200 
201 inline auto ParametersHandler::getParamGetter(const std::string & ns)
202 {
203  return [this, ns](
204  auto & setting, const std::string & name, auto default_value,
205  ParameterType param_type = ParameterType::Dynamic) {
206  getParam(
207  setting, ns.empty() ? name : ns + "." + name,
208  std::move(default_value), param_type);
209  };
210 }
211 
212 template<typename T>
213 void ParametersHandler::addParamCallback(const std::string & name, T && callback)
214 {
215  get_param_callbacks_[name] = callback;
216 }
217 
218 template<typename T>
220 {
221  post_callbacks_.push_back(callback);
222 }
223 
224 template<typename T>
225 void ParametersHandler::addPreCallback(const std::string & name, T && callback)
226 {
227  get_pre_callbacks_[name] = callback;
228 }
229 
230 template<typename SettingT, typename ParamT>
232  SettingT & setting, const std::string & name,
233  ParamT default_value,
234  ParameterType param_type)
235 {
236  auto node = node_.lock();
237 
238  nav2::declare_parameter_if_not_declared(
239  node, name, rclcpp::ParameterValue(default_value));
240 
241  setParam<ParamT>(setting, name, node);
242  setParamCallback(setting, name, param_type);
243 }
244 
245 template<typename ParamT, typename SettingT>
247  SettingT & setting, const std::string & name, nav2::LifecycleNode::SharedPtr node) const
248 {
249  ParamT param_in{};
250  node->get_parameter(name, param_in);
251  setting = static_cast<SettingT>(param_in);
252 }
253 
254 template<typename T>
256  T & setting, const std::string & name, ParameterType param_type)
257 {
258  if (get_param_callbacks_.find(name) != get_param_callbacks_.end()) {
259  return;
260  }
261 
262  auto dynamic_callback =
263  [this, &setting, name](
264  const rclcpp::Parameter & param) {
265  setting = as<T>(param);
266  if (verbose_) {
267  RCLCPP_INFO(logger_, "Dynamic parameter changed: %s", std::to_string(param).c_str());
268  }
269  };
270 
271  auto static_callback =
272  [name](
273  const rclcpp::Parameter & param, rcl_interfaces::msg::SetParametersResult & result) {
274  std::string reason = "Rejected change to static parameter: " + std::to_string(param);
275  result.successful = false;
276  if (!result.reason.empty()) {
277  result.reason += "\n";
278  }
279  result.reason += reason;
280  };
281 
282  if (param_type == ParameterType::Dynamic) {
283  addParamCallback(name, dynamic_callback);
284  } else {
285  addPreCallback(name, static_callback);
286  }
287 }
288 
289 template<typename T>
290 auto ParametersHandler::as(const rclcpp::Parameter & parameter)
291 {
292  if constexpr (std::is_same_v<T, bool>) {
293  return parameter.as_bool();
294  } else if constexpr (std::is_integral_v<T>) {
295  return parameter.as_int();
296  } else if constexpr (std::is_floating_point_v<T>) {
297  return parameter.as_double();
298  } else if constexpr (std::is_same_v<T, std::string>) {
299  return parameter.as_string();
300  } else if constexpr (std::is_same_v<T, std::vector<int64_t>>) {
301  return parameter.as_integer_array();
302  } else if constexpr (std::is_same_v<T, std::vector<double>>) {
303  return parameter.as_double_array();
304  } else if constexpr (std::is_same_v<T, std::vector<std::string>>) {
305  return parameter.as_string_array();
306  } else if constexpr (std::is_same_v<T, std::vector<bool>>) {
307  return parameter.as_bool_array();
308  }
309 }
310 
311 } // namespace mppi
312 
313 #endif // NAV2_MPPI_CONTROLLER__TOOLS__PARAMETERS_HANDLER_HPP_
Handles getting parameters and dynamic parameter changes.
void setParamCallback(T &setting, const std::string &name, ParameterType param_type=ParameterType::Dynamic)
Set a parameter to a dynamic parameter callback.
rcl_interfaces::msg::SetParametersResult validateParameterUpdatesCallback(const std::vector< rclcpp::Parameter > &parameters)
Validate incoming parameter updates before applying them. This callback is triggered when one or more...
void getParam(SettingT &setting, const std::string &name, ParamT default_value, ParameterType param_type=ParameterType::Dynamic)
Gets parameter.
void setParam(SettingT &setting, const std::string &name, nav2::LifecycleNode::SharedPtr node) const
Set a parameter.
void addPostCallback(T &&callback)
Set a callback to process after parameter changes.
void addPreCallback(const std::string &name, T &&callback)
Set a callback to process before parameter changes.
auto getParamGetter(const std::string &ns)
Get an object to retrieve parameters.
std::mutex * getLock()
Get mutex lock for changing parameters.
static auto as(const rclcpp::Parameter &parameter)
Converts parameter type to real types.
void start()
Starts processing dynamic parameter changes.
void updateParametersCallback(const std::vector< rclcpp::Parameter > &parameters)
Apply parameter updates after validation This callback is executed when parameters have been successf...
ParametersHandler()=default
Constructor for mppi::ParametersHandler.
~ParametersHandler()
Destructor for mppi::ParametersHandler.
void addParamCallback(const std::string &name, T &&callback)
register a function to be called when setting a parameter