Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04f85067e8 | ||
|
|
70f9ed58d2 | ||
|
|
e2af9da76c | ||
|
|
880d89e583 | ||
|
|
810ff6a8d6 | ||
|
|
7e4e72c70d | ||
|
|
d5d4f6c44c | ||
|
|
19e443bce9 | ||
|
|
4551b69f6e | ||
|
|
785b45a2fc | ||
|
|
c5b427c2ec | ||
|
|
3ce946f6e9 | ||
|
|
ebb6175dfa | ||
|
|
fc13cfe5fe | ||
|
|
331bcb2ec9 | ||
|
|
4db3e3303b | ||
|
|
bda164fb4d | ||
|
|
a35bc62b8c | ||
|
|
8a9f0468e3 | ||
|
|
6a2d90ebf8 | ||
|
|
c21065e979 | ||
|
|
c4ee11a5c7 | ||
|
|
14ecbc3f0b | ||
|
|
8a4cb48b2c | ||
|
|
aa634b28df | ||
|
|
8ec31edd4a | ||
|
|
a709d81a93 | ||
|
|
a35793ad28 | ||
|
|
7cba3c4882 | ||
|
|
27e800b910 | ||
|
|
e6f6b2a7ad | ||
|
|
6c95d10cca | ||
|
|
a5a7febb60 | ||
|
|
7373669455 | ||
|
|
ae930aa2e5 | ||
|
|
24846c3109 | ||
|
|
160da7b432 | ||
|
|
22939ddf9b | ||
|
|
ea1d764f42 | ||
|
|
82666affcd | ||
|
|
0be3acf32f | ||
|
|
34005e903f | ||
|
|
288be9c981 | ||
|
|
93028ff38d |
@@ -2,67 +2,59 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
30.1.2 (2025-10-21)
|
||||
29.5.7 (2026-02-09)
|
||||
-------------------
|
||||
* clear handles before node destruction in test_memory_strategy. (`#2969 <https://github.com/ros2/rclcpp/issues/2969>`_)
|
||||
* Added static assert asserting custom types have no overloaded operator new (`#2954 <https://github.com/ros2/rclcpp/issues/2954>`_)
|
||||
* Store graph listener inside the context instead of the node graph (`#2952 <https://github.com/ros2/rclcpp/issues/2952>`_)
|
||||
* Reapply "Catch the exception from rate.sleep() if the context is invalid. (`#2956 <https://github.com/ros2/rclcpp/issues/2956>`_)" (`#2963 <https://github.com/ros2/rclcpp/issues/2963>`_) (`#2964 <https://github.com/ros2/rclcpp/issues/2964>`_)
|
||||
* Revert "Catch the exception from rate.sleep() if the context is invalid. (`#2956 <https://github.com/ros2/rclcpp/issues/2956>`_)" (`#2963 <https://github.com/ros2/rclcpp/issues/2963>`_)
|
||||
* Catch the exception from rate.sleep() if the context is invalid. (`#2956 <https://github.com/ros2/rclcpp/issues/2956>`_)
|
||||
* update Time documentation (`#2955 <https://github.com/ros2/rclcpp/issues/2955>`_)
|
||||
* Contributors: Ilario A. Azzollini, Ivo Ivanov, Skyler Medeiros, Tomoya Fujita
|
||||
* include the 1st spin that might throw the exception. (`#3042 <https://github.com/ros2/rclcpp/issues/3042>`_) (`#3044 <https://github.com/ros2/rclcpp/issues/3044>`_)
|
||||
* print warning message on owner node if the parameter operation fails. (`#3037 <https://github.com/ros2/rclcpp/issues/3037>`_) (`#3038 <https://github.com/ros2/rclcpp/issues/3038>`_)
|
||||
* remove test_static_executor_entities_collector.cpp (`#3041 <https://github.com/ros2/rclcpp/issues/3041>`_) (`#3045 <https://github.com/ros2/rclcpp/issues/3045>`_)
|
||||
* fix context in wait for message wait set (`#3030 <https://github.com/ros2/rclcpp/issues/3030>`_) (`#3031 <https://github.com/ros2/rclcpp/issues/3031>`_)
|
||||
* Improve the robustness of the TopicEndpointInfo constructor (`#3013 <https://github.com/ros2/rclcpp/issues/3013>`_) (`#3014 <https://github.com/ros2/rclcpp/issues/3014>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
30.1.1 (2025-09-11)
|
||||
29.5.6 (2025-12-23)
|
||||
-------------------
|
||||
* Removed warning (`#2949 <https://github.com/ros2/rclcpp/issues/2949>`_)
|
||||
* add note about problems with spin_until_future_complete (`#2849 <https://github.com/ros2/rclcpp/issues/2849>`_)
|
||||
* deprecate rclcpp::spin_some and rclcpp::spin_all (`#2848 <https://github.com/ros2/rclcpp/issues/2848>`_)
|
||||
* Improve the function extract_type_identifier (`#2923 <https://github.com/ros2/rclcpp/issues/2923>`_)
|
||||
* Allow for implicitly convertable loggers as well (`#2922 <https://github.com/ros2/rclcpp/issues/2922>`_)
|
||||
* Contributors: Alberto Soragna, Alejandro Hernández Cordero, Barry Xu, Tim Clephas
|
||||
* Unified Node Interfaces: Add const version of get_node_x_interface() (`#3006 <https://github.com/ros2/rclcpp/issues/3006>`_) (`#3008 <https://github.com/ros2/rclcpp/issues/3008>`_)
|
||||
* remove I/O from signal handler. (`#3000 <https://github.com/ros2/rclcpp/issues/3000>`_)
|
||||
* correct test function descriptions (`#2970 <https://github.com/ros2/rclcpp/issues/2970>`_) (`#2992 <https://github.com/ros2/rclcpp/issues/2992>`_)
|
||||
* Contributors: Tomoya Fujita, mergify[bot]
|
||||
|
||||
30.1.0 (2025-07-29)
|
||||
29.5.5 (2025-11-18)
|
||||
-------------------
|
||||
* Fix: improve exception context for parameter_value_from (`#2917 <https://github.com/ros2/rclcpp/issues/2917>`_)
|
||||
* Fix `start_type_description_service` param handling (`#2897 <https://github.com/ros2/rclcpp/issues/2897>`_)
|
||||
* Add qos parameter for wait_for_message function (`#2903 <https://github.com/ros2/rclcpp/issues/2903>`_)
|
||||
* Fujitatomoya/test append parameter override (`#2896 <https://github.com/ros2/rclcpp/issues/2896>`_)
|
||||
* Expose `typesupport_helpers` API needed for the Rosbag2 (`#2858 <https://github.com/ros2/rclcpp/issues/2858>`_)
|
||||
* Remove comment about now-removed StaticSingleThreadedExecutor (`#2893 <https://github.com/ros2/rclcpp/issues/2893>`_)
|
||||
* Add overload of `append_parameter_override` (`#2891 <https://github.com/ros2/rclcpp/issues/2891>`_)
|
||||
* fix: Don't deadlock if removing shutdown callbacks in a shutdown callback (`#2886 <https://github.com/ros2/rclcpp/issues/2886>`_)
|
||||
* Contributors: Christophe Bedard, Janosch Machowinski, Michael Orlov, Michiel Leegwater, Patrick Roncagliolo, Sriharsha Ghanta, Tomoya Fujita
|
||||
* Fix REP url locations (`#2987 <https://github.com/ros2/rclcpp/issues/2987>`_) (`#2989 <https://github.com/ros2/rclcpp/issues/2989>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
30.0.0 (2025-07-01)
|
||||
29.5.4 (2025-10-21)
|
||||
-------------------
|
||||
* Hand-code logging.hpp (`#2870 <https://github.com/ros2/rclcpp/issues/2870>`_)
|
||||
* Adressed TODO in node_graph (`#2877 <https://github.com/ros2/rclcpp/issues/2877>`_)
|
||||
* fix test_publisher_with_system_default_qos. (`#2881 <https://github.com/ros2/rclcpp/issues/2881>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Chris Lalancette, Tomoya Fujita
|
||||
|
||||
29.6.1 (2025-06-23)
|
||||
29.5.3 (2025-09-11)
|
||||
-------------------
|
||||
* Fix for memory leaks in rclcpp::SerializedMessage (`#2861 <https://github.com/ros2/rclcpp/issues/2861>`_)
|
||||
* Removed warning test_qos (`#2859 <https://github.com/ros2/rclcpp/issues/2859>`_)
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_)
|
||||
* get_all_data_impl() does not handle null pointers properly, causing segmentation fault (`#2840 <https://github.com/ros2/rclcpp/issues/2840>`_)
|
||||
* QoSInitialization::from_rmw does not validate invalid history policy values, leading to silent failures (`#2841 <https://github.com/ros2/rclcpp/issues/2841>`_)
|
||||
* remove get_notify_guard_condition from NodeBaseInterface. (`#2839 <https://github.com/ros2/rclcpp/issues/2839>`_)
|
||||
* Removed deprecated StaticSingleThreadedExecutor (`#2835 <https://github.com/ros2/rclcpp/issues/2835>`_)
|
||||
* Removed deprecated rcpputils Path (`#2834 <https://github.com/ros2/rclcpp/issues/2834>`_)
|
||||
* Add range constraints for applicable array parameters (`#2828 <https://github.com/ros2/rclcpp/issues/2828>`_)
|
||||
* Update RingBufferImplementation to clear internal data. (`#2837 <https://github.com/ros2/rclcpp/issues/2837>`_)
|
||||
* Removed deprecated cancel_sleep_or_wait (`#2836 <https://github.com/ros2/rclcpp/issues/2836>`_)
|
||||
* Add missing 's' to 'NodeParametersInterface' in doc/comment (`#2831 <https://github.com/ros2/rclcpp/issues/2831>`_)
|
||||
* subordinate node consistent behavior and update docstring. (`#2822 <https://github.com/ros2/rclcpp/issues/2822>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Alex Youngs, Christophe Bedard, Michael Carlstrom, Michael Orlov, Tomoya Fujita
|
||||
* Fix: improve exception context for parameter_value_from (`#2917 <https://github.com/ros2/rclcpp/issues/2917>`_) (`#2919 <https://github.com/ros2/rclcpp/issues/2919>`_)
|
||||
* Allow for implicitly convertable loggers as well (`#2922 <https://github.com/ros2/rclcpp/issues/2922>`_) (`#2936 <https://github.com/ros2/rclcpp/issues/2936>`_)
|
||||
* Fix `start_type_description_service` param handling (`#2897 <https://github.com/ros2/rclcpp/issues/2897>`_) (`#2908 <https://github.com/ros2/rclcpp/issues/2908>`_)
|
||||
* Add qos parameter for wait_for_message function (`#2903 <https://github.com/ros2/rclcpp/issues/2903>`_) (`#2905 <https://github.com/ros2/rclcpp/issues/2905>`_)
|
||||
* Expose `typesupport_helpers` API needed for the Rosbag2 (`#2858 <https://github.com/ros2/rclcpp/issues/2858>`_) (`#2901 <https://github.com/ros2/rclcpp/issues/2901>`_)
|
||||
* Fujitatomoya/test append parameter override (`#2896 <https://github.com/ros2/rclcpp/issues/2896>`_) (`#2899 <https://github.com/ros2/rclcpp/issues/2899>`_)
|
||||
* Add overload of `append_parameter_override` (`#2891 <https://github.com/ros2/rclcpp/issues/2891>`_) (`#2894 <https://github.com/ros2/rclcpp/issues/2894>`_)
|
||||
* Contributors: Tim Clephas, mergify[bot]
|
||||
|
||||
29.6.0 (2025-04-25)
|
||||
29.5.2 (2025-07-07)
|
||||
-------------------
|
||||
* Shutdown deadlock fix jazzy (`#2887 <https://github.com/ros2/rclcpp/issues/2887>`_) (`#2888 <https://github.com/ros2/rclcpp/issues/2888>`_)
|
||||
* Fix test_publisher_with_system_default_qos (`#2881 <https://github.com/ros2/rclcpp/issues/2881>`_) (`#2884 <https://github.com/ros2/rclcpp/issues/2884>`_)
|
||||
* Contributors: Tomoya Fujita, Janosch Machowinski
|
||||
|
||||
29.5.1 (2025-06-23)
|
||||
-------------------
|
||||
* Removed warning test_qos (`#2859 <https://github.com/ros2/rclcpp/issues/2859>`_) (`#2873 <https://github.com/ros2/rclcpp/issues/2873>`_)
|
||||
* Fix for memory leaks in rclcpp::SerializedMessage (`#2861 <https://github.com/ros2/rclcpp/issues/2861>`_) (`#2863 <https://github.com/ros2/rclcpp/issues/2863>`_)
|
||||
* get_all_data_impl() does not handle null pointers properly, causing segmentation fault (backport `#2840 <https://github.com/ros2/rclcpp/issues/2840>`_) (`#2850 <https://github.com/ros2/rclcpp/issues/2850>`_)
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
|
||||
* QoSInitialization::from_rmw does not validate invalid history policy values, leading to silent failures (`#2841 <https://github.com/ros2/rclcpp/issues/2841>`_) (`#2846 <https://github.com/ros2/rclcpp/issues/2846>`_)
|
||||
* Add missing 's' to 'NodeParametersInterface' in doc/comment (`#2831 <https://github.com/ros2/rclcpp/issues/2831>`_) (`#2833 <https://github.com/ros2/rclcpp/issues/2833>`_)
|
||||
* subordinate node consistent behavior and update docstring. (`#2822 <https://github.com/ros2/rclcpp/issues/2822>`_) (`#2830 <https://github.com/ros2/rclcpp/issues/2830>`_)
|
||||
* throws std::invalid_argument if ParameterEvent is NULL. (`#2814 <https://github.com/ros2/rclcpp/issues/2814>`_)
|
||||
* Removed clang warnings (`#2823 <https://github.com/ros2/rclcpp/issues/2823>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Tomoya Fujita
|
||||
* Contributors: Alejandro Hernández Cordero, Tomoya Fujita, mergify[bot]
|
||||
|
||||
29.5.0 (2025-04-18)
|
||||
-------------------
|
||||
|
||||
@@ -70,6 +70,7 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/executors/executor_notify_waitable.cpp
|
||||
src/rclcpp/executors/multi_threaded_executor.cpp
|
||||
src/rclcpp/executors/single_threaded_executor.cpp
|
||||
src/rclcpp/executors/static_single_threaded_executor.cpp
|
||||
src/rclcpp/expand_topic_or_service_name.cpp
|
||||
src/rclcpp/experimental/executors/events_executor/events_executor.cpp
|
||||
src/rclcpp/experimental/timers_manager.cpp
|
||||
@@ -146,6 +147,27 @@ set(Python3_FIND_UNVERSIONED_NAMES FIRST)
|
||||
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||
|
||||
# "watch" template for changes
|
||||
configure_file(
|
||||
"resource/logging.hpp.em"
|
||||
"logging.hpp.em.watch"
|
||||
COPYONLY
|
||||
)
|
||||
# generate header with logging macros
|
||||
set(python_code_logging
|
||||
"import em"
|
||||
"em.invoke(['-o', 'include/rclcpp/logging.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/logging.hpp.em'])")
|
||||
string(REPLACE ";" "$<SEMICOLON>" python_code_logging "${python_code_logging}")
|
||||
add_custom_command(OUTPUT include/rclcpp/logging.hpp
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp"
|
||||
COMMAND Python3::Interpreter ARGS -c "${python_code_logging}"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/logging.hpp.em.watch"
|
||||
COMMENT "Expanding logging.hpp.em"
|
||||
VERBATIM
|
||||
)
|
||||
list(APPEND ${PROJECT_NAME}_SRCS
|
||||
include/rclcpp/logging.hpp)
|
||||
|
||||
file(GLOB interface_files "include/rclcpp/node_interfaces/node_*_interface.hpp")
|
||||
foreach(interface_file ${interface_files})
|
||||
get_filename_component(interface_name ${interface_file} NAME_WE)
|
||||
|
||||
@@ -21,22 +21,6 @@ GENERATE_LATEX = NO
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
EXCLUDE_SYMBOLS += RCLCPP_STATIC_ASSERT_LOGGER
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_ONCE
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_EXPRESSION
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_FUNCTION
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_SKIPFIRST
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_TIME_POINT_FUNC
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_THROTTLE
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_SKIPFIRST_THROTTLE
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_STREAM
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_STREAM_ONCE
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_STREAM_EXPRESSION
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_STREAM_FUNCTION
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_STREAM_SKIPFIRST
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_STREAM_THROTTLE
|
||||
EXCLUDE_SYMBOLS += RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE
|
||||
PREDEFINED += DOXYGEN_ONLY
|
||||
PREDEFINED += RCLCPP_LOCAL=
|
||||
PREDEFINED += RCLCPP_PUBLIC=
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
This document is a declaration of software quality for the `rclcpp` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
This document is a declaration of software quality for the `rclcpp` package, based on the guidelines in [REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
|
||||
# rclcpp Quality Declaration
|
||||
|
||||
The package `rclcpp` claims to be in the **Quality Level 1** category when it is used with a **Quality Level 1** middleware.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
|
||||
## Version Policy [1]
|
||||
|
||||
@@ -55,7 +55,7 @@ All pull requests will be peer-reviewed, check [ROS 2 Developer Guide](https://d
|
||||
|
||||
### Continuous Integration [2.iv]
|
||||
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://www.ros.org/reps/rep-2000.html#support-tiers)
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://reps.openrobotics.org/rep-2000/#support-tiers)
|
||||
|
||||
Currently nightly results can be seen here:
|
||||
|
||||
@@ -213,7 +213,7 @@ It is **Quality Level 1**, see its [Quality Declaration document](https://github
|
||||
|
||||
## Platform Support [6]
|
||||
|
||||
`rclcpp` supports all of the tier 1 platforms as described in [REP-2000](https://www.ros.org/reps/rep-2000.html#support-tiers), and tests each change against all of them.
|
||||
`rclcpp` supports all of the tier 1 platforms as described in [REP-2000](https://reps.openrobotics.org/rep-2000/#support-tiers), and tests each change against all of them.
|
||||
|
||||
Currently nightly build status can be seen here:
|
||||
* [linux-aarch64_release](https://ci.ros2.org/view/nightly/job/nightly_linux-aarch64_release/lastBuild/rclcpp/)
|
||||
@@ -225,4 +225,4 @@ Currently nightly build status can be seen here:
|
||||
|
||||
### Vulnerability Disclosure Policy [7.i]
|
||||
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://www.ros.org/reps/rep-2006.html).
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://reps.openrobotics.org/rep-2006/).
|
||||
|
||||
@@ -200,6 +200,21 @@ public:
|
||||
bool
|
||||
ros_time_is_active();
|
||||
|
||||
/**
|
||||
* Deprecated. This API is broken, as there is no way to get a deep
|
||||
* copy of a clock. Therefore one can experience spurious wakeups triggered
|
||||
* by some other instance of a clock.
|
||||
*
|
||||
* Cancels an ongoing or future sleep operation of one thread.
|
||||
*
|
||||
* This function can be used by one thread, to wakeup another thread that is
|
||||
* blocked using any of the sleep_ or wait_ methods of this class.
|
||||
*/
|
||||
[[deprecated("Use ClockConditionalVariable")]]
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
cancel_sleep_or_wait();
|
||||
|
||||
/// Return the rcl_clock_t clock handle
|
||||
RCLCPP_PUBLIC
|
||||
rcl_clock_t *
|
||||
|
||||
@@ -37,10 +37,6 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace graph_listener
|
||||
{
|
||||
class GraphListener;
|
||||
} // namespace graph_listener
|
||||
|
||||
/// Thrown when init is called on an already initialized context.
|
||||
class ContextAlreadyInitialized : public std::runtime_error
|
||||
@@ -313,10 +309,6 @@ public:
|
||||
std::shared_ptr<rcl_context_t>
|
||||
get_rcl_context();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<rclcpp::graph_listener::GraphListener>
|
||||
get_graph_listener();
|
||||
|
||||
/// Sleep for a given period of time or until shutdown() is called.
|
||||
/**
|
||||
* This function can be interrupted early if:
|
||||
@@ -389,19 +381,16 @@ private:
|
||||
std::recursive_mutex sub_contexts_mutex_;
|
||||
|
||||
std::vector<std::shared_ptr<OnShutdownCallback>> on_shutdown_callbacks_;
|
||||
mutable std::recursive_mutex on_shutdown_callbacks_mutex_;
|
||||
mutable std::mutex on_shutdown_callbacks_mutex_;
|
||||
|
||||
std::vector<std::shared_ptr<PreShutdownCallback>> pre_shutdown_callbacks_;
|
||||
mutable std::recursive_mutex pre_shutdown_callbacks_mutex_;
|
||||
mutable std::mutex pre_shutdown_callbacks_mutex_;
|
||||
|
||||
/// Condition variable for timed sleep (see sleep_for).
|
||||
std::condition_variable interrupt_condition_variable_;
|
||||
/// Mutex for protecting the global condition variable.
|
||||
std::mutex interrupt_mutex_;
|
||||
|
||||
/// Graph Listener which waits on graph changes for the node and is shared across nodes.
|
||||
std::shared_ptr<rclcpp::graph_listener::GraphListener> graph_listener_;
|
||||
|
||||
/// Keep shared ownership of global vector of weak contexts
|
||||
std::shared_ptr<WeakContextsWrapper> weak_contexts_;
|
||||
|
||||
|
||||
@@ -371,9 +371,6 @@ public:
|
||||
* 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`.
|
||||
* \note This method will check the future and the timeout only when the executor is woken up.
|
||||
* If this future is unrelated to an executor's entity, this method will not correctly detect
|
||||
* when it's completed and therefore may wait forever and never time out.
|
||||
*/
|
||||
template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
FutureReturnCode
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "rclcpp/executors/multi_threaded_executor.hpp"
|
||||
#include "rclcpp/executors/single_threaded_executor.hpp"
|
||||
#include "rclcpp/executors/static_single_threaded_executor.hpp"
|
||||
#include "rclcpp/experimental/executors/events_executor/events_executor.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
@@ -28,82 +29,24 @@
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Create a default single-threaded executor and execute all available work exhaustively.
|
||||
* @param node_ptr Shared pointer to the base interface of the node to spin.
|
||||
* @param max_duration max duration to spin
|
||||
*
|
||||
* This method is deprecated because it can lead to very bad performance if used in a loop:
|
||||
* each call will create a new executor and register the node, which is an expensive operation.
|
||||
* It's recommended to always manually instantiate an executor and call the methods with
|
||||
* the same name on it.
|
||||
* For example:
|
||||
* SingleThreadedExecutor executor;
|
||||
* executor.add_node(node_ptr);
|
||||
* executor.spin_all(max_duration);
|
||||
* If you are using a non-default context, this should be passed to the executor's constructor.
|
||||
*/
|
||||
[[deprecated("use SingleThreadedExecutor::spin_all instead")]]
|
||||
/// Create a default single-threaded executor and execute all available work exhaustively.
|
||||
/** \param[in] node_ptr Shared pointer to the node to spin. */
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_all(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
std::chrono::nanoseconds max_duration);
|
||||
|
||||
/**
|
||||
* @brief Create a default single-threaded executor and execute all available work exhaustively.
|
||||
* @param node_ptr Shared pointer to the node to spin.
|
||||
* @param max_duration max duration to spin
|
||||
*
|
||||
* This method is deprecated because it can lead to very bad performance if used in a loop:
|
||||
* each call will create a new executor and register the node, which is an expensive operation.
|
||||
* It's recommended to always manually instantiate an executor and call the methods with
|
||||
* the same name on it.
|
||||
* For example:
|
||||
* SingleThreadedExecutor executor;
|
||||
* executor.add_node(node_ptr);
|
||||
* executor.spin_all(max_duration);
|
||||
* If you are using a non-default context, this should be passed to the executor's constructor.
|
||||
*/
|
||||
[[deprecated("use SingleThreadedExecutor::spin_all instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_all(rclcpp::Node::SharedPtr node_ptr, std::chrono::nanoseconds max_duration);
|
||||
|
||||
/**
|
||||
* @brief Create a default single-threaded executor and execute any immediately available work.
|
||||
* @param node_ptr Shared pointer to the base interface of the node to spin.
|
||||
*
|
||||
* This method is deprecated because it can lead to very bad performance if used in a loop:
|
||||
* each call will create a new executor and register the node, which is an expensive operation.
|
||||
* It's recommended to always manually instantiate an executor and call the methods with
|
||||
* the same name on it.
|
||||
* For example:
|
||||
* SingleThreadedExecutor executor;
|
||||
* executor.add_node(node_ptr);
|
||||
* executor.spin_some();
|
||||
* If you are using a non-default context, this should be passed to the executor's constructor.
|
||||
*/
|
||||
[[deprecated("use SingleThreadedExecutor::spin_some instead")]]
|
||||
/// Create a default single-threaded executor and execute any immediately available work.
|
||||
/** \param[in] node_ptr Shared pointer to the node to spin. */
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_some(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
|
||||
|
||||
/**
|
||||
* @brief Create a default single-threaded executor and execute any immediately available work.
|
||||
* @param node_ptr Shared pointer to the node to spin.
|
||||
*
|
||||
* This method is deprecated because it can lead to very bad performance if used in a loop:
|
||||
* each call will create a new executor and register the node, which is an expensive operation.
|
||||
* It's recommended to always manually instantiate an executor and call the methods with
|
||||
* the same name on it.
|
||||
* For example:
|
||||
* SingleThreadedExecutor executor;
|
||||
* executor.add_node(node_ptr);
|
||||
* executor.spin_some();
|
||||
* If you are using a non-default context, this should be passed to the executor's constructor.
|
||||
*/
|
||||
[[deprecated("use SingleThreadedExecutor::spin_some instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_some(rclcpp::Node::SharedPtr node_ptr);
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
// Copyright 2019 Nobleo Technology
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_
|
||||
#define RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/executor.hpp"
|
||||
#include "rclcpp/executors/executor_entities_collection.hpp"
|
||||
#include "rclcpp/executors/single_threaded_executor.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
|
||||
/// Static executor implementation
|
||||
/**
|
||||
* This executor is a static version of the original single threaded executor.
|
||||
* It contains some performance optimization to avoid unnecessary reconstructions of
|
||||
* the executable list for every iteration.
|
||||
* All nodes, callbackgroups, timers, subscriptions etc. are created before
|
||||
* spin() is called, and modified only when an entity is added/removed to/from a node.
|
||||
* This executor is deprecated because these performance improvements have now been
|
||||
* applied to all other executors.
|
||||
* This executor is also considered unstable due to known bugs.
|
||||
* See the unit-tests that are only applied to `StandardExecutors` for information
|
||||
* on the known limitations.
|
||||
*
|
||||
* To run this executor instead of SingleThreadedExecutor replace:
|
||||
* rclcpp::executors::SingleThreadedExecutor exec;
|
||||
* by
|
||||
* rclcpp::executors::StaticSingleThreadedExecutor exec;
|
||||
* in your source code and spin node(s) in the following way:
|
||||
* exec.add_node(node);
|
||||
* exec.spin();
|
||||
* exec.remove_node(node);
|
||||
*/
|
||||
class [[deprecated("Use rclcpp::executors::SingleThreadedExecutor")]] StaticSingleThreadedExecutor
|
||||
: public rclcpp::Executor
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(StaticSingleThreadedExecutor)
|
||||
|
||||
/// Default constructor. See the default constructor for Executor.
|
||||
RCLCPP_PUBLIC
|
||||
explicit StaticSingleThreadedExecutor(
|
||||
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
|
||||
|
||||
/// Default destructor.
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~StaticSingleThreadedExecutor();
|
||||
|
||||
/// Static executor implementation of spin.
|
||||
/**
|
||||
* This function will block until work comes in, execute it, and keep blocking.
|
||||
* It will only be interrupted by a CTRL-C (managed by the global signal handler).
|
||||
* \throws std::runtime_error when spin() called while already spinning
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin() override;
|
||||
|
||||
/// Static executor implementation of spin some
|
||||
/**
|
||||
* This non-blocking function will execute entities that
|
||||
* were ready when this API was called, until timeout or no
|
||||
* more work available. Entities that got ready while
|
||||
* executing work, won't be taken into account here.
|
||||
*
|
||||
* Example:
|
||||
* while(condition) {
|
||||
* spin_some();
|
||||
* sleep(); // User should have some sync work or
|
||||
* // sleep to avoid a 100% CPU usage
|
||||
* }
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_some(std::chrono::nanoseconds max_duration = std::chrono::nanoseconds(0)) override;
|
||||
|
||||
/// Static executor implementation of spin all
|
||||
/**
|
||||
* This non-blocking function will execute entities until timeout (must be >= 0)
|
||||
* or no more work available.
|
||||
* If timeout is `0`, potentially it blocks forever until no more work is available.
|
||||
* If new entities get ready while executing work available, they will be executed
|
||||
* as long as the timeout hasn't expired.
|
||||
*
|
||||
* Example:
|
||||
* while(condition) {
|
||||
* spin_all();
|
||||
* sleep(); // User should have some sync work or
|
||||
* // sleep to avoid a 100% CPU usage
|
||||
* }
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_all(std::chrono::nanoseconds max_duration) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Executes ready executables from wait set.
|
||||
* @param collection entities to evaluate for ready executables.
|
||||
* @param wait_result result to check for ready executables.
|
||||
* @param spin_once if true executes only the first ready executable.
|
||||
* @return true if any executable was ready.
|
||||
*/
|
||||
bool
|
||||
execute_ready_executables(
|
||||
const rclcpp::executors::ExecutorEntitiesCollection & collection,
|
||||
rclcpp::WaitResult<rclcpp::WaitSet> & wait_result,
|
||||
bool spin_once);
|
||||
|
||||
void
|
||||
spin_some_impl(std::chrono::nanoseconds max_duration, bool exhaustive);
|
||||
|
||||
void
|
||||
spin_once_impl(std::chrono::nanoseconds timeout) override;
|
||||
|
||||
std::optional<rclcpp::WaitResult<rclcpp::WaitSet>>
|
||||
collect_and_wait(std::chrono::nanoseconds timeout);
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(StaticSingleThreadedExecutor)
|
||||
};
|
||||
|
||||
} // namespace executors
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_
|
||||
@@ -178,8 +178,6 @@ public:
|
||||
void clear() override
|
||||
{
|
||||
TRACETOOLS_TRACEPOINT(rclcpp_ring_buffer_clear, static_cast<const void *>(this));
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
clear_();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -229,14 +227,6 @@ private:
|
||||
return capacity_ - size_;
|
||||
}
|
||||
|
||||
inline void clear_()
|
||||
{
|
||||
ring_buffer_.clear();
|
||||
size_ = 0;
|
||||
read_index_ = 0;
|
||||
write_index_ = capacity_ - 1;
|
||||
}
|
||||
|
||||
/// Traits for checking if a type is std::unique_ptr
|
||||
template<typename ...>
|
||||
struct is_std_unique_ptr final : std::false_type {};
|
||||
@@ -306,7 +296,7 @@ private:
|
||||
return {};
|
||||
}
|
||||
|
||||
const size_t capacity_;
|
||||
size_t capacity_;
|
||||
|
||||
std::vector<BufferT> ring_buffer_;
|
||||
|
||||
|
||||
@@ -64,17 +64,17 @@ public:
|
||||
|
||||
/// Default constructor. See the default constructor for Executor.
|
||||
/**
|
||||
* \param[in] options Options used to configure the executor.
|
||||
* \param[in] events_queue The queue used to store events.
|
||||
* \param[in] execute_timers_separate_thread If true, timers are executed in a separate
|
||||
* thread. If false, timers are executed in the same thread as all other entities.
|
||||
* \param[in] options Options used to configure the executor.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
EventsExecutor(
|
||||
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions(),
|
||||
rclcpp::experimental::executors::EventsQueue::UniquePtr events_queue = std::make_unique<
|
||||
rclcpp::experimental::executors::SimpleEventsQueue>(),
|
||||
bool execute_timers_separate_thread = false);
|
||||
bool execute_timers_separate_thread = false,
|
||||
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
|
||||
|
||||
/// Default destructor.
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
@@ -154,12 +154,6 @@ public:
|
||||
bool
|
||||
is_shutdown();
|
||||
|
||||
/// Return true if the graph listener was started.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
bool
|
||||
is_started();
|
||||
|
||||
protected:
|
||||
/// Main function for the listening thread.
|
||||
RCLCPP_PUBLIC
|
||||
@@ -187,6 +181,7 @@ private:
|
||||
void
|
||||
__shutdown();
|
||||
|
||||
std::weak_ptr<rclcpp::Context> weak_parent_context_;
|
||||
std::shared_ptr<rcl_context_t> rcl_parent_context_;
|
||||
|
||||
std::thread listener_thread_;
|
||||
|
||||
@@ -78,6 +78,34 @@ RCLCPP_PUBLIC
|
||||
Logger
|
||||
get_node_logger(const rcl_node_t * node);
|
||||
|
||||
// TODO(ahcorde): Remove deprecated class on the next release (in Rolling after Kilted).
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
/// Get the current logging directory.
|
||||
/**
|
||||
* For more details of how the logging directory is determined,
|
||||
* see rcl_logging_get_logging_directory().
|
||||
*
|
||||
* \returns the logging directory being used.
|
||||
* \throws rclcpp::exceptions::RCLError if an unexpected error occurs.
|
||||
*/
|
||||
[[deprecated("use rclcpp::get_log_directory instead of rclcpp::get_logging_directory")]]
|
||||
RCLCPP_PUBLIC
|
||||
rcpputils::fs::path
|
||||
get_logging_directory();
|
||||
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/// Get the current logging directory.
|
||||
/**
|
||||
* For more details of how the logging directory is determined,
|
||||
|
||||
@@ -1,983 +0,0 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__LOGGING_HPP_
|
||||
#define RCLCPP__LOGGING_HPP_
|
||||
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rcutils/logging_macros.h"
|
||||
|
||||
// These are used for compiling out logging macros lower than a minimum severity.
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_DEBUG 0
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_INFO 1
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_WARN 2
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_ERROR 3
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_FATAL 4
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_NONE 5
|
||||
|
||||
#define RCLCPP_STATIC_ASSERT_LOGGER(logger) \
|
||||
do { \
|
||||
static_assert( \
|
||||
::std::is_convertible_v<decltype(logger), ::rclcpp::Logger>, \
|
||||
"First argument to logging macros must be an rclcpp::Logger"); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG
|
||||
* Log a message with given severity.
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param ... The format string, followed by the variable arguments for the format string.
|
||||
*/
|
||||
#define RCLCPP_LOG(severity, logger, ...) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
RCUTILS_LOG_NAMED(severity, (logger).get_name(), __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_ONCE
|
||||
* Log a message with given severity with the following condition:
|
||||
* - All log calls except the first one are ignored.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param ... The format string, followed by the variable arguments for the format string.
|
||||
*/
|
||||
#define RCLCPP_LOG_ONCE(severity, logger, ...) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
RCUTILS_LOG_ONCE_NAMED(severity, (logger).get_name(), __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_EXPRESSION
|
||||
* Log a message with given severity with the following condition:
|
||||
* - Log calls are ignored when the expression evaluates to false.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param expression The expression determining if the message should be logged
|
||||
* \param ... The format string, followed by the variable arguments for the format string.
|
||||
*/
|
||||
#define RCLCPP_LOG_EXPRESSION(severity, logger, expression, ...) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
RCUTILS_LOG_EXPRESSION_NAMED(severity, expression, (logger).get_name(), __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_FUNCTION
|
||||
* Log a message with given severity with the following condition:
|
||||
* - Log calls are ignored when the function returns false.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param function The functions return value determines if the message should be logged
|
||||
* \param ... The format string, followed by the variable arguments for the format string.
|
||||
*/
|
||||
#define RCLCPP_LOG_FUNCTION(severity, logger, function, ...) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
RCUTILS_LOG_FUNCTION_NAMED(severity, function, (logger).get_name(), __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_SKIPFIRST
|
||||
* Log a message with given severity with the following condition:
|
||||
* - The first log call is ignored but all subsequent calls are processed.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param ... The format string, followed by the variable arguments for the format string.
|
||||
*/
|
||||
#define RCLCPP_LOG_SKIPFIRST(severity, logger, ...) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
RCUTILS_LOG_SKIPFIRST_NAMED(severity, (logger).get_name(), __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RCLCPP_LOG_TIME_POINT_FUNC(clock) \
|
||||
[&c = clock](rcutils_time_point_value_t * time_point)->rcutils_ret_t { \
|
||||
try { \
|
||||
*time_point = c.now().nanoseconds(); \
|
||||
} catch (...) { \
|
||||
RCUTILS_SAFE_FWRITE_TO_STDERR( \
|
||||
"[rclcpp|logging.hpp] RCLCPP_DEBUG_THROTTLE could not get current time stamp\n"); \
|
||||
return RCUTILS_RET_ERROR; \
|
||||
} \
|
||||
return RCUTILS_RET_OK; \
|
||||
}
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_THROTTLE
|
||||
* Log a message with given severity with the following condition:
|
||||
* - Log calls are ignored if the last logged message is not longer ago than the specified duration.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param clock rclcpp::Clock that will be used to get the time point.
|
||||
* \param duration The duration of the throttle interval as an integral value in milliseconds.
|
||||
* \param ... The format string, followed by the variable arguments for the format string.
|
||||
*/
|
||||
#define RCLCPP_LOG_THROTTLE(severity, logger, clock, duration, ...) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
RCUTILS_LOG_THROTTLE_NAMED( \
|
||||
severity, \
|
||||
RCLCPP_LOG_TIME_POINT_FUNC(clock), \
|
||||
duration, \
|
||||
(logger).get_name(), \
|
||||
__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_SKIPFIRST_THROTTLE
|
||||
* Log a message with given severity with the following conditions:
|
||||
* - The first log call is ignored but all subsequent calls are processed.
|
||||
* - Log calls are ignored if the last logged message is not longer ago than the specified duration.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param clock rclcpp::Clock that will be used to get the time point.
|
||||
* \param duration The duration of the throttle interval as an integral value in milliseconds.
|
||||
* \param ... The format string, followed by the variable arguments for the format string.
|
||||
*/
|
||||
#define RCLCPP_LOG_SKIPFIRST_THROTTLE(severity, logger, clock, duration, ...) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
RCUTILS_LOG_SKIPFIRST_THROTTLE_NAMED( \
|
||||
severity, \
|
||||
RCLCPP_LOG_TIME_POINT_FUNC(clock), \
|
||||
duration, \
|
||||
(logger).get_name(), \
|
||||
__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_STREAM
|
||||
* Log a message with given severity.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param stream_arg The argument << into a stringstream
|
||||
*/
|
||||
#define RCLCPP_LOG_STREAM(severity, logger, stream_arg) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
std::stringstream rclcpp_stream_ss_; \
|
||||
rclcpp_stream_ss_ << stream_arg; \
|
||||
RCUTILS_LOG_NAMED(severity, (logger).get_name(), "%s", rclcpp_stream_ss_.str().c_str()); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_STREAM_ONCE
|
||||
* Log a message with given severity with the following condition:
|
||||
* - All log calls except the first one are ignored.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param stream_arg The argument << into a stringstream
|
||||
*/
|
||||
#define RCLCPP_LOG_STREAM_ONCE(severity, logger, stream_arg) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
std::stringstream rclcpp_stream_ss_; \
|
||||
rclcpp_stream_ss_ << stream_arg; \
|
||||
RCUTILS_LOG_ONCE_NAMED(severity, (logger).get_name(), "%s", rclcpp_stream_ss_.str().c_str()); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_STREAM_EXPRESSION
|
||||
* Log a message with given severity with the following condition:
|
||||
* - Log calls are being ignored when the expression evaluates to false.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param expression The expression determining if the message should be logged
|
||||
* \param stream_arg The argument << into a stringstream
|
||||
*/
|
||||
#define RCLCPP_LOG_STREAM_EXPRESSION(severity, logger, expression, stream_arg) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
std::stringstream rclcpp_stream_ss_; \
|
||||
rclcpp_stream_ss_ << stream_arg; \
|
||||
RCUTILS_LOG_EXPRESSION_NAMED( \
|
||||
severity, \
|
||||
expression, \
|
||||
(logger).get_name(), \
|
||||
"%s", rclcpp_stream_ss_.str().c_str()); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_STREAM_FUNCTION
|
||||
* Log a message with given severity with the following condition:
|
||||
* - Log calls are being ignored when the function returns false.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param function The functions return value determines if the message should be logged
|
||||
* \param stream_arg The argument << into a stringstream
|
||||
*/
|
||||
#define RCLCPP_LOG_STREAM_FUNCTION(severity, logger, function, stream_arg) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
std::stringstream rclcpp_stream_ss_; \
|
||||
rclcpp_stream_ss_ << stream_arg; \
|
||||
RCUTILS_LOG_FUNCTION_NAMED( \
|
||||
severity, \
|
||||
function, \
|
||||
(logger).get_name(), \
|
||||
"%s", rclcpp_stream_ss_.str().c_str()); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_STREAM_SKIPFIRST
|
||||
* Log a message with given severity with the following condition:
|
||||
* - The first log call is ignored but all subsequent calls are processed.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param stream_arg The argument << into a stringstream
|
||||
*/
|
||||
#define RCLCPP_LOG_STREAM_SKIPFIRST(severity, logger, stream_arg) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
std::stringstream rclcpp_stream_ss_; \
|
||||
rclcpp_stream_ss_ << stream_arg; \
|
||||
RCUTILS_LOG_SKIPFIRST_NAMED( \
|
||||
severity, \
|
||||
(logger).get_name(), \
|
||||
"%s", rclcpp_stream_ss_.str().c_str()); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_STREAM_THROTTLE
|
||||
* Log a message with given severity with the following condition:
|
||||
* - Log calls are ignored if the last logged message is not longer ago than the specified duration.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param clock rclcpp::Clock that will be used to get the time point.
|
||||
* \param duration The duration of the throttle interval as an integral value in milliseconds.
|
||||
* \param stream_arg The argument << into a stringstream
|
||||
*/
|
||||
#define RCLCPP_LOG_STREAM_THROTTLE(severity, logger, clock, duration, stream_arg) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
std::stringstream rclcpp_stream_ss_; \
|
||||
rclcpp_stream_ss_ << stream_arg; \
|
||||
RCUTILS_LOG_THROTTLE_NAMED( \
|
||||
severity, \
|
||||
RCLCPP_LOG_TIME_POINT_FUNC(clock), \
|
||||
duration, \
|
||||
(logger).get_name(), \
|
||||
"%s", rclcpp_stream_ss_.str().c_str()); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE
|
||||
* Log a message with given severity with the following conditions:
|
||||
* - The first log call is ignored but all subsequent calls are processed.
|
||||
* - Log calls are ignored if the last logged message is not longer ago than the specified duration.
|
||||
*
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
* \param clock rclcpp::Clock that will be used to get the time point.
|
||||
* \param duration The duration of the throttle interval as an integral value in milliseconds.
|
||||
* \param stream_arg The argument << into a stringstream
|
||||
*/
|
||||
#define RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE(severity, logger, clock, duration, stream_arg) \
|
||||
do { \
|
||||
RCLCPP_STATIC_ASSERT_LOGGER(logger); \
|
||||
std::stringstream rclcpp_stream_ss_; \
|
||||
rclcpp_stream_ss_ << stream_arg; \
|
||||
RCUTILS_LOG_SKIPFIRST_THROTTLE_NAMED( \
|
||||
severity, \
|
||||
RCLCPP_LOG_TIME_POINT_FUNC(clock), \
|
||||
duration, \
|
||||
(logger).get_name(), \
|
||||
"%s", rclcpp_stream_ss_.str().c_str()); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_MIN_SEVERITY
|
||||
* Define RCLCPP_LOG_MIN_SEVERITY=RCLCPP_LOG_MIN_SEVERITY_[DEBUG|INFO|WARN|ERROR|FATAL]
|
||||
* in your build options to compile out anything below that severity.
|
||||
* Use RCLCPP_LOG_MIN_SEVERITY_NONE to compile out all macros.
|
||||
*/
|
||||
#ifndef RCLCPP_LOG_MIN_SEVERITY
|
||||
#define RCLCPP_LOG_MIN_SEVERITY RCLCPP_LOG_MIN_SEVERITY_DEBUG
|
||||
#endif
|
||||
|
||||
/** @name Logging macros for severity DEBUG.
|
||||
*/
|
||||
#if (RCLCPP_LOG_MIN_SEVERITY > RCLCPP_LOG_MIN_SEVERITY_DEBUG)
|
||||
// empty logging macros for severity DEBUG when being disabled at compile time
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_ONCE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_EXPRESSION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_FUNCTION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_SKIPFIRST(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_SKIPFIRST_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_STREAM(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_STREAM_ONCE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_STREAM_EXPRESSION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_STREAM_FUNCTION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_STREAM_SKIPFIRST(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_STREAM_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_DEBUG_STREAM_SKIPFIRST_THROTTLE(...)
|
||||
|
||||
#else
|
||||
/**
|
||||
* \def RCLCPP_DEBUG
|
||||
* \copydoc RCLCPP_LOG
|
||||
*/
|
||||
#define RCLCPP_DEBUG(logger, ...) RCLCPP_LOG(RCUTILS_LOG_SEVERITY_DEBUG, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_ONCE
|
||||
* \copydoc RCLCPP_LOG_ONCE
|
||||
*/
|
||||
#define RCLCPP_DEBUG_ONCE(logger, ...) \
|
||||
RCLCPP_LOG_ONCE(RCUTILS_LOG_SEVERITY_DEBUG, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_EXPRESSION
|
||||
* \copydoc RCLCPP_LOG_EXPRESSION
|
||||
*/
|
||||
#define RCLCPP_DEBUG_EXPRESSION(logger, expression, ...) \
|
||||
RCLCPP_LOG_EXPRESSION(RCUTILS_LOG_SEVERITY_DEBUG, logger, expression, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_FUNCTION
|
||||
* \copydoc RCLCPP_LOG_FUNCTION
|
||||
*/
|
||||
#define RCLCPP_DEBUG_FUNCTION(logger, function, ...) \
|
||||
RCLCPP_LOG_FUNCTION(RCUTILS_LOG_SEVERITY_DEBUG, logger, function, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_SKIPFIRST
|
||||
* \copydoc RCLCPP_LOG_SKIPFIRST
|
||||
*/
|
||||
#define RCLCPP_DEBUG_SKIPFIRST(logger, ...) \
|
||||
RCLCPP_LOG_SKIPFIRST(RCUTILS_LOG_SEVERITY_DEBUG, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_DEBUG_THROTTLE(logger, clock, duration, ...) \
|
||||
RCLCPP_LOG_THROTTLE(RCUTILS_LOG_SEVERITY_DEBUG, logger, clock, duration, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_SKIPFIRST_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_SKIPFIRST_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_DEBUG_SKIPFIRST_THROTTLE(logger, clock, duration, ...) \
|
||||
RCLCPP_LOG_SKIPFIRST_THROTTLE(RCUTILS_LOG_SEVERITY_DEBUG, logger, clock, duration, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_STREAM
|
||||
* \copydoc RCLCPP_LOG_STREAM
|
||||
*/
|
||||
#define RCLCPP_DEBUG_STREAM(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM(RCUTILS_LOG_SEVERITY_DEBUG, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_STREAM_ONCE
|
||||
* \copydoc RCLCPP_LOG_STREAM_ONCE
|
||||
*/
|
||||
#define RCLCPP_DEBUG_STREAM_ONCE(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_ONCE(RCUTILS_LOG_SEVERITY_DEBUG, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_STREAM_EXPRESSION
|
||||
* \copydoc RCLCPP_LOG_STREAM_EXPRESSION
|
||||
*/
|
||||
#define RCLCPP_DEBUG_STREAM_EXPRESSION(logger, expression, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_EXPRESSION(RCUTILS_LOG_SEVERITY_DEBUG, logger, expression, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_STREAM_FUNCTION
|
||||
* \copydoc RCLCPP_LOG_STREAM_FUNCTION
|
||||
*/
|
||||
#define RCLCPP_DEBUG_STREAM_FUNCTION(logger, function, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_FUNCTION(RCUTILS_LOG_SEVERITY_DEBUG, logger, function, stream_args)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_STREAM_SKIPFIRST
|
||||
* \copydoc RCLCPP_LOG_STREAM_SKIPFIRST
|
||||
*/
|
||||
#define RCLCPP_DEBUG_STREAM_SKIPFIRST(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_SKIPFIRST(RCUTILS_LOG_SEVERITY_DEBUG, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_STREAM_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_STREAM_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_DEBUG_STREAM_THROTTLE(logger, clock, duration, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_THROTTLE(RCUTILS_LOG_SEVERITY_DEBUG, logger, clock, duration, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_DEBUG_STREAM_SKIPFIRST_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_DEBUG_STREAM_SKIPFIRST_THROTTLE(logger, clock, duration, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE(RCUTILS_LOG_SEVERITY_DEBUG, logger, clock, duration, \
|
||||
stream_arg)
|
||||
|
||||
#endif
|
||||
|
||||
/** @name Logging macros for severity INFO.
|
||||
*/
|
||||
#if (RCLCPP_LOG_MIN_SEVERITY > RCLCPP_LOG_MIN_SEVERITY_INFO)
|
||||
// empty logging macros for severity INFO when being disabled at compile time
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_ONCE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_EXPRESSION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_FUNCTION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_SKIPFIRST(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_SKIPFIRST_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_STREAM(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_STREAM_ONCE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_STREAM_EXPRESSION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_STREAM_FUNCTION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_STREAM_SKIPFIRST(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_STREAM_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_INFO_STREAM_SKIPFIRST_THROTTLE(...)
|
||||
|
||||
#else
|
||||
/**
|
||||
* \def RCLCPP_INFO
|
||||
* \copydoc RCLCPP_LOG
|
||||
*/
|
||||
#define RCLCPP_INFO(logger, ...) RCLCPP_LOG(RCUTILS_LOG_SEVERITY_INFO, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_ONCE
|
||||
* \copydoc RCLCPP_LOG_ONCE
|
||||
*/
|
||||
#define RCLCPP_INFO_ONCE(logger, ...) \
|
||||
RCLCPP_LOG_ONCE(RCUTILS_LOG_SEVERITY_INFO, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_EXPRESSION
|
||||
* \copydoc RCLCPP_LOG_EXPRESSION
|
||||
*/
|
||||
#define RCLCPP_INFO_EXPRESSION(logger, expression, ...) \
|
||||
RCLCPP_LOG_EXPRESSION(RCUTILS_LOG_SEVERITY_INFO, logger, expression, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_FUNCTION
|
||||
* \copydoc RCLCPP_LOG_FUNCTION
|
||||
*/
|
||||
#define RCLCPP_INFO_FUNCTION(logger, function, ...) \
|
||||
RCLCPP_LOG_FUNCTION(RCUTILS_LOG_SEVERITY_INFO, logger, function, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_SKIPFIRST
|
||||
* \copydoc RCLCPP_LOG_SKIPFIRST
|
||||
*/
|
||||
#define RCLCPP_INFO_SKIPFIRST(logger, ...) \
|
||||
RCLCPP_LOG_SKIPFIRST(RCUTILS_LOG_SEVERITY_INFO, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_INFO_THROTTLE(logger, clock, duration, ...) \
|
||||
RCLCPP_LOG_THROTTLE(RCUTILS_LOG_SEVERITY_INFO, logger, clock, duration, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_SKIPFIRST_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_SKIPFIRST_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_INFO_SKIPFIRST_THROTTLE(logger, clock, duration, ...) \
|
||||
RCLCPP_LOG_SKIPFIRST_THROTTLE(RCUTILS_LOG_SEVERITY_INFO, logger, clock, duration, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_STREAM
|
||||
* \copydoc RCLCPP_LOG_STREAM
|
||||
*/
|
||||
#define RCLCPP_INFO_STREAM(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM(RCUTILS_LOG_SEVERITY_INFO, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_STREAM_ONCE
|
||||
* \copydoc RCLCPP_LOG_STREAM_ONCE
|
||||
*/
|
||||
#define RCLCPP_INFO_STREAM_ONCE(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_ONCE(RCUTILS_LOG_SEVERITY_INFO, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_STREAM_EXPRESSION
|
||||
* \copydoc RCLCPP_LOG_STREAM_EXPRESSION
|
||||
*/
|
||||
#define RCLCPP_INFO_STREAM_EXPRESSION(logger, expression, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_EXPRESSION(RCUTILS_LOG_SEVERITY_INFO, logger, expression, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_STREAM_FUNCTION
|
||||
* \copydoc RCLCPP_LOG_STREAM_FUNCTION
|
||||
*/
|
||||
#define RCLCPP_INFO_STREAM_FUNCTION(logger, function, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_FUNCTION(RCUTILS_LOG_SEVERITY_INFO, logger, function, stream_args)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_STREAM_SKIPFIRST
|
||||
* \copydoc RCLCPP_LOG_STREAM_SKIPFIRST
|
||||
*/
|
||||
#define RCLCPP_INFO_STREAM_SKIPFIRST(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_SKIPFIRST(RCUTILS_LOG_SEVERITY_INFO, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_STREAM_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_STREAM_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_INFO_STREAM_THROTTLE(logger, clock, duration, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_THROTTLE(RCUTILS_LOG_SEVERITY_INFO, logger, clock, duration, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_INFO_STREAM_SKIPFIRST_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_INFO_STREAM_SKIPFIRST_THROTTLE(logger, clock, duration, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE(RCUTILS_LOG_SEVERITY_INFO, logger, clock, duration, \
|
||||
stream_arg)
|
||||
|
||||
#endif
|
||||
|
||||
/** @name Logging macros for severity WARN.
|
||||
*/
|
||||
#if (RCLCPP_LOG_MIN_SEVERITY > RCLCPP_LOG_MIN_SEVERITY_WARN)
|
||||
// empty logging macros for severity WARN when being disabled at compile time
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_ONCE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_EXPRESSION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_FUNCTION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_SKIPFIRST(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_SKIPFIRST_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_STREAM(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_STREAM_ONCE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_STREAM_EXPRESSION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_STREAM_FUNCTION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_STREAM_SKIPFIRST(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_STREAM_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_WARN_STREAM_SKIPFIRST_THROTTLE(...)
|
||||
|
||||
#else
|
||||
/**
|
||||
* \def RCLCPP_WARN
|
||||
* \copydoc RCLCPP_LOG
|
||||
*/
|
||||
#define RCLCPP_WARN(logger, ...) RCLCPP_LOG(RCUTILS_LOG_SEVERITY_WARN, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_ONCE
|
||||
* \copydoc RCLCPP_LOG_ONCE
|
||||
*/
|
||||
#define RCLCPP_WARN_ONCE(logger, ...) \
|
||||
RCLCPP_LOG_ONCE(RCUTILS_LOG_SEVERITY_WARN, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_EXPRESSION
|
||||
* \copydoc RCLCPP_LOG_EXPRESSION
|
||||
*/
|
||||
#define RCLCPP_WARN_EXPRESSION(logger, expression, ...) \
|
||||
RCLCPP_LOG_EXPRESSION(RCUTILS_LOG_SEVERITY_WARN, logger, expression, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_FUNCTION
|
||||
* \copydoc RCLCPP_LOG_FUNCTION
|
||||
*/
|
||||
#define RCLCPP_WARN_FUNCTION(logger, function, ...) \
|
||||
RCLCPP_LOG_FUNCTION(RCUTILS_LOG_SEVERITY_WARN, logger, function, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_SKIPFIRST
|
||||
* \copydoc RCLCPP_LOG_SKIPFIRST
|
||||
*/
|
||||
#define RCLCPP_WARN_SKIPFIRST(logger, ...) \
|
||||
RCLCPP_LOG_SKIPFIRST(RCUTILS_LOG_SEVERITY_WARN, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_WARN_THROTTLE(logger, clock, duration, ...) \
|
||||
RCLCPP_LOG_THROTTLE(RCUTILS_LOG_SEVERITY_WARN, logger, clock, duration, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_SKIPFIRST_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_SKIPFIRST_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_WARN_SKIPFIRST_THROTTLE(logger, clock, duration, ...) \
|
||||
RCLCPP_LOG_SKIPFIRST_THROTTLE(RCUTILS_LOG_SEVERITY_WARN, logger, clock, duration, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_STREAM
|
||||
* \copydoc RCLCPP_LOG_STREAM
|
||||
*/
|
||||
#define RCLCPP_WARN_STREAM(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM(RCUTILS_LOG_SEVERITY_WARN, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_STREAM_ONCE
|
||||
* \copydoc RCLCPP_LOG_STREAM_ONCE
|
||||
*/
|
||||
#define RCLCPP_WARN_STREAM_ONCE(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_ONCE(RCUTILS_LOG_SEVERITY_WARN, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_STREAM_EXPRESSION
|
||||
* \copydoc RCLCPP_LOG_STREAM_EXPRESSION
|
||||
*/
|
||||
#define RCLCPP_WARN_STREAM_EXPRESSION(logger, expression, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_EXPRESSION(RCUTILS_LOG_SEVERITY_WARN, logger, expression, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_STREAM_FUNCTION
|
||||
* \copydoc RCLCPP_LOG_STREAM_FUNCTION
|
||||
*/
|
||||
#define RCLCPP_WARN_STREAM_FUNCTION(logger, function, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_FUNCTION(RCUTILS_LOG_SEVERITY_WARN, logger, function, stream_args)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_STREAM_SKIPFIRST
|
||||
* \copydoc RCLCPP_LOG_STREAM_SKIPFIRST
|
||||
*/
|
||||
#define RCLCPP_WARN_STREAM_SKIPFIRST(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_SKIPFIRST(RCUTILS_LOG_SEVERITY_WARN, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_STREAM_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_STREAM_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_WARN_STREAM_THROTTLE(logger, clock, duration, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_THROTTLE(RCUTILS_LOG_SEVERITY_WARN, logger, clock, duration, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_WARN_STREAM_SKIPFIRST_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_WARN_STREAM_SKIPFIRST_THROTTLE(logger, clock, duration, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE(RCUTILS_LOG_SEVERITY_WARN, logger, clock, duration, \
|
||||
stream_arg)
|
||||
|
||||
#endif
|
||||
|
||||
/** @name Logging macros for severity ERROR.
|
||||
*/
|
||||
#if (RCLCPP_LOG_MIN_SEVERITY > RCLCPP_LOG_MIN_SEVERITY_ERROR)
|
||||
// empty logging macros for severity ERROR when being disabled at compile time
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_ONCE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_EXPRESSION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_FUNCTION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_SKIPFIRST(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_SKIPFIRST_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_STREAM(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_STREAM_ONCE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_STREAM_EXPRESSION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_STREAM_FUNCTION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_STREAM_SKIPFIRST(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_STREAM_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_ERROR_STREAM_SKIPFIRST_THROTTLE(...)
|
||||
|
||||
#else
|
||||
/**
|
||||
* \def RCLCPP_ERROR
|
||||
* \copydoc RCLCPP_LOG
|
||||
*/
|
||||
#define RCLCPP_ERROR(logger, ...) RCLCPP_LOG(RCUTILS_LOG_SEVERITY_ERROR, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_ONCE
|
||||
* \copydoc RCLCPP_LOG_ONCE
|
||||
*/
|
||||
#define RCLCPP_ERROR_ONCE(logger, ...) \
|
||||
RCLCPP_LOG_ONCE(RCUTILS_LOG_SEVERITY_ERROR, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_EXPRESSION
|
||||
* \copydoc RCLCPP_LOG_EXPRESSION
|
||||
*/
|
||||
#define RCLCPP_ERROR_EXPRESSION(logger, expression, ...) \
|
||||
RCLCPP_LOG_EXPRESSION(RCUTILS_LOG_SEVERITY_ERROR, logger, expression, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_FUNCTION
|
||||
* \copydoc RCLCPP_LOG_FUNCTION
|
||||
*/
|
||||
#define RCLCPP_ERROR_FUNCTION(logger, function, ...) \
|
||||
RCLCPP_LOG_FUNCTION(RCUTILS_LOG_SEVERITY_ERROR, logger, function, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_SKIPFIRST
|
||||
* \copydoc RCLCPP_LOG_SKIPFIRST
|
||||
*/
|
||||
#define RCLCPP_ERROR_SKIPFIRST(logger, ...) \
|
||||
RCLCPP_LOG_SKIPFIRST(RCUTILS_LOG_SEVERITY_ERROR, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_ERROR_THROTTLE(logger, clock, duration, ...) \
|
||||
RCLCPP_LOG_THROTTLE(RCUTILS_LOG_SEVERITY_ERROR, logger, clock, duration, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_SKIPFIRST_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_SKIPFIRST_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_ERROR_SKIPFIRST_THROTTLE(logger, clock, duration, ...) \
|
||||
RCLCPP_LOG_SKIPFIRST_THROTTLE(RCUTILS_LOG_SEVERITY_ERROR, logger, clock, duration, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_STREAM
|
||||
* \copydoc RCLCPP_LOG_STREAM
|
||||
*/
|
||||
#define RCLCPP_ERROR_STREAM(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM(RCUTILS_LOG_SEVERITY_ERROR, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_STREAM_ONCE
|
||||
* \copydoc RCLCPP_LOG_STREAM_ONCE
|
||||
*/
|
||||
#define RCLCPP_ERROR_STREAM_ONCE(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_ONCE(RCUTILS_LOG_SEVERITY_ERROR, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_STREAM_EXPRESSION
|
||||
* \copydoc RCLCPP_LOG_STREAM_EXPRESSION
|
||||
*/
|
||||
#define RCLCPP_ERROR_STREAM_EXPRESSION(logger, expression, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_EXPRESSION(RCUTILS_LOG_SEVERITY_ERROR, logger, expression, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_STREAM_FUNCTION
|
||||
* \copydoc RCLCPP_LOG_STREAM_FUNCTION
|
||||
*/
|
||||
#define RCLCPP_ERROR_STREAM_FUNCTION(logger, function, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_FUNCTION(RCUTILS_LOG_SEVERITY_ERROR, logger, function, stream_args)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_STREAM_SKIPFIRST
|
||||
* \copydoc RCLCPP_LOG_STREAM_SKIPFIRST
|
||||
*/
|
||||
#define RCLCPP_ERROR_STREAM_SKIPFIRST(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_SKIPFIRST(RCUTILS_LOG_SEVERITY_ERROR, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_STREAM_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_STREAM_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_ERROR_STREAM_THROTTLE(logger, clock, duration, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_THROTTLE(RCUTILS_LOG_SEVERITY_ERROR, logger, clock, duration, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_ERROR_STREAM_SKIPFIRST_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_ERROR_STREAM_SKIPFIRST_THROTTLE(logger, clock, duration, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE(RCUTILS_LOG_SEVERITY_ERROR, logger, clock, duration, \
|
||||
stream_arg)
|
||||
|
||||
#endif
|
||||
|
||||
/** @name Logging macros for severity FATAL.
|
||||
*/
|
||||
#if (RCLCPP_LOG_MIN_SEVERITY > RCLCPP_LOG_MIN_SEVERITY_FATAL)
|
||||
// empty logging macros for severity FATAL when being disabled at compile time
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_ONCE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_EXPRESSION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_FUNCTION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_SKIPFIRST(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_SKIPFIRST_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_STREAM(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_STREAM_ONCE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_STREAM_EXPRESSION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_STREAM_FUNCTION(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_STREAM_SKIPFIRST(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_STREAM_THROTTLE(...)
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_FATAL_STREAM_SKIPFIRST_THROTTLE(...)
|
||||
|
||||
#else
|
||||
/**
|
||||
* \def RCLCPP_FATAL
|
||||
* \copydoc RCLCPP_LOG
|
||||
*/
|
||||
#define RCLCPP_FATAL(logger, ...) RCLCPP_LOG(RCUTILS_LOG_SEVERITY_FATAL, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_ONCE
|
||||
* \copydoc RCLCPP_LOG_ONCE
|
||||
*/
|
||||
#define RCLCPP_FATAL_ONCE(logger, ...) \
|
||||
RCLCPP_LOG_ONCE(RCUTILS_LOG_SEVERITY_FATAL, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_EXPRESSION
|
||||
* \copydoc RCLCPP_LOG_EXPRESSION
|
||||
*/
|
||||
#define RCLCPP_FATAL_EXPRESSION(logger, expression, ...) \
|
||||
RCLCPP_LOG_EXPRESSION(RCUTILS_LOG_SEVERITY_FATAL, logger, expression, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_FUNCTION
|
||||
* \copydoc RCLCPP_LOG_FUNCTION
|
||||
*/
|
||||
#define RCLCPP_FATAL_FUNCTION(logger, function, ...) \
|
||||
RCLCPP_LOG_FUNCTION(RCUTILS_LOG_SEVERITY_FATAL, logger, function, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_SKIPFIRST
|
||||
* \copydoc RCLCPP_LOG_SKIPFIRST
|
||||
*/
|
||||
#define RCLCPP_FATAL_SKIPFIRST(logger, ...) \
|
||||
RCLCPP_LOG_SKIPFIRST(RCUTILS_LOG_SEVERITY_FATAL, logger, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_FATAL_THROTTLE(logger, clock, duration, ...) \
|
||||
RCLCPP_LOG_THROTTLE(RCUTILS_LOG_SEVERITY_FATAL, logger, clock, duration, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_SKIPFIRST_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_SKIPFIRST_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_FATAL_SKIPFIRST_THROTTLE(logger, clock, duration, ...) \
|
||||
RCLCPP_LOG_SKIPFIRST_THROTTLE(RCUTILS_LOG_SEVERITY_FATAL, logger, clock, duration, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_STREAM
|
||||
* \copydoc RCLCPP_LOG_STREAM
|
||||
*/
|
||||
#define RCLCPP_FATAL_STREAM(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM(RCUTILS_LOG_SEVERITY_FATAL, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_STREAM_ONCE
|
||||
* \copydoc RCLCPP_LOG_STREAM_ONCE
|
||||
*/
|
||||
#define RCLCPP_FATAL_STREAM_ONCE(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_ONCE(RCUTILS_LOG_SEVERITY_FATAL, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_STREAM_EXPRESSION
|
||||
* \copydoc RCLCPP_LOG_STREAM_EXPRESSION
|
||||
*/
|
||||
#define RCLCPP_FATAL_STREAM_EXPRESSION(logger, expression, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_EXPRESSION(RCUTILS_LOG_SEVERITY_FATAL, logger, expression, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_STREAM_FUNCTION
|
||||
* \copydoc RCLCPP_LOG_STREAM_FUNCTION
|
||||
*/
|
||||
#define RCLCPP_FATAL_STREAM_FUNCTION(logger, function, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_FUNCTION(RCUTILS_LOG_SEVERITY_FATAL, logger, function, stream_args)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_STREAM_SKIPFIRST
|
||||
* \copydoc RCLCPP_LOG_STREAM_SKIPFIRST
|
||||
*/
|
||||
#define RCLCPP_FATAL_STREAM_SKIPFIRST(logger, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_SKIPFIRST(RCUTILS_LOG_SEVERITY_FATAL, logger, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_STREAM_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_STREAM_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_FATAL_STREAM_THROTTLE(logger, clock, duration, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_THROTTLE(RCUTILS_LOG_SEVERITY_FATAL, logger, clock, duration, stream_arg)
|
||||
|
||||
/**
|
||||
* \def RCLCPP_FATAL_STREAM_SKIPFIRST_THROTTLE
|
||||
* \copydoc RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE
|
||||
*/
|
||||
#define RCLCPP_FATAL_STREAM_SKIPFIRST_THROTTLE(logger, clock, duration, stream_arg) \
|
||||
RCLCPP_LOG_STREAM_SKIPFIRST_THROTTLE(RCUTILS_LOG_SEVERITY_FATAL, logger, clock, duration, \
|
||||
stream_arg)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // RCLCPP__LOGGING_HPP_
|
||||
@@ -199,6 +199,12 @@ init_tuple(NodeT & n)
|
||||
{ \
|
||||
return StorageClassT::template get<NodeInterfaceType>(); \
|
||||
} \
|
||||
\
|
||||
std::shared_ptr<const NodeInterfaceType> \
|
||||
get_node_ ## NodeInterfaceName ## _interface() const \
|
||||
{ \
|
||||
return StorageClassT::template get<NodeInterfaceType>(); \
|
||||
} \
|
||||
}; \
|
||||
} // namespace rclcpp::node_interfaces::detail
|
||||
// *INDENT-ON*
|
||||
|
||||
@@ -121,6 +121,11 @@ public:
|
||||
std::atomic_bool &
|
||||
get_associated_with_executor_atomic() override;
|
||||
|
||||
[[deprecated("Use get_shared_notify_guard_condition or trigger_notify_guard_condition instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::GuardCondition &
|
||||
get_notify_guard_condition() override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::GuardCondition::SharedPtr
|
||||
get_shared_notify_guard_condition() override;
|
||||
|
||||
@@ -144,6 +144,17 @@ public:
|
||||
std::atomic_bool &
|
||||
get_associated_with_executor_atomic() = 0;
|
||||
|
||||
/// Return a guard condition that should be notified when the internal node state changes.
|
||||
/**
|
||||
* For example, this should be notified when a publisher is added or removed.
|
||||
*
|
||||
* \return the GuardCondition if it is valid, else throw runtime error
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::GuardCondition &
|
||||
get_notify_guard_condition() = 0;
|
||||
|
||||
/// Return a guard condition that should be notified when the internal node state changes.
|
||||
/**
|
||||
* For example, this should be notified when a publisher is added or removed.
|
||||
|
||||
@@ -165,6 +165,8 @@ private:
|
||||
/// Handle to the NodeBaseInterface given in the constructor.
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
|
||||
|
||||
/// Graph Listener which waits on graph changes for the node and is shared across nodes.
|
||||
std::shared_ptr<rclcpp::graph_listener::GraphListener> graph_listener_;
|
||||
/// Whether or not this node needs to be added to the graph listener.
|
||||
std::atomic_bool should_add_to_graph_listener_;
|
||||
|
||||
|
||||
@@ -53,13 +53,17 @@ public:
|
||||
/// Construct a TopicEndpointInfo from a rcl_topic_endpoint_info_t.
|
||||
RCLCPP_PUBLIC
|
||||
explicit TopicEndpointInfo(const rcl_topic_endpoint_info_t & info)
|
||||
: node_name_(info.node_name),
|
||||
node_namespace_(info.node_namespace),
|
||||
topic_type_(info.topic_type),
|
||||
endpoint_type_(static_cast<rclcpp::EndpointType>(info.endpoint_type)),
|
||||
: endpoint_type_(static_cast<rclcpp::EndpointType>(info.endpoint_type)),
|
||||
qos_profile_({info.qos_profile.history, info.qos_profile.depth}, info.qos_profile),
|
||||
topic_type_hash_(info.topic_type_hash)
|
||||
{
|
||||
if (!info.node_name || !info.node_namespace || !info.topic_type) {
|
||||
throw std::invalid_argument("Constructor TopicEndpointInfo with invalid topic endpoint info");
|
||||
}
|
||||
node_name_ = info.node_name;
|
||||
node_namespace_ = info.node_namespace;
|
||||
topic_type_ = info.topic_type;
|
||||
|
||||
std::copy(info.endpoint_gid, info.endpoint_gid + RMW_GID_STORAGE_SIZE, endpoint_gid_.begin());
|
||||
}
|
||||
|
||||
|
||||
@@ -574,13 +574,6 @@ protected:
|
||||
std::unique_ptr<PublishedType, PublishedTypeDeleter>
|
||||
duplicate_type_adapt_message_as_unique_ptr(const PublishedType & msg)
|
||||
{
|
||||
/// Assert that the published type has no overloaded operator new since this leads to
|
||||
/// new/delete mismatch (see https://github.com/ros2/rclcpp/issues/2951)
|
||||
static_assert(!detail::has_overloaded_operator_new_v<PublishedType>,
|
||||
"When publishing by value (i.e. when calling publish(const T& msg)), the published "
|
||||
"message type must not have an overloaded operator new. In this case, please use the "
|
||||
"publish(std::unique_ptr<T> msg) method instead.");
|
||||
|
||||
auto ptr = PublishedTypeAllocatorTraits::allocate(published_type_allocator_, 1);
|
||||
PublishedTypeAllocatorTraits::construct(published_type_allocator_, ptr, msg);
|
||||
return std::unique_ptr<PublishedType, PublishedTypeDeleter>(ptr, published_type_deleter_);
|
||||
|
||||
@@ -68,6 +68,8 @@
|
||||
*
|
||||
* - Executors (responsible for execution of callbacks through a blocking spin):
|
||||
* - rclcpp::spin()
|
||||
* - rclcpp::spin_some()
|
||||
* - rclcpp::spin_until_future_complete()
|
||||
* - rclcpp::executors::SingleThreadedExecutor
|
||||
* - rclcpp::executors::SingleThreadedExecutor::add_node()
|
||||
* - rclcpp::executors::SingleThreadedExecutor::spin()
|
||||
|
||||
@@ -33,11 +33,12 @@ class Time
|
||||
public:
|
||||
/// Time constructor
|
||||
/**
|
||||
* Indicates a specific point in time, relative to a clock's 0 point (its epoch).
|
||||
* The total time since the epoch is given by seconds + nanoseconds.
|
||||
* Initializes the time values for seconds and nanoseconds individually.
|
||||
* Large values for nanoseconds are wrapped automatically with the remainder added to seconds.
|
||||
* Both inputs must be integers.
|
||||
*
|
||||
* \param seconds the seconds component, valid only if positive
|
||||
* \param nanoseconds the nanoseconds component, to be added to the seconds component
|
||||
* \param seconds part of the time in seconds since time epoch
|
||||
* \param nanoseconds part of the time in nanoseconds since time epoch
|
||||
* \param clock_type clock type
|
||||
* \throws std::runtime_error if seconds are negative
|
||||
*/
|
||||
@@ -46,7 +47,7 @@ public:
|
||||
|
||||
/// Time constructor
|
||||
/**
|
||||
* \param nanoseconds the total time since the epoch in nanoseconds
|
||||
* \param nanoseconds since time epoch
|
||||
* \param clock_type clock type
|
||||
* \throws std::runtime_error if nanoseconds are negative
|
||||
*/
|
||||
@@ -189,7 +190,7 @@ public:
|
||||
|
||||
/// Get the nanoseconds since epoch
|
||||
/**
|
||||
* \return the total time since the epoch in nanoseconds, as a rcl_time_point_value_t structure.
|
||||
* \return the nanoseconds since epoch as a rcl_time_point_value_t structure.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rcl_time_point_value_t
|
||||
@@ -208,7 +209,7 @@ public:
|
||||
* \warning Depending on sizeof(double) there could be significant precision loss.
|
||||
* When an exact time is required use nanoseconds() instead.
|
||||
*
|
||||
* \return the total time since the epoch in seconds, as a floating point number.
|
||||
* \return the seconds since epoch as a floating point number.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
double
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define RCLCPP__TYPE_ADAPTER_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
#include <new>
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
@@ -129,24 +128,6 @@ struct assert_type_pair_is_specialized_type_adapter
|
||||
"No type adapter for this custom type/ros message type pair");
|
||||
};
|
||||
|
||||
template<typename, typename = void>
|
||||
struct has_overloaded_operator_new : std::false_type {};
|
||||
template<typename T>
|
||||
struct has_overloaded_operator_new<T, std::void_t<
|
||||
decltype(T::operator new(std::size_t()))
|
||||
>>: std::true_type {};
|
||||
|
||||
template<typename, typename = void>
|
||||
struct has_overloaded_aligned_operator_new : std::false_type {};
|
||||
template<typename T>
|
||||
struct has_overloaded_aligned_operator_new<T,
|
||||
std::void_t<decltype( T::operator new(std::size_t(), std::align_val_t()) )>>
|
||||
: std::true_type {};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool has_overloaded_operator_new_v = has_overloaded_operator_new<T>::value ||
|
||||
has_overloaded_aligned_operator_new<T>::value;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Template metafunction that can make the type being adapted explicit.
|
||||
|
||||
@@ -56,7 +56,7 @@ bool wait_for_message(
|
||||
}
|
||||
});
|
||||
|
||||
rclcpp::WaitSet wait_set;
|
||||
rclcpp::WaitSet wait_set({}, {}, {}, {}, {}, {}, context);
|
||||
wait_set.add_subscription(subscription);
|
||||
RCPPUTILS_SCOPE_EXIT(wait_set.remove_subscription(subscription); );
|
||||
wait_set.add_guard_condition(gc);
|
||||
|
||||
@@ -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>30.1.2</version>
|
||||
<version>29.5.7</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
@@ -17,7 +17,6 @@
|
||||
<buildtool_depend>ament_cmake_ros</buildtool_depend>
|
||||
<buildtool_depend>ament_cmake_gen_version_h</buildtool_depend>
|
||||
<buildtool_depend>python3</buildtool_depend>
|
||||
<buildtool_depend>python3-empy</buildtool_depend>
|
||||
|
||||
<build_depend>ament_index_cpp</build_depend>
|
||||
<build_depend>builtin_interfaces</build_depend>
|
||||
|
||||
164
rclcpp/resource/logging.hpp.em
Normal file
164
rclcpp/resource/logging.hpp.em
Normal file
@@ -0,0 +1,164 @@
|
||||
// generated from rclcpp/resource/logging.hpp.em
|
||||
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__LOGGING_HPP_
|
||||
#define RCLCPP__LOGGING_HPP_
|
||||
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rcutils/logging_macros.h"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
|
||||
// These are used for compiling out logging macros lower than a minimum severity.
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_DEBUG 0
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_INFO 1
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_WARN 2
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_ERROR 3
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_FATAL 4
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_NONE 5
|
||||
|
||||
#define RCLCPP_FIRST_ARG(N, ...) N
|
||||
#define RCLCPP_ALL_BUT_FIRST_ARGS(N, ...) __VA_ARGS__
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_MIN_SEVERITY
|
||||
* Define RCLCPP_LOG_MIN_SEVERITY=RCLCPP_LOG_MIN_SEVERITY_[DEBUG|INFO|WARN|ERROR|FATAL]
|
||||
* in your build options to compile out anything below that severity.
|
||||
* Use RCLCPP_LOG_MIN_SEVERITY_NONE to compile out all macros.
|
||||
*/
|
||||
#ifndef RCLCPP_LOG_MIN_SEVERITY
|
||||
#define RCLCPP_LOG_MIN_SEVERITY RCLCPP_LOG_MIN_SEVERITY_DEBUG
|
||||
#endif
|
||||
|
||||
@{
|
||||
from collections import OrderedDict
|
||||
from copy import deepcopy
|
||||
from rcutils.logging import feature_combinations
|
||||
from rcutils.logging import get_suffix_from_features
|
||||
from rcutils.logging import severities
|
||||
from rcutils.logging import throttle_args
|
||||
from rcutils.logging import throttle_params
|
||||
|
||||
throttle_args['condition_before'] = 'RCUTILS_LOG_CONDITION_THROTTLE_BEFORE(clock, duration)'
|
||||
del throttle_params['get_time_point_value']
|
||||
throttle_params['clock'] = 'rclcpp::Clock that will be used to get the time point.'
|
||||
throttle_params.move_to_end('clock', last=False)
|
||||
|
||||
rclcpp_feature_combinations = OrderedDict()
|
||||
for combinations, feature in feature_combinations.items():
|
||||
# skip feature combinations using 'named'
|
||||
if 'named' in combinations:
|
||||
continue
|
||||
rclcpp_feature_combinations[combinations] = feature
|
||||
# add a stream variant for each available feature combination
|
||||
stream_arg = 'stream_arg'
|
||||
for combinations, feature in list(rclcpp_feature_combinations.items()):
|
||||
combinations = ('stream', ) + combinations
|
||||
feature = deepcopy(feature)
|
||||
feature.params[stream_arg] = 'The argument << into a stringstream'
|
||||
rclcpp_feature_combinations[combinations] = feature
|
||||
|
||||
def get_rclcpp_suffix_from_features(features):
|
||||
suffix = get_suffix_from_features(features)
|
||||
if 'stream' in features:
|
||||
suffix = '_STREAM' + suffix
|
||||
return suffix
|
||||
}@
|
||||
@[for severity in severities]@
|
||||
/** @@name Logging macros for severity @(severity).
|
||||
*/
|
||||
///@@{
|
||||
#if (RCLCPP_LOG_MIN_SEVERITY > RCLCPP_LOG_MIN_SEVERITY_@(severity))
|
||||
// empty logging macros for severity @(severity) when being disabled at compile time
|
||||
@[ for feature_combination in rclcpp_feature_combinations.keys()]@
|
||||
@{suffix = get_rclcpp_suffix_from_features(feature_combination)}@
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_@(severity)@(suffix)(...)
|
||||
@[ end for]@
|
||||
|
||||
#else
|
||||
@[ for feature_combination in rclcpp_feature_combinations.keys()]@
|
||||
@{suffix = get_rclcpp_suffix_from_features(feature_combination)}@
|
||||
// The RCLCPP_@(severity)@(suffix) macro is surrounded by do { .. } while (0)
|
||||
// to implement the standard C macro idiom to make the macro safe in all
|
||||
// contexts; see http://c-faq.com/cpp/multistmt.html for more information.
|
||||
/**
|
||||
* \def RCLCPP_@(severity)@(suffix)
|
||||
* Log a message with severity @(severity)@
|
||||
@[ if rclcpp_feature_combinations[feature_combination].doc_lines]@
|
||||
with the following conditions:
|
||||
@[ else]@
|
||||
.
|
||||
@[ end if]@
|
||||
@[ for doc_line in rclcpp_feature_combinations[feature_combination].doc_lines]@
|
||||
* @(doc_line)
|
||||
@[ end for]@
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
@[ for param_name, doc_line in rclcpp_feature_combinations[feature_combination].params.items()]@
|
||||
* \param @(param_name) @(doc_line)
|
||||
@[ end for]@
|
||||
@[ if 'stream' not in feature_combination]@
|
||||
* \param ... The format string, followed by the variable arguments for the format string.
|
||||
@[ end if]@
|
||||
*/
|
||||
@{params = rclcpp_feature_combinations[feature_combination].params.keys()}@
|
||||
#define RCLCPP_@(severity)@(suffix)(logger@(''.join([', ' + p for p in params]))@
|
||||
@[ if 'stream' not in feature_combination]@
|
||||
, ...@
|
||||
@[ end if]@
|
||||
) \
|
||||
do { \
|
||||
static_assert( \
|
||||
::std::is_convertible_v<decltype(logger), ::rclcpp::Logger>, \
|
||||
"First argument to logging macros must be an rclcpp::Logger"); \
|
||||
@[ if 'throttle' in feature_combination]@ \
|
||||
auto get_time_point = [&c=clock](rcutils_time_point_value_t * time_point) -> rcutils_ret_t { \
|
||||
try { \
|
||||
*time_point = c.now().nanoseconds(); \
|
||||
} catch (...) { \
|
||||
RCUTILS_SAFE_FWRITE_TO_STDERR( \
|
||||
"[rclcpp|logging.hpp] RCLCPP_@(severity)@(suffix) could not get current time stamp\n"); \
|
||||
return RCUTILS_RET_ERROR; \
|
||||
} \
|
||||
return RCUTILS_RET_OK; \
|
||||
}; \
|
||||
@[ end if] \
|
||||
@[ if 'stream' in feature_combination]@
|
||||
std::stringstream rclcpp_stream_ss_; \
|
||||
rclcpp_stream_ss_ << @(stream_arg); \
|
||||
@[ end if]@
|
||||
RCUTILS_LOG_@(severity)@(get_suffix_from_features(feature_combination))_NAMED( \
|
||||
@{params = ['get_time_point' if p == 'clock' and 'throttle' in feature_combination else p for p in params]}@
|
||||
@[ if params]@
|
||||
@(''.join([' ' + p + ', \\\n' for p in params if p != stream_arg]))@
|
||||
@[ end if]@
|
||||
(logger).get_name(), \
|
||||
@[ if 'stream' not in feature_combination]@
|
||||
__VA_ARGS__); \
|
||||
@[ else]@
|
||||
"%s", rclcpp_stream_ss_.str().c_str()); \
|
||||
@[ end if]@
|
||||
} while (0)
|
||||
|
||||
@[ end for]@
|
||||
#endif
|
||||
///@@}
|
||||
|
||||
@[end for]@
|
||||
|
||||
#endif // RCLCPP__LOGGING_HPP_
|
||||
@@ -83,6 +83,16 @@ Clock::now() const
|
||||
return now;
|
||||
}
|
||||
|
||||
void
|
||||
Clock::cancel_sleep_or_wait()
|
||||
{
|
||||
{
|
||||
std::unique_lock lock(impl_->wait_mutex_);
|
||||
impl_->stop_sleeping_ = true;
|
||||
}
|
||||
impl_->cv_.notify_one();
|
||||
}
|
||||
|
||||
bool
|
||||
Clock::sleep_until(
|
||||
Time until,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "rclcpp/context.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
@@ -28,7 +29,7 @@
|
||||
#include "rclcpp/detail/utilities.hpp"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
#include "rclcpp/graph_listener.hpp"
|
||||
|
||||
#include "rcutils/error_handling.h"
|
||||
#include "rcutils/macros.h"
|
||||
|
||||
@@ -142,12 +143,52 @@ rclcpp_logging_output_handler(
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
/**
|
||||
* Global storage for pre and post shutdown recursive mutexes.
|
||||
* Note, this is a ABI compatibility hack.
|
||||
*/
|
||||
class MutexLookup
|
||||
{
|
||||
std::mutex m;
|
||||
|
||||
struct MutexHolder
|
||||
{
|
||||
std::recursive_mutex on_shutdown_callbacks_mutex_;
|
||||
std::recursive_mutex pre_shutdown_callbacks_mutex_;
|
||||
};
|
||||
|
||||
std::map<const Context *, std::unique_ptr<MutexHolder>> mutexMap;
|
||||
|
||||
public:
|
||||
MutexHolder & getMutexes(const Context *forContext)
|
||||
{
|
||||
auto it = mutexMap.find(forContext);
|
||||
if(it == mutexMap.end()) {
|
||||
it = mutexMap.emplace(forContext, std::make_unique<MutexHolder>()).first;
|
||||
}
|
||||
|
||||
return *(it->second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only supposed to be called on deletion of context
|
||||
*/
|
||||
void removeMutexes(const Context *forContext)
|
||||
{
|
||||
mutexMap.erase(forContext);
|
||||
}
|
||||
};
|
||||
|
||||
MutexLookup mutexStorage;
|
||||
|
||||
Context::Context()
|
||||
: rcl_context_(nullptr),
|
||||
shutdown_reason_(""),
|
||||
logging_mutex_(nullptr),
|
||||
graph_listener_(nullptr)
|
||||
{}
|
||||
logging_mutex_(nullptr)
|
||||
{
|
||||
// allocate mutexes
|
||||
mutexStorage.getMutexes(this);
|
||||
}
|
||||
|
||||
Context::~Context()
|
||||
{
|
||||
@@ -166,6 +207,9 @@ Context::~Context()
|
||||
} catch (...) {
|
||||
RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "unhandled exception in ~Context()");
|
||||
}
|
||||
|
||||
// delete mutexes
|
||||
mutexStorage.removeMutexes(this);
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
@@ -244,24 +288,6 @@ Context::init(
|
||||
|
||||
weak_contexts_ = get_weak_contexts();
|
||||
weak_contexts_->add_context(this->shared_from_this());
|
||||
|
||||
|
||||
std::lock_guard<std::recursive_mutex> lock (on_shutdown_callbacks_mutex_);
|
||||
|
||||
graph_listener_ = std::make_shared<graph_listener::GraphListener>(shared_from_this());
|
||||
|
||||
if (!graph_listener_->is_started()) {
|
||||
// Register an on_shutdown hook to shutdown the graph listener.
|
||||
// This is important to ensure that the wait set is finalized before
|
||||
// destruction of static objects occurs.
|
||||
std::weak_ptr<rclcpp::graph_listener::GraphListener> weak_graph_listener = graph_listener_;
|
||||
on_shutdown ([weak_graph_listener]() {
|
||||
auto shared_graph_listener = weak_graph_listener.lock();
|
||||
if(shared_graph_listener) {
|
||||
shared_graph_listener->shutdown(std::nothrow);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (const std::exception & e) {
|
||||
ret = rcl_shutdown(rcl_context_.get());
|
||||
rcl_context_.reset();
|
||||
@@ -329,7 +355,8 @@ Context::shutdown(const std::string & reason)
|
||||
|
||||
// call each pre-shutdown callback
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock{pre_shutdown_callbacks_mutex_};
|
||||
std::lock_guard<std::recursive_mutex> lock{mutexStorage.getMutexes(
|
||||
this).pre_shutdown_callbacks_mutex_};
|
||||
// callbacks may delete other callbacks during the execution,
|
||||
// therefore we need to save a copy and check before execution
|
||||
// if the next callback is still present
|
||||
@@ -351,7 +378,8 @@ Context::shutdown(const std::string & reason)
|
||||
shutdown_reason_ = reason;
|
||||
// call each shutdown callback
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(on_shutdown_callbacks_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> lock(mutexStorage.getMutexes(
|
||||
this).on_shutdown_callbacks_mutex_);
|
||||
// callbacks may delete other callbacks during the execution,
|
||||
// therefore we need to save a copy and check before execution
|
||||
// if the next callback is still present
|
||||
@@ -431,10 +459,12 @@ Context::add_shutdown_callback(
|
||||
shutdown_type == ShutdownType::pre_shutdown || shutdown_type == ShutdownType::on_shutdown);
|
||||
|
||||
if constexpr (shutdown_type == ShutdownType::pre_shutdown) {
|
||||
std::lock_guard<std::recursive_mutex> lock(pre_shutdown_callbacks_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> lock(mutexStorage.getMutexes(
|
||||
this).pre_shutdown_callbacks_mutex_);
|
||||
pre_shutdown_callbacks_.emplace_back(callback_shared_ptr);
|
||||
} else {
|
||||
std::lock_guard<std::recursive_mutex> lock(on_shutdown_callbacks_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> lock(mutexStorage.getMutexes(
|
||||
this).on_shutdown_callbacks_mutex_);
|
||||
on_shutdown_callbacks_.emplace_back(callback_shared_ptr);
|
||||
}
|
||||
|
||||
@@ -465,6 +495,7 @@ Context::remove_shutdown_callback(
|
||||
return false;
|
||||
}
|
||||
callback_vector.erase(iter);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -472,9 +503,11 @@ Context::remove_shutdown_callback(
|
||||
shutdown_type == ShutdownType::pre_shutdown || shutdown_type == ShutdownType::on_shutdown);
|
||||
|
||||
if constexpr (shutdown_type == ShutdownType::pre_shutdown) {
|
||||
return remove_callback(pre_shutdown_callbacks_mutex_, pre_shutdown_callbacks_);
|
||||
return remove_callback(mutexStorage.getMutexes(this).pre_shutdown_callbacks_mutex_,
|
||||
pre_shutdown_callbacks_);
|
||||
} else {
|
||||
return remove_callback(on_shutdown_callbacks_mutex_, on_shutdown_callbacks_);
|
||||
return remove_callback(mutexStorage.getMutexes(this).on_shutdown_callbacks_mutex_,
|
||||
on_shutdown_callbacks_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,9 +540,11 @@ Context::get_shutdown_callback() const
|
||||
shutdown_type == ShutdownType::pre_shutdown || shutdown_type == ShutdownType::on_shutdown);
|
||||
|
||||
if constexpr (shutdown_type == ShutdownType::pre_shutdown) {
|
||||
return get_callback_vector(pre_shutdown_callbacks_mutex_, pre_shutdown_callbacks_);
|
||||
return get_callback_vector(mutexStorage.getMutexes(this).pre_shutdown_callbacks_mutex_,
|
||||
pre_shutdown_callbacks_);
|
||||
} else {
|
||||
return get_callback_vector(on_shutdown_callbacks_mutex_, on_shutdown_callbacks_);
|
||||
return get_callback_vector(mutexStorage.getMutexes(this).on_shutdown_callbacks_mutex_,
|
||||
on_shutdown_callbacks_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,12 +554,6 @@ Context::get_rcl_context()
|
||||
return rcl_context_;
|
||||
}
|
||||
|
||||
std::shared_ptr<rclcpp::graph_listener::GraphListener>
|
||||
Context::get_graph_listener()
|
||||
{
|
||||
return graph_listener_;
|
||||
}
|
||||
|
||||
bool
|
||||
Context::sleep_for(const std::chrono::nanoseconds & nanoseconds)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
@@ -53,7 +52,6 @@ class rclcpp::ExecutorImplementation {};
|
||||
|
||||
Executor::Executor(const std::shared_ptr<rclcpp::Context> & context)
|
||||
: spinning(false),
|
||||
context_(context),
|
||||
entities_need_rebuild_(true),
|
||||
collector_(nullptr),
|
||||
wait_set_({}, {}, {}, {}, {}, {}, context)
|
||||
@@ -188,11 +186,6 @@ Executor::add_callback_group(
|
||||
void
|
||||
Executor::add_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify)
|
||||
{
|
||||
if (node_ptr->get_context() != context_) {
|
||||
throw std::runtime_error(
|
||||
"add_node() called with a node with a different context from this executor");
|
||||
}
|
||||
|
||||
this->collector_.add_node(node_ptr);
|
||||
|
||||
try {
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rcpputils/compile_warnings.hpp"
|
||||
|
||||
void
|
||||
rclcpp::spin_all(
|
||||
@@ -26,6 +25,12 @@ rclcpp::spin_all(
|
||||
exec.spin_node_all(node_ptr, max_duration);
|
||||
}
|
||||
|
||||
void
|
||||
rclcpp::spin_all(rclcpp::Node::SharedPtr node_ptr, std::chrono::nanoseconds max_duration)
|
||||
{
|
||||
rclcpp::spin_all(node_ptr->get_node_base_interface(), max_duration);
|
||||
}
|
||||
|
||||
void
|
||||
rclcpp::spin_some(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr)
|
||||
{
|
||||
@@ -35,6 +40,12 @@ rclcpp::spin_some(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr
|
||||
exec.spin_node_some(node_ptr);
|
||||
}
|
||||
|
||||
void
|
||||
rclcpp::spin_some(rclcpp::Node::SharedPtr node_ptr)
|
||||
{
|
||||
rclcpp::spin_some(node_ptr->get_node_base_interface());
|
||||
}
|
||||
|
||||
void
|
||||
rclcpp::spin(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr)
|
||||
{
|
||||
@@ -51,19 +62,3 @@ rclcpp::spin(rclcpp::Node::SharedPtr node_ptr)
|
||||
{
|
||||
rclcpp::spin(node_ptr->get_node_base_interface());
|
||||
}
|
||||
|
||||
void
|
||||
rclcpp::spin_all(rclcpp::Node::SharedPtr node_ptr, std::chrono::nanoseconds max_duration)
|
||||
{
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_START
|
||||
rclcpp::spin_all(node_ptr->get_node_base_interface(), max_duration);
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_STOP
|
||||
}
|
||||
|
||||
void
|
||||
rclcpp::spin_some(rclcpp::Node::SharedPtr node_ptr)
|
||||
{
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_START
|
||||
rclcpp::spin_some(node_ptr->get_node_base_interface());
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_STOP
|
||||
}
|
||||
|
||||
223
rclcpp/src/rclcpp/executors/static_single_threaded_executor.cpp
Normal file
223
rclcpp/src/rclcpp/executors/static_single_threaded_executor.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
// Copyright 2019 Nobleo Technology
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "rclcpp/executors/executor_entities_collection.hpp"
|
||||
#include "rcpputils/scope_exit.hpp"
|
||||
|
||||
#include "rclcpp/executors/static_single_threaded_executor.hpp"
|
||||
#include "rclcpp/any_executable.hpp"
|
||||
|
||||
using rclcpp::executors::StaticSingleThreadedExecutor;
|
||||
|
||||
StaticSingleThreadedExecutor::StaticSingleThreadedExecutor(const rclcpp::ExecutorOptions & options)
|
||||
: rclcpp::Executor(options)
|
||||
{
|
||||
}
|
||||
|
||||
StaticSingleThreadedExecutor::~StaticSingleThreadedExecutor() {}
|
||||
|
||||
void
|
||||
StaticSingleThreadedExecutor::spin()
|
||||
{
|
||||
if (spinning.exchange(true)) {
|
||||
throw std::runtime_error("spin() called while already spinning");
|
||||
}
|
||||
RCPPUTILS_SCOPE_EXIT(this->spinning.store(false); );
|
||||
|
||||
// This is essentially the contents of the rclcpp::Executor::wait_for_work method,
|
||||
// except we need to keep the wait result to reproduce the StaticSingleThreadedExecutor
|
||||
// behavior.
|
||||
while (rclcpp::ok(this->context_) && spinning.load()) {
|
||||
this->spin_once_impl(std::chrono::nanoseconds(-1));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StaticSingleThreadedExecutor::spin_some(std::chrono::nanoseconds max_duration)
|
||||
{
|
||||
// In this context a 0 input max_duration means no duration limit
|
||||
if (std::chrono::nanoseconds(0) == max_duration) {
|
||||
max_duration = std::chrono::nanoseconds::max();
|
||||
}
|
||||
return this->spin_some_impl(max_duration, false);
|
||||
}
|
||||
|
||||
void
|
||||
StaticSingleThreadedExecutor::spin_all(std::chrono::nanoseconds max_duration)
|
||||
{
|
||||
if (max_duration < std::chrono::nanoseconds(0)) {
|
||||
throw std::invalid_argument("max_duration must be greater than or equal to 0");
|
||||
}
|
||||
return this->spin_some_impl(max_duration, true);
|
||||
}
|
||||
|
||||
void
|
||||
StaticSingleThreadedExecutor::spin_some_impl(std::chrono::nanoseconds max_duration, bool exhaustive)
|
||||
{
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
auto max_duration_not_elapsed = [max_duration, start]() {
|
||||
const auto spin_forever = std::chrono::nanoseconds(0) == max_duration;
|
||||
const auto cur_duration = std::chrono::steady_clock::now() - start;
|
||||
return spin_forever || (cur_duration < max_duration);
|
||||
};
|
||||
|
||||
if (spinning.exchange(true)) {
|
||||
throw std::runtime_error("spin_some() called while already spinning");
|
||||
}
|
||||
RCPPUTILS_SCOPE_EXIT(this->spinning.store(false););
|
||||
|
||||
while (rclcpp::ok(context_) && spinning.load() && max_duration_not_elapsed()) {
|
||||
// Get executables that are ready now
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
|
||||
auto wait_result = this->collect_and_wait(std::chrono::nanoseconds(0));
|
||||
if (wait_result.has_value()) {
|
||||
// Execute ready executables
|
||||
bool work_available = this->execute_ready_executables(
|
||||
current_collection_,
|
||||
wait_result.value(),
|
||||
false);
|
||||
if (!work_available || !exhaustive) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StaticSingleThreadedExecutor::spin_once_impl(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
if (rclcpp::ok(context_) && spinning.load()) {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
auto wait_result = this->collect_and_wait(timeout);
|
||||
if (wait_result.has_value()) {
|
||||
this->execute_ready_executables(current_collection_, wait_result.value(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<rclcpp::WaitResult<rclcpp::WaitSet>>
|
||||
StaticSingleThreadedExecutor::collect_and_wait(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
// we need to make sure that callback groups don't get out of scope
|
||||
// during the wait. As in jazzy, they are not covered by the DynamicStorage,
|
||||
// we explicitly hold them here as a bugfix
|
||||
std::vector<rclcpp::CallbackGroup::SharedPtr> cbgs;
|
||||
|
||||
if (this->entities_need_rebuild_.exchange(false) || current_collection_.empty()) {
|
||||
this->collect_entities();
|
||||
}
|
||||
|
||||
auto callback_groups = this->collector_.get_all_callback_groups();
|
||||
cbgs.resize(callback_groups.size());
|
||||
for(const auto & w_ptr : callback_groups) {
|
||||
auto shr_ptr = w_ptr.lock();
|
||||
if(shr_ptr) {
|
||||
cbgs.push_back(std::move(shr_ptr));
|
||||
}
|
||||
}
|
||||
|
||||
auto wait_result = wait_set_.wait(std::chrono::nanoseconds(timeout));
|
||||
|
||||
// drop references to the callback groups, before trying to execute anything
|
||||
cbgs.clear();
|
||||
|
||||
if (wait_result.kind() == WaitResultKind::Empty) {
|
||||
RCUTILS_LOG_WARN_NAMED(
|
||||
"rclcpp",
|
||||
"empty wait set received in wait(). This should never happen.");
|
||||
return {};
|
||||
} else {
|
||||
if (wait_result.kind() == WaitResultKind::Ready && current_notify_waitable_) {
|
||||
auto & rcl_wait_set = wait_result.get_wait_set().get_rcl_wait_set();
|
||||
if (current_notify_waitable_->is_ready(rcl_wait_set)) {
|
||||
current_notify_waitable_->execute(current_notify_waitable_->take_data());
|
||||
}
|
||||
}
|
||||
}
|
||||
return wait_result;
|
||||
}
|
||||
|
||||
// This preserves the "scheduling semantics" of the StaticSingleThreadedExecutor
|
||||
// from the original implementation.
|
||||
bool StaticSingleThreadedExecutor::execute_ready_executables(
|
||||
const rclcpp::executors::ExecutorEntitiesCollection & collection,
|
||||
rclcpp::WaitResult<rclcpp::WaitSet> & wait_result,
|
||||
bool spin_once)
|
||||
{
|
||||
bool any_ready_executable = false;
|
||||
if (wait_result.kind() != rclcpp::WaitResultKind::Ready) {
|
||||
return any_ready_executable;
|
||||
}
|
||||
|
||||
while (auto subscription = wait_result.next_ready_subscription()) {
|
||||
auto entity_iter = collection.subscriptions.find(subscription->get_subscription_handle().get());
|
||||
if (entity_iter != collection.subscriptions.end()) {
|
||||
execute_subscription(subscription);
|
||||
any_ready_executable = true;
|
||||
if (spin_once) {return any_ready_executable;}
|
||||
}
|
||||
}
|
||||
|
||||
size_t current_timer_index = 0;
|
||||
while (true) {
|
||||
auto [timer, timer_index] = wait_result.peek_next_ready_timer(current_timer_index);
|
||||
if (nullptr == timer) {
|
||||
break;
|
||||
}
|
||||
current_timer_index = timer_index;
|
||||
auto entity_iter = collection.timers.find(timer->get_timer_handle().get());
|
||||
if (entity_iter != collection.timers.end()) {
|
||||
wait_result.clear_timer_with_index(current_timer_index);
|
||||
auto data = timer->call();
|
||||
if (!data) {
|
||||
// someone canceled the timer between is_ready and call
|
||||
continue;
|
||||
}
|
||||
|
||||
execute_timer(std::move(timer), data);
|
||||
any_ready_executable = true;
|
||||
if (spin_once) {return any_ready_executable;}
|
||||
}
|
||||
}
|
||||
|
||||
while (auto client = wait_result.next_ready_client()) {
|
||||
auto entity_iter = collection.clients.find(client->get_client_handle().get());
|
||||
if (entity_iter != collection.clients.end()) {
|
||||
execute_client(client);
|
||||
any_ready_executable = true;
|
||||
if (spin_once) {return any_ready_executable;}
|
||||
}
|
||||
}
|
||||
|
||||
while (auto service = wait_result.next_ready_service()) {
|
||||
auto entity_iter = collection.services.find(service->get_service_handle().get());
|
||||
if (entity_iter != collection.services.end()) {
|
||||
execute_service(service);
|
||||
any_ready_executable = true;
|
||||
if (spin_once) {return any_ready_executable;}
|
||||
}
|
||||
}
|
||||
|
||||
while (auto waitable = wait_result.next_ready_waitable()) {
|
||||
auto entity_iter = collection.waitables.find(waitable.get());
|
||||
if (entity_iter != collection.waitables.end()) {
|
||||
const auto data = waitable->take_data();
|
||||
waitable->execute(data);
|
||||
any_ready_executable = true;
|
||||
if (spin_once) {return any_ready_executable;}
|
||||
}
|
||||
}
|
||||
return any_ready_executable;
|
||||
}
|
||||
@@ -25,9 +25,9 @@ using namespace std::chrono_literals;
|
||||
using rclcpp::experimental::executors::EventsExecutor;
|
||||
|
||||
EventsExecutor::EventsExecutor(
|
||||
const rclcpp::ExecutorOptions & options,
|
||||
rclcpp::experimental::executors::EventsQueue::UniquePtr events_queue,
|
||||
bool execute_timers_separate_thread)
|
||||
bool execute_timers_separate_thread,
|
||||
const rclcpp::ExecutorOptions & options)
|
||||
: rclcpp::Executor(options)
|
||||
{
|
||||
// Get ownership of the queue used to store events.
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/types.h"
|
||||
#include "rclcpp/detail/add_guard_condition_to_rcl_wait_set.hpp"
|
||||
@@ -37,7 +38,8 @@ namespace graph_listener
|
||||
{
|
||||
|
||||
GraphListener::GraphListener(const std::shared_ptr<Context> & parent_context)
|
||||
: rcl_parent_context_(parent_context->get_rcl_context()),
|
||||
: weak_parent_context_(parent_context),
|
||||
rcl_parent_context_(parent_context->get_rcl_context()),
|
||||
is_started_(false),
|
||||
is_shutdown_(false),
|
||||
interrupt_guard_condition_(parent_context)
|
||||
@@ -70,11 +72,23 @@ void
|
||||
GraphListener::start_if_not_started()
|
||||
{
|
||||
std::lock_guard<std::mutex> shutdown_lock(shutdown_mutex_);
|
||||
if (is_shutdown()) {
|
||||
if (is_shutdown_.load()) {
|
||||
throw GraphListenerShutdownError();
|
||||
}
|
||||
|
||||
if (!is_started()) {
|
||||
auto parent_context = weak_parent_context_.lock();
|
||||
if (!is_started_ && parent_context) {
|
||||
// Register an on_shutdown hook to shtudown the graph listener.
|
||||
// This is important to ensure that the wait set is finalized before
|
||||
// destruction of static objects occurs.
|
||||
std::weak_ptr<GraphListener> weak_this = shared_from_this();
|
||||
parent_context->on_shutdown(
|
||||
[weak_this]() {
|
||||
auto shared_this = weak_this.lock();
|
||||
if (shared_this) {
|
||||
// should not throw from on_shutdown if it can be avoided
|
||||
shared_this->shutdown(std::nothrow);
|
||||
}
|
||||
});
|
||||
// Initialize the wait set before starting.
|
||||
init_wait_set();
|
||||
// Start the listener thread.
|
||||
@@ -108,7 +122,7 @@ GraphListener::run_loop()
|
||||
{
|
||||
while (true) {
|
||||
// If shutdown() was called, exit.
|
||||
if (is_shutdown()) {
|
||||
if (is_shutdown_.load()) {
|
||||
return;
|
||||
}
|
||||
rcl_ret_t ret;
|
||||
@@ -176,7 +190,7 @@ GraphListener::run_loop()
|
||||
if (graph_gc == wait_set_.guard_conditions[graph_gc_indexes[i]]) {
|
||||
node_ptr->notify_graph_change();
|
||||
}
|
||||
if (is_shutdown()) {
|
||||
if (is_shutdown_) {
|
||||
// If shutdown, then notify the node of this as well.
|
||||
node_ptr->notify_shutdown();
|
||||
}
|
||||
@@ -243,7 +257,7 @@ GraphListener::add_node(rclcpp::node_interfaces::NodeGraphInterface * node_graph
|
||||
throw std::invalid_argument("node is nullptr");
|
||||
}
|
||||
std::lock_guard<std::mutex> shutdown_lock(shutdown_mutex_);
|
||||
if (is_shutdown()) {
|
||||
if (is_shutdown_.load()) {
|
||||
throw GraphListenerShutdownError();
|
||||
}
|
||||
|
||||
@@ -318,11 +332,11 @@ GraphListener::__shutdown()
|
||||
{
|
||||
std::lock_guard<std::mutex> shutdown_lock(shutdown_mutex_);
|
||||
if (!is_shutdown_.exchange(true)) {
|
||||
if (is_started()) {
|
||||
if (is_started_) {
|
||||
interrupt_(&interrupt_guard_condition_);
|
||||
listener_thread_.join();
|
||||
}
|
||||
if (is_started()) {
|
||||
if (is_started_) {
|
||||
cleanup_wait_set();
|
||||
}
|
||||
}
|
||||
@@ -351,12 +365,6 @@ GraphListener::shutdown(const std::nothrow_t &) noexcept
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GraphListener::is_started()
|
||||
{
|
||||
return is_started_;
|
||||
}
|
||||
|
||||
bool
|
||||
GraphListener::is_shutdown()
|
||||
{
|
||||
|
||||
@@ -55,6 +55,34 @@ get_node_logger(const rcl_node_t * node)
|
||||
return rclcpp::get_logger(logger_name);
|
||||
}
|
||||
|
||||
// TODO(ahcorde): Remove deprecated class on the next release (in Rolling after Kilted).
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
rcpputils::fs::path
|
||||
get_logging_directory()
|
||||
{
|
||||
char * log_dir = NULL;
|
||||
auto allocator = rcutils_get_default_allocator();
|
||||
rcl_logging_ret_t ret = rcl_logging_get_logging_directory(allocator, &log_dir);
|
||||
if (RCL_LOGGING_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
std::string path{log_dir};
|
||||
allocator.deallocate(log_dir, allocator.state);
|
||||
return path;
|
||||
}
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
std::filesystem::path
|
||||
get_log_directory()
|
||||
{
|
||||
|
||||
@@ -275,6 +275,16 @@ NodeBase::get_associated_with_executor_atomic()
|
||||
return associated_with_executor_;
|
||||
}
|
||||
|
||||
rclcpp::GuardCondition &
|
||||
NodeBase::get_notify_guard_condition()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> notify_condition_lock(notify_guard_condition_mutex_);
|
||||
if (!notify_guard_condition_is_valid_) {
|
||||
throw std::runtime_error("failed to get notify guard condition because it is invalid");
|
||||
}
|
||||
return *notify_guard_condition_;
|
||||
}
|
||||
|
||||
rclcpp::GuardCondition::SharedPtr
|
||||
NodeBase::get_shared_notify_guard_condition()
|
||||
{
|
||||
|
||||
@@ -36,6 +36,9 @@ using rclcpp::graph_listener::GraphListener;
|
||||
|
||||
NodeGraph::NodeGraph(rclcpp::node_interfaces::NodeBaseInterface * node_base)
|
||||
: node_base_(node_base),
|
||||
graph_listener_(
|
||||
node_base->get_context()->get_sub_context<GraphListener>(node_base->get_context())
|
||||
),
|
||||
should_add_to_graph_listener_(true),
|
||||
graph_users_count_(0)
|
||||
{}
|
||||
@@ -47,7 +50,7 @@ NodeGraph::~NodeGraph()
|
||||
// graph listener after checking that it was not here.
|
||||
if (!should_add_to_graph_listener_.exchange(false)) {
|
||||
// If it was already false, then it needs to now be removed.
|
||||
node_base_->get_context()->get_graph_listener()->remove_node(this);
|
||||
graph_listener_->remove_node(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,7 +419,7 @@ NodeGraph::get_node_names_and_namespaces() const
|
||||
rcl_get_error_string().str;
|
||||
rcl_reset_error();
|
||||
}
|
||||
RCUTILS_LOG_ERROR_NAMED("rclcpp", "%s", error_msg.c_str());
|
||||
// TODO(karsten1987): Append rcutils_error_message once it's in master
|
||||
throw std::runtime_error(error_msg);
|
||||
}
|
||||
|
||||
@@ -431,15 +434,20 @@ NodeGraph::get_node_names_and_namespaces() const
|
||||
std::string error;
|
||||
rcl_ret_t ret_names = rcutils_string_array_fini(&node_names_c);
|
||||
if (ret_names != RCUTILS_RET_OK) {
|
||||
error = std::string("could not destroy node names: ") + rcl_get_error_string().str;
|
||||
// *INDENT-OFF*
|
||||
// TODO(karsten1987): Append rcutils_error_message once it's in master
|
||||
error = "could not destroy node names";
|
||||
// *INDENT-ON*
|
||||
}
|
||||
rcl_ret_t ret_ns = rcutils_string_array_fini(&node_namespaces_c);
|
||||
if (ret_ns != RCUTILS_RET_OK) {
|
||||
error += std::string(", could not destroy node namespaces: ") + rcl_get_error_string().str;
|
||||
// *INDENT-OFF*
|
||||
// TODO(karsten1987): Append rcutils_error_message once it's in master
|
||||
error += ", could not destroy node namespaces";
|
||||
// *INDENT-ON*
|
||||
}
|
||||
|
||||
if (ret_names != RCUTILS_RET_OK || ret_ns != RCUTILS_RET_OK) {
|
||||
RCUTILS_LOG_ERROR_NAMED("rclcpp", "%s", error.c_str());
|
||||
throw std::runtime_error(error);
|
||||
}
|
||||
|
||||
@@ -595,8 +603,8 @@ NodeGraph::get_graph_event()
|
||||
}
|
||||
// on first call, add node to graph_listener_
|
||||
if (should_add_to_graph_listener_.exchange(false)) {
|
||||
node_base_->get_context()->get_graph_listener()->add_node(this);
|
||||
node_base_->get_context()->get_graph_listener()->start_if_not_started();
|
||||
graph_listener_->add_node(this);
|
||||
graph_listener_->start_if_not_started();
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
@@ -192,65 +192,6 @@ format_range_reason(const std::string & name, const char * range_type)
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
__check_integer_range(
|
||||
const rcl_interfaces::msg::ParameterDescriptor & descriptor,
|
||||
const int64_t value)
|
||||
{
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
auto integer_range = descriptor.integer_range.at(0);
|
||||
if (value == integer_range.from_value || value == integer_range.to_value) {
|
||||
return result;
|
||||
}
|
||||
if ((value < integer_range.from_value) || (value > integer_range.to_value)) {
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "integer");
|
||||
return result;
|
||||
}
|
||||
if (integer_range.step == 0) {
|
||||
return result;
|
||||
}
|
||||
if (((value - integer_range.from_value) % integer_range.step) == 0) {
|
||||
return result;
|
||||
}
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "integer");
|
||||
return result;
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
__check_double_range(
|
||||
const rcl_interfaces::msg::ParameterDescriptor & descriptor,
|
||||
const double value)
|
||||
{
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
auto fp_range = descriptor.floating_point_range.at(0);
|
||||
if (__are_doubles_equal(value, fp_range.from_value) || __are_doubles_equal(value,
|
||||
fp_range.to_value))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if ((value < fp_range.from_value) || (value > fp_range.to_value)) {
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "floating point");
|
||||
return result;
|
||||
}
|
||||
if (fp_range.step == 0.0) {
|
||||
return result;
|
||||
}
|
||||
double rounded_div = std::round((value - fp_range.from_value) / fp_range.step);
|
||||
if (__are_doubles_equal(value, fp_range.from_value + rounded_div * fp_range.step)) {
|
||||
return result;
|
||||
}
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "floating point");
|
||||
return result;
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
__check_parameter_value_in_range(
|
||||
@@ -260,39 +201,49 @@ __check_parameter_value_in_range(
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
if (!descriptor.integer_range.empty() && value.get_type() == rclcpp::PARAMETER_INTEGER) {
|
||||
result = __check_integer_range(descriptor, value.get<int64_t>());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!descriptor.integer_range.empty() && value.get_type() == rclcpp::PARAMETER_INTEGER_ARRAY) {
|
||||
std::vector<int64_t> val_array = value.get<std::vector<int64_t>>();
|
||||
for (const int64_t & val : val_array) {
|
||||
result = __check_integer_range(descriptor, val);
|
||||
if (!result.successful) {
|
||||
return result;
|
||||
}
|
||||
int64_t v = value.get<int64_t>();
|
||||
auto integer_range = descriptor.integer_range.at(0);
|
||||
if (v == integer_range.from_value || v == integer_range.to_value) {
|
||||
return result;
|
||||
}
|
||||
if ((v < integer_range.from_value) || (v > integer_range.to_value)) {
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "integer");
|
||||
return result;
|
||||
}
|
||||
if (integer_range.step == 0) {
|
||||
return result;
|
||||
}
|
||||
if (((v - integer_range.from_value) % integer_range.step) == 0) {
|
||||
return result;
|
||||
}
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "integer");
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!descriptor.floating_point_range.empty() && value.get_type() == rclcpp::PARAMETER_DOUBLE) {
|
||||
result = __check_double_range(descriptor, value.get<double>());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!descriptor.floating_point_range.empty() &&
|
||||
value.get_type() == rclcpp::PARAMETER_DOUBLE_ARRAY)
|
||||
{
|
||||
std::vector<double> val_array = value.get<std::vector<double>>();
|
||||
for (const double & val : val_array) {
|
||||
result = __check_double_range(descriptor, val);
|
||||
if (!result.successful) {
|
||||
return result;
|
||||
}
|
||||
double v = value.get<double>();
|
||||
auto fp_range = descriptor.floating_point_range.at(0);
|
||||
if (__are_doubles_equal(v, fp_range.from_value) || __are_doubles_equal(v, fp_range.to_value)) {
|
||||
return result;
|
||||
}
|
||||
if ((v < fp_range.from_value) || (v > fp_range.to_value)) {
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "floating point");
|
||||
return result;
|
||||
}
|
||||
if (fp_range.step == 0.0) {
|
||||
return result;
|
||||
}
|
||||
double rounded_div = std::round((v - fp_range.from_value) / fp_range.step);
|
||||
if (__are_doubles_equal(v, fp_range.from_value + rounded_div * fp_range.step)) {
|
||||
return result;
|
||||
}
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "floating point");
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,9 +47,9 @@ ParameterService::ParameterService(
|
||||
response->values.push_back(param.get_value_message());
|
||||
}
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp"), "Failed to get parameters: %s", ex.what());
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to get parameters: %s", ex.what());
|
||||
} catch (const rclcpp::exceptions::ParameterUninitializedException & ex) {
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp"), "Failed to get parameters: %s", ex.what());
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to get parameters: %s", ex.what());
|
||||
}
|
||||
},
|
||||
qos_profile, nullptr);
|
||||
@@ -70,7 +70,7 @@ ParameterService::ParameterService(
|
||||
return static_cast<rclcpp::ParameterType>(type);
|
||||
});
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp"), "Failed to get parameter types: %s", ex.what());
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to get parameter types: %s", ex.what());
|
||||
}
|
||||
},
|
||||
qos_profile, nullptr);
|
||||
@@ -91,7 +91,7 @@ ParameterService::ParameterService(
|
||||
result = node_params->set_parameters_atomically(
|
||||
{rclcpp::Parameter::from_parameter_msg(p)});
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp"), "Failed to set parameter: %s", ex.what());
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to set parameter: %s", ex.what());
|
||||
result.successful = false;
|
||||
result.reason = ex.what();
|
||||
}
|
||||
@@ -119,7 +119,7 @@ ParameterService::ParameterService(
|
||||
auto result = node_params->set_parameters_atomically(pvariants);
|
||||
response->result = result;
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_DEBUG(
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"), "Failed to set parameters atomically: %s", ex.what());
|
||||
response->result.successful = false;
|
||||
response->result.reason = "One or more parameters were not declared before setting";
|
||||
@@ -139,7 +139,7 @@ ParameterService::ParameterService(
|
||||
auto descriptors = node_params->describe_parameters(request->names);
|
||||
response->descriptors = descriptors;
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp"), "Failed to describe parameters: %s", ex.what());
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to describe parameters: %s", ex.what());
|
||||
}
|
||||
},
|
||||
qos_profile, nullptr);
|
||||
|
||||
@@ -67,13 +67,7 @@ Rate::sleep()
|
||||
// Calculate the time to sleep
|
||||
auto time_to_sleep = next_interval - now;
|
||||
// Sleep (will get interrupted by ctrl-c, may not sleep full time)
|
||||
try {
|
||||
// If the context is invalid, an exception will be thrown.
|
||||
clock_->sleep_for(time_to_sleep);
|
||||
} catch (const std::runtime_error & e) {
|
||||
// If it didn't sleep the full time, return false
|
||||
return false;
|
||||
}
|
||||
clock_->sleep_for(time_to_sleep);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,6 @@ void
|
||||
SignalHandler::signal_handler(
|
||||
int signum, siginfo_t * siginfo, void * context)
|
||||
{
|
||||
RCLCPP_INFO(SignalHandler::get_logger(), "signal_handler(signum=%d)", signum);
|
||||
auto & instance = SignalHandler::get_global_signal_handler();
|
||||
|
||||
auto old_signal_handler = instance.get_old_signal_handler(signum);
|
||||
@@ -91,7 +90,6 @@ SignalHandler::signal_handler(
|
||||
void
|
||||
SignalHandler::signal_handler(int signum)
|
||||
{
|
||||
RCLCPP_INFO(SignalHandler::get_logger(), "signal_handler(signum=%d)", signum);
|
||||
auto & instance = SignalHandler::get_global_signal_handler();
|
||||
auto old_signal_handler = instance.get_old_signal_handler(signum);
|
||||
if (
|
||||
@@ -249,9 +247,6 @@ SignalHandler::signal_handler_common()
|
||||
{
|
||||
auto & instance = SignalHandler::get_global_signal_handler();
|
||||
instance.signal_received_.store(true);
|
||||
RCLCPP_DEBUG(
|
||||
get_logger(),
|
||||
"signal_handler(): notifying deferred signal handler");
|
||||
instance.notify_signal_handler();
|
||||
}
|
||||
|
||||
@@ -260,6 +255,7 @@ SignalHandler::deferred_signal_handler()
|
||||
{
|
||||
while (true) {
|
||||
if (signal_received_.exchange(false)) {
|
||||
RCLCPP_INFO(SignalHandler::get_logger(), "signal_handler(SIGINT/SIGTERM)");
|
||||
RCLCPP_DEBUG(get_logger(), "deferred_signal_handler(): shutting down");
|
||||
for (auto context_ptr : rclcpp::get_contexts()) {
|
||||
if (context_ptr->get_init_options().shutdown_on_signal) {
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include "rclcpp/typesupport_helpers.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
@@ -74,21 +73,6 @@ const void * get_typesupport_handle_impl(
|
||||
}
|
||||
}
|
||||
|
||||
// Trim leading and trailing whitespace from the string.
|
||||
std::string string_trim(std::string_view str_v)
|
||||
{
|
||||
auto begin = std::find_if_not(str_v.begin(), str_v.end(), [](unsigned char ch) {
|
||||
return std::isspace(ch);
|
||||
});
|
||||
auto end = std::find_if_not(str_v.rbegin(), str_v.rend(), [](unsigned char ch) {
|
||||
return std::isspace(ch);
|
||||
}).base();
|
||||
if (begin >= end) {
|
||||
return {};
|
||||
}
|
||||
return std::string(begin, end);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
std::tuple<std::string, std::string, std::string>
|
||||
@@ -98,7 +82,6 @@ extract_type_identifier(const std::string & full_type)
|
||||
auto sep_position_back = full_type.find_last_of(type_separator);
|
||||
auto sep_position_front = full_type.find_first_of(type_separator);
|
||||
if (sep_position_back == std::string::npos ||
|
||||
sep_position_front == 0 ||
|
||||
sep_position_back == 0 ||
|
||||
sep_position_back == full_type.length() - 1)
|
||||
{
|
||||
@@ -114,8 +97,7 @@ extract_type_identifier(const std::string & full_type)
|
||||
}
|
||||
std::string type_name = full_type.substr(sep_position_back + 1);
|
||||
|
||||
return std::make_tuple(
|
||||
string_trim(package_name), string_trim(middle_module), string_trim(type_name));
|
||||
return std::make_tuple(package_name, middle_module, type_name);
|
||||
}
|
||||
|
||||
std::string get_typesupport_library_path(
|
||||
|
||||
@@ -125,13 +125,11 @@ BENCHMARK_F(ServicePerformanceTest, async_send_response)(benchmark::State & stat
|
||||
auto service = node->create_service<test_msgs::srv::Empty>(empty_service_name, callback);
|
||||
|
||||
reset_heap_counters();
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node->get_node_base_interface());
|
||||
for (auto _ : state) {
|
||||
(void)_;
|
||||
state.PauseTiming();
|
||||
// Clear executor queue
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node->get_node_base_interface());
|
||||
|
||||
auto request = std::make_shared<test_msgs::srv::Empty::Request>();
|
||||
auto future = empty_client->async_send_request(request);
|
||||
@@ -139,7 +137,7 @@ BENCHMARK_F(ServicePerformanceTest, async_send_response)(benchmark::State & stat
|
||||
benchmark::DoNotOptimize(service);
|
||||
benchmark::ClobberMemory();
|
||||
|
||||
executor.spin_until_future_complete(future);
|
||||
rclcpp::spin_until_future_complete(node->get_node_base_interface(), future);
|
||||
}
|
||||
if (callback_count == 0) {
|
||||
state.SkipWithError("Service callback was not called");
|
||||
|
||||
@@ -57,6 +57,11 @@ ament_add_test_label(test_client mimick)
|
||||
if(TARGET test_client)
|
||||
target_link_libraries(test_client ${PROJECT_NAME} mimick ${rcl_interfaces_TARGETS} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_clock test_clock.cpp)
|
||||
ament_add_test_label(test_clock mimick)
|
||||
if(TARGET test_clock)
|
||||
target_link_libraries(test_clock ${PROJECT_NAME} mimick ${rcl_interfaces_TARGETS} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_clock_conditional test_clock_conditional.cpp)
|
||||
ament_add_test_label(test_clock_conditional mimick)
|
||||
if(TARGET test_clock_conditional)
|
||||
@@ -529,6 +534,13 @@ if(TARGET test_executors_warmup)
|
||||
target_link_libraries(test_executors_warmup ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_static_single_threaded_executor executors/test_static_single_threaded_executor.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
ament_add_test_label(test_static_single_threaded_executor mimick)
|
||||
if(TARGET test_static_single_threaded_executor)
|
||||
target_link_libraries(test_static_single_threaded_executor ${PROJECT_NAME} mimick ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_multi_threaded_executor executors/test_multi_threaded_executor.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_multi_threaded_executor)
|
||||
|
||||
@@ -22,13 +22,40 @@
|
||||
|
||||
#include "rclcpp/experimental/executors/events_executor/events_executor.hpp"
|
||||
#include "rclcpp/executors/single_threaded_executor.hpp"
|
||||
#include "rclcpp/executors/static_single_threaded_executor.hpp"
|
||||
#include "rclcpp/executors/multi_threaded_executor.hpp"
|
||||
|
||||
// suppress deprecated StaticSingleThreadedExecutor warning
|
||||
// we define an alias that explicitly indicates that this class is deprecated, while avoiding
|
||||
// polluting a lot of files the gcc pragmas
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
using DeprecatedStaticSingleThreadedExecutor = rclcpp::executors::StaticSingleThreadedExecutor;
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
using ExecutorTypes =
|
||||
::testing::Types<
|
||||
rclcpp::executors::SingleThreadedExecutor,
|
||||
rclcpp::executors::MultiThreadedExecutor,
|
||||
DeprecatedStaticSingleThreadedExecutor,
|
||||
rclcpp::experimental::executors::EventsExecutor>;
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
class ExecutorTypeNames
|
||||
{
|
||||
@@ -43,6 +70,16 @@ public:
|
||||
if (std::is_same<T, rclcpp::executors::MultiThreadedExecutor>()) {
|
||||
return "MultiThreadedExecutor";
|
||||
}
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
if (std::is_same<T, DeprecatedStaticSingleThreadedExecutor>()) {
|
||||
return "StaticSingleThreadedExecutor";
|
||||
}
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
if (std::is_same<T, rclcpp::experimental::executors::EventsExecutor>()) {
|
||||
return "EventsExecutor";
|
||||
@@ -52,6 +89,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// StaticSingleThreadedExecutor is not included in these tests for now, due to:
|
||||
// https://github.com/ros2/rclcpp/issues/1219
|
||||
using StandardExecutors =
|
||||
::testing::Types<
|
||||
rclcpp::executors::SingleThreadedExecutor,
|
||||
|
||||
@@ -804,10 +804,8 @@ TEST(TestExecutors, testSpinUntilFutureCompleteNodePtr)
|
||||
}
|
||||
|
||||
// Check spin functions with non default context
|
||||
TYPED_TEST(TestExecutors, testSpinWithNonDefaultContext)
|
||||
TEST(TestExecutors, testSpinWithNonDefaultContext)
|
||||
{
|
||||
using ExecutorType = TypeParam;
|
||||
|
||||
auto non_default_context = std::make_shared<rclcpp::Context>();
|
||||
non_default_context->init(0, nullptr);
|
||||
|
||||
@@ -815,14 +813,9 @@ TYPED_TEST(TestExecutors, testSpinWithNonDefaultContext)
|
||||
auto node =
|
||||
std::make_unique<rclcpp::Node>("node", rclcpp::NodeOptions().context(non_default_context));
|
||||
|
||||
rclcpp::ExecutorOptions options;
|
||||
options.context = non_default_context;
|
||||
ExecutorType executor(options);
|
||||
EXPECT_NO_THROW(executor.add_node(node->get_node_base_interface()));
|
||||
EXPECT_NO_THROW(rclcpp::spin_some(node->get_node_base_interface()));
|
||||
|
||||
EXPECT_NO_THROW(executor.spin_some());
|
||||
|
||||
EXPECT_NO_THROW(executor.spin_all(1s));
|
||||
EXPECT_NO_THROW(rclcpp::spin_all(node->get_node_base_interface(), 1s));
|
||||
|
||||
auto check_spin_until_future_complete = [&]() {
|
||||
std::promise<bool> promise;
|
||||
@@ -830,7 +823,8 @@ TYPED_TEST(TestExecutors, testSpinWithNonDefaultContext)
|
||||
promise.set_value(true);
|
||||
|
||||
auto shared_future = future.share();
|
||||
auto ret = executor.spin_until_future_complete(shared_future, 1s);
|
||||
auto ret = rclcpp::spin_until_future_complete(
|
||||
node->get_node_base_interface(), shared_future, 1s);
|
||||
EXPECT_EQ(rclcpp::FutureReturnCode::SUCCESS, ret);
|
||||
};
|
||||
EXPECT_NO_THROW(check_spin_until_future_complete());
|
||||
|
||||
@@ -285,11 +285,20 @@ public:
|
||||
T executor;
|
||||
};
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
# endif
|
||||
#endif
|
||||
using MainExecutorTypes =
|
||||
::testing::Types<
|
||||
rclcpp::executors::SingleThreadedExecutor,
|
||||
rclcpp::executors::MultiThreadedExecutor>;
|
||||
|
||||
rclcpp::executors::MultiThreadedExecutor,
|
||||
DeprecatedStaticSingleThreadedExecutor>;
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
// TODO(@fujitatomoya): this test excludes EventExecutor because it does not
|
||||
// support simulation time used for this test to relax the racy condition.
|
||||
// See more details for https://github.com/ros2/rclcpp/issues/2457.
|
||||
|
||||
@@ -1,617 +0,0 @@
|
||||
// Copyright 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
#include "rcpputils/scope_exit.hpp"
|
||||
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
#include "test_msgs/srv/empty.hpp"
|
||||
|
||||
#include "../../mocking_utils/patch.hpp"
|
||||
#include "../../utils/rclcpp_gtest_macros.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct NumberOfEntities
|
||||
{
|
||||
size_t subscriptions = 0;
|
||||
size_t timers = 0;
|
||||
size_t services = 0;
|
||||
size_t clients = 0;
|
||||
size_t waitables = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<NumberOfEntities> get_number_of_default_entities(rclcpp::Node::SharedPtr node)
|
||||
{
|
||||
auto number_of_entities = std::make_unique<NumberOfEntities>();
|
||||
node->for_each_callback_group(
|
||||
[&number_of_entities](rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
if (!group->can_be_taken_from().load()) {
|
||||
return;
|
||||
}
|
||||
group->find_subscription_ptrs_if(
|
||||
[&number_of_entities](rclcpp::SubscriptionBase::SharedPtr &)
|
||||
{
|
||||
number_of_entities->subscriptions++; return false;
|
||||
});
|
||||
group->find_timer_ptrs_if(
|
||||
[&number_of_entities](rclcpp::TimerBase::SharedPtr &)
|
||||
{
|
||||
number_of_entities->timers++; return false;
|
||||
});
|
||||
group->find_service_ptrs_if(
|
||||
[&number_of_entities](rclcpp::ServiceBase::SharedPtr &)
|
||||
{
|
||||
number_of_entities->services++; return false;
|
||||
});
|
||||
group->find_client_ptrs_if(
|
||||
[&number_of_entities](rclcpp::ClientBase::SharedPtr &)
|
||||
{
|
||||
number_of_entities->clients++; return false;
|
||||
});
|
||||
group->find_waitable_ptrs_if(
|
||||
[&number_of_entities](rclcpp::Waitable::SharedPtr &)
|
||||
{
|
||||
number_of_entities->waitables++; return false;
|
||||
});
|
||||
});
|
||||
|
||||
return number_of_entities;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class TestStaticExecutorEntitiesCollector : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
entities_collector_ =
|
||||
std::make_shared<rclcpp::executors::StaticExecutorEntitiesCollector>();
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
rclcpp::executors::StaticExecutorEntitiesCollector::SharedPtr entities_collector_;
|
||||
};
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, construct_destruct) {
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_clients());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_waitables());
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_remove_node) {
|
||||
auto node1 = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
EXPECT_NO_THROW(entities_collector_->add_node(node1->get_node_base_interface()));
|
||||
|
||||
// Check adding second time
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->add_node(node1->get_node_base_interface()),
|
||||
std::runtime_error("Node has already been added to an executor."));
|
||||
|
||||
auto node2 = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
EXPECT_FALSE(entities_collector_->remove_node(node2->get_node_base_interface()));
|
||||
EXPECT_NO_THROW(entities_collector_->add_node(node2->get_node_base_interface()));
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node1->get_node_base_interface()));
|
||||
EXPECT_FALSE(entities_collector_->remove_node(node1->get_node_base_interface()));
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node2->get_node_base_interface()));
|
||||
|
||||
auto node3 = std::make_shared<rclcpp::Node>("node3", "ns");
|
||||
node3->get_node_base_interface()->get_associated_with_executor_atomic().exchange(true);
|
||||
EXPECT_FALSE(entities_collector_->remove_node(node3->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, init_bad_arguments) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
// Check memory strategy is nullptr
|
||||
rclcpp::memory_strategy::MemoryStrategy::SharedPtr memory_strategy = nullptr;
|
||||
EXPECT_THROW(
|
||||
entities_collector_->init(&wait_set, memory_strategy),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_remove_basic_node) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
const auto expected_number_of_entities = get_number_of_default_entities(node);
|
||||
EXPECT_NE(nullptr, expected_number_of_entities);
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
EXPECT_EQ(
|
||||
expected_number_of_entities->subscriptions,
|
||||
entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(expected_number_of_entities->timers, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(expected_number_of_entities->services, entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(expected_number_of_entities->clients, entities_collector_->get_number_of_clients());
|
||||
// One extra for the executor
|
||||
EXPECT_EQ(
|
||||
1u + expected_number_of_entities->waitables,
|
||||
entities_collector_->get_number_of_waitables());
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_clients());
|
||||
|
||||
// Still one for the executor
|
||||
EXPECT_EQ(1u, entities_collector_->get_number_of_waitables());
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_remove_node_out_of_scope) {
|
||||
rclcpp::Context::SharedPtr shared_context = nullptr;
|
||||
{
|
||||
auto node1 = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
auto node2 = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
auto node3 = std::make_shared<rclcpp::Node>("node3", "ns");
|
||||
entities_collector_->add_node(node1->get_node_base_interface());
|
||||
entities_collector_->add_node(node2->get_node_base_interface());
|
||||
entities_collector_->add_node(node3->get_node_base_interface());
|
||||
shared_context = node1->get_node_base_interface()->get_context();
|
||||
}
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
// Expect weak_node pointers to be cleaned up and used
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_clients());
|
||||
|
||||
// Still one for the executor
|
||||
EXPECT_EQ(1u, entities_collector_->get_number_of_waitables());
|
||||
}
|
||||
|
||||
class TestWaitable : public rclcpp::Waitable
|
||||
{
|
||||
public:
|
||||
void add_to_wait_set(rcl_wait_set_t &) override {}
|
||||
|
||||
bool is_ready(const rcl_wait_set_t &) override {return true;}
|
||||
|
||||
std::shared_ptr<void>
|
||||
take_data() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
void
|
||||
execute(const std::shared_ptr<void> &) override {}
|
||||
};
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_remove_node_with_entities) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
auto expected_number_of_entities = get_number_of_default_entities(node);
|
||||
EXPECT_NE(nullptr, expected_number_of_entities);
|
||||
|
||||
// Create 1 of each entity type
|
||||
auto subscription =
|
||||
node->create_subscription<test_msgs::msg::Empty>(
|
||||
"topic", rclcpp::QoS(10), [](test_msgs::msg::Empty::ConstSharedPtr) {});
|
||||
auto timer =
|
||||
node->create_wall_timer(std::chrono::seconds(60), []() {});
|
||||
auto service =
|
||||
node->create_service<test_msgs::srv::Empty>(
|
||||
"service",
|
||||
[](
|
||||
const test_msgs::srv::Empty::Request::SharedPtr,
|
||||
test_msgs::srv::Empty::Response::SharedPtr) {});
|
||||
auto client = node->create_client<test_msgs::srv::Empty>("service");
|
||||
auto waitable = std::make_shared<TestWaitable>();
|
||||
|
||||
// Adding a subscription could add another waitable, so we need to get the
|
||||
// current number of waitables just before adding the new waitable.
|
||||
expected_number_of_entities->waitables = get_number_of_default_entities(node)->waitables;
|
||||
node->get_node_waitables_interface()->add_waitable(waitable, nullptr);
|
||||
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
EXPECT_EQ(
|
||||
1u + expected_number_of_entities->subscriptions,
|
||||
entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(1u + expected_number_of_entities->timers, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(
|
||||
1u + expected_number_of_entities->services,
|
||||
entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(
|
||||
1u + expected_number_of_entities->clients,
|
||||
entities_collector_->get_number_of_clients());
|
||||
|
||||
// One extra for the executor
|
||||
EXPECT_EQ(
|
||||
2u + expected_number_of_entities->waitables,
|
||||
entities_collector_->get_number_of_waitables());
|
||||
|
||||
entities_collector_->remove_node(node->get_node_base_interface());
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_clients());
|
||||
// Still one for the executor
|
||||
EXPECT_EQ(1u, entities_collector_->get_number_of_waitables());
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_callback_group) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 1u);
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_callback_group_after_add_node) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface()),
|
||||
std::runtime_error("Callback group has already been added to an executor."));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_callback_group_twice) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 1u);
|
||||
cb_group->get_associated_with_executor_atomic().exchange(false);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface()),
|
||||
std::runtime_error("Callback group was already added to executor."));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, prepare_wait_set_rcl_wait_set_clear_error) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_wait_set_clear, RCL_RET_ERROR);
|
||||
std::shared_ptr<void> data = entities_collector_->take_data();
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->execute(data),
|
||||
std::runtime_error("Couldn't clear wait set"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, prepare_wait_set_rcl_wait_set_resize_error) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_wait_set_resize, RCL_RET_ERROR);
|
||||
std::shared_ptr<void> data = entities_collector_->take_data();
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->execute(data),
|
||||
std::runtime_error("Couldn't resize the wait set: error not set"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, refresh_wait_set_not_initialized) {
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->refresh_wait_set(std::chrono::nanoseconds(1000)),
|
||||
std::runtime_error("Couldn't clear wait set"));
|
||||
rcl_reset_error();
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, refresh_wait_set_rcl_wait_failed) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_wait, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->refresh_wait_set(std::chrono::nanoseconds(1000)),
|
||||
std::runtime_error("rcl_wait() failed: error not set"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, refresh_wait_set_add_handles_to_wait_set_failed) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
// Create 1 of each entity type
|
||||
auto subscription =
|
||||
node->create_subscription<test_msgs::msg::Empty>(
|
||||
"topic", rclcpp::QoS(10), [](test_msgs::msg::Empty::ConstSharedPtr) {});
|
||||
auto timer =
|
||||
node->create_wall_timer(std::chrono::seconds(60), []() {});
|
||||
auto service =
|
||||
node->create_service<test_msgs::srv::Empty>(
|
||||
"service",
|
||||
[](
|
||||
const test_msgs::srv::Empty::Request::SharedPtr,
|
||||
test_msgs::srv::Empty::Response::SharedPtr) {});
|
||||
auto client = node->create_client<test_msgs::srv::Empty>("service");
|
||||
auto waitable = std::make_shared<TestWaitable>();
|
||||
|
||||
node->get_node_waitables_interface()->add_waitable(waitable, nullptr);
|
||||
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return(
|
||||
"lib:rclcpp", rcl_wait_set_add_subscription,
|
||||
RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->refresh_wait_set(std::chrono::nanoseconds(1000)),
|
||||
std::runtime_error("Couldn't fill wait set"));
|
||||
}
|
||||
|
||||
entities_collector_->remove_node(node->get_node_base_interface());
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_to_wait_set_nullptr) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, fill_memory_strategy_invalid_group) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 2u);
|
||||
|
||||
cb_group.reset();
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 1u);
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, remove_callback_group_after_node) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 1u);
|
||||
|
||||
node.reset();
|
||||
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->remove_callback_group(cb_group),
|
||||
std::runtime_error("Node must not be deleted before its callback group(s)."));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, remove_callback_group_twice) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 1u);
|
||||
|
||||
entities_collector_->remove_callback_group(cb_group);
|
||||
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->remove_callback_group(cb_group),
|
||||
std::runtime_error("Callback group needs to be associated with executor."));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, remove_node_opposite_order) {
|
||||
auto node1 = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
EXPECT_NO_THROW(entities_collector_->add_node(node1->get_node_base_interface()));
|
||||
|
||||
auto node2 = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
EXPECT_NO_THROW(entities_collector_->add_node(node2->get_node_base_interface()));
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node2->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
TestStaticExecutorEntitiesCollector,
|
||||
add_callback_groups_from_nodes_associated_to_executor_add) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
cb_group->get_associated_with_executor_atomic().exchange(false);
|
||||
std::shared_ptr<void> data = entities_collector_->take_data();
|
||||
entities_collector_->execute(data);
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
// Copyright 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
#include "test_msgs/srv/empty.hpp"
|
||||
|
||||
#include "./executor_types.hpp"
|
||||
#include "../../mocking_utils/patch.hpp"
|
||||
#include "../../utils/rclcpp_gtest_macros.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
class TestStaticSingleThreadedExecutor : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestStaticSingleThreadedExecutor, add_callback_group_trigger_guard_failed) {
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
DeprecatedStaticSingleThreadedExecutor executor;
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return(
|
||||
"lib:rclcpp", rcl_trigger_guard_condition, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
executor.add_callback_group(cb_group, node->get_node_base_interface(), true),
|
||||
std::runtime_error("Failed to handle entities update on callback group add: error not set"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestStaticSingleThreadedExecutor, add_node_trigger_guard_failed) {
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
DeprecatedStaticSingleThreadedExecutor executor;
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return(
|
||||
"lib:rclcpp", rcl_trigger_guard_condition, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
executor.add_node(node),
|
||||
std::runtime_error("Failed to handle entities update on node add: error not set"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestStaticSingleThreadedExecutor, remove_callback_group_trigger_guard_failed) {
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
DeprecatedStaticSingleThreadedExecutor executor;
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
executor.add_callback_group(cb_group, node->get_node_base_interface(), true);
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return(
|
||||
"lib:rclcpp", rcl_trigger_guard_condition, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
executor.remove_callback_group(cb_group, true),
|
||||
std::runtime_error(
|
||||
"Failed to handle entities update on callback group remove: error not set"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestStaticSingleThreadedExecutor, remove_node_failed) {
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
DeprecatedStaticSingleThreadedExecutor executor;
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return(
|
||||
"lib:rclcpp", rcl_trigger_guard_condition, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
executor.remove_node(node, true),
|
||||
std::runtime_error("Node '/ns/node' needs to be associated with an executor."));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestStaticSingleThreadedExecutor, remove_node_trigger_guard_failed) {
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
DeprecatedStaticSingleThreadedExecutor executor;
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
executor.add_node(node);
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return(
|
||||
"lib:rclcpp", rcl_trigger_guard_condition, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
executor.remove_node(node, true),
|
||||
std::runtime_error("Failed to handle entities update on node remove: error not set"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestStaticSingleThreadedExecutor, execute_service) {
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
DeprecatedStaticSingleThreadedExecutor executor;
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
executor.add_node(node);
|
||||
|
||||
auto service =
|
||||
node->create_service<test_msgs::srv::Empty>(
|
||||
"service",
|
||||
[](
|
||||
const test_msgs::srv::Empty::Request::SharedPtr,
|
||||
test_msgs::srv::Empty::Response::SharedPtr) {});
|
||||
auto client = node->create_client<test_msgs::srv::Empty>("service");
|
||||
|
||||
std::promise<void> promise;
|
||||
std::future<void> future = promise.get_future();
|
||||
EXPECT_EQ(
|
||||
rclcpp::FutureReturnCode::TIMEOUT,
|
||||
executor.spin_until_future_complete(future, std::chrono::milliseconds(1)));
|
||||
|
||||
executor.remove_node(node);
|
||||
executor.spin_until_future_complete(future, std::chrono::milliseconds(1));
|
||||
}
|
||||
@@ -510,9 +510,7 @@ TEST_F(TestNodeGraph, get_node_names_and_namespaces_fini_errors)
|
||||
"lib:rclcpp", rcutils_string_array_fini, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
node_graph()->get_node_names_and_namespaces(),
|
||||
std::runtime_error(
|
||||
"could not destroy node names: error not set, "
|
||||
"could not destroy node namespaces: error not set"));
|
||||
std::runtime_error("could not destroy node names, could not destroy node namespaces"));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, get_node_names_with_enclaves_fini_errors)
|
||||
|
||||
@@ -192,7 +192,7 @@ TEST_F(TestNodeInterfaces, ni_init) {
|
||||
/*
|
||||
Testing macro'ed getters.
|
||||
*/
|
||||
TEST_F(TestNodeInterfaces, ni_all_init) {
|
||||
TEST_F(TestNodeInterfaces, ni_all_init_non_const) {
|
||||
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
|
||||
|
||||
using rclcpp::node_interfaces::NodeInterfaces;
|
||||
@@ -252,3 +252,64 @@ TEST_F(TestNodeInterfaces, ni_all_init) {
|
||||
time_source = ni.get_node_time_source_interface();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestNodeInterfaces, ni_all_init_const) {
|
||||
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
|
||||
|
||||
using rclcpp::node_interfaces::NodeInterfaces;
|
||||
using rclcpp::node_interfaces::NodeBaseInterface;
|
||||
using rclcpp::node_interfaces::NodeClockInterface;
|
||||
using rclcpp::node_interfaces::NodeGraphInterface;
|
||||
using rclcpp::node_interfaces::NodeLoggingInterface;
|
||||
using rclcpp::node_interfaces::NodeTimersInterface;
|
||||
using rclcpp::node_interfaces::NodeTopicsInterface;
|
||||
using rclcpp::node_interfaces::NodeServicesInterface;
|
||||
using rclcpp::node_interfaces::NodeWaitablesInterface;
|
||||
using rclcpp::node_interfaces::NodeParametersInterface;
|
||||
using rclcpp::node_interfaces::NodeTimeSourceInterface;
|
||||
|
||||
const auto ni = rclcpp::node_interfaces::NodeInterfaces<ALL_RCLCPP_NODE_INTERFACES>(*node);
|
||||
|
||||
{
|
||||
auto base = ni.get<NodeBaseInterface>();
|
||||
base = ni.get_node_base_interface();
|
||||
EXPECT_STREQ(base->get_name(), "my_node"); // Test for functionality
|
||||
}
|
||||
{
|
||||
auto clock = ni.get<NodeClockInterface>();
|
||||
clock = ni.get_node_clock_interface();
|
||||
clock->get_clock();
|
||||
}
|
||||
{
|
||||
auto graph = ni.get<NodeGraphInterface>();
|
||||
graph = ni.get_node_graph_interface();
|
||||
}
|
||||
{
|
||||
auto logging = ni.get<NodeLoggingInterface>();
|
||||
logging = ni.get_node_logging_interface();
|
||||
}
|
||||
{
|
||||
auto timers = ni.get<NodeTimersInterface>();
|
||||
timers = ni.get_node_timers_interface();
|
||||
}
|
||||
{
|
||||
auto topics = ni.get<NodeTopicsInterface>();
|
||||
topics = ni.get_node_topics_interface();
|
||||
}
|
||||
{
|
||||
auto services = ni.get<NodeServicesInterface>();
|
||||
services = ni.get_node_services_interface();
|
||||
}
|
||||
{
|
||||
auto waitables = ni.get<NodeWaitablesInterface>();
|
||||
waitables = ni.get_node_waitables_interface();
|
||||
}
|
||||
{
|
||||
auto parameters = ni.get<NodeParametersInterface>();
|
||||
parameters = ni.get_node_parameters_interface();
|
||||
}
|
||||
{
|
||||
auto time_source = ni.get<NodeTimeSourceInterface>();
|
||||
time_source = ni.get_node_time_source_interface();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,12 +112,10 @@ protected:
|
||||
auto req_id = client->async_send_request(request, std::move(callback));
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
while (!received_response &&
|
||||
(std::chrono::steady_clock::now() - start) < timeout)
|
||||
{
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
|
||||
if (!received_response) {
|
||||
@@ -358,12 +356,10 @@ TYPED_TEST(TestAllClientTypesWithServer, on_new_response_callback)
|
||||
|
||||
this->template async_send_request<ClientType, test_msgs::srv::Empty::Request>(client, request);
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(server_node);
|
||||
while (server_requests_count == 0 &&
|
||||
(std::chrono::steady_clock::now() - start) < std::chrono::seconds(10))
|
||||
{
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(server_node);
|
||||
}
|
||||
|
||||
ASSERT_EQ(server_requests_count, 1u);
|
||||
@@ -384,7 +380,7 @@ TYPED_TEST(TestAllClientTypesWithServer, on_new_response_callback)
|
||||
while (server_requests_count == 1 &&
|
||||
(std::chrono::steady_clock::now() - start) < std::chrono::seconds(10))
|
||||
{
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(server_node);
|
||||
}
|
||||
|
||||
ASSERT_EQ(server_requests_count, 2u);
|
||||
@@ -406,7 +402,7 @@ TYPED_TEST(TestAllClientTypesWithServer, on_new_response_callback)
|
||||
while (server_requests_count < 5 &&
|
||||
(std::chrono::steady_clock::now() - start) < std::chrono::seconds(10))
|
||||
{
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(server_node);
|
||||
}
|
||||
|
||||
ASSERT_EQ(server_requests_count, 5u);
|
||||
@@ -496,12 +492,10 @@ void client_async_send_request_callback_with_request(
|
||||
auto req_id = client->async_send_request(request, std::move(callback));
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
while (!received_response &&
|
||||
(std::chrono::steady_clock::now() - start) < std::chrono::seconds(1))
|
||||
{
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
EXPECT_TRUE(received_response);
|
||||
EXPECT_FALSE(client->remove_pending_request(req_id));
|
||||
@@ -559,29 +553,25 @@ void client_qos_depth(rclcpp::Node::SharedPtr node)
|
||||
}
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
rclcpp::executors::SingleThreadedExecutor server_executor;
|
||||
server_executor.add_node(server_node);
|
||||
while ((server_cb_count_ < client_requests) &&
|
||||
(std::chrono::steady_clock::now() - start) < 2s)
|
||||
{
|
||||
server_executor.spin_some();
|
||||
rclcpp::spin_some(server_node);
|
||||
std::this_thread::sleep_for(2ms);
|
||||
}
|
||||
|
||||
EXPECT_GT(server_cb_count_, client_qos_profile.depth());
|
||||
|
||||
start = std::chrono::steady_clock::now();
|
||||
rclcpp::executors::SingleThreadedExecutor client_executor;
|
||||
client_executor.add_node(node);
|
||||
while ((client_cb_count_ < client_qos_profile.depth()) &&
|
||||
(std::chrono::steady_clock::now() - start) < 1s)
|
||||
{
|
||||
client_executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
|
||||
// Spin an extra time to check if client QoS depth has been ignored,
|
||||
// so more client callbacks might be called than expected.
|
||||
client_executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
|
||||
EXPECT_EQ(client_cb_count_, client_qos_profile.depth());
|
||||
}
|
||||
|
||||
238
rclcpp/test/rclcpp/test_clock.cpp
Normal file
238
rclcpp/test/rclcpp/test_clock.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
// Copyright 2024 Cellumation GmbH
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <rcpputils/compile_warnings.hpp>
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/time.h"
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "rclcpp/time_source.hpp"
|
||||
|
||||
#include "../utils/rclcpp_gtest_macros.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
class TestClockWakeup : public ::testing::TestWithParam<rcl_clock_type_e>
|
||||
{
|
||||
public:
|
||||
void test_wakeup_before_sleep(const rclcpp::Clock::SharedPtr & clock)
|
||||
{
|
||||
std::atomic_bool thread_finished = false;
|
||||
|
||||
std::thread wait_thread = std::thread(
|
||||
[&clock, &thread_finished]()
|
||||
{
|
||||
// make sure the thread starts sleeping late
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
clock->sleep_until(clock->now() + std::chrono::seconds(3));
|
||||
thread_finished = true;
|
||||
});
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_START
|
||||
// notify the clock, that the sleep shall be interrupted
|
||||
clock->cancel_sleep_or_wait();
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_STOP
|
||||
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
auto cur_time = start_time;
|
||||
while (!thread_finished && start_time + std::chrono::seconds(1) > cur_time) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
cur_time = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
wait_thread.join();
|
||||
|
||||
EXPECT_TRUE(thread_finished);
|
||||
EXPECT_LT(cur_time, start_time + std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
void test_wakeup_after_sleep(const rclcpp::Clock::SharedPtr & clock)
|
||||
{
|
||||
std::atomic_bool thread_finished = false;
|
||||
|
||||
std::thread wait_thread = std::thread(
|
||||
[&clock, &thread_finished]()
|
||||
{
|
||||
clock->sleep_until(clock->now() + std::chrono::seconds(3));
|
||||
thread_finished = true;
|
||||
});
|
||||
|
||||
// make sure the thread is already sleeping before we send the cancel
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_START
|
||||
// notify the clock, that the sleep shall be interrupted
|
||||
clock->cancel_sleep_or_wait();
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_STOP
|
||||
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
auto cur_time = start_time;
|
||||
while (!thread_finished && start_time + std::chrono::seconds(1) > cur_time) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
cur_time = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
wait_thread.join();
|
||||
|
||||
EXPECT_TRUE(thread_finished);
|
||||
EXPECT_LT(cur_time, start_time + std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
protected:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
void SetUp()
|
||||
{
|
||||
node = std::make_shared<rclcpp::Node>("my_node");
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
node.reset();
|
||||
}
|
||||
|
||||
rclcpp::Node::SharedPtr node;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Clocks,
|
||||
TestClockWakeup,
|
||||
::testing::Values(
|
||||
RCL_SYSTEM_TIME, RCL_ROS_TIME, RCL_STEADY_TIME
|
||||
));
|
||||
|
||||
TEST_P(TestClockWakeup, wakeup_sleep) {
|
||||
auto clock = std::make_shared<rclcpp::Clock>(GetParam());
|
||||
test_wakeup_after_sleep(clock);
|
||||
test_wakeup_before_sleep(clock);
|
||||
}
|
||||
|
||||
TEST_F(TestClockWakeup, wakeup_sleep_ros_time_active) {
|
||||
node->set_parameter({"use_sim_time", true});
|
||||
auto clock = std::make_shared<rclcpp::Clock>(RCL_ROS_TIME);
|
||||
rclcpp::TimeSource time_source(node);
|
||||
time_source.attachClock(clock);
|
||||
|
||||
EXPECT_TRUE(clock->ros_time_is_active());
|
||||
|
||||
test_wakeup_after_sleep(clock);
|
||||
test_wakeup_before_sleep(clock);
|
||||
}
|
||||
|
||||
TEST_F(TestClockWakeup, no_wakeup_on_sim_time) {
|
||||
node->set_parameter({"use_sim_time", true});
|
||||
auto clock = std::make_shared<rclcpp::Clock>(RCL_ROS_TIME);
|
||||
rclcpp::TimeSource time_source(node);
|
||||
time_source.attachClock(clock);
|
||||
|
||||
EXPECT_TRUE(clock->ros_time_is_active());
|
||||
|
||||
std::atomic_bool thread_finished = false;
|
||||
|
||||
std::thread wait_thread = std::thread(
|
||||
[&clock, &thread_finished]()
|
||||
{
|
||||
// make sure the thread starts sleeping late
|
||||
clock->sleep_until(clock->now() + std::chrono::milliseconds(10));
|
||||
thread_finished = true;
|
||||
});
|
||||
|
||||
// make sure, that the sim time clock does not wakeup, as no clock is provided
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
EXPECT_FALSE(thread_finished);
|
||||
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_START
|
||||
// notify the clock, that the sleep shall be interrupted
|
||||
clock->cancel_sleep_or_wait();
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_STOP
|
||||
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
auto cur_time = start_time;
|
||||
while (!thread_finished && start_time + std::chrono::seconds(1) > cur_time) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
cur_time = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
wait_thread.join();
|
||||
|
||||
EXPECT_TRUE(thread_finished);
|
||||
EXPECT_LT(cur_time, start_time + std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
TEST_F(TestClockWakeup, multiple_threads_wait_on_one_clock) {
|
||||
auto clock = std::make_shared<rclcpp::Clock>(RCL_ROS_TIME);
|
||||
|
||||
std::vector<std::atomic_bool> thread_finished(10);
|
||||
for (std::atomic_bool & finished : thread_finished) {
|
||||
finished = false;
|
||||
}
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
for (size_t nr = 0; nr < thread_finished.size(); nr++) {
|
||||
threads.push_back(
|
||||
std::thread(
|
||||
[&clock, &thread_finished, nr]()
|
||||
{
|
||||
// make sure the thread starts sleeping late
|
||||
clock->sleep_until(clock->now() + std::chrono::seconds(10));
|
||||
thread_finished[nr] = true;
|
||||
}));
|
||||
}
|
||||
|
||||
// wait a bit so all threads can execute the sleep_until
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
|
||||
for (const std::atomic_bool & finished : thread_finished) {
|
||||
EXPECT_FALSE(finished);
|
||||
}
|
||||
|
||||
rclcpp::shutdown();
|
||||
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
auto cur_time = start_time;
|
||||
bool threads_finished = false;
|
||||
while (!threads_finished && start_time + std::chrono::seconds(1) > cur_time) {
|
||||
threads_finished = true;
|
||||
for (const std::atomic_bool & finished : thread_finished) {
|
||||
if (!finished) {
|
||||
threads_finished = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
cur_time = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
for (const std::atomic_bool & finished : thread_finished) {
|
||||
EXPECT_TRUE(finished);
|
||||
}
|
||||
|
||||
for (auto & thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
|
||||
EXPECT_LT(cur_time, start_time + std::chrono::seconds(1));
|
||||
}
|
||||
@@ -42,9 +42,7 @@ TEST(TestCreateTimer, timer_executes)
|
||||
timer->cancel();
|
||||
});
|
||||
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
|
||||
ASSERT_TRUE(got_callback);
|
||||
rclcpp::shutdown();
|
||||
|
||||
@@ -342,12 +342,12 @@ TEST_F(TestExecutor, spin_all_fail_wait_set_clear) {
|
||||
subscription =
|
||||
rclcpp::create_subscription<test_msgs::msg::Empty>(
|
||||
node_topics, "test", rclcpp::QoS(10), std::move(callback));
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_wait_set_clear, RCL_RET_ERROR);
|
||||
|
||||
dummy.spin_all(std::chrono::milliseconds(1));
|
||||
// second spin_all triggers rcl_wait_set_clear that should be called
|
||||
// whenever a waitset gets rebuild and it was not changed in size.
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_wait_set_clear, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
// the first spin might trigger the rebuild, but only the second triggers
|
||||
// it for sure, therefore we spin two times
|
||||
dummy.spin_all(std::chrono::milliseconds(1));
|
||||
dummy.spin_all(std::chrono::milliseconds(1)),
|
||||
std::runtime_error("Couldn't clear the wait set: error not set"));
|
||||
}
|
||||
|
||||
@@ -78,10 +78,8 @@ public:
|
||||
counter++;
|
||||
});
|
||||
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node_);
|
||||
while (counter < expected_recv_msg_count) {
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node_);
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
@@ -109,13 +107,11 @@ public:
|
||||
{
|
||||
using clock = std::chrono::system_clock;
|
||||
auto start = clock::now();
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node_);
|
||||
while (!condition()) {
|
||||
if ((clock::now() - start) > timeout) {
|
||||
return false;
|
||||
}
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -372,18 +372,16 @@ TEST_F(TestGenericService, generic_service_qos_depth) {
|
||||
}
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(server_node);
|
||||
while ((server_cb_count_ < server_qos_profile.depth()) &&
|
||||
(std::chrono::steady_clock::now() - start) < 1s)
|
||||
{
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(server_node);
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
// Spin an extra time to check if server QoS depth has been ignored,
|
||||
// so more server responses might be processed than expected.
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(server_node);
|
||||
|
||||
EXPECT_EQ(server_cb_count_, server_qos_profile.depth());
|
||||
}
|
||||
|
||||
@@ -43,7 +43,9 @@ public:
|
||||
node_graph_ = node_->get_node_graph_interface();
|
||||
ASSERT_NE(nullptr, node_graph_);
|
||||
|
||||
graph_listener_ = rclcpp::contexts::get_global_default_context()->get_graph_listener();
|
||||
graph_listener_ =
|
||||
std::make_shared<rclcpp::graph_listener::GraphListener>(
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
/*
|
||||
Constructor
|
||||
Construtctor
|
||||
*/
|
||||
TEST(TestIntraProcessBuffer, constructor) {
|
||||
using MessageT = char;
|
||||
|
||||
@@ -535,7 +535,7 @@ TEST(TestIntraProcessManager, add_pub_sub) {
|
||||
* - Remove the first subscription from ipm and add a new one.
|
||||
* - Publishes a unique_ptr message with a subscription not requesting ownership.
|
||||
* - The received message is expected to be the same, the first subscription do not receive it.
|
||||
* - Publishes a shared_ptr message with a subscription not requesting ownership.
|
||||
* - Publishes a unique_ptr message with a subscription not requesting ownership.
|
||||
* - The received message is expected to be the same.
|
||||
*/
|
||||
TEST(TestIntraProcessManager, single_subscription) {
|
||||
@@ -587,9 +587,9 @@ TEST(TestIntraProcessManager, single_subscription) {
|
||||
* - One is expected to receive the published message, while the other will receive a copy.
|
||||
* - Publishes a unique_ptr message with 2 subscriptions not requesting ownership.
|
||||
* - Both received messages are expected to be the same as the published one.
|
||||
* - Publishes a shared_ptr message with 2 subscriptions requesting ownership.
|
||||
* - Publishes a unique_ptr message with 2 subscriptions requesting ownership.
|
||||
* - Both received messages are expected to be a copy of the published one.
|
||||
* - Publishes a shared_ptr message with 2 subscriptions not requesting ownership.
|
||||
* - Publishes a unique_ptr message with 2 subscriptions not requesting ownership.
|
||||
* - Both received messages are expected to be the same as the published one.
|
||||
*/
|
||||
TEST(TestIntraProcessManager, multiple_subscriptions_same_type) {
|
||||
@@ -694,9 +694,9 @@ TEST(TestIntraProcessManager, multiple_subscriptions_same_type) {
|
||||
* - The 2 subscriptions not requesting ownership are expected to both receive the same copy
|
||||
* of the message, one of the subscription requesting ownership is expected to receive a
|
||||
* different copy, while the last is expected to receive the published message.
|
||||
* - Publishes a shared_ptr message with 1 subscription requesting ownership and 1 not.
|
||||
* - The subscription requesting ownership is expected to receive a copy of the message, while
|
||||
* the other is expected to receive the published message
|
||||
* - Publishes a unique_ptr message with 1 subscription requesting ownership and 1 not.
|
||||
* - The subscription requesting ownership is expected to receive the published message, while
|
||||
* the other is expected to receive a copy of the message
|
||||
*/
|
||||
TEST(TestIntraProcessManager, multiple_subscriptions_different_type) {
|
||||
using IntraProcessManagerT = rclcpp::experimental::IntraProcessManager;
|
||||
|
||||
@@ -129,8 +129,6 @@ TEST_F(TestMemoryStrategy, get_subscription_by_handle) {
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
memory_strategy()->get_subscription_by_handle(subscription_handle, weak_groups_to_nodes));
|
||||
// Clear all handles to cleanup when node is destroyed
|
||||
memory_strategy()->clear_handles();
|
||||
} // Node goes out of scope
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
@@ -183,8 +181,6 @@ TEST_F(TestMemoryStrategy, get_service_by_handle) {
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
memory_strategy()->get_service_by_handle(service_handle, weak_groups_to_nodes));
|
||||
// Clear all handles to cleanup when node is destroyed
|
||||
memory_strategy()->clear_handles();
|
||||
} // Node goes out of scope
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
@@ -232,11 +228,6 @@ TEST_F(TestMemoryStrategy, get_client_by_handle) {
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
memory_strategy()->get_client_by_handle(client_handle, weak_groups_to_nodes));
|
||||
// Clear all handles to cleanup when node is destroyed
|
||||
memory_strategy()->clear_handles();
|
||||
// reset client handle before node destruction, otherwise it tries to access node
|
||||
// via weak_ptr in its deleter
|
||||
client_handle.reset();
|
||||
} // Node goes out of scope
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
@@ -285,8 +276,6 @@ TEST_F(TestMemoryStrategy, get_timer_by_handle) {
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
memory_strategy()->get_timer_by_handle(timer_handle, weak_groups_to_nodes));
|
||||
// Clear all handles to cleanup when node is destroyed
|
||||
memory_strategy()->clear_handles();
|
||||
} // Node goes out of scope
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
@@ -386,8 +375,6 @@ TEST_F(TestMemoryStrategy, get_group_by_subscription) {
|
||||
EXPECT_EQ(
|
||||
callback_group,
|
||||
memory_strategy()->get_group_by_subscription(subscription, weak_groups_to_nodes));
|
||||
// Clear all handles to cleanup when node is destroyed
|
||||
memory_strategy()->clear_handles();
|
||||
} // Node goes out of scope
|
||||
// NodeBase(SubscriptionBase->rcl_node_t->NodeBase) is still alive.
|
||||
EXPECT_EQ(
|
||||
@@ -433,8 +420,6 @@ TEST_F(TestMemoryStrategy, get_group_by_service) {
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
memory_strategy()->get_group_by_service(service, weak_groups_to_nodes));
|
||||
// Clear all handles to cleanup when node is destroyed
|
||||
memory_strategy()->clear_handles();
|
||||
} // Node goes out of scope
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
@@ -474,8 +459,6 @@ TEST_F(TestMemoryStrategy, get_group_by_client) {
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
memory_strategy()->get_group_by_client(client, weak_groups_to_nodes));
|
||||
// Clear all handles to cleanup when node is destroyed
|
||||
memory_strategy()->clear_handles();
|
||||
} // Node goes out of scope
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
@@ -515,8 +498,6 @@ TEST_F(TestMemoryStrategy, get_group_by_timer) {
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
memory_strategy()->get_group_by_timer(timer, weak_groups_to_nodes));
|
||||
// Clear all handles to cleanup when node is destroyed
|
||||
memory_strategy()->clear_handles();
|
||||
} // Node goes out of scope
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
@@ -555,8 +536,6 @@ TEST_F(TestMemoryStrategy, get_group_by_waitable) {
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
memory_strategy()->get_group_by_waitable(waitable, weak_groups_to_nodes));
|
||||
// Clear all handles to cleanup when node is destroyed
|
||||
memory_strategy()->clear_handles();
|
||||
} // Node goes out of scope
|
||||
EXPECT_EQ(
|
||||
nullptr,
|
||||
|
||||
@@ -1365,203 +1365,6 @@ TEST_F(TestNode, set_parameter_undeclared_parameters_not_allowed) {
|
||||
node->declare_parameter(name, 42, descriptor),
|
||||
rclcpp::exceptions::InvalidParameterValueException);
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 10;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 2;
|
||||
node->declare_parameter(name, std::vector<int64_t>{10, 12, 14, 16, 18}, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(), std::vector<int64_t>({10, 12, 14, 16, 18}));
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({12, 14, 10}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({12, 14, 10}));
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({10, 10, 10}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({10, 10, 10}));
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({18}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({15}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({20}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({8}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({12, 8, 18}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor, from_value > to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 20;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 1;
|
||||
node->declare_parameter(name, std::vector<int64_t>({18, 20}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(), std::vector<int64_t>({18, 20}));
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({20, 18}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({20, 18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({18, 19, 20}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({20, 18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({10}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({20, 18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({25}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({20, 18}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor, from_value = to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 18;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 1;
|
||||
node->declare_parameter(name, std::vector<int64_t>({18}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(), std::vector<int64_t>({18}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({17}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({19}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor,
|
||||
// step > distance(from_value, to_value)
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 18;
|
||||
integer_range.to_value = 25;
|
||||
integer_range.step = 10;
|
||||
node->declare_parameter(name, std::vector<int64_t>({18, 25}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(), std::vector<int64_t>({18, 25}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({17}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({19}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({28}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor, distance not multiple of the step.
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 18;
|
||||
integer_range.to_value = 28;
|
||||
integer_range.step = 7;
|
||||
node->declare_parameter(name, std::vector<int64_t>({18, 25, 28}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(), std::vector<int64_t>({18, 25, 28}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({17}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25, 28}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({19}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25, 28}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({32}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25, 28}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor, step=0
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 10;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 0;
|
||||
node->declare_parameter(name, std::vector<int64_t>({10, 11, 12, 13, 14, 15, 16, 17, 18}),
|
||||
descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({10, 11, 12, 13, 14, 15, 16, 17, 18}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({9}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({10, 11, 12, 13, 14, 15, 16, 17, 18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({19}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({10, 11, 12, 13, 14, 15, 16, 17, 18}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor and wrong default value will throw
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 10;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 2;
|
||||
ASSERT_THROW(
|
||||
node->declare_parameter(name, std::vector<int64_t>({10, 11, 12, 13, 14, 15, 16, 17, 18}),
|
||||
descriptor),
|
||||
rclcpp::exceptions::InvalidParameterValueException);
|
||||
}
|
||||
{
|
||||
// setting a parameter with floating point range descriptor
|
||||
auto name = "parameter"_unq;
|
||||
@@ -1732,201 +1535,6 @@ TEST_F(TestNode, set_parameter_undeclared_parameters_not_allowed) {
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.999)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 0.2;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 10.4, 11.0, 10.8, 10.2, 10.6}),
|
||||
descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.4, 11.0, 10.8, 10.2, 10.6}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({10.3}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.4, 11.0, 10.8, 10.2, 10.6}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.0}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.4, 11.0, 10.8, 10.2, 10.6}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.4}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.4, 11.0, 10.8, 10.2, 10.6}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor, negative step
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = -0.2;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 10.2, 10.4, 10.6, 10.8, 11.0}),
|
||||
descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.2, 10.4, 10.6, 10.8, 11.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({10.3}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.2, 10.4, 10.6, 10.8, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.0}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.2, 10.4, 10.6, 10.8, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.4}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.2, 10.4, 10.6, 10.8, 11.0}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor, from_value > to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 11.0;
|
||||
floating_point_range.to_value = 10.0;
|
||||
floating_point_range.step = 0.2;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 11.0}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(), std::vector<double>({10.0, 11.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({10.2}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.0}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.4}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 11.0}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor, from_value = to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 10.0;
|
||||
floating_point_range.step = 0.2;
|
||||
node->declare_parameter(name, std::vector<double>({10.0}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(), std::vector<double>({10.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({11.2}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.0}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.4}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor, step > distance
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 2.2;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 11.0}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(), std::vector<double>({10.0, 11.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.2}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({7.8}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 11.0}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor,
|
||||
// distance not multiple of the step.
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 0.7;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 10.7, 11.0}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(), std::vector<double>({10.0, 10.7, 11.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.2}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.7, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({11.4}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.7, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.3}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.7, 11.0}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor, step=0
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 0.0;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 10.0001, 10.5479051, 11.0}),
|
||||
descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.0001, 10.5479051, 11.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({11.001}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.0001, 10.5479051, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.999}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.0001, 10.5479051, 11.0}));
|
||||
}
|
||||
{
|
||||
// setting a parameter with a different type is still possible
|
||||
// when having a descriptor specifying a type (type is a status, not a constraint).
|
||||
|
||||
@@ -173,12 +173,3 @@ TEST_F(TestRate, incorrect_constuctor) {
|
||||
rclcpp::Rate rate(rclcpp::Duration(-1, 0)),
|
||||
std::invalid_argument("period must be greater than 0"));
|
||||
}
|
||||
|
||||
TEST(TestRateBasic, invalid_context) {
|
||||
rclcpp::init(0, nullptr);
|
||||
rclcpp::Rate rate(1.0);
|
||||
ASSERT_TRUE(rate.sleep());
|
||||
rclcpp::shutdown();
|
||||
EXPECT_NO_THROW(rate.sleep());
|
||||
ASSERT_FALSE(rate.sleep());
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "rclcpp/experimental/buffers/ring_buffer_implementation.hpp"
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
* Construtctor
|
||||
*/
|
||||
TEST(TestRingBufferImplementation, constructor) {
|
||||
// Cannot create a buffer of size zero.
|
||||
@@ -140,31 +140,6 @@ TEST(TestRingBufferImplementation, basic_usage_unique_ptr) {
|
||||
EXPECT_EQ(false, rb.is_full());
|
||||
}
|
||||
|
||||
TEST(TestRingBufferImplementation, test_buffer_clear) {
|
||||
rclcpp::experimental::buffers::RingBufferImplementation<char> rb(2);
|
||||
rb.enqueue('a');
|
||||
rb.enqueue('b');
|
||||
|
||||
EXPECT_EQ(true, rb.has_data());
|
||||
EXPECT_EQ(true, rb.is_full());
|
||||
const auto all_data_vec = rb.get_all_data();
|
||||
EXPECT_EQ(2u, all_data_vec.capacity());
|
||||
EXPECT_EQ(2u, all_data_vec.size());
|
||||
rb.clear();
|
||||
EXPECT_EQ(false, rb.has_data());
|
||||
EXPECT_EQ(false, rb.is_full());
|
||||
const auto all_data_vec_empty = rb.get_all_data();
|
||||
EXPECT_EQ(0u, all_data_vec_empty.capacity());
|
||||
EXPECT_EQ(0u, all_data_vec_empty.size());
|
||||
rb.enqueue('c');
|
||||
rb.enqueue('d');
|
||||
const auto c = rb.dequeue();
|
||||
const auto d = rb.dequeue();
|
||||
|
||||
EXPECT_EQ('c', c);
|
||||
EXPECT_EQ('d', d);
|
||||
}
|
||||
|
||||
TEST(TestRingBufferImplementation, handle_nullptr_deletion) {
|
||||
rclcpp::experimental::buffers::RingBufferImplementation<std::unique_ptr<int>> rb(3);
|
||||
rb.enqueue(std::make_unique<int>(42));
|
||||
|
||||
@@ -386,20 +386,17 @@ TEST_F(TestService, server_qos_depth) {
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(server_node);
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
while ((server_cb_count_ < server_qos_profile.depth()) &&
|
||||
(std::chrono::steady_clock::now() - start) < 1s)
|
||||
{
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(server_node);
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
// Spin an extra time to check if server QoS depth has been ignored,
|
||||
// so more server responses might be processed than expected.
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(server_node);
|
||||
|
||||
EXPECT_EQ(server_cb_count_, server_qos_profile.depth());
|
||||
}
|
||||
|
||||
@@ -87,9 +87,6 @@ protected:
|
||||
|
||||
TEST_F(TestServiceIntrospection, service_introspection_nominal)
|
||||
{
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
|
||||
auto request = std::make_shared<BasicTypes::Request>();
|
||||
request->set__bool_value(true);
|
||||
request->set__int64_value(42);
|
||||
@@ -109,7 +106,7 @@ TEST_F(TestServiceIntrospection, service_introspection_nominal)
|
||||
auto future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future, timeout));
|
||||
rclcpp::spin_until_future_complete(node, future, timeout));
|
||||
|
||||
BasicTypes::Response::SharedPtr response = future.get();
|
||||
ASSERT_EQ(response->bool_value, false);
|
||||
@@ -118,7 +115,7 @@ TEST_F(TestServiceIntrospection, service_introspection_nominal)
|
||||
// wrap up work to get all the service_event messages
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
while (events.size() < 4 && (std::chrono::steady_clock::now() - start) < timeout) {
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
|
||||
std::map<uint8_t, std::shared_ptr<const BasicTypes::Event>> event_map;
|
||||
@@ -177,9 +174,6 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_events)
|
||||
service->configure_introspection(
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_OFF);
|
||||
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
|
||||
ASSERT_EQ(sub->get_publisher_count(), 0);
|
||||
|
||||
auto request = std::make_shared<BasicTypes::Request>();
|
||||
@@ -188,10 +182,10 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_events)
|
||||
auto future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future, timeout));
|
||||
rclcpp::spin_until_future_complete(node, future, timeout));
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
while ((std::chrono::steady_clock::now() - start) < timeout) {
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
EXPECT_EQ(events.size(), 0U);
|
||||
|
||||
@@ -212,10 +206,10 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_events)
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future, timeout));
|
||||
rclcpp::spin_until_future_complete(node, future, timeout));
|
||||
start = std::chrono::steady_clock::now();
|
||||
while (events.size() < 2 && (std::chrono::steady_clock::now() - start) < timeout) {
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
EXPECT_EQ(events.size(), 2U);
|
||||
|
||||
@@ -236,10 +230,10 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_events)
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future, timeout));
|
||||
rclcpp::spin_until_future_complete(node, future, timeout));
|
||||
start = std::chrono::steady_clock::now();
|
||||
while (events.size() < 2 && (std::chrono::steady_clock::now() - start) < timeout) {
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
EXPECT_EQ(events.size(), 2U);
|
||||
|
||||
@@ -260,10 +254,10 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_events)
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future, timeout));
|
||||
rclcpp::spin_until_future_complete(node, future, timeout));
|
||||
start = std::chrono::steady_clock::now();
|
||||
while (events.size() < 4 && (std::chrono::steady_clock::now() - start) < timeout) {
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
EXPECT_EQ(events.size(), 4U);
|
||||
}
|
||||
@@ -275,9 +269,6 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_event_cont
|
||||
service->configure_introspection(
|
||||
node->get_clock(), rclcpp::ServicesQoS(), RCL_SERVICE_INTROSPECTION_METADATA);
|
||||
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
|
||||
// Wait for the introspection to attach to our subscription
|
||||
size_t tries = 1000;
|
||||
while (this->sub->get_publisher_count() < 2 && tries-- > 0) {
|
||||
@@ -291,10 +282,10 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_event_cont
|
||||
auto future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future, timeout));
|
||||
rclcpp::spin_until_future_complete(node, future, timeout));
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
while (events.size() < 4 && (std::chrono::steady_clock::now() - start) < timeout) {
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
EXPECT_EQ(events.size(), 4U);
|
||||
for (const auto & event : events) {
|
||||
@@ -319,10 +310,10 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_event_cont
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future, timeout));
|
||||
rclcpp::spin_until_future_complete(node, future, timeout));
|
||||
start = std::chrono::steady_clock::now();
|
||||
while (events.size() < 4 && (std::chrono::steady_clock::now() - start) < timeout) {
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
EXPECT_EQ(events.size(), 4U);
|
||||
for (const auto & event : events) {
|
||||
@@ -359,10 +350,10 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_event_cont
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future, timeout));
|
||||
rclcpp::spin_until_future_complete(node, future, timeout));
|
||||
start = std::chrono::steady_clock::now();
|
||||
while (events.size() < 4 && (std::chrono::steady_clock::now() - start) < timeout) {
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
EXPECT_EQ(events.size(), 4U);
|
||||
for (const auto & event : events) {
|
||||
@@ -399,10 +390,10 @@ TEST_F(TestServiceIntrospection, service_introspection_enable_disable_event_cont
|
||||
future = client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future, timeout));
|
||||
rclcpp::spin_until_future_complete(node, future, timeout));
|
||||
start = std::chrono::steady_clock::now();
|
||||
while (events.size() < 4 && (std::chrono::steady_clock::now() - start) < timeout) {
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
EXPECT_EQ(events.size(), 4U);
|
||||
for (const auto & event : events) {
|
||||
|
||||
@@ -69,13 +69,11 @@ public:
|
||||
{
|
||||
using clock = std::chrono::system_clock;
|
||||
auto start = clock::now();
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
while (!condition()) {
|
||||
if ((clock::now() - start) > timeout) {
|
||||
return false;
|
||||
}
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -158,15 +158,3 @@ TEST(TypesupportHelpersTest, test_throw_exception_with_invalid_type) {
|
||||
rclcpp::get_action_typesupport_handle(invalid_type, "rosidl_typesupport_cpp", *library),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(TypesupportHelpersTest, throws_exception_if_filetype_has_multiple_slashes_at_start) {
|
||||
EXPECT_ANY_THROW(rclcpp::extract_type_identifier("//name_with_slashes_at_start"));
|
||||
}
|
||||
|
||||
TEST(TypesupportHelpersTestV3, ProcessesValidTypeWithWhitespace) {
|
||||
std::string package, middle, name;
|
||||
std::tie(package, middle, name) = rclcpp::extract_type_identifier(" package/ name ");
|
||||
EXPECT_EQ(package, "package");
|
||||
EXPECT_TRUE(middle.empty());
|
||||
EXPECT_EQ(name, "name");
|
||||
}
|
||||
|
||||
@@ -134,3 +134,32 @@ TEST(TestUtilities, wait_for_last_message) {
|
||||
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
TEST(TestUtilities, wait_for_message_custom_context) {
|
||||
auto context = std::make_shared<rclcpp::Context>();
|
||||
context->init(0, nullptr);
|
||||
|
||||
auto node_opt = rclcpp::NodeOptions().context(context);
|
||||
auto node = std::make_shared<rclcpp::Node>("wait_for_message_custom_context_node", node_opt);
|
||||
|
||||
using MsgT = test_msgs::msg::Strings;
|
||||
auto pub = node->create_publisher<MsgT>("wait_for_message_topic", 10);
|
||||
|
||||
MsgT out;
|
||||
auto received = false;
|
||||
auto wait = std::async(
|
||||
[&]() {
|
||||
auto ret = rclcpp::wait_for_message(out, node, "wait_for_message_topic", 5s);
|
||||
EXPECT_TRUE(ret);
|
||||
received = true;
|
||||
});
|
||||
|
||||
for (auto i = 0u; i < 10 && received == false; ++i) {
|
||||
pub->publish(*get_messages_strings()[0]);
|
||||
std::this_thread::sleep_for(1s);
|
||||
}
|
||||
ASSERT_TRUE(received);
|
||||
EXPECT_EQ(out, *get_messages_strings()[0]);
|
||||
|
||||
context->shutdown("test complete");
|
||||
}
|
||||
|
||||
@@ -3,33 +3,37 @@ Changelog for package rclcpp_action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
30.1.2 (2025-10-21)
|
||||
29.5.7 (2026-02-09)
|
||||
-------------------
|
||||
* it misses the iterator second to lock the weakptr. (`#2958 <https://github.com/ros2/rclcpp/issues/2958>`_)
|
||||
* try aborting before canceling 1st on dtor of ServerGoalHandle. (`#2953 <https://github.com/ros2/rclcpp/issues/2953>`_)
|
||||
* Contributors: Tomoya Fujita
|
||||
* Update exception documentation for goal cancellation in ServerGoalHandle (`#3019 <https://github.com/ros2/rclcpp/issues/3019>`_) (`#3022 <https://github.com/ros2/rclcpp/issues/3022>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
30.1.1 (2025-09-11)
|
||||
-------------------
|
||||
* deprecate rclcpp::spin_some and rclcpp::spin_all (`#2848 <https://github.com/ros2/rclcpp/issues/2848>`_)
|
||||
* Contributors: Alberto Soragna
|
||||
|
||||
30.1.0 (2025-07-29)
|
||||
-------------------
|
||||
* fix cmake deprecation (`#2914 <https://github.com/ros2/rclcpp/issues/2914>`_)
|
||||
* Contributors: mosfet80
|
||||
|
||||
30.0.0 (2025-07-01)
|
||||
29.5.6 (2025-12-23)
|
||||
-------------------
|
||||
|
||||
29.6.1 (2025-06-23)
|
||||
29.5.5 (2025-11-18)
|
||||
-------------------
|
||||
* Replace std::default_random_engine with std::mt19937 (rolling) (`#2843 <https://github.com/ros2/rclcpp/issues/2843>`_)
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, keeponoiro
|
||||
* Fix REP url locations (`#2987 <https://github.com/ros2/rclcpp/issues/2987>`_) (`#2989 <https://github.com/ros2/rclcpp/issues/2989>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.6.0 (2025-04-25)
|
||||
29.5.4 (2025-10-21)
|
||||
-------------------
|
||||
* it misses the iterator second to lock the weakptr. (`#2958 <https://github.com/ros2/rclcpp/issues/2958>`_) (`#2959 <https://github.com/ros2/rclcpp/issues/2959>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.3 (2025-09-11)
|
||||
-------------------
|
||||
* fix cmake deprecation (`#2914 <https://github.com/ros2/rclcpp/issues/2914>`_) (`#2915 <https://github.com/ros2/rclcpp/issues/2915>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.2 (2025-07-07)
|
||||
-------------------
|
||||
|
||||
29.5.1 (2025-06-23)
|
||||
-------------------
|
||||
* Replace std::default_random_engine with std::mt19937 (rolling) (`#2843 <https://github.com/ros2/rclcpp/issues/2843>`_) (`#2866 <https://github.com/ros2/rclcpp/issues/2866>`_)
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.0 (2025-04-18)
|
||||
-------------------
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
This document is a declaration of software quality for the `rclcpp_action` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
This document is a declaration of software quality for the `rclcpp_action` package, based on the guidelines in [REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
|
||||
# rclcpp_action Quality Declaration
|
||||
|
||||
The package `rclcpp_action` claims to be in the **Quality Level 1** category when it is used with a **Quality Level 1** middleware.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
|
||||
## Version Policy [1]
|
||||
|
||||
@@ -53,7 +53,7 @@ All pull requests will be peer-reviewed, check [ROS 2 Developer Guide](https://d
|
||||
|
||||
### Continuous Integration [2.iv]
|
||||
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://www.ros.org/reps/rep-2000.html#support-tiers)
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://reps.openrobotics.org/rep-2000/#support-tiers)
|
||||
|
||||
Currently nightly results can be seen here:
|
||||
|
||||
@@ -179,7 +179,7 @@ It is **Quality Level 1**, see its [Quality Declaration document](https://github
|
||||
|
||||
## Platform Support [6]
|
||||
|
||||
`rclcpp_action` supports all of the tier 1 platforms as described in [REP-2000](https://www.ros.org/reps/rep-2000.html#support-tiers), and tests each change against all of them.
|
||||
`rclcpp_action` supports all of the tier 1 platforms as described in [REP-2000](https://reps.openrobotics.org/rep-2000/#support-tiers), and tests each change against all of them.
|
||||
|
||||
Currently nightly build status can be seen here:
|
||||
* [linux-aarch64_release](https://ci.ros2.org/view/nightly/job/nightly_linux-aarch64_release/lastBuild/rclcpp_action/)
|
||||
@@ -191,4 +191,4 @@ Currently nightly build status can be seen here:
|
||||
|
||||
### Vulnerability Disclosure Policy [7.i]
|
||||
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://www.ros.org/reps/rep-2006.html).
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://reps.openrobotics.org/rep-2006/).
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
#include "action_msgs/msg/goal_status.hpp"
|
||||
|
||||
#include "rclcpp/logging.hpp"
|
||||
|
||||
#include "rclcpp_action/visibility_control.hpp"
|
||||
#include "rclcpp_action/types.hpp"
|
||||
|
||||
@@ -105,19 +103,11 @@ protected:
|
||||
_execute();
|
||||
|
||||
/// Transition the goal to canceled state if it never reached a terminal state.
|
||||
/// Returns true if transitioned to canceled, else false.
|
||||
/// \internal
|
||||
RCLCPP_ACTION_PUBLIC
|
||||
bool
|
||||
try_canceling() noexcept;
|
||||
|
||||
/// Transition the goal to aborted state if it never reached a terminal state.
|
||||
/// Returns true if transitioned to aborted, else false.
|
||||
/// \internal
|
||||
RCLCPP_ACTION_PUBLIC
|
||||
bool
|
||||
try_aborting() noexcept;
|
||||
|
||||
// End API for communication between ServerGoalHandleBase and ServerGoalHandle<>
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -210,7 +200,7 @@ public:
|
||||
* This is a terminal state, no more methods should be called on a goal handle after this is
|
||||
* called.
|
||||
*
|
||||
* \throws rclcpp::exceptions::RCLError If the goal is in any state besides executing.
|
||||
* \throws rclcpp::exceptions::RCLError If a cancel request for this goal has not been received.
|
||||
*
|
||||
* \param[in] result_msg the final result to send to clients.
|
||||
*/
|
||||
@@ -253,22 +243,11 @@ public:
|
||||
|
||||
virtual ~ServerGoalHandle()
|
||||
{
|
||||
try {
|
||||
// Abort goal if handle was allowed to destruct without reaching a terminal state
|
||||
if (try_aborting()) {
|
||||
auto null_result = std::make_shared<typename ActionT::Impl::GetResultService::Response>();
|
||||
null_result->status = action_msgs::msg::GoalStatus::STATUS_ABORTED;
|
||||
on_terminal_state_(uuid_, null_result);
|
||||
} else if (try_canceling()) {
|
||||
// Cancel goal if handle was allowed to destruct without reaching a terminal state
|
||||
auto null_result = std::make_shared<typename ActionT::Impl::GetResultService::Response>();
|
||||
null_result->status = action_msgs::msg::GoalStatus::STATUS_CANCELED;
|
||||
on_terminal_state_(uuid_, null_result);
|
||||
}
|
||||
} catch (const std::exception & ex) {
|
||||
RCLCPP_DEBUG(
|
||||
rclcpp::get_logger("rclcpp_action"),
|
||||
"Failed to abort/cancel goal handler in destructor: %s", ex.what());
|
||||
// Cancel goal if handle was allowed to destruct without reaching a terminal state
|
||||
if (try_canceling()) {
|
||||
auto null_result = std::make_shared<typename ActionT::Impl::GetResultService::Response>();
|
||||
null_result->status = action_msgs::msg::GoalStatus::STATUS_CANCELED;
|
||||
on_terminal_state_(uuid_, null_result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>30.1.2</version>
|
||||
<version>29.5.7</version>
|
||||
<description>Adds action APIs for C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include "rcl_action/action_server.h"
|
||||
#include "rcl_action/goal_handle.h"
|
||||
@@ -136,24 +135,6 @@ ServerGoalHandleBase::try_canceling() noexcept
|
||||
return RCL_RET_OK == ret;
|
||||
}
|
||||
|
||||
return is_cancelable;
|
||||
}
|
||||
|
||||
bool
|
||||
ServerGoalHandleBase::try_aborting() noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(rcl_handle_mutex_);
|
||||
rcl_ret_t ret;
|
||||
// Check if the goal is abortable
|
||||
const bool is_abortable = rcl_action_goal_handle_is_abortable(rcl_handle_.get());
|
||||
if (is_abortable) {
|
||||
// Transition to ABORTED
|
||||
ret = rcl_action_update_goal_state(rcl_handle_.get(), GOAL_EVENT_ABORT);
|
||||
if (RCL_RET_OK != ret) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return is_abortable;
|
||||
return false;
|
||||
}
|
||||
} // namespace rclcpp_action
|
||||
|
||||
@@ -518,11 +518,9 @@ TEST_F(TestServer, publish_status_accepted)
|
||||
|
||||
// 10 seconds
|
||||
const size_t max_tries = 10 * 1000 / 100;
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
for (size_t retry = 0; retry < max_tries && received_msgs.size() != 1u; ++retry) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
|
||||
ASSERT_LT(0u, received_msgs.size());
|
||||
@@ -584,11 +582,9 @@ TEST_F(TestServer, publish_status_canceling)
|
||||
|
||||
// 10 seconds
|
||||
const size_t max_tries = 10 * 1000 / 100;
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
for (size_t retry = 0; retry < max_tries && received_msgs.size() < 2u; ++retry) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
|
||||
ASSERT_LT(0u, received_msgs.size());
|
||||
@@ -644,12 +640,10 @@ TEST_F(TestServer, publish_status_canceled)
|
||||
received_handle->canceled(std::make_shared<Fibonacci::Result>());
|
||||
|
||||
// 10 seconds
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
const size_t max_tries = 10 * 1000 / 100;
|
||||
for (size_t retry = 0; retry < max_tries && received_msgs.size() < 3u; ++retry) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
|
||||
ASSERT_LT(0u, received_msgs.size());
|
||||
@@ -703,12 +697,10 @@ TEST_F(TestServer, publish_status_succeeded)
|
||||
received_handle->succeed(std::make_shared<Fibonacci::Result>());
|
||||
|
||||
// 10 seconds
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
const size_t max_tries = 10 * 1000 / 100;
|
||||
for (size_t retry = 0; retry < max_tries && received_msgs.size() < 2u; ++retry) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
|
||||
ASSERT_LT(0u, received_msgs.size());
|
||||
@@ -762,12 +754,10 @@ TEST_F(TestServer, publish_status_aborted)
|
||||
received_handle->abort(std::make_shared<Fibonacci::Result>());
|
||||
|
||||
// 10 seconds
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
const size_t max_tries = 10 * 1000 / 100;
|
||||
for (size_t retry = 0; retry < max_tries && received_msgs.size() < 2u; ++retry) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
|
||||
ASSERT_LT(0u, received_msgs.size());
|
||||
@@ -824,12 +814,10 @@ TEST_F(TestServer, publish_feedback)
|
||||
received_handle->publish_feedback(sent_message);
|
||||
|
||||
// 10 seconds
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
const size_t max_tries = 10 * 1000 / 100;
|
||||
for (size_t retry = 0; retry < max_tries && received_msgs.size() < 1u; ++retry) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
}
|
||||
|
||||
ASSERT_EQ(1u, received_msgs.size());
|
||||
@@ -890,13 +878,10 @@ TEST_F(TestServer, get_result)
|
||||
result->sequence = {5, 8, 13, 21};
|
||||
received_handle->succeed(result);
|
||||
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
|
||||
// Wait for the result request to be received
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future));
|
||||
rclcpp::spin_until_future_complete(node, future));
|
||||
|
||||
auto response = future.get();
|
||||
EXPECT_EQ(action_msgs::msg::GoalStatus::STATUS_SUCCEEDED, response->status);
|
||||
@@ -906,13 +891,13 @@ TEST_F(TestServer, get_result)
|
||||
rclcpp::sleep_for(2 * result_timeout);
|
||||
|
||||
// Allow for expiration to take place
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
|
||||
// Send and wait for another result request
|
||||
future = result_client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future));
|
||||
rclcpp::spin_until_future_complete(node, future));
|
||||
|
||||
response = future.get();
|
||||
EXPECT_EQ(action_msgs::msg::GoalStatus::STATUS_UNKNOWN, response->status);
|
||||
@@ -961,12 +946,9 @@ TEST_F(TestServer, get_result_deferred)
|
||||
request->goal_id.uuid = uuid;
|
||||
auto future = result_client->async_send_request(request);
|
||||
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node);
|
||||
|
||||
// Process request first
|
||||
rclcpp::sleep_for(std::chrono::milliseconds(10)); // Give a chance for the request to be served
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node);
|
||||
|
||||
// Send a result
|
||||
auto result = std::make_shared<Fibonacci::Result>();
|
||||
@@ -976,7 +958,7 @@ TEST_F(TestServer, get_result_deferred)
|
||||
// Wait for the result request to be received
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future));
|
||||
rclcpp::spin_until_future_complete(node, future));
|
||||
|
||||
auto response = future.get();
|
||||
EXPECT_EQ(action_msgs::msg::GoalStatus::STATUS_SUCCEEDED, response->status);
|
||||
@@ -1060,13 +1042,10 @@ public:
|
||||
result->sequence = {5, 8, 13, 21};
|
||||
goal_handle_->succeed(result);
|
||||
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(node_);
|
||||
|
||||
// Wait for the result request to be received
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future));
|
||||
rclcpp::spin_until_future_complete(node_, future));
|
||||
|
||||
auto response = future.get();
|
||||
EXPECT_EQ(action_msgs::msg::GoalStatus::STATUS_SUCCEEDED, response->status);
|
||||
@@ -1076,13 +1055,13 @@ public:
|
||||
rclcpp::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
// Allow for expiration to take place
|
||||
executor.spin_some();
|
||||
rclcpp::spin_some(node_);
|
||||
|
||||
// Send and wait for another result request
|
||||
future = result_client->async_send_request(request);
|
||||
ASSERT_EQ(
|
||||
rclcpp::FutureReturnCode::SUCCESS,
|
||||
executor.spin_until_future_complete(future));
|
||||
rclcpp::spin_until_future_complete(node_, future));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -44,8 +44,6 @@ public:
|
||||
|
||||
bool try_cancel() {return try_canceling();}
|
||||
|
||||
bool try_abort() {return try_aborting();}
|
||||
|
||||
void cancel_goal() {_cancel_goal();}
|
||||
};
|
||||
|
||||
@@ -134,20 +132,6 @@ TEST_F(TestServerGoalHandle, abort) {
|
||||
EXPECT_THROW(handle_->abort(result), rclcpp::exceptions::RCLError);
|
||||
}
|
||||
|
||||
TEST_F(TestServerGoalHandle, try_abort) {
|
||||
handle_->execute();
|
||||
test_msgs::action::Fibonacci::Result::SharedPtr result =
|
||||
std::make_shared<test_msgs::action::Fibonacci::Result>();
|
||||
EXPECT_TRUE(handle_->try_abort());
|
||||
EXPECT_FALSE(handle_->is_canceling());
|
||||
EXPECT_FALSE(handle_->is_active());
|
||||
EXPECT_FALSE(handle_->is_executing());
|
||||
|
||||
auto mock = mocking_utils::patch_and_return(
|
||||
"lib:rclcpp_action", rcl_action_update_goal_state, RCL_RET_ERROR);
|
||||
EXPECT_THROW(handle_->abort(result), rclcpp::exceptions::RCLError);
|
||||
}
|
||||
|
||||
TEST_F(TestServerGoalHandle, succeed) {
|
||||
handle_->execute();
|
||||
test_msgs::action::Fibonacci::Result::SharedPtr result =
|
||||
|
||||
@@ -2,34 +2,33 @@
|
||||
Changelog for package rclcpp_components
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
30.1.2 (2025-10-21)
|
||||
29.5.7 (2026-02-09)
|
||||
-------------------
|
||||
|
||||
30.1.1 (2025-09-11)
|
||||
29.5.6 (2025-12-23)
|
||||
-------------------
|
||||
* Cleanup the dependencies in rclcpp_components. (`#2918 <https://github.com/ros2/rclcpp/issues/2918>`_)
|
||||
* Contributors: Chris Lalancette
|
||||
|
||||
30.1.0 (2025-07-29)
|
||||
29.5.5 (2025-11-18)
|
||||
-------------------
|
||||
* fix cmake deprecation (`#2914 <https://github.com/ros2/rclcpp/issues/2914>`_)
|
||||
* Contributors: mosfet80
|
||||
* Fix REP url locations (`#2987 <https://github.com/ros2/rclcpp/issues/2987>`_) (`#2989 <https://github.com/ros2/rclcpp/issues/2989>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
30.0.0 (2025-07-01)
|
||||
29.5.4 (2025-10-21)
|
||||
-------------------
|
||||
* NEW PR: Add component_container for EventsExecutor (`#2885 <https://github.com/ros2/rclcpp/issues/2885>`_)
|
||||
* make sure that plugin arg includes the double colon. (`#2878 <https://github.com/ros2/rclcpp/issues/2878>`_)
|
||||
* Contributors: Mihir Rao, Tomoya Fujita
|
||||
|
||||
29.6.1 (2025-06-23)
|
||||
29.5.3 (2025-09-11)
|
||||
-------------------
|
||||
* set thread names by node in component container isolated (`#2871 <https://github.com/ros2/rclcpp/issues/2871>`_)
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_)
|
||||
* Contributors: Adam Aposhian, Alejandro Hernández Cordero
|
||||
* fix cmake deprecation (`#2914 <https://github.com/ros2/rclcpp/issues/2914>`_) (`#2915 <https://github.com/ros2/rclcpp/issues/2915>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.6.0 (2025-04-25)
|
||||
29.5.2 (2025-07-07)
|
||||
-------------------
|
||||
|
||||
29.5.1 (2025-06-23)
|
||||
-------------------
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.0 (2025-04-18)
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -19,9 +19,7 @@ find_package(ament_index_cpp REQUIRED)
|
||||
find_package(class_loader REQUIRED)
|
||||
find_package(composition_interfaces REQUIRED)
|
||||
find_package(rclcpp REQUIRED)
|
||||
find_package(rcl_interfaces REQUIRED)
|
||||
find_package(rcpputils REQUIRED)
|
||||
find_package(rmw REQUIRED)
|
||||
|
||||
# Add an interface library that can be depended upon by libraries who register components
|
||||
add_library(component INTERFACE)
|
||||
@@ -41,15 +39,13 @@ target_include_directories(component_manager PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")
|
||||
target_link_libraries(component_manager PUBLIC
|
||||
class_loader::class_loader
|
||||
${composition_interfaces_TARGETS}
|
||||
rclcpp::rclcpp
|
||||
rmw::rmw
|
||||
)
|
||||
target_link_libraries(component_manager PRIVATE
|
||||
ament_index_cpp::ament_index_cpp
|
||||
class_loader::class_loader
|
||||
rcpputils::rcpputils
|
||||
${rcl_interfaces_TARGETS}
|
||||
)
|
||||
target_compile_definitions(component_manager
|
||||
PRIVATE "RCLCPP_COMPONENTS_BUILDING_LIBRARY")
|
||||
@@ -58,13 +54,7 @@ add_executable(
|
||||
component_container
|
||||
src/component_container.cpp
|
||||
)
|
||||
target_link_libraries(component_container PRIVATE component_manager rclcpp::rclcpp)
|
||||
|
||||
add_executable(
|
||||
component_container_event
|
||||
src/component_container_event.cpp
|
||||
)
|
||||
target_link_libraries(component_container_event PRIVATE component_manager rclcpp::rclcpp)
|
||||
target_link_libraries(component_container component_manager rclcpp::rclcpp)
|
||||
|
||||
set(node_main_template_install_dir "share/${PROJECT_NAME}")
|
||||
install(FILES
|
||||
@@ -75,13 +65,19 @@ add_executable(
|
||||
component_container_mt
|
||||
src/component_container_mt.cpp
|
||||
)
|
||||
target_link_libraries(component_container_mt PRIVATE component_manager rclcpp::rclcpp)
|
||||
target_link_libraries(component_container_mt component_manager rclcpp::rclcpp)
|
||||
|
||||
add_executable(
|
||||
component_container_isolated
|
||||
src/component_container_isolated.cpp
|
||||
)
|
||||
target_link_libraries(component_container_isolated PRIVATE component_manager rclcpp::rclcpp)
|
||||
target_link_libraries(component_container_isolated component_manager rclcpp::rclcpp)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_libraries(component_container "stdc++fs")
|
||||
target_link_libraries(component_container_mt "stdc++fs")
|
||||
target_link_libraries(component_container_isolated "stdc++fs")
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
find_package(ament_lint_auto REQUIRED)
|
||||
@@ -149,7 +145,7 @@ install(
|
||||
|
||||
# Install executables
|
||||
install(
|
||||
TARGETS component_container component_container_mt component_container_isolated component_container_event
|
||||
TARGETS component_container component_container_mt component_container_isolated
|
||||
RUNTIME DESTINATION lib/${PROJECT_NAME}
|
||||
)
|
||||
|
||||
@@ -172,5 +168,9 @@ ament_export_libraries(component_manager)
|
||||
# Export modern CMake targets
|
||||
ament_export_targets(export_${PROJECT_NAME})
|
||||
|
||||
ament_export_dependencies(class_loader composition_interfaces rclcpp rcpputils rmw)
|
||||
# specific order: dependents before dependencies
|
||||
ament_export_dependencies(ament_index_cpp)
|
||||
ament_export_dependencies(class_loader)
|
||||
ament_export_dependencies(composition_interfaces)
|
||||
ament_export_dependencies(rclcpp)
|
||||
ament_package(CONFIG_EXTRAS rclcpp_components-extras.cmake.in)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
This document is a declaration of software quality for the `rclcpp_components` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
This document is a declaration of software quality for the `rclcpp_components` package, based on the guidelines in [REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
|
||||
# rclcpp_components Quality Declaration
|
||||
|
||||
The package `rclcpp_components` claims to be in the **Quality Level 1** category.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
|
||||
## Version Policy [1]
|
||||
|
||||
@@ -53,7 +53,7 @@ All pull requests will be peer-reviewed, check [ROS 2 Developer Guide](https://d
|
||||
|
||||
### Continuous Integration [2.iv]
|
||||
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://www.ros.org/reps/rep-2000.html#support-tiers)
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://reps.openrobotics.org/rep-2000/#support-tiers)
|
||||
|
||||
Currently nightly results can be seen here:
|
||||
|
||||
@@ -191,7 +191,7 @@ It is **Quality Level 1**, see its [Quality Declaration document](https://github
|
||||
|
||||
## Platform Support [6]
|
||||
|
||||
`rclcpp_components` supports all of the tier 1 platforms as described in [REP-2000](https://www.ros.org/reps/rep-2000.html#support-tiers), and tests each change against all of them.
|
||||
`rclcpp_components` supports all of the tier 1 platforms as described in [REP-2000](https://reps.openrobotics.org/rep-2000/#support-tiers), and tests each change against all of them.
|
||||
|
||||
Currently nightly build status can be seen here:
|
||||
* [linux-aarch64_release](https://ci.ros2.org/view/nightly/job/nightly_linux-aarch64_release/lastBuild/rclcpp_components/)
|
||||
@@ -203,4 +203,4 @@ Currently nightly build status can be seen here:
|
||||
|
||||
### Vulnerability Disclosure Policy [7.i]
|
||||
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://www.ros.org/reps/rep-2006.html).
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://reps.openrobotics.org/rep-2006/).
|
||||
|
||||
@@ -57,9 +57,6 @@ macro(rclcpp_components_register_node target)
|
||||
message(STATUS "Setting executor non-default value ${executor}")
|
||||
endif()
|
||||
|
||||
if("${ARGS_PLUGIN}" MATCHES "^[^:]+:[^:]+$")
|
||||
message(FATAL_ERROR "PLUGIN argument '${ARGS_PLUGIN}' appears to be incorrect. (e.g., 'package_name::ClassName').")
|
||||
endif()
|
||||
set(component ${ARGS_PLUGIN})
|
||||
set(node ${ARGS_EXECUTABLE})
|
||||
_rclcpp_components_register_package_hook()
|
||||
|
||||
@@ -43,13 +43,10 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "class_loader/class_loader.hpp"
|
||||
|
||||
#include "composition_interfaces/srv/load_node.hpp"
|
||||
#include "composition_interfaces/srv/unload_node.hpp"
|
||||
#include "composition_interfaces/srv/list_nodes.hpp"
|
||||
@@ -59,10 +56,12 @@
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
#include "rclcpp_components/node_factory.hpp"
|
||||
#include "rclcpp_components/node_instance_wrapper.hpp"
|
||||
#include "rclcpp_components/visibility_control.hpp"
|
||||
|
||||
#include "rmw/types.h"
|
||||
namespace class_loader
|
||||
{
|
||||
class ClassLoader;
|
||||
} // namespace class_loader
|
||||
|
||||
namespace rclcpp_components
|
||||
{
|
||||
|
||||
@@ -16,22 +16,15 @@
|
||||
#ifndef RCLCPP_COMPONENTS__COMPONENT_MANAGER_ISOLATED_HPP__
|
||||
#define RCLCPP_COMPONENTS__COMPONENT_MANAGER_ISOLATED_HPP__
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <system_error>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "rclcpp/executor.hpp"
|
||||
#include "rclcpp/executors/single_threaded_executor.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp_components/component_manager.hpp"
|
||||
#include "rcpputils/thread_name.hpp"
|
||||
|
||||
|
||||
namespace rclcpp_components
|
||||
{
|
||||
@@ -84,16 +77,8 @@ protected:
|
||||
DedicatedExecutorWrapper & wrapper = result.first->second;
|
||||
wrapper.executor = exec;
|
||||
auto & thread_initialized = wrapper.thread_initialized;
|
||||
auto name = node_wrappers_[node_id].get_node_base_interface()->get_name();
|
||||
// Copy name so that it doesn't deallocate before the thread is started
|
||||
wrapper.thread = std::thread(
|
||||
[exec, &thread_initialized, name]() {
|
||||
try {
|
||||
rcpputils::set_thread_name(name);
|
||||
} catch (const std::system_error & e) {
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to set thread name: %s (%s)", e.what(),
|
||||
e.code().message().c_str());
|
||||
}
|
||||
[exec, &thread_initialized]() {
|
||||
thread_initialized = true;
|
||||
exec->spin();
|
||||
});
|
||||
|
||||
@@ -18,10 +18,7 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/node_options.hpp"
|
||||
|
||||
#include "rclcpp_components/node_factory.hpp"
|
||||
#include "rclcpp_components/node_instance_wrapper.hpp"
|
||||
|
||||
namespace rclcpp_components
|
||||
{
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define RCLCPP_COMPONENTS__REGISTER_NODE_MACRO_HPP__
|
||||
|
||||
#include "class_loader/class_loader.hpp"
|
||||
#include "rclcpp_components/node_factory.hpp"
|
||||
#include "rclcpp_components/node_factory_template.hpp"
|
||||
|
||||
/// Register a component that can be dynamically loaded at runtime.
|
||||
|
||||
@@ -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>30.1.2</version>
|
||||
<version>29.5.7</version>
|
||||
<description>Package containing tools for dynamically loadable components</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
@@ -16,32 +16,23 @@
|
||||
|
||||
<buildtool_depend>ament_cmake_ros</buildtool_depend>
|
||||
|
||||
<build_export_depend>class_loader</build_export_depend>
|
||||
<build_export_depend>composition_interfaces</build_export_depend>
|
||||
<build_export_depend>rclcpp</build_export_depend>
|
||||
<build_export_depend>rcpputils</build_export_depend>
|
||||
<build_export_depend>rmw</build_export_depend>
|
||||
|
||||
<build_depend>ament_index_cpp</build_depend>
|
||||
<build_depend>class_loader</build_depend>
|
||||
<build_depend>composition_interfaces</build_depend>
|
||||
<build_depend>rclcpp</build_depend>
|
||||
<build_depend>rcl_interfaces</build_depend>
|
||||
<build_depend>rcpputils</build_depend>
|
||||
<build_depend>rmw</build_depend>
|
||||
|
||||
<exec_depend>ament_index_cpp</exec_depend>
|
||||
<exec_depend>class_loader</exec_depend>
|
||||
<exec_depend>composition_interfaces</exec_depend>
|
||||
<exec_depend>rclcpp</exec_depend>
|
||||
<exec_depend>rcl_interfaces</exec_depend>
|
||||
<exec_depend>rcpputils</exec_depend>
|
||||
<exec_depend>rmw</exec_depend>
|
||||
|
||||
<test_depend>ament_cmake_google_benchmark</test_depend>
|
||||
<test_depend>ament_cmake_gtest</test_depend>
|
||||
<test_depend>ament_lint_auto</test_depend>
|
||||
<test_depend>ament_lint_common</test_depend>
|
||||
<test_depend>launch_testing</test_depend>
|
||||
<test_depend>std_msgs</test_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_cmake</build_type>
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/executors/single_threaded_executor.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
#include "rclcpp_components/component_manager.hpp"
|
||||
|
||||
@@ -27,6 +26,4 @@ int main(int argc, char * argv[])
|
||||
auto node = std::make_shared<rclcpp_components::ComponentManager>(exec);
|
||||
exec->add_node(node);
|
||||
exec->spin();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright 2025 Open Source Robotics Foundation, Inc.Add commentMore actions
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.Add commentMore actions
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp/experimental/executors/events_executor/events_executor.hpp"
|
||||
|
||||
#include "rclcpp_components/component_manager.hpp"
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
/// Component container with an events executor.
|
||||
rclcpp::init(argc, argv);
|
||||
auto exec = std::make_shared<rclcpp::experimental::executors::EventsExecutor>();
|
||||
auto node = std::make_shared<rclcpp_components::ComponentManager>(exec);
|
||||
exec->add_node(node);
|
||||
exec->spin();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -16,10 +16,8 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/executors/single_threaded_executor.hpp"
|
||||
#include "rclcpp/executors/multi_threaded_executor.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
|
||||
#include "rclcpp_components/component_manager_isolated.hpp"
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
@@ -48,6 +46,4 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
exec->add_node(node);
|
||||
exec->spin();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/executors/multi_threaded_executor.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
#include "rclcpp_components/component_manager.hpp"
|
||||
|
||||
@@ -36,6 +35,4 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
exec->add_node(node);
|
||||
exec->spin();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -17,29 +17,15 @@
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "ament_index_cpp/get_resource.hpp"
|
||||
|
||||
#include "class_loader/class_loader.hpp"
|
||||
|
||||
#include "rclcpp/node_options.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
|
||||
#include "rclcpp_components/node_factory.hpp"
|
||||
|
||||
#include "rcl_interfaces/msg/parameter_descriptor.hpp"
|
||||
#include "rcl_interfaces/msg/integer_range.hpp"
|
||||
|
||||
#include "rcpputils/filesystem_helper.hpp"
|
||||
#include "rcpputils/split.hpp"
|
||||
|
||||
#include "rmw/types.h"
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
namespace rclcpp_components
|
||||
|
||||
@@ -3,33 +3,35 @@ Changelog for package rclcpp_lifecycle
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
30.1.2 (2025-10-21)
|
||||
29.5.7 (2026-02-09)
|
||||
-------------------
|
||||
|
||||
30.1.1 (2025-09-11)
|
||||
-------------------
|
||||
* deprecate rclcpp::spin_some and rclcpp::spin_all (`#2848 <https://github.com/ros2/rclcpp/issues/2848>`_)
|
||||
* Clearer warning message, the old one lacked information and was perhaps misleading (`#2927 <https://github.com/ros2/rclcpp/issues/2927>`_)
|
||||
* Contributors: Alberto Soragna, Peter Mitrano (AR)
|
||||
|
||||
30.1.0 (2025-07-29)
|
||||
-------------------
|
||||
* fix cmake deprecation (`#2914 <https://github.com/ros2/rclcpp/issues/2914>`_)
|
||||
cmake version < then 3.10 is deprecated
|
||||
* Contributors: mosfet80
|
||||
|
||||
30.0.0 (2025-07-01)
|
||||
29.5.6 (2025-12-23)
|
||||
-------------------
|
||||
|
||||
29.6.1 (2025-06-23)
|
||||
29.5.5 (2025-11-18)
|
||||
-------------------
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_)
|
||||
* introduce rcl_lifecycle_get_transition_label_by_id(). (`#2827 <https://github.com/ros2/rclcpp/issues/2827>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Tomoya Fujita
|
||||
* Fix REP url locations (`#2987 <https://github.com/ros2/rclcpp/issues/2987>`_) (`#2989 <https://github.com/ros2/rclcpp/issues/2989>`_)
|
||||
* Add get_parameter_or overload returning value or alternative (`#2973 <https://github.com/ros2/rclcpp/issues/2973>`_) (`#2976 <https://github.com/ros2/rclcpp/issues/2976>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.6.0 (2025-04-25)
|
||||
29.5.4 (2025-10-21)
|
||||
-------------------
|
||||
|
||||
29.5.3 (2025-09-11)
|
||||
-------------------
|
||||
* Clearer warning message, the old one lacked information and was perhaps misleading (`#2927 <https://github.com/ros2/rclcpp/issues/2927>`_) (`#2931 <https://github.com/ros2/rclcpp/issues/2931>`_)
|
||||
* fix cmake deprecation (`#2914 <https://github.com/ros2/rclcpp/issues/2914>`_) (`#2915 <https://github.com/ros2/rclcpp/issues/2915>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.2 (2025-07-07)
|
||||
-------------------
|
||||
|
||||
29.5.1 (2025-06-23)
|
||||
-------------------
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.0 (2025-04-18)
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
This document is a declaration of software quality for the `rclcpp_lifecycle` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
This document is a declaration of software quality for the `rclcpp_lifecycle` package, based on the guidelines in [REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
|
||||
# rclcpp_lifecycle Quality Declaration
|
||||
|
||||
The package `rclcpp_lifecycle` claims to be in the **Quality Level 1** category when used with a **Quality Level 1** middleware.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
|
||||
## Version Policy [1]
|
||||
|
||||
@@ -53,7 +53,7 @@ All pull requests will be peer-reviewed, check [ROS 2 Developer Guide](https://d
|
||||
|
||||
### Continuous Integration [2.iv]
|
||||
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://www.ros.org/reps/rep-2000.html#support-tiers)
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://reps.openrobotics.org/rep-2000/#support-tiers)
|
||||
|
||||
Currently nightly results can be seen here:
|
||||
|
||||
@@ -191,7 +191,7 @@ It is **Quality Level 1**, see its [Quality Declaration document](https://github
|
||||
|
||||
## Platform Support [6]
|
||||
|
||||
`rclcpp_lifecycle` supports all of the tier 1 platforms as described in [REP-2000](https://www.ros.org/reps/rep-2000.html#support-tiers), and tests each change against all of them.
|
||||
`rclcpp_lifecycle` supports all of the tier 1 platforms as described in [REP-2000](https://reps.openrobotics.org/rep-2000/#support-tiers), and tests each change against all of them.
|
||||
|
||||
Currently nightly build status can be seen here:
|
||||
* [linux-aarch64_release](https://ci.ros2.org/view/nightly/job/nightly_linux-aarch64_release/lastBuild/rclcpp_lifecycle/)
|
||||
@@ -203,4 +203,4 @@ Currently nightly build status can be seen here:
|
||||
|
||||
### Vulnerability Disclosure Policy [7.i]
|
||||
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://www.ros.org/reps/rep-2006.html).
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://reps.openrobotics.org/rep-2006/).
|
||||
|
||||
@@ -486,6 +486,16 @@ public:
|
||||
ParameterT & value,
|
||||
const ParameterT & alternative_value) const;
|
||||
|
||||
/// Return the parameter value, or the "alternative_value" if not set.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_parameter_or
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
ParameterT
|
||||
get_parameter_or(
|
||||
const std::string & name,
|
||||
const ParameterT & alternative_value) const;
|
||||
|
||||
/// Return the parameters by the given parameter names.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_parameters
|
||||
|
||||
@@ -306,5 +306,16 @@ LifecycleNode::get_parameter_or(
|
||||
return got_parameter;
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
ParameterT
|
||||
LifecycleNode::get_parameter_or(
|
||||
const std::string & name,
|
||||
const ParameterT & alternative_value) const
|
||||
{
|
||||
ParameterT parameter;
|
||||
get_parameter_or(name, parameter, alternative_value);
|
||||
return parameter;
|
||||
}
|
||||
|
||||
} // namespace rclcpp_lifecycle
|
||||
#endif // RCLCPP_LIFECYCLE__LIFECYCLE_NODE_IMPL_HPP_
|
||||
|
||||
@@ -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>30.1.2</version>
|
||||
<version>29.5.7</version>
|
||||
<description>Package containing a prototype for lifecycle implementation</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -414,14 +414,10 @@ LifecycleNode::LifecycleNodeInterfaceImpl::change_state(
|
||||
rcl_lifecycle_trigger_transition_by_id(
|
||||
&state_machine_, transition_id, publish_update) != RCL_RET_OK)
|
||||
{
|
||||
const char * transition_label = rcl_lifecycle_get_transition_label_by_id(
|
||||
&state_machine_.transition_map, transition_id);
|
||||
RCLCPP_ERROR(
|
||||
node_logging_interface_->get_logger(),
|
||||
"Unable to start transition %u (%s) from current state %s: %s",
|
||||
transition_id,
|
||||
transition_label ? transition_label : "unknown transition",
|
||||
state_machine_.current_state->label, rcl_get_error_string().str);
|
||||
"Unable to start transition %u from current state %s: %s",
|
||||
transition_id, state_machine_.current_state->label, rcl_get_error_string().str);
|
||||
rcutils_reset_error();
|
||||
return RCL_RET_ERROR;
|
||||
}
|
||||
|
||||
@@ -840,6 +840,26 @@ TEST_F(TestDefaultStateMachine, check_parameters) {
|
||||
EXPECT_TRUE(parameter.as_bool());
|
||||
}
|
||||
|
||||
TEST_F(TestDefaultStateMachine, test_get_parameter_or) {
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
|
||||
const std::string param_name = "test_param";
|
||||
int param_int = -999;
|
||||
|
||||
// Parameter does not exist, should return "or" value
|
||||
EXPECT_FALSE(test_node->get_parameter_or(param_name, param_int, 123));
|
||||
EXPECT_EQ(param_int, 123);
|
||||
EXPECT_EQ(test_node->get_parameter_or(param_name, 456), 456);
|
||||
|
||||
// Declare param_int
|
||||
test_node->declare_parameter(param_name, rclcpp::ParameterValue(789));
|
||||
|
||||
// Parameter exists, should return existing value
|
||||
EXPECT_TRUE(test_node->get_parameter_or(param_name, param_int, 123));
|
||||
EXPECT_EQ(param_int, 789);
|
||||
EXPECT_EQ(test_node->get_parameter_or(param_name, 456), 789);
|
||||
}
|
||||
|
||||
TEST_F(TestDefaultStateMachine, test_getters) {
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
auto options = test_node->get_node_options();
|
||||
|
||||
@@ -226,28 +226,36 @@ private:
|
||||
rclcpp::init(0, nullptr);
|
||||
lifecycle_node_ = std::make_shared<EmptyLifecycleNode>();
|
||||
lifecycle_client_ = std::make_shared<LifecycleServiceClient>("client");
|
||||
|
||||
executor_ = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
|
||||
spinner_ = std::thread([this]() {
|
||||
executor_->add_node(lifecycle_node_->get_node_base_interface());
|
||||
executor_->add_node(lifecycle_client_);
|
||||
executor_->spin();
|
||||
});
|
||||
spinner_ = std::thread(&TestLifecycleServiceClient::spin, this);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
while(!executor_->is_spinning()) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(shutdown_mutex_);
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
executor_->cancel();
|
||||
spinner_.join();
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
void spin()
|
||||
{
|
||||
while (true) {
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(shutdown_mutex_);
|
||||
if (!rclcpp::ok()) {
|
||||
break;
|
||||
}
|
||||
rclcpp::spin_some(lifecycle_node_->get_node_base_interface());
|
||||
rclcpp::spin_some(lifecycle_client_);
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<EmptyLifecycleNode> lifecycle_node_;
|
||||
std::shared_ptr<LifecycleServiceClient> lifecycle_client_;
|
||||
std::shared_ptr<rclcpp::executors::SingleThreadedExecutor> executor_;
|
||||
std::mutex shutdown_mutex_;
|
||||
std::thread spinner_;
|
||||
};
|
||||
|
||||
@@ -447,39 +455,34 @@ TEST_F(TestLifecycleServiceClientRCLErrors, call_services_rcl_errors) {
|
||||
auto mock = mocking_utils::patch_and_return(
|
||||
"lib:rclcpp_lifecycle", rcl_lifecycle_state_machine_is_initialized, RCL_RET_ERROR);
|
||||
|
||||
rclcpp::executors::SingleThreadedExecutor lifecycle_node_executor;
|
||||
lifecycle_node_executor.add_node(lifecycle_node->get_node_base_interface());
|
||||
rclcpp::executors::SingleThreadedExecutor client_executor;
|
||||
client_executor.add_node(lifecycle_client);
|
||||
|
||||
// on_change_state
|
||||
lifecycle_client->change_state(
|
||||
lifecycle_msgs::msg::Transition::TRANSITION_CONFIGURE);
|
||||
client_executor.spin_some();
|
||||
rclcpp::spin_some(lifecycle_client);
|
||||
EXPECT_THROW(
|
||||
lifecycle_node_executor.spin_some(), std::runtime_error);
|
||||
rclcpp::spin_some(lifecycle_node->get_node_base_interface()), std::runtime_error);
|
||||
|
||||
// on_get_state
|
||||
lifecycle_client->get_state();
|
||||
client_executor.spin_some();
|
||||
rclcpp::spin_some(lifecycle_client);
|
||||
EXPECT_THROW(
|
||||
lifecycle_node_executor.spin_some(), std::runtime_error);
|
||||
rclcpp::spin_some(lifecycle_node->get_node_base_interface()), std::runtime_error);
|
||||
|
||||
// on_get_avilable_states
|
||||
lifecycle_client->get_available_states();
|
||||
client_executor.spin_some();
|
||||
rclcpp::spin_some(lifecycle_client);
|
||||
EXPECT_THROW(
|
||||
lifecycle_node_executor.spin_some(), std::runtime_error);
|
||||
rclcpp::spin_some(lifecycle_node->get_node_base_interface()), std::runtime_error);
|
||||
|
||||
// on_get_available_transitions
|
||||
lifecycle_client->get_available_transitions();
|
||||
client_executor.spin_some();
|
||||
rclcpp::spin_some(lifecycle_client);
|
||||
EXPECT_THROW(
|
||||
lifecycle_node_executor.spin_some(), std::runtime_error);
|
||||
rclcpp::spin_some(lifecycle_node->get_node_base_interface()), std::runtime_error);
|
||||
|
||||
// on_get_transition_graph
|
||||
lifecycle_client->get_transition_graph();
|
||||
client_executor.spin_some();
|
||||
rclcpp::spin_some(lifecycle_client);
|
||||
EXPECT_THROW(
|
||||
lifecycle_node_executor.spin_some(), std::runtime_error);
|
||||
rclcpp::spin_some(lifecycle_node->get_node_base_interface()), std::runtime_error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user