15 #ifndef RCLCPP__PUBLISHER_HPP_
16 #define RCLCPP__PUBLISHER_HPP_
23 #include <type_traits>
26 #include "rcl/error_handling.h"
28 #include "rmw/error_handling.h"
30 #include "rosidl_runtime_cpp/traits.hpp"
32 #include "rclcpp/allocator/allocator_common.hpp"
33 #include "rclcpp/allocator/allocator_deleter.hpp"
34 #include "rclcpp/detail/resolve_use_intra_process.hpp"
35 #include "rclcpp/detail/resolve_intra_process_buffer_type.hpp"
36 #include "rclcpp/experimental/buffers/intra_process_buffer.hpp"
37 #include "rclcpp/experimental/create_intra_process_buffer.hpp"
38 #include "rclcpp/experimental/intra_process_manager.hpp"
39 #include "rclcpp/get_message_type_support_handle.hpp"
40 #include "rclcpp/is_ros_compatible_type.hpp"
41 #include "rclcpp/loaned_message.hpp"
42 #include "rclcpp/macros.hpp"
43 #include "rclcpp/node_interfaces/node_base_interface.hpp"
44 #include "rclcpp/publisher_base.hpp"
45 #include "rclcpp/publisher_options.hpp"
46 #include "rclcpp/type_adapter.hpp"
47 #include "rclcpp/type_support_decl.hpp"
48 #include "rclcpp/visibility_control.hpp"
50 #include "tracetools/tracetools.h"
55 template<
typename MessageT,
typename AllocatorT>
79 template<
typename MessageT,
typename AllocatorT = std::allocator<
void>>
85 "given message type is not compatible with ROS and cannot be used with a Publisher");
88 using PublishedType =
typename rclcpp::TypeAdapter<MessageT>::custom_type;
89 using ROSMessageType =
typename rclcpp::TypeAdapter<MessageT>::ros_message_type;
91 using PublishedTypeAllocatorTraits = allocator::AllocRebind<PublishedType, AllocatorT>;
92 using PublishedTypeAllocator =
typename PublishedTypeAllocatorTraits::allocator_type;
93 using PublishedTypeDeleter = allocator::Deleter<PublishedTypeAllocator, PublishedType>;
95 using ROSMessageTypeAllocatorTraits = allocator::AllocRebind<ROSMessageType, AllocatorT>;
96 using ROSMessageTypeAllocator =
typename ROSMessageTypeAllocatorTraits::allocator_type;
97 using ROSMessageTypeDeleter = allocator::Deleter<ROSMessageTypeAllocator, ROSMessageType>;
99 using MessageAllocatorTraits
100 [[deprecated(
"use PublishedTypeAllocatorTraits")]] =
101 PublishedTypeAllocatorTraits;
102 using MessageAllocator
103 [[deprecated(
"use PublishedTypeAllocator")]] =
104 PublishedTypeAllocator;
106 [[deprecated(
"use PublishedTypeDeleter")]] =
107 PublishedTypeDeleter;
108 using MessageUniquePtr
109 [[deprecated(
"use std::unique_ptr<PublishedType, PublishedTypeDeleter>")]] =
110 std::unique_ptr<PublishedType, PublishedTypeDeleter>;
111 using MessageSharedPtr
112 [[deprecated(
"use std::shared_ptr<const PublishedType>")]] =
113 std::shared_ptr<const PublishedType>;
117 ROSMessageTypeAllocator,
118 ROSMessageTypeDeleter
135 rclcpp::node_interfaces::NodeBaseInterface * node_base,
136 const std::
string & topic,
142 rclcpp::get_message_type_support_handle<MessageT>(),
143 options.template to_rcl_publisher_options<MessageT>(qos),
145 options.event_callbacks,
146 options.use_default_callbacks),
148 published_type_allocator_(*options.get_allocator()),
149 ros_message_type_allocator_(*options.get_allocator())
151 allocator::set_allocator_for_deleter(&published_type_deleter_, &published_type_allocator_);
152 allocator::set_allocator_for_deleter(&ros_message_type_deleter_, &ros_message_type_allocator_);
161 const std::string & topic,
169 if (rclcpp::detail::resolve_use_intra_process(
options_, *node_base)) {
175 if (qos_profile.history() != rclcpp::HistoryPolicy::KeepLast) {
176 throw std::invalid_argument(
177 "intraprocess communication on topic '" + topic +
178 "' allowed only with keep last history qos policy");
180 if (qos_profile.depth() == 0) {
181 throw std::invalid_argument(
182 "intraprocess communication on topic '" + topic +
183 "' is not allowed with a zero qos history depth value");
185 if (qos_profile.durability() == rclcpp::DurabilityPolicy::TransientLocal) {
186 buffer_ = rclcpp::experimental::create_intra_process_buffer<
187 ROSMessageType, ROSMessageTypeAllocator, ROSMessageTypeDeleter>(
188 rclcpp::detail::resolve_intra_process_buffer_type(
options_.intra_process_buffer_type),
190 std::make_shared<ROSMessageTypeAllocator>(ros_message_type_allocator_));
193 uint64_t intra_process_publisher_id = ipm->add_publisher(this->shared_from_this(), buffer_);
195 intra_process_publisher_id,
223 this->get_ros_message_type_allocator());
238 typename std::enable_if_t<
239 rosidl_generator_traits::is_message<T>::value &&
240 std::is_same<T, ROSMessageType>::value
242 publish(std::unique_ptr<T, ROSMessageTypeDeleter> msg)
244 if (!intra_process_is_enabled_) {
245 this->do_inter_process_publish(*msg);
258 bool inter_process_publish_needed =
261 if (inter_process_publish_needed) {
263 this->do_intra_process_ros_message_publish_and_return_shared(std::move(msg));
265 buffer_->add_shared(shared_msg);
267 this->do_inter_process_publish(*shared_msg);
271 this->do_intra_process_ros_message_publish_and_return_shared(std::move(msg));
272 buffer_->add_shared(shared_msg);
274 this->do_intra_process_ros_message_publish(std::move(msg));
292 typename std::enable_if_t<
293 rosidl_generator_traits::is_message<T>::value &&
294 std::is_same<T, ROSMessageType>::value
299 if (!intra_process_is_enabled_) {
300 this->do_inter_process_publish(msg);
307 this->
publish(std::move(unique_msg));
322 typename std::enable_if_t<
324 std::is_same<T, PublishedType>::value
326 publish(std::unique_ptr<T, PublishedTypeDeleter> msg)
328 if (!intra_process_is_enabled_) {
330 auto ros_msg_ptr = std::make_unique<ROSMessageType>();
332 this->do_inter_process_publish(*ros_msg_ptr);
339 bool inter_process_publish_needed =
342 if (inter_process_publish_needed) {
343 auto ros_msg_ptr = std::make_shared<ROSMessageType>();
345 this->do_intra_process_publish(std::move(msg));
346 this->do_inter_process_publish(*ros_msg_ptr);
348 buffer_->add_shared(ros_msg_ptr);
352 auto ros_msg_ptr = std::make_shared<ROSMessageType>();
354 buffer_->add_shared(ros_msg_ptr);
356 this->do_intra_process_publish(std::move(msg));
372 typename std::enable_if_t<
374 std::is_same<T, PublishedType>::value
378 if (!intra_process_is_enabled_) {
380 auto ros_msg_ptr = std::make_unique<ROSMessageType>();
382 this->do_inter_process_publish(*ros_msg_ptr);
390 this->
publish(std::move(unique_msg));
396 return this->do_serialized_publish(&serialized_msg);
400 publish(
const SerializedMessage & serialized_msg)
402 return this->do_serialized_publish(&serialized_msg.get_rcl_serialized_message());
416 if (!loaned_msg.is_valid()) {
417 throw std::runtime_error(
"loaned message is not valid");
428 this->do_loaned_message_publish(loaned_msg.release());
432 this->
publish(loaned_msg.get());
436 [[deprecated(
"use get_published_type_allocator() or get_ros_message_type_allocator() instead")]]
437 std::shared_ptr<PublishedTypeAllocator>
438 get_allocator()
const
440 return std::make_shared<PublishedTypeAllocator>(published_type_allocator_);
443 PublishedTypeAllocator
444 get_published_type_allocator()
const
446 return published_type_allocator_;
449 ROSMessageTypeAllocator
450 get_ros_message_type_allocator()
const
452 return ros_message_type_allocator_;
457 do_inter_process_publish(
const ROSMessageType & msg)
459 TRACETOOLS_TRACEPOINT(rclcpp_publish,
nullptr,
static_cast<const void *
>(&msg));
460 auto status =
rcl_publish(publisher_handle_.get(), &msg,
nullptr);
473 rclcpp::exceptions::throw_from_rcl_error(status,
"failed to publish message");
480 if (intra_process_is_enabled_) {
482 throw std::runtime_error(
"storing serialized messages in intra process is not supported yet");
486 rclcpp::exceptions::throw_from_rcl_error(status,
"failed to publish serialized message");
491 do_loaned_message_publish(
492 std::unique_ptr<ROSMessageType, std::function<
void(ROSMessageType *)>> msg)
494 TRACETOOLS_TRACEPOINT(rclcpp_publish,
nullptr,
static_cast<const void *
>(msg.get()));
508 rclcpp::exceptions::throw_from_rcl_error(status,
"failed to publish message");
513 do_intra_process_publish(std::unique_ptr<PublishedType, PublishedTypeDeleter> msg)
515 auto ipm = weak_ipm_.lock();
517 throw std::runtime_error(
518 "intra process publish called after destruction of intra process manager");
521 throw std::runtime_error(
"cannot publish msg which is a null pointer");
523 TRACETOOLS_TRACEPOINT(
524 rclcpp_intra_publish,
525 static_cast<const void *
>(publisher_handle_.get()),
528 ipm->template do_intra_process_publish<PublishedType, ROSMessageType, AllocatorT>(
529 intra_process_publisher_id_,
531 published_type_allocator_);
535 do_intra_process_ros_message_publish(std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter> msg)
537 auto ipm = weak_ipm_.lock();
539 throw std::runtime_error(
540 "intra process publish called after destruction of intra process manager");
543 throw std::runtime_error(
"cannot publish msg which is a null pointer");
545 TRACETOOLS_TRACEPOINT(
546 rclcpp_intra_publish,
547 static_cast<const void *
>(publisher_handle_.get()),
550 ipm->template do_intra_process_publish<ROSMessageType, ROSMessageType, AllocatorT>(
551 intra_process_publisher_id_,
553 ros_message_type_allocator_);
556 std::shared_ptr<const ROSMessageType>
557 do_intra_process_ros_message_publish_and_return_shared(
558 std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter> msg)
560 auto ipm = weak_ipm_.lock();
562 throw std::runtime_error(
563 "intra process publish called after destruction of intra process manager");
566 throw std::runtime_error(
"cannot publish msg which is a null pointer");
568 TRACETOOLS_TRACEPOINT(
569 rclcpp_intra_publish,
570 static_cast<const void *
>(publisher_handle_.get()),
573 return ipm->template do_intra_process_publish_and_return_shared<ROSMessageType, ROSMessageType,
575 intra_process_publisher_id_,
577 ros_message_type_allocator_);
582 std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>
585 auto ptr = ROSMessageTypeAllocatorTraits::allocate(ros_message_type_allocator_, 1);
586 ROSMessageTypeAllocatorTraits::construct(ros_message_type_allocator_, ptr);
587 return std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>(ptr, ros_message_type_deleter_);
591 std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>
594 auto ptr = ROSMessageTypeAllocatorTraits::allocate(ros_message_type_allocator_, 1);
595 ROSMessageTypeAllocatorTraits::construct(ros_message_type_allocator_, ptr, msg);
596 return std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>(ptr, ros_message_type_deleter_);
600 std::unique_ptr<PublishedType, PublishedTypeDeleter>
603 auto ptr = PublishedTypeAllocatorTraits::allocate(published_type_allocator_, 1);
604 PublishedTypeAllocatorTraits::construct(published_type_allocator_, ptr, msg);
605 return std::unique_ptr<PublishedType, PublishedTypeDeleter>(ptr, published_type_deleter_);
615 PublishedTypeAllocator published_type_allocator_;
616 PublishedTypeDeleter published_type_deleter_;
617 ROSMessageTypeAllocator ros_message_type_allocator_;
618 ROSMessageTypeDeleter ros_message_type_deleter_;
620 BufferSharedPtr buffer_{
nullptr};
RCLCPP_PUBLIC size_t get_intra_process_subscription_count() const
Get intraprocess subscription count.
RCLCPP_PUBLIC rclcpp::QoS get_actual_qos() const
Get the actual QoS settings, after the defaults have been determined.
RCLCPP_PUBLIC void setup_intra_process(uint64_t intra_process_publisher_id, IntraProcessManagerSharedPtr ipm)
Implementation utility function used to setup intra process publishing after creation.
RCLCPP_PUBLIC bool can_loan_messages() const
Check if publisher instance can loan messages.
RCLCPP_PUBLIC size_t get_subscription_count() const
Get subscription count.
A publisher publishes messages of any type to a topic.
virtual void post_init_setup(rclcpp::node_interfaces::NodeBaseInterface *node_base, const std::string &topic, const rclcpp::QoS &qos, const rclcpp::PublisherOptionsWithAllocator< AllocatorT > &options)
Called post construction, so that construction may continue after shared_from_this() works.
typename rclcpp::TypeAdapter< MessageT >::custom_type PublishedType
MessageT::custom_type if MessageT is a TypeAdapter, otherwise just MessageT.
std::enable_if_t< rclcpp::TypeAdapter< MessageT >::is_specialized::value &&std::is_same< T, PublishedType >::value > publish(std::unique_ptr< T, PublishedTypeDeleter > msg)
Publish a message on the topic.
const rclcpp::PublisherOptionsWithAllocator< AllocatorT > options_
Copy of original options passed during construction.
rclcpp::LoanedMessage< ROSMessageType, AllocatorT > borrow_loaned_message()
Borrow a loaned ROS message from the middleware.
std::unique_ptr< ROSMessageType, ROSMessageTypeDeleter > duplicate_ros_message_as_unique_ptr(const ROSMessageType &msg)
Duplicate a given ros message as a unique_ptr.
std::enable_if_t< rosidl_generator_traits::is_message< T >::value &&std::is_same< T, ROSMessageType >::value > publish(std::unique_ptr< T, ROSMessageTypeDeleter > msg)
Publish a message on the topic.
std::enable_if_t< rclcpp::TypeAdapter< MessageT >::is_specialized::value &&std::is_same< T, PublishedType >::value > publish(const T &msg)
Publish a message on the topic.
std::unique_ptr< PublishedType, PublishedTypeDeleter > duplicate_type_adapt_message_as_unique_ptr(const PublishedType &msg)
Duplicate a given type adapted message as a unique_ptr.
std::unique_ptr< ROSMessageType, ROSMessageTypeDeleter > create_ros_message_unique_ptr()
Return a new unique_ptr using the ROSMessageType of the publisher.
std::enable_if_t< rosidl_generator_traits::is_message< T >::value &&std::is_same< T, ROSMessageType >::value > publish(const T &msg)
Publish a message on the topic.
void publish(rclcpp::LoanedMessage< ROSMessageType, AllocatorT > &&loaned_msg)
Publish an instance of a LoanedMessage.
Encapsulation of Quality of Service settings.
This class performs intra process communication between nodes.
Pure virtual interface class for the NodeBase part of the Node API.
virtual RCLCPP_PUBLIC rclcpp::Context::SharedPtr get_context()=0
Return the context of the node.
RCL_PUBLIC RCL_WARN_UNUSED bool rcl_context_is_valid(const rcl_context_t *context)
Return true if the given context is currently valid, otherwise false.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publish_loaned_message(const rcl_publisher_t *publisher, void *ros_message, rmw_publisher_allocation_t *allocation)
Publish a loaned message on a topic using a publisher.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publish_serialized_message(const rcl_publisher_t *publisher, const rcl_serialized_message_t *serialized_message, rmw_publisher_allocation_t *allocation)
Publish a serialized message on a topic using a publisher.
RCL_PUBLIC RCL_WARN_UNUSED rcl_context_t * rcl_publisher_get_context(const rcl_publisher_t *publisher)
Return the context associated with this publisher.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publish(const rcl_publisher_t *publisher, const void *ros_message, rmw_publisher_allocation_t *allocation)
Publish a ROS message on a topic using a publisher.
RCL_PUBLIC bool rcl_publisher_is_valid_except_context(const rcl_publisher_t *publisher)
Return true if the publisher is valid except the context, otherwise false.
Encapsulates the non-global state of an init/shutdown cycle.
Structure containing optional configuration for Publishers.
Template structure used to adapt custom, user-defined types to ROS types.
#define RCL_RET_OK
Success return code.
rmw_serialized_message_t rcl_serialized_message_t
typedef for rmw_serialized_message_t;
#define RCL_RET_PUBLISHER_INVALID
Invalid rcl_publisher_t given return code.