Compare commits

..

50 Commits

Author SHA1 Message Date
Steven! Ragnarök
403aac9662 0.7.16 2021-05-21 07:49:17 -07:00
Jacob Perron
e8cf066d7d Fix documented example in create_publisher (#1558) (#1560)
Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2021-02-24 14:15:48 -08:00
Ivan Santiago Paunovic
c4c39a2069 Fix NodeOptions copy constructor (#1376) (#1466)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2020-12-17 15:23:02 -03:00
Steven! Ragnarök
b3ecbd5ff7 0.7.15 2020-11-24 15:48:53 -08:00
Seulbae Kim
052936980e Fix typo in action client logger name (#1414)
Backport of commit 6ef2384 from #937.

Signed-off-by: Seulbae Kim <squizz617@gmail.com>
2020-10-28 12:59:50 -03:00
Michel Hidalgo
6e133c2ad7 Fix implementation of NodeOptions::use_global_arguments() (#1176) (#1206)
`this->node_options_` might still be `nullptr` for a default initialized NodeOptions instance.
`use_global_arguments()` must return `this->use_global_arguments_`, in analogy to `NodeOptions::enable_rosout()`.

Signed-off-by: Johannes Meyer <johannes@intermodalics.eu>

Co-authored-by: Johannes Meyer <johannes@intermodalics.eu>
2020-10-05 16:04:34 -03:00
Michel Hidalgo
1f0f8f6176 [dashing backport] Fix conversion of negative durations to messages (#1188) (#1207)
* Fix conversion of negative durations to messages (#1188)

* Fix conversion from negative Duration or Time to the respective message type and throw in Duration::to_rmw_time() if the duration is negative.
rmw_time_t cannot represent negative durations.

Constructors and assignment operators can be just defaulted.

Other changes are mainly cosmetical, to make conversions between signed
and unsigned types and between 32-bit and 64-bit types more explicit.

Signed-off-by: Johannes Meyer <johannes@intermodalics.eu>

* Add -Wconversion compiler option and fix implicit conversions that might alter the value

Signed-off-by: Johannes Meyer <johannes@intermodalics.eu>

* Fix usage of fixture class in some unit tests by using gtest macro TEST_F() instead of TEST().

Signed-off-by: Johannes Meyer <johannes@intermodalics.eu>

* Add compiler option -Wno-sign-conversion to fix build with Clang on macOS

Signed-off-by: Johannes Meyer <johannes@intermodalics.eu>

* Drop tests for future API.

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>

Co-authored-by: Johannes Meyer <johannes@intermodalics.eu>
2020-10-05 16:04:00 -03:00
Michel Hidalgo
ab2484295a [dashing backport] Type conversions fixes (#901) (#1209)
* Type conversions fixes (#901)

* Fix type conversions

Signed-off-by: Monika Idzik <monika.idzik@apex.ai>

* Add static_casts

Signed-off-by: Monika Idzik <monika.idzik@apex.ai>

* Address PR comments

Signed-off-by: Monika Idzik <monika.idzik@apex.ai>

* Remove one time use variable

Signed-off-by: Monika Idzik <monika.idzik@apex.ai>

* Please cpplint

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>

Co-authored-by: Monika Idzik <monika.idzik@apex.ai>
2020-09-17 20:19:12 -03:00
Ivan Santiago Paunovic
c214ddc57b add operator!= for duration (#1236) (#1277)
Signed-off-by: Jannik Abbenseth <jannik.abbenseth@ipa.fraunhofer.de>
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

Co-authored-by: Jannik Abbenseth <ipa-jba@users.noreply.github.com>
2020-08-18 10:34:08 -03:00
Ivan Santiago Paunovic
d27ca8ee85 add operator!= for duration (#1236) (#1277)
Signed-off-by: Jannik Abbenseth <jannik.abbenseth@ipa.fraunhofer.de>
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>

Co-authored-by: Jannik Abbenseth <ipa-jba@users.noreply.github.com>
2020-08-18 10:28:23 -03:00
Steven! Ragnarök
342f225053 0.7.14 2020-07-11 00:04:56 -04:00
Alejandro Hernández Cordero
3c198de5b2 [Backport Dashing]Fixed doxygen warnings (#1163) (#1208)
Signed-off-by: ahcorde <ahcorde@gmail.com>
2020-07-10 16:54:25 -04:00
Ivan Santiago Paunovic
8906c9eb7f Check if context is valid when looping in spin_some (#1167)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2020-07-02 18:26:00 -03:00
DongheeYe
9e98aa70d3 Fix spin_until_future_complete: check spinning value (#1023)
Signed-off-by: Donghee Ye <donghee.ye@samsung.com>
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2020-07-02 18:26:00 -03:00
Alejandro Hernández Cordero
6471043a0b Added rclcpp_components Doxyfile (#1091) (#1201)
* Added rclcpp components Doxyfile

Signed-off-by: ahcorde <ahcorde@gmail.com>

* Added feedback

Signed-off-by: ahcorde <ahcorde@gmail.com>
2020-06-26 19:20:32 +02:00
tomoya
f8bba370dc [dashing] backport #1182 (#1195)
Signed-off-by: Tomoya.Fujita <Tomoya.Fujita@sony.com>
2020-06-25 13:04:38 -04:00
tomoya
d5040ae304 Fix lock-order-inversion (potential deadlock) (#1135) (#1138)
Signed-off-by: Tomoya.Fujita <Tomoya.Fujita@sony.com>
2020-06-01 11:20:33 -03:00
Steven! Ragnarök
3e5b6a47ea 0.7.13 2020-03-12 17:37:15 -04:00
Jacob Perron
8c3fbce10d Don't specify calling convention in std::_Binder template (#952) (#1015)
Fix for a build error on 32-bit Windows. Member functions use the
__thiscall convention by default which is incompatible with __cdecl.

Signed-off-by: Sean Kelly <sean@seankelly.dev>
2020-03-12 14:23:08 -07:00
Jacob Perron
fb6ab9ef70 Remove absolute path from installed CMake code (#948) (#949)
Otherwise, rclcpp_components_register_node() fails if used from a fat archive.

Related to https://github.com/ros2/ros2/issues/606.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2020-01-08 10:19:12 -08:00
Shane Loretz
7629f5b6d9 0.7.12
Signed-off-by: Shane Loretz <sloretz@openrobotics.org>
2019-12-05 14:16:28 -05:00
Ivan Santiago Paunovic
7cb2ececcb issue-919 Fixed "memory leak" in action clients (#920) (#934)
Whenever a call is made to `rclcpp_action::Client::wait_for_action_server`
a weak pointer to an Event object gets added to the graph_event_ vector
of the NodeGraph interface. This vector will be cleared on a node graph
change event, but if no such event occurs the weak pointer will be stuck
in the vector.  Furthermore, if client code issues repeated calls to
`wait_for_action_server` the vector will keep growing.

The fix moves the Event object creation right after the early return from
`wait_for_action_server` so that the Event object is not created in the
case that the server is known to be present and therefore there is no
need to wait for a node graph change event to occur.

Signed-off-by: Adrian Stere <astere@clearpath.ai>
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2019-12-05 14:09:07 -05:00
Shane Loretz
0f4fc08a93 [Dashing] backport rclcpp_components_register_node (#935)
* Cmake infrastructure for creating components (#784)

*cmake macro to create components for libraries with multiple nodes

Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>
Signed-off-by: Shane Loretz <sloretz@openrobotics.org>

* fix for multiple nodes not being recognized (#790)

Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>
Signed-off-by: Shane Loretz <sloretz@openrobotics.org>

* fix linter issue (#795)

Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>
Signed-off-by: Shane Loretz <sloretz@openrobotics.org>
2019-12-05 12:48:13 -05:00
Jacob Perron
82f6dfa6de [rclcpp_action] Do not throw exception in action client if take fails (#888) (#891)
As documented in rcl_action, a return code of RCL_RET_ACTION_CLIENT_TAKE_FAILED does not mean that
an error occurred.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-11-18 14:44:06 -08:00
Ivan Santiago Paunovic
fadd923aa0 0.7.11 2019-10-11 11:08:51 -03:00
ivanpauno
f954ce5145 Fix get_node_interfaces functions taking a pointer (#821) (#870)
Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-09-26 14:18:39 -03:00
ivanpauno
895145cfc9 Fix hang with timers in MultiThreadedExecutor (#835) (#836) (#869)
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
2019-09-25 15:52:22 -03:00
Tully Foote
3cdb3cb1bf 0.7.10 2019-09-23 12:41:47 -07:00
Tully Foote
5d5d3ce09d update changelog 2019-09-23 12:40:48 -07:00
Zachary Michaels
839ad201ac reset error message before setting a new one, embed the original one (#854) (#866)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
Signed-off-by: Zachary Michaels <zmichaels11@gmail.com>
2019-09-23 12:38:26 -07:00
Michael Carroll
f3b0aa170c 0.7.9
Signed-off-by: Michael Carroll <michael@openrobotics.org>
2019-09-20 16:14:01 -05:00
Zachary Michaels
6e76503d9a add mutex in add/remove_node and wait_for_work to protect concurrent use/change of memory_strategy_ (#837) (#857)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
Signed-off-by: Zachary Michaels <zmichaels11@gmail.com>
2019-09-20 14:08:34 -07:00
William Woodall
b4629bf889 0.7.8 2019-09-06 10:37:56 -07:00
William Woodall
3f31ad0f55 changelogs
Signed-off-by: William Woodall <william@osrfoundation.org>
2019-09-06 10:37:28 -07:00
Jacob Perron
25eeffdfcc Fixe error messages not printing to terminal (#777) (#847)
* Uncommented catch exception code to print error

Signed-off-by: Yathartha Tuladhar <yathartha3@gmail.com>

* put back the e

Signed-off-by: Yathartha Tuladhar <yathartha3@gmail.com>

* uncommented error printing in exception handling

Signed-off-by: Yathartha Tuladhar <yathartha3@gmail.com>

* Removed "/n" characters.
Update lifecycle_node_interface_impl.hpp

Signed-off-by: Yathartha Tuladhar <yathartha3@gmail.com>

* Fix CI issue and remove TODO

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-09-05 11:59:18 -07:00
Karsten Knese
3293603396 0.7.7 2019-07-31 15:46:10 -07:00
Karsten Knese
50ec1e568a refine changelog text
Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-07-31 15:38:03 -07:00
Karsten Knese
607e290732 generate changelog
Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-07-31 15:11:58 -07:00
Scott K Logan
47ce42bc3f Use params from node '/**' from parameter YAML file (#805)
The short-term goal of this change is to enable the creation of a
parameter YAML file which is applied to each node, regardless of node
name or namespace.

Future work is to support all wildcard syntax in node names in
parameter YAML files.

This is a backport of #762 for Dashing.

Signed-off-by: Scott K Logan <logans@cottsay.net>
2019-07-31 14:05:01 -07:00
Scott K Logan
d2f052ee3d Fix a comparison with a sign mismatch (#804)
This is a backport of #771 for Dashing.

Signed-off-by: Scott K Logan <logans@cottsay.net>
2019-07-31 11:05:00 -07:00
Gonzo
b86127d721 changed on_parameter_event qos profile to rmw_qos_profile_parameter_events (#774) (#798)
Signed-off-by: alberto <alberto.soragna@gmail.com>
2019-07-30 15:06:44 -03:00
Michel Hidalgo
5cb6a6eeb5 Make TimeSource ignore use_sim_time events coming from other nodes. (#799) (#803)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-07-30 12:44:39 -03:00
Karsten Knese
f41e33c2a7 use default parameter descriptor in parameters interface (#765) (#794)
* use default parameter descriptor in parameters interface

Signed-off-by: Karsten Knese <karsten@openrobotics.org>

* use default parameter for value

Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-07-29 11:24:19 -07:00
Esteve Fernandez
10c34ee9e5 Added support for const member functions (#763)
* Added support for const member functions

Signed-off-by: Esteve Fernandez <esteve@apache.org>

* Added signature for Windows

Signed-off-by: Esteve Fernandez <esteve@apache.org>

* Fix style

Signed-off-by: Esteve Fernandez <esteve@apache.org>

* Attempt at fixing function_traits for macOS

Signed-off-by: Esteve Fernandez <esteve@apache.org>
2019-07-29 10:44:27 -07:00
Dirk Thomas
6d3cbd39d1 Add default value to options in LifecycleNode construnctor. Update API documentation. (#775) (#801)
Signed-off-by: Esteve Fernandez <esteve@apache.org>
2019-07-26 15:39:05 -07:00
Chris Lalancette
bfee90ab7a 0.7.6 2019-06-12 20:13:10 +00:00
Chris Lalancette
1927f7e40e Changelog.
Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2019-06-12 20:12:58 +00:00
ivanpauno
f73d80e79c Ignore parameters overrides in set parameter methods when allowing undeclared parameters (#756)
* Ignore parameters overrides in set parameter methods when allowing undeclared parameters

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>

* Address reviewer comment

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-06-12 16:02:01 -04:00
Shane Loretz
e2e35570d5 Add rclcpp::create_timer() (#757)
* Add rclcpp::create_timer()

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Friendly overload with node-like object

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* forward<CallbackT>

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Make sure test with NodeWrapper compiles

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-06-12 16:02:01 -04:00
Alberto Soragna
5c395d6651 checking origin of intra-process msg before taking them (#753)
Signed-off-by: alberto <alberto.soragna@gmail.com>
2019-06-12 16:02:01 -04:00
122 changed files with 2857 additions and 2685 deletions

View File

@@ -2,48 +2,70 @@
Changelog for package rclcpp
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.8.0 (2019-09-26)
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
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
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
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
0.7.12 (2019-12-05)
-------------------
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
0.7.10 (2019-09-23)
-------------------
0.7.9 (2019-09-20)
------------------
* 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
0.7.8 (2019-09-06)
------------------
0.7.7 (2019-07-31)
------------------
* 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.7.6 (2019-06-12)
------------------
* 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)
------------------

View File

@@ -7,7 +7,6 @@ find_package(builtin_interfaces REQUIRED)
find_package(rcl REQUIRED)
find_package(rcl_interfaces REQUIRED)
find_package(rcl_yaml_param_parser REQUIRED)
find_package(rcpputils REQUIRED)
find_package(rmw REQUIRED)
find_package(rmw_implementation REQUIRED)
find_package(rosgraph_msgs REQUIRED)
@@ -20,7 +19,11 @@ if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
# 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)
endif()
include_directories(include)
@@ -107,7 +110,6 @@ add_library(${PROJECT_NAME}
ament_target_dependencies(${PROJECT_NAME}
"rcl"
"rcl_yaml_param_parser"
"rcpputils"
"builtin_interfaces"
"rosgraph_msgs"
"rosidl_typesupport_cpp"
@@ -131,7 +133,6 @@ ament_export_libraries(${PROJECT_NAME})
ament_export_dependencies(ament_cmake)
ament_export_dependencies(rcl)
ament_export_dependencies(rcpputils)
ament_export_dependencies(builtin_interfaces)
ament_export_dependencies(rosgraph_msgs)
ament_export_dependencies(rosidl_typesupport_cpp)
@@ -146,12 +147,8 @@ if(BUILD_TESTING)
find_package(rmw_implementation_cmake REQUIRED)
find_package(test_msgs REQUIRED)
include(cmake/rclcpp_add_build_failure_test.cmake)
add_definitions(-DTEST_RESOURCES_DIRECTORY="${CMAKE_CURRENT_BINARY_DIR}/test/resources")
ament_add_gtest(test_client test/test_client.cpp)
if(TARGET test_client)
ament_target_dependencies(test_client
@@ -217,7 +214,6 @@ if(BUILD_TESTING)
if(TARGET test_node)
ament_target_dependencies(test_node
"rcl_interfaces"
"rcpputils"
"rmw"
"rosidl_generator_cpp"
"rosidl_typesupport_cpp"
@@ -262,11 +258,6 @@ if(BUILD_TESTING)
)
target_link_libraries(test_node_global_args ${PROJECT_NAME})
endif()
ament_add_gtest(test_node_options test/test_node_options.cpp)
if(TARGET test_node_options)
ament_target_dependencies(test_node_options "rcl")
target_link_libraries(test_node_options ${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
@@ -369,6 +360,7 @@ if(BUILD_TESTING)
)
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
@@ -384,17 +376,38 @@ if(BUILD_TESTING)
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)
ament_target_dependencies(test_externally_defined_services
"rcl"
"test_msgs"
)
target_link_libraries(test_externally_defined_services ${PROJECT_NAME})
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}")
@@ -466,10 +479,16 @@ if(BUILD_TESTING)
target_link_libraries(test_multi_threaded_executor ${PROJECT_NAME})
endif()
# Install test resources
install(
DIRECTORY test/resources
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/test)
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()

View File

@@ -184,12 +184,10 @@ public:
} 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_ ||
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 "
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");
@@ -211,8 +209,7 @@ public:
} 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"
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");

View File

@@ -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"
@@ -62,40 +62,25 @@ public:
RCLCPP_PUBLIC
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 &
@@ -145,21 +130,6 @@ protected:
std::vector<rclcpp::ClientBase::WeakPtr> client_ptrs_;
std::vector<rclcpp::Waitable::WeakPtr> waitable_ptrs_;
std::atomic_bool can_be_taken_from_;
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

View File

@@ -105,9 +105,9 @@ public:
*
* Function is only applicable if the clock_type is `RCL_ROS_TIME`
*
* \param pre_callback. Must be non-throwing
* \param post_callback. Must be non-throwing.
* \param threshold. Callbacks will be triggered if the time jump is greater
* \param pre_callback Must be non-throwing
* \param post_callback Must be non-throwing.
* \param threshold Callbacks will be triggered if the time jump is greater
* then the threshold.
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
* \throws std::bad_alloc if the allocation of the JumpHandler fails.

View File

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

View File

@@ -29,6 +29,36 @@
namespace rclcpp
{
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 alternative rclcpp::create_publisher() signatures")]]
std::shared_ptr<PublisherT>
create_publisher(
rclcpp::node_interfaces::NodeTopicsInterface * node_topics,
const std::string & topic_name,
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 publisher_options = rcl_publisher_get_default_options();
publisher_options.qos = qos_profile;
auto pub = node_topics->create_publisher(
topic_name,
rclcpp::create_publisher_factory<MessageT, AllocatorT, PublisherT>(event_callbacks, allocator),
publisher_options,
use_intra_process_comms);
node_topics->add_publisher(pub, group);
return std::dynamic_pointer_cast<PublisherT>(pub);
}
/// Create and return a publisher of the given MessageT type.
/**
* The NodeT type only needs to have a method called get_node_topics_interface()
@@ -37,7 +67,7 @@ namespace rclcpp
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(
@@ -46,23 +76,43 @@ create_publisher(
const rclcpp::QoS & qos,
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options = (
rclcpp::PublisherOptionsWithAllocator<AllocatorT>()
)
)
))
{
// Extract the NodeTopicsInterface from the NodeT.
using rclcpp::node_interfaces::get_node_topics_interface;
auto node_topics = get_node_topics_interface(node);
// Create the publisher.
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),
qos
rclcpp::create_publisher_factory<MessageT, AllocatorT, PublisherT>(
options.event_callbacks,
allocator
),
options.template to_rcl_publisher_options<MessageT>(qos),
use_intra_process
);
// Add the publisher to the node topics interface.
node_topics->add_publisher(pub, options.callback_group);
return std::dynamic_pointer_cast<PublisherT>(pub);
}

View File

@@ -29,6 +29,49 @@
namespace rclcpp
{
template<
typename MessageT,
typename CallbackT,
typename AllocatorT,
typename CallbackMessageT,
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(
rclcpp::node_interfaces::NodeTopicsInterface * node_topics,
const std::string & topic_name,
CallbackT && callback,
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)
{
auto subscription_options = rcl_subscription_get_default_options();
subscription_options.qos = qos_profile;
subscription_options.ignore_local_publications = ignore_local_publications;
auto factory = rclcpp::create_subscription_factory
<MessageT, CallbackT, AllocatorT, CallbackMessageT, SubscriptionT>(
std::forward<CallbackT>(callback),
event_callbacks,
msg_mem_strat,
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);
}
/// Create and return a subscription of the given MessageT type.
/**
* The NodeT type only needs to have a method called get_node_topics_interface()
@@ -42,10 +85,6 @@ 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(
@@ -56,21 +95,48 @@ create_subscription(
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)
{
using rclcpp::node_interfaces::get_node_topics_interface;
auto node_topics = get_node_topics_interface(std::forward<NodeT>(node));
auto factory = rclcpp::create_subscription_factory<MessageT>(
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();
}
auto sub = node_topics->create_subscription(topic_name, factory, qos);
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);
}

View File

@@ -20,8 +20,8 @@
#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"

View File

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

View File

@@ -1,55 +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
{
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_

View File

@@ -28,12 +28,10 @@ class RCLCPP_PUBLIC Duration
public:
Duration(int32_t seconds, uint32_t nanoseconds);
// This constructor matches any numeric value - ints or floats
explicit Duration(rcl_duration_value_t 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
@@ -57,11 +55,14 @@ public:
operator=(const Duration & rhs);
Duration &
operator=(const builtin_interfaces::msg::Duration & Duration_msg);
operator=(const builtin_interfaces::msg::Duration & duration_msg);
bool
operator==(const rclcpp::Duration & rhs) const;
bool
operator!=(const rclcpp::Duration & rhs) const;
bool
operator<(const rclcpp::Duration & rhs) const;
@@ -96,10 +97,6 @@ public:
double
seconds() const;
// Create a duration object from a floating point number representing seconds
static Duration
from_seconds(double seconds);
template<class DurationT>
DurationT
to_chrono() const

View File

@@ -17,14 +17,11 @@
#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
@@ -170,31 +167,6 @@ 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
{
@@ -247,13 +219,6 @@ class ParameterImmutableException : public std::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;
};
} // namespace exceptions
} // namespace rclcpp

View File

@@ -35,6 +35,7 @@
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/utilities.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/scope_exit.hpp"
namespace rclcpp
{
@@ -48,7 +49,6 @@ 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.
* 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.
*/
@@ -212,8 +212,8 @@ public:
/// 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
@@ -244,9 +244,14 @@ public:
}
std::chrono::nanoseconds timeout_left = timeout_ns;
while (rclcpp::ok(this->context_)) {
if (spinning.exchange(true)) {
throw std::runtime_error("spin_until_future_complete() called while already spinning");
}
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
while (rclcpp::ok(this->context_) && spinning.load()) {
// Do one item of work.
spin_once(timeout_left);
spin_once_impl(timeout_left);
// Check if the future is set, return SUCCESS if it is.
status = future.wait_for(std::chrono::seconds(0));
if (status == std::future_status::ready) {
@@ -334,6 +339,10 @@ protected:
rclcpp::callback_group::CallbackGroup::SharedPtr
get_group_by_timer(rclcpp::TimerBase::SharedPtr timer);
RCLCPP_PUBLIC
void
get_next_timer(AnyExecutable & any_exec);
RCLCPP_PUBLIC
bool
get_next_ready_executable(AnyExecutable & any_executable);
@@ -365,6 +374,10 @@ protected:
private:
RCLCPP_DISABLE_COPY(Executor)
RCLCPP_PUBLIC
void
spin_once_impl(std::chrono::nanoseconds timeout);
std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
std::list<const rcl_guard_condition_t *> guard_conditions_;
};

View File

@@ -15,7 +15,6 @@
#ifndef RCLCPP__EXECUTORS__MULTI_THREADED_EXECUTOR_HPP_
#define RCLCPP__EXECUTORS__MULTI_THREADED_EXECUTOR_HPP_
#include <chrono>
#include <memory>
#include <mutex>
#include <set>
@@ -49,13 +48,13 @@ public:
* \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
* \param timeout maximum time to wait
*/
RCLCPP_PUBLIC
MultiThreadedExecutor(
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();
@@ -79,7 +78,6 @@ private:
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_;
};

View File

@@ -88,8 +88,7 @@ struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(FArgs ...))(Args ...)>>
struct function_traits<std::_Bind<std::_Mem_fn<ReturnTypeT (ClassT::*)(Args ...)>(FArgs ...)>>
#elif defined _MSC_VER // MS Visual Studio
struct function_traits<
std::_Binder<std::_Unforced, ReturnTypeT(__cdecl ClassT::*)(Args ...), FArgs ...>
>
std::_Binder<std::_Unforced, ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
#else
#error "Unsupported C++ compiler / standard library"
#endif
@@ -106,8 +105,7 @@ struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(FArgs ...))(Args ...) co
struct function_traits<std::_Bind<std::_Mem_fn<ReturnTypeT (ClassT::*)(Args ...) const>(FArgs ...)>>
#elif defined _MSC_VER // MS Visual Studio
struct function_traits<
std::_Binder<std::_Unforced, ReturnTypeT(__cdecl ClassT::*)(Args ...) const, FArgs ...>
>
std::_Binder<std::_Unforced, ReturnTypeT (ClassT::*)(Args ...) const, FArgs ...>>
#else
#error "Unsupported C++ compiler / standard library"
#endif
@@ -121,7 +119,7 @@ struct function_traits<std::__bind<ReturnTypeT( &)(Args ...), FArgs ...>>
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
struct function_traits<std::_Bind<ReturnTypeT(*(FArgs ...))(Args ...)>>
#elif defined _MSC_VER // MS Visual Studio
struct function_traits<std::_Binder<std::_Unforced, ReturnTypeT(__cdecl &)(Args ...), FArgs ...>>
struct function_traits<std::_Binder<std::_Unforced, ReturnTypeT( &)(Args ...), FArgs ...>>
#else
#error "Unsupported C++ compiler / standard library"
#endif

View File

@@ -79,11 +79,6 @@ public:
rclcpp::executor::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_timer(
rclcpp::executor::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_waitable(
rclcpp::executor::AnyExecutable & any_exec,
@@ -107,11 +102,6 @@ public:
std::shared_ptr<const rcl_client_t> client_handle,
const WeakNodeList & weak_nodes);
static rclcpp::TimerBase::SharedPtr
get_timer_by_handle(
std::shared_ptr<const rcl_timer_t> timer_handle,
const WeakNodeList & weak_nodes);
static rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
get_node_by_group(
rclcpp::callback_group::CallbackGroup::SharedPtr group,
@@ -132,11 +122,6 @@ public:
rclcpp::ClientBase::SharedPtr client,
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
get_group_by_timer(
rclcpp::TimerBase::SharedPtr timer,
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
get_group_by_waitable(
rclcpp::Waitable::SharedPtr waitable,

View File

@@ -95,17 +95,16 @@ public:
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);
}
});
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;
}

View File

@@ -151,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().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.
@@ -174,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,
@@ -183,6 +181,44 @@ 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.
@@ -192,18 +228,16 @@ public:
* \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,
@@ -211,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.
/**
@@ -229,7 +337,13 @@ public:
CallbackT callback,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
/* Create and return a Client. */
/// Create and return a Client.
/**
* \param[in] service_name The topic to service on.
* \param[in] qos_profile rmw_qos_profile_t Quality of service profile for client.
* \param[in] group Callback group to call the service.
* \return Shared pointer to the created client.
*/
template<typename ServiceT>
typename rclcpp::Client<ServiceT>::SharedPtr
create_client(
@@ -237,7 +351,14 @@ public:
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
/* Create and return a Service. */
/// Create and return a Service.
/**
* \param[in] service_name The topic to service on.
* \param[in] callback User-defined callback function.
* \param[in] qos_profile rmw_qos_profile_t Quality of service profile for client.
* \param[in] group Callback group to call the service.
* \return Shared pointer to the created service.
*/
template<typename ServiceT, typename CallbackT>
typename rclcpp::Service<ServiceT>::SharedPtr
create_service(
@@ -261,8 +382,6 @@ 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
* set_on_parameters_set_callback to be called.
* If that callback prevents the initial value for the parameter from being
@@ -276,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.
@@ -292,8 +409,7 @@ public:
const std::string & name,
const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
rcl_interfaces::msg::ParameterDescriptor(),
bool ignore_override = false);
rcl_interfaces::msg::ParameterDescriptor());
/// Declare and initialize a parameter with a type.
/**
@@ -322,8 +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);
rcl_interfaces::msg::ParameterDescriptor());
/// Declare and initialize several parameters with the same namespace and type.
/**
@@ -338,12 +453,11 @@ 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
* set_on_parameters_set_callback to be called, once for each parameter.
@@ -352,8 +466,6 @@ public:
*
* \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
@@ -365,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.
/**
@@ -382,8 +493,7 @@ public:
const std::map<
std::string,
std::pair<ParameterT, rcl_interfaces::msg::ParameterDescriptor>
> & parameters,
bool ignore_overrides = false);
> & parameters);
/// Undeclare a previously declared parameter.
/**
@@ -514,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
@@ -657,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
@@ -727,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
@@ -742,21 +904,19 @@ 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.
@@ -770,68 +930,9 @@ 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
* set_on_parameters_set_callback() method). If a callback tries to do any
* of the latter things,
* rclcpp::exceptions::ParameterModifiedInCallbackException will be thrown.
*
* 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.
*/
RCLCPP_PUBLIC
OnSetParametersCallbackHandle::SharedPtr
add_on_set_parameters_callback(OnParametersSetCallbackType callback);
/// Remove a callback registered with `add_on_set_parameters_callback`.
/**
* 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.
*/
RCLCPP_PUBLIC
void
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler);
/// Register a callback to be called anytime a parameter is about to be changed.
/**
* With this method, only one callback can be set at a time. The callback that was previously
* set by this method is returned or `nullptr` if no callback was previously set.
*
* The callbacks added with `add_on_set_parameters_callback` are stored in a different place.
* `remove_on_set_parameters_callback` can't be used with the callbacks registered with this
* method. For removing it, use `set_on_parameters_set_callback(nullptr)`.
* 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.
*
* \param[in] callback The callback to be called when the value for a
* parameter is about to be set.
@@ -839,9 +940,20 @@ public:
* otherwise nullptr.
*/
RCLCPP_PUBLIC
OnParametersSetCallbackType
rclcpp::Node::OnParametersSetCallbackType
set_on_parameters_set_callback(rclcpp::Node::OnParametersSetCallbackType callback);
/// Register the callback for parameter changes
/**
* \param[in] callback User defined callback function.
* It is expected to atomically set parameters.
* \note Repeated invocations of this function will overwrite previous callbacks.
*/
template<typename CallbackT>
[[deprecated("use set_on_parameters_set_callback() instead")]]
void
register_param_change_callback(CallbackT && callback);
/// Get the fully-qualified names of all available nodes.
/**
* The fully-qualified name includes the local namespace and name of the node.
@@ -956,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.
@@ -988,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()

View File

@@ -36,7 +36,6 @@
#include "rcl_interfaces/msg/intra_process_message.hpp"
#include "rclcpp/contexts/default_context.hpp"
#include "rclcpp/create_client.hpp"
#include "rclcpp/create_publisher.hpp"
#include "rclcpp/create_service.hpp"
#include "rclcpp/create_subscription.hpp"
@@ -79,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,
@@ -103,6 +130,65 @@ 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(
@@ -125,13 +211,21 @@ Node::create_client(
const rmw_qos_profile_t & qos_profile,
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>
@@ -156,14 +250,12 @@ 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)
{
return this->declare_parameter(
name,
rclcpp::ParameterValue(default_value),
parameter_descriptor,
ignore_override
parameter_descriptor
).get<ParameterT>();
}
@@ -171,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;
@@ -196,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
@@ -268,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_

View File

@@ -17,7 +17,6 @@
#include <map>
#include <memory>
#include <list>
#include <string>
#include <vector>
@@ -51,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
{
@@ -105,8 +80,7 @@ public:
declare_parameter(
const std::string & name,
const rclcpp::ParameterValue & default_value,
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
bool ignore_override) override;
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor) override;
RCLCPP_PUBLIC
void
@@ -158,38 +132,26 @@ public:
rcl_interfaces::msg::ListParametersResult
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const override;
RCLCPP_PUBLIC
OnSetParametersCallbackHandle::SharedPtr
add_on_set_parameters_callback(OnParametersSetCallbackType callback) override;
RCLCPP_PUBLIC
void
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler) override;
RCLCPP_PUBLIC
OnParametersSetCallbackType
set_on_parameters_set_callback(OnParametersSetCallbackType callback) override;
[[deprecated("use set_on_parameters_set_callback() instead")]]
RCLCPP_PUBLIC
void
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_;

View File

@@ -16,7 +16,6 @@
#define RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_INTERFACE_HPP_
#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -33,18 +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;
};
/// Pure virtual interface class for the NodeParameters part of the Node API.
class NodeParametersInterface
{
@@ -66,8 +53,7 @@ public:
const std::string & name,
const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
rcl_interfaces::msg::ParameterDescriptor(),
bool ignore_override = false) = 0;
rcl_interfaces::msg::ParameterDescriptor()) = 0;
/// Undeclare a parameter.
/**
@@ -171,25 +157,13 @@ 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.
/**
* \sa rclcpp::Node::add_on_set_parameters_callback
*/
RCLCPP_PUBLIC
virtual
OnSetParametersCallbackHandle::SharedPtr
add_on_set_parameters_callback(OnParametersSetCallbackType callback) = 0;
/// Remove a callback registered with `add_on_set_parameters_callback`.
/**
* \sa rclcpp::Node::remove_on_set_parameters_callback
*/
RCLCPP_PUBLIC
virtual
void
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler) = 0;
using ParametersCallbackFunction [[deprecated("use OnParametersSetCallbackType instead")]] =
OnParametersSetCallbackType;
/// Register a callback for when parameters are being set, return an existing one.
/**
@@ -200,6 +174,12 @@ public:
OnParametersSetCallbackType
set_on_parameters_set_callback(OnParametersSetCallbackType callback) = 0;
[[deprecated("use set_on_parameters_set_callback() instead")]]
RCLCPP_PUBLIC
virtual
void
register_param_change_callback(OnParametersSetCallbackType callback) = 0;
/// Return the initial parameter values used by the NodeParameters to override default values.
RCLCPP_PUBLIC
virtual

View File

@@ -49,7 +49,8 @@ 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
@@ -62,7 +63,8 @@ public:
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

View File

@@ -50,7 +50,8 @@ 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
@@ -65,7 +66,8 @@ 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

View File

@@ -99,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.
*/

View File

@@ -46,6 +46,15 @@ class AsyncParametersClient
public:
RCLCPP_SMART_PTR_DEFINITIONS(AsyncParametersClient)
/// Create an async parameters client.
/**
* \param[in] node_base_interface The node base interface of the corresponding node.
* \param[in] node_topics_interface Node topic base interface.
* \param[in] node_graph_interface The node graph interface of the corresponding node.
* \param[in] node_services_interface Node service interface.
* \param[in] remote_node_name (optional) name of the remote node
* \param[in] qos_profile (optional) The rmw qos profile to use to subscribe
*/
RCLCPP_PUBLIC
AsyncParametersClient(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
@@ -53,22 +62,31 @@ public:
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
/// Constructor
/**
* \param[in] node The async paramters client will be added to this node.
* \param[in] remote_node_name (optional) name of the remote node
* \param[in] qos_profile (optional) The rmw qos profile to use to subscribe
*/
RCLCPP_PUBLIC
AsyncParametersClient(
const rclcpp::Node::SharedPtr node,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
/// Constructor
/**
* \param[in] node The async paramters client will be added to this node.
* \param[in] remote_node_name (optional) name of the remote node
* \param[in] qos_profile (optional) The rmw qos profile to use to subscribe
*/
RCLCPP_PUBLIC
AsyncParametersClient(
rclcpp::Node * node,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
RCLCPP_PUBLIC
std::shared_future<std::vector<rclcpp::Parameter>>
@@ -271,11 +289,7 @@ public:
{
return get_parameter_impl(
parameter_name,
std::function<T()>([&parameter_name]() -> T
{
throw std::runtime_error("Parameter '" + parameter_name + "' is not set");
})
);
std::function<T()>([]() -> T {throw std::runtime_error("Parameter not set");}));
}
RCLCPP_PUBLIC

View File

@@ -44,20 +44,16 @@ public:
* \param[in] event The parameter event message to filter.
* \param[in] names A list of parameter names of interest.
* \param[in] types A list of the types of parameter events of iterest.
* EventType NEW, DELETED, or CHANGED
*
* Example Usage:
*
* If you have recieved a parameter event and are only interested in parameters foo and
* bar being added or changed but don't care about deletion.
*
* ```cpp
* auto res = rclcpp::ParameterEventsFilter(
* event_shared_ptr,
* {"foo", "bar"},
* {rclcpp::ParameterEventsFilter::EventType::NEW, rclcpp::ParameterEventsFilter::EventType::CHANGED});
* ```
*/
* EventType NEW, DELETED, or CHANGED
*
* Example Usage:
* If you have recieved a parameter event and are only interested in parameters foo and
* bar being added or changed but don't care about deletion.
* auto res = rclcpp::ParameterEventsFilter(
* event_shared_ptr,
* {"foo", "bar"},
* {rclcpp::ParameterEventsFilter::EventType::NEW, rclcpp::ParameterEventsFilter::EventType::CHANGED});
*/
RCLCPP_PUBLIC
ParameterEventsFilter(
rcl_interfaces::msg::ParameterEvent::SharedPtr event,

View File

@@ -32,12 +32,9 @@
#include "rclcpp/allocator/allocator_common.hpp"
#include "rclcpp/allocator/allocator_deleter.hpp"
#include "rclcpp/detail/resolve_use_intra_process.hpp"
#include "rclcpp/intra_process_manager.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/publisher_base.hpp"
#include "rclcpp/publisher_options.hpp"
#include "rclcpp/type_support_decl.hpp"
#include "rclcpp/visibility_control.hpp"
@@ -45,79 +42,41 @@ namespace rclcpp
{
/// A publisher publishes messages of any type to a topic.
template<typename MessageT, typename AllocatorT = std::allocator<void>>
template<typename MessageT, typename Alloc = std::allocator<void>>
class Publisher : public PublisherBase
{
public:
using MessageAllocatorTraits = allocator::AllocRebind<MessageT, AllocatorT>;
using MessageAllocator = typename MessageAllocatorTraits::allocator_type;
using MessageDeleter = allocator::Deleter<MessageAllocator, MessageT>;
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
using MessageAlloc = typename MessageAllocTraits::allocator_type;
using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;
using MessageUniquePtr = std::unique_ptr<MessageT, MessageDeleter>;
using MessageSharedPtr = std::shared_ptr<const MessageT>;
RCLCPP_SMART_PTR_DEFINITIONS(Publisher<MessageT, AllocatorT>)
RCLCPP_SMART_PTR_DEFINITIONS(Publisher<MessageT, Alloc>)
Publisher(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const std::string & topic,
const rclcpp::QoS & qos,
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options)
const rcl_publisher_options_t & publisher_options,
const PublisherEventCallbacks & event_callbacks,
const std::shared_ptr<MessageAlloc> & allocator)
: PublisherBase(
node_base,
topic,
*rosidl_typesupport_cpp::get_message_type_support_handle<MessageT>(),
options.template to_rcl_publisher_options<MessageT>(qos)),
options_(options),
message_allocator_(new MessageAllocator(*options.get_allocator().get()))
publisher_options),
message_allocator_(allocator)
{
allocator::set_allocator_for_deleter(&message_deleter_, message_allocator_.get());
if (options_.event_callbacks.deadline_callback) {
this->add_event_handler(
options_.event_callbacks.deadline_callback,
if (event_callbacks.deadline_callback) {
this->add_event_handler(event_callbacks.deadline_callback,
RCL_PUBLISHER_OFFERED_DEADLINE_MISSED);
}
if (options_.event_callbacks.liveliness_callback) {
this->add_event_handler(
options_.event_callbacks.liveliness_callback,
if (event_callbacks.liveliness_callback) {
this->add_event_handler(event_callbacks.liveliness_callback,
RCL_PUBLISHER_LIVELINESS_LOST);
}
// Setup continues in the post construction method, post_init_setup().
}
/// Called post construction, so that construction may continue after shared_from_this() works.
virtual
void
post_init_setup(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const std::string & topic,
const rclcpp::QoS & qos,
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options)
{
// Topic is unused for now.
(void)topic;
// If needed, setup intra process communication.
if (rclcpp::detail::resolve_use_intra_process(options_, *node_base)) {
auto context = node_base->get_context();
// Get the intra process manager instance for this context.
auto ipm = context->get_sub_context<rclcpp::intra_process_manager::IntraProcessManager>();
// Register the publisher with the intra process manager.
if (qos.get_rmw_qos_profile().history == RMW_QOS_POLICY_HISTORY_KEEP_ALL) {
throw std::invalid_argument(
"intraprocess communication is not allowed with keep all history qos policy");
}
if (qos.get_rmw_qos_profile().depth == 0) {
throw std::invalid_argument(
"intraprocess communication is not allowed with a zero qos history depth value");
}
uint64_t intra_process_publisher_id = ipm->add_publisher(this->shared_from_this());
this->setup_intra_process(
intra_process_publisher_id,
ipm,
options.template to_rcl_publisher_options<MessageT>(qos));
}
}
virtual ~Publisher()
@@ -128,7 +87,7 @@ public:
{
return mapped_ring_buffer::MappedRingBuffer<
MessageT,
typename Publisher<MessageT, AllocatorT>::MessageAllocator
typename Publisher<MessageT, Alloc>::MessageAlloc
>::make_shared(size, this->get_allocator());
}
@@ -168,6 +127,18 @@ public:
}
}
// Skip deprecated attribute in windows, as it raise a warning in template specialization.
#if !defined(_WIN32)
[[deprecated(
"publishing an unique_ptr is prefered when using intra process communication."
" If using a shared_ptr, use publish(*msg).")]]
#endif
virtual void
publish(const std::shared_ptr<const MessageT> & msg)
{
publish(*msg);
}
virtual void
publish(const MessageT & msg)
{
@@ -179,20 +150,55 @@ public:
// Otherwise we have to allocate memory in a unique_ptr and pass it along.
// As the message is not const, a copy should be made.
// A shared_ptr<const MessageT> could also be constructed here.
auto ptr = MessageAllocatorTraits::allocate(*message_allocator_.get(), 1);
MessageAllocatorTraits::construct(*message_allocator_.get(), ptr, msg);
auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
MessageAllocTraits::construct(*message_allocator_.get(), ptr, msg);
MessageUniquePtr unique_msg(ptr, message_deleter_);
this->publish(std::move(unique_msg));
}
// Skip deprecated attribute in windows, as it raise a warning in template specialization.
#if !defined(_WIN32)
[[deprecated(
"Use publish(*msg). Check against nullptr before calling if necessary.")]]
#endif
virtual void
publish(const MessageT * msg)
{
if (!msg) {
throw std::runtime_error("msg argument is nullptr");
}
return this->publish(*msg);
}
void
publish(const rcl_serialized_message_t & serialized_msg)
{
return this->do_serialized_publish(&serialized_msg);
}
std::shared_ptr<MessageAllocator>
get_allocator() const
// Skip deprecated attribute in windows, as it raise a warning in template specialization.
#if !defined(_WIN32)
[[deprecated(
"Use publish(*serialized_msg). Check against nullptr before calling if necessary.")]]
#endif
void
publish(const rcl_serialized_message_t * serialized_msg)
{
return this->do_serialized_publish(serialized_msg);
}
// Skip deprecated attribute in windows, as it raise a warning in template specialization.
#if !defined(_WIN32)
[[deprecated(
"Use publish(*serialized_msg). Check against nullptr before calling if necessary.")]]
#endif
void
publish(std::shared_ptr<const rcl_serialized_message_t> serialized_msg)
{
return this->do_serialized_publish(serialized_msg.get());
}
std::shared_ptr<MessageAlloc> get_allocator() const
{
return message_allocator_;
}
@@ -266,7 +272,7 @@ protected:
throw std::runtime_error("cannot publisher msg which is a null pointer");
}
uint64_t message_seq =
ipm->template store_intra_process_message<MessageT, AllocatorT>(publisher_id, msg);
ipm->template store_intra_process_message<MessageT, Alloc>(publisher_id, msg);
return message_seq;
}
@@ -284,13 +290,11 @@ protected:
throw std::runtime_error("cannot publisher msg which is a null pointer");
}
uint64_t message_seq =
ipm->template store_intra_process_message<MessageT, AllocatorT>(publisher_id, std::move(msg));
ipm->template store_intra_process_message<MessageT, Alloc>(publisher_id, std::move(msg));
return message_seq;
}
const rclcpp::PublisherOptionsWithAllocator<AllocatorT> options_;
std::shared_ptr<MessageAllocator> message_allocator_;
std::shared_ptr<MessageAlloc> message_allocator_;
MessageDeleter message_deleter_;
};

View File

@@ -52,7 +52,7 @@ namespace intra_process_manager
class IntraProcessManager;
}
class PublisherBase : public std::enable_shared_from_this<PublisherBase>
class PublisherBase
{
friend ::rclcpp::node_interfaces::NodeTopicsInterface;
@@ -184,9 +184,8 @@ public:
/// Implementation utility function that creates a typed mapped ring buffer.
RCLCPP_PUBLIC
virtual
mapped_ring_buffer::MappedRingBufferBase::SharedPtr
make_mapped_ring_buffer(size_t size) const;
virtual make_mapped_ring_buffer(size_t size) const;
/// Implementation utility function used to setup intra process publishing after creation.
RCLCPP_PUBLIC

View File

@@ -24,7 +24,6 @@
#include "rosidl_typesupport_cpp/message_type_support.hpp"
#include "rclcpp/publisher.hpp"
#include "rclcpp/publisher_options.hpp"
#include "rclcpp/intra_process_manager.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/visibility_control.hpp"
@@ -42,9 +41,6 @@ namespace rclcpp
* called from a templated "create_publisher" method on the Node class, and
* is passed to the non-templated "create_publisher" method on the NodeTopics
* class where it is used to create and setup the Publisher.
*
* It also handles the two step construction of Publishers, first calling
* the constructor and then the post_init_setup() method.
*/
struct PublisherFactory
{
@@ -53,33 +49,39 @@ struct PublisherFactory
rclcpp::PublisherBase::SharedPtr(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const std::string & topic_name,
const rclcpp::QoS & qos
)>;
const rcl_publisher_options_t & publisher_options)>;
const PublisherFactoryFunction create_typed_publisher;
PublisherFactoryFunction create_typed_publisher;
};
/// Return a PublisherFactory with functions setup for creating a PublisherT<MessageT, AllocatorT>.
template<typename MessageT, typename AllocatorT, typename PublisherT>
/// Return a PublisherFactory with functions setup for creating a PublisherT<MessageT, Alloc>.
template<typename MessageT, typename Alloc, typename PublisherT>
PublisherFactory
create_publisher_factory(const rclcpp::PublisherOptionsWithAllocator<AllocatorT> & options)
create_publisher_factory(
const PublisherEventCallbacks & event_callbacks,
std::shared_ptr<Alloc> allocator)
{
PublisherFactory factory {
// factory function that creates a MessageT specific PublisherT
[options](
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const std::string & topic_name,
const rclcpp::QoS & qos
PublisherFactory factory;
// factory function that creates a MessageT specific PublisherT
factory.create_typed_publisher =
[event_callbacks, allocator](
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const std::string & topic_name,
const rcl_publisher_options_t & publisher_options
) -> std::shared_ptr<PublisherT>
{
auto publisher = std::make_shared<PublisherT>(node_base, topic_name, qos, options);
// This is used for setting up things like intra process comms which
// require this->shared_from_this() which cannot be called from
// the constructor.
publisher->post_init_setup(node_base, topic_name, qos, options);
return publisher;
}
};
auto options_copy = publisher_options;
auto message_alloc = std::make_shared<typename PublisherT::MessageAlloc>(*allocator.get());
options_copy.allocator = allocator::get_rcl_allocator<MessageT>(*message_alloc.get());
return std::make_shared<PublisherT>(
node_base,
topic_name,
options_copy,
event_callbacks,
message_alloc);
};
// return the factory now that it is populated
return factory;

View File

@@ -19,21 +19,16 @@
#include <string>
#include <vector>
#include "rcl/publisher.h"
#include "rclcpp/allocator/allocator_common.hpp"
#include "rclcpp/callback_group.hpp"
#include "rclcpp/intra_process_setting.hpp"
#include "rclcpp/qos.hpp"
#include "rclcpp/qos_event.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rcl/publisher.h"
namespace rclcpp
{
namespace callback_group
{
class CallbackGroup;
} // namespace callback_group
/// Non-templated part of PublisherOptionsWithAllocator<Allocator>.
struct PublisherOptionsBase
{
@@ -44,7 +39,7 @@ struct PublisherOptionsBase
PublisherEventCallbacks event_callbacks;
/// Callback group in which the waitable items from the publisher should be placed.
std::shared_ptr<rclcpp::callback_group::CallbackGroup> callback_group;
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group;
};
/// Structure containing optional configuration for Publishers.
@@ -69,26 +64,11 @@ struct PublisherOptionsWithAllocator : public PublisherOptionsBase
rcl_publisher_options_t result;
using AllocatorTraits = std::allocator_traits<Allocator>;
using MessageAllocatorT = typename AllocatorTraits::template rebind_alloc<MessageT>;
auto message_alloc = std::make_shared<MessageAllocatorT>(*this->get_allocator().get());
result.allocator = rclcpp::allocator::get_rcl_allocator<MessageT>(*message_alloc);
auto message_alloc = std::make_shared<MessageAllocatorT>(*allocator.get());
result.allocator = allocator::get_rcl_allocator<MessageT>(*message_alloc);
result.qos = qos.get_rmw_qos_profile();
return result;
}
/// Get the allocator, creating one if needed.
std::shared_ptr<Allocator>
get_allocator() const
{
if (!this->allocator) {
// TODO(wjwwood): I would like to use the commented line instead, but
// cppcheck 1.89 fails with:
// Syntax Error: AST broken, binary operator '>' doesn't have two operands.
// return std::make_shared<Allocator>();
std::shared_ptr<Allocator> tmp(new Allocator());
return tmp;
}
return this->allocator;
}
};
using PublisherOptions = PublisherOptionsWithAllocator<std::allocator<void>>;

View File

@@ -48,8 +48,7 @@
* - rclcpp::Node::get_parameter()
* - rclcpp::Node::describe_parameters()
* - rclcpp::Node::list_parameters()
* - rclcpp::Node::add_on_set_parameters_callback()
* - rclcpp::Node::remove_on_set_parameters_callback()
* - rclcpp::Node::register_param_change_callback()
* - rclcpp::Parameter
* - rclcpp::ParameterValue
* - rclcpp::AsyncParametersClient

View File

@@ -156,6 +156,16 @@ public:
}
}
/// Default constructor.
/**
* The constructor for a Service is almost never called directly.
* Instead, services should be instantiated through the function
* rclcpp::create_service().
*
* \param[in] node_handle NodeBaseInterface pointer that is used in part of the setup.
* \param[in] service_handle service handle.
* \param[in] any_callback User defined callback to call when a client request is received.
*/
Service(
std::shared_ptr<rcl_node_t> node_handle,
std::shared_ptr<rcl_service_t> service_handle,
@@ -174,6 +184,16 @@ public:
service_handle_ = service_handle;
}
/// Default constructor.
/**
* The constructor for a Service is almost never called directly.
* Instead, services should be instantiated through the function
* rclcpp::create_service().
*
* \param[in] node_handle NodeBaseInterface pointer that is used in part of the setup.
* \param[in] service_handle service handle.
* \param[in] any_callback User defined callback to call when a client request is received.
*/
Service(
std::shared_ptr<rcl_node_t> node_handle,
rcl_service_t * service_handle,

View File

@@ -164,31 +164,40 @@ public:
if (!group || !group->can_be_taken_from().load()) {
continue;
}
group->find_subscription_ptrs_if(
[this](const rclcpp::SubscriptionBase::SharedPtr & subscription) {
for (auto & weak_subscription : group->get_subscription_ptrs()) {
auto subscription = weak_subscription.lock();
if (subscription) {
subscription_handles_.push_back(subscription->get_subscription_handle());
if (subscription->get_intra_process_subscription_handle()) {
subscription_handles_.push_back(
subscription->get_intra_process_subscription_handle());
}
return false;
});
group->find_service_ptrs_if([this](const rclcpp::ServiceBase::SharedPtr & service) {
}
}
for (auto & weak_service : group->get_service_ptrs()) {
auto service = weak_service.lock();
if (service) {
service_handles_.push_back(service->get_service_handle());
return false;
});
group->find_client_ptrs_if([this](const rclcpp::ClientBase::SharedPtr & client) {
}
}
for (auto & weak_client : group->get_client_ptrs()) {
auto client = weak_client.lock();
if (client) {
client_handles_.push_back(client->get_client_handle());
return false;
});
group->find_timer_ptrs_if([this](const rclcpp::TimerBase::SharedPtr & timer) {
}
}
for (auto & weak_timer : group->get_timer_ptrs()) {
auto timer = weak_timer.lock();
if (timer) {
timer_handles_.push_back(timer->get_timer_handle());
return false;
});
group->find_waitable_ptrs_if([this](const rclcpp::Waitable::SharedPtr & waitable) {
}
}
for (auto & weak_waitable : group->get_waitable_ptrs()) {
auto waitable = weak_waitable.lock();
if (waitable) {
waitable_handles_.push_back(waitable);
return false;
});
}
}
}
}
return has_invalid_weak_nodes;
@@ -365,41 +374,6 @@ public:
}
}
virtual void
get_next_timer(
executor::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes)
{
auto it = timer_handles_.begin();
while (it != timer_handles_.end()) {
auto timer = get_timer_by_handle(*it, weak_nodes);
if (timer) {
// Find the group for this handle and see if it can be serviced
auto group = get_group_by_timer(timer, weak_nodes);
if (!group) {
// Group was not found, meaning the timer is not valid...
// Remove it from the ready list and continue looking
it = timer_handles_.erase(it);
continue;
}
if (!group->can_be_taken_from().load()) {
// Group is mutually exclusive and is being used, so skip it for now
// Leave it to be checked next time, but continue searching
++it;
continue;
}
// Otherwise it is safe to set and return the any_exec
any_exec.timer = timer;
any_exec.callback_group = group;
any_exec.node_base = get_node_by_group(group, weak_nodes);
timer_handles_.erase(it);
return;
}
// Else, the service is no longer valid, remove it and continue
it = timer_handles_.erase(it);
}
}
virtual void
get_next_waitable(executor::AnyExecutable & any_exec, const WeakNodeList & weak_nodes)
{

View File

@@ -32,16 +32,13 @@
#include "rcl_interfaces/msg/intra_process_message.hpp"
#include "rclcpp/any_subscription_callback.hpp"
#include "rclcpp/detail/resolve_use_intra_process.hpp"
#include "rclcpp/exceptions.hpp"
#include "rclcpp/expand_topic_or_service_name.hpp"
#include "rclcpp/intra_process_manager.hpp"
#include "rclcpp/logging.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/message_memory_strategy.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/subscription_base.hpp"
#include "rclcpp/subscription_options.hpp"
#include "rclcpp/subscription_traits.hpp"
#include "rclcpp/type_support_decl.hpp"
#include "rclcpp/visibility_control.hpp"
@@ -58,19 +55,15 @@ class NodeTopicsInterface;
/// Subscription implementation, templated on the type of message this subscription receives.
template<
typename CallbackMessageT,
typename AllocatorT = std::allocator<void>,
typename MessageMemoryStrategyT = rclcpp::message_memory_strategy::MessageMemoryStrategy<
CallbackMessageT,
AllocatorT
>>
typename Alloc = std::allocator<void>>
class Subscription : public SubscriptionBase
{
friend class rclcpp::node_interfaces::NodeTopicsInterface;
public:
using MessageAllocatorTraits = allocator::AllocRebind<CallbackMessageT, AllocatorT>;
using MessageAllocator = typename MessageAllocatorTraits::allocator_type;
using MessageDeleter = allocator::Deleter<MessageAllocator, CallbackMessageT>;
using MessageAllocTraits = allocator::AllocRebind<CallbackMessageT, Alloc>;
using MessageAlloc = typename MessageAllocTraits::allocator_type;
using MessageDeleter = allocator::Deleter<MessageAlloc, CallbackMessageT>;
using ConstMessageSharedPtr = std::shared_ptr<const CallbackMessageT>;
using MessageUniquePtr = std::unique_ptr<CallbackMessageT, MessageDeleter>;
@@ -78,66 +71,44 @@ public:
/// Default constructor.
/**
* The constructor for a subscription is almost never called directly.
* Instead, subscriptions should be instantiated through the function
* rclcpp::create_subscription().
*
* \param[in] node_base NodeBaseInterface pointer that is used in part of the setup.
* The constructor for a subscription is almost never called directly. Instead, subscriptions
* should be instantiated through Node::create_subscription.
* \param[in] node_handle rcl representation of the node that owns this subscription.
* \param[in] type_support_handle rosidl type support struct, for the Message type of the topic.
* \param[in] topic_name Name of the topic to subscribe to.
* \param[in] subscription_options options for the subscription.
* \param[in] callback User defined callback to call when a message is received.
* \param[in] options options for the subscription.
* \param[in] message_memory_strategy The memory strategy to be used for managing message memory.
* \param[in] memory_strategy The memory strategy to be used for managing message memory.
*/
Subscription(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
std::shared_ptr<rcl_node_t> node_handle,
const rosidl_message_type_support_t & type_support_handle,
const std::string & topic_name,
const rclcpp::QoS & qos,
AnySubscriptionCallback<CallbackMessageT, AllocatorT> callback,
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
typename MessageMemoryStrategyT::SharedPtr message_memory_strategy)
const rcl_subscription_options_t & subscription_options,
AnySubscriptionCallback<CallbackMessageT, Alloc> callback,
const SubscriptionEventCallbacks & event_callbacks,
typename message_memory_strategy::MessageMemoryStrategy<CallbackMessageT, Alloc>::SharedPtr
memory_strategy = message_memory_strategy::MessageMemoryStrategy<CallbackMessageT,
Alloc>::create_default())
: SubscriptionBase(
node_base,
node_handle,
type_support_handle,
topic_name,
options.template to_rcl_subscription_options<CallbackMessageT>(qos),
subscription_options,
rclcpp::subscription_traits::is_serialized_subscription_argument<CallbackMessageT>::value),
any_callback_(callback),
message_memory_strategy_(message_memory_strategy)
message_memory_strategy_(memory_strategy)
{
if (options.event_callbacks.deadline_callback) {
this->add_event_handler(
options.event_callbacks.deadline_callback,
if (event_callbacks.deadline_callback) {
this->add_event_handler(event_callbacks.deadline_callback,
RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED);
}
if (options.event_callbacks.liveliness_callback) {
this->add_event_handler(
options.event_callbacks.liveliness_callback,
if (event_callbacks.liveliness_callback) {
this->add_event_handler(event_callbacks.liveliness_callback,
RCL_SUBSCRIPTION_LIVELINESS_CHANGED);
}
}
/// Called after construction to continue setup that requires shared_from_this().
void
post_init_setup(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const rclcpp::QoS & qos,
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options)
{
// Setup intra process publishing if requested.
if (rclcpp::detail::resolve_use_intra_process(options, *node_base)) {
auto context = node_base->get_context();
using rclcpp::intra_process_manager::IntraProcessManager;
auto ipm = context->get_sub_context<IntraProcessManager>();
uint64_t intra_process_subscription_id = ipm->add_subscription(this->shared_from_this());
this->setup_intra_process(
intra_process_subscription_id,
ipm,
options.template to_rcl_subscription_options<CallbackMessageT>(qos));
}
}
/// Support dynamically setting the message memory strategy.
/**
* Behavior may be undefined if called while the subscription could be executing.
@@ -145,7 +116,7 @@ public:
*/
void set_message_memory_strategy(
typename message_memory_strategy::MessageMemoryStrategy<CallbackMessageT,
AllocatorT>::SharedPtr message_memory_strategy)
Alloc>::SharedPtr message_memory_strategy)
{
message_memory_strategy_ = message_memory_strategy;
}
@@ -264,7 +235,7 @@ private:
throw std::runtime_error(
"intra process take called after destruction of intra process manager");
}
ipm->template take_intra_process_message<CallbackMessageT, AllocatorT>(
ipm->template take_intra_process_message<CallbackMessageT, Alloc>(
publisher_id, message_sequence, subscription_id, message);
}
@@ -280,7 +251,7 @@ private:
throw std::runtime_error(
"intra process take called after destruction of intra process manager");
}
ipm->template take_intra_process_message<CallbackMessageT, AllocatorT>(
ipm->template take_intra_process_message<CallbackMessageT, Alloc>(
publisher_id, message_sequence, subscription_id, message);
}
@@ -301,8 +272,8 @@ private:
RCLCPP_DISABLE_COPY(Subscription)
AnySubscriptionCallback<CallbackMessageT, AllocatorT> any_callback_;
typename message_memory_strategy::MessageMemoryStrategy<CallbackMessageT, AllocatorT>::SharedPtr
AnySubscriptionCallback<CallbackMessageT, Alloc> any_callback_;
typename message_memory_strategy::MessageMemoryStrategy<CallbackMessageT, Alloc>::SharedPtr
message_memory_strategy_;
};

View File

@@ -36,7 +36,7 @@ namespace rclcpp
namespace node_interfaces
{
class NodeBaseInterface;
class NodeTopicsInterface;
} // namespace node_interfaces
namespace intra_process_manager
@@ -50,14 +50,14 @@ class IntraProcessManager;
/// Virtual base class for subscriptions. This pattern allows us to iterate over different template
/// specializations of Subscription, among other things.
class SubscriptionBase : public std::enable_shared_from_this<SubscriptionBase>
class SubscriptionBase
{
public:
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(SubscriptionBase)
/// Default constructor.
/**
* \param[in] node_base NodeBaseInterface pointer used in parts of the setup.
* \param[in] node_handle The rcl representation of the node that owns this subscription.
* \param[in] type_support_handle rosidl type support struct, for the Message type of the topic.
* \param[in] topic_name Name of the topic to subscribe to.
* \param[in] subscription_options options for the subscription.
@@ -65,7 +65,7 @@ public:
*/
RCLCPP_PUBLIC
SubscriptionBase(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
std::shared_ptr<rcl_node_t> node_handle,
const rosidl_message_type_support_t & type_support_handle,
const std::string & topic_name,
const rcl_subscription_options_t & subscription_options,
@@ -98,32 +98,14 @@ public:
const std::vector<std::shared_ptr<rclcpp::QOSEventHandlerBase>> &
get_event_handlers() const;
/// Get the actual QoS settings, after the defaults have been determined.
/**
* The actual configuration applied when using RMW_QOS_POLICY_*_SYSTEM_DEFAULT
* can only be resolved after the creation of the publisher, and it
* depends on the underlying rmw implementation.
* If the underlying setting in use can't be represented in ROS terms,
* it will be set to RMW_QOS_POLICY_*_UNKNOWN.
* May throw runtime_error when an unexpected error occurs.
* \return The actual qos settings.
*/
RCLCPP_PUBLIC
rmw_qos_profile_t
get_actual_qos() const;
/// Borrow a new message.
/** \return Shared pointer to the fresh message. */
RCLCPP_PUBLIC
virtual
std::shared_ptr<void>
virtual std::shared_ptr<void>
create_message() = 0;
/// Borrow a new serialized message
/** \return Shared pointer to a rcl_message_serialized_t. */
RCLCPP_PUBLIC
virtual
std::shared_ptr<rcl_serialized_message_t>
virtual std::shared_ptr<rcl_serialized_message_t>
create_serialized_message() = 0;
/// Check if we need to handle the message, and execute the callback if we do.
@@ -131,37 +113,27 @@ public:
* \param[in] message Shared pointer to the message to handle.
* \param[in] message_info Metadata associated with this message.
*/
RCLCPP_PUBLIC
virtual
void
virtual void
handle_message(std::shared_ptr<void> & message, const rmw_message_info_t & message_info) = 0;
/// Return the message borrowed in create_message.
/** \param[in] message Shared pointer to the returned message. */
RCLCPP_PUBLIC
virtual
void
virtual void
return_message(std::shared_ptr<void> & message) = 0;
/// Return the message borrowed in create_serialized_message.
/** \param[in] message Shared pointer to the returned message. */
RCLCPP_PUBLIC
virtual
void
virtual void
return_serialized_message(std::shared_ptr<rcl_serialized_message_t> & message) = 0;
RCLCPP_PUBLIC
virtual
void
virtual void
handle_intra_process_message(
rcl_interfaces::msg::IntraProcessMessage & ipm,
const rmw_message_info_t & message_info) = 0;
RCLCPP_PUBLIC
const rosidl_message_type_support_t &
get_message_type_support_handle() const;
RCLCPP_PUBLIC
bool
is_serialized() const;
@@ -175,9 +147,7 @@ public:
std::weak_ptr<rclcpp::intra_process_manager::IntraProcessManager>;
/// Implemenation detail.
RCLCPP_PUBLIC
void
setup_intra_process(
void setup_intra_process(
uint64_t intra_process_subscription_id,
IntraProcessManagerWeakPtr weak_ipm,
const rcl_subscription_options_t & intra_process_options);

View File

@@ -43,9 +43,6 @@ namespace rclcpp
* usually called from a templated "create_subscription" method of the Node
* class, and is passed to the non-templated "create_subscription" method of
* the NodeTopics class where it is used to create and setup the Subscription.
*
* It also handles the two step construction of Subscriptions, first calling
* the constructor and then the post_init_setup() method.
*/
struct SubscriptionFactory
{
@@ -54,62 +51,76 @@ struct SubscriptionFactory
rclcpp::SubscriptionBase::SharedPtr(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const std::string & topic_name,
const rclcpp::QoS & qos)>;
const rcl_subscription_options_t & subscription_options)>;
const SubscriptionFactoryFunction create_typed_subscription;
SubscriptionFactoryFunction create_typed_subscription;
// Function that takes a MessageT from the intra process manager
using SetupIntraProcessFunction = std::function<
void (
rclcpp::intra_process_manager::IntraProcessManager::SharedPtr ipm,
rclcpp::SubscriptionBase::SharedPtr subscription,
const rcl_subscription_options_t & subscription_options)>;
SetupIntraProcessFunction setup_intra_process;
};
/// Return a SubscriptionFactory with functions for creating a SubscriptionT<MessageT, Alloc>.
/// Return a SubscriptionFactory setup to create a SubscriptionT<MessageT, AllocatorT>.
/**
* \param[in] callback The user-defined callback function to receive a message
* \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.
*/
template<
typename MessageT,
typename CallbackT,
typename AllocatorT,
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 Alloc,
typename CallbackMessageT,
typename SubscriptionT>
SubscriptionFactory
create_subscription_factory(
CallbackT && callback,
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat)
const SubscriptionEventCallbacks & event_callbacks,
typename rclcpp::message_memory_strategy::MessageMemoryStrategy<
CallbackMessageT, Alloc>::SharedPtr
msg_mem_strat,
std::shared_ptr<Alloc> allocator)
{
auto allocator = options.get_allocator();
SubscriptionFactory factory;
using rclcpp::AnySubscriptionCallback;
AnySubscriptionCallback<CallbackMessageT, AllocatorT> any_subscription_callback(allocator);
AnySubscriptionCallback<CallbackMessageT, Alloc> any_subscription_callback(allocator);
any_subscription_callback.set(std::forward<CallbackT>(callback));
SubscriptionFactory factory {
// factory function that creates a MessageT specific SubscriptionT
[options, msg_mem_strat, any_subscription_callback](
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const std::string & topic_name,
const rclcpp::QoS & qos
auto message_alloc =
std::make_shared<typename Subscription<CallbackMessageT, Alloc>::MessageAlloc>();
// factory function that creates a MessageT specific SubscriptionT
factory.create_typed_subscription =
[allocator, msg_mem_strat, any_subscription_callback, event_callbacks, message_alloc](
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const std::string & topic_name,
const rcl_subscription_options_t & subscription_options
) -> rclcpp::SubscriptionBase::SharedPtr
{
auto options_copy = subscription_options;
options_copy.allocator =
rclcpp::allocator::get_rcl_allocator<CallbackMessageT>(*message_alloc.get());
using rclcpp::Subscription;
using rclcpp::SubscriptionBase;
auto sub = Subscription<CallbackMessageT, AllocatorT>::make_shared(
node_base,
auto sub = Subscription<CallbackMessageT, Alloc>::make_shared(
node_base->get_shared_rcl_node_handle(),
*rosidl_typesupport_cpp::get_message_type_support_handle<MessageT>(),
topic_name,
qos,
options_copy,
any_subscription_callback,
options,
event_callbacks,
msg_mem_strat);
// This is used for setting up things like intra process comms which
// require this->shared_from_this() which cannot be called from
// the constructor.
sub->post_init_setup(node_base, qos, options);
auto sub_base_ptr = std::dynamic_pointer_cast<SubscriptionBase>(sub);
return sub_base_ptr;
}
};
};
// return the factory now that it is populated
return factory;

View File

@@ -70,16 +70,6 @@ struct SubscriptionOptionsWithAllocator : public SubscriptionOptionsBase
result.qos = qos.get_rmw_qos_profile();
return result;
}
/// Get the allocator, creating one if needed.
std::shared_ptr<Allocator>
get_allocator() const
{
if (!this->allocator) {
return std::make_shared<Allocator>();
}
return this->allocator;
}
};
using SubscriptionOptions = SubscriptionOptionsWithAllocator<std::allocator<void>>;

View File

@@ -34,17 +34,32 @@ public:
RCLCPP_PUBLIC
Time(int32_t seconds, uint32_t nanoseconds, rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
/// Time constructor
/**
* \param nanoseconds since time epoch
* \param clock_type clock type
*/
RCLCPP_PUBLIC
explicit Time(int64_t nanoseconds = 0, rcl_clock_type_t clock = RCL_SYSTEM_TIME);
explicit Time(int64_t nanoseconds = 0, rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
RCLCPP_PUBLIC
Time(const Time & rhs);
/// Time constructor
/**
* \param time_msg builtin_interfaces time message to copy
* \param clock_type clock type
* \throws std::runtime_error if seconds are negative
*/
RCLCPP_PUBLIC
Time(
const builtin_interfaces::msg::Time & time_msg,
rcl_clock_type_t ros_time = RCL_ROS_TIME);
rcl_clock_type_t clock_type = RCL_ROS_TIME);
/// Time constructor
/**
* \param time_point rcl_time_point_t structure to copy
*/
RCLCPP_PUBLIC
explicit Time(const rcl_time_point_t & time_point);
@@ -58,6 +73,12 @@ public:
Time &
operator=(const Time & rhs);
/**
* Assign Time from a builtin_interfaces::msg::Time instance.
* The clock_type will be reset to RCL_ROS_TIME.
* Equivalent to *this = Time(time_msg, RCL_ROS_TIME).
* \throws std::runtime_error if seconds are negative
*/
RCLCPP_PUBLIC
Time &
operator=(const builtin_interfaces::msg::Time & time_msg);

View File

@@ -126,6 +126,7 @@ public:
* \param[in] clock The clock providing the current time.
* \param[in] period The interval at which the timer fires.
* \param[in] callback User-specified callback function.
* \param[in] context custom context to be used.
*/
explicit GenericTimer(
Clock::SharedPtr clock, std::chrono::nanoseconds period, FunctorT && callback,

View File

@@ -119,7 +119,7 @@ public:
RCLCPP_PUBLIC
virtual
bool
is_ready(rcl_wait_set_t *) = 0;
is_ready(rcl_wait_set_t * wait_set) = 0;
/// Execute any entities of the Waitable that are ready.
/**
@@ -128,7 +128,7 @@ public:
*
* Example usage:
*
* ```cpp
* ```
* // ... create a wait set and a Waitable
* // Add the Waitable to the wait set
* bool add_ret = waitable.add_to_wait_set(wait_set);

View File

@@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>rclcpp</name>
<version>0.8.0</version>
<version>0.7.16</version>
<description>The ROS client library in C++.</description>
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
<license>Apache License 2.0</license>
@@ -26,7 +26,6 @@
<depend>rcl</depend>
<depend>rcl_yaml_param_parser</depend>
<depend>rcpputils</depend>
<depend>rmw_implementation</depend>
<exec_depend>ament_cmake</exec_depend>

View File

@@ -95,7 +95,7 @@ def is_supported_feature_combination(feature_combination):
#define RCLCPP_@(severity)@(suffix)(logger, @(''.join([p + ', ' for p in get_macro_parameters(feature_combination).keys()]))...) \
do { \
static_assert( \
::std::is_same<typename std::remove_cv<typename std::remove_reference<decltype(logger)>::type>::type, \
::std::is_same<typename std::remove_reference<typename std::remove_cv<decltype(logger)>::type>::type, \
typename ::rclcpp::Logger>::value, \
"First argument to logging macros must be an rclcpp::Logger"); \
RCUTILS_LOG_@(severity)@(suffix)_NAMED( \

View File

@@ -23,6 +23,40 @@ CallbackGroup::CallbackGroup(CallbackGroupType group_type)
: type_(group_type), can_be_taken_from_(true)
{}
const std::vector<rclcpp::SubscriptionBase::WeakPtr> &
CallbackGroup::get_subscription_ptrs() const
{
std::lock_guard<std::mutex> lock(mutex_);
return subscription_ptrs_;
}
const std::vector<rclcpp::TimerBase::WeakPtr> &
CallbackGroup::get_timer_ptrs() const
{
std::lock_guard<std::mutex> lock(mutex_);
return timer_ptrs_;
}
const std::vector<rclcpp::ServiceBase::WeakPtr> &
CallbackGroup::get_service_ptrs() const
{
std::lock_guard<std::mutex> lock(mutex_);
return service_ptrs_;
}
const std::vector<rclcpp::ClientBase::WeakPtr> &
CallbackGroup::get_client_ptrs() const
{
std::lock_guard<std::mutex> lock(mutex_);
return client_ptrs_;
}
const std::vector<rclcpp::Waitable::WeakPtr> &
CallbackGroup::get_waitable_ptrs() const
{
std::lock_guard<std::mutex> lock(mutex_);
return waitable_ptrs_;
}
std::atomic_bool &
CallbackGroup::can_be_taken_from()
@@ -42,12 +76,6 @@ CallbackGroup::add_subscription(
{
std::lock_guard<std::mutex> lock(mutex_);
subscription_ptrs_.push_back(subscription_ptr);
subscription_ptrs_.erase(
std::remove_if(
subscription_ptrs_.begin(),
subscription_ptrs_.end(),
[](rclcpp::SubscriptionBase::WeakPtr x) {return x.expired();}),
subscription_ptrs_.end());
}
void
@@ -55,12 +83,6 @@ CallbackGroup::add_timer(const rclcpp::TimerBase::SharedPtr timer_ptr)
{
std::lock_guard<std::mutex> lock(mutex_);
timer_ptrs_.push_back(timer_ptr);
timer_ptrs_.erase(
std::remove_if(
timer_ptrs_.begin(),
timer_ptrs_.end(),
[](rclcpp::TimerBase::WeakPtr x) {return x.expired();}),
timer_ptrs_.end());
}
void
@@ -68,12 +90,6 @@ CallbackGroup::add_service(const rclcpp::ServiceBase::SharedPtr service_ptr)
{
std::lock_guard<std::mutex> lock(mutex_);
service_ptrs_.push_back(service_ptr);
service_ptrs_.erase(
std::remove_if(
service_ptrs_.begin(),
service_ptrs_.end(),
[](rclcpp::ServiceBase::WeakPtr x) {return x.expired();}),
service_ptrs_.end());
}
void
@@ -81,12 +97,6 @@ CallbackGroup::add_client(const rclcpp::ClientBase::SharedPtr client_ptr)
{
std::lock_guard<std::mutex> lock(mutex_);
client_ptrs_.push_back(client_ptr);
client_ptrs_.erase(
std::remove_if(
client_ptrs_.begin(),
client_ptrs_.end(),
[](rclcpp::ClientBase::WeakPtr x) {return x.expired();}),
client_ptrs_.end());
}
void
@@ -94,12 +104,6 @@ CallbackGroup::add_waitable(const rclcpp::Waitable::SharedPtr waitable_ptr)
{
std::lock_guard<std::mutex> lock(mutex_);
waitable_ptrs_.push_back(waitable_ptr);
waitable_ptrs_.erase(
std::remove_if(
waitable_ptrs_.begin(),
waitable_ptrs_.end(),
[](rclcpp::Waitable::WeakPtr x) {return x.expired();}),
waitable_ptrs_.end());
}
void

View File

@@ -35,7 +35,7 @@ Clock::Clock(rcl_clock_type_t clock_type)
allocator_ = rcl_get_default_allocator();
auto ret = rcl_clock_init(clock_type, &rcl_clock_, &allocator_);
if (ret != RCL_RET_OK) {
exceptions::throw_from_rcl_error(ret, "could not get current time stamp");
exceptions::throw_from_rcl_error(ret, "failed to initialize rcl clock");
}
}
@@ -119,9 +119,8 @@ Clock::create_jump_callback(
}
// Try to add the jump callback to the clock
rcl_ret_t ret = rcl_clock_add_jump_callback(
&rcl_clock_, threshold, Clock::on_time_jump,
handler.get());
rcl_ret_t ret = rcl_clock_add_jump_callback(&rcl_clock_, threshold,
Clock::on_time_jump, handler.get());
if (RCL_RET_OK != ret) {
exceptions::throw_from_rcl_error(ret, "Failed to add time jump callback");
}

View File

@@ -47,16 +47,14 @@ Duration::Duration(std::chrono::nanoseconds nanoseconds)
rcl_duration_.nanoseconds = nanoseconds.count();
}
Duration::Duration(const Duration & rhs)
{
rcl_duration_.nanoseconds = rhs.rcl_duration_.nanoseconds;
}
Duration::Duration(const Duration & rhs) = default;
Duration::Duration(
const builtin_interfaces::msg::Duration & duration_msg)
{
rcl_duration_.nanoseconds = RCL_S_TO_NS(static_cast<uint64_t>(duration_msg.sec));
rcl_duration_.nanoseconds += duration_msg.nanosec;
rcl_duration_.nanoseconds =
RCL_S_TO_NS(static_cast<rcl_duration_value_t>(duration_msg.sec));
rcl_duration_.nanoseconds += static_cast<rcl_duration_value_t>(duration_msg.nanosec);
}
Duration::Duration(const rcl_duration_t & duration)
@@ -68,24 +66,25 @@ Duration::Duration(const rcl_duration_t & duration)
Duration::operator builtin_interfaces::msg::Duration() const
{
builtin_interfaces::msg::Duration msg_duration;
msg_duration.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_duration_.nanoseconds));
msg_duration.nanosec =
static_cast<std::uint32_t>(rcl_duration_.nanoseconds % (1000 * 1000 * 1000));
constexpr rcl_duration_value_t kDivisor = RCL_S_TO_NS(1);
const auto result = std::div(rcl_duration_.nanoseconds, kDivisor);
if (result.rem >= 0) {
msg_duration.sec = static_cast<std::int32_t>(result.quot);
msg_duration.nanosec = static_cast<std::uint32_t>(result.rem);
} else {
msg_duration.sec = static_cast<std::int32_t>(result.quot - 1);
msg_duration.nanosec = static_cast<std::uint32_t>(kDivisor + result.rem);
}
return msg_duration;
}
Duration &
Duration::operator=(const Duration & rhs)
{
rcl_duration_.nanoseconds = rhs.rcl_duration_.nanoseconds;
return *this;
}
Duration::operator=(const Duration & rhs) = default;
Duration &
Duration::operator=(const builtin_interfaces::msg::Duration & duration_msg)
{
rcl_duration_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(duration_msg.sec));
rcl_duration_.nanoseconds += duration_msg.nanosec;
*this = Duration(duration_msg);
return *this;
}
@@ -95,6 +94,12 @@ Duration::operator==(const rclcpp::Duration & rhs) const
return rcl_duration_.nanoseconds == rhs.rcl_duration_.nanoseconds;
}
bool
Duration::operator!=(const rclcpp::Duration & rhs) const
{
return rcl_duration_.nanoseconds != rhs.rcl_duration_.nanoseconds;
}
bool
Duration::operator<(const rclcpp::Duration & rhs) const
{
@@ -122,15 +127,15 @@ Duration::operator>(const rclcpp::Duration & rhs) const
void
bounds_check_duration_sum(int64_t lhsns, int64_t rhsns, uint64_t max)
{
auto abs_lhs = (uint64_t)std::abs(lhsns);
auto abs_rhs = (uint64_t)std::abs(rhsns);
auto abs_lhs = static_cast<uint64_t>(std::abs(lhsns));
auto abs_rhs = static_cast<uint64_t>(std::abs(rhsns));
if (lhsns > 0 && rhsns > 0) {
if (abs_lhs + abs_rhs > (uint64_t) max) {
if (abs_lhs + abs_rhs > max) {
throw std::overflow_error("addition leads to int64_t overflow");
}
} else if (lhsns < 0 && rhsns < 0) {
if (abs_lhs + abs_rhs > (uint64_t) max) {
if (abs_lhs + abs_rhs > max) {
throw std::underflow_error("addition leads to int64_t underflow");
}
}
@@ -150,15 +155,15 @@ Duration::operator+(const rclcpp::Duration & rhs) const
void
bounds_check_duration_difference(int64_t lhsns, int64_t rhsns, uint64_t max)
{
auto abs_lhs = (uint64_t)std::abs(lhsns);
auto abs_rhs = (uint64_t)std::abs(rhsns);
auto abs_lhs = static_cast<uint64_t>(std::abs(lhsns));
auto abs_rhs = static_cast<uint64_t>(std::abs(rhsns));
if (lhsns > 0 && rhsns < 0) {
if (abs_lhs + abs_rhs > (uint64_t) max) {
if (abs_lhs + abs_rhs > max) {
throw std::overflow_error("duration subtraction leads to int64_t overflow");
}
} else if (lhsns < 0 && rhsns > 0) {
if (abs_lhs + abs_rhs > (uint64_t) max) {
if (abs_lhs + abs_rhs > max) {
throw std::underflow_error("duration subtraction leads to int64_t underflow");
}
}
@@ -181,8 +186,10 @@ bounds_check_duration_scale(int64_t dns, double scale, uint64_t max)
{
auto abs_dns = static_cast<uint64_t>(std::abs(dns));
auto abs_scale = std::abs(scale);
if (abs_scale > 1.0 && abs_dns > static_cast<uint64_t>(max / abs_scale)) {
if (abs_scale > 1.0 &&
abs_dns >
static_cast<uint64_t>(static_cast<long double>(max) / static_cast<long double>(abs_scale)))
{
if ((dns > 0 && scale > 0) || (dns < 0 && scale < 0)) {
throw std::overflow_error("duration scaling leads to int64_t overflow");
} else {
@@ -201,7 +208,9 @@ Duration::operator*(double scale) const
this->rcl_duration_.nanoseconds,
scale,
std::numeric_limits<rcl_duration_value_t>::max());
return Duration(static_cast<rcl_duration_value_t>(rcl_duration_.nanoseconds * scale));
long double scale_ld = static_cast<long double>(scale);
return Duration(static_cast<rcl_duration_value_t>(
static_cast<long double>(rcl_duration_.nanoseconds) * scale_ld));
}
rcl_duration_value_t
@@ -225,18 +234,16 @@ Duration::seconds() const
rmw_time_t
Duration::to_rmw_time() const
{
if (rcl_duration_.nanoseconds < 0) {
throw std::runtime_error("rmw_time_t cannot be negative");
}
// reuse conversion logic from msg creation
builtin_interfaces::msg::Duration msg = *this;
rmw_time_t result;
result.sec = msg.sec;
result.nsec = msg.nanosec;
result.sec = static_cast<uint64_t>(msg.sec);
result.nsec = static_cast<uint64_t>(msg.nanosec);
return result;
}
Duration
Duration::from_seconds(double seconds)
{
return Duration(static_cast<int64_t>(RCL_S_TO_NS(seconds)));
}
} // namespace rclcpp

View File

@@ -17,7 +17,6 @@
#include <cstdio>
#include <functional>
#include <string>
#include <vector>
using namespace std::string_literals;
@@ -69,8 +68,6 @@ from_rcl_error(
return std::make_exception_ptr(RCLBadAlloc(base_exc));
case RCL_RET_INVALID_ARGUMENT:
return std::make_exception_ptr(RCLInvalidArgument(base_exc, formatted_prefix));
case RCL_RET_INVALID_ROS_ARGS:
return std::make_exception_ptr(RCLInvalidROSArgsError(base_exc, formatted_prefix));
default:
return std::make_exception_ptr(RCLError(base_exc, formatted_prefix));
}
@@ -129,18 +126,5 @@ RCLInvalidArgument::RCLInvalidArgument(
: RCLErrorBase(base_exc), std::invalid_argument(prefix + base_exc.formatted_message)
{}
RCLInvalidROSArgsError::RCLInvalidROSArgsError(
rcl_ret_t ret,
const rcl_error_state_t * error_state,
const std::string & prefix)
: RCLInvalidROSArgsError(RCLErrorBase(ret, error_state), prefix)
{}
RCLInvalidROSArgsError::RCLInvalidROSArgsError(
const RCLErrorBase & base_exc,
const std::string & prefix)
: RCLErrorBase(base_exc), std::runtime_error(prefix + base_exc.formatted_message)
{}
} // namespace exceptions
} // namespace rclcpp

View File

@@ -234,7 +234,7 @@ Executor::spin_some(std::chrono::nanoseconds max_duration)
throw std::runtime_error("spin_some() called while already spinning");
}
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
while (spinning.load() && max_duration_not_elapsed()) {
while (rclcpp::ok(context_) && spinning.load() && max_duration_not_elapsed()) {
AnyExecutable any_exec;
if (get_next_executable(any_exec, std::chrono::milliseconds::zero())) {
execute_any_executable(any_exec);
@@ -244,6 +244,15 @@ Executor::spin_some(std::chrono::nanoseconds max_duration)
}
}
void
Executor::spin_once_impl(std::chrono::nanoseconds timeout)
{
AnyExecutable any_exec;
if (get_next_executable(any_exec, timeout)) {
execute_any_executable(any_exec);
}
}
void
Executor::spin_once(std::chrono::nanoseconds timeout)
{
@@ -251,10 +260,7 @@ Executor::spin_once(std::chrono::nanoseconds timeout)
throw std::runtime_error("spin_once() called while already spinning");
}
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
AnyExecutable any_exec;
if (get_next_executable(any_exec, timeout)) {
execute_any_executable(any_exec);
}
spin_once_impl(timeout);
}
void
@@ -517,23 +523,48 @@ Executor::get_group_by_timer(rclcpp::TimerBase::SharedPtr timer)
if (!group) {
continue;
}
auto timer_ref = group->find_timer_ptrs_if(
[timer](const rclcpp::TimerBase::SharedPtr & timer_ptr) -> bool {
return timer_ptr == timer;
});
if (timer_ref) {
return group;
for (auto & weak_timer : group->get_timer_ptrs()) {
auto t = weak_timer.lock();
if (t == timer) {
return group;
}
}
}
}
return rclcpp::callback_group::CallbackGroup::SharedPtr();
}
void
Executor::get_next_timer(AnyExecutable & any_exec)
{
for (auto & weak_node : weak_nodes_) {
auto node = weak_node.lock();
if (!node) {
continue;
}
for (auto & weak_group : node->get_callback_groups()) {
auto group = weak_group.lock();
if (!group || !group->can_be_taken_from().load()) {
continue;
}
for (auto & timer_ref : group->get_timer_ptrs()) {
auto timer = timer_ref.lock();
if (timer && timer->is_ready()) {
any_exec.timer = timer;
any_exec.callback_group = group;
node = get_node_by_group(group);
return;
}
}
}
}
}
bool
Executor::get_next_ready_executable(AnyExecutable & any_executable)
{
// Check the timers to see if there are any that are ready
memory_strategy_->get_next_timer(any_executable, weak_nodes_);
// Check the timers to see if there are any that are ready, if so return
get_next_timer(any_executable);
if (any_executable.timer) {
return true;
}

View File

@@ -27,11 +27,8 @@ using rclcpp::executors::MultiThreadedExecutor;
MultiThreadedExecutor::MultiThreadedExecutor(
const rclcpp::executor::ExecutorArgs & args,
size_t number_of_threads,
bool yield_before_execute,
std::chrono::nanoseconds next_exec_timeout)
: executor::Executor(args),
yield_before_execute_(yield_before_execute),
next_exec_timeout_(next_exec_timeout)
bool yield_before_execute)
: executor::Executor(args), yield_before_execute_(yield_before_execute)
{
number_of_threads_ = number_of_threads ? number_of_threads : std::thread::hardware_concurrency();
if (number_of_threads_ == 0) {
@@ -80,7 +77,7 @@ MultiThreadedExecutor::run(size_t)
if (!rclcpp::ok(this->context_) || !spinning.load()) {
return;
}
if (!get_next_executable(any_exec, next_exec_timeout_)) {
if (!get_next_executable(any_exec)) {
continue;
}
if (any_exec.timer) {

View File

@@ -32,14 +32,16 @@ MemoryStrategy::get_subscription_by_handle(
if (!group) {
continue;
}
auto match_subscription = group->find_subscription_ptrs_if(
[&subscriber_handle](const rclcpp::SubscriptionBase::SharedPtr & subscription) -> bool {
return
(subscription->get_subscription_handle() == subscriber_handle) ||
(subscription->get_intra_process_subscription_handle() == subscriber_handle);
});
if (match_subscription) {
return match_subscription;
for (auto & weak_subscription : group->get_subscription_ptrs()) {
auto subscription = weak_subscription.lock();
if (subscription) {
if (subscription->get_subscription_handle() == subscriber_handle) {
return subscription;
}
if (subscription->get_intra_process_subscription_handle() == subscriber_handle) {
return subscription;
}
}
}
}
}
@@ -61,12 +63,11 @@ MemoryStrategy::get_service_by_handle(
if (!group) {
continue;
}
auto service_ref = group->find_service_ptrs_if(
[&service_handle](const rclcpp::ServiceBase::SharedPtr & service) -> bool {
return service->get_service_handle() == service_handle;
});
if (service_ref) {
return service_ref;
for (auto & weak_service : group->get_service_ptrs()) {
auto service = weak_service.lock();
if (service && service->get_service_handle() == service_handle) {
return service;
}
}
}
}
@@ -88,39 +89,11 @@ MemoryStrategy::get_client_by_handle(
if (!group) {
continue;
}
auto client_ref = group->find_client_ptrs_if(
[&client_handle](const rclcpp::ClientBase::SharedPtr & client) -> bool {
return client->get_client_handle() == client_handle;
});
if (client_ref) {
return client_ref;
}
}
}
return nullptr;
}
rclcpp::TimerBase::SharedPtr
MemoryStrategy::get_timer_by_handle(
std::shared_ptr<const rcl_timer_t> timer_handle,
const WeakNodeList & weak_nodes)
{
for (auto & weak_node : weak_nodes) {
auto node = weak_node.lock();
if (!node) {
continue;
}
for (auto & weak_group : node->get_callback_groups()) {
auto group = weak_group.lock();
if (!group) {
continue;
}
auto timer_ref = group->find_timer_ptrs_if(
[&timer_handle](const rclcpp::TimerBase::SharedPtr & timer) -> bool {
return timer->get_timer_handle() == timer_handle;
});
if (timer_ref) {
return timer_ref;
for (auto & weak_client : group->get_client_ptrs()) {
auto client = weak_client.lock();
if (client && client->get_client_handle() == client_handle) {
return client;
}
}
}
}
@@ -165,12 +138,11 @@ MemoryStrategy::get_group_by_subscription(
if (!group) {
continue;
}
auto match_sub = group->find_subscription_ptrs_if(
[&subscription](const rclcpp::SubscriptionBase::SharedPtr & sub) -> bool {
return sub == subscription;
});
if (match_sub) {
return group;
for (auto & weak_sub : group->get_subscription_ptrs()) {
auto sub = weak_sub.lock();
if (sub == subscription) {
return group;
}
}
}
}
@@ -192,12 +164,11 @@ MemoryStrategy::get_group_by_service(
if (!group) {
continue;
}
auto service_ref = group->find_service_ptrs_if(
[&service](const rclcpp::ServiceBase::SharedPtr & serv) -> bool {
return serv == service;
});
if (service_ref) {
return group;
for (auto & weak_serv : group->get_service_ptrs()) {
auto serv = weak_serv.lock();
if (serv && serv == service) {
return group;
}
}
}
}
@@ -219,39 +190,11 @@ MemoryStrategy::get_group_by_client(
if (!group) {
continue;
}
auto client_ref = group->find_client_ptrs_if(
[&client](const rclcpp::ClientBase::SharedPtr & cli) -> bool {
return cli == client;
});
if (client_ref) {
return group;
}
}
}
return nullptr;
}
rclcpp::callback_group::CallbackGroup::SharedPtr
MemoryStrategy::get_group_by_timer(
rclcpp::TimerBase::SharedPtr timer,
const WeakNodeList & weak_nodes)
{
for (auto & weak_node : weak_nodes) {
auto node = weak_node.lock();
if (!node) {
continue;
}
for (auto & weak_group : node->get_callback_groups()) {
auto group = weak_group.lock();
if (!group) {
continue;
}
auto timer_ref = group->find_timer_ptrs_if(
[&timer](const rclcpp::TimerBase::SharedPtr & time) -> bool {
return time == timer;
});
if (timer_ref) {
return group;
for (auto & weak_client : group->get_client_ptrs()) {
auto cli = weak_client.lock();
if (cli && cli == client) {
return group;
}
}
}
}
@@ -273,12 +216,11 @@ MemoryStrategy::get_group_by_waitable(
if (!group) {
continue;
}
auto waitable_ref = group->find_waitable_ptrs_if(
[&waitable](const rclcpp::Waitable::SharedPtr & group_waitable) -> bool {
return group_waitable == waitable;
});
if (waitable_ref) {
return group;
for (auto & weak_waitable : group->get_waitable_ptrs()) {
auto group_waitable = weak_waitable.lock();
if (group_waitable && group_waitable == waitable) {
return group;
}
}
}
}

View File

@@ -27,7 +27,17 @@
#include "rclcpp/node_interfaces/node_clock.hpp"
#include "rclcpp/node_interfaces/node_graph.hpp"
#include "rclcpp/node_interfaces/node_logging.hpp"
// When compiling this file, Windows produces a deprecation warning for the
// deprecated function prototype of NodeParameters::register_param_change_callback().
// Other compilers do not.
#if defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
#include "rclcpp/node_interfaces/node_parameters.hpp"
#if defined(_WIN32)
# pragma warning(pop)
#endif
#include "rclcpp/node_interfaces/node_services.hpp"
#include "rclcpp/node_interfaces/node_time_source.hpp"
#include "rclcpp/node_interfaces/node_timers.hpp"
@@ -226,14 +236,9 @@ const rclcpp::ParameterValue &
Node::declare_parameter(
const std::string & name,
const rclcpp::ParameterValue & default_value,
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
bool ignore_override)
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor)
{
return this->node_parameters_->declare_parameter(
name,
default_value,
parameter_descriptor,
ignore_override);
return this->node_parameters_->declare_parameter(name, default_value, parameter_descriptor);
}
void
@@ -316,18 +321,6 @@ Node::list_parameters(const std::vector<std::string> & prefixes, uint64_t depth)
return node_parameters_->list_parameters(prefixes, depth);
}
rclcpp::Node::OnSetParametersCallbackHandle::SharedPtr
Node::add_on_set_parameters_callback(OnParametersSetCallbackType callback)
{
return node_parameters_->add_on_set_parameters_callback(callback);
}
void
Node::remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const callback)
{
return node_parameters_->remove_on_set_parameters_callback(callback);
}
rclcpp::Node::OnParametersSetCallbackType
Node::set_on_parameters_set_callback(rclcpp::Node::OnParametersSetCallbackType callback)
{

View File

@@ -137,8 +137,7 @@ NodeGraph::get_node_names() const
std::vector<std::string> nodes;
auto names_and_namespaces = get_node_names_and_namespaces();
std::transform(
names_and_namespaces.begin(),
std::transform(names_and_namespaces.begin(),
names_and_namespaces.end(),
std::back_inserter(nodes),
[](std::pair<std::string, std::string> nns) {
@@ -321,9 +320,11 @@ rclcpp::Event::SharedPtr
NodeGraph::get_graph_event()
{
auto event = rclcpp::Event::make_shared();
std::lock_guard<std::mutex> graph_changed_lock(graph_mutex_);
graph_events_.push_back(event);
graph_users_count_++;
{
std::lock_guard<std::mutex> graph_changed_lock(graph_mutex_);
graph_events_.push_back(event);
graph_users_count_++;
}
// on first call, add node to graph_listener_
if (should_add_to_graph_listener_.exchange(false)) {
graph_listener_->add_node(this);

View File

@@ -12,13 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// When compiling this file, Windows produces a deprecation warning for the
// deprecated function prototype of NodeParameters::register_param_change_callback().
// Other compilers do not.
#if defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
#include "rclcpp/node_interfaces/node_parameters.hpp"
#if defined(_WIN32)
# pragma warning(pop)
#endif
#include <rcl_yaml_param_parser/parser.h>
#include <cmath>
#include <cstdlib>
#include <functional>
#include <limits>
#include <map>
#include <memory>
@@ -84,37 +93,65 @@ NodeParameters::NodeParameters(
throw std::runtime_error("Need valid node options in NodeParameters");
}
std::vector<const rcl_arguments_t *> argument_sources;
// Get paths to yaml files containing initial parameter values
std::vector<std::string> yaml_paths;
auto get_yaml_paths = [&yaml_paths, &options](const rcl_arguments_t * args) {
int num_yaml_files = rcl_arguments_get_param_files_count(args);
if (num_yaml_files > 0) {
char ** param_files;
rcl_ret_t ret = rcl_arguments_get_param_files(args, options->allocator, &param_files);
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret);
}
auto cleanup_param_files = make_scope_exit(
[&param_files, &num_yaml_files, &options]() {
for (int i = 0; i < num_yaml_files; ++i) {
options->allocator.deallocate(param_files[i], options->allocator.state);
}
options->allocator.deallocate(param_files, options->allocator.state);
});
for (int i = 0; i < num_yaml_files; ++i) {
yaml_paths.emplace_back(param_files[i]);
}
}
};
// global before local so that local overwrites global
if (options->use_global_arguments) {
auto context_ptr = node_base->get_context()->get_rcl_context();
argument_sources.push_back(&(context_ptr->global_arguments));
get_yaml_paths(&(context_ptr->global_arguments));
}
argument_sources.push_back(&options->arguments);
get_yaml_paths(&(options->arguments));
// Get fully qualified node name post-remapping to use to find node's params in yaml files
combined_name_ = node_base->get_fully_qualified_name();
for (const rcl_arguments_t * source : argument_sources) {
rcl_params_t * params = NULL;
rcl_ret_t ret = rcl_arguments_get_param_overrides(source, &params);
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret);
// TODO(sloretz) use rcl to parse yaml when circular dependency is solved
// See https://github.com/ros2/rcl/issues/252
for (const std::string & yaml_path : yaml_paths) {
rcl_params_t * yaml_params = rcl_yaml_node_struct_init(options->allocator);
if (nullptr == yaml_params) {
throw std::bad_alloc();
}
if (params) {
auto cleanup_params = make_scope_exit(
[params]() {
rcl_yaml_node_struct_fini(params);
});
rclcpp::ParameterMap initial_map = rclcpp::parameter_map_from(params);
for (auto iter = initial_map.begin(); initial_map.end() != iter; iter++) {
// TODO(cottsay) implement further wildcard matching
if (iter->first == "/**" || iter->first == combined_name_) {
// Combine parameter yaml files, overwriting values in older ones
for (auto & param : iter->second) {
parameter_overrides_[param.get_name()] =
rclcpp::ParameterValue(param.get_value_message());
}
if (!rcl_parse_yaml_file(yaml_path.c_str(), yaml_params)) {
std::ostringstream ss;
ss << "Failed to parse parameters from file '" << yaml_path << "': " <<
rcl_get_error_string().str;
rcl_reset_error();
throw std::runtime_error(ss.str());
}
rclcpp::ParameterMap initial_map = rclcpp::parameter_map_from(yaml_params);
rcl_yaml_node_struct_fini(yaml_params);
for (auto iter = initial_map.begin(); initial_map.end() != iter; iter++) {
// TODO(cottsay) implement further wildcard matching
if (iter->first == "/**" || iter->first == combined_name_) {
// Combine parameter yaml files, overwriting values in older ones
for (auto & param : iter->second) {
parameter_overrides_[param.get_name()] =
rclcpp::ParameterValue(param.get_value_message());
}
}
}
@@ -134,8 +171,7 @@ NodeParameters::NodeParameters(
this->declare_parameter(
pair.first,
pair.second,
rcl_interfaces::msg::ParameterDescriptor(),
true);
rcl_interfaces::msg::ParameterDescriptor());
}
}
}
@@ -156,7 +192,7 @@ __lockless_has_parameter(
// see https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
RCLCPP_LOCAL
bool
__are_doubles_equal(double x, double y, size_t ulp = 100)
__are_doubles_equal(double x, double y, double ulp = 100.0)
{
return std::abs(x - y) <= std::numeric_limits<double>::epsilon() * std::abs(x + y) * ulp;
}
@@ -204,7 +240,9 @@ __check_parameter_value_in_range(
if (!descriptor.floating_point_range.empty() && value.get_type() == rclcpp::PARAMETER_DOUBLE) {
double v = value.get<double>();
auto fp_range = descriptor.floating_point_range.at(0);
if (__are_doubles_equal(v, fp_range.from_value) || __are_doubles_equal(v, fp_range.to_value)) {
if (__are_doubles_equal(v, fp_range.from_value) ||
__are_doubles_equal(v, fp_range.to_value))
{
return result;
}
if ((v < fp_range.from_value) || (v > fp_range.to_value)) {
@@ -250,50 +288,20 @@ __check_parameters(
using OnParametersSetCallbackType =
rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;
using CallbacksContainerType =
rclcpp::node_interfaces::NodeParameters::CallbacksContainerType;
using OnSetParametersCallbackHandle =
rclcpp::node_interfaces::OnSetParametersCallbackHandle;
RCLCPP_LOCAL
rcl_interfaces::msg::SetParametersResult
__call_on_parameters_set_callbacks(
const std::vector<rclcpp::Parameter> & parameters,
CallbacksContainerType & callback_container,
const OnParametersSetCallbackType & callback)
{
rcl_interfaces::msg::SetParametersResult result;
result.successful = true;
auto it = callback_container.begin();
while (it != callback_container.end()) {
auto shared_handle = it->lock();
if (nullptr != shared_handle) {
result = shared_handle->callback(parameters);
if (!result.successful) {
return result;
}
it++;
} else {
it = callback_container.erase(it);
}
}
if (callback) {
result = callback(parameters);
}
return result;
}
RCLCPP_LOCAL
rcl_interfaces::msg::SetParametersResult
__set_parameters_atomically_common(
const std::vector<rclcpp::Parameter> & parameters,
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameter_infos,
CallbacksContainerType & callback_container,
const OnParametersSetCallbackType & callback)
OnParametersSetCallbackType on_set_parameters_callback)
{
// Call the user callback to see if the new value(s) are allowed.
rcl_interfaces::msg::SetParametersResult result =
__call_on_parameters_set_callbacks(parameters, callback_container, callback);
rcl_interfaces::msg::SetParametersResult result;
result.successful = true;
if (on_set_parameters_callback) {
result = on_set_parameters_callback(parameters);
}
if (!result.successful) {
return result;
}
@@ -324,10 +332,9 @@ __declare_parameter_common(
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameters_out,
const std::map<std::string, rclcpp::ParameterValue> & overrides,
CallbacksContainerType & callback_container,
const OnParametersSetCallbackType & callback,
OnParametersSetCallbackType on_set_parameters_callback,
rcl_interfaces::msg::ParameterEvent * parameter_event_out,
bool ignore_override = false)
bool use_overrides = true)
{
using rclcpp::node_interfaces::ParameterInfo;
std::map<std::string, ParameterInfo> parameter_infos {{name, ParameterInfo()}};
@@ -336,7 +343,7 @@ __declare_parameter_common(
// Use the value from the overrides if available, otherwise use the default.
const rclcpp::ParameterValue * initial_value = &default_value;
auto overrides_it = overrides.find(name);
if (!ignore_override && overrides_it != overrides.end()) {
if (use_overrides && overrides_it != overrides.end()) {
initial_value = &overrides_it->second;
}
@@ -346,8 +353,7 @@ __declare_parameter_common(
auto result = __set_parameters_atomically_common(
parameter_wrappers,
parameter_infos,
callback_container,
callback);
on_set_parameters_callback);
// Add declared parameters to storage.
parameters_out[name] = parameter_infos.at(name);
@@ -364,12 +370,9 @@ const rclcpp::ParameterValue &
NodeParameters::declare_parameter(
const std::string & name,
const rclcpp::ParameterValue & default_value,
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
bool ignore_override)
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor)
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
std::lock_guard<std::mutex> lock(mutex_);
// TODO(sloretz) parameter name validation
if (name.empty()) {
@@ -389,10 +392,8 @@ NodeParameters::declare_parameter(
parameter_descriptor,
parameters_,
parameter_overrides_,
on_parameters_set_callback_container_,
on_parameters_set_callback_,
&parameter_event,
ignore_override);
&parameter_event);
// If it failed to be set, then throw an exception.
if (!result.successful) {
@@ -411,9 +412,7 @@ NodeParameters::declare_parameter(
void
NodeParameters::undeclare_parameter(const std::string & name)
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
std::lock_guard<std::mutex> lock(mutex_);
auto parameter_info = parameters_.find(name);
if (parameter_info == parameters_.end()) {
@@ -432,7 +431,7 @@ NodeParameters::undeclare_parameter(const std::string & name)
bool
NodeParameters::has_parameter(const std::string & name) const
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
std::lock_guard<std::mutex> lock(mutex_);
return __lockless_has_parameter(parameters_, name);
}
@@ -466,9 +465,7 @@ __find_parameter_by_name(
rcl_interfaces::msg::SetParametersResult
NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> & parameters)
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
std::lock_guard<std::mutex> lock(mutex_);
rcl_interfaces::msg::SetParametersResult result;
@@ -517,7 +514,6 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> staged_parameter_changes;
rcl_interfaces::msg::ParameterEvent parameter_event_msg;
parameter_event_msg.node = combined_name_;
CallbacksContainerType empty_callback_container;
for (auto parameter_to_be_declared : parameters_to_be_declared) {
// This should not throw, because we validated the name and checked that
// the parameter was not already declared.
@@ -527,11 +523,9 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
rcl_interfaces::msg::ParameterDescriptor(), // Implicit declare uses default descriptor.
staged_parameter_changes,
parameter_overrides_,
// Only call callbacks once below
empty_callback_container, // callback_container is explicitly empty
nullptr, // callback is explicitly null.
nullptr, // callback is explicitly null, so that it is called only once, when setting below.
&parameter_event_msg,
true);
false);
if (!result.successful) {
// Declare failed, return knowing that nothing was changed because the
// staged changes were not applied.
@@ -578,16 +572,13 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
}
}
// Set all of the parameters including the ones declared implicitly above.
// Set the all of the parameters including the ones declared implicitly above.
result = __set_parameters_atomically_common(
// either the original parameters given by the user, or ones updated with initial values
*parameters_to_be_set,
// they are actually set on the official parameter storage
parameters_,
// this will get called once, with all the parameters to be set
on_parameters_set_callback_container_,
// These callbacks are called once. When a callback returns an unsuccessful result,
// the remaining aren't called.
on_parameters_set_callback_);
// If not successful, then stop here.
@@ -650,7 +641,7 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
std::vector<rclcpp::Parameter>
NodeParameters::get_parameters(const std::vector<std::string> & names) const
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
std::lock_guard<std::mutex> lock(mutex_);
std::vector<rclcpp::Parameter> results;
results.reserve(names.size());
@@ -689,7 +680,7 @@ NodeParameters::get_parameter(
const std::string & name,
rclcpp::Parameter & parameter) const
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
std::lock_guard<std::mutex> lock(mutex_);
auto param_iter = parameters_.find(name);
if (
@@ -708,7 +699,7 @@ NodeParameters::get_parameters_by_prefix(
const std::string & prefix,
std::map<std::string, rclcpp::Parameter> & parameters) const
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
std::lock_guard<std::mutex> lock(mutex_);
std::string prefix_with_dot = prefix.empty() ? prefix : prefix + ".";
bool ret = false;
@@ -727,7 +718,7 @@ NodeParameters::get_parameters_by_prefix(
std::vector<rcl_interfaces::msg::ParameterDescriptor>
NodeParameters::describe_parameters(const std::vector<std::string> & names) const
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
std::lock_guard<std::mutex> lock(mutex_);
std::vector<rcl_interfaces::msg::ParameterDescriptor> results;
results.reserve(names.size());
@@ -755,7 +746,7 @@ NodeParameters::describe_parameters(const std::vector<std::string> & names) cons
std::vector<uint8_t>
NodeParameters::get_parameter_types(const std::vector<std::string> & names) const
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
std::lock_guard<std::mutex> lock(mutex_);
std::vector<uint8_t> results;
results.reserve(names.size());
@@ -781,7 +772,7 @@ NodeParameters::get_parameter_types(const std::vector<std::string> & names) cons
rcl_interfaces::msg::ListParametersResult
NodeParameters::list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
std::lock_guard<std::mutex> lock(mutex_);
rcl_interfaces::msg::ListParametersResult result;
// TODO(mikaelarguedas) define parameter separator different from "/" to avoid ambiguity
@@ -791,27 +782,25 @@ NodeParameters::list_parameters(const std::vector<std::string> & prefixes, uint6
bool get_all = (prefixes.size() == 0) &&
((depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) ||
(static_cast<uint64_t>(std::count(kv.first.begin(), kv.first.end(), *separator)) < depth));
bool prefix_matches = std::any_of(
prefixes.cbegin(), prefixes.cend(),
[&kv, &depth, &separator](const std::string & prefix) {
if (kv.first == prefix) {
return true;
} else if (kv.first.find(prefix + separator) == 0) {
size_t length = prefix.length();
std::string substr = kv.first.substr(length);
// Cast as unsigned integer to avoid warning
return (depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) ||
(static_cast<uint64_t>(std::count(substr.begin(), substr.end(), *separator)) < depth);
}
return false;
});
bool prefix_matches = std::any_of(prefixes.cbegin(), prefixes.cend(),
[&kv, &depth, &separator](const std::string & prefix) {
if (kv.first == prefix) {
return true;
} else if (kv.first.find(prefix + separator) == 0) {
size_t length = prefix.length();
std::string substr = kv.first.substr(length);
// Cast as unsigned integer to avoid warning
return (depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) ||
(static_cast<uint64_t>(std::count(substr.begin(), substr.end(), *separator)) < depth);
}
return false;
});
if (get_all || prefix_matches) {
result.names.push_back(kv.first);
size_t last_separator = kv.first.find_last_of(separator);
if (std::string::npos != last_separator) {
std::string prefix = kv.first.substr(0, last_separator);
if (
std::find(result.prefixes.cbegin(), result.prefixes.cend(), prefix) ==
if (std::find(result.prefixes.cbegin(), result.prefixes.cend(), prefix) ==
result.prefixes.cend())
{
result.prefixes.push_back(prefix);
@@ -822,65 +811,37 @@ NodeParameters::list_parameters(const std::vector<std::string> & prefixes, uint6
return result;
}
struct HandleCompare
: public std::unary_function<OnSetParametersCallbackHandle::WeakPtr, bool>
{
explicit HandleCompare(const OnSetParametersCallbackHandle * const base)
: base_(base) {}
bool operator()(const OnSetParametersCallbackHandle::WeakPtr & handle)
{
auto shared_handle = handle.lock();
if (base_ == shared_handle.get()) {
return true;
}
return false;
}
const OnSetParametersCallbackHandle * const base_;
};
void
NodeParameters::remove_on_set_parameters_callback(
const OnSetParametersCallbackHandle * const handle)
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
auto it = std::find_if(
on_parameters_set_callback_container_.begin(),
on_parameters_set_callback_container_.end(),
HandleCompare(handle));
if (it != on_parameters_set_callback_container_.end()) {
on_parameters_set_callback_container_.erase(it);
} else {
throw std::runtime_error("Callback doesn't exist");
}
}
OnSetParametersCallbackHandle::SharedPtr
NodeParameters::add_on_set_parameters_callback(OnParametersSetCallbackType callback)
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
auto handle = std::make_shared<OnSetParametersCallbackHandle>();
handle->callback = callback;
// the last callback registered is executed first.
on_parameters_set_callback_container_.emplace_front(handle);
return handle;
}
NodeParameters::OnParametersSetCallbackType
NodeParameters::set_on_parameters_set_callback(OnParametersSetCallbackType callback)
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
auto existing_callback = on_parameters_set_callback_;
on_parameters_set_callback_ = callback;
return existing_callback;
}
#if !defined(_WIN32)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else // !defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
void
NodeParameters::register_param_change_callback(ParametersCallbackFunction callback)
{
if (on_parameters_set_callback_) {
RCLCPP_WARN(
node_logging_->get_logger(),
"on_parameters_set_callback already registered, overwriting previous callback");
}
on_parameters_set_callback_ = callback;
}
#if !defined(_WIN32)
# pragma GCC diagnostic pop
#else // !defined(_WIN32)
# pragma warning(pop)
#endif
const std::map<std::string, rclcpp::ParameterValue> &
NodeParameters::get_parameter_overrides() const
{

View File

@@ -34,10 +34,36 @@ rclcpp::PublisherBase::SharedPtr
NodeTopics::create_publisher(
const std::string & topic_name,
const rclcpp::PublisherFactory & publisher_factory,
const rclcpp::QoS & qos)
const rcl_publisher_options_t & publisher_options,
bool use_intra_process)
{
// Create the MessageT specific Publisher using the factory, but return it as PublisherBase.
return publisher_factory.create_typed_publisher(node_base_, topic_name, qos);
// Create the MessageT specific Publisher using the factory, but store it as PublisherBase.
auto publisher = publisher_factory.create_typed_publisher(
node_base_, topic_name, publisher_options);
// Setup intra process publishing if requested.
if (use_intra_process) {
auto context = node_base_->get_context();
// Get the intra process manager instance for this context.
auto ipm = context->get_sub_context<rclcpp::intra_process_manager::IntraProcessManager>();
// Register the publisher with the intra process manager.
if (publisher_options.qos.history == RMW_QOS_POLICY_HISTORY_KEEP_ALL) {
throw std::invalid_argument(
"intraprocess communication is not allowed with keep all history qos policy");
}
if (publisher_options.qos.depth == 0) {
throw std::invalid_argument(
"intraprocess communication is not allowed with a zero qos history depth value");
}
uint64_t intra_process_publisher_id = ipm->add_publisher(publisher);
publisher->setup_intra_process(
intra_process_publisher_id,
ipm,
publisher_options);
}
// Return the completed publisher.
return publisher;
}
void
@@ -73,10 +99,25 @@ rclcpp::SubscriptionBase::SharedPtr
NodeTopics::create_subscription(
const std::string & topic_name,
const rclcpp::SubscriptionFactory & subscription_factory,
const rclcpp::QoS & qos)
const rcl_subscription_options_t & subscription_options,
bool use_intra_process)
{
// Create the MessageT specific Subscription using the factory, but return a SubscriptionBase.
return subscription_factory.create_typed_subscription(node_base_, topic_name, qos);
auto subscription = subscription_factory.create_typed_subscription(
node_base_, topic_name, subscription_options);
// Setup intra process publishing if requested.
if (use_intra_process) {
auto context = node_base_->get_context();
auto ipm =
context->get_sub_context<rclcpp::intra_process_manager::IntraProcessManager>();
uint64_t intra_process_subscription_id = ipm->add_subscription(subscription);
auto options_copy = subscription_options;
options_copy.ignore_local_publications = false;
subscription->setup_intra_process(intra_process_subscription_id, ipm, options_copy);
}
// Return the completed subscription.
return subscription;
}
void

View File

@@ -18,7 +18,6 @@
#include <memory>
#include <string>
#include <vector>
#include <utility>
#include "rclcpp/exceptions.hpp"
#include "rclcpp/logging.hpp"
@@ -66,16 +65,20 @@ NodeOptions &
NodeOptions::operator=(const NodeOptions & other)
{
if (this != &other) {
this->node_options_.reset();
this->context_ = other.context_;
this->arguments_ = other.arguments_;
this->parameter_overrides_ = other.parameter_overrides_;
this->use_global_arguments_ = other.use_global_arguments_;
this->use_intra_process_comms_ = other.use_intra_process_comms_;
this->start_parameter_services_ = other.start_parameter_services_;
this->allocator_ = other.allocator_;
this->start_parameter_event_publisher_ = other.start_parameter_event_publisher_;
this->parameter_event_qos_ = other.parameter_event_qos_;
this->parameter_event_publisher_options_ = other.parameter_event_publisher_options_;
this->allow_undeclared_parameters_ = other.allow_undeclared_parameters_;
this->automatically_declare_parameters_from_overrides_ =
other.automatically_declare_parameters_from_overrides_;
this->allocator_ = other.allocator_;
}
return *this;
}
@@ -91,48 +94,25 @@ NodeOptions::get_rcl_node_options() const
node_options_->use_global_arguments = this->use_global_arguments_;
node_options_->domain_id = this->get_domain_id_from_env();
int c_argc = 0;
std::unique_ptr<const char *[]> c_argv;
std::unique_ptr<const char *[]> c_args;
if (!this->arguments_.empty()) {
if (this->arguments_.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
throw_from_rcl_error(RCL_RET_INVALID_ARGUMENT, "Too many args");
}
c_argc = static_cast<int>(this->arguments_.size());
c_argv.reset(new const char *[c_argc]);
c_args.reset(new const char *[this->arguments_.size()]);
for (std::size_t i = 0; i < this->arguments_.size(); ++i) {
c_argv[i] = this->arguments_[i].c_str();
c_args[i] = this->arguments_[i].c_str();
}
}
rcl_ret_t ret = rcl_parse_arguments(
c_argc, c_argv.get(), this->allocator_, &(node_options_->arguments));
if (this->arguments_.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
throw_from_rcl_error(RCL_RET_INVALID_ARGUMENT, "Too many args");
}
rmw_ret_t ret = rcl_parse_arguments(
static_cast<int>(this->arguments_.size()), c_args.get(), this->allocator_,
&(node_options_->arguments));
if (RCL_RET_OK != ret) {
throw_from_rcl_error(ret, "failed to parse arguments");
}
int unparsed_ros_args_count =
rcl_arguments_get_count_unparsed_ros(&(node_options_->arguments));
if (unparsed_ros_args_count > 0) {
int * unparsed_ros_args_indices = nullptr;
ret = rcl_arguments_get_unparsed_ros(
&(node_options_->arguments), this->allocator_, &unparsed_ros_args_indices);
if (RCL_RET_OK != ret) {
throw_from_rcl_error(ret, "failed to get unparsed ROS arguments");
}
try {
std::vector<std::string> unparsed_ros_args;
for (int i = 0; i < unparsed_ros_args_count; ++i) {
unparsed_ros_args.push_back(c_argv[unparsed_ros_args_indices[i]]);
}
throw exceptions::UnknownROSArgsError(std::move(unparsed_ros_args));
} catch (...) {
this->allocator_.deallocate(unparsed_ros_args_indices, this->allocator_.state);
throw;
}
}
}
return node_options_.get();
@@ -187,7 +167,7 @@ NodeOptions::parameter_overrides(const std::vector<rclcpp::Parameter> & paramete
bool
NodeOptions::use_global_arguments() const
{
return this->node_options_->use_global_arguments;
return this->use_global_arguments_;
}
NodeOptions &
@@ -322,7 +302,7 @@ NodeOptions::get_domain_id_from_env() const
_dupenv_s(&ros_domain_id, &ros_domain_id_size, env_var);
#endif
if (ros_domain_id) {
uint32_t number = strtoul(ros_domain_id, NULL, 0);
uint32_t number = static_cast<uint32_t>(strtoul(ros_domain_id, NULL, 0));
if (number == (std::numeric_limits<uint32_t>::max)()) {
#ifdef _WIN32
// free the ros_domain_id before throwing, if getenv was used on Windows

View File

@@ -19,7 +19,17 @@
#include <string>
#include <vector>
// When compiling this file, Windows produces a deprecation warning for the
// deprecated function prototype of NodeParameters::register_param_change_callback().
// Other compilers do not.
#if defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
#include "rclcpp/node_interfaces/node_parameters.hpp"
#if defined(_WIN32)
# pragma warning(pop)
#endif
#include "rclcpp/utilities.hpp"
using rclcpp::ParameterType;

View File

@@ -30,8 +30,7 @@ AsyncParametersClient::AsyncParametersClient(
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
const rmw_qos_profile_t & qos_profile)
: node_topics_interface_(node_topics_interface)
{
if (remote_node_name != "") {
@@ -52,7 +51,7 @@ AsyncParametersClient::AsyncParametersClient(
remote_node_name_ + "/" + parameter_service_names::get_parameters,
options);
auto get_parameters_base = std::dynamic_pointer_cast<ClientBase>(get_parameters_client_);
node_services_interface->add_client(get_parameters_base, group);
node_services_interface->add_client(get_parameters_base, nullptr);
get_parameter_types_client_ = Client<rcl_interfaces::srv::GetParameterTypes>::make_shared(
node_base_interface.get(),
@@ -61,7 +60,7 @@ AsyncParametersClient::AsyncParametersClient(
options);
auto get_parameter_types_base =
std::dynamic_pointer_cast<ClientBase>(get_parameter_types_client_);
node_services_interface->add_client(get_parameter_types_base, group);
node_services_interface->add_client(get_parameter_types_base, nullptr);
set_parameters_client_ = Client<rcl_interfaces::srv::SetParameters>::make_shared(
node_base_interface.get(),
@@ -69,17 +68,16 @@ AsyncParametersClient::AsyncParametersClient(
remote_node_name_ + "/" + parameter_service_names::set_parameters,
options);
auto set_parameters_base = std::dynamic_pointer_cast<ClientBase>(set_parameters_client_);
node_services_interface->add_client(set_parameters_base, group);
node_services_interface->add_client(set_parameters_base, nullptr);
set_parameters_atomically_client_ =
Client<rcl_interfaces::srv::SetParametersAtomically>::make_shared(
node_base_interface.get(),
node_graph_interface,
remote_node_name_ + "/" + parameter_service_names::set_parameters_atomically,
options);
Client<rcl_interfaces::srv::SetParametersAtomically>::make_shared(node_base_interface.get(),
node_graph_interface,
remote_node_name_ + "/" + parameter_service_names::set_parameters_atomically,
options);
auto set_parameters_atomically_base = std::dynamic_pointer_cast<ClientBase>(
set_parameters_atomically_client_);
node_services_interface->add_client(set_parameters_atomically_base, group);
node_services_interface->add_client(set_parameters_atomically_base, nullptr);
list_parameters_client_ = Client<rcl_interfaces::srv::ListParameters>::make_shared(
node_base_interface.get(),
@@ -87,7 +85,7 @@ AsyncParametersClient::AsyncParametersClient(
remote_node_name_ + "/" + parameter_service_names::list_parameters,
options);
auto list_parameters_base = std::dynamic_pointer_cast<ClientBase>(list_parameters_client_);
node_services_interface->add_client(list_parameters_base, group);
node_services_interface->add_client(list_parameters_base, nullptr);
describe_parameters_client_ = Client<rcl_interfaces::srv::DescribeParameters>::make_shared(
node_base_interface.get(),
@@ -96,37 +94,33 @@ AsyncParametersClient::AsyncParametersClient(
options);
auto describe_parameters_base =
std::dynamic_pointer_cast<ClientBase>(describe_parameters_client_);
node_services_interface->add_client(describe_parameters_base, group);
node_services_interface->add_client(describe_parameters_base, nullptr);
}
AsyncParametersClient::AsyncParametersClient(
const rclcpp::Node::SharedPtr node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
const rmw_qos_profile_t & qos_profile)
: AsyncParametersClient(
node->get_node_base_interface(),
node->get_node_topics_interface(),
node->get_node_graph_interface(),
node->get_node_services_interface(),
remote_node_name,
qos_profile,
group)
qos_profile)
{}
AsyncParametersClient::AsyncParametersClient(
rclcpp::Node * node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
const rmw_qos_profile_t & qos_profile)
: AsyncParametersClient(
node->get_node_base_interface(),
node->get_node_topics_interface(),
node->get_node_graph_interface(),
node->get_node_services_interface(),
remote_node_name,
qos_profile,
group)
qos_profile)
{}
std::shared_future<std::vector<rclcpp::Parameter>>
@@ -152,11 +146,12 @@ AsyncParametersClient::get_parameters(
auto & pvalues = cb_f.get()->values;
for (auto & pvalue : pvalues) {
auto i = &pvalue - &pvalues[0];
auto i = static_cast<size_t>(&pvalue - &pvalues[0]);
rcl_interfaces::msg::Parameter parameter;
parameter.name = request->names[i];
parameter.value = pvalue;
parameters.push_back(rclcpp::Parameter::from_parameter_msg(parameter));
parameters.push_back(rclcpp::Parameter::from_parameter_msg(
parameter));
}
promise_result->set_value(parameters);
@@ -216,9 +211,10 @@ AsyncParametersClient::set_parameters(
auto request = std::make_shared<rcl_interfaces::srv::SetParameters::Request>();
std::transform(
parameters.begin(), parameters.end(), std::back_inserter(request->parameters),
[](rclcpp::Parameter p) {return p.to_parameter_msg();}
std::transform(parameters.begin(), parameters.end(), std::back_inserter(request->parameters),
[](rclcpp::Parameter p) {
return p.to_parameter_msg();
}
);
set_parameters_client_->async_send_request(
@@ -249,9 +245,10 @@ AsyncParametersClient::set_parameters_atomically(
auto request = std::make_shared<rcl_interfaces::srv::SetParametersAtomically::Request>();
std::transform(
parameters.begin(), parameters.end(), std::back_inserter(request->parameters),
[](rclcpp::Parameter p) {return p.to_parameter_msg();}
std::transform(parameters.begin(), parameters.end(), std::back_inserter(request->parameters),
[](rclcpp::Parameter p) {
return p.to_parameter_msg();
}
);
set_parameters_atomically_client_->async_send_request(
@@ -414,10 +411,8 @@ SyncParametersClient::get_parameters(const std::vector<std::string> & parameter_
{
auto f = async_parameters_client_->get_parameters(parameter_names);
using rclcpp::executors::spin_node_until_future_complete;
if (
spin_node_until_future_complete(
*executor_, node_base_interface_,
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
if (spin_node_until_future_complete(*executor_, node_base_interface_, f) ==
rclcpp::executor::FutureReturnCode::SUCCESS)
{
return f.get();
}
@@ -440,10 +435,8 @@ SyncParametersClient::get_parameter_types(const std::vector<std::string> & param
auto f = async_parameters_client_->get_parameter_types(parameter_names);
using rclcpp::executors::spin_node_until_future_complete;
if (
spin_node_until_future_complete(
*executor_, node_base_interface_,
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
if (spin_node_until_future_complete(*executor_, node_base_interface_, f) ==
rclcpp::executor::FutureReturnCode::SUCCESS)
{
return f.get();
}
@@ -457,10 +450,8 @@ SyncParametersClient::set_parameters(
auto f = async_parameters_client_->set_parameters(parameters);
using rclcpp::executors::spin_node_until_future_complete;
if (
spin_node_until_future_complete(
*executor_, node_base_interface_,
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
if (spin_node_until_future_complete(*executor_, node_base_interface_, f) ==
rclcpp::executor::FutureReturnCode::SUCCESS)
{
return f.get();
}
@@ -474,10 +465,8 @@ SyncParametersClient::set_parameters_atomically(
auto f = async_parameters_client_->set_parameters_atomically(parameters);
using rclcpp::executors::spin_node_until_future_complete;
if (
spin_node_until_future_complete(
*executor_, node_base_interface_,
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
if (spin_node_until_future_complete(*executor_, node_base_interface_, f) ==
rclcpp::executor::FutureReturnCode::SUCCESS)
{
return f.get();
}
@@ -493,10 +482,8 @@ SyncParametersClient::list_parameters(
auto f = async_parameters_client_->list_parameters(parameter_prefixes, depth);
using rclcpp::executors::spin_node_until_future_complete;
if (
spin_node_until_future_complete(
*executor_, node_base_interface_,
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
if (spin_node_until_future_complete(*executor_, node_base_interface_, f) ==
rclcpp::executor::FutureReturnCode::SUCCESS)
{
return f.get();
}

View File

@@ -59,11 +59,10 @@ ParameterService::ParameterService(
{
try {
auto types = node_params->get_parameter_types(request->names);
std::transform(
types.cbegin(), types.cend(),
std::back_inserter(response->types), [](const uint8_t & type) {
return static_cast<rclcpp::ParameterType>(type);
});
std::transform(types.cbegin(), types.cend(),
std::back_inserter(response->types), [](const uint8_t & type) {
return static_cast<rclcpp::ParameterType>(type);
});
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to get parameter types: %s", ex.what());
}
@@ -104,12 +103,11 @@ ParameterService::ParameterService(
std::shared_ptr<rcl_interfaces::srv::SetParametersAtomically::Response> response)
{
std::vector<rclcpp::Parameter> pvariants;
std::transform(
request->parameters.cbegin(), request->parameters.cend(),
std::back_inserter(pvariants),
[](const rcl_interfaces::msg::Parameter & p) {
return rclcpp::Parameter::from_parameter_msg(p);
});
std::transform(request->parameters.cbegin(), request->parameters.cend(),
std::back_inserter(pvariants),
[](const rcl_interfaces::msg::Parameter & p) {
return rclcpp::Parameter::from_parameter_msg(p);
});
try {
auto result = node_params->set_parameters_atomically(pvariants);
response->result = result;

View File

@@ -154,7 +154,7 @@ ParameterValue::ParameterValue(const int64_t int_value)
ParameterValue::ParameterValue(const float double_value)
{
value_.double_value = double_value;
value_.double_value = static_cast<double>(double_value);
value_.type = rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE;
}

View File

@@ -23,7 +23,6 @@
#include "rclcpp/expand_topic_or_service_name.hpp"
#include "rclcpp/intra_process_manager.hpp"
#include "rclcpp/logging.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rmw/error_handling.h"
#include "rmw/rmw.h"
@@ -31,18 +30,18 @@
using rclcpp::SubscriptionBase;
SubscriptionBase::SubscriptionBase(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
std::shared_ptr<rcl_node_t> node_handle,
const rosidl_message_type_support_t & type_support_handle,
const std::string & topic_name,
const rcl_subscription_options_t & subscription_options,
bool is_serialized)
: node_handle_(node_base->get_shared_rcl_node_handle()),
: node_handle_(node_handle),
use_intra_process_(false),
intra_process_subscription_id_(0),
type_support_(type_support_handle),
is_serialized_(is_serialized)
{
auto custom_deletor = [node_handle = this->node_handle_](rcl_subscription_t * rcl_subs)
auto custom_deletor = [node_handle](rcl_subscription_t * rcl_subs)
{
if (rcl_subscription_fini(rcl_subs, node_handle.get()) != RCL_RET_OK) {
RCLCPP_ERROR(
@@ -129,18 +128,6 @@ SubscriptionBase::get_event_handlers() const
return event_handlers_;
}
rmw_qos_profile_t
SubscriptionBase::get_actual_qos() const
{
const rmw_qos_profile_t * qos = rcl_subscription_get_actual_qos(subscription_handle_.get());
if (!qos) {
auto msg = std::string("failed to get qos settings: ") + rcl_get_error_string().str;
rcl_reset_error();
throw std::runtime_error(msg);
}
return *qos;
}
const rosidl_message_type_support_t &
SubscriptionBase::get_message_type_support_handle() const
{
@@ -168,8 +155,7 @@ SubscriptionBase::get_publisher_count() const
return inter_process_publisher_count;
}
void
SubscriptionBase::setup_intra_process(
void SubscriptionBase::setup_intra_process(
uint64_t intra_process_subscription_id,
IntraProcessManagerWeakPtr weak_ipm,
const rcl_subscription_options_t & intra_process_options)

View File

@@ -13,7 +13,6 @@
// limitations under the License.
#include <limits>
#include <string>
#include <utility>
#include "rclcpp/clock.hpp"
@@ -63,17 +62,13 @@ Time::Time(int64_t nanoseconds, rcl_clock_type_t clock_type)
rcl_time_.nanoseconds = nanoseconds;
}
Time::Time(const Time & rhs)
: rcl_time_(rhs.rcl_time_)
{
rcl_time_.nanoseconds = rhs.rcl_time_.nanoseconds;
}
Time::Time(const Time & rhs) = default;
Time::Time(
const builtin_interfaces::msg::Time & time_msg,
rcl_clock_type_t ros_time)
rcl_clock_type_t clock_type)
: rcl_time_(init_time_point(clock_type))
{
rcl_time_ = init_time_point(ros_time);
if (time_msg.sec < 0) {
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
}
@@ -95,31 +90,25 @@ Time::~Time()
Time::operator builtin_interfaces::msg::Time() const
{
builtin_interfaces::msg::Time msg_time;
msg_time.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_time_.nanoseconds));
msg_time.nanosec = static_cast<std::uint32_t>(rcl_time_.nanoseconds % (1000 * 1000 * 1000));
constexpr rcl_time_point_value_t kRemainder = RCL_S_TO_NS(1);
const auto result = std::div(rcl_time_.nanoseconds, kRemainder);
if (result.rem >= 0) {
msg_time.sec = static_cast<std::int32_t>(result.quot);
msg_time.nanosec = static_cast<std::uint32_t>(result.rem);
} else {
msg_time.sec = static_cast<std::int32_t>(result.quot - 1);
msg_time.nanosec = static_cast<std::uint32_t>(kRemainder + result.rem);
}
return msg_time;
}
Time &
Time::operator=(const Time & rhs)
{
rcl_time_ = rhs.rcl_time_;
return *this;
}
Time::operator=(const Time & rhs) = default;
Time &
Time::operator=(const builtin_interfaces::msg::Time & time_msg)
{
if (time_msg.sec < 0) {
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
}
rcl_clock_type_t ros_time = RCL_ROS_TIME;
rcl_time_ = init_time_point(ros_time); // TODO(tfoote) hard coded ROS here
rcl_time_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(time_msg.sec));
rcl_time_.nanoseconds += time_msg.nanosec;
*this = Time(time_msg);
return *this;
}
@@ -195,10 +184,7 @@ Duration
Time::operator-(const rclcpp::Time & rhs) const
{
if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
throw std::runtime_error(
std::string("can't subtract times with different time sources [") +
std::to_string(rcl_time_.clock_type) + " != " +
std::to_string(rhs.rcl_time_.clock_type) + "]");
throw std::runtime_error("can't subtract times with different time sources");
}
if (rclcpp::sub_will_overflow(rcl_time_.nanoseconds, rhs.rcl_time_.nanoseconds)) {

View File

@@ -100,8 +100,7 @@ void TimeSource::attachNode(
} else {
// TODO(wjwwood): use set_on_parameters_set_callback to catch the type mismatch,
// before the use_sim_time parameter can ever be set to an invalid value
RCLCPP_ERROR(
logger_, "Invalid type '%s' for parameter 'use_sim_time', should be 'bool'",
RCLCPP_ERROR(logger_, "Invalid type '%s' for parameter 'use_sim_time', should be 'bool'",
rclcpp::to_string(use_sim_time_param.get_type()).c_str());
}
@@ -155,8 +154,7 @@ void TimeSource::detachClock(std::shared_ptr<rclcpp::Clock> clock)
TimeSource::~TimeSource()
{
if (
node_base_ || node_topics_ || node_graph_ || node_services_ ||
if (node_base_ || node_topics_ || node_graph_ || node_services_ ||
node_logging_ || node_clock_ || node_parameters_)
{
this->detachNode();

View File

@@ -55,8 +55,7 @@ TimerBase::TimerBase(
*timer_handle_.get() = rcl_get_zero_initialized_timer();
rcl_clock_t * clock_handle = clock_->get_clock_handle();
if (
rcl_timer_init(
if (rcl_timer_init(
timer_handle_.get(), clock_handle, rcl_context.get(), period.count(), nullptr,
rcl_get_default_allocator()) != RCL_RET_OK)
{
@@ -111,14 +110,12 @@ std::chrono::nanoseconds
TimerBase::time_until_trigger()
{
int64_t time_until_next_call = 0;
if (
rcl_timer_get_time_until_next_call(
timer_handle_.get(),
&time_until_next_call) != RCL_RET_OK)
if (rcl_timer_get_time_until_next_call(timer_handle_.get(),
&time_until_next_call) != RCL_RET_OK)
{
throw std::runtime_error(
std::string(
"Timer could not get time until next call: ") + rcl_get_error_string().str);
std::string("Timer could not get time until next call: ") +
rcl_get_error_string().str);
}
return std::chrono::nanoseconds(time_until_next_call);
}

View File

@@ -103,9 +103,9 @@ remove_ros_arguments(int argc, char const * const argv[])
throw exceptions::RCLError(base_exc, "");
}
std::vector<std::string> return_arguments(nonros_argc);
std::vector<std::string> return_arguments(static_cast<size_t>(nonros_argc));
for (int ii = 0; ii < nonros_argc; ++ii) {
for (size_t ii = 0; ii < static_cast<size_t>(nonros_argc); ++ii) {
return_arguments[ii] = std::string(nonros_argv[ii]);
}

View File

@@ -86,7 +86,7 @@ TEST_F(TestMultiThreadedExecutor, timer_over_take) {
{
std::lock_guard<std::mutex> lock(last_mutex);
double diff = std::abs((now - last).nanoseconds()) / 1.0e9;
double diff = static_cast<double>(std::abs((now - last).nanoseconds())) / 1.0e9;
last = now;
if (diff < PERIOD - TOLERANCE || diff > PERIOD + TOLERANCE) {

View File

@@ -0,0 +1,3 @@
bool request
---
bool response

View File

@@ -0,0 +1,57 @@
// 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.
#include <gtest/gtest.h>
#include <string>
#include <vector>
#include "rcl/allocator.h"
#include "rcl/arguments.h"
#include "rcl/remap.h"
#include "rclcpp/node_options.hpp"
TEST(TestNodeOptions, use_global_arguments) {
{
auto options = rclcpp::NodeOptions();
EXPECT_TRUE(options.use_global_arguments());
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
}
{
auto options = rclcpp::NodeOptions().use_global_arguments(false);
EXPECT_FALSE(options.use_global_arguments());
EXPECT_FALSE(options.get_rcl_node_options()->use_global_arguments);
}
{
auto options = rclcpp::NodeOptions().use_global_arguments(true);
EXPECT_TRUE(options.use_global_arguments());
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
}
{
auto options = rclcpp::NodeOptions();
EXPECT_TRUE(options.use_global_arguments());
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
options.use_global_arguments(false);
EXPECT_FALSE(options.use_global_arguments());
EXPECT_FALSE(options.get_rcl_node_options()->use_global_arguments);
options.use_global_arguments(true);
EXPECT_TRUE(options.use_global_arguments());
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
}
}

View File

@@ -1,4 +0,0 @@
/**:
ros__parameters:
parameter_int: 21
parameter_string_array: [baz, baz, baz]

View File

@@ -75,37 +75,12 @@ TEST_F(TestClient, construction_and_destruction) {
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto client = node->create_client<ListParameters>("invalid_service?");
}, rclcpp::exceptions::InvalidServiceNameError);
}
}
TEST_F(TestClient, construction_with_free_function) {
{
auto client = rclcpp::create_client<rcl_interfaces::srv::ListParameters>(
node->get_node_base_interface(),
node->get_node_graph_interface(),
node->get_node_services_interface(),
"service",
rmw_qos_profile_services_default,
nullptr);
}
{
ASSERT_THROW(
{
auto client = rclcpp::create_client<rcl_interfaces::srv::ListParameters>(
node->get_node_base_interface(),
node->get_node_graph_interface(),
node->get_node_services_interface(),
"invalid_?service",
rmw_qos_profile_services_default,
nullptr);
}, rclcpp::exceptions::InvalidServiceNameError);
}
}
/*
Testing client construction and destruction for subnodes.
*/
@@ -117,8 +92,7 @@ TEST_F(TestClientSub, construction_and_destruction) {
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto client = node->create_client<ListParameters>("invalid_service?");
}, rclcpp::exceptions::InvalidServiceNameError);
}

View File

@@ -32,11 +32,7 @@ class TestDuration : public ::testing::Test
{
};
// TEST(TestDuration, conversions) {
// TODO(tfoote) Implement conversion methods
// }
TEST(TestDuration, operators) {
TEST_F(TestDuration, operators) {
rclcpp::Duration old(1, 0);
rclcpp::Duration young(2, 0);
@@ -45,17 +41,18 @@ TEST(TestDuration, operators) {
EXPECT_TRUE(old <= young);
EXPECT_TRUE(young >= old);
EXPECT_FALSE(young == old);
EXPECT_TRUE(young != old);
rclcpp::Duration add = old + young;
EXPECT_EQ(add.nanoseconds(), (rcl_duration_value_t)(old.nanoseconds() + young.nanoseconds()));
EXPECT_EQ(add.nanoseconds(), old.nanoseconds() + young.nanoseconds());
EXPECT_EQ(add, old + young);
rclcpp::Duration sub = young - old;
EXPECT_EQ(sub.nanoseconds(), (rcl_duration_value_t)(young.nanoseconds() - old.nanoseconds()));
EXPECT_EQ(sub.nanoseconds(), young.nanoseconds() - old.nanoseconds());
EXPECT_EQ(sub, young - old);
rclcpp::Duration scale = old * 3;
EXPECT_EQ(scale.nanoseconds(), (rcl_duration_value_t)(old.nanoseconds() * 3));
EXPECT_EQ(scale.nanoseconds(), old.nanoseconds() * 3);
rclcpp::Duration time = rclcpp::Duration(0, 0);
rclcpp::Duration copy_constructor_duration(time);
@@ -67,7 +64,7 @@ TEST(TestDuration, operators) {
EXPECT_TRUE(time == assignment_op_duration);
}
TEST(TestDuration, chrono_overloads) {
TEST_F(TestDuration, chrono_overloads) {
int64_t ns = 123456789l;
auto chrono_ns = std::chrono::nanoseconds(ns);
auto d1 = rclcpp::Duration(ns);
@@ -86,7 +83,7 @@ TEST(TestDuration, chrono_overloads) {
EXPECT_EQ(chrono_float_seconds, d5.to_chrono<decltype(chrono_float_seconds)>());
}
TEST(TestDuration, overflows) {
TEST_F(TestDuration, overflows) {
rclcpp::Duration max(std::numeric_limits<rcl_duration_value_t>::max());
rclcpp::Duration min(std::numeric_limits<rcl_duration_value_t>::min());
@@ -107,7 +104,7 @@ TEST(TestDuration, overflows) {
EXPECT_THROW(base_d_neg * 4, std::underflow_error);
}
TEST(TestDuration, negative_duration) {
TEST_F(TestDuration, negative_duration) {
rclcpp::Duration assignable_duration = rclcpp::Duration(0) - rclcpp::Duration(5, 0);
{
@@ -130,7 +127,7 @@ TEST(TestDuration, negative_duration) {
}
}
TEST(TestDuration, maximum_duration) {
TEST_F(TestDuration, maximum_duration) {
rclcpp::Duration max_duration = rclcpp::Duration::max();
rclcpp::Duration max(std::numeric_limits<int32_t>::max(), 999999999);
@@ -138,18 +135,98 @@ TEST(TestDuration, maximum_duration) {
}
static const int64_t HALF_SEC_IN_NS = 500 * 1000 * 1000;
static const int64_t ONE_SEC_IN_NS = 1000 * 1000 * 1000;
static const int64_t ONE_AND_HALF_SEC_IN_NS = 3 * HALF_SEC_IN_NS;
TEST(TestDuration, from_seconds) {
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration::from_seconds(0.0));
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration::from_seconds(0));
EXPECT_EQ(rclcpp::Duration(1, HALF_SEC_IN_NS), rclcpp::Duration::from_seconds(1.5));
EXPECT_EQ(rclcpp::Duration(-ONE_AND_HALF_SEC_IN_NS), rclcpp::Duration::from_seconds(-1.5));
}
TEST(TestDuration, std_chrono_constructors) {
TEST_F(TestDuration, std_chrono_constructors) {
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration(0.0s));
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration(0s));
EXPECT_EQ(rclcpp::Duration(1, HALF_SEC_IN_NS), rclcpp::Duration(1.5s));
EXPECT_EQ(rclcpp::Duration(-1, 0), rclcpp::Duration(-1s));
}
TEST_F(TestDuration, conversions) {
{
const rclcpp::Duration duration(HALF_SEC_IN_NS);
const auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
EXPECT_EQ(duration_msg.sec, 0);
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), HALF_SEC_IN_NS);
const auto rmw_time = duration.to_rmw_time();
EXPECT_EQ(rmw_time.sec, 0u);
EXPECT_EQ(rmw_time.nsec, static_cast<uint64_t>(HALF_SEC_IN_NS));
const auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
EXPECT_EQ(chrono_duration.count(), HALF_SEC_IN_NS);
}
{
const rclcpp::Duration duration(ONE_SEC_IN_NS);
const auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
EXPECT_EQ(duration_msg.sec, 1);
EXPECT_EQ(duration_msg.nanosec, 0u);
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), ONE_SEC_IN_NS);
const auto rmw_time = duration.to_rmw_time();
EXPECT_EQ(rmw_time.sec, 1u);
EXPECT_EQ(rmw_time.nsec, 0u);
const auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
EXPECT_EQ(chrono_duration.count(), ONE_SEC_IN_NS);
}
{
const rclcpp::Duration duration(ONE_AND_HALF_SEC_IN_NS);
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
EXPECT_EQ(duration_msg.sec, 1);
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), ONE_AND_HALF_SEC_IN_NS);
auto rmw_time = duration.to_rmw_time();
EXPECT_EQ(rmw_time.sec, 1u);
EXPECT_EQ(rmw_time.nsec, static_cast<uint64_t>(HALF_SEC_IN_NS));
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
EXPECT_EQ(chrono_duration.count(), ONE_AND_HALF_SEC_IN_NS);
}
{
rclcpp::Duration duration(-HALF_SEC_IN_NS);
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
EXPECT_EQ(duration_msg.sec, -1);
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -HALF_SEC_IN_NS);
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
EXPECT_EQ(chrono_duration.count(), -HALF_SEC_IN_NS);
}
{
rclcpp::Duration duration(-ONE_SEC_IN_NS);
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
EXPECT_EQ(duration_msg.sec, -1);
EXPECT_EQ(duration_msg.nanosec, 0u);
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -ONE_SEC_IN_NS);
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
EXPECT_EQ(chrono_duration.count(), -ONE_SEC_IN_NS);
}
{
rclcpp::Duration duration(-ONE_AND_HALF_SEC_IN_NS);
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
EXPECT_EQ(duration_msg.sec, -2);
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -ONE_AND_HALF_SEC_IN_NS);
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
EXPECT_EQ(chrono_duration.count(), -ONE_AND_HALF_SEC_IN_NS);
}
}

View File

@@ -33,45 +33,39 @@ TEST(TestExpandTopicOrServiceName, normal) {
TEST(TestExpandTopicOrServiceName, exceptions) {
using rclcpp::expand_topic_or_service_name;
{
ASSERT_THROW(
{
ASSERT_THROW({
expand_topic_or_service_name("chatter", "invalid_node?", "/ns");
}, rclcpp::exceptions::InvalidNodeNameError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
expand_topic_or_service_name("chatter", "node", "/invalid_ns?");
}, rclcpp::exceptions::InvalidNamespaceError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
expand_topic_or_service_name("chatter/42invalid", "node", "/ns");
}, rclcpp::exceptions::InvalidTopicNameError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
// this one will only fail on the "full" topic name validation check
expand_topic_or_service_name("chatter/{ns}/invalid", "node", "/ns");
}, rclcpp::exceptions::InvalidTopicNameError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
// is_service = true
expand_topic_or_service_name("chatter/42invalid", "node", "/ns", true);
}, rclcpp::exceptions::InvalidServiceNameError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
// is_service = true
// this one will only fail on the "full" topic name validation check
expand_topic_or_service_name("chatter/{ns}/invalid", "node", "/ns", true);

View File

@@ -24,8 +24,8 @@
#include "rcl/service.h"
#include "test_msgs/srv/empty.hpp"
#include "test_msgs/srv/empty.h"
#include "rclcpp/srv/mock.hpp"
#include "rclcpp/srv/mock.h"
class TestExternallyDefinedServices : public ::testing::Test
{
@@ -38,15 +38,16 @@ protected:
void
callback(
const std::shared_ptr<test_msgs::srv::Empty::Request>/*req*/,
std::shared_ptr<test_msgs::srv::Empty::Response>/*resp*/)
const std::shared_ptr<rclcpp::srv::Mock::Request>/*req*/,
std::shared_ptr<rclcpp::srv::Mock::Response>/*resp*/)
{}
TEST_F(TestExternallyDefinedServices, default_behavior) {
auto node_handle = rclcpp::Node::make_shared("base_node");
try {
auto srv = node_handle->create_service<test_msgs::srv::Empty>("test", callback);
auto srv = node_handle->create_service<rclcpp::srv::Mock>("test",
callback);
} catch (const std::exception &) {
FAIL();
return;
@@ -54,18 +55,19 @@ TEST_F(TestExternallyDefinedServices, default_behavior) {
SUCCEED();
}
TEST_F(TestExternallyDefinedServices, extern_defined_uninitialized) {
auto node_handle = rclcpp::Node::make_shared("base_node");
// mock for externally defined service
rcl_service_t service_handle = rcl_get_zero_initialized_service();
rclcpp::AnyServiceCallback<test_msgs::srv::Empty> cb;
rclcpp::AnyServiceCallback<rclcpp::srv::Mock> cb;
// don't initialize the service
// expect fail
try {
rclcpp::Service<test_msgs::srv::Empty>(
rclcpp::Service<rclcpp::srv::Mock>(
node_handle->get_node_base_interface()->get_shared_rcl_node_handle(),
&service_handle, cb);
} catch (const std::runtime_error &) {
@@ -83,7 +85,7 @@ TEST_F(TestExternallyDefinedServices, extern_defined_initialized) {
rcl_service_t service_handle = rcl_get_zero_initialized_service();
rcl_service_options_t service_options = rcl_service_get_default_options();
const rosidl_service_type_support_t * ts =
rosidl_typesupport_cpp::get_service_type_support_handle<test_msgs::srv::Empty>();
rosidl_typesupport_cpp::get_service_type_support_handle<rclcpp::srv::Mock>();
rcl_ret_t ret = rcl_service_init(
&service_handle,
node_handle->get_node_base_interface()->get_rcl_node_handle(),
@@ -93,10 +95,10 @@ TEST_F(TestExternallyDefinedServices, extern_defined_initialized) {
return;
}
rclcpp::AnyServiceCallback<test_msgs::srv::Empty> cb;
rclcpp::AnyServiceCallback<rclcpp::srv::Mock> cb;
try {
rclcpp::Service<test_msgs::srv::Empty>(
rclcpp::Service<rclcpp::srv::Mock>(
node_handle->get_node_base_interface()->get_shared_rcl_node_handle(),
&service_handle, cb);
} catch (const std::runtime_error &) {
@@ -123,7 +125,7 @@ TEST_F(TestExternallyDefinedServices, extern_defined_destructor) {
rcl_service_t service_handle = rcl_get_zero_initialized_service();
rcl_service_options_t service_options = rcl_service_get_default_options();
const rosidl_service_type_support_t * ts =
rosidl_typesupport_cpp::get_service_type_support_handle<test_msgs::srv::Empty>();
rosidl_typesupport_cpp::get_service_type_support_handle<rclcpp::srv::Mock>();
rcl_ret_t ret = rcl_service_init(
&service_handle,
node_handle->get_node_base_interface()->get_rcl_node_handle(),
@@ -132,11 +134,11 @@ TEST_F(TestExternallyDefinedServices, extern_defined_destructor) {
FAIL();
return;
}
rclcpp::AnyServiceCallback<test_msgs::srv::Empty> cb;
rclcpp::AnyServiceCallback<rclcpp::srv::Mock> cb;
{
// Call constructor
rclcpp::Service<test_msgs::srv::Empty> srv_cpp(
rclcpp::Service<rclcpp::srv::Mock> srv_cpp(
node_handle->get_node_base_interface()->get_shared_rcl_node_handle(),
&service_handle, cb);
// Call destructor

View File

@@ -742,9 +742,8 @@ public:
TEST_F GTest macro.
*/
TEST_F(TestMember, bind_member_functor) {
auto bind_member_functor = std::bind(
&TestMember::MemberFunctor, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3);
auto bind_member_functor = std::bind(&TestMember::MemberFunctor, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3);
static_assert(
rclcpp::function_traits::check_arguments<decltype(bind_member_functor), int, float,

View File

@@ -0,0 +1,97 @@
// Copyright 2018 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cstdio>
#include <map>
#include <string>
#include "gtest/gtest.h"
#include "rclcpp/rclcpp.hpp"
TEST(test_local_parameters, set_parameter_if_not_set) {
auto node = rclcpp::Node::make_shared(
"test_local_parameters_set_parameter_if_not_set",
rclcpp::NodeOptions().allow_undeclared_parameters(true));
{
// try to set a map of parameters
std::map<std::string, double> bar_map{
{"x", 0.5},
{"y", 1.0},
};
#if !defined(_WIN32)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else // !defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
node->set_parameters_if_not_set("bar", bar_map);
#if !defined(_WIN32)
# pragma GCC diagnostic pop
#else // !defined(_WIN32)
# pragma warning(pop)
#endif
double bar_x_value;
ASSERT_TRUE(node->get_parameter("bar.x", bar_x_value));
EXPECT_EQ(bar_x_value, 0.5);
double bar_y_value;
ASSERT_TRUE(node->get_parameter("bar.y", bar_y_value));
EXPECT_EQ(bar_y_value, 1.0);
std::map<std::string, double> new_map;
ASSERT_TRUE(node->get_parameters("bar", new_map));
ASSERT_EQ(new_map.size(), 2U);
EXPECT_EQ(new_map["x"], 0.5);
EXPECT_EQ(new_map["y"], 1.0);
}
{
// try to get a map of parameters that doesn't exist
std::map<std::string, double> no_exist_map;
ASSERT_FALSE(node->get_parameters("no_exist", no_exist_map));
}
{
// set parameters for a map with different types, then try to get them back as a map
#if !defined(_WIN32)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else // !defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
node->set_parameter_if_not_set("baz.x", 1.0);
node->set_parameter_if_not_set("baz.y", "hello");
#if !defined(_WIN32)
# pragma GCC diagnostic pop
#else // !defined(_WIN32)
# pragma warning(pop)
#endif
std::map<std::string, double> baz_map;
EXPECT_THROW(node->get_parameters("baz", baz_map), rclcpp::ParameterTypeException);
}
}
int main(int argc, char ** argv)
{
::setvbuf(stdout, NULL, _IONBF, BUFSIZ);
// NOTE: use custom main to ensure that rclcpp::init is called only once
rclcpp::init(argc, argv);
::testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
rclcpp::shutdown();
return ret;
}

View File

@@ -162,28 +162,3 @@ TEST_F(TestLoggingMacros, test_logging_skipfirst) {
EXPECT_EQ(i - 1, g_log_calls);
}
}
bool log_function(rclcpp::Logger logger)
{
RCLCPP_INFO(logger, "successful log");
return true;
}
bool log_function_const(const rclcpp::Logger logger)
{
RCLCPP_INFO(logger, "successful log");
return true;
}
bool log_function_const_ref(const rclcpp::Logger & logger)
{
RCLCPP_INFO(logger, "successful log");
return true;
}
TEST_F(TestLoggingMacros, test_log_from_node) {
auto logger = rclcpp::get_logger("test_logging_logger");
EXPECT_TRUE(log_function(logger));
EXPECT_TRUE(log_function_const(logger));
EXPECT_TRUE(log_function_const_ref(logger));
}

View File

@@ -25,8 +25,6 @@
#include "rclcpp/scope_exit.hpp"
#include "rclcpp/rclcpp.hpp"
#include "rcpputils/filesystem_helper.hpp"
class TestNode : public ::testing::Test
{
protected:
@@ -34,13 +32,6 @@ protected:
{
rclcpp::init(0, nullptr);
}
void SetUp() override
{
test_resources_path /= "test_node";
}
rcpputils::fs::path test_resources_path{TEST_RESOURCES_DIRECTORY};
};
/*
@@ -52,15 +43,13 @@ TEST_F(TestNode, construction_and_destruction) {
}
{
ASSERT_THROW(
{
ASSERT_THROW({
std::make_shared<rclcpp::Node>("invalid_node?", "/ns");
}, rclcpp::exceptions::InvalidNodeNameError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
std::make_shared<rclcpp::Node>("my_node", "/invalid_ns?");
}, rclcpp::exceptions::InvalidNamespaceError);
}
@@ -75,7 +64,7 @@ TEST_F(TestNode, get_name_and_namespace) {
}
{
auto options = rclcpp::NodeOptions()
.arguments({"--ros-args", "-r", "__ns:=/another_ns"});
.arguments({"__ns:=/another_ns"});
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns", options);
EXPECT_STREQ("my_node", node->get_name());
EXPECT_STREQ("/another_ns", node->get_namespace());
@@ -117,9 +106,8 @@ TEST_F(TestNode, get_name_and_namespace) {
auto node3 = std::make_shared<rclcpp::Node>("my_node3", "/ns2");
auto node4 = std::make_shared<rclcpp::Node>("my_node4", "my/ns3");
auto names_and_namespaces = node1->get_node_names();
auto name_namespace_set = std::unordered_set<std::string>(
names_and_namespaces.begin(),
names_and_namespaces.end());
auto name_namespace_set = std::unordered_set<std::string>(names_and_namespaces.begin(),
names_and_namespaces.end());
std::function<bool(std::string)> Set_Contains = [&](std::string string_key)
{
return name_namespace_set.find(string_key) != name_namespace_set.end();
@@ -184,8 +172,7 @@ TEST_F(TestNode, subnode_get_name_and_namespace) {
}
{
auto node = std::make_shared<rclcpp::Node>("my_node");
ASSERT_THROW(
{
ASSERT_THROW({
auto subnode = node->create_sub_node("/sub_ns");
}, rclcpp::exceptions::NameValidationError);
}
@@ -195,70 +182,60 @@ TEST_F(TestNode, subnode_get_name_and_namespace) {
*/
TEST_F(TestNode, subnode_construction_and_destruction) {
{
ASSERT_NO_THROW(
{
ASSERT_NO_THROW({
auto node = std::make_shared<rclcpp::Node>("my_node", "ns");
auto subnode = node->create_sub_node("sub_ns");
});
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto node = std::make_shared<rclcpp::Node>("my_node", "ns");
auto subnode = node->create_sub_node("invalid_ns?");
}, rclcpp::exceptions::InvalidNamespaceError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto node = std::make_shared<rclcpp::Node>("my_node", "ns/");
}, rclcpp::exceptions::InvalidNamespaceError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto node = std::make_shared<rclcpp::Node>("my_node", "ns/");
auto subnode = node->create_sub_node("/sub_ns");
}, rclcpp::exceptions::InvalidNamespaceError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto node = std::make_shared<rclcpp::Node>("my_node", "ns");
auto subnode = node->create_sub_node("/sub_ns");
}, rclcpp::exceptions::NameValidationError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto node = std::make_shared<rclcpp::Node>("my_node", "ns");
auto subnode = node->create_sub_node("~sub_ns");
}, rclcpp::exceptions::InvalidNamespaceError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
auto subnode = node->create_sub_node("invalid_ns?");
}, rclcpp::exceptions::InvalidNamespaceError);
}
{
ASSERT_NO_THROW(
{
ASSERT_NO_THROW({
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
auto subnode = node->create_sub_node("sub_ns");
});
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
auto subnode = node->create_sub_node("/sub_ns");
}, rclcpp::exceptions::NameValidationError);
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
auto subnode = node->create_sub_node("~sub_ns");
}, rclcpp::exceptions::InvalidNamespaceError);
@@ -385,109 +362,29 @@ TEST_F(TestNode, declare_parameter_with_no_initial_values) {
}
}
auto get_fixed_on_parameter_set_callback(const std::string & name, bool successful)
{
return
[name, successful](const std::vector<rclcpp::Parameter> & parameters) {
(void)parameters;
rcl_interfaces::msg::SetParametersResult result;
result.successful = successful;
return result;
};
}
TEST_F(TestNode, test_registering_multiple_callbacks_api) {
auto node = std::make_shared<rclcpp::Node>("test_declare_parameter_node"_unq);
{
int64_t default_value{42};
auto name1 = "parameter"_unq;
auto scoped_callback1 = node->add_on_set_parameters_callback(
get_fixed_on_parameter_set_callback(name1, true));
EXPECT_NE(scoped_callback1, nullptr);
int64_t value{node->declare_parameter(name1, default_value)};
EXPECT_EQ(value, default_value);
auto name2 = "parameter"_unq;
auto scoped_callback2 = node->add_on_set_parameters_callback(
get_fixed_on_parameter_set_callback(name2, false));
EXPECT_NE(scoped_callback2, nullptr);
EXPECT_THROW(
{node->declare_parameter(name2, default_value);},
rclcpp::exceptions::InvalidParameterValueException);
auto name3 = "parameter"_unq;
scoped_callback2.reset();
value = node->declare_parameter(name3, default_value);
EXPECT_EQ(value, default_value);
}
{
int64_t default_value{42};
auto name1 = "parameter"_unq;
auto scoped_callback1 = node->add_on_set_parameters_callback(
get_fixed_on_parameter_set_callback(name1, true));
EXPECT_NE(scoped_callback1, nullptr);
int64_t value{node->declare_parameter(name1, default_value)};
EXPECT_EQ(value, default_value);
auto name2 = "parameter"_unq;
auto scoped_callback2 = node->add_on_set_parameters_callback(
get_fixed_on_parameter_set_callback(name2, false));
EXPECT_NE(scoped_callback2, nullptr);
EXPECT_THROW(
{node->declare_parameter(name2, default_value);},
rclcpp::exceptions::InvalidParameterValueException);
auto name3 = "parameter"_unq;
node->remove_on_set_parameters_callback(scoped_callback2.get());
value = node->declare_parameter(name3, default_value);
EXPECT_EQ(value, default_value);
}
{
int64_t default_value{42};
auto name1 = "parameter"_unq;
rclcpp::Node::OnSetParametersCallbackHandle::SharedPtr scoped_callback(
node->add_on_set_parameters_callback(
get_fixed_on_parameter_set_callback(name1, false)));
rclcpp::Node::OnSetParametersCallbackHandle::SharedPtr scoped_callback_copy(scoped_callback);
scoped_callback.reset();
EXPECT_THROW(
{node->declare_parameter("parameter"_unq, default_value);},
rclcpp::exceptions::InvalidParameterValueException);
scoped_callback_copy.reset();
// All the shared_ptr has been reset
int64_t value = node->declare_parameter("parameter"_unq, default_value);
EXPECT_EQ(value, default_value);
}
}
TEST_F(TestNode, declare_parameter_with_overrides) {
// test cases with overrides
TEST_F(TestNode, declare_parameter_with_initial_values) {
// test cases with initial values
rclcpp::NodeOptions no;
no.parameter_overrides(
{
no.parameter_overrides({
{"parameter_no_default", 42},
{"parameter_no_default_set", 42},
{"parameter_no_default_set_cvref", 42},
{"parameter_and_default", 42},
{"parameter_and_default_ignore_override", 42},
{"parameter_custom", 42},
{"parameter_template", 42},
{"parameter_already_declared", 42},
{"parameter_rejected", 42},
{"parameter_type_mismatch", "not an int"},
});
auto node = std::make_shared<rclcpp::Node>("test_declare_parameter_node"_unq, no);
{
// no default, with override
// no default, with initial
rclcpp::ParameterValue value = node->declare_parameter("parameter_no_default");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get<int>(), 42);
}
{
// no default, with override, and set after
// no default, with initial, and set after
rclcpp::ParameterValue value = node->declare_parameter("parameter_no_default_set");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get<int>(), 42);
@@ -496,7 +393,7 @@ TEST_F(TestNode, declare_parameter_with_overrides) {
EXPECT_EQ(node->get_parameter("parameter_no_default_set").get_value<int>(), 44);
}
{
// no default, with override
// no default, with initial
const rclcpp::ParameterValue & value =
node->declare_parameter("parameter_no_default_set_cvref");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
@@ -506,23 +403,12 @@ TEST_F(TestNode, declare_parameter_with_overrides) {
EXPECT_EQ(value.get<int>(), 44);
}
{
// int default, with override
// int default, with initial
rclcpp::ParameterValue default_value(43);
rclcpp::ParameterValue value = node->declare_parameter("parameter_and_default", default_value);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get<int>(), 42); // and not 43 which is the default value
}
{
// int default, with override and ignoring it
rclcpp::ParameterValue default_value(43);
rclcpp::ParameterValue value = node->declare_parameter(
"parameter_and_default_ignore_override",
default_value,
rcl_interfaces::msg::ParameterDescriptor(),
true);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get<int>(), 43); // and not 42, the parameter override is ignored.
}
{
// int default, with initial, custom parameter descriptor
rclcpp::ParameterValue default_value(43);
@@ -596,8 +482,7 @@ TEST_F(TestNode, declare_parameters_with_no_initial_values) {
{
// with namespace, defaults, no custom descriptors, no initial
int64_t bigger_than_int = INT64_MAX - 42;
auto values = node->declare_parameters<int64_t>(
"namespace1", {
auto values = node->declare_parameters<int64_t>("namespace1", {
{"parameter_a", 42},
{"parameter_b", 256},
{"parameter_c", bigger_than_int},
@@ -610,8 +495,7 @@ TEST_F(TestNode, declare_parameters_with_no_initial_values) {
}
{
// without namespace, defaults, no custom descriptors, no initial
auto values = node->declare_parameters<int64_t>(
"", {
auto values = node->declare_parameters<int64_t>("", {
{"parameter_without_ns_a", 42},
{"parameter_without_ns_b", 256},
});
@@ -624,8 +508,7 @@ TEST_F(TestNode, declare_parameters_with_no_initial_values) {
// with namespace, defaults, custom descriptors, no initial
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.read_only = true;
auto values = node->declare_parameters<int64_t>(
"namespace2", {
auto values = node->declare_parameters<int64_t>("namespace2", {
{"parameter_a", {42, descriptor}},
{"parameter_b", {256, descriptor}},
});
@@ -639,8 +522,7 @@ TEST_F(TestNode, declare_parameters_with_no_initial_values) {
// without namespace, defaults, custom descriptors, no initial
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.read_only = true;
auto values = node->declare_parameters<int64_t>(
"", {
auto values = node->declare_parameters<int64_t>("", {
{"parameter_without_ns_c", {42, descriptor}},
{"parameter_without_ns_d", {256, descriptor}},
});
@@ -695,72 +577,6 @@ TEST_F(TestNode, declare_parameters_with_no_initial_values) {
}
}
TEST_F(TestNode, declare_parameter_with_cli_overrides) {
const std::string parameters_filepath = (
test_resources_path / "test_parameters.yaml").string();
// test cases with overrides
rclcpp::NodeOptions no;
no.arguments({
"--ros-args",
"-p", "parameter_bool:=true",
"-p", "parameter_int:=42",
"-p", "parameter_double:=0.42",
"-p", "parameter_string:=foo",
"--params-file", parameters_filepath.c_str(),
"-p", "parameter_bool_array:=[false, true]",
"-p", "parameter_int_array:=[-21, 42]",
"-p", "parameter_double_array:=[-1.0, .42]",
"-p", "parameter_string_array:=[foo, bar]"
});
auto node = std::make_shared<rclcpp::Node>("test_declare_parameter_node"_unq, no);
{
rclcpp::ParameterValue value = node->declare_parameter("parameter_bool");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_BOOL);
EXPECT_EQ(value.get<bool>(), true);
}
{
rclcpp::ParameterValue value = node->declare_parameter("parameter_int");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get<int64_t>(), 21); // set to 42 in CLI, overriden by file
}
{
rclcpp::ParameterValue value = node->declare_parameter("parameter_double");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
EXPECT_EQ(value.get<double>(), 0.42);
}
{
rclcpp::ParameterValue value = node->declare_parameter("parameter_string");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_STRING);
EXPECT_EQ(value.get<std::string>(), "foo");
}
{
rclcpp::ParameterValue value = node->declare_parameter("parameter_bool_array");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_BOOL_ARRAY);
std::vector<bool> expected_value{false, true};
EXPECT_EQ(value.get<std::vector<bool>>(), expected_value);
}
{
rclcpp::ParameterValue value = node->declare_parameter("parameter_int_array");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
std::vector<int64_t> expected_value{-21, 42};
EXPECT_EQ(value.get<std::vector<int64_t>>(), expected_value);
}
{
rclcpp::ParameterValue value = node->declare_parameter("parameter_double_array");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
std::vector<double> expected_value{-1.0, 0.42};
EXPECT_EQ(value.get<std::vector<double>>(), expected_value);
}
{
rclcpp::ParameterValue value = node->declare_parameter("parameter_string_array");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_STRING_ARRAY);
std::vector<std::string> expected_value{"foo", "bar"};
// set to [baz, baz, baz] in file, overriden by CLI
EXPECT_EQ(value.get<std::vector<std::string>>(), expected_value);
}
}
TEST_F(TestNode, undeclare_parameter) {
auto node = std::make_shared<rclcpp::Node>("test_undeclare_parameter_node"_unq);
{
@@ -1251,8 +1067,7 @@ TEST_F(TestNode, set_parameter_undeclared_parameters_not_allowed) {
TEST_F(TestNode, set_parameter_undeclared_parameters_allowed) {
rclcpp::NodeOptions no;
no.parameter_overrides(
{
no.parameter_overrides({
{"parameter_with_override", 30},
});
no.allow_undeclared_parameters(true);
@@ -1299,8 +1114,7 @@ TEST_F(TestNode, set_parameters_undeclared_parameters_not_allowed) {
node->declare_parameter(name2, true);
node->declare_parameter<std::string>(name3, "blue");
auto rets = node->set_parameters(
{
auto rets = node->set_parameters({
{name1, 2},
{name2, false},
{name3, "red"},
@@ -1315,8 +1129,7 @@ TEST_F(TestNode, set_parameters_undeclared_parameters_not_allowed) {
auto name = "parameter"_unq;
node->declare_parameter(name, 1);
auto rets = node->set_parameters(
{
auto rets = node->set_parameters({
{name, 42},
{name, 2},
});
@@ -1335,8 +1148,7 @@ TEST_F(TestNode, set_parameters_undeclared_parameters_not_allowed) {
EXPECT_THROW(
{
node->set_parameters(
{
node->set_parameters({
{name1, 2},
{name2, "not declared :("},
{name3, 101},
@@ -1373,8 +1185,7 @@ TEST_F(TestNode, set_parameters_undeclared_parameters_not_allowed) {
};
node->set_on_parameters_set_callback(on_set_parameters);
auto rets = node->set_parameters(
{
auto rets = node->set_parameters({
{name1, 2},
{name2, false},
{name3, "red"},
@@ -1434,8 +1245,7 @@ TEST_F(TestNode, set_parameters_undeclared_parameters_allowed) {
EXPECT_TRUE(node->has_parameter(name2));
EXPECT_EQ(node->get_parameter(name2).get_value<std::string>(), "test");
auto rets = node->set_parameters(
{
auto rets = node->set_parameters({
rclcpp::Parameter(name1, 43),
rclcpp::Parameter(name2, "other"),
});
@@ -1451,8 +1261,7 @@ TEST_F(TestNode, set_parameters_undeclared_parameters_allowed) {
EXPECT_FALSE(node->has_parameter(name1));
EXPECT_FALSE(node->has_parameter(name2));
auto rets = node->set_parameters(
{
auto rets = node->set_parameters({
rclcpp::Parameter(name1, 42),
rclcpp::Parameter(name2, "test"),
});
@@ -1475,8 +1284,7 @@ TEST_F(TestNode, set_parameters_atomically_undeclared_parameters_not_allowed) {
node->declare_parameter(name2, true);
node->declare_parameter<std::string>(name3, "blue");
auto ret = node->set_parameters_atomically(
{
auto ret = node->set_parameters_atomically({
{name1, 2},
{name2, false},
{name3, "red"},
@@ -1491,8 +1299,7 @@ TEST_F(TestNode, set_parameters_atomically_undeclared_parameters_not_allowed) {
auto name = "parameter"_unq;
node->declare_parameter(name, 1);
auto ret = node->set_parameters_atomically(
{
auto ret = node->set_parameters_atomically({
{name, 42},
{name, 2},
});
@@ -1511,8 +1318,7 @@ TEST_F(TestNode, set_parameters_atomically_undeclared_parameters_not_allowed) {
EXPECT_THROW(
{
node->set_parameters_atomically(
{
node->set_parameters_atomically({
{name1, 2},
{name2, "not declared :("},
{name3, 101},
@@ -1550,8 +1356,7 @@ TEST_F(TestNode, set_parameters_atomically_undeclared_parameters_not_allowed) {
};
node->set_on_parameters_set_callback(on_set_parameters);
auto ret = node->set_parameters_atomically(
{
auto ret = node->set_parameters_atomically({
{name1, 2},
{name2, false}, // should fail to be set, failing the whole operation
{name3, "red"},
@@ -1608,8 +1413,7 @@ TEST_F(TestNode, set_parameters_atomically_undeclared_parameters_allowed) {
EXPECT_TRUE(node->has_parameter(name2));
EXPECT_EQ(node->get_parameter(name2).get_value<std::string>(), "test");
auto ret = node->set_parameters_atomically(
{
auto ret = node->set_parameters_atomically({
rclcpp::Parameter(name1, 43),
rclcpp::Parameter(name2, "other"),
});
@@ -1625,8 +1429,7 @@ TEST_F(TestNode, set_parameters_atomically_undeclared_parameters_allowed) {
EXPECT_FALSE(node->has_parameter(name1));
EXPECT_FALSE(node->has_parameter(name2));
auto ret = node->set_parameters_atomically(
{
auto ret = node->set_parameters_atomically({
rclcpp::Parameter(name1, 42),
rclcpp::Parameter(name2, "test"),
});
@@ -1661,8 +1464,7 @@ TEST_F(TestNode, set_parameters_atomically_undeclared_parameters_allowed) {
};
node->set_on_parameters_set_callback(on_set_parameters);
auto ret = node->set_parameters_atomically(
{
auto ret = node->set_parameters_atomically({
rclcpp::Parameter(name1, 43),
rclcpp::Parameter(name2, true), // this would cause implicit declaration
rclcpp::Parameter(name3, "other"), // this set should fail, and fail the whole operation
@@ -2042,8 +1844,7 @@ TEST_F(TestNode, describe_parameter_undeclared_parameters_not_allowed) {
auto name = "parameter"_unq;
{
EXPECT_THROW(
{
EXPECT_THROW({
node->describe_parameter(name);
}, rclcpp::exceptions::ParameterNotDeclaredException);
}
@@ -2123,8 +1924,7 @@ TEST_F(TestNode, describe_parameters_undeclared_parameters_not_allowed) {
auto name = "parameter"_unq;
{
EXPECT_THROW(
{
EXPECT_THROW({
node->describe_parameters({name});
}, rclcpp::exceptions::ParameterNotDeclaredException);
}
@@ -2137,8 +1937,7 @@ TEST_F(TestNode, describe_parameters_undeclared_parameters_not_allowed) {
node->declare_parameter(name1, 42);
{
EXPECT_THROW(
{
EXPECT_THROW({
node->describe_parameters({name1, name2});
}, rclcpp::exceptions::ParameterNotDeclaredException);
}
@@ -2261,8 +2060,7 @@ TEST_F(TestNode, get_parameter_types_undeclared_parameters_not_allowed) {
auto name = "parameter"_unq;
{
EXPECT_THROW(
{
EXPECT_THROW({
node->get_parameter_types({name});
}, rclcpp::exceptions::ParameterNotDeclaredException);
}
@@ -2338,187 +2136,3 @@ TEST_F(TestNode, get_parameter_types_undeclared_parameters_allowed) {
EXPECT_EQ(results[2], rcl_interfaces::msg::ParameterType::PARAMETER_NOT_SET);
}
}
// test that it is possible to call get_parameter within the set_callback
TEST_F(TestNode, set_on_parameters_set_callback_get_parameter) {
auto node = std::make_shared<rclcpp::Node>("test_set_callback_get_parameter_node"_unq);
int64_t intval = node->declare_parameter("intparam", 42);
EXPECT_EQ(intval, 42);
double floatval = node->declare_parameter("floatparam", 5.4);
EXPECT_EQ(floatval, 5.4);
double floatout;
RCLCPP_SCOPE_EXIT({node->set_on_parameters_set_callback(nullptr);}); // always reset
auto on_set_parameters =
[&node, &floatout](const std::vector<rclcpp::Parameter> & parameters) {
rcl_interfaces::msg::SetParametersResult result;
result.successful = true;
if (parameters.size() != 1) {
result.successful = false;
}
if (parameters[0].get_value<int>() != 40) {
result.successful = false;
}
rclcpp::Parameter floatparam = node->get_parameter("floatparam");
if (floatparam.get_value<double>() != 5.4) {
result.successful = false;
}
floatout = floatparam.get_value<double>();
return result;
};
EXPECT_EQ(node->set_on_parameters_set_callback(on_set_parameters), nullptr);
ASSERT_NO_THROW(node->set_parameter({"intparam", 40}));
ASSERT_EQ(floatout, 5.4);
}
// test that calling set_parameter inside of a set_callback throws an exception
TEST_F(TestNode, set_on_parameters_set_callback_set_parameter) {
auto node = std::make_shared<rclcpp::Node>("test_set_callback_set_parameter_node"_unq);
int64_t intval = node->declare_parameter("intparam", 42);
EXPECT_EQ(intval, 42);
double floatval = node->declare_parameter("floatparam", 5.4);
EXPECT_EQ(floatval, 5.4);
RCLCPP_SCOPE_EXIT({node->set_on_parameters_set_callback(nullptr);}); // always reset
auto on_set_parameters =
[&node](const std::vector<rclcpp::Parameter> & parameters) {
rcl_interfaces::msg::SetParametersResult result;
result.successful = true;
if (parameters.size() != 1) {
result.successful = false;
}
if (parameters[0].get_value<int>() != 40) {
result.successful = false;
}
// This should throw an exception
node->set_parameter({"floatparam", 5.6});
return result;
};
EXPECT_EQ(node->set_on_parameters_set_callback(on_set_parameters), nullptr);
EXPECT_THROW(
{
node->set_parameter(rclcpp::Parameter("intparam", 40));
}, rclcpp::exceptions::ParameterModifiedInCallbackException);
}
// test that calling declare_parameter inside of a set_callback throws an exception
TEST_F(TestNode, set_on_parameters_set_callback_declare_parameter) {
auto node = std::make_shared<rclcpp::Node>("test_set_callback_declare_parameter_node"_unq);
int64_t intval = node->declare_parameter("intparam", 42);
EXPECT_EQ(intval, 42);
double floatval = node->declare_parameter("floatparam", 5.4);
EXPECT_EQ(floatval, 5.4);
RCLCPP_SCOPE_EXIT({node->set_on_parameters_set_callback(nullptr);}); // always reset
auto on_set_parameters =
[&node](const std::vector<rclcpp::Parameter> & parameters) {
rcl_interfaces::msg::SetParametersResult result;
result.successful = true;
if (parameters.size() != 1) {
result.successful = false;
}
if (parameters[0].get_value<int>() != 40) {
result.successful = false;
}
// This should throw an exception
node->declare_parameter("floatparam2", 5.6);
return result;
};
EXPECT_EQ(node->set_on_parameters_set_callback(on_set_parameters), nullptr);
EXPECT_THROW(
{
node->set_parameter(rclcpp::Parameter("intparam", 40));
}, rclcpp::exceptions::ParameterModifiedInCallbackException);
}
// test that calling undeclare_parameter inside a set_callback throws an exception
TEST_F(TestNode, set_on_parameters_set_callback_undeclare_parameter) {
auto node = std::make_shared<rclcpp::Node>("test_set_callback_undeclare_parameter_node"_unq);
int64_t intval = node->declare_parameter("intparam", 42);
EXPECT_EQ(intval, 42);
double floatval = node->declare_parameter("floatparam", 5.4);
EXPECT_EQ(floatval, 5.4);
RCLCPP_SCOPE_EXIT({node->set_on_parameters_set_callback(nullptr);}); // always reset
auto on_set_parameters =
[&node](const std::vector<rclcpp::Parameter> & parameters) {
rcl_interfaces::msg::SetParametersResult result;
result.successful = true;
if (parameters.size() != 1) {
result.successful = false;
}
if (parameters[0].get_value<int>() != 40) {
result.successful = false;
}
// This should throw an exception
node->undeclare_parameter("floatparam");
return result;
};
EXPECT_EQ(node->set_on_parameters_set_callback(on_set_parameters), nullptr);
EXPECT_THROW(
{
node->set_parameter(rclcpp::Parameter("intparam", 40));
}, rclcpp::exceptions::ParameterModifiedInCallbackException);
}
// test that calling set_on_parameters_set_callback from a set_callback throws an exception
TEST_F(TestNode, set_on_parameters_set_callback_set_on_parameters_set_callback) {
auto node = std::make_shared<rclcpp::Node>("test_set_callback_set_callback_node"_unq);
int64_t intval = node->declare_parameter("intparam", 42);
EXPECT_EQ(intval, 42);
double floatval = node->declare_parameter("floatparam", 5.4);
EXPECT_EQ(floatval, 5.4);
RCLCPP_SCOPE_EXIT({node->set_on_parameters_set_callback(nullptr);}); // always reset
auto on_set_parameters =
[&node](const std::vector<rclcpp::Parameter> & parameters) {
rcl_interfaces::msg::SetParametersResult result;
result.successful = true;
if (parameters.size() != 1) {
result.successful = false;
}
if (parameters[0].get_value<int>() != 40) {
result.successful = false;
}
auto bad_parameters =
[](const std::vector<rclcpp::Parameter> & parameters) {
(void)parameters;
rcl_interfaces::msg::SetParametersResult result;
return result;
};
// This should throw an exception
node->set_on_parameters_set_callback(bad_parameters);
return result;
};
EXPECT_EQ(node->set_on_parameters_set_callback(on_set_parameters), nullptr);
EXPECT_THROW(
{
node->set_parameter(rclcpp::Parameter("intparam", 40));
}, rclcpp::exceptions::ParameterModifiedInCallbackException);
}

View File

@@ -28,15 +28,14 @@ class TestNodeWithGlobalArgs : public ::testing::Test
protected:
static void SetUpTestCase()
{
const char * const args[] = {"proc", "--ros-args", "-r", "__node:=global_node_name"};
const int argc = sizeof(args) / sizeof(const char *);
rclcpp::init(argc, args);
const char * const args[] = {"proc", "__node:=global_node_name"};
rclcpp::init(2, args);
}
};
TEST_F(TestNodeWithGlobalArgs, local_arguments_before_global) {
auto options = rclcpp::NodeOptions()
.arguments({"--ros-args", "-r", "__node:=local_arguments_test"});
.arguments({"__node:=local_arguments_test"});
auto node = rclcpp::Node::make_shared("orig_name", options);
EXPECT_STREQ("local_arguments_test", node->get_name());

View File

@@ -1,100 +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.
#include <gtest/gtest.h>
#include <string>
#include <vector>
#include "rcl/allocator.h"
#include "rcl/arguments.h"
#include "rcl/remap.h"
#include "rclcpp/node_options.hpp"
TEST(TestNodeOptions, ros_args_only) {
rcl_allocator_t allocator = rcl_get_default_allocator();
auto options = rclcpp::NodeOptions(allocator)
.arguments({"--ros-args", "-r", "__node:=some_node", "-r", "__ns:=/some_ns"});
const rcl_node_options_t * rcl_options = options.get_rcl_node_options();
ASSERT_TRUE(rcl_options != nullptr);
ASSERT_EQ(0, rcl_arguments_get_count_unparsed(&rcl_options->arguments));
ASSERT_EQ(0, rcl_arguments_get_count_unparsed_ros(&rcl_options->arguments));
char * node_name = nullptr;
EXPECT_EQ(RCL_RET_OK, rcl_remap_node_name(
&rcl_options->arguments, nullptr, "my_node", allocator, &node_name));
ASSERT_TRUE(node_name != nullptr);
EXPECT_STREQ("some_node", node_name);
allocator.deallocate(node_name, allocator.state);
char * namespace_name = nullptr;
EXPECT_EQ(RCL_RET_OK, rcl_remap_node_namespace(
&rcl_options->arguments, nullptr, "my_ns", allocator, &namespace_name));
ASSERT_TRUE(namespace_name != nullptr);
EXPECT_STREQ("/some_ns", namespace_name);
allocator.deallocate(namespace_name, allocator.state);
}
TEST(TestNodeOptions, ros_args_and_non_ros_args) {
rcl_allocator_t allocator = rcl_get_default_allocator();
auto options = rclcpp::NodeOptions(allocator).arguments({
"--non-ros-flag", "--ros-args", "-r", "__node:=some_node",
"-r", "__ns:=/some_ns", "--", "non-ros-arg"});
const rcl_node_options_t * rcl_options = options.get_rcl_node_options();
ASSERT_TRUE(rcl_options != nullptr);
ASSERT_EQ(0, rcl_arguments_get_count_unparsed_ros(&rcl_options->arguments));
ASSERT_EQ(2, rcl_arguments_get_count_unparsed(&rcl_options->arguments));
char * node_name = nullptr;
EXPECT_EQ(RCL_RET_OK, rcl_remap_node_name(
&rcl_options->arguments, nullptr, "my_node", allocator, &node_name));
ASSERT_TRUE(node_name != nullptr);
EXPECT_STREQ("some_node", node_name);
allocator.deallocate(node_name, allocator.state);
char * namespace_name = nullptr;
EXPECT_EQ(RCL_RET_OK, rcl_remap_node_namespace(
&rcl_options->arguments, nullptr, "my_ns", allocator, &namespace_name));
ASSERT_TRUE(namespace_name != nullptr);
EXPECT_STREQ("/some_ns", namespace_name);
allocator.deallocate(namespace_name, allocator.state);
int * output_indices = nullptr;
EXPECT_EQ(RCL_RET_OK, rcl_arguments_get_unparsed(
&rcl_options->arguments, allocator, &output_indices));
ASSERT_TRUE(output_indices != nullptr);
const std::vector<std::string> & args = options.arguments();
EXPECT_EQ("--non-ros-flag", args[output_indices[0]]);
EXPECT_EQ("non-ros-arg", args[output_indices[1]]);
allocator.deallocate(output_indices, allocator.state);
}
TEST(TestNodeOptions, bad_ros_args) {
rcl_allocator_t allocator = rcl_get_default_allocator();
auto options = rclcpp::NodeOptions(allocator)
.arguments({"--ros-args", "-r", "foo:="});
EXPECT_THROW(
options.get_rcl_node_options(),
rclcpp::exceptions::RCLInvalidROSArgsError);
options.arguments({"--ros-args", "-r", "foo:=bar", "not-a-ros-arg"});
EXPECT_THROW(
options.get_rcl_node_options(),
rclcpp::exceptions::UnknownROSArgsError);
}

View File

@@ -32,7 +32,7 @@ protected:
}
};
TEST(TestParameter, not_set_variant) {
TEST_F(TestParameter, not_set_variant) {
// Direct instantiation
rclcpp::Parameter not_set_variant;
EXPECT_EQ(rclcpp::PARAMETER_NOT_SET, not_set_variant.get_type());
@@ -53,12 +53,11 @@ TEST(TestParameter, not_set_variant) {
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_NOT_SET, not_set_param.value.type);
// From parameter message
EXPECT_EQ(
rclcpp::ParameterType::PARAMETER_NOT_SET,
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_NOT_SET,
rclcpp::Parameter::from_parameter_msg(not_set_param).get_type());
}
TEST(TestParameter, bool_variant) {
TEST_F(TestParameter, bool_variant) {
// Direct instantiation
rclcpp::Parameter bool_variant_true("bool_param", true);
EXPECT_EQ("bool_param", bool_variant_true.get_name());
@@ -66,8 +65,7 @@ TEST(TestParameter, bool_variant) {
EXPECT_EQ("bool", bool_variant_true.get_type_name());
EXPECT_TRUE(bool_variant_true.get_value<rclcpp::ParameterType::PARAMETER_BOOL>());
EXPECT_TRUE(bool_variant_true.get_value_message().bool_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_BOOL,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_BOOL,
bool_variant_true.get_value_message().type);
EXPECT_TRUE(bool_variant_true.as_bool());
@@ -85,8 +83,7 @@ TEST(TestParameter, bool_variant) {
rclcpp::Parameter bool_variant_false("bool_param", false);
EXPECT_FALSE(bool_variant_false.get_value<rclcpp::ParameterType::PARAMETER_BOOL>());
EXPECT_FALSE(bool_variant_false.get_value_message().bool_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_BOOL,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_BOOL,
bool_variant_false.get_value_message().type);
rcl_interfaces::msg::Parameter bool_param = bool_variant_true.to_parameter_msg();
@@ -102,8 +99,7 @@ TEST(TestParameter, bool_variant) {
EXPECT_EQ("bool", from_msg_true.get_type_name());
EXPECT_TRUE(from_msg_true.get_value<rclcpp::ParameterType::PARAMETER_BOOL>());
EXPECT_TRUE(from_msg_true.get_value_message().bool_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_BOOL,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_BOOL,
bool_variant_false.get_value_message().type);
bool_param.value.bool_value = false;
@@ -111,12 +107,11 @@ TEST(TestParameter, bool_variant) {
rclcpp::Parameter::from_parameter_msg(bool_param);
EXPECT_FALSE(from_msg_false.get_value<rclcpp::ParameterType::PARAMETER_BOOL>());
EXPECT_FALSE(from_msg_false.get_value_message().bool_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_BOOL,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_BOOL,
bool_variant_false.get_value_message().type);
}
TEST(TestParameter, integer_variant) {
TEST_F(TestParameter, integer_variant) {
const int TEST_VALUE {42};
// Direct instantiation
@@ -124,12 +119,10 @@ TEST(TestParameter, integer_variant) {
EXPECT_EQ("integer_param", integer_variant.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_INTEGER, integer_variant.get_type());
EXPECT_EQ("integer", integer_variant.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
integer_variant.get_value<rclcpp::ParameterType::PARAMETER_INTEGER>());
EXPECT_EQ(TEST_VALUE, integer_variant.get_value_message().integer_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER,
integer_variant.get_value_message().type);
EXPECT_EQ(TEST_VALUE, integer_variant.as_int());
@@ -155,16 +148,14 @@ TEST(TestParameter, integer_variant) {
EXPECT_EQ("integer_param", from_msg.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_INTEGER, from_msg.get_type());
EXPECT_EQ("integer", from_msg.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
from_msg.get_value<rclcpp::ParameterType::PARAMETER_INTEGER>());
EXPECT_EQ(TEST_VALUE, from_msg.get_value_message().integer_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER,
from_msg.get_value_message().type);
}
TEST(TestParameter, long_integer_variant) {
TEST_F(TestParameter, long_integer_variant) {
const int64_t TEST_VALUE {std::numeric_limits<int64_t>::max()};
// Direct instantiation
@@ -172,12 +163,10 @@ TEST(TestParameter, long_integer_variant) {
EXPECT_EQ("long_integer_param", long_variant.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_INTEGER, long_variant.get_type());
EXPECT_EQ("integer", long_variant.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
long_variant.get_value<rclcpp::ParameterType::PARAMETER_INTEGER>());
EXPECT_EQ(TEST_VALUE, long_variant.get_value_message().integer_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER,
long_variant.get_value_message().type);
EXPECT_EQ(TEST_VALUE, long_variant.as_int());
@@ -203,16 +192,14 @@ TEST(TestParameter, long_integer_variant) {
EXPECT_EQ("long_integer_param", from_msg.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_INTEGER, from_msg.get_type());
EXPECT_EQ("integer", from_msg.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
from_msg.get_value<rclcpp::ParameterType::PARAMETER_INTEGER>());
EXPECT_EQ(TEST_VALUE, from_msg.get_value_message().integer_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER,
from_msg.get_value_message().type);
}
TEST(TestParameter, float_variant) {
TEST_F(TestParameter, float_variant) {
const float TEST_VALUE {42.0f};
// Direct instantiation
@@ -220,12 +207,10 @@ TEST(TestParameter, float_variant) {
EXPECT_EQ("float_param", float_variant.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_DOUBLE, float_variant.get_type());
EXPECT_EQ("double", float_variant.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
float_variant.get_value<rclcpp::ParameterType::PARAMETER_DOUBLE>());
EXPECT_EQ(TEST_VALUE, float_variant.get_value_message().double_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE,
float_variant.get_value_message().type);
EXPECT_EQ(TEST_VALUE, float_variant.as_double());
@@ -251,16 +236,14 @@ TEST(TestParameter, float_variant) {
EXPECT_EQ("float_param", from_msg.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_DOUBLE, from_msg.get_type());
EXPECT_EQ("double", from_msg.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
from_msg.get_value<rclcpp::ParameterType::PARAMETER_DOUBLE>());
EXPECT_EQ(TEST_VALUE, from_msg.get_value_message().double_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE,
from_msg.get_value_message().type);
}
TEST(TestParameter, double_variant) {
TEST_F(TestParameter, double_variant) {
const double TEST_VALUE {-42.1};
// Direct instantiation
@@ -268,12 +251,10 @@ TEST(TestParameter, double_variant) {
EXPECT_EQ("double_param", double_variant.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_DOUBLE, double_variant.get_type());
EXPECT_EQ("double", double_variant.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
double_variant.get_value<rclcpp::ParameterType::PARAMETER_DOUBLE>());
EXPECT_EQ(TEST_VALUE, double_variant.get_value_message().double_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE,
double_variant.get_value_message().type);
EXPECT_EQ(TEST_VALUE, double_variant.as_double());
@@ -299,16 +280,14 @@ TEST(TestParameter, double_variant) {
EXPECT_EQ("double_param", from_msg.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_DOUBLE, from_msg.get_type());
EXPECT_EQ("double", from_msg.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
from_msg.get_value<rclcpp::ParameterType::PARAMETER_DOUBLE>());
EXPECT_EQ(TEST_VALUE, from_msg.get_value_message().double_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE,
from_msg.get_value_message().type);
}
TEST(TestParameter, string_variant) {
TEST_F(TestParameter, string_variant) {
const std::string TEST_VALUE {"ROS2"};
// Direct instantiation
@@ -316,12 +295,10 @@ TEST(TestParameter, string_variant) {
EXPECT_EQ("string_param", string_variant.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_STRING, string_variant.get_type());
EXPECT_EQ("string", string_variant.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
string_variant.get_value<rclcpp::ParameterType::PARAMETER_STRING>());
EXPECT_EQ(TEST_VALUE, string_variant.get_value_message().string_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_STRING,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_STRING,
string_variant.get_value_message().type);
EXPECT_EQ(TEST_VALUE, string_variant.as_string());
@@ -349,12 +326,11 @@ TEST(TestParameter, string_variant) {
EXPECT_EQ("string", from_msg.get_type_name());
EXPECT_EQ(TEST_VALUE, from_msg.get_value<rclcpp::ParameterType::PARAMETER_STRING>());
EXPECT_EQ(TEST_VALUE, from_msg.get_value_message().string_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_STRING,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_STRING,
from_msg.get_value_message().type);
}
TEST(TestParameter, byte_array_variant) {
TEST_F(TestParameter, byte_array_variant) {
const std::vector<uint8_t> TEST_VALUE {0x52, 0x4f, 0x53, 0x32};
// Direct instantiation
@@ -362,12 +338,10 @@ TEST(TestParameter, byte_array_variant) {
EXPECT_EQ("byte_array_param", byte_array_variant.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_BYTE_ARRAY, byte_array_variant.get_type());
EXPECT_EQ("byte_array", byte_array_variant.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
byte_array_variant.get_value<rclcpp::ParameterType::PARAMETER_BYTE_ARRAY>());
EXPECT_EQ(TEST_VALUE, byte_array_variant.get_value_message().byte_array_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_BYTE_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_BYTE_ARRAY,
byte_array_variant.get_value_message().type);
EXPECT_EQ(TEST_VALUE, byte_array_variant.as_byte_array());
@@ -393,16 +367,14 @@ TEST(TestParameter, byte_array_variant) {
EXPECT_EQ("byte_array_param", from_msg.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_BYTE_ARRAY, from_msg.get_type());
EXPECT_EQ("byte_array", from_msg.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
from_msg.get_value<rclcpp::ParameterType::PARAMETER_BYTE_ARRAY>());
EXPECT_EQ(TEST_VALUE, from_msg.get_value_message().byte_array_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_BYTE_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_BYTE_ARRAY,
from_msg.get_value_message().type);
}
TEST(TestParameter, bool_array_variant) {
TEST_F(TestParameter, bool_array_variant) {
const std::vector<bool> TEST_VALUE {false, true, true, false, false, true};
// Direct instantiation
@@ -410,12 +382,10 @@ TEST(TestParameter, bool_array_variant) {
EXPECT_EQ("bool_array_param", bool_array_variant.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_BOOL_ARRAY, bool_array_variant.get_type());
EXPECT_EQ("bool_array", bool_array_variant.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
bool_array_variant.get_value<rclcpp::ParameterType::PARAMETER_BOOL_ARRAY>());
EXPECT_EQ(TEST_VALUE, bool_array_variant.get_value_message().bool_array_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_BOOL_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_BOOL_ARRAY,
bool_array_variant.get_value_message().type);
EXPECT_EQ(TEST_VALUE, bool_array_variant.as_bool_array());
@@ -441,16 +411,14 @@ TEST(TestParameter, bool_array_variant) {
EXPECT_EQ("bool_array_param", from_msg.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_BOOL_ARRAY, from_msg.get_type());
EXPECT_EQ("bool_array", from_msg.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
from_msg.get_value<rclcpp::ParameterType::PARAMETER_BOOL_ARRAY>());
EXPECT_EQ(TEST_VALUE, from_msg.get_value_message().bool_array_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_BOOL_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_BOOL_ARRAY,
from_msg.get_value_message().type);
}
TEST(TestParameter, integer_array_variant) {
TEST_F(TestParameter, integer_array_variant) {
const std::vector<int> TEST_VALUE
{42, -99, std::numeric_limits<int>::max(), std::numeric_limits<int>::lowest(), 0};
@@ -458,12 +426,10 @@ TEST(TestParameter, integer_array_variant) {
rclcpp::Parameter integer_array_variant("integer_array_param", TEST_VALUE);
EXPECT_EQ("integer_array_param", integer_array_variant.get_name());
EXPECT_EQ(
rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY,
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY,
integer_array_variant.get_type());
EXPECT_EQ("integer_array", integer_array_variant.get_type_name());
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY,
integer_array_variant.get_value_message().type);
// No direct comparison of vectors of ints and long ints
@@ -498,8 +464,7 @@ TEST(TestParameter, integer_array_variant) {
rcl_interfaces::msg::Parameter integer_array_param = integer_array_variant.to_parameter_msg();
EXPECT_EQ("integer_array_param", integer_array_param.name);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY,
integer_array_param.value.type);
param_value = integer_array_param.value.integer_array_value;
@@ -524,26 +489,22 @@ TEST(TestParameter, integer_array_variant) {
EXPECT_EQ(TEST_VALUE.end(), mismatches.first);
EXPECT_EQ(param_value.end(), mismatches.second);
EXPECT_EQ(
from_msg.get_value_message().type,
EXPECT_EQ(from_msg.get_value_message().type,
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY);
}
TEST(TestParameter, long_integer_array_variant) {
TEST_F(TestParameter, long_integer_array_variant) {
const std::vector<int64_t> TEST_VALUE
{42, -99, std::numeric_limits<int64_t>::max(), std::numeric_limits<int64_t>::lowest(), 0};
rclcpp::Parameter long_array_variant("long_integer_array_param", TEST_VALUE);
EXPECT_EQ("long_integer_array_param", long_array_variant.get_name());
EXPECT_EQ(
rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY,
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY,
long_array_variant.get_type());
EXPECT_EQ("integer_array", long_array_variant.get_type_name());
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY,
long_array_variant.get_value_message().type);
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
long_array_variant.get_value<rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY>());
EXPECT_EQ(TEST_VALUE, long_array_variant.get_value_message().integer_array_value);
EXPECT_EQ(TEST_VALUE, long_array_variant.as_integer_array());
@@ -563,8 +524,7 @@ TEST(TestParameter, long_integer_array_variant) {
rcl_interfaces::msg::Parameter integer_array_param = long_array_variant.to_parameter_msg();
EXPECT_EQ("long_integer_array_param", integer_array_param.name);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY,
integer_array_param.value.type);
EXPECT_EQ(TEST_VALUE, integer_array_param.value.integer_array_value);
@@ -574,16 +534,14 @@ TEST(TestParameter, long_integer_array_variant) {
EXPECT_EQ("long_integer_array_param", from_msg.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY, from_msg.get_type());
EXPECT_EQ("integer_array", from_msg.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
from_msg.get_value<rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY>());
EXPECT_EQ(TEST_VALUE, from_msg.get_value_message().integer_array_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY,
from_msg.get_value_message().type);
}
TEST(TestParameter, float_array_variant) {
TEST_F(TestParameter, float_array_variant) {
const std::vector<float> TEST_VALUE
{42.1f, -99.1f, std::numeric_limits<float>::max(), std::numeric_limits<float>::lowest(), 0.1f};
@@ -591,12 +549,10 @@ TEST(TestParameter, float_array_variant) {
rclcpp::Parameter float_array_variant("float_array_param", TEST_VALUE);
EXPECT_EQ("float_array_param", float_array_variant.get_name());
EXPECT_EQ(
rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY,
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY,
float_array_variant.get_type());
EXPECT_EQ("double_array", float_array_variant.get_type_name());
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
float_array_variant.get_value_message().type);
// No direct comparison of vectors of floats and doubles
@@ -631,8 +587,7 @@ TEST(TestParameter, float_array_variant) {
rcl_interfaces::msg::Parameter float_array_param = float_array_variant.to_parameter_msg();
EXPECT_EQ("float_array_param", float_array_param.name);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
float_array_param.value.type);
param_value = float_array_param.value.double_array_value;
@@ -657,26 +612,22 @@ TEST(TestParameter, float_array_variant) {
EXPECT_EQ(TEST_VALUE.end(), mismatches.first);
EXPECT_EQ(param_value.end(), mismatches.second);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
from_msg.get_value_message().type);
}
TEST(TestParameter, double_array_variant) {
TEST_F(TestParameter, double_array_variant) {
const std::vector<double> TEST_VALUE
{42.1, -99.1, std::numeric_limits<double>::max(), std::numeric_limits<double>::lowest(), 0.1};
rclcpp::Parameter double_array_variant("double_array_param", TEST_VALUE);
EXPECT_EQ("double_array_param", double_array_variant.get_name());
EXPECT_EQ(
rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY,
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY,
double_array_variant.get_type());
EXPECT_EQ("double_array", double_array_variant.get_type_name());
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
double_array_variant.get_value_message().type);
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
double_array_variant.get_value<rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY>());
EXPECT_EQ(TEST_VALUE, double_array_variant.get_value_message().double_array_value);
EXPECT_EQ(TEST_VALUE, double_array_variant.as_double_array());
@@ -696,8 +647,7 @@ TEST(TestParameter, double_array_variant) {
rcl_interfaces::msg::Parameter double_array_param = double_array_variant.to_parameter_msg();
EXPECT_EQ("double_array_param", double_array_param.name);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
double_array_param.value.type);
EXPECT_EQ(TEST_VALUE, double_array_param.value.double_array_value);
@@ -707,31 +657,26 @@ TEST(TestParameter, double_array_variant) {
EXPECT_EQ("double_array_param", from_msg.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY, from_msg.get_type());
EXPECT_EQ("double_array", from_msg.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
from_msg.get_value<rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY>());
EXPECT_EQ(TEST_VALUE, from_msg.get_value_message().double_array_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE_ARRAY,
from_msg.get_value_message().type);
}
TEST(TestParameter, string_array_variant) {
TEST_F(TestParameter, string_array_variant) {
const std::vector<std::string> TEST_VALUE {"R", "O", "S2"};
// Direct instantiation
rclcpp::Parameter string_array_variant("string_array_param", TEST_VALUE);
EXPECT_EQ("string_array_param", string_array_variant.get_name());
EXPECT_EQ(
rclcpp::ParameterType::PARAMETER_STRING_ARRAY,
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_STRING_ARRAY,
string_array_variant.get_type());
EXPECT_EQ("string_array", string_array_variant.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
string_array_variant.get_value<rclcpp::ParameterType::PARAMETER_STRING_ARRAY>());
EXPECT_EQ(TEST_VALUE, string_array_variant.get_value_message().string_array_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_STRING_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_STRING_ARRAY,
string_array_variant.get_value_message().type);
EXPECT_EQ(TEST_VALUE, string_array_variant.as_string_array());
@@ -748,8 +693,7 @@ TEST(TestParameter, string_array_variant) {
rcl_interfaces::msg::Parameter string_array_param = string_array_variant.to_parameter_msg();
EXPECT_EQ("string_array_param", string_array_param.name);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_STRING_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_STRING_ARRAY,
string_array_param.value.type);
EXPECT_EQ(TEST_VALUE, string_array_param.value.string_array_value);
@@ -759,11 +703,9 @@ TEST(TestParameter, string_array_variant) {
EXPECT_EQ("string_array_param", from_msg.get_name());
EXPECT_EQ(rclcpp::ParameterType::PARAMETER_STRING_ARRAY, from_msg.get_type());
EXPECT_EQ("string_array", from_msg.get_type_name());
EXPECT_EQ(
TEST_VALUE,
EXPECT_EQ(TEST_VALUE,
from_msg.get_value<rclcpp::ParameterType::PARAMETER_STRING_ARRAY>());
EXPECT_EQ(TEST_VALUE, from_msg.get_value_message().string_array_value);
EXPECT_EQ(
rcl_interfaces::msg::ParameterType::PARAMETER_STRING_ARRAY,
EXPECT_EQ(rcl_interfaces::msg::ParameterType::PARAMETER_STRING_ARRAY,
from_msg.get_value_message().type);
}

View File

@@ -67,8 +67,7 @@ TEST_F(TestParameterClient, async_construction_and_destruction) {
}
{
ASSERT_THROW(
{
ASSERT_THROW({
std::make_shared<rclcpp::AsyncParametersClient>(node, "invalid_remote_node?");
}, rclcpp::exceptions::InvalidServiceNameError);
}
@@ -101,8 +100,7 @@ TEST_F(TestParameterClient, sync_construction_and_destruction) {
}
{
ASSERT_THROW(
{
ASSERT_THROW({
std::make_shared<rclcpp::SyncParametersClient>(node, "invalid_remote_node?");
}, rclcpp::exceptions::InvalidServiceNameError);
}

View File

@@ -13,7 +13,6 @@
// limitations under the License.
#include <gtest/gtest.h>
#include <rcl/allocator.h>
#include <rcl_yaml_param_parser/parser.h>
#include <rcutils/strdup.h>

View File

@@ -98,8 +98,7 @@ TEST_F(TestPublisher, construction_and_destruction) {
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto publisher = node->create_publisher<IntraProcessMessage>("invalid_topic?", 42);
}, rclcpp::exceptions::InvalidTopicNameError);
}
@@ -139,6 +138,41 @@ TEST_F(TestPublisher, various_creation_signatures) {
rclcpp::create_publisher<IntraProcessMessage>(node, "topic", 42, rclcpp::PublisherOptions());
(void)publisher;
}
// Now deprecated functions.
#if !defined(_WIN32)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else // !defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
{
auto publisher = node->create_publisher<IntraProcessMessage>("topic");
(void)publisher;
}
{
auto publisher = node->create_publisher<IntraProcessMessage>(
"topic",
42,
std::make_shared<std::allocator<IntraProcessMessage>>());
(void)publisher;
}
{
auto publisher = node->create_publisher<IntraProcessMessage>("topic", rmw_qos_profile_default);
(void)publisher;
}
{
auto publisher = node->create_publisher<IntraProcessMessage>(
"topic",
rmw_qos_profile_default,
std::make_shared<std::allocator<IntraProcessMessage>>());
(void)publisher;
}
#if !defined(_WIN32)
# pragma GCC diagnostic pop
#else // !defined(_WIN32)
# pragma warning(pop)
#endif
}
/*
@@ -199,8 +233,7 @@ TEST_F(TestPublisherSub, construction_and_destruction) {
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto publisher = subnode->create_publisher<IntraProcessMessage>("invalid_topic?", 42);
}, rclcpp::exceptions::InvalidTopicNameError);
}

View File

@@ -56,9 +56,8 @@ TEST(TestSerializedMessageAllocator, borrow_from_subscription) {
auto node = std::make_shared<rclcpp::Node>("test_serialized_message_allocator_node");
std::shared_ptr<rclcpp::SubscriptionBase> sub =
node->create_subscription<test_msgs::msg::Empty>(
"~/dummy_topic", 10,
[](std::shared_ptr<test_msgs::msg::Empty> test_msg) {(void) test_msg;});
node->create_subscription<test_msgs::msg::Empty>("~/dummy_topic", 10,
[](std::shared_ptr<test_msgs::msg::Empty> test_msg) {(void) test_msg;});
auto msg0 = sub->create_serialized_message();
EXPECT_EQ(0u, msg0->buffer_capacity);

View File

@@ -78,8 +78,7 @@ TEST_F(TestService, construction_and_destruction) {
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto service = node->create_service<ListParameters>("invalid_service?", callback);
}, rclcpp::exceptions::InvalidServiceNameError);
}
@@ -99,8 +98,7 @@ TEST_F(TestServiceSub, construction_and_destruction) {
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto service = node->create_service<ListParameters>("invalid_service?", callback);
}, rclcpp::exceptions::InvalidServiceNameError);
}

View File

@@ -129,8 +129,7 @@ TEST_F(TestSubscription, construction_and_destruction) {
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto sub = node->create_subscription<IntraProcessMessage>("invalid_topic?", 10, callback);
}, rclcpp::exceptions::InvalidTopicNameError);
}
@@ -162,8 +161,7 @@ TEST_F(TestSubscriptionSub, construction_and_destruction) {
}
{
ASSERT_THROW(
{
ASSERT_THROW({
auto sub = node->create_subscription<IntraProcessMessage>("invalid_topic?", 1, callback);
}, rclcpp::exceptions::InvalidTopicNameError);
}
@@ -203,6 +201,40 @@ TEST_F(TestSubscription, various_creation_signatures) {
node, "topic", 42, cb, rclcpp::SubscriptionOptions());
(void)sub;
}
// Now deprecated functions.
#if !defined(_WIN32)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else // !defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
{
auto sub = node->create_subscription<IntraProcessMessage>("topic", cb, 42);
(void)sub;
}
{
auto sub = node->create_subscription<IntraProcessMessage>("topic", cb);
(void)sub;
}
{
auto sub = node->create_subscription<IntraProcessMessage>("topic", cb, rmw_qos_profile_default);
(void)sub;
}
{
auto sub =
node->create_subscription<IntraProcessMessage>("topic", cb, rmw_qos_profile_default, nullptr);
(void)sub;
}
{
auto sub = node->create_subscription<IntraProcessMessage>("topic", cb, 42, nullptr);
(void)sub;
}
#if !defined(_WIN32)
# pragma GCC diagnostic pop
#else // !defined(_WIN32)
# pragma warning(pop)
#endif
}
/*

View File

@@ -45,7 +45,7 @@ protected:
}
};
TEST(TestTime, clock_type_access) {
TEST_F(TestTime, clock_type_access) {
rclcpp::Clock ros_clock(RCL_ROS_TIME);
EXPECT_EQ(RCL_ROS_TIME, ros_clock.get_clock_type());
@@ -56,7 +56,7 @@ TEST(TestTime, clock_type_access) {
EXPECT_EQ(RCL_STEADY_TIME, steady_clock.get_clock_type());
}
TEST(TestTime, time_sources) {
TEST_F(TestTime, time_sources) {
using builtin_interfaces::msg::Time;
rclcpp::Clock ros_clock(RCL_ROS_TIME);
Time ros_now = ros_clock.now();
@@ -74,44 +74,124 @@ TEST(TestTime, time_sources) {
EXPECT_NE(0u, steady_now.nanosec);
}
TEST(TestTime, conversions) {
static const int64_t HALF_SEC_IN_NS = 500 * 1000 * 1000;
static const int64_t ONE_SEC_IN_NS = 1000 * 1000 * 1000;
static const int64_t ONE_AND_HALF_SEC_IN_NS = 3 * HALF_SEC_IN_NS;
TEST_F(TestTime, conversions) {
rclcpp::Clock system_clock(RCL_SYSTEM_TIME);
rclcpp::Time now = system_clock.now();
builtin_interfaces::msg::Time now_msg = now;
rclcpp::Time now_again = now_msg;
EXPECT_EQ(now.nanoseconds(), now_again.nanoseconds());
builtin_interfaces::msg::Time msg;
msg.sec = 12345;
msg.nanosec = 67890;
rclcpp::Time time = msg;
EXPECT_EQ(
RCL_S_TO_NS(static_cast<int64_t>(msg.sec)) + static_cast<int64_t>(msg.nanosec),
time.nanoseconds());
EXPECT_EQ(static_cast<int64_t>(msg.sec), RCL_NS_TO_S(time.nanoseconds()));
builtin_interfaces::msg::Time negative_time_msg;
negative_time_msg.sec = -1;
negative_time_msg.nanosec = 1;
EXPECT_ANY_THROW(
{
rclcpp::Time negative_time = negative_time_msg;
});
rclcpp::Time now = system_clock.now();
builtin_interfaces::msg::Time now_msg = now;
EXPECT_ANY_THROW(rclcpp::Time(-1, 1));
rclcpp::Time now_again = now_msg;
EXPECT_EQ(now.nanoseconds(), now_again.nanoseconds());
}
EXPECT_ANY_THROW(
{
rclcpp::Time assignment(1, 2);
assignment = negative_time_msg;
});
rclcpp::Time positive_time = rclcpp::Time(12345, 67890u);
builtin_interfaces::msg::Time msg = positive_time;
EXPECT_EQ(msg.sec, 12345);
EXPECT_EQ(msg.nanosec, 67890u);
rclcpp::Time time = msg;
EXPECT_EQ(time.nanoseconds(), positive_time.nanoseconds());
EXPECT_EQ(
RCL_S_TO_NS(static_cast<int64_t>(msg.sec)) + static_cast<int64_t>(msg.nanosec),
time.nanoseconds());
EXPECT_EQ(static_cast<int64_t>(msg.sec), RCL_NS_TO_S(time.nanoseconds()));
}
// throw on construction/assignment of negative times
{
builtin_interfaces::msg::Time negative_time_msg;
negative_time_msg.sec = -1;
negative_time_msg.nanosec = 1;
EXPECT_ANY_THROW(
{
rclcpp::Time negative_time = negative_time_msg;
});
EXPECT_ANY_THROW(rclcpp::Time(-1, 1));
EXPECT_ANY_THROW(
{
rclcpp::Time assignment(1, 2);
assignment = negative_time_msg;
});
}
{
const rclcpp::Time time(HALF_SEC_IN_NS);
const auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
EXPECT_EQ(time_msg.sec, 0);
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), HALF_SEC_IN_NS);
}
{
const rclcpp::Time time(ONE_SEC_IN_NS);
const auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
EXPECT_EQ(time_msg.sec, 1);
EXPECT_EQ(time_msg.nanosec, 0u);
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), ONE_SEC_IN_NS);
}
{
const rclcpp::Time time(ONE_AND_HALF_SEC_IN_NS);
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
EXPECT_EQ(time_msg.sec, 1);
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), ONE_AND_HALF_SEC_IN_NS);
}
{
// Can rclcpp::Time be negative or not? The following constructor works:
rclcpp::Time time(-HALF_SEC_IN_NS);
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
EXPECT_EQ(time_msg.sec, -1);
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
// The opposite conversion throws...
EXPECT_ANY_THROW(
{
rclcpp::Time negative_time(time_msg);
});
}
{
// Can rclcpp::Time be negative or not? The following constructor works:
rclcpp::Time time(-ONE_SEC_IN_NS);
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
EXPECT_EQ(time_msg.sec, -1);
EXPECT_EQ(time_msg.nanosec, 0u);
// The opposite conversion throws...
EXPECT_ANY_THROW(
{
rclcpp::Time negative_time(time_msg);
});
}
{
// Can rclcpp::Time be negative or not? The following constructor works:
rclcpp::Time time(-ONE_AND_HALF_SEC_IN_NS);
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
EXPECT_EQ(time_msg.sec, -2);
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
// The opposite conversion throws...
EXPECT_ANY_THROW(
{
rclcpp::Time negative_time(time_msg);
});
}
}
TEST(TestTime, operators) {
TEST_F(TestTime, operators) {
rclcpp::Time old(1, 0);
rclcpp::Time young(2, 0);
@@ -123,7 +203,7 @@ TEST(TestTime, operators) {
EXPECT_TRUE(young != old);
rclcpp::Duration sub = young - old;
EXPECT_EQ(sub.nanoseconds(), (rcl_duration_value_t)(young.nanoseconds() - old.nanoseconds()));
EXPECT_EQ(sub.nanoseconds(), (young.nanoseconds() - old.nanoseconds()));
EXPECT_EQ(sub, young - old);
rclcpp::Time system_time(0, 0, RCL_SYSTEM_TIME);
@@ -162,7 +242,7 @@ TEST(TestTime, operators) {
}
}
TEST(TestTime, overflow_detectors) {
TEST_F(TestTime, overflow_detectors) {
/////////////////////////////////////////////////////////////////////////////
// Test logical_eq call first:
EXPECT_TRUE(logical_eq(false, false));
@@ -182,8 +262,8 @@ TEST(TestTime, overflow_detectors) {
// 256 * 256 = 64K total loops, should be pretty fast on everything
for (big_type_t y = min_val; y <= max_val; ++y) {
for (big_type_t x = min_val; x <= max_val; ++x) {
const big_type_t sum = x + y;
const big_type_t diff = x - y;
const big_type_t sum = static_cast<big_type_t>(x + y);
const big_type_t diff = static_cast<big_type_t>(x - y);
const bool add_will_overflow =
rclcpp::add_will_overflow(test_type_t(x), test_type_t(y));
@@ -219,7 +299,7 @@ TEST(TestTime, overflow_detectors) {
EXPECT_TRUE(rclcpp::sub_will_underflow<int64_t>(INT64_MIN, 1));
}
TEST(TestTime, overflows) {
TEST_F(TestTime, overflows) {
rclcpp::Time max_time(std::numeric_limits<rcl_time_point_value_t>::max());
rclcpp::Time min_time(std::numeric_limits<rcl_time_point_value_t>::min());
rclcpp::Duration one(1);
@@ -247,7 +327,7 @@ TEST(TestTime, overflows) {
EXPECT_NO_THROW(one_time - two_time);
}
TEST(TestTime, seconds) {
TEST_F(TestTime, seconds) {
EXPECT_DOUBLE_EQ(0.0, rclcpp::Time(0, 0).seconds());
EXPECT_DOUBLE_EQ(4.5, rclcpp::Time(4, 500000000).seconds());
EXPECT_DOUBLE_EQ(2.5, rclcpp::Time(0, 2500000000).seconds());

View File

@@ -161,8 +161,7 @@ void set_use_sim_time_parameter(
using namespace std::chrono_literals;
EXPECT_TRUE(parameters_client->wait_for_service(2s));
auto set_parameters_results = parameters_client->set_parameters(
{
auto set_parameters_results = parameters_client->set_parameters({
rclcpp::Parameter("use_sim_time", value)
});
for (auto & result : set_parameters_results) {

View File

@@ -40,18 +40,17 @@ protected:
test_node = std::make_shared<rclcpp::Node>("test_timer_node");
timer = test_node->create_wall_timer(
100ms,
[this]() -> void
{
this->has_timer_run.store(true);
timer = test_node->create_wall_timer(100ms,
[this]() -> void
{
this->has_timer_run.store(true);
if (this->cancel_timer.load()) {
this->timer->cancel();
if (this->cancel_timer.load()) {
this->timer->cancel();
}
// prevent any tests running timer from blocking
this->executor->cancel();
}
// prevent any tests running timer from blocking
this->executor->cancel();
}
);
executor->add_node(test_node);

View File

@@ -22,13 +22,8 @@
#include "rclcpp/utilities.hpp"
TEST(TestUtilities, remove_ros_arguments) {
const char * const argv[] = {
"process_name",
"-d", "--ros-args",
"-r", "__ns:=/foo/bar",
"-r", "__ns:=/fiz/buz",
"--", "--foo=bar", "--baz"
};
const char * const argv[] = {"process_name", "-d", "__ns:=/foo/bar",
"__ns:=/fiz/buz", "--foo=bar", "--baz"};
int argc = sizeof(argv) / sizeof(const char *);
auto args = rclcpp::remove_ros_arguments(argc, argv);
@@ -42,8 +37,7 @@ TEST(TestUtilities, remove_ros_arguments) {
TEST(TestUtilities, remove_ros_arguments_null) {
// In the case of a C executable, we would expect to get
// argc=1 and argv = ["process_name"], so this is an invalid input.
ASSERT_THROW(
{
ASSERT_THROW({
rclcpp::remove_ros_arguments(0, nullptr);
}, rclcpp::exceptions::RCLErrorBase);
}

View File

@@ -2,14 +2,45 @@
Changelog for package rclcpp_action
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.7.16 (2021-05-21)
-------------------
0.8.0 (2019-09-26)
0.7.15 (2020-11-24)
-------------------
* Fix typo in action client logger name. (`#1414 <https://github.com/ros2/rclcpp/issues/1414>`_)
* Contributors: Seulbae Kim
0.7.14 (2020-07-10)
-------------------
* Fixed doxygen warnings. (`#1208 <https://github.com/ros2/rclcpp/issues/1208>`_)
* Contributors: Alejandro Hernández Cordero
0.7.13 (2020-03-12)
-------------------
0.7.12 (2019-12-05)
-------------------
* Fixed memory leak in action clients (`#934 <https://github.com/ros2/rclcpp/issues/934>`_)
* Do not throw exception in action client if take fails (`#891 <https://github.com/ros2/rclcpp/issues/891>`_)
* Contributors: Ivan Santiago Paunovic, Jacob Perron
0.7.11 (2019-10-11)
-------------------
0.7.10 (2019-09-23)
-------------------
0.7.9 (2019-09-20)
------------------
0.7.8 (2019-09-06)
------------------
0.7.7 (2019-07-31)
------------------
0.7.6 (2019-06-12)
------------------
* Fix UnknownGoalHandle error string. (`#856 <https://github.com/ros2/rclcpp/issues/856>`_)
* Guard against making multiple result requests for a goal handle (`#808 <https://github.com/ros2/rclcpp/issues/808>`_)
* Add line break after first open paren in multiline function call (`#785 <https://github.com/ros2/rclcpp/issues/785>`_)
* Fix typo in test fixture tear down method name (`#787 <https://github.com/ros2/rclcpp/issues/787>`_)
* Contributors: Chris Lalancette, Dan Rose, Jacob Perron
0.7.5 (2019-05-30)
------------------

View File

@@ -410,7 +410,10 @@ public:
// This will override any previously registered callback
goal_handle->set_result_callback(result_callback);
}
this->make_result_aware(goal_handle);
// If the user chose to ignore the result before, then ask the server for the result now.
if (!goal_handle->is_result_aware()) {
this->make_result_aware(goal_handle);
}
return goal_handle->async_result();
}
@@ -592,10 +595,6 @@ private:
void
make_result_aware(typename GoalHandle::SharedPtr goal_handle)
{
// Avoid making more than one request
if (goal_handle->set_result_awareness(true)) {
return;
}
using GoalResultRequest = typename ActionT::Impl::GetResultService::Request;
auto goal_result_request = std::make_shared<GoalResultRequest>();
goal_result_request->goal_id.uuid = goal_handle->get_goal_id();
@@ -615,6 +614,7 @@ private:
std::lock_guard<std::mutex> lock(goal_handles_mutex_);
goal_handles_.erase(goal_handle->get_goal_id());
});
goal_handle->set_result_awareness(true);
}
/// \internal

View File

@@ -134,8 +134,7 @@ private:
typename ClientGoalHandle<ActionT>::SharedPtr shared_this,
typename std::shared_ptr<const Feedback> feedback_message);
/// Returns the previous value of awareness
bool
void
set_result_awareness(bool awareness);
void

View File

@@ -127,13 +127,11 @@ ClientGoalHandle<ActionT>::is_result_aware()
}
template<typename ActionT>
bool
void
ClientGoalHandle<ActionT>::set_result_awareness(bool awareness)
{
std::lock_guard<std::mutex> guard(handle_mutex_);
bool previous = is_result_aware_;
is_result_aware_ = awareness;
return previous;
}
template<typename ActionT>
@@ -142,7 +140,8 @@ ClientGoalHandle<ActionT>::invalidate()
{
std::lock_guard<std::mutex> guard(handle_mutex_);
status_ = GoalStatus::STATUS_UNKNOWN;
result_promise_.set_exception(std::make_exception_ptr(exceptions::UnawareGoalHandleError()));
result_promise_.set_exception(std::make_exception_ptr(
exceptions::UnawareGoalHandleError()));
}
template<typename ActionT>

View File

@@ -30,10 +30,10 @@ namespace rclcpp_action
* This function is equivalent to \sa create_client()` however is using the individual
* node interfaces to create the client.
*
* \param node_base_interface[in] The node base interface of the corresponding node.
* \param node_graph_interface[in] The node graph interface of the corresponding node.
* \param node_logging_interface[in] The node logging interface of the corresponding node.
* \param node_waitables_interface[in] The node waitables interface of the corresponding node.
* \param[in] node_base_interface The node base interface of the corresponding node.
* \param[in] node_graph_interface The node graph interface of the corresponding node.
* \param[in] node_logging_interface The node logging interface of the corresponding node.
* \param[in] node_waitables_interface The node waitables interface of the corresponding node.
* \param[in] name The action name.
* \param[in] group The action client will be added to this callback group.
* If `nullptr`, then the action client is added to the default callback group.

View File

@@ -39,18 +39,18 @@ namespace rclcpp_action
*
* \sa Server::Server() for more information.
*
* \param node_base_interface[in] The node base interface of the corresponding node.
* \param node_clock_interface[in] The node clock interface of the corresponding node.
* \param node_logging_interface[in] The node logging interface of the corresponding node.
* \param node_waitables_interface[in] The node waitables interface of the corresponding node.
* \param name[in] The action name.
* \param[in] node_base_interface The node base interface of the corresponding node.
* \param[in] node_clock_interface The node clock interface of the corresponding node.
* \param[in] node_logging_interface The node logging interface of the corresponding node.
* \param[in] node_waitables_interface The node waitables interface of the corresponding node.
* \param[in] name The action name.
* \param[in] handle_goal A callback that decides if a goal should be accepted or rejected.
* \param[in] handle_cancel A callback that decides if a goal should be attempted to be canceled.
* The return from this callback only indicates if the server will try to cancel a goal.
* It does not indicate if the goal was actually canceled.
* \param[in] handle_accepted A callback that is called to give the user a handle to the goal.
* \param[in] options options to pass to the underlying `rcl_action_server_t`.
* \param group[in] The action server will be added to this callback group.
* \param[in] group The action server will be added to this callback group.
* If `nullptr`, then the action server is added to the default callback group.
*/
template<typename ActionT>
@@ -117,15 +117,15 @@ create_server(
*
* \sa Server::Server() for more information.
*
* \param node[in] The action server will be added to this node.
* \param name[in] The action name.
* \param[in] node] The action server will be added to this node.
* \param[in] name The action name.
* \param[in] handle_goal A callback that decides if a goal should be accepted or rejected.
* \param[in] handle_cancel A callback that decides if a goal should be attempted to be canceled.
* The return from this callback only indicates if the server will try to cancel a goal.
* It does not indicate if the goal was actually canceled.
* \param[in] handle_accepted A callback that is called to give the user a handle to the goal.
* \param[in] options options to pass to the underlying `rcl_action_server_t`.
* \param group[in] The action server will be added to this callback group.
* \param[in] group The action server will be added to this callback group.
* If `nullptr`, then the action server is added to the default callback group.
*/
template<typename ActionT>

View File

@@ -25,7 +25,7 @@ class UnknownGoalHandleError : public std::invalid_argument
{
public:
UnknownGoalHandleError()
: std::invalid_argument("Goal handle is not known to this client.")
: std::invalid_argument("Goal handle is not know to this client.")
{
}
};

View File

@@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>rclcpp_action</name>
<version>0.8.0</version>
<version>0.7.16</version>
<description>Adds action APIs for C++.</description>
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
<license>Apache License 2.0</license>

View File

@@ -41,7 +41,7 @@ public:
const rcl_action_client_options_t & client_options)
: node_graph_(node_graph),
node_handle(node_base->get_shared_rcl_node_handle()),
logger(node_logging->get_logger().get_child("rclcpp_acton")),
logger(node_logging->get_logger().get_child("rclcpp_action")),
random_bytes_generator(std::random_device{} ())
{
std::weak_ptr<rcl_node_t> weak_node_handle(node_handle);
@@ -165,11 +165,11 @@ ClientBase::wait_for_action_server_nanoseconds(std::chrono::nanoseconds timeout)
if (!node_ptr) {
throw rclcpp::exceptions::InvalidNodeError();
}
auto event = node_ptr->get_graph_event();
// check to see if the server is ready immediately
if (this->action_server_is_ready()) {
return true;
}
auto event = node_ptr->get_graph_event();
if (timeout == std::chrono::nanoseconds(0)) {
// check was non-blocking, return immediately
return false;
@@ -388,20 +388,20 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_feedback(
pimpl_->client_handle.get(), feedback_message.get());
pimpl_->is_feedback_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking feedback");
} else {
if (RCL_RET_OK == ret) {
this->handle_feedback_message(feedback_message);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking feedback");
}
} else if (pimpl_->is_status_ready) {
std::shared_ptr<void> status_message = this->create_status_message();
rcl_ret_t ret = rcl_action_take_status(
pimpl_->client_handle.get(), status_message.get());
pimpl_->is_status_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking status");
} else {
if (RCL_RET_OK == ret) {
this->handle_status_message(status_message);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking status");
}
} else if (pimpl_->is_goal_response_ready) {
rmw_request_id_t response_header;
@@ -409,10 +409,10 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_goal_response(
pimpl_->client_handle.get(), &response_header, goal_response.get());
pimpl_->is_goal_response_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking goal response");
} else {
if (RCL_RET_OK == ret) {
this->handle_goal_response(response_header, goal_response);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking goal response");
}
} else if (pimpl_->is_result_response_ready) {
rmw_request_id_t response_header;
@@ -420,10 +420,10 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_result_response(
pimpl_->client_handle.get(), &response_header, result_response.get());
pimpl_->is_result_response_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking result response");
} else {
if (RCL_RET_OK == ret) {
this->handle_result_response(response_header, result_response);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking result response");
}
} else if (pimpl_->is_cancel_response_ready) {
rmw_request_id_t response_header;
@@ -431,10 +431,10 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_cancel_response(
pimpl_->client_handle.get(), &response_header, cancel_response.get());
pimpl_->is_cancel_response_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking cancel response");
} else {
if (RCL_RET_OK == ret) {
this->handle_cancel_response(response_header, cancel_response);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking cancel response");
}
} else {
throw std::runtime_error("Executing action client but nothing is ready");

View File

@@ -89,8 +89,7 @@ ServerBase::ServerBase(
rcl_node_t * rcl_node = node_base->get_rcl_node_handle();
rcl_ret_t ret = rcl_action_server_fini(ptr, rcl_node);
(void)ret;
RCLCPP_DEBUG(
rclcpp::get_logger("rclcpp_action"),
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp_action"),
"failed to fini rcl_action_server_t in deleter");
}
delete ptr;
@@ -255,8 +254,7 @@ ServerBase::execute_goal_request_received()
if (nullptr != ptr) {
rcl_ret_t fail_ret = rcl_action_goal_handle_fini(ptr);
(void)fail_ret;
RCLCPP_DEBUG(
rclcpp::get_logger("rclcpp_action"),
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp_action"),
"failed to fini rcl_action_goal_handle_t in deleter");
delete ptr;
}
@@ -331,8 +329,7 @@ ServerBase::execute_cancel_request_received()
rclcpp::exceptions::throw_from_rcl_error(ret);
}
RCLCPP_SCOPE_EXIT(
{
RCLCPP_SCOPE_EXIT({
ret = rcl_action_cancel_response_fini(&cancel_response);
if (RCL_RET_OK != ret) {
RCLCPP_ERROR(pimpl_->logger_, "Failed to fini cancel response");
@@ -481,8 +478,7 @@ ServerBase::publish_status()
rclcpp::exceptions::throw_from_rcl_error(ret);
}
RCLCPP_SCOPE_EXIT(
{
RCLCPP_SCOPE_EXIT({
ret = rcl_action_goal_status_array_fini(&c_status_array);
if (RCL_RET_OK != ret) {
RCLCPP_ERROR(pimpl_->logger_, "Failed to fini status array message");

View File

@@ -219,7 +219,7 @@ protected:
ASSERT_EQ(RCL_RET_OK, rcl_set_ros_time_override(clock.get_clock_handle(), RCL_S_TO_NS(1)));
}
void TearDown()
void Teardown()
{
status_publisher.reset();
feedback_publisher.reset();
@@ -396,8 +396,7 @@ TEST_F(TestClient, async_send_goal_with_result_callback_wait_for_result)
[&result_callback_received](
const typename ActionGoalHandle::WrappedResult & result) mutable
{
if (
rclcpp_action::ResultCode::SUCCEEDED == result.code &&
if (rclcpp_action::ResultCode::SUCCEEDED == result.code &&
result.result->sequence.size() == 5u)
{
result_callback_received = true;

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