Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5237763f7d | ||
|
|
6212355775 | ||
|
|
a0e2240ca3 | ||
|
|
c4e82ddabb | ||
|
|
f43d4edc6b | ||
|
|
53eed44771 | ||
|
|
b6cd8393db | ||
|
|
1b040e7df8 | ||
|
|
c751dfb76b | ||
|
|
493fe2b5d5 | ||
|
|
6084057f89 | ||
|
|
d3e6254ff1 | ||
|
|
19773973a8 | ||
|
|
99f1d8d124 | ||
|
|
1a353f09c0 |
@@ -2,6 +2,22 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
16.0.13 (2025-06-23)
|
||||
--------------------
|
||||
* Fix for memory leaks in rclcpp::SerializedMessage (`#2861 <https://github.com/ros2/rclcpp/issues/2861>`_) (`#2865 <https://github.com/ros2/rclcpp/issues/2865>`_)
|
||||
* Added missing chrono includes (backport `#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2857 <https://github.com/ros2/rclcpp/issues/2857>`_)
|
||||
* QoSInitialization::from_rmw does not validate invalid history policy … (backport `#2841 <https://github.com/ros2/rclcpp/issues/2841>`_) (`#2844 <https://github.com/ros2/rclcpp/issues/2844>`_)
|
||||
* throws std::invalid_argument if ParameterEvent is NULL. (`#2814 <https://github.com/ros2/rclcpp/issues/2814>`_) (`#2824 <https://github.com/ros2/rclcpp/issues/2824>`_)
|
||||
* remove redundant typesupport check in serialization module (`#2808 <https://github.com/ros2/rclcpp/issues/2808>`_) (`#2816 <https://github.com/ros2/rclcpp/issues/2816>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
16.0.12 (2025-03-25)
|
||||
--------------------
|
||||
* doc: Added warning to not instantiate Clock directly with RCL_ROS_TIME (`#2768 <https://github.com/ros2/rclcpp/issues/2768>`_) (`#2770 <https://github.com/ros2/rclcpp/issues/2770>`_)
|
||||
* apply actual QoS from rmw to the IPC publisher. (backport `#2707 <https://github.com/ros2/rclcpp/issues/2707>`_) (`#2711 <https://github.com/ros2/rclcpp/issues/2711>`_)
|
||||
* Adding in topic name to logging on IPC issues (`#2706 <https://github.com/ros2/rclcpp/issues/2706>`_) (`#2709 <https://github.com/ros2/rclcpp/issues/2709>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
16.0.11 (2024-11-25)
|
||||
--------------------
|
||||
* Fix subscription.is_serialized() for callbacks with message info (`#1950 <https://github.com/ros2/rclcpp/issues/1950>`_) (`#2622 <https://github.com/ros2/rclcpp/issues/2622>`_)
|
||||
|
||||
@@ -60,6 +60,13 @@ public:
|
||||
/**
|
||||
* Initializes the clock instance with the given clock_type.
|
||||
*
|
||||
* WARNING Don't instantiate a clock using RCL_ROS_TIME directly,
|
||||
* unless you really know what you are doing. By default no TimeSource
|
||||
* is attached to a new clock. This will lead to the unexpected behavior,
|
||||
* that your RCL_ROS_TIME will run always on system time. If you want
|
||||
* a RCL_ROS_TIME use Node::get_clock(), or make sure to attach a
|
||||
* TimeSource yourself.
|
||||
*
|
||||
* \param clock_type type of the clock.
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
*/
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
* \param[in] names A list of parameter names of interest.
|
||||
* \param[in] types A list of the types of parameter events of iterest.
|
||||
* EventType NEW, DELETED, or CHANGED
|
||||
* \throws std::invalid_argument if event is NULL.
|
||||
*
|
||||
* Example Usage:
|
||||
*
|
||||
|
||||
@@ -177,8 +177,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.
|
||||
@@ -186,19 +185,23 @@ 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::Volatile) {
|
||||
if (qos_profile.durability() != rclcpp::DurabilityPolicy::Volatile) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication allowed only with volatile durability");
|
||||
}
|
||||
// Register the publisher with the intra process manager.
|
||||
uint64_t intra_process_publisher_id = ipm->add_publisher(this->shared_from_this());
|
||||
this->setup_intra_process(
|
||||
intra_process_publisher_id,
|
||||
|
||||
@@ -186,11 +186,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");
|
||||
}
|
||||
if (qos_profile.durability() != rclcpp::DurabilityPolicy::Volatile) {
|
||||
throw std::invalid_argument(
|
||||
|
||||
@@ -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>16.0.11</version>
|
||||
<version>16.0.13</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||
|
||||
@@ -28,6 +28,9 @@ ParameterEventsFilter::ParameterEventsFilter(
|
||||
const std::vector<EventType> & types)
|
||||
: event_(event)
|
||||
{
|
||||
if (!event) {
|
||||
throw std::invalid_argument("event cannot be null");
|
||||
}
|
||||
if (std::find(types.begin(), types.end(), EventType::NEW) != types.end()) {
|
||||
for (auto & new_parameter : event->new_parameters) {
|
||||
if (std::find(names.begin(), names.end(), new_parameter.name) != names.end()) {
|
||||
|
||||
@@ -56,8 +56,10 @@ QoSInitialization::from_rmw(const rmw_qos_profile_t & rmw_qos)
|
||||
case RMW_QOS_POLICY_HISTORY_KEEP_LAST:
|
||||
case RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT:
|
||||
case RMW_QOS_POLICY_HISTORY_UNKNOWN:
|
||||
default:
|
||||
return KeepLast(rmw_qos.depth);
|
||||
default:
|
||||
throw std::invalid_argument(
|
||||
"Invalid history policy enum value passed to QoSInitialization::from_rmw");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ SerializationBase::SerializationBase(const rosidl_message_type_support_t * type_
|
||||
void SerializationBase::serialize_message(
|
||||
const void * ros_message, SerializedMessage * serialized_message) const
|
||||
{
|
||||
rcpputils::check_true(nullptr != type_support_, "Typesupport is nullpointer.");
|
||||
rcpputils::check_true(nullptr != ros_message, "ROS message is nullpointer.");
|
||||
rcpputils::check_true(nullptr != serialized_message, "Serialized message is nullpointer.");
|
||||
|
||||
@@ -52,7 +51,6 @@ void SerializationBase::serialize_message(
|
||||
void SerializationBase::deserialize_message(
|
||||
const SerializedMessage * serialized_message, void * ros_message) const
|
||||
{
|
||||
rcpputils::check_true(nullptr != type_support_, "Typesupport is nullpointer.");
|
||||
rcpputils::check_true(nullptr != serialized_message, "Serialized message is nullpointer.");
|
||||
rcpputils::check_true(
|
||||
0u != serialized_message->capacity(),
|
||||
|
||||
@@ -26,8 +26,13 @@ namespace rclcpp
|
||||
|
||||
inline void copy_rcl_message(const rcl_serialized_message_t & from, rcl_serialized_message_t & to)
|
||||
{
|
||||
const auto ret = rmw_serialized_message_init(
|
||||
&to, from.buffer_capacity, &from.allocator);
|
||||
auto ret = RCL_RET_ERROR;
|
||||
if (nullptr == to.buffer) {
|
||||
ret = rmw_serialized_message_init(&to, from.buffer_capacity, &from.allocator);
|
||||
} else {
|
||||
ret = rmw_serialized_message_resize(&to, from.buffer_capacity);
|
||||
}
|
||||
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
@@ -78,7 +83,6 @@ SerializedMessage::SerializedMessage(rcl_serialized_message_t && other)
|
||||
SerializedMessage & SerializedMessage::operator=(const SerializedMessage & other)
|
||||
{
|
||||
if (this != &other) {
|
||||
serialized_message_ = rmw_get_zero_initialized_serialized_message();
|
||||
copy_rcl_message(other.serialized_message_, serialized_message_);
|
||||
}
|
||||
|
||||
@@ -88,7 +92,6 @@ SerializedMessage & SerializedMessage::operator=(const SerializedMessage & other
|
||||
SerializedMessage & SerializedMessage::operator=(const rcl_serialized_message_t & other)
|
||||
{
|
||||
if (&serialized_message_ != &other) {
|
||||
serialized_message_ = rmw_get_zero_initialized_serialized_message();
|
||||
copy_rcl_message(other, serialized_message_);
|
||||
}
|
||||
|
||||
@@ -98,6 +101,14 @@ SerializedMessage & SerializedMessage::operator=(const rcl_serialized_message_t
|
||||
SerializedMessage & SerializedMessage::operator=(SerializedMessage && other)
|
||||
{
|
||||
if (this != &other) {
|
||||
if (nullptr != serialized_message_.buffer) {
|
||||
const auto fini_ret = rmw_serialized_message_fini(&serialized_message_);
|
||||
if (RCL_RET_OK != fini_ret) {
|
||||
RCLCPP_ERROR(
|
||||
get_logger("rclcpp"),
|
||||
"Failed to destroy serialized message: %s", rcl_get_error_string().str);
|
||||
}
|
||||
}
|
||||
serialized_message_ =
|
||||
std::exchange(other.serialized_message_, rmw_get_zero_initialized_serialized_message());
|
||||
}
|
||||
@@ -108,6 +119,14 @@ SerializedMessage & SerializedMessage::operator=(SerializedMessage && other)
|
||||
SerializedMessage & SerializedMessage::operator=(rcl_serialized_message_t && other)
|
||||
{
|
||||
if (&serialized_message_ != &other) {
|
||||
if (nullptr != serialized_message_.buffer) {
|
||||
const auto fini_ret = rmw_serialized_message_fini(&serialized_message_);
|
||||
if (RCL_RET_OK != fini_ret) {
|
||||
RCLCPP_ERROR(
|
||||
get_logger("rclcpp"),
|
||||
"Failed to destroy serialized message: %s", rcl_get_error_string().str);
|
||||
}
|
||||
}
|
||||
serialized_message_ =
|
||||
std::exchange(other, rmw_get_zero_initialized_serialized_message());
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@@ -93,3 +93,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());
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -72,6 +72,13 @@ protected:
|
||||
/*
|
||||
Testing filters.
|
||||
*/
|
||||
TEST_F(TestParameterEventFilter, invalide_arguments) {
|
||||
EXPECT_THROW(
|
||||
rclcpp::ParameterEventsFilter(nullptr, {"new"}, {nt}),
|
||||
std::invalid_argument
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(TestParameterEventFilter, full_by_type) {
|
||||
auto res = rclcpp::ParameterEventsFilter(
|
||||
full,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@@ -176,6 +176,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
|
||||
*/
|
||||
@@ -418,11 +433,10 @@ TEST_F(TestPublisher, intra_process_publish_failures) {
|
||||
publisher->publish(std::move(loaned_msg)),
|
||||
std::runtime_error("loaned message is not valid"));
|
||||
}
|
||||
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) {
|
||||
|
||||
@@ -250,3 +250,15 @@ TEST(TestQoS, qos_check_compatible)
|
||||
EXPECT_FALSE(ret.reason.empty());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestQoS, from_rmw_validity)
|
||||
{
|
||||
rmw_qos_profile_t invalid_qos;
|
||||
memset(&invalid_qos, 0, sizeof(invalid_qos));
|
||||
reinterpret_cast<uint32_t &>(invalid_qos.history) = 999;
|
||||
|
||||
EXPECT_THROW(
|
||||
{
|
||||
rclcpp::QoSInitialization::from_rmw(invalid_qos);
|
||||
}, std::invalid_argument);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -3,6 +3,16 @@ Changelog for package rclcpp_action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
16.0.13 (2025-06-23)
|
||||
--------------------
|
||||
* Replace std::default_random_engine with std::mt19937 (humble) (`#2847 <https://github.com/ros2/rclcpp/issues/2847>`_)
|
||||
* Added missing chrono includes (backport `#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2857 <https://github.com/ros2/rclcpp/issues/2857>`_)
|
||||
* Harden rclcpp_action::convert(). (backport `#2786 <https://github.com/ros2/rclcpp/issues/2786>`_) (`#2788 <https://github.com/ros2/rclcpp/issues/2788>`_)
|
||||
* Contributors: keeponoiro, mergify[bot]
|
||||
|
||||
16.0.12 (2025-03-25)
|
||||
--------------------
|
||||
|
||||
16.0.11 (2024-11-25)
|
||||
--------------------
|
||||
* fix: Fixed race condition in action server between is_ready and take. Backport from iron `#2531 <https://github.com/ros2/rclcpp/issues/2531>`_ (`#2635 <https://github.com/ros2/rclcpp/issues/2635>`_)
|
||||
|
||||
@@ -39,12 +39,22 @@ RCLCPP_ACTION_PUBLIC
|
||||
std::string
|
||||
to_string(const GoalUUID & goal_id);
|
||||
|
||||
// Convert C++ GoalID to rcl_action_goal_info_t
|
||||
/// Convert C++ GoalID to rcl_action_goal_info_t
|
||||
/**
|
||||
* \param[in] goal_id C++ GoalUUID reference to be converted.
|
||||
* \param[inout] info rcl_action_goal_info_t structure to be filled.
|
||||
* \throws std::runtime_error if info is null.
|
||||
*/
|
||||
RCLCPP_ACTION_PUBLIC
|
||||
void
|
||||
convert(const GoalUUID & goal_id, rcl_action_goal_info_t * info);
|
||||
|
||||
// Convert rcl_action_goal_info_t to C++ GoalID
|
||||
/// Convert rcl_action_goal_info_t to C++ GoalID
|
||||
/**
|
||||
* \param[in] info rcl_action_goal_info_t reference to be converted.
|
||||
* \param[inout] goal_id C++ GoalUUID structure to be filled.
|
||||
* \throws std::runtime_error if goal_id is null.
|
||||
*/
|
||||
RCLCPP_ACTION_PUBLIC
|
||||
void
|
||||
convert(const rcl_action_goal_info_t & info, GoalUUID * goal_id);
|
||||
|
||||
@@ -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>16.0.11</version>
|
||||
<version>16.0.13</version>
|
||||
<description>Adds action APIs for C++.</description>
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||
|
||||
@@ -183,7 +183,7 @@ public:
|
||||
std::mutex cancel_requests_mutex;
|
||||
|
||||
std::independent_bits_engine<
|
||||
std::default_random_engine, 8, unsigned int> random_bytes_generator;
|
||||
std::mt19937, 8, unsigned int> random_bytes_generator;
|
||||
};
|
||||
|
||||
ClientBase::ClientBase(
|
||||
|
||||
@@ -33,6 +33,9 @@ to_string(const GoalUUID & goal_id)
|
||||
void
|
||||
convert(const GoalUUID & goal_id, rcl_action_goal_info_t * info)
|
||||
{
|
||||
if (info == nullptr) {
|
||||
throw std::invalid_argument("info is nullptr");
|
||||
}
|
||||
for (size_t i = 0; i < 16; ++i) {
|
||||
info->goal_id.uuid[i] = goal_id[i];
|
||||
}
|
||||
@@ -41,6 +44,9 @@ convert(const GoalUUID & goal_id, rcl_action_goal_info_t * info)
|
||||
void
|
||||
convert(const rcl_action_goal_info_t & info, GoalUUID * goal_id)
|
||||
{
|
||||
if (goal_id == nullptr) {
|
||||
throw std::invalid_argument("goal_id is nullptr");
|
||||
}
|
||||
for (size_t i = 0; i < 16; ++i) {
|
||||
(*goal_id)[i] = info.goal_id.uuid[i];
|
||||
}
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ TEST(TestActionTypes, goal_uuid_to_rcl_action_goal_info) {
|
||||
for (uint8_t i = 0; i < UUID_SIZE; ++i) {
|
||||
goal_id[i] = i;
|
||||
}
|
||||
ASSERT_THROW(rclcpp_action::convert(goal_id, nullptr), std::invalid_argument);
|
||||
rcl_action_goal_info_t goal_info = rcl_action_get_zero_initialized_goal_info();
|
||||
rclcpp_action::convert(goal_id, &goal_info);
|
||||
for (uint8_t i = 0; i < UUID_SIZE; ++i) {
|
||||
@@ -53,6 +54,7 @@ TEST(TestActionTypes, rcl_action_goal_info_to_goal_uuid) {
|
||||
goal_info.goal_id.uuid[i] = i;
|
||||
}
|
||||
|
||||
ASSERT_THROW(rclcpp_action::convert(goal_info, nullptr), std::invalid_argument);
|
||||
rclcpp_action::GoalUUID goal_id;
|
||||
rclcpp_action::convert(goal_id, &goal_info);
|
||||
for (uint8_t i = 0; i < UUID_SIZE; ++i) {
|
||||
|
||||
@@ -2,6 +2,16 @@
|
||||
Changelog for package rclcpp_components
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
16.0.13 (2025-06-23)
|
||||
--------------------
|
||||
* Added missing chrono includes (backport `#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2857 <https://github.com/ros2/rclcpp/issues/2857>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
16.0.12 (2025-03-25)
|
||||
--------------------
|
||||
* Redundant .c_str() usage in rclcpp_components triggers ament_clang_tidy warning (`#2718 <https://github.com/ros2/rclcpp/issues/2718>`_)
|
||||
* Contributors: LihanChen2004
|
||||
|
||||
16.0.11 (2024-11-25)
|
||||
--------------------
|
||||
|
||||
|
||||
@@ -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>16.0.11</version>
|
||||
<version>16.0.13</version>
|
||||
<description>Package containing tools for dynamically loadable components</description>
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||
|
||||
@@ -40,8 +40,7 @@ int main(int argc, char * argv[])
|
||||
auto loader = new class_loader::ClassLoader(library_name);
|
||||
auto classes = loader->getAvailableClasses<rclcpp_components::NodeFactory>();
|
||||
for (const auto & clazz : classes) {
|
||||
std::string name = clazz.c_str();
|
||||
if (name.compare(class_name) == 0) {
|
||||
if (clazz.compare(class_name) == 0) {
|
||||
RCLCPP_DEBUG(logger, "Instantiate class %s", clazz.c_str());
|
||||
std::shared_ptr<rclcpp_components::NodeFactory> node_factory = nullptr;
|
||||
try {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -3,6 +3,15 @@ Changelog for package rclcpp_lifecycle
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
16.0.13 (2025-06-23)
|
||||
--------------------
|
||||
* Added missing chrono includes (backport `#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2857 <https://github.com/ros2/rclcpp/issues/2857>`_)
|
||||
* should pull valid transition before trying to change the state. (backport `#2774 <https://github.com/ros2/rclcpp/issues/2774>`_) (`#2785 <https://github.com/ros2/rclcpp/issues/2785>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
16.0.12 (2025-03-25)
|
||||
--------------------
|
||||
|
||||
16.0.11 (2024-11-25)
|
||||
--------------------
|
||||
|
||||
|
||||
@@ -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>16.0.11</version>
|
||||
<version>16.0.13</version>
|
||||
<description>Package containing a prototype for lifecycle implementation</description>
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||
|
||||
@@ -535,15 +535,22 @@ public:
|
||||
trigger_transition(uint8_t transition_id)
|
||||
{
|
||||
LifecycleNodeInterface::CallbackReturn error;
|
||||
change_state(transition_id, error);
|
||||
(void) error;
|
||||
return get_current_state();
|
||||
return trigger_transition(transition_id, error);
|
||||
}
|
||||
|
||||
const State &
|
||||
trigger_transition(uint8_t transition_id, LifecycleNodeInterface::CallbackReturn & cb_return_code)
|
||||
{
|
||||
change_state(transition_id, cb_return_code);
|
||||
const rcl_lifecycle_transition_t * transition;
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(state_machine_mutex_);
|
||||
|
||||
transition =
|
||||
rcl_lifecycle_get_transition_by_id(state_machine_.current_state, transition_id);
|
||||
}
|
||||
if (transition) {
|
||||
change_state(static_cast<uint8_t>(transition->id), cb_return_code);
|
||||
}
|
||||
return get_current_state();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
@@ -264,11 +265,146 @@ TEST_F(TestDefaultStateMachine, trigger_transition) {
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_UNCONFIGURED, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)).id());
|
||||
// supposed to fail because primary state is NOT active
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_UNCONFIGURED, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVE_SHUTDOWN)).id());
|
||||
// supposed to fail because primary state is NOT inactive
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_UNCONFIGURED, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_INACTIVE_SHUTDOWN)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_FINALIZED, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN)).id());
|
||||
}
|
||||
|
||||
TEST_F(TestDefaultStateMachine, trigger_transition_shutdown_id) {
|
||||
// test Transition::TRANSITION_ACTIVE_SHUTDOWN
|
||||
{
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
|
||||
EXPECT_EQ(State::PRIMARY_STATE_UNCONFIGURED, test_node->get_current_state().id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_INACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_ACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_FINALIZED, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVE_SHUTDOWN)).id());
|
||||
}
|
||||
|
||||
// test Transition::TRANSITION_INACTIVE_SHUTDOWN
|
||||
{
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
|
||||
EXPECT_EQ(State::PRIMARY_STATE_UNCONFIGURED, test_node->get_current_state().id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_INACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_ACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_INACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id());
|
||||
// supposed to fail because primary state is NOT active
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_INACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVE_SHUTDOWN)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_FINALIZED, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_INACTIVE_SHUTDOWN)).id());
|
||||
}
|
||||
|
||||
// test Transition::TRANSITION_UNCONFIGURED_SHUTDOWN
|
||||
{
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
|
||||
EXPECT_EQ(State::PRIMARY_STATE_UNCONFIGURED, test_node->get_current_state().id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_INACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_ACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_INACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_UNCONFIGURED, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)).id());
|
||||
// supposed to fail because primary state is NOT active
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_UNCONFIGURED, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVE_SHUTDOWN)).id());
|
||||
// supposed to fail because primary state is NOT inactive
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_UNCONFIGURED, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_INACTIVE_SHUTDOWN)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_FINALIZED, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN)).id());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestDefaultStateMachine, trigger_transition_shutdown_label) {
|
||||
// test Transition::TRANSITION_ACTIVE_SHUTDOWN
|
||||
{
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
|
||||
EXPECT_EQ(State::PRIMARY_STATE_UNCONFIGURED, test_node->get_current_state().id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_INACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_ACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_FINALIZED, test_node->shutdown().id());
|
||||
}
|
||||
|
||||
// test Transition::TRANSITION_INACTIVE_SHUTDOWN
|
||||
{
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
|
||||
EXPECT_EQ(State::PRIMARY_STATE_UNCONFIGURED, test_node->get_current_state().id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_INACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_ACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_INACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_FINALIZED, test_node->shutdown().id());
|
||||
}
|
||||
|
||||
// test Transition::TRANSITION_UNCONFIGURED_SHUTDOWN
|
||||
{
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
|
||||
EXPECT_EQ(State::PRIMARY_STATE_UNCONFIGURED, test_node->get_current_state().id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_INACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_CONFIGURE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_ACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_ACTIVATE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_INACTIVE, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_DEACTIVATE)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_UNCONFIGURED, test_node->trigger_transition(
|
||||
rclcpp_lifecycle::Transition(Transition::TRANSITION_CLEANUP)).id());
|
||||
ASSERT_EQ(
|
||||
State::PRIMARY_STATE_FINALIZED, test_node->shutdown().id());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestDefaultStateMachine, trigger_transition_rcl_errors) {
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user