Skip to content

Commit 6b321ed

Browse files
authored
Add non transform capabilities for intra-process (#1849)
That is, make it so that if both a publisher and a subscriber using intra-process and using TypeAdaptation are the same type, we don't need to convert to a ROS Message type on the publisher and from a ROS Message type before delivering to the subscriber. Instead, we store the original message type in the subscription buffer, and deliver it straight through to the subscriber. This has two main benefits: 1. It is better for performance; we are eliding unnecessary work. 2. We can use TypeAdaptation to pass custom handles (like hardware accelerator handles) between a publisher and subscriber. That means we can avoid unnecessary overhead when using a hardware accelerator, like synchronizing between the hardware accelerator and the main CPU. The main way this is accomplished is by causing the SubscriptionIntraProcessBuffer to store messages of the Subscribed Type (which in the case of a ROS message type subscriber is a ROS message type, but in the case of a TypeAdapter type is the custom type). When a publish with a Type Adapted type happens, it delays conversion of the message, and passes the message type from the user down into the IntraProcessManager. The IntraProcessManager checks to see if it can cast the SubscriptionBuffer to the custom type being published first. If it can, then it knows it can deliver the message directly into the SubscriptionBuffer with no conversion necessary. If it can't, it then sees if the SubscriptionBuffer is of a ROS message type. If it is, then it performs the conversion as necessary, and then stores it. In all cases, the Subscription is then triggered underneath so that the message will eventually be delivered by an executor. We also add tests to ensure that in the case where the publisher and subscriber and using the same type adapter, no conversion happens when delivering the message. Signed-off-by: Chris Lalancette <clalancette@openrobotics.org> Signed-off-by: Gonzalo de Pedro <gonzalo@depedro.com.ar>
1 parent 8093648 commit 6b321ed

13 files changed

+1603
-217
lines changed

rclcpp/include/rclcpp/any_subscription_callback.hpp

+104-36
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,22 @@ class AnySubscriptionCallback
476476
}
477477
}
478478

479+
std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>
480+
convert_custom_type_to_ros_message_unique_ptr(const SubscribedType & msg)
481+
{
482+
if constexpr (rclcpp::TypeAdapter<MessageT>::is_specialized::value) {
483+
auto ptr = ROSMessageTypeAllocatorTraits::allocate(ros_message_type_allocator_, 1);
484+
ROSMessageTypeAllocatorTraits::construct(ros_message_type_allocator_, ptr);
485+
rclcpp::TypeAdapter<MessageT>::convert_to_ros_message(msg, *ptr);
486+
return std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>(ptr, ros_message_type_deleter_);
487+
} else {
488+
static_assert(
489+
!sizeof(MessageT *),
490+
"convert_custom_type_to_ros_message_unique_ptr() "
491+
"unexpectedly called without specialized TypeAdapter");
492+
}
493+
}
494+
479495
// Dispatch when input is a ros message and the output could be anything.
480496
void
481497
dispatch(
@@ -658,7 +674,7 @@ class AnySubscriptionCallback
658674

659675
void
660676
dispatch_intra_process(
661-
std::shared_ptr<const ROSMessageType> message,
677+
std::shared_ptr<const SubscribedType> message,
662678
const rclcpp::MessageInfo & message_info)
663679
{
664680
TRACEPOINT(callback_start, static_cast<const void *>(this), true);
@@ -677,65 +693,89 @@ class AnySubscriptionCallback
677693

678694
// conditions for custom type
679695
if constexpr (is_ta && std::is_same_v<T, ConstRefCallback>) {
680-
auto local_message = convert_ros_message_to_custom_type_unique_ptr(*message);
681-
callback(*local_message);
696+
callback(*message);
682697
} else if constexpr (is_ta && std::is_same_v<T, ConstRefWithInfoCallback>) { // NOLINT
683-
auto local_message = convert_ros_message_to_custom_type_unique_ptr(*message);
684-
callback(*local_message, message_info);
698+
callback(*message, message_info);
685699
} else if constexpr ( // NOLINT[readability/braces]
686700
is_ta && (
687701
std::is_same_v<T, UniquePtrCallback>||
688702
std::is_same_v<T, SharedPtrCallback>
689703
))
690704
{
691-
callback(convert_ros_message_to_custom_type_unique_ptr(*message));
705+
callback(create_custom_unique_ptr_from_custom_shared_ptr_message(message));
692706
} else if constexpr ( // NOLINT[readability/braces]
693707
is_ta && (
694708
std::is_same_v<T, UniquePtrWithInfoCallback>||
695709
std::is_same_v<T, SharedPtrWithInfoCallback>
696710
))
697711
{
698-
callback(convert_ros_message_to_custom_type_unique_ptr(*message), message_info);
712+
callback(create_custom_unique_ptr_from_custom_shared_ptr_message(message), message_info);
699713
} else if constexpr ( // NOLINT[readability/braces]
700714
is_ta && (
701715
std::is_same_v<T, SharedConstPtrCallback>||
702716
std::is_same_v<T, ConstRefSharedConstPtrCallback>
703717
))
704718
{
705-
callback(convert_ros_message_to_custom_type_unique_ptr(*message));
719+
callback(message);
706720
} else if constexpr ( // NOLINT[readability/braces]
707721
is_ta && (
708722
std::is_same_v<T, SharedConstPtrWithInfoCallback>||
709723
std::is_same_v<T, ConstRefSharedConstPtrWithInfoCallback>
710724
))
711725
{
712-
callback(convert_ros_message_to_custom_type_unique_ptr(*message), message_info);
726+
callback(message, message_info);
713727
}
714728
// conditions for ros message type
715-
else if constexpr (std::is_same_v<T, ConstRefROSMessageCallback>) { // NOLINT
716-
callback(*message);
717-
} else if constexpr (std::is_same_v<T, ConstRefWithInfoROSMessageCallback>) {
718-
callback(*message, message_info);
729+
else if constexpr (std::is_same_v<T, ConstRefROSMessageCallback>) { // NOLINT[readability/braces]
730+
if constexpr (is_ta) {
731+
auto local = convert_custom_type_to_ros_message_unique_ptr(*message);
732+
callback(*local);
733+
} else {
734+
callback(*message);
735+
}
736+
} else if constexpr (std::is_same_v<T, ConstRefWithInfoROSMessageCallback>) { // NOLINT[readability/braces]
737+
if constexpr (is_ta) {
738+
auto local = convert_custom_type_to_ros_message_unique_ptr(*message);
739+
callback(*local, message_info);
740+
} else {
741+
callback(*message, message_info);
742+
}
719743
} else if constexpr ( // NOLINT[readability/braces]
720744
std::is_same_v<T, UniquePtrROSMessageCallback>||
721745
std::is_same_v<T, SharedPtrROSMessageCallback>)
722746
{
723-
callback(create_ros_unique_ptr_from_ros_shared_ptr_message(message));
747+
if constexpr (is_ta) {
748+
callback(convert_custom_type_to_ros_message_unique_ptr(*message));
749+
} else {
750+
callback(create_ros_unique_ptr_from_ros_shared_ptr_message(message));
751+
}
724752
} else if constexpr ( // NOLINT[readability/braces]
725753
std::is_same_v<T, UniquePtrWithInfoROSMessageCallback>||
726754
std::is_same_v<T, SharedPtrWithInfoROSMessageCallback>)
727755
{
728-
callback(create_ros_unique_ptr_from_ros_shared_ptr_message(message), message_info);
756+
if constexpr (is_ta) {
757+
callback(convert_custom_type_to_ros_message_unique_ptr(*message), message_info);
758+
} else {
759+
callback(create_ros_unique_ptr_from_ros_shared_ptr_message(message), message_info);
760+
}
729761
} else if constexpr ( // NOLINT[readability/braces]
730762
std::is_same_v<T, SharedConstPtrROSMessageCallback>||
731763
std::is_same_v<T, ConstRefSharedConstPtrROSMessageCallback>)
732764
{
733-
callback(message);
765+
if constexpr (is_ta) {
766+
callback(convert_custom_type_to_ros_message_unique_ptr(*message));
767+
} else {
768+
callback(message);
769+
}
734770
} else if constexpr ( // NOLINT[readability/braces]
735771
std::is_same_v<T, SharedConstPtrWithInfoROSMessageCallback>||
736772
std::is_same_v<T, ConstRefSharedConstPtrWithInfoROSMessageCallback>)
737773
{
738-
callback(message, message_info);
774+
if constexpr (is_ta) {
775+
callback(convert_custom_type_to_ros_message_unique_ptr(*message), message_info);
776+
} else {
777+
callback(message, message_info);
778+
}
739779
}
740780
// condition to catch SerializedMessage types
741781
else if constexpr ( // NOLINT[readability/braces]
@@ -764,7 +804,7 @@ class AnySubscriptionCallback
764804

765805
void
766806
dispatch_intra_process(
767-
std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter> message,
807+
std::unique_ptr<SubscribedType, SubscribedTypeDeleter> message,
768808
const rclcpp::MessageInfo & message_info)
769809
{
770810
TRACEPOINT(callback_start, static_cast<const void *>(this), true);
@@ -778,70 +818,98 @@ class AnySubscriptionCallback
778818
// Dispatch.
779819
std::visit(
780820
[&message, &message_info, this](auto && callback) {
821+
// clang complains that 'this' lambda capture is unused, which is true
822+
// in *some* specializations of this template, but not others. Just
823+
// quiet it down.
824+
(void)this;
825+
781826
using T = std::decay_t<decltype(callback)>;
782827
static constexpr bool is_ta = rclcpp::TypeAdapter<MessageT>::is_specialized::value;
783828

784829
// conditions for custom type
785830
if constexpr (is_ta && std::is_same_v<T, ConstRefCallback>) {
786-
auto local_message = convert_ros_message_to_custom_type_unique_ptr(*message);
787-
callback(*local_message);
831+
callback(*message);
788832
} else if constexpr (is_ta && std::is_same_v<T, ConstRefWithInfoCallback>) { // NOLINT
789-
auto local_message = convert_ros_message_to_custom_type_unique_ptr(*message);
790-
callback(*local_message, message_info);
833+
callback(*message, message_info);
791834
} else if constexpr ( // NOLINT[readability/braces]
792835
is_ta && (
793836
std::is_same_v<T, UniquePtrCallback>||
794-
std::is_same_v<T, SharedPtrCallback>
795-
))
837+
std::is_same_v<T, SharedPtrCallback>))
796838
{
797-
callback(convert_ros_message_to_custom_type_unique_ptr(*message));
839+
callback(std::move(message));
798840
} else if constexpr ( // NOLINT[readability/braces]
799841
is_ta && (
800842
std::is_same_v<T, UniquePtrWithInfoCallback>||
801843
std::is_same_v<T, SharedPtrWithInfoCallback>
802844
))
803845
{
804-
callback(convert_ros_message_to_custom_type_unique_ptr(*message), message_info);
846+
callback(std::move(message), message_info);
805847
} else if constexpr ( // NOLINT[readability/braces]
806848
is_ta && (
807849
std::is_same_v<T, SharedConstPtrCallback>||
808850
std::is_same_v<T, ConstRefSharedConstPtrCallback>
809851
))
810852
{
811-
callback(convert_ros_message_to_custom_type_unique_ptr(*message));
853+
callback(std::move(message));
812854
} else if constexpr ( // NOLINT[readability/braces]
813855
is_ta && (
814856
std::is_same_v<T, SharedConstPtrWithInfoCallback>||
815857
std::is_same_v<T, ConstRefSharedConstPtrWithInfoCallback>
816858
))
817859
{
818-
callback(convert_ros_message_to_custom_type_unique_ptr(*message), message_info);
860+
callback(std::move(message), message_info);
819861
}
820862
// conditions for ros message type
821-
else if constexpr (std::is_same_v<T, ConstRefROSMessageCallback>) { // NOLINT
822-
callback(*message);
823-
} else if constexpr (std::is_same_v<T, ConstRefWithInfoROSMessageCallback>) {
824-
callback(*message, message_info);
863+
else if constexpr (std::is_same_v<T, ConstRefROSMessageCallback>) { // NOLINT[readability/braces]
864+
if constexpr (is_ta) {
865+
auto local = convert_custom_type_to_ros_message_unique_ptr(*message);
866+
callback(*local);
867+
} else {
868+
callback(*message);
869+
}
870+
} else if constexpr (std::is_same_v<T, ConstRefWithInfoROSMessageCallback>) { // NOLINT[readability/braces]
871+
if constexpr (is_ta) {
872+
auto local = convert_custom_type_to_ros_message_unique_ptr(*message);
873+
callback(*local, message_info);
874+
} else {
875+
callback(*message, message_info);
876+
}
825877
} else if constexpr ( // NOLINT[readability/braces]
826878
std::is_same_v<T, UniquePtrROSMessageCallback>||
827879
std::is_same_v<T, SharedPtrROSMessageCallback>)
828880
{
829-
callback(std::move(message));
881+
if constexpr (is_ta) {
882+
callback(convert_custom_type_to_ros_message_unique_ptr(*message));
883+
} else {
884+
callback(std::move(message));
885+
}
830886
} else if constexpr ( // NOLINT[readability/braces]
831887
std::is_same_v<T, UniquePtrWithInfoROSMessageCallback>||
832888
std::is_same_v<T, SharedPtrWithInfoROSMessageCallback>)
833889
{
834-
callback(std::move(message), message_info);
890+
if constexpr (is_ta) {
891+
callback(convert_custom_type_to_ros_message_unique_ptr(*message), message_info);
892+
} else {
893+
callback(std::move(message), message_info);
894+
}
835895
} else if constexpr ( // NOLINT[readability/braces]
836896
std::is_same_v<T, SharedConstPtrROSMessageCallback>||
837897
std::is_same_v<T, ConstRefSharedConstPtrROSMessageCallback>)
838898
{
839-
callback(std::move(message));
899+
if constexpr (is_ta) {
900+
callback(convert_custom_type_to_ros_message_unique_ptr(*message));
901+
} else {
902+
callback(std::move(message));
903+
}
840904
} else if constexpr ( // NOLINT[readability/braces]
841905
std::is_same_v<T, SharedConstPtrWithInfoROSMessageCallback>||
842906
std::is_same_v<T, ConstRefSharedConstPtrWithInfoROSMessageCallback>)
843907
{
844-
callback(std::move(message), message_info);
908+
if constexpr (is_ta) {
909+
callback(convert_custom_type_to_ros_message_unique_ptr(*message), message_info);
910+
} else {
911+
callback(std::move(message), message_info);
912+
}
845913
}
846914
// condition to catch SerializedMessage types
847915
else if constexpr ( // NOLINT[readability/braces]

0 commit comments

Comments
 (0)