Compare commits
146 Commits
fix_wait_s
...
2.4.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11edf82c7d | ||
|
|
48ec78cb24 | ||
|
|
5c1dd19456 | ||
|
|
15edc93a5f | ||
|
|
1ea25302c3 | ||
|
|
7e1740a52b | ||
|
|
a8baa3ce88 | ||
|
|
a58f8c1de4 | ||
|
|
d7804e1b3f | ||
|
|
e70a07d0c0 | ||
|
|
4859c4e435 | ||
|
|
97a852454e | ||
|
|
c191956f63 | ||
|
|
c2285c9a40 | ||
|
|
92fe787a74 | ||
|
|
dc3832c4ec | ||
|
|
ac3fc4d50f | ||
|
|
1fff1b7cba | ||
|
|
1c92622516 | ||
|
|
122355704b | ||
|
|
d12ed36e89 | ||
|
|
791c23afe5 | ||
|
|
6ceeff0f0f | ||
|
|
6a1b6a3f38 | ||
|
|
47f21dab3d | ||
|
|
8f2809df64 | ||
|
|
a2004f8369 | ||
|
|
6756ccfb50 | ||
|
|
234b5e423b | ||
|
|
3dddfd7d93 | ||
|
|
b132a2b0cd | ||
|
|
a4fd8ceece | ||
|
|
965b4d2c24 | ||
|
|
bea9c5a8f6 | ||
|
|
3497650ee2 | ||
|
|
17847ee90a | ||
|
|
46ec8bb5df | ||
|
|
4cc446d9a2 | ||
|
|
6820dac315 | ||
|
|
29cfc45e81 | ||
|
|
5607c3242d | ||
|
|
c277b4c8bb | ||
|
|
d65bc667fa | ||
|
|
37415670c6 | ||
|
|
1c22d6b2c4 | ||
|
|
9f2f754029 | ||
|
|
0e8450940f | ||
|
|
7266e67683 | ||
|
|
d04ec4bf80 | ||
|
|
e920175dae | ||
|
|
ed7a23731a | ||
|
|
85235938f6 | ||
|
|
f357033ad7 | ||
|
|
bee4b760fb | ||
|
|
8f2f746b41 | ||
|
|
f1c5524164 | ||
|
|
dec7d8a00f | ||
|
|
730e99b742 | ||
|
|
43df9eff37 | ||
|
|
77aae4019e | ||
|
|
504e68bdab | ||
|
|
5e8fff6549 | ||
|
|
1ae8ca41fb | ||
|
|
b3f50460f4 | ||
|
|
17c53a16f0 | ||
|
|
1b9cf547a4 | ||
|
|
a6b9def7ae | ||
|
|
707f9cfa8e | ||
|
|
ec31b29824 | ||
|
|
77a3c06f2b | ||
|
|
7757f6b402 | ||
|
|
80b2f5439b | ||
|
|
bcce051eb2 | ||
|
|
ee7b8ca5f2 | ||
|
|
2078887a2b | ||
|
|
8808f4b287 | ||
|
|
cb6ac99a49 | ||
|
|
8cc331f38c | ||
|
|
6238b4263b | ||
|
|
ddb43bb3ab | ||
|
|
823163e68e | ||
|
|
55b30fc1e2 | ||
|
|
b49295ceee | ||
|
|
f8da934ac9 | ||
|
|
0a4ff4db3d | ||
|
|
94082318c9 | ||
|
|
f000b53095 | ||
|
|
443fc180c7 | ||
|
|
e700d3becd | ||
|
|
5fd6e2340a | ||
|
|
b451425ce6 | ||
|
|
0312defbc5 | ||
|
|
fb76d4b640 | ||
|
|
e20837bf6a | ||
|
|
420eb01a65 | ||
|
|
9f11b1d6a2 | ||
|
|
d2d4c599e0 | ||
|
|
baea732ec9 | ||
|
|
8be1e76fd8 | ||
|
|
b17c73992a | ||
|
|
954cc3d27f | ||
|
|
efef96e657 | ||
|
|
32ef520434 | ||
|
|
61357c49f7 | ||
|
|
41d5f24425 | ||
|
|
48f956a3e3 | ||
|
|
48d3603018 | ||
|
|
3b1319b23d | ||
|
|
04bccb95cb | ||
|
|
60bcee36ab | ||
|
|
f1283ef4b9 | ||
|
|
7d7d4c3b96 | ||
|
|
623e013f48 | ||
|
|
df036bbe03 | ||
|
|
30e9fae395 | ||
|
|
25286ac1c3 | ||
|
|
c21ddaaf8b | ||
|
|
23ef782e02 | ||
|
|
00b4020194 | ||
|
|
823e1dd404 | ||
|
|
f71d3bfda2 | ||
|
|
cf1be86f5c | ||
|
|
4dcb0eda68 | ||
|
|
9c1cbdf6c7 | ||
|
|
6e6dd9cb1a | ||
|
|
45a47c6448 | ||
|
|
6e408b79f3 | ||
|
|
b843c75ef8 | ||
|
|
cb1b32ee15 | ||
|
|
b67fa594f8 | ||
|
|
8bfc8e631f | ||
|
|
75f3d54d57 | ||
|
|
27e59d930a | ||
|
|
ce5de8757d | ||
|
|
6ea67a4e9f | ||
|
|
5f6bf45202 | ||
|
|
dc528ad710 | ||
|
|
26e824c7c0 | ||
|
|
3a3ba55fa2 | ||
|
|
1745db6dcd | ||
|
|
7ed387f862 | ||
|
|
a10ae56629 | ||
|
|
1f000b8d97 | ||
|
|
c14f46e6f3 | ||
|
|
70e1830ecd | ||
|
|
77564eb2ff |
@@ -8,10 +8,10 @@ rclcpp provides the standard C++ API for interacting with ROS 2.
|
||||
|
||||
`#include "rclcpp/rclcpp.hpp"` allows use of the most common elements of the ROS 2 system.
|
||||
|
||||
Visit the [rclcpp API documentation](http://docs.ros2.org/latest/api/rclcpp/) for a complete list of its main components.
|
||||
Visit the [rclcpp API documentation](http://docs.ros2.org/foxy/api/rclcpp/) for a complete list of its main components.
|
||||
|
||||
### Examples
|
||||
|
||||
The ROS 2 tutorials [Writing a simple publisher and subscriber](https://docs.ros.org/en/rolling/Tutorials/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html).
|
||||
and [Writing a simple service and client](https://docs.ros.org/en/rolling/Tutorials/Writing-A-Simple-Cpp-Service-And-Client.html)
|
||||
The ROS 2 tutorials [Writing a simple publisher and subscriber](https://docs.ros.org/en/foxy/Tutorials/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html).
|
||||
and [Writing a simple service and client](https://docs.ros.org/en/foxy/Tutorials/Writing-A-Simple-Cpp-Service-And-Client.html)
|
||||
contain some examples of rclcpp APIs in use.
|
||||
|
||||
@@ -2,309 +2,157 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
11.0.0 (2021-05-18)
|
||||
-------------------
|
||||
* Allow declare uninitialized parameters (`#1673 <https://github.com/ros2/rclcpp/issues/1673>`_)
|
||||
* Fix syntax issue with gcc (`#1674 <https://github.com/ros2/rclcpp/issues/1674>`_)
|
||||
* [service] Don't use a weak_ptr to avoid leaking (`#1668 <https://github.com/ros2/rclcpp/issues/1668>`_)
|
||||
* Contributors: Ivan Santiago Paunovic, Jacob Perron, William Woodall
|
||||
|
||||
10.0.0 (2021-05-11)
|
||||
-------------------
|
||||
* Fix doc typo (`#1663 <https://github.com/ros2/rclcpp/issues/1663>`_)
|
||||
* [rclcpp] Type Adaptation feature (`#1557 <https://github.com/ros2/rclcpp/issues/1557>`_)
|
||||
* Do not attempt to use void allocators for memory allocation. (`#1657 <https://github.com/ros2/rclcpp/issues/1657>`_)
|
||||
* Keep custom allocator in publisher and subscription options alive. (`#1647 <https://github.com/ros2/rclcpp/issues/1647>`_)
|
||||
* Fix get_publishers_subscriptions_info_by_topic test in test_node.cpp (`#1648 <https://github.com/ros2/rclcpp/issues/1648>`_)
|
||||
* Use OnShutdown callback handle instead of OnShutdown callback (`#1639 <https://github.com/ros2/rclcpp/issues/1639>`_)
|
||||
* use dynamic_pointer_cast to detect allocator mismatch in intra process manager (`#1643 <https://github.com/ros2/rclcpp/issues/1643>`_)
|
||||
* Increase cppcheck timeout to 500s (`#1634 <https://github.com/ros2/rclcpp/issues/1634>`_)
|
||||
* Clarify node parameters docs (`#1631 <https://github.com/ros2/rclcpp/issues/1631>`_)
|
||||
* Contributors: Audrow Nash, Barry Xu, Jacob Perron, Michel Hidalgo, Shane Loretz, William Woodall
|
||||
|
||||
9.0.2 (2021-04-14)
|
||||
2.4.2 (2022-07-25)
|
||||
------------------
|
||||
* Avoid returning loan when none was obtained. (`#1629 <https://github.com/ros2/rclcpp/issues/1629>`_)
|
||||
* Use a different implementation of mutex two priorities (`#1628 <https://github.com/ros2/rclcpp/issues/1628>`_)
|
||||
* Do not test the value of the history policy when testing the get_publishers/subscriptions_info_by_topic() methods (`#1626 <https://github.com/ros2/rclcpp/issues/1626>`_)
|
||||
* Check first parameter type and range before calling the user validation callbacks (`#1627 <https://github.com/ros2/rclcpp/issues/1627>`_)
|
||||
* Contributors: Ivan Santiago Paunovic, Miguel Company
|
||||
* Add statistics for handle_loaned_message (`#1927 <https://github.com/ros2/rclcpp/issues/1927>`_) (`#1934 <https://github.com/ros2/rclcpp/issues/1934>`_)
|
||||
* Add test-dep ament_cmake_google_benchmark (`#1904 <https://github.com/ros2/rclcpp/issues/1904>`_) (`#1910 <https://github.com/ros2/rclcpp/issues/1910>`_)
|
||||
* Use parantheses around logging macro parameter (`#1820 <https://github.com/ros2/rclcpp/issues/1820>`_) (`#1823 <https://github.com/ros2/rclcpp/issues/1823>`_)
|
||||
* Contributors: Abrar Rahman Protyasha, Barry Xu, Gaël Écorchard
|
||||
|
||||
9.0.1 (2021-04-12)
|
||||
2.4.1 (2022-01-31)
|
||||
------------------
|
||||
* Restore test exception for Connext (`#1625 <https://github.com/ros2/rclcpp/issues/1625>`_)
|
||||
* Fix race condition in TimeSource clock thread setup (`#1623 <https://github.com/ros2/rclcpp/issues/1623>`_)
|
||||
* Contributors: Andrea Sorbini, Michel Hidalgo
|
||||
* Fix subscription instrumentation for ConstSharedPtr[WithInfo]Callback (`#1872 <https://github.com/ros2/rclcpp/issues/1872>`_)
|
||||
* Add node_waitables\_ to copy constructor (backport `#1799 <https://github.com/ros2/rclcpp/issues/1799>`_) (`#1834 <https://github.com/ros2/rclcpp/issues/1834>`_)
|
||||
* Fix returning invalid namespace if sub_namespace is empty (`#1658 <https://github.com/ros2/rclcpp/issues/1658>`_) (`#1811 <https://github.com/ros2/rclcpp/issues/1811>`_)
|
||||
* [service] Don't use a weak_ptr to avoid leaking (`#1668 <https://github.com/ros2/rclcpp/issues/1668>`_) (`#1669 <https://github.com/ros2/rclcpp/issues/1669>`_)
|
||||
* Use dynamic_pointer_cast to detect allocator mismatch in intra process manager (backport `#1643 <https://github.com/ros2/rclcpp/issues/1643>`_) (`#1645 <https://github.com/ros2/rclcpp/issues/1645>`_)
|
||||
* Contributors: Abrar Rahman Protyasha, Christophe Bedard, Ivan Santiago Paunovic, M. Hofstätter, Michel Hidalgo, Tomoya Fujita, William Woodall
|
||||
|
||||
9.0.0 (2021-04-06)
|
||||
2.4.0 (2021-09-01)
|
||||
------------------
|
||||
* remove deprecated code which was deprecated in foxy and should be removed in galactic (`#1622 <https://github.com/ros2/rclcpp/issues/1622>`_)
|
||||
* Change index.ros.org -> docs.ros.org. (`#1620 <https://github.com/ros2/rclcpp/issues/1620>`_)
|
||||
* Unique network flows (`#1496 <https://github.com/ros2/rclcpp/issues/1496>`_)
|
||||
* Add spin_some support to the StaticSingleThreadedExecutor (`#1338 <https://github.com/ros2/rclcpp/issues/1338>`_)
|
||||
* Add publishing instrumentation (`#1600 <https://github.com/ros2/rclcpp/issues/1600>`_)
|
||||
* Create load_parameters and delete_parameters methods (`#1596 <https://github.com/ros2/rclcpp/issues/1596>`_)
|
||||
* refactor AnySubscriptionCallback and add/deprecate callback signatures (`#1598 <https://github.com/ros2/rclcpp/issues/1598>`_)
|
||||
* Add generic publisher and generic subscription for serialized messages (`#1452 <https://github.com/ros2/rclcpp/issues/1452>`_)
|
||||
* use context from `node_base\_` for clock executor. (`#1617 <https://github.com/ros2/rclcpp/issues/1617>`_)
|
||||
* updating quality declaration links (re: `ros2/docs.ros2.org#52 <https://github.com/ros2/docs.ros2.org/issues/52>`_) (`#1615 <https://github.com/ros2/rclcpp/issues/1615>`_)
|
||||
* Contributors: Ananya Muddukrishna, BriceRenaudeau, Chris Lalancette, Christophe Bedard, Nikolai Morin, Tomoya Fujita, William Woodall, mauropasse, shonigmann
|
||||
* Guard against integer overflow in duration conversion (`#1584 <https://github.com/ros2/rclcpp/issues/1584>`_) (`#1761 <https://github.com/ros2/rclcpp/issues/1761>`_)
|
||||
* Update for checking correct variable (`#1534 <https://github.com/ros2/rclcpp/issues/1534>`_) (`#1760 <https://github.com/ros2/rclcpp/issues/1760>`_)
|
||||
* Fix SEGV caused by order of destruction of Node sub-interfaces (`#1469 <https://github.com/ros2/rclcpp/issues/1469>`_) (`#1736 <https://github.com/ros2/rclcpp/issues/1736>`_)
|
||||
* Add wait for message API (`#1705 <https://github.com/ros2/rclcpp/issues/1705>`_) (`#1737 <https://github.com/ros2/rclcpp/issues/1737>`_)
|
||||
* Fix documentation bug (`#1719 <https://github.com/ros2/rclcpp/issues/1719>`_) (`#1721 <https://github.com/ros2/rclcpp/issues/1721>`_)
|
||||
* Fix clock thread issue (`#1266 <https://github.com/ros2/rclcpp/issues/1266>`_) (`#1267 <https://github.com/ros2/rclcpp/issues/1267>`_) (`#1685 <https://github.com/ros2/rclcpp/issues/1685>`_)
|
||||
* Allow timers to keep up the intended rate in MultiThreadedExecutor `#1516 <https://github.com/ros2/rclcpp/issues/1516>`_ (`#1636 <https://github.com/ros2/rclcpp/issues/1636>`_)
|
||||
Backports `#1516 <https://github.com/ros2/rclcpp/issues/1516>`_ and follow-up fix `#1628 <https://github.com/ros2/rclcpp/issues/1628>`_
|
||||
* Contributors: Chen Lihui, Colin MacKenzie, Daisuke Sato, Jacob Perron, Karsten Knese, Tomoya Fujita, hsgwa, William Woodall
|
||||
|
||||
8.2.0 (2021-03-31)
|
||||
2.3.1 (2021-04-14)
|
||||
------------------
|
||||
* Initialize integers in test_parameter_event_handler.cpp to avoid undefined behavior (`#1609 <https://github.com/ros2/rclcpp/issues/1609>`_)
|
||||
* Namespace tracetools C++ functions (`#1608 <https://github.com/ros2/rclcpp/issues/1608>`_)
|
||||
* Revert "Namespace tracetools C++ functions (`#1603 <https://github.com/ros2/rclcpp/issues/1603>`_)" (`#1607 <https://github.com/ros2/rclcpp/issues/1607>`_)
|
||||
* Namespace tracetools C++ functions (`#1603 <https://github.com/ros2/rclcpp/issues/1603>`_)
|
||||
* Clock subscription callback group spins in its own thread (`#1556 <https://github.com/ros2/rclcpp/issues/1556>`_)
|
||||
* Contributors: Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, anaelle-sw
|
||||
* Update quality declaration links (re: `ros2/docs.ros2.org#52 <https://github.com/ros2/docs.ros2.org/issues/52>`_) (`#1616 <https://github.com/ros2/rclcpp/issues/1616>`_)
|
||||
* Fix documented example in create_publisher (`#1558 <https://github.com/ros2/rclcpp/issues/1558>`_) (`#1559 <https://github.com/ros2/rclcpp/issues/1559>`_)
|
||||
* Fix runtime error: reference binding to null pointer of type (`#1547 <https://github.com/ros2/rclcpp/issues/1547>`_) (`#1548 <https://github.com/ros2/rclcpp/issues/1548>`_)
|
||||
* Contributors: Jacob Perron, Simon Honigmann, Tomoya Fujita
|
||||
|
||||
8.1.0 (2021-03-25)
|
||||
2.3.0 (2020-12-09)
|
||||
------------------
|
||||
* Remove rmw_connext_cpp references. (`#1595 <https://github.com/ros2/rclcpp/issues/1595>`_)
|
||||
* Add API for checking QoS profile compatibility (`#1554 <https://github.com/ros2/rclcpp/issues/1554>`_)
|
||||
* Document misuse of parameters callback (`#1590 <https://github.com/ros2/rclcpp/issues/1590>`_)
|
||||
* use const auto & to iterate over parameters (`#1593 <https://github.com/ros2/rclcpp/issues/1593>`_)
|
||||
* Contributors: Chris Lalancette, Jacob Perron, Karsten Knese
|
||||
|
||||
8.0.0 (2021-03-23)
|
||||
------------------
|
||||
* Guard against integer overflow in duration conversion (`#1584 <https://github.com/ros2/rclcpp/issues/1584>`_)
|
||||
* Contributors: Jacob Perron
|
||||
|
||||
7.0.1 (2021-03-22)
|
||||
------------------
|
||||
* get_parameters service should return empty if undeclared parameters are allowed (`#1514 <https://github.com/ros2/rclcpp/issues/1514>`_)
|
||||
* Made 'Context::shutdown_reason' function a const function (`#1578 <https://github.com/ros2/rclcpp/issues/1578>`_)
|
||||
* Contributors: Tomoya Fujita, suab321321
|
||||
|
||||
7.0.0 (2021-03-18)
|
||||
------------------
|
||||
* Document design decisions that were made for statically typed parameters (`#1568 <https://github.com/ros2/rclcpp/issues/1568>`_)
|
||||
* Fix doc typo in CallbackGroup constructor (`#1582 <https://github.com/ros2/rclcpp/issues/1582>`_)
|
||||
* Enable qos parameter overrides for the /parameter_events topic (`#1532 <https://github.com/ros2/rclcpp/issues/1532>`_)
|
||||
* Add support for rmw_connextdds (`#1574 <https://github.com/ros2/rclcpp/issues/1574>`_)
|
||||
* Remove 'struct' from the rcl_time_jump_t. (`#1577 <https://github.com/ros2/rclcpp/issues/1577>`_)
|
||||
* Add tests for declaring statically typed parameters when undeclared parameters are allowed (`#1575 <https://github.com/ros2/rclcpp/issues/1575>`_)
|
||||
* Quiet clang memory leak warning on "DoNotOptimize". (`#1571 <https://github.com/ros2/rclcpp/issues/1571>`_)
|
||||
* Add ParameterEventsSubscriber class (`#829 <https://github.com/ros2/rclcpp/issues/829>`_)
|
||||
* When a parameter change is rejected, the parameters map shouldn't be updated. (`#1567 <https://github.com/ros2/rclcpp/pull/1567>`_)
|
||||
* Fix when to throw the NoParameterOverrideProvided exception. (`#1567 <https://github.com/ros2/rclcpp/pull/1567>`_)
|
||||
* Fix SEGV caused by order of destruction of Node sub-interfaces (`#1469 <https://github.com/ros2/rclcpp/issues/1469>`_)
|
||||
* Fix benchmark test failure introduced in `#1522 <https://github.com/ros2/rclcpp/issues/1522>`_ (`#1564 <https://github.com/ros2/rclcpp/issues/1564>`_)
|
||||
* Fix documented example in create_publisher (`#1558 <https://github.com/ros2/rclcpp/issues/1558>`_)
|
||||
* Enforce static parameter types (`#1522 <https://github.com/ros2/rclcpp/issues/1522>`_)
|
||||
* Allow timers to keep up the intended rate in MultiThreadedExecutor (`#1516 <https://github.com/ros2/rclcpp/issues/1516>`_)
|
||||
* Fix UBSAN warnings in any_subscription_callback. (`#1551 <https://github.com/ros2/rclcpp/issues/1551>`_)
|
||||
* Fix runtime error: reference binding to null pointer of type (`#1547 <https://github.com/ros2/rclcpp/issues/1547>`_)
|
||||
* Contributors: Andrea Sorbini, Chris Lalancette, Colin MacKenzie, Ivan Santiago Paunovic, Jacob Perron, Steven! Ragnarök, bpwilcox, tomoya
|
||||
|
||||
6.3.1 (2021-02-08)
|
||||
------------------
|
||||
* Reference test resources directly from source tree (`#1543 <https://github.com/ros2/rclcpp/issues/1543>`_)
|
||||
* clear statistics after window reset (`#1531 <https://github.com/ros2/rclcpp/issues/1531>`_) (`#1535 <https://github.com/ros2/rclcpp/issues/1535>`_)
|
||||
* Fix a minor string error in the topic_statistics test. (`#1541 <https://github.com/ros2/rclcpp/issues/1541>`_)
|
||||
* Avoid `Resource deadlock avoided` if use intra_process_comms (`#1530 <https://github.com/ros2/rclcpp/issues/1530>`_)
|
||||
* Avoid an object copy in parameter_value.cpp. (`#1538 <https://github.com/ros2/rclcpp/issues/1538>`_)
|
||||
* Assert that the publisher_list size is 1. (`#1537 <https://github.com/ros2/rclcpp/issues/1537>`_)
|
||||
* Don't access objects after they have been std::move (`#1536 <https://github.com/ros2/rclcpp/issues/1536>`_)
|
||||
* Update for checking correct variable (`#1534 <https://github.com/ros2/rclcpp/issues/1534>`_)
|
||||
* Destroy msg extracted from LoanedMessage. (`#1305 <https://github.com/ros2/rclcpp/issues/1305>`_)
|
||||
* Contributors: Chen Lihui, Chris Lalancette, Ivan Santiago Paunovic, Miaofei Mei, Scott K Logan, William Woodall, hsgwa
|
||||
|
||||
6.3.0 (2021-01-25)
|
||||
------------------
|
||||
* Add instrumentation for linking a timer to a node (`#1500 <https://github.com/ros2/rclcpp/issues/1500>`_)
|
||||
* Fix error when using IPC with StaticSingleThreadExecutor (`#1520 <https://github.com/ros2/rclcpp/issues/1520>`_)
|
||||
* Change to using unique_ptrs for DummyExecutor. (`#1517 <https://github.com/ros2/rclcpp/issues/1517>`_)
|
||||
* Allow reconfiguring 'clock' topic qos (`#1512 <https://github.com/ros2/rclcpp/issues/1512>`_)
|
||||
* Allow to add/remove nodes thread safely in rclcpp::Executor (`#1505 <https://github.com/ros2/rclcpp/issues/1505>`_)
|
||||
* Call rclcpp::shutdown in test_node for clean shutdown on Windows (`#1515 <https://github.com/ros2/rclcpp/issues/1515>`_)
|
||||
* Reapply "Add get_logging_directory method to rclcpp::Logger (`#1509 <https://github.com/ros2/rclcpp/issues/1509>`_)" (`#1513 <https://github.com/ros2/rclcpp/issues/1513>`_)
|
||||
* use describe_parameters of parameter client for test (`#1499 <https://github.com/ros2/rclcpp/issues/1499>`_)
|
||||
* Revert "Add get_logging_directory method to rclcpp::Logger (`#1509 <https://github.com/ros2/rclcpp/issues/1509>`_)" (`#1511 <https://github.com/ros2/rclcpp/issues/1511>`_)
|
||||
* Add get_logging_directory method to rclcpp::Logger (`#1509 <https://github.com/ros2/rclcpp/issues/1509>`_)
|
||||
* Contributors: Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, eboasson, mauropasse, tomoya
|
||||
|
||||
6.2.0 (2021-01-08)
|
||||
------------------
|
||||
* Better documentation for the QoS class (`#1508 <https://github.com/ros2/rclcpp/issues/1508>`_)
|
||||
* Modify excluding callback duration from topic statistics (`#1492 <https://github.com/ros2/rclcpp/issues/1492>`_)
|
||||
* Make the test of graph users more robust. (`#1504 <https://github.com/ros2/rclcpp/issues/1504>`_)
|
||||
* Make sure to wait for graph change events in test_node_graph. (`#1503 <https://github.com/ros2/rclcpp/issues/1503>`_)
|
||||
* add timeout to SyncParametersClient methods (`#1493 <https://github.com/ros2/rclcpp/issues/1493>`_)
|
||||
* Fix wrong test expectations (`#1497 <https://github.com/ros2/rclcpp/issues/1497>`_)
|
||||
* Update create_publisher/subscription documentation, clarifying when a parameters interface is required (`#1494 <https://github.com/ros2/rclcpp/issues/1494>`_)
|
||||
* Fix string literal warnings (`#1442 <https://github.com/ros2/rclcpp/issues/1442>`_)
|
||||
* support describe_parameters methods to parameter client. (`#1453 <https://github.com/ros2/rclcpp/issues/1453>`_)
|
||||
* Contributors: Audrow Nash, Chris Lalancette, Ivan Santiago Paunovic, Nikolai Morin, hsgwa, tomoya
|
||||
|
||||
6.1.0 (2020-12-10)
|
||||
------------------
|
||||
* Add getters to rclcpp::qos and rclcpp::Policy enum classes (`#1467 <https://github.com/ros2/rclcpp/issues/1467>`_)
|
||||
* Change nullptr checks to use ASSERT_TRUE. (`#1486 <https://github.com/ros2/rclcpp/issues/1486>`_)
|
||||
* Adjust logic around finding and erasing guard_condition (`#1474 <https://github.com/ros2/rclcpp/issues/1474>`_)
|
||||
* Update QDs to QL 1 (`#1477 <https://github.com/ros2/rclcpp/issues/1477>`_)
|
||||
* Add performance tests for parameter transport (`#1463 <https://github.com/ros2/rclcpp/issues/1463>`_)
|
||||
* Contributors: Chris Lalancette, Ivan Santiago Paunovic, Scott K Logan, Stephen Brawner
|
||||
|
||||
6.0.0 (2020-11-18)
|
||||
------------------
|
||||
* Move ownership of shutdown_guard_condition to executors/graph_listener (`#1404 <https://github.com/ros2/rclcpp/issues/1404>`_)
|
||||
* Add options to automatically declare qos parameters when creating a publisher/subscription (`#1465 <https://github.com/ros2/rclcpp/issues/1465>`_)
|
||||
* Add `take_data` to `Waitable` and `data` to `AnyExecutable` (`#1241 <https://github.com/ros2/rclcpp/issues/1241>`_)
|
||||
* Add benchmarks for node parameters interface (`#1444 <https://github.com/ros2/rclcpp/issues/1444>`_)
|
||||
* Remove allocation from executor::remove_node() (`#1448 <https://github.com/ros2/rclcpp/issues/1448>`_)
|
||||
* Fix test crashes on CentOS 7 (`#1449 <https://github.com/ros2/rclcpp/issues/1449>`_)
|
||||
* Bump rclcpp packages to Quality Level 2 (`#1445 <https://github.com/ros2/rclcpp/issues/1445>`_)
|
||||
* Update QD to QL 1 (`#1480 <https://github.com/ros2/rclcpp/issues/1480>`_)
|
||||
* Add performance tests for parameter transport (`#1470 <https://github.com/ros2/rclcpp/issues/1470>`_)
|
||||
* Add benchmarks for node parameters interface (`#1470 <https://github.com/ros2/rclcpp/issues/1470>`_)
|
||||
* Fix NodeOptions copy constructor (`#1376 <https://github.com/ros2/rclcpp/issues/1376>`_) (`#1451 <https://github.com/ros2/rclcpp/issues/1451>`_)
|
||||
* Avoid reference cycle to fix memory leak (`#1301 <https://github.com/ros2/rclcpp/issues/1301>`_) (`#1450 <https://github.com/ros2/rclcpp/issues/1450>`_)
|
||||
* Bump rclcpp packages to Quality Level 2 (`#1445 <https://github.com/ros2/rclcpp/issues/1445>`_) (`#1446 <https://github.com/ros2/rclcpp/issues/1446>`_)
|
||||
* Added executor benchmark tests (`#1413 <https://github.com/ros2/rclcpp/issues/1413>`_)
|
||||
* Add fully-qualified namespace to WeakCallbackGroupsToNodesMap (`#1435 <https://github.com/ros2/rclcpp/issues/1435>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Audrow Nash, Chris Lalancette, Ivan Santiago Paunovic, Louise Poubel, Scott K Logan, brawner
|
||||
|
||||
5.1.0 (2020-11-02)
|
||||
------------------
|
||||
* Deprecate Duration(rcl_duration_value_t) in favor of static Duration::from_nanoseconds(rcl_duration_value_t) (`#1432 <https://github.com/ros2/rclcpp/issues/1432>`_)
|
||||
* Avoid parsing arguments twice in `rclcpp::init_and_remove_ros_arguments` (`#1415 <https://github.com/ros2/rclcpp/issues/1415>`_)
|
||||
* Add service and client benchmarks (`#1425 <https://github.com/ros2/rclcpp/issues/1425>`_)
|
||||
* Set CMakeLists to only use default rmw for benchmarks (`#1427 <https://github.com/ros2/rclcpp/issues/1427>`_)
|
||||
* Update tracetools' QL in rclcpp's QD (`#1428 <https://github.com/ros2/rclcpp/issues/1428>`_)
|
||||
* Add missing locking to the rclcpp_action::ServerBase. (`#1421 <https://github.com/ros2/rclcpp/issues/1421>`_)
|
||||
* Initial benchmark tests for rclcpp::init/shutdown create/destroy node (`#1411 <https://github.com/ros2/rclcpp/issues/1411>`_)
|
||||
* Refactor test CMakeLists in prep for benchmarks (`#1422 <https://github.com/ros2/rclcpp/issues/1422>`_)
|
||||
* Add methods in topic and service interface to resolve a name (`#1410 <https://github.com/ros2/rclcpp/issues/1410>`_)
|
||||
* Update deprecated gtest macros (`#1370 <https://github.com/ros2/rclcpp/issues/1370>`_)
|
||||
* Use global namespace for parameter events subscription topic (`#1257 <https://github.com/ros2/rclcpp/issues/1257>`_) (`#1261 <https://github.com/ros2/rclcpp/issues/1261>`_)
|
||||
* Refactor test CMakeLists.txt (`#1422 <https://github.com/ros2/rclcpp/issues/1422>`_) and moving rosidl_generate_interfaces_call (`#1424 <https://github.com/ros2/rclcpp/issues/1424>`_) (`#1437 <https://github.com/ros2/rclcpp/issues/1437>`_)
|
||||
* Update tracetools' QL in rclcpp's QD (`#1428 <https://github.com/ros2/rclcpp/issues/1428>`_) (`#1430 <https://github.com/ros2/rclcpp/issues/1430>`_)
|
||||
* Add coverage statement (`#1367 <https://github.com/ros2/rclcpp/issues/1367>`_)
|
||||
* Update tracetools' QL to 2 in rclcpp's QD (`#1187 <https://github.com/ros2/rclcpp/issues/1187>`_)
|
||||
* Fix reference to rclcpp in its QD (`#1161 <https://github.com/ros2/rclcpp/issues/1161>`_)
|
||||
* Clear members for StaticExecutorEntitiesCollector to avoid shared_ptr dependency (`#1303 <https://github.com/ros2/rclcpp/issues/1303>`_)
|
||||
* Increase test timeouts of slow running tests with rmw_connext_cpp (`#1400 <https://github.com/ros2/rclcpp/issues/1400>`_)
|
||||
* Avoid self dependency that not destoryed (`#1301 <https://github.com/ros2/rclcpp/issues/1301>`_)
|
||||
* Update maintainers (`#1384 <https://github.com/ros2/rclcpp/issues/1384>`_)
|
||||
* Add clock qos to node options (`#1375 <https://github.com/ros2/rclcpp/issues/1375>`_)
|
||||
* Fix NodeOptions copy constructor (`#1376 <https://github.com/ros2/rclcpp/issues/1376>`_)
|
||||
* Make sure to clean the external client/service handle. (`#1296 <https://github.com/ros2/rclcpp/issues/1296>`_)
|
||||
* Increase coverage of WaitSetTemplate (`#1368 <https://github.com/ros2/rclcpp/issues/1368>`_)
|
||||
* Increase coverage of guard_condition.cpp to 100% (`#1369 <https://github.com/ros2/rclcpp/issues/1369>`_)
|
||||
* Add coverage statement (`#1367 <https://github.com/ros2/rclcpp/issues/1367>`_)
|
||||
* Tests for LoanedMessage with mocked loaned message publisher (`#1366 <https://github.com/ros2/rclcpp/issues/1366>`_)
|
||||
* Add unit tests for qos and qos_event files (`#1352 <https://github.com/ros2/rclcpp/issues/1352>`_)
|
||||
* Finish coverage of publisher API (`#1365 <https://github.com/ros2/rclcpp/issues/1365>`_)
|
||||
* Finish API coverage on executors. (`#1364 <https://github.com/ros2/rclcpp/issues/1364>`_)
|
||||
* Finish API coverage on executors (`#1364 <https://github.com/ros2/rclcpp/issues/1364>`_)
|
||||
* Only exchange intra_process waitable if nonnull (`#1317 <https://github.com/ros2/rclcpp/issues/1317>`_)
|
||||
* Add test for ParameterService (`#1355 <https://github.com/ros2/rclcpp/issues/1355>`_)
|
||||
* Add time API coverage tests (`#1347 <https://github.com/ros2/rclcpp/issues/1347>`_)
|
||||
* Add timer coverage tests (`#1363 <https://github.com/ros2/rclcpp/issues/1363>`_)
|
||||
* Add in additional tests for parameter_client.cpp coverage.
|
||||
* Minor fixes to the parameter_service.cpp file.
|
||||
* reset rcl_context shared_ptr after calling rcl_init sucessfully (`#1357 <https://github.com/ros2/rclcpp/issues/1357>`_)
|
||||
* Improved test publisher - zero qos history depth value exception (`#1360 <https://github.com/ros2/rclcpp/issues/1360>`_)
|
||||
* Improve test publisher - zero qos history depth value exception (`#1360 <https://github.com/ros2/rclcpp/issues/1360>`_)
|
||||
* Covered resolve_use_intra_process (`#1359 <https://github.com/ros2/rclcpp/issues/1359>`_)
|
||||
* Improve test_subscription_options (`#1358 <https://github.com/ros2/rclcpp/issues/1358>`_)
|
||||
* Add in more tests for init_options coverage. (`#1353 <https://github.com/ros2/rclcpp/issues/1353>`_)
|
||||
* Add in more tests for init_options coverage (`#1353 <https://github.com/ros2/rclcpp/issues/1353>`_)
|
||||
* Test the remaining node public API (`#1342 <https://github.com/ros2/rclcpp/issues/1342>`_)
|
||||
* Complete coverage of Parameter and ParameterValue API (`#1344 <https://github.com/ros2/rclcpp/issues/1344>`_)
|
||||
* Add in more tests for the utilities. (`#1349 <https://github.com/ros2/rclcpp/issues/1349>`_)
|
||||
* Add in two more tests for expand_topic_or_service_name. (`#1350 <https://github.com/ros2/rclcpp/issues/1350>`_)
|
||||
* Add in more tests for the utilities (`#1349 <https://github.com/ros2/rclcpp/issues/1349>`_)
|
||||
* Add in two more tests for expand_topic_or_service_name (`#1350 <https://github.com/ros2/rclcpp/issues/1350>`_)
|
||||
* Add tests for node_options API (`#1343 <https://github.com/ros2/rclcpp/issues/1343>`_)
|
||||
* Add in more coverage for expand_topic_or_service_name. (`#1346 <https://github.com/ros2/rclcpp/issues/1346>`_)
|
||||
* Test exception in spin_until_future_complete. (`#1345 <https://github.com/ros2/rclcpp/issues/1345>`_)
|
||||
* Add coverage tests graph_listener (`#1330 <https://github.com/ros2/rclcpp/issues/1330>`_)
|
||||
* Add in unit tests for the Executor class.
|
||||
* Allow mimick patching of methods with up to 9 arguments.
|
||||
* Improve the error messages in the Executor class.
|
||||
* Add executor unit tests `#1336 <https://github.com/ros2/rclcpp/issues/1336>`_ (`#1395 <https://github.com/ros2/rclcpp/issues/1395>`_)
|
||||
* Add coverage for client API (`#1329 <https://github.com/ros2/rclcpp/issues/1329>`_)
|
||||
* Increase service coverage (`#1332 <https://github.com/ros2/rclcpp/issues/1332>`_)
|
||||
* Make more of the static entity collector API private.
|
||||
* Const-ify more of the static executor.
|
||||
* Add more tests for the static single threaded executor.
|
||||
* Many more tests for the static_executor_entities_collector.
|
||||
* Get one more line of code coverage in memory_strategy.cpp
|
||||
* Bugfix when adding callback group.
|
||||
* Fix typos in comments.
|
||||
* Remove deprecated executor::FutureReturnCode APIs. (`#1327 <https://github.com/ros2/rclcpp/issues/1327>`_)
|
||||
* Add ostream test for FutureReturnCode (`#1327 <https://github.com/ros2/rclcpp/issues/1327>`_) (`#1393 <https://github.com/ros2/rclcpp/issues/1393>`_)
|
||||
* Increase coverage of publisher/subscription API (`#1325 <https://github.com/ros2/rclcpp/issues/1325>`_)
|
||||
* Not finalize guard condition while destructing SubscriptionIntraProcess (`#1307 <https://github.com/ros2/rclcpp/issues/1307>`_)
|
||||
* Expose qos setting for /rosout (`#1247 <https://github.com/ros2/rclcpp/issues/1247>`_)
|
||||
* Add coverage for missing API (except executors) (`#1326 <https://github.com/ros2/rclcpp/issues/1326>`_)
|
||||
* Include topic name in QoS mismatch warning messages (`#1286 <https://github.com/ros2/rclcpp/issues/1286>`_)
|
||||
* Add coverage tests context functions (`#1321 <https://github.com/ros2/rclcpp/issues/1321>`_)
|
||||
* Increase coverage of node_interfaces, including with mocking rcl errors (`#1322 <https://github.com/ros2/rclcpp/issues/1322>`_)
|
||||
* Contributors: Ada-King, Alejandro Hernández Cordero, Audrow Nash, Barry Xu, Chen Lihui, Chris Lalancette, Christophe Bedard, Ivan Santiago Paunovic, Jorge Perez, Morgan Quigley, brawner
|
||||
|
||||
5.0.0 (2020-09-18)
|
||||
------------------
|
||||
* Make node_graph::count_graph_users() const (`#1320 <https://github.com/ros2/rclcpp/issues/1320>`_)
|
||||
* Add coverage for wait_set_policies (`#1316 <https://github.com/ros2/rclcpp/issues/1316>`_)
|
||||
* Only exchange intra_process waitable if nonnull (`#1317 <https://github.com/ros2/rclcpp/issues/1317>`_)
|
||||
* Check waitable for nullptr during constructor (`#1315 <https://github.com/ros2/rclcpp/issues/1315>`_)
|
||||
* Call vector.erase with end iterator overload (`#1314 <https://github.com/ros2/rclcpp/issues/1314>`_)
|
||||
* Use best effort, keep last, history depth 1 QoS Profile for '/clock' subscriptions (`#1312 <https://github.com/ros2/rclcpp/issues/1312>`_)
|
||||
* Add tests type_support module (`#1308 <https://github.com/ros2/rclcpp/issues/1308>`_)
|
||||
* Replace std_msgs with test_msgs in executors test (`#1310 <https://github.com/ros2/rclcpp/issues/1310>`_)
|
||||
* Add set_level for rclcpp::Logger (`#1284 <https://github.com/ros2/rclcpp/issues/1284>`_)
|
||||
* Remove unused private function (rclcpp::Node and rclcpp_lifecycle::Node) (`#1294 <https://github.com/ros2/rclcpp/issues/1294>`_)
|
||||
* Adding tests basic getters (`#1291 <https://github.com/ros2/rclcpp/issues/1291>`_)
|
||||
* Adding callback groups in executor (`#1218 <https://github.com/ros2/rclcpp/issues/1218>`_)
|
||||
* Refactor Subscription Topic Statistics Tests (`#1281 <https://github.com/ros2/rclcpp/issues/1281>`_)
|
||||
* Add operator!= for duration (`#1236 <https://github.com/ros2/rclcpp/issues/1236>`_)
|
||||
* Fix clock thread issue (`#1266 <https://github.com/ros2/rclcpp/issues/1266>`_) (`#1267 <https://github.com/ros2/rclcpp/issues/1267>`_)
|
||||
* Fix topic stats test, wait for more messages, only check the ones with samples (`#1274 <https://github.com/ros2/rclcpp/issues/1274>`_)
|
||||
* Add get_domain_id method to rclcpp::Context (`#1271 <https://github.com/ros2/rclcpp/issues/1271>`_)
|
||||
* Fixes for unit tests that fail under cyclonedds (`#1270 <https://github.com/ros2/rclcpp/issues/1270>`_)
|
||||
* initialize_logging\_ should be copied (`#1272 <https://github.com/ros2/rclcpp/issues/1272>`_)
|
||||
* Use static_cast instead of C-style cast for instrumentation (`#1263 <https://github.com/ros2/rclcpp/issues/1263>`_)
|
||||
* Make parameter clients use template constructors (`#1249 <https://github.com/ros2/rclcpp/issues/1249>`_)
|
||||
* Ability to configure domain_id via InitOptions. (`#1165 <https://github.com/ros2/rclcpp/issues/1165>`_)
|
||||
* Ability to configure domain_id via InitOptions (`#1165 <https://github.com/ros2/rclcpp/issues/1165>`_)
|
||||
* Simplify and fix allocator memory strategy unit test for connext (`#1252 <https://github.com/ros2/rclcpp/issues/1252>`_)
|
||||
* Use global namespace for parameter events subscription topic (`#1257 <https://github.com/ros2/rclcpp/issues/1257>`_)
|
||||
* Increase timeouts for connext for long tests (`#1253 <https://github.com/ros2/rclcpp/issues/1253>`_)
|
||||
* Adjust test_static_executor_entities_collector for rmw_connext_cpp (`#1251 <https://github.com/ros2/rclcpp/issues/1251>`_)
|
||||
* Fix failing test with Connext since it doesn't wait for discovery (`#1246 <https://github.com/ros2/rclcpp/issues/1246>`_)
|
||||
* Fix node graph test with Connext and CycloneDDS returning actual data (`#1245 <https://github.com/ros2/rclcpp/issues/1245>`_)
|
||||
* Warn about unused result of add_on_set_parameters_callback (`#1238 <https://github.com/ros2/rclcpp/issues/1238>`_)
|
||||
* Unittests for memory strategy files, except allocator_memory_strategy (`#1189 <https://github.com/ros2/rclcpp/issues/1189>`_)
|
||||
* EXPECT_THROW_EQ and ASSERT_THROW_EQ macros for unittests (`#1232 <https://github.com/ros2/rclcpp/issues/1232>`_)
|
||||
* Parameterize test executors for all executor types (`#1222 <https://github.com/ros2/rclcpp/issues/1222>`_) (`#1386 <https://github.com/ros2/rclcpp/issues/1386>`_)
|
||||
* Derive and throw exception in spin_some spin_all for StaticSingleThreadedExecutor (`#1385 <https://github.com/ros2/rclcpp/issues/1385>`_)
|
||||
* Add unit test for static_executor_entities_collector (`#1221 <https://github.com/ros2/rclcpp/issues/1221>`_)
|
||||
* Parameterize test executors for all executor types (`#1222 <https://github.com/ros2/rclcpp/issues/1222>`_)
|
||||
* Unit tests for allocator_memory_strategy.cpp part 2 (`#1198 <https://github.com/ros2/rclcpp/issues/1198>`_)
|
||||
* Unit tests for allocator_memory_strategy.hpp (`#1197 <https://github.com/ros2/rclcpp/issues/1197>`_)
|
||||
* Derive and throw exception in spin_some spin_all for StaticSingleThreadedExecutor (`#1220 <https://github.com/ros2/rclcpp/issues/1220>`_)
|
||||
* Make ring buffer thread-safe (`#1213 <https://github.com/ros2/rclcpp/issues/1213>`_)
|
||||
* Add missing RCLCPP_PUBLIC to ~StaticExecutorEntitiesCollector (`#1227 <https://github.com/ros2/rclcpp/issues/1227>`_)
|
||||
* Document graph functions don't apply remap rules (`#1225 <https://github.com/ros2/rclcpp/issues/1225>`_)
|
||||
* Remove recreation of entities_collector (`#1217 <https://github.com/ros2/rclcpp/issues/1217>`_)
|
||||
* Contributors: Audrow Nash, Chen Lihui, Christophe Bedard, Daisuke Sato, Devin Bonnie, Dirk Thomas, Ivan Santiago Paunovic, Jacob Perron, Jannik Abbenseth, Jorge Perez, Pedro Pena, Shane Loretz, Stephen Brawner, Tomoya Fujita
|
||||
|
||||
4.0.0 (2020-07-09)
|
||||
------------------
|
||||
* Fix rclcpp::NodeOptions::operator= (`#1211 <https://github.com/ros2/rclcpp/issues/1211>`_)
|
||||
* Link against thread library where necessary (`#1210 <https://github.com/ros2/rclcpp/issues/1210>`_)
|
||||
* Unit tests for node interfaces (`#1202 <https://github.com/ros2/rclcpp/issues/1202>`_)
|
||||
* Remove usage of domain id in node options (`#1205 <https://github.com/ros2/rclcpp/issues/1205>`_)
|
||||
* Remove deprecated set_on_parameters_set_callback function (`#1199 <https://github.com/ros2/rclcpp/issues/1199>`_)
|
||||
* Fix conversion of negative durations to messages (`#1188 <https://github.com/ros2/rclcpp/issues/1188>`_)
|
||||
* Fix implementation of NodeOptions::use_global_arguments() (`#1176 <https://github.com/ros2/rclcpp/issues/1176>`_)
|
||||
* Bump to QD to level 3 and fixed links (`#1158 <https://github.com/ros2/rclcpp/issues/1158>`_)
|
||||
* Fix pub/sub count API tests (`#1203 <https://github.com/ros2/rclcpp/issues/1203>`_)
|
||||
* Update tracetools' QL to 2 in rclcpp's QD (`#1187 <https://github.com/ros2/rclcpp/issues/1187>`_)
|
||||
* Fix exception message on rcl_clock_init (`#1182 <https://github.com/ros2/rclcpp/issues/1182>`_)
|
||||
* Throw exception if rcl_timer_init fails (`#1179 <https://github.com/ros2/rclcpp/issues/1179>`_)
|
||||
* Unit tests for some header-only functions/classes (`#1181 <https://github.com/ros2/rclcpp/issues/1181>`_)
|
||||
* Callback should be perfectly-forwarded (`#1183 <https://github.com/ros2/rclcpp/issues/1183>`_)
|
||||
* Add unit tests for logging functionality (`#1184 <https://github.com/ros2/rclcpp/issues/1184>`_)
|
||||
* Add create_publisher include to create_subscription (`#1180 <https://github.com/ros2/rclcpp/issues/1180>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Christophe Bedard, Claire Wang, Dirk Thomas, Ivan Santiago Paunovic, Johannes Meyer, Michel Hidalgo, Stephen Brawner, tomoya
|
||||
|
||||
3.0.0 (2020-06-18)
|
||||
------------------
|
||||
* Fix rclcpp::NodeOptions::operator= (`#1211 <https://github.com/ros2/rclcpp/issues/1211>`_)
|
||||
* Check period duration in create_wall_timer (`#1178 <https://github.com/ros2/rclcpp/issues/1178>`_)
|
||||
* Fix get_node_time_source_interface() docstring (`#988 <https://github.com/ros2/rclcpp/issues/988>`_)
|
||||
* Add message lost subscription event (`#1164 <https://github.com/ros2/rclcpp/issues/1164>`_)
|
||||
* Add spin_all method to Executor (`#1156 <https://github.com/ros2/rclcpp/issues/1156>`_)
|
||||
* Reorganize test directory and split CMakeLists.txt (`#1173 <https://github.com/ros2/rclcpp/issues/1173>`_)
|
||||
* Throw exception if rcl_timer_init fails (`#1179 <https://github.com/ros2/rclcpp/issues/1179>`_)
|
||||
* Remove finalization of guard_condition from GraphListener::__shutdown() (`#1401 <https://github.com/ros2/rclcpp/issues/1401>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Chen Lihui, Chris Lalancette, Christophe Bedard, Devin Bonnie, Dirk Thomas, Jacob Perron, Jorge Perez, Louise Poubel, Michel Hidalgo, Scott K Logan, Stephen Brawner, tomoya
|
||||
|
||||
2.2.0 (2020-10-07)
|
||||
------------------
|
||||
* Fix implementation of NodeOptions::use_global_arguments() (`#1176 <https://github.com/ros2/rclcpp/issues/1176>`_) (`#1372 <https://github.com/ros2/rclcpp/issues/1372>`_)
|
||||
* Fix conversion of negative durations to messages (`#1188 <https://github.com/ros2/rclcpp/issues/1188>`_) (`#1371 <https://github.com/ros2/rclcpp/issues/1371>`_)
|
||||
* Call vector.erase with end iterator overload (`#1314 <https://github.com/ros2/rclcpp/issues/1314>`_) (`#1380 <https://github.com/ros2/rclcpp/issues/1380>`_)
|
||||
* Check waitable for nullptr during constructor (`#1315 <https://github.com/ros2/rclcpp/issues/1315>`_) (`#1379 <https://github.com/ros2/rclcpp/issues/1379>`_)
|
||||
* Fix pub/sub count API tests. (`#1203 <https://github.com/ros2/rclcpp/issues/1203>`_) (`#1319 <https://github.com/ros2/rclcpp/issues/1319>`_)
|
||||
* Reorganize test directory and split CMakeLists.txt (`#1173 <https://github.com/ros2/rclcpp/issues/1173>`_) (`#1262 <https://github.com/ros2/rclcpp/issues/1262>`_)
|
||||
* Add operator!= for duration (`#1236 <https://github.com/ros2/rclcpp/issues/1236>`_) (`#1278 <https://github.com/ros2/rclcpp/issues/1278>`_)
|
||||
* Contributors: Ivan Santiago Paunovic, Jacob Perron, Jannik Abbenseth, Johannes Meyer, Michel Hidalgo, Stephen Brawner
|
||||
|
||||
2.1.0 (2020-08-03)
|
||||
------------------
|
||||
* Warn about unused result of add_on_set_parameters_callback (`#1238 <https://github.com/ros2/rclcpp/issues/1238>`_) (`#1244 <https://github.com/ros2/rclcpp/issues/1244>`_)
|
||||
* Add missing RCLCPP_PUBLIC to ~StaticExecutorEntitiesCollector (`#1227 <https://github.com/ros2/rclcpp/issues/1227>`_) (`#1228 <https://github.com/ros2/rclcpp/issues/1228>`_)
|
||||
* Remove recreation of entities_collector (`#1217 <https://github.com/ros2/rclcpp/issues/1217>`_) (`#1224 <https://github.com/ros2/rclcpp/issues/1224>`_)
|
||||
* Contributors: Jacob Perron, brawner
|
||||
|
||||
2.0.2 (2020-07-07)
|
||||
------------------
|
||||
* Link against thread library where necessary (`#1210 <https://github.com/ros2/rclcpp/issues/1210>`_) (`#1214 <https://github.com/ros2/rclcpp/issues/1214>`_)
|
||||
* Fix exception message on rcl_clock_init (`#1182 <https://github.com/ros2/rclcpp/issues/1182>`_) (`#1193 <https://github.com/ros2/rclcpp/issues/1193>`_)
|
||||
* Contributors: Dirk Thomas, tomoya
|
||||
|
||||
2.0.1 (2020-06-23)
|
||||
------------------
|
||||
* Add create_publisher include to create_subscription (`#1180 <https://github.com/ros2/rclcpp/issues/1180>`_) (`#1192 <https://github.com/ros2/rclcpp/issues/1192>`_)
|
||||
* Fix get_node_time_source_interface() docstring (`#988 <https://github.com/ros2/rclcpp/issues/988>`_) (`#1185 <https://github.com/ros2/rclcpp/issues/1185>`_)
|
||||
* Fixed doxygen warnings (`#1163 <https://github.com/ros2/rclcpp/issues/1163>`_) (`#1191 <https://github.com/ros2/rclcpp/issues/1191>`_)
|
||||
* Check if context is valid when looping in spin_some (`#1167 <https://github.com/ros2/rclcpp/issues/1167>`_)
|
||||
* Add check for invalid topic statistics publish period (`#1151 <https://github.com/ros2/rclcpp/issues/1151>`_)
|
||||
* Fix spin_until_future_complete: check spinning value (`#1023 <https://github.com/ros2/rclcpp/issues/1023>`_)
|
||||
* Fix doxygen warnings (`#1163 <https://github.com/ros2/rclcpp/issues/1163>`_)
|
||||
* Fix reference to rclcpp in its Quality declaration (`#1161 <https://github.com/ros2/rclcpp/issues/1161>`_)
|
||||
* Allow spin_until_future_complete to accept any future like object (`#1113 <https://github.com/ros2/rclcpp/issues/1113>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Christophe Bedard, Devin Bonnie, Dirk Thomas, DongheeYe, Ivan Santiago Paunovic, Jacob Perron, Sarthak Mittal, brawner, tomoya
|
||||
Make Executor::spin_once_impl private before backporting, to avoid API compatibility issues
|
||||
* Add check for invalid topic statistics publish period (`#1151 <https://github.com/ros2/rclcpp/issues/1151>`_) (`#1172 <https://github.com/ros2/rclcpp/issues/1172>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Devin Bonnie, DongheeYe, Ivan Santiago Paunovic, Jacob Perron, Stephen Brawner
|
||||
|
||||
2.0.0 (2020-06-01)
|
||||
------------------
|
||||
|
||||
@@ -5,7 +5,6 @@ project(rclcpp)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_package(ament_cmake_ros REQUIRED)
|
||||
find_package(ament_index_cpp REQUIRED)
|
||||
find_package(builtin_interfaces REQUIRED)
|
||||
find_package(libstatistics_collector REQUIRED)
|
||||
find_package(rcl REQUIRED)
|
||||
@@ -21,10 +20,9 @@ find_package(rosidl_typesupport_cpp REQUIRED)
|
||||
find_package(statistics_msgs REQUIRED)
|
||||
find_package(tracetools REQUIRED)
|
||||
|
||||
# TODO(wjwwood): remove this when gtest can build on its own, when using target_compile_features()
|
||||
# Default to C++17
|
||||
# Default to C++14
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
endif()
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# About -Wno-sign-conversion: With Clang, -Wconversion implies -Wsign-conversion. There are a number of
|
||||
@@ -42,7 +40,6 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/context.cpp
|
||||
src/rclcpp/contexts/default_context.cpp
|
||||
src/rclcpp/detail/mutex_two_priorities.cpp
|
||||
src/rclcpp/detail/resolve_parameter_overrides.cpp
|
||||
src/rclcpp/detail/rmw_implementation_specific_payload.cpp
|
||||
src/rclcpp/detail/rmw_implementation_specific_publisher_payload.cpp
|
||||
src/rclcpp/detail/rmw_implementation_specific_subscription_payload.cpp
|
||||
@@ -53,14 +50,12 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/executable_list.cpp
|
||||
src/rclcpp/executor.cpp
|
||||
src/rclcpp/executors.cpp
|
||||
src/rclcpp/expand_topic_or_service_name.cpp
|
||||
src/rclcpp/executors/multi_threaded_executor.cpp
|
||||
src/rclcpp/executors/single_threaded_executor.cpp
|
||||
src/rclcpp/executors/static_executor_entities_collector.cpp
|
||||
src/rclcpp/executors/static_single_threaded_executor.cpp
|
||||
src/rclcpp/expand_topic_or_service_name.cpp
|
||||
src/rclcpp/future_return_code.cpp
|
||||
src/rclcpp/generic_publisher.cpp
|
||||
src/rclcpp/generic_subscription.cpp
|
||||
src/rclcpp/graph_listener.cpp
|
||||
src/rclcpp/guard_condition.cpp
|
||||
src/rclcpp/init_options.cpp
|
||||
@@ -70,8 +65,8 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/memory_strategies.cpp
|
||||
src/rclcpp/memory_strategy.cpp
|
||||
src/rclcpp/message_info.cpp
|
||||
src/rclcpp/network_flow_endpoint.cpp
|
||||
src/rclcpp/node.cpp
|
||||
src/rclcpp/node_options.cpp
|
||||
src/rclcpp/node_interfaces/node_base.cpp
|
||||
src/rclcpp/node_interfaces/node_clock.cpp
|
||||
src/rclcpp/node_interfaces/node_graph.cpp
|
||||
@@ -82,18 +77,15 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/node_interfaces/node_timers.cpp
|
||||
src/rclcpp/node_interfaces/node_topics.cpp
|
||||
src/rclcpp/node_interfaces/node_waitables.cpp
|
||||
src/rclcpp/node_options.cpp
|
||||
src/rclcpp/parameter.cpp
|
||||
src/rclcpp/parameter_value.cpp
|
||||
src/rclcpp/parameter_client.cpp
|
||||
src/rclcpp/parameter_event_handler.cpp
|
||||
src/rclcpp/parameter_events_filter.cpp
|
||||
src/rclcpp/parameter_map.cpp
|
||||
src/rclcpp/parameter_service.cpp
|
||||
src/rclcpp/parameter_value.cpp
|
||||
src/rclcpp/publisher_base.cpp
|
||||
src/rclcpp/qos.cpp
|
||||
src/rclcpp/qos_event.cpp
|
||||
src/rclcpp/qos_overriding_options.cpp
|
||||
src/rclcpp/serialization.cpp
|
||||
src/rclcpp/serialized_message.cpp
|
||||
src/rclcpp/service.cpp
|
||||
@@ -104,7 +96,6 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/time_source.cpp
|
||||
src/rclcpp/timer.cpp
|
||||
src/rclcpp/type_support.cpp
|
||||
src/rclcpp/typesupport_helpers.cpp
|
||||
src/rclcpp/utilities.cpp
|
||||
src/rclcpp/wait_set_policies/detail/write_preferring_read_write_lock.cpp
|
||||
src/rclcpp/waitable.cpp
|
||||
@@ -176,12 +167,8 @@ foreach(interface_file ${interface_files})
|
||||
include/rclcpp/node_interfaces/get_${interface_name}.hpp)
|
||||
endforeach()
|
||||
|
||||
add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS})
|
||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)
|
||||
# TODO(wjwwood): address all deprecation warnings and then remove this
|
||||
if(WIN32)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC "_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS")
|
||||
endif()
|
||||
add_library(${PROJECT_NAME}
|
||||
${${PROJECT_NAME}_SRCS})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||
@@ -189,7 +176,6 @@ target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
target_link_libraries(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT})
|
||||
# specific order: dependents before dependencies
|
||||
ament_target_dependencies(${PROJECT_NAME}
|
||||
"ament_index_cpp"
|
||||
"libstatistics_collector"
|
||||
"rcl"
|
||||
"rcl_yaml_param_parser"
|
||||
@@ -220,7 +206,6 @@ ament_export_include_directories(include)
|
||||
ament_export_libraries(${PROJECT_NAME})
|
||||
ament_export_targets(${PROJECT_NAME})
|
||||
|
||||
ament_export_dependencies(ament_index_cpp)
|
||||
ament_export_dependencies(libstatistics_collector)
|
||||
ament_export_dependencies(rcl)
|
||||
ament_export_dependencies(rcpputils)
|
||||
@@ -247,8 +232,3 @@ install(
|
||||
DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/
|
||||
DESTINATION include
|
||||
)
|
||||
|
||||
if(TEST cppcheck)
|
||||
# must set the property after ament_package()
|
||||
set_tests_properties(cppcheck PROPERTIES TIMEOUT 500)
|
||||
endif()
|
||||
|
||||
@@ -10,7 +10,7 @@ Below are the rationales, notes, and caveats for this claim, organized by each r
|
||||
|
||||
### Version Scheme [1.i]
|
||||
|
||||
`rclcpp` uses `semver` according to the recommendation for ROS Core packages in the [ROS 2 Developer Guide](https://docs.ros.org/en/rolling/Contributing/Developer-Guide.html#versioning).
|
||||
`rclcpp` uses `semver` according to the recommendation for ROS Core packages in the [ROS 2 Developer Guide](https://docs.ros.org/en/foxy/Contributing/Developer-Guide.html#versioning).
|
||||
|
||||
### Version Stability [1.ii]
|
||||
|
||||
@@ -39,11 +39,11 @@ Headers under the folder `detail` are not considered part of the public API and
|
||||
|
||||
## Change Control Process [2]
|
||||
|
||||
`rclcpp` follows the recommended guidelines for ROS Core packages in the [ROS 2 Developer Guide](https://docs.ros.org/en/rolling/Contributing/Developer-Guide.html#change-control-process).
|
||||
`rclcpp` follows the recommended guidelines for ROS Core packages in the [ROS 2 Developer Guide](https://docs.ros.org/en/foxy/Contributing/Developer-Guide.html#change-control-process).
|
||||
|
||||
### Change Requests [2.i]
|
||||
|
||||
All changes will occur through a pull request, check [ROS 2 Developer Guide](https://docs.ros.org/en/rolling/Contributing/Developer-Guide.html#change-control-process) for additional information.
|
||||
All changes will occur through a pull request, check [ROS 2 Developer Guide](https://docs.ros.org/en/foxy/Contributing/Developer-Guide.html#change-control-process) for additional information.
|
||||
|
||||
### Contributor Origin [2.ii]
|
||||
|
||||
@@ -51,18 +51,17 @@ This package uses DCO as its confirmation of contributor origin policy. More inf
|
||||
|
||||
### Peer Review Policy [2.iii]
|
||||
|
||||
All pull requests will be peer-reviewed, check [ROS 2 Developer Guide](https://docs.ros.org/en/rolling/Contributing/Developer-Guide.html#change-control-process) for additional information.
|
||||
All pull requests will be peer-reviewed, check [ROS 2 Developer Guide](https://docs.ros.org/en/foxy/Contributing/Developer-Guide.html#change-control-process) for additional information.
|
||||
|
||||
### Continuous Integration [2.iv]
|
||||
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://www.ros.org/reps/rep-2000.html#support-tiers)
|
||||
|
||||
Currently nightly results can be seen here:
|
||||
|
||||
* [linux-aarch64_release](https://ci.ros2.org/view/nightly/job/nightly_linux-aarch64_release/lastBuild/testReport/rclcpp/)
|
||||
* [linux_release](https://ci.ros2.org/view/nightly/job/nightly_linux_release/lastBuild/testReport/rclcpp/)
|
||||
* [mac_osx_release](https://ci.ros2.org/view/nightly/job/nightly_osx_release/lastBuild/testReport/rclcpp/)
|
||||
* [windows_release](https://ci.ros2.org/view/nightly/job/nightly_win_rel/lastBuild/testReport/rclcpp/)
|
||||
Though there are no nightly jobs for foxy outside of linux, each change is tested on ci.ros2.org.
|
||||
* [linux-aarch64](https://ci.ros2.org/job/ci_linux-aarch64)
|
||||
* [linux](https://ci.ros2.org/job/ci_linux)
|
||||
* [mac_osx](https://ci.ros2.org/job/ci_osx)
|
||||
* [windows](https://ci.ros2.org/job/ci_windows)
|
||||
|
||||
### Documentation Policy [2.v]
|
||||
|
||||
@@ -72,37 +71,36 @@ All pull requests must resolve related documentation changes before merging.
|
||||
|
||||
### Feature Documentation [3.i]
|
||||
|
||||
`rclcpp` has a [feature list](http://docs.ros2.org/latest/api/rclcpp/) and each item in the list links to the corresponding feature documentation. There is documentation for all of the features, and new features require documentation before being added.
|
||||
`rclcpp` has a [feature list](http://docs.ros2.org/foxy/api/rclcpp/) and each item in the list links to the corresponding feature documentation. There is documentation for all of the features, and new features require documentation before being added.
|
||||
|
||||
### Public API Documentation [3.ii]
|
||||
|
||||
The API is publicly available in its [ROS 2 API documentation](http://docs.ros2.org/latest/api/rclcpp/).
|
||||
The API is publicly available in its [ROS 2 API documentation](http://docs.ros2.org/foxy/api/rclcpp/).
|
||||
|
||||
### License [3.iii]
|
||||
|
||||
The license for `rclcpp` is Apache 2.0, and a summary is in each source file, the type is declared in the [`package.xml`](./package.xml) manifest file, and a full copy of the license is in the [`LICENSE`](../LICENSE) file.
|
||||
|
||||
There is an automated test which runs a linter that ensures each file has a license statement. [Here](http://build.ros2.org/view/Rpr/job/Rpr__rclcpp__ubuntu_focal_amd64/lastCompletedBuild/testReport/rclcpp/) can be found a list with the latest results of the various linters being run on the package.
|
||||
There is an automated test which runs a linter that ensures each file has a license statement. [Here](http://build.ros2.org/view/Fpr/job/Fpr__rclcpp__ubuntu_focal_amd64/lastCompletedBuild/testReport/rclcpp/) can be found a list with the latest results of the various linters being run on the package.
|
||||
|
||||
### Copyright Statements [3.iv]
|
||||
|
||||
The copyright holders each provide a statement of copyright in each source code file in `rclcpp`.
|
||||
|
||||
There is an automated test which runs a linter that ensures each file has at least one copyright statement. Latest linter result report can be seen [here](http://build.ros2.org/view/Rpr/job/Rpr__rclcpp__ubuntu_focal_amd64/lastCompletedBuild/testReport/rclcpp/copyright/).
|
||||
There is an automated test which runs a linter that ensures each file has at least one copyright statement. Latest linter result report can be seen [here](http://build.ros2.org/view/Fpr/job/Fpr__rclcpp__ubuntu_focal_amd64/lastCompletedBuild/testReport/rclcpp/copyright/).
|
||||
|
||||
## Testing [4]
|
||||
|
||||
### Feature Testing [4.i]
|
||||
|
||||
Each feature in `rclcpp` has corresponding tests which simulate typical usage, and they are located in the [`test`](https://github.com/ros2/rclcpp/tree/master/test) directory.
|
||||
Each feature in `rclcpp` has corresponding tests which simulate typical usage, and they are located in the [`test`](https://github.com/ros2/rclcpp/tree/foxy/test) directory.
|
||||
New features are required to have tests before being added.
|
||||
|
||||
Currently nightly test results can be seen here:
|
||||
|
||||
* [linux-aarch64_release](https://ci.ros2.org/view/nightly/job/nightly_linux-aarch64_release/lastBuild/testReport/rclcpp/)
|
||||
* [linux_release](https://ci.ros2.org/view/nightly/job/nightly_linux_release/lastBuild/testReport/rclcpp/)
|
||||
* [mac_osx_release](https://ci.ros2.org/view/nightly/job/nightly_osx_release/lastBuild/testReport/rclcpp/)
|
||||
* [windows_release](https://ci.ros2.org/view/nightly/job/nightly_win_rel/lastBuild/testReport/rclcpp/)
|
||||
Though there are no nightly jobs for foxy outside of linux, each change is tested on ci.ros2.org.
|
||||
* [linux-aarch64](https://ci.ros2.org/job/ci_linux-aarch64)
|
||||
* [linux](https://ci.ros2.org/job/ci_linux)
|
||||
* [mac_osx](https://ci.ros2.org/job/ci_osx)
|
||||
* [windows](https://ci.ros2.org/job/ci_windows)
|
||||
|
||||
### Public API Testing [4.ii]
|
||||
|
||||
@@ -111,7 +109,7 @@ The tests aim to cover both typical usage and corner cases, but are quantified b
|
||||
|
||||
### Coverage [4.iii]
|
||||
|
||||
`rclcpp` follows the recommendations for ROS Core packages in the [ROS 2 Developer Guide](https://docs.ros.org/en/rolling/Contributing/Developer-Guide.html#code-coverage), and opts to use line coverage instead of branch coverage.
|
||||
`rclcpp` follows the recommendations for ROS Core packages in the [ROS 2 Developer Guide](https://docs.ros.org/en/foxy/Contributing/Developer-Guide.html#code-coverage), and opts to use line coverage instead of branch coverage.
|
||||
|
||||
This includes:
|
||||
|
||||
@@ -121,31 +119,27 @@ This includes:
|
||||
|
||||
Changes are required to make a best effort to keep or increase coverage before being accepted, but decreases are allowed if properly justified and accepted by reviewers.
|
||||
|
||||
Current coverage statistics can be viewed [here](https://ci.ros2.org/job/nightly_linux_coverage/lastCompletedBuild/cobertura/src_ros2_rclcpp_rclcpp_src_rclcpp/). A description of how coverage statistics are calculated is summarized in this page ["ROS 2 Onboarding Guide"](https://docs.ros.org/en/rolling/Contributing/Developer-Guide.html#note-on-coverage-runs).
|
||||
Current coverage statistics can be viewed [here](https://ci.ros2.org/job/nightly_linux_foxy_coverage/lastCompletedBuild/cobertura/src_ros2_rclcpp_rclcpp_src_rclcpp/). A description of how coverage statistics are calculated is summarized in this page ["ROS 2 Onboarding Guide"](https://docs.ros.org/en/foxy/Contributing/Developer-Guide.html#note-on-coverage-runs).
|
||||
|
||||
`rclcpp` has a line coverage `>= 95%`, which is calculated over all directories within `rclcpp` with the exception of the `experimental` directory.
|
||||
|
||||
### Performance [4.iv]
|
||||
|
||||
`rclcpp` follows the recommendations for performance testing of C/C++ code in the [ROS 2 Developer Guide](https://docs.ros.org/en/rolling/Contributing/Developer-Guide.html#performance), and opts to do performance analysis on each release rather than each change.
|
||||
`rclcpp` follows the recommendations for performance testing of C/C++ code in the [ROS 2 Developer Guide](https://docs.ros.org/en/foxy/Contributing/Developer-Guide.html#performance), and opts to do performance analysis on each release rather than each change.
|
||||
|
||||
The performance tests of `rclcpp` are located in the [test/benchmark directory](https://github.com/ros2/rclcpp/tree/master/rclcpp/test/benchmark).
|
||||
The performance tests of `rclcpp` are located in the [test/benchmark directory](https://github.com/ros2/rclcpp/tree/foxy/rclcpp/test/benchmark).
|
||||
|
||||
System level performance benchmarks that cover features of `rclcpp` can be found at:
|
||||
* [Benchmarks](http://build.ros2.org/view/Rci/job/Rci__benchmark_ubuntu_focal_amd64/BenchmarkTable/)
|
||||
* [Performance](http://build.ros2.org/view/Rci/job/Rci__nightly-performance_ubuntu_focal_amd64/lastCompletedBuild/)
|
||||
* [Benchmarks](http://build.ros2.org/view/Fci/job/Fci__benchmark_ubuntu_focal_amd64/BenchmarkTable/)
|
||||
* [Performance](http://build.ros2.org/view/Fci/job/Fci__nightly-performance_ubuntu_focal_amd64/lastCompletedBuild/)
|
||||
|
||||
Changes that introduce regressions in performance must be adequately justified in order to be accepted and merged.
|
||||
|
||||
### Linters and Static Analysis [4.v]
|
||||
|
||||
`rclcpp` uses and passes all the ROS2 standard linters and static analysis tools for a C++ package as described in the [ROS 2 Developer Guide](https://docs.ros.org/en/rolling/Contributing/Developer-Guide.html#linters-and-static-analysis). Passing implies there are no linter/static errors when testing against CI of supported platforms.
|
||||
`rclcpp` uses and passes all the ROS2 standard linters and static analysis tools for a C++ package as described in the [ROS 2 Developer Guide](https://docs.ros.org/en/foxy/Contributing/Developer-Guide.html#linters-and-static-analysis). Passing implies there are no linter/static errors when testing against CI of supported platforms.
|
||||
|
||||
Currently nightly test results can be seen here:
|
||||
* [linux-aarch64_release](https://ci.ros2.org/view/nightly/job/nightly_linux-aarch64_release/lastBuild/testReport/rclcpp/)
|
||||
* [linux_release](https://ci.ros2.org/view/nightly/job/nightly_linux_release/lastBuild/testReport/rclcpp/)
|
||||
* [mac_osx_release](https://ci.ros2.org/view/nightly/job/nightly_osx_release/lastBuild/testReport/rclcpp/)
|
||||
* [windows_release](https://ci.ros2.org/view/nightly/job/nightly_win_rel/lastBuild/testReport/rclcpp/)
|
||||
Currently nightly test results can be seen [here](http://build.ros2.org/view/Fpr/job/Fpr__rclcpp__ubuntu_focal_amd64/lastCompletedBuild/testReport/rclcpp).
|
||||
|
||||
## Dependencies [5]
|
||||
|
||||
@@ -163,49 +157,49 @@ It also has several test dependencies, which do not affect the resulting quality
|
||||
|
||||
The `libstatistics_collector` package provides lightweight aggregation utilities to collect statistics and measure message metrics.
|
||||
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros-tooling/libstatistics_collector/tree/master/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros-tooling/libstatistics_collector/tree/foxy-devel/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rcl`
|
||||
|
||||
`rcl` a library to support implementation of language specific ROS 2 Client Libraries.
|
||||
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rcl/blob/master/rcl/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rcl/blob/foxy/rcl/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rcl_yaml_param_parser`
|
||||
|
||||
The `rcl_yaml_param_parser` package provides an API that is used to parse YAML configuration files which may be used to configure ROS and specific nodes.
|
||||
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rcl/tree/master/rcl_yaml_param_parser/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rcl/tree/foxy/rcl_yaml_param_parser/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rcpputils`
|
||||
|
||||
The `rcpputils` package provides an API which contains common utilities and data structures useful when programming in C++.
|
||||
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rcpputils/blob/master/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rcpputils/blob/foxy/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rcutils`
|
||||
|
||||
The `rcutils` package provides an API which contains common utilities and data structures useful when programming in C.
|
||||
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rcutils/blob/master/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rcutils/blob/foxy/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rmw`
|
||||
|
||||
`rmw` is the ROS 2 middleware library.
|
||||
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rmw/blob/master/rmw/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rmw/blob/foxy/rmw/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `statistics_msgs`
|
||||
|
||||
The `statistics_msgs` package contains ROS 2 message definitions for reporting statistics for topics and system resources.
|
||||
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rcl_interfaces/blob/master/statistics_msgs/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://github.com/ros2/rcl_interfaces/blob/foxy/statistics_msgs/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `tracetools`
|
||||
|
||||
The `tracetools` package provides utilities for instrumenting the code in `rclcpp` so that it may be traced for debugging and performance analysis.
|
||||
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://gitlab.com/ros-tracing/ros2_tracing/-/blob/master/tracetools/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 1**, see its [Quality Declaration document](https://gitlab.com/ros-tracing/ros2_tracing/-/blob/foxy/tracetools/QUALITY_DECLARATION.md).
|
||||
|
||||
### Direct Runtime non-ROS Dependency [5.iii]
|
||||
|
||||
@@ -215,11 +209,11 @@ It is **Quality Level 1**, see its [Quality Declaration document](https://gitlab
|
||||
|
||||
`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/)
|
||||
* [linux_release](https://ci.ros2.org/view/nightly/job/nightly_linux_release/lastBuild/rclcpp/)
|
||||
* [mac_osx_release](https://ci.ros2.org/view/nightly/job/nightly_osx_release/lastBuild/rclcpp/)
|
||||
* [windows_release](https://ci.ros2.org/view/nightly/job/nightly_win_rel/lastBuild/rclcpp/)
|
||||
Though there are no nightly jobs for foxy outside of linux, each change is tested on ci.ros2.org.
|
||||
* [linux-aarch64](https://ci.ros2.org/job/ci_linux-aarch64)
|
||||
* [linux](https://ci.ros2.org/job/ci_linux)
|
||||
* [mac_osx](https://ci.ros2.org/job/ci_osx)
|
||||
* [windows](https://ci.ros2.org/job/ci_windows)
|
||||
|
||||
## Security
|
||||
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
# Notes on statically typed parameters
|
||||
|
||||
## Introduction
|
||||
|
||||
Until ROS 2 Foxy, all parameters could change type anytime, except if the user installed a parameter callback to reject a change.
|
||||
This could generate confusing errors, for example:
|
||||
|
||||
```
|
||||
$ ros2 run demo_nodes_py listener &
|
||||
$ ros2 param set /listener use_sim_time not_a_boolean
|
||||
[ERROR] [1614712713.233733147] [listener]: use_sim_time parameter set to something besides a bool
|
||||
Set parameter successful
|
||||
$ ros2 param get /listener use_sim_time
|
||||
String value is: not_a_boolean
|
||||
```
|
||||
|
||||
For most use cases, having static parameter types is enough.
|
||||
This article documents some of the decisions that were made when implementing static parameter types enforcement in:
|
||||
|
||||
* https://github.com/ros2/rclcpp/pull/1522
|
||||
* https://github.com/ros2/rclpy/pull/683
|
||||
|
||||
## Allowing dynamically typed parameters
|
||||
|
||||
There might be some scenarios where dynamic typing is desired, so a `dynamic_typing` field was added to the [parameter descriptor](https://github.com/ros2/rcl_interfaces/blob/09b5ed93a733adb9deddc47f9a4a8c6e9f584667/rcl_interfaces/msg/ParameterDescriptor.msg#L25).
|
||||
It defaults to `false`.
|
||||
|
||||
For example:
|
||||
|
||||
```cpp
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.dynamic_typing = true;
|
||||
|
||||
node->declare_parameter("dynamically_typed_parameter", rclcpp::ParameterValue{}, descriptor);
|
||||
```
|
||||
|
||||
```py
|
||||
rcl_interfaces.msg.ParameterDescriptor descriptor;
|
||||
descriptor.dynamic_typing = True;
|
||||
|
||||
node.declare_parameter("dynamically_typed_parameter", None, descriptor);
|
||||
```
|
||||
|
||||
## How is the parameter type specified?
|
||||
|
||||
The parameter type will be inferred from the default value provided when declaring it.
|
||||
|
||||
## Statically typed parameters when allowing undeclared parameters
|
||||
|
||||
When undeclared parameters are allowed and a parameter is set without a previous declaration, the parameter will be dynamically typed.
|
||||
This is consistent with other allowed behaviors when undeclared parameters are allowed, e.g. trying to get an undeclared parameter returns "NOT_SET".
|
||||
Parameter declarations will remain special and dynamic or static typing will be used based on the parameter descriptor (default to static).
|
||||
|
||||
## Declaring a parameter without a default value
|
||||
|
||||
There might be cases were a default value does not make sense and the user must always provide an override.
|
||||
In those cases, the parameter type can be specified explicitly:
|
||||
|
||||
```cpp
|
||||
// method signature
|
||||
template<typename T>
|
||||
Node::declare_parameter<T>(std::string name, rcl_interfaces::msg::ParameterDescriptor = rcl_interfaces::msg::ParameterDescriptor{});
|
||||
// or alternatively
|
||||
Node::declare_parameter(std::string name, rclcpp::ParameterType type, rcl_interfaces::msg::ParameterDescriptor = rcl_interfaces::msg::ParameterDescriptor{});
|
||||
|
||||
// examples
|
||||
node->declare_parameter<int64_t>("my_integer_parameter"); // declare an integer parameter
|
||||
node->declare_parameter("another_integer_parameter", rclcpp::ParameterType::PARAMETER_INTEGER); // another way to do the same
|
||||
```
|
||||
|
||||
```py
|
||||
# method signature
|
||||
Node.declare_parameter(name: str, param_type: rclpy.Parameter.Type, descriptor: rcl_interfaces.msg.ParameterDescriptor = rcl_interfaces.msg.ParameterDescriptor())
|
||||
|
||||
# example
|
||||
node.declare_parameter('my_integer_parameter', rclpy.Parameter.Type.INTEGER); # declare an integer parameter
|
||||
```
|
||||
|
||||
If the parameter may be unused, but when used requires a parameter override, then you could conditionally declare it:
|
||||
|
||||
```cpp
|
||||
auto mode = node->declare_parameter("mode", "modeA"); // "mode" parameter is an string
|
||||
if (mode == "modeB") {
|
||||
node->declare_parameter<int64_t>("param_needed_when_mode_b"); // when "modeB", the user must provide "param_needed_when_mode_b"
|
||||
}
|
||||
```
|
||||
|
||||
## Other migration notes
|
||||
|
||||
Declaring a parameter with only a name is deprecated:
|
||||
|
||||
```cpp
|
||||
node->declare_parameter("my_param"); // this generates a build warning
|
||||
```
|
||||
|
||||
```py
|
||||
node.declare_parameter("my_param"); # this generates a python user warning
|
||||
```
|
||||
|
||||
Before, you could initialize a parameter with the "NOT SET" value (in cpp `rclcpp::ParameterValue{}`, in python `None`).
|
||||
Now this will throw an exception in both cases:
|
||||
|
||||
```cpp
|
||||
node->declare_parameter("my_param", rclcpp::ParameterValue{}); // not valid, will throw exception
|
||||
```
|
||||
|
||||
```py
|
||||
node.declare_parameter("my_param", None); # not valid, will raise error
|
||||
```
|
||||
|
||||
## Possible improvements
|
||||
|
||||
### Easier way to declare dynamically typed parameters
|
||||
|
||||
Declaring a dynamically typed parameter in `rclcpp` could be considered to be a bit verbose:
|
||||
|
||||
```cpp
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.dynamic_typing = true;
|
||||
|
||||
node->declare_parameter(name, rclcpp::ParameterValue{}, descriptor);
|
||||
```
|
||||
|
||||
the following ways could be supported to make it simpler:
|
||||
|
||||
```cpp
|
||||
node->declare_parameter(name, rclcpp::PARAMETER_DYNAMIC);
|
||||
node->declare_parameter(name, default_value, rclcpp::PARAMETER_DYNAMIC);
|
||||
```
|
||||
|
||||
or alternatively:
|
||||
|
||||
```cpp
|
||||
node->declare_parameter(name, default_value, rclcpp::ParameterDescriptor{}.dynamic_typing());
|
||||
```
|
||||
|
||||
For `rclpy`, there's already a short way to do it:
|
||||
|
||||
```py
|
||||
node.declare_parameter(name, default_value, rclpy.ParameterDescriptor(dynamic_typing=true));
|
||||
```
|
||||
@@ -1,161 +0,0 @@
|
||||
# Architecture of the rclcpp::WaitSet Type
|
||||
|
||||
The `rclcpp::WaitSet` type is actually a specific configuration of a the more general `rclcpp::WaitSetTemplate` class.
|
||||
|
||||
The `rclcpp::WaitSetTemplate` class is design to have interchangeable implementations for controlling storage of items in the wait set, as well as to control access to the wait set functionality, i.e. whether or not it has thread-safety.
|
||||
|
||||
In general the idea behind a wait set in rclcpp is that you gather a set of entities that can be waited on, e.g. subscriptions, timers, guard conditions, and then wait for one or more of them to be ready.
|
||||
These things are driven by asynchronous events, e.g. subscriptions become ready when new data arrives or timers become ready when their period has elapsed.
|
||||
|
||||
At the moment, things that can be waited on are limited by what can be put into an `rcl_wait_set_t`, which includes subscriptions, service clients, service servers, timers, guard conditions, and events.
|
||||
In this context events are QoS events, as defined in the `rcl` and `rmw` interfaces.
|
||||
|
||||
## Design Goals
|
||||
|
||||
There are some design goals for the `rclcpp::WaitSet` family of classes:
|
||||
|
||||
- minimize inheritance and avoid virtual functions
|
||||
- Overhead of the executor and wait set design have been a common complaint and are often blamed for performance issues.
|
||||
- Since the wait set is at the core of the wait-do loop of the system, aggressive optimization can actually pay off.
|
||||
- avoid unnecessary changes to the underlying `rcl_wait_set_t` instances or unnecessarily recreating it
|
||||
- This can be expensive, because under the hood that requires changes to the middleware's object, e.g. a DDS wait set or similar.
|
||||
- minimize memory allocations in the wait() function, avoid them entirely if the set of things to wait on has not changed
|
||||
- prevent accidentally using an entity with more than wait set at the same time
|
||||
|
||||
Several of these surround performance concerns, but others are concerned with safety and convenience for the user.
|
||||
|
||||
## Architecture
|
||||
|
||||
The `rclcpp::WaitSetTemplate` is the core fixture in the feature, which is using a policy-based design (see https://en.wikipedia.org/wiki/Modern_C%2B%2B_Design#Policy-based_design).
|
||||
|
||||
It delegates storage and synchronization to policy template arguments to the `rclcpp::WaitSetTemplate` via the `StoragePolicy` and `SynchronizationPolicy` template arguments respectively.
|
||||
|
||||
These policies can be mixed and matched to achieve different results.
|
||||
There are a few predefined combinations, `rclcpp::WaitSet` which is a non-thread-safe wait set with dynamic storage, `rclcpp::StaticWaitSet` which is a non-thread-safe wait set with fixed storage, and `rclcpp::ThreadSafeWaitSet` which is a thread-safe wait set with dynamic storage.
|
||||
They are all just aliases to `rclcpp::WaitSetTemplate` with difference combinations of policies.
|
||||
|
||||
Users can extend the behavior by implementing their own policies if desired.
|
||||
|
||||
This kind of design allows for specialization and code sharing without using standard polymorphism via virtual functions, and the benefit of that is that calls on the wait set class are always non-virtual, avoiding dispatching via the v-table.
|
||||
It also forces us to use templates, which means a head-only implementation, which will increase compile times, but will avoid some calls to shared libraries which on some systems has a small overhead too.
|
||||
|
||||
These are aggressive optimizations, but it can actually be very beneficial in the inner-loop of applications, and the hope is that this approach will offer the best performance we can achieve.
|
||||
|
||||
### StoragePolicy
|
||||
|
||||
The storage policy is responsible for storing the entities in the wait set and providing accessors and setters (if appropriate).
|
||||
|
||||
The storage policy is also responsible for maintaining ownership of the entities it is storing at the right times.
|
||||
For example, entities are always given to the wait set as `std::shared_ptr`'s and some policies might only maintain ownership for the lifetime of the wait set or until the entity is removed.
|
||||
Other policies might only hold ownership of the entities while waiting on them, i.e. while they are actively using them, but maintain only weak ownership otherwise.
|
||||
|
||||
There are two built-in storage policies available, the `rclcpp::wait_set_policies::DynamicStorage` and the `rclcpp::wait_set_policies::StaticStorage<...>` classes.
|
||||
|
||||
The `StaticStorage` policy requires that you fully specify the number of entities of each time that can be stored as template arguments and uses the `std:array` class as backing storage.
|
||||
Therefore, it also does not allow adding or removing entities after construction.
|
||||
Because entities cannot be removed and are therefore "always" in use by the wait set, it maintains shared ownership of the entities for the lifetime of the wait set.
|
||||
|
||||
The `DynamicStorage` policy provides access to the entities and allows add and removing entities at any time after construction.
|
||||
It also only maintains shared ownership of the entities while actively waiting on them, which allows the entities to go out of scope while the wait set is idle.
|
||||
Entities that go out of scope in this manner will be removed from the wait set when it notices their weak pointers no longer lock to the entity's shared pointer.
|
||||
|
||||
Both policies allow you to initialize the wait set with entities in the constructor.
|
||||
|
||||
### SynchronizationPolicy
|
||||
|
||||
The synchronization policy is responsible for synchronizing access to wait set operations that share access to the StoragePolicy.
|
||||
|
||||
There are two built-in synchronization policies available, the `rclcpp::wait_set_policies::SequentialSynchronization` and the `rclcpp::wait_set_policies::ThreadSafeSynchronization` policies.
|
||||
|
||||
The `rclcpp::wait_set_policies::SequentialSynchronization` policy essentially does nothing but pass through requests from the user-facing `rclcpp::WaitSetTemplate` interface to the `StoragePolicy` that is being used.
|
||||
|
||||
The `rclcpp::wait_set_policies::ThreadSafeSynchronization` policy sequences access to the `StoragePolicy` being used so that it is safe to call methods like `add_subscription()` on the wait set while it is doing something else, like waiting with the `wait()` method.
|
||||
This synchronization comes at the expense of using mutexes and extra logic to organize the access, but provides some thread-safety.
|
||||
|
||||
### Entity Intake and Management
|
||||
|
||||
Entities, i.e. `rclcpp::SubscriptionBase`, `rclcpp::Waitable`, `rclcpp::ClientBase`, `rclcpp::ServiceBase`, `rclcpp::TimerBase`, `rclcpp::GuardCondition`, etc., may be passed to the wait set during construction.
|
||||
If the wait set has policies that allow for dynamic storage and supports adding and removing entities after construction, then entities can also be added and removed using method on the wait set.
|
||||
|
||||
Either way, the entities are initially given to the wait set as a `std::shared_ptr` in order to maintain shared ownership, but depending on the storage policy it may be stored as a `std::weak_ptr` while the wait set is not actively using the entities.
|
||||
|
||||
Also, when taking on new entities the wait set is responsible for ensuring that entity is not being used by another wait set (at least another instance of `rclcpp::WaitSetTemplate`).
|
||||
|
||||
One more thing that plays into intake of entities is that a few entity types have some extra requirements, specifically subscriptions and waitables.
|
||||
|
||||
Subscriptions (specifically `rclcpp::SubscriptionBase`) are complex objects that contain not only a subscription that can be waited on, but also may have `rclcpp::Waitable`'s inside in order to implement intra-process communication and for QoS events that are also implemented as `rclcpp::Waitable` instances.
|
||||
Therefore, you need a way to say which parts of the subscription should be added to the wait set, because you don't need to add all the entities that make up a subscription to a single wait set.
|
||||
The `rclcpp::SubscriptionWaitSetMask` class provides this mapping, and when adding subscriptions to a wait set you need to provide the subscription shared pointer as well as a mask instance.
|
||||
|
||||
Waitables are complicated by the fact that they often are part of a larger piece of the API, as we saw with subscriptions, and therefore the waitable may need to keep additional things in scope while being used.
|
||||
So when adding a waitable to a wait set you may also provide an "associated entity" as a shared pointer to void, which is purely there to keep something in scope along with the waitable.
|
||||
|
||||
#### EntityEntry classes
|
||||
|
||||
In order to address the need to pair extra information with some entities (e.g. the subscription mask with the subscription entity) and to provide a convenient place to check if the entity is in use by another wait set and claim if not.
|
||||
|
||||
There are a series of classes that are a variation of the `EntityEntry` concept, which wrap the incoming entities and their associated data into a single class, and also provide some safety when converting between the shared ownership and weak ownership if needed.
|
||||
|
||||
They also provide RAII-style checking about whether or not an entity is already associated with a wait set.
|
||||
This is important because when ingesting multiple entities at the same time, e.g. via the constructor, because if you claim the first few entities to be associated with the wait set, but then find one that is already associated, then you need to abort and throw an exception.
|
||||
The RAII-style of these classes addresses this by "dissociating" the first few entities from the wait set when going out of scope due to the thrown exception.
|
||||
|
||||
The process from intake to cleanup of the entity entries follows something like this, using waitables as an example:
|
||||
|
||||
|
||||
|
||||
┌───────────────┐
|
||||
┌────────────────────────┐ │ WaitSet │
|
||||
│ ├──────►│ ├───────────────┐
|
||||
│ shared_ptr<Waitable> │ │ constructor │ │
|
||||
│ │ └───────────────┘ Implicit │
|
||||
│ and optional │ │
|
||||
│ │ ┌───────────────┐ Conversion │
|
||||
│ shared_ptr<void> │ │ add_waitable()│ │
|
||||
│ ├──────►│ ├───────────────┤
|
||||
└────────────────────────┘ │ method │ │
|
||||
└───────────────┘ │
|
||||
│
|
||||
│
|
||||
│
|
||||
┌──────────────────────┐ ┌─────────────────┐ │
|
||||
│ │ │ │ │
|
||||
┌─────┤ ManagedWaitableEntry │◄──┬────┤ WaitableEntry │◄──────┘
|
||||
│ │ │ │ │ │
|
||||
│ └─┬──────────────────┬─┘ │ └─┬─────────────┬─┘
|
||||
│ │ shared_ptr+RAII │ │ │ shared_ptr │
|
||||
│ └──────────────────┘ │ └─────────────┘
|
||||
│ │
|
||||
│ ┌───────┴───────────┐
|
||||
│ │Check that entity │
|
||||
│ Conversion to │is not in use, then│
|
||||
│ weak ownership │claim it for this │
|
||||
│ if needed. │wait set. │
|
||||
│ └───────────────────┘
|
||||
│
|
||||
│ ┌───────────────────────────┐
|
||||
│ │ │
|
||||
└────►│ WeakManagedWaitableEntry │
|
||||
│ │
|
||||
└─┬───────────────────────┬─┘
|
||||
│ weak_ptr + RAII │
|
||||
└───────────────────────┘
|
||||
|
||||
Using the diagram as a reference, you can see that the input from the user is converted into the entity entry class that, for now, just stores the entity and any associated data if it exists.
|
||||
At this point the entity comes in with shared ownership and stays as shared ownership in the basic entry class.
|
||||
Then this entry class is converted into a "managed" entry class, which will check that the entity is not associated with another wait set and associate it with the current wait set during construction.
|
||||
This managed entry class will also automatically disassociate the entity with the current wait set during destruction.
|
||||
The new managed entry class continues to keep shared ownership of the entity.
|
||||
|
||||
Optionally, if the storage policy requires it, the managed entry class can be converted into a "weak" version, where in the entity is stored as a weak pointer instead of a shared pointer.
|
||||
In this case the entity will remain stored as a "weak managed" entry until it is removed or the wait set is destroyed.
|
||||
In the meantime, if the wait set needs to take shared ownership again, it can do that be getting a copy of the weak pointer(s) in the entry and locking them to get shared pointers.
|
||||
But the weak managed entry remains responsible for the RAII-style dissociation from the current wait set when destroyed.
|
||||
Unlike the managed entry that maintains shared ownership, the weak version will need to attempt to lock the weak pointer for the entity before trying to dissociate it from the wait set, because this association is maintained within the entity itself, through methods like `rclcpp::Waitable::exchange_in_use_by_wait_set_state()`.
|
||||
If the entity cannot be accessed via the weak pointer, then it is not explicitly dissociated by the managed entry, but it doesn't matter because the object has gone out of scope and has been deleted anyway.
|
||||
So the cleanup for the weak managed entry is best effort, but that does not pose an issue.
|
||||
|
||||
#### The EntityEntryTemplate classes
|
||||
|
||||
There is a template class called `rclcpp::wait_set_policies::detail::EntityEntryTemplate<EntityT>` (and associated managed and weak-managed versions) which is the foundation for most of the entity types which don't require special handling, like `rclcpp::GuardCondition` and `rclcpp::TimerBase` for example.
|
||||
Other entities like `rclcpp::SubscriptionBase` and `rclcpp::Waitable` have custom specializations of these classes to handle extra storage, custom constructors, and other extra logic to help them work.
|
||||
@@ -95,7 +95,7 @@ void set_allocator_for_deleter(AllocatorDeleter<T> * deleter, Alloc * alloc)
|
||||
template<typename Alloc, typename T>
|
||||
using Deleter = typename std::conditional<
|
||||
std::is_same<typename std::allocator_traits<Alloc>::template rebind_alloc<T>,
|
||||
std::allocator<T>>::value,
|
||||
typename std::allocator<void>::template rebind<T>::other>::value,
|
||||
std::default_delete<T>,
|
||||
AllocatorDeleter<Alloc>
|
||||
>::type;
|
||||
|
||||
@@ -47,9 +47,14 @@ struct AnyExecutable
|
||||
// These are used to keep the scope on the containing items
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group;
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base;
|
||||
std::shared_ptr<void> data;
|
||||
};
|
||||
|
||||
namespace executor
|
||||
{
|
||||
|
||||
using AnyExecutable [[deprecated("use rclcpp::AnyExecutable instead")]] = AnyExecutable;
|
||||
|
||||
} // namespace executor
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__ANY_EXECUTABLE_HPP_
|
||||
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
std::shared_ptr<typename ServiceT::Request> request,
|
||||
std::shared_ptr<typename ServiceT::Response> response)
|
||||
{
|
||||
TRACEPOINT(callback_start, static_cast<const void *>(this), false);
|
||||
TRACEPOINT(callback_start, (const void *)this, false);
|
||||
if (shared_ptr_callback_ != nullptr) {
|
||||
(void)request_header;
|
||||
shared_ptr_callback_(request, response);
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
} else {
|
||||
throw std::runtime_error("unexpected request without any callback set");
|
||||
}
|
||||
TRACEPOINT(callback_end, static_cast<const void *>(this));
|
||||
TRACEPOINT(callback_end, (const void *)this);
|
||||
}
|
||||
|
||||
void register_callback_for_tracing()
|
||||
@@ -106,13 +106,13 @@ public:
|
||||
if (shared_ptr_callback_) {
|
||||
TRACEPOINT(
|
||||
rclcpp_callback_register,
|
||||
static_cast<const void *>(this),
|
||||
tracetools::get_symbol(shared_ptr_callback_));
|
||||
(const void *)this,
|
||||
get_symbol(shared_ptr_callback_));
|
||||
} else if (shared_ptr_with_request_header_callback_) {
|
||||
TRACEPOINT(
|
||||
rclcpp_callback_register,
|
||||
static_cast<const void *>(this),
|
||||
tracetools::get_symbol(shared_ptr_with_request_header_callback_));
|
||||
(const void *)this,
|
||||
get_symbol(shared_ptr_with_request_header_callback_));
|
||||
}
|
||||
#endif // TRACETOOLS_DISABLED
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,44 +56,8 @@ 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.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit CallbackGroup(
|
||||
CallbackGroupType group_type,
|
||||
bool automatically_add_to_executor_with_node = true);
|
||||
explicit CallbackGroup(CallbackGroupType group_type);
|
||||
|
||||
template<typename Function>
|
||||
rclcpp::SubscriptionBase::SharedPtr
|
||||
@@ -138,31 +102,6 @@ public:
|
||||
const CallbackGroupType &
|
||||
type() const;
|
||||
|
||||
/// Return a reference to the 'associated with executor' atomic boolean.
|
||||
/**
|
||||
* When a callback group is added to an executor this boolean is checked
|
||||
* to ensure it has not already been added to another executor.
|
||||
* If it has not been, then this boolean is set to true to indicate it is
|
||||
* now associated with an executor.
|
||||
*
|
||||
* When the callback group is removed from the executor, this atomic boolean
|
||||
* is set back to false.
|
||||
*
|
||||
* \return the 'associated with executor' atomic boolean
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::atomic_bool &
|
||||
get_associated_with_executor_atomic();
|
||||
|
||||
/// Return true if this callback group should be automatically added to an executor by the node.
|
||||
/**
|
||||
* \return boolean true if this callback group should be automatically added
|
||||
* to an executor when the associated node is added, otherwise false.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
automatically_add_to_executor_with_node() const;
|
||||
|
||||
protected:
|
||||
RCLCPP_DISABLE_COPY(CallbackGroup)
|
||||
|
||||
@@ -197,14 +136,12 @@ protected:
|
||||
CallbackGroupType type_;
|
||||
// Mutex to protect the subsequent vectors of pointers.
|
||||
mutable std::mutex mutex_;
|
||||
std::atomic_bool associated_with_executor_;
|
||||
std::vector<rclcpp::SubscriptionBase::WeakPtr> subscription_ptrs_;
|
||||
std::vector<rclcpp::TimerBase::WeakPtr> timer_ptrs_;
|
||||
std::vector<rclcpp::ServiceBase::WeakPtr> service_ptrs_;
|
||||
std::vector<rclcpp::ClientBase::WeakPtr> client_ptrs_;
|
||||
std::vector<rclcpp::Waitable::WeakPtr> waitable_ptrs_;
|
||||
std::atomic_bool can_be_taken_from_;
|
||||
const bool automatically_add_to_executor_with_node_;
|
||||
|
||||
private:
|
||||
template<typename TypeT, typename Function>
|
||||
@@ -222,6 +159,13 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
namespace callback_group
|
||||
{
|
||||
|
||||
using CallbackGroupType [[deprecated("use rclcpp::CallbackGroupType instead")]] = CallbackGroupType;
|
||||
using CallbackGroup [[deprecated("use rclcpp::CallbackGroup instead")]] = CallbackGroup;
|
||||
|
||||
} // namespace callback_group
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CALLBACK_GROUP_HPP_
|
||||
|
||||
@@ -361,8 +361,7 @@ public:
|
||||
SharedPromiseWithRequest promise = std::make_shared<PromiseWithRequest>();
|
||||
SharedFutureWithRequest future_with_request(promise->get_future());
|
||||
|
||||
auto wrapping_cb = [future_with_request, promise, request,
|
||||
cb = std::forward<CallbackWithRequestType>(cb)](SharedFuture future) {
|
||||
auto wrapping_cb = [future_with_request, promise, request, &cb](SharedFuture future) {
|
||||
auto response = future.get();
|
||||
promise->set_value(std::make_pair(request, response));
|
||||
cb(future_with_request);
|
||||
|
||||
@@ -136,7 +136,7 @@ private:
|
||||
RCLCPP_PUBLIC
|
||||
static void
|
||||
on_time_jump(
|
||||
const rcl_time_jump_t * time_jump,
|
||||
const struct rcl_time_jump_t * time_jump,
|
||||
bool before_jump,
|
||||
void * user_data);
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -48,17 +47,6 @@ public:
|
||||
/// Forward declare WeakContextsWrapper
|
||||
class WeakContextsWrapper;
|
||||
|
||||
class OnShutdownCallbackHandle
|
||||
{
|
||||
friend class Context;
|
||||
|
||||
public:
|
||||
using OnShutdownCallbackType = std::function<void ()>;
|
||||
|
||||
private:
|
||||
std::weak_ptr<OnShutdownCallbackType> callback;
|
||||
};
|
||||
|
||||
/// Context which encapsulates shared state between nodes and other similar entities.
|
||||
/**
|
||||
* A context also represents the lifecycle between init and shutdown of rclcpp.
|
||||
@@ -92,7 +80,7 @@ public:
|
||||
*
|
||||
* Note that this function does not setup any signal handlers, so if you want
|
||||
* it to be shutdown by the signal handler, then you need to either install
|
||||
* them manually with rclcpp::install_signal_handlers() or use rclcpp::init().
|
||||
* them manually with rclcpp::install_signal_handers() or use rclcpp::init().
|
||||
* In addition to installing the signal handlers, the shutdown_on_sigint
|
||||
* of the InitOptions needs to be `true` for this context to be shutdown by
|
||||
* the signal handler, otherwise it will be passed over.
|
||||
@@ -151,18 +139,13 @@ public:
|
||||
rclcpp::InitOptions
|
||||
get_init_options();
|
||||
|
||||
/// Return actual domain id.
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_domain_id() const;
|
||||
|
||||
/// Return the shutdown reason, or empty string if not shutdown.
|
||||
/**
|
||||
* This function is thread-safe.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
shutdown_reason() const;
|
||||
shutdown_reason();
|
||||
|
||||
/// Shutdown the context, making it uninitialized and therefore invalid for derived entities.
|
||||
/**
|
||||
@@ -189,7 +172,7 @@ public:
|
||||
bool
|
||||
shutdown(const std::string & reason);
|
||||
|
||||
using OnShutdownCallback = OnShutdownCallbackHandle::OnShutdownCallbackType;
|
||||
using OnShutdownCallback = std::function<void ()>;
|
||||
|
||||
/// Add a on_shutdown callback to be called when shutdown is called for this context.
|
||||
/**
|
||||
@@ -215,47 +198,23 @@ public:
|
||||
OnShutdownCallback
|
||||
on_shutdown(OnShutdownCallback callback);
|
||||
|
||||
/// Add a on_shutdown callback to be called when shutdown is called for this context.
|
||||
/// Return the shutdown callbacks as const.
|
||||
/**
|
||||
* These callbacks will be called in the order they are added as the second
|
||||
* to last step in shutdown().
|
||||
*
|
||||
* When shutdown occurs due to the signal handler, these callbacks are run
|
||||
* asynchronously in the dedicated singal handling thread.
|
||||
*
|
||||
* Also, shutdown() may be called from the destructor of this function.
|
||||
* Therefore, it is not safe to throw exceptions from these callbacks.
|
||||
* Instead, log errors or use some other mechanism to indicate an error has
|
||||
* occurred.
|
||||
*
|
||||
* On shutdown callbacks may be registered before init and after shutdown,
|
||||
* and persist on repeated init's.
|
||||
*
|
||||
* \param[in] callback the on_shutdown callback to be registered
|
||||
* \return the created callback handle
|
||||
* Using the returned reference is not thread-safe with calls that modify
|
||||
* the list of "on shutdown" callbacks, i.e. on_shutdown().
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
OnShutdownCallbackHandle
|
||||
add_on_shutdown_callback(OnShutdownCallback callback);
|
||||
|
||||
/// Remove an registered on_shutdown callbacks.
|
||||
/**
|
||||
* \param[in] callback_handle the on_shutdown callback handle to be removed.
|
||||
* \return true if the callback is found and removed, otherwise false.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
bool
|
||||
remove_on_shutdown_callback(const OnShutdownCallbackHandle & callback_handle);
|
||||
const std::vector<OnShutdownCallback> &
|
||||
get_on_shutdown_callbacks() const;
|
||||
|
||||
/// Return the shutdown callbacks.
|
||||
/**
|
||||
* Returned callbacks are a copy of the registered callbacks.
|
||||
* Using the returned reference is not thread-safe with calls that modify
|
||||
* the list of "on shutdown" callbacks, i.e. on_shutdown().
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<OnShutdownCallback>
|
||||
get_on_shutdown_callbacks() const;
|
||||
std::vector<OnShutdownCallback> &
|
||||
get_on_shutdown_callbacks();
|
||||
|
||||
/// Return the internal rcl context.
|
||||
RCLCPP_PUBLIC
|
||||
@@ -284,6 +243,67 @@ public:
|
||||
void
|
||||
interrupt_all_sleep_for();
|
||||
|
||||
/// Get a handle to the guard condition which is triggered when interrupted.
|
||||
/**
|
||||
* This guard condition is triggered any time interrupt_all_wait_sets() is
|
||||
* called, which may be called by the user, or shutdown().
|
||||
* And in turn, shutdown() may be called by the user, the destructor of this
|
||||
* context, or the signal handler if installed and shutdown_on_sigint is true
|
||||
* for this context.
|
||||
*
|
||||
* The first time that this function is called for a given wait set a new guard
|
||||
* condition will be created and returned; thereafter the same guard condition
|
||||
* will be returned for the same wait set.
|
||||
* This mechanism is designed to ensure that the same guard condition is not
|
||||
* reused across wait sets (e.g., when using multiple executors in the same
|
||||
* process).
|
||||
* This method will throw an exception if initialization of the guard
|
||||
* condition fails.
|
||||
*
|
||||
* The returned guard condition needs to be released with the
|
||||
* release_interrupt_guard_condition() method in order to reclaim resources.
|
||||
*
|
||||
* \param[in] wait_set Pointer to the rcl_wait_set_t that will be using the
|
||||
* resulting guard condition.
|
||||
* \return Pointer to the guard condition.
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rcl_guard_condition_t *
|
||||
get_interrupt_guard_condition(rcl_wait_set_t * wait_set);
|
||||
|
||||
/// Release the previously allocated guard condition which is triggered when interrupted.
|
||||
/**
|
||||
* If you previously called get_interrupt_guard_condition() for a given wait
|
||||
* set to get a interrupt guard condition, then you should call
|
||||
* release_interrupt_guard_condition() when you're done, to free that
|
||||
* condition.
|
||||
* Will throw an exception if get_interrupt_guard_condition() wasn't
|
||||
* previously called for the given wait set.
|
||||
*
|
||||
* After calling this, the pointer returned by get_interrupt_guard_condition()
|
||||
* for the given wait_set is invalid.
|
||||
*
|
||||
* \param[in] wait_set Pointer to the rcl_wait_set_t that was using the
|
||||
* resulting guard condition.
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
* \throws std::runtime_error if a nonexistent wait set is trying to release sigint guard condition.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
release_interrupt_guard_condition(rcl_wait_set_t * wait_set);
|
||||
|
||||
/// Nothrow version of release_interrupt_guard_condition(), logs to RCLCPP_ERROR instead.
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
release_interrupt_guard_condition(rcl_wait_set_t * wait_set, const std::nothrow_t &) noexcept;
|
||||
|
||||
/// Interrupt any blocking executors, or wait sets associated with this context.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
interrupt_all_wait_sets();
|
||||
|
||||
/// Return a singleton instance for the SubContext type, constructing one if necessary.
|
||||
template<typename SubContext, typename ... Args>
|
||||
std::shared_ptr<SubContext>
|
||||
@@ -322,7 +342,7 @@ private:
|
||||
|
||||
// This mutex is recursive so that the destructor can ensure atomicity
|
||||
// between is_initialized and shutdown.
|
||||
mutable std::recursive_mutex init_mutex_;
|
||||
std::recursive_mutex init_mutex_;
|
||||
std::shared_ptr<rcl_context_t> rcl_context_;
|
||||
rclcpp::InitOptions init_options_;
|
||||
std::string shutdown_reason_;
|
||||
@@ -335,14 +355,19 @@ private:
|
||||
// attempt to acquire another sub context.
|
||||
std::recursive_mutex sub_contexts_mutex_;
|
||||
|
||||
std::unordered_set<std::shared_ptr<OnShutdownCallback>> on_shutdown_callbacks_;
|
||||
mutable std::mutex on_shutdown_callbacks_mutex_;
|
||||
std::vector<OnShutdownCallback> on_shutdown_callbacks_;
|
||||
std::mutex on_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_;
|
||||
|
||||
/// Mutex to protect sigint_guard_cond_handles_.
|
||||
std::mutex interrupt_guard_cond_handles_mutex_;
|
||||
/// Guard conditions for interrupting of associated wait sets on interrupt_all_wait_sets().
|
||||
std::unordered_map<rcl_wait_set_t *, rcl_guard_condition_t> interrupt_guard_cond_handles_;
|
||||
|
||||
/// Keep shared ownership of global vector of weak contexts
|
||||
std::shared_ptr<WeakContextsWrapper> weak_contexts_;
|
||||
};
|
||||
|
||||
@@ -36,6 +36,22 @@ RCLCPP_PUBLIC
|
||||
DefaultContext::SharedPtr
|
||||
get_global_default_context();
|
||||
|
||||
namespace default_context
|
||||
{
|
||||
|
||||
using DefaultContext
|
||||
[[deprecated("use rclcpp::contexts::DefaultContext instead")]] = DefaultContext;
|
||||
|
||||
[[deprecated("use rclcpp::contexts::get_global_default_context() instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
inline
|
||||
DefaultContext::SharedPtr
|
||||
get_global_default_context()
|
||||
{
|
||||
return rclcpp::contexts::get_global_default_context();
|
||||
}
|
||||
|
||||
} // namespace default_context
|
||||
} // namespace contexts
|
||||
} // namespace rclcpp
|
||||
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
// Copyright 2020, Apex.AI Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__CREATE_GENERIC_PUBLISHER_HPP_
|
||||
#define RCLCPP__CREATE_GENERIC_PUBLISHER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/generic_publisher.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
#include "rclcpp/publisher_options.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/typesupport_helpers.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Create and return a GenericPublisher.
|
||||
/**
|
||||
* The returned pointer will never be empty, but this function can throw various exceptions, for
|
||||
* instance when the message's package can not be found on the AMENT_PREFIX_PATH.
|
||||
*
|
||||
* \param topics_interface NodeTopicsInterface pointer used in parts of the setup
|
||||
* \param topic_name Topic name
|
||||
* \param topic_type Topic type
|
||||
* \param qos %QoS settings
|
||||
* \param options %Publisher options.
|
||||
* Not all publisher options are currently respected, the only relevant options for this
|
||||
* publisher are `event_callbacks`, `use_default_callbacks`, and `%callback_group`.
|
||||
*/
|
||||
template<typename AllocatorT = std::allocator<void>>
|
||||
std::shared_ptr<GenericPublisher> create_generic_publisher(
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr topics_interface,
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::PublisherOptionsWithAllocator<AllocatorT>()
|
||||
)
|
||||
)
|
||||
{
|
||||
auto ts_lib = rclcpp::get_typesupport_library(topic_type, "rosidl_typesupport_cpp");
|
||||
auto pub = std::make_shared<GenericPublisher>(
|
||||
topics_interface->get_node_base_interface(),
|
||||
std::move(ts_lib),
|
||||
topic_name,
|
||||
topic_type,
|
||||
qos,
|
||||
options);
|
||||
topics_interface->add_publisher(pub, options.callback_group);
|
||||
return pub;
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CREATE_GENERIC_PUBLISHER_HPP_
|
||||
@@ -1,79 +0,0 @@
|
||||
// Copyright 2020, Apex.AI Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__CREATE_GENERIC_SUBSCRIPTION_HPP_
|
||||
#define RCLCPP__CREATE_GENERIC_SUBSCRIPTION_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rcl/subscription.h"
|
||||
#include "rclcpp/generic_subscription.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
#include "rclcpp/subscription_options.hpp"
|
||||
#include "rclcpp/typesupport_helpers.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Create and return a GenericSubscription.
|
||||
/**
|
||||
* The returned pointer will never be empty, but this function can throw various exceptions, for
|
||||
* instance when the message's package can not be found on the AMENT_PREFIX_PATH.
|
||||
*
|
||||
* \param topics_interface NodeTopicsInterface pointer used in parts of the setup.
|
||||
* \param topic_name Topic name
|
||||
* \param topic_type Topic type
|
||||
* \param qos %QoS settings
|
||||
* \param callback Callback for new messages of serialized form
|
||||
* \param options %Publisher options.
|
||||
* Not all publisher options are currently respected, the only relevant options for this
|
||||
* publisher are `event_callbacks`, `use_default_callbacks`, and `%callback_group`.
|
||||
*/
|
||||
template<typename AllocatorT = std::allocator<void>>
|
||||
std::shared_ptr<GenericSubscription> create_generic_subscription(
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr topics_interface,
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
)
|
||||
)
|
||||
{
|
||||
auto ts_lib = rclcpp::get_typesupport_library(
|
||||
topic_type, "rosidl_typesupport_cpp");
|
||||
|
||||
auto subscription = std::make_shared<GenericSubscription>(
|
||||
topics_interface->get_node_base_interface(),
|
||||
std::move(ts_lib),
|
||||
topic_name,
|
||||
topic_type,
|
||||
qos,
|
||||
callback,
|
||||
options);
|
||||
|
||||
topics_interface->add_subscription(subscription, options.callback_group);
|
||||
|
||||
return subscription;
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CREATE_GENERIC_SUBSCRIPTION_HPP_
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/node_interfaces/get_node_topics_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
@@ -25,65 +24,15 @@
|
||||
#include "rclcpp/publisher_factory.hpp"
|
||||
#include "rclcpp/publisher_options.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/qos_overriding_options.hpp"
|
||||
#include "rclcpp/detail/qos_parameters.hpp"
|
||||
|
||||
#include "rmw/qos_profiles.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/// Create and return a publisher of the given MessageT type.
|
||||
template<
|
||||
typename MessageT,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
typename PublisherT = rclcpp::Publisher<MessageT, AllocatorT>,
|
||||
typename NodeParametersT,
|
||||
typename NodeTopicsT>
|
||||
std::shared_ptr<PublisherT>
|
||||
create_publisher(
|
||||
NodeParametersT & node_parameters,
|
||||
NodeTopicsT & node_topics,
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos,
|
||||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::PublisherOptionsWithAllocator<AllocatorT>()
|
||||
)
|
||||
)
|
||||
{
|
||||
auto node_topics_interface = rclcpp::node_interfaces::get_node_topics_interface(node_topics);
|
||||
const rclcpp::QoS & actual_qos = options.qos_overriding_options.get_policy_kinds().size() ?
|
||||
rclcpp::detail::declare_qos_parameters(
|
||||
options.qos_overriding_options, node_parameters,
|
||||
node_topics_interface->resolve_topic_name(topic_name),
|
||||
qos, rclcpp::detail::PublisherQosParametersTraits{}) :
|
||||
qos;
|
||||
|
||||
// Create the publisher.
|
||||
auto pub = node_topics_interface->create_publisher(
|
||||
topic_name,
|
||||
rclcpp::create_publisher_factory<MessageT, AllocatorT, PublisherT>(options),
|
||||
actual_qos
|
||||
);
|
||||
|
||||
// Add the publisher to the node topics interface.
|
||||
node_topics_interface->add_publisher(pub, options.callback_group);
|
||||
|
||||
return std::dynamic_pointer_cast<PublisherT>(pub);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
|
||||
/// Create and return a publisher of the given MessageT type.
|
||||
/**
|
||||
* The NodeT type only needs to have a method called get_node_topics_interface()
|
||||
* which returns a shared_ptr to a NodeTopicsInterface.
|
||||
*
|
||||
* In case `options.qos_overriding_options` is enabling qos parameter overrides,
|
||||
* NodeT must also have a method called get_node_parameters_interface()
|
||||
* which returns a shared_ptr to a NodeParametersInterface.
|
||||
*/
|
||||
template<
|
||||
typename MessageT,
|
||||
@@ -100,28 +49,21 @@ create_publisher(
|
||||
)
|
||||
)
|
||||
{
|
||||
return detail::create_publisher<MessageT, AllocatorT, PublisherT>(
|
||||
node, node, topic_name, qos, options);
|
||||
}
|
||||
// Extract the NodeTopicsInterface from the NodeT.
|
||||
using rclcpp::node_interfaces::get_node_topics_interface;
|
||||
auto node_topics = get_node_topics_interface(node);
|
||||
|
||||
/// Create and return a publisher of the given MessageT type.
|
||||
template<
|
||||
typename MessageT,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
typename PublisherT = rclcpp::Publisher<MessageT, AllocatorT>>
|
||||
std::shared_ptr<PublisherT>
|
||||
create_publisher(
|
||||
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr & node_parameters,
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr & node_topics,
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos,
|
||||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::PublisherOptionsWithAllocator<AllocatorT>()
|
||||
)
|
||||
)
|
||||
{
|
||||
return detail::create_publisher<MessageT, AllocatorT, PublisherT>(
|
||||
node_parameters, node_topics, topic_name, qos, options);
|
||||
// Create the publisher.
|
||||
auto pub = node_topics->create_publisher(
|
||||
topic_name,
|
||||
rclcpp::create_publisher_factory<MessageT, AllocatorT, PublisherT>(options),
|
||||
qos
|
||||
);
|
||||
|
||||
// Add the publisher to the node topics interface.
|
||||
node_topics->add_publisher(pub, options.callback_group);
|
||||
|
||||
return std::dynamic_pointer_cast<PublisherT>(pub);
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -41,118 +41,16 @@
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename AllocatorT,
|
||||
typename SubscriptionT,
|
||||
typename MessageMemoryStrategyT,
|
||||
typename NodeParametersT,
|
||||
typename NodeTopicsT,
|
||||
typename ROSMessageType = typename SubscriptionT::ROSMessageType>
|
||||
typename std::shared_ptr<SubscriptionT>
|
||||
create_subscription(
|
||||
NodeParametersT & node_parameters,
|
||||
NodeTopicsT & node_topics,
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos,
|
||||
CallbackT && callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
),
|
||||
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat = (
|
||||
MessageMemoryStrategyT::create_default()
|
||||
)
|
||||
)
|
||||
{
|
||||
using rclcpp::node_interfaces::get_node_topics_interface;
|
||||
auto node_topics_interface = get_node_topics_interface(node_topics);
|
||||
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>>
|
||||
subscription_topic_stats = nullptr;
|
||||
|
||||
if (rclcpp::detail::resolve_enable_topic_statistics(
|
||||
options,
|
||||
*node_topics_interface->get_node_base_interface()))
|
||||
{
|
||||
if (options.topic_stats_options.publish_period <= std::chrono::milliseconds(0)) {
|
||||
throw std::invalid_argument(
|
||||
"topic_stats_options.publish_period must be greater than 0, specified value of " +
|
||||
std::to_string(options.topic_stats_options.publish_period.count()) +
|
||||
" ms");
|
||||
}
|
||||
|
||||
std::shared_ptr<Publisher<statistics_msgs::msg::MetricsMessage>>
|
||||
publisher = rclcpp::detail::create_publisher<statistics_msgs::msg::MetricsMessage>(
|
||||
node_parameters,
|
||||
node_topics_interface,
|
||||
options.topic_stats_options.publish_topic,
|
||||
qos);
|
||||
|
||||
subscription_topic_stats = std::make_shared<
|
||||
rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>
|
||||
>(node_topics_interface->get_node_base_interface()->get_name(), publisher);
|
||||
|
||||
std::weak_ptr<
|
||||
rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>
|
||||
> weak_subscription_topic_stats(subscription_topic_stats);
|
||||
auto sub_call_back = [weak_subscription_topic_stats]() {
|
||||
auto subscription_topic_stats = weak_subscription_topic_stats.lock();
|
||||
if (subscription_topic_stats) {
|
||||
subscription_topic_stats->publish_message_and_reset_measurements();
|
||||
}
|
||||
};
|
||||
|
||||
auto node_timer_interface = node_topics_interface->get_node_timers_interface();
|
||||
|
||||
auto timer = create_wall_timer(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
options.topic_stats_options.publish_period),
|
||||
sub_call_back,
|
||||
options.callback_group,
|
||||
node_topics_interface->get_node_base_interface(),
|
||||
node_timer_interface
|
||||
);
|
||||
|
||||
subscription_topic_stats->set_publisher_timer(timer);
|
||||
}
|
||||
|
||||
auto factory = rclcpp::create_subscription_factory<MessageT>(
|
||||
std::forward<CallbackT>(callback),
|
||||
options,
|
||||
msg_mem_strat,
|
||||
subscription_topic_stats
|
||||
);
|
||||
|
||||
const rclcpp::QoS & actual_qos = options.qos_overriding_options.get_policy_kinds().size() ?
|
||||
rclcpp::detail::declare_qos_parameters(
|
||||
options.qos_overriding_options, node_parameters,
|
||||
node_topics_interface->resolve_topic_name(topic_name),
|
||||
qos, rclcpp::detail::SubscriptionQosParametersTraits{}) :
|
||||
qos;
|
||||
|
||||
auto sub = node_topics_interface->create_subscription(topic_name, factory, actual_qos);
|
||||
node_topics_interface->add_subscription(sub, options.callback_group);
|
||||
|
||||
return std::dynamic_pointer_cast<SubscriptionT>(sub);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// Create and return a subscription of the given MessageT type.
|
||||
/**
|
||||
* The NodeT type only needs to have a method called get_node_topics_interface()
|
||||
* which returns a shared_ptr to a NodeTopicsInterface, or be a
|
||||
* NodeTopicsInterface pointer itself.
|
||||
*
|
||||
* In case `options.qos_overriding_options` is enabling qos parameter overrides,
|
||||
* NodeT must also have a method called get_node_parameters_interface()
|
||||
* which returns a shared_ptr to a NodeParametersInterface.
|
||||
*
|
||||
* \tparam MessageT
|
||||
* \tparam CallbackT
|
||||
* \tparam AllocatorT
|
||||
* \tparam CallbackMessageT
|
||||
* \tparam SubscriptionT
|
||||
* \tparam MessageMemoryStrategyT
|
||||
* \tparam NodeT
|
||||
@@ -170,12 +68,17 @@ template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
typename SubscriptionT = rclcpp::Subscription<MessageT, AllocatorT>,
|
||||
typename MessageMemoryStrategyT = typename SubscriptionT::MessageMemoryStrategyType,
|
||||
typename CallbackMessageT =
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type,
|
||||
typename SubscriptionT = rclcpp::Subscription<CallbackMessageT, AllocatorT>,
|
||||
typename MessageMemoryStrategyT = rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
CallbackMessageT,
|
||||
AllocatorT
|
||||
>,
|
||||
typename NodeT>
|
||||
typename std::shared_ptr<SubscriptionT>
|
||||
create_subscription(
|
||||
NodeT & node,
|
||||
NodeT && node,
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos,
|
||||
CallbackT && callback,
|
||||
@@ -187,40 +90,68 @@ create_subscription(
|
||||
)
|
||||
)
|
||||
{
|
||||
return rclcpp::detail::create_subscription<
|
||||
MessageT, CallbackT, AllocatorT, SubscriptionT, MessageMemoryStrategyT>(
|
||||
node, node, topic_name, qos, std::forward<CallbackT>(callback), options, msg_mem_strat);
|
||||
}
|
||||
using rclcpp::node_interfaces::get_node_topics_interface;
|
||||
auto node_topics = get_node_topics_interface(std::forward<NodeT>(node));
|
||||
|
||||
/// Create and return a subscription of the given MessageT type.
|
||||
/**
|
||||
* See \ref create_subscription().
|
||||
*/
|
||||
template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
typename SubscriptionT = rclcpp::Subscription<MessageT, AllocatorT>,
|
||||
typename MessageMemoryStrategyT = typename SubscriptionT::MessageMemoryStrategyType>
|
||||
typename std::shared_ptr<SubscriptionT>
|
||||
create_subscription(
|
||||
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr & node_parameters,
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr & node_topics,
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos,
|
||||
CallbackT && callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
),
|
||||
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat = (
|
||||
MessageMemoryStrategyT::create_default()
|
||||
)
|
||||
)
|
||||
{
|
||||
return rclcpp::detail::create_subscription<
|
||||
MessageT, CallbackT, AllocatorT, SubscriptionT, MessageMemoryStrategyT>(
|
||||
node_parameters, node_topics, topic_name, qos,
|
||||
std::forward<CallbackT>(callback), options, msg_mem_strat);
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>>
|
||||
subscription_topic_stats = nullptr;
|
||||
|
||||
if (rclcpp::detail::resolve_enable_topic_statistics(
|
||||
options,
|
||||
*node_topics->get_node_base_interface()))
|
||||
{
|
||||
if (options.topic_stats_options.publish_period <= std::chrono::milliseconds(0)) {
|
||||
throw std::invalid_argument(
|
||||
"topic_stats_options.publish_period must be greater than 0, specified value of " +
|
||||
std::to_string(options.topic_stats_options.publish_period.count()) +
|
||||
" ms");
|
||||
}
|
||||
|
||||
std::shared_ptr<Publisher<statistics_msgs::msg::MetricsMessage>> publisher =
|
||||
create_publisher<statistics_msgs::msg::MetricsMessage>(
|
||||
node,
|
||||
options.topic_stats_options.publish_topic,
|
||||
qos);
|
||||
|
||||
subscription_topic_stats = std::make_shared<
|
||||
rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>
|
||||
>(node_topics->get_node_base_interface()->get_name(), publisher);
|
||||
|
||||
std::weak_ptr<
|
||||
rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>
|
||||
> weak_subscription_topic_stats(subscription_topic_stats);
|
||||
auto sub_call_back = [weak_subscription_topic_stats]() {
|
||||
auto subscription_topic_stats = weak_subscription_topic_stats.lock();
|
||||
if (subscription_topic_stats) {
|
||||
subscription_topic_stats->publish_message();
|
||||
}
|
||||
};
|
||||
|
||||
auto node_timer_interface = node_topics->get_node_timers_interface();
|
||||
|
||||
auto timer = create_wall_timer(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
options.topic_stats_options.publish_period),
|
||||
sub_call_back,
|
||||
options.callback_group,
|
||||
node_topics->get_node_base_interface(),
|
||||
node_timer_interface
|
||||
);
|
||||
|
||||
subscription_topic_stats->set_publisher_timer(timer);
|
||||
}
|
||||
|
||||
auto factory = rclcpp::create_subscription_factory<MessageT>(
|
||||
std::forward<CallbackT>(callback),
|
||||
options,
|
||||
msg_mem_strat,
|
||||
subscription_topic_stats
|
||||
);
|
||||
|
||||
auto sub = node_topics->create_subscription(topic_name, factory, qos);
|
||||
node_topics->add_subscription(sub, options.callback_group);
|
||||
|
||||
return std::dynamic_pointer_cast<SubscriptionT>(sub);
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -1,326 +0,0 @@
|
||||
// Copyright 2020 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__DETAIL__QOS_PARAMETERS_HPP_
|
||||
#define RCLCPP__DETAIL__QOS_PARAMETERS_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl_interfaces/msg/parameter_descriptor.hpp"
|
||||
#include "rcpputils/pointer_traits.hpp"
|
||||
#include "rmw/qos_string_conversions.h"
|
||||
|
||||
#include "rclcpp/duration.hpp"
|
||||
#include "rclcpp/node_interfaces/get_node_parameters_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
|
||||
#include "rclcpp/qos_overriding_options.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// \internal Trait used to specialize `declare_qos_parameters()` for publishers.
|
||||
struct PublisherQosParametersTraits
|
||||
{
|
||||
static constexpr const char * entity_type() {return "publisher";}
|
||||
static constexpr auto allowed_policies()
|
||||
{
|
||||
return std::array<::rclcpp::QosPolicyKind, 9> {
|
||||
QosPolicyKind::AvoidRosNamespaceConventions,
|
||||
QosPolicyKind::Deadline,
|
||||
QosPolicyKind::Durability,
|
||||
QosPolicyKind::History,
|
||||
QosPolicyKind::Depth,
|
||||
QosPolicyKind::Lifespan,
|
||||
QosPolicyKind::Liveliness,
|
||||
QosPolicyKind::LivelinessLeaseDuration,
|
||||
QosPolicyKind::Reliability,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// \internal Trait used to specialize `declare_qos_parameters()` for subscriptions.
|
||||
struct SubscriptionQosParametersTraits
|
||||
{
|
||||
static constexpr const char * entity_type() {return "subscription";}
|
||||
static constexpr auto allowed_policies()
|
||||
{
|
||||
return std::array<::rclcpp::QosPolicyKind, 8> {
|
||||
QosPolicyKind::AvoidRosNamespaceConventions,
|
||||
QosPolicyKind::Deadline,
|
||||
QosPolicyKind::Durability,
|
||||
QosPolicyKind::History,
|
||||
QosPolicyKind::Depth,
|
||||
QosPolicyKind::Liveliness,
|
||||
QosPolicyKind::LivelinessLeaseDuration,
|
||||
QosPolicyKind::Reliability,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// \internal Returns the given `policy` of the profile `qos` converted to a parameter value.
|
||||
inline
|
||||
::rclcpp::ParameterValue
|
||||
get_default_qos_param_value(rclcpp::QosPolicyKind policy, const rclcpp::QoS & qos);
|
||||
|
||||
/// \internal Modify the given `policy` in `qos` to be `value`.
|
||||
inline
|
||||
void
|
||||
apply_qos_override(
|
||||
rclcpp::QosPolicyKind policy, rclcpp::ParameterValue value, rclcpp::QoS & qos);
|
||||
|
||||
inline
|
||||
rclcpp::ParameterValue
|
||||
declare_parameter_or_get(
|
||||
rclcpp::node_interfaces::NodeParametersInterface & parameters_interface,
|
||||
const std::string & param_name,
|
||||
rclcpp::ParameterValue param_value,
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor)
|
||||
{
|
||||
try {
|
||||
return parameters_interface.declare_parameter(
|
||||
param_name, param_value, descriptor);
|
||||
} catch (const rclcpp::exceptions::ParameterAlreadyDeclaredException &) {
|
||||
return parameters_interface.get_parameter(param_name).get_parameter_value();
|
||||
}
|
||||
}
|
||||
|
||||
/// \internal Declare QoS parameters for the given entity.
|
||||
/**
|
||||
* \tparam NodeT Node pointer or reference type.
|
||||
* \tparam EntityQosParametersTraits A class with two static methods: `entity_type()` and
|
||||
* `allowed_policies()`. See `PublisherQosParametersTraits` and `SubscriptionQosParametersTraits`.
|
||||
* \param options User provided options that indicate if QoS parameter overrides should be
|
||||
* declared or not, which policy can have overrides, and optionally a callback to validate the profile.
|
||||
* \param node Parameters will be declared using this node.
|
||||
* \param topic_name Name of the topic of the entity.
|
||||
* \param default_qos User provided qos. It will be used as a default for the parameters declared.
|
||||
* \return qos profile based on the user provided parameter overrides.
|
||||
*/
|
||||
template<typename NodeT, typename EntityQosParametersTraits>
|
||||
std::enable_if_t<
|
||||
rclcpp::node_interfaces::has_node_parameters_interface<
|
||||
decltype(std::declval<typename rcpputils::remove_pointer<NodeT>::type>())>::value ||
|
||||
std::is_same<typename std::decay_t<NodeT>,
|
||||
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr>::value,
|
||||
rclcpp::QoS>
|
||||
declare_qos_parameters(
|
||||
const ::rclcpp::QosOverridingOptions & options,
|
||||
NodeT & node,
|
||||
const std::string & topic_name,
|
||||
const ::rclcpp::QoS & default_qos,
|
||||
EntityQosParametersTraits)
|
||||
{
|
||||
auto & parameters_interface = *rclcpp::node_interfaces::get_node_parameters_interface(node);
|
||||
std::string param_prefix;
|
||||
const auto & id = options.get_id();
|
||||
{
|
||||
std::ostringstream oss{"qos_overrides.", std::ios::ate};
|
||||
oss << topic_name << "." << EntityQosParametersTraits::entity_type();
|
||||
if (!id.empty()) {
|
||||
oss << "_" << id;
|
||||
}
|
||||
oss << ".";
|
||||
param_prefix = oss.str();
|
||||
}
|
||||
std::string param_description_suffix;
|
||||
{
|
||||
std::ostringstream oss{"} for ", std::ios::ate};
|
||||
oss << EntityQosParametersTraits::entity_type() << " {" << topic_name << "}";
|
||||
if (!id.empty()) {
|
||||
oss << " with id {" << id << "}";
|
||||
}
|
||||
param_description_suffix = oss.str();
|
||||
}
|
||||
rclcpp::QoS qos = default_qos;
|
||||
for (auto policy : EntityQosParametersTraits::allowed_policies()) {
|
||||
if (
|
||||
std::count(options.get_policy_kinds().begin(), options.get_policy_kinds().end(), policy))
|
||||
{
|
||||
std::ostringstream param_name{param_prefix, std::ios::ate};
|
||||
param_name << qos_policy_kind_to_cstr(policy);
|
||||
std::ostringstream param_desciption{"qos policy {", std::ios::ate};
|
||||
param_desciption << qos_policy_kind_to_cstr(policy) << param_description_suffix;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor{};
|
||||
descriptor.description = param_desciption.str();
|
||||
descriptor.read_only = true;
|
||||
auto value = declare_parameter_or_get(
|
||||
parameters_interface, param_name.str(),
|
||||
get_default_qos_param_value(policy, qos), descriptor);
|
||||
::rclcpp::detail::apply_qos_override(policy, value, qos);
|
||||
}
|
||||
}
|
||||
const auto & validation_callback = options.get_validation_callback();
|
||||
if (validation_callback) {
|
||||
auto result = validation_callback(qos);
|
||||
if (!result.successful) {
|
||||
throw rclcpp::exceptions::InvalidQosOverridesException{
|
||||
"validation callback failed: " + result.reason};
|
||||
}
|
||||
}
|
||||
return qos;
|
||||
}
|
||||
|
||||
// TODO(ivanpauno): This overload cannot declare the QoS parameters, as a node parameters interface
|
||||
// was not provided.
|
||||
template<typename NodeT, typename EntityQosParametersTraits>
|
||||
std::enable_if_t<
|
||||
!(rclcpp::node_interfaces::has_node_parameters_interface<
|
||||
decltype(std::declval<typename rcpputils::remove_pointer<NodeT>::type>())>::value ||
|
||||
std::is_same<typename std::decay_t<NodeT>,
|
||||
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr>::value),
|
||||
rclcpp::QoS>
|
||||
declare_qos_parameters(
|
||||
const ::rclcpp::QosOverridingOptions & options,
|
||||
NodeT &,
|
||||
const std::string &,
|
||||
const ::rclcpp::QoS & default_qos,
|
||||
EntityQosParametersTraits)
|
||||
{
|
||||
if (options.get_policy_kinds().size()) {
|
||||
std::runtime_error exc{
|
||||
"passed non-default qos overriding options without providing a parameters interface"};
|
||||
throw exc;
|
||||
}
|
||||
return default_qos;
|
||||
}
|
||||
|
||||
/// \internal Helper function to get a rmw qos policy value from a string.
|
||||
#define RCLCPP_DETAIL_APPLY_QOS_OVERRIDE_FROM_PARAMETER_STRING( \
|
||||
kind_lower, kind_upper, parameter_value, rclcpp_qos) \
|
||||
do { \
|
||||
auto policy_string = (parameter_value).get<std::string>(); \
|
||||
auto policy_value = rmw_qos_ ## kind_lower ## _policy_from_str(policy_string.c_str()); \
|
||||
if (RMW_QOS_POLICY_ ## kind_upper ## _UNKNOWN == policy_value) { \
|
||||
throw std::invalid_argument{"unknown QoS policy " #kind_lower " value: " + policy_string}; \
|
||||
} \
|
||||
((rclcpp_qos).kind_lower)(policy_value); \
|
||||
} while (0)
|
||||
|
||||
inline
|
||||
void
|
||||
apply_qos_override(
|
||||
rclcpp::QosPolicyKind policy, rclcpp::ParameterValue value, rclcpp::QoS & qos)
|
||||
{
|
||||
switch (policy) {
|
||||
case QosPolicyKind::AvoidRosNamespaceConventions:
|
||||
qos.avoid_ros_namespace_conventions(value.get<bool>());
|
||||
break;
|
||||
case QosPolicyKind::Deadline:
|
||||
qos.deadline(::rclcpp::Duration::from_nanoseconds(value.get<int64_t>()));
|
||||
break;
|
||||
case QosPolicyKind::Durability:
|
||||
RCLCPP_DETAIL_APPLY_QOS_OVERRIDE_FROM_PARAMETER_STRING(
|
||||
durability, DURABILITY, value, qos);
|
||||
break;
|
||||
case QosPolicyKind::History:
|
||||
RCLCPP_DETAIL_APPLY_QOS_OVERRIDE_FROM_PARAMETER_STRING(
|
||||
history, HISTORY, value, qos);
|
||||
break;
|
||||
case QosPolicyKind::Depth:
|
||||
qos.get_rmw_qos_profile().depth = static_cast<size_t>(value.get<int64_t>());
|
||||
break;
|
||||
case QosPolicyKind::Lifespan:
|
||||
qos.lifespan(::rclcpp::Duration::from_nanoseconds(value.get<int64_t>()));
|
||||
break;
|
||||
case QosPolicyKind::Liveliness:
|
||||
RCLCPP_DETAIL_APPLY_QOS_OVERRIDE_FROM_PARAMETER_STRING(
|
||||
liveliness, LIVELINESS, value, qos);
|
||||
break;
|
||||
case QosPolicyKind::LivelinessLeaseDuration:
|
||||
qos.liveliness_lease_duration(::rclcpp::Duration::from_nanoseconds(value.get<int64_t>()));
|
||||
break;
|
||||
case QosPolicyKind::Reliability:
|
||||
RCLCPP_DETAIL_APPLY_QOS_OVERRIDE_FROM_PARAMETER_STRING(
|
||||
reliability, RELIABILITY, value, qos);
|
||||
break;
|
||||
default:
|
||||
throw std::invalid_argument{"unknown QosPolicyKind"};
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert `rmw_time_t` to `int64_t` that can be used as a parameter value.
|
||||
inline
|
||||
int64_t
|
||||
rmw_duration_to_int64_t(rmw_time_t rmw_duration)
|
||||
{
|
||||
return ::rclcpp::Duration(
|
||||
static_cast<int32_t>(rmw_duration.sec),
|
||||
static_cast<uint32_t>(rmw_duration.nsec)
|
||||
).nanoseconds();
|
||||
}
|
||||
|
||||
/// \internal Throw an exception if `policy_value_stringified` is NULL.
|
||||
inline
|
||||
const char *
|
||||
check_if_stringified_policy_is_null(const char * policy_value_stringified, QosPolicyKind kind)
|
||||
{
|
||||
if (!policy_value_stringified) {
|
||||
std::ostringstream oss{"unknown value for policy kind {", std::ios::ate};
|
||||
oss << kind << "}";
|
||||
throw std::invalid_argument{oss.str()};
|
||||
}
|
||||
return policy_value_stringified;
|
||||
}
|
||||
|
||||
inline
|
||||
::rclcpp::ParameterValue
|
||||
get_default_qos_param_value(rclcpp::QosPolicyKind kind, const rclcpp::QoS & qos)
|
||||
{
|
||||
using ParameterValue = ::rclcpp::ParameterValue;
|
||||
const auto & rmw_qos = qos.get_rmw_qos_profile();
|
||||
switch (kind) {
|
||||
case QosPolicyKind::AvoidRosNamespaceConventions:
|
||||
return ParameterValue(rmw_qos.avoid_ros_namespace_conventions);
|
||||
case QosPolicyKind::Deadline:
|
||||
return ParameterValue(rmw_duration_to_int64_t(rmw_qos.deadline));
|
||||
case QosPolicyKind::Durability:
|
||||
return ParameterValue(
|
||||
check_if_stringified_policy_is_null(
|
||||
rmw_qos_durability_policy_to_str(rmw_qos.durability), kind));
|
||||
case QosPolicyKind::History:
|
||||
return ParameterValue(
|
||||
check_if_stringified_policy_is_null(
|
||||
rmw_qos_history_policy_to_str(rmw_qos.history), kind));
|
||||
case QosPolicyKind::Depth:
|
||||
return ParameterValue(static_cast<int64_t>(rmw_qos.depth));
|
||||
case QosPolicyKind::Lifespan:
|
||||
return ParameterValue(rmw_duration_to_int64_t(rmw_qos.lifespan));
|
||||
case QosPolicyKind::Liveliness:
|
||||
return ParameterValue(
|
||||
check_if_stringified_policy_is_null(
|
||||
rmw_qos_liveliness_policy_to_str(rmw_qos.liveliness), kind));
|
||||
case QosPolicyKind::LivelinessLeaseDuration:
|
||||
return ParameterValue(rmw_duration_to_int64_t(rmw_qos.liveliness_lease_duration));
|
||||
case QosPolicyKind::Reliability:
|
||||
return ParameterValue(
|
||||
check_if_stringified_policy_is_null(
|
||||
rmw_qos_reliability_policy_to_str(rmw_qos.reliability), kind));
|
||||
default:
|
||||
throw std::invalid_argument{"unknown QoS policy kind"};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DETAIL__QOS_PARAMETERS_HPP_
|
||||
@@ -1,164 +0,0 @@
|
||||
// Copyright 2021 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__DETAIL__SUBSCRIPTION_CALLBACK_TYPE_HELPER_HPP_
|
||||
#define RCLCPP__DETAIL__SUBSCRIPTION_CALLBACK_TYPE_HELPER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/function_traits.hpp"
|
||||
#include "rclcpp/message_info.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// Template metaprogramming helper used to resolve the callback argument into a std::function.
|
||||
/**
|
||||
* Sometimes the CallbackT is a std::function already, but it could also be a
|
||||
* function pointer, lambda, bind, or some variant of those.
|
||||
* In some cases, like a lambda where the arguments can be converted between one
|
||||
* another, e.g. std::function<void (shared_ptr<...>)> and
|
||||
* std::function<void (unique_ptr<...>)>, you need to make that not ambiguous
|
||||
* by checking the arguments independently using function traits rather than
|
||||
* rely on overloading the two std::function types.
|
||||
*
|
||||
* This issue, with the lambda's, can be demonstrated with this minimal program:
|
||||
*
|
||||
* #include <functional>
|
||||
* #include <memory>
|
||||
*
|
||||
* void f(std::function<void (std::shared_ptr<int>)>) {}
|
||||
* void f(std::function<void (std::unique_ptr<int>)>) {}
|
||||
*
|
||||
* int main() {
|
||||
* // Fails to compile with an "ambiguous call" error.
|
||||
* f([](std::shared_ptr<int>){});
|
||||
*
|
||||
* // Works.
|
||||
* std::function<void (std::shared_ptr<int>)> cb = [](std::shared_ptr<int>){};
|
||||
* f(cb);
|
||||
* }
|
||||
*
|
||||
* If this program ever starts working in a future version of C++, this class
|
||||
* may become redundant.
|
||||
*
|
||||
* This helper works by using SFINAE with rclcpp::function_traits::same_arguments<>
|
||||
* to narrow down the exact std::function<> type for the given CallbackT.
|
||||
*/
|
||||
template<typename MessageT, typename CallbackT, typename Enable = void>
|
||||
struct SubscriptionCallbackTypeHelper
|
||||
{
|
||||
using callback_type = typename rclcpp::function_traits::as_std_function<CallbackT>::type;
|
||||
};
|
||||
|
||||
template<typename MessageT, typename CallbackT>
|
||||
struct SubscriptionCallbackTypeHelper<
|
||||
MessageT,
|
||||
CallbackT,
|
||||
typename std::enable_if_t<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
CallbackT,
|
||||
std::function<void(std::shared_ptr<const MessageT>)>
|
||||
>::value
|
||||
>
|
||||
>
|
||||
{
|
||||
using callback_type = std::function<void (std::shared_ptr<const MessageT>)>;
|
||||
};
|
||||
|
||||
template<typename MessageT, typename CallbackT>
|
||||
struct SubscriptionCallbackTypeHelper<
|
||||
MessageT,
|
||||
CallbackT,
|
||||
typename std::enable_if_t<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
CallbackT,
|
||||
std::function<void(std::shared_ptr<const MessageT>, const rclcpp::MessageInfo &)>
|
||||
>::value
|
||||
>
|
||||
>
|
||||
{
|
||||
using callback_type =
|
||||
std::function<void (std::shared_ptr<const MessageT>, const rclcpp::MessageInfo &)>;
|
||||
};
|
||||
|
||||
template<typename MessageT, typename CallbackT>
|
||||
struct SubscriptionCallbackTypeHelper<
|
||||
MessageT,
|
||||
CallbackT,
|
||||
typename std::enable_if_t<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
CallbackT,
|
||||
std::function<void(const std::shared_ptr<const MessageT> &)>
|
||||
>::value
|
||||
>
|
||||
>
|
||||
{
|
||||
using callback_type = std::function<void (const std::shared_ptr<const MessageT> &)>;
|
||||
};
|
||||
|
||||
template<typename MessageT, typename CallbackT>
|
||||
struct SubscriptionCallbackTypeHelper<
|
||||
MessageT,
|
||||
CallbackT,
|
||||
typename std::enable_if_t<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
CallbackT,
|
||||
std::function<void(const std::shared_ptr<const MessageT> &, const rclcpp::MessageInfo &)>
|
||||
>::value
|
||||
>
|
||||
>
|
||||
{
|
||||
using callback_type =
|
||||
std::function<void (const std::shared_ptr<const MessageT> &, const rclcpp::MessageInfo &)>;
|
||||
};
|
||||
|
||||
template<typename MessageT, typename CallbackT>
|
||||
struct SubscriptionCallbackTypeHelper<
|
||||
MessageT,
|
||||
CallbackT,
|
||||
typename std::enable_if_t<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
CallbackT,
|
||||
std::function<void(std::shared_ptr<MessageT>)>
|
||||
>::value
|
||||
>
|
||||
>
|
||||
{
|
||||
using callback_type = std::function<void (std::shared_ptr<MessageT>)>;
|
||||
};
|
||||
|
||||
template<typename MessageT, typename CallbackT>
|
||||
struct SubscriptionCallbackTypeHelper<
|
||||
MessageT,
|
||||
CallbackT,
|
||||
typename std::enable_if_t<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
CallbackT,
|
||||
std::function<void(std::shared_ptr<MessageT>, const rclcpp::MessageInfo &)>
|
||||
>::value
|
||||
>
|
||||
>
|
||||
{
|
||||
using callback_type =
|
||||
std::function<void (std::shared_ptr<MessageT>, const rclcpp::MessageInfo &)>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DETAIL__SUBSCRIPTION_CALLBACK_TYPE_HELPER_HPP_
|
||||
@@ -38,14 +38,10 @@ public:
|
||||
*/
|
||||
Duration(int32_t seconds, uint32_t nanoseconds);
|
||||
|
||||
/// Construct duration from the specified nanoseconds.
|
||||
[[deprecated(
|
||||
"Use Duration::from_nanoseconds instead or std::chrono_literals. For example:"
|
||||
"rclcpp::Duration::from_nanoseconds(int64_variable);"
|
||||
"rclcpp::Duration(0ns);")]]
|
||||
// This constructor matches any numeric value - ints or floats.
|
||||
explicit Duration(rcl_duration_value_t nanoseconds);
|
||||
|
||||
/// Construct duration from the specified std::chrono::nanoseconds.
|
||||
// This constructor matches std::chrono::nanoseconds.
|
||||
explicit Duration(std::chrono::nanoseconds nanoseconds);
|
||||
|
||||
// This constructor matches any std::chrono value other than nanoseconds
|
||||
@@ -133,13 +129,6 @@ public:
|
||||
static Duration
|
||||
from_seconds(double seconds);
|
||||
|
||||
/// Create a duration object from an integer number representing nanoseconds
|
||||
static Duration
|
||||
from_nanoseconds(rcl_duration_value_t nanoseconds);
|
||||
|
||||
static Duration
|
||||
from_rmw_time(rmw_time_t duration);
|
||||
|
||||
/// Convert Duration into a std::chrono::Duration.
|
||||
template<class DurationT>
|
||||
DurationT
|
||||
@@ -154,8 +143,6 @@ public:
|
||||
|
||||
private:
|
||||
rcl_duration_t rcl_duration_;
|
||||
|
||||
Duration() = default;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -282,34 +282,6 @@ class ParameterModifiedInCallbackException : public std::runtime_error
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown when an uninitialized parameter is accessed.
|
||||
class ParameterUninitializedException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/// Construct an instance.
|
||||
/**
|
||||
* \param[in] name the name of the parameter.
|
||||
* \param[in] message custom exception message.
|
||||
*/
|
||||
explicit ParameterUninitializedException(const std::string & name)
|
||||
: std::runtime_error("parameter '" + name + "' is not initialized")
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown if the QoS overrides provided aren't valid.
|
||||
class InvalidQosOverridesException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if a QoS compatibility check fails.
|
||||
class QoSCheckCompatibleException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
} // namespace exceptions
|
||||
} // namespace rclcpp
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
@@ -30,9 +29,7 @@
|
||||
#include "rcl/guard_condition.h"
|
||||
#include "rcl/wait.h"
|
||||
|
||||
#include "rclcpp/context.hpp"
|
||||
#include "rclcpp/contexts/default_context.hpp"
|
||||
#include "rclcpp/guard_condition.hpp"
|
||||
#include "rclcpp/executor_options.hpp"
|
||||
#include "rclcpp/future_return_code.hpp"
|
||||
#include "rclcpp/memory_strategies.hpp"
|
||||
@@ -45,10 +42,6 @@
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
typedef std::map<rclcpp::CallbackGroup::WeakPtr,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::WeakPtr,
|
||||
std::owner_less<rclcpp::CallbackGroup::WeakPtr>> WeakCallbackGroupsToNodesMap;
|
||||
|
||||
// Forward declaration is used in convenience method signature.
|
||||
class Node;
|
||||
|
||||
@@ -83,118 +76,13 @@ public:
|
||||
virtual void
|
||||
spin() = 0;
|
||||
|
||||
/// Add a callback group to an executor.
|
||||
/**
|
||||
* An executor can have zero or more callback groups which provide work during `spin` functions.
|
||||
* When an executor attempts to add a callback group, the executor checks to see if it is already
|
||||
* associated with another executor, and if it has been, then an exception is thrown.
|
||||
* Otherwise, the callback group is added to the executor.
|
||||
*
|
||||
* Adding a callback group with this method does not associate its node with this executor
|
||||
* in any way
|
||||
*
|
||||
* \param[in] group_ptr a shared ptr that points to a callback group
|
||||
* \param[in] node_ptr a shared pointer that points to a node base interface
|
||||
* \param[in] notify True to trigger the interrupt guard condition during this function. If
|
||||
* the executor is blocked at the rmw layer while waiting for work and it is notified that a new
|
||||
* callback group was added, it will wake up.
|
||||
* \throw std::runtime_error if the callback group is associated to an executor
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
add_callback_group(
|
||||
rclcpp::CallbackGroup::SharedPtr group_ptr,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
bool notify = true);
|
||||
|
||||
/// Get callback groups that belong to executor.
|
||||
/**
|
||||
* This function returns a vector of weak pointers that point to callback groups that were
|
||||
* associated with the executor.
|
||||
* The callback groups associated with this executor may have been added with
|
||||
* `add_callback_group`, or added when a node was added to the executor with `add_node`, or
|
||||
* automatically added when it created by a node already associated with this executor and the
|
||||
* automatically_add_to_executor_with_node parameter was true.
|
||||
*
|
||||
* \return a vector of weak pointers that point to callback groups that are associated with
|
||||
* the executor
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual std::vector<rclcpp::CallbackGroup::WeakPtr>
|
||||
get_all_callback_groups();
|
||||
|
||||
/// Get callback groups that belong to executor.
|
||||
/**
|
||||
* This function returns a vector of weak pointers that point to callback groups that were
|
||||
* associated with the executor.
|
||||
* The callback groups associated with this executor have been added with
|
||||
* `add_callback_group`.
|
||||
*
|
||||
* \return a vector of weak pointers that point to callback groups that are associated with
|
||||
* the executor
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual std::vector<rclcpp::CallbackGroup::WeakPtr>
|
||||
get_manually_added_callback_groups();
|
||||
|
||||
/// Get callback groups that belong to executor.
|
||||
/**
|
||||
* This function returns a vector of weak pointers that point to callback groups that were
|
||||
* added from a node that is associated with the executor.
|
||||
* The callback groups are added when a node is added to the executor with `add_node`, or
|
||||
* automatically if they are created in the future by that node and have the
|
||||
* automatically_add_to_executor_with_node argument set to true.
|
||||
*
|
||||
* \return a vector of weak pointers that point to callback groups from a node associated with
|
||||
* the executor
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual std::vector<rclcpp::CallbackGroup::WeakPtr>
|
||||
get_automatically_added_callback_groups_from_nodes();
|
||||
|
||||
/// Remove a callback group from the executor.
|
||||
/**
|
||||
* The callback group is removed from and disassociated with the executor.
|
||||
* If the callback group removed was the last callback group from the node
|
||||
* that is associated with the executor, the interrupt guard condition
|
||||
* is triggered and node's guard condition is removed from the executor.
|
||||
*
|
||||
* This function only removes a callback group that was manually added with
|
||||
* rclcpp::Executor::add_callback_group.
|
||||
* To remove callback groups that were added from a node using
|
||||
* rclcpp::Executor::add_node, use rclcpp::Executor::remove_node instead.
|
||||
*
|
||||
* \param[in] group_ptr Shared pointer to the callback group to be added.
|
||||
* \param[in] notify True to trigger the interrupt guard condition during this function. If
|
||||
* the executor is blocked at the rmw layer while waiting for work and it is notified that a
|
||||
* callback group was removed, it will wake up.
|
||||
* \throw std::runtime_error if node is deleted before callback group
|
||||
* \throw std::runtime_error if the callback group is not associated with the executor
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
remove_callback_group(
|
||||
rclcpp::CallbackGroup::SharedPtr group_ptr,
|
||||
bool notify = true);
|
||||
|
||||
/// Add a node to the executor.
|
||||
/**
|
||||
* Nodes have associated callback groups, and this method adds any of those callback groups
|
||||
* to this executor which have their automatically_add_to_executor_with_node parameter true.
|
||||
* The node is also associated with the executor so that future callback groups which are
|
||||
* created on the node with the automatically_add_to_executor_with_node parameter set to true
|
||||
* are also automatically associated with this executor.
|
||||
*
|
||||
* Callback groups with the automatically_add_to_executor_with_node parameter set to false must
|
||||
* be manually added to an executor using the rclcpp::Executor::add_callback_group method.
|
||||
*
|
||||
* If a node is already associated with an executor, this method throws an exception.
|
||||
*
|
||||
* An executor can have zero or more nodes which provide work during `spin` functions.
|
||||
* \param[in] node_ptr Shared pointer to the node to be added.
|
||||
* \param[in] notify True to trigger the interrupt guard condition during this function. If
|
||||
* the executor is blocked at the rmw layer while waiting for work and it is notified that a new
|
||||
* node was added, it will wake up.
|
||||
* \throw std::runtime_error if a node is already associated to an executor
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
@@ -210,19 +98,10 @@ public:
|
||||
|
||||
/// Remove a node from the executor.
|
||||
/**
|
||||
* Any callback groups automatically added when this node was added with
|
||||
* rclcpp::Executor::add_node are automatically removed, and the node is no longer associated
|
||||
* with this executor.
|
||||
*
|
||||
* This also means that future callback groups created by the given node are no longer
|
||||
* automatically added to this executor.
|
||||
*
|
||||
* \param[in] node_ptr Shared pointer to the node to remove.
|
||||
* \param[in] notify True to trigger the interrupt guard condition and wake up the executor.
|
||||
* This is useful if the last node was removed from the executor while the executor was blocked
|
||||
* waiting for work in another thread, because otherwise the executor would never be notified.
|
||||
* \throw std::runtime_error if the node is not associated with an executor.
|
||||
* \throw std::runtime_error if the node is not associated with this executor.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
@@ -281,7 +160,7 @@ public:
|
||||
void
|
||||
spin_node_some(std::shared_ptr<rclcpp::Node> node);
|
||||
|
||||
/// Collect work once and execute all available work, optionally within a duration.
|
||||
/// Complete all available queued work without blocking.
|
||||
/**
|
||||
* This function can be overridden. The default implementation is suitable for a
|
||||
* single-threaded model of execution.
|
||||
@@ -296,23 +175,6 @@ public:
|
||||
virtual void
|
||||
spin_some(std::chrono::nanoseconds max_duration = std::chrono::nanoseconds(0));
|
||||
|
||||
/// Collect and execute work repeatedly within a duration or until no more work is available.
|
||||
/**
|
||||
* This function can be overridden. The default implementation is suitable for a
|
||||
* single-threaded model of execution.
|
||||
* Adding subscriptions, timers, services, etc. with blocking callbacks will cause this function
|
||||
* to block (which may have unintended consequences).
|
||||
* If the time that waitables take to be executed is longer than the period on which new waitables
|
||||
* become ready, this method will execute work repeatedly until `max_duration` has elapsed.
|
||||
*
|
||||
* \param[in] max_duration The maximum amount of time to spend executing work. Must be positive.
|
||||
* Note that spin_all() may take longer than this time as it only returns once max_duration has
|
||||
* been exceeded.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
spin_all(std::chrono::nanoseconds max_duration);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
spin_once(std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
|
||||
@@ -327,10 +189,10 @@ public:
|
||||
* code.
|
||||
* \return The return code, one of `SUCCESS`, `INTERRUPTED`, or `TIMEOUT`.
|
||||
*/
|
||||
template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
const FutureT & future,
|
||||
const std::shared_future<ResponseT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
// TODO(wjwwood): does not work recursively; can't call spin_node_until_future_complete
|
||||
@@ -408,10 +270,6 @@ protected:
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_some_impl(std::chrono::nanoseconds max_duration, bool exhaustive);
|
||||
|
||||
/// Find the next available executable and do the work associated with it.
|
||||
/**
|
||||
* \param[in] any_exec Union structure that can hold any executable type (timer, subscription,
|
||||
@@ -448,135 +306,57 @@ protected:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
get_node_by_group(
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes,
|
||||
rclcpp::CallbackGroup::SharedPtr group);
|
||||
|
||||
/// Return true if the node has been added to this executor.
|
||||
/**
|
||||
* \param[in] node_ptr a shared pointer that points to a node base interface
|
||||
* \return true if the node is associated with the executor, otherwise false
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
has_node(
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) const;
|
||||
get_node_by_group(rclcpp::CallbackGroup::SharedPtr group);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_timer(rclcpp::TimerBase::SharedPtr timer);
|
||||
|
||||
/// Add a callback group to an executor
|
||||
/**
|
||||
* \see rclcpp::Executor::add_callback_group
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
add_callback_group_to_map(
|
||||
rclcpp::CallbackGroup::SharedPtr group_ptr,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
WeakCallbackGroupsToNodesMap & weak_groups_to_nodes,
|
||||
bool notify = true) RCPPUTILS_TSA_REQUIRES(mutex_);
|
||||
|
||||
/// Remove a callback group from the executor.
|
||||
/**
|
||||
* \see rclcpp::Executor::remove_callback_group
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
remove_callback_group_from_map(
|
||||
rclcpp::CallbackGroup::SharedPtr group_ptr,
|
||||
WeakCallbackGroupsToNodesMap & weak_groups_to_nodes,
|
||||
bool notify = true) RCPPUTILS_TSA_REQUIRES(mutex_);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
get_next_ready_executable(AnyExecutable & any_executable);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
get_next_ready_executable_from_map(
|
||||
AnyExecutable & any_executable,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
get_next_executable(
|
||||
AnyExecutable & any_executable,
|
||||
std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
|
||||
|
||||
/// Add all callback groups that can be automatically added from associated nodes.
|
||||
/**
|
||||
* The executor, before collecting entities, verifies if any callback group from
|
||||
* nodes associated with the executor, which is not already associated to an executor,
|
||||
* can be automatically added to this executor.
|
||||
* This takes care of any callback group that has been added to a node but not explicitly added
|
||||
* to the executor.
|
||||
* It is important to note that in order for the callback groups to be automatically added to an
|
||||
* executor through this function, the node of the callback groups needs to have been added
|
||||
* through the `add_node` method.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
add_callback_groups_from_nodes_associated_to_executor() RCPPUTILS_TSA_REQUIRES(mutex_);
|
||||
|
||||
/// Spinning state, used to prevent multi threaded calls to spin and to cancel blocking spins.
|
||||
std::atomic_bool spinning;
|
||||
|
||||
/// Guard condition for signaling the rmw layer to wake up for special events.
|
||||
rcl_guard_condition_t interrupt_guard_condition_ = rcl_get_zero_initialized_guard_condition();
|
||||
|
||||
std::shared_ptr<rclcpp::GuardCondition> shutdown_guard_condition_;
|
||||
|
||||
/// Wait set for managing entities that the rmw layer waits on.
|
||||
rcl_wait_set_t wait_set_ = rcl_get_zero_initialized_wait_set();
|
||||
|
||||
// Mutex to protect the subsequent memory_strategy_.
|
||||
mutable std::mutex mutex_;
|
||||
std::mutex memory_strategy_mutex_;
|
||||
|
||||
/// The memory strategy: an interface for handling user-defined memory allocation strategies.
|
||||
memory_strategy::MemoryStrategy::SharedPtr
|
||||
memory_strategy_ RCPPUTILS_TSA_PT_GUARDED_BY(mutex_);
|
||||
memory_strategy::MemoryStrategy::SharedPtr memory_strategy_;
|
||||
|
||||
/// The context associated with this executor.
|
||||
std::shared_ptr<rclcpp::Context> context_;
|
||||
|
||||
RCLCPP_DISABLE_COPY(Executor)
|
||||
|
||||
std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
|
||||
std::list<const rcl_guard_condition_t *> guard_conditions_;
|
||||
|
||||
private:
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
void
|
||||
spin_once_impl(std::chrono::nanoseconds timeout);
|
||||
|
||||
typedef std::map<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr,
|
||||
const rcl_guard_condition_t *,
|
||||
std::owner_less<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>>
|
||||
WeakNodesToGuardConditionsMap;
|
||||
|
||||
/// maps nodes to guard conditions
|
||||
WeakNodesToGuardConditionsMap
|
||||
weak_nodes_to_guard_conditions_ RCPPUTILS_TSA_GUARDED_BY(mutex_);
|
||||
|
||||
/// maps callback groups associated to nodes
|
||||
WeakCallbackGroupsToNodesMap
|
||||
weak_groups_associated_with_executor_to_nodes_ RCPPUTILS_TSA_GUARDED_BY(mutex_);
|
||||
|
||||
/// maps callback groups to nodes associated with executor
|
||||
WeakCallbackGroupsToNodesMap
|
||||
weak_groups_to_nodes_associated_with_executor_ RCPPUTILS_TSA_GUARDED_BY(mutex_);
|
||||
|
||||
/// maps all callback groups to nodes
|
||||
WeakCallbackGroupsToNodesMap
|
||||
weak_groups_to_nodes_ RCPPUTILS_TSA_GUARDED_BY(mutex_);
|
||||
|
||||
/// nodes that are associated with the executor
|
||||
std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>
|
||||
weak_nodes_ RCPPUTILS_TSA_GUARDED_BY(mutex_);
|
||||
|
||||
/// shutdown callback handle registered to Context
|
||||
rclcpp::OnShutdownCallbackHandle shutdown_callback_handle_;
|
||||
};
|
||||
|
||||
namespace executor
|
||||
{
|
||||
|
||||
using Executor [[deprecated("use rclcpp::Executor instead")]] = rclcpp::Executor;
|
||||
|
||||
} // namespace executor
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXECUTOR_HPP_
|
||||
|
||||
@@ -38,6 +38,20 @@ struct ExecutorOptions
|
||||
size_t max_conditions;
|
||||
};
|
||||
|
||||
namespace executor
|
||||
{
|
||||
|
||||
using ExecutorArgs [[deprecated("use rclcpp::ExecutorOptions instead")]] = ExecutorOptions;
|
||||
|
||||
[[deprecated("use rclcpp::ExecutorOptions() instead")]]
|
||||
inline
|
||||
rclcpp::ExecutorOptions
|
||||
create_default_executor_arguments()
|
||||
{
|
||||
return rclcpp::ExecutorOptions();
|
||||
}
|
||||
|
||||
} // namespace executor
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXECUTOR_OPTIONS_HPP_
|
||||
|
||||
@@ -66,12 +66,12 @@ using rclcpp::executors::SingleThreadedExecutor;
|
||||
* If the time spent inside the blocking loop exceeds this timeout, return a `TIMEOUT` return code.
|
||||
* \return The return code, one of `SUCCESS`, `INTERRUPTED`, or `TIMEOUT`.
|
||||
*/
|
||||
template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
rclcpp::FutureReturnCode
|
||||
spin_node_until_future_complete(
|
||||
rclcpp::Executor & executor,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
const FutureT & future,
|
||||
const std::shared_future<ResponseT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
// TODO(wjwwood): does not work recursively; can't call spin_node_until_future_complete
|
||||
@@ -82,13 +82,13 @@ spin_node_until_future_complete(
|
||||
return retcode;
|
||||
}
|
||||
|
||||
template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeRepT = int64_t,
|
||||
template<typename NodeT = rclcpp::Node, typename ResponseT, typename TimeRepT = int64_t,
|
||||
typename TimeT = std::milli>
|
||||
rclcpp::FutureReturnCode
|
||||
spin_node_until_future_complete(
|
||||
rclcpp::Executor & executor,
|
||||
std::shared_ptr<NodeT> node_ptr,
|
||||
const FutureT & future,
|
||||
const std::shared_future<ResponseT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
return rclcpp::executors::spin_node_until_future_complete(
|
||||
@@ -104,7 +104,7 @@ template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::mi
|
||||
rclcpp::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
const FutureT & future,
|
||||
const std::shared_future<FutureT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
@@ -116,7 +116,7 @@ template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeRepT = in
|
||||
rclcpp::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
std::shared_ptr<NodeT> node_ptr,
|
||||
const FutureT & future,
|
||||
const std::shared_future<FutureT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
return rclcpp::spin_until_future_complete(node_ptr->get_node_base_interface(), future, timeout);
|
||||
|
||||
@@ -82,12 +82,17 @@ protected:
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(MultiThreadedExecutor)
|
||||
|
||||
detail::MutexTwoPriorities wait_mutex_;
|
||||
std::mutex wait_mutex_; // Unused. Leave it for ABI compatibility.
|
||||
size_t number_of_threads_;
|
||||
bool yield_before_execute_;
|
||||
std::chrono::nanoseconds next_exec_timeout_;
|
||||
|
||||
std::set<TimerBase::SharedPtr> scheduled_timers_;
|
||||
static std::unordered_map<MultiThreadedExecutor *,
|
||||
std::shared_ptr<detail::MutexTwoPriorities>> wait_mutex_set_;
|
||||
static std::mutex shared_wait_mutex_;
|
||||
// These variables are declared as static variables for ABI-compatibiliity.
|
||||
// And they mimic member variables needed to backport from master.
|
||||
};
|
||||
|
||||
} // namespace executors
|
||||
|
||||
@@ -17,9 +17,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/guard_condition.h"
|
||||
#include "rcl/wait.h"
|
||||
@@ -34,9 +32,6 @@ namespace rclcpp
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
typedef std::map<rclcpp::CallbackGroup::WeakPtr,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::WeakPtr,
|
||||
std::owner_less<rclcpp::CallbackGroup::WeakPtr>> WeakCallbackGroupsToNodesMap;
|
||||
|
||||
class StaticExecutorEntitiesCollector final
|
||||
: public rclcpp::Waitable,
|
||||
@@ -64,37 +59,39 @@ public:
|
||||
void
|
||||
init(
|
||||
rcl_wait_set_t * p_wait_set,
|
||||
rclcpp::memory_strategy::MemoryStrategy::SharedPtr memory_strategy,
|
||||
rclcpp::memory_strategy::MemoryStrategy::SharedPtr & memory_strategy,
|
||||
rcl_guard_condition_t * executor_guard_condition);
|
||||
|
||||
/// Finalize StaticExecutorEntitiesCollector to clear resources
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
is_init() {return initialized_;}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
fini();
|
||||
|
||||
/// Execute the waitable.
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
execute(std::shared_ptr<void> & data) override;
|
||||
execute() override;
|
||||
|
||||
/// Take the data so that it can be consumed with `execute`.
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
fill_memory_strategy();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
fill_executable_list();
|
||||
|
||||
/// Function to reallocate space for entities in the wait set.
|
||||
/**
|
||||
* For `StaticExecutorEntitiesCollector`, this always return `nullptr`.
|
||||
* \sa rclcpp::Waitable::take_data()
|
||||
* \throws std::runtime_error if wait set couldn't be cleared or resized.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<void>
|
||||
take_data() override;
|
||||
void
|
||||
prepare_wait_set();
|
||||
|
||||
/// Function to add_handles_to_wait_set and wait for work and
|
||||
/**
|
||||
* block until the wait set is ready or until the timeout has been exceeded.
|
||||
* \throws std::runtime_error if wait set couldn't be cleared or filled.
|
||||
* \throws any rcl errors from rcl_wait, \see rclcpp::exceptions::throw_from_rcl_error()
|
||||
* \throws any rcl errors from rcl_wait, \sa rclcpp::exceptions::throw_from_rcl_error()
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
@@ -111,58 +108,17 @@ public:
|
||||
size_t
|
||||
get_number_of_ready_guard_conditions() override;
|
||||
|
||||
/// Add a callback group to an executor.
|
||||
/**
|
||||
* \see rclcpp::Executor::add_callback_group
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
add_callback_group(
|
||||
rclcpp::CallbackGroup::SharedPtr group_ptr,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
|
||||
|
||||
/// Add a callback group to an executor.
|
||||
/**
|
||||
* \see rclcpp::Executor::add_callback_group
|
||||
* \return boolean whether the node from the callback group is new
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
add_callback_group(
|
||||
rclcpp::CallbackGroup::SharedPtr group_ptr,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
|
||||
/// Remove a callback group from the executor.
|
||||
/**
|
||||
* \see rclcpp::Executor::remove_callback_group
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
remove_callback_group(
|
||||
rclcpp::CallbackGroup::SharedPtr group_ptr);
|
||||
|
||||
/// Remove a callback group from the executor.
|
||||
/**
|
||||
* \see rclcpp::Executor::remove_callback_group_from_map
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
remove_callback_group_from_map(
|
||||
rclcpp::CallbackGroup::SharedPtr group_ptr,
|
||||
WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
|
||||
/**
|
||||
* \see rclcpp::Executor::add_node()
|
||||
* \sa rclcpp::Executor::add_node()
|
||||
* \throw std::runtime_error if node was already added
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
void
|
||||
add_node(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
|
||||
|
||||
/**
|
||||
* \see rclcpp::Executor::remove_node()
|
||||
* \sa rclcpp::Executor::remove_node()
|
||||
* \throw std::runtime_error if no guard condition is associated with node.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
@@ -170,26 +126,6 @@ public:
|
||||
remove_node(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::CallbackGroup::WeakPtr>
|
||||
get_all_callback_groups();
|
||||
|
||||
/// Get callback groups that belong to executor.
|
||||
/**
|
||||
* \see rclcpp::Executor::get_manually_added_callback_groups()
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::CallbackGroup::WeakPtr>
|
||||
get_manually_added_callback_groups();
|
||||
|
||||
/// Get callback groups that belong to executor.
|
||||
/**
|
||||
* \see rclcpp::Executor::get_automatically_added_callback_groups_from_nodes()
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::CallbackGroup::WeakPtr>
|
||||
get_automatically_added_callback_groups_from_nodes();
|
||||
|
||||
/// Complete all available queued work without blocking.
|
||||
/**
|
||||
* This function checks if after the guard condition was triggered
|
||||
@@ -286,55 +222,12 @@ public:
|
||||
get_waitable(size_t i) {return exec_list_.waitable[i];}
|
||||
|
||||
private:
|
||||
/// Function to reallocate space for entities in the wait set.
|
||||
/**
|
||||
* \throws std::runtime_error if wait set couldn't be cleared or resized.
|
||||
*/
|
||||
void
|
||||
prepare_wait_set();
|
||||
|
||||
void
|
||||
fill_executable_list();
|
||||
|
||||
void
|
||||
fill_memory_strategy();
|
||||
|
||||
/// Return true if the node belongs to the collector
|
||||
/**
|
||||
* \param[in] group_ptr a node base interface shared pointer
|
||||
* \return boolean whether a node belongs the collector
|
||||
*/
|
||||
bool
|
||||
has_node(
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) const;
|
||||
|
||||
/// Add all callback groups that can be automatically added by any executor
|
||||
/// and is not already associated with an executor from nodes
|
||||
/// that are associated with executor
|
||||
/**
|
||||
* \see rclcpp::Executor::add_callback_groups_from_nodes_associated_to_executor()
|
||||
*/
|
||||
void
|
||||
add_callback_groups_from_nodes_associated_to_executor();
|
||||
|
||||
void
|
||||
fill_executable_list_from_map(const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
/// Nodes guard conditions which trigger this waitable
|
||||
std::list<const rcl_guard_condition_t *> guard_conditions_;
|
||||
|
||||
/// Memory strategy: an interface for handling user-defined memory allocation strategies.
|
||||
rclcpp::memory_strategy::MemoryStrategy::SharedPtr memory_strategy_;
|
||||
|
||||
// maps callback groups to nodes.
|
||||
WeakCallbackGroupsToNodesMap weak_groups_associated_with_executor_to_nodes_;
|
||||
// maps callback groups to nodes.
|
||||
WeakCallbackGroupsToNodesMap weak_groups_to_nodes_associated_with_executor_;
|
||||
|
||||
typedef std::map<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr,
|
||||
const rcl_guard_condition_t *,
|
||||
std::owner_less<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>>
|
||||
WeakNodesToGuardConditionsMap;
|
||||
WeakNodesToGuardConditionsMap weak_nodes_to_guard_conditions_;
|
||||
|
||||
/// List of weak nodes registered in the static executor
|
||||
std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
|
||||
|
||||
@@ -343,9 +236,6 @@ private:
|
||||
|
||||
/// Executable list: timers, subscribers, clients, services and waitables
|
||||
rclcpp::experimental::ExecutableList exec_list_;
|
||||
|
||||
/// Bool to check if the entities collector has been initialized
|
||||
bool initialized_ = false;
|
||||
};
|
||||
|
||||
} // namespace executors
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#ifndef RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_
|
||||
#define RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_
|
||||
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
@@ -79,66 +78,15 @@ 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 or no more work 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;
|
||||
|
||||
/// 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;
|
||||
|
||||
/// Add a node to the executor.
|
||||
/**
|
||||
* \sa rclcpp::Executor::add_node
|
||||
* An executor can have zero or more nodes which provide work during `spin` functions.
|
||||
* \param[in] node_ptr Shared pointer to the node to be added.
|
||||
* \param[in] notify True to trigger the interrupt guard condition during this function. If
|
||||
* the executor is blocked at the rmw layer while waiting for work and it is notified that a new
|
||||
* node was added, it will wake up.
|
||||
* \throw std::runtime_error if node was already added or if rcl_trigger_guard_condition
|
||||
* return an error
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
@@ -148,7 +96,8 @@ public:
|
||||
|
||||
/// Convenience function which takes Node and forwards NodeBaseInterface.
|
||||
/**
|
||||
* \sa rclcpp::StaticSingleThreadedExecutor::add_node
|
||||
* \throw std::runtime_error if node was already added or if rcl_trigger_guard_condition
|
||||
* returns an error
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
@@ -156,7 +105,11 @@ public:
|
||||
|
||||
/// Remove a node from the executor.
|
||||
/**
|
||||
* \sa rclcpp::Executor::remove_node
|
||||
* \param[in] node_ptr Shared pointer to the node to remove.
|
||||
* \param[in] notify True to trigger the interrupt guard condition and wake up the executor.
|
||||
* This is useful if the last node was removed from the executor while the executor was blocked
|
||||
* waiting for work in another thread, because otherwise the executor would never be notified.
|
||||
* \throw std::runtime_error if rcl_trigger_guard_condition returns an error
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
@@ -166,49 +119,87 @@ public:
|
||||
|
||||
/// Convenience function which takes Node and forwards NodeBaseInterface.
|
||||
/**
|
||||
* \sa rclcpp::Executor::remove_node
|
||||
* \throw std::runtime_error if rcl_trigger_guard_condition returns an error
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::CallbackGroup::WeakPtr>
|
||||
get_all_callback_groups() override;
|
||||
|
||||
/// Get callback groups that belong to executor.
|
||||
/// Spin (blocking) until the future is complete, it times out waiting, or rclcpp is interrupted.
|
||||
/**
|
||||
* \sa rclcpp::Executor::get_manually_added_callback_groups()
|
||||
* \param[in] future The future to wait on. If this function returns SUCCESS, the future can be
|
||||
* accessed without blocking (though it may still throw an exception).
|
||||
* \param[in] timeout Optional timeout parameter, which gets passed to
|
||||
* Executor::execute_ready_executables.
|
||||
* `-1` is block forever, `0` is non-blocking.
|
||||
* 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`.
|
||||
*
|
||||
* Example usage:
|
||||
* rclcpp::executors::StaticSingleThreadedExecutor exec;
|
||||
* // ... other part of code like creating node
|
||||
* // define future
|
||||
* exec.add_node(node);
|
||||
* exec.spin_until_future_complete(future);
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::CallbackGroup::WeakPtr>
|
||||
get_manually_added_callback_groups() override;
|
||||
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
rclcpp::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
std::shared_future<ResponseT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
std::future_status status = future.wait_for(std::chrono::seconds(0));
|
||||
if (status == std::future_status::ready) {
|
||||
return rclcpp::FutureReturnCode::SUCCESS;
|
||||
}
|
||||
|
||||
/// 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;
|
||||
auto end_time = std::chrono::steady_clock::now();
|
||||
std::chrono::nanoseconds timeout_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
timeout);
|
||||
if (timeout_ns > std::chrono::nanoseconds::zero()) {
|
||||
end_time += timeout_ns;
|
||||
}
|
||||
std::chrono::nanoseconds timeout_left = timeout_ns;
|
||||
|
||||
entities_collector_->init(&wait_set_, memory_strategy_, &interrupt_guard_condition_);
|
||||
RCLCPP_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
while (rclcpp::ok(this->context_)) {
|
||||
// Do one set of work.
|
||||
entities_collector_->refresh_wait_set(timeout_left);
|
||||
execute_ready_executables();
|
||||
// Check if the future is set, return SUCCESS if it is.
|
||||
status = future.wait_for(std::chrono::seconds(0));
|
||||
if (status == std::future_status::ready) {
|
||||
return rclcpp::FutureReturnCode::SUCCESS;
|
||||
}
|
||||
// If the original timeout is < 0, then this is blocking, never TIMEOUT.
|
||||
if (timeout_ns < std::chrono::nanoseconds::zero()) {
|
||||
continue;
|
||||
}
|
||||
// Otherwise check if we still have time to wait, return TIMEOUT if not.
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
if (now >= end_time) {
|
||||
return rclcpp::FutureReturnCode::TIMEOUT;
|
||||
}
|
||||
// Subtract the elapsed time from the original timeout.
|
||||
timeout_left = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - now);
|
||||
}
|
||||
|
||||
// The future did not complete before ok() returned false, return INTERRUPTED.
|
||||
return rclcpp::FutureReturnCode::INTERRUPTED;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Check which executables in ExecutableList struct are ready from wait_set and execute them.
|
||||
/**
|
||||
* @brief Executes ready executables from wait set.
|
||||
* @param spin_once if true executes only the first ready executable.
|
||||
* @return true if any executable was ready.
|
||||
* \param[in] exec_list Structure that can hold subscriptionbases, timerbases, etc
|
||||
* \param[in] timeout Optional timeout parameter.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
execute_ready_executables(bool spin_once = false);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_some_impl(std::chrono::nanoseconds max_duration, bool exhaustive);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_once_impl(std::chrono::nanoseconds timeout) override;
|
||||
execute_ready_executables();
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(StaticSingleThreadedExecutor)
|
||||
|
||||
@@ -37,10 +37,6 @@ namespace experimental
|
||||
namespace buffers
|
||||
{
|
||||
|
||||
/// Store elements in a fixed-size, FIFO buffer
|
||||
/**
|
||||
* All public member functions are thread-safe.
|
||||
*/
|
||||
template<typename BufferT>
|
||||
class RingBufferImplementation : public BufferImplementationBase<BufferT>
|
||||
{
|
||||
@@ -59,125 +55,55 @@ public:
|
||||
|
||||
virtual ~RingBufferImplementation() {}
|
||||
|
||||
/// Add a new element to store in the ring buffer
|
||||
/**
|
||||
* This member function is thread-safe.
|
||||
*
|
||||
* \param request the element to be stored in the ring buffer
|
||||
*/
|
||||
void enqueue(BufferT request)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
write_index_ = next_(write_index_);
|
||||
write_index_ = next(write_index_);
|
||||
ring_buffer_[write_index_] = std::move(request);
|
||||
|
||||
if (is_full_()) {
|
||||
read_index_ = next_(read_index_);
|
||||
if (is_full()) {
|
||||
read_index_ = next(read_index_);
|
||||
} else {
|
||||
size_++;
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the oldest element from ring buffer
|
||||
/**
|
||||
* This member function is thread-safe.
|
||||
*
|
||||
* \return the element that is being removed from the ring buffer
|
||||
*/
|
||||
BufferT dequeue()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
if (!has_data_()) {
|
||||
if (!has_data()) {
|
||||
RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Calling dequeue on empty intra-process buffer");
|
||||
throw std::runtime_error("Calling dequeue on empty intra-process buffer");
|
||||
}
|
||||
|
||||
auto request = std::move(ring_buffer_[read_index_]);
|
||||
read_index_ = next_(read_index_);
|
||||
read_index_ = next(read_index_);
|
||||
|
||||
size_--;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
/// Get the next index value for the ring buffer
|
||||
/**
|
||||
* This member function is thread-safe.
|
||||
*
|
||||
* \param val the current index value
|
||||
* \return the next index value
|
||||
*/
|
||||
inline size_t next(size_t val)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return next_(val);
|
||||
return (val + 1) % capacity_;
|
||||
}
|
||||
|
||||
/// Get if the ring buffer has at least one element stored
|
||||
/**
|
||||
* This member function is thread-safe.
|
||||
*
|
||||
* \return `true` if there is data and `false` otherwise
|
||||
*/
|
||||
inline bool has_data() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return has_data_();
|
||||
return size_ != 0;
|
||||
}
|
||||
|
||||
/// Get if the size of the buffer is equal to its capacity
|
||||
/**
|
||||
* This member function is thread-safe.
|
||||
*
|
||||
* \return `true` if the size of the buffer is equal is capacity
|
||||
* and `false` otherwise
|
||||
*/
|
||||
inline bool is_full() const
|
||||
inline bool is_full()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return is_full_();
|
||||
return size_ == capacity_;
|
||||
}
|
||||
|
||||
void clear() {}
|
||||
|
||||
private:
|
||||
/// Get the next index value for the ring buffer
|
||||
/**
|
||||
* This member function is not thread-safe.
|
||||
*
|
||||
* \param val the current index value
|
||||
* \return the next index value
|
||||
*/
|
||||
inline size_t next_(size_t val)
|
||||
{
|
||||
return (val + 1) % capacity_;
|
||||
}
|
||||
|
||||
/// Get if the ring buffer has at least one element stored
|
||||
/**
|
||||
* This member function is not thread-safe.
|
||||
*
|
||||
* \return `true` if there is data and `false` otherwise
|
||||
*/
|
||||
inline bool has_data_() const
|
||||
{
|
||||
return size_ != 0;
|
||||
}
|
||||
|
||||
/// Get if the size of the buffer is equal to its capacity
|
||||
/**
|
||||
* This member function is not thread-safe.
|
||||
*
|
||||
* \return `true` if the size of the buffer is equal is capacity
|
||||
* and `false` otherwise
|
||||
*/
|
||||
inline bool is_full_() const
|
||||
{
|
||||
return size_ == capacity_;
|
||||
}
|
||||
|
||||
size_t capacity_;
|
||||
|
||||
std::vector<BufferT> ring_buffer_;
|
||||
@@ -186,7 +112,7 @@ private:
|
||||
size_t read_index_;
|
||||
size_t size_;
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
std::mutex mutex_;
|
||||
};
|
||||
|
||||
} // namespace buffers
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "rclcpp/experimental/buffers/intra_process_buffer.hpp"
|
||||
#include "rclcpp/experimental/buffers/ring_buffer_implementation.hpp"
|
||||
#include "rclcpp/intra_process_buffer_type.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
@@ -38,13 +37,13 @@ template<
|
||||
typename rclcpp::experimental::buffers::IntraProcessBuffer<MessageT, Alloc, Deleter>::UniquePtr
|
||||
create_intra_process_buffer(
|
||||
IntraProcessBufferType buffer_type,
|
||||
const rclcpp::QoS & qos,
|
||||
rmw_qos_profile_t qos,
|
||||
std::shared_ptr<Alloc> allocator)
|
||||
{
|
||||
using MessageSharedPtr = std::shared_ptr<const MessageT>;
|
||||
using MessageUniquePtr = std::unique_ptr<MessageT, Deleter>;
|
||||
|
||||
size_t buffer_size = qos.depth();
|
||||
size_t buffer_size = qos.depth;
|
||||
|
||||
using rclcpp::experimental::buffers::IntraProcessBuffer;
|
||||
typename IntraProcessBuffer<MessageT, Alloc, Deleter>::UniquePtr buffer;
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "rclcpp/allocator/allocator_deleter.hpp"
|
||||
#include "rclcpp/experimental/subscription_intra_process.hpp"
|
||||
#include "rclcpp/experimental/subscription_intra_process_base.hpp"
|
||||
#include "rclcpp/experimental/subscription_intra_process_buffer.hpp"
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
@@ -182,7 +181,7 @@ public:
|
||||
do_intra_process_publish(
|
||||
uint64_t intra_process_publisher_id,
|
||||
std::unique_ptr<MessageT, Deleter> message,
|
||||
typename allocator::AllocRebind<MessageT, Alloc>::allocator_type & allocator)
|
||||
std::shared_ptr<typename allocator::AllocRebind<MessageT, Alloc>::allocator_type> allocator)
|
||||
{
|
||||
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
|
||||
using MessageAllocatorT = typename MessageAllocTraits::allocator_type;
|
||||
@@ -209,7 +208,7 @@ public:
|
||||
sub_ids.take_shared_subscriptions.size() <= 1)
|
||||
{
|
||||
// There is at maximum 1 buffer that does not require ownership.
|
||||
// So this case is equivalent to all the buffers requiring ownership
|
||||
// So we this case is equivalent to all the buffers requiring ownership
|
||||
|
||||
// Merge the two vector of ids into a unique one
|
||||
std::vector<uint64_t> concatenated_vector(sub_ids.take_shared_subscriptions);
|
||||
@@ -227,7 +226,7 @@ public:
|
||||
{
|
||||
// Construct a new shared pointer from the message
|
||||
// for the buffers that do not require ownership
|
||||
auto shared_msg = std::allocate_shared<MessageT, MessageAllocatorT>(allocator, *message);
|
||||
auto shared_msg = std::allocate_shared<MessageT, MessageAllocatorT>(*allocator, *message);
|
||||
|
||||
this->template add_shared_msg_to_buffers<MessageT, Alloc, Deleter>(
|
||||
shared_msg, sub_ids.take_shared_subscriptions);
|
||||
@@ -244,7 +243,7 @@ public:
|
||||
do_intra_process_publish_and_return_shared(
|
||||
uint64_t intra_process_publisher_id,
|
||||
std::unique_ptr<MessageT, Deleter> message,
|
||||
typename allocator::AllocRebind<MessageT, Alloc>::allocator_type & allocator)
|
||||
std::shared_ptr<typename allocator::AllocRebind<MessageT, Alloc>::allocator_type> allocator)
|
||||
{
|
||||
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
|
||||
using MessageAllocatorT = typename MessageAllocTraits::allocator_type;
|
||||
@@ -272,7 +271,7 @@ public:
|
||||
} else {
|
||||
// Construct a new shared pointer from the message for the buffers that
|
||||
// do not require ownership and to return.
|
||||
auto shared_msg = std::allocate_shared<MessageT, MessageAllocatorT>(allocator, *message);
|
||||
auto shared_msg = std::allocate_shared<MessageT, MessageAllocatorT>(*allocator, *message);
|
||||
|
||||
if (!sub_ids.take_shared_subscriptions.empty()) {
|
||||
this->template add_shared_msg_to_buffers<MessageT, Alloc, Deleter>(
|
||||
@@ -305,6 +304,25 @@ public:
|
||||
get_subscription_intra_process(uint64_t intra_process_subscription_id);
|
||||
|
||||
private:
|
||||
struct SubscriptionInfo
|
||||
{
|
||||
SubscriptionInfo() = default;
|
||||
|
||||
rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr subscription;
|
||||
rmw_qos_profile_t qos;
|
||||
const char * topic_name;
|
||||
bool use_take_shared_method;
|
||||
};
|
||||
|
||||
struct PublisherInfo
|
||||
{
|
||||
PublisherInfo() = default;
|
||||
|
||||
rclcpp::PublisherBase::WeakPtr publisher;
|
||||
rmw_qos_profile_t qos;
|
||||
const char * topic_name;
|
||||
};
|
||||
|
||||
struct SplittedSubscriptions
|
||||
{
|
||||
std::vector<uint64_t> take_shared_subscriptions;
|
||||
@@ -312,10 +330,10 @@ private:
|
||||
};
|
||||
|
||||
using SubscriptionMap =
|
||||
std::unordered_map<uint64_t, rclcpp::experimental::SubscriptionIntraProcessBase::WeakPtr>;
|
||||
std::unordered_map<uint64_t, SubscriptionInfo>;
|
||||
|
||||
using PublisherMap =
|
||||
std::unordered_map<uint64_t, rclcpp::PublisherBase::WeakPtr>;
|
||||
std::unordered_map<uint64_t, PublisherInfo>;
|
||||
|
||||
using PublisherToSubscriptionIdsMap =
|
||||
std::unordered_map<uint64_t, SplittedSubscriptions>;
|
||||
@@ -331,9 +349,7 @@ private:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
can_communicate(
|
||||
rclcpp::PublisherBase::SharedPtr pub,
|
||||
rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr sub) const;
|
||||
can_communicate(PublisherInfo pub_info, SubscriptionInfo sub_info) const;
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
@@ -349,23 +365,19 @@ private:
|
||||
if (subscription_it == subscriptions_.end()) {
|
||||
throw std::runtime_error("subscription has unexpectedly gone out of scope");
|
||||
}
|
||||
auto subscription_base = subscription_it->second.lock();
|
||||
if (subscription_base) {
|
||||
auto subscription = std::dynamic_pointer_cast<
|
||||
rclcpp::experimental::SubscriptionIntraProcessBuffer<MessageT, Alloc, Deleter>
|
||||
>(subscription_base);
|
||||
if (nullptr == subscription) {
|
||||
throw std::runtime_error(
|
||||
"failed to dynamic cast SubscriptionIntraProcessBase to "
|
||||
"SubscriptionIntraProcessBuffer<MessageT, Alloc, Deleter>, which "
|
||||
"can happen when the publisher and subscription use different "
|
||||
"allocator types, which is not supported");
|
||||
}
|
||||
auto subscription_base = subscription_it->second.subscription;
|
||||
|
||||
subscription->provide_intra_process_message(message);
|
||||
} else {
|
||||
subscriptions_.erase(id);
|
||||
auto subscription = std::dynamic_pointer_cast<
|
||||
rclcpp::experimental::SubscriptionIntraProcess<MessageT, Alloc, Deleter>
|
||||
>(subscription_base);
|
||||
if (nullptr == subscription) {
|
||||
throw std::runtime_error(
|
||||
"failed to dynamic cast SubscriptionIntraProcessBase to "
|
||||
"SubscriptionIntraProcess<MessageT, Alloc, Deleter>, which "
|
||||
"can happen when the publisher and subscription use different "
|
||||
"allocator types, which is not supported");
|
||||
}
|
||||
subscription->provide_intra_process_message(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,7 +389,7 @@ private:
|
||||
add_owned_msg_to_buffers(
|
||||
std::unique_ptr<MessageT, Deleter> message,
|
||||
std::vector<uint64_t> subscription_ids,
|
||||
typename allocator::AllocRebind<MessageT, Alloc>::allocator_type & allocator)
|
||||
std::shared_ptr<typename allocator::AllocRebind<MessageT, Alloc>::allocator_type> allocator)
|
||||
{
|
||||
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
|
||||
using MessageUniquePtr = std::unique_ptr<MessageT, Deleter>;
|
||||
@@ -387,34 +399,31 @@ private:
|
||||
if (subscription_it == subscriptions_.end()) {
|
||||
throw std::runtime_error("subscription has unexpectedly gone out of scope");
|
||||
}
|
||||
auto subscription_base = subscription_it->second.lock();
|
||||
if (subscription_base) {
|
||||
auto subscription = std::dynamic_pointer_cast<
|
||||
rclcpp::experimental::SubscriptionIntraProcessBuffer<MessageT, Alloc, Deleter>
|
||||
>(subscription_base);
|
||||
if (nullptr == subscription) {
|
||||
throw std::runtime_error(
|
||||
"failed to dynamic cast SubscriptionIntraProcessBase to "
|
||||
"SubscriptionIntraProcessBuffer<MessageT, Alloc, Deleter>, which "
|
||||
"can happen when the publisher and subscription use different "
|
||||
"allocator types, which is not supported");
|
||||
}
|
||||
auto subscription_base = subscription_it->second.subscription;
|
||||
|
||||
if (std::next(it) == subscription_ids.end()) {
|
||||
// If this is the last subscription, give up ownership
|
||||
subscription->provide_intra_process_message(std::move(message));
|
||||
} else {
|
||||
// Copy the message since we have additional subscriptions to serve
|
||||
MessageUniquePtr copy_message;
|
||||
Deleter deleter = message.get_deleter();
|
||||
auto ptr = MessageAllocTraits::allocate(allocator, 1);
|
||||
MessageAllocTraits::construct(allocator, ptr, *message);
|
||||
copy_message = MessageUniquePtr(ptr, deleter);
|
||||
auto subscription = std::dynamic_pointer_cast<
|
||||
rclcpp::experimental::SubscriptionIntraProcess<MessageT, Alloc, Deleter>
|
||||
>(subscription_base);
|
||||
if (nullptr == subscription) {
|
||||
throw std::runtime_error(
|
||||
"failed to dynamic cast SubscriptionIntraProcessBase to "
|
||||
"SubscriptionIntraProcess<MessageT, Alloc, Deleter>, which "
|
||||
"can happen when the publisher and subscription use different "
|
||||
"allocator types, which is not supported");
|
||||
}
|
||||
|
||||
subscription->provide_intra_process_message(std::move(copy_message));
|
||||
}
|
||||
if (std::next(it) == subscription_ids.end()) {
|
||||
// If this is the last subscription, give up ownership
|
||||
subscription->provide_intra_process_message(std::move(message));
|
||||
} else {
|
||||
subscriptions_.erase(subscription_it);
|
||||
// Copy the message since we have additional subscriptions to serve
|
||||
MessageUniquePtr copy_message;
|
||||
Deleter deleter = message.get_deleter();
|
||||
auto ptr = MessageAllocTraits::allocate(*allocator.get(), 1);
|
||||
MessageAllocTraits::construct(*allocator.get(), ptr, *message);
|
||||
copy_message = MessageUniquePtr(ptr, deleter);
|
||||
|
||||
subscription->provide_intra_process_message(std::move(copy_message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
#include <rmw/rmw.h>
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@@ -30,8 +28,6 @@
|
||||
#include "rclcpp/experimental/buffers/intra_process_buffer.hpp"
|
||||
#include "rclcpp/experimental/create_intra_process_buffer.hpp"
|
||||
#include "rclcpp/experimental/subscription_intra_process_base.hpp"
|
||||
#include "rclcpp/experimental/subscription_intra_process_buffer.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/waitable.hpp"
|
||||
#include "tracetools/tracetools.h"
|
||||
@@ -46,47 +42,58 @@ template<
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>,
|
||||
typename CallbackMessageT = MessageT>
|
||||
class SubscriptionIntraProcess
|
||||
: public SubscriptionIntraProcessBuffer<
|
||||
MessageT,
|
||||
Alloc,
|
||||
Deleter
|
||||
>
|
||||
class SubscriptionIntraProcess : public SubscriptionIntraProcessBase
|
||||
{
|
||||
using SubscriptionIntraProcessBufferT = SubscriptionIntraProcessBuffer<
|
||||
MessageT,
|
||||
Alloc,
|
||||
Deleter
|
||||
>;
|
||||
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(SubscriptionIntraProcess)
|
||||
|
||||
using MessageAllocTraits = typename SubscriptionIntraProcessBufferT::MessageAllocTraits;
|
||||
using MessageAlloc = typename SubscriptionIntraProcessBufferT::MessageAlloc;
|
||||
using ConstMessageSharedPtr = typename SubscriptionIntraProcessBufferT::ConstMessageSharedPtr;
|
||||
using MessageUniquePtr = typename SubscriptionIntraProcessBufferT::MessageUniquePtr;
|
||||
using BufferUniquePtr = typename SubscriptionIntraProcessBufferT::BufferUniquePtr;
|
||||
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
|
||||
using MessageAlloc = typename MessageAllocTraits::allocator_type;
|
||||
using ConstMessageSharedPtr = std::shared_ptr<const MessageT>;
|
||||
using MessageUniquePtr = std::unique_ptr<MessageT, Deleter>;
|
||||
|
||||
using BufferUniquePtr = typename rclcpp::experimental::buffers::IntraProcessBuffer<
|
||||
MessageT,
|
||||
Alloc,
|
||||
Deleter
|
||||
>::UniquePtr;
|
||||
|
||||
SubscriptionIntraProcess(
|
||||
AnySubscriptionCallback<CallbackMessageT, Alloc> callback,
|
||||
std::shared_ptr<Alloc> allocator,
|
||||
rclcpp::Context::SharedPtr context,
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos_profile,
|
||||
rmw_qos_profile_t qos_profile,
|
||||
rclcpp::IntraProcessBufferType buffer_type)
|
||||
: SubscriptionIntraProcessBuffer<MessageT, Alloc, Deleter>(
|
||||
allocator,
|
||||
context,
|
||||
topic_name,
|
||||
qos_profile,
|
||||
buffer_type),
|
||||
: SubscriptionIntraProcessBase(topic_name, qos_profile),
|
||||
any_callback_(callback)
|
||||
{
|
||||
if (!std::is_same<MessageT, CallbackMessageT>::value) {
|
||||
throw std::runtime_error("SubscriptionIntraProcess wrong callback type");
|
||||
}
|
||||
|
||||
// Create the intra-process buffer.
|
||||
buffer_ = rclcpp::experimental::create_intra_process_buffer<MessageT, Alloc, Deleter>(
|
||||
buffer_type,
|
||||
qos_profile,
|
||||
allocator);
|
||||
|
||||
// Create the guard condition.
|
||||
rcl_guard_condition_options_t guard_condition_options =
|
||||
rcl_guard_condition_get_default_options();
|
||||
|
||||
gc_ = rcl_get_zero_initialized_guard_condition();
|
||||
rcl_ret_t ret = rcl_guard_condition_init(
|
||||
&gc_, context->get_rcl_context().get(), guard_condition_options);
|
||||
|
||||
if (RCL_RET_OK != ret) {
|
||||
throw std::runtime_error("SubscriptionIntraProcess init error initializing guard condition");
|
||||
}
|
||||
|
||||
TRACEPOINT(
|
||||
rclcpp_subscription_callback_added,
|
||||
static_cast<const void *>(this),
|
||||
static_cast<const void *>(&any_callback_));
|
||||
(const void *)this,
|
||||
(const void *)&any_callback_);
|
||||
// The callback object gets copied, so if registration is done too early/before this point
|
||||
// (e.g. in `AnySubscriptionCallback::set()`), its address won't match any address used later
|
||||
// in subsequent tracepoints.
|
||||
@@ -95,66 +102,72 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual ~SubscriptionIntraProcess() = default;
|
||||
|
||||
std::shared_ptr<void>
|
||||
take_data()
|
||||
bool
|
||||
is_ready(rcl_wait_set_t * wait_set)
|
||||
{
|
||||
ConstMessageSharedPtr shared_msg;
|
||||
MessageUniquePtr unique_msg;
|
||||
|
||||
if (any_callback_.use_take_shared_method()) {
|
||||
shared_msg = this->buffer_->consume_shared();
|
||||
} else {
|
||||
unique_msg = this->buffer_->consume_unique();
|
||||
}
|
||||
return std::static_pointer_cast<void>(
|
||||
std::make_shared<std::pair<ConstMessageSharedPtr, MessageUniquePtr>>(
|
||||
std::pair<ConstMessageSharedPtr, MessageUniquePtr>(
|
||||
shared_msg, std::move(unique_msg)))
|
||||
);
|
||||
(void)wait_set;
|
||||
return buffer_->has_data();
|
||||
}
|
||||
|
||||
void execute(std::shared_ptr<void> & data)
|
||||
void execute()
|
||||
{
|
||||
execute_impl<MessageT>(data);
|
||||
execute_impl<CallbackMessageT>();
|
||||
}
|
||||
|
||||
void
|
||||
provide_intra_process_message(ConstMessageSharedPtr message)
|
||||
{
|
||||
buffer_->add_shared(std::move(message));
|
||||
trigger_guard_condition();
|
||||
}
|
||||
|
||||
void
|
||||
provide_intra_process_message(MessageUniquePtr message)
|
||||
{
|
||||
buffer_->add_unique(std::move(message));
|
||||
trigger_guard_condition();
|
||||
}
|
||||
|
||||
bool
|
||||
use_take_shared_method() const
|
||||
{
|
||||
return buffer_->use_take_shared_method();
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
trigger_guard_condition()
|
||||
{
|
||||
rcl_ret_t ret = rcl_trigger_guard_condition(&gc_);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
typename std::enable_if<std::is_same<T, rcl_serialized_message_t>::value, void>::type
|
||||
execute_impl(std::shared_ptr<void> & data)
|
||||
execute_impl()
|
||||
{
|
||||
(void)data;
|
||||
throw std::runtime_error("Subscription intra-process can't handle serialized messages");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<!std::is_same<T, rcl_serialized_message_t>::value, void>::type
|
||||
execute_impl(std::shared_ptr<void> & data)
|
||||
execute_impl()
|
||||
{
|
||||
if (!data) {
|
||||
throw std::runtime_error("'data' is empty");
|
||||
}
|
||||
|
||||
rmw_message_info_t msg_info;
|
||||
msg_info.publisher_gid = {0, {0}};
|
||||
msg_info.from_intra_process = true;
|
||||
|
||||
auto shared_ptr = std::static_pointer_cast<std::pair<ConstMessageSharedPtr, MessageUniquePtr>>(
|
||||
data);
|
||||
|
||||
if (any_callback_.use_take_shared_method()) {
|
||||
ConstMessageSharedPtr shared_msg = shared_ptr->first;
|
||||
any_callback_.dispatch_intra_process(shared_msg, msg_info);
|
||||
ConstMessageSharedPtr msg = buffer_->consume_shared();
|
||||
any_callback_.dispatch_intra_process(msg, msg_info);
|
||||
} else {
|
||||
MessageUniquePtr unique_msg = std::move(shared_ptr->second);
|
||||
any_callback_.dispatch_intra_process(std::move(unique_msg), msg_info);
|
||||
MessageUniquePtr msg = buffer_->consume_unique();
|
||||
any_callback_.dispatch_intra_process(std::move(msg), msg_info);
|
||||
}
|
||||
shared_ptr.reset();
|
||||
}
|
||||
|
||||
AnySubscriptionCallback<CallbackMessageT, Alloc> any_callback_;
|
||||
BufferUniquePtr buffer_;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/waitable.hpp"
|
||||
|
||||
@@ -40,9 +39,7 @@ public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(SubscriptionIntraProcessBase)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
SubscriptionIntraProcessBase(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos_profile)
|
||||
SubscriptionIntraProcessBase(const std::string & topic_name, rmw_qos_profile_t qos_profile)
|
||||
: topic_name_(topic_name), qos_profile_(qos_profile)
|
||||
{}
|
||||
|
||||
@@ -59,12 +56,8 @@ public:
|
||||
virtual bool
|
||||
is_ready(rcl_wait_set_t * wait_set) = 0;
|
||||
|
||||
virtual
|
||||
std::shared_ptr<void>
|
||||
take_data() = 0;
|
||||
|
||||
virtual void
|
||||
execute(std::shared_ptr<void> & data) = 0;
|
||||
execute() = 0;
|
||||
|
||||
virtual bool
|
||||
use_take_shared_method() const = 0;
|
||||
@@ -74,7 +67,7 @@ public:
|
||||
get_topic_name() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
QoS
|
||||
rmw_qos_profile_t
|
||||
get_actual_qos() const;
|
||||
|
||||
protected:
|
||||
@@ -86,7 +79,7 @@ private:
|
||||
trigger_guard_condition() = 0;
|
||||
|
||||
std::string topic_name_;
|
||||
QoS qos_profile_;
|
||||
rmw_qos_profile_t qos_profile_;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
// Copyright 2021 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__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_BUFFER_HPP_
|
||||
#define RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_BUFFER_HPP_
|
||||
|
||||
#include <rmw/rmw.h>
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
|
||||
#include "rclcpp/any_subscription_callback.hpp"
|
||||
#include "rclcpp/experimental/buffers/intra_process_buffer.hpp"
|
||||
#include "rclcpp/experimental/create_intra_process_buffer.hpp"
|
||||
#include "rclcpp/experimental/subscription_intra_process_base.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/waitable.hpp"
|
||||
#include "tracetools/tracetools.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>
|
||||
>
|
||||
class SubscriptionIntraProcessBuffer : public SubscriptionIntraProcessBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(SubscriptionIntraProcessBuffer)
|
||||
|
||||
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
|
||||
using MessageAlloc = typename MessageAllocTraits::allocator_type;
|
||||
using ConstMessageSharedPtr = std::shared_ptr<const MessageT>;
|
||||
using MessageUniquePtr = std::unique_ptr<MessageT, Deleter>;
|
||||
|
||||
using BufferUniquePtr = typename rclcpp::experimental::buffers::IntraProcessBuffer<
|
||||
MessageT,
|
||||
Alloc,
|
||||
Deleter
|
||||
>::UniquePtr;
|
||||
|
||||
SubscriptionIntraProcessBuffer(
|
||||
std::shared_ptr<Alloc> allocator,
|
||||
rclcpp::Context::SharedPtr context,
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos_profile,
|
||||
rclcpp::IntraProcessBufferType buffer_type)
|
||||
: SubscriptionIntraProcessBase(topic_name, qos_profile)
|
||||
{
|
||||
// Create the intra-process buffer.
|
||||
buffer_ = rclcpp::experimental::create_intra_process_buffer<MessageT, Alloc, Deleter>(
|
||||
buffer_type,
|
||||
qos_profile,
|
||||
allocator);
|
||||
|
||||
// Create the guard condition.
|
||||
rcl_guard_condition_options_t guard_condition_options =
|
||||
rcl_guard_condition_get_default_options();
|
||||
|
||||
gc_ = rcl_get_zero_initialized_guard_condition();
|
||||
rcl_ret_t ret = rcl_guard_condition_init(
|
||||
&gc_, context->get_rcl_context().get(), guard_condition_options);
|
||||
|
||||
if (RCL_RET_OK != ret) {
|
||||
throw std::runtime_error(
|
||||
"SubscriptionIntraProcessBuffer init error initializing guard condition");
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~SubscriptionIntraProcessBuffer()
|
||||
{
|
||||
if (rcl_guard_condition_fini(&gc_) != RCL_RET_OK) {
|
||||
RCUTILS_LOG_ERROR_NAMED(
|
||||
"rclcpp",
|
||||
"Failed to destroy guard condition: %s",
|
||||
rcutils_get_error_string().str);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
is_ready(rcl_wait_set_t * wait_set)
|
||||
{
|
||||
(void) wait_set;
|
||||
return buffer_->has_data();
|
||||
}
|
||||
|
||||
void
|
||||
provide_intra_process_message(ConstMessageSharedPtr message)
|
||||
{
|
||||
buffer_->add_shared(std::move(message));
|
||||
trigger_guard_condition();
|
||||
}
|
||||
|
||||
void
|
||||
provide_intra_process_message(MessageUniquePtr message)
|
||||
{
|
||||
buffer_->add_unique(std::move(message));
|
||||
trigger_guard_condition();
|
||||
}
|
||||
|
||||
bool
|
||||
use_take_shared_method() const
|
||||
{
|
||||
return buffer_->use_take_shared_method();
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
trigger_guard_condition()
|
||||
{
|
||||
rcl_ret_t ret = rcl_trigger_guard_condition(&gc_);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
BufferUniquePtr buffer_;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_BUFFER_HPP_
|
||||
@@ -162,32 +162,6 @@ struct same_arguments : std::is_same<
|
||||
>
|
||||
{};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename ReturnTypeT, typename ... Args>
|
||||
struct as_std_function_helper;
|
||||
|
||||
template<typename ReturnTypeT, typename ... Args>
|
||||
struct as_std_function_helper<ReturnTypeT, std::tuple<Args ...>>
|
||||
{
|
||||
using type = std::function<ReturnTypeT(Args ...)>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<
|
||||
typename FunctorT,
|
||||
typename FunctionTraits = function_traits<FunctorT>
|
||||
>
|
||||
struct as_std_function
|
||||
{
|
||||
using type = typename detail::as_std_function_helper<
|
||||
typename FunctionTraits::return_type,
|
||||
typename FunctionTraits::arguments
|
||||
>::type;
|
||||
};
|
||||
|
||||
} // namespace function_traits
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -42,6 +42,20 @@ RCLCPP_PUBLIC
|
||||
std::string
|
||||
to_string(const FutureReturnCode & future_return_code);
|
||||
|
||||
namespace executor
|
||||
{
|
||||
|
||||
using FutureReturnCode [[deprecated("use rclcpp::FutureReturnCode instead")]] = FutureReturnCode;
|
||||
|
||||
[[deprecated("use rclcpp::to_string(const rclcpp::FutureReturnCode &) instead")]]
|
||||
inline
|
||||
std::string
|
||||
to_string(const rclcpp::FutureReturnCode & future_return_code)
|
||||
{
|
||||
return rclcpp::to_string(future_return_code);
|
||||
}
|
||||
|
||||
} // namespace executor
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__FUTURE_RETURN_CODE_HPP_
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
// Copyright 2018, Bosch Software Innovations GmbH.
|
||||
// Copyright 2021, Apex.AI 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__GENERIC_PUBLISHER_HPP_
|
||||
#define RCLCPP__GENERIC_PUBLISHER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rcpputils/shared_library.hpp"
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
#include "rclcpp/publisher_base.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
#include "rclcpp/typesupport_helpers.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// %Publisher for serialized messages whose type is not known at compile time.
|
||||
/**
|
||||
* Since the type is not known at compile time, this is not a template, and the dynamic library
|
||||
* containing type support information has to be identified and loaded based on the type name.
|
||||
*
|
||||
* It does not support intra-process handling.
|
||||
*/
|
||||
class GenericPublisher : public rclcpp::PublisherBase
|
||||
{
|
||||
public:
|
||||
// cppcheck-suppress unknownMacro
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(GenericPublisher)
|
||||
|
||||
/// Constructor.
|
||||
/**
|
||||
* In order to properly publish to a topic, this publisher needs to be added to
|
||||
* the node_topic_interface of the node passed into this constructor.
|
||||
*
|
||||
* \sa rclcpp::Node::create_generic_publisher() or rclcpp::create_generic_publisher() for
|
||||
* creating an instance of this class and adding it to the node_topic_interface.
|
||||
*
|
||||
* \param node_base Pointer to parent node's NodeBaseInterface
|
||||
* \param ts_lib Type support library, needs to correspond to topic_type
|
||||
* \param topic_name Topic name
|
||||
* \param topic_type Topic type
|
||||
* \param qos %QoS settings
|
||||
* \param callback Callback for new messages of serialized form
|
||||
* \param options %Publisher options.
|
||||
* Not all publisher options are currently respected, the only relevant options for this
|
||||
* publisher are `event_callbacks`, `use_default_callbacks`, and `%callback_group`.
|
||||
*/
|
||||
template<typename AllocatorT = std::allocator<void>>
|
||||
GenericPublisher(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
std::shared_ptr<rcpputils::SharedLibrary> ts_lib,
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options)
|
||||
: rclcpp::PublisherBase(
|
||||
node_base,
|
||||
topic_name,
|
||||
*rclcpp::get_typesupport_handle(topic_type, "rosidl_typesupport_cpp", *ts_lib),
|
||||
options.template to_rcl_publisher_options<rclcpp::SerializedMessage>(qos)),
|
||||
ts_lib_(ts_lib)
|
||||
{
|
||||
// This is unfortunately duplicated with the code in publisher.hpp.
|
||||
// TODO(nnmm): Deduplicate by moving this into PublisherBase.
|
||||
if (options.event_callbacks.deadline_callback) {
|
||||
this->add_event_handler(
|
||||
options.event_callbacks.deadline_callback,
|
||||
RCL_PUBLISHER_OFFERED_DEADLINE_MISSED);
|
||||
}
|
||||
if (options.event_callbacks.liveliness_callback) {
|
||||
this->add_event_handler(
|
||||
options.event_callbacks.liveliness_callback,
|
||||
RCL_PUBLISHER_LIVELINESS_LOST);
|
||||
}
|
||||
if (options.event_callbacks.incompatible_qos_callback) {
|
||||
this->add_event_handler(
|
||||
options.event_callbacks.incompatible_qos_callback,
|
||||
RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS);
|
||||
} else if (options.use_default_callbacks) {
|
||||
// Register default callback when not specified
|
||||
try {
|
||||
this->add_event_handler(
|
||||
[this](QOSOfferedIncompatibleQoSInfo & info) {
|
||||
this->default_incompatible_qos_callback(info);
|
||||
},
|
||||
RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS);
|
||||
} catch (UnsupportedEventTypeException & /*exc*/) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~GenericPublisher() = default;
|
||||
|
||||
/// Publish a rclcpp::SerializedMessage.
|
||||
RCLCPP_PUBLIC
|
||||
void publish(const rclcpp::SerializedMessage & message);
|
||||
|
||||
private:
|
||||
// The type support library should stay loaded, so it is stored in the GenericPublisher
|
||||
std::shared_ptr<rcpputils::SharedLibrary> ts_lib_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__GENERIC_PUBLISHER_HPP_
|
||||
@@ -1,168 +0,0 @@
|
||||
// Copyright 2018, Bosch Software Innovations GmbH.
|
||||
// Copyright 2021, Apex.AI 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__GENERIC_SUBSCRIPTION_HPP_
|
||||
#define RCLCPP__GENERIC_SUBSCRIPTION_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rcpputils/shared_library.hpp"
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
#include "rclcpp/subscription_base.hpp"
|
||||
#include "rclcpp/typesupport_helpers.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// %Subscription for serialized messages whose type is not known at compile time.
|
||||
/**
|
||||
* Since the type is not known at compile time, this is not a template, and the dynamic library
|
||||
* containing type support information has to be identified and loaded based on the type name.
|
||||
*
|
||||
* It does not support intra-process handling.
|
||||
*/
|
||||
class GenericSubscription : public rclcpp::SubscriptionBase
|
||||
{
|
||||
public:
|
||||
// cppcheck-suppress unknownMacro
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(GenericSubscription)
|
||||
|
||||
/// Constructor.
|
||||
/**
|
||||
* In order to properly subscribe to a topic, this subscription needs to be added to
|
||||
* the node_topic_interface of the node passed into this constructor.
|
||||
*
|
||||
* \sa rclcpp::Node::create_generic_subscription() or rclcpp::create_generic_subscription() for
|
||||
* creating an instance of this class and adding it to the node_topic_interface.
|
||||
*
|
||||
* \param node_base Pointer to parent node's NodeBaseInterface
|
||||
* \param ts_lib Type support library, needs to correspond to topic_type
|
||||
* \param topic_name Topic name
|
||||
* \param topic_type Topic type
|
||||
* \param qos %QoS settings
|
||||
* \param callback Callback for new messages of serialized form
|
||||
* \param options %Subscription options.
|
||||
* Not all subscription options are currently respected, the only relevant options for this
|
||||
* subscription are `event_callbacks`, `use_default_callbacks`, `ignore_local_publications`, and
|
||||
* `%callback_group`.
|
||||
*/
|
||||
template<typename AllocatorT = std::allocator<void>>
|
||||
GenericSubscription(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
const std::shared_ptr<rcpputils::SharedLibrary> ts_lib,
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
// TODO(nnmm): Add variant for callback with message info. See issue #1604.
|
||||
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options)
|
||||
: SubscriptionBase(
|
||||
node_base,
|
||||
*rclcpp::get_typesupport_handle(topic_type, "rosidl_typesupport_cpp", *ts_lib),
|
||||
topic_name,
|
||||
options.template to_rcl_subscription_options<rclcpp::SerializedMessage>(qos),
|
||||
true),
|
||||
callback_(callback),
|
||||
ts_lib_(ts_lib)
|
||||
{
|
||||
// This is unfortunately duplicated with the code in subscription.hpp.
|
||||
// TODO(nnmm): Deduplicate by moving this into SubscriptionBase.
|
||||
if (options.event_callbacks.deadline_callback) {
|
||||
this->add_event_handler(
|
||||
options.event_callbacks.deadline_callback,
|
||||
RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED);
|
||||
}
|
||||
if (options.event_callbacks.liveliness_callback) {
|
||||
this->add_event_handler(
|
||||
options.event_callbacks.liveliness_callback,
|
||||
RCL_SUBSCRIPTION_LIVELINESS_CHANGED);
|
||||
}
|
||||
if (options.event_callbacks.incompatible_qos_callback) {
|
||||
this->add_event_handler(
|
||||
options.event_callbacks.incompatible_qos_callback,
|
||||
RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS);
|
||||
} else if (options.use_default_callbacks) {
|
||||
// Register default callback when not specified
|
||||
try {
|
||||
this->add_event_handler(
|
||||
[this](QOSRequestedIncompatibleQoSInfo & info) {
|
||||
this->default_incompatible_qos_callback(info);
|
||||
},
|
||||
RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS);
|
||||
} catch (UnsupportedEventTypeException & /*exc*/) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
if (options.event_callbacks.message_lost_callback) {
|
||||
this->add_event_handler(
|
||||
options.event_callbacks.message_lost_callback,
|
||||
RCL_SUBSCRIPTION_MESSAGE_LOST);
|
||||
}
|
||||
}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~GenericSubscription() = default;
|
||||
|
||||
// Same as create_serialized_message() as the subscription is to serialized_messages only
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<void> create_message() override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<rclcpp::SerializedMessage> create_serialized_message() override;
|
||||
|
||||
/// Cast the message to a rclcpp::SerializedMessage and call the callback.
|
||||
RCLCPP_PUBLIC
|
||||
void handle_message(
|
||||
std::shared_ptr<void> & message, const rclcpp::MessageInfo & message_info) override;
|
||||
|
||||
/// Handle dispatching rclcpp::SerializedMessage to user callback.
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
handle_serialized_message(
|
||||
const std::shared_ptr<rclcpp::SerializedMessage> & serialized_message,
|
||||
const rclcpp::MessageInfo & message_info) override;
|
||||
|
||||
/// This function is currently not implemented.
|
||||
RCLCPP_PUBLIC
|
||||
void handle_loaned_message(
|
||||
void * loaned_message, const rclcpp::MessageInfo & message_info) override;
|
||||
|
||||
// Same as return_serialized_message() as the subscription is to serialized_messages only
|
||||
RCLCPP_PUBLIC
|
||||
void return_message(std::shared_ptr<void> & message) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void return_serialized_message(std::shared_ptr<rclcpp::SerializedMessage> & message) override;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(GenericSubscription)
|
||||
|
||||
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> callback_;
|
||||
// The type support library should stay loaded, so it is stored in the GenericSubscription
|
||||
std::shared_ptr<rcpputils::SharedLibrary> ts_lib_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__GENERIC_SUBSCRIPTION_HPP_
|
||||
@@ -1,90 +0,0 @@
|
||||
// Copyright 2021 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__GET_MESSAGE_TYPE_SUPPORT_HANDLE_HPP_
|
||||
#define RCLCPP__GET_MESSAGE_TYPE_SUPPORT_HANDLE_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "rosidl_runtime_cpp/traits.hpp"
|
||||
#include "rosidl_runtime_cpp/message_type_support_decl.hpp"
|
||||
#include "rosidl_typesupport_cpp/message_type_support.hpp"
|
||||
|
||||
#include "rclcpp/type_adapter.hpp"
|
||||
|
||||
/// Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Specialization for when MessageT is an actual ROS message type.
|
||||
template<typename MessageT>
|
||||
constexpr
|
||||
typename std::enable_if_t<
|
||||
rosidl_generator_traits::is_message<MessageT>::value,
|
||||
const rosidl_message_type_support_t &
|
||||
>
|
||||
get_message_type_support_handle()
|
||||
{
|
||||
auto handle = rosidl_typesupport_cpp::get_message_type_support_handle<MessageT>();
|
||||
if (!handle) {
|
||||
throw std::runtime_error("Type support handle unexpectedly nullptr");
|
||||
}
|
||||
return *handle;
|
||||
}
|
||||
|
||||
/// Specialization for when MessageT is an adapted type using rclcpp::TypeAdapter.
|
||||
template<typename AdaptedType>
|
||||
constexpr
|
||||
typename std::enable_if_t<
|
||||
!rosidl_generator_traits::is_message<AdaptedType>::value &&
|
||||
rclcpp::TypeAdapter<AdaptedType>::is_specialized::value,
|
||||
const rosidl_message_type_support_t &
|
||||
>
|
||||
get_message_type_support_handle()
|
||||
{
|
||||
auto handle = rosidl_typesupport_cpp::get_message_type_support_handle<
|
||||
typename TypeAdapter<AdaptedType>::ros_message_type
|
||||
>();
|
||||
if (!handle) {
|
||||
throw std::runtime_error("Type support handle unexpectedly nullptr");
|
||||
}
|
||||
return *handle;
|
||||
}
|
||||
|
||||
/// Specialization for when MessageT is not a ROS message nor an adapted type.
|
||||
/**
|
||||
* This specialization is a pass through runtime check, which allows a better
|
||||
* static_assert to catch this issue further down the line.
|
||||
* This should never get to be called in practice, and is purely defensive.
|
||||
*/
|
||||
template<
|
||||
typename AdaptedType
|
||||
>
|
||||
constexpr
|
||||
typename std::enable_if_t<
|
||||
!rosidl_generator_traits::is_message<AdaptedType>::value &&
|
||||
!TypeAdapter<AdaptedType>::is_specialized::value,
|
||||
const rosidl_message_type_support_t &
|
||||
>
|
||||
get_message_type_support_handle()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"this specialization of rclcpp::get_message_type_support_handle() "
|
||||
"should never be called");
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__GET_MESSAGE_TYPE_SUPPORT_HANDLE_HPP_
|
||||
@@ -63,7 +63,7 @@ class GraphListener : public std::enable_shared_from_this<GraphListener>
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
explicit GraphListener(const rclcpp::Context::SharedPtr & parent_context);
|
||||
explicit GraphListener(std::shared_ptr<rclcpp::Context> parent_context);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~GraphListener();
|
||||
@@ -160,23 +160,14 @@ protected:
|
||||
void
|
||||
run_loop();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
init_wait_set();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
cleanup_wait_set();
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(GraphListener)
|
||||
|
||||
/** \internal */
|
||||
void
|
||||
__shutdown();
|
||||
__shutdown(bool);
|
||||
|
||||
std::weak_ptr<rclcpp::Context> weak_parent_context_;
|
||||
std::shared_ptr<rcl_context_t> rcl_parent_context_;
|
||||
rclcpp::Context::WeakPtr parent_context_;
|
||||
|
||||
std::thread listener_thread_;
|
||||
bool is_started_;
|
||||
@@ -188,6 +179,7 @@ private:
|
||||
std::vector<rclcpp::node_interfaces::NodeGraphInterface *> node_graph_interfaces_;
|
||||
|
||||
rcl_guard_condition_t interrupt_guard_condition_ = rcl_get_zero_initialized_guard_condition();
|
||||
rcl_guard_condition_t * shutdown_guard_condition_;
|
||||
rcl_wait_set_t wait_set_ = rcl_get_zero_initialized_wait_set();
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define RCLCPP__INIT_OPTIONS_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include "rcl/init_options.h"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
@@ -81,30 +80,11 @@ public:
|
||||
const rcl_init_options_t *
|
||||
get_rcl_init_options() const;
|
||||
|
||||
/// Retrieve default domain id and set.
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
use_default_domain_id();
|
||||
|
||||
/// Set the domain id.
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_domain_id(size_t domain_id);
|
||||
|
||||
/// Return domain id.
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_domain_id() const;
|
||||
|
||||
protected:
|
||||
void
|
||||
finalize_init_options();
|
||||
|
||||
private:
|
||||
void
|
||||
finalize_init_options_impl();
|
||||
|
||||
mutable std::mutex init_options_mutex_;
|
||||
std::unique_ptr<rcl_init_options_t> init_options_;
|
||||
bool initialize_logging_{true};
|
||||
};
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright 2021 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__IS_ROS_COMPATIBLE_TYPE_HPP_
|
||||
#define RCLCPP__IS_ROS_COMPATIBLE_TYPE_HPP_
|
||||
|
||||
#include "rosidl_runtime_cpp/traits.hpp"
|
||||
|
||||
#include "rclcpp/type_adapter.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
struct is_ros_compatible_type
|
||||
{
|
||||
static constexpr bool value =
|
||||
rosidl_generator_traits::is_message<T>::value ||
|
||||
rclcpp::TypeAdapter<T>::is_specialized::value;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__IS_ROS_COMPATIBLE_TYPE_HPP_
|
||||
@@ -103,9 +103,6 @@ public:
|
||||
* \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)
|
||||
@@ -186,30 +183,14 @@ public:
|
||||
/**
|
||||
* A call to `release()` will unmanage the memory for the ROS message.
|
||||
* That means that the destructor of this class will not free the memory on scope exit.
|
||||
* If the message is loaned from the middleware but not be published, the user needs to call
|
||||
* `rcl_return_loaned_message_from_publisher` manually.
|
||||
* If the memory is from the local allocator, the memory is freed when the unique pointer
|
||||
* goes out instead.
|
||||
*
|
||||
* \return std::unique_ptr to the message instance.
|
||||
* \return Raw pointer to the message instance.
|
||||
*/
|
||||
std::unique_ptr<MessageT, std::function<void(MessageT *)>>
|
||||
release()
|
||||
MessageT * release()
|
||||
{
|
||||
auto msg = message_;
|
||||
message_ = nullptr;
|
||||
|
||||
if (pub_.can_loan_messages()) {
|
||||
return std::unique_ptr<MessageT, std::function<void(MessageT *)>>(msg, [](MessageT *) {});
|
||||
}
|
||||
|
||||
return std::unique_ptr<MessageT, std::function<void(MessageT *)>>(
|
||||
msg,
|
||||
[allocator = message_allocator_](MessageT * msg_ptr) mutable {
|
||||
// call destructor before deallocating
|
||||
msg_ptr->~MessageT();
|
||||
allocator.deallocate(msg_ptr, 1);
|
||||
});
|
||||
return msg;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rcl/node.h"
|
||||
#include "rcutils/logging.h"
|
||||
#include "rcpputils/filesystem_helper.hpp"
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOGGING_ENABLED
|
||||
@@ -76,32 +74,8 @@ RCLCPP_PUBLIC
|
||||
Logger
|
||||
get_node_logger(const rcl_node_t * node);
|
||||
|
||||
/// Get the current logging directory.
|
||||
/**
|
||||
* For more details of how the logging directory is determined,
|
||||
* see \ref rcl_logging_get_logging_directory.
|
||||
*
|
||||
* \returns the logging directory being used.
|
||||
* \throws rclcpp::exceptions::RCLError if an unexpected error occurs.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rcpputils::fs::path
|
||||
get_logging_directory();
|
||||
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
/// An enum for the type of logger level.
|
||||
enum class Level
|
||||
{
|
||||
Unset = RCUTILS_LOG_SEVERITY_UNSET, ///< The unset log level
|
||||
Debug = RCUTILS_LOG_SEVERITY_DEBUG, ///< The debug log level
|
||||
Info = RCUTILS_LOG_SEVERITY_INFO, ///< The info log level
|
||||
Warn = RCUTILS_LOG_SEVERITY_WARN, ///< The warn log level
|
||||
Error = RCUTILS_LOG_SEVERITY_ERROR, ///< The error log level
|
||||
Fatal = RCUTILS_LOG_SEVERITY_FATAL, ///< The fatal log level
|
||||
};
|
||||
|
||||
private:
|
||||
friend Logger rclcpp::get_logger(const std::string & name);
|
||||
friend ::rclcpp::node_interfaces::NodeLogging;
|
||||
@@ -164,16 +138,6 @@ public:
|
||||
}
|
||||
return Logger(*name_ + "." + suffix);
|
||||
}
|
||||
|
||||
/// Set level for current logger.
|
||||
/**
|
||||
* \param[in] level the logger's level
|
||||
* \throws rclcpp::exceptions::RCLInvalidArgument if level is invalid.
|
||||
* \throws rclcpp::exceptions::RCLError if other error happens.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_level(Level level);
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define RCLCPP__MEMORY_STRATEGY_HPP_
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "rcl/allocator.h"
|
||||
@@ -43,13 +42,11 @@ class RCLCPP_PUBLIC MemoryStrategy
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(MemoryStrategy)
|
||||
using WeakCallbackGroupsToNodesMap = std::map<rclcpp::CallbackGroup::WeakPtr,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::WeakPtr,
|
||||
std::owner_less<rclcpp::CallbackGroup::WeakPtr>>;
|
||||
using WeakNodeList = std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>;
|
||||
|
||||
virtual ~MemoryStrategy() = default;
|
||||
|
||||
virtual bool collect_entities(const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) = 0;
|
||||
virtual bool collect_entities(const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual size_t number_of_ready_subscriptions() const = 0;
|
||||
virtual size_t number_of_ready_services() const = 0;
|
||||
@@ -71,27 +68,27 @@ public:
|
||||
virtual void
|
||||
get_next_subscription(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) = 0;
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_service(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) = 0;
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_client(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) = 0;
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_timer(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) = 0;
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_waitable(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) = 0;
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual rcl_allocator_t
|
||||
get_allocator() = 0;
|
||||
@@ -99,52 +96,52 @@ public:
|
||||
static rclcpp::SubscriptionBase::SharedPtr
|
||||
get_subscription_by_handle(
|
||||
std::shared_ptr<const rcl_subscription_t> subscriber_handle,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::ServiceBase::SharedPtr
|
||||
get_service_by_handle(
|
||||
std::shared_ptr<const rcl_service_t> service_handle,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::ClientBase::SharedPtr
|
||||
get_client_by_handle(
|
||||
std::shared_ptr<const rcl_client_t> client_handle,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::TimerBase::SharedPtr
|
||||
get_timer_by_handle(
|
||||
std::shared_ptr<const rcl_timer_t> timer_handle,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
get_node_by_group(
|
||||
rclcpp::CallbackGroup::SharedPtr group,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_service(
|
||||
rclcpp::ServiceBase::SharedPtr service,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_client(
|
||||
rclcpp::ClientBase::SharedPtr client,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_timer(
|
||||
rclcpp::TimerBase::SharedPtr timer,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
};
|
||||
|
||||
} // namespace memory_strategy
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
// Copyright 2020 Ericsson AB
|
||||
//
|
||||
// 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__NETWORK_FLOW_ENDPOINT_HPP_
|
||||
#define RCLCPP__NETWORK_FLOW_ENDPOINT_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "rcl/network_flow_endpoints.h"
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Forward declaration
|
||||
class NetworkFlowEndpoint;
|
||||
|
||||
/// Check if two NetworkFlowEndpoint instances are equal
|
||||
RCLCPP_PUBLIC
|
||||
bool operator==(const NetworkFlowEndpoint & left, const NetworkFlowEndpoint & right);
|
||||
|
||||
/// Check if two NetworkFlowEndpoint instances are not equal
|
||||
RCLCPP_PUBLIC
|
||||
bool operator!=(const NetworkFlowEndpoint & left, const NetworkFlowEndpoint & right);
|
||||
|
||||
/// Streaming helper for NetworkFlowEndpoint
|
||||
RCLCPP_PUBLIC
|
||||
std::ostream & operator<<(std::ostream & os, const NetworkFlowEndpoint & network_flow_endpoint);
|
||||
|
||||
/**
|
||||
* Class describes a network flow endpoint based on the counterpart definition
|
||||
* in the RMW layer.
|
||||
*/
|
||||
class NetworkFlowEndpoint
|
||||
{
|
||||
public:
|
||||
/// Construct from rcl_network_flow_endpoint_t
|
||||
RCLCPP_PUBLIC
|
||||
explicit NetworkFlowEndpoint(const rcl_network_flow_endpoint_t & network_flow_endpoint)
|
||||
: transport_protocol_(
|
||||
rcl_network_flow_endpoint_get_transport_protocol_string(network_flow_endpoint.
|
||||
transport_protocol)),
|
||||
internet_protocol_(
|
||||
rcl_network_flow_endpoint_get_internet_protocol_string(
|
||||
network_flow_endpoint.internet_protocol)),
|
||||
transport_port_(network_flow_endpoint.transport_port),
|
||||
flow_label_(network_flow_endpoint.flow_label),
|
||||
dscp_(network_flow_endpoint.dscp),
|
||||
internet_address_(network_flow_endpoint.internet_address)
|
||||
{
|
||||
}
|
||||
|
||||
/// Get transport protocol
|
||||
RCLCPP_PUBLIC
|
||||
const std::string & transport_protocol() const;
|
||||
|
||||
/// Get internet protocol
|
||||
RCLCPP_PUBLIC
|
||||
const std::string & internet_protocol() const;
|
||||
|
||||
/// Get transport port
|
||||
RCLCPP_PUBLIC
|
||||
uint16_t transport_port() const;
|
||||
|
||||
/// Get flow label
|
||||
RCLCPP_PUBLIC
|
||||
uint32_t flow_label() const;
|
||||
|
||||
/// Get DSCP
|
||||
RCLCPP_PUBLIC
|
||||
uint8_t dscp() const;
|
||||
|
||||
/// Get internet address
|
||||
RCLCPP_PUBLIC
|
||||
const std::string & internet_address() const;
|
||||
|
||||
/// Compare two NetworkFlowEndpoint instances
|
||||
friend bool rclcpp::operator==(
|
||||
const NetworkFlowEndpoint & left,
|
||||
const NetworkFlowEndpoint & right);
|
||||
friend bool rclcpp::operator!=(
|
||||
const NetworkFlowEndpoint & left,
|
||||
const NetworkFlowEndpoint & right);
|
||||
|
||||
/// Streaming helper
|
||||
friend std::ostream & rclcpp::operator<<(
|
||||
std::ostream & os,
|
||||
const NetworkFlowEndpoint & network_flow_endpoint);
|
||||
|
||||
private:
|
||||
std::string transport_protocol_;
|
||||
std::string internet_protocol_;
|
||||
uint16_t transport_port_;
|
||||
uint32_t flow_label_;
|
||||
uint8_t dscp_;
|
||||
std::string internet_address_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NETWORK_FLOW_ENDPOINT_HPP_
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -42,8 +41,6 @@
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/context.hpp"
|
||||
#include "rclcpp/event.hpp"
|
||||
#include "rclcpp/generic_publisher.hpp"
|
||||
#include "rclcpp/generic_subscription.hpp"
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/message_memory_strategy.hpp"
|
||||
@@ -144,9 +141,7 @@ public:
|
||||
/// Create and return a callback group.
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
create_callback_group(
|
||||
rclcpp::CallbackGroupType group_type,
|
||||
bool automatically_add_to_executor_with_node = true);
|
||||
create_callback_group(rclcpp::CallbackGroupType group_type);
|
||||
|
||||
/// Return the list of callback groups in the node.
|
||||
RCLCPP_PUBLIC
|
||||
@@ -206,8 +201,13 @@ public:
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
typename SubscriptionT = rclcpp::Subscription<MessageT, AllocatorT>,
|
||||
typename MessageMemoryStrategyT = typename SubscriptionT::MessageMemoryStrategyType
|
||||
typename CallbackMessageT =
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type,
|
||||
typename SubscriptionT = rclcpp::Subscription<CallbackMessageT, AllocatorT>,
|
||||
typename MessageMemoryStrategyT = rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
CallbackMessageT,
|
||||
AllocatorT
|
||||
>
|
||||
>
|
||||
std::shared_ptr<SubscriptionT>
|
||||
create_subscription(
|
||||
@@ -264,55 +264,6 @@ public:
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a GenericPublisher.
|
||||
/**
|
||||
* The returned pointer will never be empty, but this function can throw various exceptions, for
|
||||
* instance when the message's package can not be found on the AMENT_PREFIX_PATH.
|
||||
*
|
||||
* \param[in] topic_name Topic name
|
||||
* \param[in] topic_type Topic type
|
||||
* \param[in] qos %QoS settings
|
||||
* \param options %Publisher options.
|
||||
* Not all publisher options are currently respected, the only relevant options for this
|
||||
* publisher are `event_callbacks`, `use_default_callbacks`, and `%callback_group`.
|
||||
* \return Shared pointer to the created generic publisher.
|
||||
*/
|
||||
template<typename AllocatorT = std::allocator<void>>
|
||||
std::shared_ptr<rclcpp::GenericPublisher> create_generic_publisher(
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::PublisherOptionsWithAllocator<AllocatorT>()
|
||||
)
|
||||
);
|
||||
|
||||
/// Create and return a GenericSubscription.
|
||||
/**
|
||||
* The returned pointer will never be empty, but this function can throw various exceptions, for
|
||||
* instance when the message's package can not be found on the AMENT_PREFIX_PATH.
|
||||
*
|
||||
* \param[in] topic_name Topic name
|
||||
* \param[in] topic_type Topic type
|
||||
* \param[in] qos %QoS settings
|
||||
* \param[in] callback Callback for new messages of serialized form
|
||||
* \param[in] options %Subscription options.
|
||||
* Not all subscription options are currently respected, the only relevant options for this
|
||||
* subscription are `event_callbacks`, `use_default_callbacks`, `ignore_local_publications`, and
|
||||
* `%callback_group`.
|
||||
* \return Shared pointer to the created generic subscription.
|
||||
*/
|
||||
template<typename AllocatorT = std::allocator<void>>
|
||||
std::shared_ptr<rclcpp::GenericSubscription> create_generic_subscription(
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
)
|
||||
);
|
||||
|
||||
/// Declare and initialize a parameter, return the effective value.
|
||||
/**
|
||||
* This method is used to declare that a parameter exists on this node.
|
||||
@@ -352,59 +303,16 @@ public:
|
||||
* name is invalid.
|
||||
* \throws rclcpp::exceptions::InvalidParameterValueException if initial
|
||||
* value fails to be set.
|
||||
* \throws rclcpp::exceptions::InvalidParameterTypeException
|
||||
* if the type of the default value or override is wrong.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor(),
|
||||
bool ignore_override = false);
|
||||
|
||||
/// Declare and initialize a parameter, return the effective value.
|
||||
/**
|
||||
* Same as the previous one, but a default value is not provided and the user
|
||||
* must provide a parameter override of the correct type.
|
||||
*
|
||||
* \param[in] name The name of the parameter.
|
||||
* \param[in] type Desired type of the parameter, which will enforced at runtime.
|
||||
* \param[in] parameter_descriptor An optional, custom description for
|
||||
* the parameter.
|
||||
* \param[in] ignore_override When `true`, the parameter override is ignored.
|
||||
* Default to `false`.
|
||||
* \return A const reference to the value of the parameter.
|
||||
* \throws Same as the previous overload taking a default value.
|
||||
* \throws rclcpp::exceptions::InvalidParameterTypeException
|
||||
* if an override is not provided or the provided override is of the wrong type.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
rclcpp::ParameterType type,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor{},
|
||||
bool ignore_override = false);
|
||||
|
||||
/// Declare a parameter
|
||||
[[deprecated(
|
||||
"declare_parameter() with only a name is deprecated and will be deleted in the future.\n" \
|
||||
"If you want to declare a parameter that won't change type without a default value use:\n" \
|
||||
"`node->declare_parameter<ParameterT>(name)`, where e.g. ParameterT=int64_t.\n\n" \
|
||||
"If you want to declare a parameter that can dynamically change type use:\n" \
|
||||
"```\n" \
|
||||
"rcl_interfaces::msg::ParameterDescriptor descriptor;\n" \
|
||||
"descriptor.dynamic_typing = true;\n" \
|
||||
"node->declare_parameter(name, rclcpp::ParameterValue{}, descriptor);\n" \
|
||||
"```"
|
||||
)]]
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(const std::string & name);
|
||||
|
||||
/// Declare and initialize a parameter with a type.
|
||||
/**
|
||||
* See the non-templated declare_parameter() on this class for details.
|
||||
@@ -435,18 +343,6 @@ public:
|
||||
rcl_interfaces::msg::ParameterDescriptor(),
|
||||
bool ignore_override = false);
|
||||
|
||||
/// Declare and initialize a parameter with a type.
|
||||
/**
|
||||
* See the non-templated declare_parameter() on this class for details.
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
auto
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor(),
|
||||
bool ignore_override = false);
|
||||
|
||||
/// Declare and initialize several parameters with the same namespace and type.
|
||||
/**
|
||||
* For each key in the map, a parameter with a name of "namespace.key"
|
||||
@@ -887,9 +783,6 @@ public:
|
||||
*
|
||||
* This allows the node developer to control which parameters may be changed.
|
||||
*
|
||||
* It is considered bad practice to reject changes for "unknown" parameters as this prevents
|
||||
* other parts of the node (that may be aware of these parameters) from handling them.
|
||||
*
|
||||
* Note that the callback is called when declare_parameter() and its variants
|
||||
* are called, and so you cannot assume the parameter has been set before
|
||||
* this callback, so when checking a new value against the existing one, you
|
||||
@@ -952,6 +845,26 @@ public:
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler);
|
||||
|
||||
/// Register a callback to be called anytime a parameter is about to be changed.
|
||||
/**
|
||||
* \deprecated Use add_on_set_parameters_callback instead.
|
||||
* With this method, only one callback can be set at a time. The callback that was previously
|
||||
* set by this method is returned or `nullptr` if no callback was previously set.
|
||||
*
|
||||
* The callbacks added with `add_on_set_parameters_callback` are stored in a different place.
|
||||
* `remove_on_set_parameters_callback` can't be used with the callbacks registered with this
|
||||
* method. For removing it, use `set_on_parameters_set_callback(nullptr)`.
|
||||
*
|
||||
* \param[in] callback The callback to be called when the value for a
|
||||
* parameter is about to be set.
|
||||
* \return The previous callback that was registered, if there was one,
|
||||
* otherwise nullptr.
|
||||
*/
|
||||
[[deprecated("use add_on_set_parameters_callback(OnParametersSetCallbackType callback) instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
OnParametersSetCallbackType
|
||||
set_on_parameters_set_callback(rclcpp::Node::OnParametersSetCallbackType callback);
|
||||
|
||||
/// Get the fully-qualified names of all available nodes.
|
||||
/**
|
||||
* The fully-qualified name includes the local namespace and name of the node.
|
||||
@@ -979,12 +892,15 @@ public:
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_service_names_and_types() const;
|
||||
|
||||
/// Return the number of publishers that are advertised on a given topic.
|
||||
/// Return a map of existing service names to list of service types for a specific node.
|
||||
/**
|
||||
* \param[in] node_name the node_name on which to count the publishers.
|
||||
* \param[in] namespace_ the namespace of the node associated with the name
|
||||
* \return number of publishers that are advertised on a given topic.
|
||||
* \throws std::runtime_error if publishers could not be counted
|
||||
* This function only considers services - not clients.
|
||||
* The returned names are the actual names used and do not have remap rules applied.
|
||||
*
|
||||
* \param[in] node_name name of the node.
|
||||
* \param[in] namespace_ namespace of the node.
|
||||
* \return a map of existing service names to list of service types.
|
||||
* \throws std::runtime_error anything that rcl_error can throw.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
@@ -992,21 +908,15 @@ public:
|
||||
const std::string & node_name,
|
||||
const std::string & namespace_) const;
|
||||
|
||||
/// Return the number of publishers created for a given topic.
|
||||
/**
|
||||
* \param[in] topic_name the actual topic name used; it will not be automatically remapped.
|
||||
* \return number of publishers that have been created for the given topic.
|
||||
* \throws std::runtime_error if publishers could not be counted
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_publishers(const std::string & topic_name) const;
|
||||
|
||||
/// Return the number of subscribers created for a given topic.
|
||||
/// Return the number of subscribers who have created a subscription for a given topic.
|
||||
/**
|
||||
* \param[in] topic_name the actual topic name used; it will not be automatically remapped.
|
||||
* \return number of subscribers that have been created for the given topic.
|
||||
* \throws std::runtime_error if subscribers could not be counted
|
||||
* \param[in] topic_name the topic_name on which to count the subscribers.
|
||||
* \return number of subscribers who have created a subscription for a given topic.
|
||||
* \throws std::runtime_error if publishers could not be counted
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
@@ -1027,7 +937,7 @@ public:
|
||||
* A relative or private topic will be expanded using this node's namespace and name.
|
||||
* The queried `topic_name` is not remapped.
|
||||
*
|
||||
* \param[in] topic_name the actual topic name used; it will not be automatically remapped.
|
||||
* \param[in] topic_name the topic_name on which to find the publishers.
|
||||
* \param[in] no_mangle if `true`, `topic_name` needs to be a valid middleware topic name,
|
||||
* otherwise it should be a valid ROS topic name. Defaults to `false`.
|
||||
* \return a list of TopicEndpointInfo representing all the publishers on this topic.
|
||||
@@ -1053,7 +963,7 @@ public:
|
||||
* A relative or private topic will be expanded using this node's namespace and name.
|
||||
* The queried `topic_name` is not remapped.
|
||||
*
|
||||
* \param[in] topic_name the actual topic name used; it will not be automatically remapped.
|
||||
* \param[in] topic_name the topic_name on which to find the subscriptions.
|
||||
* \param[in] no_mangle if `true`, `topic_name` needs to be a valid middleware topic name,
|
||||
* otherwise it should be a valid ROS topic name. Defaults to `false`.
|
||||
* \return a list of TopicEndpointInfo representing all the subscriptions on this topic.
|
||||
@@ -1287,6 +1197,10 @@ protected:
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(Node)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
group_in_node(CallbackGroup::SharedPtr group);
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_;
|
||||
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_;
|
||||
|
||||
@@ -36,12 +36,10 @@
|
||||
|
||||
#include "rclcpp/contexts/default_context.hpp"
|
||||
#include "rclcpp/create_client.hpp"
|
||||
#include "rclcpp/create_generic_publisher.hpp"
|
||||
#include "rclcpp/create_generic_subscription.hpp"
|
||||
#include "rclcpp/create_publisher.hpp"
|
||||
#include "rclcpp/create_service.hpp"
|
||||
#include "rclcpp/create_subscription.hpp"
|
||||
#include "rclcpp/create_timer.hpp"
|
||||
#include "rclcpp/create_subscription.hpp"
|
||||
#include "rclcpp/detail/resolve_enable_topic_statistics.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
@@ -86,6 +84,7 @@ template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename AllocatorT,
|
||||
typename CallbackMessageT,
|
||||
typename SubscriptionT,
|
||||
typename MessageMemoryStrategyT>
|
||||
std::shared_ptr<SubscriptionT>
|
||||
@@ -153,43 +152,6 @@ Node::create_service(
|
||||
group);
|
||||
}
|
||||
|
||||
template<typename AllocatorT>
|
||||
std::shared_ptr<rclcpp::GenericPublisher>
|
||||
Node::create_generic_publisher(
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options)
|
||||
{
|
||||
return rclcpp::create_generic_publisher(
|
||||
node_topics_,
|
||||
extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
|
||||
topic_type,
|
||||
qos,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
template<typename AllocatorT>
|
||||
std::shared_ptr<rclcpp::GenericSubscription>
|
||||
Node::create_generic_subscription(
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options)
|
||||
{
|
||||
return rclcpp::create_generic_subscription(
|
||||
node_topics_,
|
||||
extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
|
||||
topic_type,
|
||||
qos,
|
||||
std::move(callback),
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<typename ParameterT>
|
||||
auto
|
||||
Node::declare_parameter(
|
||||
@@ -210,24 +172,6 @@ Node::declare_parameter(
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
auto
|
||||
Node::declare_parameter(
|
||||
const std::string & name,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
|
||||
bool ignore_override)
|
||||
{
|
||||
// get advantage of parameter value template magic to get
|
||||
// the correct rclcpp::ParameterType from ParameterT
|
||||
rclcpp::ParameterValue value{ParameterT{}};
|
||||
return this->declare_parameter(
|
||||
name,
|
||||
value.get_type(),
|
||||
parameter_descriptor,
|
||||
ignore_override
|
||||
).get<ParameterT>();
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
std::vector<ParameterT>
|
||||
Node::declare_parameters(
|
||||
|
||||
@@ -83,9 +83,7 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
create_callback_group(
|
||||
rclcpp::CallbackGroupType group_type,
|
||||
bool automatically_add_to_executor_with_node = true) override;
|
||||
create_callback_group(rclcpp::CallbackGroupType group_type) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
@@ -118,10 +116,6 @@ public:
|
||||
bool
|
||||
get_enable_topic_statistics_default() const override;
|
||||
|
||||
std::string
|
||||
resolve_topic_or_service_name(
|
||||
const std::string & name, bool is_service, bool only_expand = false) const override;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeBase)
|
||||
|
||||
|
||||
@@ -106,9 +106,7 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
create_callback_group(
|
||||
rclcpp::CallbackGroupType group_type,
|
||||
bool automatically_add_to_executor_with_node = true) = 0;
|
||||
create_callback_group(rclcpp::CallbackGroupType group_type) = 0;
|
||||
|
||||
/// Return the default callback group.
|
||||
RCLCPP_PUBLIC
|
||||
@@ -163,13 +161,6 @@ public:
|
||||
virtual
|
||||
bool
|
||||
get_enable_topic_statistics_default() const = 0;
|
||||
|
||||
/// Expand and remap a given topic or service name.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::string
|
||||
resolve_topic_or_service_name(
|
||||
const std::string & name, bool is_service, bool only_expand = false) const = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_graph_users() const override;
|
||||
count_graph_users() override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::TopicEndpointInfo>
|
||||
|
||||
@@ -146,7 +146,6 @@ public:
|
||||
/**
|
||||
* A topic is considered to exist when at least one publisher or subscriber
|
||||
* exists for it, whether they be local or remote to this process.
|
||||
* The returned names are the actual names used and do not have remap rules applied.
|
||||
*
|
||||
* \param[in] no_demangle if true, topic names and types are not demangled
|
||||
*/
|
||||
@@ -160,7 +159,6 @@ public:
|
||||
* A service is considered to exist when at least one service server or
|
||||
* service client exists for it, whether they be local or remote to this
|
||||
* process.
|
||||
* The returned names are the actual names used and do not have remap rules applied.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
@@ -170,7 +168,6 @@ public:
|
||||
/// Return a map of existing service names to list of service types for a specific node.
|
||||
/**
|
||||
* This function only considers services - not clients.
|
||||
* The returned names are the actual names used and do not have remap rules applied.
|
||||
*
|
||||
* \param[in] node_name name of the node
|
||||
* \param[in] namespace_ namespace of the node
|
||||
@@ -183,36 +180,24 @@ public:
|
||||
const std::string & namespace_) const = 0;
|
||||
|
||||
/// Return a vector of existing node names (string).
|
||||
/*
|
||||
* The returned names are the actual names used and do not have remap rules applied.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::vector<std::string>
|
||||
get_node_names() const = 0;
|
||||
|
||||
/// Return a vector of existing node names and namespaces (pair of string).
|
||||
/*
|
||||
* The returned names are the actual names used and do not have remap rules applied.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::vector<std::pair<std::string, std::string>>
|
||||
get_node_names_and_namespaces() const = 0;
|
||||
|
||||
/// Return the number of publishers that are advertised on a given topic.
|
||||
/*
|
||||
* \param[in] topic_name the actual topic name used; it will not be automatically remapped.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
size_t
|
||||
count_publishers(const std::string & topic_name) const = 0;
|
||||
|
||||
/// Return the number of subscribers who have created a subscription for a given topic.
|
||||
/*
|
||||
* \param[in] topic_name the actual topic name used; it will not be automatically remapped.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
size_t
|
||||
@@ -278,11 +263,10 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
size_t
|
||||
count_graph_users() const = 0;
|
||||
count_graph_users() = 0;
|
||||
|
||||
/// Return the topic endpoint information about publishers on a given topic.
|
||||
/**
|
||||
* \param[in] topic_name the actual topic name used; it will not be automatically remapped.
|
||||
* \sa rclcpp::Node::get_publishers_info_by_topic
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
@@ -292,7 +276,6 @@ public:
|
||||
|
||||
/// Return the topic endpoint information about subscriptions on a given topic.
|
||||
/**
|
||||
* \param[in] topic_name the actual topic name used; it will not be automatically remapped.
|
||||
* \sa rclcpp::Node::get_subscriptions_info_by_topic
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
@@ -103,42 +103,13 @@ public:
|
||||
virtual
|
||||
~NodeParameters();
|
||||
|
||||
// This is overriding a deprecated method, so we need to ignore the deprecation warning here.
|
||||
// Users of the method will still get a warning!
|
||||
#ifndef _WIN32
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
[[deprecated(RCLCPP_INTERNAL_NODE_PARAMETERS_INTERFACE_DEPRECATE_DECLARE)]]
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(const std::string & name) override;
|
||||
#ifndef _WIN32
|
||||
# pragma GCC diagnostic pop
|
||||
#else
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor{},
|
||||
bool ignore_override = false) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
rclcpp::ParameterType type,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor(),
|
||||
bool ignore_override = false) override;
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
|
||||
bool ignore_override) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
@@ -199,6 +170,11 @@ public:
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler) override;
|
||||
|
||||
[[deprecated("use add_on_set_parameters_callback(OnParametersSetCallbackType callback) instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
OnParametersSetCallbackType
|
||||
set_on_parameters_set_callback(OnParametersSetCallbackType callback) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::map<std::string, rclcpp::ParameterValue> &
|
||||
get_parameter_overrides() const override;
|
||||
|
||||
@@ -45,17 +45,6 @@ struct OnSetParametersCallbackHandle
|
||||
OnParametersSetCallbackType callback;
|
||||
};
|
||||
|
||||
#define RCLCPP_INTERNAL_NODE_PARAMETERS_INTERFACE_DEPRECATE_DECLARE \
|
||||
"declare_parameter() with only a name is deprecated and will be deleted in the future.\n" \
|
||||
"If you want to declare a parameter that won't change type without a default value use:\n" \
|
||||
"`node_params->declare_parameter(name, type)`, with e.g. type=rclcpp::PARAMETER_INTEGER.\n\n" \
|
||||
"If you want to declare a parameter that can dynamically change type use:\n" \
|
||||
"```\n" \
|
||||
"rcl_interfaces::msg::ParameterDescriptor descriptor;\n" \
|
||||
"descriptor.dynamic_typing = true;\n" \
|
||||
"node_params->declare_parameter(name, rclcpp::ParameterValue{}, descriptor);\n" \
|
||||
"```"
|
||||
|
||||
/// Pure virtual interface class for the NodeParameters part of the Node API.
|
||||
class NodeParametersInterface
|
||||
{
|
||||
@@ -66,15 +55,6 @@ public:
|
||||
virtual
|
||||
~NodeParametersInterface() = default;
|
||||
|
||||
/// Declare a parameter.
|
||||
/**
|
||||
* \sa rclcpp::Node::declare_parameter
|
||||
*/
|
||||
[[deprecated(RCLCPP_INTERNAL_NODE_PARAMETERS_INTERFACE_DEPRECATE_DECLARE)]]
|
||||
virtual
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(const std::string & name) = 0;
|
||||
|
||||
/// Declare and initialize a parameter.
|
||||
/**
|
||||
* \sa rclcpp::Node::declare_parameter
|
||||
@@ -84,21 +64,7 @@ public:
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor(),
|
||||
bool ignore_override = false) = 0;
|
||||
|
||||
/// Declare a parameter.
|
||||
/**
|
||||
* \sa rclcpp::Node::declare_parameter
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
rclcpp::ParameterType type,
|
||||
const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor(),
|
||||
bool ignore_override = false) = 0;
|
||||
@@ -130,7 +96,7 @@ public:
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
set_parameters(const std::vector<rclcpp::Parameter> & parameters) = 0;
|
||||
|
||||
/// Set one or more parameters, all at once.
|
||||
/// Set and initialize a parameter, all at once.
|
||||
/**
|
||||
* \sa rclcpp::Node::set_parameters_atomically
|
||||
*/
|
||||
@@ -225,6 +191,17 @@ public:
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler) = 0;
|
||||
|
||||
/// Register a callback for when parameters are being set, return an existing one.
|
||||
/**
|
||||
* \deprecated Use add_on_set_parameters_callback instead.
|
||||
* \sa rclcpp::Node::set_on_parameters_set_callback
|
||||
*/
|
||||
[[deprecated("use add_on_set_parameters_callback(OnParametersSetCallbackType callback) instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
OnParametersSetCallbackType
|
||||
set_on_parameters_set_callback(OnParametersSetCallbackType callback) = 0;
|
||||
|
||||
/// Return the initial parameter values used by the NodeParameters to override default values.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_SERVICES_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_SERVICES_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/client.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
@@ -55,10 +53,6 @@ public:
|
||||
rclcpp::ServiceBase::SharedPtr service_base_ptr,
|
||||
rclcpp::CallbackGroup::SharedPtr group) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
resolve_service_name(const std::string & name, bool only_expand = false) const override;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeServices)
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_SERVICES_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_SERVICES_INTERFACE_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/client.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
@@ -51,12 +49,6 @@ public:
|
||||
add_service(
|
||||
rclcpp::ServiceBase::SharedPtr service_base_ptr,
|
||||
rclcpp::CallbackGroup::SharedPtr group) = 0;
|
||||
|
||||
/// Get the remapped and expanded service name given a input name.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::string
|
||||
resolve_service_name(const std::string & name, bool only_expand = false) const = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "rclcpp/node_interfaces/node_services_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_time_source_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/time_source.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
@@ -47,9 +46,7 @@ public:
|
||||
rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services,
|
||||
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
|
||||
rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock,
|
||||
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters,
|
||||
const rclcpp::QoS & qos = rclcpp::RosoutQoS(),
|
||||
bool use_clock_thread = true
|
||||
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters
|
||||
);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
@@ -81,10 +81,6 @@ public:
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface() const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
resolve_topic_name(const std::string & name, bool only_expand = false) const override;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeTopics)
|
||||
|
||||
|
||||
@@ -86,12 +86,6 @@ public:
|
||||
virtual
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface() const = 0;
|
||||
|
||||
/// Get a remapped and expanded topic name given an input name.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::string
|
||||
resolve_topic_name(const std::string & name, bool only_expand = false) const = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -46,9 +46,6 @@ public:
|
||||
* - enable_topic_statistics = false
|
||||
* - start_parameter_services = true
|
||||
* - start_parameter_event_publisher = true
|
||||
* - clock_qos = rclcpp::ClockQoS()
|
||||
* - use_clock_thread = true
|
||||
* - rosout_qos = rclcpp::RosoutQoS()
|
||||
* - parameter_event_qos = rclcpp::ParameterEventQoS
|
||||
* - with history setting and depth from rmw_qos_profile_parameter_events
|
||||
* - parameter_event_publisher_options = rclcpp::PublisherOptionsBase
|
||||
@@ -246,33 +243,6 @@ public:
|
||||
NodeOptions &
|
||||
start_parameter_event_publisher(bool start_parameter_event_publisher);
|
||||
|
||||
/// Return a reference to the clock QoS.
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::QoS &
|
||||
clock_qos() const;
|
||||
|
||||
/// Set the clock QoS.
|
||||
/**
|
||||
* The QoS settings to be used for the publisher on /clock topic, if enabled.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
NodeOptions &
|
||||
clock_qos(const rclcpp::QoS & clock_qos);
|
||||
|
||||
|
||||
/// Return the use_clock_thread flag.
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
use_clock_thread() const;
|
||||
|
||||
/// Set the use_clock_thread flag, return this for parameter idiom.
|
||||
/**
|
||||
* If true, a dedicated thread will be used to subscribe to "/clock" topic.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
NodeOptions &
|
||||
use_clock_thread(bool use_clock_thread);
|
||||
|
||||
/// Return a reference to the parameter_event_qos QoS.
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::QoS &
|
||||
@@ -286,19 +256,6 @@ public:
|
||||
NodeOptions &
|
||||
parameter_event_qos(const rclcpp::QoS & parameter_event_qos);
|
||||
|
||||
/// Return a reference to the rosout QoS.
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::QoS &
|
||||
rosout_qos() const;
|
||||
|
||||
/// Set the rosout QoS.
|
||||
/**
|
||||
* The QoS settings to be used for the publisher on /rosout topic, if enabled.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
NodeOptions &
|
||||
rosout_qos(const rclcpp::QoS & rosout_qos);
|
||||
|
||||
/// Return a reference to the parameter_event_publisher_options.
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::PublisherOptionsBase &
|
||||
@@ -370,6 +327,11 @@ public:
|
||||
NodeOptions &
|
||||
allocator(rcl_allocator_t allocator);
|
||||
|
||||
protected:
|
||||
/// Retrieve the ROS_DOMAIN_ID environment variable and populate options.
|
||||
size_t
|
||||
get_domain_id_from_env() const;
|
||||
|
||||
private:
|
||||
// This is mutable to allow for a const accessor which lazily creates the node options instance.
|
||||
/// Underlying rcl_node_options structure.
|
||||
@@ -397,16 +359,10 @@ private:
|
||||
|
||||
bool start_parameter_event_publisher_ {true};
|
||||
|
||||
rclcpp::QoS clock_qos_ = rclcpp::ClockQoS();
|
||||
|
||||
bool use_clock_thread_ {true};
|
||||
|
||||
rclcpp::QoS parameter_event_qos_ = rclcpp::ParameterEventsQoS(
|
||||
rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events)
|
||||
);
|
||||
|
||||
rclcpp::QoS rosout_qos_ = rclcpp::RosoutQoS();
|
||||
|
||||
rclcpp::PublisherOptionsBase parameter_event_publisher_options_ = rclcpp::PublisherOptionsBase();
|
||||
|
||||
bool allow_undeclared_parameters_ {false};
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#ifndef RCLCPP__PARAMETER_CLIENT_HPP_
|
||||
#define RCLCPP__PARAMETER_CLIENT_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -31,14 +29,11 @@
|
||||
#include "rcl_interfaces/srv/list_parameters.hpp"
|
||||
#include "rcl_interfaces/srv/set_parameters.hpp"
|
||||
#include "rcl_interfaces/srv/set_parameters_atomically.hpp"
|
||||
#include "rcl_yaml_param_parser/parser.h"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rclcpp/create_subscription.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/parameter_map.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rmw/rmw.h"
|
||||
@@ -78,21 +73,12 @@ public:
|
||||
* \param[in] qos_profile (optional) The rmw qos profile to use to subscribe
|
||||
* \param[in] group (optional) The async parameter client will be added to this callback group.
|
||||
*/
|
||||
template<typename NodeT>
|
||||
RCLCPP_PUBLIC
|
||||
AsyncParametersClient(
|
||||
const std::shared_ptr<NodeT> node,
|
||||
const rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
|
||||
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,
|
||||
qos_profile,
|
||||
group)
|
||||
{}
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
@@ -101,21 +87,12 @@ public:
|
||||
* \param[in] qos_profile (optional) The rmw qos profile to use to subscribe
|
||||
* \param[in] group (optional) The async parameter client will be added to this callback group.
|
||||
*/
|
||||
template<typename NodeT>
|
||||
RCLCPP_PUBLIC
|
||||
AsyncParametersClient(
|
||||
NodeT * node,
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
|
||||
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,
|
||||
qos_profile,
|
||||
group)
|
||||
{}
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_future<std::vector<rclcpp::Parameter>>
|
||||
@@ -125,14 +102,6 @@ public:
|
||||
void(std::shared_future<std::vector<rclcpp::Parameter>>)
|
||||
> callback = nullptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_future<std::vector<rcl_interfaces::msg::ParameterDescriptor>>
|
||||
describe_parameters(
|
||||
const std::vector<std::string> & names,
|
||||
std::function<
|
||||
void(std::shared_future<std::vector<rcl_interfaces::msg::ParameterDescriptor>>)
|
||||
> callback = nullptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_future<std::vector<rclcpp::ParameterType>>
|
||||
get_parameter_types(
|
||||
@@ -157,42 +126,6 @@ public:
|
||||
void(std::shared_future<rcl_interfaces::msg::SetParametersResult>)
|
||||
> callback = nullptr);
|
||||
|
||||
/// Delete several parameters at once.
|
||||
/**
|
||||
* This function behaves like command-line tool `ros2 param delete` would.
|
||||
*
|
||||
* \param parameters_names vector of parameters names
|
||||
* \return the future of the set_parameter service used to delete the parameters
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_future<std::vector<rcl_interfaces::msg::SetParametersResult>>
|
||||
delete_parameters(
|
||||
const std::vector<std::string> & parameters_names);
|
||||
|
||||
/// Load parameters from yaml file.
|
||||
/**
|
||||
* This function behaves like command-line tool `ros2 param load` would.
|
||||
*
|
||||
* \param yaml_filename the full name of the yaml file
|
||||
* \return the future of the set_parameter service used to load the parameters
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_future<std::vector<rcl_interfaces::msg::SetParametersResult>>
|
||||
load_parameters(
|
||||
const std::string & yaml_filename);
|
||||
|
||||
/// Load parameters from parameter map.
|
||||
/**
|
||||
* This function filters the parameters to be set based on the node name.
|
||||
*
|
||||
* \param yaml_filename the full name of the yaml file
|
||||
* \return the future of the set_parameter service used to load the parameters
|
||||
* \throw InvalidParametersException if there is no parameter to set
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_future<std::vector<rcl_interfaces::msg::SetParametersResult>>
|
||||
load_parameters(const rclcpp::ParameterMap & parameter_map);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_future<rcl_interfaces::msg::ListParametersResult>
|
||||
list_parameters(
|
||||
@@ -304,61 +237,31 @@ class SyncParametersClient
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(SyncParametersClient)
|
||||
|
||||
template<typename NodeT>
|
||||
RCLCPP_PUBLIC
|
||||
explicit SyncParametersClient(
|
||||
std::shared_ptr<NodeT> node,
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters)
|
||||
: SyncParametersClient(
|
||||
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
|
||||
node,
|
||||
remote_node_name,
|
||||
qos_profile)
|
||||
{}
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
template<typename NodeT>
|
||||
RCLCPP_PUBLIC
|
||||
SyncParametersClient(
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
std::shared_ptr<NodeT> node,
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters)
|
||||
: 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,
|
||||
qos_profile)
|
||||
{}
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
template<typename NodeT>
|
||||
SyncParametersClient(
|
||||
NodeT * node,
|
||||
RCLCPP_PUBLIC
|
||||
explicit SyncParametersClient(
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters)
|
||||
: SyncParametersClient(
|
||||
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
|
||||
node,
|
||||
remote_node_name,
|
||||
qos_profile)
|
||||
{}
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
template<typename NodeT>
|
||||
RCLCPP_PUBLIC
|
||||
SyncParametersClient(
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
NodeT * node,
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters)
|
||||
: 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,
|
||||
qos_profile)
|
||||
{}
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
SyncParametersClient(
|
||||
@@ -368,30 +271,11 @@ public:
|
||||
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 = rmw_qos_profile_parameters)
|
||||
: 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,
|
||||
qos_profile);
|
||||
}
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
template<typename RepT = int64_t, typename RatioT = std::milli>
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::Parameter>
|
||||
get_parameters(
|
||||
const std::vector<std::string> & parameter_names,
|
||||
std::chrono::duration<RepT, RatioT> timeout = std::chrono::duration<RepT, RatioT>(-1))
|
||||
{
|
||||
return get_parameters(
|
||||
parameter_names,
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
|
||||
);
|
||||
}
|
||||
get_parameters(const std::vector<std::string> & parameter_names);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
@@ -435,107 +319,23 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
template<typename RepT = int64_t, typename RatioT = std::milli>
|
||||
std::vector<rcl_interfaces::msg::ParameterDescriptor>
|
||||
describe_parameters(
|
||||
const std::vector<std::string> & parameter_names,
|
||||
std::chrono::duration<RepT, RatioT> timeout = std::chrono::duration<RepT, RatioT>(-1))
|
||||
{
|
||||
return describe_parameters(
|
||||
parameter_names,
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename RepT = int64_t, typename RatioT = std::milli>
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::ParameterType>
|
||||
get_parameter_types(
|
||||
const std::vector<std::string> & parameter_names,
|
||||
std::chrono::duration<RepT, RatioT> timeout = std::chrono::duration<RepT, RatioT>(-1))
|
||||
{
|
||||
return get_parameter_types(
|
||||
parameter_names,
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
|
||||
);
|
||||
}
|
||||
get_parameter_types(const std::vector<std::string> & parameter_names);
|
||||
|
||||
template<typename RepT = int64_t, typename RatioT = std::milli>
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
set_parameters(
|
||||
const std::vector<rclcpp::Parameter> & parameters,
|
||||
std::chrono::duration<RepT, RatioT> timeout = std::chrono::duration<RepT, RatioT>(-1))
|
||||
{
|
||||
return set_parameters(
|
||||
parameters,
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
|
||||
);
|
||||
}
|
||||
set_parameters(const std::vector<rclcpp::Parameter> & parameters);
|
||||
|
||||
template<typename RepT = int64_t, typename RatioT = std::milli>
|
||||
RCLCPP_PUBLIC
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
set_parameters_atomically(
|
||||
const std::vector<rclcpp::Parameter> & parameters,
|
||||
std::chrono::duration<RepT, RatioT> timeout = std::chrono::duration<RepT, RatioT>(-1))
|
||||
{
|
||||
return set_parameters_atomically(
|
||||
parameters,
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
|
||||
);
|
||||
}
|
||||
set_parameters_atomically(const std::vector<rclcpp::Parameter> & parameters);
|
||||
|
||||
/// Delete several parameters at once.
|
||||
/**
|
||||
* This function behaves like command-line tool `ros2 param delete` would.
|
||||
*
|
||||
* \param parameters_names vector of parameters names
|
||||
* \param timeout for the spin used to make it synchronous
|
||||
* \return the future of the set_parameter service used to delete the parameters
|
||||
*/
|
||||
template<typename RepT = int64_t, typename RatioT = std::milli>
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
delete_parameters(
|
||||
const std::vector<std::string> & parameters_names,
|
||||
std::chrono::duration<RepT, RatioT> timeout = std::chrono::duration<RepT, RatioT>(-1))
|
||||
{
|
||||
return delete_parameters(
|
||||
parameters_names,
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
|
||||
);
|
||||
}
|
||||
|
||||
/// Load parameters from yaml file.
|
||||
/**
|
||||
* This function behaves like command-line tool `ros2 param load` would.
|
||||
*
|
||||
* \param yaml_filename the full name of the yaml file
|
||||
* \param timeout for the spin used to make it synchronous
|
||||
* \return the future of the set_parameter service used to load the parameters
|
||||
*/
|
||||
template<typename RepT = int64_t, typename RatioT = std::milli>
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
load_parameters(
|
||||
const std::string & yaml_filename,
|
||||
std::chrono::duration<RepT, RatioT> timeout = std::chrono::duration<RepT, RatioT>(-1))
|
||||
{
|
||||
return load_parameters(
|
||||
yaml_filename,
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename RepT = int64_t, typename RatioT = std::milli>
|
||||
RCLCPP_PUBLIC
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
list_parameters(
|
||||
const std::vector<std::string> & parameter_prefixes,
|
||||
uint64_t depth,
|
||||
std::chrono::duration<RepT, RatioT> timeout = std::chrono::duration<RepT, RatioT>(-1))
|
||||
{
|
||||
return list_parameters(
|
||||
parameter_prefixes,
|
||||
depth,
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
|
||||
);
|
||||
}
|
||||
uint64_t depth);
|
||||
|
||||
template<typename CallbackT>
|
||||
typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
|
||||
@@ -578,56 +378,6 @@ public:
|
||||
return async_parameters_client_->wait_for_service(timeout);
|
||||
}
|
||||
|
||||
protected:
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::Parameter>
|
||||
get_parameters(
|
||||
const std::vector<std::string> & parameter_names,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rcl_interfaces::msg::ParameterDescriptor>
|
||||
describe_parameters(
|
||||
const std::vector<std::string> & parameter_names,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::ParameterType>
|
||||
get_parameter_types(
|
||||
const std::vector<std::string> & parameter_names,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
set_parameters(
|
||||
const std::vector<rclcpp::Parameter> & parameters,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
delete_parameters(
|
||||
const std::vector<std::string> & parameters_names,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
load_parameters(
|
||||
const std::string & yaml_filename,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
set_parameters_atomically(
|
||||
const std::vector<rclcpp::Parameter> & parameters,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
list_parameters(
|
||||
const std::vector<std::string> & parameter_prefixes,
|
||||
uint64_t depth,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
private:
|
||||
rclcpp::Executor::SharedPtr executor_;
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface_;
|
||||
|
||||
@@ -1,338 +0,0 @@
|
||||
// Copyright 2019 Intel 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__PARAMETER_EVENT_HANDLER_HPP_
|
||||
#define RCLCPP__PARAMETER_EVENT_HANDLER_HPP_
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/create_subscription.hpp"
|
||||
#include "rclcpp/node_interfaces/get_node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/get_node_topics_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/subscription.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rcl_interfaces/msg/parameter_event.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
struct ParameterCallbackHandle
|
||||
{
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(ParameterCallbackHandle)
|
||||
|
||||
using ParameterCallbackType = std::function<void (const rclcpp::Parameter &)>;
|
||||
|
||||
std::string parameter_name;
|
||||
std::string node_name;
|
||||
ParameterCallbackType callback;
|
||||
};
|
||||
|
||||
struct ParameterEventCallbackHandle
|
||||
{
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(ParameterEventCallbackHandle)
|
||||
|
||||
using ParameterEventCallbackType =
|
||||
std::function<void (const rcl_interfaces::msg::ParameterEvent &)>;
|
||||
|
||||
ParameterEventCallbackType callback;
|
||||
};
|
||||
|
||||
/// A class used to "handle" (monitor and respond to) changes to parameters.
|
||||
/**
|
||||
* The ParameterEventHandler class allows for the monitoring of changes to node parameters,
|
||||
* either a node's own parameters or parameters owned by other nodes in the system.
|
||||
* Multiple parameter callbacks can be set and will be invoked when the specified parameter
|
||||
* changes.
|
||||
*
|
||||
* The first step is to instantiate a ParameterEventHandler, providing a ROS node to use
|
||||
* to create any required subscriptions:
|
||||
*
|
||||
* auto param_handler = std::make_shared<rclcpp::ParameterEventHandler>(node);
|
||||
*
|
||||
* Next, you can supply a callback to the add_parameter_callback method, as follows:
|
||||
*
|
||||
* 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
|
||||
* the ROS node supplied in the ParameterEventHandler constructor.
|
||||
* The callback, a lambda function in this case, simply prints out the value of the parameter.
|
||||
*
|
||||
* You may also monitor for changes to parameters in other nodes by supplying the node
|
||||
* name to add_parameter_callback:
|
||||
*
|
||||
* 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".
|
||||
*
|
||||
* To remove a parameter callback, call remove_parameter_callback, passing the handle returned
|
||||
* from add_parameter_callback:
|
||||
*
|
||||
* 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.
|
||||
* You are likely interested in a subset of these parameter changes, so in the callback it
|
||||
* is convenient to use a regular expression on the node names or namespaces of interest.
|
||||
* For example:
|
||||
*
|
||||
* 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::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);
|
||||
*
|
||||
* For both parameter callbacks and parameter event callbacks, when multiple callbacks are added,
|
||||
* the callbacks are invoked last-in, first-called order (LIFO).
|
||||
*
|
||||
* To remove a parameter event callback, use:
|
||||
*
|
||||
* param_handler->remove_event_parameter_callback(handle);
|
||||
*/
|
||||
class ParameterEventHandler
|
||||
{
|
||||
public:
|
||||
/// Construct a parameter events monitor.
|
||||
/**
|
||||
* \param[in] node The node to use to create any required subscribers.
|
||||
* \param[in] qos The QoS settings to use for any subscriptions.
|
||||
*/
|
||||
template<typename NodeT>
|
||||
ParameterEventHandler(
|
||||
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);
|
||||
auto node_topics = rclcpp::node_interfaces::get_node_topics_interface(node);
|
||||
|
||||
event_subscription_ = rclcpp::create_subscription<rcl_interfaces::msg::ParameterEvent>(
|
||||
node_topics, "/parameter_events", qos,
|
||||
std::bind(&ParameterEventHandler::event_callback, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
using ParameterEventCallbackType =
|
||||
ParameterEventCallbackHandle::ParameterEventCallbackType;
|
||||
|
||||
/// Set a callback for all parameter events.
|
||||
/**
|
||||
* This function may be called multiple times to set multiple parameter event callbacks.
|
||||
*
|
||||
* \param[in] callback Function callback to be invoked on parameter updates.
|
||||
* \returns A handle used to refer to the callback.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
ParameterEventCallbackHandle::SharedPtr
|
||||
add_parameter_event_callback(
|
||||
ParameterEventCallbackType callback);
|
||||
|
||||
/// Remove parameter event callback registered with add_parameter_event_callback.
|
||||
/**
|
||||
* \param[in] callback_handle Handle of the callback to remove.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_parameter_event_callback(
|
||||
ParameterEventCallbackHandle::SharedPtr callback_handle);
|
||||
|
||||
using ParameterCallbackType = ParameterCallbackHandle::ParameterCallbackType;
|
||||
|
||||
/// Add a callback for a specified parameter.
|
||||
/**
|
||||
* If a node_name is not provided, defaults to the current node.
|
||||
*
|
||||
* \param[in] parameter_name Name of parameter to monitor.
|
||||
* \param[in] callback Function callback to be invoked upon parameter update.
|
||||
* \param[in] node_name Name of node which hosts the parameter.
|
||||
* \returns A handle used to refer to the callback.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
ParameterCallbackHandle::SharedPtr
|
||||
add_parameter_callback(
|
||||
const std::string & parameter_name,
|
||||
ParameterCallbackType callback,
|
||||
const std::string & node_name = "");
|
||||
|
||||
/// Remove a parameter callback registered with add_parameter_callback.
|
||||
/**
|
||||
* The parameter name and node name are inspected from the callback handle. The callback handle
|
||||
* is erased from the list of callback handles on the {parameter_name, node_name} in the map.
|
||||
* An error is thrown if the handle does not exist and/or was already removed.
|
||||
*
|
||||
* \param[in] callback_handle Handle of the callback to remove.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_parameter_callback(
|
||||
ParameterCallbackHandle::SharedPtr callback_handle);
|
||||
|
||||
/// Get an rclcpp::Parameter from a parameter event.
|
||||
/**
|
||||
* If a node_name is not provided, defaults to the current node.
|
||||
*
|
||||
* \param[in] event Event msg to be inspected.
|
||||
* \param[out] parameter Reference to rclcpp::Parameter to be assigned.
|
||||
* \param[in] parameter_name Name of parameter.
|
||||
* \param[in] node_name Name of node which hosts the parameter.
|
||||
* \returns Output parameter is set with requested parameter info and returns true if
|
||||
* requested parameter name and node is in event. Otherwise, returns false.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
static bool
|
||||
get_parameter_from_event(
|
||||
const rcl_interfaces::msg::ParameterEvent & event,
|
||||
rclcpp::Parameter & parameter,
|
||||
const std::string parameter_name,
|
||||
const std::string node_name = "");
|
||||
|
||||
/// Get an rclcpp::Parameter from parameter event
|
||||
/**
|
||||
* If a node_name is not provided, defaults to the current node.
|
||||
*
|
||||
* The user is responsible to check if the returned parameter has been properly assigned.
|
||||
* By default, if the requested parameter is not found in the event, the returned parameter
|
||||
* has parameter value of type rclcpp::PARAMETER_NOT_SET.
|
||||
*
|
||||
* \param[in] event Event msg to be inspected.
|
||||
* \param[in] parameter_name Name of parameter.
|
||||
* \param[in] node_name Name of node which hosts the parameter.
|
||||
* \returns The resultant rclcpp::Parameter from the event.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
static rclcpp::Parameter
|
||||
get_parameter_from_event(
|
||||
const rcl_interfaces::msg::ParameterEvent & event,
|
||||
const std::string parameter_name,
|
||||
const std::string node_name = "");
|
||||
|
||||
/// Get all rclcpp::Parameter values from a parameter event
|
||||
/**
|
||||
* \param[in] event Event msg to be inspected.
|
||||
* \returns A vector rclcpp::Parameter values from the event.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
static std::vector<rclcpp::Parameter>
|
||||
get_parameters_from_event(
|
||||
const rcl_interfaces::msg::ParameterEvent & event);
|
||||
|
||||
using CallbacksContainerType = std::list<ParameterCallbackHandle::WeakPtr>;
|
||||
|
||||
protected:
|
||||
/// Callback for parameter events subscriptions.
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
event_callback(const rcl_interfaces::msg::ParameterEvent & event);
|
||||
|
||||
// Utility function for resolving node path.
|
||||
std::string resolve_path(const std::string & path);
|
||||
|
||||
// Node interface used for base functionality
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface> node_base_;
|
||||
|
||||
// *INDENT-OFF* Uncrustify doesn't handle indented public/private labels
|
||||
// Hash function for string pair required in std::unordered_map
|
||||
// See: https://stackoverflow.com/questions/35985960/c-why-is-boosthash-combine-the-best-way-to-combine-hash-values
|
||||
class StringPairHash
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
inline void hash_combine(std::size_t & seed, const T & v) const
|
||||
{
|
||||
std::hash<T> hasher;
|
||||
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
|
||||
inline size_t operator()(const std::pair<std::string, std::string> & s) const
|
||||
{
|
||||
size_t seed = 0;
|
||||
hash_combine(seed, s.first);
|
||||
hash_combine(seed, s.second);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
// *INDENT-ON*
|
||||
|
||||
// Map container for registered parameters
|
||||
std::unordered_map<
|
||||
std::pair<std::string, std::string>,
|
||||
CallbacksContainerType,
|
||||
StringPairHash
|
||||
> parameter_callbacks_;
|
||||
|
||||
rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr event_subscription_;
|
||||
|
||||
std::list<ParameterEventCallbackHandle::WeakPtr> event_callbacks_;
|
||||
|
||||
std::recursive_mutex mutex_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__PARAMETER_EVENT_HANDLER_HPP_
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(ParameterEventsFilter)
|
||||
enum class EventType {NEW, DELETED, CHANGED}; ///< An enum for the type of event.
|
||||
/// Used for the listed results
|
||||
using EventPair = std::pair<EventType, const rcl_interfaces::msg::Parameter *>;
|
||||
using EventPair = std::pair<EventType, rcl_interfaces::msg::Parameter *>;
|
||||
|
||||
/// Construct a filtered view of a parameter event.
|
||||
/**
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
ParameterEventsFilter(
|
||||
std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event,
|
||||
rcl_interfaces::msg::ParameterEvent::SharedPtr event,
|
||||
const std::vector<std::string> & names,
|
||||
const std::vector<EventType> & types);
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
private:
|
||||
// access only allowed via const accessor.
|
||||
std::vector<EventPair> result_; ///< Storage of the resultant vector
|
||||
std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event_; ///< Keep event in scope
|
||||
rcl_interfaces::msg::ParameterEvent::SharedPtr event_; ///< Keep event in scope
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#ifndef RCLCPP__PARAMETER_MAP_HPP_
|
||||
#define RCLCPP__PARAMETER_MAP_HPP_
|
||||
|
||||
#include <rcl_yaml_param_parser/parser.h>
|
||||
#include <rcl_yaml_param_parser/types.h>
|
||||
|
||||
#include <string>
|
||||
@@ -49,14 +48,6 @@ RCLCPP_PUBLIC
|
||||
ParameterValue
|
||||
parameter_value_from(const rcl_variant_t * const c_value);
|
||||
|
||||
/// Get the ParameterMap from a yaml file.
|
||||
/// \param[in] yaml_filename full name of the yaml file.
|
||||
/// \returns an instance of a parameter map
|
||||
/// \throws from rcl error of rcl_parse_yaml_file()
|
||||
RCLCPP_PUBLIC
|
||||
ParameterMap
|
||||
parameter_map_from_yaml_file(const std::string & yaml_filename);
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__PARAMETER_MAP_HPP_
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#ifndef RCLCPP__PUBLISHER_HPP_
|
||||
#define RCLCPP__PUBLISHER_HPP_
|
||||
|
||||
#include <rmw/error_handling.h>
|
||||
#include <rmw/rmw.h>
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@@ -24,26 +27,19 @@
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/publisher.h"
|
||||
#include "rmw/error_handling.h"
|
||||
#include "rmw/rmw.h"
|
||||
|
||||
#include "rclcpp/allocator/allocator_common.hpp"
|
||||
#include "rclcpp/allocator/allocator_deleter.hpp"
|
||||
#include "rclcpp/detail/resolve_use_intra_process.hpp"
|
||||
#include "rclcpp/experimental/intra_process_manager.hpp"
|
||||
#include "rclcpp/get_message_type_support_handle.hpp"
|
||||
#include "rclcpp/is_ros_compatible_type.hpp"
|
||||
#include "rclcpp/loaned_message.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/publisher_base.hpp"
|
||||
#include "rclcpp/publisher_options.hpp"
|
||||
#include "rclcpp/type_adapter.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "tracetools/tracetools.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
@@ -51,62 +47,15 @@ template<typename MessageT, typename AllocatorT>
|
||||
class LoanedMessage;
|
||||
|
||||
/// A publisher publishes messages of any type to a topic.
|
||||
/**
|
||||
* MessageT must be a:
|
||||
*
|
||||
* - ROS message type with its own type support (e.g. std_msgs::msgs::String), or a
|
||||
* - rclcpp::TypeAdapter<CustomType, ROSMessageType>
|
||||
* (e.g. rclcpp::TypeAdapter<std::string, std_msgs::msg::String), or a
|
||||
* - custom type that has been setup as the implicit type for a ROS type using
|
||||
* RCLCPP_USING_CUSTOM_TYPE_AS_ROS_MESSAGE_TYPE(custom_type, ros_message_type)
|
||||
*
|
||||
* In the case that MessageT is ROS message type (e.g. std_msgs::msg::String),
|
||||
* both PublishedType and ROSMessageType will be that type.
|
||||
* In the case that MessageT is a TypeAdapter<CustomType, ROSMessageType> type
|
||||
* (e.g. TypeAdapter<std::string, std_msgs::msg::String>), PublishedType will
|
||||
* be the custom type, and ROSMessageType will be the ros message type.
|
||||
*
|
||||
* This is achieved because of the "identity specialization" for TypeAdapter,
|
||||
* which returns itself if it is already a TypeAdapter, and the default
|
||||
* specialization which allows ROSMessageType to be void.
|
||||
* \sa rclcpp::TypeAdapter for more details.
|
||||
*/
|
||||
template<typename MessageT, typename AllocatorT = std::allocator<void>>
|
||||
class Publisher : public PublisherBase
|
||||
{
|
||||
public:
|
||||
static_assert(
|
||||
rclcpp::is_ros_compatible_type<MessageT>::value,
|
||||
"given message type is not compatible with ROS and cannot be used with a Publisher");
|
||||
|
||||
/// MessageT::custom_type if MessageT is a TypeAdapter, otherwise just MessageT.
|
||||
using PublishedType = typename rclcpp::TypeAdapter<MessageT>::custom_type;
|
||||
/// MessageT::ros_message_type if MessageT is a TypeAdapter, otherwise just MessageT.
|
||||
using ROSMessageType = typename rclcpp::TypeAdapter<MessageT>::ros_message_type;
|
||||
|
||||
using PublishedTypeAllocatorTraits = allocator::AllocRebind<PublishedType, AllocatorT>;
|
||||
using PublishedTypeAllocator = typename PublishedTypeAllocatorTraits::allocator_type;
|
||||
using PublishedTypeDeleter = allocator::Deleter<PublishedTypeAllocator, PublishedType>;
|
||||
|
||||
using ROSMessageTypeAllocatorTraits = allocator::AllocRebind<ROSMessageType, AllocatorT>;
|
||||
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 MessageAllocatorTraits = allocator::AllocRebind<MessageT, AllocatorT>;
|
||||
using MessageAllocator = typename MessageAllocatorTraits::allocator_type;
|
||||
using MessageDeleter = allocator::Deleter<MessageAllocator, MessageT>;
|
||||
using MessageUniquePtr = std::unique_ptr<MessageT, MessageDeleter>;
|
||||
using MessageSharedPtr = std::shared_ptr<const MessageT>;
|
||||
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(Publisher<MessageT, AllocatorT>)
|
||||
|
||||
@@ -119,7 +68,7 @@ public:
|
||||
* \param[in] node_base NodeBaseInterface pointer that is used in part of the setup.
|
||||
* \param[in] topic Name of the topic to publish to.
|
||||
* \param[in] qos QoS profile for Subcription.
|
||||
* \param[in] options Options for the subscription.
|
||||
* \param[in] options options for the subscription.
|
||||
*/
|
||||
Publisher(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
@@ -129,14 +78,12 @@ public:
|
||||
: PublisherBase(
|
||||
node_base,
|
||||
topic,
|
||||
rclcpp::get_message_type_support_handle<MessageT>(),
|
||||
*rosidl_typesupport_cpp::get_message_type_support_handle<MessageT>(),
|
||||
options.template to_rcl_publisher_options<MessageT>(qos)),
|
||||
options_(options),
|
||||
published_type_allocator_(*options.get_allocator()),
|
||||
ros_message_type_allocator_(*options.get_allocator())
|
||||
message_allocator_(new MessageAllocator(*options.get_allocator().get()))
|
||||
{
|
||||
allocator::set_allocator_for_deleter(&published_type_deleter_, &published_type_allocator_);
|
||||
allocator::set_allocator_for_deleter(&ros_message_type_deleter_, &ros_message_type_allocator_);
|
||||
allocator::set_allocator_for_deleter(&message_deleter_, message_allocator_.get());
|
||||
|
||||
if (options_.event_callbacks.deadline_callback) {
|
||||
this->add_event_handler(
|
||||
@@ -186,15 +133,15 @@ public:
|
||||
// Get the intra process manager instance for this context.
|
||||
auto ipm = context->get_sub_context<rclcpp::experimental::IntraProcessManager>();
|
||||
// Register the publisher with the intra process manager.
|
||||
if (qos.history() != rclcpp::HistoryPolicy::KeepLast) {
|
||||
if (qos.get_rmw_qos_profile().history == RMW_QOS_POLICY_HISTORY_KEEP_ALL) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication allowed only with keep last history qos policy");
|
||||
"intraprocess communication is not allowed with keep all history qos policy");
|
||||
}
|
||||
if (qos.depth() == 0) {
|
||||
if (qos.get_rmw_qos_profile().depth == 0) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication is not allowed with a zero qos history depth value");
|
||||
}
|
||||
if (qos.durability() != rclcpp::DurabilityPolicy::Volatile) {
|
||||
if (qos.get_rmw_qos_profile().durability != RMW_QOS_POLICY_DURABILITY_VOLATILE) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication allowed only with volatile durability");
|
||||
}
|
||||
@@ -221,33 +168,21 @@ public:
|
||||
* allocator.
|
||||
* \sa rclcpp::LoanedMessage for details of the LoanedMessage class.
|
||||
*
|
||||
* \return LoanedMessage containing memory for a ROS message of type ROSMessageType
|
||||
* \return LoanedMessage containing memory for a ROS message of type MessageT
|
||||
*/
|
||||
rclcpp::LoanedMessage<ROSMessageType, AllocatorT>
|
||||
rclcpp::LoanedMessage<MessageT, AllocatorT>
|
||||
borrow_loaned_message()
|
||||
{
|
||||
return rclcpp::LoanedMessage<ROSMessageType, AllocatorT>(
|
||||
*this,
|
||||
this->get_ros_message_type_allocator());
|
||||
return rclcpp::LoanedMessage<MessageT, AllocatorT>(this, this->get_allocator());
|
||||
}
|
||||
|
||||
/// Publish a message on the topic.
|
||||
/// Send a message to the topic for this publisher.
|
||||
/**
|
||||
* This signature is enabled if the element_type of the std::unique_ptr is
|
||||
* a ROS message type, as opposed to the custom_type of a TypeAdapter, and
|
||||
* that type matches the type given when creating the publisher.
|
||||
*
|
||||
* This signature allows the user to give ownership of the message to rclcpp,
|
||||
* allowing for more efficient intra-process communication optimizations.
|
||||
*
|
||||
* \param[in] msg A unique pointer to the message to send.
|
||||
* This function is templated on the input message type, MessageT.
|
||||
* \param[in] msg A shared pointer to the message to send.
|
||||
*/
|
||||
template<typename T>
|
||||
typename std::enable_if_t<
|
||||
rosidl_generator_traits::is_message<T>::value &&
|
||||
std::is_same<T, ROSMessageType>::value
|
||||
>
|
||||
publish(std::unique_ptr<T, ROSMessageTypeDeleter> msg)
|
||||
virtual void
|
||||
publish(std::unique_ptr<MessageT, MessageDeleter> msg)
|
||||
{
|
||||
if (!intra_process_is_enabled_) {
|
||||
this->do_inter_process_publish(*msg);
|
||||
@@ -270,24 +205,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// Publish a message on the topic.
|
||||
/**
|
||||
* This signature is enabled if the object being published is
|
||||
* a ROS message type, as opposed to the custom_type of a TypeAdapter, and
|
||||
* that type matches the type given when creating the publisher.
|
||||
*
|
||||
* This signature allows the user to give a reference to a message, which is
|
||||
* copied onto the heap without modification so that a copy can be owned by
|
||||
* rclcpp and ownership of the copy can be moved later if needed.
|
||||
*
|
||||
* \param[in] msg A const reference to the message to send.
|
||||
*/
|
||||
template<typename T>
|
||||
typename std::enable_if_t<
|
||||
rosidl_generator_traits::is_message<T>::value &&
|
||||
std::is_same<T, ROSMessageType>::value
|
||||
>
|
||||
publish(const T & msg)
|
||||
virtual void
|
||||
publish(const MessageT & msg)
|
||||
{
|
||||
// Avoid allocating when not using intra process.
|
||||
if (!intra_process_is_enabled_) {
|
||||
@@ -297,77 +216,12 @@ public:
|
||||
// Otherwise we have to allocate memory in a unique_ptr and pass it along.
|
||||
// As the message is not const, a copy should be made.
|
||||
// A shared_ptr<const MessageT> could also be constructed here.
|
||||
auto unique_msg = this->duplicate_ros_message_as_unique_ptr(msg);
|
||||
auto ptr = MessageAllocatorTraits::allocate(*message_allocator_.get(), 1);
|
||||
MessageAllocatorTraits::construct(*message_allocator_.get(), ptr, msg);
|
||||
MessageUniquePtr unique_msg(ptr, message_deleter_);
|
||||
this->publish(std::move(unique_msg));
|
||||
}
|
||||
|
||||
/// Publish a message on the topic.
|
||||
/**
|
||||
* This signature is enabled if this class was created with a TypeAdapter and
|
||||
* the element_type of the std::unique_ptr matches the custom_type for the
|
||||
* TypeAdapter used with this class.
|
||||
*
|
||||
* This signature allows the user to give ownership of the message to rclcpp,
|
||||
* allowing for more efficient intra-process communication optimizations.
|
||||
*
|
||||
* \param[in] msg A unique pointer to the message to send.
|
||||
*/
|
||||
template<typename T>
|
||||
typename std::enable_if_t<
|
||||
rclcpp::TypeAdapter<MessageT>::is_specialized::value &&
|
||||
std::is_same<T, PublishedType>::value
|
||||
>
|
||||
publish(std::unique_ptr<T, PublishedTypeDeleter> msg)
|
||||
{
|
||||
// TODO(wjwwood): later update this to give the unique_ptr to the intra
|
||||
// process manager and let it decide if it needs to be converted or not.
|
||||
// For now, convert it unconditionally and pass it the ROSMessageType
|
||||
// publish function specialization.
|
||||
auto unique_ros_msg = this->create_ros_message_unique_ptr();
|
||||
rclcpp::TypeAdapter<MessageT>::convert_to_ros_message(*msg, *unique_ros_msg);
|
||||
this->publish(std::move(unique_ros_msg));
|
||||
}
|
||||
|
||||
/// Publish a message on the topic.
|
||||
/**
|
||||
* This signature is enabled if this class was created with a TypeAdapter and
|
||||
* the given type matches the custom_type of the TypeAdapter.
|
||||
*
|
||||
* This signature allows the user to give a reference to a message, which is
|
||||
* copied onto the heap without modification so that a copy can be owned by
|
||||
* rclcpp and ownership of the copy can be moved later if needed.
|
||||
*
|
||||
* \param[in] msg A const reference to the message to send.
|
||||
*/
|
||||
template<typename T>
|
||||
typename std::enable_if_t<
|
||||
rclcpp::TypeAdapter<MessageT>::is_specialized::value &&
|
||||
std::is_same<T, PublishedType>::value
|
||||
>
|
||||
publish(const T & msg)
|
||||
{
|
||||
// TODO(wjwwood): later update this to give the unique_ptr to the intra
|
||||
// process manager and let it decide if it needs to be converted or not.
|
||||
// For now, convert it unconditionally and pass it the ROSMessageType
|
||||
// publish function specialization.
|
||||
|
||||
// Avoid allocating when not using intra process.
|
||||
if (!intra_process_is_enabled_) {
|
||||
// Convert to the ROS message equivalent and publish it.
|
||||
ROSMessageType ros_msg;
|
||||
rclcpp::TypeAdapter<MessageT>::convert_to_ros_message(msg, ros_msg);
|
||||
// In this case we're not using intra process.
|
||||
return this->do_inter_process_publish(ros_msg);
|
||||
}
|
||||
// Otherwise we have to allocate memory in a unique_ptr, convert it,
|
||||
// and pass it along.
|
||||
// As the message is not const, a copy should be made.
|
||||
// A shared_ptr<const MessageT> could also be constructed here.
|
||||
auto unique_ros_msg = this->create_ros_message_unique_ptr();
|
||||
rclcpp::TypeAdapter<MessageT>::convert_to_ros_message(msg, *unique_ros_msg);
|
||||
this->publish(std::move(unique_ros_msg));
|
||||
}
|
||||
|
||||
void
|
||||
publish(const rcl_serialized_message_t & serialized_msg)
|
||||
{
|
||||
@@ -389,7 +243,7 @@ public:
|
||||
* \param loaned_msg The LoanedMessage instance to be published.
|
||||
*/
|
||||
void
|
||||
publish(rclcpp::LoanedMessage<ROSMessageType, AllocatorT> && loaned_msg)
|
||||
publish(rclcpp::LoanedMessage<MessageT, AllocatorT> && loaned_msg)
|
||||
{
|
||||
if (!loaned_msg.is_valid()) {
|
||||
throw std::runtime_error("loaned message is not valid");
|
||||
@@ -407,7 +261,7 @@ public:
|
||||
if (this->can_loan_messages()) {
|
||||
// we release the ownership from the rclpp::LoanedMessage instance
|
||||
// and let the middleware clean up the memory.
|
||||
this->do_loaned_message_publish(std::move(loaned_msg.release()));
|
||||
this->do_loaned_message_publish(loaned_msg.release());
|
||||
} else {
|
||||
// we don't release the ownership, let the middleware copy the ros message
|
||||
// and thus the destructor of rclcpp::LoanedMessage cleans up the memory.
|
||||
@@ -415,33 +269,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
[[deprecated("use get_published_type_allocator() or get_ros_message_type_allocator() instead")]]
|
||||
std::shared_ptr<PublishedTypeAllocator>
|
||||
std::shared_ptr<MessageAllocator>
|
||||
get_allocator() const
|
||||
{
|
||||
return std::make_shared<PublishedTypeAllocator>(published_type_allocator_);
|
||||
}
|
||||
|
||||
PublishedTypeAllocator
|
||||
get_published_type_allocator() const
|
||||
{
|
||||
return published_type_allocator_;
|
||||
}
|
||||
|
||||
ROSMessageTypeAllocator
|
||||
get_ros_message_type_allocator() const
|
||||
{
|
||||
return ros_message_type_allocator_;
|
||||
return message_allocator_;
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
do_inter_process_publish(const ROSMessageType & msg)
|
||||
do_inter_process_publish(const MessageT & msg)
|
||||
{
|
||||
TRACEPOINT(
|
||||
rclcpp_publish,
|
||||
static_cast<const void *>(publisher_handle_.get()),
|
||||
static_cast<const void *>(&msg));
|
||||
auto status = rcl_publish(publisher_handle_.get(), &msg, nullptr);
|
||||
|
||||
if (RCL_RET_PUBLISHER_INVALID == status) {
|
||||
@@ -473,10 +310,9 @@ protected:
|
||||
}
|
||||
|
||||
void
|
||||
do_loaned_message_publish(
|
||||
std::unique_ptr<ROSMessageType, std::function<void(ROSMessageType *)>> msg)
|
||||
do_loaned_message_publish(MessageT * msg)
|
||||
{
|
||||
auto status = rcl_publish_loaned_message(publisher_handle_.get(), msg.get(), nullptr);
|
||||
auto status = rcl_publish_loaned_message(publisher_handle_.get(), msg, nullptr);
|
||||
|
||||
if (RCL_RET_PUBLISHER_INVALID == status) {
|
||||
rcl_reset_error(); // next call will reset error message if not context
|
||||
@@ -494,7 +330,7 @@ protected:
|
||||
}
|
||||
|
||||
void
|
||||
do_intra_process_publish(std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter> msg)
|
||||
do_intra_process_publish(std::unique_ptr<MessageT, MessageDeleter> msg)
|
||||
{
|
||||
auto ipm = weak_ipm_.lock();
|
||||
if (!ipm) {
|
||||
@@ -505,15 +341,14 @@ protected:
|
||||
throw std::runtime_error("cannot publish msg which is a null pointer");
|
||||
}
|
||||
|
||||
ipm->template do_intra_process_publish<ROSMessageType, AllocatorT>(
|
||||
ipm->template do_intra_process_publish<MessageT, AllocatorT>(
|
||||
intra_process_publisher_id_,
|
||||
std::move(msg),
|
||||
ros_message_type_allocator_);
|
||||
message_allocator_);
|
||||
}
|
||||
|
||||
std::shared_ptr<const ROSMessageType>
|
||||
do_intra_process_publish_and_return_shared(
|
||||
std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter> msg)
|
||||
std::shared_ptr<const MessageT>
|
||||
do_intra_process_publish_and_return_shared(std::unique_ptr<MessageT, MessageDeleter> msg)
|
||||
{
|
||||
auto ipm = weak_ipm_.lock();
|
||||
if (!ipm) {
|
||||
@@ -524,29 +359,10 @@ protected:
|
||||
throw std::runtime_error("cannot publish msg which is a null pointer");
|
||||
}
|
||||
|
||||
return ipm->template do_intra_process_publish_and_return_shared<ROSMessageType,
|
||||
AllocatorT>(
|
||||
return ipm->template do_intra_process_publish_and_return_shared<MessageT, AllocatorT>(
|
||||
intra_process_publisher_id_,
|
||||
std::move(msg),
|
||||
ros_message_type_allocator_);
|
||||
}
|
||||
|
||||
/// Return a new unique_ptr using the ROSMessageType of the publisher.
|
||||
std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>
|
||||
create_ros_message_unique_ptr()
|
||||
{
|
||||
auto ptr = ROSMessageTypeAllocatorTraits::allocate(ros_message_type_allocator_, 1);
|
||||
ROSMessageTypeAllocatorTraits::construct(ros_message_type_allocator_, ptr);
|
||||
return std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>(ptr, ros_message_type_deleter_);
|
||||
}
|
||||
|
||||
/// Duplicate a given ros message as a unique_ptr.
|
||||
std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>
|
||||
duplicate_ros_message_as_unique_ptr(const ROSMessageType & msg)
|
||||
{
|
||||
auto ptr = ROSMessageTypeAllocatorTraits::allocate(ros_message_type_allocator_, 1);
|
||||
ROSMessageTypeAllocatorTraits::construct(ros_message_type_allocator_, ptr, msg);
|
||||
return std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>(ptr, ros_message_type_deleter_);
|
||||
message_allocator_);
|
||||
}
|
||||
|
||||
/// Copy of original options passed during construction.
|
||||
@@ -556,10 +372,9 @@ protected:
|
||||
*/
|
||||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> options_;
|
||||
|
||||
PublishedTypeAllocator published_type_allocator_;
|
||||
PublishedTypeDeleter published_type_deleter_;
|
||||
ROSMessageTypeAllocator ros_message_type_allocator_;
|
||||
ROSMessageTypeDeleter ros_message_type_deleter_;
|
||||
std::shared_ptr<MessageAllocator> message_allocator_;
|
||||
|
||||
MessageDeleter message_deleter_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "rcl/publisher.h"
|
||||
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/network_flow_endpoint.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/qos_event.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
@@ -194,15 +193,6 @@ public:
|
||||
uint64_t intra_process_publisher_id,
|
||||
IntraProcessManagerSharedPtr ipm);
|
||||
|
||||
/// Get network flow endpoints
|
||||
/**
|
||||
* Describes network flow endpoints that this publisher is sending messages out on
|
||||
* \return vector of NetworkFlowEndpoint
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::NetworkFlowEndpoint>
|
||||
get_network_flow_endpoints() const;
|
||||
|
||||
protected:
|
||||
template<typename EventCallbackT>
|
||||
void
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/publisher.h"
|
||||
@@ -27,7 +26,6 @@
|
||||
#include "rclcpp/intra_process_setting.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/qos_event.hpp"
|
||||
#include "rclcpp/qos_overriding_options.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
@@ -46,29 +44,18 @@ struct PublisherOptionsBase
|
||||
/// Whether or not to use default callbacks when user doesn't supply any in event_callbacks
|
||||
bool use_default_callbacks = true;
|
||||
|
||||
/// Require middleware to generate unique network flow endpoints
|
||||
/// Disabled by default
|
||||
rmw_unique_network_flow_endpoints_requirement_t require_unique_network_flow_endpoints =
|
||||
RMW_UNIQUE_NETWORK_FLOW_ENDPOINTS_NOT_REQUIRED;
|
||||
|
||||
/// Callback group in which the waitable items from the publisher should be placed.
|
||||
std::shared_ptr<rclcpp::CallbackGroup> callback_group;
|
||||
|
||||
/// Optional RMW implementation specific payload to be used during creation of the publisher.
|
||||
std::shared_ptr<rclcpp::detail::RMWImplementationSpecificPublisherPayload>
|
||||
rmw_implementation_payload = nullptr;
|
||||
|
||||
QosOverridingOptions qos_overriding_options;
|
||||
};
|
||||
|
||||
/// Structure containing optional configuration for Publishers.
|
||||
template<typename Allocator>
|
||||
struct PublisherOptionsWithAllocator : public PublisherOptionsBase
|
||||
{
|
||||
static_assert(
|
||||
std::is_void_v<typename std::allocator_traits<Allocator>::value_type>,
|
||||
"Publisher allocator value type must be void");
|
||||
|
||||
/// Optional custom allocator.
|
||||
std::shared_ptr<Allocator> allocator = nullptr;
|
||||
|
||||
@@ -85,10 +72,11 @@ struct PublisherOptionsWithAllocator : public PublisherOptionsBase
|
||||
to_rcl_publisher_options(const rclcpp::QoS & qos) const
|
||||
{
|
||||
rcl_publisher_options_t result = rcl_publisher_get_default_options();
|
||||
result.allocator = this->get_rcl_allocator();
|
||||
using AllocatorTraits = std::allocator_traits<Allocator>;
|
||||
using MessageAllocatorT = typename AllocatorTraits::template rebind_alloc<MessageT>;
|
||||
auto message_alloc = std::make_shared<MessageAllocatorT>(*this->get_allocator().get());
|
||||
result.allocator = rclcpp::allocator::get_rcl_allocator<MessageT>(*message_alloc);
|
||||
result.qos = qos.get_rmw_qos_profile();
|
||||
result.rmw_publisher_options.require_unique_network_flow_endpoints =
|
||||
this->require_unique_network_flow_endpoints;
|
||||
|
||||
// Apply payload to rcl_publisher_options if necessary.
|
||||
if (rmw_implementation_payload && rmw_implementation_payload->has_been_customized()) {
|
||||
@@ -104,35 +92,10 @@ struct PublisherOptionsWithAllocator : public PublisherOptionsBase
|
||||
get_allocator() const
|
||||
{
|
||||
if (!this->allocator) {
|
||||
if (!allocator_storage_) {
|
||||
allocator_storage_ = std::make_shared<Allocator>();
|
||||
}
|
||||
return allocator_storage_;
|
||||
return std::make_shared<Allocator>();
|
||||
}
|
||||
return this->allocator;
|
||||
}
|
||||
|
||||
private:
|
||||
using PlainAllocator =
|
||||
typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
|
||||
|
||||
rcl_allocator_t
|
||||
get_rcl_allocator() const
|
||||
{
|
||||
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()
|
||||
// always returns a copy of the same allocator.
|
||||
mutable std::shared_ptr<Allocator> allocator_storage_;
|
||||
|
||||
// This is a temporal workaround, to keep the plain allocator that backs
|
||||
// up the rcl allocator returned in rcl_publisher_options_t alive.
|
||||
mutable std::shared_ptr<PlainAllocator> plain_allocator_storage_;
|
||||
};
|
||||
|
||||
using PublisherOptions = PublisherOptionsWithAllocator<std::allocator<void>>;
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/duration.hpp"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rcl/logging_rosout.h"
|
||||
#include "rmw/incompatible_qos_events_statuses.h"
|
||||
#include "rmw/qos_profiles.h"
|
||||
#include "rmw/types.h"
|
||||
@@ -31,45 +29,6 @@ namespace rclcpp
|
||||
RCLCPP_PUBLIC
|
||||
std::string qos_policy_name_from_kind(rmw_qos_policy_kind_t policy_kind);
|
||||
|
||||
enum class HistoryPolicy
|
||||
{
|
||||
KeepLast = RMW_QOS_POLICY_HISTORY_KEEP_LAST,
|
||||
KeepAll = RMW_QOS_POLICY_HISTORY_KEEP_ALL,
|
||||
SystemDefault = RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT,
|
||||
Unknown = RMW_QOS_POLICY_HISTORY_UNKNOWN,
|
||||
};
|
||||
|
||||
enum class ReliabilityPolicy
|
||||
{
|
||||
BestEffort = RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT,
|
||||
Reliable = RMW_QOS_POLICY_RELIABILITY_RELIABLE,
|
||||
SystemDefault = RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT,
|
||||
Unknown = RMW_QOS_POLICY_RELIABILITY_UNKNOWN,
|
||||
};
|
||||
|
||||
enum class DurabilityPolicy
|
||||
{
|
||||
Volatile = RMW_QOS_POLICY_DURABILITY_VOLATILE,
|
||||
TransientLocal = RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL,
|
||||
SystemDefault = RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT,
|
||||
Unknown = RMW_QOS_POLICY_DURABILITY_UNKNOWN,
|
||||
};
|
||||
|
||||
enum class LivelinessPolicy
|
||||
{
|
||||
Automatic = RMW_QOS_POLICY_LIVELINESS_AUTOMATIC,
|
||||
ManualByTopic = RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC,
|
||||
SystemDefault = RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT,
|
||||
Unknown = RMW_QOS_POLICY_LIVELINESS_UNKNOWN,
|
||||
};
|
||||
|
||||
enum class QoSCompatibility
|
||||
{
|
||||
Ok = RMW_QOS_COMPATIBILITY_OK,
|
||||
Warning = RMW_QOS_COMPATIBILITY_WARNING,
|
||||
Error = RMW_QOS_COMPATIBILITY_ERROR,
|
||||
};
|
||||
|
||||
/// QoS initialization values, cannot be created directly, use KeepAll or KeepLast instead.
|
||||
struct RCLCPP_PUBLIC QoSInitialization
|
||||
{
|
||||
@@ -98,32 +57,10 @@ struct RCLCPP_PUBLIC KeepLast : public rclcpp::QoSInitialization
|
||||
};
|
||||
|
||||
/// Encapsulation of Quality of Service settings.
|
||||
/**
|
||||
* Quality of Service settings control the behavior of publishers, subscriptions,
|
||||
* and other entities, and includes things like how data is sent or resent,
|
||||
* how data is buffered on the publishing and subscribing side, and other things.
|
||||
* See:
|
||||
* <a href="https://docs.ros.org/en/rolling/Concepts/About-Quality-of-Service-Settings.html">
|
||||
* https://docs.ros.org/en/rolling/Concepts/About-Quality-of-Service-Settings.html
|
||||
* </a>
|
||||
*/
|
||||
class RCLCPP_PUBLIC QoS
|
||||
{
|
||||
public:
|
||||
/// Create a QoS by specifying only the history policy and history depth.
|
||||
/**
|
||||
* When using the default initial profile, the defaults will include:
|
||||
*
|
||||
* - \link rclcpp::ReliabilityPolicy::Reliable ReliabilityPolicy::Reliable\endlink
|
||||
* - \link rclcpp::DurabilityPolicy::Volatile DurabilityPolicy::Volatile\endlink
|
||||
*
|
||||
* See rmw_qos_profile_default for a full list of default settings.
|
||||
* If some other rmw_qos_profile_t is passed to initial_profile, then the defaults will derive from
|
||||
* that profile instead.
|
||||
*
|
||||
* \param[in] qos_initialization Specifies history policy and history depth.
|
||||
* \param[in] initial_profile The rmw_qos_profile_t instance on which to base the default settings.
|
||||
*/
|
||||
/// Constructor which allows you to construct a QoS by giving the only required settings.
|
||||
explicit
|
||||
QoS(
|
||||
const QoSInitialization & qos_initialization,
|
||||
@@ -131,11 +68,7 @@ public:
|
||||
|
||||
/// Conversion constructor to ease construction in the common case of just specifying depth.
|
||||
/**
|
||||
* This is a convenience constructor that calls QoS(KeepLast(history_depth)).
|
||||
*
|
||||
* \param[in] history_depth How many messages can be queued when publishing
|
||||
* with a Publisher, or how many messages can be queued before being replaced
|
||||
* by a Subscription.
|
||||
* Convenience constructor, equivalent to QoS(KeepLast(history_depth)).
|
||||
*/
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
QoS(size_t history_depth); // NOLINT(runtime/explicit): conversion constructor
|
||||
@@ -148,10 +81,6 @@ public:
|
||||
const rmw_qos_profile_t &
|
||||
get_rmw_qos_profile() const;
|
||||
|
||||
/// Set the history policy.
|
||||
QoS &
|
||||
history(HistoryPolicy history);
|
||||
|
||||
/// Set the history policy.
|
||||
QoS &
|
||||
history(rmw_qos_history_policy_t history);
|
||||
@@ -168,10 +97,6 @@ public:
|
||||
QoS &
|
||||
reliability(rmw_qos_reliability_policy_t reliability);
|
||||
|
||||
/// Set the reliability setting.
|
||||
QoS &
|
||||
reliability(ReliabilityPolicy reliability);
|
||||
|
||||
/// Set the reliability setting to reliable.
|
||||
QoS &
|
||||
reliable();
|
||||
@@ -184,10 +109,6 @@ public:
|
||||
QoS &
|
||||
durability(rmw_qos_durability_policy_t durability);
|
||||
|
||||
/// Set the durability setting.
|
||||
QoS &
|
||||
durability(DurabilityPolicy durability);
|
||||
|
||||
/// Set the durability setting to volatile.
|
||||
/**
|
||||
* Note that this cannot be named `volatile` because it is a C++ keyword.
|
||||
@@ -219,10 +140,6 @@ public:
|
||||
QoS &
|
||||
liveliness(rmw_qos_liveliness_policy_t liveliness);
|
||||
|
||||
/// Set the liveliness setting.
|
||||
QoS &
|
||||
liveliness(LivelinessPolicy liveliness);
|
||||
|
||||
/// Set the liveliness_lease_duration setting.
|
||||
QoS &
|
||||
liveliness_lease_duration(rmw_time_t liveliness_lease_duration);
|
||||
@@ -235,42 +152,6 @@ public:
|
||||
QoS &
|
||||
avoid_ros_namespace_conventions(bool avoid_ros_namespace_conventions);
|
||||
|
||||
/// Get the history qos policy.
|
||||
HistoryPolicy
|
||||
history() const;
|
||||
|
||||
/// Get the history depth.
|
||||
size_t
|
||||
depth() const;
|
||||
|
||||
/// Get the reliability policy.
|
||||
ReliabilityPolicy
|
||||
reliability() const;
|
||||
|
||||
/// Get the durability policy.
|
||||
DurabilityPolicy
|
||||
durability() const;
|
||||
|
||||
/// Get the deadline duration setting.
|
||||
rclcpp::Duration
|
||||
deadline() const;
|
||||
|
||||
/// Get the lifespan duration setting.
|
||||
rclcpp::Duration
|
||||
lifespan() const;
|
||||
|
||||
/// Get the liveliness policy.
|
||||
LivelinessPolicy
|
||||
liveliness() const;
|
||||
|
||||
/// Get the liveliness lease duration setting.
|
||||
rclcpp::Duration
|
||||
liveliness_lease_duration() const;
|
||||
|
||||
/// Get the `avoid ros namespace convention` setting.
|
||||
bool
|
||||
avoid_ros_namespace_conventions() const;
|
||||
|
||||
private:
|
||||
rmw_qos_profile_t rmw_qos_profile_;
|
||||
};
|
||||
@@ -281,81 +162,6 @@ bool operator==(const QoS & left, const QoS & right);
|
||||
RCLCPP_PUBLIC
|
||||
bool operator!=(const QoS & left, const QoS & right);
|
||||
|
||||
/// Result type for checking QoS compatibility
|
||||
/**
|
||||
* \see rclcpp::qos_check_compatible()
|
||||
*/
|
||||
struct QoSCheckCompatibleResult
|
||||
{
|
||||
/// Compatibility result.
|
||||
QoSCompatibility compatibility;
|
||||
|
||||
/// Reason for a (possible) incompatibility.
|
||||
/**
|
||||
* Set if compatiblity is QoSCompatibility::Warning or QoSCompatiblity::Error.
|
||||
* Not set if the QoS profiles are compatible.
|
||||
*/
|
||||
std::string reason;
|
||||
};
|
||||
|
||||
/// Check if two QoS profiles are compatible.
|
||||
/**
|
||||
* Two QoS profiles are compatible if a publisher and subcription
|
||||
* using the QoS policies can communicate with each other.
|
||||
*
|
||||
* If any policies have value "system default" or "unknown" then it is possible that
|
||||
* compatiblity cannot be determined.
|
||||
* In this case, the value QoSCompatility::Warning is set as part of
|
||||
* the returned structure.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* ```cpp
|
||||
* rclcpp::QoSCheckCompatibleResult result = rclcpp::qos_check_compatible(
|
||||
* publisher_qos, subscription_qos);
|
||||
* if (rclcpp::QoSCompatibility::Error != result.compatibility) {
|
||||
* // QoS not compatible ...
|
||||
* // result.reason contains info about the incompatibility
|
||||
* } else if (rclcpp::QoSCompatibility::Warning != result.compatibility) {
|
||||
* // QoS may not be compatible ...
|
||||
* // result.reason contains info about the possible incompatibility
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* \param[in] publisher_qos: The QoS profile for a publisher.
|
||||
* \param[in] subscription_qos: The QoS profile for a subscription.
|
||||
* \return Struct with compatiblity set to QoSCompatibility::Ok if the QoS profiles are
|
||||
* compatible, or
|
||||
* \return Struct with compatibility set to QoSCompatibility::Warning if there is a chance
|
||||
* the QoS profiles are not compatible, or
|
||||
* \return Struct with compatibility set to QoSCompatibility::Error if the QoS profiles are
|
||||
* not compatible.
|
||||
* \throws rclcpp::exceptions::QoSCheckCompatibilityException if an unexpected error occurs.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
QoSCheckCompatibleResult
|
||||
qos_check_compatible(const QoS & publisher_qos, const QoS & subscription_qos);
|
||||
|
||||
/**
|
||||
* Clock QoS class
|
||||
* - History: Keep last,
|
||||
* - Depth: 1,
|
||||
* - Reliability: Best effort,
|
||||
* - Durability: Volatile,
|
||||
* - Deadline: Default,
|
||||
* - Lifespan: Default,
|
||||
* - Liveliness: System default,
|
||||
* - Liveliness lease duration: default,
|
||||
* - avoid ros namespace conventions: false
|
||||
*/
|
||||
class RCLCPP_PUBLIC ClockQoS : public QoS
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
ClockQoS(
|
||||
const QoSInitialization & qos_initialization = KeepLast(1));
|
||||
};
|
||||
|
||||
/**
|
||||
* Sensor Data QoS class
|
||||
* - History: Keep last,
|
||||
@@ -444,28 +250,6 @@ public:
|
||||
));
|
||||
};
|
||||
|
||||
/**
|
||||
* Rosout QoS class
|
||||
* - History: Keep last,
|
||||
* - Depth: 1000,
|
||||
* - Reliability: Reliable,
|
||||
* - Durability: TRANSIENT_LOCAL,
|
||||
* - Deadline: Default,
|
||||
* - Lifespan: {10, 0},
|
||||
* - Liveliness: System default,
|
||||
* - Liveliness lease duration: default,
|
||||
* - Avoid ros namespace conventions: false
|
||||
*/
|
||||
class RCLCPP_PUBLIC RosoutQoS : public QoS
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
RosoutQoS(
|
||||
const QoSInitialization & rosout_qos_initialization = (
|
||||
QoSInitialization::from_rmw(rcl_qos_profile_rosout_default)
|
||||
));
|
||||
};
|
||||
|
||||
/**
|
||||
* System defaults QoS class
|
||||
* - History: System default,
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
#define RCLCPP__QOS_EVENT_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
@@ -36,7 +34,6 @@ using QOSDeadlineRequestedInfo = rmw_requested_deadline_missed_status_t;
|
||||
using QOSDeadlineOfferedInfo = rmw_offered_deadline_missed_status_t;
|
||||
using QOSLivelinessChangedInfo = rmw_liveliness_changed_status_t;
|
||||
using QOSLivelinessLostInfo = rmw_liveliness_lost_status_t;
|
||||
using QOSMessageLostInfo = rmw_message_lost_status_t;
|
||||
using QOSOfferedIncompatibleQoSInfo = rmw_offered_qos_incompatible_event_status_t;
|
||||
using QOSRequestedIncompatibleQoSInfo = rmw_requested_qos_incompatible_event_status_t;
|
||||
|
||||
@@ -44,7 +41,6 @@ using QOSDeadlineRequestedCallbackType = std::function<void (QOSDeadlineRequeste
|
||||
using QOSDeadlineOfferedCallbackType = std::function<void (QOSDeadlineOfferedInfo &)>;
|
||||
using QOSLivelinessChangedCallbackType = std::function<void (QOSLivelinessChangedInfo &)>;
|
||||
using QOSLivelinessLostCallbackType = std::function<void (QOSLivelinessLostInfo &)>;
|
||||
using QOSMessageLostCallbackType = std::function<void (QOSMessageLostInfo &)>;
|
||||
using QOSOfferedIncompatibleQoSCallbackType = std::function<void (QOSOfferedIncompatibleQoSInfo &)>;
|
||||
using QOSRequestedIncompatibleQoSCallbackType =
|
||||
std::function<void (QOSRequestedIncompatibleQoSInfo &)>;
|
||||
@@ -63,7 +59,6 @@ struct SubscriptionEventCallbacks
|
||||
QOSDeadlineRequestedCallbackType deadline_callback;
|
||||
QOSLivelinessChangedCallbackType liveliness_callback;
|
||||
QOSRequestedIncompatibleQoSCallbackType incompatible_qos_callback;
|
||||
QOSMessageLostCallbackType message_lost_callback;
|
||||
};
|
||||
|
||||
class UnsupportedEventTypeException : public exceptions::RCLErrorBase, public std::runtime_error
|
||||
@@ -133,31 +128,21 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// Take data so that the callback cannot be scheduled again
|
||||
std::shared_ptr<void>
|
||||
take_data() override
|
||||
/// Execute any entities of the Waitable that are ready.
|
||||
void
|
||||
execute() override
|
||||
{
|
||||
EventCallbackInfoT callback_info;
|
||||
|
||||
rcl_ret_t ret = rcl_take_event(&event_handle_, &callback_info);
|
||||
if (ret != RCL_RET_OK) {
|
||||
RCUTILS_LOG_ERROR_NAMED(
|
||||
"rclcpp",
|
||||
"Couldn't take event info: %s", rcl_get_error_string().str);
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
return std::static_pointer_cast<void>(std::make_shared<EventCallbackInfoT>(callback_info));
|
||||
}
|
||||
|
||||
/// Execute any entities of the Waitable that are ready.
|
||||
void
|
||||
execute(std::shared_ptr<void> & data) override
|
||||
{
|
||||
if (!data) {
|
||||
throw std::runtime_error("'data' is empty");
|
||||
}
|
||||
auto callback_ptr = std::static_pointer_cast<EventCallbackInfoT>(data);
|
||||
event_callback_(*callback_ptr);
|
||||
callback_ptr.reset();
|
||||
event_callback_(callback_info);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
// Copyright 2020 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__QOS_OVERRIDING_OPTIONS_HPP_
|
||||
#define RCLCPP__QOS_OVERRIDING_OPTIONS_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rcl_interfaces/msg/set_parameters_result.hpp"
|
||||
#include "rmw/qos_policy_kind.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
enum class RCLCPP_PUBLIC_TYPE QosPolicyKind
|
||||
{
|
||||
AvoidRosNamespaceConventions = RMW_QOS_POLICY_AVOID_ROS_NAMESPACE_CONVENTIONS,
|
||||
Deadline = RMW_QOS_POLICY_DEADLINE,
|
||||
Depth = RMW_QOS_POLICY_DEPTH,
|
||||
Durability = RMW_QOS_POLICY_DURABILITY,
|
||||
History = RMW_QOS_POLICY_HISTORY,
|
||||
Lifespan = RMW_QOS_POLICY_LIFESPAN,
|
||||
Liveliness = RMW_QOS_POLICY_LIVELINESS,
|
||||
LivelinessLeaseDuration = RMW_QOS_POLICY_LIVELINESS_LEASE_DURATION,
|
||||
Reliability = RMW_QOS_POLICY_RELIABILITY,
|
||||
Invalid = RMW_QOS_POLICY_INVALID,
|
||||
};
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const char *
|
||||
qos_policy_kind_to_cstr(const QosPolicyKind & qpk);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::ostream &
|
||||
operator<<(std::ostream & os, const QosPolicyKind & qpk);
|
||||
|
||||
using QosCallbackResult = rcl_interfaces::msg::SetParametersResult;
|
||||
using QosCallback = std::function<QosCallbackResult(const rclcpp::QoS &)>;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// forward declare
|
||||
template<typename T>
|
||||
class QosParameters;
|
||||
}
|
||||
|
||||
/// Options that are passed in subscription/publisher constructor to specify QoSConfigurability.
|
||||
/**
|
||||
* This options struct allows configuring:
|
||||
* - Which policy kinds will have declared parameters.
|
||||
* - An optional callback, that will be called to validate the final qos profile.
|
||||
* - An optional id. In the case that different qos are desired for two publishers/subscriptions in
|
||||
* the same topic, this id will allow disambiguating them.
|
||||
*
|
||||
* Example parameter file:
|
||||
*
|
||||
* ```yaml
|
||||
* my_node_name:
|
||||
* ros__parameters:
|
||||
* qos_overrides:
|
||||
* /my/topic/name:
|
||||
* publisher: # publisher without provided id
|
||||
* reliability: reliable
|
||||
* depth: 100
|
||||
* publisher_my_id: # publisher with `id="my_id"
|
||||
* reliability: reliable
|
||||
* depth: 10
|
||||
* ```
|
||||
*/
|
||||
class QosOverridingOptions
|
||||
{
|
||||
public:
|
||||
/// Default constructor, no overrides allowed.
|
||||
RCLCPP_PUBLIC
|
||||
QosOverridingOptions() = default;
|
||||
|
||||
/// Construct passing a list of QoS policies and a verification callback.
|
||||
/**
|
||||
* This constructor is implicit, e.g.:
|
||||
* ```cpp
|
||||
* node->create_publisher(
|
||||
* "topic_name",
|
||||
* default_qos_profile,
|
||||
* {
|
||||
* {QosPolicyKind::Reliability},
|
||||
* [] (auto && qos) {return check_qos_validity(qos)},
|
||||
* "my_id"
|
||||
* });
|
||||
* ```
|
||||
* \param policy_kinds list of policy kinds that will be reconfigurable.
|
||||
* \param validation_callback callbak that will be called to validate the validity of
|
||||
* the qos profile set by the user.
|
||||
* \param id id of the entity.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
QosOverridingOptions(
|
||||
std::initializer_list<QosPolicyKind> policy_kinds,
|
||||
QosCallback validation_callback = nullptr,
|
||||
std::string id = {});
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::string &
|
||||
get_id() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<QosPolicyKind> &
|
||||
get_policy_kinds() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const QosCallback &
|
||||
get_validation_callback() const;
|
||||
|
||||
/// Construct passing a list of QoS policies and a verification callback.
|
||||
/**
|
||||
* Same as `QosOverridingOptions` constructor, but only declares the default policies:
|
||||
*
|
||||
* History, Depth, Reliability.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
static
|
||||
QosOverridingOptions
|
||||
with_default_policies(QosCallback validation_callback = nullptr, std::string id = {});
|
||||
|
||||
private:
|
||||
/// \internal Id of the entity requesting to create parameters.
|
||||
std::string id_;
|
||||
/// \internal Policy kinds that are allowed to be reconfigured.
|
||||
std::vector<QosPolicyKind> policy_kinds_;
|
||||
/// \internal Validation callback that will be called to verify the profile.
|
||||
QosCallback validation_callback_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__QOS_OVERRIDING_OPTIONS_HPP_
|
||||
@@ -117,15 +117,6 @@
|
||||
* - Allocator related items:
|
||||
* - rclcpp/allocator/allocator_common.hpp
|
||||
* - rclcpp/allocator/allocator_deleter.hpp
|
||||
* - Generic publisher
|
||||
* - rclcpp::Node::create_generic_publisher()
|
||||
* - rclcpp::GenericPublisher
|
||||
* - rclcpp::GenericPublisher::publish()
|
||||
* - rclcpp/generic_publisher.hpp
|
||||
* - Generic subscription
|
||||
* - rclcpp::Node::create_generic_subscription()
|
||||
* - rclcpp::GenericSubscription
|
||||
* - rclcpp/generic_subscription.hpp
|
||||
* - Memory management tools:
|
||||
* - rclcpp/memory_strategies.hpp
|
||||
* - rclcpp/memory_strategy.hpp
|
||||
@@ -143,7 +134,6 @@
|
||||
* - rclcpp/scope_exit.hpp
|
||||
* - rclcpp/time.hpp
|
||||
* - rclcpp/utilities.hpp
|
||||
* - rclcpp/typesupport_helpers.hpp
|
||||
* - rclcpp/visibility_control.hpp
|
||||
*/
|
||||
|
||||
@@ -157,15 +147,14 @@
|
||||
#include "rclcpp/guard_condition.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/parameter_client.hpp"
|
||||
#include "rclcpp/parameter_event_handler.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/parameter_client.hpp"
|
||||
#include "rclcpp/parameter_service.hpp"
|
||||
#include "rclcpp/rate.hpp"
|
||||
#include "rclcpp/time.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rclcpp/waitable.hpp"
|
||||
#include "rclcpp/wait_set.hpp"
|
||||
#include "rclcpp/waitable.hpp"
|
||||
|
||||
#endif // RCLCPP__RCLCPP_HPP_
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
* \param[in] initial_capacity The amount of memory to be allocated.
|
||||
* \param[in] allocator The allocator to be used for the initialization.
|
||||
*/
|
||||
explicit SerializedMessage(
|
||||
SerializedMessage(
|
||||
size_t initial_capacity,
|
||||
const rcl_allocator_t & allocator = rcl_get_default_allocator());
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ public:
|
||||
|
||||
// rcl does the static memory allocation here
|
||||
service_handle_ = std::shared_ptr<rcl_service_t>(
|
||||
new rcl_service_t, [handle = node_handle_, service_name](rcl_service_t * service)
|
||||
new rcl_service_t, [handle = node_handle_](rcl_service_t * service)
|
||||
{
|
||||
if (rcl_service_fini(service, handle.get()) != RCL_RET_OK) {
|
||||
RCLCPP_ERROR(
|
||||
@@ -214,8 +214,8 @@ public:
|
||||
}
|
||||
TRACEPOINT(
|
||||
rclcpp_service_callback_added,
|
||||
static_cast<const void *>(get_service_handle().get()),
|
||||
static_cast<const void *>(&any_callback_));
|
||||
(const void *)get_service_handle().get(),
|
||||
(const void *)&any_callback_);
|
||||
#ifndef TRACETOOLS_DISABLED
|
||||
any_callback_.register_callback_for_tracing();
|
||||
#endif
|
||||
@@ -249,8 +249,8 @@ public:
|
||||
service_handle_ = service_handle;
|
||||
TRACEPOINT(
|
||||
rclcpp_service_callback_added,
|
||||
static_cast<const void *>(get_service_handle().get()),
|
||||
static_cast<const void *>(&any_callback_));
|
||||
(const void *)get_service_handle().get(),
|
||||
(const void *)&any_callback_);
|
||||
#ifndef TRACETOOLS_DISABLED
|
||||
any_callback_.register_callback_for_tracing();
|
||||
#endif
|
||||
@@ -286,8 +286,8 @@ public:
|
||||
service_handle_->impl = service_handle->impl;
|
||||
TRACEPOINT(
|
||||
rclcpp_service_callback_added,
|
||||
static_cast<const void *>(get_service_handle().get()),
|
||||
static_cast<const void *>(&any_callback_));
|
||||
(const void *)get_service_handle().get(),
|
||||
(const void *)&any_callback_);
|
||||
#ifndef TRACETOOLS_DISABLED
|
||||
any_callback_.register_callback_for_tracing();
|
||||
#endif
|
||||
@@ -340,6 +340,15 @@ public:
|
||||
send_response(*request_header, *response);
|
||||
}
|
||||
|
||||
[[deprecated("use the send_response() which takes references instead of shared pointers")]]
|
||||
void
|
||||
send_response(
|
||||
std::shared_ptr<rmw_request_id_t> req_id,
|
||||
std::shared_ptr<typename ServiceT::Response> response)
|
||||
{
|
||||
send_response(*req_id, *response);
|
||||
}
|
||||
|
||||
void
|
||||
send_response(rmw_request_id_t & req_id, typename ServiceT::Response & response)
|
||||
{
|
||||
|
||||
@@ -150,47 +150,48 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
bool collect_entities(const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) override
|
||||
bool collect_entities(const WeakNodeList & weak_nodes) override
|
||||
{
|
||||
bool has_invalid_weak_groups_or_nodes = false;
|
||||
for (const auto & pair : weak_groups_to_nodes) {
|
||||
auto group = pair.first.lock();
|
||||
auto node = pair.second.lock();
|
||||
if (group == nullptr || node == nullptr) {
|
||||
has_invalid_weak_groups_or_nodes = true;
|
||||
bool has_invalid_weak_nodes = false;
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
auto node = weak_node.lock();
|
||||
if (!node) {
|
||||
has_invalid_weak_nodes = true;
|
||||
continue;
|
||||
}
|
||||
if (!group || !group->can_be_taken_from().load()) {
|
||||
continue;
|
||||
for (auto & weak_group : node->get_callback_groups()) {
|
||||
auto group = weak_group.lock();
|
||||
if (!group || !group->can_be_taken_from().load()) {
|
||||
continue;
|
||||
}
|
||||
group->find_subscription_ptrs_if(
|
||||
[this](const rclcpp::SubscriptionBase::SharedPtr & subscription) {
|
||||
subscription_handles_.push_back(subscription->get_subscription_handle());
|
||||
return false;
|
||||
});
|
||||
group->find_service_ptrs_if(
|
||||
[this](const rclcpp::ServiceBase::SharedPtr & service) {
|
||||
service_handles_.push_back(service->get_service_handle());
|
||||
return false;
|
||||
});
|
||||
group->find_client_ptrs_if(
|
||||
[this](const rclcpp::ClientBase::SharedPtr & client) {
|
||||
client_handles_.push_back(client->get_client_handle());
|
||||
return false;
|
||||
});
|
||||
group->find_timer_ptrs_if(
|
||||
[this](const rclcpp::TimerBase::SharedPtr & timer) {
|
||||
timer_handles_.push_back(timer->get_timer_handle());
|
||||
return false;
|
||||
});
|
||||
group->find_waitable_ptrs_if(
|
||||
[this](const rclcpp::Waitable::SharedPtr & waitable) {
|
||||
waitable_handles_.push_back(waitable);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
group->find_subscription_ptrs_if(
|
||||
[this](const rclcpp::SubscriptionBase::SharedPtr & subscription) {
|
||||
subscription_handles_.push_back(subscription->get_subscription_handle());
|
||||
return false;
|
||||
});
|
||||
group->find_service_ptrs_if(
|
||||
[this](const rclcpp::ServiceBase::SharedPtr & service) {
|
||||
service_handles_.push_back(service->get_service_handle());
|
||||
return false;
|
||||
});
|
||||
group->find_client_ptrs_if(
|
||||
[this](const rclcpp::ClientBase::SharedPtr & client) {
|
||||
client_handles_.push_back(client->get_client_handle());
|
||||
return false;
|
||||
});
|
||||
group->find_timer_ptrs_if(
|
||||
[this](const rclcpp::TimerBase::SharedPtr & timer) {
|
||||
timer_handles_.push_back(timer->get_timer_handle());
|
||||
return false;
|
||||
});
|
||||
group->find_waitable_ptrs_if(
|
||||
[this](const rclcpp::Waitable::SharedPtr & waitable) {
|
||||
waitable_handles_.push_back(waitable);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
return has_invalid_weak_groups_or_nodes;
|
||||
return has_invalid_weak_nodes;
|
||||
}
|
||||
|
||||
void add_waitable_handle(const rclcpp::Waitable::SharedPtr & waitable) override
|
||||
@@ -263,14 +264,14 @@ public:
|
||||
void
|
||||
get_next_subscription(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) override
|
||||
const WeakNodeList & weak_nodes) override
|
||||
{
|
||||
auto it = subscription_handles_.begin();
|
||||
while (it != subscription_handles_.end()) {
|
||||
auto subscription = get_subscription_by_handle(*it, weak_groups_to_nodes);
|
||||
auto subscription = get_subscription_by_handle(*it, weak_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);
|
||||
auto group = get_group_by_subscription(subscription, weak_nodes);
|
||||
if (!group) {
|
||||
// Group was not found, meaning the subscription is not valid...
|
||||
// Remove it from the ready list and continue looking
|
||||
@@ -286,7 +287,7 @@ public:
|
||||
// Otherwise it is safe to set and return the any_exec
|
||||
any_exec.subscription = subscription;
|
||||
any_exec.callback_group = group;
|
||||
any_exec.node_base = get_node_by_group(group, weak_groups_to_nodes);
|
||||
any_exec.node_base = get_node_by_group(group, weak_nodes);
|
||||
subscription_handles_.erase(it);
|
||||
return;
|
||||
}
|
||||
@@ -298,14 +299,14 @@ public:
|
||||
void
|
||||
get_next_service(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) override
|
||||
const WeakNodeList & weak_nodes) override
|
||||
{
|
||||
auto it = service_handles_.begin();
|
||||
while (it != service_handles_.end()) {
|
||||
auto service = get_service_by_handle(*it, weak_groups_to_nodes);
|
||||
auto service = get_service_by_handle(*it, weak_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);
|
||||
auto group = get_group_by_service(service, weak_nodes);
|
||||
if (!group) {
|
||||
// Group was not found, meaning the service is not valid...
|
||||
// Remove it from the ready list and continue looking
|
||||
@@ -321,7 +322,7 @@ public:
|
||||
// Otherwise it is safe to set and return the any_exec
|
||||
any_exec.service = service;
|
||||
any_exec.callback_group = group;
|
||||
any_exec.node_base = get_node_by_group(group, weak_groups_to_nodes);
|
||||
any_exec.node_base = get_node_by_group(group, weak_nodes);
|
||||
service_handles_.erase(it);
|
||||
return;
|
||||
}
|
||||
@@ -331,16 +332,14 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
get_next_client(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) override
|
||||
get_next_client(rclcpp::AnyExecutable & any_exec, const WeakNodeList & weak_nodes) override
|
||||
{
|
||||
auto it = client_handles_.begin();
|
||||
while (it != client_handles_.end()) {
|
||||
auto client = get_client_by_handle(*it, weak_groups_to_nodes);
|
||||
auto client = get_client_by_handle(*it, weak_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);
|
||||
auto group = get_group_by_client(client, weak_nodes);
|
||||
if (!group) {
|
||||
// Group was not found, meaning the service is not valid...
|
||||
// Remove it from the ready list and continue looking
|
||||
@@ -356,7 +355,7 @@ public:
|
||||
// Otherwise it is safe to set and return the any_exec
|
||||
any_exec.client = client;
|
||||
any_exec.callback_group = group;
|
||||
any_exec.node_base = get_node_by_group(group, weak_groups_to_nodes);
|
||||
any_exec.node_base = get_node_by_group(group, weak_nodes);
|
||||
client_handles_.erase(it);
|
||||
return;
|
||||
}
|
||||
@@ -368,14 +367,14 @@ public:
|
||||
void
|
||||
get_next_timer(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) override
|
||||
const WeakNodeList & weak_nodes) override
|
||||
{
|
||||
auto it = timer_handles_.begin();
|
||||
while (it != timer_handles_.end()) {
|
||||
auto timer = get_timer_by_handle(*it, weak_groups_to_nodes);
|
||||
auto timer = get_timer_by_handle(*it, weak_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);
|
||||
auto group = get_group_by_timer(timer, weak_nodes);
|
||||
if (!group) {
|
||||
// Group was not found, meaning the timer is not valid...
|
||||
// Remove it from the ready list and continue looking
|
||||
@@ -391,7 +390,7 @@ public:
|
||||
// Otherwise it is safe to set and return the any_exec
|
||||
any_exec.timer = timer;
|
||||
any_exec.callback_group = group;
|
||||
any_exec.node_base = get_node_by_group(group, weak_groups_to_nodes);
|
||||
any_exec.node_base = get_node_by_group(group, weak_nodes);
|
||||
timer_handles_.erase(it);
|
||||
return;
|
||||
}
|
||||
@@ -401,16 +400,14 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
get_next_waitable(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) override
|
||||
get_next_waitable(rclcpp::AnyExecutable & any_exec, const WeakNodeList & weak_nodes) override
|
||||
{
|
||||
auto it = waitable_handles_.begin();
|
||||
while (it != waitable_handles_.end()) {
|
||||
auto waitable = *it;
|
||||
if (waitable) {
|
||||
// Find the group for this handle and see if it can be serviced
|
||||
auto group = get_group_by_waitable(waitable, weak_groups_to_nodes);
|
||||
auto group = get_group_by_waitable(waitable, weak_nodes);
|
||||
if (!group) {
|
||||
// Group was not found, meaning the waitable is not valid...
|
||||
// Remove it from the ready list and continue looking
|
||||
@@ -426,7 +423,7 @@ public:
|
||||
// Otherwise it is safe to set and return the any_exec
|
||||
any_exec.waitable = waitable;
|
||||
any_exec.callback_group = group;
|
||||
any_exec.node_base = get_node_by_group(group, weak_groups_to_nodes);
|
||||
any_exec.node_base = get_node_by_group(group, weak_nodes);
|
||||
waitable_handles_.erase(it);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -60,16 +60,10 @@ class NodeTopicsInterface;
|
||||
|
||||
/// Subscription implementation, templated on the type of message this subscription receives.
|
||||
template<
|
||||
typename MessageT,
|
||||
typename CallbackMessageT,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
/// MessageT::custom_type if MessageT is a TypeAdapter,
|
||||
/// otherwise just MessageT.
|
||||
typename SubscribedT = typename rclcpp::TypeAdapter<MessageT>::custom_type,
|
||||
/// MessageT::ros_message_type if MessageT is a TypeAdapter,
|
||||
/// otherwise just MessageT.
|
||||
typename ROSMessageT = typename rclcpp::TypeAdapter<MessageT>::ros_message_type,
|
||||
typename MessageMemoryStrategyT = rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
ROSMessageT,
|
||||
CallbackMessageT,
|
||||
AllocatorT
|
||||
>>
|
||||
class Subscription : public SubscriptionBase
|
||||
@@ -77,36 +71,14 @@ class Subscription : public SubscriptionBase
|
||||
friend class rclcpp::node_interfaces::NodeTopicsInterface;
|
||||
|
||||
public:
|
||||
// Redeclare these here to use outside of the class.
|
||||
using SubscribedType = SubscribedT;
|
||||
using ROSMessageType = ROSMessageT;
|
||||
using MessageMemoryStrategyType = MessageMemoryStrategyT;
|
||||
|
||||
using SubscribedTypeAllocatorTraits = allocator::AllocRebind<SubscribedType, AllocatorT>;
|
||||
using SubscribedTypeAllocator = typename SubscribedTypeAllocatorTraits::allocator_type;
|
||||
using SubscribedTypeDeleter = allocator::Deleter<SubscribedTypeAllocator, SubscribedType>;
|
||||
|
||||
using ROSMessageTypeAllocatorTraits = allocator::AllocRebind<ROSMessageType, AllocatorT>;
|
||||
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 MessageAllocatorTraits = allocator::AllocRebind<CallbackMessageT, AllocatorT>;
|
||||
using MessageAllocator = typename MessageAllocatorTraits::allocator_type;
|
||||
using MessageDeleter = allocator::Deleter<MessageAllocator, CallbackMessageT>;
|
||||
using ConstMessageSharedPtr = std::shared_ptr<const CallbackMessageT>;
|
||||
using MessageUniquePtr = std::unique_ptr<CallbackMessageT, MessageDeleter>;
|
||||
using SubscriptionTopicStatisticsSharedPtr =
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>>;
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>>;
|
||||
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(Subscription)
|
||||
|
||||
/// Default constructor.
|
||||
@@ -120,7 +92,7 @@ public:
|
||||
* \param[in] topic_name Name of the topic to subscribe to.
|
||||
* \param[in] qos QoS profile for Subcription.
|
||||
* \param[in] callback User defined callback to call when a message is received.
|
||||
* \param[in] options Options for the subscription.
|
||||
* \param[in] options options for the subscription.
|
||||
* \param[in] message_memory_strategy The memory strategy to be used for managing message memory.
|
||||
* \param[in] subscription_topic_statistics Optional pointer to a topic statistics subcription.
|
||||
* \throws std::invalid_argument if the QoS is uncompatible with intra-process (if one
|
||||
@@ -132,7 +104,7 @@ public:
|
||||
const rosidl_message_type_support_t & type_support_handle,
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos,
|
||||
AnySubscriptionCallback<MessageT, AllocatorT> callback,
|
||||
AnySubscriptionCallback<CallbackMessageT, AllocatorT> callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
|
||||
typename MessageMemoryStrategyT::SharedPtr message_memory_strategy,
|
||||
SubscriptionTopicStatisticsSharedPtr subscription_topic_statistics = nullptr)
|
||||
@@ -140,8 +112,8 @@ public:
|
||||
node_base,
|
||||
type_support_handle,
|
||||
topic_name,
|
||||
options.template to_rcl_subscription_options<ROSMessageType>(qos),
|
||||
callback.is_serialized_message_callback()),
|
||||
options.template to_rcl_subscription_options<CallbackMessageT>(qos),
|
||||
rclcpp::subscription_traits::is_serialized_subscription_argument<CallbackMessageT>::value),
|
||||
any_callback_(callback),
|
||||
options_(options),
|
||||
message_memory_strategy_(message_memory_strategy)
|
||||
@@ -172,34 +144,33 @@ public:
|
||||
// pass
|
||||
}
|
||||
}
|
||||
if (options.event_callbacks.message_lost_callback) {
|
||||
this->add_event_handler(
|
||||
options.event_callbacks.message_lost_callback,
|
||||
RCL_SUBSCRIPTION_MESSAGE_LOST);
|
||||
}
|
||||
|
||||
// Setup intra process publishing if requested.
|
||||
if (rclcpp::detail::resolve_use_intra_process(options, *node_base)) {
|
||||
using rclcpp::detail::resolve_intra_process_buffer_type;
|
||||
|
||||
// Check if the QoS is compatible with intra-process.
|
||||
auto qos_profile = get_actual_qos();
|
||||
if (qos_profile.history() != rclcpp::HistoryPolicy::KeepLast) {
|
||||
rmw_qos_profile_t qos_profile = get_actual_qos().get_rmw_qos_profile();
|
||||
if (qos_profile.history == RMW_QOS_POLICY_HISTORY_KEEP_ALL) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication allowed only with keep last history qos policy");
|
||||
"intraprocess communication is not allowed with keep all history qos policy");
|
||||
}
|
||||
if (qos_profile.depth() == 0) {
|
||||
if (qos_profile.depth == 0) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication is not allowed with 0 depth qos policy");
|
||||
}
|
||||
if (qos_profile.durability() != rclcpp::DurabilityPolicy::Volatile) {
|
||||
if (qos_profile.durability != RMW_QOS_POLICY_DURABILITY_VOLATILE) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication allowed only with volatile durability");
|
||||
}
|
||||
|
||||
// First create a SubscriptionIntraProcess which will be given to the intra-process manager.
|
||||
auto context = node_base->get_context();
|
||||
subscription_intra_process_ = std::make_shared<SubscriptionIntraProcessT>(
|
||||
using SubscriptionIntraProcessT = rclcpp::experimental::SubscriptionIntraProcess<
|
||||
CallbackMessageT,
|
||||
AllocatorT,
|
||||
typename MessageUniquePtr::deleter_type>;
|
||||
auto subscription_intra_process = std::make_shared<SubscriptionIntraProcessT>(
|
||||
callback,
|
||||
options.get_allocator(),
|
||||
context,
|
||||
@@ -208,13 +179,13 @@ public:
|
||||
resolve_intra_process_buffer_type(options.intra_process_buffer_type, callback));
|
||||
TRACEPOINT(
|
||||
rclcpp_subscription_init,
|
||||
static_cast<const void *>(get_subscription_handle().get()),
|
||||
static_cast<const void *>(subscription_intra_process_.get()));
|
||||
(const void *)get_subscription_handle().get(),
|
||||
(const void *)subscription_intra_process.get());
|
||||
|
||||
// Add it to the intra process manager.
|
||||
using rclcpp::experimental::IntraProcessManager;
|
||||
auto ipm = context->get_sub_context<IntraProcessManager>();
|
||||
uint64_t intra_process_subscription_id = ipm->add_subscription(subscription_intra_process_);
|
||||
uint64_t intra_process_subscription_id = ipm->add_subscription(subscription_intra_process);
|
||||
this->setup_intra_process(intra_process_subscription_id, ipm);
|
||||
}
|
||||
|
||||
@@ -224,12 +195,12 @@ public:
|
||||
|
||||
TRACEPOINT(
|
||||
rclcpp_subscription_init,
|
||||
static_cast<const void *>(get_subscription_handle().get()),
|
||||
static_cast<const void *>(this));
|
||||
(const void *)get_subscription_handle().get(),
|
||||
(const void *)this);
|
||||
TRACEPOINT(
|
||||
rclcpp_subscription_callback_added,
|
||||
static_cast<const void *>(this),
|
||||
static_cast<const void *>(&any_callback_));
|
||||
(const void *)this,
|
||||
(const void *)&any_callback_);
|
||||
// The callback object gets copied, so if registration is done too early/before this point
|
||||
// (e.g. in `AnySubscriptionCallback::set()`), its address won't match any address used later
|
||||
// in subsequent tracepoints.
|
||||
@@ -269,34 +240,11 @@ public:
|
||||
* \throws any rcl errors from rcl_take, \sa rclcpp::exceptions::throw_from_rcl_error()
|
||||
*/
|
||||
bool
|
||||
take(ROSMessageType & message_out, rclcpp::MessageInfo & message_info_out)
|
||||
take(CallbackMessageT & message_out, rclcpp::MessageInfo & message_info_out)
|
||||
{
|
||||
return this->take_type_erased(static_cast<void *>(&message_out), message_info_out);
|
||||
}
|
||||
|
||||
/// Take the next message from the inter-process subscription.
|
||||
/**
|
||||
* This verison takes a SubscribedType which is different frmo the
|
||||
* ROSMessageType when a rclcpp::TypeAdapter is in used.
|
||||
*
|
||||
* \sa take(ROSMessageType &, rclcpp::MessageInfo &)
|
||||
*/
|
||||
template<typename TakeT>
|
||||
std::enable_if_t<
|
||||
!rosidl_generator_traits::is_message<TakeT>::value &&
|
||||
std::is_same_v<TakeT, SubscribedType>,
|
||||
bool
|
||||
>
|
||||
take(TakeT & message_out, rclcpp::MessageInfo & message_info_out)
|
||||
{
|
||||
ROSMessageType local_message;
|
||||
bool taken = this->take_type_erased(static_cast<void *>(&local_message), message_info_out);
|
||||
if (taken) {
|
||||
rclcpp::TypeAdapter<MessageT>::convert_to_custom(local_message, message_out);
|
||||
}
|
||||
return taken;
|
||||
}
|
||||
|
||||
std::shared_ptr<void>
|
||||
create_message() override
|
||||
{
|
||||
@@ -323,7 +271,32 @@ public:
|
||||
// we should ignore this copy of the message.
|
||||
return;
|
||||
}
|
||||
auto typed_message = std::static_pointer_cast<ROSMessageType>(message);
|
||||
auto typed_message = std::static_pointer_cast<CallbackMessageT>(message);
|
||||
any_callback_.dispatch(typed_message, message_info);
|
||||
|
||||
if (subscription_topic_statistics_) {
|
||||
const auto nanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::system_clock::now());
|
||||
const auto time = rclcpp::Time(nanos.time_since_epoch().count());
|
||||
subscription_topic_statistics_->handle_message(*typed_message, time);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_loaned_message(
|
||||
void * loaned_message,
|
||||
const rclcpp::MessageInfo & message_info) override
|
||||
{
|
||||
if (matches_any_intra_process_publishers(&message_info.get_rmw_message_info().publisher_gid)) {
|
||||
// In this case, the message will be delivered via intra process and
|
||||
// we should ignore this copy of the message.
|
||||
return;
|
||||
}
|
||||
|
||||
auto typed_message = static_cast<CallbackMessageT *>(loaned_message);
|
||||
// message is loaned, so we have to make sure that the deleter does not deallocate the message
|
||||
auto sptr = std::shared_ptr<CallbackMessageT>(
|
||||
typed_message, [](CallbackMessageT * msg) {(void) msg;});
|
||||
|
||||
std::chrono::time_point<std::chrono::system_clock> now;
|
||||
if (subscription_topic_statistics_) {
|
||||
@@ -332,7 +305,7 @@ public:
|
||||
now = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
any_callback_.dispatch(typed_message, message_info);
|
||||
any_callback_.dispatch(sptr, message_info);
|
||||
|
||||
if (subscription_topic_statistics_) {
|
||||
const auto nanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(now);
|
||||
@@ -341,27 +314,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_serialized_message(
|
||||
const std::shared_ptr<rclcpp::SerializedMessage> & serialized_message,
|
||||
const rclcpp::MessageInfo & message_info) override
|
||||
{
|
||||
// TODO(wjwwood): enable topic statistics for serialized messages
|
||||
any_callback_.dispatch(serialized_message, message_info);
|
||||
}
|
||||
|
||||
void
|
||||
handle_loaned_message(
|
||||
void * loaned_message,
|
||||
const rclcpp::MessageInfo & message_info) override
|
||||
{
|
||||
auto typed_message = static_cast<ROSMessageType *>(loaned_message);
|
||||
// message is loaned, so we have to make sure that the deleter does not deallocate the message
|
||||
auto sptr = std::shared_ptr<ROSMessageType>(
|
||||
typed_message, [](ROSMessageType * msg) {(void) msg;});
|
||||
any_callback_.dispatch(sptr, message_info);
|
||||
}
|
||||
|
||||
/// Return the borrowed message.
|
||||
/**
|
||||
* \param[inout] message message to be returned
|
||||
@@ -369,7 +321,7 @@ public:
|
||||
void
|
||||
return_message(std::shared_ptr<void> & message) override
|
||||
{
|
||||
auto typed_message = std::static_pointer_cast<ROSMessageType>(message);
|
||||
auto typed_message = std::static_pointer_cast<CallbackMessageT>(message);
|
||||
message_memory_strategy_->return_message(typed_message);
|
||||
}
|
||||
|
||||
@@ -392,25 +344,17 @@ public:
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(Subscription)
|
||||
|
||||
AnySubscriptionCallback<MessageT, AllocatorT> any_callback_;
|
||||
AnySubscriptionCallback<CallbackMessageT, AllocatorT> any_callback_;
|
||||
/// Copy of original options passed during construction.
|
||||
/**
|
||||
* It is important to save a copy of this so that the rmw payload which it
|
||||
* may contain is kept alive for the duration of the subscription.
|
||||
*/
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> options_;
|
||||
typename message_memory_strategy::MessageMemoryStrategy<ROSMessageType, AllocatorT>::SharedPtr
|
||||
typename message_memory_strategy::MessageMemoryStrategy<CallbackMessageT, AllocatorT>::SharedPtr
|
||||
message_memory_strategy_;
|
||||
|
||||
/// Component which computes and publishes topic statistics for this subscriber
|
||||
SubscriptionTopicStatisticsSharedPtr subscription_topic_statistics_{nullptr};
|
||||
|
||||
using SubscriptionIntraProcessT = rclcpp::experimental::SubscriptionIntraProcess<
|
||||
ROSMessageType,
|
||||
AllocatorT,
|
||||
ROSMessageTypeDeleter,
|
||||
MessageT>;
|
||||
std::shared_ptr<SubscriptionIntraProcessT> subscription_intra_process_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "rclcpp/experimental/subscription_intra_process_base.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/message_info.hpp"
|
||||
#include "rclcpp/network_flow_endpoint.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/qos_event.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
@@ -62,15 +61,12 @@ class SubscriptionBase : public std::enable_shared_from_this<SubscriptionBase>
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(SubscriptionBase)
|
||||
|
||||
/// Constructor.
|
||||
/// Default constructor.
|
||||
/**
|
||||
* This accepts rcl_subscription_options_t instead of rclcpp::SubscriptionOptions because
|
||||
* rclcpp::SubscriptionOptions::to_rcl_subscription_options depends on the message type.
|
||||
*
|
||||
* \param[in] node_base NodeBaseInterface pointer used in parts of the setup.
|
||||
* \param[in] type_support_handle rosidl type support struct, for the Message type of the topic.
|
||||
* \param[in] topic_name Name of the topic to subscribe to.
|
||||
* \param[in] subscription_options Options for the subscription.
|
||||
* \param[in] subscription_options options for the subscription.
|
||||
* \param[in] is_serialized is true if the message will be delivered still serialized
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
@@ -81,7 +77,7 @@ public:
|
||||
const rcl_subscription_options_t & subscription_options,
|
||||
bool is_serialized = false);
|
||||
|
||||
/// Destructor.
|
||||
/// Default destructor.
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~SubscriptionBase();
|
||||
|
||||
@@ -183,13 +179,6 @@ public:
|
||||
void
|
||||
handle_message(std::shared_ptr<void> & message, const rclcpp::MessageInfo & message_info) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
handle_serialized_message(
|
||||
const std::shared_ptr<rclcpp::SerializedMessage> & serialized_message,
|
||||
const rclcpp::MessageInfo & message_info) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
@@ -274,15 +263,6 @@ public:
|
||||
bool
|
||||
exchange_in_use_by_wait_set_state(void * pointer_to_subscription_part, bool in_use_state);
|
||||
|
||||
/// Get network flow endpoints
|
||||
/**
|
||||
* Describes network flow endpoints that this subscription is receiving messages on
|
||||
* \return vector of NetworkFlowEndpoint
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::NetworkFlowEndpoint>
|
||||
get_network_flow_endpoints() const;
|
||||
|
||||
protected:
|
||||
template<typename EventCallbackT>
|
||||
void
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "rosidl_typesupport_cpp/message_type_support.hpp"
|
||||
|
||||
#include "rclcpp/any_subscription_callback.hpp"
|
||||
#include "rclcpp/get_message_type_support_handle.hpp"
|
||||
#include "rclcpp/intra_process_buffer_type.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
@@ -75,23 +74,26 @@ template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename AllocatorT,
|
||||
typename SubscriptionT = rclcpp::Subscription<MessageT, AllocatorT>,
|
||||
typename MessageMemoryStrategyT = typename SubscriptionT::MessageMemoryStrategyType,
|
||||
typename ROSMessageType = typename SubscriptionT::ROSMessageType
|
||||
>
|
||||
typename CallbackMessageT =
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type,
|
||||
typename SubscriptionT = rclcpp::Subscription<CallbackMessageT, AllocatorT>,
|
||||
typename MessageMemoryStrategyT = rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
CallbackMessageT,
|
||||
AllocatorT
|
||||
>>
|
||||
SubscriptionFactory
|
||||
create_subscription_factory(
|
||||
CallbackT && callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
|
||||
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat,
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>>
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>>
|
||||
subscription_topic_stats = nullptr
|
||||
)
|
||||
{
|
||||
auto allocator = options.get_allocator();
|
||||
|
||||
using rclcpp::AnySubscriptionCallback;
|
||||
AnySubscriptionCallback<MessageT, AllocatorT> any_subscription_callback(*allocator);
|
||||
AnySubscriptionCallback<CallbackMessageT, AllocatorT> any_subscription_callback(allocator);
|
||||
any_subscription_callback.set(std::forward<CallbackT>(callback));
|
||||
|
||||
SubscriptionFactory factory {
|
||||
@@ -105,9 +107,9 @@ create_subscription_factory(
|
||||
using rclcpp::Subscription;
|
||||
using rclcpp::SubscriptionBase;
|
||||
|
||||
auto sub = Subscription<MessageT, AllocatorT>::make_shared(
|
||||
auto sub = Subscription<CallbackMessageT, AllocatorT>::make_shared(
|
||||
node_base,
|
||||
rclcpp::get_message_type_support_handle<MessageT>(),
|
||||
*rosidl_typesupport_cpp::get_message_type_support_handle<MessageT>(),
|
||||
topic_name,
|
||||
qos,
|
||||
any_subscription_callback,
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
@@ -27,7 +26,6 @@
|
||||
#include "rclcpp/intra_process_setting.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/qos_event.hpp"
|
||||
#include "rclcpp/qos_overriding_options.hpp"
|
||||
#include "rclcpp/topic_statistics_state.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
@@ -46,11 +44,6 @@ struct SubscriptionOptionsBase
|
||||
/// True to ignore local publications.
|
||||
bool ignore_local_publications = false;
|
||||
|
||||
/// Require middleware to generate unique network flow endpoints
|
||||
/// Disabled by default
|
||||
rmw_unique_network_flow_endpoints_requirement_t require_unique_network_flow_endpoints =
|
||||
RMW_UNIQUE_NETWORK_FLOW_ENDPOINTS_NOT_REQUIRED;
|
||||
|
||||
/// The callback group for this subscription. NULL to use the default callback group.
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group = nullptr;
|
||||
|
||||
@@ -79,18 +72,12 @@ struct SubscriptionOptionsBase
|
||||
};
|
||||
|
||||
TopicStatisticsOptions topic_stats_options;
|
||||
|
||||
QosOverridingOptions qos_overriding_options;
|
||||
};
|
||||
|
||||
/// Structure containing optional configuration for Subscriptions.
|
||||
template<typename Allocator>
|
||||
struct SubscriptionOptionsWithAllocator : public SubscriptionOptionsBase
|
||||
{
|
||||
static_assert(
|
||||
std::is_void_v<typename std::allocator_traits<Allocator>::value_type>,
|
||||
"Subscription allocator value type must be void");
|
||||
|
||||
/// Optional custom allocator.
|
||||
std::shared_ptr<Allocator> allocator = nullptr;
|
||||
|
||||
@@ -112,11 +99,12 @@ struct SubscriptionOptionsWithAllocator : public SubscriptionOptionsBase
|
||||
to_rcl_subscription_options(const rclcpp::QoS & qos) const
|
||||
{
|
||||
rcl_subscription_options_t result = rcl_subscription_get_default_options();
|
||||
result.allocator = this->get_rcl_allocator();
|
||||
using AllocatorTraits = std::allocator_traits<Allocator>;
|
||||
using MessageAllocatorT = typename AllocatorTraits::template rebind_alloc<MessageT>;
|
||||
auto message_alloc = std::make_shared<MessageAllocatorT>(*this->get_allocator().get());
|
||||
result.allocator = allocator::get_rcl_allocator<MessageT>(*message_alloc);
|
||||
result.qos = qos.get_rmw_qos_profile();
|
||||
result.rmw_subscription_options.ignore_local_publications = this->ignore_local_publications;
|
||||
result.rmw_subscription_options.require_unique_network_flow_endpoints =
|
||||
this->require_unique_network_flow_endpoints;
|
||||
|
||||
// Apply payload to rcl_subscription_options if necessary.
|
||||
if (rmw_implementation_payload && rmw_implementation_payload->has_been_customized()) {
|
||||
@@ -126,39 +114,15 @@ struct SubscriptionOptionsWithAllocator : public SubscriptionOptionsBase
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Get the allocator, creating one if needed.
|
||||
std::shared_ptr<Allocator>
|
||||
get_allocator() const
|
||||
{
|
||||
if (!this->allocator) {
|
||||
if (!allocator_storage_) {
|
||||
allocator_storage_ = std::make_shared<Allocator>();
|
||||
}
|
||||
return allocator_storage_;
|
||||
return std::make_shared<Allocator>();
|
||||
}
|
||||
return this->allocator;
|
||||
}
|
||||
|
||||
private:
|
||||
using PlainAllocator =
|
||||
typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
|
||||
|
||||
rcl_allocator_t
|
||||
get_rcl_allocator() const
|
||||
{
|
||||
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()
|
||||
// always returns a copy of the same allocator.
|
||||
mutable std::shared_ptr<Allocator> allocator_storage_;
|
||||
|
||||
// This is a temporal workaround, to keep the plain allocator that backs
|
||||
// up the rcl allocator returned in rcl_subscription_options_t alive.
|
||||
mutable std::shared_ptr<PlainAllocator> plain_allocator_storage_;
|
||||
};
|
||||
|
||||
using SubscriptionOptions = SubscriptionOptionsWithAllocator<std::allocator<void>>;
|
||||
|
||||
@@ -64,7 +64,7 @@ struct is_serialized_callback
|
||||
template<typename MessageT>
|
||||
struct extract_message_type
|
||||
{
|
||||
using type = typename std::remove_cv_t<std::remove_reference_t<MessageT>>;
|
||||
using type = typename std::remove_cv<MessageT>::type;
|
||||
};
|
||||
|
||||
template<typename MessageT>
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "rcl_interfaces/msg/parameter_event.hpp"
|
||||
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
|
||||
|
||||
|
||||
@@ -33,20 +32,6 @@ namespace rclcpp
|
||||
{
|
||||
class Clock;
|
||||
|
||||
/**
|
||||
* Time source that will drive the attached clocks.
|
||||
*
|
||||
* If the attached node `use_sim_time` parameter is `true`, the attached clocks will
|
||||
* be updated based on messages received.
|
||||
*
|
||||
* The subscription to the clock topic created by the time source can have it's qos reconfigured
|
||||
* using parameter overrides, particularly the following ones are accepted:
|
||||
*
|
||||
* - qos_overrides./clock.depth
|
||||
* - qos_overrides./clock.durability
|
||||
* - qos_overrides./clock.history
|
||||
* - qos_overrides./clock.reliability
|
||||
*/
|
||||
class TimeSource
|
||||
{
|
||||
public:
|
||||
@@ -55,33 +40,25 @@ public:
|
||||
* The node will be attached to the time source.
|
||||
*
|
||||
* \param node std::shared pointer to a initialized node
|
||||
* \param qos QoS that will be used when creating a `/clock` subscription.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit TimeSource(
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const rclcpp::QoS & qos = rclcpp::ClockQoS(),
|
||||
bool use_clock_thread = true);
|
||||
explicit TimeSource(rclcpp::Node::SharedPtr node);
|
||||
|
||||
/// Empty constructor
|
||||
/**
|
||||
* An Empty TimeSource class
|
||||
*
|
||||
* \param qos QoS that will be used when creating a `/clock` subscription.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit TimeSource(
|
||||
const rclcpp::QoS & qos = rclcpp::ClockQoS(),
|
||||
bool use_clock_thread = true);
|
||||
TimeSource();
|
||||
|
||||
/// Attach node to the time source.
|
||||
/// Attack node to the time source.
|
||||
/**
|
||||
* \param node std::shared pointer to a initialized node
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void attachNode(rclcpp::Node::SharedPtr node);
|
||||
|
||||
/// Attach node to the time source.
|
||||
/// Attack node to the time source.
|
||||
/**
|
||||
* If the parameter `use_sim_time` is `true` then the source time is the simulation time,
|
||||
* otherwise the source time is defined by the system.
|
||||
@@ -124,11 +101,6 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
~TimeSource();
|
||||
|
||||
protected:
|
||||
// Dedicated thread for clock subscription.
|
||||
bool use_clock_thread_;
|
||||
std::thread clock_executor_thread_;
|
||||
|
||||
private:
|
||||
// Preserve the node reference
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
|
||||
@@ -142,21 +114,15 @@ private:
|
||||
// Store (and update on node attach) logger for logging.
|
||||
Logger logger_;
|
||||
|
||||
// QoS of the clock subscription.
|
||||
rclcpp::QoS qos_;
|
||||
|
||||
// The subscription for the clock callback
|
||||
using MessageT = rosgraph_msgs::msg::Clock;
|
||||
using Alloc = std::allocator<void>;
|
||||
using SubscriptionT = rclcpp::Subscription<MessageT, Alloc>;
|
||||
std::shared_ptr<SubscriptionT> clock_subscription_{nullptr};
|
||||
std::shared_ptr<SubscriptionT> clock_subscription_;
|
||||
std::mutex clock_sub_lock_;
|
||||
rclcpp::CallbackGroup::SharedPtr clock_callback_group_;
|
||||
rclcpp::executors::SingleThreadedExecutor::SharedPtr clock_executor_;
|
||||
std::promise<void> cancel_clock_executor_promise_;
|
||||
|
||||
// The clock callback itself
|
||||
void clock_cb(std::shared_ptr<const rosgraph_msgs::msg::Clock> msg);
|
||||
void clock_cb(const rosgraph_msgs::msg::Clock::SharedPtr msg);
|
||||
|
||||
// Create the subscription for the clock topic
|
||||
void create_clock_sub();
|
||||
@@ -170,7 +136,7 @@ private:
|
||||
std::shared_ptr<ParamSubscriptionT> parameter_subscription_;
|
||||
|
||||
// Callback for parameter updates
|
||||
void on_parameter_event(std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event);
|
||||
void on_parameter_event(const rcl_interfaces::msg::ParameterEvent::SharedPtr event);
|
||||
|
||||
// An enum to hold the parameter state
|
||||
enum UseSimTimeParameterState {UNSET, SET_TRUE, SET_FALSE};
|
||||
@@ -189,16 +155,16 @@ private:
|
||||
|
||||
// Local storage of validity of ROS time
|
||||
// This is needed when new clocks are added.
|
||||
bool ros_time_active_{false};
|
||||
bool ros_time_active_;
|
||||
// Last set message to be passed to newly registered clocks
|
||||
std::shared_ptr<const rosgraph_msgs::msg::Clock> last_msg_set_;
|
||||
rosgraph_msgs::msg::Clock::SharedPtr last_msg_set_;
|
||||
|
||||
// A lock to protect iterating the associated_clocks_ field.
|
||||
std::mutex clock_list_lock_;
|
||||
// A vector to store references to associated clocks.
|
||||
std::vector<rclcpp::Clock::SharedPtr> associated_clocks_;
|
||||
// A handler for the use_sim_time parameter callback.
|
||||
rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr sim_time_cb_handler_{nullptr};
|
||||
rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr sim_time_cb_handler_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -176,12 +176,12 @@ public:
|
||||
{
|
||||
TRACEPOINT(
|
||||
rclcpp_timer_callback_added,
|
||||
static_cast<const void *>(get_timer_handle().get()),
|
||||
static_cast<const void *>(&callback_));
|
||||
(const void *)get_timer_handle().get(),
|
||||
(const void *)&callback_);
|
||||
TRACEPOINT(
|
||||
rclcpp_callback_register,
|
||||
static_cast<const void *>(&callback_),
|
||||
tracetools::get_symbol(callback_));
|
||||
(const void *)&callback_,
|
||||
get_symbol(callback_));
|
||||
}
|
||||
|
||||
/// Default destructor.
|
||||
@@ -205,9 +205,9 @@ public:
|
||||
if (ret != RCL_RET_OK) {
|
||||
throw std::runtime_error("Failed to notify timer that callback occurred");
|
||||
}
|
||||
TRACEPOINT(callback_start, static_cast<const void *>(&callback_), false);
|
||||
TRACEPOINT(callback_start, (const void *)&callback_, false);
|
||||
execute_callback_delegate<>();
|
||||
TRACEPOINT(callback_end, static_cast<const void *>(&callback_));
|
||||
TRACEPOINT(callback_end, (const void *)&callback_);
|
||||
}
|
||||
|
||||
// void specialization
|
||||
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
/**
|
||||
* This method acquires a lock to prevent race conditions to collectors list.
|
||||
*/
|
||||
virtual void publish_message_and_reset_measurements()
|
||||
virtual void publish_message()
|
||||
{
|
||||
std::vector<MetricsMessage> msgs;
|
||||
rclcpp::Time window_end{get_current_nanoseconds_since_epoch()};
|
||||
@@ -136,7 +136,6 @@ public:
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
for (auto & collector : subscriber_statistics_collectors_) {
|
||||
const auto collected_stats = collector->GetStatisticsResults();
|
||||
collector->ClearCurrentMeasurements();
|
||||
|
||||
auto message = libstatistics_collector::collector::GenerateStatisticMessage(
|
||||
node_name_,
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
// Copyright 2021 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__TYPE_ADAPTER_HPP_
|
||||
#define RCLCPP__TYPE_ADAPTER_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Template structure used to adapt custom, user-defined types to ROS types.
|
||||
/**
|
||||
* Adapting a custom, user-defined type to a ROS type allows that custom type
|
||||
* to be used when publishing and subscribing in ROS.
|
||||
*
|
||||
* In order to adapt a custom type to a ROS type, the user must create a
|
||||
* template specialization of this structure for the custom type.
|
||||
* In that specialization they must:
|
||||
*
|
||||
* - change `is_specialized` to `std::true_type`,
|
||||
* - specify the custom type with `using custom_type = ...`,
|
||||
* - specify the ROS type with `using ros_message_type = ...`,
|
||||
* - provide static convert functions with the signatures:
|
||||
* - static void convert_to_ros(const custom_type &, ros_message_type &)
|
||||
* - static void convert_to_custom(const ros_message_type &, custom_type &)
|
||||
*
|
||||
* The convert functions must convert from one type to the other.
|
||||
*
|
||||
* For example, here is a theoretical example for adapting `std::string` to the
|
||||
* `std_msgs::msg::String` ROS message type:
|
||||
*
|
||||
* template<>
|
||||
* struct rclcpp::TypeAdapter<std::string, std_msgs::msg::String>
|
||||
* {
|
||||
* using is_specialized = std::true_type;
|
||||
* using custom_type = std::string;
|
||||
* using ros_message_type = std_msgs::msg::String;
|
||||
*
|
||||
* static
|
||||
* void
|
||||
* convert_to_ros_message(
|
||||
* const custom_type & source,
|
||||
* ros_message_type & destination)
|
||||
* {
|
||||
* destination.data = source;
|
||||
* }
|
||||
*
|
||||
* static
|
||||
* void
|
||||
* convert_to_custom(
|
||||
* const ros_message_type & source,
|
||||
* custom_type & destination)
|
||||
* {
|
||||
* destination = source.data;
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* The adapter can then be used when creating a publisher or subscription,
|
||||
* e.g.:
|
||||
*
|
||||
* using MyAdaptedType = TypeAdapter<std::string, std_msgs::msg::String>;
|
||||
* auto pub = node->create_publisher<MyAdaptedType>("topic", 10);
|
||||
* auto sub = node->create_subscription<MyAdaptedType>(
|
||||
* "topic",
|
||||
* 10,
|
||||
* [](const std::string & msg) {...});
|
||||
*
|
||||
* You can also be more declarative by using the adapt_type::as metafunctions,
|
||||
* which are a bit less ambiguous to read:
|
||||
*
|
||||
* using AdaptedType = rclcpp::adapt_type<std::string>::as<std_msgs::msg::String>;
|
||||
* auto pub = node->create_publisher<AdaptedType>(...);
|
||||
*
|
||||
* If you wish, you may associate a custom type with a single ROS message type,
|
||||
* allowing you to be a bit more brief when creating entities, e.g.:
|
||||
*
|
||||
* // First you must declare the association, this is similar to how you
|
||||
* // would avoid using the namespace in C++ by doing `using std::vector;`.
|
||||
* RCLCPP_USING_CUSTOM_TYPE_AS_ROS_MESSAGE_TYPE(std::string, std_msgs::msg::String);
|
||||
*
|
||||
* // Then you can create things with just the custom type, and the ROS
|
||||
* // message type is implied based on the previous statement.
|
||||
* auto pub = node->create_publisher<std::string>(...);
|
||||
*/
|
||||
template<typename CustomType, typename ROSMessageType = void, class Enable = void>
|
||||
struct TypeAdapter
|
||||
{
|
||||
using is_specialized = std::false_type;
|
||||
using custom_type = CustomType;
|
||||
// In this case, the CustomType is the only thing given, or there is no specialization.
|
||||
// Assign ros_message_type to CustomType for the former case.
|
||||
using ros_message_type = CustomType;
|
||||
};
|
||||
|
||||
/// Helper template to determine if a type is a TypeAdapter, false specialization.
|
||||
template<typename T>
|
||||
struct is_type_adapter : std::false_type {};
|
||||
|
||||
/// Helper template to determine if a type is a TypeAdapter, true specialization.
|
||||
template<typename ... Ts>
|
||||
struct is_type_adapter<TypeAdapter<Ts...>>: std::true_type {};
|
||||
|
||||
/// Identity specialization for TypeAdapter.
|
||||
template<typename T>
|
||||
struct TypeAdapter<T, void, std::enable_if_t<is_type_adapter<T>::value>>: T {};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename CustomType, typename ROSMessageType>
|
||||
struct assert_type_pair_is_specialized_type_adapter
|
||||
{
|
||||
using type_adapter = TypeAdapter<CustomType, ROSMessageType>;
|
||||
static_assert(
|
||||
type_adapter::is_specialized::value,
|
||||
"No type adapter for this custom type/ros message type pair");
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Template metafunction that can make the type being adapted explicit.
|
||||
template<typename CustomType>
|
||||
struct adapt_type
|
||||
{
|
||||
template<typename ROSMessageType>
|
||||
using as = typename ::rclcpp::detail::assert_type_pair_is_specialized_type_adapter<
|
||||
CustomType,
|
||||
ROSMessageType
|
||||
>::type_adapter;
|
||||
};
|
||||
|
||||
/// Implicit type adapter used as a short hand way to create something with just the custom type.
|
||||
/**
|
||||
* This is used when creating a publisher or subscription using just the custom
|
||||
* type in conjunction with RCLCPP_USING_CUSTOM_TYPE_AS_ROS_MESSAGE_TYPE().
|
||||
* For example:
|
||||
*
|
||||
* #include "type_adapter_for_std_string_to_std_msgs_String.hpp"
|
||||
*
|
||||
* RCLCPP_USING_CUSTOM_TYPE_AS_ROS_MESSAGE_TYPE(std::string, std_msgs::msg::String);
|
||||
*
|
||||
* int main(...) {
|
||||
* // ...
|
||||
* auto pub = node->create_publisher<std::string>(...);
|
||||
* }
|
||||
*
|
||||
* \sa TypeAdapter for more examples.
|
||||
*/
|
||||
template<typename CustomType>
|
||||
struct ImplicitTypeAdapter
|
||||
{
|
||||
using is_specialized = std::false_type;
|
||||
};
|
||||
|
||||
/// Specialization of TypeAdapter for ImplicitTypeAdapter.
|
||||
/**
|
||||
* This allows for things like this:
|
||||
*
|
||||
* RCLCPP_USING_CUSTOM_TYPE_AS_ROS_MESSAGE_TYPE(std::string, std_msgs::msg::String);
|
||||
* auto pub = node->create_publisher<std::string>("topic", 10);
|
||||
*
|
||||
*/
|
||||
template<typename T>
|
||||
struct TypeAdapter<T, void, std::enable_if_t<ImplicitTypeAdapter<T>::is_specialized::value>>
|
||||
: ImplicitTypeAdapter<T>
|
||||
{};
|
||||
|
||||
/// Assigns the custom type implicitly to the given custom type/ros message type pair.
|
||||
/**
|
||||
* Note: this macro needs to be used in the root namespace.
|
||||
* We cannot use ::rclcpp to protect against this, due to how GCC interprets the
|
||||
* syntax, see: https://stackoverflow.com/a/2781537
|
||||
*
|
||||
* \sa TypeAdapter
|
||||
* \sa ImplicitTypeAdapter
|
||||
*/
|
||||
#define RCLCPP_USING_CUSTOM_TYPE_AS_ROS_MESSAGE_TYPE(CustomType, ROSMessageType) \
|
||||
template<> \
|
||||
struct rclcpp::ImplicitTypeAdapter<CustomType> \
|
||||
: public rclcpp::TypeAdapter<CustomType, ROSMessageType> \
|
||||
{ \
|
||||
static_assert( \
|
||||
is_specialized::value, \
|
||||
"Cannot use custom type as ros type when there is no TypeAdapter for that pair"); \
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__TYPE_ADAPTER_HPP_
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright 2018, Bosch Software Innovations GmbH.
|
||||
// Copyright 2021, Apex.AI 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__TYPESUPPORT_HELPERS_HPP_
|
||||
#define RCLCPP__TYPESUPPORT_HELPERS_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
#include "rcpputils/shared_library.hpp"
|
||||
#include "rosidl_runtime_cpp/message_type_support_decl.hpp"
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
/// Load the type support library for the given type.
|
||||
/**
|
||||
* \param[in] type The topic type, e.g. "std_msgs/msg/String"
|
||||
* \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
|
||||
* \return A shared library
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<rcpputils::SharedLibrary>
|
||||
get_typesupport_library(const std::string & type, const std::string & typesupport_identifier);
|
||||
|
||||
/// Extract the type support handle from the library.
|
||||
/**
|
||||
* The library needs to match the topic type. The shared library must stay loaded for the lifetime of the result.
|
||||
* \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
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_message_type_support_t *
|
||||
get_typesupport_handle(
|
||||
const std::string & type,
|
||||
const std::string & typesupport_identifier,
|
||||
rcpputils::SharedLibrary & library);
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__TYPESUPPORT_HELPERS_HPP_
|
||||
@@ -143,6 +143,21 @@ RCLCPP_PUBLIC
|
||||
bool
|
||||
ok(rclcpp::Context::SharedPtr context = nullptr);
|
||||
|
||||
/// Return true if init() has already been called for the given context.
|
||||
/**
|
||||
* If nullptr is given for the context, then the global context is used, i.e.
|
||||
* the context initialized by rclcpp::init().
|
||||
*
|
||||
* Deprecated, as it is no longer different from rcl_ok().
|
||||
*
|
||||
* \param[in] context Optional check for initialization of this Context.
|
||||
* \return true if the context is initialized, and false otherwise
|
||||
*/
|
||||
[[deprecated("use the function ok() instead, which has the same usage.")]]
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
is_initialized(rclcpp::Context::SharedPtr context = nullptr);
|
||||
|
||||
/// Shutdown rclcpp context, invalidating it for derived entities.
|
||||
/**
|
||||
* If nullptr is given for the context, then the global context is used, i.e.
|
||||
|
||||
100
rclcpp/include/rclcpp/wait_for_message.hpp
Normal file
100
rclcpp/include/rclcpp/wait_for_message.hpp
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright 2021 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__WAIT_FOR_MESSAGE_HPP_
|
||||
#define RCLCPP__WAIT_FOR_MESSAGE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rclcpp/wait_set.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
/// Wait for the next incoming message.
|
||||
/**
|
||||
* Given an already initialized subscription,
|
||||
* wait for the next incoming message to arrive before the specified timeout.
|
||||
*
|
||||
* \param[out] out is the message to be filled when a new message is arriving.
|
||||
* \param[in] subscription shared pointer to a previously initialized subscription.
|
||||
* \param[in] context shared pointer to a context to watch for SIGINT requests.
|
||||
* \param[in] time_to_wait parameter specifying the timeout before returning.
|
||||
* \return true if a message was successfully received, false if message could not
|
||||
* be obtained or shutdown was triggered asynchronously on the context.
|
||||
*/
|
||||
template<class MsgT, class Rep = int64_t, class Period = std::milli>
|
||||
bool wait_for_message(
|
||||
MsgT & out,
|
||||
std::shared_ptr<rclcpp::Subscription<MsgT>> subscription,
|
||||
std::shared_ptr<rclcpp::Context> context,
|
||||
std::chrono::duration<Rep, Period> time_to_wait = std::chrono::duration<Rep, Period>(-1))
|
||||
{
|
||||
auto gc = std::make_shared<rclcpp::GuardCondition>(context);
|
||||
auto shutdown_callback = context->on_shutdown(
|
||||
[weak_gc = std::weak_ptr<rclcpp::GuardCondition>{gc}]() {
|
||||
auto strong_gc = weak_gc.lock();
|
||||
if (strong_gc) {
|
||||
strong_gc->trigger();
|
||||
}
|
||||
});
|
||||
|
||||
rclcpp::WaitSet wait_set;
|
||||
wait_set.add_subscription(subscription);
|
||||
wait_set.add_guard_condition(gc);
|
||||
auto ret = wait_set.wait(time_to_wait);
|
||||
if (ret.kind() != rclcpp::WaitResultKind::Ready) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wait_set.get_rcl_wait_set().guard_conditions[0]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rclcpp::MessageInfo info;
|
||||
if (!subscription->take(out, info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Wait for the next incoming message.
|
||||
/**
|
||||
* Wait for the next incoming message to arrive on a specified topic before the specified timeout.
|
||||
*
|
||||
* \param[out] out is the message to be filled when a new message is arriving.
|
||||
* \param[in] node the node pointer to initialize the subscription on.
|
||||
* \param[in] topic the topic to wait for messages.
|
||||
* \param[in] time_to_wait parameter specifying the timeout before returning.
|
||||
* \return true if a message was successfully received, false if message could not
|
||||
* be obtained or shutdown was triggered asynchronously on the context.
|
||||
*/
|
||||
template<class MsgT, class Rep = int64_t, class Period = std::milli>
|
||||
bool wait_for_message(
|
||||
MsgT & out,
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const std::string & topic,
|
||||
std::chrono::duration<Rep, Period> time_to_wait = std::chrono::duration<Rep, Period>(-1))
|
||||
{
|
||||
auto sub = node->create_subscription<MsgT>(topic, 1, [](const std::shared_ptr<MsgT>) {});
|
||||
return wait_for_message<MsgT, Rep, Period>(
|
||||
out, sub, node->get_node_options().context(), time_to_wait);
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__WAIT_FOR_MESSAGE_HPP_
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright 2021 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__WAIT_SET_POLICIES__ALREADY_ASSOCIATED_WITH_WAIT_SET_EXCEPTION_HPP_
|
||||
#define RCLCPP__WAIT_SET_POLICIES__ALREADY_ASSOCIATED_WITH_WAIT_SET_EXCEPTION_HPP_
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "rmw/impl/cpp/demangle.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace wait_set_policies
|
||||
{
|
||||
|
||||
class AlreadyAssociatedWithWaitSetException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
template<typename EntityT>
|
||||
explicit
|
||||
AlreadyAssociatedWithWaitSetException(const EntityT & entity_instance)
|
||||
: std::runtime_error(
|
||||
"cannot associate " +
|
||||
rmw::impl::cpp::demangle(entity_instance) +
|
||||
" with wait set because it is already in use by a wait set")
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace wait_set_policies
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__WAIT_SET_POLICIES__ALREADY_ASSOCIATED_WITH_WAIT_SET_EXCEPTION_HPP_
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright 2021 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__WAIT_SET_POLICIES__DETAIL__CLIENT_ENTRY_HPP_
|
||||
#define RCLCPP__WAIT_SET_POLICIES__DETAIL__CLIENT_ENTRY_HPP_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/client.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/entity_entry.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace wait_set_policies
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
using ClientEntry =
|
||||
// EntityEntryTemplate<rclcpp::ClientBase, std::shared_ptr<rclcpp::ClientBase>>;
|
||||
EntityEntryTemplate<rclcpp::ClientBase>;
|
||||
using WeakClientEntry =
|
||||
// EntityEntryTemplate<rclcpp::ClientBase, std::weak_ptr<rclcpp::ClientBase>>;
|
||||
EntityEntryTemplate<rclcpp::ClientBase>;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace wait_set_policies
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__WAIT_SET_POLICIES__DETAIL__CLIENT_ENTRY_HPP_
|
||||
@@ -1,183 +0,0 @@
|
||||
// Copyright 2021 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__WAIT_SET_POLICIES__DETAIL__ENTITY_ENTRY_HPP_
|
||||
#define RCLCPP__WAIT_SET_POLICIES__DETAIL__ENTITY_ENTRY_HPP_
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/wait_set_policies/already_associated_with_wait_set_exception.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace wait_set_policies
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Forward declaration for use in friend statement.
|
||||
template<typename EntityT>
|
||||
class ManagedEntityEntryTemplate;
|
||||
|
||||
/// Encapsulating class for wait set entities, and gateway to the ManagedEntityEntryTemplate.
|
||||
/**
|
||||
* The entity is stored as a std::shared_ptr.
|
||||
*
|
||||
* This is class can be converted to a "managed" version which ensures the
|
||||
* entity is not associated with another wait set already, then associates it
|
||||
* with the current wait set, and then dissociates it on destruction.
|
||||
*/
|
||||
template<typename EntityT>
|
||||
class EntityEntryTemplate
|
||||
{
|
||||
public:
|
||||
EntityEntryTemplate(std::shared_ptr<EntityT> entity_in = nullptr)
|
||||
: entity_(entity_in)
|
||||
{}
|
||||
private:
|
||||
std::shared_ptr<EntityT> entity_;
|
||||
|
||||
friend ManagedEntityEntryTemplate<EntityT>;
|
||||
};
|
||||
|
||||
/// Managing class for wait set entities, with RAII-style (dis)association with the wait set.
|
||||
/**
|
||||
* The entity is stored as a std::shared_ptr, but ths class can be converted
|
||||
* (one way) into a weak version that stores it as a std::weak_ptr.
|
||||
*
|
||||
* This class will assert that the entity is not already associated with a
|
||||
* wait set, while atomically indicating it is associated with this wait set
|
||||
* to prevent other wait sets from using it, and then on destruction this class
|
||||
* will disassociate it.
|
||||
*
|
||||
* \throws rclcpp::wait_set_policies::AlreadyAssociatedWithWaitSetException if entity
|
||||
* is already associated with a wait set.
|
||||
*/
|
||||
template<typename EntityT>
|
||||
class ManagedEntityEntryTemplate
|
||||
{
|
||||
public:
|
||||
/// The only valid way to construct this is with an unmanaged entity entry.
|
||||
explicit ManagedEntityEntryTemplate(const EntityEntryTemplate<EntityT> & unmanaged_entity_entry)
|
||||
: entity_(unmanaged_entity_entry.entity_)
|
||||
{
|
||||
if (nullptr == entity_) {
|
||||
throw std::invalid_argument("entity cannot be nullptr for a managed entry");
|
||||
}
|
||||
bool already_in_use = entity_->exchange_in_use_by_wait_set_state(true);
|
||||
if (already_in_use) {
|
||||
throw rclcpp::wait_set_policies::AlreadyAssociatedWithWaitSetException(*entity_);
|
||||
}
|
||||
}
|
||||
|
||||
// ManagedEntityEntryTemplate(const ManagedEntityEntryTemplate<EntityT> & other)
|
||||
// {
|
||||
// if (other.should_set_in_use_by_wait_set_of_entity_to_false_on_destruction_) {
|
||||
// throw std::runtime_error("")
|
||||
// }
|
||||
// }
|
||||
|
||||
~ManagedEntityEntryTemplate()
|
||||
{
|
||||
if ((nullptr != entity_)) {
|
||||
bool was_in_use = entity_->exchange_in_use_by_wait_set_state(false);
|
||||
assert(was_in_use);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the interal entity shared pointer.
|
||||
std::shared_ptr<EntityT>
|
||||
get_entity() const
|
||||
{
|
||||
return entity_;
|
||||
}
|
||||
|
||||
/// Reset the entity.
|
||||
/**
|
||||
* Specializations of this class may reset more than one item.
|
||||
* Having this method in all instantiations of this class provides uniform access.
|
||||
*/
|
||||
// void
|
||||
// reset() noexcept
|
||||
// {
|
||||
// entity_.reset();
|
||||
// }
|
||||
|
||||
protected:
|
||||
std::shared_ptr<EntityT> entity_;
|
||||
|
||||
};
|
||||
|
||||
/// Version of ManagedEntityEntryTemplate with weak ownership and best effort disassociation.
|
||||
/**
|
||||
* The entity is stored as a std::weak_ptr, but on destruction, the entity is
|
||||
* locked, and if not nullptr, then it will be marked as not in use by a wait set.
|
||||
*/
|
||||
template<typename EntityT>
|
||||
class WeakManagedEntityEntryTemplate
|
||||
{
|
||||
public:
|
||||
/// Can only be constructed from a moved ManagedEntityEntryTemplate.
|
||||
explicit WeakManagedEntityEntryTemplate(ManagedEntityEntryTemplate<EntityT> && moved_entity_entry)
|
||||
: weak_entity_(moved_entity_entry.get_entity())
|
||||
{}
|
||||
|
||||
~WeakManagedEntityEntryTemplate()
|
||||
{
|
||||
auto entity = weak_entity_.lock();
|
||||
if (nullptr != entity) {
|
||||
bool was_in_use = entity->exchange_in_use_by_wait_set_state(false);
|
||||
assert(was_in_use);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the interal entity weak pointer.
|
||||
std::weak_ptr<EntityT>
|
||||
get_weak_entity() const
|
||||
{
|
||||
return weak_entity_;
|
||||
}
|
||||
|
||||
// /// Lock the entity.
|
||||
// /**
|
||||
// * Specializations of this class may select from more than one item to lock.
|
||||
// * Having this method in all instantiations of this class provides uniform access.
|
||||
// */
|
||||
// std::shared_ptr<EntityT>
|
||||
// lock() const
|
||||
// {
|
||||
// return weak_entity_.lock();
|
||||
// }
|
||||
|
||||
// /// Return true if the entity has expired, otherwise false.
|
||||
// /**
|
||||
// * Specializations of this class may select from more than one item to check.
|
||||
// * Having this method in all instantiations of this class provides uniform access.
|
||||
// */
|
||||
// bool
|
||||
// expired() const noexcept
|
||||
// {
|
||||
// return weak_entity_.expired();
|
||||
// }
|
||||
private:
|
||||
std::weak_ptr<EntityT> weak_entity_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace wait_set_policies
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__WAIT_SET_POLICIES__DETAIL__ENTITY_ENTRY_HPP_
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright 2021 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__WAIT_SET_POLICIES__DETAIL__GUARD_CONDITION_ENTRY_HPP_
|
||||
#define RCLCPP__WAIT_SET_POLICIES__DETAIL__GUARD_CONDITION_ENTRY_HPP_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/guard_condition.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/entity_entry.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace wait_set_policies
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
using GuardConditionEntry =
|
||||
// EntityEntryTemplate<rclcpp::GuardCondition, std::shared_ptr<rclcpp::GuardCondition>>;
|
||||
EntityEntryTemplate<rclcpp::GuardCondition>;
|
||||
using WeakGuardConditionEntry =
|
||||
// EntityEntryTemplate<rclcpp::GuardCondition, std::weak_ptr<rclcpp::GuardCondition>>;
|
||||
EntityEntryTemplate<rclcpp::GuardCondition>;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace wait_set_policies
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__WAIT_SET_POLICIES__DETAIL__GUARD_CONDITION_ENTRY_HPP_
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright 2021 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__WAIT_SET_POLICIES__DETAIL__SERVICE_ENTRY_HPP_
|
||||
#define RCLCPP__WAIT_SET_POLICIES__DETAIL__SERVICE_ENTRY_HPP_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/service.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/entity_entry.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace wait_set_policies
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
using ServiceEntry =
|
||||
// EntityEntryTemplate<rclcpp::ServiceBase, std::shared_ptr<rclcpp::ServiceBase>>;
|
||||
EntityEntryTemplate<rclcpp::ServiceBase>;
|
||||
using WeakServiceEntry =
|
||||
// EntityEntryTemplate<rclcpp::ServiceBase, std::weak_ptr<rclcpp::ServiceBase>>;
|
||||
EntityEntryTemplate<rclcpp::ServiceBase>;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace wait_set_policies
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__WAIT_SET_POLICIES__DETAIL__SERVICE_ENTRY_HPP_
|
||||
@@ -1,403 +0,0 @@
|
||||
// Copyright 2021 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__WAIT_SET_POLICIES__DETAIL__SUBSCRIPTION_ENTRY_HPP_
|
||||
#define RCLCPP__WAIT_SET_POLICIES__DETAIL__SUBSCRIPTION_ENTRY_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/subscription_base.hpp"
|
||||
#include "rclcpp/subscription_wait_set_mask.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/entity_entry.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/waitable_entry.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace wait_set_policies
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// See rclcpp::wait_set_policies::detail::EntityEntryTemplate.
|
||||
template<>
|
||||
class EntityEntryTemplate<rclcpp::SubscriptionBase>
|
||||
{
|
||||
using EntityT = rclcpp::SubscriptionBase;
|
||||
|
||||
public:
|
||||
EntityEntryTemplate(
|
||||
std::shared_ptr<EntityT> entity_in = nullptr,
|
||||
const rclcpp::SubscriptionWaitSetMask & mask_in = {})
|
||||
: entity_(entity_in),
|
||||
mask_(mask_in)
|
||||
{}
|
||||
|
||||
/// Create ManagedEntityEntryTemplate instances for the subscription and waitables if needed.
|
||||
/**
|
||||
* This method uses the SubscriptionWaitSetMask to determine how to decompose
|
||||
* the various entities within the subscription into managed entries.
|
||||
*
|
||||
* It optionally returns a managed entry for the subscription, if the mask
|
||||
* indicates it should, and then optionally any waitables for the
|
||||
* intra-process communication and QoS events.
|
||||
*/
|
||||
std::pair<
|
||||
std::optional<ManagedEntityEntryTemplate<rclcpp::SubscriptionBase>>,
|
||||
std::vector<ManagedEntityEntryTemplate<rclcpp::Waitable>>
|
||||
>
|
||||
manage();
|
||||
// defined below ManagedEntityEntryTemplate<rclcpp::SubscriptionBase>.
|
||||
|
||||
private:
|
||||
std::shared_ptr<EntityT> entity_;
|
||||
rclcpp::SubscriptionWaitSetMask mask_;
|
||||
};
|
||||
|
||||
/// See rclcpp::wait_set_policies::detail::ManagedEntityEntryTemplate.
|
||||
template<>
|
||||
class ManagedEntityEntryTemplate<rclcpp::SubscriptionBase>
|
||||
{
|
||||
using EntityT = rclcpp::SubscriptionBase;
|
||||
|
||||
/// Only constructed by EntityEntryTemplate<rclcpp::SubscriptionBase>::manage().
|
||||
explicit ManagedEntityEntryTemplate(std::shared_ptr<EntityT> subscription)
|
||||
: entity_(subscription)
|
||||
{
|
||||
if (nullptr == entity_) {
|
||||
throw std::invalid_argument("entity cannot be nullptr for a managed entry");
|
||||
}
|
||||
bool already_in_use = entity_->exchange_in_use_by_wait_set_state(entity_.get(), true);
|
||||
if (already_in_use) {
|
||||
throw rclcpp::wait_set_policies::AlreadyAssociatedWithWaitSetException(*entity_);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// ManagedEntityEntryTemplate(const ManagedEntityEntryTemplate<EntityT> & other)
|
||||
// {
|
||||
// if (other.should_set_in_use_by_wait_set_of_entity_to_false_on_destruction_) {
|
||||
// throw std::runtime_error("")
|
||||
// }
|
||||
// }
|
||||
|
||||
~ManagedEntityEntryTemplate()
|
||||
{
|
||||
if ((nullptr != entity_)) {
|
||||
bool was_in_use = entity_->exchange_in_use_by_wait_set_state(entity_.get(), false);
|
||||
assert(was_in_use);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the interal entity shared pointer.
|
||||
std::shared_ptr<EntityT>
|
||||
get_entity() const
|
||||
{
|
||||
return entity_;
|
||||
}
|
||||
|
||||
/// Reset the entity.
|
||||
/**
|
||||
* Specializations of this class may reset more than one item.
|
||||
* Having this method in all instantiations of this class provides uniform access.
|
||||
*/
|
||||
// void
|
||||
// reset() noexcept
|
||||
// {
|
||||
// entity_.reset();
|
||||
// }
|
||||
|
||||
private:
|
||||
std::shared_ptr<EntityT> entity_;
|
||||
|
||||
friend EntityEntryTemplate<EntityT>;
|
||||
|
||||
};
|
||||
|
||||
std::pair<
|
||||
std::optional<ManagedEntityEntryTemplate<rclcpp::SubscriptionBase>>,
|
||||
std::vector<ManagedEntityEntryTemplate<rclcpp::Waitable>>
|
||||
>
|
||||
EntityEntryTemplate<rclcpp::SubscriptionBase>::manage()
|
||||
{
|
||||
std::optional<ManagedEntityEntryTemplate<rclcpp::SubscriptionBase>> managed_subscription_entry;
|
||||
std::vector<ManagedEntityEntryTemplate<rclcpp::Waitable>> waitables;
|
||||
|
||||
if (mask_.include_subscription) {
|
||||
managed_subscription_entry = ManagedEntityEntryTemplate<rclcpp::SubscriptionBase>(entity_);
|
||||
}
|
||||
if (mask_.include_events) {
|
||||
for (const auto & event_waitable : entity_->get_event_handlers()) {
|
||||
waitables.emplace_back(EntityEntryTemplate<rclcpp::Waitable>(event_waitable, entity_));
|
||||
}
|
||||
}
|
||||
if (mask_.include_intra_process_waitable) {
|
||||
waitables.emplace_back(
|
||||
EntityEntryTemplate<rclcpp::Waitable>(entity_->get_intra_process_waitable(), entity_)
|
||||
);
|
||||
}
|
||||
|
||||
return {managed_subscription_entry, waitables};
|
||||
}
|
||||
|
||||
/// See rclcpp::wait_set_policies::detail::WeakManagedEntityEntryTemplate.
|
||||
template<>
|
||||
class WeakManagedEntityEntryTemplate<rclcpp::SubscriptionBase>
|
||||
{
|
||||
using EntityT = rclcpp::SubscriptionBase;
|
||||
|
||||
public:
|
||||
/// Can only be constructed from a moved ManagedEntityEntryTemplate.
|
||||
explicit WeakManagedEntityEntryTemplate(ManagedEntityEntryTemplate<EntityT> && moved_entity_entry)
|
||||
: weak_entity_(moved_entity_entry.get_entity())
|
||||
{}
|
||||
|
||||
~WeakManagedEntityEntryTemplate()
|
||||
{
|
||||
auto entity = weak_entity_.lock();
|
||||
if (nullptr != entity) {
|
||||
bool was_in_use = entity->exchange_in_use_by_wait_set_state(entity.get(), false);
|
||||
assert(was_in_use);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the interal entity weak pointer.
|
||||
std::weak_ptr<EntityT>
|
||||
get_weak_entity() const
|
||||
{
|
||||
return weak_entity_;
|
||||
}
|
||||
|
||||
// /// Lock the entity.
|
||||
// /**
|
||||
// * Specializations of this class may select from more than one item to lock.
|
||||
// * Having this method in all instantiations of this class provides uniform access.
|
||||
// */
|
||||
// std::shared_ptr<EntityT>
|
||||
// lock() const
|
||||
// {
|
||||
// return weak_entity_.lock();
|
||||
// }
|
||||
|
||||
// /// Return true if the entity has expired, otherwise false.
|
||||
// /**
|
||||
// * Specializations of this class may select from more than one item to check.
|
||||
// * Having this method in all instantiations of this class provides uniform access.
|
||||
// */
|
||||
// bool
|
||||
// expired() const noexcept
|
||||
// {
|
||||
// return weak_entity_.expired();
|
||||
// }
|
||||
private:
|
||||
std::weak_ptr<EntityT> weak_entity_;
|
||||
std::weak_ptr<void> weak_associated_entity_;
|
||||
|
||||
};
|
||||
|
||||
using SubscriptionEntry = EntityEntryTemplate<rclcpp::SubscriptionBase>;
|
||||
using ManagedSubscriptionEntry = ManagedEntityEntryTemplate<rclcpp::SubscriptionBase>;
|
||||
using WeakManagedSubscriptionEntry = WeakManagedEntityEntryTemplate<rclcpp::SubscriptionBase>;
|
||||
|
||||
// /// Specialization for Subscriptions.
|
||||
// template<>
|
||||
// class EntityEntryTemplate<rclcpp::SubscriptionBase>
|
||||
// {
|
||||
// using EntityT = rclcpp::SubscriptionBase;
|
||||
// std::shared_ptr<EntityT> entity_;
|
||||
// rclcpp::SubscriptionWaitSetMask mask_;
|
||||
|
||||
// public:
|
||||
// EntityEntryTemplate(
|
||||
// std::shared_ptr<EntityT> entity_in = nullptr,
|
||||
// const rclcpp::SubscriptionWaitSetMask & mask_in = {})
|
||||
// : entity_(entity_in),
|
||||
// mask_(mask_in)
|
||||
// {}
|
||||
|
||||
// ~EntityEntryTemplate()
|
||||
// {
|
||||
// if (should_set_in_use_by_wait_set_of_entity_to_false_on_destruction_) {
|
||||
// EntityEntryTemplate<rclcpp::SubscriptionBase>::cleanup(entity_, mask_);
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// See EntityEntryTemplate::get_entity().
|
||||
// std::shared_ptr<EntityT>
|
||||
// get_entity() const
|
||||
// {
|
||||
// return entity_;
|
||||
// }
|
||||
|
||||
// /// Return a const reference to the subscrption mask.
|
||||
// const rclcpp::SubscriptionWaitSetMask &
|
||||
// get_mask() const
|
||||
// {
|
||||
// return mask_;
|
||||
// }
|
||||
|
||||
// /// See EntityEntryTemplate::manage().
|
||||
// std::vector<WaitableEntry>
|
||||
// manage()
|
||||
// {
|
||||
// if (nullptr == entity_) {
|
||||
// throw std::runtime_error("manage() called on EntityEntry with null entity");
|
||||
// }
|
||||
// auto associate = [this](void * entity_part) {
|
||||
// bool already_in_use = entity_->exchange_in_use_by_wait_set_state(entity_part, true);
|
||||
// if (already_in_use) {
|
||||
// throw rclcpp::wait_set_policies::AlreadyAssociatedWithWaitSetException(*entity_);
|
||||
// }
|
||||
// };
|
||||
|
||||
// if (mask_.include_subscription) {
|
||||
// associate(entity_.get());
|
||||
// }
|
||||
|
||||
// std::vector<WaitableEntry> decomposed_waitables;
|
||||
|
||||
// if (mask_.include_events) {
|
||||
// for (auto event : entity_->get_event_handlers()) {
|
||||
// // TODO(wjwwood): do we need to use the unmanage_function argument
|
||||
// // to utilize the exchange_in_use_by_wait_set_state of SubscriptionBase?
|
||||
// decomposed_waitables.emplace_back(event, entity_);
|
||||
// decomposed_waitables.back().manage();
|
||||
// }
|
||||
// // mask_.include_events = false;
|
||||
// }
|
||||
// if (mask_.include_intra_process_waitable) {
|
||||
// auto waitable = entity_->get_intra_process_waitable();
|
||||
// if (nullptr != waitable) {
|
||||
// // TODO(wjwwood): do we need to use the unmanage_function argument
|
||||
// // to utilize the exchange_in_use_by_wait_set_state of SubscriptionBase?
|
||||
// decomposed_waitables.emplace_back(waitable, entity_);
|
||||
// decomposed_waitables.back().manage();
|
||||
// // mask_.include_intra_process_waitable = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// should_set_in_use_by_wait_set_of_entity_to_false_on_destruction_ = true;
|
||||
|
||||
// return decomposed_waitables;
|
||||
// }
|
||||
|
||||
// /// See EntityEntryTemplate::reset().
|
||||
// void
|
||||
// reset() noexcept
|
||||
// {
|
||||
// entity_.reset();
|
||||
// }
|
||||
|
||||
// protected:
|
||||
// bool should_set_in_use_by_wait_set_of_entity_to_false_on_destruction_{false};
|
||||
|
||||
// static
|
||||
// void
|
||||
// cleanup(std::shared_ptr<EntityT> subscription, rclcpp::SubscriptionWaitSetMask mask)
|
||||
// {
|
||||
// if (subscription != nullptr) {
|
||||
// auto dissociate = [&subscription](void * entity_part) {
|
||||
// bool was_in_use = subscription->exchange_in_use_by_wait_set_state(entity_part, false);
|
||||
// assert(was_in_use);
|
||||
// };
|
||||
// if (mask.include_subscription) {
|
||||
// dissociate(subscription.get());
|
||||
// }
|
||||
// if (mask.include_events) {
|
||||
// for (auto event : subscription->get_event_handlers()) {
|
||||
// dissociate(event.get());
|
||||
// }
|
||||
// }
|
||||
// if (mask.include_intra_process_waitable) {
|
||||
// auto waitable = subscription->get_intra_process_waitable();
|
||||
// if (nullptr != waitable) {
|
||||
// dissociate(waitable.get());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// friend WeakEntityEntryTemplate<EntityT>;
|
||||
|
||||
// };
|
||||
|
||||
// /// Specialization for Subscriptions.
|
||||
// template<>
|
||||
// class WeakEntityEntryTemplate<rclcpp::SubscriptionBase>
|
||||
// {
|
||||
// using EntityT = rclcpp::SubscriptionBase;
|
||||
// std::weak_ptr<EntityT> weak_entity_;
|
||||
// rclcpp::SubscriptionWaitSetMask mask_;
|
||||
|
||||
// public:
|
||||
// explicit WeakEntityEntryTemplate(EntityEntryTemplate<EntityT> && moved_entity_entry)
|
||||
// : weak_entity_(moved_entity_entry.get_entity()),
|
||||
// mask_(moved_entity_entry.mask_),
|
||||
// should_set_in_use_by_wait_set_of_entity_to_false_on_destruction_(
|
||||
// moved_entity_entry.should_set_in_use_by_wait_set_of_entity_to_false_on_destruction_
|
||||
// )
|
||||
// {
|
||||
// moved_entity_entry.should_set_in_use_by_wait_set_of_entity_to_false_on_destruction_ = false;
|
||||
// }
|
||||
|
||||
// ~WeakEntityEntryTemplate()
|
||||
// {
|
||||
// auto entity = weak_entity_.lock();
|
||||
// if (should_set_in_use_by_wait_set_of_entity_to_false_on_destruction_) {
|
||||
// EntityEntryTemplate<rclcpp::SubscriptionBase>::cleanup(entity, mask_);
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// See WeakEntityEntryTemplate::get_weak_entity().
|
||||
// std::weak_ptr<EntityT>
|
||||
// get_weak_entity() const
|
||||
// {
|
||||
// return weak_entity_;
|
||||
// }
|
||||
|
||||
// /// Return a const reference to the subscrption mask.
|
||||
// const rclcpp::SubscriptionWaitSetMask &
|
||||
// get_mask() const
|
||||
// {
|
||||
// return mask_;
|
||||
// }
|
||||
|
||||
// /// See WeakEntityEntryTemplate::lock().
|
||||
// std::shared_ptr<EntityT>
|
||||
// lock() const
|
||||
// {
|
||||
// return weak_entity_.lock();
|
||||
// }
|
||||
|
||||
// /// See WeakEntityEntryTemplate::expired().
|
||||
// bool
|
||||
// expired() const noexcept
|
||||
// {
|
||||
// return weak_entity_.expired();
|
||||
// }
|
||||
|
||||
// protected:
|
||||
// bool should_set_in_use_by_wait_set_of_entity_to_false_on_destruction_{false};
|
||||
|
||||
// };
|
||||
|
||||
// using SubscriptionEntry = EntityEntryTemplate<rclcpp::SubscriptionBase>;
|
||||
// using WeakSubscriptionEntry = WeakEntityEntryTemplate<rclcpp::SubscriptionBase>;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace wait_set_policies
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__WAIT_SET_POLICIES__DETAIL__SUBSCRIPTION_ENTRY_HPP_
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright 2021 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__WAIT_SET_POLICIES__DETAIL__TIMER_ENTRY_HPP_
|
||||
#define RCLCPP__WAIT_SET_POLICIES__DETAIL__TIMER_ENTRY_HPP_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/timer.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/entity_entry.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace wait_set_policies
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
using TimerEntry =
|
||||
// EntityEntryTemplate<rclcpp::TimerBase, std::shared_ptr<rclcpp::TimerBase>>;
|
||||
EntityEntryTemplate<rclcpp::TimerBase>;
|
||||
using WeakTimerEntry =
|
||||
// EntityEntryTemplate<rclcpp::TimerBase, std::weak_ptr<rclcpp::TimerBase>>;
|
||||
EntityEntryTemplate<rclcpp::TimerBase>;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace wait_set_policies
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__WAIT_SET_POLICIES__DETAIL__TIMER_ENTRY_HPP_
|
||||
@@ -1,183 +0,0 @@
|
||||
// Copyright 2021 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__WAIT_SET_POLICIES__DETAIL__WAITABLE_ENTRY_HPP_
|
||||
#define RCLCPP__WAIT_SET_POLICIES__DETAIL__WAITABLE_ENTRY_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/waitable.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/entity_entry.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace wait_set_policies
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// See rclcpp::wait_set_policies::detail::EntityEntryTemplate.
|
||||
template<>
|
||||
class EntityEntryTemplate<rclcpp::Waitable>
|
||||
{
|
||||
using EntityT = rclcpp::Waitable;
|
||||
|
||||
public:
|
||||
EntityEntryTemplate(
|
||||
std::shared_ptr<EntityT> entity_in = nullptr,
|
||||
std::shared_ptr<void> associated_entity_in = nullptr)
|
||||
: entity_(entity_in),
|
||||
associated_entity_(associated_entity_in)
|
||||
{}
|
||||
private:
|
||||
std::shared_ptr<EntityT> entity_;
|
||||
std::shared_ptr<void> associated_entity_;
|
||||
|
||||
friend ManagedEntityEntryTemplate<EntityT>;
|
||||
};
|
||||
|
||||
/// See rclcpp::wait_set_policies::detail::ManagedEntityEntryTemplate.
|
||||
template<>
|
||||
class ManagedEntityEntryTemplate<rclcpp::Waitable>
|
||||
{
|
||||
using EntityT = rclcpp::Waitable;
|
||||
|
||||
public:
|
||||
/// The only valid way to construct this is with an unmanaged entity entry.
|
||||
explicit ManagedEntityEntryTemplate(const EntityEntryTemplate<EntityT> & unmanaged_entity_entry)
|
||||
: entity_(unmanaged_entity_entry.entity_),
|
||||
associated_entity_(unmanaged_entity_entry.associated_entity_)
|
||||
{
|
||||
if (nullptr == entity_) {
|
||||
throw std::invalid_argument("entity cannot be nullptr for a managed entry");
|
||||
}
|
||||
bool already_in_use = entity_->exchange_in_use_by_wait_set_state(true);
|
||||
if (already_in_use) {
|
||||
throw rclcpp::wait_set_policies::AlreadyAssociatedWithWaitSetException(*entity_);
|
||||
}
|
||||
}
|
||||
|
||||
// ManagedEntityEntryTemplate(const ManagedEntityEntryTemplate<EntityT> & other)
|
||||
// {
|
||||
// if (other.should_set_in_use_by_wait_set_of_entity_to_false_on_destruction_) {
|
||||
// throw std::runtime_error("")
|
||||
// }
|
||||
// }
|
||||
|
||||
~ManagedEntityEntryTemplate()
|
||||
{
|
||||
if ((nullptr != entity_)) {
|
||||
bool was_in_use = entity_->exchange_in_use_by_wait_set_state(false);
|
||||
assert(was_in_use);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the interal entity shared pointer.
|
||||
std::shared_ptr<EntityT>
|
||||
get_entity() const
|
||||
{
|
||||
return entity_;
|
||||
}
|
||||
|
||||
/// Return the interal associated entity shared pointer.
|
||||
std::shared_ptr<void>
|
||||
get_associated_entity() const
|
||||
{
|
||||
return associated_entity_;
|
||||
}
|
||||
|
||||
/// Reset the entity.
|
||||
/**
|
||||
* Specializations of this class may reset more than one item.
|
||||
* Having this method in all instantiations of this class provides uniform access.
|
||||
*/
|
||||
// void
|
||||
// reset() noexcept
|
||||
// {
|
||||
// entity_.reset();
|
||||
// }
|
||||
|
||||
protected:
|
||||
std::shared_ptr<EntityT> entity_;
|
||||
std::shared_ptr<void> associated_entity_;
|
||||
|
||||
};
|
||||
|
||||
/// See rclcpp::wait_set_policies::detail::WeakManagedEntityEntryTemplate.
|
||||
template<>
|
||||
class WeakManagedEntityEntryTemplate<rclcpp::Waitable>
|
||||
{
|
||||
using EntityT = rclcpp::Waitable;
|
||||
|
||||
public:
|
||||
/// Can only be constructed from a moved ManagedEntityEntryTemplate.
|
||||
explicit WeakManagedEntityEntryTemplate(ManagedEntityEntryTemplate<EntityT> && moved_entity_entry)
|
||||
: weak_entity_(moved_entity_entry.get_entity()),
|
||||
weak_associated_entity_(moved_entity_entry.get_associated_entity())
|
||||
{}
|
||||
|
||||
~WeakManagedEntityEntryTemplate()
|
||||
{
|
||||
auto entity = weak_entity_.lock();
|
||||
if (nullptr != entity) {
|
||||
bool was_in_use = entity->exchange_in_use_by_wait_set_state(false);
|
||||
assert(was_in_use);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the interal entity weak pointer.
|
||||
std::weak_ptr<EntityT>
|
||||
get_weak_entity() const
|
||||
{
|
||||
return weak_entity_;
|
||||
}
|
||||
|
||||
// /// Lock the entity.
|
||||
// /**
|
||||
// * Specializations of this class may select from more than one item to lock.
|
||||
// * Having this method in all instantiations of this class provides uniform access.
|
||||
// */
|
||||
// std::shared_ptr<EntityT>
|
||||
// lock() const
|
||||
// {
|
||||
// return weak_entity_.lock();
|
||||
// }
|
||||
|
||||
// /// Return true if the entity has expired, otherwise false.
|
||||
// /**
|
||||
// * Specializations of this class may select from more than one item to check.
|
||||
// * Having this method in all instantiations of this class provides uniform access.
|
||||
// */
|
||||
// bool
|
||||
// expired() const noexcept
|
||||
// {
|
||||
// return weak_entity_.expired();
|
||||
// }
|
||||
private:
|
||||
std::weak_ptr<EntityT> weak_entity_;
|
||||
std::weak_ptr<void> weak_associated_entity_;
|
||||
|
||||
};
|
||||
|
||||
using WaitableEntry = EntityEntryTemplate<rclcpp::Waitable>;
|
||||
using ManagedWaitableEntry = ManagedEntityEntryTemplate<rclcpp::Waitable>;
|
||||
using WeakManagedWaitableEntry = WeakManagedEntityEntryTemplate<rclcpp::Waitable>;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace wait_set_policies
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__WAIT_SET_POLICIES__DETAIL__WAITABLE_ENTRY_HPP_
|
||||
@@ -28,13 +28,7 @@
|
||||
#include "rclcpp/subscription_wait_set_mask.hpp"
|
||||
#include "rclcpp/timer.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/client_entry.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/guard_condition_entry.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/service_entry.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/storage_policy_common.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/subscription_entry.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/timer_entry.hpp"
|
||||
#include "rclcpp/wait_set_policies/detail/waitable_entry.hpp"
|
||||
#include "rclcpp/waitable.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
@@ -48,27 +42,124 @@ class DynamicStorage : public rclcpp::wait_set_policies::detail::StoragePolicyCo
|
||||
protected:
|
||||
using is_mutable = std::true_type;
|
||||
|
||||
using WeakManagedSubscriptionEntry = detail::WeakManagedSubscriptionEntry;
|
||||
using SubscriptionEntry = detail::SubscriptionEntry;
|
||||
class SubscriptionEntry
|
||||
{
|
||||
// (wjwwood): indent of 'public:' is weird, I know. uncrustify is dumb.
|
||||
|
||||
using SequenceOfWeakSubscriptions = std::vector<WeakManagedSubscriptionEntry>;
|
||||
public:
|
||||
std::shared_ptr<rclcpp::SubscriptionBase> subscription;
|
||||
rclcpp::SubscriptionWaitSetMask mask;
|
||||
|
||||
/// Conversion constructor, which is intentionally not marked explicit.
|
||||
SubscriptionEntry(
|
||||
std::shared_ptr<rclcpp::SubscriptionBase> subscription_in = nullptr,
|
||||
const rclcpp::SubscriptionWaitSetMask & mask_in = {})
|
||||
: subscription(std::move(subscription_in)),
|
||||
mask(mask_in)
|
||||
{}
|
||||
|
||||
void
|
||||
reset() noexcept
|
||||
{
|
||||
subscription.reset();
|
||||
}
|
||||
};
|
||||
class WeakSubscriptionEntry
|
||||
{
|
||||
public:
|
||||
std::weak_ptr<rclcpp::SubscriptionBase> subscription;
|
||||
rclcpp::SubscriptionWaitSetMask mask;
|
||||
|
||||
explicit WeakSubscriptionEntry(
|
||||
const std::shared_ptr<rclcpp::SubscriptionBase> & subscription_in,
|
||||
const rclcpp::SubscriptionWaitSetMask & mask_in) noexcept
|
||||
: subscription(subscription_in),
|
||||
mask(mask_in)
|
||||
{}
|
||||
|
||||
explicit WeakSubscriptionEntry(const SubscriptionEntry & other)
|
||||
: subscription(other.subscription),
|
||||
mask(other.mask)
|
||||
{}
|
||||
|
||||
std::shared_ptr<rclcpp::SubscriptionBase>
|
||||
lock() const
|
||||
{
|
||||
return subscription.lock();
|
||||
}
|
||||
|
||||
bool
|
||||
expired() const noexcept
|
||||
{
|
||||
return subscription.expired();
|
||||
}
|
||||
};
|
||||
using SequenceOfWeakSubscriptions = std::vector<WeakSubscriptionEntry>;
|
||||
using SubscriptionsIterable = std::vector<SubscriptionEntry>;
|
||||
|
||||
using SequenceOfWeakGuardConditions = std::vector<detail::WeakGuardConditionEntry>;
|
||||
using GuardConditionsIterable = std::vector<detail::GuardConditionEntry>;
|
||||
using SequenceOfWeakGuardConditions = std::vector<std::weak_ptr<rclcpp::GuardCondition>>;
|
||||
using GuardConditionsIterable = std::vector<std::shared_ptr<rclcpp::GuardCondition>>;
|
||||
|
||||
using SequenceOfWeakTimers = std::vector<detail::WeakTimerEntry>;
|
||||
using TimersIterable = std::vector<detail::TimerEntry>;
|
||||
using SequenceOfWeakTimers = std::vector<std::weak_ptr<rclcpp::TimerBase>>;
|
||||
using TimersIterable = std::vector<std::shared_ptr<rclcpp::TimerBase>>;
|
||||
|
||||
using SequenceOfWeakClients = std::vector<detail::WeakClientEntry>;
|
||||
using ClientsIterable = std::vector<detail::ClientEntry>;
|
||||
using SequenceOfWeakClients = std::vector<std::weak_ptr<rclcpp::ClientBase>>;
|
||||
using ClientsIterable = std::vector<std::shared_ptr<rclcpp::ClientBase>>;
|
||||
|
||||
using SequenceOfWeakServices = std::vector<detail::WeakServiceEntry>;
|
||||
using ServicesIterable = std::vector<detail::ServiceEntry>;
|
||||
using SequenceOfWeakServices = std::vector<std::weak_ptr<rclcpp::ServiceBase>>;
|
||||
using ServicesIterable = std::vector<std::shared_ptr<rclcpp::ServiceBase>>;
|
||||
|
||||
using WeakWaitableEntry = detail::WeakWaitableEntry;
|
||||
using WaitableEntry = detail::WaitableEntry;
|
||||
class WaitableEntry
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<rclcpp::Waitable> waitable;
|
||||
std::shared_ptr<void> associated_entity;
|
||||
|
||||
/// Conversion constructor, which is intentionally not marked explicit.
|
||||
WaitableEntry(
|
||||
std::shared_ptr<rclcpp::Waitable> waitable_in = nullptr,
|
||||
std::shared_ptr<void> associated_entity_in = nullptr) noexcept
|
||||
: waitable(std::move(waitable_in)),
|
||||
associated_entity(std::move(associated_entity_in))
|
||||
{}
|
||||
|
||||
void
|
||||
reset() noexcept
|
||||
{
|
||||
waitable.reset();
|
||||
associated_entity.reset();
|
||||
}
|
||||
};
|
||||
class WeakWaitableEntry
|
||||
{
|
||||
public:
|
||||
std::weak_ptr<rclcpp::Waitable> waitable;
|
||||
std::weak_ptr<void> associated_entity;
|
||||
|
||||
explicit WeakWaitableEntry(
|
||||
const std::shared_ptr<rclcpp::Waitable> & waitable_in,
|
||||
const std::shared_ptr<void> & associated_entity_in) noexcept
|
||||
: waitable(waitable_in),
|
||||
associated_entity(associated_entity_in)
|
||||
{}
|
||||
|
||||
explicit WeakWaitableEntry(const WaitableEntry & other)
|
||||
: waitable(other.waitable),
|
||||
associated_entity(other.associated_entity)
|
||||
{}
|
||||
|
||||
std::shared_ptr<rclcpp::Waitable>
|
||||
lock() const
|
||||
{
|
||||
return waitable.lock();
|
||||
}
|
||||
|
||||
bool
|
||||
expired() const noexcept
|
||||
{
|
||||
return waitable.expired();
|
||||
}
|
||||
};
|
||||
using SequenceOfWeakWaitables = std::vector<WeakWaitableEntry>;
|
||||
using WaitablesIterable = std::vector<WaitableEntry>;
|
||||
|
||||
@@ -93,9 +184,8 @@ protected:
|
||||
services,
|
||||
waitables,
|
||||
context),
|
||||
// subscriptions_ is populated in the constructor dynamically, in order
|
||||
// to respect the mask.
|
||||
// shared_subscriptions_ is resized based on the result of subscriptions_.
|
||||
subscriptions_(subscriptions.cbegin(), subscriptions.cend()),
|
||||
shared_subscriptions_(subscriptions_.size()),
|
||||
guard_conditions_(guard_conditions.cbegin(), guard_conditions.cend()),
|
||||
shared_guard_conditions_(guard_conditions_.size()),
|
||||
timers_(timers.cbegin(), timers.cend()),
|
||||
@@ -104,39 +194,9 @@ protected:
|
||||
shared_clients_(clients_.size()),
|
||||
services_(services.cbegin(), services.cend()),
|
||||
shared_services_(services_.size()),
|
||||
waitables_(waitables.cbegin(), waitables.cend())
|
||||
// shared_waitables_ is resized based on the result of waitables_ after
|
||||
// waitables from subscriptions are added, if any.
|
||||
{
|
||||
// Ensure subscriptions are not being used by other wait sets and extract
|
||||
// their waitables, if they have them.
|
||||
std::vector<WaitableEntry> waitables_from_subscriptions;
|
||||
for (auto & subscription_entry : subscriptions) {
|
||||
std::vector<WaitableEntry> local_waitables_from_subscriptions = subscription_entry.manage();
|
||||
if (subscription_entry.get_mask().include_subscription) {
|
||||
subscriptions_.push_back(subscription_entry);
|
||||
}
|
||||
}
|
||||
// Add subscription entries from subscriptions, if the subscription mask indicates.
|
||||
std::copy_if(
|
||||
subscriptions.cbegin(),
|
||||
subscriptions.cend(),
|
||||
std::back_inserter(subscriptions_),
|
||||
[](const auto & subscription_entry) {
|
||||
return subscription_entry.mask.include_subscription;
|
||||
}
|
||||
);
|
||||
shared_subscriptions_.resize(subscriptions_.size());
|
||||
// Add waitables from subscriptions, if the subscription mask indicates.
|
||||
for (const auto & subscription_entry : subscriptions) {
|
||||
if (subscription_entry.mask.include_events) {
|
||||
for (const auto & event : subscription_entry.subscription->get_event_handlers()) {
|
||||
waitables_.push_back({event, subscription_entry.subscription});
|
||||
}
|
||||
}
|
||||
}
|
||||
shared_waitables_.resize(waitables_.size());
|
||||
}
|
||||
waitables_(waitables.cbegin(), waitables.cend()),
|
||||
shared_waitables_(waitables_.size())
|
||||
{}
|
||||
|
||||
~DynamicStorage() = default;
|
||||
|
||||
@@ -183,7 +243,7 @@ protected:
|
||||
if (this->storage_has_entity(*subscription, subscriptions_)) {
|
||||
throw std::runtime_error("subscription already in wait set");
|
||||
}
|
||||
WeakManagedSubscriptionEntry weak_entry{std::move(subscription), {}};
|
||||
WeakSubscriptionEntry weak_entry{std::move(subscription), {}};
|
||||
subscriptions_.push_back(std::move(weak_entry));
|
||||
this->storage_flag_for_resize();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define RCLCPP__WAITABLE_HPP_
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
@@ -126,17 +125,8 @@ public:
|
||||
bool
|
||||
is_ready(rcl_wait_set_t * wait_set) = 0;
|
||||
|
||||
/// Take the data so that it can be consumed with `execute`.
|
||||
/// Execute any entities of the Waitable that are ready.
|
||||
/**
|
||||
* NOTE: take_data is a partial fix to a larger design issue with the
|
||||
* multithreaded executor. This method is likely to be removed when
|
||||
* a more permanent fix is implemented. A longterm fix is currently
|
||||
* being discussed here: https://github.com/ros2/rclcpp/pull/1276
|
||||
*
|
||||
* This method takes the data from the underlying data structure and
|
||||
* writes it to the void shared pointer `data` that is passed into the
|
||||
* method. The `data` can then be executed with the `execute` method.
|
||||
*
|
||||
* Before calling this method, the Waitable should be added to a wait set,
|
||||
* waited on, and then updated.
|
||||
*
|
||||
@@ -153,41 +143,13 @@ public:
|
||||
* // Update the Waitable
|
||||
* waitable.update(wait_set);
|
||||
* // Execute any entities of the Waitable that may be ready
|
||||
* std::shared_ptr<void> data = waitable.take_data();
|
||||
* ```
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::shared_ptr<void>
|
||||
take_data() = 0;
|
||||
|
||||
/// Execute data that is passed in.
|
||||
/**
|
||||
* Before calling this method, the Waitable should be added to a wait set,
|
||||
* waited on, and then updated - and the `take_data` method should be
|
||||
* called.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* ```cpp
|
||||
* // ... create a wait set and a Waitable
|
||||
* // Add the Waitable to the wait set
|
||||
* bool add_ret = waitable.add_to_wait_set(wait_set);
|
||||
* // ... error handling
|
||||
* // Wait
|
||||
* rcl_ret_t wait_ret = rcl_wait(wait_set);
|
||||
* // ... error handling
|
||||
* // Update the Waitable
|
||||
* waitable.update(wait_set);
|
||||
* // Execute any entities of the Waitable that may be ready
|
||||
* std::shared_ptr<void> data = waitable.take_data();
|
||||
* waitable.execute(data);
|
||||
* waitable.execute();
|
||||
* ```
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
execute(std::shared_ptr<void> & data) = 0;
|
||||
execute() = 0;
|
||||
|
||||
/// Exchange the "in use by wait set" state for this timer.
|
||||
/**
|
||||
|
||||
@@ -2,24 +2,19 @@
|
||||
<?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>11.0.0</version>
|
||||
<version>2.4.2</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
<maintainer email="mabel@openrobotics.org">Mabel Zhang</maintainer>
|
||||
<maintainer email="william@openrobotics.org">William Woodall</maintainer>
|
||||
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
<author email="dthomas@openrobotics.org">Dirk Thomas</author>
|
||||
|
||||
<buildtool_depend>ament_cmake_ros</buildtool_depend>
|
||||
|
||||
<build_depend>ament_index_cpp</build_depend>
|
||||
<build_depend>builtin_interfaces</build_depend>
|
||||
<build_depend>rcl_interfaces</build_depend>
|
||||
<build_depend>rosgraph_msgs</build_depend>
|
||||
<build_depend>rosidl_runtime_cpp</build_depend>
|
||||
<build_depend>rosidl_typesupport_c</build_depend>
|
||||
<build_depend>rosidl_typesupport_cpp</build_depend>
|
||||
<build_export_depend>ament_index_cpp</build_export_depend>
|
||||
<build_export_depend>builtin_interfaces</build_export_depend>
|
||||
<build_export_depend>rcl_interfaces</build_export_depend>
|
||||
<build_export_depend>rosgraph_msgs</build_export_depend>
|
||||
@@ -37,6 +32,7 @@
|
||||
<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_lint_auto</test_depend>
|
||||
<test_depend>ament_lint_common</test_depend>
|
||||
|
||||
@@ -149,11 +149,12 @@ def get_rclcpp_suffix_from_features(features):
|
||||
@[ if params]@
|
||||
@(''.join([' ' + p + ', \\\n' for p in params if p != stream_arg]))@
|
||||
@[ end if]@
|
||||
logger.get_name(), \
|
||||
(logger).get_name(), \
|
||||
@[ if 'stream' not in feature_combination]@
|
||||
__VA_ARGS__); \
|
||||
rclcpp::get_c_string(RCLCPP_FIRST_ARG(__VA_ARGS__, "")), \
|
||||
RCLCPP_ALL_BUT_FIRST_ARGS(__VA_ARGS__,"")); \
|
||||
@[ else]@
|
||||
"%s", ss.str().c_str()); \
|
||||
"%s", rclcpp::get_c_string(ss.str())); \
|
||||
@[ end if]@
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -19,12 +19,8 @@
|
||||
using rclcpp::CallbackGroup;
|
||||
using rclcpp::CallbackGroupType;
|
||||
|
||||
CallbackGroup::CallbackGroup(
|
||||
CallbackGroupType group_type,
|
||||
bool automatically_add_to_executor_with_node)
|
||||
: type_(group_type), associated_with_executor_(false),
|
||||
can_be_taken_from_(true),
|
||||
automatically_add_to_executor_with_node_(automatically_add_to_executor_with_node)
|
||||
CallbackGroup::CallbackGroup(CallbackGroupType group_type)
|
||||
: type_(group_type), can_be_taken_from_(true)
|
||||
{}
|
||||
|
||||
|
||||
@@ -40,18 +36,6 @@ CallbackGroup::type() const
|
||||
return type_;
|
||||
}
|
||||
|
||||
std::atomic_bool &
|
||||
CallbackGroup::get_associated_with_executor_atomic()
|
||||
{
|
||||
return associated_with_executor_;
|
||||
}
|
||||
|
||||
bool
|
||||
CallbackGroup::automatically_add_to_executor_with_node() const
|
||||
{
|
||||
return automatically_add_to_executor_with_node_;
|
||||
}
|
||||
|
||||
void
|
||||
CallbackGroup::add_subscription(
|
||||
const rclcpp::SubscriptionBase::SharedPtr subscription_ptr)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user