Compare commits

...

22 Commits

Author SHA1 Message Date
Steven! Ragnarök
342f225053 0.7.14 2020-07-11 00:04:56 -04:00
Alejandro Hernández Cordero
3c198de5b2 [Backport Dashing]Fixed doxygen warnings (#1163) (#1208)
Signed-off-by: ahcorde <ahcorde@gmail.com>
2020-07-10 16:54:25 -04:00
Ivan Santiago Paunovic
8906c9eb7f Check if context is valid when looping in spin_some (#1167)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2020-07-02 18:26:00 -03:00
DongheeYe
9e98aa70d3 Fix spin_until_future_complete: check spinning value (#1023)
Signed-off-by: Donghee Ye <donghee.ye@samsung.com>
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2020-07-02 18:26:00 -03:00
Alejandro Hernández Cordero
6471043a0b Added rclcpp_components Doxyfile (#1091) (#1201)
* Added rclcpp components Doxyfile

Signed-off-by: ahcorde <ahcorde@gmail.com>

* Added feedback

Signed-off-by: ahcorde <ahcorde@gmail.com>
2020-06-26 19:20:32 +02:00
tomoya
f8bba370dc [dashing] backport #1182 (#1195)
Signed-off-by: Tomoya.Fujita <Tomoya.Fujita@sony.com>
2020-06-25 13:04:38 -04:00
tomoya
d5040ae304 Fix lock-order-inversion (potential deadlock) (#1135) (#1138)
Signed-off-by: Tomoya.Fujita <Tomoya.Fujita@sony.com>
2020-06-01 11:20:33 -03:00
Steven! Ragnarök
3e5b6a47ea 0.7.13 2020-03-12 17:37:15 -04:00
Jacob Perron
8c3fbce10d Don't specify calling convention in std::_Binder template (#952) (#1015)
Fix for a build error on 32-bit Windows. Member functions use the
__thiscall convention by default which is incompatible with __cdecl.

Signed-off-by: Sean Kelly <sean@seankelly.dev>
2020-03-12 14:23:08 -07:00
Jacob Perron
fb6ab9ef70 Remove absolute path from installed CMake code (#948) (#949)
Otherwise, rclcpp_components_register_node() fails if used from a fat archive.

Related to https://github.com/ros2/ros2/issues/606.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2020-01-08 10:19:12 -08:00
Shane Loretz
7629f5b6d9 0.7.12
Signed-off-by: Shane Loretz <sloretz@openrobotics.org>
2019-12-05 14:16:28 -05:00
Ivan Santiago Paunovic
7cb2ececcb issue-919 Fixed "memory leak" in action clients (#920) (#934)
Whenever a call is made to `rclcpp_action::Client::wait_for_action_server`
a weak pointer to an Event object gets added to the graph_event_ vector
of the NodeGraph interface. This vector will be cleared on a node graph
change event, but if no such event occurs the weak pointer will be stuck
in the vector.  Furthermore, if client code issues repeated calls to
`wait_for_action_server` the vector will keep growing.

The fix moves the Event object creation right after the early return from
`wait_for_action_server` so that the Event object is not created in the
case that the server is known to be present and therefore there is no
need to wait for a node graph change event to occur.

Signed-off-by: Adrian Stere <astere@clearpath.ai>
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2019-12-05 14:09:07 -05:00
Shane Loretz
0f4fc08a93 [Dashing] backport rclcpp_components_register_node (#935)
* Cmake infrastructure for creating components (#784)

*cmake macro to create components for libraries with multiple nodes

Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>
Signed-off-by: Shane Loretz <sloretz@openrobotics.org>

* fix for multiple nodes not being recognized (#790)

Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>
Signed-off-by: Shane Loretz <sloretz@openrobotics.org>

* fix linter issue (#795)

Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>
Signed-off-by: Shane Loretz <sloretz@openrobotics.org>
2019-12-05 12:48:13 -05:00
Jacob Perron
82f6dfa6de [rclcpp_action] Do not throw exception in action client if take fails (#888) (#891)
As documented in rcl_action, a return code of RCL_RET_ACTION_CLIENT_TAKE_FAILED does not mean that
an error occurred.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-11-18 14:44:06 -08:00
Ivan Santiago Paunovic
fadd923aa0 0.7.11 2019-10-11 11:08:51 -03:00
ivanpauno
f954ce5145 Fix get_node_interfaces functions taking a pointer (#821) (#870)
Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-09-26 14:18:39 -03:00
ivanpauno
895145cfc9 Fix hang with timers in MultiThreadedExecutor (#835) (#836) (#869)
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
2019-09-25 15:52:22 -03:00
Tully Foote
3cdb3cb1bf 0.7.10 2019-09-23 12:41:47 -07:00
Tully Foote
5d5d3ce09d update changelog 2019-09-23 12:40:48 -07:00
Zachary Michaels
839ad201ac reset error message before setting a new one, embed the original one (#854) (#866)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
Signed-off-by: Zachary Michaels <zmichaels11@gmail.com>
2019-09-23 12:38:26 -07:00
Michael Carroll
f3b0aa170c 0.7.9
Signed-off-by: Michael Carroll <michael@openrobotics.org>
2019-09-20 16:14:01 -05:00
Zachary Michaels
6e76503d9a add mutex in add/remove_node and wait_for_work to protect concurrent use/change of memory_strategy_ (#837) (#857)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
Signed-off-by: Zachary Michaels <zmichaels11@gmail.com>
2019-09-20 14:08:34 -07:00
37 changed files with 498 additions and 103 deletions

View File

@@ -2,6 +2,37 @@
Changelog for package rclcpp
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.7.14 (2020-07-10)
-------------------
* Fixed doxygen warnings. (`#1208 <https://github.com/ros2/rclcpp/issues/1208>`_)
* Check if context is valid when looping in spin_some. (`#1167 <https://github.com/ros2/rclcpp/issues/1167>`_)
* Fix spin_until_future_complete: check spinning value. (`#1023 <https://github.com/ros2/rclcpp/issues/1023>`_)
* Fix exception on rcl_clock_init. (`#1195 <https://github.com/ros2/rclcpp/issues/1195>`_)
* Fix lock-order-inversion (potential deadlock). (`#1138 <https://github.com/ros2/rclcpp/issues/1138>`_)
* Contributors: Alejandro Hernández Cordero, DongheeYe, Ivan Santiago Paunovic, tomoya
0.7.13 (2020-03-12)
-------------------
* Don't specify calling convention in std::_Binder template. (`#1015 <https://github.com/ros2/rclcpp/issues/1015>`_)
* Contributors: Jacob Perron, Sean Kelly
0.7.12 (2019-12-05)
-------------------
0.7.11 (2019-10-11)
-------------------
* Fix `get_node_*_interface` functions taking a pointer (`#870 <https://github.com/ros2/rclcpp/pull/870>`_).
* Fix hang with timers in `MultiThreadedExecutor` (`#869 <https://github.com/ros2/rclcpp/pull/869>`_).
* Contributors: Todd Malsbary, ivanpauno
0.7.10 (2019-09-23)
-------------------
0.7.9 (2019-09-20)
------------------
* add mutex in add/remove_node and wait_for_work to protect concurrent use/change of memory_strategy\_ (`#837 <https://github.com/ros2/rclcpp/issues/837>`_) (`#857 <https://github.com/ros2/rclcpp/issues/857>`_)
* Contributors: Zachary Michaels
0.7.8 (2019-09-06)
------------------

View File

@@ -105,9 +105,9 @@ public:
*
* Function is only applicable if the clock_type is `RCL_ROS_TIME`
*
* \param pre_callback. Must be non-throwing
* \param post_callback. Must be non-throwing.
* \param threshold. Callbacks will be triggered if the time jump is greater
* \param pre_callback Must be non-throwing
* \param post_callback Must be non-throwing.
* \param threshold Callbacks will be triggered if the time jump is greater
* then the threshold.
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
* \throws std::bad_alloc if the allocation of the JumpHandler fails.

View File

@@ -22,6 +22,7 @@
#include <iostream>
#include <list>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
@@ -34,6 +35,7 @@
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/utilities.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/scope_exit.hpp"
namespace rclcpp
{
@@ -242,9 +244,14 @@ public:
}
std::chrono::nanoseconds timeout_left = timeout_ns;
while (rclcpp::ok(this->context_)) {
if (spinning.exchange(true)) {
throw std::runtime_error("spin_until_future_complete() called while already spinning");
}
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
while (rclcpp::ok(this->context_) && spinning.load()) {
// Do one item of work.
spin_once(timeout_left);
spin_once_impl(timeout_left);
// Check if the future is set, return SUCCESS if it is.
status = future.wait_for(std::chrono::seconds(0));
if (status == std::future_status::ready) {
@@ -355,6 +362,9 @@ protected:
/// Wait set for managing entities that the rmw layer waits on.
rcl_wait_set_t wait_set_ = rcl_get_zero_initialized_wait_set();
// Mutex to protect the subsequent memory_strategy_.
std::mutex memory_strategy_mutex_;
/// The memory strategy: an interface for handling user-defined memory allocation strategies.
memory_strategy::MemoryStrategy::SharedPtr memory_strategy_;
@@ -364,6 +374,10 @@ protected:
private:
RCLCPP_DISABLE_COPY(Executor)
RCLCPP_PUBLIC
void
spin_once_impl(std::chrono::nanoseconds timeout);
std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
std::list<const rcl_guard_condition_t *> guard_conditions_;
};

View File

@@ -48,6 +48,7 @@ public:
* \param number_of_threads number of threads to have in the thread pool,
* the default 0 will use the number of cpu cores found instead
* \param yield_before_execute if true std::this_thread::yield() is called
* \param timeout maximum time to wait
*/
RCLCPP_PUBLIC
MultiThreadedExecutor(

View File

@@ -88,8 +88,7 @@ struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(FArgs ...))(Args ...)>>
struct function_traits<std::_Bind<std::_Mem_fn<ReturnTypeT (ClassT::*)(Args ...)>(FArgs ...)>>
#elif defined _MSC_VER // MS Visual Studio
struct function_traits<
std::_Binder<std::_Unforced, ReturnTypeT(__cdecl ClassT::*)(Args ...), FArgs ...>
>
std::_Binder<std::_Unforced, ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
#else
#error "Unsupported C++ compiler / standard library"
#endif
@@ -106,8 +105,7 @@ struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(FArgs ...))(Args ...) co
struct function_traits<std::_Bind<std::_Mem_fn<ReturnTypeT (ClassT::*)(Args ...) const>(FArgs ...)>>
#elif defined _MSC_VER // MS Visual Studio
struct function_traits<
std::_Binder<std::_Unforced, ReturnTypeT(__cdecl ClassT::*)(Args ...) const, FArgs ...>
>
std::_Binder<std::_Unforced, ReturnTypeT (ClassT::*)(Args ...) const, FArgs ...>>
#else
#error "Unsupported C++ compiler / standard library"
#endif
@@ -121,7 +119,7 @@ struct function_traits<std::__bind<ReturnTypeT( &)(Args ...), FArgs ...>>
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
struct function_traits<std::_Bind<ReturnTypeT(*(FArgs ...))(Args ...)>>
#elif defined _MSC_VER // MS Visual Studio
struct function_traits<std::_Binder<std::_Unforced, ReturnTypeT(__cdecl &)(Args ...), FArgs ...>>
struct function_traits<std::_Binder<std::_Unforced, ReturnTypeT( &)(Args ...), FArgs ...>>
#else
#error "Unsupported C++ compiler / standard library"
#endif

View File

@@ -337,7 +337,13 @@ public:
CallbackT callback,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
/* Create and return a Client. */
/// Create and return a Client.
/**
* \param[in] service_name The topic to service on.
* \param[in] qos_profile rmw_qos_profile_t Quality of service profile for client.
* \param[in] group Callback group to call the service.
* \return Shared pointer to the created client.
*/
template<typename ServiceT>
typename rclcpp::Client<ServiceT>::SharedPtr
create_client(
@@ -345,7 +351,14 @@ public:
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
/* Create and return a Service. */
/// Create and return a Service.
/**
* \param[in] service_name The topic to service on.
* \param[in] callback User-defined callback function.
* \param[in] qos_profile rmw_qos_profile_t Quality of service profile for client.
* \param[in] group Callback group to call the service.
* \return Shared pointer to the created service.
*/
template<typename ServiceT, typename CallbackT>
typename rclcpp::Service<ServiceT>::SharedPtr
create_service(

View File

@@ -123,16 +123,18 @@ template<
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface(NodeType && node_pointer)
get_node_base_interface(NodeType node_pointer)
{
// Forward pointers to detail implmentation directly.
return detail::get_node_base_interface_from_pointer(std::forward<NodeType>(node_pointer));
return detail::get_node_base_interface_from_pointer(node_pointer);
}
/// Get the NodeBaseInterface as a pointer from a "Node like" object.
template<
typename NodeType,
typename std::enable_if<!std::is_pointer<NodeType>::value, int>::type = 0
typename std::enable_if<
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface(NodeType && node_reference)

View File

@@ -123,16 +123,18 @@ template<
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface(NodeType && node_pointer)
get_node_timers_interface(NodeType node_pointer)
{
// Forward pointers to detail implmentation directly.
return detail::get_node_timers_interface_from_pointer(std::forward<NodeType>(node_pointer));
return detail::get_node_timers_interface_from_pointer(node_pointer);
}
/// Get the NodeTimersInterface as a pointer from a "Node like" object.
template<
typename NodeType,
typename std::enable_if<!std::is_pointer<NodeType>::value, int>::type = 0
typename std::enable_if<
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface(NodeType && node_reference)

View File

@@ -123,16 +123,18 @@ template<
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTopicsInterface *
get_node_topics_interface(NodeType && node_pointer)
get_node_topics_interface(NodeType node_pointer)
{
// Forward pointers to detail implmentation directly.
return detail::get_node_topics_interface_from_pointer(std::forward<NodeType>(node_pointer));
return detail::get_node_topics_interface_from_pointer(node_pointer);
}
/// Get the NodeTopicsInterface as a pointer from a "Node like" object.
template<
typename NodeType,
typename std::enable_if<!std::is_pointer<NodeType>::value, int>::type = 0
typename std::enable_if<
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
>::type = 0
>
rclcpp::node_interfaces::NodeTopicsInterface *
get_node_topics_interface(NodeType && node_reference)

View File

@@ -46,6 +46,15 @@ class AsyncParametersClient
public:
RCLCPP_SMART_PTR_DEFINITIONS(AsyncParametersClient)
/// Create an async parameters client.
/**
* \param[in] node_base_interface The node base interface of the corresponding node.
* \param[in] node_topics_interface Node topic base interface.
* \param[in] node_graph_interface The node graph interface of the corresponding node.
* \param[in] node_services_interface Node service interface.
* \param[in] remote_node_name (optional) name of the remote node
* \param[in] qos_profile (optional) The rmw qos profile to use to subscribe
*/
RCLCPP_PUBLIC
AsyncParametersClient(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
@@ -55,12 +64,24 @@ public:
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
/// Constructor
/**
* \param[in] node The async paramters client will be added to this node.
* \param[in] remote_node_name (optional) name of the remote node
* \param[in] qos_profile (optional) The rmw qos profile to use to subscribe
*/
RCLCPP_PUBLIC
AsyncParametersClient(
const rclcpp::Node::SharedPtr node,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
/// Constructor
/**
* \param[in] node The async paramters client will be added to this node.
* \param[in] remote_node_name (optional) name of the remote node
* \param[in] qos_profile (optional) The rmw qos profile to use to subscribe
*/
RCLCPP_PUBLIC
AsyncParametersClient(
rclcpp::Node * node,

View File

@@ -156,6 +156,16 @@ public:
}
}
/// Default constructor.
/**
* The constructor for a Service is almost never called directly.
* Instead, services should be instantiated through the function
* rclcpp::create_service().
*
* \param[in] node_handle NodeBaseInterface pointer that is used in part of the setup.
* \param[in] service_handle service handle.
* \param[in] any_callback User defined callback to call when a client request is received.
*/
Service(
std::shared_ptr<rcl_node_t> node_handle,
std::shared_ptr<rcl_service_t> service_handle,
@@ -174,6 +184,16 @@ public:
service_handle_ = service_handle;
}
/// Default constructor.
/**
* The constructor for a Service is almost never called directly.
* Instead, services should be instantiated through the function
* rclcpp::create_service().
*
* \param[in] node_handle NodeBaseInterface pointer that is used in part of the setup.
* \param[in] service_handle service handle.
* \param[in] any_callback User defined callback to call when a client request is received.
*/
Service(
std::shared_ptr<rcl_node_t> node_handle,
rcl_service_t * service_handle,

View File

@@ -65,7 +65,12 @@ struct SubscriptionFactory
SetupIntraProcessFunction setup_intra_process;
};
/// Return a SubscriptionFactory with functions for creating a SubscriptionT<MessageT, Alloc>.
/// Return a SubscriptionFactory setup to create a SubscriptionT<MessageT, AllocatorT>.
/**
* \param[in] callback The user-defined callback function to receive a message
* \param[in] options Additional options for the creation of the Subscription.
* \param[in] msg_mem_strat The message memory strategy to use for allocating messages.
*/
template<
typename MessageT,
typename CallbackT,

View File

@@ -34,17 +34,32 @@ public:
RCLCPP_PUBLIC
Time(int32_t seconds, uint32_t nanoseconds, rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
/// Time constructor
/**
* \param nanoseconds since time epoch
* \param clock clock type
*/
RCLCPP_PUBLIC
explicit Time(int64_t nanoseconds = 0, rcl_clock_type_t clock = RCL_SYSTEM_TIME);
RCLCPP_PUBLIC
Time(const Time & rhs);
/// Time constructor
/**
* \param time_msg builtin_interfaces time message to copy
* \param ros_time clock type
* \throws std::runtime_error if seconds are negative
*/
RCLCPP_PUBLIC
Time(
const builtin_interfaces::msg::Time & time_msg,
rcl_clock_type_t ros_time = RCL_ROS_TIME);
/// Time constructor
/**
* \param time_point rcl_time_point_t structure to copy
*/
RCLCPP_PUBLIC
explicit Time(const rcl_time_point_t & time_point);

View File

@@ -126,6 +126,7 @@ public:
* \param[in] clock The clock providing the current time.
* \param[in] period The interval at which the timer fires.
* \param[in] callback User-specified callback function.
* \param[in] context custom context to be used.
*/
explicit GenericTimer(
Clock::SharedPtr clock, std::chrono::nanoseconds period, FunctorT && callback,

View File

@@ -119,7 +119,7 @@ public:
RCLCPP_PUBLIC
virtual
bool
is_ready(rcl_wait_set_t *) = 0;
is_ready(rcl_wait_set_t * wait_set) = 0;
/// Execute any entities of the Waitable that are ready.
/**

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>0.7.8</version>
<version>0.7.14</version>
<description>The ROS client library in C++.</description>
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
<license>Apache License 2.0</license>

View File

@@ -35,7 +35,7 @@ Clock::Clock(rcl_clock_type_t clock_type)
allocator_ = rcl_get_default_allocator();
auto ret = rcl_clock_init(clock_type, &rcl_clock_, &allocator_);
if (ret != RCL_RET_OK) {
exceptions::throw_from_rcl_error(ret, "could not get current time stamp");
exceptions::throw_from_rcl_error(ret, "failed to initialize rcl clock");
}
}

View File

@@ -140,6 +140,7 @@ Executor::add_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_pt
}
}
// Add the node's notify condition to the guard condition handles
std::unique_lock<std::mutex> lock(memory_strategy_mutex_);
memory_strategy_->add_guard_condition(node_ptr->get_notify_guard_condition());
}
@@ -178,6 +179,7 @@ Executor::remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node
}
}
}
std::unique_lock<std::mutex> lock(memory_strategy_mutex_);
memory_strategy_->remove_guard_condition(node_ptr->get_notify_guard_condition());
}
@@ -232,7 +234,7 @@ Executor::spin_some(std::chrono::nanoseconds max_duration)
throw std::runtime_error("spin_some() called while already spinning");
}
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
while (spinning.load() && max_duration_not_elapsed()) {
while (rclcpp::ok(context_) && spinning.load() && max_duration_not_elapsed()) {
AnyExecutable any_exec;
if (get_next_executable(any_exec, std::chrono::milliseconds::zero())) {
execute_any_executable(any_exec);
@@ -242,6 +244,15 @@ Executor::spin_some(std::chrono::nanoseconds max_duration)
}
}
void
Executor::spin_once_impl(std::chrono::nanoseconds timeout)
{
AnyExecutable any_exec;
if (get_next_executable(any_exec, timeout)) {
execute_any_executable(any_exec);
}
}
void
Executor::spin_once(std::chrono::nanoseconds timeout)
{
@@ -249,10 +260,7 @@ Executor::spin_once(std::chrono::nanoseconds timeout)
throw std::runtime_error("spin_once() called while already spinning");
}
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
AnyExecutable any_exec;
if (get_next_executable(any_exec, timeout)) {
execute_any_executable(any_exec);
}
spin_once_impl(timeout);
}
void
@@ -423,43 +431,47 @@ Executor::execute_client(
void
Executor::wait_for_work(std::chrono::nanoseconds timeout)
{
// Collect the subscriptions and timers to be waited on
memory_strategy_->clear_handles();
bool has_invalid_weak_nodes = memory_strategy_->collect_entities(weak_nodes_);
{
std::unique_lock<std::mutex> lock(memory_strategy_mutex_);
// Clean up any invalid nodes, if they were detected
if (has_invalid_weak_nodes) {
auto node_it = weak_nodes_.begin();
auto gc_it = guard_conditions_.begin();
while (node_it != weak_nodes_.end()) {
if (node_it->expired()) {
node_it = weak_nodes_.erase(node_it);
memory_strategy_->remove_guard_condition(*gc_it);
gc_it = guard_conditions_.erase(gc_it);
} else {
++node_it;
++gc_it;
// Collect the subscriptions and timers to be waited on
memory_strategy_->clear_handles();
bool has_invalid_weak_nodes = memory_strategy_->collect_entities(weak_nodes_);
// Clean up any invalid nodes, if they were detected
if (has_invalid_weak_nodes) {
auto node_it = weak_nodes_.begin();
auto gc_it = guard_conditions_.begin();
while (node_it != weak_nodes_.end()) {
if (node_it->expired()) {
node_it = weak_nodes_.erase(node_it);
memory_strategy_->remove_guard_condition(*gc_it);
gc_it = guard_conditions_.erase(gc_it);
} else {
++node_it;
++gc_it;
}
}
}
}
// clear wait set
if (rcl_wait_set_clear(&wait_set_) != RCL_RET_OK) {
throw std::runtime_error("Couldn't clear wait set");
}
// clear wait set
if (rcl_wait_set_clear(&wait_set_) != RCL_RET_OK) {
throw std::runtime_error("Couldn't clear wait set");
}
// The size of waitables are accounted for in size of the other entities
rcl_ret_t ret = rcl_wait_set_resize(
&wait_set_, memory_strategy_->number_of_ready_subscriptions(),
memory_strategy_->number_of_guard_conditions(), memory_strategy_->number_of_ready_timers(),
memory_strategy_->number_of_ready_clients(), memory_strategy_->number_of_ready_services(),
memory_strategy_->number_of_ready_events());
if (RCL_RET_OK != ret) {
throw std::runtime_error(
std::string("Couldn't resize the wait set : ") + rcl_get_error_string().str);
}
// The size of waitables are accounted for in size of the other entities
rcl_ret_t ret = rcl_wait_set_resize(
&wait_set_, memory_strategy_->number_of_ready_subscriptions(),
memory_strategy_->number_of_guard_conditions(), memory_strategy_->number_of_ready_timers(),
memory_strategy_->number_of_ready_clients(), memory_strategy_->number_of_ready_services(),
memory_strategy_->number_of_ready_events());
if (RCL_RET_OK != ret) {
throw std::runtime_error(
std::string("Couldn't resize the wait set : ") + rcl_get_error_string().str);
}
if (!memory_strategy_->add_handles_to_wait_set(&wait_set_)) {
throw std::runtime_error("Couldn't fill wait set");
if (!memory_strategy_->add_handles_to_wait_set(&wait_set_)) {
throw std::runtime_error("Couldn't fill wait set");
}
}
rcl_ret_t status =
rcl_wait(&wait_set_, std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count());

View File

@@ -83,6 +83,11 @@ MultiThreadedExecutor::run(size_t)
if (any_exec.timer) {
// Guard against multiple threads getting the same timer.
if (scheduled_timers_.count(any_exec.timer) != 0) {
// Make sure that any_exec's callback group is reset before
// the lock is released.
if (any_exec.callback_group) {
any_exec.callback_group->can_be_taken_from().store(true);
}
continue;
}
scheduled_timers_.insert(any_exec.timer);

View File

@@ -320,9 +320,11 @@ rclcpp::Event::SharedPtr
NodeGraph::get_graph_event()
{
auto event = rclcpp::Event::make_shared();
std::lock_guard<std::mutex> graph_changed_lock(graph_mutex_);
graph_events_.push_back(event);
graph_users_count_++;
{
std::lock_guard<std::mutex> graph_changed_lock(graph_mutex_);
graph_events_.push_back(event);
graph_users_count_++;
}
// on first call, add node to graph_listener_
if (should_add_to_graph_listener_.exchange(false)) {
graph_listener_->add_node(this);

View File

@@ -85,6 +85,26 @@ TEST_F(TestGetNodeInterfaces, node_reference) {
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
}
TEST_F(TestGetNodeInterfaces, rclcpp_node_pointer) {
rclcpp::Node * node_pointer = this->node.get();
auto result = rclcpp::node_interfaces::get_node_topics_interface(node_pointer);
static_assert(
std::is_same<
rclcpp::node_interfaces::NodeTopicsInterface *,
decltype(result)
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
}
TEST_F(TestGetNodeInterfaces, node_pointer) {
NodeWrapper * wrapped_node_pointer = this->wrapped_node.get();
auto result = rclcpp::node_interfaces::get_node_topics_interface(wrapped_node_pointer);
static_assert(
std::is_same<
rclcpp::node_interfaces::NodeTopicsInterface *,
decltype(result)
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
}
TEST_F(TestGetNodeInterfaces, interface_shared_pointer) {
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface> interface_shared_ptr =
this->node->get_node_topics_interface();

View File

@@ -3,6 +3,29 @@ Changelog for package rclcpp_action
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.7.14 (2020-07-10)
-------------------
* Fixed doxygen warnings. (`#1208 <https://github.com/ros2/rclcpp/issues/1208>`_)
* Contributors: Alejandro Hernández Cordero
0.7.13 (2020-03-12)
-------------------
0.7.12 (2019-12-05)
-------------------
* Fixed memory leak in action clients (`#934 <https://github.com/ros2/rclcpp/issues/934>`_)
* Do not throw exception in action client if take fails (`#891 <https://github.com/ros2/rclcpp/issues/891>`_)
* Contributors: Ivan Santiago Paunovic, Jacob Perron
0.7.11 (2019-10-11)
-------------------
0.7.10 (2019-09-23)
-------------------
0.7.9 (2019-09-20)
------------------
0.7.8 (2019-09-06)
------------------

View File

@@ -30,10 +30,10 @@ namespace rclcpp_action
* This function is equivalent to \sa create_client()` however is using the individual
* node interfaces to create the client.
*
* \param node_base_interface[in] The node base interface of the corresponding node.
* \param node_graph_interface[in] The node graph interface of the corresponding node.
* \param node_logging_interface[in] The node logging interface of the corresponding node.
* \param node_waitables_interface[in] The node waitables interface of the corresponding node.
* \param[in] node_base_interface The node base interface of the corresponding node.
* \param[in] node_graph_interface The node graph interface of the corresponding node.
* \param[in] node_logging_interface The node logging interface of the corresponding node.
* \param[in] node_waitables_interface The node waitables interface of the corresponding node.
* \param[in] name The action name.
* \param[in] group The action client will be added to this callback group.
* If `nullptr`, then the action client is added to the default callback group.

View File

@@ -39,18 +39,18 @@ namespace rclcpp_action
*
* \sa Server::Server() for more information.
*
* \param node_base_interface[in] The node base interface of the corresponding node.
* \param node_clock_interface[in] The node clock interface of the corresponding node.
* \param node_logging_interface[in] The node logging interface of the corresponding node.
* \param node_waitables_interface[in] The node waitables interface of the corresponding node.
* \param name[in] The action name.
* \param[in] node_base_interface The node base interface of the corresponding node.
* \param[in] node_clock_interface The node clock interface of the corresponding node.
* \param[in] node_logging_interface The node logging interface of the corresponding node.
* \param[in] node_waitables_interface The node waitables interface of the corresponding node.
* \param[in] name The action name.
* \param[in] handle_goal A callback that decides if a goal should be accepted or rejected.
* \param[in] handle_cancel A callback that decides if a goal should be attempted to be canceled.
* The return from this callback only indicates if the server will try to cancel a goal.
* It does not indicate if the goal was actually canceled.
* \param[in] handle_accepted A callback that is called to give the user a handle to the goal.
* \param[in] options options to pass to the underlying `rcl_action_server_t`.
* \param group[in] The action server will be added to this callback group.
* \param[in] group The action server will be added to this callback group.
* If `nullptr`, then the action server is added to the default callback group.
*/
template<typename ActionT>
@@ -117,15 +117,15 @@ create_server(
*
* \sa Server::Server() for more information.
*
* \param node[in] The action server will be added to this node.
* \param name[in] The action name.
* \param[in] node] The action server will be added to this node.
* \param[in] name The action name.
* \param[in] handle_goal A callback that decides if a goal should be accepted or rejected.
* \param[in] handle_cancel A callback that decides if a goal should be attempted to be canceled.
* The return from this callback only indicates if the server will try to cancel a goal.
* It does not indicate if the goal was actually canceled.
* \param[in] handle_accepted A callback that is called to give the user a handle to the goal.
* \param[in] options options to pass to the underlying `rcl_action_server_t`.
* \param group[in] The action server will be added to this callback group.
* \param[in] group The action server will be added to this callback group.
* If `nullptr`, then the action server is added to the default callback group.
*/
template<typename ActionT>

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

View File

@@ -165,11 +165,11 @@ ClientBase::wait_for_action_server_nanoseconds(std::chrono::nanoseconds timeout)
if (!node_ptr) {
throw rclcpp::exceptions::InvalidNodeError();
}
auto event = node_ptr->get_graph_event();
// check to see if the server is ready immediately
if (this->action_server_is_ready()) {
return true;
}
auto event = node_ptr->get_graph_event();
if (timeout == std::chrono::nanoseconds(0)) {
// check was non-blocking, return immediately
return false;
@@ -388,20 +388,20 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_feedback(
pimpl_->client_handle.get(), feedback_message.get());
pimpl_->is_feedback_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking feedback");
} else {
if (RCL_RET_OK == ret) {
this->handle_feedback_message(feedback_message);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking feedback");
}
} else if (pimpl_->is_status_ready) {
std::shared_ptr<void> status_message = this->create_status_message();
rcl_ret_t ret = rcl_action_take_status(
pimpl_->client_handle.get(), status_message.get());
pimpl_->is_status_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking status");
} else {
if (RCL_RET_OK == ret) {
this->handle_status_message(status_message);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking status");
}
} else if (pimpl_->is_goal_response_ready) {
rmw_request_id_t response_header;
@@ -409,10 +409,10 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_goal_response(
pimpl_->client_handle.get(), &response_header, goal_response.get());
pimpl_->is_goal_response_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking goal response");
} else {
if (RCL_RET_OK == ret) {
this->handle_goal_response(response_header, goal_response);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking goal response");
}
} else if (pimpl_->is_result_response_ready) {
rmw_request_id_t response_header;
@@ -420,10 +420,10 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_result_response(
pimpl_->client_handle.get(), &response_header, result_response.get());
pimpl_->is_result_response_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking result response");
} else {
if (RCL_RET_OK == ret) {
this->handle_result_response(response_header, result_response);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking result response");
}
} else if (pimpl_->is_cancel_response_ready) {
rmw_request_id_t response_header;
@@ -431,10 +431,10 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_cancel_response(
pimpl_->client_handle.get(), &response_header, cancel_response.get());
pimpl_->is_cancel_response_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking cancel response");
} else {
if (RCL_RET_OK == ret) {
this->handle_cancel_response(response_header, cancel_response);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking cancel response");
}
} else {
throw std::runtime_error("Executing action client but nothing is ready");

View File

@@ -2,6 +2,30 @@
Changelog for package rclcpp_components
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.7.14 (2020-07-10)
-------------------
* Added rclcpp_components Doxyfile. (`#1201 <https://github.com/ros2/rclcpp/issues/1201>`_)
* Contributors: Alejandro Hernández Cordero
0.7.13 (2020-03-12)
-------------------
* Remove absolute path from installed CMake code. (`#949 <https://github.com/ros2/rclcpp/issues/949>`_)
* Contributors: Jacob Perron
0.7.12 (2019-12-05)
-------------------
* Backport rclcpp_components_register_node (`#935 <https://github.com/ros2/rclcpp/issues/935>`_)
* Contributors: Shane Loretz
0.7.11 (2019-10-11)
-------------------
0.7.10 (2019-09-23)
-------------------
0.7.9 (2019-09-20)
------------------
0.7.8 (2019-09-06)
------------------

View File

@@ -41,6 +41,11 @@ ament_target_dependencies(component_container
"rclcpp"
)
set(node_main_template_install_dir "share/${PROJECT_NAME}")
install(FILES
src/node_main.cpp.in
DESTINATION ${node_main_template_install_dir})
add_executable(
component_container_mt
src/component_container_mt.cpp
@@ -119,4 +124,4 @@ install(
ament_export_include_directories(include)
ament_export_dependencies(class_loader)
ament_export_dependencies(rclcpp)
ament_package(CONFIG_EXTRAS rclcpp_components-extras.cmake)
ament_package(CONFIG_EXTRAS rclcpp_components-extras.cmake.in)

View File

@@ -0,0 +1,33 @@
# All settings not listed here will use the Doxygen default values.
PROJECT_NAME = "rclcpp_components"
PROJECT_NUMBER = master
PROJECT_BRIEF = "Package containing tools for dynamically loadable components"
# Use these lines to include the generated logging.hpp (update install path if needed)
# Otherwise just generate for the local (non-generated header files)
INPUT = ./include
RECURSIVE = YES
OUTPUT_DIRECTORY = doc_output
EXTRACT_ALL = YES
SORT_MEMBER_DOCS = NO
GENERATE_LATEX = NO
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = RCLCPP_COMPONENTS_PUBLIC=
# Tag files that do not exist will produce a warning and cross-project linking will not work.
TAGFILES += "../../../../doxygen_tag_files/cppreference-doxygen-web.tag.xml=http://en.cppreference.com/w/"
# Consider changing "latest" to the version you want to reference (e.g. beta1 or 1.0.0)
TAGFILES += "../../../../doxygen_tag_files/class_loader.tag=http://docs.ros2.org/latest/api/class_loader/"
TAGFILES += "../../../../doxygen_tag_files/rclcpp.tag=http://docs.ros2.org/latest/api/rclcpp/"
TAGFILES += "../../../../doxygen_tag_files/rcl.tag=http://docs.ros2.org/latest/api/rcl/"
TAGFILES += "../../../../doxygen_tag_files/rcutils.tag=http://docs.ros2.org/latest/api/rcutils/"
TAGFILES += "../../../../doxygen_tag_files/rmw.tag=http://docs.ros2.org/latest/api/rmw/"
# Uncomment to generate tag files for cross-project linking.
GENERATE_TAGFILE = "../../../../doxygen_tag_files/rclcpp_components.tag"

View File

@@ -0,0 +1,52 @@
# Copyright 2019 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# usage: rclcpp_components_register_node(
# <target> PLUGIN <component> EXECUTABLE <node>)
#
# Register an rclcpp component with the ament
# resource index and create an executable.
#
# :param target: the shared library target
# :type target: string
# :param PLUGIN: the plugin name
# :type PLUGIN: string
# :type EXECUTABLE: the node's executable name
# :type EXECUTABLE: string
#
macro(rclcpp_components_register_node target)
cmake_parse_arguments(ARGS "" "PLUGIN;EXECUTABLE" "" ${ARGN})
set(component ${ARGS_PLUGIN})
set(node ${ARGS_EXECUTABLE})
_rclcpp_components_register_package_hook()
set(_path "lib")
set(library_name "$<TARGET_FILE_NAME:${target}>")
if(WIN32)
set(_path "bin")
endif()
set(_RCLCPP_COMPONENTS__NODES
"${_RCLCPP_COMPONENTS__NODES}${component};${_path}/$<TARGET_FILE_NAME:${target}>\n")
configure_file(${rclcpp_components_NODE_TEMPLATE}
${PROJECT_BINARY_DIR}/rclcpp_components/node_main_configured_${node}.cpp.in)
file(GENERATE OUTPUT ${PROJECT_BINARY_DIR}/rclcpp_components/node_main_${node}.cpp
INPUT ${PROJECT_BINARY_DIR}/rclcpp_components/node_main_configured_${node}.cpp.in)
add_executable(${node} ${PROJECT_BINARY_DIR}/rclcpp_components/node_main_${node}.cpp)
ament_target_dependencies(${node}
"rclcpp"
"class_loader"
"rclcpp_components")
install(TARGETS
${node}
DESTINATION lib/${PROJECT_NAME})
endmacro()

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

View File

@@ -25,5 +25,8 @@ macro(_rclcpp_components_register_package_hook)
endif()
endmacro()
include("${rclcpp_components_DIR}/rclcpp_components_register_nodes.cmake")
get_filename_component(@PROJECT_NAME@_SHARE_DIR "${@PROJECT_NAME@_DIR}" DIRECTORY)
set(@PROJECT_NAME@_NODE_TEMPLATE "${@PROJECT_NAME@_SHARE_DIR}/node_main.cpp.in")
include("${rclcpp_components_DIR}/rclcpp_components_register_nodes.cmake")
include("${rclcpp_components_DIR}/rclcpp_components_register_node.cmake")

View File

@@ -0,0 +1,66 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <memory>
#include <string>
#include <vector>
#include "class_loader/class_loader.hpp"
#include "rclcpp/rclcpp.hpp"
#include "rclcpp_components/node_factory.hpp"
#include "rclcpp_components/node_factory_template.hpp"
#define NODE_MAIN_LOGGER_NAME "@node@"
int main(int argc, char * argv[])
{
auto args = rclcpp::init_and_remove_ros_arguments(argc, argv);
rclcpp::Logger logger = rclcpp::get_logger(NODE_MAIN_LOGGER_NAME);
rclcpp::executors::SingleThreadedExecutor exec;
rclcpp::NodeOptions options;
options.arguments(args);
std::vector<class_loader::ClassLoader * > loaders;
std::vector<rclcpp_components::NodeInstanceWrapper> node_wrappers;
std::string library_name = "@library_name@";
std::string class_name = "rclcpp_components::NodeFactoryTemplate<@component@>";
RCLCPP_DEBUG(logger, "Load library %s", library_name.c_str());
auto loader = new class_loader::ClassLoader(library_name);
auto classes = loader->getAvailableClasses<rclcpp_components::NodeFactory>();
for (auto clazz : classes) {
std::string name = clazz.c_str();
if (!(name.compare(class_name))) {
RCLCPP_DEBUG(logger, "Instantiate class %s", clazz.c_str());
auto node_factory = loader->createInstance<rclcpp_components::NodeFactory>(clazz);
auto wrapper = node_factory->create_node_instance(options);
auto node = wrapper.get_node_base_interface();
node_wrappers.push_back(wrapper);
exec.add_node(node);
}
}
loaders.push_back(loader);
exec.spin();
for (auto wrapper : node_wrappers) {
exec.remove_node(wrapper.get_node_base_interface());
}
node_wrappers.clear();
rclcpp::shutdown();
return 0;
}

View File

@@ -3,6 +3,28 @@ Changelog for package rclcpp_lifecycle
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.7.14 (2020-07-10)
-------------------
* Fixed doxygen warnings. (`#1208 <https://github.com/ros2/rclcpp/issues/1208>`_)
* Contributors: Alejandro Hernández Cordero
0.7.13 (2020-03-12)
-------------------
0.7.12 (2019-12-05)
-------------------
0.7.11 (2019-10-11)
-------------------
0.7.10 (2019-09-23)
-------------------
* reset error message before setting a new one, embed the original one (`#854 <https://github.com/ros2/rclcpp/issues/854>`_) (`#866 <https://github.com/ros2/rclcpp/issues/866>`_)
* Contributors: Dirk Thomas, Zachary Michaels
0.7.9 (2019-09-20)
------------------
0.7.8 (2019-09-06)
------------------
* Fixed error messages which were not printing to console. (`#777 <https://github.com/ros2/rclcpp/issues/777>`_) (`#847 <https://github.com/ros2/rclcpp/issues/847>`_)

View File

@@ -103,7 +103,6 @@ public:
/// Create a new lifecycle node with the specified name.
/**
* \param[in] node_name Name of the node.
* \param[in] namespace_ Namespace of the node.
* \param[in] options Additional options to control creation of the node.
*/
RCLCPP_LIFECYCLE_PUBLIC

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

View File

@@ -369,6 +369,7 @@ public:
{
RCUTILS_LOG_ERROR("Unable to start transition %u from current state %s: %s",
transition_id, state_machine_.current_state->label, rcl_get_error_string().str);
rcutils_reset_error();
return RCL_RET_ERROR;
}
@@ -389,8 +390,10 @@ public:
if (rcl_lifecycle_trigger_transition_by_label(
&state_machine_, transition_label, publish_update) != RCL_RET_OK)
{
RCUTILS_LOG_ERROR("Failed to finish transition %u. Current state is now: %s",
transition_id, state_machine_.current_state->label);
RCUTILS_LOG_ERROR(
"Failed to finish transition %u. Current state is now: %s (%s)",
transition_id, state_machine_.current_state->label, rcl_get_error_string().str);
rcutils_reset_error();
return RCL_RET_ERROR;
}
@@ -404,7 +407,8 @@ public:
if (rcl_lifecycle_trigger_transition_by_label(
&state_machine_, error_cb_label, publish_update) != RCL_RET_OK)
{
RCUTILS_LOG_ERROR("Failed to call cleanup on error state");
RCUTILS_LOG_ERROR("Failed to call cleanup on error state: %s", rcl_get_error_string().str);
rcutils_reset_error();
return RCL_RET_ERROR;
}
}