Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf1be86f5c | ||
|
|
4dcb0eda68 | ||
|
|
9c1cbdf6c7 | ||
|
|
6e6dd9cb1a | ||
|
|
45a47c6448 | ||
|
|
6e408b79f3 | ||
|
|
b843c75ef8 | ||
|
|
cb1b32ee15 | ||
|
|
b67fa594f8 | ||
|
|
8bfc8e631f | ||
|
|
75f3d54d57 | ||
|
|
27e59d930a | ||
|
|
ce5de8757d | ||
|
|
6ea67a4e9f | ||
|
|
5f6bf45202 | ||
|
|
dc528ad710 | ||
|
|
26e824c7c0 | ||
|
|
3a3ba55fa2 | ||
|
|
1745db6dcd | ||
|
|
7ed387f862 | ||
|
|
a10ae56629 | ||
|
|
1f000b8d97 | ||
|
|
c14f46e6f3 | ||
|
|
70e1830ecd | ||
|
|
77564eb2ff |
@@ -2,20 +2,40 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
3.0.0 (2020-06-18)
|
||||
2.2.0 (2020-10-07)
|
||||
------------------
|
||||
* Check period duration in create_wall_timer (`#1178 <https://github.com/ros2/rclcpp/issues/1178>`_)
|
||||
* Fix get_node_time_source_interface() docstring (`#988 <https://github.com/ros2/rclcpp/issues/988>`_)
|
||||
* Add message lost subscription event (`#1164 <https://github.com/ros2/rclcpp/issues/1164>`_)
|
||||
* Add spin_all method to Executor (`#1156 <https://github.com/ros2/rclcpp/issues/1156>`_)
|
||||
* Reorganize test directory and split CMakeLists.txt (`#1173 <https://github.com/ros2/rclcpp/issues/1173>`_)
|
||||
* Fix implementation of NodeOptions::use_global_arguments() (`#1176 <https://github.com/ros2/rclcpp/issues/1176>`_) (`#1372 <https://github.com/ros2/rclcpp/issues/1372>`_)
|
||||
* Fix conversion of negative durations to messages (`#1188 <https://github.com/ros2/rclcpp/issues/1188>`_) (`#1371 <https://github.com/ros2/rclcpp/issues/1371>`_)
|
||||
* Call vector.erase with end iterator overload (`#1314 <https://github.com/ros2/rclcpp/issues/1314>`_) (`#1380 <https://github.com/ros2/rclcpp/issues/1380>`_)
|
||||
* Check waitable for nullptr during constructor (`#1315 <https://github.com/ros2/rclcpp/issues/1315>`_) (`#1379 <https://github.com/ros2/rclcpp/issues/1379>`_)
|
||||
* Fix pub/sub count API tests. (`#1203 <https://github.com/ros2/rclcpp/issues/1203>`_) (`#1319 <https://github.com/ros2/rclcpp/issues/1319>`_)
|
||||
* Reorganize test directory and split CMakeLists.txt (`#1173 <https://github.com/ros2/rclcpp/issues/1173>`_) (`#1262 <https://github.com/ros2/rclcpp/issues/1262>`_)
|
||||
* Add operator!= for duration (`#1236 <https://github.com/ros2/rclcpp/issues/1236>`_) (`#1278 <https://github.com/ros2/rclcpp/issues/1278>`_)
|
||||
* Contributors: Ivan Santiago Paunovic, Jacob Perron, Jannik Abbenseth, Johannes Meyer, Michel Hidalgo, Stephen Brawner
|
||||
|
||||
2.1.0 (2020-08-03)
|
||||
------------------
|
||||
* Warn about unused result of add_on_set_parameters_callback (`#1238 <https://github.com/ros2/rclcpp/issues/1238>`_) (`#1244 <https://github.com/ros2/rclcpp/issues/1244>`_)
|
||||
* Add missing RCLCPP_PUBLIC to ~StaticExecutorEntitiesCollector (`#1227 <https://github.com/ros2/rclcpp/issues/1227>`_) (`#1228 <https://github.com/ros2/rclcpp/issues/1228>`_)
|
||||
* Remove recreation of entities_collector (`#1217 <https://github.com/ros2/rclcpp/issues/1217>`_) (`#1224 <https://github.com/ros2/rclcpp/issues/1224>`_)
|
||||
* Contributors: Jacob Perron, brawner
|
||||
|
||||
2.0.2 (2020-07-07)
|
||||
------------------
|
||||
* Link against thread library where necessary (`#1210 <https://github.com/ros2/rclcpp/issues/1210>`_) (`#1214 <https://github.com/ros2/rclcpp/issues/1214>`_)
|
||||
* Fix exception message on rcl_clock_init (`#1182 <https://github.com/ros2/rclcpp/issues/1182>`_) (`#1193 <https://github.com/ros2/rclcpp/issues/1193>`_)
|
||||
* Contributors: Dirk Thomas, tomoya
|
||||
|
||||
2.0.1 (2020-06-23)
|
||||
------------------
|
||||
* Add create_publisher include to create_subscription (`#1180 <https://github.com/ros2/rclcpp/issues/1180>`_) (`#1192 <https://github.com/ros2/rclcpp/issues/1192>`_)
|
||||
* Fix get_node_time_source_interface() docstring (`#988 <https://github.com/ros2/rclcpp/issues/988>`_) (`#1185 <https://github.com/ros2/rclcpp/issues/1185>`_)
|
||||
* Fixed doxygen warnings (`#1163 <https://github.com/ros2/rclcpp/issues/1163>`_) (`#1191 <https://github.com/ros2/rclcpp/issues/1191>`_)
|
||||
* Check if context is valid when looping in spin_some (`#1167 <https://github.com/ros2/rclcpp/issues/1167>`_)
|
||||
* Add check for invalid topic statistics publish period (`#1151 <https://github.com/ros2/rclcpp/issues/1151>`_)
|
||||
* Fix spin_until_future_complete: check spinning value (`#1023 <https://github.com/ros2/rclcpp/issues/1023>`_)
|
||||
* Fix doxygen warnings (`#1163 <https://github.com/ros2/rclcpp/issues/1163>`_)
|
||||
* Fix reference to rclcpp in its Quality declaration (`#1161 <https://github.com/ros2/rclcpp/issues/1161>`_)
|
||||
* Allow spin_until_future_complete to accept any future like object (`#1113 <https://github.com/ros2/rclcpp/issues/1113>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Christophe Bedard, Devin Bonnie, Dirk Thomas, DongheeYe, Ivan Santiago Paunovic, Jacob Perron, Sarthak Mittal, brawner, tomoya
|
||||
Make Executor::spin_once_impl private before backporting, to avoid API compatibility issues
|
||||
* Add check for invalid topic statistics publish period (`#1151 <https://github.com/ros2/rclcpp/issues/1151>`_) (`#1172 <https://github.com/ros2/rclcpp/issues/1172>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Devin Bonnie, DongheeYe, Ivan Santiago Paunovic, Jacob Perron, Stephen Brawner
|
||||
|
||||
2.0.0 (2020-06-01)
|
||||
------------------
|
||||
|
||||
@@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(rclcpp)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_package(ament_cmake_ros REQUIRED)
|
||||
find_package(builtin_interfaces REQUIRED)
|
||||
find_package(libstatistics_collector REQUIRED)
|
||||
@@ -23,7 +25,11 @@ if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
endif()
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(-Wall -Wextra -Wpedantic -Wnon-virtual-dtor -Woverloaded-virtual)
|
||||
# About -Wno-sign-conversion: With Clang, -Wconversion implies -Wsign-conversion. There are a number of
|
||||
# implicit sign conversions in rclcpp and gtest.cc, see https://ci.ros2.org/job/ci_osx/9265/.
|
||||
# Hence disabling -Wsign-conversion for now until all those have eventually been fixed.
|
||||
# (from https://github.com/ros2/rclcpp/pull/1188#issuecomment-650229140)
|
||||
add_compile_options(-Wall -Wextra -Wconversion -Wno-sign-conversion -Wpedantic -Wnon-virtual-dtor -Woverloaded-virtual)
|
||||
endif()
|
||||
|
||||
set(${PROJECT_NAME}_SRCS
|
||||
@@ -166,6 +172,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:include>")
|
||||
target_link_libraries(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT})
|
||||
# specific order: dependents before dependencies
|
||||
ament_target_dependencies(${PROJECT_NAME}
|
||||
"libstatistics_collector"
|
||||
|
||||
@@ -191,7 +191,7 @@ It is **Quality Level 4**, see its [Quality Declaration document](https://github
|
||||
|
||||
#### `tracetools`
|
||||
|
||||
The `tracetools` package provides utilities for instrumenting the code in `rclcpp` so that it may be traced for debugging and performance analysis.
|
||||
The `tracetools` package provides utilities for instrumenting the code in `rcl` so that it may be traced for debugging and performance analysis.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://gitlab.com/micro-ROS/ros_tracing/ros2_tracing/-/blob/master/tracetools/QUALITY_DECLARATION.md).
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
|
||||
#include "rclcpp/create_publisher.hpp"
|
||||
#include "rclcpp/create_timer.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/subscription_factory.hpp"
|
||||
|
||||
@@ -76,14 +76,14 @@ create_timer(
|
||||
* \tparam DurationRepT
|
||||
* \tparam DurationT
|
||||
* \tparam CallbackT
|
||||
* \param period period to execute callback. This duration must be 0 <= period < nanoseconds::max()
|
||||
* \param period period to exectute callback
|
||||
* \param callback callback to execute via the timer period
|
||||
* \param group
|
||||
* \param node_base
|
||||
* \param node_timers
|
||||
* \return
|
||||
* \throws std::invalid argument if either node_base or node_timers
|
||||
* are null, or period is negative or too large
|
||||
* are null
|
||||
*/
|
||||
template<typename DurationRepT, typename DurationT, typename CallbackT>
|
||||
typename rclcpp::WallTimer<CallbackT>::SharedPtr
|
||||
@@ -102,38 +102,10 @@ create_wall_timer(
|
||||
throw std::invalid_argument{"input node_timers cannot be null"};
|
||||
}
|
||||
|
||||
if (period < std::chrono::duration<DurationRepT, DurationT>::zero()) {
|
||||
throw std::invalid_argument{"timer period cannot be negative"};
|
||||
}
|
||||
|
||||
// Casting to a double representation might lose precision and allow the check below to succeed
|
||||
// but the actual cast to nanoseconds fail. Using 1 DurationT worth of nanoseconds less than max.
|
||||
constexpr auto maximum_safe_cast_ns =
|
||||
std::chrono::nanoseconds::max() - std::chrono::duration<DurationRepT, DurationT>(1);
|
||||
|
||||
// If period is greater than nanoseconds::max(), the duration_cast to nanoseconds will overflow
|
||||
// a signed integer, which is undefined behavior. Checking whether any std::chrono::duration is
|
||||
// greater than nanoseconds::max() is a difficult general problem. This is a more conservative
|
||||
// version of Howard Hinnant's (the <chrono> guy>) response here:
|
||||
// https://stackoverflow.com/a/44637334/2089061
|
||||
// However, this doesn't solve the issue for all possible duration types of period.
|
||||
// Follow-up issue: https://github.com/ros2/rclcpp/issues/1177
|
||||
constexpr auto ns_max_as_double =
|
||||
std::chrono::duration_cast<std::chrono::duration<double, std::chrono::nanoseconds::period>>(
|
||||
maximum_safe_cast_ns);
|
||||
if (period > ns_max_as_double) {
|
||||
throw std::invalid_argument{
|
||||
"timer period must be less than std::chrono::nanoseconds::max()"};
|
||||
}
|
||||
|
||||
const auto period_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(period);
|
||||
if (period_ns < std::chrono::nanoseconds::zero()) {
|
||||
throw std::runtime_error{
|
||||
"Casting timer period to nanoseconds resulted in integer overflow."};
|
||||
}
|
||||
|
||||
auto timer = rclcpp::WallTimer<CallbackT>::make_shared(
|
||||
period_ns, std::move(callback), node_base->get_context());
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(period),
|
||||
std::move(callback),
|
||||
node_base->get_context());
|
||||
node_timers->add_timer(timer, group);
|
||||
return timer;
|
||||
}
|
||||
|
||||
@@ -72,11 +72,14 @@ public:
|
||||
operator=(const Duration & rhs);
|
||||
|
||||
Duration &
|
||||
operator=(const builtin_interfaces::msg::Duration & Duration_msg);
|
||||
operator=(const builtin_interfaces::msg::Duration & duration_msg);
|
||||
|
||||
bool
|
||||
operator==(const rclcpp::Duration & rhs) const;
|
||||
|
||||
bool
|
||||
operator!=(const rclcpp::Duration & rhs) const;
|
||||
|
||||
bool
|
||||
operator<(const rclcpp::Duration & rhs) const;
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ public:
|
||||
void
|
||||
spin_node_some(std::shared_ptr<rclcpp::Node> node);
|
||||
|
||||
/// Collect work once and execute all available work, optionally within a duration.
|
||||
/// Complete all available queued work without blocking.
|
||||
/**
|
||||
* This function can be overridden. The default implementation is suitable for a
|
||||
* single-threaded model of execution.
|
||||
@@ -175,23 +175,6 @@ public:
|
||||
virtual void
|
||||
spin_some(std::chrono::nanoseconds max_duration = std::chrono::nanoseconds(0));
|
||||
|
||||
/// Collect and execute work repeatedly within a duration or until no more work is available.
|
||||
/**
|
||||
* This function can be overridden. The default implementation is suitable for a
|
||||
* single-threaded model of execution.
|
||||
* Adding subscriptions, timers, services, etc. with blocking callbacks will cause this function
|
||||
* to block (which may have unintended consequences).
|
||||
* If the time that waitables take to be executed is longer than the period on which new waitables
|
||||
* become ready, this method will execute work repeatedly until `max_duration` has elapsed.
|
||||
*
|
||||
* \param[in] max_duration The maximum amount of time to spend executing work. Must be positive.
|
||||
* Note that spin_all() may take longer than this time as it only returns once max_duration has
|
||||
* been exceeded.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
spin_all(std::chrono::nanoseconds max_duration);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
spin_once(std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
|
||||
@@ -206,10 +189,10 @@ public:
|
||||
* code.
|
||||
* \return The return code, one of `SUCCESS`, `INTERRUPTED`, or `TIMEOUT`.
|
||||
*/
|
||||
template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
const FutureT & future,
|
||||
const std::shared_future<ResponseT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
// TODO(wjwwood): does not work recursively; can't call spin_node_until_future_complete
|
||||
@@ -287,10 +270,6 @@ protected:
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_some_impl(std::chrono::nanoseconds max_duration, bool exhaustive);
|
||||
|
||||
/// Find the next available executable and do the work associated with it.
|
||||
/**
|
||||
* \param[in] any_exec Union structure that can hold any executable type (timer, subscription,
|
||||
@@ -363,12 +342,13 @@ protected:
|
||||
|
||||
RCLCPP_DISABLE_COPY(Executor)
|
||||
|
||||
std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
|
||||
std::list<const rcl_guard_condition_t *> guard_conditions_;
|
||||
|
||||
private:
|
||||
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_;
|
||||
};
|
||||
|
||||
namespace executor
|
||||
|
||||
@@ -66,12 +66,12 @@ using rclcpp::executors::SingleThreadedExecutor;
|
||||
* If the time spent inside the blocking loop exceeds this timeout, return a `TIMEOUT` return code.
|
||||
* \return The return code, one of `SUCCESS`, `INTERRUPTED`, or `TIMEOUT`.
|
||||
*/
|
||||
template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
rclcpp::FutureReturnCode
|
||||
spin_node_until_future_complete(
|
||||
rclcpp::Executor & executor,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
const FutureT & future,
|
||||
const std::shared_future<ResponseT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
// TODO(wjwwood): does not work recursively; can't call spin_node_until_future_complete
|
||||
@@ -82,13 +82,13 @@ spin_node_until_future_complete(
|
||||
return retcode;
|
||||
}
|
||||
|
||||
template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeRepT = int64_t,
|
||||
template<typename NodeT = rclcpp::Node, typename ResponseT, typename TimeRepT = int64_t,
|
||||
typename TimeT = std::milli>
|
||||
rclcpp::FutureReturnCode
|
||||
spin_node_until_future_complete(
|
||||
rclcpp::Executor & executor,
|
||||
std::shared_ptr<NodeT> node_ptr,
|
||||
const FutureT & future,
|
||||
const std::shared_future<ResponseT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
return rclcpp::executors::spin_node_until_future_complete(
|
||||
@@ -104,7 +104,7 @@ template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::mi
|
||||
rclcpp::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
const FutureT & future,
|
||||
const std::shared_future<FutureT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
@@ -116,7 +116,7 @@ template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeRepT = in
|
||||
rclcpp::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
std::shared_ptr<NodeT> node_ptr,
|
||||
const FutureT & future,
|
||||
const std::shared_future<FutureT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
return rclcpp::spin_until_future_complete(node_ptr->get_node_base_interface(), future, timeout);
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
StaticExecutorEntitiesCollector() = default;
|
||||
|
||||
// Destructor
|
||||
RCLCPP_PUBLIC
|
||||
~StaticExecutorEntitiesCollector();
|
||||
|
||||
/// Initialize StaticExecutorEntitiesCollector
|
||||
|
||||
@@ -143,10 +143,10 @@ public:
|
||||
* exec.add_node(node);
|
||||
* exec.spin_until_future_complete(future);
|
||||
*/
|
||||
template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
rclcpp::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
FutureT & future,
|
||||
std::shared_future<ResponseT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
std::future_status status = future.wait_for(std::chrono::seconds(0));
|
||||
@@ -162,7 +162,6 @@ public:
|
||||
}
|
||||
std::chrono::nanoseconds timeout_left = timeout_ns;
|
||||
|
||||
entities_collector_ = std::make_shared<StaticExecutorEntitiesCollector>();
|
||||
entities_collector_->init(&wait_set_, memory_strategy_, &interrupt_guard_condition_);
|
||||
|
||||
while (rclcpp::ok(this->context_)) {
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rcutils/macros.h"
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/node.h"
|
||||
|
||||
@@ -812,6 +814,7 @@ public:
|
||||
* \throws std::bad_alloc if the allocation of the OnSetParametersCallbackHandle fails.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
OnSetParametersCallbackHandle::SharedPtr
|
||||
add_on_set_parameters_callback(OnParametersSetCallbackType callback);
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcutils/macros.h"
|
||||
|
||||
#include "rcl_interfaces/msg/list_parameters_result.hpp"
|
||||
#include "rcl_interfaces/msg/parameter_descriptor.hpp"
|
||||
#include "rcl_interfaces/msg/parameter_event.hpp"
|
||||
@@ -160,6 +162,7 @@ public:
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
OnSetParametersCallbackHandle::SharedPtr
|
||||
add_on_set_parameters_callback(OnParametersSetCallbackType callback) override;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
* \param[in] node_base NodeBaseInterface pointer that is used in part of the setup.
|
||||
* \param[in] topic Name of the topic to publish to.
|
||||
* \param[in] qos QoS profile for Subcription.
|
||||
* \param[in] options Options for the subscription.
|
||||
* \param[in] options options for the subscription.
|
||||
*/
|
||||
Publisher(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
|
||||
@@ -34,7 +34,6 @@ using QOSDeadlineRequestedInfo = rmw_requested_deadline_missed_status_t;
|
||||
using QOSDeadlineOfferedInfo = rmw_offered_deadline_missed_status_t;
|
||||
using QOSLivelinessChangedInfo = rmw_liveliness_changed_status_t;
|
||||
using QOSLivelinessLostInfo = rmw_liveliness_lost_status_t;
|
||||
using QOSMessageLostInfo = rmw_message_lost_status_t;
|
||||
using QOSOfferedIncompatibleQoSInfo = rmw_offered_qos_incompatible_event_status_t;
|
||||
using QOSRequestedIncompatibleQoSInfo = rmw_requested_qos_incompatible_event_status_t;
|
||||
|
||||
@@ -42,7 +41,6 @@ using QOSDeadlineRequestedCallbackType = std::function<void (QOSDeadlineRequeste
|
||||
using QOSDeadlineOfferedCallbackType = std::function<void (QOSDeadlineOfferedInfo &)>;
|
||||
using QOSLivelinessChangedCallbackType = std::function<void (QOSLivelinessChangedInfo &)>;
|
||||
using QOSLivelinessLostCallbackType = std::function<void (QOSLivelinessLostInfo &)>;
|
||||
using QOSMessageLostCallbackType = std::function<void (QOSMessageLostInfo &)>;
|
||||
using QOSOfferedIncompatibleQoSCallbackType = std::function<void (QOSOfferedIncompatibleQoSInfo &)>;
|
||||
using QOSRequestedIncompatibleQoSCallbackType =
|
||||
std::function<void (QOSRequestedIncompatibleQoSInfo &)>;
|
||||
@@ -61,7 +59,6 @@ struct SubscriptionEventCallbacks
|
||||
QOSDeadlineRequestedCallbackType deadline_callback;
|
||||
QOSLivelinessChangedCallbackType liveliness_callback;
|
||||
QOSRequestedIncompatibleQoSCallbackType incompatible_qos_callback;
|
||||
QOSMessageLostCallbackType message_lost_callback;
|
||||
};
|
||||
|
||||
class UnsupportedEventTypeException : public exceptions::RCLErrorBase, public std::runtime_error
|
||||
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
* \param[in] topic_name Name of the topic to subscribe to.
|
||||
* \param[in] qos QoS profile for Subcription.
|
||||
* \param[in] callback User defined callback to call when a message is received.
|
||||
* \param[in] options Options for the subscription.
|
||||
* \param[in] options options for the subscription.
|
||||
* \param[in] message_memory_strategy The memory strategy to be used for managing message memory.
|
||||
* \param[in] subscription_topic_statistics Optional pointer to a topic statistics subcription.
|
||||
* \throws std::invalid_argument if the QoS is uncompatible with intra-process (if one
|
||||
@@ -144,11 +144,6 @@ public:
|
||||
// pass
|
||||
}
|
||||
}
|
||||
if (options.event_callbacks.message_lost_callback) {
|
||||
this->add_event_handler(
|
||||
options.event_callbacks.message_lost_callback,
|
||||
RCL_SUBSCRIPTION_MESSAGE_LOST);
|
||||
}
|
||||
|
||||
// Setup intra process publishing if requested.
|
||||
if (rclcpp::detail::resolve_use_intra_process(options, *node_base)) {
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
* \param[in] node_base NodeBaseInterface pointer used in parts of the setup.
|
||||
* \param[in] type_support_handle rosidl type support struct, for the Message type of the topic.
|
||||
* \param[in] topic_name Name of the topic to subscribe to.
|
||||
* \param[in] subscription_options Options for the subscription.
|
||||
* \param[in] subscription_options options for the subscription.
|
||||
* \param[in] is_serialized is true if the message will be delivered still serialized
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
@@ -48,10 +48,10 @@ public:
|
||||
/// Time constructor
|
||||
/**
|
||||
* \param nanoseconds since time epoch
|
||||
* \param clock clock type
|
||||
* \param clock_type clock type
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit Time(int64_t nanoseconds = 0, rcl_clock_type_t clock = RCL_SYSTEM_TIME);
|
||||
explicit Time(int64_t nanoseconds = 0, rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
|
||||
|
||||
/// Copy constructor
|
||||
RCLCPP_PUBLIC
|
||||
@@ -60,13 +60,13 @@ public:
|
||||
/// Time constructor
|
||||
/**
|
||||
* \param time_msg builtin_interfaces time message to copy
|
||||
* \param ros_time clock type
|
||||
* \param clock_type 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);
|
||||
rcl_clock_type_t clock_type = RCL_ROS_TIME);
|
||||
|
||||
/// Time constructor
|
||||
/**
|
||||
@@ -90,6 +90,12 @@ public:
|
||||
Time &
|
||||
operator=(const Time & rhs);
|
||||
|
||||
/**
|
||||
* Assign Time from a builtin_interfaces::msg::Time instance.
|
||||
* The clock_type will be reset to RCL_ROS_TIME.
|
||||
* Equivalent to *this = Time(time_msg, RCL_ROS_TIME).
|
||||
* \throws std::runtime_error if seconds are negative
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
Time &
|
||||
operator=(const builtin_interfaces::msg::Time & time_msg);
|
||||
|
||||
@@ -73,7 +73,17 @@ protected:
|
||||
size_t services_from_waitables = 0;
|
||||
size_t events_from_waitables = 0;
|
||||
for (const auto & waitable_entry : waitables) {
|
||||
rclcpp::Waitable & waitable = *waitable_entry.waitable.get();
|
||||
auto waitable_ptr_pair = get_raw_pointer_from_smart_pointer(waitable_entry.waitable);
|
||||
if (nullptr == waitable_ptr_pair.second) {
|
||||
if (HasStrongOwnership) {
|
||||
throw std::runtime_error("unexpected condition, fixed storage policy needs pruning");
|
||||
}
|
||||
// Flag for pruning.
|
||||
needs_pruning_ = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
rclcpp::Waitable & waitable = *waitable_ptr_pair.second;
|
||||
subscriptions_from_waitables += waitable.get_number_of_ready_subscriptions();
|
||||
guard_conditions_from_waitables += waitable.get_number_of_ready_guard_conditions();
|
||||
timers_from_waitables += waitable.get_number_of_ready_timers();
|
||||
|
||||
@@ -382,11 +382,13 @@ public:
|
||||
return weak_ptr.expired();
|
||||
};
|
||||
// remove guard conditions which have been deleted
|
||||
guard_conditions_.erase(std::remove_if(guard_conditions_.begin(), guard_conditions_.end(), p));
|
||||
timers_.erase(std::remove_if(timers_.begin(), timers_.end(), p));
|
||||
clients_.erase(std::remove_if(clients_.begin(), clients_.end(), p));
|
||||
services_.erase(std::remove_if(services_.begin(), services_.end(), p));
|
||||
waitables_.erase(std::remove_if(waitables_.begin(), waitables_.end(), p));
|
||||
guard_conditions_.erase(
|
||||
std::remove_if(guard_conditions_.begin(), guard_conditions_.end(), p),
|
||||
guard_conditions_.end());
|
||||
timers_.erase(std::remove_if(timers_.begin(), timers_.end(), p), timers_.end());
|
||||
clients_.erase(std::remove_if(clients_.begin(), clients_.end(), p), clients_.end());
|
||||
services_.erase(std::remove_if(services_.begin(), services_.end(), p), services_.end());
|
||||
waitables_.erase(std::remove_if(waitables_.begin(), waitables_.end(), p), waitables_.end());
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -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>3.0.0</version>
|
||||
<version>2.2.0</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
{
|
||||
rcl_ret_t 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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,17 +47,14 @@ Duration::Duration(std::chrono::nanoseconds nanoseconds)
|
||||
rcl_duration_.nanoseconds = nanoseconds.count();
|
||||
}
|
||||
|
||||
Duration::Duration(const Duration & rhs)
|
||||
{
|
||||
rcl_duration_.nanoseconds = rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
Duration::Duration(const Duration & rhs) = default;
|
||||
|
||||
Duration::Duration(
|
||||
const builtin_interfaces::msg::Duration & duration_msg)
|
||||
{
|
||||
rcl_duration_.nanoseconds =
|
||||
static_cast<rcl_duration_value_t>(RCL_S_TO_NS(duration_msg.sec));
|
||||
rcl_duration_.nanoseconds += duration_msg.nanosec;
|
||||
RCL_S_TO_NS(static_cast<rcl_duration_value_t>(duration_msg.sec));
|
||||
rcl_duration_.nanoseconds += static_cast<rcl_duration_value_t>(duration_msg.nanosec);
|
||||
}
|
||||
|
||||
Duration::Duration(const rcl_duration_t & duration)
|
||||
@@ -69,24 +66,25 @@ Duration::Duration(const rcl_duration_t & duration)
|
||||
Duration::operator builtin_interfaces::msg::Duration() const
|
||||
{
|
||||
builtin_interfaces::msg::Duration msg_duration;
|
||||
msg_duration.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_duration_.nanoseconds));
|
||||
msg_duration.nanosec =
|
||||
static_cast<std::uint32_t>(rcl_duration_.nanoseconds % (1000 * 1000 * 1000));
|
||||
constexpr rcl_duration_value_t kDivisor = RCL_S_TO_NS(1);
|
||||
const auto result = std::div(rcl_duration_.nanoseconds, kDivisor);
|
||||
if (result.rem >= 0) {
|
||||
msg_duration.sec = static_cast<std::int32_t>(result.quot);
|
||||
msg_duration.nanosec = static_cast<std::uint32_t>(result.rem);
|
||||
} else {
|
||||
msg_duration.sec = static_cast<std::int32_t>(result.quot - 1);
|
||||
msg_duration.nanosec = static_cast<std::uint32_t>(kDivisor + result.rem);
|
||||
}
|
||||
return msg_duration;
|
||||
}
|
||||
|
||||
Duration &
|
||||
Duration::operator=(const Duration & rhs)
|
||||
{
|
||||
rcl_duration_.nanoseconds = rhs.rcl_duration_.nanoseconds;
|
||||
return *this;
|
||||
}
|
||||
Duration::operator=(const Duration & rhs) = default;
|
||||
|
||||
Duration &
|
||||
Duration::operator=(const builtin_interfaces::msg::Duration & duration_msg)
|
||||
{
|
||||
rcl_duration_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(duration_msg.sec));
|
||||
rcl_duration_.nanoseconds += duration_msg.nanosec;
|
||||
*this = Duration(duration_msg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -96,6 +94,12 @@ Duration::operator==(const rclcpp::Duration & rhs) const
|
||||
return rcl_duration_.nanoseconds == rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
|
||||
bool
|
||||
Duration::operator!=(const rclcpp::Duration & rhs) const
|
||||
{
|
||||
return rcl_duration_.nanoseconds != rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
|
||||
bool
|
||||
Duration::operator<(const rclcpp::Duration & rhs) const
|
||||
{
|
||||
@@ -230,6 +234,10 @@ Duration::seconds() const
|
||||
rmw_time_t
|
||||
Duration::to_rmw_time() const
|
||||
{
|
||||
if (rcl_duration_.nanoseconds < 0) {
|
||||
throw std::runtime_error("rmw_time_t cannot be negative");
|
||||
}
|
||||
|
||||
// reuse conversion logic from msg creation
|
||||
builtin_interfaces::msg::Duration msg = *this;
|
||||
rmw_time_t result;
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
#include "rcutils/logging_macros.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
using rclcpp::exceptions::throw_from_rcl_error;
|
||||
using rclcpp::AnyExecutable;
|
||||
using rclcpp::Executor;
|
||||
@@ -214,21 +212,8 @@ Executor::spin_node_some(std::shared_ptr<rclcpp::Node> node)
|
||||
this->spin_node_some(node->get_node_base_interface());
|
||||
}
|
||||
|
||||
void Executor::spin_some(std::chrono::nanoseconds max_duration)
|
||||
{
|
||||
return this->spin_some_impl(max_duration, false);
|
||||
}
|
||||
|
||||
void Executor::spin_all(std::chrono::nanoseconds max_duration)
|
||||
{
|
||||
if (max_duration <= 0ns) {
|
||||
throw std::invalid_argument("max_duration must be positive");
|
||||
}
|
||||
return this->spin_some_impl(max_duration, true);
|
||||
}
|
||||
|
||||
void
|
||||
Executor::spin_some_impl(std::chrono::nanoseconds max_duration, bool exhaustive)
|
||||
Executor::spin_some(std::chrono::nanoseconds max_duration)
|
||||
{
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
auto max_duration_not_elapsed = [max_duration, start]() {
|
||||
@@ -247,20 +232,14 @@ Executor::spin_some_impl(std::chrono::nanoseconds max_duration, bool exhaustive)
|
||||
throw std::runtime_error("spin_some() called while already spinning");
|
||||
}
|
||||
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
|
||||
bool work_available = false;
|
||||
// non-blocking call to pre-load all available work
|
||||
wait_for_work(std::chrono::milliseconds::zero());
|
||||
while (rclcpp::ok(context_) && spinning.load() && max_duration_not_elapsed()) {
|
||||
AnyExecutable any_exec;
|
||||
if (!work_available) {
|
||||
wait_for_work(std::chrono::milliseconds::zero());
|
||||
}
|
||||
if (get_next_ready_executable(any_exec)) {
|
||||
execute_any_executable(any_exec);
|
||||
work_available = true;
|
||||
} else {
|
||||
if (!work_available || !exhaustive) {
|
||||
break;
|
||||
}
|
||||
work_available = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ __lockless_has_parameter(
|
||||
// see https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
|
||||
RCLCPP_LOCAL
|
||||
bool
|
||||
__are_doubles_equal(double x, double y, size_t ulp = 100)
|
||||
__are_doubles_equal(double x, double y, double ulp = 100.0)
|
||||
{
|
||||
return std::abs(x - y) <= std::numeric_limits<double>::epsilon() * std::abs(x + y) * ulp;
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ NodeOptions::parameter_overrides(const std::vector<rclcpp::Parameter> & paramete
|
||||
bool
|
||||
NodeOptions::use_global_arguments() const
|
||||
{
|
||||
return this->node_options_->use_global_arguments;
|
||||
return this->use_global_arguments_;
|
||||
}
|
||||
|
||||
NodeOptions &
|
||||
@@ -338,7 +338,7 @@ NodeOptions::get_domain_id_from_env() const
|
||||
_dupenv_s(&ros_domain_id, &ros_domain_id_size, env_var);
|
||||
#endif
|
||||
if (ros_domain_id) {
|
||||
uint32_t number = strtoul(ros_domain_id, NULL, 0);
|
||||
uint32_t number = static_cast<uint32_t>(strtoul(ros_domain_id, NULL, 0));
|
||||
if (number == (std::numeric_limits<uint32_t>::max)()) {
|
||||
#ifdef _WIN32
|
||||
// free the ros_domain_id before throwing, if getenv was used on Windows
|
||||
|
||||
@@ -63,17 +63,13 @@ Time::Time(int64_t nanoseconds, rcl_clock_type_t clock_type)
|
||||
rcl_time_.nanoseconds = nanoseconds;
|
||||
}
|
||||
|
||||
Time::Time(const Time & rhs)
|
||||
: rcl_time_(rhs.rcl_time_)
|
||||
{
|
||||
rcl_time_.nanoseconds = rhs.rcl_time_.nanoseconds;
|
||||
}
|
||||
Time::Time(const Time & rhs) = default;
|
||||
|
||||
Time::Time(
|
||||
const builtin_interfaces::msg::Time & time_msg,
|
||||
rcl_clock_type_t ros_time)
|
||||
rcl_clock_type_t clock_type)
|
||||
: rcl_time_(init_time_point(clock_type))
|
||||
{
|
||||
rcl_time_ = init_time_point(ros_time);
|
||||
if (time_msg.sec < 0) {
|
||||
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
|
||||
}
|
||||
@@ -95,31 +91,25 @@ Time::~Time()
|
||||
Time::operator builtin_interfaces::msg::Time() const
|
||||
{
|
||||
builtin_interfaces::msg::Time msg_time;
|
||||
msg_time.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_time_.nanoseconds));
|
||||
msg_time.nanosec = static_cast<std::uint32_t>(rcl_time_.nanoseconds % (1000 * 1000 * 1000));
|
||||
constexpr rcl_time_point_value_t kRemainder = RCL_S_TO_NS(1);
|
||||
const auto result = std::div(rcl_time_.nanoseconds, kRemainder);
|
||||
if (result.rem >= 0) {
|
||||
msg_time.sec = static_cast<std::int32_t>(result.quot);
|
||||
msg_time.nanosec = static_cast<std::uint32_t>(result.rem);
|
||||
} else {
|
||||
msg_time.sec = static_cast<std::int32_t>(result.quot - 1);
|
||||
msg_time.nanosec = static_cast<std::uint32_t>(kRemainder + result.rem);
|
||||
}
|
||||
return msg_time;
|
||||
}
|
||||
|
||||
Time &
|
||||
Time::operator=(const Time & rhs)
|
||||
{
|
||||
rcl_time_ = rhs.rcl_time_;
|
||||
return *this;
|
||||
}
|
||||
Time::operator=(const Time & rhs) = default;
|
||||
|
||||
Time &
|
||||
Time::operator=(const builtin_interfaces::msg::Time & time_msg)
|
||||
{
|
||||
if (time_msg.sec < 0) {
|
||||
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
|
||||
}
|
||||
|
||||
|
||||
rcl_clock_type_t ros_time = RCL_ROS_TIME;
|
||||
rcl_time_ = init_time_point(ros_time); // TODO(tfoote) hard coded ROS here
|
||||
|
||||
rcl_time_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(time_msg.sec));
|
||||
rcl_time_.nanoseconds += time_msg.nanosec;
|
||||
*this = Time(time_msg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ TEST_F(TestMultiThreadedExecutor, timer_over_take) {
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(last_mutex);
|
||||
double diff = std::abs((now - last).nanoseconds()) / 1.0e9;
|
||||
double diff = static_cast<double>(std::abs((now - last).nanoseconds())) / 1.0e9;
|
||||
last = now;
|
||||
|
||||
if (diff < PERIOD - TOLERANCE) {
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include "node_interfaces/node_wrapper.hpp"
|
||||
#include "rclcpp/create_timer.hpp"
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "node_interfaces/node_wrapper.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
@@ -61,58 +61,3 @@ TEST(TestCreateTimer, call_with_node_wrapper_compiles)
|
||||
[]() {});
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
TEST(TestCreateTimer, call_wall_timer_with_bad_arguments)
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
NodeWrapper node("test_create_wall_timers_with_bad_arguments");
|
||||
auto callback = []() {};
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr;
|
||||
auto node_interface =
|
||||
rclcpp::node_interfaces::get_node_base_interface(node).get();
|
||||
auto timers_interface =
|
||||
rclcpp::node_interfaces::get_node_timers_interface(node).get();
|
||||
|
||||
// Negative period
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_wall_timer(-1ms, callback, group, node_interface, timers_interface),
|
||||
std::invalid_argument);
|
||||
|
||||
// Very negative period
|
||||
constexpr auto nanoseconds_min = std::chrono::nanoseconds::min();
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_wall_timer(
|
||||
nanoseconds_min, callback, group, node_interface, timers_interface),
|
||||
std::invalid_argument);
|
||||
|
||||
// Period must be less than nanoseconds::max()
|
||||
constexpr auto nanoseconds_max = std::chrono::nanoseconds::min();
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_wall_timer(
|
||||
nanoseconds_max, callback, group, node_interface, timers_interface),
|
||||
std::invalid_argument);
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
rclcpp::create_wall_timer(
|
||||
nanoseconds_max - 1us, callback, group, node_interface, timers_interface));
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
rclcpp::create_wall_timer(0ms, callback, group, node_interface, timers_interface));
|
||||
|
||||
// Period must be less than nanoseconds::max()
|
||||
constexpr auto hours_max = std::chrono::hours::max();
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_wall_timer(hours_max, callback, group, node_interface, timers_interface),
|
||||
std::invalid_argument);
|
||||
|
||||
// node_interface is null
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_wall_timer(1ms, callback, group, nullptr, timers_interface),
|
||||
std::invalid_argument);
|
||||
|
||||
// timers_interface is null
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_wall_timer(1ms, callback, group, node_interface, nullptr),
|
||||
std::invalid_argument);
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
@@ -32,11 +32,7 @@ class TestDuration : public ::testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
// TEST(TestDuration, conversions) {
|
||||
// TODO(tfoote) Implement conversion methods
|
||||
// }
|
||||
|
||||
TEST(TestDuration, operators) {
|
||||
TEST_F(TestDuration, operators) {
|
||||
rclcpp::Duration old(1, 0);
|
||||
rclcpp::Duration young(2, 0);
|
||||
|
||||
@@ -45,6 +41,7 @@ TEST(TestDuration, operators) {
|
||||
EXPECT_TRUE(old <= young);
|
||||
EXPECT_TRUE(young >= old);
|
||||
EXPECT_FALSE(young == old);
|
||||
EXPECT_TRUE(young != old);
|
||||
|
||||
rclcpp::Duration add = old + young;
|
||||
EXPECT_EQ(add.nanoseconds(), old.nanoseconds() + young.nanoseconds());
|
||||
@@ -67,7 +64,7 @@ TEST(TestDuration, operators) {
|
||||
EXPECT_TRUE(time == assignment_op_duration);
|
||||
}
|
||||
|
||||
TEST(TestDuration, chrono_overloads) {
|
||||
TEST_F(TestDuration, chrono_overloads) {
|
||||
int64_t ns = 123456789l;
|
||||
auto chrono_ns = std::chrono::nanoseconds(ns);
|
||||
auto d1 = rclcpp::Duration(ns);
|
||||
@@ -86,7 +83,7 @@ TEST(TestDuration, chrono_overloads) {
|
||||
EXPECT_EQ(chrono_float_seconds, d5.to_chrono<decltype(chrono_float_seconds)>());
|
||||
}
|
||||
|
||||
TEST(TestDuration, overflows) {
|
||||
TEST_F(TestDuration, overflows) {
|
||||
rclcpp::Duration max(std::numeric_limits<rcl_duration_value_t>::max());
|
||||
rclcpp::Duration min(std::numeric_limits<rcl_duration_value_t>::min());
|
||||
|
||||
@@ -107,7 +104,7 @@ TEST(TestDuration, overflows) {
|
||||
EXPECT_THROW(base_d_neg * 4, std::underflow_error);
|
||||
}
|
||||
|
||||
TEST(TestDuration, negative_duration) {
|
||||
TEST_F(TestDuration, negative_duration) {
|
||||
rclcpp::Duration assignable_duration = rclcpp::Duration(0) - rclcpp::Duration(5, 0);
|
||||
|
||||
{
|
||||
@@ -130,7 +127,7 @@ TEST(TestDuration, negative_duration) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestDuration, maximum_duration) {
|
||||
TEST_F(TestDuration, maximum_duration) {
|
||||
rclcpp::Duration max_duration = rclcpp::Duration::max();
|
||||
rclcpp::Duration max(std::numeric_limits<int32_t>::max(), 999999999);
|
||||
|
||||
@@ -138,18 +135,105 @@ TEST(TestDuration, maximum_duration) {
|
||||
}
|
||||
|
||||
static const int64_t HALF_SEC_IN_NS = 500 * 1000 * 1000;
|
||||
static const int64_t ONE_SEC_IN_NS = 1000 * 1000 * 1000;
|
||||
static const int64_t ONE_AND_HALF_SEC_IN_NS = 3 * HALF_SEC_IN_NS;
|
||||
|
||||
TEST(TestDuration, from_seconds) {
|
||||
TEST_F(TestDuration, from_seconds) {
|
||||
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration::from_seconds(0.0));
|
||||
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration::from_seconds(0));
|
||||
EXPECT_EQ(rclcpp::Duration(1, HALF_SEC_IN_NS), rclcpp::Duration::from_seconds(1.5));
|
||||
EXPECT_EQ(rclcpp::Duration(-ONE_AND_HALF_SEC_IN_NS), rclcpp::Duration::from_seconds(-1.5));
|
||||
}
|
||||
|
||||
TEST(TestDuration, std_chrono_constructors) {
|
||||
TEST_F(TestDuration, std_chrono_constructors) {
|
||||
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration(0.0s));
|
||||
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration(0s));
|
||||
EXPECT_EQ(rclcpp::Duration(1, HALF_SEC_IN_NS), rclcpp::Duration(1.5s));
|
||||
EXPECT_EQ(rclcpp::Duration(-1, 0), rclcpp::Duration(-1s));
|
||||
}
|
||||
|
||||
TEST_F(TestDuration, conversions) {
|
||||
{
|
||||
const rclcpp::Duration duration(HALF_SEC_IN_NS);
|
||||
const auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, 0);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), HALF_SEC_IN_NS);
|
||||
|
||||
const auto rmw_time = duration.to_rmw_time();
|
||||
EXPECT_EQ(rmw_time.sec, 0u);
|
||||
EXPECT_EQ(rmw_time.nsec, static_cast<uint64_t>(HALF_SEC_IN_NS));
|
||||
|
||||
const auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Duration duration(ONE_SEC_IN_NS);
|
||||
const auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, 1);
|
||||
EXPECT_EQ(duration_msg.nanosec, 0u);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), ONE_SEC_IN_NS);
|
||||
|
||||
const auto rmw_time = duration.to_rmw_time();
|
||||
EXPECT_EQ(rmw_time.sec, 1u);
|
||||
EXPECT_EQ(rmw_time.nsec, 0u);
|
||||
|
||||
const auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), ONE_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Duration duration(ONE_AND_HALF_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, 1);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), ONE_AND_HALF_SEC_IN_NS);
|
||||
|
||||
auto rmw_time = duration.to_rmw_time();
|
||||
EXPECT_EQ(rmw_time.sec, 1u);
|
||||
EXPECT_EQ(rmw_time.nsec, static_cast<uint64_t>(HALF_SEC_IN_NS));
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), ONE_AND_HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
rclcpp::Duration duration(-HALF_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, -1);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -HALF_SEC_IN_NS);
|
||||
|
||||
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), -HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
rclcpp::Duration duration(-ONE_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, -1);
|
||||
EXPECT_EQ(duration_msg.nanosec, 0u);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -ONE_SEC_IN_NS);
|
||||
|
||||
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), -ONE_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
rclcpp::Duration duration(-ONE_AND_HALF_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, -2);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -ONE_AND_HALF_SEC_IN_NS);
|
||||
|
||||
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), -ONE_AND_HALF_SEC_IN_NS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,133 +67,3 @@ TEST_F(TestExecutors, addTemporaryNode) {
|
||||
executor.add_node(std::make_shared<rclcpp::Node>("temporary_node"));
|
||||
EXPECT_NO_THROW(executor.spin_some());
|
||||
}
|
||||
|
||||
// Make sure that the spin_until_future_complete works correctly with std::future
|
||||
TEST_F(TestExecutors, testSpinUntilFutureComplete) {
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
std::future<void> future;
|
||||
rclcpp::FutureReturnCode ret;
|
||||
|
||||
// test success
|
||||
future = std::async(
|
||||
[]() {
|
||||
return;
|
||||
});
|
||||
ret = executor.spin_until_future_complete(future, 1s);
|
||||
EXPECT_EQ(rclcpp::FutureReturnCode::SUCCESS, ret);
|
||||
|
||||
// test timeout
|
||||
future = std::async(
|
||||
[]() {
|
||||
std::this_thread::sleep_for(1s);
|
||||
return;
|
||||
});
|
||||
ret = executor.spin_until_future_complete(future, 100ms);
|
||||
EXPECT_EQ(rclcpp::FutureReturnCode::TIMEOUT, ret);
|
||||
}
|
||||
|
||||
// Make sure that the spin_until_future_complete works correctly with std::shared_future
|
||||
TEST_F(TestExecutors, testSpinUntilFutureCompleteSharedFuture) {
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
std::future<void> future;
|
||||
rclcpp::FutureReturnCode ret;
|
||||
|
||||
// test success
|
||||
future = std::async(
|
||||
[]() {
|
||||
return;
|
||||
});
|
||||
ret = executor.spin_until_future_complete(future.share(), 1s);
|
||||
EXPECT_EQ(rclcpp::FutureReturnCode::SUCCESS, ret);
|
||||
|
||||
// test timeout
|
||||
future = std::async(
|
||||
[]() {
|
||||
std::this_thread::sleep_for(1s);
|
||||
return;
|
||||
});
|
||||
ret = executor.spin_until_future_complete(future.share(), 100ms);
|
||||
EXPECT_EQ(rclcpp::FutureReturnCode::TIMEOUT, ret);
|
||||
}
|
||||
|
||||
class TestWaitable : public rclcpp::Waitable
|
||||
{
|
||||
public:
|
||||
TestWaitable()
|
||||
{
|
||||
rcl_guard_condition_options_t guard_condition_options =
|
||||
rcl_guard_condition_get_default_options();
|
||||
|
||||
gc_ = rcl_get_zero_initialized_guard_condition();
|
||||
rcl_ret_t ret = rcl_guard_condition_init(
|
||||
&gc_,
|
||||
rclcpp::contexts::get_global_default_context()->get_rcl_context().get(),
|
||||
guard_condition_options);
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
add_to_wait_set(rcl_wait_set_t * wait_set) override
|
||||
{
|
||||
rcl_ret_t ret = rcl_wait_set_add_guard_condition(wait_set, &gc_, NULL);
|
||||
if (RCL_RET_OK != ret) {
|
||||
return false;
|
||||
}
|
||||
ret = rcl_trigger_guard_condition(&gc_);
|
||||
return RCL_RET_OK == ret;
|
||||
}
|
||||
|
||||
bool
|
||||
is_ready(rcl_wait_set_t * wait_set) override
|
||||
{
|
||||
(void)wait_set;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
execute() override
|
||||
{
|
||||
count_++;
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
|
||||
size_t
|
||||
get_number_of_ready_guard_conditions() override {return 1;}
|
||||
|
||||
size_t
|
||||
get_count()
|
||||
{
|
||||
return count_;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t count_ = 0;
|
||||
rcl_guard_condition_t gc_;
|
||||
};
|
||||
|
||||
TEST_F(TestExecutors, testSpinAllvsSpinSome) {
|
||||
{
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
auto waitable_interfaces = node->get_node_waitables_interface();
|
||||
auto my_waitable = std::make_shared<TestWaitable>();
|
||||
waitable_interfaces->add_waitable(my_waitable, nullptr);
|
||||
executor.add_node(node);
|
||||
executor.spin_all(1s);
|
||||
executor.remove_node(node);
|
||||
EXPECT_GT(my_waitable->get_count(), 1u);
|
||||
waitable_interfaces->remove_waitable(my_waitable, nullptr);
|
||||
}
|
||||
{
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
auto waitable_interfaces = node->get_node_waitables_interface();
|
||||
auto my_waitable = std::make_shared<TestWaitable>();
|
||||
waitable_interfaces->add_waitable(my_waitable, nullptr);
|
||||
executor.add_node(node);
|
||||
executor.spin_some(1s);
|
||||
executor.remove_node(node);
|
||||
EXPECT_EQ(my_waitable->get_count(), 1u);
|
||||
waitable_interfaces->remove_waitable(my_waitable, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +105,38 @@ TEST(TestNodeOptions, bad_ros_args) {
|
||||
rclcpp::exceptions::UnknownROSArgsError);
|
||||
}
|
||||
|
||||
TEST(TestNodeOptions, use_global_arguments) {
|
||||
{
|
||||
auto options = rclcpp::NodeOptions();
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
|
||||
{
|
||||
auto options = rclcpp::NodeOptions().use_global_arguments(false);
|
||||
EXPECT_FALSE(options.use_global_arguments());
|
||||
EXPECT_FALSE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
|
||||
{
|
||||
auto options = rclcpp::NodeOptions().use_global_arguments(true);
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
|
||||
{
|
||||
auto options = rclcpp::NodeOptions();
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
options.use_global_arguments(false);
|
||||
EXPECT_FALSE(options.use_global_arguments());
|
||||
EXPECT_FALSE(options.get_rcl_node_options()->use_global_arguments);
|
||||
options.use_global_arguments(true);
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestNodeOptions, enable_rosout) {
|
||||
{
|
||||
auto options = rclcpp::NodeOptions();
|
||||
|
||||
@@ -32,7 +32,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestParameter, not_set_variant) {
|
||||
TEST_F(TestParameter, not_set_variant) {
|
||||
// Direct instantiation
|
||||
rclcpp::Parameter not_set_variant;
|
||||
EXPECT_EQ(rclcpp::PARAMETER_NOT_SET, not_set_variant.get_type());
|
||||
@@ -58,7 +58,7 @@ TEST(TestParameter, not_set_variant) {
|
||||
rclcpp::Parameter::from_parameter_msg(not_set_param).get_type());
|
||||
}
|
||||
|
||||
TEST(TestParameter, bool_variant) {
|
||||
TEST_F(TestParameter, bool_variant) {
|
||||
// Direct instantiation
|
||||
rclcpp::Parameter bool_variant_true("bool_param", true);
|
||||
EXPECT_EQ("bool_param", bool_variant_true.get_name());
|
||||
@@ -116,7 +116,7 @@ TEST(TestParameter, bool_variant) {
|
||||
bool_variant_false.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, integer_variant) {
|
||||
TEST_F(TestParameter, integer_variant) {
|
||||
const int TEST_VALUE {42};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -164,7 +164,7 @@ TEST(TestParameter, integer_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, long_integer_variant) {
|
||||
TEST_F(TestParameter, long_integer_variant) {
|
||||
const int64_t TEST_VALUE {std::numeric_limits<int64_t>::max()};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -212,7 +212,7 @@ TEST(TestParameter, long_integer_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, float_variant) {
|
||||
TEST_F(TestParameter, float_variant) {
|
||||
const float TEST_VALUE {42.0f};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -260,7 +260,7 @@ TEST(TestParameter, float_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, double_variant) {
|
||||
TEST_F(TestParameter, double_variant) {
|
||||
const double TEST_VALUE {-42.1};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -308,7 +308,7 @@ TEST(TestParameter, double_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, string_variant) {
|
||||
TEST_F(TestParameter, string_variant) {
|
||||
const std::string TEST_VALUE {"ROS2"};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -354,7 +354,7 @@ TEST(TestParameter, string_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, byte_array_variant) {
|
||||
TEST_F(TestParameter, byte_array_variant) {
|
||||
const std::vector<uint8_t> TEST_VALUE {0x52, 0x4f, 0x53, 0x32};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -402,7 +402,7 @@ TEST(TestParameter, byte_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, bool_array_variant) {
|
||||
TEST_F(TestParameter, bool_array_variant) {
|
||||
const std::vector<bool> TEST_VALUE {false, true, true, false, false, true};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -450,7 +450,7 @@ TEST(TestParameter, bool_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, integer_array_variant) {
|
||||
TEST_F(TestParameter, integer_array_variant) {
|
||||
const std::vector<int> TEST_VALUE
|
||||
{42, -99, std::numeric_limits<int>::max(), std::numeric_limits<int>::lowest(), 0};
|
||||
|
||||
@@ -529,7 +529,7 @@ TEST(TestParameter, integer_array_variant) {
|
||||
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY);
|
||||
}
|
||||
|
||||
TEST(TestParameter, long_integer_array_variant) {
|
||||
TEST_F(TestParameter, long_integer_array_variant) {
|
||||
const std::vector<int64_t> TEST_VALUE
|
||||
{42, -99, std::numeric_limits<int64_t>::max(), std::numeric_limits<int64_t>::lowest(), 0};
|
||||
|
||||
@@ -583,7 +583,7 @@ TEST(TestParameter, long_integer_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, float_array_variant) {
|
||||
TEST_F(TestParameter, float_array_variant) {
|
||||
const std::vector<float> TEST_VALUE
|
||||
{42.1f, -99.1f, std::numeric_limits<float>::max(), std::numeric_limits<float>::lowest(), 0.1f};
|
||||
|
||||
@@ -662,7 +662,7 @@ TEST(TestParameter, float_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, double_array_variant) {
|
||||
TEST_F(TestParameter, double_array_variant) {
|
||||
const std::vector<double> TEST_VALUE
|
||||
{42.1, -99.1, std::numeric_limits<double>::max(), std::numeric_limits<double>::lowest(), 0.1};
|
||||
|
||||
@@ -716,7 +716,7 @@ TEST(TestParameter, double_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, string_array_variant) {
|
||||
TEST_F(TestParameter, string_array_variant) {
|
||||
const std::vector<std::string> TEST_VALUE {"R", "O", "S2"};
|
||||
|
||||
// Direct instantiation
|
||||
|
||||
@@ -24,27 +24,92 @@
|
||||
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
|
||||
using test_msgs::msg::Empty;
|
||||
|
||||
/**
|
||||
* Parameterized test.
|
||||
* The first param are the NodeOptions used to create the nodes.
|
||||
* The second param are the expect intraprocess count results.
|
||||
*/
|
||||
struct TestParameters
|
||||
namespace
|
||||
{
|
||||
rclcpp::NodeOptions node_options[2];
|
||||
uint64_t intraprocess_count_results[2];
|
||||
std::string description;
|
||||
|
||||
|
||||
template<typename ... Ts>
|
||||
class NodeCreationPolicy
|
||||
{
|
||||
public:
|
||||
rclcpp::NodeOptions & node_options()
|
||||
{
|
||||
return options_;
|
||||
}
|
||||
|
||||
private:
|
||||
rclcpp::NodeOptions options_;
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, const TestParameters & params)
|
||||
template<typename T, typename ... Ts>
|
||||
class NodeCreationPolicy<T, Ts...>
|
||||
{
|
||||
out << params.description;
|
||||
return out;
|
||||
}
|
||||
public:
|
||||
NodeCreationPolicy()
|
||||
{
|
||||
gather<T, Ts...>(options_);
|
||||
}
|
||||
|
||||
class TestPublisherSubscriptionCount : public ::testing::TestWithParam<TestParameters>
|
||||
rclcpp::NodeOptions & node_options()
|
||||
{
|
||||
return options_;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename U>
|
||||
static rclcpp::NodeOptions &
|
||||
gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
return U::gather(options);
|
||||
}
|
||||
|
||||
template<typename U, typename V, typename ... Ws>
|
||||
static rclcpp::NodeOptions &
|
||||
gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
return gather<V, Ws...>(U::gather(options));
|
||||
}
|
||||
|
||||
rclcpp::NodeOptions options_;
|
||||
};
|
||||
|
||||
template<bool value>
|
||||
struct ShouldUseIntraprocess
|
||||
{
|
||||
static rclcpp::NodeOptions & gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
return options.use_intra_process_comms(value);
|
||||
}
|
||||
};
|
||||
|
||||
using UseIntraprocess = ShouldUseIntraprocess<true>;
|
||||
using DoNotUseIntraprocess = ShouldUseIntraprocess<false>;
|
||||
|
||||
struct UseCustomContext
|
||||
{
|
||||
static rclcpp::NodeOptions & gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
auto context = rclcpp::Context::make_shared();
|
||||
context->init(0, nullptr);
|
||||
return options.context(context);
|
||||
}
|
||||
};
|
||||
|
||||
struct PrintTestDescription
|
||||
{
|
||||
template<typename T>
|
||||
static std::string GetName(int i)
|
||||
{
|
||||
static_cast<void>(i);
|
||||
return T::description;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
template<typename TestDescription>
|
||||
class TestPublisherSubscriptionCount : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
@@ -57,126 +122,128 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetUp() {}
|
||||
static void OnMessage(const test_msgs::msg::Empty::SharedPtr msg)
|
||||
{
|
||||
(void)msg;
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::chrono::milliseconds offset;
|
||||
std::chrono::milliseconds offset{2000};
|
||||
};
|
||||
|
||||
std::chrono::milliseconds TestPublisherSubscriptionCount::offset = std::chrono::milliseconds(2000);
|
||||
|
||||
void OnMessage(const test_msgs::msg::Empty::SharedPtr msg)
|
||||
/* Testing publisher subscription count api and internal process subscription count.
|
||||
* Two subscriptions in the same topic, both using intraprocess comm.
|
||||
*/
|
||||
struct TwoSubscriptionsIntraprocessComm
|
||||
{
|
||||
(void)msg;
|
||||
}
|
||||
static constexpr const char * description =
|
||||
"two_subscriptions_intraprocess_comm";
|
||||
using FirstNodeCreationPolicy = NodeCreationPolicy<UseIntraprocess>;
|
||||
using SecondNodeCreationPolicy = NodeCreationPolicy<UseIntraprocess>;
|
||||
|
||||
TEST_P(TestPublisherSubscriptionCount, increasing_and_decreasing_counts)
|
||||
static constexpr bool first_node_talks_intraprocess{true};
|
||||
static constexpr bool both_nodes_talk_intraprocess{true};
|
||||
};
|
||||
|
||||
/* Testing publisher subscription count api and internal process subscription count.
|
||||
* Two subscriptions, one using intra-process comm and the other not using it.
|
||||
*/
|
||||
struct TwoSubscriptionsOneIntraprocessOneNot
|
||||
{
|
||||
TestParameters parameters = GetParam();
|
||||
static constexpr const char * description =
|
||||
"two_subscriptions_one_intraprocess_one_not";
|
||||
using FirstNodeCreationPolicy = NodeCreationPolicy<UseIntraprocess>;
|
||||
using SecondNodeCreationPolicy = NodeCreationPolicy<>;
|
||||
|
||||
static constexpr bool first_node_talks_intraprocess{true};
|
||||
static constexpr bool both_nodes_talk_intraprocess{false};
|
||||
};
|
||||
|
||||
/* Testing publisher subscription count api and internal process subscription count.
|
||||
* Two contexts, both using intra-process.
|
||||
*/
|
||||
struct TwoSubscriptionsInTwoContextsWithIntraprocessComm
|
||||
{
|
||||
static constexpr const char * description =
|
||||
"two_subscriptions_in_two_contexts_with_intraprocess_comm";
|
||||
using FirstNodeCreationPolicy = NodeCreationPolicy<UseIntraprocess>;
|
||||
using SecondNodeCreationPolicy = NodeCreationPolicy<UseCustomContext, UseIntraprocess>;
|
||||
|
||||
static constexpr bool first_node_talks_intraprocess{true};
|
||||
static constexpr bool both_nodes_talk_intraprocess{false};
|
||||
};
|
||||
|
||||
/* Testing publisher subscription count api and internal process subscription count.
|
||||
* Two contexts, both of them not using intra-process comm.
|
||||
*/
|
||||
struct TwoSubscriptionsInTwoContextsWithoutIntraprocessComm
|
||||
{
|
||||
static constexpr const char * description =
|
||||
"two_subscriptions_in_two_contexts_without_intraprocess_comm";
|
||||
using FirstNodeCreationPolicy = NodeCreationPolicy<>;
|
||||
using SecondNodeCreationPolicy = NodeCreationPolicy<UseCustomContext>;
|
||||
|
||||
static constexpr bool first_node_talks_intraprocess{false};
|
||||
static constexpr bool both_nodes_talk_intraprocess{false};
|
||||
};
|
||||
|
||||
using AllTestDescriptions = ::testing::Types<
|
||||
TwoSubscriptionsIntraprocessComm,
|
||||
TwoSubscriptionsOneIntraprocessOneNot,
|
||||
TwoSubscriptionsInTwoContextsWithIntraprocessComm,
|
||||
TwoSubscriptionsInTwoContextsWithoutIntraprocessComm
|
||||
>;
|
||||
TYPED_TEST_CASE(TestPublisherSubscriptionCount, AllTestDescriptions, PrintTestDescription);
|
||||
|
||||
|
||||
using test_msgs::msg::Empty;
|
||||
|
||||
TYPED_TEST(TestPublisherSubscriptionCount, increasing_and_decreasing_counts)
|
||||
{
|
||||
using TestDescription = TypeParam;
|
||||
typename TestDescription::FirstNodeCreationPolicy my_node_creation_policy;
|
||||
rclcpp::Node::SharedPtr node = std::make_shared<rclcpp::Node>(
|
||||
"my_node",
|
||||
"/ns",
|
||||
parameters.node_options[0]);
|
||||
my_node_creation_policy.node_options());
|
||||
auto publisher = node->create_publisher<Empty>("/topic", 10);
|
||||
|
||||
EXPECT_EQ(publisher->get_subscription_count(), 0u);
|
||||
EXPECT_EQ(publisher->get_intra_process_subscription_count(), 0u);
|
||||
{
|
||||
auto sub = node->create_subscription<Empty>("/topic", 10, &OnMessage);
|
||||
rclcpp::sleep_for(offset);
|
||||
auto sub = node->create_subscription<Empty>(
|
||||
"/topic", 10, &TestPublisherSubscriptionCount<TestDescription>::OnMessage);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(publisher->get_subscription_count(), 1u);
|
||||
EXPECT_EQ(
|
||||
publisher->get_intra_process_subscription_count(),
|
||||
parameters.intraprocess_count_results[0]);
|
||||
(TestDescription::first_node_talks_intraprocess ? 1u : 0u));
|
||||
{
|
||||
typename TestDescription::SecondNodeCreationPolicy another_node_creation_policy;
|
||||
rclcpp::Node::SharedPtr another_node = std::make_shared<rclcpp::Node>(
|
||||
"another_node",
|
||||
"/ns",
|
||||
parameters.node_options[1]);
|
||||
auto another_sub =
|
||||
another_node->create_subscription<Empty>("/topic", 10, &OnMessage);
|
||||
another_node_creation_policy.node_options());
|
||||
auto another_sub = another_node->create_subscription<Empty>(
|
||||
"/topic", 10, &TestPublisherSubscriptionCount<TestDescription>::OnMessage);
|
||||
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(publisher->get_subscription_count(), 2u);
|
||||
EXPECT_EQ(
|
||||
publisher->get_intra_process_subscription_count(),
|
||||
parameters.intraprocess_count_results[1]);
|
||||
(TestDescription::first_node_talks_intraprocess ? 1u : 0u) +
|
||||
(TestDescription::both_nodes_talk_intraprocess ? 1u : 0u));
|
||||
}
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(publisher->get_subscription_count(), 1u);
|
||||
EXPECT_EQ(
|
||||
publisher->get_intra_process_subscription_count(),
|
||||
parameters.intraprocess_count_results[0]);
|
||||
(TestDescription::first_node_talks_intraprocess ? 1u : 0u));
|
||||
}
|
||||
/**
|
||||
* Counts should be zero here, as all are subscriptions are out of scope.
|
||||
* Subscriptions count checking is always preceeded with an sleep, as random failures had been
|
||||
* detected without it. */
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(publisher->get_subscription_count(), 0u);
|
||||
EXPECT_EQ(publisher->get_intra_process_subscription_count(), 0u);
|
||||
}
|
||||
|
||||
auto get_new_context()
|
||||
{
|
||||
auto context = rclcpp::Context::make_shared();
|
||||
context->init(0, nullptr);
|
||||
return context;
|
||||
}
|
||||
|
||||
TestParameters parameters[] = {
|
||||
/*
|
||||
Testing publisher subscription count api and internal process subscription count.
|
||||
Two subscriptions in the same topic, both using intraprocess comm.
|
||||
*/
|
||||
{
|
||||
{
|
||||
rclcpp::NodeOptions().use_intra_process_comms(true),
|
||||
rclcpp::NodeOptions().use_intra_process_comms(true)
|
||||
},
|
||||
{1u, 2u},
|
||||
"two_subscriptions_intraprocess_comm"
|
||||
},
|
||||
/*
|
||||
Testing publisher subscription count api and internal process subscription count.
|
||||
Two subscriptions, one using intra-process comm and the other not using it.
|
||||
*/
|
||||
{
|
||||
{
|
||||
rclcpp::NodeOptions().use_intra_process_comms(true),
|
||||
rclcpp::NodeOptions().use_intra_process_comms(false)
|
||||
},
|
||||
{1u, 1u},
|
||||
"two_subscriptions_one_intraprocess_one_not"
|
||||
},
|
||||
/*
|
||||
Testing publisher subscription count api and internal process subscription count.
|
||||
Two contexts, both using intra-process.
|
||||
*/
|
||||
{
|
||||
{
|
||||
rclcpp::NodeOptions().use_intra_process_comms(true),
|
||||
rclcpp::NodeOptions().context(get_new_context()).use_intra_process_comms(true)
|
||||
},
|
||||
{1u, 1u},
|
||||
"two_subscriptions_in_two_contexts_with_intraprocess_comm"
|
||||
},
|
||||
/*
|
||||
Testing publisher subscription count api and internal process subscription count.
|
||||
Two contexts, both of them not using intra-process comm.
|
||||
*/
|
||||
{
|
||||
{
|
||||
rclcpp::NodeOptions().use_intra_process_comms(false),
|
||||
rclcpp::NodeOptions().context(get_new_context()).use_intra_process_comms(false)
|
||||
},
|
||||
{0u, 0u},
|
||||
"two_subscriptions_in_two_contexts_without_intraprocess_comm"
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
TestWithDifferentNodeOptions, TestPublisherSubscriptionCount,
|
||||
::testing::ValuesIn(parameters),
|
||||
::testing::PrintToStringParamName());
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
// Copyright 2019-2020 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.
|
||||
@@ -23,21 +23,79 @@
|
||||
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
|
||||
using test_msgs::msg::Empty;
|
||||
|
||||
struct TestParameters
|
||||
namespace
|
||||
{
|
||||
rclcpp::NodeOptions node_options;
|
||||
std::string description;
|
||||
|
||||
template<typename ... Ts>
|
||||
class NodeCreationPolicy
|
||||
{
|
||||
public:
|
||||
rclcpp::NodeOptions & node_options()
|
||||
{
|
||||
return options_;
|
||||
}
|
||||
|
||||
private:
|
||||
rclcpp::NodeOptions options_;
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, const TestParameters & params)
|
||||
template<typename T, typename ... Ts>
|
||||
class NodeCreationPolicy<T, Ts...>
|
||||
{
|
||||
out << params.description;
|
||||
return out;
|
||||
}
|
||||
public:
|
||||
NodeCreationPolicy()
|
||||
{
|
||||
gather<T, Ts...>(options_);
|
||||
}
|
||||
|
||||
class TestSubscriptionPublisherCount : public ::testing::TestWithParam<TestParameters>
|
||||
rclcpp::NodeOptions & node_options()
|
||||
{
|
||||
return options_;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename U>
|
||||
static rclcpp::NodeOptions &
|
||||
gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
return U::gather(options);
|
||||
}
|
||||
|
||||
template<typename U, typename V, typename ... Ws>
|
||||
static rclcpp::NodeOptions &
|
||||
gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
return gather<V, Ws...>(U::gather(options));
|
||||
}
|
||||
|
||||
rclcpp::NodeOptions options_;
|
||||
};
|
||||
|
||||
struct UseCustomContext
|
||||
{
|
||||
static rclcpp::NodeOptions & gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
auto context = rclcpp::Context::make_shared();
|
||||
context->init(0, nullptr);
|
||||
return options.context(context);
|
||||
}
|
||||
};
|
||||
|
||||
struct PrintTestDescription
|
||||
{
|
||||
template<typename T>
|
||||
static std::string GetName(int i)
|
||||
{
|
||||
static_cast<void>(i);
|
||||
return T::description;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
template<typename TestDescription>
|
||||
class TestSubscriptionPublisherCount : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
@@ -50,78 +108,59 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetUp() {}
|
||||
void TearDown() {}
|
||||
static std::chrono::milliseconds offset;
|
||||
static void OnMessage(const test_msgs::msg::Empty::SharedPtr msg)
|
||||
{
|
||||
(void)msg;
|
||||
}
|
||||
|
||||
std::chrono::milliseconds offset{2000};
|
||||
};
|
||||
|
||||
std::chrono::milliseconds TestSubscriptionPublisherCount::offset = std::chrono::milliseconds(2000);
|
||||
|
||||
void OnMessage(const test_msgs::msg::Empty::SharedPtr msg)
|
||||
struct OneContextPerTest
|
||||
{
|
||||
(void)msg;
|
||||
}
|
||||
static constexpr const char * description = "one_context_test";
|
||||
using NodeCreationPolicy = ::NodeCreationPolicy<>;
|
||||
};
|
||||
|
||||
TEST_P(TestSubscriptionPublisherCount, increasing_and_decreasing_counts)
|
||||
struct TwoContextsPerTest
|
||||
{
|
||||
rclcpp::NodeOptions node_options = GetParam().node_options;
|
||||
rclcpp::Node::SharedPtr node = std::make_shared<rclcpp::Node>(
|
||||
"my_node",
|
||||
"/ns",
|
||||
node_options);
|
||||
auto subscription = node->create_subscription<Empty>("/topic", 10, &OnMessage);
|
||||
static constexpr const char * description = "two_contexts_test";
|
||||
using NodeCreationPolicy = ::NodeCreationPolicy<UseCustomContext>;
|
||||
};
|
||||
|
||||
using AllTestDescriptions = ::testing::Types<OneContextPerTest, TwoContextsPerTest>;
|
||||
TYPED_TEST_CASE(TestSubscriptionPublisherCount, AllTestDescriptions, PrintTestDescription);
|
||||
|
||||
|
||||
using test_msgs::msg::Empty;
|
||||
|
||||
TYPED_TEST(TestSubscriptionPublisherCount, increasing_and_decreasing_counts)
|
||||
{
|
||||
using TestDescription = TypeParam;
|
||||
rclcpp::Node::SharedPtr node = std::make_shared<rclcpp::Node>("my_node", "/ns");
|
||||
auto subscription = node->create_subscription<Empty>(
|
||||
"/topic", 10, &TestSubscriptionPublisherCount<TestDescription>::OnMessage);
|
||||
|
||||
EXPECT_EQ(subscription->get_publisher_count(), 0u);
|
||||
{
|
||||
auto pub = node->create_publisher<Empty>("/topic", 10);
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(subscription->get_publisher_count(), 1u);
|
||||
{
|
||||
typename TestDescription::NodeCreationPolicy node_creation_policy;
|
||||
rclcpp::Node::SharedPtr another_node = std::make_shared<rclcpp::Node>(
|
||||
"another_node",
|
||||
"/ns",
|
||||
node_options);
|
||||
node_creation_policy.node_options());
|
||||
auto another_pub =
|
||||
another_node->create_publisher<Empty>("/topic", 10);
|
||||
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(subscription->get_publisher_count(), 2u);
|
||||
}
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(subscription->get_publisher_count(), 1u);
|
||||
}
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(subscription->get_publisher_count(), 0u);
|
||||
}
|
||||
|
||||
auto get_new_context()
|
||||
{
|
||||
auto context = rclcpp::Context::make_shared();
|
||||
context->init(0, nullptr);
|
||||
return context;
|
||||
}
|
||||
|
||||
TestParameters parameters[] = {
|
||||
/*
|
||||
Testing subscription publisher count api.
|
||||
One context.
|
||||
*/
|
||||
{
|
||||
rclcpp::NodeOptions(),
|
||||
"one_context_test"
|
||||
},
|
||||
/*
|
||||
Testing subscription publisher count api.
|
||||
Two contexts.
|
||||
*/
|
||||
{
|
||||
rclcpp::NodeOptions().context(get_new_context()),
|
||||
"two_contexts_test"
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
TestWithDifferentNodeOptions,
|
||||
TestSubscriptionPublisherCount,
|
||||
testing::ValuesIn(parameters),
|
||||
testing::PrintToStringParamName());
|
||||
|
||||
@@ -45,7 +45,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestTime, clock_type_access) {
|
||||
TEST_F(TestTime, clock_type_access) {
|
||||
rclcpp::Clock ros_clock(RCL_ROS_TIME);
|
||||
EXPECT_EQ(RCL_ROS_TIME, ros_clock.get_clock_type());
|
||||
|
||||
@@ -57,7 +57,7 @@ TEST(TestTime, clock_type_access) {
|
||||
}
|
||||
|
||||
// Check that the clock may go out of the scope before the jump callback without leading in UB.
|
||||
TEST(TestTime, clock_jump_callback_destruction_order) {
|
||||
TEST_F(TestTime, clock_jump_callback_destruction_order) {
|
||||
rclcpp::JumpHandler::SharedPtr handler;
|
||||
{
|
||||
rclcpp::Clock ros_clock(RCL_ROS_TIME);
|
||||
@@ -68,7 +68,7 @@ TEST(TestTime, clock_jump_callback_destruction_order) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestTime, time_sources) {
|
||||
TEST_F(TestTime, time_sources) {
|
||||
using builtin_interfaces::msg::Time;
|
||||
rclcpp::Clock ros_clock(RCL_ROS_TIME);
|
||||
Time ros_now = ros_clock.now();
|
||||
@@ -86,44 +86,124 @@ TEST(TestTime, time_sources) {
|
||||
EXPECT_NE(0u, steady_now.nanosec);
|
||||
}
|
||||
|
||||
TEST(TestTime, conversions) {
|
||||
static const int64_t HALF_SEC_IN_NS = 500 * 1000 * 1000;
|
||||
static const int64_t ONE_SEC_IN_NS = 1000 * 1000 * 1000;
|
||||
static const int64_t ONE_AND_HALF_SEC_IN_NS = 3 * HALF_SEC_IN_NS;
|
||||
|
||||
TEST_F(TestTime, conversions) {
|
||||
rclcpp::Clock system_clock(RCL_SYSTEM_TIME);
|
||||
|
||||
rclcpp::Time now = system_clock.now();
|
||||
builtin_interfaces::msg::Time now_msg = now;
|
||||
|
||||
rclcpp::Time now_again = now_msg;
|
||||
EXPECT_EQ(now.nanoseconds(), now_again.nanoseconds());
|
||||
|
||||
builtin_interfaces::msg::Time msg;
|
||||
msg.sec = 12345;
|
||||
msg.nanosec = 67890;
|
||||
|
||||
rclcpp::Time time = msg;
|
||||
EXPECT_EQ(
|
||||
RCL_S_TO_NS(static_cast<int64_t>(msg.sec)) + static_cast<int64_t>(msg.nanosec),
|
||||
time.nanoseconds());
|
||||
EXPECT_EQ(static_cast<int64_t>(msg.sec), RCL_NS_TO_S(time.nanoseconds()));
|
||||
|
||||
builtin_interfaces::msg::Time negative_time_msg;
|
||||
negative_time_msg.sec = -1;
|
||||
negative_time_msg.nanosec = 1;
|
||||
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time = negative_time_msg;
|
||||
});
|
||||
rclcpp::Time now = system_clock.now();
|
||||
builtin_interfaces::msg::Time now_msg = now;
|
||||
|
||||
EXPECT_ANY_THROW(rclcpp::Time(-1, 1));
|
||||
rclcpp::Time now_again = now_msg;
|
||||
EXPECT_EQ(now.nanoseconds(), now_again.nanoseconds());
|
||||
}
|
||||
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time assignment(1, 2);
|
||||
assignment = negative_time_msg;
|
||||
});
|
||||
rclcpp::Time positive_time = rclcpp::Time(12345, 67890u);
|
||||
|
||||
builtin_interfaces::msg::Time msg = positive_time;
|
||||
EXPECT_EQ(msg.sec, 12345);
|
||||
EXPECT_EQ(msg.nanosec, 67890u);
|
||||
|
||||
rclcpp::Time time = msg;
|
||||
EXPECT_EQ(time.nanoseconds(), positive_time.nanoseconds());
|
||||
EXPECT_EQ(
|
||||
RCL_S_TO_NS(static_cast<int64_t>(msg.sec)) + static_cast<int64_t>(msg.nanosec),
|
||||
time.nanoseconds());
|
||||
EXPECT_EQ(static_cast<int64_t>(msg.sec), RCL_NS_TO_S(time.nanoseconds()));
|
||||
}
|
||||
|
||||
// throw on construction/assignment of negative times
|
||||
{
|
||||
builtin_interfaces::msg::Time negative_time_msg;
|
||||
negative_time_msg.sec = -1;
|
||||
negative_time_msg.nanosec = 1;
|
||||
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time = negative_time_msg;
|
||||
});
|
||||
|
||||
EXPECT_ANY_THROW(rclcpp::Time(-1, 1));
|
||||
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time assignment(1, 2);
|
||||
assignment = negative_time_msg;
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Time time(HALF_SEC_IN_NS);
|
||||
const auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, 0);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Time time(ONE_SEC_IN_NS);
|
||||
const auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, 1);
|
||||
EXPECT_EQ(time_msg.nanosec, 0u);
|
||||
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), ONE_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Time time(ONE_AND_HALF_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, 1);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), ONE_AND_HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
// Can rclcpp::Time be negative or not? The following constructor works:
|
||||
rclcpp::Time time(-HALF_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, -1);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
|
||||
// The opposite conversion throws...
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time(time_msg);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// Can rclcpp::Time be negative or not? The following constructor works:
|
||||
rclcpp::Time time(-ONE_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, -1);
|
||||
EXPECT_EQ(time_msg.nanosec, 0u);
|
||||
|
||||
// The opposite conversion throws...
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time(time_msg);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// Can rclcpp::Time be negative or not? The following constructor works:
|
||||
rclcpp::Time time(-ONE_AND_HALF_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, -2);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
|
||||
// The opposite conversion throws...
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time(time_msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestTime, operators) {
|
||||
TEST_F(TestTime, operators) {
|
||||
rclcpp::Time old(1, 0);
|
||||
rclcpp::Time young(2, 0);
|
||||
|
||||
@@ -178,7 +258,7 @@ TEST(TestTime, operators) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestTime, overflow_detectors) {
|
||||
TEST_F(TestTime, overflow_detectors) {
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Test logical_eq call first:
|
||||
EXPECT_TRUE(logical_eq(false, false));
|
||||
@@ -198,8 +278,8 @@ TEST(TestTime, overflow_detectors) {
|
||||
// 256 * 256 = 64K total loops, should be pretty fast on everything
|
||||
for (big_type_t y = min_val; y <= max_val; ++y) {
|
||||
for (big_type_t x = min_val; x <= max_val; ++x) {
|
||||
const big_type_t sum = x + y;
|
||||
const big_type_t diff = x - y;
|
||||
const big_type_t sum = static_cast<big_type_t>(x + y);
|
||||
const big_type_t diff = static_cast<big_type_t>(x - y);
|
||||
|
||||
const bool add_will_overflow =
|
||||
rclcpp::add_will_overflow(test_type_t(x), test_type_t(y));
|
||||
@@ -235,7 +315,7 @@ TEST(TestTime, overflow_detectors) {
|
||||
EXPECT_TRUE(rclcpp::sub_will_underflow<int64_t>(INT64_MIN, 1));
|
||||
}
|
||||
|
||||
TEST(TestTime, overflows) {
|
||||
TEST_F(TestTime, overflows) {
|
||||
rclcpp::Time max_time(std::numeric_limits<rcl_time_point_value_t>::max());
|
||||
rclcpp::Time min_time(std::numeric_limits<rcl_time_point_value_t>::min());
|
||||
rclcpp::Duration one(1);
|
||||
@@ -267,7 +347,7 @@ TEST(TestTime, overflows) {
|
||||
EXPECT_NO_THROW(one_time - two_time);
|
||||
}
|
||||
|
||||
TEST(TestTime, seconds) {
|
||||
TEST_F(TestTime, seconds) {
|
||||
EXPECT_DOUBLE_EQ(0.0, rclcpp::Time(0, 0).seconds());
|
||||
EXPECT_DOUBLE_EQ(4.5, rclcpp::Time(4, 500000000).seconds());
|
||||
EXPECT_DOUBLE_EQ(2.5, rclcpp::Time(0, 2500000000).seconds());
|
||||
|
||||
@@ -3,12 +3,19 @@ Changelog for package rclcpp_action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
3.0.0 (2020-06-18)
|
||||
2.2.0 (2020-10-07)
|
||||
------------------
|
||||
* Add rcl_action_client_options when creating action client. (`#1133 <https://github.com/ros2/rclcpp/issues/1133>`_)
|
||||
* Fix doxygen warnings (`#1163 <https://github.com/ros2/rclcpp/issues/1163>`_)
|
||||
* Increase rclcpp_action test coverage (`#1153 <https://github.com/ros2/rclcpp/issues/1153>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Michel Hidalgo, tomoya
|
||||
|
||||
2.1.0 (2020-08-03)
|
||||
------------------
|
||||
|
||||
2.0.2 (2020-07-07)
|
||||
------------------
|
||||
|
||||
2.0.1 (2020-06-23)
|
||||
------------------
|
||||
* Fixed doxygen warnings (`#1163 <https://github.com/ros2/rclcpp/issues/1163>`_) (`#1191 <https://github.com/ros2/rclcpp/issues/1191>`_)
|
||||
* Contributors: Alejandro Hernández Cordero
|
||||
|
||||
2.0.0 (2020-06-01)
|
||||
------------------
|
||||
|
||||
@@ -317,7 +317,7 @@ public:
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
|
||||
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
|
||||
const std::string & action_name,
|
||||
const rcl_action_client_options_t & client_options = rcl_action_client_get_default_options()
|
||||
const rcl_action_client_options_t client_options = rcl_action_client_get_default_options()
|
||||
)
|
||||
: ClientBase(
|
||||
node_base, node_graph, node_logging, action_name,
|
||||
|
||||
@@ -37,7 +37,6 @@ namespace rclcpp_action
|
||||
* \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.
|
||||
* \param[in] options Options to pass to the underlying `rcl_action_client_t`.
|
||||
*/
|
||||
template<typename ActionT>
|
||||
typename Client<ActionT>::SharedPtr
|
||||
@@ -47,8 +46,7 @@ create_client(
|
||||
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_interface,
|
||||
rclcpp::node_interfaces::NodeWaitablesInterface::SharedPtr node_waitables_interface,
|
||||
const std::string & name,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr,
|
||||
const rcl_action_client_options_t & options = rcl_action_client_get_default_options())
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
std::weak_ptr<rclcpp::node_interfaces::NodeWaitablesInterface> weak_node =
|
||||
node_waitables_interface;
|
||||
@@ -61,19 +59,20 @@ create_client(
|
||||
return;
|
||||
}
|
||||
auto shared_node = weak_node.lock();
|
||||
if (shared_node) {
|
||||
// API expects a shared pointer, give it one with a deleter that does nothing.
|
||||
std::shared_ptr<Client<ActionT>> fake_shared_ptr(ptr, [](Client<ActionT> *) {});
|
||||
if (!shared_node) {
|
||||
return;
|
||||
}
|
||||
// API expects a shared pointer, give it one with a deleter that does nothing.
|
||||
std::shared_ptr<Client<ActionT>> fake_shared_ptr(ptr, [](Client<ActionT> *) {});
|
||||
|
||||
if (group_is_null) {
|
||||
// Was added to default group
|
||||
shared_node->remove_waitable(fake_shared_ptr, nullptr);
|
||||
} else {
|
||||
// Was added to a specific group
|
||||
auto shared_group = weak_group.lock();
|
||||
if (shared_group) {
|
||||
shared_node->remove_waitable(fake_shared_ptr, shared_group);
|
||||
}
|
||||
if (group_is_null) {
|
||||
// Was added to default group
|
||||
shared_node->remove_waitable(fake_shared_ptr, nullptr);
|
||||
} else {
|
||||
// Was added to a specfic group
|
||||
auto shared_group = weak_group.lock();
|
||||
if (shared_group) {
|
||||
shared_node->remove_waitable(fake_shared_ptr, shared_group);
|
||||
}
|
||||
}
|
||||
delete ptr;
|
||||
@@ -84,8 +83,7 @@ create_client(
|
||||
node_base_interface,
|
||||
node_graph_interface,
|
||||
node_logging_interface,
|
||||
name,
|
||||
options),
|
||||
name),
|
||||
deleter);
|
||||
|
||||
node_waitables_interface->add_waitable(action_client, group);
|
||||
@@ -98,15 +96,13 @@ create_client(
|
||||
* \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.
|
||||
* \param[in] options Options to pass to the underlying `rcl_action_client_t`.
|
||||
*/
|
||||
template<typename ActionT, typename NodeT>
|
||||
typename Client<ActionT>::SharedPtr
|
||||
create_client(
|
||||
NodeT node,
|
||||
const std::string & name,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr,
|
||||
const rcl_action_client_options_t & options = rcl_action_client_get_default_options())
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
return rclcpp_action::create_client<ActionT>(
|
||||
node->get_node_base_interface(),
|
||||
@@ -114,8 +110,7 @@ create_client(
|
||||
node->get_node_logging_interface(),
|
||||
node->get_node_waitables_interface(),
|
||||
name,
|
||||
group,
|
||||
options);
|
||||
group);
|
||||
}
|
||||
} // namespace rclcpp_action
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace rclcpp_action
|
||||
* 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[in] options options to pass to the underlying `rcl_action_server_t`.
|
||||
* \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.
|
||||
*/
|
||||
@@ -78,19 +78,20 @@ create_server(
|
||||
return;
|
||||
}
|
||||
auto shared_node = weak_node.lock();
|
||||
if (shared_node) {
|
||||
// API expects a shared pointer, give it one with a deleter that does nothing.
|
||||
std::shared_ptr<Server<ActionT>> fake_shared_ptr(ptr, [](Server<ActionT> *) {});
|
||||
if (!shared_node) {
|
||||
return;
|
||||
}
|
||||
// API expects a shared pointer, give it one with a deleter that does nothing.
|
||||
std::shared_ptr<Server<ActionT>> fake_shared_ptr(ptr, [](Server<ActionT> *) {});
|
||||
|
||||
if (group_is_null) {
|
||||
// Was added to default group
|
||||
shared_node->remove_waitable(fake_shared_ptr, nullptr);
|
||||
} else {
|
||||
// Was added to a specific group
|
||||
auto shared_group = weak_group.lock();
|
||||
if (shared_group) {
|
||||
shared_node->remove_waitable(fake_shared_ptr, shared_group);
|
||||
}
|
||||
if (group_is_null) {
|
||||
// Was added to default group
|
||||
shared_node->remove_waitable(fake_shared_ptr, nullptr);
|
||||
} else {
|
||||
// Was added to a specfic group
|
||||
auto shared_group = weak_group.lock();
|
||||
if (shared_group) {
|
||||
shared_node->remove_waitable(fake_shared_ptr, shared_group);
|
||||
}
|
||||
}
|
||||
delete ptr;
|
||||
@@ -123,7 +124,7 @@ create_server(
|
||||
* 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[in] options options to pass to the underlying `rcl_action_server_t`.
|
||||
* \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.
|
||||
*/
|
||||
|
||||
@@ -296,7 +296,7 @@ public:
|
||||
* \param[in] name the name of an action.
|
||||
* The same name and type must be used by both the action client and action server to
|
||||
* communicate.
|
||||
* \param[in] options Options to pass to the underlying `rcl_action_server_t`.
|
||||
* \param[in] options options to pass to the underlying `rcl_action_server_t`.
|
||||
* \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 attemted to be canceled.
|
||||
* The return from this callback only indicates if the server will try to cancel a goal.
|
||||
|
||||
@@ -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>3.0.0</version>
|
||||
<version>2.2.0</version>
|
||||
<description>Adds action APIs for C++.</description>
|
||||
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <test_msgs/action/fibonacci.hpp>
|
||||
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -74,7 +73,7 @@ protected:
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void SetUpServer()
|
||||
void SetUp()
|
||||
{
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
|
||||
@@ -212,10 +211,7 @@ protected:
|
||||
ASSERT_TRUE(status_publisher != nullptr);
|
||||
allocator.deallocate(status_topic_name, allocator.state);
|
||||
server_executor.add_node(server_node);
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
client_node = std::make_shared<rclcpp::Node>(client_node_name, namespace_name);
|
||||
client_executor.add_node(client_node);
|
||||
|
||||
@@ -223,12 +219,7 @@ protected:
|
||||
ASSERT_EQ(RCL_RET_OK, rcl_set_ros_time_override(clock.get_clock_handle(), RCL_S_TO_NS(1)));
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
void TearDownServer()
|
||||
void TearDown()
|
||||
{
|
||||
status_publisher.reset();
|
||||
feedback_publisher.reset();
|
||||
@@ -236,10 +227,6 @@ protected:
|
||||
result_service.reset();
|
||||
goal_service.reset();
|
||||
server_node.reset();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
client_node.reset();
|
||||
}
|
||||
|
||||
@@ -278,42 +265,15 @@ protected:
|
||||
typename rclcpp::Publisher<ActionStatusMessage>::SharedPtr status_publisher;
|
||||
};
|
||||
|
||||
class TestClientAgainstServer : public TestClient
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
SetUpServer();
|
||||
TestClient::SetUp();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
TestClient::TearDown();
|
||||
TearDownServer();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST_F(TestClient, construction_and_destruction)
|
||||
{
|
||||
ASSERT_NO_THROW(rclcpp_action::create_client<ActionType>(client_node, action_name).reset());
|
||||
}
|
||||
|
||||
TEST_F(TestClient, construction_and_destruction_after_node)
|
||||
{
|
||||
ASSERT_NO_THROW(
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
client_node.reset();
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TestClient, construction_and_destruction_callback_group)
|
||||
{
|
||||
auto group = client_node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
const rcl_action_client_options_t & options = rcl_action_client_get_default_options();
|
||||
ASSERT_NO_THROW(
|
||||
rclcpp_action::create_client<ActionType>(
|
||||
client_node->get_node_base_interface(),
|
||||
@@ -321,29 +281,11 @@ TEST_F(TestClient, construction_and_destruction_callback_group)
|
||||
client_node->get_node_logging_interface(),
|
||||
client_node->get_node_waitables_interface(),
|
||||
action_name,
|
||||
group,
|
||||
options
|
||||
group
|
||||
).reset());
|
||||
}
|
||||
|
||||
TEST_F(TestClient, wait_for_action_server)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
EXPECT_FALSE(action_client->wait_for_action_server(0ms));
|
||||
EXPECT_FALSE(action_client->wait_for_action_server(100ms));
|
||||
auto future = std::async(
|
||||
std::launch::async, [&action_client]() {
|
||||
return action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT);
|
||||
});
|
||||
SetUpServer();
|
||||
EXPECT_TRUE(future.get());
|
||||
TearDownServer();
|
||||
|
||||
client_node.reset(); // Drop node before action client
|
||||
EXPECT_THROW(action_client->wait_for_action_server(0ms), rclcpp::exceptions::InvalidNodeError);
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_send_goal_no_callbacks)
|
||||
TEST_F(TestClient, async_send_goal_no_callbacks)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
@@ -364,24 +306,7 @@ TEST_F(TestClientAgainstServer, async_send_goal_no_callbacks)
|
||||
EXPECT_FALSE(goal_handle->is_result_aware());
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, bad_goal_handles)
|
||||
{
|
||||
auto action_client0 = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client0->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
|
||||
ActionGoal goal;
|
||||
goal.order = 0;
|
||||
auto future_goal_handle = action_client0->async_send_goal(goal);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
|
||||
auto action_client1 = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
using rclcpp_action::exceptions::UnknownGoalHandleError;
|
||||
EXPECT_THROW(action_client1->async_get_result(goal_handle), UnknownGoalHandleError);
|
||||
EXPECT_THROW(action_client1->async_cancel_goal(goal_handle), UnknownGoalHandleError);
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_send_goal_no_callbacks_wait_for_result)
|
||||
TEST_F(TestClient, async_send_goal_no_callbacks_wait_for_result)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
@@ -404,33 +329,13 @@ TEST_F(TestClientAgainstServer, async_send_goal_no_callbacks_wait_for_result)
|
||||
EXPECT_EQ(5, wrapped_result.result->sequence[5]);
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_send_goal_no_callbacks_then_invalidate)
|
||||
TEST_F(TestClient, async_send_goal_with_goal_response_callback_wait_for_result)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
|
||||
ActionGoal goal;
|
||||
goal.order = 5;
|
||||
auto future_goal_handle = action_client->async_send_goal(goal);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
ASSERT_NE(nullptr, goal_handle);
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_ACCEPTED, goal_handle->get_status());
|
||||
auto future_result = action_client->async_get_result(goal_handle);
|
||||
EXPECT_TRUE(goal_handle->is_result_aware());
|
||||
|
||||
action_client.reset(); // Ensure goal handle is invalidated once client goes out of scope
|
||||
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_UNKNOWN, goal_handle->get_status());
|
||||
using rclcpp_action::exceptions::UnawareGoalHandleError;
|
||||
EXPECT_THROW(future_result.get(), UnawareGoalHandleError);
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_send_goal_with_goal_response_callback_wait_for_result)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
|
||||
goal.order = 4;
|
||||
bool goal_response_received = false;
|
||||
auto send_goal_ops = rclcpp_action::Client<ActionType>::SendGoalOptions();
|
||||
send_goal_ops.goal_response_callback =
|
||||
@@ -442,37 +347,23 @@ TEST_F(TestClientAgainstServer, async_send_goal_with_goal_response_callback_wait
|
||||
goal_response_received = true;
|
||||
}
|
||||
};
|
||||
auto future_goal_handle = action_client->async_send_goal(goal, send_goal_ops);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
EXPECT_TRUE(goal_response_received);
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_ACCEPTED, goal_handle->get_status());
|
||||
EXPECT_FALSE(goal_handle->is_feedback_aware());
|
||||
EXPECT_FALSE(goal_handle->is_result_aware());
|
||||
auto future_result = action_client->async_get_result(goal_handle);
|
||||
EXPECT_TRUE(goal_handle->is_result_aware());
|
||||
dual_spin_until_future_complete(future_result);
|
||||
auto wrapped_result = future_result.get();
|
||||
|
||||
{
|
||||
ActionGoal bad_goal;
|
||||
bad_goal.order = -1;
|
||||
auto future_goal_handle = action_client->async_send_goal(bad_goal, send_goal_ops);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
EXPECT_FALSE(goal_response_received);
|
||||
EXPECT_EQ(nullptr, goal_handle);
|
||||
}
|
||||
|
||||
{
|
||||
ActionGoal goal;
|
||||
goal.order = 4;
|
||||
auto future_goal_handle = action_client->async_send_goal(goal, send_goal_ops);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
EXPECT_TRUE(goal_response_received);
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_ACCEPTED, goal_handle->get_status());
|
||||
EXPECT_FALSE(goal_handle->is_feedback_aware());
|
||||
EXPECT_FALSE(goal_handle->is_result_aware());
|
||||
auto future_result = action_client->async_get_result(goal_handle);
|
||||
EXPECT_TRUE(goal_handle->is_result_aware());
|
||||
dual_spin_until_future_complete(future_result);
|
||||
auto wrapped_result = future_result.get();
|
||||
ASSERT_EQ(5u, wrapped_result.result->sequence.size());
|
||||
EXPECT_EQ(3, wrapped_result.result->sequence.back());
|
||||
}
|
||||
ASSERT_EQ(5u, wrapped_result.result->sequence.size());
|
||||
EXPECT_EQ(3, wrapped_result.result->sequence.back());
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_send_goal_with_feedback_callback_wait_for_result)
|
||||
TEST_F(TestClient, async_send_goal_with_feedback_callback_wait_for_result)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
@@ -506,7 +397,7 @@ TEST_F(TestClientAgainstServer, async_send_goal_with_feedback_callback_wait_for_
|
||||
EXPECT_EQ(5, feedback_count);
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_send_goal_with_result_callback_wait_for_result)
|
||||
TEST_F(TestClient, async_send_goal_with_result_callback_wait_for_result)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
@@ -541,7 +432,7 @@ TEST_F(TestClientAgainstServer, async_send_goal_with_result_callback_wait_for_re
|
||||
EXPECT_EQ(3, wrapped_result.result->sequence.back());
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_get_result_with_callback)
|
||||
TEST_F(TestClient, async_get_result_with_callback)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
@@ -576,7 +467,7 @@ TEST_F(TestClientAgainstServer, async_get_result_with_callback)
|
||||
EXPECT_EQ(3, wrapped_result.result->sequence.back());
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_cancel_one_goal)
|
||||
TEST_F(TestClient, async_cancel_one_goal)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
@@ -594,7 +485,7 @@ TEST_F(TestClientAgainstServer, async_cancel_one_goal)
|
||||
EXPECT_EQ(ActionCancelGoalResponse::ERROR_NONE, cancel_response->return_code);
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_cancel_one_goal_with_callback)
|
||||
TEST_F(TestClient, async_cancel_one_goal_with_callback)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
@@ -628,7 +519,7 @@ TEST_F(TestClientAgainstServer, async_cancel_one_goal_with_callback)
|
||||
EXPECT_TRUE(cancel_response_received);
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_cancel_all_goals)
|
||||
TEST_F(TestClient, async_cancel_all_goals)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
@@ -664,7 +555,7 @@ TEST_F(TestClientAgainstServer, async_cancel_all_goals)
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_CANCELED, goal_handle1->get_status());
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_cancel_all_goals_with_callback)
|
||||
TEST_F(TestClient, async_cancel_all_goals_with_callback)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
@@ -714,7 +605,7 @@ TEST_F(TestClientAgainstServer, async_cancel_all_goals_with_callback)
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_CANCELED, goal_handle1->get_status());
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_cancel_some_goals)
|
||||
TEST_F(TestClient, async_cancel_some_goals)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
@@ -745,7 +636,7 @@ TEST_F(TestClientAgainstServer, async_cancel_some_goals)
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_CANCELED, goal_handle0->get_status());
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, async_cancel_some_goals_with_callback)
|
||||
TEST_F(TestClient, async_cancel_some_goals_with_callback)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
|
||||
@@ -82,42 +82,17 @@ TEST_F(TestServer, construction_and_destruction)
|
||||
{
|
||||
auto node = std::make_shared<rclcpp::Node>("construct_node", "/rclcpp_action/construct");
|
||||
|
||||
ASSERT_NO_THROW(
|
||||
{
|
||||
using GoalHandle = rclcpp_action::ServerGoalHandle<Fibonacci>;
|
||||
auto as = rclcpp_action::create_server<Fibonacci>(
|
||||
node, "fibonacci",
|
||||
[](const GoalUUID &, std::shared_ptr<const Fibonacci::Goal>) {
|
||||
return rclcpp_action::GoalResponse::REJECT;
|
||||
},
|
||||
[](std::shared_ptr<GoalHandle>) {
|
||||
return rclcpp_action::CancelResponse::REJECT;
|
||||
},
|
||||
[](std::shared_ptr<GoalHandle>) {});
|
||||
(void)as;
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TestServer, construction_and_destruction_after_node)
|
||||
{
|
||||
auto node = std::make_shared<rclcpp::Node>("construct_node", "/rclcpp_action/construct");
|
||||
|
||||
ASSERT_NO_THROW(
|
||||
{
|
||||
using GoalHandle = rclcpp_action::ServerGoalHandle<Fibonacci>;
|
||||
auto as = rclcpp_action::create_server<Fibonacci>(
|
||||
node, "fibonacci",
|
||||
[](const GoalUUID &, std::shared_ptr<const Fibonacci::Goal>) {
|
||||
return rclcpp_action::GoalResponse::REJECT;
|
||||
},
|
||||
[](std::shared_ptr<GoalHandle>) {
|
||||
return rclcpp_action::CancelResponse::REJECT;
|
||||
},
|
||||
[](std::shared_ptr<GoalHandle>) {});
|
||||
(void)as;
|
||||
|
||||
node.reset();
|
||||
});
|
||||
using GoalHandle = rclcpp_action::ServerGoalHandle<Fibonacci>;
|
||||
auto as = rclcpp_action::create_server<Fibonacci>(
|
||||
node, "fibonacci",
|
||||
[](const GoalUUID &, std::shared_ptr<const Fibonacci::Goal>) {
|
||||
return rclcpp_action::GoalResponse::REJECT;
|
||||
},
|
||||
[](std::shared_ptr<GoalHandle>) {
|
||||
return rclcpp_action::CancelResponse::REJECT;
|
||||
},
|
||||
[](std::shared_ptr<GoalHandle>) {});
|
||||
(void)as;
|
||||
}
|
||||
|
||||
TEST_F(TestServer, construction_and_destruction_callback_group)
|
||||
@@ -758,84 +733,6 @@ TEST_F(TestServer, get_result)
|
||||
|
||||
using GoalHandle = rclcpp_action::ServerGoalHandle<Fibonacci>;
|
||||
|
||||
auto handle_cancel = [](std::shared_ptr<GoalHandle>)
|
||||
{
|
||||
return rclcpp_action::CancelResponse::REJECT;
|
||||
};
|
||||
|
||||
std::shared_ptr<GoalHandle> received_handle;
|
||||
auto handle_accepted = [&received_handle](std::shared_ptr<GoalHandle> handle)
|
||||
{
|
||||
received_handle = handle;
|
||||
};
|
||||
|
||||
const std::chrono::milliseconds result_timeout{50};
|
||||
|
||||
rcl_action_server_options_t options = rcl_action_server_get_default_options();
|
||||
options.result_timeout.nanoseconds = RCL_MS_TO_NS(result_timeout.count());
|
||||
auto as = rclcpp_action::create_server<Fibonacci>(
|
||||
node, "fibonacci",
|
||||
handle_goal,
|
||||
handle_cancel,
|
||||
handle_accepted,
|
||||
options);
|
||||
(void)as;
|
||||
|
||||
send_goal_request(node, uuid);
|
||||
|
||||
// Send result request
|
||||
auto result_client = node->create_client<Fibonacci::Impl::GetResultService>(
|
||||
"fibonacci/_action/get_result");
|
||||
if (!result_client->wait_for_service(std::chrono::seconds(20))) {
|
||||
throw std::runtime_error("get result service didn't become available");
|
||||
}
|
||||
auto request = std::make_shared<Fibonacci::Impl::GetResultService::Request>();
|
||||
request->goal_id.uuid = uuid;
|
||||
auto future = result_client->async_send_request(request);
|
||||
|
||||
// Send a result
|
||||
auto result = std::make_shared<Fibonacci::Result>();
|
||||
result->sequence = {5, 8, 13, 21};
|
||||
received_handle->succeed(result);
|
||||
|
||||
// Wait for the result request to be received
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
rclcpp::spin_until_future_complete(node, future));
|
||||
|
||||
auto response = future.get();
|
||||
EXPECT_EQ(action_msgs::msg::GoalStatus::STATUS_SUCCEEDED, response->status);
|
||||
EXPECT_EQ(result->sequence, response->result.sequence);
|
||||
|
||||
// Wait for goal expiration
|
||||
rclcpp::sleep_for(2 * result_timeout);
|
||||
|
||||
// Allow for expiration to take place
|
||||
rclcpp::spin_some(node);
|
||||
|
||||
// Send and wait for another result request
|
||||
future = result_client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
rclcpp::spin_until_future_complete(node, future));
|
||||
|
||||
response = future.get();
|
||||
EXPECT_EQ(action_msgs::msg::GoalStatus::STATUS_UNKNOWN, response->status);
|
||||
}
|
||||
|
||||
TEST_F(TestServer, get_result_deferred)
|
||||
{
|
||||
auto node = std::make_shared<rclcpp::Node>("get_result", "/rclcpp_action/get_result");
|
||||
const GoalUUID uuid{{1, 2, 3, 4, 5, 6, 7, 80, 90, 10, 11, 12, 13, 14, 15, 160}};
|
||||
|
||||
auto handle_goal = [](
|
||||
const GoalUUID &, std::shared_ptr<const Fibonacci::Goal>)
|
||||
{
|
||||
return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
|
||||
};
|
||||
|
||||
using GoalHandle = rclcpp_action::ServerGoalHandle<Fibonacci>;
|
||||
|
||||
auto handle_cancel = [](std::shared_ptr<GoalHandle>)
|
||||
{
|
||||
return rclcpp_action::CancelResponse::REJECT;
|
||||
@@ -866,10 +763,6 @@ TEST_F(TestServer, get_result_deferred)
|
||||
request->goal_id.uuid = uuid;
|
||||
auto future = result_client->async_send_request(request);
|
||||
|
||||
// Process request first
|
||||
rclcpp::sleep_for(std::chrono::milliseconds(10)); // Give a chance for the request to be served
|
||||
rclcpp::spin_some(node);
|
||||
|
||||
// Send a result
|
||||
auto result = std::make_shared<Fibonacci::Result>();
|
||||
result->sequence = {5, 8, 13, 21};
|
||||
|
||||
@@ -2,13 +2,24 @@
|
||||
Changelog for package rclcpp_components
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
3.0.0 (2020-06-18)
|
||||
2.2.0 (2020-10-07)
|
||||
------------------
|
||||
* Include original exception in ComponentManagerException (`#1157 <https://github.com/ros2/rclcpp/issues/1157>`_) (`#1223 <https://github.com/ros2/rclcpp/issues/1223>`_)
|
||||
* Contributors: Dereck Wonnacott
|
||||
|
||||
2.1.0 (2020-08-03)
|
||||
------------------
|
||||
|
||||
2.0.2 (2020-07-07)
|
||||
------------------
|
||||
|
||||
2.0.1 (2020-06-23)
|
||||
------------------
|
||||
|
||||
2.0.0 (2020-06-01)
|
||||
------------------
|
||||
* Added missing virtual destructors. (`#1149 <https://github.com/ros2/rclcpp/issues/1149>`_)
|
||||
* Add Security Vulnerability Policy pointing to REP-2006. (`#1130 <https://github.com/ros2/rclcpp/issues/1130>`_)
|
||||
* Added missing virtual destructors (`#1149 <https://github.com/ros2/rclcpp/issues/1149>`_)
|
||||
* Add Security Vulnerability Policy pointing to REP-2006 (`#1130 <https://github.com/ros2/rclcpp/issues/1130>`_)
|
||||
* Contributors: Chris Lalancette, Ivan Santiago Paunovic
|
||||
|
||||
1.1.0 (2020-05-26)
|
||||
|
||||
@@ -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>3.0.0</version>
|
||||
<version>2.2.0</version>
|
||||
<description>Package containing tools for dynamically loadable components</description>
|
||||
<maintainer email="michael@openrobotics.org">Michael Carroll</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -196,6 +196,11 @@ ComponentManager::OnLoadNode(
|
||||
|
||||
try {
|
||||
node_wrappers_[node_id] = factory->create_node_instance(options);
|
||||
} catch (const std::exception & ex) {
|
||||
// In the case that the component constructor throws an exception,
|
||||
// rethrow into the following catch block.
|
||||
throw ComponentManagerException(
|
||||
"Component constructor threw an exception: " + std::string(ex.what()));
|
||||
} catch (...) {
|
||||
// In the case that the component constructor throws an exception,
|
||||
// rethrow into the following catch block.
|
||||
|
||||
@@ -3,9 +3,23 @@ Changelog for package rclcpp_lifecycle
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
3.0.0 (2020-06-18)
|
||||
2.2.0 (2020-10-07)
|
||||
------------------
|
||||
* Fix doxygen warnings (`#1163 <https://github.com/ros2/rclcpp/issues/1163>`_)
|
||||
* Log error instead of throwing exception in Transition and State reset() mark no except (`#1297 <https://github.com/ros2/rclcpp/issues/1297>`_) (`#1378 <https://github.com/ros2/rclcpp/issues/1378>`_)
|
||||
* Remove rmw-dependent unit-test checks (`#1293 <https://github.com/ros2/rclcpp/issues/1293>`_) (`#1377 <https://github.com/ros2/rclcpp/issues/1377>`_)
|
||||
* Contributors: Stephen Brawner
|
||||
|
||||
2.1.0 (2020-08-03)
|
||||
------------------
|
||||
* Warn about unused result of add_on_set_parameters_callback (`#1238 <https://github.com/ros2/rclcpp/issues/1238>`_) (`#1244 <https://github.com/ros2/rclcpp/issues/1244>`_)
|
||||
* Contributors: Jacob Perron
|
||||
|
||||
2.0.2 (2020-07-07)
|
||||
------------------
|
||||
|
||||
2.0.1 (2020-06-23)
|
||||
------------------
|
||||
* Fixed doxygen warnings (`#1163 <https://github.com/ros2/rclcpp/issues/1163>`_) (`#1191 <https://github.com/ros2/rclcpp/issues/1191>`_)
|
||||
* Contributors: Alejandro Hernández Cordero
|
||||
|
||||
2.0.0 (2020-06-01)
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rcutils/macros.h"
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/node.h"
|
||||
|
||||
@@ -456,6 +458,7 @@ public:
|
||||
* \sa rclcpp::Node::add_on_set_parameters_callback
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
rclcpp_lifecycle::LifecycleNode::OnSetParametersCallbackHandle::SharedPtr
|
||||
add_on_set_parameters_callback(
|
||||
rclcpp_lifecycle::LifecycleNode::OnParametersSetCallbackType callback);
|
||||
|
||||
@@ -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>3.0.0</version>
|
||||
<version>2.2.0</version>
|
||||
<description>Package containing a prototype for lifecycle implementation</description>
|
||||
<maintainer email="karsten@osrfoundation.org">Karsten Knese</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "rcl_lifecycle/rcl_lifecycle.h"
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
|
||||
#include "rcutils/allocator.h"
|
||||
|
||||
@@ -157,7 +158,9 @@ State::reset()
|
||||
allocator_.deallocate(state_handle_, allocator_.state);
|
||||
state_handle_ = nullptr;
|
||||
if (ret != RCL_RET_OK) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
RCLCPP_ERROR(
|
||||
rclcpp::get_logger("rclcpp_lifecycle"),
|
||||
"rcl_lifecycle_transition_fini did not complete successfully, leaking memory");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "rcl_lifecycle/rcl_lifecycle.h"
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
|
||||
#include "rcutils/allocator.h"
|
||||
|
||||
@@ -261,7 +262,9 @@ Transition::reset()
|
||||
allocator_.deallocate(transition_handle_, allocator_.state);
|
||||
transition_handle_ = nullptr;
|
||||
if (ret != RCL_RET_OK) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
RCLCPP_ERROR(
|
||||
rclcpp::get_logger("rclcpp_lifecycle"),
|
||||
"rcl_lifecycle_transition_fini did not complete successfully, leaking memory");
|
||||
}
|
||||
}
|
||||
} // namespace rclcpp_lifecycle
|
||||
|
||||
@@ -492,31 +492,51 @@ TEST_F(TestDefaultStateMachine, test_getters) {
|
||||
TEST_F(TestDefaultStateMachine, test_graph) {
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
auto names = test_node->get_node_names();
|
||||
EXPECT_EQ(names.size(), 1u);
|
||||
EXPECT_STREQ(names[0].c_str(), "/testnode");
|
||||
|
||||
// parameter_events, rosout, /testnode/transition_event
|
||||
ASSERT_NE(names.end(), std::find(names.begin(), names.end(), std::string("/testnode")));
|
||||
|
||||
// Other topics may exist for an rclcpp::Node, but just checking the lifecycle one exists
|
||||
auto topic_names_and_types = test_node->get_topic_names_and_types();
|
||||
EXPECT_EQ(topic_names_and_types.size(), 3u);
|
||||
ASSERT_NE(
|
||||
topic_names_and_types.end(),
|
||||
topic_names_and_types.find(std::string("/testnode/transition_event")));
|
||||
EXPECT_STREQ(
|
||||
topic_names_and_types["/testnode/transition_event"][0].c_str(),
|
||||
"lifecycle_msgs/msg/TransitionEvent");
|
||||
|
||||
auto service_names_and_types = test_node->get_service_names_and_types();
|
||||
EXPECT_EQ(service_names_and_types.size(), 11u);
|
||||
// These are specific to lifecycle nodes, other services are provided by rclcpp::Node
|
||||
ASSERT_NE(
|
||||
service_names_and_types.end(),
|
||||
service_names_and_types.find(std::string("/testnode/change_state")));
|
||||
EXPECT_STREQ(
|
||||
service_names_and_types["/testnode/change_state"][0].c_str(),
|
||||
"lifecycle_msgs/srv/ChangeState");
|
||||
|
||||
ASSERT_NE(
|
||||
service_names_and_types.end(),
|
||||
service_names_and_types.find(std::string("/testnode/get_available_states")));
|
||||
EXPECT_STREQ(
|
||||
service_names_and_types["/testnode/get_available_states"][0].c_str(),
|
||||
"lifecycle_msgs/srv/GetAvailableStates");
|
||||
|
||||
ASSERT_NE(
|
||||
service_names_and_types.end(),
|
||||
service_names_and_types.find(std::string("/testnode/get_available_transitions")));
|
||||
EXPECT_STREQ(
|
||||
service_names_and_types["/testnode/get_available_transitions"][0].c_str(),
|
||||
"lifecycle_msgs/srv/GetAvailableTransitions");
|
||||
|
||||
ASSERT_NE(
|
||||
service_names_and_types.end(),
|
||||
service_names_and_types.find(std::string("/testnode/get_state")));
|
||||
EXPECT_STREQ(
|
||||
service_names_and_types["/testnode/get_state"][0].c_str(),
|
||||
"lifecycle_msgs/srv/GetState");
|
||||
|
||||
ASSERT_NE(
|
||||
service_names_and_types.end(),
|
||||
service_names_and_types.find(std::string("/testnode/get_transition_graph")));
|
||||
EXPECT_STREQ(
|
||||
service_names_and_types["/testnode/get_transition_graph"][0].c_str(),
|
||||
"lifecycle_msgs/srv/GetAvailableTransitions");
|
||||
|
||||
Reference in New Issue
Block a user