-
Notifications
You must be signed in to change notification settings - Fork 418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add rclcpp_generic, a publisher and subscription for serialized messages #1452
Changes from all commits
06e9272
93fc497
83be9dc
513c1b8
1481f81
4a8bfbc
8e923ee
4b82f3a
aa9f827
f41f738
ff8c8ef
9a2607e
d02fd9d
be8eea8
b7c8a26
fb39f2e
66cca2a
e338ceb
221efa6
6d816a2
ee68c11
78b2fc2
1fabb9a
eb3c70e
3a2ee61
a90c915
3a6aad4
fb5af58
4f26f36
9450c3d
2ec829b
7c18bdc
9c6f0ed
dc4ddbb
dc347c9
34d7316
f5d8d14
f585d66
be5453c
66468bf
e584230
3541fe6
5742f7d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright 2020, Apex.AI Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#ifndef RCLCPP__CREATE_GENERIC_PUBLISHER_HPP_ | ||
#define RCLCPP__CREATE_GENERIC_PUBLISHER_HPP_ | ||
|
||
#include <memory> | ||
#include <string> | ||
#include <utility> | ||
|
||
#include "rclcpp/generic_publisher.hpp" | ||
#include "rclcpp/node_interfaces/node_topics_interface.hpp" | ||
#include "rclcpp/publisher_options.hpp" | ||
#include "rclcpp/qos.hpp" | ||
#include "rclcpp/typesupport_helpers.hpp" | ||
|
||
namespace rclcpp | ||
{ | ||
|
||
/// Create and return a GenericPublisher. | ||
/** | ||
* The returned pointer will never be empty, but this function can throw various exceptions, for | ||
* instance when the message's package can not be found on the AMENT_PREFIX_PATH. | ||
* | ||
* \param topics_interface NodeTopicsInterface pointer used in parts of the setup | ||
* \param topic_name Topic name | ||
* \param topic_type Topic type | ||
* \param qos %QoS settings | ||
* \param options %Publisher options. | ||
* Not all publisher options are currently respected, the only relevant options for this | ||
* publisher are `event_callbacks`, `use_default_callbacks`, and `%callback_group`. | ||
*/ | ||
template<typename AllocatorT = std::allocator<void>> | ||
std::shared_ptr<GenericPublisher> create_generic_publisher( | ||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr topics_interface, | ||
const std::string & topic_name, | ||
const std::string & topic_type, | ||
const rclcpp::QoS & qos, | ||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options = ( | ||
rclcpp::PublisherOptionsWithAllocator<AllocatorT>() | ||
) | ||
) | ||
{ | ||
auto ts_lib = rclcpp::get_typesupport_library(topic_type, "rosidl_typesupport_cpp"); | ||
auto pub = std::make_shared<GenericPublisher>( | ||
topics_interface->get_node_base_interface(), | ||
std::move(ts_lib), | ||
topic_name, | ||
topic_type, | ||
qos, | ||
options); | ||
topics_interface->add_publisher(pub, options.callback_group); | ||
return pub; | ||
} | ||
|
||
} // namespace rclcpp | ||
|
||
#endif // RCLCPP__CREATE_GENERIC_PUBLISHER_HPP_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Copyright 2020, Apex.AI Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#ifndef RCLCPP__CREATE_GENERIC_SUBSCRIPTION_HPP_ | ||
#define RCLCPP__CREATE_GENERIC_SUBSCRIPTION_HPP_ | ||
|
||
#include <functional> | ||
#include <memory> | ||
#include <string> | ||
#include <utility> | ||
|
||
#include "rcl/subscription.h" | ||
#include "rclcpp/generic_subscription.hpp" | ||
#include "rclcpp/node_interfaces/node_topics_interface.hpp" | ||
#include "rclcpp/qos.hpp" | ||
#include "rclcpp/serialized_message.hpp" | ||
#include "rclcpp/subscription_options.hpp" | ||
#include "rclcpp/typesupport_helpers.hpp" | ||
|
||
namespace rclcpp | ||
{ | ||
|
||
/// Create and return a GenericSubscription. | ||
/** | ||
* The returned pointer will never be empty, but this function can throw various exceptions, for | ||
* instance when the message's package can not be found on the AMENT_PREFIX_PATH. | ||
* | ||
* \param topics_interface NodeTopicsInterface pointer used in parts of the setup. | ||
* \param topic_name Topic name | ||
* \param topic_type Topic type | ||
* \param qos %QoS settings | ||
* \param callback Callback for new messages of serialized form | ||
* \param options %Publisher options. | ||
* Not all publisher options are currently respected, the only relevant options for this | ||
* publisher are `event_callbacks`, `use_default_callbacks`, and `%callback_group`. | ||
*/ | ||
template<typename AllocatorT = std::allocator<void>> | ||
std::shared_ptr<GenericSubscription> create_generic_subscription( | ||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr topics_interface, | ||
const std::string & topic_name, | ||
const std::string & topic_type, | ||
const rclcpp::QoS & qos, | ||
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> callback, | ||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = ( | ||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>() | ||
) | ||
) | ||
{ | ||
auto ts_lib = rclcpp::get_typesupport_library( | ||
topic_type, "rosidl_typesupport_cpp"); | ||
Comment on lines
+60
to
+61
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know how expensive this operation is, but it might be nice to have an alternate API to let users pass in a the typesupport library object directly (instead of a string). This way they can optionally cache the object for repeated calls to Something to think about; I don't think this comment should block this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess users could always construct There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can always add an overload for this function later on. I don't see any API/ABI breaks here. |
||
|
||
auto subscription = std::make_shared<GenericSubscription>( | ||
topics_interface->get_node_base_interface(), | ||
std::move(ts_lib), | ||
topic_name, | ||
topic_type, | ||
qos, | ||
callback, | ||
options); | ||
|
||
topics_interface->add_subscription(subscription, options.callback_group); | ||
|
||
return subscription; | ||
} | ||
|
||
} // namespace rclcpp | ||
|
||
#endif // RCLCPP__CREATE_GENERIC_SUBSCRIPTION_HPP_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
// Copyright 2018, Bosch Software Innovations GmbH. | ||
// Copyright 2021, Apex.AI Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#ifndef RCLCPP__GENERIC_PUBLISHER_HPP_ | ||
#define RCLCPP__GENERIC_PUBLISHER_HPP_ | ||
|
||
#include <memory> | ||
#include <string> | ||
|
||
#include "rcpputils/shared_library.hpp" | ||
|
||
#include "rclcpp/callback_group.hpp" | ||
#include "rclcpp/macros.hpp" | ||
#include "rclcpp/node_interfaces/node_base_interface.hpp" | ||
#include "rclcpp/node_interfaces/node_topics_interface.hpp" | ||
#include "rclcpp/publisher_base.hpp" | ||
#include "rclcpp/qos.hpp" | ||
#include "rclcpp/serialized_message.hpp" | ||
#include "rclcpp/typesupport_helpers.hpp" | ||
#include "rclcpp/visibility_control.hpp" | ||
|
||
namespace rclcpp | ||
{ | ||
|
||
/// %Publisher for serialized messages whose type is not known at compile time. | ||
/** | ||
* Since the type is not known at compile time, this is not a template, and the dynamic library | ||
* containing type support information has to be identified and loaded based on the type name. | ||
* | ||
* It does not support intra-process handling. | ||
*/ | ||
class GenericPublisher : public rclcpp::PublisherBase | ||
{ | ||
public: | ||
// cppcheck-suppress unknownMacro | ||
RCLCPP_SMART_PTR_DEFINITIONS(GenericPublisher) | ||
|
||
/// Constructor. | ||
/** | ||
* In order to properly publish to a topic, this publisher needs to be added to | ||
* the node_topic_interface of the node passed into this constructor. | ||
nnmm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* \sa rclcpp::Node::create_generic_publisher() or rclcpp::create_generic_publisher() for | ||
* creating an instance of this class and adding it to the node_topic_interface. | ||
* | ||
* \param node_base Pointer to parent node's NodeBaseInterface | ||
* \param ts_lib Type support library, needs to correspond to topic_type | ||
* \param topic_name Topic name | ||
* \param topic_type Topic type | ||
* \param qos %QoS settings | ||
* \param callback Callback for new messages of serialized form | ||
* \param options %Publisher options. | ||
* Not all publisher options are currently respected, the only relevant options for this | ||
* publisher are `event_callbacks`, `use_default_callbacks`, and `%callback_group`. | ||
*/ | ||
template<typename AllocatorT = std::allocator<void>> | ||
GenericPublisher( | ||
rclcpp::node_interfaces::NodeBaseInterface * node_base, | ||
std::shared_ptr<rcpputils::SharedLibrary> ts_lib, | ||
const std::string & topic_name, | ||
const std::string & topic_type, | ||
const rclcpp::QoS & qos, | ||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options) | ||
: rclcpp::PublisherBase( | ||
node_base, | ||
topic_name, | ||
*rclcpp::get_typesupport_handle(topic_type, "rosidl_typesupport_cpp", *ts_lib), | ||
options.template to_rcl_publisher_options<rclcpp::SerializedMessage>(qos)), | ||
ts_lib_(ts_lib) | ||
{ | ||
// This is unfortunately duplicated with the code in publisher.hpp. | ||
// TODO(nnmm): Deduplicate by moving this into PublisherBase. | ||
if (options.event_callbacks.deadline_callback) { | ||
this->add_event_handler( | ||
options.event_callbacks.deadline_callback, | ||
RCL_PUBLISHER_OFFERED_DEADLINE_MISSED); | ||
} | ||
if (options.event_callbacks.liveliness_callback) { | ||
this->add_event_handler( | ||
options.event_callbacks.liveliness_callback, | ||
RCL_PUBLISHER_LIVELINESS_LOST); | ||
} | ||
if (options.event_callbacks.incompatible_qos_callback) { | ||
this->add_event_handler( | ||
options.event_callbacks.incompatible_qos_callback, | ||
RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS); | ||
} else if (options.use_default_callbacks) { | ||
// Register default callback when not specified | ||
try { | ||
this->add_event_handler( | ||
[this](QOSOfferedIncompatibleQoSInfo & info) { | ||
this->default_incompatible_qos_callback(info); | ||
}, | ||
RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS); | ||
} catch (UnsupportedEventTypeException & /*exc*/) { | ||
// pass | ||
} | ||
} | ||
} | ||
|
||
RCLCPP_PUBLIC | ||
Karsten1987 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
virtual ~GenericPublisher() = default; | ||
|
||
/// Publish a rclcpp::SerializedMessage. | ||
RCLCPP_PUBLIC | ||
void publish(const rclcpp::SerializedMessage & message); | ||
|
||
private: | ||
// The type support library should stay loaded, so it is stored in the GenericPublisher | ||
std::shared_ptr<rcpputils::SharedLibrary> ts_lib_; | ||
}; | ||
|
||
} // namespace rclcpp | ||
|
||
#endif // RCLCPP__GENERIC_PUBLISHER_HPP_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better, but I won't require it, if the exceptions were detailed individually using the
\throws
doxygen directive.