rclcpp  master
C++ ROS Client Library API
publisher_factory.hpp
Go to the documentation of this file.
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 #ifndef RCLCPP__PUBLISHER_FACTORY_HPP_
16 #define RCLCPP__PUBLISHER_FACTORY_HPP_
17 
18 #include <functional>
19 #include <memory>
20 #include <string>
21 
22 #include "rcl/publisher.h"
23 
24 #include "rosidl_typesupport_cpp/message_type_support.hpp"
25 
26 #include "rclcpp/publisher.hpp"
30 
31 namespace rclcpp
32 {
33 
35 
46 {
47  // Creates a PublisherT<MessageT, ...> publisher object and returns it as a PublisherBase.
49  rclcpp::PublisherBase::SharedPtr(
51  const std::string & topic_name,
52  rcl_publisher_options_t & publisher_options)>;
53 
55 
56  // Adds the PublisherBase to the intraprocess manager with the correctly
57  // templated call to IntraProcessManager::store_intra_process_message.
59  uint64_t(
61  rclcpp::PublisherBase::SharedPtr publisher)>;
62 
64 
65  // Creates the callback function which is called on each
66  // PublisherT::publish() and which handles the intra process transmission of
67  // the message being published.
70  rclcpp::intra_process_manager::IntraProcessManager::SharedPtr ipm)>;
71 
73 };
74 
76 template<typename MessageT, typename Alloc, typename PublisherT>
79 {
80  PublisherFactory factory;
81 
82  // factory function that creates a MessageT specific PublisherT
83  factory.create_typed_publisher =
84  [allocator](
86  const std::string & topic_name,
88  {
89  auto message_alloc = std::make_shared<typename PublisherT::MessageAlloc>(*allocator.get());
90  publisher_options.allocator = allocator::get_rcl_allocator<MessageT>(*message_alloc.get());
91 
92  return std::make_shared<PublisherT>(node_base, topic_name, publisher_options, message_alloc);
93  };
94 
95  // function to add a publisher to the intra process manager
97  [](
99  rclcpp::PublisherBase::SharedPtr publisher) -> uint64_t
100  {
101  return ipm->add_publisher<MessageT, Alloc>(std::dynamic_pointer_cast<PublisherT>(publisher));
102  };
103 
104  // function to create a shared publish callback std::function
105  using StoreMessageCallbackT = rclcpp::PublisherBase::StoreMessageCallbackT;
107  [](rclcpp::intra_process_manager::IntraProcessManager::SharedPtr ipm) -> StoreMessageCallbackT
108  {
109  rclcpp::intra_process_manager::IntraProcessManager::WeakPtr weak_ipm = ipm;
110 
111  // this function is called on each call to publish() and handles storing
112  // of the published message in the intra process manager
113  auto shared_publish_callback =
114  [weak_ipm](uint64_t publisher_id, void * msg, const std::type_info & type_info) -> uint64_t
115  {
116  auto ipm = weak_ipm.lock();
117  if (!ipm) {
118  // TODO(wjwwood): should this just return silently? Or maybe return with a warning?
119  throw std::runtime_error(
120  "intra process publish called after destruction of intra process manager");
121  }
122  if (!msg) {
123  throw std::runtime_error("cannot publisher msg which is a null pointer");
124  }
125  auto & message_type_info = typeid(MessageT);
126  if (message_type_info != type_info) {
127  throw std::runtime_error(
128  std::string("published type '") + type_info.name() +
129  "' is incompatible from the publisher type '" + message_type_info.name() + "'");
130  }
131  MessageT * typed_message_ptr = static_cast<MessageT *>(msg);
132  using MessageDeleter = typename Publisher<MessageT, Alloc>::MessageDeleter;
133  std::unique_ptr<MessageT, MessageDeleter> unique_msg(typed_message_ptr);
134  uint64_t message_seq =
135  ipm->store_intra_process_message<MessageT, Alloc>(publisher_id, unique_msg);
136  return message_seq;
137  };
138 
139  return shared_publish_callback;
140  };
141 
142  // return the factory now that it is populated
143  return factory;
144 }
145 
146 } // namespace rclcpp
147 
148 #endif // RCLCPP__PUBLISHER_FACTORY_HPP_
PublisherFactory create_publisher_factory(std::shared_ptr< Alloc > allocator)
Return a PublisherFactory with functions setup for creating a PublisherT<MessageT, Alloc>.
Definition: publisher_factory.hpp:78
PublisherFactoryFunction create_typed_publisher
Definition: publisher_factory.hpp:54
SharedPublishCallbackFactoryFunction create_shared_publish_callback
Definition: publisher_factory.hpp:72
Definition: allocator_common.hpp:24
Factory with functions used to create a MessageT specific PublisherT.
Definition: publisher_factory.hpp:45
uint64_t add_publisher(typename Publisher< MessageT, Alloc >::SharedPtr publisher, size_t buffer_size=0)
Register a publisher with the manager, returns the publisher unique id.
Definition: intra_process_manager.hpp:189
uint64_t store_intra_process_message(uint64_t intra_process_publisher_id, std::unique_ptr< MessageT, Deleter > &message)
Store a message in the manager, and return the message sequence number.
Definition: intra_process_manager.hpp:248
allocator::Deleter< MessageAlloc, MessageT > MessageDeleter
Definition: publisher.hpp:160
AddPublisherToIntraProcessManagerFunction add_publisher_to_intra_process_manager
Definition: publisher_factory.hpp:63
std::function< uint64_t(uint64_t, void *, const std::type_info &)> StoreMessageCallbackT
Definition: publisher.hpp:130
Pure virtual interface class for the NodeBase part of the Node API.
Definition: node_base_interface.hpp:36
T dynamic_pointer_cast(T... args)
T get(T... args)
This class facilitates intra process communication between nodes.
Definition: intra_process_manager.hpp:122