Compare commits

...

15 Commits

Author SHA1 Message Date
Chris Lalancette
0f331f90a9 24.0.0 2023-11-06 17:36:49 +00:00
Chris Lalancette
620fcf1e05 Changelog.
Signed-off-by: Chris Lalancette <clalancette@gmail.com>
2023-11-06 17:36:40 +00:00
Zard-C
d407a5e331 fix (signal_handler.hpp): spelling (#2356)
Signed-off-by: Zard-C <patrick.zhang5233@gmail.com>
2023-11-05 14:28:17 -05:00
Chris Lalancette
7f411371b3 Updates to not use std::move in some places. (#2353)
gcc 13.1.1 complains that these uses inhibit copy elision.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
2023-11-05 14:27:40 -05:00
Tomoya Fujita
76e2b2677b rclcpp::Time::max() clock type support. (#2352)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2023-11-04 09:08:11 -07:00
Lucas Wendland
5049c45f85 Serialized Messages with Topic Statistics (#2274)
Signed-off-by: CursedRock17 <mtglucas1@gmail.com>
2023-11-03 15:06:25 -07:00
Michael Carroll
4691063a61 Add a custom deleter when constructing rcl_service_t (#2351)
* Add a custom deleter when constructing rcl_service_t

In the type description service construction, we were previously passing
the shared_ptr to the rcl_service_t with the assumption that
rclcpp::Service would do the clean up.  This was an incorrect
assumption, and so I have added a custom deleter to fini the service and
delete when the shared_ptr is cleaned up.

Signed-off-by: Michael Carroll <mjcarroll@intrinsic.ai>
2023-11-03 08:59:06 -04:00
Chris Lalancette
f294488e17 Disable the loaned messages inside the executor. (#2335)
* Disable the loaned messages inside the executor.

They are currently unsafe to use; see the comment in the
commit for more information.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
2023-11-02 18:29:12 -04:00
Michael Orlov
8a02e3934c Use message_info in SubscriptionTopicStatistics instead of typed message (#2337)
* Use message_info in SubscriptionTopicStatistics instead of typed message

- Untemplatize the rclcpp::topic_statistics::SubscriptionTopicStatistics
class. Now we will be using message_info instead of typed deserialized
messages in the handle_message callbacks.

* Fix test_receive_stats_include_window_reset by using publisher emulator

- Emulate publishing messages by directly calling
rclcpp::Subscription::handle_message(msg_shared_ptr, message_info) and
settling up needed message_info.source_timestamp

Signed-off-by: Michael Orlov <michael.orlov@apex.ai>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2023-11-02 13:26:33 -04:00
Jiaqi Li
fff009a751 Add missing 'enable_rosout' comments (#2345)
Signed-off-by: Jiaqi Li <ljq0831@qq.com>
2023-10-31 00:21:28 -07:00
Michael Carroll
2204e44305 Adjust rclcpp usage of type description service (#2344)
Signed-off-by: Michael Carroll <mjcarroll@intrinsic.ai>
2023-10-30 19:24:24 +00:00
Tomoya Fujita
fcbe64cff4 address rate related flaky tests. (#2329)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2023-10-26 00:08:18 -07:00
Chris Lalancette
c366e531fa Fixes pointed out by the clang analyzer. (#2339)
1. Remove the default Logger copy constructor without copy
assignment (rule of three -> rule of zero).
2. Remove an unnecessary capture in a lambda.
3. Mark a variable unused.
4. Mark a method as override.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
2023-10-23 11:10:18 -05:00
Alexey Merzlyakov
5ffc963e1a Remove useless ROSRate class (#2326)
Signed-off-by: Alexey Merzlyakov <alexey.merzlyakov@samsung.com>
2023-10-16 09:38:38 -04:00
Chris Lalancette
7f7ffcf6ed Fix rclcpp_lifecycle inclusion on Windows. (#2331)
The comment in the commit explains this clearly, but
on Windows ERROR is a macro.  The reuse of it, even
as an enum, causes compilation errors on downstream
users.  Push the macro and undefine it so downstream
consumers can freely include it.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
2023-10-10 13:25:55 -04:00
33 changed files with 256 additions and 426 deletions

View File

@@ -2,6 +2,22 @@
Changelog for package rclcpp
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24.0.0 (2023-11-06)
-------------------
* fix (signal_handler.hpp): spelling (`#2356 <https://github.com/ros2/rclcpp/issues/2356>`_)
* Updates to not use std::move in some places. (`#2353 <https://github.com/ros2/rclcpp/issues/2353>`_)
* rclcpp::Time::max() clock type support. (`#2352 <https://github.com/ros2/rclcpp/issues/2352>`_)
* Serialized Messages with Topic Statistics (`#2274 <https://github.com/ros2/rclcpp/issues/2274>`_)
* Add a custom deleter when constructing rcl_service_t (`#2351 <https://github.com/ros2/rclcpp/issues/2351>`_)
* Disable the loaned messages inside the executor. (`#2335 <https://github.com/ros2/rclcpp/issues/2335>`_)
* Use message_info in SubscriptionTopicStatistics instead of typed message (`#2337 <https://github.com/ros2/rclcpp/issues/2337>`_)
* Add missing 'enable_rosout' comments (`#2345 <https://github.com/ros2/rclcpp/issues/2345>`_)
* Adjust rclcpp usage of type description service (`#2344 <https://github.com/ros2/rclcpp/issues/2344>`_)
* address rate related flaky tests. (`#2329 <https://github.com/ros2/rclcpp/issues/2329>`_)
* Fixes pointed out by the clang analyzer. (`#2339 <https://github.com/ros2/rclcpp/issues/2339>`_)
* Remove useless ROSRate class (`#2326 <https://github.com/ros2/rclcpp/issues/2326>`_)
* Contributors: Alexey Merzlyakov, Chris Lalancette, Jiaqi Li, Lucas Wendland, Michael Carroll, Michael Orlov, Tomoya Fujita, Zard-C
23.2.0 (2023-10-09)
-------------------
* add clients & services count (`#2072 <https://github.com/ros2/rclcpp/issues/2072>`_)

View File

@@ -50,8 +50,8 @@ template<
typename SubscriptionT,
typename MessageMemoryStrategyT,
typename NodeParametersT,
typename NodeTopicsT,
typename ROSMessageType = typename SubscriptionT::ROSMessageType>
typename NodeTopicsT
>
typename std::shared_ptr<SubscriptionT>
create_subscription(
NodeParametersT & node_parameters,
@@ -70,7 +70,7 @@ create_subscription(
using rclcpp::node_interfaces::get_node_topics_interface;
auto node_topics_interface = get_node_topics_interface(node_topics);
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>>
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics>
subscription_topic_stats = nullptr;
if (rclcpp::detail::resolve_enable_topic_statistics(
@@ -80,8 +80,7 @@ create_subscription(
if (options.topic_stats_options.publish_period <= std::chrono::milliseconds(0)) {
throw std::invalid_argument(
"topic_stats_options.publish_period must be greater than 0, specified value of " +
std::to_string(options.topic_stats_options.publish_period.count()) +
" ms");
std::to_string(options.topic_stats_options.publish_period.count()) + " ms");
}
std::shared_ptr<Publisher<statistics_msgs::msg::MetricsMessage>>
@@ -91,12 +90,12 @@ create_subscription(
options.topic_stats_options.publish_topic,
qos);
subscription_topic_stats = std::make_shared<
rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>
>(node_topics_interface->get_node_base_interface()->get_name(), publisher);
subscription_topic_stats =
std::make_shared<rclcpp::topic_statistics::SubscriptionTopicStatistics>(
node_topics_interface->get_node_base_interface()->get_name(), publisher);
std::weak_ptr<
rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>
rclcpp::topic_statistics::SubscriptionTopicStatistics
> weak_subscription_topic_stats(subscription_topic_stats);
auto sub_call_back = [weak_subscription_topic_stats]() {
auto subscription_topic_stats = weak_subscription_topic_stats.lock();

View File

@@ -467,7 +467,7 @@ private:
auto ptr = MessageAllocTraits::allocate(allocator, 1);
MessageAllocTraits::construct(allocator, ptr, *message);
subscription->provide_intra_process_data(std::move(MessageUniquePtr(ptr, deleter)));
subscription->provide_intra_process_data(MessageUniquePtr(ptr, deleter));
}
continue;
@@ -510,7 +510,7 @@ private:
MessageAllocTraits::construct(allocator, ptr, *message);
ros_message_subscription->provide_intra_process_message(
std::move(MessageUniquePtr(ptr, deleter)));
MessageUniquePtr(ptr, deleter));
}
}
}

View File

@@ -126,9 +126,6 @@ private:
std::shared_ptr<std::pair<std::string, std::string>> logger_sublogger_pairname_ = nullptr;
public:
RCLCPP_PUBLIC
Logger(const Logger &) = default;
/// Get the name of this logger.
/**
* \return the full name of the logger including any prefixes, or

View File

@@ -43,6 +43,7 @@ public:
* - arguments = {}
* - parameter_overrides = {}
* - use_global_arguments = true
* - enable_rosout = true
* - use_intra_process_comms = false
* - enable_topic_statistics = false
* - start_parameter_services = true

View File

@@ -390,7 +390,7 @@ public:
if (this->can_loan_messages()) {
// we release the ownership from the rclpp::LoanedMessage instance
// and let the middleware clean up the memory.
this->do_loaned_message_publish(std::move(loaned_msg.release()));
this->do_loaned_message_publish(loaned_msg.release());
} else {
// we don't release the ownership, let the middleware copy the ros message
// and thus the destructor of rclcpp::LoanedMessage cleans up the memory.

View File

@@ -184,16 +184,6 @@ public:
explicit WallRate(const Duration & period);
};
class ROSRate : public Rate
{
public:
RCLCPP_PUBLIC
explicit ROSRate(const double rate);
RCLCPP_PUBLIC
explicit ROSRate(const Duration & period);
};
} // namespace rclcpp
#endif // RCLCPP__RATE_HPP_

View File

@@ -104,7 +104,7 @@ public:
private:
using SubscriptionTopicStatisticsSharedPtr =
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>>;
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics>;
public:
RCLCPP_SMART_PTR_DEFINITIONS(Subscription)
@@ -316,7 +316,7 @@ public:
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);
subscription_topic_statistics_->handle_message(message_info.get_rmw_message_info(), time);
}
}
@@ -325,8 +325,20 @@ public:
const std::shared_ptr<rclcpp::SerializedMessage> & serialized_message,
const rclcpp::MessageInfo & message_info) override
{
// TODO(wjwwood): enable topic statistics for serialized messages
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(serialized_message, 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(message_info.get_rmw_message_info(), time);
}
}
void
@@ -357,7 +369,7 @@ public:
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);
subscription_topic_statistics_->handle_message(message_info.get_rmw_message_info(), time);
}
}

View File

@@ -75,15 +75,14 @@ template<
typename CallbackT,
typename AllocatorT,
typename SubscriptionT = rclcpp::Subscription<MessageT, AllocatorT>,
typename MessageMemoryStrategyT = typename SubscriptionT::MessageMemoryStrategyType,
typename ROSMessageType = typename SubscriptionT::ROSMessageType
typename MessageMemoryStrategyT = typename SubscriptionT::MessageMemoryStrategyType
>
SubscriptionFactory
create_subscription_factory(
CallbackT && callback,
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat,
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>>
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics>
subscription_topic_stats = nullptr
)
{

View File

@@ -189,7 +189,7 @@ public:
*/
RCLCPP_PUBLIC
static Time
max();
max(rcl_clock_type_t clock_type = RCL_SYSTEM_TIME); // NOLINT
/// Get the seconds since epoch
/**

View File

@@ -48,21 +48,12 @@ using libstatistics_collector::moving_average_statistics::StatisticData;
/**
* Class used to collect, measure, and publish topic statistics data. Current statistics
* supported for subscribers are received message age and received message period.
*
* \tparam CallbackMessageT the subscribed message type
*/
template<typename CallbackMessageT>
*/
class SubscriptionTopicStatistics
{
using TopicStatsCollector =
libstatistics_collector::topic_statistics_collector::TopicStatisticsCollector<
CallbackMessageT>;
using ReceivedMessageAge =
libstatistics_collector::topic_statistics_collector::ReceivedMessageAgeCollector<
CallbackMessageT>;
using ReceivedMessagePeriod =
libstatistics_collector::topic_statistics_collector::ReceivedMessagePeriodCollector<
CallbackMessageT>;
using TopicStatsCollector = libstatistics_collector::TopicStatisticsCollector;
using ReceivedMessageAge = libstatistics_collector::ReceivedMessageAgeCollector;
using ReceivedMessagePeriod = libstatistics_collector::ReceivedMessagePeriodCollector;
public:
/// Construct a SubscriptionTopicStatistics object.
@@ -101,16 +92,16 @@ public:
/**
* This method acquires a lock to prevent race conditions to collectors list.
*
* \param received_message the message received by the subscription
* \param message_info the message info corresponding to the received message
* \param now_nanoseconds current time in nanoseconds
*/
virtual void handle_message(
const CallbackMessageT & received_message,
const rmw_message_info_t & message_info,
const rclcpp::Time now_nanoseconds) const
{
std::lock_guard<std::mutex> lock(mutex_);
for (const auto & collector : subscriber_statistics_collectors_) {
collector->OnMessageReceived(received_message, now_nanoseconds.nanoseconds());
collector->OnMessageReceived(message_info, now_nanoseconds.nanoseconds());
}
}

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>23.2.0</version>
<version>24.0.0</version>
<description>The ROS client library in C++.</description>
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>

View File

@@ -462,7 +462,7 @@ template<Context::ShutdownType shutdown_type>
std::vector<rclcpp::Context::ShutdownCallback>
Context::get_shutdown_callback() const
{
const auto get_callback_vector = [this](auto & mutex, auto & callback_set) {
const auto get_callback_vector = [](auto & mutex, auto & callback_set) {
const std::lock_guard<std::mutex> lock(mutex);
std::vector<rclcpp::Context::ShutdownCallback> callbacks;
for (auto & callback : callback_set) {
@@ -496,7 +496,7 @@ Context::sleep_for(const std::chrono::nanoseconds & nanoseconds)
std::unique_lock<std::mutex> lock(interrupt_mutex_);
auto start = std::chrono::steady_clock::now();
// this will release the lock while waiting
interrupt_condition_variable_.wait_for(lock, nanoseconds);
interrupt_condition_variable_.wait_for(lock, time_left);
time_left -= std::chrono::steady_clock::now() - start;
}
} while (time_left > std::chrono::nanoseconds::zero() && this->is_valid());

View File

@@ -669,6 +669,11 @@ Executor::execute_subscription(rclcpp::SubscriptionBase::SharedPtr subscription)
subscription->get_topic_name(),
[&]() {return subscription->take_type_erased(message.get(), message_info);},
[&]() {subscription->handle_message(message, message_info);});
// TODO(clalancette): In the case that the user is using the MessageMemoryPool,
// and they take a shared_ptr reference to the message in the callback, this can
// inadvertently return the message to the pool when the user is still using it.
// This is a bug that needs to be fixed in the pool, and we should probably have
// a custom deleter for the message that actually does the return_message().
subscription->return_message(message);
}
break;

View File

@@ -84,23 +84,31 @@ public:
}
if (enabled) {
auto rcl_node = node_base->get_rcl_node_handle();
rcl_ret_t rcl_ret = rcl_node_type_description_service_init(rcl_node);
auto * rcl_node = node_base->get_rcl_node_handle();
std::shared_ptr<rcl_service_t> rcl_srv(
new rcl_service_t,
[rcl_node, logger = this->logger_](rcl_service_t * service)
{
if (rcl_service_fini(service, rcl_node) != RCL_RET_OK) {
RCLCPP_ERROR(
logger,
"Error in destruction of rcl service handle [~/get_type_description]: %s",
rcl_get_error_string().str);
rcl_reset_error();
}
delete service;
});
*rcl_srv = rcl_get_zero_initialized_service();
rcl_ret_t rcl_ret = rcl_node_type_description_service_init(rcl_srv.get(), rcl_node);
if (rcl_ret != RCL_RET_OK) {
RCLCPP_ERROR(
logger_, "Failed to initialize ~/get_type_description_service: %s",
logger_, "Failed to initialize ~/get_type_description service: %s",
rcl_get_error_string().str);
throw std::runtime_error(
"Failed to initialize ~/get_type_description service.");
}
rcl_service_t * rcl_srv = nullptr;
rcl_ret = rcl_node_get_type_description_service(rcl_node, &rcl_srv);
if (rcl_ret != RCL_RET_OK) {
throw std::runtime_error(
"Failed to get initialized ~/get_type_description service from rcl.");
}
rclcpp::AnyServiceCallback<ServiceT> cb;
cb.set(
[this](
@@ -124,18 +132,6 @@ public:
nullptr);
}
}
~NodeTypeDescriptionsImpl()
{
if (
type_description_srv_ &&
RCL_RET_OK != rcl_node_type_description_service_fini(node_base_->get_rcl_node_handle()))
{
RCLCPP_ERROR(
logger_,
"Error in shutdown of get_type_description service: %s", rcl_get_error_string().str);
}
}
};
NodeTypeDescriptions::NodeTypeDescriptions(

View File

@@ -67,7 +67,8 @@ Rate::sleep()
// Calculate the time to sleep
auto time_to_sleep = next_interval - now;
// Sleep (will get interrupted by ctrl-c, may not sleep full time)
return clock_->sleep_for(time_to_sleep);
clock_->sleep_for(time_to_sleep);
return true;
}
bool
@@ -102,12 +103,4 @@ WallRate::WallRate(const Duration & period)
: Rate(period, std::make_shared<Clock>(RCL_STEADY_TIME))
{}
ROSRate::ROSRate(const double rate)
: Rate(rate, std::make_shared<Clock>(RCL_ROS_TIME))
{}
ROSRate::ROSRate(const Duration & period)
: Rate(period, std::make_shared<Clock>(RCL_ROS_TIME))
{}
} // namespace rclcpp

View File

@@ -75,7 +75,7 @@ public:
bool
install(SignalHandlerOptions signal_handler_options = SignalHandlerOptions::All);
/// Uninstall the signal handler for SIGINT/SIGTERM and join the dedicated singal handling
/// Uninstall the signal handler for SIGINT/SIGTERM and join the dedicated signal handling
/// thread.
/**
* Also restores the previous signal handler.
@@ -189,7 +189,7 @@ private:
// Whether or not a signal has been received.
std::atomic_bool signal_received_ = false;
// A thread to which singal handling tasks are deferred.
// A thread to which signal handling tasks are deferred.
std::thread signal_handler_thread_;
// A mutex used to synchronize the install() and uninstall() methods.

View File

@@ -298,7 +298,20 @@ SubscriptionBase::setup_intra_process(
bool
SubscriptionBase::can_loan_messages() const
{
return rcl_subscription_can_loan_messages(subscription_handle_.get());
bool retval = rcl_subscription_can_loan_messages(subscription_handle_.get());
if (retval) {
// TODO(clalancette): The loaned message interface is currently not safe to use with
// shared_ptr callbacks. If a user takes a copy of the shared_ptr, it can get freed from
// underneath them via rcl_return_loaned_message_from_subscription(). The correct solution is
// to return the loaned message in a custom deleter, but that needs to be carefully handled
// with locking. Warn the user about this until we fix it.
RCLCPP_WARN_ONCE(
this->node_logger_,
"Loaned messages are only safe with const ref subscription callbacks. "
"If you are using any other kind of subscriptions, "
"set the ROS_DISABLE_LOANED_MESSAGES environment variable to 1 (the default).");
}
return retval;
}
rclcpp::Waitable::SharedPtr

View File

@@ -276,9 +276,9 @@ Time::operator-=(const rclcpp::Duration & rhs)
}
Time
Time::max()
Time::max(rcl_clock_type_t clock_type)
{
return Time(std::numeric_limits<int32_t>::max(), 999999999);
return Time(std::numeric_limits<int32_t>::max(), 999999999, clock_type);
}

View File

@@ -644,6 +644,7 @@ TYPED_TEST(TestExecutors, testRaceConditionAddNode)
break;
}
total += k * (i + 42);
(void)total;
}
});
}

View File

@@ -43,10 +43,9 @@ TEST_F(TestNodeTypeDescriptions, disabled_no_service)
node_options.append_parameter_override("start_type_description_service", false);
rclcpp::Node node{"node", "ns", node_options};
rcl_node_t * rcl_node = node.get_node_base_interface()->get_rcl_node_handle();
rcl_service_t * srv = nullptr;
rcl_ret_t ret = rcl_node_get_type_description_service(rcl_node, &srv);
ASSERT_EQ(RCL_RET_NOT_INIT, ret);
auto services = node.get_node_graph_interface()->get_service_names_and_types_by_node(
"node", "/ns");
EXPECT_TRUE(services.find("/ns/node/get_type_description") == services.end());
}
TEST_F(TestNodeTypeDescriptions, enabled_creates_service)
@@ -55,9 +54,8 @@ TEST_F(TestNodeTypeDescriptions, enabled_creates_service)
node_options.append_parameter_override("start_type_description_service", true);
rclcpp::Node node{"node", "ns", node_options};
rcl_node_t * rcl_node = node.get_node_base_interface()->get_rcl_node_handle();
rcl_service_t * srv = nullptr;
rcl_ret_t ret = rcl_node_get_type_description_service(rcl_node, &srv);
ASSERT_EQ(RCL_RET_OK, ret);
ASSERT_NE(nullptr, srv);
auto services = node.get_node_graph_interface()->get_service_names_and_types_by_node(
"node", "/ns");
EXPECT_TRUE(services.find("/ns/node/get_type_description") != services.end());
}

View File

@@ -289,7 +289,7 @@ public:
}
bool
use_take_shared_method() const
use_take_shared_method() const override
{
return take_shared_method;
}

View File

@@ -482,7 +482,7 @@ public:
void publish_loaned_message(rclcpp::LoanedMessage<MessageT, AllocatorT> && loaned_msg)
{
this->do_loaned_message_publish(std::move(loaned_msg.release()));
this->do_loaned_message_publish(loaned_msg.release());
}
void call_default_incompatible_qos_callback(rclcpp::QOSOfferedIncompatibleQoSInfo & event) const

View File

@@ -21,12 +21,24 @@
#include "../utils/rclcpp_gtest_macros.hpp"
/*
Basic tests for the Rate, WallRate and ROSRate classes.
*/
TEST(TestRate, rate_basics) {
rclcpp::init(0, nullptr);
class TestRate : public ::testing::Test
{
public:
void SetUp()
{
rclcpp::init(0, nullptr);
}
void TearDown()
{
rclcpp::shutdown();
}
};
/*
Basic tests for the Rate and WallRate classes.
*/
TEST_F(TestRate, rate_basics) {
auto period = std::chrono::milliseconds(1000);
auto offset = std::chrono::milliseconds(500);
auto epsilon = std::chrono::milliseconds(100);
@@ -79,13 +91,9 @@ TEST(TestRate, rate_basics) {
auto five = std::chrono::system_clock::now();
delta = five - four;
ASSERT_TRUE(epsilon > delta);
rclcpp::shutdown();
}
TEST(TestRate, wall_rate_basics) {
rclcpp::init(0, nullptr);
TEST_F(TestRate, wall_rate_basics) {
auto period = std::chrono::milliseconds(100);
auto offset = std::chrono::milliseconds(50);
auto epsilon = std::chrono::milliseconds(1);
@@ -140,77 +148,12 @@ TEST(TestRate, wall_rate_basics) {
auto five = std::chrono::steady_clock::now();
delta = five - four;
EXPECT_GT(epsilon, delta);
rclcpp::shutdown();
}
TEST(TestRate, ros_rate_basics) {
rclcpp::init(0, nullptr);
auto period = std::chrono::milliseconds(100);
auto offset = std::chrono::milliseconds(50);
auto epsilon = std::chrono::milliseconds(1);
double overrun_ratio = 1.5;
rclcpp::Clock clock(RCL_ROS_TIME);
auto start = clock.now();
rclcpp::ROSRate r(period);
EXPECT_EQ(rclcpp::Duration(period), r.period());
// suppress deprecated warnings
#if !defined(_WIN32)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else // !defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
ASSERT_FALSE(r.is_steady());
// suppress deprecated warnings
#if !defined(_WIN32)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else // !defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
ASSERT_EQ(RCL_ROS_TIME, r.get_type());
ASSERT_TRUE(r.sleep());
auto one = clock.now();
auto delta = one - start;
EXPECT_LT(rclcpp::Duration(period), delta);
EXPECT_GT(rclcpp::Duration(period * overrun_ratio), delta);
clock.sleep_for(offset);
ASSERT_TRUE(r.sleep());
auto two = clock.now();
delta = two - start;
EXPECT_LT(rclcpp::Duration(2 * period), delta + epsilon);
EXPECT_GT(rclcpp::Duration(2 * period * overrun_ratio), delta);
clock.sleep_for(offset);
auto two_offset = clock.now();
r.reset();
ASSERT_TRUE(r.sleep());
auto three = clock.now();
delta = three - two_offset;
EXPECT_LT(rclcpp::Duration(period), delta);
EXPECT_GT(rclcpp::Duration(period * overrun_ratio), delta);
clock.sleep_for(offset + period);
auto four = clock.now();
ASSERT_FALSE(r.sleep());
auto five = clock.now();
delta = five - four;
EXPECT_GT(rclcpp::Duration(epsilon), delta);
rclcpp::shutdown();
}
/*
Basic test for the deprecated GenericRate class.
*/
TEST(TestRate, generic_rate) {
TEST_F(TestRate, generic_rate) {
auto period = std::chrono::milliseconds(100);
auto offset = std::chrono::milliseconds(50);
auto epsilon = std::chrono::milliseconds(1);
@@ -325,13 +268,13 @@ TEST(TestRate, generic_rate) {
}
}
TEST(TestRate, from_double) {
TEST_F(TestRate, from_double) {
{
rclcpp::Rate rate(1.0);
EXPECT_EQ(rclcpp::Duration(std::chrono::seconds(1)), rate.period());
}
{
rclcpp::WallRate rate(2.0);
rclcpp::Rate rate(2.0);
EXPECT_EQ(rclcpp::Duration(std::chrono::milliseconds(500)), rate.period());
}
{
@@ -339,12 +282,12 @@ TEST(TestRate, from_double) {
EXPECT_EQ(rclcpp::Duration(std::chrono::seconds(2)), rate.period());
}
{
rclcpp::ROSRate rate(4.0);
rclcpp::WallRate rate(4.0);
EXPECT_EQ(rclcpp::Duration(std::chrono::milliseconds(250)), rate.period());
}
}
TEST(TestRate, clock_types) {
TEST_F(TestRate, clock_types) {
{
rclcpp::Rate rate(1.0, std::make_shared<rclcpp::Clock>(RCL_SYSTEM_TIME));
// suppress deprecated warnings
@@ -404,7 +347,7 @@ TEST(TestRate, clock_types) {
}
}
TEST(TestRate, incorrect_constuctor) {
TEST_F(TestRate, incorrect_constuctor) {
// Constructor with 0-frequency
RCLCPP_EXPECT_THROW_EQ(
rclcpp::Rate rate(0.0),

View File

@@ -363,10 +363,27 @@ TEST_F(TestTime, seconds) {
}
TEST_F(TestTime, test_max) {
const rclcpp::Time time_max = rclcpp::Time::max();
const rclcpp::Time max_time(std::numeric_limits<int32_t>::max(), 999999999);
EXPECT_DOUBLE_EQ(max_time.seconds(), time_max.seconds());
EXPECT_EQ(max_time.nanoseconds(), time_max.nanoseconds());
// Same clock types
for (rcl_clock_type_t type = RCL_ROS_TIME;
type != RCL_STEADY_TIME; type = static_cast<rcl_clock_type_t>(type + 1))
{
const rclcpp::Time time_max = rclcpp::Time::max(type);
const rclcpp::Time max_time(std::numeric_limits<int32_t>::max(), 999999999, type);
EXPECT_DOUBLE_EQ(max_time.seconds(), time_max.seconds());
EXPECT_EQ(max_time.nanoseconds(), time_max.nanoseconds());
}
// Different clock types
{
const rclcpp::Time time_max = rclcpp::Time::max(RCL_ROS_TIME);
const rclcpp::Time max_time(std::numeric_limits<int32_t>::max(), 999999999, RCL_STEADY_TIME);
EXPECT_ANY_THROW((void)(time_max == max_time));
EXPECT_ANY_THROW((void)(time_max != max_time));
EXPECT_ANY_THROW((void)(time_max <= max_time));
EXPECT_ANY_THROW((void)(time_max >= max_time));
EXPECT_ANY_THROW((void)(time_max < max_time));
EXPECT_ANY_THROW((void)(time_max > max_time));
EXPECT_ANY_THROW((void)(time_max - max_time));
}
}
TEST_F(TestTime, test_constructor_from_rcl_time_point) {

View File

@@ -14,7 +14,6 @@
#include <gtest/gtest.h>
#include <atomic>
#include <chrono>
#include <iostream>
#include <memory>
@@ -22,12 +21,12 @@
#include <set>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
#include "libstatistics_collector/moving_average_statistics/types.hpp"
#include "rclcpp/create_publisher.hpp"
#include "rclcpp/msg/message_with_header.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/qos.hpp"
#include "rclcpp/rclcpp.hpp"
@@ -36,10 +35,10 @@
#include "rclcpp/topic_statistics/subscription_topic_statistics.hpp"
#include "statistics_msgs/msg/metrics_message.hpp"
#include "statistics_msgs/msg/statistic_data_point.hpp"
#include "statistics_msgs/msg/statistic_data_type.hpp"
#include "test_msgs/msg/empty.hpp"
#include "test_msgs/msg/strings.hpp"
#include "test_topic_stats_utils.hpp"
@@ -67,7 +66,6 @@ constexpr const std::chrono::seconds kUnstableMessageAgeWindowDuration{
constexpr const std::chrono::seconds kUnstableMessageAgeOffset{std::chrono::seconds{1}};
} // namespace
using rclcpp::msg::MessageWithHeader;
using test_msgs::msg::Empty;
using rclcpp::topic_statistics::SubscriptionTopicStatistics;
using statistics_msgs::msg::MetricsMessage;
@@ -76,114 +74,73 @@ using statistics_msgs::msg::StatisticDataType;
using libstatistics_collector::moving_average_statistics::StatisticData;
/**
* Wrapper class to test and expose parts of the SubscriptionTopicStatistics<T> class.
* \tparam CallbackMessageT
* Wrapper class to test and expose parts of the SubscriptionTopicStatistics class.
*/
template<typename CallbackMessageT>
class TestSubscriptionTopicStatistics : public SubscriptionTopicStatistics<CallbackMessageT>
class TestSubscriptionTopicStatistics : public SubscriptionTopicStatistics
{
public:
TestSubscriptionTopicStatistics(
const std::string & node_name,
rclcpp::Publisher<statistics_msgs::msg::MetricsMessage>::SharedPtr publisher)
: SubscriptionTopicStatistics<CallbackMessageT>(node_name, publisher)
: SubscriptionTopicStatistics(node_name, std::move(publisher))
{
}
virtual ~TestSubscriptionTopicStatistics() = default;
~TestSubscriptionTopicStatistics() override = default;
/// Exposed for testing
std::vector<StatisticData> get_current_collector_data() const
{
return SubscriptionTopicStatistics<CallbackMessageT>::get_current_collector_data();
}
using SubscriptionTopicStatistics::get_current_collector_data;
};
/**
* Empty publisher node: used to publish empty messages
* PublisherNode wrapper: used to create publisher node
*/
class EmptyPublisher : public rclcpp::Node
template<typename MessageT>
class PublisherNode : public rclcpp::Node
{
public:
EmptyPublisher(
PublisherNode(
const std::string & name, const std::string & topic,
const std::chrono::milliseconds & publish_period = std::chrono::milliseconds{100})
: Node(name)
{
publisher_ = create_publisher<Empty>(topic, 10);
publisher_ = create_publisher<MessageT>(topic, 10);
publish_timer_ = this->create_wall_timer(
publish_period, [this]() {
this->publish_message();
});
}
virtual ~EmptyPublisher() = default;
~PublisherNode() override = default;
private:
void publish_message()
{
auto msg = Empty{};
auto msg = MessageT{};
publisher_->publish(msg);
}
rclcpp::Publisher<Empty>::SharedPtr publisher_;
typename rclcpp::Publisher<MessageT>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr publish_timer_;
};
/**
* MessageWithHeader publisher node: used to publish MessageWithHeader with `header` value set
*/
class MessageWithHeaderPublisher : public rclcpp::Node
{
public:
MessageWithHeaderPublisher(
const std::string & name, const std::string & topic,
const std::chrono::milliseconds & publish_period = std::chrono::milliseconds{100})
: Node(name)
{
publisher_ = create_publisher<MessageWithHeader>(topic, 10);
publish_timer_ = this->create_wall_timer(
publish_period, [this]() {
this->publish_message();
});
uniform_dist_ = std::uniform_int_distribution<uint32_t>{1000000, 100000000};
}
virtual ~MessageWithHeaderPublisher() = default;
private:
void publish_message()
{
std::random_device rd;
std::mt19937 gen{rd()};
uint32_t d = uniform_dist_(gen);
auto msg = MessageWithHeader{};
// Subtract ~1 second (add some noise for a non-zero standard deviation)
// so the received message age calculation is always > 0
msg.header.stamp = this->now() - rclcpp::Duration{1, d};
publisher_->publish(msg);
}
rclcpp::Publisher<MessageWithHeader>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr publish_timer_;
std::uniform_int_distribution<uint32_t> uniform_dist_;
};
/**
* TransitionMessageStamp publisher node : used to publish MessageWithHeader with `header` value set
* TransitionMessageStamp publisher emulator node : used to emulate publishing messages by
* directly calling rclcpp::Subscription::handle_message(msg_shared_ptr, message_info).
* The message age results change during the test.
*/
class TransitionMessageStampPublisher : public rclcpp::Node
template<typename MessageT>
class TransitionMessageStampPublisherEmulator : public rclcpp::Node
{
public:
TransitionMessageStampPublisher(
const std::string & name, const std::string & topic,
TransitionMessageStampPublisherEmulator(
const std::string & name,
const std::chrono::seconds transition_duration, const std::chrono::seconds message_age_offset,
typename rclcpp::Subscription<MessageT>::SharedPtr subscription,
const std::chrono::milliseconds & publish_period = std::chrono::milliseconds{100})
: Node(name), transition_duration_(transition_duration), message_age_offset_(message_age_offset)
: Node(name), transition_duration_(transition_duration), message_age_offset_(message_age_offset),
subscription_(std::move(subscription))
{
publisher_ = create_publisher<MessageWithHeader>(topic, 10);
publish_timer_ = this->create_wall_timer(publish_period, [this]() {this->publish_message();});
start_time_ = this->now();
}
@@ -191,84 +148,66 @@ public:
private:
void publish_message()
{
auto msg = MessageWithHeader{};
std::shared_ptr<void> msg_shared_ptr = std::make_shared<MessageT>();
rmw_message_info_t rmw_message_info = rmw_get_zero_initialized_message_info();
auto now = this->now();
auto elapsed_time = now - start_time_;
if (elapsed_time < transition_duration_) {
// Apply only to the topic statistics in the first half
// Subtract offset so message_age is always >= offset.
msg.header.stamp = now - message_age_offset_;
rmw_message_info.source_timestamp = (now - message_age_offset_).nanoseconds();
} else {
msg.header.stamp = now;
rmw_message_info.source_timestamp = now.nanoseconds();
}
publisher_->publish(msg);
rclcpp::MessageInfo message_info{rmw_message_info};
subscription_->handle_message(msg_shared_ptr, message_info);
}
std::chrono::seconds transition_duration_;
std::chrono::seconds message_age_offset_;
typename rclcpp::Subscription<MessageT>::SharedPtr subscription_;
rclcpp::Time start_time_;
rclcpp::Publisher<MessageWithHeader>::SharedPtr publisher_;
rclcpp::TimerBase::SharedPtr publish_timer_;
};
/**
* Empty subscriber node: used to create subscriber topic statistics requirements
* Message subscriber node: used to create subscriber with enabled topic statistics collectors
*
*/
class EmptySubscriber : public rclcpp::Node
template<typename MessageT>
class SubscriberWithTopicStatistics : public rclcpp::Node
{
public:
EmptySubscriber(const std::string & name, const std::string & topic)
SubscriberWithTopicStatistics(
const std::string & name, const std::string & topic,
std::chrono::milliseconds publish_period = defaultStatisticsPublishPeriod)
: Node(name)
{
// manually enable topic statistics via options
// Manually enable topic statistics via options
auto options = rclcpp::SubscriptionOptions();
options.topic_stats_options.state = rclcpp::TopicStatisticsState::Enable;
options.topic_stats_options.publish_period = publish_period;
auto callback = [](Empty::UniquePtr msg) {
auto callback = [](typename MessageT::UniquePtr msg) {
(void) msg;
};
subscription_ = create_subscription<Empty,
std::function<void(Empty::UniquePtr)>>(
subscription_ = create_subscription<MessageT,
std::function<void(typename MessageT::UniquePtr)>>(
topic,
rclcpp::QoS(rclcpp::KeepAll()),
callback,
options);
}
virtual ~EmptySubscriber() = default;
~SubscriberWithTopicStatistics() override = default;
private:
rclcpp::Subscription<Empty>::SharedPtr subscription_;
};
/**
* MessageWithHeader subscriber node: used to create subscriber topic statistics requirements
*/
class MessageWithHeaderSubscriber : public rclcpp::Node
{
public:
MessageWithHeaderSubscriber(const std::string & name, const std::string & topic)
: Node(name)
typename rclcpp::Subscription<MessageT>::SharedPtr get_subscription()
{
// manually enable topic statistics via options
auto options = rclcpp::SubscriptionOptions();
options.topic_stats_options.state = rclcpp::TopicStatisticsState::Enable;
options.topic_stats_options.publish_period = defaultStatisticsPublishPeriod;
auto callback = [](MessageWithHeader::UniquePtr msg) {
(void) msg;
};
subscription_ = create_subscription<MessageWithHeader,
std::function<void(MessageWithHeader::UniquePtr)>>(
topic,
rclcpp::QoS(rclcpp::KeepAll()),
callback,
options);
return subscription_;
}
virtual ~MessageWithHeaderSubscriber() = default;
private:
rclcpp::Subscription<MessageWithHeader>::SharedPtr subscription_;
typename rclcpp::Subscription<MessageT>::SharedPtr subscription_;
};
/**
@@ -277,43 +216,17 @@ private:
class TestSubscriptionTopicStatisticsFixture : public ::testing::Test
{
protected:
void SetUp()
void SetUp() override
{
rclcpp::init(0 /* argc */, nullptr /* argv */);
}
void TearDown()
void TearDown() override
{
rclcpp::shutdown();
}
};
/**
* Check if a received statistics message is empty (no data was observed)
* \param message_to_check
*/
void check_if_statistics_message_is_empty(const MetricsMessage & message_to_check)
{
for (const auto & stats_point : message_to_check.statistics) {
const auto type = stats_point.data_type;
switch (type) {
case StatisticDataType::STATISTICS_DATA_TYPE_SAMPLE_COUNT:
EXPECT_EQ(0, stats_point.data) << "unexpected sample count" << stats_point.data;
break;
case StatisticDataType::STATISTICS_DATA_TYPE_AVERAGE:
case StatisticDataType::STATISTICS_DATA_TYPE_MINIMUM:
case StatisticDataType::STATISTICS_DATA_TYPE_MAXIMUM:
case StatisticDataType::STATISTICS_DATA_TYPE_STDDEV:
EXPECT_TRUE(std::isnan(stats_point.data)) << "unexpected value" << stats_point.data <<
" for type:" << type;
break;
default:
FAIL() << "received unknown statistics type: " << std::dec <<
static_cast<unsigned int>(type);
}
}
}
/**
* Check if a received statistics message observed data and contains some calculation
* \param message_to_check
@@ -348,28 +261,13 @@ void check_if_statistic_message_is_populated(const MetricsMessage & message_to_c
/**
* Test an invalid argument is thrown for a bad input publish period.
*/
TEST(TestSubscriptionTopicStatistics, test_invalid_publish_period)
TEST_F(TestSubscriptionTopicStatisticsFixture, test_invalid_publish_period)
{
rclcpp::init(0 /* argc */, nullptr /* argv */);
auto node = std::make_shared<rclcpp::Node>("test_period_node");
auto options = rclcpp::SubscriptionOptions();
options.topic_stats_options.state = rclcpp::TopicStatisticsState::Enable;
options.topic_stats_options.publish_period = std::chrono::milliseconds(0);
auto callback = [](Empty::UniquePtr msg) {
(void) msg;
};
ASSERT_THROW(
(node->create_subscription<Empty, std::function<void(Empty::UniquePtr)>>(
"should_throw_invalid_arg",
rclcpp::QoS(rclcpp::KeepAll()),
callback,
options)), std::invalid_argument);
rclcpp::shutdown();
SubscriberWithTopicStatistics<Empty>(
"test_period_node", "should_throw_invalid_arg", std::chrono::milliseconds(0)
),
std::invalid_argument);
}
/**
@@ -378,7 +276,7 @@ TEST(TestSubscriptionTopicStatistics, test_invalid_publish_period)
*/
TEST_F(TestSubscriptionTopicStatisticsFixture, test_manual_construction)
{
auto empty_subscriber = std::make_shared<EmptySubscriber>(
auto empty_subscriber = std::make_shared<SubscriberWithTopicStatistics<Empty>>(
kTestSubNodeName,
kTestSubStatsEmptyTopic);
@@ -389,7 +287,7 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_manual_construction)
10);
// Construct a separate instance
auto sub_topic_stats = std::make_unique<TestSubscriptionTopicStatistics<Empty>>(
auto sub_topic_stats = std::make_unique<TestSubscriptionTopicStatistics>(
empty_subscriber->get_name(),
topic_stats_publisher);
@@ -410,7 +308,7 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_manual_construction)
TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_no_header)
{
// Create an empty publisher
auto empty_publisher = std::make_shared<EmptyPublisher>(
auto empty_publisher = std::make_shared<PublisherNode<Empty>>(
kTestPubNodeName,
kTestSubStatsEmptyTopic);
// empty_subscriber has a topic statistics instance as part of its subscription
@@ -422,7 +320,7 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_no
"/statistics",
kNumExpectedMessages);
auto empty_subscriber = std::make_shared<EmptySubscriber>(
auto empty_subscriber = std::make_shared<SubscriberWithTopicStatistics<Empty>>(
kTestSubNodeName,
kTestSubStatsEmptyTopic);
@@ -432,74 +330,7 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_no
ex.add_node(empty_subscriber);
// Spin and get future
ex.spin_until_future_complete(
statistics_listener->GetFuture(),
kTestTimeout);
// Compare message counts, sample count should be the same as published and received count
EXPECT_EQ(kNumExpectedMessages, statistics_listener->GetNumberOfMessagesReceived());
// Check the received message total count
const auto received_messages = statistics_listener->GetReceivedMessages();
EXPECT_EQ(kNumExpectedMessages, received_messages.size());
// check the type of statistics that were received and their counts
uint64_t message_age_count{0};
uint64_t message_period_count{0};
std::set<std::string> received_metrics;
for (const auto & msg : received_messages) {
if (msg.metrics_source == "message_age") {
message_age_count++;
}
if (msg.metrics_source == "message_period") {
message_period_count++;
}
}
EXPECT_EQ(kNumExpectedMessageAgeMessages, message_age_count);
EXPECT_EQ(kNumExpectedMessagePeriodMessages, message_period_count);
// Check the collected statistics for message period.
// Message age statistics will not be calculated because Empty messages
// don't have a `header` with timestamp. This means that we expect to receive a `message_age`
// and `message_period` message for each empty message published.
for (const auto & msg : received_messages) {
if (msg.metrics_source == kMessageAgeSourceLabel) {
check_if_statistics_message_is_empty(msg);
} else if (msg.metrics_source == kMessagePeriodSourceLabel) {
check_if_statistic_message_is_populated(msg);
}
}
}
TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_with_header)
{
// Create a MessageWithHeader publisher
auto msg_with_header_publisher = std::make_shared<MessageWithHeaderPublisher>(
kTestPubNodeName,
kTestSubStatsTopic);
// empty_subscriber has a topic statistics instance as part of its subscription
// this will listen to and generate statistics for the empty message
// Create a listener for topic statistics messages
auto statistics_listener = std::make_shared<rclcpp::topic_statistics::MetricsMessageSubscriber>(
"test_receive_stats_for_message_with_header",
"/statistics",
kNumExpectedMessages);
auto msg_with_header_subscriber = std::make_shared<MessageWithHeaderSubscriber>(
kTestSubNodeName,
kTestSubStatsTopic);
rclcpp::executors::SingleThreadedExecutor ex;
ex.add_node(msg_with_header_publisher);
ex.add_node(statistics_listener);
ex.add_node(msg_with_header_subscriber);
// Spin and get future
ex.spin_until_future_complete(
statistics_listener->GetFuture(),
kTestTimeout);
ex.spin_until_future_complete(statistics_listener->GetFuture(), kTestTimeout);
// Compare message counts, sample count should be the same as published and received count
EXPECT_EQ(kNumExpectedMessages, statistics_listener->GetNumberOfMessagesReceived());
@@ -524,6 +355,7 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_wi
EXPECT_EQ(kNumExpectedMessageAgeMessages, message_age_count);
EXPECT_EQ(kNumExpectedMessagePeriodMessages, message_period_count);
// Check the collected statistics for message period.
for (const auto & msg : received_messages) {
check_if_statistic_message_is_populated(msg);
}
@@ -531,23 +363,27 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_wi
TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_include_window_reset)
{
// Create a MessageWithHeader publisher
auto msg_with_header_publisher = std::make_shared<TransitionMessageStampPublisher>(
kTestPubNodeName, kTestSubStatsTopic, kUnstableMessageAgeWindowDuration,
kUnstableMessageAgeOffset);
// msg_with_header_subscriber has a topic statistics instance as part of its
// msg_subscriber_with_topic_statistics has a topic statistics instance as part of its
// subscription this will listen to and generate statistics
auto msg_with_header_subscriber =
std::make_shared<MessageWithHeaderSubscriber>(kTestSubNodeName, kTestSubStatsTopic);
auto msg_subscriber_with_topic_statistics =
std::make_shared<SubscriberWithTopicStatistics<test_msgs::msg::Strings>>(
kTestSubNodeName,
kTestSubStatsTopic);
// Create a message publisher
auto msg_publisher =
std::make_shared<TransitionMessageStampPublisherEmulator<test_msgs::msg::Strings>>(
kTestPubNodeName, kUnstableMessageAgeWindowDuration,
kUnstableMessageAgeOffset, msg_subscriber_with_topic_statistics->get_subscription());
// Create a listener for topic statistics messages
auto statistics_listener = std::make_shared<rclcpp::topic_statistics::MetricsMessageSubscriber>(
"test_receive_stats_include_window_reset", "/statistics", kNumExpectedMessages);
rclcpp::executors::SingleThreadedExecutor ex;
ex.add_node(msg_with_header_publisher);
ex.add_node(msg_publisher);
ex.add_node(statistics_listener);
ex.add_node(msg_with_header_subscriber);
ex.add_node(msg_subscriber_with_topic_statistics);
// Spin and get future
ex.spin_until_future_complete(statistics_listener->GetFuture(), kTestTimeout);

View File

@@ -3,6 +3,9 @@ Changelog for package rclcpp_action
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24.0.0 (2023-11-06)
-------------------
23.2.0 (2023-10-09)
-------------------

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>23.2.0</version>
<version>24.0.0</version>
<description>Adds action APIs for C++.</description>
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>

View File

@@ -2,6 +2,9 @@
Changelog for package rclcpp_components
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24.0.0 (2023-11-06)
-------------------
23.2.0 (2023-10-09)
-------------------

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>23.2.0</version>
<version>24.0.0</version>
<description>Package containing tools for dynamically loadable components</description>
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>

View File

@@ -3,6 +3,11 @@ Changelog for package rclcpp_lifecycle
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24.0.0 (2023-11-06)
-------------------
* Fix rclcpp_lifecycle inclusion on Windows. (`#2331 <https://github.com/ros2/rclcpp/issues/2331>`_)
* Contributors: Chris Lalancette
23.2.0 (2023-10-09)
-------------------
* add clients & services count (`#2072 <https://github.com/ros2/rclcpp/issues/2072>`_)

View File

@@ -21,6 +21,14 @@
#include "rclcpp_lifecycle/visibility_control.h"
#include "rclcpp/node_interfaces/detail/node_interfaces_helpers.hpp"
// When windows.h is included, ERROR is defined as a macro. So the use of it later in this file,
// even as an enum, causes compilation errors. Work around this by undefining the macro here,
// and then redefining when this header is finished being included.
#if defined(_WIN32)
#pragma push_macro("ERROR")
#undef ERROR
#endif
namespace rclcpp_lifecycle
{
namespace node_interfaces
@@ -108,6 +116,10 @@ public:
} // namespace node_interfaces
} // namespace rclcpp_lifecycle
#if defined(_WIN32)
#pragma pop_macro("ERROR")
#endif
RCLCPP_NODE_INTERFACE_HELPERS_SUPPORT(
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface, lifecycle_node)

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>23.2.0</version>
<version>24.0.0</version>
<description>Package containing a prototype for lifecycle implementation</description>
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>