ROS 2 rclcpp + rcl - rolling  rolling-29de98cf
ROS 2 C++ Client Library with ROS Client Library
node_impl.hpp
1 // Copyright 2014 Open Source Robotics Foundation, Inc.
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 RCLCPP__NODE_IMPL_HPP_
16 #define RCLCPP__NODE_IMPL_HPP_
17 
18 #include <algorithm>
19 #include <chrono>
20 #include <map>
21 #include <memory>
22 #include <stdexcept>
23 #include <string>
24 #include <utility>
25 #include <vector>
26 
27 #include "rcl/publisher.h"
28 #include "rcl/subscription.h"
29 
30 #include "rclcpp/contexts/default_context.hpp"
31 #include "rclcpp/create_client.hpp"
32 #include "rclcpp/create_generic_publisher.hpp"
33 #include "rclcpp/create_generic_subscription.hpp"
34 #include "rclcpp/create_publisher.hpp"
35 #include "rclcpp/create_service.hpp"
36 #include "rclcpp/create_generic_service.hpp"
37 #include "rclcpp/create_subscription.hpp"
38 #include "rclcpp/create_timer.hpp"
39 #include "rclcpp/detail/resolve_enable_topic_statistics.hpp"
40 #include "rclcpp/parameter.hpp"
41 #include "rclcpp/qos.hpp"
42 #include "rclcpp/timer.hpp"
43 #include "rclcpp/type_support_decl.hpp"
44 #include "rclcpp/visibility_control.hpp"
45 
46 #ifndef RCLCPP__NODE_HPP_
47 #include "node.hpp"
48 #endif
49 
50 namespace rclcpp
51 {
52 
53 RCLCPP_LOCAL
54 inline
55 std::string
56 extend_name_with_sub_namespace(const std::string & name, const std::string & sub_namespace)
57 {
58  std::string name_with_sub_namespace(name);
59  if (sub_namespace != "" && name.front() != '/' && name.front() != '~') {
60  name_with_sub_namespace = sub_namespace + "/" + name;
61  }
62  return name_with_sub_namespace;
63 }
64 
65 template<typename MessageT, typename AllocatorT, typename PublisherT>
66 std::shared_ptr<PublisherT>
68  const std::string & topic_name,
69  const rclcpp::QoS & qos,
71 {
72  return rclcpp::create_publisher<MessageT, AllocatorT, PublisherT>(
73  *this,
74  extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
75  qos,
76  options);
77 }
78 
79 template<
80  typename MessageT,
81  typename CallbackT,
82  typename AllocatorT,
83  typename SubscriptionT,
84  typename MessageMemoryStrategyT>
85 std::shared_ptr<SubscriptionT>
87  const std::string & topic_name,
88  const rclcpp::QoS & qos,
89  CallbackT && callback,
91  typename MessageMemoryStrategyT::SharedPtr msg_mem_strat)
92 {
93  return rclcpp::create_subscription<MessageT>(
94  *this,
95  extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
96  qos,
97  std::forward<CallbackT>(callback),
98  options,
99  msg_mem_strat);
100 }
101 
102 template<typename DurationRepT, typename DurationT, typename CallbackT>
105  std::chrono::duration<DurationRepT, DurationT> period,
106  CallbackT callback,
107  const rclcpp::CallbackGroup::SharedPtr & group,
108  bool autostart)
109 {
111  period,
112  std::move(callback),
113  group,
114  this->node_base_.get(),
115  this->node_timers_.get(),
116  autostart);
117 }
118 
119 template<typename DurationRepT, typename DurationT, typename CallbackT>
122  std::chrono::duration<DurationRepT, DurationT> period,
123  CallbackT callback,
124  const rclcpp::CallbackGroup::SharedPtr & group)
125 {
126  return rclcpp::create_timer(
127  this->get_clock(),
128  period,
129  std::move(callback),
130  group,
131  this->node_base_.get(),
132  this->node_timers_.get());
133 }
134 
135 template<typename ServiceT>
138  const std::string & service_name,
139  const rclcpp::QoS & qos,
140  const rclcpp::CallbackGroup::SharedPtr & group)
141 {
142  return rclcpp::create_client<ServiceT>(
143  node_base_,
144  node_graph_,
145  node_services_,
146  extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
147  qos,
148  group);
149 }
150 
151 template<typename ServiceT, typename CallbackT>
154  const std::string & service_name,
155  CallbackT && callback,
156  const rclcpp::QoS & qos,
157  const rclcpp::CallbackGroup::SharedPtr & group)
158 {
159  return rclcpp::create_service<ServiceT, CallbackT>(
160  node_base_,
161  node_services_,
162  extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
163  std::forward<CallbackT>(callback),
164  qos,
165  group);
166 }
167 
168 template<typename CallbackT>
169 typename rclcpp::GenericService::SharedPtr
171  const std::string & service_name,
172  const std::string & service_type,
173  CallbackT && callback,
174  const rclcpp::QoS & qos,
175  const rclcpp::CallbackGroup::SharedPtr & group)
176 {
177  return rclcpp::create_generic_service<CallbackT>(
178  node_base_,
179  node_services_,
180  extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
181  service_type,
182  std::forward<CallbackT>(callback),
183  qos,
184  group);
185 }
186 
187 template<typename AllocatorT>
188 std::shared_ptr<rclcpp::GenericPublisher>
190  const std::string & topic_name,
191  const std::string & topic_type,
192  const rclcpp::QoS & qos,
194 {
196  node_topics_,
197  extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
198  topic_type,
199  qos,
200  options
201  );
202 }
203 
204 template<typename CallbackT, typename AllocatorT>
205 std::shared_ptr<rclcpp::GenericSubscription>
207  const std::string & topic_name,
208  const std::string & topic_type,
209  const rclcpp::QoS & qos,
210  CallbackT && callback,
212 {
214  node_topics_,
215  extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
216  topic_type,
217  qos,
218  std::forward<CallbackT>(callback),
219  options
220  );
221 }
222 
223 
224 template<typename ParameterT>
225 auto
227  const std::string & name,
228  const ParameterT & default_value,
229  const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
230  bool ignore_override)
231 {
232  try {
233  return this->declare_parameter(
234  name,
235  rclcpp::ParameterValue(default_value),
236  parameter_descriptor,
237  ignore_override
238  ).get<ParameterT>();
239  } catch (const ParameterTypeException & ex) {
240  throw exceptions::InvalidParameterTypeException(name, ex.what());
241  }
242 }
243 
244 template<typename ParameterT>
245 auto
247  const std::string & name,
248  const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
249  bool ignore_override)
250 {
251  // get advantage of parameter value template magic to get
252  // the correct rclcpp::ParameterType from ParameterT
253  rclcpp::ParameterValue value{ParameterT{}};
254  try {
255  return this->declare_parameter(
256  name,
257  value.get_type(),
258  parameter_descriptor,
259  ignore_override
260  ).get<ParameterT>();
261  } catch (const ParameterTypeException &) {
263  }
264 }
265 
266 template<typename ParameterT>
267 std::vector<ParameterT>
269  const std::string & namespace_,
270  const std::map<std::string, ParameterT> & parameters,
271  bool ignore_overrides)
272 {
273  std::vector<ParameterT> result;
274  std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
275  std::transform(
276  parameters.begin(), parameters.end(), std::back_inserter(result),
277  [this, &normalized_namespace, ignore_overrides](auto element) {
278  return this->declare_parameter(
279  normalized_namespace + element.first,
280  element.second,
281  rcl_interfaces::msg::ParameterDescriptor(),
282  ignore_overrides);
283  }
284  );
285  return result;
286 }
287 
288 template<typename ParameterT>
289 std::vector<ParameterT>
291  const std::string & namespace_,
292  const std::map<
293  std::string,
294  std::pair<ParameterT, rcl_interfaces::msg::ParameterDescriptor>
295  > & parameters,
296  bool ignore_overrides)
297 {
298  std::vector<ParameterT> result;
299  std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
300  std::transform(
301  parameters.begin(), parameters.end(), std::back_inserter(result),
302  [this, &normalized_namespace, ignore_overrides](auto element) {
303  return static_cast<ParameterT>(
304  this->declare_parameter(
305  normalized_namespace + element.first,
306  element.second.first,
307  element.second.second,
308  ignore_overrides)
309  );
310  }
311  );
312  return result;
313 }
314 
315 template<typename ParameterT>
316 bool
317 Node::get_parameter(const std::string & name, ParameterT & parameter) const
318 {
319  rclcpp::Parameter parameter_variant;
320 
321  bool result = get_parameter(name, parameter_variant);
322  if (result) {
323  parameter = static_cast<ParameterT>(parameter_variant.get_value<ParameterT>());
324  }
325 
326  return result;
327 }
328 
329 template<typename ParameterT>
330 bool
332  const std::string & name,
333  ParameterT & parameter,
334  const ParameterT & alternative_value) const
335 {
336  bool got_parameter = get_parameter(name, parameter);
337  if (!got_parameter) {
338  parameter = alternative_value;
339  }
340  return got_parameter;
341 }
342 
343 template<typename ParameterT>
344 ParameterT
346  const std::string & name,
347  const ParameterT & alternative_value) const
348 {
349  ParameterT parameter;
350  get_parameter_or(name, parameter, alternative_value);
351  return parameter;
352 }
353 
354 // this is a partially-specialized version of get_parameter above,
355 // where our concrete type for ParameterT is std::map, but the to-be-determined
356 // type is the value in the map.
357 template<typename ParameterT>
358 bool
360  const std::string & prefix,
361  std::map<std::string, ParameterT> & values) const
362 {
363  std::map<std::string, rclcpp::Parameter> params;
364  bool result = node_parameters_->get_parameters_by_prefix(prefix, params);
365  if (result) {
366  for (const auto & param : params) {
367  values[param.first] = static_cast<ParameterT>(param.second.get_value<ParameterT>());
368  }
369  }
370 
371  return result;
372 }
373 
374 } // namespace rclcpp
375 
376 #endif // RCLCPP__NODE_IMPL_HPP_
Generic timer. Periodically executes a user-specified callback.
Definition: timer.hpp:227
RCLCPP_PUBLIC std::vector< rclcpp::Parameter > get_parameters(const std::vector< std::string > &names) const
Return the parameters by the given parameter names.
Definition: node.cpp:416
RCLCPP_PUBLIC rclcpp::Clock::SharedPtr get_clock()
Get a clock as a non-const shared pointer which is managed by the node.
Definition: node.cpp:586
rclcpp::GenericService::SharedPtr create_generic_service(const std::string &service_name, const std::string &service_type, CallbackT &&callback, const rclcpp::QoS &qos=rclcpp::ServicesQoS(), const rclcpp::CallbackGroup::SharedPtr &group=nullptr)
Create and return a GenericService.
Definition: node_impl.hpp:170
RCLCPP_PUBLIC const rclcpp::ParameterValue & declare_parameter(const std::string &name, const rclcpp::ParameterValue &default_value, const rcl_interfaces::msg::ParameterDescriptor &parameter_descriptor=rcl_interfaces::msg::ParameterDescriptor(), bool ignore_override=false)
Declare and initialize a parameter, return the effective value.
Definition: node.cpp:346
bool get_parameter_or(const std::string &name, ParameterT &parameter, const ParameterT &alternative_value) const
Get the parameter value, or the "alternative_value" if not set, and assign it to "parameter".
Definition: node_impl.hpp:331
std::vector< ParameterT > declare_parameters(const std::string &namespace_, const std::map< std::string, ParameterT > &parameters, bool ignore_overrides=false)
Declare and initialize several parameters with the same namespace and type.
Definition: node_impl.hpp:268
RCLCPP_PUBLIC rclcpp::Parameter get_parameter(const std::string &name) const
Return the parameter by the given name.
Definition: node.cpp:404
rclcpp::GenericTimer< CallbackT >::SharedPtr create_timer(std::chrono::duration< DurationRepT, DurationT > period, CallbackT callback, const rclcpp::CallbackGroup::SharedPtr &group=nullptr)
Create a timer that uses the node clock to drive the callback.
Definition: node_impl.hpp:121
std::shared_ptr< rclcpp::GenericSubscription > create_generic_subscription(const std::string &topic_name, const std::string &topic_type, const rclcpp::QoS &qos, CallbackT &&callback, const rclcpp::SubscriptionOptionsWithAllocator< AllocatorT > &options=(rclcpp::SubscriptionOptionsWithAllocator< AllocatorT >()))
Create and return a GenericSubscription.
Definition: node_impl.hpp:206
std::shared_ptr< SubscriptionT > create_subscription(const std::string &topic_name, const rclcpp::QoS &qos, CallbackT &&callback, const SubscriptionOptionsWithAllocator< AllocatorT > &options=SubscriptionOptionsWithAllocator< AllocatorT >(), typename MessageMemoryStrategyT::SharedPtr msg_mem_strat=(MessageMemoryStrategyT::create_default()))
Create and return a Subscription.
Definition: node_impl.hpp:86
std::shared_ptr< PublisherT > create_publisher(const std::string &topic_name, const rclcpp::QoS &qos, const PublisherOptionsWithAllocator< AllocatorT > &options=PublisherOptionsWithAllocator< AllocatorT >())
Create and return a Publisher.
Definition: node_impl.hpp:67
rclcpp::WallTimer< CallbackT >::SharedPtr create_wall_timer(std::chrono::duration< DurationRepT, DurationT > period, CallbackT callback, const rclcpp::CallbackGroup::SharedPtr &group=nullptr, bool autostart=true)
Create a wall timer that uses the wall clock to drive the callback.
Definition: node_impl.hpp:104
RCLCPP_PUBLIC const std::string & get_sub_namespace() const
Return the sub-namespace, if this is a sub-node, otherwise an empty string.
Definition: node.cpp:670
rclcpp::Client< ServiceT >::SharedPtr create_client(const std::string &service_name, const rclcpp::QoS &qos=rclcpp::ServicesQoS(), const rclcpp::CallbackGroup::SharedPtr &group=nullptr)
Create and return a Client.
std::shared_ptr< rclcpp::GenericPublisher > create_generic_publisher(const std::string &topic_name, const std::string &topic_type, const rclcpp::QoS &qos, const rclcpp::PublisherOptionsWithAllocator< AllocatorT > &options=(rclcpp::PublisherOptionsWithAllocator< AllocatorT >()))
Create and return a GenericPublisher.
Definition: node_impl.hpp:189
rclcpp::Service< ServiceT >::SharedPtr create_service(const std::string &service_name, CallbackT &&callback, const rclcpp::QoS &qos=rclcpp::ServicesQoS(), const rclcpp::CallbackGroup::SharedPtr &group=nullptr)
Create and return a Service.
Definition: node_impl.hpp:153
Indicate the parameter type does not match the expected type.
Store the type and value of a parameter.
Structure to store an arbitrary parameter with templated get/set methods.
Definition: parameter.hpp:53
decltype(auto) get_value() const
Get value of parameter using rclcpp::ParameterType as template argument.
Definition: parameter.hpp:117
Encapsulation of Quality of Service settings.
Definition: qos.hpp:114
Thrown if requested parameter type is invalid.
Definition: exceptions.hpp:271
Thrown if user attempts to create an uninitialized statically typed parameter.
Definition: exceptions.hpp:289
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
rclcpp::TimerBase::SharedPtr create_timer(std::shared_ptr< node_interfaces::NodeBaseInterface > node_base, std::shared_ptr< node_interfaces::NodeTimersInterface > node_timers, rclcpp::Clock::SharedPtr clock, rclcpp::Duration period, CallbackT &&callback, rclcpp::CallbackGroup::SharedPtr group=nullptr, bool autostart=true)
rclcpp::WallTimer< CallbackT >::SharedPtr create_wall_timer(std::chrono::duration< DurationRepT, DurationT > period, CallbackT callback, rclcpp::CallbackGroup::SharedPtr group, node_interfaces::NodeBaseInterface *node_base, node_interfaces::NodeTimersInterface *node_timers, bool autostart=true)
Convenience method to create a wall timer with node resources.
std::shared_ptr< GenericPublisher > create_generic_publisher(rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr topics_interface, const std::string &topic_name, const std::string &topic_type, const rclcpp::QoS &qos, const rclcpp::PublisherOptionsWithAllocator< AllocatorT > &options=(rclcpp::PublisherOptionsWithAllocator< AllocatorT >()))
Create and return a GenericPublisher.
std::shared_ptr< GenericSubscription > create_generic_subscription(rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr topics_interface, const std::string &topic_name, const std::string &topic_type, const rclcpp::QoS &qos, CallbackT &&callback, const rclcpp::SubscriptionOptionsWithAllocator< AllocatorT > &options=(rclcpp::SubscriptionOptionsWithAllocator< AllocatorT >()))
Create and return a GenericSubscription.
Structure containing optional configuration for Publishers.
Structure containing optional configuration for Subscriptions.