Compare commits

..

479 Commits

Author SHA1 Message Date
William Woodall
ad5fbbfcff wip
Signed-off-by: William Woodall <william@osrfoundation.org>
2020-04-22 12:38:05 -07:00
William Woodall
db43729de4 deprecate redundant namespaces, move classes to own files, rename some classes
Signed-off-by: William Woodall <william@osrfoundation.org>
2020-04-22 01:41:25 -07:00
Karsten Knese
c9319dafc2 use composition for serialized message (#1082)
* use composition over inheritance

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

* make parameter names equal

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

* address review comments

Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2020-04-21 22:35:35 -07:00
DensoADAS
0f0a4a8e39 Dnae adas/serialized message (#1075)
* Addes SerializedMessage and helper class for serialization to rcl_serialized_message

@Karsten1987 Thank you for your support

Signed-off-by: Joshua Hampp <j.hampp@denso-adas.de>

* Updateds subscription traits for SerializedMessage

@Karsten1987 Thank you for your support

Signed-off-by: Joshua Hampp <j.hampp@denso-adas.de>

* Addes tests SerializedMessage and subscription traits

@Karsten1987 Thank you for your support

Signed-off-by: Joshua Hampp <j.hampp@denso-adas.de>

* Update rclcpp/include/rclcpp/serialization.hpp

Co-Authored-By: Karsten Knese <Karsten1987@users.noreply.github.com>

* Update rclcpp/test/test_serialized_message.cpp

Co-Authored-By: Karsten Knese <Karsten1987@users.noreply.github.com>

* fix windows compilation

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

* cosmetic touchups

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

Co-authored-by: Joshua Hampp <j.hampp@denso-adas.de>
Co-authored-by: Karsten Knese <Karsten1987@users.noreply.github.com>
Co-authored-by: Karsten Knese <karsten@openrobotics.org>
2020-04-21 17:30:35 -07:00
Prajakta Gokhale
649d72f835 Reflect changes in rclcpp API (#1079)
* Reflect changes in rclcpp API

Signed-off-by: Prajakta Gokhale <prajaktg@amazon.com>

* Revert earlier fix made in rclcpp

Signed-off-by: Prajakta Gokhale <prajaktg@amazon.com>
2020-04-21 14:14:47 -07:00
Dirk Thomas
679196880e fix build regression (#1078)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2020-04-21 08:57:31 -07:00
Prajakta Gokhale
1feea5e137 Add NodeDefault option for enabling topic statistics (#1074)
* Add NodeDefault option for enabling topic statistics

Signed-off-by: Prajakta Gokhale <prajaktg@amazon.com>

* Remove unnecessary if statement

Signed-off-by: Prajakta Gokhale <prajaktg@amazon.com>
2020-04-21 00:07:14 -07:00
Devin Bonnie
61e5075d06 Topic Statistics: Add SubscriptionTopicStatistics class (#1050)
* Add SubscriberTopicStatistics class

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Add SubscriberTopicStatistics Test

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Address review comments

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Modify constructor to allow a node to create necessary components

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Fix docstring style

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Remove SetPublisherTimer method

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Change naming style to match rclcpp

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Address style issues

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Fix rebase issue

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Use rclcpp:Time

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Address review comments

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Remove unnecessary check for null publisher timer
Move anonymous namespace function to private class method

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Update message dependency

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Revert constructor changes

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Address review comments

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>
2020-04-20 16:18:21 -07:00
Prajakta Gokhale
593b577294 Add SubscriptionOptions for topic statistics (#1057)
* Add SubscriptionOptions for topic statistics

Signed-off-by: Prajakta Gokhale <prajaktg@amazon.com>

* Add more options and unit test

Signed-off-by: Prajakta Gokhale <prajaktg@amazon.com>

* Address review comments

Signed-off-by: Prajakta Gokhale <prajaktg@amazon.com>

* Make default publish period 1sec

Signed-off-by: Prajakta Gokhale <prajaktg@amazon.com>
2020-04-20 14:52:54 -07:00
Miaofei Mei
911291f8d3 remove warning message from failing to register default callback (#1067)
Signed-off-by: Miaofei <miaofei@amazon.com>
2020-04-17 16:56:26 -03:00
DensoADAS
ee6ab95cfc Export component manager (#1070)
* Export component manager library

Signed-off-by: Fabian König <f.koenig@eu.denso.com>

* Export composition interfaces dependency

Signed-off-by: Fabian König <f.koenig@eu.denso.com>

Co-authored-by: Fabian König <f.koenig@eu.denso.com>
2020-04-17 09:52:28 -07:00
Michael Carroll
6c7d662333 Install the component_manager library (#1068)
Signed-off-by: Michael Carroll <michael@openrobotics.org>
2020-04-16 19:34:42 -05:00
Karsten Knese
50d500e84e Make Component Manager public (#1065)
* make functions public & virtual

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

* flexible resource index for cmake macros

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

* review comments

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

* remove superfluous include

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

* remove wrong dllexort

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

* check for empty plugin & executable args

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

* remove commented lines

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

* fix typo

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

* relax macro constraints

Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2020-04-15 19:08:04 -07:00
Miaofei Mei
44fa4fe019 Create a default warning for qos incompatibility (#1051)
Signed-off-by: Miaofei <miaofei@amazon.com>
2020-04-14 15:16:39 -03:00
William Woodall
aaf8b3828c [rclcpp] add WaitSet class and modify entities to work without executor (#1047)
* add rclcpp::GuardCondition wrapping rcl_guard_condition_t

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

* WIP second wait set refactor, just guard conditions so far

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

* fix typo

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

* removing a question/todo, I think this is fine as is

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

* added subscriptions and waitable to wait sets

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

* improve usability with subscriptions and wait sets

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

* adding take to subscription so it can be used without the executor

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

* add rclcpp::MessageInfo to replace use of rmw_message_info_t

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

* refactor Subscription and Executor so they can be used separately

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

* style and cpplint

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

* fixup take_serialized() and add tests for it

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

* add support for client and service to wait set

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

* fix typo

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

* fix typo

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

* fix review comment

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

* add thread-safe wait set policy

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

* add check for use with multiple wait set

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

* fixup visibility macro usage

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

* remove vestigial test case

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

* move visibility macro fixes

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

* remove vestigial TODO

Signed-off-by: William Woodall <william@osrfoundation.org>
2020-04-13 16:41:59 -07:00
Chris Lalancette
0f0b83368a Make sure to include what you use. (#1059)
Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2020-04-13 12:01:08 -04:00
Dirk Thomas
d62fce39bb rename rosidl_generator_c namespace to rosidl_runtime_c (#1062)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2020-04-10 21:58:22 -07:00
Dirk Thomas
5015cbf793 rename rosidl_generator_cpp namespace to rosidl_runtime_cpp (#1060)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2020-04-10 15:55:25 -07:00
Alejandro Hernández Cordero
c1a7a65537 Changed rosidl_generator_c/cpp to rosidl_runtime_c/cpp (#1014)
Signed-off-by: ahcorde <ahcorde@gmail.com>
2020-04-10 12:25:16 +02:00
Alberto Soragna
fd961bc23f use constexpr for endpoint type name (#1055)
Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>
2020-04-09 10:28:41 -07:00
Jacob Perron
fd8cfa8fe3 Add InvalidParameterTypeException (#1027)
* Add InvalidParameterTypeException

Used to wrap the ParameterTypeException coming from ParameterValue::get() for improving the error message.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>

* Describe new exception

Signed-off-by: Jacob Perron <jacob@openrobotics.org>

* Update tests

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2020-04-08 20:58:22 -07:00
Jaison Titus
01a6befdde Support for ON_REQUESTED_INCOMPATIBLE_QOS and ON_OFFERED_INCOMPATIBLE_QOS events (#924)
Signed-off-by: Jaison Titus <jaisontj92@gmail.com>
Signed-off-by: Miaofei <miaofei@amazon.com>
Co-authored-by: Miaofei <miaofei@amazon.com>
2020-04-01 12:17:20 -03:00
William Woodall
efa47546ab fixup clang warning (#1040)
Signed-off-by: William Woodall <william@osrfoundation.org>
2020-03-31 09:00:09 -07:00
William Woodall
99286978f9 [rclcpp] adding a "static" single threaded executor (#1034)
* Added static single threaded executor functionality

Signed-off-by: Ishu Goel <ishu.goel@nobleo.nl>

executor enhanced to run clients and waitable

Signed-off-by: Ishu Goel <ishu.goel@nobleo.nl>

tested executor

Signed-off-by: Ishu Goel <ishu.goel@nobleo.nl>

added semi-dynamic feature to the executor

Signed-off-by: Ishu Goel <ishu.goel@nobleo.nl>

Jenkins error fixes

Signed-off-by: Ishu Goel <ishu.goel@nobleo.nl>

Added static single threaded executor functionality

Signed-off-by: Ishu Goel <ishu.goel@nobleo.nl>

* Added semi-dynamic feature and made changes based on review comments

Signed-off-by: Ishu Goel <ishu.goel@nobleo.nl>

* re-added accidentally deleted code in node.hpp, fixed static_single_threaded_executor.cpp w.r.t. intra-process change since last commit

Signed-off-by: MartinCornelis2 <martin.cornelis@nobleo.nl>

* Remove not needed comparison

wait_set_.size_of_* is always different than '0'
if we are inside the for loop

Signed-off-by: Mauro <mpasserino@irobot.com>

* If new entity added to a node: re-collect entities

Now we check ONLY node guard_conditions_

Some possible guard conditions to be triggered HERE are:
1. Ctrl+C guard condition
2. Executor interrupt_guard_condition_
3. Node guard_conditions_
4. Waitables guard conditions
5. ..more

The previous approach was only checking if NOT (1 & 2),
so if a Waitable was triggered, it would re-collect all
entities, even if no new node entity was added. This was the case
of the intra process manager, who relies on waitables.
Every time a subscriber got a message, all the entities
were collected.

Signed-off-by: Mauro <mpasserino@irobot.com>

* Implement static executor entities collector

Signed-off-by: Mauro <mpasserino@irobot.com>

* fixup and style

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

* mark new classes as final, with non-virtual destructors

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

* adding copyright to static executor files

Signed-off-by: Ishu Goel <ishu.goel@nobleo.nl>

* fixup

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

* cpplint fixes

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

Co-authored-by: Ishu Goel <ishu.goel@nobleo.nl>
Co-authored-by: MartinCornelis2 <martin.cornelis@nobleo.nl>
Co-authored-by: Mauro <mpasserino@irobot.com>
2020-03-28 00:37:51 -07:00
Emerson Knapp
9017efbca0 Add equality operators for QoS profile (#1032)
* Add equality operators for QoS profile

Signed-off-by: Emerson Knapp <emerson.b.knapp@gmail.com>

* Use == operator for rmw_time_t as well

Signed-off-by: Emerson Knapp <emerson.b.knapp@gmail.com>

* Add visibility macros for the new functions

Signed-off-by: Emerson Knapp <emerson.b.knapp@gmail.com>

* Add tests for every member of the profile

Signed-off-by: Emerson Knapp <emerson.b.knapp@gmail.com>

* Remove dangling space

Signed-off-by: Emerson Knapp <emerson.b.knapp@gmail.com>
2020-03-25 15:30:30 -07:00
Jacob Perron
a985d6dd3a Remove extra vertical whitespace (#1030)
Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2020-03-20 17:24:16 -07:00
brawner
626e722a63 Switch IntraProcessMessage to test_msgs/Empty (#1017)
Signed-off-by: Stephen Brawner <brawner@gmail.com>
2020-03-20 16:36:19 -03:00
Miaofei Mei
3361e68bb9 add new type of exception that may be thrown during creation of publisher/subscription (#1026)
Signed-off-by: Miaofei <miaofei@amazon.com>
2020-03-19 17:16:24 -03:00
Dan Rose
96ebf59a60 Don't check lifespan on publisher QoS (#1002)
Signed-off-by: Dan Rose <dan@digilabs.io>
2020-03-10 17:51:40 -03:00
DongheeYe
d508ce3492 Fix get_parameter_tyeps of AsyncPrameterClient results are always empty (#1019)
Signed-off-by: Donghee Ye <donghee.ye@samsung.com>
2020-03-09 13:58:23 -07:00
Jacob Perron
977c6a5de1 Cleanup node interfaces includes (#1016)
Some headers were being included even though they are not required and other headers were being included transitively.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2020-03-09 13:36:58 -07:00
Dirk Thomas
87fa896e38 Add ifdefs to remove tracing-related calls if tracing is disabled (#1001)
* Add ifdefs to remove tracing-related calls if tracing is disabled

Signed-off-by: Christophe Bedard <bedard.christophe@gmail.com>

* Move ifndefs inside register_callback_for_tracing

Signed-off-by: Christophe Bedard <bedard.christophe@gmail.com>
2020-03-05 11:03:19 -08:00
Jacob Perron
68cb936bca Include missing header in node_graph.cpp (#994)
Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2020-03-04 18:00:37 -08:00
Jacob Perron
603a4a85fb Add missing includes of logging.hpp (#995)
The header is needed wherever RCLCPP_* logging macros are used.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2020-03-04 12:59:09 -08:00
Jacob Perron
e3949cb5ec Fix unknown macro errors reported by cppcheck 1.90 (#1000)
It was complaining about an unknown macro RCLCPP_SMART_PTR_DEFINITIONS.
Passing rclcpp include directories to cppcheck resolves the errors
reported in rclcpp_action and rclcpp_lifecycle.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2020-03-04 09:05:21 -08:00
Jacob Perron
d48d4608e5 Zero initialize publisher GID in subscription intra process callback (#1011)
This fixes a cppcheck error that was detected when including the rclcpp headers in rclcpp_action and rclcpp_lifecycle.
It is not clear to me why cppcheck does not report the unitialized member when testing rclcpp directly.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2020-03-03 09:28:20 -08:00
Alejandro Hernández Cordero
fffbe5972c removed ament_cmake from package and cmakelists.txt (#989)
Signed-off-by: Alejandro Hernández <ahcorde@gmail.com>
2020-03-03 10:44:37 +01:00
Chris Lalancette
f30329fbec Switch to using new rcutils_strerror. (#993)
* Switch to using new rcutils_strerror.

Also increase timeouts for test_logging, which should reduce flakes on Windows.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2020-02-28 15:22:25 -05:00
Michel Hidalgo
1644e926f9 Ensure all rclcpp::Clock accesses are thread-safe.
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2020-02-28 09:43:59 -03:00
Michel Hidalgo
b100b39353 Use a PIMPL for rclcpp::Clock implementation
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2020-02-28 09:43:59 -03:00
Alejandro Hernández Cordero
09bde58ba7 [rclcpp] replace rmw_implementation for rmw dependency in package.xml (#990)
* rclcpp removed rmw_implementation

Signed-off-by: Alejandro Hernández <ahcorde@gmail.com>

* rclcpp added rmw as a depend in package.xml

Signed-off-by: Alejandro Hernández <ahcorde@gmail.com>

* rclcpp alpha order package.xml

Signed-off-by: Alejandro Hernández <ahcorde@gmail.com>
2020-02-28 08:59:52 +01:00
Alejandro Hernández Cordero
88ce87457c [rclcpp_action] removed rosidl_generator_c dependency (#992)
* rclcpp_action removed rosidl_generator_cpp and rosidl_generator_c dependencies

Signed-off-by: Alejandro Hernández <ahcorde@gmail.com>

* rclcpp_action restored rosidl_generator_c dependency

Signed-off-by: Alejandro Hernández <ahcorde@gmail.com>

* rclcpp action alpha order CMakeLists.txt

Signed-off-by: Alejandro Hernández <ahcorde@gmail.com>
2020-02-27 18:25:10 +01:00
Alejandro Hernández Cordero
090e1cbec3 [rclcpp lifecycle] removed rmw_implementation from package.xml (#991)
* rclcpp lifecycle removed rmw_implementation from package.xml

Signed-off-by: Alejandro Hernández <ahcorde@gmail.com>

* rclcpp lifecycle added rmw depend in package.xml

Signed-off-by: Alejandro Hernández <ahcorde@gmail.com>
2020-02-27 08:39:11 +01:00
Christophe Bedard
2371923761 Add missing service callback registration tracepoint (#986)
Signed-off-by: Christophe Bedard <bedard.christophe@gmail.com>
2020-02-26 09:51:38 -03:00
Ivan Santiago Paunovic
9c002c65da Rename rmw_topic_endpoint_info_array count to size (#996)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2020-02-20 14:11:18 -03:00
Barry Xu
2d9c6ea3a7 Implement functions to get publisher and subcription informations like QoS policies from topic name (#960)
Signed-off-by: Barry Xu <Barry.Xu@sony.com>
Signed-off-by: Miaofei <miaofei@amazon.com>
Co-authored-by: Miaofei Mei <ameision@hotmail.com>
2020-02-14 17:25:03 -03:00
Dirk Thomas
7c1721a0b3 code style only: wrap after open parenthesis if not in one line (#977)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2020-02-03 09:06:57 -08:00
Ivan Santiago Paunovic
c2b855897f Accept taking an rvalue ref future in spin_until_future_complete (#971)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2020-01-30 09:35:11 -03:00
mschickler
3ec882cd2d Allow node clock use in logging macros (#969) (#970)
Capturing a cached reference allows a clock object that is not a local
(e.g. the one returned by Node::get_clock()) to be passed to the throttle
logging macro.

Signed-off-by: Matt Schickler <mschickler@gmail.com>
Co-Authored-By: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2020-01-28 14:08:00 -03:00
Jacob Perron
fdaf96f217 Change order of deprecated and visibility attributes (#968)
This fixes a build issue with Clang.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2020-01-22 15:18:09 -08:00
Jacob Perron
7a8606fb39 Deprecated is_initialized() (#967)
The function was previously documented as being deprecated, but this change adds compiler warnings if it is used.
Ignore compiler warnings where the function is being tested and change to the preferred usage elsewhere.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2020-01-22 14:11:58 -05:00
Sean Kelly
54ad49703a Don't specify calling convention in std::_Binder template (#952)
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-01-21 13:16:32 -05:00
Dino Hüllmann
9037bba7f1 logging.hpp: Added missing include (#964)
Signed-off-by: Dino Hüllmann <dino.huellmann@bam.de>
2020-01-16 19:00:00 -05:00
Dirk Thomas
b25213a186 fix style from #963 2020-01-13 15:08:19 -08:00
brawner
9dbd124f1d Assigning make_shared result to variables in test (#963)
* Assigning make_shared result to variables in test
Signed-off-by: Stephen Brawner <brawner@gmail.com>

* PR fixup

Signed-off-by: Stephen Brawner <brawner@gmail.com>
2020-01-13 14:23:41 -08:00
Mikael Arguedas
d2723fb159 fix unused parameter warning (#962)
Signed-off-by: Mikael Arguedas <mikael.arguedas@gmail.com>
2020-01-12 09:57:32 -08:00
Ivan Santiago Paunovic
01d03c5d4e Stop retaining ownership of the rcl context in GraphListener (#946)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2020-01-07 10:01:36 -03:00
Ivan Santiago Paunovic
914ea81c63 Clear sub contexts when starting another init-shutdown cycle (#947)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2020-01-03 09:55:11 -03:00
Ivan Santiago Paunovic
fd3655c26c Avoid possible UB in Clock jump callbacks (#954)
* Avoid possible UB in Clock jump callbacks

Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2019-12-20 12:04:29 -03:00
Michel Hidalgo
efbce4a11b Handle unknown global ROS arguments. (#951)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-12-19 13:38:28 +00:00
Jacob Perron
0c66d0c725 Remove absolute path from installed CMake code (#948)
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>
2019-12-17 15:23:16 -08:00
Dirk Thomas
afbdfc1dec fix function docblock, check for unparsed arguments (#945)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-12-16 14:39:37 -08:00
Marya Belanger
26bc60704c New README (#942)
* New README

* dashing to eloquent for api docs

* remove "accepted"

Co-Authored-By: Chris Lalancette <clalancette@openrobotics.org>

* components > APIs

Co-Authored-By: Chris Lalancette <clalancette@openrobotics.org>
2019-12-11 19:39:06 +03:00
Steven! Ragnarök
7e3f5511c4 Mark get_clock() as override to fix clang warnings. (#939)
Signed-off-by: Steven! Ragnarök <steven@nuclearsandwich.com>
2019-12-09 22:27:44 -05:00
Steven Macenski
9d5947108b Create node clock calls const (try 2) (#922)
* create node clock calls const

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

* two methods for get clock, one const

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

* changing APIs for NodeClock and NodeClockInterface

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

* changing RCLCPP_LIFECYCLE_PUBLIC from RCLCPP_PUBLIC for rclcpp lifecycle node get_clock const method

Signed-off-by: stevemacenski <stevenmacenski@gmail.com>
2019-12-06 14:03:58 -08:00
Zachary Michaels
6ba0f59fed Fix asserts on shared_ptr::use_count; expects long, got uint32 (#936)
* Fix asserts on shared_ptr::use_count; expects long, got uint32

Signed-off-by: Zachary Michaels <zmichaels11@gmail.com>

* Add suffix to integer literals to make them longs

Signed-off-by: Zachary Michaels <zmichaels11@gmail.com>

* Add missing L

Signed-off-by: Zachary Michaels <zmichaels11@gmail.com>
2019-12-06 11:25:58 -08:00
Jacob Perron
6ef23841f4 Fix typo in action client logger name (#937)
Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-12-05 16:29:13 -08:00
Ivan Santiago Paunovic
4f84948a8e Use absolute topic name for parameter events (#929)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2019-12-05 10:25:59 -03:00
Barry Xu
e494b3efad Add enable_rosout into NodeOptions. (#900)
* Add disable_rosout into NodeOptions.

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

* Update comments

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

* keep implementation consistency by using enable_rosout name

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

* fix error comment

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

* add test case for node options

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

* fix source about copy value and reset rcl_node_options, add more test cases

Signed-off-by: Barry Xu <Barry.Xu@sony.com>
2019-12-03 10:08:06 -03:00
Claire Wang
e2efb76477 Merge pull request #897 from monidzik/upstream-apex-changes
Removing "virtual", adding "override" keywords in the package
2019-12-02 14:22:25 -08:00
Barry Xu
3288bdd2c5 Use weak_ptr to store context in GraphListener (#906)
* Use weak_ptr to store context in graph listener

Signed-off-by: Barry Xu <Barry.Xu@sony.com>
2019-12-02 18:38:41 -03:00
Ivan Santiago Paunovic
5867e52d68 Complete published event message when declaring a parameter (#928)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2019-11-29 10:01:10 -03:00
Devin Bonnie
3eb1fe52d7 Fix duration.cpp lint error (#930)
* Fix duration.cpp lint error

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Apply review format suggestion

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>
2019-11-27 13:58:17 -08:00
Todd Malsbary
59e7bbbe7c Intra-process subscriber should use RMW actual qos. (ros2#913) (#914)
* Intra-process subscriber should use RMW actual qos. (ros2#913)

Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
2019-11-25 09:42:09 -03:00
monidzik
88a342db29 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>
2019-11-22 10:23:55 -08:00
Monika Idzik
c024189773 Add override keyword to functions
Signed-off-by: Monika Idzik <monika.idzik@apex.ai>
2019-11-22 18:02:00 +01:00
Monika Idzik
ef52953824 Remove unnecessary virtual keywords
Signed-off-by: Monika Idzik <monika.idzik@apex.ai>
2019-11-22 17:55:20 +01:00
roger-strain
b1dc6f36b9 Only check for new work once in spin_some (#471) (#844)
To prevent the Executor::spin_some() method for potentially running
indefinitely long.

Distribution Statement A; OPSEC #2893

Signed-off-by: Roger Strain <rstrain@swri.org>
2019-11-22 13:19:47 -03:00
Scott K Logan
3e08d9e43f Add addition/subtraction assignment operators to Time (#748)
Signed-off-by: Scott K Logan <logans@cottsay.net>
2019-11-21 15:50:14 -08:00
Michael Carroll
2014385671 0.8.3
Signed-off-by: Michael Carroll <michael@openrobotics.org>
2019-11-19 23:16:21 -06:00
astere-cpr
ecc39cace6 issue-919 Fixed "memory leak" in action clients (#920)
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>
2019-11-19 16:09:41 -03:00
William Woodall
a512d58a4f 0.8.2 2019-11-18 16:56:29 -08:00
William Woodall
64319062cd changelogs
Signed-off-by: William Woodall <william@osrfoundation.org>
2019-11-18 16:56:14 -08:00
Christophe Bedard
1f79bdb3f7 Put subscription callback tracepoints in intraprocess subscription too (#918)
* Put subscription callback tracepoints in intraprocess subscription too

Signed-off-by: Christophe Bedard <christophe.bedard@apex.ai>

* Add missing tracetools header

Signed-off-by: Christophe Bedard <christophe.bedard@apex.ai>

* Move Subscription tracepoints back to outside of intra-process condition

Signed-off-by: Christophe Bedard <christophe.bedard@apex.ai>

* Revert API change by adding new tracepoint as an intermediate

Signed-off-by: Christophe Bedard <christophe.bedard@apex.ai>
2019-11-19 08:53:02 +08:00
alexfneves
5254e6abc3 Bug fix on shutdown_on_sigint (not set on InitOptions constructors) (#850)
Signed-off-by: Alex Fernandes Neves <alexfneves@gmail.com>
2019-11-19 08:45:39 +08:00
Dirk Thomas
6963c2d05a add support for STREAM logging macros (#926)
* refactor template logic around feature combinations

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>

* add support for STREAM logging macros

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-11-18 16:07:57 -06:00
Michel Hidalgo
b92db52bb1 [rclcpp_action] Bump test_client timeout. (#917)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-11-12 19:15:38 -03:00
Anas Abou Allaban
2ed4456474 Relax multithreaded test constraint (#907)
Signed-off-by: Anas Abou Allaban <aabouallaban@pm.me>
2019-10-29 20:50:17 -07:00
Shane Loretz
8cc2a9ba83 0.8.1
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-10-23 17:25:23 -07:00
Michael Carroll
2716d3e81e De-flake tests for rmw_connext (#899)
* Remove duplicate tests

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Expand test timeout to 240 seconds for Connext

Signed-off-by: Michael Carroll <michael@openrobotics.org>
2019-10-23 10:14:47 -05:00
Karsten Knese
a6e3412bb0 rename return functions for loaned messages (#896)
* fix up documentation for zero copy api

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

* rename loan_message to borrow_loaned_message

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

* use return_loaned_message_from

Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-10-21 22:47:42 -05:00
Brian Marchi
3de5337376 Enable throttling logs (#879)
* Enable throttling logs

Signed-off-by: Brian Ezequiel Marchi <brian.marchi65@gmail.com>

* Change time source macro parameter generation

Signed-off-by: Brian Ezequiel Marchi <brian.marchi65@gmail.com>

* Modify only throttle parameters for logging

Signed-off-by: Brian Ezequiel Marchi <brian.marchi65@gmail.com>
2019-10-21 18:06:27 -03:00
Alberto Soragna
8525ee2eb5 New Intra-Process Communication (#778)
* basic ipc implementation from alsora/new_ipc_proposal

Signed-off-by: alberto <alberto.soragna@gmail.com>

better use of node_topic create subscription

Signed-off-by: alberto <alberto.soragna@gmail.com>

added intra process manager test

Signed-off-by: alberto <alberto.soragna@gmail.com>

fixed ring buffer and added test

Signed-off-by: alberto <alberto.soragna@gmail.com>

added intra process buffer test

Signed-off-by: alberto <alberto.soragna@gmail.com>

added intra process buffer test

Signed-off-by: alberto <alberto.soragna@gmail.com>

Signed-off-by: alberto <alberto.soragna@gmail.com>

removed intra-process methods from subscription base

Signed-off-by: alberto <alberto.soragna@gmail.com>

using lock_guard instead of unique_lock, renamed var without camel case

Signed-off-by: alberto <alberto.soragna@gmail.com>

using unordered set and references in intra process manager

Signed-off-by: alberto <alberto.soragna@gmail.com>

subscription intra-process does not depend anymore on subscription, but has a copy of the callback

Signed-off-by: alberto <alberto.soragna@gmail.com>

changed buffer API to use rvo

Signed-off-by: Alberto <alberto.soragna@gmail.com>

avoid copying shared_ptr

Signed-off-by: alberto <alberto.soragna@gmail.com>

revert not needed changes to create_subscription

Signed-off-by: alberto <alberto.soragna@gmail.com>

updated tests according to new buffer APIs

Signed-off-by: alberto <alberto.soragna@gmail.com>

updated types in ring buffer implementation avoid using uint32_t

Signed-off-by: alberto <alberto.soragna@gmail.com>

using unique ptr for buffers in subscription_intra_process

Signed-off-by: alberto <alberto.soragna@gmail.com>

added missing std::move in subscription_intra_process constructor

Signed-off-by: alberto <alberto.soragna@gmail.com>

use consisting names for ring_buffer_implementation members

Signed-off-by: alberto <alberto.soragna@gmail.com>

addressing typos, one-liners and similar from ivanpauno review

Signed-off-by: alberto <alberto.soragna@gmail.com>

moved subscription_intra_process_base to its own files and moved non templated method from derived class

Signed-off-by: alberto <alberto.soragna@gmail.com>

removed forward declarations, fixed include subscription_intra_process_base

Signed-off-by: alberto <alberto.soragna@gmail.com>

removed member variable from do_intra_process_publish signature

Signed-off-by: alberto <alberto.soragna@gmail.com>

declare public before private in intra_process_manager_impl

Signed-off-by: alberto <alberto.soragna@gmail.com>

made matches_any_intra_process_publishers const

Signed-off-by: alberto <alberto.soragna@gmail.com>

using const reference in get_all_matching_publishers

Signed-off-by: alberto <alberto.soragna@gmail.com>

added deleter and alloc templates in intra_process_buffer

Signed-off-by: alberto <alberto.soragna@gmail.com>

added RCLCPP_WARN to intra_process_manager_impl

Signed-off-by: alberto <alberto.soragna@gmail.com>

passing context from node to subscription_intra_process

Signed-off-by: alberto <alberto.soragna@gmail.com>

using allocators in intra_process_manager

Signed-off-by: alberto <alberto.soragna@gmail.com>

use size_t instead of int in ring buffer indices

Signed-off-by: alberto <alberto.soragna@gmail.com>

creating buffer inside subscription_intra_process constructor

Signed-off-by: alberto <alberto.soragna@gmail.com>

fix lint errors

Signed-off-by: alberto <alberto.soragna@gmail.com>

throw error if trying to dequeue when buffer empty; remove duplicated methods in intra_process_buffer

Signed-off-by: alberto <alberto.soragna@gmail.com>

added todo for creating an rmw function for checking qos compatibility

Signed-off-by: alberto <alberto.soragna@gmail.com>

test fixes

Signed-off-by: alberto <alberto.soragna@gmail.com>

refactored intra_process_manager, removed ipm impl

Signed-off-by: alberto <alberto.soragna@gmail.com>

added mutex in intra_process_manager add_* methods

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

added allocator to intra_process_buffer

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

added invalid intra_process qos test for subscription

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

throw error if history size is 0 with keep last and ipc

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

using allocator when creating unique_ptr from shared_ptr

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

adding deleter template argument to intra_process buffer

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

fix linter

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

throw error with callbackT different from messageT

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

updated deleter template argument in subscription factory

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

Fix typo in test fixture tear down method name (#787)

Signed-off-by: Jacob Perron <jacob@openrobotics.org>

Add free function for creating service clients (#788)

Equivalent to the free function for creating a service.
Resolves #768

Signed-off-by: Jacob Perron <jacob@openrobotics.org>

Cmake infrastructure for creating components (#784)

*cmake macro to create components for libraries with multiple nodes

Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>

Allow registering multiple on_parameters_set_callback (#772)

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

fix for multiple nodes not being recognized (#790)

Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>

Remove non-package from ament_target_dependencies() (#793)

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

fix linter issue (#795)

Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>

Make TimeSource ignore use_sim_time events coming from other nodes. (#799)

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

passing deleter template parameter

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

small fixes for failing tests

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

fixed imports in test_intra_process_manager

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

using RCLCPP_SMART_PTR_ALIASES_ONLY and RCLCPP_PUBLIC macros

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

added RCLCPP_PUBLIC macros and virtual destructor to sub intra_process base

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

added unique_ptr alias to macros

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

updated test_intra_process_manager.cpp

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

remove mock msgs from rclcpp (#800)

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

Add line break after first open paren in multiline function call (#785)

* Add line break after first open paren in multiline function call

as per developer guide:
https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#open-versus-cuddled-braces
see https://github.com/ament/ament_lint/pull/148

Signed-off-by: Dan Rose <dan@digilabs.io>

Fix dedent when first function argument starts with a brace

Signed-off-by: Dan Rose <dan@digilabs.io>

Line break with multiline if condition
Remove line breaks where allowed.

Signed-off-by: Dan Rose <dan@digilabs.io>

Fixup after rebase

Signed-off-by: Dan Rose <dan@digilabs.io>

Fixup again after reverting indent_paren_open_brace

Signed-off-by: Dan Rose <dan@digilabs.io>

* Revert comment spacing change, condense some lines

Signed-off-by: Dan Rose <dan@digilabs.io>

Adapt to '--ros-args ... [--]'-based ROS args extraction (#816)

* Use --ros-args to deal with node arguments in rclcpp.

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

* Document implicit --ros-args flag in NodeOptions::arguments().

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

* Add missing size_t to int cast.

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

* Only add implicit --ros-args flag if not present already.

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

* Add some rclcpp::NodeOptions test coverage.

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

* Address peer review comments.

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

* Please cpplint and uncrustify.

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

Guard against making multiple result requests for a goal handle (#808)

This fixes a runtime error caused by a race condition when making consecutive requests for the
result.
Specifically, this happens if the user provides a result callback when sending a goal and then
calls async_get_result shortly after.

Resolves #783

Signed-off-by: Jacob Perron <jacob@openrobotics.org>

Explain return value of spin_until_future_complete (#792)

Signed-off-by: Dan Rose <dan@digilabs.io>

Allow passing logger by const ref (#820)

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

Delete unnecessary call for get_node_by_group (#823)

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

Fix get_node_interfaces functions taking a pointer (#821)

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

add callback group as member variable and constructor arg (#811)

Signed-off-by: bpwilcox <bpwilcox@eng.ucsd.edu>

remove callback group as member variable

Wrap documentation examples in code blocks (#830)

This makes the code examples easier to read in the generated documentation.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>

Crash in callback group pointer vector iterator (#814)

Signed-off-by: Guillaume Autran <gautran@clearpath.ai>

add mutex in add/remove_node and wait_for_work to protect concurrent use/change of memory_strategy_ (#837)

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>

Fix hang with timers in MultiThreadedExecutor (#835) (#836)

Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>

Use of -r/--remap flags where appropriate. (#834)

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

Force explicit --ros-args in NodeOptions::arguments(). (#845)

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

Fail on invalid and unknown ROS specific arguments (#842)

* Fail on invalid and unknown ROS specific arguments.

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

* Revert changes to utilities.hpp in rclcpp

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

* Fully revert change to utilities.hpp

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

Fix typo in deprecated warning. (#848)

"it's" instead of its

Signed-off-by: Luca Della Vedova <luca@openrobotics.org>

Add throwing parameter name if parameter is not set (#833)

* added throwing parameter name if parameter is not set

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

check valid timer handler 1st to reduce the time window for scan. (#841)

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

remove features and related code which were deprecated in dashing (#852)

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

reset error message before setting a new one, embed the original one (#854)

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>

restored virtual destructor in publisher_base

Signed-off-by: Soragna, Alberto <alberto.soragna@gmail.com>

* fixup a few things after rebase

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

* refactor some API's and get code compiling again

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

* docs and style changes (whitespace)

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

* move new intra process internals into experimental namespace

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

* uncrustify

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

* fix issues with LoanedMessages after rebase

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

* more fixups

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

* readd logic for avoiding in compatible QoS

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

* avoid an error when intra process is disabled

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

* change intra process to preserve pointer in cyclic_pipeline

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

* fix issue matching topics in intra process

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

* fix some issues with the tests after latest behavior change

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

* address review feedback

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

* fix the initialization order

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

* avoid possible loss of data warning

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

* more fixes related to initialization

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

* fix use of custom allocators

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-10-21 16:46:38 -04:00
Ingo Lütkebohle
8fd9a0a00c Instrumentation update (#789)
* Add initial instrumentation
* Rename function registration method and elaborate on object copy issue
* Rely on get_symbol overload instead of using enable_if

Signed-off-by: Christophe Bedard <fixed-term.christophe.bourquebedard@de.bosch.com>
Signed-off-by: Christophe Bedard <christophe.bedard@apex.ai>
Signed-off-by: Ingo Luetkebohle <ingo.luetkebohle@de.bosch.com>
2019-10-18 19:28:04 -03:00
Karsten Knese
ed0bd16e31 Zero copy api (#864)
* loaned message

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

wip

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

loaned message

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

* use publisher allocator

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

* use unique_ptr inside LoanedMessage

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

* can_loan_messages for subscription_base

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

* use correct rcl_publish function

* default move constructor not allowed in gcc

Signed-off-by: Knese Karsten (CR/RTC-HMI4) <karsten.knese@us.bosch.com>

*  remove get_instance and make LoanedMessage constructor public

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

* some more api doc

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

* rebase ontop of master

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

* warn when not being able to loan message

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

* first draft loaned_message_sequence

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

* rmw_take_loaned_message

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

* address review comments

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

* introduce rmw_publish_loaned_message

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

* const correct publish

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

* placement new

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

* disable deleter for callback

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

* print info once

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

* uncrustify

Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-10-18 14:51:24 -07:00
Michel Hidalgo
658f207dd8 Drop rclcpp remove_ros_arguments_null test case. (#894)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-10-17 16:22:57 -03:00
Steven Macenski
d83a947c26 template node type for rclcpp action server and clients (#892)
Signed-off-by: stevemacenski <stevenmacenski@gmail.com>
2019-10-16 18:31:36 -07:00
Michael Carroll
231b991098 Trait tests for generated actions (#853)
* Trait tests for generated actions

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Address reviewer feedback

Signed-off-by: Michael Carroll <michael@openrobotics.org>
2019-10-15 13:51:57 -05:00
Jacob Perron
8e69b7d505 [rclcpp_action] Do not throw exception in action client if take fails (#888)
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-10-14 09:03:59 -07:00
Michel Hidalgo
07cb443a18 [rclcpp_components] Enable intra-process comm via LoadNode request. (#871)
Look for a 'use_intra_process_comms' boolean in extra_arguments.

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-10-10 13:14:24 -03:00
William Woodall
b8f7237087 add mechanism to pass rmw impl specific payloads during pub/sub creation (#882)
* add mechanism to pass rmw impl specific payloads during pub/sub creation

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

* use class instead of struct

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

* narrow API of rmw payload to just use rmw_*_options_t's

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

* fixup after recent change

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-10-08 15:40:27 -07:00
William Woodall
27a97e868c make get_actual_qos return a rclcpp::QoS (#883)
* make get_actual_qos return a rclcpp::QoS

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

* make simpler following suggestion from review

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-10-08 15:15:08 -07:00
Hunter L. Allen
9b4f049277 Fix Compiler Warning (#881)
Signed-off-by: Hunter L. Allen <hunterlallen@protonmail.com>
2019-10-04 16:07:26 -07:00
Brian Marchi
9723576821 Add callback handler for use_sim_time parameter #802 (#875)
* Add callback handler for use_sim_time parameter #802

Signed-off-by: Brian Ezequiel Marchi <brian.marchi65@gmail.com>
2019-10-01 10:14:55 -03:00
Michel Hidalgo
4afd1cd5ad Aggregate all component manager API tests. (#876)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-09-26 18:16:04 -03:00
Michael Carroll
b178c47134 0.8.0
Signed-off-by: Michael Carroll <michael@openrobotics.org>
2019-09-26 14:11:36 -05:00
William Woodall
81049c42c0 clean up publisher and subscription creation logic (#867)
* streamline creation of publishers after removing deprecated API

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

* use deduced template arguments to cleanup create_subscription

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

* add missing file

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

* streamline creation of subscriptions after removing deprecated API

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

* small subscription code cleanup to match publisher's style

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

* some fixes to rclcpp_lifecycle to match rclcpp

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

* add README to the rclcpp/detail include directory

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

* fixup SubscriptionBase's use of visibility macros

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

* reapply function to create default options, as it is still needed on Windows

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

* address review comments

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

* workaround cppcheck 1.89 syntax error

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-09-25 16:22:06 -07:00
Michel Hidalgo
7728d8a38c Take parameter overrides provided through the CLI. (#865)
* Take parameter overrides provided through the CLI.

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

* Address peer review comments.

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

* Do not 'find_package' rcpputils twice.

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-09-25 14:57:49 -03:00
Dirk Thomas
b6d18ccc81 add more context to exception message (#858)
* add more context to exception message

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>

* fix linter warnings

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-09-19 13:15:19 -07:00
Chris Lalancette
9b47f36080 Fix UnknownGoalHandle error string. (#856)
Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2019-09-18 17:52:49 -04:00
Dirk Thomas
cf838d1eb7 reset error message before setting a new one, embed the original one (#854)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-09-17 08:54:39 -07:00
William Woodall
89119c6422 remove features and related code which were deprecated in dashing (#852)
Signed-off-by: William Woodall <william@osrfoundation.org>
2019-09-16 15:37:19 -07:00
fujitatomoya
dfb144d3cb check valid timer handler 1st to reduce the time window for scan. (#841)
Signed-off-by: Tomoya.Fujita <Tomoya.Fujita@sony.com>
2019-09-12 08:26:19 -07:00
ivanpauno
64c0f86f14 Add throwing parameter name if parameter is not set (#833)
* added throwing parameter name if parameter is not set

Signed-off-by: Alex <cvbn127@gmail.com>
Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-09-10 10:21:25 -07:00
Luca Della Vedova
925460dcfb Fix typo in deprecated warning. (#848)
"it's" instead of its

Signed-off-by: Luca Della Vedova <luca@openrobotics.org>
2019-09-09 20:30:42 -07:00
Michel Hidalgo
458967bb56 Fail on invalid and unknown ROS specific arguments (#842)
* Fail on invalid and unknown ROS specific arguments.

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

* Revert changes to utilities.hpp in rclcpp

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

* Fully revert change to utilities.hpp

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-09-06 11:35:36 -07:00
Michel Hidalgo
1fff8cbac1 Force explicit --ros-args in NodeOptions::arguments(). (#845)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-09-05 13:20:47 -03:00
Michel Hidalgo
a6e80fcaea Use of -r/--remap flags where appropriate. (#834)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-09-03 14:34:54 -03:00
Todd Malsbary
f153cf7173 Fix hang with timers in MultiThreadedExecutor (#835) (#836)
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
2019-08-30 14:38:51 -03:00
Dirk Thomas
d5301c1c7c add mutex in add/remove_node and wait_for_work to protect concurrent use/change of memory_strategy_ (#837)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-08-29 15:09:39 -07:00
Guillaume Autran
4feecc5945 Crash in callback group pointer vector iterator (#814)
Signed-off-by: Guillaume Autran <gautran@clearpath.ai>
2019-08-28 18:11:11 -03:00
Jacob Perron
17841d6b7c Wrap documentation examples in code blocks (#830)
This makes the code examples easier to read in the generated documentation.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-08-23 08:58:08 -07:00
bpwilcox
ccd5b49186 add callback group as member variable and constructor arg (#811)
Signed-off-by: bpwilcox <bpwilcox@eng.ucsd.edu>

remove callback group as member variable
2019-08-21 17:02:37 -07:00
ivanpauno
4dbc7192d2 Fix get_node_interfaces functions taking a pointer (#821)
Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-08-21 09:17:25 -03:00
fujitatomoya
65188b021d Delete unnecessary call for get_node_by_group (#823)
Signed-off-by: Tomoya.Fujita <Tomoya.Fujita@sony.com>
2019-08-20 09:24:59 -03:00
Karsten Knese
25f196989c Allow passing logger by const ref (#820)
Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-08-09 09:56:38 -07:00
Dan Rose
78ab3731c9 Explain return value of spin_until_future_complete (#792)
Signed-off-by: Dan Rose <dan@digilabs.io>
2019-08-08 17:29:10 -03:00
Jacob Perron
41a99b64d3 Guard against making multiple result requests for a goal handle (#808)
This fixes a runtime error caused by a race condition when making consecutive requests for the
result.
Specifically, this happens if the user provides a result callback when sending a goal and then
calls async_get_result shortly after.

Resolves #783

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-08-07 09:26:19 -07:00
Michel Hidalgo
871c375da7 Adapt to '--ros-args ... [--]'-based ROS args extraction (#816)
* Use --ros-args to deal with node arguments in rclcpp.

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

* Document implicit --ros-args flag in NodeOptions::arguments().

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

* Add missing size_t to int cast.

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

* Only add implicit --ros-args flag if not present already.

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

* Add some rclcpp::NodeOptions test coverage.

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

* Address peer review comments.

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

* Please cpplint and uncrustify.

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-08-07 12:58:25 -03:00
Dan Rose
4a5eed968c Add line break after first open paren in multiline function call (#785)
* Add line break after first open paren in multiline function call

as per developer guide:
https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#open-versus-cuddled-braces
see https://github.com/ament/ament_lint/pull/148

Signed-off-by: Dan Rose <dan@digilabs.io>

Fix dedent when first function argument starts with a brace

Signed-off-by: Dan Rose <dan@digilabs.io>

Line break with multiline if condition
Remove line breaks where allowed.

Signed-off-by: Dan Rose <dan@digilabs.io>

Fixup after rebase

Signed-off-by: Dan Rose <dan@digilabs.io>

Fixup again after reverting indent_paren_open_brace

Signed-off-by: Dan Rose <dan@digilabs.io>

* Revert comment spacing change, condense some lines

Signed-off-by: Dan Rose <dan@digilabs.io>
2019-08-07 08:33:06 -07:00
Karsten Knese
dc3c36c7f0 remove mock msgs from rclcpp (#800)
Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-08-05 22:43:30 -07:00
Michel Hidalgo
9be3e08cd4 Make TimeSource ignore use_sim_time events coming from other nodes. (#799)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-07-29 16:57:51 -03:00
Siddharth Kucheria
9aacc6d895 fix linter issue (#795)
Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>
2019-07-25 12:44:57 -07:00
Shane Loretz
c1d7c6b7be Remove non-package from ament_target_dependencies() (#793)
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-07-25 09:09:49 -07:00
Siddharth Kucheria
d31ea14985 fix for multiple nodes not being recognized (#790)
Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>
2019-07-24 10:18:04 -07:00
ivanpauno
94ea26bffb Allow registering multiple on_parameters_set_callback (#772)
Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-07-24 14:01:23 -03:00
Siddharth Kucheria
b214324bf2 Cmake infrastructure for creating components (#784)
*cmake macro to create components for libraries with multiple nodes

Signed-off-by: Siddharth Kucheria <kucheria@usc.edu>
2019-07-24 09:15:37 -07:00
Jacob Perron
cd063575ff Add free function for creating service clients (#788)
Equivalent to the free function for creating a service.
Resolves #768

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-07-22 10:25:48 -07:00
Jacob Perron
c7d01d7bf3 Fix typo in test fixture tear down method name (#787)
Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-07-18 14:49:42 -07:00
Michel Hidalgo
8c48dbede7 Include missing rcl headers in use. (#782)
And stop relying on transitive dependencies.

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-07-12 11:01:21 -03:00
Chris Lalancette
f8d609496e Switch the NodeParameters lock to recursive. (#781)
* Switch the NodeParameters lock to recursive.

This is so that the on_set_parameter_callback can successfully
call other parameter methods (like get_parameter) without
deadlocking.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Make sure that modifications can't happen within a callback.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Review fixes.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Set parameter_modification_enabled_ in calls that make modifications.

This will prevent any modification from within modification,
which is a good thing.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Fix windows errors.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Switch to an RAII-style recursion guard.

Also update the documentation.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2019-07-11 14:56:04 -04:00
Yathartha Tuladhar
207bcc5de3 Fixe error messages not printing to terminal (#777)
* 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-07-11 11:25:21 -07:00
Esteve Fernandez
378657865e Add default value to options in LifecycleNode construnctor. Update API documentation. (#775)
Signed-off-by: Esteve Fernandez <esteve@apache.org>
2019-07-02 10:51:47 -03:00
Alberto Soragna
61312b0576 changed on_parameter_event qos profile to rmw_qos_profile_parameter_events (#774)
Signed-off-by: alberto <alberto.soragna@gmail.com>
2019-07-01 12:44:34 -03:00
Carl Delsey
0ccac1e3bd Adding a factory method to create a Duration from seconds (#567)
* Adding a factory method to create a Duration from seconds

There are many places in the ROS codebase where a time duration is
specified as a floating point number of seconds. A factory function
to create a Duration object from these values makes the code a
bit simpler in many cases.

Signed-off-by: Carl Delsey <carl.r.delsey@intel.com>

* Adding some comments to clarify which constructors get matched.

Signed-off-by: Carl Delsey <carl.r.delsey@intel.com>
2019-06-28 12:43:09 -04:00
Scott K Logan
5a5a1fe530 Fix a comparison with a sign mismatch (#771)
Signed-off-by: Scott K Logan <logans@cottsay.net>
2019-06-26 10:26:07 -07:00
Karsten Knese
890b724e6f delete superfluous spaces (#770)
not exactly sure if this was on purpose, but it looks to me like a typo
2019-06-25 01:34:02 +02:00
Scott K Logan
dff36c2f67 Use params from node '/**' from parameter YAML file (#762)
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.

Signed-off-by: Scott K Logan <logans@cottsay.net>
2019-06-24 15:55:15 -07:00
ivanpauno
2069594cc2 Add ignore override argument to declare parameter (#767)
Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-06-24 14:09:36 -03:00
Karsten Knese
e7c463dc74 use default parameter descriptor in parameters interface (#765)
* 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-06-20 10:43:44 -07:00
Esteve Fernandez
2bee266adf 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-06-14 13:09:47 -07:00
M. M
0ae3da49e7 add get_actual_qos() feature to subscriptions (#754)
Signed-off-by: Miaofei <miaofei@amazon.com>
2019-06-12 12:51:29 -03:00
ivanpauno
91198ef917 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-11 12:04:38 -07:00
Shane Loretz
411e748632 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-10 16:37:55 -07:00
Alberto Soragna
4532d9cf78 checking origin of intra-process msg before taking them (#753)
Signed-off-by: alberto <alberto.soragna@gmail.com>
2019-06-06 17:56:50 -03:00
Jacob Perron
24080a458d 0.7.5 2019-05-30 17:31:20 -07:00
ivanpauno
8ff51833ad Avoid 'Intra process message no longer being stored when trying to ha… (#749)
Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-05-30 15:54:02 -03:00
Michael Carroll
347f8d0b1d 0.7.4
Signed-off-by: Michael Carroll <michael@openrobotics.org>
2019-05-29 18:53:14 -05:00
William Woodall
ecc95009f1 Rename parameter options (#745)
* rename initial_parameters in NodeOptions to parameter_overrides

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

* rename automatically_declare_initial_parameters to automatically_declare_parameters_from_overrides

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

* some additional renames I missed

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

* add test for setting after declaring with parameter overrides

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

* fixup NodeOptions docs

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

Co-Authored-By: chapulina <louise@openrobotics.org>

* clarify relationship between allow_undeclared_parameters and parameter_overrides

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-05-29 12:12:42 -07:00
roderick-koehle
d2b2f9124e Bionic use of strerror_r (#742)
Since API 23 Android Bionic uses the GNU convention for strerror_r.
Following bionic/libc line 96,
  https://android.googlesource.com/platform/bionic.git/+/refs/heads/master/libc/include/string.h

Signed-off-by: roderick-koehle <50633232+roderick-koehle@users.noreply.github.com>
2019-05-29 11:15:50 -07:00
ivanpauno
ca01555936 Enforce parameter ranges (#735)
Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-05-29 12:03:06 -03:00
Alberto Soragna
0723a0a6fc removed not used parameter client (#740)
* removed not used parameter client

Signed-off-by: alberto <alberto.soragna@gmail.com>

* moved parameter include directives to time source cpp file

Signed-off-by: alberto <alberto.soragna@gmail.com>
2019-05-28 14:52:32 -07:00
Dirk Thomas
8553fbea7f ensure removal of guard conditions of expired nodes from memory strategy (#741)
* change memory strategy API from vector of nodes to list of nodes

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>

* store guard_condition of node in executor and ensure that it is removed from the memory strategy

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>

* add unit test

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-05-24 15:31:31 -07:00
Jacob Perron
131a11bba5 Guard against calling null goal response callback (#738)
Also make sure to invoke the goal response callback before the result callback.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-05-23 21:00:58 -07:00
Jacob Perron
29308dc8bc Fix typo in log warning message (#737)
Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-05-23 16:10:36 -07:00
Dirk Thomas
06275105fc don't use global arguments for components loaded into the manager (#736)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-05-23 13:06:23 -07:00
ivanpauno
30df5cdf36 Throw nice errors when creating a publisher with intraprocess communication and incompatible qos policy (#729)
* Throw nice errors when creating a publisher with intraprocess communication and history keep all or history depth 0.

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-05-22 15:38:10 -03:00
William Woodall
1a662d46fb 0.7.3 2019-05-20 16:12:29 -07:00
William Woodall
4467ce9913 changelogs
Signed-off-by: William Woodall <william@osrfoundation.org>
2019-05-20 16:12:05 -07:00
Emerson Knapp
005131dba8 I realize why the original was spelled wrong, volatile is a c++ keyword. Modify to not require learning a misspelling, and note why it can't have that name (#725)
Signed-off-by: Emerson Knapp <eknapp@amazon.com>
2019-05-17 18:18:58 -07:00
Emerson Knapp
05c19028f4 volitile -> volatile (#724)
Signed-off-by: Emerson Knapp <eknapp@amazon.com>
2019-05-17 15:37:38 -07:00
Dirk Thomas
a8f4d391f2 fix clang warning (#723)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-05-17 09:26:16 -07:00
Alberto Soragna
0682ceb3e1 Created on_parameter_event static function (#688)
* created static functions

Signed-off-by: alsora <alberto.soragna@gmail.com>
Signed-off-by: alberto soragna <alberto.soragna@gmail.com>

* updated on_parameter_event to new subscriber api

Signed-off-by: alberto soragna <alberto.soragna@gmail.com>

* Update parameter_client.hpp

Reorderd typenames in template

Signed-off-by: alberto soragna <alberto.soragna@gmail.com>

* updated API also for Synchronous client and fixed linter errors

Signed-off-by: alberto soragna <alberto.soragna@gmail.com>

* added empty line at the end of files

Signed-off-by: alberto soragna <alberto.soragna@gmail.com>

* fixed linter error

Signed-off-by: alsora <alberto.soragna@gmail.com>

* added parameter client tests

Signed-off-by: alsora <alberto.soragna@gmail.com>

* added missing includes in unit test

Signed-off-by: alsora <alberto.soragna@gmail.com>
2019-05-16 13:45:10 -07:00
Jacob Perron
2152e0574b Guard against ParameterNotDeclaredException in parameter service callbacks (#718)
Fixes #705.

If the set_parameters() call fails, it's nice to be able to return a partial result.
Since there is no convenient method to obtain a partial result, we call set_parameters()
once for each parameter.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-05-15 16:10:53 -07:00
Michael Jeronimo
1081e75079 Add missing template functionality to lifecycle_node. (#707)
* Add missing template functionality to lifecycle_node.

Recent changes to the node_parameters interface was accompanied by additions to the
node.hpp header and implementation files. However, these additions were not also made
to the corresponding lifecycle node files. This PR includes the changes required for
the lifecycle node.

Going forward, I suggest that any code like this that supplements the basic node interfaces
should either be factored out into a separate header that both node and lifecycle_node
include, or that the supplemental code simply be included in the appropriate node_interface
file directly, if possible. That way we can avoid code duplication and its symptoms which
is node and lifecycle_node getting out of sync (which they have several times).

Signed-off-by: Michael Jeronimo <michael.jeronimo@intel.com>

* consolidate documentation to just be in rclcpp/node.hpp

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

* fix visibility macros

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

* deprecation methods that were also deprecated in rclcpp::Node

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

* fixup variable name

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

* add missing template method implementations

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

* add more methods that were not ported to lifecycle node originally

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

* fix cpplint

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-05-15 15:15:40 -07:00
Prajakta Gokhale
b17bbf31b3 Fix heap-use-after-free and memory leaks reported from test_node.cpp (#719)
Fix AddressSanitizer errors reported by test_node.cpp unit test.

Signed-off-by: Prajakta Gokhale <prajaktg@amazon.com>
2019-05-14 21:08:33 -07:00
William Woodall
ef41059a75 0.7.2 2019-05-08 17:27:05 -07:00
William Woodall
cfeb6a6360 changelogs
Signed-off-by: William Woodall <william@osrfoundation.org>
2019-05-08 17:25:59 -07:00
William Woodall
c769b1b030 change API to encourage users to specify history depth always (#713)
* improve interoperability with rclcpp::Duration and std::chrono

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

* add to_rmw_time to Duration

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

* add new QoS class to rclcpp

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

* changes to NodeBase, NodeTopics, etc in preparation for changes to pub/sub

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

* refactor publisher creation to use new QoS class

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

* refactor subscription creation to use new QoS class

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

* fixing fallout from changes to pub/sub creation

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

* fixed Windows error: no appropriate default constructor available

why? who knows

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

* fixed Windows error: could not deduce template argument for 'PublisherT'

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

* fix missing vftable linker error on Windows

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

* fix more cases of no suitable default constructor errors...

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

* prevent msvc from trying to interpret some cases as functions

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

* uncrustify

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

* cpplint

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

* add C++ version of default action qos

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

* fixing lifecycle subscription signatures

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

* fix allocators (we actually use this already in the pub/sub factory)

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

* suppress cppcheck on false positive syntax error

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

* fix more cppcheck syntax error false positives

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

* fix case where sub-type of QoS is used

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

* fixup get_node_topics_interface.hpp according to reviews and tests

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

* additional fixes based on local testing and CI

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

* another trick to avoid 'no appropriate default constructor available'

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

* fix compiler error with clang on macOS

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

* disable build failure tests until we can get Jenkins to ignore their output

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

* suppress more cppcheck false positives

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

* add missing visibility macros to default QoS profile classes

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

* fix another case of 'no appropriate default constructor available'

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

* unfortunately this actaully fixes a build error on Windows...

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

* fix typos

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-05-08 14:24:40 -07:00
ivanpauno
385cccc2cc Deprecate shared ptr publish (#709)
* Deprecate publish methods with shared_ptr signature

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

* Corrected with PR comments. Deprecated similar methods in lifecycle publisher

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

* Removed reference in unique_ptr publish call

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

* Corrected with PR comments. Corrected warning problem in lifecycle_publisher

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

* Deprecate publish call taking a raw ptr. Stop deprecating publish methods in LifecyclePublisher.

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

* Pleased linter

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

* Corrected mac warning

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

* Corrected serialized publish methods

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

* Avoid windows warning

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

* Not deprecate on windows

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-05-06 13:32:50 -07:00
M. M
d399fef9c6 Implement callbacks for liveliness and deadline QoS events (#695)
* implement deadline and liveliness qos callbacks

Signed-off-by: Miaofei <miaofei@amazon.com>

* fix windows build

Signed-off-by: Miaofei <miaofei@amazon.com>

* address feedback from pull request

Signed-off-by: Miaofei <miaofei@amazon.com>

* update formatting to be compatible with ros2 coding style and ament_uncrustify

Signed-off-by: Miaofei <miaofei@amazon.com>

* make QOSEventHandlerBase::add_to_wait_set() throw

Signed-off-by: Miaofei <miaofei@amazon.com>

* mark throw_from_rcl_error as [[noreturn]]

Signed-off-by: Miaofei <miaofei@amazon.com>

* fix windows compilation error

Signed-off-by: Miaofei <miaofei@amazon.com>

* Ignore uncrustify for single [[noreturn]] syntax instance

Signed-off-by: Emerson Knapp <eknapp@amazon.com>
2019-05-03 10:16:39 -07:00
Jacob Perron
ecf35114b6 Add return code to CancelGoal service response (#710)
* Populate return code of CancelGoal service response

Signed-off-by: Jacob Perron <jacob@openrobotics.org>

* Throw if there is an error processing a cancel goal request

Signed-off-by: Jacob Perron <jacob@openrobotics.org>

* Make cancel callback signature consistent across cancel methods and add tests

Refactored the callback signature for canceling one goal. Now it is the same as the other cancel methods.
This makes it easier to communicate the error code to the user.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>

* Address review

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-05-02 15:25:15 -07:00
Alberto Soragna
7ed130cf7a check for nullptr before publishing event (#714)
Signed-off-by: alberto <asoragna@irobot.com>
2019-05-02 10:24:44 -07:00
Michael Carroll
59d59b0c18 API updates for rmw preallocation work (#711)
* API updates for rmw preallocation work.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Adjust for allocation in serialized message method.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Fix extra take call.

Signed-off-by: Michael Carroll <michael@openrobotics.org>
2019-05-02 11:32:35 -05:00
jhdcs
a8a0788f81 [WIP / Re-Opened] Add functions to return formatted Node Name-Namespace strings (#698)
* Add functions to return formatted Node Name-Namespace strings

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Changed get_node_names to return fully qualified names, removed namespace method
Signed-off-by: Oswin So <oswinso@gmail.com>

* Removed unnecessary capture-by-reference

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Added first draft of tests

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Fixed bug creating phantom empty name/namespaces

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Re-ordered includes

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Swap checks to see if name is in set

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Fixed style errors from uncrustify

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Swapped to unordered_set

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Re-ordered includes again

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* nitpick: minimize vertical whitespace

see: https://google.github.io/styleguide/cppguide.html#Vertical_Whitespace

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

* Add API documentation for added get_node_names function

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Revert to last known semi-working point

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Modified expected test results

A fully-qualified name is "namespace"/"name". If namespace is set to be "/" (as they are in these tests), we would expect a qualified name of "//name"
Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Have get_node_names determine if central slash needed or not

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Corrected tests to not accept double slashes

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Undo changes to .gitignore

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Change qualified string construction to better handle invalid slashes

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Removed debugging statements

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Simplified slash-checking logic

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>
2019-05-01 17:56:05 -07:00
Tully Foote
e9101b49cd Add rcl_node_get_fully_qualified_name (ros2/rcl#255) (#712)
Signed-off-by: RARvolt <rarvolt@gmail.com>
2019-04-30 18:13:16 -07:00
Dima Dorezyuk
078d5ff662 Fixup clock (#696)
* Fix uninitialized bool in clock.cpp

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Fixup includes of clock.hpp/cpp

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Add documentation for exceptions to clock.hpp

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Adjust function signature of getters of clock.hpp/cpp

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Remove raw pointers Clock::create_jump_callback

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Remove unnecessary rclcpp namespace reference from clock.cpp

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Change exception to bad_alloc on JumpHandler allocation failure

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Fix missing nullptr check in Clock::on_time_jump

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Add JumpHandler::callback types

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Add warning for lifetime of Clock and JumpHandler

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Incorporate review

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Incorporate review

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>
2019-04-30 17:22:26 -07:00
Michael Jeronimo
dc05a2e755 Add assignment of parameter-related fields in node options constructor (#708)
* Add assignment of missing parameter-related fields in node options copy constructor.

The allow_undeclared_parameters and automatically_declare_initial_parameters fields of
the node options class were not assigned in the assignment operator, resulting in
an incorrect copy of the node options object, which also indirectly affects the
copy constructor.

Signed-off-by: Michael Jeronimo <michael.jeronimo@intel.com>

* Run linters
2019-04-30 13:47:20 -07:00
ivanpauno
98f610c114 New IntraProcessManager capable of storing shared_ptr<const T> (#690)
* Changed mapped_ring_buffer class to store both shared_ptr or unique_ptr

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

* Changed the IPM store and take methods

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

* Changed publish methods to take advantage of the new IPM

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

* Change how subscriptions handle intraprocess messages

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

* Modified publish method signatures

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

* Renamed 'publisher.cpp' and 'subscription.cpp' to 'publisher_base.cpp' and 'subscription_base.cpp'

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

* Updated lifecycle_publisher publish methods

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-04-30 16:05:53 -03:00
Steven! Ragnarök
d34fa607a2 0.7.1 2019-04-26 11:37:10 -07:00
Jacob Perron
02050c3901 Add optional cancel callback to asynchronous cancel goal methods
Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-04-26 09:21:24 -07:00
Jacob Perron
1a0f8e3f28 Add optional result callback to async_get_result
Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-04-26 09:21:24 -07:00
Jacob Perron
0da966b981 Use options struct for passing callbacks to async_send_goal
Now supports callbacks for the goal response and result.
This also makes it easier to incorporate action clients in composable nodes since we don't have to rely on waiting on futures.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-04-26 09:21:24 -07:00
Shane Loretz
6b10841477 Read only parameters (#495)
* in progress broken test_time_source

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

* style

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

* test undeclared params

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

* Only get parameter if it is set

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

* doc fixup

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

* use override rather than virtual in places

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

* rename ParameterInfo_t to ParameterInfo and just use struct, no typedef

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

* add method to access ParameterValue within a Parameter

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

* enable get<Parameter> and get<ParameterValue> on Parameter class

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

* avoid const pass by value

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

* match type of enum in C++ to type used in message definition

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

* fixup after rebase

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

* more fixup after rebase

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

* replace create_parameter with declare_parameter

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

* provide implementation for templated declare_parameter method

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

* style

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

* do not use const reference when it's a primitive (like bool)

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

* typo

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

* follow to bool change that wasn't staged

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

* fixup tests

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

* added lots of docs, alternative API signatures, and some of the tests

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

* more tests and associated fixes

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

* address documentation feedback

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

* fixup previously added tests

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

* add tests and fixes for describe_parameter(s) and get_parameter_types

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

* remove old parameter tests

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

* use const reference where possible

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

* address comments

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

* fix tests for deprecated methods

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

* address feedback

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

* significantly improve the reliability of the time_source tests

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

* uncrustify, cpplint, and cppcheck fixes

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

* Revert "significantly improve the reliability of the time_source tests"

This reverts commit 3ef385d841.

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

* only declare use_sim_time parameter if not already declared

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

* fixup rclcpp_lifecycle

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

* fixup tests

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

* add missing namespace scope which fails on Windows

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

* extend deprecation warning suppression to support Windows too

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

* fix compiler warnings and missing visibility macro

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

* remove commented left over tests

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

* fix compiler warning on Windows

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

* suppress deprecation warning on include of file in Windows

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

* avoid potential loss of data warning converting int64_t to int

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

* trying to fix more loss of data warnings

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

* fix test_node

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

* add option to automatically declare parameters from initial parameters (yaml file)

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

* remove redundant conditional

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-04-23 10:44:55 -07:00
Guillaume Autran
97ed34a042 Fix a concurrency problem in the multithreaded executor (#703)
Both, the `Executor::execute_any_executable` and the destructor for the `AnyExecutable` object used by the multithreaded executor, reset the `can_be_taken_from_` flag on a MutuallyExclusive group. This cause the variable to get out of sync and threads to process executables out of sequence.

This fix clears the callback group variable of the `AnyExecutable` instance effectively preventing its destructor from modifying the variable at the wrong time.

Issue: #702
Signed-off-by: Guillaume Autran <gautran@clearpath.ai>
2019-04-22 11:39:32 -07:00
Dima Dorezyuk
ddf4d345b3 Fixup utilities (#692)
* Fixed dependencies in the utility.hpp/cpp

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Add missing documentation for exceptions in utility.hpp

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Add rclcpp namespace to the utility.cpp

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Add check for a non-negative nonros_argc value

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Simplify syntax for the return_arguments

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>

* Incorporate Review

Signed-off-by: Dmitrij Dorezyuk <dmitrij.dorezyuk@hotmail.de>
2019-04-19 16:19:17 -07:00
Devin Bonnie
ddcc1ec553 Add method to read timer cancellation (#697)
* Add method to read timer cancellation

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Add improved documentation
Add improved and more unit tests

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Add missing include
Add override for inherited methods

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>

* Addressed review comments

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>
2019-04-18 14:29:38 -07:00
Karsten Knese
60996d1e59 overload for node interfaces (#700)
* overload for node interfaces

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

* remove new line

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

* overload client for node iterfaces

Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-04-17 17:01:26 -05:00
jhdcs
713dd0c184 [WIP] Exception Generator function for implementing "from_rcl_error" (#678)
* Created function to generate exception objects

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Created function to generate exception objects

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Fixed typo

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Fixed typo

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Throw exceptions not created by ret

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Throw exceptions not created by ret

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* convert throw_from_rcl_error to use from_rcl_error

Mostly just a convenience function
Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Updated .gitignore

Please ignore
Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Re-ordered functions to allow compilation

Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* Revert "Updated .gitignore"

This reverts commit bee0ee13ce687bc56bdc7ad1e8382506d9aef428.
Signed-off-by: Jacob Hassold <jhassold@dcscorp.com>

* restore .gitignore to original state

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

* oops, actually restore .gitignore

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-04-16 11:25:25 -07:00
Jacob Perron
68d0ac1e61 Rename action state transitions (#677)
* Rename action state transitions

Now using active verbs as described in the design doc:

http://design.ros2.org/articles/actions.html#goal-states

Connects to ros2/rcl#399.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-04-16 04:46:40 -07:00
M. M
70f48d68b9 correct initialization of rmw_qos_profile_t struct instances (#691)
Signed-off-by: Miaofei <miaofei@amazon.com>
2019-04-15 17:44:44 -07:00
Víctor Mayoral Vilches
fcfe94e404 logging, remove_const before comparison (#680)
* logging, remove_const before comparison

This change removes the const value from the logger before
comparing with std::is_same.

Signed-off-by: Víctor Mayoral Vilches <v.mayoralv@gmail.com>

* logging template, replace remove_const by remove_cv

Signed-off-by: Víctor Mayoral Vilches <v.mayoralv@gmail.com>

* Append typename

Located after compiling rclcpp_action from source

Signed-off-by: Víctor Mayoral Vilches <v.mayoralv@gmail.com>
2019-04-15 11:42:07 -07:00
Steven! Ragnarök
24769507d3 0.7.0 2019-04-14 13:11:48 -07:00
Emerson Knapp
8c00607c39 Options-struct interfaces for creating publishers/subscribers (pre-QoS, standalone) (#673)
* Options-based create_publisher and create_subscription interfaces

Introduce new Options structs for creating publishers and subscribers. Deprecate existing interfaces for checking in CI how often they are used.

Signed-off-by: Emerson Knapp <eknapp@amazon.com>

* Remove default params that resulted in ambiguous declarations.

Signed-off-by: Emerson Knapp <eknapp@amazon.com>

* Remove one deprecation to limit upstream impact, add documentation on pub/sub options, slim down test lambdas character count

Signed-off-by: Emerson Knapp <eknapp@amazon.com>

* Un-abbreviate Allocator in new interfaces/types, define a common Options specialization that doesn't need empty brackets

Signed-off-by: Emerson Knapp <eknapp@amazon.com>

* Suppress cppcheck syntaxError for the one function

Signed-off-by: Emerson Knapp <eknapp@amazon.com>
2019-04-12 16:55:39 -07:00
ivanpauno
af9ae4a61c Replaced strncpy with memcpy (#684)
* Replaced strncpy with memcpy

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-04-05 16:11:01 -03:00
ivanpauno
ed21cf4699 Replace const char * with a std::array<char, TOPIC_NAME_LENGTH> as the key of IPM IDTopicMap (#671)
Use std::array<char, TOPIC_NAME_LENGTH> and not const char * as key in IPM IDTopicMap

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-04-04 17:47:33 -03:00
Dirk Thomas
ee7e642592 refactor SignalHandler logger to avoid race during destruction (#682)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-04-04 09:31:59 -07:00
Michael Carroll
0f25f714fe Introduce rclcpp_components to implement composition (#665)
* Introduce rclcpp_components package

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Keep pointer to NodeWrapper vs NodeInterface.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Remove component registration from rclcpp

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Make topics names private-prefix.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Handle name and namespace with remap rules.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Linting.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Address reviewer feedback.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Change to smart pointers for managing memory.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Update to use rcpputils filesystem/split.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Address reviewer feedback and add docs.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Add tests around ComponentManager.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Lint.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Address reviewer feedback and add overflow check.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Fix CI.

Signed-off-by: Michael Carroll <michael@openrobotics.org>
2019-04-04 11:16:32 -05:00
ivanpauno
d11a10a583 Check QoS policy when configuring intraprocess, skip interprocess publish when possible (#674)
* Only setup intraprocess if 'durability' qos policy is 'volatile'.

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

* Skip interprocess publish when only having intraprocess subscriptions.

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

* Add intraprocess configuration option at publisher/subscription level

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

* Use get_actual_qos when setting-up intraprocess. Add test.

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-04-03 18:03:10 -03:00
Dirk Thomas
8783cdcf96 use do { .. } while(0) around content of logging macros (#681)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-04-03 06:16:57 -07:00
ivanpauno
1f2904f980 Add function to get publisher actual qos settings (#667)
* Added get_actual_qos method to publisher.

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-04-01 17:55:08 -03:00
Karsten Knese
4f2f8def98 fix linter errors in rclcpp_lifecycle (#672)
Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-03-28 11:01:52 -07:00
Vinnam Kim
cb20529e5e Add parameter-related templates to LifecycleNode (#645)
* Add parameter-related templates to LifecycleNode

Signed-off-by: vinnamkim <vinnam.kim@gmail.com>

* Update rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node.hpp

Co-Authored-By: vinnamkim <vinnam.kim@gmail.com>

* Update rclcpp_lifecycle/include/rclcpp_lifecycle/lifecycle_node.hpp
2019-03-27 21:05:42 -07:00
Vinnam Kim
b352d45031 Fix use_sim_time issue on LifeCycleNode (#651)
Signed-off-by: vinnamkim <vinnam.kim@gmail.com>
2019-03-26 16:24:20 -07:00
Marko Durkovic
0a44344f43 Avoid race that triggers timer too often (#621)
The two distinct operations of acquiring and subsequent checking of a
timer have to be protected by one lock_guard against races with other
threads. The releasing of a timer has to be protected by the same lock.

Given this requirement there is no use for a second mutex.

Signed-off-by: Marko Durkovic <marko@ternaris.com>
2019-03-23 00:18:43 -07:00
Dirk Thomas
43f891dac8 add section about DCO to CONTRIBUTING.md 2019-03-20 08:38:07 -07:00
Michael Carroll
d8d64e1efc Expose get_fully_qualified_name in NodeBase API. (#662)
Signed-off-by: Michael Carroll <michael@openrobotics.org>
2019-03-19 13:50:01 -05:00
ivanpauno
2929e4b133 Using ament_target_dependencies where possible (#659)
* Modified rclcpp CMakeLists.txt to use ament_target_dependencies

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

* Modified rclcpp_lifecycle CMakeLists.txt to use ament_target_dependencies

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

* Corrected with PR comment

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-03-19 09:23:10 -03:00
Wei Liu
284d0c1c70 fix wait for service memory leak bug (#656)
* when call wait for service in an while loop, the event will be make forever and never release
* fix it by: creating it when we need

Signed-off-by: reed-lau <geoliuwei@gmail.com>
2019-03-15 09:55:53 -07:00
Peter Baughman
ec64b40a9d Fix test_time_source test (#639)
* Fix flakey test

Signed-off-by: Pete Baughman <pete.baughman@apex.ai>

* Fix lint and uncrustify issues

Signed-off-by: Pete Baughman <pete.baughman@apex.ai>
2019-03-13 10:45:05 -07:00
Emerson Knapp
83beaf8a3f Don't hardcode int64_t for duration type representations (#648)
In LLVM's `libcxx`, `int64_t` doesn't match chrono literals. See example below. To compile, run  `clang++-6.0 -stdlib=libc++ -std=c++14 TEST.cpp`

```
using namespace std::chrono_literals;

template<typename RatioT = std::milli>
bool
wait_for_service(
   std::chrono::duration<int64_t, RatioT> timeout
)
{
   return timeout == std::chrono::nanoseconds(0);
}

int main() {
   wait_for_service(2s);
   return 0;
}

```

Result of compilation
```
TEST.cpp:6:1: note: candidate template ignored: could not match 'long' against 'long long'
wait_for_service(
```

Signed-off-by: Emerson Knapp <eknapp@amazon.com>
Signed-off-by: Steven! Ragnarök <steven@nuclearsandwich.com>
2019-03-12 18:32:41 -04:00
Jacob Perron
fce1d4b86f Add documentation to rclcpp_action
Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-03-12 11:56:18 -07:00
Jacob Perron
b8b875228b Add Doxyfile for rclcpp_action
Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-03-12 11:56:18 -07:00
Michel Hidalgo
718d24f942 update to use separated action types (#601)
* match renamed action types

* fix action type casting

* rename type/field to use correct term

* rename custom GoalID type to avoid naming collision, update types using unique_identifier_msgs

* remove obsolete comments

* change signature of set_succeeded / set_canceled

* change signature of     on_terminal_state_(uuid_, result_msg);set_succeeded / set_canceled

* change signature of set_aborted

* change signature of publish_feedback

* update another test
2019-03-11 21:12:47 -07:00
Michael Jeronimo
d2d9ad8796 Add a method to the LifecycleNode class to get the logging interface (#652)
There are getters for the other interfaces, but the logging interface
appears to have been overlooked.

Signed-off-by: Michael Jeronimo <michael.jeronimo@intel.com>
2019-03-06 13:12:38 -08:00
Shane Loretz
c51b28420f Attempt to fix cppcheck (#646)
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-03-04 11:11:07 -08:00
Shane Loretz
3919ab1897 Wait for action server before sending goal (#637)
Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-02-22 10:30:21 -08:00
ivanpauno
8743bcb0a1 Added count matching api and intra-process subscriber count (#628)
* Added count matching api to publishers. Also, internal method to count intra-process subscriptions

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

* Addressed PR comments

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

* Corrected error checking in publisher interprocess subscription count api. Minimal modifications in test

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

* Moved intraprocess subscription count api to public. Started removing publishers and subscribers from ipm.

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

* Added publisher count api in subscription class

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

* Addressed PR comments

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

* Addressed PR comments

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

* Solved Wreorder

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-02-21 14:18:06 -03:00
Francisco Martín Rico
ef5f3d3fc1 Sub Node alternative (#581)
* Sub Node alternative

* Sub Node alternative

* Test // characters in namespaces

* Sub Node alternative

* Test // characters in namespaces

* Fixing style and warning in the order of initalizing members

* Fixing cases with / in different positions, and adding new tests

* Removing commented methods

* Changing extended_namespace to sub_namespace

* Fixed a bug when merging

* Fixed a bug when merging

* Sub Node alternative

* Sub Node alternative

* Test // characters in namespaces

* Fixing style and warning in the order of initalizing members

* Fixing cases with / in different positions, and adding new tests

* Removing commented methods

* Changing extended_namespace to sub_namespace

* Fixed a bug when merging

* Merge with origin to update branch

* improvements to API and documentation

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

* style and fixing tests

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

* fixup subnode specific tests

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

* remove vestigial function

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

* improve documentation

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

* add test to check interaction between ~ and sub-nodes

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

* typo

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-02-15 12:50:39 -08:00
Yutaka Kondo
10d7b7c72b replace 'auto' to 'const auto &' (#630)
Signed-off-by: Yutaka Kondo <yutaka.kondo@youtalk.jp>
2019-02-12 18:02:29 -08:00
rarvolt
4046563de6 Set Parameter Event Publisher settings #591 (#614)
* Add ability to disable Parameter Event Publisher and change its QoS settings

Signed-off-by: RARvolt <rarvolt@gmail.com>

* address review comments

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

* use NodeOptions struct

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

* remove vestigial doc strings and improve docs

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

* fix lifecycle node constructor

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-02-06 23:04:53 -08:00
Michael Carroll
0f9098e9b6 Replace node constructor arguments with NodeOptions (#622)
* Start work on creaating NodeOptions structure.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Continue work on NodeOptions.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Update tests for NodeOptions impl.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Update documentation and copy/assignment.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Update rclcpp_lifecycle to conform to new API.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Use builder pattern with NodeOptions.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Documentation updates.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* Update rclcpp_lifecycle to use NodeOptions.

Signed-off-by: Michael Carroll <michael@openrobotics.org>

* change to parameter idiom only, from builder pattern

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

* Update rclcpp/include/rclcpp/node_options.hpp

Co-Authored-By: wjwwood <william+github@osrfoundation.org>

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

* follow up with more resets of the rcl_node_options_t

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

* todo about get env

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-02-05 23:10:43 -08:00
William Woodall
c7ac39a0e6 remove dependency on rclpy (#626)
Not sure why it was there in the first place...

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-02-05 16:02:00 -08:00
William Woodall
c0a6b474d7 pass context to wait set (#617)
Signed-off-by: William Woodall <william@osrfoundation.org>
2019-01-24 19:44:07 -08:00
Chris Lalancette
99dd0313ab Get parameter map (#575)
* Add in the ability to get parameters in a map.

Any parameters that have a "." in them will be considered to
be part of a "map" (though they can also be get and set
individually).  This PR adds two new template specializations
to the public node API so that it can take a map, and store
the list of values (so setting the parameter with a name of
"foo" and a key of "x" will end up with a parameter of "foo.x").
It also adds an API to get all of the keys corresponding to
a prefix, and returing that as a map (so a get of "foo" will
get all parameters that begin with "foo.").  Note that all
parameters within the map must have the same type, otherwise
an rclcpp::ParameterTypeException will be thrown.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Fix style problems pointed out by uncrustify/cpplint.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Move tests for set_parameter_if_not_set/get_parameter map to rclcpp.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Rename get_parameter -> get_parameters.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Add in documentation from review.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2019-01-16 14:30:12 -05:00
kuzai
1e91face39 Bind is no longer in std::__1 (#618)
Signed-off-by: kuzai <kuzai@users.noreply.github.com>
2019-01-14 14:31:57 -08:00
Jacob Perron
5c92811739 Refactor server goal handle's try_canceling() function (#603)
Makes use of rcl_action_goal_handle_is_cancelable() for one less rcl_action call.
2019-01-08 11:52:51 -08:00
Jacob Perron
22abd62e31 Fix errors from uncrustify v0.68 (#613) 2018-12-21 10:06:39 -08:00
Alberto Soragna
eb2081bb25 Added new constructors for SyncParameterClient (#612)
* added new constructors for sync parameter client

* sync param client now has raw ptr member instead of shared ptr

* fixed pointer style

* allow objects which do not inherit from node to create a sync parameters client
2018-12-20 14:41:45 -06:00
Steven! Ragnarök
69d7e69957 0.6.2 2018-12-12 21:56:41 -08:00
William Woodall
2e58dde5ef use signal safe synchronization with platform specific semaphores (#607)
* use signal safe synchronization with platform specific semaphores

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

* addressed feedback and refactored into separate files

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

* Apply suggestions from code review

Co-Authored-By: wjwwood <william+github@osrfoundation.org>

* include what you use (cpplint)

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

* avoid redundant use of SignalHandler::

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

* Update rclcpp/src/rclcpp/signal_handler.hpp

Co-Authored-By: wjwwood <william+github@osrfoundation.org>

* fix Windows build

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

* actually fix Windows

Signed-off-by: William Woodall <william@osrfoundation.org>
2018-12-12 21:12:49 -08:00
Tully Foote
c93beb5d16 Resolve startup race condition for sim time (#608)
Resolves #595 

* Separate the Node Time Source from the Node Clock
* Implement initial value checking of use_sim_time parameter parameter
* Be sure to update all newly attached clocks
* Homogenizing the behavior to use the last received value otherwise zero time when enabling sim time.
* Add virtual destructors to interface classes
2018-12-12 11:52:54 -08:00
William Woodall
a54a329153 defer signal handling to a singleton thread (#605)
* [WIP] Refactor signal handling.

* fix deadlock

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

* finished fixing signal handling and removing more global state

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

* add missing include of <condition_variable>

* use unordered map in signal handling class

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

* use consistent terminology

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

* use emplace in map

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

* avoid throwing in destructor

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

* words

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

* avoid throwing from destructors in a few places

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

* make install/uninstall thread-safe

Signed-off-by: William Woodall <william@osrfoundation.org>
2018-12-11 18:17:26 -08:00
Steven! Ragnarök
9da1b95ece 0.6.1 2018-12-06 22:12:26 -08:00
William Woodall
8bffd25746 add wait_for_action_server() for action clients (#598)
* add wait_for_action_server() for action clients

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

* Handle negative timeouts in wait_for_service() and wait_for_action_server() methods.

* Fix uncrustify errors.

* Ignore take failure on services for connext
2018-12-06 18:57:25 -08:00
Shane Loretz
ef2014ac4d adapt to action implicit changes (#602) 2018-12-06 16:42:25 -08:00
Shane Loretz
fe09d937b7 rclcpp_action Server implementation (#593)
* Commiting to back up work, does not function

* Can call user callback when goal request received

* fini action server in destructor

* rename user callback virtual functions

* handle_execute test passes

* Remove out of date comment

* Refactor execute into three functions

* Remove unused file

* Add failing cancel test

* Cancel test passes

* Remove out of date comments

* Make sure server publishes status when accepting a goal

* Send status when goals transition to cancelling

* Refactored sending goal request to its own function

* Refactor cancel request into it's own function

* Comment with remaining tests

* Executing and terminal state statuses

* publish feedback works

* server sends result to clients that request it

* Remove out of date comment

* Add ServerGoalHandle::is_active()

* Cleanup when goals expire

* Can pass in action server options

* cpplint and uncrustify fixes

* Fix clang warnings

* Copy rcl goal handle

* Fix clang warning

* Use intermediate value to avoid left shift on 32bit integer

* RCLCPP_ACTION_PUBLIC everwhere

* Change callback parameter from C type to C++

* Add accessors for request and uuid

* Feedback must include goal id

* Document Server<> and ServerBase<>

* handle_execute -> handle_accepted

* Test deferred execution

* only publish feedback if goal is executing

* Documentation for ServerGoalHandle

* document msg parameters

* remove unnecessary fini

* notify_goal_done only takes server

* Use unique_indentifier_msgs

* create_server accepts group and removes waitable

* uncrustify

* Use weak ptr to avoid crash if goal handle lives longer than server

* Handle goal callback const message

* Goal handle doesn't have server pointer anymore

* Lock goal_handles_ on Server<>

* rcl_action_server_t protected with mutex

* ServerBase results protected with mutex

* protect rcl goal handle with mutex

* is_cancel_request -> is_canceling

* Add missing include

* use GoalID and change uuid -> goal_id

* Keep rcl goal handle alive until it expires on server

* uncrustify

* Move UUID hash

* Log messages in server

* ACTION -> ActionT

* Cancel abandoned goal handles

* Add convert() for C and C++ goal id

* Remove unused variable

* Constant reference

* Move variable declaration down

* is_ready if goal expired

* map[] default constructs if it doesn't exist

* Use rcl_action_get_goal_status_array()

* Array -> GoalID

* Use reentrant mutex for everything

* comment

* scope exit to fini cancel response

* using GoalID
2018-12-06 09:38:01 -08:00
Michel Hidalgo
91167393ea [rclcpp_action] Action client implementation (#594)
* WIP

* Removed async_cancel from action ClintGoalHandle API

* Added status handler to action client goal handler

* Added result handler to action client goal handler

* Identation fix

* Added get/set for action client goal handler

* Changed action client goal handler attrs from rcl to cpp versions

* Added check methods to action client goal handler

* Removed rcl_client pointer from action client goal handler

* Added basic waitable interface to action client

* Updated waitable execute from action client

* Added throw for rcl calls in action client

* Removed duplicated ready flags from action client

* Minor fix

* Added header to action ClientBaseImpl execute

* Mich's update to action client interface

* Added trailing suffix to client pimpl attrs

* Towards a consistent action client

* Misc fixes for the action client

* Yet more misc fixes for the action client

* Few more fixes and shortcuts to deal with missing type support.

* Fixed lint errors in action headers and client

* Fixes to action client internal workflow.

* Misc fixes to get client example to build

* More misck client fixes

* Remove debug print

* replace logging with throw_from_rcl_error

* Wrap result object given by client to user

* Fix a couple bugs trying to cancel goals

* Use unique_indentifier_msgs

* create_client accepts group and removes waitable

* Uncrustify fixes

* [rclcpp_action] Adds tests for action client.

* [WIP] Failing action client tests.

* [rclcpp_action] Action client tests passing.

* Spin both executors to make tests pass on my machine

* Feedback callback uses shared pointer

* comment about why make_result_aware is called

* Client documentation

* Execute one thing at a time

* Return nullptr instead of throwing RejectedGoalError

* ClientGoalHandle worries about feedback awareness

* cpplint + uncrustify

* Use node logging interface

* ACTION -> ActionT

* Make ClientBase constructor protected

* Return types on different line

* Avoid passing const reference to temporary

* Child logger rclcpp_action

* Child logger rclcpp_action

* possible windows fixes

* remove excess space

* swap argument order

* Misc test additions

* Windows independent_bits_engine can't do uint8_t

* Windows link issues
2018-12-05 14:51:23 -08:00
Dirk Thomas
33f1e1776c remove trailing spaces (regression from #584) 2018-12-05 09:12:57 -08:00
bpwilcox
9d7b50e4f7 adding node path and time stamp to parameter event message (#584)
modify adding clock for rclcpp_lifestyle
2018-12-04 14:24:48 -08:00
Shane Loretz
9c25ba9a4a Allow removing a waitable (#597) 2018-12-04 13:02:57 -08:00
William Woodall
3af8d2cfed refactor init to allow for non-global init (#587)
* refactor init to allow for non-global init

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

* Update rclcpp/include/rclcpp/utilities.hpp

Co-Authored-By: wjwwood <william+github@osrfoundation.org>

* Update rclcpp/include/rclcpp/utilities.hpp

Co-Authored-By: wjwwood <william+github@osrfoundation.org>

* Update rclcpp/include/rclcpp/utilities.hpp

Co-Authored-By: wjwwood <william+github@osrfoundation.org>

* Update rclcpp/src/rclcpp/utilities.cpp

Co-Authored-By: wjwwood <william+github@osrfoundation.org>

* refactor state into context objects and fix signal handling

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

* avoid nullptr access in error messages

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

* avoid exception in publish after shutdown was called

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

* fix missing and unused headers

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

* cpplint

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

* fixes found during testing

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

* address bug found in review comment

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

* fixes and warnings fixed during testing

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

* addressing review comments

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

* ensure new ExecutorArgs are used everywhere
2018-11-29 21:33:01 -08:00
Dirk Thomas
36262a5cf5 Merge pull request #596 from ros2/fix_wrong_use_of_constructor
fix wrong use of constructor and hanging test
2018-11-29 06:15:22 -08:00
Dirk Thomas
03cbc1c895 call shutdown in test 2018-11-28 21:14:46 -08:00
Dirk Thomas
457b0e7077 fix wrong use of constructor 2018-11-28 16:44:18 -08:00
Jacob Perron
27b0428f7a [rclcpp] Add class Waitable (#589)
* [rclcpp] Add class Waitable

Provides a virtual API for interacting with wait sets.

* [rclcpp] Add node interface for Waitables

* [rclcpp] Implement node interface for Waitables

* [rclcpp] Integrate Waitable entities with executor

* Implement remaining logic for integrating Waitables

* Add visibility macros and other refactoring to Waitable class

* Return zero size for entities in a Waitable by default

* Bugfix: Clear list of waitable handles

* Bugfix: update Waitable handle list based on readiness

* Bugfix: update for loop condition

* Give node a node_waitables_

* Give lifecycle node a node_waitables
2018-11-22 14:03:51 -08:00
Shane Loretz
be010cb2d5 Skeleton for Action Server and Client (#579)
* Skeleton for ActionServer and ActionClient
2018-11-21 09:16:51 -08:00
Jacob Perron
f212d73413 Update rcl_wait_set_add_* calls (#586)
Now the functions take an optional output index argument.
Refactored the graph listener usage of rcl_wait_set_add_guard_condition() to take advantage of the new API.
2018-11-20 11:02:13 -08:00
Steven! Ragnarök
c8f3fd3b0e 0.6.0 2018-11-19 07:47:26 -08:00
William Woodall
33a755c535 use new error handling API from rcutils (#577)
Signed-off-by: William Woodall <william@osrfoundation.org>
2018-11-01 21:08:54 -05:00
Karsten Knese
ec834d321b delete TRANSITION_SHUTDOWN (#576) 2018-10-31 19:20:03 -07:00
Francisco Martín Rico
e30f31551e issue a warning if publishing on a not active publisher (#574)
* issue a warning if publishing on a not active publisher

* Adding a logger private member in LifecyclePublisher for avoiding creating a new one echa call
2018-10-27 17:35:17 -07:00
Francisco Martín Rico
b600c18121 Providing logging macro signature that accepts std::string (#573)
* Providing logging macro signature that accepts std::string

* - RCLCPP_ prefix to macros Add
- New tests added

* - Added doc to the functions and macros
- Functions declared as RCLCPP_PUBLIC

* - Small typo in doc corrected

* Fixed error when compiling with clang

* touch up docs
2018-10-25 15:49:38 -07:00
cho3
144c24c8fd Add SMART_PTRS_DEF to LifecyclePublisher (#569) 2018-10-11 17:33:41 -07:00
Karsten Knese
3353ffbb15 service for transition graph (#555)
* service for transition graph

* remove keys, transition id unique, label ambiguous

* semicolon for macro call
2018-10-11 14:03:57 -07:00
Chris Lalancette
bedb3ae361 Add virtual destructors to classes with virtual functions. (#566)
This fixes the build on MacOS High Sierra and later, and
is the more correct thing to do anyway.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2018-10-08 11:02:08 -04:00
Chris Lalancette
b3cbf06c09 Add semicolons to all RCLCPP and RCUTILS macros. (#565)
Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2018-10-05 17:30:22 -04:00
Anis Ladram
eb439ddc73 Removing std::binary_function usage (#561)
Deprecated in C++11, removed in C++17
2018-10-02 09:49:17 +02:00
dhood
6ff3ff43fe Don't auto-activate ROS time if clock topic is being published (#559)
* Don't auto-activate ROS time if clock topic is being published

* Destroy subscription when not needed, avoid re-creating it

* Additional tests

* Always reset pointer

* Initialise sub in initialiser list
2018-09-25 08:34:25 -07:00
Mikael Arguedas
f6c2f5ba0d use add_compile_options instead of setting only cxx flags 2018-09-20 11:13:23 -07:00
Shane Loretz
e8d3fdd56c Fix cpplint on xenial (#556)
* Change variable name to fix cpplint on xenial

* Set variable to null to satisfy cpplint

* additional null
2018-09-20 09:19:45 -07:00
Chris Lalancette
be8c05ed9e Implement get_parameter_or_set_default. (#551)
* Implement get_parameter_or_set_default.

This is syntactic sugar to allow the user to get a parameter.
If the parameter is already set on the node, it gets the value
of the parameter.  If it is not set, then it gets the alternative
value and sets it on the node, ensuring that it exists.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Review fixes (one sentence per line).

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Rename get_parameter_or_set_default -> get_parameter_or_set

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2018-09-20 09:21:24 -04:00
Shane Loretz
b860b899e5 Add max_duration to spin_some() (#558)
With max_duration spin_some will execute work until it has spent more
time than the elapsed duration.
2018-09-17 15:51:15 -07:00
dhood
86cc8fdb3a Output rcl error message when yaml parsing fails (#557) 2018-09-13 17:46:56 -07:00
dhood
80595f37d1 Link to ticket re rcl_yaml_param_parser avoiding circular dependency 2018-09-13 17:10:39 -07:00
Shane Loretz
b1af28047c Make sure timer is fini'd before clock (#553)
* Make sure timer is fini'd before clock
2018-09-07 17:28:10 -07:00
Michael Carroll
8c6f38a0fa Get node names and namespaces (#545)
* Rework to account for new get_node_names signiture.

* cpplint.

* Address reviewer feedback.
2018-09-06 08:02:44 -05:00
William Woodall
198c6daf49 Doc fixups (#546)
* add missing docs for number_of_threads parameter

* add missing docs for start_parameter_services parameter

* add missing docs for parameters, rename short variable name

* doc fixups
2018-08-31 18:32:20 -07:00
Shane Loretz
a55e320e6e Use rcl_clock_t jump callbacks (#543)
* Use rcl_clock_t jump callbacks

Relieves rclcpp::TimeSource responsibility of calling jump callbacks.
2018-08-28 10:12:12 -07:00
Shane Loretz
4653bfcce6 Rcl consolidate wait set functions (#540)
* Use consolidated rcl_wait_set_clear()

* Use consolidated rcl_wait_set_resize()
2018-08-27 11:55:04 -07:00
Sagnik Basu
18ad26e654 Add TIME_MAX and DURATION_MAX functions (#538)
* Add TIME_MAX and DURATION_MAX functions

* Fix Linting Errors

* change funtion name as per coding style

* change function name as per coding style

* Update duration.cpp

* Update time.cpp

* Update test_duration.cpp

* Update time.hpp

* remove extra empty line
2018-08-27 11:44:25 -07:00
Karsten Knese
354d933870 publish shared_ptr of rcl_serialized_message (#541)
* publish shared_ptr of rcl_serialized_message

* const parameter
2018-08-24 14:34:51 -05:00
Dirk Thomas
25a9b4e339 add Time::is_zero and Duration::seconds (#536)
add Duration::seconds
2018-08-20 08:58:32 -07:00
Karsten Knese
45d74ba4dc log error message instead of throwing exception in destructor (#535) 2018-08-17 10:17:37 -07:00
dhood
e409e44413 Relax tolerance of now test because timing affected by OS scheduling (#533) 2018-08-17 10:03:45 -07:00
Shane Loretz
6b34bcc94c Remove incorrect exception on sec < 0 (#527)
* Remove incorrect exception on sec < 0
2018-08-09 09:23:33 -07:00
Shane Loretz
ea047655d8 Add rclcpp::Time::seconds() (#526)
* Get seconds since epoch as double
2018-08-08 16:04:35 -07:00
Dirk Thomas
4ddb76f466 construct TimerBase/GenericTimer with Clock (#523)
* construct TimerBase/GenericTimer with Clock

* pass rcl_time_point_value_t to rcl_clock_get_now

* update docblocks
2018-07-27 18:27:25 -07:00
chapulina
fba891c0df Implement rclcpp::is_initialized() (#522)
* Implement rclcpp::is_initialized()

* linter
2018-07-26 13:17:33 -07:00
dhood
8f2052d65a Support jump handlers with only pre- or post-jump callback (#517)
* Add failing tests for partial jump handlers

* Code deduplication

* Check callbacks before calling them
2018-07-18 07:11:35 +10:00
Mikael Arguedas
3067a72a2a nothing uses std_msgs anymore (#513) 2018-07-17 13:24:04 -07:00
Dirk Thomas
0ad17575a2 remove use of uninitialized CMake var (#512) 2018-07-11 14:08:09 -07:00
Mikael Arguedas
ae6f8e3e9a Uncrustify 0.67 (#510)
* fix indentation to comply with uncrusity 0.67

* fix spacing before opening brackets

* space between reference and variable name in signature

* questionable space between pointer marker and variable name
2018-07-11 08:31:11 -07:00
Dirk Thomas
d36910d2d7 remove use of uninitialized CMake var (#511) 2018-07-10 16:51:09 -07:00
Sriram Raghunathan
93e2945802 Expose get_node_names API from node. (#508)
* Exposing get_node_names from node handle

Signed-off-by: Sriram Raghunathan <rsriram7@visteon.com>

* Exposing get_node_names from node handle for lifecycle_nodes

Signed-off-by: Sriram Raghunathan <rsriram7@visteon.com>

* Fix stray demangle type
2018-07-05 17:45:09 -07:00
Mikael Arguedas
4507d7a40b Fix rosidl dependencies (#507)
* [rclcpp_lifecycle] remove rosidl deps as this package doesnt generate any messages

* depend on rosidl_typesupport_cpp
2018-07-05 13:01:23 -07:00
Dirk Thomas
1869b84a0c 0.5.1 2018-06-28 16:34:33 -07:00
William Woodall
a49281cff3 keep shared pointer reference to rcl_node handle for subscription fini (#505) 2018-06-27 13:37:49 -07:00
William Woodall
4d67a8671b 0.5.0 2018-06-25 16:31:01 -07:00
William Woodall
f5c3854585 changelogs 2018-06-25 16:30:51 -07:00
William Woodall
39c22c8508 typo (#502) 2018-06-19 12:43:06 -07:00
Michael Carroll
bf89dc0797 Further expand test tolerance to address flakiness. (#501)
* Further expand test tolerance to address flakiness.

* Remove newline.
2018-06-19 13:06:30 -05:00
William Woodall
62c8c5b762 executor could take more than once incorrectly (#383)
* Baseline test and force threads to yield.

* Add timer tracking for executor.

* Add locking and test happy-path exit conditions.

* Move logic to multi_threaded_executor

* Address reviewer feedback by reducing scope of set.

* Expand tolerance on testing.

* comment fixup

Otherwise it seemed to me like it would yield twice.
2018-06-18 22:46:28 -05:00
Karsten Knese
d33a46c3b6 comply to new subscription template (#500) 2018-06-19 00:20:55 +02:00
William Woodall
bfbb263f3c fix tests due to changes in rcutils (#452) 2018-06-16 13:48:01 -07:00
Karsten Knese
ec17d68b41 *_raw function (#388)
* publish_raw function

* subscription traits

* listener raw

* rebased

* cleanup and linters

* explicit test for deleter in unique_ptr

* add missing copyright

* cleanup

* add rmw_serialize functions

* linters

* explicit differentiation between take and take_raw

* cleanup debug messages

* rename to rmw_message_init`

* address comments

* address review comments

* raw->serialized

* use size_t (#497)
2018-06-16 10:36:00 +02:00
William Woodall
1556b6edf4 always get service name from rcl to account for remapping (#498) 2018-06-14 21:42:00 -07:00
Mikael Arguedas
1b87970d8e add missing set_parameters_atomically client (#494) 2018-06-12 01:53:40 +02:00
Shane Loretz
4886b2485c Initialize params via yaml from command line (#488)
* Initialize params from yaml files
2018-06-08 17:24:29 -07:00
Shane Loretz
9b294ec720 Get parameters that aren't set (#493)
* Document get_parameters()

* Return NOT_SET params in get params service
2018-06-06 10:23:42 -07:00
Shane Loretz
84c8d58612 Pass initial parameter values to node constructor (#486)
* Pass parameter values to node constructor
2018-06-05 15:29:20 -07:00
Shane Loretz
8f793fdb4a Convert rcl_params_t to ParameterMap (#485)
Convert from rcl_params_t to map of node parameters

Adds rclcpp::parameter_map_from(const rcl_params_t * const)
Adds rclcpp::parameter_value_from(const rcl_variant_t * const)
Adds dependency on rcl_yaml_param_parser
2018-06-05 10:54:08 -07:00
Dirk Thomas
5ab6bde1db fully delete parameters (#489)
* allow ParameterValue class to be copy constructed with type not-set

* actually remove deleted parameters from the map
2018-06-04 15:06:01 -07:00
dhood
2a17232ad0 Subscription tests using bind in member callback (#480)
* Add tests for member callbacks

* Add tests for member callback in Test class (not working with gcc7)

* Uncomment test that was failing

* Linter fixup
2018-06-04 12:48:02 -07:00
Shane Loretz
d298fa4445 Split ParameterVariant into Parameter and ParameterValue (#481)
* Split ParametrVariant into Parameter and ParameterValue
* Test expects ParameterTypeException
* get_parameter_value() -> get_value_message()
* Make to_parameter() const and rename to to_parameter_msg()
2018-06-01 11:48:56 -07:00
Esteve Fernandez
97575fd59b Relax template matching rules for std::bind and GNU C++ >= 7.1 (#484)
* Relax template matching rules for std::bind and GNU C++ >= 7.1

* Document reason test was added
2018-06-01 13:28:45 -04:00
Ernesto Corbellini
d6057270f2 Use rosgraph_msgs/Clock for /clock topic. (#474)
* Use rosgraph_msgs/Clock for /clock topic.

* Update the test cases.
2018-05-31 01:32:08 +02:00
Shane Loretz
4efcd330fe Spin before checking if clock changed (#483) 2018-05-30 15:09:30 -07:00
Shane Loretz
d82ce9666c Autostart parameter services (#478)
* Autostart parameter services
* Add bool start_parameter_services
2018-05-25 13:07:59 -07:00
dhood
f9a78df9fe Workaround for wait_for_service lasting the full timeout with connext (#476)
* Limit wait_for_graph_change timeout as alternative workaround for connext

* Increase max wait time to 100ms
2018-05-22 21:01:47 -04:00
Tom Moore
15d505ec1f Adding parameter array support (#443)
* Adding parameter array support

* PR feedback

* Matching changes in upstream branch

* EXPECT_EQ takes expected value a first argument and actual as second
2018-05-10 16:05:52 -07:00
Michael Carroll
1be4d2d914 Fix bug when mixing shared_ptr and bind. (#470) 2018-05-04 13:10:47 -05:00
Shane Loretz
7cd8429534 Fini arguments passed to rcl_node_init() (#468)
* Fix memory leak in node_base
* Always free arguments
2018-05-01 12:59:15 -07:00
Mikael Arguedas
66a7c62531 update to rcutils logging in commented code as well (#466) 2018-04-27 15:31:08 -07:00
William Woodall
1610fc3973 pass AnyExecutable objects as reference to avoid memory allocation (#463)
* pass AnyExecutable objects as reference to avoid memory allocation

* remove style change
2018-04-17 21:54:42 -05:00
Shane Loretz
360f1b9425 Add CLI args to Node constructor (#461)
* Add CLI args to Node constructor

Adds arguments and use_global_arguments to NodeBase

* Check for integer overflow
2018-04-17 10:52:49 -07:00
Michael Carroll
07e5be7621 Correctly clean up arguments structure. (#459)
* Correctly clean up arguments structure.
* Use zero-initialized structure.
2018-04-11 12:43:18 -05:00
Dirk Thomas
45dcd0c6e5 handle node names which are null (#435) 2018-03-30 10:56:06 -07:00
Matthew
fa81d95e33 Add argument for thread count to multithreaded executor (#442) 2018-03-29 17:18:00 -07:00
Michael Carroll
ef17ec6248 Remove ros arguments (#454)
* Mark arguments vector as const.

* Add C++ version of rcl_remove_ros_arguments
2018-03-27 14:57:23 -07:00
Dirk Thomas
5f1fc660ea change export order for static linking (#446) 2018-03-22 16:26:42 -07:00
jwang11
947e3f7e67 Fix time type issue in time unittest (#453)
Obviously it mean RCL_SYSTEM_TIME but not RCL_ROS_TIME in some test cases

Signed-off-by: jwang <jing.j.wang@intel.com>
2018-03-20 15:43:40 -07:00
William Woodall
9ce5aaa792 Revert "Revert "Store the subscriber, client, service and timer"" (#449)
* Revert "Revert "Store the subscriber, client, service and timer (#431)" (#448)"

This reverts commit 168d75cf1e.

* Convert all rcl_*_t types to shared pointers

Converts all rcl_*_t types in the memory allocation strategy to shared pointers to prevent crash happening when a subscriber is reset.

Issue: #349

* fixups
2018-03-19 21:05:26 -07:00
jwang
af6e86c522 Make rclcpp::Duration support scale operation
Duration scale is a convinient operation which had supported in ROS.
This commit make ROS2 support it.

Signed-off-by: jwang <jing.j.wang@intel.com>
2018-03-16 00:56:32 -07:00
William Woodall
d8abea55ec make log location parameter const (#451) 2018-03-15 18:05:15 -07:00
William Woodall
168d75cf1e Revert "Store the subscriber, client, service and timer (#431)" (#448)
This reverts commit 36526469c7.
2018-03-13 18:37:52 -07:00
Denise Eng
36526469c7 Store the subscriber, client, service and timer (#431)
* Convert all rcl_*_t types to shared pointers

Converts all rcl_*_t types in the memory allocation strategy to shared pointers to prevent crash happening when a subscriber is reset.

Issue: #349

* fixup! Convert all rcl_*_t types to shared pointers

* fix { use on function definitions

We always put the { on a new line for function definitions and class declarations.
2018-03-12 11:26:11 -07:00
Dirk Thomas
1a604b0c28 update style (#445) 2018-03-01 08:58:52 -08:00
Mikael Arguedas
2b7cb21cbd advise to ask questions on ROS answers 2018-02-26 22:01:36 -08:00
dhood
787de6ebf1 Get node's logger name from rcl (#433)
* Get logger name from rcl [direct]

* Get logger name from rcl [indirect]

* Update tests

* fixup on variable usage

* Move get_logger_name to NodeLogging interface
2018-02-26 14:36:10 -08:00
dhood
3786c91deb Use ament_cmake_ros (#444)
* Control shared/static linking via BUILD_SHARED_LIBS

* Remove rmw dependency

* Add for rclcpp_lifecycle too

* exec depend on ament_cmake is for normalize_path
2018-02-26 09:46:44 -08:00
Guillaume Autran
0e79842b6b rclcpp logging still uses fprintf all over the place. (#439)
* rclcpp logging still uses fprintf all over the place.

Remove all printf log lines and replace with RCLUTILS_LOG_XXX macros.

Issue: #438

* fixup include order
2018-02-23 17:24:37 -08:00
William Woodall
f88ade7a2a avoid using invalid iterator when erasing items using an iterator in a loop (#436)
* avoid using invalid iterator when erasing items using an iterator in a loop

* do not overwrite iterator in cases where it will be unused
2018-02-02 16:46:24 -08:00
serge-nikulin
3a503685bf change rcutils_time_point_value_t type from uint64_t to int64_t (#429)
* change rcutils_time_point_value_t type from uint64_t to int64_t

* small style changes

* fix test time datatype

* Update time primatives to int64_t

* change time primitive datatype to signed

* A few more instances of UL to L
2018-02-01 13:50:33 -08:00
Mikael Arguedas
e4b5c0bbb9 Byte array parameter rename (#428)
* rename bytes_value to byte_values

* adapt enum to new names

* rename byte_values to byte_array_values

* linters
2018-01-26 15:03:22 -08:00
jwang11
e08c80052a Move clear wait set from after rcl_wait to ahead (#427)
* Move clear wait set from after rcl_wait to ahead

Current code clear wait set after rcl_wait, it is not respond latency
friendly. In fact, clear wait set operation is not urgent, making sure it is
done before next rcl_wait should be fine.

Signed-off-by: jwang <jing.j.wang@intel.com>

* remove trailing whitespace
2018-01-18 18:49:52 -08:00
Ethan Gao
b81f55e5df Fix the dereference to NULL (#405)
* Fix the dereference to NULL
rmw_*_validation_result_string(validation_result) may return NULL,
and it's dereferenced by passing arg to NameValidationError

Signed-off-by: Ethan Gao <ethan.gao@linux.intel.com>

* address NULL case of undefined type

Signed-off-by: Ethan Gao <ethan.gao@linux.intel.com>

* Address the issue to deference to NULL with adapt
to the change of API rmw_*_validation_result_string

Signed-off-by: Ethan Gao <ethan.gao@linux.intel.com>

* revise the typo

* throw exception when valid rmw check but invalid rcl check

Signed-off-by: Ethan Gao <ethan.gao@linux.intel.com>
2018-01-09 06:02:23 +11:00
Sriram Raghunathan
2bf688827b Change rmw_count_publishers API, to rcl equivalent rcl_count_publishe… (#425)
* Change rmw_count_publishers API, to rcl equivalent rcl_count_publishers and remove the TODO line.

Signed-off-by: Sriram Raghunathan <rsriram7@visteon.com>

* Remove rmw_handle and refer to rcl_node_handle, change the API signature to topic_names.

Signed-off-by: Sriram Raghunathan <rsriram7@visteon.com>

* Use rcl_* specific functions to derive the fully qualified topic name.

Signed-off-by: Sriram Raghunathan <rsriram7@visteon.com>

* [nitpick] remove unnecessary variable storage
2017-12-19 19:45:58 -08:00
Ethan Gao
199a26984d Fix the potential application crash issues (#426)
* err msg

* err msg

* Fix the potential application crash issues

Signed-off-by: Ethan Gao <ethan.gao@linux.intel.com>

* minor tweak the code structure

Signed-off-by: Ethan Gao <ethan.gao@linux.intel.com>
2017-12-19 16:39:56 -05:00
Mikael Arguedas
bea1a52e24 0.4.0 2017-12-08 18:06:51 -08:00
Karsten Knese
3e0fa4be66 deallocate state and transition handles after call to fini (#424)
* deallocate state and transition handles after call to fini

* deallocate also when error occured
2017-12-06 17:26:18 -08:00
Karsten Knese
6d13bcb0fc Fix 394 (#419)
* copy and assignment operator for state

copy and assignment operator for transition

remove unused const_casts

address comments

check for null in copy constructor

up

use init and fini functions from rcl

remove unused include

* explicitly zero initialize state and transitions

* add todo comment for follow up
2017-12-05 22:51:52 -08:00
Karsten Knese
c40f3c25c6 Fix 393 (#418)
* correctly copy state label

* correctly copy transition label

* uncrustify

* address comments

* up

* use init and fini functions from rcl
2017-12-05 20:22:57 -08:00
dhood
d823982f22 Allow logger to be passed into macros as a reference (#423)
* Remove reference for logger so it can be rclcpp::Logger &

This is the type when captured by reference in a lambda; windows can't
resolve it without.

* Wrap lines
2017-12-05 15:12:20 -08:00
dhood
6129a12df5 Remove namespaces and namespace escalation e.g. node:: (#416)
* Remove publisher:: namespace

* Remove subscription:: namespace

* Remove client:: namespace

* Remove service:: namespace

* Remove parameter_client:: namespace

* Remove parameter_service:: namespace

* Remove rate:: namespace

* Remove timer:: namespace

* Remove node:: namespace

* Remove any_service_callback:: namespace

* Remove any_subscription_callback:: namespace

* Remove event:: namespace

* Remove ContextSharedPtr escalation

Users can use the  directive themselves if they want

* Remove single_threaded_executor:: namespace

* Remove multi_threaded_executor:: namespace

* Remove context:: namespace

* node:: removal from new logger additions

* Fix linter issues that has been triggered with uncrustify

* Remove utilities:: namespace
2017-12-05 15:02:00 -08:00
Tully Foote
713ee8059c Mirror clock API from Node to LifecycleNode (#417)
* Mirror clock API from Node to LifecycleNode

Follow up to #407

* adding headers for completeness
2017-12-05 00:25:28 -08:00
dhood
2e4e85f141 Add Logger class and give one to nodes (#411)
* Add Logger class and give one to nodes

* Try to improve compiler errors when non-Logger is passed to macros

* Add define for 'disabling' loggers

* Add/update tests

* Linter fix

* Documentation

* Windows fix

* Move free functions to source file (windows was upset)

* Fix windows by changing prototype ordering

* Store node logger in NodeBase

* Windows is not happy with this EXPECT_ANY_THROW

* Move get_logger to a NodeLogger interface

* Move Logger into 'logger' namespace

* Move helper function for macro errors into macro header

* Remove 'logger' namespace

* Return type on separate line

* Update copyright year

* Give lifecycle nodes a logger

* Add test for lifecycle node logger

Move the default_state_machine tests to another file because having
different test fixtures was causing init to be called twice.

* Switch to static_assert for logger check

* global ns scope in macro calls

just in case

* Revert "Add test for lifecycle node logger" (make diff smaller)

demos use the loggers and we don't test other node stuff in lifecycle_node

* Update for rcutils function name change

* Add reference to Node::get_logger() in doxygen

* Rename NodeLoggerInterface to NodeLoggingInterface
2017-12-04 16:07:29 -08:00
dhood
d989bd15c1 Prevent callback from being captured as a reference (#414) 2017-12-03 19:26:30 -08:00
dhood
bc47fa83dc Rename severity_threshold -> level (#412) 2017-12-03 18:40:28 -08:00
dhood
8177771773 Allow creating parameter client from constructor of Node subclass (#413) 2017-12-03 17:12:43 -08:00
dhood
e9f0328ec8 Allow client to trigger another service call from its callback (#415) 2017-12-03 17:11:50 -08:00
Tully Foote
284dc17918 Add a clock interface to the Node API (#407)
node clock interface lower level abstraction
Update node and node interface to expose get_clock and now.
add unit tests to cover node clock API
2017-11-30 14:07:23 -08:00
dhood
3b06aa3721 Escalate more namespaces e.g. rclcpp::Service (#410) 2017-11-30 13:27:44 -08:00
Tully Foote
3426696541 provide a class to filter parameter events conveniently based on name and type of parameter event (#391)
adding test for parameter events filter
2017-11-29 11:11:18 -08:00
Mikael Arguedas
7bbf5f6e5b waitset -> wait_set (#408)
* waitset -> wait_set

* cpplint

* use wait set in doc

* doc fixup
2017-11-27 13:30:07 -08:00
Tully Foote
5e64191e10 Resolve erase race condition. (#406)
Fixes #401

Extend time source tests to allocate and deallocate callback handlers.
2017-11-21 20:44:28 -08:00
Tully Foote
5e565c7e75 detach nodes from executors in destruction. (#404) 2017-11-21 11:42:44 -08:00
Hunter Allen
9be9d66da5 Remove const modifier to prevent compiler error for GCC 8. (#403) 2017-11-20 15:54:53 -05:00
Tully Foote
5c57de016f work around windows failing debug test. Ticketing full debugging separately. (#402) 2017-11-19 20:09:41 -08:00
William Woodall
eed5999221 small doc touchup (#400) 2017-11-17 16:06:06 -08:00
Mikael Arguedas
e08428c79b include cstdlib for std::abs function (#399) 2017-11-17 11:26:52 -08:00
Tully Foote
a215d2d22e update rclcpp to use the refactored TimeSource Clock logic (#371)
This implements a TimeSource in rclcpp, adds the Clock class.
2017-11-16 17:26:56 -08:00
dhood
24f39700c6 Implement rclcpp-specific logging macros [taking name not object] (#389) 2017-11-15 14:14:09 -08:00
Karsten Knese
989084b3de move callback (#387) 2017-10-15 22:40:03 -07:00
G.A. vd. Hoorn
70d2b4b739 macros: fix two minor typos in doxygen. (#386) 2017-10-13 12:08:10 -07:00
G.A. vd. Hoorn
c182f5805e lifecycle: fix minor typo in LC pub Doxygen (#384) 2017-10-13 06:25:20 -07:00
Karsten Knese
022b2b1b80 sync parameter takes optional remote node name (#380) 2017-10-02 11:46:00 -07:00
Dirk Thomas
070b3125c1 Merge pull request #382 from ros2/remove_indent_off
remove obsolete INDENT-OFF usage
2017-09-29 14:24:31 -07:00
Dirk Thomas
c70f2f1452 Merge pull request #381 from ros2/uncrustify_master
update style to match latest uncrustify
2017-09-29 11:12:43 -07:00
Dirk Thomas
acd231abab remove obsolete INDENT-OFF usage 2017-09-29 10:34:52 -07:00
Dirk Thomas
38c750b876 update style to match latest uncrustify 2017-09-28 15:38:40 -07:00
Shane Loretz
e1f4568bc7 Fix static assertion on xcode 9 (#379)
* Change allocator type to match map key
2017-09-27 19:09:20 -07:00
William Woodall
5813ba54db use throw_from_rcl_error() for error state cleanup (#376) 2017-09-19 14:13:28 -07:00
William Woodall
ca5fb57126 Improvements to rclcpp::Time (#375)
* enable Time to be trivially constructible

This is required to use it in a Qt Signal/Slot.

* operator= should return T &

See: https://stackoverflow.com/questions/9072169/why-should-the-assignment-operator-return-a-reference-to-the-object

* add operator!=
2017-09-19 08:32:10 -07:00
dhood
4a2e9d8af9 Reset rcl errors (#374) 2017-09-14 11:03:24 -07:00
Dirk Thomas
ed26865b71 0.0.3 2017-09-13 15:07:07 -07:00
dhood
a8aa556df0 Check for the client error code, not server (#373) 2017-09-12 08:59:13 -07:00
Mikael Arguedas
b68b761462 restore . as parameter separator (#372) 2017-09-12 08:43:42 -07:00
Karsten Knese
1c42a75f43 parameter client takes node interfaces (#368)
* parameter client takes node interfaces

* correct wrong copy paste

* correctly fetch node name

* use node_topics_interface for creating parameter event

* fix typos
2017-09-05 15:04:36 -07:00
Karsten Knese
2c5ab49e7c change parameter separator to forward slash (#367)
* change parameter separator to forward slash

* add separator to prefix

* const char separator
2017-09-05 11:46:31 -07:00
Dirk Thomas
a5f94ac412 Merge pull request #369 from csukuangfj/fix-test-typo
fix a typo.
2017-09-04 08:22:42 -07:00
KUANG Fangjun
de14d54322 fix a typo. 2017-09-04 16:10:45 +02:00
Karsten Knese
b1ed15ebc7 use forward slashes instead of double underscores (#364)
* use forward slashes instead of double underscores

* define parameter service suffixes in commonly shared header

* style

* forgot list_parameters

* correct license year
2017-09-01 10:00:29 -07:00
Dirk Thomas
f175726b0e Merge pull request #366 from ros2/reset_error_code_init_failed
reset error code before throwing in rclcpp::utilities::init
2017-08-31 16:44:01 -07:00
Dirk Thomas
b28648c61d reset error code before throwing in rclcpp::utilities::init 2017-08-31 16:41:05 -07:00
Karsten Knese
8e2e64e82a freeing Time members in destructor, adding copy constructor / assignment operator (#362)
* copy constructor for fixing windows debug

* remove debug prints

* style

* correctly free resources in destructor

* correct copy and assignment operators

* explicit call to copy constructor
2017-08-24 15:21:01 -07:00
Dirk Thomas
6f3020ce23 Merge pull request #361 from ros2/demo_nodes_cpp_native
expose rcl handles
2017-08-24 09:41:13 -07:00
Dirk Thomas
688c83a44c expose rcl handles 2017-08-23 14:29:37 -07:00
dhood
124500511b Add wait_for_service and service_is_ready for SyncParametersClient (#356) 2017-08-16 22:28:53 -07:00
Mikael Arguedas
98dded0ba5 add issue template 2017-08-14 18:04:51 -07:00
dhood
89c43e78c8 Merge pull request #353 from ros2/restore_old_signal_handler
Restore old signal handler after shutdown
2017-08-11 14:02:54 -07:00
dhood
d7b7d7491f Factor out guard condition triggering 2017-08-11 10:31:40 -07:00
dhood
be985a652b Restore old signal handler on shutdown 2017-08-11 10:31:40 -07:00
dhood
c15db0b675 Factor out signal handler swapping 2017-08-11 10:31:40 -07:00
Chris Lalancette
cd839663b4 Fix memory leaks in rclcpp (#354)
* Make sure to delete service_handle when in the Service() destructor.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Make sure to delete the allocated rcl_node on error paths.

This all happens *before* we setup the shared_ptr destructor,
so we have to hand delete in the error paths.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>

* Move delete rcl_node up.

It turns out that we are always going to throw in that block,
and we never access rcl_node, so just delete it very early
on.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2017-08-11 05:45:25 -07:00
Dirk Thomas
5e7aa50af6 Merge pull request #355 from ros2/fix_race_condition
lock around taking the buffer and deciding to get a copy of the message or popping it
2017-08-10 17:28:49 -07:00
Dirk Thomas
48b19af04a lock around taking the buffer and deciding to get a copy of the message or popping it 2017-08-10 14:51:17 -07:00
Mikael Arguedas
2c3336510d typo 2017-08-08 15:27:32 -07:00
Karsten Knese
def973e3dd time operators (#351)
* time operators

* explicitely cast to uint64_t and prevent overflow

* check for negative seconds .. again

* split into hpp/cpp

* export symbols

* change test macro

* fix unsigned comparison

* address comments

* test for specific exception

* Fix typo
2017-08-08 15:18:17 -07:00
Karsten Knese
d090ddc358 fix return value when calling lifecycle service (#350) 2017-08-04 12:57:12 -07:00
Karsten Knese
388a3ca5be use rcl api for rclcpp time (#348)
* use rcl api for rclcpp time

* address comments
2017-08-03 20:33:32 -07:00
Karsten Knese
9281e32f82 rename RCL_LIFECYCLE_RET_T to lifecycle_msgs::msgs::Transition::TRANSITION_CALLBACK_* (#345) 2017-08-02 14:04:34 -07:00
Esteve Fernandez
a41245e6bf Added support to function_traits for std::bind in GCC >= 7.1 (#346)
* Added support to function_traits for std::bind in GCC >= 7.1

* linter fixup
2017-08-01 16:16:39 -04:00
Karsten Knese
0c26dd99b6 expose error handling for state changes (#344)
* remove fprintf, use logging

* expose lifecycle error code

* address comments
2017-07-27 07:55:15 -07:00
Dirk Thomas
40b09b5b14 added wait method to AsyncParametersClient (#342)
* added wait and ready methods to AsyncParametersClient

* style only

* style only

* remove RCLCPP_PUBLIC from template methods

* style
2017-07-10 10:22:08 -07:00
Dirk Thomas
9dd3d4c3c5 0.0.2 2017-06-30 15:11:46 -07:00
William Woodall
9c008267ef add rcutils tag file reference (#341) 2017-06-27 12:02:41 -07:00
Chris Lalancette
b8d72d682a Remove a constructor that we can't test. (#340)
There are currently no paths that lead to it, and it has
a bug anyway; if a large enough value is passed into sec,
then we will overflow sec on the multiply.  Just remove it
since we can't reach the code anyway.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2017-06-21 09:24:01 -04:00
William Woodall
5a99bbdc6e refactor to support multiple types and no_demangle (#339)
* refactor to support multiple types and no_demangle

* add get_service_names_and_types
2017-06-16 18:03:16 -07:00
Karsten Knese
99441d8494 comply with rcl allocator (#336)
* comply with rcl allocator

* do not throw exception in destructor
2017-06-16 14:44:25 -07:00
Mikael Arguedas
756ef6886d use CMAKE_X_STANDARD and check compiler rather than platform 2017-06-16 13:24:30 -07:00
Karsten Knese
f396ff2bac string array takes allocator (#338) 2017-06-14 11:39:22 -07:00
Karsten Knese
2847e4aefd expose explicit transition calls (#334) 2017-06-05 18:24:12 -07:00
Mikael Arguedas
a4f00dc574 include rcutils/time (#333)
* include rcutils/time

* include rcl/time for time source enum
2017-06-05 14:42:36 -07:00
Dirk Thomas
c0a78bac37 Merge pull request #332 from ros2/move_time
use time from rcutils
2017-06-01 22:11:15 -07:00
Dirk Thomas
bfa09fb78c use steady and system time from rcutils 2017-06-01 21:01:38 -07:00
Karsten Knese
454d38776c Topic names (#331)
* expand topic name before invoking count pub/sub

* convenience function for get_namespace()

* uncrustify

* typo

* add get_namespace() test

* add get_namespace() for lifecycle
2017-06-01 14:01:18 -07:00
William Woodall
b90676871d Use namespaces (#328)
* add expand_topic_or_service_name()

* use namespace in intra process

(actual change to topic names in next commit)

* catch and report name issues

for node names, namespaces, and topic/service names

* address comment
2017-05-30 18:25:11 -07:00
Karsten Knese
708903e5df Warn unused (#327)
* comply with unused warnings

* fix flakiness and add test for transitions

* mark flaky test

* duplicate const char * in State constructor

* linters

* correct year in license

* mark flaky test
2017-05-25 19:52:50 -07:00
William Woodall
5777bbee79 add method to reset a timer in TimerBase (#326) 2017-05-10 00:34:52 -07:00
gerkey
100417a98d fix race conditions in guard condition handling (#325) 2017-04-27 18:47:13 -07:00
dhood
675ad04c76 Update spin error message to match function name (#323) 2017-04-25 09:56:01 -07:00
William Woodall
3e6a6d2781 rename {c_}utilities to rcutils (#322) 2017-04-20 11:15:10 -07:00
William Woodall
d2112b294b refactor to pass allocator to some functions in rcl (#321) 2017-04-19 12:37:55 -07:00
Karsten Knese
81b8255e61 use string_array_t from c_utilities package (#320)
* use c_utilities package

* compare return value to utilities_ret_ok

* fix error handling

* better error handling
2017-04-14 16:18:43 -07:00
William Woodall
e6e1848b97 expose node namespace in API and pass to rcl (#316)
* expose node namespace in API and pass to rcl

* name_space -> namespace_
2017-04-08 02:04:41 -07:00
William Woodall
dbe674deb7 compare unsigned to unsigned (#313) 2017-03-22 00:42:37 -07:00
Karsten Knese
c07aee5cf0 Rclcpp time (#311)
* initial commit for rclcpp::time::now()

* switch between times

* introduce time class

* add rclcpp/time.hpp to rclcpp/rclcpp.hpp

* throw exceptions on time error

* fix test_time to catch exceptions

* explicit one-parameter constructor

* fix msvc compiler warnings

* address review comments

* cleanup includes

* re-add todo for fixing test once ros-time is there
2017-03-21 17:41:49 -07:00
William Woodall
2009ca676b add a new Node::get_parameter() with a default value (#309)
* add a new Node::get_parameter() with a default value

* update function parameter name (signature)

* update function parameter name (definition)

* rename new function to get_parameter_or

* rename arg "parameter" to "value" and fix get_parameter

* add set_parameter_if_not_set

* add some comments to clarify logic in set_parameters_atomically

* uncrustify

* address comments

* add some docs for get_parameter*
2017-03-20 17:04:12 -07:00
Mikael Arguedas
71f5b7fe5b Use -Wpedantic (#306)
* add /W4 flag for windows

* use uint8 like defined in messages: fix warning C4244

* fix sign size_t comparison

* add only pedantic, not W4, deal with windows another day

* another sign compare warning
2017-02-27 21:07:57 -08:00
William Woodall
ce146cfdba add a publish method with the const MessageT * signature (#307) 2017-02-27 18:48:01 -08:00
Karsten Knese
dc6b15983a Rosnode list (#304)
* expose list of nodes

* uncrustify

* review comments

* warn for memory leak

* extend year of copyright
2017-01-30 10:30:57 -08:00
Dirk Thomas
4d8b60feb5 Merge pull request #302 from ros2/use_rmw_impl
use rmw implementation
2017-01-09 08:54:27 -08:00
Dirk Thomas
78dfef75b4 remove obsolete CMake functions 2017-01-06 15:46:08 -08:00
dhood
8ca02c9d37 Fix cmake for appending c/cxx flags (#300) 2017-01-06 07:48:47 +10:00
Dirk Thomas
fee3118bdd use rmw implementation 2017-01-05 12:16:12 -08:00
Mikael Arguedas
9603db7b7d dependency order (#301) 2017-01-05 17:27:53 +01:00
Dirk Thomas
e3d4995383 Merge pull request #299 from ros2/single_ts_shortcut
fix dependencies
2016-12-28 13:13:18 -08:00
Dirk Thomas
197c17ae99 fix dependencies 2016-12-28 12:12:05 -08:00
Dirk Thomas
d9673a556d Merge pull request #298 from ros2/typesupport_c_reloaded
use rosidl_typesupport_c
2016-12-28 09:02:43 -08:00
Rohan Agrawal
c0af872c18 Warn on second call of register_param_change_callback (#297) 2016-12-22 13:56:44 -08:00
Dirk Thomas
9e309db793 use rosidl_typesupport_c 2016-12-22 09:47:57 -08:00
William Woodall
321e0b61b0 Doxygen setup (#293)
* basic doxygen configuration

* fix up documentation

* change default value of PROJECT_NUMBER

* more generalization

* fixup

* fixup

* avoid displaying RCLCPP_PUBLIC on all functions

* main page
2016-12-20 18:30:18 -08:00
Dirk Thomas
0515e7aaf2 replace deprecated <CONFIGURATION> with <CONFIG> 2016-12-20 11:38:44 -08:00
Guillaume Papin
d00a441195 move user-defined literals in their own namespace (#284)
* isolate chrono literals in literals.hpp

* rclcpp.hpp: remove 'using namespace rclcpp::literals'

The examples have been migrated to the new namespace.

* literals: constexpr, make return types consistent with function body

_ms returned nanoseconds instead of milliseconds.

A few return types where using integral return type
for floating point literals.

* remove literals in favor of std::chrono_literals
2016-12-17 02:16:43 -08:00
Karsten Knese
2c6d95946e add rclcpp lifecycle
* initial state machine implementation

(fix) correctly initialize default state machine

uncrustify

(dev) first high level api interface

src/default_state_machine.c

(fix) correctly initialize arrays in statemachine

(dev) deactivate/activate publisher demo

(dev) initial state machine implementation in rcl

* (dev) demo application for a managed lifecycle node

* add visibility control

* correct install of c-library

* fix compilation on windows

* refactoring of external/internal api

* (dev) generate static functions for c-callback

* (fix) correct typo

* (dev) cleanup for c-statemachine

(dev) cleanup for c-statemachine

* (dev) cpp callback map

* (dev) mv source file into project folders

* (dev) more helper functions for valid transition

* (dev) pimpl implementation for cpp lifecyclemanager

* (dev) register non-default callback functions

* (dev) cleanup lifecycle node to serve as base class

* (dev) new my_node child of lifecyclenode for demo purpose

update

stuff

(cleanup) remove unused comments

(fix) correct dllexport in windows

(fix) correctly install libraries

(fix) uncrustify

(dev) composition over inheritance

(dev) publish notification in state_machine transition

 (dev) lifecycle talker + listener demo for notification

(dev) custom transition message generation

(dev) publish transition message on state change

(dev) correctly malloc/free c data structures

(fix) use single thread executor

(dev) use services for get state

(fix) set freed pointer to NULL

(dev) add change state service

(dev) introduce services: get_state and change_state in LM

(dev) asynchronous caller script for service client

(fix) correct dllexport for pimpl

(dev) correct constness

(dev) concatenate function for topic

(fix) uncrustify

prepare new service api

(tmp) refactor stash

(fix) correctly concatenate topics

(fix) correctly initialize Service wo/ copy

(dev) call both service types

extract demo files

(fix) remove debug prints

(dev) change to lifecycle_msgs

(refactor) extract rcl_lifecycle package

(refactor) extract lifecycle demos

(fix) address review comments

(fix) address review comments

(fix) pass shared_ptr by value

(fix) make find_package(rmw) required

(fix) return to shared node handle pointer

(refactor) attach sm to lifecycle node and disable lc_manager

(dev) construct service from existing rcl_service_t

(refactor) extract method for adding a service to a node

(fix) stop mock msgs from being installed

service takes rcl_node_t*

correct typo

add_service has to be public

uncrustify

initial state machine implementation

(fix) correctly initialize default state machine

uncrustify

(dev) first high level api interface

src/default_state_machine.c

(fix) correctly initialize arrays in statemachine

(dev) deactivate/activate publisher demo

(dev) initial state machine implementation in rcl

(dev) demo application for a managed lifecycle node

add visibility control

correct install of c-library

fix compilation on windows

refactoring of external/internal api

(dev) generate static functions for c-callback

(fix) correct typo

(dev) cleanup for c-statemachine

(dev) cleanup for c-statemachine

(dev) cpp callback map

(dev) mv source file into project folders

(dev) more helper functions for valid transition

(dev) pimpl implementation for cpp lifecyclemanager

(dev) register non-default callback functions

(dev) cleanup lifecycle node to serve as base class

(dev) new my_node child of lifecyclenode for demo purpose

update

stuff

(cleanup) remove unused comments

(fix) correct dllexport in windows

(fix) correctly install libraries

(fix) uncrustify

(dev) composition over inheritance

(dev) publish notification in state_machine transition

 (dev) lifecycle talker + listener demo for notification

(dev) custom transition message generation

(dev) publish transition message on state change

(dev) correctly malloc/free c data structures

(fix) use single thread executor

(dev) use services for get state

(fix) set freed pointer to NULL

(dev) add change state service

(dev) introduce services: get_state and change_state in LM

(dev) asynchronous caller script for service client

(fix) correct dllexport for pimpl

(dev) correct constness

(dev) concatenate function for topic

(fix) uncrustify

prepare new service api

(tmp) refactor stash

* (dev) construct service from existing rcl_service_t

* service takes rcl_node_t*

* correct typo

* add_service has to be public

* uncrustify

* (fix) correctly concatenate topics

* (fix) correctly initialize Service wo/ copy

* (dev) call both service types

* extract demo files

* (fix) remove debug prints

* (dev) change to lifecycle_msgs

* (refactor) extract rcl_lifecycle package

* (refactor) extract lifecycle demos

* (fix) address review comments

(fix) address review comments

* (fix) make find_package(rmw) required

* (refactor) attach sm to lifecycle node and disable lc_manager

* (fix) adjust code to rcl_test refactor

* (dev) remove unused deps

* (rebase) merge commit

* (bugfix) correct rcl_ret_t error handling

* (fix) depedencies

* (refactor) change to lifecycle_msgs

* (fix) correct find_rcl

* (refactor) comply for new state machine

* visibility control and test api

* (rebase) change to new typesupport

* uncrustify'

* fix visibility control

* (fix) correct whitespace

* (fix) unused variable

* comparison signed and unsigned

* get_state returns complete state

* get_available_states service

* new service msgs

* get available states and transitions api

* (broken) state after rebase, does not compile demos

* fix the way lifecycle node impl is included

* fixed rebase compilation errors

* remove copy&paste comment

* remove empty line

* (test) register custom callbacks

* (dev) return codes

* style

* test for exception handling

* refacotr new state machine

* c++14

* change exception message for windows ci bug

change exception message for windows ci bug
2016-12-14 09:29:27 -08:00
Morgan Quigley
d241a730fe c++14 (#287) 2016-12-13 14:41:22 -08:00
William Woodall
cc98d00add remove unused include (#291) 2016-12-12 11:56:59 -08:00
William Woodall
e2f53b09b4 fix the return type of create_subscription (#290) 2016-12-09 22:25:09 -08:00
William Woodall
734ac278db break Node into several separate interfaces (#277)
* add the NodeBaseInterface and impl NodeBase

* refactor rclcpp to use NodeBaseInterface

* triggering a guard condition is not const

* remove unnecessary pure virtual destructor

* remove unused private member, style

* create NodeTopics interface, refactor pub/sub

* add convenience functions to fix API breaks

* fix compilation errors from NodeTopics refactor

* move "Event" based exceptions to exceptions.hpp

* add the NodeGraphInterface and related API's

* update node and graph_listener to use NodeGraph API

* initialize node_topics_ and node_graph_ in Node

* remove methods from Node and reorganize the order

the removed methods are really low level and still
available via their respective Node*Interface class

* add the NodeServices API and implementation

* add the NodeParameters API and refactor Node

* mixups

* fixup NodeParameters constructor

* added NodeTimers API and refactor Node

* make new create_publisher and create_subscription free template functions

* fixup

* fixup

* fixup

* fixup share pointer to node in any_executable

* free env value before throwing on Windows

* uncrustify and cpplint

* address constness issues

* do not store the topic name as a std::string in subscription

* fixes to support const char * topic name

* fix incomplete type specification, which fails on Windows

* refactor after rebase from type support changes

* fixup Windows build

* fix template issues on Windows

* uncrustify

* remove the unnecessary callback group argument from the add_publisher func

* remove unnecessary using = directive

* do not store node name in C++

* fix client and service creation in Node constructor

* fix include orders
2016-12-09 17:09:29 -08:00
Dirk Thomas
2309e5e250 Merge pull request #285 from ros2/typesupport_reloaded
use rosidl_typesupport_cpp
2016-12-08 14:00:42 -08:00
Dirk Thomas
3fe1924c63 pass custom LIBRARY_NAME 2016-12-06 14:54:31 -08:00
Dirk Thomas
3405f489d3 use rosidl_typesupport_cpp 2016-12-06 11:07:11 -08:00
Karsten Knese
1b5168195b construct service from existing rcl_service_t (#279)
* (dev) construct service from existing rcl_service_t

* (refactor) extract method for adding a service to a node

* (fix) stop mock msgs from being installed

* service takes rcl_node_t*

* correct typo

* add_service has to be public

* uncrustify

* correctly initialize service_handle

* (fix) address review comments

* (fix) pass shared pointer by value

* (fix) return to shared node handle pointer

* (fix) make find_package(rmw) required

* style

* (revert) leave c++11 flags within CXX flags

* (fix) unused variable warning

* (fix) remove unnecessary if in cmake
2016-12-02 01:05:59 -08:00
geoffviola
a987f8d015 removed extra semi-colon (#253)
* removed extra semi-colon

* added -Wpedantic flag for GCC

* added same warnings for clang

* simplified CMake command
2016-11-28 14:11:22 -08:00
Geoffrey Biggs
aa2d0a3954 Fix has_invalid_weak_nodes (#266)
* Fix #264

* Corrected test comment
2016-11-17 09:59:50 -08:00
Dirk Thomas
5894a9cd4e Merge pull request #270 from ros2/composition
fix allocator type
2016-11-10 16:55:02 -08:00
Dirk Thomas
80fc2a59cd Merge pull request #271 from ros2/fix_error_reporting
fix error reporting for services
2016-11-10 13:25:29 -08:00
Dirk Thomas
d12154b1f9 fix error reporting for services 2016-11-10 11:13:19 -08:00
Dirk Thomas
a06a397cc6 fix allocator type 2016-11-10 10:09:24 -08:00
Dirk Thomas
4c876d5966 fix wrong variable name in docblock 2016-11-08 15:21:48 -08:00
Mikael Arguedas
da14d88cd6 line length (#269) 2016-11-07 18:47:05 -08:00
Dirk Thomas
01317def07 Merge pull request #268 from ros2/composition
add rclcpp_register_node_plugins macro
2016-11-07 15:41:14 -08:00
Dirk Thomas
74505f25fa add rclcpp_register_node_plugins macro 2016-11-07 15:21:53 -08:00
Dirk Thomas
ec71e6562e move CMake function into separate file 2016-11-07 10:55:17 -08:00
Karsten Knese
7f714a8601 open Node/Publisher API for allowing inheritance (#258)
* (dev) template create_publisher with publisher type

* (dev) template publisher type for dynamic publisher type instantiation

* (dev) make Publisher::publish function virtual

* (fix) uncrustify

* different indentation of long template declaration
2016-11-01 15:07:58 -07:00
William Woodall
7494350ad2 always check if the service is available, even if the graph event wasn't triggered (#262)
* always check if the service is available, even if the graph event wasn't triggered

* more descriptive comment

* Even more descriptive in case the link ever breaks
2016-10-28 18:31:15 -07:00
Rafał Kozik
d158dd46db CallbackGroup keeps now WeakPtrs to Services. (#261)
It was not possible to shutdown a service when there
was a shared pointer preventing destructor from being called.
2016-10-28 15:59:46 -07:00
Mikael Arguedas
a71ce25a5a Zero init topic names and types (#260)
* use zero init topic_names_and_type struct

* use the right arguments

* line length
2016-10-27 19:02:35 -07:00
332 changed files with 49093 additions and 5775 deletions

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

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

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.DS_Store

View File

@@ -11,3 +11,8 @@ be under the Apache 2 License, as dictated by that
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
~~~
Contributors must sign-off each commit by adding a `Signed-off-by: ...`
line to commit messages to certify that they have the right to submit
the code they are contributing to the project according to the
[Developer Certificate of Origin (DCO)](https://developercertificate.org/).

17
README.md Normal file
View File

@@ -0,0 +1,17 @@
# rclcpp
This repository contains the source code for the ROS Client Library for C++ package, included with a standard install of any ROS 2 distro.
rclcpp provides the standard C++ API for interacting with ROS 2.
## Usage
`#include "rclcpp/rclcpp.hpp"` allows use of the most common elements of the ROS 2 system.
Visit the [rclcpp API documentation](http://docs.ros2.org/eloquent/api/rclcpp/) for a complete list of its main components.
### Examples
The ROS 2 tutorials [Writing a simple publisher and subscriber](https://index.ros.org/doc/ros2/Tutorials/Writing-A-Simple-Cpp-Publisher-And-Subscriber/)
and [Writing a simple service and client](https://index.ros.org/doc/ros2/Tutorials/Writing-A-Simple-Cpp-Service-And-Client/)
contain some examples of rclcpp APIs in use.

1
rclcpp/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
doc_output

258
rclcpp/CHANGELOG.rst Normal file
View File

@@ -0,0 +1,258 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package rclcpp
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.8.3 (2019-11-19)
------------------
0.8.2 (2019-11-18)
------------------
* Updated tracing logic to match changes in rclcpp's intra-process system (`#918 <https://github.com/ros2/rclcpp/issues/918>`_)
* Fixed a bug that prevented the ``shutdown_on_sigint`` option to not work correctly (`#850 <https://github.com/ros2/rclcpp/issues/850>`_)
* Added support for STREAM logging macros (`#926 <https://github.com/ros2/rclcpp/issues/926>`_)
* Relaxed multithreaded test constraint (`#907 <https://github.com/ros2/rclcpp/issues/907>`_)
* Contributors: Anas Abou Allaban, Christophe Bedard, Dirk Thomas, alexfneves
0.8.1 (2019-10-23)
------------------
* De-flake tests for rmw_connext (`#899 <https://github.com/ros2/rclcpp/issues/899>`_)
* rename return functions for loaned messages (`#896 <https://github.com/ros2/rclcpp/issues/896>`_)
* Enable throttling logs (`#879 <https://github.com/ros2/rclcpp/issues/879>`_)
* New Intra-Process Communication (`#778 <https://github.com/ros2/rclcpp/issues/778>`_)
* Instrumentation update (`#789 <https://github.com/ros2/rclcpp/issues/789>`_)
* Zero copy api (`#864 <https://github.com/ros2/rclcpp/issues/864>`_)
* Drop rclcpp remove_ros_arguments_null test case. (`#894 <https://github.com/ros2/rclcpp/issues/894>`_)
* add mechanism to pass rmw impl specific payloads during pub/sub creation (`#882 <https://github.com/ros2/rclcpp/issues/882>`_)
* make get_actual_qos return a rclcpp::QoS (`#883 <https://github.com/ros2/rclcpp/issues/883>`_)
* Fix Compiler Warning (`#881 <https://github.com/ros2/rclcpp/issues/881>`_)
* Add callback handler for use_sim_time parameter `#802 <https://github.com/ros2/rclcpp/issues/802>`_ (`#875 <https://github.com/ros2/rclcpp/issues/875>`_)
* Contributors: Alberto Soragna, Brian Marchi, Hunter L. Allen, Ingo Lütkebohle, Karsten Knese, Michael Carroll, Michel Hidalgo, William Woodall
0.8.0 (2019-09-26)
------------------
* clean up publisher and subscription creation logic (`#867 <https://github.com/ros2/rclcpp/issues/867>`_)
* Take parameter overrides provided through the CLI. (`#865 <https://github.com/ros2/rclcpp/issues/865>`_)
* add more context to exception message (`#858 <https://github.com/ros2/rclcpp/issues/858>`_)
* remove features and related code which were deprecated in dashing (`#852 <https://github.com/ros2/rclcpp/issues/852>`_)
* check valid timer handler 1st to reduce the time window for scan. (`#841 <https://github.com/ros2/rclcpp/issues/841>`_)
* Add throwing parameter name if parameter is not set (`#833 <https://github.com/ros2/rclcpp/issues/833>`_)
* Fix typo in deprecated warning. (`#848 <https://github.com/ros2/rclcpp/issues/848>`_)
* Fail on invalid and unknown ROS specific arguments (`#842 <https://github.com/ros2/rclcpp/issues/842>`_)
* Force explicit --ros-args in NodeOptions::arguments(). (`#845 <https://github.com/ros2/rclcpp/issues/845>`_)
* Use of -r/--remap flags where appropriate. (`#834 <https://github.com/ros2/rclcpp/issues/834>`_)
* Fix hang with timers in MultiThreadedExecutor (`#835 <https://github.com/ros2/rclcpp/issues/835>`_) (`#836 <https://github.com/ros2/rclcpp/issues/836>`_)
* add mutex in add/remove_node and wait_for_work to protect concurrent use/change of memory_strategy\_ (`#837 <https://github.com/ros2/rclcpp/issues/837>`_)
* Crash in callback group pointer vector iterator (`#814 <https://github.com/ros2/rclcpp/issues/814>`_)
* Wrap documentation examples in code blocks (`#830 <https://github.com/ros2/rclcpp/issues/830>`_)
* add callback group as member variable and constructor arg (`#811 <https://github.com/ros2/rclcpp/issues/811>`_)
* Fix get_node_interfaces functions taking a pointer (`#821 <https://github.com/ros2/rclcpp/issues/821>`_)
* Delete unnecessary call for get_node_by_group (`#823 <https://github.com/ros2/rclcpp/issues/823>`_)
* Allow passing logger by const ref (`#820 <https://github.com/ros2/rclcpp/issues/820>`_)
* Explain return value of spin_until_future_complete (`#792 <https://github.com/ros2/rclcpp/issues/792>`_)
* Adapt to '--ros-args ... [--]'-based ROS args extraction (`#816 <https://github.com/ros2/rclcpp/issues/816>`_)
* Add line break after first open paren in multiline function call (`#785 <https://github.com/ros2/rclcpp/issues/785>`_)
* remove mock msgs from rclcpp (`#800 <https://github.com/ros2/rclcpp/issues/800>`_)
* Make TimeSource ignore use_sim_time events coming from other nodes. (`#799 <https://github.com/ros2/rclcpp/issues/799>`_)
* Allow registering multiple on_parameters_set_callback (`#772 <https://github.com/ros2/rclcpp/issues/772>`_)
* Add free function for creating service clients (`#788 <https://github.com/ros2/rclcpp/issues/788>`_)
* Include missing rcl headers in use. (`#782 <https://github.com/ros2/rclcpp/issues/782>`_)
* Switch the NodeParameters lock to recursive. (`#781 <https://github.com/ros2/rclcpp/issues/781>`_)
* changed on_parameter_event qos profile to rmw_qos_profile_parameter_events (`#774 <https://github.com/ros2/rclcpp/issues/774>`_)
* Adding a factory method to create a Duration from seconds (`#567 <https://github.com/ros2/rclcpp/issues/567>`_)
* Fix a comparison with a sign mismatch (`#771 <https://github.com/ros2/rclcpp/issues/771>`_)
* delete superfluous spaces (`#770 <https://github.com/ros2/rclcpp/issues/770>`_)
* Use params from node '/\*\*' from parameter YAML file (`#762 <https://github.com/ros2/rclcpp/issues/762>`_)
* Add ignore override argument to declare parameter (`#767 <https://github.com/ros2/rclcpp/issues/767>`_)
* use default parameter descriptor in parameters interface (`#765 <https://github.com/ros2/rclcpp/issues/765>`_)
* Added support for const member functions (`#763 <https://github.com/ros2/rclcpp/issues/763>`_)
* add get_actual_qos() feature to subscriptions (`#754 <https://github.com/ros2/rclcpp/issues/754>`_)
* Ignore parameters overrides in set parameter methods when allowing undeclared parameters (`#756 <https://github.com/ros2/rclcpp/issues/756>`_)
* Add rclcpp::create_timer() (`#757 <https://github.com/ros2/rclcpp/issues/757>`_)
* checking origin of intra-process msg before taking them (`#753 <https://github.com/ros2/rclcpp/issues/753>`_)
* Contributors: Alberto Soragna, Carl Delsey, Chris Lalancette, Dan Rose, Dirk Thomas, Esteve Fernandez, Guillaume Autran, Jacob Perron, Karsten Knese, Luca Della Vedova, M. M, Michel Hidalgo, Scott K Logan, Shane Loretz, Todd Malsbary, William Woodall, bpwilcox, fujitatomoya, ivanpauno
0.7.5 (2019-05-30)
------------------
* Avoid 'Intra process message no longer being stored when trying to handle it' warning (`#749 <https://github.com/ros2/rclcpp/issues/749>`_)
* Contributors: ivanpauno
0.7.4 (2019-05-29)
------------------
* Rename parameter options (`#745 <https://github.com/ros2/rclcpp/issues/745>`_)
* Bionic use of strerror_r (`#742 <https://github.com/ros2/rclcpp/issues/742>`_)
* Enforce parameter ranges (`#735 <https://github.com/ros2/rclcpp/issues/735>`_)
* removed not used parameter client (`#740 <https://github.com/ros2/rclcpp/issues/740>`_)
* ensure removal of guard conditions of expired nodes from memory strategy (`#741 <https://github.com/ros2/rclcpp/issues/741>`_)
* Fix typo in log warning message (`#737 <https://github.com/ros2/rclcpp/issues/737>`_)
* Throw nice errors when creating a publisher with intraprocess communication and incompatible qos policy (`#729 <https://github.com/ros2/rclcpp/issues/729>`_)
* Contributors: Alberto Soragna, Dirk Thomas, Jacob Perron, William Woodall, ivanpauno, roderick-koehle
0.7.3 (2019-05-20)
------------------
* Fixed misspelling, volitile -> volatile (`#724 <https://github.com/ros2/rclcpp/issues/724>`_), and then fixed that since it is a C++ keyword to be ``durability_volatile`` (`#725 <https://github.com/ros2/rclcpp/issues/725>`_)
* Fixed a clang warning (`#723 <https://github.com/ros2/rclcpp/issues/723>`_)
* Added ``on_parameter_event`` static method to the ``AsyncParametersClient`` (`#688 <https://github.com/ros2/rclcpp/issues/688>`_)
* Added a guard against ``ParameterNotDeclaredException`` throwing from within the parameter service callbacks. (`#718 <https://github.com/ros2/rclcpp/issues/718>`_)
* Added missing template functionality to lifecycle_node. (`#707 <https://github.com/ros2/rclcpp/issues/707>`_)
* Fixed heap-use-after-free and memory leaks reported from ``test_node.cpp`` (`#719 <https://github.com/ros2/rclcpp/issues/719>`_)
* Contributors: Alberto Soragna, Dirk Thomas, Emerson Knapp, Jacob Perron, Michael Jeronimo, Prajakta Gokhale
0.7.2 (2019-05-08)
------------------
* Added new way to specify QoS settings for publishers and subscriptions. (`#713 <https://github.com/ros2/rclcpp/issues/713>`_)
* The new way requires that you specify a history depth when creating a publisher or subscription.
* In the past it was possible to create one without specifying any history depth, but these signatures have been deprecated.
* Deprecated ``shared_ptr`` and raw pointer versions of ``Publisher<T>::publish()``. (`#709 <https://github.com/ros2/rclcpp/issues/709>`_)
* Implemented API to set callbacks for liveliness and deadline QoS events for publishers and subscriptions. (`#695 <https://github.com/ros2/rclcpp/issues/695>`_)
* Fixed a segmentation fault when publishing a parameter event when they ought to be disabled. (`#714 <https://github.com/ros2/rclcpp/issues/714>`_)
* Changes required for upcoming pre-allocation API. (`#711 <https://github.com/ros2/rclcpp/issues/711>`_)
* Changed ``Node::get_node_names()`` to return the full node names rather than just the base name. (`#698 <https://github.com/ros2/rclcpp/issues/698>`_)
* Remove logic made redundant by the `ros2/rcl#255 <https://github.com/ros2/rcl/issues/255>`_ pull request. (`#712 <https://github.com/ros2/rclcpp/issues/712>`_)
* Various improvements for ``rclcpp::Clock``. (`#696 <https://github.com/ros2/rclcpp/issues/696>`_)
* Fixed uninitialized bool in ``clock.cpp``.
* Fixed up includes of ``clock.hpp/cpp``.
* Added documentation for exceptions to ``clock.hpp``.
* Adjusted function signature of getters of ``clock.hpp/cpp``.
* Removed raw pointers to ``Clock::create_jump_callback``.
* Removed unnecessary ``rclcpp`` namespace reference from ``clock.cpp``.
* Changed exception to ``bad_alloc`` on ``JumpHandler`` allocation failure.
* Fixed missing ``nullptr`` check in ``Clock::on_time_jump``.
* Added ``JumpHandler::callback`` types.
* Added warning for lifetime of Clock and JumpHandler
* Fixed bug left over from the `pull request #495 <https://github.com/ros2/rclcpp/pull/495>`_. (`#708 <https://github.com/ros2/rclcpp/issues/708>`_)
* Changed the ``IntraProcessManager`` to be capable of storing ``shared_ptr<const T>`` in addition to ``unique_ptr<T>``. (`#690 <https://github.com/ros2/rclcpp/issues/690>`_)
* Contributors: Alberto Soragna, Dima Dorezyuk, M. M, Michael Carroll, Michael Jeronimo, Tully Foote, William Woodall, ivanpauno, jhdcs
0.7.1 (2019-04-26)
------------------
* Added read only parameters. (`#495 <https://github.com/ros2/rclcpp/issues/495>`_)
* Fixed a concurrency problem in the multithreaded executor. (`#703 <https://github.com/ros2/rclcpp/issues/703>`_)
* Fixup utilities. (`#692 <https://github.com/ros2/rclcpp/issues/692>`_)
* Added method to read timer cancellation. (`#697 <https://github.com/ros2/rclcpp/issues/697>`_)
* Added Exception Generator function for implementing "from_rcl_error". (`#678 <https://github.com/ros2/rclcpp/issues/678>`_)
* Updated initialization of rmw_qos_profile_t struct instances. (`#691 <https://github.com/ros2/rclcpp/issues/691>`_)
* Removed the const value from the logger before comparison. (`#680 <https://github.com/ros2/rclcpp/issues/680>`_)
* Contributors: Devin Bonnie, Dima Dorezyuk, Guillaume Autran, M. M, Shane Loretz, Víctor Mayoral Vilches, William Woodall, jhdcs
0.7.0 (2019-04-14)
------------------
* Added Options-struct interfaces for creating publishers/subscribers (pre-QoS, standalone). (`#673 <https://github.com/ros2/rclcpp/issues/673>`_)
* Replaced strncpy with memcpy. (`#684 <https://github.com/ros2/rclcpp/issues/684>`_)
* Replaced const char * with a std::array<char, TOPIC_NAME_LENGTH> as the key of IPM IDTopicMap. (`#671 <https://github.com/ros2/rclcpp/issues/671>`_)
* Refactored SignalHandler logger to avoid race during destruction. (`#682 <https://github.com/ros2/rclcpp/issues/682>`_)
* Introduce rclcpp_components to implement composition. (`#665 <https://github.com/ros2/rclcpp/issues/665>`_)
* Added QoS policy check when configuring intraprocess, skip interprocess publish when possible. (`#674 <https://github.com/ros2/rclcpp/issues/674>`_)
* Updated to use do { .. } while(0) around content of logging macros. (`#681 <https://github.com/ros2/rclcpp/issues/681>`_)
* Added function to get publisher's actual QoS settings. (`#667 <https://github.com/ros2/rclcpp/issues/667>`_)
* Updated to avoid race that triggers timer too often. (`#621 <https://github.com/ros2/rclcpp/issues/621>`_)
* Exposed get_fully_qualified_name in NodeBase API. (`#662 <https://github.com/ros2/rclcpp/issues/662>`_)
* Updated to use ament_target_dependencies where possible. (`#659 <https://github.com/ros2/rclcpp/issues/659>`_)
* Fixed wait for service memory leak bug. (`#656 <https://github.com/ros2/rclcpp/issues/656>`_)
* Fixed test_time_source test. (`#639 <https://github.com/ros2/rclcpp/issues/639>`_)
* Fixed hard-coded duration type representation so int64_t isn't assumed. (`#648 <https://github.com/ros2/rclcpp/issues/648>`_)
* Fixed cppcheck warning. (`#646 <https://github.com/ros2/rclcpp/issues/646>`_)
* Added count matching api and intra-process subscriber count. (`#628 <https://github.com/ros2/rclcpp/issues/628>`_)
* Added Sub Node alternative. (`#581 <https://github.com/ros2/rclcpp/issues/581>`_)
* Replaced 'auto' with 'const auto &'. (`#630 <https://github.com/ros2/rclcpp/issues/630>`_)
* Set Parameter Event Publisher settings. `#591 <https://github.com/ros2/rclcpp/issues/591>`_ (`#614 <https://github.com/ros2/rclcpp/issues/614>`_)
* Replaced node constructor arguments with NodeOptions. (`#622 <https://github.com/ros2/rclcpp/issues/622>`_)
* Updated to pass context to wait set (`#617 <https://github.com/ros2/rclcpp/issues/617>`_)
* Added API to get parameters in a map. (`#575 <https://github.com/ros2/rclcpp/issues/575>`_)
* Updated Bind usage since it is is no longer in std::__1. (`#618 <https://github.com/ros2/rclcpp/issues/618>`_)
* Fixed errors from uncrustify v0.68. (`#613 <https://github.com/ros2/rclcpp/issues/613>`_)
* Added new constructors for SyncParameterClient. (`#612 <https://github.com/ros2/rclcpp/issues/612>`_)
* Contributors: Alberto Soragna, Chris Lalancette, Dirk Thomas, Emerson Knapp, Francisco Martín Rico, Jacob Perron, Marko Durkovic, Michael Carroll, Peter Baughman, Shane Loretz, Wei Liu, William Woodall, Yutaka Kondo, ivanpauno, kuzai, rarvolt
0.6.2 (2018-12-13)
------------------
* Updated to use signal safe synchronization with platform specific semaphores (`#607 <https://github.com/ros2/rclcpp/issues/607>`_)
* Resolved startup race condition for sim time (`#608 <https://github.com/ros2/rclcpp/issues/608>`_)
Resolves `#595 <https://github.com/ros2/rclcpp/issues/595>`_
* Contributors: Tully Foote, William Woodall
0.6.1 (2018-12-07)
------------------
* Added wait_for_action_server() for action clients (`#598 <https://github.com/ros2/rclcpp/issues/598>`_)
* Added node path and time stamp to parameter event message (`#584 <https://github.com/ros2/rclcpp/issues/584>`_)
* Updated to allow removing a waitable (`#597 <https://github.com/ros2/rclcpp/issues/597>`_)
* Refactored init to allow for non-global init (`#587 <https://github.com/ros2/rclcpp/issues/587>`_)
* Fixed wrong use of constructor and hanging test (`#596 <https://github.com/ros2/rclcpp/issues/596>`_)
* Added class Waitable (`#589 <https://github.com/ros2/rclcpp/issues/589>`_)
* Updated rcl_wait_set_add\_* calls (`#586 <https://github.com/ros2/rclcpp/issues/586>`_)
* Contributors: Dirk Thomas, Jacob Perron, Shane Loretz, William Woodall, bpwilcox
0.6.0 (2018-11-19)
------------------
* Updated to use new error handling API from rcutils (`#577 <https://github.com/ros2/rclcpp/issues/577>`_)
* Added a warning when publishing if publisher is not active (`#574 <https://github.com/ros2/rclcpp/issues/574>`_)
* Added logging macro signature that accepts std::string (`#573 <https://github.com/ros2/rclcpp/issues/573>`_)
* Added virtual destructors to classes with virtual functions. (`#566 <https://github.com/ros2/rclcpp/issues/566>`_)
* Added semicolons to all RCLCPP and RCUTILS macros. (`#565 <https://github.com/ros2/rclcpp/issues/565>`_)
* Removed std::binary_function usage (`#561 <https://github.com/ros2/rclcpp/issues/561>`_)
* Updated to avoid auto-activating ROS time if clock topic is being published (`#559 <https://github.com/ros2/rclcpp/issues/559>`_)
* Fixed cpplint on xenial (`#556 <https://github.com/ros2/rclcpp/issues/556>`_)
* Added get_parameter_or_set_default. (`#551 <https://github.com/ros2/rclcpp/issues/551>`_)
* Added max_duration to spin_some() (`#558 <https://github.com/ros2/rclcpp/issues/558>`_)
* Updated to output rcl error message when yaml parsing fails (`#557 <https://github.com/ros2/rclcpp/issues/557>`_)
* Updated to make sure timer is fini'd before clock (`#553 <https://github.com/ros2/rclcpp/issues/553>`_)
* Get node names and namespaces (`#545 <https://github.com/ros2/rclcpp/issues/545>`_)
* Fixed and improved documentation (`#546 <https://github.com/ros2/rclcpp/issues/546>`_)
* Updated to use rcl_clock_t jump callbacks (`#543 <https://github.com/ros2/rclcpp/issues/543>`_)
* Updated to use rcl consolidated wait set functions (`#540 <https://github.com/ros2/rclcpp/issues/540>`_)
* Addeed TIME_MAX and DURATION_MAX functions (`#538 <https://github.com/ros2/rclcpp/issues/538>`_)
* Updated to publish shared_ptr of rcl_serialized_message (`#541 <https://github.com/ros2/rclcpp/issues/541>`_)
* Added Time::is_zero and Duration::seconds (`#536 <https://github.com/ros2/rclcpp/issues/536>`_)
* Changed to log an error message instead of throwing exception in destructor (`#535 <https://github.com/ros2/rclcpp/issues/535>`_)
* Updated to relax tolerance of now test because timing affected by OS scheduling (`#533 <https://github.com/ros2/rclcpp/issues/533>`_)
* Removed incorrect exception on sec < 0 (`#527 <https://github.com/ros2/rclcpp/issues/527>`_)
* Added rclcpp::Time::seconds() (`#526 <https://github.com/ros2/rclcpp/issues/526>`_)
* Updated Timer API to construct TimerBase/GenericTimer with Clock (`#523 <https://github.com/ros2/rclcpp/issues/523>`_)
* Added rclcpp::is_initialized() (`#522 <https://github.com/ros2/rclcpp/issues/522>`_)
* Added support for jump handlers with only pre- or post-jump callback (`#517 <https://github.com/ros2/rclcpp/issues/517>`_)
* Removed use of uninitialized CMake var (`#512 <https://github.com/ros2/rclcpp/issues/512>`_)
* Updated for Uncrustify 0.67 (`#510 <https://github.com/ros2/rclcpp/issues/510>`_)
* Added get_node_names API from node. (`#508 <https://github.com/ros2/rclcpp/issues/508>`_)
* Contributors: Anis Ladram, Chris Lalancette, Dirk Thomas, Francisco Martín Rico, Karsten Knese, Michael Carroll, Mikael Arguedas, Sagnik Basu, Shane Loretz, Sriram Raghunathan, William Woodall, chapulina, dhood
0.5.0 (2018-06-25)
------------------
* Fixed a bug in the multi-threaded executor which could cause it to take a timer (potentially other types of wait-able items) more than once to be worked one. (`#383 <https://github.com/ros2/rclcpp/issues/383>`_)
* Specifically this could result in a timer getting called more often that it should when using the multi-threaded executor.
* Added functions that allow you to publish serialized messages and received serialized messages in your subscription callback. (`#388 <https://github.com/ros2/rclcpp/issues/388>`_)
* Changed code to always get the Service name from ``rcl`` to ensure the remapped name is returned. (`#498 <https://github.com/ros2/rclcpp/issues/498>`_)
* Added previously missing ``set_parameters_atomically()`` method to the Service client interface. (`#494 <https://github.com/ros2/rclcpp/issues/494>`_)
* Added ability to initialize parameter values in a Node via a YAML file passed on the command line. (`#488 <https://github.com/ros2/rclcpp/issues/488>`_)
* Fixed the ROS parameter interface which got parameters that aren't set. (`#493 <https://github.com/ros2/rclcpp/issues/493>`_)
* Added ability to initialize parameter values in a node with an argument to the Node constructor. (`#486 <https://github.com/ros2/rclcpp/issues/486>`_)
* Added a ``Subscription`` tests which uses ``std::bind`` to a class member callback. (`#480 <https://github.com/ros2/rclcpp/issues/480>`_)
* Refactored the ``ParameterVariant`` class into the ``Parameter`` and ``ParameterValue`` classes. (`#481 <https://github.com/ros2/rclcpp/issues/481>`_)
* Relaxed template matching rules for ``std::bind`` and ``GNU C++ >= 7.1``. (`#484 <https://github.com/ros2/rclcpp/issues/484>`_)
* Changed to use the new ``rosgraph_msgs/Clock`` message type for the ``/clock`` topic. (`#474 <https://github.com/ros2/rclcpp/issues/474>`_)
* Fixed a flaky ROS time test due to not spinning before getting the time. (`#483 <https://github.com/ros2/rclcpp/issues/483>`_)
* Nodes now autostart the ROS parameter services which let you get, set, and list parameters in a node. (`#478 <https://github.com/ros2/rclcpp/issues/478>`_)
* Added support for arrays in Parameters. (`#443 <https://github.com/ros2/rclcpp/issues/443>`_)
* Changed how executors use ``AnyExecutable`` objects so that they are a reference instead of a shared pointer, in order to avoid memory allocation in the "common case". (`#463 <https://github.com/ros2/rclcpp/issues/463>`_)
* Added ability to pass command line arguments to the Node constructor. (`#461 <https://github.com/ros2/rclcpp/issues/461>`_)
* Added an argument to specify the number of threads a multithreaded executor should create. (`#442 <https://github.com/ros2/rclcpp/issues/442>`_)
* Changed library export order for static linking. (`#446 <https://github.com/ros2/rclcpp/issues/446>`_)
* Fixed some typos in the time unit tests. (`#453 <https://github.com/ros2/rclcpp/issues/453>`_)
Obviously it mean RCL_SYSTEM_TIME but not RCL_ROS_TIME in some test cases
* Signed-off-by: jwang <jing.j.wang@intel.com>
* Added the scale operation to ``rclcpp::Duration``.
* Signed-off-by: jwang <jing.j.wang@intel.com>
* Changed API of the log location parameter to be ``const``. (`#451 <https://github.com/ros2/rclcpp/issues/451>`_)
* Changed how the subscriber, client, service, and timer handles are stored to resolve shutdown order issues. (`#431 <https://github.com/ros2/rclcpp/issues/431>`_ and `#448 <https://github.com/ros2/rclcpp/issues/448>`_)
* Updated to get the node's logger name from ``rcl``. (`#433 <https://github.com/ros2/rclcpp/issues/433>`_)
* Now depends on ``ament_cmake_ros``. (`#444 <https://github.com/ros2/rclcpp/issues/444>`_)
* Updaed code to use logging macros rather than ``fprintf()``. (`#439 <https://github.com/ros2/rclcpp/issues/439>`_)
* Fixed a bug that was using an invalid iterator when erasing items using an iterator in a loop. (`#436 <https://github.com/ros2/rclcpp/issues/436>`_)
* Changed code to support move of ``rcutils_time_point_value_t`` type from ``uint64_t`` to ``int64_t``. (`#429 <https://github.com/ros2/rclcpp/issues/429>`_)
* Renamed parameter byte type to ``byte_values`` from ``bytes_value``. (`#428 <https://github.com/ros2/rclcpp/issues/428>`_)
* Changed executor code to clear the wait set before resizing and waiting. (`#427 <https://github.com/ros2/rclcpp/issues/427>`_)
* Fixed a potential dereference of nullptr in the topic name validation error string. (`#405 <https://github.com/ros2/rclcpp/issues/405>`_)
* Signed-off-by: Ethan Gao <ethan.gao@linux.intel.com>
* Changed to use ``rcl_count_publishers()`` like API's rather than the lower level ``rmw_count_publishers()`` API. (`#425 <https://github.com/ros2/rclcpp/issues/425>`_)
* Signed-off-by: Sriram Raghunathan <rsriram7@visteon.com>
* Fix potential segmentation fault due to ``get_topic_name()`` or ``rcl_service_get_service_name()`` returning nullptr and that not being checked before access in ``rclcpp``. (`#426 <https://github.com/ros2/rclcpp/issues/426>`_)
* Signed-off-by: Ethan Gao <ethan.gao@linux.intel.com>
* Contributors: Denise Eng, Dirk Thomas, Ernesto Corbellini, Esteve Fernandez, Ethan Gao, Guillaume Autran, Karsten Knese, Matthew, Michael Carroll, Mikael Arguedas, Shane Loretz, Sriram Raghunathan, Tom Moore, William Woodall, dhood, jwang, jwang11, serge-nikulin

View File

@@ -2,16 +2,28 @@ cmake_minimum_required(VERSION 3.5)
project(rclcpp)
find_package(ament_cmake REQUIRED)
find_package(ament_cmake_ros REQUIRED)
find_package(builtin_interfaces REQUIRED)
find_package(libstatistics_collector REQUIRED)
find_package(rcl REQUIRED)
find_package(rcl_interfaces REQUIRED)
find_package(rcl_yaml_param_parser REQUIRED)
find_package(rcpputils REQUIRED)
find_package(rcutils REQUIRED)
find_package(rmw REQUIRED)
find_package(rmw_implementation REQUIRED)
find_package(rmw_implementation_cmake REQUIRED)
find_package(rosidl_generator_cpp REQUIRED)
find_package(rosgraph_msgs REQUIRED)
find_package(rosidl_runtime_cpp REQUIRED)
find_package(rosidl_typesupport_c REQUIRED)
find_package(rosidl_typesupport_cpp REQUIRED)
find_package(statistics_msgs REQUIRED)
find_package(tracetools REQUIRED)
if(NOT WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra")
# Default to C++14
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)
endif()
include_directories(include)
@@ -20,118 +32,557 @@ set(${PROJECT_NAME}_SRCS
src/rclcpp/any_executable.cpp
src/rclcpp/callback_group.cpp
src/rclcpp/client.cpp
src/rclcpp/clock.cpp
src/rclcpp/context.cpp
src/rclcpp/contexts/default_context.cpp
src/rclcpp/detail/rmw_implementation_specific_payload.cpp
src/rclcpp/detail/rmw_implementation_specific_publisher_payload.cpp
src/rclcpp/detail/rmw_implementation_specific_subscription_payload.cpp
src/rclcpp/detail/utilities.cpp
src/rclcpp/duration.cpp
src/rclcpp/event.cpp
src/rclcpp/exceptions.cpp
src/rclcpp/exceptions/exceptions.cpp
src/rclcpp/executable_list.cpp
src/rclcpp/executor.cpp
src/rclcpp/executors.cpp
src/rclcpp/expand_topic_or_service_name.cpp
src/rclcpp/executors/multi_threaded_executor.cpp
src/rclcpp/executors/single_threaded_executor.cpp
src/rclcpp/executors/static_executor_entities_collector.cpp
src/rclcpp/executors/static_single_threaded_executor.cpp
src/rclcpp/future_return_code.cpp
src/rclcpp/graph_listener.cpp
src/rclcpp/guard_condition.cpp
src/rclcpp/init_options.cpp
src/rclcpp/intra_process_manager.cpp
src/rclcpp/intra_process_manager_impl.cpp
src/rclcpp/logger.cpp
src/rclcpp/memory_strategies.cpp
src/rclcpp/memory_strategy.cpp
src/rclcpp/parameter.cpp
src/rclcpp/parameter_client.cpp
src/rclcpp/parameter_service.cpp
src/rclcpp/publisher.cpp
src/rclcpp/message_info.cpp
src/rclcpp/node.cpp
src/rclcpp/node_options.cpp
src/rclcpp/node_interfaces/node_base.cpp
src/rclcpp/node_interfaces/node_clock.cpp
src/rclcpp/node_interfaces/node_graph.cpp
src/rclcpp/node_interfaces/node_logging.cpp
src/rclcpp/node_interfaces/node_parameters.cpp
src/rclcpp/node_interfaces/node_services.cpp
src/rclcpp/node_interfaces/node_time_source.cpp
src/rclcpp/node_interfaces/node_timers.cpp
src/rclcpp/node_interfaces/node_topics.cpp
src/rclcpp/node_interfaces/node_waitables.cpp
src/rclcpp/parameter.cpp
src/rclcpp/parameter_value.cpp
src/rclcpp/parameter_client.cpp
src/rclcpp/parameter_events_filter.cpp
src/rclcpp/parameter_map.cpp
src/rclcpp/parameter_service.cpp
src/rclcpp/publisher_base.cpp
src/rclcpp/qos.cpp
src/rclcpp/qos_event.cpp
src/rclcpp/serialization.cpp
src/rclcpp/serialized_message.cpp
src/rclcpp/service.cpp
src/rclcpp/subscription.cpp
src/rclcpp/signal_handler.cpp
src/rclcpp/subscription_base.cpp
src/rclcpp/subscription_intra_process_base.cpp
src/rclcpp/time.cpp
src/rclcpp/time_source.cpp
src/rclcpp/timer.cpp
src/rclcpp/type_support.cpp
src/rclcpp/utilities.cpp
src/rclcpp/wait_set_policies/detail/write_preferring_read_write_lock.cpp
src/rclcpp/waitable.cpp
)
macro(target)
if(NOT target_suffix STREQUAL "")
get_rcl_information("${rmw_implementation}" "rcl${target_suffix}")
endif()
add_library(${PROJECT_NAME}${target_suffix} SHARED
${${PROJECT_NAME}_SRCS})
ament_target_dependencies(${PROJECT_NAME}${target_suffix}
"rcl${target_suffix}"
"rosidl_generator_cpp")
# "watch" template for changes
configure_file(
"resource/logging.hpp.em"
"logging.hpp.em.watch"
COPYONLY
)
# generate header with logging macros
set(python_code
"import em"
"em.invoke(['-o', 'include/rclcpp/logging.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/logging.hpp.em'])")
string(REPLACE ";" "$<SEMICOLON>" python_code "${python_code}")
add_custom_command(OUTPUT include/rclcpp/logging.hpp
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp"
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_code}"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/logging.hpp.em.watch"
COMMENT "Expanding logging.hpp.em"
VERBATIM
)
list(APPEND ${PROJECT_NAME}_SRCS
include/rclcpp/logging.hpp)
include_directories("${CMAKE_CURRENT_BINARY_DIR}/include")
# Causes the visibility macros to use dllexport rather than dllimport,
# which is appropriate when building the dll but not consuming it.
target_compile_definitions(${PROJECT_NAME}${target_suffix}
PRIVATE "RCLCPP_BUILDING_LIBRARY")
add_library(${PROJECT_NAME}
${${PROJECT_NAME}_SRCS})
# specific order: dependents before dependencies
ament_target_dependencies(${PROJECT_NAME}
"libstatistics_collector"
"rcl"
"rcl_yaml_param_parser"
"rcpputils"
"rcutils"
"builtin_interfaces"
"rosgraph_msgs"
"rosidl_typesupport_cpp"
"rosidl_runtime_cpp"
"statistics_msgs"
"tracetools"
)
install(
TARGETS ${PROJECT_NAME}${target_suffix}
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
endmacro()
# Causes the visibility macros to use dllexport rather than dllimport,
# which is appropriate when building the dll but not consuming it.
target_compile_definitions(${PROJECT_NAME}
PRIVATE "RCLCPP_BUILDING_LIBRARY")
call_for_each_rmw_implementation(target GENERATE_DEFAULT)
ament_export_dependencies(ament_cmake)
ament_export_dependencies(rcl)
ament_export_dependencies(rosidl_generator_cpp)
install(
TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
# specific order: dependents before dependencies
ament_export_include_directories(include)
ament_export_libraries(${PROJECT_NAME})
ament_export_dependencies(libstatistics_collector)
ament_export_dependencies(rcl)
ament_export_dependencies(rcpputils)
ament_export_dependencies(rcutils)
ament_export_dependencies(builtin_interfaces)
ament_export_dependencies(rosgraph_msgs)
ament_export_dependencies(rosidl_typesupport_cpp)
ament_export_dependencies(rosidl_typesupport_c)
ament_export_dependencies(rosidl_runtime_cpp)
ament_export_dependencies(rcl_yaml_param_parser)
ament_export_dependencies(statistics_msgs)
ament_export_dependencies(tracetools)
if(BUILD_TESTING)
find_package(ament_cmake_gtest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
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
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
target_link_libraries(test_client ${PROJECT_NAME})
endif()
ament_add_gtest(test_create_timer test/test_create_timer.cpp)
if(TARGET test_create_timer)
ament_target_dependencies(test_create_timer
"rcl_interfaces"
"rmw"
"rcl"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
target_link_libraries(test_create_timer ${PROJECT_NAME})
target_include_directories(test_create_timer PRIVATE test/)
endif()
ament_add_gtest(test_expand_topic_or_service_name test/test_expand_topic_or_service_name.cpp)
if(TARGET test_expand_topic_or_service_name)
ament_target_dependencies(test_expand_topic_or_service_name
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
target_link_libraries(test_expand_topic_or_service_name ${PROJECT_NAME})
endif()
ament_add_gtest(test_function_traits test/test_function_traits.cpp)
if(TARGET test_function_traits)
target_include_directories(test_function_traits PUBLIC
${rcl_interfaces_INCLUDE_DIRS}
${rmw_INCLUDE_DIRS}
${rosidl_generator_cpp_INCLUDE_DIRS}
ament_target_dependencies(test_function_traits
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
endif()
ament_add_gtest(test_mapped_ring_buffer test/test_mapped_ring_buffer.cpp)
if(TARGET test_mapped_ring_buffer)
target_include_directories(test_mapped_ring_buffer PUBLIC
${rcl_INCLUDE_DIRS}
${rcl_interfaces_INCLUDE_DIRS}
${rmw_INCLUDE_DIRS}
${rosidl_generator_cpp_INCLUDE_DIRS}
)
endif()
ament_add_gtest(test_intra_process_manager test/test_intra_process_manager.cpp)
ament_add_gmock(test_intra_process_manager test/test_intra_process_manager.cpp)
if(TARGET test_intra_process_manager)
target_include_directories(test_intra_process_manager PUBLIC
${rcl_INCLUDE_DIRS}
${rcl_interfaces_INCLUDE_DIRS}
${rmw_INCLUDE_DIRS}
${rosidl_generator_cpp_INCLUDE_DIRS}
ament_target_dependencies(test_intra_process_manager
"rcl"
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
target_link_libraries(test_intra_process_manager ${PROJECT_NAME})
endif()
ament_add_gtest(test_ring_buffer_implementation test/test_ring_buffer_implementation.cpp)
if(TARGET test_ring_buffer_implementation)
ament_target_dependencies(test_ring_buffer_implementation
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
target_link_libraries(test_ring_buffer_implementation ${PROJECT_NAME})
endif()
ament_add_gtest(test_intra_process_buffer test/test_intra_process_buffer.cpp)
if(TARGET test_intra_process_buffer)
ament_target_dependencies(test_intra_process_buffer
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
target_link_libraries(test_intra_process_buffer ${PROJECT_NAME})
endif()
ament_add_gtest(test_loaned_message test/test_loaned_message.cpp)
ament_target_dependencies(test_loaned_message
"test_msgs"
)
target_link_libraries(test_loaned_message ${PROJECT_NAME})
ament_add_gtest(test_node test/test_node.cpp TIMEOUT 240)
if(TARGET test_node)
ament_target_dependencies(test_node
"rcl_interfaces"
"rcpputils"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
"test_msgs"
)
target_link_libraries(test_node ${PROJECT_NAME})
endif()
ament_add_gtest(test_node_interfaces__get_node_interfaces
test/node_interfaces/test_get_node_interfaces.cpp)
if(TARGET test_node_interfaces__get_node_interfaces)
target_link_libraries(test_node_interfaces__get_node_interfaces ${PROJECT_NAME})
endif()
# TODO(wjwwood): reenable these build failure tests when I can get Jenkins to ignore their output
# rclcpp_add_build_failure_test(build_failure__get_node_topics_interface_const_ref_rclcpp_node
# test/node_interfaces/test_does_not_compile/get_node_topics_interface_const_ref_rclcpp_node.cpp)
# target_link_libraries(build_failure__get_node_topics_interface_const_ref_rclcpp_node
# ${PROJECT_NAME})
# rclcpp_add_build_failure_test(build_failure__get_node_topics_interface_const_ptr_rclcpp_node
# test/node_interfaces/test_does_not_compile/get_node_topics_interface_const_ptr_rclcpp_node.cpp)
# target_link_libraries(build_failure__get_node_topics_interface_const_ptr_rclcpp_node
# ${PROJECT_NAME})
# rclcpp_add_build_failure_test(build_failure__get_node_topics_interface_const_ref_wrapped_node
# test/node_interfaces/test_does_not_compile/get_node_topics_interface_const_ref_wrapped_node.cpp)
# target_link_libraries(build_failure__get_node_topics_interface_const_ref_rclcpp_node
# ${PROJECT_NAME})
# rclcpp_add_build_failure_test(build_failure__get_node_topics_interface_const_ptr_wrapped_node
# test/node_interfaces/test_does_not_compile/get_node_topics_interface_const_ptr_wrapped_node.cpp)
# target_link_libraries(build_failure__get_node_topics_interface_const_ptr_rclcpp_node
# ${PROJECT_NAME})
ament_add_gtest(test_node_global_args test/test_node_global_args.cpp)
if(TARGET test_node_global_args)
ament_target_dependencies(test_node_global_args
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
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
"rcl_interfaces"
)
target_link_libraries(test_parameter_client ${PROJECT_NAME})
endif()
ament_add_gtest(test_parameter_events_filter test/test_parameter_events_filter.cpp)
if(TARGET test_parameter_events_filter)
ament_target_dependencies(test_parameter_events_filter
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
target_link_libraries(test_parameter_events_filter ${PROJECT_NAME})
endif()
ament_add_gtest(test_parameter test/test_parameter.cpp)
if(TARGET test_parameter)
ament_target_dependencies(test_parameter
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
target_link_libraries(test_parameter ${PROJECT_NAME})
endif()
ament_add_gtest(test_parameter_map test/test_parameter_map.cpp)
if(TARGET test_parameter_map)
target_link_libraries(test_parameter_map ${PROJECT_NAME})
endif()
ament_add_gtest(test_publisher test/test_publisher.cpp)
if(TARGET test_publisher)
ament_target_dependencies(test_publisher
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
"test_msgs"
)
target_link_libraries(test_publisher ${PROJECT_NAME})
endif()
ament_add_gtest(test_publisher_subscription_count_api test/test_publisher_subscription_count_api.cpp)
if(TARGET test_publisher_subscription_count_api)
ament_target_dependencies(test_publisher_subscription_count_api
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
"test_msgs"
)
target_link_libraries(test_publisher_subscription_count_api ${PROJECT_NAME})
endif()
ament_add_gtest(test_qos test/test_qos.cpp)
if(TARGET test_qos)
ament_target_dependencies(test_qos
"rmw"
)
target_link_libraries(test_qos
${PROJECT_NAME}
)
endif()
ament_add_gtest(test_rate test/test_rate.cpp
ENV RCL_ASSERT_RMW_ID_MATCHES=${rmw_implementation})
ament_add_gtest(test_qos_event test/test_qos_event.cpp)
if(TARGET test_qos_event)
ament_target_dependencies(test_qos_event
"rmw"
"test_msgs"
)
target_link_libraries(test_qos_event
${PROJECT_NAME}
)
endif()
ament_add_gtest(test_rate test/test_rate.cpp)
if(TARGET test_rate)
target_include_directories(test_rate PUBLIC
${rcl_interfaces_INCLUDE_DIRS}
${rmw_INCLUDE_DIRS}
${rosidl_generator_cpp_INCLUDE_DIRS}
ament_target_dependencies(test_rate
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
target_link_libraries(test_rate
${PROJECT_NAME}
)
endif()
ament_add_gtest(test_serialized_message_allocator test/test_serialized_message_allocator.cpp)
if(TARGET test_serialized_message_allocator)
ament_target_dependencies(test_serialized_message_allocator
test_msgs
)
target_link_libraries(test_serialized_message_allocator
${PROJECT_NAME}
)
endif()
ament_add_gtest(test_serialized_message test/test_serialized_message.cpp)
if(TARGET test_serialized_message)
ament_target_dependencies(test_serialized_message
test_msgs
)
target_link_libraries(test_serialized_message
${PROJECT_NAME}
)
endif()
ament_add_gtest(test_service test/test_service.cpp)
if(TARGET test_service)
ament_target_dependencies(test_service
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
)
target_link_libraries(test_service ${PROJECT_NAME})
endif()
ament_add_gtest(test_subscription test/test_subscription.cpp)
if(TARGET test_subscription)
ament_target_dependencies(test_subscription
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
"test_msgs"
)
target_link_libraries(test_subscription ${PROJECT_NAME})
endif()
ament_add_gtest(test_subscription_publisher_count_api test/test_subscription_publisher_count_api.cpp)
if(TARGET test_subscription_publisher_count_api)
ament_target_dependencies(test_subscription_publisher_count_api
"rcl_interfaces"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
"test_msgs"
)
target_link_libraries(test_subscription_publisher_count_api ${PROJECT_NAME})
endif()
ament_add_gtest(test_subscription_traits test/test_subscription_traits.cpp)
if(TARGET test_subscription_traits)
ament_target_dependencies(test_subscription_traits
"rcl"
"test_msgs"
)
target_link_libraries(test_subscription_traits ${PROJECT_NAME})
endif()
ament_add_gtest(test_find_weak_nodes test/test_find_weak_nodes.cpp)
if(TARGET test_find_weak_nodes)
ament_target_dependencies(test_find_weak_nodes
"rcl"
)
target_link_libraries(test_find_weak_nodes ${PROJECT_NAME})
endif()
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_duration test/test_duration.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}")
if(TARGET test_duration)
ament_target_dependencies(test_duration
"rcl")
target_link_libraries(test_duration ${PROJECT_NAME})
endif()
ament_add_gtest(test_executor test/test_executor.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}")
if(TARGET test_executor)
ament_target_dependencies(test_executor
"rcl")
target_link_libraries(test_executor ${PROJECT_NAME})
endif()
ament_add_gtest(test_logger test/test_logger.cpp)
target_link_libraries(test_logger ${PROJECT_NAME})
ament_add_gmock(test_logging test/test_logging.cpp)
target_link_libraries(test_logging ${PROJECT_NAME})
ament_add_gtest(test_time test/test_time.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}")
if(TARGET test_time)
ament_target_dependencies(test_time
"rcl")
target_link_libraries(test_time ${PROJECT_NAME})
endif()
ament_add_gtest(test_timer test/test_timer.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}")
if(TARGET test_timer)
ament_target_dependencies(test_timer
"rcl")
target_link_libraries(test_timer ${PROJECT_NAME})
endif()
ament_add_gtest(test_time_source test/test_time_source.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}")
if(TARGET test_time_source)
ament_target_dependencies(test_time_source
"rcl")
target_link_libraries(test_time_source ${PROJECT_NAME})
endif()
ament_add_gtest(test_utilities test/test_utilities.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}")
if(TARGET test_utilities)
ament_target_dependencies(test_utilities
"rcl")
target_link_libraries(test_utilities ${PROJECT_NAME})
endif()
ament_add_gtest(test_init test/test_init.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}")
if(TARGET test_init)
ament_target_dependencies(test_init
"rcl")
target_link_libraries(test_init ${PROJECT_NAME})
endif()
ament_add_gtest(test_multi_threaded_executor test/executors/test_multi_threaded_executor.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}")
if(TARGET test_multi_threaded_executor)
ament_target_dependencies(test_multi_threaded_executor
"rcl")
target_link_libraries(test_multi_threaded_executor ${PROJECT_NAME})
endif()
ament_add_gtest(test_guard_condition test/test_guard_condition.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}")
if(TARGET test_guard_condition)
target_link_libraries(test_guard_condition ${PROJECT_NAME})
endif()
ament_add_gtest(test_wait_set test/test_wait_set.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}")
if(TARGET test_wait_set)
ament_target_dependencies(test_wait_set "test_msgs")
target_link_libraries(test_wait_set ${PROJECT_NAME})
endif()
ament_add_gtest(test_subscription_topic_statistics test/topic_statistics/test_subscription_topic_statistics.cpp)
if(TARGET test_subscription_topic_statistics)
ament_target_dependencies(test_subscription_topic_statistics
"libstatistics_collector"
"rcl_interfaces"
"rcutils"
"rmw"
"rosidl_runtime_cpp"
"rosidl_typesupport_cpp"
"statistics_msgs"
"test_msgs")
target_link_libraries(test_subscription_topic_statistics ${PROJECT_NAME})
endif()
ament_add_gtest(test_subscription_options test/test_subscription_options.cpp)
if(TARGET test_subscription_options)
ament_target_dependencies(test_subscription_options "rcl")
target_link_libraries(test_subscription_options ${PROJECT_NAME})
endif()
# Install test resources
install(
DIRECTORY test/resources
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/test)
endif()
ament_package(
CONFIG_EXTRAS rclcpp-extras.cmake
)
ament_package()
install(
DIRECTORY cmake
DESTINATION share/${PROJECT_NAME}
)
install(
DIRECTORY include/
DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/
DESTINATION include
)

33
rclcpp/Doxyfile Normal file
View File

@@ -0,0 +1,33 @@
# All settings not listed here will use the Doxygen default values.
PROJECT_NAME = "rclcpp"
PROJECT_NUMBER = master
PROJECT_BRIEF = "C++ ROS Client Library API"
# Use these lines to include the generated logging.hpp (update install path if needed)
#INPUT = ../../../../install_isolated/rclcpp/include
#STRIP_FROM_PATH = /Users/william/ros2_ws/install_isolated/rclcpp/include
# Otherwise just generate for the local (non-generated header files)
INPUT = ./include
RECURSIVE = YES
OUTPUT_DIRECTORY = doc_output
EXTRACT_ALL = YES
SORT_MEMBER_DOCS = NO
GENERATE_LATEX = NO
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = RCLCPP_PUBLIC=
# Tag files that do not exist will produce a warning and cross-project linking will not work.
TAGFILES += "../../../../doxygen_tag_files/cppreference-doxygen-web.tag.xml=http://en.cppreference.com/w/"
# Consider changing "latest" to the version you want to reference (e.g. beta1 or 1.0.0)
TAGFILES += "../../../../doxygen_tag_files/rcl.tag=http://docs.ros2.org/latest/api/rcl/"
TAGFILES += "../../../../doxygen_tag_files/rmw.tag=http://docs.ros2.org/latest/api/rmw/"
TAGFILES += "../../../../doxygen_tag_files/rcutils.tag=http://docs.ros2.org/latest/api/rcutils/"
# Uncomment to generate tag files for cross-project linking.
#GENERATE_TAGFILE = "../../../../doxygen_tag_files/rclcpp.tag"

View File

@@ -1,92 +0,0 @@
# Copyright 2015 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Get all information about rclcpp for a specific RMW implementation.
#
# It sets the common variables _DEFINITIONS, _INCLUDE_DIRS and _LIBRARIES
# with the given prefix.
#
# :param rmw_implementation: the RMW implementation name
# :type target: string
# :param var_prefix: the prefix of all output variable names
# :type var_prefix: string
#
macro(get_rclcpp_information rmw_implementation var_prefix)
# pretend to be a "package"
# so that the variables can be used by various functions / macros
set(${var_prefix}_FOUND TRUE)
# Get rcl using the existing macro
if(NOT target_suffix STREQUAL "")
get_rcl_information("${rmw_implementation}" "rcl${target_suffix}")
endif()
# include directories
normalize_path(${var_prefix}_INCLUDE_DIRS
"${rclcpp_DIR}/../../../include")
# libraries
set(_libs)
# search for library relative to this CMake file
set(_library_target "rclcpp")
get_available_rmw_implementations(_rmw_impls)
list(LENGTH _rmw_impls _rmw_impls_length)
if(_rmw_impls_length GREATER 1)
set(_library_target "${_library_target}__${rmw_implementation}")
endif()
set(_lib "NOTFOUND")
find_library(
_lib NAMES "${_library_target}"
PATHS "${rclcpp_DIR}/../../../lib"
NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH
)
if(NOT _lib)
# warn about not existing library and ignore it
message(WARNING "Package 'rclcpp' doesn't contain the library '${_library_target}'")
elseif(NOT IS_ABSOLUTE "${_lib}")
# the found library must be an absolute path
message(FATAL_ERROR "Package 'rclcpp' found the library '${_library_target}' at '${_lib}' which is not an absolute path")
elseif(NOT EXISTS "${_lib}")
# the found library must exist
message(FATAL_ERROR "Package 'rclcpp' found the library '${_lib}' which doesn't exist")
else()
list(APPEND _libs "${_lib}")
endif()
# dependencies
set(_exported_dependencies
"rcl_interfaces"
"rcl${target_suffix}"
"rosidl_generator_cpp")
set(${var_prefix}_DEFINITIONS)
foreach(_dep ${_exported_dependencies})
if(NOT ${_dep}_FOUND)
find_package("${_dep}" QUIET REQUIRED)
endif()
if(${_dep}_DEFINITIONS)
list_append_unique(${var_prefix}_DEFINITIONS "${${_dep}_DEFINITIONS}")
endif()
if(${_dep}_INCLUDE_DIRS)
list_append_unique(${var_prefix}_INCLUDE_DIRS "${${_dep}_INCLUDE_DIRS}")
endif()
if(${_dep}_LIBRARIES)
list(APPEND _libs "${${_dep}_LIBRARIES}")
endif()
endforeach()
if(_libs)
ament_libraries_deduplicate(_libs "${_libs}")
endif()
set(${var_prefix}_LIBRARIES "${_libs}")
endmacro()

View File

@@ -0,0 +1,56 @@
# 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.
#
# Register a test which tries to compile a file and expects it to fail to build.
#
# This will create two targets, one by the given target name and a test target
# which has the same name prefixed with `test_`.
# For example, if target is `should_not_compile__use_const_argument` then there
# will be an executable target called `should_not_compile__use_const_argument`
# and a test target called `test_should_not_compile__use_const_argument`.
#
# :param target: the name of the target to be created
# :type target: string
# :param ARGN: the list of source files to be used to create the test executable
# :type ARGN: list of strings
#
macro(rclcpp_add_build_failure_test target)
if(${ARGC} EQUAL 0)
message(
FATAL_ERROR
"rclcpp_add_build_failure_test() requires a target name and "
"at least one source file")
endif()
add_executable(${target} ${ARGN})
set_target_properties(${target}
PROPERTIES
EXCLUDE_FROM_ALL TRUE
EXCLUDE_FROM_DEFAULT_BUILD TRUE)
add_test(
NAME test_${target}
COMMAND
${CMAKE_COMMAND}
--build .
--target ${target}
--config $<CONFIGURATION>
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_tests_properties(test_${target}
PROPERTIES
WILL_FAIL TRUE
LABELS "build_failure"
)
endmacro()

View File

@@ -64,8 +64,10 @@ void * retyped_reallocate(void * untyped_pointer, size_t size, void * untyped_al
// Convert a std::allocator_traits-formatted Allocator into an rcl allocator
template<typename T, typename Alloc,
typename std::enable_if<!std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
template<
typename T,
typename Alloc,
typename std::enable_if<!std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
rcl_allocator_t get_rcl_allocator(Alloc & allocator)
{
rcl_allocator_t rcl_allocator = rcl_get_default_allocator();
@@ -81,8 +83,10 @@ rcl_allocator_t get_rcl_allocator(Alloc & allocator)
}
// TODO(jacquelinekay) Workaround for an incomplete implementation of std::allocator<void>
template<typename T, typename Alloc,
typename std::enable_if<std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
template<
typename T,
typename Alloc,
typename std::enable_if<std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
rcl_allocator_t get_rcl_allocator(Alloc & allocator)
{
(void)allocator;

View File

@@ -94,11 +94,11 @@ void set_allocator_for_deleter(AllocatorDeleter<T> * deleter, Alloc * alloc)
template<typename Alloc, typename T>
using Deleter = typename std::conditional<
std::is_same<typename std::allocator_traits<Alloc>::template rebind_alloc<T>,
typename std::allocator<void>::template rebind<T>::other>::value,
std::default_delete<T>,
AllocatorDeleter<Alloc>
>::type;
std::is_same<typename std::allocator_traits<Alloc>::template rebind_alloc<T>,
typename std::allocator<void>::template rebind<T>::other>::value,
std::default_delete<T>,
AllocatorDeleter<Alloc>
>::type;
} // namespace allocator
} // namespace rclcpp

View File

@@ -17,19 +17,21 @@
#include <memory>
#include "rclcpp/callback_group.hpp"
#include "rclcpp/client.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/service.hpp"
#include "rclcpp/subscription.hpp"
#include "rclcpp/timer.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/waitable.hpp"
namespace rclcpp
{
namespace executor
{
struct AnyExecutable
{
RCLCPP_SMART_PTR_DEFINITIONS(AnyExecutable);
RCLCPP_PUBLIC
AnyExecutable();
@@ -37,16 +39,21 @@ struct AnyExecutable
virtual ~AnyExecutable();
// Only one of the following pointers will be set.
rclcpp::subscription::SubscriptionBase::SharedPtr subscription;
rclcpp::subscription::SubscriptionBase::SharedPtr subscription_intra_process;
rclcpp::timer::TimerBase::SharedPtr timer;
rclcpp::service::ServiceBase::SharedPtr service;
rclcpp::client::ClientBase::SharedPtr client;
rclcpp::SubscriptionBase::SharedPtr subscription;
rclcpp::TimerBase::SharedPtr timer;
rclcpp::ServiceBase::SharedPtr service;
rclcpp::ClientBase::SharedPtr client;
rclcpp::Waitable::SharedPtr waitable;
// These are used to keep the scope on the containing items
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group;
rclcpp::node::Node::SharedPtr node;
rclcpp::CallbackGroup::SharedPtr callback_group;
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base;
};
namespace executor
{
using AnyExecutable [[deprecated("use rclcpp::AnyExecutable instead")]] = AnyExecutable;
} // namespace executor
} // namespace rclcpp

View File

@@ -23,26 +23,27 @@
#include "rclcpp/function_traits.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rmw/types.h"
#include "tracetools/tracetools.h"
#include "tracetools/utils.hpp"
namespace rclcpp
{
namespace any_service_callback
{
template<typename ServiceT>
class AnyServiceCallback
{
private:
using SharedPtrCallback = std::function<void(
const std::shared_ptr<typename ServiceT::Request>,
std::shared_ptr<typename ServiceT::Response>
)>;
using SharedPtrWithRequestHeaderCallback = std::function<void(
const std::shared_ptr<rmw_request_id_t>,
const std::shared_ptr<typename ServiceT::Request>,
std::shared_ptr<typename ServiceT::Response>
)>;
using SharedPtrCallback = std::function<
void (
const std::shared_ptr<typename ServiceT::Request>,
std::shared_ptr<typename ServiceT::Response>
)>;
using SharedPtrWithRequestHeaderCallback = std::function<
void (
const std::shared_ptr<rmw_request_id_t>,
const std::shared_ptr<typename ServiceT::Request>,
std::shared_ptr<typename ServiceT::Response>
)>;
SharedPtrCallback shared_ptr_callback_;
SharedPtrWithRequestHeaderCallback shared_ptr_with_request_header_callback_;
@@ -87,6 +88,7 @@ public:
std::shared_ptr<typename ServiceT::Request> request,
std::shared_ptr<typename ServiceT::Response> response)
{
TRACEPOINT(callback_start, (const void *)this, false);
if (shared_ptr_callback_ != nullptr) {
(void)request_header;
shared_ptr_callback_(request, response);
@@ -95,10 +97,27 @@ public:
} else {
throw std::runtime_error("unexpected request without any callback set");
}
TRACEPOINT(callback_end, (const void *)this);
}
void register_callback_for_tracing()
{
#ifndef TRACETOOLS_DISABLED
if (shared_ptr_callback_) {
TRACEPOINT(
rclcpp_callback_register,
(const void *)this,
get_symbol(shared_ptr_callback_));
} else if (shared_ptr_with_request_header_callback_) {
TRACEPOINT(
rclcpp_callback_register,
(const void *)this,
get_symbol(shared_ptr_with_request_header_callback_));
}
#endif // TRACETOOLS_DISABLED
}
};
} // namespace any_service_callback
} // namespace rclcpp
#endif // RCLCPP__ANY_SERVICE_CALLBACK_HPP_

View File

@@ -25,31 +25,32 @@
#include "rclcpp/allocator/allocator_common.hpp"
#include "rclcpp/function_traits.hpp"
#include "rclcpp/message_info.hpp"
#include "rclcpp/visibility_control.hpp"
#include "tracetools/tracetools.h"
#include "tracetools/utils.hpp"
namespace rclcpp
{
namespace any_subscription_callback
{
template<typename MessageT, typename Alloc>
class AnySubscriptionCallback
{
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
using MessageAlloc = typename MessageAllocTraits::allocator_type;
using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;
using ConstMessageSharedPtr = std::shared_ptr<const MessageT>;
using MessageUniquePtr = std::unique_ptr<MessageT, MessageDeleter>;
using SharedPtrCallback = std::function<void(const std::shared_ptr<MessageT>)>;
using SharedPtrCallback = std::function<void (const std::shared_ptr<MessageT>)>;
using SharedPtrWithInfoCallback =
std::function<void(const std::shared_ptr<MessageT>, const rmw_message_info_t &)>;
using ConstSharedPtrCallback = std::function<void(const std::shared_ptr<const MessageT>)>;
std::function<void (const std::shared_ptr<MessageT>, const rclcpp::MessageInfo &)>;
using ConstSharedPtrCallback = std::function<void (const std::shared_ptr<const MessageT>)>;
using ConstSharedPtrWithInfoCallback =
std::function<void(const std::shared_ptr<const MessageT>, const rmw_message_info_t &)>;
using UniquePtrCallback = std::function<void(MessageUniquePtr)>;
std::function<void (const std::shared_ptr<const MessageT>, const rclcpp::MessageInfo &)>;
using UniquePtrCallback = std::function<void (MessageUniquePtr)>;
using UniquePtrWithInfoCallback =
std::function<void(MessageUniquePtr, const rmw_message_info_t &)>;
std::function<void (MessageUniquePtr, const rclcpp::MessageInfo &)>;
SharedPtrCallback shared_ptr_callback_;
SharedPtrWithInfoCallback shared_ptr_with_info_callback_;
@@ -155,9 +156,9 @@ public:
}
void dispatch(
std::shared_ptr<MessageT> message, const rmw_message_info_t & message_info)
std::shared_ptr<MessageT> message, const rclcpp::MessageInfo & message_info)
{
(void)message_info;
TRACEPOINT(callback_start, (const void *)this, false);
if (shared_ptr_callback_) {
shared_ptr_callback_(message);
} else if (shared_ptr_with_info_callback_) {
@@ -177,31 +178,86 @@ public:
} else {
throw std::runtime_error("unexpected message without any callback set");
}
TRACEPOINT(callback_end, (const void *)this);
}
void dispatch_intra_process(
MessageUniquePtr & message, const rmw_message_info_t & message_info)
ConstMessageSharedPtr message, const rclcpp::MessageInfo & message_info)
{
(void)message_info;
TRACEPOINT(callback_start, (const void *)this, true);
if (const_shared_ptr_callback_) {
const_shared_ptr_callback_(message);
} else if (const_shared_ptr_with_info_callback_) {
const_shared_ptr_with_info_callback_(message, message_info);
} else {
if (
unique_ptr_callback_ || unique_ptr_with_info_callback_ ||
shared_ptr_callback_ || shared_ptr_with_info_callback_)
{
throw std::runtime_error(
"unexpected dispatch_intra_process const shared "
"message call with no const shared_ptr callback");
} else {
throw std::runtime_error("unexpected message without any callback set");
}
}
TRACEPOINT(callback_end, (const void *)this);
}
void dispatch_intra_process(
MessageUniquePtr message, const rclcpp::MessageInfo & message_info)
{
TRACEPOINT(callback_start, (const void *)this, true);
if (shared_ptr_callback_) {
typename std::shared_ptr<MessageT> shared_message = std::move(message);
shared_ptr_callback_(shared_message);
} else if (shared_ptr_with_info_callback_) {
typename std::shared_ptr<MessageT> shared_message = std::move(message);
shared_ptr_with_info_callback_(shared_message, message_info);
} else if (const_shared_ptr_callback_) {
typename std::shared_ptr<MessageT const> const_shared_message = std::move(message);
const_shared_ptr_callback_(const_shared_message);
} else if (const_shared_ptr_with_info_callback_) {
typename std::shared_ptr<MessageT const> const_shared_message = std::move(message);
const_shared_ptr_with_info_callback_(const_shared_message, message_info);
} else if (unique_ptr_callback_) {
unique_ptr_callback_(std::move(message));
} else if (unique_ptr_with_info_callback_) {
unique_ptr_with_info_callback_(std::move(message), message_info);
} else if (const_shared_ptr_callback_ || const_shared_ptr_with_info_callback_) {
throw std::runtime_error(
"unexpected dispatch_intra_process unique message call"
" with const shared_ptr callback");
} else {
throw std::runtime_error("unexpected message without any callback set");
}
TRACEPOINT(callback_end, (const void *)this);
}
bool use_take_shared_method() const
{
return const_shared_ptr_callback_ || const_shared_ptr_with_info_callback_;
}
void register_callback_for_tracing()
{
#ifndef TRACETOOLS_DISABLED
if (shared_ptr_callback_) {
TRACEPOINT(
rclcpp_callback_register,
(const void *)this,
get_symbol(shared_ptr_callback_));
} else if (shared_ptr_with_info_callback_) {
TRACEPOINT(
rclcpp_callback_register,
(const void *)this,
get_symbol(shared_ptr_with_info_callback_));
} else if (unique_ptr_callback_) {
TRACEPOINT(
rclcpp_callback_register,
(const void *)this,
get_symbol(unique_ptr_callback_));
} else if (unique_ptr_with_info_callback_) {
TRACEPOINT(
rclcpp_callback_register,
(const void *)this,
get_symbol(unique_ptr_with_info_callback_));
}
#endif // TRACETOOLS_DISABLED
}
private:
@@ -209,7 +265,6 @@ private:
MessageDeleter message_deleter_;
};
} // namespace any_subscription_callback
} // namespace rclcpp
#endif // RCLCPP__ANY_SUBSCRIPTION_CALLBACK_HPP_

View File

@@ -21,22 +21,24 @@
#include <vector>
#include "rclcpp/client.hpp"
#include "rclcpp/publisher_base.hpp"
#include "rclcpp/service.hpp"
#include "rclcpp/subscription.hpp"
#include "rclcpp/subscription_base.hpp"
#include "rclcpp/timer.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/waitable.hpp"
namespace rclcpp
{
// Forward declarations for friend statement in class CallbackGroup
namespace node
{
class Node;
} // namespace node
namespace callback_group
namespace node_interfaces
{
class NodeServices;
class NodeTimers;
class NodeTopics;
class NodeWaitables;
} // namespace node_interfaces
enum class CallbackGroupType
{
@@ -46,29 +48,51 @@ enum class CallbackGroupType
class CallbackGroup
{
friend class rclcpp::node::Node;
friend class rclcpp::node_interfaces::NodeServices;
friend class rclcpp::node_interfaces::NodeTimers;
friend class rclcpp::node_interfaces::NodeTopics;
friend class rclcpp::node_interfaces::NodeWaitables;
public:
RCLCPP_SMART_PTR_DEFINITIONS(CallbackGroup);
RCLCPP_SMART_PTR_DEFINITIONS(CallbackGroup)
RCLCPP_PUBLIC
explicit CallbackGroup(CallbackGroupType group_type);
RCLCPP_PUBLIC
const std::vector<rclcpp::subscription::SubscriptionBase::WeakPtr> &
get_subscription_ptrs() const;
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::timer::TimerBase::WeakPtr> &
get_timer_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::service::ServiceBase::SharedPtr> &
get_service_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::client::ClientBase::WeakPtr> &
get_client_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_);
}
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
std::atomic_bool &
@@ -78,35 +102,69 @@ public:
const CallbackGroupType &
type() const;
private:
RCLCPP_DISABLE_COPY(CallbackGroup);
protected:
RCLCPP_DISABLE_COPY(CallbackGroup)
RCLCPP_PUBLIC
void
add_subscription(const rclcpp::subscription::SubscriptionBase::SharedPtr subscription_ptr);
add_publisher(const rclcpp::PublisherBase::SharedPtr publisher_ptr);
RCLCPP_PUBLIC
void
add_timer(const rclcpp::timer::TimerBase::SharedPtr timer_ptr);
add_subscription(const rclcpp::SubscriptionBase::SharedPtr subscription_ptr);
RCLCPP_PUBLIC
void
add_service(const rclcpp::service::ServiceBase::SharedPtr service_ptr);
add_timer(const rclcpp::TimerBase::SharedPtr timer_ptr);
RCLCPP_PUBLIC
void
add_client(const rclcpp::client::ClientBase::SharedPtr client_ptr);
add_service(const rclcpp::ServiceBase::SharedPtr service_ptr);
RCLCPP_PUBLIC
void
add_client(const rclcpp::ClientBase::SharedPtr client_ptr);
RCLCPP_PUBLIC
void
add_waitable(const rclcpp::Waitable::SharedPtr waitable_ptr);
RCLCPP_PUBLIC
void
remove_waitable(const rclcpp::Waitable::SharedPtr waitable_ptr) noexcept;
CallbackGroupType type_;
// Mutex to protect the subsequent vectors of pointers.
mutable std::mutex mutex_;
std::vector<rclcpp::subscription::SubscriptionBase::WeakPtr> subscription_ptrs_;
std::vector<rclcpp::timer::TimerBase::WeakPtr> timer_ptrs_;
std::vector<rclcpp::service::ServiceBase::SharedPtr> service_ptrs_;
std::vector<rclcpp::client::ClientBase::WeakPtr> client_ptrs_;
std::vector<rclcpp::SubscriptionBase::WeakPtr> subscription_ptrs_;
std::vector<rclcpp::TimerBase::WeakPtr> timer_ptrs_;
std::vector<rclcpp::ServiceBase::WeakPtr> service_ptrs_;
std::vector<rclcpp::ClientBase::WeakPtr> client_ptrs_;
std::vector<rclcpp::Waitable::WeakPtr> waitable_ptrs_;
std::atomic_bool can_be_taken_from_;
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
{
using CallbackGroupType [[deprecated("use rclcpp::CallbackGroupType instead")]] = CallbackGroupType;
using CallbackGroup [[deprecated("use rclcpp::CallbackGroup instead")]] = CallbackGroup;
} // namespace callback_group
} // namespace rclcpp

View File

@@ -15,6 +15,7 @@
#ifndef RCLCPP__CLIENT_HPP_
#define RCLCPP__CLIENT_HPP_
#include <atomic>
#include <future>
#include <map>
#include <memory>
@@ -27,55 +28,82 @@
#include "rcl/error_handling.h"
#include "rcl/wait.h"
#include "rclcpp/exceptions.hpp"
#include "rclcpp/function_traits.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
#include "rclcpp/type_support_decl.hpp"
#include "rclcpp/utilities.hpp"
#include "rclcpp/expand_topic_or_service_name.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rcutils/logging_macros.h"
#include "rmw/error_handling.h"
#include "rmw/rmw.h"
namespace rclcpp
{
namespace node
{
class Node;
} // namespace node
namespace client
namespace node_interfaces
{
class NodeBaseInterface;
} // namespace node_interfaces
class ClientBase
{
public:
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(ClientBase);
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(ClientBase)
RCLCPP_PUBLIC
ClientBase(
std::shared_ptr<rclcpp::node::Node> parent_node,
const std::string & service_name);
rclcpp::node_interfaces::NodeBaseInterface * node_base,
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph);
RCLCPP_PUBLIC
virtual ~ClientBase();
/// Take the next response for this client as a type erased pointer.
/**
* The type erased pointer allows for this method to be used in a type
* agnostic way along with ClientBase::create_response(),
* ClientBase::create_request_header(), and ClientBase::handle_response().
* The typed version of this can be used if the Service type is known,
* \sa Client::take_response().
*
* \param[out] response_out The type erased pointer to a Service Response into
* which the middleware will copy the response being taken.
* \param[out] request_header_out The request header to be filled by the
* middleware when taking, and which can be used to associte the response
* to a specific request.
* \returns true if the response was taken, otherwise false.
* \throws rclcpp::exceptions::RCLError based exceptions if the underlying
* rcl function fail.
*/
RCLCPP_PUBLIC
const std::string &
bool
take_type_erased_response(void * response_out, rmw_request_id_t & request_header_out);
RCLCPP_PUBLIC
const char *
get_service_name() const;
RCLCPP_PUBLIC
const rcl_client_t *
std::shared_ptr<rcl_client_t>
get_client_handle();
RCLCPP_PUBLIC
std::shared_ptr<const rcl_client_t>
get_client_handle() const;
RCLCPP_PUBLIC
bool
service_is_ready() const;
template<typename RatioT = std::milli>
template<typename RepT = int64_t, typename RatioT = std::milli>
bool
wait_for_service(
std::chrono::duration<int64_t, RatioT> timeout = std::chrono::duration<int64_t, RatioT>(-1))
std::chrono::duration<RepT, RatioT> timeout = std::chrono::duration<RepT, RatioT>(-1))
{
return wait_for_service_nanoseconds(
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
@@ -87,8 +115,22 @@ public:
virtual void handle_response(
std::shared_ptr<rmw_request_id_t> request_header, std::shared_ptr<void> response) = 0;
/// Exchange the "in use by wait set" state for this client.
/**
* This is used to ensure this client is not used by multiple
* wait sets at the same time.
*
* \param[in] in_use_state the new state to exchange into the state, true
* indicates it is now in use by a wait set, and false is that it is no
* longer in use by a wait set.
* \returns the previous state.
*/
RCLCPP_PUBLIC
bool
exchange_in_use_by_wait_set_state(bool in_use_state);
protected:
RCLCPP_DISABLE_COPY(ClientBase);
RCLCPP_DISABLE_COPY(ClientBase)
RCLCPP_PUBLIC
bool
@@ -96,13 +138,19 @@ protected:
RCLCPP_PUBLIC
rcl_node_t *
get_rcl_node_handle();
RCLCPP_PUBLIC
const rcl_node_t *
get_rcl_node_handle() const;
std::weak_ptr<rclcpp::node::Node> node_;
rclcpp::node_interfaces::NodeGraphInterface::WeakPtr node_graph_;
std::shared_ptr<rcl_node_t> node_handle_;
std::shared_ptr<rclcpp::Context> context_;
rcl_client_t client_handle_ = rcl_get_zero_initialized_client();
std::string service_name_;
std::shared_ptr<rcl_client_t> client_handle_;
std::atomic<bool> in_use_by_wait_set_{false};
};
template<typename ServiceT>
@@ -121,47 +169,73 @@ public:
using SharedFuture = std::shared_future<SharedResponse>;
using SharedFutureWithRequest = std::shared_future<std::pair<SharedRequest, SharedResponse>>;
using CallbackType = std::function<void(SharedFuture)>;
using CallbackWithRequestType = std::function<void(SharedFutureWithRequest)>;
using CallbackType = std::function<void (SharedFuture)>;
using CallbackWithRequestType = std::function<void (SharedFutureWithRequest)>;
RCLCPP_SMART_PTR_DEFINITIONS(Client);
RCLCPP_SMART_PTR_DEFINITIONS(Client)
Client(
std::shared_ptr<rclcpp::node::Node> parent_node,
rclcpp::node_interfaces::NodeBaseInterface * node_base,
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
const std::string & service_name,
rcl_client_options_t & client_options)
: ClientBase(parent_node, service_name)
: ClientBase(node_base, node_graph)
{
using rosidl_generator_cpp::get_service_type_support_handle;
using rosidl_typesupport_cpp::get_service_type_support_handle;
auto service_type_support_handle =
get_service_type_support_handle<ServiceT>();
if (rcl_client_init(&client_handle_, this->get_rcl_node_handle(),
service_type_support_handle, service_name.c_str(), &client_options) != RCL_RET_OK)
{
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
throw std::runtime_error(
std::string("could not create client: ") +
rcl_get_error_string_safe());
// *INDENT-ON*
rcl_ret_t ret = rcl_client_init(
this->get_client_handle().get(),
this->get_rcl_node_handle(),
service_type_support_handle,
service_name.c_str(),
&client_options);
if (ret != RCL_RET_OK) {
if (ret == RCL_RET_SERVICE_NAME_INVALID) {
auto rcl_node_handle = this->get_rcl_node_handle();
// this will throw on any validation problem
rcl_reset_error();
expand_topic_or_service_name(
service_name,
rcl_node_get_name(rcl_node_handle),
rcl_node_get_namespace(rcl_node_handle),
true);
}
rclcpp::exceptions::throw_from_rcl_error(ret, "could not create client");
}
}
virtual ~Client()
{
if (rcl_client_fini(&client_handle_, this->get_rcl_node_handle()) != RCL_RET_OK) {
fprintf(stderr,
"Error in destruction of rmw client handle: %s\n", rmw_get_error_string_safe());
}
}
/// Take the next response for this client.
/**
* \sa ClientBase::take_type_erased_response().
*
* \param[out] response_out The reference to a Service Response into
* which the middleware will copy the response being taken.
* \param[out] request_header_out The request header to be filled by the
* middleware when taking, and which can be used to associte the response
* to a specific request.
* \returns true if the response was taken, otherwise false.
* \throws rclcpp::exceptions::RCLError based exceptions if the underlying
* rcl function fail.
*/
bool
take_response(typename ServiceT::Response & response_out, rmw_request_id_t & request_header_out)
{
return this->take_type_erased_response(&response_out, request_header_out);
}
std::shared_ptr<void>
create_response()
create_response() override
{
return std::shared_ptr<void>(new typename ServiceT::Response());
}
std::shared_ptr<rmw_request_id_t>
create_request_header()
create_request_header() override
{
// TODO(wjwwood): This should probably use rmw_request_id's allocator.
// (since it is a C type)
@@ -169,15 +243,18 @@ public:
}
void
handle_response(std::shared_ptr<rmw_request_id_t> request_header,
std::shared_ptr<void> response)
handle_response(
std::shared_ptr<rmw_request_id_t> request_header,
std::shared_ptr<void> response) override
{
std::lock_guard<std::mutex> lock(pending_requests_mutex_);
std::unique_lock<std::mutex> lock(pending_requests_mutex_);
auto typed_response = std::static_pointer_cast<typename ServiceT::Response>(response);
int64_t sequence_number = request_header->sequence_number;
// TODO(esteve) this should throw instead since it is not expected to happen in the first place
if (this->pending_requests_.count(sequence_number) == 0) {
fprintf(stderr, "Received invalid sequence number. Ignoring...\n");
RCUTILS_LOG_ERROR_NAMED(
"rclcpp",
"Received invalid sequence number. Ignoring...");
return;
}
auto tuple = this->pending_requests_[sequence_number];
@@ -185,6 +262,9 @@ public:
auto callback = std::get<1>(tuple);
auto future = std::get<2>(tuple);
this->pending_requests_.erase(sequence_number);
// Unlock here to allow the service to be called recursively from one of its callbacks.
lock.unlock();
call_promise->set_value(typed_response);
callback(future);
}
@@ -209,11 +289,9 @@ public:
{
std::lock_guard<std::mutex> lock(pending_requests_mutex_);
int64_t sequence_number;
if (RCL_RET_OK != rcl_send_request(get_client_handle(), request.get(), &sequence_number)) {
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
throw std::runtime_error(
std::string("failed to send request: ") + rcl_get_error_string_safe());
// *INDENT-ON*
rcl_ret_t ret = rcl_send_request(get_client_handle().get(), request.get(), &sequence_number);
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to send request");
}
SharedPromise call_promise = std::make_shared<Promise>();
@@ -250,13 +328,12 @@ public:
}
private:
RCLCPP_DISABLE_COPY(Client);
RCLCPP_DISABLE_COPY(Client)
std::map<int64_t, std::tuple<SharedPromise, CallbackType, SharedFuture>> pending_requests_;
std::mutex pending_requests_mutex_;
};
} // namespace client
} // namespace rclcpp
#endif // RCLCPP__CLIENT_HPP_

View File

@@ -0,0 +1,149 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__CLOCK_HPP_
#define RCLCPP__CLOCK_HPP_
#include <functional>
#include <memory>
#include <mutex>
#include "rclcpp/macros.hpp"
#include "rclcpp/time.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rcl/time.h"
#include "rcutils/time.h"
#include "rcutils/types/rcutils_ret.h"
namespace rclcpp
{
class TimeSource;
class JumpHandler
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(JumpHandler)
using pre_callback_t = std::function<void ()>;
using post_callback_t = std::function<void (const rcl_time_jump_t &)>;
JumpHandler(
pre_callback_t pre_callback,
post_callback_t post_callback,
const rcl_jump_threshold_t & threshold);
pre_callback_t pre_callback;
post_callback_t post_callback;
rcl_jump_threshold_t notice_threshold;
};
class Clock
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(Clock)
/// Default c'tor
/**
* Initializes the clock instance with the given clock_type.
*
* \param clock_type type of the clock.
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
*/
RCLCPP_PUBLIC
explicit Clock(rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
RCLCPP_PUBLIC
~Clock();
/**
* Returns current time from the time source specified by clock_type.
*
* \return current time.
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
*/
RCLCPP_PUBLIC
Time
now();
/**
* Returns the clock of the type `RCL_ROS_TIME` is active.
*
* \return true if the clock is active
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw if
* the current clock does not have the clock_type `RCL_ROS_TIME`.
*/
RCLCPP_PUBLIC
bool
ros_time_is_active();
RCLCPP_PUBLIC
rcl_clock_t *
get_clock_handle() noexcept;
RCLCPP_PUBLIC
rcl_clock_type_t
get_clock_type() const noexcept;
RCLCPP_PUBLIC
std::mutex &
get_clock_mutex() noexcept;
// Add a callback to invoke if the jump threshold is exceeded.
/**
* These callback functions must remain valid as long as the
* returned shared pointer is valid.
*
* Function will register callbacks to the callback queue. On time jump all
* callbacks will be executed whose threshold is greater then the time jump;
* The logic will first call selected pre_callbacks and then all selected
* post_callbacks.
*
* 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
* then the threshold.
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
* \throws std::bad_alloc if the allocation of the JumpHandler fails.
* \warning the instance of the clock must remain valid as long as any created
* JumpHandler.
*/
RCLCPP_PUBLIC
JumpHandler::SharedPtr
create_jump_callback(
JumpHandler::pre_callback_t pre_callback,
JumpHandler::post_callback_t post_callback,
const rcl_jump_threshold_t & threshold);
private:
// Invoke time jump callback
RCLCPP_PUBLIC
static void
on_time_jump(
const struct rcl_time_jump_t * time_jump,
bool before_jump,
void * user_data);
/// Private internal storage
class Impl;
std::shared_ptr<Impl> impl_;
};
} // namespace rclcpp
#endif // RCLCPP__CLOCK_HPP_

View File

@@ -15,50 +15,303 @@
#ifndef RCLCPP__CONTEXT_HPP_
#define RCLCPP__CONTEXT_HPP_
#include <iostream>
#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
#include <utility>
#include <vector>
#include "rcl/context.h"
#include "rcl/guard_condition.h"
#include "rcl/wait.h"
#include "rclcpp/init_options.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rmw/rmw.h"
namespace rclcpp
{
namespace context
{
class Context
/// Thrown when init is called on an already initialized context.
class ContextAlreadyInitialized : public std::runtime_error
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(Context);
ContextAlreadyInitialized()
: std::runtime_error("context is already initialized") {}
};
/// Context which encapsulates shared state between nodes and other similar entities.
/**
* A context also represents the lifecycle between init and shutdown of rclcpp.
* It is often used in conjunction with rclcpp::init, or rclcpp::init_local,
* and rclcpp::shutdown.
*/
class Context : public std::enable_shared_from_this<Context>
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(Context)
/// Default constructor, after which the Context is still not "initialized".
/**
* Every context which is constructed is added to a global vector of contexts,
* which is used by the signal handler to conditionally shutdown each context
* on SIGINT.
* See the shutdown_on_sigint option in the InitOptions class.
*/
RCLCPP_PUBLIC
Context();
RCLCPP_PUBLIC
virtual
~Context();
/// Initialize the context, and the underlying elements like the rcl context.
/**
* This method must be called before passing this context to things like the
* constructor of Node.
* It must also be called before trying to shutdown the context.
*
* Note that this function does not setup any signal handlers, so if you want
* it to be shutdown by the signal handler, then you need to either install
* them manually with rclcpp::install_signal_handers() or use rclcpp::init().
* In addition to installing the signal handlers, the shutdown_on_sigint
* of the InitOptions needs to be `true` for this context to be shutdown by
* the signal handler, otherwise it will be passed over.
*
* After calling this method, shutdown() can be called to invalidate the
* context for derived entities, e.g. nodes, guard conditions, etc.
* However, the underlying rcl context is not finalized until this Context's
* destructor is called or this function is called again.
* Allowing this class to go out of scope and get destructed or calling this
* function a second time while derived entities are still using the context
* is undefined behavior and should be avoided.
* It's a good idea to not reuse context objects and instead create a new one
* each time you need to shutdown and init again.
* This allows derived entities to hold on to shard pointers to the first
* context object until they are done.
*
* This function is thread-safe.
*
* \param[in] argc number of arguments
* \param[in] argv argument array which may contain arguments intended for ROS
* \param[in] init_options initialization options for rclcpp and underlying layers
* \throw ContextAlreadyInitialized if called if init is called more than once
*/
RCLCPP_PUBLIC
virtual
void
init(
int argc,
char const * const argv[],
const rclcpp::InitOptions & init_options = rclcpp::InitOptions());
/// Return true if the context is valid, otherwise false.
/**
* The context is valid if it has been initialized but not shutdown.
*
* This function is thread-safe.
* This function is lock free so long as pointers and uint64_t atomics are
* lock free.
*
* \return true if valid, otherwise false
*/
RCLCPP_PUBLIC
bool
is_valid() const;
/// Return the init options used during init.
RCLCPP_PUBLIC
const rclcpp::InitOptions &
get_init_options() const;
/// Return a copy of the init options used during init.
RCLCPP_PUBLIC
rclcpp::InitOptions
get_init_options();
/// Return the shutdown reason, or empty string if not shutdown.
/**
* This function is thread-safe.
*/
RCLCPP_PUBLIC
std::string
shutdown_reason();
/// Shutdown the context, making it uninitialized and therefore invalid for derived entities.
/**
* Several things happen when the context is shutdown, in this order:
*
* - acquires a lock to prevent race conditions with init, on_shutdown, etc.
* - if the context is not initialized, return false
* - rcl_shutdown() is called on the internal rcl_context_t instance
* - the shutdown reason is set
* - each on_shutdown callback is called, in the order that they were added
* - interrupt blocking sleep_for() calls, so they return early due to shutdown
* - interrupt blocking executors and wait sets
*
* The underlying rcl context is not finalized by this function.
*
* This function is thread-safe.
*
* \param[in] reason the description of why shutdown happened
* \return true if shutdown was successful, false if context was already shutdown
* \throw various exceptions derived from rclcpp::exceptions::RCLError, if rcl_shutdown fails
*/
RCLCPP_PUBLIC
virtual
bool
shutdown(const std::string & reason);
using OnShutdownCallback = std::function<void ()>;
/// Add a on_shutdown callback to be called when shutdown is called for this context.
/**
* These callbacks will be called in the order they are added as the second
* to last step in shutdown().
*
* When shutdown occurs due to the signal handler, these callbacks are run
* asynchronoulsy in the dedicated singal handling thread.
*
* Also, shutdown() may be called from the destructor of this function.
* Therefore, it is not safe to throw exceptions from these callbacks.
* Instead, log errors or use some other mechanism to indicate an error has
* occurred.
*
* On shutdown callbacks may be registered before init and after shutdown,
* and persist on repeated init's.
*
* \param[in] callback the on shutdown callback to be registered
* \return the callback passed, for convenience when storing a passed lambda
*/
RCLCPP_PUBLIC
virtual
OnShutdownCallback
on_shutdown(OnShutdownCallback callback);
/// Return the shutdown callbacks as const.
/**
* Using the returned reference is not thread-safe with calls that modify
* the list of "on shutdown" callbacks, i.e. on_shutdown().
*/
RCLCPP_PUBLIC
const std::vector<OnShutdownCallback> &
get_on_shutdown_callbacks() const;
/// Return the shutdown callbacks.
/**
* Using the returned reference is not thread-safe with calls that modify
* the list of "on shutdown" callbacks, i.e. on_shutdown().
*/
RCLCPP_PUBLIC
std::vector<OnShutdownCallback> &
get_on_shutdown_callbacks();
/// Return the internal rcl context.
RCLCPP_PUBLIC
std::shared_ptr<rcl_context_t>
get_rcl_context();
/// Sleep for a given period of time or until shutdown() is called.
/**
* This function can be interrupted early if:
*
* - this context is shutdown()
* - this context is destructed (resulting in shutdown)
* - this context has shutdown_on_sigint=true and SIGINT occurs (resulting in shutdown)
* - interrupt_all_sleep_for() is called
*
* \param[in] nanoseconds A std::chrono::duration representing how long to sleep for.
* \return true if the condition variable did not timeout, i.e. you were interrupted.
*/
RCLCPP_PUBLIC
bool
sleep_for(const std::chrono::nanoseconds & nanoseconds);
/// Interrupt any blocking sleep_for calls, causing them to return immediately and return true.
RCLCPP_PUBLIC
virtual
void
interrupt_all_sleep_for();
/// Get a handle to the guard condition which is triggered when interrupted.
/**
* This guard condition is triggered any time interrupt_all_wait_sets() is
* called, which may be called by the user, or shutdown().
* And in turn, shutdown() may be called by the user, the destructor of this
* context, or the signal handler if installed and shutdown_on_sigint is true
* for this context.
*
* The first time that this function is called for a given wait set a new guard
* condition will be created and returned; thereafter the same guard condition
* will be returned for the same wait set.
* This mechanism is designed to ensure that the same guard condition is not
* reused across wait sets (e.g., when using multiple executors in the same
* process).
* This method will throw an exception if initialization of the guard
* condition fails.
*
* The returned guard condition needs to be released with the
* release_interrupt_guard_condition() method in order to reclaim resources.
*
* \param[in] wait_set Pointer to the rcl_wait_set_t that will be using the
* resulting guard condition.
* \return Pointer to the guard condition.
*/
RCLCPP_PUBLIC
rcl_guard_condition_t *
get_interrupt_guard_condition(rcl_wait_set_t * wait_set);
/// Release the previously allocated guard condition which is triggered when interrupted.
/**
* If you previously called get_interrupt_guard_condition() for a given wait
* set to get a interrupt guard condition, then you should call
* release_interrupt_guard_condition() when you're done, to free that
* condition.
* Will throw an exception if get_interrupt_guard_condition() wasn't
* previously called for the given wait set.
*
* After calling this, the pointer returned by get_interrupt_guard_condition()
* for the given wait_set is invalid.
*
* \param[in] wait_set Pointer to the rcl_wait_set_t that was using the
* resulting guard condition.
*/
RCLCPP_PUBLIC
void
release_interrupt_guard_condition(rcl_wait_set_t * wait_set);
/// Nothrow version of release_interrupt_guard_condition(), logs to RCLCPP_ERROR instead.
RCLCPP_PUBLIC
void
release_interrupt_guard_condition(rcl_wait_set_t * wait_set, const std::nothrow_t &) noexcept;
/// Interrupt any blocking executors, or wait sets associated with this context.
RCLCPP_PUBLIC
virtual
void
interrupt_all_wait_sets();
/// Return a singleton instance for the SubContext type, constructing one if necessary.
template<typename SubContext, typename ... Args>
std::shared_ptr<SubContext>
get_sub_context(Args && ... args)
{
std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::recursive_mutex> lock(sub_contexts_mutex_);
std::type_index type_i(typeid(SubContext));
std::shared_ptr<SubContext> sub_context;
auto it = sub_contexts_.find(type_i);
if (it == sub_contexts_.end()) {
// It doesn't exist yet, make it
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
sub_context = std::shared_ptr<SubContext>(
new SubContext(std::forward<Args>(args) ...),
[] (SubContext * sub_context_ptr) {
[](SubContext * sub_context_ptr) {
delete sub_context_ptr;
});
// *INDENT-ON*
sub_contexts_[type_i] = sub_context;
} else {
// It exists, get it out and cast it.
@@ -67,14 +320,51 @@ public:
return sub_context;
}
protected:
// Called by constructor and destructor to clean up by finalizing the
// shutdown rcl context and preparing for a new init cycle.
RCLCPP_PUBLIC
virtual
void
clean_up();
private:
RCLCPP_DISABLE_COPY(Context);
RCLCPP_DISABLE_COPY(Context)
// This mutex is recursive so that the destructor can ensure atomicity
// between is_initialized and shutdown.
std::recursive_mutex init_mutex_;
std::shared_ptr<rcl_context_t> rcl_context_;
rclcpp::InitOptions init_options_;
std::string shutdown_reason_;
std::unordered_map<std::type_index, std::shared_ptr<void>> sub_contexts_;
std::mutex mutex_;
// This mutex is recursive so that the constructor of a sub context may
// attempt to acquire another sub context.
std::recursive_mutex sub_contexts_mutex_;
std::vector<OnShutdownCallback> on_shutdown_callbacks_;
std::mutex on_shutdown_callbacks_mutex_;
/// Condition variable for timed sleep (see sleep_for).
std::condition_variable interrupt_condition_variable_;
/// Mutex for protecting the global condition variable.
std::mutex interrupt_mutex_;
/// Mutex to protect sigint_guard_cond_handles_.
std::mutex interrupt_guard_cond_handles_mutex_;
/// Guard conditions for interrupting of associated wait sets on interrupt_all_wait_sets().
std::unordered_map<rcl_wait_set_t *, rcl_guard_condition_t> interrupt_guard_cond_handles_;
};
} // namespace context
/// Return a copy of the list of context shared pointers.
/**
* This function is thread-safe.
*/
RCLCPP_PUBLIC
std::vector<Context::SharedPtr>
get_contexts();
} // namespace rclcpp
#endif // RCLCPP__CONTEXT_HPP_

View File

@@ -22,13 +22,11 @@ namespace rclcpp
{
namespace contexts
{
namespace default_context
{
class DefaultContext : public rclcpp::context::Context
class DefaultContext : public rclcpp::Context
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(DefaultContext);
RCLCPP_SMART_PTR_DEFINITIONS(DefaultContext)
RCLCPP_PUBLIC
DefaultContext();
@@ -38,6 +36,21 @@ RCLCPP_PUBLIC
DefaultContext::SharedPtr
get_global_default_context();
namespace default_context
{
using DefaultContext
[[deprecated("use rclcpp::contexts::DefaultContext instead")]] = DefaultContext;
[[deprecated("use rclcpp::contexts::get_global_default_context() instead")]]
RCLCPP_PUBLIC
inline
DefaultContext::SharedPtr
get_global_default_context()
{
return rclcpp::contexts::get_global_default_context();
}
} // namespace default_context
} // namespace contexts
} // namespace rclcpp

View File

@@ -0,0 +1,56 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__CREATE_CLIENT_HPP_
#define RCLCPP__CREATE_CLIENT_HPP_
#include <memory>
#include <string>
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_services_interface.hpp"
#include "rmw/rmw.h"
namespace rclcpp
{
/// Create a service client with a given type.
/// \internal
template<typename ServiceT>
typename rclcpp::Client<ServiceT>::SharedPtr
create_client(
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
std::shared_ptr<node_interfaces::NodeGraphInterface> node_graph,
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
const std::string & service_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::CallbackGroup::SharedPtr group)
{
rcl_client_options_t options = rcl_client_get_default_options();
options.qos = qos_profile;
auto cli = rclcpp::Client<ServiceT>::make_shared(
node_base.get(),
node_graph,
service_name,
options);
auto cli_base_ptr = std::dynamic_pointer_cast<rclcpp::ClientBase>(cli);
node_services->add_client(cli_base_ptr, group);
return cli;
}
} // namespace rclcpp
#endif // RCLCPP__CREATE_CLIENT_HPP_

View File

@@ -0,0 +1,71 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__CREATE_PUBLISHER_HPP_
#define RCLCPP__CREATE_PUBLISHER_HPP_
#include <memory>
#include <string>
#include "rclcpp/node_interfaces/get_node_topics_interface.hpp"
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
#include "rclcpp/node_options.hpp"
#include "rclcpp/publisher_factory.hpp"
#include "rclcpp/publisher_options.hpp"
#include "rclcpp/qos.hpp"
#include "rmw/qos_profiles.h"
namespace rclcpp
{
/// Create and return a publisher of the given MessageT type.
/**
* The NodeT type only needs to have a method called get_node_topics_interface()
* which returns a shared_ptr to a NodeTopicsInterface.
*/
template<
typename MessageT,
typename AllocatorT = std::allocator<void>,
typename PublisherT = rclcpp::Publisher<MessageT, AllocatorT>,
typename NodeT>
std::shared_ptr<PublisherT>
create_publisher(
NodeT & node,
const std::string & topic_name,
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.
auto pub = node_topics->create_publisher(
topic_name,
rclcpp::create_publisher_factory<MessageT, AllocatorT, PublisherT>(options),
qos
);
// Add the publisher to the node topics interface.
node_topics->add_publisher(pub, options.callback_group);
return std::dynamic_pointer_cast<PublisherT>(pub);
}
} // namespace rclcpp
#endif // RCLCPP__CREATE_PUBLISHER_HPP_

View File

@@ -0,0 +1,58 @@
// 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.
#ifndef RCLCPP__CREATE_SERVICE_HPP_
#define RCLCPP__CREATE_SERVICE_HPP_
#include <memory>
#include <string>
#include <utility>
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_services_interface.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rmw/rmw.h"
namespace rclcpp
{
/// Create a service with a given type.
/// \internal
template<typename ServiceT, typename CallbackT>
typename rclcpp::Service<ServiceT>::SharedPtr
create_service(
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
const std::string & service_name,
CallbackT && callback,
const rmw_qos_profile_t & qos_profile,
rclcpp::CallbackGroup::SharedPtr group)
{
rclcpp::AnyServiceCallback<ServiceT> any_service_callback;
any_service_callback.set(std::forward<CallbackT>(callback));
rcl_service_options_t service_options = rcl_service_get_default_options();
service_options.qos = qos_profile;
auto serv = Service<ServiceT>::make_shared(
node_base->get_shared_rcl_node_handle(),
service_name, any_service_callback, service_options);
auto serv_base_ptr = std::dynamic_pointer_cast<ServiceBase>(serv);
node_services->add_service(serv_base_ptr, group);
return serv;
}
} // namespace rclcpp
#endif // RCLCPP__CREATE_SERVICE_HPP_

View File

@@ -0,0 +1,81 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__CREATE_SUBSCRIPTION_HPP_
#define RCLCPP__CREATE_SUBSCRIPTION_HPP_
#include <memory>
#include <string>
#include <utility>
#include "rclcpp/node_interfaces/get_node_topics_interface.hpp"
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
#include "rclcpp/subscription_factory.hpp"
#include "rclcpp/subscription_options.hpp"
#include "rclcpp/qos.hpp"
#include "rmw/qos_profiles.h"
namespace rclcpp
{
/// Create and return a subscription of the given MessageT type.
/**
* The NodeT type only needs to have a method called get_node_topics_interface()
* which returns a shared_ptr to a NodeTopicsInterface, or be a
* NodeTopicsInterface pointer itself.
*/
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 NodeT>
typename std::shared_ptr<SubscriptionT>
create_subscription(
NodeT && node,
const std::string & topic_name,
const rclcpp::QoS & qos,
CallbackT && callback,
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
),
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat = (
MessageMemoryStrategyT::create_default()
)
)
{
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
);
auto sub = node_topics->create_subscription(topic_name, factory, qos);
node_topics->add_subscription(sub, options.callback_group);
return std::dynamic_pointer_cast<SubscriptionT>(sub);
}
} // namespace rclcpp
#endif // RCLCPP__CREATE_SUBSCRIPTION_HPP_

View File

@@ -0,0 +1,73 @@
// 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_TIMER_HPP_
#define RCLCPP__CREATE_TIMER_HPP_
#include <memory>
#include <string>
#include <utility>
#include "rclcpp/duration.hpp"
#include "rclcpp/node_interfaces/get_node_base_interface.hpp"
#include "rclcpp/node_interfaces/get_node_timers_interface.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
namespace rclcpp
{
/// Create a timer with a given clock
/// \internal
template<typename CallbackT>
typename rclcpp::TimerBase::SharedPtr
create_timer(
node_interfaces::NodeBaseInterface * node_base,
node_interfaces::NodeTimersInterface * node_timers,
rclcpp::Clock::SharedPtr clock,
rclcpp::Duration period,
CallbackT && callback,
rclcpp::CallbackGroup::SharedPtr group = nullptr)
{
auto timer = rclcpp::GenericTimer<CallbackT>::make_shared(
clock,
period.to_chrono<std::chrono::nanoseconds>(),
std::forward<CallbackT>(callback),
node_base->get_context());
node_timers->add_timer(timer, group);
return timer;
}
/// Create a timer with a given clock
template<typename NodeT, typename CallbackT>
typename rclcpp::TimerBase::SharedPtr
create_timer(
NodeT node,
rclcpp::Clock::SharedPtr clock,
rclcpp::Duration period,
CallbackT && callback,
rclcpp::CallbackGroup::SharedPtr group = nullptr)
{
return create_timer(
rclcpp::node_interfaces::get_node_base_interface(node),
rclcpp::node_interfaces::get_node_timers_interface(node),
clock,
period,
std::forward<CallbackT>(callback),
group);
}
} // namespace rclcpp
#endif // RCLCPP__CREATE_TIMER_HPP_

View File

@@ -0,0 +1,3 @@
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

@@ -0,0 +1,54 @@
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__DETAIL__RESOLVE_ENABLE_TOPIC_STATISTICS_HPP_
#define RCLCPP__DETAIL__RESOLVE_ENABLE_TOPIC_STATISTICS_HPP_
#include <stdexcept>
#include "rclcpp/topic_statistics_state.hpp"
namespace rclcpp
{
namespace detail
{
/// Return whether or not topic statistics is enabled, resolving "NodeDefault" if needed.
template<typename OptionsT, typename NodeBaseT>
bool
resolve_enable_topic_statistics(const OptionsT & options, const NodeBaseT & node_base)
{
bool topic_stats_enabled;
switch (options.topic_stats_options.state) {
case TopicStatisticsState::Enable:
topic_stats_enabled = true;
break;
case TopicStatisticsState::Disable:
topic_stats_enabled = false;
break;
case TopicStatisticsState::NodeDefault:
topic_stats_enabled = node_base.get_enable_topic_statistics_default();
break;
default:
throw std::runtime_error("Unrecognized EnableTopicStatistics value");
break;
}
return topic_stats_enabled;
}
} // namespace detail
} // namespace rclcpp
#endif // RCLCPP__DETAIL__RESOLVE_ENABLE_TOPIC_STATISTICS_HPP_

View File

@@ -0,0 +1,54 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__DETAIL__RESOLVE_INTRA_PROCESS_BUFFER_TYPE_HPP_
#define RCLCPP__DETAIL__RESOLVE_INTRA_PROCESS_BUFFER_TYPE_HPP_
#include <stdexcept>
#include "rclcpp/any_subscription_callback.hpp"
#include "rclcpp/intra_process_buffer_type.hpp"
namespace rclcpp
{
namespace detail
{
/// Return the buffer type, resolving the "CallbackDefault" type to an actual type if needed.
template<typename CallbackMessageT, typename AllocatorT>
rclcpp::IntraProcessBufferType
resolve_intra_process_buffer_type(
const rclcpp::IntraProcessBufferType buffer_type,
const rclcpp::AnySubscriptionCallback<CallbackMessageT, AllocatorT> & any_subscription_callback)
{
rclcpp::IntraProcessBufferType resolved_buffer_type = buffer_type;
// If the user has not specified a type for the intra-process buffer, use the callback's type.
if (resolved_buffer_type == IntraProcessBufferType::CallbackDefault) {
if (any_subscription_callback.use_take_shared_method()) {
resolved_buffer_type = IntraProcessBufferType::SharedPtr;
} else {
resolved_buffer_type = IntraProcessBufferType::UniquePtr;
}
}
return resolved_buffer_type;
}
} // namespace detail
} // namespace rclcpp
#endif // RCLCPP__DETAIL__RESOLVE_INTRA_PROCESS_BUFFER_TYPE_HPP_

View File

@@ -0,0 +1,56 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__DETAIL__RESOLVE_USE_INTRA_PROCESS_HPP_
#define RCLCPP__DETAIL__RESOLVE_USE_INTRA_PROCESS_HPP_
#include <stdexcept>
#include "rclcpp/intra_process_setting.hpp"
namespace rclcpp
{
namespace detail
{
/// Return whether or not intra process is enabled, resolving "NodeDefault" if needed.
template<typename OptionsT, typename NodeBaseT>
bool
resolve_use_intra_process(const OptionsT & options, const NodeBaseT & node_base)
{
bool use_intra_process;
switch (options.use_intra_process_comm) {
case IntraProcessSetting::Enable:
use_intra_process = true;
break;
case IntraProcessSetting::Disable:
use_intra_process = false;
break;
case IntraProcessSetting::NodeDefault:
use_intra_process = node_base.get_use_intra_process_default();
break;
default:
throw std::runtime_error("Unrecognized IntraProcessSetting value");
break;
}
return use_intra_process;
}
} // namespace detail
} // namespace rclcpp
#endif // RCLCPP__DETAIL__RESOLVE_USE_INTRA_PROCESS_HPP_

View File

@@ -0,0 +1,51 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PAYLOAD_HPP_
#define RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PAYLOAD_HPP_
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace detail
{
/// Mechanism for passing rmw implementation specific settings through the ROS interfaces.
class RCLCPP_PUBLIC RMWImplementationSpecificPayload
{
public:
virtual
~RMWImplementationSpecificPayload() = default;
/// Return false if this class has not been customized, otherwise true.
/**
* It does this based on the value of the rmw implementation identifier that
* this class reports, and so it is important for a specialization of this
* class to override the get_rmw_implementation_identifier() method to return
* something other than nullptr.
*/
bool
has_been_customized() const;
/// Derrived classes should override this and return the identifier of its rmw implementation.
virtual
const char *
get_implementation_identifier() const;
};
} // namespace detail
} // namespace rclcpp
#endif // RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PAYLOAD_HPP_

View File

@@ -0,0 +1,52 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PUBLISHER_PAYLOAD_HPP_
#define RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PUBLISHER_PAYLOAD_HPP_
#include "rcl/publisher.h"
#include "rclcpp/detail/rmw_implementation_specific_payload.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace detail
{
class RCLCPP_PUBLIC RMWImplementationSpecificPublisherPayload
: public RMWImplementationSpecificPayload
{
public:
~RMWImplementationSpecificPublisherPayload() override = default;
/// Opportunity for a derived class to inject information into the rcl options.
/**
* This is called after the rcl_publisher_options_t has been prepared by
* rclcpp, but before rcl_publisher_init() is called.
*
* The passed option is the rmw_publisher_options field of the
* rcl_publisher_options_t that will be passed to rcl_publisher_init().
*
* By default the options are unmodified.
*/
virtual
void
modify_rmw_publisher_options(rmw_publisher_options_t & rmw_publisher_options) const;
};
} // namespace detail
} // namespace rclcpp
#endif // RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_PUBLISHER_PAYLOAD_HPP_

View File

@@ -0,0 +1,53 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_SUBSCRIPTION_PAYLOAD_HPP_
#define RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_SUBSCRIPTION_PAYLOAD_HPP_
#include "rcl/subscription.h"
#include "rclcpp/detail/rmw_implementation_specific_payload.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace detail
{
/// Subscription payload that may be rmw implementation specific.
class RCLCPP_PUBLIC RMWImplementationSpecificSubscriptionPayload
: public RMWImplementationSpecificPayload
{
public:
~RMWImplementationSpecificSubscriptionPayload() override = default;
/// Opportunity for a derived class to inject information into the rcl options.
/**
* This is called after the rcl_subscription_options_t has been prepared by
* rclcpp, but before rcl_subscription_init() is called.
*
* The passed option is the rmw_subscription_options field of the
* rcl_subscription_options_t that will be passed to rcl_subscription_init().
*
* By default the options are unmodified.
*/
virtual
void
modify_rmw_subscription_options(rmw_subscription_options_t & rmw_subscription_options) const;
};
} // namespace detail
} // namespace rclcpp
#endif // RCLCPP__DETAIL__RMW_IMPLEMENTATION_SPECIFIC_SUBSCRIPTION_PAYLOAD_HPP_

View File

@@ -0,0 +1,40 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__DETAIL__UTILITIES_HPP_
#define RCLCPP__DETAIL__UTILITIES_HPP_
#include "rclcpp/detail/utilities.hpp"
#include <string>
#include <vector>
#include "rcl/allocator.h"
#include "rcl/arguments.h"
namespace rclcpp
{
namespace detail
{
std::vector<std::string>
get_unparsed_ros_arguments(
int argc, char const * const argv[],
rcl_arguments_t * arguments,
rcl_allocator_t allocator);
} // namespace detail
} // namespace rclcpp
#endif // RCLCPP__DETAIL__UTILITIES_HPP_

View File

@@ -0,0 +1,119 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__DURATION_HPP_
#define RCLCPP__DURATION_HPP_
#include <chrono>
#include "builtin_interfaces/msg/duration.hpp"
#include "rcl/time.h"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
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
Duration(const std::chrono::duration<Rep, Period> & duration) // NOLINT(runtime/explicit)
: Duration(std::chrono::duration_cast<std::chrono::nanoseconds>(duration))
{}
// cppcheck-suppress noExplicitConstructor
Duration(const builtin_interfaces::msg::Duration & duration_msg); // NOLINT(runtime/explicit)
explicit Duration(const rcl_duration_t & duration);
Duration(const Duration & rhs);
virtual ~Duration() = default;
operator builtin_interfaces::msg::Duration() const;
// cppcheck-suppress operatorEq // this is a false positive from cppcheck
Duration &
operator=(const Duration & rhs);
Duration &
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;
bool
operator>=(const rclcpp::Duration & rhs) const;
bool
operator>(const rclcpp::Duration & rhs) const;
Duration
operator+(const rclcpp::Duration & rhs) const;
Duration
operator-(const rclcpp::Duration & rhs) const;
static
Duration
max();
Duration
operator*(double scale) const;
rcl_duration_value_t
nanoseconds() const;
/// \return the duration in seconds as a floating point number.
/// \warning Depending on sizeof(double) there could be significant precision loss.
/// When an exact time is required use nanoseconds() instead.
double
seconds() const;
// Create a duration object from a floating point number representing seconds
static Duration
from_seconds(double seconds);
template<class DurationT>
DurationT
to_chrono() const
{
return std::chrono::duration_cast<DurationT>(std::chrono::nanoseconds(this->nanoseconds()));
}
rmw_time_t
to_rmw_time() const;
private:
rcl_duration_t rcl_duration_;
};
} // namespace rclcpp
#endif // RCLCPP__DURATION_HPP_

View File

@@ -23,13 +23,11 @@
namespace rclcpp
{
namespace event
{
class Event
{
public:
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(Event);
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(Event)
RCLCPP_PUBLIC
Event();
@@ -47,12 +45,11 @@ public:
check_and_clear();
private:
RCLCPP_DISABLE_COPY(Event);
RCLCPP_DISABLE_COPY(Event)
std::atomic_bool state_;
};
} // namespace event
} // namespace rclcpp
#endif // RCLCPP__EVENT_HPP_

View File

@@ -15,87 +15,6 @@
#ifndef RCLCPP__EXCEPTIONS_HPP_
#define RCLCPP__EXCEPTIONS_HPP_
#include <stdexcept>
#include <string>
#include "rcl/error_handling.h"
#include "rcl/types.h"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace exceptions
{
/// Thrown when a method is trying to use a node, but it is invalid.
class InvalidNodeError : public std::runtime_error
{
public:
InvalidNodeError()
: std::runtime_error("node is invalid") {}
};
/// Throw a C++ std::exception which was created based on an rcl error.
/*
* \param ret the return code for the current error state
* \param prefix string to prefix to the error if applicable (not all errors have custom messages)
* \param reset_error if true rcl_reset_error() is called before returning
* \throws std::invalid_argument if ret is RCL_RET_OK
* \throws std::runtime_error if the rcl_get_error_state returns 0
* \throws RCLErrorBase some child class exception based on ret
*/
RCLCPP_PUBLIC
void
throw_from_rcl_error(rcl_ret_t ret, const std::string & prefix = "", bool reset_error = true);
class RCLErrorBase
{
public:
RCLCPP_PUBLIC
RCLErrorBase(rcl_ret_t ret, const rcl_error_state_t * error_state);
virtual ~RCLErrorBase() {}
rcl_ret_t ret;
std::string message;
std::string file;
size_t line;
std::string formatted_message;
};
/// Created when the return code does not match one of the other specialized exceptions.
class RCLError : public RCLErrorBase, public std::runtime_error
{
public:
RCLCPP_PUBLIC
RCLError(rcl_ret_t ret, const rcl_error_state_t * error_state, const std::string & prefix);
RCLCPP_PUBLIC
RCLError(const RCLErrorBase & base_exc, const std::string & prefix);
};
/// Created when the ret is RCL_RET_BAD_ALLOC.
class RCLBadAlloc : public RCLErrorBase, public std::bad_alloc
{
public:
RCLCPP_PUBLIC
RCLBadAlloc(rcl_ret_t ret, const rcl_error_state_t * error_state);
RCLCPP_PUBLIC
explicit RCLBadAlloc(const RCLErrorBase & base_exc);
};
/// Created when the ret is RCL_RET_INVALID_ARGUMENT.
class RCLInvalidArgument : public RCLErrorBase, public std::invalid_argument
{
public:
RCLCPP_PUBLIC
RCLInvalidArgument(
rcl_ret_t ret,
const rcl_error_state_t * error_state,
const std::string & prefix);
RCLCPP_PUBLIC
RCLInvalidArgument(const RCLErrorBase & base_exc, const std::string & prefix);
};
} // namespace exceptions
} // namespace rclcpp
#include "rclcpp/exceptions/exceptions.hpp"
#endif // RCLCPP__EXCEPTIONS_HPP_

View File

@@ -0,0 +1,279 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXCEPTIONS__EXCEPTIONS_HPP_
#define RCLCPP__EXCEPTIONS__EXCEPTIONS_HPP_
#include <stdexcept>
#include <string>
#include <vector>
#include "rcl/error_handling.h"
#include "rcl/types.h"
#include "rclcpp/visibility_control.hpp"
#include "rcpputils/join.hpp"
namespace rclcpp
{
namespace exceptions
{
/// Thrown when a method is trying to use a node, but it is invalid.
class InvalidNodeError : public std::runtime_error
{
public:
InvalidNodeError()
: std::runtime_error("node is invalid") {}
};
/// Thrown when a any kind of name (node, namespace, topic, etc.) is invalid.
class NameValidationError : public std::invalid_argument
{
public:
NameValidationError(
const char * name_type_,
const char * name_,
const char * error_msg_,
size_t invalid_index_)
: std::invalid_argument(format_error(name_type_, name_, error_msg_, invalid_index_)),
name_type(name_type_), name(name_), error_msg(error_msg_), invalid_index(invalid_index_)
{}
static std::string
format_error(
const char * name_type,
const char * name,
const char * error_msg,
size_t invalid_index);
const std::string name_type;
const std::string name;
const std::string error_msg;
const size_t invalid_index;
};
/// Thrown when a node name is invalid.
class InvalidNodeNameError : public NameValidationError
{
public:
InvalidNodeNameError(const char * node_name, const char * error_msg, size_t invalid_index)
: NameValidationError("node name", node_name, error_msg, invalid_index)
{}
};
/// Thrown when a node namespace is invalid.
class InvalidNamespaceError : public NameValidationError
{
public:
InvalidNamespaceError(const char * namespace_, const char * error_msg, size_t invalid_index)
: NameValidationError("namespace", namespace_, error_msg, invalid_index)
{}
};
/// Thrown when a topic name is invalid.
class InvalidTopicNameError : public NameValidationError
{
public:
InvalidTopicNameError(const char * namespace_, const char * error_msg, size_t invalid_index)
: NameValidationError("topic name", namespace_, error_msg, invalid_index)
{}
};
/// Thrown when a service name is invalid.
class InvalidServiceNameError : public NameValidationError
{
public:
InvalidServiceNameError(const char * namespace_, const char * error_msg, size_t invalid_index)
: NameValidationError("service name", namespace_, error_msg, invalid_index)
{}
};
/// Throw a C++ std::exception which was created based on an rcl error.
/**
* Passing nullptr for reset_error is safe and will avoid calling any function
* to reset the error.
*
* \param ret the return code for the current error state
* \param prefix string to prefix to the error if applicable (not all errors have custom messages)
* \param error_state error state to create exception from, if nullptr rcl_get_error_state is used
* \param reset_error function to be called before throwing which whill clear the error state
* \throws std::invalid_argument if ret is RCL_RET_OK
* \throws std::runtime_error if the rcl_get_error_state returns 0
* \throws RCLErrorBase some child class exception based on ret
*/
/* *INDENT-OFF* */ // Uncrustify cannot yet understand [[noreturn]] properly
RCLCPP_PUBLIC
void
throw_from_rcl_error [[noreturn]] (
rcl_ret_t ret,
const std::string & prefix = "",
const rcl_error_state_t * error_state = nullptr,
void (* reset_error)() = rcl_reset_error);
/* *INDENT-ON* */
class RCLErrorBase
{
public:
RCLCPP_PUBLIC
RCLErrorBase(rcl_ret_t ret, const rcl_error_state_t * error_state);
virtual ~RCLErrorBase() {}
rcl_ret_t ret;
std::string message;
std::string file;
size_t line;
std::string formatted_message;
};
/// Created when the return code does not match one of the other specialized exceptions.
class RCLError : public RCLErrorBase, public std::runtime_error
{
public:
RCLCPP_PUBLIC
RCLError(rcl_ret_t ret, const rcl_error_state_t * error_state, const std::string & prefix);
RCLCPP_PUBLIC
RCLError(const RCLErrorBase & base_exc, const std::string & prefix);
};
/// Created when the ret is RCL_RET_BAD_ALLOC.
class RCLBadAlloc : public RCLErrorBase, public std::bad_alloc
{
public:
RCLCPP_PUBLIC
RCLBadAlloc(rcl_ret_t ret, const rcl_error_state_t * error_state);
RCLCPP_PUBLIC
explicit RCLBadAlloc(const RCLErrorBase & base_exc);
};
/// Created when the ret is RCL_RET_INVALID_ARGUMENT.
class RCLInvalidArgument : public RCLErrorBase, public std::invalid_argument
{
public:
RCLCPP_PUBLIC
RCLInvalidArgument(
rcl_ret_t ret,
const rcl_error_state_t * error_state,
const std::string & prefix);
RCLCPP_PUBLIC
RCLInvalidArgument(const RCLErrorBase & base_exc, const std::string & prefix);
};
/// Created when the ret is RCL_RET_INVALID_ROS_ARGS.
class RCLInvalidROSArgsError : public RCLErrorBase, public std::runtime_error
{
public:
RCLCPP_PUBLIC
RCLInvalidROSArgsError(
rcl_ret_t ret, const rcl_error_state_t * error_state, const std::string & prefix);
RCLCPP_PUBLIC
RCLInvalidROSArgsError(const RCLErrorBase & base_exc, const std::string & prefix);
};
/// Thrown when unparsed ROS specific arguments are found.
class UnknownROSArgsError : public std::runtime_error
{
public:
explicit UnknownROSArgsError(std::vector<std::string> && unknown_ros_args_in)
: std::runtime_error(
"found unknown ROS arguments: '" + rcpputils::join(unknown_ros_args_in, "', '") + "'"),
unknown_ros_args(unknown_ros_args_in)
{
}
const std::vector<std::string> unknown_ros_args;
};
/// Thrown when an invalid rclcpp::Event object or SharedPtr is encountered.
class InvalidEventError : public std::runtime_error
{
public:
InvalidEventError()
: std::runtime_error("event is invalid") {}
};
/// Thrown when an unregistered rclcpp::Event is encountered where a registered one was expected.
class EventNotRegisteredError : public std::runtime_error
{
public:
EventNotRegisteredError()
: std::runtime_error("event already registered") {}
};
/// Thrown if passed parameters are inconsistent or invalid
class InvalidParametersException : public std::runtime_error
{
public:
// Inherit constructors from runtime_error.
using std::runtime_error::runtime_error;
};
/// Thrown if passed parameter value is invalid.
class InvalidParameterValueException : public std::runtime_error
{
// Inherit constructors from runtime_error.
using std::runtime_error::runtime_error;
};
/// Thrown if requested parameter type is invalid.
/**
* Essentially the same as rclcpp::ParameterTypeException, but with parameter
* name in the error message.
*/
class InvalidParameterTypeException : public std::runtime_error
{
public:
/// Construct an instance.
/**
* \param[in] name the name of the parameter.
* \param[in] message custom exception message.
*/
RCLCPP_PUBLIC
InvalidParameterTypeException(const std::string & name, const std::string message)
: std::runtime_error("parameter '" + name + "' has invalid type: " + message)
{}
};
/// Thrown if parameter is already declared.
class ParameterAlreadyDeclaredException : public std::runtime_error
{
// Inherit constructors from runtime_error.
using std::runtime_error::runtime_error;
};
/// Thrown if parameter is not declared, e.g. either set or get was called without first declaring.
class ParameterNotDeclaredException : public std::runtime_error
{
// Inherit constructors from runtime_error.
using std::runtime_error::runtime_error;
};
/// Thrown if parameter is immutable and therefore cannot be undeclared.
class ParameterImmutableException : public std::runtime_error
{
// Inherit constructors from runtime_error.
using std::runtime_error::runtime_error;
};
/// Thrown if parameter is modified while in a set callback.
class ParameterModifiedInCallbackException : public std::runtime_error
{
// Inherit constructors from runtime_error.
using std::runtime_error::runtime_error;
};
} // namespace exceptions
} // namespace rclcpp
#endif // RCLCPP__EXCEPTIONS__EXCEPTIONS_HPP_

View File

@@ -22,122 +22,254 @@
#include <iostream>
#include <list>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
#include "rcl/guard_condition.h"
#include "rcl/wait.h"
#include "rclcpp/any_executable.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/callback_group.hpp"
#include "rclcpp/executor_options.hpp"
#include "rclcpp/executor_policies/timer_favoring_priority_queue.hpp"
#include "rclcpp/future_return_code.hpp"
#include "rclcpp/guard_condition.hpp"
#include "rclcpp/memory_strategies.hpp"
#include "rclcpp/memory_strategy.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/utilities.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/wait_set.hpp"
namespace rclcpp
{
namespace executor
{
/// Return codes to be used with spin_until_future_complete.
/**
* SUCCESS: The future is complete and can be accessed with "get" without blocking.
* INTERRUPTED: The future is not complete, spinning was interrupted by Ctrl-C or another error.
* TIMEOUT: Spinning timed out.
*/
enum class FutureReturnCode {SUCCESS, INTERRUPTED, TIMEOUT};
RCLCPP_PUBLIC
std::ostream &
operator<<(std::ostream & os, const FutureReturnCode & future_return_code);
RCLCPP_PUBLIC
std::string
to_string(const FutureReturnCode & future_return_code);
///
/**
* Options to be passed to the executor constructor.
*/
struct ExecutorArgs
{
memory_strategy::MemoryStrategy::SharedPtr memory_strategy;
size_t max_conditions = 0;
};
static inline ExecutorArgs create_default_executor_arguments()
{
ExecutorArgs args;
args.memory_strategy = memory_strategies::create_default_strategy();
args.max_conditions = 0;
return args;
}
/// Coordinate the order and timing of available communication tasks.
/**
* Executor provides spin functions (including spin_node_once and spin_some).
* It coordinates the nodes and callback groups by looking for available work and completing it,
* based on the threading or concurrency scheme provided by the subclass implementation.
* An example of available work is executing a subscription callback, or a timer callback.
* The executor structure allows for a decoupling of the communication graph and the execution
* model.
* See SingleThreadedExecutor and MultiThreadedExecutor for examples of execution paradigms.
*/
class Executor
/// Base class for Executor providing the common interface for adding items, spinning, etc.
class ExecutorBase
{
public:
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(Executor);
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(ExecutorBase)
/// Default constructor.
// \param[in] ms The memory strategy to be used with this executor.
/**
* \param[in] options Options for the executor.
*/
RCLCPP_PUBLIC
explicit Executor(const ExecutorArgs & args = create_default_executor_arguments());
explicit ExecutorBase(const ExecutorOptions & options = ExecutorOptions());
/// Default destructor.
RCLCPP_PUBLIC
virtual ~Executor();
virtual ~ExecutorBase();
/// Do work periodically as it becomes available to us. Blocking call, may block indefinitely.
// It is up to the implementation of Executor to implement spin.
virtual void
/// Execution loop which waits for work, executes work, and repeats until canceled.
/**
* This will block, continuing to wait for work and then execute it, until
* canceled, either by the cancel() method or by the associated context being
* shutdown, either explicitly or due to a SIGINT (perhaps due to ctrl-c).
*/
virtual
void
spin() = 0;
/// Add a node to the executor.
/// Add all of a node's callback groups to the executor.
/**
* An executor can have zero or more nodes which provide work during `spin` functions.
* \param[in] node_ptr Shared pointer to the node to be added.
* \param[in] notify True to trigger the interrupt guard condition during this function. If
* the executor is blocked at the rmw layer while waiting for work and it is notified that a new
* node was added, it will wake up.
* Add all of the callback groups of a node to this executor.
*
* If any callback groups are associated with another executor, this method
* will throw a std::runtime_error.
*
* It will also trigger the interrupt guard condition which will cause the
* executor to wake up and consider the changes, then go back to waiting.
* Unless the notify parameter is passed false, in which case it will not
* interrupt the executor, and the changes may not be considered immediately.
*
* \param[in] node_ptr Shared pointer to the node which will have callback groups added.
* \param[in] notify If true, notfiy the executor of changes, otherwise do not.
* \throws std::runtime_error if any callback groups are associated with another executor.
*/
RCLCPP_PUBLIC
virtual void
add_node(rclcpp::node::Node::SharedPtr node_ptr, bool notify = true);
template<class NodeT>
void
add_node(const std::shared_ptr<NodeT> & node_ptr, bool notify = true)
{
this->add_node(
node_ptr->get_node_base_interface(),
notify,
false // raise on encountering already associated callback groups
);
}
/// Remove a node from the executor.
/// Overload that takes the NodeBaseInterface directly.
template<class NodeT>
void
add_node(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
bool notify = true)
{
this->add_node(
node_ptr,
notify,
false // raise on encountering already associated callback groups
);
}
/// Add all unassociated callback groups of the given node to this executor.
/**
* \param[in] node_ptr Shared pointer to the node to remove.
* \param[in] notify True to trigger the interrupt guard condition and wake up the executor.
* This is useful if the last node was removed from the executor while the executor was blocked
* waiting for work in another thread, because otherwise the executor would never be notified.
* Same as add_node(), but instead of throwing if a callback group is already
* associated with another exector (already added to it) it will just ignore
* it rather than throwing.
*
* \param[in] node_ptr Shared pointer to the node which will have callback groups added.
* \param[in] notify If true, notfiy the executor of changes, otherwise do not.
*/
template<class NodeT>
void
add_unassociated_callback_groups_from_node(
const std::shared_ptr<NodeT> & node_ptr,
bool notify = true)
{
this->add_node(
node_ptr->get_node_base_interface(),
notify,
true // ignore already associated callback groups
);
}
/// Overload that takes the NodeBaseInterface directly.
template<class NodeT>
void
add_unassociated_callback_groups_from_node(
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr & node_ptr,
bool notify = true)
{
this->add_node(
node_ptr,
notify,
true // ignore already associated callback groups
);
}
/// Remove all of a node's callback groups from the executor.
/**
* Remove all of the callback groups of a node from this executor.
*
* It will also trigger the interrupt guard condition which will cause the
* executor to wake up and consider the changes, then go back to waiting.
* Unless the notify parameter is passed false, in which case it will not
* interrupt the executor, and the changes may not be considered immediately.
*
* \param[in] node Node which will have callback groups removed.
* \param[in] notify If true, notfiy the executor of changes, otherwise do not.
*/
template<class NodeT>
void
remove_node(const NodeT & node, bool notify = true)
{
this->remove_node(*node.get_node_base_interface(), notify);
}
/// Overload that takes a shared pointer to the node.
/**
* This is kept for backwards compatibility from when executors shared
* ownership of Nodes.
*/
template<class NodeT>
void
remove_node(const std::shared_ptr<NodeT> & node_ptr, bool notify = true)
{
this->remove_node(*node_ptr->get_node_base_interface(), notify);
}
/// Placeholder used to indicate that a method overload should not notify the executor.
struct DoNotNotify {};
/// Add a callback group to this executor.
/**
* If the given callback group is already associated with another executor,
* this method will throw a std::runtime_error.
*
* This overload of add_callback_group() will notify the executor so it will
* wake up if waiting and consider the changes.
*
* Weak ownership of the callback group is kept by the executor all of the
* time, but while waiting the weak ownership is periodically elevated to
* shared ownership.
* Therefore, if you let the callback group shared pointer go out of scope
* then it will stay in scope until this executor is done using it, at which
* point the callback group will be destructed and automatically removed from
* this executor in the next pass.
*
* \param[in] callback_group_ptr The callback group to be added.
* \throws std::runtime_error if the callback group is associated with another
* executor already.
* \throws std::invalid_argument if the callback group pointer is nullptr.
*/
RCLCPP_PUBLIC
virtual void
remove_node(rclcpp::node::Node::SharedPtr node_ptr, bool notify = true);
virtual
void
add_callback_group(rclcpp::CallbackGroup::SharedPtr callback_group_ptr) = 0;
/// Add a callback group to this executor without notifying the executor.
/**
* The same as the other overload of add_callback_group(), except it does not
* notify the executor, so it will not wake up and these changes may not be
* considered immediately.
*
* Note, a bool with a default value would be preferable for controlling the
* notify behavior, and we're using it in the add/remove node above, but
* in order to keep this function virtual, and to avoid using default values
* in conjunction with virtual methods, we use an overload instead, in the
* spirit of std::nothrow_t, e.g.:
* https://en.cppreference.com/w/cpp/memory/new/nothrow
*/
RCLCPP_PUBLIC
virtual
void
add_callback_group(rclcpp::CallbackGroup::SharedPtr callback_group_ptr, DoNotNotify) = 0;
/// Remove a callback group from this executor.
/**
* If the given callback group is not associated with this executor, this
* method will throw a std::runtime_error.
*
* This overload of add_callback_group() will notify the executor so it will
* wake up if waiting and consider the changes.
*
* \param[in] callback_group The callback group to be removed.
* \throws std::runtime_error if the callback group is not associated with
* this executor.
* \throws std::invalid_argument if the callback group pointer is nullptr.
*/
RCLCPP_PUBLIC
virtual
void
remove_callback_group(const rclcpp::CallbackGroup & callback_group) = 0;
/// Remove a callback group from this executor without notifying the executor.
/**
* The same as the other overload of remove_callback_group(), except it does not
* notify the executor, so it will not wake up and these changes may not be
* considered immediately.
*
* See add_callback_group() for a note about the use of DoNotNotify.
*/
RCLCPP_PUBLIC
virtual
void
remove_callback_group(const rclcpp::CallbackGroup & callback_group, DoNotNotify) = 0;
/// Add a node to executor, execute the next available unit of work, and remove the node.
/**
* \param[in] node Shared pointer to the node to add.
* \param[in] timeout How long to wait for work to become available. Negative values cause
* spin_node_once to block indefinitely (the default behavior). A timeout of 0 causes this
* function to be non-blocking.
* \param[in] timeout How long to wait for work to become available.
* Negative values cause spin_node_once to block indefinitely (the default
* behavior).
* A timeout of 0 causes this function to be non-blocking.
*/
template<typename T = std::milli>
template<typename RepT = int64_t, typename T = std::milli>
void
spin_node_once(rclcpp::node::Node::SharedPtr node,
std::chrono::duration<int64_t, T> timeout = std::chrono::duration<int64_t, T>(-1))
spin_node_once(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
std::chrono::duration<RepT, T> timeout = std::chrono::duration<RepT, T>(-1))
{
return spin_node_once_nanoseconds(
node,
@@ -145,13 +277,29 @@ public:
);
}
/// Convenience function which takes Node and forwards NodeBaseInterface.
template<typename NodeT, typename RepT = int64_t, typename T = std::milli>
void
spin_node_once(
std::shared_ptr<NodeT> node,
std::chrono::duration<RepT, T> timeout = std::chrono::duration<RepT, T>(-1))
{
return spin_node_once_nanoseconds(
node->get_node_base_interface(),
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
);
}
/// Add a node, complete all immediately available work, and remove the node.
/**
* \param[in] node Shared pointer to the node to add.
* \param[in] node Shared pointer to the node to spin some.
*/
RCLCPP_PUBLIC
template<class NodeT>
void
spin_node_some(rclcpp::node::Node::SharedPtr node);
spin_node_some(const std::shared_ptr<NodeT> & node)
{
this->spin_node_some(node->get_node_base_interface());
}
/// Complete all available queued work without blocking.
/**
@@ -159,31 +307,36 @@ public:
* single-threaded model of execution.
* Adding subscriptions, timers, services, etc. with blocking callbacks will cause this function
* to block (which may have unintended consequences).
*
* \param[in] max_duration The maximum amount of time to spend executing work, or 0 for no limit.
* Note that spin_some() may take longer than this time as it only returns once max_duration has
* been exceeded.
*/
RCLCPP_PUBLIC
virtual void
spin_some();
virtual
void
spin_some(std::chrono::nanoseconds max_duration = std::chrono::nanoseconds(0)) = 0;
RCLCPP_PUBLIC
virtual void
spin_once(std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
virtual
void
spin_once(std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1)) = 0;
/// Spin (blocking) until the future is complete, it times out waiting, or rclcpp is interrupted.
/**
* \param[in] executor The executor which will spin the node.
* \param[in] node_ptr The node to spin.
* \param[in] future The future to wait on. If SUCCESS, the future is safe to access after this
function.
* \param[in] future The future to wait on. If this function returns SUCCESS, the future can be
* accessed without blocking (though it may still throw an exception).
* \param[in] timeout Optional timeout parameter, which gets passed to Executor::spin_node_once.
-1 is block forever, 0 is non-blocking.
If the time spent inside the blocking loop exceeds this timeout, return a TIMEOUT return code.
* \return The return code, one of SUCCESS, INTERRUPTED, or TIMEOUT.
* `-1` is block forever, `0` is non-blocking.
* If the time spent inside the blocking loop exceeds this timeout, return a TIMEOUT return
* code.
* \return The return code, one of `SUCCESS`, `INTERRUPTED`, or `TIMEOUT`.
*/
template<typename ResponseT, typename TimeT = std::milli>
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
FutureReturnCode
spin_until_future_complete(
std::shared_future<ResponseT> & future,
std::chrono::duration<int64_t, TimeT> timeout = std::chrono::duration<int64_t, TimeT>(-1))
const std::shared_future<ResponseT> & future,
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
{
// TODO(wjwwood): does not work recursively; can't call spin_node_until_future_complete
// inside a callback executed by an executor.
@@ -203,7 +356,7 @@ public:
}
std::chrono::nanoseconds timeout_left = timeout_ns;
while (rclcpp::utilities::ok()) {
while (rclcpp::ok(this->context_)) {
// Do one item of work.
spin_once(timeout_left);
// Check if the future is set, return SUCCESS if it is.
@@ -229,25 +382,51 @@ public:
}
/// Cancel any running spin* function, causing it to return.
/* This function can be called asynchonously from any thread. */
RCLCPP_PUBLIC
void
cancel();
/// Support dynamic switching of the memory strategy.
/**
* Switching the memory strategy while the executor is spinning in another threading could have
* unintended consequences.
* \param[in] memory_strategy Shared pointer to the memory strategy to set.
* This function can be called asynchronously from any thread.
*/
RCLCPP_PUBLIC
virtual
void
set_memory_strategy(memory_strategy::MemoryStrategy::SharedPtr memory_strategy);
cancel() = 0;
protected:
/// Implementation of add_node().
/**
* \param[in] node_ptr The node which will have its callback groups added.
* \param[in] notify If true, the executor is interrupted to consider the
* changes, otherwise it is not interrupted.
* \param[in] ignore_associated_callback_groups If true, then when a callback
* group which is already been added to another executor is encountered
* it will be ignored, if false then std::runtime_error is thrown instead.
* \throws std::runtime_error if ignore_associated_callback_groups is false
* and a callback group which is already associated with another executor
* is encountered.
* \throws std::invalid_argument if node_ptr is nullptr.
*/
RCLCPP_PUBLIC
virtual
void
add_node(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
bool notify,
bool ignore_associated_callback_groups) = 0;
RCLCPP_PUBLIC
virtual
void
remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify) = 0;
RCLCPP_PUBLIC
void
spin_node_once_nanoseconds(rclcpp::node::Node::SharedPtr node, std::chrono::nanoseconds timeout);
spin_node_once_nanoseconds(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
std::chrono::nanoseconds timeout);
RCLCPP_PUBLIC
virtual
void
spin_node_some(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node);
/// Find the next available executable and do the work associated with it.
/** \param[in] any_exec Union structure that can hold any executable type (timer, subscription,
@@ -255,72 +434,131 @@ protected:
*/
RCLCPP_PUBLIC
void
execute_any_executable(AnyExecutable::SharedPtr any_exec);
execute_any_executable(rclcpp::AnyExecutable & any_exec);
RCLCPP_PUBLIC
static void
static
void
execute_subscription(
rclcpp::subscription::SubscriptionBase::SharedPtr subscription);
rclcpp::SubscriptionBase::SharedPtr subscription);
RCLCPP_PUBLIC
static void
execute_intra_process_subscription(
rclcpp::subscription::SubscriptionBase::SharedPtr subscription);
static
void
execute_timer(rclcpp::TimerBase::SharedPtr timer);
RCLCPP_PUBLIC
static void
execute_timer(rclcpp::timer::TimerBase::SharedPtr timer);
static
void
execute_service(rclcpp::ServiceBase::SharedPtr service);
RCLCPP_PUBLIC
static void
execute_service(rclcpp::service::ServiceBase::SharedPtr service);
RCLCPP_PUBLIC
static void
execute_client(rclcpp::client::ClientBase::SharedPtr client);
static
void
execute_client(rclcpp::ClientBase::SharedPtr client);
RCLCPP_PUBLIC
void
wait_for_work(std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
RCLCPP_PUBLIC
rclcpp::node::Node::SharedPtr
get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr group);
rclcpp::CallbackGroup::SharedPtr
get_group_by_timer(rclcpp::TimerBase::SharedPtr timer);
RCLCPP_PUBLIC
rclcpp::callback_group::CallbackGroup::SharedPtr
get_group_by_timer(rclcpp::timer::TimerBase::SharedPtr timer);
bool
get_next_ready_executable(rclcpp::AnyExecutable & any_executable);
RCLCPP_PUBLIC
void
get_next_timer(AnyExecutable::SharedPtr any_exec);
bool
get_next_executable(
rclcpp::AnyExecutable & any_executable,
std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
RCLCPP_PUBLIC
AnyExecutable::SharedPtr
get_next_ready_executable();
RCLCPP_PUBLIC
AnyExecutable::SharedPtr
get_next_executable(std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
RCLCPP_DISABLE_COPY(ExecutorBase)
/// Spinning state, used to prevent multi threaded calls to spin and to cancel blocking spins.
std::atomic_bool spinning;
/// Guard condition for signaling the rmw layer to wake up for special events.
rcl_guard_condition_t interrupt_guard_condition_ = rcl_get_zero_initialized_guard_condition();
rclcpp::GuardCondition interrupt_guard_condition_;
// rcl_guard_condition_t interrupt_guard_condition_ = rcl_get_zero_initialized_guard_condition();
/// Waitset for managing entities that the rmw layer waits on.
rcl_wait_set_t waitset_ = rcl_get_zero_initialized_wait_set();
// /// Wait set for managing entities that the rmw layer waits on.
// rcl_wait_set_t wait_set_ = rcl_get_zero_initialized_wait_set();
/// The memory strategy: an interface for handling user-defined memory allocation strategies.
memory_strategy::MemoryStrategy::SharedPtr memory_strategy_;
// // Mutex to protect the subsequent memory_strategy_.
// std::mutex memory_strategy_mutex_;
private:
RCLCPP_DISABLE_COPY(Executor);
// /// The memory strategy: an interface for handling user-defined memory allocation strategies.
// memory_strategy::MemoryStrategy::SharedPtr memory_strategy_;
/// The context associated with this executor.
rclcpp::Context::SharedPtr context_;
// std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
// std::list<const rcl_guard_condition_t *> guard_conditions_;
std::vector<rclcpp::CallbackGroup::WeakPtr> weak_guard_conditions_;
std::vector<std::weak_ptr<rclcpp::node::Node>> weak_nodes_;
};
/// Template class which serves as the foundation of actual executors.
/**
* This class combines the wait set, scheduling policy, and the ExecutorBase
* class, and implements all of the pure virtual functions of ExecutorBase
* making it a concrete class.
*/
template<class WaitSetT, class SchedulingPolicy>
class ExecutorTemplate : public ExecutorBase, public SchedulingPolicy
{
public:
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(ExecutorTemplate)
/// Default constructor.
/**
* \param[in] options Options for the executor.
*/
explicit ExecutorTemplate(const ExecutorOptions & options = ExecutorOptions())
: ExecutorBase(options), SchedulingPolicy(options), WaitSetT(options.context)
{}
/// Default virtual destructor.
RCLCPP_PUBLIC
virtual
~ExecutorTemplate() = default;
protected:
WaitSetT wait_set_;
};
/// Executor concept which waits for work and coordinates execution of user callbacks.
/**
* Executor provides spin functions (including spin_node_once and spin_some).
* It coordinates the nodes and callback groups by looking for available work
* and completing it, based on the threading or concurrency scheme provided by
* the subclass implementation.
* An example of available work is executing a subscription callback, or a
* timer callback.
* The executor structure allows for a decoupling of the communication graph
* and the execution model.
* See SingleThreadedExecutor and MultiThreadedExecutor for examples of
* different execution paradigms.
*
* By default this alias provides a foundation based on specific wait set type
* and a scheduling policy.
* The wait set is expected to be dynamic, i.e. items can be added or removed
* after creation, and thread-safe, i.e. items can be added or removed while
* also waiting concurrently.
*/
using Executor = ExecutorTemplate<
rclcpp::ThreadSafeWaitSet,
rclcpp::executor_policies::TimerFavoringPriorityQueue>;
namespace executor
{
using Executor [[deprecated("use rclcpp::Executor instead")]] = Executor;
} // namespace executor
} // namespace rclcpp

View File

@@ -0,0 +1,49 @@
// Copyright 2014 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXECUTOR_OPTIONS_HPP_
#define RCLCPP__EXECUTOR_OPTIONS_HPP_
#include "rclcpp/context.hpp"
#include "rclcpp/contexts/default_context.hpp"
#include "rclcpp/memory_strategies.hpp"
#include "rclcpp/memory_strategy.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
/// Options to be passed to the executor constructor.
struct ExecutorOptions
{
ExecutorOptions()
: memory_strategy(rclcpp::memory_strategies::create_default_strategy()),
context(rclcpp::contexts::get_global_default_context()),
max_conditions(0)
{}
rclcpp::memory_strategy::MemoryStrategy::SharedPtr memory_strategy;
rclcpp::Context::SharedPtr context;
size_t max_conditions;
};
namespace executor
{
using ExecutorArgs [[deprecated("use rclcpp::ExecutorOptions instead")]] = ExecutorOptions;
} // namespace executor
} // namespace rclcpp
#endif // RCLCPP__EXECUTOR_OPTIONS_HPP_

View File

@@ -0,0 +1,35 @@
// Copyright 2020 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXECUTOR_POLICIES__SCHEDULING_RESULT_HPP_
#define RCLCPP__EXECUTOR_POLICIES__SCHEDULING_RESULT_HPP_
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace executor_policies
{
/// Represents the directions a SchedulingPolicy can give to an Executor.
enum RCLCPP_PUBLIC SchedulingResult
{
ContinueExecuting, //<! Indicates more work should be done before waiting.
WaitForWork, //<! Indicates that the executor should wait on the wait set again.
};
} // namespace executor_policies
} // namespace rclcpp
#endif // RCLCPP__EXECUTOR_POLICIES__SCHEDULING_RESULT_HPP_

View File

@@ -0,0 +1,77 @@
// Copyright 2020 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXECUTOR_POLICIES__TIMER_FAVORING_PRIORITY_QUEUE_HPP_
#define RCLCPP__EXECUTOR_POLICIES__TIMER_FAVORING_PRIORITY_QUEUE_HPP_
#include "rclcpp/any_executable.hpp"
#include "rclcpp/executor_options.hpp"
#include "rclcpp/executor_policies/scheduling_result.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/wait_result.hpp"
namespace rclcpp
{
namespace executor_policies
{
/// A naive scheduling policy which selects Timers first, then Subscriptions and other items.
/**
* Items are executed in the order they were added, favoring Timers, then
* Subscriptions, Service Servers, Service Clients, and finally Waitables.
* All Timers are executed before any Subscriptions, and all Subscriptions
* before any Service Servers, and so on.
*
* User guard conditions are not yet supported by the Executor and so all guard
* condition are used by the executor itself and are handled before this policy
* is consulted.
* Therefore, guard conditions are ignored for the purposes of scheduling.
*
* This is a naive policy, but is the default until a better one is implemented.
*/
class TimerFavoringPriorityQueue
{
public:
explicit TimerFavoringPriorityQueue(const rclcpp::ExecutorOptions &) {}
/// Select which item should next be executed, and indicate if waiting should resume.
/**
* Selects which item to be executed next, assign it to the any_executable, or
* assigning nullptr if no work should be done right now.
*
* This method is called by the executor after waiting on a wait set, in
* order to determine what to execute next based on the result.
*
* Additionally, if returning SchedulingResult::ContinueExecuting then the
* executor will call this function again without waiting on the wait set, or
* if returning SchedulingResult::WaitForWork then the executor will wait on
* the wait set again after executing the selected any_executable, or
* immediately if any_executable was assigned nullptr.
*/
template<class WaitSetT>
rclcpp::executor_policies::SchedulingResult
schedule_next_any_executable(
const WaitResult<WaitSetT> & wait_result,
rclcpp::AnyExecutable & any_executable)
{
// Explicitly ignore guard conditions.
// Check Timers for being ready.
}
};
} // namespace executor_policies
} // namespace rclcpp
#endif // RCLCPP__EXECUTOR_POLICIES__TIMER_FAVORING_PRIORITY_QUEUE_HPP_

View File

@@ -16,9 +16,11 @@
#define RCLCPP__EXECUTORS_HPP_
#include <future>
#include <memory>
#include "rclcpp/executors/multi_threaded_executor.hpp"
#include "rclcpp/executors/single_threaded_executor.hpp"
#include "rclcpp/executors/static_single_threaded_executor.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/utilities.hpp"
#include "rclcpp/visibility_control.hpp"
@@ -27,39 +29,50 @@ namespace rclcpp
{
/// Create a default single-threaded executor and execute any immediately available work.
// \param[in] node_ptr Shared pointer to the node to spin.
/** \param[in] node_ptr Shared pointer to the node to spin. */
RCLCPP_PUBLIC
void
spin_some(node::Node::SharedPtr node_ptr);
spin_some(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
RCLCPP_PUBLIC
void
spin_some(rclcpp::Node::SharedPtr node_ptr);
/// Create a default single-threaded executor and spin the specified node.
// \param[in] node_ptr Shared pointer to the node to spin.
/** \param[in] node_ptr Shared pointer to the node to spin. */
RCLCPP_PUBLIC
void
spin(node::Node::SharedPtr node_ptr);
spin(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
RCLCPP_PUBLIC
void
spin(rclcpp::Node::SharedPtr node_ptr);
namespace executors
{
using rclcpp::executors::multi_threaded_executor::MultiThreadedExecutor;
using rclcpp::executors::single_threaded_executor::SingleThreadedExecutor;
using rclcpp::executors::MultiThreadedExecutor;
using rclcpp::executors::SingleThreadedExecutor;
/// Spin (blocking) until the future is complete, it times out waiting, or rclcpp is interrupted.
/**
* \param[in] executor The executor which will spin the node.
* \param[in] node_ptr The node to spin.
* \param[in] future The future to wait on. If SUCCESS, the future is safe to access after this function
* \param[in] timeout Optional timeout parameter, which gets passed to Executor::spin_node_once.
-1 is block forever, 0 is non-blocking.
If the time spent inside the blocking loop exceeds this timeout, return a TIMEOUT return code.
* \return The return code, one of SUCCESS, INTERRUPTED, or TIMEOUT.
* \param[in] future The future to wait on. If `SUCCESS`, the future is safe to
* access after this function
* \param[in] timeout Optional timeout parameter, which gets passed to
* Executor::spin_node_once.
* `-1` is block forever, `0` is non-blocking.
* If the time spent inside the blocking loop exceeds this timeout, return a `TIMEOUT` return code.
* \return The return code, one of `SUCCESS`, `INTERRUPTED`, or `TIMEOUT`.
*/
template<typename ResponseT, typename TimeT = std::milli>
rclcpp::executor::FutureReturnCode
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
rclcpp::FutureReturnCode
spin_node_until_future_complete(
rclcpp::executor::Executor & executor, rclcpp::node::Node::SharedPtr node_ptr,
std::shared_future<ResponseT> & future,
std::chrono::duration<int64_t, TimeT> timeout = std::chrono::duration<int64_t, TimeT>(-1))
rclcpp::Executor & executor,
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
const std::shared_future<ResponseT> & future,
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
{
// TODO(wjwwood): does not work recursively; can't call spin_node_until_future_complete
// inside a callback executed by an executor.
@@ -69,18 +82,46 @@ spin_node_until_future_complete(
return retcode;
}
template<typename NodeT = rclcpp::Node, typename ResponseT, typename TimeRepT = int64_t,
typename TimeT = std::milli>
rclcpp::FutureReturnCode
spin_node_until_future_complete(
rclcpp::Executor & executor,
std::shared_ptr<NodeT> node_ptr,
const std::shared_future<ResponseT> & future,
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
{
return rclcpp::executors::spin_node_until_future_complete(
executor,
node_ptr->get_node_base_interface(),
future,
timeout);
}
} // namespace executors
template<typename FutureT, typename TimeT = std::milli>
rclcpp::executor::FutureReturnCode
template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::milli>
rclcpp::FutureReturnCode
spin_until_future_complete(
node::Node::SharedPtr node_ptr, std::shared_future<FutureT> & future,
std::chrono::duration<int64_t, TimeT> timeout = std::chrono::duration<int64_t, TimeT>(-1))
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
const std::shared_future<FutureT> & future,
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
{
rclcpp::executors::SingleThreadedExecutor executor;
return executors::spin_node_until_future_complete<FutureT>(executor, node_ptr, future, timeout);
}
template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeRepT = int64_t,
typename TimeT = std::milli>
rclcpp::FutureReturnCode
spin_until_future_complete(
std::shared_ptr<NodeT> node_ptr,
const std::shared_future<FutureT> & future,
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
{
return rclcpp::spin_until_future_complete(node_ptr->get_node_base_interface(), future, timeout);
}
} // namespace rclcpp
#endif // RCLCPP__EXECUTORS_HPP_

View File

@@ -15,7 +15,10 @@
#ifndef RCLCPP__EXECUTORS__MULTI_THREADED_EXECUTOR_HPP_
#define RCLCPP__EXECUTORS__MULTI_THREADED_EXECUTOR_HPP_
#include <chrono>
#include <memory>
#include <mutex>
#include <set>
#include <thread>
#include <unordered_map>
@@ -28,24 +31,38 @@ namespace rclcpp
{
namespace executors
{
namespace multi_threaded_executor
{
class MultiThreadedExecutor : public executor::Executor
class MultiThreadedExecutor : public rclcpp::Executor
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(MultiThreadedExecutor);
RCLCPP_SMART_PTR_DEFINITIONS(MultiThreadedExecutor)
/// Constructor for MultiThreadedExecutor.
/**
* For the yield_before_execute option, when true std::this_thread::yield()
* will be called after acquiring work (as an AnyExecutable) and
* releasing the spinning lock, but before executing the work.
* This is useful for reproducing some bugs related to taking work more than
* once.
*
* \param options common options for all executors
* \param number_of_threads number of threads to have in the thread pool,
* the default 0 will use the number of cpu cores found instead
* \param yield_before_execute if true std::this_thread::yield() is called
*/
RCLCPP_PUBLIC
MultiThreadedExecutor(
const executor::ExecutorArgs & args = rclcpp::executor::create_default_executor_arguments());
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions(),
size_t number_of_threads = 0,
bool yield_before_execute = false,
std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
RCLCPP_PUBLIC
virtual ~MultiThreadedExecutor();
RCLCPP_PUBLIC
void
spin();
spin() override;
RCLCPP_PUBLIC
size_t
@@ -57,13 +74,16 @@ protected:
run(size_t this_thread_number);
private:
RCLCPP_DISABLE_COPY(MultiThreadedExecutor);
RCLCPP_DISABLE_COPY(MultiThreadedExecutor)
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_;
};
} // namespace multi_threaded_executor
} // namespace executors
} // namespace rclcpp

View File

@@ -34,37 +34,40 @@ namespace rclcpp
{
namespace executors
{
namespace single_threaded_executor
{
/// Single-threaded executor implementation
// This is the default executor created by rclcpp::spin.
class SingleThreadedExecutor : public executor::Executor
/// Single-threaded executor implementation.
/**
* This is the default executor created by rclcpp::spin.
*/
class SingleThreadedExecutor : public rclcpp::Executor
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(SingleThreadedExecutor);
RCLCPP_SMART_PTR_DEFINITIONS(SingleThreadedExecutor)
/// Default constructor. See the default constructor for Executor.
RCLCPP_PUBLIC
SingleThreadedExecutor(
const executor::ExecutorArgs & args = rclcpp::executor::create_default_executor_arguments());
explicit SingleThreadedExecutor(
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
/// Default destrcutor.
/// Default destructor.
RCLCPP_PUBLIC
virtual ~SingleThreadedExecutor();
/// Single-threaded implementation of spin.
// This function will block until work comes in, execute it, and keep blocking.
// It will only be interrupt by a CTRL-C (managed by the global signal handler).
/**
* This function will block until work comes in, execute it, and then repeat
* the process until canceled.
* It may be interrupt by a call to rclcpp::Executor::cancel() or by ctrl-c
* if the associated context is configured to shutdown on SIGINT.
*/
RCLCPP_PUBLIC
void
spin();
spin() override;
private:
RCLCPP_DISABLE_COPY(SingleThreadedExecutor);
RCLCPP_DISABLE_COPY(SingleThreadedExecutor)
};
} // namespace single_threaded_executor
} // namespace executors
} // namespace rclcpp

View File

@@ -0,0 +1,168 @@
// Copyright 2020 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXECUTORS__STATIC_EXECUTOR_ENTITIES_COLLECTOR_HPP_
#define RCLCPP__EXECUTORS__STATIC_EXECUTOR_ENTITIES_COLLECTOR_HPP_
#include <chrono>
#include <list>
#include <memory>
#include "rcl/guard_condition.h"
#include "rcl/wait.h"
#include "rclcpp/experimental/executable_list.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/memory_strategy.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/waitable.hpp"
namespace rclcpp
{
namespace executors
{
class StaticExecutorEntitiesCollector final
: public rclcpp::Waitable,
public std::enable_shared_from_this<StaticExecutorEntitiesCollector>
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(StaticExecutorEntitiesCollector)
// Constructor
RCLCPP_PUBLIC
StaticExecutorEntitiesCollector() = default;
// Destructor
~StaticExecutorEntitiesCollector();
RCLCPP_PUBLIC
void
init(
rcl_wait_set_t * p_wait_set,
rclcpp::memory_strategy::MemoryStrategy::SharedPtr & memory_strategy,
rcl_guard_condition_t * executor_guard_condition);
RCLCPP_PUBLIC
void
execute() override;
RCLCPP_PUBLIC
void
fill_memory_strategy();
RCLCPP_PUBLIC
void
fill_executable_list();
/// Function to reallocate space for entities in the wait set.
RCLCPP_PUBLIC
void
prepare_wait_set();
/// Function to add_handles_to_wait_set and wait for work and
// block until the wait set is ready or until the timeout has been exceeded.
RCLCPP_PUBLIC
void
refresh_wait_set(std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
RCLCPP_PUBLIC
bool
add_to_wait_set(rcl_wait_set_t * wait_set) override;
RCLCPP_PUBLIC
size_t
get_number_of_ready_guard_conditions() override;
RCLCPP_PUBLIC
void
add_node(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
RCLCPP_PUBLIC
bool
remove_node(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
/// Complete all available queued work without blocking.
/**
* This function checks if after the guard condition was triggered
* (or a spurious wakeup happened) we are really ready to execute
* i.e. re-collect entities
*/
RCLCPP_PUBLIC
bool
is_ready(rcl_wait_set_t * wait_set) override;
RCLCPP_PUBLIC
size_t
get_number_of_timers() {return exec_list_.number_of_timers;}
RCLCPP_PUBLIC
size_t
get_number_of_subscriptions() {return exec_list_.number_of_subscriptions;}
RCLCPP_PUBLIC
size_t
get_number_of_services() {return exec_list_.number_of_services;}
RCLCPP_PUBLIC
size_t
get_number_of_clients() {return exec_list_.number_of_clients;}
RCLCPP_PUBLIC
size_t
get_number_of_waitables() {return exec_list_.number_of_waitables;}
RCLCPP_PUBLIC
rclcpp::SubscriptionBase::SharedPtr
get_subscription(size_t i) {return exec_list_.subscription[i];}
RCLCPP_PUBLIC
rclcpp::TimerBase::SharedPtr
get_timer(size_t i) {return exec_list_.timer[i];}
RCLCPP_PUBLIC
rclcpp::ServiceBase::SharedPtr
get_service(size_t i) {return exec_list_.service[i];}
RCLCPP_PUBLIC
rclcpp::ClientBase::SharedPtr
get_client(size_t i) {return exec_list_.client[i];}
RCLCPP_PUBLIC
rclcpp::Waitable::SharedPtr
get_waitable(size_t i) {return exec_list_.waitable[i];}
private:
/// Nodes guard conditions which trigger this waitable
std::list<const rcl_guard_condition_t *> guard_conditions_;
/// Memory strategy: an interface for handling user-defined memory allocation strategies.
rclcpp::memory_strategy::MemoryStrategy::SharedPtr memory_strategy_;
/// List of weak nodes registered in the static executor
std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
/// Wait set for managing entities that the rmw layer waits on.
rcl_wait_set_t * p_wait_set_ = nullptr;
/// Executable list: timers, subscribers, clients, services and waitables
rclcpp::experimental::ExecutableList exec_list_;
};
} // namespace executors
} // namespace rclcpp
#endif // RCLCPP__EXECUTORS__STATIC_EXECUTOR_ENTITIES_COLLECTOR_HPP_

View File

@@ -0,0 +1,200 @@
// Copyright 2019 Nobleo Technology
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_
#define RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_
#include <cassert>
#include <cstdlib>
#include <memory>
#include <vector>
#include <string>
#include "rmw/rmw.h"
#include "rclcpp/executor.hpp"
#include "rclcpp/executors/static_executor_entities_collector.hpp"
#include "rclcpp/experimental/executable_list.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/memory_strategies.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/rate.hpp"
#include "rclcpp/utilities.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace executors
{
/// Static executor implementation
/**
* This executor is a static version of the original single threaded executor.
* It's static because it doesn't reconstruct the executable list for every iteration.
* All nodes, callbackgroups, timers, subscriptions etc. are created before
* spin() is called, and modified only when an entity is added/removed to/from a node.
*
* To run this executor instead of SingleThreadedExecutor replace:
* rclcpp::executors::SingleThreadedExecutor exec;
* by
* rclcpp::executors::StaticSingleThreadedExecutor exec;
* in your source code and spin node(s) in the following way:
* exec.add_node(node);
* exec.spin();
* exec.remove_node(node);
*/
class StaticSingleThreadedExecutor : public rclcpp::Executor
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(StaticSingleThreadedExecutor)
/// Default constructor. See the default constructor for Executor.
RCLCPP_PUBLIC
explicit StaticSingleThreadedExecutor(
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
/// Default destrcutor.
RCLCPP_PUBLIC
virtual ~StaticSingleThreadedExecutor();
/// Static executor implementation of spin.
// This function will block until work comes in, execute it, and keep blocking.
// It will only be interrupt by a CTRL-C (managed by the global signal handler).
RCLCPP_PUBLIC
void
spin() override;
/// Add a node to the executor.
/**
* An executor can have zero or more nodes which provide work during `spin` functions.
* \param[in] node_ptr Shared pointer to the node to be added.
* \param[in] notify True to trigger the interrupt guard condition during this function. If
* the executor is blocked at the rmw layer while waiting for work and it is notified that a new
* node was added, it will wake up.
*/
RCLCPP_PUBLIC
void
add_node(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
bool notify = true) override;
/// Convenience function which takes Node and forwards NodeBaseInterface.
RCLCPP_PUBLIC
void
add_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true) override;
/// Remove a node from the executor.
/**
* \param[in] node_ptr Shared pointer to the node to remove.
* \param[in] notify True to trigger the interrupt guard condition and wake up the executor.
* This is useful if the last node was removed from the executor while the executor was blocked
* waiting for work in another thread, because otherwise the executor would never be notified.
*/
RCLCPP_PUBLIC
void
remove_node(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
bool notify = true) override;
/// Convenience function which takes Node and forwards NodeBaseInterface.
RCLCPP_PUBLIC
void
remove_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true) override;
/// 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] timeout Optional timeout parameter, which gets passed to
* Executor::execute_ready_executables.
* `-1` is block forever, `0` is non-blocking.
* If the time spent inside the blocking loop exceeds this timeout, return a TIMEOUT return
* code.
* \return The return code, one of `SUCCESS`, `INTERRUPTED`, or `TIMEOUT`.
*
* Example usage:
* rclcpp::executors::StaticSingleThreadedExecutor exec;
* // ... other part of code like creating node
* // define future
* exec.add_node(node);
* exec.spin_until_future_complete(future);
*/
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
rclcpp::FutureReturnCode
spin_until_future_complete(
std::shared_future<ResponseT> & future,
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
{
std::future_status status = future.wait_for(std::chrono::seconds(0));
if (status == std::future_status::ready) {
return rclcpp::FutureReturnCode::SUCCESS;
}
auto end_time = std::chrono::steady_clock::now();
std::chrono::nanoseconds timeout_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
timeout);
if (timeout_ns > std::chrono::nanoseconds::zero()) {
end_time += timeout_ns;
}
std::chrono::nanoseconds timeout_left = timeout_ns;
entities_collector_ = std::make_shared<StaticExecutorEntitiesCollector>();
entities_collector_->init(&wait_set_, memory_strategy_, &interrupt_guard_condition_);
while (rclcpp::ok(this->context_)) {
// Do one set of work.
entities_collector_->refresh_wait_set(timeout_left);
execute_ready_executables();
// Check if the future is set, return SUCCESS if it is.
status = future.wait_for(std::chrono::seconds(0));
if (status == std::future_status::ready) {
return rclcpp::FutureReturnCode::SUCCESS;
}
// If the original timeout is < 0, then this is blocking, never TIMEOUT.
if (timeout_ns < std::chrono::nanoseconds::zero()) {
continue;
}
// Otherwise check if we still have time to wait, return TIMEOUT if not.
auto now = std::chrono::steady_clock::now();
if (now >= end_time) {
return rclcpp::FutureReturnCode::TIMEOUT;
}
// Subtract the elapsed time from the original timeout.
timeout_left = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - now);
}
// The future did not complete before ok() returned false, return INTERRUPTED.
return rclcpp::FutureReturnCode::INTERRUPTED;
}
protected:
/// Check which executables in ExecutableList struct are ready from wait_set and execute them.
/**
* \param[in] exec_list Structure that can hold subscriptionbases, timerbases, etc
* \param[in] timeout Optional timeout parameter.
*/
RCLCPP_PUBLIC
void
execute_ready_executables();
private:
RCLCPP_DISABLE_COPY(StaticSingleThreadedExecutor)
StaticExecutorEntitiesCollector::SharedPtr entities_collector_;
};
} // namespace executors
} // namespace rclcpp
#endif // RCLCPP__EXECUTORS__STATIC_SINGLE_THREADED_EXECUTOR_HPP_

View File

@@ -0,0 +1,63 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXPAND_TOPIC_OR_SERVICE_NAME_HPP_
#define RCLCPP__EXPAND_TOPIC_OR_SERVICE_NAME_HPP_
#include <string>
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
/// Expand a topic or service name and throw if it is not valid.
/**
* This function can be used to "just" validate a topic or service name too,
* since expanding the topic name is required to fully validate a name.
*
* If the name is invalid, then InvalidTopicNameError is thrown or
* InvalidServiceNameError if is_service is true.
*
* This function can take any form of a topic or service name, i.e. it does not
* have to be a fully qualified name.
* The node name and namespace are used to expand it if necessary while
* validating it.
*
* Expansion is done with rcl_expand_topic_name.
* The validation is doen with rcl_validate_topic_name and
* rmw_validate_full_topic_name, so details about failures can be found in the
* documentation for those functions.
*
* \param name the topic or service name to be validated
* \param node_name the name of the node associated with the name
* \param namespace_ the namespace of the node associated with the name
* \param is_service if true InvalidServiceNameError is thrown instead
* \returns expanded (and validated) topic name
* \throws InvalidTopicNameError if name is invalid and is_service is false
* \throws InvalidServiceNameError if name is invalid and is_service is true
* \throws std::bad_alloc if memory cannot be allocated
* \throws RCLError if an unexpect error occurs
*/
RCLCPP_PUBLIC
std::string
expand_topic_or_service_name(
const std::string & name,
const std::string & node_name,
const std::string & namespace_,
bool is_service = false);
} // namespace rclcpp
#endif // RCLCPP__EXPAND_TOPIC_OR_SERVICE_NAME_HPP_

View File

@@ -0,0 +1,4 @@
Notice that headers in this folder should only provide symbols in the rclcpp::experimental namespace.
Also notice that these headers are not considered part of the public API as they have not yet been stabilized.
And therefore they are subject to change without notice.

View File

@@ -0,0 +1,42 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXPERIMENTAL__BUFFERS__BUFFER_IMPLEMENTATION_BASE_HPP_
#define RCLCPP__EXPERIMENTAL__BUFFERS__BUFFER_IMPLEMENTATION_BASE_HPP_
namespace rclcpp
{
namespace experimental
{
namespace buffers
{
template<typename BufferT>
class BufferImplementationBase
{
public:
virtual ~BufferImplementationBase() {}
virtual BufferT dequeue() = 0;
virtual void enqueue(BufferT request) = 0;
virtual void clear() = 0;
virtual bool has_data() const = 0;
};
} // namespace buffers
} // namespace experimental
} // namespace rclcpp
#endif // RCLCPP__EXPERIMENTAL__BUFFERS__BUFFER_IMPLEMENTATION_BASE_HPP_

View File

@@ -0,0 +1,241 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXPERIMENTAL__BUFFERS__INTRA_PROCESS_BUFFER_HPP_
#define RCLCPP__EXPERIMENTAL__BUFFERS__INTRA_PROCESS_BUFFER_HPP_
#include <memory>
#include <type_traits>
#include <utility>
#include "rclcpp/allocator/allocator_common.hpp"
#include "rclcpp/allocator/allocator_deleter.hpp"
#include "rclcpp/experimental/buffers/buffer_implementation_base.hpp"
#include "rclcpp/macros.hpp"
namespace rclcpp
{
namespace experimental
{
namespace buffers
{
class IntraProcessBufferBase
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(IntraProcessBufferBase)
virtual ~IntraProcessBufferBase() {}
virtual void clear() = 0;
virtual bool has_data() const = 0;
virtual bool use_take_shared_method() const = 0;
};
template<
typename MessageT,
typename Alloc = std::allocator<void>,
typename MessageDeleter = std::default_delete<MessageT>>
class IntraProcessBuffer : public IntraProcessBufferBase
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(IntraProcessBuffer)
virtual ~IntraProcessBuffer() {}
using MessageUniquePtr = std::unique_ptr<MessageT, MessageDeleter>;
using MessageSharedPtr = std::shared_ptr<const MessageT>;
virtual void add_shared(MessageSharedPtr msg) = 0;
virtual void add_unique(MessageUniquePtr msg) = 0;
virtual MessageSharedPtr consume_shared() = 0;
virtual MessageUniquePtr consume_unique() = 0;
};
template<
typename MessageT,
typename Alloc = std::allocator<void>,
typename MessageDeleter = std::default_delete<MessageT>,
typename BufferT = std::unique_ptr<MessageT>>
class TypedIntraProcessBuffer : public IntraProcessBuffer<MessageT, Alloc, MessageDeleter>
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(TypedIntraProcessBuffer)
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
using MessageAlloc = typename MessageAllocTraits::allocator_type;
using MessageUniquePtr = std::unique_ptr<MessageT, MessageDeleter>;
using MessageSharedPtr = std::shared_ptr<const MessageT>;
explicit
TypedIntraProcessBuffer(
std::unique_ptr<BufferImplementationBase<BufferT>> buffer_impl,
std::shared_ptr<Alloc> allocator = nullptr)
{
bool valid_type = (std::is_same<BufferT, MessageSharedPtr>::value ||
std::is_same<BufferT, MessageUniquePtr>::value);
if (!valid_type) {
throw std::runtime_error("Creating TypedIntraProcessBuffer with not valid BufferT");
}
buffer_ = std::move(buffer_impl);
if (!allocator) {
message_allocator_ = std::make_shared<MessageAlloc>();
} else {
message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
}
}
virtual ~TypedIntraProcessBuffer() {}
void add_shared(MessageSharedPtr msg) override
{
add_shared_impl<BufferT>(std::move(msg));
}
void add_unique(MessageUniquePtr msg) override
{
buffer_->enqueue(std::move(msg));
}
MessageSharedPtr consume_shared() override
{
return consume_shared_impl<BufferT>();
}
MessageUniquePtr consume_unique() override
{
return consume_unique_impl<BufferT>();
}
bool has_data() const override
{
return buffer_->has_data();
}
void clear() override
{
buffer_->clear();
}
bool use_take_shared_method() const override
{
return std::is_same<BufferT, MessageSharedPtr>::value;
}
private:
std::unique_ptr<BufferImplementationBase<BufferT>> buffer_;
std::shared_ptr<MessageAlloc> message_allocator_;
// MessageSharedPtr to MessageSharedPtr
template<typename DestinationT>
typename std::enable_if<
std::is_same<DestinationT, MessageSharedPtr>::value
>::type
add_shared_impl(MessageSharedPtr shared_msg)
{
buffer_->enqueue(std::move(shared_msg));
}
// MessageSharedPtr to MessageUniquePtr
template<typename DestinationT>
typename std::enable_if<
std::is_same<DestinationT, MessageUniquePtr>::value
>::type
add_shared_impl(MessageSharedPtr shared_msg)
{
// This should not happen: here a copy is unconditionally made, while the intra-process manager
// can decide whether a copy is needed depending on the number and the type of buffers
MessageUniquePtr unique_msg;
MessageDeleter * deleter = std::get_deleter<MessageDeleter, const MessageT>(shared_msg);
auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
MessageAllocTraits::construct(*message_allocator_.get(), ptr, *shared_msg);
if (deleter) {
unique_msg = MessageUniquePtr(ptr, *deleter);
} else {
unique_msg = MessageUniquePtr(ptr);
}
buffer_->enqueue(std::move(unique_msg));
}
// MessageSharedPtr to MessageSharedPtr
template<typename OriginT>
typename std::enable_if<
std::is_same<OriginT, MessageSharedPtr>::value,
MessageSharedPtr
>::type
consume_shared_impl()
{
return buffer_->dequeue();
}
// MessageUniquePtr to MessageSharedPtr
template<typename OriginT>
typename std::enable_if<
(std::is_same<OriginT, MessageUniquePtr>::value),
MessageSharedPtr
>::type
consume_shared_impl()
{
// automatic cast from unique ptr to shared ptr
return buffer_->dequeue();
}
// MessageSharedPtr to MessageUniquePtr
template<typename OriginT>
typename std::enable_if<
(std::is_same<OriginT, MessageSharedPtr>::value),
MessageUniquePtr
>::type
consume_unique_impl()
{
MessageSharedPtr buffer_msg = buffer_->dequeue();
MessageUniquePtr unique_msg;
MessageDeleter * deleter = std::get_deleter<MessageDeleter, const MessageT>(buffer_msg);
auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
MessageAllocTraits::construct(*message_allocator_.get(), ptr, *buffer_msg);
if (deleter) {
unique_msg = MessageUniquePtr(ptr, *deleter);
} else {
unique_msg = MessageUniquePtr(ptr);
}
return unique_msg;
}
// MessageUniquePtr to MessageUniquePtr
template<typename OriginT>
typename std::enable_if<
(std::is_same<OriginT, MessageUniquePtr>::value),
MessageUniquePtr
>::type
consume_unique_impl()
{
return buffer_->dequeue();
}
};
} // namespace buffers
} // namespace experimental
} // namespace rclcpp
#endif // RCLCPP__EXPERIMENTAL__BUFFERS__INTRA_PROCESS_BUFFER_HPP_

View File

@@ -0,0 +1,122 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
#define RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <utility>
#include <vector>
#include "rclcpp/experimental/buffers/buffer_implementation_base.hpp"
#include "rclcpp/logger.hpp"
#include "rclcpp/logging.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace experimental
{
namespace buffers
{
template<typename BufferT>
class RingBufferImplementation : public BufferImplementationBase<BufferT>
{
public:
explicit RingBufferImplementation(size_t capacity)
: capacity_(capacity),
ring_buffer_(capacity),
write_index_(capacity_ - 1),
read_index_(0),
size_(0)
{
if (capacity == 0) {
throw std::invalid_argument("capacity must be a positive, non-zero value");
}
}
virtual ~RingBufferImplementation() {}
void enqueue(BufferT request)
{
std::lock_guard<std::mutex> lock(mutex_);
write_index_ = next(write_index_);
ring_buffer_[write_index_] = std::move(request);
if (is_full()) {
read_index_ = next(read_index_);
} else {
size_++;
}
}
BufferT dequeue()
{
std::lock_guard<std::mutex> lock(mutex_);
if (!has_data()) {
RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Calling dequeue on empty intra-process buffer");
throw std::runtime_error("Calling dequeue on empty intra-process buffer");
}
auto request = std::move(ring_buffer_[read_index_]);
read_index_ = next(read_index_);
size_--;
return request;
}
inline size_t next(size_t val)
{
return (val + 1) % capacity_;
}
inline bool has_data() const
{
return size_ != 0;
}
inline bool is_full()
{
return size_ == capacity_;
}
void clear() {}
private:
size_t capacity_;
std::vector<BufferT> ring_buffer_;
size_t write_index_;
size_t read_index_;
size_t size_;
std::mutex mutex_;
};
} // namespace buffers
} // namespace experimental
} // namespace rclcpp
#endif // RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_

View File

@@ -0,0 +1,99 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXPERIMENTAL__CREATE_INTRA_PROCESS_BUFFER_HPP_
#define RCLCPP__EXPERIMENTAL__CREATE_INTRA_PROCESS_BUFFER_HPP_
#include <memory>
#include <type_traits>
#include <utility>
#include "rcl/subscription.h"
#include "rclcpp/experimental/buffers/intra_process_buffer.hpp"
#include "rclcpp/experimental/buffers/ring_buffer_implementation.hpp"
#include "rclcpp/intra_process_buffer_type.hpp"
namespace rclcpp
{
namespace experimental
{
template<
typename MessageT,
typename Alloc = std::allocator<void>,
typename Deleter = std::default_delete<MessageT>>
typename rclcpp::experimental::buffers::IntraProcessBuffer<MessageT, Alloc, Deleter>::UniquePtr
create_intra_process_buffer(
IntraProcessBufferType buffer_type,
rmw_qos_profile_t qos,
std::shared_ptr<Alloc> allocator)
{
using MessageSharedPtr = std::shared_ptr<const MessageT>;
using MessageUniquePtr = std::unique_ptr<MessageT, Deleter>;
size_t buffer_size = qos.depth;
using rclcpp::experimental::buffers::IntraProcessBuffer;
typename IntraProcessBuffer<MessageT, Alloc, Deleter>::UniquePtr buffer;
switch (buffer_type) {
case IntraProcessBufferType::SharedPtr:
{
using BufferT = MessageSharedPtr;
auto buffer_implementation =
std::make_unique<rclcpp::experimental::buffers::RingBufferImplementation<BufferT>>(
buffer_size);
// Construct the intra_process_buffer
buffer =
std::make_unique<rclcpp::experimental::buffers::TypedIntraProcessBuffer<MessageT, Alloc,
Deleter, BufferT>>(
std::move(buffer_implementation),
allocator);
break;
}
case IntraProcessBufferType::UniquePtr:
{
using BufferT = MessageUniquePtr;
auto buffer_implementation =
std::make_unique<rclcpp::experimental::buffers::RingBufferImplementation<BufferT>>(
buffer_size);
// Construct the intra_process_buffer
buffer =
std::make_unique<rclcpp::experimental::buffers::TypedIntraProcessBuffer<MessageT, Alloc,
Deleter, BufferT>>(
std::move(buffer_implementation),
allocator);
break;
}
default:
{
throw std::runtime_error("Unrecognized IntraProcessBufferType value");
break;
}
}
return buffer;
}
} // namespace experimental
} // namespace rclcpp
#endif // RCLCPP__EXPERIMENTAL__CREATE_INTRA_PROCESS_BUFFER_HPP_

View File

@@ -0,0 +1,92 @@
// Copyright 2019 Nobleo Technology
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_
#define RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_
#include <memory>
#include <vector>
#include "rclcpp/client.hpp"
#include "rclcpp/service.hpp"
#include "rclcpp/subscription_base.hpp"
#include "rclcpp/timer.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/waitable.hpp"
namespace rclcpp
{
namespace experimental
{
/// This class contains subscriptionbase, timerbase, etc. which can be used to run callbacks.
class ExecutableList final
{
public:
RCLCPP_PUBLIC
ExecutableList();
RCLCPP_PUBLIC
~ExecutableList();
RCLCPP_PUBLIC
void
clear();
RCLCPP_PUBLIC
void
add_subscription(rclcpp::SubscriptionBase::SharedPtr subscription);
RCLCPP_PUBLIC
void
add_timer(rclcpp::TimerBase::SharedPtr timer);
RCLCPP_PUBLIC
void
add_service(rclcpp::ServiceBase::SharedPtr service);
RCLCPP_PUBLIC
void
add_client(rclcpp::ClientBase::SharedPtr client);
RCLCPP_PUBLIC
void
add_waitable(rclcpp::Waitable::SharedPtr waitable);
// Vector containing the SubscriptionBase of all the subscriptions added to the executor.
std::vector<rclcpp::SubscriptionBase::SharedPtr> subscription;
// Contains the count of added subscriptions
size_t number_of_subscriptions;
// Vector containing the TimerBase of all the timers added to the executor.
std::vector<rclcpp::TimerBase::SharedPtr> timer;
// Contains the count of added timers
size_t number_of_timers;
// Vector containing the ServiceBase of all the services added to the executor.
std::vector<rclcpp::ServiceBase::SharedPtr> service;
// Contains the count of added services
size_t number_of_services;
// Vector containing the ClientBase of all the clients added to the executor.
std::vector<rclcpp::ClientBase::SharedPtr> client;
// Contains the count of added clients
size_t number_of_clients;
// Vector containing all the waitables added to the executor.
std::vector<rclcpp::Waitable::SharedPtr> waitable;
// Contains the count of added waitables
size_t number_of_waitables;
};
} // namespace experimental
} // namespace rclcpp
#endif // RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_

View File

@@ -0,0 +1,424 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXPERIMENTAL__INTRA_PROCESS_MANAGER_HPP_
#define RCLCPP__EXPERIMENTAL__INTRA_PROCESS_MANAGER_HPP_
#include <rmw/types.h>
#include <shared_mutex>
#include <algorithm>
#include <atomic>
#include <cstdint>
#include <exception>
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "rclcpp/allocator/allocator_deleter.hpp"
#include "rclcpp/experimental/subscription_intra_process.hpp"
#include "rclcpp/experimental/subscription_intra_process_base.hpp"
#include "rclcpp/logger.hpp"
#include "rclcpp/logging.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/publisher_base.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace experimental
{
/// This class performs intra process communication between nodes.
/**
* This class is used in the creation of publishers and subscriptions.
* A singleton instance of this class is owned by a rclcpp::Context and a
* rclcpp::Node can use an associated Context to get an instance of this class.
* Nodes which do not have a common Context will not exchange intra process
* messages because they do not share access to the same instance of this class.
*
* When a Node creates a subscription, it can also create a helper class,
* called SubscriptionIntraProcess, meant to receive intra process messages.
* It can be registered with this class.
* It is also allocated an id which is unique among all publishers
* and subscriptions in this process and that is associated to the subscription.
*
* When a Node creates a publisher, as with subscriptions, a helper class can
* be registered with this class.
* This is required in order to publish intra-process messages.
* It is also allocated an id which is unique among all publishers
* and subscriptions in this process and that is associated to the publisher.
*
* When a publisher or a subscription are registered, this class checks to see
* which other subscriptions or publishers it will communicate with,
* i.e. they have the same topic and compatible QoS.
*
* When the user publishes a message, if intra-process communication is enabled
* on the publisher, the message is given to this class.
* Using the publisher id, a list of recipients for the message is selected.
* For each subscription in the list, this class stores the message, whether
* sharing ownership or making a copy, in a buffer associated with the
* subscription helper class.
*
* The subscription helper class contains a buffer where published
* intra-process messages are stored until they are taken from the subscription.
* Depending on the data type stored in the buffer, the subscription helper
* class can request either shared or exclusive ownership on the message.
*
* Thus, when an intra-process message is published, this class knows how many
* intra-process subscriptions needs it and how many require ownership.
* This information allows this class to operate efficiently by performing the
* fewest number of copies of the message required.
*
* This class is neither CopyConstructable nor CopyAssignable.
*/
class IntraProcessManager
{
private:
RCLCPP_DISABLE_COPY(IntraProcessManager)
public:
RCLCPP_SMART_PTR_DEFINITIONS(IntraProcessManager)
RCLCPP_PUBLIC
IntraProcessManager();
RCLCPP_PUBLIC
virtual ~IntraProcessManager();
/// Register a subscription with the manager, returns subscriptions unique id.
/**
* This method stores the subscription intra process object, together with
* the information of its wrapped subscription (i.e. topic name and QoS).
*
* In addition this generates a unique intra process id for the subscription.
*
* \param subscription the SubscriptionIntraProcess to register.
* \return an unsigned 64-bit integer which is the subscription's unique id.
*/
RCLCPP_PUBLIC
uint64_t
add_subscription(rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr subscription);
/// Unregister a subscription using the subscription's unique id.
/**
* This method does not allocate memory.
*
* \param intra_process_subscription_id id of the subscription to remove.
*/
RCLCPP_PUBLIC
void
remove_subscription(uint64_t intra_process_subscription_id);
/// Register a publisher with the manager, returns the publisher unique id.
/**
* This method stores the publisher intra process object, together with
* the information of its wrapped publisher (i.e. topic name and QoS).
*
* In addition this generates a unique intra process id for the publisher.
*
* \param publisher publisher to be registered with the manager.
* \return an unsigned 64-bit integer which is the publisher's unique id.
*/
RCLCPP_PUBLIC
uint64_t
add_publisher(rclcpp::PublisherBase::SharedPtr publisher);
/// Unregister a publisher using the publisher's unique id.
/**
* This method does not allocate memory.
*
* \param intra_process_publisher_id id of the publisher to remove.
*/
RCLCPP_PUBLIC
void
remove_publisher(uint64_t intra_process_publisher_id);
/// Publishes an intra-process message, passed as a unique pointer.
/**
* This is one of the two methods for publishing intra-process.
*
* Using the intra-process publisher id, a list of recipients is obtained.
* This list is split in half, depending whether they require ownership or not.
*
* This particular method takes a unique pointer as input.
* The pointer can be promoted to a shared pointer and passed to all the subscriptions
* that do not require ownership.
* In case of subscriptions requiring ownership, the message will be copied for all of
* them except the last one, when ownership can be transferred.
*
* This method can save an additional copy compared to the shared pointer one.
*
* This method can throw an exception if the publisher id is not found or
* if the publisher shared_ptr given to add_publisher has gone out of scope.
*
* This method does allocate memory.
*
* \param intra_process_publisher_id the id of the publisher of this message.
* \param message the message that is being stored.
*/
template<
typename MessageT,
typename Alloc = std::allocator<void>,
typename Deleter = std::default_delete<MessageT>>
void
do_intra_process_publish(
uint64_t intra_process_publisher_id,
std::unique_ptr<MessageT, Deleter> message,
std::shared_ptr<typename allocator::AllocRebind<MessageT, Alloc>::allocator_type> allocator)
{
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
using MessageAllocatorT = typename MessageAllocTraits::allocator_type;
std::shared_lock<std::shared_timed_mutex> lock(mutex_);
auto publisher_it = pub_to_subs_.find(intra_process_publisher_id);
if (publisher_it == pub_to_subs_.end()) {
// Publisher is either invalid or no longer exists.
RCLCPP_WARN(
rclcpp::get_logger("rclcpp"),
"Calling do_intra_process_publish for invalid or no longer existing publisher id");
return;
}
const auto & sub_ids = publisher_it->second;
if (sub_ids.take_ownership_subscriptions.empty()) {
// None of the buffers require ownership, so we promote the pointer
std::shared_ptr<MessageT> msg = std::move(message);
this->template add_shared_msg_to_buffers<MessageT>(msg, sub_ids.take_shared_subscriptions);
} else if (!sub_ids.take_ownership_subscriptions.empty() && // NOLINT
sub_ids.take_shared_subscriptions.size() <= 1)
{
// There is at maximum 1 buffer that does not require ownership.
// So we this case is equivalent to all the buffers requiring ownership
// Merge the two vector of ids into a unique one
std::vector<uint64_t> concatenated_vector(sub_ids.take_shared_subscriptions);
concatenated_vector.insert(
concatenated_vector.end(),
sub_ids.take_ownership_subscriptions.begin(),
sub_ids.take_ownership_subscriptions.end());
this->template add_owned_msg_to_buffers<MessageT, Alloc, Deleter>(
std::move(message),
concatenated_vector,
allocator);
} else if (!sub_ids.take_ownership_subscriptions.empty() && // NOLINT
sub_ids.take_shared_subscriptions.size() > 1)
{
// Construct a new shared pointer from the message
// for the buffers that do not require ownership
auto shared_msg = std::allocate_shared<MessageT, MessageAllocatorT>(*allocator, *message);
this->template add_shared_msg_to_buffers<MessageT>(
shared_msg, sub_ids.take_shared_subscriptions);
this->template add_owned_msg_to_buffers<MessageT, Alloc, Deleter>(
std::move(message), sub_ids.take_ownership_subscriptions, allocator);
}
}
template<
typename MessageT,
typename Alloc = std::allocator<void>,
typename Deleter = std::default_delete<MessageT>>
std::shared_ptr<const MessageT>
do_intra_process_publish_and_return_shared(
uint64_t intra_process_publisher_id,
std::unique_ptr<MessageT, Deleter> message,
std::shared_ptr<typename allocator::AllocRebind<MessageT, Alloc>::allocator_type> allocator)
{
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
using MessageAllocatorT = typename MessageAllocTraits::allocator_type;
std::shared_lock<std::shared_timed_mutex> lock(mutex_);
auto publisher_it = pub_to_subs_.find(intra_process_publisher_id);
if (publisher_it == pub_to_subs_.end()) {
// Publisher is either invalid or no longer exists.
RCLCPP_WARN(
rclcpp::get_logger("rclcpp"),
"Calling do_intra_process_publish for invalid or no longer existing publisher id");
return nullptr;
}
const auto & sub_ids = publisher_it->second;
if (sub_ids.take_ownership_subscriptions.empty()) {
// If there are no owning, just convert to shared.
std::shared_ptr<MessageT> shared_msg = std::move(message);
if (!sub_ids.take_shared_subscriptions.empty()) {
this->template add_shared_msg_to_buffers<MessageT>(
shared_msg, sub_ids.take_shared_subscriptions);
}
return shared_msg;
} else {
// Construct a new shared pointer from the message for the buffers that
// do not require ownership and to return.
auto shared_msg = std::allocate_shared<MessageT, MessageAllocatorT>(*allocator, *message);
if (!sub_ids.take_shared_subscriptions.empty()) {
this->template add_shared_msg_to_buffers<MessageT>(
shared_msg,
sub_ids.take_shared_subscriptions);
}
if (!sub_ids.take_ownership_subscriptions.empty()) {
this->template add_owned_msg_to_buffers<MessageT, Alloc, Deleter>(
std::move(message),
sub_ids.take_ownership_subscriptions,
allocator);
}
return shared_msg;
}
}
/// Return true if the given rmw_gid_t matches any stored Publishers.
RCLCPP_PUBLIC
bool
matches_any_publishers(const rmw_gid_t * id) const;
/// Return the number of intraprocess subscriptions that are matched with a given publisher id.
RCLCPP_PUBLIC
size_t
get_subscription_count(uint64_t intra_process_publisher_id) const;
RCLCPP_PUBLIC
rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr
get_subscription_intra_process(uint64_t intra_process_subscription_id);
private:
struct SubscriptionInfo
{
SubscriptionInfo() = default;
rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr subscription;
rmw_qos_profile_t qos;
const char * topic_name;
bool use_take_shared_method;
};
struct PublisherInfo
{
PublisherInfo() = default;
rclcpp::PublisherBase::WeakPtr publisher;
rmw_qos_profile_t qos;
const char * topic_name;
};
struct SplittedSubscriptions
{
std::vector<uint64_t> take_shared_subscriptions;
std::vector<uint64_t> take_ownership_subscriptions;
};
using SubscriptionMap =
std::unordered_map<uint64_t, SubscriptionInfo>;
using PublisherMap =
std::unordered_map<uint64_t, PublisherInfo>;
using PublisherToSubscriptionIdsMap =
std::unordered_map<uint64_t, SplittedSubscriptions>;
RCLCPP_PUBLIC
static
uint64_t
get_next_unique_id();
RCLCPP_PUBLIC
void
insert_sub_id_for_pub(uint64_t sub_id, uint64_t pub_id, bool use_take_shared_method);
RCLCPP_PUBLIC
bool
can_communicate(PublisherInfo pub_info, SubscriptionInfo sub_info) const;
template<typename MessageT>
void
add_shared_msg_to_buffers(
std::shared_ptr<const MessageT> message,
std::vector<uint64_t> subscription_ids)
{
for (auto id : subscription_ids) {
auto subscription_it = subscriptions_.find(id);
if (subscription_it == subscriptions_.end()) {
throw std::runtime_error("subscription has unexpectedly gone out of scope");
}
auto subscription_base = subscription_it->second.subscription;
auto subscription = std::static_pointer_cast<
rclcpp::experimental::SubscriptionIntraProcess<MessageT>
>(subscription_base);
subscription->provide_intra_process_message(message);
}
}
template<
typename MessageT,
typename Alloc = std::allocator<void>,
typename Deleter = std::default_delete<MessageT>>
void
add_owned_msg_to_buffers(
std::unique_ptr<MessageT, Deleter> message,
std::vector<uint64_t> subscription_ids,
std::shared_ptr<typename allocator::AllocRebind<MessageT, Alloc>::allocator_type> allocator)
{
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
using MessageUniquePtr = std::unique_ptr<MessageT, Deleter>;
for (auto it = subscription_ids.begin(); it != subscription_ids.end(); it++) {
auto subscription_it = subscriptions_.find(*it);
if (subscription_it == subscriptions_.end()) {
throw std::runtime_error("subscription has unexpectedly gone out of scope");
}
auto subscription_base = subscription_it->second.subscription;
auto subscription = std::static_pointer_cast<
rclcpp::experimental::SubscriptionIntraProcess<MessageT>
>(subscription_base);
if (std::next(it) == subscription_ids.end()) {
// If this is the last subscription, give up ownership
subscription->provide_intra_process_message(std::move(message));
} else {
// Copy the message since we have additional subscriptions to serve
MessageUniquePtr copy_message;
Deleter deleter = message.get_deleter();
auto ptr = MessageAllocTraits::allocate(*allocator.get(), 1);
MessageAllocTraits::construct(*allocator.get(), ptr, *message);
copy_message = MessageUniquePtr(ptr, deleter);
subscription->provide_intra_process_message(std::move(copy_message));
}
}
}
PublisherToSubscriptionIdsMap pub_to_subs_;
SubscriptionMap subscriptions_;
PublisherMap publishers_;
mutable std::shared_timed_mutex mutex_;
};
} // namespace experimental
} // namespace rclcpp
#endif // RCLCPP__EXPERIMENTAL__INTRA_PROCESS_MANAGER_HPP_

View File

@@ -0,0 +1,176 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_HPP_
#define RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_HPP_
#include <rmw/rmw.h>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include "rcl/error_handling.h"
#include "rclcpp/any_subscription_callback.hpp"
#include "rclcpp/experimental/buffers/intra_process_buffer.hpp"
#include "rclcpp/experimental/create_intra_process_buffer.hpp"
#include "rclcpp/experimental/subscription_intra_process_base.hpp"
#include "rclcpp/type_support_decl.hpp"
#include "rclcpp/waitable.hpp"
#include "tracetools/tracetools.h"
namespace rclcpp
{
namespace experimental
{
template<
typename MessageT,
typename Alloc = std::allocator<void>,
typename Deleter = std::default_delete<MessageT>,
typename CallbackMessageT = MessageT>
class SubscriptionIntraProcess : public SubscriptionIntraProcessBase
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(SubscriptionIntraProcess)
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
using MessageAlloc = typename MessageAllocTraits::allocator_type;
using ConstMessageSharedPtr = std::shared_ptr<const MessageT>;
using MessageUniquePtr = std::unique_ptr<MessageT, Deleter>;
using BufferUniquePtr = typename rclcpp::experimental::buffers::IntraProcessBuffer<
MessageT,
Alloc,
Deleter
>::UniquePtr;
SubscriptionIntraProcess(
AnySubscriptionCallback<CallbackMessageT, Alloc> callback,
std::shared_ptr<Alloc> allocator,
rclcpp::Context::SharedPtr context,
const std::string & topic_name,
rmw_qos_profile_t qos_profile,
rclcpp::IntraProcessBufferType buffer_type)
: SubscriptionIntraProcessBase(topic_name, qos_profile),
any_callback_(callback)
{
if (!std::is_same<MessageT, CallbackMessageT>::value) {
throw std::runtime_error("SubscriptionIntraProcess wrong callback type");
}
// Create the intra-process buffer.
buffer_ = rclcpp::experimental::create_intra_process_buffer<MessageT, Alloc, Deleter>(
buffer_type,
qos_profile,
allocator);
// Create the guard condition.
rcl_guard_condition_options_t guard_condition_options =
rcl_guard_condition_get_default_options();
gc_ = rcl_get_zero_initialized_guard_condition();
rcl_ret_t ret = rcl_guard_condition_init(
&gc_, context->get_rcl_context().get(), guard_condition_options);
if (RCL_RET_OK != ret) {
throw std::runtime_error("SubscriptionIntraProcess init error initializing guard condition");
}
TRACEPOINT(
rclcpp_subscription_callback_added,
(const void *)this,
(const void *)&any_callback_);
// The callback object gets copied, so if registration is done too early/before this point
// (e.g. in `AnySubscriptionCallback::set()`), its address won't match any address used later
// in subsequent tracepoints.
#ifndef TRACETOOLS_DISABLED
any_callback_.register_callback_for_tracing();
#endif
}
bool
is_ready(rcl_wait_set_t * wait_set)
{
(void)wait_set;
return buffer_->has_data();
}
void execute()
{
execute_impl<CallbackMessageT>();
}
void
provide_intra_process_message(ConstMessageSharedPtr message)
{
buffer_->add_shared(std::move(message));
trigger_guard_condition();
}
void
provide_intra_process_message(MessageUniquePtr message)
{
buffer_->add_unique(std::move(message));
trigger_guard_condition();
}
bool
use_take_shared_method() const
{
return buffer_->use_take_shared_method();
}
private:
void
trigger_guard_condition()
{
rcl_ret_t ret = rcl_trigger_guard_condition(&gc_);
(void)ret;
}
template<typename T>
typename std::enable_if<std::is_same<T, rcl_serialized_message_t>::value, void>::type
execute_impl()
{
throw std::runtime_error("Subscription intra-process can't handle serialized messages");
}
template<class T>
typename std::enable_if<!std::is_same<T, rcl_serialized_message_t>::value, void>::type
execute_impl()
{
rmw_message_info_t msg_info;
msg_info.publisher_gid = {0, {0}};
msg_info.from_intra_process = true;
if (any_callback_.use_take_shared_method()) {
ConstMessageSharedPtr msg = buffer_->consume_shared();
any_callback_.dispatch_intra_process(msg, msg_info);
} else {
MessageUniquePtr msg = buffer_->consume_unique();
any_callback_.dispatch_intra_process(std::move(msg), msg_info);
}
}
AnySubscriptionCallback<CallbackMessageT, Alloc> any_callback_;
BufferUniquePtr buffer_;
};
} // namespace experimental
} // namespace rclcpp
#endif // RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_HPP_

View File

@@ -0,0 +1,88 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_BASE_HPP_
#define RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_BASE_HPP_
#include <rmw/rmw.h>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <utility>
#include "rcl/error_handling.h"
#include "rclcpp/type_support_decl.hpp"
#include "rclcpp/waitable.hpp"
namespace rclcpp
{
namespace experimental
{
class SubscriptionIntraProcessBase : public rclcpp::Waitable
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(SubscriptionIntraProcessBase)
RCLCPP_PUBLIC
SubscriptionIntraProcessBase(const std::string & topic_name, rmw_qos_profile_t qos_profile)
: topic_name_(topic_name), qos_profile_(qos_profile)
{}
virtual ~SubscriptionIntraProcessBase() = default;
RCLCPP_PUBLIC
size_t
get_number_of_ready_guard_conditions() {return 1;}
RCLCPP_PUBLIC
bool
add_to_wait_set(rcl_wait_set_t * wait_set);
virtual bool
is_ready(rcl_wait_set_t * wait_set) = 0;
virtual void
execute() = 0;
virtual bool
use_take_shared_method() const = 0;
RCLCPP_PUBLIC
const char *
get_topic_name() const;
RCLCPP_PUBLIC
rmw_qos_profile_t
get_actual_qos() const;
protected:
std::recursive_mutex reentrant_mutex_;
rcl_guard_condition_t gc_;
private:
virtual void
trigger_guard_condition() = 0;
std::string topic_name_;
rmw_qos_profile_t qos_profile_;
};
} // namespace experimental
} // namespace rclcpp
#endif // RCLCPP__EXPERIMENTAL__SUBSCRIPTION_INTRA_PROCESS_BASE_HPP_

View File

@@ -49,14 +49,14 @@ template<typename FunctionT>
struct function_traits
{
using arguments = typename tuple_tail<
typename function_traits<decltype( & FunctionT::operator())>::arguments>::type;
typename function_traits<decltype( &FunctionT::operator())>::arguments>::type;
static constexpr std::size_t arity = std::tuple_size<arguments>::value;
template<std::size_t N>
using argument_type = typename std::tuple_element<N, arguments>::type;
using return_type = typename function_traits<decltype( & FunctionT::operator())>::return_type;
using return_type = typename function_traits<decltype( &FunctionT::operator())>::return_type;
};
// Free functions
@@ -81,13 +81,31 @@ struct function_traits<ReturnTypeT (*)(Args ...)>: function_traits<ReturnTypeT(A
// std::bind for object methods
template<typename ClassT, typename ReturnTypeT, typename ... Args, typename ... FArgs>
#if defined _LIBCPP_VERSION // libc++ (Clang)
struct function_traits<std::__1::__bind<ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
struct function_traits<std::__bind<ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
#elif defined _GLIBCXX_RELEASE // glibc++ (GNU C++ >= 7.1)
struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(FArgs ...))(Args ...)>>
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
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
: function_traits<ReturnTypeT(Args ...)>
{};
// std::bind for object const methods
template<typename ClassT, typename ReturnTypeT, typename ... Args, typename ... FArgs>
#if defined _LIBCPP_VERSION // libc++ (Clang)
struct function_traits<std::__bind<ReturnTypeT (ClassT::*)(Args ...) const, FArgs ...>>
#elif defined _GLIBCXX_RELEASE // glibc++ (GNU C++ >= 7.1)
struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(FArgs ...))(Args ...) const>>
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
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 (ClassT::*)(Args ...) const, FArgs ...>>
#else
#error "Unsupported C++ compiler / standard library"
#endif
@@ -97,11 +115,11 @@ struct function_traits<
// std::bind for free functions
template<typename ReturnTypeT, typename ... Args, typename ... FArgs>
#if defined _LIBCPP_VERSION // libc++ (Clang)
struct function_traits<std::__1::__bind<ReturnTypeT( &)(Args ...), FArgs ...>>
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
@@ -128,20 +146,20 @@ struct function_traits<FunctionT &&>: function_traits<FunctionT>
*/
template<std::size_t Arity, typename FunctorT>
struct arity_comparator : std::integral_constant<
bool, (Arity == function_traits<FunctorT>::arity)>{};
bool, (Arity == function_traits<FunctorT>::arity)> {};
template<typename FunctorT, typename ... Args>
struct check_arguments : std::is_same<
typename function_traits<FunctorT>::arguments,
std::tuple<Args ...>
>
>
{};
template<typename FunctorAT, typename FunctorBT>
struct same_arguments : std::is_same<
typename function_traits<FunctorAT>::arguments,
typename function_traits<FunctorBT>::arguments
>
>
{};
} // namespace function_traits

View File

@@ -0,0 +1,53 @@
// Copyright 2014 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__FUTURE_RETURN_CODE_HPP_
#define RCLCPP__FUTURE_RETURN_CODE_HPP_
#include <iostream>
#include <string>
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
/// Return codes to be used with spin_until_future_complete.
/**
* SUCCESS: The future is complete and can be accessed with "get" without blocking.
* This does not indicate that the operation succeeded; "get" may still throw an exception.
* INTERRUPTED: The future is not complete, spinning was interrupted by Ctrl-C or another error.
* TIMEOUT: Spinning timed out.
*/
enum class FutureReturnCode {SUCCESS, INTERRUPTED, TIMEOUT};
/// Stream operator for FutureReturnCode.
RCLCPP_PUBLIC
std::ostream &
operator<<(std::ostream & os, const FutureReturnCode & future_return_code);
/// String conversion function for FutureReturnCode.
RCLCPP_PUBLIC
std::string
to_string(const FutureReturnCode & future_return_code);
namespace executor
{
using FutureReturnCode [[deprecated("use rclcpp::FutureReturnCode instead")]] = FutureReturnCode;
} // namespace executor
} // namespace rclcpp
#endif // RCLCPP__FUTURE_RETURN_CODE_HPP_

View File

@@ -23,17 +23,14 @@
#include "rcl/guard_condition.h"
#include "rcl/wait.h"
#include "rclcpp/context.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node
{
class Node;
} // namespace node
namespace graph_listener
{
@@ -66,13 +63,14 @@ class GraphListener : public std::enable_shared_from_this<GraphListener>
{
public:
RCLCPP_PUBLIC
GraphListener();
explicit GraphListener(std::shared_ptr<rclcpp::Context> parent_context);
RCLCPP_PUBLIC
virtual ~GraphListener();
/// Start the graph listener's listen thread if it hasn't been started.
/* This function is thread-safe.
/**
* This function is thread-safe.
*
* \throws GraphListenerShutdownError if the GraphListener is shutdown
*/
@@ -82,7 +80,7 @@ public:
start_if_not_started();
/// Add a node to the graph listener's list of nodes.
/*
/**
* \throws GraphListenerShutdownError if the GraphListener is shutdown
* \throws NodeAlreadyAddedError if the given node is already in the list
* \throws std::invalid_argument if node is nullptr
@@ -91,20 +89,22 @@ public:
RCLCPP_PUBLIC
virtual
void
add_node(rclcpp::node::Node * node);
add_node(rclcpp::node_interfaces::NodeGraphInterface * node_graph);
/// Return true if the given node is in the graph listener's list of nodes.
/* Also return false if given nullptr.
/**
* Also return false if given nullptr.
*
* \throws std::system_error anything std::mutex::lock() throws
*/
RCLCPP_PUBLIC
virtual
bool
has_node(rclcpp::node::Node * node);
has_node(rclcpp::node_interfaces::NodeGraphInterface * node_graph);
/// Remove a node from the graph listener's list of nodes.
/*
/**
*
* \throws NodeNotFoundError if the given node is not in the list
* \throws std::invalid_argument if node is nullptr
* \throws std::system_error anything std::mutex::lock() throws
@@ -112,10 +112,11 @@ public:
RCLCPP_PUBLIC
virtual
void
remove_node(rclcpp::node::Node * node);
remove_node(rclcpp::node_interfaces::NodeGraphInterface * node_graph);
/// Stop the listening thread.
/* The thread cannot be restarted, and the class is defunct after calling.
/**
* The thread cannot be restarted, and the class is defunct after calling.
* This function is called by the ~GraphListener() and does nothing if
* shutdown() was already called.
* This function exists separately from the ~GraphListener() so that it can
@@ -133,6 +134,12 @@ public:
void
shutdown();
/// Nothrow version of shutdown(), logs to RCLCPP_ERROR instead.
RCLCPP_PUBLIC
virtual
void
shutdown(const std::nothrow_t &) noexcept;
/// Return true if shutdown() has been called, else false.
RCLCPP_PUBLIC
virtual
@@ -152,16 +159,22 @@ protected:
run_loop();
private:
RCLCPP_DISABLE_COPY(GraphListener);
RCLCPP_DISABLE_COPY(GraphListener)
/** \internal */
void
__shutdown(bool);
rclcpp::Context::WeakPtr parent_context_;
std::thread listener_thread_;
bool is_started_;
std::atomic_bool is_shutdown_;
mutable std::mutex shutdown_mutex_;
mutable std::mutex nodes_barrier_mutex_;
mutable std::mutex nodes_mutex_;
std::vector<rclcpp::node::Node *> nodes_;
mutable std::mutex node_graph_interfaces_barrier_mutex_;
mutable std::mutex node_graph_interfaces_mutex_;
std::vector<rclcpp::node_interfaces::NodeGraphInterface *> node_graph_interfaces_;
rcl_guard_condition_t interrupt_guard_condition_ = rcl_get_zero_initialized_guard_condition();
rcl_guard_condition_t * shutdown_guard_condition_;

View File

@@ -0,0 +1,100 @@
// Copyright 2020 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__GUARD_CONDITION_HPP_
#define RCLCPP__GUARD_CONDITION_HPP_
#include <atomic>
#include "rcl/guard_condition.h"
#include "rclcpp/context.hpp"
#include "rclcpp/contexts/default_context.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
/// A condition that can be waited on in a single wait set and asynchronously triggered.
class GuardCondition
{
public:
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(GuardCondition)
// TODO(wjwwood): support custom allocator, maybe restrict to polymorphic allocator
/// Construct the guard condition, optionally specifying which Context to use.
/**
* \param[in] context Optional custom context to be used.
* Defaults to using the global default context singleton.
* Shared ownership of the context is held with the guard condition until
* destruction.
* \throws std::invalid_argument if the context is nullptr.
* \throws rclcpp::exceptions::RCLError based exceptions when underlying
* rcl functions fail.
*/
RCLCPP_PUBLIC
explicit GuardCondition(
rclcpp::Context::SharedPtr context =
rclcpp::contexts::get_global_default_context());
RCLCPP_PUBLIC
virtual
~GuardCondition();
/// Return the context used when creating this guard condition.
RCLCPP_PUBLIC
rclcpp::Context::SharedPtr
get_context() const;
/// Return the underlying rcl guard condition structure.
RCLCPP_PUBLIC
const rcl_guard_condition_t &
get_rcl_guard_condition() const;
/// Notify the wait set waiting on this condition, if any, that the condition had been met.
/**
* This function is thread-safe, and may be called concurrently with waiting
* on this guard condition in a wait set.
*
* \throws rclcpp::exceptions::RCLError based exceptions when underlying
* rcl functions fail.
*/
RCLCPP_PUBLIC
void
trigger();
/// Exchange the "in use by wait set" state for this guard condition.
/**
* This is used to ensure this guard condition is not used by multiple
* wait sets at the same time.
*
* \param[in] in_use_state the new state to exchange into the state, true
* indicates it is now in use by a wait set, and false is that it is no
* longer in use by a wait set.
* \returns the previous state.
*/
RCLCPP_PUBLIC
bool
exchange_in_use_by_wait_set_state(bool in_use_state);
protected:
rclcpp::Context::SharedPtr context_;
rcl_guard_condition_t rcl_guard_condition_;
std::atomic<bool> in_use_by_wait_set_{false};
};
} // namespace rclcpp
#endif // RCLCPP__GUARD_CONDITION_HPP_

View File

@@ -0,0 +1,69 @@
// 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.
#ifndef RCLCPP__INIT_OPTIONS_HPP_
#define RCLCPP__INIT_OPTIONS_HPP_
#include <memory>
#include "rcl/init_options.h"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
/// Encapsulation of options for initializing rclcpp.
class InitOptions
{
public:
/// If true, the context will be shutdown on SIGINT by the signal handler (if it was installed).
bool shutdown_on_sigint = true;
/// Constructor which allows you to specify the allocator used within the init options.
RCLCPP_PUBLIC
explicit InitOptions(rcl_allocator_t allocator = rcl_get_default_allocator());
/// Constructor which is initialized by an existing init_options.
RCLCPP_PUBLIC
explicit InitOptions(const rcl_init_options_t & init_options);
/// Copy constructor.
RCLCPP_PUBLIC
InitOptions(const InitOptions & other);
/// Assignment operator.
RCLCPP_PUBLIC
InitOptions &
operator=(const InitOptions & other);
RCLCPP_PUBLIC
virtual
~InitOptions();
/// Return the rcl init options.
RCLCPP_PUBLIC
const rcl_init_options_t *
get_rcl_init_options() const;
protected:
void
finalize_init_options();
private:
std::unique_ptr<rcl_init_options_t> init_options_;
};
} // namespace rclcpp
#endif // RCLCPP__INIT_OPTIONS_HPP_

View File

@@ -0,0 +1,35 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__INTRA_PROCESS_BUFFER_TYPE_HPP_
#define RCLCPP__INTRA_PROCESS_BUFFER_TYPE_HPP_
namespace rclcpp
{
/// Used as argument in create_publisher and create_subscriber
/// when intra-process communication is enabled
enum class IntraProcessBufferType
{
/// Set the data type used in the intra-process buffer as std::shared_ptr<MessageT>
SharedPtr,
/// Set the data type used in the intra-process buffer as std::unique_ptr<MessageT>
UniquePtr,
/// Set the data type used in the intra-process buffer as the same used in the callback
CallbackDefault
};
} // namespace rclcpp
#endif // RCLCPP__INTRA_PROCESS_BUFFER_TYPE_HPP_

View File

@@ -1,347 +0,0 @@
// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__INTRA_PROCESS_MANAGER_HPP_
#define RCLCPP__INTRA_PROCESS_MANAGER_HPP_
#include <rmw/types.h>
#include <algorithm>
#include <atomic>
#include <cstdint>
#include <exception>
#include <map>
#include <memory>
#include <unordered_map>
#include <set>
#include "rclcpp/allocator/allocator_deleter.hpp"
#include "rclcpp/intra_process_manager_impl.hpp"
#include "rclcpp/mapped_ring_buffer.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/publisher.hpp"
#include "rclcpp/subscription.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace intra_process_manager
{
/// This class facilitates intra process communication between nodes.
/* This class is used in the creation of publishers and subscriptions.
* A singleton instance of this class is owned by a rclcpp::Context and a
* rclcpp::Node can use an associated Context to get an instance of this class.
* Nodes which do not have a common Context will not exchange intra process
* messages because they will not share access to an instance of this class.
*
* When a Node creates a publisher or subscription, it will register them
* with this class.
* The node will also hook into the publisher's publish call
* in order to do intra process related work.
*
* When a publisher is created, it advertises on the topic the user provided,
* as well as a "shadowing" topic of type rcl_interfaces/IntraProcessMessage.
* For instance, if the user specified the topic '/namespace/chatter', then the
* corresponding intra process topic might be '/namespace/chatter__intra'.
* The publisher is also allocated an id which is unique among all publishers
* and subscriptions in this process.
* Additionally, when registered with this class a ring buffer is created and
* owned by this class as a temporary place to hold messages destined for intra
* process subscriptions.
*
* When a subscription is created, it subscribes to the topic provided by the
* user as well as to the corresponding intra process topic.
* It is also gets a unique id from the singleton instance of this class which
* is unique among publishers and subscriptions.
*
* When the user publishes a message, the message is stored by calling
* store_intra_process_message on this class.
* The instance of that message is uniquely identified by a publisher id and a
* message sequence number.
* The publisher id, message sequence pair is unique with in the process.
* At that point a list of the id's of intra process subscriptions which have
* been registered with the singleton instance of this class are stored with
* the message instance so that delivery is only made to those subscriptions.
* Then an instance of rcl_interfaces/IntraProcessMessage is published to the
* intra process topic which is specific to the topic specified by the user.
*
* When an instance of rcl_interfaces/IntraProcessMessage is received by a
* subscription, then it is handled by calling take_intra_process_message
* on a singleton of this class.
* The subscription passes a publisher id, message sequence pair which
* uniquely identifies the message instance it was suppose to receive as well
* as the subscriptions unique id.
* If the message is still being held by this class and the subscription's id
* is in the list of intended subscriptions then the message is returned.
* If either of those predicates are not satisfied then the message is not
* returned and the subscription does not call the users callback.
*
* Since the publisher builds a list of destined subscriptions on publish, and
* other requests are ignored, this class knows how many times a message
* instance should be requested.
* The final time a message is requested, the ownership is passed out of this
* class and passed to the final subscription, effectively freeing space in
* this class's internal storage.
*
* Since a topic is being used to ferry notifications about new intra process
* messages between publishers and subscriptions, it is possible for that
* notification to be lost.
* It is also possible that a subscription which was available when publish was
* called will no longer exist once the notification gets posted.
* In both cases this might result in a message instance getting requested
* fewer times than expected.
* This is why the internal storage of this class is a ring buffer.
* That way if a message is orphaned it will eventually be dropped from storage
* when a new message instance is stored and will not result in a memory leak.
*
* However, since the storage system is finite, this also means that a message
* instance might get displaced by an incoming message instance before all
* interested parties have called take_intra_process_message.
* Because of this the size of the internal storage should be carefully
* considered.
*
* /TODO(wjwwood): update to include information about handling latching.
* /TODO(wjwwood): consider thread safety of the class.
*
* This class is neither CopyConstructable nor CopyAssignable.
*/
class IntraProcessManager
{
private:
RCLCPP_DISABLE_COPY(IntraProcessManager);
public:
RCLCPP_SMART_PTR_DEFINITIONS(IntraProcessManager);
RCLCPP_PUBLIC
explicit IntraProcessManager(
IntraProcessManagerImplBase::SharedPtr state = create_default_impl());
RCLCPP_PUBLIC
virtual ~IntraProcessManager();
/// Register a subscription with the manager, returns subscriptions unique id.
/* In addition to generating a unique intra process id for the subscription,
* this method also stores the topic name of the subscription.
*
* This method is normally called during the creation of a subscription,
* but after it creates the internal intra process rmw_subscription_t.
*
* This method will allocate memory.
*
* \param subscription the Subscription to register.
* \return an unsigned 64-bit integer which is the subscription's unique id.
*/
RCLCPP_PUBLIC
uint64_t
add_subscription(subscription::SubscriptionBase::SharedPtr subscription);
/// Unregister a subscription using the subscription's unique id.
/* This method does not allocate memory.
*
* \param intra_process_subscription_id id of the subscription to remove.
*/
RCLCPP_PUBLIC
void
remove_subscription(uint64_t intra_process_subscription_id);
/// Register a publisher with the manager, returns the publisher unique id.
/* In addition to generating and returning a unique id for the publisher,
* this method creates internal ring buffer storage for "in-flight" intra
* process messages which are stored when store_intra_process_message is
* called with this publisher's unique id.
*
* The buffer_size must be less than or equal to the max uint64_t value.
* If the buffer_size is 0 then a buffer size is calculated using the
* publisher's QoS settings.
* The default is to use the depth field of the publisher's QoS.
* TODO(wjwwood): Consider doing depth *= 1.2, round up, or similar.
* TODO(wjwwood): Consider what to do for keep all.
*
* This method is templated on the publisher's message type so that internal
* storage of the same type can be allocated.
*
* This method will allocate memory.
*
* \param publisher publisher to be registered with the manager.
* \param buffer_size if 0 (default) a size is calculated based on the QoS.
* \return an unsigned 64-bit integer which is the publisher's unique id.
*/
template<typename MessageT, typename Alloc>
uint64_t
add_publisher(typename publisher::Publisher<MessageT, Alloc>::SharedPtr publisher,
size_t buffer_size = 0)
{
auto id = IntraProcessManager::get_next_unique_id();
size_t size = buffer_size > 0 ? buffer_size : publisher->get_queue_size();
auto mrb = mapped_ring_buffer::MappedRingBuffer<MessageT,
typename publisher::Publisher<MessageT, Alloc>::MessageAlloc>::make_shared(
size, publisher->get_allocator());
impl_->add_publisher(id, publisher, mrb, size);
return id;
}
/// Unregister a publisher using the publisher's unique id.
/* This method does not allocate memory.
*
* \param intra_process_publisher_id id of the publisher to remove.
*/
RCLCPP_PUBLIC
void
remove_publisher(uint64_t intra_process_publisher_id);
/// Store a message in the manager, and return the message sequence number.
/* The given message is stored in internal storage using the given publisher
* id and the newly generated message sequence, which is also returned.
* The combination of publisher id and message sequence number can later
* be used with a subscription id to retrieve the message by calling
* take_intra_process_message.
* The number of times take_intra_process_message can be called with this
* unique pair of id's is determined by the number of subscriptions currently
* subscribed to the same topic and which share the same Context, i.e. once
* for each subscription which should receive the intra process message.
*
* The ownership of the incoming message is transfered to the internal
* storage in order to avoid copying the message data.
* Therefore, the message parameter will no longer contain the original
* message after calling this method.
* Instead it will either be a nullptr or it will contain the ownership of
* the message instance which was displaced.
* If the message parameter is not equal to nullptr after calling this method
* then a message was prematurely displaced, i.e. take_intra_process_message
* had not been called on it as many times as was expected.
*
* This method can throw an exception if the publisher id is not found or
* if the publisher shared_ptr given to add_publisher has gone out of scope.
*
* This method does allocate memory.
*
* \param intra_process_publisher_id the id of the publisher of this message.
* \param message the message that is being stored.
* \return the message sequence number.
*/
template<typename MessageT, typename Alloc = std::allocator<void>,
typename Deleter = std::default_delete<MessageT>>
uint64_t
store_intra_process_message(
uint64_t intra_process_publisher_id,
std::unique_ptr<MessageT, Deleter> & message)
{
using MRBMessageAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<MessageT>;
using TypedMRB = typename mapped_ring_buffer::MappedRingBuffer<MessageT, MRBMessageAlloc>;
uint64_t message_seq = 0;
mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer = impl_->get_publisher_info_for_id(
intra_process_publisher_id, message_seq);
typename TypedMRB::SharedPtr typed_buffer = std::static_pointer_cast<TypedMRB>(buffer);
if (!typed_buffer) {
throw std::runtime_error("Typecast failed due to incorrect message type");
}
// Insert the message into the ring buffer using the message_seq to identify it.
bool did_replace = typed_buffer->push_and_replace(message_seq, message);
// TODO(wjwwood): do something when a message was displaced. log debug?
(void)did_replace; // Avoid unused variable warning.
impl_->store_intra_process_message(intra_process_publisher_id, message_seq);
// Return the message sequence which is sent to the subscription.
return message_seq;
}
/// Take an intra process message.
/* The intra_process_publisher_id and message_sequence_number parameters
* uniquely identify a message instance, which should be taken.
*
* The requesting_subscriptions_intra_process_id parameter is used to make
* sure the requesting subscription was intended to receive this message
* instance.
* This check is made because it could happen that the requester
* comes up after the publish event, so it still receives the notification of
* a new intra process message, but it wasn't registered with the manager at
* the time of publishing, causing it to take when it wasn't intended.
* This should be avioded unless latching-like behavior is involved.
*
* The message parameter is used to store the taken message.
* On the last expected call to this method, the ownership is transfered out
* of internal storage and into the message parameter.
* On all previous calls a copy of the internally stored message is made and
* the ownership of the copy is transfered to the message parameter.
* TODO(wjwwood): update this documentation when latching is supported.
*
* The message parameter can be set to nullptr if:
*
* - The publisher id is not found.
* - The message sequence is not found for the given publisher id.
* - The requesting subscription's id is not in the list of intended takers.
* - The requesting subscription's id has been used before with this message.
*
* This method may allocate memory to copy the stored message.
*
* \param intra_process_publisher_id the id of the message's publisher.
* \param message_sequence_number the sequence number of the message.
* \param requesting_subscriptions_intra_process_id the subscription's id.
* \param message the message typed unique_ptr used to return the message.
*/
template<typename MessageT, typename Alloc = std::allocator<void>,
typename Deleter = std::default_delete<MessageT>>
void
take_intra_process_message(
uint64_t intra_process_publisher_id,
uint64_t message_sequence_number,
uint64_t requesting_subscriptions_intra_process_id,
std::unique_ptr<MessageT, Deleter> & message)
{
using MRBMessageAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<MessageT>;
using TypedMRB = mapped_ring_buffer::MappedRingBuffer<MessageT, MRBMessageAlloc>;
message = nullptr;
size_t target_subs_size = 0;
mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer = impl_->take_intra_process_message(
intra_process_publisher_id,
message_sequence_number,
requesting_subscriptions_intra_process_id,
target_subs_size
);
typename TypedMRB::SharedPtr typed_buffer = std::static_pointer_cast<TypedMRB>(buffer);
if (!typed_buffer) {
return;
}
// Return a copy or the unique_ptr (ownership) depending on how many subscriptions are left.
if (target_subs_size) {
// There are more subscriptions to serve, return a copy.
typed_buffer->get_copy_at_key(message_sequence_number, message);
} else {
// This is the last one to be returned, transfer ownership.
typed_buffer->pop_at_key(message_sequence_number, message);
}
}
/// Return true if the given rmw_gid_t matches any stored Publishers.
RCLCPP_PUBLIC
bool
matches_any_publishers(const rmw_gid_t * id) const;
private:
RCLCPP_PUBLIC
static uint64_t
get_next_unique_id();
IntraProcessManagerImplBase::SharedPtr impl_;
};
} // namespace intra_process_manager
} // namespace rclcpp
#endif // RCLCPP__INTRA_PROCESS_MANAGER_HPP_

View File

@@ -1,295 +0,0 @@
// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__INTRA_PROCESS_MANAGER_IMPL_HPP_
#define RCLCPP__INTRA_PROCESS_MANAGER_IMPL_HPP_
#include <algorithm>
#include <atomic>
#include <functional>
#include <limits>
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include "rclcpp/macros.hpp"
#include "rclcpp/mapped_ring_buffer.hpp"
#include "rclcpp/publisher.hpp"
#include "rclcpp/subscription.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace intra_process_manager
{
class IntraProcessManagerImplBase
{
public:
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(IntraProcessManagerImplBase);
IntraProcessManagerImplBase() = default;
~IntraProcessManagerImplBase() = default;
virtual void
add_subscription(uint64_t id, subscription::SubscriptionBase::SharedPtr subscription) = 0;
virtual void
remove_subscription(uint64_t intra_process_subscription_id) = 0;
virtual void add_publisher(uint64_t id,
publisher::PublisherBase::WeakPtr publisher,
mapped_ring_buffer::MappedRingBufferBase::SharedPtr mrb,
size_t size) = 0;
virtual void
remove_publisher(uint64_t intra_process_publisher_id) = 0;
virtual mapped_ring_buffer::MappedRingBufferBase::SharedPtr
get_publisher_info_for_id(
uint64_t intra_process_publisher_id,
uint64_t & message_seq) = 0;
virtual void
store_intra_process_message(uint64_t intra_process_publisher_id, uint64_t message_seq) = 0;
virtual mapped_ring_buffer::MappedRingBufferBase::SharedPtr
take_intra_process_message(uint64_t intra_process_publisher_id,
uint64_t message_sequence_number,
uint64_t requesting_subscriptions_intra_process_id,
size_t & size) = 0;
virtual bool
matches_any_publishers(const rmw_gid_t * id) const = 0;
private:
RCLCPP_DISABLE_COPY(IntraProcessManagerImplBase);
};
template<typename Allocator = std::allocator<void>>
class IntraProcessManagerImpl : public IntraProcessManagerImplBase
{
public:
IntraProcessManagerImpl() = default;
~IntraProcessManagerImpl() = default;
void
add_subscription(uint64_t id, subscription::SubscriptionBase::SharedPtr subscription)
{
subscriptions_[id] = subscription;
subscription_ids_by_topic_[subscription->get_topic_name()].insert(id);
}
void
remove_subscription(uint64_t intra_process_subscription_id)
{
subscriptions_.erase(intra_process_subscription_id);
for (auto & pair : subscription_ids_by_topic_) {
pair.second.erase(intra_process_subscription_id);
}
// Iterate over all publisher infos and all stored subscription id's and
// remove references to this subscription's id.
for (auto & publisher_pair : publishers_) {
for (auto & sub_pair : publisher_pair.second.target_subscriptions_by_message_sequence) {
sub_pair.second.erase(intra_process_subscription_id);
}
}
}
void add_publisher(uint64_t id,
publisher::PublisherBase::WeakPtr publisher,
mapped_ring_buffer::MappedRingBufferBase::SharedPtr mrb,
size_t size)
{
publishers_[id].publisher = publisher;
// As long as the size of the ring buffer is less than the max sequence number, we're safe.
if (size > std::numeric_limits<uint64_t>::max()) {
throw std::invalid_argument("the calculated buffer size is too large");
}
publishers_[id].sequence_number.store(0);
publishers_[id].buffer = mrb;
publishers_[id].target_subscriptions_by_message_sequence.reserve(size);
}
void
remove_publisher(uint64_t intra_process_publisher_id)
{
publishers_.erase(intra_process_publisher_id);
}
// return message_seq and mrb
mapped_ring_buffer::MappedRingBufferBase::SharedPtr
get_publisher_info_for_id(
uint64_t intra_process_publisher_id,
uint64_t & message_seq)
{
std::lock_guard<std::mutex> lock(runtime_mutex_);
auto it = publishers_.find(intra_process_publisher_id);
if (it == publishers_.end()) {
throw std::runtime_error("get_publisher_info_for_id called with invalid publisher id");
}
PublisherInfo & info = it->second;
// Calculate the next message sequence number.
message_seq = info.sequence_number.fetch_add(1);
return info.buffer;
}
void
store_intra_process_message(uint64_t intra_process_publisher_id, uint64_t message_seq)
{
std::lock_guard<std::mutex> lock(runtime_mutex_);
auto it = publishers_.find(intra_process_publisher_id);
if (it == publishers_.end()) {
throw std::runtime_error("store_intra_process_message called with invalid publisher id");
}
PublisherInfo & info = it->second;
auto publisher = info.publisher.lock();
if (!publisher) {
throw std::runtime_error("publisher has unexpectedly gone out of scope");
}
// Figure out what subscriptions should receive the message.
auto & destined_subscriptions = subscription_ids_by_topic_[publisher->get_topic_name()];
// Store the list for later comparison.
if (info.target_subscriptions_by_message_sequence.count(message_seq) == 0) {
info.target_subscriptions_by_message_sequence.emplace(
message_seq, AllocSet(std::less<uint64_t>(), uint64_allocator));
} else {
info.target_subscriptions_by_message_sequence[message_seq].clear();
}
std::copy(
destined_subscriptions.begin(), destined_subscriptions.end(),
// Memory allocation occurs in info.target_subscriptions_by_message_sequence[message_seq]
std::inserter(
info.target_subscriptions_by_message_sequence[message_seq],
// This ends up only being a hint to std::set, could also be .begin().
info.target_subscriptions_by_message_sequence[message_seq].end()
)
);
}
mapped_ring_buffer::MappedRingBufferBase::SharedPtr
take_intra_process_message(uint64_t intra_process_publisher_id,
uint64_t message_sequence_number,
uint64_t requesting_subscriptions_intra_process_id,
size_t & size
)
{
std::lock_guard<std::mutex> lock(runtime_mutex_);
PublisherInfo * info;
{
auto it = publishers_.find(intra_process_publisher_id);
if (it == publishers_.end()) {
// Publisher is either invalid or no longer exists.
return 0;
}
info = &it->second;
}
// Figure out how many subscriptions are left.
AllocSet * target_subs;
{
auto it = info->target_subscriptions_by_message_sequence.find(message_sequence_number);
if (it == info->target_subscriptions_by_message_sequence.end()) {
// Message is no longer being stored by this publisher.
return 0;
}
target_subs = &it->second;
}
{
auto it = std::find(
target_subs->begin(), target_subs->end(),
requesting_subscriptions_intra_process_id);
if (it == target_subs->end()) {
// This publisher id/message seq pair was not intended for this subscription.
return 0;
}
target_subs->erase(it);
}
size = target_subs->size();
return info->buffer;
}
bool
matches_any_publishers(const rmw_gid_t * id) const
{
for (auto & publisher_pair : publishers_) {
auto publisher = publisher_pair.second.publisher.lock();
if (!publisher) {
continue;
}
if (*publisher.get() == id) {
return true;
}
}
return false;
}
private:
RCLCPP_DISABLE_COPY(IntraProcessManagerImpl);
template<typename T>
using RebindAlloc = typename std::allocator_traits<Allocator>::template rebind_alloc<T>;
RebindAlloc<uint64_t> uint64_allocator;
using AllocSet = std::set<uint64_t, std::less<uint64_t>, RebindAlloc<uint64_t>>;
using SubscriptionMap = std::unordered_map<uint64_t, subscription::SubscriptionBase::WeakPtr,
std::hash<uint64_t>, std::equal_to<uint64_t>,
RebindAlloc<std::pair<const uint64_t, subscription::SubscriptionBase::WeakPtr>>>;
using IDTopicMap = std::map<std::string, AllocSet,
std::less<std::string>, RebindAlloc<std::pair<std::string, AllocSet>>>;
SubscriptionMap subscriptions_;
IDTopicMap subscription_ids_by_topic_;
struct PublisherInfo
{
RCLCPP_DISABLE_COPY(PublisherInfo);
PublisherInfo() = default;
publisher::PublisherBase::WeakPtr publisher;
std::atomic<uint64_t> sequence_number;
mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer;
using TargetSubscriptionsMap = std::unordered_map<uint64_t, AllocSet,
std::hash<uint64_t>, std::equal_to<uint64_t>,
RebindAlloc<std::pair<const uint64_t, AllocSet>>>;
TargetSubscriptionsMap target_subscriptions_by_message_sequence;
};
using PublisherMap = std::unordered_map<uint64_t, PublisherInfo,
std::hash<uint64_t>, std::equal_to<uint64_t>,
RebindAlloc<std::pair<const uint64_t, PublisherInfo>>>;
PublisherMap publishers_;
std::mutex runtime_mutex_;
};
RCLCPP_PUBLIC
IntraProcessManagerImplBase::SharedPtr
create_default_impl();
} // namespace intra_process_manager
} // namespace rclcpp
#endif // RCLCPP__INTRA_PROCESS_MANAGER_IMPL_HPP_

View File

@@ -0,0 +1,34 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__INTRA_PROCESS_SETTING_HPP_
#define RCLCPP__INTRA_PROCESS_SETTING_HPP_
namespace rclcpp
{
/// Used as argument in create_publisher and create_subscriber.
enum class IntraProcessSetting
{
/// Explicitly enable intraprocess comm at publisher/subscription level.
Enable,
/// Explicitly disable intraprocess comm at publisher/subscription level.
Disable,
/// Take intraprocess configuration from the node.
NodeDefault
};
} // namespace rclcpp
#endif // RCLCPP__INTRA_PROCESS_SETTING_HPP_

View File

@@ -0,0 +1,207 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__LOANED_MESSAGE_HPP_
#define RCLCPP__LOANED_MESSAGE_HPP_
#include <memory>
#include <utility>
#include "rclcpp/allocator/allocator_common.hpp"
#include "rclcpp/logging.hpp"
#include "rclcpp/publisher_base.hpp"
#include "rcl/allocator.h"
#include "rcl/publisher.h"
namespace rclcpp
{
template<typename MessageT, typename AllocatorT = std::allocator<void>>
class LoanedMessage
{
using MessageAllocatorTraits = rclcpp::allocator::AllocRebind<MessageT, AllocatorT>;
using MessageAllocator = typename MessageAllocatorTraits::allocator_type;
public:
/// Constructor of the LoanedMessage class.
/**
* The constructor of this class allocates memory for a given message type
* and associates this with a given publisher.
*
* Given the publisher instance, a case differentiation is being performaned
* which decides whether the underlying middleware is able to allocate the appropriate
* memory for this message type or not.
* In the case that the middleware can not loan messages, the passed in allocator instance
* is being used to allocate the message within the scope of this class.
* Otherwise, the allocator is being ignored and the allocation is solely performaned
* in the underlying middleware with its appropriate allocation strategy.
* The need for this arises as the user code can be written explicitly targeting a middleware
* capable of loaning messages.
* However, this user code is ought to be usable even when dynamically linked against
* a middleware which doesn't support message loaning in which case the allocator will be used.
*
* \param pub rclcpp::Publisher instance to which the memory belongs
* \param allocator Allocator instance in case middleware can not allocate messages
*/
LoanedMessage(
const rclcpp::PublisherBase & pub,
std::allocator<MessageT> allocator)
: pub_(pub),
message_(nullptr),
message_allocator_(std::move(allocator))
{
if (pub_.can_loan_messages()) {
void * message_ptr = nullptr;
auto ret = rcl_borrow_loaned_message(
pub_.get_publisher_handle(),
rosidl_typesupport_cpp::get_message_type_support_handle<MessageT>(),
&message_ptr);
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret);
}
message_ = static_cast<MessageT *>(message_ptr);
} else {
RCLCPP_INFO_ONCE(
rclcpp::get_logger("rclcpp"),
"Currently used middleware can't loan messages. Local allocator will be used.");
message_ = message_allocator_.allocate(1);
new (message_) MessageT();
}
}
/// Constructor of the LoanedMessage class.
/**
* The constructor of this class allocates memory for a given message type
* and associates this with a given publisher.
*
* Given the publisher instance, a case differentiation is being performaned
* which decides whether the underlying middleware is able to allocate the appropriate
* memory for this message type or not.
* In the case that the middleware can not loan messages, the passed in allocator instance
* is being used to allocate the message within the scope of this class.
* Otherwise, the allocator is being ignored and the allocation is solely performaned
* in the underlying middleware with its appropriate allocation strategy.
* The need for this arises as the user code can be written explicitly targeting a middleware
* capable of loaning messages.
* However, this user code is ought to be usable even when dynamically linked against
* a middleware which doesn't support message loaning in which case the allocator will be used.
*
* \param pub rclcpp::Publisher instance to which the memory belongs
* \param allocator Allocator instance in case middleware can not allocate messages
*/
LoanedMessage(
const rclcpp::PublisherBase * pub,
std::shared_ptr<std::allocator<MessageT>> allocator)
: LoanedMessage(*pub, *allocator)
{}
/// Move semantic for RVO
LoanedMessage(LoanedMessage<MessageT> && other)
: pub_(std::move(other.pub_)),
message_(std::move(other.message_)),
message_allocator_(std::move(other.message_allocator_))
{}
/// Destructor of the LoanedMessage class.
/**
* The destructor has the explicit task to return the allocated memory for its message
* instance.
* If the message was previously allocated via the middleware, the message is getting
* returned to the middleware to cleanly destroy the allocation.
* In the case that the local allocator instance was used, the same instance is then
* being used to destroy the allocated memory.
*
* The contract here is that the memory for this message is valid as long as this instance
* of the LoanedMessage class is alive.
*/
virtual ~LoanedMessage()
{
auto error_logger = rclcpp::get_logger("LoanedMessage");
if (message_ == nullptr) {
return;
}
if (pub_.can_loan_messages()) {
// return allocated memory to the middleware
auto ret =
rcl_return_loaned_message_from_publisher(pub_.get_publisher_handle(), message_);
if (ret != RCL_RET_OK) {
RCLCPP_ERROR(
error_logger, "rcl_deallocate_loaned_message failed: %s", rcl_get_error_string().str);
rcl_reset_error();
}
} else {
// call destructor before deallocating
message_->~MessageT();
message_allocator_.deallocate(message_, 1);
}
message_ = nullptr;
}
/// Validate if the message was correctly allocated.
/**
* The allocated memory might not be always consistent and valid.
* Reasons why this could fail is that an allocation step was failing,
* e.g. just like malloc could fail or a maximum amount of previously allocated
* messages is exceeded in which case the loaned messages have to be returned
* to the middleware prior to be able to allocate a new one.
*/
bool is_valid() const
{
return message_ != nullptr;
}
/// Access the ROS message instance.
/**
* A call to `get()` will return a mutable reference to the underlying ROS message instance.
* This allows a user to modify the content of the message prior to publishing it.
*
* If this reference is copied, the memory for this copy is no longer managed
* by the LoanedMessage instance and has to be cleanup individually.
*/
MessageT & get() const
{
return *message_;
}
/// Release ownership of the ROS message instance.
/**
* A call to `release()` will unmanage the memory for the ROS message.
* That means that the destructor of this class will not free the memory on scope exit.
*
* \return Raw pointer to the message instance.
*/
MessageT * release()
{
auto msg = message_;
message_ = nullptr;
return msg;
}
protected:
const rclcpp::PublisherBase & pub_;
MessageT * message_;
MessageAllocator message_allocator_;
/// Deleted copy constructor to preserve memory integrity.
LoanedMessage(const LoanedMessage<MessageT> & other) = delete;
};
} // namespace rclcpp
#endif // RCLCPP__LOANED_MESSAGE_HPP_

View File

@@ -0,0 +1,145 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__LOGGER_HPP_
#define RCLCPP__LOGGER_HPP_
#include <memory>
#include <string>
#include "rclcpp/visibility_control.hpp"
#include "rcl/node.h"
/**
* \def RCLCPP_LOGGING_ENABLED
* When this define evaluates to true (default), logger factory functions will
* behave normally.
* When false, logger factory functions will create dummy loggers to avoid
* computational expense in manipulating objects.
* This should be used in combination with `RCLCPP_LOG_MIN_SEVERITY` to compile
* out logging macros.
*/
// TODO(dhood): determine this automatically from `RCLCPP_LOG_MIN_SEVERITY`
#ifndef RCLCPP_LOGGING_ENABLED
#define RCLCPP_LOGGING_ENABLED 1
#endif
namespace rclcpp
{
// Forward declaration is used for friend statement.
namespace node_interfaces
{
class NodeLogging;
}
class Logger;
/// Return a named logger.
/**
* The returned logger's name will include any naming conventions, such as a
* name prefix.
* Currently there are no such naming conventions but they may be introduced in
* the future.
*
* \param[in] name the name of the logger
* \return a logger with the fully-qualified name including naming conventions, or
* \return a dummy logger if logging is disabled.
*/
RCLCPP_PUBLIC
Logger
get_logger(const std::string & name);
/// Return a named logger using an rcl_node_t.
/**
* This is a convenience function that does error checking and returns the node
* logger name, or "rclcpp" if it is unable to get the node name.
*
* \param[in] node the rcl node from which to get the logger name
* \return a logger based on the node name, or "rclcpp" if there's an error
*/
RCLCPP_PUBLIC
Logger
get_node_logger(const rcl_node_t * node);
class Logger
{
private:
friend Logger rclcpp::get_logger(const std::string & name);
friend ::rclcpp::node_interfaces::NodeLogging;
/// Constructor of a dummy logger.
/**
* This is used when logging is disabled: see `RCLCPP_LOGGING_ENABLED`.
* This cannot be called directly, see `rclcpp::get_logger` instead.
*/
Logger()
: name_(nullptr) {}
/// Constructor of a named logger.
/**
* This cannot be called directly, see `rclcpp::get_logger` instead.
*/
explicit Logger(const std::string & name)
: name_(new std::string(name)) {}
std::shared_ptr<const std::string> name_;
public:
RCLCPP_PUBLIC
Logger(const Logger &) = default;
/// Get the name of this logger.
/**
* \return the full name of the logger including any prefixes, or
* \return `nullptr` if this logger is invalid (e.g. because logging is
* disabled).
*/
RCLCPP_PUBLIC
const char *
get_name() const
{
if (!name_) {
return nullptr;
}
return name_->c_str();
}
/// Return a logger that is a descendant of this logger.
/**
* The child logger's full name will include any hierarchy conventions that
* indicate it is a descendant of this logger.
* For example, ```get_logger('abc').get_child('def')``` will return a logger
* with name `abc.def`.
*
* \param[in] suffix the child logger's suffix
* \return a logger with the fully-qualified name including the suffix, or
* \return a dummy logger if this logger is invalid (e.g. because logging is
* disabled).
*/
RCLCPP_PUBLIC
Logger
get_child(const std::string & suffix)
{
if (!name_) {
return Logger();
}
return Logger(*name_ + "." + suffix);
}
};
} // namespace rclcpp
#endif // RCLCPP__LOGGER_HPP_

View File

@@ -18,7 +18,8 @@
#ifndef RCLCPP__MACROS_HPP_
#define RCLCPP__MACROS_HPP_
/* Disables the copy constructor and operator= for the given class.
/**
* Disables the copy constructor and operator= for the given class.
*
* Use in the private section of the class.
*/
@@ -26,31 +27,51 @@
__VA_ARGS__(const __VA_ARGS__ &) = delete; \
__VA_ARGS__ & operator=(const __VA_ARGS__ &) = delete;
/* Defines aliases and static functions for using the Class with smart pointers.
/**
* Defines aliases and static functions for using the Class with smart pointers.
*
* Use in the public section of the class.
* Make sure to include <memory> in the header when using this.
* Make sure to include `<memory>` in the header when using this.
*/
#define RCLCPP_SMART_PTR_DEFINITIONS(...) \
RCLCPP_SHARED_PTR_DEFINITIONS(__VA_ARGS__) \
RCLCPP_WEAK_PTR_DEFINITIONS(__VA_ARGS__) \
RCLCPP_UNIQUE_PTR_DEFINITIONS(__VA_ARGS__)
/* Defines aliases and static functions for using the Class with smart pointers.
/**
* Defines aliases and static functions for using the Class with smart pointers.
*
* Same as RCLCPP_SMART_PTR_DEFINITIONS expect it excludes the static
* Same as RCLCPP_SMART_PTR_DEFINITIONS except it excludes the static
* Class::make_unique() method definition which does not work on classes which
* are not CopyConstructable.
*
* Use in the public section of the class.
* Make sure to include <memory> in the header when using this.
* Make sure to include `<memory>` in the header when using this.
*/
#define RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(...) \
RCLCPP_SHARED_PTR_DEFINITIONS(__VA_ARGS__) \
RCLCPP_WEAK_PTR_DEFINITIONS(__VA_ARGS__) \
__RCLCPP_UNIQUE_PTR_ALIAS(__VA_ARGS__)
#define __RCLCPP_SHARED_PTR_ALIAS(...) using SharedPtr = std::shared_ptr<__VA_ARGS__>;
/**
* Defines aliases only for using the Class with smart pointers.
*
* Same as RCLCPP_SMART_PTR_DEFINITIONS except it excludes the static
* method definitions which do not work on pure virtual classes and classes
* which are not CopyConstructable.
*
* Use in the public section of the class.
* Make sure to include `<memory>` in the header when using this.
*/
#define RCLCPP_SMART_PTR_ALIASES_ONLY(...) \
__RCLCPP_SHARED_PTR_ALIAS(__VA_ARGS__) \
__RCLCPP_WEAK_PTR_ALIAS(__VA_ARGS__) \
__RCLCPP_UNIQUE_PTR_ALIAS(__VA_ARGS__) \
__RCLCPP_MAKE_SHARED_DEFINITION(__VA_ARGS__)
#define __RCLCPP_SHARED_PTR_ALIAS(...) \
using SharedPtr = std::shared_ptr<__VA_ARGS__>; \
using ConstSharedPtr = std::shared_ptr<const __VA_ARGS__>;
#define __RCLCPP_MAKE_SHARED_DEFINITION(...) \
template<typename ... Args> \
@@ -65,7 +86,9 @@
__RCLCPP_SHARED_PTR_ALIAS(__VA_ARGS__) \
__RCLCPP_MAKE_SHARED_DEFINITION(__VA_ARGS__)
#define __RCLCPP_WEAK_PTR_ALIAS(...) using WeakPtr = std::weak_ptr<__VA_ARGS__>;
#define __RCLCPP_WEAK_PTR_ALIAS(...) \
using WeakPtr = std::weak_ptr<__VA_ARGS__>; \
using ConstWeakPtr = std::weak_ptr<const __VA_ARGS__>;
/// Defines aliases and static functions for using the Class with weak_ptrs.
#define RCLCPP_WEAK_PTR_DEFINITIONS(...) __RCLCPP_WEAK_PTR_ALIAS(__VA_ARGS__)
@@ -88,6 +111,4 @@
#define RCLCPP_STRING_JOIN(arg1, arg2) RCLCPP_DO_STRING_JOIN(arg1, arg2)
#define RCLCPP_DO_STRING_JOIN(arg1, arg2) arg1 ## arg2
#define RCLCPP_INFO(Args) std::cout << Args << std::endl;
#endif // RCLCPP__MACROS_HPP_

View File

@@ -1,241 +0,0 @@
// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__MAPPED_RING_BUFFER_HPP_
#define RCLCPP__MAPPED_RING_BUFFER_HPP_
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <mutex>
#include <utility>
#include <vector>
#include "rclcpp/allocator/allocator_common.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace mapped_ring_buffer
{
class RCLCPP_PUBLIC MappedRingBufferBase
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(MappedRingBufferBase);
};
/// Ring buffer container of unique_ptr's of T, which can be accessed by a key.
/* T must be a CopyConstructable and CopyAssignable.
* This class can be used in a container by using the base class MappedRingBufferBase.
* This class must have a positive, non-zero size.
* This class cannot be resized nor can it reserve additional space after construction.
* This class is not CopyConstructable nor CopyAssignable.
*
* The key's are not guaranteed to be unique because push_and_replace does not
* check for colliding keys.
* It is up to the user to only use unique keys.
* A side effect of this is that when get_copy_at_key or pop_at_key are called,
* they return the first encountered instance of the key.
* But iteration does not begin with the ring buffer's head, and therefore
* there is no guarantee on which value is returned if a key is used multiple
* times.
*/
template<typename T, typename Alloc = std::allocator<void>>
class MappedRingBuffer : public MappedRingBufferBase
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(MappedRingBuffer<T, Alloc>);
using ElemAllocTraits = allocator::AllocRebind<T, Alloc>;
using ElemAlloc = typename ElemAllocTraits::allocator_type;
using ElemDeleter = allocator::Deleter<ElemAlloc, T>;
using ElemUniquePtr = std::unique_ptr<T, ElemDeleter>;
/// Constructor.
/* The constructor will allocate memory while reserving space.
*
* \param size size of the ring buffer; must be positive and non-zero.
*/
explicit MappedRingBuffer(size_t size, std::shared_ptr<Alloc> allocator = nullptr)
: elements_(size), head_(0)
{
if (size == 0) {
throw std::invalid_argument("size must be a positive, non-zero value");
}
if (!allocator) {
allocator_ = std::make_shared<ElemAlloc>();
} else {
allocator_ = std::make_shared<ElemAlloc>(*allocator.get());
}
}
virtual ~MappedRingBuffer() {}
/// Return a copy of the value stored in the ring buffer at the given key.
/* The key is matched if an element in the ring buffer has a matching key.
* This method will allocate in order to return a copy.
*
* The key is not guaranteed to be unique, see the class docs for more.
*
* The contents of value before the method is called are discarded.
*
* \param key the key associated with the stored value
* \param value if the key is found, the value is stored in this parameter
*/
void
get_copy_at_key(uint64_t key, ElemUniquePtr & value)
{
std::lock_guard<std::mutex> lock(data_mutex_);
auto it = get_iterator_of_key(key);
value = nullptr;
if (it != elements_.end() && it->in_use) {
auto ptr = ElemAllocTraits::allocate(*allocator_.get(), 1);
ElemAllocTraits::construct(*allocator_.get(), ptr, *it->value);
value = ElemUniquePtr(ptr);
}
}
/// Return ownership of the value stored in the ring buffer, leaving a copy.
/* The key is matched if an element in the ring bufer has a matching key.
* This method will allocate in order to store a copy.
*
* The key is not guaranteed to be unique, see the class docs for more.
*
* The ownership of the currently stored object is returned, but a copy is
* made and stored in its place.
* This means that multiple calls to this function for a particular element
* will result in returning the copied and stored object not the original.
* This also means that later calls to pop_at_key will not return the
* originally stored object, since it was returned by the first call to this
* method.
*
* The contents of value before the method is called are discarded.
*
* \param key the key associated with the stored value
* \param value if the key is found, the value is stored in this parameter
*/
void
get_ownership_at_key(uint64_t key, ElemUniquePtr & value)
{
std::lock_guard<std::mutex> lock(data_mutex_);
auto it = get_iterator_of_key(key);
value = nullptr;
if (it != elements_.end() && it->in_use) {
// Make a copy.
auto ptr = ElemAllocTraits::allocate(*allocator_.get(), 1);
ElemAllocTraits::construct(*allocator_.get(), ptr, *it->value);
auto copy = ElemUniquePtr(ptr);
// Return the original.
value.swap(it->value);
// Store the copy.
it->value.swap(copy);
}
}
/// Return ownership of the value stored in the ring buffer at the given key.
/* The key is matched if an element in the ring buffer has a matching key.
*
* The key is not guaranteed to be unique, see the class docs for more.
*
* The contents of value before the method is called are discarded.
*
* \param key the key associated with the stored value
* \param value if the key is found, the value is stored in this parameter
*/
void
pop_at_key(uint64_t key, ElemUniquePtr & value)
{
std::lock_guard<std::mutex> lock(data_mutex_);
auto it = get_iterator_of_key(key);
value = nullptr;
if (it != elements_.end() && it->in_use) {
value.swap(it->value);
it->in_use = false;
}
}
/// Insert a key-value pair, displacing an existing pair if necessary.
/* The key's uniqueness is not checked on insertion.
* It is up to the user to ensure the key is unique.
* This method should not allocate memory.
*
* After insertion, if a pair was replaced, then value will contain ownership
* of that displaced value. Otherwise it will be a nullptr.
*
* \param key the key associated with the value to be stored
* \param value the value to store, and optionally the value displaced
*/
bool
push_and_replace(uint64_t key, ElemUniquePtr & value)
{
std::lock_guard<std::mutex> lock(data_mutex_);
bool did_replace = elements_[head_].in_use;
elements_[head_].key = key;
elements_[head_].value.swap(value);
elements_[head_].in_use = true;
head_ = (head_ + 1) % elements_.size();
return did_replace;
}
bool
push_and_replace(uint64_t key, ElemUniquePtr && value)
{
ElemUniquePtr temp = std::move(value);
return push_and_replace(key, temp);
}
/// Return true if the key is found in the ring buffer, otherwise false.
bool
has_key(uint64_t key)
{
std::lock_guard<std::mutex> lock(data_mutex_);
return elements_.end() != get_iterator_of_key(key);
}
private:
RCLCPP_DISABLE_COPY(MappedRingBuffer<T, Alloc>);
struct element
{
uint64_t key;
ElemUniquePtr value;
bool in_use;
};
using VectorAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<element>;
typename std::vector<element, VectorAlloc>::iterator
get_iterator_of_key(uint64_t key)
{
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
auto it = std::find_if(elements_.begin(), elements_.end(), [key](element & e) -> bool {
return e.key == key && e.in_use;
});
// *INDENT-ON*
return it;
}
std::vector<element, VectorAlloc> elements_;
size_t head_;
std::shared_ptr<ElemAlloc> allocator_;
std::mutex data_mutex_;
};
} // namespace mapped_ring_buffer
} // namespace rclcpp
#endif // RCLCPP__MAPPED_RING_BUFFER_HPP_

View File

@@ -15,16 +15,17 @@
#ifndef RCLCPP__MEMORY_STRATEGY_HPP_
#define RCLCPP__MEMORY_STRATEGY_HPP_
#include <list>
#include <memory>
#include <vector>
#include "rcl/allocator.h"
#include "rcl/wait.h"
#include "rclcpp/any_executable.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/waitable.hpp"
namespace rclcpp
{
@@ -40,71 +41,107 @@ namespace memory_strategy
class RCLCPP_PUBLIC MemoryStrategy
{
public:
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(MemoryStrategy);
using WeakNodeVector = std::vector<std::weak_ptr<rclcpp::node::Node>>;
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(MemoryStrategy)
using WeakNodeList = std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>;
virtual bool collect_entities(const WeakNodeVector & weak_nodes) = 0;
virtual ~MemoryStrategy() = default;
virtual bool collect_entities(const WeakNodeList & weak_nodes) = 0;
virtual size_t number_of_ready_subscriptions() const = 0;
virtual size_t number_of_ready_services() const = 0;
virtual size_t number_of_ready_clients() const = 0;
virtual size_t number_of_ready_events() const = 0;
virtual size_t number_of_ready_timers() const = 0;
virtual size_t number_of_guard_conditions() const = 0;
virtual size_t number_of_waitables() const = 0;
virtual bool add_handles_to_waitset(rcl_wait_set_t * wait_set) = 0;
virtual void add_waitable_handle(const rclcpp::Waitable::SharedPtr & waitable) = 0;
virtual bool add_handles_to_wait_set(rcl_wait_set_t * wait_set) = 0;
virtual void clear_handles() = 0;
virtual void remove_null_handles(rcl_wait_set_t * wait_set) = 0;
/// Provide a newly initialized AnyExecutable object.
// \return Shared pointer to the fresh executable.
virtual rclcpp::executor::AnyExecutable::SharedPtr instantiate_next_executable() = 0;
virtual void add_guard_condition(const rcl_guard_condition_t * guard_condition) = 0;
virtual void remove_guard_condition(const rcl_guard_condition_t * guard_condition) = 0;
virtual void
get_next_subscription(rclcpp::executor::AnyExecutable::SharedPtr any_exec,
const WeakNodeVector & weak_nodes) = 0;
get_next_subscription(
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_service(rclcpp::executor::AnyExecutable::SharedPtr any_exec,
const WeakNodeVector & weak_nodes) = 0;
get_next_service(
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_client(rclcpp::executor::AnyExecutable::SharedPtr any_exec,
const WeakNodeVector & weak_nodes) = 0;
get_next_client(
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_timer(
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_waitable(
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual rcl_allocator_t
get_allocator() = 0;
static rclcpp::subscription::SubscriptionBase::SharedPtr
get_subscription_by_handle(const rcl_subscription_t * subscriber_handle,
const WeakNodeVector & weak_nodes);
static rclcpp::SubscriptionBase::SharedPtr
get_subscription_by_handle(
std::shared_ptr<const rcl_subscription_t> subscriber_handle,
const WeakNodeList & weak_nodes);
static rclcpp::service::ServiceBase::SharedPtr
get_service_by_handle(const rcl_service_t * service_handle, const WeakNodeVector & weak_nodes);
static rclcpp::ServiceBase::SharedPtr
get_service_by_handle(
std::shared_ptr<const rcl_service_t> service_handle,
const WeakNodeList & weak_nodes);
static rclcpp::client::ClientBase::SharedPtr
get_client_by_handle(const rcl_client_t * client_handle, const WeakNodeVector & weak_nodes);
static rclcpp::ClientBase::SharedPtr
get_client_by_handle(
std::shared_ptr<const rcl_client_t> client_handle,
const WeakNodeList & weak_nodes);
static rclcpp::node::Node::SharedPtr
get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr group,
const WeakNodeVector & 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::callback_group::CallbackGroup::SharedPtr
static rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
get_node_by_group(
rclcpp::CallbackGroup::SharedPtr group,
const WeakNodeList & weak_nodes);
static rclcpp::CallbackGroup::SharedPtr
get_group_by_subscription(
rclcpp::subscription::SubscriptionBase::SharedPtr subscription,
const WeakNodeVector & weak_nodes);
rclcpp::SubscriptionBase::SharedPtr subscription,
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
static rclcpp::CallbackGroup::SharedPtr
get_group_by_service(
rclcpp::service::ServiceBase::SharedPtr service,
const WeakNodeVector & weak_nodes);
rclcpp::ServiceBase::SharedPtr service,
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
get_group_by_client(rclcpp::client::ClientBase::SharedPtr client,
const WeakNodeVector & weak_nodes);
static rclcpp::CallbackGroup::SharedPtr
get_group_by_client(
rclcpp::ClientBase::SharedPtr client,
const WeakNodeList & weak_nodes);
static rclcpp::CallbackGroup::SharedPtr
get_group_by_timer(
rclcpp::TimerBase::SharedPtr timer,
const WeakNodeList & weak_nodes);
static rclcpp::CallbackGroup::SharedPtr
get_group_by_waitable(
rclcpp::Waitable::SharedPtr waitable,
const WeakNodeList & weak_nodes);
};
} // namespace memory_strategy

View File

@@ -0,0 +1,52 @@
// Copyright 2020 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__MESSAGE_INFO_HPP_
#define RCLCPP__MESSAGE_INFO_HPP_
#include "rmw/types.h"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
/// Additional meta data about messages taken from subscriptions.
class RCLCPP_PUBLIC MessageInfo
{
public:
/// Default empty constructor.
MessageInfo() = default;
/// Conversion constructor, which is intentionally not marked as explicit.
// cppcheck-suppress noExplicitConstructor
MessageInfo(const rmw_message_info_t & rmw_message_info); // NOLINT(runtime/explicit)
virtual ~MessageInfo();
/// Return the message info as the underlying rmw message info type.
const rmw_message_info_t &
get_rmw_message_info() const;
/// Return the message info as the underlying rmw message info type.
rmw_message_info_t &
get_rmw_message_info();
private:
rmw_message_info_t rmw_message_info_;
};
} // namespace rclcpp
#endif // RCLCPP__MESSAGE_INFO_HPP_

View File

@@ -18,37 +18,61 @@
#include <memory>
#include <stdexcept>
#include "rcl/types.h"
#include "rclcpp/allocator/allocator_common.hpp"
#include "rclcpp/exceptions.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rcutils/logging_macros.h"
#include "rmw/serialized_message.h"
namespace rclcpp
{
namespace message_memory_strategy
{
/// Default allocation strategy for messages received by subscriptions.
// A message memory strategy must be templated on the type of the subscription it belongs to.
/** A message memory strategy must be templated on the type of the subscription it belongs to. */
template<typename MessageT, typename Alloc = std::allocator<void>>
class MessageMemoryStrategy
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(MessageMemoryStrategy);
RCLCPP_SMART_PTR_DEFINITIONS(MessageMemoryStrategy)
using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
using MessageAlloc = typename MessageAllocTraits::allocator_type;
using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;
using SerializedMessageAllocTraits = allocator::AllocRebind<rcl_serialized_message_t, Alloc>;
using SerializedMessageAlloc = typename SerializedMessageAllocTraits::allocator_type;
using SerializedMessageDeleter =
allocator::Deleter<SerializedMessageAlloc, rcl_serialized_message_t>;
using BufferAllocTraits = allocator::AllocRebind<char, Alloc>;
using BufferAlloc = typename BufferAllocTraits::allocator_type;
using BufferDeleter = allocator::Deleter<BufferAlloc, char>;
MessageMemoryStrategy()
{
message_allocator_ = std::make_shared<MessageAlloc>();
serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>();
buffer_allocator_ = std::make_shared<BufferAlloc>();
rcutils_allocator_ = allocator::get_rcl_allocator<char, BufferAlloc>(*buffer_allocator_.get());
}
explicit MessageMemoryStrategy(std::shared_ptr<Alloc> allocator)
{
message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>(*allocator.get());
buffer_allocator_ = std::make_shared<BufferAlloc>(*allocator.get());
rcutils_allocator_ = allocator::get_rcl_allocator<char, BufferAlloc>(*buffer_allocator_.get());
}
virtual ~MessageMemoryStrategy() = default;
/// Default factory method
static SharedPtr create_default()
{
@@ -56,21 +80,69 @@ public:
}
/// By default, dynamically allocate a new message.
// \return Shared pointer to the new message.
/** \return Shared pointer to the new message. */
virtual std::shared_ptr<MessageT> borrow_message()
{
return std::allocate_shared<MessageT, MessageAlloc>(*message_allocator_.get());
}
virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message(size_t capacity)
{
auto msg = new rcl_serialized_message_t;
*msg = rmw_get_zero_initialized_serialized_message();
auto ret = rmw_serialized_message_init(msg, capacity, &rcutils_allocator_);
if (ret != RCL_RET_OK) {
rclcpp::exceptions::throw_from_rcl_error(ret);
}
auto serialized_msg = std::shared_ptr<rcl_serialized_message_t>(
msg,
[](rmw_serialized_message_t * msg) {
auto fini_ret = rmw_serialized_message_fini(msg);
delete msg;
if (fini_ret != RCL_RET_OK) {
RCUTILS_LOG_ERROR_NAMED(
"rclcpp",
"failed to destroy serialized message: %s", rcl_get_error_string().str);
}
});
return serialized_msg;
}
virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message()
{
return borrow_serialized_message(default_buffer_capacity_);
}
virtual void set_default_buffer_capacity(size_t capacity)
{
default_buffer_capacity_ = capacity;
}
/// Release ownership of the message, which will deallocate it if it has no more owners.
// \param[in] Shared pointer to the message we are returning.
/** \param[in] msg Shared pointer to the message we are returning. */
virtual void return_message(std::shared_ptr<MessageT> & msg)
{
msg.reset();
}
virtual void return_serialized_message(std::shared_ptr<rcl_serialized_message_t> & serialized_msg)
{
serialized_msg.reset();
}
std::shared_ptr<MessageAlloc> message_allocator_;
MessageDeleter message_deleter_;
std::shared_ptr<SerializedMessageAlloc> serialized_message_allocator_;
SerializedMessageDeleter serialized_message_deleter_;
std::shared_ptr<BufferAlloc> buffer_allocator_;
BufferDeleter buffer_deleter_;
size_t default_buffer_capacity_ = 0;
rcutils_allocator_t rcutils_allocator_;
};
} // namespace message_memory_strategy

File diff suppressed because it is too large Load Diff

View File

@@ -33,11 +33,14 @@
#include "rcl/publisher.h"
#include "rcl/subscription.h"
#include "rcl_interfaces/msg/intra_process_message.hpp"
#include "rclcpp/contexts/default_context.hpp"
#include "rclcpp/intra_process_manager.hpp"
#include "rclcpp/create_client.hpp"
#include "rclcpp/create_publisher.hpp"
#include "rclcpp/create_service.hpp"
#include "rclcpp/create_subscription.hpp"
#include "rclcpp/detail/resolve_enable_topic_statistics.hpp"
#include "rclcpp/parameter.hpp"
#include "rclcpp/qos.hpp"
#include "rclcpp/type_support_decl.hpp"
#include "rclcpp/visibility_control.hpp"
@@ -47,338 +50,226 @@
namespace rclcpp
{
namespace node
{
template<typename MessageT, typename Alloc>
typename rclcpp::publisher::Publisher<MessageT, Alloc>::SharedPtr
RCLCPP_LOCAL
inline
std::string
extend_name_with_sub_namespace(const std::string & name, const std::string & sub_namespace)
{
std::string name_with_sub_namespace(name);
if (sub_namespace != "" && name.front() != '/' && name.front() != '~') {
name_with_sub_namespace = sub_namespace + "/" + name;
}
return name_with_sub_namespace;
}
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<Alloc> allocator)
{
if (!allocator) {
allocator = std::make_shared<Alloc>();
}
rmw_qos_profile_t qos = rmw_qos_profile_default;
qos.depth = qos_history_depth;
return this->create_publisher<MessageT, Alloc>(topic_name, qos, allocator);
}
template<typename MessageT, typename Alloc>
typename publisher::Publisher<MessageT, Alloc>::SharedPtr
Node::create_publisher(
const std::string & topic_name, const rmw_qos_profile_t & qos_profile,
std::shared_ptr<Alloc> allocator)
{
if (!allocator) {
allocator = std::make_shared<Alloc>();
}
auto publisher_options = rcl_publisher_get_default_options();
publisher_options.qos = qos_profile;
auto message_alloc =
std::make_shared<typename publisher::Publisher<MessageT, Alloc>::MessageAlloc>(
*allocator.get());
publisher_options.allocator = allocator::get_rcl_allocator<MessageT>(
*message_alloc.get());
auto publisher = publisher::Publisher<MessageT, Alloc>::make_shared(
node_handle_, topic_name, publisher_options, message_alloc);
if (use_intra_process_comms_) {
auto intra_process_manager =
context_->get_sub_context<rclcpp::intra_process_manager::IntraProcessManager>();
uint64_t intra_process_publisher_id =
intra_process_manager->add_publisher<MessageT, Alloc>(publisher);
rclcpp::intra_process_manager::IntraProcessManager::WeakPtr weak_ipm = intra_process_manager;
// *INDENT-OFF*
auto shared_publish_callback =
[weak_ipm](uint64_t publisher_id, void * msg, const std::type_info & type_info) -> uint64_t
{
auto ipm = weak_ipm.lock();
if (!ipm) {
// TODO(wjwwood): should this just return silently? Or maybe return with a logged warning?
throw std::runtime_error(
"intra process publish called after destruction of intra process manager");
}
if (!msg) {
throw std::runtime_error("cannot publisher msg which is a null pointer");
}
auto & message_type_info = typeid(MessageT);
if (message_type_info != type_info) {
throw std::runtime_error(
std::string("published type '") + type_info.name() +
"' is incompatible from the publisher type '" + message_type_info.name() + "'");
}
MessageT * typed_message_ptr = static_cast<MessageT *>(msg);
using MessageDeleter = typename publisher::Publisher<MessageT, Alloc>::MessageDeleter;
std::unique_ptr<MessageT, MessageDeleter> unique_msg(typed_message_ptr);
uint64_t message_seq =
ipm->store_intra_process_message<MessageT, Alloc>(publisher_id, unique_msg);
return message_seq;
};
// *INDENT-ON*
publisher->setup_intra_process(
intra_process_publisher_id,
shared_publish_callback,
publisher_options);
}
if (rcl_trigger_guard_condition(&notify_guard_condition_) != RCL_RET_OK) {
throw std::runtime_error(
std::string(
"Failed to notify waitset on publisher creation: ") + rmw_get_error_string());
}
return publisher;
}
template<typename MessageT, typename CallbackT, typename Alloc>
typename rclcpp::subscription::Subscription<MessageT, Alloc>::SharedPtr
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<MessageT, Alloc>::SharedPtr
msg_mem_strat,
typename std::shared_ptr<Alloc> allocator)
const rclcpp::QoS & qos,
const PublisherOptionsWithAllocator<AllocatorT> & options)
{
if (!allocator) {
allocator = std::make_shared<Alloc>();
}
rclcpp::subscription::AnySubscriptionCallback<MessageT,
Alloc> any_subscription_callback(allocator);
any_subscription_callback.set(std::forward<CallbackT>(callback));
if (!msg_mem_strat) {
msg_mem_strat =
rclcpp::message_memory_strategy::MessageMemoryStrategy<MessageT, Alloc>::create_default();
}
auto message_alloc =
std::make_shared<typename subscription::Subscription<MessageT, Alloc>::MessageAlloc>();
auto subscription_options = rcl_subscription_get_default_options();
subscription_options.qos = qos_profile;
subscription_options.allocator = rclcpp::allocator::get_rcl_allocator<MessageT>(
*message_alloc.get());
subscription_options.ignore_local_publications = ignore_local_publications;
using rclcpp::subscription::Subscription;
using rclcpp::subscription::SubscriptionBase;
auto sub = Subscription<MessageT, Alloc>::make_shared(
node_handle_,
topic_name,
subscription_options,
any_subscription_callback,
msg_mem_strat);
auto sub_base_ptr = std::dynamic_pointer_cast<SubscriptionBase>(sub);
// Setup intra process.
if (use_intra_process_comms_) {
auto intra_process_options = rcl_subscription_get_default_options();
intra_process_options.allocator = rclcpp::allocator::get_rcl_allocator<MessageT>(
*message_alloc.get());
intra_process_options.qos = qos_profile;
intra_process_options.ignore_local_publications = false;
auto intra_process_manager =
context_->get_sub_context<rclcpp::intra_process_manager::IntraProcessManager>();
rclcpp::intra_process_manager::IntraProcessManager::WeakPtr weak_ipm = intra_process_manager;
uint64_t intra_process_subscription_id =
intra_process_manager->add_subscription(sub_base_ptr);
// *INDENT-OFF*
sub->setup_intra_process(
intra_process_subscription_id,
[weak_ipm](
uint64_t publisher_id,
uint64_t message_sequence,
uint64_t subscription_id,
typename Subscription<MessageT, Alloc>::MessageUniquePtr & message)
{
auto ipm = weak_ipm.lock();
if (!ipm) {
// TODO(wjwwood): should this just return silently? Or maybe return with a logged warning?
throw std::runtime_error(
"intra process take called after destruction of intra process manager");
}
ipm->take_intra_process_message<MessageT, Alloc>(
publisher_id, message_sequence, subscription_id, message);
},
[weak_ipm](const rmw_gid_t * sender_gid) -> bool {
auto ipm = weak_ipm.lock();
if (!ipm) {
throw std::runtime_error(
"intra process publisher check called after destruction of intra process manager");
}
return ipm->matches_any_publishers(sender_gid);
},
intra_process_options
);
// *INDENT-ON*
}
// Assign to a group.
if (group) {
if (!group_in_node(group)) {
// TODO(jacquelinekay): use custom exception
throw std::runtime_error("Cannot create subscription, group not in node.");
}
group->add_subscription(sub_base_ptr);
} else {
default_callback_group_->add_subscription(sub_base_ptr);
}
number_of_subscriptions_++;
if (rcl_trigger_guard_condition(&notify_guard_condition_) != RCL_RET_OK) {
throw std::runtime_error(
std::string(
"Failed to notify waitset on subscription creation: ") + rmw_get_error_string());
}
return sub;
}
template<typename MessageT, typename CallbackT, typename Alloc>
typename rclcpp::subscription::Subscription<MessageT, Alloc>::SharedPtr
Node::create_subscription(
const std::string & topic_name,
size_t qos_history_depth,
CallbackT && callback,
rclcpp::callback_group::CallbackGroup::SharedPtr group,
bool ignore_local_publications,
typename rclcpp::message_memory_strategy::MessageMemoryStrategy<MessageT, Alloc>::SharedPtr
msg_mem_strat,
std::shared_ptr<Alloc> allocator)
{
rmw_qos_profile_t qos = rmw_qos_profile_default;
qos.depth = qos_history_depth;
return this->create_subscription<MessageT, CallbackT, Alloc>(
topic_name,
std::forward<CallbackT>(callback),
return rclcpp::create_publisher<MessageT, AllocatorT, PublisherT>(
*this,
extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
qos,
group,
ignore_local_publications,
msg_mem_strat,
allocator);
options);
}
template<typename CallbackType>
typename rclcpp::timer::WallTimer<CallbackType>::SharedPtr
Node::create_wall_timer(
std::chrono::nanoseconds period,
CallbackType callback,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
template<
typename MessageT,
typename CallbackT,
typename AllocatorT,
typename CallbackMessageT,
typename SubscriptionT,
typename MessageMemoryStrategyT>
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)
{
auto timer = rclcpp::timer::WallTimer<CallbackType>::make_shared(
period, std::move(callback));
if (group) {
if (!group_in_node(group)) {
// TODO(jacquelinekay): use custom exception
throw std::runtime_error("Cannot create timer, group not in node.");
}
group->add_timer(timer);
} else {
default_callback_group_->add_timer(timer);
}
number_of_timers_++;
if (rcl_trigger_guard_condition(&notify_guard_condition_) != RCL_RET_OK) {
throw std::runtime_error(
std::string(
"Failed to notify waitset on timer creation: ") + rmw_get_error_string());
}
return rclcpp::create_subscription<MessageT>(
*this,
extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
qos,
std::forward<CallbackT>(callback),
options,
msg_mem_strat);
}
template<typename DurationRepT, typename DurationT, typename CallbackT>
typename rclcpp::WallTimer<CallbackT>::SharedPtr
Node::create_wall_timer(
std::chrono::duration<DurationRepT, DurationT> period,
CallbackT callback,
rclcpp::CallbackGroup::SharedPtr group)
{
auto timer = rclcpp::WallTimer<CallbackT>::make_shared(
std::chrono::duration_cast<std::chrono::nanoseconds>(period),
std::move(callback),
this->node_base_->get_context());
node_timers_->add_timer(timer, group);
return timer;
}
template<typename ServiceT>
typename client::Client<ServiceT>::SharedPtr
typename Client<ServiceT>::SharedPtr
Node::create_client(
const std::string & service_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
rclcpp::CallbackGroup::SharedPtr group)
{
rcl_client_options_t options = rcl_client_get_default_options();
options.qos = qos_profile;
using rclcpp::client::Client;
using rclcpp::client::ClientBase;
auto cli = Client<ServiceT>::make_shared(
shared_from_this(),
service_name,
options);
auto cli_base_ptr = std::dynamic_pointer_cast<ClientBase>(cli);
if (group) {
if (!group_in_node(group)) {
// TODO(esteve): use custom exception
throw std::runtime_error("Cannot create client, group not in node.");
}
group->add_client(cli_base_ptr);
} else {
default_callback_group_->add_client(cli_base_ptr);
}
number_of_clients_++;
if (rcl_trigger_guard_condition(&notify_guard_condition_) != RCL_RET_OK) {
throw std::runtime_error(
std::string(
"Failed to notify waitset on client creation: ") + rmw_get_error_string());
}
return cli;
return rclcpp::create_client<ServiceT>(
node_base_,
node_graph_,
node_services_,
extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
qos_profile,
group);
}
template<typename ServiceT, typename CallbackT>
typename rclcpp::service::Service<ServiceT>::SharedPtr
typename rclcpp::Service<ServiceT>::SharedPtr
Node::create_service(
const std::string & service_name,
CallbackT && callback,
const rmw_qos_profile_t & qos_profile,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
rclcpp::CallbackGroup::SharedPtr group)
{
rclcpp::service::AnyServiceCallback<ServiceT> any_service_callback;
any_service_callback.set(std::forward<CallbackT>(callback));
rcl_service_options_t service_options = rcl_service_get_default_options();
service_options.qos = qos_profile;
auto serv = service::Service<ServiceT>::make_shared(
node_handle_,
service_name, any_service_callback, service_options);
auto serv_base_ptr = std::dynamic_pointer_cast<service::ServiceBase>(serv);
if (group) {
if (!group_in_node(group)) {
// TODO(jacquelinekay): use custom exception
throw std::runtime_error("Cannot create service, group not in node.");
}
group->add_service(serv_base_ptr);
} else {
default_callback_group_->add_service(serv_base_ptr);
}
number_of_services_++;
if (rcl_trigger_guard_condition(&notify_guard_condition_) != RCL_RET_OK) {
throw std::runtime_error(
std::string(
"Failed to notify waitset on service creation: ") + rmw_get_error_string());
}
return serv;
}
template<typename CallbackT>
void Node::register_param_change_callback(CallbackT && callback)
{
this->parameters_callback_ = callback;
return rclcpp::create_service<ServiceT, CallbackT>(
node_base_,
node_services_,
extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
std::forward<CallbackT>(callback),
qos_profile,
group);
}
template<typename ParameterT>
bool Node::get_parameter(const std::string & name, ParameterT & parameter) const
auto
Node::declare_parameter(
const std::string & name,
const ParameterT & default_value,
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
bool ignore_override)
{
rclcpp::parameter::ParameterVariant parameter_variant(name, parameter);
bool result = get_parameter(name, parameter_variant);
parameter = parameter_variant.get_value<ParameterT>();
try {
return this->declare_parameter(
name,
rclcpp::ParameterValue(default_value),
parameter_descriptor,
ignore_override
).get<ParameterT>();
} catch (const ParameterTypeException & ex) {
throw exceptions::InvalidParameterTypeException(name, ex.what());
}
}
template<typename ParameterT>
std::vector<ParameterT>
Node::declare_parameters(
const std::string & namespace_,
const std::map<std::string, ParameterT> & parameters,
bool ignore_overrides)
{
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);
}
);
return result;
}
template<typename ParameterT>
std::vector<ParameterT>
Node::declare_parameters(
const std::string & namespace_,
const std::map<
std::string,
std::pair<ParameterT, rcl_interfaces::msg::ParameterDescriptor>
> & parameters,
bool ignore_overrides)
{
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 static_cast<ParameterT>(
this->declare_parameter(
normalized_namespace + element.first,
element.second.first,
element.second.second,
ignore_overrides)
);
}
);
return result;
}
template<typename ParameterT>
bool
Node::get_parameter(const std::string & name, ParameterT & parameter) const
{
std::string sub_name = extend_name_with_sub_namespace(name, this->get_sub_namespace());
rclcpp::Parameter parameter_variant;
bool result = get_parameter(sub_name, parameter_variant);
if (result) {
parameter = static_cast<ParameterT>(parameter_variant.get_value<ParameterT>());
}
return result;
}
template<typename ParameterT>
bool
Node::get_parameter_or(
const std::string & name,
ParameterT & parameter,
const ParameterT & alternative_value) const
{
std::string sub_name = extend_name_with_sub_namespace(name, this->get_sub_namespace());
bool got_parameter = get_parameter(sub_name, parameter);
if (!got_parameter) {
parameter = alternative_value;
}
return got_parameter;
}
// this is a partially-specialized version of get_parameter 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>
bool
Node::get_parameters(
const std::string & prefix,
std::map<std::string, ParameterT> & values) const
{
std::map<std::string, rclcpp::Parameter> params;
bool result = node_parameters_->get_parameters_by_prefix(prefix, params);
if (result) {
for (const auto & param : params) {
values[param.first] = static_cast<ParameterT>(param.second.get_value<ParameterT>());
}
}
return result;
}
} // namespace node
} // namespace rclcpp
#endif // RCLCPP__NODE_IMPL_HPP_

View File

@@ -0,0 +1,149 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
#include <memory>
#include <utility>
#include <type_traits>
#include "rclcpp/node_interfaces/node_base_interface.hpp"
/// This header provides the get_node_base_interface() template function.
/**
* This function is useful for getting the NodeBaseInterface pointer from
* various kinds of Node-like classes.
*
* It's able to get the NodeBaseInterface pointer so long as the class
* has a method called ``get_node_base_interface()`` which returns
* either a pointer (const or not) to a NodeBaseInterface or a
* std::shared_ptr to a NodeBaseInterface.
*/
namespace rclcpp
{
namespace node_interfaces
{
namespace detail
{
// This is a meta-programming checker for if a given Node-like object has a
// getter called get_node_base_interface() which returns various types,
// e.g. const pointer or a shared pointer.
template<typename NodeType, typename ReturnType>
struct has_get_node_base_interface
{
private:
template<typename T>
static constexpr
auto
check(T *)->typename std::is_same<
decltype(std::declval<T>().get_node_base_interface()),
ReturnType
>::type;
template<typename>
static constexpr
std::false_type
check(...);
public:
using type = decltype(check<NodeType>(nullptr));
static constexpr bool value = type::value;
};
// If NodeType is a pointer to NodeBaseInterface already (just normal function overload).
inline
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface_from_pointer(rclcpp::node_interfaces::NodeBaseInterface * pointer)
{
return pointer;
}
// If NodeType has a method called get_node_base_interface() which returns a shared pointer.
template<
typename NodeType,
typename std::enable_if<has_get_node_base_interface<
typename std::remove_pointer<NodeType>::type,
std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface>
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface_from_pointer(NodeType node_pointer)
{
return node_pointer->get_node_base_interface().get();
}
// If NodeType has a method called get_node_base_interface() which returns a pointer.
template<
typename NodeType,
typename std::enable_if<has_get_node_base_interface<
typename std::remove_pointer<NodeType>::type,
rclcpp::node_interfaces::NodeBaseInterface *
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface_from_pointer(NodeType node_pointer)
{
return node_pointer->get_node_base_interface();
}
// Forward shared_ptr's to const node pointer signatures.
template<
typename NodeType,
typename std::enable_if<std::is_same<
NodeType,
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface_from_pointer(NodeType node_shared_pointer)
{
return get_node_base_interface_from_pointer(node_shared_pointer->get());
}
} // namespace detail
/// Get the NodeBaseInterface as a pointer from a pointer to a "Node like" object.
template<
typename NodeType,
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface(NodeType node_pointer)
{
// Forward pointers to detail implmentation directly.
return detail::get_node_base_interface_from_pointer(node_pointer);
}
/// Get the NodeBaseInterface as a pointer from a "Node like" object.
template<
typename NodeType,
typename std::enable_if<
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface(NodeType && node_reference)
{
// Forward references to detail implmentation as a pointer.
return detail::get_node_base_interface_from_pointer(&node_reference);
}
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_

View File

@@ -0,0 +1,149 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
#include <memory>
#include <utility>
#include <type_traits>
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
/// This header provides the get_node_timers_interface() template function.
/**
* This function is useful for getting the NodeTimersInterface pointer from
* various kinds of Node-like classes.
*
* It's able to get the NodeTimersInterface pointer so long as the class
* has a method called ``get_node_timers_interface()`` which returns
* either a pointer (const or not) to a NodeTimersInterface or a
* std::shared_ptr to a NodeTimersInterface.
*/
namespace rclcpp
{
namespace node_interfaces
{
namespace detail
{
// This is a meta-programming checker for if a given Node-like object has a
// getter called get_node_timers_interface() which returns various types,
// e.g. const pointer or a shared pointer.
template<typename NodeType, typename ReturnType>
struct has_get_node_timers_interface
{
private:
template<typename T>
static constexpr
auto
check(T *)->typename std::is_same<
decltype(std::declval<T>().get_node_timers_interface()),
ReturnType
>::type;
template<typename>
static constexpr
std::false_type
check(...);
public:
using type = decltype(check<NodeType>(nullptr));
static constexpr bool value = type::value;
};
// If NodeType is a pointer to NodeTimersInterface already (just normal function overload).
inline
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface_from_pointer(rclcpp::node_interfaces::NodeTimersInterface * pointer)
{
return pointer;
}
// If NodeType has a method called get_node_timers_interface() which returns a shared pointer.
template<
typename NodeType,
typename std::enable_if<has_get_node_timers_interface<
typename std::remove_pointer<NodeType>::type,
std::shared_ptr<rclcpp::node_interfaces::NodeTimersInterface>
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface_from_pointer(NodeType node_pointer)
{
return node_pointer->get_node_timers_interface().get();
}
// If NodeType has a method called get_node_timers_interface() which returns a pointer.
template<
typename NodeType,
typename std::enable_if<has_get_node_timers_interface<
typename std::remove_pointer<NodeType>::type,
rclcpp::node_interfaces::NodeTimersInterface *
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface_from_pointer(NodeType node_pointer)
{
return node_pointer->get_node_timers_interface();
}
// Forward shared_ptr's to const node pointer signatures.
template<
typename NodeType,
typename std::enable_if<std::is_same<
NodeType,
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface_from_pointer(NodeType node_shared_pointer)
{
return get_node_timers_interface_from_pointer(node_shared_pointer->get());
}
} // namespace detail
/// Get the NodeTimersInterface as a pointer from a pointer to a "Node like" object.
template<
typename NodeType,
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface(NodeType node_pointer)
{
// Forward pointers to detail implmentation directly.
return detail::get_node_timers_interface_from_pointer(node_pointer);
}
/// Get the NodeTimersInterface as a pointer from a "Node like" object.
template<
typename NodeType,
typename std::enable_if<
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface(NodeType && node_reference)
{
// Forward references to detail implmentation as a pointer.
return detail::get_node_timers_interface_from_pointer(&node_reference);
}
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_

View File

@@ -0,0 +1,149 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_TOPICS_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__GET_NODE_TOPICS_INTERFACE_HPP_
#include <memory>
#include <utility>
#include <type_traits>
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
/// This header provides the get_node_topics_interface() template function.
/**
* This function is useful for getting the NodeTopicsInterface pointer from
* various kinds of Node-like classes.
*
* It's able to get the NodeTopicsInterface pointer so long as the class
* has a method called ``get_node_topics_interface()`` which returns
* either a pointer (const or not) to a NodeTopicsInterface or a
* std::shared_ptr to a NodeTopicsInterface.
*/
namespace rclcpp
{
namespace node_interfaces
{
namespace detail
{
// This is a meta-programming checker for if a given Node-like object has a
// getter called get_node_topics_interface() which returns various types,
// e.g. const pointer or a shared pointer.
template<typename NodeType, typename ReturnType>
struct has_get_node_topics_interface
{
private:
template<typename T>
static constexpr
auto
check(T *)->typename std::is_same<
decltype(std::declval<T>().get_node_topics_interface()),
ReturnType
>::type;
template<typename>
static constexpr
std::false_type
check(...);
public:
using type = decltype(check<NodeType>(nullptr));
static constexpr bool value = type::value;
};
// If NodeType is a pointer to NodeTopicsInterface already (just normal function overload).
inline
rclcpp::node_interfaces::NodeTopicsInterface *
get_node_topics_interface_from_pointer(rclcpp::node_interfaces::NodeTopicsInterface * pointer)
{
return pointer;
}
// If NodeType has a method called get_node_topics_interface() which returns a shared pointer.
template<
typename NodeType,
typename std::enable_if<has_get_node_topics_interface<
typename std::remove_pointer<NodeType>::type,
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTopicsInterface *
get_node_topics_interface_from_pointer(NodeType node_pointer)
{
return node_pointer->get_node_topics_interface().get();
}
// If NodeType has a method called get_node_topics_interface() which returns a pointer.
template<
typename NodeType,
typename std::enable_if<has_get_node_topics_interface<
typename std::remove_pointer<NodeType>::type,
rclcpp::node_interfaces::NodeTopicsInterface *
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTopicsInterface *
get_node_topics_interface_from_pointer(NodeType node_pointer)
{
return node_pointer->get_node_topics_interface();
}
// Forward shared_ptr's to const node pointer signatures.
template<
typename NodeType,
typename std::enable_if<std::is_same<
NodeType,
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTopicsInterface *
get_node_topics_interface_from_pointer(NodeType node_shared_pointer)
{
return get_node_topics_interface_from_pointer(node_shared_pointer->get());
}
} // namespace detail
/// Get the NodeTopicsInterface as a pointer from a pointer to a "Node like" object.
template<
typename NodeType,
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTopicsInterface *
get_node_topics_interface(NodeType node_pointer)
{
// Forward pointers to detail implmentation directly.
return detail::get_node_topics_interface_from_pointer(node_pointer);
}
/// Get the NodeTopicsInterface as a pointer from a "Node like" object.
template<
typename NodeType,
typename std::enable_if<
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
>::type = 0
>
rclcpp::node_interfaces::NodeTopicsInterface *
get_node_topics_interface(NodeType && node_reference)
{
// Forward references to detail implmentation as a pointer.
return detail::get_node_topics_interface_from_pointer(&node_reference);
}
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_TOPICS_INTERFACE_HPP_

View File

@@ -0,0 +1,163 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_BASE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_BASE_HPP_
#include <memory>
#include <string>
#include <vector>
#include "rcl/node.h"
#include "rclcpp/context.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Implementation of the NodeBase part of the Node API.
class NodeBase : public NodeBaseInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeBase)
RCLCPP_PUBLIC
NodeBase(
const std::string & node_name,
const std::string & namespace_,
rclcpp::Context::SharedPtr context,
const rcl_node_options_t & rcl_node_options,
bool use_intra_process_default,
bool enable_topic_statistics_default);
RCLCPP_PUBLIC
virtual
~NodeBase();
RCLCPP_PUBLIC
const char *
get_name() const override;
RCLCPP_PUBLIC
const char *
get_namespace() const override;
RCLCPP_PUBLIC
const char *
get_fully_qualified_name() const override;
RCLCPP_PUBLIC
rclcpp::Context::SharedPtr
get_context() override;
RCLCPP_PUBLIC
rcl_node_t *
get_rcl_node_handle() override;
RCLCPP_PUBLIC
const rcl_node_t *
get_rcl_node_handle() const override;
RCLCPP_PUBLIC
std::shared_ptr<rcl_node_t>
get_shared_rcl_node_handle() override;
RCLCPP_PUBLIC
std::shared_ptr<const rcl_node_t>
get_shared_rcl_node_handle() const override;
RCLCPP_PUBLIC
bool
assert_liveliness() const override;
RCLCPP_PUBLIC
rclcpp::CallbackGroup::SharedPtr
create_callback_group(rclcpp::CallbackGroupType group_type) override;
RCLCPP_PUBLIC
rclcpp::CallbackGroup::SharedPtr
get_default_callback_group() override;
RCLCPP_PUBLIC
bool
callback_group_in_node(rclcpp::CallbackGroup::SharedPtr group) override;
RCLCPP_PUBLIC
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
get_callback_groups() const override;
RCLCPP_PUBLIC
std::atomic_bool &
get_associated_with_executor_atomic() override;
RCLCPP_PUBLIC
rcl_guard_condition_t *
get_notify_guard_condition() override;
RCLCPP_PUBLIC
std::unique_lock<std::recursive_mutex>
acquire_notify_guard_condition_lock() const override;
RCLCPP_PUBLIC
bool
get_use_intra_process_default() const override;
bool
get_enable_topic_statistics_default() const override;
private:
RCLCPP_DISABLE_COPY(NodeBase)
rclcpp::Context::SharedPtr context_;
bool use_intra_process_default_;
bool enable_topic_statistics_default_;
std::shared_ptr<rcl_node_t> node_handle_;
rclcpp::CallbackGroup::SharedPtr default_callback_group_;
std::vector<rclcpp::CallbackGroup::WeakPtr> callback_groups_;
std::atomic_bool associated_with_executor_;
/// Guard condition for notifying the Executor of changes to this node.
mutable std::recursive_mutex notify_guard_condition_mutex_;
rcl_guard_condition_t notify_guard_condition_ = rcl_get_zero_initialized_guard_condition();
bool notify_guard_condition_is_valid_;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_BASE_HPP_

View File

@@ -0,0 +1,175 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_BASE_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_BASE_INTERFACE_HPP_
#include <memory>
#include <mutex>
#include <string>
#include <vector>
#include "rcl/node.h"
#include "rclcpp/callback_group.hpp"
#include "rclcpp/context.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Pure virtual interface class for the NodeBase part of the Node API.
class NodeBaseInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeBaseInterface)
RCLCPP_PUBLIC
virtual
~NodeBaseInterface() = default;
/// Return the name of the node.
/** \return The name of the node. */
RCLCPP_PUBLIC
virtual
const char *
get_name() const = 0;
/// Return the namespace of the node.
/** \return The namespace of the node. */
RCLCPP_PUBLIC
virtual
const char *
get_namespace() const = 0;
/// Return the fully qualified name of the node.
/** \return The fully qualified name of the node. */
RCLCPP_PUBLIC
virtual
const char *
get_fully_qualified_name() const = 0;
/// Return the context of the node.
/** \return SharedPtr to the node's context. */
RCLCPP_PUBLIC
virtual
rclcpp::Context::SharedPtr
get_context() = 0;
/// Return the rcl_node_t node handle (non-const version).
RCLCPP_PUBLIC
virtual
rcl_node_t *
get_rcl_node_handle() = 0;
/// Return the rcl_node_t node handle (const version).
RCLCPP_PUBLIC
virtual
const rcl_node_t *
get_rcl_node_handle() const = 0;
/// Return the rcl_node_t node handle in a std::shared_ptr.
/**
* This handle remains valid after the Node is destroyed.
* The actual rcl node is not finalized until it is out of scope everywhere.
*/
RCLCPP_PUBLIC
virtual
std::shared_ptr<rcl_node_t>
get_shared_rcl_node_handle() = 0;
/// Return the rcl_node_t node handle in a std::shared_ptr.
/**
* This handle remains valid after the Node is destroyed.
* The actual rcl node is not finalized until it is out of scope everywhere.
*/
RCLCPP_PUBLIC
virtual
std::shared_ptr<const rcl_node_t>
get_shared_rcl_node_handle() const = 0;
/// Manually assert that this Node is alive (for RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE).
RCLCPP_PUBLIC
virtual
bool
assert_liveliness() const = 0;
/// Create and return a callback group.
RCLCPP_PUBLIC
virtual
rclcpp::CallbackGroup::SharedPtr
create_callback_group(rclcpp::CallbackGroupType group_type) = 0;
/// Return the default callback group.
RCLCPP_PUBLIC
virtual
rclcpp::CallbackGroup::SharedPtr
get_default_callback_group() = 0;
/// Return true if the given callback group is associated with this node.
RCLCPP_PUBLIC
virtual
bool
callback_group_in_node(rclcpp::CallbackGroup::SharedPtr group) = 0;
/// Return list of callback groups associated with this node.
RCLCPP_PUBLIC
virtual
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
get_callback_groups() const = 0;
/// Return the atomic bool which is used to ensure only one executor is used.
RCLCPP_PUBLIC
virtual
std::atomic_bool &
get_associated_with_executor_atomic() = 0;
/// Return guard condition that should be notified when the internal node state changes.
/**
* For example, this should be notified when a publisher is added or removed.
*
* \return the rcl_guard_condition_t if it is valid, else nullptr
*/
RCLCPP_PUBLIC
virtual
rcl_guard_condition_t *
get_notify_guard_condition() = 0;
/// Acquire and return a scoped lock that protects the notify guard condition.
/** This should be used when triggering the notify guard condition. */
RCLCPP_PUBLIC
virtual
std::unique_lock<std::recursive_mutex>
acquire_notify_guard_condition_lock() const = 0;
/// Return the default preference for using intra process communication.
RCLCPP_PUBLIC
virtual
bool
get_use_intra_process_default() const = 0;
/// Return the default preference for enabling topic statistics collection.
RCLCPP_PUBLIC
virtual
bool
get_enable_topic_statistics_default() const = 0;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_BASE_INTERFACE_HPP_

View File

@@ -0,0 +1,76 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_CLOCK_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_CLOCK_HPP_
#include "rclcpp/clock.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_clock_interface.hpp"
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
#include "rclcpp/node_interfaces/node_services_interface.hpp"
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Implementation of the NodeClock part of the Node API.
class NodeClock : public NodeClockInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeClock)
RCLCPP_PUBLIC
explicit NodeClock(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services,
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging);
RCLCPP_PUBLIC
virtual
~NodeClock();
/// Get a clock which will be kept up to date by the node.
RCLCPP_PUBLIC
rclcpp::Clock::SharedPtr
get_clock() override;
/// Get a clock which will be kept up to date by the node.
RCLCPP_PUBLIC
rclcpp::Clock::ConstSharedPtr
get_clock() const override;
private:
RCLCPP_DISABLE_COPY(NodeClock)
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_;
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_;
rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_;
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_;
rclcpp::Clock::SharedPtr ros_clock_;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_CLOCK_HPP_

View File

@@ -0,0 +1,53 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_CLOCK_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_CLOCK_INTERFACE_HPP_
#include "rclcpp/clock.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Pure virtual interface class for the NodeClock part of the Node API.
class NodeClockInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeClockInterface)
RCLCPP_PUBLIC
virtual
~NodeClockInterface() = default;
/// Get a ROS clock which will be kept up to date by the node.
RCLCPP_PUBLIC
virtual
rclcpp::Clock::SharedPtr
get_clock() = 0;
/// Get a const ROS clock which will be kept up to date by the node.
RCLCPP_PUBLIC
virtual
rclcpp::Clock::ConstSharedPtr
get_clock() const = 0;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_CLOCK_INTERFACE_HPP_

View File

@@ -0,0 +1,158 @@
// Copyright 2016-2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_GRAPH_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_GRAPH_HPP_
#include <chrono>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <utility>
#include <vector>
#include "rcl/guard_condition.h"
#include "rclcpp/event.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rmw/topic_endpoint_info_array.h"
namespace rclcpp
{
namespace graph_listener
{
class GraphListener;
} // namespace graph_listener
namespace node_interfaces
{
/// Implementation the NodeGraph part of the Node API.
class NodeGraph : public NodeGraphInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeGraph)
RCLCPP_PUBLIC
explicit NodeGraph(rclcpp::node_interfaces::NodeBaseInterface * node_base);
RCLCPP_PUBLIC
virtual
~NodeGraph();
RCLCPP_PUBLIC
std::map<std::string, std::vector<std::string>>
get_topic_names_and_types(bool no_demangle = false) const override;
RCLCPP_PUBLIC
std::map<std::string, std::vector<std::string>>
get_service_names_and_types() const override;
RCLCPP_PUBLIC
std::vector<std::string>
get_node_names() const override;
RCLCPP_PUBLIC
std::vector<std::pair<std::string, std::string>>
get_node_names_and_namespaces() const override;
RCLCPP_PUBLIC
size_t
count_publishers(const std::string & topic_name) const override;
RCLCPP_PUBLIC
size_t
count_subscribers(const std::string & topic_name) const override;
RCLCPP_PUBLIC
const rcl_guard_condition_t *
get_graph_guard_condition() const override;
RCLCPP_PUBLIC
void
notify_graph_change() override;
RCLCPP_PUBLIC
void
notify_shutdown() override;
RCLCPP_PUBLIC
rclcpp::Event::SharedPtr
get_graph_event() override;
RCLCPP_PUBLIC
void
wait_for_graph_change(
rclcpp::Event::SharedPtr event,
std::chrono::nanoseconds timeout) override;
RCLCPP_PUBLIC
size_t
count_graph_users() override;
RCLCPP_PUBLIC
std::vector<rclcpp::TopicEndpointInfo>
get_publishers_info_by_topic(
const std::string & topic_name,
bool no_mangle = false) const override;
RCLCPP_PUBLIC
std::vector<rclcpp::TopicEndpointInfo>
get_subscriptions_info_by_topic(
const std::string & topic_name,
bool no_mangle = false) const override;
private:
RCLCPP_DISABLE_COPY(NodeGraph)
/// Handle to the NodeBaseInterface given in the constructor.
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
/// Graph Listener which waits on graph changes for the node and is shared across nodes.
std::shared_ptr<rclcpp::graph_listener::GraphListener> graph_listener_;
/// Whether or not this node needs to be added to the graph listener.
std::atomic_bool should_add_to_graph_listener_;
/// Mutex to guard the graph event related data structures.
mutable std::mutex graph_mutex_;
/// For notifying waiting threads (wait_for_graph_change()) on changes (notify_graph_change()).
std::condition_variable graph_cv_;
/// Weak references to graph events out on loan.
std::vector<rclcpp::Event::WeakPtr> graph_events_;
/// Number of graph events out on loan, used to determine if the graph should be monitored.
/** graph_users_count_ is atomic so that it can be accessed without acquiring the graph_mutex_ */
std::atomic_size_t graph_users_count_;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_GRAPH_HPP_

View File

@@ -0,0 +1,276 @@
// Copyright 2016-2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_GRAPH_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_GRAPH_INTERFACE_HPP_
#include <algorithm>
#include <array>
#include <chrono>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "rcl/graph.h"
#include "rcl/guard_condition.h"
#include "rclcpp/event.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/qos.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
enum class EndpointType
{
Invalid = RMW_ENDPOINT_INVALID,
Publisher = RMW_ENDPOINT_PUBLISHER,
Subscription = RMW_ENDPOINT_SUBSCRIPTION
};
/**
* Struct that contains topic endpoint information like the associated node name, node namespace,
* topic type, endpoint type, endpoint GID, and its QoS.
*/
class TopicEndpointInfo
{
public:
/// Construct a TopicEndpointInfo from a rcl_topic_endpoint_info_t.
RCLCPP_PUBLIC
explicit TopicEndpointInfo(const rcl_topic_endpoint_info_t & info)
: node_name_(info.node_name),
node_namespace_(info.node_namespace),
topic_type_(info.topic_type),
endpoint_type_(static_cast<rclcpp::EndpointType>(info.endpoint_type)),
qos_profile_({info.qos_profile.history, info.qos_profile.depth}, info.qos_profile)
{
std::copy(info.endpoint_gid, info.endpoint_gid + RMW_GID_STORAGE_SIZE, endpoint_gid_.begin());
}
/// Get a mutable reference to the node name.
RCLCPP_PUBLIC
std::string &
node_name();
/// Get a const reference to the node name.
RCLCPP_PUBLIC
const std::string &
node_name() const;
/// Get a mutable reference to the node namespace.
RCLCPP_PUBLIC
std::string &
node_namespace();
/// Get a const reference to the node namespace.
RCLCPP_PUBLIC
const std::string &
node_namespace() const;
/// Get a mutable reference to the topic type string.
RCLCPP_PUBLIC
std::string &
topic_type();
/// Get a const reference to the topic type string.
RCLCPP_PUBLIC
const std::string &
topic_type() const;
/// Get a mutable reference to the topic endpoint type.
RCLCPP_PUBLIC
rclcpp::EndpointType &
endpoint_type();
/// Get a const reference to the topic endpoint type.
RCLCPP_PUBLIC
const rclcpp::EndpointType &
endpoint_type() const;
/// Get a mutable reference to the GID of the topic endpoint.
RCLCPP_PUBLIC
std::array<uint8_t, RMW_GID_STORAGE_SIZE> &
endpoint_gid();
/// Get a const reference to the GID of the topic endpoint.
RCLCPP_PUBLIC
const std::array<uint8_t, RMW_GID_STORAGE_SIZE> &
endpoint_gid() const;
/// Get a mutable reference to the QoS profile of the topic endpoint.
RCLCPP_PUBLIC
rclcpp::QoS &
qos_profile();
/// Get a const reference to the QoS profile of the topic endpoint.
RCLCPP_PUBLIC
const rclcpp::QoS &
qos_profile() const;
private:
std::string node_name_;
std::string node_namespace_;
std::string topic_type_;
rclcpp::EndpointType endpoint_type_;
std::array<uint8_t, RMW_GID_STORAGE_SIZE> endpoint_gid_;
rclcpp::QoS qos_profile_;
};
namespace node_interfaces
{
/// Pure virtual interface class for the NodeGraph part of the Node API.
class NodeGraphInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeGraphInterface)
RCLCPP_PUBLIC
virtual
~NodeGraphInterface() = default;
/// Return a map of existing topic names to list of topic types.
/**
* A topic is considered to exist when at least one publisher or subscriber
* exists for it, whether they be local or remote to this process.
*
* \param[in] no_demangle if true, topic names and types are not demangled
*/
RCLCPP_PUBLIC
virtual
std::map<std::string, std::vector<std::string>>
get_topic_names_and_types(bool no_demangle = false) const = 0;
/// Return a map of existing service names to list of service types.
/**
* A service is considered to exist when at least one service server or
* service client exists for it, whether they be local or remote to this
* process.
*/
RCLCPP_PUBLIC
virtual
std::map<std::string, std::vector<std::string>>
get_service_names_and_types() const = 0;
/// Return a vector of existing node names (string).
RCLCPP_PUBLIC
virtual
std::vector<std::string>
get_node_names() const = 0;
/// Return a vector of existing node names and namespaces (pair of string).
RCLCPP_PUBLIC
virtual
std::vector<std::pair<std::string, std::string>>
get_node_names_and_namespaces() const = 0;
/// Return the number of publishers that are advertised on a given topic.
RCLCPP_PUBLIC
virtual
size_t
count_publishers(const std::string & topic_name) const = 0;
/// Return the number of subscribers who have created a subscription for a given topic.
RCLCPP_PUBLIC
virtual
size_t
count_subscribers(const std::string & topic_name) const = 0;
/// Return the rcl guard condition which is triggered when the ROS graph changes.
RCLCPP_PUBLIC
virtual
const rcl_guard_condition_t *
get_graph_guard_condition() const = 0;
/// Notify threads waiting on graph changes.
/**
* Affects threads waiting on the notify guard condition, see:
* get_notify_guard_condition(), as well as the threads waiting on graph
* changes using a graph Event, see: wait_for_graph_change().
*
* This is typically only used by the rclcpp::graph_listener::GraphListener.
*
* \throws RCLBaseError (a child of that exception) when an rcl error occurs
*/
RCLCPP_PUBLIC
virtual
void
notify_graph_change() = 0;
/// Notify any and all blocking node actions that shutdown has occurred.
RCLCPP_PUBLIC
virtual
void
notify_shutdown() = 0;
/// Return a graph event, which will be set anytime a graph change occurs.
/**
* The graph Event object is a loan which must be returned.
* The Event object is scoped and therefore to return the load just let it go
* out of scope.
*/
RCLCPP_PUBLIC
virtual
rclcpp::Event::SharedPtr
get_graph_event() = 0;
/// Wait for a graph event to occur by waiting on an Event to become set.
/**
* The given Event must be acquire through the get_graph_event() method.
*
* \throws InvalidEventError if the given event is nullptr
* \throws EventNotRegisteredError if the given event was not acquired with
* get_graph_event().
*/
RCLCPP_PUBLIC
virtual
void
wait_for_graph_change(
rclcpp::Event::SharedPtr event,
std::chrono::nanoseconds timeout) = 0;
/// Return the number of on loan graph events, see get_graph_event().
/**
* This is typically only used by the rclcpp::graph_listener::GraphListener.
*/
RCLCPP_PUBLIC
virtual
size_t
count_graph_users() = 0;
/// Return the topic endpoint information about publishers on a given topic.
/**
* \sa rclcpp::Node::get_publishers_info_by_topic
*/
RCLCPP_PUBLIC
virtual
std::vector<rclcpp::TopicEndpointInfo>
get_publishers_info_by_topic(const std::string & topic_name, bool no_mangle = false) const = 0;
/// Return the topic endpoint information about subscriptions on a given topic.
/**
* \sa rclcpp::Node::get_subscriptions_info_by_topic
*/
RCLCPP_PUBLIC
virtual
std::vector<rclcpp::TopicEndpointInfo>
get_subscriptions_info_by_topic(const std::string & topic_name, bool no_mangle = false) const = 0;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_GRAPH_INTERFACE_HPP_

View File

@@ -0,0 +1,66 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_LOGGING_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_LOGGING_HPP_
#include <memory>
#include "rclcpp/logger.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Implementation of the NodeLogging part of the Node API.
class NodeLogging : public NodeLoggingInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeLoggingInterface)
RCLCPP_PUBLIC
explicit NodeLogging(rclcpp::node_interfaces::NodeBaseInterface * node_base);
RCLCPP_PUBLIC
virtual
~NodeLogging();
RCLCPP_PUBLIC
rclcpp::Logger
get_logger() const override;
RCLCPP_PUBLIC
const char *
get_logger_name() const override;
private:
RCLCPP_DISABLE_COPY(NodeLogging)
/// Handle to the NodeBaseInterface given in the constructor.
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
rclcpp::Logger logger_;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_LOGGING_HPP_

View File

@@ -0,0 +1,57 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_LOGGING_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_LOGGING_INTERFACE_HPP_
#include <memory>
#include "rclcpp/logger.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Pure virtual interface class for the NodeLogging part of the Node API.
class NodeLoggingInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeLoggingInterface)
RCLCPP_PUBLIC
virtual
~NodeLoggingInterface() = default;
/// Return the logger of the node.
/** \return The logger of the node. */
RCLCPP_PUBLIC
virtual
rclcpp::Logger
get_logger() const = 0;
/// Return the logger name associated with the node.
/** \return The logger name associated with the node. */
RCLCPP_PUBLIC
virtual
const char *
get_logger_name() const = 0;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_LOGGING_INTERFACE_HPP_

View File

@@ -0,0 +1,213 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_HPP_
#include <map>
#include <memory>
#include <list>
#include <string>
#include <vector>
#include "rcl_interfaces/msg/list_parameters_result.hpp"
#include "rcl_interfaces/msg/parameter_descriptor.hpp"
#include "rcl_interfaces/msg/parameter_event.hpp"
#include "rcl_interfaces/msg/set_parameters_result.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
#include "rclcpp/node_interfaces/node_services_interface.hpp"
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
#include "rclcpp/parameter.hpp"
#include "rclcpp/parameter_service.hpp"
#include "rclcpp/publisher.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
// Internal struct for holding useful info about parameters
struct ParameterInfo
{
/// Current value of the parameter.
rclcpp::ParameterValue value;
/// A description of the parameter
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
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeParameters)
RCLCPP_PUBLIC
NodeParameters(
const node_interfaces::NodeBaseInterface::SharedPtr node_base,
const node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
const node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
const node_interfaces::NodeServicesInterface::SharedPtr node_services,
const node_interfaces::NodeClockInterface::SharedPtr node_clock,
const std::vector<Parameter> & parameter_overrides,
bool start_parameter_services,
bool start_parameter_event_publisher,
const rclcpp::QoS & parameter_event_qos,
const rclcpp::PublisherOptionsBase & parameter_event_publisher_options,
bool allow_undeclared_parameters,
bool automatically_declare_parameters_from_overrides);
RCLCPP_PUBLIC
virtual
~NodeParameters();
RCLCPP_PUBLIC
const rclcpp::ParameterValue &
declare_parameter(
const std::string & name,
const rclcpp::ParameterValue & default_value,
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
bool ignore_override) override;
RCLCPP_PUBLIC
void
undeclare_parameter(const std::string & name) override;
RCLCPP_PUBLIC
bool
has_parameter(const std::string & name) const override;
RCLCPP_PUBLIC
std::vector<rcl_interfaces::msg::SetParametersResult>
set_parameters(
const std::vector<rclcpp::Parameter> & parameters) override;
RCLCPP_PUBLIC
rcl_interfaces::msg::SetParametersResult
set_parameters_atomically(
const std::vector<rclcpp::Parameter> & parameters) override;
RCLCPP_PUBLIC
std::vector<rclcpp::Parameter>
get_parameters(const std::vector<std::string> & names) const override;
RCLCPP_PUBLIC
rclcpp::Parameter
get_parameter(const std::string & name) const override;
RCLCPP_PUBLIC
bool
get_parameter(
const std::string & name,
rclcpp::Parameter & parameter) const override;
RCLCPP_PUBLIC
bool
get_parameters_by_prefix(
const std::string & prefix,
std::map<std::string, rclcpp::Parameter> & parameters) const override;
RCLCPP_PUBLIC
std::vector<rcl_interfaces::msg::ParameterDescriptor>
describe_parameters(const std::vector<std::string> & names) const override;
RCLCPP_PUBLIC
std::vector<uint8_t>
get_parameter_types(const std::vector<std::string> & names) const override;
RCLCPP_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;
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};
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_;
bool allow_undeclared_ = false;
Publisher<rcl_interfaces::msg::ParameterEvent>::SharedPtr events_publisher_;
std::shared_ptr<ParameterService> parameter_service_;
std::string combined_name_;
node_interfaces::NodeLoggingInterface::SharedPtr node_logging_;
node_interfaces::NodeClockInterface::SharedPtr node_clock_;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_HPP_

View File

@@ -0,0 +1,213 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_INTERFACE_HPP_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "rcl_interfaces/msg/list_parameters_result.hpp"
#include "rcl_interfaces/msg/parameter_descriptor.hpp"
#include "rcl_interfaces/msg/set_parameters_result.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/parameter.hpp"
#include "rclcpp/visibility_control.hpp"
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
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeParametersInterface)
RCLCPP_PUBLIC
virtual
~NodeParametersInterface() = default;
/// Declare and initialize a parameter.
/**
* \sa rclcpp::Node::declare_parameter
*/
RCLCPP_PUBLIC
virtual
const rclcpp::ParameterValue &
declare_parameter(
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;
/// Undeclare a parameter.
/**
* \sa rclcpp::Node::undeclare_parameter
*/
RCLCPP_PUBLIC
virtual
void
undeclare_parameter(const std::string & name) = 0;
/// Return true if the parameter has been declared, otherwise false.
/**
* \sa rclcpp::Node::has_parameter
*/
RCLCPP_PUBLIC
virtual
bool
has_parameter(const std::string & name) const = 0;
/// Set one or more parameters, one at a time.
/**
* \sa rclcpp::Node::set_parameters
*/
RCLCPP_PUBLIC
virtual
std::vector<rcl_interfaces::msg::SetParametersResult>
set_parameters(const std::vector<rclcpp::Parameter> & parameters) = 0;
/// Set and initialize a parameter, all at once.
/**
* \sa rclcpp::Node::set_parameters_atomically
*/
RCLCPP_PUBLIC
virtual
rcl_interfaces::msg::SetParametersResult
set_parameters_atomically(
const std::vector<rclcpp::Parameter> & parameters) = 0;
/// Get descriptions of parameters given their names.
/*
* \param[in] names a list of parameter names to check.
* \return the list of parameters that were found.
* Any parameter not found is omitted from the returned list.
*/
RCLCPP_PUBLIC
virtual
std::vector<rclcpp::Parameter>
get_parameters(const std::vector<std::string> & names) const = 0;
/// Get the description of one parameter given a name.
/*
* \param[in] name the name of the parameter to look for.
* \return the parameter if it exists on the node.
* \throws std::out_of_range if the parameter does not exist on the node.
*/
RCLCPP_PUBLIC
virtual
rclcpp::Parameter
get_parameter(const std::string & name) const = 0;
/// Get the description of one parameter given a name.
/*
* \param[in] name the name of the parameter to look for.
* \param[out] parameter the description if parameter exists on the node.
* \return true if the parameter exists on the node, or
* \return false if the parameter does not exist.
*/
RCLCPP_PUBLIC
virtual
bool
get_parameter(
const std::string & name,
rclcpp::Parameter & parameter) const = 0;
/// Get all parameters that have the specified prefix into the parameters map.
/*
* \param[in] prefix the name of the prefix to look for.
* \param[out] parameters a map of parameters that matched the prefix.
* \return true if any parameters with the prefix exists on the node, or
* \return false otherwise.
*/
RCLCPP_PUBLIC
virtual
bool
get_parameters_by_prefix(
const std::string & prefix,
std::map<std::string, rclcpp::Parameter> & parameters) const = 0;
RCLCPP_PUBLIC
virtual
std::vector<rcl_interfaces::msg::ParameterDescriptor>
describe_parameters(const std::vector<std::string> & names) const = 0;
RCLCPP_PUBLIC
virtual
std::vector<uint8_t>
get_parameter_types(const std::vector<std::string> & names) const = 0;
RCLCPP_PUBLIC
virtual
rcl_interfaces::msg::ListParametersResult
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const = 0;
using OnParametersSetCallbackType = OnSetParametersCallbackHandle::OnParametersSetCallbackType;
/// 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;
/// Register a callback for when parameters are being set, return an existing one.
/**
* \sa rclcpp::Node::set_on_parameters_set_callback
*/
RCLCPP_PUBLIC
virtual
OnParametersSetCallbackType
set_on_parameters_set_callback(OnParametersSetCallbackType callback) = 0;
/// Return the initial parameter values used by the NodeParameters to override default values.
RCLCPP_PUBLIC
virtual
const std::map<std::string, rclcpp::ParameterValue> &
get_parameter_overrides() const = 0;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_INTERFACE_HPP_

View File

@@ -0,0 +1,67 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_SERVICES_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_SERVICES_HPP_
#include "rclcpp/callback_group.hpp"
#include "rclcpp/client.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_services_interface.hpp"
#include "rclcpp/service.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Implementation of the NodeServices part of the Node API.
class NodeServices : public NodeServicesInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeServices)
RCLCPP_PUBLIC
explicit NodeServices(rclcpp::node_interfaces::NodeBaseInterface * node_base);
RCLCPP_PUBLIC
virtual
~NodeServices();
RCLCPP_PUBLIC
void
add_client(
rclcpp::ClientBase::SharedPtr client_base_ptr,
rclcpp::CallbackGroup::SharedPtr group) override;
RCLCPP_PUBLIC
void
add_service(
rclcpp::ServiceBase::SharedPtr service_base_ptr,
rclcpp::CallbackGroup::SharedPtr group) override;
private:
RCLCPP_DISABLE_COPY(NodeServices)
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_SERVICES_HPP_

View File

@@ -0,0 +1,57 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_SERVICES_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_SERVICES_INTERFACE_HPP_
#include "rclcpp/callback_group.hpp"
#include "rclcpp/client.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/service.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Pure virtual interface class for the NodeServices part of the Node API.
class NodeServicesInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeServicesInterface)
RCLCPP_PUBLIC
virtual
~NodeServicesInterface() = default;
RCLCPP_PUBLIC
virtual
void
add_client(
rclcpp::ClientBase::SharedPtr client_base_ptr,
rclcpp::CallbackGroup::SharedPtr group) = 0;
RCLCPP_PUBLIC
virtual
void
add_service(
rclcpp::ServiceBase::SharedPtr service_base_ptr,
rclcpp::CallbackGroup::SharedPtr group) = 0;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_SERVICES_INTERFACE_HPP_

View File

@@ -0,0 +1,73 @@
// 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.
#ifndef RCLCPP__NODE_INTERFACES__NODE_TIME_SOURCE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_TIME_SOURCE_HPP_
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_clock_interface.hpp"
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
#include "rclcpp/node_interfaces/node_services_interface.hpp"
#include "rclcpp/node_interfaces/node_time_source_interface.hpp"
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
#include "rclcpp/time_source.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Implementation of the NodeTimeSource part of the Node API.
class NodeTimeSource : public NodeTimeSourceInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeTimeSource)
RCLCPP_PUBLIC
explicit NodeTimeSource(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services,
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock,
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters
);
RCLCPP_PUBLIC
virtual
~NodeTimeSource();
private:
RCLCPP_DISABLE_COPY(NodeTimeSource)
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_;
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_;
rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_;
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_;
rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock_;
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters_;
rclcpp::TimeSource time_source_;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_TIME_SOURCE_HPP_

View File

@@ -0,0 +1,40 @@
// 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.
#ifndef RCLCPP__NODE_INTERFACES__NODE_TIME_SOURCE_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_TIME_SOURCE_INTERFACE_HPP_
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Pure virtual interface class for the NodeTimeSource part of the Node API.
class NodeTimeSourceInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeTimeSourceInterface)
RCLCPP_PUBLIC
virtual
~NodeTimeSourceInterface() = default;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_TIME_SOURCE_INTERFACE_HPP_

View File

@@ -0,0 +1,60 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_TIMERS_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_TIMERS_HPP_
#include "rclcpp/callback_group.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
#include "rclcpp/timer.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Implementation of the NodeTimers part of the Node API.
class NodeTimers : public NodeTimersInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeTimers)
RCLCPP_PUBLIC
explicit NodeTimers(rclcpp::node_interfaces::NodeBaseInterface * node_base);
RCLCPP_PUBLIC
virtual
~NodeTimers();
/// Add a timer to the node.
RCLCPP_PUBLIC
void
add_timer(
rclcpp::TimerBase::SharedPtr timer,
rclcpp::CallbackGroup::SharedPtr callback_group) override;
private:
RCLCPP_DISABLE_COPY(NodeTimers)
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_TIMERS_HPP_

View File

@@ -0,0 +1,50 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_TIMERS_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_TIMERS_INTERFACE_HPP_
#include "rclcpp/callback_group.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/timer.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Pure virtual interface class for the NodeTimers part of the Node API.
class NodeTimersInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeTimersInterface)
RCLCPP_PUBLIC
virtual
~NodeTimersInterface() = default;
/// Add a timer to the node.
RCLCPP_PUBLIC
virtual
void
add_timer(
rclcpp::TimerBase::SharedPtr timer,
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_TIMERS_INTERFACE_HPP_

View File

@@ -0,0 +1,86 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_TOPICS_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_TOPICS_HPP_
#include <string>
#include "rcl/publisher.h"
#include "rcl/subscription.h"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
#include "rclcpp/publisher.hpp"
#include "rclcpp/publisher_factory.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Implementation of the NodeTopics part of the Node API.
class NodeTopics : public NodeTopicsInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeTopicsInterface)
RCLCPP_PUBLIC
explicit NodeTopics(rclcpp::node_interfaces::NodeBaseInterface * node_base);
RCLCPP_PUBLIC
~NodeTopics() override;
RCLCPP_PUBLIC
rclcpp::PublisherBase::SharedPtr
create_publisher(
const std::string & topic_name,
const rclcpp::PublisherFactory & publisher_factory,
const rclcpp::QoS & qos) override;
RCLCPP_PUBLIC
void
add_publisher(
rclcpp::PublisherBase::SharedPtr publisher,
rclcpp::CallbackGroup::SharedPtr callback_group) override;
RCLCPP_PUBLIC
rclcpp::SubscriptionBase::SharedPtr
create_subscription(
const std::string & topic_name,
const rclcpp::SubscriptionFactory & subscription_factory,
const rclcpp::QoS & qos) override;
RCLCPP_PUBLIC
void
add_subscription(
rclcpp::SubscriptionBase::SharedPtr subscription,
rclcpp::CallbackGroup::SharedPtr callback_group) override;
RCLCPP_PUBLIC
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface() const override;
private:
RCLCPP_DISABLE_COPY(NodeTopics)
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_TOPICS_HPP_

View File

@@ -0,0 +1,88 @@
// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__NODE_TOPICS_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_TOPICS_INTERFACE_HPP_
#include <functional>
#include <memory>
#include <string>
#include "rcl/publisher.h"
#include "rcl/subscription.h"
#include "rclcpp/callback_group.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/publisher.hpp"
#include "rclcpp/publisher_factory.hpp"
#include "rclcpp/subscription.hpp"
#include "rclcpp/subscription_factory.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Pure virtual interface class for the NodeTopics part of the Node API.
class NodeTopicsInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeTopicsInterface)
RCLCPP_PUBLIC
virtual
~NodeTopicsInterface() = default;
RCLCPP_PUBLIC
virtual
rclcpp::PublisherBase::SharedPtr
create_publisher(
const std::string & topic_name,
const rclcpp::PublisherFactory & publisher_factory,
const rclcpp::QoS & qos) = 0;
RCLCPP_PUBLIC
virtual
void
add_publisher(
rclcpp::PublisherBase::SharedPtr publisher,
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
RCLCPP_PUBLIC
virtual
rclcpp::SubscriptionBase::SharedPtr
create_subscription(
const std::string & topic_name,
const rclcpp::SubscriptionFactory & subscription_factory,
const rclcpp::QoS & qos) = 0;
RCLCPP_PUBLIC
virtual
void
add_subscription(
rclcpp::SubscriptionBase::SharedPtr subscription,
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
RCLCPP_PUBLIC
virtual
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface() const = 0;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_TOPICS_INTERFACE_HPP_

View File

@@ -0,0 +1,66 @@
// 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.
#ifndef RCLCPP__NODE_INTERFACES__NODE_WAITABLES_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_WAITABLES_HPP_
#include "rclcpp/callback_group.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_waitables_interface.hpp"
#include "rclcpp/waitable.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Implementation of the NodeWaitables part of the Node API.
class NodeWaitables : public NodeWaitablesInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeWaitables)
RCLCPP_PUBLIC
explicit NodeWaitables(rclcpp::node_interfaces::NodeBaseInterface * node_base);
RCLCPP_PUBLIC
virtual
~NodeWaitables();
RCLCPP_PUBLIC
void
add_waitable(
rclcpp::Waitable::SharedPtr waitable_base_ptr,
rclcpp::CallbackGroup::SharedPtr group) override;
RCLCPP_PUBLIC
void
remove_waitable(
rclcpp::Waitable::SharedPtr waitable_ptr,
rclcpp::CallbackGroup::SharedPtr group) noexcept override;
private:
RCLCPP_DISABLE_COPY(NodeWaitables)
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_WAITABLES_HPP_

View File

@@ -0,0 +1,57 @@
// 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.
#ifndef RCLCPP__NODE_INTERFACES__NODE_WAITABLES_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_WAITABLES_INTERFACE_HPP_
#include "rclcpp/callback_group.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/waitable.hpp"
namespace rclcpp
{
namespace node_interfaces
{
/// Pure virtual interface class for the NodeWaitables part of the Node API.
class NodeWaitablesInterface
{
public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeWaitablesInterface)
RCLCPP_PUBLIC
virtual
~NodeWaitablesInterface() = default;
RCLCPP_PUBLIC
virtual
void
add_waitable(
rclcpp::Waitable::SharedPtr waitable_ptr,
rclcpp::CallbackGroup::SharedPtr group) = 0;
/// \note this function should not throw because it may be called in destructors
RCLCPP_PUBLIC
virtual
void
remove_waitable(
rclcpp::Waitable::SharedPtr waitable_ptr,
rclcpp::CallbackGroup::SharedPtr group) noexcept = 0;
};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__NODE_WAITABLES_INTERFACE_HPP_

View File

@@ -0,0 +1,374 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_OPTIONS_HPP_
#define RCLCPP__NODE_OPTIONS_HPP_
#include <memory>
#include <string>
#include <vector>
#include "rcl/node_options.h"
#include "rclcpp/context.hpp"
#include "rclcpp/contexts/default_context.hpp"
#include "rclcpp/parameter.hpp"
#include "rclcpp/publisher_options.hpp"
#include "rclcpp/qos.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
/// Encapsulation of options for node initialization.
class NodeOptions
{
public:
/// Create NodeOptions with default values, optionally specifying the allocator to use.
/**
* Default values for the node options:
*
* - context = rclcpp::contexts::get_global_default_context()
* - arguments = {}
* - parameter_overrides = {}
* - use_global_arguments = true
* - use_intra_process_comms = false
* - enable_topic_statistics = false
* - start_parameter_services = true
* - start_parameter_event_publisher = true
* - parameter_event_qos = rclcpp::ParameterEventQoS
* - with history setting and depth from rmw_qos_profile_parameter_events
* - parameter_event_publisher_options = rclcpp::PublisherOptionsBase
* - allow_undeclared_parameters = false
* - automatically_declare_parameters_from_overrides = false
* - allocator = rcl_get_default_allocator()
*
* \param[in] allocator allocator to use in construction of NodeOptions.
*/
RCLCPP_PUBLIC
explicit NodeOptions(rcl_allocator_t allocator = rcl_get_default_allocator());
/// Destructor.
RCLCPP_PUBLIC
virtual
~NodeOptions() = default;
/// Copy constructor.
RCLCPP_PUBLIC
NodeOptions(const NodeOptions & other);
/// Assignment operator.
RCLCPP_PUBLIC
NodeOptions &
operator=(const NodeOptions & other);
/// Return the rcl_node_options used by the node.
/**
* This data structure is created lazily, on the first call to this function.
* Repeated calls will not regenerate it unless one of the input settings
* changed, like arguments, use_global_arguments, or the rcl allocator.
*/
RCLCPP_PUBLIC
const rcl_node_options_t *
get_rcl_node_options() const;
/// Return the context to be used by the node.
RCLCPP_PUBLIC
rclcpp::Context::SharedPtr
context() const;
/// Set the context, return this for parameter idiom.
RCLCPP_PUBLIC
NodeOptions &
context(rclcpp::Context::SharedPtr context);
/// Return a reference to the list of arguments for the node.
RCLCPP_PUBLIC
const std::vector<std::string> &
arguments() const;
/// 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.
*
* This will cause the internal rcl_node_options_t struct to be invalidated.
*/
RCLCPP_PUBLIC
NodeOptions &
arguments(const std::vector<std::string> & arguments);
/// Return a reference to the list of parameter overrides.
RCLCPP_PUBLIC
std::vector<rclcpp::Parameter> &
parameter_overrides();
RCLCPP_PUBLIC
const std::vector<rclcpp::Parameter> &
parameter_overrides() const;
/// Set the parameters overrides, return this for parameter idiom.
/**
* These parameter overrides are used to change the initial value
* of declared parameters within the node, overriding hard coded default
* values if necessary.
*/
RCLCPP_PUBLIC
NodeOptions &
parameter_overrides(const std::vector<rclcpp::Parameter> & parameter_overrides);
/// Append a single parameter override, parameter idiom style.
template<typename ParameterT>
NodeOptions &
append_parameter_override(const std::string & name, const ParameterT & value)
{
this->parameter_overrides().emplace_back(name, rclcpp::ParameterValue(value));
return *this;
}
/// Return the use_global_arguments flag.
RCLCPP_PUBLIC
bool
use_global_arguments() const;
/// Set the use_global_arguments flag, return this for parameter idiom.
/**
* If true this will cause the node's behavior to be influenced by "global"
* arguments, i.e. arguments not targeted at specific nodes, as well as the
* arguments targeted at the current node.
*
* This will cause the internal rcl_node_options_t struct to be invalidated.
*/
RCLCPP_PUBLIC
NodeOptions &
use_global_arguments(bool use_global_arguments);
/// Return the enable_rosout flag.
RCLCPP_PUBLIC
bool
enable_rosout() const;
/// Set the enable_rosout flag, return this for parameter idiom.
/**
* If false this will cause the node not to use rosout logging.
*
* Defaults to true for now, as there are still some cases where it is
* desirable.
*/
RCLCPP_PUBLIC
NodeOptions &
enable_rosout(bool enable_rosout);
/// Return the use_intra_process_comms flag.
RCLCPP_PUBLIC
bool
use_intra_process_comms() const;
/// Set the use_intra_process_comms flag, return this for parameter idiom.
/**
* If true, messages on topics which are published and subscribed to within
* this context will go through a special intra-process communication code
* code path which can avoid serialization and deserialization, unnecessary
* copies, and achieve lower latencies in some cases.
*
* Defaults to false for now, as there are still some cases where it is not
* desirable.
*/
RCLCPP_PUBLIC
NodeOptions &
use_intra_process_comms(bool use_intra_process_comms);
/// Return the enable_topic_statistics flag.
RCLCPP_PUBLIC
bool
enable_topic_statistics() const;
/// Set the enable_topic_statistics flag, return this for parameter idiom.
/**
* If true, topic statistics collection and publication will be enabled
* for all subscriptions.
* This can be used to override the global topic statistics setting.
*
* Defaults to false.
*/
RCLCPP_PUBLIC
NodeOptions &
enable_topic_statistics(bool enable_topic_statistics);
/// Return the start_parameter_services flag.
RCLCPP_PUBLIC
bool
start_parameter_services() const;
/// Set the start_parameter_services flag, return this for parameter idiom.
/**
* If true, ROS services are created to allow external nodes to list, get,
* and request to set parameters of this node.
*
* If false, parameters will still work locally, but will not be accessible
* remotely.
*
* \sa start_parameter_event_publisher()
*/
RCLCPP_PUBLIC
NodeOptions &
start_parameter_services(bool start_parameter_services);
/// Return the start_parameter_event_publisher flag.
RCLCPP_PUBLIC
bool
start_parameter_event_publisher() const;
/// Set the start_parameter_event_publisher flag, return this for parameter idiom.
/**
* If true, a publisher is created on which an event message is published
* each time a parameter's state changes.
* This is used for recording and introspection, but is configurable
* separately from the other parameter services.
*/
RCLCPP_PUBLIC
NodeOptions &
start_parameter_event_publisher(bool start_parameter_event_publisher);
/// Return a reference to the parameter_event_qos QoS.
RCLCPP_PUBLIC
const rclcpp::QoS &
parameter_event_qos() const;
/// Set the parameter_event_qos QoS, return this for parameter idiom.
/**
* The QoS settings to be used for the parameter event publisher, if enabled.
*/
RCLCPP_PUBLIC
NodeOptions &
parameter_event_qos(const rclcpp::QoS & parameter_event_qos);
/// Return a reference to the parameter_event_publisher_options.
RCLCPP_PUBLIC
const rclcpp::PublisherOptionsBase &
parameter_event_publisher_options() const;
/// Set the parameter_event_publisher_options, return this for parameter idiom.
/**
* The QoS settings to be used for the parameter event publisher, if enabled.
*
* \todo(wjwwood): make this take/store an instance of
* rclcpp::PublisherOptionsWithAllocator<Allocator>, but to do that requires
* NodeOptions to also be templated based on the Allocator type.
*/
RCLCPP_PUBLIC
NodeOptions &
parameter_event_publisher_options(
const rclcpp::PublisherOptionsBase & parameter_event_publisher_options);
/// Return the allow_undeclared_parameters flag.
RCLCPP_PUBLIC
bool
allow_undeclared_parameters() const;
/// Set the allow_undeclared_parameters, return this for parameter idiom.
/**
* If true, allow any parameter name to be set on the node without first
* being declared.
* Otherwise, setting an undeclared parameter will raise an exception.
*
* This option being true does not affect parameter_overrides, as the first
* set action will implicitly declare the parameter and therefore consider
* any parameter overrides.
*/
RCLCPP_PUBLIC
NodeOptions &
allow_undeclared_parameters(bool allow_undeclared_parameters);
/// Return the automatically_declare_parameters_from_overrides flag.
RCLCPP_PUBLIC
bool
automatically_declare_parameters_from_overrides() const;
/// Set the automatically_declare_parameters_from_overrides, return this.
/**
* If true, automatically iterate through the node's parameter overrides and
* implicitly declare any that have not already been declared.
* Otherwise, parameters passed to the node's parameter_overrides, and/or the
* global arguments (e.g. parameter overrides from a YAML file), which are
* not explicitly declared will not appear on the node at all, even if
* `allow_undeclared_parameters` is true.
* Already declared parameters will not be re-declared, and parameters
* declared in this way will use the default constructed ParameterDescriptor.
*/
RCLCPP_PUBLIC
NodeOptions &
automatically_declare_parameters_from_overrides(
bool automatically_declare_parameters_from_overrides);
/// Return the rcl_allocator_t to be used.
RCLCPP_PUBLIC
const rcl_allocator_t &
allocator() const;
/// Set the rcl_allocator_t to be used, may cause deallocation of existing rcl_node_options_t.
/**
* This will cause the internal rcl_node_options_t struct to be invalidated.
*/
RCLCPP_PUBLIC
NodeOptions &
allocator(rcl_allocator_t allocator);
protected:
/// Retrieve the ROS_DOMAIN_ID environment variable and populate options.
size_t
get_domain_id_from_env() const;
private:
// This is mutable to allow for a const accessor which lazily creates the node options instance.
/// Underlying rcl_node_options structure.
mutable std::unique_ptr<rcl_node_options_t, void (*)(rcl_node_options_t *)> node_options_;
// IMPORTANT: if any of these default values are changed, please update the
// documentation in this class.
rclcpp::Context::SharedPtr context_ {
rclcpp::contexts::get_global_default_context()};
std::vector<std::string> arguments_ {};
std::vector<rclcpp::Parameter> parameter_overrides_ {};
bool use_global_arguments_ {true};
bool enable_rosout_ {true};
bool use_intra_process_comms_ {false};
bool enable_topic_statistics_ {false};
bool start_parameter_services_ {true};
bool start_parameter_event_publisher_ {true};
rclcpp::QoS parameter_event_qos_ = rclcpp::ParameterEventsQoS(
rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events)
);
rclcpp::PublisherOptionsBase parameter_event_publisher_options_ = rclcpp::PublisherOptionsBase();
bool allow_undeclared_parameters_ {false};
bool automatically_declare_parameters_from_overrides_ {false};
rcl_allocator_t allocator_ {rcl_get_default_allocator()};
};
} // namespace rclcpp
#endif // RCLCPP__NODE_OPTIONS_HPP_

View File

@@ -15,54 +15,73 @@
#ifndef RCLCPP__PARAMETER_HPP_
#define RCLCPP__PARAMETER_HPP_
#include <iostream>
#include <ostream>
#include <sstream>
#include <string>
#include <vector>
#include "rcl_interfaces/msg/parameter.hpp"
#include "rcl_interfaces/msg/parameter_type.hpp"
#include "rcl_interfaces/msg/parameter_value.hpp"
#include "rclcpp/exceptions.hpp"
#include "rclcpp/parameter_value.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rmw/rmw.h"
namespace rclcpp
{
namespace parameter
class Parameter;
namespace node_interfaces
{
struct ParameterInfo;
} // namespace node_interfaces
namespace detail
{
enum ParameterType
{
PARAMETER_NOT_SET = rcl_interfaces::msg::ParameterType::PARAMETER_NOT_SET,
PARAMETER_BOOL = rcl_interfaces::msg::ParameterType::PARAMETER_BOOL,
PARAMETER_INTEGER = rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER,
PARAMETER_DOUBLE = rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE,
PARAMETER_STRING = rcl_interfaces::msg::ParameterType::PARAMETER_STRING,
PARAMETER_BYTES = rcl_interfaces::msg::ParameterType::PARAMETER_BYTES,
};
// This helper function is required because you cannot do specialization on a
// class method, so instead we specialize this template function and call it
// from the unspecialized, but dependent, class method.
template<typename T>
auto
get_value_helper(const rclcpp::Parameter * parameter);
// Structure to store an arbitrary parameter with templated get/set methods
class ParameterVariant
} // namespace detail
/// Structure to store an arbitrary parameter with templated get/set methods.
class Parameter
{
public:
/// Construct with an empty name and a parameter value of type rclcpp::PARAMETER_NOT_SET.
RCLCPP_PUBLIC
ParameterVariant();
Parameter();
/// Construct with given name and a parameter value of type rclcpp::PARAMETER_NOT_SET.
RCLCPP_PUBLIC
explicit ParameterVariant(const std::string & name, const bool bool_value);
explicit Parameter(const std::string & name);
/// Construct with given name and given parameter value.
RCLCPP_PUBLIC
explicit ParameterVariant(const std::string & name, const int int_value);
Parameter(const std::string & name, const ParameterValue & value);
/// Construct with given name and given parameter value.
template<typename ValueTypeT>
Parameter(const std::string & name, ValueTypeT value)
: Parameter(name, ParameterValue(value))
{}
RCLCPP_PUBLIC
explicit ParameterVariant(const std::string & name, const int64_t int_value);
explicit Parameter(const rclcpp::node_interfaces::ParameterInfo & parameter_info);
/// Equal operator.
RCLCPP_PUBLIC
explicit ParameterVariant(const std::string & name, const float double_value);
bool
operator==(const Parameter & rhs) const;
/// Not equal operator.
RCLCPP_PUBLIC
explicit ParameterVariant(const std::string & name, const double double_value);
RCLCPP_PUBLIC
explicit ParameterVariant(const std::string & name, const std::string & string_value);
RCLCPP_PUBLIC
explicit ParameterVariant(const std::string & name, const char * string_value);
RCLCPP_PUBLIC
explicit ParameterVariant(const std::string & name, const std::vector<uint8_t> & bytes_value);
bool
operator!=(const Parameter & rhs) const;
RCLCPP_PUBLIC
ParameterType
@@ -78,105 +97,29 @@ public:
RCLCPP_PUBLIC
rcl_interfaces::msg::ParameterValue
get_value_message() const;
/// Get the internal storage for the parameter value.
RCLCPP_PUBLIC
const rclcpp::ParameterValue &
get_parameter_value() const;
// The following get_value() variants require the use of ParameterType
template<ParameterType type>
typename std::enable_if<type == ParameterType::PARAMETER_INTEGER, int64_t>::type
/// Get value of parameter using rclcpp::ParameterType as template argument.
template<ParameterType ParamT>
decltype(auto)
get_value() const
{
if (value_.type != rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER) {
// TODO(wjwwood): use custom exception
throw std::runtime_error("Invalid type");
}
return value_.integer_value;
return value_.get<ParamT>();
}
template<ParameterType type>
typename std::enable_if<type == ParameterType::PARAMETER_DOUBLE, double>::type
get_value() const
{
if (value_.type != rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE) {
// TODO(wjwwood): use custom exception
throw std::runtime_error("Invalid type");
}
return value_.double_value;
}
/// Get value of parameter using c++ types as template argument.
template<typename T>
decltype(auto)
get_value() const;
template<ParameterType type>
typename std::enable_if<type == ParameterType::PARAMETER_STRING, const std::string &>::type
get_value() const
{
if (value_.type != rcl_interfaces::msg::ParameterType::PARAMETER_STRING) {
// TODO(wjwwood): use custom exception
throw std::runtime_error("Invalid type");
}
return value_.string_value;
}
template<ParameterType type>
typename std::enable_if<type == ParameterType::PARAMETER_BOOL, bool>::type
get_value() const
{
if (value_.type != rcl_interfaces::msg::ParameterType::PARAMETER_BOOL) {
// TODO(wjwwood): use custom exception
throw std::runtime_error("Invalid type");
}
return value_.bool_value;
}
template<ParameterType type>
typename std::enable_if<
type == ParameterType::PARAMETER_BYTES, const std::vector<uint8_t> &>::type
get_value() const
{
if (value_.type != rcl_interfaces::msg::ParameterType::PARAMETER_BYTES) {
// TODO(wjwwood): use custom exception
throw std::runtime_error("Invalid type");
}
return value_.bytes_value;
}
// The following get_value() variants allow the use of primitive types
template<typename type>
typename std::enable_if<
std::is_integral<type>::value && !std::is_same<type, bool>::value, int64_t>::type
get_value() const
{
return get_value<ParameterType::PARAMETER_INTEGER>();
}
template<typename type>
typename std::enable_if<std::is_floating_point<type>::value, double>::type
get_value() const
{
return get_value<ParameterType::PARAMETER_DOUBLE>();
}
template<typename type>
typename std::enable_if<std::is_convertible<type, std::string>::value, const std::string &>::type
get_value() const
{
return get_value<ParameterType::PARAMETER_STRING>();
}
template<typename type>
typename std::enable_if<std::is_same<type, bool>::value, bool>::type
get_value() const
{
return get_value<ParameterType::PARAMETER_BOOL>();
}
template<typename type>
typename std::enable_if<
std::is_convertible<
type, const std::vector<uint8_t> &>::value, const std::vector<uint8_t> &>::type
get_value() const
{
return get_value<ParameterType::PARAMETER_BYTES>();
}
RCLCPP_PUBLIC
bool
as_bool() const;
RCLCPP_PUBLIC
int64_t
@@ -190,21 +133,33 @@ public:
const std::string &
as_string() const;
RCLCPP_PUBLIC
bool
as_bool() const;
RCLCPP_PUBLIC
const std::vector<uint8_t> &
as_bytes() const;
as_byte_array() const;
RCLCPP_PUBLIC
static ParameterVariant
from_parameter(const rcl_interfaces::msg::Parameter & parameter);
const std::vector<bool> &
as_bool_array() const;
RCLCPP_PUBLIC
const std::vector<int64_t> &
as_integer_array() const;
RCLCPP_PUBLIC
const std::vector<double> &
as_double_array() const;
RCLCPP_PUBLIC
const std::vector<std::string> &
as_string_array() const;
RCLCPP_PUBLIC
static Parameter
from_parameter_msg(const rcl_interfaces::msg::Parameter & parameter);
RCLCPP_PUBLIC
rcl_interfaces::msg::Parameter
to_parameter();
to_parameter_msg() const;
RCLCPP_PUBLIC
std::string
@@ -212,38 +167,83 @@ public:
private:
std::string name_;
rcl_interfaces::msg::ParameterValue value_;
ParameterValue value_;
};
/* Return a json encoded version of the parameter intended for a dict. */
/// Return a json encoded version of the parameter intended for a dict.
RCLCPP_PUBLIC
std::string
_to_json_dict_entry(const ParameterVariant & param);
_to_json_dict_entry(const Parameter & param);
RCLCPP_PUBLIC
std::ostream &
operator<<(std::ostream & os, const rclcpp::parameter::ParameterVariant & pv);
operator<<(std::ostream & os, const rclcpp::Parameter & pv);
RCLCPP_PUBLIC
std::ostream &
operator<<(std::ostream & os, const std::vector<ParameterVariant> & parameters);
operator<<(std::ostream & os, const std::vector<Parameter> & parameters);
namespace detail
{
template<typename T>
auto
get_value_helper(const rclcpp::Parameter * parameter)
{
return parameter->get_parameter_value().get<T>();
}
// Specialization allowing Parameter::get() to return a const ref to the parameter value object.
template<>
inline
auto
get_value_helper<rclcpp::ParameterValue>(const rclcpp::Parameter * parameter)
{
return parameter->get_parameter_value();
}
// Specialization allowing Parameter::get() to return a const ref to the parameter itself.
template<>
inline
auto
get_value_helper<rclcpp::Parameter>(const rclcpp::Parameter * parameter)
{
// Use this lambda to ensure it's a const reference being returned (and not a copy).
auto type_enforcing_lambda =
[&parameter]() -> const rclcpp::Parameter & {
return *parameter;
};
return type_enforcing_lambda();
}
} // namespace detail
template<typename T>
decltype(auto)
Parameter::get_value() const
{
try {
// use the helper to specialize for the ParameterValue and Parameter cases.
return detail::get_value_helper<T>(this);
} catch (const ParameterTypeException & ex) {
throw exceptions::InvalidParameterTypeException(this->name_, ex.what());
}
}
} // namespace parameter
} // namespace rclcpp
namespace std
{
/* Return a json encoded version of the parameter intended for a list. */
/// Return a json encoded version of the parameter intended for a list.
RCLCPP_PUBLIC
std::string
to_string(const rclcpp::parameter::ParameterVariant & param);
to_string(const rclcpp::Parameter & param);
/* Return a json encoded version of a vector of parameters, as a string*/
/// Return a json encoded version of a vector of parameters, as a string.
RCLCPP_PUBLIC
std::string
to_string(const std::vector<rclcpp::parameter::ParameterVariant> & parameters);
to_string(const std::vector<rclcpp::Parameter> & parameters);
} // namespace std

View File

@@ -15,6 +15,7 @@
#ifndef RCLCPP__PARAMETER_CLIENT_HPP_
#define RCLCPP__PARAMETER_CLIENT_HPP_
#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -29,6 +30,7 @@
#include "rcl_interfaces/srv/set_parameters.hpp"
#include "rcl_interfaces/srv/set_parameters_atomically.hpp"
#include "rclcpp/executors.hpp"
#include "rclcpp/create_subscription.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/parameter.hpp"
@@ -38,40 +40,56 @@
namespace rclcpp
{
namespace parameter_client
{
class AsyncParametersClient
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(AsyncParametersClient);
RCLCPP_SMART_PTR_DEFINITIONS(AsyncParametersClient)
RCLCPP_PUBLIC
AsyncParametersClient(
const rclcpp::node::Node::SharedPtr node,
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
rclcpp::CallbackGroup::SharedPtr group = nullptr);
RCLCPP_PUBLIC
std::shared_future<std::vector<rclcpp::parameter::ParameterVariant>>
AsyncParametersClient(
const rclcpp::Node::SharedPtr node,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
rclcpp::CallbackGroup::SharedPtr group = nullptr);
RCLCPP_PUBLIC
AsyncParametersClient(
rclcpp::Node * node,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
rclcpp::CallbackGroup::SharedPtr group = nullptr);
RCLCPP_PUBLIC
std::shared_future<std::vector<rclcpp::Parameter>>
get_parameters(
const std::vector<std::string> & names,
std::function<
void(std::shared_future<std::vector<rclcpp::parameter::ParameterVariant>>)
void(std::shared_future<std::vector<rclcpp::Parameter>>)
> callback = nullptr);
RCLCPP_PUBLIC
std::shared_future<std::vector<rclcpp::parameter::ParameterType>>
std::shared_future<std::vector<rclcpp::ParameterType>>
get_parameter_types(
const std::vector<std::string> & names,
std::function<
void(std::shared_future<std::vector<rclcpp::parameter::ParameterType>>)
void(std::shared_future<std::vector<rclcpp::ParameterType>>)
> callback = nullptr);
RCLCPP_PUBLIC
std::shared_future<std::vector<rcl_interfaces::msg::SetParametersResult>>
set_parameters(
const std::vector<rclcpp::parameter::ParameterVariant> & parameters,
const std::vector<rclcpp::Parameter> & parameters,
std::function<
void(std::shared_future<std::vector<rcl_interfaces::msg::SetParametersResult>>)
> callback = nullptr);
@@ -79,7 +97,7 @@ public:
RCLCPP_PUBLIC
std::shared_future<rcl_interfaces::msg::SetParametersResult>
set_parameters_atomically(
const std::vector<rclcpp::parameter::ParameterVariant> & parameters,
const std::vector<rclcpp::Parameter> & parameters,
std::function<
void(std::shared_future<rcl_interfaces::msg::SetParametersResult>)
> callback = nullptr);
@@ -93,24 +111,83 @@ public:
void(std::shared_future<rcl_interfaces::msg::ListParametersResult>)
> callback = nullptr);
template<typename CallbackT>
typename rclcpp::subscription::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
on_parameter_event(CallbackT && callback)
template<
typename CallbackT,
typename AllocatorT = std::allocator<void>>
typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
on_parameter_event(
CallbackT && callback,
const rclcpp::QoS & qos = (
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events))
),
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
))
{
return node_->create_subscription<rcl_interfaces::msg::ParameterEvent>(
"parameter_events", std::forward<CallbackT>(callback), rmw_qos_profile_parameter_events);
return this->on_parameter_event(
this->node_topics_interface_,
callback,
qos,
options);
}
/**
* The NodeT type only needs to have a method called get_node_topics_interface()
* which returns a shared_ptr to a NodeTopicsInterface, or be a
* NodeTopicsInterface pointer itself.
*/
template<
typename CallbackT,
typename NodeT,
typename AllocatorT = std::allocator<void>>
static typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
on_parameter_event(
NodeT && node,
CallbackT && callback,
const rclcpp::QoS & qos = (
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events))
),
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
))
{
return rclcpp::create_subscription<rcl_interfaces::msg::ParameterEvent>(
node,
"parameter_events",
qos,
std::forward<CallbackT>(callback),
options);
}
RCLCPP_PUBLIC
bool
service_is_ready() const;
template<typename RepT = int64_t, typename RatioT = std::milli>
bool
wait_for_service(
std::chrono::duration<RepT, RatioT> timeout = std::chrono::duration<RepT, RatioT>(-1))
{
return wait_for_service_nanoseconds(
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
);
}
protected:
RCLCPP_PUBLIC
bool
wait_for_service_nanoseconds(std::chrono::nanoseconds timeout);
private:
const rclcpp::node::Node::SharedPtr node_;
rclcpp::client::Client<rcl_interfaces::srv::GetParameters>::SharedPtr get_parameters_client_;
rclcpp::client::Client<rcl_interfaces::srv::GetParameterTypes>::SharedPtr
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface_;
rclcpp::Client<rcl_interfaces::srv::GetParameters>::SharedPtr get_parameters_client_;
rclcpp::Client<rcl_interfaces::srv::GetParameterTypes>::SharedPtr
get_parameter_types_client_;
rclcpp::client::Client<rcl_interfaces::srv::SetParameters>::SharedPtr set_parameters_client_;
rclcpp::client::Client<rcl_interfaces::srv::SetParametersAtomically>::SharedPtr
rclcpp::Client<rcl_interfaces::srv::SetParameters>::SharedPtr set_parameters_client_;
rclcpp::Client<rcl_interfaces::srv::SetParametersAtomically>::SharedPtr
set_parameters_atomically_client_;
rclcpp::client::Client<rcl_interfaces::srv::ListParameters>::SharedPtr list_parameters_client_;
rclcpp::client::Client<rcl_interfaces::srv::DescribeParameters>::SharedPtr
rclcpp::Client<rcl_interfaces::srv::ListParameters>::SharedPtr list_parameters_client_;
rclcpp::Client<rcl_interfaces::srv::DescribeParameters>::SharedPtr
describe_parameters_client_;
std::string remote_node_name_;
};
@@ -118,21 +195,46 @@ private:
class SyncParametersClient
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(SyncParametersClient);
RCLCPP_SMART_PTR_DEFINITIONS(SyncParametersClient)
RCLCPP_PUBLIC
explicit SyncParametersClient(
rclcpp::node::Node::SharedPtr node,
rclcpp::Node::SharedPtr node,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
RCLCPP_PUBLIC
SyncParametersClient(
rclcpp::executor::Executor::SharedPtr executor,
rclcpp::node::Node::SharedPtr node,
rclcpp::Executor::SharedPtr executor,
rclcpp::Node::SharedPtr node,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
RCLCPP_PUBLIC
std::vector<rclcpp::parameter::ParameterVariant>
explicit SyncParametersClient(
rclcpp::Node * node,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
RCLCPP_PUBLIC
SyncParametersClient(
rclcpp::Executor::SharedPtr executor,
rclcpp::Node * node,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
RCLCPP_PUBLIC
SyncParametersClient(
rclcpp::Executor::SharedPtr executor,
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
RCLCPP_PUBLIC
std::vector<rclcpp::Parameter>
get_parameters(const std::vector<std::string> & parameter_names);
RCLCPP_PUBLIC
@@ -147,7 +249,7 @@ public:
std::vector<std::string> names;
names.push_back(parameter_name);
auto vars = get_parameters(names);
if ((vars.size() != 1) || (vars[0].get_type() == rclcpp::parameter::PARAMETER_NOT_SET)) {
if ((vars.size() != 1) || (vars[0].get_type() == rclcpp::ParameterType::PARAMETER_NOT_SET)) {
return parameter_not_found_handler();
} else {
return static_cast<T>(vars[0].get_value<T>());
@@ -158,33 +260,36 @@ public:
T
get_parameter(const std::string & parameter_name, const T & default_value)
{
// *INDENT-OFF*
return get_parameter_impl(parameter_name,
std::function<T()>([&default_value]() -> T {return default_value; }));
// *INDENT-ON*
return get_parameter_impl(
parameter_name,
std::function<T()>([&default_value]() -> T {return default_value;}));
}
template<typename T>
T
get_parameter(const std::string & parameter_name)
{
// *INDENT-OFF*
return get_parameter_impl(parameter_name,
std::function<T()>([]() -> T {throw std::runtime_error("Parameter not set"); }));
// *INDENT-ON*
return get_parameter_impl(
parameter_name,
std::function<T()>(
[&parameter_name]() -> T
{
throw std::runtime_error("Parameter '" + parameter_name + "' is not set");
})
);
}
RCLCPP_PUBLIC
std::vector<rclcpp::parameter::ParameterType>
std::vector<rclcpp::ParameterType>
get_parameter_types(const std::vector<std::string> & parameter_names);
RCLCPP_PUBLIC
std::vector<rcl_interfaces::msg::SetParametersResult>
set_parameters(const std::vector<rclcpp::parameter::ParameterVariant> & parameters);
set_parameters(const std::vector<rclcpp::Parameter> & parameters);
RCLCPP_PUBLIC
rcl_interfaces::msg::SetParametersResult
set_parameters_atomically(const std::vector<rclcpp::parameter::ParameterVariant> & parameters);
set_parameters_atomically(const std::vector<rclcpp::Parameter> & parameters);
RCLCPP_PUBLIC
rcl_interfaces::msg::ListParametersResult
@@ -193,19 +298,52 @@ public:
uint64_t depth);
template<typename CallbackT>
typename rclcpp::subscription::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
on_parameter_event(CallbackT && callback)
{
return async_parameters_client_->on_parameter_event(std::forward<CallbackT>(callback));
return async_parameters_client_->on_parameter_event(
std::forward<CallbackT>(callback));
}
/**
* The NodeT type only needs to have a method called get_node_topics_interface()
* which returns a shared_ptr to a NodeTopicsInterface, or be a
* NodeTopicsInterface pointer itself.
*/
template<
typename CallbackT,
typename NodeT>
static typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
on_parameter_event(
NodeT && node,
CallbackT && callback)
{
return AsyncParametersClient::on_parameter_event(
node,
std::forward<CallbackT>(callback));
}
RCLCPP_PUBLIC
bool
service_is_ready() const
{
return async_parameters_client_->service_is_ready();
}
template<typename RepT = int64_t, typename RatioT = std::milli>
bool
wait_for_service(
std::chrono::duration<RepT, RatioT> timeout = std::chrono::duration<RepT, RatioT>(-1))
{
return async_parameters_client_->wait_for_service(timeout);
}
private:
rclcpp::executor::Executor::SharedPtr executor_;
rclcpp::node::Node::SharedPtr node_;
rclcpp::Executor::SharedPtr executor_;
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface_;
AsyncParametersClient::SharedPtr async_parameters_client_;
};
} // namespace parameter_client
} // namespace rclcpp
#endif // RCLCPP__PARAMETER_CLIENT_HPP_

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