ROS 2 rclcpp + rcl - rolling  rolling-20536064
ROS 2 C++ Client Library with ROS Client Library
subscription_base.hpp
1 // Copyright 2019 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__SUBSCRIPTION_BASE_HPP_
16 #define RCLCPP__SUBSCRIPTION_BASE_HPP_
17 
18 #include <atomic>
19 #include <memory>
20 #include <mutex>
21 #include <string>
22 #include <unordered_map>
23 #include <utility>
24 #include <vector>
25 
26 #include "rcl/event_callback.h"
27 #include "rcl/subscription.h"
28 
29 #include "rmw/rmw.h"
30 
31 #include "rclcpp/any_subscription_callback.hpp"
32 #include "rclcpp/dynamic_typesupport/dynamic_message.hpp"
33 #include "rclcpp/dynamic_typesupport/dynamic_message_type.hpp"
34 #include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp"
35 #include "rclcpp/experimental/intra_process_manager.hpp"
36 #include "rclcpp/experimental/subscription_intra_process_base.hpp"
37 #include "rclcpp/logger.hpp"
38 #include "rclcpp/macros.hpp"
39 #include "rclcpp/message_info.hpp"
40 #include "rclcpp/network_flow_endpoint.hpp"
41 #include "rclcpp/qos.hpp"
42 #include "rclcpp/event_handler.hpp"
43 #include "rclcpp/serialized_message.hpp"
44 #include "rclcpp/subscription_content_filter_options.hpp"
45 #include "rclcpp/type_support_decl.hpp"
46 #include "rclcpp/visibility_control.hpp"
47 
48 namespace rclcpp
49 {
50 
51 namespace node_interfaces
52 {
53 class NodeBaseInterface;
54 } // namespace node_interfaces
55 
56 namespace experimental
57 {
62 class IntraProcessManager;
63 } // namespace experimental
64 
66 
78 enum class DeliveredMessageKind : uint8_t
79 {
80  INVALID = 0,
81  ROS_MESSAGE = 1, // The subscription delivers a ROS message to its callback
82  SERIALIZED_MESSAGE = 2, // The subscription delivers a serialized message to its callback
83  DYNAMIC_MESSAGE = 3, // The subscription delivers a dynamic message to its callback
84 };
85 
88 class SubscriptionBase : public std::enable_shared_from_this<SubscriptionBase>
89 {
90 public:
91  RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(SubscriptionBase)
92 
93 
105  RCLCPP_PUBLIC
108  const rosidl_message_type_support_t & type_support_handle,
109  const std::string & topic_name,
110  const rcl_subscription_options_t & subscription_options,
111  const SubscriptionEventCallbacks & event_callbacks,
112  bool use_default_callbacks,
113  DeliveredMessageKind delivered_message_kind = DeliveredMessageKind::ROS_MESSAGE);
114 
116  RCLCPP_PUBLIC
117  virtual ~SubscriptionBase();
118 
120 
129  RCLCPP_PUBLIC
130  static
131  bool
133 
135  RCLCPP_PUBLIC
136  void
138  const SubscriptionEventCallbacks & event_callbacks, bool use_default_callbacks);
139 
141  RCLCPP_PUBLIC
142  const char *
143  get_topic_name() const;
144 
145  RCLCPP_PUBLIC
146  std::shared_ptr<rcl_subscription_t>
147  get_subscription_handle();
148 
149  RCLCPP_PUBLIC
150  std::shared_ptr<const rcl_subscription_t>
151  get_subscription_handle() const;
152 
154 
155  RCLCPP_PUBLIC
156  const
157  std::unordered_map<rcl_subscription_event_type_t, std::shared_ptr<rclcpp::EventHandlerBase>> &
158  get_event_handlers() const;
159 
161 
172  RCLCPP_PUBLIC
174  get_actual_qos() const;
175 
177 
193  RCLCPP_PUBLIC
194  bool
195  take_type_erased(void * message_out, rclcpp::MessageInfo & message_info_out);
196 
198 
211  RCLCPP_PUBLIC
212  bool
213  take_serialized(rclcpp::SerializedMessage & message_out, rclcpp::MessageInfo & message_info_out);
214 
216 
217  RCLCPP_PUBLIC
218  virtual
219  std::shared_ptr<void>
221 
223 
224  RCLCPP_PUBLIC
225  virtual
226  std::shared_ptr<rclcpp::SerializedMessage>
228 
230 
233  RCLCPP_PUBLIC
234  virtual
235  void disable_callbacks();
236 
238 
242  RCLCPP_PUBLIC
243  virtual
244  void enable_callbacks();
245 
247 
251  RCLCPP_PUBLIC
252  virtual
253  void
254  handle_message(std::shared_ptr<void> & message, const rclcpp::MessageInfo & message_info) = 0;
255 
256  RCLCPP_PUBLIC
257  virtual
258  void
259  handle_serialized_message(
260  const std::shared_ptr<rclcpp::SerializedMessage> & serialized_message,
261  const rclcpp::MessageInfo & message_info) = 0;
262 
263  RCLCPP_PUBLIC
264  virtual
265  void
266  handle_loaned_message(void * loaned_message, const rclcpp::MessageInfo & message_info) = 0;
267 
269 
270  RCLCPP_PUBLIC
271  virtual
272  void
273  return_message(std::shared_ptr<void> & message) = 0;
274 
276 
277  RCLCPP_PUBLIC
278  virtual
279  void
280  return_serialized_message(std::shared_ptr<rclcpp::SerializedMessage> & message) = 0;
281 
282  RCLCPP_PUBLIC
283  const rosidl_message_type_support_t &
284  get_message_type_support_handle() const;
285 
287 
290  RCLCPP_PUBLIC
291  bool
292  is_serialized() const;
293 
295 
298  RCLCPP_PUBLIC
301 
303 
304  RCLCPP_PUBLIC
305  size_t
306  get_publisher_count() const;
307 
309 
315  RCLCPP_PUBLIC
316  bool
317  can_loan_messages() const;
318 
319  using IntraProcessManagerWeakPtr =
320  std::weak_ptr<rclcpp::experimental::IntraProcessManager>;
321 
323  RCLCPP_PUBLIC
324  void
326  uint64_t intra_process_subscription_id,
327  IntraProcessManagerWeakPtr weak_ipm);
328 
330 
334  RCLCPP_PUBLIC
335  rclcpp::Waitable::SharedPtr
337 
339 
351  RCLCPP_PUBLIC
352  bool
353  exchange_in_use_by_wait_set_state(void * pointer_to_subscription_part, bool in_use_state);
354 
356 
360  RCLCPP_PUBLIC
361  std::vector<rclcpp::NetworkFlowEndpoint>
363 
365 
388  RCLCPP_PUBLIC
389  void
390  set_on_new_message_callback(const std::function<void(size_t)> & callback);
391 
393  RCLCPP_PUBLIC
394  void
396 
398 
415  RCLCPP_PUBLIC
416  void
417  set_on_new_intra_process_message_callback(const std::function<void(size_t)> & callback);
418 
420  RCLCPP_PUBLIC
421  void
423 
425 
450  RCLCPP_PUBLIC
451  void
453  const std::function<void(size_t)> & callback,
454  rcl_subscription_event_type_t event_type);
455 
457  RCLCPP_PUBLIC
458  void
460 
462 
466  RCLCPP_PUBLIC
467  bool
468  is_cft_supported() const;
469 
471 
474  RCLCPP_PUBLIC
475  bool
476  is_cft_enabled() const;
477 
479 
488  RCLCPP_PUBLIC
489  void
491  const std::string & filter_expression,
492  const std::vector<std::string> & expression_parameters = {});
493 
495 
500  RCLCPP_PUBLIC
502  get_content_filter() const;
503 
504  // DYNAMIC TYPE ==================================================================================
505  // TODO(methylDragon): Reorder later
506  RCLCPP_PUBLIC
507  virtual
508  rclcpp::dynamic_typesupport::DynamicMessageType::SharedPtr
509  get_shared_dynamic_message_type() = 0;
510 
511  RCLCPP_PUBLIC
512  virtual
513  rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr
514  get_shared_dynamic_message() = 0;
515 
516  RCLCPP_PUBLIC
517  virtual
518  rclcpp::dynamic_typesupport::DynamicSerializationSupport::SharedPtr
519  get_shared_dynamic_serialization_support() = 0;
520 
522 
523  RCLCPP_PUBLIC
524  virtual
525  rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr
527 
528  RCLCPP_PUBLIC
529  virtual
530  void
531  return_dynamic_message(rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message) = 0;
532 
533  RCLCPP_PUBLIC
534  virtual
535  void
536  handle_dynamic_message(
537  const rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message,
538  const rclcpp::MessageInfo & message_info) = 0;
539 
540  RCLCPP_PUBLIC
541  bool
542  take_dynamic_message(
544  rclcpp::MessageInfo & message_info_out);
545  // ===============================================================================================
546 
547 protected:
548  template<typename EventCallbackT>
549  void
550  add_event_handler(
551  const EventCallbackT & callback,
552  const rcl_subscription_event_type_t event_type)
553  {
554  auto handler = std::make_shared<EventHandler<EventCallbackT,
555  std::shared_ptr<rcl_subscription_t>>>(
556  callback,
558  get_subscription_handle(),
559  event_type);
560  qos_events_in_use_by_wait_set_.insert(std::make_pair(handler.get(), false));
561  event_handlers_.insert(std::make_pair(event_type, handler));
562  }
563 
564  RCLCPP_PUBLIC
565  void default_incompatible_qos_callback(QOSRequestedIncompatibleQoSInfo & info) const;
566 
567  RCLCPP_PUBLIC
568  void default_incompatible_type_callback(IncompatibleTypeInfo & info) const;
569 
570  RCLCPP_PUBLIC
571  bool
572  matches_any_intra_process_publishers(const rmw_gid_t * sender_gid) const;
573 
574  RCLCPP_PUBLIC
575  void
576  set_on_new_message_callback(rcl_event_callback_t callback, const void * user_data);
577 
579 
580  std::shared_ptr<rcl_node_t> node_handle_;
581 
582  std::recursive_mutex on_new_message_callback_mutex_;
583  // It is important to declare on_new_message_callback_ before
584  // subscription_handle_, so on destruction the subscription is
585  // destroyed first. Otherwise, the rmw subscription callback
586  // would point briefly to a destroyed function.
587  std::function<void(size_t)> on_new_message_callback_{nullptr};
588  // Declare subscription_handle_ after callback
589  std::shared_ptr<rcl_subscription_t> subscription_handle_;
590  std::shared_ptr<rcl_subscription_t> intra_process_subscription_handle_;
591  rclcpp::Logger node_logger_;
592 
593  std::unordered_map<rcl_subscription_event_type_t,
594  std::shared_ptr<rclcpp::EventHandlerBase>> event_handlers_;
595 
596  bool use_intra_process_;
597  IntraProcessManagerWeakPtr weak_ipm_;
598  uint64_t intra_process_subscription_id_;
599  std::shared_ptr<rclcpp::experimental::SubscriptionIntraProcessBase> subscription_intra_process_;
600 
601  const SubscriptionEventCallbacks event_callbacks_;
602 
603 private:
604  RCLCPP_DISABLE_COPY(SubscriptionBase)
605 
606  rosidl_message_type_support_t type_support_;
607  DeliveredMessageKind delivered_message_kind_;
608 
609  std::atomic<bool> subscription_in_use_by_wait_set_{false};
610  std::atomic<bool> intra_process_subscription_waitable_in_use_by_wait_set_{false};
611  std::unordered_map<rclcpp::EventHandlerBase *,
612  std::atomic<bool>> qos_events_in_use_by_wait_set_;
613 };
614 
615 } // namespace rclcpp
616 
617 #endif // RCLCPP__SUBSCRIPTION_BASE_HPP_
Additional meta data about messages taken from subscriptions.
Encapsulation of Quality of Service settings.
Definition: qos.hpp:114
Object oriented version of rcl_serialized_message_t with destructor to avoid memory leaks.
virtual RCLCPP_PUBLIC std::shared_ptr< void > create_message()=0
Borrow a new message.
RCLCPP_PUBLIC size_t get_publisher_count() const
Get matching publisher count.
virtual RCLCPP_PUBLIC rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr create_dynamic_message()=0
Borrow a new serialized message (this clones!)
RCLCPP_PUBLIC rclcpp::QoS get_actual_qos() const
Get the actual QoS settings, after the defaults have been determined.
RCLCPP_PUBLIC void set_on_new_message_callback(const std::function< void(size_t)> &callback)
Set a callback to be called when each new message is received.
RCLCPP_PUBLIC void clear_on_new_message_callback()
Unset the callback registered for new messages, if any.
virtual RCLCPP_PUBLIC void handle_message(std::shared_ptr< void > &message, const rclcpp::MessageInfo &message_info)=0
Check if we need to handle the message, and execute the callback if we do.
RCLCPP_PUBLIC void set_on_new_qos_event_callback(const std::function< void(size_t)> &callback, rcl_subscription_event_type_t event_type)
Set a callback to be called when each new qos event instance occurs.
virtual RCLCPP_PUBLIC void enable_callbacks()
Enable the callbacks to be called.
RCLCPP_PUBLIC bool can_loan_messages() const
Check if subscription instance can loan messages.
static RCLCPP_PUBLIC bool event_type_is_supported(const rcl_subscription_event_type_t event_type)
Check if a subscription event type is supported by the active RMW implementation.
RCLCPP_PUBLIC bool is_cft_supported() const
Check if content filtered topic feature of the subscription instance is supported.
RCLCPP_PUBLIC rclcpp::Waitable::SharedPtr get_intra_process_waitable() const
Return the waitable for intra-process.
RCLCPP_PUBLIC std::vector< rclcpp::NetworkFlowEndpoint > get_network_flow_endpoints() const
Get network flow endpoints.
RCLCPP_PUBLIC void setup_intra_process(uint64_t intra_process_subscription_id, IntraProcessManagerWeakPtr weak_ipm)
Implemenation detail.
RCLCPP_PUBLIC DeliveredMessageKind get_delivered_message_kind() const
Return the delivered message kind.
virtual RCLCPP_PUBLIC void return_message(std::shared_ptr< void > &message)=0
Return the message borrowed in create_message.
RCLCPP_PUBLIC void set_on_new_intra_process_message_callback(const std::function< void(size_t)> &callback)
Set a callback to be called when each new intra-process message is received.
virtual RCLCPP_PUBLIC void disable_callbacks()
Disable callbacks from being called.
virtual RCLCPP_PUBLIC std::shared_ptr< rclcpp::SerializedMessage > create_serialized_message()=0
Borrow a new serialized message.
RCLCPP_PUBLIC void clear_on_new_qos_event_callback(rcl_subscription_event_type_t event_type)
Unset the callback registered for new qos events, if any.
RCLCPP_PUBLIC bool take_serialized(rclcpp::SerializedMessage &message_out, rclcpp::MessageInfo &message_info_out)
Take the next inter-process message, in its serialized form, from the subscription.
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.
RCLCPP_PUBLIC bool exchange_in_use_by_wait_set_state(void *pointer_to_subscription_part, bool in_use_state)
Exchange state of whether or not a part of the subscription is used by a wait set.
RCLCPP_PUBLIC void set_content_filter(const std::string &filter_expression, const std::vector< std::string > &expression_parameters={})
Set the filter expression and expression parameters for the subscription.
virtual RCLCPP_PUBLIC ~SubscriptionBase()
Destructor.
RCLCPP_PUBLIC SubscriptionBase(rclcpp::node_interfaces::NodeBaseInterface *node_base, const rosidl_message_type_support_t &type_support_handle, const std::string &topic_name, const rcl_subscription_options_t &subscription_options, const SubscriptionEventCallbacks &event_callbacks, bool use_default_callbacks, DeliveredMessageKind delivered_message_kind=DeliveredMessageKind::ROS_MESSAGE)
Constructor.
virtual RCLCPP_PUBLIC void return_serialized_message(std::shared_ptr< rclcpp::SerializedMessage > &message)=0
Return the message borrowed in create_serialized_message.
RCLCPP_PUBLIC bool is_cft_enabled() const
Check if content filtered topic feature of the subscription instance is enabled.
RCLCPP_PUBLIC void bind_event_callbacks(const SubscriptionEventCallbacks &event_callbacks, bool use_default_callbacks)
Add event handlers for passed in event_callbacks.
RCLCPP_PUBLIC const std::unordered_map< rcl_subscription_event_type_t, std::shared_ptr< rclcpp::EventHandlerBase > > & get_event_handlers() const
Get all the QoS event handlers associated with this subscription.
RCLCPP_PUBLIC void clear_on_new_intra_process_message_callback()
Unset the callback registered for new intra-process messages, if any.
RCLCPP_PUBLIC rclcpp::ContentFilterOptions get_content_filter() const
Get the filter expression and expression parameters for the subscription.
RCLCPP_PUBLIC bool is_serialized() const
Return if the subscription is serialized.
RCLCPP_PUBLIC const char * get_topic_name() const
Get the topic that this subscription is subscribed on.
Pure virtual interface class for the NodeBase part of the Node API.
enum rcl_subscription_event_type_e rcl_subscription_event_type_t
Enumeration of all of the subscription events that may fire.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_subscription_event_init(rcl_event_t *event, const rcl_subscription_t *subscription, const rcl_subscription_event_type_t event_type)
Initialize an rcl_event_t with a subscription.
Definition: event.c:101
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.
Options available for a rcl subscription.
Definition: subscription.h:47
Options to configure content filtered topic in the subscription.
Contains callbacks for non-message events that a Subscription can receive from the middleware.