ROS 2 rclcpp + rcl - humble  humble
ROS 2 C++ Client Library with ROS Client Library
node_topics.cpp
1 // Copyright 2016 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 #include "rclcpp/node_interfaces/node_topics.hpp"
16 
17 #include <stdexcept>
18 #include <string>
19 
20 #include "rclcpp/callback_group.hpp"
21 #include "rclcpp/exceptions.hpp"
22 #include "rclcpp/node_interfaces/node_base_interface.hpp"
23 #include "rclcpp/node_interfaces/node_timers_interface.hpp"
24 #include "rclcpp/publisher_base.hpp"
25 #include "rclcpp/publisher_factory.hpp"
26 #include "rclcpp/subscription_base.hpp"
27 #include "rclcpp/subscription_factory.hpp"
28 #include "rclcpp/qos.hpp"
29 
30 using rclcpp::exceptions::throw_from_rcl_error;
31 
33 
34 NodeTopics::NodeTopics(
37 : node_base_(node_base), node_timers_(node_timers)
38 {}
39 
40 NodeTopics::~NodeTopics()
41 {}
42 
43 rclcpp::PublisherBase::SharedPtr
44 NodeTopics::create_publisher(
45  const std::string & topic_name,
46  const rclcpp::PublisherFactory & publisher_factory,
47  const rclcpp::QoS & qos)
48 {
49  // Create the MessageT specific Publisher using the factory, but return it as PublisherBase.
50  return publisher_factory.create_typed_publisher(node_base_, topic_name, qos);
51 }
52 
53 void
54 NodeTopics::add_publisher(
55  rclcpp::PublisherBase::SharedPtr publisher,
56  rclcpp::CallbackGroup::SharedPtr callback_group)
57 {
58  // Assign to a group.
59  if (callback_group) {
60  if (!node_base_->callback_group_in_node(callback_group)) {
61  throw std::runtime_error("Cannot create publisher, callback group not in node.");
62  }
63  } else {
64  callback_group = node_base_->get_default_callback_group();
65  }
66 
67  for (auto & key_event_pair : publisher->get_event_handlers()) {
68  auto publisher_event = key_event_pair.second;
69  callback_group->add_waitable(publisher_event);
70  }
71 
72  // Notify the executor that a new publisher was created using the parent Node.
73  auto & node_gc = node_base_->get_notify_guard_condition();
74  try {
75  node_gc.trigger();
76  callback_group->trigger_notify_guard_condition();
77  } catch (const rclcpp::exceptions::RCLError & ex) {
78  throw std::runtime_error(
79  std::string("failed to notify wait set on publisher creation: ") + ex.what());
80  }
81 }
82 
83 rclcpp::SubscriptionBase::SharedPtr
84 NodeTopics::create_subscription(
85  const std::string & topic_name,
86  const rclcpp::SubscriptionFactory & subscription_factory,
87  const rclcpp::QoS & qos)
88 {
89  // Create the MessageT specific Subscription using the factory, but return a SubscriptionBase.
90  return subscription_factory.create_typed_subscription(node_base_, topic_name, qos);
91 }
92 
93 void
94 NodeTopics::add_subscription(
95  rclcpp::SubscriptionBase::SharedPtr subscription,
96  rclcpp::CallbackGroup::SharedPtr callback_group)
97 {
98  // Assign to a group.
99  if (callback_group) {
100  if (!node_base_->callback_group_in_node(callback_group)) {
101  // TODO(jacquelinekay): use custom exception
102  throw std::runtime_error("Cannot create subscription, callback group not in node.");
103  }
104  } else {
105  callback_group = node_base_->get_default_callback_group();
106  }
107 
108  callback_group->add_subscription(subscription);
109 
110  for (auto & key_event_pair : subscription->get_event_handlers()) {
111  auto subscription_event = key_event_pair.second;
112  callback_group->add_waitable(subscription_event);
113  }
114 
115  auto intra_process_waitable = subscription->get_intra_process_waitable();
116  if (nullptr != intra_process_waitable) {
117  // Add to the callback group to be notified about intra-process msgs.
118  callback_group->add_waitable(intra_process_waitable);
119  }
120 
121  // Notify the executor that a new subscription was created using the parent Node.
122  auto & node_gc = node_base_->get_notify_guard_condition();
123  try {
124  node_gc.trigger();
125  callback_group->trigger_notify_guard_condition();
126  } catch (const rclcpp::exceptions::RCLError & ex) {
127  throw std::runtime_error(
128  std::string("failed to notify wait set on subscription creation: ") + ex.what());
129  }
130 }
131 
133 NodeTopics::get_node_base_interface() const
134 {
135  return node_base_;
136 }
137 
139 NodeTopics::get_node_timers_interface() const
140 {
141  return node_timers_;
142 }
143 
144 std::string
145 NodeTopics::resolve_topic_name(const std::string & name, bool only_expand) const
146 {
147  return node_base_->resolve_topic_or_service_name(name, false, only_expand);
148 }
RCLCPP_PUBLIC void trigger()
Notify the wait set waiting on this condition, if any, that the condition had been met.
Encapsulation of Quality of Service settings.
Definition: qos.hpp:111
Created when the return code does not match one of the other specialized exceptions.
Definition: exceptions.hpp:153
Pure virtual interface class for the NodeBase part of the Node API.
virtual RCLCPP_PUBLIC bool callback_group_in_node(rclcpp::CallbackGroup::SharedPtr group)=0
Return true if the given callback group is associated with this node.
virtual RCLCPP_PUBLIC rclcpp::CallbackGroup::SharedPtr get_default_callback_group()=0
Return the default callback group.
virtual RCLCPP_PUBLIC std::string resolve_topic_or_service_name(const std::string &name, bool is_service, bool only_expand=false) const =0
Expand and remap a given topic or service name.
virtual RCLCPP_PUBLIC rclcpp::GuardCondition & get_notify_guard_condition()=0
Return a guard condition that should be notified when the internal node state changes.
Pure virtual interface class for the NodeTimers part of the Node API.
Implementation of the NodeTopics part of the Node API.
Definition: node_topics.hpp:42
RCLCPP_PUBLIC std::string resolve_topic_name(const std::string &name, bool only_expand=false) const override
Get a remapped and expanded topic name given an input name.
Factory with functions used to create a MessageT specific PublisherT.
Factory containing a function used to create a Subscription<MessageT>.