Compare commits

...

11 Commits
2.4.0 ... 2.4.2

Author SHA1 Message Date
Jacob Perron
11edf82c7d 2.4.2 2022-07-25 12:24:51 -07:00
mergify[bot]
48ec78cb24 Add statistics for handle_loaned_message (backport #1927) (#1934)
* Add statistics for handle_loaned_message (#1927)

Signed-off-by: Barry Xu <barry.xu@sony.com>
(cherry picked from commit 5c688303b3)

# Conflicts:
#	rclcpp/include/rclcpp/subscription.hpp

* Fix merge conflicts (#1939)

Signed-off-by: Barry Xu <barry.xu@sony.com>
2022-06-09 11:49:31 -07:00
mergify[bot]
5c1dd19456 Add test-dep ament_cmake_google_benchmark (#1904) (#1910)
Signed-off-by: Gaël Écorchard <gael.ecorchard@cvut.cz>
(cherry picked from commit eac0063176)

Co-authored-by: Gaël Écorchard <galou_breizh@yahoo.fr>
2022-04-25 13:34:30 -07:00
mergify[bot]
15edc93a5f Use parantheses around logging macro parameter (#1820) (#1823)
* Use parantheses around logging macro parameter

This allows the macro to expand "correctly", i.e. macro argument
expression is fully evaluated before use.

Signed-off-by: Abrar Rahman Protyasha <aprotyas@u.rochester.edu>

* Remove redundant parantheses around macro param

`decltype(X)` already provides sufficient "scoping" to the macro
parameter `X`.

Signed-off-by: Abrar Rahman Protyasha <aprotyas@u.rochester.edu>

* Add test case for expressions as logging param

Signed-off-by: Abrar Rahman Protyasha <aprotyas@u.rochester.edu>
(cherry picked from commit f7bb88fc8f)

Co-authored-by: Abrar Rahman Protyasha <aprotyas@u.rochester.edu>
2022-02-04 16:57:44 -05:00
Jacob Perron
1ea25302c3 2.4.1 2022-01-31 13:58:28 -08:00
Christophe Bedard
7e1740a52b Fix subscription instrumentation for ConstSharedPtr[WithInfo]Callback (#1872)
Signed-off-by: Christophe Bedard <bedard.christophe@gmail.com>
2022-01-31 09:27:56 -05:00
mergify[bot]
a8baa3ce88 add node_waitables_ to copy constructor. (backport #1799) (#1834)
* add node_waitables_ to copy constructor.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

* add node_time_source_ to copy constructor.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

* add construction_and_destruction_sub_node for action server.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

Co-authored-by: Abrar Rahman Protyasha <abrar@openrobotics.org>
(cherry picked from commit 301957515a)

Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2021-12-03 16:24:28 -03:00
mergify[bot]
a58f8c1de4 Fix returning invalid namespace if sub_namespace is empty (#1658) (#1811)
* Create valid effective namespace when sub-namespace is empty

Fix #1656.

Signed-off-by: Markus Hofstaetter <markus.hofstaetter@ait.ac.at>

* Add regression test for effective namespace and empty sub-namespace

Adds regression test for #1656.

Signed-off-by: Markus Hofstaetter <markus.hofstaetter@ait.ac.at>
(cherry picked from commit 3cddb4edab)

Co-authored-by: M. Hofstätter <markus.hofstaetter@gmx.net>
2021-11-11 09:22:24 -05:00
mergify[bot]
d7804e1b3f [service] Don't use a weak_ptr to avoid leaking (#1668) (#1669)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
(cherry picked from commit d488535f36)

# Conflicts:
#	rclcpp/include/rclcpp/service.hpp

Co-authored-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2021-10-25 17:07:23 -03:00
mergify[bot]
e70a07d0c0 use dynamic_pointer_cast to detect allocator mismatch in intra process manager (backport #1643) (#1645)
* use dynamic_pointer_cast to detect allocator mismatch in intra process manager (#1643)

* use dynamic_pointer_cast to detect allocator mismatch in intra process manager

Signed-off-by: William Woodall <william@osrfoundation.org>

* add test case for mismatched allocators

Signed-off-by: William Woodall <william@osrfoundation.org>

* forward template arguments to avoid mismatched types in intra process manager

Signed-off-by: William Woodall <william@osrfoundation.org>

* style fixes

Signed-off-by: William Woodall <william@osrfoundation.org>

* refactor to test message address and count, more DRY

Signed-off-by: William Woodall <william@osrfoundation.org>

* update copyright

Signed-off-by: William Woodall <william@osrfoundation.org>

* fix typo

Signed-off-by: William Woodall <william@osrfoundation.org>

Co-authored-by: Michel Hidalgo <michel@ekumenlabs.com>

Co-authored-by: Michel Hidalgo <michel@ekumenlabs.com>
(cherry picked from commit 79c2dd8e8b)

# Conflicts:
#	rclcpp/include/rclcpp/experimental/intra_process_manager.hpp

* fix conflicts

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

* cpp14 compatibility

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

* More cpp14 compat

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

* fix

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

* Fix bug

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

Co-authored-by: William Woodall <william@osrfoundation.org>
Co-authored-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2021-10-12 12:23:57 -07:00
George Stavrinos
4859c4e435 Foxy README now points to foxy docs (#1794)
Signed-off-by: George Stavrinos <gstavrinos@protonmail.com>
2021-10-04 08:52:41 -04:00
21 changed files with 476 additions and 36 deletions

View File

@@ -8,10 +8,10 @@ rclcpp provides the standard C++ API for interacting with ROS 2.
`#include "rclcpp/rclcpp.hpp"` allows use of the most common elements of the ROS 2 system.
Visit the [rclcpp API documentation](http://docs.ros2.org/latest/api/rclcpp/) for a complete list of its main components.
Visit the [rclcpp API documentation](http://docs.ros2.org/foxy/api/rclcpp/) for a complete list of its main components.
### Examples
The ROS 2 tutorials [Writing a simple publisher and subscriber](https://index.ros.org/doc/ros2/Tutorials/Writing-A-Simple-Cpp-Publisher-And-Subscriber/)
and [Writing a simple service and client](https://index.ros.org/doc/ros2/Tutorials/Writing-A-Simple-Cpp-Service-And-Client/)
The ROS 2 tutorials [Writing a simple publisher and subscriber](https://docs.ros.org/en/foxy/Tutorials/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html).
and [Writing a simple service and client](https://docs.ros.org/en/foxy/Tutorials/Writing-A-Simple-Cpp-Service-And-Client.html)
contain some examples of rclcpp APIs in use.

View File

@@ -2,6 +2,22 @@
Changelog for package rclcpp
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2.4.2 (2022-07-25)
------------------
* Add statistics for handle_loaned_message (`#1927 <https://github.com/ros2/rclcpp/issues/1927>`_) (`#1934 <https://github.com/ros2/rclcpp/issues/1934>`_)
* Add test-dep ament_cmake_google_benchmark (`#1904 <https://github.com/ros2/rclcpp/issues/1904>`_) (`#1910 <https://github.com/ros2/rclcpp/issues/1910>`_)
* Use parantheses around logging macro parameter (`#1820 <https://github.com/ros2/rclcpp/issues/1820>`_) (`#1823 <https://github.com/ros2/rclcpp/issues/1823>`_)
* Contributors: Abrar Rahman Protyasha, Barry Xu, Gaël Écorchard
2.4.1 (2022-01-31)
------------------
* Fix subscription instrumentation for ConstSharedPtr[WithInfo]Callback (`#1872 <https://github.com/ros2/rclcpp/issues/1872>`_)
* Add node_waitables\_ to copy constructor (backport `#1799 <https://github.com/ros2/rclcpp/issues/1799>`_) (`#1834 <https://github.com/ros2/rclcpp/issues/1834>`_)
* Fix returning invalid namespace if sub_namespace is empty (`#1658 <https://github.com/ros2/rclcpp/issues/1658>`_) (`#1811 <https://github.com/ros2/rclcpp/issues/1811>`_)
* [service] Don't use a weak_ptr to avoid leaking (`#1668 <https://github.com/ros2/rclcpp/issues/1668>`_) (`#1669 <https://github.com/ros2/rclcpp/issues/1669>`_)
* Use dynamic_pointer_cast to detect allocator mismatch in intra process manager (backport `#1643 <https://github.com/ros2/rclcpp/issues/1643>`_) (`#1645 <https://github.com/ros2/rclcpp/issues/1645>`_)
* Contributors: Abrar Rahman Protyasha, Christophe Bedard, Ivan Santiago Paunovic, M. Hofstätter, Michel Hidalgo, Tomoya Fujita, William Woodall
2.4.0 (2021-09-01)
------------------
* Guard against integer overflow in duration conversion (`#1584 <https://github.com/ros2/rclcpp/issues/1584>`_) (`#1761 <https://github.com/ros2/rclcpp/issues/1761>`_)

View File

@@ -246,6 +246,16 @@ public:
rclcpp_callback_register,
(const void *)this,
get_symbol(shared_ptr_with_info_callback_));
} else if (const_shared_ptr_callback_) {
TRACEPOINT(
rclcpp_callback_register,
(const void *)this,
get_symbol(const_shared_ptr_callback_));
} else if (const_shared_ptr_with_info_callback_) {
TRACEPOINT(
rclcpp_callback_register,
(const void *)this,
get_symbol(const_shared_ptr_with_info_callback_));
} else if (unique_ptr_callback_) {
TRACEPOINT(
rclcpp_callback_register,

View File

@@ -202,7 +202,8 @@ public:
// None of the buffers require ownership, so we promote the pointer
std::shared_ptr<MessageT> msg = std::move(message);
this->template add_shared_msg_to_buffers<MessageT>(msg, sub_ids.take_shared_subscriptions);
this->template add_shared_msg_to_buffers<MessageT, Alloc, Deleter>(
msg, sub_ids.take_shared_subscriptions);
} else if (!sub_ids.take_ownership_subscriptions.empty() && // NOLINT
sub_ids.take_shared_subscriptions.size() <= 1)
{
@@ -227,7 +228,7 @@ public:
// for the buffers that do not require ownership
auto shared_msg = std::allocate_shared<MessageT, MessageAllocatorT>(*allocator, *message);
this->template add_shared_msg_to_buffers<MessageT>(
this->template add_shared_msg_to_buffers<MessageT, Alloc, Deleter>(
shared_msg, sub_ids.take_shared_subscriptions);
this->template add_owned_msg_to_buffers<MessageT, Alloc, Deleter>(
std::move(message), sub_ids.take_ownership_subscriptions, allocator);
@@ -263,7 +264,7 @@ public:
// If there are no owning, just convert to shared.
std::shared_ptr<MessageT> shared_msg = std::move(message);
if (!sub_ids.take_shared_subscriptions.empty()) {
this->template add_shared_msg_to_buffers<MessageT>(
this->template add_shared_msg_to_buffers<MessageT, Alloc, Deleter>(
shared_msg, sub_ids.take_shared_subscriptions);
}
return shared_msg;
@@ -273,7 +274,7 @@ public:
auto shared_msg = std::allocate_shared<MessageT, MessageAllocatorT>(*allocator, *message);
if (!sub_ids.take_shared_subscriptions.empty()) {
this->template add_shared_msg_to_buffers<MessageT>(
this->template add_shared_msg_to_buffers<MessageT, Alloc, Deleter>(
shared_msg,
sub_ids.take_shared_subscriptions);
}
@@ -350,7 +351,10 @@ private:
bool
can_communicate(PublisherInfo pub_info, SubscriptionInfo sub_info) const;
template<typename MessageT>
template<
typename MessageT,
typename Alloc,
typename Deleter>
void
add_shared_msg_to_buffers(
std::shared_ptr<const MessageT> message,
@@ -363,10 +367,16 @@ private:
}
auto subscription_base = subscription_it->second.subscription;
auto subscription = std::static_pointer_cast<
rclcpp::experimental::SubscriptionIntraProcess<MessageT>
auto subscription = std::dynamic_pointer_cast<
rclcpp::experimental::SubscriptionIntraProcess<MessageT, Alloc, Deleter>
>(subscription_base);
if (nullptr == subscription) {
throw std::runtime_error(
"failed to dynamic cast SubscriptionIntraProcessBase to "
"SubscriptionIntraProcess<MessageT, Alloc, Deleter>, which "
"can happen when the publisher and subscription use different "
"allocator types, which is not supported");
}
subscription->provide_intra_process_message(message);
}
}
@@ -391,9 +401,16 @@ private:
}
auto subscription_base = subscription_it->second.subscription;
auto subscription = std::static_pointer_cast<
rclcpp::experimental::SubscriptionIntraProcess<MessageT>
auto subscription = std::dynamic_pointer_cast<
rclcpp::experimental::SubscriptionIntraProcess<MessageT, Alloc, Deleter>
>(subscription_base);
if (nullptr == subscription) {
throw std::runtime_error(
"failed to dynamic cast SubscriptionIntraProcessBase to "
"SubscriptionIntraProcess<MessageT, Alloc, Deleter>, which "
"can happen when the publisher and subscription use different "
"allocator types, which is not supported");
}
if (std::next(it) == subscription_ids.end()) {
// If this is the last subscription, give up ownership

View File

@@ -177,25 +177,16 @@ public:
using rosidl_typesupport_cpp::get_service_type_support_handle;
auto service_type_support_handle = get_service_type_support_handle<ServiceT>();
std::weak_ptr<rcl_node_t> weak_node_handle(node_handle_);
// rcl does the static memory allocation here
service_handle_ = std::shared_ptr<rcl_service_t>(
new rcl_service_t, [weak_node_handle, service_name](rcl_service_t * service)
new rcl_service_t, [handle = node_handle_](rcl_service_t * service)
{
auto handle = weak_node_handle.lock();
if (handle) {
if (rcl_service_fini(service, handle.get()) != RCL_RET_OK) {
RCLCPP_ERROR(
rclcpp::get_node_logger(handle.get()).get_child("rclcpp"),
"Error in destruction of rcl service handle: %s",
rcl_get_error_string().str);
rcl_reset_error();
}
} else {
RCLCPP_ERROR_STREAM(
rclcpp::get_logger("rclcpp"),
"Error in destruction of rcl service handle " << service_name <<
": the Node Handle was destructed too early. You will leak memory");
if (rcl_service_fini(service, handle.get()) != RCL_RET_OK) {
RCLCPP_ERROR(
rclcpp::get_node_logger(handle.get()).get_child("rclcpp"),
"Error in destruction of rcl service handle: %s",
rcl_get_error_string().str);
rcl_reset_error();
}
delete service;
});

View File

@@ -287,11 +287,31 @@ public:
void * loaned_message,
const rclcpp::MessageInfo & message_info) override
{
if (matches_any_intra_process_publishers(&message_info.get_rmw_message_info().publisher_gid)) {
// In this case, the message will be delivered via intra process and
// we should ignore this copy of the message.
return;
}
auto typed_message = static_cast<CallbackMessageT *>(loaned_message);
// message is loaned, so we have to make sure that the deleter does not deallocate the message
auto sptr = std::shared_ptr<CallbackMessageT>(
typed_message, [](CallbackMessageT * msg) {(void) msg;});
std::chrono::time_point<std::chrono::system_clock> now;
if (subscription_topic_statistics_) {
// get current time before executing callback to
// exclude callback duration from topic statistics result.
now = std::chrono::system_clock::now();
}
any_callback_.dispatch(sptr, message_info);
if (subscription_topic_statistics_) {
const auto nanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(now);
const auto time = rclcpp::Time(nanos.time_since_epoch().count());
subscription_topic_statistics_->handle_message(*typed_message, time);
}
}
/// Return the borrowed message.

View File

@@ -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>2.4.0</version>
<version>2.4.2</version>
<description>The ROS client library in C++.</description>
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
<license>Apache License 2.0</license>
@@ -32,6 +32,7 @@
<depend>tracetools</depend>
<test_depend>ament_cmake_gmock</test_depend>
<test_depend>ament_cmake_google_benchmark</test_depend>
<test_depend>ament_cmake_gtest</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>

View File

@@ -149,7 +149,7 @@ def get_rclcpp_suffix_from_features(features):
@[ if params]@
@(''.join([' ' + p + ', \\\n' for p in params if p != stream_arg]))@
@[ end if]@
logger.get_name(), \
(logger).get_name(), \
@[ if 'stream' not in feature_combination]@
rclcpp::get_c_string(RCLCPP_FIRST_ARG(__VA_ARGS__, "")), \
RCLCPP_ALL_BUT_FIRST_ARGS(__VA_ARGS__,"")); \

View File

@@ -54,6 +54,12 @@ extend_sub_namespace(const std::string & existing_sub_namespace, const std::stri
extension.c_str(),
"a sub-namespace should not have a leading /",
0);
} else if (existing_sub_namespace.empty() && extension.empty()) {
throw rclcpp::exceptions::NameValidationError(
"sub_namespace",
extension.c_str(),
"sub-nodes should not extend nodes by an empty sub-namespace",
0);
}
std::string new_sub_namespace;
@@ -79,7 +85,11 @@ create_effective_namespace(const std::string & node_namespace, const std::string
// and do not need trimming of `/` and other things, as they were validated
// in other functions already.
if (node_namespace.back() == '/') {
// A node may not have a sub_namespace if it is no sub_node. In this case,
// just return the original namespace
if (sub_namespace.empty()) {
return node_namespace;
} else if (node_namespace.back() == '/') {
// this is the special case where node_namespace is just `/`
return node_namespace + sub_namespace;
} else {
@@ -158,6 +168,8 @@ Node::Node(
node_services_(other.node_services_),
node_clock_(other.node_clock_),
node_parameters_(other.node_parameters_),
node_time_source_(other.node_time_source_),
node_waitables_(other.node_waitables_),
node_options_(other.node_options_),
sub_namespace_(extend_sub_namespace(other.get_sub_namespace(), sub_namespace)),
effective_namespace_(create_effective_namespace(other.get_namespace(), sub_namespace_))

View File

@@ -134,6 +134,13 @@ if(TARGET test_intra_process_manager)
)
target_link_libraries(test_intra_process_manager ${PROJECT_NAME})
endif()
ament_add_gmock(test_intra_process_manager_with_allocators test_intra_process_manager_with_allocators.cpp)
if(TARGET test_intra_process_manager_with_allocators)
ament_target_dependencies(test_intra_process_manager_with_allocators
"test_msgs"
)
target_link_libraries(test_intra_process_manager_with_allocators ${PROJECT_NAME})
endif()
ament_add_gtest(test_ring_buffer_implementation test_ring_buffer_implementation.cpp)
if(TARGET test_ring_buffer_implementation)
ament_target_dependencies(test_ring_buffer_implementation

View File

@@ -216,7 +216,10 @@ public:
const char * topic_name;
};
template<typename MessageT>
template<
typename MessageT,
typename Alloc = std::allocator<void>,
typename Deleter = std::default_delete<MessageT>>
class SubscriptionIntraProcess : public SubscriptionIntraProcessBase
{
public:

View File

@@ -0,0 +1,303 @@
// Copyright 2021 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 <gmock/gmock.h>
#include <chrono>
#include <list>
#include <memory>
#include <string>
#include <utility>
#include "test_msgs/msg/empty.hpp"
#include "rclcpp/rclcpp.hpp"
#include "rclcpp/allocator/allocator_common.hpp"
#include "rclcpp/strategies/allocator_memory_strategy.hpp"
// For demonstration purposes only, not necessary for allocator_traits
static uint32_t num_allocs = 0;
static uint32_t num_deallocs = 0;
// A very simple custom allocator. Counts calls to allocate and deallocate.
template<typename T = void>
struct MyAllocator
{
public:
using value_type = T;
using size_type = std::size_t;
using pointer = T *;
using const_pointer = const T *;
using difference_type = typename std::pointer_traits<pointer>::difference_type;
MyAllocator() noexcept
{
}
~MyAllocator() noexcept {}
template<typename U>
MyAllocator(const MyAllocator<U> &) noexcept
{
}
T * allocate(size_t size, const void * = 0)
{
if (size == 0) {
return nullptr;
}
num_allocs++;
return static_cast<T *>(std::malloc(size * sizeof(T)));
}
void deallocate(T * ptr, size_t size)
{
(void)size;
if (!ptr) {
return;
}
num_deallocs++;
std::free(ptr);
}
template<typename U>
struct rebind
{
typedef MyAllocator<U> other;
};
};
template<typename T, typename U>
constexpr bool operator==(
const MyAllocator<T> &,
const MyAllocator<U> &) noexcept
{
return true;
}
template<typename T, typename U>
constexpr bool operator!=(
const MyAllocator<T> &,
const MyAllocator<U> &) noexcept
{
return false;
}
template<
typename ExpectedExceptionT,
typename PublisherT,
typename FutureT,
typename MessageT,
typename ExpectedMessagePtr,
typename std::enable_if<std::is_same<ExpectedExceptionT, void>::value, int>::type = 0>
void check_exception(
PublisherT & publisher, rclcpp::Executor & executor, FutureT received_message_future,
uint32_t & counter, MessageT msg, ExpectedMessagePtr expected_ptr)
{
// no exception expected
EXPECT_NO_THROW(
{
publisher->publish(std::move(msg));
executor.spin_until_future_complete(received_message_future, std::chrono::seconds(10));
});
EXPECT_EQ(expected_ptr, received_message_future.get().get());
EXPECT_EQ(1u, counter);
}
template<
typename ExpectedExceptionT,
typename PublisherT,
typename FutureT,
typename MessageT,
typename ExpectedMessagePtr,
typename std::enable_if<!std::is_same<ExpectedExceptionT, void>::value, int>::type = 0>
void check_exception(
PublisherT & publisher, rclcpp::Executor & executor, FutureT received_message_future,
uint32_t counter, MessageT msg, ExpectedMessagePtr expected_ptr)
{
(void)counter;
(void)expected_ptr;
// exception expected
EXPECT_THROW(
{
publisher->publish(std::move(msg));
executor.spin_until_future_complete(received_message_future, std::chrono::seconds(10));
}, ExpectedExceptionT);
}
template<
typename PublishedMessageAllocatorT,
typename PublisherAllocatorT,
typename SubscribedMessageAllocatorT,
typename SubscriptionAllocatorT,
typename MessageMemoryStrategyAllocatorT,
typename MemoryStrategyAllocatorT,
typename ExpectedExceptionT
>
void
do_custom_allocator_test(
PublishedMessageAllocatorT published_message_allocator,
PublisherAllocatorT publisher_allocator,
SubscribedMessageAllocatorT /* subscribed_message_allocator */, // intentionally unused
SubscriptionAllocatorT subscription_allocator,
MessageMemoryStrategyAllocatorT message_memory_strategy,
MemoryStrategyAllocatorT memory_strategy_allocator)
{
using PublishedMessageAllocTraits =
rclcpp::allocator::AllocRebind<test_msgs::msg::Empty, PublishedMessageAllocatorT>;
using PublishedMessageAlloc = typename PublishedMessageAllocTraits::allocator_type;
using PublishedMessageDeleter =
rclcpp::allocator::Deleter<PublishedMessageAlloc, test_msgs::msg::Empty>;
using SubscribedMessageAllocTraits =
rclcpp::allocator::AllocRebind<test_msgs::msg::Empty, SubscribedMessageAllocatorT>;
using SubscribedMessageAlloc = typename SubscribedMessageAllocTraits::allocator_type;
using SubscribedMessageDeleter =
rclcpp::allocator::Deleter<SubscribedMessageAlloc, test_msgs::msg::Empty>;
// init and node
auto context = std::make_shared<rclcpp::Context>();
context->init(0, nullptr);
auto node = std::make_shared<rclcpp::Node>(
"custom_allocator_test",
rclcpp::NodeOptions().context(context).use_intra_process_comms(true));
// publisher
auto shared_publisher_allocator = std::make_shared<PublisherAllocatorT>(publisher_allocator);
rclcpp::PublisherOptionsWithAllocator<PublisherAllocatorT> publisher_options;
publisher_options.allocator = shared_publisher_allocator;
auto publisher =
node->create_publisher<test_msgs::msg::Empty>("custom_allocator_test", 10, publisher_options);
// callback for subscription
uint32_t counter = 0;
std::promise<std::unique_ptr<test_msgs::msg::Empty, SubscribedMessageDeleter>> received_message;
auto received_message_future = received_message.get_future().share();
auto callback =
[&counter, &received_message](
std::unique_ptr<test_msgs::msg::Empty, SubscribedMessageDeleter> msg)
{
++counter;
received_message.set_value(std::move(msg));
};
// subscription
auto shared_subscription_allocator =
std::make_shared<SubscriptionAllocatorT>(subscription_allocator);
rclcpp::SubscriptionOptionsWithAllocator<SubscriptionAllocatorT> subscription_options;
subscription_options.allocator = shared_subscription_allocator;
auto shared_message_strategy_allocator =
std::make_shared<MessageMemoryStrategyAllocatorT>(message_memory_strategy);
auto msg_mem_strat = std::make_shared<
rclcpp::message_memory_strategy::MessageMemoryStrategy<
test_msgs::msg::Empty,
MessageMemoryStrategyAllocatorT
>
>(shared_message_strategy_allocator);
using CallbackMessageT =
typename rclcpp::subscription_traits::has_message_type<decltype(callback)>::type;
auto subscriber = node->create_subscription<
test_msgs::msg::Empty,
decltype(callback),
SubscriptionAllocatorT,
CallbackMessageT,
rclcpp::Subscription<CallbackMessageT, SubscriptionAllocatorT>,
rclcpp::message_memory_strategy::MessageMemoryStrategy<
CallbackMessageT,
MessageMemoryStrategyAllocatorT
>
>(
"custom_allocator_test",
10,
std::forward<decltype(callback)>(callback),
subscription_options,
msg_mem_strat);
// executor memory strategy
using rclcpp::memory_strategies::allocator_memory_strategy::AllocatorMemoryStrategy;
auto shared_memory_strategy_allocator = std::make_shared<MemoryStrategyAllocatorT>(
memory_strategy_allocator);
std::shared_ptr<rclcpp::memory_strategy::MemoryStrategy> memory_strategy =
std::make_shared<AllocatorMemoryStrategy<MemoryStrategyAllocatorT>>(
shared_memory_strategy_allocator);
// executor
rclcpp::ExecutorOptions options;
options.memory_strategy = memory_strategy;
options.context = context;
rclcpp::executors::SingleThreadedExecutor executor(options);
executor.add_node(node);
// rebind message_allocator to ensure correct type
PublishedMessageDeleter message_deleter;
PublishedMessageAlloc rebound_message_allocator = published_message_allocator;
rclcpp::allocator::set_allocator_for_deleter(&message_deleter, &rebound_message_allocator);
// allocate a message
auto ptr = PublishedMessageAllocTraits::allocate(rebound_message_allocator, 1);
PublishedMessageAllocTraits::construct(rebound_message_allocator, ptr);
std::unique_ptr<test_msgs::msg::Empty, PublishedMessageDeleter> msg(ptr, message_deleter);
// publisher and receive
check_exception<ExpectedExceptionT>(
publisher, executor, received_message_future, counter, std::move(msg), ptr);
}
/*
This tests the case where a custom allocator is used correctly, i.e. the same
custom allocator on both sides.
*/
TEST(TestIntraProcessManagerWithAllocators, custom_allocator) {
using PublishedMessageAllocatorT = std::allocator<void>;
using PublisherAllocatorT = std::allocator<void>;
using SubscribedMessageAllocatorT = std::allocator<void>;
using SubscriptionAllocatorT = std::allocator<void>;
using MessageMemoryStrategyAllocatorT = std::allocator<void>;
using MemoryStrategyAllocatorT = std::allocator<void>;
auto allocator = std::allocator<void>();
do_custom_allocator_test<
PublishedMessageAllocatorT,
PublisherAllocatorT,
SubscribedMessageAllocatorT,
SubscriptionAllocatorT,
MessageMemoryStrategyAllocatorT,
MemoryStrategyAllocatorT,
void // no exception expected
>(allocator, allocator, allocator, allocator, allocator, allocator);
}
/*
This tests the case where a custom allocator is used incorrectly, i.e. different
custom allocators on both sides.
*/
TEST(TestIntraProcessManagerWithAllocators, custom_allocator_wrong) {
// explicitly use a different allocator here to provoke a failure
using PublishedMessageAllocatorT = std::allocator<void>;
using PublisherAllocatorT = std::allocator<void>;
using SubscribedMessageAllocatorT = MyAllocator<void>;
using SubscriptionAllocatorT = MyAllocator<void>;
using MessageMemoryStrategyAllocatorT = MyAllocator<void>;
using MemoryStrategyAllocatorT = std::allocator<void>;
auto allocator = std::allocator<void>();
auto my_allocator = MyAllocator<void>();
do_custom_allocator_test<
PublishedMessageAllocatorT,
PublisherAllocatorT,
SubscribedMessageAllocatorT,
SubscriptionAllocatorT,
MessageMemoryStrategyAllocatorT,
MemoryStrategyAllocatorT,
std::runtime_error // expected exception
>(allocator, allocator, my_allocator, my_allocator, my_allocator, allocator);
}

View File

@@ -249,6 +249,12 @@ TEST_F(TestLoggingMacros, test_throttle) {
}
}
TEST_F(TestLoggingMacros, test_parameter_expression) {
RCLCPP_DEBUG_STREAM(*&g_logger, "message");
EXPECT_EQ(1u, g_log_calls);
EXPECT_EQ("message", g_last_log_event.message);
}
bool log_function(rclcpp::Logger logger)
{
RCLCPP_INFO(logger, "successful log");

View File

@@ -94,6 +94,7 @@ TEST_F(TestNode, get_name_and_namespace) {
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
EXPECT_STREQ("my_node", node->get_name());
EXPECT_STREQ("/ns", node->get_namespace());
EXPECT_STREQ("/ns", node->get_effective_namespace().c_str());
EXPECT_STREQ("/ns/my_node", node->get_fully_qualified_name());
}
{
@@ -108,30 +109,35 @@ TEST_F(TestNode, get_name_and_namespace) {
auto node = std::make_shared<rclcpp::Node>("my_node", "ns");
EXPECT_STREQ("my_node", node->get_name());
EXPECT_STREQ("/ns", node->get_namespace());
EXPECT_STREQ("/ns", node->get_effective_namespace().c_str());
EXPECT_STREQ("/ns/my_node", node->get_fully_qualified_name());
}
{
auto node = std::make_shared<rclcpp::Node>("my_node");
EXPECT_STREQ("my_node", node->get_name());
EXPECT_STREQ("/", node->get_namespace());
EXPECT_STREQ("/", node->get_effective_namespace().c_str());
EXPECT_STREQ("/my_node", node->get_fully_qualified_name());
}
{
auto node = std::make_shared<rclcpp::Node>("my_node", "");
EXPECT_STREQ("my_node", node->get_name());
EXPECT_STREQ("/", node->get_namespace());
EXPECT_STREQ("/", node->get_effective_namespace().c_str());
EXPECT_STREQ("/my_node", node->get_fully_qualified_name());
}
{
auto node = std::make_shared<rclcpp::Node>("my_node", "/my/ns");
EXPECT_STREQ("my_node", node->get_name());
EXPECT_STREQ("/my/ns", node->get_namespace());
EXPECT_STREQ("/my/ns", node->get_effective_namespace().c_str());
EXPECT_STREQ("/my/ns/my_node", node->get_fully_qualified_name());
}
{
auto node = std::make_shared<rclcpp::Node>("my_node", "my/ns");
EXPECT_STREQ("my_node", node->get_name());
EXPECT_STREQ("/my/ns", node->get_namespace());
EXPECT_STREQ("/my/ns", node->get_effective_namespace().c_str());
EXPECT_STREQ("/my/ns/my_node", node->get_fully_qualified_name());
}
{
@@ -270,6 +276,13 @@ TEST_F(TestNode, subnode_construction_and_destruction) {
auto subnode = node->create_sub_node("~sub_ns");
}, rclcpp::exceptions::InvalidNamespaceError);
}
{
ASSERT_THROW(
{
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
auto subnode = node->create_sub_node("");
}, rclcpp::exceptions::NameValidationError);
}
}
TEST_F(TestNode, get_logger) {

View File

@@ -3,6 +3,14 @@ Changelog for package rclcpp_action
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2.4.2 (2022-07-25)
------------------
2.4.1 (2022-01-31)
------------------
* Add node_waitables\_ to copy constructor (backport `#1799 <https://github.com/ros2/rclcpp/issues/1799>`_) (`#1834 <https://github.com/ros2/rclcpp/issues/1834>`_)
* Contributors: Abrar Rahman Protyasha, Tomoya Fujita
2.4.0 (2021-09-01)
------------------
* Fix occasionally missing goal result caused by race condition (`#1677 <https://github.com/ros2/rclcpp/issues/1677>`_) (`#1682 <https://github.com/ros2/rclcpp/issues/1682>`_)

View File

@@ -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>2.4.0</version>
<version>2.4.2</version>
<description>Adds action APIs for C++.</description>
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
<license>Apache License 2.0</license>

View File

@@ -205,6 +205,27 @@ TEST_F(TestServer, construction_and_destruction_wait_set_error)
}, rclcpp::exceptions::RCLError);
}
TEST_F(TestServer, construction_and_destruction_sub_node)
{
auto parent_node = std::make_shared<rclcpp::Node>("construct_node", "/rclcpp_action/construct");
auto sub_node = parent_node->create_sub_node("construct_sub_node");
ASSERT_NO_THROW(
{
using GoalHandle = rclcpp_action::ServerGoalHandle<Fibonacci>;
auto as = rclcpp_action::create_server<Fibonacci>(
sub_node, "fibonacci",
[](const GoalUUID &, std::shared_ptr<const Fibonacci::Goal>) {
return rclcpp_action::GoalResponse::REJECT;
},
[](std::shared_ptr<GoalHandle>) {
return rclcpp_action::CancelResponse::REJECT;
},
[](std::shared_ptr<GoalHandle>) {});
(void)as;
});
}
TEST_F(TestServer, handle_goal_called)
{
auto node = std::make_shared<rclcpp::Node>("handle_goal_node", "/rclcpp_action/handle_goal");

View File

@@ -2,6 +2,12 @@
Changelog for package rclcpp_components
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2.4.2 (2022-07-25)
------------------
2.4.1 (2022-01-31)
------------------
2.4.0 (2021-09-01)
------------------

View File

@@ -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>2.4.0</version>
<version>2.4.2</version>
<description>Package containing tools for dynamically loadable components</description>
<maintainer email="michael@openrobotics.org">Michael Carroll</maintainer>
<license>Apache License 2.0</license>

View File

@@ -3,6 +3,12 @@ Changelog for package rclcpp_lifecycle
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2.4.2 (2022-07-25)
------------------
2.4.1 (2022-01-31)
------------------
2.4.0 (2021-09-01)
------------------
* Fix SEGV caused by order of destruction of Node sub-interfaces (`#1469 <https://github.com/ros2/rclcpp/issues/1469>`_) (`#1736 <https://github.com/ros2/rclcpp/issues/1736>`_)

View File

@@ -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>2.4.0</version>
<version>2.4.2</version>
<description>Package containing a prototype for lifecycle implementation</description>
<maintainer email="karsten@osrfoundation.org">Karsten Knese</maintainer>
<license>Apache License 2.0</license>