15 #ifndef RCLCPP__SUBSCRIPTION_HPP_
16 #define RCLCPP__SUBSCRIPTION_HPP_
18 #include <rmw/error_handling.h>
26 #include "rcl/error_handling.h"
29 #include "rclcpp/any_subscription_callback.hpp"
30 #include "rclcpp/detail/resolve_use_intra_process.hpp"
31 #include "rclcpp/detail/resolve_intra_process_buffer_type.hpp"
32 #include "rclcpp/exceptions.hpp"
33 #include "rclcpp/expand_topic_or_service_name.hpp"
34 #include "rclcpp/experimental/intra_process_manager.hpp"
35 #include "rclcpp/experimental/subscription_intra_process.hpp"
36 #include "rclcpp/logging.hpp"
37 #include "rclcpp/macros.hpp"
38 #include "rclcpp/message_info.hpp"
39 #include "rclcpp/message_memory_strategy.hpp"
40 #include "rclcpp/node_interfaces/node_base_interface.hpp"
41 #include "rclcpp/subscription_base.hpp"
42 #include "rclcpp/subscription_options.hpp"
43 #include "rclcpp/type_support_decl.hpp"
44 #include "rclcpp/visibility_control.hpp"
45 #include "rclcpp/waitable.hpp"
46 #include "tracetools/tracetools.h"
51 namespace node_interfaces
53 class NodeTopicsInterface;
59 typename AllocatorT = std::allocator<void>,
62 typename SubscribedT =
typename rclcpp::TypeAdapter<MessageT>::custom_type,
65 typename ROSMessageT =
typename rclcpp::TypeAdapter<MessageT>::ros_message_type,
76 using SubscribedType = SubscribedT;
77 using ROSMessageType = ROSMessageT;
78 using MessageMemoryStrategyType = MessageMemoryStrategyT;
80 using SubscribedTypeAllocatorTraits = allocator::AllocRebind<SubscribedType, AllocatorT>;
81 using SubscribedTypeAllocator =
typename SubscribedTypeAllocatorTraits::allocator_type;
82 using SubscribedTypeDeleter = allocator::Deleter<SubscribedTypeAllocator, SubscribedType>;
84 using ROSMessageTypeAllocatorTraits = allocator::AllocRebind<ROSMessageType, AllocatorT>;
85 using ROSMessageTypeAllocator =
typename ROSMessageTypeAllocatorTraits::allocator_type;
86 using ROSMessageTypeDeleter = allocator::Deleter<ROSMessageTypeAllocator, ROSMessageType>;
110 rclcpp::node_interfaces::NodeBaseInterface * node_base,
111 const rosidl_message_type_support_t & type_support_handle,
112 const std::
string & topic_name,
116 typename MessageMemoryStrategyT::SharedPtr message_memory_strategy)
121 options.to_rcl_subscription_options(qos),
123 options.event_callbacks,
124 options.use_default_callbacks,
126 any_callback_(callback),
128 message_memory_strategy_(message_memory_strategy)
132 if (rclcpp::detail::resolve_use_intra_process(options_, *node_base)) {
133 using rclcpp::detail::resolve_intra_process_buffer_type;
137 if (qos_profile.history() != rclcpp::HistoryPolicy::KeepLast) {
138 throw std::invalid_argument(
139 "intraprocess communication on topic '" + topic_name +
140 "' allowed only with keep last history qos policy");
142 if (qos_profile.depth() == 0) {
143 throw std::invalid_argument(
144 "intraprocess communication on topic '" + topic_name +
145 "' is not allowed with 0 depth qos policy");
151 SubscribedTypeAllocator,
152 SubscribedTypeDeleter,
157 auto context = node_base->get_context();
158 subscription_intra_process_ = std::make_shared<SubscriptionIntraProcessT>(
160 options_.get_allocator(),
162 this->get_topic_name(),
164 resolve_intra_process_buffer_type(options_.intra_process_buffer_type, callback));
165 TRACETOOLS_TRACEPOINT(
166 rclcpp_subscription_init,
167 static_cast<const void *
>(get_subscription_handle().get()),
168 static_cast<const void *
>(subscription_intra_process_.get()));
172 auto ipm = context->get_sub_context<IntraProcessManager>();
173 uint64_t intra_process_subscription_id = ipm->template add_subscription<
174 ROSMessageType, ROSMessageTypeAllocator>(subscription_intra_process_);
178 TRACETOOLS_TRACEPOINT(
179 rclcpp_subscription_init,
180 static_cast<const void *
>(get_subscription_handle().get()),
181 static_cast<const void *
>(
this));
182 TRACETOOLS_TRACEPOINT(
183 rclcpp_subscription_callback_added,
184 static_cast<const void *
>(
this),
185 static_cast<const void *
>(&any_callback_));
189 #ifndef TRACETOOLS_DISABLED
190 any_callback_.register_callback_for_tracing();
225 return this->
take_type_erased(
static_cast<void *
>(&message_out), message_info_out);
235 template<
typename TakeT>
237 !rosidl_generator_traits::is_message<TakeT>::value &&
238 std::is_same_v<TakeT, SubscribedType>,
243 ROSMessageType local_message;
244 bool taken = this->
take_type_erased(
static_cast<void *
>(&local_message), message_info_out);
251 std::shared_ptr<void>
258 return message_memory_strategy_->borrow_message();
261 std::shared_ptr<rclcpp::SerializedMessage>
264 return message_memory_strategy_->borrow_serialized_message();
280 any_callback_.disable();
281 if (subscription_intra_process_) {
282 subscription_intra_process_->disable_callbacks();
284 for (
const auto & [_, event_ptr] : event_handlers_) {
286 event_ptr->disable();
300 any_callback_.enable();
301 if (subscription_intra_process_) {
302 subscription_intra_process_->enable_callbacks();
304 for (
const auto & [_, event_ptr] : event_handlers_) {
313 std::shared_ptr<void> & message,
321 auto typed_message = std::static_pointer_cast<ROSMessageType>(message);
322 any_callback_.dispatch(typed_message, message_info);
326 handle_serialized_message(
327 const std::shared_ptr<rclcpp::SerializedMessage> & serialized_message,
330 any_callback_.dispatch(serialized_message, message_info);
334 handle_loaned_message(
335 void * loaned_message,
344 auto typed_message =
static_cast<ROSMessageType *
>(loaned_message);
346 auto sptr = std::shared_ptr<ROSMessageType>(
347 typed_message, [](ROSMessageType * msg) {(void) msg;});
348 any_callback_.dispatch(sptr, message_info);
358 auto typed_message = std::static_pointer_cast<ROSMessageType>(message);
359 message_memory_strategy_->return_message(typed_message);
369 message_memory_strategy_->return_serialized_message(message);
373 use_take_shared_method()
const
375 return any_callback_.use_take_shared_method();
381 rclcpp::dynamic_typesupport::DynamicMessageType::SharedPtr
382 get_shared_dynamic_message_type()
override
385 "get_shared_dynamic_message_type is not implemented for Subscription");
388 rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr
389 get_shared_dynamic_message()
override
392 "get_shared_dynamic_message is not implemented for Subscription");
395 rclcpp::dynamic_typesupport::DynamicSerializationSupport::SharedPtr
396 get_shared_dynamic_serialization_support()
override
399 "get_shared_dynamic_serialization_support is not implemented for Subscription");
402 rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr
406 "create_dynamic_message is not implemented for Subscription");
410 return_dynamic_message(
411 [[maybe_unused]] rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message)
override
414 "return_dynamic_message is not implemented for Subscription");
418 handle_dynamic_message(
419 [[maybe_unused]]
const rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message,
423 "handle_dynamic_message is not implemented for Subscription");
429 AnySubscriptionCallback<MessageT, AllocatorT> any_callback_;
436 typename message_memory_strategy::MessageMemoryStrategy<ROSMessageType, AllocatorT>::SharedPtr
437 message_memory_strategy_;
Additional meta data about messages taken from subscriptions.
const rmw_message_info_t & get_rmw_message_info() const
Return the message info as the underlying rmw message info type.
Encapsulation of Quality of Service settings.
RCLCPP_PUBLIC rclcpp::QoS get_actual_qos() const
Get the actual QoS settings, after the defaults have been determined.
virtual RCLCPP_PUBLIC void enable_callbacks()
Enable the callbacks to be called.
RCLCPP_PUBLIC void setup_intra_process(uint64_t intra_process_subscription_id, IntraProcessManagerWeakPtr weak_ipm)
Implemenation detail.
virtual RCLCPP_PUBLIC void disable_callbacks()
Disable callbacks from being called.
RCLCPP_PUBLIC bool take_type_erased(void *message_out, rclcpp::MessageInfo &message_info_out)
Take the next inter-process message from the subscription as a type erased pointer.
Subscription implementation, templated on the type of message this subscription receives.
std::enable_if_t< !rosidl_generator_traits::is_message< TakeT >::value &&std::is_same_v< TakeT, SubscribedType >, bool > take(TakeT &message_out, rclcpp::MessageInfo &message_info_out)
Take the next message from the inter-process subscription.
void enable_callbacks() override
Enable the callbacks to be called.
void disable_callbacks() override
Disable callbacks from being called.
void return_serialized_message(std::shared_ptr< rclcpp::SerializedMessage > &message) override
Return the borrowed serialized message.
std::shared_ptr< rclcpp::SerializedMessage > create_serialized_message() override
Borrow a new serialized message.
Subscription(rclcpp::node_interfaces::NodeBaseInterface *node_base, const rosidl_message_type_support_t &type_support_handle, const std::string &topic_name, const rclcpp::QoS &qos, AnySubscriptionCallback< MessageT, AllocatorT > callback, const rclcpp::SubscriptionOptionsWithAllocator< AllocatorT > &options, typename MessageMemoryStrategyT::SharedPtr message_memory_strategy)
Default constructor.
void return_message(std::shared_ptr< void > &message) override
Return the borrowed message.
rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr create_dynamic_message() override
Borrow a new serialized message (this clones!)
void post_init_setup([[maybe_unused]] rclcpp::node_interfaces::NodeBaseInterface *node_base, [[maybe_unused]] const rclcpp::QoS &qos, [[maybe_unused]] const rclcpp::SubscriptionOptionsWithAllocator< AllocatorT > &options)
Called after construction to continue setup that requires shared_from_this().
void handle_message(std::shared_ptr< void > &message, const rclcpp::MessageInfo &message_info) override
Check if we need to handle the message, and execute the callback if we do.
std::shared_ptr< void > create_message() override
Borrow a new message.
bool take(ROSMessageType &message_out, rclcpp::MessageInfo &message_info_out)
Take the next message from the inter-process subscription.
This class performs intra process communication between nodes.
Default allocation strategy for messages received by subscriptions.
Pure virtual interface class for the NodeBase part of the Node API.
Pure virtual interface class for the NodeTopics part of the Node API.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
DeliveredMessageKind
The kind of message that the subscription delivers in its callback, used by the executor.
Structure containing optional configuration for Subscriptions.
Template structure used to adapt custom, user-defined types to ROS types.