rclcpp  master
C++ ROS Client Library API
node_impl.hpp
Go to the documentation of this file.
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 <rmw/error_handling.h>
19 #include <rmw/rmw.h>
20 
21 #include <algorithm>
22 #include <cstdlib>
23 #include <iostream>
24 #include <limits>
25 #include <map>
26 #include <memory>
27 #include <sstream>
28 #include <stdexcept>
29 #include <string>
30 #include <utility>
31 #include <vector>
32 
33 #include "rcl/publisher.h"
34 #include "rcl/subscription.h"
35 
36 #include "rcl_interfaces/msg/intra_process_message.hpp"
37 
43 #include "rclcpp/parameter.hpp"
44 #include "rclcpp/qos.hpp"
47 
48 #ifndef RCLCPP__NODE_HPP_
49 #include "node.hpp"
50 #endif
51 
52 namespace rclcpp
53 {
54 
56 inline
58 extend_name_with_sub_namespace(const std::string & name, const std::string & sub_namespace)
59 {
60  std::string name_with_sub_namespace(name);
61  if (sub_namespace != "" && name.front() != '/' && name.front() != '~') {
62  name_with_sub_namespace = sub_namespace + "/" + name;
63  }
64  return name_with_sub_namespace;
65 }
66 
67 template<typename MessageT, typename AllocatorT, typename PublisherT>
70  const std::string & topic_name,
71  const rclcpp::QoS & qos,
73 {
74  return rclcpp::create_publisher<MessageT, AllocatorT, PublisherT>(
75  *this,
77  qos,
78  options);
79 }
80 
81 template<typename MessageT, typename AllocatorT, typename PublisherT>
84  const std::string & topic_name,
85  size_t qos_history_depth,
87 {
89  pub_options.allocator = allocator;
90  return this->create_publisher<MessageT, AllocatorT, PublisherT>(
91  topic_name, rclcpp::QoS(rclcpp::KeepLast(qos_history_depth)), pub_options);
92 }
93 
94 template<typename MessageT, typename AllocatorT, typename PublisherT>
97  const std::string & topic_name,
98  const rmw_qos_profile_t & qos_profile,
100 {
102  qos.get_rmw_qos_profile() = qos_profile;
103 
105  pub_options.allocator = allocator;
106  return this->create_publisher<MessageT, AllocatorT, PublisherT>(topic_name, qos, pub_options);
107 }
108 
109 template<
110  typename MessageT,
111  typename CallbackT,
112  typename AllocatorT,
113  typename SubscriptionT>
116  const std::string & topic_name,
117  const rclcpp::QoS & qos,
118  CallbackT && callback,
122  msg_mem_strat)
123 {
124  return rclcpp::create_subscription<MessageT>(
125  *this,
127  qos,
128  std::forward<CallbackT>(callback),
129  options,
130  msg_mem_strat);
131 }
132 
133 template<
134  typename MessageT,
135  typename CallbackT,
136  typename Alloc,
137  typename SubscriptionT>
140  const std::string & topic_name,
141  CallbackT && callback,
142  const rmw_qos_profile_t & qos_profile,
143  rclcpp::callback_group::CallbackGroup::SharedPtr group,
144  bool ignore_local_publications,
147  msg_mem_strat,
148  std::shared_ptr<Alloc> allocator)
149 {
151  qos.get_rmw_qos_profile() = qos_profile;
152 
154  sub_options.callback_group = group;
155  sub_options.ignore_local_publications = ignore_local_publications;
156  sub_options.allocator = allocator;
157 
158  return this->create_subscription<MessageT, CallbackT, Alloc, SubscriptionT>(
159  topic_name, qos, std::forward<CallbackT>(callback), sub_options, msg_mem_strat);
160 }
161 
162 template<
163  typename MessageT,
164  typename CallbackT,
165  typename Alloc,
166  typename SubscriptionT>
169  const std::string & topic_name,
170  CallbackT && callback,
171  size_t qos_history_depth,
172  rclcpp::callback_group::CallbackGroup::SharedPtr group,
173  bool ignore_local_publications,
176  msg_mem_strat,
177  std::shared_ptr<Alloc> allocator)
178 {
180  sub_options.callback_group = group;
181  sub_options.ignore_local_publications = ignore_local_publications;
182  sub_options.allocator = allocator;
183 
184  return this->create_subscription<MessageT, CallbackT, Alloc, SubscriptionT>(
185  topic_name,
186  rclcpp::QoS(rclcpp::KeepLast(qos_history_depth)),
187  std::forward<CallbackT>(callback),
188  sub_options,
189  msg_mem_strat);
190 }
191 
192 template<typename DurationRepT, typename DurationT, typename CallbackT>
196  CallbackT callback,
197  rclcpp::callback_group::CallbackGroup::SharedPtr group)
198 {
200  std::chrono::duration_cast<std::chrono::nanoseconds>(period),
201  std::move(callback),
202  this->node_base_->get_context());
203  node_timers_->add_timer(timer, group);
204  return timer;
205 }
206 
207 template<typename ServiceT>
210  const std::string & service_name,
211  const rmw_qos_profile_t & qos_profile,
212  rclcpp::callback_group::CallbackGroup::SharedPtr group)
213 {
215  options.qos = qos_profile;
216 
217  using rclcpp::Client;
218  using rclcpp::ClientBase;
219 
221  node_base_.get(),
222  node_graph_,
223  extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
224  options);
225 
226  auto cli_base_ptr = std::dynamic_pointer_cast<ClientBase>(cli);
227  node_services_->add_client(cli_base_ptr, group);
228  return cli;
229 }
230 
231 template<typename ServiceT, typename CallbackT>
234  const std::string & service_name,
235  CallbackT && callback,
236  const rmw_qos_profile_t & qos_profile,
237  rclcpp::callback_group::CallbackGroup::SharedPtr group)
238 {
239  return rclcpp::create_service<ServiceT, CallbackT>(
240  node_base_,
241  node_services_,
242  extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
243  std::forward<CallbackT>(callback),
244  qos_profile,
245  group);
246 }
247 
248 template<typename ParameterT>
249 auto
251  const std::string & name,
252  const ParameterT & default_value,
253  const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor)
254 {
255  return this->declare_parameter(
256  name,
257  rclcpp::ParameterValue(default_value),
258  parameter_descriptor
259  ).get<ParameterT>();
260 }
261 
262 template<typename ParameterT>
265  const std::string & namespace_,
266  const std::map<std::string, ParameterT> & parameters)
267 {
269  std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
271  parameters.begin(), parameters.end(), std::back_inserter(result),
272  [this, &normalized_namespace](auto element) {
273  return this->declare_parameter(normalized_namespace + element.first, element.second);
274  }
275  );
276  return result;
277 }
278 
279 template<typename ParameterT>
282  const std::string & namespace_,
283  const std::map<
284  std::string,
286  > & parameters)
287 {
289  std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
291  parameters.begin(), parameters.end(), std::back_inserter(result),
292  [this, &normalized_namespace](auto element) {
293  return static_cast<ParameterT>(
294  this->declare_parameter(
295  normalized_namespace + element.first,
296  element.second.first,
297  element.second.second)
298  );
299  }
300  );
301  return result;
302 }
303 
304 template<typename ParameterT>
305 void
307  const std::string & name,
308  const ParameterT & value)
309 {
310  if (
311  !this->has_parameter(name) ||
312  this->describe_parameter(name).type == PARAMETER_NOT_SET)
313  {
314  this->set_parameter(rclcpp::Parameter(name, value));
315  }
316 }
317 
318 // this is a partially-specialized version of set_parameter_if_not_set above,
319 // where our concrete type for ParameterT is std::map, but the to-be-determined
320 // type is the value in the map.
321 template<typename ParameterT>
322 void
324  const std::string & name,
325  const std::map<std::string, ParameterT> & values)
326 {
328 
329  for (const auto & val : values) {
330  std::string parameter_name = name + "." + val.first;
331  if (
332  !this->has_parameter(parameter_name) ||
333  this->describe_parameter(parameter_name).type == PARAMETER_NOT_SET)
334  {
335  params.push_back(rclcpp::Parameter(parameter_name, val.second));
336  }
337  }
338 
339  this->set_parameters(params);
340 }
341 
342 template<typename ParameterT>
343 bool
344 Node::get_parameter(const std::string & name, ParameterT & parameter) const
345 {
347 
348  rclcpp::Parameter parameter_variant;
349 
350  bool result = get_parameter(sub_name, parameter_variant);
351  if (result) {
352  parameter = static_cast<ParameterT>(parameter_variant.get_value<ParameterT>());
353  }
354 
355  return result;
356 }
357 
358 template<typename ParameterT>
359 bool
361  const std::string & name,
362  ParameterT & parameter,
363  const ParameterT & alternative_value) const
364 {
366 
367  bool got_parameter = get_parameter(sub_name, parameter);
368  if (!got_parameter) {
369  parameter = alternative_value;
370  }
371  return got_parameter;
372 }
373 
374 // this is a partially-specialized version of get_parameter above,
375 // where our concrete type for ParameterT is std::map, but the to-be-determined
376 // type is the value in the map.
377 template<typename ParameterT>
378 bool
380  const std::string & prefix,
381  std::map<std::string, ParameterT> & values) const
382 {
384  bool result = node_parameters_->get_parameters_by_prefix(prefix, params);
385  if (result) {
386  for (const auto & param : params) {
387  values[param.first] = static_cast<ParameterT>(param.second.get_value<ParameterT>());
388  }
389  }
390 
391  return result;
392 }
393 
394 template<typename ParameterT>
395 void
397  const std::string & name,
398  ParameterT & value,
399  const ParameterT & alternative_value)
400 {
402 
403  bool got_parameter = get_parameter(sub_name, value);
404  if (!got_parameter) {
405  this->set_parameters({
406  rclcpp::Parameter(sub_name, alternative_value),
407  });
408  value = alternative_value;
409  }
410 }
411 
412 template<typename CallbackT>
413 void
415 {
416  this->node_parameters_->register_param_change_callback(std::forward<CallbackT>(callback));
417 }
418 
419 } // namespace rclcpp
420 
421 #endif // RCLCPP__NODE_IMPL_HPP_
void register_param_change_callback(CallbackT &&callback)
Register the callback for parameter changes.
Definition: node_impl.hpp:414
Definition: client.hpp:52
Default allocation strategy for messages received by subscriptions.
Definition: message_memory_strategy.hpp:40
T empty(T... args)
rclcpp::Client< ServiceT >::SharedPtr create_client(const std::string &service_name, const rmw_qos_profile_t &qos_profile=rmw_qos_profile_services_default, rclcpp::callback_group::CallbackGroup::SharedPtr group=nullptr)
rcl_interfaces::msg::SetParametersResult set_parameter(const rclcpp::Parameter &parameter)
Set a single parameter.
Definition: parameter_value.hpp:34
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:360
Encapsulation of Quality of Service settings.
Definition: qos.hpp:55
Structure to store an arbitrary parameter with templated get/set methods.
Definition: parameter.hpp:51
Definition: timer.hpp:202
T front(T... args)
bool has_parameter(const std::string &name) const
Return true if a given parameter is declared.
const std::string & get_sub_namespace() const
Return the sub-namespace, if this is a sub-node, otherwise an empty string.
rmw_qos_profile_t & get_rmw_qos_profile()
Return the rmw qos profile.
This header provides the get_node_topics_interface() template function.
Definition: allocator_common.hpp:24
Use to initialize the QoS with the keep_last history setting and the given depth. ...
Definition: qos.hpp:49
T end(T... args)
static QoSInitialization from_rmw(const rmw_qos_profile_t &rmw_qos)
Create a QoSInitialization from an existing rmw_qos_profile_t, using its history and depth...
Definition: service.hpp:88
RCLCPP_LOCAL std::string extend_name_with_sub_namespace(const std::string &name, const std::string &sub_namespace)
Definition: node_impl.hpp:58
std::vector< ParameterT > declare_parameters(const std::string &namespace_, const std::map< std::string, ParameterT > &parameters)
Declare and initialize several parameters with the same namespace and type.
Definition: node_impl.hpp:264
Definition: client.hpp:119
void get_parameter_or_set(const std::string &name, ParameterT &value, const ParameterT &alternative_value)
Get the parameter value; if not set, set the "alternative value" and store it in the node...
Definition: node_impl.hpp:396
rmw_qos_profile_t qos
decltype(auto) get_value() const
Get value of parameter using rclcpp::ParameterType as template argument.
Definition: parameter.hpp:109
std::shared_ptr< Allocator > allocator
Optional custom allocator.
Definition: subscription_options.hpp:49
T push_back(T... args)
typename std::remove_cv< rclcpp::function_traits::function_traits< CallbackT >::template argument_type< 0 > >::type type
Definition: subscription_traits.hpp:65
std::shared_ptr< Allocator > allocator
Optional custom allocator.
Definition: publisher_options.hpp:50
std::vector< rcl_interfaces::msg::SetParametersResult > set_parameters(const std::vector< rclcpp::Parameter > &parameters)
Set one or more parameters, one at a time.
rcl_interfaces::msg::ParameterDescriptor describe_parameter(const std::string &name) const
Return the parameter descriptor for the given parameter name.
void set_parameters_if_not_set(const std::string &name, const std::map< std::string, ParameterT > &values)
Set a map of parameters with the same prefix.
Definition: node_impl.hpp:323
rcl_client_options_t rcl_client_get_default_options(void)
T dynamic_pointer_cast(T... args)
#define RCLCPP_LOCAL
Definition: visibility_control.hpp:51
T move(T... args)
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:69
Structure containing optional configuration for Publishers.
Definition: publisher_options.hpp:47
Structure containing optional configuration for Subscriptions.
Definition: subscription_options.hpp:46
void set_parameter_if_not_set(const std::string &name, const ParameterT &value)
Set one parameter, unless that parameter has already been set.
Definition: node_impl.hpp:306
rclcpp::WallTimer< CallbackT >::SharedPtr create_wall_timer(std::chrono::duration< DurationRepT, DurationT > period, CallbackT callback, rclcpp::callback_group::CallbackGroup::SharedPtr group=nullptr)
Create a timer.
Definition: node_impl.hpp:194
const rclcpp::ParameterValue & declare_parameter(const std::string &name, const rclcpp::ParameterValue &default_value=rclcpp::ParameterValue(), const rcl_interfaces::msg::ParameterDescriptor &parameter_descriptor=rcl_interfaces::msg::ParameterDescriptor())
Declare and initialize a parameter, return the effective value.
T begin(T... args)
T back_inserter(T... args)
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group
The callback group for this subscription. NULL to use the default callback group. ...
Definition: subscription_options.hpp:39
constexpr std::enable_if< type==ParameterType::PARAMETER_BOOL, const bool & >::type get() const
Definition: parameter_value.hpp:148
Store the type and value of a parameter.
Definition: parameter_value.hpp:71
std::shared_ptr< SubscriptionT > create_subscription(const std::string &topic_name, const rclcpp::QoS &qos, CallbackT &&callback, const SubscriptionOptionsWithAllocator< AllocatorT > &options=SubscriptionOptionsWithAllocator< AllocatorT >(), typename rclcpp::message_memory_strategy::MessageMemoryStrategy< typename rclcpp::subscription_traits::has_message_type< CallbackT >::type, AllocatorT >::SharedPtr msg_mem_strat=nullptr)
Create and return a Subscription.
Definition: node_impl.hpp:115
rclcpp::Parameter get_parameter(const std::string &name) const
Return the parameter by the given name.
T transform(T... args)
std::vector< rclcpp::Parameter > get_parameters(const std::vector< std::string > &names) const
Return the parameters by the given parameter names.
rclcpp::Service< ServiceT >::SharedPtr create_service(const std::string &service_name, CallbackT &&callback, const rmw_qos_profile_t &qos_profile=rmw_qos_profile_services_default, rclcpp::callback_group::CallbackGroup::SharedPtr group=nullptr)
Definition: node_impl.hpp:233
bool ignore_local_publications
True to ignore local publications.
Definition: subscription_options.hpp:37