Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea31f94eb4 | ||
|
|
f496291e81 | ||
|
|
dd6fad6d42 | ||
|
|
38734d769a | ||
|
|
e103b8d37e | ||
|
|
253d395d4e |
@@ -2,6 +2,13 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Fix the return type of Rate::period. (`#2301 <https://github.com/ros2/rclcpp/issues/2301>`_)
|
||||
* Update API docs links in package READMEs (`#2302 <https://github.com/ros2/rclcpp/issues/2302>`_)
|
||||
* Cleanup flaky timers_manager tests. (`#2299 <https://github.com/ros2/rclcpp/issues/2299>`_)
|
||||
* Contributors: Chris Lalancette, Christophe Bedard
|
||||
|
||||
22.2.0 (2023-09-07)
|
||||
-------------------
|
||||
* Topic correct typeadapter deduction (`#2294 <https://github.com/ros2/rclcpp/issues/2294>`_)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
The ROS client library in C++.
|
||||
|
||||
Visit the [rclcpp API documentation](http://docs.ros2.org/latest/api/rclcpp/) for a complete list of its main components and features.
|
||||
The link to the latest rclcpp API documentation, which includes a complete list of its main components and features, can be found on the rclcpp package info page, at the [ROS Index](https://index.ros.org/p/rclcpp/).
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
|
||||
@@ -527,7 +527,7 @@ private:
|
||||
void execute_ready_timers_unsafe();
|
||||
|
||||
// Callback to be called when timer is ready
|
||||
std::function<void(const rclcpp::TimerBase *)> on_ready_callback_ = nullptr;
|
||||
std::function<void(const rclcpp::TimerBase *)> on_ready_callback_;
|
||||
|
||||
// Thread used to run the timers execution task
|
||||
std::thread timers_thread_;
|
||||
|
||||
@@ -163,7 +163,7 @@ public:
|
||||
reset();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Duration
|
||||
std::chrono::nanoseconds
|
||||
period() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -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>22.2.0</version>
|
||||
<version>23.0.0</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -28,9 +28,9 @@ using rclcpp::experimental::TimersManager;
|
||||
TimersManager::TimersManager(
|
||||
std::shared_ptr<rclcpp::Context> context,
|
||||
std::function<void(const rclcpp::TimerBase *)> on_ready_callback)
|
||||
: on_ready_callback_(on_ready_callback),
|
||||
context_(context)
|
||||
{
|
||||
context_ = context;
|
||||
on_ready_callback_ = on_ready_callback;
|
||||
}
|
||||
|
||||
TimersManager::~TimersManager()
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "rclcpp/rate.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace rclcpp
|
||||
@@ -87,10 +88,10 @@ Rate::reset()
|
||||
last_interval_ = clock_->now();
|
||||
}
|
||||
|
||||
Duration
|
||||
std::chrono::nanoseconds
|
||||
Rate::period() const
|
||||
{
|
||||
return period_;
|
||||
return std::chrono::nanoseconds(period_.nanoseconds());
|
||||
}
|
||||
|
||||
WallRate::WallRate(const double rate)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
@@ -65,8 +66,10 @@ TEST_F(TestTimersManager, empty_manager)
|
||||
TEST_F(TestTimersManager, add_run_remove_timer)
|
||||
{
|
||||
size_t t_runs = 0;
|
||||
std::chrono::milliseconds timer_period(10);
|
||||
|
||||
auto t = TimerT::make_shared(
|
||||
10ms,
|
||||
timer_period,
|
||||
[&t_runs]() {
|
||||
t_runs++;
|
||||
},
|
||||
@@ -79,7 +82,7 @@ TEST_F(TestTimersManager, add_run_remove_timer)
|
||||
timers_manager->add_timer(t);
|
||||
|
||||
// Sleep for more 3 times the timer period
|
||||
std::this_thread::sleep_for(30ms);
|
||||
std::this_thread::sleep_for(3 * timer_period);
|
||||
|
||||
// The timer is executed only once, even if we slept 3 times the period
|
||||
execute_all_ready_timers(timers_manager);
|
||||
@@ -191,67 +194,6 @@ TEST_F(TestTimersManager, head_not_ready)
|
||||
EXPECT_EQ(0u, t_runs);
|
||||
}
|
||||
|
||||
TEST_F(TestTimersManager, timers_order)
|
||||
{
|
||||
auto timers_manager = std::make_shared<TimersManager>(
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
size_t t1_runs = 0;
|
||||
auto t1 = TimerT::make_shared(
|
||||
10ms,
|
||||
[&t1_runs]() {
|
||||
t1_runs++;
|
||||
},
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
size_t t2_runs = 0;
|
||||
auto t2 = TimerT::make_shared(
|
||||
30ms,
|
||||
[&t2_runs]() {
|
||||
t2_runs++;
|
||||
},
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
size_t t3_runs = 0;
|
||||
auto t3 = TimerT::make_shared(
|
||||
100ms,
|
||||
[&t3_runs]() {
|
||||
t3_runs++;
|
||||
},
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
// Add timers in a random order
|
||||
timers_manager->add_timer(t2);
|
||||
timers_manager->add_timer(t3);
|
||||
timers_manager->add_timer(t1);
|
||||
|
||||
std::this_thread::sleep_for(10ms);
|
||||
execute_all_ready_timers(timers_manager);
|
||||
EXPECT_EQ(1u, t1_runs);
|
||||
EXPECT_EQ(0u, t2_runs);
|
||||
EXPECT_EQ(0u, t3_runs);
|
||||
|
||||
std::this_thread::sleep_for(30ms);
|
||||
execute_all_ready_timers(timers_manager);
|
||||
EXPECT_EQ(2u, t1_runs);
|
||||
EXPECT_EQ(1u, t2_runs);
|
||||
EXPECT_EQ(0u, t3_runs);
|
||||
|
||||
std::this_thread::sleep_for(100ms);
|
||||
execute_all_ready_timers(timers_manager);
|
||||
EXPECT_EQ(3u, t1_runs);
|
||||
EXPECT_EQ(2u, t2_runs);
|
||||
EXPECT_EQ(1u, t3_runs);
|
||||
|
||||
timers_manager->remove_timer(t1);
|
||||
|
||||
std::this_thread::sleep_for(30ms);
|
||||
execute_all_ready_timers(timers_manager);
|
||||
EXPECT_EQ(3u, t1_runs);
|
||||
EXPECT_EQ(3u, t2_runs);
|
||||
EXPECT_EQ(1u, t3_runs);
|
||||
}
|
||||
|
||||
TEST_F(TestTimersManager, start_stop_timers_thread)
|
||||
{
|
||||
auto timers_manager = std::make_shared<TimersManager>(
|
||||
@@ -274,7 +216,7 @@ TEST_F(TestTimersManager, timers_thread)
|
||||
auto timers_manager = std::make_shared<TimersManager>(
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
size_t t1_runs = 0;
|
||||
int t1_runs = 0;
|
||||
auto t1 = TimerT::make_shared(
|
||||
1ms,
|
||||
[&t1_runs]() {
|
||||
@@ -282,7 +224,7 @@ TEST_F(TestTimersManager, timers_thread)
|
||||
},
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
size_t t2_runs = 0;
|
||||
int t2_runs = 0;
|
||||
auto t2 = TimerT::make_shared(
|
||||
1ms,
|
||||
[&t2_runs]() {
|
||||
@@ -296,12 +238,12 @@ TEST_F(TestTimersManager, timers_thread)
|
||||
|
||||
// Run timers thread for a while
|
||||
timers_manager->start();
|
||||
std::this_thread::sleep_for(5ms);
|
||||
std::this_thread::sleep_for(50ms);
|
||||
timers_manager->stop();
|
||||
|
||||
EXPECT_LT(1u, t1_runs);
|
||||
EXPECT_LT(1u, t2_runs);
|
||||
EXPECT_EQ(t1_runs, t2_runs);
|
||||
EXPECT_LE(std::abs(t1_runs - t2_runs), 1);
|
||||
}
|
||||
|
||||
TEST_F(TestTimersManager, destructor)
|
||||
@@ -365,13 +307,13 @@ TEST_F(TestTimersManager, add_remove_while_thread_running)
|
||||
timers_manager->start();
|
||||
|
||||
// After a while remove t1 and add t2
|
||||
std::this_thread::sleep_for(5ms);
|
||||
std::this_thread::sleep_for(50ms);
|
||||
timers_manager->remove_timer(t1);
|
||||
size_t tmp_t1 = t1_runs;
|
||||
timers_manager->add_timer(t2);
|
||||
|
||||
// Wait some more time and then stop
|
||||
std::this_thread::sleep_for(5ms);
|
||||
std::this_thread::sleep_for(50ms);
|
||||
timers_manager->stop();
|
||||
|
||||
// t1 has stopped running
|
||||
|
||||
@@ -3,6 +3,12 @@ Changelog for package rclcpp_action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Update API docs links in package READMEs (`#2302 <https://github.com/ros2/rclcpp/issues/2302>`_)
|
||||
* fix(ClientGoalHandle): Made mutex recursive to prevent deadlocks (`#2267 <https://github.com/ros2/rclcpp/issues/2267>`_)
|
||||
* Contributors: Christophe Bedard, jmachowinski
|
||||
|
||||
22.2.0 (2023-09-07)
|
||||
-------------------
|
||||
* Correct the position of a comment. (`#2290 <https://github.com/ros2/rclcpp/issues/2290>`_)
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
Adds action APIs for C++.
|
||||
|
||||
Visit the [rclcpp_action API documentation](http://docs.ros2.org/latest/api/rclcpp_action/) for a complete list of its main components and features. For more information about Actions in ROS 2, see the [design document](http://design.ros2.org/articles/actions.html).
|
||||
The link to the latest rclcpp_action API documentation, which includes a complete list of its main components and features, can be found on the rclcpp_action package info page, at the [ROS Index](https://index.ros.org/p/rclcpp_action/).
|
||||
For more information about Actions in ROS 2, see the [design document](http://design.ros2.org/articles/actions.html).
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ private:
|
||||
ResultCallback result_callback_{nullptr};
|
||||
int8_t status_{GoalStatus::STATUS_ACCEPTED};
|
||||
|
||||
std::mutex handle_mutex_;
|
||||
std::recursive_mutex handle_mutex_;
|
||||
};
|
||||
} // namespace rclcpp_action
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ template<typename ActionT>
|
||||
std::shared_future<typename ClientGoalHandle<ActionT>::WrappedResult>
|
||||
ClientGoalHandle<ActionT>::async_get_result()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
if (!is_result_aware_) {
|
||||
throw exceptions::UnawareGoalHandleError();
|
||||
}
|
||||
@@ -70,7 +70,7 @@ template<typename ActionT>
|
||||
void
|
||||
ClientGoalHandle<ActionT>::set_result(const WrappedResult & wrapped_result)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
status_ = static_cast<int8_t>(wrapped_result.code);
|
||||
result_promise_.set_value(wrapped_result);
|
||||
if (result_callback_) {
|
||||
@@ -82,7 +82,7 @@ template<typename ActionT>
|
||||
void
|
||||
ClientGoalHandle<ActionT>::set_feedback_callback(FeedbackCallback callback)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
feedback_callback_ = callback;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ template<typename ActionT>
|
||||
void
|
||||
ClientGoalHandle<ActionT>::set_result_callback(ResultCallback callback)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
result_callback_ = callback;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ template<typename ActionT>
|
||||
int8_t
|
||||
ClientGoalHandle<ActionT>::get_status()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
return status_;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ template<typename ActionT>
|
||||
void
|
||||
ClientGoalHandle<ActionT>::set_status(int8_t status)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
status_ = status;
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ template<typename ActionT>
|
||||
bool
|
||||
ClientGoalHandle<ActionT>::is_feedback_aware()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
return feedback_callback_ != nullptr;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ template<typename ActionT>
|
||||
bool
|
||||
ClientGoalHandle<ActionT>::is_result_aware()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
return is_result_aware_;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ template<typename ActionT>
|
||||
bool
|
||||
ClientGoalHandle<ActionT>::set_result_awareness(bool awareness)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
bool previous = is_result_aware_;
|
||||
is_result_aware_ = awareness;
|
||||
return previous;
|
||||
@@ -140,7 +140,7 @@ template<typename ActionT>
|
||||
void
|
||||
ClientGoalHandle<ActionT>::invalidate(const exceptions::UnawareGoalHandleError & ex)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
// Guard against multiple calls
|
||||
if (is_invalidated()) {
|
||||
return;
|
||||
@@ -168,7 +168,7 @@ ClientGoalHandle<ActionT>::call_feedback_callback(
|
||||
RCLCPP_ERROR(rclcpp::get_logger("rclcpp_action"), "Sent feedback to wrong goal handle.");
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
if (nullptr == feedback_callback_) {
|
||||
// Normal, some feedback messages may arrive after the goal result.
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp_action"), "Received feedback but goal ignores it.");
|
||||
|
||||
@@ -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>22.2.0</version>
|
||||
<version>23.0.0</version>
|
||||
<description>Adds action APIs for C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -852,6 +852,86 @@ TEST_F(TestClientAgainstServer, async_cancel_some_goals_with_callback)
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_CANCELED, goal_handle0->get_status());
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, deadlock_in_callbacks)
|
||||
{
|
||||
std::atomic<bool> feedback_callback_called = false;
|
||||
std::atomic<bool> response_callback_called = false;
|
||||
std::atomic<bool> result_callback_called = false;
|
||||
std::atomic<bool> no_deadlock = false;
|
||||
|
||||
std::thread tr = std::thread(
|
||||
[&]() {
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
|
||||
ActionGoal goal;
|
||||
|
||||
using GoalHandle = rclcpp_action::ClientGoalHandle<ActionType>;
|
||||
rclcpp_action::Client<ActionType>::SendGoalOptions ops;
|
||||
ops.feedback_callback =
|
||||
[&feedback_callback_called](const GoalHandle::SharedPtr handle,
|
||||
ActionType::Feedback::ConstSharedPtr) {
|
||||
// call functions on the handle that acquire the lock
|
||||
handle->get_status();
|
||||
handle->is_feedback_aware();
|
||||
handle->is_result_aware();
|
||||
|
||||
feedback_callback_called = true;
|
||||
};
|
||||
ops.goal_response_callback = [&response_callback_called](
|
||||
const GoalHandle::SharedPtr & handle) {
|
||||
// call functions on the handle that acquire the lock
|
||||
handle->get_status();
|
||||
handle->is_feedback_aware();
|
||||
handle->is_result_aware();
|
||||
|
||||
response_callback_called = true;
|
||||
};
|
||||
ops.result_callback = [&result_callback_called](
|
||||
const GoalHandle::WrappedResult &) {
|
||||
result_callback_called = true;
|
||||
};
|
||||
|
||||
goal.order = 6;
|
||||
auto future_goal_handle = action_client->async_send_goal(goal, ops);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
|
||||
ASSERT_TRUE(goal_handle);
|
||||
|
||||
ASSERT_EQ(RCL_RET_OK, rcl_set_ros_time_override(clock.get_clock_handle(), RCL_S_TO_NS(2)));
|
||||
|
||||
auto result_future = action_client->async_get_result(goal_handle);
|
||||
dual_spin_until_future_complete(result_future);
|
||||
|
||||
EXPECT_TRUE(result_future.valid());
|
||||
auto result = result_future.get();
|
||||
|
||||
no_deadlock = true;
|
||||
});
|
||||
|
||||
auto start_time = std::chrono::system_clock::now();
|
||||
|
||||
while (std::chrono::system_clock::now() - start_time < std::chrono::milliseconds(2000) &&
|
||||
!no_deadlock)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
|
||||
if (no_deadlock) {
|
||||
tr.join();
|
||||
} else {
|
||||
// In case of a failure, the thread is assumed to be in a deadlock.
|
||||
// We detach the thread so we don't block further tests.
|
||||
tr.detach();
|
||||
}
|
||||
|
||||
EXPECT_TRUE(no_deadlock);
|
||||
EXPECT_TRUE(response_callback_called);
|
||||
EXPECT_TRUE(result_callback_called);
|
||||
EXPECT_TRUE(feedback_callback_called);
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, send_rcl_errors)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
Changelog for package rclcpp_components
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Update API docs links in package READMEs (`#2302 <https://github.com/ros2/rclcpp/issues/2302>`_)
|
||||
* Contributors: Christophe Bedard
|
||||
|
||||
22.2.0 (2023-09-07)
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Package containing tools for dynamically loadable components.
|
||||
|
||||
Visit the [rclcpp_components API documentation](http://docs.ros2.org/latest/api/rclcpp_components/) for a complete list of its main components and features.
|
||||
The link to the latest rclcpp_components API documentation, which includes a complete list of its main components and features, can be found on the rclcpp_components package info page, at the [ROS Index](https://index.ros.org/p/rclcpp_components/).
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
|
||||
@@ -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>22.2.0</version>
|
||||
<version>23.0.0</version>
|
||||
<description>Package containing tools for dynamically loadable components</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -3,6 +3,11 @@ Changelog for package rclcpp_lifecycle
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Update API docs links in package READMEs (`#2302 <https://github.com/ros2/rclcpp/issues/2302>`_)
|
||||
* Contributors: Christophe Bedard
|
||||
|
||||
22.2.0 (2023-09-07)
|
||||
-------------------
|
||||
* add logger level service to lifecycle node. (`#2277 <https://github.com/ros2/rclcpp/issues/2277>`_)
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
Package containing a prototype for lifecycle implementation.
|
||||
|
||||
Visit the [rclcpp_lifecycle API documentation](http://docs.ros2.org/latest/api/rclcpp_lifecycle/) for a complete list of its main components and features. For more information about LifeCycle in ROS 2, see the [design document](http://design.ros2.org/articles/node_lifecycle.html).
|
||||
The link to the latest rclcpp_lifecycle API documentation, which includes a complete list of its main components and features, can be found on the rclcpp_lifecycle package info page, at the [ROS Index](https://index.ros.org/p/rclcpp_lifecycle/).
|
||||
For more information about LifeCycle in ROS 2, see the [design document](http://design.ros2.org/articles/node_lifecycle.html).
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
|
||||
@@ -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>22.2.0</version>
|
||||
<version>23.0.0</version>
|
||||
<description>Package containing a prototype for lifecycle implementation</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
Reference in New Issue
Block a user