Nav2 Navigation Stack - kilted  kilted
ROS 2 Navigation Stack
node_utils.hpp
1 // Copyright (c) 2019 Intel Corporation
2 // Copyright (c) 2023 Open Navigation LLC
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #ifndef NAV2_UTIL__NODE_UTILS_HPP_
17 #define NAV2_UTIL__NODE_UTILS_HPP_
18 
19 #include <vector>
20 #include <string>
21 #include "rclcpp/rclcpp.hpp"
22 #include "rcl_interfaces/srv/list_parameters.hpp"
23 #include "pluginlib/exceptions.hpp"
24 
25 namespace nav2_util
26 {
27 
29 
38 std::string sanitize_node_name(const std::string & potential_node_name);
39 
41 
46 std::string add_namespaces(const std::string & top_ns, const std::string & sub_ns = "");
47 
49 
59 std::string generate_internal_node_name(const std::string & prefix = "");
60 
62 
71 rclcpp::Node::SharedPtr generate_internal_node(const std::string & prefix = "");
72 
74 
82 std::string time_to_string(size_t len);
83 
84 using ParameterDescriptor = rcl_interfaces::msg::ParameterDescriptor;
85 
87 /* Declares static ROS2 parameter and sets it to a given value
88  * if it was not already declared.
89  *
90  * \param[in] node A node in which given parameter to be declared
91  * \param[in] parameter_name The name of parameter
92  * \param[in] default_value Parameter value to initialize with
93  * \param[in] parameter_descriptor Parameter descriptor (optional)
94  */
95 template<typename NodeT>
96 void declare_parameter_if_not_declared(
97  NodeT node,
98  const std::string & parameter_name,
99  const rclcpp::ParameterValue & default_value,
100  const ParameterDescriptor & parameter_descriptor = ParameterDescriptor())
101 {
102  if (!node->has_parameter(parameter_name)) {
103  node->declare_parameter(parameter_name, default_value, parameter_descriptor);
104  }
105 }
106 
108 /* Declares static ROS2 parameter with given type if it was not already declared.
109  *
110  * \param[in] node A node in which given parameter to be declared
111  * \param[in] parameter_name Name of the parameter
112  * \param[in] param_type The type of parameter
113  * \param[in] parameter_descriptor Parameter descriptor (optional)
114  */
115 template<typename NodeT>
116 void declare_parameter_if_not_declared(
117  NodeT node,
118  const std::string & parameter_name,
119  const rclcpp::ParameterType & param_type,
120  const ParameterDescriptor & parameter_descriptor = ParameterDescriptor())
121 {
122  if (!node->has_parameter(parameter_name)) {
123  node->declare_parameter(parameter_name, param_type, parameter_descriptor);
124  }
125 }
126 
129 /* Declares a parameter with the specified type if it was not already declared.
130  * If the parameter was overridden, its value is returned, otherwise an
131  * rclcpp::exceptions::InvalidParameterValueException is thrown
132  *
133  * \param[in] node A node in which given parameter to be declared
134  * \param[in] parameter_name Name of the parameter
135  * \param[in] param_type The type of parameter
136  * \param[in] parameter_descriptor Parameter descriptor (optional)
137  * \return The value of the parameter or an exception
138  */
139 template<typename ParameterT, typename NodeT>
140 ParameterT declare_or_get_parameter(
141  NodeT node,
142  const std::string & parameter_name,
143  const rclcpp::ParameterType & param_type,
144  const ParameterDescriptor & parameter_descriptor = ParameterDescriptor())
145 {
146  if (node->has_parameter(parameter_name)) {
147  return node->get_parameter(parameter_name).template get_value<ParameterT>();
148  }
149  auto parameter = node->declare_parameter(parameter_name, param_type, parameter_descriptor);
150  if (parameter.get_type() == rclcpp::ParameterType::PARAMETER_NOT_SET) {
151  std::string description = "Parameter " + parameter_name + " not in overrides";
152  throw rclcpp::exceptions::InvalidParameterValueException(description.c_str());
153  }
154  return parameter.template get<ParameterT>();
155 }
156 
157 using NodeParamInterfacePtr = rclcpp::node_interfaces::NodeParametersInterface::SharedPtr;
158 
161 
175 template<typename ParamType>
176 ParamType declare_or_get_parameter(
177  const rclcpp::Logger & logger, NodeParamInterfacePtr param_interface,
178  const std::string & parameter_name, const ParamType & default_value,
179  bool warn_if_no_override = false, bool strict_param_loading = false,
180  const ParameterDescriptor & parameter_descriptor = ParameterDescriptor())
181 {
182  if (param_interface->has_parameter(parameter_name)) {
183  rclcpp::Parameter param(parameter_name, default_value);
184  param_interface->get_parameter(parameter_name, param);
185  return param.get_value<ParamType>();
186  }
187 
188  auto return_value = param_interface
189  ->declare_parameter(parameter_name, rclcpp::ParameterValue{default_value},
190  parameter_descriptor)
191  .get<ParamType>();
192 
193  const bool no_param_override = param_interface->get_parameter_overrides().find(parameter_name) ==
194  param_interface->get_parameter_overrides().end();
195  if (no_param_override) {
196  if (warn_if_no_override) {
197  RCLCPP_WARN_STREAM(
198  logger,
199  "Failed to get param " << parameter_name << " from overrides, using default value.");
200  }
201  if (strict_param_loading) {
202  std::string description = "Parameter " + parameter_name +
203  " not in overrides and strict_param_loading is True";
204  throw rclcpp::exceptions::InvalidParameterValueException(description.c_str());
205  }
206  }
207 
208  return return_value;
209 }
210 
213 
226 template<typename ParamType, typename NodeT>
227 ParamType declare_or_get_parameter(
228  NodeT node, const std::string & parameter_name,
229  const ParamType & default_value,
230  const ParameterDescriptor & parameter_descriptor = ParameterDescriptor())
231 {
232  declare_parameter_if_not_declared(node, "warn_on_missing_params", rclcpp::ParameterValue(false));
233  bool warn_if_no_override{false};
234  node->get_parameter("warn_on_missing_params", warn_if_no_override);
235  declare_parameter_if_not_declared(node, "strict_param_loading", rclcpp::ParameterValue(false));
236  bool strict_param_loading{false};
237  node->get_parameter("strict_param_loading", strict_param_loading);
238  return declare_or_get_parameter(node->get_logger(), node->get_node_parameters_interface(),
239  parameter_name, default_value, warn_if_no_override, strict_param_loading, parameter_descriptor);
240 }
241 
243 
251 template<typename NodeT>
252 std::string get_plugin_type_param(
253  NodeT node,
254  const std::string & plugin_name)
255 {
256  declare_parameter_if_not_declared(node, plugin_name + ".plugin", rclcpp::PARAMETER_STRING);
257  std::string plugin_type;
258  try {
259  if (!node->get_parameter(plugin_name + ".plugin", plugin_type)) {
260  RCLCPP_FATAL(
261  node->get_logger(), "Can not get 'plugin' param value for %s", plugin_name.c_str());
262  throw pluginlib::PluginlibException("No 'plugin' param for param ns!");
263  }
264  } catch (rclcpp::exceptions::ParameterUninitializedException & ex) {
265  RCLCPP_FATAL(node->get_logger(), "'plugin' param not defined for %s", plugin_name.c_str());
266  throw pluginlib::PluginlibException("No 'plugin' param for param ns!");
267  }
268 
269  return plugin_type;
270 }
271 
277 void setSoftRealTimePriority();
278 
279 } // namespace nav2_util
280 
281 #endif // NAV2_UTIL__NODE_UTILS_HPP_