Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
403aac9662 | ||
|
|
e8cf066d7d | ||
|
|
c4c39a2069 | ||
|
|
b3ecbd5ff7 | ||
|
|
052936980e | ||
|
|
6e133c2ad7 | ||
|
|
1f0f8f6176 | ||
|
|
ab2484295a | ||
|
|
c214ddc57b | ||
|
|
d27ca8ee85 | ||
|
|
342f225053 | ||
|
|
3c198de5b2 | ||
|
|
8906c9eb7f | ||
|
|
9e98aa70d3 | ||
|
|
6471043a0b | ||
|
|
f8bba370dc | ||
|
|
d5040ae304 | ||
|
|
3e5b6a47ea | ||
|
|
8c3fbce10d | ||
|
|
fb6ab9ef70 | ||
|
|
7629f5b6d9 | ||
|
|
7cb2ececcb | ||
|
|
0f4fc08a93 | ||
|
|
82f6dfa6de | ||
|
|
fadd923aa0 | ||
|
|
f954ce5145 | ||
|
|
895145cfc9 | ||
|
|
3cdb3cb1bf | ||
|
|
5d5d3ce09d | ||
|
|
839ad201ac | ||
|
|
f3b0aa170c | ||
|
|
6e76503d9a | ||
|
|
b4629bf889 | ||
|
|
3f31ad0f55 | ||
|
|
25eeffdfcc | ||
|
|
3293603396 | ||
|
|
50ec1e568a | ||
|
|
607e290732 | ||
|
|
47ce42bc3f | ||
|
|
d2f052ee3d | ||
|
|
b86127d721 | ||
|
|
5cb6a6eeb5 | ||
|
|
f41e33c2a7 | ||
|
|
10c34ee9e5 | ||
|
|
6d3cbd39d1 | ||
|
|
bfee90ab7a | ||
|
|
1927f7e40e | ||
|
|
f73d80e79c | ||
|
|
e2e35570d5 | ||
|
|
5c395d6651 |
17
README.md
17
README.md
@@ -1,17 +0,0 @@
|
||||
# rclcpp
|
||||
|
||||
This repository contains the source code for the ROS Client Library for C++ package, included with a standard install of any ROS 2 distro.
|
||||
|
||||
rclcpp provides the standard C++ API for interacting with ROS 2.
|
||||
|
||||
## Usage
|
||||
|
||||
`#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/galactic/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/galactic/Tutorials/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html).
|
||||
and [Writing a simple service and client](https://docs.ros.org/en/galactic/Tutorials/Writing-A-Simple-Cpp-Service-And-Client.html)
|
||||
contain some examples of rclcpp APIs in use.
|
||||
@@ -2,521 +2,70 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
9.2.2 (2022-12-06)
|
||||
------------------
|
||||
* Fix returning invalid namespace if sub_namespace is empty (`#1810 <https://github.com/ros2/rclcpp/issues/1810>`_)
|
||||
* use regex for wildcard matching (`#1987 <https://github.com/ros2/rclcpp/issues/1987>`_)
|
||||
* Add statistics for handle_loaned_message (`#1933 <https://github.com/ros2/rclcpp/issues/1933>`_)
|
||||
* Contributors: Aaron Lipinski, Barry Xu, Chen Lihui, M. Hofstätter
|
||||
0.7.16 (2021-05-21)
|
||||
-------------------
|
||||
* Fix documented example in create_publisher. (`#1558 <https://github.com/ros2/rclcpp/issues/1558>`_) (`#1560 <https://github.com/ros2/rclcpp/issues/1560>`_)
|
||||
* Fix NodeOptions copy constructor. (`#1376 <https://github.com/ros2/rclcpp/issues/1376>`_) (`#1466 <https://github.com/ros2/rclcpp/issues/1466>`_)
|
||||
* Contributors: Ivan Santiago Paunovic, Jacob Perron
|
||||
|
||||
9.2.1 (2022-04-28)
|
||||
------------------
|
||||
* Add test-dep ament_cmake_google_benchmark (`#1904 <https://github.com/ros2/rclcpp/issues/1904>`_) (`#1909 <https://github.com/ros2/rclcpp/issues/1909>`_)
|
||||
* Use parantheses around logging macro parameter (`#1820 <https://github.com/ros2/rclcpp/issues/1820>`_) (`#1822 <https://github.com/ros2/rclcpp/issues/1822>`_)
|
||||
* Contributors: mergify[bot]
|
||||
0.7.15 (2020-11-24)
|
||||
-------------------
|
||||
* Fix implementation of NodeOptions::use_global_arguments(). (`#1176 <https://github.com/ros2/rclcpp/issues/1176>`_) (`#1206 <https://github.com/ros2/rclcpp/issues/1206>`_)
|
||||
* Fix conversion of negative durations to messages. (`#1188 <https://github.com/ros2/rclcpp/issues/1188>`_) (`#1207 <https://github.com/ros2/rclcpp/issues/1207>`_)
|
||||
* Type conversions fixes. (`#901 <https://github.com/ros2/rclcpp/issues/901>`_) (`#1209 <https://github.com/ros2/rclcpp/issues/1209>`_)
|
||||
* Add operator!= for duration (`#1236 <https://github.com/ros2/rclcpp/issues/1236>`_) (`#1277 <https://github.com/ros2/rclcpp/issues/1277>`_)
|
||||
* Contributors: Ivan Santiago Paunovic, Michel Hidalgo, Monika Idzik
|
||||
|
||||
9.2.0 (2021-09-17)
|
||||
------------------
|
||||
* Added thread safe for_each_callback_group method (`#1741 <https://github.com/ros2/rclcpp/issues/1741>`_)
|
||||
* Added a function rclcpp::wait_for_message() convenience function (`#1705 <https://github.com/ros2/rclcpp/issues/1705>`_) (`#1740 <https://github.com/ros2/rclcpp/issues/1740>`_)
|
||||
* Fixed a documentation bug (`#1719 <https://github.com/ros2/rclcpp/issues/1719>`_) (`#1720 <https://github.com/ros2/rclcpp/issues/1720>`_)
|
||||
* Contributors: Aditya Pande, Karsten Knese, mergify[bot]
|
||||
0.7.14 (2020-07-10)
|
||||
-------------------
|
||||
* Fixed doxygen warnings. (`#1208 <https://github.com/ros2/rclcpp/issues/1208>`_)
|
||||
* Check if context is valid when looping in spin_some. (`#1167 <https://github.com/ros2/rclcpp/issues/1167>`_)
|
||||
* Fix spin_until_future_complete: check spinning value. (`#1023 <https://github.com/ros2/rclcpp/issues/1023>`_)
|
||||
* Fix exception on rcl_clock_init. (`#1195 <https://github.com/ros2/rclcpp/issues/1195>`_)
|
||||
* Fix lock-order-inversion (potential deadlock). (`#1138 <https://github.com/ros2/rclcpp/issues/1138>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, DongheeYe, Ivan Santiago Paunovic, tomoya
|
||||
|
||||
9.1.0 (2021-05-20)
|
||||
------------------
|
||||
* Allow declaring uninitialized statically typed parameters. (`#1673 <https://github.com/ros2/rclcpp/issues/1673>`_) (`#1681 <https://github.com/ros2/rclcpp/issues/1681>`_)
|
||||
* [service] Don't use a weak_ptr to avoid leaking. (`#1668 <https://github.com/ros2/rclcpp/issues/1668>`_) (`#1670 <https://github.com/ros2/rclcpp/issues/1670>`_)
|
||||
* Contributors: Jacob Perron, Ivan Santiago Paunovic
|
||||
0.7.13 (2020-03-12)
|
||||
-------------------
|
||||
* Don't specify calling convention in std::_Binder template. (`#1015 <https://github.com/ros2/rclcpp/issues/1015>`_)
|
||||
* Contributors: Jacob Perron, Sean Kelly
|
||||
|
||||
9.0.3 (2021-05-10)
|
||||
------------------
|
||||
* Use OnShutdown callback handle instead of OnShutdown callback (`#1639 <https://github.com/ros2/rclcpp/issues/1639>`_) (`#1650 <https://github.com/ros2/rclcpp/issues/1650>`_)
|
||||
* use dynamic_pointer_cast to detect allocator mismatch in intra process manager (`#1643 <https://github.com/ros2/rclcpp/issues/1643>`_) (`#1644 <https://github.com/ros2/rclcpp/issues/1644>`_)
|
||||
* 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: Barry Xu, Jacob Perron, Michel Hidalgo, Shane Loretz, William Woodall
|
||||
0.7.12 (2019-12-05)
|
||||
-------------------
|
||||
|
||||
9.0.2 (2021-04-14)
|
||||
------------------
|
||||
* 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
|
||||
0.7.11 (2019-10-11)
|
||||
-------------------
|
||||
* Fix `get_node_*_interface` functions taking a pointer (`#870 <https://github.com/ros2/rclcpp/pull/870>`_).
|
||||
* Fix hang with timers in `MultiThreadedExecutor` (`#869 <https://github.com/ros2/rclcpp/pull/869>`_).
|
||||
* Contributors: Todd Malsbary, ivanpauno
|
||||
|
||||
9.0.1 (2021-04-12)
|
||||
------------------
|
||||
* 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
|
||||
0.7.10 (2019-09-23)
|
||||
-------------------
|
||||
|
||||
9.0.0 (2021-04-06)
|
||||
0.7.9 (2019-09-20)
|
||||
------------------
|
||||
* 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
|
||||
* add mutex in add/remove_node and wait_for_work to protect concurrent use/change of memory_strategy\_ (`#837 <https://github.com/ros2/rclcpp/issues/837>`_) (`#857 <https://github.com/ros2/rclcpp/issues/857>`_)
|
||||
* Contributors: Zachary Michaels
|
||||
|
||||
8.2.0 (2021-03-31)
|
||||
------------------
|
||||
* 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
|
||||
|
||||
8.1.0 (2021-03-25)
|
||||
------------------
|
||||
* 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>`_)
|
||||
* 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>`_)
|
||||
* 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>`_)
|
||||
* 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>`_)
|
||||
* 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>`_)
|
||||
* 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 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 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>`_)
|
||||
* 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>`_)
|
||||
* 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>`_)
|
||||
* 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)
|
||||
------------------
|
||||
* 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>`_)
|
||||
* 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
|
||||
|
||||
2.0.0 (2020-06-01)
|
||||
------------------
|
||||
* Added missing virtual destructors. (`#1149 <https://github.com/ros2/rclcpp/issues/1149>`_)
|
||||
* Fixed a test which was using different types on the same topic. (`#1150 <https://github.com/ros2/rclcpp/issues/1150>`_)
|
||||
* Made ``test_rate`` more reliable on Windows and improve error output when it fails (`#1146 <https://github.com/ros2/rclcpp/issues/1146>`_)
|
||||
* Added Security Vulnerability Policy pointing to REP-2006. (`#1130 <https://github.com/ros2/rclcpp/issues/1130>`_)
|
||||
* Added missing header in ``logging_mutex.cpp``. (`#1145 <https://github.com/ros2/rclcpp/issues/1145>`_)
|
||||
* Changed the WaitSet API to pass a shared pointer by value instead than by const reference when possible. (`#1141 <https://github.com/ros2/rclcpp/issues/1141>`_)
|
||||
* Changed ``SubscriptionBase::get_subscription_handle() const`` to return a shared pointer to const value. (`#1140 <https://github.com/ros2/rclcpp/issues/1140>`_)
|
||||
* Extended the lifetime of ``rcl_publisher_t`` by holding onto the shared pointer in order to avoid a use after free situation. (`#1119 <https://github.com/ros2/rclcpp/issues/1119>`_)
|
||||
* Improved some docblocks (`#1127 <https://github.com/ros2/rclcpp/issues/1127>`_)
|
||||
* Fixed a lock-order-inversion (potential deadlock) (`#1135 <https://github.com/ros2/rclcpp/issues/1135>`_)
|
||||
* Fixed a potential Construction/Destruction order problem between global contexts vector and Context of static lifetime (`#1132 <https://github.com/ros2/rclcpp/issues/1132>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Chris Lalancette, Ivan Santiago Paunovic, Michel Hidalgo, tomoya
|
||||
|
||||
1.1.0 (2020-05-26)
|
||||
------------------
|
||||
* Deprecate set_on_parameters_set_callback (`#1123 <https://github.com/ros2/rclcpp/issues/1123>`_)
|
||||
* Expose get_service_names_and_types_by_node from rcl in rclcpp (`#1131 <https://github.com/ros2/rclcpp/issues/1131>`_)
|
||||
* Fix thread safety issues related to logging (`#1125 <https://github.com/ros2/rclcpp/issues/1125>`_)
|
||||
* Make sure rmw_publisher_options is initialized in to_rcl_publisher_options (`#1099 <https://github.com/ros2/rclcpp/issues/1099>`_)
|
||||
* Remove empty lines within method signatures (`#1128 <https://github.com/ros2/rclcpp/issues/1128>`_)
|
||||
* Add API review March 2020 document (`#1031 <https://github.com/ros2/rclcpp/issues/1031>`_)
|
||||
* Improve documentation (`#1106 <https://github.com/ros2/rclcpp/issues/1106>`_)
|
||||
* Make test multi threaded executor more reliable (`#1105 <https://github.com/ros2/rclcpp/issues/1105>`_)
|
||||
* Fixed rep links and added more details to dependencies in quality declaration (`#1116 <https://github.com/ros2/rclcpp/issues/1116>`_)
|
||||
* Update quality declarations to reflect version 1.0 (`#1115 <https://github.com/ros2/rclcpp/issues/1115>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, ChenYing Kuo, Claire Wang, Dirk Thomas, Ivan Santiago Paunovic, William Woodall, Stephen Brawner
|
||||
|
||||
1.0.0 (2020-05-12)
|
||||
------------------
|
||||
* Remove MANUAL_BY_NODE liveliness API (`#1107 <https://github.com/ros2/rclcpp/issues/1107>`_)
|
||||
* Use rosidl_default_generators dependency in test (`#1114 <https://github.com/ros2/rclcpp/issues/1114>`_)
|
||||
* Make sure to include what you use (`#1112 <https://github.com/ros2/rclcpp/issues/1112>`_)
|
||||
* Mark flaky test with xfail: TestMultiThreadedExecutor (`#1109 <https://github.com/ros2/rclcpp/issues/1109>`_)
|
||||
* Contributors: Chris Lalancette, Ivan Santiago Paunovic, Karsten Knese, Louise Poubel
|
||||
|
||||
0.9.1 (2020-05-08)
|
||||
------------------
|
||||
* Fix tests that were not properly torn down (`#1073 <https://github.com/ros2/rclcpp/issues/1073>`_)
|
||||
* Added docblock in rclcpp (`#1103 <https://github.com/ros2/rclcpp/issues/1103>`_)
|
||||
* Added Quality declaration: rclcpp, rclpp_action, rclcpp_components andrclcpp_lifecycle (`#1100 <https://github.com/ros2/rclcpp/issues/1100>`_)
|
||||
* Use RCL_RET_SERVICE_TAKE_FAILED and not RCL_RET_CLIENT_TAKE_FAILED when checking a request take (`#1101 <https://github.com/ros2/rclcpp/issues/1101>`_)
|
||||
* Update comment about return value in Executor::get_next_ready_executable (`#1085 <https://github.com/ros2/rclcpp/issues/1085>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Christophe Bedard, Devin Bonnie, Ivan Santiago Paunovic
|
||||
|
||||
0.9.0 (2020-04-29)
|
||||
------------------
|
||||
* Serialized message move constructor (`#1097 <https://github.com/ros2/rclcpp/issues/1097>`_)
|
||||
* Enforce a precedence for wildcard matching in parameter overrides. (`#1094 <https://github.com/ros2/rclcpp/issues/1094>`_)
|
||||
* Add serialized_message.hpp header (`#1095 <https://github.com/ros2/rclcpp/issues/1095>`_)
|
||||
* Add received message age metric to topic statistics (`#1080 <https://github.com/ros2/rclcpp/issues/1080>`_)
|
||||
* Deprecate redundant namespaces (`#1083 <https://github.com/ros2/rclcpp/issues/1083>`_)
|
||||
* Export targets in addition to include directories / libraries (`#1088 <https://github.com/ros2/rclcpp/issues/1088>`_)
|
||||
* Ensure logging is initialized just once (`#998 <https://github.com/ros2/rclcpp/issues/998>`_)
|
||||
* Adapt subscription traits to rclcpp::SerializedMessage (`#1092 <https://github.com/ros2/rclcpp/issues/1092>`_)
|
||||
* Protect subscriber_statistics_collectors\_ with a mutex (`#1084 <https://github.com/ros2/rclcpp/issues/1084>`_)
|
||||
* Remove unused test variable (`#1087 <https://github.com/ros2/rclcpp/issues/1087>`_)
|
||||
* Use serialized message (`#1081 <https://github.com/ros2/rclcpp/issues/1081>`_)
|
||||
* Integrate topic statistics (`#1072 <https://github.com/ros2/rclcpp/issues/1072>`_)
|
||||
* Fix rclcpp interface traits test (`#1086 <https://github.com/ros2/rclcpp/issues/1086>`_)
|
||||
* Generate node interfaces' getters and traits (`#1069 <https://github.com/ros2/rclcpp/issues/1069>`_)
|
||||
* Use composition for serialized message (`#1082 <https://github.com/ros2/rclcpp/issues/1082>`_)
|
||||
* Dnae adas/serialized message (`#1075 <https://github.com/ros2/rclcpp/issues/1075>`_)
|
||||
* Reflect changes in rclcpp API (`#1079 <https://github.com/ros2/rclcpp/issues/1079>`_)
|
||||
* Fix build regression (`#1078 <https://github.com/ros2/rclcpp/issues/1078>`_)
|
||||
* Add NodeDefault option for enabling topic statistics (`#1074 <https://github.com/ros2/rclcpp/issues/1074>`_)
|
||||
* Topic Statistics: Add SubscriptionTopicStatistics class (`#1050 <https://github.com/ros2/rclcpp/issues/1050>`_)
|
||||
* Add SubscriptionOptions for topic statistics (`#1057 <https://github.com/ros2/rclcpp/issues/1057>`_)
|
||||
* Remove warning message from failing to register default callback (`#1067 <https://github.com/ros2/rclcpp/issues/1067>`_)
|
||||
* Create a default warning for qos incompatibility (`#1051 <https://github.com/ros2/rclcpp/issues/1051>`_)
|
||||
* Add WaitSet class and modify entities to work without executor (`#1047 <https://github.com/ros2/rclcpp/issues/1047>`_)
|
||||
* Include what you use (`#1059 <https://github.com/ros2/rclcpp/issues/1059>`_)
|
||||
* Rename rosidl_generator_cpp namespace to rosidl_runtime_cpp (`#1060 <https://github.com/ros2/rclcpp/issues/1060>`_)
|
||||
* Changed rosidl_generator_c/cpp to rosidl_runtime_c/cpp (`#1014 <https://github.com/ros2/rclcpp/issues/1014>`_)
|
||||
* Use constexpr for endpoint type name (`#1055 <https://github.com/ros2/rclcpp/issues/1055>`_)
|
||||
* Add InvalidParameterTypeException (`#1027 <https://github.com/ros2/rclcpp/issues/1027>`_)
|
||||
* Support for ON_REQUESTED_INCOMPATIBLE_QOS and ON_OFFERED_INCOMPATIBLE_QOS events (`#924 <https://github.com/ros2/rclcpp/issues/924>`_)
|
||||
* Fixup clang warning (`#1040 <https://github.com/ros2/rclcpp/issues/1040>`_)
|
||||
* Adding a "static" single threaded executor (`#1034 <https://github.com/ros2/rclcpp/issues/1034>`_)
|
||||
* Add equality operators for QoS profile (`#1032 <https://github.com/ros2/rclcpp/issues/1032>`_)
|
||||
* Remove extra vertical whitespace (`#1030 <https://github.com/ros2/rclcpp/issues/1030>`_)
|
||||
* Switch IntraProcessMessage to test_msgs/Empty (`#1017 <https://github.com/ros2/rclcpp/issues/1017>`_)
|
||||
* Add new type of exception that may be thrown during creation of publisher/subscription (`#1026 <https://github.com/ros2/rclcpp/issues/1026>`_)
|
||||
* Don't check lifespan on publisher QoS (`#1002 <https://github.com/ros2/rclcpp/issues/1002>`_)
|
||||
* Fix get_parameter_tyeps of AsyncPrameterClient results are always empty (`#1019 <https://github.com/ros2/rclcpp/issues/1019>`_)
|
||||
* Cleanup node interfaces includes (`#1016 <https://github.com/ros2/rclcpp/issues/1016>`_)
|
||||
* Add ifdefs to remove tracing-related calls if tracing is disabled (`#1001 <https://github.com/ros2/rclcpp/issues/1001>`_)
|
||||
* Include missing header in node_graph.cpp (`#994 <https://github.com/ros2/rclcpp/issues/994>`_)
|
||||
* Add missing includes of logging.hpp (`#995 <https://github.com/ros2/rclcpp/issues/995>`_)
|
||||
* Zero initialize publisher GID in subscription intra process callback (`#1011 <https://github.com/ros2/rclcpp/issues/1011>`_)
|
||||
* Removed ament_cmake dependency (`#989 <https://github.com/ros2/rclcpp/issues/989>`_)
|
||||
* Switch to using new rcutils_strerror (`#993 <https://github.com/ros2/rclcpp/issues/993>`_)
|
||||
* Ensure all rclcpp::Clock accesses are thread-safe
|
||||
* Use a PIMPL for rclcpp::Clock implementation
|
||||
* Replace rmw_implementation for rmw dependency in package.xml (`#990 <https://github.com/ros2/rclcpp/issues/990>`_)
|
||||
* Add missing service callback registration tracepoint (`#986 <https://github.com/ros2/rclcpp/issues/986>`_)
|
||||
* Rename rmw_topic_endpoint_info_array count to size (`#996 <https://github.com/ros2/rclcpp/issues/996>`_)
|
||||
* Implement functions to get publisher and subcription informations like QoS policies from topic name (`#960 <https://github.com/ros2/rclcpp/issues/960>`_)
|
||||
* Code style only: wrap after open parenthesis if not in one line (`#977 <https://github.com/ros2/rclcpp/issues/977>`_)
|
||||
* Accept taking an rvalue ref future in spin_until_future_complete (`#971 <https://github.com/ros2/rclcpp/issues/971>`_)
|
||||
* Allow node clock use in logging macros (`#969 <https://github.com/ros2/rclcpp/issues/969>`_) (`#970 <https://github.com/ros2/rclcpp/issues/970>`_)
|
||||
* Change order of deprecated and visibility attributes (`#968 <https://github.com/ros2/rclcpp/issues/968>`_)
|
||||
* Deprecated is_initialized() (`#967 <https://github.com/ros2/rclcpp/issues/967>`_)
|
||||
* Don't specify calling convention in std::_Binder template (`#952 <https://github.com/ros2/rclcpp/issues/952>`_)
|
||||
* Added missing include to logging.hpp (`#964 <https://github.com/ros2/rclcpp/issues/964>`_)
|
||||
* Assigning make_shared result to variables in test (`#963 <https://github.com/ros2/rclcpp/issues/963>`_)
|
||||
* Fix unused parameter warning (`#962 <https://github.com/ros2/rclcpp/issues/962>`_)
|
||||
* Stop retaining ownership of the rcl context in GraphListener (`#946 <https://github.com/ros2/rclcpp/issues/946>`_)
|
||||
* Clear sub contexts when starting another init-shutdown cycle (`#947 <https://github.com/ros2/rclcpp/issues/947>`_)
|
||||
* Avoid possible UB in Clock jump callbacks (`#954 <https://github.com/ros2/rclcpp/issues/954>`_)
|
||||
* Handle unknown global ROS arguments (`#951 <https://github.com/ros2/rclcpp/issues/951>`_)
|
||||
* Mark get_clock() as override to fix clang warnings (`#939 <https://github.com/ros2/rclcpp/issues/939>`_)
|
||||
* Create node clock calls const (try 2) (`#922 <https://github.com/ros2/rclcpp/issues/922>`_)
|
||||
* Fix asserts on shared_ptr::use_count; expects long, got uint32 (`#936 <https://github.com/ros2/rclcpp/issues/936>`_)
|
||||
* Use absolute topic name for parameter events (`#929 <https://github.com/ros2/rclcpp/issues/929>`_)
|
||||
* Add enable_rosout into NodeOptions. (`#900 <https://github.com/ros2/rclcpp/issues/900>`_)
|
||||
* Removing "virtual", adding "override" keywords (`#897 <https://github.com/ros2/rclcpp/issues/897>`_)
|
||||
* Use weak_ptr to store context in GraphListener (`#906 <https://github.com/ros2/rclcpp/issues/906>`_)
|
||||
* Complete published event message when declaring a parameter (`#928 <https://github.com/ros2/rclcpp/issues/928>`_)
|
||||
* Fix duration.cpp lint error (`#930 <https://github.com/ros2/rclcpp/issues/930>`_)
|
||||
* Intra-process subscriber should use RMW actual qos. (ros2`#913 <https://github.com/ros2/rclcpp/issues/913>`_) (`#914 <https://github.com/ros2/rclcpp/issues/914>`_)
|
||||
* Type conversions fixes (`#901 <https://github.com/ros2/rclcpp/issues/901>`_)
|
||||
* Add override keyword to functions
|
||||
* Remove unnecessary virtual keywords
|
||||
* Only check for new work once in spin_some (`#471 <https://github.com/ros2/rclcpp/issues/471>`_) (`#844 <https://github.com/ros2/rclcpp/issues/844>`_)
|
||||
* Add addition/subtraction assignment operators to Time (`#748 <https://github.com/ros2/rclcpp/issues/748>`_)
|
||||
* Contributors: Alberto Soragna, Alejandro Hernández Cordero, Barry Xu, Chris Lalancette, Christophe Bedard, Claire Wang, Dan Rose, DensoADAS, Devin Bonnie, Dino Hüllmann, Dirk Thomas, DongheeYe, Emerson Knapp, Ivan Santiago Paunovic, Jacob Perron, Jaison Titus, Karsten Knese, Matt Schickler, Miaofei Mei, Michel Hidalgo, Mikael Arguedas, Monika Idzik, Prajakta Gokhale, Roger Strain, Scott K Logan, Sean Kelly, Stephen Brawner, Steven Macenski, Steven! Ragnarök, Todd Malsbary, Tomoya Fujita, William Woodall, Zachary Michaels
|
||||
|
||||
0.8.3 (2019-11-19)
|
||||
0.7.8 (2019-09-06)
|
||||
------------------
|
||||
|
||||
0.8.2 (2019-11-18)
|
||||
0.7.7 (2019-07-31)
|
||||
------------------
|
||||
* Updated tracing logic to match changes in rclcpp's intra-process system (`#918 <https://github.com/ros2/rclcpp/issues/918>`_)
|
||||
* Fixed a bug that prevented the ``shutdown_on_sigint`` option to not work correctly (`#850 <https://github.com/ros2/rclcpp/issues/850>`_)
|
||||
* Added support for STREAM logging macros (`#926 <https://github.com/ros2/rclcpp/issues/926>`_)
|
||||
* Relaxed multithreaded test constraint (`#907 <https://github.com/ros2/rclcpp/issues/907>`_)
|
||||
* Contributors: Anas Abou Allaban, Christophe Bedard, Dirk Thomas, alexfneves
|
||||
* Enabled the creation of a parameter YAML file which is applied to each node. (`#805 <https://github.com/ros2/rclcpp/issues/805>`_)
|
||||
* Fixed a signed/unsigned integer comparison compiler warning. (`#804 <https://github.com/ros2/rclcpp/issues/804>`_)
|
||||
* Changed the QoS profile used when subscribing to parameter events to match the publishing side, i.e. ``rmw_qos_profile_parameter_events``. (`#798 <https://github.com/ros2/rclcpp/issues/798>`_)
|
||||
* Changed the logic in TimeSource to ignore use_sim_time parameter events coming from other nodes. (`#803 <https://github.com/ros2/rclcpp/issues/803>`_)
|
||||
* Added missing default values in the NodeParametersInterface. (`#794 <https://github.com/ros2/rclcpp/issues/794>`_)
|
||||
* Added support for const member callback functions. (`#763 <https://github.com/ros2/rclcpp/issues/763>`_)
|
||||
* Contributors: Esteve Fernandez, Gonzo, Karsten Knese, Michel Hidalgo, Scott K Logan
|
||||
|
||||
0.8.1 (2019-10-23)
|
||||
0.7.6 (2019-06-12)
|
||||
------------------
|
||||
* De-flake tests for rmw_connext (`#899 <https://github.com/ros2/rclcpp/issues/899>`_)
|
||||
* rename return functions for loaned messages (`#896 <https://github.com/ros2/rclcpp/issues/896>`_)
|
||||
* Enable throttling logs (`#879 <https://github.com/ros2/rclcpp/issues/879>`_)
|
||||
* New Intra-Process Communication (`#778 <https://github.com/ros2/rclcpp/issues/778>`_)
|
||||
* Instrumentation update (`#789 <https://github.com/ros2/rclcpp/issues/789>`_)
|
||||
* Zero copy api (`#864 <https://github.com/ros2/rclcpp/issues/864>`_)
|
||||
* Drop rclcpp remove_ros_arguments_null test case. (`#894 <https://github.com/ros2/rclcpp/issues/894>`_)
|
||||
* add mechanism to pass rmw impl specific payloads during pub/sub creation (`#882 <https://github.com/ros2/rclcpp/issues/882>`_)
|
||||
* make get_actual_qos return a rclcpp::QoS (`#883 <https://github.com/ros2/rclcpp/issues/883>`_)
|
||||
* Fix Compiler Warning (`#881 <https://github.com/ros2/rclcpp/issues/881>`_)
|
||||
* Add callback handler for use_sim_time parameter `#802 <https://github.com/ros2/rclcpp/issues/802>`_ (`#875 <https://github.com/ros2/rclcpp/issues/875>`_)
|
||||
* Contributors: Alberto Soragna, Brian Marchi, Hunter L. Allen, Ingo Lütkebohle, Karsten Knese, Michael Carroll, Michel Hidalgo, William Woodall
|
||||
|
||||
0.8.0 (2019-09-26)
|
||||
------------------
|
||||
* clean up publisher and subscription creation logic (`#867 <https://github.com/ros2/rclcpp/issues/867>`_)
|
||||
* Take parameter overrides provided through the CLI. (`#865 <https://github.com/ros2/rclcpp/issues/865>`_)
|
||||
* add more context to exception message (`#858 <https://github.com/ros2/rclcpp/issues/858>`_)
|
||||
* remove features and related code which were deprecated in dashing (`#852 <https://github.com/ros2/rclcpp/issues/852>`_)
|
||||
* check valid timer handler 1st to reduce the time window for scan. (`#841 <https://github.com/ros2/rclcpp/issues/841>`_)
|
||||
* Add throwing parameter name if parameter is not set (`#833 <https://github.com/ros2/rclcpp/issues/833>`_)
|
||||
* Fix typo in deprecated warning. (`#848 <https://github.com/ros2/rclcpp/issues/848>`_)
|
||||
* Fail on invalid and unknown ROS specific arguments (`#842 <https://github.com/ros2/rclcpp/issues/842>`_)
|
||||
* Force explicit --ros-args in NodeOptions::arguments(). (`#845 <https://github.com/ros2/rclcpp/issues/845>`_)
|
||||
* Use of -r/--remap flags where appropriate. (`#834 <https://github.com/ros2/rclcpp/issues/834>`_)
|
||||
* Fix hang with timers in MultiThreadedExecutor (`#835 <https://github.com/ros2/rclcpp/issues/835>`_) (`#836 <https://github.com/ros2/rclcpp/issues/836>`_)
|
||||
* add mutex in add/remove_node and wait_for_work to protect concurrent use/change of memory_strategy\_ (`#837 <https://github.com/ros2/rclcpp/issues/837>`_)
|
||||
* Crash in callback group pointer vector iterator (`#814 <https://github.com/ros2/rclcpp/issues/814>`_)
|
||||
* Wrap documentation examples in code blocks (`#830 <https://github.com/ros2/rclcpp/issues/830>`_)
|
||||
* add callback group as member variable and constructor arg (`#811 <https://github.com/ros2/rclcpp/issues/811>`_)
|
||||
* Fix get_node_interfaces functions taking a pointer (`#821 <https://github.com/ros2/rclcpp/issues/821>`_)
|
||||
* Delete unnecessary call for get_node_by_group (`#823 <https://github.com/ros2/rclcpp/issues/823>`_)
|
||||
* Allow passing logger by const ref (`#820 <https://github.com/ros2/rclcpp/issues/820>`_)
|
||||
* Explain return value of spin_until_future_complete (`#792 <https://github.com/ros2/rclcpp/issues/792>`_)
|
||||
* Adapt to '--ros-args ... [--]'-based ROS args extraction (`#816 <https://github.com/ros2/rclcpp/issues/816>`_)
|
||||
* Add line break after first open paren in multiline function call (`#785 <https://github.com/ros2/rclcpp/issues/785>`_)
|
||||
* remove mock msgs from rclcpp (`#800 <https://github.com/ros2/rclcpp/issues/800>`_)
|
||||
* Make TimeSource ignore use_sim_time events coming from other nodes. (`#799 <https://github.com/ros2/rclcpp/issues/799>`_)
|
||||
* Allow registering multiple on_parameters_set_callback (`#772 <https://github.com/ros2/rclcpp/issues/772>`_)
|
||||
* Add free function for creating service clients (`#788 <https://github.com/ros2/rclcpp/issues/788>`_)
|
||||
* Include missing rcl headers in use. (`#782 <https://github.com/ros2/rclcpp/issues/782>`_)
|
||||
* Switch the NodeParameters lock to recursive. (`#781 <https://github.com/ros2/rclcpp/issues/781>`_)
|
||||
* changed on_parameter_event qos profile to rmw_qos_profile_parameter_events (`#774 <https://github.com/ros2/rclcpp/issues/774>`_)
|
||||
* Adding a factory method to create a Duration from seconds (`#567 <https://github.com/ros2/rclcpp/issues/567>`_)
|
||||
* Fix a comparison with a sign mismatch (`#771 <https://github.com/ros2/rclcpp/issues/771>`_)
|
||||
* delete superfluous spaces (`#770 <https://github.com/ros2/rclcpp/issues/770>`_)
|
||||
* Use params from node '/\*\*' from parameter YAML file (`#762 <https://github.com/ros2/rclcpp/issues/762>`_)
|
||||
* Add ignore override argument to declare parameter (`#767 <https://github.com/ros2/rclcpp/issues/767>`_)
|
||||
* use default parameter descriptor in parameters interface (`#765 <https://github.com/ros2/rclcpp/issues/765>`_)
|
||||
* Added support for const member functions (`#763 <https://github.com/ros2/rclcpp/issues/763>`_)
|
||||
* add get_actual_qos() feature to subscriptions (`#754 <https://github.com/ros2/rclcpp/issues/754>`_)
|
||||
* Ignore parameters overrides in set parameter methods when allowing undeclared parameters (`#756 <https://github.com/ros2/rclcpp/issues/756>`_)
|
||||
* Add rclcpp::create_timer() (`#757 <https://github.com/ros2/rclcpp/issues/757>`_)
|
||||
* checking origin of intra-process msg before taking them (`#753 <https://github.com/ros2/rclcpp/issues/753>`_)
|
||||
* Contributors: Alberto Soragna, Carl Delsey, Chris Lalancette, Dan Rose, Dirk Thomas, Esteve Fernandez, Guillaume Autran, Jacob Perron, Karsten Knese, Luca Della Vedova, M. M, Michel Hidalgo, Scott K Logan, Shane Loretz, Todd Malsbary, William Woodall, bpwilcox, fujitatomoya, ivanpauno
|
||||
* Contributors: Alberto Soragna, Shane Loretz, ivanpauno
|
||||
|
||||
0.7.5 (2019-05-30)
|
||||
------------------
|
||||
|
||||
@@ -2,38 +2,32 @@ cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
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)
|
||||
find_package(rcl_interfaces REQUIRED)
|
||||
find_package(rcl_yaml_param_parser REQUIRED)
|
||||
find_package(rcpputils REQUIRED)
|
||||
find_package(rcutils REQUIRED)
|
||||
find_package(rmw REQUIRED)
|
||||
find_package(rmw_implementation REQUIRED)
|
||||
find_package(rosgraph_msgs REQUIRED)
|
||||
find_package(rosidl_runtime_cpp REQUIRED)
|
||||
find_package(rosidl_generator_cpp REQUIRED)
|
||||
find_package(rosidl_typesupport_c REQUIRED)
|
||||
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
|
||||
# implicit sign conversions in rclcpp and gtest.cc, see https://ci.ros2.org/job/ci_osx/9265/.
|
||||
# Hence disabling -Wsign-conversion for now until all those have eventually been fixed.
|
||||
# (from https://github.com/ros2/rclcpp/pull/1188#issuecomment-650229140)
|
||||
add_compile_options(-Wall -Wextra -Wconversion -Wno-sign-conversion -Wpedantic -Wnon-virtual-dtor -Woverloaded-virtual)
|
||||
add_compile_options(-Wall -Wextra -Wconversion -Wno-sign-conversion -Wpedantic)
|
||||
endif()
|
||||
|
||||
include_directories(include)
|
||||
|
||||
set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/any_executable.cpp
|
||||
src/rclcpp/callback_group.cpp
|
||||
@@ -41,37 +35,23 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/clock.cpp
|
||||
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
|
||||
src/rclcpp/detail/utilities.cpp
|
||||
src/rclcpp/duration.cpp
|
||||
src/rclcpp/event.cpp
|
||||
src/rclcpp/exceptions/exceptions.cpp
|
||||
src/rclcpp/executable_list.cpp
|
||||
src/rclcpp/exceptions.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
|
||||
src/rclcpp/intra_process_manager.cpp
|
||||
src/rclcpp/intra_process_manager_impl.cpp
|
||||
src/rclcpp/logger.cpp
|
||||
src/rclcpp/logging_mutex.cpp
|
||||
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,31 +62,23 @@ 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
|
||||
src/rclcpp/signal_handler.cpp
|
||||
src/rclcpp/subscription_base.cpp
|
||||
src/rclcpp/subscription_intra_process_base.cpp
|
||||
src/rclcpp/time.cpp
|
||||
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
|
||||
)
|
||||
|
||||
@@ -117,91 +89,31 @@ configure_file(
|
||||
COPYONLY
|
||||
)
|
||||
# generate header with logging macros
|
||||
set(python_code_logging
|
||||
set(python_code
|
||||
"import em"
|
||||
"em.invoke(['-o', 'include/rclcpp/logging.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/logging.hpp.em'])")
|
||||
string(REPLACE ";" "$<SEMICOLON>" python_code_logging "${python_code_logging}")
|
||||
string(REPLACE ";" "$<SEMICOLON>" python_code "${python_code}")
|
||||
add_custom_command(OUTPUT include/rclcpp/logging.hpp
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp"
|
||||
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_code_logging}"
|
||||
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_code}"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/logging.hpp.em.watch"
|
||||
COMMENT "Expanding logging.hpp.em"
|
||||
VERBATIM
|
||||
)
|
||||
list(APPEND ${PROJECT_NAME}_SRCS
|
||||
include/rclcpp/logging.hpp)
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
|
||||
file(GLOB interface_files "include/rclcpp/node_interfaces/node_*_interface.hpp")
|
||||
foreach(interface_file ${interface_files})
|
||||
get_filename_component(interface_name ${interface_file} NAME_WE)
|
||||
|
||||
# "watch" template for changes
|
||||
configure_file(
|
||||
"resource/interface_traits.hpp.em"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${interface_name}_traits.hpp.em.watch"
|
||||
COPYONLY
|
||||
)
|
||||
set(python_${interface_name}_traits
|
||||
"import em"
|
||||
"em.invoke(['-D', 'interface_name = \\'${interface_name}\\'', '-o', 'include/rclcpp/node_interfaces/${interface_name}_traits.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/interface_traits.hpp.em'])")
|
||||
string(REPLACE ";" "$<SEMICOLON>" python_${interface_name}_traits "${python_${interface_name}_traits}")
|
||||
add_custom_command(OUTPUT include/rclcpp/node_interfaces/${interface_name}_traits.hpp
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp/node_interfaces"
|
||||
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_${interface_name}_traits}"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${interface_name}_traits.hpp.em.watch"
|
||||
COMMENT "Expanding interface_traits.hpp.em into ${interface_name}_traits.hpp"
|
||||
VERBATIM
|
||||
)
|
||||
list(APPEND ${PROJECT_NAME}_SRCS
|
||||
include/rclcpp/node_interfaces/${interface_name}_traits.hpp)
|
||||
|
||||
# "watch" template for changes
|
||||
configure_file(
|
||||
"resource/get_interface.hpp.em"
|
||||
"get_${interface_name}.hpp.em.watch"
|
||||
COPYONLY
|
||||
)
|
||||
set(python_get_${interface_name}
|
||||
"import em"
|
||||
"em.invoke(['-D', 'interface_name = \\'${interface_name}\\'', '-o', 'include/rclcpp/node_interfaces/get_${interface_name}.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/get_interface.hpp.em'])")
|
||||
string(REPLACE ";" "$<SEMICOLON>" python_get_${interface_name} "${python_get_${interface_name}}")
|
||||
add_custom_command(OUTPUT include/rclcpp/node_interfaces/get_${interface_name}.hpp
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp/node_interfaces"
|
||||
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_get_${interface_name}}"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/get_${interface_name}.hpp.em.watch"
|
||||
COMMENT "Expanding get_interface.hpp.em into get_${interface_file}.hpp"
|
||||
VERBATIM
|
||||
)
|
||||
list(APPEND ${PROJECT_NAME}_SRCS
|
||||
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()
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:include>")
|
||||
target_link_libraries(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT})
|
||||
add_library(${PROJECT_NAME}
|
||||
${${PROJECT_NAME}_SRCS})
|
||||
# specific order: dependents before dependencies
|
||||
ament_target_dependencies(${PROJECT_NAME}
|
||||
"ament_index_cpp"
|
||||
"libstatistics_collector"
|
||||
"rcl"
|
||||
"rcl_yaml_param_parser"
|
||||
"rcpputils"
|
||||
"rcutils"
|
||||
"builtin_interfaces"
|
||||
"rosgraph_msgs"
|
||||
"rosidl_typesupport_cpp"
|
||||
"rosidl_runtime_cpp"
|
||||
"statistics_msgs"
|
||||
"tracetools"
|
||||
)
|
||||
"rosidl_generator_cpp")
|
||||
|
||||
# Causes the visibility macros to use dllexport rather than dllimport,
|
||||
# which is appropriate when building the dll but not consuming it.
|
||||
@@ -209,7 +121,7 @@ target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE "RCLCPP_BUILDING_LIBRARY")
|
||||
|
||||
install(
|
||||
TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}
|
||||
TARGETS ${PROJECT_NAME}
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
RUNTIME DESTINATION bin
|
||||
@@ -218,27 +130,365 @@ install(
|
||||
# specific order: dependents before dependencies
|
||||
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(ament_cmake)
|
||||
ament_export_dependencies(rcl)
|
||||
ament_export_dependencies(rcpputils)
|
||||
ament_export_dependencies(rcutils)
|
||||
ament_export_dependencies(builtin_interfaces)
|
||||
ament_export_dependencies(rosgraph_msgs)
|
||||
ament_export_dependencies(rosidl_typesupport_cpp)
|
||||
ament_export_dependencies(rosidl_typesupport_c)
|
||||
ament_export_dependencies(rosidl_runtime_cpp)
|
||||
ament_export_dependencies(rosidl_generator_cpp)
|
||||
ament_export_dependencies(rcl_yaml_param_parser)
|
||||
ament_export_dependencies(statistics_msgs)
|
||||
ament_export_dependencies(tracetools)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
find_package(ament_cmake_gtest REQUIRED)
|
||||
find_package(ament_lint_auto REQUIRED)
|
||||
ament_lint_auto_find_test_dependencies()
|
||||
|
||||
add_subdirectory(test)
|
||||
find_package(rmw_implementation_cmake REQUIRED)
|
||||
|
||||
include(cmake/rclcpp_add_build_failure_test.cmake)
|
||||
|
||||
ament_add_gtest(test_client test/test_client.cpp)
|
||||
if(TARGET test_client)
|
||||
ament_target_dependencies(test_client
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_client ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_create_timer test/test_create_timer.cpp)
|
||||
if(TARGET test_create_timer)
|
||||
ament_target_dependencies(test_create_timer
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rcl"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_create_timer ${PROJECT_NAME})
|
||||
target_include_directories(test_create_timer PRIVATE test/)
|
||||
endif()
|
||||
ament_add_gtest(test_expand_topic_or_service_name test/test_expand_topic_or_service_name.cpp)
|
||||
if(TARGET test_expand_topic_or_service_name)
|
||||
ament_target_dependencies(test_expand_topic_or_service_name
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_expand_topic_or_service_name ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_function_traits test/test_function_traits.cpp)
|
||||
if(TARGET test_function_traits)
|
||||
ament_target_dependencies(test_function_traits
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
endif()
|
||||
ament_add_gtest(test_mapped_ring_buffer test/test_mapped_ring_buffer.cpp)
|
||||
if(TARGET test_mapped_ring_buffer)
|
||||
ament_target_dependencies(test_mapped_ring_buffer
|
||||
"rcl"
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
endif()
|
||||
ament_add_gtest(test_intra_process_manager test/test_intra_process_manager.cpp)
|
||||
if(TARGET test_intra_process_manager)
|
||||
ament_target_dependencies(test_intra_process_manager
|
||||
"rcl"
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
endif()
|
||||
ament_add_gtest(test_node test/test_node.cpp)
|
||||
if(TARGET test_node)
|
||||
ament_target_dependencies(test_node
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_node ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_node_interfaces__get_node_interfaces
|
||||
test/node_interfaces/test_get_node_interfaces.cpp)
|
||||
if(TARGET test_node_interfaces__get_node_interfaces)
|
||||
target_link_libraries(test_node_interfaces__get_node_interfaces ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
# TODO(wjwwood): reenable these build failure tests when I can get Jenkins to ignore their output
|
||||
# rclcpp_add_build_failure_test(build_failure__get_node_topics_interface_const_ref_rclcpp_node
|
||||
# test/node_interfaces/test_does_not_compile/get_node_topics_interface_const_ref_rclcpp_node.cpp)
|
||||
# target_link_libraries(build_failure__get_node_topics_interface_const_ref_rclcpp_node
|
||||
# ${PROJECT_NAME})
|
||||
|
||||
# rclcpp_add_build_failure_test(build_failure__get_node_topics_interface_const_ptr_rclcpp_node
|
||||
# test/node_interfaces/test_does_not_compile/get_node_topics_interface_const_ptr_rclcpp_node.cpp)
|
||||
# target_link_libraries(build_failure__get_node_topics_interface_const_ptr_rclcpp_node
|
||||
# ${PROJECT_NAME})
|
||||
|
||||
# rclcpp_add_build_failure_test(build_failure__get_node_topics_interface_const_ref_wrapped_node
|
||||
# test/node_interfaces/test_does_not_compile/get_node_topics_interface_const_ref_wrapped_node.cpp)
|
||||
# target_link_libraries(build_failure__get_node_topics_interface_const_ref_rclcpp_node
|
||||
# ${PROJECT_NAME})
|
||||
|
||||
# rclcpp_add_build_failure_test(build_failure__get_node_topics_interface_const_ptr_wrapped_node
|
||||
# test/node_interfaces/test_does_not_compile/get_node_topics_interface_const_ptr_wrapped_node.cpp)
|
||||
# target_link_libraries(build_failure__get_node_topics_interface_const_ptr_rclcpp_node
|
||||
# ${PROJECT_NAME})
|
||||
|
||||
ament_add_gtest(test_node_global_args test/test_node_global_args.cpp)
|
||||
if(TARGET test_node_global_args)
|
||||
ament_target_dependencies(test_node_global_args
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_node_global_args ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter_client test/test_parameter_client.cpp)
|
||||
if(TARGET test_parameter_client)
|
||||
ament_target_dependencies(test_parameter_client
|
||||
"rcl_interfaces"
|
||||
)
|
||||
target_link_libraries(test_parameter_client ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter_events_filter test/test_parameter_events_filter.cpp)
|
||||
if(TARGET test_parameter_events_filter)
|
||||
ament_target_dependencies(test_parameter_events_filter
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_parameter_events_filter ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter test/test_parameter.cpp)
|
||||
if(TARGET test_parameter)
|
||||
ament_target_dependencies(test_parameter
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_parameter ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter_map test/test_parameter_map.cpp)
|
||||
if(TARGET test_parameter_map)
|
||||
target_link_libraries(test_parameter_map ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_publisher test/test_publisher.cpp)
|
||||
if(TARGET test_publisher)
|
||||
ament_target_dependencies(test_publisher
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_publisher ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_publisher_subscription_count_api test/test_publisher_subscription_count_api.cpp)
|
||||
if(TARGET test_publisher_subscription_count_api)
|
||||
ament_target_dependencies(test_publisher_subscription_count_api
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_publisher_subscription_count_api ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_rate test/test_rate.cpp)
|
||||
if(TARGET test_rate)
|
||||
ament_target_dependencies(test_rate
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_rate
|
||||
${PROJECT_NAME}
|
||||
)
|
||||
endif()
|
||||
ament_add_gtest(test_serialized_message_allocator test/test_serialized_message_allocator.cpp)
|
||||
if(TARGET test_serialized_message_allocator)
|
||||
ament_target_dependencies(test_serialized_message_allocator
|
||||
test_msgs
|
||||
)
|
||||
target_link_libraries(test_serialized_message_allocator
|
||||
${PROJECT_NAME}
|
||||
)
|
||||
endif()
|
||||
ament_add_gtest(test_service test/test_service.cpp)
|
||||
if(TARGET test_service)
|
||||
ament_target_dependencies(test_service
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_service ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_subscription test/test_subscription.cpp)
|
||||
if(TARGET test_subscription)
|
||||
ament_target_dependencies(test_subscription
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_subscription ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_subscription_publisher_count_api test/test_subscription_publisher_count_api.cpp)
|
||||
if(TARGET test_subscription_publisher_count_api)
|
||||
ament_target_dependencies(test_subscription_publisher_count_api
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_subscription_publisher_count_api ${PROJECT_NAME})
|
||||
endif()
|
||||
find_package(test_msgs REQUIRED)
|
||||
ament_add_gtest(test_subscription_traits test/test_subscription_traits.cpp)
|
||||
if(TARGET test_subscription_traits)
|
||||
ament_target_dependencies(test_subscription_traits
|
||||
"rcl"
|
||||
"test_msgs"
|
||||
)
|
||||
endif()
|
||||
ament_add_gtest(test_find_weak_nodes test/test_find_weak_nodes.cpp)
|
||||
if(TARGET test_find_weak_nodes)
|
||||
ament_target_dependencies(test_find_weak_nodes
|
||||
"rcl"
|
||||
)
|
||||
target_link_libraries(test_find_weak_nodes ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
get_default_rmw_implementation(default_rmw)
|
||||
find_package(${default_rmw} REQUIRED)
|
||||
get_rmw_typesupport(typesupport_impls_cpp "${default_rmw}" LANGUAGE "cpp")
|
||||
get_rmw_typesupport(typesupport_impls_c "${default_rmw}" LANGUAGE "c")
|
||||
set(mock_msg_files
|
||||
"test/mock_msgs/srv/Mock.srv")
|
||||
rosidl_generate_interfaces(mock_msgs
|
||||
${mock_msg_files}
|
||||
LIBRARY_NAME "rclcpp"
|
||||
SKIP_INSTALL)
|
||||
|
||||
set(append_library_dirs "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
if(WIN32)
|
||||
set(append_library_dirs "${append_library_dirs}/$<CONFIG>")
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_externally_defined_services test/test_externally_defined_services.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_externally_defined_services)
|
||||
ament_target_dependencies(test_externally_defined_services
|
||||
"rcl"
|
||||
)
|
||||
target_link_libraries(test_externally_defined_services ${PROJECT_NAME})
|
||||
foreach(typesupport_impl_cpp ${typesupport_impls_cpp})
|
||||
rosidl_target_interfaces(test_externally_defined_services
|
||||
mock_msgs ${typesupport_impl_cpp})
|
||||
endforeach()
|
||||
foreach(typesupport_impl_c ${typesupport_impls_c})
|
||||
rosidl_target_interfaces(test_externally_defined_services
|
||||
mock_msgs ${typesupport_impl_c})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_duration test/test_duration.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_duration)
|
||||
ament_target_dependencies(test_duration
|
||||
"rcl")
|
||||
target_link_libraries(test_duration ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_executor test/test_executor.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_executor)
|
||||
ament_target_dependencies(test_executor
|
||||
"rcl")
|
||||
target_link_libraries(test_executor ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_logger test/test_logger.cpp)
|
||||
target_link_libraries(test_logger ${PROJECT_NAME})
|
||||
|
||||
ament_add_gmock(test_logging test/test_logging.cpp)
|
||||
target_link_libraries(test_logging ${PROJECT_NAME})
|
||||
|
||||
ament_add_gtest(test_time test/test_time.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_time)
|
||||
ament_target_dependencies(test_time
|
||||
"rcl")
|
||||
target_link_libraries(test_time ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_timer test/test_timer.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_timer)
|
||||
ament_target_dependencies(test_timer
|
||||
"rcl")
|
||||
target_link_libraries(test_timer ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_time_source test/test_time_source.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_time_source)
|
||||
ament_target_dependencies(test_time_source
|
||||
"rcl")
|
||||
target_link_libraries(test_time_source ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_utilities test/test_utilities.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_utilities)
|
||||
ament_target_dependencies(test_utilities
|
||||
"rcl")
|
||||
target_link_libraries(test_utilities ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_init test/test_init.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_init)
|
||||
ament_target_dependencies(test_init
|
||||
"rcl")
|
||||
target_link_libraries(test_init ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_multi_threaded_executor test/executors/test_multi_threaded_executor.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_multi_threaded_executor)
|
||||
ament_target_dependencies(test_multi_threaded_executor
|
||||
"rcl")
|
||||
target_link_libraries(test_multi_threaded_executor ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_local_parameters test/test_local_parameters.cpp)
|
||||
if(TARGET test_local_parameters)
|
||||
ament_target_dependencies(test_local_parameters
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_local_parameters ${PROJECT_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ament_package()
|
||||
@@ -247,8 +497,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()
|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
This document is a declaration of software quality for the `rclcpp` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
# rclcpp Quality Declaration
|
||||
|
||||
The package `rclcpp` claims to be in the **Quality Level 1** category when it is used with a **Quality Level 1** middleware.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Quality Categories in REP-2004](https://www.ros.org/reps/rep-2004.html) of the ROS2 developer guide.
|
||||
|
||||
## Version Policy [1]
|
||||
|
||||
### 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).
|
||||
|
||||
### Version Stability [1.ii]
|
||||
|
||||
`rclcpp` is at a stable version, i.e. `>= 1.0.0`.
|
||||
The current version can be found in its [package.xml](package.xml), and its change history can be found in its [CHANGELOG](CHANGELOG.rst).
|
||||
|
||||
### Public API Declaration [1.iii]
|
||||
|
||||
All symbols in the installed headers are considered part of the public API.
|
||||
|
||||
Except for the exclusions listed below, all installed headers are in the `include` directory of the package, headers in any other folders are not installed and considered private.
|
||||
Headers under the folder `experimental` are not considered part of the public API as they have not yet been stabilized. These symbols are namespaced `rclcpp::experimental`.
|
||||
Headers under the folder `detail` are not considered part of the public API and are subject to change without notice. These symbols are namespaced `rclcpp::detail`.
|
||||
|
||||
### API Stability Policy [1.iv]
|
||||
|
||||
`rclcpp` will not break public API within a released ROS distribution, i.e. no major releases once the ROS distribution is released.
|
||||
|
||||
### ABI Stability Policy [1.v]
|
||||
|
||||
`rclcpp` contains C++ code and therefore must be concerned with ABI stability, and will maintain ABI stability within a ROS distribution.
|
||||
|
||||
### ABI and ABI Stability Within a Released ROS Distribution [1.vi]
|
||||
|
||||
`rclcpp` will not break API nor ABI within a released ROS distribution, i.e. no major releases once the ROS distribution is released.
|
||||
|
||||
## 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).
|
||||
|
||||
### 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.
|
||||
|
||||
### Contributor Origin [2.ii]
|
||||
|
||||
This package uses DCO as its confirmation of contributor origin policy. More information can be found in [CONTRIBUTING](../CONTRIBUTING.md).
|
||||
|
||||
### 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.
|
||||
|
||||
### 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/)
|
||||
|
||||
### Documentation Policy [2.v]
|
||||
|
||||
All pull requests must resolve related documentation changes before merging.
|
||||
|
||||
## Documentation [3]
|
||||
|
||||
### 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.
|
||||
|
||||
### Public API Documentation [3.ii]
|
||||
|
||||
The API is publicly available in its [ROS 2 API documentation](http://docs.ros2.org/latest/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.
|
||||
|
||||
### 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/).
|
||||
|
||||
## 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.
|
||||
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/)
|
||||
|
||||
### Public API Testing [4.ii]
|
||||
|
||||
Each part of the public API has tests, and new additions or changes to the public API require tests before being added.
|
||||
The tests aim to cover both typical usage and corner cases, but are quantified by contributing to code coverage.
|
||||
|
||||
### 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.
|
||||
|
||||
This includes:
|
||||
|
||||
- tracking and reporting line coverage statistics
|
||||
- achieving and maintaining a reasonable branch line coverage (90-100%)
|
||||
- no lines are manually skipped in coverage calculations
|
||||
|
||||
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).
|
||||
|
||||
`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.
|
||||
|
||||
The performance tests of `rclcpp` are located in the [test/benchmark directory](https://github.com/ros2/rclcpp/tree/master/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/)
|
||||
|
||||
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.
|
||||
|
||||
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/)
|
||||
|
||||
## Dependencies [5]
|
||||
|
||||
Below are evaluations of each of `rclcpp`'s run-time and build-time dependencies that have been determined to influence the quality.
|
||||
|
||||
It has several "buildtool" dependencies, which do not affect the resulting quality of the package, because they do not contribute to the public library API.
|
||||
|
||||
It also has several test dependencies, which do not affect the resulting quality of the package, because they are only used to build and run the test code.
|
||||
|
||||
### Direct and Optional Runtime ROS Dependencies [5.i]/[5.ii]
|
||||
|
||||
`rclcpp` has the following runtime ROS dependencies:
|
||||
|
||||
#### `libstatistics_collector`
|
||||
|
||||
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).
|
||||
|
||||
#### `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).
|
||||
|
||||
#### `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).
|
||||
|
||||
#### `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).
|
||||
|
||||
#### `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).
|
||||
|
||||
#### `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).
|
||||
|
||||
#### `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).
|
||||
|
||||
#### `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).
|
||||
|
||||
### Direct Runtime non-ROS Dependency [5.iii]
|
||||
|
||||
`rclcpp` has no run-time or build-time dependencies that need to be considered for this declaration.
|
||||
|
||||
## Platform Support [6]
|
||||
|
||||
`rclcpp` supports all of the tier 1 platforms as described in [REP-2000](https://www.ros.org/reps/rep-2000.html#support-tiers), and tests each change against all of them.
|
||||
|
||||
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/)
|
||||
|
||||
## Security
|
||||
|
||||
### Vulnerability Disclosure Policy [7.i]
|
||||
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://www.ros.org/reps/rep-2006.html).
|
||||
@@ -1,9 +0,0 @@
|
||||
# `rclcpp`
|
||||
|
||||
The ROS client library in C++.
|
||||
|
||||
Visit the [rclcpp API documentation](http://docs.ros2.org/latest/api/rclcpp/) for a complete list of its main components and features.
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
This package claims to be in the **Quality Level 1** category, see the [Quality Declaration](QUALITY_DECLARATION.md) for more details.
|
||||
@@ -1,437 +0,0 @@
|
||||
# API Review for `rclcpp` from March 2020
|
||||
|
||||
## Notes
|
||||
|
||||
### Off-Topic Questions
|
||||
|
||||
> [rclcpp_action] There exists a thread-safe and non-thread-safe way to get the goal result from an action client. We probably want to remove the public interface to the non-thread safe call (or consolidate somehow): https://github.com/ros2/rclcpp/issues/955
|
||||
|
||||
`rclcpp_action` is out of scope atm.
|
||||
|
||||
**Notes from 2020-03-19**: To be handled in separate API review.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Calling Syntax and Keeping Node-like Class APIs in Sync
|
||||
|
||||
> Currently, much of the API is exposed via the `rclcpp::Node` class, and due to the nature of the current architecture there is a lot of repeated code to expose these methods and then call the implementations which are in other classes like `rclcpp::node_interfaces::NodeTopics`, for example.
|
||||
>
|
||||
> Also, we have other versions of the class `rclcpp::Node` with different semantics and interfaces, like `rclcpp_lifecycle::LifecycleNode`, and we have been having trouble keeping the interface provided there up to date with how things are done in `rclcpp::Node`. Since `LifecycleNode` has a different API from `Node` in some important cases, it does not just inherit from `Node`.
|
||||
>
|
||||
> There are two main proposals (as I see it) to try and address this issue, either (a) break up the functionality in `Node` so that it is in separate classes and make `Node` multiple inherit from those classes, and then `LifecycleNode` could selectively inherit from those as well, or (b) change our calling convention from `node->do_thing(...)` to be `do_thing(node, ...)`.
|
||||
>
|
||||
> For (a) which commonly referred to as the [Policy Based Design Pattern](https://en.wikipedia.org/wiki/Modern_C%2B%2B_Design#Policy-based_design), we'd be reversing previous design decisions which we discussed at length where we decided to use composition over inheritance for various reasons.
|
||||
> One of the reasons was testing, with the theory that having simpler separate interfaces we could more easily mock them as needed for testing.
|
||||
> The testing goal would still be met, either by keeping the "node_interface" classes as-is or by mocking the classes that node would multiple inherit from, however it's harder to indicate that a function needs a class that multiple inherits from several classes but not others.
|
||||
> Also having interdependency between the classes which are inherited from is a bit complicated in this design pattern.
|
||||
>
|
||||
> For (b), we would be changing how we recommend all code be written (not a trivial thing to do at all), because example code like `auto pub = node->create_publsiher(...);` would be come `auto pub = create_publisher(node, ...);`.
|
||||
> This has some distinct advantages, however, in that it allows us to write these functions, like `create_publisher(node, ...)`, so that the node argument can be any class that meets the criteria of the function.
|
||||
> That not only means that when we add a feature it automatically works with `Node` and `LifecycleNode` without adding anything to them, it also means that user defined `Node`-like classes will also work, even if they do not inherit from or provide the complete interface for `rclcpp::Node`.
|
||||
> Another major downside of this approach is discoverability of the API when using auto-completion in text editors, as `node-><tab>` will often give you a list of methods to explore, but with the new calling convention, there's not way to get an auto complete for code who's first argument is a `Node`-like class.
|
||||
>
|
||||
> Both of the above approaches address some of the main concerns, which are: keeping `Node` and `LifecycleNode` in sync, reducing the size of the `Node` class so it is more easily maintained, documented, and so that related functions are grouped more clearly.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/898
|
||||
- https://github.com/ros2/rclcpp/issues/509
|
||||
- https://github.com/ros2/rclcpp/issues/855
|
||||
- https://github.com/ros2/rclcpp/issues/985
|
||||
- subnode feature is in rclcpp::Node only, complicating "node using" API designs
|
||||
- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4174.pdf
|
||||
- https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax#C++_proposal
|
||||
- "Many programmers are tempted to write member functions to get the benefits of the member function syntax (e.g. "dot-autocomplete" to list member functions);[6] however, this leads to excessive coupling between classes.[7]"
|
||||
|
||||
**Suggested Action**: Document the discussion and defer until Foxy.
|
||||
|
||||
**Notes from 2020-03-19**:
|
||||
|
||||
- Another version of (b) could be to have classes that are constructed with node, e.g. `Publisher(node, ...)` rather than `node->create_publisher(...)`
|
||||
- (tfoote) interface class? `NodeInterface<NodeLike>::something(node_like)`
|
||||
- DRY?
|
||||
- `NodeInterface<LifecycleNode>::<tab>` -> only life cycle node methods
|
||||
- (karsten) use interface classes directly, e.g. node->get_X_interface()->do_thing()
|
||||
- (dirk) use macros to add methods to class
|
||||
- Question: Do we want tab-completable API (specifically list of member functions)?
|
||||
- Question: Is consistency in calling between core and non-core features more important than tab-completion?
|
||||
- Add better example of adding new feature and not needing to touch `rclcpp::Node`.
|
||||
- (dirk) methods and free functions not mutually exclusive.
|
||||
|
||||
### Scoped Versus Non-Scoped Entities (e.g. Publishers/Subscriptions)
|
||||
|
||||
> Currently, Publisher and Subscription (and similar entities) are scoped, meaning that when they are created they are added to the ROS graph as a side effect, and when they are let out of scope they remove themselves from the graph too.
|
||||
> Additionally, they necessarily have shared state with the system, for instance when you are spinning on a node, the executor shares ownership of the Subscriptions with the user.
|
||||
> Therefore, the Subscription only gets removed when both the user and executor are done with it.
|
||||
>
|
||||
> This shared ownership is accomplished with the use of shared pointers and weak pointers.
|
||||
>
|
||||
> There are a few concerns here, (a) use of shared pointers confuses users, (b) overhead of shared pointers and lack of an ability to use these classes on the stack rather than the heap, and (c) complexity of shutdown of an entity from the users perspective.
|
||||
>
|
||||
> For (a), some users are overwhelmed by the need to use a shared pointer.
|
||||
> In ROS 1 this was avoided by having a class which itself just thinly wraps a shared pointer (see: https://github.com/ros/ros_comm/blob/ac9f88c59a676ca6895e13445fc7d71f398ebe1f/clients/roscpp/include/ros/subscriber.h#L108-L111).
|
||||
> This could be achieved in ROS 2 either by doing the same with a wrapper class (at the expense of lots of repeated code), or by eliminating the need for using shared ownership.
|
||||
>
|
||||
> For (b), for some use cases, especially resource constrained / real-time / safety-critical environments, requiring these classes to be on the heap rather than the stack is at least inconvenient.
|
||||
> Additionally, there is a cost associated with using shared pointers, in the storage of shared state and in some implementation the use of locks or at least atomics for thread-safety.
|
||||
>
|
||||
> For (c), this is the most concerning drawback, because right now when a user lets their shared pointer to a, for example, Subscription go out of scope, a post condition is not that the Subscription is destroyed, nor that it has been removed from the graph.
|
||||
> In stead, the behavior is more like "at some point in the future the Subscription will be destroyed and removed from the graph, when the system is done with it".
|
||||
> This isn't a very satisfactory contract, as some users may wish to know when the Subscription has been deleted, but cannot easily know that.
|
||||
>
|
||||
> The benefit to the shared state is a safety net for users.
|
||||
> The alternative would be to document that a Subscription, again for example, cannot be deleted until the system is done with it.
|
||||
> We'd basically be pushing the responsibility onto the user to ensure the shared ownership is handled properly by the execution of their application, i.e. they create the Subscription, share a reference with the system (adding it by reference to an executor, for example), and they have to make sure the system is done with it before deleting the Subscription.
|
||||
>
|
||||
>Separately, from the above points, there is the related concern of forcing the user to keep a copy of their entities in scope, whether it be with a shared pointer or a class wrapping one.
|
||||
> There is the desire to create it and forget it in some cases.
|
||||
> The downside to this is that if/when the user wants to destroy the entity, they have no way of doing that as they have no handle or unique way to address the entity.
|
||||
>
|
||||
> One proposed solution would be to have a set of "named X" APIs, e.g. `create_named_subscription` rather than just `create_subscription`.
|
||||
> This would allow the user to address the Subscription in the future in order to obtain a new reference to it or delete it.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/506
|
||||
- https://github.com/ros2/rclcpp/issues/726
|
||||
|
||||
**Suggested Action**: Consolidate to a single issue, and defer.
|
||||
|
||||
**Notes from 2020-03-23**:
|
||||
|
||||
- (chris) Putting ownership mechanics on user is hard.
|
||||
- (dirk) add documentation clearly outlining ownership
|
||||
- (shane) warn on unused to catch issues with immediately deleted items
|
||||
- (tfoote) debugging output for destruction so it easy to see when reviewing logs
|
||||
- (chris) possible to create API that checks for destruction
|
||||
- (william) might lead to complex synchronization issues
|
||||
- (tfoote) could add helper classes to make scoped things non-scoped
|
||||
- (shane) concerned that there is no longer "one good way" to do it
|
||||
|
||||
### Allow QoS to be configured externally, like we allow remapping of topic names
|
||||
|
||||
> Suggestion from @stonier: allow the qos setting on a topic to be changed externally at startup, similar to how we do topic remapping (e.g., do it on the command-line using appropriate syntax).
|
||||
>
|
||||
> To keep the syntax manageable, we might just allow profiles to be picked.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/239
|
||||
|
||||
**Suggested Action**: Update issue, defer for now.
|
||||
|
||||
**Notes from 2020-03-19**:
|
||||
|
||||
- (wjwwood) it depends on the QoS setting, but many don't make sense, mostly because they can change some of the behaviors of underlying API
|
||||
- (dirk) Should developers expose a parameter instead?
|
||||
- (multiple) should be a feature that makes configuring them (after opt-in) consistent
|
||||
- (jacob) customers feedback was that this was expected, surprised it was not allowed
|
||||
- (karsten) could limit to profiles
|
||||
|
||||
## Init/shutdown and Context
|
||||
|
||||
### Consider renaming `rclcpp::ok()`
|
||||
|
||||
> Old discussion to rename `rclcpp::ok()` to something more specific, like `rclcpp::is_not_shutdown()` or the corollary `rclcpp::is_shutdown()`.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/3
|
||||
|
||||
**Suggested Action**: Defer.
|
||||
|
||||
**Notes from 2020-03-19**:
|
||||
|
||||
- (shane) preference to not have a negative in the function name
|
||||
|
||||
## Executor
|
||||
|
||||
### Exposing Scheduling of Tasks in Executor and a Better Default
|
||||
|
||||
> Currently there is a hard coded procedure for handling ready tasks in the executor, first timers, then subscriptions, and so on.
|
||||
> This scheduling is not fair and results in non-deterministic behavior and starvation issues.
|
||||
>
|
||||
> We should provide a better default scheduling which is fairer and ideally deterministic, something like round-robin or FIFO.
|
||||
>
|
||||
> Additionally, we should make it easier to let the user override the scheduling logic in the executor.
|
||||
|
||||
- https://github.com/ros2/rclcpp/pull/614
|
||||
- https://github.com/ros2/rclcpp/issues/633
|
||||
- https://github.com/ros2/rclcpp/issues/392
|
||||
|
||||
**Suggested Action**: Follow up on proposals to implement FIFO scheduling and refactor the Executor design to more easily expose the scheduling logic.
|
||||
|
||||
**Notes from 2020-03-19**:
|
||||
|
||||
- No comments.
|
||||
|
||||
### Make it possible to wait on entities (e.g. Subscriptions) without an Executor
|
||||
|
||||
> Currently, it is only possible to use things like Timers and Subscriptions and Services with an executor.
|
||||
> It should be possible, however, to either poll these entities or wait on them and then decide which to process as a user.
|
||||
>
|
||||
> This is most easily accomplished with a WaitSet-like class.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/520
|
||||
|
||||
**Suggested Action**: implement WaitSet class in rclcpp so that this is possible, and make "waitable" entities such that they can be polled, e.g. `Subscription`s should have a user facing `take()` method, which can fail if no data is available.
|
||||
|
||||
**Notes from 2020-03-19**:
|
||||
|
||||
- No comments.
|
||||
|
||||
### Make it possible to use multiple executors per node
|
||||
|
||||
> Currently, you cannot use more than one executor per node, this limits your options when it comes to distributing work within a node across threads.
|
||||
> You can use a multi-threaded executor, or make your own executor which does this, but it is often convenient to be able to spin part of the node separately from the the rest of the node.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/519
|
||||
|
||||
**Suggested Action**: Make this possible, moving the exclusivity to be between an executor and callback groups rather than nodes.
|
||||
|
||||
**Notes from 2020-03-19**:
|
||||
|
||||
- No comments.
|
||||
|
||||
### Implement a Lock-free Executor
|
||||
|
||||
> This would presumably be useful for real-time and safety critical systems where locks and any kind of blocking code is considered undesirable.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/77
|
||||
|
||||
**Suggested Action**: Keep in backlog until someone needs it specifically.
|
||||
|
||||
**Notes from 2020-03-19**:
|
||||
|
||||
- No comments.
|
||||
|
||||
### Add implementation of `spin_some()` to the `MultiThreadedExecutor`
|
||||
|
||||
> Currently `spin_some()` is only available in the `SingleThreadedExecutor`.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/85
|
||||
|
||||
**Suggested Action**: Defer.
|
||||
|
||||
**Notes from 2020-03-19**:
|
||||
|
||||
- No comments.
|
||||
|
||||
## Node
|
||||
|
||||
### Do argument parsing outside of node constructor
|
||||
|
||||
> Things that come from command line arguments should be separately passed into the node's constructor rather than passing in arguments and asking the node to do the parsing.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/492
|
||||
|
||||
**Suggested Action**: Defer until after foxy.
|
||||
|
||||
**Notes from 2020-03-23**:
|
||||
|
||||
- (dirk) may be related to ROS 1 heritage of argc/argv being passed to node directly
|
||||
- (shane) impacts rcl API as well, two parts "global options" as well node specific options
|
||||
- (dirk) what is the recommendation to users that want to add arguments programmatically
|
||||
- user should be able to get non-ros argc/argv somehow (seems like you can now)
|
||||
- (jacob) the argument in NodeOptions are used for application specific argument via component loading as well
|
||||
|
||||
## Timer
|
||||
|
||||
### Timer based on ROS Time
|
||||
|
||||
> `node->create_wall_timer` does exactly what it says; creates a timer that will call the callback when the wall time expires. But this is almost never what the user wants, since this won’t work properly in simulation. Suggestion: deprecate `create_wall_timer`, add a new method called `create_timer` that takes the timer to use as one of the arguments, which defaults to ROS_TIME.
|
||||
|
||||
- https://github.com/ros2/rclcpp/blob/96ebf59a6045a535730d98fff25e522807c7aa75/rclcpp/include/rclcpp/node.hpp#L219-L230
|
||||
- https://github.com/ros2/rclcpp/issues/465
|
||||
|
||||
**Suggested Action**: Promote `rclcpp::create_timer()` which is templated on a clock type, as suggested, but leave `create_wall_timer` as a convenience.
|
||||
|
||||
**Notes from 2020-03-19**:
|
||||
|
||||
- (shane) may be a `rclcpp::create_timer()` that can be used to create a non-wall timer already
|
||||
|
||||
## Publisher
|
||||
|
||||
## Subscription
|
||||
|
||||
### Callback Signature
|
||||
|
||||
> Is there a reason the subscription callback must have a smart pointer argument instead of accepting a const-reference argument?
|
||||
|
||||
- https://github.com/ros2/rclcpp/blob/96ebf59a6045a535730d98fff25e522807c7aa75/rclcpp/include/rclcpp/any_subscription_callback.hpp#L44-L52
|
||||
- https://github.com/ros2/rclcpp/issues/281
|
||||
|
||||
**Suggested Action**: Provide const reference as an option, add documentation as to the implications of one callback signature versus others.
|
||||
|
||||
**Notes from 2020-03-19**:
|
||||
|
||||
- (dirk) have const reference and document it
|
||||
|
||||
## Service Server
|
||||
|
||||
### Allow for asynchronous Service Server callbacks
|
||||
|
||||
> Currently, the only callback signature for Service Servers takes a request and must return a response.
|
||||
> This means that all of the activity of the service server has to happen within that function.
|
||||
> This can cause issues, specifically if you want to call another service within the current service server's callback, as it causes deadlock issues trying to synchronously call the second service within a spin callback.
|
||||
> More generally, it seems likely that long running service server callbacks may be necessary in the future and requiring them to be synchronous would tie up at least on thread in the spinning executor unnecessarily.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/491
|
||||
|
||||
**Suggested Action**: Defer.
|
||||
|
||||
**Notes from 2020-03-23**:
|
||||
|
||||
- (dirk) likely new API, so possible to backport
|
||||
|
||||
## Service Client
|
||||
|
||||
### Callback has SharedFuture rather than const reference to response
|
||||
|
||||
> Why does the Client::send_async_request take in a callback that has a SharedFuture argument instead of an argument that is simply a const-reference (or smart pointer) to the service response type? The current API seems to imply that the callback ought to check whether the promise is broken or fulfilled before trying to access it. Is that the case? If so, it should be documented in the header.
|
||||
|
||||
- https://github.com/ros2/rclcpp/blob/7c1721a0b390be8242a6b824489d0bc861f6a0ad/rclcpp/include/rclcpp/client.hpp#L134
|
||||
|
||||
**Suggested Action**: Update ticket and defer.
|
||||
|
||||
**Notes from 2020-03-19**:
|
||||
|
||||
- (wjwwood) we wanted the user to handle error cases with the future?
|
||||
- (dirk) future allows for single callback (rather than one for response and one for error)
|
||||
- (jacob) actions uses a "wrapped result" object
|
||||
|
||||
### rclcpp missing synchronous `send_request` and issues with deadlocks
|
||||
|
||||
> This has been reported by several users, but there is only an `async_send_request` currently. `rclpy` has a synchronous `send_request` but it has issues with deadlock, specifically if you call it without spinning in another thread then it will deadlock. Or if you call it from within a spin callback when using a single threaded executor, it will deadlock.
|
||||
|
||||
- https://discourse.ros.org/t/synchronous-request-to-service-in-callback-results-in-deadlock/12767
|
||||
- https://github.com/ros2/rclcpp/issues/975
|
||||
- https://github.com/ros2/demos/blob/948b4f4869298f39cfe99d3ae517ad60a72a8909/demo_nodes_cpp/src/services/add_two_ints_client.cpp#L24-L39
|
||||
|
||||
**Suggested Action**: Update issue and defer. Also defer decision on reconciling rclpy's send_request.
|
||||
|
||||
**Notes from 2020-03-23**:
|
||||
|
||||
- (karsten/shane) async spinner helps in rclpy version, rclcpp could emulate
|
||||
- (chris) sees three options:
|
||||
- only async (current case in rclcpp)
|
||||
- have sync version, add lots of docs that spinning needs to happen elsewhere (current case for rclpy)
|
||||
- reentrant spinning
|
||||
- (william) you either need async/await from language or ".then" syntax (we have this in async_send_request())
|
||||
- (chris) more error checking for recursive spinning
|
||||
- (chris) weird that rclcpp and rclpy have different API
|
||||
- (shane) thinks it is ok to have different API, but rclpy is not ideal
|
||||
|
||||
## Parameters
|
||||
|
||||
### Expected vs Unexpected parameters
|
||||
|
||||
> Allow node author to define expected parameters and what happens when an unexpected parameter is set.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/475
|
||||
- https://github.com/ros2/rclcpp/tree/check_parameters
|
||||
|
||||
**Suggested Action**: Defer as nice to have.
|
||||
|
||||
**Notes from 2020-03-23**:
|
||||
|
||||
- None.
|
||||
|
||||
### Implicitly cast integer values for double parameters
|
||||
|
||||
> If we try to pass an integer value to a double parameter from the command line or from a parameters YAML file we get a `rclcpp::ParameterTypeException`.
|
||||
> For example, passing a parameter from the command line:
|
||||
>
|
||||
> ros2 run foo_package foo_node --ros-args -p foo_arg:=1
|
||||
>
|
||||
> results in the following error:
|
||||
>
|
||||
> terminate called after throwing an instance of 'rclcpp::ParameterTypeException'
|
||||
> what(): expected [double] got [integer]
|
||||
>
|
||||
> and we can fix it by explicitly making our value a floating point number:
|
||||
>
|
||||
> ros2 run foo_package foo_node --ros-args -p foo_arg:=1.0
|
||||
>
|
||||
> But, it seems reasonable to me that if a user forgets to explicitly provide a floating point value that we should implicitly cast an integer to a float (as is done in many programming languages).
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/979
|
||||
|
||||
**Suggested Action**: Continue with issue.
|
||||
|
||||
**Notes from 2020-03-23**:
|
||||
|
||||
- (shane) says "yes please" :)
|
||||
|
||||
### Use `std::variant` instead of custom `ParameterValue` class
|
||||
|
||||
> This is only possible if C++17 is available, but it would simplify our code, make our interface more standard, and allow us to use constexpr-if to simply our templated code.
|
||||
|
||||
**Suggested Action**: Create an issue for future work.
|
||||
|
||||
**Notes from 2020-03-23**:
|
||||
|
||||
- (chris) not sure churn is worth
|
||||
- (ivan) other places for std::variant, like AnySubscriptionCallback
|
||||
|
||||
### Cannot set name or value on `Parameter`/`ParameterValue`
|
||||
|
||||
> Both `Parameter` and `ParameterValue` are read-only after construction.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/238
|
||||
|
||||
**Suggested Action**: Update issue, possibly close.
|
||||
|
||||
**Notes from 2020-03-23**:
|
||||
|
||||
- (chris/william) setting values on temporary (local) objects is not reflected in the node, so misleading
|
||||
|
||||
## Parameter Clients
|
||||
|
||||
### No timeout option with synchronous parameter client calls
|
||||
|
||||
> As an example, SyncParametersClient::set_parameters doesn't take a timeout option. So, if anything goes wrong in the service call (e.g. the server goes down), we will get stuck waiting indefinitely.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/360
|
||||
- https://github.com/ros2/rclcpp/blob/96ebf59a6045a535730d98fff25e522807c7aa75/rclcpp/src/rclcpp/parameter_client.cpp#L453-L468
|
||||
|
||||
**Suggested Action**: Update issue, decide if it can be taken for Foxy or not.
|
||||
|
||||
**Notes from 2020-03-23**:
|
||||
|
||||
- (tfoote) Seems like adding a timeout is a good idea.
|
||||
|
||||
### Name of AsyncParametersClient inconsistent
|
||||
|
||||
> AsyncParameter**s**Client uses plural, when filename is singular (and ParameterService is singular):
|
||||
|
||||
- https://github.com/ros2/rclcpp/blob/7c1721a0b390be8242a6b824489d0bc861f6a0ad/rclcpp/include/rclcpp/parameter_client.hpp#L44
|
||||
|
||||
**Suggested Action**: Reconcile class and file name, switch to singular name?
|
||||
|
||||
**Notes from on-line, post 2020-03-23 meeting**:
|
||||
|
||||
- (tfoote) +1 for homogenizing to singular
|
||||
|
||||
### `SyncParametersClient::get_parameters` doesn't allow you to detect error cases
|
||||
|
||||
> E.g. https://github.com/ros2/rclcpp/blob/249b7d80d8f677edcda05052f598de84f4c2181c/rclcpp/src/rclcpp/parameter_client.cpp#L246-L257 returns an empty vector if something goes wrong which is also a valid response.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/200
|
||||
- https://github.com/ros2/rclcpp/blob/96ebf59a6045a535730d98fff25e522807c7aa75/rclcpp/src/rclcpp/parameter_client.cpp#L412-L426
|
||||
|
||||
**Suggested Action**: Throw an exception to indicate if something went wrong and document other expected conditions of the API.
|
||||
|
||||
**Notes from on-line, post 2020-03-23 meeting**:
|
||||
|
||||
- (tfoote) An empty list is not a valid response unless you passed in an empty list. The return should have the same length as the request in the same order. Any parameters that are not set should return a ParameterVariant with type PARAMETER_NOT_SET. to indicate that it was polled and determined to not be set. Suggested action improve documentation of the API to clarify a short or incomplete.
|
||||
- (jacobperron) I think throwing an exception is also a valid action, making it clear that an error occurred.
|
||||
- (wjwwood) Using exceptions to indicate an exceptional case (something went wrong) seems reasonable to me too.
|
||||
|
||||
## Clock
|
||||
|
||||
### Clock Jump callbacks on System or Steady time?
|
||||
|
||||
> Currently time jump callbacks are registered via Clock::create_jump_handler(). Jump handlers are only invoked by TimeSource::set_clock(). This is only called if the clock type is RCL_ROS_TIME and ROS time is active.
|
||||
|
||||
- https://github.com/ros2/rclcpp/issues/528
|
||||
|
||||
**Suggested Action**: Document that time jumping is only detected with ROS time, consider a warning.
|
||||
|
||||
**Notes from on-line, post 2020-03-23 meeting**:
|
||||
|
||||
- (tfoote) There should be no jumps in steady time. If there's a big change in system time, it doesn't necessarily mean that time jumped, just that you might have been sleeping for a long time. Most ntp systems adjust the slew rate these days instead of jumping but still that's an external process and I don't know of any APIs to introspect the state of the clock. I'm not sure that we have a way to detect jumps in time for system or steady time. To that end I think that we should be clear that we only provide callbacks when simulation time starts or stops, or simulation time jumps. We should also strongly recommend that operators not actively adjust their system clocks while running ROS nodes.
|
||||
- (jacobperron) I agree with Tully, if we don't have a way to detect system time jumps then I think we should just document that this only works with ROS time. In addition to documentation, we could log an info or warning message if the user registers jump callback with steady or system time, but it may be unnecessarily noisy.
|
||||
|
||||
@@ -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));
|
||||
```
|
||||
@@ -29,6 +29,8 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace executor
|
||||
{
|
||||
|
||||
struct AnyExecutable
|
||||
{
|
||||
@@ -40,16 +42,17 @@ struct AnyExecutable
|
||||
|
||||
// Only one of the following pointers will be set.
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription;
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription_intra_process;
|
||||
rclcpp::TimerBase::SharedPtr timer;
|
||||
rclcpp::ServiceBase::SharedPtr service;
|
||||
rclcpp::ClientBase::SharedPtr client;
|
||||
rclcpp::Waitable::SharedPtr waitable;
|
||||
// These are used to keep the scope on the containing items
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group;
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base;
|
||||
std::shared_ptr<void> data;
|
||||
};
|
||||
|
||||
} // namespace executor
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__ANY_EXECUTABLE_HPP_
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
#include "rclcpp/function_traits.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rmw/types.h"
|
||||
#include "tracetools/tracetools.h"
|
||||
#include "tracetools/utils.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
@@ -88,7 +86,6 @@ public:
|
||||
std::shared_ptr<typename ServiceT::Request> request,
|
||||
std::shared_ptr<typename ServiceT::Response> response)
|
||||
{
|
||||
TRACEPOINT(callback_start, static_cast<const void *>(this), false);
|
||||
if (shared_ptr_callback_ != nullptr) {
|
||||
(void)request_header;
|
||||
shared_ptr_callback_(request, response);
|
||||
@@ -97,24 +94,6 @@ public:
|
||||
} else {
|
||||
throw std::runtime_error("unexpected request without any callback set");
|
||||
}
|
||||
TRACEPOINT(callback_end, static_cast<const void *>(this));
|
||||
}
|
||||
|
||||
void register_callback_for_tracing()
|
||||
{
|
||||
#ifndef TRACETOOLS_DISABLED
|
||||
if (shared_ptr_callback_) {
|
||||
TRACEPOINT(
|
||||
rclcpp_callback_register,
|
||||
static_cast<const void *>(this),
|
||||
tracetools::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_));
|
||||
}
|
||||
#endif // TRACETOOLS_DISABLED
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,394 +15,214 @@
|
||||
#ifndef RCLCPP__ANY_SUBSCRIPTION_CALLBACK_HPP_
|
||||
#define RCLCPP__ANY_SUBSCRIPTION_CALLBACK_HPP_
|
||||
|
||||
#include <rmw/types.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <variant> // NOLINT[build/include_order]
|
||||
|
||||
#include "tracetools/tracetools.h"
|
||||
#include "tracetools/utils.hpp"
|
||||
|
||||
#include "rclcpp/allocator/allocator_common.hpp"
|
||||
#include "rclcpp/detail/subscription_callback_type_helper.hpp"
|
||||
#include "rclcpp/function_traits.hpp"
|
||||
#include "rclcpp/message_info.hpp"
|
||||
|
||||
template<class>
|
||||
inline constexpr bool always_false_v = false;
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename MessageT, typename AllocatorT>
|
||||
struct MessageDeleterHelper
|
||||
{
|
||||
using MessageAllocTraits = allocator::AllocRebind<MessageT, AllocatorT>;
|
||||
using MessageAlloc = typename MessageAllocTraits::allocator_type;
|
||||
using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;
|
||||
};
|
||||
|
||||
template<typename MessageT, typename AllocatorT>
|
||||
struct AnySubscriptionCallbackHelper
|
||||
{
|
||||
using MessageDeleter = typename MessageDeleterHelper<MessageT, AllocatorT>::MessageDeleter;
|
||||
|
||||
using ConstRefCallback =
|
||||
std::function<void (const MessageT &)>;
|
||||
using ConstRefWithInfoCallback =
|
||||
std::function<void (const MessageT &, const rclcpp::MessageInfo &)>;
|
||||
|
||||
using UniquePtrCallback =
|
||||
std::function<void (std::unique_ptr<MessageT, MessageDeleter>)>;
|
||||
using UniquePtrWithInfoCallback =
|
||||
std::function<void (std::unique_ptr<MessageT, MessageDeleter>, const rclcpp::MessageInfo &)>;
|
||||
|
||||
using SharedConstPtrCallback =
|
||||
std::function<void (std::shared_ptr<const MessageT>)>;
|
||||
using SharedConstPtrWithInfoCallback =
|
||||
std::function<void (std::shared_ptr<const MessageT>, const rclcpp::MessageInfo &)>;
|
||||
|
||||
using ConstRefSharedConstPtrCallback =
|
||||
std::function<void (const std::shared_ptr<const MessageT> &)>;
|
||||
using ConstRefSharedConstPtrWithInfoCallback =
|
||||
std::function<void (const std::shared_ptr<const MessageT> &, const rclcpp::MessageInfo &)>;
|
||||
|
||||
// Deprecated signatures:
|
||||
using SharedPtrCallback =
|
||||
std::function<void (std::shared_ptr<MessageT>)>;
|
||||
using SharedPtrWithInfoCallback =
|
||||
std::function<void (std::shared_ptr<MessageT>, const rclcpp::MessageInfo &)>;
|
||||
|
||||
using variant_type = std::variant<
|
||||
ConstRefCallback,
|
||||
ConstRefWithInfoCallback,
|
||||
UniquePtrCallback,
|
||||
UniquePtrWithInfoCallback,
|
||||
SharedConstPtrCallback,
|
||||
SharedConstPtrWithInfoCallback,
|
||||
ConstRefSharedConstPtrCallback,
|
||||
ConstRefSharedConstPtrWithInfoCallback,
|
||||
SharedPtrCallback,
|
||||
SharedPtrWithInfoCallback
|
||||
>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
typename AllocatorT = std::allocator<void>
|
||||
>
|
||||
template<typename MessageT, typename Alloc>
|
||||
class AnySubscriptionCallback
|
||||
{
|
||||
private:
|
||||
using HelperT = typename rclcpp::detail::AnySubscriptionCallbackHelper<MessageT, AllocatorT>;
|
||||
using MessageDeleterHelper = rclcpp::detail::MessageDeleterHelper<MessageT, AllocatorT>;
|
||||
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
|
||||
using MessageAlloc = typename MessageAllocTraits::allocator_type;
|
||||
using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;
|
||||
using ConstMessageSharedPtr = std::shared_ptr<const MessageT>;
|
||||
using MessageUniquePtr = std::unique_ptr<MessageT, MessageDeleter>;
|
||||
|
||||
using MessageAllocTraits = typename MessageDeleterHelper::MessageAllocTraits;
|
||||
using MessageAlloc = typename MessageDeleterHelper::MessageAlloc;
|
||||
using MessageDeleter = typename MessageDeleterHelper::MessageDeleter;
|
||||
using SharedPtrCallback = std::function<void (const std::shared_ptr<MessageT>)>;
|
||||
using SharedPtrWithInfoCallback =
|
||||
std::function<void (const std::shared_ptr<MessageT>, const rmw_message_info_t &)>;
|
||||
using ConstSharedPtrCallback = std::function<void (const std::shared_ptr<const MessageT>)>;
|
||||
using ConstSharedPtrWithInfoCallback =
|
||||
std::function<void (const std::shared_ptr<const MessageT>, const rmw_message_info_t &)>;
|
||||
using UniquePtrCallback = std::function<void (MessageUniquePtr)>;
|
||||
using UniquePtrWithInfoCallback =
|
||||
std::function<void (MessageUniquePtr, const rmw_message_info_t &)>;
|
||||
|
||||
// See AnySubscriptionCallbackHelper for the types of these.
|
||||
using ConstRefCallback = typename HelperT::ConstRefCallback;
|
||||
using ConstRefWithInfoCallback = typename HelperT::ConstRefWithInfoCallback;
|
||||
|
||||
using UniquePtrCallback = typename HelperT::UniquePtrCallback;
|
||||
using UniquePtrWithInfoCallback = typename HelperT::UniquePtrWithInfoCallback;
|
||||
|
||||
using SharedConstPtrCallback = typename HelperT::SharedConstPtrCallback;
|
||||
using SharedConstPtrWithInfoCallback = typename HelperT::SharedConstPtrWithInfoCallback;
|
||||
|
||||
using ConstRefSharedConstPtrCallback =
|
||||
typename HelperT::ConstRefSharedConstPtrCallback;
|
||||
using ConstRefSharedConstPtrWithInfoCallback =
|
||||
typename HelperT::ConstRefSharedConstPtrWithInfoCallback;
|
||||
|
||||
using SharedPtrCallback = typename HelperT::SharedPtrCallback;
|
||||
using SharedPtrWithInfoCallback = typename HelperT::SharedPtrWithInfoCallback;
|
||||
SharedPtrCallback shared_ptr_callback_;
|
||||
SharedPtrWithInfoCallback shared_ptr_with_info_callback_;
|
||||
ConstSharedPtrCallback const_shared_ptr_callback_;
|
||||
ConstSharedPtrWithInfoCallback const_shared_ptr_with_info_callback_;
|
||||
UniquePtrCallback unique_ptr_callback_;
|
||||
UniquePtrWithInfoCallback unique_ptr_with_info_callback_;
|
||||
|
||||
public:
|
||||
explicit
|
||||
AnySubscriptionCallback(const AllocatorT & allocator = AllocatorT()) // NOLINT[runtime/explicit]
|
||||
explicit AnySubscriptionCallback(std::shared_ptr<Alloc> allocator)
|
||||
: shared_ptr_callback_(nullptr), shared_ptr_with_info_callback_(nullptr),
|
||||
const_shared_ptr_callback_(nullptr), const_shared_ptr_with_info_callback_(nullptr),
|
||||
unique_ptr_callback_(nullptr), unique_ptr_with_info_callback_(nullptr)
|
||||
{
|
||||
message_allocator_ = allocator;
|
||||
allocator::set_allocator_for_deleter(&message_deleter_, &message_allocator_);
|
||||
}
|
||||
|
||||
[[deprecated("use AnySubscriptionCallback(const AllocatorT & allocator) instead")]]
|
||||
explicit
|
||||
AnySubscriptionCallback(std::shared_ptr<AllocatorT> allocator) // NOLINT[runtime/explicit]
|
||||
{
|
||||
if (allocator == nullptr) {
|
||||
throw std::runtime_error("invalid allocator");
|
||||
}
|
||||
message_allocator_ = *allocator;
|
||||
allocator::set_allocator_for_deleter(&message_deleter_, &message_allocator_);
|
||||
message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
|
||||
allocator::set_allocator_for_deleter(&message_deleter_, message_allocator_.get());
|
||||
}
|
||||
|
||||
AnySubscriptionCallback(const AnySubscriptionCallback &) = default;
|
||||
|
||||
/// Generic function for setting the callback.
|
||||
/**
|
||||
* There are specializations that overload this in order to deprecate some
|
||||
* callback signatures, and also to fix ambiguity between shared_ptr and
|
||||
* unique_ptr callback signatures when using them with lambda functions.
|
||||
*/
|
||||
template<typename CallbackT>
|
||||
AnySubscriptionCallback<MessageT, AllocatorT>
|
||||
set(CallbackT callback)
|
||||
{
|
||||
// Use the SubscriptionCallbackTypeHelper to determine the actual type of
|
||||
// the CallbackT, in terms of std::function<...>, which does not happen
|
||||
// automatically with lambda functions in cases where the arguments can be
|
||||
// converted to one another, e.g. shared_ptr and unique_ptr.
|
||||
using scbth = detail::SubscriptionCallbackTypeHelper<MessageT, CallbackT>;
|
||||
|
||||
// Determine if the given CallbackT is a deprecated signature or not.
|
||||
constexpr auto is_deprecated =
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
typename scbth::callback_type,
|
||||
std::function<void(std::shared_ptr<MessageT>)>
|
||||
CallbackT,
|
||||
SharedPtrCallback
|
||||
>::value
|
||||
||
|
||||
>::type * = nullptr
|
||||
>
|
||||
void set(CallbackT callback)
|
||||
{
|
||||
shared_ptr_callback_ = callback;
|
||||
}
|
||||
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
typename scbth::callback_type,
|
||||
std::function<void(std::shared_ptr<MessageT>, const rclcpp::MessageInfo &)>
|
||||
>::value;
|
||||
CallbackT,
|
||||
SharedPtrWithInfoCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
void set(CallbackT callback)
|
||||
{
|
||||
shared_ptr_with_info_callback_ = callback;
|
||||
}
|
||||
|
||||
// Use the discovered type to force the type of callback when assigning
|
||||
// into the variant.
|
||||
if constexpr (is_deprecated) {
|
||||
// If deprecated, call sub-routine that is deprecated.
|
||||
set_deprecated(static_cast<typename scbth::callback_type>(callback));
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
CallbackT,
|
||||
ConstSharedPtrCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
void set(CallbackT callback)
|
||||
{
|
||||
const_shared_ptr_callback_ = callback;
|
||||
}
|
||||
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
CallbackT,
|
||||
ConstSharedPtrWithInfoCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
void set(CallbackT callback)
|
||||
{
|
||||
const_shared_ptr_with_info_callback_ = callback;
|
||||
}
|
||||
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
CallbackT,
|
||||
UniquePtrCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
void set(CallbackT callback)
|
||||
{
|
||||
unique_ptr_callback_ = callback;
|
||||
}
|
||||
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename std::enable_if<
|
||||
rclcpp::function_traits::same_arguments<
|
||||
CallbackT,
|
||||
UniquePtrWithInfoCallback
|
||||
>::value
|
||||
>::type * = nullptr
|
||||
>
|
||||
void set(CallbackT callback)
|
||||
{
|
||||
unique_ptr_with_info_callback_ = callback;
|
||||
}
|
||||
|
||||
void dispatch(
|
||||
std::shared_ptr<MessageT> message, const rmw_message_info_t & message_info)
|
||||
{
|
||||
if (shared_ptr_callback_) {
|
||||
shared_ptr_callback_(message);
|
||||
} else if (shared_ptr_with_info_callback_) {
|
||||
shared_ptr_with_info_callback_(message, message_info);
|
||||
} else if (const_shared_ptr_callback_) {
|
||||
const_shared_ptr_callback_(message);
|
||||
} else if (const_shared_ptr_with_info_callback_) {
|
||||
const_shared_ptr_with_info_callback_(message, message_info);
|
||||
} else if (unique_ptr_callback_) {
|
||||
auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
|
||||
MessageAllocTraits::construct(*message_allocator_.get(), ptr, *message);
|
||||
unique_ptr_callback_(MessageUniquePtr(ptr, message_deleter_));
|
||||
} else if (unique_ptr_with_info_callback_) {
|
||||
auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
|
||||
MessageAllocTraits::construct(*message_allocator_.get(), ptr, *message);
|
||||
unique_ptr_with_info_callback_(MessageUniquePtr(ptr, message_deleter_), message_info);
|
||||
} else {
|
||||
// Otherwise just assign it.
|
||||
callback_variant_ = static_cast<typename scbth::callback_type>(callback);
|
||||
throw std::runtime_error("unexpected message without any callback set");
|
||||
}
|
||||
|
||||
// Return copy of self for easier testing, normally will be compiled out.
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Function for shared_ptr to non-const MessageT, which is deprecated.
|
||||
// TODO(wjwwood): enable this deprecation after Galactic
|
||||
// [[deprecated(
|
||||
// "use 'void (std::shared_ptr<const MessageT>)' instead"
|
||||
// )]]
|
||||
void
|
||||
set_deprecated(std::function<void(std::shared_ptr<MessageT>)> callback)
|
||||
// set(CallbackT callback)
|
||||
void dispatch_intra_process(
|
||||
ConstMessageSharedPtr message, const rmw_message_info_t & message_info)
|
||||
{
|
||||
callback_variant_ = callback;
|
||||
}
|
||||
|
||||
/// Function for shared_ptr to non-const MessageT with MessageInfo, which is deprecated.
|
||||
// TODO(wjwwood): enable this deprecation after Galactic
|
||||
// [[deprecated(
|
||||
// "use 'void (std::shared_ptr<const MessageT>, const rclcpp::MessageInfo &)' instead"
|
||||
// )]]
|
||||
void
|
||||
set_deprecated(
|
||||
std::function<void(std::shared_ptr<MessageT>, const rclcpp::MessageInfo &)> callback)
|
||||
{
|
||||
callback_variant_ = callback;
|
||||
}
|
||||
|
||||
std::unique_ptr<MessageT, MessageDeleter>
|
||||
create_unique_ptr_from_shared_ptr_message(const std::shared_ptr<const MessageT> & message)
|
||||
{
|
||||
auto ptr = MessageAllocTraits::allocate(message_allocator_, 1);
|
||||
MessageAllocTraits::construct(message_allocator_, ptr, *message);
|
||||
return std::unique_ptr<MessageT, MessageDeleter>(ptr, message_deleter_);
|
||||
}
|
||||
|
||||
void
|
||||
dispatch(
|
||||
std::shared_ptr<MessageT> message,
|
||||
const rclcpp::MessageInfo & message_info)
|
||||
{
|
||||
TRACEPOINT(callback_start, static_cast<const void *>(this), false);
|
||||
// Check if the variant is "unset", throw if it is.
|
||||
if (callback_variant_.index() == 0) {
|
||||
if (std::get<0>(callback_variant_) == nullptr) {
|
||||
// This can happen if it is default initialized, or if it is assigned nullptr.
|
||||
throw std::runtime_error("dispatch called on an unset AnySubscriptionCallback");
|
||||
if (const_shared_ptr_callback_) {
|
||||
const_shared_ptr_callback_(message);
|
||||
} else if (const_shared_ptr_with_info_callback_) {
|
||||
const_shared_ptr_with_info_callback_(message, message_info);
|
||||
} else {
|
||||
if (unique_ptr_callback_ || unique_ptr_with_info_callback_ ||
|
||||
shared_ptr_callback_ || shared_ptr_with_info_callback_)
|
||||
{
|
||||
throw std::runtime_error("unexpected dispatch_intra_process const shared "
|
||||
"message call with no const shared_ptr callback");
|
||||
} else {
|
||||
throw std::runtime_error("unexpected message without any callback set");
|
||||
}
|
||||
}
|
||||
// Dispatch.
|
||||
std::visit(
|
||||
[&message, &message_info, this](auto && callback) {
|
||||
using T = std::decay_t<decltype(callback)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, ConstRefCallback>) {
|
||||
callback(*message);
|
||||
} else if constexpr (std::is_same_v<T, ConstRefWithInfoCallback>) {
|
||||
callback(*message, message_info);
|
||||
} else if constexpr (std::is_same_v<T, UniquePtrCallback>) {
|
||||
callback(create_unique_ptr_from_shared_ptr_message(message));
|
||||
} else if constexpr (std::is_same_v<T, UniquePtrWithInfoCallback>) {
|
||||
callback(create_unique_ptr_from_shared_ptr_message(message), message_info);
|
||||
} else if constexpr ( // NOLINT[readability/braces]
|
||||
std::is_same_v<T, SharedConstPtrCallback>||
|
||||
std::is_same_v<T, ConstRefSharedConstPtrCallback>||
|
||||
std::is_same_v<T, SharedPtrCallback>)
|
||||
{
|
||||
callback(message);
|
||||
} else if constexpr ( // NOLINT[readability/braces]
|
||||
std::is_same_v<T, SharedConstPtrWithInfoCallback>||
|
||||
std::is_same_v<T, ConstRefSharedConstPtrWithInfoCallback>||
|
||||
std::is_same_v<T, SharedPtrWithInfoCallback>)
|
||||
{
|
||||
callback(message, message_info);
|
||||
} else {
|
||||
static_assert(always_false_v<T>, "unhandled callback type");
|
||||
}
|
||||
}, callback_variant_);
|
||||
TRACEPOINT(callback_end, static_cast<const void *>(this));
|
||||
}
|
||||
|
||||
void
|
||||
dispatch_intra_process(
|
||||
std::shared_ptr<const MessageT> message,
|
||||
const rclcpp::MessageInfo & message_info)
|
||||
void dispatch_intra_process(
|
||||
MessageUniquePtr message, const rmw_message_info_t & message_info)
|
||||
{
|
||||
TRACEPOINT(callback_start, static_cast<const void *>(this), true);
|
||||
// Check if the variant is "unset", throw if it is.
|
||||
if (callback_variant_.index() == 0) {
|
||||
if (std::get<0>(callback_variant_) == nullptr) {
|
||||
// This can happen if it is default initialized, or if it is assigned nullptr.
|
||||
throw std::runtime_error("dispatch called on an unset AnySubscriptionCallback");
|
||||
}
|
||||
if (shared_ptr_callback_) {
|
||||
typename std::shared_ptr<MessageT> shared_message = std::move(message);
|
||||
shared_ptr_callback_(shared_message);
|
||||
} else if (shared_ptr_with_info_callback_) {
|
||||
typename std::shared_ptr<MessageT> shared_message = std::move(message);
|
||||
shared_ptr_with_info_callback_(shared_message, message_info);
|
||||
} else if (unique_ptr_callback_) {
|
||||
unique_ptr_callback_(std::move(message));
|
||||
} else if (unique_ptr_with_info_callback_) {
|
||||
unique_ptr_with_info_callback_(std::move(message), message_info);
|
||||
} else if (const_shared_ptr_callback_ || const_shared_ptr_with_info_callback_) {
|
||||
throw std::runtime_error("unexpected dispatch_intra_process unique message call"
|
||||
" with const shared_ptr callback");
|
||||
} else {
|
||||
throw std::runtime_error("unexpected message without any callback set");
|
||||
}
|
||||
// Dispatch.
|
||||
std::visit(
|
||||
[&message, &message_info, this](auto && callback) {
|
||||
using T = std::decay_t<decltype(callback)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, ConstRefCallback>) {
|
||||
callback(*message);
|
||||
} else if constexpr (std::is_same_v<T, ConstRefWithInfoCallback>) {
|
||||
callback(*message, message_info);
|
||||
} else if constexpr ( // NOLINT[readability/braces]
|
||||
std::is_same_v<T, UniquePtrCallback>||
|
||||
std::is_same_v<T, SharedPtrCallback>)
|
||||
{
|
||||
callback(create_unique_ptr_from_shared_ptr_message(message));
|
||||
} else if constexpr ( // NOLINT[readability/braces]
|
||||
std::is_same_v<T, UniquePtrWithInfoCallback>||
|
||||
std::is_same_v<T, SharedPtrWithInfoCallback>)
|
||||
{
|
||||
callback(create_unique_ptr_from_shared_ptr_message(message), message_info);
|
||||
} else if constexpr ( // NOLINT[readability/braces]
|
||||
std::is_same_v<T, SharedConstPtrCallback>||
|
||||
std::is_same_v<T, ConstRefSharedConstPtrCallback>)
|
||||
{
|
||||
callback(message);
|
||||
} else if constexpr ( // NOLINT[readability/braces]
|
||||
std::is_same_v<T, SharedConstPtrWithInfoCallback>||
|
||||
std::is_same_v<T, ConstRefSharedConstPtrWithInfoCallback>)
|
||||
{
|
||||
callback(message, message_info);
|
||||
} else {
|
||||
static_assert(always_false_v<T>, "unhandled callback type");
|
||||
}
|
||||
}, callback_variant_);
|
||||
TRACEPOINT(callback_end, static_cast<const void *>(this));
|
||||
}
|
||||
|
||||
void
|
||||
dispatch_intra_process(
|
||||
std::unique_ptr<MessageT, MessageDeleter> message,
|
||||
const rclcpp::MessageInfo & message_info)
|
||||
bool use_take_shared_method()
|
||||
{
|
||||
TRACEPOINT(callback_start, static_cast<const void *>(this), true);
|
||||
// Check if the variant is "unset", throw if it is.
|
||||
if (callback_variant_.index() == 0) {
|
||||
if (std::get<0>(callback_variant_) == nullptr) {
|
||||
// This can happen if it is default initialized, or if it is assigned nullptr.
|
||||
throw std::runtime_error("dispatch called on an unset AnySubscriptionCallback");
|
||||
}
|
||||
}
|
||||
// Dispatch.
|
||||
std::visit(
|
||||
[&message, &message_info](auto && callback) {
|
||||
using T = std::decay_t<decltype(callback)>;
|
||||
|
||||
if constexpr (std::is_same_v<T, ConstRefCallback>) {
|
||||
callback(*message);
|
||||
} else if constexpr (std::is_same_v<T, ConstRefWithInfoCallback>) {
|
||||
callback(*message, message_info);
|
||||
} else if constexpr ( // NOLINT[readability/braces]
|
||||
std::is_same_v<T, UniquePtrCallback>||
|
||||
std::is_same_v<T, SharedConstPtrCallback>||
|
||||
std::is_same_v<T, ConstRefSharedConstPtrCallback>||
|
||||
std::is_same_v<T, SharedPtrCallback>)
|
||||
{
|
||||
callback(std::move(message));
|
||||
} else if constexpr ( // NOLINT[readability/braces]
|
||||
std::is_same_v<T, UniquePtrWithInfoCallback>||
|
||||
std::is_same_v<T, SharedConstPtrWithInfoCallback>||
|
||||
std::is_same_v<T, ConstRefSharedConstPtrWithInfoCallback>||
|
||||
std::is_same_v<T, SharedPtrWithInfoCallback>)
|
||||
{
|
||||
callback(std::move(message), message_info);
|
||||
} else {
|
||||
static_assert(always_false_v<T>, "unhandled callback type");
|
||||
}
|
||||
}, callback_variant_);
|
||||
TRACEPOINT(callback_end, static_cast<const void *>(this));
|
||||
}
|
||||
|
||||
constexpr
|
||||
bool
|
||||
use_take_shared_method() const
|
||||
{
|
||||
return
|
||||
std::holds_alternative<SharedConstPtrCallback>(callback_variant_) ||
|
||||
std::holds_alternative<SharedConstPtrWithInfoCallback>(callback_variant_) ||
|
||||
std::holds_alternative<ConstRefSharedConstPtrCallback>(callback_variant_) ||
|
||||
std::holds_alternative<ConstRefSharedConstPtrWithInfoCallback>(callback_variant_);
|
||||
}
|
||||
|
||||
void
|
||||
register_callback_for_tracing()
|
||||
{
|
||||
#ifndef TRACETOOLS_DISABLED
|
||||
std::visit(
|
||||
[this](auto && callback) {
|
||||
TRACEPOINT(
|
||||
rclcpp_callback_register,
|
||||
static_cast<const void *>(this),
|
||||
tracetools::get_symbol(callback));
|
||||
}, callback_variant_);
|
||||
#endif // TRACETOOLS_DISABLED
|
||||
}
|
||||
|
||||
typename HelperT::variant_type &
|
||||
get_variant()
|
||||
{
|
||||
return callback_variant_;
|
||||
}
|
||||
|
||||
const typename HelperT::variant_type &
|
||||
get_variant() const
|
||||
{
|
||||
return callback_variant_;
|
||||
return const_shared_ptr_callback_ || const_shared_ptr_with_info_callback_;
|
||||
}
|
||||
|
||||
private:
|
||||
// TODO(wjwwood): switch to inheriting from std::variant (i.e. HelperT::variant_type) once
|
||||
// inheriting from std::variant is realistic (maybe C++23?), see:
|
||||
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2162r0.html
|
||||
// For now, compose the variant into this class as a private attribute.
|
||||
typename HelperT::variant_type callback_variant_;
|
||||
|
||||
MessageAlloc message_allocator_;
|
||||
std::shared_ptr<MessageAlloc> message_allocator_;
|
||||
MessageDeleter message_deleter_;
|
||||
};
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/client.hpp"
|
||||
#include "rclcpp/publisher_base.hpp"
|
||||
#include "rclcpp/publisher.hpp"
|
||||
#include "rclcpp/service.hpp"
|
||||
#include "rclcpp/subscription_base.hpp"
|
||||
#include "rclcpp/subscription.hpp"
|
||||
#include "rclcpp/timer.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rclcpp/waitable.hpp"
|
||||
@@ -40,6 +40,9 @@ class NodeTopics;
|
||||
class NodeWaitables;
|
||||
} // namespace node_interfaces
|
||||
|
||||
namespace callback_group
|
||||
{
|
||||
|
||||
enum class CallbackGroupType
|
||||
{
|
||||
MutuallyExclusive,
|
||||
@@ -56,79 +59,28 @@ 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
|
||||
find_subscription_ptrs_if(Function func) const
|
||||
{
|
||||
return _find_ptrs_if_impl<rclcpp::SubscriptionBase, Function>(func, subscription_ptrs_);
|
||||
}
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::SubscriptionBase::WeakPtr> &
|
||||
get_subscription_ptrs() const;
|
||||
|
||||
template<typename Function>
|
||||
rclcpp::TimerBase::SharedPtr
|
||||
find_timer_ptrs_if(Function func) const
|
||||
{
|
||||
return _find_ptrs_if_impl<rclcpp::TimerBase, Function>(func, timer_ptrs_);
|
||||
}
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::TimerBase::WeakPtr> &
|
||||
get_timer_ptrs() const;
|
||||
|
||||
template<typename Function>
|
||||
rclcpp::ServiceBase::SharedPtr
|
||||
find_service_ptrs_if(Function func) const
|
||||
{
|
||||
return _find_ptrs_if_impl<rclcpp::ServiceBase, Function>(func, service_ptrs_);
|
||||
}
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::ServiceBase::WeakPtr> &
|
||||
get_service_ptrs() const;
|
||||
|
||||
template<typename Function>
|
||||
rclcpp::ClientBase::SharedPtr
|
||||
find_client_ptrs_if(Function func) const
|
||||
{
|
||||
return _find_ptrs_if_impl<rclcpp::ClientBase, Function>(func, client_ptrs_);
|
||||
}
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::ClientBase::WeakPtr> &
|
||||
get_client_ptrs() const;
|
||||
|
||||
template<typename Function>
|
||||
rclcpp::Waitable::SharedPtr
|
||||
find_waitable_ptrs_if(Function func) const
|
||||
{
|
||||
return _find_ptrs_if_impl<rclcpp::Waitable, Function>(func, waitable_ptrs_);
|
||||
}
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::Waitable::WeakPtr> &
|
||||
get_waitable_ptrs() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::atomic_bool &
|
||||
@@ -138,31 +90,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,31 +124,15 @@ 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>
|
||||
typename TypeT::SharedPtr _find_ptrs_if_impl(
|
||||
Function func, const std::vector<typename TypeT::WeakPtr> & vect_ptrs) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
for (auto & weak_ptr : vect_ptrs) {
|
||||
auto ref_ptr = weak_ptr.lock();
|
||||
if (ref_ptr && func(ref_ptr)) {
|
||||
return ref_ptr;
|
||||
}
|
||||
}
|
||||
return typename TypeT::SharedPtr();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace callback_group
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CALLBACK_GROUP_HPP_
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#ifndef RCLCPP__CLIENT_HPP_
|
||||
#define RCLCPP__CLIENT_HPP_
|
||||
|
||||
#include <atomic>
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -63,64 +62,22 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~ClientBase();
|
||||
|
||||
/// Take the next response for this client as a type erased pointer.
|
||||
/**
|
||||
* The type erased pointer allows for this method to be used in a type
|
||||
* agnostic way along with ClientBase::create_response(),
|
||||
* ClientBase::create_request_header(), and ClientBase::handle_response().
|
||||
* The typed version of this can be used if the Service type is known,
|
||||
* \sa Client::take_response().
|
||||
*
|
||||
* \param[out] response_out The type erased pointer to a Service Response into
|
||||
* which the middleware will copy the response being taken.
|
||||
* \param[out] request_header_out The request header to be filled by the
|
||||
* middleware when taking, and which can be used to associte the response
|
||||
* to a specific request.
|
||||
* \returns true if the response was taken, otherwise false.
|
||||
* \throws rclcpp::exceptions::RCLError based exceptions if the underlying
|
||||
* rcl function fail.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
take_type_erased_response(void * response_out, rmw_request_id_t & request_header_out);
|
||||
|
||||
/// Return the name of the service.
|
||||
/** \return The name of the service. */
|
||||
RCLCPP_PUBLIC
|
||||
const char *
|
||||
get_service_name() const;
|
||||
|
||||
/// Return the rcl_client_t client handle in a std::shared_ptr.
|
||||
/**
|
||||
* This handle remains valid after the Client is destroyed.
|
||||
* The actual rcl client is not finalized until it is out of scope everywhere.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<rcl_client_t>
|
||||
get_client_handle();
|
||||
|
||||
/// Return the rcl_client_t client handle in a std::shared_ptr.
|
||||
/**
|
||||
* This handle remains valid after the Client is destroyed.
|
||||
* The actual rcl client is not finalized until it is out of scope everywhere.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<const rcl_client_t>
|
||||
get_client_handle() const;
|
||||
|
||||
/// Return if the service is ready.
|
||||
/**
|
||||
* \return `true` if the service is ready, `false` otherwise
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
service_is_ready() const;
|
||||
|
||||
/// Wait for a service to be ready.
|
||||
/**
|
||||
* \param timeout maximum time to wait
|
||||
* \return `true` if the service is ready and the timeout is not over, `false` otherwise
|
||||
*/
|
||||
template<typename RepT = int64_t, typename RatioT = std::milli>
|
||||
bool
|
||||
wait_for_service(
|
||||
@@ -136,20 +93,6 @@ public:
|
||||
virtual void handle_response(
|
||||
std::shared_ptr<rmw_request_id_t> request_header, std::shared_ptr<void> response) = 0;
|
||||
|
||||
/// Exchange the "in use by wait set" state for this client.
|
||||
/**
|
||||
* This is used to ensure this client is not used by multiple
|
||||
* wait sets at the same time.
|
||||
*
|
||||
* \param[in] in_use_state the new state to exchange into the state, true
|
||||
* indicates it is now in use by a wait set, and false is that it is no
|
||||
* longer in use by a wait set.
|
||||
* \returns the previous state.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
exchange_in_use_by_wait_set_state(bool in_use_state);
|
||||
|
||||
protected:
|
||||
RCLCPP_DISABLE_COPY(ClientBase)
|
||||
|
||||
@@ -170,8 +113,6 @@ protected:
|
||||
std::shared_ptr<rclcpp::Context> context_;
|
||||
|
||||
std::shared_ptr<rcl_client_t> client_handle_;
|
||||
|
||||
std::atomic<bool> in_use_by_wait_set_{false};
|
||||
};
|
||||
|
||||
template<typename ServiceT>
|
||||
@@ -195,17 +136,6 @@ public:
|
||||
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(Client)
|
||||
|
||||
/// Default constructor.
|
||||
/**
|
||||
* The constructor for a Client is almost never called directly.
|
||||
* Instead, clients should be instantiated through the function
|
||||
* rclcpp::create_client().
|
||||
*
|
||||
* \param[in] node_base NodeBaseInterface pointer that is used in part of the setup.
|
||||
* \param[in] node_graph The node graph interface of the corresponding node.
|
||||
* \param[in] service_name Name of the topic to publish to.
|
||||
* \param[in] client_options options for the subscription.
|
||||
*/
|
||||
Client(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
|
||||
@@ -241,39 +171,12 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
/// Take the next response for this client.
|
||||
/**
|
||||
* \sa ClientBase::take_type_erased_response().
|
||||
*
|
||||
* \param[out] response_out The reference to a Service Response into
|
||||
* which the middleware will copy the response being taken.
|
||||
* \param[out] request_header_out The request header to be filled by the
|
||||
* middleware when taking, and which can be used to associte the response
|
||||
* to a specific request.
|
||||
* \returns true if the response was taken, otherwise false.
|
||||
* \throws rclcpp::exceptions::RCLError based exceptions if the underlying
|
||||
* rcl function fail.
|
||||
*/
|
||||
bool
|
||||
take_response(typename ServiceT::Response & response_out, rmw_request_id_t & request_header_out)
|
||||
{
|
||||
return this->take_type_erased_response(&response_out, request_header_out);
|
||||
}
|
||||
|
||||
/// Create a shared pointer with the response type
|
||||
/**
|
||||
* \return shared pointer with the response type
|
||||
*/
|
||||
std::shared_ptr<void>
|
||||
create_response() override
|
||||
{
|
||||
return std::shared_ptr<void>(new typename ServiceT::Response());
|
||||
}
|
||||
|
||||
/// Create a shared pointer with a rmw_request_id_t
|
||||
/**
|
||||
* \return shared pointer with a rmw_request_id_t
|
||||
*/
|
||||
std::shared_ptr<rmw_request_id_t>
|
||||
create_request_header() override
|
||||
{
|
||||
@@ -282,11 +185,6 @@ public:
|
||||
return std::shared_ptr<rmw_request_id_t>(new rmw_request_id_t);
|
||||
}
|
||||
|
||||
/// Handle a server response
|
||||
/**
|
||||
* \param[in] request_header used to check if the secuence number is valid
|
||||
* \param[in] response message with the server response
|
||||
*/
|
||||
void
|
||||
handle_response(
|
||||
std::shared_ptr<rmw_request_id_t> request_header,
|
||||
@@ -361,8 +259,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);
|
||||
|
||||
@@ -16,16 +16,12 @@
|
||||
#define RCLCPP__CLOCK_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/time.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rcl/time.h"
|
||||
#include "rcutils/time.h"
|
||||
#include "rcutils/types/rcutils_ret.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
@@ -89,7 +85,6 @@ public:
|
||||
bool
|
||||
ros_time_is_active();
|
||||
|
||||
/// Return the rcl_clock_t clock handle
|
||||
RCLCPP_PUBLIC
|
||||
rcl_clock_t *
|
||||
get_clock_handle() noexcept;
|
||||
@@ -98,11 +93,6 @@ public:
|
||||
rcl_clock_type_t
|
||||
get_clock_type() const noexcept;
|
||||
|
||||
/// Get the clock's mutex
|
||||
RCLCPP_PUBLIC
|
||||
std::mutex &
|
||||
get_clock_mutex() noexcept;
|
||||
|
||||
// Add a callback to invoke if the jump threshold is exceeded.
|
||||
/**
|
||||
* These callback functions must remain valid as long as the
|
||||
@@ -136,14 +126,14 @@ 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);
|
||||
|
||||
/// Private internal storage
|
||||
class Impl;
|
||||
|
||||
std::shared_ptr<Impl> impl_;
|
||||
/// Internal storage backed by rcl
|
||||
rcl_clock_t rcl_clock_;
|
||||
friend TimeSource; /// Allow TimeSource to access the rcl_clock_ datatype.
|
||||
rcl_allocator_t allocator_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -45,20 +44,6 @@ public:
|
||||
: std::runtime_error("context is already initialized") {}
|
||||
};
|
||||
|
||||
/// 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.
|
||||
@@ -115,9 +100,6 @@ public:
|
||||
* \param[in] argv argument array which may contain arguments intended for ROS
|
||||
* \param[in] init_options initialization options for rclcpp and underlying layers
|
||||
* \throw ContextAlreadyInitialized if called if init is called more than once
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
* \throws std::runtime_error if the global logging configure mutex is NULL
|
||||
* \throws exceptions::UnknownROSArgsError if there are unknown ROS arguments
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
@@ -151,18 +133,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.
|
||||
/**
|
||||
@@ -182,14 +159,14 @@ public:
|
||||
*
|
||||
* \param[in] reason the description of why shutdown happened
|
||||
* \return true if shutdown was successful, false if context was already shutdown
|
||||
* \throw various exceptions derived from rclcpp::exceptions::RCLError, if rcl_shutdown fails
|
||||
* \throw various exceptions derived from RCLErrorBase, if rcl_shutdown fails
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
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 +192,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 +237,64 @@ 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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,29 +333,28 @@ 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_;
|
||||
|
||||
// Keep shared ownership of the global logging mutex.
|
||||
std::shared_ptr<std::recursive_mutex> logging_mutex_;
|
||||
|
||||
std::unordered_map<std::type_index, std::shared_ptr<void>> sub_contexts_;
|
||||
// This mutex is recursive so that the constructor of a sub context may
|
||||
// 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_;
|
||||
|
||||
/// Keep shared ownership of global vector of weak contexts
|
||||
std::shared_ptr<WeakContextsWrapper> weak_contexts_;
|
||||
/// 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_;
|
||||
};
|
||||
|
||||
/// Return a copy of the list of context shared pointers.
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace rclcpp
|
||||
{
|
||||
namespace contexts
|
||||
{
|
||||
namespace default_context
|
||||
{
|
||||
|
||||
class DefaultContext : public rclcpp::Context
|
||||
{
|
||||
@@ -36,6 +38,7 @@ RCLCPP_PUBLIC
|
||||
DefaultContext::SharedPtr
|
||||
get_global_default_context();
|
||||
|
||||
} // namespace default_context
|
||||
} // namespace contexts
|
||||
} // namespace rclcpp
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__CREATE_CLIENT_HPP_
|
||||
#define RCLCPP__CREATE_CLIENT_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_services_interface.hpp"
|
||||
#include "rmw/rmw.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Create a service client with a given type.
|
||||
/// \internal
|
||||
template<typename ServiceT>
|
||||
typename rclcpp::Client<ServiceT>::SharedPtr
|
||||
create_client(
|
||||
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
|
||||
std::shared_ptr<node_interfaces::NodeGraphInterface> node_graph,
|
||||
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
rcl_client_options_t options = rcl_client_get_default_options();
|
||||
options.qos = qos_profile;
|
||||
|
||||
auto cli = rclcpp::Client<ServiceT>::make_shared(
|
||||
node_base.get(),
|
||||
node_graph,
|
||||
service_name,
|
||||
options);
|
||||
|
||||
auto cli_base_ptr = std::dynamic_pointer_cast<rclcpp::ClientBase>(cli);
|
||||
node_services->add_client(cli_base_ptr, group);
|
||||
return cli;
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CREATE_CLIENT_HPP_
|
||||
@@ -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,70 +24,50 @@
|
||||
#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>
|
||||
typename PublisherT = ::rclcpp::Publisher<MessageT, AllocatorT>>
|
||||
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
|
||||
[[deprecated("use alternative rclcpp::create_publisher() signatures")]]
|
||||
std::shared_ptr<PublisherT>
|
||||
create_publisher(
|
||||
NodeParametersT & node_parameters,
|
||||
NodeTopicsT & node_topics,
|
||||
rclcpp::node_interfaces::NodeTopicsInterface * node_topics,
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos,
|
||||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::PublisherOptionsWithAllocator<AllocatorT>()
|
||||
)
|
||||
)
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
const PublisherEventCallbacks & event_callbacks,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
bool use_intra_process_comms,
|
||||
std::shared_ptr<AllocatorT> allocator)
|
||||
{
|
||||
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;
|
||||
auto publisher_options = rcl_publisher_get_default_options();
|
||||
publisher_options.qos = qos_profile;
|
||||
|
||||
// Create the publisher.
|
||||
auto pub = node_topics_interface->create_publisher(
|
||||
auto pub = node_topics->create_publisher(
|
||||
topic_name,
|
||||
rclcpp::create_publisher_factory<MessageT, AllocatorT, PublisherT>(options),
|
||||
actual_qos
|
||||
);
|
||||
rclcpp::create_publisher_factory<MessageT, AllocatorT, PublisherT>(event_callbacks, allocator),
|
||||
publisher_options,
|
||||
use_intra_process_comms);
|
||||
|
||||
// Add the publisher to the node topics interface.
|
||||
node_topics_interface->add_publisher(pub, options.callback_group);
|
||||
node_topics->add_publisher(pub, 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,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
typename PublisherT = rclcpp::Publisher<MessageT, AllocatorT>,
|
||||
typename PublisherT = ::rclcpp::Publisher<MessageT, AllocatorT>,
|
||||
typename NodeT>
|
||||
std::shared_ptr<PublisherT>
|
||||
create_publisher(
|
||||
@@ -97,31 +76,44 @@ create_publisher(
|
||||
const rclcpp::QoS & qos,
|
||||
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::PublisherOptionsWithAllocator<AllocatorT>()
|
||||
)
|
||||
)
|
||||
))
|
||||
{
|
||||
return detail::create_publisher<MessageT, AllocatorT, PublisherT>(
|
||||
node, node, topic_name, qos, options);
|
||||
}
|
||||
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);
|
||||
std::shared_ptr<AllocatorT> allocator = options.allocator;
|
||||
if (!allocator) {
|
||||
allocator = std::make_shared<AllocatorT>();
|
||||
}
|
||||
|
||||
bool use_intra_process;
|
||||
switch (options.use_intra_process_comm) {
|
||||
case IntraProcessSetting::Enable:
|
||||
use_intra_process = true;
|
||||
break;
|
||||
case IntraProcessSetting::Disable:
|
||||
use_intra_process = false;
|
||||
break;
|
||||
case IntraProcessSetting::NodeDefault:
|
||||
use_intra_process = node_topics->get_node_base_interface()->get_use_intra_process_default();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unrecognized IntraProcessSetting value");
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO(wjwwood): convert all of the interfaces to use QoS and PublisherOptionsBase
|
||||
auto pub = node_topics->create_publisher(
|
||||
topic_name,
|
||||
rclcpp::create_publisher_factory<MessageT, AllocatorT, PublisherT>(
|
||||
options.event_callbacks,
|
||||
allocator
|
||||
),
|
||||
options.template to_rcl_publisher_options<MessageT>(qos),
|
||||
use_intra_process
|
||||
);
|
||||
node_topics->add_publisher(pub, options.callback_group);
|
||||
return std::dynamic_pointer_cast<PublisherT>(pub);
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -37,7 +37,7 @@ create_service(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
rclcpp::AnyServiceCallback<ServiceT> any_service_callback;
|
||||
any_service_callback.set(std::forward<CallbackT>(callback));
|
||||
|
||||
@@ -15,157 +15,68 @@
|
||||
#ifndef RCLCPP__CREATE_SUBSCRIPTION_HPP_
|
||||
#define RCLCPP__CREATE_SUBSCRIPTION_HPP_
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/detail/resolve_enable_topic_statistics.hpp"
|
||||
|
||||
#include "rclcpp/node_interfaces/get_node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/get_node_topics_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
|
||||
#include "rclcpp/create_publisher.hpp"
|
||||
#include "rclcpp/create_timer.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/subscription_factory.hpp"
|
||||
#include "rclcpp/subscription_options.hpp"
|
||||
#include "rclcpp/timer.hpp"
|
||||
#include "rclcpp/topic_statistics/subscription_topic_statistics.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rmw/qos_profiles.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename AllocatorT,
|
||||
typename CallbackMessageT,
|
||||
typename SubscriptionT,
|
||||
typename MessageMemoryStrategyT,
|
||||
typename NodeParametersT,
|
||||
typename NodeTopicsT>
|
||||
typename SubscriptionT = rclcpp::Subscription<CallbackMessageT, AllocatorT>>
|
||||
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
|
||||
[[deprecated("use alternative rclcpp::create_subscription() signatures")]]
|
||||
typename std::shared_ptr<SubscriptionT>
|
||||
create_subscription(
|
||||
NodeParametersT & node_parameters,
|
||||
NodeTopicsT & node_topics,
|
||||
rclcpp::node_interfaces::NodeTopicsInterface * 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()
|
||||
)
|
||||
)
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
const SubscriptionEventCallbacks & event_callbacks,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
bool ignore_local_publications,
|
||||
bool use_intra_process_comms,
|
||||
typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
CallbackMessageT, AllocatorT>::SharedPtr
|
||||
msg_mem_strat,
|
||||
typename std::shared_ptr<AllocatorT> allocator)
|
||||
{
|
||||
using rclcpp::node_interfaces::get_node_topics_interface;
|
||||
auto node_topics_interface = get_node_topics_interface(node_topics);
|
||||
auto subscription_options = rcl_subscription_get_default_options();
|
||||
subscription_options.qos = qos_profile;
|
||||
subscription_options.ignore_local_publications = ignore_local_publications;
|
||||
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>>
|
||||
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<CallbackMessageT>
|
||||
>(node_topics_interface->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_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>(
|
||||
auto factory = rclcpp::create_subscription_factory
|
||||
<MessageT, CallbackT, AllocatorT, CallbackMessageT, SubscriptionT>(
|
||||
std::forward<CallbackT>(callback),
|
||||
options,
|
||||
event_callbacks,
|
||||
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);
|
||||
allocator);
|
||||
|
||||
auto sub = node_topics->create_subscription(
|
||||
topic_name,
|
||||
factory,
|
||||
subscription_options,
|
||||
use_intra_process_comms);
|
||||
node_topics->add_subscription(sub, 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
|
||||
* \param node
|
||||
* \param topic_name
|
||||
* \param qos
|
||||
* \param callback
|
||||
* \param options
|
||||
* \param msg_mem_strat
|
||||
* \return the created subscription
|
||||
* \throws std::invalid_argument if topic statistics is enabled and the publish period is
|
||||
* less than or equal to zero.
|
||||
*/
|
||||
template<
|
||||
typename MessageT,
|
||||
@@ -174,64 +85,60 @@ template<
|
||||
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,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
),
|
||||
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat = (
|
||||
MessageMemoryStrategyT::create_default()
|
||||
)
|
||||
)
|
||||
typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
CallbackMessageT, AllocatorT>::SharedPtr
|
||||
msg_mem_strat = nullptr)
|
||||
{
|
||||
return rclcpp::detail::create_subscription<
|
||||
MessageT, CallbackT, AllocatorT, CallbackMessageT, 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 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 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, CallbackMessageT, SubscriptionT, MessageMemoryStrategyT>(
|
||||
node_parameters, node_topics, topic_name, qos,
|
||||
std::forward<CallbackT>(callback), options, msg_mem_strat);
|
||||
if (!msg_mem_strat) {
|
||||
using rclcpp::message_memory_strategy::MessageMemoryStrategy;
|
||||
msg_mem_strat = MessageMemoryStrategy<CallbackMessageT, AllocatorT>::create_default();
|
||||
}
|
||||
|
||||
std::shared_ptr<AllocatorT> allocator = options.allocator;
|
||||
if (!allocator) {
|
||||
allocator = std::make_shared<AllocatorT>();
|
||||
}
|
||||
auto factory = rclcpp::create_subscription_factory
|
||||
<MessageT, CallbackT, AllocatorT, CallbackMessageT, SubscriptionT>(
|
||||
std::forward<CallbackT>(callback), options.event_callbacks, msg_mem_strat, allocator);
|
||||
|
||||
bool use_intra_process;
|
||||
switch (options.use_intra_process_comm) {
|
||||
case IntraProcessSetting::Enable:
|
||||
use_intra_process = true;
|
||||
break;
|
||||
case IntraProcessSetting::Disable:
|
||||
use_intra_process = false;
|
||||
break;
|
||||
case IntraProcessSetting::NodeDefault:
|
||||
use_intra_process = node_topics->get_node_base_interface()->get_use_intra_process_default();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unrecognized IntraProcessSetting value");
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO(wjwwood): convert all of the interfaces to use QoS and SubscriptionOptionsBase
|
||||
auto sub = node_topics->create_subscription(
|
||||
topic_name,
|
||||
factory,
|
||||
options.template to_rcl_subscription_options<MessageT>(qos),
|
||||
use_intra_process);
|
||||
node_topics->add_subscription(sub, options.callback_group);
|
||||
return std::dynamic_pointer_cast<SubscriptionT>(sub);
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -15,15 +15,13 @@
|
||||
#ifndef RCLCPP__CREATE_TIMER_HPP_
|
||||
#define RCLCPP__CREATE_TIMER_HPP_
|
||||
|
||||
#include <chrono>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/duration.hpp"
|
||||
#include "rclcpp/node_interfaces/get_node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/get_node_timers_interface.hpp"
|
||||
# include "rclcpp/node_interfaces/get_node_base_interface.hpp"
|
||||
# include "rclcpp/node_interfaces/get_node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
|
||||
@@ -34,12 +32,12 @@ namespace rclcpp
|
||||
template<typename CallbackT>
|
||||
typename rclcpp::TimerBase::SharedPtr
|
||||
create_timer(
|
||||
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
|
||||
std::shared_ptr<node_interfaces::NodeTimersInterface> node_timers,
|
||||
node_interfaces::NodeBaseInterface * node_base,
|
||||
node_interfaces::NodeTimersInterface * node_timers,
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
auto timer = rclcpp::GenericTimer<CallbackT>::make_shared(
|
||||
clock,
|
||||
@@ -59,7 +57,7 @@ create_timer(
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
return create_timer(
|
||||
rclcpp::node_interfaces::get_node_base_interface(node),
|
||||
@@ -70,74 +68,6 @@ create_timer(
|
||||
group);
|
||||
}
|
||||
|
||||
/// Convenience method to create a timer with node resources.
|
||||
/**
|
||||
*
|
||||
* \tparam DurationRepT
|
||||
* \tparam DurationT
|
||||
* \tparam CallbackT
|
||||
* \param period period to execute callback. This duration must be 0 <= period < nanoseconds::max()
|
||||
* \param callback callback to execute via the timer period
|
||||
* \param group
|
||||
* \param node_base
|
||||
* \param node_timers
|
||||
* \return
|
||||
* \throws std::invalid argument if either node_base or node_timers
|
||||
* are null, or period is negative or too large
|
||||
*/
|
||||
template<typename DurationRepT, typename DurationT, typename CallbackT>
|
||||
typename rclcpp::WallTimer<CallbackT>::SharedPtr
|
||||
create_wall_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group,
|
||||
node_interfaces::NodeBaseInterface * node_base,
|
||||
node_interfaces::NodeTimersInterface * node_timers)
|
||||
{
|
||||
if (node_base == nullptr) {
|
||||
throw std::invalid_argument{"input node_base cannot be null"};
|
||||
}
|
||||
|
||||
if (node_timers == nullptr) {
|
||||
throw std::invalid_argument{"input node_timers cannot be null"};
|
||||
}
|
||||
|
||||
if (period < std::chrono::duration<DurationRepT, DurationT>::zero()) {
|
||||
throw std::invalid_argument{"timer period cannot be negative"};
|
||||
}
|
||||
|
||||
// Casting to a double representation might lose precision and allow the check below to succeed
|
||||
// but the actual cast to nanoseconds fail. Using 1 DurationT worth of nanoseconds less than max.
|
||||
constexpr auto maximum_safe_cast_ns =
|
||||
std::chrono::nanoseconds::max() - std::chrono::duration<DurationRepT, DurationT>(1);
|
||||
|
||||
// If period is greater than nanoseconds::max(), the duration_cast to nanoseconds will overflow
|
||||
// a signed integer, which is undefined behavior. Checking whether any std::chrono::duration is
|
||||
// greater than nanoseconds::max() is a difficult general problem. This is a more conservative
|
||||
// version of Howard Hinnant's (the <chrono> guy>) response here:
|
||||
// https://stackoverflow.com/a/44637334/2089061
|
||||
// However, this doesn't solve the issue for all possible duration types of period.
|
||||
// Follow-up issue: https://github.com/ros2/rclcpp/issues/1177
|
||||
constexpr auto ns_max_as_double =
|
||||
std::chrono::duration_cast<std::chrono::duration<double, std::chrono::nanoseconds::period>>(
|
||||
maximum_safe_cast_ns);
|
||||
if (period > ns_max_as_double) {
|
||||
throw std::invalid_argument{
|
||||
"timer period must be less than std::chrono::nanoseconds::max()"};
|
||||
}
|
||||
|
||||
const auto period_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(period);
|
||||
if (period_ns < std::chrono::nanoseconds::zero()) {
|
||||
throw std::runtime_error{
|
||||
"Casting timer period to nanoseconds resulted in integer overflow."};
|
||||
}
|
||||
|
||||
auto timer = rclcpp::WallTimer<CallbackT>::make_shared(
|
||||
period_ns, std::move(callback), node_base->get_context());
|
||||
node_timers->add_timer(timer, group);
|
||||
return timer;
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CREATE_TIMER_HPP_
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
Notice that headers in this folder should only provide symbols in the rclcpp::detail namespace.
|
||||
|
||||
Also that these headers are not considered part of the public API and are subject to change without notice.
|
||||
@@ -1,76 +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__MUTEX_TWO_PRIORITIES_HPP_
|
||||
#define RCLCPP__DETAIL__MUTEX_TWO_PRIORITIES_HPP_
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// \internal A mutex that has two locking mechanism, one with higher priority than the other.
|
||||
/**
|
||||
* After the current mutex owner release the lock, a thread that used the high
|
||||
* priority mechanism will have priority over threads that used the low priority mechanism.
|
||||
*/
|
||||
class MutexTwoPriorities
|
||||
{
|
||||
public:
|
||||
class HighPriorityLockable
|
||||
{
|
||||
public:
|
||||
explicit HighPriorityLockable(MutexTwoPriorities & parent);
|
||||
|
||||
void lock();
|
||||
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
MutexTwoPriorities & parent_;
|
||||
};
|
||||
|
||||
class LowPriorityLockable
|
||||
{
|
||||
public:
|
||||
explicit LowPriorityLockable(MutexTwoPriorities & parent);
|
||||
|
||||
void lock();
|
||||
|
||||
void unlock();
|
||||
|
||||
private:
|
||||
MutexTwoPriorities & parent_;
|
||||
};
|
||||
|
||||
HighPriorityLockable
|
||||
get_high_priority_lockable();
|
||||
|
||||
LowPriorityLockable
|
||||
get_low_priority_lockable();
|
||||
|
||||
private:
|
||||
std::condition_variable hp_cv_;
|
||||
std::condition_variable lp_cv_;
|
||||
std::mutex cv_mutex_;
|
||||
size_t hp_waiting_count_{0u};
|
||||
bool data_taken_{false};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DETAIL__MUTEX_TWO_PRIORITIES_HPP_
|
||||
@@ -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,53 +0,0 @@
|
||||
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
//
|
||||
// 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__RESOLVE_ENABLE_TOPIC_STATISTICS_HPP_
|
||||
#define RCLCPP__DETAIL__RESOLVE_ENABLE_TOPIC_STATISTICS_HPP_
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "rclcpp/topic_statistics_state.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// Return whether or not topic statistics is enabled, resolving "NodeDefault" if needed.
|
||||
template<typename OptionsT, typename NodeBaseT>
|
||||
bool
|
||||
resolve_enable_topic_statistics(const OptionsT & options, const NodeBaseT & node_base)
|
||||
{
|
||||
bool topic_stats_enabled;
|
||||
switch (options.topic_stats_options.state) {
|
||||
case TopicStatisticsState::Enable:
|
||||
topic_stats_enabled = true;
|
||||
break;
|
||||
case TopicStatisticsState::Disable:
|
||||
topic_stats_enabled = false;
|
||||
break;
|
||||
case TopicStatisticsState::NodeDefault:
|
||||
topic_stats_enabled = node_base.get_enable_topic_statistics_default();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unrecognized EnableTopicStatistics value");
|
||||
}
|
||||
|
||||
return topic_stats_enabled;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DETAIL__RESOLVE_ENABLE_TOPIC_STATISTICS_HPP_
|
||||
@@ -1,54 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__DETAIL__RESOLVE_INTRA_PROCESS_BUFFER_TYPE_HPP_
|
||||
#define RCLCPP__DETAIL__RESOLVE_INTRA_PROCESS_BUFFER_TYPE_HPP_
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "rclcpp/any_subscription_callback.hpp"
|
||||
#include "rclcpp/intra_process_buffer_type.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// Return the buffer type, resolving the "CallbackDefault" type to an actual type if needed.
|
||||
template<typename CallbackMessageT, typename AllocatorT>
|
||||
rclcpp::IntraProcessBufferType
|
||||
resolve_intra_process_buffer_type(
|
||||
const rclcpp::IntraProcessBufferType buffer_type,
|
||||
const rclcpp::AnySubscriptionCallback<CallbackMessageT, AllocatorT> & any_subscription_callback)
|
||||
{
|
||||
rclcpp::IntraProcessBufferType resolved_buffer_type = buffer_type;
|
||||
|
||||
// If the user has not specified a type for the intra-process buffer, use the callback's type.
|
||||
if (resolved_buffer_type == IntraProcessBufferType::CallbackDefault) {
|
||||
if (any_subscription_callback.use_take_shared_method()) {
|
||||
resolved_buffer_type = IntraProcessBufferType::SharedPtr;
|
||||
} else {
|
||||
resolved_buffer_type = IntraProcessBufferType::UniquePtr;
|
||||
}
|
||||
}
|
||||
|
||||
return resolved_buffer_type;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DETAIL__RESOLVE_INTRA_PROCESS_BUFFER_TYPE_HPP_
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__DETAIL__RESOLVE_USE_INTRA_PROCESS_HPP_
|
||||
#define RCLCPP__DETAIL__RESOLVE_USE_INTRA_PROCESS_HPP_
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "rclcpp/intra_process_setting.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// Return whether or not intra process is enabled, resolving "NodeDefault" if needed.
|
||||
template<typename OptionsT, typename NodeBaseT>
|
||||
bool
|
||||
resolve_use_intra_process(const OptionsT & options, const NodeBaseT & node_base)
|
||||
{
|
||||
bool use_intra_process;
|
||||
switch (options.use_intra_process_comm) {
|
||||
case IntraProcessSetting::Enable:
|
||||
use_intra_process = true;
|
||||
break;
|
||||
case IntraProcessSetting::Disable:
|
||||
use_intra_process = false;
|
||||
break;
|
||||
case IntraProcessSetting::NodeDefault:
|
||||
use_intra_process = node_base.get_use_intra_process_default();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unrecognized IntraProcessSetting value");
|
||||
break;
|
||||
}
|
||||
|
||||
return use_intra_process;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DETAIL__RESOLVE_USE_INTRA_PROCESS_HPP_
|
||||
@@ -1,51 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PAYLOAD_HPP_
|
||||
#define RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PAYLOAD_HPP_
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// Mechanism for passing rmw implementation specific settings through the ROS interfaces.
|
||||
class RCLCPP_PUBLIC RMWImplementationSpecificPayload
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
~RMWImplementationSpecificPayload() = default;
|
||||
|
||||
/// Return false if this class has not been customized, otherwise true.
|
||||
/**
|
||||
* It does this based on the value of the rmw implementation identifier that
|
||||
* this class reports, and so it is important for a specialization of this
|
||||
* class to override the get_rmw_implementation_identifier() method to return
|
||||
* something other than nullptr.
|
||||
*/
|
||||
bool
|
||||
has_been_customized() const;
|
||||
|
||||
/// Derrived classes should override this and return the identifier of its rmw implementation.
|
||||
virtual
|
||||
const char *
|
||||
get_implementation_identifier() const;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PAYLOAD_HPP_
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PUBLISHER_PAYLOAD_HPP_
|
||||
#define RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PUBLISHER_PAYLOAD_HPP_
|
||||
|
||||
#include "rcl/publisher.h"
|
||||
|
||||
#include "rclcpp/detail/rmw_implementation_specific_payload.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class RCLCPP_PUBLIC RMWImplementationSpecificPublisherPayload
|
||||
: public RMWImplementationSpecificPayload
|
||||
{
|
||||
public:
|
||||
~RMWImplementationSpecificPublisherPayload() override = default;
|
||||
|
||||
/// Opportunity for a derived class to inject information into the rcl options.
|
||||
/**
|
||||
* This is called after the rcl_publisher_options_t has been prepared by
|
||||
* rclcpp, but before rcl_publisher_init() is called.
|
||||
*
|
||||
* The passed option is the rmw_publisher_options field of the
|
||||
* rcl_publisher_options_t that will be passed to rcl_publisher_init().
|
||||
*
|
||||
* By default the options are unmodified.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
modify_rmw_publisher_options(rmw_publisher_options_t & rmw_publisher_options) const;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PUBLISHER_PAYLOAD_HPP_
|
||||
@@ -1,53 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_SUBSCRIPTION_PAYLOAD_HPP_
|
||||
#define RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_SUBSCRIPTION_PAYLOAD_HPP_
|
||||
|
||||
#include "rcl/subscription.h"
|
||||
|
||||
#include "rclcpp/detail/rmw_implementation_specific_payload.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
/// Subscription payload that may be rmw implementation specific.
|
||||
class RCLCPP_PUBLIC RMWImplementationSpecificSubscriptionPayload
|
||||
: public RMWImplementationSpecificPayload
|
||||
{
|
||||
public:
|
||||
~RMWImplementationSpecificSubscriptionPayload() override = default;
|
||||
|
||||
/// Opportunity for a derived class to inject information into the rcl options.
|
||||
/**
|
||||
* This is called after the rcl_subscription_options_t has been prepared by
|
||||
* rclcpp, but before rcl_subscription_init() is called.
|
||||
*
|
||||
* The passed option is the rmw_subscription_options field of the
|
||||
* rcl_subscription_options_t that will be passed to rcl_subscription_init().
|
||||
*
|
||||
* By default the options are unmodified.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
modify_rmw_subscription_options(rmw_subscription_options_t & rmw_subscription_options) const;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_SUBSCRIPTION_PAYLOAD_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_
|
||||
@@ -1,40 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__DETAIL__UTILITIES_HPP_
|
||||
#define RCLCPP__DETAIL__UTILITIES_HPP_
|
||||
|
||||
#include "rclcpp/detail/utilities.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/allocator.h"
|
||||
#include "rcl/arguments.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
std::vector<std::string>
|
||||
get_unparsed_ros_arguments(
|
||||
int argc, char const * const argv[],
|
||||
rcl_arguments_t * arguments,
|
||||
rcl_allocator_t allocator);
|
||||
|
||||
} // namespace detail
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DETAIL__UTILITIES_HPP_
|
||||
@@ -26,29 +26,12 @@ namespace rclcpp
|
||||
class RCLCPP_PUBLIC Duration
|
||||
{
|
||||
public:
|
||||
/// Duration constructor.
|
||||
/**
|
||||
* Initializes the time values for seconds and nanoseconds individually.
|
||||
* Large values for nsecs are wrapped automatically with the remainder added to secs.
|
||||
* Both inputs must be integers.
|
||||
* Seconds can be negative.
|
||||
*
|
||||
* \param seconds time in seconds
|
||||
* \param nanoseconds time in nanoseconds
|
||||
*/
|
||||
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);")]]
|
||||
explicit Duration(rcl_duration_value_t nanoseconds);
|
||||
|
||||
/// Construct duration from the specified std::chrono::nanoseconds.
|
||||
explicit Duration(std::chrono::nanoseconds nanoseconds);
|
||||
|
||||
// This constructor matches any std::chrono value other than nanoseconds
|
||||
// intentionally not using explicit to create a conversion constructor
|
||||
template<class Rep, class Period>
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
@@ -59,10 +42,6 @@ public:
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
Duration(const builtin_interfaces::msg::Duration & duration_msg); // NOLINT(runtime/explicit)
|
||||
|
||||
/// Time constructor
|
||||
/**
|
||||
* \param duration rcl_duration_t structure to copy.
|
||||
*/
|
||||
explicit Duration(const rcl_duration_t & duration);
|
||||
|
||||
Duration(const Duration & rhs);
|
||||
@@ -102,10 +81,6 @@ public:
|
||||
Duration
|
||||
operator-(const rclcpp::Duration & rhs) const;
|
||||
|
||||
/// Get the maximum representable value.
|
||||
/**
|
||||
* \return the maximum representable value
|
||||
*/
|
||||
static
|
||||
Duration
|
||||
max();
|
||||
@@ -113,34 +88,15 @@ public:
|
||||
Duration
|
||||
operator*(double scale) const;
|
||||
|
||||
/// Get duration in nanosecods
|
||||
/**
|
||||
* \return the duration in nanoseconds as a rcl_duration_value_t.
|
||||
*/
|
||||
rcl_duration_value_t
|
||||
nanoseconds() const;
|
||||
|
||||
/// Get duration in seconds
|
||||
/**
|
||||
* \warning Depending on sizeof(double) there could be significant precision loss.
|
||||
* When an exact time is required use nanoseconds() instead.
|
||||
* \return the duration in seconds as a floating point number.
|
||||
*/
|
||||
/// \return the duration in seconds as a floating point number.
|
||||
/// \warning Depending on sizeof(double) there could be significant precision loss.
|
||||
/// When an exact time is required use nanoseconds() instead.
|
||||
double
|
||||
seconds() const;
|
||||
|
||||
/// Create a duration object from a floating point number representing seconds
|
||||
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
|
||||
to_chrono() const
|
||||
@@ -148,14 +104,11 @@ public:
|
||||
return std::chrono::duration_cast<DurationT>(std::chrono::nanoseconds(this->nanoseconds()));
|
||||
}
|
||||
|
||||
/// Convert Duration into rmw_time_t.
|
||||
rmw_time_t
|
||||
to_rmw_time() const;
|
||||
|
||||
private:
|
||||
rcl_duration_t rcl_duration_;
|
||||
|
||||
Duration() = default;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -29,33 +29,17 @@ class Event
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(Event)
|
||||
|
||||
/// Default construct
|
||||
/**
|
||||
* Set the default value to false
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
Event();
|
||||
|
||||
/// Set the Event state value to true
|
||||
/**
|
||||
* \return The state value before the call.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
set();
|
||||
|
||||
/// Get the state value of the Event
|
||||
/**
|
||||
* \return the Event state value
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
check();
|
||||
|
||||
/// Get the state value of the Event and set to false
|
||||
/**
|
||||
* \return the Event state value
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
check_and_clear();
|
||||
|
||||
@@ -15,6 +15,211 @@
|
||||
#ifndef RCLCPP__EXCEPTIONS_HPP_
|
||||
#define RCLCPP__EXCEPTIONS_HPP_
|
||||
|
||||
#include "rclcpp/exceptions/exceptions.hpp"
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/types.h"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace exceptions
|
||||
{
|
||||
|
||||
/// Thrown when a method is trying to use a node, but it is invalid.
|
||||
class InvalidNodeError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
InvalidNodeError()
|
||||
: std::runtime_error("node is invalid") {}
|
||||
};
|
||||
|
||||
/// Thrown when a any kind of name (node, namespace, topic, etc.) is invalid.
|
||||
class NameValidationError : public std::invalid_argument
|
||||
{
|
||||
public:
|
||||
NameValidationError(
|
||||
const char * name_type_,
|
||||
const char * name_,
|
||||
const char * error_msg_,
|
||||
size_t invalid_index_)
|
||||
: std::invalid_argument(format_error(name_type_, name_, error_msg_, invalid_index_)),
|
||||
name_type(name_type_), name(name_), error_msg(error_msg_), invalid_index(invalid_index_)
|
||||
{}
|
||||
|
||||
static std::string
|
||||
format_error(
|
||||
const char * name_type,
|
||||
const char * name,
|
||||
const char * error_msg,
|
||||
size_t invalid_index);
|
||||
|
||||
const std::string name_type;
|
||||
const std::string name;
|
||||
const std::string error_msg;
|
||||
const size_t invalid_index;
|
||||
};
|
||||
|
||||
/// Thrown when a node name is invalid.
|
||||
class InvalidNodeNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidNodeNameError(const char * node_name, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("node name", node_name, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a node namespace is invalid.
|
||||
class InvalidNamespaceError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidNamespaceError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("namespace", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a topic name is invalid.
|
||||
class InvalidTopicNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidTopicNameError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("topic name", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a service name is invalid.
|
||||
class InvalidServiceNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidServiceNameError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("service name", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Throw a C++ std::exception which was created based on an rcl error.
|
||||
/**
|
||||
* Passing nullptr for reset_error is safe and will avoid calling any function
|
||||
* to reset the error.
|
||||
*
|
||||
* \param ret the return code for the current error state
|
||||
* \param prefix string to prefix to the error if applicable (not all errors have custom messages)
|
||||
* \param error_state error state to create exception from, if nullptr rcl_get_error_state is used
|
||||
* \param reset_error function to be called before throwing which whill clear the error state
|
||||
* \throws std::invalid_argument if ret is RCL_RET_OK
|
||||
* \throws std::runtime_error if the rcl_get_error_state returns 0
|
||||
* \throws RCLErrorBase some child class exception based on ret
|
||||
*/
|
||||
/* *INDENT-OFF* */ // Uncrustify cannot yet understand [[noreturn]] properly
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
throw_from_rcl_error [[noreturn]] (
|
||||
rcl_ret_t ret,
|
||||
const std::string & prefix = "",
|
||||
const rcl_error_state_t * error_state = nullptr,
|
||||
void (* reset_error)() = rcl_reset_error);
|
||||
/* *INDENT-ON* */
|
||||
|
||||
class RCLErrorBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLErrorBase(rcl_ret_t ret, const rcl_error_state_t * error_state);
|
||||
virtual ~RCLErrorBase() {}
|
||||
|
||||
rcl_ret_t ret;
|
||||
std::string message;
|
||||
std::string file;
|
||||
size_t line;
|
||||
std::string formatted_message;
|
||||
};
|
||||
|
||||
/// Created when the return code does not match one of the other specialized exceptions.
|
||||
class RCLError : public RCLErrorBase, public std::runtime_error
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLError(rcl_ret_t ret, const rcl_error_state_t * error_state, const std::string & prefix);
|
||||
RCLCPP_PUBLIC
|
||||
RCLError(const RCLErrorBase & base_exc, const std::string & prefix);
|
||||
};
|
||||
|
||||
/// Created when the ret is RCL_RET_BAD_ALLOC.
|
||||
class RCLBadAlloc : public RCLErrorBase, public std::bad_alloc
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLBadAlloc(rcl_ret_t ret, const rcl_error_state_t * error_state);
|
||||
RCLCPP_PUBLIC
|
||||
explicit RCLBadAlloc(const RCLErrorBase & base_exc);
|
||||
};
|
||||
|
||||
/// Created when the ret is RCL_RET_INVALID_ARGUMENT.
|
||||
class RCLInvalidArgument : public RCLErrorBase, public std::invalid_argument
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidArgument(
|
||||
rcl_ret_t ret,
|
||||
const rcl_error_state_t * error_state,
|
||||
const std::string & prefix);
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidArgument(const RCLErrorBase & base_exc, const std::string & prefix);
|
||||
};
|
||||
|
||||
/// Thrown when an invalid rclcpp::Event object or SharedPtr is encountered.
|
||||
class InvalidEventError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
InvalidEventError()
|
||||
: std::runtime_error("event is invalid") {}
|
||||
};
|
||||
|
||||
/// Thrown when an unregistered rclcpp::Event is encountered where a registered one was expected.
|
||||
class EventNotRegisteredError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
EventNotRegisteredError()
|
||||
: std::runtime_error("event already registered") {}
|
||||
};
|
||||
|
||||
/// Thrown if passed parameters are inconsistent or invalid
|
||||
class InvalidParametersException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if passed parameter value is invalid.
|
||||
class InvalidParameterValueException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is already declared.
|
||||
class ParameterAlreadyDeclaredException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is not declared, e.g. either set or get was called without first declaring.
|
||||
class ParameterNotDeclaredException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is immutable and therefore cannot be undeclared.
|
||||
class ParameterImmutableException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
} // namespace exceptions
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXCEPTIONS_HPP_
|
||||
|
||||
@@ -1,316 +0,0 @@
|
||||
// Copyright 2016 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__EXCEPTIONS__EXCEPTIONS_HPP_
|
||||
#define RCLCPP__EXCEPTIONS__EXCEPTIONS_HPP_
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/types.h"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rcpputils/join.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace exceptions
|
||||
{
|
||||
|
||||
/// Thrown when a method is trying to use a node, but it is invalid.
|
||||
class InvalidNodeError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
InvalidNodeError()
|
||||
: std::runtime_error("node is invalid") {}
|
||||
};
|
||||
|
||||
/// Thrown when a any kind of name (node, namespace, topic, etc.) is invalid.
|
||||
class NameValidationError : public std::invalid_argument
|
||||
{
|
||||
public:
|
||||
NameValidationError(
|
||||
const char * name_type_,
|
||||
const char * name_,
|
||||
const char * error_msg_,
|
||||
size_t invalid_index_)
|
||||
: std::invalid_argument(format_error(name_type_, name_, error_msg_, invalid_index_)),
|
||||
name_type(name_type_), name(name_), error_msg(error_msg_), invalid_index(invalid_index_)
|
||||
{}
|
||||
|
||||
static std::string
|
||||
format_error(
|
||||
const char * name_type,
|
||||
const char * name,
|
||||
const char * error_msg,
|
||||
size_t invalid_index);
|
||||
|
||||
const std::string name_type;
|
||||
const std::string name;
|
||||
const std::string error_msg;
|
||||
const size_t invalid_index;
|
||||
};
|
||||
|
||||
/// Thrown when a node name is invalid.
|
||||
class InvalidNodeNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidNodeNameError(const char * node_name, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("node name", node_name, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a node namespace is invalid.
|
||||
class InvalidNamespaceError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidNamespaceError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("namespace", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a topic name is invalid.
|
||||
class InvalidTopicNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidTopicNameError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("topic name", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a service name is invalid.
|
||||
class InvalidServiceNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidServiceNameError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("service name", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
class UnimplementedError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
UnimplementedError()
|
||||
: std::runtime_error("This code is unimplemented.") {}
|
||||
explicit UnimplementedError(const std::string & msg)
|
||||
: std::runtime_error(msg) {}
|
||||
};
|
||||
|
||||
/// Throw a C++ std::exception which was created based on an rcl error.
|
||||
/**
|
||||
* Passing nullptr for reset_error is safe and will avoid calling any function
|
||||
* to reset the error.
|
||||
*
|
||||
* \param ret the return code for the current error state
|
||||
* \param prefix string to prefix to the error if applicable (not all errors have custom messages)
|
||||
* \param error_state error state to create exception from, if nullptr rcl_get_error_state is used
|
||||
* \param reset_error function to be called before throwing which whill clear the error state
|
||||
* \throws std::invalid_argument if ret is RCL_RET_OK
|
||||
* \throws std::runtime_error if the rcl_get_error_state returns 0
|
||||
* \throws RCLErrorBase some child class exception based on ret
|
||||
*/
|
||||
/* *INDENT-OFF* */ // Uncrustify cannot yet understand [[noreturn]] properly
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
throw_from_rcl_error [[noreturn]] (
|
||||
rcl_ret_t ret,
|
||||
const std::string & prefix = "",
|
||||
const rcl_error_state_t * error_state = nullptr,
|
||||
void (* reset_error)() = rcl_reset_error);
|
||||
/* *INDENT-ON* */
|
||||
|
||||
class RCLErrorBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLErrorBase(rcl_ret_t ret, const rcl_error_state_t * error_state);
|
||||
virtual ~RCLErrorBase() {}
|
||||
|
||||
rcl_ret_t ret;
|
||||
std::string message;
|
||||
std::string file;
|
||||
size_t line;
|
||||
std::string formatted_message;
|
||||
};
|
||||
|
||||
/// Created when the return code does not match one of the other specialized exceptions.
|
||||
class RCLError : public RCLErrorBase, public std::runtime_error
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLError(rcl_ret_t ret, const rcl_error_state_t * error_state, const std::string & prefix);
|
||||
RCLCPP_PUBLIC
|
||||
RCLError(const RCLErrorBase & base_exc, const std::string & prefix);
|
||||
};
|
||||
|
||||
/// Created when the ret is RCL_RET_BAD_ALLOC.
|
||||
class RCLBadAlloc : public RCLErrorBase, public std::bad_alloc
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLBadAlloc(rcl_ret_t ret, const rcl_error_state_t * error_state);
|
||||
RCLCPP_PUBLIC
|
||||
explicit RCLBadAlloc(const RCLErrorBase & base_exc);
|
||||
};
|
||||
|
||||
/// Created when the ret is RCL_RET_INVALID_ARGUMENT.
|
||||
class RCLInvalidArgument : public RCLErrorBase, public std::invalid_argument
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidArgument(
|
||||
rcl_ret_t ret,
|
||||
const rcl_error_state_t * error_state,
|
||||
const std::string & prefix);
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidArgument(const RCLErrorBase & base_exc, const std::string & prefix);
|
||||
};
|
||||
|
||||
/// Created when the ret is RCL_RET_INVALID_ROS_ARGS.
|
||||
class RCLInvalidROSArgsError : public RCLErrorBase, public std::runtime_error
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidROSArgsError(
|
||||
rcl_ret_t ret, const rcl_error_state_t * error_state, const std::string & prefix);
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidROSArgsError(const RCLErrorBase & base_exc, const std::string & prefix);
|
||||
};
|
||||
|
||||
/// Thrown when unparsed ROS specific arguments are found.
|
||||
class UnknownROSArgsError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit UnknownROSArgsError(std::vector<std::string> && unknown_ros_args_in)
|
||||
: std::runtime_error(
|
||||
"found unknown ROS arguments: '" + rcpputils::join(unknown_ros_args_in, "', '") + "'"),
|
||||
unknown_ros_args(unknown_ros_args_in)
|
||||
{
|
||||
}
|
||||
|
||||
const std::vector<std::string> unknown_ros_args;
|
||||
};
|
||||
|
||||
/// Thrown when an invalid rclcpp::Event object or SharedPtr is encountered.
|
||||
class InvalidEventError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
InvalidEventError()
|
||||
: std::runtime_error("event is invalid") {}
|
||||
};
|
||||
|
||||
/// Thrown when an unregistered rclcpp::Event is encountered where a registered one was expected.
|
||||
class EventNotRegisteredError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
EventNotRegisteredError()
|
||||
: std::runtime_error("event already registered") {}
|
||||
};
|
||||
|
||||
/// Thrown if passed parameters are inconsistent or invalid
|
||||
class InvalidParametersException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if passed parameter value is invalid.
|
||||
class InvalidParameterValueException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if requested parameter type is invalid.
|
||||
/**
|
||||
* Essentially the same as rclcpp::ParameterTypeException, but with parameter
|
||||
* name in the error message.
|
||||
*/
|
||||
class InvalidParameterTypeException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/// Construct an instance.
|
||||
/**
|
||||
* \param[in] name the name of the parameter.
|
||||
* \param[in] message custom exception message.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
InvalidParameterTypeException(const std::string & name, const std::string message)
|
||||
: std::runtime_error("parameter '" + name + "' has invalid type: " + message)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown if parameter is already declared.
|
||||
class ParameterAlreadyDeclaredException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is not declared, e.g. either set or get was called without first declaring.
|
||||
class ParameterNotDeclaredException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is immutable and therefore cannot be undeclared.
|
||||
class ParameterImmutableException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is modified while in a set callback.
|
||||
class ParameterModifiedInCallbackException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from 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
|
||||
|
||||
#endif // RCLCPP__EXCEPTIONS__EXCEPTIONS_HPP_
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
@@ -30,11 +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"
|
||||
#include "rclcpp/memory_strategy.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
@@ -45,13 +40,50 @@
|
||||
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;
|
||||
|
||||
namespace executor
|
||||
{
|
||||
|
||||
/// Return codes to be used with spin_until_future_complete.
|
||||
/**
|
||||
* SUCCESS: The future is complete and can be accessed with "get" without blocking.
|
||||
* INTERRUPTED: The future is not complete, spinning was interrupted by Ctrl-C or another error.
|
||||
* TIMEOUT: Spinning timed out.
|
||||
*/
|
||||
enum class FutureReturnCode {SUCCESS, INTERRUPTED, TIMEOUT};
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::ostream &
|
||||
operator<<(std::ostream & os, const FutureReturnCode & future_return_code);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
to_string(const FutureReturnCode & future_return_code);
|
||||
|
||||
///
|
||||
/**
|
||||
* Options to be passed to the executor constructor.
|
||||
*/
|
||||
struct ExecutorArgs
|
||||
{
|
||||
ExecutorArgs()
|
||||
: memory_strategy(memory_strategies::create_default_strategy()),
|
||||
context(rclcpp::contexts::default_context::get_global_default_context()),
|
||||
max_conditions(0)
|
||||
{}
|
||||
|
||||
memory_strategy::MemoryStrategy::SharedPtr memory_strategy;
|
||||
std::shared_ptr<rclcpp::Context> context;
|
||||
size_t max_conditions;
|
||||
};
|
||||
|
||||
static inline ExecutorArgs create_default_executor_arguments()
|
||||
{
|
||||
return ExecutorArgs();
|
||||
}
|
||||
|
||||
/// Coordinate the order and timing of available communication tasks.
|
||||
/**
|
||||
* Executor provides spin functions (including spin_node_once and spin_some).
|
||||
@@ -68,11 +100,9 @@ public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(Executor)
|
||||
|
||||
/// Default constructor.
|
||||
/**
|
||||
* \param[in] options Options used to configure the executor.
|
||||
*/
|
||||
// \param[in] ms The memory strategy to be used with this executor.
|
||||
RCLCPP_PUBLIC
|
||||
explicit Executor(const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
|
||||
explicit Executor(const ExecutorArgs & args = ExecutorArgs());
|
||||
|
||||
/// Default destructor.
|
||||
RCLCPP_PUBLIC
|
||||
@@ -83,155 +113,35 @@ 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
|
||||
add_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify = true);
|
||||
|
||||
/// Convenience function which takes Node and forwards NodeBaseInterface.
|
||||
/**
|
||||
* \see rclcpp::Executor::add_node
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
add_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true);
|
||||
|
||||
/// 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
|
||||
remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify = true);
|
||||
|
||||
/// Convenience function which takes Node and forwards NodeBaseInterface.
|
||||
/**
|
||||
* \see rclcpp::Executor::remove_node
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
remove_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true);
|
||||
@@ -281,7 +191,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,41 +206,24 @@ 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));
|
||||
|
||||
/// Spin (blocking) until the future is complete, it times out waiting, or rclcpp is interrupted.
|
||||
/**
|
||||
* \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] future The future to wait on. If SUCCESS, the future is safe to access after this
|
||||
* function.
|
||||
* \param[in] timeout Optional timeout parameter, which gets passed to Executor::spin_node_once.
|
||||
* `-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`.
|
||||
*/
|
||||
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,
|
||||
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
|
||||
@@ -382,10 +275,7 @@ public:
|
||||
}
|
||||
|
||||
/// Cancel any running spin* function, causing it to return.
|
||||
/**
|
||||
* This function can be called asynchonously from any thread.
|
||||
* \throws std::runtime_error if there is an issue triggering the guard condition
|
||||
*/
|
||||
/* This function can be called asynchonously from any thread. */
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
cancel();
|
||||
@@ -395,7 +285,6 @@ public:
|
||||
* Switching the memory strategy while the executor is spinning in another threading could have
|
||||
* unintended consequences.
|
||||
* \param[in] memory_strategy Shared pointer to the memory strategy to set.
|
||||
* \throws std::runtime_error if memory_strategy is null
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
@@ -408,15 +297,9 @@ 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,
|
||||
/** \param[in] any_exec Union structure that can hold any executable type (timer, subscription,
|
||||
* service, client).
|
||||
* \throws std::runtime_error if there is an issue triggering the guard condition
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
@@ -427,6 +310,11 @@ protected:
|
||||
execute_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
static void
|
||||
execute_intra_process_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
static void
|
||||
execute_timer(rclcpp::TimerBase::SharedPtr timer);
|
||||
@@ -439,144 +327,62 @@ protected:
|
||||
static void
|
||||
execute_client(rclcpp::ClientBase::SharedPtr client);
|
||||
|
||||
/**
|
||||
* \throws std::runtime_error if the wait set can be cleared
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
wait_for_work(std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
|
||||
|
||||
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::callback_group::CallbackGroup::SharedPtr group);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
rclcpp::callback_group::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_);
|
||||
void
|
||||
get_next_timer(AnyExecutable & any_exec);
|
||||
|
||||
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_;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(Executor)
|
||||
|
||||
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_;
|
||||
std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
|
||||
std::list<const rcl_guard_condition_t *> guard_conditions_;
|
||||
};
|
||||
|
||||
} // namespace executor
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXECUTOR_HPP_
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright 2014-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__EXECUTOR_OPTIONS_HPP_
|
||||
#define RCLCPP__EXECUTOR_OPTIONS_HPP_
|
||||
|
||||
#include "rclcpp/context.hpp"
|
||||
#include "rclcpp/contexts/default_context.hpp"
|
||||
#include "rclcpp/memory_strategies.hpp"
|
||||
#include "rclcpp/memory_strategy.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Options to be passed to the executor constructor.
|
||||
struct ExecutorOptions
|
||||
{
|
||||
ExecutorOptions()
|
||||
: memory_strategy(rclcpp::memory_strategies::create_default_strategy()),
|
||||
context(rclcpp::contexts::get_global_default_context()),
|
||||
max_conditions(0)
|
||||
{}
|
||||
|
||||
rclcpp::memory_strategy::MemoryStrategy::SharedPtr memory_strategy;
|
||||
rclcpp::Context::SharedPtr context;
|
||||
size_t max_conditions;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXECUTOR_OPTIONS_HPP_
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include "rclcpp/executors/multi_threaded_executor.hpp"
|
||||
#include "rclcpp/executors/single_threaded_executor.hpp"
|
||||
#include "rclcpp/executors/static_single_threaded_executor.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
@@ -66,12 +65,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>
|
||||
rclcpp::FutureReturnCode
|
||||
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
rclcpp::executor::FutureReturnCode
|
||||
spin_node_until_future_complete(
|
||||
rclcpp::Executor & executor,
|
||||
rclcpp::executor::Executor & executor,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
const FutureT & future,
|
||||
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 +81,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
|
||||
rclcpp::executor::FutureReturnCode
|
||||
spin_node_until_future_complete(
|
||||
rclcpp::Executor & executor,
|
||||
rclcpp::executor::Executor & executor,
|
||||
std::shared_ptr<NodeT> node_ptr,
|
||||
const FutureT & future,
|
||||
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(
|
||||
@@ -101,10 +100,10 @@ spin_node_until_future_complete(
|
||||
} // namespace executors
|
||||
|
||||
template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
rclcpp::FutureReturnCode
|
||||
rclcpp::executor::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
const FutureT & future,
|
||||
std::shared_future<FutureT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
@@ -113,10 +112,10 @@ spin_until_future_complete(
|
||||
|
||||
template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeRepT = int64_t,
|
||||
typename TimeT = std::milli>
|
||||
rclcpp::FutureReturnCode
|
||||
rclcpp::executor::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
std::shared_ptr<NodeT> node_ptr,
|
||||
const FutureT & future,
|
||||
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);
|
||||
|
||||
@@ -15,14 +15,12 @@
|
||||
#ifndef RCLCPP__EXECUTORS__MULTI_THREADED_EXECUTOR_HPP_
|
||||
#define RCLCPP__EXECUTORS__MULTI_THREADED_EXECUTOR_HPP_
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "rclcpp/detail/mutex_two_priorities.hpp"
|
||||
#include "rclcpp/executor.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/memory_strategies.hpp"
|
||||
@@ -33,7 +31,7 @@ namespace rclcpp
|
||||
namespace executors
|
||||
{
|
||||
|
||||
class MultiThreadedExecutor : public rclcpp::Executor
|
||||
class MultiThreadedExecutor : public executor::Executor
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(MultiThreadedExecutor)
|
||||
@@ -46,7 +44,7 @@ public:
|
||||
* This is useful for reproducing some bugs related to taking work more than
|
||||
* once.
|
||||
*
|
||||
* \param options common options for all executors
|
||||
* \param args common arguments for all executors
|
||||
* \param number_of_threads number of threads to have in the thread pool,
|
||||
* the default 0 will use the number of cpu cores found instead
|
||||
* \param yield_before_execute if true std::this_thread::yield() is called
|
||||
@@ -54,21 +52,16 @@ public:
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
MultiThreadedExecutor(
|
||||
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions(),
|
||||
const executor::ExecutorArgs & args = executor::ExecutorArgs(),
|
||||
size_t number_of_threads = 0,
|
||||
bool yield_before_execute = false,
|
||||
std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
|
||||
bool yield_before_execute = false);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~MultiThreadedExecutor();
|
||||
|
||||
/**
|
||||
* \sa rclcpp::Executor:spin() for more details
|
||||
* \throws std::runtime_error when spin() called while already spinning
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin() override;
|
||||
spin();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
@@ -82,10 +75,9 @@ protected:
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(MultiThreadedExecutor)
|
||||
|
||||
detail::MutexTwoPriorities wait_mutex_;
|
||||
std::mutex wait_mutex_;
|
||||
size_t number_of_threads_;
|
||||
bool yield_before_execute_;
|
||||
std::chrono::nanoseconds next_exec_timeout_;
|
||||
|
||||
std::set<TimerBase::SharedPtr> scheduled_timers_;
|
||||
};
|
||||
|
||||
@@ -35,35 +35,28 @@ namespace rclcpp
|
||||
namespace executors
|
||||
{
|
||||
|
||||
/// Single-threaded executor implementation.
|
||||
/**
|
||||
* This is the default executor created by rclcpp::spin.
|
||||
*/
|
||||
class SingleThreadedExecutor : public rclcpp::Executor
|
||||
/// Single-threaded executor implementation
|
||||
// This is the default executor created by rclcpp::spin.
|
||||
class SingleThreadedExecutor : public executor::Executor
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(SingleThreadedExecutor)
|
||||
|
||||
/// Default constructor. See the default constructor for Executor.
|
||||
RCLCPP_PUBLIC
|
||||
explicit SingleThreadedExecutor(
|
||||
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
|
||||
SingleThreadedExecutor(
|
||||
const executor::ExecutorArgs & args = executor::ExecutorArgs());
|
||||
|
||||
/// Default destructor.
|
||||
/// Default destrcutor.
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~SingleThreadedExecutor();
|
||||
|
||||
/// Single-threaded implementation of spin.
|
||||
/**
|
||||
* This function will block until work comes in, execute it, and then repeat
|
||||
* the process until canceled.
|
||||
* It may be interrupt by a call to rclcpp::Executor::cancel() or by ctrl-c
|
||||
* if the associated context is configured to shutdown on SIGINT.
|
||||
* \throws std::runtime_error when spin() called while already spinning
|
||||
*/
|
||||
// This function will block until work comes in, execute it, and keep blocking.
|
||||
// It will only be interrupt by a CTRL-C (managed by the global signal handler).
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin() override;
|
||||
spin();
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(SingleThreadedExecutor)
|
||||
|
||||
@@ -1,354 +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__EXECUTORS__STATIC_EXECUTOR_ENTITIES_COLLECTOR_HPP_
|
||||
#define RCLCPP__EXECUTORS__STATIC_EXECUTOR_ENTITIES_COLLECTOR_HPP_
|
||||
|
||||
#include <chrono>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/guard_condition.h"
|
||||
#include "rcl/wait.h"
|
||||
|
||||
#include "rclcpp/experimental/executable_list.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/memory_strategy.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rclcpp/waitable.hpp"
|
||||
|
||||
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,
|
||||
public std::enable_shared_from_this<StaticExecutorEntitiesCollector>
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(StaticExecutorEntitiesCollector)
|
||||
|
||||
// Constructor
|
||||
RCLCPP_PUBLIC
|
||||
StaticExecutorEntitiesCollector() = default;
|
||||
|
||||
// Destructor
|
||||
RCLCPP_PUBLIC
|
||||
~StaticExecutorEntitiesCollector();
|
||||
|
||||
/// Initialize StaticExecutorEntitiesCollector
|
||||
/**
|
||||
* \param p_wait_set A reference to the wait set to be used in the executor
|
||||
* \param memory_strategy Shared pointer to the memory strategy to set.
|
||||
* \param executor_guard_condition executor's guard condition
|
||||
* \throws std::runtime_error if memory strategy is null
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
init(
|
||||
rcl_wait_set_t * p_wait_set,
|
||||
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;
|
||||
|
||||
/// Take the data so that it can be consumed with `execute`.
|
||||
/**
|
||||
* For `StaticExecutorEntitiesCollector`, this always return `nullptr`.
|
||||
* \sa rclcpp::Waitable::take_data()
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<void>
|
||||
take_data() override;
|
||||
|
||||
/// 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()
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
refresh_wait_set(std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
|
||||
|
||||
/**
|
||||
* \throws std::runtime_error if it couldn't add guard condition to wait set
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
add_to_wait_set(rcl_wait_set_t * wait_set) override;
|
||||
|
||||
RCLCPP_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()
|
||||
* \throw std::runtime_error if node was already added
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
add_node(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
|
||||
|
||||
/**
|
||||
* \see rclcpp::Executor::remove_node()
|
||||
* \throw std::runtime_error if no guard condition is associated with node.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
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
|
||||
* (or a spurious wakeup happened) we are really ready to execute
|
||||
* i.e. re-collect entities
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
is_ready(rcl_wait_set_t * wait_set) override;
|
||||
|
||||
/// Return number of timers
|
||||
/**
|
||||
* \return number of timers
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_number_of_timers() {return exec_list_.number_of_timers;}
|
||||
|
||||
/// Return number of subscriptions
|
||||
/**
|
||||
* \return number of subscriptions
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_number_of_subscriptions() {return exec_list_.number_of_subscriptions;}
|
||||
|
||||
/// Return number of services
|
||||
/**
|
||||
* \return number of services
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_number_of_services() {return exec_list_.number_of_services;}
|
||||
|
||||
/// Return number of clients
|
||||
/**
|
||||
* \return number of clients
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_number_of_clients() {return exec_list_.number_of_clients;}
|
||||
|
||||
/// Return number of waitables
|
||||
/**
|
||||
* \return number of waitables
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_number_of_waitables() {return exec_list_.number_of_waitables;}
|
||||
|
||||
/** Return a SubscritionBase Sharedptr by index.
|
||||
* \param[in] i The index of the SubscritionBase
|
||||
* \return a SubscritionBase shared pointer
|
||||
* \throws std::out_of_range if the argument is higher than the size of the structrue.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::SubscriptionBase::SharedPtr
|
||||
get_subscription(size_t i) {return exec_list_.subscription[i];}
|
||||
|
||||
/** Return a TimerBase Sharedptr by index.
|
||||
* \param[in] i The index of the TimerBase
|
||||
* \return a TimerBase shared pointer
|
||||
* \throws std::out_of_range if the argument is higher than the size.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::TimerBase::SharedPtr
|
||||
get_timer(size_t i) {return exec_list_.timer[i];}
|
||||
|
||||
/** Return a ServiceBase Sharedptr by index.
|
||||
* \param[in] i The index of the ServiceBase
|
||||
* \return a ServiceBase shared pointer
|
||||
* \throws std::out_of_range if the argument is higher than the size.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::ServiceBase::SharedPtr
|
||||
get_service(size_t i) {return exec_list_.service[i];}
|
||||
|
||||
/** Return a ClientBase Sharedptr by index
|
||||
* \param[in] i The index of the ClientBase
|
||||
* \return a ClientBase shared pointer
|
||||
* \throws std::out_of_range if the argument is higher than the size.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::ClientBase::SharedPtr
|
||||
get_client(size_t i) {return exec_list_.client[i];}
|
||||
|
||||
/** Return a Waitable Sharedptr by index
|
||||
* \param[in] i The index of the Waitable
|
||||
* \return a Waitable shared pointer
|
||||
* \throws std::out_of_range if the argument is higher than the size.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::Waitable::SharedPtr
|
||||
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);
|
||||
|
||||
/// 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_;
|
||||
|
||||
/// Wait set for managing entities that the rmw layer waits on.
|
||||
rcl_wait_set_t * p_wait_set_ = nullptr;
|
||||
|
||||
/// 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
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXECUTORS__STATIC_EXECUTOR_ENTITIES_COLLECTOR_HPP_
|
||||
@@ -1,222 +0,0 @@
|
||||
// Copyright 2019 Nobleo Technology
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_
|
||||
#define RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_
|
||||
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "rmw/rmw.h"
|
||||
|
||||
#include "rclcpp/executor.hpp"
|
||||
#include "rclcpp/executors/static_executor_entities_collector.hpp"
|
||||
#include "rclcpp/experimental/executable_list.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/memory_strategies.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/rate.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
|
||||
/// Static executor implementation
|
||||
/**
|
||||
* This executor is a static version of the original single threaded executor.
|
||||
* It's static because it doesn't reconstruct the executable list for every iteration.
|
||||
* All nodes, callbackgroups, timers, subscriptions etc. are created before
|
||||
* spin() is called, and modified only when an entity is added/removed to/from a node.
|
||||
*
|
||||
* To run this executor instead of SingleThreadedExecutor replace:
|
||||
* rclcpp::executors::SingleThreadedExecutor exec;
|
||||
* by
|
||||
* rclcpp::executors::StaticSingleThreadedExecutor exec;
|
||||
* in your source code and spin node(s) in the following way:
|
||||
* exec.add_node(node);
|
||||
* exec.spin();
|
||||
* exec.remove_node(node);
|
||||
*/
|
||||
class StaticSingleThreadedExecutor : public rclcpp::Executor
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(StaticSingleThreadedExecutor)
|
||||
|
||||
/// Default constructor. See the default constructor for Executor.
|
||||
RCLCPP_PUBLIC
|
||||
explicit StaticSingleThreadedExecutor(
|
||||
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
|
||||
|
||||
/// Default destrcutor.
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~StaticSingleThreadedExecutor();
|
||||
|
||||
/// Static executor implementation of spin.
|
||||
/**
|
||||
* This function will block until work comes in, execute it, and keep blocking.
|
||||
* It will only be interrupted by a CTRL-C (managed by the global signal handler).
|
||||
* \throws std::runtime_error when spin() called while already spinning
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin() override;
|
||||
|
||||
/// Static executor implementation of spin some
|
||||
/**
|
||||
* This non-blocking function will execute entities that
|
||||
* were ready when this API was called, until timeout or no
|
||||
* more work available. Entities that got ready while
|
||||
* executing work, won't be taken into account here.
|
||||
*
|
||||
* Example:
|
||||
* while(condition) {
|
||||
* spin_some();
|
||||
* sleep(); // User should have some sync work or
|
||||
* // sleep to avoid a 100% CPU usage
|
||||
* }
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_some(std::chrono::nanoseconds max_duration = std::chrono::nanoseconds(0)) override;
|
||||
|
||||
/// Static executor implementation of spin all
|
||||
/**
|
||||
* This non-blocking function will execute entities until
|
||||
* timeout 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
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_node(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
bool notify = true) override;
|
||||
|
||||
/// Convenience function which takes Node and forwards NodeBaseInterface.
|
||||
/**
|
||||
* \sa rclcpp::StaticSingleThreadedExecutor::add_node
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true) override;
|
||||
|
||||
/// Remove a node from the executor.
|
||||
/**
|
||||
* \sa rclcpp::Executor::remove_node
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_node(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
bool notify = true) override;
|
||||
|
||||
/// Convenience function which takes Node and forwards NodeBaseInterface.
|
||||
/**
|
||||
* \sa rclcpp::Executor::remove_node
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::CallbackGroup::WeakPtr>
|
||||
get_all_callback_groups() override;
|
||||
|
||||
/// Get callback groups that belong to executor.
|
||||
/**
|
||||
* \sa rclcpp::Executor::get_manually_added_callback_groups()
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::CallbackGroup::WeakPtr>
|
||||
get_manually_added_callback_groups() override;
|
||||
|
||||
/// Get callback groups that belong to executor.
|
||||
/**
|
||||
* \sa rclcpp::Executor::get_automatically_added_callback_groups_from_nodes()
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::CallbackGroup::WeakPtr>
|
||||
get_automatically_added_callback_groups_from_nodes() override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
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;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(StaticSingleThreadedExecutor)
|
||||
|
||||
StaticExecutorEntitiesCollector::SharedPtr entities_collector_;
|
||||
};
|
||||
|
||||
} // namespace executors
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_
|
||||
@@ -49,8 +49,6 @@ namespace rclcpp
|
||||
* \throws InvalidServiceNameError if name is invalid and is_service is true
|
||||
* \throws std::bad_alloc if memory cannot be allocated
|
||||
* \throws RCLError if an unexpect error occurs
|
||||
* \throws std::runtime_error if the topic name is unexpectedly valid or,
|
||||
* if the rcl name is invalid or if the rcl namespace is invalid
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
Notice that headers in this folder should only provide symbols in the rclcpp::experimental namespace.
|
||||
|
||||
Also notice that these headers are not considered part of the public API as they have not yet been stabilized.
|
||||
And therefore they are subject to change without notice.
|
||||
@@ -1,42 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXPERIMENTAL__BUFFERS__BUFFER_IMPLEMENTATION_BASE_HPP_
|
||||
#define RCLCPP__EXPERIMENTAL__BUFFERS__BUFFER_IMPLEMENTATION_BASE_HPP_
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace buffers
|
||||
{
|
||||
|
||||
template<typename BufferT>
|
||||
class BufferImplementationBase
|
||||
{
|
||||
public:
|
||||
virtual ~BufferImplementationBase() {}
|
||||
|
||||
virtual BufferT dequeue() = 0;
|
||||
virtual void enqueue(BufferT request) = 0;
|
||||
|
||||
virtual void clear() = 0;
|
||||
virtual bool has_data() const = 0;
|
||||
};
|
||||
|
||||
} // namespace buffers
|
||||
} // namespace experimental
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXPERIMENTAL__BUFFERS__BUFFER_IMPLEMENTATION_BASE_HPP_
|
||||
@@ -1,241 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXPERIMENTAL__BUFFERS__INTRA_PROCESS_BUFFER_HPP_
|
||||
#define RCLCPP__EXPERIMENTAL__BUFFERS__INTRA_PROCESS_BUFFER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/allocator/allocator_common.hpp"
|
||||
#include "rclcpp/allocator/allocator_deleter.hpp"
|
||||
#include "rclcpp/experimental/buffers/buffer_implementation_base.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace buffers
|
||||
{
|
||||
|
||||
class IntraProcessBufferBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(IntraProcessBufferBase)
|
||||
|
||||
virtual ~IntraProcessBufferBase() {}
|
||||
|
||||
virtual void clear() = 0;
|
||||
|
||||
virtual bool has_data() const = 0;
|
||||
virtual bool use_take_shared_method() const = 0;
|
||||
};
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename MessageDeleter = std::default_delete<MessageT>>
|
||||
class IntraProcessBuffer : public IntraProcessBufferBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(IntraProcessBuffer)
|
||||
|
||||
virtual ~IntraProcessBuffer() {}
|
||||
|
||||
using MessageUniquePtr = std::unique_ptr<MessageT, MessageDeleter>;
|
||||
using MessageSharedPtr = std::shared_ptr<const MessageT>;
|
||||
|
||||
virtual void add_shared(MessageSharedPtr msg) = 0;
|
||||
virtual void add_unique(MessageUniquePtr msg) = 0;
|
||||
|
||||
virtual MessageSharedPtr consume_shared() = 0;
|
||||
virtual MessageUniquePtr consume_unique() = 0;
|
||||
};
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename MessageDeleter = std::default_delete<MessageT>,
|
||||
typename BufferT = std::unique_ptr<MessageT>>
|
||||
class TypedIntraProcessBuffer : public IntraProcessBuffer<MessageT, Alloc, MessageDeleter>
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(TypedIntraProcessBuffer)
|
||||
|
||||
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
|
||||
using MessageAlloc = typename MessageAllocTraits::allocator_type;
|
||||
using MessageUniquePtr = std::unique_ptr<MessageT, MessageDeleter>;
|
||||
using MessageSharedPtr = std::shared_ptr<const MessageT>;
|
||||
|
||||
explicit
|
||||
TypedIntraProcessBuffer(
|
||||
std::unique_ptr<BufferImplementationBase<BufferT>> buffer_impl,
|
||||
std::shared_ptr<Alloc> allocator = nullptr)
|
||||
{
|
||||
bool valid_type = (std::is_same<BufferT, MessageSharedPtr>::value ||
|
||||
std::is_same<BufferT, MessageUniquePtr>::value);
|
||||
if (!valid_type) {
|
||||
throw std::runtime_error("Creating TypedIntraProcessBuffer with not valid BufferT");
|
||||
}
|
||||
|
||||
buffer_ = std::move(buffer_impl);
|
||||
|
||||
if (!allocator) {
|
||||
message_allocator_ = std::make_shared<MessageAlloc>();
|
||||
} else {
|
||||
message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~TypedIntraProcessBuffer() {}
|
||||
|
||||
void add_shared(MessageSharedPtr msg) override
|
||||
{
|
||||
add_shared_impl<BufferT>(std::move(msg));
|
||||
}
|
||||
|
||||
void add_unique(MessageUniquePtr msg) override
|
||||
{
|
||||
buffer_->enqueue(std::move(msg));
|
||||
}
|
||||
|
||||
MessageSharedPtr consume_shared() override
|
||||
{
|
||||
return consume_shared_impl<BufferT>();
|
||||
}
|
||||
|
||||
MessageUniquePtr consume_unique() override
|
||||
{
|
||||
return consume_unique_impl<BufferT>();
|
||||
}
|
||||
|
||||
bool has_data() const override
|
||||
{
|
||||
return buffer_->has_data();
|
||||
}
|
||||
|
||||
void clear() override
|
||||
{
|
||||
buffer_->clear();
|
||||
}
|
||||
|
||||
bool use_take_shared_method() const override
|
||||
{
|
||||
return std::is_same<BufferT, MessageSharedPtr>::value;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<BufferImplementationBase<BufferT>> buffer_;
|
||||
|
||||
std::shared_ptr<MessageAlloc> message_allocator_;
|
||||
|
||||
// MessageSharedPtr to MessageSharedPtr
|
||||
template<typename DestinationT>
|
||||
typename std::enable_if<
|
||||
std::is_same<DestinationT, MessageSharedPtr>::value
|
||||
>::type
|
||||
add_shared_impl(MessageSharedPtr shared_msg)
|
||||
{
|
||||
buffer_->enqueue(std::move(shared_msg));
|
||||
}
|
||||
|
||||
// MessageSharedPtr to MessageUniquePtr
|
||||
template<typename DestinationT>
|
||||
typename std::enable_if<
|
||||
std::is_same<DestinationT, MessageUniquePtr>::value
|
||||
>::type
|
||||
add_shared_impl(MessageSharedPtr shared_msg)
|
||||
{
|
||||
// This should not happen: here a copy is unconditionally made, while the intra-process manager
|
||||
// can decide whether a copy is needed depending on the number and the type of buffers
|
||||
|
||||
MessageUniquePtr unique_msg;
|
||||
MessageDeleter * deleter = std::get_deleter<MessageDeleter, const MessageT>(shared_msg);
|
||||
auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
|
||||
MessageAllocTraits::construct(*message_allocator_.get(), ptr, *shared_msg);
|
||||
if (deleter) {
|
||||
unique_msg = MessageUniquePtr(ptr, *deleter);
|
||||
} else {
|
||||
unique_msg = MessageUniquePtr(ptr);
|
||||
}
|
||||
|
||||
buffer_->enqueue(std::move(unique_msg));
|
||||
}
|
||||
|
||||
// MessageSharedPtr to MessageSharedPtr
|
||||
template<typename OriginT>
|
||||
typename std::enable_if<
|
||||
std::is_same<OriginT, MessageSharedPtr>::value,
|
||||
MessageSharedPtr
|
||||
>::type
|
||||
consume_shared_impl()
|
||||
{
|
||||
return buffer_->dequeue();
|
||||
}
|
||||
|
||||
// MessageUniquePtr to MessageSharedPtr
|
||||
template<typename OriginT>
|
||||
typename std::enable_if<
|
||||
(std::is_same<OriginT, MessageUniquePtr>::value),
|
||||
MessageSharedPtr
|
||||
>::type
|
||||
consume_shared_impl()
|
||||
{
|
||||
// automatic cast from unique ptr to shared ptr
|
||||
return buffer_->dequeue();
|
||||
}
|
||||
|
||||
// MessageSharedPtr to MessageUniquePtr
|
||||
template<typename OriginT>
|
||||
typename std::enable_if<
|
||||
(std::is_same<OriginT, MessageSharedPtr>::value),
|
||||
MessageUniquePtr
|
||||
>::type
|
||||
consume_unique_impl()
|
||||
{
|
||||
MessageSharedPtr buffer_msg = buffer_->dequeue();
|
||||
|
||||
MessageUniquePtr unique_msg;
|
||||
MessageDeleter * deleter = std::get_deleter<MessageDeleter, const MessageT>(buffer_msg);
|
||||
auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
|
||||
MessageAllocTraits::construct(*message_allocator_.get(), ptr, *buffer_msg);
|
||||
if (deleter) {
|
||||
unique_msg = MessageUniquePtr(ptr, *deleter);
|
||||
} else {
|
||||
unique_msg = MessageUniquePtr(ptr);
|
||||
}
|
||||
|
||||
return unique_msg;
|
||||
}
|
||||
|
||||
// MessageUniquePtr to MessageUniquePtr
|
||||
template<typename OriginT>
|
||||
typename std::enable_if<
|
||||
(std::is_same<OriginT, MessageUniquePtr>::value),
|
||||
MessageUniquePtr
|
||||
>::type
|
||||
consume_unique_impl()
|
||||
{
|
||||
return buffer_->dequeue();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace buffers
|
||||
} // namespace experimental
|
||||
} // namespace rclcpp
|
||||
|
||||
|
||||
#endif // RCLCPP__EXPERIMENTAL__BUFFERS__INTRA_PROCESS_BUFFER_HPP_
|
||||
@@ -1,196 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
|
||||
#define RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/experimental/buffers/buffer_implementation_base.hpp"
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
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>
|
||||
{
|
||||
public:
|
||||
explicit RingBufferImplementation(size_t capacity)
|
||||
: capacity_(capacity),
|
||||
ring_buffer_(capacity),
|
||||
write_index_(capacity_ - 1),
|
||||
read_index_(0),
|
||||
size_(0)
|
||||
{
|
||||
if (capacity == 0) {
|
||||
throw std::invalid_argument("capacity must be a positive, non-zero value");
|
||||
}
|
||||
}
|
||||
|
||||
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_);
|
||||
ring_buffer_[write_index_] = std::move(request);
|
||||
|
||||
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_()) {
|
||||
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_);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/// 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_();
|
||||
}
|
||||
|
||||
/// 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
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return is_full_();
|
||||
}
|
||||
|
||||
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_;
|
||||
|
||||
size_t write_index_;
|
||||
size_t read_index_;
|
||||
size_t size_;
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
};
|
||||
|
||||
} // namespace buffers
|
||||
} // namespace experimental
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
|
||||
@@ -1,99 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXPERIMENTAL__CREATE_INTRA_PROCESS_BUFFER_HPP_
|
||||
#define RCLCPP__EXPERIMENTAL__CREATE_INTRA_PROCESS_BUFFER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "rcl/subscription.h"
|
||||
|
||||
#include "rclcpp/experimental/buffers/intra_process_buffer.hpp"
|
||||
#include "rclcpp/experimental/buffers/ring_buffer_implementation.hpp"
|
||||
#include "rclcpp/intra_process_buffer_type.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>>
|
||||
typename rclcpp::experimental::buffers::IntraProcessBuffer<MessageT, Alloc, Deleter>::UniquePtr
|
||||
create_intra_process_buffer(
|
||||
IntraProcessBufferType buffer_type,
|
||||
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;
|
||||
|
||||
using rclcpp::experimental::buffers::IntraProcessBuffer;
|
||||
typename IntraProcessBuffer<MessageT, Alloc, Deleter>::UniquePtr buffer;
|
||||
|
||||
switch (buffer_type) {
|
||||
case IntraProcessBufferType::SharedPtr:
|
||||
{
|
||||
using BufferT = MessageSharedPtr;
|
||||
|
||||
auto buffer_implementation =
|
||||
std::make_unique<rclcpp::experimental::buffers::RingBufferImplementation<BufferT>>(
|
||||
buffer_size);
|
||||
|
||||
// Construct the intra_process_buffer
|
||||
buffer =
|
||||
std::make_unique<rclcpp::experimental::buffers::TypedIntraProcessBuffer<MessageT, Alloc,
|
||||
Deleter, BufferT>>(
|
||||
std::move(buffer_implementation),
|
||||
allocator);
|
||||
|
||||
break;
|
||||
}
|
||||
case IntraProcessBufferType::UniquePtr:
|
||||
{
|
||||
using BufferT = MessageUniquePtr;
|
||||
|
||||
auto buffer_implementation =
|
||||
std::make_unique<rclcpp::experimental::buffers::RingBufferImplementation<BufferT>>(
|
||||
buffer_size);
|
||||
|
||||
// Construct the intra_process_buffer
|
||||
buffer =
|
||||
std::make_unique<rclcpp::experimental::buffers::TypedIntraProcessBuffer<MessageT, Alloc,
|
||||
Deleter, BufferT>>(
|
||||
std::move(buffer_implementation),
|
||||
allocator);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw std::runtime_error("Unrecognized IntraProcessBufferType value");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXPERIMENTAL__CREATE_INTRA_PROCESS_BUFFER_HPP_
|
||||
@@ -1,92 +0,0 @@
|
||||
// Copyright 2019 Nobleo Technology
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_
|
||||
#define RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/client.hpp"
|
||||
#include "rclcpp/service.hpp"
|
||||
#include "rclcpp/subscription_base.hpp"
|
||||
#include "rclcpp/timer.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rclcpp/waitable.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
/// This class contains subscriptionbase, timerbase, etc. which can be used to run callbacks.
|
||||
class ExecutableList final
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
ExecutableList();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
~ExecutableList();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
clear();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_subscription(rclcpp::SubscriptionBase::SharedPtr subscription);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_timer(rclcpp::TimerBase::SharedPtr timer);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_service(rclcpp::ServiceBase::SharedPtr service);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_client(rclcpp::ClientBase::SharedPtr client);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_waitable(rclcpp::Waitable::SharedPtr waitable);
|
||||
|
||||
// Vector containing the SubscriptionBase of all the subscriptions added to the executor.
|
||||
std::vector<rclcpp::SubscriptionBase::SharedPtr> subscription;
|
||||
// Contains the count of added subscriptions
|
||||
size_t number_of_subscriptions;
|
||||
// Vector containing the TimerBase of all the timers added to the executor.
|
||||
std::vector<rclcpp::TimerBase::SharedPtr> timer;
|
||||
// Contains the count of added timers
|
||||
size_t number_of_timers;
|
||||
// Vector containing the ServiceBase of all the services added to the executor.
|
||||
std::vector<rclcpp::ServiceBase::SharedPtr> service;
|
||||
// Contains the count of added services
|
||||
size_t number_of_services;
|
||||
// Vector containing the ClientBase of all the clients added to the executor.
|
||||
std::vector<rclcpp::ClientBase::SharedPtr> client;
|
||||
// Contains the count of added clients
|
||||
size_t number_of_clients;
|
||||
// Vector containing all the waitables added to the executor.
|
||||
std::vector<rclcpp::Waitable::SharedPtr> waitable;
|
||||
// Contains the count of added waitables
|
||||
size_t number_of_waitables;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_
|
||||
@@ -1,448 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXPERIMENTAL__INTRA_PROCESS_MANAGER_HPP_
|
||||
#define RCLCPP__EXPERIMENTAL__INTRA_PROCESS_MANAGER_HPP_
|
||||
|
||||
#include <rmw/types.h>
|
||||
|
||||
#include <shared_mutex>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/allocator/allocator_deleter.hpp"
|
||||
#include "rclcpp/experimental/subscription_intra_process.hpp"
|
||||
#include "rclcpp/experimental/subscription_intra_process_base.hpp"
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/publisher_base.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
/// This class performs intra process communication between nodes.
|
||||
/**
|
||||
* This class is used in the creation of publishers and subscriptions.
|
||||
* A singleton instance of this class is owned by a rclcpp::Context and a
|
||||
* rclcpp::Node can use an associated Context to get an instance of this class.
|
||||
* Nodes which do not have a common Context will not exchange intra process
|
||||
* messages because they do not share access to the same instance of this class.
|
||||
*
|
||||
* When a Node creates a subscription, it can also create a helper class,
|
||||
* called SubscriptionIntraProcess, meant to receive intra process messages.
|
||||
* It can be registered with this class.
|
||||
* It is also allocated an id which is unique among all publishers
|
||||
* and subscriptions in this process and that is associated to the subscription.
|
||||
*
|
||||
* When a Node creates a publisher, as with subscriptions, a helper class can
|
||||
* be registered with this class.
|
||||
* This is required in order to publish intra-process messages.
|
||||
* It is also allocated an id which is unique among all publishers
|
||||
* and subscriptions in this process and that is associated to the publisher.
|
||||
*
|
||||
* When a publisher or a subscription are registered, this class checks to see
|
||||
* which other subscriptions or publishers it will communicate with,
|
||||
* i.e. they have the same topic and compatible QoS.
|
||||
*
|
||||
* When the user publishes a message, if intra-process communication is enabled
|
||||
* on the publisher, the message is given to this class.
|
||||
* Using the publisher id, a list of recipients for the message is selected.
|
||||
* For each subscription in the list, this class stores the message, whether
|
||||
* sharing ownership or making a copy, in a buffer associated with the
|
||||
* subscription helper class.
|
||||
*
|
||||
* The subscription helper class contains a buffer where published
|
||||
* intra-process messages are stored until they are taken from the subscription.
|
||||
* Depending on the data type stored in the buffer, the subscription helper
|
||||
* class can request either shared or exclusive ownership on the message.
|
||||
*
|
||||
* Thus, when an intra-process message is published, this class knows how many
|
||||
* intra-process subscriptions needs it and how many require ownership.
|
||||
* This information allows this class to operate efficiently by performing the
|
||||
* fewest number of copies of the message required.
|
||||
*
|
||||
* This class is neither CopyConstructable nor CopyAssignable.
|
||||
*/
|
||||
class IntraProcessManager
|
||||
{
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(IntraProcessManager)
|
||||
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(IntraProcessManager)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
IntraProcessManager();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~IntraProcessManager();
|
||||
|
||||
/// Register a subscription with the manager, returns subscriptions unique id.
|
||||
/**
|
||||
* This method stores the subscription intra process object, together with
|
||||
* the information of its wrapped subscription (i.e. topic name and QoS).
|
||||
*
|
||||
* In addition this generates a unique intra process id for the subscription.
|
||||
*
|
||||
* \param subscription the SubscriptionIntraProcess to register.
|
||||
* \return an unsigned 64-bit integer which is the subscription's unique id.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
uint64_t
|
||||
add_subscription(rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr subscription);
|
||||
|
||||
/// Unregister a subscription using the subscription's unique id.
|
||||
/**
|
||||
* This method does not allocate memory.
|
||||
*
|
||||
* \param intra_process_subscription_id id of the subscription to remove.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_subscription(uint64_t intra_process_subscription_id);
|
||||
|
||||
/// Register a publisher with the manager, returns the publisher unique id.
|
||||
/**
|
||||
* This method stores the publisher intra process object, together with
|
||||
* the information of its wrapped publisher (i.e. topic name and QoS).
|
||||
*
|
||||
* In addition this generates a unique intra process id for the publisher.
|
||||
*
|
||||
* \param publisher publisher to be registered with the manager.
|
||||
* \return an unsigned 64-bit integer which is the publisher's unique id.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
uint64_t
|
||||
add_publisher(rclcpp::PublisherBase::SharedPtr publisher);
|
||||
|
||||
/// Unregister a publisher using the publisher's unique id.
|
||||
/**
|
||||
* This method does not allocate memory.
|
||||
*
|
||||
* \param intra_process_publisher_id id of the publisher to remove.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_publisher(uint64_t intra_process_publisher_id);
|
||||
|
||||
/// Publishes an intra-process message, passed as a unique pointer.
|
||||
/**
|
||||
* This is one of the two methods for publishing intra-process.
|
||||
*
|
||||
* Using the intra-process publisher id, a list of recipients is obtained.
|
||||
* This list is split in half, depending whether they require ownership or not.
|
||||
*
|
||||
* This particular method takes a unique pointer as input.
|
||||
* The pointer can be promoted to a shared pointer and passed to all the subscriptions
|
||||
* that do not require ownership.
|
||||
* In case of subscriptions requiring ownership, the message will be copied for all of
|
||||
* them except the last one, when ownership can be transferred.
|
||||
*
|
||||
* This method can save an additional copy compared to the shared pointer one.
|
||||
*
|
||||
* This method can throw an exception if the publisher id is not found or
|
||||
* if the publisher shared_ptr given to add_publisher has gone out of scope.
|
||||
*
|
||||
* This method does allocate memory.
|
||||
*
|
||||
* \param intra_process_publisher_id the id of the publisher of this message.
|
||||
* \param message the message that is being stored.
|
||||
*/
|
||||
template<
|
||||
typename MessageT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>>
|
||||
void
|
||||
do_intra_process_publish(
|
||||
uint64_t intra_process_publisher_id,
|
||||
std::unique_ptr<MessageT, Deleter> message,
|
||||
std::shared_ptr<typename allocator::AllocRebind<MessageT, Alloc>::allocator_type> allocator)
|
||||
{
|
||||
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
|
||||
using MessageAllocatorT = typename MessageAllocTraits::allocator_type;
|
||||
|
||||
std::shared_lock<std::shared_timed_mutex> lock(mutex_);
|
||||
|
||||
auto publisher_it = pub_to_subs_.find(intra_process_publisher_id);
|
||||
if (publisher_it == pub_to_subs_.end()) {
|
||||
// Publisher is either invalid or no longer exists.
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Calling do_intra_process_publish for invalid or no longer existing publisher id");
|
||||
return;
|
||||
}
|
||||
const auto & sub_ids = publisher_it->second;
|
||||
|
||||
if (sub_ids.take_ownership_subscriptions.empty()) {
|
||||
// None of the buffers require ownership, so we promote the pointer
|
||||
std::shared_ptr<MessageT> msg = std::move(message);
|
||||
|
||||
this->template add_shared_msg_to_buffers<MessageT, Alloc, Deleter>(
|
||||
msg, sub_ids.take_shared_subscriptions);
|
||||
} else if (!sub_ids.take_ownership_subscriptions.empty() && // NOLINT
|
||||
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
|
||||
|
||||
// Merge the two vector of ids into a unique one
|
||||
std::vector<uint64_t> concatenated_vector(sub_ids.take_shared_subscriptions);
|
||||
concatenated_vector.insert(
|
||||
concatenated_vector.end(),
|
||||
sub_ids.take_ownership_subscriptions.begin(),
|
||||
sub_ids.take_ownership_subscriptions.end());
|
||||
|
||||
this->template add_owned_msg_to_buffers<MessageT, Alloc, Deleter>(
|
||||
std::move(message),
|
||||
concatenated_vector,
|
||||
allocator);
|
||||
} else if (!sub_ids.take_ownership_subscriptions.empty() && // NOLINT
|
||||
sub_ids.take_shared_subscriptions.size() > 1)
|
||||
{
|
||||
// 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);
|
||||
|
||||
this->template add_shared_msg_to_buffers<MessageT, Alloc, Deleter>(
|
||||
shared_msg, sub_ids.take_shared_subscriptions);
|
||||
this->template add_owned_msg_to_buffers<MessageT, Alloc, Deleter>(
|
||||
std::move(message), sub_ids.take_ownership_subscriptions, allocator);
|
||||
}
|
||||
}
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>>
|
||||
std::shared_ptr<const MessageT>
|
||||
do_intra_process_publish_and_return_shared(
|
||||
uint64_t intra_process_publisher_id,
|
||||
std::unique_ptr<MessageT, Deleter> message,
|
||||
std::shared_ptr<typename allocator::AllocRebind<MessageT, Alloc>::allocator_type> allocator)
|
||||
{
|
||||
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
|
||||
using MessageAllocatorT = typename MessageAllocTraits::allocator_type;
|
||||
|
||||
std::shared_lock<std::shared_timed_mutex> lock(mutex_);
|
||||
|
||||
auto publisher_it = pub_to_subs_.find(intra_process_publisher_id);
|
||||
if (publisher_it == pub_to_subs_.end()) {
|
||||
// Publisher is either invalid or no longer exists.
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Calling do_intra_process_publish for invalid or no longer existing publisher id");
|
||||
return nullptr;
|
||||
}
|
||||
const auto & sub_ids = publisher_it->second;
|
||||
|
||||
if (sub_ids.take_ownership_subscriptions.empty()) {
|
||||
// If there are no owning, just convert to shared.
|
||||
std::shared_ptr<MessageT> shared_msg = std::move(message);
|
||||
if (!sub_ids.take_shared_subscriptions.empty()) {
|
||||
this->template add_shared_msg_to_buffers<MessageT, Alloc, Deleter>(
|
||||
shared_msg, sub_ids.take_shared_subscriptions);
|
||||
}
|
||||
return shared_msg;
|
||||
} 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);
|
||||
|
||||
if (!sub_ids.take_shared_subscriptions.empty()) {
|
||||
this->template add_shared_msg_to_buffers<MessageT, Alloc, Deleter>(
|
||||
shared_msg,
|
||||
sub_ids.take_shared_subscriptions);
|
||||
}
|
||||
if (!sub_ids.take_ownership_subscriptions.empty()) {
|
||||
this->template add_owned_msg_to_buffers<MessageT, Alloc, Deleter>(
|
||||
std::move(message),
|
||||
sub_ids.take_ownership_subscriptions,
|
||||
allocator);
|
||||
}
|
||||
|
||||
return shared_msg;
|
||||
}
|
||||
}
|
||||
|
||||
/// Return true if the given rmw_gid_t matches any stored Publishers.
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
matches_any_publishers(const rmw_gid_t * id) const;
|
||||
|
||||
/// Return the number of intraprocess subscriptions that are matched with a given publisher id.
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_subscription_count(uint64_t intra_process_publisher_id) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr
|
||||
get_subscription_intra_process(uint64_t intra_process_subscription_id);
|
||||
|
||||
private:
|
||||
struct SubscriptionInfo
|
||||
{
|
||||
SubscriptionInfo() = default;
|
||||
|
||||
rclcpp::experimental::SubscriptionIntraProcessBase::WeakPtr 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;
|
||||
std::vector<uint64_t> take_ownership_subscriptions;
|
||||
};
|
||||
|
||||
using SubscriptionMap =
|
||||
std::unordered_map<uint64_t, SubscriptionInfo>;
|
||||
|
||||
using PublisherMap =
|
||||
std::unordered_map<uint64_t, PublisherInfo>;
|
||||
|
||||
using PublisherToSubscriptionIdsMap =
|
||||
std::unordered_map<uint64_t, SplittedSubscriptions>;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
static
|
||||
uint64_t
|
||||
get_next_unique_id();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
insert_sub_id_for_pub(uint64_t sub_id, uint64_t pub_id, bool use_take_shared_method);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
can_communicate(PublisherInfo pub_info, SubscriptionInfo sub_info) const;
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
typename Alloc,
|
||||
typename Deleter>
|
||||
void
|
||||
add_shared_msg_to_buffers(
|
||||
std::shared_ptr<const MessageT> message,
|
||||
std::vector<uint64_t> subscription_ids)
|
||||
{
|
||||
for (auto id : subscription_ids) {
|
||||
auto subscription_it = subscriptions_.find(id);
|
||||
if (subscription_it == subscriptions_.end()) {
|
||||
throw std::runtime_error("subscription has unexpectedly gone out of scope");
|
||||
}
|
||||
auto subscription_base = subscription_it->second.subscription.lock();
|
||||
if (subscription_base) {
|
||||
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);
|
||||
} else {
|
||||
subscriptions_.erase(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>>
|
||||
void
|
||||
add_owned_msg_to_buffers(
|
||||
std::unique_ptr<MessageT, Deleter> message,
|
||||
std::vector<uint64_t> subscription_ids,
|
||||
std::shared_ptr<typename allocator::AllocRebind<MessageT, Alloc>::allocator_type> allocator)
|
||||
{
|
||||
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
|
||||
using MessageUniquePtr = std::unique_ptr<MessageT, Deleter>;
|
||||
|
||||
for (auto it = subscription_ids.begin(); it != subscription_ids.end(); it++) {
|
||||
auto subscription_it = subscriptions_.find(*it);
|
||||
if (subscription_it == subscriptions_.end()) {
|
||||
throw std::runtime_error("subscription has unexpectedly gone out of scope");
|
||||
}
|
||||
auto subscription_base = subscription_it->second.subscription.lock();
|
||||
if (subscription_base) {
|
||||
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");
|
||||
}
|
||||
|
||||
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.get(), 1);
|
||||
MessageAllocTraits::construct(*allocator.get(), ptr, *message);
|
||||
copy_message = MessageUniquePtr(ptr, deleter);
|
||||
|
||||
subscription->provide_intra_process_message(std::move(copy_message));
|
||||
}
|
||||
} else {
|
||||
subscriptions_.erase(subscription_it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PublisherToSubscriptionIdsMap pub_to_subs_;
|
||||
SubscriptionMap subscriptions_;
|
||||
PublisherMap publishers_;
|
||||
|
||||
mutable std::shared_timed_mutex mutex_;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXPERIMENTAL__INTRA_PROCESS_MANAGER_HPP_
|
||||
@@ -1,215 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_HPP_
|
||||
#define RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_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/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>,
|
||||
typename CallbackMessageT = MessageT>
|
||||
class SubscriptionIntraProcess : public SubscriptionIntraProcessBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(SubscriptionIntraProcess)
|
||||
|
||||
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,
|
||||
rmw_qos_profile_t qos_profile,
|
||||
rclcpp::IntraProcessBufferType 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_));
|
||||
// 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.
|
||||
#ifndef TRACETOOLS_DISABLED
|
||||
any_callback_.register_callback_for_tracing();
|
||||
#endif
|
||||
}
|
||||
|
||||
~SubscriptionIntraProcess()
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
std::shared_ptr<void>
|
||||
take_data()
|
||||
{
|
||||
ConstMessageSharedPtr shared_msg;
|
||||
MessageUniquePtr unique_msg;
|
||||
|
||||
if (any_callback_.use_take_shared_method()) {
|
||||
shared_msg = buffer_->consume_shared();
|
||||
} else {
|
||||
unique_msg = 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 execute(std::shared_ptr<void> & data)
|
||||
{
|
||||
execute_impl<CallbackMessageT>(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();
|
||||
}
|
||||
|
||||
private:
|
||||
void
|
||||
trigger_guard_condition()
|
||||
{
|
||||
rcl_ret_t ret = rcl_trigger_guard_condition(&gc_);
|
||||
(void)ret;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
(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)
|
||||
{
|
||||
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);
|
||||
} else {
|
||||
MessageUniquePtr unique_msg = std::move(shared_ptr->second);
|
||||
any_callback_.dispatch_intra_process(std::move(unique_msg), msg_info);
|
||||
}
|
||||
shared_ptr.reset();
|
||||
}
|
||||
|
||||
AnySubscriptionCallback<CallbackMessageT, Alloc> any_callback_;
|
||||
BufferUniquePtr buffer_;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_HPP_
|
||||
@@ -1,92 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_BASE_HPP_
|
||||
#define RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_BASE_HPP_
|
||||
|
||||
#include <rmw/rmw.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/waitable.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
class SubscriptionIntraProcessBase : public rclcpp::Waitable
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(SubscriptionIntraProcessBase)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
SubscriptionIntraProcessBase(const std::string & topic_name, rmw_qos_profile_t qos_profile)
|
||||
: topic_name_(topic_name), qos_profile_(qos_profile)
|
||||
{}
|
||||
|
||||
virtual ~SubscriptionIntraProcessBase() = default;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_number_of_ready_guard_conditions() {return 1;}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
add_to_wait_set(rcl_wait_set_t * wait_set);
|
||||
|
||||
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;
|
||||
|
||||
virtual bool
|
||||
use_take_shared_method() const = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const char *
|
||||
get_topic_name() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rmw_qos_profile_t
|
||||
get_actual_qos() const;
|
||||
|
||||
protected:
|
||||
std::recursive_mutex reentrant_mutex_;
|
||||
rcl_guard_condition_t gc_;
|
||||
|
||||
private:
|
||||
virtual void
|
||||
trigger_guard_condition() = 0;
|
||||
|
||||
std::string topic_name_;
|
||||
rmw_qos_profile_t qos_profile_;
|
||||
};
|
||||
|
||||
} // namespace experimental
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_BASE_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
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
// Copyright 2014 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__FUTURE_RETURN_CODE_HPP_
|
||||
#define RCLCPP__FUTURE_RETURN_CODE_HPP_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Return codes to be used with spin_until_future_complete.
|
||||
/**
|
||||
* SUCCESS: The future is complete and can be accessed with "get" without blocking.
|
||||
* This does not indicate that the operation succeeded; "get" may still throw an exception.
|
||||
* INTERRUPTED: The future is not complete, spinning was interrupted by Ctrl-C or another error.
|
||||
* TIMEOUT: Spinning timed out.
|
||||
*/
|
||||
enum class FutureReturnCode {SUCCESS, INTERRUPTED, TIMEOUT};
|
||||
|
||||
/// Stream operator for FutureReturnCode.
|
||||
RCLCPP_PUBLIC
|
||||
std::ostream &
|
||||
operator<<(std::ostream & os, const FutureReturnCode & future_return_code);
|
||||
|
||||
/// String conversion function for FutureReturnCode.
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
to_string(const FutureReturnCode & future_return_code);
|
||||
|
||||
} // 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,161 +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;
|
||||
|
||||
/// 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_
|
||||
@@ -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();
|
||||
@@ -73,8 +73,6 @@ public:
|
||||
* This function is thread-safe.
|
||||
*
|
||||
* \throws GraphListenerShutdownError if the GraphListener is shutdown
|
||||
* \throws std::runtime if the parent context was destroyed
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
@@ -160,23 +158,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::SharedPtr parent_context_;
|
||||
|
||||
std::thread listener_thread_;
|
||||
bool is_started_;
|
||||
@@ -188,6 +177,8 @@ private:
|
||||
std::vector<rclcpp::node_interfaces::NodeGraphInterface *> node_graph_interfaces_;
|
||||
|
||||
rcl_guard_condition_t interrupt_guard_condition_ = rcl_get_zero_initialized_guard_condition();
|
||||
std::shared_ptr<rcl_context_t> interrupt_guard_condition_context_;
|
||||
rcl_guard_condition_t * shutdown_guard_condition_;
|
||||
rcl_wait_set_t wait_set_ = rcl_get_zero_initialized_wait_set();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,100 +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__GUARD_CONDITION_HPP_
|
||||
#define RCLCPP__GUARD_CONDITION_HPP_
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "rcl/guard_condition.h"
|
||||
|
||||
#include "rclcpp/context.hpp"
|
||||
#include "rclcpp/contexts/default_context.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// A condition that can be waited on in a single wait set and asynchronously triggered.
|
||||
class GuardCondition
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(GuardCondition)
|
||||
|
||||
// TODO(wjwwood): support custom allocator, maybe restrict to polymorphic allocator
|
||||
/// Construct the guard condition, optionally specifying which Context to use.
|
||||
/**
|
||||
* \param[in] context Optional custom context to be used.
|
||||
* Defaults to using the global default context singleton.
|
||||
* Shared ownership of the context is held with the guard condition until
|
||||
* destruction.
|
||||
* \throws std::invalid_argument if the context is nullptr.
|
||||
* \throws rclcpp::exceptions::RCLError based exceptions when underlying
|
||||
* rcl functions fail.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit GuardCondition(
|
||||
rclcpp::Context::SharedPtr context =
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
~GuardCondition();
|
||||
|
||||
/// Return the context used when creating this guard condition.
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::Context::SharedPtr
|
||||
get_context() const;
|
||||
|
||||
/// Return the underlying rcl guard condition structure.
|
||||
RCLCPP_PUBLIC
|
||||
const rcl_guard_condition_t &
|
||||
get_rcl_guard_condition() const;
|
||||
|
||||
/// Notify the wait set waiting on this condition, if any, that the condition had been met.
|
||||
/**
|
||||
* This function is thread-safe, and may be called concurrently with waiting
|
||||
* on this guard condition in a wait set.
|
||||
*
|
||||
* \throws rclcpp::exceptions::RCLError based exceptions when underlying
|
||||
* rcl functions fail.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
trigger();
|
||||
|
||||
/// Exchange the "in use by wait set" state for this guard condition.
|
||||
/**
|
||||
* This is used to ensure this guard condition is not used by multiple
|
||||
* wait sets at the same time.
|
||||
*
|
||||
* \param[in] in_use_state the new state to exchange into the state, true
|
||||
* indicates it is now in use by a wait set, and false is that it is no
|
||||
* longer in use by a wait set.
|
||||
* \returns the previous state.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
exchange_in_use_by_wait_set_state(bool in_use_state);
|
||||
|
||||
protected:
|
||||
rclcpp::Context::SharedPtr context_;
|
||||
rcl_guard_condition_t rcl_guard_condition_;
|
||||
std::atomic<bool> in_use_by_wait_set_{false};
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__GUARD_CONDITION_HPP_
|
||||
@@ -16,7 +16,6 @@
|
||||
#define RCLCPP__INIT_OPTIONS_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include "rcl/init_options.h"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
@@ -31,21 +30,11 @@ public:
|
||||
/// If true, the context will be shutdown on SIGINT by the signal handler (if it was installed).
|
||||
bool shutdown_on_sigint = true;
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
* It allows you to specify the allocator used within the init options.
|
||||
* \param[in] allocator used allocate memory within the init options
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
*/
|
||||
/// Constructor which allows you to specify the allocator used within the init options.
|
||||
RCLCPP_PUBLIC
|
||||
explicit InitOptions(rcl_allocator_t allocator = rcl_get_default_allocator());
|
||||
|
||||
/// Constructor which is initialized by an existing init_options.
|
||||
/**
|
||||
* Initialized by an existing init_options.
|
||||
* \param[in] init_options rcl_init_options_t to initialized
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit InitOptions(const rcl_init_options_t & init_options);
|
||||
|
||||
@@ -53,16 +42,6 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
InitOptions(const InitOptions & other);
|
||||
|
||||
/// Return `true` if logging should be initialized when `rclcpp::Context::init` is called.
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
auto_initialize_logging() const;
|
||||
|
||||
/// Set flag indicating if logging should be initialized or not.
|
||||
RCLCPP_PUBLIC
|
||||
InitOptions &
|
||||
auto_initialize_logging(bool initialize_logging);
|
||||
|
||||
/// Assignment operator.
|
||||
RCLCPP_PUBLIC
|
||||
InitOptions &
|
||||
@@ -73,40 +52,16 @@ public:
|
||||
~InitOptions();
|
||||
|
||||
/// Return the rcl init options.
|
||||
/**
|
||||
* \return the rcl init options.
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
*/
|
||||
RCLCPP_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};
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__INTRA_PROCESS_BUFFER_TYPE_HPP_
|
||||
#define RCLCPP__INTRA_PROCESS_BUFFER_TYPE_HPP_
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Used as argument in create_publisher and create_subscriber
|
||||
/// when intra-process communication is enabled
|
||||
enum class IntraProcessBufferType
|
||||
{
|
||||
/// Set the data type used in the intra-process buffer as std::shared_ptr<MessageT>
|
||||
SharedPtr,
|
||||
/// Set the data type used in the intra-process buffer as std::unique_ptr<MessageT>
|
||||
UniquePtr,
|
||||
/// Set the data type used in the intra-process buffer as the same used in the callback
|
||||
CallbackDefault
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__INTRA_PROCESS_BUFFER_TYPE_HPP_
|
||||
420
rclcpp/include/rclcpp/intra_process_manager.hpp
Normal file
420
rclcpp/include/rclcpp/intra_process_manager.hpp
Normal file
@@ -0,0 +1,420 @@
|
||||
// Copyright 2015 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__INTRA_PROCESS_MANAGER_HPP_
|
||||
#define RCLCPP__INTRA_PROCESS_MANAGER_HPP_
|
||||
|
||||
#include <rmw/types.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <set>
|
||||
|
||||
#include "rclcpp/allocator/allocator_deleter.hpp"
|
||||
#include "rclcpp/intra_process_manager_impl.hpp"
|
||||
#include "rclcpp/mapped_ring_buffer.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/publisher_base.hpp"
|
||||
#include "rclcpp/subscription_base.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace intra_process_manager
|
||||
{
|
||||
|
||||
/// This class facilitates intra process communication between nodes.
|
||||
/**
|
||||
* This class is used in the creation of publishers and subscriptions.
|
||||
* A singleton instance of this class is owned by a rclcpp::Context and a
|
||||
* rclcpp::Node can use an associated Context to get an instance of this class.
|
||||
* Nodes which do not have a common Context will not exchange intra process
|
||||
* messages because they will not share access to an instance of this class.
|
||||
*
|
||||
* When a Node creates a publisher or subscription, it will register them
|
||||
* with this class.
|
||||
* The node will also hook into the publisher's publish call
|
||||
* in order to do intra process related work.
|
||||
*
|
||||
* When a publisher is created, it advertises on the topic the user provided,
|
||||
* as well as a "shadowing" topic of type rcl_interfaces/IntraProcessMessage.
|
||||
* For instance, if the user specified the topic '/namespace/chatter', then the
|
||||
* corresponding intra process topic might be '/namespace/chatter/_intra'.
|
||||
* The publisher is also allocated an id which is unique among all publishers
|
||||
* and subscriptions in this process.
|
||||
* Additionally, when registered with this class a ring buffer is created and
|
||||
* owned by this class as a temporary place to hold messages destined for intra
|
||||
* process subscriptions.
|
||||
*
|
||||
* When a subscription is created, it subscribes to the topic provided by the
|
||||
* user as well as to the corresponding intra process topic.
|
||||
* It is also gets a unique id from the singleton instance of this class which
|
||||
* is unique among publishers and subscriptions.
|
||||
*
|
||||
* When the user publishes a message, the message is stored by calling
|
||||
* store_intra_process_message on this class.
|
||||
* The instance of that message is uniquely identified by a publisher id and a
|
||||
* message sequence number.
|
||||
* The publisher id, message sequence pair is unique with in the process.
|
||||
* At that point a list of the id's of intra process subscriptions which have
|
||||
* been registered with the singleton instance of this class are stored with
|
||||
* the message instance so that delivery is only made to those subscriptions.
|
||||
* Then an instance of rcl_interfaces/IntraProcessMessage is published to the
|
||||
* intra process topic which is specific to the topic specified by the user.
|
||||
*
|
||||
* When an instance of rcl_interfaces/IntraProcessMessage is received by a
|
||||
* subscription, then it is handled by calling take_intra_process_message
|
||||
* on a singleton of this class.
|
||||
* The subscription passes a publisher id, message sequence pair which
|
||||
* uniquely identifies the message instance it was suppose to receive as well
|
||||
* as the subscriptions unique id.
|
||||
* If the message is still being held by this class and the subscription's id
|
||||
* is in the list of intended subscriptions then the message is returned.
|
||||
* If either of those predicates are not satisfied then the message is not
|
||||
* returned and the subscription does not call the users callback.
|
||||
*
|
||||
* Since the publisher builds a list of destined subscriptions on publish, and
|
||||
* other requests are ignored, this class knows how many times a message
|
||||
* instance should be requested.
|
||||
* The final time a message is requested, the ownership is passed out of this
|
||||
* class and passed to the final subscription, effectively freeing space in
|
||||
* this class's internal storage.
|
||||
*
|
||||
* Since a topic is being used to ferry notifications about new intra process
|
||||
* messages between publishers and subscriptions, it is possible for that
|
||||
* notification to be lost.
|
||||
* It is also possible that a subscription which was available when publish was
|
||||
* called will no longer exist once the notification gets posted.
|
||||
* In both cases this might result in a message instance getting requested
|
||||
* fewer times than expected.
|
||||
* This is why the internal storage of this class is a ring buffer.
|
||||
* That way if a message is orphaned it will eventually be dropped from storage
|
||||
* when a new message instance is stored and will not result in a memory leak.
|
||||
*
|
||||
* However, since the storage system is finite, this also means that a message
|
||||
* instance might get displaced by an incoming message instance before all
|
||||
* interested parties have called take_intra_process_message.
|
||||
* Because of this the size of the internal storage should be carefully
|
||||
* considered.
|
||||
*
|
||||
* /TODO(wjwwood): update to include information about handling latching.
|
||||
* /TODO(wjwwood): consider thread safety of the class.
|
||||
*
|
||||
* This class is neither CopyConstructable nor CopyAssignable.
|
||||
*/
|
||||
class IntraProcessManager
|
||||
{
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(IntraProcessManager)
|
||||
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(IntraProcessManager)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit IntraProcessManager(
|
||||
IntraProcessManagerImplBase::SharedPtr state = create_default_impl());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~IntraProcessManager();
|
||||
|
||||
/// Register a subscription with the manager, returns subscriptions unique id.
|
||||
/**
|
||||
* In addition to generating a unique intra process id for the subscription,
|
||||
* this method also stores the topic name of the subscription.
|
||||
*
|
||||
* This method is normally called during the creation of a subscription,
|
||||
* but after it creates the internal intra process rmw_subscription_t.
|
||||
*
|
||||
* This method will allocate memory.
|
||||
*
|
||||
* \param subscription the Subscription to register.
|
||||
* \return an unsigned 64-bit integer which is the subscription's unique id.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
uint64_t
|
||||
add_subscription(SubscriptionBase::SharedPtr subscription);
|
||||
|
||||
/// Unregister a subscription using the subscription's unique id.
|
||||
/**
|
||||
* This method does not allocate memory.
|
||||
*
|
||||
* \param intra_process_subscription_id id of the subscription to remove.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_subscription(uint64_t intra_process_subscription_id);
|
||||
|
||||
/// Register a publisher with the manager, returns the publisher unique id.
|
||||
/**
|
||||
* In addition to generating and returning a unique id for the publisher,
|
||||
* this method creates internal ring buffer storage for "in-flight" intra
|
||||
* process messages which are stored when store_intra_process_message is
|
||||
* called with this publisher's unique id.
|
||||
*
|
||||
* The buffer_size must be less than or equal to the max uint64_t value.
|
||||
* If the buffer_size is 0 then a buffer size is calculated using the
|
||||
* publisher's QoS settings.
|
||||
* The default is to use the depth field of the publisher's QoS.
|
||||
* TODO(wjwwood): Consider doing depth *= 1.2, round up, or similar.
|
||||
* TODO(wjwwood): Consider what to do for keep all.
|
||||
*
|
||||
* This method is templated on the publisher's message type so that internal
|
||||
* storage of the same type can be allocated.
|
||||
*
|
||||
* This method will allocate memory.
|
||||
*
|
||||
* \param publisher publisher to be registered with the manager.
|
||||
* \param buffer_size if 0 (default) a size is calculated based on the QoS.
|
||||
* \return an unsigned 64-bit integer which is the publisher's unique id.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
uint64_t
|
||||
add_publisher(
|
||||
rclcpp::PublisherBase::SharedPtr publisher,
|
||||
size_t buffer_size = 0);
|
||||
|
||||
/// Unregister a publisher using the publisher's unique id.
|
||||
/**
|
||||
* This method does not allocate memory.
|
||||
*
|
||||
* \param intra_process_publisher_id id of the publisher to remove.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_publisher(uint64_t intra_process_publisher_id);
|
||||
|
||||
/// Store a message in the manager, and return the message sequence number.
|
||||
/**
|
||||
* The given message is stored in internal storage using the given publisher
|
||||
* id and the newly generated message sequence, which is also returned.
|
||||
* The combination of publisher id and message sequence number can later
|
||||
* be used with a subscription id to retrieve the message by calling
|
||||
* take_intra_process_message.
|
||||
* The number of times take_intra_process_message can be called with this
|
||||
* unique pair of id's is determined by the number of subscriptions currently
|
||||
* subscribed to the same topic and which share the same Context, i.e. once
|
||||
* for each subscription which should receive the intra process message.
|
||||
*
|
||||
* The ownership of the incoming message is transfered to the internal
|
||||
* storage in order to avoid copying the message data.
|
||||
* Therefore, the message parameter will no longer contain the original
|
||||
* message after calling this method.
|
||||
* Instead it will either be a nullptr or it will contain the ownership of
|
||||
* the message instance which was displaced.
|
||||
* If the message parameter is not equal to nullptr after calling this method
|
||||
* then a message was prematurely displaced, i.e. take_intra_process_message
|
||||
* had not been called on it as many times as was expected.
|
||||
*
|
||||
* This method can throw an exception if the publisher id is not found or
|
||||
* if the publisher shared_ptr given to add_publisher has gone out of scope.
|
||||
*
|
||||
* This method does allocate memory.
|
||||
*
|
||||
* \param intra_process_publisher_id the id of the publisher of this message.
|
||||
* \param message the message that is being stored.
|
||||
* \return the message sequence number.
|
||||
*/
|
||||
template<
|
||||
typename MessageT, typename Alloc = std::allocator<void>>
|
||||
uint64_t
|
||||
store_intra_process_message(
|
||||
uint64_t intra_process_publisher_id,
|
||||
std::shared_ptr<const MessageT> message)
|
||||
{
|
||||
using MRBMessageAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<MessageT>;
|
||||
using TypedMRB = typename mapped_ring_buffer::MappedRingBuffer<MessageT, MRBMessageAlloc>;
|
||||
uint64_t message_seq = 0;
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer = impl_->get_publisher_info_for_id(
|
||||
intra_process_publisher_id, message_seq);
|
||||
typename TypedMRB::SharedPtr typed_buffer = std::static_pointer_cast<TypedMRB>(buffer);
|
||||
if (!typed_buffer) {
|
||||
throw std::runtime_error("Typecast failed due to incorrect message type");
|
||||
}
|
||||
|
||||
// Insert the message into the ring buffer using the message_seq to identify it.
|
||||
bool did_replace = typed_buffer->push_and_replace(message_seq, message);
|
||||
// TODO(wjwwood): do something when a message was displaced. log debug?
|
||||
(void)did_replace; // Avoid unused variable warning.
|
||||
|
||||
impl_->store_intra_process_message(intra_process_publisher_id, message_seq);
|
||||
|
||||
// Return the message sequence which is sent to the subscription.
|
||||
return message_seq;
|
||||
}
|
||||
|
||||
template<
|
||||
typename MessageT, typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>>
|
||||
uint64_t
|
||||
store_intra_process_message(
|
||||
uint64_t intra_process_publisher_id,
|
||||
std::unique_ptr<MessageT, Deleter> message)
|
||||
{
|
||||
using MRBMessageAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<MessageT>;
|
||||
using TypedMRB = typename mapped_ring_buffer::MappedRingBuffer<MessageT, MRBMessageAlloc>;
|
||||
uint64_t message_seq = 0;
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer = impl_->get_publisher_info_for_id(
|
||||
intra_process_publisher_id, message_seq);
|
||||
typename TypedMRB::SharedPtr typed_buffer = std::static_pointer_cast<TypedMRB>(buffer);
|
||||
if (!typed_buffer) {
|
||||
throw std::runtime_error("Typecast failed due to incorrect message type");
|
||||
}
|
||||
|
||||
// Insert the message into the ring buffer using the message_seq to identify it.
|
||||
bool did_replace = typed_buffer->push_and_replace(message_seq, std::move(message));
|
||||
// TODO(wjwwood): do something when a message was displaced. log debug?
|
||||
(void)did_replace; // Avoid unused variable warning.
|
||||
|
||||
impl_->store_intra_process_message(intra_process_publisher_id, message_seq);
|
||||
|
||||
// Return the message sequence which is sent to the subscription.
|
||||
return message_seq;
|
||||
}
|
||||
|
||||
/// Take an intra process message.
|
||||
/**
|
||||
* The intra_process_publisher_id and message_sequence_number parameters
|
||||
* uniquely identify a message instance, which should be taken.
|
||||
*
|
||||
* The requesting_subscriptions_intra_process_id parameter is used to make
|
||||
* sure the requesting subscription was intended to receive this message
|
||||
* instance.
|
||||
* This check is made because it could happen that the requester
|
||||
* comes up after the publish event, so it still receives the notification of
|
||||
* a new intra process message, but it wasn't registered with the manager at
|
||||
* the time of publishing, causing it to take when it wasn't intended.
|
||||
* This should be avioded unless latching-like behavior is involved.
|
||||
*
|
||||
* The message parameter is used to store the taken message.
|
||||
* On the last expected call to this method, the ownership is transfered out
|
||||
* of internal storage and into the message parameter.
|
||||
* On all previous calls a copy of the internally stored message is made and
|
||||
* the ownership of the copy is transfered to the message parameter.
|
||||
* TODO(wjwwood): update this documentation when latching is supported.
|
||||
*
|
||||
* The message parameter can be set to nullptr if:
|
||||
*
|
||||
* - The publisher id is not found.
|
||||
* - The message sequence is not found for the given publisher id.
|
||||
* - The requesting subscription's id is not in the list of intended takers.
|
||||
* - The requesting subscription's id has been used before with this message.
|
||||
*
|
||||
* This method may allocate memory to copy the stored message.
|
||||
*
|
||||
* \param intra_process_publisher_id the id of the message's publisher.
|
||||
* \param message_sequence_number the sequence number of the message.
|
||||
* \param requesting_subscriptions_intra_process_id the subscription's id.
|
||||
* \param message the message typed unique_ptr used to return the message.
|
||||
*/
|
||||
template<
|
||||
typename MessageT, typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>>
|
||||
void
|
||||
take_intra_process_message(
|
||||
uint64_t intra_process_publisher_id,
|
||||
uint64_t message_sequence_number,
|
||||
uint64_t requesting_subscriptions_intra_process_id,
|
||||
std::unique_ptr<MessageT, Deleter> & message)
|
||||
{
|
||||
using MRBMessageAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<MessageT>;
|
||||
using TypedMRB = mapped_ring_buffer::MappedRingBuffer<MessageT, MRBMessageAlloc>;
|
||||
message = nullptr;
|
||||
|
||||
size_t target_subs_size = 0;
|
||||
std::lock_guard<std::mutex> lock(take_mutex_);
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer = impl_->take_intra_process_message(
|
||||
intra_process_publisher_id,
|
||||
message_sequence_number,
|
||||
requesting_subscriptions_intra_process_id,
|
||||
target_subs_size
|
||||
);
|
||||
typename TypedMRB::SharedPtr typed_buffer = std::static_pointer_cast<TypedMRB>(buffer);
|
||||
if (!typed_buffer) {
|
||||
return;
|
||||
}
|
||||
// Return a copy or the unique_ptr (ownership) depending on how many subscriptions are left.
|
||||
if (target_subs_size) {
|
||||
// There are more subscriptions to serve, return a copy.
|
||||
typed_buffer->get(message_sequence_number, message);
|
||||
} else {
|
||||
// This is the last one to be returned, transfer ownership.
|
||||
typed_buffer->pop(message_sequence_number, message);
|
||||
}
|
||||
}
|
||||
|
||||
template<
|
||||
typename MessageT, typename Alloc = std::allocator<void>>
|
||||
void
|
||||
take_intra_process_message(
|
||||
uint64_t intra_process_publisher_id,
|
||||
uint64_t message_sequence_number,
|
||||
uint64_t requesting_subscriptions_intra_process_id,
|
||||
std::shared_ptr<const MessageT> & message)
|
||||
{
|
||||
using MRBMessageAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<MessageT>;
|
||||
using TypedMRB = mapped_ring_buffer::MappedRingBuffer<MessageT, MRBMessageAlloc>;
|
||||
message = nullptr;
|
||||
|
||||
size_t target_subs_size = 0;
|
||||
std::lock_guard<std::mutex> lock(take_mutex_);
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer = impl_->take_intra_process_message(
|
||||
intra_process_publisher_id,
|
||||
message_sequence_number,
|
||||
requesting_subscriptions_intra_process_id,
|
||||
target_subs_size
|
||||
);
|
||||
typename TypedMRB::SharedPtr typed_buffer = std::static_pointer_cast<TypedMRB>(buffer);
|
||||
if (!typed_buffer) {
|
||||
return;
|
||||
}
|
||||
// Return a copy or the unique_ptr (ownership) depending on how many subscriptions are left.
|
||||
if (target_subs_size) {
|
||||
// There are more subscriptions to serve, return a copy.
|
||||
typed_buffer->get(message_sequence_number, message);
|
||||
} else {
|
||||
// This is the last one to be returned, transfer ownership.
|
||||
typed_buffer->pop(message_sequence_number, message);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return true if the given rmw_gid_t matches any stored Publishers.
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
matches_any_publishers(const rmw_gid_t * id) const;
|
||||
|
||||
/// Return the number of intraprocess subscriptions to a topic, given the publisher id.
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_subscription_count(uint64_t intra_process_publisher_id) const;
|
||||
|
||||
private:
|
||||
RCLCPP_PUBLIC
|
||||
static uint64_t
|
||||
get_next_unique_id();
|
||||
|
||||
IntraProcessManagerImplBase::SharedPtr impl_;
|
||||
std::mutex take_mutex_;
|
||||
};
|
||||
|
||||
} // namespace intra_process_manager
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__INTRA_PROCESS_MANAGER_HPP_
|
||||
358
rclcpp/include/rclcpp/intra_process_manager_impl.hpp
Normal file
358
rclcpp/include/rclcpp/intra_process_manager_impl.hpp
Normal file
@@ -0,0 +1,358 @@
|
||||
// Copyright 2015 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__INTRA_PROCESS_MANAGER_IMPL_HPP_
|
||||
#define RCLCPP__INTRA_PROCESS_MANAGER_IMPL_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include "rmw/validate_full_topic_name.h"
|
||||
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/mapped_ring_buffer.hpp"
|
||||
#include "rclcpp/publisher_base.hpp"
|
||||
#include "rclcpp/subscription_base.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace intra_process_manager
|
||||
{
|
||||
|
||||
class IntraProcessManagerImplBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(IntraProcessManagerImplBase)
|
||||
|
||||
IntraProcessManagerImplBase() = default;
|
||||
virtual ~IntraProcessManagerImplBase() = default;
|
||||
|
||||
virtual void
|
||||
add_subscription(uint64_t id, SubscriptionBase::SharedPtr subscription) = 0;
|
||||
|
||||
virtual void
|
||||
remove_subscription(uint64_t intra_process_subscription_id) = 0;
|
||||
|
||||
virtual void add_publisher(
|
||||
uint64_t id,
|
||||
PublisherBase::WeakPtr publisher,
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr mrb,
|
||||
size_t size) = 0;
|
||||
|
||||
virtual void
|
||||
remove_publisher(uint64_t intra_process_publisher_id) = 0;
|
||||
|
||||
virtual mapped_ring_buffer::MappedRingBufferBase::SharedPtr
|
||||
get_publisher_info_for_id(
|
||||
uint64_t intra_process_publisher_id,
|
||||
uint64_t & message_seq) = 0;
|
||||
|
||||
virtual void
|
||||
store_intra_process_message(uint64_t intra_process_publisher_id, uint64_t message_seq) = 0;
|
||||
|
||||
virtual mapped_ring_buffer::MappedRingBufferBase::SharedPtr
|
||||
take_intra_process_message(
|
||||
uint64_t intra_process_publisher_id,
|
||||
uint64_t message_sequence_number,
|
||||
uint64_t requesting_subscriptions_intra_process_id,
|
||||
size_t & size) = 0;
|
||||
|
||||
virtual bool
|
||||
matches_any_publishers(const rmw_gid_t * id) const = 0;
|
||||
|
||||
virtual size_t
|
||||
get_subscription_count(uint64_t intra_process_publisher_id) const = 0;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(IntraProcessManagerImplBase)
|
||||
};
|
||||
|
||||
template<typename Allocator = std::allocator<void>>
|
||||
class IntraProcessManagerImpl : public IntraProcessManagerImplBase
|
||||
{
|
||||
public:
|
||||
IntraProcessManagerImpl() = default;
|
||||
~IntraProcessManagerImpl() = default;
|
||||
|
||||
void
|
||||
add_subscription(uint64_t id, SubscriptionBase::SharedPtr subscription)
|
||||
{
|
||||
subscriptions_[id] = subscription;
|
||||
subscription_ids_by_topic_[fixed_size_string(subscription->get_topic_name())].insert(id);
|
||||
}
|
||||
|
||||
void
|
||||
remove_subscription(uint64_t intra_process_subscription_id)
|
||||
{
|
||||
subscriptions_.erase(intra_process_subscription_id);
|
||||
for (auto & pair : subscription_ids_by_topic_) {
|
||||
pair.second.erase(intra_process_subscription_id);
|
||||
}
|
||||
// Iterate over all publisher infos and all stored subscription id's and
|
||||
// remove references to this subscription's id.
|
||||
for (auto & publisher_pair : publishers_) {
|
||||
for (auto & sub_pair : publisher_pair.second.target_subscriptions_by_message_sequence) {
|
||||
sub_pair.second.erase(intra_process_subscription_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void add_publisher(
|
||||
uint64_t id,
|
||||
PublisherBase::WeakPtr publisher,
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr mrb,
|
||||
size_t size)
|
||||
{
|
||||
publishers_[id].publisher = publisher;
|
||||
// As long as the size of the ring buffer is less than the max sequence number, we're safe.
|
||||
if (size > std::numeric_limits<uint64_t>::max()) {
|
||||
throw std::invalid_argument("the calculated buffer size is too large");
|
||||
}
|
||||
publishers_[id].sequence_number.store(0);
|
||||
|
||||
publishers_[id].buffer = mrb;
|
||||
publishers_[id].target_subscriptions_by_message_sequence.reserve(size);
|
||||
}
|
||||
|
||||
void
|
||||
remove_publisher(uint64_t intra_process_publisher_id)
|
||||
{
|
||||
publishers_.erase(intra_process_publisher_id);
|
||||
}
|
||||
|
||||
// return message_seq and mrb
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr
|
||||
get_publisher_info_for_id(
|
||||
uint64_t intra_process_publisher_id,
|
||||
uint64_t & message_seq)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(runtime_mutex_);
|
||||
auto it = publishers_.find(intra_process_publisher_id);
|
||||
if (it == publishers_.end()) {
|
||||
throw std::runtime_error("get_publisher_info_for_id called with invalid publisher id");
|
||||
}
|
||||
PublisherInfo & info = it->second;
|
||||
// Calculate the next message sequence number.
|
||||
message_seq = info.sequence_number.fetch_add(1);
|
||||
|
||||
return info.buffer;
|
||||
}
|
||||
|
||||
void
|
||||
store_intra_process_message(uint64_t intra_process_publisher_id, uint64_t message_seq)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(runtime_mutex_);
|
||||
auto it = publishers_.find(intra_process_publisher_id);
|
||||
if (it == publishers_.end()) {
|
||||
throw std::runtime_error("store_intra_process_message called with invalid publisher id");
|
||||
}
|
||||
PublisherInfo & info = it->second;
|
||||
auto publisher = info.publisher.lock();
|
||||
if (!publisher) {
|
||||
throw std::runtime_error("publisher has unexpectedly gone out of scope");
|
||||
}
|
||||
|
||||
// Figure out what subscriptions should receive the message.
|
||||
auto & destined_subscriptions =
|
||||
subscription_ids_by_topic_[fixed_size_string(publisher->get_topic_name())];
|
||||
// Store the list for later comparison.
|
||||
if (info.target_subscriptions_by_message_sequence.count(message_seq) == 0) {
|
||||
info.target_subscriptions_by_message_sequence.emplace(
|
||||
message_seq, AllocSet(std::less<uint64_t>(), uint64_allocator));
|
||||
} else {
|
||||
info.target_subscriptions_by_message_sequence[message_seq].clear();
|
||||
}
|
||||
std::copy(
|
||||
destined_subscriptions.begin(), destined_subscriptions.end(),
|
||||
// Memory allocation occurs in info.target_subscriptions_by_message_sequence[message_seq]
|
||||
std::inserter(
|
||||
info.target_subscriptions_by_message_sequence[message_seq],
|
||||
// This ends up only being a hint to std::set, could also be .begin().
|
||||
info.target_subscriptions_by_message_sequence[message_seq].end()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr
|
||||
take_intra_process_message(
|
||||
uint64_t intra_process_publisher_id,
|
||||
uint64_t message_sequence_number,
|
||||
uint64_t requesting_subscriptions_intra_process_id,
|
||||
size_t & size
|
||||
)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(runtime_mutex_);
|
||||
PublisherInfo * info;
|
||||
{
|
||||
auto it = publishers_.find(intra_process_publisher_id);
|
||||
if (it == publishers_.end()) {
|
||||
// Publisher is either invalid or no longer exists.
|
||||
return 0;
|
||||
}
|
||||
info = &it->second;
|
||||
}
|
||||
// Figure out how many subscriptions are left.
|
||||
AllocSet * target_subs;
|
||||
{
|
||||
auto it = info->target_subscriptions_by_message_sequence.find(message_sequence_number);
|
||||
if (it == info->target_subscriptions_by_message_sequence.end()) {
|
||||
// Message is no longer being stored by this publisher.
|
||||
return 0;
|
||||
}
|
||||
target_subs = &it->second;
|
||||
}
|
||||
{
|
||||
auto it = std::find(
|
||||
target_subs->begin(), target_subs->end(),
|
||||
requesting_subscriptions_intra_process_id);
|
||||
if (it == target_subs->end()) {
|
||||
// This publisher id/message seq pair was not intended for this subscription.
|
||||
return 0;
|
||||
}
|
||||
target_subs->erase(it);
|
||||
}
|
||||
size = target_subs->size();
|
||||
return info->buffer;
|
||||
}
|
||||
|
||||
bool
|
||||
matches_any_publishers(const rmw_gid_t * id) const
|
||||
{
|
||||
for (auto & publisher_pair : publishers_) {
|
||||
auto publisher = publisher_pair.second.publisher.lock();
|
||||
if (!publisher) {
|
||||
continue;
|
||||
}
|
||||
if (*publisher.get() == id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t
|
||||
get_subscription_count(uint64_t intra_process_publisher_id) const
|
||||
{
|
||||
auto publisher_it = publishers_.find(intra_process_publisher_id);
|
||||
if (publisher_it == publishers_.end()) {
|
||||
// Publisher is either invalid or no longer exists.
|
||||
return 0;
|
||||
}
|
||||
auto publisher = publisher_it->second.publisher.lock();
|
||||
if (!publisher) {
|
||||
throw std::runtime_error("publisher has unexpectedly gone out of scope");
|
||||
}
|
||||
auto sub_map_it =
|
||||
subscription_ids_by_topic_.find(fixed_size_string(publisher->get_topic_name()));
|
||||
if (sub_map_it == subscription_ids_by_topic_.end()) {
|
||||
// No intraprocess subscribers
|
||||
return 0;
|
||||
}
|
||||
return sub_map_it->second.size();
|
||||
}
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(IntraProcessManagerImpl)
|
||||
|
||||
using FixedSizeString = std::array<char, RMW_TOPIC_MAX_NAME_LENGTH + 1>;
|
||||
|
||||
FixedSizeString
|
||||
fixed_size_string(const char * str) const
|
||||
{
|
||||
FixedSizeString ret;
|
||||
size_t size = std::strlen(str) + 1;
|
||||
if (size > ret.size()) {
|
||||
throw std::runtime_error("failed to copy topic name");
|
||||
}
|
||||
std::memcpy(ret.data(), str, size);
|
||||
return ret;
|
||||
}
|
||||
struct strcmp_wrapper
|
||||
{
|
||||
bool
|
||||
operator()(const FixedSizeString lhs, const FixedSizeString rhs) const
|
||||
{
|
||||
return std::strcmp(lhs.data(), rhs.data()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using RebindAlloc = typename std::allocator_traits<Allocator>::template rebind_alloc<T>;
|
||||
|
||||
RebindAlloc<uint64_t> uint64_allocator;
|
||||
|
||||
using AllocSet = std::set<uint64_t, std::less<uint64_t>, RebindAlloc<uint64_t>>;
|
||||
using SubscriptionMap = std::unordered_map<
|
||||
uint64_t, SubscriptionBase::WeakPtr,
|
||||
std::hash<uint64_t>, std::equal_to<uint64_t>,
|
||||
RebindAlloc<std::pair<const uint64_t, SubscriptionBase::WeakPtr>>>;
|
||||
|
||||
using IDTopicMap = std::map<
|
||||
FixedSizeString,
|
||||
AllocSet,
|
||||
strcmp_wrapper,
|
||||
RebindAlloc<std::pair<const FixedSizeString, AllocSet>>>;
|
||||
|
||||
SubscriptionMap subscriptions_;
|
||||
|
||||
IDTopicMap subscription_ids_by_topic_;
|
||||
|
||||
struct PublisherInfo
|
||||
{
|
||||
RCLCPP_DISABLE_COPY(PublisherInfo)
|
||||
|
||||
PublisherInfo() = default;
|
||||
|
||||
PublisherBase::WeakPtr publisher;
|
||||
std::atomic<uint64_t> sequence_number;
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer;
|
||||
|
||||
using TargetSubscriptionsMap = std::unordered_map<
|
||||
uint64_t, AllocSet,
|
||||
std::hash<uint64_t>, std::equal_to<uint64_t>,
|
||||
RebindAlloc<std::pair<const uint64_t, AllocSet>>>;
|
||||
TargetSubscriptionsMap target_subscriptions_by_message_sequence;
|
||||
};
|
||||
|
||||
using PublisherMap = std::unordered_map<
|
||||
uint64_t, PublisherInfo,
|
||||
std::hash<uint64_t>, std::equal_to<uint64_t>,
|
||||
RebindAlloc<std::pair<const uint64_t, PublisherInfo>>>;
|
||||
|
||||
PublisherMap publishers_;
|
||||
|
||||
std::mutex runtime_mutex_;
|
||||
};
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
IntraProcessManagerImplBase::SharedPtr
|
||||
create_default_impl();
|
||||
|
||||
} // namespace intra_process_manager
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__INTRA_PROCESS_MANAGER_IMPL_HPP_
|
||||
@@ -1,225 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__LOANED_MESSAGE_HPP_
|
||||
#define RCLCPP__LOANED_MESSAGE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/allocator/allocator_common.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
#include "rclcpp/publisher_base.hpp"
|
||||
|
||||
#include "rcl/allocator.h"
|
||||
#include "rcl/publisher.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
template<typename MessageT, typename AllocatorT = std::allocator<void>>
|
||||
class LoanedMessage
|
||||
{
|
||||
using MessageAllocatorTraits = rclcpp::allocator::AllocRebind<MessageT, AllocatorT>;
|
||||
using MessageAllocator = typename MessageAllocatorTraits::allocator_type;
|
||||
|
||||
public:
|
||||
/// Constructor of the LoanedMessage class.
|
||||
/**
|
||||
* The constructor of this class allocates memory for a given message type
|
||||
* and associates this with a given publisher.
|
||||
*
|
||||
* Given the publisher instance, a case differentiation is being performaned
|
||||
* which decides whether the underlying middleware is able to allocate the appropriate
|
||||
* memory for this message type or not.
|
||||
* In the case that the middleware can not loan messages, the passed in allocator instance
|
||||
* is being used to allocate the message within the scope of this class.
|
||||
* Otherwise, the allocator is being ignored and the allocation is solely performaned
|
||||
* in the underlying middleware with its appropriate allocation strategy.
|
||||
* The need for this arises as the user code can be written explicitly targeting a middleware
|
||||
* capable of loaning messages.
|
||||
* However, this user code is ought to be usable even when dynamically linked against
|
||||
* a middleware which doesn't support message loaning in which case the allocator will be used.
|
||||
*
|
||||
* \param[in] pub rclcpp::Publisher instance to which the memory belongs
|
||||
* \param[in] allocator Allocator instance in case middleware can not allocate messages
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
*/
|
||||
LoanedMessage(
|
||||
const rclcpp::PublisherBase & pub,
|
||||
std::allocator<MessageT> allocator)
|
||||
: pub_(pub),
|
||||
message_(nullptr),
|
||||
message_allocator_(std::move(allocator))
|
||||
{
|
||||
if (pub_.can_loan_messages()) {
|
||||
void * message_ptr = nullptr;
|
||||
auto ret = rcl_borrow_loaned_message(
|
||||
pub_.get_publisher_handle().get(),
|
||||
rosidl_typesupport_cpp::get_message_type_support_handle<MessageT>(),
|
||||
&message_ptr);
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
message_ = static_cast<MessageT *>(message_ptr);
|
||||
} else {
|
||||
RCLCPP_INFO_ONCE(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"Currently used middleware can't loan messages. Local allocator will be used.");
|
||||
message_ = message_allocator_.allocate(1);
|
||||
new (message_) MessageT();
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructor of the LoanedMessage class.
|
||||
/**
|
||||
* The constructor of this class allocates memory for a given message type
|
||||
* and associates this with a given publisher.
|
||||
*
|
||||
* Given the publisher instance, a case differentiation is being performaned
|
||||
* which decides whether the underlying middleware is able to allocate the appropriate
|
||||
* memory for this message type or not.
|
||||
* In the case that the middleware can not loan messages, the passed in allocator instance
|
||||
* is being used to allocate the message within the scope of this class.
|
||||
* Otherwise, the allocator is being ignored and the allocation is solely performaned
|
||||
* in the underlying middleware with its appropriate allocation strategy.
|
||||
* The need for this arises as the user code can be written explicitly targeting a middleware
|
||||
* capable of loaning messages.
|
||||
* However, this user code is ought to be usable even when dynamically linked against
|
||||
* a middleware which doesn't support message loaning in which case the allocator will be used.
|
||||
*
|
||||
* \param[in] pub rclcpp::Publisher instance to which the memory belongs
|
||||
* \param[in] allocator Allocator instance in case middleware can not allocate messages
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
*/
|
||||
LoanedMessage(
|
||||
const rclcpp::PublisherBase * pub,
|
||||
std::shared_ptr<std::allocator<MessageT>> allocator)
|
||||
: LoanedMessage(*pub, *allocator)
|
||||
{}
|
||||
|
||||
/// Move semantic for RVO
|
||||
LoanedMessage(LoanedMessage<MessageT> && other)
|
||||
: pub_(std::move(other.pub_)),
|
||||
message_(std::move(other.message_)),
|
||||
message_allocator_(std::move(other.message_allocator_))
|
||||
{}
|
||||
|
||||
/// Destructor of the LoanedMessage class.
|
||||
/**
|
||||
* The destructor has the explicit task to return the allocated memory for its message
|
||||
* instance.
|
||||
* If the message was previously allocated via the middleware, the message is getting
|
||||
* returned to the middleware to cleanly destroy the allocation.
|
||||
* In the case that the local allocator instance was used, the same instance is then
|
||||
* being used to destroy the allocated memory.
|
||||
*
|
||||
* The contract here is that the memory for this message is valid as long as this instance
|
||||
* of the LoanedMessage class is alive.
|
||||
*/
|
||||
virtual ~LoanedMessage()
|
||||
{
|
||||
auto error_logger = rclcpp::get_logger("LoanedMessage");
|
||||
|
||||
if (message_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pub_.can_loan_messages()) {
|
||||
// return allocated memory to the middleware
|
||||
auto ret =
|
||||
rcl_return_loaned_message_from_publisher(pub_.get_publisher_handle().get(), message_);
|
||||
if (ret != RCL_RET_OK) {
|
||||
RCLCPP_ERROR(
|
||||
error_logger, "rcl_deallocate_loaned_message failed: %s", rcl_get_error_string().str);
|
||||
rcl_reset_error();
|
||||
}
|
||||
} else {
|
||||
// call destructor before deallocating
|
||||
message_->~MessageT();
|
||||
message_allocator_.deallocate(message_, 1);
|
||||
}
|
||||
message_ = nullptr;
|
||||
}
|
||||
|
||||
/// Validate if the message was correctly allocated.
|
||||
/**
|
||||
* The allocated memory might not be always consistent and valid.
|
||||
* Reasons why this could fail is that an allocation step was failing,
|
||||
* e.g. just like malloc could fail or a maximum amount of previously allocated
|
||||
* messages is exceeded in which case the loaned messages have to be returned
|
||||
* to the middleware prior to be able to allocate a new one.
|
||||
*/
|
||||
bool is_valid() const
|
||||
{
|
||||
return message_ != nullptr;
|
||||
}
|
||||
|
||||
/// Access the ROS message instance.
|
||||
/**
|
||||
* A call to `get()` will return a mutable reference to the underlying ROS message instance.
|
||||
* This allows a user to modify the content of the message prior to publishing it.
|
||||
*
|
||||
* If this reference is copied, the memory for this copy is no longer managed
|
||||
* by the LoanedMessage instance and has to be cleanup individually.
|
||||
*/
|
||||
MessageT & get() const
|
||||
{
|
||||
return *message_;
|
||||
}
|
||||
|
||||
/// Release ownership of the ROS message instance.
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
std::unique_ptr<MessageT, std::function<void(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);
|
||||
});
|
||||
}
|
||||
|
||||
protected:
|
||||
const rclcpp::PublisherBase & pub_;
|
||||
|
||||
MessageT * message_;
|
||||
|
||||
MessageAllocator message_allocator_;
|
||||
|
||||
/// Deleted copy constructor to preserve memory integrity.
|
||||
LoanedMessage(const LoanedMessage<MessageT> & other) = delete;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__LOANED_MESSAGE_HPP_
|
||||
@@ -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
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
#define RCLCPP_SMART_PTR_ALIASES_ONLY(...) \
|
||||
__RCLCPP_SHARED_PTR_ALIAS(__VA_ARGS__) \
|
||||
__RCLCPP_WEAK_PTR_ALIAS(__VA_ARGS__) \
|
||||
__RCLCPP_UNIQUE_PTR_ALIAS(__VA_ARGS__) \
|
||||
__RCLCPP_MAKE_SHARED_DEFINITION(__VA_ARGS__)
|
||||
|
||||
#define __RCLCPP_SHARED_PTR_ALIAS(...) \
|
||||
|
||||
319
rclcpp/include/rclcpp/mapped_ring_buffer.hpp
Normal file
319
rclcpp/include/rclcpp/mapped_ring_buffer.hpp
Normal file
@@ -0,0 +1,319 @@
|
||||
// Copyright 2015 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__MAPPED_RING_BUFFER_HPP_
|
||||
#define RCLCPP__MAPPED_RING_BUFFER_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/allocator/allocator_common.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace mapped_ring_buffer
|
||||
{
|
||||
|
||||
class RCLCPP_PUBLIC MappedRingBufferBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(MappedRingBufferBase)
|
||||
};
|
||||
|
||||
/// Ring buffer container of shared_ptr's or unique_ptr's of T, which can be accessed by a key.
|
||||
/**
|
||||
* T must be a CopyConstructable and CopyAssignable.
|
||||
* This class can be used in a container by using the base class MappedRingBufferBase.
|
||||
* This class must have a positive, non-zero size.
|
||||
* This class cannot be resized nor can it reserve additional space after construction.
|
||||
* This class is not CopyConstructable nor CopyAssignable.
|
||||
*
|
||||
* The key's are not guaranteed to be unique because push_and_replace does not
|
||||
* check for colliding keys.
|
||||
* It is up to the user to only use unique keys.
|
||||
* A side effect of this is that when get_copy_at_key or pop_at_key are called,
|
||||
* they return the first encountered instance of the key.
|
||||
* But iteration does not begin with the ring buffer's head, and therefore
|
||||
* there is no guarantee on which value is returned if a key is used multiple
|
||||
* times.
|
||||
*/
|
||||
template<typename T, typename Alloc = std::allocator<void>>
|
||||
class MappedRingBuffer : public MappedRingBufferBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(MappedRingBuffer<T, Alloc>)
|
||||
using ElemAllocTraits = allocator::AllocRebind<T, Alloc>;
|
||||
using ElemAlloc = typename ElemAllocTraits::allocator_type;
|
||||
using ElemDeleter = allocator::Deleter<ElemAlloc, T>;
|
||||
|
||||
using ConstElemSharedPtr = std::shared_ptr<const T>;
|
||||
using ElemUniquePtr = std::unique_ptr<T, ElemDeleter>;
|
||||
|
||||
/// Constructor.
|
||||
/**
|
||||
* The constructor will allocate memory while reserving space.
|
||||
*
|
||||
* \param size size of the ring buffer; must be positive and non-zero.
|
||||
* \param allocator optional custom allocator
|
||||
*/
|
||||
explicit MappedRingBuffer(size_t size, std::shared_ptr<Alloc> allocator = nullptr)
|
||||
: elements_(size), head_(0)
|
||||
{
|
||||
if (size == 0) {
|
||||
throw std::invalid_argument("size must be a positive, non-zero value");
|
||||
}
|
||||
if (!allocator) {
|
||||
allocator_ = std::make_shared<ElemAlloc>();
|
||||
} else {
|
||||
allocator_ = std::make_shared<ElemAlloc>(*allocator.get());
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~MappedRingBuffer() {}
|
||||
|
||||
/// Return a copy of the value stored in the ring buffer at the given key.
|
||||
/**
|
||||
* The key is matched if an element in the ring buffer has a matching key.
|
||||
* This method will allocate in order to return a copy.
|
||||
*
|
||||
* The key is not guaranteed to be unique, see the class docs for more.
|
||||
*
|
||||
* The contents of value before the method is called are discarded.
|
||||
*
|
||||
* \param key the key associated with the stored value
|
||||
* \param value if the key is found, the value is stored in this parameter
|
||||
*/
|
||||
void
|
||||
get(uint64_t key, ElemUniquePtr & value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(data_mutex_);
|
||||
auto it = get_iterator_of_key(key);
|
||||
value = nullptr;
|
||||
if (it != elements_.end() && it->in_use) {
|
||||
if (it->unique_value) {
|
||||
ElemDeleter deleter = it->unique_value.get_deleter();
|
||||
auto ptr = ElemAllocTraits::allocate(*allocator_.get(), 1);
|
||||
ElemAllocTraits::construct(*allocator_.get(), ptr, *it->unique_value);
|
||||
value = ElemUniquePtr(ptr, deleter);
|
||||
} else if (it->shared_value) {
|
||||
ElemDeleter * deleter = std::get_deleter<ElemDeleter, const T>(it->shared_value);
|
||||
auto ptr = ElemAllocTraits::allocate(*allocator_.get(), 1);
|
||||
ElemAllocTraits::construct(*allocator_.get(), ptr, *it->shared_value);
|
||||
if (deleter) {
|
||||
value = ElemUniquePtr(ptr, *deleter);
|
||||
} else {
|
||||
value = ElemUniquePtr(ptr);
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("Unexpected empty MappedRingBuffer element.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Share ownership of the value stored in the ring buffer at the given key.
|
||||
/**
|
||||
* The key is matched if an element in the ring buffer has a matching key.
|
||||
*
|
||||
* The key is not guaranteed to be unique, see the class docs for more.
|
||||
*
|
||||
* The contents of value before the method is called are discarded.
|
||||
*
|
||||
* \param key the key associated with the stored value
|
||||
* \param value if the key is found, the value is stored in this parameter
|
||||
*/
|
||||
void
|
||||
get(uint64_t key, ConstElemSharedPtr & value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(data_mutex_);
|
||||
auto it = get_iterator_of_key(key);
|
||||
value.reset();
|
||||
if (it != elements_.end() && it->in_use) {
|
||||
if (!it->shared_value) {
|
||||
// The stored unique_ptr is upgraded to a shared_ptr here.
|
||||
// All the remaining get and pop calls done with unique_ptr
|
||||
// signature will receive a copy.
|
||||
if (!it->unique_value) {
|
||||
throw std::runtime_error("Unexpected empty MappedRingBuffer element.");
|
||||
}
|
||||
it->shared_value = std::move(it->unique_value);
|
||||
}
|
||||
value = it->shared_value;
|
||||
}
|
||||
}
|
||||
|
||||
/// Give the ownership of the stored value to the caller if possible, or copy and release.
|
||||
/**
|
||||
* The key is matched if an element in the ring buffer has a matching key.
|
||||
* This method may allocate in order to return a copy.
|
||||
*
|
||||
* If the stored value is a shared_ptr, it is not possible to downgrade it to a unique_ptr.
|
||||
* In that case, a copy is returned and the stored value is released.
|
||||
*
|
||||
* The key is not guaranteed to be unique, see the class docs for more.
|
||||
*
|
||||
* The contents of value before the method is called are discarded.
|
||||
*
|
||||
* \param key the key associated with the stored value
|
||||
* \param value if the key is found, the value is stored in this parameter
|
||||
*/
|
||||
void
|
||||
pop(uint64_t key, ElemUniquePtr & value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(data_mutex_);
|
||||
auto it = get_iterator_of_key(key);
|
||||
value = nullptr;
|
||||
if (it != elements_.end() && it->in_use) {
|
||||
if (it->unique_value) {
|
||||
value = std::move(it->unique_value);
|
||||
} else if (it->shared_value) {
|
||||
auto ptr = ElemAllocTraits::allocate(*allocator_.get(), 1);
|
||||
ElemAllocTraits::construct(*allocator_.get(), ptr, *it->shared_value);
|
||||
auto deleter = std::get_deleter<ElemDeleter, const T>(it->shared_value);
|
||||
if (deleter) {
|
||||
value = ElemUniquePtr(ptr, *deleter);
|
||||
} else {
|
||||
value = ElemUniquePtr(ptr);
|
||||
}
|
||||
it->shared_value.reset();
|
||||
} else {
|
||||
throw std::runtime_error("Unexpected empty MappedRingBuffer element.");
|
||||
}
|
||||
it->in_use = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Give the ownership of the stored value to the caller, at the given key.
|
||||
/**
|
||||
* The key is matched if an element in the ring buffer has a matching key.
|
||||
*
|
||||
* The key is not guaranteed to be unique, see the class docs for more.
|
||||
*
|
||||
* The contents of value before the method is called are discarded.
|
||||
*
|
||||
* \param key the key associated with the stored value
|
||||
* \param value if the key is found, the value is stored in this parameter
|
||||
*/
|
||||
void
|
||||
pop(uint64_t key, ConstElemSharedPtr & value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(data_mutex_);
|
||||
auto it = get_iterator_of_key(key);
|
||||
if (it != elements_.end() && it->in_use) {
|
||||
if (it->shared_value) {
|
||||
value = std::move(it->shared_value);
|
||||
} else if (it->unique_value) {
|
||||
value = std::move(it->unique_value);
|
||||
} else {
|
||||
throw std::runtime_error("Unexpected empty MappedRingBuffer element.");
|
||||
}
|
||||
it->in_use = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert a key-value pair, displacing an existing pair if necessary.
|
||||
/**
|
||||
* The key's uniqueness is not checked on insertion.
|
||||
* It is up to the user to ensure the key is unique.
|
||||
* This method should not allocate memory.
|
||||
*
|
||||
* After insertion the value will be a nullptr.
|
||||
* If a pair were replaced, its smart pointer is reset.
|
||||
*
|
||||
* \param key the key associated with the value to be stored
|
||||
* \param value the value to store, and optionally the value displaced
|
||||
*/
|
||||
bool
|
||||
push_and_replace(uint64_t key, ConstElemSharedPtr value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(data_mutex_);
|
||||
bool did_replace = elements_[head_].in_use;
|
||||
Element & element = elements_[head_];
|
||||
element.key = key;
|
||||
element.unique_value.reset();
|
||||
element.shared_value.reset();
|
||||
element.shared_value = value;
|
||||
element.in_use = true;
|
||||
head_ = (head_ + 1) % elements_.size();
|
||||
return did_replace;
|
||||
}
|
||||
|
||||
/// Insert a key-value pair, displacing an existing pair if necessary.
|
||||
/**
|
||||
* See `bool push_and_replace(uint64_t key, const ConstElemSharedPtr & value)`.
|
||||
*/
|
||||
bool
|
||||
push_and_replace(uint64_t key, ElemUniquePtr value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(data_mutex_);
|
||||
bool did_replace = elements_[head_].in_use;
|
||||
Element & element = elements_[head_];
|
||||
element.key = key;
|
||||
element.unique_value.reset();
|
||||
element.shared_value.reset();
|
||||
element.unique_value = std::move(value);
|
||||
element.in_use = true;
|
||||
head_ = (head_ + 1) % elements_.size();
|
||||
return did_replace;
|
||||
}
|
||||
|
||||
/// Return true if the key is found in the ring buffer, otherwise false.
|
||||
bool
|
||||
has_key(uint64_t key)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(data_mutex_);
|
||||
return elements_.end() != get_iterator_of_key(key);
|
||||
}
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(MappedRingBuffer<T, Alloc>)
|
||||
|
||||
struct Element
|
||||
{
|
||||
uint64_t key;
|
||||
ElemUniquePtr unique_value;
|
||||
ConstElemSharedPtr shared_value;
|
||||
bool in_use;
|
||||
};
|
||||
|
||||
using VectorAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<Element>;
|
||||
|
||||
typename std::vector<Element, VectorAlloc>::iterator
|
||||
get_iterator_of_key(uint64_t key)
|
||||
{
|
||||
auto it = std::find_if(
|
||||
elements_.begin(), elements_.end(),
|
||||
[key](Element & e) -> bool {
|
||||
return e.key == key && e.in_use;
|
||||
});
|
||||
return it;
|
||||
}
|
||||
|
||||
std::vector<Element, VectorAlloc> elements_;
|
||||
size_t head_;
|
||||
std::shared_ptr<ElemAlloc> allocator_;
|
||||
std::mutex data_mutex_;
|
||||
};
|
||||
|
||||
} // namespace mapped_ring_buffer
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__MAPPED_RING_BUFFER_HPP_
|
||||
@@ -23,10 +23,6 @@ namespace rclcpp
|
||||
namespace memory_strategies
|
||||
{
|
||||
|
||||
/// Create a MemoryStrategy sharedPtr
|
||||
/**
|
||||
* \return a MemoryStrategy sharedPtr
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
memory_strategy::MemoryStrategy::SharedPtr
|
||||
create_default_strategy();
|
||||
|
||||
@@ -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;
|
||||
@@ -59,7 +56,6 @@ public:
|
||||
virtual size_t number_of_guard_conditions() const = 0;
|
||||
virtual size_t number_of_waitables() const = 0;
|
||||
|
||||
virtual void add_waitable_handle(const rclcpp::Waitable::SharedPtr & waitable) = 0;
|
||||
virtual bool add_handles_to_wait_set(rcl_wait_set_t * wait_set) = 0;
|
||||
virtual void clear_handles() = 0;
|
||||
virtual void remove_null_handles(rcl_wait_set_t * wait_set) = 0;
|
||||
@@ -70,28 +66,23 @@ public:
|
||||
|
||||
virtual void
|
||||
get_next_subscription(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) = 0;
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_service(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) = 0;
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_client(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_timer(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) = 0;
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_waitable(
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes) = 0;
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual rcl_allocator_t
|
||||
get_allocator() = 0;
|
||||
@@ -99,52 +90,42 @@ 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);
|
||||
|
||||
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);
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_group_by_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_group_by_service(
|
||||
rclcpp::ServiceBase::SharedPtr service,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
static rclcpp::callback_group::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);
|
||||
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_group_by_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable,
|
||||
const WeakCallbackGroupsToNodesMap & weak_groups_to_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
};
|
||||
|
||||
} // namespace memory_strategy
|
||||
|
||||
@@ -1,55 +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__MESSAGE_INFO_HPP_
|
||||
#define RCLCPP__MESSAGE_INFO_HPP_
|
||||
|
||||
#include "rmw/types.h"
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Additional meta data about messages taken from subscriptions.
|
||||
class RCLCPP_PUBLIC MessageInfo
|
||||
{
|
||||
public:
|
||||
/// Default empty constructor.
|
||||
MessageInfo() = default;
|
||||
|
||||
/// Conversion constructor, which is intentionally not marked as explicit.
|
||||
/**
|
||||
* \param[in] rmw_message_info message info to initialize the class
|
||||
*/
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
MessageInfo(const rmw_message_info_t & rmw_message_info); // NOLINT(runtime/explicit)
|
||||
|
||||
virtual ~MessageInfo();
|
||||
|
||||
/// Return the message info as the underlying rmw message info type.
|
||||
const rmw_message_info_t &
|
||||
get_rmw_message_info() const;
|
||||
|
||||
/// Return the message info as the underlying rmw message info type.
|
||||
rmw_message_info_t &
|
||||
get_rmw_message_info();
|
||||
|
||||
private:
|
||||
rmw_message_info_t rmw_message_info_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__MESSAGE_INFO_HPP_
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "rclcpp/allocator/allocator_common.hpp"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rcutils/logging_macros.h"
|
||||
@@ -47,10 +46,10 @@ public:
|
||||
using MessageAlloc = typename MessageAllocTraits::allocator_type;
|
||||
using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;
|
||||
|
||||
using SerializedMessageAllocTraits = allocator::AllocRebind<rclcpp::SerializedMessage, Alloc>;
|
||||
using SerializedMessageAllocTraits = allocator::AllocRebind<rcl_serialized_message_t, Alloc>;
|
||||
using SerializedMessageAlloc = typename SerializedMessageAllocTraits::allocator_type;
|
||||
using SerializedMessageDeleter =
|
||||
allocator::Deleter<SerializedMessageAlloc, rclcpp::SerializedMessage>;
|
||||
allocator::Deleter<SerializedMessageAlloc, rcl_serialized_message_t>;
|
||||
|
||||
using BufferAllocTraits = allocator::AllocRebind<char, Alloc>;
|
||||
using BufferAlloc = typename BufferAllocTraits::allocator_type;
|
||||
@@ -87,12 +86,30 @@ public:
|
||||
return std::allocate_shared<MessageT, MessageAlloc>(*message_allocator_.get());
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<rclcpp::SerializedMessage> borrow_serialized_message(size_t capacity)
|
||||
virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message(size_t capacity)
|
||||
{
|
||||
return std::make_shared<rclcpp::SerializedMessage>(capacity);
|
||||
auto msg = new rcl_serialized_message_t;
|
||||
*msg = rmw_get_zero_initialized_serialized_message();
|
||||
auto ret = rmw_serialized_message_init(msg, capacity, &rcutils_allocator_);
|
||||
if (ret != RCL_RET_OK) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
|
||||
auto serialized_msg = std::shared_ptr<rcl_serialized_message_t>(msg,
|
||||
[](rmw_serialized_message_t * msg) {
|
||||
auto ret = rmw_serialized_message_fini(msg);
|
||||
delete msg;
|
||||
if (ret != RCL_RET_OK) {
|
||||
RCUTILS_LOG_ERROR_NAMED(
|
||||
"rclcpp",
|
||||
"failed to destroy serialized message: %s", rcl_get_error_string().str);
|
||||
}
|
||||
});
|
||||
|
||||
return serialized_msg;
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<rclcpp::SerializedMessage> borrow_serialized_message()
|
||||
virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message()
|
||||
{
|
||||
return borrow_serialized_message(default_buffer_capacity_);
|
||||
}
|
||||
@@ -109,8 +126,7 @@ public:
|
||||
msg.reset();
|
||||
}
|
||||
|
||||
virtual void return_serialized_message(
|
||||
std::shared_ptr<rclcpp::SerializedMessage> & serialized_msg)
|
||||
virtual void return_serialized_message(std::shared_ptr<rcl_serialized_message_t> & serialized_msg)
|
||||
{
|
||||
serialized_msg.reset();
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -27,8 +26,6 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rcutils/macros.h"
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/node.h"
|
||||
|
||||
@@ -42,8 +39,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"
|
||||
@@ -83,7 +78,6 @@ public:
|
||||
/**
|
||||
* \param[in] node_name Name of the node.
|
||||
* \param[in] options Additional options to control creation of the node.
|
||||
* \throws InvalidNamespaceError if the namespace is invalid
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit Node(
|
||||
@@ -95,7 +89,6 @@ public:
|
||||
* \param[in] node_name Name of the node.
|
||||
* \param[in] namespace_ Namespace of the node.
|
||||
* \param[in] options Additional options to control creation of the node.
|
||||
* \throws InvalidNamespaceError if the namespace is invalid
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit Node(
|
||||
@@ -129,7 +122,6 @@ public:
|
||||
/// Get the fully-qualified name of the node.
|
||||
/**
|
||||
* The fully-qualified name includes the local namespace and name of the node.
|
||||
* \return fully-qualified name of the node.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
const char *
|
||||
@@ -143,27 +135,14 @@ 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);
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
create_callback_group(rclcpp::callback_group::CallbackGroupType group_type);
|
||||
|
||||
/// Return the list of callback groups in the node.
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
|
||||
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
|
||||
get_callback_groups() const;
|
||||
|
||||
/// Iterate over the callback groups in the node, calling the given function on each valid one.
|
||||
/**
|
||||
* This method is called in a thread-safe way, and also makes sure to only call the given
|
||||
* function on those items that are still valid.
|
||||
*
|
||||
* \param[in] func The callback function to call on each valid callback group.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
for_each_callback_group(const node_interfaces::NodeBaseInterface::CallbackGroupFunction & func);
|
||||
|
||||
/// Create and return a Publisher.
|
||||
/**
|
||||
* The rclcpp::QoS has several convenient constructors, including a
|
||||
@@ -172,17 +151,15 @@ public:
|
||||
*
|
||||
* For example, all of these cases will work:
|
||||
*
|
||||
* ```cpp
|
||||
* pub = node->create_publisher<MsgT>("chatter", 10); // implicitly KeepLast
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(10)); // implicitly KeepLast
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(KeepLast(10)));
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(KeepAll()));
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(1).best_effort().durability_volatile());
|
||||
* {
|
||||
* rclcpp::QoS custom_qos(KeepLast(10), rmw_qos_profile_sensor_data);
|
||||
* pub = node->create_publisher<MsgT>("chatter", custom_qos);
|
||||
* }
|
||||
* ```
|
||||
* pub = node->create_publisher<MsgT>("chatter", 10); // implicitly KeepLast
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(10)); // implicitly KeepLast
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(KeepLast(10)));
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(KeepAll()));
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(1).best_effort().durability_volatile());
|
||||
* {
|
||||
* rclcpp::QoS custom_qos(KeepLast(10), rmw_qos_profile_sensor_data);
|
||||
* pub = node->create_publisher<MsgT>("chatter", custom_qos);
|
||||
* }
|
||||
*
|
||||
* The publisher options may optionally be passed as the third argument for
|
||||
* any of the above cases.
|
||||
@@ -195,7 +172,7 @@ public:
|
||||
template<
|
||||
typename MessageT,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
typename PublisherT = rclcpp::Publisher<MessageT, AllocatorT>>
|
||||
typename PublisherT = ::rclcpp::Publisher<MessageT, AllocatorT>>
|
||||
std::shared_ptr<PublisherT>
|
||||
create_publisher(
|
||||
const std::string & topic_name,
|
||||
@@ -204,27 +181,63 @@ public:
|
||||
PublisherOptionsWithAllocator<AllocatorT>()
|
||||
);
|
||||
|
||||
/// Create and return a Publisher.
|
||||
/**
|
||||
* \param[in] topic_name The topic for this publisher to publish on.
|
||||
* \param[in] qos_history_depth The depth of the publisher message queue.
|
||||
* \param[in] allocator Custom allocator.
|
||||
* \return Shared pointer to the created publisher.
|
||||
*/
|
||||
template<
|
||||
typename MessageT,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
typename PublisherT = ::rclcpp::Publisher<MessageT, AllocatorT>>
|
||||
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
|
||||
[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]
|
||||
std::shared_ptr<PublisherT>
|
||||
create_publisher(
|
||||
const std::string & topic_name,
|
||||
size_t qos_history_depth,
|
||||
std::shared_ptr<AllocatorT> allocator);
|
||||
|
||||
/// Create and return a Publisher.
|
||||
/**
|
||||
* \param[in] topic_name The topic for this publisher to publish on.
|
||||
* \param[in] qos_profile The quality of service profile to pass on to the rmw implementation.
|
||||
* \param[in] allocator Optional custom allocator.
|
||||
* \return Shared pointer to the created publisher.
|
||||
*/
|
||||
template<
|
||||
typename MessageT,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
typename PublisherT = ::rclcpp::Publisher<MessageT, AllocatorT>>
|
||||
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
|
||||
[[deprecated("use create_publisher(const std::string &, const rclcpp::QoS &, ...) instead")]]
|
||||
std::shared_ptr<PublisherT>
|
||||
create_publisher(
|
||||
const std::string & topic_name,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_default,
|
||||
std::shared_ptr<AllocatorT> allocator = nullptr);
|
||||
|
||||
/// Create and return a Subscription.
|
||||
/**
|
||||
* \param[in] topic_name The topic to subscribe on.
|
||||
* \param[in] qos QoS profile for Subcription.
|
||||
* \param[in] callback The user-defined callback function to receive a message
|
||||
* \param[in] qos_history_depth The depth of the subscription's incoming message queue.
|
||||
* \param[in] options Additional options for the creation of the Subscription.
|
||||
* \param[in] msg_mem_strat The message memory strategy to use for allocating messages.
|
||||
* \return Shared pointer to the created subscription.
|
||||
*/
|
||||
/* TODO(jacquelinekay):
|
||||
Windows build breaks when static member function passed as default
|
||||
argument to msg_mem_strat, nullptr is a workaround.
|
||||
*/
|
||||
template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
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 SubscriptionT = rclcpp::Subscription<
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, AllocatorT>>
|
||||
std::shared_ptr<SubscriptionT>
|
||||
create_subscription(
|
||||
const std::string & topic_name,
|
||||
@@ -232,10 +245,84 @@ public:
|
||||
CallbackT && callback,
|
||||
const SubscriptionOptionsWithAllocator<AllocatorT> & options =
|
||||
SubscriptionOptionsWithAllocator<AllocatorT>(),
|
||||
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat = (
|
||||
MessageMemoryStrategyT::create_default()
|
||||
)
|
||||
);
|
||||
typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, AllocatorT
|
||||
>::SharedPtr
|
||||
msg_mem_strat = nullptr);
|
||||
|
||||
/// Create and return a Subscription.
|
||||
/**
|
||||
* \param[in] topic_name The topic to subscribe on.
|
||||
* \param[in] callback The user-defined callback function.
|
||||
* \param[in] qos_profile The quality of service profile to pass on to the rmw implementation.
|
||||
* \param[in] group The callback group for this subscription. NULL for no callback group.
|
||||
* \param[in] ignore_local_publications True to ignore local publications.
|
||||
* \param[in] msg_mem_strat The message memory strategy to use for allocating messages.
|
||||
* \param[in] allocator Optional custom allocator.
|
||||
* \return Shared pointer to the created subscription.
|
||||
*/
|
||||
/* TODO(jacquelinekay):
|
||||
Windows build breaks when static member function passed as default
|
||||
argument to msg_mem_strat, nullptr is a workaround.
|
||||
*/
|
||||
template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename SubscriptionT = rclcpp::Subscription<
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, Alloc>>
|
||||
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
|
||||
[[deprecated(
|
||||
"use create_subscription(const std::string &, const rclcpp::QoS &, CallbackT, ...) instead"
|
||||
)]]
|
||||
std::shared_ptr<SubscriptionT>
|
||||
create_subscription(
|
||||
const std::string & topic_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_default,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr,
|
||||
bool ignore_local_publications = false,
|
||||
typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, Alloc>::SharedPtr
|
||||
msg_mem_strat = nullptr,
|
||||
std::shared_ptr<Alloc> allocator = nullptr);
|
||||
|
||||
/// Create and return a Subscription.
|
||||
/**
|
||||
* \param[in] topic_name The topic to subscribe on.
|
||||
* \param[in] qos_history_depth The depth of the subscription's incoming message queue.
|
||||
* \param[in] callback The user-defined callback function.
|
||||
* \param[in] group The callback group for this subscription. NULL for no callback group.
|
||||
* \param[in] ignore_local_publications True to ignore local publications.
|
||||
* \param[in] msg_mem_strat The message memory strategy to use for allocating messages.
|
||||
* \param[in] allocator Optional custom allocator.
|
||||
* \return Shared pointer to the created subscription.
|
||||
*/
|
||||
/* TODO(jacquelinekay):
|
||||
Windows build breaks when static member function passed as default
|
||||
argument to msg_mem_strat, nullptr is a workaround.
|
||||
*/
|
||||
template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename SubscriptionT = rclcpp::Subscription<
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, Alloc>>
|
||||
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
|
||||
[[deprecated(
|
||||
"use create_subscription(const std::string &, const rclcpp::QoS &, CallbackT, ...) instead"
|
||||
)]]
|
||||
std::shared_ptr<SubscriptionT>
|
||||
create_subscription(
|
||||
const std::string & topic_name,
|
||||
CallbackT && callback,
|
||||
size_t qos_history_depth,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr,
|
||||
bool ignore_local_publications = false,
|
||||
typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, Alloc>::SharedPtr
|
||||
msg_mem_strat = nullptr,
|
||||
std::shared_ptr<Alloc> allocator = nullptr);
|
||||
|
||||
/// Create a timer.
|
||||
/**
|
||||
@@ -248,7 +335,7 @@ public:
|
||||
create_wall_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a Client.
|
||||
/**
|
||||
@@ -262,7 +349,7 @@ public:
|
||||
create_client(
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a Service.
|
||||
/**
|
||||
@@ -278,56 +365,7 @@ public:
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
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>()
|
||||
)
|
||||
);
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Declare and initialize a parameter, return the effective value.
|
||||
/**
|
||||
@@ -344,10 +382,8 @@ public:
|
||||
* are ignored, and should be specified using the name argument to this
|
||||
* function and the default value's type instead.
|
||||
*
|
||||
* If `ignore_override` is `true`, the parameter override will be ignored.
|
||||
*
|
||||
* This method, if successful, will result in any callback registered with
|
||||
* add_on_set_parameters_callback to be called.
|
||||
* set_on_parameters_set_callback to be called.
|
||||
* If that callback prevents the initial value for the parameter from being
|
||||
* set then rclcpp::exceptions::InvalidParameterValueException is thrown.
|
||||
*
|
||||
@@ -359,8 +395,6 @@ public:
|
||||
* did not override it.
|
||||
* \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 rclcpp::exceptions::ParameterAlreadyDeclaredException if parameter
|
||||
* has already been declared.
|
||||
@@ -368,58 +402,14 @@ 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);
|
||||
rcl_interfaces::msg::ParameterDescriptor());
|
||||
|
||||
/// Declare and initialize a parameter with a type.
|
||||
/**
|
||||
@@ -427,7 +417,7 @@ public:
|
||||
*
|
||||
* If the type of the default value, and therefore also the type of return
|
||||
* value, differs from the initial value provided in the node options, then
|
||||
* a rclcpp::exceptions::InvalidParameterTypeException may be thrown.
|
||||
* a rclcpp::ParameterTypeException may be thrown.
|
||||
* To avoid this, use the declare_parameter() method which returns an
|
||||
* rclcpp::ParameterValue instead.
|
||||
*
|
||||
@@ -448,20 +438,7 @@ public:
|
||||
const std::string & name,
|
||||
const ParameterT & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
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);
|
||||
rcl_interfaces::msg::ParameterDescriptor());
|
||||
|
||||
/// Declare and initialize several parameters with the same namespace and type.
|
||||
/**
|
||||
@@ -476,22 +453,19 @@ public:
|
||||
* expanding "namespace.key".
|
||||
* This allows you to declare several parameters at once without a namespace.
|
||||
*
|
||||
* The map contains default values for parameters.
|
||||
* There is another overload which takes the std::pair with the default value
|
||||
* and descriptor.
|
||||
*
|
||||
* If `ignore_overrides` is `true`, all the overrides of the parameters declared
|
||||
* by the function call will be ignored.
|
||||
* The map may either contain default values for parameters, or a std::pair
|
||||
* where the first element is a default value and the second is a
|
||||
* parameter descriptor.
|
||||
* This function only takes the default value, but there is another overload
|
||||
* which takes the std::pair with the default value and descriptor.
|
||||
*
|
||||
* This method, if successful, will result in any callback registered with
|
||||
* add_on_set_parameters_callback to be called, once for each parameter.
|
||||
* set_on_parameters_set_callback to be called, once for each parameter.
|
||||
* If that callback prevents the initial value for any parameter from being
|
||||
* set then rclcpp::exceptions::InvalidParameterValueException is thrown.
|
||||
*
|
||||
* \param[in] namespace_ The namespace in which to declare the parameters.
|
||||
* \param[in] parameters The parameters to set in the given namespace.
|
||||
* \param[in] ignore_overrides When `true`, the parameters overrides are ignored.
|
||||
* Default to `false`.
|
||||
* \throws rclcpp::exceptions::ParameterAlreadyDeclaredException if parameter
|
||||
* has already been declared.
|
||||
* \throws rclcpp::exceptions::InvalidParametersException if a parameter
|
||||
@@ -503,8 +477,7 @@ public:
|
||||
std::vector<ParameterT>
|
||||
declare_parameters(
|
||||
const std::string & namespace_,
|
||||
const std::map<std::string, ParameterT> & parameters,
|
||||
bool ignore_overrides = false);
|
||||
const std::map<std::string, ParameterT> & parameters);
|
||||
|
||||
/// Declare and initialize several parameters with the same namespace and type.
|
||||
/**
|
||||
@@ -520,13 +493,12 @@ public:
|
||||
const std::map<
|
||||
std::string,
|
||||
std::pair<ParameterT, rcl_interfaces::msg::ParameterDescriptor>
|
||||
> & parameters,
|
||||
bool ignore_overrides = false);
|
||||
> & parameters);
|
||||
|
||||
/// Undeclare a previously declared parameter.
|
||||
/**
|
||||
* This method will not cause a callback registered with
|
||||
* add_on_set_parameters_callback to be called.
|
||||
* set_on_parameters_set_callback to be called.
|
||||
*
|
||||
* \param[in] name The name of the parameter to be undeclared.
|
||||
* \throws rclcpp::exceptions::ParameterNotDeclaredException if the parameter
|
||||
@@ -560,7 +532,7 @@ public:
|
||||
* Parameter overrides are ignored by set_parameter.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* add_on_set_parameters_callback to be called.
|
||||
* set_on_parameters_set_callback to be called.
|
||||
* If the callback prevents the parameter from being set, then it will be
|
||||
* reflected in the SetParametersResult that is returned, but no exception
|
||||
* will be thrown.
|
||||
@@ -601,7 +573,7 @@ public:
|
||||
* corresponding SetParametersResult in the vector returned by this function.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* add_on_set_parameters_callback to be called, once for each parameter.
|
||||
* set_on_parameters_set_callback to be called, once for each parameter.
|
||||
* If the callback prevents the parameter from being set, then, as mentioned
|
||||
* before, it will be reflected in the corresponding SetParametersResult
|
||||
* that is returned, but no exception will be thrown.
|
||||
@@ -632,7 +604,7 @@ public:
|
||||
* If the exception is thrown then none of the parameters will have been set.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* add_on_set_parameters_callback to be called, just one time.
|
||||
* set_on_parameters_set_callback to be called, just one time.
|
||||
* If the callback prevents the parameters from being set, then it will be
|
||||
* reflected in the SetParametersResult which is returned, but no exception
|
||||
* will be thrown.
|
||||
@@ -652,6 +624,38 @@ public:
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
set_parameters_atomically(const std::vector<rclcpp::Parameter> & parameters);
|
||||
|
||||
/// Set one parameter, unless that parameter has already been set.
|
||||
/**
|
||||
* Set the given parameter unless already set.
|
||||
*
|
||||
* Deprecated, instead use declare_parameter().
|
||||
*
|
||||
* \param[in] parameters The vector of parameters to be set.
|
||||
* \return The result of each set action as a vector.
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
|
||||
[[deprecated("use declare_parameter() instead")]]
|
||||
void
|
||||
set_parameter_if_not_set(const std::string & name, const ParameterT & value);
|
||||
|
||||
/// Set a map of parameters with the same prefix.
|
||||
/**
|
||||
* For each key in the map, a parameter with a name of "name.key" will be set
|
||||
* to the value in the map.
|
||||
*
|
||||
* Deprecated, instead use declare_parameters().
|
||||
*
|
||||
* \param[in] name The prefix of the parameters to set.
|
||||
* \param[in] values The parameters to set in the given prefix.
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
[[deprecated("use declare_parameters() instead")]]
|
||||
void
|
||||
set_parameters_if_not_set(
|
||||
const std::string & name,
|
||||
const std::map<std::string, ParameterT> & values);
|
||||
|
||||
/// Return the parameter by the given name.
|
||||
/**
|
||||
* If the parameter has not been declared, then this method may throw the
|
||||
@@ -795,6 +799,28 @@ public:
|
||||
const std::string & prefix,
|
||||
std::map<std::string, ParameterT> & values) const;
|
||||
|
||||
/// Get the parameter value; if not set, set the "alternative value" and store it in the node.
|
||||
/**
|
||||
* If the parameter is set, then the "value" argument is assigned the value
|
||||
* in the parameter.
|
||||
* If the parameter is not set, then the "value" argument is assigned the "alternative_value",
|
||||
* and the parameter is set to the "alternative_value" on the node.
|
||||
*
|
||||
* Deprecated, instead use declare_parameter()'s return value, or use
|
||||
* has_parameter() to ensure it exists before getting it.
|
||||
*
|
||||
* \param[in] name The name of the parameter to get.
|
||||
* \param[out] value The output where the value of the parameter should be assigned.
|
||||
* \param[in] alternative_value Value to be used if the parameter was not set.
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
[[deprecated("use declare_parameter() and it's return value instead")]]
|
||||
void
|
||||
get_parameter_or_set(
|
||||
const std::string & name,
|
||||
ParameterT & value,
|
||||
const ParameterT & alternative_value);
|
||||
|
||||
/// Return the parameter descriptor for the given parameter name.
|
||||
/**
|
||||
* Like get_parameters(), this method may throw the
|
||||
@@ -810,7 +836,6 @@ public:
|
||||
* \throws rclcpp::exceptions::ParameterNotDeclaredException if the
|
||||
* parameter has not been declared and undeclared parameters are not
|
||||
* allowed.
|
||||
* \throws std::runtime_error if the number of described parameters is more than one
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rcl_interfaces::msg::ParameterDescriptor
|
||||
@@ -833,7 +858,6 @@ public:
|
||||
* \throws rclcpp::exceptions::ParameterNotDeclaredException if any of the
|
||||
* parameters have not been declared and undeclared parameters are not
|
||||
* allowed.
|
||||
* \throws std::runtime_error if the number of described parameters is more than one
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rcl_interfaces::msg::ParameterDescriptor>
|
||||
@@ -867,12 +891,10 @@ public:
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const;
|
||||
|
||||
using OnSetParametersCallbackHandle =
|
||||
rclcpp::node_interfaces::OnSetParametersCallbackHandle;
|
||||
using OnParametersSetCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;
|
||||
|
||||
/// Add a callback for when parameters are being set.
|
||||
/// Register a callback to be called anytime a parameter is about to be changed.
|
||||
/**
|
||||
* The callback signature is designed to allow handling of any of the above
|
||||
* `set_parameter*` or `declare_parameter*` methods, and so it takes a const
|
||||
@@ -882,30 +904,25 @@ public:
|
||||
*
|
||||
* For an example callback:
|
||||
*
|
||||
* ```cpp
|
||||
* rcl_interfaces::msg::SetParametersResult
|
||||
* my_callback(const std::vector<rclcpp::Parameter> & parameters)
|
||||
* {
|
||||
* rcl_interfaces::msg::SetParametersResult result;
|
||||
* result.successful = true;
|
||||
* for (const auto & parameter : parameters) {
|
||||
* if (!some_condition) {
|
||||
* result.successful = false;
|
||||
* result.reason = "the reason it could not be allowed";
|
||||
* rcl_interfaces::msg::SetParametersResult
|
||||
* my_callback(const std::vector<rclcpp::Parameter> & parameters)
|
||||
* {
|
||||
* rcl_interfaces::msg::SetParametersResult result;
|
||||
* result.successful = true;
|
||||
* for (const auto & parameter : parameters) {
|
||||
* if (!some_condition) {
|
||||
* result.successful = false;
|
||||
* result.reason = "the reason it could not be allowed";
|
||||
* }
|
||||
* }
|
||||
* return result;
|
||||
* }
|
||||
* return result;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* You can see that the SetParametersResult is a boolean flag for success
|
||||
* and an optional reason that can be used in error reporting when it fails.
|
||||
*
|
||||
* 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
|
||||
@@ -913,60 +930,29 @@ public:
|
||||
*
|
||||
* Some constraints like read_only are enforced before the callback is called.
|
||||
*
|
||||
* The callback may introspect other already set parameters (by calling any
|
||||
* of the {get,list,describe}_parameter() methods), but may *not* modify
|
||||
* other parameters (by calling any of the {set,declare}_parameter() methods)
|
||||
* or modify the registered callback itself (by calling the
|
||||
* add_on_set_parameters_callback() method). If a callback tries to do any
|
||||
* of the latter things,
|
||||
* rclcpp::exceptions::ParameterModifiedInCallbackException will be thrown.
|
||||
* There may only be one callback set at a time, so the previously set
|
||||
* callback is returned when this method is used, or nullptr will be returned
|
||||
* if no callback was previously set.
|
||||
*
|
||||
* The callback functions must remain valid as long as the
|
||||
* returned smart pointer is valid.
|
||||
* The returned smart pointer can be promoted to a shared version.
|
||||
*
|
||||
* Resetting or letting the smart pointer go out of scope unregisters the callback.
|
||||
* `remove_on_set_parameters_callback` can also be used.
|
||||
*
|
||||
* The registered callbacks are called when a parameter is set.
|
||||
* When a callback returns a not successful result, the remaining callbacks aren't called.
|
||||
* The order of the callback is the reverse from the registration order.
|
||||
*
|
||||
* \param callback The callback to register.
|
||||
* \returns A shared pointer. The callback is valid as long as the smart pointer is alive.
|
||||
* \throws std::bad_alloc if the allocation of the OnSetParametersCallbackHandle fails.
|
||||
* \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.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
OnSetParametersCallbackHandle::SharedPtr
|
||||
add_on_set_parameters_callback(OnParametersSetCallbackType callback);
|
||||
rclcpp::Node::OnParametersSetCallbackType
|
||||
set_on_parameters_set_callback(rclcpp::Node::OnParametersSetCallbackType callback);
|
||||
|
||||
/// Remove a callback registered with `add_on_set_parameters_callback`.
|
||||
/// Register the callback for parameter changes
|
||||
/**
|
||||
* Delete a handler returned by `add_on_set_parameters_callback`.
|
||||
*
|
||||
* e.g.:
|
||||
*
|
||||
* `remove_on_set_parameters_callback(scoped_callback.get())`
|
||||
*
|
||||
* As an alternative, the smart pointer can be reset:
|
||||
*
|
||||
* `scoped_callback.reset()`
|
||||
*
|
||||
* Supposing that `scoped_callback` was the only owner.
|
||||
*
|
||||
* Calling `remove_on_set_parameters_callback` more than once with the same handler,
|
||||
* or calling it after the shared pointer has been reset is an error.
|
||||
* Resetting or letting the smart pointer go out of scope after calling
|
||||
* `remove_on_set_parameters_callback` is not a problem.
|
||||
*
|
||||
* \param handler The callback handler to remove.
|
||||
* \throws std::runtime_error if the handler was not created with `add_on_set_parameters_callback`,
|
||||
* or if it has been removed before.
|
||||
* \param[in] callback User defined callback function.
|
||||
* It is expected to atomically set parameters.
|
||||
* \note Repeated invocations of this function will overwrite previous callbacks.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
template<typename CallbackT>
|
||||
[[deprecated("use set_on_parameters_set_callback() instead")]]
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler);
|
||||
register_param_change_callback(CallbackT && callback);
|
||||
|
||||
/// Get the fully-qualified names of all available nodes.
|
||||
/**
|
||||
@@ -977,112 +963,22 @@ public:
|
||||
std::vector<std::string>
|
||||
get_node_names() const;
|
||||
|
||||
/// Return a map of existing topic names to list of topic types.
|
||||
/**
|
||||
* \return a map of existing topic names to list of topic types.
|
||||
* \throws std::runtime_error anything that rcl_error can throw
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_topic_names_and_types() const;
|
||||
|
||||
/// Return a map of existing service names to list of service types.
|
||||
/**
|
||||
* \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>>
|
||||
get_service_names_and_types() const;
|
||||
|
||||
/// 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.
|
||||
* \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>>
|
||||
get_service_names_and_types_by_node(
|
||||
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.
|
||||
/**
|
||||
* \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
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_subscribers(const std::string & topic_name) const;
|
||||
|
||||
/// Return the topic endpoint information about publishers on a given topic.
|
||||
/**
|
||||
* The returned parameter is a list of topic endpoint information, where each item will contain
|
||||
* the node name, node namespace, topic type, endpoint type, topic endpoint's GID, and its QoS
|
||||
* profile.
|
||||
*
|
||||
* When the `no_mangle` parameter is `true`, the provided `topic_name` should be a valid topic
|
||||
* name for the middleware (useful when combining ROS with native middleware (e.g. DDS) apps).
|
||||
* When the `no_mangle` parameter is `false`, the provided `topic_name` should follow
|
||||
* ROS topic name conventions.
|
||||
*
|
||||
* `topic_name` may be a relative, private, or fully qualified topic name.
|
||||
* 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] 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.
|
||||
* \throws InvalidTopicNameError if the given topic_name is invalid.
|
||||
* \throws std::runtime_error if internal error happens.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::TopicEndpointInfo>
|
||||
get_publishers_info_by_topic(const std::string & topic_name, bool no_mangle = false) const;
|
||||
|
||||
/// Return the topic endpoint information about subscriptions on a given topic.
|
||||
/**
|
||||
* The returned parameter is a list of topic endpoint information, where each item will contain
|
||||
* the node name, node namespace, topic type, endpoint type, topic endpoint's GID, and its QoS
|
||||
* profile.
|
||||
*
|
||||
* When the `no_mangle` parameter is `true`, the provided `topic_name` should be a valid topic
|
||||
* name for the middleware (useful when combining ROS with native middleware (e.g. DDS) apps).
|
||||
* When the `no_mangle` parameter is `false`, the provided `topic_name` should follow
|
||||
* ROS topic name conventions.
|
||||
*
|
||||
* `topic_name` may be a relative, private, or fully qualified topic name.
|
||||
* 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] 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.
|
||||
* \throws InvalidTopicNameError if the given topic_name is invalid.
|
||||
* \throws std::runtime_error if internal error happens.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::TopicEndpointInfo>
|
||||
get_subscriptions_info_by_topic(const std::string & topic_name, bool no_mangle = false) const;
|
||||
|
||||
/// Return a graph event, which will be set anytime a graph change occurs.
|
||||
/* The graph Event object is a loan which must be returned.
|
||||
* The Event object is scoped and therefore to return the loan just let it go
|
||||
@@ -1096,9 +992,6 @@ public:
|
||||
/**
|
||||
* The given Event must be acquire through the get_graph_event() method.
|
||||
*
|
||||
* \param[in] event pointer to an Event to wait for
|
||||
* \param[in] timeout nanoseconds to wait for the Event to change the state
|
||||
*
|
||||
* \throws InvalidEventError if the given event is nullptr
|
||||
* \throws EventNotRegisteredError if the given event was not acquired with
|
||||
* get_graph_event().
|
||||
@@ -1109,29 +1002,13 @@ public:
|
||||
rclcpp::Event::SharedPtr event,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
/// Get a clock as a non-const shared pointer which is managed by the node.
|
||||
/**
|
||||
* \sa rclcpp::node_interfaces::NodeClock::get_clock
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::Clock::SharedPtr
|
||||
get_clock();
|
||||
|
||||
/// Get a clock as a const shared pointer which is managed by the node.
|
||||
/**
|
||||
* \sa rclcpp::node_interfaces::NodeClock::get_clock
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::Clock::ConstSharedPtr
|
||||
get_clock() const;
|
||||
|
||||
/// Returns current time from the time source specified by clock_type.
|
||||
/**
|
||||
* \sa rclcpp::Clock::now
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
Time
|
||||
now() const;
|
||||
now();
|
||||
|
||||
/// Return the Node's internal NodeBaseInterface implementation.
|
||||
RCLCPP_PUBLIC
|
||||
@@ -1178,7 +1055,7 @@ public:
|
||||
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr
|
||||
get_node_parameters_interface();
|
||||
|
||||
/// Return the Node's internal NodeTimeSourceInterface implementation.
|
||||
/// Return the Node's internal NodeParametersInterface implementation.
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::node_interfaces::NodeTimeSourceInterface::SharedPtr
|
||||
get_node_time_source_interface();
|
||||
@@ -1191,17 +1068,15 @@ public:
|
||||
*
|
||||
* For example, consider:
|
||||
*
|
||||
* ```cpp
|
||||
* auto node = std::make_shared<rclcpp::Node>("my_node", "my_ns");
|
||||
* node->get_sub_namespace(); // -> ""
|
||||
* auto sub_node1 = node->create_sub_node("a");
|
||||
* sub_node1->get_sub_namespace(); // -> "a"
|
||||
* auto sub_node2 = sub_node1->create_sub_node("b");
|
||||
* sub_node2->get_sub_namespace(); // -> "a/b"
|
||||
* auto sub_node3 = node->create_sub_node("foo");
|
||||
* sub_node3->get_sub_namespace(); // -> "foo"
|
||||
* node->get_sub_namespace(); // -> ""
|
||||
* ```
|
||||
* auto node = std::make_shared<rclcpp::Node>("my_node", "my_ns");
|
||||
* node->get_sub_namespace(); // -> ""
|
||||
* auto sub_node1 = node->create_sub_node("a");
|
||||
* sub_node1->get_sub_namespace(); // -> "a"
|
||||
* auto sub_node2 = sub_node1->create_sub_node("b");
|
||||
* sub_node2->get_sub_namespace(); // -> "a/b"
|
||||
* auto sub_node3 = node->create_sub_node("foo");
|
||||
* sub_node3->get_sub_namespace(); // -> "foo"
|
||||
* node->get_sub_namespace(); // -> ""
|
||||
*
|
||||
* get_namespace() will return the original node namespace, and will not
|
||||
* include the sub-namespace if one exists.
|
||||
@@ -1223,17 +1098,15 @@ public:
|
||||
*
|
||||
* For example, consider:
|
||||
*
|
||||
* ```cpp
|
||||
* auto node = std::make_shared<rclcpp::Node>("my_node", "my_ns");
|
||||
* node->get_effective_namespace(); // -> "/my_ns"
|
||||
* auto sub_node1 = node->create_sub_node("a");
|
||||
* sub_node1->get_effective_namespace(); // -> "/my_ns/a"
|
||||
* auto sub_node2 = sub_node1->create_sub_node("b");
|
||||
* sub_node2->get_effective_namespace(); // -> "/my_ns/a/b"
|
||||
* auto sub_node3 = node->create_sub_node("foo");
|
||||
* sub_node3->get_effective_namespace(); // -> "/my_ns/foo"
|
||||
* node->get_effective_namespace(); // -> "/my_ns"
|
||||
* ```
|
||||
* auto node = std::make_shared<rclcpp::Node>("my_node", "my_ns");
|
||||
* node->get_effective_namespace(); // -> "/my_ns"
|
||||
* auto sub_node1 = node->create_sub_node("a");
|
||||
* sub_node1->get_effective_namespace(); // -> "/my_ns/a"
|
||||
* auto sub_node2 = sub_node1->create_sub_node("b");
|
||||
* sub_node2->get_effective_namespace(); // -> "/my_ns/a/b"
|
||||
* auto sub_node3 = node->create_sub_node("foo");
|
||||
* sub_node3->get_effective_namespace(); // -> "/my_ns/foo"
|
||||
* node->get_effective_namespace(); // -> "/my_ns"
|
||||
*
|
||||
* \sa get_namespace()
|
||||
* \sa get_sub_namespace()
|
||||
@@ -1290,6 +1163,19 @@ public:
|
||||
const rclcpp::NodeOptions &
|
||||
get_node_options() const;
|
||||
|
||||
/// Manually assert that this Node is alive (for RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE).
|
||||
/**
|
||||
* If the rmw Liveliness policy is set to RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE, the creator
|
||||
* of this node may manually call `assert_liveliness` at some point in time to signal to the rest
|
||||
* of the system that this Node is still alive.
|
||||
*
|
||||
* \return `true` if the liveliness was asserted successfully, otherwise `false`
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
bool
|
||||
assert_liveliness() const;
|
||||
|
||||
protected:
|
||||
/// Construct a sub-node, which will extend the namespace of all entities created with it.
|
||||
/**
|
||||
@@ -1306,6 +1192,10 @@ protected:
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(Node)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
group_in_node(callback_group::CallbackGroup::SharedPtr group);
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_;
|
||||
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_;
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <rmw/rmw.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
@@ -34,18 +33,15 @@
|
||||
#include "rcl/publisher.h"
|
||||
#include "rcl/subscription.h"
|
||||
|
||||
#include "rcl_interfaces/msg/intra_process_message.hpp"
|
||||
|
||||
#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/detail/resolve_enable_topic_statistics.hpp"
|
||||
#include "rclcpp/intra_process_manager.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/timer.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
@@ -82,20 +78,48 @@ Node::create_publisher(
|
||||
options);
|
||||
}
|
||||
|
||||
template<typename MessageT, typename AllocatorT, typename PublisherT>
|
||||
std::shared_ptr<PublisherT>
|
||||
Node::create_publisher(
|
||||
const std::string & topic_name,
|
||||
size_t qos_history_depth,
|
||||
std::shared_ptr<AllocatorT> allocator)
|
||||
{
|
||||
PublisherOptionsWithAllocator<AllocatorT> pub_options;
|
||||
pub_options.allocator = allocator;
|
||||
return this->create_publisher<MessageT, AllocatorT, PublisherT>(
|
||||
topic_name, rclcpp::QoS(rclcpp::KeepLast(qos_history_depth)), pub_options);
|
||||
}
|
||||
|
||||
template<typename MessageT, typename AllocatorT, typename PublisherT>
|
||||
std::shared_ptr<PublisherT>
|
||||
Node::create_publisher(
|
||||
const std::string & topic_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
std::shared_ptr<AllocatorT> allocator)
|
||||
{
|
||||
rclcpp::QoS qos(rclcpp::QoSInitialization::from_rmw(qos_profile));
|
||||
qos.get_rmw_qos_profile() = qos_profile;
|
||||
|
||||
PublisherOptionsWithAllocator<AllocatorT> pub_options;
|
||||
pub_options.allocator = allocator;
|
||||
return this->create_publisher<MessageT, AllocatorT, PublisherT>(topic_name, qos, pub_options);
|
||||
}
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename AllocatorT,
|
||||
typename CallbackMessageT,
|
||||
typename SubscriptionT,
|
||||
typename MessageMemoryStrategyT>
|
||||
typename SubscriptionT>
|
||||
std::shared_ptr<SubscriptionT>
|
||||
Node::create_subscription(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos,
|
||||
CallbackT && callback,
|
||||
const SubscriptionOptionsWithAllocator<AllocatorT> & options,
|
||||
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat)
|
||||
typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, AllocatorT>::SharedPtr
|
||||
msg_mem_strat)
|
||||
{
|
||||
return rclcpp::create_subscription<MessageT>(
|
||||
*this,
|
||||
@@ -106,19 +130,78 @@ Node::create_subscription(
|
||||
msg_mem_strat);
|
||||
}
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename Alloc,
|
||||
typename SubscriptionT>
|
||||
std::shared_ptr<SubscriptionT>
|
||||
Node::create_subscription(
|
||||
const std::string & topic_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
bool ignore_local_publications,
|
||||
typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, Alloc>::SharedPtr
|
||||
msg_mem_strat,
|
||||
std::shared_ptr<Alloc> allocator)
|
||||
{
|
||||
rclcpp::QoS qos(rclcpp::QoSInitialization::from_rmw(qos_profile));
|
||||
qos.get_rmw_qos_profile() = qos_profile;
|
||||
|
||||
SubscriptionOptionsWithAllocator<Alloc> sub_options;
|
||||
sub_options.callback_group = group;
|
||||
sub_options.ignore_local_publications = ignore_local_publications;
|
||||
sub_options.allocator = allocator;
|
||||
|
||||
return this->create_subscription<MessageT, CallbackT, Alloc, SubscriptionT>(
|
||||
topic_name, qos, std::forward<CallbackT>(callback), sub_options, msg_mem_strat);
|
||||
}
|
||||
|
||||
template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename Alloc,
|
||||
typename SubscriptionT>
|
||||
std::shared_ptr<SubscriptionT>
|
||||
Node::create_subscription(
|
||||
const std::string & topic_name,
|
||||
CallbackT && callback,
|
||||
size_t qos_history_depth,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
bool ignore_local_publications,
|
||||
typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
|
||||
typename rclcpp::subscription_traits::has_message_type<CallbackT>::type, Alloc>::SharedPtr
|
||||
msg_mem_strat,
|
||||
std::shared_ptr<Alloc> allocator)
|
||||
{
|
||||
SubscriptionOptionsWithAllocator<Alloc> sub_options;
|
||||
sub_options.callback_group = group;
|
||||
sub_options.ignore_local_publications = ignore_local_publications;
|
||||
sub_options.allocator = allocator;
|
||||
|
||||
return this->create_subscription<MessageT, CallbackT, Alloc, SubscriptionT>(
|
||||
topic_name,
|
||||
rclcpp::QoS(rclcpp::KeepLast(qos_history_depth)),
|
||||
std::forward<CallbackT>(callback),
|
||||
sub_options,
|
||||
msg_mem_strat);
|
||||
}
|
||||
|
||||
template<typename DurationRepT, typename DurationT, typename CallbackT>
|
||||
typename rclcpp::WallTimer<CallbackT>::SharedPtr
|
||||
Node::create_wall_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return rclcpp::create_wall_timer(
|
||||
period,
|
||||
auto timer = rclcpp::WallTimer<CallbackT>::make_shared(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(period),
|
||||
std::move(callback),
|
||||
group,
|
||||
this->node_base_.get(),
|
||||
this->node_timers_.get());
|
||||
this->node_base_->get_context());
|
||||
node_timers_->add_timer(timer, group);
|
||||
return timer;
|
||||
}
|
||||
|
||||
template<typename ServiceT>
|
||||
@@ -126,15 +209,23 @@ typename Client<ServiceT>::SharedPtr
|
||||
Node::create_client(
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return rclcpp::create_client<ServiceT>(
|
||||
node_base_,
|
||||
rcl_client_options_t options = rcl_client_get_default_options();
|
||||
options.qos = qos_profile;
|
||||
|
||||
using rclcpp::Client;
|
||||
using rclcpp::ClientBase;
|
||||
|
||||
auto cli = Client<ServiceT>::make_shared(
|
||||
node_base_.get(),
|
||||
node_graph_,
|
||||
node_services_,
|
||||
extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
|
||||
qos_profile,
|
||||
group);
|
||||
options);
|
||||
|
||||
auto cli_base_ptr = std::dynamic_pointer_cast<ClientBase>(cli);
|
||||
node_services_->add_client(cli_base_ptr, group);
|
||||
return cli;
|
||||
}
|
||||
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
@@ -143,7 +234,7 @@ Node::create_service(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return rclcpp::create_service<ServiceT, CallbackT>(
|
||||
node_base_,
|
||||
@@ -154,78 +245,17 @@ 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(
|
||||
const std::string & name,
|
||||
const ParameterT & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
|
||||
bool ignore_override)
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor)
|
||||
{
|
||||
try {
|
||||
return this->declare_parameter(
|
||||
name,
|
||||
rclcpp::ParameterValue(default_value),
|
||||
parameter_descriptor,
|
||||
ignore_override
|
||||
).get<ParameterT>();
|
||||
} catch (const ParameterTypeException & ex) {
|
||||
throw exceptions::InvalidParameterTypeException(name, ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
rclcpp::ParameterValue(default_value),
|
||||
parameter_descriptor
|
||||
).get<ParameterT>();
|
||||
}
|
||||
|
||||
@@ -233,19 +263,14 @@ template<typename ParameterT>
|
||||
std::vector<ParameterT>
|
||||
Node::declare_parameters(
|
||||
const std::string & namespace_,
|
||||
const std::map<std::string, ParameterT> & parameters,
|
||||
bool ignore_overrides)
|
||||
const std::map<std::string, ParameterT> & parameters)
|
||||
{
|
||||
std::vector<ParameterT> result;
|
||||
std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
|
||||
std::transform(
|
||||
parameters.begin(), parameters.end(), std::back_inserter(result),
|
||||
[this, &normalized_namespace, ignore_overrides](auto element) {
|
||||
return this->declare_parameter(
|
||||
normalized_namespace + element.first,
|
||||
element.second,
|
||||
rcl_interfaces::msg::ParameterDescriptor(),
|
||||
ignore_overrides);
|
||||
[this, &normalized_namespace](auto element) {
|
||||
return this->declare_parameter(normalized_namespace + element.first, element.second);
|
||||
}
|
||||
);
|
||||
return result;
|
||||
@@ -258,26 +283,62 @@ Node::declare_parameters(
|
||||
const std::map<
|
||||
std::string,
|
||||
std::pair<ParameterT, rcl_interfaces::msg::ParameterDescriptor>
|
||||
> & parameters,
|
||||
bool ignore_overrides)
|
||||
> & parameters)
|
||||
{
|
||||
std::vector<ParameterT> result;
|
||||
std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
|
||||
std::transform(
|
||||
parameters.begin(), parameters.end(), std::back_inserter(result),
|
||||
[this, &normalized_namespace, ignore_overrides](auto element) {
|
||||
[this, &normalized_namespace](auto element) {
|
||||
return static_cast<ParameterT>(
|
||||
this->declare_parameter(
|
||||
normalized_namespace + element.first,
|
||||
element.second.first,
|
||||
element.second.second,
|
||||
ignore_overrides)
|
||||
element.second.second)
|
||||
);
|
||||
}
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
void
|
||||
Node::set_parameter_if_not_set(
|
||||
const std::string & name,
|
||||
const ParameterT & value)
|
||||
{
|
||||
if (
|
||||
!this->has_parameter(name) ||
|
||||
this->describe_parameter(name).type == PARAMETER_NOT_SET)
|
||||
{
|
||||
this->set_parameter(rclcpp::Parameter(name, value));
|
||||
}
|
||||
}
|
||||
|
||||
// this is a partially-specialized version of set_parameter_if_not_set above,
|
||||
// where our concrete type for ParameterT is std::map, but the to-be-determined
|
||||
// type is the value in the map.
|
||||
template<typename ParameterT>
|
||||
void
|
||||
Node::set_parameters_if_not_set(
|
||||
const std::string & name,
|
||||
const std::map<std::string, ParameterT> & values)
|
||||
{
|
||||
std::vector<rclcpp::Parameter> params;
|
||||
|
||||
for (const auto & val : values) {
|
||||
std::string parameter_name = name + "." + val.first;
|
||||
if (
|
||||
!this->has_parameter(parameter_name) ||
|
||||
this->describe_parameter(parameter_name).type == PARAMETER_NOT_SET)
|
||||
{
|
||||
params.push_back(rclcpp::Parameter(parameter_name, val.second));
|
||||
}
|
||||
}
|
||||
|
||||
this->set_parameters(params);
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
bool
|
||||
Node::get_parameter(const std::string & name, ParameterT & parameter) const
|
||||
@@ -330,6 +391,31 @@ Node::get_parameters(
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
void
|
||||
Node::get_parameter_or_set(
|
||||
const std::string & name,
|
||||
ParameterT & value,
|
||||
const ParameterT & alternative_value)
|
||||
{
|
||||
std::string sub_name = extend_name_with_sub_namespace(name, this->get_sub_namespace());
|
||||
|
||||
bool got_parameter = get_parameter(sub_name, value);
|
||||
if (!got_parameter) {
|
||||
this->set_parameters({
|
||||
rclcpp::Parameter(sub_name, alternative_value),
|
||||
});
|
||||
value = alternative_value;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename CallbackT>
|
||||
void
|
||||
Node::register_param_change_callback(CallbackT && callback)
|
||||
{
|
||||
this->node_parameters_->register_param_change_callback(std::forward<CallbackT>(callback));
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_IMPL_HPP_
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
|
||||
/// This header provides the get_node_base_interface() template function.
|
||||
/**
|
||||
* This function is useful for getting the NodeBaseInterface pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get the NodeBaseInterface pointer so long as the class
|
||||
* has a method called ``get_node_base_interface()`` which returns
|
||||
* either a pointer (const or not) to a NodeBaseInterface or a
|
||||
* std::shared_ptr to a NodeBaseInterface.
|
||||
*/
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This is a meta-programming checker for if a given Node-like object has a
|
||||
// getter called get_node_base_interface() which returns various types,
|
||||
// e.g. const pointer or a shared pointer.
|
||||
template<typename NodeType, typename ReturnType>
|
||||
struct has_get_node_base_interface
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static constexpr
|
||||
auto
|
||||
check(T *)->typename std::is_same<
|
||||
decltype(std::declval<T>().get_node_base_interface()),
|
||||
ReturnType
|
||||
>::type;
|
||||
|
||||
template<typename>
|
||||
static constexpr
|
||||
std::false_type
|
||||
check(...);
|
||||
|
||||
public:
|
||||
using type = decltype(check<NodeType>(nullptr));
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
// If NodeType is a pointer to NodeBaseInterface already (just normal function overload).
|
||||
inline
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(rclcpp::node_interfaces::NodeBaseInterface * pointer)
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_base_interface() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_base_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface>
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_base_interface().get();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_base_interface() which returns a pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_base_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_base_interface();
|
||||
}
|
||||
|
||||
// Forward shared_ptr's to const node pointer signatures.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_same<
|
||||
NodeType,
|
||||
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_shared_pointer)
|
||||
{
|
||||
return get_node_base_interface_from_pointer(node_shared_pointer->get());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the NodeBaseInterface as a pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface(NodeType node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
return detail::get_node_base_interface_from_pointer(node_pointer);
|
||||
}
|
||||
|
||||
/// Get the NodeBaseInterface as a pointer from a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<
|
||||
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface(NodeType && node_reference)
|
||||
{
|
||||
// Forward references to detail implmentation as a pointer.
|
||||
return detail::get_node_base_interface_from_pointer(&node_reference);
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
@@ -0,0 +1,149 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
|
||||
/// This header provides the get_node_timers_interface() template function.
|
||||
/**
|
||||
* This function is useful for getting the NodeTimersInterface pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get the NodeTimersInterface pointer so long as the class
|
||||
* has a method called ``get_node_timers_interface()`` which returns
|
||||
* either a pointer (const or not) to a NodeTimersInterface or a
|
||||
* std::shared_ptr to a NodeTimersInterface.
|
||||
*/
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This is a meta-programming checker for if a given Node-like object has a
|
||||
// getter called get_node_timers_interface() which returns various types,
|
||||
// e.g. const pointer or a shared pointer.
|
||||
template<typename NodeType, typename ReturnType>
|
||||
struct has_get_node_timers_interface
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static constexpr
|
||||
auto
|
||||
check(T *)->typename std::is_same<
|
||||
decltype(std::declval<T>().get_node_timers_interface()),
|
||||
ReturnType
|
||||
>::type;
|
||||
|
||||
template<typename>
|
||||
static constexpr
|
||||
std::false_type
|
||||
check(...);
|
||||
|
||||
public:
|
||||
using type = decltype(check<NodeType>(nullptr));
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
// If NodeType is a pointer to NodeTimersInterface already (just normal function overload).
|
||||
inline
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(rclcpp::node_interfaces::NodeTimersInterface * pointer)
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_timers_interface() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_timers_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTimersInterface>
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_timers_interface().get();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_timers_interface() which returns a pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_timers_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_timers_interface();
|
||||
}
|
||||
|
||||
// Forward shared_ptr's to const node pointer signatures.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_same<
|
||||
NodeType,
|
||||
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_shared_pointer)
|
||||
{
|
||||
return get_node_timers_interface_from_pointer(node_shared_pointer->get());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the NodeTimersInterface as a pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface(NodeType node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
return detail::get_node_timers_interface_from_pointer(node_pointer);
|
||||
}
|
||||
|
||||
/// Get the NodeTimersInterface as a pointer from a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<
|
||||
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface(NodeType && node_reference)
|
||||
{
|
||||
// Forward references to detail implmentation as a pointer.
|
||||
return detail::get_node_timers_interface_from_pointer(&node_reference);
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
@@ -0,0 +1,149 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_TOPICS_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_NODE_TOPICS_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
|
||||
/// This header provides the get_node_topics_interface() template function.
|
||||
/**
|
||||
* This function is useful for getting the NodeTopicsInterface pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get the NodeTopicsInterface pointer so long as the class
|
||||
* has a method called ``get_node_topics_interface()`` which returns
|
||||
* either a pointer (const or not) to a NodeTopicsInterface or a
|
||||
* std::shared_ptr to a NodeTopicsInterface.
|
||||
*/
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This is a meta-programming checker for if a given Node-like object has a
|
||||
// getter called get_node_topics_interface() which returns various types,
|
||||
// e.g. const pointer or a shared pointer.
|
||||
template<typename NodeType, typename ReturnType>
|
||||
struct has_get_node_topics_interface
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static constexpr
|
||||
auto
|
||||
check(T *)->typename std::is_same<
|
||||
decltype(std::declval<T>().get_node_topics_interface()),
|
||||
ReturnType
|
||||
>::type;
|
||||
|
||||
template<typename>
|
||||
static constexpr
|
||||
std::false_type
|
||||
check(...);
|
||||
|
||||
public:
|
||||
using type = decltype(check<NodeType>(nullptr));
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
// If NodeType is a pointer to NodeTopicsInterface already (just normal function overload).
|
||||
inline
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface_from_pointer(rclcpp::node_interfaces::NodeTopicsInterface * pointer)
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_topics_interface() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_topics_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_topics_interface().get();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_topics_interface() which returns a pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_topics_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_topics_interface();
|
||||
}
|
||||
|
||||
// Forward shared_ptr's to const node pointer signatures.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_same<
|
||||
NodeType,
|
||||
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface_from_pointer(NodeType node_shared_pointer)
|
||||
{
|
||||
return get_node_topics_interface_from_pointer(node_shared_pointer->get());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the NodeTopicsInterface as a pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface(NodeType node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
return detail::get_node_topics_interface_from_pointer(node_pointer);
|
||||
}
|
||||
|
||||
/// Get the NodeTopicsInterface as a pointer from a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<
|
||||
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface(NodeType && node_reference)
|
||||
{
|
||||
// Forward references to detail implmentation as a pointer.
|
||||
return detail::get_node_topics_interface_from_pointer(&node_reference);
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_TOPICS_INTERFACE_HPP_
|
||||
@@ -16,16 +16,14 @@
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_BASE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/node.h"
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/context.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_options.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
@@ -33,131 +31,119 @@ namespace rclcpp
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void global_for_each_callback_group(
|
||||
NodeBaseInterface * node_base_interface,
|
||||
const NodeBaseInterface::CallbackGroupFunction & func);
|
||||
|
||||
// Class to hold the global map of mutexes
|
||||
class map_of_mutexes final
|
||||
{
|
||||
public:
|
||||
// Methods need to be protected by internal mutex
|
||||
void create_mutex_of_nodebase(const NodeBaseInterface * nodebase);
|
||||
std::shared_ptr<std::mutex>
|
||||
get_mutex_of_nodebase(const NodeBaseInterface * nodebase);
|
||||
void delete_mutex_of_nodebase(const NodeBaseInterface * nodebase);
|
||||
|
||||
private:
|
||||
std::unordered_map<const NodeBaseInterface *, std::shared_ptr<std::mutex>> data_;
|
||||
std::mutex internal_mutex_;
|
||||
};
|
||||
|
||||
/// Implementation of the NodeBase part of the Node API.
|
||||
class NodeBase : public NodeBaseInterface
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeBase)
|
||||
|
||||
static map_of_mutexes map_object;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
NodeBase(
|
||||
const std::string & node_name,
|
||||
const std::string & namespace_,
|
||||
rclcpp::Context::SharedPtr context,
|
||||
const rcl_node_options_t & rcl_node_options,
|
||||
bool use_intra_process_default,
|
||||
bool enable_topic_statistics_default);
|
||||
bool use_intra_process_default);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
~NodeBase();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const char *
|
||||
get_name() const override;
|
||||
get_name() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const char *
|
||||
get_namespace() const override;
|
||||
get_namespace() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const char *
|
||||
get_fully_qualified_name() const override;
|
||||
get_fully_qualified_name() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Context::SharedPtr
|
||||
get_context() override;
|
||||
get_context();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rcl_node_t *
|
||||
get_rcl_node_handle() override;
|
||||
get_rcl_node_handle();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const rcl_node_t *
|
||||
get_rcl_node_handle() const override;
|
||||
get_rcl_node_handle() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::shared_ptr<rcl_node_t>
|
||||
get_shared_rcl_node_handle() override;
|
||||
get_shared_rcl_node_handle();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::shared_ptr<const rcl_node_t>
|
||||
get_shared_rcl_node_handle() const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
create_callback_group(
|
||||
rclcpp::CallbackGroupType group_type,
|
||||
bool automatically_add_to_executor_with_node = true) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
get_default_callback_group() override;
|
||||
get_shared_rcl_node_handle() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
bool
|
||||
callback_group_in_node(rclcpp::CallbackGroup::SharedPtr group) override;
|
||||
assert_liveliness() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
|
||||
get_callback_groups() const override;
|
||||
virtual
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
create_callback_group(rclcpp::callback_group::CallbackGroupType group_type);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_default_callback_group();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
bool
|
||||
callback_group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
|
||||
get_callback_groups() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::atomic_bool &
|
||||
get_associated_with_executor_atomic() override;
|
||||
get_associated_with_executor_atomic();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rcl_guard_condition_t *
|
||||
get_notify_guard_condition() override;
|
||||
get_notify_guard_condition();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::unique_lock<std::recursive_mutex>
|
||||
acquire_notify_guard_condition_lock() const override;
|
||||
acquire_notify_guard_condition_lock() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
bool
|
||||
get_use_intra_process_default() const override;
|
||||
|
||||
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;
|
||||
get_use_intra_process_default() const;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeBase)
|
||||
|
||||
rclcpp::Context::SharedPtr context_;
|
||||
bool use_intra_process_default_;
|
||||
bool enable_topic_statistics_default_;
|
||||
|
||||
std::shared_ptr<rcl_node_t> node_handle_;
|
||||
|
||||
rclcpp::CallbackGroup::SharedPtr default_callback_group_;
|
||||
std::vector<rclcpp::CallbackGroup::WeakPtr> callback_groups_;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr default_callback_group_;
|
||||
std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> callback_groups_;
|
||||
|
||||
std::atomic_bool associated_with_executor_;
|
||||
|
||||
|
||||
@@ -38,8 +38,6 @@ class NodeBaseInterface
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeBaseInterface)
|
||||
|
||||
using CallbackGroupFunction = std::function<void (rclcpp::CallbackGroup::SharedPtr)>;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
~NodeBaseInterface() = default;
|
||||
@@ -104,30 +102,34 @@ public:
|
||||
std::shared_ptr<const rcl_node_t>
|
||||
get_shared_rcl_node_handle() const = 0;
|
||||
|
||||
/// Manually assert that this Node is alive (for RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE).
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
bool
|
||||
assert_liveliness() const = 0;
|
||||
|
||||
/// Create and return a callback group.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
create_callback_group(
|
||||
rclcpp::CallbackGroupType group_type,
|
||||
bool automatically_add_to_executor_with_node = true) = 0;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
create_callback_group(rclcpp::callback_group::CallbackGroupType group_type) = 0;
|
||||
|
||||
/// Return the default callback group.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_default_callback_group() = 0;
|
||||
|
||||
/// Return true if the given callback group is associated with this node.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
bool
|
||||
callback_group_in_node(rclcpp::CallbackGroup::SharedPtr group) = 0;
|
||||
callback_group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
|
||||
|
||||
/// Return list of callback groups associated with this node.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
|
||||
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
|
||||
get_callback_groups() const = 0;
|
||||
|
||||
/// Return the atomic bool which is used to ensure only one executor is used.
|
||||
@@ -159,19 +161,6 @@ public:
|
||||
virtual
|
||||
bool
|
||||
get_use_intra_process_default() const = 0;
|
||||
|
||||
/// Return the default preference for enabling topic statistics collection.
|
||||
RCLCPP_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
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_CLOCK_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_CLOCK_HPP_
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_clock_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_services_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
#include "rclcpp/time_source.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
@@ -50,13 +50,9 @@ public:
|
||||
|
||||
/// Get a clock which will be kept up to date by the node.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Clock::SharedPtr
|
||||
get_clock() override;
|
||||
|
||||
/// Get a clock which will be kept up to date by the node.
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::Clock::ConstSharedPtr
|
||||
get_clock() const override;
|
||||
get_clock();
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeClock)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_CLOCK_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_CLOCK_INTERFACE_HPP_
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
@@ -39,12 +40,6 @@ public:
|
||||
virtual
|
||||
rclcpp::Clock::SharedPtr
|
||||
get_clock() = 0;
|
||||
|
||||
/// Get a const ROS clock which will be kept up to date by the node.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Clock::ConstSharedPtr
|
||||
get_clock() const = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rmw/topic_endpoint_info_array.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
@@ -57,72 +56,66 @@ public:
|
||||
~NodeGraph();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_topic_names_and_types(bool no_demangle = false) const override;
|
||||
get_topic_names_and_types(bool no_demangle = false) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_service_names_and_types() const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_service_names_and_types_by_node(
|
||||
const std::string & node_name,
|
||||
const std::string & namespace_) const override;
|
||||
get_service_names_and_types() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::vector<std::string>
|
||||
get_node_names() const override;
|
||||
get_node_names() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::vector<std::pair<std::string, std::string>>
|
||||
get_node_names_and_namespaces() const override;
|
||||
get_node_names_and_namespaces() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
size_t
|
||||
count_publishers(const std::string & topic_name) const override;
|
||||
count_publishers(const std::string & topic_name) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
size_t
|
||||
count_subscribers(const std::string & topic_name) const override;
|
||||
count_subscribers(const std::string & topic_name) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const rcl_guard_condition_t *
|
||||
get_graph_guard_condition() const override;
|
||||
get_graph_guard_condition() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
notify_graph_change() override;
|
||||
notify_graph_change();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
notify_shutdown() override;
|
||||
notify_shutdown();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Event::SharedPtr
|
||||
get_graph_event() override;
|
||||
get_graph_event();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
wait_for_graph_change(
|
||||
rclcpp::Event::SharedPtr event,
|
||||
std::chrono::nanoseconds timeout) override;
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
size_t
|
||||
count_graph_users() const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::TopicEndpointInfo>
|
||||
get_publishers_info_by_topic(
|
||||
const std::string & topic_name,
|
||||
bool no_mangle = false) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::TopicEndpointInfo>
|
||||
get_subscriptions_info_by_topic(
|
||||
const std::string & topic_name,
|
||||
bool no_mangle = false) const override;
|
||||
count_graph_users();
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeGraph)
|
||||
|
||||
@@ -15,120 +15,20 @@
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_GRAPH_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_GRAPH_INTERFACE_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/graph.h"
|
||||
#include "rcl/guard_condition.h"
|
||||
|
||||
#include "rclcpp/event.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
enum class EndpointType
|
||||
{
|
||||
Invalid = RMW_ENDPOINT_INVALID,
|
||||
Publisher = RMW_ENDPOINT_PUBLISHER,
|
||||
Subscription = RMW_ENDPOINT_SUBSCRIPTION
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct that contains topic endpoint information like the associated node name, node namespace,
|
||||
* topic type, endpoint type, endpoint GID, and its QoS.
|
||||
*/
|
||||
class TopicEndpointInfo
|
||||
{
|
||||
public:
|
||||
/// Construct a TopicEndpointInfo from a rcl_topic_endpoint_info_t.
|
||||
RCLCPP_PUBLIC
|
||||
explicit TopicEndpointInfo(const rcl_topic_endpoint_info_t & info)
|
||||
: node_name_(info.node_name),
|
||||
node_namespace_(info.node_namespace),
|
||||
topic_type_(info.topic_type),
|
||||
endpoint_type_(static_cast<rclcpp::EndpointType>(info.endpoint_type)),
|
||||
qos_profile_({info.qos_profile.history, info.qos_profile.depth}, info.qos_profile)
|
||||
{
|
||||
std::copy(info.endpoint_gid, info.endpoint_gid + RMW_GID_STORAGE_SIZE, endpoint_gid_.begin());
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the node name.
|
||||
RCLCPP_PUBLIC
|
||||
std::string &
|
||||
node_name();
|
||||
|
||||
/// Get a const reference to the node name.
|
||||
RCLCPP_PUBLIC
|
||||
const std::string &
|
||||
node_name() const;
|
||||
|
||||
/// Get a mutable reference to the node namespace.
|
||||
RCLCPP_PUBLIC
|
||||
std::string &
|
||||
node_namespace();
|
||||
|
||||
/// Get a const reference to the node namespace.
|
||||
RCLCPP_PUBLIC
|
||||
const std::string &
|
||||
node_namespace() const;
|
||||
|
||||
/// Get a mutable reference to the topic type string.
|
||||
RCLCPP_PUBLIC
|
||||
std::string &
|
||||
topic_type();
|
||||
|
||||
/// Get a const reference to the topic type string.
|
||||
RCLCPP_PUBLIC
|
||||
const std::string &
|
||||
topic_type() const;
|
||||
|
||||
/// Get a mutable reference to the topic endpoint type.
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::EndpointType &
|
||||
endpoint_type();
|
||||
|
||||
/// Get a const reference to the topic endpoint type.
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::EndpointType &
|
||||
endpoint_type() const;
|
||||
|
||||
/// Get a mutable reference to the GID of the topic endpoint.
|
||||
RCLCPP_PUBLIC
|
||||
std::array<uint8_t, RMW_GID_STORAGE_SIZE> &
|
||||
endpoint_gid();
|
||||
|
||||
/// Get a const reference to the GID of the topic endpoint.
|
||||
RCLCPP_PUBLIC
|
||||
const std::array<uint8_t, RMW_GID_STORAGE_SIZE> &
|
||||
endpoint_gid() const;
|
||||
|
||||
/// Get a mutable reference to the QoS profile of the topic endpoint.
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::QoS &
|
||||
qos_profile();
|
||||
|
||||
/// Get a const reference to the QoS profile of the topic endpoint.
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::QoS &
|
||||
qos_profile() const;
|
||||
|
||||
private:
|
||||
std::string node_name_;
|
||||
std::string node_namespace_;
|
||||
std::string topic_type_;
|
||||
rclcpp::EndpointType endpoint_type_;
|
||||
std::array<uint8_t, RMW_GID_STORAGE_SIZE> endpoint_gid_;
|
||||
rclcpp::QoS qos_profile_;
|
||||
};
|
||||
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
@@ -146,7 +46,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,59 +59,31 @@ 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
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_service_names_and_types() const = 0;
|
||||
|
||||
/// 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
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_service_names_and_types_by_node(
|
||||
const std::string & node_name,
|
||||
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,27 +149,7 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
size_t
|
||||
count_graph_users() const = 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
|
||||
virtual
|
||||
std::vector<rclcpp::TopicEndpointInfo>
|
||||
get_publishers_info_by_topic(const std::string & topic_name, bool no_mangle = false) const = 0;
|
||||
|
||||
/// 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
|
||||
virtual
|
||||
std::vector<rclcpp::TopicEndpointInfo>
|
||||
get_subscriptions_info_by_topic(const std::string & topic_name, bool no_mangle = false) const = 0;
|
||||
count_graph_users() = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -42,12 +42,14 @@ public:
|
||||
~NodeLogging();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Logger
|
||||
get_logger() const override;
|
||||
get_logger() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const char *
|
||||
get_logger_name() const override;
|
||||
get_logger_name() const;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeLogging)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
|
||||
@@ -17,12 +17,9 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcutils/macros.h"
|
||||
|
||||
#include "rcl_interfaces/msg/list_parameters_result.hpp"
|
||||
#include "rcl_interfaces/msg/parameter_descriptor.hpp"
|
||||
#include "rcl_interfaces/msg/parameter_event.hpp"
|
||||
@@ -30,7 +27,6 @@
|
||||
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_services_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
@@ -54,30 +50,6 @@ struct ParameterInfo
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
};
|
||||
|
||||
// Internal RAII-style guard for mutation recursion
|
||||
class ParameterMutationRecursionGuard
|
||||
{
|
||||
public:
|
||||
explicit ParameterMutationRecursionGuard(bool & allow_mod)
|
||||
: allow_modification_(allow_mod)
|
||||
{
|
||||
if (!allow_modification_) {
|
||||
throw rclcpp::exceptions::ParameterModifiedInCallbackException(
|
||||
"cannot set or declare a parameter, or change the callback from within set callback");
|
||||
}
|
||||
|
||||
allow_modification_ = false;
|
||||
}
|
||||
|
||||
~ParameterMutationRecursionGuard()
|
||||
{
|
||||
allow_modification_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool & allow_modification_;
|
||||
};
|
||||
|
||||
/// Implementation of the NodeParameters part of the Node API.
|
||||
class NodeParameters : public NodeParametersInterface
|
||||
{
|
||||
@@ -103,42 +75,12 @@ 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) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
@@ -191,34 +133,25 @@ public:
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
OnSetParametersCallbackHandle::SharedPtr
|
||||
add_on_set_parameters_callback(OnParametersSetCallbackType callback) override;
|
||||
OnParametersSetCallbackType
|
||||
set_on_parameters_set_callback(OnParametersSetCallbackType callback) override;
|
||||
|
||||
[[deprecated("use set_on_parameters_set_callback() instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler) override;
|
||||
register_param_change_callback(OnParametersSetCallbackType callback) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::map<std::string, rclcpp::ParameterValue> &
|
||||
get_parameter_overrides() const override;
|
||||
|
||||
using CallbacksContainerType = std::list<OnSetParametersCallbackHandle::WeakPtr>;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeParameters)
|
||||
|
||||
mutable std::recursive_mutex mutex_;
|
||||
|
||||
// There are times when we don't want to allow modifications to parameters
|
||||
// (particularly when a set_parameter callback tries to call set_parameter,
|
||||
// declare_parameter, etc). In those cases, this will be set to false.
|
||||
bool parameter_modification_enabled_{true};
|
||||
mutable std::mutex mutex_;
|
||||
|
||||
OnParametersSetCallbackType on_parameters_set_callback_ = nullptr;
|
||||
|
||||
CallbacksContainerType on_parameters_set_callback_container_;
|
||||
|
||||
std::map<std::string, ParameterInfo> parameters_;
|
||||
|
||||
std::map<std::string, rclcpp::ParameterValue> parameter_overrides_;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_INTERFACE_HPP_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -33,29 +32,6 @@ namespace rclcpp
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
struct OnSetParametersCallbackHandle
|
||||
{
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(OnSetParametersCallbackHandle)
|
||||
|
||||
using OnParametersSetCallbackType =
|
||||
std::function<
|
||||
rcl_interfaces::msg::SetParametersResult(
|
||||
const std::vector<rclcpp::Parameter> &)>;
|
||||
|
||||
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 +42,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,24 +51,9 @@ 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) = 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 rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor(),
|
||||
bool ignore_override = false) = 0;
|
||||
rcl_interfaces::msg::ParameterDescriptor()) = 0;
|
||||
|
||||
/// Undeclare a parameter.
|
||||
/**
|
||||
@@ -130,7 +82,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
|
||||
*/
|
||||
@@ -205,25 +157,28 @@ public:
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const = 0;
|
||||
|
||||
using OnParametersSetCallbackType = OnSetParametersCallbackHandle::OnParametersSetCallbackType;
|
||||
using OnParametersSetCallbackType =
|
||||
std::function<
|
||||
rcl_interfaces::msg::SetParametersResult(const std::vector<rclcpp::Parameter> &)
|
||||
>;
|
||||
|
||||
/// Add a callback for when parameters are being set.
|
||||
using ParametersCallbackFunction [[deprecated("use OnParametersSetCallbackType instead")]] =
|
||||
OnParametersSetCallbackType;
|
||||
|
||||
/// Register a callback for when parameters are being set, return an existing one.
|
||||
/**
|
||||
* \sa rclcpp::Node::add_on_set_parameters_callback
|
||||
* \sa rclcpp::Node::set_on_parameters_set_callback
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
OnSetParametersCallbackHandle::SharedPtr
|
||||
add_on_set_parameters_callback(OnParametersSetCallbackType callback) = 0;
|
||||
OnParametersSetCallbackType
|
||||
set_on_parameters_set_callback(OnParametersSetCallbackType callback) = 0;
|
||||
|
||||
/// Remove a callback registered with `add_on_set_parameters_callback`.
|
||||
/**
|
||||
* \sa rclcpp::Node::remove_on_set_parameters_callback
|
||||
*/
|
||||
[[deprecated("use set_on_parameters_set_callback() instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler) = 0;
|
||||
register_param_change_callback(OnParametersSetCallbackType callback) = 0;
|
||||
|
||||
/// Return the initial parameter values used by the NodeParameters to override default values.
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
@@ -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"
|
||||
@@ -44,20 +42,18 @@ public:
|
||||
~NodeServices();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
add_client(
|
||||
rclcpp::ClientBase::SharedPtr client_base_ptr,
|
||||
rclcpp::CallbackGroup::SharedPtr group) override;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
add_service(
|
||||
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;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group);
|
||||
|
||||
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"
|
||||
@@ -43,20 +41,14 @@ public:
|
||||
void
|
||||
add_client(
|
||||
rclcpp::ClientBase::SharedPtr client_base_ptr,
|
||||
rclcpp::CallbackGroup::SharedPtr group) = 0;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
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;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -15,16 +15,14 @@
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_TIME_SOURCE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_TIME_SOURCE_HPP_
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_clock_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
|
||||
#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 +45,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
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_TIME_SOURCE_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_TIME_SOURCE_INTERFACE_HPP_
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
|
||||
@@ -42,10 +42,11 @@ public:
|
||||
|
||||
/// Add a timer to the node.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
add_timer(
|
||||
rclcpp::TimerBase::SharedPtr timer,
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) override;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group);
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeTimers)
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
void
|
||||
add_timer(
|
||||
rclcpp::TimerBase::SharedPtr timer,
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
#include "rclcpp/publisher.hpp"
|
||||
#include "rclcpp/publisher_factory.hpp"
|
||||
@@ -40,9 +39,7 @@ public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeTopicsInterface)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
NodeTopics(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
rclcpp::node_interfaces::NodeTimersInterface * node_timers);
|
||||
explicit NodeTopics(rclcpp::node_interfaces::NodeBaseInterface * node_base);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
~NodeTopics() override;
|
||||
@@ -52,44 +49,37 @@ public:
|
||||
create_publisher(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::PublisherFactory & publisher_factory,
|
||||
const rclcpp::QoS & qos) override;
|
||||
const rcl_publisher_options_t & publisher_options,
|
||||
bool use_intra_process) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_publisher(
|
||||
rclcpp::PublisherBase::SharedPtr publisher,
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) override;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::SubscriptionBase::SharedPtr
|
||||
create_subscription(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::SubscriptionFactory & subscription_factory,
|
||||
const rclcpp::QoS & qos) override;
|
||||
const rcl_subscription_options_t & subscription_options,
|
||||
bool use_intra_process) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) override;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface() const override;
|
||||
|
||||
RCLCPP_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)
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
|
||||
rclcpp::node_interfaces::NodeTimersInterface * node_timers_;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -22,10 +22,7 @@
|
||||
#include "rcl/publisher.h"
|
||||
#include "rcl/subscription.h"
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
#include "rclcpp/publisher.hpp"
|
||||
#include "rclcpp/publisher_factory.hpp"
|
||||
#include "rclcpp/subscription.hpp"
|
||||
@@ -53,14 +50,15 @@ public:
|
||||
create_publisher(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::PublisherFactory & publisher_factory,
|
||||
const rclcpp::QoS & qos) = 0;
|
||||
const rcl_publisher_options_t & publisher_options,
|
||||
bool use_intra_process) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
add_publisher(
|
||||
rclcpp::PublisherBase::SharedPtr publisher,
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
@@ -68,30 +66,20 @@ public:
|
||||
create_subscription(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::SubscriptionFactory & subscription_factory,
|
||||
const rclcpp::QoS & qos) = 0;
|
||||
const rcl_subscription_options_t & subscription_options,
|
||||
bool use_intra_process) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
add_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface() const = 0;
|
||||
|
||||
RCLCPP_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
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_WAITABLES_HPP_
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/client.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_waitables_interface.hpp"
|
||||
@@ -41,16 +42,18 @@ public:
|
||||
~NodeWaitables();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
add_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable_base_ptr,
|
||||
rclcpp::CallbackGroup::SharedPtr group) override;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
remove_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable_ptr,
|
||||
rclcpp::CallbackGroup::SharedPtr group) noexcept override;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) noexcept;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeWaitables)
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
void
|
||||
add_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable_ptr,
|
||||
rclcpp::CallbackGroup::SharedPtr group) = 0;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
|
||||
|
||||
/// \note this function should not throw because it may be called in destructors
|
||||
RCLCPP_PUBLIC
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
void
|
||||
remove_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable_ptr,
|
||||
rclcpp::CallbackGroup::SharedPtr group) noexcept = 0;
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) noexcept = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -38,17 +38,13 @@ public:
|
||||
/**
|
||||
* Default values for the node options:
|
||||
*
|
||||
* - context = rclcpp::contexts::get_global_default_context()
|
||||
* - context = rclcpp::contexts::default_context::get_global_default_context()
|
||||
* - arguments = {}
|
||||
* - parameter_overrides = {}
|
||||
* - use_global_arguments = true
|
||||
* - use_intra_process_comms = false
|
||||
* - 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
|
||||
@@ -80,9 +76,6 @@ public:
|
||||
* This data structure is created lazily, on the first call to this function.
|
||||
* Repeated calls will not regenerate it unless one of the input settings
|
||||
* changed, like arguments, use_global_arguments, or the rcl allocator.
|
||||
*
|
||||
* \return a const rcl_node_options_t structure used by the node
|
||||
* \throws exceptions::UnknownROSArgsError if there are unknown ROS arguments
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
const rcl_node_options_t *
|
||||
@@ -106,7 +99,7 @@ public:
|
||||
/// Set the arguments, return this for parameter idiom.
|
||||
/**
|
||||
* These arguments are used to extract remappings used by the node and other
|
||||
* ROS specific settings, as well as user defined non-ROS arguments.
|
||||
* settings.
|
||||
*
|
||||
* This will cause the internal rcl_node_options_t struct to be invalidated.
|
||||
*/
|
||||
@@ -159,22 +152,6 @@ public:
|
||||
NodeOptions &
|
||||
use_global_arguments(bool use_global_arguments);
|
||||
|
||||
/// Return the enable_rosout flag.
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
enable_rosout() const;
|
||||
|
||||
/// Set the enable_rosout flag, return this for parameter idiom.
|
||||
/**
|
||||
* If false this will cause the node not to use rosout logging.
|
||||
*
|
||||
* Defaults to true for now, as there are still some cases where it is
|
||||
* desirable.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
NodeOptions &
|
||||
enable_rosout(bool enable_rosout);
|
||||
|
||||
/// Return the use_intra_process_comms flag.
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
@@ -194,23 +171,6 @@ public:
|
||||
NodeOptions &
|
||||
use_intra_process_comms(bool use_intra_process_comms);
|
||||
|
||||
/// Return the enable_topic_statistics flag.
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
enable_topic_statistics() const;
|
||||
|
||||
/// Set the enable_topic_statistics flag, return this for parameter idiom.
|
||||
/**
|
||||
* If true, topic statistics collection and publication will be enabled
|
||||
* for all subscriptions.
|
||||
* This can be used to override the global topic statistics setting.
|
||||
*
|
||||
* Defaults to false.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
NodeOptions &
|
||||
enable_topic_statistics(bool enable_topic_statistics);
|
||||
|
||||
/// Return the start_parameter_services flag.
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
@@ -246,33 +206,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 +219,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 +290,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.
|
||||
@@ -379,7 +304,7 @@ private:
|
||||
// documentation in this class.
|
||||
|
||||
rclcpp::Context::SharedPtr context_ {
|
||||
rclcpp::contexts::get_global_default_context()};
|
||||
rclcpp::contexts::default_context::get_global_default_context()};
|
||||
|
||||
std::vector<std::string> arguments_ {};
|
||||
|
||||
@@ -387,26 +312,16 @@ private:
|
||||
|
||||
bool use_global_arguments_ {true};
|
||||
|
||||
bool enable_rosout_ {true};
|
||||
|
||||
bool use_intra_process_comms_ {false};
|
||||
|
||||
bool enable_topic_statistics_ {false};
|
||||
|
||||
bool start_parameter_services_ {true};
|
||||
|
||||
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};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user