ROS 2 rclcpp + rcl - rolling  rolling-e7363f10
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/parameter.hpp"
40 #include "rclcpp/qos.hpp"
41 #include "rclcpp/timer.hpp"
42 #include "rclcpp/type_support_decl.hpp"
43 #include "rclcpp/visibility_control.hpp"
44 
45 #ifndef RCLCPP__NODE_HPP_
46 #include "node.hpp"
47 #endif
48 
49 namespace rclcpp
50 {
51 
52 RCLCPP_LOCAL
53 inline
54 std::string
55 extend_name_with_sub_namespace(const std::string & name, const std::string & sub_namespace)
56 {
57  std::string name_with_sub_namespace(name);
58  if (sub_namespace != "" && name.front() != '/' && name.front() != '~') {
59  name_with_sub_namespace = sub_namespace + "/" + name;
60  }
61  return name_with_sub_namespace;
62 }
63 
64 template<typename MessageT, typename AllocatorT, typename PublisherT>
65 std::shared_ptr<PublisherT>
67  const std::string & topic_name,
68  const rclcpp::QoS & qos,
70 {
71  return rclcpp::create_publisher<MessageT, AllocatorT, PublisherT>(
72  *this,
73  extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
74  qos,
75  options);
76 }
77 
78 template<
79  typename MessageT,
80  typename CallbackT,
81  typename AllocatorT,
82  typename SubscriptionT,
83  typename MessageMemoryStrategyT>
84 std::shared_ptr<SubscriptionT>
86  const std::string & topic_name,
87  const rclcpp::QoS & qos,
88  CallbackT && callback,
90  typename MessageMemoryStrategyT::SharedPtr msg_mem_strat)
91 {
92  return rclcpp::create_subscription<MessageT>(
93  *this,
94  extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
95  qos,
96  std::forward<CallbackT>(callback),
97  options,
98  msg_mem_strat);
99 }
100 
101 template<typename DurationRepT, typename DurationT, typename CallbackT>
104  std::chrono::duration<DurationRepT, DurationT> period,
105  CallbackT callback,
106  const rclcpp::CallbackGroup::SharedPtr & group,
107  bool autostart)
108 {
110  period,
111  std::move(callback),
112  group,
113  this->node_base_.get(),
114  this->node_timers_.get(),
115  autostart);
116 }
117 
118 template<typename DurationRepT, typename DurationT, typename CallbackT>
121  std::chrono::duration<DurationRepT, DurationT> period,
122  CallbackT callback,
123  const rclcpp::CallbackGroup::SharedPtr & group)
124 {
125  return rclcpp::create_timer(
126  this->get_clock(),
127  period,
128  std::move(callback),
129  group,
130  this->node_base_.get(),
131  this->node_timers_.get());
132 }
133 
134 template<typename ServiceT>
137  const std::string & service_name,
138  const rclcpp::QoS & qos,
139  const rclcpp::CallbackGroup::SharedPtr & group)
140 {
141  return rclcpp::create_client<ServiceT>(
142  node_base_,
143  node_graph_,
144  node_services_,
145  extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
146  qos,
147  group);
148 }
149 
150 template<typename ServiceT, typename CallbackT>
153  const std::string & service_name,
154  CallbackT && callback,
155  const rclcpp::QoS & qos,
156  const rclcpp::CallbackGroup::SharedPtr & group)
157 {
158  return rclcpp::create_service<ServiceT, CallbackT>(
159  node_base_,
160  node_services_,
161  extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
162  std::forward<CallbackT>(callback),
163  qos,
164  group);
165 }
166 
167 template<typename CallbackT>
168 typename rclcpp::GenericService::SharedPtr
170  const std::string & service_name,
171  const std::string & service_type,
172  CallbackT && callback,
173  const rclcpp::QoS & qos,
174  const rclcpp::CallbackGroup::SharedPtr & group)
175 {
176  return rclcpp::create_generic_service<CallbackT>(
177  node_base_,
178  node_services_,
179  extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
180  service_type,
181  std::forward<CallbackT>(callback),
182  qos,
183  group);
184 }
185 
186 template<typename AllocatorT>
187 std::shared_ptr<rclcpp::GenericPublisher>
189  const std::string & topic_name,
190  const std::string & topic_type,
191  const rclcpp::QoS & qos,
193 {
195  node_topics_,
196  extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
197  topic_type,
198  qos,
199  options
200  );
201 }
202 
203 template<typename CallbackT, typename AllocatorT>
204 std::shared_ptr<rclcpp::GenericSubscription>
206  const std::string & topic_name,
207  const std::string & topic_type,
208  const rclcpp::QoS & qos,
209  CallbackT && callback,
211 {
213  node_topics_,
214  extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
215  topic_type,
216  qos,
217  std::forward<CallbackT>(callback),
218  options
219  );
220 }
221 
222 
223 template<typename ParameterT>
224 auto
226  const std::string & name,
227  const ParameterT & default_value,
228  const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
229  bool ignore_override)
230 {
231  try {
232  return this->declare_parameter(
233  name,
234  rclcpp::ParameterValue(default_value),
235  parameter_descriptor,
236  ignore_override
237  ).get<ParameterT>();
238  } catch (const ParameterTypeException & ex) {
239  throw exceptions::InvalidParameterTypeException(name, ex.what());
240  }
241 }
242 
243 template<typename ParameterT>
244 auto
246  const std::string & name,
247  const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
248  bool ignore_override)
249 {
250  // get advantage of parameter value template magic to get
251  // the correct rclcpp::ParameterType from ParameterT
252  rclcpp::ParameterValue value{ParameterT{}};
253  try {
254  return this->declare_parameter(
255  name,
256  value.get_type(),
257  parameter_descriptor,
258  ignore_override
259  ).get<ParameterT>();
260  } catch (const ParameterTypeException &) {
262  }
263 }
264 
265 template<typename ParameterT>
266 std::vector<ParameterT>
268  const std::string & namespace_,
269  const std::map<std::string, ParameterT> & parameters,
270  bool ignore_overrides)
271 {
272  std::vector<ParameterT> result;
273  std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
274  std::transform(
275  parameters.begin(), parameters.end(), std::back_inserter(result),
276  [this, &normalized_namespace, ignore_overrides](auto element) {
277  return this->declare_parameter(
278  normalized_namespace + element.first,
279  element.second,
280  rcl_interfaces::msg::ParameterDescriptor(),
281  ignore_overrides);
282  }
283  );
284  return result;
285 }
286 
287 template<typename ParameterT>
288 std::vector<ParameterT>
290  const std::string & namespace_,
291  const std::map<
292  std::string,
293  std::pair<ParameterT, rcl_interfaces::msg::ParameterDescriptor>
294  > & parameters,
295  bool ignore_overrides)
296 {
297  std::vector<ParameterT> result;
298  std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
299  std::transform(
300  parameters.begin(), parameters.end(), std::back_inserter(result),
301  [this, &normalized_namespace, ignore_overrides](auto element) {
302  return static_cast<ParameterT>(
303  this->declare_parameter(
304  normalized_namespace + element.first,
305  element.second.first,
306  element.second.second,
307  ignore_overrides)
308  );
309  }
310  );
311  return result;
312 }
313 
314 template<typename ParameterT>
315 bool
316 Node::get_parameter(const std::string & name, ParameterT & parameter) const
317 {
318  rclcpp::Parameter parameter_variant;
319 
320  bool result = get_parameter(name, parameter_variant);
321  if (result) {
322  parameter = static_cast<ParameterT>(parameter_variant.get_value<ParameterT>());
323  }
324 
325  return result;
326 }
327 
328 template<typename ParameterT>
329 bool
331  const std::string & name,
332  ParameterT & parameter,
333  const ParameterT & alternative_value) const
334 {
335  bool got_parameter = get_parameter(name, parameter);
336  if (!got_parameter) {
337  parameter = alternative_value;
338  }
339  return got_parameter;
340 }
341 
342 template<typename ParameterT>
343 ParameterT
345  const std::string & name,
346  const ParameterT & alternative_value) const
347 {
348  ParameterT parameter;
349  get_parameter_or(name, parameter, alternative_value);
350  return parameter;
351 }
352 
353 // this is a partially-specialized version of get_parameter above,
354 // where our concrete type for ParameterT is std::map, but the to-be-determined
355 // type is the value in the map.
356 template<typename ParameterT>
357 bool
359  const std::string & prefix,
360  std::map<std::string, ParameterT> & values) const
361 {
362  std::map<std::string, rclcpp::Parameter> params;
363  bool result = node_parameters_->get_parameters_by_prefix(prefix, params);
364  if (result) {
365  for (const auto & param : params) {
366  values[param.first] = static_cast<ParameterT>(param.second.get_value<ParameterT>());
367  }
368  }
369 
370  return result;
371 }
372 
373 } // namespace rclcpp
374 
375 #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:415
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:585
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:169
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:345
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:330
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:267
RCLCPP_PUBLIC rclcpp::Parameter get_parameter(const std::string &name) const
Return the parameter by the given name.
Definition: node.cpp:403
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:120
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:205
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:85
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:66
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:103
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:669
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:188
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:152
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.