Compare commits

..

85 Commits

Author SHA1 Message Date
Alejandro Hernandez Cordero
525a418188 28.1.13 2025-10-21 11:55:22 +02:00
Alejandro Hernandez Cordero
c3c5b693b7 Changelog
Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
2025-10-21 11:55:15 +02:00
mergify[bot]
d65ea282ac it misses the iterator second to lock the weakptr. (#2958) (#2960)
(cherry picked from commit aa60fcf22a)

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-09-30 12:05:17 +02:00
Alejandro Hernandez Cordero
2f854aa9c3 28.1.12 2025-09-11 15:27:00 +02:00
Alejandro Hernandez Cordero
d5fdfd5f27 Changelog
Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
2025-09-11 15:26:56 +02:00
mergify[bot]
0601de2ac8 Removed warning test_qos (#2859) (#2945)
(cherry picked from commit df3a303a17)

Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
2025-09-04 08:38:17 +09:00
mergify[bot]
de7f83cac4 Clearer warning message, the old one lacked information and was perhaps misleading (#2927) (#2932)
* change misleading warning message, making it more correct and informative



* Fix compile error. Needed to also build rcl from source.



* explicitely initialize pointer as null, to adhere to best practice



---------


(cherry picked from commit 37677791ca)

Signed-off-by: Peter Mitrano (AR) <peter.mitrano@agile-robots.com>
Co-authored-by: Peter Mitrano (AR) <peter.mitrano@agile-robots.com>
2025-08-19 10:58:38 +02:00
mergify[bot]
2096d63a1b Allow for implicitly convertable loggers as well (#2922) (#2936) (#2937)
(cherry picked from commit 8a4cb48b2c)

Signed-off-by: Tim Clephas <tim.clephas@nobleo.nl>
Co-authored-by: Tim Clephas <tim.clephas@nobleo.nl>
2025-08-19 11:50:35 +09:00
mergify[bot]
4cbc807f46 Fix: improve exception context for parameter_value_from (#2917) (#2920)
(cherry picked from commit 1f2adc9829)

Signed-off-by: Michiel Leegwater <mleegwt@users.noreply.github.com>
Signed-off-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
Co-authored-by: Michiel Leegwater <mleegwt@users.noreply.github.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
2025-08-18 19:59:31 +02:00
Marco A. Gutierrez
2445c37af3 28.1.11
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2025-08-06 16:18:45 +08:00
Marco A. Gutierrez
a73ce84e32 Changelog.
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2025-08-06 16:04:45 +08:00
mergify[bot]
ebdaf1f8ef Fix start_type_description_service param handling (#2897) (#2909)
* Fix `start_type_description_service` param handling



* Add test



* Demonstrate different exceptions depending on node options



* Same exact exception and `what()` message in both cases



* Uncrustify



---------


(cherry picked from commit 4fb558ae7b)

Signed-off-by: Patrick Roncagliolo <ronca.pat@gmail.com>
Co-authored-by: Patrick Roncagliolo <ronca.pat@gmail.com>
2025-07-16 21:52:58 -07:00
mergify[bot]
37f0960640 Add qos parameter for wait_for_message function (#2903) (#2906)
(cherry picked from commit 2fcef70ea7)

Signed-off-by: Sriharsha Ghanta <ghanta1996@gmail.com>
Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
Co-authored-by: Sriharsha Ghanta <ghanta_sriharsha@mymail.sutd.edu.sg>
Co-authored-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
2025-07-16 15:51:22 -07:00
mergify[bot]
b6a0b004a7 [jazzy] Expose typesupport_helpers API needed for the Rosbag2 (backport #2858) (#2902)
* Expose `typesupport_helpers` API needed for the Rosbag2 (#2858)

* Expose extract_type_identifier and get_typesupport_library_path API

- Rationale: We need to use this API in the Rosbag2
- Reference PR https://github.com/ros2/rosbag2/pull/2017 in the Rosbag2

Signed-off-by: Michael Orlov <michael.orlov@apex.ai>

* Use C++ style in doxygen documentation

Signed-off-by: Michael Orlov <michael.orlov@apex.ai>

---------

Signed-off-by: Michael Orlov <michael.orlov@apex.ai>
(cherry picked from commit 448287b109)

# Conflicts:
#	rclcpp/include/rclcpp/typesupport_helpers.hpp

* Address merge conflicts

Signed-off-by: Michael Orlov <michael.orlov@apex.ai>

---------

Signed-off-by: Michael Orlov <michael.orlov@apex.ai>
Co-authored-by: Michael Orlov <morlovmr@gmail.com>
2025-07-10 21:11:44 -07:00
mergify[bot]
bb3233b029 Fujitatomoya/test append parameter override (#2896) (#2900)
(cherry picked from commit 84c6fb1cfc)

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-07-10 14:30:39 +02:00
mergify[bot]
c4ca0dfb2d Add overload of append_parameter_override (#2891) (#2895)
(cherry picked from commit fa0cf2da31)

Signed-off-by: Patrick Roncagliolo <ronca.pat@gmail.com>
Co-authored-by: Patrick Roncagliolo <ronca.pat@gmail.com>
2025-07-09 14:03:31 -07:00
Janosch Machowinski
83e0ec56b7 Event exec timer fix for https://github.com/ros2/rclcpp/issues/2889 (#2890)
Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Signed-off-by: Janosch Machowinski <jmachowinski@users.noreply.github.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
2025-07-08 09:41:56 +02:00
Janosch Machowinski
7aab9b6f99 Shutdown deadlock fix jazzy (#2887)
* fix: Don't deadlock if removing shutdown callbacks in a shutdown callback

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>

* refactor: Made fix API compatible

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>

---------

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
2025-07-02 16:52:43 +02:00
mergify[bot]
7860a8c490 fix test_publisher_with_system_default_qos. (#2881) (#2883)
(cherry picked from commit e6577c6792)

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-06-26 22:57:05 +02:00
Alejandro Hernandez Cordero
4d8a695c79 28.1.10 2025-06-23 16:51:12 +02:00
Alejandro Hernandez Cordero
f4b1b7694f Changelog
Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
2025-06-23 16:51:08 +02:00
mergify[bot]
d126fe2b34 Replace std::default_random_engine with std::mt19937 (humble) (#2847) (#2867)
(cherry picked from commit a0e2240ca3)

Signed-off-by: keeponoiro <keeeeeeep@gmail.com>
Co-authored-by: keeponoiro <keeeeeeep@gmail.com>
2025-05-30 17:16:49 -07:00
mergify[bot]
a8b90f5221 Fix for memory leaks in rclcpp::SerializedMessage (#2861) (#2864)
(cherry picked from commit 8d44b95d8b)

Signed-off-by: Michael Orlov <morlovmr@gmail.com>
Signed-off-by: Michael Orlov <michael.orlov@apex.ai>
Co-authored-by: Michael Orlov <morlovmr@gmail.com>
Co-authored-by: kylemarcey <marcey.kyle@gmail.com>
2025-05-30 10:42:59 +02:00
mergify[bot]
2b8ab746ff Added missing chrono includes (#2854) (#2856)
(cherry picked from commit 373a63c5e6)

Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
2025-05-23 19:00:51 +02:00
mergify[bot]
8a145880bd get_all_data_impl() does not handle null pointers properly, causing segmentation fault (backport #2840) (#2851)
Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
2025-05-19 19:11:44 +02:00
mergify[bot]
dd807bf4b5 QoSInitialization::from_rmw does not validate invalid history policy values, leading to silent failures (#2841) (#2845)
(cherry picked from commit 73e9bfb62b)

Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
2025-05-19 16:02:41 +02:00
mergify[bot]
8266f85bc8 throws std::invalid_argument if ParameterEvent is NULL. (#2814) (#2825)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
(cherry picked from commit 8b9691f42d)

Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-05-05 13:45:56 -07:00
Michael Orlov
b15203914b Merge pull request #2821 from ros2/mergify/bp/jazzy/pr-2819
Fix race condition in test clock (backport #2819)
2025-05-01 10:45:30 -07:00
Marco A. Gutierrez
86142c3aac 28.1.9
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2025-04-23 05:03:02 +00:00
Marco A. Gutierrez
379430b2ce Changelog.
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2025-04-23 05:02:13 +00:00
Pedro de Azeredo
2412329935 Fix race condition (#2819)
Signed-off-by: pedroazeredo04 <pedro_azeredo@usp.br>
Signed-off-by: Pedro Nogueira <pedro_azeredo@usp.br>
(cherry picked from commit 8e49befce9)
2025-04-18 21:49:00 +00:00
mergify[bot]
fe6aca3faf remove redundant typesupport check in serialization module (#2808) (#2815)
Signed-off-by: Tanishq Chaudhary <tanishqchaudhary101010@gmail.com>
(cherry picked from commit f78ed952b2)

Co-authored-by: Tanishq Chaudhary <tanishqchaudhary101010@gmail.com>
2025-04-15 09:38:01 +02:00
Janosch Machowinski
f3d66b892e fix(rclcpp_action): Fix sleep of expire thread in case of canceled timer (#2800)
This fixes a bug, that the expire action thread would not sleep as,
the sleep duration was not computed correctly.

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
2025-04-11 11:38:59 +02:00
Marco A. Gutierrez
3ca1e69c20 28.1.8
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2025-04-02 11:04:46 +00:00
Marco A. Gutierrez
405687cc5e Changelog.
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2025-04-02 11:04:17 +00:00
mergify[bot]
52d2bbfb8a Harden rclcpp_action::convert(). (#2786) (#2789)
* Harden rclcpp_action::convert().

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

* update docstring.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

---------

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
(cherry picked from commit ce86ef7e62)

Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-03-30 11:33:07 -07:00
mergify[bot]
b6acdc9ab6 should pull valid transition before trying to change the state. (#2774) (#2784)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
(cherry picked from commit 7b6ee8a2e7)

Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2025-03-28 15:39:41 +01:00
Michael Carroll
a982829f69 28.1.7 2025-03-26 16:27:46 +00:00
Michael Carroll
1aa7c7a969 Changelog.
Signed-off-by: Michael Carroll <mjcarroll@intrinsic.ai>
2025-03-26 13:23:38 +00:00
Janosch Machowinski
04502128a4 fix(ClockConditionalVariable): Fixed potential crash on shutdown (#2762)
This commit deregisters the context shutdown callback on deletion of
the ClockConditionalVariable thus fixing a memory violation on shutdown.

Also adds tests for the ClockConditionalVariable.

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
2025-03-18 13:56:34 +01:00
mergify[bot]
6d586d17aa doc: Added warning to not instantiate Clock directly with RCL_ROS_TIME (#2768) (#2769)
Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Signed-off-by: Janosch Machowinski <jmachowinski@users.noreply.github.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
(cherry picked from commit 30e61c955d)

Co-authored-by: Janosch Machowinski <jmachowinski@users.noreply.github.com>
2025-03-14 17:25:02 -07:00
mergify[bot]
9c7e591e62 Use rmw_event_type_is_supported in test_qos_event (backport #2761) (#2766)
* Use rmw_event_type_is_supported in test_qos_event (#2761)

Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
(cherry picked from commit 9db7fa2ccb)
2025-03-12 21:42:45 +01:00
Jonas Otto
c31daa608d add NO_UNDEFINED_SYMBOLS to rclcpp_components_register_node cmake macro (#2746)
Signed-off-by: Jonas Otto <jonas.otto@ipa.fraunhofer.de>
Signed-off-by: Jonas Otto <jonas@jonasotto.com>
2025-03-07 22:29:37 +01:00
Janosch Machowinski
4c239d30a9 fix: Fixed expiring of goals if events executor is used (#2674)
* feat: Add ClockWaiter and ClockConditionalVariable

Added two new synchronization primitives to perform waits
using an rclcpp::Clock.

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>

* fix: Fixed expiring of goals if events executor is used

This commit is only relevant if the events executor is used.

This commit starts a background thread, to create events
for the expire timer of the action. Without this the action
server will not expire old goal results leading to memory and
performance issues.

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>

---------

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
2025-02-21 16:33:31 +01:00
mergify[bot]
d24a31738c Executor strong reference fix (#2745) (#2754)
https://github.com/ros2/rclcpp/issues/2678 reported that the executor
was holding strong references to entities during execution. This commit
adds a regression test for this.

* fix(Executor): Don't hold strong references to entities during spin

This fixes a bug, were dropping an entity during a callback would
not prevent further callbacks. Note, there might still be a race
in the case of the mutithreaded executor.

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
(cherry picked from commit 9c493c4615)

Co-authored-by: Janosch Machowinski <jmachowinski@users.noreply.github.com>
2025-02-21 16:31:41 +01:00
Janosch Machowinski
7dadf343b7 Double gc executor fix (#2753)
* fix(Executor): Don't add the notify_waitable two times to the waitset

Signed-off-by: Janosch Machowinski <j.machowinski@cellumation.com>

* test: Fix  TestExecutorNotifyWaitable wait test

The test was adding the same guard condition twice. This not allowed.

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>

---------

Signed-off-by: Janosch Machowinski <j.machowinski@cellumation.com>
Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Janosch Machowinski <j.machowinski@cellumation.com>
2025-02-19 18:11:13 -06:00
mergify[bot]
1044236ade Fix typo in doc section for get_service_typesupport_handle (#2751) (#2752)
Signed-off-by: Barry Xu <barry.xu@sony.com>
(cherry picked from commit 06d400d795)

Co-authored-by: Barry Xu <barry.xu@sony.com>
2025-02-19 20:52:53 +01:00
mergify[bot]
abc76111dc Test case and fix for for https://github.com/ros2/rclcpp/issues/2652 (#2713) (#2740)
Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Signed-off-by: Francisco Martín Rico <fmrico@gmail.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Francisco Martín Rico <fmrico@gmail.com>
(cherry picked from commit 605251bd71)

Co-authored-by: Janosch Machowinski <jmachowinski@users.noreply.github.com>
2025-02-11 15:29:00 -08:00
mergify[bot]
2eaa2eb355 fix(timer): Delete node, after executor thread terminated (#2737) (#2738)
This fixes a potential race leading to a segfault. The segfault would
happen, if the tear down of the test would occur before the timer thread
stopped the spinning of the executor.

Also simplifies the test code, as the cancel of the executor is now in
the TearDown().

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
(cherry picked from commit f6b80abe4a)

Co-authored-by: Janosch Machowinski <jmachowinski@users.noreply.github.com>
2025-02-11 12:19:30 +01:00
mergify[bot]
9dd2c91d7d fix(Executor): Fixed entities not beeing executed after just beeing added (#2724) (#2729)
Fixes https://github.com/ros2/rclcpp/issues/2589

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
(cherry picked from commit e7afaa636a)

Co-authored-by: Janosch Machowinski <jmachowinski@users.noreply.github.com>
2025-01-28 12:06:34 -08:00
mergify[bot]
7c896265a6 Fix transient local IPC publish (#2708) (#2722)
* Fix transient local publish when inter and intra process communications are both present.

* Apply the fix to TypeAdapted signature

* Add an executor to intra_process_inter_process_mix_transient_local test case to enable inter process publishing test

Signed-off-by: Jeffery Hsu <jefferyyjhsu@gmail.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
(cherry picked from commit f5e08c2d0c)

Co-authored-by: Jeffery Hsu <jefferyyjhsu@gmail.com>
2025-01-07 09:11:33 +01:00
Marco A. Gutierrez
985e320de3 28.1.6
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2024-12-18 06:28:23 +00:00
Marco A. Gutierrez
eac2e8a7dd Changelog.
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2024-12-18 06:27:18 +00:00
mergify[bot]
cff2711aba apply actual QoS from rmw to the IPC publisher. (#2707) (#2712)
* apply actual QoS from rmw to the IPC publisher.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

* address uncrustify warning.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

---------

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
(cherry picked from commit 016cfeac99)

Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2024-12-16 17:27:51 -08:00
mergify[bot]
608e2f2e56 Adding in topic name to logging on IPC issues (#2706) (#2710)
* Adding in topic name to logging on IPC issues

Signed-off-by: Steve Macenski <stevenmacenski@gmail.com>

* Update test matching output logging

Signed-off-by: Steve Macenski <stevenmacenski@gmail.com>

* adding in single quotes

Signed-off-by: Steve Macenski <stevenmacenski@gmail.com>

---------

Signed-off-by: Steve Macenski <stevenmacenski@gmail.com>
(cherry picked from commit a13e16e2cb)

Co-authored-by: Steve Macenski <stevenmacenski@gmail.com>
2024-12-14 15:16:19 -08:00
Tomoya Fujita
bd695f4a3b enable testRaceConditionAddNode for rmw_connextdds. (#2698)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2024-12-04 12:45:09 -08:00
mergify[bot]
74162b19bf Re-enable executor test on rmw_connextdds. (#2693) (#2695)
It supports the events executor now, so re-enable the test.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
(cherry picked from commit d7245365ed)

Co-authored-by: Chris Lalancette <clalancette@gmail.com>
2024-12-04 08:32:48 -08:00
mergify[bot]
e217532817 Fix warnings on Windows. (backport #2692) (#2694)
* Fix warnings on Windows. (#2692)

For reasons I admit I do not understand, the deprecation
warnings for StaticSingleThreadedExecutor on Windows
happen when we construct a shared_ptr for it in the tests.
If we construct a regular object, then it is fine.  Luckily
this test does not require a shared_ptr, so just make it
a regular object here, which rixes the warning.

While we are in here, make all of the tests camel case to
be consistent.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
(cherry picked from commit 3310f9eaed)

# Conflicts:
#	rclcpp/test/rclcpp/executors/test_executors.cpp

* resolve backport conflict.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

---------

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: Chris Lalancette <clalancette@gmail.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2024-12-04 09:50:19 +01:00
mergify[bot]
a7b8ada6a7 Omnibus fixes for running tests with Connext. (backport #2684) (#2690)
* Omnibus fixes for running tests with Connext. (#2684)

* Omnibus fixes for running tests with Connext.

When running the tests with RTI Connext as the default
RMW, some of the tests are failing.  There are three
different failures fixed here:

1.  Setting the liveliness duration to a value smaller than
a microsecond causes Connext to throw an error.  Set it to
a millisecond.

2.  Using the SystemDefaultsQoS sets the QoS to KEEP_LAST 1.
Connext is somewhat slow in this regard, so it can be the case
that we are overwriting a previous service introspection event
with the next one.  Switch to the ServicesDefaultQoS in the test,
which ensures we will not lose events.

3.  Connext is slow to match publishers and subscriptions.  Thus,
when creating a subscription "on-the-fly", we should wait for the
publisher to match it before expecting the subscription to actually
receive data from it.

With these fixes in place, the test_client_common, test_generic_service,
test_service_introspection, and test_executors tests all pass for
me with rmw_connextdds.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>

* Fixes for executors.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>

* One more fix for services.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>

* More fixes for service_introspection.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>

* More fixes for introspection.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>

---------

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
(cherry picked from commit 9984197c29)

# Conflicts:
#	rclcpp/test/rclcpp/executors/test_executors.cpp
#	rclcpp/test/rclcpp/test_generic_service.cpp

* address backport merge conflicts.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

---------

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: Chris Lalancette <clalancette@gmail.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2024-12-03 15:04:57 -08:00
jmachowinski
df09c6e77d fix(Executor): Fix segfault if callback group is deleted during rmw_wait (#2682)
Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
2024-12-01 12:31:09 -08:00
mergify[bot]
06ae92ae96 Remove CODEOWNERS and the rolling-to-master job. (#2686) (#2687)
They are both legacy from times past, and are both
no longer serving their intended purposes.  Just remove them.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
(cherry picked from commit e64627004f)

Co-authored-by: Chris Lalancette <clalancette@gmail.com>
2024-11-27 10:45:36 +01:00
mergify[bot]
99b3803ce2 Fix NodeOptions assignment operator (#2656) (#2660)
* Fix NodeOptions assignment operator

Also copy the enable_logger_service_ member during the assignment operation

* Add more checks for NodeOptions copy test

* Set non default values by avoiding the copy-assignement

Signed-off-by: Romain DESILLE <r.desille@gmail.com>
Co-authored-by: Christophe Bedard <bedard.christophe@gmail.com>
(cherry picked from commit 9b654942f9)

Co-authored-by: Romain DESILLE <r.desille@gmail.com>
2024-11-07 09:47:55 -08:00
Cristóbal Arroyo
bbe2b99893 set QoS History KEEP_ALL explicitly for statistics publisher. (#2650) (#2657)
* set QoS History KEEP_ALL explicitly for statistics publisher.

* test_subscription_options adjustment.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2024-10-30 12:57:18 -04:00
Marco A. Gutierrez
09e5dd70f4 28.1.5 2024-09-19 17:15:53 +00:00
Marco A. Gutierrez
5551facd9b Changelog.
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2024-09-19 17:14:46 +00:00
Alberto Soragna
38ed9ed172 backport fix events-executor warm-up bug and add unit-tests (#2591) (#2628)
Signed-off-by: Alberto Soragna <alberto.soragna@gmail.com>
2024-09-17 13:38:52 +02:00
Marco A. Gutierrez
fad351ff85 28.1.4
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2024-09-06 19:00:36 +00:00
Marco A. Gutierrez
08c6cd9f9a Changelog.
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2024-09-06 18:59:53 +00:00
mergify[bot]
830a1f0212 Split test_executors.cpp even further. (#2572) (#2619)
That's because it is too large for Windows Debug to compile,
so split into smaller bits.

Even with this split, the file is too big; that's likely
because we are using TYPED_TEST here, which generates multiple
symbols per test case.  To deal with this, without further
breaking up the file, also add in the /bigobj flag when
compiling on Windows Debug.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
(cherry picked from commit c743c173e6)

Co-authored-by: Chris Lalancette <clalancette@gmail.com>
2024-09-06 10:28:31 -04:00
mergify[bot]
1b4485443d Correct node name in service test code (#2615) (#2616)
Signed-off-by: Barry Xu <barry.xu@sony.com>
(cherry picked from commit e846f56224)

Co-authored-by: Barry Xu <barry.xu@sony.com>
2024-09-03 09:14:43 +02:00
mergify[bot]
d73fc2a86a Release ownership of entities after spinning cancelled (backport #2556) (#2580)
* Release ownership of entities after spinning cancelled (#2556)

* Release ownership of entities after spinning cancelled

Signed-off-by: Barry Xu <barry.xu@sony.com>

* Move release action to every exit point in different spin functions

Signed-off-by: Barry Xu <barry.xu@sony.com>

* Move wait_result_.reset() before setting spinning to false

Signed-off-by: Barry Xu <barry.xu@sony.com>

* Update test code

Signed-off-by: Barry Xu <barry.xu@sony.com>

* Move test code to test_executors.cpp

Signed-off-by: Barry Xu <barry.xu@sony.com>

---------

Signed-off-by: Barry Xu <barry.xu@sony.com>
(cherry picked from commit 069a001893)

# Conflicts:
#	rclcpp/test/rclcpp/executors/test_executors.cpp

* Fix backport issue (#2581)

Signed-off-by: Barry Xu <barry.xu@sony.com>

---------

Signed-off-by: Barry Xu <barry.xu@sony.com>
Co-authored-by: Barry Xu <barry.xu@sony.com>
2024-07-18 12:43:49 -07:00
Marco A. Gutierrez
e083bf9b7d 28.1.3
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2024-06-27 10:35:14 +00:00
Marco A. Gutierrez
c3bc232eae Changelog.
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2024-06-27 10:28:12 +00:00
Tomoya Fujita
7f5b44ebe2 Revert "call shutdown in LifecycleNode dtor to avoid leaving the device in unknown state (2nd) (backport #2528) (#2542)" (#2558)
This reverts commit 8ab10aabc0.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2024-06-11 07:41:22 -07:00
mergify[bot]
8ab10aabc0 call shutdown in LifecycleNode dtor to avoid leaving the device in unknown state (2nd) (backport #2528) (#2542)
* call shutdown in LifecycleNode dtor to avoid leaving the device in unknown state (2nd) (#2528)

* Revert "Revert "call shutdown in LifecycleNode dtor to avoid leaving the device in un… (#2450)" (#2522)"

This reverts commit 42b0b5775b.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

* lifecycle node dtor shutdown should be called only in primary state.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

* adjust warning message if the node is still in transition state in dtor.

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

---------

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
(cherry picked from commit 3bc364a10b)

* LifecycleNode shutdown on dtor only with valid context. (#2545)

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>

---------

Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2024-06-07 10:33:43 -07:00
mergify[bot]
119a7bcbac Add test creating two content filter topics with the same topic name (#2546) (#2549) (#2552)
Signed-off-by: Mario-DL <mariodominguez@eprosima.com>
Co-authored-by: Mario Domínguez López <116071334+Mario-DL@users.noreply.github.com>
(cherry picked from commit 7c096888ca)

Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
2024-06-06 10:11:46 +02:00
mergify[bot]
0beba97156 rclcpp::shutdown should not be called before LifecycleNode dtor. (#2527) (#2540)
Signed-off-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
(cherry picked from commit 22df1d593a)

Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
2024-05-23 22:13:09 -07:00
Marco A. Gutierrez
c88a3602ab 28.1.2
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2024-05-13 21:21:56 +00:00
Marco A. Gutierrez
258b0a06bb Changelog.
Signed-off-by: Marco A. Gutierrez <marcogg@marcogg.com>
2024-05-13 21:20:28 +00:00
mergify[bot]
bf6a6733a1 add impl pointer for ExecutorOptions (#2523) (#2525)
* add impl pointer for ExecutorOptions

Signed-off-by: William Woodall <william@osrfoundation.org>
(cherry picked from commit 343b29b617)

Co-authored-by: William Woodall <william@osrfoundation.org>
2024-05-10 13:21:04 -04:00
mergify[bot]
4f17dee383 Revert "call shutdown in LifecycleNode dtor to avoid leaving the device in un… (#2450)" (#2522) (#2524)
This reverts commit 04ea0bb002.

(cherry picked from commit 42b0b5775b)

Co-authored-by: Chris Lalancette <clalancette@gmail.com>
2024-05-09 15:36:08 -04:00
mergify[bot]
2c23e3a73a Fixup Executor::spin_all() regression fix (#2517) (#2521)
* test(Executors): Added tests for busy waiting

Checks if executors are busy waiting while they should block
in spin_some or spin_all.

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>

* fix: Reworked spinAll test

This test was strange. It looked like, it assumed that spin_all did
not return instantly. Also it was racy, as the thread could terminate
instantly.

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>

* fix(Executor): Fixed spin_all not returning instantly is no work was available

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>

* Update rclcpp/test/rclcpp/executors/test_executors.cpp

Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Signed-off-by: jmachowinski <jmachowinski@users.noreply.github.com>

* test(executors): Added test for busy waiting while calling spin

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>

* fix(executor): Reset wait_result on every call to spin_some_impl

Before, the method would not recollect available work in case of
spin_some, spin_all. This would lead to the method behaving differently
than to what the documentation states.

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>

* restore previous test logic for now

Signed-off-by: William Woodall <william@osrfoundation.org>

* refactor spin_some_impl's logic and improve busy wait tests

Signed-off-by: William Woodall <william@osrfoundation.org>

* added some more comments about the implementation

Signed-off-by: William Woodall <william@osrfoundation.org>

---------

Signed-off-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Signed-off-by: jmachowinski <jmachowinski@users.noreply.github.com>
Signed-off-by: William Woodall <william@osrfoundation.org>
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: jmachowinski <jmachowinski@users.noreply.github.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
(cherry picked from commit f7185dc129)

Co-authored-by: William Woodall <william@osrfoundation.org>
2024-05-02 21:50:04 -07:00
Chris Lalancette
8934b5a0a9 28.1.1 2024-04-24 17:02:48 +00:00
Chris Lalancette
3407564a15 Changelog.
Signed-off-by: Chris Lalancette <clalancette@gmail.com>
2024-04-24 17:02:42 +00:00
mergify[bot]
8b3be2ad7e Revise the description of service configure_introspection() (#2511) (#2513)
Signed-off-by: Barry Xu <barry.xu@sony.com>
(cherry picked from commit 55939613a0)

Co-authored-by: Barry Xu <barry.xu@sony.com>
2024-04-23 22:57:31 +02:00
286 changed files with 5985 additions and 12138 deletions

45
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,45 @@
<!--
For general questions, please ask on ROS answers: https://answers.ros.org, make sure to include at least the `ros2` tag and the rosdistro version you are running, e.g. `ardent`.
For general design discussions, please post on discourse: https://discourse.ros.org/c/ng-ros
Not sure if this is the right repository? Open an issue on https://github.com/ros2/ros2/issues
For Bug report or feature requests, please fill out the relevant category below
-->
## Bug report
**Required Info:**
- Operating System:
- <!-- OS and version (e.g. Windows 10, Ubuntu 16.04...) -->
- Installation type:
- <!-- binaries or from source -->
- Version or commit hash:
- <!-- Output of git rev-parse HEAD, release version, or repos file -->
- DDS implementation:
- <!-- rmw_implementation used (e.g. Fast-RTPS, RTI Connext, etc -->
- Client library (if applicable):
- <!-- e.g. rclcpp, rclpy, or N/A -->
#### Steps to reproduce issue
<!-- Detailed instructions on how to reliably reproduce this issue http://sscce.org/
``` code that can be copy-pasted is preferred ``` -->
```
```
#### Expected behavior
#### Actual behavior
#### Additional information
<!-- If you are reporting a bug delete everything below
If you are requesting a feature deleted everything above this line -->
----
## Feature request
#### Feature description
<!-- Description in a few sentences what the feature consists of and what problem it will solve -->
#### Implementation considerations
<!-- Relevant information on how the feature could be implemented and pros and cons of the different solutions -->

View File

@@ -2,235 +2,201 @@
Changelog for package rclcpp
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30.1.5 (2026-02-09)
-------------------
* remove default: so that compiler can detect the missing case. (`#3048 <https://github.com/ros2/rclcpp/issues/3048>`_)
* use weak_ptr for rcl entities in the memory strategy. (`#2988 <https://github.com/ros2/rclcpp/issues/2988>`_)
* remove test_static_executor_entities_collector.cpp (`#3041 <https://github.com/ros2/rclcpp/issues/3041>`_)
* include the 1st spin that might throw the exception. (`#3042 <https://github.com/ros2/rclcpp/issues/3042>`_)
* print warning message on owner node if the parameter operation fails. (`#3037 <https://github.com/ros2/rclcpp/issues/3037>`_)
* fix context in wait for message wait set (`#3030 <https://github.com/ros2/rclcpp/issues/3030>`_)
* Revert "construct wait set with passed in context (`#3021 <https://github.com/ros2/rclcpp/issues/3021>`_)" (`#3028 <https://github.com/ros2/rclcpp/issues/3028>`_)
* construct wait set with passed in context (`#3021 <https://github.com/ros2/rclcpp/issues/3021>`_)
* Improve the robustness of the TopicEndpointInfo constructor (`#3013 <https://github.com/ros2/rclcpp/issues/3013>`_)
* Deprecate the shared_ptr<MessageT> subscription callback signatures (`#2975 <https://github.com/ros2/rclcpp/issues/2975>`_)
* Contributors: Barry Xu, Maurice Alexander Purnawan, Michael Carroll, Rahat Dhande, Tomoya Fujita
28.1.13 (2025-10-21)
--------------------
30.1.4 (2025-12-23)
-------------------
* Updated deprecated ament_index_cpp API (`#3011 <https://github.com/ros2/rclcpp/issues/3011>`_)
* Unified Node Interfaces: Add const version of get_node_x_interface() (`#3006 <https://github.com/ros2/rclcpp/issues/3006>`_)
* Parameter Descriptor Simplification (`#2179 <https://github.com/ros2/rclcpp/issues/2179>`_)
* ParameterEventHandler support ContentFiltering (`#2971 <https://github.com/ros2/rclcpp/issues/2971>`_)
* update policy_name_from_kind && test_qos (`#2156 <https://github.com/ros2/rclcpp/issues/2156>`_)
* Add ability to disable and enable subscription's callbacks (`#2985 <https://github.com/ros2/rclcpp/issues/2985>`_)
* Switch to isolated testing via rmw_test_fixture (`#2929 <https://github.com/ros2/rclcpp/issues/2929>`_)
* remove I/O from signal handler. (`#2986 <https://github.com/ros2/rclcpp/issues/2986>`_)
* Contributors: Alejandro Hernández Cordero, Andrianov Roman, Barry Xu, Lucas Wendland, Michael Orlov, Tomoya Fujita, fabianhirmann, yadunund
28.1.12 (2025-09-11)
--------------------
* Removed warning test_qos (`#2859 <https://github.com/ros2/rclcpp/issues/2859>`_) (`#2945 <https://github.com/ros2/rclcpp/issues/2945>`_)
* Allow for implicitly convertable loggers as well (`#2922 <https://github.com/ros2/rclcpp/issues/2922>`_) (`#2936 <https://github.com/ros2/rclcpp/issues/2936>`_) (`#2937 <https://github.com/ros2/rclcpp/issues/2937>`_)
* Fix: improve exception context for parameter_value_from (`#2917 <https://github.com/ros2/rclcpp/issues/2917>`_) (`#2920 <https://github.com/ros2/rclcpp/issues/2920>`_)
* Contributors: mergify[bot]
30.1.3 (2025-11-18)
-------------------
* correct test function descriptions (`#2970 <https://github.com/ros2/rclcpp/issues/2970>`_)
* add : get clients, servers info (`#2569 <https://github.com/ros2/rclcpp/issues/2569>`_)
* Fix REP url locations (`#2987 <https://github.com/ros2/rclcpp/issues/2987>`_)
* Contributors: Minju, Lee, Tim Clephas, Yuchen966
30.1.2 (2025-10-21)
-------------------
* 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
30.1.1 (2025-09-11)
-------------------
* 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
30.1.0 (2025-07-29)
-------------------
* 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
30.0.0 (2025-07-01)
-------------------
* 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)
-------------------
* 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
29.6.0 (2025-04-25)
-------------------
* 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
29.5.0 (2025-04-18)
-------------------
* Fix a race condition (`#2819 <https://github.com/ros2/rclcpp/issues/2819>`_)
* Remove redundant typesupport check in serialization module (`#2808 <https://github.com/ros2/rclcpp/issues/2808>`_)
* Remove get_typesupport_handle implementation. (`#2806 <https://github.com/ros2/rclcpp/issues/2806>`_)
* Use NodeParameterInterface instead of /parameter_event to update "use_sim_time" (`#2378 <https://github.com/ros2/rclcpp/issues/2378>`_)
* Remove cancel_clock_executor_promise\_. (`#2797 <https://github.com/ros2/rclcpp/issues/2797>`_)
* Enable parameter update recursively only when QoS override parameters. (`#2742 <https://github.com/ros2/rclcpp/issues/2742>`_)
* Contributors: Pedro de Azeredo, Tanishq Chaudhary, Tomoya Fujita
29.4.0 (2025-04-04)
-------------------
* Removed trailing whitespace from the codebase. (`#2791 <https://github.com/ros2/rclcpp/issues/2791>`_)
* Expanded docstring of `get_rmw_qos_profile()` (`#2787 <https://github.com/ros2/rclcpp/issues/2787>`_)
* Set envars to run tests with rmw_zenoh_cpp with multicast discovery (`#2776 <https://github.com/ros2/rclcpp/issues/2776>`_)
* fix: Compilefix for clang (`#2775 <https://github.com/ros2/rclcpp/issues/2775>`_)
* add exception doc for configure_introspection. (`#2773 <https://github.com/ros2/rclcpp/issues/2773>`_)
* feat: Add ClockWaiter and ClockConditionalVariable (`#2691 <https://github.com/ros2/rclcpp/issues/2691>`_)
* doc: Added warning to not instantiate Clock directly with RCL_ROS_TIME (`#2768 <https://github.com/ros2/rclcpp/issues/2768>`_)
* Use rmw_event_type_is_supported in test_qos_event (`#2761 <https://github.com/ros2/rclcpp/issues/2761>`_)
* Support action typesupport helper (`#2750 <https://github.com/ros2/rclcpp/issues/2750>`_)
* use maybe_unused attribute for the portability. (`#2758 <https://github.com/ros2/rclcpp/issues/2758>`_)
* Executor strong reference fix (`#2745 <https://github.com/ros2/rclcpp/issues/2745>`_)
* Cleanup of https://github.com/ros2/rclcpp/pull/2683 (`#2714 <https://github.com/ros2/rclcpp/issues/2714>`_)
* Fix typo in doc section for get_service_typesupport_handle (`#2751 <https://github.com/ros2/rclcpp/issues/2751>`_)
* Test case and fix for for https://github.com/ros2/rclcpp/issues/2652 (`#2713 <https://github.com/ros2/rclcpp/issues/2713>`_)
* fix(timer): Delete node, after executor thread terminated (`#2737 <https://github.com/ros2/rclcpp/issues/2737>`_)
* update doc section for spin_xxx methods. (`#2730 <https://github.com/ros2/rclcpp/issues/2730>`_)
* fix: Expose timers used by rclcpp::Waitables (`#2699 <https://github.com/ros2/rclcpp/issues/2699>`_)
* use rmw_qos_profile_rosout_default instead of rcl. (`#2663 <https://github.com/ros2/rclcpp/issues/2663>`_)
* fix(Executor): Fixed entities not beeing executed after just beeing added (`#2724 <https://github.com/ros2/rclcpp/issues/2724>`_)
* fix: make the loop condition align with the description (`#2726 <https://github.com/ros2/rclcpp/issues/2726>`_)
* Collect log messages from rcl, and reset. (`#2720 <https://github.com/ros2/rclcpp/issues/2720>`_)
* Contributors: Abhishek Kashyap, Alejandro Hernández Cordero, Barry Xu, Janosch Machowinski, Leander Stephen D'Souza, Tomoya Fujita, Yuyuan Yuan
29.3.0 (2024-12-20)
-------------------
* Fix transient local IPC publish (`#2708 <https://github.com/ros2/rclcpp/issues/2708>`_)
* apply actual QoS from rmw to the IPC publisher. (`#2707 <https://github.com/ros2/rclcpp/issues/2707>`_)
* Adding in topic name to logging on IPC issues (`#2706 <https://github.com/ros2/rclcpp/issues/2706>`_)
* fix TestTimeSource.ROS_time_valid_attach_detach. (`#2700 <https://github.com/ros2/rclcpp/issues/2700>`_)
* Update docstring for `rclcpp::Node::now()` (`#2696 <https://github.com/ros2/rclcpp/issues/2696>`_)
* Re-enable executor test on rmw_connextdds. (`#2693 <https://github.com/ros2/rclcpp/issues/2693>`_)
* Fix warnings on Windows. (`#2692 <https://github.com/ros2/rclcpp/issues/2692>`_)
* Omnibus fixes for running tests with Connext. (`#2684 <https://github.com/ros2/rclcpp/issues/2684>`_)
* fix(Executor): Fix segfault if callback group is deleted during rmw_wait (`#2683 <https://github.com/ros2/rclcpp/issues/2683>`_)
* Contributors: Chris Lalancette, Jeffery Hsu, Patrick Roncagliolo, Steve Macenski, Tomoya Fujita, jmachowinski
29.2.0 (2024-11-25)
-------------------
* accept custom allocator for LoanedMessage. (`#2672 <https://github.com/ros2/rclcpp/issues/2672>`_)
* Contributors: Tomoya Fujita
29.1.0 (2024-11-20)
-------------------
* a couple of typo fixes in doc section for LoanedMessage. (`#2676 <https://github.com/ros2/rclcpp/issues/2676>`_)
* Make sure callback_end tracepoint is triggered in AnyServiceCallback (`#2670 <https://github.com/ros2/rclcpp/issues/2670>`_)
* Correct the incorrect comments in generic_client.hpp (`#2662 <https://github.com/ros2/rclcpp/issues/2662>`_)
* Fix NodeOptions assignment operator (`#2656 <https://github.com/ros2/rclcpp/issues/2656>`_)
* set QoS History KEEP_ALL explicitly for statistics publisher. (`#2650 <https://github.com/ros2/rclcpp/issues/2650>`_)
* Fix test_intra_process_manager.cpp with rmw_zenoh_cpp (`#2653 <https://github.com/ros2/rclcpp/issues/2653>`_)
* Fixed test_events_executors in zenoh (`#2643 <https://github.com/ros2/rclcpp/issues/2643>`_)
* rmw_fastrtps supports service event gid uniqueness test. (`#2638 <https://github.com/ros2/rclcpp/issues/2638>`_)
* print warning if event callback is not supported instead of passing exception. (`#2648 <https://github.com/ros2/rclcpp/issues/2648>`_)
* Implement callback support of async_send_request for service generic client (`#2614 <https://github.com/ros2/rclcpp/issues/2614>`_)
* Contributors: Alejandro Hernández Cordero, Barry Xu, Chris Lalancette, Christophe Bedard, Romain DESILLE, Tomoya Fujita
29.0.0 (2024-10-03)
-------------------
* Fixed test qos rmw zenoh (`#2639 <https://github.com/ros2/rclcpp/issues/2639>`_)
* verify client gid uniqueness for a single service event. (`#2636 <https://github.com/ros2/rclcpp/issues/2636>`_)
* Skip some tests in test_qos_event and run others with event types supported by rmw_zenoh (`#2626 <https://github.com/ros2/rclcpp/issues/2626>`_)
* Shutdown the context before context's destructor is invoked in tests (`#2633 <https://github.com/ros2/rclcpp/issues/2633>`_)
* Skip rmw zenoh content filtering tests (`#2627 <https://github.com/ros2/rclcpp/issues/2627>`_)
* Use InvalidServiceTypeError for unavailable service type in GenericClient (`#2629 <https://github.com/ros2/rclcpp/issues/2629>`_)
* Implement generic service (`#2617 <https://github.com/ros2/rclcpp/issues/2617>`_)
* fix events-executor warm-up bug and add unit-tests (`#2591 <https://github.com/ros2/rclcpp/issues/2591>`_)
* remove unnecessary gtest-skip in test_executors (`#2600 <https://github.com/ros2/rclcpp/issues/2600>`_)
* Correct node name in service test code (`#2615 <https://github.com/ros2/rclcpp/issues/2615>`_)
* Minor naming fixes for ParameterValue to_string() function (`#2609 <https://github.com/ros2/rclcpp/issues/2609>`_)
* Removed clang warnings (`#2605 <https://github.com/ros2/rclcpp/issues/2605>`_)
* Fix a couple of issues in the documentation. (`#2608 <https://github.com/ros2/rclcpp/issues/2608>`_)
* deprecate the static single threaded executor (`#2598 <https://github.com/ros2/rclcpp/issues/2598>`_)
* Fix name of ParameterEventHandler class in doc (`#2604 <https://github.com/ros2/rclcpp/issues/2604>`_)
* subscriber_statistics_collectors\_ should be protected by mutex. (`#2592 <https://github.com/ros2/rclcpp/issues/2592>`_)
* Fix bug in timers lifecycle for events executor (`#2586 <https://github.com/ros2/rclcpp/issues/2586>`_)
* fix rclcpp/test/rclcpp/CMakeLists.txt to check for the correct targets existance (`#2596 <https://github.com/ros2/rclcpp/issues/2596>`_)
* Shut down context during init if logging config fails (`#2594 <https://github.com/ros2/rclcpp/issues/2594>`_)
* Make more of the Waitable API abstract (`#2593 <https://github.com/ros2/rclcpp/issues/2593>`_)
* Contributors: Alberto Soragna, Alejandro Hernández Cordero, Alexis Pojomovsky, Barry Xu, Chris Lalancette, Christophe Bedard, Kang, Hsin-Yi, Tomoya Fujita
28.3.3 (2024-07-29)
-------------------
* Only compile the tests once. (`#2590 <https://github.com/ros2/rclcpp/issues/2590>`_)
* Contributors: Chris Lalancette
28.3.2 (2024-07-24)
-------------------
* Updated rcpputils path API (`#2579 <https://github.com/ros2/rclcpp/issues/2579>`_)
* Make the subscriber_triggered_to_receive_message test more reliable. (`#2584 <https://github.com/ros2/rclcpp/issues/2584>`_)
* Make the subscriber_triggered_to_receive_message test more reliable.
In the current code, inside of the timer we create the subscription
and the publisher, publish immediately, and expect the subscription
to get it immediately. But it may be the case that discovery
hasn't even happened between the publisher and the subscription
by the time the publish call happens.
To make this more reliable, create the subscription and publish *before*
we ever create and spin on the timer. This at least gives 100
milliseconds for discovery to happen. That may not be quite enough
to make this reliable on all platforms, but in my local testing this
helps a lot. Prior to this change I can make this fail one out of 10
times, and after the change I've run 100 times with no failures.
* Have the EventsExecutor use more common code (`#2570 <https://github.com/ros2/rclcpp/issues/2570>`_)
* move notify waitable setup to its own function
* move mutex lock to retrieve_entity utility
* use entities_need_rebuild\_ atomic bool in events-executors
* remove duplicated set_on_ready_callback for notify_waitable
* use mutex from base class rather than a new recursive mutex
* use current_collection\_ member in events-executor
* delay adding notify waitable to collection
* postpone clearing the current collection
* commonize notify waitable and collection
* commonize add/remove node/cbg methods
* fix linter errors
28.1.11 (2025-08-06)
--------------------
* Fix `start_type_description_service` param handling (`#2897 <https://github.com/ros2/rclcpp/issues/2897>`_) (`#2909 <https://github.com/ros2/rclcpp/issues/2909>`_)
* Fix `start_type_description_service` param handling
* Add test
* Demonstrate different exceptions depending on node options
* Same exact exception and `what()` message in both cases
* Uncrustify
---------
* Removed deprecated methods and classes (`#2575 <https://github.com/ros2/rclcpp/issues/2575>`_)
* Release ownership of entities after spinning cancelled (`#2556 <https://github.com/ros2/rclcpp/issues/2556>`_)
* Release ownership of entities after spinning cancelled
* Move release action to every exit point in different spin functions
* Move wait_result\_.reset() before setting spinning to false
* Update test code
* Move test code to test_executors.cpp
(cherry picked from commit 4fb558ae7b2ce7ce9b546e103beaac4f99991e5c)
Co-authored-by: Patrick Roncagliolo <ronca.pat@gmail.com>
* Add qos parameter for wait_for_message function (`#2903 <https://github.com/ros2/rclcpp/issues/2903>`_) (`#2906 <https://github.com/ros2/rclcpp/issues/2906>`_)
(cherry picked from commit 2fcef70ea78c2c3a45391e59aebb265c05113050)
Co-authored-by: Sriharsha Ghanta <ghanta_sriharsha@mymail.sutd.edu.sg>
Co-authored-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
* [jazzy] Expose `typesupport_helpers` API needed for the Rosbag2 (backport `#2858 <https://github.com/ros2/rclcpp/issues/2858>`_) (`#2902 <https://github.com/ros2/rclcpp/issues/2902>`_)
* Expose `typesupport_helpers` API needed for the Rosbag2 (`#2858 <https://github.com/ros2/rclcpp/issues/2858>`_)
* Expose extract_type_identifier and get_typesupport_library_path API
- Rationale: We need to use this API in the Rosbag2
- Reference PR https://github.com/ros2/rosbag2/pull/2017 in the Rosbag2
* Use C++ style in doxygen documentation
---------
* Split test_executors.cpp even further. (`#2572 <https://github.com/ros2/rclcpp/issues/2572>`_)
(cherry picked from commit 448287b1090567181c809e59a3c72eed5ef4c69c)
# Conflicts:
# rclcpp/include/rclcpp/typesupport_helpers.hpp
* Address merge conflicts
---------
Co-authored-by: Michael Orlov <morlovmr@gmail.com>
* Fujitatomoya/test append parameter override (`#2896 <https://github.com/ros2/rclcpp/issues/2896>`_) (`#2900 <https://github.com/ros2/rclcpp/issues/2900>`_)
(cherry picked from commit 84c6fb1cfc945521680a0e1fccf5b32237acbcc3)
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
* Add overload of `append_parameter_override` (`#2891 <https://github.com/ros2/rclcpp/issues/2891>`_) (`#2895 <https://github.com/ros2/rclcpp/issues/2895>`_)
(cherry picked from commit fa0cf2da31dfae7c83f185e3bf18cb8fd55f0f57)
Co-authored-by: Patrick Roncagliolo <ronca.pat@gmail.com>
* Event exec timer fix for https://github.com/ros2/rclcpp/issues/2889 (`#2890 <https://github.com/ros2/rclcpp/issues/2890>`_)
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
* Shutdown deadlock fix jazzy (`#2887 <https://github.com/ros2/rclcpp/issues/2887>`_)
* fix: Don't deadlock if removing shutdown callbacks in a shutdown callback
* refactor: Made fix API compatible
---------
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
* fix test_publisher_with_system_default_qos. (`#2881 <https://github.com/ros2/rclcpp/issues/2881>`_) (`#2883 <https://github.com/ros2/rclcpp/issues/2883>`_)
(cherry picked from commit e6577c6792f76a74e303cc0c061e89abeb8cb1a6)
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
* Contributors: Janosch Machowinski, mergify[bot]
28.1.10 (2025-06-23)
--------------------
* Fix for memory leaks in rclcpp::SerializedMessage (`#2861 <https://github.com/ros2/rclcpp/issues/2861>`_) (`#2864 <https://github.com/ros2/rclcpp/issues/2864>`_)
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2856 <https://github.com/ros2/rclcpp/issues/2856>`_)
* get_all_data_impl() does not handle null pointers properly, causing segmentation fault (backport `#2840 <https://github.com/ros2/rclcpp/issues/2840>`_) (`#2851 <https://github.com/ros2/rclcpp/issues/2851>`_)
* QoSInitialization::from_rmw does not validate invalid history policy values, leading to silent failures (`#2841 <https://github.com/ros2/rclcpp/issues/2841>`_) (`#2845 <https://github.com/ros2/rclcpp/issues/2845>`_)
* throws std::invalid_argument if ParameterEvent is NULL. (`#2814 <https://github.com/ros2/rclcpp/issues/2814>`_) (`#2825 <https://github.com/ros2/rclcpp/issues/2825>`_)
* Merge pull request `#2821 <https://github.com/ros2/rclcpp/issues/2821>`_ from ros2/mergify/bp/jazzy/pr-2819
* Fix race condition (`#2819 <https://github.com/ros2/rclcpp/issues/2819>`_)
* Contributors: Michael Orlov, Pedro de Azeredo, mergify[bot]
28.1.9 (2025-04-23)
-------------------
* remove redundant typesupport check in serialization module (`#2808 <https://github.com/ros2/rclcpp/issues/2808>`_) (`#2815 <https://github.com/ros2/rclcpp/issues/2815>`_)
(cherry picked from commit f78ed952b27acc63ef8022d78cb816c309a9ca3d)
Co-authored-by: Tanishq Chaudhary <tanishqchaudhary101010@gmail.com>
* Contributors: mergify[bot]
28.1.8 (2025-04-02)
-------------------
28.1.7 (2025-03-26)
-------------------
* fix(ClockConditionalVariable): Fixed potential crash on shutdown (`#2762 <https://github.com/ros2/rclcpp/issues/2762>`_)
* doc: Added warning to not instantiate Clock directly with RCL_ROS_TIME (`#2769 <https://github.com/ros2/rclcpp/issues/2769>`_)
* Backports: `#2768 <https://github.com/ros2/rclcpp/issues/2768>`_
* Use rmw_event_type_is_supported in test_qos_event (`#2766 <https://github.com/ros2/rclcpp/issues/2766>`_)
* Backports: `#2761 <https://github.com/ros2/rclcpp/issues/2761>`_
* fix: Fixed expiring of goals if events executor is used (`#2674 <https://github.com/ros2/rclcpp/issues/2674>`_)
* Executor strong reference fix (`#2754 <https://github.com/ros2/rclcpp/issues/2754>`_)
* Backports: `#2745 <https://github.com/ros2/rclcpp/issues/2745>`_
* Double gc executor fix (`#2753 <https://github.com/ros2/rclcpp/issues/2753>`_)
* Fix typo in doc section for get_service_typesupport_handle (`#2752 <https://github.com/ros2/rclcpp/issues/2752>`_)
* Backports: `#2751 <https://github.com/ros2/rclcpp/issues/2751>`_
* Test case and fix for for https://github.com/ros2/rclcpp/issues/2652 (`#2740 <https://github.com/ros2/rclcpp/issues/2740>`_)
* Backports: `#2713 <https://github.com/ros2/rclcpp/issues/2713>`_
* fix(timer): Delete node, after executor thread terminated (`#2738 <https://github.com/ros2/rclcpp/issues/2738>`_)
* Backports: `#2737 <https://github.com/ros2/rclcpp/issues/2737>`_
* fix(Executor): Fixed entities not beeing executed after just beeing added (`#2729 <https://github.com/ros2/rclcpp/issues/2729>`_)
* Backports: `#2737 <https://github.com/ros2/rclcpp/issues/2724>`_
* Fix transient local IPC publish (`#2722 <https://github.com/ros2/rclcpp/issues/2722>`_)
* Backports: `#2708 <https://github.com/ros2/rclcpp/issues/2708>`_
* Contributors: Janosch Machowinski, Jeffery Hsu, Tomoya Fujita, Francisco Martín Rico
28.1.6 (2024-12-18)
-------------------
* apply actual QoS from rmw to the IPC publisher. (`#2707 <https://github.com/ros2/rclcpp/issues/2707>`_) (`#2712 <https://github.com/ros2/rclcpp/issues/2712>`_)
* apply actual QoS from rmw to the IPC publisher.
* address uncrustify warning.
---------
(cherry picked from commit 016cfeac99e4b67f58abdf247e57f05b85c09ec4)
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
* Adding in topic name to logging on IPC issues (`#2706 <https://github.com/ros2/rclcpp/issues/2706>`_) (`#2710 <https://github.com/ros2/rclcpp/issues/2710>`_)
* Adding in topic name to logging on IPC issues
* Update test matching output logging
* adding in single quotes
---------
(cherry picked from commit a13e16e2cbaeacb14ff31272d01cbb21bd8ac037)
Co-authored-by: Steve Macenski <stevenmacenski@gmail.com>
* enable testRaceConditionAddNode for rmw_connextdds. (`#2698 <https://github.com/ros2/rclcpp/issues/2698>`_)
* Re-enable executor test on rmw_connextdds. (`#2693 <https://github.com/ros2/rclcpp/issues/2693>`_) (`#2695 <https://github.com/ros2/rclcpp/issues/2695>`_)
It supports the events executor now, so re-enable the test.
(cherry picked from commit d7245365ed867db9b309ed3efbfb0391bda09bd5)
Co-authored-by: Chris Lalancette <clalancette@gmail.com>
* Fix warnings on Windows. (backport `#2692 <https://github.com/ros2/rclcpp/issues/2692>`_) (`#2694 <https://github.com/ros2/rclcpp/issues/2694>`_)
* Fix warnings on Windows. (`#2692 <https://github.com/ros2/rclcpp/issues/2692>`_)
For reasons I admit I do not understand, the deprecation
warnings for StaticSingleThreadedExecutor on Windows
happen when we construct a shared_ptr for it in the tests.
If we construct a regular object, then it is fine. Luckily
this test does not require a shared_ptr, so just make it
a regular object here, which rixes the warning.
While we are in here, make all of the tests camel case to
be consistent.
(cherry picked from commit 3310f9eaed967e0c18d17bb2f82d2def838bb7a5)
# Conflicts:
# rclcpp/test/rclcpp/executors/test_executors.cpp
* resolve backport conflict.
---------
Co-authored-by: Chris Lalancette <clalancette@gmail.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
* Omnibus fixes for running tests with Connext. (backport `#2684 <https://github.com/ros2/rclcpp/issues/2684>`_) (`#2690 <https://github.com/ros2/rclcpp/issues/2690>`_)
* Omnibus fixes for running tests with Connext. (`#2684 <https://github.com/ros2/rclcpp/issues/2684>`_)
* Omnibus fixes for running tests with Connext.
When running the tests with RTI Connext as the default
RMW, some of the tests are failing. There are three
different failures fixed here:
1. Setting the liveliness duration to a value smaller than
a microsecond causes Connext to throw an error. Set it to
a millisecond.
2. Using the SystemDefaultsQoS sets the QoS to KEEP_LAST 1.
Connext is somewhat slow in this regard, so it can be the case
that we are overwriting a previous service introspection event
with the next one. Switch to the ServicesDefaultQoS in the test,
which ensures we will not lose events.
3. Connext is slow to match publishers and subscriptions. Thus,
when creating a subscription "on-the-fly", we should wait for the
publisher to match it before expecting the subscription to actually
receive data from it.
With these fixes in place, the test_client_common, test_generic_service,
test_service_introspection, and test_executors tests all pass for
me with rmw_connextdds.
* Fixes for executors.
* One more fix for services.
* More fixes for service_introspection.
* More fixes for introspection.
---------
(cherry picked from commit 9984197c292d6c5ae0e7661aaea245ffb0fea057)
# Conflicts:
# rclcpp/test/rclcpp/executors/test_executors.cpp
# rclcpp/test/rclcpp/test_generic_service.cpp
* address backport merge conflicts.
---------
Co-authored-by: Chris Lalancette <clalancette@gmail.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
* fix(Executor): Fix segfault if callback group is deleted during rmw_wait (`#2682 <https://github.com/ros2/rclcpp/issues/2682>`_)
* Fix NodeOptions assignment operator (`#2656 <https://github.com/ros2/rclcpp/issues/2656>`_) (`#2660 <https://github.com/ros2/rclcpp/issues/2660>`_)
* Fix NodeOptions assignment operator
Also copy the enable_logger_service\_ member during the assignment operation
* Add more checks for NodeOptions copy test
* Set non default values by avoiding the copy-assignement
Co-authored-by: Christophe Bedard <bedard.christophe@gmail.com>
(cherry picked from commit 9b654942f99f17850e0e95480958abdbb508bc00)
Co-authored-by: Romain DESILLE <r.desille@gmail.com>
* set QoS History KEEP_ALL explicitly for statistics publisher. (`#2650 <https://github.com/ros2/rclcpp/issues/2650>`_) (`#2657 <https://github.com/ros2/rclcpp/issues/2657>`_)
* set QoS History KEEP_ALL explicitly for statistics publisher.
* test_subscription_options adjustment.
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
* Contributors: Cristóbal Arroyo, Tomoya Fujita, jmachowinski, mergify[bot]
28.1.5 (2024-09-19)
-------------------
* backport fix events-executor warm-up bug and add unit-tests (`#2591 <https://github.com/ros2/rclcpp/issues/2591>`_) (`#2628 <https://github.com/ros2/rclcpp/issues/2628>`_)
* Contributors: Alberto Soragna
28.1.4 (2024-09-06)
-------------------
* Split test_executors.cpp even further. (`#2572 <https://github.com/ros2/rclcpp/issues/2572>`_) (`#2619 <https://github.com/ros2/rclcpp/issues/2619>`_)
That's because it is too large for Windows Debug to compile,
so split into smaller bits.
Even with this split, the file is too big; that's likely
@@ -238,32 +204,70 @@ Changelog for package rclcpp
symbols per test case. To deal with this, without further
breaking up the file, also add in the /bigobj flag when
compiling on Windows Debug.
* avoid adding notify waitable twice to events-executor collection (`#2564 <https://github.com/ros2/rclcpp/issues/2564>`_)
* avoid adding notify waitable twice to events-executor entities collection
* remove redundant mutex lock
(cherry picked from commit c743c173e68d92af872cf163e10721a8dbe51dd0)
Co-authored-by: Chris Lalancette <clalancette@gmail.com>
* Correct node name in service test code (`#2615 <https://github.com/ros2/rclcpp/issues/2615>`_) (`#2616 <https://github.com/ros2/rclcpp/issues/2616>`_)
(cherry picked from commit e846f56224a39b93f1c609e7ee03fff0662b7453)
Co-authored-by: Barry Xu <barry.xu@sony.com>
* Release ownership of entities after spinning cancelled (backport `#2556 <https://github.com/ros2/rclcpp/issues/2556>`_) (`#2580 <https://github.com/ros2/rclcpp/issues/2580>`_)
* Release ownership of entities after spinning cancelled (`#2556 <https://github.com/ros2/rclcpp/issues/2556>`_)
* Release ownership of entities after spinning cancelled
* Move release action to every exit point in different spin functions
* Move wait_result\_.reset() before setting spinning to false
* Update test code
* Move test code to test_executors.cpp
---------
* Contributors: Alberto Soragna, Alejandro Hernández Cordero, Barry Xu, Chris Lalancette
(cherry picked from commit 069a0018935b33a14632a1cdf4074984a1cf80fe)
# Conflicts:
# rclcpp/test/rclcpp/executors/test_executors.cpp
* Fix backport issue (`#2581 <https://github.com/ros2/rclcpp/issues/2581>`_)
---------
Co-authored-by: Barry Xu <barry.xu@sony.com>
* Contributors: mergify[bot]
28.3.1 (2024-06-25)
28.1.3 (2024-06-27)
-------------------
* Remove unnecessary msg includes in tests (`#2566 <https://github.com/ros2/rclcpp/issues/2566>`_)
* Fix copy-paste errors in function docs (`#2565 <https://github.com/ros2/rclcpp/issues/2565>`_)
* Fix typo in function doc (`#2563 <https://github.com/ros2/rclcpp/issues/2563>`_)
* Contributors: Christophe Bedard
* Add test creating two content filter topics with the same topic name (`#2546 <https://github.com/ros2/rclcpp/issues/2546>`_) (`#2549 <https://github.com/ros2/rclcpp/issues/2549>`_) (`#2552 <https://github.com/ros2/rclcpp/issues/2552>`_)
Co-authored-by: Mario Domínguez López <116071334+Mario-DL@users.noreply.github.com>
(cherry picked from commit 7c096888caf92aa7557e1d3efc5448b56d8ce81c)
Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com>
* Contributors: mergify[bot]
28.3.0 (2024-06-17)
28.1.2 (2024-05-13)
-------------------
* Add test creating two content filter topics with the same topic name (`#2546 <https://github.com/ros2/rclcpp/issues/2546>`_) (`#2549 <https://github.com/ros2/rclcpp/issues/2549>`_)
* add impl pointer for ExecutorOptions (`#2523 <https://github.com/ros2/rclcpp/issues/2523>`_)
* Fixup Executor::spin_all() regression fix (`#2517 <https://github.com/ros2/rclcpp/issues/2517>`_)
* Add 'mimick' label to tests which use Mimick (`#2516 <https://github.com/ros2/rclcpp/issues/2516>`_)
* Contributors: Alejandro Hernández Cordero, Scott K Logan, William Woodall
* add impl pointer for ExecutorOptions (`#2523 <https://github.com/ros2/rclcpp/issues/2523>`_) (`#2525 <https://github.com/ros2/rclcpp/issues/2525>`_)
* add impl pointer for ExecutorOptions
(cherry picked from commit 343b29b617b163ad72b9fe3f6441dd4ed3d3af09)
Co-authored-by: William Woodall <william@osrfoundation.org>
* Fixup Executor::spin_all() regression fix (`#2517 <https://github.com/ros2/rclcpp/issues/2517>`_) (`#2521 <https://github.com/ros2/rclcpp/issues/2521>`_)
* test(Executors): Added tests for busy waiting
Checks if executors are busy waiting while they should block
in spin_some or spin_all.
* fix: Reworked spinAll test
This test was strange. It looked like, it assumed that spin_all did
not return instantly. Also it was racy, as the thread could terminate
instantly.
* fix(Executor): Fixed spin_all not returning instantly is no work was available
* Update rclcpp/test/rclcpp/executors/test_executors.cpp
* test(executors): Added test for busy waiting while calling spin
* fix(executor): Reset wait_result on every call to spin_some_impl
Before, the method would not recollect available work in case of
spin_some, spin_all. This would lead to the method behaving differently
than to what the documentation states.
* restore previous test logic for now
* refactor spin_some_impl's logic and improve busy wait tests
* added some more comments about the implementation
---------
Co-authored-by: Janosch Machowinski <J.Machowinski@cellumation.com>
Co-authored-by: jmachowinski <jmachowinski@users.noreply.github.com>
Co-authored-by: Tomoya Fujita <Tomoya.Fujita@sony.com>
Co-authored-by: William Woodall <william@osrfoundation.org>
* Contributors: mergify[bot]
28.2.0 (2024-04-26)
28.1.1 (2024-04-24)
-------------------
* Check for negative time in rclcpp::Time(int64_t nanoseconds, ...) constructor (`#2510 <https://github.com/ros2/rclcpp/issues/2510>`_)
* Revise the description of service configure_introspection() (`#2511 <https://github.com/ros2/rclcpp/issues/2511>`_)
* Contributors: Barry Xu, Sharmin Ramli
* Revise the description of service configure_introspection() (`#2511 <https://github.com/ros2/rclcpp/issues/2511>`_) (`#2513 <https://github.com/ros2/rclcpp/issues/2513>`_)
* Contributors: mergify[bot]
28.1.0 (2024-04-16)
-------------------

View File

@@ -70,13 +70,13 @@ 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
src/rclcpp/future_return_code.cpp
src/rclcpp/generic_client.cpp
src/rclcpp/generic_publisher.cpp
src/rclcpp/generic_service.cpp
src/rclcpp/generic_subscription.cpp
src/rclcpp/graph_listener.cpp
src/rclcpp/guard_condition.cpp
@@ -103,7 +103,6 @@ set(${PROJECT_NAME}_SRCS
src/rclcpp/node_options.cpp
src/rclcpp/parameter.cpp
src/rclcpp/parameter_client.cpp
src/rclcpp/parameter_descriptor_wrapper.cpp
src/rclcpp/parameter_event_handler.cpp
src/rclcpp/parameter_events_filter.cpp
src/rclcpp/parameter_map.cpp
@@ -147,6 +146,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)

View File

@@ -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=

View File

@@ -1,10 +1,10 @@
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/).
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).
# 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://reps.openrobotics.org/rep-2004/).
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).
## 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://reps.openrobotics.org/rep-2000/#support-tiers)
All pull requests must pass CI on all [tier 1 platforms](https://www.ros.org/reps/rep-2000.html#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://reps.openrobotics.org/rep-2000/#support-tiers), and tests each change against all of them.
`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.
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://reps.openrobotics.org/rep-2006/).
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://www.ros.org/reps/rep-2006.html).

View File

@@ -434,3 +434,4 @@
- (tfoote) There should be no jumps in steady time. If there's a big change in system time, it doesn't necessarily mean that time jumped, just that you might have been sleeping for a long time. Most ntp systems adjust the slew rate these days instead of jumping but still that's an external process and I don't know of any APIs to introspect the state of the clock. I'm not sure that we have a way to detect jumps in time for system or steady time. To that end I think that we should be clear that we only provide callbacks when simulation time starts or stops, or simulation time jumps. We should also strongly recommend that operators not actively adjust their system clocks while running ROS nodes.
- (jacobperron) I agree with Tully, if we don't have a way to detect system time jumps then I think we should just document that this only works with ROS time. In addition to documentation, we could log an info or warning message if the user registers jump callback with steady or system time, but it may be unnecessarily noisy.

View File

@@ -2,15 +2,15 @@
## Introduction:
The original requirement came in **gazebo_ros_pkgs** for setting individual wheel slip parameters based on global wheel slip value [link to original issue](https://github.com/ros-simulation/gazebo_ros_pkgs/pull/1365).
The original requirement came in **gazebo_ros_pkgs** for setting individual wheel slip parameters based on global wheel slip value [link to original issue](https://github.com/ros-simulation/gazebo_ros_pkgs/pull/1365).
The main requirement is to set one or more parameters after another parameter is set successfully.
The main requirement is to set one or more parameters after another parameter is set successfully.
Additionally, it would be nice if users could be notified locally (via a callback) when parameters have been set successfully (i.e. post validation).
Related discussion can be found in [#609](https://github.com/ros2/rclcpp/issues/609) [#1789](https://github.com/ros2/rclcpp/pull/1789)
With the current parameters API, the `add_on_set_parameters_callback` is intended for validation of parameter values before they are set, it should **not** cause any side-effects.
With the current parameters API, the `add_on_set_parameters_callback` is intended for validation of parameter values before they are set, it should **not** cause any side-effects.
There is also the `ParameterEventHandler` that publishes changes to node parameters on `/parameter_events` topic for external nodes to see. Though the node could subscribe to the `/parameter_events` topic to be notified of changes to its own parameters, it is less than ideal since there is a delay caused by waiting for an executor to process the callback.
@@ -19,11 +19,11 @@ We propose adding a `PostSetParametersCallbackHandle` for successful parameter s
The validation callback is often abused to trigger side effects in the code, for instance updating class attributes even before a parameter has been set successfully. Instead of relying on the `/parameter_events` topic to be notified of parameter changes, users can register a callback with a new API, `add_post_set_parameters_callback`.
It is possible to use the proposed `add_post_set_parameters_callback` for setting additional parameters, but this might result in infinite recursion and does not allow those additional parameters to be set atomically with the original parameter(s) changed.
To workaround these issues, we propose adding a "pre set" callback type that can be registered with `add_pre_set_parameters_callback`, which will be triggered before the validation callbacks and can be used to modify the parameter list.
To workaround these issues, we propose adding a "pre set" callback type that can be registered with `add_pre_set_parameters_callback`, which will be triggered before the validation callbacks and can be used to modify the parameter list.
![Desgin API](https://github.com/ros2/rclcpp/blob/deepanshu/local-param-changed-callback-support/rclcpp/doc/param_callback_design.png?raw=true)
## Alternatives
* Users could call `set_parameter` while processing a message from the `/parameter_events` topic, however, there is extra overhead in having to create subscription (as noted earlier).
* Users could call `set_parameter` inside the "on set" parameters callback, however it is not well-defined how side-effects should handle cases where parameter validation fails.
* Users could call `set_parameter` inside the "on set" parameters callback, however it is not well-defined how side-effects should handle cases where parameter validation fails.

View File

@@ -27,39 +27,10 @@ namespace rclcpp
namespace allocator
{
template<typename T>
using clean_t = std::remove_cv_t<std::remove_reference_t<T>>;
// Primary template: false
template<typename, typename = std::void_t<>>
struct has_get_rcl_allocator : std::false_type {};
// Specialization: true if expression is valid
template<typename T>
struct has_get_rcl_allocator<T,
std::void_t<
decltype(std::declval<clean_t<T> &>().get_rcl_allocator())
>
>
: std::bool_constant<
std::is_same_v<
decltype(std::declval<clean_t<T> &>().get_rcl_allocator()),
rcl_allocator_t
>
>
{};
// Helper variable template
template<typename T>
inline constexpr bool has_get_rcl_allocator_v =
has_get_rcl_allocator<T>::value;
template<typename T, typename Alloc>
using AllocRebind = typename std::allocator_traits<Alloc>::template rebind_traits<T>;
template<typename Alloc>
[[deprecated("Conversion of C++ allocators to C style is not valid, as the size on deallocate"
"can not be determined. This will be remove in future versions of ros.")]]
void * retyped_allocate(size_t size, void * untyped_allocator)
{
auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
@@ -70,8 +41,6 @@ void * retyped_allocate(size_t size, void * untyped_allocator)
}
template<typename Alloc>
[[deprecated("Conversion of C++ allocators to C style is not valid, as the size on deallocate"
"can not be determined. This will be remove in future versions of ros.")]]
void * retyped_zero_allocate(size_t number_of_elem, size_t size_of_elem, void * untyped_allocator)
{
auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
@@ -88,8 +57,6 @@ void * retyped_zero_allocate(size_t number_of_elem, size_t size_of_elem, void *
}
template<typename T, typename Alloc>
[[deprecated("Conversion of C++ allocators to C style is not valid, as the size on deallocate"
"can not be determined. This will be remove in future versions of ros.")]]
void retyped_deallocate(void * untyped_pointer, void * untyped_allocator)
{
auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
@@ -101,8 +68,6 @@ void retyped_deallocate(void * untyped_pointer, void * untyped_allocator)
}
template<typename T, typename Alloc>
[[deprecated("Conversion of C++ allocators to C style is not valid, as the size on deallocate"
"can not be determined. This will be remove in future versions of ros.")]]
void * retyped_reallocate(void * untyped_pointer, size_t size, void * untyped_allocator)
{
auto typed_allocator = static_cast<Alloc *>(untyped_allocator);
@@ -120,9 +85,6 @@ template<
typename T,
typename Alloc,
typename std::enable_if<!std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
[[deprecated("Conversion of C++ allocators to C style is not valid, as the size on deallocate"
"can not be determined. This will be remove in future versions of ros. To suppress this warning"
"define the method 'rcl_allocator_t get_rcl_allocator()' on your allocator")]]
rcl_allocator_t get_rcl_allocator(Alloc & allocator)
{
rcl_allocator_t rcl_allocator = rcl_get_default_allocator();

View File

@@ -69,17 +69,18 @@ private:
};
template<typename Alloc, typename T, typename D>
void set_allocator_for_deleter([[maybe_unused]] D * deleter, [[maybe_unused]] Alloc * alloc)
void set_allocator_for_deleter(D * deleter, Alloc * alloc)
{
(void) alloc;
(void) deleter;
throw std::runtime_error("Reached unexpected template specialization");
}
template<typename T, typename U>
void set_allocator_for_deleter(
[[maybe_unused]] std::default_delete<T> * deleter,
[[maybe_unused]] std::allocator<U> * alloc)
void set_allocator_for_deleter(std::default_delete<T> * deleter, std::allocator<U> * alloc)
{
// This function is intentionally left empty.
(void) deleter;
(void) alloc;
}
template<typename Alloc, typename T>

View File

@@ -165,13 +165,11 @@ public:
if (std::holds_alternative<SharedPtrDeferResponseCallback>(callback_)) {
const auto & cb = std::get<SharedPtrDeferResponseCallback>(callback_);
cb(request_header, std::move(request));
TRACETOOLS_TRACEPOINT(callback_end, static_cast<const void *>(this));
return nullptr;
}
if (std::holds_alternative<SharedPtrDeferResponseCallbackWithServiceHandle>(callback_)) {
const auto & cb = std::get<SharedPtrDeferResponseCallbackWithServiceHandle>(callback_);
cb(service_handle, request_header, std::move(request));
TRACETOOLS_TRACEPOINT(callback_end, static_cast<const void *>(this));
return nullptr;
}
// auto response = allocate_shared<typename ServiceT::Response, Allocator>();

View File

@@ -15,10 +15,8 @@
#ifndef RCLCPP__ANY_SUBSCRIPTION_CALLBACK_HPP_
#define RCLCPP__ANY_SUBSCRIPTION_CALLBACK_HPP_
#include <atomic>
#include <functional>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <type_traits>
#include <utility>
@@ -377,19 +375,7 @@ public:
allocator::set_allocator_for_deleter(&ros_message_type_deleter_, &ros_message_type_allocator_);
}
AnySubscriptionCallback(const AnySubscriptionCallback & other)
: callback_variant_(other.callback_variant_),
callback_disabled_(other.callback_disabled_.load()),
subscribed_type_allocator_(other.subscribed_type_allocator_),
subscribed_type_deleter_(other.subscribed_type_deleter_),
ros_message_type_allocator_(other.ros_message_type_allocator_),
ros_message_type_deleter_(other.ros_message_type_deleter_),
serialized_message_allocator_(other.serialized_message_allocator_),
serialized_message_deleter_(other.serialized_message_deleter_)
{
allocator::set_allocator_for_deleter(&subscribed_type_deleter_, &subscribed_type_allocator_);
allocator::set_allocator_for_deleter(&ros_message_type_deleter_, &ros_message_type_allocator_);
}
AnySubscriptionCallback(const AnySubscriptionCallback &) = default;
/// Generic function for setting the callback.
/**
@@ -407,91 +393,12 @@ public:
// converted to one another, e.g. shared_ptr and unique_ptr.
using scbth = detail::SubscriptionCallbackTypeHelper<MessageT, CallbackT>;
// Determine if the given CallbackT is a deprecated signature or not.
constexpr auto is_deprecated =
rclcpp::function_traits::same_arguments<
typename scbth::callback_type,
std::function<void(std::shared_ptr<SubscribedType>)>
>::value ||
rclcpp::function_traits::same_arguments<
typename scbth::callback_type,
std::function<void(std::shared_ptr<SubscribedType>, const rclcpp::MessageInfo &)>
>::value ||
rclcpp::function_traits::same_arguments<
typename scbth::callback_type,
std::function<void(std::shared_ptr<ROSMessageType>)>
>::value ||
rclcpp::function_traits::same_arguments<
typename scbth::callback_type,
std::function<void(std::shared_ptr<ROSMessageType>, const rclcpp::MessageInfo &)>
>::value ||
rclcpp::function_traits::same_arguments<
typename scbth::callback_type,
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)>
>::value ||
rclcpp::function_traits::same_arguments<
typename scbth::callback_type,
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>, const rclcpp::MessageInfo &)>
>::value;
// Use the discovered type to force the type of callback when assigning
// into the variant.
if constexpr (is_deprecated) {
// If deprecated, call sub-routine that is deprecated.
set_deprecated(static_cast<typename scbth::callback_type>(callback));
} else {
// Otherwise just assign it.
callback_variant_ = static_cast<typename scbth::callback_type>(callback);
}
callback_variant_ = static_cast<typename scbth::callback_type>(callback);
// Return copy of self for easier testing, normally will be compiled out.
return *this;
}
/// Function for shared_ptr to non-const MessageT, which is deprecated.
template<typename SetT>
// *INDENT-OFF*
#if !defined(RCLCPP_AVOID_DEPRECATIONS_FOR_UNIT_TESTS)
// suppress deprecation warnings in `test_any_subscription_callback.cpp`
[[deprecated("use 'void(std::shared_ptr<const MessageT>)' instead")]]
#endif
// *INDENT-ON*
void
set_deprecated(std::function<void(std::shared_ptr<SetT>)> callback)
{
callback_variant_ = callback;
}
/// Function for shared_ptr to non-const MessageT with MessageInfo, which is deprecated.
template<typename SetT>
// *INDENT-OFF*
#if !defined(RCLCPP_AVOID_DEPRECATIONS_FOR_UNIT_TESTS)
// suppress deprecation warnings in `test_any_subscription_callback.cpp`
[[deprecated(
"use 'void(std::shared_ptr<const MessageT>, const rclcpp::MessageInfo &)' instead"
)]]
#endif
// *INDENT-ON*
void
set_deprecated(std::function<void(std::shared_ptr<SetT>, const rclcpp::MessageInfo &)> callback)
{
callback_variant_ = callback;
}
/// Disable the callback from being called during dispatch.
void disable()
{
std::unique_lock<std::recursive_mutex> callback_lock(callback_mutex_);
callback_disabled_.store(true);
}
/// Enable the callback to be called during dispatch.
void enable()
{
std::unique_lock<std::recursive_mutex> callback_lock(callback_mutex_);
callback_disabled_.store(false);
}
std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>
create_ros_unique_ptr_from_ros_shared_ptr_message(
const std::shared_ptr<const ROSMessageType> & message)
@@ -562,10 +469,6 @@ public:
std::shared_ptr<ROSMessageType> message,
const rclcpp::MessageInfo & message_info)
{
std::unique_lock<std::recursive_mutex> callback_lock(callback_mutex_);
if (callback_disabled_.load()) {
return;
}
TRACETOOLS_TRACEPOINT(callback_start, static_cast<const void *>(this), false);
// Check if the variant is "unset", throw if it is.
if (callback_variant_.index() == 0) {
@@ -666,10 +569,6 @@ public:
std::shared_ptr<const rclcpp::SerializedMessage> serialized_message,
const rclcpp::MessageInfo & message_info)
{
std::unique_lock<std::recursive_mutex> callback_lock(callback_mutex_);
if (callback_disabled_.load()) {
return;
}
TRACETOOLS_TRACEPOINT(callback_start, static_cast<const void *>(this), false);
// Check if the variant is "unset", throw if it is.
if (callback_variant_.index() == 0) {
@@ -749,10 +648,6 @@ public:
std::shared_ptr<const SubscribedType> message,
const rclcpp::MessageInfo & message_info)
{
std::unique_lock<std::recursive_mutex> callback_lock(callback_mutex_);
if (callback_disabled_.load()) {
return;
}
TRACETOOLS_TRACEPOINT(callback_start, static_cast<const void *>(this), true);
// Check if the variant is "unset", throw if it is.
if (callback_variant_.index() == 0) {
@@ -883,10 +778,6 @@ public:
std::unique_ptr<SubscribedType, SubscribedTypeDeleter> message,
const rclcpp::MessageInfo & message_info)
{
std::unique_lock<std::recursive_mutex> callback_lock(callback_mutex_);
if (callback_disabled_.load()) {
return;
}
TRACETOOLS_TRACEPOINT(callback_start, static_cast<const void *>(this), true);
// Check if the variant is "unset", throw if it is.
if (callback_variant_.index() == 0) {
@@ -1081,8 +972,6 @@ private:
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2162r0.html
// For now, compose the variant into this class as a private attribute.
typename HelperT::variant_type callback_variant_;
std::recursive_mutex callback_mutex_;
std::atomic_bool callback_disabled_{false};
SubscribedTypeAllocator subscribed_type_allocator_;
SubscribedTypeDeleter subscribed_type_deleter_;

View File

@@ -59,6 +59,46 @@ class CallbackGroup
public:
RCLCPP_SMART_PTR_DEFINITIONS(CallbackGroup)
/// Constructor for CallbackGroup.
/**
* Callback Groups have a type, either 'Mutually Exclusive' or 'Reentrant'
* and when creating one the type must be specified.
*
* Callbacks in Reentrant Callback Groups must be able to:
* - run at the same time as themselves (reentrant)
* - run at the same time as other callbacks in their group
* - run at the same time as other callbacks in other groups
*
* Callbacks in Mutually Exclusive Callback Groups:
* - will not be run multiple times simultaneously (non-reentrant)
* - will not be run at the same time as other callbacks in their group
* - but must run at the same time as callbacks in other groups
*
* Additionally, callback groups have a property which determines whether or
* not they are added to an executor with their associated node automatically.
* When creating a callback group the automatically_add_to_executor_with_node
* argument determines this behavior, and if true it will cause the newly
* created callback group to be added to an executor with the node when the
* Executor::add_node method is used.
* If false, this callback group will not be added automatically and would
* have to be added to an executor manually using the
* Executor::add_callback_group method.
*
* Whether the node was added to the executor before creating the callback
* group, or after, is irrelevant; the callback group will be automatically
* added to the executor in either case.
*
* \param[in] group_type The type of the callback group.
* \param[in] automatically_add_to_executor_with_node A boolean that
* determines whether a callback group is automatically added to an executor
* with the node with which it is associated.
*/
[[deprecated("Use CallbackGroup constructor with context function argument")]]
RCLCPP_PUBLIC
explicit CallbackGroup(
CallbackGroupType group_type,
bool automatically_add_to_executor_with_node = true);
/// Constructor for CallbackGroup.
/**
* Callback Groups have a type, either 'Mutually Exclusive' or 'Reentrant'
@@ -97,7 +137,7 @@ public:
RCLCPP_PUBLIC
explicit CallbackGroup(
CallbackGroupType group_type,
const rclcpp::Context::WeakPtr & context,
rclcpp::Context::WeakPtr context,
bool automatically_add_to_executor_with_node = true);
/// Default destructor.
@@ -106,35 +146,35 @@ public:
template<typename Function>
rclcpp::SubscriptionBase::SharedPtr
find_subscription_ptrs_if(const Function & func) const
find_subscription_ptrs_if(Function func) const
{
return _find_ptrs_if_impl<rclcpp::SubscriptionBase, Function>(func, subscription_ptrs_);
}
template<typename Function>
rclcpp::TimerBase::SharedPtr
find_timer_ptrs_if(const Function & func) const
find_timer_ptrs_if(Function func) const
{
return _find_ptrs_if_impl<rclcpp::TimerBase, Function>(func, timer_ptrs_);
}
template<typename Function>
rclcpp::ServiceBase::SharedPtr
find_service_ptrs_if(const Function & func) const
find_service_ptrs_if(Function func) const
{
return _find_ptrs_if_impl<rclcpp::ServiceBase, Function>(func, service_ptrs_);
}
template<typename Function>
rclcpp::ClientBase::SharedPtr
find_client_ptrs_if(const Function & func) const
find_client_ptrs_if(Function func) const
{
return _find_ptrs_if_impl<rclcpp::ClientBase, Function>(func, client_ptrs_);
}
template<typename Function>
rclcpp::Waitable::SharedPtr
find_waitable_ptrs_if(const Function & func) const
find_waitable_ptrs_if(Function func) const
{
return _find_ptrs_if_impl<rclcpp::Waitable, Function>(func, waitable_ptrs_);
}
@@ -179,11 +219,11 @@ public:
RCLCPP_PUBLIC
void
collect_all_ptrs(
const std::function<void(const rclcpp::SubscriptionBase::SharedPtr &)> & sub_func,
const std::function<void(const rclcpp::ServiceBase::SharedPtr &)> & service_func,
const std::function<void(const rclcpp::ClientBase::SharedPtr &)> & client_func,
const std::function<void(const rclcpp::TimerBase::SharedPtr &)> & timer_func,
const std::function<void(const rclcpp::Waitable::SharedPtr &)> & waitable_func) const;
std::function<void(const rclcpp::SubscriptionBase::SharedPtr &)> sub_func,
std::function<void(const rclcpp::ServiceBase::SharedPtr &)> service_func,
std::function<void(const rclcpp::ClientBase::SharedPtr &)> client_func,
std::function<void(const rclcpp::TimerBase::SharedPtr &)> timer_func,
std::function<void(const rclcpp::Waitable::SharedPtr &)> waitable_func) const;
/// Return a reference to the 'associated with executor' atomic boolean.
/**
@@ -228,31 +268,31 @@ protected:
RCLCPP_PUBLIC
void
add_publisher(const rclcpp::PublisherBase::SharedPtr & publisher_ptr);
add_publisher(const rclcpp::PublisherBase::SharedPtr publisher_ptr);
RCLCPP_PUBLIC
void
add_subscription(const rclcpp::SubscriptionBase::SharedPtr & subscription_ptr);
add_subscription(const rclcpp::SubscriptionBase::SharedPtr subscription_ptr);
RCLCPP_PUBLIC
void
add_timer(const rclcpp::TimerBase::SharedPtr & timer_ptr);
add_timer(const rclcpp::TimerBase::SharedPtr timer_ptr);
RCLCPP_PUBLIC
void
add_service(const rclcpp::ServiceBase::SharedPtr & service_ptr);
add_service(const rclcpp::ServiceBase::SharedPtr service_ptr);
RCLCPP_PUBLIC
void
add_client(const rclcpp::ClientBase::SharedPtr & client_ptr);
add_client(const rclcpp::ClientBase::SharedPtr client_ptr);
RCLCPP_PUBLIC
void
add_waitable(const rclcpp::Waitable::SharedPtr & waitable_ptr);
add_waitable(const rclcpp::Waitable::SharedPtr waitable_ptr);
RCLCPP_PUBLIC
void
remove_waitable(const rclcpp::Waitable::SharedPtr & waitable_ptr) noexcept;
remove_waitable(const rclcpp::Waitable::SharedPtr waitable_ptr) noexcept;
CallbackGroupType type_;
// Mutex to protect the subsequent vectors of pointers.
@@ -274,7 +314,7 @@ protected:
private:
template<typename TypeT, typename Function>
typename TypeT::SharedPtr _find_ptrs_if_impl(
const Function & func, const std::vector<typename TypeT::WeakPtr> & vect_ptrs) const
Function func, const std::vector<typename TypeT::WeakPtr> & vect_ptrs) const
{
std::lock_guard<std::mutex> lock(mutex_);
for (auto & weak_ptr : vect_ptrs) {

View File

@@ -70,6 +70,14 @@ struct FutureAndRequestId
/// Allow implicit conversions to `std::future` by reference.
operator FutureT &() {return this->future;}
/// Deprecated, use the `future` member variable instead.
/**
* Allow implicit conversions to `std::future` by value.
* \deprecated
*/
[[deprecated("FutureAndRequestId: use .future instead of an implicit conversion")]]
operator FutureT() {return this->future;}
// delegate future like methods in the std::future impl_
/// See std::future::get().
@@ -145,7 +153,7 @@ public:
RCLCPP_PUBLIC
ClientBase(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr & node_graph);
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph);
RCLCPP_PUBLIC
virtual ~ClientBase() = default;
@@ -221,8 +229,7 @@ public:
virtual std::shared_ptr<void> create_response() = 0;
virtual std::shared_ptr<rmw_request_id_t> create_request_header() = 0;
virtual void handle_response(
const std::shared_ptr<rmw_request_id_t> & request_header,
const std::shared_ptr<void> & response) = 0;
std::shared_ptr<rmw_request_id_t> request_header, std::shared_ptr<void> response) = 0;
/// Exchange the "in use by wait set" state for this client.
/**
@@ -297,7 +304,7 @@ public:
* \param[in] callback functor to be called when a new response is received
*/
void
set_on_new_response_callback(const std::function<void(size_t)> & callback)
set_on_new_response_callback(std::function<void(size_t)> callback)
{
if (!callback) {
throw std::invalid_argument(
@@ -429,6 +436,15 @@ public:
{
using detail::FutureAndRequestId<std::future<SharedResponse>>::FutureAndRequestId;
/// Deprecated, use `.future.share()` instead.
/**
* Allow implicit conversions to `std::shared_future` by value.
* \deprecated
*/
[[deprecated(
"FutureAndRequestId: use .future.share() instead of an implicit conversion")]]
operator SharedFuture() {return this->future.share();}
// delegate future like methods in the std::future impl_
/// See std::future::share().
@@ -474,11 +490,11 @@ public:
* \param[in] node_base NodeBaseInterface pointer that is used in part of the setup.
* \param[in] node_graph The node graph interface of the corresponding node.
* \param[in] service_name Name of the topic to publish to.
* \param[in] client_options options for the client.
* \param[in] client_options options for the subscription.
*/
Client(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr & node_graph,
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
const std::string & service_name,
rcl_client_options_t & client_options)
: ClientBase(node_base, node_graph),
@@ -557,8 +573,8 @@ public:
*/
void
handle_response(
const std::shared_ptr<rmw_request_id_t> & request_header,
const std::shared_ptr<void> & response) override
std::shared_ptr<rmw_request_id_t> request_header,
std::shared_ptr<void> response) override
{
std::optional<CallbackInfoVariant>
optional_pending_request = this->get_and_erase_pending_request(request_header->sequence_number);
@@ -567,7 +583,7 @@ public:
}
auto & value = *optional_pending_request;
auto typed_response = std::static_pointer_cast<typename ServiceT::Response>(
response);
std::move(response));
if (std::holds_alternative<Promise>(value)) {
auto & promise = std::get<Promise>(value);
promise.set_value(std::move(typed_response));
@@ -618,7 +634,7 @@ public:
* \return a FutureAndRequestId instance.
*/
FutureAndRequestId
async_send_request(const SharedRequest & request)
async_send_request(SharedRequest request)
{
Promise promise;
auto future = promise.get_future();
@@ -653,7 +669,7 @@ public:
>::type * = nullptr
>
SharedFutureAndRequestId
async_send_request(const SharedRequest & request, CallbackT && cb)
async_send_request(SharedRequest request, CallbackT && cb)
{
Promise promise;
auto shared_future = promise.get_future().share();
@@ -684,7 +700,7 @@ public:
>::type * = nullptr
>
SharedFutureWithRequestAndRequestId
async_send_request(const SharedRequest & request, CallbackT && cb)
async_send_request(SharedRequest request, CallbackT && cb)
{
PromiseWithRequest promise;
auto shared_future = promise.get_future().share();
@@ -790,13 +806,10 @@ public:
* \param[in] clock clock to use to generate introspection timestamps
* \param[in] qos_service_event_pub QoS settings to use when creating the introspection publisher
* \param[in] introspection_state the state to set introspection to
*
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw if
* it failed to configure introspection.
*/
void
configure_introspection(
const Clock::SharedPtr & clock, const QoS & qos_service_event_pub,
Clock::SharedPtr clock, const QoS & qos_service_event_pub,
rcl_service_introspection_state_t introspection_state)
{
rcl_publisher_options_t pub_opts = rcl_publisher_get_default_options();

View File

@@ -117,8 +117,8 @@ public:
RCLCPP_PUBLIC
bool
sleep_until(
const Time & until,
const Context::SharedPtr & context = contexts::get_global_default_context());
Time until,
Context::SharedPtr context = contexts::get_global_default_context());
/**
* Sleep for a specified Duration.
@@ -141,8 +141,8 @@ public:
RCLCPP_PUBLIC
bool
sleep_for(
const Duration & rel_time,
const Context::SharedPtr & context = contexts::get_global_default_context());
Duration rel_time,
Context::SharedPtr context = contexts::get_global_default_context());
/**
* Check if the clock is started.
@@ -168,7 +168,7 @@ public:
*/
RCLCPP_PUBLIC
bool
wait_until_started(const Context::SharedPtr & context = contexts::get_global_default_context());
wait_until_started(Context::SharedPtr context = contexts::get_global_default_context());
/**
* Wait for clock to start, with timeout.
@@ -186,7 +186,7 @@ public:
bool
wait_until_started(
const rclcpp::Duration & timeout,
const Context::SharedPtr & context = contexts::get_global_default_context(),
Context::SharedPtr context = contexts::get_global_default_context(),
const rclcpp::Duration & wait_tick_ns = rclcpp::Duration(0, static_cast<uint32_t>(1e7)));
/**
@@ -200,6 +200,16 @@ public:
bool
ros_time_is_active();
/**
* 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.
*/
RCLCPP_PUBLIC
void
cancel_sleep_or_wait();
/// Return the rcl_clock_t clock handle
RCLCPP_PUBLIC
rcl_clock_t *
@@ -214,13 +224,13 @@ public:
std::mutex &
get_clock_mutex() noexcept;
/// Add a callback to invoke if the jump threshold is exceeded.
// Add a callback to invoke if the jump threshold is exceeded.
/**
* These callback functions must remain valid as long as the
* returned shared pointer is valid.
*
* Function will register callbacks to the callback queue. On time jump all
* callbacks will be executed whose threshold is greater than the time jump;
* callbacks will be executed whose threshold is greater then the time jump;
* The logic will first call selected pre_callbacks and then all selected
* post_callbacks.
*
@@ -229,7 +239,7 @@ public:
* \param pre_callback Must be non-throwing
* \param post_callback Must be non-throwing.
* \param threshold Callbacks will be triggered if the time jump is greater
* than the threshold.
* then the threshold.
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
* \throws std::bad_alloc if the allocation of the JumpHandler fails.
* \warning the instance of the clock must remain valid as long as any created
@@ -238,8 +248,8 @@ public:
RCLCPP_PUBLIC
JumpHandler::SharedPtr
create_jump_callback(
const JumpHandler::pre_callback_t & pre_callback,
const JumpHandler::post_callback_t & post_callback,
JumpHandler::pre_callback_t pre_callback,
JumpHandler::post_callback_t post_callback,
const rcl_jump_threshold_t & threshold);
private:
@@ -327,7 +337,7 @@ public:
RCLCPP_PUBLIC
ClockConditionalVariable(
const rclcpp::Clock::SharedPtr & clock,
const rclcpp::Context::SharedPtr & context = rclcpp::contexts::get_global_default_context());
rclcpp::Context::SharedPtr context = rclcpp::contexts::get_global_default_context());
RCLCPP_PUBLIC
~ClockConditionalVariable();
@@ -347,7 +357,7 @@ public:
RCLCPP_PUBLIC
bool
wait_until(
std::unique_lock<std::mutex> & lock, const rclcpp::Time & until,
std::unique_lock<std::mutex> & lock, rclcpp::Time until,
const std::function<bool ()> & pred);
/**

View File

@@ -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
@@ -229,7 +225,7 @@ public:
RCLCPP_PUBLIC
virtual
OnShutdownCallback
on_shutdown(const OnShutdownCallback & callback);
on_shutdown(OnShutdownCallback callback);
/// Add a on_shutdown callback to be called when shutdown is called for this context.
/**
@@ -253,7 +249,7 @@ public:
RCLCPP_PUBLIC
virtual
OnShutdownCallbackHandle
add_on_shutdown_callback(const OnShutdownCallback & callback);
add_on_shutdown_callback(OnShutdownCallback callback);
/// Remove an registered on_shutdown callbacks.
/**
@@ -280,7 +276,7 @@ public:
RCLCPP_PUBLIC
virtual
PreShutdownCallbackHandle
add_pre_shutdown_callback(const PreShutdownCallback & callback);
add_pre_shutdown_callback(PreShutdownCallback callback);
/// Remove an registered pre_shutdown callback.
/**
@@ -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_;
@@ -417,7 +406,7 @@ private:
RCLCPP_LOCAL
ShutdownCallbackHandle
add_shutdown_callback(
const ShutdownCallback & callback);
ShutdownCallback callback);
template<ShutdownType shutdown_type>
RCLCPP_LOCAL

View File

@@ -47,9 +47,28 @@ create_client(
const std::string & service_name,
const rclcpp::QoS & qos = rclcpp::ServicesQoS(),
rclcpp::CallbackGroup::SharedPtr group = nullptr)
{
return create_client<ServiceT>(
node_base, node_graph, node_services,
service_name,
qos.get_rmw_qos_profile(),
group);
}
/// Create a service client with a given type.
/// \internal
template<typename ServiceT>
typename rclcpp::Client<ServiceT>::SharedPtr
create_client(
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
std::shared_ptr<node_interfaces::NodeGraphInterface> node_graph,
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
const std::string & service_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::CallbackGroup::SharedPtr group)
{
rcl_client_options_t options = rcl_client_get_default_options();
options.qos = qos.get_rmw_qos_profile();
options.qos = qos_profile;
auto cli = rclcpp::Client<ServiceT>::make_shared(
node_base.get(),
@@ -61,6 +80,7 @@ create_client(
node_services->add_client(cli_base_ptr, group);
return cli;
}
} // namespace rclcpp
#endif // RCLCPP__CREATE_CLIENT_HPP_

View File

@@ -46,13 +46,13 @@ namespace rclcpp
RCLCPP_PUBLIC
rclcpp::GenericClient::SharedPtr
create_generic_client(
const std::shared_ptr<node_interfaces::NodeBaseInterface> & node_base,
const std::shared_ptr<node_interfaces::NodeGraphInterface> & node_graph,
const std::shared_ptr<node_interfaces::NodeServicesInterface> & node_services,
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
std::shared_ptr<node_interfaces::NodeGraphInterface> node_graph,
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
const std::string & service_name,
const std::string & service_type,
const rclcpp::QoS & qos = rclcpp::ServicesQoS(),
const rclcpp::CallbackGroup::SharedPtr & group = rclcpp::CallbackGroup::SharedPtr());
rclcpp::CallbackGroup::SharedPtr group = nullptr);
/// Create a generic service client with a name of given type.
/**

View File

@@ -1,102 +0,0 @@
// Copyright 2024 Sony Group Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__CREATE_GENERIC_SERVICE_HPP_
#define RCLCPP__CREATE_GENERIC_SERVICE_HPP_
#include <memory>
#include <string>
#include <utility>
#include "rclcpp/generic_service.hpp"
#include "rclcpp/node_interfaces/get_node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/get_node_services_interface.hpp"
#include "rclcpp/node_interfaces/node_services_interface.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rmw/rmw.h"
namespace rclcpp
{
/// Create a generic service with a given type.
/**
* \param[in] node_base NodeBaseInterface implementation of the node on which
* to create the generic service.
* \param[in] node_services NodeServicesInterface implementation of the node on
* which to create the service.
* \param[in] service_name The name on which the service is accessible.
* \param[in] service_type The name of service type, e.g. "std_srvs/srv/SetBool".
* \param[in] callback The callback to call when the service gets a request.
* \param[in] qos Quality of service profile for the service.
* \param[in] group Callback group to handle the reply to service calls.
* \return Shared pointer to the created service.
*/
template<typename CallbackT>
typename rclcpp::GenericService::SharedPtr
create_generic_service(
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
const std::string & service_name,
const std::string & service_type,
CallbackT && callback,
const rclcpp::QoS & qos,
rclcpp::CallbackGroup::SharedPtr group)
{
rclcpp::GenericServiceCallback any_service_callback;
any_service_callback.set(std::forward<CallbackT>(callback));
rcl_service_options_t service_options = rcl_service_get_default_options();
service_options.qos = qos.get_rmw_qos_profile();
auto serv = GenericService::make_shared(
node_base->get_shared_rcl_node_handle(),
service_name, service_type, any_service_callback, service_options);
auto serv_base_ptr = std::dynamic_pointer_cast<ServiceBase>(serv);
node_services->add_service(serv_base_ptr, group);
return serv;
}
/// Create a generic service with a given type.
/**
* The NodeT type needs to have NodeBaseInterface implementation and NodeServicesInterface
* implementation of the node which to create the generic service.
*
* \param[in] node The node on which to create the generic service.
* \param[in] service_name The name on which the service is accessible.
* \param[in] service_type The name of service type, e.g. "std_srvs/srv/SetBool".
* \param[in] callback The callback to call when the service gets a request.
* \param[in] qos Quality of service profile for the service.
* \param[in] group Callback group to handle the reply to service calls.
* \return Shared pointer to the created service.
*/
template<typename NodeT, typename CallbackT>
typename rclcpp::GenericService::SharedPtr
create_generic_service(
NodeT node,
const std::string & service_name,
const std::string & service_type,
CallbackT && callback,
const rclcpp::QoS & qos,
rclcpp::CallbackGroup::SharedPtr group)
{
return create_generic_service<CallbackT>(
rclcpp::node_interfaces::get_node_base_interface(node),
rclcpp::node_interfaces::get_node_services_interface(node),
service_name,
service_type,
std::forward<CallbackT>(callback), qos.get_rmw_qos_profile(), group);
}
} // namespace rclcpp
#endif // RCLCPP__CREATE_GENERIC_SERVICE_HPP_

View File

@@ -97,9 +97,6 @@ declare_parameter_or_get(
rcl_interfaces::msg::ParameterDescriptor descriptor)
{
try {
// enable parameter modification to make it possible
// to declare QoS override parameters during parameter callbacks.
parameters_interface.enable_parameter_modification();
return parameters_interface.declare_parameter(
param_name, param_value, descriptor);
} catch (const rclcpp::exceptions::ParameterAlreadyDeclaredException &) {
@@ -270,8 +267,8 @@ apply_qos_override(
RCLCPP_DETAIL_APPLY_QOS_OVERRIDE_FROM_PARAMETER_STRING(
reliability, RELIABILITY, value, qos);
break;
case QosPolicyKind::Invalid:
throw std::invalid_argument{"invalid QosPolicyKind"};
default:
throw std::invalid_argument{"unknown QosPolicyKind"};
}
}
@@ -332,11 +329,9 @@ get_default_qos_param_value(rclcpp::QosPolicyKind kind, const rclcpp::QoS & qos)
return ParameterValue(
check_if_stringified_policy_is_null(
rmw_qos_reliability_policy_to_str(rmw_qos.reliability), kind));
case QosPolicyKind::Invalid:
throw std::invalid_argument{"invalid QoS policy kind"};
default:
throw std::invalid_argument{"unknown QoS policy kind"};
}
return ParameterValue();
}
} // namespace detail

View File

@@ -29,7 +29,7 @@ template<typename OptionsT, typename NodeBaseT>
bool
resolve_enable_topic_statistics(const OptionsT & options, const NodeBaseT & node_base)
{
bool topic_stats_enabled = false;
bool topic_stats_enabled;
switch (options.topic_stats_options.state) {
case TopicStatisticsState::Enable:
topic_stats_enabled = true;

View File

@@ -30,7 +30,7 @@ template<typename OptionsT, typename NodeBaseT>
bool
resolve_use_intra_process(const OptionsT & options, const NodeBaseT & node_base)
{
bool use_intra_process = false;
bool use_intra_process;
switch (options.use_intra_process_comm) {
case IntraProcessSetting::Enable:
use_intra_process = true;
@@ -43,6 +43,7 @@ resolve_use_intra_process(const OptionsT & options, const NodeBaseT & node_base)
break;
default:
throw std::runtime_error("Unrecognized IntraProcessSetting value");
break;
}
return use_intra_process;

View File

@@ -15,13 +15,11 @@
#ifndef RCLCPP__EVENT_HANDLER_HPP_
#define RCLCPP__EVENT_HANDLER_HPP_
#include <atomic>
#include <functional>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <string>
#include <vector>
#include "rcl/error_handling.h"
#include "rcl/event_callback.h"
@@ -111,14 +109,6 @@ public:
RCLCPP_PUBLIC
virtual ~EventHandlerBase();
RCLCPP_PUBLIC
virtual
void enable() = 0;
RCLCPP_PUBLIC
virtual
void disable() = 0;
/// Get the number of ready events
RCLCPP_PUBLIC
size_t
@@ -201,7 +191,7 @@ public:
}
};
std::lock_guard<std::recursive_mutex> lock(on_new_event_callback_mutex_);
std::lock_guard<std::recursive_mutex> lock(callback_mutex_);
// Set it temporarily to the new callback, while we replace the old one.
// This two-step setting, prevents a gap where the old std::function has
@@ -224,32 +214,27 @@ public:
void
clear_on_ready_callback() override
{
std::lock_guard<std::recursive_mutex> lock(on_new_event_callback_mutex_);
std::lock_guard<std::recursive_mutex> lock(callback_mutex_);
if (on_new_event_callback_) {
set_on_new_event_callback(nullptr, nullptr);
on_new_event_callback_ = nullptr;
}
}
RCLCPP_PUBLIC
std::vector<std::shared_ptr<rclcpp::TimerBase>>
get_timers() const override
{
return {};
}
protected:
RCLCPP_PUBLIC
void
set_on_new_event_callback(rcl_event_callback_t callback, const void * user_data);
std::recursive_mutex on_new_event_callback_mutex_;
std::recursive_mutex callback_mutex_;
std::function<void(size_t)> on_new_event_callback_{nullptr};
rcl_event_t event_handle_;
size_t wait_set_event_index_;
};
using QOSEventHandlerBase [[deprecated("Use rclcpp::EventHandlerBase")]] = EventHandlerBase;
template<typename EventCallbackT, typename ParentHandleT>
class EventHandler : public EventHandlerBase
{
@@ -295,15 +280,15 @@ public:
RCUTILS_LOG_ERROR_NAMED(
"rclcpp",
"Couldn't take event info: %s", rcl_get_error_string().str);
rcl_reset_error();
return nullptr;
}
return std::static_pointer_cast<void>(std::make_shared<EventCallbackInfoT>(callback_info));
}
std::shared_ptr<void>
take_data_by_entity_id([[maybe_unused]] size_t id) override
take_data_by_entity_id(size_t id) override
{
(void)id;
return take_data();
}
@@ -311,10 +296,6 @@ public:
void
execute(const std::shared_ptr<void> & data) override
{
std::unique_lock<std::mutex> event_callback_lock(event_callback_mutex_);
if (disabled_.load()) {
return;
}
if (!data) {
throw std::runtime_error("'data' is empty");
}
@@ -323,54 +304,18 @@ public:
callback_ptr.reset();
}
/// Disable the event callback from being called when execute(..) invoked
/**
* This will also temporarily remove the on_new_event_callback from the underlying rmw layer,
* so that it is not called from the middleware while disabled.
*/
void disable() override
{
{
// Temporary remove the on_new_event_callback_ to prevent it from being called
std::lock_guard<std::recursive_mutex> on_new_event_lock(on_new_event_callback_mutex_);
if (on_new_event_callback_) {
set_on_new_event_callback(nullptr, nullptr);
}
}
std::lock_guard<std::mutex> event_callback_lock(event_callback_mutex_);
disabled_.store(true);
}
/// Enable the event callback to be called when execute(..) invoked
/**
* This will also set back the on_new_event_callback to the underlying rmw layer, if it was
* previously removed with disable().
*/
void enable() override
{
{
// Set callback again if it was previously removed in disable()
std::lock_guard<std::recursive_mutex> on_new_event_lock(on_new_event_callback_mutex_);
if (on_new_event_callback_) {
set_on_new_event_callback(
rclcpp::detail::cpp_callback_trampoline<
decltype(on_new_event_callback_), const void *, size_t>,
static_cast<const void *>(&on_new_event_callback_));
}
}
std::lock_guard<std::mutex> event_callback_lock(event_callback_mutex_);
disabled_.store(false);
}
private:
using EventCallbackInfoT = typename std::remove_reference<typename
rclcpp::function_traits::function_traits<EventCallbackT>::template argument_type<0>>::type;
ParentHandleT parent_handle_;
EventCallbackT event_callback_;
std::mutex event_callback_mutex_;
std::atomic_bool disabled_{false};
};
template<typename EventCallbackT, typename ParentHandleT>
using QOSEventHandler [[deprecated("Use rclcpp::EventHandler")]] = EventHandler<EventCallbackT,
ParentHandleT>;
} // namespace rclcpp
#endif // RCLCPP__EVENT_HANDLER_HPP_

View File

@@ -100,15 +100,6 @@ public:
{}
};
class InvalidServiceTypeError : public std::runtime_error
{
public:
InvalidServiceTypeError()
: std::runtime_error("Service type is invalid.") {}
explicit InvalidServiceTypeError(const std::string & msg)
: std::runtime_error(msg) {}
};
class UnimplementedError : public std::runtime_error
{
public:

View File

@@ -102,8 +102,8 @@ public:
RCLCPP_PUBLIC
virtual void
add_callback_group(
const rclcpp::CallbackGroup::SharedPtr & group_ptr,
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
rclcpp::CallbackGroup::SharedPtr group_ptr,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
bool notify = true);
/// Get callback groups that belong to executor.
@@ -173,7 +173,7 @@ public:
RCLCPP_PUBLIC
virtual void
remove_callback_group(
const rclcpp::CallbackGroup::SharedPtr & group_ptr,
rclcpp::CallbackGroup::SharedPtr group_ptr,
bool notify = true);
/// Add a node to the executor.
@@ -197,9 +197,7 @@ public:
*/
RCLCPP_PUBLIC
virtual void
add_node(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
bool notify = true);
add_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify = true);
/// Convenience function which takes Node and forwards NodeBaseInterface.
/**
@@ -207,7 +205,7 @@ public:
*/
RCLCPP_PUBLIC
virtual void
add_node(const std::shared_ptr<rclcpp::Node> & node_ptr, bool notify = true);
add_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true);
/// Remove a node from the executor.
/**
@@ -227,9 +225,7 @@ public:
*/
RCLCPP_PUBLIC
virtual void
remove_node(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
bool notify = true);
remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify = true);
/// Convenience function which takes Node and forwards NodeBaseInterface.
/**
@@ -237,7 +233,7 @@ public:
*/
RCLCPP_PUBLIC
virtual void
remove_node(const std::shared_ptr<rclcpp::Node> & node_ptr, bool notify = true);
remove_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true);
/// Add a node to executor, execute the next available unit of work, and remove the node.
/**
@@ -249,7 +245,7 @@ public:
template<typename RepT = int64_t, typename T = std::milli>
void
spin_node_once(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
std::chrono::duration<RepT, T> timeout = std::chrono::duration<RepT, T>(-1))
{
return spin_node_once_nanoseconds(
@@ -262,7 +258,7 @@ public:
template<typename NodeT = rclcpp::Node, typename RepT = int64_t, typename T = std::milli>
void
spin_node_once(
const std::shared_ptr<NodeT> & node,
std::shared_ptr<NodeT> node,
std::chrono::duration<RepT, T> timeout = std::chrono::duration<RepT, T>(-1))
{
return spin_node_once_nanoseconds(
@@ -277,12 +273,12 @@ public:
*/
RCLCPP_PUBLIC
virtual void
spin_node_some(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node);
spin_node_some(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node);
/// Convenience function which takes Node and forwards NodeBaseInterface.
RCLCPP_PUBLIC
virtual void
spin_node_some(const std::shared_ptr<rclcpp::Node> & node);
spin_node_some(std::shared_ptr<rclcpp::Node> node);
/// Collect work once and execute all available work, optionally within a max duration.
/**
@@ -291,18 +287,6 @@ public:
* Adding subscriptions, timers, services, etc. with blocking or long running
* callbacks may cause the function exceed the max_duration significantly.
*
* Work that is ready to be done is collected only once, and when collecting that work
* entities which may have multiple pieces of work ready will only be executed at most
* one time.
* The reason for this is that it is not possible to tell if, for example, a ready
* subscription has only one message ready or multiple without checking again.
* Because, in order to find out if there are multiple messages, one message must
* be taken and executed before checking again if that subscription is still ready.
* However, this function only checks for ready entities to work on once,
* and so it will never execute a single entity more than once per call to this function.
* See spin_all() variants for a function that will repeatedly work on a single entity
* in a single call.
*
* If there is no work to be done when this called, it will return immediately
* because the collecting of available work is non-blocking.
* Before each piece of ready work is executed this function checks if the
@@ -325,13 +309,13 @@ public:
RCLCPP_PUBLIC
virtual void
spin_node_all(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
std::chrono::nanoseconds max_duration);
/// Convenience function which takes Node and forwards NodeBaseInterface.
RCLCPP_PUBLIC
virtual void
spin_node_all(const std::shared_ptr<rclcpp::Node> & node, std::chrono::nanoseconds max_duration);
spin_node_all(std::shared_ptr<rclcpp::Node> node, std::chrono::nanoseconds max_duration);
/// Collect and execute work repeatedly within a duration or until no more work is available.
/**
@@ -375,9 +359,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
@@ -431,7 +412,7 @@ protected:
RCLCPP_PUBLIC
void
spin_node_once_nanoseconds(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
std::chrono::nanoseconds timeout);
/// Spin (blocking) until the future is complete, it times out waiting, or rclcpp is interrupted.
@@ -482,7 +463,7 @@ protected:
RCLCPP_PUBLIC
static void
execute_subscription(
const rclcpp::SubscriptionBase::SharedPtr & subscription);
rclcpp::SubscriptionBase::SharedPtr subscription);
/// Run timer executable.
/**
@@ -491,7 +472,7 @@ protected:
*/
RCLCPP_PUBLIC
static void
execute_timer(const rclcpp::TimerBase::SharedPtr & timer, const std::shared_ptr<void> & data_ptr);
execute_timer(rclcpp::TimerBase::SharedPtr timer, const std::shared_ptr<void> & data_ptr);
/// Run service server executable.
/**
@@ -500,7 +481,7 @@ protected:
*/
RCLCPP_PUBLIC
static void
execute_service(const rclcpp::ServiceBase::SharedPtr & service);
execute_service(rclcpp::ServiceBase::SharedPtr service);
/// Run service client executable.
/**
@@ -509,7 +490,7 @@ protected:
*/
RCLCPP_PUBLIC
static void
execute_client(const rclcpp::ClientBase::SharedPtr & client);
execute_client(rclcpp::ClientBase::SharedPtr client);
/// Gather all of the waitable entities from associated nodes and callback groups.
RCLCPP_PUBLIC
@@ -560,9 +541,8 @@ protected:
*
* \param[in] notify if true will execute a trigger that will wake up a waiting executor
*/
RCLCPP_PUBLIC
virtual void
handle_updated_entities(bool notify);
void
trigger_entity_recollect(bool notify);
/// Spinning state, used to prevent multi threaded calls to spin and to cancel blocking spins.
std::atomic_bool spinning;

View File

@@ -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,95 +29,37 @@
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(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
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(const rclcpp::Node::SharedPtr & node_ptr, std::chrono::nanoseconds max_duration);
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(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr);
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(const rclcpp::Node::SharedPtr & node_ptr);
spin_some(rclcpp::Node::SharedPtr node_ptr);
/// Create a default single-threaded executor and spin the specified node.
/** \param[in] node_ptr Shared pointer to the node to spin. */
RCLCPP_PUBLIC
void
spin(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr);
spin(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
RCLCPP_PUBLIC
void
spin(const rclcpp::Node::SharedPtr & node_ptr);
spin(rclcpp::Node::SharedPtr node_ptr);
namespace executors
{
@@ -140,7 +83,7 @@ template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::mi
rclcpp::FutureReturnCode
spin_node_until_future_complete(
rclcpp::Executor & executor,
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
const FutureT & future,
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
{
@@ -157,7 +100,7 @@ template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeRepT = in
rclcpp::FutureReturnCode
spin_node_until_future_complete(
rclcpp::Executor & executor,
const std::shared_ptr<NodeT> & node_ptr,
std::shared_ptr<NodeT> node_ptr,
const FutureT & future,
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
{
@@ -173,7 +116,7 @@ spin_node_until_future_complete(
template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::milli>
rclcpp::FutureReturnCode
spin_until_future_complete(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
const FutureT & future,
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
{
@@ -187,7 +130,7 @@ template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeRepT = in
typename TimeT = std::milli>
rclcpp::FutureReturnCode
spin_until_future_complete(
const std::shared_ptr<NodeT> & node_ptr,
std::shared_ptr<NodeT> node_ptr,
const FutureT & future,
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
{

View File

@@ -63,7 +63,7 @@ public:
*/
RCLCPP_PUBLIC
explicit ExecutorEntitiesCollector(
const std::shared_ptr<ExecutorNotifyWaitable> & notify_waitable);
std::shared_ptr<ExecutorNotifyWaitable> notify_waitable);
/// Destructor
RCLCPP_PUBLIC
@@ -82,7 +82,7 @@ public:
*/
RCLCPP_PUBLIC
void
add_node(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr);
add_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
/// Remove a node from the entity collector
/**
@@ -92,7 +92,7 @@ public:
*/
RCLCPP_PUBLIC
void
remove_node(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr);
remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
/// Add a callback group to the entity collector
/**
@@ -101,7 +101,7 @@ public:
*/
RCLCPP_PUBLIC
void
add_callback_group(const rclcpp::CallbackGroup::SharedPtr & group_ptr);
add_callback_group(rclcpp::CallbackGroup::SharedPtr group_ptr);
/// Remove a callback group from the entity collector
/**
@@ -111,7 +111,7 @@ public:
*/
RCLCPP_PUBLIC
void
remove_callback_group(const rclcpp::CallbackGroup::SharedPtr & group_ptr);
remove_callback_group(rclcpp::CallbackGroup::SharedPtr group_ptr);
/// Get all callback groups known to this entity collector
/**
@@ -211,7 +211,7 @@ protected:
RCLCPP_PUBLIC
void
add_callback_group_to_collection(
const rclcpp::CallbackGroup::SharedPtr & group_ptr,
rclcpp::CallbackGroup::SharedPtr group_ptr,
CallbackGroupCollection & collection) RCPPUTILS_TSA_REQUIRES(mutex_);
/// Iterate over queued added/remove nodes and callback_groups

View File

@@ -19,7 +19,6 @@
#include <memory>
#include <mutex>
#include <set>
#include <vector>
#include "rclcpp/guard_condition.hpp"
#include "rclcpp/waitable.hpp"
@@ -42,10 +41,7 @@ public:
* of this waitable has signaled the wait_set.
*/
RCLCPP_PUBLIC
explicit ExecutorNotifyWaitable(
const std::function<void(void)> & on_execute_callback = {},
const rclcpp::Context::SharedPtr & context =
rclcpp::contexts::get_global_default_context());
explicit ExecutorNotifyWaitable(std::function<void(void)> on_execute_callback = {});
// Destructor
RCLCPP_PUBLIC
@@ -116,7 +112,7 @@ public:
*/
RCLCPP_PUBLIC
void
add_guard_condition(const rclcpp::GuardCondition::WeakPtr & guard_condition);
add_guard_condition(rclcpp::GuardCondition::WeakPtr guard_condition);
/// Unset any callback registered via set_on_ready_callback.
/**
@@ -126,21 +122,13 @@ public:
void
clear_on_ready_callback() override;
/// Set a new callback to be called whenever this waitable is executed.
/**
* \param[in] on_execute_callback The new callback
*/
RCLCPP_PUBLIC
void
set_execute_callback(std::function<void(void)> on_execute_callback);
/// Remove a guard condition from being waited on.
/**
* \param[in] weak_guard_condition The guard condition to remove.
*/
RCLCPP_PUBLIC
void
remove_guard_condition(const rclcpp::GuardCondition::WeakPtr & weak_guard_condition);
remove_guard_condition(rclcpp::GuardCondition::WeakPtr weak_guard_condition);
/// Get the number of ready guard_conditions
/**
@@ -150,37 +138,17 @@ public:
size_t
get_number_of_ready_guard_conditions() override;
/// Returns the number of used Timers
/**
* Will always return an empty vector.
*/
RCLCPP_PUBLIC
std::vector<std::shared_ptr<rclcpp::TimerBase>>
get_timers() const override;
private:
/// Callback to run when waitable executes
std::function<void(void)> execute_callback_;
/// Mutex to procetect the guard conditions
std::mutex guard_condition_mutex_;
/// Mutex to protect the execute callback
std::mutex execute_mutex_;
std::function<void(size_t)> on_ready_callback_;
/// The collection of guard conditions to be waited on.
std::set<rclcpp::GuardCondition::SharedPtr> notify_guard_conditions_;
/// The indixes were our guard conditions were stored in the
/// rcl waitset
std::vector<size_t> idxs_of_added_guard_condition_;
/// set to true, if we got a pending trigger
bool needs_processing = false;
/// A guard condition needed to generate wakeups
rclcpp::GuardCondition::SharedPtr guard_condition_;
std::set<rclcpp::GuardCondition::WeakPtr,
std::owner_less<rclcpp::GuardCondition::WeakPtr>> notify_guard_conditions_;
};
} // namespace executors

View File

@@ -0,0 +1,138 @@
// 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's static because it doesn't reconstruct 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.
*
* 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 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_

View File

@@ -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_;

View File

@@ -82,9 +82,10 @@ create_intra_process_buffer(
break;
}
case IntraProcessBufferType::CallbackDefault:
default:
{
throw std::runtime_error("IntraProcessBufferType::CallbackDefault is not allowed");
throw std::runtime_error("Unrecognized IntraProcessBufferType value");
break;
}
}

View File

@@ -59,22 +59,24 @@ namespace executors
*/
class EventsExecutor : public rclcpp::Executor
{
friend class EventsExecutorEntitiesCollector;
public:
RCLCPP_SMART_PTR_DEFINITIONS(EventsExecutor)
/// 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(),
explicit EventsExecutor(
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
@@ -126,6 +128,87 @@ public:
void
spin_all(std::chrono::nanoseconds max_duration) override;
/// Add a node to the executor.
/**
* \sa rclcpp::Executor::add_node
*/
RCLCPP_PUBLIC
void
add_node(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
bool notify = true) override;
/// Convenience function which takes Node and forwards NodeBaseInterface.
/**
* \sa rclcpp::EventsExecutor::add_node
*/
RCLCPP_PUBLIC
void
add_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true) override;
/// Remove a node from the executor.
/**
* \sa rclcpp::Executor::remove_node
*/
RCLCPP_PUBLIC
void
remove_node(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
bool notify = true) override;
/// Convenience function which takes Node and forwards NodeBaseInterface.
/**
* \sa rclcpp::Executor::remove_node
*/
RCLCPP_PUBLIC
void
remove_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true) override;
/// Add a callback group to an executor.
/**
* \sa rclcpp::Executor::add_callback_group
*/
RCLCPP_PUBLIC
void
add_callback_group(
rclcpp::CallbackGroup::SharedPtr group_ptr,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
bool notify = true) override;
/// Remove callback group from the executor
/**
* \sa rclcpp::Executor::remove_callback_group
*/
RCLCPP_PUBLIC
void
remove_callback_group(
rclcpp::CallbackGroup::SharedPtr group_ptr,
bool notify = true) override;
/// Get callback groups that belong to executor.
/**
* \sa rclcpp::Executor::get_all_callback_groups()
*/
RCLCPP_PUBLIC
std::vector<rclcpp::CallbackGroup::WeakPtr>
get_all_callback_groups() override;
/// Get callback groups that belong to executor.
/**
* \sa rclcpp::Executor::get_manually_added_callback_groups()
*/
RCLCPP_PUBLIC
std::vector<rclcpp::CallbackGroup::WeakPtr>
get_manually_added_callback_groups() override;
/// Get callback groups that belong to executor.
/**
* \sa rclcpp::Executor::get_automatically_added_callback_groups_from_nodes()
*/
RCLCPP_PUBLIC
std::vector<rclcpp::CallbackGroup::WeakPtr>
get_automatically_added_callback_groups_from_nodes() override;
protected:
/// Internal implementation of spin_once
RCLCPP_PUBLIC
@@ -137,11 +220,6 @@ protected:
void
spin_some_impl(std::chrono::nanoseconds max_duration, bool exhaustive);
/// Collect entities from callback groups and refresh the current collection with them
RCLCPP_PUBLIC
void
handle_updated_entities(bool notify) override;
private:
RCLCPP_DISABLE_COPY(EventsExecutor)
@@ -149,9 +227,9 @@ private:
void
execute_event(const ExecutorEvent & event);
/// Rebuilds the executor's notify waitable, as we can't use the one built in the base class
/// Collect entities from callback groups and refresh the current collection with them
void
setup_notify_waitable();
refresh_current_collection_from_callback_groups();
/// Refresh the current collection using the provided new_collection
void
@@ -175,11 +253,6 @@ private:
typename CollectionType::EntitySharedPtr
retrieve_entity(typename CollectionType::Key entity_id, CollectionType & collection)
{
// Note: we lock the mutex because we assume that you are trying to get an element from the
// current collection... If there will be a use-case to retrieve elements also from other
// collections, we can move the mutex back to the calling codes.
std::lock_guard<std::mutex> guard(mutex_);
// Check if the entity_id is in the collection
auto it = collection.find(entity_id);
if (it == collection.end()) {
@@ -200,6 +273,16 @@ private:
/// Queue where entities can push events
rclcpp::experimental::executors::EventsQueue::UniquePtr events_queue_;
std::shared_ptr<rclcpp::executors::ExecutorEntitiesCollector> entities_collector_;
std::shared_ptr<rclcpp::executors::ExecutorNotifyWaitable> notify_waitable_;
/// Mutex to protect the current_entities_collection_
std::recursive_mutex collection_mutex_;
std::shared_ptr<rclcpp::executors::ExecutorEntitiesCollection> current_entities_collection_;
/// Flag used to reduce the number of unnecessary waitable events
std::atomic<bool> notify_waitable_event_pushed_ {false};
/// Timers manager used to track and/or execute associated timers
std::shared_ptr<rclcpp::experimental::TimersManager> timers_manager_;
};

View File

@@ -19,7 +19,6 @@
#include <shared_mutex>
#include <algorithm>
#include <iterator>
#include <memory>
#include <stdexcept>
@@ -119,8 +118,7 @@ public:
typename Alloc = std::allocator<ROSMessageType>
>
uint64_t
add_subscription(
const rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr & subscription)
add_subscription(rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr subscription)
{
std::unique_lock<std::shared_timed_mutex> lock(mutex_);
@@ -177,8 +175,8 @@ public:
RCLCPP_PUBLIC
uint64_t
add_publisher(
const rclcpp::PublisherBase::SharedPtr & publisher,
const rclcpp::experimental::buffers::IntraProcessBufferBase::SharedPtr & buffer =
rclcpp::PublisherBase::SharedPtr publisher,
rclcpp::experimental::buffers::IntraProcessBufferBase::SharedPtr buffer =
rclcpp::experimental::buffers::IntraProcessBufferBase::SharedPtr());
/// Unregister a publisher using the publisher's unique id.
@@ -388,39 +386,6 @@ private:
std::vector<uint64_t> take_ownership_subscriptions;
};
/// Hash function for rmw_gid_t to enable use in unordered_map
struct rmw_gid_hash
{
std::size_t operator()(const rmw_gid_t & gid) const noexcept
{
// Using the FNV-1a hash algorithm on the gid data
constexpr std::size_t FNV_prime = 1099511628211u;
std::size_t result = 14695981039346656037u;
for (std::size_t i = 0; i < RMW_GID_STORAGE_SIZE; ++i) {
result ^= gid.data[i];
result *= FNV_prime;
}
return result;
}
};
/// Equality comparison for rmw_gid_t to enable use in unordered_map
struct rmw_gid_equal
{
bool operator()(const rmw_gid_t & lhs, const rmw_gid_t & rhs) const noexcept
{
// Compare the data bytes only.
// implementation_identifier pointer comparison is not used here because
// intra-process communication is always within the same process and RMW,
// and pointer comparison is fragile across dynamically loaded components.
return std::equal(
std::begin(lhs.data),
std::end(lhs.data),
std::begin(rhs.data));
}
};
using SubscriptionMap =
std::unordered_map<uint64_t, rclcpp::experimental::SubscriptionIntraProcessBase::WeakPtr>;
@@ -433,16 +398,6 @@ private:
using PublisherToSubscriptionIdsMap =
std::unordered_map<uint64_t, SplittedSubscriptions>;
/// Structure to store publisher information in GID lookup map
struct PublisherInfo
{
uint64_t pub_id;
rclcpp::PublisherBase::WeakPtr publisher;
};
using GidToPublisherInfoMap =
std::unordered_map<rmw_gid_t, PublisherInfo, rmw_gid_hash, rmw_gid_equal>;
RCLCPP_PUBLIC
static
uint64_t
@@ -455,8 +410,8 @@ private:
RCLCPP_PUBLIC
bool
can_communicate(
const rclcpp::PublisherBase::SharedPtr & pub,
const rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr & sub) const;
rclcpp::PublisherBase::SharedPtr pub,
rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr sub) const;
template<
typename ROSMessageType,
@@ -687,8 +642,6 @@ private:
PublisherBufferMap publisher_buffers_;
mutable std::shared_timed_mutex mutex_;
GidToPublisherInfoMap gid_to_publisher_info_;
};
} // namespace experimental

View File

@@ -154,29 +154,6 @@ public:
execute_impl<SubscribedType>(data);
}
/// Disable callbacks from being called
/**
* This method will block, until any subscription's callbacks currently being executed are
* finished.
* This method is thread safe, and provides a safe way to atomically disable the callbacks.
*/
void disable_callbacks() override
{
SubscriptionIntraProcessBase::disable_callbacks();
any_callback_.disable();
}
/// Enable the callbacks to be called
/**
* This method is thread safe, and provides a safe way to atomically enable the callbacks
* in a multithreaded environment.
*/
void enable_callbacks() override
{
SubscriptionIntraProcessBase::enable_callbacks();
any_callback_.enable();
}
protected:
template<typename T>
typename std::enable_if<std::is_same<T, rcl_serialized_message_t>::value, void>::type

View File

@@ -19,7 +19,6 @@
#include <memory>
#include <mutex>
#include <string>
#include <vector>
#include "rcl/wait.h"
#include "rmw/impl/cpp/demangle.hpp"
@@ -79,30 +78,15 @@ public:
take_data() override = 0;
std::shared_ptr<void>
take_data_by_entity_id([[maybe_unused]] size_t id) override
take_data_by_entity_id(size_t id) override
{
(void)id;
return take_data();
}
void
execute(const std::shared_ptr<void> & data) override = 0;
/// Disable callbacks from being called
/**
* This function temporary disable on_new_message_callback to prevent it from being called.
*/
RCLCPP_PUBLIC
virtual
void disable_callbacks();
/// Enable the callbacks to be called
/**
* This function enable the on_new_message_callback if it was previously set.
*/
RCLCPP_PUBLIC
virtual
void enable_callbacks();
virtual
bool
use_take_shared_method() const = 0;
@@ -174,7 +158,7 @@ public:
}
};
std::lock_guard<std::recursive_mutex> lock(on_new_message_callback_mutex_);
std::lock_guard<std::recursive_mutex> lock(callback_mutex_);
on_new_message_callback_ = new_callback;
if (unread_count_ > 0) {
@@ -192,21 +176,13 @@ public:
void
clear_on_ready_callback() override
{
std::lock_guard<std::recursive_mutex> lock(on_new_message_callback_mutex_);
std::lock_guard<std::recursive_mutex> lock(callback_mutex_);
on_new_message_callback_ = nullptr;
}
RCLCPP_PUBLIC
std::vector<std::shared_ptr<rclcpp::TimerBase>>
get_timers() const override
{
return {};
}
protected:
std::recursive_mutex on_new_message_callback_mutex_;
std::recursive_mutex callback_mutex_;
std::function<void(size_t)> on_new_message_callback_ {nullptr};
bool on_new_message_callback_disabled_{false};
size_t unread_count_{0};
rclcpp::GuardCondition gc_;
@@ -216,13 +192,11 @@ protected:
void
invoke_on_new_message()
{
std::lock_guard<std::recursive_mutex> lock(this->on_new_message_callback_mutex_);
if (!on_new_message_callback_disabled_) {
if (this->on_new_message_callback_) {
this->on_new_message_callback_(1);
} else {
this->unread_count_++;
}
std::lock_guard<std::recursive_mutex> lock(this->callback_mutex_);
if (this->on_new_message_callback_) {
this->on_new_message_callback_(1);
} else {
this->unread_count_++;
}
}

View File

@@ -110,8 +110,9 @@ public:
}
bool
is_ready([[maybe_unused]] const rcl_wait_set_t & wait_set) override
is_ready(const rcl_wait_set_t & wait_set) override
{
(void) wait_set;
return buffer_->has_data();
}

View File

@@ -103,7 +103,7 @@ public:
* @throws std::invalid_argument if timer is a nullptr.
*/
RCLCPP_PUBLIC
void add_timer(const rclcpp::TimerBase::SharedPtr & timer);
void add_timer(rclcpp::TimerBase::SharedPtr timer);
/**
* @brief Remove a single timer from the object storage.
@@ -113,7 +113,7 @@ public:
* @param timer the timer to remove.
*/
RCLCPP_PUBLIC
void remove_timer(const rclcpp::TimerBase::SharedPtr & timer);
void remove_timer(rclcpp::TimerBase::SharedPtr timer);
/**
* @brief Remove all the timers stored in the object.

View File

@@ -19,7 +19,6 @@
#include <memory>
#include <future>
#include <string>
#include <tuple>
#include <vector>
#include <utility>
@@ -36,8 +35,8 @@ namespace rclcpp
class GenericClient : public ClientBase
{
public:
using Request = void *; // Deserialized data pointer of request message
using Response = void *; // Deserialized data pointer of response message
using Request = void *; // Serialized data pointer of request message
using Response = void *; // Serialized data pointer of response message
using SharedResponse = std::shared_ptr<void>;
@@ -47,8 +46,6 @@ public:
using Future = std::future<SharedResponse>;
using SharedFuture = std::shared_future<SharedResponse>;
using CallbackType = std::function<void (SharedFuture)>;
RCLCPP_SMART_PTR_DEFINITIONS(GenericClient)
/// A convenient GenericClient::Future and request id pair.
@@ -79,23 +76,9 @@ public:
~FutureAndRequestId() = default;
};
/// A convenient GenericClient::SharedFuture and request id pair.
/**
* Public members:
* - future: a std::shared_future<SharedResponse>.
* - request_id: the request id associated with the future.
*
* All the other methods are equivalent to the ones std::shared_future provides.
*/
struct SharedFutureAndRequestId
: detail::FutureAndRequestId<std::shared_future<SharedResponse>>
{
using detail::FutureAndRequestId<std::shared_future<SharedResponse>>::FutureAndRequestId;
};
GenericClient(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr & node_graph,
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
const std::string & service_name,
const std::string & service_type,
rcl_client_options_t & client_options);
@@ -111,8 +94,8 @@ public:
RCLCPP_PUBLIC
void
handle_response(
const std::shared_ptr<rmw_request_id_t> & request_header,
const std::shared_ptr<void> & response) override;
std::shared_ptr<rmw_request_id_t> request_header,
std::shared_ptr<void> response) override;
/// Send a request to the service server.
/**
@@ -123,16 +106,16 @@ public:
* If the future never completes,
* e.g. the call to Executor::spin_until_future_complete() times out,
* GenericClient::remove_pending_request() must be called to clean the client internal state.
* Not doing so will make the `GenericClient` instance to use more memory each time a response is
* not received from the service server.
* Not doing so will make the `Client` instance to use more memory each time a response is not
* received from the service server.
*
* ```cpp
* auto future = generic_client->async_send_request(my_request);
* auto future = client->async_send_request(my_request);
* if (
* rclcpp::FutureReturnCode::TIMEOUT ==
* executor->spin_until_future_complete(future, timeout))
* {
* generic_client->remove_pending_request(future);
* client->remove_pending_request(future);
* // handle timeout
* } else {
* handle_response(future.get());
@@ -144,46 +127,7 @@ public:
*/
RCLCPP_PUBLIC
FutureAndRequestId
async_send_request(const Request & request);
/// Send a request to the service server and schedule a callback in the executor.
/**
* Similar to the previous overload, but a callback will automatically be called when a response
* is received.
*
* If the callback is never called, because we never got a reply for the service server,
* remove_pending_request() has to be called with the returned request id or
* prune_pending_requests().
* Not doing so will make the `GenericClient` instance use more memory each time a response is not
* received from the service server.
* In this case, it's convenient to setup a timer to cleanup the pending requests.
*
* \param[in] request request to be send.
* \param[in] cb callback that will be called when we get a response for this request.
* \return the request id representing the request just sent.
*/
template<
typename CallbackT,
typename std::enable_if<
rclcpp::function_traits::same_arguments<
CallbackT,
CallbackType
>::value
>::type * = nullptr
>
SharedFutureAndRequestId
async_send_request(const Request & request, CallbackT && cb)
{
Promise promise;
auto shared_future = promise.get_future().share();
auto req_id = async_send_request_impl(
request,
std::make_tuple(
CallbackType{std::forward<CallbackT>(cb)},
shared_future,
std::move(promise)));
return SharedFutureAndRequestId{std::move(shared_future), req_id};
}
async_send_request(const Request request);
/// Clean all pending requests older than a time_point.
/**
@@ -205,52 +149,15 @@ public:
pruned_requests);
}
/// Clean all pending requests.
/**
* \return number of pending requests that were removed.
*/
RCLCPP_PUBLIC
size_t
prune_pending_requests();
/// Cleanup a pending request.
/**
* This notifies the client that we have waited long enough for a response from the server
* to come, we have given up and we are not waiting for a response anymore.
*
* Not calling this will make the client start using more memory for each request
* that never got a reply from the server.
*
* \param[in] request_id request id returned by async_send_request().
* \return true when a pending request was removed, false if not (e.g. a response was received).
*/
RCLCPP_PUBLIC
bool
remove_pending_request(
int64_t request_id);
/// Cleanup a pending request.
/**
* Convenient overload, same as:
*
* `GenericClient::remove_pending_request(this, future.request_id)`.
*/
RCLCPP_PUBLIC
bool
remove_pending_request(
const FutureAndRequestId & future);
/// Cleanup a pending request.
/**
* Convenient overload, same as:
*
* `GenericClient::remove_pending_request(this, future.request_id)`.
*/
RCLCPP_PUBLIC
bool
remove_pending_request(
const SharedFutureAndRequestId & future);
/// Take the next response for this client.
/**
* \sa ClientBase::take_type_erased_response().
@@ -272,15 +179,12 @@ public:
}
protected:
using CallbackTypeValueVariant = std::tuple<CallbackType, SharedFuture, Promise>;
using CallbackInfoVariant = std::variant<
std::promise<SharedResponse>,
CallbackTypeValueVariant>; // Use variant for extension
std::promise<SharedResponse>>; // Use variant for extension
RCLCPP_PUBLIC
int64_t
async_send_request_impl(
const Request & request,
const Request request,
CallbackInfoVariant value);
std::optional<CallbackInfoVariant>

View File

@@ -1,308 +0,0 @@
// Copyright 2024 Sony Group Corporation.
//
// 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__GENERIC_SERVICE_HPP_
#define RCLCPP__GENERIC_SERVICE_HPP_
#include <cstdlib>
#include <functional>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <variant>
#include "rclcpp/typesupport_helpers.hpp"
#include "rosidl_runtime_c/service_type_support_struct.h"
#include "rosidl_typesupport_introspection_cpp/identifier.hpp"
#include "rosidl_typesupport_introspection_cpp/service_introspection.hpp"
#include "service.hpp"
namespace rclcpp
{
class GenericService;
class GenericServiceCallback
{
public:
using SharedRequest = std::shared_ptr<void>;
using SharedResponse = std::shared_ptr<void>;
GenericServiceCallback()
: callback_(std::monostate{})
{}
template<
typename CallbackT,
typename std::enable_if_t<!detail::can_be_nullptr<CallbackT>::value, int> = 0>
void
set(CallbackT && callback)
{
// Workaround Windows issue with std::bind
if constexpr (
rclcpp::function_traits::same_arguments<
CallbackT,
SharedPtrCallback
>::value)
{
callback_.template emplace<SharedPtrCallback>(callback);
} else if constexpr ( // NOLINT, can't satisfy both cpplint and uncrustify
rclcpp::function_traits::same_arguments<
CallbackT,
SharedPtrWithRequestHeaderCallback
>::value)
{
callback_.template emplace<SharedPtrWithRequestHeaderCallback>(callback);
} else if constexpr ( // NOLINT
rclcpp::function_traits::same_arguments<
CallbackT,
SharedPtrDeferResponseCallback
>::value)
{
callback_.template emplace<SharedPtrDeferResponseCallback>(callback);
} else if constexpr ( // NOLINT
rclcpp::function_traits::same_arguments<
CallbackT,
SharedPtrDeferResponseCallbackWithServiceHandle
>::value)
{
callback_.template emplace<SharedPtrDeferResponseCallbackWithServiceHandle>(callback);
} else {
// the else clause is not needed, but anyways we should only be doing this instead
// of all the above workaround ...
callback_ = std::forward<CallbackT>(callback);
}
}
template<
typename CallbackT,
typename std::enable_if_t<detail::can_be_nullptr<CallbackT>::value, int> = 0>
void
set(CallbackT && callback)
{
if (!callback) {
throw std::invalid_argument("AnyServiceCallback::set(): callback cannot be nullptr");
}
// Workaround Windows issue with std::bind
if constexpr (
rclcpp::function_traits::same_arguments<
CallbackT,
SharedPtrCallback
>::value)
{
callback_.template emplace<SharedPtrCallback>(callback);
} else if constexpr ( // NOLINT
rclcpp::function_traits::same_arguments<
CallbackT,
SharedPtrWithRequestHeaderCallback
>::value)
{
callback_.template emplace<SharedPtrWithRequestHeaderCallback>(callback);
} else if constexpr ( // NOLINT
rclcpp::function_traits::same_arguments<
CallbackT,
SharedPtrDeferResponseCallback
>::value)
{
callback_.template emplace<SharedPtrDeferResponseCallback>(callback);
} else if constexpr ( // NOLINT
rclcpp::function_traits::same_arguments<
CallbackT,
SharedPtrDeferResponseCallbackWithServiceHandle
>::value)
{
callback_.template emplace<SharedPtrDeferResponseCallbackWithServiceHandle>(callback);
} else {
// the else clause is not needed, but anyways we should only be doing this instead
// of all the above workaround ...
callback_ = std::forward<CallbackT>(callback);
}
}
SharedResponse
dispatch(
const std::shared_ptr<rclcpp::GenericService> & service_handle,
const std::shared_ptr<rmw_request_id_t> & request_header,
SharedRequest request,
SharedRequest response)
{
TRACETOOLS_TRACEPOINT(callback_start, static_cast<const void *>(this), false);
if (std::holds_alternative<std::monostate>(callback_)) {
// TODO(ivanpauno): Remove the set method, and force the users of this class
// to pass a callback at construnciton.
throw std::runtime_error{"unexpected request without any callback set"};
}
if (std::holds_alternative<SharedPtrDeferResponseCallback>(callback_)) {
const auto & cb = std::get<SharedPtrDeferResponseCallback>(callback_);
cb(request_header, std::move(request));
return nullptr;
}
if (std::holds_alternative<SharedPtrDeferResponseCallbackWithServiceHandle>(callback_)) {
const auto & cb = std::get<SharedPtrDeferResponseCallbackWithServiceHandle>(callback_);
cb(service_handle, request_header, std::move(request));
return nullptr;
}
if (std::holds_alternative<SharedPtrCallback>(callback_)) {
(void)request_header;
const auto & cb = std::get<SharedPtrCallback>(callback_);
cb(std::move(request), response);
} else if (std::holds_alternative<SharedPtrWithRequestHeaderCallback>(callback_)) {
const auto & cb = std::get<SharedPtrWithRequestHeaderCallback>(callback_);
cb(request_header, std::move(request), response);
}
TRACETOOLS_TRACEPOINT(callback_end, static_cast<const void *>(this));
return response;
}
void register_callback_for_tracing()
{
#ifndef TRACETOOLS_DISABLED
std::visit(
[this](auto && arg) {
if (TRACETOOLS_TRACEPOINT_ENABLED(rclcpp_callback_register)) {
char * symbol = tracetools::get_symbol(arg);
TRACETOOLS_DO_TRACEPOINT(
rclcpp_callback_register,
static_cast<const void *>(this),
symbol);
std::free(symbol);
}
}, callback_);
#endif // TRACETOOLS_DISABLED
}
private:
using SharedPtrCallback = std::function<void (SharedRequest, SharedResponse)>;
using SharedPtrWithRequestHeaderCallback = std::function<
void (
std::shared_ptr<rmw_request_id_t>,
SharedRequest,
SharedResponse
)>;
using SharedPtrDeferResponseCallback = std::function<
void (
std::shared_ptr<rmw_request_id_t>,
SharedRequest
)>;
using SharedPtrDeferResponseCallbackWithServiceHandle = std::function<
void (
std::shared_ptr<rclcpp::GenericService>,
std::shared_ptr<rmw_request_id_t>,
SharedRequest
)>;
std::variant<
std::monostate,
SharedPtrCallback,
SharedPtrWithRequestHeaderCallback,
SharedPtrDeferResponseCallback,
SharedPtrDeferResponseCallbackWithServiceHandle> callback_;
};
class GenericService
: public ServiceBase,
public std::enable_shared_from_this<GenericService>
{
public:
using Request = void *; // Serialized/Deserialized data pointer of request message
using Response = void *; // Serialized/Deserialized data pointer of response message
using SharedRequest = std::shared_ptr<void>;
using SharedResponse = std::shared_ptr<void>;
using CallbackType = std::function<void (const SharedRequest, SharedResponse)>;
using CallbackWithHeaderType =
std::function<void (const std::shared_ptr<rmw_request_id_t>,
const SharedRequest,
SharedResponse)>;
RCLCPP_SMART_PTR_DEFINITIONS(GenericService)
/// Default constructor.
/**
* The constructor for a Service is almost never called directly.
* Instead, services should be instantiated through the function
* rclcpp::create_service().
*
* \param[in] node_handle NodeBaseInterface pointer that is used in part of the setup.
* \param[in] service_name Name of the topic to publish to.
* \param[in] service_type The name of service type, e.g. "std_srvs/srv/SetBool".
* \param[in] any_callback User defined callback to call when a client request is received.
* \param[in] service_options options for the service.
*/
RCLCPP_PUBLIC
GenericService(
const std::shared_ptr<rcl_node_t> & node_handle,
const std::string & service_name,
const std::string & service_type,
GenericServiceCallback any_callback,
rcl_service_options_t & service_options);
GenericService() = delete;
RCLCPP_PUBLIC
virtual ~GenericService() {}
/// Take the next request from the service.
/**
* \sa ServiceBase::take_type_erased_request().
*
* \param[out] request_out The reference to a service deserialized request object
* into which the middleware will copy the taken request.
* \param[out] request_id_out The output id for the request which can be used
* to associate response with this request in the future.
* \returns true if the request was taken, otherwise false.
* \throws rclcpp::exceptions::RCLError based exceptions if the underlying
* rcl calls fail.
*/
RCLCPP_PUBLIC
bool
take_request(SharedRequest & request_out, rmw_request_id_t & request_id_out);
RCLCPP_PUBLIC
std::shared_ptr<void>
create_request() override;
RCLCPP_PUBLIC
std::shared_ptr<void>
create_response();
RCLCPP_PUBLIC
std::shared_ptr<rmw_request_id_t>
create_request_header() override;
RCLCPP_PUBLIC
void
handle_request(
const std::shared_ptr<rmw_request_id_t> & request_header,
const std::shared_ptr<void> & request) override;
RCLCPP_PUBLIC
void
send_response(rmw_request_id_t & req_id, SharedResponse & response);
private:
RCLCPP_DISABLE_COPY(GenericService)
GenericServiceCallback any_callback_;
std::shared_ptr<rcpputils::SharedLibrary> ts_lib_;
const rosidl_typesupport_introspection_cpp::MessageMembers * request_members_;
const rosidl_typesupport_introspection_cpp::MessageMembers * response_members_;
};
} // namespace rclcpp
#endif // RCLCPP__GENERIC_SERVICE_HPP_

View File

@@ -80,7 +80,7 @@ public:
node_base,
*rclcpp::get_message_typesupport_handle(topic_type, "rosidl_typesupport_cpp", *ts_lib),
topic_name,
force_cpu_buffer_backend_(options).to_rcl_subscription_options(qos),
options.to_rcl_subscription_options(qos),
options.event_callbacks,
options.use_default_callbacks,
DeliveredMessageKind::SERIALIZED_MESSAGE),
@@ -111,26 +111,6 @@ public:
RCLCPP_PUBLIC
std::shared_ptr<rclcpp::SerializedMessage> create_serialized_message() override;
/// Disable callbacks from being called
/**
* This method will block, until any subscription's callbacks provided during construction
* currently being executed are finished.
* \note This method also temporary removes the on new message callback and all
* on new event callbacks from the rmw layer to prevent them from being called. However, this
* method will not block and wait until the currently executing on_new_[message]event callbacks
* are finished.
*/
RCLCPP_PUBLIC
void disable_callbacks() override;
/// Enable the callbacks to be called
/**
* This method is thread safe, and provides a safe way to atomically enable the callbacks
* in a multithreaded environment.
*/
RCLCPP_PUBLIC
void enable_callbacks() override;
/// Cast the message to a rclcpp::SerializedMessage and call the callback.
RCLCPP_PUBLIC
void handle_message(
@@ -182,17 +162,6 @@ public:
private:
RCLCPP_DISABLE_COPY(GenericSubscription)
template<typename AllocatorT>
static rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>
force_cpu_buffer_backend_(
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options)
{
auto opts = options;
opts.acceptable_buffer_backends = "cpu";
return opts;
}
AnySubscriptionCallback<rclcpp::SerializedMessage, std::allocator<void>> any_callback_;
// The type support library should stay loaded, so it is stored in the GenericSubscription
std::shared_ptr<rcpputils::SharedLibrary> ts_lib_;

View File

@@ -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_;

View File

@@ -120,7 +120,7 @@ public:
*/
RCLCPP_PUBLIC
void
set_on_trigger_callback(const std::function<void(size_t)> & callback);
set_on_trigger_callback(std::function<void(size_t)> callback);
protected:
rcl_guard_condition_t rcl_guard_condition_;

View File

@@ -31,20 +31,21 @@ namespace rclcpp
template<typename MessageT, typename AllocatorT = std::allocator<void>>
class LoanedMessage
{
public:
using MessageAllocatorTraits = rclcpp::allocator::AllocRebind<MessageT, AllocatorT>;
using MessageAllocator = typename MessageAllocatorTraits::allocator_type;
public:
/// Constructor of the LoanedMessage class.
/**
* The constructor of this class allocates memory for a given message type
* and associates this with a given publisher.
*
* The underlying middleware is queried to determine whether it is able to allocate the
* appropriate memory for this message type or not.
* In the case that the middleware cannot loan messages, the passed in allocator instance
* is used to allocate the message within the scope of this class.
* Otherwise, the allocator is ignored and the allocation is solely performed
* Given the publisher instance, a case differentiation is being performaned
* which decides whether the underlying middleware is able to allocate the appropriate
* memory for this message type or not.
* In the case that the middleware can not loan messages, the passed in allocator instance
* is being used to allocate the message within the scope of this class.
* Otherwise, the allocator is being ignored and the allocation is solely performaned
* in the underlying middleware with its appropriate allocation strategy.
* The need for this arises as the user code can be written explicitly targeting a middleware
* capable of loaning messages.
@@ -52,12 +53,12 @@ public:
* a middleware which doesn't support message loaning in which case the allocator will be used.
*
* \param[in] pub rclcpp::Publisher instance to which the memory belongs
* \param[in] allocator Allocator instance in case middleware cannot allocate messages
* \param[in] allocator Allocator instance in case middleware can not allocate messages
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
*/
LoanedMessage(
const rclcpp::PublisherBase & pub,
MessageAllocator allocator)
std::allocator<MessageT> allocator)
: pub_(pub),
message_(nullptr),
message_allocator_(std::move(allocator))
@@ -81,6 +82,36 @@ public:
}
}
/// Constructor of the LoanedMessage class.
/**
* The constructor of this class allocates memory for a given message type
* and associates this with a given publisher.
*
* Given the publisher instance, a case differentiation is being performaned
* which decides whether the underlying middleware is able to allocate the appropriate
* memory for this message type or not.
* In the case that the middleware can not loan messages, the passed in allocator instance
* is being used to allocate the message within the scope of this class.
* Otherwise, the allocator is being ignored and the allocation is solely performaned
* in the underlying middleware with its appropriate allocation strategy.
* The need for this arises as the user code can be written explicitly targeting a middleware
* capable of loaning messages.
* However, this user code is ought to be usable even when dynamically linked against
* a middleware which doesn't support message loaning in which case the allocator will be used.
*
* \param[in] pub rclcpp::Publisher instance to which the memory belongs
* \param[in] allocator Allocator instance in case middleware can not allocate messages
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
*/
[[
deprecated("used the LoanedMessage constructor that does not use a shared_ptr to the allocator")
]]
LoanedMessage(
const rclcpp::PublisherBase * pub,
std::shared_ptr<std::allocator<MessageT>> allocator)
: LoanedMessage(*pub, *allocator)
{}
/// Move semantic for RVO
LoanedMessage(LoanedMessage<MessageT> && other)
: pub_(std::move(other.pub_)),

View File

@@ -15,7 +15,6 @@
#ifndef RCLCPP__LOGGER_HPP_
#define RCLCPP__LOGGER_HPP_
#include <filesystem>
#include <memory>
#include <string>
#include <utility>
@@ -87,8 +86,8 @@ get_node_logger(const rcl_node_t * node);
* \throws rclcpp::exceptions::RCLError if an unexpected error occurs.
*/
RCLCPP_PUBLIC
std::filesystem::path
get_log_directory();
rcpputils::fs::path
get_logging_directory();
class Logger
{

View File

@@ -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_

View File

@@ -18,7 +18,6 @@
#include <memory>
#include <stdexcept>
#include "rcl/allocator.h"
#include "rcl/types.h"
#include "rclcpp/allocator/allocator_common.hpp"
@@ -62,16 +61,7 @@ public:
message_allocator_ = std::make_shared<MessageAlloc>();
serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>();
buffer_allocator_ = std::make_shared<BufferAlloc>();
if constexpr (std::is_same_v<Alloc, std::allocator<void>>) {
rcutils_allocator_ = rcl_get_default_allocator();
} else {
if constexpr (rclcpp::allocator::has_get_rcl_allocator_v<Alloc>) {
rcutils_allocator_ = message_allocator_->get_rcl_allocator();
} else {
rcutils_allocator_ = allocator::get_rcl_allocator<char,
BufferAlloc>(*buffer_allocator_.get());
}
}
rcutils_allocator_ = allocator::get_rcl_allocator<char, BufferAlloc>(*buffer_allocator_.get());
}
explicit MessageMemoryStrategy(std::shared_ptr<Alloc> allocator)
@@ -79,16 +69,7 @@ public:
message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>(*allocator.get());
buffer_allocator_ = std::make_shared<BufferAlloc>(*allocator.get());
if constexpr (std::is_same_v<Alloc, std::allocator<void>>) {
rcutils_allocator_ = rcl_get_default_allocator();
} else {
if constexpr (rclcpp::allocator::has_get_rcl_allocator_v<Alloc>) {
rcutils_allocator_ = allocator->get_rcl_allocator();
} else {
rcutils_allocator_ = allocator::get_rcl_allocator<char,
BufferAlloc>(*buffer_allocator_.get());
}
}
rcutils_allocator_ = allocator::get_rcl_allocator<char, BufferAlloc>(*buffer_allocator_.get());
}
virtual ~MessageMemoryStrategy() = default;

View File

@@ -44,7 +44,6 @@
#include "rclcpp/event.hpp"
#include "rclcpp/generic_client.hpp"
#include "rclcpp/generic_publisher.hpp"
#include "rclcpp/generic_service.hpp"
#include "rclcpp/generic_subscription.hpp"
#include "rclcpp/logger.hpp"
#include "rclcpp/macros.hpp"
@@ -242,7 +241,7 @@ public:
create_wall_timer(
std::chrono::duration<DurationRepT, DurationT> period,
CallbackT callback,
const rclcpp::CallbackGroup::SharedPtr & group = nullptr,
rclcpp::CallbackGroup::SharedPtr group = nullptr,
bool autostart = true);
/// Create a timer that uses the node clock to drive the callback.
@@ -256,7 +255,23 @@ public:
create_timer(
std::chrono::duration<DurationRepT, DurationT> period,
CallbackT callback,
const rclcpp::CallbackGroup::SharedPtr & group = nullptr);
rclcpp::CallbackGroup::SharedPtr group = nullptr);
/// Create and return a Client.
/**
* \param[in] service_name The topic to service on.
* \param[in] qos_profile rmw_qos_profile_t Quality of service profile for client.
* \param[in] group Callback group to call the service.
* \return Shared pointer to the created client.
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
*/
template<typename ServiceT>
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
typename rclcpp::Client<ServiceT>::SharedPtr
create_client(
const std::string & service_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::CallbackGroup::SharedPtr group = nullptr);
/// Create and return a Client.
/**
@@ -270,7 +285,25 @@ public:
create_client(
const std::string & service_name,
const rclcpp::QoS & qos = rclcpp::ServicesQoS(),
const rclcpp::CallbackGroup::SharedPtr & group = nullptr);
rclcpp::CallbackGroup::SharedPtr group = nullptr);
/// Create and return a Service.
/**
* \param[in] service_name The topic to service on.
* \param[in] callback User-defined callback function.
* \param[in] qos_profile rmw_qos_profile_t Quality of service profile for client.
* \param[in] group Callback group to call the service.
* \return Shared pointer to the created service.
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
*/
template<typename ServiceT, typename CallbackT>
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
typename rclcpp::Service<ServiceT>::SharedPtr
create_service(
const std::string & service_name,
CallbackT && callback,
const rmw_qos_profile_t & qos_profile,
rclcpp::CallbackGroup::SharedPtr group = nullptr);
/// Create and return a Service.
/**
@@ -286,7 +319,7 @@ public:
const std::string & service_name,
CallbackT && callback,
const rclcpp::QoS & qos = rclcpp::ServicesQoS(),
const rclcpp::CallbackGroup::SharedPtr & group = nullptr);
rclcpp::CallbackGroup::SharedPtr group = nullptr);
/// Create and return a GenericClient.
/**
@@ -302,25 +335,7 @@ public:
const std::string & service_name,
const std::string & service_type,
const rclcpp::QoS & qos = rclcpp::ServicesQoS(),
const rclcpp::CallbackGroup::SharedPtr & group = nullptr);
/// Create and return a GenericService.
/**
* \param[in] service_name The topic to service on.
* \param[in] service_type The name of service type, e.g. "std_srvs/srv/SetBool"
* \param[in] callback User-defined callback function.
* \param[in] qos Quality of service profile for the service.
* \param[in] group Callback group to call the service.
* \return Shared pointer to the created service.
*/
template<typename CallbackT>
typename rclcpp::GenericService::SharedPtr
create_generic_service(
const std::string & service_name,
const std::string & service_type,
CallbackT && callback,
const rclcpp::QoS & qos = rclcpp::ServicesQoS(),
const rclcpp::CallbackGroup::SharedPtr & group = nullptr);
rclcpp::CallbackGroup::SharedPtr group = nullptr);
/// Create and return a GenericPublisher.
/**
@@ -1000,6 +1015,8 @@ public:
rclcpp::node_interfaces::OnSetParametersCallbackHandle;
using OnSetParametersCallbackType =
rclcpp::node_interfaces::NodeParametersInterface::OnSetParametersCallbackType;
using OnParametersSetCallbackType [[deprecated("use OnSetParametersCallbackType instead")]] =
OnSetParametersCallbackType;
using PostSetParametersCallbackHandle =
rclcpp::node_interfaces::PostSetParametersCallbackHandle;
@@ -1388,66 +1405,6 @@ public:
std::vector<rclcpp::TopicEndpointInfo>
get_subscriptions_info_by_topic(const std::string & topic_name, bool no_mangle = false) const;
/// Return the service endpoint information about clients on a given service.
/**
* The returned parameter is a list of service endpoint information, where each item will contain
* the node name, node namespace, service type, endpoint type, endpoint count,
* service endpoint's GIDs, and its QoS profiles.
*
* When the `no_mangle` parameter is `true`, the provided `service_name` should be a valid service
* name for the middleware (useful when combining ROS with native middleware apps).
* When the `no_mangle` parameter is `false`, the provided `service_name` should follow
* ROS service name conventions. In DDS-based RMWs, services are implemented as topics with mangled
* names (e.g., `rq/my_serviceRequest` and `rp/my_serviceReply`), so `no_mangle = true` is not
* supported and will result in an error. Use `get_publishers_info_by_topic` or
* `get_subscriptions_info_by_topic` for unmangled topic queries in such cases. Other RMWs
* (e.g., Zenoh) may support `no_mangle = true` if they natively handle services without topic-based
*
* 'service_name` may be a relative, private, or fully qualified service name.
* A relative or private service will be expanded using this node's namespace and name.
* The queried `service_name` is not remapped.
*
* \param[in] service_name the actual service name used; it will not be automatically remapped.
* \param[in] no_mangle if `true`, `service_name` needs to be a valid middleware service name,
* otherwise it should be a valid ROS service name. Defaults to `false`.
* \return a list of SeviceEndpointInfo representing all the clients on this service.
* \throws InvalidServiceNameError if the given service_name is invalid.
* \throws std::runtime_error if internal error happens.
*/
RCLCPP_PUBLIC
std::vector<rclcpp::ServiceEndpointInfo>
get_clients_info_by_service(const std::string & service_name, bool no_mangle = false) const;
/// Return the service endpoint information about servers on a given service.
/**
* The returned parameter is a list of service endpoint information, where each item will contain
* the node name, node namespace, service type, endpoint type, endpoint count,
* service endpoint's GIDs, and its QoS profiles.
*
* When the `no_mangle` parameter is `true`, the provided `service_name` should be a valid service
* name for the middleware (useful when combining ROS with native middleware apps).
* When the `no_mangle` parameter is `false`, the provided `service_name` should follow
* ROS service name conventions. In DDS-based RMWs, services are implemented as topics with mangled
* names (e.g., `rq/my_serviceRequest` and `rp/my_serviceReply`), so `no_mangle = true` is not
* supported and will result in an error. Use `rcl_get_publishers_info_by_topic` or
* `rcl_get_subscriptions_info_by_topic` for unmangled topic queries in such cases. Other RMWs
* (e.g., Zenoh) may support `no_mangle = true` if they natively handle services without topic-based
*
* 'service_name` may be a relative, private, or fully qualified service name.
* A relative or private service will be expanded using this node's namespace and name.
* The queried `service_name` is not remapped.
*
* \param[in] service_name the actual service name used; it will not be automatically remapped.
* \param[in] no_mangle if `true`, `service_name` needs to be a valid middleware service name,
* otherwise it should be a valid ROS service name. Defaults to `false`.
* \return a list of SeviceEndpointInfo representing all the servers on this service.
* \throws InvalidServiceNameError if the given service_name is invalid.
* \throws std::runtime_error if internal error happens.
*/
RCLCPP_PUBLIC
std::vector<rclcpp::ServiceEndpointInfo>
get_servers_info_by_service(const std::string & service_name, bool no_mangle = false) const;
/// Return a graph event, which will be set anytime a graph change occurs.
/* The graph Event object is a loan which must be returned.
* The Event object is scoped and therefore to return the loan just let it go
@@ -1471,7 +1428,7 @@ public:
RCLCPP_PUBLIC
void
wait_for_graph_change(
const rclcpp::Event::SharedPtr & event,
rclcpp::Event::SharedPtr event,
std::chrono::nanoseconds timeout);
/// Get a clock as a non-const shared pointer which is managed by the node.
@@ -1490,7 +1447,7 @@ public:
rclcpp::Clock::ConstSharedPtr
get_clock() const;
/// Returns current time from the node clock.
/// Returns current time from the time source specified by clock_type.
/**
* \sa rclcpp::Clock::now
*/
@@ -1619,10 +1576,6 @@ public:
* which has been created using an existing instance of this class, but which
* has an additional sub-namespace (short for subordinate namespace)
* associated with it.
* A subordinate node and an instance of this class share all the node interfaces
* such as `rclcpp::node_interfaces::NodeParametersInterface`.
* Subordinate nodes are primarily used to organize namespaces and provide a
* hierarchical structure, but they are not meant to be completely independent nodes.
* The sub-namespace will extend the node's namespace for the purpose of
* creating additional entities, such as Publishers, Subscriptions, Service
* Clients and Servers, and so on.

View File

@@ -40,7 +40,6 @@
#include "rclcpp/create_generic_subscription.hpp"
#include "rclcpp/create_publisher.hpp"
#include "rclcpp/create_service.hpp"
#include "rclcpp/create_generic_service.hpp"
#include "rclcpp/create_subscription.hpp"
#include "rclcpp/create_timer.hpp"
#include "rclcpp/detail/resolve_enable_topic_statistics.hpp"
@@ -111,7 +110,7 @@ typename rclcpp::WallTimer<CallbackT>::SharedPtr
Node::create_wall_timer(
std::chrono::duration<DurationRepT, DurationT> period,
CallbackT callback,
const rclcpp::CallbackGroup::SharedPtr & group,
rclcpp::CallbackGroup::SharedPtr group,
bool autostart)
{
return rclcpp::create_wall_timer(
@@ -128,7 +127,7 @@ typename rclcpp::GenericTimer<CallbackT>::SharedPtr
Node::create_timer(
std::chrono::duration<DurationRepT, DurationT> period,
CallbackT callback,
const rclcpp::CallbackGroup::SharedPtr & group)
rclcpp::CallbackGroup::SharedPtr group)
{
return rclcpp::create_timer(
this->get_clock(),
@@ -144,7 +143,7 @@ typename Client<ServiceT>::SharedPtr
Node::create_client(
const std::string & service_name,
const rclcpp::QoS & qos,
const rclcpp::CallbackGroup::SharedPtr & group)
rclcpp::CallbackGroup::SharedPtr group)
{
return rclcpp::create_client<ServiceT>(
node_base_,
@@ -155,13 +154,29 @@ Node::create_client(
group);
}
template<typename ServiceT>
typename Client<ServiceT>::SharedPtr
Node::create_client(
const std::string & service_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::CallbackGroup::SharedPtr group)
{
return rclcpp::create_client<ServiceT>(
node_base_,
node_graph_,
node_services_,
extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
qos_profile,
group);
}
template<typename ServiceT, typename CallbackT>
typename rclcpp::Service<ServiceT>::SharedPtr
Node::create_service(
const std::string & service_name,
CallbackT && callback,
const rclcpp::QoS & qos,
const rclcpp::CallbackGroup::SharedPtr & group)
rclcpp::CallbackGroup::SharedPtr group)
{
return rclcpp::create_service<ServiceT, CallbackT>(
node_base_,
@@ -172,22 +187,20 @@ Node::create_service(
group);
}
template<typename CallbackT>
typename rclcpp::GenericService::SharedPtr
Node::create_generic_service(
template<typename ServiceT, typename CallbackT>
typename rclcpp::Service<ServiceT>::SharedPtr
Node::create_service(
const std::string & service_name,
const std::string & service_type,
CallbackT && callback,
const rclcpp::QoS & qos,
const rclcpp::CallbackGroup::SharedPtr & group)
const rmw_qos_profile_t & qos_profile,
rclcpp::CallbackGroup::SharedPtr group)
{
return rclcpp::create_generic_service<CallbackT>(
return rclcpp::create_service<ServiceT, CallbackT>(
node_base_,
node_services_,
extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
service_type,
std::forward<CallbackT>(callback),
qos,
qos_profile,
group);
}
@@ -323,9 +336,11 @@ template<typename ParameterT>
bool
Node::get_parameter(const std::string & name, ParameterT & parameter) const
{
std::string sub_name = extend_name_with_sub_namespace(name, this->get_sub_namespace());
rclcpp::Parameter parameter_variant;
bool result = get_parameter(name, parameter_variant);
bool result = get_parameter(sub_name, parameter_variant);
if (result) {
parameter = static_cast<ParameterT>(parameter_variant.get_value<ParameterT>());
}
@@ -340,7 +355,9 @@ Node::get_parameter_or(
ParameterT & parameter,
const ParameterT & alternative_value) const
{
bool got_parameter = get_parameter(name, parameter);
std::string sub_name = extend_name_with_sub_namespace(name, this->get_sub_namespace());
bool got_parameter = get_parameter(sub_name, parameter);
if (!got_parameter) {
parameter = alternative_value;
}

View File

@@ -199,12 +199,6 @@ 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*

View File

@@ -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;

View File

@@ -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.

View File

@@ -33,7 +33,6 @@
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rmw/service_endpoint_info_array.h"
#include "rmw/topic_endpoint_info_array.h"
namespace rclcpp
@@ -160,24 +159,14 @@ public:
const std::string & topic_name,
bool no_mangle = false) const override;
RCLCPP_PUBLIC
std::vector<rclcpp::ServiceEndpointInfo>
get_clients_info_by_service(
const std::string & service_name,
bool no_mangle = false) const override;
RCLCPP_PUBLIC
std::vector<rclcpp::ServiceEndpointInfo>
get_servers_info_by_service(
const std::string & service_name,
bool no_mangle = false) const override;
private:
RCLCPP_DISABLE_COPY(NodeGraph)
/// 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_;

View File

@@ -18,8 +18,6 @@
#include <algorithm>
#include <array>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <map>
#include <string>
#include <tuple>
@@ -42,9 +40,7 @@ enum class EndpointType
{
Invalid = RMW_ENDPOINT_INVALID,
Publisher = RMW_ENDPOINT_PUBLISHER,
Subscription = RMW_ENDPOINT_SUBSCRIPTION,
Client = RMW_ENDPOINT_CLIENT,
Server = RMW_ENDPOINT_SERVER
Subscription = RMW_ENDPOINT_SUBSCRIPTION
};
/**
@@ -57,17 +53,13 @@ public:
/// Construct a TopicEndpointInfo from a rcl_topic_endpoint_info_t.
RCLCPP_PUBLIC
explicit TopicEndpointInfo(const rcl_topic_endpoint_info_t & info)
: endpoint_type_(static_cast<rclcpp::EndpointType>(info.endpoint_type)),
: node_name_(info.node_name),
node_namespace_(info.node_namespace),
topic_type_(info.topic_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());
}
@@ -151,125 +143,6 @@ private:
rosidl_type_hash_t topic_type_hash_;
};
/**
* Struct that contains service endpoint information like the associated node name, node namespace,
* service type, endpoint type, endpoint count, endpoint GIDs, and its QoS profiles.
*/
class ServiceEndpointInfo
{
public:
/// Construct a ServiceEndpointInfo from a rcl_service_endpoint_info_t.
RCLCPP_PUBLIC
explicit ServiceEndpointInfo(const rcl_service_endpoint_info_t & info)
: node_name_(info.node_name),
node_namespace_(info.node_namespace),
service_type_(info.service_type),
endpoint_type_(static_cast<rclcpp::EndpointType>(info.endpoint_type)),
service_type_hash_(info.service_type_hash),
endpoint_count_(info.endpoint_count)
{
for(size_t i = 0; i < endpoint_count_; i++) {
std::array<uint8_t, RMW_GID_STORAGE_SIZE> gid;
std::copy(info.endpoint_gids[i], info.endpoint_gids[i] + RMW_GID_STORAGE_SIZE, gid.begin());
endpoint_gids_.push_back(gid);
rclcpp::QoS qos(
{info.qos_profiles[i].history, info.qos_profiles[i].depth}, info.qos_profiles[i]);
qos_profiles_.push_back(qos);
}
}
/// Get a mutable reference to the node name.
RCLCPP_PUBLIC
std::string &
node_name();
/// Get a const reference to the node name.
RCLCPP_PUBLIC
const std::string &
node_name() const;
/// Get a mutable reference to the node namespace.
RCLCPP_PUBLIC
std::string &
node_namespace();
/// Get a const reference to the node namespace.
RCLCPP_PUBLIC
const std::string &
node_namespace() const;
/// Get a mutable reference to the service type string.
RCLCPP_PUBLIC
std::string &
service_type();
/// Get a const reference to the service type string.
RCLCPP_PUBLIC
const std::string &
service_type() const;
/// Get a mutable reference to the service endpoint type.
RCLCPP_PUBLIC
rclcpp::EndpointType &
endpoint_type();
/// Get a const reference to the service endpoint type.
RCLCPP_PUBLIC
const rclcpp::EndpointType &
endpoint_type() const;
/// Get a mutable reference to the endpoint count.
RCLCPP_PUBLIC
size_t &
endpoint_count();
/// Get a const reference to the endpoint count.
RCLCPP_PUBLIC
const size_t &
endpoint_count() const;
/// Get a mutable reference to the GID of the service endpoint.
RCLCPP_PUBLIC
std::vector<std::array<uint8_t, RMW_GID_STORAGE_SIZE>> &
endpoint_gids();
/// Get a const reference to the GID of the service endpoint.
RCLCPP_PUBLIC
const std::vector<std::array<uint8_t, RMW_GID_STORAGE_SIZE>> &
endpoint_gids() const;
/// Get a mutable reference to the QoS profile of the service endpoint.
RCLCPP_PUBLIC
std::vector<rclcpp::QoS> &
qos_profiles();
/// Get a const reference to the QoS profile of the service endpoint.
RCLCPP_PUBLIC
const std::vector<rclcpp::QoS> &
qos_profiles() const;
/// Get a mutable reference to the type hash of the service endpoint.
RCLCPP_PUBLIC
rosidl_type_hash_t &
service_type_hash();
/// Get a const reference to the type hash of the service endpoint.
RCLCPP_PUBLIC
const rosidl_type_hash_t &
service_type_hash() const;
private:
std::string node_name_;
std::string node_namespace_;
std::string service_type_;
rclcpp::EndpointType endpoint_type_;
std::vector<std::array<uint8_t, RMW_GID_STORAGE_SIZE>> endpoint_gids_;
std::vector<rclcpp::QoS> qos_profiles_;
rosidl_type_hash_t service_type_hash_;
size_t endpoint_count_;
};
namespace node_interfaces
{
@@ -535,30 +408,6 @@ public:
virtual
std::vector<rclcpp::TopicEndpointInfo>
get_subscriptions_info_by_topic(const std::string & topic_name, bool no_mangle = false) const = 0;
/// Return the service endpoint information about clients on a given service.
/**
* \param[in] service_name the actual service name used; it will not be automatically remapped.
* \param[in] no_mangle if `true`, `service_name` needs to be a valid middleware service name,
* otherwise it should be a valid ROS service name.
* \sa rclcpp::Node::get_clients_info_by_service
*/
RCLCPP_PUBLIC
virtual
std::vector<rclcpp::ServiceEndpointInfo>
get_clients_info_by_service(const std::string & service_name, bool no_mangle = false) const = 0;
/// Return the service endpoint information about servers on a given service.
/**
* \param[in] service_name the actual service name used; it will not be automatically remapped.
* \param[in] no_mangle if `true`, `service_name` needs to be a valid middleware service name,
* otherwise it should be a valid ROS service name.
* \sa rclcpp::Node::get_servers_info_by_service
*/
RCLCPP_PUBLIC
virtual
std::vector<rclcpp::ServiceEndpointInfo>
get_servers_info_by_service(const std::string & service_name, bool no_mangle = false) const = 0;
};
} // namespace node_interfaces

View File

@@ -38,7 +38,7 @@ public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeLoggingInterface)
RCLCPP_PUBLIC
explicit NodeLogging(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_base);
explicit NodeLogging(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base);
RCLCPP_PUBLIC
virtual
@@ -55,7 +55,7 @@ public:
RCLCPP_PUBLIC
void
create_logger_services(
const node_interfaces::NodeServicesInterface::SharedPtr & node_services) override;
node_interfaces::NodeServicesInterface::SharedPtr node_services) override;
private:
RCLCPP_DISABLE_COPY(NodeLogging)

View File

@@ -61,7 +61,7 @@ public:
virtual
void
create_logger_services(
const node_interfaces::NodeServicesInterface::SharedPtr & node_services) = 0;
node_interfaces::NodeServicesInterface::SharedPtr node_services) = 0;
};
} // namespace node_interfaces

View File

@@ -214,10 +214,6 @@ public:
const std::map<std::string, rclcpp::ParameterValue> &
get_parameter_overrides() const override;
RCLCPP_PUBLIC
void
enable_parameter_modification() override;
using PreSetCallbacksHandleContainer = std::list<PreSetParametersCallbackHandle::WeakPtr>;
using OnSetCallbacksHandleContainer = std::list<OnSetParametersCallbackHandle::WeakPtr>;
using PostSetCallbacksHandleContainer = std::list<PostSetParametersCallbackHandle::WeakPtr>;

View File

@@ -52,6 +52,8 @@ struct OnSetParametersCallbackHandle
std::function<
rcl_interfaces::msg::SetParametersResult(
const std::vector<rclcpp::Parameter> &)>;
using OnParametersSetCallbackType [[deprecated("use OnSetParametersCallbackType instead")]] =
OnSetParametersCallbackType;
OnSetParametersCallbackType callback;
};
@@ -270,26 +272,6 @@ public:
virtual
const std::map<std::string, rclcpp::ParameterValue> &
get_parameter_overrides() const = 0;
/// Enable parameter modification recursively during parameter callbacks.
/**
* This function is used to enable parameter modification during parameter callbacks.
*
* There are times when it does not allow parameter modification, such as when the parameter
* callbacks are being called and tries to modify the parameters with set_parameter and
* declare_parameter to avoid recursive parameter modification.
* This is protected by rclcpp::node_interfaces::ParameterMutationRecursionGuard.
*
* This function is explicitly called to allow the recursive parameter operation during
* parameter callbacks by the application.
* Once it is enabled, the next parameter operation set/declare/undeclare_parameter are
* allowed to execute in the parameter callback. But, no more further recursive operation
* is allowed, unless user application calls this API again.
*/
RCLCPP_PUBLIC
virtual
void
enable_parameter_modification() = 0;
};
} // namespace node_interfaces

View File

@@ -39,10 +39,10 @@ public:
RCLCPP_PUBLIC
explicit NodeTypeDescriptions(
const NodeBaseInterface::SharedPtr & node_base,
const NodeLoggingInterface::SharedPtr & node_logging,
const NodeParametersInterface::SharedPtr & node_parameters,
const NodeServicesInterface::SharedPtr & node_services);
NodeBaseInterface::SharedPtr node_base,
NodeLoggingInterface::SharedPtr node_logging,
NodeParametersInterface::SharedPtr node_parameters,
NodeServicesInterface::SharedPtr node_services);
RCLCPP_PUBLIC
virtual

View File

@@ -100,7 +100,7 @@ public:
/// Set the context, return this for parameter idiom.
RCLCPP_PUBLIC
NodeOptions &
context(const rclcpp::Context::SharedPtr & context);
context(rclcpp::Context::SharedPtr context);
/// Return a reference to the list of arguments for the node.
RCLCPP_PUBLIC

View File

@@ -52,6 +52,37 @@ class AsyncParametersClient
public:
RCLCPP_SMART_PTR_DEFINITIONS(AsyncParametersClient)
/// Create an async parameters client.
/**
* \param[in] node_base_interface The node base interface of the corresponding node.
* \param[in] node_topics_interface Node topic base interface.
* \param[in] node_graph_interface The node graph interface of the corresponding node.
* \param[in] node_services_interface Node service interface.
* \param[in] remote_node_name Name of the remote node
* \param[in] qos_profile The rmw qos profile to use to subscribe
* \param[in] group (optional) The async parameter client will be added to this callback group.
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
*/
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
RCLCPP_PUBLIC
AsyncParametersClient(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::CallbackGroup::SharedPtr group = nullptr)
: AsyncParametersClient(
node_base_interface,
node_topics_interface,
node_graph_interface,
node_services_interface,
remote_node_name,
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)),
group)
{}
/// Create an async parameters client.
/**
* \param[in] node_base_interface The node base interface of the corresponding node.
@@ -64,13 +95,38 @@ public:
*/
RCLCPP_PUBLIC
AsyncParametersClient(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_base_interface,
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr & node_topics_interface,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr & node_graph_interface,
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr & node_services_interface,
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
const std::string & remote_node_name = "",
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS(),
const rclcpp::CallbackGroup::SharedPtr & group = nullptr);
rclcpp::CallbackGroup::SharedPtr group = nullptr);
/// Constructor
/**
* \param[in] node The async parameters client will be added to this node.
* \param[in] remote_node_name name of the remote node
* \param[in] qos_profile The rmw qos profile to use to subscribe
* \param[in] group (optional) The async parameter client will be added to this callback group.
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
*/
template<typename NodeT>
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
AsyncParametersClient(
const std::shared_ptr<NodeT> node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::CallbackGroup::SharedPtr group = nullptr)
: AsyncParametersClient(
node->get_node_base_interface(),
node->get_node_topics_interface(),
node->get_node_graph_interface(),
node->get_node_services_interface(),
remote_node_name,
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)),
group)
{}
/**
* \param[in] node The async parameters client will be added to this node.
@@ -80,10 +136,10 @@ public:
*/
template<typename NodeT>
explicit AsyncParametersClient(
const std::shared_ptr<NodeT> & node,
const std::shared_ptr<NodeT> node,
const std::string & remote_node_name = "",
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS(),
const rclcpp::CallbackGroup::SharedPtr & group = nullptr)
rclcpp::CallbackGroup::SharedPtr group = nullptr)
: AsyncParametersClient(
node->get_node_base_interface(),
node->get_node_topics_interface(),
@@ -94,6 +150,31 @@ public:
group)
{}
/// Constructor
/**
* \param[in] node The async parameters client will be added to this node.
* \param[in] remote_node_name Name of the remote node
* \param[in] qos_profile The rmw qos profile to use to subscribe
* \param[in] group (optional) The async parameter client will be added to this callback group.
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
*/
template<typename NodeT>
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
AsyncParametersClient(
NodeT * node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::CallbackGroup::SharedPtr group = nullptr)
: AsyncParametersClient(
node->get_node_base_interface(),
node->get_node_topics_interface(),
node->get_node_graph_interface(),
node->get_node_services_interface(),
remote_node_name,
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)),
group)
{}
/**
* \param[in] node The async parameters client will be added to this node.
* \param[in] remote_node_name (optional) name of the remote node
@@ -105,7 +186,7 @@ public:
NodeT * node,
const std::string & remote_node_name = "",
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS(),
const rclcpp::CallbackGroup::SharedPtr & group = nullptr)
rclcpp::CallbackGroup::SharedPtr group = nullptr)
: AsyncParametersClient(
node->get_node_base_interface(),
node->get_node_topics_interface(),
@@ -120,41 +201,41 @@ public:
std::shared_future<std::vector<rclcpp::Parameter>>
get_parameters(
const std::vector<std::string> & names,
const std::function<
std::function<
void(std::shared_future<std::vector<rclcpp::Parameter>>)
> & callback = nullptr);
> callback = nullptr);
RCLCPP_PUBLIC
std::shared_future<std::vector<rcl_interfaces::msg::ParameterDescriptor>>
describe_parameters(
const std::vector<std::string> & names,
const std::function<
std::function<
void(std::shared_future<std::vector<rcl_interfaces::msg::ParameterDescriptor>>)
> & callback = nullptr);
> callback = nullptr);
RCLCPP_PUBLIC
std::shared_future<std::vector<rclcpp::ParameterType>>
get_parameter_types(
const std::vector<std::string> & names,
const std::function<
std::function<
void(std::shared_future<std::vector<rclcpp::ParameterType>>)
> & callback = nullptr);
> callback = nullptr);
RCLCPP_PUBLIC
std::shared_future<std::vector<rcl_interfaces::msg::SetParametersResult>>
set_parameters(
const std::vector<rclcpp::Parameter> & parameters,
const std::function<
std::function<
void(std::shared_future<std::vector<rcl_interfaces::msg::SetParametersResult>>)
> & callback = nullptr);
> callback = nullptr);
RCLCPP_PUBLIC
std::shared_future<rcl_interfaces::msg::SetParametersResult>
set_parameters_atomically(
const std::vector<rclcpp::Parameter> & parameters,
const std::function<
std::function<
void(std::shared_future<rcl_interfaces::msg::SetParametersResult>)
> & callback = nullptr);
> callback = nullptr);
/// Delete several parameters at once.
/**
@@ -200,9 +281,9 @@ public:
list_parameters(
const std::vector<std::string> & prefixes,
uint64_t depth,
const std::function<
std::function<
void(std::shared_future<rcl_interfaces::msg::ListParametersResult>)
> & callback = nullptr);
> callback = nullptr);
template<
typename CallbackT,
@@ -302,9 +383,22 @@ class SyncParametersClient
public:
RCLCPP_SMART_PTR_DEFINITIONS(SyncParametersClient)
template<typename NodeT>
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
SyncParametersClient(
std::shared_ptr<NodeT> node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile)
: SyncParametersClient(
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
node,
remote_node_name,
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)))
{}
template<typename NodeT>
explicit SyncParametersClient(
const std::shared_ptr<NodeT> & node,
std::shared_ptr<NodeT> node,
const std::string & remote_node_name = "",
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS())
: SyncParametersClient(
@@ -315,9 +409,26 @@ public:
{}
template<typename NodeT>
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
SyncParametersClient(
const rclcpp::Executor::SharedPtr & executor,
const std::shared_ptr<NodeT> & node,
rclcpp::Executor::SharedPtr executor,
std::shared_ptr<NodeT> node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile)
: SyncParametersClient(
executor,
node->get_node_base_interface(),
node->get_node_topics_interface(),
node->get_node_graph_interface(),
node->get_node_services_interface(),
remote_node_name,
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)))
{}
template<typename NodeT>
SyncParametersClient(
rclcpp::Executor::SharedPtr executor,
std::shared_ptr<NodeT> node,
const std::string & remote_node_name = "",
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS())
: SyncParametersClient(
@@ -330,6 +441,19 @@ public:
qos_profile)
{}
template<typename NodeT>
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
SyncParametersClient(
NodeT * node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile)
: SyncParametersClient(
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
node,
remote_node_name,
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)))
{}
template<typename NodeT>
explicit SyncParametersClient(
NodeT * node,
@@ -343,8 +467,25 @@ public:
{}
template<typename NodeT>
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
SyncParametersClient(
const rclcpp::Executor::SharedPtr & executor,
rclcpp::Executor::SharedPtr executor,
NodeT * node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile)
: SyncParametersClient(
executor,
node->get_node_base_interface(),
node->get_node_topics_interface(),
node->get_node_graph_interface(),
node->get_node_services_interface(),
remote_node_name,
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)))
{}
template<typename NodeT>
SyncParametersClient(
rclcpp::Executor::SharedPtr executor,
NodeT * node,
const std::string & remote_node_name = "",
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS())
@@ -358,13 +499,35 @@ public:
qos_profile)
{}
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
RCLCPP_PUBLIC
SyncParametersClient(
rclcpp::Executor::SharedPtr executor,
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile)
: executor_(executor), node_base_interface_(node_base_interface)
{
async_parameters_client_ =
std::make_shared<AsyncParametersClient>(
node_base_interface,
node_topics_interface,
node_graph_interface,
node_services_interface,
remote_node_name,
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)));
}
RCLCPP_PUBLIC
SyncParametersClient(
const rclcpp::Executor::SharedPtr & executor,
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_base_interface,
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr & node_topics_interface,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr & node_graph_interface,
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr & node_services_interface,
rclcpp::Executor::SharedPtr executor,
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
const std::string & remote_node_name = "",
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS())
: executor_(executor), node_base_interface_(node_base_interface)

View File

@@ -1,82 +0,0 @@
// Copyright 2023 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__PARAMETER_DESCRIPTOR_WRAPPER_HPP_
#define RCLCPP__PARAMETER_DESCRIPTOR_WRAPPER_HPP_
// C++ Standard library includes
#include <functional>
#include <utility>
#include <memory>
#include <string>
// Additional ROS libraries needed
#include "rcl_interfaces/msg/parameter_descriptor.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/parameter_value.hpp"
#include "rclcpp/node_interfaces/get_node_parameters_interface.hpp"
#include "rclcpp/visibility_control.hpp"
#include "node_interfaces/node_parameters_interface.hpp"
namespace rclcpp
{
// Implements ParameterDesription class with builder design pattern
class ParameterDescription
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(ParameterDescription)
// List of classes the builder manages
RCLCPP_PUBLIC
ParameterDescription();
// Our Main build methods which will construct the base class
RCLCPP_PUBLIC rcl_interfaces::msg::ParameterDescriptor build() const;
// Builder Methods:
// Describes the instances in a parameter_description object
RCLCPP_PUBLIC ParameterDescription & set_name(const std::string & name);
RCLCPP_PUBLIC ParameterDescription & set_type(std::uint8_t type);
RCLCPP_PUBLIC ParameterDescription & set_description_text(const std::string & description);
RCLCPP_PUBLIC ParameterDescription & set_additional_constraints(const std::string & constraints);
RCLCPP_PUBLIC ParameterDescription & set_read_only(bool read_only);
RCLCPP_PUBLIC ParameterDescription & set_dynamic_typing(bool dynamic_typing);
RCLCPP_PUBLIC ParameterDescription & set_floating_point_description_range(
float min, float max, float step);
RCLCPP_PUBLIC ParameterDescription & set_integer_description_range(int min, int max, int step);
// Need the current node in order to begin the configuration state
// for it via the declare_parameter function
template<typename NodeT>
ParameterDescription & declare_parameter(
const rclcpp::ParameterValue & default_value,
NodeT && node)
{
auto node_param = rclcpp::node_interfaces::get_node_parameters_interface(node);
node_param->declare_parameter(
parameter_descriptor.name, default_value,
parameter_descriptor);
return *this;
}
private:
// The main descriptor object we're meant to initialize and adjust
rcl_interfaces::msg::ParameterDescriptor parameter_descriptor;
};
} // namespace rclcpp
#endif // RCLCPP__PARAMETER_DESCRIPTOR_WRAPPER_HPP_

View File

@@ -67,23 +67,19 @@ struct ParameterEventCallbackHandle
* The first step is to instantiate a ParameterEventHandler, providing a ROS node to use
* to create any required subscriptions:
*
* ```cpp
* auto param_handler = std::make_shared<rclcpp::ParameterEventHandler>(node);
* ```
* auto param_handler = std::make_shared<rclcpp::ParameterEventHandler>(node);
*
* Next, you can supply a callback to the add_parameter_callback method, as follows:
*
* ```cpp
* auto cb1 = [&node](const rclcpp::Parameter & p) {
* RCLCPP_INFO(
* node->get_logger(),
* "cb1: Received an update to parameter \"%s\" of type %s: \"%ld\"",
* p.get_name().c_str(),
* p.get_type_name().c_str(),
* p.as_int());
* };
* auto handle1 = param_handler->add_parameter_callback("an_int_param", cb1);
* ```
* auto cb1 = [&node](const rclcpp::Parameter & p) {
* RCLCPP_INFO(
* node->get_logger(),
* "cb1: Received an update to parameter \"%s\" of type %s: \"%ld\"",
* p.get_name().c_str(),
* p.get_type_name().c_str(),
* p.as_int());
* };
* auto handle1 = param_handler->add_parameter_callback("an_int_param", cb1);
*
* In this case, we didn't supply a node name (the third, optional, parameter) so the
* default will be to monitor for changes to the "an_int_param" parameter associated with
@@ -96,18 +92,16 @@ struct ParameterEventCallbackHandle
* You may also monitor for changes to parameters in other nodes by supplying the node
* name to add_parameter_callback:
*
* ```cpp
* auto cb2 = [&node](const rclcpp::Parameter & p) {
* RCLCPP_INFO(
* node->get_logger(),
* "cb2: Received an update to parameter \"%s\" of type: %s: \"%s\"",
* p.get_name().c_str(),
* p.get_type_name().c_str(),
* p.as_string().c_str());
* };
* auto handle2 = param_handler->add_parameter_callback(
* "some_remote_param_name", cb2, "some_remote_node_name");
* ```
* auto cb2 = [&node](const rclcpp::Parameter & p) {
* RCLCPP_INFO(
* node->get_logger(),
* "cb2: Received an update to parameter \"%s\" of type: %s: \"%s\"",
* p.get_name().c_str(),
* p.get_type_name().c_str(),
* p.as_string().c_str());
* };
* auto handle2 = param_handler->add_parameter_callback(
* "some_remote_param_name", cb2, "some_remote_node_name");
*
* In this case, the callback will be invoked whenever "some_remote_param_name" changes
* on remote node "some_remote_node_name".
@@ -115,9 +109,7 @@ struct ParameterEventCallbackHandle
* To remove a parameter callback, reset the callback handle smart pointer or call
* remove_parameter_callback, passing the handle returned from add_parameter_callback:
*
* ```cpp
* param_handler->remove_parameter_callback(handle2);
* ```
* param_handler->remove_parameter_callback(handle2);
*
* You can also monitor for *all* parameter changes, using add_parameter_event_callback.
* In this case, the callback will be invoked whenever any parameter changes in the system.
@@ -125,42 +117,40 @@ struct ParameterEventCallbackHandle
* is convenient to use a regular expression on the node names or namespaces of interest.
* For example:
*
* ```cpp
* auto cb3 =
* [fqn, remote_param_name, &node](const rcl_interfaces::msg::ParameterEvent & event) {
* // Look for any updates to parameters in "/a_namespace" as well as any parameter changes
* // to our own node ("this_node")
* std::regex re("(/a_namespace/.*)|(/this_node)");
* if (regex_match(event.node, re)) {
* // Now that we know the event matches the regular expression we scanned for, we can
* // use 'get_parameter_from_event' to get a specific parameter name that we're looking for
* rclcpp::Parameter p;
* if (rclcpp::ParameterEventHandler::get_parameter_from_event(
* event, p, remote_param_name, fqn))
* {
* RCLCPP_INFO(
* node->get_logger(),
* "cb3: Received an update to parameter \"%s\" of type: %s: \"%s\"",
* p.get_name().c_str(),
* p.get_type_name().c_str(),
* p.as_string().c_str());
* }
* auto cb3 =
* [fqn, remote_param_name, &node](const rcl_interfaces::msg::ParameterEvent & event) {
* // Look for any updates to parameters in "/a_namespace" as well as any parameter changes
* // to our own node ("this_node")
* std::regex re("(/a_namespace/.*)|(/this_node)");
* if (regex_match(event.node, re)) {
* // Now that we know the event matches the regular expression we scanned for, we can
* // use 'get_parameter_from_event' to get a specific parameter name that we're looking for
* rclcpp::Parameter p;
* if (rclcpp::ParameterEventsSubscriber::get_parameter_from_event(
* event, p, remote_param_name, fqn))
* {
* RCLCPP_INFO(
* node->get_logger(),
* "cb3: Received an update to parameter \"%s\" of type: %s: \"%s\"",
* p.get_name().c_str(),
* p.get_type_name().c_str(),
* p.as_string().c_str());
* }
*
* // You can also use 'get_parameter*s*_from_event' to enumerate all changes that came
* // in on this event
* auto params = rclcpp::ParameterEventHandler::get_parameters_from_event(event);
* for (auto & p : params) {
* RCLCPP_INFO(
* node->get_logger(),
* "cb3: Received an update to parameter \"%s\" of type: %s: \"%s\"",
* p.get_name().c_str(),
* p.get_type_name().c_str(),
* p.value_to_string().c_str());
* // You can also use 'get_parameter*s*_from_event' to enumerate all changes that came
* // in on this event
* auto params = rclcpp::ParameterEventsSubscriber::get_parameters_from_event(event);
* for (auto & p : params) {
* RCLCPP_INFO(
* node->get_logger(),
* "cb3: Received an update to parameter \"%s\" of type: %s: \"%s\"",
* p.get_name().c_str(),
* p.get_type_name().c_str(),
* p.value_to_string().c_str());
* }
* }
* }
* };
* auto handle3 = param_handler->add_parameter_event_callback(cb3);
* ```
* };
* auto handle3 = param_handler->add_parameter_event_callback(cb3);
*
* For both parameter callbacks and parameter event callbacks, when multiple callbacks are added,
* the callbacks are invoked last-in, first-called order (LIFO).
@@ -170,9 +160,7 @@ struct ParameterEventCallbackHandle
*
* To remove a parameter event callback, reset the callback smart pointer or use:
*
* ```cpp
* param_handler->remove_event_parameter_callback(handle3);
* ```
* param_handler->remove_event_parameter_callback(handle3);
*/
class ParameterEventHandler
{
@@ -184,7 +172,7 @@ public:
*/
template<typename NodeT>
explicit ParameterEventHandler(
const NodeT & node,
NodeT node,
const rclcpp::QoS & qos =
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events)))
: node_base_(rclcpp::node_interfaces::get_node_base_interface(node))
@@ -217,7 +205,7 @@ public:
RCUTILS_WARN_UNUSED
ParameterEventCallbackHandle::SharedPtr
add_parameter_event_callback(
const ParameterEventCallbackType & callback);
ParameterEventCallbackType callback);
/// Remove parameter event callback registered with add_parameter_event_callback.
/**
@@ -226,7 +214,7 @@ public:
RCLCPP_PUBLIC
void
remove_parameter_event_callback(
const ParameterEventCallbackHandle::SharedPtr & callback_handle);
ParameterEventCallbackHandle::SharedPtr callback_handle);
using ParameterCallbackType = ParameterCallbackHandle::ParameterCallbackType;
@@ -234,10 +222,6 @@ public:
/**
* If a node_name is not provided, defaults to the current node.
*
* The configure_nodes_filter() function will affect the behavior of this function.
* If the node specified in this function isn't included in the nodes specified in
* configure_nodes_filter(), the callback will never be called.
*
* Note: if the returned callback handle smart pointer is not captured, the callback
* is immediately unregistered. A compiler warning should be generated to warn
* of this.
@@ -252,34 +236,9 @@ public:
ParameterCallbackHandle::SharedPtr
add_parameter_callback(
const std::string & parameter_name,
const ParameterCallbackType & callback,
ParameterCallbackType callback,
const std::string & node_name = "");
/// Configure which node parameter events will be received.
/**
* This function depends on rmw implementation support for content filtering.
* If middleware doesn't support contentfilter, return false.
*
* If node_names is empty, the configured node filter will be cleared.
*
* If this function return true, only parameter events from the specified node will be received.
* It affects the behavior of the following two functions.
* - add_parameter_event_callback()
* The callback will only be called for parameter events from the specified nodes which are
* configured in this function.
* - add_parameter_callback()
* The callback will only be called for parameter events from the specified nodes which are
* configured in this function and add_parameter_callback().
* If the nodes specified in this function is different from the nodes specified in
* add_parameter_callback(), the callback will never be called.
*
* \param[in] node_names Node names to filter parameter events from.
* \returns true if configuring was successfully applied, false otherwise.
* \throws rclcpp::exceptions::RCLError if internal error occurred when calling the rcl function.
*/
RCLCPP_PUBLIC
bool configure_nodes_filter(const std::vector<std::string> & node_names);
/// Remove a parameter callback registered with add_parameter_callback.
/**
* The parameter name and node name are inspected from the callback handle. The callback handle
@@ -291,7 +250,7 @@ public:
RCLCPP_PUBLIC
void
remove_parameter_callback(
const ParameterCallbackHandle::SharedPtr & callback_handle);
ParameterCallbackHandle::SharedPtr callback_handle);
/// Get an rclcpp::Parameter from a parameter event.
/**

View File

@@ -40,10 +40,24 @@ class ParameterService
public:
RCLCPP_SMART_PTR_DEFINITIONS(ParameterService)
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
RCLCPP_PUBLIC
ParameterService(
const std::shared_ptr<node_interfaces::NodeBaseInterface> & node_base,
const std::shared_ptr<node_interfaces::NodeServicesInterface> & node_services,
const std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
const std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
rclcpp::node_interfaces::NodeParametersInterface * node_params,
const rmw_qos_profile_t & qos_profile)
: ParameterService(
node_base,
node_services,
node_params,
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)))
{}
RCLCPP_PUBLIC
ParameterService(
const std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
const std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
rclcpp::node_interfaces::NodeParametersInterface * node_params,
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS());

View File

@@ -359,7 +359,7 @@ private:
/// Return the value of a parameter as a string
RCLCPP_PUBLIC
std::string
to_string(const ParameterValue & value);
to_string(const ParameterValue & type);
} // namespace rclcpp

View File

@@ -96,6 +96,22 @@ public:
using ROSMessageTypeAllocator = typename ROSMessageTypeAllocatorTraits::allocator_type;
using ROSMessageTypeDeleter = allocator::Deleter<ROSMessageTypeAllocator, ROSMessageType>;
using MessageAllocatorTraits
[[deprecated("use PublishedTypeAllocatorTraits")]] =
PublishedTypeAllocatorTraits;
using MessageAllocator
[[deprecated("use PublishedTypeAllocator")]] =
PublishedTypeAllocator;
using MessageDeleter
[[deprecated("use PublishedTypeDeleter")]] =
PublishedTypeDeleter;
using MessageUniquePtr
[[deprecated("use std::unique_ptr<PublishedType, PublishedTypeDeleter>")]] =
std::unique_ptr<PublishedType, PublishedTypeDeleter>;
using MessageSharedPtr
[[deprecated("use std::shared_ptr<const PublishedType>")]] =
std::shared_ptr<const PublishedType>;
using BufferSharedPtr = typename rclcpp::experimental::buffers::IntraProcessBuffer<
ROSMessageType,
ROSMessageTypeAllocator,
@@ -112,8 +128,8 @@ public:
*
* \param[in] node_base NodeBaseInterface pointer that is used in part of the setup.
* \param[in] topic Name of the topic to publish to.
* \param[in] qos QoS profile for the publisher.
* \param[in] options Options for the publisher.
* \param[in] qos QoS profile for Subcription.
* \param[in] options Options for the subscription.
*/
Publisher(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
@@ -143,9 +159,12 @@ public:
post_init_setup(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const std::string & topic,
[[maybe_unused]] const rclcpp::QoS & qos,
[[maybe_unused]] const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options)
const rclcpp::QoS & qos,
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options)
{
(void)qos;
(void)options;
// If needed, setup intra process communication.
if (rclcpp::detail::resolve_use_intra_process(options_, *node_base)) {
auto context = node_base->get_context();
@@ -187,7 +206,7 @@ public:
* the loaned message will be directly allocated in the middleware.
* If not, the message allocator of this rclcpp::Publisher instance is being used.
*
* With a call to `publish` the LoanedMessage instance is being returned to the middleware
* With a call to \sa `publish` the LoanedMessage instance is being returned to the middleware
* or free'd accordingly to the allocator.
* If the message is not being published but processed differently, the destructor of this
* class will either return the message to the middleware or deallocate it via the internal
@@ -414,6 +433,13 @@ public:
}
}
[[deprecated("use get_published_type_allocator() or get_ros_message_type_allocator() instead")]]
std::shared_ptr<PublishedTypeAllocator>
get_allocator() const
{
return std::make_shared<PublishedTypeAllocator>(published_type_allocator_);
}
PublishedTypeAllocator
get_published_type_allocator() const
{
@@ -574,13 +600,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_);

View File

@@ -210,7 +210,7 @@ public:
void
setup_intra_process(
uint64_t intra_process_publisher_id,
const IntraProcessManagerSharedPtr & ipm);
IntraProcessManagerSharedPtr ipm);
/// Get network flow endpoints
/**
@@ -300,7 +300,7 @@ public:
*/
void
set_on_new_qos_event_callback(
const std::function<void(size_t)> & callback,
std::function<void(size_t)> callback,
rcl_publisher_event_type_t event_type)
{
if (event_handlers_.count(event_type) == 0) {
@@ -319,7 +319,7 @@ public:
// The on_ready_callback signature has an extra `int` argument used to disambiguate between
// possible different entities within a generic waitable.
// We hide that detail to users of this method.
std::function<void(size_t, int)> new_callback = [callback] (size_t nr, int) {callback(nr);};
std::function<void(size_t, int)> new_callback = std::bind(callback, std::placeholders::_1);
event_handlers_[event_type]->set_on_ready_callback(new_callback);
}

View File

@@ -123,20 +123,11 @@ private:
rcl_allocator_t
get_rcl_allocator() const
{
if constexpr (std::is_same_v<Allocator, std::allocator<void>>) {
return rcl_get_default_allocator();
} else {
if constexpr (rclcpp::allocator::has_get_rcl_allocator_v<Allocator>) {
return get_allocator()->get_rcl_allocator();
} else {
if (!plain_allocator_storage_) {
plain_allocator_storage_ =
std::make_shared<PlainAllocator>(*this->get_allocator());
}
return rclcpp::allocator::get_rcl_allocator<char>(*plain_allocator_storage_);
}
if (!plain_allocator_storage_) {
plain_allocator_storage_ =
std::make_shared<PlainAllocator>(*this->get_allocator());
}
return rclcpp::allocator::get_rcl_allocator<char>(*plain_allocator_storage_);
}
// This is a temporal workaround, to make sure that get_allocator()

View File

@@ -146,18 +146,10 @@ public:
QoS(size_t history_depth); // NOLINT(runtime/explicit): conversion constructor
/// Return the rmw qos profile.
/**
* The profile consists of various QoS policies such as history, reliability, and durability.
* Use the corresponding getter functions to retrieve individual policies.
*/
rmw_qos_profile_t &
get_rmw_qos_profile();
/// Return the rmw qos profile.
/**
* The profile consists of various QoS policies such as history, reliability, and durability.
* Use the corresponding getter functions to retrieve individual policies.
*/
const rmw_qos_profile_t &
get_rmw_qos_profile() const;
@@ -483,7 +475,7 @@ public:
explicit
RosoutQoS(
const QoSInitialization & rosout_qos_initialization = (
QoSInitialization::from_rmw(rmw_qos_profile_rosout_default)
QoSInitialization::from_rmw(rcl_qos_profile_rosout_default)
));
};

View File

@@ -39,6 +39,10 @@ public:
RCLCPP_PUBLIC
virtual bool sleep() = 0;
[[deprecated("use get_type() instead")]]
RCLCPP_PUBLIC
virtual bool is_steady() const = 0;
RCLCPP_PUBLIC
virtual rcl_clock_type_t get_type() const = 0;
@@ -50,6 +54,82 @@ using std::chrono::duration;
using std::chrono::duration_cast;
using std::chrono::nanoseconds;
template<class Clock = std::chrono::high_resolution_clock>
class [[deprecated("use rclcpp::Rate class instead of GenericRate")]] GenericRate : public RateBase
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(GenericRate)
explicit GenericRate(double rate)
: period_(duration_cast<nanoseconds>(duration<double>(1.0 / rate))), last_interval_(Clock::now())
{}
explicit GenericRate(std::chrono::nanoseconds period)
: period_(period), last_interval_(Clock::now())
{}
virtual bool
sleep()
{
// Time coming into sleep
auto now = Clock::now();
// Time of next interval
auto next_interval = last_interval_ + period_;
// Detect backwards time flow
if (now < last_interval_) {
// Best thing to do is to set the next_interval to now + period
next_interval = now + period_;
}
// Calculate the time to sleep
auto time_to_sleep = next_interval - now;
// Update the interval
last_interval_ += period_;
// If the time_to_sleep is negative or zero, don't sleep
if (time_to_sleep <= std::chrono::seconds(0)) {
// If an entire cycle was missed then reset next interval.
// This might happen if the loop took more than a cycle.
// Or if time jumps forward.
if (now > next_interval + period_) {
last_interval_ = now + period_;
}
// Either way do not sleep and return false
return false;
}
// Sleep (will get interrupted by ctrl-c, may not sleep full time)
rclcpp::sleep_for(time_to_sleep);
return true;
}
[[deprecated("use get_type() instead")]]
virtual bool
is_steady() const
{
return Clock::is_steady;
}
virtual rcl_clock_type_t get_type() const
{
return Clock::is_steady ? RCL_STEADY_TIME : RCL_SYSTEM_TIME;
}
virtual void
reset()
{
last_interval_ = Clock::now();
}
std::chrono::nanoseconds period() const
{
return period_;
}
private:
RCLCPP_DISABLE_COPY(GenericRate)
std::chrono::nanoseconds period_;
using ClockDurationNano = std::chrono::duration<typename Clock::rep, std::nano>;
std::chrono::time_point<Clock, ClockDurationNano> last_interval_;
};
class Rate : public RateBase
{
public:
@@ -58,17 +138,22 @@ public:
RCLCPP_PUBLIC
explicit Rate(
const double rate,
const Clock::SharedPtr & clock = std::make_shared<Clock>(RCL_SYSTEM_TIME));
Clock::SharedPtr clock = std::make_shared<Clock>(RCL_SYSTEM_TIME));
RCLCPP_PUBLIC
explicit Rate(
const Duration & period,
const Clock::SharedPtr & clock = std::make_shared<Clock>(RCL_SYSTEM_TIME));
Clock::SharedPtr clock = std::make_shared<Clock>(RCL_SYSTEM_TIME));
RCLCPP_PUBLIC
virtual bool
sleep();
[[deprecated("use get_type() instead")]]
RCLCPP_PUBLIC
virtual bool
is_steady() const;
RCLCPP_PUBLIC
virtual rcl_clock_type_t
get_type() const;

View File

@@ -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()
@@ -175,7 +177,6 @@
#include "rclcpp/parameter_event_handler.hpp"
#include "rclcpp/parameter.hpp"
#include "rclcpp/parameter_service.hpp"
#include "rclcpp/parameter_descriptor_wrapper.hpp"
#include "rclcpp/rate.hpp"
#include "rclcpp/time.hpp"
#include "rclcpp/utilities.hpp"

View File

@@ -58,10 +58,10 @@ public:
explicit SerializedMessage(const rcl_serialized_message_t & other);
/// Move Constructor for a SerializedMessage
SerializedMessage(SerializedMessage && other) noexcept;
SerializedMessage(SerializedMessage && other);
/// Constructor for a SerializedMessage from a moved rcl_serialized_message_t
explicit SerializedMessage(rcl_serialized_message_t && other) noexcept;
explicit SerializedMessage(rcl_serialized_message_t && other);
/// Copy assignment operator
SerializedMessage & operator=(const SerializedMessage & other);
@@ -70,10 +70,10 @@ public:
SerializedMessage & operator=(const rcl_serialized_message_t & other);
/// Move assignment operator
SerializedMessage & operator=(SerializedMessage && other) noexcept;
SerializedMessage & operator=(SerializedMessage && other);
/// Move assignment operator from a rcl_serialized_message_t
SerializedMessage & operator=(rcl_serialized_message_t && other) noexcept;
SerializedMessage & operator=(rcl_serialized_message_t && other);
/// Destructor for a SerializedMessage
virtual ~SerializedMessage();

View File

@@ -22,7 +22,6 @@
#include <mutex>
#include <sstream>
#include <string>
#include <utility>
#include "rcl/error_handling.h"
#include "rcl/event_callback.h"
@@ -55,7 +54,7 @@ public:
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(ServiceBase)
RCLCPP_PUBLIC
explicit ServiceBase(const std::shared_ptr<rcl_node_t> & node_handle);
explicit ServiceBase(std::shared_ptr<rcl_node_t> node_handle);
RCLCPP_PUBLIC
virtual ~ServiceBase() = default;
@@ -114,8 +113,8 @@ public:
virtual
void
handle_request(
const std::shared_ptr<rmw_request_id_t> & request_header,
const std::shared_ptr<void> & request) = 0;
std::shared_ptr<rmw_request_id_t> request_header,
std::shared_ptr<void> request) = 0;
/// Exchange the "in use by wait set" state for this service.
/**
@@ -191,7 +190,7 @@ public:
* \param[in] callback functor to be called when a new request is received
*/
void
set_on_new_request_callback(const std::function<void(size_t)> & callback)
set_on_new_request_callback(std::function<void(size_t)> callback)
{
if (!callback) {
throw std::invalid_argument(
@@ -287,7 +286,6 @@ class Service
public std::enable_shared_from_this<Service<ServiceT>>
{
public:
using ServiceType = ServiceT;
using CallbackType = std::function<
void (
const std::shared_ptr<typename ServiceT::Request>,
@@ -309,7 +307,7 @@ public:
* \param[in] node_handle NodeBaseInterface pointer that is used in part of the setup.
* \param[in] service_name Name of the topic to publish to.
* \param[in] any_callback User defined callback to call when a client request is received.
* \param[in] service_options options for the service.
* \param[in] service_options options for the subscription.
*/
Service(
std::shared_ptr<rcl_node_t> node_handle,
@@ -374,10 +372,10 @@ public:
* \param[in] any_callback User defined callback to call when a client request is received.
*/
Service(
const std::shared_ptr<rcl_node_t> & node_handle,
const std::shared_ptr<rcl_service_t> & service_handle,
std::shared_ptr<rcl_node_t> node_handle,
std::shared_ptr<rcl_service_t> service_handle,
AnyServiceCallback<ServiceT> any_callback)
: ServiceBase(node_handle), any_callback_(std::move(any_callback)),
: ServiceBase(node_handle), any_callback_(any_callback),
srv_type_support_handle_(rosidl_typesupport_cpp::get_service_type_support_handle<ServiceT>())
{
// check if service handle was initialized
@@ -409,10 +407,10 @@ public:
* \param[in] any_callback User defined callback to call when a client request is received.
*/
Service(
const std::shared_ptr<rcl_node_t> & node_handle,
std::shared_ptr<rcl_node_t> node_handle,
rcl_service_t * service_handle,
AnyServiceCallback<ServiceT> any_callback)
: ServiceBase(node_handle), any_callback_(std::move(any_callback)),
: ServiceBase(node_handle), any_callback_(any_callback),
srv_type_support_handle_(rosidl_typesupport_cpp::get_service_type_support_handle<ServiceT>())
{
// check if service handle was initialized
@@ -473,8 +471,8 @@ public:
void
handle_request(
const std::shared_ptr<rmw_request_id_t> & request_header,
const std::shared_ptr<void> & request) override
std::shared_ptr<rmw_request_id_t> request_header,
std::shared_ptr<void> request) override
{
auto typed_request = std::static_pointer_cast<typename ServiceT::Request>(request);
auto response = any_callback_.dispatch(this->shared_from_this(), request_header, typed_request);
@@ -506,13 +504,10 @@ public:
* \param[in] clock clock to use to generate introspection timestamps
* \param[in] qos_service_event_pub QoS settings to use when creating the introspection publisher
* \param[in] introspection_state the state to set introspection to
*
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw if
* it failed to configure introspection.
*/
void
configure_introspection(
const Clock::SharedPtr & clock, const QoS & qos_service_event_pub,
Clock::SharedPtr clock, const QoS & qos_service_event_pub,
rcl_service_introspection_state_t introspection_state)
{
rcl_publisher_options_t pub_opts = rcl_publisher_get_default_options();

View File

@@ -99,92 +99,49 @@ public:
// Important to use subscription_handles_.size() instead of wait set's size since
// there may be more subscriptions in the wait set due to Waitables added to the end.
// The same logic applies for other entities.
// Mark corresponding weak_ptr as expired for entities that are null in the wait set
size_t valid_subscription_count = 0;
for (size_t i = 0; i < subscription_handles_.size(); ++i) {
if (valid_subscription_count < wait_set->size_of_subscriptions &&
!wait_set->subscriptions[valid_subscription_count])
{
subscription_handles_[i] = std::weak_ptr<const rcl_subscription_t>{};
}
if (subscription_handles_[i].lock()) {
++valid_subscription_count;
if (!wait_set->subscriptions[i]) {
subscription_handles_[i].reset();
}
}
size_t valid_service_count = 0;
for (size_t i = 0; i < service_handles_.size(); ++i) {
if (valid_service_count < wait_set->size_of_services &&
!wait_set->services[valid_service_count])
{
service_handles_[i] = std::weak_ptr<const rcl_service_t>{};
}
if (service_handles_[i].lock()) {
++valid_service_count;
if (!wait_set->services[i]) {
service_handles_[i].reset();
}
}
size_t valid_client_count = 0;
for (size_t i = 0; i < client_handles_.size(); ++i) {
if (valid_client_count < wait_set->size_of_clients &&
!wait_set->clients[valid_client_count])
{
client_handles_[i] = std::weak_ptr<const rcl_client_t>{};
}
if (client_handles_[i].lock()) {
++valid_client_count;
if (!wait_set->clients[i]) {
client_handles_[i].reset();
}
}
size_t valid_timer_count = 0;
for (size_t i = 0; i < timer_handles_.size(); ++i) {
if (valid_timer_count < wait_set->size_of_timers &&
!wait_set->timers[valid_timer_count])
{
timer_handles_[i] = std::weak_ptr<const rcl_timer_t>{};
}
if (timer_handles_[i].lock()) {
++valid_timer_count;
if (!wait_set->timers[i]) {
timer_handles_[i].reset();
}
}
for (size_t i = 0; i < waitable_handles_.size(); ++i) {
if (!waitable_handles_[i]->is_ready(*wait_set)) {
waitable_handles_[i].reset();
}
}
// Remove expired weak_ptr instances
subscription_handles_.erase(
std::remove_if(subscription_handles_.begin(), subscription_handles_.end(),
[](const std::weak_ptr<const rcl_subscription_t> & weak_ptr) {
return weak_ptr.expired();
}),
std::remove(subscription_handles_.begin(), subscription_handles_.end(), nullptr),
subscription_handles_.end()
);
service_handles_.erase(
std::remove_if(service_handles_.begin(), service_handles_.end(),
[](const std::weak_ptr<const rcl_service_t> & weak_ptr) {
return weak_ptr.expired();
}),
std::remove(service_handles_.begin(), service_handles_.end(), nullptr),
service_handles_.end()
);
client_handles_.erase(
std::remove_if(client_handles_.begin(), client_handles_.end(),
[](const std::weak_ptr<const rcl_client_t> & weak_ptr) {
return weak_ptr.expired();
}),
std::remove(client_handles_.begin(), client_handles_.end(), nullptr),
client_handles_.end()
);
timer_handles_.erase(
std::remove_if(timer_handles_.begin(), timer_handles_.end(),
[](const std::weak_ptr<const rcl_timer_t> & weak_ptr) {
return weak_ptr.expired();
}),
std::remove(timer_handles_.begin(), timer_handles_.end(), nullptr),
timer_handles_.end()
);
@@ -239,60 +196,38 @@ public:
bool add_handles_to_wait_set(rcl_wait_set_t * wait_set) override
{
for (const std::weak_ptr<const rcl_subscription_t> & weak_subscription :
subscription_handles_)
{
auto subscription = weak_subscription.lock();
if (!subscription) {
continue; // Skip expired handles
}
for (const std::shared_ptr<const rcl_subscription_t> & subscription : subscription_handles_) {
if (rcl_wait_set_add_subscription(wait_set, subscription.get(), NULL) != RCL_RET_OK) {
RCUTILS_LOG_ERROR_NAMED(
"rclcpp",
"Couldn't add subscription to wait set: %s", rcl_get_error_string().str);
rcl_reset_error();
return false;
}
}
for (const std::weak_ptr<const rcl_client_t> & weak_client : client_handles_) {
auto client = weak_client.lock();
if (!client) {
continue; // Skip expired handles
}
for (const std::shared_ptr<const rcl_client_t> & client : client_handles_) {
if (rcl_wait_set_add_client(wait_set, client.get(), NULL) != RCL_RET_OK) {
RCUTILS_LOG_ERROR_NAMED(
"rclcpp",
"Couldn't add client to wait set: %s", rcl_get_error_string().str);
rcl_reset_error();
return false;
}
}
for (const std::weak_ptr<const rcl_service_t> & weak_service : service_handles_) {
auto service = weak_service.lock();
if (!service) {
continue; // Skip expired handles
}
for (const std::shared_ptr<const rcl_service_t> & service : service_handles_) {
if (rcl_wait_set_add_service(wait_set, service.get(), NULL) != RCL_RET_OK) {
RCUTILS_LOG_ERROR_NAMED(
"rclcpp",
"Couldn't add service to wait set: %s", rcl_get_error_string().str);
rcl_reset_error();
return false;
}
}
for (const std::weak_ptr<const rcl_timer_t> & weak_timer : timer_handles_) {
auto timer = weak_timer.lock();
if (!timer) {
continue; // Skip expired handles
}
for (const std::shared_ptr<const rcl_timer_t> & timer : timer_handles_) {
if (rcl_wait_set_add_timer(wait_set, timer.get(), NULL) != RCL_RET_OK) {
RCUTILS_LOG_ERROR_NAMED(
"rclcpp",
"Couldn't add timer to wait set: %s", rcl_get_error_string().str);
rcl_reset_error();
return false;
}
}
@@ -314,13 +249,7 @@ public:
{
auto it = subscription_handles_.begin();
while (it != subscription_handles_.end()) {
auto subscription_handle = it->lock();
if (!subscription_handle) {
// Handle expired, remove it and continue
it = subscription_handles_.erase(it);
continue;
}
auto subscription = get_subscription_by_handle(subscription_handle, weak_groups_to_nodes);
auto subscription = get_subscription_by_handle(*it, weak_groups_to_nodes);
if (subscription) {
// Find the group for this handle and see if it can be serviced
auto group = get_group_by_subscription(subscription, weak_groups_to_nodes);
@@ -355,13 +284,7 @@ public:
{
auto it = service_handles_.begin();
while (it != service_handles_.end()) {
auto service_handle = it->lock();
if (!service_handle) {
// Handle expired, remove it and continue
it = service_handles_.erase(it);
continue;
}
auto service = get_service_by_handle(service_handle, weak_groups_to_nodes);
auto service = get_service_by_handle(*it, weak_groups_to_nodes);
if (service) {
// Find the group for this handle and see if it can be serviced
auto group = get_group_by_service(service, weak_groups_to_nodes);
@@ -396,13 +319,7 @@ public:
{
auto it = client_handles_.begin();
while (it != client_handles_.end()) {
auto client_handle = it->lock();
if (!client_handle) {
// Handle expired, remove it and continue
it = client_handles_.erase(it);
continue;
}
auto client = get_client_by_handle(client_handle, weak_groups_to_nodes);
auto client = get_client_by_handle(*it, weak_groups_to_nodes);
if (client) {
// Find the group for this handle and see if it can be serviced
auto group = get_group_by_client(client, weak_groups_to_nodes);
@@ -437,13 +354,7 @@ public:
{
auto it = timer_handles_.begin();
while (it != timer_handles_.end()) {
auto timer_handle = it->lock();
if (!timer_handle) {
// Handle expired, remove it and continue
it = timer_handles_.erase(it);
continue;
}
auto timer = get_timer_by_handle(timer_handle, weak_groups_to_nodes);
auto timer = get_timer_by_handle(*it, weak_groups_to_nodes);
if (timer) {
// Find the group for this handle and see if it can be serviced
auto group = get_group_by_timer(timer, weak_groups_to_nodes);
@@ -515,22 +426,12 @@ public:
rcl_allocator_t get_allocator() override
{
if constexpr (std::is_same_v<Alloc, std::allocator<void>>) {
return rcl_get_default_allocator();
} else {
return rclcpp::allocator::get_rcl_allocator<void *, VoidAlloc>(*allocator_.get());
}
return rclcpp::allocator::get_rcl_allocator<void *, VoidAlloc>(*allocator_.get());
}
size_t number_of_ready_subscriptions() const override
{
size_t number_of_subscriptions = 0;
// Count only non-expired weak_ptr references
for (const auto & weak_subscription : subscription_handles_) {
if (!weak_subscription.expired()) {
++number_of_subscriptions;
}
}
size_t number_of_subscriptions = subscription_handles_.size();
for (const std::shared_ptr<Waitable> & waitable : waitable_handles_) {
number_of_subscriptions += waitable->get_number_of_ready_subscriptions();
}
@@ -539,13 +440,7 @@ public:
size_t number_of_ready_services() const override
{
size_t number_of_services = 0;
// Count only non-expired weak_ptr references
for (const auto & weak_service : service_handles_) {
if (!weak_service.expired()) {
++number_of_services;
}
}
size_t number_of_services = service_handles_.size();
for (const std::shared_ptr<Waitable> & waitable : waitable_handles_) {
number_of_services += waitable->get_number_of_ready_services();
}
@@ -563,13 +458,7 @@ public:
size_t number_of_ready_clients() const override
{
size_t number_of_clients = 0;
// Count only non-expired weak_ptr references
for (const auto & weak_client : client_handles_) {
if (!weak_client.expired()) {
++number_of_clients;
}
}
size_t number_of_clients = client_handles_.size();
for (const std::shared_ptr<Waitable> & waitable : waitable_handles_) {
number_of_clients += waitable->get_number_of_ready_clients();
}
@@ -587,13 +476,7 @@ public:
size_t number_of_ready_timers() const override
{
size_t number_of_timers = 0;
// Count only non-expired weak_ptr references
for (const auto & weak_timer : timer_handles_) {
if (!weak_timer.expired()) {
++number_of_timers;
}
}
size_t number_of_timers = timer_handles_.size();
for (const std::shared_ptr<Waitable> & waitable : waitable_handles_) {
number_of_timers += waitable->get_number_of_ready_timers();
}
@@ -612,10 +495,10 @@ private:
VectorRebind<const rclcpp::GuardCondition *> guard_conditions_;
VectorRebind<std::weak_ptr<const rcl_subscription_t>> subscription_handles_;
VectorRebind<std::weak_ptr<const rcl_service_t>> service_handles_;
VectorRebind<std::weak_ptr<const rcl_client_t>> client_handles_;
VectorRebind<std::weak_ptr<const rcl_timer_t>> timer_handles_;
VectorRebind<std::shared_ptr<const rcl_subscription_t>> subscription_handles_;
VectorRebind<std::shared_ptr<const rcl_service_t>> service_handles_;
VectorRebind<std::shared_ptr<const rcl_client_t>> client_handles_;
VectorRebind<std::shared_ptr<const rcl_timer_t>> timer_handles_;
VectorRebind<std::shared_ptr<Waitable>> waitable_handles_;
std::shared_ptr<VoidAlloc> allocator_;

View File

@@ -114,9 +114,9 @@ public:
* all references.
* \param[in] msg Shared pointer to the message to return.
*/
void return_message([[maybe_unused]] std::shared_ptr<MessageT> & msg)
void return_message(std::shared_ptr<MessageT> & msg)
{
// This function is intentionally left empty.
(void)msg;
}
protected:

View File

@@ -90,6 +90,18 @@ public:
using ROSMessageTypeAllocator = typename ROSMessageTypeAllocatorTraits::allocator_type;
using ROSMessageTypeDeleter = allocator::Deleter<ROSMessageTypeAllocator, ROSMessageType>;
using MessageAllocatorTraits [[deprecated("use ROSMessageTypeAllocatorTraits")]] =
ROSMessageTypeAllocatorTraits;
using MessageAllocator [[deprecated("use ROSMessageTypeAllocator")]] =
ROSMessageTypeAllocator;
using MessageDeleter [[deprecated("use ROSMessageTypeDeleter")]] =
ROSMessageTypeDeleter;
using ConstMessageSharedPtr [[deprecated]] = std::shared_ptr<const ROSMessageType>;
using MessageUniquePtr
[[deprecated("use std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter> instead")]] =
std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>;
private:
using SubscriptionTopicStatisticsSharedPtr =
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics>;
@@ -209,11 +221,13 @@ public:
/// Called after construction to continue setup that requires shared_from_this().
void
post_init_setup(
[[maybe_unused]] rclcpp::node_interfaces::NodeBaseInterface * node_base,
[[maybe_unused]] const rclcpp::QoS & qos,
[[maybe_unused]] const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options)
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const rclcpp::QoS & qos,
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options)
{
// This function is intentionally left empty.
(void)node_base;
(void)qos;
(void)options;
}
/// Take the next message from the inter-process subscription.
@@ -279,50 +293,6 @@ public:
return message_memory_strategy_->borrow_serialized_message();
}
/// Disable callbacks from being called
/**
* This method will block, until any subscription's callbacks provided during construction
* currently being executed are finished.
* \note This method also temporary removes the on new message callback and all
* on new event callbacks from the rmw layer to prevent them from being called. However, this
* method will not block and wait until the currently executing on_new_[message]event callbacks
* are finished.
*/
void
disable_callbacks() override
{
SubscriptionBase::disable_callbacks();
any_callback_.disable();
if (subscription_intra_process_) {
subscription_intra_process_->disable_callbacks();
}
for (const auto & [_, event_ptr] : event_handlers_) {
if (event_ptr) {
event_ptr->disable();
}
}
}
/// Enable the callbacks to be called
/**
* This method is thread safe, and provides a safe way to atomically enable the callbacks
* in a multithreaded environment.
*/
void
enable_callbacks() override
{
SubscriptionBase::enable_callbacks();
any_callback_.enable();
if (subscription_intra_process_) {
subscription_intra_process_->enable_callbacks();
}
for (const auto & [_, event_ptr] : event_handlers_) {
if (event_ptr) {
event_ptr->enable();
}
}
}
void
handle_message(
std::shared_ptr<void> & message,
@@ -464,17 +434,20 @@ public:
void
return_dynamic_message(
[[maybe_unused]] rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message) override
rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message) override
{
(void) message;
throw rclcpp::exceptions::UnimplementedError(
"return_dynamic_message is not implemented for Subscription");
}
void
handle_dynamic_message(
[[maybe_unused]] const rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message,
[[maybe_unused]] const rclcpp::MessageInfo & message_info) override
const rclcpp::dynamic_typesupport::DynamicMessage::SharedPtr & message,
const rclcpp::MessageInfo & message_info) override
{
(void) message;
(void) message_info;
throw rclcpp::exceptions::UnimplementedError(
"handle_dynamic_message is not implemented for Subscription");
}

View File

@@ -20,8 +20,8 @@
#include <mutex>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <utility>
#include "rcl/event_callback.h"
#include "rcl/subscription.h"
@@ -212,23 +212,6 @@ public:
std::shared_ptr<rclcpp::SerializedMessage>
create_serialized_message() = 0;
/// Disable callbacks from being called
/**
* This function temporary removes the on_new_message_callback to prevent it from being called.
*/
RCLCPP_PUBLIC
virtual
void disable_callbacks();
/// Enable the callbacks to be called
/**
* This function sets back the on_new_message_callback if it was previously removed in
* disable_callbacks().
*/
RCLCPP_PUBLIC
virtual
void enable_callbacks();
/// Check if we need to handle the message, and execute the callback if we do.
/**
* \param[in] message Shared pointer to the message to handle.
@@ -372,7 +355,7 @@ public:
* \param[in] callback functor to be called when a new message is received
*/
void
set_on_new_message_callback(const std::function<void(size_t)> & callback)
set_on_new_message_callback(std::function<void(size_t)> callback)
{
if (!callback) {
throw std::invalid_argument(
@@ -400,7 +383,7 @@ public:
}
};
std::lock_guard<std::recursive_mutex> lock(on_new_message_callback_mutex_);
std::lock_guard<std::recursive_mutex> lock(callback_mutex_);
// Set it temporarily to the new callback, while we replace the old one.
// This two-step setting, prevents a gap where the old std::function has
@@ -423,7 +406,7 @@ public:
void
clear_on_new_message_callback()
{
std::lock_guard<std::recursive_mutex> lock(on_new_message_callback_mutex_);
std::lock_guard<std::recursive_mutex> lock(callback_mutex_);
if (on_new_message_callback_) {
set_on_new_message_callback(nullptr, nullptr);
@@ -450,7 +433,7 @@ public:
* \param[in] callback functor to be called when a new message is received
*/
void
set_on_new_intra_process_message_callback(const std::function<void(size_t)> & callback)
set_on_new_intra_process_message_callback(std::function<void(size_t)> callback)
{
if (!use_intra_process_) {
RCLCPP_WARN(
@@ -468,7 +451,7 @@ public:
// The on_ready_callback signature has an extra `int` argument used to disambiguate between
// possible different entities within a generic waitable.
// We hide that detail to users of this method.
std::function<void(size_t, int)> new_callback = [callback] (size_t nr, int) {callback(nr);};
std::function<void(size_t, int)> new_callback = std::bind(callback, std::placeholders::_1);
subscription_intra_process_->set_on_ready_callback(new_callback);
}
@@ -514,7 +497,7 @@ public:
*/
void
set_on_new_qos_event_callback(
const std::function<void(size_t)> & callback,
std::function<void(size_t)> callback,
rcl_subscription_event_type_t event_type)
{
if (event_handlers_.count(event_type) == 0) {
@@ -533,7 +516,7 @@ public:
// The on_ready_callback signature has an extra `int` argument used to disambiguate between
// possible different entities within a generic waitable.
// We hide that detail to users of this method.
std::function<void(size_t, int)> new_callback = [callback] (size_t nr, int) {callback(nr);};
std::function<void(size_t, int)> new_callback = std::bind(callback, std::placeholders::_1);
event_handlers_[event_type]->set_on_ready_callback(new_callback);
}
@@ -663,7 +646,7 @@ protected:
std::shared_ptr<rcl_node_t> node_handle_;
std::recursive_mutex on_new_message_callback_mutex_;
std::recursive_mutex callback_mutex_;
// It is important to declare on_new_message_callback_ before
// subscription_handle_, so on destruction the subscription is
// destroyed first. Otherwise, the rmw subscription callback

View File

@@ -89,15 +89,6 @@ struct SubscriptionOptionsBase
QosOverridingOptions qos_overriding_options;
ContentFilterOptions content_filter_options;
/// Acceptable buffer backend names for this subscription.
/**
* Empty string or "cpu" means CPU-only (default for backward compatibility).
* "any" means all installed backends are acceptable.
* Comma-separated for specific backends, e.g. "cuda,demo".
* CPU is always implicitly acceptable regardless of this value.
*/
std::string acceptable_buffer_backends{"cpu"};
};
/// Structure containing optional configuration for Subscriptions.
@@ -154,11 +145,6 @@ struct SubscriptionOptionsWithAllocator : public SubscriptionOptionsBase
}
}
if (!acceptable_buffer_backends.empty()) {
result.rmw_subscription_options.acceptable_buffer_backends =
acceptable_buffer_backends.c_str();
}
return result;
}
@@ -181,20 +167,11 @@ private:
rcl_allocator_t
get_rcl_allocator() const
{
if constexpr (std::is_same_v<Allocator, std::allocator<void>>) {
return rcl_get_default_allocator();
} else {
if constexpr (rclcpp::allocator::has_get_rcl_allocator_v<Allocator>) {
return get_allocator()->get_rcl_allocator();
} else {
if (!plain_allocator_storage_) {
plain_allocator_storage_ =
std::make_shared<PlainAllocator>(*this->get_allocator());
}
return rclcpp::allocator::get_rcl_allocator<char>(*plain_allocator_storage_);
}
if (!plain_allocator_storage_) {
plain_allocator_storage_ =
std::make_shared<PlainAllocator>(*this->get_allocator());
}
return rclcpp::allocator::get_rcl_allocator<char>(*plain_allocator_storage_);
}
// This is a temporal workaround, to make sure that get_allocator()

View File

@@ -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,9 +47,8 @@ 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
*/
RCLCPP_PUBLIC
explicit Time(int64_t nanoseconds = 0, rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
@@ -189,7 +189,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 +208,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

View File

@@ -60,7 +60,7 @@ public:
*/
RCLCPP_PUBLIC
explicit TimeSource(
const rclcpp::Node::SharedPtr & node,
rclcpp::Node::SharedPtr node,
const rclcpp::QoS & qos = rclcpp::ClockQoS(),
bool use_clock_thread = true);
@@ -89,7 +89,7 @@ public:
* \param node std::shared pointer to a initialized node
*/
RCLCPP_PUBLIC
void attachNode(const rclcpp::Node::SharedPtr & node);
void attachNode(rclcpp::Node::SharedPtr node);
/// Attach node to the time source.
/**
@@ -124,11 +124,11 @@ public:
* \throws std::invalid_argument the time source must be a RCL_ROS_TIME otherwise throws an exception
*/
RCLCPP_PUBLIC
void attachClock(const rclcpp::Clock::SharedPtr & clock);
void attachClock(rclcpp::Clock::SharedPtr clock);
/// Detach a clock from the time source
RCLCPP_PUBLIC
void detachClock(const rclcpp::Clock::SharedPtr & clock);
void detachClock(rclcpp::Clock::SharedPtr clock);
/// Get whether a separate clock thread is used or not
RCLCPP_PUBLIC

View File

@@ -183,7 +183,7 @@ public:
*/
RCLCPP_PUBLIC
void
set_on_reset_callback(const std::function<void(size_t)> & callback);
set_on_reset_callback(std::function<void(size_t)> callback);
/// Unset the callback registered for reset timer
RCLCPP_PUBLIC

View File

@@ -172,11 +172,12 @@ private:
{
auto received_message_age = std::make_unique<ReceivedMessageAge>();
received_message_age->Start();
subscriber_statistics_collectors_.emplace_back(std::move(received_message_age));
auto received_message_period = std::make_unique<ReceivedMessagePeriod>();
received_message_period->Start();
{
std::lock_guard<std::mutex> lock(mutex_);
subscriber_statistics_collectors_.emplace_back(std::move(received_message_age));
subscriber_statistics_collectors_.emplace_back(std::move(received_message_period));
}

View File

@@ -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.

View File

@@ -21,7 +21,6 @@
#include <tuple>
#include "rcpputils/shared_library.hpp"
#include "rosidl_runtime_cpp/action_type_support_decl.hpp"
#include "rosidl_runtime_cpp/message_type_support_decl.hpp"
#include "rosidl_runtime_cpp/service_type_support_decl.hpp"
@@ -63,6 +62,22 @@ RCLCPP_PUBLIC
std::shared_ptr<rcpputils::SharedLibrary>
get_typesupport_library(const std::string & type, const std::string & typesupport_identifier);
/// \brief Extract the type support handle from the library.
/// \note The library needs to match the topic type. The shared library must stay loaded for the
/// lifetime of the result.
/// \deprecated Use get_message_typesupport_handle() instead
/// \param[in] type The topic type, e.g. "std_msgs/msg/String"
/// \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
/// \param[in] library The shared type support library
/// \return A type support handle
[[deprecated("Use `get_message_typesupport_handle` instead")]]
RCLCPP_PUBLIC
const rosidl_message_type_support_t *
get_typesupport_handle(
const std::string & type,
const std::string & typesupport_identifier,
rcpputils::SharedLibrary & library);
/// \brief Extracts the message type support handle from the library.
/// \note The library needs to match the topic type. The shared library must stay loaded for the
/// lifetime of the result.
@@ -93,21 +108,6 @@ get_service_typesupport_handle(
const std::string & typesupport_identifier,
rcpputils::SharedLibrary & library);
/// \brief Extracts the action type support handle from the library.
/// \note The library needs to match the action type. The shared library must stay loaded for the
/// lifetime of the result.
/// \param[in] type The action type, e.g. "example_interfaces/action/Fibonacci"
/// \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
/// \param[in] library The shared type support library
/// \throws std::runtime_error if the symbol of type not found in the library.
/// \return A action type support handle
RCLCPP_PUBLIC
const rosidl_action_type_support_t *
get_action_typesupport_handle(
const std::string & type,
const std::string & typesupport_identifier,
rcpputils::SharedLibrary & library);
} // namespace rclcpp
#endif // RCLCPP__TYPESUPPORT_HELPERS_HPP_

View File

@@ -22,7 +22,6 @@
#include <vector>
#include "rclcpp/context.hpp"
#include "rclcpp/contexts/default_context.hpp"
#include "rclcpp/init_options.hpp"
#include "rclcpp/visibility_control.hpp"
@@ -174,7 +173,7 @@ remove_ros_arguments(int argc, char const * const * argv);
*/
RCLCPP_PUBLIC
bool
ok(const rclcpp::Context::SharedPtr & context = rclcpp::contexts::get_global_default_context());
ok(rclcpp::Context::SharedPtr context = nullptr);
/// Shutdown rclcpp context, invalidating it for derived entities.
/**
@@ -193,7 +192,7 @@ ok(const rclcpp::Context::SharedPtr & context = rclcpp::contexts::get_global_def
RCLCPP_PUBLIC
bool
shutdown(
const rclcpp::Context::SharedPtr & context = rclcpp::contexts::get_global_default_context(),
rclcpp::Context::SharedPtr context = nullptr,
const std::string & reason = "user called rclcpp::shutdown()");
/// Register a function to be called when shutdown is called on the context.
@@ -213,9 +212,7 @@ shutdown(
*/
RCLCPP_PUBLIC
void
on_shutdown(
const std::function<void()> & callback,
const rclcpp::Context::SharedPtr & context = rclcpp::contexts::get_global_default_context());
on_shutdown(std::function<void()> callback, rclcpp::Context::SharedPtr context = nullptr);
/// Use the global condition variable to block for the specified amount of time.
/**
@@ -234,7 +231,7 @@ RCLCPP_PUBLIC
bool
sleep_for(
const std::chrono::nanoseconds & nanoseconds,
const rclcpp::Context::SharedPtr & context = rclcpp::contexts::get_global_default_context());
rclcpp::Context::SharedPtr context = nullptr);
/// Safely check if addition will overflow.
/**

View File

@@ -56,7 +56,7 @@ bool wait_for_message(
}
});
rclcpp::WaitSet wait_set({}, {}, {}, {}, {}, {}, context);
rclcpp::WaitSet wait_set;
wait_set.add_subscription(subscription);
RCPPUTILS_SCOPE_EXIT(wait_set.remove_subscription(subscription); );
wait_set.add_guard_condition(gc);

View File

@@ -704,12 +704,10 @@ public:
return WaitResult<WaitSetTemplate>::from_timeout_wait_result_kind();
case WaitResultKind::Empty:
return WaitResult<WaitSetTemplate>::from_empty_wait_result_kind();
case WaitResultKind::Invalid:
auto msg = "invalid WaitResultKind with value: " + std::to_string(wait_result_kind);
default:
auto msg = "unknown WaitResultKind with value: " + std::to_string(wait_result_kind);
throw std::runtime_error(msg);
}
// This should never be reached, but is needed to satisfy the compiler
throw std::runtime_error("unreachable code in wait result kind switch");
}
);
}

View File

@@ -18,7 +18,6 @@
#include <atomic>
#include <functional>
#include <memory>
#include <vector>
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"
@@ -28,8 +27,6 @@
namespace rclcpp
{
class TimerBase;
class Waitable
{
public:
@@ -104,6 +101,23 @@ public:
size_t
get_number_of_ready_guard_conditions();
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
#endif
/// Deprecated.
/**
* \sa add_to_wait_set(rcl_wait_set_t &)
*/
[[deprecated("Use add_to_wait_set(rcl_wait_set_t & wait_set) signature")]]
RCLCPP_PUBLIC
virtual
void
add_to_wait_set(rcl_wait_set_t * wait_set);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
/// Add the Waitable to a wait set.
/**
* \param[in] wait_set A handle to the wait set to add the Waitable to.
@@ -112,7 +126,24 @@ public:
RCLCPP_PUBLIC
virtual
void
add_to_wait_set(rcl_wait_set_t & wait_set) = 0;
add_to_wait_set(rcl_wait_set_t & wait_set);
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
#endif
/// Deprecated.
/**
* \sa is_ready(const rcl_wait_set_t &)
*/
[[deprecated("Use is_ready(const rcl_wait_set_t & wait_set) signature")]]
RCLCPP_PUBLIC
virtual
bool
is_ready(rcl_wait_set_t * wait_set);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
/// Check if the Waitable is ready.
/**
@@ -127,7 +158,7 @@ public:
RCLCPP_PUBLIC
virtual
bool
is_ready(const rcl_wait_set_t & wait_set) = 0;
is_ready(const rcl_wait_set_t & wait_set);
/// Take the data so that it can be consumed with `execute`.
/**
@@ -179,7 +210,24 @@ public:
RCLCPP_PUBLIC
virtual
std::shared_ptr<void>
take_data_by_entity_id(size_t id) = 0;
take_data_by_entity_id(size_t id);
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
#endif
/// Deprecated.
/**
* \sa execute(const std::shared_ptr<void> &)
*/
[[deprecated("Use execute(const std::shared_ptr<void> & data) signature")]]
RCLCPP_PUBLIC
virtual
void
execute(std::shared_ptr<void> & data);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
/// Execute data that is passed in.
/**
@@ -206,7 +254,7 @@ public:
RCLCPP_PUBLIC
virtual
void
execute(const std::shared_ptr<void> & data) = 0;
execute(const std::shared_ptr<void> & data);
/// Exchange the "in use by wait set" state for this timer.
/**
@@ -249,7 +297,7 @@ public:
RCLCPP_PUBLIC
virtual
void
set_on_ready_callback(std::function<void(size_t, int)> callback) = 0;
set_on_ready_callback(std::function<void(size_t, int)> callback);
/// Unset any callback registered via set_on_ready_callback.
/**
@@ -259,18 +307,7 @@ public:
RCLCPP_PUBLIC
virtual
void
clear_on_ready_callback() = 0;
/// Returns all timers used by this waitable
/**
* Must return all timers used within the waitable.
* Note, it is not supported, that timers are added
* or removed over the lifetime of the waitable.
*/
RCLCPP_PUBLIC
virtual
std::vector<std::shared_ptr<rclcpp::TimerBase>>
get_timers() const = 0;
clear_on_ready_callback();
private:
std::atomic<bool> in_use_by_wait_set_{false};

View File

@@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>rclcpp</name>
<version>30.1.5</version>
<version>28.1.13</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>
@@ -47,9 +46,9 @@
<depend>statistics_msgs</depend>
<depend>tracetools</depend>
<test_depend>ament_cmake_gmock</test_depend>
<test_depend>ament_cmake_google_benchmark</test_depend>
<test_depend>ament_cmake_gtest</test_depend>
<test_depend>ament_cmake_ros</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>mimick_vendor</test_depend>

View 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_

View File

@@ -31,7 +31,7 @@ using rclcpp::CallbackGroupType;
CallbackGroup::CallbackGroup(
CallbackGroupType group_type,
const rclcpp::Context::WeakPtr & context,
rclcpp::Context::WeakPtr context,
bool automatically_add_to_executor_with_node)
: type_(group_type), associated_with_executor_(false),
can_be_taken_from_(true),
@@ -59,7 +59,6 @@ CallbackGroup::type() const
size_t
CallbackGroup::size() const
{
std::lock_guard<std::mutex> lock(mutex_);
return
subscription_ptrs_.size() +
service_ptrs_.size() +
@@ -69,11 +68,11 @@ CallbackGroup::size() const
}
void CallbackGroup::collect_all_ptrs(
const std::function<void(const rclcpp::SubscriptionBase::SharedPtr &)> & sub_func,
const std::function<void(const rclcpp::ServiceBase::SharedPtr &)> & service_func,
const std::function<void(const rclcpp::ClientBase::SharedPtr &)> & client_func,
const std::function<void(const rclcpp::TimerBase::SharedPtr &)> & timer_func,
const std::function<void(const rclcpp::Waitable::SharedPtr &)> & waitable_func) const
std::function<void(const rclcpp::SubscriptionBase::SharedPtr &)> sub_func,
std::function<void(const rclcpp::ServiceBase::SharedPtr &)> service_func,
std::function<void(const rclcpp::ClientBase::SharedPtr &)> client_func,
std::function<void(const rclcpp::TimerBase::SharedPtr &)> timer_func,
std::function<void(const rclcpp::Waitable::SharedPtr &)> waitable_func) const
{
std::lock_guard<std::mutex> lock(mutex_);
@@ -150,7 +149,7 @@ CallbackGroup::trigger_notify_guard_condition()
void
CallbackGroup::add_subscription(
const rclcpp::SubscriptionBase::SharedPtr & subscription_ptr)
const rclcpp::SubscriptionBase::SharedPtr subscription_ptr)
{
std::lock_guard<std::mutex> lock(mutex_);
subscription_ptrs_.push_back(subscription_ptr);
@@ -158,12 +157,12 @@ CallbackGroup::add_subscription(
std::remove_if(
subscription_ptrs_.begin(),
subscription_ptrs_.end(),
[](const rclcpp::SubscriptionBase::WeakPtr & x) {return x.expired();}),
[](rclcpp::SubscriptionBase::WeakPtr x) {return x.expired();}),
subscription_ptrs_.end());
}
void
CallbackGroup::add_timer(const rclcpp::TimerBase::SharedPtr & timer_ptr)
CallbackGroup::add_timer(const rclcpp::TimerBase::SharedPtr timer_ptr)
{
std::lock_guard<std::mutex> lock(mutex_);
timer_ptrs_.push_back(timer_ptr);
@@ -171,12 +170,12 @@ CallbackGroup::add_timer(const rclcpp::TimerBase::SharedPtr & timer_ptr)
std::remove_if(
timer_ptrs_.begin(),
timer_ptrs_.end(),
[](const rclcpp::TimerBase::WeakPtr & x) {return x.expired();}),
[](rclcpp::TimerBase::WeakPtr x) {return x.expired();}),
timer_ptrs_.end());
}
void
CallbackGroup::add_service(const rclcpp::ServiceBase::SharedPtr & service_ptr)
CallbackGroup::add_service(const rclcpp::ServiceBase::SharedPtr service_ptr)
{
std::lock_guard<std::mutex> lock(mutex_);
service_ptrs_.push_back(service_ptr);
@@ -184,12 +183,12 @@ CallbackGroup::add_service(const rclcpp::ServiceBase::SharedPtr & service_ptr)
std::remove_if(
service_ptrs_.begin(),
service_ptrs_.end(),
[](const rclcpp::ServiceBase::WeakPtr & x) {return x.expired();}),
[](rclcpp::ServiceBase::WeakPtr x) {return x.expired();}),
service_ptrs_.end());
}
void
CallbackGroup::add_client(const rclcpp::ClientBase::SharedPtr & client_ptr)
CallbackGroup::add_client(const rclcpp::ClientBase::SharedPtr client_ptr)
{
std::lock_guard<std::mutex> lock(mutex_);
client_ptrs_.push_back(client_ptr);
@@ -197,12 +196,12 @@ CallbackGroup::add_client(const rclcpp::ClientBase::SharedPtr & client_ptr)
std::remove_if(
client_ptrs_.begin(),
client_ptrs_.end(),
[](const rclcpp::ClientBase::WeakPtr & x) {return x.expired();}),
[](rclcpp::ClientBase::WeakPtr x) {return x.expired();}),
client_ptrs_.end());
}
void
CallbackGroup::add_waitable(const rclcpp::Waitable::SharedPtr & waitable_ptr)
CallbackGroup::add_waitable(const rclcpp::Waitable::SharedPtr waitable_ptr)
{
std::lock_guard<std::mutex> lock(mutex_);
waitable_ptrs_.push_back(waitable_ptr);
@@ -210,12 +209,12 @@ CallbackGroup::add_waitable(const rclcpp::Waitable::SharedPtr & waitable_ptr)
std::remove_if(
waitable_ptrs_.begin(),
waitable_ptrs_.end(),
[](const rclcpp::Waitable::WeakPtr & x) {return x.expired();}),
[](rclcpp::Waitable::WeakPtr x) {return x.expired();}),
waitable_ptrs_.end());
}
void
CallbackGroup::remove_waitable(const rclcpp::Waitable::SharedPtr & waitable_ptr) noexcept
CallbackGroup::remove_waitable(const rclcpp::Waitable::SharedPtr waitable_ptr) noexcept
{
std::lock_guard<std::mutex> lock(mutex_);
for (auto iter = waitable_ptrs_.begin(); iter != waitable_ptrs_.end(); ++iter) {

View File

@@ -37,7 +37,7 @@ using rclcpp::exceptions::throw_from_rcl_error;
ClientBase::ClientBase(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr & node_graph)
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph)
: node_graph_(node_graph),
node_handle_(node_base->get_shared_rcl_node_handle()),
context_(node_base->get_context()),

View File

@@ -60,8 +60,8 @@ JumpHandler::JumpHandler(
pre_callback_t pre_callback,
post_callback_t post_callback,
const rcl_jump_threshold_t & threshold)
: pre_callback(std::move(pre_callback)),
post_callback(std::move(post_callback)),
: pre_callback(pre_callback),
post_callback(post_callback),
notice_threshold(threshold)
{}
@@ -83,10 +83,20 @@ 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(
const Time & until,
const Context::SharedPtr & context)
Time until,
Context::SharedPtr context)
{
if (!context || !context->is_valid()) {
throw std::runtime_error("context cannot be slept with because it's invalid");
@@ -108,7 +118,7 @@ Clock::sleep_until(
});
// No longer need the shutdown callback when this function exits
auto callback_remover = rcpputils::scope_exit(
[context, &shutdown_cb_handle]() {
[&context, &shutdown_cb_handle]() {
context->remove_on_shutdown_callback(shutdown_cb_handle);
});
@@ -194,7 +204,7 @@ Clock::sleep_until(
}
bool
Clock::sleep_for(const Duration & rel_time, const Context::SharedPtr & context)
Clock::sleep_for(Duration rel_time, Context::SharedPtr context)
{
return sleep_until(now() + rel_time, context);
}
@@ -209,7 +219,7 @@ Clock::started()
}
bool
Clock::wait_until_started(const Context::SharedPtr & context)
Clock::wait_until_started(Context::SharedPtr context)
{
if (!context || !context->is_valid()) {
throw std::runtime_error("context cannot be slept with because it's invalid");
@@ -229,7 +239,7 @@ Clock::wait_until_started(const Context::SharedPtr & context)
bool
Clock::wait_until_started(
const Duration & timeout,
const Context::SharedPtr & context,
Context::SharedPtr context,
const Duration & wait_tick_ns)
{
if (!context || !context->is_valid()) {
@@ -318,8 +328,8 @@ Clock::on_time_jump(
JumpHandler::SharedPtr
Clock::create_jump_callback(
const JumpHandler::pre_callback_t & pre_callback,
const JumpHandler::post_callback_t & post_callback,
JumpHandler::pre_callback_t pre_callback,
JumpHandler::post_callback_t post_callback,
const rcl_jump_threshold_t & threshold)
{
// Allocate a new jump handler
@@ -516,7 +526,7 @@ class ClockConditionalVariable::Impl
ClockWaiter::UniquePtr clock_;
public:
Impl(const rclcpp::Clock::SharedPtr & clock, const rclcpp::Context::SharedPtr & context)
Impl(const rclcpp::Clock::SharedPtr & clock, rclcpp::Context::SharedPtr context)
:context_(context),
clock_(std::make_unique<ClockWaiter>(clock))
{
@@ -541,7 +551,7 @@ public:
bool
wait_until(
std::unique_lock<std::mutex> & lock, const rclcpp::Time & until,
std::unique_lock<std::mutex> & lock, rclcpp::Time until,
const std::function<bool ()> & pred)
{
if(lock.mutex() != &pred_mutex_) {
@@ -571,7 +581,7 @@ public:
ClockConditionalVariable::ClockConditionalVariable(
const rclcpp::Clock::SharedPtr & clock,
const rclcpp::Context::SharedPtr & context)
rclcpp::Context::SharedPtr context)
:impl_(std::make_unique<Impl>(clock, context))
{
}
@@ -586,7 +596,7 @@ ClockConditionalVariable::notify_one()
bool
ClockConditionalVariable::wait_until(
std::unique_lock<std::mutex> & lock, const rclcpp::Time & until,
std::unique_lock<std::mutex> & lock, rclcpp::Time until,
const std::function<bool ()> & pred)
{
return impl_->wait_until(lock, until, pred);

View File

@@ -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"
@@ -59,7 +60,7 @@ public:
std::remove_if(
weak_contexts_.begin(),
weak_contexts_.end(),
[context](const Context::WeakPtr & weak_context) {
[context](const Context::WeakPtr weak_context) {
auto locked_context = weak_context.lock();
if (!locked_context) {
// take advantage and removed expired contexts
@@ -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
@@ -213,27 +257,28 @@ Context::init(
}
rcl_context_.reset(context, __delete_context);
try {
if (init_options.auto_initialize_logging()) {
logging_mutex_ = get_global_logging_mutex();
std::lock_guard<std::recursive_mutex> guard(*logging_mutex_);
size_t & count = get_logging_reference_count();
if (0u == count) {
ret = rcl_logging_configure_with_output_handler(
&rcl_context_->global_arguments,
rcl_init_options_get_allocator(init_options.get_rcl_init_options()),
rclcpp_logging_output_handler);
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to configure logging");
}
} else {
RCLCPP_WARN(
rclcpp::get_logger("rclcpp"),
"logging was initialized more than once");
if (init_options.auto_initialize_logging()) {
logging_mutex_ = get_global_logging_mutex();
std::lock_guard<std::recursive_mutex> guard(*logging_mutex_);
size_t & count = get_logging_reference_count();
if (0u == count) {
ret = rcl_logging_configure_with_output_handler(
&rcl_context_->global_arguments,
rcl_init_options_get_allocator(init_options.get_rcl_init_options()),
rclcpp_logging_output_handler);
if (RCL_RET_OK != ret) {
rcl_context_.reset();
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to configure logging");
}
++count;
} else {
RCLCPP_WARN(
rclcpp::get_logger("rclcpp"),
"logging was initialized more than once");
}
++count;
}
try {
std::vector<std::string> unparsed_ros_arguments = detail::get_unparsed_ros_arguments(
argc, argv, &(rcl_context_->global_arguments), rcl_get_default_allocator());
if (!unparsed_ros_arguments.empty()) {
@@ -244,24 +289,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 +356,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 +379,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
@@ -388,14 +417,14 @@ Context::shutdown(const std::string & reason)
}
rclcpp::Context::OnShutdownCallback
Context::on_shutdown(const OnShutdownCallback & callback)
Context::on_shutdown(OnShutdownCallback callback)
{
add_on_shutdown_callback(callback);
return callback;
}
rclcpp::OnShutdownCallbackHandle
Context::add_on_shutdown_callback(const OnShutdownCallback & callback)
Context::add_on_shutdown_callback(OnShutdownCallback callback)
{
return add_shutdown_callback<ShutdownType::on_shutdown>(callback);
}
@@ -407,7 +436,7 @@ Context::remove_on_shutdown_callback(const OnShutdownCallbackHandle & callback_h
}
rclcpp::PreShutdownCallbackHandle
Context::add_pre_shutdown_callback(const PreShutdownCallback & callback)
Context::add_pre_shutdown_callback(PreShutdownCallback callback)
{
return add_shutdown_callback<ShutdownType::pre_shutdown>(callback);
}
@@ -422,7 +451,7 @@ Context::remove_pre_shutdown_callback(
template<Context::ShutdownType shutdown_type>
rclcpp::ShutdownCallbackHandle
Context::add_shutdown_callback(
const ShutdownCallback & callback)
ShutdownCallback callback)
{
auto callback_shared_ptr =
std::make_shared<ShutdownCallbackHandle::ShutdownCallbackType>(callback);
@@ -431,10 +460,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 +496,7 @@ Context::remove_shutdown_callback(
return false;
}
callback_vector.erase(iter);
return true;
};
@@ -472,9 +504,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_);
}
}
@@ -497,9 +531,8 @@ Context::get_shutdown_callback() const
const auto get_callback_vector = [](auto & mutex, auto & callback_set) {
const std::lock_guard<std::recursive_mutex> lock(mutex);
std::vector<rclcpp::Context::ShutdownCallback> callbacks;
callbacks.reserve(callback_set.size());
for (auto & callback : callback_set) {
callbacks.emplace_back(*callback);
callbacks.push_back(*callback);
}
return callbacks;
};
@@ -508,9 +541,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_);
}
}
@@ -520,12 +555,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)
{

View File

@@ -19,13 +19,13 @@ namespace rclcpp
{
rclcpp::GenericClient::SharedPtr
create_generic_client(
const std::shared_ptr<node_interfaces::NodeBaseInterface> & node_base,
const std::shared_ptr<node_interfaces::NodeGraphInterface> & node_graph,
const std::shared_ptr<node_interfaces::NodeServicesInterface> & node_services,
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
std::shared_ptr<node_interfaces::NodeGraphInterface> node_graph,
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
const std::string & service_name,
const std::string & service_type,
const rclcpp::QoS & qos,
const rclcpp::CallbackGroup::SharedPtr & group)
rclcpp::CallbackGroup::SharedPtr group)
{
rcl_client_options_t options = rcl_client_get_default_options();
options.qos = qos.get_rmw_qos_profile();

View File

@@ -1,49 +0,0 @@
// Copyright 2024 Sony Group Corporation.
//
// 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 <string>
#include <memory>
#include "rclcpp/create_generic_service.hpp"
#include "rclcpp/generic_service.hpp"
namespace rclcpp
{
rclcpp::GenericService::SharedPtr
create_generic_service(
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
std::shared_ptr<node_interfaces::NodeGraphInterface> node_graph,
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
const std::string & service_name,
const std::string & service_type,
GenericServiceCallback any_callback,
const rclcpp::QoS & qos,
rclcpp::CallbackGroup::SharedPtr group)
{
rcl_service_options_t options = rcl_service_get_default_options();
options.qos = qos.get_rmw_qos_profile();
auto srv = rclcpp::GenericService::make_shared(
node_base.get(),
node_graph,
service_name,
service_type,
any_callback,
options);
auto srv_base_ptr = std::dynamic_pointer_cast<rclcpp::ServiceBase>(srv);
node_services->add_service(srv_base_ptr, group);
return srv;
}
} // namespace rclcpp

View File

@@ -23,9 +23,10 @@ namespace detail
void
RMWImplementationSpecificPublisherPayload::modify_rmw_publisher_options(
[[maybe_unused]] rmw_publisher_options_t & rmw_publisher_options) const
rmw_publisher_options_t & rmw_publisher_options) const
{
// By default, do not mutate the rmw publisher options.
(void)rmw_publisher_options;
}
} // namespace detail

View File

@@ -23,9 +23,10 @@ namespace detail
void
RMWImplementationSpecificSubscriptionPayload::modify_rmw_subscription_options(
[[maybe_unused]] rmw_subscription_options_t & rmw_subscription_options) const
rmw_subscription_options_t & rmw_subscription_options) const
{
// By default, do not mutate the rmw subscription options.
(void)rmw_subscription_options;
}
} // namespace detail

View File

@@ -31,10 +31,11 @@ namespace detail
std::vector<std::string>
get_unparsed_ros_arguments(
[[maybe_unused]] int argc, char const * const * argv,
int argc, char const * const * argv,
rcl_arguments_t * arguments,
rcl_allocator_t allocator)
{
(void)argc;
std::vector<std::string> unparsed_ros_arguments;
int unparsed_ros_args_count = rcl_arguments_get_count_unparsed_ros(arguments);
if (unparsed_ros_args_count > 0) {

View File

@@ -93,9 +93,7 @@ throw_from_rcl_error(
RCLErrorBase::RCLErrorBase(rcl_ret_t ret, const rcl_error_state_t * error_state)
: ret(ret), message(error_state->message), file(error_state->file), line(error_state->line_number),
formatted_message(rcl_get_error_string().str)
{
rcl_reset_error();
}
{}
RCLError::RCLError(
rcl_ret_t ret,

View File

@@ -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)
@@ -68,7 +66,7 @@ Executor::Executor(const rclcpp::ExecutorOptions & options)
notify_waitable_(std::make_shared<rclcpp::executors::ExecutorNotifyWaitable>(
[this]() {
this->entities_need_rebuild_.store(true);
}, options.context)),
})),
entities_need_rebuild_(true),
collector_(notify_waitable_),
wait_set_({}, {}, {}, {}, {}, {}, options.context),
@@ -99,29 +97,29 @@ Executor::~Executor()
notify_waitable_->remove_guard_condition(shutdown_guard_condition_);
current_collection_.timers.update(
{}, {},
[this](auto timer) {wait_set_.remove_timer(std::move(timer));});
[this](auto timer) {wait_set_.remove_timer(timer);});
current_collection_.subscriptions.update(
{}, {},
[this](auto subscription) {
wait_set_.remove_subscription(std::move(subscription), kDefaultSubscriptionMask);
wait_set_.remove_subscription(subscription, kDefaultSubscriptionMask);
});
current_collection_.clients.update(
{}, {},
[this](auto client) {wait_set_.remove_client(std::move(client));});
[this](auto client) {wait_set_.remove_client(client);});
current_collection_.services.update(
{}, {},
[this](auto service) {wait_set_.remove_service(std::move(service));});
[this](auto service) {wait_set_.remove_service(service);});
current_collection_.guard_conditions.update(
{}, {},
[this](auto guard_condition) {wait_set_.remove_guard_condition(std::move(guard_condition));});
[this](auto guard_condition) {wait_set_.remove_guard_condition(guard_condition);});
current_collection_.waitables.update(
{}, {},
[this](auto waitable) {wait_set_.remove_waitable(std::move(waitable));});
[this](auto waitable) {wait_set_.remove_waitable(waitable);});
// Remove shutdown callback handle registered to Context
if (!context_->remove_on_shutdown_callback(shutdown_callback_handle_)) {
@@ -133,7 +131,7 @@ Executor::~Executor()
}
void
Executor::handle_updated_entities(bool notify)
Executor::trigger_entity_recollect(bool notify)
{
this->entities_need_rebuild_.store(true);
@@ -170,89 +168,81 @@ Executor::get_automatically_added_callback_groups_from_nodes()
void
Executor::add_callback_group(
const rclcpp::CallbackGroup::SharedPtr & group_ptr,
[[maybe_unused]] const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
rclcpp::CallbackGroup::SharedPtr group_ptr,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
bool notify)
{
(void) node_ptr;
this->collector_.add_callback_group(group_ptr);
try {
this->handle_updated_entities(notify);
this->trigger_entity_recollect(notify);
} catch (const rclcpp::exceptions::RCLError & ex) {
throw std::runtime_error(
std::string(
"Failed to handle entities update on callback group add: ") + ex.what());
"Failed to trigger guard condition on callback group add: ") + ex.what());
}
}
void
Executor::add_node(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
bool notify)
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 {
this->handle_updated_entities(notify);
this->trigger_entity_recollect(notify);
} catch (const rclcpp::exceptions::RCLError & ex) {
throw std::runtime_error(
std::string(
"Failed to handle entities update on node add: ") + ex.what());
"Failed to trigger guard condition on node add: ") + ex.what());
}
}
void
Executor::remove_callback_group(
const rclcpp::CallbackGroup::SharedPtr & group_ptr,
rclcpp::CallbackGroup::SharedPtr group_ptr,
bool notify)
{
this->collector_.remove_callback_group(group_ptr);
try {
this->handle_updated_entities(notify);
this->trigger_entity_recollect(notify);
} catch (const rclcpp::exceptions::RCLError & ex) {
throw std::runtime_error(
std::string(
"Failed to handle entities update on callback group remove: ") + ex.what());
"Failed to trigger guard condition on callback group remove: ") + ex.what());
}
}
void
Executor::add_node(const std::shared_ptr<rclcpp::Node> & node_ptr, bool notify)
Executor::add_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify)
{
this->add_node(node_ptr->get_node_base_interface(), notify);
}
void
Executor::remove_node(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
bool notify)
Executor::remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify)
{
this->collector_.remove_node(node_ptr);
try {
this->handle_updated_entities(notify);
this->trigger_entity_recollect(notify);
} catch (const rclcpp::exceptions::RCLError & ex) {
throw std::runtime_error(
std::string(
"Failed to handle entities update on node remove: ") + ex.what());
"Failed to trigger guard condition on node remove: ") + ex.what());
}
}
void
Executor::remove_node(const std::shared_ptr<rclcpp::Node> & node_ptr, bool notify)
Executor::remove_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify)
{
this->remove_node(node_ptr->get_node_base_interface(), notify);
}
void
Executor::spin_node_once_nanoseconds(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
std::chrono::nanoseconds timeout)
{
this->add_node(node, false);
@@ -315,7 +305,7 @@ Executor::spin_until_future_complete_impl(
}
void
Executor::spin_node_some(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node)
Executor::spin_node_some(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node)
{
this->add_node(node, false);
spin_some();
@@ -323,7 +313,7 @@ Executor::spin_node_some(const rclcpp::node_interfaces::NodeBaseInterface::Share
}
void
Executor::spin_node_some(const std::shared_ptr<rclcpp::Node> & node)
Executor::spin_node_some(std::shared_ptr<rclcpp::Node> node)
{
this->spin_node_some(node->get_node_base_interface());
}
@@ -335,7 +325,7 @@ void Executor::spin_some(std::chrono::nanoseconds max_duration)
void
Executor::spin_node_all(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
std::chrono::nanoseconds max_duration)
{
this->add_node(node, false);
@@ -344,9 +334,7 @@ Executor::spin_node_all(
}
void
Executor::spin_node_all(
const std::shared_ptr<rclcpp::Node> & node,
std::chrono::nanoseconds max_duration)
Executor::spin_node_all(std::shared_ptr<rclcpp::Node> node, std::chrono::nanoseconds max_duration)
{
this->spin_node_all(node->get_node_base_interface(), max_duration);
}
@@ -552,7 +540,7 @@ take_and_do_error_handling(
}
void
Executor::execute_subscription(const rclcpp::SubscriptionBase::SharedPtr & subscription)
Executor::execute_subscription(rclcpp::SubscriptionBase::SharedPtr subscription)
{
using rclcpp::dynamic_typesupport::DynamicMessage;
@@ -597,7 +585,6 @@ Executor::execute_subscription(const rclcpp::SubscriptionBase::SharedPtr & subsc
"rcl_return_loaned_message_from_subscription() failed for subscription on topic "
"'%s': %s",
subscription->get_topic_name(), rcl_get_error_string().str);
rcl_reset_error();
}
loaned_msg = nullptr;
}
@@ -646,7 +633,7 @@ Executor::execute_subscription(const rclcpp::SubscriptionBase::SharedPtr & subsc
throw std::runtime_error("Unimplemented");
}
case rclcpp::DeliveredMessageKind::INVALID:
default:
{
throw std::runtime_error("Delivered message kind is not supported");
}
@@ -654,15 +641,13 @@ Executor::execute_subscription(const rclcpp::SubscriptionBase::SharedPtr & subsc
}
void
Executor::execute_timer(
const rclcpp::TimerBase::SharedPtr & timer,
const std::shared_ptr<void> & data_ptr)
Executor::execute_timer(rclcpp::TimerBase::SharedPtr timer, const std::shared_ptr<void> & data_ptr)
{
timer->execute_callback(data_ptr);
}
void
Executor::execute_service(const rclcpp::ServiceBase::SharedPtr & service)
Executor::execute_service(rclcpp::ServiceBase::SharedPtr service)
{
auto request_header = service->create_request_header();
std::shared_ptr<void> request = service->create_request();
@@ -674,7 +659,7 @@ Executor::execute_service(const rclcpp::ServiceBase::SharedPtr & service)
}
void
Executor::execute_client(const rclcpp::ClientBase::SharedPtr & client)
Executor::execute_client(rclcpp::ClientBase::SharedPtr client)
{
auto request_header = client->create_request_header();
std::shared_ptr<void> response = client->create_response();
@@ -716,37 +701,37 @@ Executor::collect_entities()
// from the wait set as necessary.
current_collection_.timers.update(
collection.timers,
[this](auto timer) {wait_set_.add_timer(std::move(timer));},
[this](auto timer) {wait_set_.remove_timer(std::move(timer));});
[this](auto timer) {wait_set_.add_timer(timer);},
[this](auto timer) {wait_set_.remove_timer(timer);});
current_collection_.subscriptions.update(
collection.subscriptions,
[this](auto subscription) {
wait_set_.add_subscription(std::move(subscription), kDefaultSubscriptionMask);
wait_set_.add_subscription(subscription, kDefaultSubscriptionMask);
},
[this](auto subscription) {
wait_set_.remove_subscription(std::move(subscription), kDefaultSubscriptionMask);
wait_set_.remove_subscription(subscription, kDefaultSubscriptionMask);
});
current_collection_.clients.update(
collection.clients,
[this](auto client) {wait_set_.add_client(std::move(client));},
[this](auto client) {wait_set_.remove_client(std::move(client));});
[this](auto client) {wait_set_.add_client(client);},
[this](auto client) {wait_set_.remove_client(client);});
current_collection_.services.update(
collection.services,
[this](auto service) {wait_set_.add_service(std::move(service));},
[this](auto service) {wait_set_.remove_service(std::move(service));});
[this](auto service) {wait_set_.add_service(service);},
[this](auto service) {wait_set_.remove_service(service);});
current_collection_.guard_conditions.update(
collection.guard_conditions,
[this](auto guard_condition) {wait_set_.add_guard_condition(std::move(guard_condition));},
[this](auto guard_condition) {wait_set_.remove_guard_condition(std::move(guard_condition));});
[this](auto guard_condition) {wait_set_.add_guard_condition(guard_condition);},
[this](auto guard_condition) {wait_set_.remove_guard_condition(guard_condition);});
current_collection_.waitables.update(
collection.waitables,
[this](auto waitable) {wait_set_.add_waitable(std::move(waitable));},
[this](auto waitable) {wait_set_.remove_waitable(std::move(waitable));});
[this](auto waitable) {wait_set_.add_waitable(waitable);},
[this](auto waitable) {wait_set_.remove_waitable(waitable);});
// In the case that an entity already has an expired weak pointer
// before being removed from the waitset, additionally prune the waitset.
@@ -761,16 +746,33 @@ Executor::wait_for_work(std::chrono::nanoseconds timeout)
// Clear any previous wait result
this->wait_result_.reset();
// 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;
{
std::lock_guard<std::mutex> guard(mutex_);
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));
}
}
}
this->wait_result_.emplace(wait_set_.wait(timeout));
// drop references to the callback groups, before trying to execute anything
cbgs.clear();
if (!this->wait_result_ || this->wait_result_->kind() == WaitResultKind::Empty) {
RCUTILS_LOG_WARN_NAMED(
"rclcpp",

View File

@@ -13,11 +13,10 @@
// limitations under the License.
#include "rclcpp/executors.hpp"
#include "rcpputils/compile_warnings.hpp"
void
rclcpp::spin_all(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
std::chrono::nanoseconds max_duration)
{
rclcpp::ExecutorOptions options;
@@ -27,7 +26,13 @@ rclcpp::spin_all(
}
void
rclcpp::spin_some(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr)
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)
{
rclcpp::ExecutorOptions options;
options.context = node_ptr->get_context();
@@ -36,7 +41,13 @@ rclcpp::spin_some(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr &
}
void
rclcpp::spin(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr)
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)
{
rclcpp::ExecutorOptions options;
options.context = node_ptr->get_context();
@@ -47,23 +58,7 @@ rclcpp::spin(const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_
}
void
rclcpp::spin(const rclcpp::Node::SharedPtr & node_ptr)
rclcpp::spin(rclcpp::Node::SharedPtr node_ptr)
{
rclcpp::spin(node_ptr->get_node_base_interface());
}
void
rclcpp::spin_all(const 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(const rclcpp::Node::SharedPtr & node_ptr)
{
RCPPUTILS_DEPRECATION_WARNING_OFF_START
rclcpp::spin_some(node_ptr->get_node_base_interface());
RCPPUTILS_DEPRECATION_WARNING_OFF_STOP
}

Some files were not shown because too many files have changed in this diff Show More