Compare commits
32 Commits
29.0.0
...
dynamic_su
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd5c60827d | ||
|
|
a0a2a067d8 | ||
|
|
094618a044 | ||
|
|
f5e08c2d0c | ||
|
|
016cfeac99 | ||
|
|
a13e16e2cb | ||
|
|
aad8cb53ad | ||
|
|
8c0161a07f | ||
|
|
a7f05a904a | ||
|
|
d7245365ed | ||
|
|
3310f9eaed | ||
|
|
785a70d604 | ||
|
|
9984197c29 | ||
|
|
e9b1004247 | ||
|
|
e64627004f | ||
|
|
83c282a161 | ||
|
|
226044022a | ||
|
|
7e9ff5f4c7 | ||
|
|
64dd644469 | ||
|
|
322b5f5d79 | ||
|
|
e854bb29cd | ||
|
|
88ebea94e9 | ||
|
|
1e6767ac13 | ||
|
|
37e3688026 | ||
|
|
9b654942f9 | ||
|
|
f12e3c69dc | ||
|
|
bcc14755f9 | ||
|
|
4567b6ec80 | ||
|
|
0be8aa013e | ||
|
|
41d3a27437 | ||
|
|
c50f0c9c3d | ||
|
|
f8aea8cc51 |
13
.github/workflows/mirror-rolling-to-master.yaml
vendored
13
.github/workflows/mirror-rolling-to-master.yaml
vendored
@@ -1,13 +0,0 @@
|
||||
name: Mirror rolling to master
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ rolling ]
|
||||
|
||||
jobs:
|
||||
mirror-to-master:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: zofrex/mirror-branch@v1
|
||||
with:
|
||||
target-branch: master
|
||||
@@ -1,2 +0,0 @@
|
||||
# This file was generated by https://github.com/audrow/update-ros2-repos
|
||||
* @ivanpauno @hidmic @wjwwood
|
||||
@@ -2,6 +2,38 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
29.3.0 (2024-12-20)
|
||||
-------------------
|
||||
* Fix transient local IPC publish (`#2708 <https://github.com/ros2/rclcpp/issues/2708>`_)
|
||||
* apply actual QoS from rmw to the IPC publisher. (`#2707 <https://github.com/ros2/rclcpp/issues/2707>`_)
|
||||
* Adding in topic name to logging on IPC issues (`#2706 <https://github.com/ros2/rclcpp/issues/2706>`_)
|
||||
* fix TestTimeSource.ROS_time_valid_attach_detach. (`#2700 <https://github.com/ros2/rclcpp/issues/2700>`_)
|
||||
* Update docstring for `rclcpp::Node::now()` (`#2696 <https://github.com/ros2/rclcpp/issues/2696>`_)
|
||||
* Re-enable executor test on rmw_connextdds. (`#2693 <https://github.com/ros2/rclcpp/issues/2693>`_)
|
||||
* Fix warnings on Windows. (`#2692 <https://github.com/ros2/rclcpp/issues/2692>`_)
|
||||
* Omnibus fixes for running tests with Connext. (`#2684 <https://github.com/ros2/rclcpp/issues/2684>`_)
|
||||
* fix(Executor): Fix segfault if callback group is deleted during rmw_wait (`#2683 <https://github.com/ros2/rclcpp/issues/2683>`_)
|
||||
* Contributors: Chris Lalancette, Jeffery Hsu, Patrick Roncagliolo, Steve Macenski, Tomoya Fujita, jmachowinski
|
||||
|
||||
29.2.0 (2024-11-25)
|
||||
-------------------
|
||||
* accept custom allocator for LoanedMessage. (`#2672 <https://github.com/ros2/rclcpp/issues/2672>`_)
|
||||
* Contributors: Tomoya Fujita
|
||||
|
||||
29.1.0 (2024-11-20)
|
||||
-------------------
|
||||
* a couple of typo fixes in doc section for LoanedMessage. (`#2676 <https://github.com/ros2/rclcpp/issues/2676>`_)
|
||||
* Make sure callback_end tracepoint is triggered in AnyServiceCallback (`#2670 <https://github.com/ros2/rclcpp/issues/2670>`_)
|
||||
* Correct the incorrect comments in generic_client.hpp (`#2662 <https://github.com/ros2/rclcpp/issues/2662>`_)
|
||||
* Fix NodeOptions assignment operator (`#2656 <https://github.com/ros2/rclcpp/issues/2656>`_)
|
||||
* set QoS History KEEP_ALL explicitly for statistics publisher. (`#2650 <https://github.com/ros2/rclcpp/issues/2650>`_)
|
||||
* Fix test_intra_process_manager.cpp with rmw_zenoh_cpp (`#2653 <https://github.com/ros2/rclcpp/issues/2653>`_)
|
||||
* Fixed test_events_executors in zenoh (`#2643 <https://github.com/ros2/rclcpp/issues/2643>`_)
|
||||
* rmw_fastrtps supports service event gid uniqueness test. (`#2638 <https://github.com/ros2/rclcpp/issues/2638>`_)
|
||||
* print warning if event callback is not supported instead of passing exception. (`#2648 <https://github.com/ros2/rclcpp/issues/2648>`_)
|
||||
* Implement callback support of async_send_request for service generic client (`#2614 <https://github.com/ros2/rclcpp/issues/2614>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Barry Xu, Chris Lalancette, Christophe Bedard, Romain DESILLE, Tomoya Fujita
|
||||
|
||||
29.0.0 (2024-10-03)
|
||||
-------------------
|
||||
* Fixed test qos rmw zenoh (`#2639 <https://github.com/ros2/rclcpp/issues/2639>`_)
|
||||
|
||||
@@ -113,6 +113,7 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/qos.cpp
|
||||
src/rclcpp/event_handler.cpp
|
||||
src/rclcpp/qos_overriding_options.cpp
|
||||
src/rclcpp/dynamic_subscription.cpp
|
||||
src/rclcpp/rate.cpp
|
||||
src/rclcpp/serialization.cpp
|
||||
src/rclcpp/serialized_message.cpp
|
||||
|
||||
@@ -165,11 +165,13 @@ public:
|
||||
if (std::holds_alternative<SharedPtrDeferResponseCallback>(callback_)) {
|
||||
const auto & cb = std::get<SharedPtrDeferResponseCallback>(callback_);
|
||||
cb(request_header, std::move(request));
|
||||
TRACETOOLS_TRACEPOINT(callback_end, static_cast<const void *>(this));
|
||||
return nullptr;
|
||||
}
|
||||
if (std::holds_alternative<SharedPtrDeferResponseCallbackWithServiceHandle>(callback_)) {
|
||||
const auto & cb = std::get<SharedPtrDeferResponseCallbackWithServiceHandle>(callback_);
|
||||
cb(service_handle, request_header, std::move(request));
|
||||
TRACETOOLS_TRACEPOINT(callback_end, static_cast<const void *>(this));
|
||||
return nullptr;
|
||||
}
|
||||
// auto response = allocate_shared<typename ServiceT::Response, Allocator>();
|
||||
|
||||
175
rclcpp/include/rclcpp/dynamic_subscription.hpp
Normal file
175
rclcpp/include/rclcpp/dynamic_subscription.hpp
Normal file
@@ -0,0 +1,175 @@
|
||||
// Copyright 2022 Open Source Robotics Foundation, 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__DYNAMIC_SUBSCRIPTION_HPP_
|
||||
#define RCLCPP__DYNAMIC_SUBSCRIPTION_HPP_
|
||||
|
||||
#include <rosidl_dynamic_typesupport/identifier.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rcpputils/shared_library.hpp"
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
#include "rclcpp/subscription_base.hpp"
|
||||
#include "rclcpp/typesupport_helpers.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// %Subscription for messages whose type descriptions are obtained at runtime.
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* NOTE(methylDragon): No considerations for intra-process handling are made.
|
||||
*/
|
||||
class DynamicSubscription : public rclcpp::SubscriptionBase
|
||||
{
|
||||
public:
|
||||
// cppcheck-suppress unknownMacro
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(DynamicSubscription)
|
||||
|
||||
template<typename AllocatorT = std::allocator<void>>
|
||||
DynamicSubscription(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
rclcpp::dynamic_typesupport::DynamicMessageTypeSupport::SharedPtr type_support,
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos,
|
||||
std::function<void(
|
||||
rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr,
|
||||
const rosidl_runtime_c__type_description__TypeDescription &
|
||||
)> callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options)
|
||||
: SubscriptionBase(
|
||||
node_base,
|
||||
type_support->get_const_rosidl_message_type_support(),
|
||||
topic_name,
|
||||
options.to_rcl_subscription_options(
|
||||
qos),
|
||||
options.event_callbacks,
|
||||
options.use_default_callbacks,
|
||||
DeliveredMessageKind::DYNAMIC_MESSAGE),
|
||||
ts_(type_support),
|
||||
callback_(callback),
|
||||
serialization_support_(nullptr),
|
||||
dynamic_message_(nullptr),
|
||||
dynamic_message_type_(nullptr)
|
||||
{
|
||||
if (!type_support) {
|
||||
throw std::runtime_error("DynamicMessageTypeSupport cannot be nullptr!");
|
||||
}
|
||||
|
||||
if (type_support->get_const_rosidl_message_type_support().typesupport_identifier !=
|
||||
rosidl_get_dynamic_typesupport_identifier())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"DynamicSubscription must use dynamic type introspection type support!");
|
||||
}
|
||||
|
||||
serialization_support_ = type_support->get_shared_dynamic_serialization_support();
|
||||
dynamic_message_type_ = type_support->get_shared_dynamic_message_type()->clone_shared();
|
||||
dynamic_message_ = type_support->get_shared_dynamic_message()->clone_shared();
|
||||
}
|
||||
|
||||
// TODO(methylDragon):
|
||||
/// Deferred type description constructor, only usable if the middleware implementation supports
|
||||
/// type discovery
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~DynamicSubscription() = default;
|
||||
|
||||
// Same as create_serialized_message() as the subscription is to serialized_messages only
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<void> create_message() override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<rclcpp::SerializedMessage> create_serialized_message() override;
|
||||
|
||||
/// Cast the message to a rclcpp::SerializedMessage and call the callback.
|
||||
RCLCPP_PUBLIC
|
||||
void handle_message(
|
||||
std::shared_ptr<void> & message, const rclcpp::MessageInfo & message_info) override;
|
||||
|
||||
/// Handle dispatching rclcpp::SerializedMessage to user callback.
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
handle_serialized_message(
|
||||
const std::shared_ptr<rclcpp::SerializedMessage> & serialized_message,
|
||||
const rclcpp::MessageInfo & message_info) override;
|
||||
|
||||
/// This function is currently not implemented.
|
||||
RCLCPP_PUBLIC
|
||||
void handle_loaned_message(
|
||||
void * loaned_message, const rclcpp::MessageInfo & message_info) override;
|
||||
|
||||
// Same as return_serialized_message() as the subscription is to serialized_messages only
|
||||
RCLCPP_PUBLIC
|
||||
void return_message(std::shared_ptr<void> & message) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void return_serialized_message(std::shared_ptr<rclcpp::SerializedMessage> & message) override;
|
||||
|
||||
|
||||
// DYNAMIC TYPE ==================================================================================
|
||||
// TODO(methylDragon): Reorder later
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::dynamic_typesupport::DynamicMessageType::SharedPtr
|
||||
get_shared_dynamic_message_type() override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr get_shared_dynamic_message() override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::dynamic_typesupport::DynamicSerializationSupport::SharedPtr
|
||||
get_shared_dynamic_serialization_support() override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr create_dynamic_message() override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void return_dynamic_message(
|
||||
rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void handle_dynamic_message(
|
||||
const rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message,
|
||||
const rclcpp::MessageInfo & message_info) override;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(DynamicSubscription)
|
||||
|
||||
rclcpp::dynamic_typesupport::DynamicMessageTypeSupport::SharedPtr ts_;
|
||||
std::function<void(
|
||||
rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr,
|
||||
const rosidl_runtime_c__type_description__TypeDescription &
|
||||
)> callback_;
|
||||
|
||||
rclcpp::dynamic_typesupport::DynamicSerializationSupport::SharedPtr serialization_support_;
|
||||
rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr dynamic_message_;
|
||||
rclcpp::dynamic_typesupport::DynamicMessageType::SharedPtr dynamic_message_type_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DYNAMIC_SUBSCRIPTION_HPP_
|
||||
@@ -0,0 +1,327 @@
|
||||
// Copyright 2023 Open Source Robotics Foundation, 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__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_MESSAGE_IMPL_HPP_
|
||||
#define RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_MESSAGE_IMPL_HPP_
|
||||
|
||||
#include <rosidl_dynamic_typesupport/types.h>
|
||||
#include <rosidl_dynamic_typesupport/api/dynamic_data.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
|
||||
#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_MESSAGE_HPP_
|
||||
#include "rclcpp/dynamic_typesupport/dynamic_message.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
#define __DYNAMIC_MESSAGE_GET_VALUE_BY_ID_FN(ValueT, FunctionT) \
|
||||
template<> \
|
||||
ValueT \
|
||||
DynamicMessage::get_value<ValueT>(rosidl_dynamic_typesupport_member_id_t id) \
|
||||
{ \
|
||||
ValueT out; \
|
||||
rosidl_dynamic_typesupport_dynamic_data_get_ ## FunctionT ## _value( \
|
||||
&rosidl_dynamic_data_, id, &out); \
|
||||
return out; \
|
||||
}
|
||||
|
||||
#define __DYNAMIC_MESSAGE_GET_VALUE_BY_NAME_FN(ValueT, FunctionT) \
|
||||
template<> \
|
||||
ValueT \
|
||||
DynamicMessage::get_value<ValueT>(const std::string & name) \
|
||||
{ \
|
||||
return get_value<ValueT>(get_member_id(name)); \
|
||||
}
|
||||
|
||||
#define __DYNAMIC_MESSAGE_SET_VALUE_BY_ID_FN(ValueT, FunctionT) \
|
||||
template<> \
|
||||
void \
|
||||
DynamicMessage::set_value<ValueT>(rosidl_dynamic_typesupport_member_id_t id, ValueT value) \
|
||||
{ \
|
||||
rosidl_dynamic_typesupport_dynamic_data_set_ ## FunctionT ## _value( \
|
||||
&rosidl_dynamic_data_, id, value); \
|
||||
}
|
||||
|
||||
#define __DYNAMIC_MESSAGE_SET_VALUE_BY_NAME_FN(ValueT, FunctionT) \
|
||||
template<> \
|
||||
void \
|
||||
DynamicMessage::set_value<ValueT>(const std::string & name, ValueT value) \
|
||||
{ \
|
||||
set_value<ValueT>(get_member_id(name), value); \
|
||||
}
|
||||
|
||||
#define __DYNAMIC_MESSAGE_INSERT_VALUE(ValueT, FunctionT) \
|
||||
template<> \
|
||||
rosidl_dynamic_typesupport_member_id_t \
|
||||
DynamicMessage::insert_value<ValueT>(ValueT value) \
|
||||
{ \
|
||||
rosidl_dynamic_typesupport_member_id_t out; \
|
||||
rosidl_dynamic_typesupport_dynamic_data_insert_ ## FunctionT ## _value( \
|
||||
&rosidl_dynamic_data_, value, &out); \
|
||||
return out; \
|
||||
}
|
||||
|
||||
#define DYNAMIC_MESSAGE_DEFINITIONS(ValueT, FunctionT) \
|
||||
__DYNAMIC_MESSAGE_GET_VALUE_BY_ID_FN(ValueT, FunctionT) \
|
||||
__DYNAMIC_MESSAGE_GET_VALUE_BY_NAME_FN(ValueT, FunctionT) \
|
||||
__DYNAMIC_MESSAGE_SET_VALUE_BY_ID_FN(ValueT, FunctionT) \
|
||||
__DYNAMIC_MESSAGE_SET_VALUE_BY_NAME_FN(ValueT, FunctionT) \
|
||||
__DYNAMIC_MESSAGE_INSERT_VALUE(ValueT, FunctionT)
|
||||
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace dynamic_typesupport
|
||||
{
|
||||
|
||||
/**
|
||||
* Since we're in a ROS layer, these should support all ROS interface C++ types as found in:
|
||||
* https://docs.ros.org/en/rolling/Concepts/About-ROS-Interfaces.html
|
||||
*
|
||||
* Explicitly:
|
||||
* - Basic types: bool, byte, char
|
||||
* - Float types: float, double
|
||||
* - Int types: int8_t, int16_t, int32_t, int64_t
|
||||
* - Unsigned int types: uint8_t, uint16_t, uint32_t, uint64_t
|
||||
* - String types: std::string, std::u16string
|
||||
*/
|
||||
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(bool, bool);
|
||||
// DYNAMIC_MESSAGE_DEFINITIONS(std::byte, byte);
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(char, char);
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(float, float32);
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(double, float64);
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(int8_t, int8);
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(int16_t, int16);
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(int32_t, int32);
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(int64_t, int64);
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(uint8_t, uint8);
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(uint16_t, uint16);
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(uint32_t, uint32);
|
||||
DYNAMIC_MESSAGE_DEFINITIONS(uint64_t, uint64);
|
||||
// DYNAMIC_MESSAGE_DEFINITIONS(std::string, std::string);
|
||||
// DYNAMIC_MESSAGE_DEFINITIONS(std::u16string, std::u16string);
|
||||
|
||||
// Byte and String getters have a different implementation and are defined below
|
||||
|
||||
|
||||
// BYTE ============================================================================================
|
||||
template<>
|
||||
std::byte
|
||||
DynamicMessage::get_value<std::byte>(rosidl_dynamic_typesupport_member_id_t id)
|
||||
{
|
||||
unsigned char out;
|
||||
rosidl_dynamic_typesupport_dynamic_data_get_byte_value(&get_rosidl_dynamic_data(), id, &out);
|
||||
return static_cast<std::byte>(out);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
std::byte
|
||||
DynamicMessage::get_value<std::byte>(const std::string & name)
|
||||
{
|
||||
return get_value<std::byte>(get_member_id(name));
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
void
|
||||
DynamicMessage::set_value<std::byte>(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::byte value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_set_byte_value(
|
||||
&rosidl_dynamic_data_, id, static_cast<unsigned char>(value));
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
void
|
||||
DynamicMessage::set_value<std::byte>(const std::string & name, const std::byte value)
|
||||
{
|
||||
set_value<std::byte>(get_member_id(name), value);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::insert_value<std::byte>(const std::byte value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t out;
|
||||
rosidl_dynamic_typesupport_dynamic_data_insert_byte_value(
|
||||
&rosidl_dynamic_data_, static_cast<unsigned char>(value), &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
// STRINGS =========================================================================================
|
||||
template<>
|
||||
std::string
|
||||
DynamicMessage::get_value<std::string>(rosidl_dynamic_typesupport_member_id_t id)
|
||||
{
|
||||
size_t buf_length;
|
||||
char * buf = nullptr;
|
||||
rosidl_dynamic_typesupport_dynamic_data_get_string_value(
|
||||
&get_rosidl_dynamic_data(), id, &buf, &buf_length);
|
||||
auto out = std::string(buf, buf_length);
|
||||
delete buf;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
std::u16string
|
||||
DynamicMessage::get_value<std::u16string>(rosidl_dynamic_typesupport_member_id_t id)
|
||||
{
|
||||
size_t buf_length;
|
||||
char16_t * buf = nullptr;
|
||||
rosidl_dynamic_typesupport_dynamic_data_get_wstring_value(
|
||||
&get_rosidl_dynamic_data(), id, &buf, &buf_length);
|
||||
auto out = std::u16string(buf, buf_length);
|
||||
delete buf;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
std::string
|
||||
DynamicMessage::get_value<std::string>(const std::string & name)
|
||||
{
|
||||
return get_value<std::string>(get_member_id(name));
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
std::u16string
|
||||
DynamicMessage::get_value<std::u16string>(const std::string & name)
|
||||
{
|
||||
return get_value<std::u16string>(get_member_id(name));
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
void
|
||||
DynamicMessage::set_value<std::string>(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_set_string_value(
|
||||
&rosidl_dynamic_data_, id, value.c_str(), value.size());
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
void
|
||||
DynamicMessage::set_value<std::u16string>(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::u16string value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_set_wstring_value(
|
||||
&rosidl_dynamic_data_, id, value.c_str(), value.size());
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
void
|
||||
DynamicMessage::set_value<std::string>(const std::string & name, const std::string value)
|
||||
{
|
||||
set_value<std::string>(get_member_id(name), value);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
void
|
||||
DynamicMessage::set_value<std::u16string>(const std::string & name, const std::u16string value)
|
||||
{
|
||||
set_value<std::u16string>(get_member_id(name), value);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::insert_value<std::string>(const std::string value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t out;
|
||||
rosidl_dynamic_typesupport_dynamic_data_insert_string_value(
|
||||
&rosidl_dynamic_data_, value.c_str(), value.size(), &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::insert_value<std::u16string>(const std::u16string value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t out;
|
||||
rosidl_dynamic_typesupport_dynamic_data_insert_wstring_value(
|
||||
&rosidl_dynamic_data_, value.c_str(), value.size(), &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
// THROW FOR UNSUPPORTED TYPES =====================================================================
|
||||
template<typename ValueT>
|
||||
ValueT
|
||||
DynamicMessage::get_value(rosidl_dynamic_typesupport_member_id_t id)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError("get_value is not implemented for input type");
|
||||
}
|
||||
|
||||
|
||||
template<typename ValueT>
|
||||
ValueT
|
||||
DynamicMessage::get_value(const std::string & name)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError("get_value is not implemented for input type");
|
||||
}
|
||||
|
||||
|
||||
template<typename ValueT>
|
||||
void
|
||||
DynamicMessage::set_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, ValueT value)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError("set_value is not implemented for input type");
|
||||
}
|
||||
|
||||
|
||||
template<typename ValueT>
|
||||
void
|
||||
DynamicMessage::set_value(const std::string & name, ValueT value)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError("set_value is not implemented for input type");
|
||||
}
|
||||
|
||||
|
||||
template<typename ValueT>
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::insert_value(ValueT value)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError("insert_value is not implemented for input type");
|
||||
}
|
||||
|
||||
|
||||
} // namespace dynamic_typesupport
|
||||
} // namespace rclcpp
|
||||
|
||||
#undef __DYNAMIC_MESSAGE_GET_VALUE_BY_ID_FN
|
||||
#undef __DYNAMIC_MESSAGE_GET_VALUE_BY_NAME_FN
|
||||
#undef __DYNAMIC_MESSAGE_SET_VALUE_BY_ID_FN
|
||||
#undef __DYNAMIC_MESSAGE_SET_VALUE_BY_NAME_FN
|
||||
#undef __DYNAMIC_MESSAGE_INSERT_VALUE
|
||||
#undef DYNAMIC_MESSAGE_DEFINITIONS
|
||||
|
||||
#endif // RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_MESSAGE_IMPL_HPP_
|
||||
@@ -0,0 +1,189 @@
|
||||
// Copyright 2023 Open Source Robotics Foundation, 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__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_MESSAGE_TYPE_BUILDER_IMPL_HPP_
|
||||
#define RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_MESSAGE_TYPE_BUILDER_IMPL_HPP_
|
||||
|
||||
#include <rosidl_dynamic_typesupport/types.h>
|
||||
#include <rosidl_dynamic_typesupport/api/dynamic_type.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
|
||||
#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_MESSAGE_TYPE_BUILDER_HPP_
|
||||
#include "rclcpp/dynamic_typesupport/dynamic_message_type_builder.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
#define __DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_MEMBER_FN(MemberT, FunctionT) \
|
||||
template<> \
|
||||
void \
|
||||
DynamicMessageTypeBuilder::add_member<MemberT>( \
|
||||
rosidl_dynamic_typesupport_member_id_t id, \
|
||||
const std::string & name, \
|
||||
const std::string & default_value) \
|
||||
{ \
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_ ## FunctionT ## _member( \
|
||||
&rosidl_dynamic_type_builder_, \
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size()); \
|
||||
}
|
||||
|
||||
#define __DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_ARRAY_MEMBER_FN(MemberT, FunctionT) \
|
||||
template<> \
|
||||
void \
|
||||
DynamicMessageTypeBuilder::add_array_member<MemberT>( \
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, \
|
||||
size_t array_length, \
|
||||
const std::string & default_value) \
|
||||
{ \
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_ ## FunctionT ## _array_member( \
|
||||
&rosidl_dynamic_type_builder_, \
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(), \
|
||||
array_length); \
|
||||
}
|
||||
|
||||
#define __DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_UNBOUNDED_SEQUENCE_MEMBER_FN(MemberT, FunctionT) \
|
||||
template<> \
|
||||
void \
|
||||
DynamicMessageTypeBuilder::add_unbounded_sequence_member<MemberT>( \
|
||||
rosidl_dynamic_typesupport_member_id_t id, \
|
||||
const std::string & name, \
|
||||
const std::string & default_value) \
|
||||
{ \
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_ ## FunctionT ## \
|
||||
_unbounded_sequence_member( \
|
||||
&rosidl_dynamic_type_builder_, \
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size()); \
|
||||
}
|
||||
|
||||
#define __DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_BOUNDED_SEQUENCE_MEMBER_FN(MemberT, FunctionT) \
|
||||
template<> \
|
||||
void \
|
||||
DynamicMessageTypeBuilder::add_bounded_sequence_member<MemberT>( \
|
||||
rosidl_dynamic_typesupport_member_id_t id, \
|
||||
const std::string & name, \
|
||||
size_t sequence_bound, \
|
||||
const std::string & default_value) \
|
||||
{ \
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_ ## FunctionT ## _bounded_sequence_member( \
|
||||
&rosidl_dynamic_type_builder_, \
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(), \
|
||||
sequence_bound); \
|
||||
}
|
||||
|
||||
#define DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(MemberT, FunctionT) \
|
||||
__DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_MEMBER_FN(MemberT, FunctionT) \
|
||||
__DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_ARRAY_MEMBER_FN(MemberT, FunctionT) \
|
||||
__DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_UNBOUNDED_SEQUENCE_MEMBER_FN(MemberT, FunctionT) \
|
||||
__DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_BOUNDED_SEQUENCE_MEMBER_FN(MemberT, FunctionT) \
|
||||
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace dynamic_typesupport
|
||||
{
|
||||
|
||||
/**
|
||||
* Since we're in a ROS layer, these should support all ROS interface C++ types as found in:
|
||||
* https://docs.ros.org/en/rolling/Concepts/About-ROS-Interfaces.html
|
||||
*
|
||||
* Explicitly:
|
||||
* - Basic types: bool, byte, char
|
||||
* - Float types: float, double
|
||||
* - Int types: int8_t, int16_t, int32_t, int64_t
|
||||
* - Unsigned int types: uint8_t, uint16_t, uint32_t, uint64_t
|
||||
* - String types: std::string, std::u16string
|
||||
*/
|
||||
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(bool, bool);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(std::byte, byte);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(char, char);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(float, float32);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(double, float64);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(int8_t, int8);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(int16_t, int16);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(int32_t, int32);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(int64_t, int64);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(uint8_t, uint8);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(uint16_t, uint16);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(uint32_t, uint32);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(uint64_t, uint64);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(std::string, string);
|
||||
DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS(std::u16string, wstring);
|
||||
|
||||
|
||||
// THROW FOR UNSUPPORTED TYPES =====================================================================
|
||||
template<typename MemberT>
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id,
|
||||
const std::string & name,
|
||||
const std::string & default_value)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError(
|
||||
"add_member is not implemented for input type");
|
||||
}
|
||||
|
||||
|
||||
template<typename MemberT>
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id,
|
||||
const std::string & name,
|
||||
size_t array_length, const std::string & default_value)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError(
|
||||
"add_array_member is not implemented for input type");
|
||||
}
|
||||
|
||||
|
||||
template<typename MemberT>
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id,
|
||||
const std::string & name,
|
||||
const std::string & default_value)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError(
|
||||
"add_unbounded_sequence_member is not implemented for input type");
|
||||
}
|
||||
|
||||
|
||||
template<typename MemberT>
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id,
|
||||
const std::string & name,
|
||||
size_t sequence_bound,
|
||||
const std::string & default_value)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError(
|
||||
"add_bounded_sequence_member is not implemented for input type");
|
||||
}
|
||||
|
||||
|
||||
} // namespace dynamic_typesupport
|
||||
} // namespace rclcpp
|
||||
|
||||
#undef __DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_MEMBER_FN
|
||||
#undef __DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_ARRAY_MEMBER_FN
|
||||
#undef __DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_UNBOUNDED_SEQUENCE_MEMBER_FN
|
||||
#undef __DYNAMIC_MESSAGE_TYPE_BUILDER_ADD_BOUNDED_SEQUENCE_MEMBER_FN
|
||||
#undef DYNAMIC_MESSAGE_TYPE_BUILDER_DEFINITIONS
|
||||
|
||||
#endif // RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_MESSAGE_TYPE_BUILDER_IMPL_HPP_
|
||||
@@ -32,16 +32,372 @@ namespace rclcpp
|
||||
namespace dynamic_typesupport
|
||||
{
|
||||
|
||||
class DynamicMessageType;
|
||||
class DynamicMessageTypeBuilder;
|
||||
|
||||
/// Utility wrapper class for rosidl_dynamic_typesupport_dynamic_data_t
|
||||
/// STUBBED OUT
|
||||
/**
|
||||
* This class:
|
||||
* - Exposes getter methods for the struct
|
||||
* - Exposes the underlying serialization support API
|
||||
*
|
||||
* Ownership:
|
||||
* - This class borrows the rosidl_dynamic_typesupport_serialization_support_t stored in the passed
|
||||
* DynamicSerializationSupport. So it cannot outlive the DynamicSerializationSupport.
|
||||
* - The DynamicSerializationSupport's rosidl_dynamic_typesupport_serialization_support_t pointer
|
||||
* must point to the same location in memory as the stored raw pointer!
|
||||
*
|
||||
* Note: This class is meant to map to the lower level rosidl_dynamic_typesupport_dynamic_data_t,
|
||||
* even though rosidl_dynamic_typesupport_dynamic_data_t is equivalent to
|
||||
* rosidl_dynamic_typesupport_dynamic_data_t, exposing the fundamental methods available to
|
||||
* rosidl_dynamic_typesupport_dynamic_data_t, allowing the user to access the data's fields.
|
||||
*/
|
||||
class DynamicMessage : public std::enable_shared_from_this<DynamicMessage>
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessage)
|
||||
|
||||
// CONSTRUCTION ==================================================================================
|
||||
// Most constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the
|
||||
// lifetime of the serialization support (if the constructor cannot otherwise get it from args).
|
||||
//
|
||||
// In cases where a dynamic data pointer is passed, the serialization support composed by
|
||||
// the data should be the exact same object managed by the DynamicSerializationSupport,
|
||||
// otherwise the lifetime management will not work properly.
|
||||
|
||||
/// Construct a new DynamicMessage with the provided dynamic type builder, using its allocator
|
||||
RCLCPP_PUBLIC
|
||||
explicit DynamicMessage(std::shared_ptr<DynamicMessageTypeBuilder> dynamic_type_builder);
|
||||
|
||||
/// Construct a new DynamicMessage with the provided dynamic type builder and allocator
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage(
|
||||
std::shared_ptr<DynamicMessageTypeBuilder> dynamic_type_builder,
|
||||
rcl_allocator_t allocator);
|
||||
|
||||
/// Construct a new DynamicMessage with the provided dynamic type, using its allocator
|
||||
RCLCPP_PUBLIC
|
||||
explicit DynamicMessage(std::shared_ptr<DynamicMessageType> dynamic_type);
|
||||
|
||||
/// Construct a new DynamicMessage with the provided dynamic type and allocator
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage(
|
||||
std::shared_ptr<DynamicMessageType> dynamic_type,
|
||||
rcl_allocator_t allocator);
|
||||
|
||||
/// Assume ownership of struct
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
rosidl_dynamic_typesupport_dynamic_data_t && rosidl_dynamic_data);
|
||||
|
||||
/// Loaning constructor
|
||||
/// Must only be called with a rosidl dynaimc data object obtained from loaning!
|
||||
// NOTE(methylDragon): I'd put this in protected, but I need this exposed to
|
||||
// enable_shared_from_this...
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage(
|
||||
DynamicMessage::SharedPtr parent_data,
|
||||
rosidl_dynamic_typesupport_dynamic_data_t && rosidl_loaned_data);
|
||||
|
||||
// NOTE(methylDragon): Deliberately no constructor from description to nudge users towards using
|
||||
// construction from dynamic type/builder, which is more efficient
|
||||
|
||||
/// Move constructor
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage(DynamicMessage && other) noexcept;
|
||||
|
||||
/// Move assignment
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage & operator=(DynamicMessage && other) noexcept;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~DynamicMessage();
|
||||
|
||||
|
||||
// GETTERS =======================================================================================
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_serialization_library_identifier() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_name() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_dynamic_data_t &
|
||||
get_rosidl_dynamic_data();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_dynamic_typesupport_dynamic_data_t &
|
||||
get_rosidl_dynamic_data() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicSerializationSupport::SharedPtr
|
||||
get_shared_dynamic_serialization_support();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicSerializationSupport::ConstSharedPtr
|
||||
get_shared_dynamic_serialization_support() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_item_count() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
get_member_id(size_t index) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
get_member_id(const std::string & name) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
get_array_index(size_t index) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
get_array_index(const std::string & name) const;
|
||||
|
||||
|
||||
// METHODS =======================================================================================
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage
|
||||
clone(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage::SharedPtr
|
||||
clone_shared(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage
|
||||
init_from_type(
|
||||
DynamicMessageType & type, rcl_allocator_t allocator = rcl_get_default_allocator()) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage::SharedPtr
|
||||
init_from_type_shared(
|
||||
DynamicMessageType & type, rcl_allocator_t allocator = rcl_get_default_allocator()) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
equals(const DynamicMessage & other) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage::SharedPtr
|
||||
loan_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage::SharedPtr
|
||||
loan_value(
|
||||
const std::string & name,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
clear_all_values();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
clear_nonkey_values();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
clear_value(rosidl_dynamic_typesupport_member_id_t id);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
clear_value(const std::string & name);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
clear_sequence();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
insert_sequence_data();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_sequence_data(rosidl_dynamic_typesupport_member_id_t index);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
serialize(rcl_serialized_message_t & buffer);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
deserialize(rcl_serialized_message_t & buffer);
|
||||
|
||||
|
||||
// MEMBER ACCESS TEMPLATES =======================================================================
|
||||
/**
|
||||
* Since we're in a ROS layer, these should support all ROS interface C++ types as found in:
|
||||
* https://docs.ros.org/en/rolling/Concepts/About-ROS-Interfaces.html
|
||||
*
|
||||
* Explicitly:
|
||||
* - Basic types: bool, byte, char
|
||||
* - Float types: float, double
|
||||
* - Int types: int8_t, int16_t, int32_t, int64_t
|
||||
* - Unsigned int types: uint8_t, uint16_t, uint32_t, uint64_t
|
||||
* - String types: std::string, std::u16string
|
||||
*/
|
||||
|
||||
template<typename ValueT>
|
||||
ValueT
|
||||
get_value(rosidl_dynamic_typesupport_member_id_t id);
|
||||
|
||||
template<typename ValueT>
|
||||
ValueT
|
||||
get_value(const std::string & name);
|
||||
|
||||
template<typename ValueT>
|
||||
void
|
||||
set_value(rosidl_dynamic_typesupport_member_id_t id, ValueT value);
|
||||
|
||||
template<typename ValueT>
|
||||
void
|
||||
set_value(const std::string & name, ValueT value);
|
||||
|
||||
template<typename ValueT>
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
insert_value(ValueT value);
|
||||
|
||||
|
||||
// FIXED STRING MEMBER ACCESS ====================================================================
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_fixed_string_value(rosidl_dynamic_typesupport_member_id_t id, size_t string_length);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_fixed_string_value(const std::string & name, size_t string_length);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::u16string
|
||||
get_fixed_wstring_value(rosidl_dynamic_typesupport_member_id_t id, size_t wstring_length);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::u16string
|
||||
get_fixed_wstring_value(const std::string & name, size_t wstring_length);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_fixed_string_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string value, size_t string_length);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_fixed_string_value(const std::string & name, const std::string value, size_t string_length);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_fixed_wstring_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::u16string value, size_t wstring_length);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_fixed_wstring_value(
|
||||
const std::string & name, const std::u16string value, size_t wstring_length);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
insert_fixed_string_value(const std::string value, size_t string_length);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
insert_fixed_wstring_value(const std::u16string value, size_t wstring_length);
|
||||
|
||||
|
||||
// BOUNDED STRING MEMBER ACCESS ==================================================================
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_bounded_string_value(rosidl_dynamic_typesupport_member_id_t id, size_t string_bound);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_bounded_string_value(const std::string & name, size_t string_bound);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::u16string
|
||||
get_bounded_wstring_value(rosidl_dynamic_typesupport_member_id_t id, size_t wstring_bound);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::u16string
|
||||
get_bounded_wstring_value(const std::string & name, size_t wstring_bound);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_bounded_string_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string value, size_t string_bound);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_bounded_string_value(const std::string & name, const std::string value, size_t string_bound);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_bounded_wstring_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::u16string value, size_t wstring_bound);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_bounded_wstring_value(
|
||||
const std::string & name, const std::u16string value, size_t wstring_bound);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
insert_bounded_string_value(const std::string value, size_t string_bound);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
insert_bounded_wstring_value(const std::u16string value, size_t wstring_bound);
|
||||
|
||||
|
||||
// NESTED MEMBER ACCESS ==========================================================================
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage
|
||||
get_nested_data(
|
||||
rosidl_dynamic_typesupport_member_id_t id,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage
|
||||
get_nested_data(
|
||||
const std::string & name,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage::SharedPtr
|
||||
get_nested_data_shared(
|
||||
rosidl_dynamic_typesupport_member_id_t id,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage::SharedPtr
|
||||
get_nested_data_shared(
|
||||
const std::string & name,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_nested_data(rosidl_dynamic_typesupport_member_id_t id, DynamicMessage & value);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_nested_data(const std::string & name, DynamicMessage & value);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
insert_nested_data_copy(const DynamicMessage & value);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
insert_nested_data(DynamicMessage & value);
|
||||
|
||||
protected:
|
||||
// NOTE(methylDragon):
|
||||
// This is just here to extend the lifetime of the serialization support
|
||||
@@ -62,6 +418,12 @@ private:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
match_serialization_support_(
|
||||
const DynamicSerializationSupport & serialization_support,
|
||||
const rosidl_dynamic_typesupport_dynamic_data_t & dynamic_data);
|
||||
};
|
||||
|
||||
} // namespace dynamic_typesupport
|
||||
|
||||
@@ -30,16 +30,143 @@ namespace rclcpp
|
||||
namespace dynamic_typesupport
|
||||
{
|
||||
|
||||
class DynamicMessage;
|
||||
class DynamicMessageTypeBuilder;
|
||||
|
||||
/// Utility wrapper class for `rosidl_dynamic_typesupport_dynamic_type_t`
|
||||
/// STUBBED OUT
|
||||
/**
|
||||
* This class:
|
||||
* - Exposes getter methods for the struct
|
||||
* - Exposes the underlying serialization support API
|
||||
*
|
||||
* Ownership:
|
||||
* - This class borrows the `rosidl_dynamic_typesupport_serialization_support_t` stored in the
|
||||
* passed `DynamicSerializationSupport`.
|
||||
* So it cannot outlive the `DynamicSerializationSupport`.
|
||||
* - The `DynamicSerializationSupport`'s `rosidl_dynamic_typesupport_serialization_support_t`
|
||||
* pointer must point to the same location in memory as the stored raw pointer!
|
||||
*
|
||||
* This class is meant to map to the lower level `rosidl_dynamic_typesupport_dynamic_type_t`,
|
||||
* which can be constructed via `DynamicMessageTypeBuilder`, which maps to
|
||||
* `rosidl_dynamic_typesupport_dynamic_type_builder_t`.
|
||||
*
|
||||
* The usual method of obtaining a `DynamicMessageType` is through construction of
|
||||
* `rosidl_message_type_support_t` via `rcl_dynamic_message_type_support_handle_create()`, then
|
||||
* taking ownership of its contents. But `DynamicMessageTypeBuilder` can also be used to obtain
|
||||
* `DynamicMessageType` by constructing it bottom-up instead, since it exposes the lower_level
|
||||
* rosidl methods.
|
||||
*/
|
||||
class DynamicMessageType : public std::enable_shared_from_this<DynamicMessageType>
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessageType)
|
||||
|
||||
// CONSTRUCTION ==================================================================================
|
||||
// Most constructors require a passed in `DynamicSerializationSupport::SharedPtr`, to extend the
|
||||
// lifetime of the serialization support (if the constructor cannot otherwise get it from args).
|
||||
//
|
||||
// In cases where a dynamic type pointer is passed, the serialization support composed by
|
||||
// the type should be the exact same object managed by the `DynamicSerializationSupport`,
|
||||
// otherwise the lifetime management will not work properly.
|
||||
|
||||
/// Construct a new `DynamicMessageType` with the provided dynamic type builder,
|
||||
/// using its allocator
|
||||
RCLCPP_PUBLIC
|
||||
explicit DynamicMessageType(std::shared_ptr<DynamicMessageTypeBuilder> dynamic_type_builder);
|
||||
|
||||
/// Construct a new `DynamicMessageType` with the provided dynamic type builder and allocator
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType(
|
||||
std::shared_ptr<DynamicMessageTypeBuilder> dynamic_type_builder,
|
||||
rcl_allocator_t allocator);
|
||||
|
||||
/// Assume ownership of struct
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
rosidl_dynamic_typesupport_dynamic_type_t && rosidl_dynamic_type);
|
||||
|
||||
/// From description
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
/// Move constructor
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType(DynamicMessageType && other) noexcept;
|
||||
|
||||
/// Move assignment
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType & operator=(DynamicMessageType && other) noexcept;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~DynamicMessageType();
|
||||
|
||||
/// Swaps the serialization support if `serialization_support` is populated
|
||||
/**
|
||||
* The user can call this with another description to reconfigure the type without changing the
|
||||
* serialization support
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
init_from_description(
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator(),
|
||||
DynamicSerializationSupport::SharedPtr serialization_support = nullptr);
|
||||
|
||||
// GETTERS =======================================================================================
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_serialization_library_identifier() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_name() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_member_count() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_dynamic_type_t &
|
||||
get_rosidl_dynamic_type();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_dynamic_typesupport_dynamic_type_t &
|
||||
get_rosidl_dynamic_type() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicSerializationSupport::SharedPtr
|
||||
get_shared_dynamic_serialization_support();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicSerializationSupport::ConstSharedPtr
|
||||
get_shared_dynamic_serialization_support() const;
|
||||
|
||||
|
||||
// METHODS =======================================================================================
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType
|
||||
clone(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType::SharedPtr
|
||||
clone_shared(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
equals(const DynamicMessageType & other) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage
|
||||
build_dynamic_message(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<DynamicMessage>
|
||||
build_dynamic_message_shared(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
protected:
|
||||
// NOTE(methylDragon):
|
||||
// This is just here to extend the lifetime of the serialization support
|
||||
@@ -56,6 +183,12 @@ private:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
match_serialization_support_(
|
||||
const DynamicSerializationSupport & serialization_support,
|
||||
const rosidl_dynamic_typesupport_dynamic_type_t & rosidl_dynamic_type);
|
||||
};
|
||||
|
||||
} // namespace dynamic_typesupport
|
||||
|
||||
@@ -30,16 +30,347 @@ namespace rclcpp
|
||||
namespace dynamic_typesupport
|
||||
{
|
||||
|
||||
class DynamicMessage;
|
||||
class DynamicMessageType;
|
||||
|
||||
/// Utility wrapper class for `rosidl_dynamic_typesupport_dynamic_type_builder_t *`
|
||||
/// STUBBED OUT
|
||||
/**
|
||||
* This class:
|
||||
* - Manages the lifetime of the raw pointer.
|
||||
* - Exposes getter methods to get the raw pointer and shared pointers
|
||||
* - Exposes the underlying serialization support API
|
||||
*
|
||||
* Ownership:
|
||||
* - This class borrows the rosidl_dynamic_typesupport_serialization_support_t stored in the passed
|
||||
* `DynamicSerializationSupport`.
|
||||
* So it cannot outlive the `DynamicSerializationSupport`.
|
||||
* - The `DynamicSerializationSupport`'s `rosidl_dynamic_typesupport_serialization_support_t`
|
||||
* pointer must point to the same location in memory as the stored raw pointer!
|
||||
*
|
||||
* This class is meant to map to rosidl_dynamic_typesupport_dynamic_type_builder_t, facilitating the
|
||||
* construction of dynamic types bottom-up in the C++ layer.
|
||||
*
|
||||
* The usual method of obtaining a `DynamicMessageType` is through construction of
|
||||
* `rosidl_message_type_support_t` via `rcl_dynamic_message_type_support_handle_create()`, then
|
||||
* taking ownership of its contents.
|
||||
* But `DynamicMessageTypeBuilder` can also be used to obtain `DynamicMessageType` by constructing
|
||||
* it bottom-up instead, since it exposes the lower_level rosidl methods.
|
||||
*/
|
||||
class DynamicMessageTypeBuilder : public std::enable_shared_from_this<DynamicMessageTypeBuilder>
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessageTypeBuilder)
|
||||
|
||||
// CONSTRUCTION ==================================================================================
|
||||
// All constructors require a passed in `DynamicSerializationSupport::SharedPtr`, to extend the
|
||||
// lifetime of the serialization support.
|
||||
//
|
||||
// In cases where a dynamic type builder pointer is passed, the serialization support composed by
|
||||
// the builder should be the exact same object managed by the `DynamicSerializationSupport`,
|
||||
// otherwise the lifetime management will not work properly.
|
||||
|
||||
/// Construct a new `DynamicMessageTypeBuilder` with the provided serialization support using its
|
||||
/// allocator
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeBuilder(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
const std::string & name);
|
||||
|
||||
/// Construct a new `DynamicMessageTypeBuilder` with the provided serialization support and
|
||||
/// allocator
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeBuilder(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
const std::string & name,
|
||||
rcl_allocator_t allocator);
|
||||
|
||||
/// Assume ownership of struct
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeBuilder(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_t && dynamic_type_builder);
|
||||
|
||||
/// From description
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeBuilder(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
/// Move constructor
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeBuilder(DynamicMessageTypeBuilder && other) noexcept;
|
||||
|
||||
/// Move assignment
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeBuilder & operator=(DynamicMessageTypeBuilder && other) noexcept;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~DynamicMessageTypeBuilder();
|
||||
|
||||
/// Swaps the serialization support if serialization_support is populated
|
||||
/**
|
||||
* The user can call this with another description to reconfigure the type without changing the
|
||||
* serialization support
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
init_from_description(
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator(),
|
||||
DynamicSerializationSupport::SharedPtr serialization_support = nullptr);
|
||||
|
||||
|
||||
// GETTERS =======================================================================================
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_serialization_library_identifier() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_name() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_t &
|
||||
get_rosidl_dynamic_type_builder();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_dynamic_typesupport_dynamic_type_builder_t &
|
||||
get_rosidl_dynamic_type_builder() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicSerializationSupport::SharedPtr
|
||||
get_shared_dynamic_serialization_support();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicSerializationSupport::ConstSharedPtr
|
||||
get_shared_dynamic_serialization_support() const;
|
||||
|
||||
|
||||
// METHODS =======================================================================================
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_name(const std::string & name);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeBuilder
|
||||
clone(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeBuilder::SharedPtr
|
||||
clone_shared(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
clear(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage
|
||||
build_dynamic_message(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage::SharedPtr
|
||||
build_dynamic_message_shared(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType
|
||||
build_dynamic_message_type(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType::SharedPtr
|
||||
build_dynamic_message_type_shared(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
|
||||
// ADD MEMBERS TEMPLATES =========================================================================
|
||||
/**
|
||||
* Since we're in a ROS layer, these should support all ROS interface C++ types as found in:
|
||||
* https://docs.ros.org/en/rolling/Concepts/About-ROS-Interfaces.html
|
||||
*
|
||||
* Explicitly:
|
||||
* - Basic types: bool, byte, char
|
||||
* - Float types: float, double
|
||||
* - Int types: int8_t, int16_t, int32_t, int64_t
|
||||
* - Unsigned int types: uint8_t, uint16_t, uint32_t, uint64_t
|
||||
* - String types: std::string, std::u16string
|
||||
*/
|
||||
|
||||
template<typename MemberT>
|
||||
void
|
||||
add_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
const std::string & default_value = "");
|
||||
|
||||
template<typename MemberT>
|
||||
void
|
||||
add_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t array_length,
|
||||
const std::string & default_value = "");
|
||||
|
||||
template<typename MemberT>
|
||||
void
|
||||
add_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
const std::string & default_value = "");
|
||||
|
||||
template<typename MemberT>
|
||||
void
|
||||
add_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t sequence_bound,
|
||||
const std::string & default_value = "");
|
||||
|
||||
|
||||
// ADD FIXED STRING MEMBERS ======================================================================
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_fixed_string_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_length,
|
||||
const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_fixed_wstring_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_length,
|
||||
const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_fixed_string_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t string_length, size_t array_length, const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_fixed_wstring_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t wstring_length, size_t array_length, const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_fixed_string_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_length,
|
||||
const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_fixed_wstring_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_length,
|
||||
const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_fixed_string_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t string_length, size_t sequence_bound, const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_fixed_wstring_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t wstring_length, size_t sequence_bound, const std::string & default_value = "");
|
||||
|
||||
|
||||
// ADD BOUNDED STRING MEMBERS ====================================================================
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_bounded_string_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_bound,
|
||||
const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_bounded_wstring_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_bound,
|
||||
const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_bounded_string_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t string_bound, size_t array_length, const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_bounded_wstring_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t wstring_bound, size_t array_length, const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_bounded_string_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_bound,
|
||||
const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_bounded_wstring_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_bound,
|
||||
const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_bounded_string_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t string_bound, size_t sequence_bound, const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_bounded_wstring_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t wstring_bound, size_t sequence_bound, const std::string & default_value = "");
|
||||
|
||||
|
||||
// ADD NESTED MEMBERS ============================================================================
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_complex_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageType & nested_type, const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_complex_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageType & nested_type, size_t array_length, const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_complex_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageType & nested_type, const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_complex_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageType & nested_type, size_t sequence_bound,
|
||||
const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_complex_member_builder(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageTypeBuilder & nested_type_builder, const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_complex_array_member_builder(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageTypeBuilder & nested_type_builder, size_t array_length,
|
||||
const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_complex_unbounded_sequence_member_builder(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageTypeBuilder & nested_type_builder, const std::string & default_value = "");
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_complex_bounded_sequence_member_builder(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageTypeBuilder & nested_type_builder, size_t sequence_bound,
|
||||
const std::string & default_value = "");
|
||||
|
||||
protected:
|
||||
// NOTE(methylDragon):
|
||||
// This is just here to extend the lifetime of the serialization support
|
||||
@@ -56,6 +387,19 @@ private:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeBuilder();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
init_from_serialization_support_(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
const std::string & name,
|
||||
rcl_allocator_t allocator);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
match_serialization_support_(
|
||||
const DynamicSerializationSupport & serialization_support,
|
||||
const rosidl_dynamic_typesupport_dynamic_type_builder_t & dynamic_type_builder);
|
||||
};
|
||||
|
||||
} // namespace dynamic_typesupport
|
||||
|
||||
@@ -38,16 +38,115 @@ namespace dynamic_typesupport
|
||||
{
|
||||
|
||||
/// Utility wrapper class for `rosidl_message_type_support_t` containing managed
|
||||
/// STUBBED OUT
|
||||
/// instances of the typesupport handle impl.
|
||||
/**
|
||||
*
|
||||
* NOTE: This class is the recommended way to obtain the dynamic message type
|
||||
* support struct, instead of `rcl_dynamic_message_type_support_handle_init()`,
|
||||
* because this class will manage the lifetimes for you.
|
||||
*
|
||||
* Do NOT call rcl_dynamic_message_type_support_handle_fini
|
||||
*
|
||||
* This class:
|
||||
* - Exposes getter methods for the struct
|
||||
* - Stores shared pointers to wrapper classes that expose the underlying
|
||||
* serialization support API
|
||||
*
|
||||
* Ownership:
|
||||
* - This class, similarly to the `rosidl_dynamic_typesupport_serialization_support_t`, must outlive
|
||||
* all downstream usages of the serialization support.
|
||||
*/
|
||||
class DynamicMessageTypeSupport : public std::enable_shared_from_this<DynamicMessageTypeSupport>
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessageTypeSupport)
|
||||
|
||||
// CONSTRUCTION ==================================================================================
|
||||
/// From description
|
||||
/// Does NOT take ownership of the description (copies instead.)
|
||||
/// Constructs type support top-down (calling `rcl_dynamic_message_type_support_handle_create()`)
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeSupport(
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
const std::string & serialization_library_name = "",
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
/// From description, for provided serialization support
|
||||
/// Does NOT take ownership of the description (copies instead.)
|
||||
/// Constructs type support top-down (calling `rosidl_dynamic_message_type_support_handle_init()`)
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeSupport(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
/// Assume ownership of managed types
|
||||
/// Does NOT take ownership of the description (copies instead.)
|
||||
///
|
||||
/// The serialization support used to construct all managed SharedPtrs must match.
|
||||
/// The structure of the provided `description` must match the `dynamic_message_type`
|
||||
/// The structure of the provided `dynamic_message_type` must match the `dynamic_message
|
||||
///
|
||||
/// In this case, the user would have constructed the type support bototm-up (by creating the
|
||||
/// respective dynamic members.)
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageTypeSupport(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
DynamicMessageType::SharedPtr dynamic_message_type,
|
||||
DynamicMessage::SharedPtr dynamic_message,
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~DynamicMessageTypeSupport();
|
||||
|
||||
|
||||
// GETTERS =======================================================================================
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_serialization_library_identifier() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_message_type_support_t &
|
||||
get_const_rosidl_message_type_support();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_message_type_support_t &
|
||||
get_const_rosidl_message_type_support() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_runtime_c__type_description__TypeDescription &
|
||||
get_rosidl_runtime_c_type_description() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicSerializationSupport::SharedPtr
|
||||
get_shared_dynamic_serialization_support();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicSerializationSupport::ConstSharedPtr
|
||||
get_shared_dynamic_serialization_support() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType::SharedPtr
|
||||
get_shared_dynamic_message_type();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessageType::ConstSharedPtr
|
||||
get_shared_dynamic_message_type() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage::SharedPtr
|
||||
get_shared_dynamic_message();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
DynamicMessage::ConstSharedPtr
|
||||
get_shared_dynamic_message() const;
|
||||
|
||||
protected:
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_message_type_support_t &
|
||||
get_rosidl_message_type_support();
|
||||
|
||||
DynamicSerializationSupport::SharedPtr serialization_support_;
|
||||
DynamicMessageType::SharedPtr dynamic_message_type_;
|
||||
DynamicMessage::SharedPtr dynamic_message_;
|
||||
|
||||
@@ -31,22 +31,60 @@ namespace dynamic_typesupport
|
||||
{
|
||||
|
||||
/// Utility wrapper class for rosidl_dynamic_typesupport_serialization_support_t
|
||||
/**
|
||||
* This class:
|
||||
* - Exposes getter methods for the struct
|
||||
* - Exposes the underlying serialization support API
|
||||
*
|
||||
* Ownership:
|
||||
* - This class, similarly to the rosidl_dynamic_typesupport_serialization_support_t, must outlive
|
||||
* all downstream usages of the serialization support.
|
||||
*/
|
||||
class DynamicSerializationSupport : public std::enable_shared_from_this<DynamicSerializationSupport>
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicSerializationSupport)
|
||||
|
||||
// CONSTRUCTION ==================================================================================
|
||||
RCLCPP_PUBLIC
|
||||
explicit DynamicSerializationSupport(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
/// Get the rmw middleware implementation specific serialization support (configured by name)
|
||||
RCLCPP_PUBLIC
|
||||
DynamicSerializationSupport(
|
||||
const std::string & serialization_library_name,
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
/// Assume ownership of struct
|
||||
RCLCPP_PUBLIC
|
||||
explicit DynamicSerializationSupport(
|
||||
rosidl_dynamic_typesupport_serialization_support_t && rosidl_serialization_support);
|
||||
|
||||
/// Move constructor
|
||||
RCLCPP_PUBLIC
|
||||
DynamicSerializationSupport(DynamicSerializationSupport && other) noexcept;
|
||||
|
||||
/// Move assignment
|
||||
RCLCPP_PUBLIC
|
||||
DynamicSerializationSupport & operator=(DynamicSerializationSupport && other) noexcept;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~DynamicSerializationSupport();
|
||||
|
||||
|
||||
// GETTERS =======================================================================================
|
||||
RCLCPP_PUBLIC
|
||||
const std::string
|
||||
get_serialization_library_identifier() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rosidl_dynamic_typesupport_serialization_support_t &
|
||||
get_rosidl_serialization_support();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_dynamic_typesupport_serialization_support_t &
|
||||
get_rosidl_serialization_support() const;
|
||||
|
||||
protected:
|
||||
rosidl_dynamic_typesupport_serialization_support_t rosidl_serialization_support_;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <memory>
|
||||
#include <future>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
@@ -35,8 +36,8 @@ namespace rclcpp
|
||||
class GenericClient : public ClientBase
|
||||
{
|
||||
public:
|
||||
using Request = void *; // Serialized data pointer of request message
|
||||
using Response = void *; // Serialized data pointer of response message
|
||||
using Request = void *; // Deserialized data pointer of request message
|
||||
using Response = void *; // Deserialized data pointer of response message
|
||||
|
||||
using SharedResponse = std::shared_ptr<void>;
|
||||
|
||||
@@ -46,6 +47,8 @@ public:
|
||||
using Future = std::future<SharedResponse>;
|
||||
using SharedFuture = std::shared_future<SharedResponse>;
|
||||
|
||||
using CallbackType = std::function<void (SharedFuture)>;
|
||||
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(GenericClient)
|
||||
|
||||
/// A convenient GenericClient::Future and request id pair.
|
||||
@@ -76,6 +79,20 @@ public:
|
||||
~FutureAndRequestId() = default;
|
||||
};
|
||||
|
||||
/// A convenient GenericClient::SharedFuture and request id pair.
|
||||
/**
|
||||
* Public members:
|
||||
* - future: a std::shared_future<SharedResponse>.
|
||||
* - request_id: the request id associated with the future.
|
||||
*
|
||||
* All the other methods are equivalent to the ones std::shared_future provides.
|
||||
*/
|
||||
struct SharedFutureAndRequestId
|
||||
: detail::FutureAndRequestId<std::shared_future<SharedResponse>>
|
||||
{
|
||||
using detail::FutureAndRequestId<std::shared_future<SharedResponse>>::FutureAndRequestId;
|
||||
};
|
||||
|
||||
GenericClient(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
|
||||
@@ -106,16 +123,16 @@ public:
|
||||
* If the future never completes,
|
||||
* e.g. the call to Executor::spin_until_future_complete() times out,
|
||||
* GenericClient::remove_pending_request() must be called to clean the client internal state.
|
||||
* Not doing so will make the `Client` instance to use more memory each time a response is not
|
||||
* received from the service server.
|
||||
* Not doing so will make the `GenericClient` instance to use more memory each time a response is
|
||||
* not received from the service server.
|
||||
*
|
||||
* ```cpp
|
||||
* auto future = client->async_send_request(my_request);
|
||||
* auto future = generic_client->async_send_request(my_request);
|
||||
* if (
|
||||
* rclcpp::FutureReturnCode::TIMEOUT ==
|
||||
* executor->spin_until_future_complete(future, timeout))
|
||||
* {
|
||||
* client->remove_pending_request(future);
|
||||
* generic_client->remove_pending_request(future);
|
||||
* // handle timeout
|
||||
* } else {
|
||||
* handle_response(future.get());
|
||||
@@ -129,6 +146,45 @@ public:
|
||||
FutureAndRequestId
|
||||
async_send_request(const Request request);
|
||||
|
||||
/// Send a request to the service server and schedule a callback in the executor.
|
||||
/**
|
||||
* Similar to the previous overload, but a callback will automatically be called when a response
|
||||
* is received.
|
||||
*
|
||||
* If the callback is never called, because we never got a reply for the service server,
|
||||
* remove_pending_request() has to be called with the returned request id or
|
||||
* prune_pending_requests().
|
||||
* Not doing so will make the `GenericClient` instance use more memory each time a response is not
|
||||
* received from the service server.
|
||||
* In this case, it's convenient to setup a timer to cleanup the pending requests.
|
||||
*
|
||||
* \param[in] request request to be send.
|
||||
* \param[in] cb callback that will be called when we get a response for this request.
|
||||
* \return the request id representing the request just sent.
|
||||
*/
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
CallbackT,
|
||||
CallbackType
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
SharedFutureAndRequestId
|
||||
async_send_request(const Request request, CallbackT && cb)
|
||||
{
|
||||
Promise promise;
|
||||
auto shared_future = promise.get_future().share();
|
||||
auto req_id = async_send_request_impl(
|
||||
request,
|
||||
std::make_tuple(
|
||||
CallbackType{std::forward<CallbackT>(cb)},
|
||||
shared_future,
|
||||
std::move(promise)));
|
||||
return SharedFutureAndRequestId{std::move(shared_future), req_id};
|
||||
}
|
||||
|
||||
/// Clean all pending requests older than a time_point.
|
||||
/**
|
||||
* \param[in] time_point Requests that were sent before this point are going to be removed.
|
||||
@@ -149,15 +205,52 @@ public:
|
||||
pruned_requests);
|
||||
}
|
||||
|
||||
/// Clean all pending requests.
|
||||
/**
|
||||
* \return number of pending requests that were removed.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
prune_pending_requests();
|
||||
|
||||
/// Cleanup a pending request.
|
||||
/**
|
||||
* This notifies the client that we have waited long enough for a response from the server
|
||||
* to come, we have given up and we are not waiting for a response anymore.
|
||||
*
|
||||
* Not calling this will make the client start using more memory for each request
|
||||
* that never got a reply from the server.
|
||||
*
|
||||
* \param[in] request_id request id returned by async_send_request().
|
||||
* \return true when a pending request was removed, false if not (e.g. a response was received).
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
remove_pending_request(
|
||||
int64_t request_id);
|
||||
|
||||
/// Cleanup a pending request.
|
||||
/**
|
||||
* Convenient overload, same as:
|
||||
*
|
||||
* `GenericClient::remove_pending_request(this, future.request_id)`.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
remove_pending_request(
|
||||
const FutureAndRequestId & future);
|
||||
|
||||
/// Cleanup a pending request.
|
||||
/**
|
||||
* Convenient overload, same as:
|
||||
*
|
||||
* `GenericClient::remove_pending_request(this, future.request_id)`.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
remove_pending_request(
|
||||
const SharedFutureAndRequestId & future);
|
||||
|
||||
/// Take the next response for this client.
|
||||
/**
|
||||
* \sa ClientBase::take_type_erased_response().
|
||||
@@ -179,9 +272,12 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
using CallbackTypeValueVariant = std::tuple<CallbackType, SharedFuture, Promise>;
|
||||
using CallbackInfoVariant = std::variant<
|
||||
std::promise<SharedResponse>>; // Use variant for extension
|
||||
std::promise<SharedResponse>,
|
||||
CallbackTypeValueVariant>; // Use variant for extension
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
int64_t
|
||||
async_send_request_impl(
|
||||
const Request request,
|
||||
|
||||
@@ -31,21 +31,20 @@ namespace rclcpp
|
||||
template<typename MessageT, typename AllocatorT = std::allocator<void>>
|
||||
class LoanedMessage
|
||||
{
|
||||
public:
|
||||
using MessageAllocatorTraits = rclcpp::allocator::AllocRebind<MessageT, AllocatorT>;
|
||||
using MessageAllocator = typename MessageAllocatorTraits::allocator_type;
|
||||
|
||||
public:
|
||||
/// Constructor of the LoanedMessage class.
|
||||
/**
|
||||
* The constructor of this class allocates memory for a given message type
|
||||
* and associates this with a given publisher.
|
||||
*
|
||||
* Given the publisher instance, a case differentiation is being performaned
|
||||
* which decides whether the underlying middleware is able to allocate the appropriate
|
||||
* memory for this message type or not.
|
||||
* In the case that the middleware can not loan messages, the passed in allocator instance
|
||||
* is being used to allocate the message within the scope of this class.
|
||||
* Otherwise, the allocator is being ignored and the allocation is solely performaned
|
||||
* The underlying middleware is queried to determine whether it is able to allocate the
|
||||
* appropriate memory for this message type or not.
|
||||
* In the case that the middleware cannot loan messages, the passed in allocator instance
|
||||
* is used to allocate the message within the scope of this class.
|
||||
* Otherwise, the allocator is ignored and the allocation is solely performed
|
||||
* in the underlying middleware with its appropriate allocation strategy.
|
||||
* The need for this arises as the user code can be written explicitly targeting a middleware
|
||||
* capable of loaning messages.
|
||||
@@ -53,12 +52,12 @@ public:
|
||||
* a middleware which doesn't support message loaning in which case the allocator will be used.
|
||||
*
|
||||
* \param[in] pub rclcpp::Publisher instance to which the memory belongs
|
||||
* \param[in] allocator Allocator instance in case middleware can not allocate messages
|
||||
* \param[in] allocator Allocator instance in case middleware cannot allocate messages
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
*/
|
||||
LoanedMessage(
|
||||
const rclcpp::PublisherBase & pub,
|
||||
std::allocator<MessageT> allocator)
|
||||
MessageAllocator allocator)
|
||||
: pub_(pub),
|
||||
message_(nullptr),
|
||||
message_allocator_(std::move(allocator))
|
||||
|
||||
@@ -1430,7 +1430,7 @@ public:
|
||||
rclcpp::Clock::ConstSharedPtr
|
||||
get_clock() const;
|
||||
|
||||
/// Returns current time from the time source specified by clock_type.
|
||||
/// Returns current time from the node clock.
|
||||
/**
|
||||
* \sa rclcpp::Clock::now
|
||||
*/
|
||||
|
||||
@@ -146,8 +146,7 @@ public:
|
||||
const rclcpp::QoS & qos,
|
||||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options)
|
||||
{
|
||||
// Topic is unused for now.
|
||||
(void)topic;
|
||||
(void)qos;
|
||||
(void)options;
|
||||
|
||||
// If needed, setup intra process communication.
|
||||
@@ -155,22 +154,26 @@ public:
|
||||
auto context = node_base->get_context();
|
||||
// Get the intra process manager instance for this context.
|
||||
auto ipm = context->get_sub_context<rclcpp::experimental::IntraProcessManager>();
|
||||
// Register the publisher with the intra process manager.
|
||||
if (qos.history() != rclcpp::HistoryPolicy::KeepLast) {
|
||||
// Check if the QoS is compatible with intra-process.
|
||||
auto qos_profile = get_actual_qos();
|
||||
if (qos_profile.history() != rclcpp::HistoryPolicy::KeepLast) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication allowed only with keep last history qos policy");
|
||||
"intraprocess communication on topic '" + topic +
|
||||
"' allowed only with keep last history qos policy");
|
||||
}
|
||||
if (qos.depth() == 0) {
|
||||
if (qos_profile.depth() == 0) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication is not allowed with a zero qos history depth value");
|
||||
"intraprocess communication on topic '" + topic +
|
||||
"' is not allowed with a zero qos history depth value");
|
||||
}
|
||||
if (qos.durability() == rclcpp::DurabilityPolicy::TransientLocal) {
|
||||
if (qos_profile.durability() == rclcpp::DurabilityPolicy::TransientLocal) {
|
||||
buffer_ = rclcpp::experimental::create_intra_process_buffer<
|
||||
ROSMessageType, ROSMessageTypeAllocator, ROSMessageTypeDeleter>(
|
||||
rclcpp::detail::resolve_intra_process_buffer_type(options_.intra_process_buffer_type),
|
||||
qos,
|
||||
qos_profile,
|
||||
std::make_shared<ROSMessageTypeAllocator>(ros_message_type_allocator_));
|
||||
}
|
||||
// Register the publisher with the intra process manager.
|
||||
uint64_t intra_process_publisher_id = ipm->add_publisher(this->shared_from_this(), buffer_);
|
||||
this->setup_intra_process(
|
||||
intra_process_publisher_id,
|
||||
@@ -232,8 +235,12 @@ public:
|
||||
// interprocess publish, resulting in lower publish-to-subscribe latency.
|
||||
// It's not possible to do that with an unique_ptr,
|
||||
// as do_intra_process_publish takes the ownership of the message.
|
||||
|
||||
// When durability is set to TransientLocal (i.e. there is a buffer),
|
||||
// inter process publish should always take place to ensure
|
||||
// late joiners receive past data.
|
||||
bool inter_process_publish_needed =
|
||||
get_subscription_count() > get_intra_process_subscription_count();
|
||||
get_subscription_count() > get_intra_process_subscription_count() || buffer_;
|
||||
|
||||
if (inter_process_publish_needed) {
|
||||
auto shared_msg =
|
||||
@@ -310,8 +317,11 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
// When durability is set to TransientLocal (i.e. there is a buffer),
|
||||
// inter process publish should always take place to ensure
|
||||
// late joiners receive past data.
|
||||
bool inter_process_publish_needed =
|
||||
get_subscription_count() > get_intra_process_subscription_count();
|
||||
get_subscription_count() > get_intra_process_subscription_count() || buffer_;
|
||||
|
||||
if (inter_process_publish_needed) {
|
||||
auto ros_msg_ptr = std::make_shared<ROSMessageType>();
|
||||
|
||||
@@ -133,6 +133,9 @@
|
||||
* - Dynamic typesupport
|
||||
* - rclcpp::dynamic_typesupport::DynamicMessageTypeSupport
|
||||
* - rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp
|
||||
* - Dynamic subscription
|
||||
* - rclcpp::DynamicSubscription
|
||||
* - rclcpp/dynamic_subscription.hpp
|
||||
* - Generic publisher
|
||||
* - rclcpp::Node::create_generic_publisher()
|
||||
* - rclcpp::GenericPublisher
|
||||
@@ -184,4 +187,6 @@
|
||||
#include "rclcpp/waitable.hpp"
|
||||
#include "rclcpp/wait_set.hpp"
|
||||
|
||||
#include "rclcpp/dynamic_subscription.hpp"
|
||||
|
||||
#endif // RCLCPP__RCLCPP_HPP_
|
||||
|
||||
@@ -147,11 +147,13 @@ public:
|
||||
auto qos_profile = get_actual_qos();
|
||||
if (qos_profile.history() != rclcpp::HistoryPolicy::KeepLast) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication allowed only with keep last history qos policy");
|
||||
"intraprocess communication on topic '" + topic_name +
|
||||
"' allowed only with keep last history qos policy");
|
||||
}
|
||||
if (qos_profile.depth() == 0) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication is not allowed with 0 depth qos policy");
|
||||
"intraprocess communication on topic '" + topic_name +
|
||||
"' is not allowed with 0 depth qos policy");
|
||||
}
|
||||
|
||||
using SubscriptionIntraProcessT = rclcpp::experimental::SubscriptionIntraProcess<
|
||||
|
||||
@@ -644,6 +644,10 @@ protected:
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface * const node_base_;
|
||||
|
||||
// TODO(methylDragon): Remove if we don't need this
|
||||
// rclcpp::node_interfaces::NodeGraphInterface * const node_graph_;
|
||||
// rclcpp::node_interfaces::NodeServicesInterface * const node_services_;
|
||||
|
||||
std::shared_ptr<rcl_node_t> node_handle_;
|
||||
|
||||
std::recursive_mutex callback_mutex_;
|
||||
|
||||
@@ -80,7 +80,8 @@ struct SubscriptionOptionsBase
|
||||
|
||||
// An optional QoS which can provide topic_statistics with a stable QoS separate from
|
||||
// the subscription's current QoS settings which could be unstable.
|
||||
rclcpp::QoS qos = SystemDefaultsQoS();
|
||||
// Explicitly set the enough depth to avoid missing the statistics messages.
|
||||
rclcpp::QoS qos = SystemDefaultsQoS().keep_last(10);
|
||||
};
|
||||
|
||||
TopicStatisticsOptions topic_stats_options;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="2">
|
||||
<name>rclcpp</name>
|
||||
<version>29.0.0</version>
|
||||
<version>29.3.0</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
113
rclcpp/src/rclcpp/dynamic_subscription.cpp
Normal file
113
rclcpp/src/rclcpp/dynamic_subscription.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright 2022 Open Source Robotics Foundation, 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.
|
||||
|
||||
#include "rclcpp/dynamic_subscription.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rcl/subscription.h"
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
std::shared_ptr<void> DynamicSubscription::create_message()
|
||||
{
|
||||
return create_serialized_message();
|
||||
}
|
||||
|
||||
std::shared_ptr<rclcpp::SerializedMessage> DynamicSubscription::create_serialized_message()
|
||||
{
|
||||
return std::make_shared<rclcpp::SerializedMessage>(0);
|
||||
}
|
||||
|
||||
void DynamicSubscription::handle_message(std::shared_ptr<void> &, const rclcpp::MessageInfo &)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError(
|
||||
"handle_message is not implemented for DynamicSubscription");
|
||||
}
|
||||
|
||||
void DynamicSubscription::handle_serialized_message(
|
||||
const std::shared_ptr<rclcpp::SerializedMessage> &, const rclcpp::MessageInfo &)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError(
|
||||
"handle_serialized_message is not implemented for DynamicSubscription");
|
||||
}
|
||||
|
||||
void DynamicSubscription::handle_loaned_message(void *, const rclcpp::MessageInfo &)
|
||||
{
|
||||
throw rclcpp::exceptions::UnimplementedError(
|
||||
"handle_loaned_message is not implemented for DynamicSubscription");
|
||||
}
|
||||
|
||||
void DynamicSubscription::return_message(std::shared_ptr<void> & message)
|
||||
{
|
||||
auto typed_message = std::static_pointer_cast<rclcpp::SerializedMessage>(message);
|
||||
return_serialized_message(typed_message);
|
||||
}
|
||||
|
||||
void DynamicSubscription::return_serialized_message(
|
||||
std::shared_ptr<rclcpp::SerializedMessage> & message)
|
||||
{
|
||||
message.reset();
|
||||
}
|
||||
|
||||
|
||||
// DYNAMIC TYPE ====================================================================================
|
||||
// TODO(methylDragon): Re-order later
|
||||
|
||||
// Does not clone
|
||||
rclcpp::dynamic_typesupport::DynamicMessageType::SharedPtr
|
||||
DynamicSubscription::get_shared_dynamic_message_type()
|
||||
{
|
||||
return dynamic_message_type_;
|
||||
}
|
||||
|
||||
// Does not clone
|
||||
rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr
|
||||
DynamicSubscription::get_shared_dynamic_message()
|
||||
{
|
||||
return dynamic_message_;
|
||||
}
|
||||
|
||||
rclcpp::dynamic_typesupport::DynamicSerializationSupport::SharedPtr
|
||||
DynamicSubscription::get_shared_dynamic_serialization_support()
|
||||
{
|
||||
return serialization_support_;
|
||||
}
|
||||
|
||||
rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr
|
||||
DynamicSubscription::create_dynamic_message()
|
||||
{
|
||||
return dynamic_message_->init_from_type_shared(*dynamic_message_type_);
|
||||
}
|
||||
|
||||
void
|
||||
DynamicSubscription::return_dynamic_message(
|
||||
rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message)
|
||||
{
|
||||
message.reset();
|
||||
}
|
||||
|
||||
void DynamicSubscription::handle_dynamic_message(
|
||||
const rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message,
|
||||
const rclcpp::MessageInfo & message_info)
|
||||
{
|
||||
(void) message_info;
|
||||
callback_(message, ts_->get_rosidl_runtime_c_type_description());
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
@@ -36,5 +36,734 @@ using rclcpp::dynamic_typesupport::DynamicMessageType;
|
||||
using rclcpp::dynamic_typesupport::DynamicMessageTypeBuilder;
|
||||
using rclcpp::dynamic_typesupport::DynamicSerializationSupport;
|
||||
|
||||
#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_MESSAGE_IMPL_HPP_
|
||||
// Template specialization implementations
|
||||
#include "rclcpp/dynamic_typesupport/detail/dynamic_message_impl.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
// CONSTRUCTION ==================================================================================
|
||||
DynamicMessage::DynamicMessage(const DynamicMessageTypeBuilder::SharedPtr dynamic_type_builder)
|
||||
: DynamicMessage::DynamicMessage(
|
||||
dynamic_type_builder, dynamic_type_builder->get_rosidl_dynamic_type_builder().allocator) {}
|
||||
|
||||
|
||||
DynamicMessage::DynamicMessage(
|
||||
const DynamicMessageTypeBuilder::SharedPtr dynamic_type_builder,
|
||||
rcl_allocator_t allocator)
|
||||
: serialization_support_(dynamic_type_builder->get_shared_dynamic_serialization_support()),
|
||||
rosidl_dynamic_data_(rosidl_dynamic_typesupport_get_zero_initialized_dynamic_data()),
|
||||
is_loaned_(false),
|
||||
parent_data_(nullptr)
|
||||
{
|
||||
if (!serialization_support_) {
|
||||
throw std::runtime_error("dynamic message could not bind serialization support!");
|
||||
}
|
||||
if (!dynamic_type_builder) {
|
||||
throw std::runtime_error("dynamic message type builder cannot be nullptr!");
|
||||
}
|
||||
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_t rosidl_dynamic_type_builder =
|
||||
dynamic_type_builder->get_rosidl_dynamic_type_builder();
|
||||
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_init_from_dynamic_type_builder(
|
||||
&rosidl_dynamic_type_builder, &allocator, &get_rosidl_dynamic_data());
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not init new dynamic data object from dynamic type builder");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::DynamicMessage(const DynamicMessageType::SharedPtr dynamic_type)
|
||||
: DynamicMessage::DynamicMessage(
|
||||
dynamic_type, dynamic_type->get_rosidl_dynamic_type().allocator) {}
|
||||
|
||||
|
||||
DynamicMessage::DynamicMessage(
|
||||
const DynamicMessageType::SharedPtr dynamic_type,
|
||||
rcl_allocator_t allocator)
|
||||
: serialization_support_(dynamic_type->get_shared_dynamic_serialization_support()),
|
||||
rosidl_dynamic_data_(rosidl_dynamic_typesupport_get_zero_initialized_dynamic_data()),
|
||||
is_loaned_(false),
|
||||
parent_data_(nullptr)
|
||||
{
|
||||
if (!serialization_support_) {
|
||||
throw std::runtime_error("dynamic type could not bind serialization support!");
|
||||
}
|
||||
if (!dynamic_type) {
|
||||
throw std::runtime_error("dynamic message type cannot be nullptr!");
|
||||
}
|
||||
|
||||
rosidl_dynamic_typesupport_dynamic_type_t rosidl_dynamic_type =
|
||||
dynamic_type->get_rosidl_dynamic_type();
|
||||
|
||||
rosidl_dynamic_typesupport_dynamic_data_t rosidl_dynamic_data =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_data();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_init_from_dynamic_type(
|
||||
&rosidl_dynamic_type, &allocator, &rosidl_dynamic_data);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could not init new dynamic data object from dynamic type") +
|
||||
rcl_get_error_string().str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::DynamicMessage(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
rosidl_dynamic_typesupport_dynamic_data_t && rosidl_dynamic_data)
|
||||
: serialization_support_(serialization_support),
|
||||
rosidl_dynamic_data_(std::move(rosidl_dynamic_data)),
|
||||
is_loaned_(false),
|
||||
parent_data_(nullptr)
|
||||
{
|
||||
if (serialization_support) {
|
||||
if (!match_serialization_support_(*serialization_support, rosidl_dynamic_data)) {
|
||||
throw std::runtime_error(
|
||||
"serialization support library identifier does not match dynamic data's!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::DynamicMessage(
|
||||
DynamicMessage::SharedPtr parent_data,
|
||||
rosidl_dynamic_typesupport_dynamic_data_t && rosidl_loaned_data)
|
||||
: serialization_support_(parent_data->get_shared_dynamic_serialization_support()),
|
||||
rosidl_dynamic_data_(std::move(rosidl_loaned_data)),
|
||||
is_loaned_(true),
|
||||
parent_data_(nullptr)
|
||||
{
|
||||
if (!parent_data) {
|
||||
throw std::runtime_error("parent dynamic data cannot be nullptr!");
|
||||
}
|
||||
if (serialization_support_) {
|
||||
if (!match_serialization_support_(*serialization_support_, rosidl_loaned_data)) {
|
||||
throw std::runtime_error(
|
||||
"serialization support library identifier does not match loaned dynamic data's!");
|
||||
}
|
||||
}
|
||||
parent_data_ = parent_data;
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::DynamicMessage(DynamicMessage && other) noexcept
|
||||
: serialization_support_(std::exchange(other.serialization_support_, nullptr)),
|
||||
rosidl_dynamic_data_(std::exchange(
|
||||
other.rosidl_dynamic_data_,
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_data())),
|
||||
is_loaned_(other.is_loaned_),
|
||||
parent_data_(std::exchange(other.parent_data_, nullptr))
|
||||
{}
|
||||
|
||||
|
||||
DynamicMessage &
|
||||
DynamicMessage::operator=(DynamicMessage && other) noexcept
|
||||
{
|
||||
std::swap(serialization_support_, other.serialization_support_);
|
||||
std::swap(rosidl_dynamic_data_, other.rosidl_dynamic_data_);
|
||||
is_loaned_ = other.is_loaned_;
|
||||
std::swap(parent_data_, other.parent_data_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::~DynamicMessage()
|
||||
{} // STUBBED
|
||||
{
|
||||
if (!is_loaned_) {
|
||||
if (rosidl_dynamic_typesupport_dynamic_data_fini(&get_rosidl_dynamic_data()) !=
|
||||
RCUTILS_RET_OK)
|
||||
{
|
||||
RCUTILS_LOG_ERROR("could not fini rosidl dynamic data");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Loaned case
|
||||
if (!parent_data_) {
|
||||
RCUTILS_LOG_ERROR("dynamic data is loaned, but parent is missing!!");
|
||||
} else {
|
||||
rosidl_dynamic_typesupport_dynamic_data_return_loaned_value(
|
||||
&parent_data_->get_rosidl_dynamic_data(), &get_rosidl_dynamic_data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DynamicMessage::match_serialization_support_(
|
||||
const DynamicSerializationSupport & serialization_support,
|
||||
const rosidl_dynamic_typesupport_dynamic_data_t & rosidl_dynamic_type_data)
|
||||
{
|
||||
if (serialization_support.get_serialization_library_identifier() != std::string(
|
||||
rosidl_dynamic_type_data.serialization_support->serialization_library_identifier))
|
||||
{
|
||||
RCUTILS_LOG_ERROR("serialization support library identifier does not match dynamic data's");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// GETTERS =======================================================================================
|
||||
const std::string
|
||||
DynamicMessage::get_serialization_library_identifier() const
|
||||
{
|
||||
return std::string(
|
||||
get_rosidl_dynamic_data().serialization_support->serialization_library_identifier);
|
||||
}
|
||||
|
||||
|
||||
const std::string
|
||||
DynamicMessage::get_name() const
|
||||
{
|
||||
size_t buf_length;
|
||||
const char * buf;
|
||||
if (
|
||||
rosidl_dynamic_typesupport_dynamic_data_get_name(
|
||||
&get_rosidl_dynamic_data(), &buf,
|
||||
&buf_length) !=
|
||||
RCUTILS_RET_OK)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("could not get name for dynamic data") + rcl_get_error_string().str);
|
||||
}
|
||||
return std::string(buf, buf_length);
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_dynamic_data_t &
|
||||
DynamicMessage::get_rosidl_dynamic_data()
|
||||
{
|
||||
return rosidl_dynamic_data_;
|
||||
}
|
||||
|
||||
|
||||
const rosidl_dynamic_typesupport_dynamic_data_t &
|
||||
DynamicMessage::get_rosidl_dynamic_data() const
|
||||
{
|
||||
return rosidl_dynamic_data_;
|
||||
}
|
||||
|
||||
|
||||
DynamicSerializationSupport::SharedPtr
|
||||
DynamicMessage::get_shared_dynamic_serialization_support()
|
||||
{
|
||||
return serialization_support_;
|
||||
}
|
||||
|
||||
|
||||
DynamicSerializationSupport::ConstSharedPtr
|
||||
DynamicMessage::get_shared_dynamic_serialization_support() const
|
||||
{
|
||||
return serialization_support_;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
DynamicMessage::get_item_count() const
|
||||
{
|
||||
size_t item_count;
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_get_item_count(
|
||||
&get_rosidl_dynamic_data(), &item_count);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not get item count of dynamic data");
|
||||
}
|
||||
return item_count;
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::get_member_id(size_t index) const
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t member_id;
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_get_member_id_at_index(
|
||||
&get_rosidl_dynamic_data(), index, &member_id);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not member id of dynamic data element by index");
|
||||
}
|
||||
return member_id;
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::get_member_id(const std::string & name) const
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t member_id;
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_get_member_id_by_name(
|
||||
&get_rosidl_dynamic_data(), name.c_str(), name.size(), &member_id);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not member id of dynamic data element by name");
|
||||
}
|
||||
return member_id;
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::get_array_index(size_t index) const
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t array_index;
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_get_array_index(
|
||||
&get_rosidl_dynamic_data(), index, &array_index);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not array index of dynamic data element by index");
|
||||
}
|
||||
return array_index;
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::get_array_index(const std::string & name) const
|
||||
{
|
||||
return get_array_index(get_member_id(name));
|
||||
}
|
||||
|
||||
|
||||
// METHODS =======================================================================================
|
||||
DynamicMessage
|
||||
DynamicMessage::clone(rcl_allocator_t allocator)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_t rosidl_dynamic_data =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_data();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_clone(
|
||||
&get_rosidl_dynamic_data(), &allocator, &rosidl_dynamic_data);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could not clone dynamic data: ") + rcl_get_error_string().str);
|
||||
}
|
||||
return DynamicMessage(get_shared_dynamic_serialization_support(), std::move(rosidl_dynamic_data));
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::SharedPtr
|
||||
DynamicMessage::clone_shared(rcl_allocator_t allocator)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_t rosidl_dynamic_data =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_data();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_clone(
|
||||
&get_rosidl_dynamic_data(), &allocator, &rosidl_dynamic_data);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could not clone dynamic data: ") + rcl_get_error_string().str);
|
||||
}
|
||||
return DynamicMessage::make_shared(
|
||||
get_shared_dynamic_serialization_support(), std::move(rosidl_dynamic_data));
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage
|
||||
DynamicMessage::init_from_type(DynamicMessageType & type, rcl_allocator_t allocator) const
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_t rosidl_dynamic_data =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_data();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_init_from_dynamic_type(
|
||||
&type.get_rosidl_dynamic_type(), &allocator, &rosidl_dynamic_data);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not init new dynamic data object from dynamic type");
|
||||
}
|
||||
return DynamicMessage(serialization_support_, std::move(rosidl_dynamic_data));
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::SharedPtr
|
||||
DynamicMessage::init_from_type_shared(DynamicMessageType & type, rcl_allocator_t allocator) const
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_t rosidl_dynamic_data =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_data();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_init_from_dynamic_type(
|
||||
&type.get_rosidl_dynamic_type(), &allocator, &rosidl_dynamic_data);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not init new dynamic data object from dynamic type");
|
||||
}
|
||||
return DynamicMessage::make_shared(serialization_support_, std::move(rosidl_dynamic_data));
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DynamicMessage::equals(const DynamicMessage & other) const
|
||||
{
|
||||
if (get_serialization_library_identifier() != other.get_serialization_library_identifier()) {
|
||||
throw std::runtime_error("library identifiers don't match");
|
||||
}
|
||||
bool equals;
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_equals(
|
||||
&get_rosidl_dynamic_data(), &other.get_rosidl_dynamic_data(), &equals);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not equate dynamic messages");
|
||||
}
|
||||
return equals;
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::SharedPtr
|
||||
DynamicMessage::loan_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id,
|
||||
rcl_allocator_t allocator)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_t rosidl_dynamic_data =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_data();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_loan_value(
|
||||
&get_rosidl_dynamic_data(), id, &allocator, &rosidl_dynamic_data);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could not loan dynamic data: ") + rcl_get_error_string().str);
|
||||
}
|
||||
return DynamicMessage::make_shared(shared_from_this(), std::move(rosidl_dynamic_data));
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::SharedPtr
|
||||
DynamicMessage::loan_value(const std::string & name, rcl_allocator_t allocator)
|
||||
{
|
||||
return loan_value(get_member_id(name), allocator);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::clear_all_values()
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_clear_all_values(&get_rosidl_dynamic_data());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::clear_nonkey_values()
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_clear_nonkey_values(&get_rosidl_dynamic_data());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::clear_value(rosidl_dynamic_typesupport_member_id_t id)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_clear_value(&get_rosidl_dynamic_data(), id);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::clear_value(const std::string & name)
|
||||
{
|
||||
clear_value(get_member_id(name));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::clear_sequence()
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_clear_sequence_data(&get_rosidl_dynamic_data());
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::insert_sequence_data()
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t out;
|
||||
rosidl_dynamic_typesupport_dynamic_data_insert_sequence_data(&get_rosidl_dynamic_data(), &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::remove_sequence_data(rosidl_dynamic_typesupport_member_id_t index)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_remove_sequence_data(
|
||||
&get_rosidl_dynamic_data(), index);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DynamicMessage::serialize(rcl_serialized_message_t & buffer)
|
||||
{
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_serialize(
|
||||
&get_rosidl_dynamic_data(), &buffer);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could serialize loan dynamic data: ") + rcl_get_error_string().str);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DynamicMessage::deserialize(rcl_serialized_message_t & buffer)
|
||||
{
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_data_deserialize(
|
||||
&get_rosidl_dynamic_data(), &buffer);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could deserialize loan dynamic data: ") + rcl_get_error_string().str);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// MEMBER ACCESS ===================================================================================
|
||||
// Defined in "detail/dynamic_message_impl.hpp"
|
||||
|
||||
|
||||
// FIXED STRING MEMBER ACCESS ======================================================================
|
||||
const std::string
|
||||
DynamicMessage::get_fixed_string_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, size_t string_length)
|
||||
{
|
||||
size_t buf_length;
|
||||
char * buf = nullptr;
|
||||
rosidl_dynamic_typesupport_dynamic_data_get_fixed_string_value(
|
||||
&get_rosidl_dynamic_data(), id, &buf, &buf_length, string_length);
|
||||
auto out = std::string(buf, buf_length);
|
||||
delete buf;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
const std::string
|
||||
DynamicMessage::get_fixed_string_value(const std::string & name, size_t string_length)
|
||||
{
|
||||
return get_fixed_string_value(get_member_id(name), string_length);
|
||||
}
|
||||
|
||||
|
||||
const std::u16string
|
||||
DynamicMessage::get_fixed_wstring_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, size_t wstring_length)
|
||||
{
|
||||
size_t buf_length;
|
||||
char16_t * buf = nullptr;
|
||||
rosidl_dynamic_typesupport_dynamic_data_get_fixed_wstring_value(
|
||||
&get_rosidl_dynamic_data(), id, &buf, &buf_length, wstring_length);
|
||||
auto out = std::u16string(buf, buf_length);
|
||||
delete buf;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
const std::u16string
|
||||
DynamicMessage::get_fixed_wstring_value(const std::string & name, size_t wstring_length)
|
||||
{
|
||||
return get_fixed_wstring_value(get_member_id(name), wstring_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::set_fixed_string_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string value, size_t string_length)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_set_fixed_string_value(
|
||||
&get_rosidl_dynamic_data(), id, value.c_str(), value.size(), string_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::set_fixed_string_value(
|
||||
const std::string & name, const std::string value, size_t string_length)
|
||||
{
|
||||
set_fixed_string_value(get_member_id(name), value, string_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::set_fixed_wstring_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::u16string value, size_t wstring_length)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_set_fixed_wstring_value(
|
||||
&get_rosidl_dynamic_data(), id, value.c_str(), value.size(), wstring_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::set_fixed_wstring_value(
|
||||
const std::string & name, const std::u16string value, size_t wstring_length)
|
||||
{
|
||||
set_fixed_wstring_value(get_member_id(name), value, wstring_length);
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::insert_fixed_string_value(const std::string value, size_t string_length)
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t out;
|
||||
rosidl_dynamic_typesupport_dynamic_data_insert_fixed_string_value(
|
||||
&get_rosidl_dynamic_data(), value.c_str(), value.size(), string_length, &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::insert_fixed_wstring_value(const std::u16string value, size_t wstring_length)
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t out;
|
||||
rosidl_dynamic_typesupport_dynamic_data_insert_fixed_wstring_value(
|
||||
&get_rosidl_dynamic_data(), value.c_str(), value.size(), wstring_length, &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
// BOUNDED STRING MEMBER ACCESS ====================================================================
|
||||
const std::string
|
||||
DynamicMessage::get_bounded_string_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, size_t string_bound)
|
||||
{
|
||||
size_t buf_length;
|
||||
char * buf = nullptr;
|
||||
rosidl_dynamic_typesupport_dynamic_data_get_bounded_string_value(
|
||||
&get_rosidl_dynamic_data(), id, &buf, &buf_length, string_bound);
|
||||
auto out = std::string(buf, buf_length);
|
||||
delete buf;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
const std::string
|
||||
DynamicMessage::get_bounded_string_value(const std::string & name, size_t string_bound)
|
||||
{
|
||||
return get_bounded_string_value(get_member_id(name), string_bound);
|
||||
}
|
||||
|
||||
|
||||
const std::u16string
|
||||
DynamicMessage::get_bounded_wstring_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, size_t wstring_bound)
|
||||
{
|
||||
size_t buf_length;
|
||||
char16_t * buf = nullptr;
|
||||
rosidl_dynamic_typesupport_dynamic_data_get_bounded_wstring_value(
|
||||
&get_rosidl_dynamic_data(), id, &buf, &buf_length, wstring_bound);
|
||||
auto out = std::u16string(buf, buf_length);
|
||||
delete buf;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
const std::u16string
|
||||
DynamicMessage::get_bounded_wstring_value(const std::string & name, size_t wstring_bound)
|
||||
{
|
||||
return get_bounded_wstring_value(get_member_id(name), wstring_bound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::set_bounded_string_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string value, size_t string_bound)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_set_bounded_string_value(
|
||||
&get_rosidl_dynamic_data(), id, value.c_str(), value.size(), string_bound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::set_bounded_string_value(
|
||||
const std::string & name, const std::string value, size_t string_bound)
|
||||
{
|
||||
set_bounded_string_value(get_member_id(name), value, string_bound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::set_bounded_wstring_value(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::u16string value, size_t wstring_bound)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_set_bounded_wstring_value(
|
||||
&get_rosidl_dynamic_data(), id, value.c_str(), value.size(), wstring_bound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::set_bounded_wstring_value(
|
||||
const std::string & name, const std::u16string value, size_t wstring_bound)
|
||||
{
|
||||
set_bounded_wstring_value(get_member_id(name), value, wstring_bound);
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::insert_bounded_string_value(const std::string value, size_t string_bound)
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t out;
|
||||
rosidl_dynamic_typesupport_dynamic_data_insert_bounded_string_value(
|
||||
&get_rosidl_dynamic_data(), value.c_str(), value.size(), string_bound, &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::insert_bounded_wstring_value(const std::u16string value, size_t wstring_bound)
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t out;
|
||||
rosidl_dynamic_typesupport_dynamic_data_insert_bounded_wstring_value(
|
||||
&get_rosidl_dynamic_data(), value.c_str(), value.size(), wstring_bound, &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
// NESTED MEMBER ACCESS ============================================================================
|
||||
DynamicMessage
|
||||
DynamicMessage::get_nested_data(
|
||||
rosidl_dynamic_typesupport_member_id_t id, rcl_allocator_t allocator)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_t out =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_data();
|
||||
rosidl_dynamic_typesupport_dynamic_data_get_nested_data(
|
||||
&get_rosidl_dynamic_data(), id, &allocator, &out);
|
||||
return DynamicMessage(get_shared_dynamic_serialization_support(), std::move(out));
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage
|
||||
DynamicMessage::get_nested_data(const std::string & name, rcl_allocator_t allocator)
|
||||
{
|
||||
return get_nested_data(get_member_id(name), allocator);
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::SharedPtr
|
||||
DynamicMessage::get_nested_data_shared(
|
||||
rosidl_dynamic_typesupport_member_id_t id, rcl_allocator_t allocator)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_t out =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_data();
|
||||
rosidl_dynamic_typesupport_dynamic_data_get_nested_data(
|
||||
&get_rosidl_dynamic_data(), id, &allocator, &out);
|
||||
return DynamicMessage::make_shared(get_shared_dynamic_serialization_support(), std::move(out));
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::SharedPtr
|
||||
DynamicMessage::get_nested_data_shared(const std::string & name, rcl_allocator_t allocator)
|
||||
{
|
||||
return get_nested_data_shared(get_member_id(name), allocator);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::set_nested_data(
|
||||
rosidl_dynamic_typesupport_member_id_t id, DynamicMessage & value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_data_set_nested_data(
|
||||
&get_rosidl_dynamic_data(), id, &value.get_rosidl_dynamic_data());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessage::set_nested_data(const std::string & name, DynamicMessage & value)
|
||||
{
|
||||
set_nested_data(get_member_id(name), value);
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::insert_nested_data_copy(const DynamicMessage & value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t out;
|
||||
rosidl_dynamic_typesupport_dynamic_data_insert_nested_data_copy(
|
||||
&get_rosidl_dynamic_data(), &value.get_rosidl_dynamic_data(), &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_member_id_t
|
||||
DynamicMessage::insert_nested_data(DynamicMessage & value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_member_id_t out;
|
||||
rosidl_dynamic_typesupport_dynamic_data_insert_nested_data(
|
||||
&get_rosidl_dynamic_data(), &value.get_rosidl_dynamic_data(), &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -34,5 +34,248 @@ using rclcpp::dynamic_typesupport::DynamicMessageType;
|
||||
using rclcpp::dynamic_typesupport::DynamicMessageTypeBuilder;
|
||||
using rclcpp::dynamic_typesupport::DynamicSerializationSupport;
|
||||
|
||||
|
||||
// CONSTRUCTION ====================================================================================
|
||||
DynamicMessageType::DynamicMessageType(DynamicMessageTypeBuilder::SharedPtr dynamic_type_builder)
|
||||
: DynamicMessageType::DynamicMessageType(
|
||||
dynamic_type_builder, dynamic_type_builder->get_rosidl_dynamic_type_builder().allocator) {}
|
||||
|
||||
|
||||
DynamicMessageType::DynamicMessageType(
|
||||
DynamicMessageTypeBuilder::SharedPtr dynamic_type_builder,
|
||||
rcl_allocator_t allocator)
|
||||
: serialization_support_(dynamic_type_builder->get_shared_dynamic_serialization_support()),
|
||||
rosidl_dynamic_type_(rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type())
|
||||
{
|
||||
if (!serialization_support_) {
|
||||
throw std::runtime_error("dynamic type could not bind serialization support!");
|
||||
}
|
||||
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_t rosidl_dynamic_type_builder =
|
||||
dynamic_type_builder->get_rosidl_dynamic_type_builder();
|
||||
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_type_init_from_dynamic_type_builder(
|
||||
&rosidl_dynamic_type_builder, &allocator, &get_rosidl_dynamic_type());
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not init new dynamic type object");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageType::DynamicMessageType(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
rosidl_dynamic_typesupport_dynamic_type_t && rosidl_dynamic_type)
|
||||
: serialization_support_(serialization_support),
|
||||
rosidl_dynamic_type_(std::move(rosidl_dynamic_type))
|
||||
{
|
||||
if (serialization_support) {
|
||||
if (!match_serialization_support_(*serialization_support, rosidl_dynamic_type)) {
|
||||
throw std::runtime_error(
|
||||
"serialization support library identifier does not match dynamic type's!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageType::DynamicMessageType(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator)
|
||||
: serialization_support_(serialization_support),
|
||||
rosidl_dynamic_type_(rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type())
|
||||
{
|
||||
init_from_description(description, allocator, serialization_support);
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageType::DynamicMessageType(DynamicMessageType && other) noexcept
|
||||
: serialization_support_(std::exchange(other.serialization_support_, nullptr)),
|
||||
rosidl_dynamic_type_(std::exchange(
|
||||
other.rosidl_dynamic_type_, rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type()))
|
||||
{}
|
||||
|
||||
|
||||
DynamicMessageType &
|
||||
DynamicMessageType::operator=(DynamicMessageType && other) noexcept
|
||||
{
|
||||
std::swap(serialization_support_, other.serialization_support_);
|
||||
std::swap(rosidl_dynamic_type_, other.rosidl_dynamic_type_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageType::~DynamicMessageType()
|
||||
{} // STUBBED
|
||||
{
|
||||
if (rosidl_dynamic_typesupport_dynamic_type_fini(&get_rosidl_dynamic_type()) != RCUTILS_RET_OK) {
|
||||
RCUTILS_LOG_ERROR("could not fini rosidl dynamic type");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageType::init_from_description(
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator,
|
||||
DynamicSerializationSupport::SharedPtr serialization_support)
|
||||
{
|
||||
if (serialization_support) {
|
||||
// Swap serialization support if serialization support is given
|
||||
serialization_support_ = serialization_support;
|
||||
}
|
||||
|
||||
rosidl_dynamic_typesupport_dynamic_type_t rosidl_dynamic_type =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_type_init_from_description(
|
||||
&serialization_support_->get_rosidl_serialization_support(),
|
||||
&description,
|
||||
&allocator,
|
||||
&rosidl_dynamic_type);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not init new dynamic type object");
|
||||
}
|
||||
|
||||
rosidl_dynamic_type_ = std::move(rosidl_dynamic_type);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DynamicMessageType::match_serialization_support_(
|
||||
const DynamicSerializationSupport & serialization_support,
|
||||
const rosidl_dynamic_typesupport_dynamic_type_t & rosidl_dynamic_type)
|
||||
{
|
||||
if (serialization_support.get_serialization_library_identifier() != std::string(
|
||||
rosidl_dynamic_type.serialization_support->serialization_library_identifier))
|
||||
{
|
||||
RCUTILS_LOG_ERROR(
|
||||
"serialization support library identifier does not match dynamic type's (%s vs %s)",
|
||||
serialization_support.get_serialization_library_identifier().c_str(),
|
||||
rosidl_dynamic_type.serialization_support->serialization_library_identifier);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// GETTERS =========================================================================================
|
||||
const std::string
|
||||
DynamicMessageType::get_serialization_library_identifier() const
|
||||
{
|
||||
return std::string(
|
||||
get_rosidl_dynamic_type().serialization_support->serialization_library_identifier);
|
||||
}
|
||||
|
||||
|
||||
const std::string
|
||||
DynamicMessageType::get_name() const
|
||||
{
|
||||
size_t buf_length;
|
||||
const char * buf;
|
||||
rosidl_dynamic_typesupport_dynamic_type_get_name(&get_rosidl_dynamic_type(), &buf, &buf_length);
|
||||
return std::string(buf, buf_length);
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
DynamicMessageType::get_member_count() const
|
||||
{
|
||||
size_t out;
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_type_get_member_count(
|
||||
&get_rosidl_dynamic_type(), &out);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could not get member count: ") + rcl_get_error_string().str);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_dynamic_type_t &
|
||||
DynamicMessageType::get_rosidl_dynamic_type()
|
||||
{
|
||||
return rosidl_dynamic_type_;
|
||||
}
|
||||
|
||||
|
||||
const rosidl_dynamic_typesupport_dynamic_type_t &
|
||||
DynamicMessageType::get_rosidl_dynamic_type() const
|
||||
{
|
||||
return rosidl_dynamic_type_;
|
||||
}
|
||||
|
||||
|
||||
DynamicSerializationSupport::SharedPtr
|
||||
DynamicMessageType::get_shared_dynamic_serialization_support()
|
||||
{
|
||||
return serialization_support_;
|
||||
}
|
||||
|
||||
|
||||
DynamicSerializationSupport::ConstSharedPtr
|
||||
DynamicMessageType::get_shared_dynamic_serialization_support() const
|
||||
{
|
||||
return serialization_support_;
|
||||
}
|
||||
|
||||
|
||||
// METHODS =========================================================================================
|
||||
DynamicMessageType
|
||||
DynamicMessageType::clone(rcl_allocator_t allocator)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_t rosidl_dynamic_type =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_type_clone(
|
||||
&get_rosidl_dynamic_type(), &allocator, &rosidl_dynamic_type);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could not clone dynamic type: ") + rcl_get_error_string().str);
|
||||
}
|
||||
return DynamicMessageType(
|
||||
get_shared_dynamic_serialization_support(), std::move(rosidl_dynamic_type));
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageType::SharedPtr
|
||||
DynamicMessageType::clone_shared(rcl_allocator_t allocator)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_t rosidl_dynamic_type =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_type_clone(
|
||||
&get_rosidl_dynamic_type(), &allocator, &rosidl_dynamic_type);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could not clone dynamic type: ") + rcl_get_error_string().str);
|
||||
}
|
||||
return DynamicMessageType::make_shared(
|
||||
get_shared_dynamic_serialization_support(), std::move(rosidl_dynamic_type));
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DynamicMessageType::equals(const DynamicMessageType & other) const
|
||||
{
|
||||
if (get_serialization_library_identifier() != other.get_serialization_library_identifier()) {
|
||||
throw std::runtime_error("library identifiers don't match");
|
||||
}
|
||||
bool out;
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_type_equals(
|
||||
&get_rosidl_dynamic_type(), &other.get_rosidl_dynamic_type(), &out);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could not equate dynamic message types: ") + rcl_get_error_string().str);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage
|
||||
DynamicMessageType::build_dynamic_message(rcl_allocator_t allocator)
|
||||
{
|
||||
return DynamicMessage(shared_from_this(), allocator);
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::SharedPtr
|
||||
DynamicMessageType::build_dynamic_message_shared(rcl_allocator_t allocator)
|
||||
{
|
||||
return DynamicMessage::make_shared(shared_from_this(), allocator);
|
||||
}
|
||||
|
||||
@@ -33,5 +33,582 @@ using rclcpp::dynamic_typesupport::DynamicMessageType;
|
||||
using rclcpp::dynamic_typesupport::DynamicMessageTypeBuilder;
|
||||
using rclcpp::dynamic_typesupport::DynamicSerializationSupport;
|
||||
|
||||
#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_MESSAGE_TYPE_BUILDER_IMPL_HPP_
|
||||
// Template specialization implementations
|
||||
#include "rclcpp/dynamic_typesupport/detail/dynamic_message_type_builder_impl.hpp"
|
||||
#endif
|
||||
|
||||
// CONSTRUCTION ====================================================================================
|
||||
DynamicMessageTypeBuilder::DynamicMessageTypeBuilder(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support, const std::string & name)
|
||||
: DynamicMessageTypeBuilder::DynamicMessageTypeBuilder(
|
||||
serialization_support,
|
||||
name,
|
||||
serialization_support->get_rosidl_serialization_support().allocator) {}
|
||||
|
||||
|
||||
DynamicMessageTypeBuilder::DynamicMessageTypeBuilder(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
const std::string & name,
|
||||
rcl_allocator_t allocator)
|
||||
: serialization_support_(serialization_support),
|
||||
rosidl_dynamic_type_builder_(
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type_builder())
|
||||
{
|
||||
init_from_serialization_support_(serialization_support, name, allocator);
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageTypeBuilder::DynamicMessageTypeBuilder(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_t && rosidl_dynamic_type_builder)
|
||||
: serialization_support_(serialization_support),
|
||||
rosidl_dynamic_type_builder_(
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type_builder())
|
||||
{
|
||||
if (!serialization_support) {
|
||||
throw std::runtime_error("serialization support cannot be nullptr!");
|
||||
}
|
||||
if (!match_serialization_support_(*serialization_support, rosidl_dynamic_type_builder)) {
|
||||
throw std::runtime_error(
|
||||
"serialization support library does not match dynamic type builder's!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageTypeBuilder::DynamicMessageTypeBuilder(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator)
|
||||
: serialization_support_(serialization_support),
|
||||
rosidl_dynamic_type_builder_(
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type_builder())
|
||||
{
|
||||
if (!serialization_support) {
|
||||
throw std::runtime_error("serialization support cannot be nullptr!");
|
||||
}
|
||||
init_from_description(description, allocator, serialization_support);
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageTypeBuilder::DynamicMessageTypeBuilder(DynamicMessageTypeBuilder && other) noexcept
|
||||
: serialization_support_(std::exchange(other.serialization_support_, nullptr)),
|
||||
rosidl_dynamic_type_builder_(std::exchange(
|
||||
other.rosidl_dynamic_type_builder_,
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type_builder())) {}
|
||||
|
||||
|
||||
DynamicMessageTypeBuilder &
|
||||
DynamicMessageTypeBuilder::operator=(DynamicMessageTypeBuilder && other) noexcept
|
||||
{
|
||||
std::swap(serialization_support_, other.serialization_support_);
|
||||
std::swap(rosidl_dynamic_type_builder_, other.rosidl_dynamic_type_builder_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageTypeBuilder::~DynamicMessageTypeBuilder()
|
||||
{} // STUBBED
|
||||
{
|
||||
if (rosidl_dynamic_typesupport_dynamic_type_builder_fini(&get_rosidl_dynamic_type_builder()) !=
|
||||
RCUTILS_RET_OK)
|
||||
{
|
||||
RCUTILS_LOG_ERROR("could not fini rosidl dynamic type builder");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::init_from_description(
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator,
|
||||
DynamicSerializationSupport::SharedPtr serialization_support)
|
||||
{
|
||||
if (serialization_support) {
|
||||
// Swap serialization support if serialization support is given
|
||||
serialization_support_ = serialization_support;
|
||||
}
|
||||
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_t rosidl_dynamic_type_builder =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type_builder();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_type_builder_init_from_description(
|
||||
&serialization_support_->get_rosidl_serialization_support(),
|
||||
&description,
|
||||
&allocator,
|
||||
&rosidl_dynamic_type_builder);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not init new dynamic type builder object");
|
||||
}
|
||||
|
||||
rosidl_dynamic_type_builder_ = std::move(rosidl_dynamic_type_builder);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::init_from_serialization_support_(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
const std::string & name,
|
||||
rcl_allocator_t allocator)
|
||||
{
|
||||
if (!serialization_support) {
|
||||
throw std::runtime_error("serialization support cannot be nullptr!");
|
||||
}
|
||||
if (!&serialization_support->get_rosidl_serialization_support()) {
|
||||
throw std::runtime_error("serialization support raw pointer cannot be nullptr!");
|
||||
}
|
||||
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_t rosidl_dynamic_type_builder =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type_builder();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_type_builder_init(
|
||||
&serialization_support->get_rosidl_serialization_support(),
|
||||
name.c_str(), name.size(),
|
||||
&allocator,
|
||||
&rosidl_dynamic_type_builder);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could not init dynamic type builder: ") + rcl_get_error_string().str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DynamicMessageTypeBuilder::match_serialization_support_(
|
||||
const DynamicSerializationSupport & serialization_support,
|
||||
const rosidl_dynamic_typesupport_dynamic_type_builder_t & rosidl_dynamic_type_builder)
|
||||
{
|
||||
if (serialization_support.get_serialization_library_identifier() != std::string(
|
||||
rosidl_dynamic_type_builder.serialization_support->serialization_library_identifier))
|
||||
{
|
||||
RCUTILS_LOG_ERROR(
|
||||
"serialization support library identifier does not match dynamic type builder's");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// GETTERS =======================================================================================
|
||||
const std::string
|
||||
DynamicMessageTypeBuilder::get_serialization_library_identifier() const
|
||||
{
|
||||
return std::string(
|
||||
get_rosidl_dynamic_type_builder().serialization_support->serialization_library_identifier);
|
||||
}
|
||||
|
||||
|
||||
const std::string
|
||||
DynamicMessageTypeBuilder::get_name() const
|
||||
{
|
||||
size_t buf_length;
|
||||
const char * buf;
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_get_name(
|
||||
&get_rosidl_dynamic_type_builder(), &buf, &buf_length);
|
||||
return std::string(buf, buf_length);
|
||||
}
|
||||
|
||||
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_t &
|
||||
DynamicMessageTypeBuilder::get_rosidl_dynamic_type_builder()
|
||||
{
|
||||
return rosidl_dynamic_type_builder_;
|
||||
}
|
||||
|
||||
|
||||
const rosidl_dynamic_typesupport_dynamic_type_builder_t &
|
||||
DynamicMessageTypeBuilder::get_rosidl_dynamic_type_builder() const
|
||||
{
|
||||
return rosidl_dynamic_type_builder_;
|
||||
}
|
||||
|
||||
|
||||
DynamicSerializationSupport::SharedPtr
|
||||
DynamicMessageTypeBuilder::get_shared_dynamic_serialization_support()
|
||||
{
|
||||
return serialization_support_;
|
||||
}
|
||||
|
||||
|
||||
DynamicSerializationSupport::ConstSharedPtr
|
||||
DynamicMessageTypeBuilder::get_shared_dynamic_serialization_support() const
|
||||
{
|
||||
return serialization_support_;
|
||||
}
|
||||
|
||||
|
||||
// METHODS =======================================================================================
|
||||
void
|
||||
DynamicMessageTypeBuilder::set_name(const std::string & name)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_set_name(
|
||||
&get_rosidl_dynamic_type_builder(), name.c_str(), name.size());
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageTypeBuilder
|
||||
DynamicMessageTypeBuilder::clone(rcl_allocator_t allocator)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_t rosidl_dynamic_type_builder =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type_builder();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_type_builder_clone(
|
||||
&get_rosidl_dynamic_type_builder(), &allocator, &rosidl_dynamic_type_builder);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could not clone dynamic type builder: ") + rcl_get_error_string().str);
|
||||
}
|
||||
return DynamicMessageTypeBuilder(
|
||||
get_shared_dynamic_serialization_support(), std::move(rosidl_dynamic_type_builder));
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageTypeBuilder::SharedPtr
|
||||
DynamicMessageTypeBuilder::clone_shared(rcl_allocator_t allocator)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_t rosidl_dynamic_type_builder =
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_dynamic_type_builder();
|
||||
rcutils_ret_t ret = rosidl_dynamic_typesupport_dynamic_type_builder_clone(
|
||||
&get_rosidl_dynamic_type_builder(), &allocator, &rosidl_dynamic_type_builder);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("could not clone dynamic type builder: ") + rcl_get_error_string().str);
|
||||
}
|
||||
return DynamicMessageTypeBuilder::make_shared(
|
||||
get_shared_dynamic_serialization_support(), std::move(rosidl_dynamic_type_builder));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::clear(rcl_allocator_t allocator)
|
||||
{
|
||||
if (!serialization_support_) {
|
||||
throw std::runtime_error(
|
||||
"cannot call clear() on a dynamic type builder with uninitialized serialization support"
|
||||
);
|
||||
}
|
||||
|
||||
const std::string & name = get_name();
|
||||
init_from_serialization_support_(serialization_support_, name, allocator);
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage
|
||||
DynamicMessageTypeBuilder::build_dynamic_message(rcl_allocator_t allocator)
|
||||
{
|
||||
return DynamicMessage(shared_from_this(), allocator);
|
||||
}
|
||||
|
||||
|
||||
DynamicMessage::SharedPtr
|
||||
DynamicMessageTypeBuilder::build_dynamic_message_shared(rcl_allocator_t allocator)
|
||||
{
|
||||
return DynamicMessage::make_shared(shared_from_this(), allocator);
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageType
|
||||
DynamicMessageTypeBuilder::build_dynamic_message_type(rcl_allocator_t allocator)
|
||||
{
|
||||
return DynamicMessageType(shared_from_this(), allocator);
|
||||
}
|
||||
|
||||
|
||||
DynamicMessageType::SharedPtr
|
||||
DynamicMessageTypeBuilder::build_dynamic_message_type_shared(rcl_allocator_t allocator)
|
||||
{
|
||||
return DynamicMessageType::make_shared(shared_from_this(), allocator);
|
||||
}
|
||||
|
||||
|
||||
// ADD MEMBERS =====================================================================================
|
||||
// Defined in "detail/dynamic_message_type_builder_impl.hpp"
|
||||
|
||||
|
||||
// ADD FIXED STRING MEMBERS ========================================================================
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_fixed_string_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_length,
|
||||
const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_fixed_string_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
string_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_fixed_wstring_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_length,
|
||||
const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_fixed_wstring_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
wstring_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_fixed_string_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t string_length, size_t array_length, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_fixed_string_array_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
string_length, array_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_fixed_wstring_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t wstring_length, size_t array_length, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_fixed_wstring_array_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
wstring_length, array_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_fixed_string_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_length,
|
||||
const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_fixed_string_unbounded_sequence_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
string_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_fixed_wstring_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_length,
|
||||
const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_fixed_wstring_unbounded_sequence_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
wstring_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_fixed_string_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t string_length, size_t sequence_bound, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_fixed_string_bounded_sequence_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
string_length, sequence_bound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_fixed_wstring_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t wstring_length, size_t sequence_bound, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_fixed_wstring_bounded_sequence_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
wstring_length, sequence_bound);
|
||||
}
|
||||
|
||||
|
||||
// ADD BOUNDED STRING MEMBERS ======================================================================
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_bounded_string_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_bound,
|
||||
const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_string_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
string_bound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_bounded_wstring_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_bound,
|
||||
const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_wstring_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
wstring_bound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_bounded_string_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t string_bound, size_t array_length, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_string_array_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
string_bound, array_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_bounded_wstring_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t wstring_bound, size_t array_length, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_wstring_array_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
wstring_bound, array_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_bounded_string_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_bound,
|
||||
const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_string_unbounded_sequence_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
string_bound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_bounded_wstring_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_bound,
|
||||
const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_wstring_unbounded_sequence_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
wstring_bound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_bounded_string_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t string_bound, size_t sequence_bound, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_string_bounded_sequence_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
string_bound, sequence_bound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_bounded_wstring_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
size_t wstring_bound, size_t sequence_bound, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_wstring_bounded_sequence_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
wstring_bound, sequence_bound);
|
||||
}
|
||||
|
||||
|
||||
// ADD NESTED MEMBERS ==============================================================================
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_complex_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageType & nested_type, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
&nested_type.get_rosidl_dynamic_type());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_complex_array_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageType & nested_type, size_t array_length, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_array_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
&nested_type.get_rosidl_dynamic_type(), array_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_complex_unbounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageType & nested_type, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_unbounded_sequence_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
&nested_type.get_rosidl_dynamic_type());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_complex_bounded_sequence_member(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageType & nested_type, size_t sequence_bound, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_bounded_sequence_member(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
&nested_type.get_rosidl_dynamic_type(), sequence_bound);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_complex_member_builder(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageTypeBuilder & nested_type_builder, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_member_builder(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
&nested_type_builder.get_rosidl_dynamic_type_builder());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_complex_array_member_builder(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageTypeBuilder & nested_type_builder, size_t array_length,
|
||||
const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_array_member_builder(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
&nested_type_builder.get_rosidl_dynamic_type_builder(), array_length);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_complex_unbounded_sequence_member_builder(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageTypeBuilder & nested_type_builder, const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_unbounded_sequence_member_builder(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
&nested_type_builder.get_rosidl_dynamic_type_builder());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicMessageTypeBuilder::add_complex_bounded_sequence_member_builder(
|
||||
rosidl_dynamic_typesupport_member_id_t id, const std::string & name,
|
||||
DynamicMessageTypeBuilder & nested_type_builder, size_t sequence_bound,
|
||||
const std::string & default_value)
|
||||
{
|
||||
rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_bounded_sequence_member_builder(
|
||||
&get_rosidl_dynamic_type_builder(),
|
||||
id, name.c_str(), name.size(), default_value.c_str(), default_value.size(),
|
||||
&nested_type_builder.get_rosidl_dynamic_type_builder(), sequence_bound);
|
||||
}
|
||||
|
||||
@@ -45,5 +45,273 @@ using rclcpp::dynamic_typesupport::DynamicMessageType;
|
||||
using rclcpp::dynamic_typesupport::DynamicMessageTypeSupport;
|
||||
using rclcpp::dynamic_typesupport::DynamicSerializationSupport;
|
||||
|
||||
// CONSTRUCTION ====================================================================================
|
||||
DynamicMessageTypeSupport::DynamicMessageTypeSupport(
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
const std::string & serialization_library_name,
|
||||
rcl_allocator_t allocator)
|
||||
: serialization_support_(nullptr),
|
||||
dynamic_message_type_(nullptr),
|
||||
dynamic_message_(nullptr),
|
||||
rosidl_message_type_support_(rosidl_get_zero_initialized_message_type_support_handle())
|
||||
{
|
||||
rcl_ret_t ret;
|
||||
if (serialization_library_name.empty()) {
|
||||
ret = rcl_dynamic_message_type_support_handle_init(
|
||||
nullptr, &description, &allocator, &rosidl_message_type_support_);
|
||||
} else {
|
||||
ret = rcl_dynamic_message_type_support_handle_init(
|
||||
serialization_library_name.c_str(), &description, &allocator, &rosidl_message_type_support_);
|
||||
}
|
||||
if (ret != RCL_RET_OK) {
|
||||
std::string error_msg =
|
||||
std::string("error initializing rosidl message type support: ") + rcl_get_error_string().str;
|
||||
rcl_reset_error();
|
||||
throw std::runtime_error(error_msg);
|
||||
}
|
||||
if (rosidl_message_type_support_.typesupport_identifier !=
|
||||
rosidl_get_dynamic_typesupport_identifier())
|
||||
{
|
||||
throw std::runtime_error("rosidl message type support is of the wrong type");
|
||||
}
|
||||
|
||||
auto ts_impl = static_cast<rosidl_dynamic_message_type_support_impl_t *>(const_cast<void *>(
|
||||
rosidl_message_type_support_.data));
|
||||
|
||||
serialization_support_ = DynamicSerializationSupport::make_shared(
|
||||
std::move(ts_impl->serialization_support));
|
||||
|
||||
dynamic_message_type_ = DynamicMessageType::make_shared(
|
||||
get_shared_dynamic_serialization_support(), std::move(*ts_impl->dynamic_message_type));
|
||||
|
||||
dynamic_message_ = DynamicMessage::make_shared(
|
||||
get_shared_dynamic_serialization_support(), std::move(*ts_impl->dynamic_message));
|
||||
}
|
||||
|
||||
DynamicMessageTypeSupport::DynamicMessageTypeSupport(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator)
|
||||
: serialization_support_(serialization_support),
|
||||
dynamic_message_type_(nullptr),
|
||||
dynamic_message_(nullptr),
|
||||
rosidl_message_type_support_(rosidl_get_zero_initialized_message_type_support_handle())
|
||||
{
|
||||
// Check null
|
||||
if (!serialization_support) {
|
||||
throw std::runtime_error("serialization_support cannot be nullptr.");
|
||||
}
|
||||
|
||||
rosidl_type_hash_t type_hash;
|
||||
rcutils_ret_t hash_ret = rcl_calculate_type_hash(
|
||||
// TODO(methylDragon): Swap this out with the conversion function when it is ready
|
||||
reinterpret_cast<const type_description_interfaces__msg__TypeDescription *>(&description),
|
||||
&type_hash);
|
||||
if (hash_ret != RCL_RET_OK) {
|
||||
throw std::runtime_error("failed to get type hash");
|
||||
}
|
||||
|
||||
rcutils_ret_t ret = rosidl_dynamic_message_type_support_handle_init(
|
||||
&serialization_support->get_rosidl_serialization_support(),
|
||||
&type_hash, // type_hash
|
||||
&description, // type_description
|
||||
nullptr, // type_description_sources (not implemented for dynamic types)
|
||||
&allocator,
|
||||
&rosidl_message_type_support_);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
throw std::runtime_error("could not init rosidl message type support");
|
||||
}
|
||||
if (rosidl_message_type_support_.typesupport_identifier !=
|
||||
rosidl_get_dynamic_typesupport_identifier())
|
||||
{
|
||||
throw std::runtime_error("rosidl message type support is of the wrong type");
|
||||
}
|
||||
|
||||
auto ts_impl = static_cast<const rosidl_dynamic_message_type_support_impl_t *>(
|
||||
rosidl_message_type_support_.data);
|
||||
|
||||
dynamic_message_type_ = DynamicMessageType::make_shared(
|
||||
get_shared_dynamic_serialization_support(), std::move(*ts_impl->dynamic_message_type));
|
||||
|
||||
dynamic_message_ = DynamicMessage::make_shared(
|
||||
get_shared_dynamic_serialization_support(), std::move(*ts_impl->dynamic_message));
|
||||
}
|
||||
|
||||
DynamicMessageTypeSupport::DynamicMessageTypeSupport(
|
||||
DynamicSerializationSupport::SharedPtr serialization_support,
|
||||
DynamicMessageType::SharedPtr dynamic_message_type,
|
||||
DynamicMessage::SharedPtr dynamic_message,
|
||||
const rosidl_runtime_c__type_description__TypeDescription & description,
|
||||
rcl_allocator_t allocator)
|
||||
: serialization_support_(serialization_support),
|
||||
dynamic_message_type_(dynamic_message_type),
|
||||
dynamic_message_(dynamic_message),
|
||||
rosidl_message_type_support_(rosidl_get_zero_initialized_message_type_support_handle())
|
||||
{
|
||||
// Check null
|
||||
if (!serialization_support) {
|
||||
throw std::runtime_error("serialization_support cannot be nullptr.");
|
||||
}
|
||||
if (!dynamic_message_type) {
|
||||
throw std::runtime_error("dynamic_message_type cannot be nullptr.");
|
||||
}
|
||||
if (!dynamic_message) {
|
||||
throw std::runtime_error("dynamic_message cannot be nullptr.");
|
||||
}
|
||||
|
||||
// Check identifiers
|
||||
if (serialization_support->get_serialization_library_identifier() !=
|
||||
dynamic_message_type->get_serialization_library_identifier())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"serialization support library identifier does not match "
|
||||
"dynamic message type library identifier.");
|
||||
}
|
||||
if (dynamic_message_type->get_serialization_library_identifier() !=
|
||||
dynamic_message->get_serialization_library_identifier())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"dynamic message type library identifier does not match "
|
||||
"dynamic message library identifier.");
|
||||
}
|
||||
|
||||
rosidl_type_hash_t type_hash;
|
||||
rcutils_ret_t hash_ret = rcl_calculate_type_hash(
|
||||
// TODO(methylDragon): Swap this out with the conversion function when it is ready
|
||||
// from https://github.com/ros2/rcl/pull/1052
|
||||
reinterpret_cast<const type_description_interfaces__msg__TypeDescription *>(&description),
|
||||
&type_hash);
|
||||
if (hash_ret != RCL_RET_OK) {
|
||||
std::string error_msg = std::string("failed to get type hash: ") + rcl_get_error_string().str;
|
||||
rcl_reset_error();
|
||||
throw std::runtime_error(error_msg);
|
||||
}
|
||||
|
||||
auto ts_impl = static_cast<rosidl_dynamic_message_type_support_impl_t *>(
|
||||
allocator.zero_allocate(1, sizeof(rosidl_dynamic_message_type_support_impl_t), allocator.state)
|
||||
);
|
||||
if (!ts_impl) {
|
||||
throw std::runtime_error("could not allocate rosidl_message_type_support_t");
|
||||
}
|
||||
|
||||
ts_impl->allocator = allocator;
|
||||
ts_impl->type_hash = type_hash;
|
||||
if (!rosidl_runtime_c__type_description__TypeDescription__copy(
|
||||
&description, &ts_impl->type_description))
|
||||
{
|
||||
throw std::runtime_error("could not copy type description");
|
||||
}
|
||||
// ts_impl->type_description_sources = // Not used
|
||||
|
||||
ts_impl->serialization_support = serialization_support->get_rosidl_serialization_support();
|
||||
ts_impl->dynamic_message_type = &dynamic_message_type->get_rosidl_dynamic_type();
|
||||
ts_impl->dynamic_message = &dynamic_message->get_rosidl_dynamic_data();
|
||||
|
||||
rosidl_message_type_support_ = {
|
||||
rosidl_get_dynamic_typesupport_identifier(), // typesupport_identifier
|
||||
ts_impl, // data
|
||||
get_message_typesupport_handle_function, // func
|
||||
// get_type_hash_func
|
||||
rosidl_get_dynamic_message_type_support_type_hash_function,
|
||||
// get_type_description_func
|
||||
rosidl_get_dynamic_message_type_support_type_description_function,
|
||||
// get_type_description_sources_func
|
||||
rosidl_get_dynamic_message_type_support_type_description_sources_function
|
||||
};
|
||||
}
|
||||
|
||||
DynamicMessageTypeSupport::~DynamicMessageTypeSupport()
|
||||
{} // STUBBED
|
||||
{
|
||||
// These must go first
|
||||
serialization_support_.reset();
|
||||
dynamic_message_type_.reset();
|
||||
dynamic_message_.reset();
|
||||
|
||||
// Early return if type support isn't populated to avoid segfaults
|
||||
if (!rosidl_message_type_support_.data) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We only partially finalize the rosidl_message_type_support->data since its pointer members are
|
||||
// managed by their respective SharedPtr wrapper classes.
|
||||
auto ts_impl = static_cast<rosidl_dynamic_message_type_support_impl_t *>(
|
||||
const_cast<void *>(rosidl_message_type_support_.data)
|
||||
);
|
||||
rcutils_allocator_t allocator = ts_impl->allocator;
|
||||
|
||||
rosidl_runtime_c__type_description__TypeDescription__fini(&ts_impl->type_description);
|
||||
rosidl_runtime_c__type_description__TypeSource__Sequence__fini(
|
||||
&ts_impl->type_description_sources);
|
||||
allocator.deallocate(static_cast<void *>(ts_impl), allocator.state); // Always C allocated
|
||||
}
|
||||
|
||||
|
||||
// GETTERS =========================================================================================
|
||||
const std::string
|
||||
DynamicMessageTypeSupport::get_serialization_library_identifier() const
|
||||
{
|
||||
return serialization_support_->get_serialization_library_identifier();
|
||||
}
|
||||
|
||||
rosidl_message_type_support_t &
|
||||
DynamicMessageTypeSupport::get_rosidl_message_type_support()
|
||||
{
|
||||
return rosidl_message_type_support_;
|
||||
}
|
||||
|
||||
const rosidl_message_type_support_t &
|
||||
DynamicMessageTypeSupport::get_const_rosidl_message_type_support()
|
||||
{
|
||||
return rosidl_message_type_support_;
|
||||
}
|
||||
|
||||
const rosidl_message_type_support_t &
|
||||
DynamicMessageTypeSupport::get_const_rosidl_message_type_support() const
|
||||
{
|
||||
return rosidl_message_type_support_;
|
||||
}
|
||||
|
||||
const rosidl_runtime_c__type_description__TypeDescription &
|
||||
DynamicMessageTypeSupport::get_rosidl_runtime_c_type_description() const
|
||||
{
|
||||
auto ts_impl = static_cast<const rosidl_dynamic_message_type_support_impl_t *>(
|
||||
get_const_rosidl_message_type_support().data
|
||||
);
|
||||
return ts_impl->type_description;
|
||||
}
|
||||
|
||||
DynamicSerializationSupport::SharedPtr
|
||||
DynamicMessageTypeSupport::get_shared_dynamic_serialization_support()
|
||||
{
|
||||
return serialization_support_;
|
||||
}
|
||||
|
||||
DynamicSerializationSupport::ConstSharedPtr
|
||||
DynamicMessageTypeSupport::get_shared_dynamic_serialization_support() const
|
||||
{
|
||||
return serialization_support_;
|
||||
}
|
||||
|
||||
DynamicMessageType::SharedPtr
|
||||
DynamicMessageTypeSupport::get_shared_dynamic_message_type()
|
||||
{
|
||||
return dynamic_message_type_;
|
||||
}
|
||||
|
||||
DynamicMessageType::ConstSharedPtr
|
||||
DynamicMessageTypeSupport::get_shared_dynamic_message_type() const
|
||||
{
|
||||
return dynamic_message_type_;
|
||||
}
|
||||
|
||||
DynamicMessage::SharedPtr
|
||||
DynamicMessageTypeSupport::get_shared_dynamic_message()
|
||||
{
|
||||
return dynamic_message_;
|
||||
}
|
||||
|
||||
DynamicMessage::ConstSharedPtr
|
||||
DynamicMessageTypeSupport::get_shared_dynamic_message() const
|
||||
{
|
||||
return dynamic_message_;
|
||||
}
|
||||
|
||||
@@ -28,19 +28,71 @@ using rclcpp::dynamic_typesupport::DynamicSerializationSupport;
|
||||
|
||||
// CONSTRUCTION ====================================================================================
|
||||
DynamicSerializationSupport::DynamicSerializationSupport(rcl_allocator_t allocator)
|
||||
: DynamicSerializationSupport::DynamicSerializationSupport("", allocator)
|
||||
{
|
||||
throw std::runtime_error("Unimplemented");
|
||||
}
|
||||
: DynamicSerializationSupport::DynamicSerializationSupport("", allocator) {}
|
||||
|
||||
DynamicSerializationSupport::DynamicSerializationSupport(
|
||||
const std::string & /*serialization_library_name*/,
|
||||
rcl_allocator_t /*allocator*/)
|
||||
const std::string & serialization_library_name,
|
||||
rcl_allocator_t allocator)
|
||||
: rosidl_serialization_support_(
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_serialization_support())
|
||||
{
|
||||
throw std::runtime_error("Unimplemented");
|
||||
rmw_ret_t ret = RMW_RET_ERROR;
|
||||
|
||||
if (serialization_library_name.empty()) {
|
||||
ret = rmw_serialization_support_init(NULL, &allocator, &rosidl_serialization_support_);
|
||||
} else {
|
||||
ret = rmw_serialization_support_init(
|
||||
serialization_library_name.c_str(), &allocator, &rosidl_serialization_support_);
|
||||
}
|
||||
if (ret != RCL_RET_OK) {
|
||||
std::string error_msg =
|
||||
std::string("could not initialize new serialization support object: ") +
|
||||
rcl_get_error_string().str;
|
||||
rcl_reset_error();
|
||||
throw std::runtime_error(error_msg);
|
||||
}
|
||||
}
|
||||
|
||||
DynamicSerializationSupport::DynamicSerializationSupport(
|
||||
rosidl_dynamic_typesupport_serialization_support_t && rosidl_serialization_support)
|
||||
: rosidl_serialization_support_(std::move(rosidl_serialization_support)) {}
|
||||
|
||||
DynamicSerializationSupport::DynamicSerializationSupport(
|
||||
DynamicSerializationSupport && other) noexcept
|
||||
: rosidl_serialization_support_(std::exchange(
|
||||
other.rosidl_serialization_support_,
|
||||
rosidl_dynamic_typesupport_get_zero_initialized_serialization_support())) {}
|
||||
|
||||
DynamicSerializationSupport &
|
||||
DynamicSerializationSupport::operator=(DynamicSerializationSupport && other) noexcept
|
||||
{
|
||||
std::swap(rosidl_serialization_support_, other.rosidl_serialization_support_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
DynamicSerializationSupport::~DynamicSerializationSupport()
|
||||
{} // STUBBED
|
||||
{
|
||||
rosidl_dynamic_typesupport_serialization_support_fini(&rosidl_serialization_support_);
|
||||
}
|
||||
|
||||
|
||||
// GETTERS =========================================================================================
|
||||
const std::string
|
||||
DynamicSerializationSupport::get_serialization_library_identifier() const
|
||||
{
|
||||
return std::string(
|
||||
rosidl_dynamic_typesupport_serialization_support_get_library_identifier(
|
||||
&rosidl_serialization_support_));
|
||||
}
|
||||
|
||||
rosidl_dynamic_typesupport_serialization_support_t &
|
||||
DynamicSerializationSupport::get_rosidl_serialization_support()
|
||||
{
|
||||
return rosidl_serialization_support_;
|
||||
}
|
||||
|
||||
const rosidl_dynamic_typesupport_serialization_support_t &
|
||||
DynamicSerializationSupport::get_rosidl_serialization_support() const
|
||||
{
|
||||
return rosidl_serialization_support_;
|
||||
}
|
||||
|
||||
@@ -610,10 +610,25 @@ Executor::execute_subscription(rclcpp::SubscriptionBase::SharedPtr subscription)
|
||||
}
|
||||
|
||||
// DYNAMIC SUBSCRIPTION ========================================================================
|
||||
// Deliver dynamic message
|
||||
// If a subscription is dynamic, then it will use its serialization-specific dynamic data.
|
||||
//
|
||||
// Two cases:
|
||||
// - Dynamic type subscription using dynamic type stored in its own internal type support struct
|
||||
// - Non-dynamic type subscription with no stored dynamic type
|
||||
// - Subscriptions of this type must be able to lookup the local message description to
|
||||
// generate a dynamic type at runtime!
|
||||
// - TODO(methylDragon): I won't be handling this case yet
|
||||
case rclcpp::DeliveredMessageKind::DYNAMIC_MESSAGE:
|
||||
{
|
||||
throw std::runtime_error("Unimplemented");
|
||||
DynamicMessage::SharedPtr dynamic_message = subscription->create_dynamic_message();
|
||||
take_and_do_error_handling(
|
||||
"taking a dynamic message from topic",
|
||||
subscription->get_topic_name(),
|
||||
// This modifies the stored dynamic data in the DynamicMessage in-place
|
||||
[&]() {return subscription->take_dynamic_message(*dynamic_message, message_info);},
|
||||
[&]() {subscription->handle_dynamic_message(dynamic_message, message_info);});
|
||||
subscription->return_dynamic_message(dynamic_message);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -729,13 +744,33 @@ Executor::wait_for_work(std::chrono::nanoseconds timeout)
|
||||
// Clear any previous wait result
|
||||
this->wait_result_.reset();
|
||||
|
||||
// we need to make sure that callback groups don't get out of scope
|
||||
// during the wait. As in jazzy, they are not covered by the DynamicStorage,
|
||||
// we explicitly hold them here as a bugfix
|
||||
std::vector<rclcpp::CallbackGroup::SharedPtr> cbgs;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
|
||||
if (this->entities_need_rebuild_.exchange(false) || current_collection_.empty()) {
|
||||
this->collect_entities();
|
||||
}
|
||||
|
||||
auto callback_groups = this->collector_.get_all_callback_groups();
|
||||
cbgs.resize(callback_groups.size());
|
||||
for(const auto & w_ptr : callback_groups) {
|
||||
auto shr_ptr = w_ptr.lock();
|
||||
if(shr_ptr) {
|
||||
cbgs.push_back(std::move(shr_ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->wait_result_.emplace(wait_set_.wait(timeout));
|
||||
|
||||
// drop references to the callback groups, before trying to execute anything
|
||||
cbgs.clear();
|
||||
|
||||
if (!this->wait_result_ || this->wait_result_->kind() == WaitResultKind::Empty) {
|
||||
RCUTILS_LOG_WARN_NAMED(
|
||||
"rclcpp",
|
||||
|
||||
@@ -110,10 +110,29 @@ StaticSingleThreadedExecutor::spin_once_impl(std::chrono::nanoseconds timeout)
|
||||
std::optional<rclcpp::WaitResult<rclcpp::WaitSet>>
|
||||
StaticSingleThreadedExecutor::collect_and_wait(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
// we need to make sure that callback groups don't get out of scope
|
||||
// during the wait. As in jazzy, they are not covered by the DynamicStorage,
|
||||
// we explicitly hold them here as a bugfix
|
||||
std::vector<rclcpp::CallbackGroup::SharedPtr> cbgs;
|
||||
|
||||
if (this->entities_need_rebuild_.exchange(false) || current_collection_.empty()) {
|
||||
this->collect_entities();
|
||||
}
|
||||
|
||||
auto callback_groups = this->collector_.get_all_callback_groups();
|
||||
cbgs.resize(callback_groups.size());
|
||||
for(const auto & w_ptr : callback_groups) {
|
||||
auto shr_ptr = w_ptr.lock();
|
||||
if(shr_ptr) {
|
||||
cbgs.push_back(std::move(shr_ptr));
|
||||
}
|
||||
}
|
||||
|
||||
auto wait_result = wait_set_.wait(std::chrono::nanoseconds(timeout));
|
||||
|
||||
// drop references to the callback groups, before trying to execute anything
|
||||
cbgs.clear();
|
||||
|
||||
if (wait_result.kind() == WaitResultKind::Empty) {
|
||||
RCUTILS_LOG_WARN_NAMED(
|
||||
"rclcpp",
|
||||
|
||||
@@ -109,6 +109,13 @@ GenericClient::handle_response(
|
||||
if (std::holds_alternative<Promise>(value)) {
|
||||
auto & promise = std::get<Promise>(value);
|
||||
promise.set_value(std::move(response));
|
||||
} else if (std::holds_alternative<CallbackTypeValueVariant>(value)) {
|
||||
auto & inner = std::get<CallbackTypeValueVariant>(value);
|
||||
const auto & callback = std::get<CallbackType>(inner);
|
||||
auto & promise = std::get<Promise>(inner);
|
||||
auto & future = std::get<SharedFuture>(inner);
|
||||
promise.set_value(std::move(response));
|
||||
callback(std::move(future));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +135,18 @@ GenericClient::remove_pending_request(int64_t request_id)
|
||||
return pending_requests_.erase(request_id) != 0u;
|
||||
}
|
||||
|
||||
bool
|
||||
GenericClient::remove_pending_request(const FutureAndRequestId & future)
|
||||
{
|
||||
return this->remove_pending_request(future.request_id);
|
||||
}
|
||||
|
||||
bool
|
||||
GenericClient::remove_pending_request(const SharedFutureAndRequestId & future)
|
||||
{
|
||||
return this->remove_pending_request(future.request_id);
|
||||
}
|
||||
|
||||
std::optional<GenericClient::CallbackInfoVariant>
|
||||
GenericClient::get_and_erase_pending_request(int64_t request_number)
|
||||
{
|
||||
|
||||
@@ -46,8 +46,7 @@ GenericSubscription::handle_message(
|
||||
"handle_message is not implemented for GenericSubscription");
|
||||
}
|
||||
|
||||
void
|
||||
GenericSubscription::handle_serialized_message(
|
||||
void GenericSubscription::handle_serialized_message(
|
||||
const std::shared_ptr<rclcpp::SerializedMessage> & message,
|
||||
const rclcpp::MessageInfo & message_info)
|
||||
{
|
||||
|
||||
@@ -80,6 +80,7 @@ NodeOptions::operator=(const NodeOptions & other)
|
||||
this->clock_type_ = other.clock_type_;
|
||||
this->clock_qos_ = other.clock_qos_;
|
||||
this->use_clock_thread_ = other.use_clock_thread_;
|
||||
this->enable_logger_service_ = other.enable_logger_service_;
|
||||
this->parameter_event_qos_ = other.parameter_event_qos_;
|
||||
this->rosout_qos_ = other.rosout_qos_;
|
||||
this->parameter_event_publisher_options_ = other.parameter_event_publisher_options_;
|
||||
|
||||
@@ -135,15 +135,28 @@ void
|
||||
PublisherBase::bind_event_callbacks(
|
||||
const PublisherEventCallbacks & event_callbacks, bool use_default_callbacks)
|
||||
{
|
||||
if (event_callbacks.deadline_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.deadline_callback,
|
||||
RCL_PUBLISHER_OFFERED_DEADLINE_MISSED);
|
||||
try {
|
||||
if (event_callbacks.deadline_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.deadline_callback,
|
||||
RCL_PUBLISHER_OFFERED_DEADLINE_MISSED);
|
||||
}
|
||||
} catch (const UnsupportedEventTypeException & /*exc*/) {
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Failed to add event handler for deadline; not supported");
|
||||
}
|
||||
if (event_callbacks.liveliness_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.liveliness_callback,
|
||||
RCL_PUBLISHER_LIVELINESS_LOST);
|
||||
|
||||
try {
|
||||
if (event_callbacks.liveliness_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.liveliness_callback,
|
||||
RCL_PUBLISHER_LIVELINESS_LOST);
|
||||
}
|
||||
} catch (const UnsupportedEventTypeException & /*exc*/) {
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Failed to add event handler for liveliness; not supported");
|
||||
}
|
||||
|
||||
QOSOfferedIncompatibleQoSCallbackType incompatible_qos_cb;
|
||||
@@ -160,9 +173,9 @@ PublisherBase::bind_event_callbacks(
|
||||
this->add_event_handler(incompatible_qos_cb, RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS);
|
||||
}
|
||||
} catch (const UnsupportedEventTypeException & /*exc*/) {
|
||||
RCLCPP_DEBUG(
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Failed to add event handler for incompatible qos; wrong callback type");
|
||||
"Failed to add event handler for incompatible qos; not supported");
|
||||
}
|
||||
|
||||
IncompatibleTypeCallbackType incompatible_type_cb;
|
||||
@@ -179,14 +192,21 @@ PublisherBase::bind_event_callbacks(
|
||||
this->add_event_handler(incompatible_type_cb, RCL_PUBLISHER_INCOMPATIBLE_TYPE);
|
||||
}
|
||||
} catch (UnsupportedEventTypeException & /*exc*/) {
|
||||
RCLCPP_DEBUG(
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Failed to add event handler for incompatible type; wrong callback type");
|
||||
"Failed to add event handler for incompatible type; not supported");
|
||||
}
|
||||
if (event_callbacks.matched_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.matched_callback,
|
||||
RCL_PUBLISHER_MATCHED);
|
||||
|
||||
try {
|
||||
if (event_callbacks.matched_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.matched_callback,
|
||||
RCL_PUBLISHER_MATCHED);
|
||||
}
|
||||
} catch (const UnsupportedEventTypeException & /*exc*/) {
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Failed to add event handler for matched; not supported");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,16 +112,28 @@ void
|
||||
SubscriptionBase::bind_event_callbacks(
|
||||
const SubscriptionEventCallbacks & event_callbacks, bool use_default_callbacks)
|
||||
{
|
||||
if (event_callbacks.deadline_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.deadline_callback,
|
||||
RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED);
|
||||
try {
|
||||
if (event_callbacks.deadline_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.deadline_callback,
|
||||
RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED);
|
||||
}
|
||||
} catch (const UnsupportedEventTypeException & /*exc*/) {
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Failed to add event handler for deadline; not supported");
|
||||
}
|
||||
|
||||
if (event_callbacks.liveliness_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.liveliness_callback,
|
||||
RCL_SUBSCRIPTION_LIVELINESS_CHANGED);
|
||||
try {
|
||||
if (event_callbacks.liveliness_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.liveliness_callback,
|
||||
RCL_SUBSCRIPTION_LIVELINESS_CHANGED);
|
||||
}
|
||||
} catch (const UnsupportedEventTypeException & /*exc*/) {
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Failed to add event handler for liveliness; not supported");
|
||||
}
|
||||
|
||||
QOSRequestedIncompatibleQoSCallbackType incompatible_qos_cb;
|
||||
@@ -139,7 +151,9 @@ SubscriptionBase::bind_event_callbacks(
|
||||
this->add_event_handler(incompatible_qos_cb, RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS);
|
||||
}
|
||||
} catch (const UnsupportedEventTypeException & /*exc*/) {
|
||||
// pass
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Failed to add event handler for incompatible qos; not supported");
|
||||
}
|
||||
|
||||
IncompatibleTypeCallbackType incompatible_type_cb;
|
||||
@@ -156,18 +170,33 @@ SubscriptionBase::bind_event_callbacks(
|
||||
this->add_event_handler(incompatible_type_cb, RCL_SUBSCRIPTION_INCOMPATIBLE_TYPE);
|
||||
}
|
||||
} catch (UnsupportedEventTypeException & /*exc*/) {
|
||||
// pass
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Failed to add event handler for incompatible type; not supported");
|
||||
}
|
||||
|
||||
if (event_callbacks.message_lost_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.message_lost_callback,
|
||||
RCL_SUBSCRIPTION_MESSAGE_LOST);
|
||||
try {
|
||||
if (event_callbacks.message_lost_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.message_lost_callback,
|
||||
RCL_SUBSCRIPTION_MESSAGE_LOST);
|
||||
}
|
||||
} catch (const UnsupportedEventTypeException & /*exc*/) {
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Failed to add event handler for message lost; not supported");
|
||||
}
|
||||
if (event_callbacks.matched_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.matched_callback,
|
||||
RCL_SUBSCRIPTION_MATCHED);
|
||||
|
||||
try {
|
||||
if (event_callbacks.matched_callback) {
|
||||
this->add_event_handler(
|
||||
event_callbacks.matched_callback,
|
||||
RCL_SUBSCRIPTION_MATCHED);
|
||||
}
|
||||
} catch (const UnsupportedEventTypeException & /*exc*/) {
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Failed to add event handler for matched; not supported");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,9 +573,30 @@ SubscriptionBase::get_content_filter() const
|
||||
// DYNAMIC TYPE ==================================================================================
|
||||
bool
|
||||
SubscriptionBase::take_dynamic_message(
|
||||
rclcpp::dynamic_typesupport::DynamicMessage & /*message_out*/,
|
||||
rclcpp::MessageInfo & /*message_info_out*/)
|
||||
rclcpp::dynamic_typesupport::DynamicMessage & message_out,
|
||||
rclcpp::MessageInfo & message_info_out)
|
||||
{
|
||||
throw std::runtime_error("Unimplemented");
|
||||
return false;
|
||||
if (rmw_feature_supported(RMW_MIDDLEWARE_CAN_TAKE_DYNAMIC_MESSAGE)) {
|
||||
rcl_ret_t ret = rcl_take_dynamic_message(
|
||||
this->get_subscription_handle().get(),
|
||||
&message_out.get_rosidl_dynamic_data(),
|
||||
&message_info_out.get_rmw_message_info(),
|
||||
nullptr);
|
||||
if (RCL_RET_SUBSCRIPTION_TAKE_FAILED == ret) {
|
||||
return false;
|
||||
} else if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "Error when taking dynamic message");
|
||||
}
|
||||
} else { // Fall back to serialized conversion if direct dynamic message taking isn't supported
|
||||
std::shared_ptr<rclcpp::SerializedMessage> serialized_msg = this->create_serialized_message();
|
||||
if (!this->take_serialized(*serialized_msg.get(), message_info_out)) {
|
||||
std::runtime_error("Couldn't take serialized message when attempting to take dynamic data!");
|
||||
}
|
||||
bool ret = message_out.deserialize(serialized_msg->get_rcl_serialized_message());
|
||||
if (!ret) {
|
||||
throw std::runtime_error("Couldn't convert serialized message to dynamic data!");
|
||||
}
|
||||
this->return_serialized_message(serialized_msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -555,7 +555,7 @@ if(TARGET test_executor_notify_waitable)
|
||||
target_link_libraries(test_executor_notify_waitable ${PROJECT_NAME} mimick rcpputils::rcpputils)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_events_executor executors/test_events_executor.cpp TIMEOUT 5)
|
||||
ament_add_gtest(test_events_executor executors/test_events_executor.cpp TIMEOUT 60)
|
||||
if(TARGET test_events_executor)
|
||||
target_link_libraries(test_events_executor ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
@@ -479,14 +479,21 @@ TEST_F(TestEventsExecutor, test_default_incompatible_qos_callbacks)
|
||||
const auto timeout = std::chrono::seconds(10);
|
||||
ex.spin_until_future_complete(log_msgs_future, timeout);
|
||||
|
||||
EXPECT_EQ(
|
||||
"New subscription discovered on topic '/test_topic', requesting incompatible QoS. "
|
||||
"No messages will be sent to it. Last incompatible policy: DURABILITY_QOS_POLICY",
|
||||
pub_log_msg);
|
||||
EXPECT_EQ(
|
||||
"New publisher discovered on topic '/test_topic', offering incompatible QoS. "
|
||||
"No messages will be sent to it. Last incompatible policy: DURABILITY_QOS_POLICY",
|
||||
sub_log_msg);
|
||||
rclcpp::QoSCheckCompatibleResult qos_compatible = rclcpp::qos_check_compatible(
|
||||
publisher->get_actual_qos(), subscription->get_actual_qos());
|
||||
if (qos_compatible.compatibility == rclcpp::QoSCompatibility::Error) {
|
||||
EXPECT_EQ(
|
||||
"New subscription discovered on topic '/test_topic', requesting incompatible QoS. "
|
||||
"No messages will be sent to it. Last incompatible policy: DURABILITY_QOS_POLICY",
|
||||
pub_log_msg);
|
||||
EXPECT_EQ(
|
||||
"New publisher discovered on topic '/test_topic', offering incompatible QoS. "
|
||||
"No messages will be sent to it. Last incompatible policy: DURABILITY_QOS_POLICY",
|
||||
sub_log_msg);
|
||||
} else {
|
||||
EXPECT_EQ("", pub_log_msg);
|
||||
EXPECT_EQ("", sub_log_msg);
|
||||
}
|
||||
|
||||
rcutils_logging_set_output_handler(original_output_handler);
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ to_nanoseconds_helper(DurationT duration)
|
||||
// - works nominally (it can execute entities)
|
||||
// - it can execute multiple items at once
|
||||
// - it does not wait for work to be available before returning
|
||||
TYPED_TEST(TestExecutors, spin_some)
|
||||
TYPED_TEST(TestExecutors, spinSome)
|
||||
{
|
||||
using ExecutorType = TypeParam;
|
||||
|
||||
@@ -484,7 +484,7 @@ TYPED_TEST(TestExecutors, spin_some)
|
||||
// do not properly implement max_duration (it seems), so disable this test
|
||||
// for them in the meantime.
|
||||
// see: https://github.com/ros2/rclcpp/issues/2462
|
||||
TYPED_TEST(TestExecutorsStable, spin_some_max_duration)
|
||||
TYPED_TEST(TestExecutorsStable, spinSomeMaxDuration)
|
||||
{
|
||||
using ExecutorType = TypeParam;
|
||||
|
||||
@@ -714,6 +714,13 @@ TYPED_TEST(TestExecutors, notifyTwiceWhileSpinning)
|
||||
sub1_msg_count++;
|
||||
});
|
||||
|
||||
// Wait for the subscription to be matched
|
||||
size_t tries = 10000;
|
||||
while (this->publisher->get_subscription_count() < 2 && tries-- > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
ASSERT_EQ(this->publisher->get_subscription_count(), 2);
|
||||
|
||||
// Publish a message and verify it's received
|
||||
this->publisher->publish(test_msgs::msg::Empty());
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
@@ -731,6 +738,13 @@ TYPED_TEST(TestExecutors, notifyTwiceWhileSpinning)
|
||||
sub2_msg_count++;
|
||||
});
|
||||
|
||||
// Wait for the subscription to be matched
|
||||
tries = 10000;
|
||||
while (this->publisher->get_subscription_count() < 3 && tries-- > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
ASSERT_EQ(this->publisher->get_subscription_count(), 3);
|
||||
|
||||
// Publish a message and verify it's received by both subscriptions
|
||||
this->publisher->publish(test_msgs::msg::Empty());
|
||||
start = std::chrono::steady_clock::now();
|
||||
@@ -820,7 +834,7 @@ TEST(TestExecutors, testSpinWithNonDefaultContext)
|
||||
rclcpp::shutdown(non_default_context);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestExecutors, release_ownership_entity_after_spinning_cancel)
|
||||
TYPED_TEST(TestExecutors, releaseOwnershipEntityAfterSpinningCancel)
|
||||
{
|
||||
using ExecutorType = TypeParam;
|
||||
ExecutorType executor;
|
||||
@@ -843,3 +857,36 @@ TYPED_TEST(TestExecutors, release_ownership_entity_after_spinning_cancel)
|
||||
|
||||
EXPECT_EQ(server.use_count(), 1);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestExecutors, testRaceDropCallbackGroupFromSecondThread)
|
||||
{
|
||||
using ExecutorType = TypeParam;
|
||||
|
||||
// Create an executor
|
||||
ExecutorType executor;
|
||||
executor.add_node(this->node);
|
||||
|
||||
// Start spinning
|
||||
auto executor_thread = std::thread(
|
||||
[&executor]() {
|
||||
executor.spin();
|
||||
});
|
||||
|
||||
// As the problem is a race, we do this multiple times,
|
||||
// to raise our chances of hitting the problem
|
||||
for (size_t i = 0; i < 10; i++) {
|
||||
auto cg = this->node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
auto timer = this->node->create_timer(1s, [] {}, cg);
|
||||
// sleep a bit, so that the spin thread can pick up the callback group
|
||||
// and add it to the executor
|
||||
std::this_thread::sleep_for(5ms);
|
||||
|
||||
// At this point the callbackgroup should be used within the waitset of the executor
|
||||
// as we leave the scope, the reference to cg will be dropped.
|
||||
// If the executor has a race, we will experience a segfault at this point.
|
||||
}
|
||||
|
||||
executor.cancel();
|
||||
executor_thread.join();
|
||||
}
|
||||
|
||||
@@ -431,7 +431,7 @@ TYPED_TEST(TestAllClientTypesWithServer, client_qos)
|
||||
|
||||
rclcpp::ServicesQoS qos_profile;
|
||||
qos_profile.liveliness(rclcpp::LivelinessPolicy::Automatic);
|
||||
rclcpp::Duration duration(std::chrono::nanoseconds(1));
|
||||
rclcpp::Duration duration(std::chrono::milliseconds(1));
|
||||
qos_profile.deadline(duration);
|
||||
qos_profile.lifespan(duration);
|
||||
qos_profile.liveliness_lease_duration(duration);
|
||||
|
||||
@@ -92,3 +92,19 @@ TEST_F(TestCreateSubscription, create_with_statistics) {
|
||||
ASSERT_NE(nullptr, subscription);
|
||||
EXPECT_STREQ("/ns/topic_name", subscription->get_topic_name());
|
||||
}
|
||||
|
||||
TEST_F(TestCreateSubscription, create_with_intra_process_com) {
|
||||
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
|
||||
auto options = rclcpp::SubscriptionOptions();
|
||||
options.use_intra_process_comm = rclcpp::IntraProcessSetting::Enable;
|
||||
|
||||
auto callback = [](test_msgs::msg::Empty::ConstSharedPtr) {};
|
||||
rclcpp::Subscription<test_msgs::msg::Empty>::SharedPtr subscription;
|
||||
ASSERT_NO_THROW(
|
||||
{
|
||||
subscription = rclcpp::create_subscription<test_msgs::msg::Empty>(
|
||||
node, "topic_name", rclcpp::SystemDefaultsQoS(), callback, options);
|
||||
});
|
||||
ASSERT_NE(nullptr, subscription);
|
||||
EXPECT_STREQ("/ns/topic_name", subscription->get_topic_name());
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
@@ -28,6 +30,7 @@
|
||||
#include "../mocking_utils/patch.hpp"
|
||||
|
||||
#include "test_msgs/srv/empty.hpp"
|
||||
#include "test_msgs/srv/basic_types.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
@@ -228,3 +231,69 @@ TEST_F(TestGenericClientSub, construction_and_destruction) {
|
||||
}, rclcpp::exceptions::InvalidServiceNameError);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestGenericClientSub, async_send_request_with_request) {
|
||||
const std::string service_name = "test_service";
|
||||
int64_t expected_change = 1111;
|
||||
|
||||
auto client = node->create_generic_client(service_name, "test_msgs/srv/BasicTypes");
|
||||
|
||||
auto callback = [&expected_change](
|
||||
const test_msgs::srv::BasicTypes::Request::SharedPtr request,
|
||||
test_msgs::srv::BasicTypes::Response::SharedPtr response) {
|
||||
response->int64_value = request->int64_value + expected_change;
|
||||
};
|
||||
|
||||
auto service =
|
||||
node->create_service<test_msgs::srv::BasicTypes>(service_name, std::move(callback));
|
||||
|
||||
ASSERT_TRUE(client->wait_for_service(std::chrono::seconds(5)));
|
||||
ASSERT_TRUE(client->service_is_ready());
|
||||
|
||||
test_msgs::srv::BasicTypes::Request request;
|
||||
request.int64_value = 12345678;
|
||||
|
||||
auto future = client->async_send_request(static_cast<void *>(&request));
|
||||
rclcpp::spin_until_future_complete(
|
||||
node->get_node_base_interface(), future, std::chrono::seconds(5));
|
||||
ASSERT_TRUE(future.valid());
|
||||
auto get_untyped_response = future.get();
|
||||
auto typed_response =
|
||||
static_cast<test_msgs::srv::BasicTypes::Response *>(get_untyped_response.get());
|
||||
EXPECT_EQ(typed_response->int64_value, (request.int64_value + expected_change));
|
||||
}
|
||||
|
||||
TEST_F(TestGenericClientSub, async_send_request_with_request_and_callback) {
|
||||
const std::string service_name = "test_service";
|
||||
int64_t expected_change = 2222;
|
||||
|
||||
auto client = node->create_generic_client(service_name, "test_msgs/srv/BasicTypes");
|
||||
|
||||
auto server_callback = [&expected_change](
|
||||
const test_msgs::srv::BasicTypes::Request::SharedPtr request,
|
||||
test_msgs::srv::BasicTypes::Response::SharedPtr response) {
|
||||
response->int64_value = request->int64_value + expected_change;
|
||||
};
|
||||
|
||||
auto service =
|
||||
node->create_service<test_msgs::srv::BasicTypes>(service_name, std::move(server_callback));
|
||||
|
||||
ASSERT_TRUE(client->wait_for_service(std::chrono::seconds(5)));
|
||||
ASSERT_TRUE(client->service_is_ready());
|
||||
|
||||
test_msgs::srv::BasicTypes::Request request;
|
||||
request.int64_value = 12345678;
|
||||
|
||||
auto client_callback = [&request, &expected_change](
|
||||
rclcpp::GenericClient::SharedFuture future) {
|
||||
auto untyped_response = future.get();
|
||||
auto typed_response =
|
||||
static_cast<test_msgs::srv::BasicTypes::Response *>(untyped_response.get());
|
||||
EXPECT_EQ(typed_response->int64_value, (request.int64_value + expected_change));
|
||||
};
|
||||
|
||||
auto future =
|
||||
client->async_send_request(static_cast<void *>(&request), client_callback);
|
||||
rclcpp::spin_until_future_complete(
|
||||
node->get_node_base_interface(), future, std::chrono::seconds(5));
|
||||
}
|
||||
|
||||
@@ -89,9 +89,9 @@ public:
|
||||
T2 message;
|
||||
write_message(data, message);
|
||||
|
||||
rclcpp::Serialization<T2> ser;
|
||||
rclcpp::Serialization<T2> serialization_support;
|
||||
SerializedMessage result;
|
||||
ser.serialize_message(&message, &result);
|
||||
serialization_support.serialize_message(&message, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -320,7 +320,7 @@ TEST_F(TestGenericService, rcl_service_request_subscription_get_actual_qos_error
|
||||
TEST_F(TestGenericService, generic_service_qos) {
|
||||
rclcpp::ServicesQoS qos_profile;
|
||||
qos_profile.liveliness(rclcpp::LivelinessPolicy::Automatic);
|
||||
rclcpp::Duration duration(std::chrono::nanoseconds(1));
|
||||
rclcpp::Duration duration(std::chrono::milliseconds(1));
|
||||
qos_profile.deadline(duration);
|
||||
qos_profile.lifespan(duration);
|
||||
qos_profile.liveliness_lease_duration(duration);
|
||||
|
||||
@@ -123,6 +123,7 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
// need to store the messages somewhere otherwise the memory address will be reused
|
||||
ConstMessageSharedPtr shared_msg;
|
||||
MessageUniquePtr unique_msg;
|
||||
@@ -158,9 +159,9 @@ class PublisherBase
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(PublisherBase)
|
||||
|
||||
explicit PublisherBase(rclcpp::QoS qos = rclcpp::QoS(10))
|
||||
: qos_profile(qos),
|
||||
topic_name("topic")
|
||||
explicit PublisherBase(const std::string & topic, const rclcpp::QoS & qos)
|
||||
: topic_name(topic),
|
||||
qos_profile(qos)
|
||||
{}
|
||||
|
||||
virtual ~PublisherBase()
|
||||
@@ -205,10 +206,12 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
rclcpp::QoS qos_profile;
|
||||
std::string topic_name;
|
||||
uint64_t intra_process_publisher_id_;
|
||||
IntraProcessManagerWeakPtr weak_ipm_;
|
||||
|
||||
private:
|
||||
std::string topic_name;
|
||||
rclcpp::QoS qos_profile;
|
||||
};
|
||||
|
||||
template<typename T, typename Alloc = std::allocator<void>>
|
||||
@@ -223,8 +226,8 @@ public:
|
||||
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(Publisher<T, Alloc>)
|
||||
|
||||
explicit Publisher(rclcpp::QoS qos = rclcpp::QoS(10))
|
||||
: PublisherBase(qos)
|
||||
explicit Publisher(const std::string & topic, const rclcpp::QoS & qos)
|
||||
: PublisherBase(topic, qos)
|
||||
{
|
||||
auto allocator = std::make_shared<Alloc>();
|
||||
message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
|
||||
@@ -258,9 +261,9 @@ public:
|
||||
|
||||
explicit SubscriptionIntraProcessBase(
|
||||
rclcpp::Context::SharedPtr context,
|
||||
const std::string & topic = "topic",
|
||||
rclcpp::QoS qos = rclcpp::QoS(10))
|
||||
: qos_profile(qos), topic_name(topic)
|
||||
const std::string & topic,
|
||||
const rclcpp::QoS & qos)
|
||||
: topic_name(topic), qos_profile(qos)
|
||||
{
|
||||
(void)context;
|
||||
}
|
||||
@@ -292,8 +295,8 @@ public:
|
||||
size_t
|
||||
available_capacity() const = 0;
|
||||
|
||||
rclcpp::QoS qos_profile;
|
||||
std::string topic_name;
|
||||
rclcpp::QoS qos_profile;
|
||||
};
|
||||
|
||||
template<
|
||||
@@ -307,8 +310,8 @@ class SubscriptionIntraProcessBuffer : public SubscriptionIntraProcessBase
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(SubscriptionIntraProcessBuffer)
|
||||
|
||||
explicit SubscriptionIntraProcessBuffer(rclcpp::QoS qos)
|
||||
: SubscriptionIntraProcessBase(nullptr, "topic", qos), take_shared_method(false)
|
||||
explicit SubscriptionIntraProcessBuffer(const std::string & topic, const rclcpp::QoS & qos)
|
||||
: SubscriptionIntraProcessBase(nullptr, topic, qos), take_shared_method(false)
|
||||
{
|
||||
buffer = std::make_unique<rclcpp::experimental::buffers::mock::IntraProcessBuffer<MessageT>>();
|
||||
}
|
||||
@@ -375,8 +378,8 @@ class SubscriptionIntraProcess : public SubscriptionIntraProcessBuffer<
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(SubscriptionIntraProcess)
|
||||
|
||||
explicit SubscriptionIntraProcess(rclcpp::QoS qos = rclcpp::QoS(10))
|
||||
: SubscriptionIntraProcessBuffer<MessageT, Alloc, Deleter>(qos)
|
||||
explicit SubscriptionIntraProcess(const std::string & topic, const rclcpp::QoS & qos)
|
||||
: SubscriptionIntraProcessBuffer<MessageT, Alloc, Deleter>(topic, qos)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -466,12 +469,11 @@ TEST(TestIntraProcessManager, add_pub_sub) {
|
||||
|
||||
auto ipm = std::make_shared<IntraProcessManagerT>();
|
||||
|
||||
auto p1 = std::make_shared<PublisherT>(rclcpp::QoS(10).best_effort());
|
||||
auto p1 = std::make_shared<PublisherT>("topic", rclcpp::QoS(10).best_effort());
|
||||
|
||||
auto p2 = std::make_shared<PublisherT>(rclcpp::QoS(10).best_effort());
|
||||
p2->topic_name = "different_topic_name";
|
||||
auto p2 = std::make_shared<PublisherT>("different_topic_name", rclcpp::QoS(10).best_effort());
|
||||
|
||||
auto s1 = std::make_shared<SubscriptionIntraProcessT>(rclcpp::QoS(10).best_effort());
|
||||
auto s1 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10).best_effort());
|
||||
|
||||
auto p1_id = ipm->add_publisher(p1);
|
||||
auto p2_id = ipm->add_publisher(p2);
|
||||
@@ -480,24 +482,42 @@ TEST(TestIntraProcessManager, add_pub_sub) {
|
||||
bool unique_ids = p1_id != p2_id && p2_id != s1_id;
|
||||
ASSERT_TRUE(unique_ids);
|
||||
|
||||
// p1 has 1 subcription, s1
|
||||
size_t p1_subs = ipm->get_subscription_count(p1_id);
|
||||
// p2 has 0 subscriptions
|
||||
size_t p2_subs = ipm->get_subscription_count(p2_id);
|
||||
// Non-existent publisher_id has 0 subscriptions
|
||||
size_t non_existing_pub_subs = ipm->get_subscription_count(42);
|
||||
ASSERT_EQ(1u, p1_subs);
|
||||
ASSERT_EQ(0u, p2_subs);
|
||||
ASSERT_EQ(0u, non_existing_pub_subs);
|
||||
|
||||
auto p3 = std::make_shared<PublisherT>(rclcpp::QoS(10).reliable());
|
||||
auto p3 = std::make_shared<PublisherT>("topic", rclcpp::QoS(10).reliable());
|
||||
|
||||
auto s2 = std::make_shared<SubscriptionIntraProcessT>(rclcpp::QoS(10).reliable());
|
||||
auto s2 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10).reliable());
|
||||
|
||||
// s2 may be able to communicate with p1 depending on the RMW
|
||||
auto s2_id = ipm->template add_subscription<MessageT>(s2);
|
||||
// p3 can definitely communicate with s2, may be able to communicate with s1 depending on the RMW
|
||||
auto p3_id = ipm->add_publisher(p3);
|
||||
|
||||
// p1 definitely matches subscription s1, since the topic name and QoS match exactly.
|
||||
// If the RMW can match best-effort publishers to reliable subscriptions (like Zenoh can),
|
||||
// then p1 will also match s2.
|
||||
p1_subs = ipm->get_subscription_count(p1_id);
|
||||
// No subscriptions with a topic name of "different_topic_name" were added.
|
||||
p2_subs = ipm->get_subscription_count(p2_id);
|
||||
// On all current RMWs (DDS and Zenoh), a reliable publisher like p3 can communicate with both
|
||||
// reliable and best-effort subscriptions (s1 and s2).
|
||||
size_t p3_subs = ipm->get_subscription_count(p3_id);
|
||||
ASSERT_EQ(1u, p1_subs);
|
||||
|
||||
rclcpp::QoSCheckCompatibleResult qos_compatible =
|
||||
rclcpp::qos_check_compatible(p1->get_actual_qos(), s2->get_actual_qos());
|
||||
if (qos_compatible.compatibility == rclcpp::QoSCompatibility::Error) {
|
||||
ASSERT_EQ(1u, p1_subs);
|
||||
} else {
|
||||
ASSERT_EQ(2u, p1_subs);
|
||||
}
|
||||
ASSERT_EQ(0u, p2_subs);
|
||||
ASSERT_EQ(2u, p3_subs);
|
||||
|
||||
@@ -528,11 +548,11 @@ TEST(TestIntraProcessManager, single_subscription) {
|
||||
|
||||
auto ipm = std::make_shared<IntraProcessManagerT>();
|
||||
|
||||
auto p1 = std::make_shared<PublisherT>();
|
||||
auto p1 = std::make_shared<PublisherT>("topic", rclcpp::QoS(10));
|
||||
auto p1_id = ipm->add_publisher(p1);
|
||||
p1->set_intra_process_manager(p1_id, ipm);
|
||||
|
||||
auto s1 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s1 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s1->take_shared_method = false;
|
||||
auto s1_id = ipm->template add_subscription<MessageT>(s1);
|
||||
|
||||
@@ -543,7 +563,7 @@ TEST(TestIntraProcessManager, single_subscription) {
|
||||
ASSERT_EQ(original_message_pointer, received_message_pointer_1);
|
||||
|
||||
ipm->remove_subscription(s1_id);
|
||||
auto s2 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s2 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s2->take_shared_method = true;
|
||||
auto s2_id = ipm->template add_subscription<MessageT>(s2);
|
||||
(void)s2_id;
|
||||
@@ -582,15 +602,15 @@ TEST(TestIntraProcessManager, multiple_subscriptions_same_type) {
|
||||
|
||||
auto ipm = std::make_shared<IntraProcessManagerT>();
|
||||
|
||||
auto p1 = std::make_shared<PublisherT>();
|
||||
auto p1 = std::make_shared<PublisherT>("topic", rclcpp::QoS(10));
|
||||
auto p1_id = ipm->add_publisher(p1);
|
||||
p1->set_intra_process_manager(p1_id, ipm);
|
||||
|
||||
auto s1 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s1 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s1->take_shared_method = false;
|
||||
auto s1_id = ipm->template add_subscription<MessageT>(s1);
|
||||
|
||||
auto s2 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s2 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s2->take_shared_method = false;
|
||||
auto s2_id = ipm->template add_subscription<MessageT>(s2);
|
||||
|
||||
@@ -606,11 +626,11 @@ TEST(TestIntraProcessManager, multiple_subscriptions_same_type) {
|
||||
ipm->remove_subscription(s1_id);
|
||||
ipm->remove_subscription(s2_id);
|
||||
|
||||
auto s3 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s3 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s3->take_shared_method = true;
|
||||
auto s3_id = ipm->template add_subscription<MessageT>(s3);
|
||||
|
||||
auto s4 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s4 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s4->take_shared_method = true;
|
||||
auto s4_id = ipm->template add_subscription<MessageT>(s4);
|
||||
|
||||
@@ -625,11 +645,11 @@ TEST(TestIntraProcessManager, multiple_subscriptions_same_type) {
|
||||
ipm->remove_subscription(s3_id);
|
||||
ipm->remove_subscription(s4_id);
|
||||
|
||||
auto s5 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s5 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s5->take_shared_method = false;
|
||||
auto s5_id = ipm->template add_subscription<MessageT>(s5);
|
||||
|
||||
auto s6 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s6 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s6->take_shared_method = false;
|
||||
auto s6_id = ipm->template add_subscription<MessageT>(s6);
|
||||
|
||||
@@ -645,12 +665,12 @@ TEST(TestIntraProcessManager, multiple_subscriptions_same_type) {
|
||||
ipm->remove_subscription(s5_id);
|
||||
ipm->remove_subscription(s6_id);
|
||||
|
||||
auto s7 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s7 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s7->take_shared_method = true;
|
||||
auto s7_id = ipm->template add_subscription<MessageT>(s7);
|
||||
(void)s7_id;
|
||||
|
||||
auto s8 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s8 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s8->take_shared_method = true;
|
||||
auto s8_id = ipm->template add_subscription<MessageT>(s8);
|
||||
(void)s8_id;
|
||||
@@ -688,15 +708,15 @@ TEST(TestIntraProcessManager, multiple_subscriptions_different_type) {
|
||||
|
||||
auto ipm = std::make_shared<IntraProcessManagerT>();
|
||||
|
||||
auto p1 = std::make_shared<PublisherT>();
|
||||
auto p1 = std::make_shared<PublisherT>("topic", rclcpp::QoS(10));
|
||||
auto p1_id = ipm->add_publisher(p1);
|
||||
p1->set_intra_process_manager(p1_id, ipm);
|
||||
|
||||
auto s1 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s1 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s1->take_shared_method = true;
|
||||
auto s1_id = ipm->template add_subscription<MessageT>(s1);
|
||||
|
||||
auto s2 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s2 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s2->take_shared_method = false;
|
||||
auto s2_id = ipm->template add_subscription<MessageT>(s2);
|
||||
|
||||
@@ -711,15 +731,15 @@ TEST(TestIntraProcessManager, multiple_subscriptions_different_type) {
|
||||
ipm->remove_subscription(s1_id);
|
||||
ipm->remove_subscription(s2_id);
|
||||
|
||||
auto s3 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s3 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s3->take_shared_method = false;
|
||||
auto s3_id = ipm->template add_subscription<MessageT>(s3);
|
||||
|
||||
auto s4 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s4 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s4->take_shared_method = false;
|
||||
auto s4_id = ipm->template add_subscription<MessageT>(s4);
|
||||
|
||||
auto s5 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s5 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s5->take_shared_method = true;
|
||||
auto s5_id = ipm->template add_subscription<MessageT>(s5);
|
||||
|
||||
@@ -743,19 +763,19 @@ TEST(TestIntraProcessManager, multiple_subscriptions_different_type) {
|
||||
ipm->remove_subscription(s4_id);
|
||||
ipm->remove_subscription(s5_id);
|
||||
|
||||
auto s6 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s6 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s6->take_shared_method = true;
|
||||
auto s6_id = ipm->template add_subscription<MessageT>(s6);
|
||||
|
||||
auto s7 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s7 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s7->take_shared_method = true;
|
||||
auto s7_id = ipm->template add_subscription<MessageT>(s7);
|
||||
|
||||
auto s8 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s8 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s8->take_shared_method = false;
|
||||
auto s8_id = ipm->template add_subscription<MessageT>(s8);
|
||||
|
||||
auto s9 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s9 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s9->take_shared_method = false;
|
||||
auto s9_id = ipm->template add_subscription<MessageT>(s9);
|
||||
|
||||
@@ -781,12 +801,12 @@ TEST(TestIntraProcessManager, multiple_subscriptions_different_type) {
|
||||
ipm->remove_subscription(s8_id);
|
||||
ipm->remove_subscription(s9_id);
|
||||
|
||||
auto s10 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s10 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s10->take_shared_method = false;
|
||||
auto s10_id = ipm->template add_subscription<MessageT>(s10);
|
||||
(void)s10_id;
|
||||
|
||||
auto s11 = std::make_shared<SubscriptionIntraProcessT>();
|
||||
auto s11 = std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(10));
|
||||
s11->take_shared_method = true;
|
||||
auto s11_id = ipm->template add_subscription<MessageT>(s11);
|
||||
(void)s11_id;
|
||||
@@ -831,10 +851,12 @@ TEST(TestIntraProcessManager, lowest_available_capacity) {
|
||||
|
||||
auto ipm = std::make_shared<IntraProcessManagerT>();
|
||||
|
||||
auto p1 = std::make_shared<PublisherT>(rclcpp::QoS(history_depth).best_effort());
|
||||
auto p1 = std::make_shared<PublisherT>("topic", rclcpp::QoS(history_depth).best_effort());
|
||||
|
||||
auto s1 = std::make_shared<SubscriptionIntraProcessT>(rclcpp::QoS(history_depth).best_effort());
|
||||
auto s2 = std::make_shared<SubscriptionIntraProcessT>(rclcpp::QoS(history_depth).best_effort());
|
||||
auto s1 =
|
||||
std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(history_depth).best_effort());
|
||||
auto s2 =
|
||||
std::make_shared<SubscriptionIntraProcessT>("topic", rclcpp::QoS(history_depth).best_effort());
|
||||
|
||||
auto p1_id = ipm->add_publisher(p1);
|
||||
p1->set_intra_process_manager(p1_id, ipm);
|
||||
@@ -902,7 +924,7 @@ TEST(TestIntraProcessManager, transient_local_invalid_buffer) {
|
||||
|
||||
auto ipm = std::make_shared<IntraProcessManagerT>();
|
||||
|
||||
auto p1 = std::make_shared<PublisherT>(rclcpp::QoS(history_depth).transient_local());
|
||||
auto p1 = std::make_shared<PublisherT>("topic", rclcpp::QoS(history_depth).transient_local());
|
||||
|
||||
ASSERT_THROW(
|
||||
{
|
||||
@@ -926,14 +948,14 @@ TEST(TestIntraProcessManager, transient_local) {
|
||||
|
||||
auto ipm = std::make_shared<IntraProcessManagerT>();
|
||||
|
||||
auto p1 = std::make_shared<PublisherT>(rclcpp::QoS(history_depth).transient_local());
|
||||
auto p1 = std::make_shared<PublisherT>("topic", rclcpp::QoS(history_depth).transient_local());
|
||||
|
||||
auto s1 =
|
||||
std::make_shared<SubscriptionIntraProcessT>(rclcpp::QoS(history_depth).transient_local());
|
||||
auto s2 =
|
||||
std::make_shared<SubscriptionIntraProcessT>(rclcpp::QoS(history_depth).transient_local());
|
||||
auto s3 =
|
||||
std::make_shared<SubscriptionIntraProcessT>(rclcpp::QoS(history_depth).transient_local());
|
||||
auto s1 = std::make_shared<SubscriptionIntraProcessT>(
|
||||
"topic", rclcpp::QoS(history_depth).transient_local());
|
||||
auto s2 = std::make_shared<SubscriptionIntraProcessT>(
|
||||
"topic", rclcpp::QoS(history_depth).transient_local());
|
||||
auto s3 = std::make_shared<SubscriptionIntraProcessT>(
|
||||
"topic", rclcpp::QoS(history_depth).transient_local());
|
||||
|
||||
s1->take_shared_method = false;
|
||||
s2->take_shared_method = true;
|
||||
|
||||
@@ -200,6 +200,57 @@ TEST(TestNodeOptions, copy) {
|
||||
rcl_arguments_get_count_unparsed(&other_rcl_options->arguments),
|
||||
rcl_arguments_get_count_unparsed(&rcl_options->arguments));
|
||||
}
|
||||
|
||||
{
|
||||
// The following scope test is missing:
|
||||
// "arguments" because it is already tested in the above scopes
|
||||
// "parameter_event_publisher_options" because it can not be directly compared with EXPECT_EQ
|
||||
// "allocator" because it can not be directly compared with EXPECT_EQ
|
||||
|
||||
// We separate attribute modification from variable initialisation (copy assignment operator)
|
||||
// to be sure the "non_default_options"'s properties are correctly set before testing the
|
||||
// assignment operator.
|
||||
auto non_default_options = rclcpp::NodeOptions();
|
||||
non_default_options
|
||||
.parameter_overrides({rclcpp::Parameter("foo", 0), rclcpp::Parameter("bar", "1")})
|
||||
.use_global_arguments(false)
|
||||
.enable_rosout(false)
|
||||
.use_intra_process_comms(true)
|
||||
.enable_topic_statistics(true)
|
||||
.start_parameter_services(false)
|
||||
.enable_logger_service(true)
|
||||
.start_parameter_event_publisher(false)
|
||||
.clock_type(RCL_SYSTEM_TIME)
|
||||
.clock_qos(rclcpp::SensorDataQoS())
|
||||
.use_clock_thread(false)
|
||||
.parameter_event_qos(rclcpp::ClockQoS())
|
||||
.rosout_qos(rclcpp::ParameterEventsQoS())
|
||||
.allow_undeclared_parameters(true)
|
||||
.automatically_declare_parameters_from_overrides(true);
|
||||
|
||||
auto copied_options = non_default_options;
|
||||
EXPECT_EQ(non_default_options.parameter_overrides(), copied_options.parameter_overrides());
|
||||
EXPECT_EQ(non_default_options.use_global_arguments(), copied_options.use_global_arguments());
|
||||
EXPECT_EQ(non_default_options.enable_rosout(), copied_options.enable_rosout());
|
||||
EXPECT_EQ(non_default_options.use_intra_process_comms(),
|
||||
copied_options.use_intra_process_comms());
|
||||
EXPECT_EQ(non_default_options.enable_topic_statistics(),
|
||||
copied_options.enable_topic_statistics());
|
||||
EXPECT_EQ(non_default_options.start_parameter_services(),
|
||||
copied_options.start_parameter_services());
|
||||
EXPECT_EQ(non_default_options.enable_logger_service(), copied_options.enable_logger_service());
|
||||
EXPECT_EQ(non_default_options.start_parameter_event_publisher(),
|
||||
copied_options.start_parameter_event_publisher());
|
||||
EXPECT_EQ(non_default_options.clock_type(), copied_options.clock_type());
|
||||
EXPECT_EQ(non_default_options.clock_qos(), copied_options.clock_qos());
|
||||
EXPECT_EQ(non_default_options.use_clock_thread(), copied_options.use_clock_thread());
|
||||
EXPECT_EQ(non_default_options.parameter_event_qos(), copied_options.parameter_event_qos());
|
||||
EXPECT_EQ(non_default_options.rosout_qos(), copied_options.rosout_qos());
|
||||
EXPECT_EQ(non_default_options.allow_undeclared_parameters(),
|
||||
copied_options.allow_undeclared_parameters());
|
||||
EXPECT_EQ(non_default_options.automatically_declare_parameters_from_overrides(),
|
||||
copied_options.automatically_declare_parameters_from_overrides());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestNodeOptions, append_parameter_override) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <future>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -187,6 +188,21 @@ TEST_F(TestPublisher, various_creation_signatures) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Testing publisher with intraprocess enabled and SystemDefaultQoS
|
||||
*/
|
||||
TEST_F(TestPublisher, test_publisher_with_system_default_qos) {
|
||||
initialize(rclcpp::NodeOptions().use_intra_process_comms(false));
|
||||
// explicitly enable intra-process comm with publisher option
|
||||
auto options = rclcpp::PublisherOptions();
|
||||
options.use_intra_process_comm = rclcpp::IntraProcessSetting::Enable;
|
||||
using test_msgs::msg::Empty;
|
||||
ASSERT_NO_THROW(
|
||||
{
|
||||
auto publisher = node->create_publisher<Empty>("topic", rclcpp::SystemDefaultsQoS());
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
Testing publisher with intraprocess enabled and invalid QoS
|
||||
*/
|
||||
@@ -432,11 +448,10 @@ TEST_F(TestPublisher, intra_process_publish_failures) {
|
||||
publisher->get_publisher_handle().get(), msg.get()));
|
||||
}
|
||||
}
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
node->create_publisher<test_msgs::msg::Empty>(
|
||||
"topic", rclcpp::QoS(0), options),
|
||||
std::invalid_argument(
|
||||
"intraprocess communication is not allowed with a zero qos history depth value"));
|
||||
// a zero depth with KEEP_LAST doesn't make sense,
|
||||
// this will be interpreted as SystemDefaultQoS by rclcpp.
|
||||
EXPECT_NO_THROW(
|
||||
node->create_publisher<test_msgs::msg::Empty>("topic", rclcpp::QoS(0), options));
|
||||
}
|
||||
|
||||
TEST_F(TestPublisher, inter_process_publish_failures) {
|
||||
@@ -711,11 +726,7 @@ TEST_F(TestPublisher, intra_process_transient_local) {
|
||||
auto do_nothing = [](std::shared_ptr<const test_msgs::msg::Empty>) {};
|
||||
struct IntraProcessCallback
|
||||
{
|
||||
void callback_fun(size_t s)
|
||||
{
|
||||
(void) s;
|
||||
called = true;
|
||||
}
|
||||
void callback_fun(size_t) {called = true;}
|
||||
bool called = false;
|
||||
};
|
||||
rclcpp::SubscriptionOptions sub_options_ipm_disabled;
|
||||
@@ -772,3 +783,44 @@ TEST_F(TestPublisher, intra_process_transient_local) {
|
||||
EXPECT_FALSE(callback3.called);
|
||||
EXPECT_FALSE(callback4.called);
|
||||
}
|
||||
|
||||
TEST_F(TestPublisher, intra_process_inter_process_mix_transient_local) {
|
||||
constexpr auto history_depth = 10u;
|
||||
initialize(rclcpp::NodeOptions().use_intra_process_comms(true));
|
||||
|
||||
rclcpp::PublisherOptionsWithAllocator<std::allocator<void>> pub_options_ipm_enabled;
|
||||
pub_options_ipm_enabled.use_intra_process_comm = rclcpp::IntraProcessSetting::Enable;
|
||||
|
||||
auto pub_ipm_enabled_transient_local_enabled = node->create_publisher<test_msgs::msg::Empty>(
|
||||
"topic1",
|
||||
rclcpp::QoS(rclcpp::KeepLast(history_depth)).transient_local(), pub_options_ipm_enabled);
|
||||
|
||||
test_msgs::msg::Empty msg;
|
||||
pub_ipm_enabled_transient_local_enabled->publish(msg);
|
||||
|
||||
auto do_nothing = [](std::shared_ptr<const test_msgs::msg::Empty>) {};
|
||||
struct SubscriptionCallback
|
||||
{
|
||||
void callback_fun(size_t) {called.set_value();}
|
||||
std::promise<void> called;
|
||||
};
|
||||
rclcpp::SubscriptionOptions sub_options_ipm_disabled;
|
||||
sub_options_ipm_disabled.use_intra_process_comm = rclcpp::IntraProcessSetting::Disable;
|
||||
SubscriptionCallback intra_callback, inter_callback;
|
||||
std::future<void> intra_callback_future = intra_callback.called.get_future(),
|
||||
inter_callback_future = inter_callback.called.get_future();
|
||||
auto sub_ipm_disabled_transient_local_enabled = node->create_subscription<test_msgs::msg::Empty>(
|
||||
"topic1",
|
||||
rclcpp::QoS(rclcpp::KeepLast(history_depth)).transient_local(),
|
||||
do_nothing, sub_options_ipm_disabled);
|
||||
sub_ipm_disabled_transient_local_enabled->set_on_new_intra_process_message_callback(
|
||||
std::bind(&SubscriptionCallback::callback_fun, &intra_callback, std::placeholders::_1));
|
||||
sub_ipm_disabled_transient_local_enabled->set_on_new_message_callback(
|
||||
std::bind(&SubscriptionCallback::callback_fun, &inter_callback, std::placeholders::_1));
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
EXPECT_EQ(executor.spin_until_future_complete(inter_callback_future,
|
||||
std::chrono::milliseconds(100)), rclcpp::FutureReturnCode::SUCCESS);
|
||||
EXPECT_EQ(executor.spin_until_future_complete(intra_callback_future,
|
||||
std::chrono::milliseconds(100)), rclcpp::FutureReturnCode::TIMEOUT);
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ TEST_F(TestService, rcl_service_request_subscription_get_actual_qos_error) {
|
||||
TEST_F(TestService, server_qos) {
|
||||
rclcpp::ServicesQoS qos_profile;
|
||||
qos_profile.liveliness(rclcpp::LivelinessPolicy::Automatic);
|
||||
rclcpp::Duration duration(std::chrono::nanoseconds(1));
|
||||
rclcpp::Duration duration(std::chrono::milliseconds(1));
|
||||
qos_profile.deadline(duration);
|
||||
qos_profile.lifespan(duration);
|
||||
qos_profile.liveliness_lease_duration(duration);
|
||||
|
||||
@@ -92,9 +92,16 @@ TEST_F(TestServiceIntrospection, service_introspection_nominal)
|
||||
request->set__int64_value(42);
|
||||
|
||||
client->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
service->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
|
||||
// Wait for the introspection to attach to our subscription
|
||||
size_t tries = 1000;
|
||||
while (this->sub->get_publisher_count() < 2 && tries-- > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
ASSERT_EQ(sub->get_publisher_count(), 2u);
|
||||
|
||||
auto future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
@@ -124,10 +131,10 @@ TEST_F(TestServiceIntrospection, service_introspection_nominal)
|
||||
ASSERT_THAT(
|
||||
client_gid_arr,
|
||||
testing::Eq(event_map[ServiceEventInfo::REQUEST_SENT]->info.client_gid));
|
||||
// TODO(@fujitatomoya): Remove this if statement once other rmw implementations support test.
|
||||
// Only rmw_connextdds can pass this test requirement for now.
|
||||
// TODO(@fujitatomoya): Remove this if statement once rmw implementations support test.
|
||||
// rmw_cyclonedds_cpp does not pass this test requirement for now.
|
||||
// See more details for https://github.com/ros2/rmw/issues/357
|
||||
if (std::string(rmw_get_implementation_identifier()).find("rmw_connextdds") == 0) {
|
||||
if (std::string(rmw_get_implementation_identifier()).find("rmw_cyclonedds_cpp") != 0) {
|
||||
ASSERT_THAT(
|
||||
client_gid_arr,
|
||||
testing::Eq(event_map[ServiceEventInfo::REQUEST_RECEIVED]->info.client_gid));
|
||||
@@ -163,9 +170,11 @@ TEST_F(TestServiceIntrospection, service_introspection_nominal)
|
||||
TEST_F(TestServiceIntrospection, service_introspection_enable_disable_events)
|
||||
{
|
||||
client->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_OFF);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_OFF);
|
||||
service->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_OFF);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_OFF);
|
||||
|
||||
ASSERT_EQ(sub->get_publisher_count(), 0);
|
||||
|
||||
auto request = std::make_shared<BasicTypes::Request>();
|
||||
request->set__bool_value(true);
|
||||
@@ -183,9 +192,16 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_events)
|
||||
events.clear();
|
||||
|
||||
client->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
service->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_OFF);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_OFF);
|
||||
|
||||
// Wait for the introspection to attach to our subscription
|
||||
size_t tries = 1000;
|
||||
while (this->sub->get_publisher_count() < 1 && tries-- > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
ASSERT_EQ(sub->get_publisher_count(), 1u);
|
||||
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
@@ -200,9 +216,16 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_events)
|
||||
events.clear();
|
||||
|
||||
client->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_OFF);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_OFF);
|
||||
service->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
|
||||
// Wait for the introspection to attach to our subscription
|
||||
tries = 1000;
|
||||
while (this->sub->get_publisher_count() < 1 && tries-- > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
ASSERT_EQ(sub->get_publisher_count(), 1u);
|
||||
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
@@ -217,9 +240,16 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_events)
|
||||
events.clear();
|
||||
|
||||
client->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
service->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
|
||||
// Wait for the introspection to attach to our subscription
|
||||
tries = 1000;
|
||||
while (this->sub->get_publisher_count() < 2 && tries-- > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
ASSERT_EQ(sub->get_publisher_count(), 2u);
|
||||
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
@@ -235,9 +265,16 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_events)
|
||||
TEST_F(TestServiceIntrospection, service_introspection_enable_disable_event_content)
|
||||
{
|
||||
client->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
service->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
|
||||
// Wait for the introspection to attach to our subscription
|
||||
size_t tries = 1000;
|
||||
while (this->sub->get_publisher_count() < 2 && tries-- > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
ASSERT_EQ(sub->get_publisher_count(), 2u);
|
||||
|
||||
auto request = std::make_shared<BasicTypes::Request>();
|
||||
request->set__bool_value(true);
|
||||
@@ -259,9 +296,16 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_event_cont
|
||||
events.clear();
|
||||
|
||||
client->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
service->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
|
||||
// Wait for the introspection to attach to our subscription
|
||||
tries = 1000;
|
||||
while (this->sub->get_publisher_count() < 2 && tries-- > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
ASSERT_EQ(sub->get_publisher_count(), 2u);
|
||||
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
@@ -292,9 +336,16 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_event_cont
|
||||
events.clear();
|
||||
|
||||
client->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
service->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
|
||||
// Wait for the introspection to attach to our subscription
|
||||
tries = 1000;
|
||||
while (this->sub->get_publisher_count() < 2 && tries-- > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
ASSERT_EQ(sub->get_publisher_count(), 2u);
|
||||
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
@@ -325,9 +376,16 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_event_cont
|
||||
events.clear();
|
||||
|
||||
client->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
service->configure_introspection(
|
||||
node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS);
|
||||
|
||||
// Wait for the introspection to attach to our subscription
|
||||
tries = 1000;
|
||||
while (this->sub->get_publisher_count() < 2 && tries-- > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
ASSERT_EQ(sub->get_publisher_count(), 2u);
|
||||
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
|
||||
@@ -65,7 +65,7 @@ TEST_F(TestSubscriptionOptions, topic_statistics_options_default_and_set) {
|
||||
EXPECT_EQ(options.topic_stats_options.state, rclcpp::TopicStatisticsState::NodeDefault);
|
||||
EXPECT_EQ(options.topic_stats_options.publish_topic, defaultPublishTopic);
|
||||
EXPECT_EQ(options.topic_stats_options.publish_period, 1s);
|
||||
EXPECT_EQ(options.topic_stats_options.qos, rclcpp::SystemDefaultsQoS());
|
||||
EXPECT_EQ(options.topic_stats_options.qos, rclcpp::SystemDefaultsQoS().keep_last(10));
|
||||
|
||||
options.topic_stats_options.state = rclcpp::TopicStatisticsState::Enable;
|
||||
options.topic_stats_options.publish_topic = "topic_statistics";
|
||||
|
||||
@@ -212,6 +212,9 @@ TEST_F(TestTimeSource, ROS_time_valid_attach_detach) {
|
||||
ts.attachNode(node);
|
||||
EXPECT_FALSE(ros_clock->ros_time_is_active());
|
||||
|
||||
ts.attachClock(ros_clock);
|
||||
EXPECT_FALSE(ros_clock->ros_time_is_active());
|
||||
|
||||
ts.detachClock(ros_clock);
|
||||
EXPECT_FALSE(ros_clock->ros_time_is_active());
|
||||
}
|
||||
|
||||
@@ -3,6 +3,19 @@ Changelog for package rclcpp_action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
29.3.0 (2024-12-20)
|
||||
-------------------
|
||||
* Make ament_cmake a buildtool dependency (`#2689 <https://github.com/ros2/rclcpp/issues/2689>`_)
|
||||
* Contributors: Nathan Wiebe Neufeldt
|
||||
|
||||
29.2.0 (2024-11-25)
|
||||
-------------------
|
||||
|
||||
29.1.0 (2024-11-20)
|
||||
-------------------
|
||||
* Fix documentation typo in server_goal_handle.hpp (`#2669 <https://github.com/ros2/rclcpp/issues/2669>`_)
|
||||
* Contributors: YR
|
||||
|
||||
29.0.0 (2024-10-03)
|
||||
-------------------
|
||||
* Increase the timeout for the cppcheck on rclcpp_action. (`#2640 <https://github.com/ros2/rclcpp/issues/2640>`_)
|
||||
|
||||
@@ -43,7 +43,7 @@ class ServerGoalHandleBase
|
||||
{
|
||||
public:
|
||||
/// Indicate if client has requested this goal be cancelled.
|
||||
/// \return true if a cancelation request has been accepted for this goal.
|
||||
/// \return true if a cancellation request has been accepted for this goal.
|
||||
RCLCPP_ACTION_PUBLIC
|
||||
bool
|
||||
is_canceling() const;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="2">
|
||||
<name>rclcpp_action</name>
|
||||
<version>29.0.0</version>
|
||||
<version>29.3.0</version>
|
||||
<description>Adds action APIs for C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
@@ -26,8 +26,6 @@
|
||||
<depend>rcl</depend>
|
||||
<depend>rcpputils</depend>
|
||||
|
||||
<depend>ament_cmake</depend>
|
||||
|
||||
<test_depend>ament_cmake_gtest</test_depend>
|
||||
<test_depend>ament_lint_auto</test_depend>
|
||||
<test_depend>ament_lint_common</test_depend>
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
Changelog for package rclcpp_components
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
29.3.0 (2024-12-20)
|
||||
-------------------
|
||||
* Add parsing for rest of obvious boolean extra arguments and throw for unsupported ones (`#2685 <https://github.com/ros2/rclcpp/issues/2685>`_)
|
||||
* Contributors: rcp1
|
||||
|
||||
29.2.0 (2024-11-25)
|
||||
-------------------
|
||||
|
||||
29.1.0 (2024-11-20)
|
||||
-------------------
|
||||
|
||||
29.0.0 (2024-10-03)
|
||||
-------------------
|
||||
* Shutdown the context before context's destructor is invoked in tests (`#2633 <https://github.com/ros2/rclcpp/issues/2633>`_)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="2">
|
||||
<name>rclcpp_components</name>
|
||||
<version>29.0.0</version>
|
||||
<version>29.3.0</version>
|
||||
<description>Package containing tools for dynamically loadable components</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -169,24 +169,63 @@ ComponentManager::create_node_options(const std::shared_ptr<LoadNode::Request> r
|
||||
|
||||
for (const auto & a : request->extra_arguments) {
|
||||
const rclcpp::Parameter extra_argument = rclcpp::Parameter::from_parameter_msg(a);
|
||||
if (extra_argument.get_name() == "use_intra_process_comms") {
|
||||
if (extra_argument.get_name() == "forward_global_arguments") {
|
||||
if (extra_argument.get_type() != rclcpp::ParameterType::PARAMETER_BOOL) {
|
||||
throw ComponentManagerException(
|
||||
"Extra component argument 'use_intra_process_comms' must be a boolean");
|
||||
}
|
||||
options.use_intra_process_comms(extra_argument.get_value<bool>());
|
||||
} else if (extra_argument.get_name() == "forward_global_arguments") {
|
||||
if (extra_argument.get_type() != rclcpp::ParameterType::PARAMETER_BOOL) {
|
||||
throw ComponentManagerException(
|
||||
"Extra component argument 'forward_global_arguments' must be a boolean");
|
||||
"Extra component argument 'forward_global_arguments' must be a boolean");
|
||||
}
|
||||
options.use_global_arguments(extra_argument.get_value<bool>());
|
||||
if (extra_argument.get_value<bool>()) {
|
||||
RCLCPP_WARN(
|
||||
get_logger(), "forward_global_arguments is true by default in nodes, but is not "
|
||||
"recommended in a component manager. If true, this will cause this node's behavior "
|
||||
"to be influenced by global arguments, not only those targeted at this node.");
|
||||
get_logger(), "forward_global_arguments is true by default in nodes, but is not "
|
||||
"recommended in a component manager. If true, this will cause this node's behavior "
|
||||
"to be influenced by global arguments, not only those targeted at this node.");
|
||||
}
|
||||
} else if (extra_argument.get_name() == "enable_rosout") {
|
||||
if (extra_argument.get_type() != rclcpp::ParameterType::PARAMETER_BOOL) {
|
||||
throw ComponentManagerException(
|
||||
"Extra component argument 'enable_rosout' must be a boolean");
|
||||
}
|
||||
options.enable_rosout(extra_argument.get_value<bool>());
|
||||
} else if (extra_argument.get_name() == "use_intra_process_comms") {
|
||||
if (extra_argument.get_type() != rclcpp::ParameterType::PARAMETER_BOOL) {
|
||||
throw ComponentManagerException(
|
||||
"Extra component argument 'use_intra_process_comms' must be a boolean");
|
||||
}
|
||||
options.use_intra_process_comms(extra_argument.get_value<bool>());
|
||||
} else if (extra_argument.get_name() == "enable_topic_statistics") {
|
||||
if (extra_argument.get_type() != rclcpp::ParameterType::PARAMETER_BOOL) {
|
||||
throw ComponentManagerException(
|
||||
"Extra component argument 'enable_topic_statistics' must be a boolean");
|
||||
}
|
||||
options.enable_topic_statistics(extra_argument.get_value<bool>());
|
||||
} else if (extra_argument.get_name() == "start_parameter_services") {
|
||||
if (extra_argument.get_type() != rclcpp::ParameterType::PARAMETER_BOOL) {
|
||||
throw ComponentManagerException(
|
||||
"Extra component argument 'start_parameter_services' must be a boolean");
|
||||
}
|
||||
options.start_parameter_services(extra_argument.get_value<bool>());
|
||||
} else if (extra_argument.get_name() == "start_parameter_event_publisher") {
|
||||
if (extra_argument.get_type() != rclcpp::ParameterType::PARAMETER_BOOL) {
|
||||
throw ComponentManagerException(
|
||||
"Extra component argument 'start_parameter_event_publisher' must be a boolean");
|
||||
}
|
||||
options.start_parameter_event_publisher(extra_argument.get_value<bool>());
|
||||
} else if (extra_argument.get_name() == "use_clock_thread") {
|
||||
if (extra_argument.get_type() != rclcpp::ParameterType::PARAMETER_BOOL) {
|
||||
throw ComponentManagerException(
|
||||
"Extra component argument 'use_clock_thread' must be a boolean");
|
||||
}
|
||||
options.use_clock_thread(extra_argument.get_value<bool>());
|
||||
} else if (extra_argument.get_name() == "enable_logger_service") {
|
||||
if (extra_argument.get_type() != rclcpp::ParameterType::PARAMETER_BOOL) {
|
||||
throw ComponentManagerException(
|
||||
"Extra component argument 'enable_logger_service' must be a boolean");
|
||||
}
|
||||
options.enable_logger_service(extra_argument.get_value<bool>());
|
||||
} else {
|
||||
throw ComponentManagerException("Extra component argument '" + extra_argument.get_name() +
|
||||
"' is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -181,90 +181,74 @@ void test_components_api(bool use_dedicated_executor)
|
||||
}
|
||||
|
||||
{
|
||||
// use_intra_process_comms
|
||||
// invalid extra argument
|
||||
auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
|
||||
request->package_name = "rclcpp_components";
|
||||
request->plugin_name = "test_rclcpp_components::TestComponentFoo";
|
||||
request->node_name = "test_component_intra_process";
|
||||
rclcpp::Parameter use_intraprocess_comms("use_intra_process_comms",
|
||||
rclcpp::ParameterValue(true));
|
||||
request->extra_arguments.push_back(use_intraprocess_comms.to_parameter_msg());
|
||||
request->node_name = "test_component_allow_undeclared_parameters";
|
||||
rclcpp::Parameter extra_argument("allow_undeclared_parameters", rclcpp::ParameterValue(true));
|
||||
request->extra_arguments.push_back(extra_argument.to_parameter_msg());
|
||||
|
||||
auto future = composition_client->async_send_request(request);
|
||||
auto ret = exec->spin_until_future_complete(future, 5s); // Wait for the result.
|
||||
auto result = future.get();
|
||||
EXPECT_EQ(ret, rclcpp::FutureReturnCode::SUCCESS);
|
||||
EXPECT_EQ(result->success, true);
|
||||
EXPECT_EQ(result->error_message, "");
|
||||
std::cout << result->full_node_name << std::endl;
|
||||
EXPECT_EQ(result->full_node_name, "/test_component_intra_process");
|
||||
EXPECT_EQ(result->unique_id, 6u);
|
||||
}
|
||||
|
||||
{
|
||||
// use_intra_process_comms is not a bool type parameter
|
||||
auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
|
||||
request->package_name = "rclcpp_components";
|
||||
request->plugin_name = "test_rclcpp_components::TestComponentFoo";
|
||||
request->node_name = "test_component_intra_process_str";
|
||||
|
||||
rclcpp::Parameter use_intraprocess_comms("use_intra_process_comms",
|
||||
rclcpp::ParameterValue("hello"));
|
||||
request->extra_arguments.push_back(use_intraprocess_comms.to_parameter_msg());
|
||||
|
||||
auto future = composition_client->async_send_request(request);
|
||||
auto ret = exec->spin_until_future_complete(future, 5s); // Wait for the result.
|
||||
auto ret = exec->spin_until_future_complete(future, 5s); // Wait for the result.
|
||||
auto result = future.get();
|
||||
EXPECT_EQ(ret, rclcpp::FutureReturnCode::SUCCESS);
|
||||
EXPECT_EQ(result->success, false);
|
||||
EXPECT_EQ(
|
||||
result->error_message,
|
||||
"Extra component argument 'use_intra_process_comms' must be a boolean");
|
||||
EXPECT_EQ(result->error_message,
|
||||
"Extra component argument 'allow_undeclared_parameters' is not supported");
|
||||
EXPECT_EQ(result->full_node_name, "");
|
||||
EXPECT_EQ(result->unique_id, 0u);
|
||||
}
|
||||
|
||||
{
|
||||
// forward_global_arguments
|
||||
std::array<std::string, 8u> valid_extra_arguments = {
|
||||
"forward_global_arguments",
|
||||
"use_intra_process_comms",
|
||||
"enable_rosout",
|
||||
"enable_topic_statistics",
|
||||
"start_parameter_services",
|
||||
"start_parameter_event_publisher",
|
||||
"use_clock_thread",
|
||||
"enable_logger_service"
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < valid_extra_arguments.size(); ++i) {
|
||||
const auto & arg = valid_extra_arguments[i];
|
||||
auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
|
||||
request->package_name = "rclcpp_components";
|
||||
request->plugin_name = "test_rclcpp_components::TestComponentFoo";
|
||||
request->node_name = "test_component_global_arguments";
|
||||
rclcpp::Parameter forward_global_arguments("forward_global_arguments",
|
||||
rclcpp::ParameterValue(true));
|
||||
request->extra_arguments.push_back(forward_global_arguments.to_parameter_msg());
|
||||
{
|
||||
// success
|
||||
request->node_name = "test_component_" + arg;
|
||||
rclcpp::Parameter extra_argument(arg, rclcpp::ParameterValue(true));
|
||||
request->extra_arguments.push_back(extra_argument.to_parameter_msg());
|
||||
|
||||
auto future = composition_client->async_send_request(request);
|
||||
auto ret = exec->spin_until_future_complete(future, 5s); // Wait for the result.
|
||||
auto result = future.get();
|
||||
EXPECT_EQ(ret, rclcpp::FutureReturnCode::SUCCESS);
|
||||
EXPECT_EQ(result->success, true);
|
||||
EXPECT_EQ(result->error_message, "");
|
||||
EXPECT_EQ(result->full_node_name, "/test_component_global_arguments");
|
||||
EXPECT_EQ(result->unique_id, 7u);
|
||||
}
|
||||
auto future = composition_client->async_send_request(request);
|
||||
auto ret = exec->spin_until_future_complete(future, 5s); // Wait for the result.
|
||||
auto result = future.get();
|
||||
EXPECT_EQ(ret, rclcpp::FutureReturnCode::SUCCESS);
|
||||
EXPECT_EQ(result->success, true);
|
||||
EXPECT_EQ(result->error_message, "");
|
||||
EXPECT_EQ(result->full_node_name, "/test_component_" + arg);
|
||||
EXPECT_EQ(result->unique_id, 6u + i);
|
||||
}
|
||||
|
||||
{
|
||||
// forward_global_arguments is not a bool type parameter
|
||||
auto request = std::make_shared<composition_interfaces::srv::LoadNode::Request>();
|
||||
request->package_name = "rclcpp_components";
|
||||
request->plugin_name = "test_rclcpp_components::TestComponentFoo";
|
||||
request->node_name = "test_component_global_arguments_str";
|
||||
{
|
||||
// not a bool type parameter
|
||||
request->node_name = "test_component_" + arg + "_str";
|
||||
rclcpp::Parameter extra_argument(arg, rclcpp::ParameterValue("hello"));
|
||||
request->extra_arguments.clear();
|
||||
request->extra_arguments.push_back(extra_argument.to_parameter_msg());
|
||||
|
||||
rclcpp::Parameter forward_global_arguments("forward_global_arguments",
|
||||
rclcpp::ParameterValue("hello"));
|
||||
request->extra_arguments.push_back(forward_global_arguments.to_parameter_msg());
|
||||
|
||||
auto future = composition_client->async_send_request(request);
|
||||
auto ret = exec->spin_until_future_complete(future, 5s); // Wait for the result.
|
||||
auto result = future.get();
|
||||
EXPECT_EQ(ret, rclcpp::FutureReturnCode::SUCCESS);
|
||||
EXPECT_EQ(result->success, false);
|
||||
EXPECT_EQ(
|
||||
result->error_message,
|
||||
"Extra component argument 'forward_global_arguments' must be a boolean");
|
||||
EXPECT_EQ(result->full_node_name, "");
|
||||
EXPECT_EQ(result->unique_id, 0u);
|
||||
auto future = composition_client->async_send_request(request);
|
||||
auto ret = exec->spin_until_future_complete(future, 5s); // Wait for the result.
|
||||
auto result = future.get();
|
||||
EXPECT_EQ(ret, rclcpp::FutureReturnCode::SUCCESS);
|
||||
EXPECT_EQ(result->success, false);
|
||||
EXPECT_EQ(result->error_message,
|
||||
"Extra component argument '" + arg + "' must be a boolean");
|
||||
EXPECT_EQ(result->full_node_name, "");
|
||||
EXPECT_EQ(result->unique_id, 0u);
|
||||
}
|
||||
}
|
||||
|
||||
auto node_names = node->get_node_names();
|
||||
@@ -295,22 +279,19 @@ void test_components_api(bool use_dedicated_executor)
|
||||
auto result_node_names = result->full_node_names;
|
||||
auto result_unique_ids = result->unique_ids;
|
||||
|
||||
EXPECT_EQ(result_node_names.size(), 7u);
|
||||
EXPECT_EQ(result_node_names.size(), 5u + valid_extra_arguments.size());
|
||||
EXPECT_EQ(result_node_names[0], "/test_component_foo");
|
||||
EXPECT_EQ(result_node_names[1], "/test_component_bar");
|
||||
EXPECT_EQ(result_node_names[2], "/test_component_baz");
|
||||
EXPECT_EQ(result_node_names[3], "/ns/test_component_bing");
|
||||
EXPECT_EQ(result_node_names[4], "/test_component_remap");
|
||||
EXPECT_EQ(result_node_names[5], "/test_component_intra_process");
|
||||
EXPECT_EQ(result_node_names[6], "/test_component_global_arguments");
|
||||
EXPECT_EQ(result_unique_ids.size(), 7u);
|
||||
EXPECT_EQ(result_unique_ids[0], 1u);
|
||||
EXPECT_EQ(result_unique_ids[1], 2u);
|
||||
EXPECT_EQ(result_unique_ids[2], 3u);
|
||||
EXPECT_EQ(result_unique_ids[3], 4u);
|
||||
EXPECT_EQ(result_unique_ids[4], 5u);
|
||||
EXPECT_EQ(result_unique_ids[5], 6u);
|
||||
EXPECT_EQ(result_unique_ids[6], 7u);
|
||||
for (size_t i = 0u; i < valid_extra_arguments.size(); ++i) {
|
||||
EXPECT_EQ(result_node_names[5u + i], "/test_component_" + valid_extra_arguments[i]);
|
||||
}
|
||||
EXPECT_EQ(result_unique_ids.size(), 5u + valid_extra_arguments.size());
|
||||
for (size_t i = 0u; i < result_unique_ids.size(); ++i) {
|
||||
EXPECT_EQ(result_unique_ids[i], 1u + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,20 +345,18 @@ void test_components_api(bool use_dedicated_executor)
|
||||
auto result_node_names = result->full_node_names;
|
||||
auto result_unique_ids = result->unique_ids;
|
||||
|
||||
EXPECT_EQ(result_node_names.size(), 6u);
|
||||
EXPECT_EQ(result_node_names.size(), 4u + valid_extra_arguments.size());
|
||||
EXPECT_EQ(result_node_names[0], "/test_component_bar");
|
||||
EXPECT_EQ(result_node_names[1], "/test_component_baz");
|
||||
EXPECT_EQ(result_node_names[2], "/ns/test_component_bing");
|
||||
EXPECT_EQ(result_node_names[3], "/test_component_remap");
|
||||
EXPECT_EQ(result_node_names[4], "/test_component_intra_process");
|
||||
EXPECT_EQ(result_node_names[5], "/test_component_global_arguments");
|
||||
EXPECT_EQ(result_unique_ids.size(), 6u);
|
||||
EXPECT_EQ(result_unique_ids[0], 2u);
|
||||
EXPECT_EQ(result_unique_ids[1], 3u);
|
||||
EXPECT_EQ(result_unique_ids[2], 4u);
|
||||
EXPECT_EQ(result_unique_ids[3], 5u);
|
||||
EXPECT_EQ(result_unique_ids[4], 6u);
|
||||
EXPECT_EQ(result_unique_ids[5], 7u);
|
||||
for (size_t i = 0u; i < valid_extra_arguments.size(); ++i) {
|
||||
EXPECT_EQ(result_node_names[4u + i], "/test_component_" + valid_extra_arguments[i]);
|
||||
}
|
||||
EXPECT_EQ(result_unique_ids.size(), 4u + valid_extra_arguments.size());
|
||||
for (size_t i = 0u; i < result_unique_ids.size(); ++i) {
|
||||
EXPECT_EQ(result_unique_ids[i], 2u + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,19 @@ Changelog for package rclcpp_lifecycle
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
29.3.0 (2024-12-20)
|
||||
-------------------
|
||||
* Update docstring for `rclcpp::Node::now()` (`#2696 <https://github.com/ros2/rclcpp/issues/2696>`_)
|
||||
* Contributors: Patrick Roncagliolo
|
||||
|
||||
29.2.0 (2024-11-25)
|
||||
-------------------
|
||||
|
||||
29.1.0 (2024-11-20)
|
||||
-------------------
|
||||
* Fix error message in rclcpp_lifecycle::State::reset() (`#2647 <https://github.com/ros2/rclcpp/issues/2647>`_)
|
||||
* Contributors: Christophe Bedard
|
||||
|
||||
29.0.0 (2024-10-03)
|
||||
-------------------
|
||||
* Shutdown the context before context's destructor is invoked in tests (`#2633 <https://github.com/ros2/rclcpp/issues/2633>`_)
|
||||
|
||||
@@ -731,7 +731,7 @@ public:
|
||||
rclcpp::Clock::ConstSharedPtr
|
||||
get_clock() const;
|
||||
|
||||
/// Returns current time from the time source specified by clock_type.
|
||||
/// Returns current time from the node clock.
|
||||
/**
|
||||
* \sa rclcpp::Clock::now
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="2">
|
||||
<name>rclcpp_lifecycle</name>
|
||||
<version>29.0.0</version>
|
||||
<version>29.3.0</version>
|
||||
<description>Package containing a prototype for lifecycle implementation</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -167,7 +167,7 @@ State::reset() noexcept
|
||||
if (ret != RCL_RET_OK) {
|
||||
RCLCPP_ERROR(
|
||||
rclcpp::get_logger("rclcpp_lifecycle"),
|
||||
"rcl_lifecycle_transition_fini did not complete successfully, leaking memory");
|
||||
"rcl_lifecycle_state_fini did not complete successfully, leaking memory");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user