Compare commits
30 Commits
native_buf
...
0.7.12
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7629f5b6d9 | ||
|
|
7cb2ececcb | ||
|
|
0f4fc08a93 | ||
|
|
82f6dfa6de | ||
|
|
fadd923aa0 | ||
|
|
f954ce5145 | ||
|
|
895145cfc9 | ||
|
|
3cdb3cb1bf | ||
|
|
5d5d3ce09d | ||
|
|
839ad201ac | ||
|
|
f3b0aa170c | ||
|
|
6e76503d9a | ||
|
|
b4629bf889 | ||
|
|
3f31ad0f55 | ||
|
|
25eeffdfcc | ||
|
|
3293603396 | ||
|
|
50ec1e568a | ||
|
|
607e290732 | ||
|
|
47ce42bc3f | ||
|
|
d2f052ee3d | ||
|
|
b86127d721 | ||
|
|
5cb6a6eeb5 | ||
|
|
f41e33c2a7 | ||
|
|
10c34ee9e5 | ||
|
|
6d3cbd39d1 | ||
|
|
bfee90ab7a | ||
|
|
1927f7e40e | ||
|
|
f73d80e79c | ||
|
|
e2e35570d5 | ||
|
|
5c395d6651 |
@@ -2,6 +2,43 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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)
|
||||
------------------
|
||||
|
||||
0.7.7 (2019-07-31)
|
||||
------------------
|
||||
* Enabled the creation of a parameter YAML file which is applied to each node. (`#805 <https://github.com/ros2/rclcpp/issues/805>`_)
|
||||
* Fixed a signed/unsigned integer comparison compiler warning. (`#804 <https://github.com/ros2/rclcpp/issues/804>`_)
|
||||
* Changed the QoS profile used when subscribing to parameter events to match the publishing side, i.e. ``rmw_qos_profile_parameter_events``. (`#798 <https://github.com/ros2/rclcpp/issues/798>`_)
|
||||
* Changed the logic in TimeSource to ignore use_sim_time parameter events coming from other nodes. (`#803 <https://github.com/ros2/rclcpp/issues/803>`_)
|
||||
* Added missing default values in the NodeParametersInterface. (`#794 <https://github.com/ros2/rclcpp/issues/794>`_)
|
||||
* Added support for const member callback functions. (`#763 <https://github.com/ros2/rclcpp/issues/763>`_)
|
||||
* Contributors: Esteve Fernandez, Gonzo, Karsten Knese, Michel Hidalgo, Scott K Logan
|
||||
|
||||
0.7.6 (2019-06-12)
|
||||
------------------
|
||||
* Ignore parameters overrides in set parameter methods when allowing undeclared parameters (`#756 <https://github.com/ros2/rclcpp/issues/756>`_)
|
||||
* Add rclcpp::create_timer() (`#757 <https://github.com/ros2/rclcpp/issues/757>`_)
|
||||
* checking origin of intra-process msg before taking them (`#753 <https://github.com/ros2/rclcpp/issues/753>`_)
|
||||
* Contributors: Alberto Soragna, Shane Loretz, ivanpauno
|
||||
|
||||
0.7.5 (2019-05-30)
|
||||
------------------
|
||||
* Avoid 'Intra process message no longer being stored when trying to handle it' warning (`#749 <https://github.com/ros2/rclcpp/issues/749>`_)
|
||||
|
||||
@@ -155,6 +155,18 @@ if(BUILD_TESTING)
|
||||
)
|
||||
target_link_libraries(test_client ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_create_timer test/test_create_timer.cpp)
|
||||
if(TARGET test_create_timer)
|
||||
ament_target_dependencies(test_create_timer
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rcl"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_create_timer ${PROJECT_NAME})
|
||||
target_include_directories(test_create_timer PRIVATE test/)
|
||||
endif()
|
||||
ament_add_gtest(test_expand_topic_or_service_name test/test_expand_topic_or_service_name.cpp)
|
||||
if(TARGET test_expand_topic_or_service_name)
|
||||
ament_target_dependencies(test_expand_topic_or_service_name
|
||||
|
||||
73
rclcpp/include/rclcpp/create_timer.hpp
Normal file
73
rclcpp/include/rclcpp/create_timer.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
// 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.
|
||||
|
||||
#ifndef RCLCPP__CREATE_TIMER_HPP_
|
||||
#define RCLCPP__CREATE_TIMER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/duration.hpp"
|
||||
# include "rclcpp/node_interfaces/get_node_base_interface.hpp"
|
||||
# include "rclcpp/node_interfaces/get_node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
/// Create a timer with a given clock
|
||||
/// \internal
|
||||
template<typename CallbackT>
|
||||
typename rclcpp::TimerBase::SharedPtr
|
||||
create_timer(
|
||||
node_interfaces::NodeBaseInterface * node_base,
|
||||
node_interfaces::NodeTimersInterface * node_timers,
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
auto timer = rclcpp::GenericTimer<CallbackT>::make_shared(
|
||||
clock,
|
||||
period.to_chrono<std::chrono::nanoseconds>(),
|
||||
std::forward<CallbackT>(callback),
|
||||
node_base->get_context());
|
||||
|
||||
node_timers->add_timer(timer, group);
|
||||
return timer;
|
||||
}
|
||||
|
||||
/// Create a timer with a given clock
|
||||
template<typename NodeT, typename CallbackT>
|
||||
typename rclcpp::TimerBase::SharedPtr
|
||||
create_timer(
|
||||
NodeT node,
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
return create_timer(
|
||||
rclcpp::node_interfaces::get_node_base_interface(node),
|
||||
rclcpp::node_interfaces::get_node_timers_interface(node),
|
||||
clock,
|
||||
period,
|
||||
std::forward<CallbackT>(callback),
|
||||
group);
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CREATE_TIMER_HPP_
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -355,6 +356,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_;
|
||||
|
||||
|
||||
@@ -96,6 +96,24 @@ struct function_traits<
|
||||
: function_traits<ReturnTypeT(Args ...)>
|
||||
{};
|
||||
|
||||
// std::bind for object const methods
|
||||
template<typename ClassT, typename ReturnTypeT, typename ... Args, typename ... FArgs>
|
||||
#if defined _LIBCPP_VERSION // libc++ (Clang)
|
||||
struct function_traits<std::__bind<ReturnTypeT (ClassT::*)(Args ...) const, FArgs ...>>
|
||||
#elif defined _GLIBCXX_RELEASE // glibc++ (GNU C++ >= 7.1)
|
||||
struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(FArgs ...))(Args ...) const>>
|
||||
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
|
||||
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 ...>
|
||||
>
|
||||
#else
|
||||
#error "Unsupported C++ compiler / standard library"
|
||||
#endif
|
||||
: function_traits<ReturnTypeT(Args ...)>
|
||||
{};
|
||||
|
||||
// std::bind for free functions
|
||||
template<typename ReturnTypeT, typename ... Args, typename ... FArgs>
|
||||
#if defined _LIBCPP_VERSION // libc++ (Clang)
|
||||
|
||||
@@ -516,6 +516,7 @@ public:
|
||||
* rclcpp::NodeOptions::allow_undeclared_parameters set to true.
|
||||
* If undeclared parameters are allowed, then the parameter is implicitly
|
||||
* declared with the default parameter meta data before being set.
|
||||
* Parameter overrides are ignored by set_parameter.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* set_on_parameters_set_callback to be called.
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
// 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.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
|
||||
/// This header provides the get_node_base_interface() template function.
|
||||
/**
|
||||
* This function is useful for getting the NodeBaseInterface pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get the NodeBaseInterface pointer so long as the class
|
||||
* has a method called ``get_node_base_interface()`` which returns
|
||||
* either a pointer (const or not) to a NodeBaseInterface or a
|
||||
* std::shared_ptr to a NodeBaseInterface.
|
||||
*/
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This is a meta-programming checker for if a given Node-like object has a
|
||||
// getter called get_node_base_interface() which returns various types,
|
||||
// e.g. const pointer or a shared pointer.
|
||||
template<typename NodeType, typename ReturnType>
|
||||
struct has_get_node_base_interface
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static constexpr
|
||||
auto
|
||||
check(T *)->typename std::is_same<
|
||||
decltype(std::declval<T>().get_node_base_interface()),
|
||||
ReturnType
|
||||
>::type;
|
||||
|
||||
template<typename>
|
||||
static constexpr
|
||||
std::false_type
|
||||
check(...);
|
||||
|
||||
public:
|
||||
using type = decltype(check<NodeType>(nullptr));
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
// If NodeType is a pointer to NodeBaseInterface already (just normal function overload).
|
||||
inline
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(rclcpp::node_interfaces::NodeBaseInterface * pointer)
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_base_interface() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_base_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface>
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_base_interface().get();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_base_interface() which returns a pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_base_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_base_interface();
|
||||
}
|
||||
|
||||
// Forward shared_ptr's to const node pointer signatures.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_same<
|
||||
NodeType,
|
||||
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_shared_pointer)
|
||||
{
|
||||
return get_node_base_interface_from_pointer(node_shared_pointer->get());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the NodeBaseInterface as a pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface(NodeType node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
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<typename std::remove_reference<NodeType>::type>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface(NodeType && node_reference)
|
||||
{
|
||||
// Forward references to detail implmentation as a pointer.
|
||||
return detail::get_node_base_interface_from_pointer(&node_reference);
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
@@ -0,0 +1,149 @@
|
||||
// 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.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
|
||||
/// This header provides the get_node_timers_interface() template function.
|
||||
/**
|
||||
* This function is useful for getting the NodeTimersInterface pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get the NodeTimersInterface pointer so long as the class
|
||||
* has a method called ``get_node_timers_interface()`` which returns
|
||||
* either a pointer (const or not) to a NodeTimersInterface or a
|
||||
* std::shared_ptr to a NodeTimersInterface.
|
||||
*/
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This is a meta-programming checker for if a given Node-like object has a
|
||||
// getter called get_node_timers_interface() which returns various types,
|
||||
// e.g. const pointer or a shared pointer.
|
||||
template<typename NodeType, typename ReturnType>
|
||||
struct has_get_node_timers_interface
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static constexpr
|
||||
auto
|
||||
check(T *)->typename std::is_same<
|
||||
decltype(std::declval<T>().get_node_timers_interface()),
|
||||
ReturnType
|
||||
>::type;
|
||||
|
||||
template<typename>
|
||||
static constexpr
|
||||
std::false_type
|
||||
check(...);
|
||||
|
||||
public:
|
||||
using type = decltype(check<NodeType>(nullptr));
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
// If NodeType is a pointer to NodeTimersInterface already (just normal function overload).
|
||||
inline
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(rclcpp::node_interfaces::NodeTimersInterface * pointer)
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_timers_interface() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_timers_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTimersInterface>
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_timers_interface().get();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_timers_interface() which returns a pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_timers_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_timers_interface();
|
||||
}
|
||||
|
||||
// Forward shared_ptr's to const node pointer signatures.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_same<
|
||||
NodeType,
|
||||
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_shared_pointer)
|
||||
{
|
||||
return get_node_timers_interface_from_pointer(node_shared_pointer->get());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the NodeTimersInterface as a pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface(NodeType node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
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<typename std::remove_reference<NodeType>::type>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface(NodeType && node_reference)
|
||||
{
|
||||
// Forward references to detail implmentation as a pointer.
|
||||
return detail::get_node_timers_interface_from_pointer(&node_reference);
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
@@ -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)
|
||||
|
||||
@@ -51,8 +51,9 @@ public:
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor) = 0;
|
||||
const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor()) = 0;
|
||||
|
||||
/// Undeclare a parameter.
|
||||
/**
|
||||
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
on_parameter_event(
|
||||
CallbackT && callback,
|
||||
const rclcpp::QoS & qos = (
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_default))
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events))
|
||||
),
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
NodeT && node,
|
||||
CallbackT && callback,
|
||||
const rclcpp::QoS & qos = (
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_default))
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events))
|
||||
),
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
|
||||
@@ -170,6 +170,13 @@ public:
|
||||
// However, this can only really happen if this node has it disabled, but the other doesn't.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!matches_any_intra_process_publishers(&message_info.publisher_gid)) {
|
||||
// This intra-process message has not been created by a publisher from this context.
|
||||
// we should ignore this copy of the message.
|
||||
return;
|
||||
}
|
||||
|
||||
if (any_callback_.use_take_shared_method()) {
|
||||
ConstMessageSharedPtr msg;
|
||||
take_intra_process_message(
|
||||
|
||||
@@ -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.5</version>
|
||||
<version>0.7.12</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -423,43 +425,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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -144,15 +144,16 @@ NodeParameters::NodeParameters(
|
||||
|
||||
rclcpp::ParameterMap initial_map = rclcpp::parameter_map_from(yaml_params);
|
||||
rcl_yaml_node_struct_fini(yaml_params);
|
||||
auto iter = initial_map.find(combined_name_);
|
||||
if (initial_map.end() == iter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Combine parameter yaml files, overwriting values in older ones
|
||||
for (auto & param : iter->second) {
|
||||
parameter_overrides_[param.get_name()] =
|
||||
rclcpp::ParameterValue(param.get_value_message());
|
||||
for (auto iter = initial_map.begin(); initial_map.end() != iter; iter++) {
|
||||
// TODO(cottsay) implement further wildcard matching
|
||||
if (iter->first == "/**" || iter->first == combined_name_) {
|
||||
// Combine parameter yaml files, overwriting values in older ones
|
||||
for (auto & param : iter->second) {
|
||||
parameter_overrides_[param.get_name()] =
|
||||
rclcpp::ParameterValue(param.get_value_message());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,19 +331,20 @@ __declare_parameter_common(
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
|
||||
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameters_out,
|
||||
const std::map<std::string, rclcpp::ParameterValue> & initial_values,
|
||||
const std::map<std::string, rclcpp::ParameterValue> & overrides,
|
||||
OnParametersSetCallbackType on_set_parameters_callback,
|
||||
rcl_interfaces::msg::ParameterEvent * parameter_event_out)
|
||||
rcl_interfaces::msg::ParameterEvent * parameter_event_out,
|
||||
bool use_overrides = true)
|
||||
{
|
||||
using rclcpp::node_interfaces::ParameterInfo;
|
||||
std::map<std::string, ParameterInfo> parameter_infos {{name, ParameterInfo()}};
|
||||
parameter_infos.at(name).descriptor = parameter_descriptor;
|
||||
|
||||
// Use the value from the initial_values if available, otherwise use the default.
|
||||
// Use the value from the overrides if available, otherwise use the default.
|
||||
const rclcpp::ParameterValue * initial_value = &default_value;
|
||||
auto initial_value_it = initial_values.find(name);
|
||||
if (initial_value_it != initial_values.end()) {
|
||||
initial_value = &initial_value_it->second;
|
||||
auto overrides_it = overrides.find(name);
|
||||
if (use_overrides && overrides_it != overrides.end()) {
|
||||
initial_value = &overrides_it->second;
|
||||
}
|
||||
|
||||
// Check with the user's callback to see if the initial value can be set.
|
||||
@@ -522,7 +524,8 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
|
||||
staged_parameter_changes,
|
||||
parameter_overrides_,
|
||||
nullptr, // callback is explicitly null, so that it is called only once, when setting below.
|
||||
¶meter_event_msg);
|
||||
¶meter_event_msg,
|
||||
false);
|
||||
if (!result.successful) {
|
||||
// Declare failed, return knowing that nothing was changed because the
|
||||
// staged changes were not applied.
|
||||
|
||||
@@ -98,7 +98,7 @@ NodeOptions::get_rcl_node_options() const
|
||||
}
|
||||
}
|
||||
|
||||
if (this->arguments_.size() > std::numeric_limits<int>::max()) {
|
||||
if (this->arguments_.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
|
||||
throw_from_rcl_error(RCL_RET_INVALID_ARGUMENT, "Too many args");
|
||||
}
|
||||
|
||||
|
||||
@@ -220,13 +220,17 @@ void TimeSource::destroy_clock_sub()
|
||||
|
||||
void TimeSource::on_parameter_event(const rcl_interfaces::msg::ParameterEvent::SharedPtr event)
|
||||
{
|
||||
// Filter out events on 'use_sim_time' parameter instances in other nodes.
|
||||
if (event->node != node_base_->get_fully_qualified_name()) {
|
||||
return;
|
||||
}
|
||||
// Filter for only 'use_sim_time' being added or changed.
|
||||
rclcpp::ParameterEventsFilter filter(event, {"use_sim_time"},
|
||||
{rclcpp::ParameterEventsFilter::EventType::NEW,
|
||||
rclcpp::ParameterEventsFilter::EventType::CHANGED});
|
||||
for (auto & it : filter.get_events()) {
|
||||
if (it.second->value.type != ParameterType::PARAMETER_BOOL) {
|
||||
RCLCPP_ERROR(logger_, "use_sim_time parameter set to something besides a bool");
|
||||
RCLCPP_ERROR(logger_, "use_sim_time parameter cannot be set to anything but a bool");
|
||||
continue;
|
||||
}
|
||||
if (it.second->value.bool_value) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
63
rclcpp/test/test_create_timer.cpp
Normal file
63
rclcpp/test/test_create_timer.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/create_timer.hpp"
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "node_interfaces/node_wrapper.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
TEST(TestCreateTimer, timer_executes)
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
auto node = std::make_shared<rclcpp::Node>("test_create_timer_node");
|
||||
|
||||
std::atomic<bool> got_callback{false};
|
||||
|
||||
rclcpp::TimerBase::SharedPtr timer;
|
||||
timer = rclcpp::create_timer(
|
||||
node,
|
||||
node->get_clock(),
|
||||
rclcpp::Duration(0ms),
|
||||
[&got_callback, &timer]() {
|
||||
got_callback = true;
|
||||
timer->cancel();
|
||||
});
|
||||
|
||||
rclcpp::spin_some(node);
|
||||
|
||||
ASSERT_TRUE(got_callback);
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
TEST(TestCreateTimer, call_with_node_wrapper_compiles)
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
NodeWrapper node("test_create_timer_call_with_node_wrapper_compiles");
|
||||
|
||||
rclcpp::TimerBase::SharedPtr timer;
|
||||
timer = rclcpp::create_timer(
|
||||
node,
|
||||
node.get_node_clock_interface()->get_clock(),
|
||||
rclcpp::Duration(0ms),
|
||||
[]() {});
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
@@ -80,6 +80,12 @@ struct ObjectMember
|
||||
return 7;
|
||||
}
|
||||
|
||||
int callback_one_bool_const(bool a) const
|
||||
{
|
||||
(void)a;
|
||||
return 7;
|
||||
}
|
||||
|
||||
int callback_two_bools(bool a, bool b)
|
||||
{
|
||||
(void)a;
|
||||
@@ -394,6 +400,16 @@ TEST(TestFunctionTraits, argument_types) {
|
||||
rclcpp::function_traits::function_traits<decltype(bind_one_bool)>::template argument_type<0>
|
||||
>::value, "Functor accepts a bool as first argument");
|
||||
|
||||
auto bind_one_bool_const = std::bind(
|
||||
&ObjectMember::callback_one_bool_const, &object_member, std::placeholders::_1);
|
||||
|
||||
static_assert(
|
||||
std::is_same<
|
||||
bool,
|
||||
rclcpp::function_traits::function_traits<decltype(bind_one_bool_const)>::template
|
||||
argument_type<0>
|
||||
>::value, "Functor accepts a bool as first argument");
|
||||
|
||||
auto bind_two_bools = std::bind(
|
||||
&ObjectMember::callback_two_bools, &object_member, std::placeholders::_1,
|
||||
std::placeholders::_2);
|
||||
@@ -561,6 +577,14 @@ TEST(TestFunctionTraits, check_arguments) {
|
||||
static_assert(
|
||||
rclcpp::function_traits::check_arguments<decltype(bind_one_bool), bool>::value,
|
||||
"Functor accepts a single bool as arguments");
|
||||
|
||||
auto bind_one_bool_const = std::bind(
|
||||
&ObjectMember::callback_one_bool_const, &object_member, std::placeholders::_1);
|
||||
|
||||
// Test std::bind functions
|
||||
static_assert(
|
||||
rclcpp::function_traits::check_arguments<decltype(bind_one_bool_const), bool>::value,
|
||||
"Functor accepts a single bool as arguments");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1066,9 +1066,20 @@ TEST_F(TestNode, set_parameter_undeclared_parameters_not_allowed) {
|
||||
}
|
||||
|
||||
TEST_F(TestNode, set_parameter_undeclared_parameters_allowed) {
|
||||
auto node = std::make_shared<rclcpp::Node>(
|
||||
"test_set_parameter_node"_unq,
|
||||
rclcpp::NodeOptions().allow_undeclared_parameters(true));
|
||||
rclcpp::NodeOptions no;
|
||||
no.parameter_overrides({
|
||||
{"parameter_with_override", 30},
|
||||
});
|
||||
no.allow_undeclared_parameters(true);
|
||||
auto node = std::make_shared<rclcpp::Node>("test_set_parameter_node"_unq, no);
|
||||
{
|
||||
// overrides are ignored when not declaring a parameter
|
||||
auto name = "parameter_with_override";
|
||||
EXPECT_FALSE(node->has_parameter(name));
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 43)).successful);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int>(), 43);
|
||||
}
|
||||
{
|
||||
// normal use (declare first) still works with this true
|
||||
auto name = "parameter"_unq;
|
||||
|
||||
@@ -3,6 +3,30 @@ Changelog for package rclcpp_action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
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)
|
||||
------------------
|
||||
|
||||
0.7.7 (2019-07-31)
|
||||
------------------
|
||||
|
||||
0.7.6 (2019-06-12)
|
||||
------------------
|
||||
|
||||
0.7.5 (2019-05-30)
|
||||
------------------
|
||||
|
||||
|
||||
@@ -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.5</version>
|
||||
<version>0.7.12</version>
|
||||
<description>Adds action APIs for C++.</description>
|
||||
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -2,6 +2,29 @@
|
||||
Changelog for package rclcpp_components
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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)
|
||||
------------------
|
||||
|
||||
0.7.7 (2019-07-31)
|
||||
------------------
|
||||
|
||||
0.7.6 (2019-06-12)
|
||||
------------------
|
||||
|
||||
0.7.5 (2019-05-30)
|
||||
------------------
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
@@ -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.5</version>
|
||||
<version>0.7.12</version>
|
||||
<description>Package containing tools for dynamically loadable components</description>
|
||||
<maintainer email="michael@openrobotics.org">Michael Carroll</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -25,5 +25,7 @@ macro(_rclcpp_components_register_package_hook)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
include("${rclcpp_components_DIR}/rclcpp_components_register_nodes.cmake")
|
||||
set(@PROJECT_NAME@_NODE_TEMPLATE "@CMAKE_INSTALL_PREFIX@/@node_main_template_install_dir@/node_main.cpp.in")
|
||||
|
||||
include("${rclcpp_components_DIR}/rclcpp_components_register_nodes.cmake")
|
||||
include("${rclcpp_components_DIR}/rclcpp_components_register_node.cmake")
|
||||
66
rclcpp_components/src/node_main.cpp.in
Normal file
66
rclcpp_components/src/node_main.cpp.in
Normal 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;
|
||||
}
|
||||
@@ -3,6 +3,33 @@ Changelog for package rclcpp_lifecycle
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
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>`_)
|
||||
* Contributors: Jacob Perron
|
||||
|
||||
0.7.7 (2019-07-31)
|
||||
------------------
|
||||
* Added a default value to node options in LifecycleNode constructor to match node constructor. Updated API documentation. (`#801 <https://github.com/ros2/rclcpp/issues/801>`_)
|
||||
* Contributors: Esteve Fernandez, Dirk Thomas
|
||||
|
||||
0.7.6 (2019-06-12)
|
||||
------------------
|
||||
|
||||
0.7.5 (2019-05-30)
|
||||
------------------
|
||||
|
||||
|
||||
@@ -115,14 +115,13 @@ public:
|
||||
/**
|
||||
* \param[in] node_name Name of the node.
|
||||
* \param[in] namespace_ Namespace of the node.
|
||||
* \param[in] context The context for the node (usually represents the state of a process).
|
||||
* \param[in] options Additional options to control creation of the node.
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
LifecycleNode(
|
||||
const std::string & node_name,
|
||||
const std::string & namespace_,
|
||||
const rclcpp::NodeOptions & options);
|
||||
const rclcpp::NodeOptions & options = rclcpp::NodeOptions());
|
||||
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
virtual ~LifecycleNode();
|
||||
|
||||
@@ -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.5</version>
|
||||
<version>0.7.12</version>
|
||||
<description>Package containing a prototype for lifecycle implementation</description>
|
||||
<maintainer email="karsten@osrfoundation.org">Karsten Knese</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -425,14 +429,9 @@ public:
|
||||
auto callback = it->second;
|
||||
try {
|
||||
cb_success = callback(State(previous_state));
|
||||
} catch (const std::exception &) {
|
||||
// TODO(karsten1987): Windows CI doesn't let me print the msg here
|
||||
// the todo is to forward the exception to the on_error callback
|
||||
// RCUTILS_LOG_ERROR("Caught exception in callback for transition %d\n",
|
||||
// it->first);
|
||||
// RCUTILS_LOG_ERROR("Original error msg: %s\n", e.what());
|
||||
// maybe directly go for error handling here
|
||||
// and pass exception along with it
|
||||
} catch (const std::exception & e) {
|
||||
RCUTILS_LOG_ERROR("Caught exception in callback for transition %d", it->first);
|
||||
RCUTILS_LOG_ERROR("Original error: %s", e.what());
|
||||
cb_success = node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user