Compare commits

...

18 Commits

Author SHA1 Message Date
Jacob Perron
1c943d16fc 0.9.0 2020-04-29 22:44:16 -07:00
brawner
e6325839f1 Increasing test coverage of rclcpp_action (#1043)
* Increasing test coverage of rclcpp_action

Signed-off-by: Stephen Brawner <brawner@gmail.com>

* PR Fixup

Signed-off-by: Stephen Brawner <brawner@gmail.com>

* PR Fixup

Signed-off-by: Stephen Brawner <brawner@gmail.com>

* PR Fixup

Signed-off-by: Stephen Brawner <brawner@gmail.com>

* Increasing test coverage of rclcpp_action

Signed-off-by: Stephen Brawner <brawner@gmail.com>

* PR Fixup

Signed-off-by: Stephen Brawner <brawner@gmail.com>

* PR Fixup

Signed-off-by: Stephen Brawner <brawner@gmail.com>

* PR Fixup

Signed-off-by: Stephen Brawner <brawner@gmail.com>

* Fix warnings

Signed-off-by: Stephen Brawner <brawner@gmail.com>
2020-04-29 14:25:52 -07:00
Alejandro Hernández Cordero
9150201d28 Added rclcpp_components Doxyfile (#1091)
* Added rclcpp components Doxyfile

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

* Added feedback

Signed-off-by: ahcorde <ahcorde@gmail.com>
2020-04-29 08:45:04 +02:00
Karsten Knese
c1b80bd367 Serialized message move constructor (#1097)
* correct use of move semantics

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

* more tests

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

* make error message more exact

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

* use std::exchange

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

* fix typo

Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2020-04-27 22:23:43 -07:00
Michel Hidalgo
814298480c Enforce a precedence for wildcard matching in parameter overrides. (#1094)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2020-04-27 15:14:48 -03:00
Dirk Thomas
45f3976453 export targets in a addition to include directories / libraries (#1096)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2020-04-27 10:30:33 -07:00
brawner
e0bf4a9c20 Add serialized_message.hpp header (#1095)
Signed-off-by: Stephen Brawner <brawner@gmail.com>
2020-04-26 21:40:40 -07:00
Prajakta Gokhale
04f3c33de5 Add received message age metric to topic statistics (#1080)
* Add received message age metric to topic statistics

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

* Add unit tests

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

* Add IMU messages in unit test

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

* Use system time instead of steady time
Test received message age stats values are greater than 0

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

* Fix test warnings

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

* Replace IMU messages with new dummy messages

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

* Remove outdated TODO and unused test variables

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

* Address review comments

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

* Address review comments

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

* Re-add message with header for unit testing

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

* Address message review feedback

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

* Remove extra newline

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

* Address more review feedback

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

* Fix Windows failure

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

* Only set append_library_dirs once

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>
2020-04-23 20:41:35 -07:00
William Woodall
df3c2ffa8a deprecate redundant namespaces (#1083)
* deprecate redundant namespaces, move classes to own files, rename some classes

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

* fixup

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

* address review comments

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

* fix ups since rebase

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

* avoid deprecation warnings from deprecated functions

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

* more fixes

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

* another fixup, after another rebase

Signed-off-by: William Woodall <william@osrfoundation.org>
2020-04-23 15:28:45 -07:00
Dirk Thomas
52ae3e0337 export targets in a addition to include directories / libraries (#1088)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2020-04-23 14:18:51 -07:00
Ivan Santiago Paunovic
80e8dcad02 Ensure logging is initialized just once (#998)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
2020-04-23 17:33:56 -03:00
Karsten Knese
e64022f753 adapt subscription traits to rclcpp::SerializedMessage (#1092)
Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2020-04-23 15:09:40 -03:00
tomoya
c3d599fc8c protect subscriber_statistics_collectors_ with a mutex (#1084)
* subscriber_statistics_collectors_ should be protected with mutex.

Co-Authored-By: William Woodall <william+github@osrfoundation.org>
Signed-off-by: Tomoya.Fujita <Tomoya.Fujita@sony.com>
2020-04-22 23:55:04 -07:00
Devin Bonnie
cdeed8903d Remove unused test variable (#1087)
Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>
2020-04-22 21:45:50 -07:00
Karsten Knese
46cfe84b14 Use serialized message (#1081)
* use serialized message in callback

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

* introduce resize method for serialized message

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

* introduce release for serialized message

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

* address review comments

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

* correct typo

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

* fix interface traits test

Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2020-04-22 19:30:56 -07:00
Devin Bonnie
bb91b6c2ef Integrate topic statistics (#1072)
* 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>

* 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>

* Initial integration of Subscriber Topic Statistics

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

* Fix nanoseconds used for Topic Stats

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

* Add simple publishing test
Minor fixes

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

* Add test utils header

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

* Integrate with Topic Statistics options
Fixes after rebasing with master

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

* Update after rebasing

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

* Address minor review comments

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

* Move Topic Statistics instantiation to create_subscription

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

* Fix rebase issue
Fix topic statistics enable flag usage
Address minor formatting

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

* Move new timer creation method to relevant header

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

* Add timers interface to topic interface

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

* Use new create timer method

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

* Address review comments

Signed-off-by: Devin Bonnie <dbbonnie@amazon.com>
2020-04-22 16:09:41 -07:00
Karsten Knese
4eab2a3c60 Fix rclcpp interface traits test (#1086)
Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2020-04-22 14:19:39 -07:00
Michel Hidalgo
bb8c8ff2c0 Generate node interfaces' getters and traits. (#1069)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Co-authored-by: Karsten Knese <karsten@openrobotics.org>
2020-04-22 17:02:02 -03:00
123 changed files with 2256 additions and 1193 deletions

View File

@@ -2,6 +2,89 @@
Changelog for package rclcpp
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.9.0 (2020-04-29)
------------------
* Serialized message move constructor (`#1097 <https://github.com/ros2/rclcpp/issues/1097>`_)
* Enforce a precedence for wildcard matching in parameter overrides. (`#1094 <https://github.com/ros2/rclcpp/issues/1094>`_)
* Add serialized_message.hpp header (`#1095 <https://github.com/ros2/rclcpp/issues/1095>`_)
* Add received message age metric to topic statistics (`#1080 <https://github.com/ros2/rclcpp/issues/1080>`_)
* Deprecate redundant namespaces (`#1083 <https://github.com/ros2/rclcpp/issues/1083>`_)
* Export targets in addition to include directories / libraries (`#1088 <https://github.com/ros2/rclcpp/issues/1088>`_)
* Ensure logging is initialized just once (`#998 <https://github.com/ros2/rclcpp/issues/998>`_)
* Adapt subscription traits to rclcpp::SerializedMessage (`#1092 <https://github.com/ros2/rclcpp/issues/1092>`_)
* Protect subscriber_statistics_collectors\_ with a mutex (`#1084 <https://github.com/ros2/rclcpp/issues/1084>`_)
* Remove unused test variable (`#1087 <https://github.com/ros2/rclcpp/issues/1087>`_)
* Use serialized message (`#1081 <https://github.com/ros2/rclcpp/issues/1081>`_)
* Integrate topic statistics (`#1072 <https://github.com/ros2/rclcpp/issues/1072>`_)
* Fix rclcpp interface traits test (`#1086 <https://github.com/ros2/rclcpp/issues/1086>`_)
* Generate node interfaces' getters and traits (`#1069 <https://github.com/ros2/rclcpp/issues/1069>`_)
* Use composition for serialized message (`#1082 <https://github.com/ros2/rclcpp/issues/1082>`_)
* Dnae adas/serialized message (`#1075 <https://github.com/ros2/rclcpp/issues/1075>`_)
* Reflect changes in rclcpp API (`#1079 <https://github.com/ros2/rclcpp/issues/1079>`_)
* Fix build regression (`#1078 <https://github.com/ros2/rclcpp/issues/1078>`_)
* Add NodeDefault option for enabling topic statistics (`#1074 <https://github.com/ros2/rclcpp/issues/1074>`_)
* Topic Statistics: Add SubscriptionTopicStatistics class (`#1050 <https://github.com/ros2/rclcpp/issues/1050>`_)
* Add SubscriptionOptions for topic statistics (`#1057 <https://github.com/ros2/rclcpp/issues/1057>`_)
* Remove warning message from failing to register default callback (`#1067 <https://github.com/ros2/rclcpp/issues/1067>`_)
* Create a default warning for qos incompatibility (`#1051 <https://github.com/ros2/rclcpp/issues/1051>`_)
* Add WaitSet class and modify entities to work without executor (`#1047 <https://github.com/ros2/rclcpp/issues/1047>`_)
* Include what you use (`#1059 <https://github.com/ros2/rclcpp/issues/1059>`_)
* Rename rosidl_generator_cpp namespace to rosidl_runtime_cpp (`#1060 <https://github.com/ros2/rclcpp/issues/1060>`_)
* Changed rosidl_generator_c/cpp to rosidl_runtime_c/cpp (`#1014 <https://github.com/ros2/rclcpp/issues/1014>`_)
* Use constexpr for endpoint type name (`#1055 <https://github.com/ros2/rclcpp/issues/1055>`_)
* Add InvalidParameterTypeException (`#1027 <https://github.com/ros2/rclcpp/issues/1027>`_)
* Support for ON_REQUESTED_INCOMPATIBLE_QOS and ON_OFFERED_INCOMPATIBLE_QOS events (`#924 <https://github.com/ros2/rclcpp/issues/924>`_)
* Fixup clang warning (`#1040 <https://github.com/ros2/rclcpp/issues/1040>`_)
* Adding a "static" single threaded executor (`#1034 <https://github.com/ros2/rclcpp/issues/1034>`_)
* Add equality operators for QoS profile (`#1032 <https://github.com/ros2/rclcpp/issues/1032>`_)
* Remove extra vertical whitespace (`#1030 <https://github.com/ros2/rclcpp/issues/1030>`_)
* Switch IntraProcessMessage to test_msgs/Empty (`#1017 <https://github.com/ros2/rclcpp/issues/1017>`_)
* Add new type of exception that may be thrown during creation of publisher/subscription (`#1026 <https://github.com/ros2/rclcpp/issues/1026>`_)
* Don't check lifespan on publisher QoS (`#1002 <https://github.com/ros2/rclcpp/issues/1002>`_)
* Fix get_parameter_tyeps of AsyncPrameterClient results are always empty (`#1019 <https://github.com/ros2/rclcpp/issues/1019>`_)
* Cleanup node interfaces includes (`#1016 <https://github.com/ros2/rclcpp/issues/1016>`_)
* Add ifdefs to remove tracing-related calls if tracing is disabled (`#1001 <https://github.com/ros2/rclcpp/issues/1001>`_)
* Include missing header in node_graph.cpp (`#994 <https://github.com/ros2/rclcpp/issues/994>`_)
* Add missing includes of logging.hpp (`#995 <https://github.com/ros2/rclcpp/issues/995>`_)
* Zero initialize publisher GID in subscription intra process callback (`#1011 <https://github.com/ros2/rclcpp/issues/1011>`_)
* Removed ament_cmake dependency (`#989 <https://github.com/ros2/rclcpp/issues/989>`_)
* Switch to using new rcutils_strerror (`#993 <https://github.com/ros2/rclcpp/issues/993>`_)
* Ensure all rclcpp::Clock accesses are thread-safe
* Use a PIMPL for rclcpp::Clock implementation
* Replace rmw_implementation for rmw dependency in package.xml (`#990 <https://github.com/ros2/rclcpp/issues/990>`_)
* Add missing service callback registration tracepoint (`#986 <https://github.com/ros2/rclcpp/issues/986>`_)
* Rename rmw_topic_endpoint_info_array count to size (`#996 <https://github.com/ros2/rclcpp/issues/996>`_)
* Implement functions to get publisher and subcription informations like QoS policies from topic name (`#960 <https://github.com/ros2/rclcpp/issues/960>`_)
* Code style only: wrap after open parenthesis if not in one line (`#977 <https://github.com/ros2/rclcpp/issues/977>`_)
* Accept taking an rvalue ref future in spin_until_future_complete (`#971 <https://github.com/ros2/rclcpp/issues/971>`_)
* Allow node clock use in logging macros (`#969 <https://github.com/ros2/rclcpp/issues/969>`_) (`#970 <https://github.com/ros2/rclcpp/issues/970>`_)
* Change order of deprecated and visibility attributes (`#968 <https://github.com/ros2/rclcpp/issues/968>`_)
* Deprecated is_initialized() (`#967 <https://github.com/ros2/rclcpp/issues/967>`_)
* Don't specify calling convention in std::_Binder template (`#952 <https://github.com/ros2/rclcpp/issues/952>`_)
* Added missing include to logging.hpp (`#964 <https://github.com/ros2/rclcpp/issues/964>`_)
* Assigning make_shared result to variables in test (`#963 <https://github.com/ros2/rclcpp/issues/963>`_)
* Fix unused parameter warning (`#962 <https://github.com/ros2/rclcpp/issues/962>`_)
* Stop retaining ownership of the rcl context in GraphListener (`#946 <https://github.com/ros2/rclcpp/issues/946>`_)
* Clear sub contexts when starting another init-shutdown cycle (`#947 <https://github.com/ros2/rclcpp/issues/947>`_)
* Avoid possible UB in Clock jump callbacks (`#954 <https://github.com/ros2/rclcpp/issues/954>`_)
* Handle unknown global ROS arguments (`#951 <https://github.com/ros2/rclcpp/issues/951>`_)
* Mark get_clock() as override to fix clang warnings (`#939 <https://github.com/ros2/rclcpp/issues/939>`_)
* Create node clock calls const (try 2) (`#922 <https://github.com/ros2/rclcpp/issues/922>`_)
* Fix asserts on shared_ptr::use_count; expects long, got uint32 (`#936 <https://github.com/ros2/rclcpp/issues/936>`_)
* Use absolute topic name for parameter events (`#929 <https://github.com/ros2/rclcpp/issues/929>`_)
* Add enable_rosout into NodeOptions. (`#900 <https://github.com/ros2/rclcpp/issues/900>`_)
* Removing "virtual", adding "override" keywords (`#897 <https://github.com/ros2/rclcpp/issues/897>`_)
* Use weak_ptr to store context in GraphListener (`#906 <https://github.com/ros2/rclcpp/issues/906>`_)
* Complete published event message when declaring a parameter (`#928 <https://github.com/ros2/rclcpp/issues/928>`_)
* Fix duration.cpp lint error (`#930 <https://github.com/ros2/rclcpp/issues/930>`_)
* Intra-process subscriber should use RMW actual qos. (ros2`#913 <https://github.com/ros2/rclcpp/issues/913>`_) (`#914 <https://github.com/ros2/rclcpp/issues/914>`_)
* Type conversions fixes (`#901 <https://github.com/ros2/rclcpp/issues/901>`_)
* Add override keyword to functions
* Remove unnecessary virtual keywords
* Only check for new work once in spin_some (`#471 <https://github.com/ros2/rclcpp/issues/471>`_) (`#844 <https://github.com/ros2/rclcpp/issues/844>`_)
* Add addition/subtraction assignment operators to Time (`#748 <https://github.com/ros2/rclcpp/issues/748>`_)
* Contributors: Alberto Soragna, Alejandro Hernández Cordero, Barry Xu, Chris Lalancette, Christophe Bedard, Claire Wang, Dan Rose, DensoADAS, Devin Bonnie, Dino Hüllmann, Dirk Thomas, DongheeYe, Emerson Knapp, Ivan Santiago Paunovic, Jacob Perron, Jaison Titus, Karsten Knese, Matt Schickler, Miaofei Mei, Michel Hidalgo, Mikael Arguedas, Monika Idzik, Prajakta Gokhale, Roger Strain, Scott K Logan, Sean Kelly, Stephen Brawner, Steven Macenski, Steven! Ragnarök, Todd Malsbary, Tomoya Fujita, William Woodall, Zachary Michaels
0.8.3 (2019-11-19)
------------------

View File

@@ -12,6 +12,7 @@ find_package(rcpputils REQUIRED)
find_package(rcutils REQUIRED)
find_package(rmw REQUIRED)
find_package(rosgraph_msgs REQUIRED)
find_package(rosidl_default_generators REQUIRED)
find_package(rosidl_runtime_cpp REQUIRED)
find_package(rosidl_typesupport_c REQUIRED)
find_package(rosidl_typesupport_cpp REQUIRED)
@@ -26,8 +27,6 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
include_directories(include)
set(${PROJECT_NAME}_SRCS
src/rclcpp/any_executable.cpp
src/rclcpp/callback_group.cpp
@@ -41,7 +40,7 @@ set(${PROJECT_NAME}_SRCS
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
@@ -50,6 +49,7 @@ set(${PROJECT_NAME}_SRCS
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
@@ -101,23 +101,71 @@ configure_file(
COPYONLY
)
# generate header with logging macros
set(python_code
set(python_code_logging
"import em"
"em.invoke(['-o', 'include/rclcpp/logging.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/logging.hpp.em'])")
string(REPLACE ";" "$<SEMICOLON>" python_code "${python_code}")
string(REPLACE ";" "$<SEMICOLON>" python_code_logging "${python_code_logging}")
add_custom_command(OUTPUT include/rclcpp/logging.hpp
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp"
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_code}"
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_code_logging}"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/logging.hpp.em.watch"
COMMENT "Expanding logging.hpp.em"
VERBATIM
)
list(APPEND ${PROJECT_NAME}_SRCS
include/rclcpp/logging.hpp)
include_directories("${CMAKE_CURRENT_BINARY_DIR}/include")
file(GLOB interface_files "include/rclcpp/node_interfaces/node_*_interface.hpp")
foreach(interface_file ${interface_files})
get_filename_component(interface_name ${interface_file} NAME_WE)
# "watch" template for changes
configure_file(
"resource/interface_traits.hpp.em"
"${CMAKE_CURRENT_BINARY_DIR}/${interface_name}_traits.hpp.em.watch"
COPYONLY
)
set(python_${interface_name}_traits
"import em"
"em.invoke(['-D', 'interface_name = \\'${interface_name}\\'', '-o', 'include/rclcpp/node_interfaces/${interface_name}_traits.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/interface_traits.hpp.em'])")
string(REPLACE ";" "$<SEMICOLON>" python_${interface_name}_traits "${python_${interface_name}_traits}")
add_custom_command(OUTPUT include/rclcpp/node_interfaces/${interface_name}_traits.hpp
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp/node_interfaces"
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_${interface_name}_traits}"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${interface_name}_traits.hpp.em.watch"
COMMENT "Expanding interface_traits.hpp.em into ${interface_name}_traits.hpp"
VERBATIM
)
list(APPEND ${PROJECT_NAME}_SRCS
include/rclcpp/node_interfaces/${interface_name}_traits.hpp)
# "watch" template for changes
configure_file(
"resource/get_interface.hpp.em"
"get_${interface_name}.hpp.em.watch"
COPYONLY
)
set(python_get_${interface_name}
"import em"
"em.invoke(['-D', 'interface_name = \\'${interface_name}\\'', '-o', 'include/rclcpp/node_interfaces/get_${interface_name}.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/get_interface.hpp.em'])")
string(REPLACE ";" "$<SEMICOLON>" python_get_${interface_name} "${python_get_${interface_name}}")
add_custom_command(OUTPUT include/rclcpp/node_interfaces/get_${interface_name}.hpp
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp/node_interfaces"
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_get_${interface_name}}"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/get_${interface_name}.hpp.em.watch"
COMMENT "Expanding get_interface.hpp.em into get_${interface_file}.hpp"
VERBATIM
)
list(APPEND ${PROJECT_NAME}_SRCS
include/rclcpp/node_interfaces/get_${interface_name}.hpp)
endforeach()
add_library(${PROJECT_NAME}
${${PROJECT_NAME}_SRCS})
target_include_directories(${PROJECT_NAME} PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
"$<INSTALL_INTERFACE:include>")
# specific order: dependents before dependencies
ament_target_dependencies(${PROJECT_NAME}
"libstatistics_collector"
@@ -139,7 +187,7 @@ target_compile_definitions(${PROJECT_NAME}
PRIVATE "RCLCPP_BUILDING_LIBRARY")
install(
TARGETS ${PROJECT_NAME}
TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
@@ -148,6 +196,7 @@ install(
# specific order: dependents before dependencies
ament_export_include_directories(include)
ament_export_libraries(${PROJECT_NAME})
ament_export_targets(${PROJECT_NAME})
ament_export_dependencies(libstatistics_collector)
ament_export_dependencies(rcl)
@@ -175,6 +224,14 @@ if(BUILD_TESTING)
add_definitions(-DTEST_RESOURCES_DIRECTORY="${CMAKE_CURRENT_BINARY_DIR}/test/resources")
rosidl_generate_interfaces(${PROJECT_NAME}_test_msgs
test/msg/Header.msg
test/msg/MessageWithHeader.msg
DEPENDENCIES builtin_interfaces
LIBRARY_NAME ${PROJECT_NAME}
SKIP_INSTALL
)
ament_add_gtest(test_client test/test_client.cpp)
if(TARGET test_client)
ament_target_dependencies(test_client
@@ -209,6 +266,7 @@ if(BUILD_TESTING)
endif()
ament_add_gtest(test_function_traits test/test_function_traits.cpp)
if(TARGET test_function_traits)
target_include_directories(test_function_traits PUBLIC include)
ament_target_dependencies(test_function_traits
"rcl_interfaces"
"rmw"
@@ -532,6 +590,14 @@ if(BUILD_TESTING)
target_link_libraries(test_init ${PROJECT_NAME})
endif()
ament_add_gtest(test_interface_traits test/test_interface_traits.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}")
if(TARGET test_interface_traits)
ament_target_dependencies(test_interface_traits
"rcl")
target_link_libraries(test_interface_traits ${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)
@@ -553,9 +619,12 @@ if(BUILD_TESTING)
target_link_libraries(test_wait_set ${PROJECT_NAME})
endif()
ament_add_gtest(test_subscription_topic_statistics test/topic_statistics/test_subscription_topic_statistics.cpp)
ament_add_gtest(test_subscription_topic_statistics test/topic_statistics/test_subscription_topic_statistics.cpp
APPEND_LIBRARY_DIRS "${append_library_dirs}"
)
if(TARGET test_subscription_topic_statistics)
ament_target_dependencies(test_subscription_topic_statistics
"builtin_interfaces"
"libstatistics_collector"
"rcl_interfaces"
"rcutils"
@@ -564,6 +633,7 @@ if(BUILD_TESTING)
"rosidl_typesupport_cpp"
"statistics_msgs"
"test_msgs")
rosidl_target_interfaces(test_subscription_topic_statistics ${PROJECT_NAME}_test_msgs "rosidl_typesupport_cpp")
target_link_libraries(test_subscription_topic_statistics ${PROJECT_NAME})
endif()

View File

@@ -29,8 +29,6 @@
namespace rclcpp
{
namespace executor
{
struct AnyExecutable
{
@@ -47,10 +45,15 @@ struct AnyExecutable
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::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

@@ -40,9 +40,6 @@ class NodeTopics;
class NodeWaitables;
} // namespace node_interfaces
namespace callback_group
{
enum class CallbackGroupType
{
MutuallyExclusive,
@@ -162,6 +159,12 @@ private:
}
};
namespace callback_group
{
using CallbackGroupType [[deprecated("use rclcpp::CallbackGroupType instead")]] = CallbackGroupType;
using CallbackGroup [[deprecated("use rclcpp::CallbackGroup instead")]] = CallbackGroup;
} // namespace callback_group
} // namespace rclcpp

View File

@@ -338,6 +338,9 @@ private:
rclcpp::InitOptions init_options_;
std::string shutdown_reason_;
// Keep shared ownership of global logging configure mutex.
std::shared_ptr<std::mutex> logging_configure_mutex_;
std::unordered_map<std::type_index, std::shared_ptr<void>> sub_contexts_;
// This mutex is recursive so that the constructor of a sub context may
// attempt to acquire another sub context.

View File

@@ -22,8 +22,6 @@ namespace rclcpp
{
namespace contexts
{
namespace default_context
{
class DefaultContext : public rclcpp::Context
{
@@ -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

@@ -35,7 +35,7 @@ create_client(
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
const std::string & service_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
rclcpp::CallbackGroup::SharedPtr group)
{
rcl_client_options_t options = rcl_client_get_default_options();
options.qos = qos_profile;

View File

@@ -37,7 +37,7 @@ 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::AnyServiceCallback<ServiceT> any_service_callback;
any_service_callback.set(std::forward<CallbackT>(callback));

View File

@@ -15,15 +15,25 @@
#ifndef RCLCPP__CREATE_SUBSCRIPTION_HPP_
#define RCLCPP__CREATE_SUBSCRIPTION_HPP_
#include <chrono>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include "rclcpp/detail/resolve_enable_topic_statistics.hpp"
#include "rclcpp/node_interfaces/get_node_timers_interface.hpp"
#include "rclcpp/node_interfaces/get_node_topics_interface.hpp"
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
#include "rclcpp/create_timer.hpp"
#include "rclcpp/qos.hpp"
#include "rclcpp/subscription_factory.hpp"
#include "rclcpp/subscription_options.hpp"
#include "rclcpp/qos.hpp"
#include "rclcpp/timer.hpp"
#include "rclcpp/topic_statistics/subscription_topic_statistics.hpp"
#include "rmw/qos_profiles.h"
namespace rclcpp
@@ -64,10 +74,46 @@ create_subscription(
using rclcpp::node_interfaces::get_node_topics_interface;
auto node_topics = get_node_topics_interface(std::forward<NodeT>(node));
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>>
subscription_topic_stats = nullptr;
if (rclcpp::detail::resolve_enable_topic_statistics(
options,
*node_topics->get_node_base_interface()))
{
std::shared_ptr<Publisher<statistics_msgs::msg::MetricsMessage>> publisher =
create_publisher<statistics_msgs::msg::MetricsMessage>(
node,
options.topic_stats_options.publish_topic,
qos);
subscription_topic_stats = std::make_shared<
rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>
>(node_topics->get_node_base_interface()->get_name(), publisher);
auto sub_call_back = [subscription_topic_stats]() {
subscription_topic_stats->publish_message();
};
auto node_timer_interface = node_topics->get_node_timers_interface();
auto timer = create_wall_timer(
std::chrono::duration_cast<std::chrono::nanoseconds>(
options.topic_stats_options.publish_period),
sub_call_back,
options.callback_group,
node_topics->get_node_base_interface(),
node_timer_interface
);
subscription_topic_stats->set_publisher_timer(timer);
}
auto factory = rclcpp::create_subscription_factory<MessageT>(
std::forward<CallbackT>(callback),
options,
msg_mem_strat
msg_mem_strat,
subscription_topic_stats
);
auto sub = node_topics->create_subscription(topic_name, factory, qos);

View File

@@ -15,6 +15,8 @@
#ifndef RCLCPP__CREATE_TIMER_HPP_
#define RCLCPP__CREATE_TIMER_HPP_
#include <chrono>
#include <exception>
#include <memory>
#include <string>
#include <utility>
@@ -32,12 +34,12 @@ namespace rclcpp
template<typename CallbackT>
typename rclcpp::TimerBase::SharedPtr
create_timer(
node_interfaces::NodeBaseInterface * node_base,
node_interfaces::NodeTimersInterface * node_timers,
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
std::shared_ptr<node_interfaces::NodeTimersInterface> node_timers,
rclcpp::Clock::SharedPtr clock,
rclcpp::Duration period,
CallbackT && callback,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
rclcpp::CallbackGroup::SharedPtr group = nullptr)
{
auto timer = rclcpp::GenericTimer<CallbackT>::make_shared(
clock,
@@ -57,7 +59,7 @@ create_timer(
rclcpp::Clock::SharedPtr clock,
rclcpp::Duration period,
CallbackT && callback,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
rclcpp::CallbackGroup::SharedPtr group = nullptr)
{
return create_timer(
rclcpp::node_interfaces::get_node_base_interface(node),
@@ -68,6 +70,46 @@ create_timer(
group);
}
/// Convenience method to create a timer with node resources.
/**
*
* \tparam DurationRepT
* \tparam DurationT
* \tparam CallbackT
* \param period period to exectute callback
* \param callback callback to execute via the timer period
* \param group
* \param node_base
* \param node_timers
* \return
* \throws std::invalid argument if either node_base or node_timers
* are null
*/
template<typename DurationRepT, typename DurationT, typename CallbackT>
typename rclcpp::WallTimer<CallbackT>::SharedPtr
create_wall_timer(
std::chrono::duration<DurationRepT, DurationT> period,
CallbackT callback,
rclcpp::CallbackGroup::SharedPtr group,
node_interfaces::NodeBaseInterface * node_base,
node_interfaces::NodeTimersInterface * node_timers)
{
if (node_base == nullptr) {
throw std::invalid_argument{"input node_base cannot be null"};
}
if (node_timers == nullptr) {
throw std::invalid_argument{"input node_timers cannot be null"};
}
auto timer = rclcpp::WallTimer<CallbackT>::make_shared(
std::chrono::duration_cast<std::chrono::nanoseconds>(period),
std::move(callback),
node_base->get_context());
node_timers->add_timer(timer, group);
return timer;
}
} // namespace rclcpp
#endif // RCLCPP__CREATE_TIMER_HPP_

View File

@@ -42,7 +42,6 @@ resolve_enable_topic_statistics(const OptionsT & options, const NodeBaseT & node
break;
default:
throw std::runtime_error("Unrecognized EnableTopicStatistics value");
break;
}
return topic_stats_enabled;

View File

@@ -15,265 +15,6 @@
#ifndef RCLCPP__EXCEPTIONS_HPP_
#define RCLCPP__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
#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

@@ -30,6 +30,8 @@
#include "rcl/wait.h"
#include "rclcpp/contexts/default_context.hpp"
#include "rclcpp/executor_options.hpp"
#include "rclcpp/future_return_code.hpp"
#include "rclcpp/memory_strategies.hpp"
#include "rclcpp/memory_strategy.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
@@ -42,48 +44,6 @@ namespace rclcpp
// Forward declaration is used in convenience method signature.
class Node;
namespace executor
{
/// Return codes to be used with spin_until_future_complete.
/**
* SUCCESS: The future is complete and can be accessed with "get" without blocking.
* 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};
RCLCPP_PUBLIC
std::ostream &
operator<<(std::ostream & os, const FutureReturnCode & future_return_code);
RCLCPP_PUBLIC
std::string
to_string(const FutureReturnCode & future_return_code);
///
/**
* Options to be passed to the executor constructor.
*/
struct ExecutorArgs
{
ExecutorArgs()
: memory_strategy(memory_strategies::create_default_strategy()),
context(rclcpp::contexts::default_context::get_global_default_context()),
max_conditions(0)
{}
memory_strategy::MemoryStrategy::SharedPtr memory_strategy;
std::shared_ptr<rclcpp::Context> context;
size_t max_conditions;
};
static inline ExecutorArgs create_default_executor_arguments()
{
return ExecutorArgs();
}
/// Coordinate the order and timing of available communication tasks.
/**
* Executor provides spin functions (including spin_node_once and spin_some).
@@ -100,9 +60,11 @@ public:
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(Executor)
/// Default constructor.
// \param[in] ms The memory strategy to be used with this executor.
/**
* \param[in] options Options used to configure the executor.
*/
RCLCPP_PUBLIC
explicit Executor(const ExecutorArgs & args = ExecutorArgs());
explicit Executor(const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
/// Default destructor.
RCLCPP_PUBLIC
@@ -323,10 +285,10 @@ protected:
RCLCPP_PUBLIC
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr group);
get_node_by_group(rclcpp::CallbackGroup::SharedPtr group);
RCLCPP_PUBLIC
rclcpp::callback_group::CallbackGroup::SharedPtr
rclcpp::CallbackGroup::SharedPtr
get_group_by_timer(rclcpp::TimerBase::SharedPtr timer);
RCLCPP_PUBLIC
@@ -363,6 +325,11 @@ protected:
std::list<const rcl_guard_condition_t *> guard_conditions_;
};
namespace executor
{
using Executor [[deprecated("use rclcpp::Executor instead")]] = rclcpp::Executor;
} // namespace executor
} // namespace rclcpp

View File

@@ -0,0 +1,57 @@
// Copyright 2014-2020 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXECUTOR_OPTIONS_HPP_
#define RCLCPP__EXECUTOR_OPTIONS_HPP_
#include "rclcpp/context.hpp"
#include "rclcpp/contexts/default_context.hpp"
#include "rclcpp/memory_strategies.hpp"
#include "rclcpp/memory_strategy.hpp"
#include "rclcpp/visibility_control.hpp"
namespace rclcpp
{
/// Options to be passed to the executor constructor.
struct ExecutorOptions
{
ExecutorOptions()
: memory_strategy(rclcpp::memory_strategies::create_default_strategy()),
context(rclcpp::contexts::get_global_default_context()),
max_conditions(0)
{}
rclcpp::memory_strategy::MemoryStrategy::SharedPtr memory_strategy;
rclcpp::Context::SharedPtr context;
size_t max_conditions;
};
namespace executor
{
using ExecutorArgs [[deprecated("use rclcpp::ExecutorOptions instead")]] = ExecutorOptions;
[[deprecated("use rclcpp::ExecutorOptions() instead")]]
inline
rclcpp::ExecutorOptions
create_default_executor_arguments()
{
return rclcpp::ExecutorOptions();
}
} // namespace executor
} // namespace rclcpp
#endif // RCLCPP__EXECUTOR_OPTIONS_HPP_

View File

@@ -67,9 +67,9 @@ using rclcpp::executors::SingleThreadedExecutor;
* \return The return code, one of `SUCCESS`, `INTERRUPTED`, or `TIMEOUT`.
*/
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
rclcpp::executor::FutureReturnCode
rclcpp::FutureReturnCode
spin_node_until_future_complete(
rclcpp::executor::Executor & executor,
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))
@@ -84,9 +84,9 @@ spin_node_until_future_complete(
template<typename NodeT = rclcpp::Node, typename ResponseT, typename TimeRepT = int64_t,
typename TimeT = std::milli>
rclcpp::executor::FutureReturnCode
rclcpp::FutureReturnCode
spin_node_until_future_complete(
rclcpp::executor::Executor & executor,
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))
@@ -101,7 +101,7 @@ spin_node_until_future_complete(
} // namespace executors
template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::milli>
rclcpp::executor::FutureReturnCode
rclcpp::FutureReturnCode
spin_until_future_complete(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
const std::shared_future<FutureT> & future,
@@ -113,7 +113,7 @@ spin_until_future_complete(
template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeRepT = int64_t,
typename TimeT = std::milli>
rclcpp::executor::FutureReturnCode
rclcpp::FutureReturnCode
spin_until_future_complete(
std::shared_ptr<NodeT> node_ptr,
const std::shared_future<FutureT> & future,

View File

@@ -32,7 +32,7 @@ namespace rclcpp
namespace executors
{
class MultiThreadedExecutor : public executor::Executor
class MultiThreadedExecutor : public rclcpp::Executor
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(MultiThreadedExecutor)
@@ -45,14 +45,14 @@ public:
* This is useful for reproducing some bugs related to taking work more than
* once.
*
* \param args common arguments for all executors
* \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 = executor::ExecutorArgs(),
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));

View File

@@ -35,25 +35,31 @@ namespace rclcpp
namespace executors
{
/// 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)
/// Default constructor. See the default constructor for Executor.
RCLCPP_PUBLIC
SingleThreadedExecutor(
const executor::ExecutorArgs & args = executor::ExecutorArgs());
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() override;

View File

@@ -22,7 +22,7 @@
#include "rcl/guard_condition.h"
#include "rcl/wait.h"
#include "rclcpp/executable_list.hpp"
#include "rclcpp/experimental/executable_list.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/memory_strategy.hpp"
#include "rclcpp/visibility_control.hpp"
@@ -159,7 +159,7 @@ private:
rcl_wait_set_t * p_wait_set_ = nullptr;
/// Executable list: timers, subscribers, clients, services and waitables
rclcpp::executor::ExecutableList exec_list_;
rclcpp::experimental::ExecutableList exec_list_;
};
} // namespace executors

View File

@@ -23,9 +23,9 @@
#include "rmw/rmw.h"
#include "rclcpp/executable_list.hpp"
#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"
@@ -54,7 +54,7 @@ namespace executors
* exec.spin();
* exec.remove_node(node);
*/
class StaticSingleThreadedExecutor : public executor::Executor
class StaticSingleThreadedExecutor : public rclcpp::Executor
{
public:
RCLCPP_SMART_PTR_DEFINITIONS(StaticSingleThreadedExecutor)
@@ -62,7 +62,7 @@ public:
/// Default constructor. See the default constructor for Executor.
RCLCPP_PUBLIC
explicit StaticSingleThreadedExecutor(
const executor::ExecutorArgs & args = executor::ExecutorArgs());
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
/// Default destrcutor.
RCLCPP_PUBLIC
@@ -131,14 +131,14 @@ public:
* exec.spin_until_future_complete(future);
*/
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
rclcpp::executor::FutureReturnCode
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::executor::FutureReturnCode::SUCCESS;
return rclcpp::FutureReturnCode::SUCCESS;
}
auto end_time = std::chrono::steady_clock::now();
@@ -159,7 +159,7 @@ public:
// 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::executor::FutureReturnCode::SUCCESS;
return rclcpp::FutureReturnCode::SUCCESS;
}
// If the original timeout is < 0, then this is blocking, never TIMEOUT.
if (timeout_ns < std::chrono::nanoseconds::zero()) {
@@ -168,14 +168,14 @@ public:
// 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::executor::FutureReturnCode::TIMEOUT;
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::executor::FutureReturnCode::INTERRUPTED;
return rclcpp::FutureReturnCode::INTERRUPTED;
}
protected:

View File

@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__EXECUTABLE_LIST_HPP_
#define RCLCPP__EXECUTABLE_LIST_HPP_
#ifndef RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_
#define RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_
#include <memory>
#include <vector>
@@ -27,7 +27,7 @@
namespace rclcpp
{
namespace executor
namespace experimental
{
/// This class contains subscriptionbase, timerbase, etc. which can be used to run callbacks.
@@ -86,7 +86,7 @@ public:
size_t number_of_waitables;
};
} // namespace executor
} // namespace experimental
} // namespace rclcpp
#endif // RCLCPP__EXECUTABLE_LIST_HPP_
#endif // RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_

View File

@@ -0,0 +1,61 @@
// 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;
[[deprecated("use rclcpp::to_string(const rclcpp::FutureReturnCode &) instead")]]
inline
std::string
to_string(const rclcpp::FutureReturnCode & future_return_code)
{
return rclcpp::to_string(future_return_code);
}
} // namespace executor
} // namespace rclcpp
#endif // RCLCPP__FUTURE_RETURN_CODE_HPP_

View File

@@ -47,7 +47,7 @@ public:
RCLCPP_PUBLIC
explicit GuardCondition(
rclcpp::Context::SharedPtr context =
rclcpp::contexts::default_context::get_global_default_context());
rclcpp::contexts::get_global_default_context());
RCLCPP_PUBLIC
virtual

View File

@@ -42,6 +42,16 @@ public:
RCLCPP_PUBLIC
InitOptions(const InitOptions & other);
/// Return `true` if logging should be initialized when `rclcpp::Context::init` is called.
RCLCPP_PUBLIC
bool
auto_initialize_logging() const;
/// Set flag indicating if logging should be initialized or not.
RCLCPP_PUBLIC
InitOptions &
auto_initialize_logging(bool initialize_logging);
/// Assignment operator.
RCLCPP_PUBLIC
InitOptions &
@@ -62,6 +72,7 @@ protected:
private:
std::unique_ptr<rcl_init_options_t> init_options_;
bool initialize_logging_{true};
};
} // namespace rclcpp

View File

@@ -67,27 +67,27 @@ public:
virtual void
get_next_subscription(
rclcpp::executor::AnyExecutable & any_exec,
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_service(
rclcpp::executor::AnyExecutable & any_exec,
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_client(
rclcpp::executor::AnyExecutable & any_exec,
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_timer(
rclcpp::executor::AnyExecutable & any_exec,
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_waitable(
rclcpp::executor::AnyExecutable & any_exec,
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) = 0;
virtual rcl_allocator_t
@@ -115,30 +115,30 @@ public:
static rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
get_node_by_group(
rclcpp::callback_group::CallbackGroup::SharedPtr group,
rclcpp::CallbackGroup::SharedPtr group,
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
static rclcpp::CallbackGroup::SharedPtr
get_group_by_subscription(
rclcpp::SubscriptionBase::SharedPtr subscription,
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
static rclcpp::CallbackGroup::SharedPtr
get_group_by_service(
rclcpp::ServiceBase::SharedPtr service,
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
static rclcpp::CallbackGroup::SharedPtr
get_group_by_client(
rclcpp::ClientBase::SharedPtr client,
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
static rclcpp::CallbackGroup::SharedPtr
get_group_by_timer(
rclcpp::TimerBase::SharedPtr timer,
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
static rclcpp::CallbackGroup::SharedPtr
get_group_by_waitable(
rclcpp::Waitable::SharedPtr waitable,
const WeakNodeList & weak_nodes);

View File

@@ -23,6 +23,7 @@
#include "rclcpp/allocator/allocator_common.hpp"
#include "rclcpp/exceptions.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/serialized_message.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rcutils/logging_macros.h"
@@ -46,10 +47,10 @@ public:
using MessageAlloc = typename MessageAllocTraits::allocator_type;
using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;
using SerializedMessageAllocTraits = allocator::AllocRebind<rcl_serialized_message_t, Alloc>;
using SerializedMessageAllocTraits = allocator::AllocRebind<rclcpp::SerializedMessage, Alloc>;
using SerializedMessageAlloc = typename SerializedMessageAllocTraits::allocator_type;
using SerializedMessageDeleter =
allocator::Deleter<SerializedMessageAlloc, rcl_serialized_message_t>;
allocator::Deleter<SerializedMessageAlloc, rclcpp::SerializedMessage>;
using BufferAllocTraits = allocator::AllocRebind<char, Alloc>;
using BufferAlloc = typename BufferAllocTraits::allocator_type;
@@ -86,31 +87,12 @@ public:
return std::allocate_shared<MessageT, MessageAlloc>(*message_allocator_.get());
}
virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message(size_t capacity)
virtual std::shared_ptr<rclcpp::SerializedMessage> 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;
return std::make_shared<rclcpp::SerializedMessage>(capacity);
}
virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message()
virtual std::shared_ptr<rclcpp::SerializedMessage> borrow_serialized_message()
{
return borrow_serialized_message(default_buffer_capacity_);
}
@@ -127,7 +109,8 @@ public:
msg.reset();
}
virtual void return_serialized_message(std::shared_ptr<rcl_serialized_message_t> & serialized_msg)
virtual void return_serialized_message(
std::shared_ptr<rclcpp::SerializedMessage> & serialized_msg)
{
serialized_msg.reset();
}

View File

@@ -135,12 +135,12 @@ public:
/// Create and return a callback group.
RCLCPP_PUBLIC
rclcpp::callback_group::CallbackGroup::SharedPtr
create_callback_group(rclcpp::callback_group::CallbackGroupType group_type);
rclcpp::CallbackGroup::SharedPtr
create_callback_group(rclcpp::CallbackGroupType group_type);
/// Return the list of callback groups in the node.
RCLCPP_PUBLIC
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
get_callback_groups() const;
/// Create and return a Publisher.
@@ -227,7 +227,7 @@ public:
create_wall_timer(
std::chrono::duration<DurationRepT, DurationT> period,
CallbackT callback,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
rclcpp::CallbackGroup::SharedPtr group = nullptr);
/* Create and return a Client. */
template<typename ServiceT>
@@ -235,7 +235,7 @@ public:
create_client(
const std::string & service_name,
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
rclcpp::CallbackGroup::SharedPtr group = nullptr);
/* Create and return a Service. */
template<typename ServiceT, typename CallbackT>
@@ -244,7 +244,7 @@ public:
const std::string & service_name,
CallbackT && callback,
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
rclcpp::CallbackGroup::SharedPtr group = nullptr);
/// Declare and initialize a parameter, return the effective value.
/**
@@ -1142,7 +1142,7 @@ private:
RCLCPP_PUBLIC
bool
group_in_node(callback_group::CallbackGroup::SharedPtr group);
group_in_node(CallbackGroup::SharedPtr group);
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_;

View File

@@ -19,6 +19,7 @@
#include <rmw/rmw.h>
#include <algorithm>
#include <chrono>
#include <cstdlib>
#include <iostream>
#include <limits>
@@ -37,10 +38,12 @@
#include "rclcpp/create_client.hpp"
#include "rclcpp/create_publisher.hpp"
#include "rclcpp/create_service.hpp"
#include "rclcpp/create_timer.hpp"
#include "rclcpp/create_subscription.hpp"
#include "rclcpp/detail/resolve_enable_topic_statistics.hpp"
#include "rclcpp/parameter.hpp"
#include "rclcpp/qos.hpp"
#include "rclcpp/timer.hpp"
#include "rclcpp/type_support_decl.hpp"
#include "rclcpp/visibility_control.hpp"
@@ -106,14 +109,14 @@ typename rclcpp::WallTimer<CallbackT>::SharedPtr
Node::create_wall_timer(
std::chrono::duration<DurationRepT, DurationT> period,
CallbackT callback,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
rclcpp::CallbackGroup::SharedPtr group)
{
auto timer = rclcpp::WallTimer<CallbackT>::make_shared(
std::chrono::duration_cast<std::chrono::nanoseconds>(period),
return rclcpp::create_wall_timer(
period,
std::move(callback),
this->node_base_->get_context());
node_timers_->add_timer(timer, group);
return timer;
group,
this->node_base_.get(),
this->node_timers_.get());
}
template<typename ServiceT>
@@ -121,7 +124,7 @@ 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)
{
return rclcpp::create_client<ServiceT>(
node_base_,
@@ -138,7 +141,7 @@ 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)
{
return rclcpp::create_service<ServiceT, CallbackT>(
node_base_,

View File

@@ -1,149 +0,0 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__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

@@ -1,149 +0,0 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__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

@@ -1,149 +0,0 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__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

@@ -96,22 +96,22 @@ public:
RCLCPP_PUBLIC
rclcpp::callback_group::CallbackGroup::SharedPtr
create_callback_group(rclcpp::callback_group::CallbackGroupType group_type) override;
rclcpp::CallbackGroup::SharedPtr
create_callback_group(rclcpp::CallbackGroupType group_type) override;
RCLCPP_PUBLIC
rclcpp::callback_group::CallbackGroup::SharedPtr
rclcpp::CallbackGroup::SharedPtr
get_default_callback_group() override;
RCLCPP_PUBLIC
bool
callback_group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group) override;
callback_group_in_node(rclcpp::CallbackGroup::SharedPtr group) override;
RCLCPP_PUBLIC
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
get_callback_groups() const override;
RCLCPP_PUBLIC
@@ -146,8 +146,8 @@ private:
std::shared_ptr<rcl_node_t> node_handle_;
rclcpp::callback_group::CallbackGroup::SharedPtr default_callback_group_;
std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> callback_groups_;
rclcpp::CallbackGroup::SharedPtr default_callback_group_;
std::vector<rclcpp::CallbackGroup::WeakPtr> callback_groups_;
std::atomic_bool associated_with_executor_;

View File

@@ -111,25 +111,25 @@ public:
/// Create and return a callback group.
RCLCPP_PUBLIC
virtual
rclcpp::callback_group::CallbackGroup::SharedPtr
create_callback_group(rclcpp::callback_group::CallbackGroupType group_type) = 0;
rclcpp::CallbackGroup::SharedPtr
create_callback_group(rclcpp::CallbackGroupType group_type) = 0;
/// Return the default callback group.
RCLCPP_PUBLIC
virtual
rclcpp::callback_group::CallbackGroup::SharedPtr
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::callback_group::CallbackGroup::SharedPtr group) = 0;
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::callback_group::CallbackGroup::WeakPtr> &
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.

View File

@@ -46,14 +46,14 @@ public:
void
add_client(
rclcpp::ClientBase::SharedPtr client_base_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group) override;
rclcpp::CallbackGroup::SharedPtr group) override;
RCLCPP_PUBLIC
void
add_service(
rclcpp::ServiceBase::SharedPtr service_base_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group) override;
rclcpp::CallbackGroup::SharedPtr group) override;
private:
RCLCPP_DISABLE_COPY(NodeServices)

View File

@@ -41,14 +41,14 @@ public:
void
add_client(
rclcpp::ClientBase::SharedPtr client_base_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
rclcpp::CallbackGroup::SharedPtr group) = 0;
RCLCPP_PUBLIC
virtual
void
add_service(
rclcpp::ServiceBase::SharedPtr service_base_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
rclcpp::CallbackGroup::SharedPtr group) = 0;
};
} // namespace node_interfaces

View File

@@ -46,7 +46,7 @@ public:
void
add_timer(
rclcpp::TimerBase::SharedPtr timer,
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) override;
rclcpp::CallbackGroup::SharedPtr callback_group) override;
private:
RCLCPP_DISABLE_COPY(NodeTimers)

View File

@@ -41,7 +41,7 @@ public:
void
add_timer(
rclcpp::TimerBase::SharedPtr timer,
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) = 0;
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
};
} // namespace node_interfaces

View File

@@ -22,6 +22,7 @@
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
#include "rclcpp/publisher.hpp"
#include "rclcpp/publisher_factory.hpp"
@@ -39,7 +40,9 @@ public:
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeTopicsInterface)
RCLCPP_PUBLIC
explicit NodeTopics(rclcpp::node_interfaces::NodeBaseInterface * node_base);
NodeTopics(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
rclcpp::node_interfaces::NodeTimersInterface * node_timers);
RCLCPP_PUBLIC
~NodeTopics() override;
@@ -55,7 +58,7 @@ public:
void
add_publisher(
rclcpp::PublisherBase::SharedPtr publisher,
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) override;
rclcpp::CallbackGroup::SharedPtr callback_group) override;
RCLCPP_PUBLIC
rclcpp::SubscriptionBase::SharedPtr
@@ -68,16 +71,21 @@ public:
void
add_subscription(
rclcpp::SubscriptionBase::SharedPtr subscription,
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) override;
rclcpp::CallbackGroup::SharedPtr callback_group) override;
RCLCPP_PUBLIC
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface() const override;
RCLCPP_PUBLIC
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface() const override;
private:
RCLCPP_DISABLE_COPY(NodeTopics)
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
rclcpp::node_interfaces::NodeTimersInterface * node_timers_;
};
} // namespace node_interfaces

View File

@@ -25,6 +25,7 @@
#include "rclcpp/callback_group.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
#include "rclcpp/publisher.hpp"
#include "rclcpp/publisher_factory.hpp"
#include "rclcpp/subscription.hpp"
@@ -59,7 +60,7 @@ public:
void
add_publisher(
rclcpp::PublisherBase::SharedPtr publisher,
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) = 0;
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
RCLCPP_PUBLIC
virtual
@@ -74,12 +75,17 @@ public:
void
add_subscription(
rclcpp::SubscriptionBase::SharedPtr subscription,
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) = 0;
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
RCLCPP_PUBLIC
virtual
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface() const = 0;
RCLCPP_PUBLIC
virtual
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface() const = 0;
};
} // namespace node_interfaces

View File

@@ -45,14 +45,14 @@ public:
void
add_waitable(
rclcpp::Waitable::SharedPtr waitable_base_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group) override;
rclcpp::CallbackGroup::SharedPtr group) override;
RCLCPP_PUBLIC
void
remove_waitable(
rclcpp::Waitable::SharedPtr waitable_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group) noexcept override;
rclcpp::CallbackGroup::SharedPtr group) noexcept override;
private:
RCLCPP_DISABLE_COPY(NodeWaitables)

View File

@@ -40,7 +40,7 @@ public:
void
add_waitable(
rclcpp::Waitable::SharedPtr waitable_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
rclcpp::CallbackGroup::SharedPtr group) = 0;
/// \note this function should not throw because it may be called in destructors
RCLCPP_PUBLIC
@@ -48,7 +48,7 @@ public:
void
remove_waitable(
rclcpp::Waitable::SharedPtr waitable_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group) noexcept = 0;
rclcpp::CallbackGroup::SharedPtr group) noexcept = 0;
};
} // namespace node_interfaces

View File

@@ -38,7 +38,7 @@ public:
/**
* Default values for the node options:
*
* - context = rclcpp::contexts::default_context::get_global_default_context()
* - context = rclcpp::contexts::get_global_default_context()
* - arguments = {}
* - parameter_overrides = {}
* - use_global_arguments = true
@@ -338,7 +338,7 @@ private:
// documentation in this class.
rclcpp::Context::SharedPtr context_ {
rclcpp::contexts::default_context::get_global_default_context()};
rclcpp::contexts::get_global_default_context()};
std::vector<std::string> arguments_ {};

View File

@@ -54,21 +54,21 @@ public:
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
rclcpp::CallbackGroup::SharedPtr group = nullptr);
RCLCPP_PUBLIC
AsyncParametersClient(
const rclcpp::Node::SharedPtr node,
const std::string & remote_node_name = "",
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
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::callback_group::CallbackGroup::SharedPtr group = nullptr);
rclcpp::CallbackGroup::SharedPtr group = nullptr);
RCLCPP_PUBLIC
std::shared_future<std::vector<rclcpp::Parameter>>
@@ -205,7 +205,7 @@ public:
RCLCPP_PUBLIC
SyncParametersClient(
rclcpp::executor::Executor::SharedPtr executor,
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);
@@ -218,14 +218,14 @@ public:
RCLCPP_PUBLIC
SyncParametersClient(
rclcpp::executor::Executor::SharedPtr executor,
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::Executor::SharedPtr executor,
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,
@@ -339,7 +339,7 @@ public:
}
private:
rclcpp::executor::Executor::SharedPtr executor_;
rclcpp::Executor::SharedPtr executor_;
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface_;
AsyncParametersClient::SharedPtr async_parameters_client_;
};

View File

@@ -217,6 +217,12 @@ public:
return this->do_serialized_publish(&serialized_msg);
}
void
publish(const SerializedMessage & serialized_msg)
{
return this->do_serialized_publish(&serialized_msg.get_rcl_serialized_message());
}
/// Publish an instance of a LoanedMessage.
/**
* When publishing a loaned message, the memory for this ROS message will be deallocated

View File

@@ -30,10 +30,7 @@
namespace rclcpp
{
namespace callback_group
{
class CallbackGroup;
} // namespace callback_group
/// Non-templated part of PublisherOptionsWithAllocator<Allocator>.
struct PublisherOptionsBase
@@ -48,7 +45,7 @@ struct PublisherOptionsBase
bool use_default_callbacks = true;
/// Callback group in which the waitable items from the publisher should be placed.
std::shared_ptr<rclcpp::callback_group::CallbackGroup> callback_group;
std::shared_ptr<rclcpp::CallbackGroup> callback_group;
/// Optional RMW implementation specific payload to be used during creation of the publisher.
std::shared_ptr<rclcpp::detail::RMWImplementationSpecificPublisherPayload>

View File

@@ -81,7 +81,7 @@
* - rclcpp/executors/multi_threaded_executor.hpp
* - CallbackGroups (mechanism for enforcing concurrency rules for callbacks):
* - rclcpp::Node::create_callback_group()
* - rclcpp::callback_group::CallbackGroup
* - rclcpp::CallbackGroup
* - rclcpp/callback_group.hpp
*
* Additionally, there are some methods for introspecting the ROS graph:

View File

@@ -39,10 +39,6 @@ template<typename T>
struct is_serialized_message_class : std::false_type
{};
template<>
struct is_serialized_message_class<rcl_serialized_message_t>: std::true_type
{};
template<>
struct is_serialized_message_class<SerializedMessage>: std::true_type
{};

View File

@@ -98,6 +98,20 @@ public:
*/
size_t capacity() const;
/// Allocate memory in the data buffer
/**
* The data buffer of the underlying rcl_serialized_message_t will be resized.
* This might change the data layout and invalidates all pointers to the data.
*/
void reserve(size_t capacity);
/// Release the underlying rcl_serialized_message_t
/**
* The memory (i.e. the data buffer) of the serialized message will no longer
* be managed by this instance and the memory won't be deallocated on destruction.
*/
rcl_serialized_message_t release_rcl_serialized_message();
private:
rcl_serialized_message_t serialized_message_;
};

View File

@@ -263,7 +263,7 @@ public:
void
get_next_subscription(
executor::AnyExecutable & any_exec,
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) override
{
auto it = subscription_handles_.begin();
@@ -298,7 +298,7 @@ public:
void
get_next_service(
executor::AnyExecutable & any_exec,
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) override
{
auto it = service_handles_.begin();
@@ -332,7 +332,7 @@ public:
}
void
get_next_client(executor::AnyExecutable & any_exec, const WeakNodeList & weak_nodes) override
get_next_client(rclcpp::AnyExecutable & any_exec, const WeakNodeList & weak_nodes) override
{
auto it = client_handles_.begin();
while (it != client_handles_.end()) {
@@ -366,7 +366,7 @@ public:
void
get_next_timer(
executor::AnyExecutable & any_exec,
rclcpp::AnyExecutable & any_exec,
const WeakNodeList & weak_nodes) override
{
auto it = timer_handles_.begin();
@@ -400,7 +400,7 @@ public:
}
void
get_next_waitable(executor::AnyExecutable & any_exec, const WeakNodeList & weak_nodes) override
get_next_waitable(rclcpp::AnyExecutable & any_exec, const WeakNodeList & weak_nodes) override
{
auto it = waitable_handles_.begin();
while (it != waitable_handles_.end()) {

View File

@@ -17,6 +17,8 @@
#include <memory>
#include "rosidl_runtime_cpp/traits.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/message_memory_strategy.hpp"
#include "rclcpp/visibility_control.hpp"

View File

@@ -18,6 +18,7 @@
#include <rmw/error_handling.h>
#include <rmw/rmw.h>
#include <chrono>
#include <functional>
#include <iostream>
#include <memory>
@@ -25,7 +26,6 @@
#include <string>
#include <utility>
#include "rcl/error_handling.h"
#include "rcl/subscription.h"
@@ -47,6 +47,7 @@
#include "rclcpp/type_support_decl.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/waitable.hpp"
#include "rclcpp/topic_statistics/subscription_topic_statistics.hpp"
#include "tracetools/tracetools.h"
namespace rclcpp
@@ -75,6 +76,8 @@ public:
using MessageDeleter = allocator::Deleter<MessageAllocator, CallbackMessageT>;
using ConstMessageSharedPtr = std::shared_ptr<const CallbackMessageT>;
using MessageUniquePtr = std::unique_ptr<CallbackMessageT, MessageDeleter>;
using SubscriptionTopicStatisticsSharedPtr =
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>>;
RCLCPP_SMART_PTR_DEFINITIONS(Subscription)
@@ -98,7 +101,8 @@ public:
const rclcpp::QoS & qos,
AnySubscriptionCallback<CallbackMessageT, AllocatorT> callback,
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
typename MessageMemoryStrategyT::SharedPtr message_memory_strategy)
typename MessageMemoryStrategyT::SharedPtr message_memory_strategy,
SubscriptionTopicStatisticsSharedPtr subscription_topic_statistics = nullptr)
: SubscriptionBase(
node_base,
type_support_handle,
@@ -180,6 +184,10 @@ public:
this->setup_intra_process(intra_process_subscription_id, ipm);
}
if (subscription_topic_statistics != nullptr) {
this->subscription_topic_statistics_ = std::move(subscription_topic_statistics);
}
TRACEPOINT(
rclcpp_subscription_init,
(const void *)get_subscription_handle().get(),
@@ -242,7 +250,7 @@ public:
return message_memory_strategy_->borrow_message();
}
std::shared_ptr<rcl_serialized_message_t>
std::shared_ptr<rclcpp::SerializedMessage>
create_serialized_message() override
{
return message_memory_strategy_->borrow_serialized_message();
@@ -260,6 +268,13 @@ public:
}
auto typed_message = std::static_pointer_cast<CallbackMessageT>(message);
any_callback_.dispatch(typed_message, message_info);
if (subscription_topic_statistics_) {
const auto nanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now());
const auto time = rclcpp::Time(nanos.time_since_epoch().count());
subscription_topic_statistics_->handle_message(*typed_message, time);
}
}
void
@@ -284,7 +299,7 @@ public:
}
void
return_serialized_message(std::shared_ptr<rcl_serialized_message_t> & message) override
return_serialized_message(std::shared_ptr<rclcpp::SerializedMessage> & message) override
{
message_memory_strategy_->return_serialized_message(message);
}
@@ -307,6 +322,8 @@ private:
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> options_;
typename message_memory_strategy::MessageMemoryStrategy<CallbackMessageT, AllocatorT>::SharedPtr
message_memory_strategy_;
/// Component which computes and publishes topic statistics for this subscriber
SubscriptionTopicStatisticsSharedPtr subscription_topic_statistics_{nullptr};
};
} // namespace rclcpp

View File

@@ -33,6 +33,7 @@
#include "rclcpp/message_info.hpp"
#include "rclcpp/qos.hpp"
#include "rclcpp/qos_event.hpp"
#include "rclcpp/serialized_message.hpp"
#include "rclcpp/type_support_decl.hpp"
#include "rclcpp/visibility_control.hpp"
@@ -151,7 +152,7 @@ public:
*/
RCLCPP_PUBLIC
bool
take_serialized(rcl_serialized_message_t & message_out, rclcpp::MessageInfo & message_info_out);
take_serialized(rclcpp::SerializedMessage & message_out, rclcpp::MessageInfo & message_info_out);
/// Borrow a new message.
/** \return Shared pointer to the fresh message. */
@@ -164,7 +165,7 @@ public:
/** \return Shared pointer to a rcl_message_serialized_t. */
RCLCPP_PUBLIC
virtual
std::shared_ptr<rcl_serialized_message_t>
std::shared_ptr<rclcpp::SerializedMessage>
create_serialized_message() = 0;
/// Check if we need to handle the message, and execute the callback if we do.
@@ -194,7 +195,7 @@ public:
RCLCPP_PUBLIC
virtual
void
return_serialized_message(std::shared_ptr<rcl_serialized_message_t> & message) = 0;
return_serialized_message(std::shared_ptr<rclcpp::SerializedMessage> & message) = 0;
RCLCPP_PUBLIC
const rosidl_message_type_support_t &

View File

@@ -32,6 +32,7 @@
#include "rclcpp/subscription_options.hpp"
#include "rclcpp/subscription_traits.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rclcpp/topic_statistics/subscription_topic_statistics.hpp"
namespace rclcpp
{
@@ -78,7 +79,10 @@ SubscriptionFactory
create_subscription_factory(
CallbackT && callback,
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat)
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat,
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>>
subscription_topic_stats = nullptr
)
{
auto allocator = options.get_allocator();
@@ -88,7 +92,7 @@ create_subscription_factory(
SubscriptionFactory factory {
// factory function that creates a MessageT specific SubscriptionT
[options, msg_mem_strat, any_subscription_callback](
[options, msg_mem_strat, any_subscription_callback, subscription_topic_stats](
rclcpp::node_interfaces::NodeBaseInterface * node_base,
const std::string & topic_name,
const rclcpp::QoS & qos
@@ -104,7 +108,8 @@ create_subscription_factory(
qos,
any_subscription_callback,
options,
msg_mem_strat);
msg_mem_strat,
subscription_topic_stats);
// This is used for setting up things like intra process comms which
// require this->shared_from_this() which cannot be called from
// the constructor.

View File

@@ -45,7 +45,7 @@ struct SubscriptionOptionsBase
bool ignore_local_publications = false;
/// The callback group for this subscription. NULL to use the default callback group.
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group = nullptr;
rclcpp::CallbackGroup::SharedPtr callback_group = nullptr;
/// Setting to explicitly set intraprocess communications.
IntraProcessSetting use_intra_process_comm = IntraProcessSetting::NodeDefault;

View File

@@ -42,15 +42,6 @@ template<typename T>
struct is_serialized_subscription_argument : std::false_type
{};
template<>
struct is_serialized_subscription_argument<rcl_serialized_message_t>: std::true_type
{};
template<>
struct is_serialized_subscription_argument<std::shared_ptr<rcl_serialized_message_t>>
: std::true_type
{};
template<>
struct is_serialized_subscription_argument<SerializedMessage>: std::true_type
{};

View File

@@ -23,6 +23,7 @@
#include "libstatistics_collector/collector/generate_statistics_message.hpp"
#include "libstatistics_collector/moving_average_statistics/types.hpp"
#include "libstatistics_collector/topic_statistics_collector/constants.hpp"
#include "libstatistics_collector/topic_statistics_collector/received_message_age.hpp"
#include "libstatistics_collector/topic_statistics_collector/received_message_period.hpp"
#include "rcl/time.h"
@@ -56,6 +57,9 @@ class SubscriptionTopicStatistics
using TopicStatsCollector =
libstatistics_collector::topic_statistics_collector::TopicStatisticsCollector<
CallbackMessageT>;
using ReceivedMessageAge =
libstatistics_collector::topic_statistics_collector::ReceivedMessageAgeCollector<
CallbackMessageT>;
using ReceivedMessagePeriod =
libstatistics_collector::topic_statistics_collector::ReceivedMessagePeriodCollector<
CallbackMessageT>;
@@ -94,6 +98,8 @@ public:
/// Handle a message received by the subscription to collect statistics.
/**
* This method acquires a lock to prevent race conditions to collectors list.
*
* \param received_message the message received by the subscription
* \param now_nanoseconds current time in nanoseconds
*/
@@ -101,6 +107,7 @@ public:
const CallbackMessageT & received_message,
const rclcpp::Time now_nanoseconds) const
{
std::lock_guard<std::mutex> lock(mutex_);
for (const auto & collector : subscriber_statistics_collectors_) {
collector->OnMessageReceived(received_message, now_nanoseconds.nanoseconds());
}
@@ -116,21 +123,32 @@ public:
}
/// Publish a populated MetricsStatisticsMessage.
/**
* This method acquires a lock to prevent race conditions to collectors list.
*/
virtual void publish_message()
{
std::vector<MetricsMessage> msgs;
rclcpp::Time window_end{get_current_nanoseconds_since_epoch()};
for (auto & collector : subscriber_statistics_collectors_) {
const auto collected_stats = collector->GetStatisticsResults();
{
std::lock_guard<std::mutex> lock(mutex_);
for (auto & collector : subscriber_statistics_collectors_) {
const auto collected_stats = collector->GetStatisticsResults();
auto message = libstatistics_collector::collector::GenerateStatisticMessage(
node_name_,
collector->GetMetricName(),
collector->GetMetricUnit(),
window_start_,
window_end,
collected_stats);
publisher_->publish(message);
auto message = libstatistics_collector::collector::GenerateStatisticMessage(
node_name_,
collector->GetMetricName(),
collector->GetMetricUnit(),
window_start_,
window_end,
collected_stats);
msgs.push_back(message);
}
}
for (auto & msg : msgs) {
publisher_->publish(msg);
}
window_start_ = window_end;
}
@@ -138,11 +156,14 @@ public:
protected:
/// Return a vector of all the currently collected data.
/**
* This method acquires a lock to prevent race conditions to collectors list.
*
* \return a vector of all the collected data
*/
std::vector<StatisticData> get_current_collector_data() const
{
std::vector<StatisticData> data;
std::lock_guard<std::mutex> lock(mutex_);
for (const auto & collector : subscriber_statistics_collectors_) {
data.push_back(collector->GetStatisticsResults());
}
@@ -151,23 +172,39 @@ protected:
private:
/// Construct and start all collectors and set window_start_.
/**
* This method acquires a lock to prevent race conditions to collectors list.
*/
void bring_up()
{
auto received_message_age = std::make_unique<ReceivedMessageAge>();
received_message_age->Start();
subscriber_statistics_collectors_.emplace_back(std::move(received_message_age));
auto received_message_period = std::make_unique<ReceivedMessagePeriod>();
received_message_period->Start();
subscriber_statistics_collectors_.emplace_back(std::move(received_message_period));
{
std::lock_guard<std::mutex> lock(mutex_);
subscriber_statistics_collectors_.emplace_back(std::move(received_message_period));
}
window_start_ = rclcpp::Time(get_current_nanoseconds_since_epoch());
}
/// Stop all collectors, clear measurements, stop publishing timer, and reset publisher.
/**
* This method acquires a lock to prevent race conditions to collectors list.
*/
void tear_down()
{
for (auto & collector : subscriber_statistics_collectors_) {
collector->Stop();
}
{
std::lock_guard<std::mutex> lock(mutex_);
for (auto & collector : subscriber_statistics_collectors_) {
collector->Stop();
}
subscriber_statistics_collectors_.clear();
subscriber_statistics_collectors_.clear();
}
if (publisher_timer_) {
publisher_timer_->cancel();
@@ -187,6 +224,8 @@ private:
return std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
}
/// Mutex to protect the subsequence vectors
mutable std::mutex mutex_;
/// Collection of statistics collectors
std::vector<std::unique_ptr<TopicStatsCollector>> subscriber_statistics_collectors_{};
/// Node name used to generate topic statistics messages to be published

View File

@@ -45,7 +45,7 @@ namespace rclcpp
/// Initialize communications via the rmw implementation and set up a global signal handler.
/**
* Initializes the global context which is accessible via the function
* rclcpp::contexts::default_context::get_global_default_context().
* rclcpp::contexts::get_global_default_context().
* Also, installs the global signal handlers with the function
* rclcpp::install_signal_handlers().
*

View File

@@ -74,7 +74,7 @@ public:
const typename StoragePolicy::ServicesIterable & services = {},
const typename StoragePolicy::WaitablesIterable & waitables = {},
rclcpp::Context::SharedPtr context =
rclcpp::contexts::default_context::get_global_default_context())
rclcpp::contexts::get_global_default_context())
: SynchronizationPolicy(context),
StoragePolicy(
subscriptions,

View File

@@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>rclcpp</name>
<version>0.8.3</version>
<version>0.9.0</version>
<description>The ROS client library in C++.</description>
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
<license>Apache License 2.0</license>
@@ -37,6 +37,7 @@
<test_depend>ament_lint_common</test_depend>
<test_depend>rmw</test_depend>
<test_depend>rmw_implementation_cmake</test_depend>
<test_depend>rosidl_default_generators</test_depend>
<test_depend>test_msgs</test_depend>
<export>

View File

@@ -0,0 +1,111 @@
// 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.
@{
uppercase_interface_name = interface_name.upper()
}@
#ifndef RCLCPP__NODE_INTERFACES__GET_@(uppercase_interface_name)_HPP_
#define RCLCPP__NODE_INTERFACES__GET_@(uppercase_interface_name)_HPP_
#include <memory>
#include <utility>
#include <type_traits>
#include "rcpputils/pointer_traits.hpp"
#include "rclcpp/node_interfaces/@(interface_name).hpp"
#include "rclcpp/node_interfaces/@(interface_name)_traits.hpp"
@{
interface_typename = ''.join([part.capitalize() for part in interface_name.split('_')])
}@
/// This header provides the get_@(interface_name)() template function.
/**
* This function is useful for getting the @(interface_typename) pointer from
* various kinds of Node-like classes.
*
* It's able to get a std::shared_ptr to a @(interface_typename) so long as the class
* has a method called ``get_@(interface_name)()`` which returns one.
*/
namespace rclcpp
{
namespace node_interfaces
{
namespace detail
{
// If NodeType has a method called get_@(interface_name)() which returns a shared pointer.
template<
typename NodeType,
typename std::enable_if<has_@(interface_name)<
typename rcpputils::remove_pointer<NodeType>::type
>::value, int>::type = 0
>
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)>
get_@(interface_name)_from_pointer(NodeType node_pointer)
{
if (!node_pointer) {
throw std::invalid_argument("node cannot be nullptr");
}
return node_pointer->get_@(interface_name)();
}
} // namespace detail
/// Get the @(interface_typename) as a shared pointer from a pointer to a "Node like" object.
template<
typename NodeType,
typename std::enable_if<
rcpputils::is_pointer<NodeType>::value, int
>::type = 0
>
inline
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)>
get_@(interface_name)(NodeType && node)
{
// Forward pointers to detail implementation directly.
return detail::get_@(interface_name)_from_pointer(node);
}
/// Get the @(interface_typename) as a shared pointer from a "Node like" object.
template<
typename NodeType,
typename std::enable_if<
!rcpputils::is_pointer<NodeType>::value, int
>::type = 0
>
inline
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)>
get_@(interface_name)(NodeType && node)
{
// Forward references to detail implementation as a pointer.
return detail::get_@(interface_name)_from_pointer(&node);
}
/// Keep the @(interface_typename) a shared pointer.
inline
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)>
get_@(interface_name)(
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)> & node_interface)
{
return node_interface;
}
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__GET_@(uppercase_interface_name)_HPP_

View File

@@ -0,0 +1,47 @@
// 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.
@{
uppercase_interface_name = interface_name.upper()
interface_typename = ''.join([part.capitalize() for part in interface_name.split('_')])
}@
#ifndef RCLCPP__NODE_INTERFACES__@(uppercase_interface_name)_TRAITS_HPP_
#define RCLCPP__NODE_INTERFACES__@(uppercase_interface_name)_TRAITS_HPP_
#include <functional>
#include <type_traits>
#include "rclcpp/node_interfaces/@(interface_name).hpp"
namespace rclcpp
{
namespace node_interfaces
{
template<class T, typename = void>
struct has_@(interface_name) : std::false_type
{};
template<class T>
struct has_@(interface_name)<
T, typename std::enable_if<
std::is_same<
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)>,
decltype(std::declval<T>().get_@(interface_name)())>::value>::type> : std::true_type
{};
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__@(uppercase_interface_name)_TRAITS_HPP_

View File

@@ -14,7 +14,7 @@
#include "rclcpp/any_executable.hpp"
using rclcpp::executor::AnyExecutable;
using rclcpp::AnyExecutable;
AnyExecutable::AnyExecutable()
: subscription(nullptr),

View File

@@ -16,8 +16,8 @@
#include <vector>
using rclcpp::callback_group::CallbackGroup;
using rclcpp::callback_group::CallbackGroupType;
using rclcpp::CallbackGroup;
using rclcpp::CallbackGroupType;
CallbackGroup::CallbackGroup(CallbackGroupType group_type)
: type_(group_type), can_be_taken_from_(true)

View File

@@ -22,6 +22,7 @@
#include <utility>
#include "rcl/init.h"
#include "rcl/logging.h"
#include "rclcpp/detail/utilities.hpp"
#include "rclcpp/exceptions.hpp"
#include "rclcpp/logging.hpp"
@@ -34,8 +35,27 @@ static std::vector<std::weak_ptr<rclcpp::Context>> g_contexts;
using rclcpp::Context;
static
std::shared_ptr<std::mutex>
get_global_logging_configure_mutex()
{
static auto mutex = std::make_shared<std::mutex>();
return mutex;
}
static
size_t &
get_logging_reference_count()
{
static size_t ref_count = 0;
return ref_count;
}
Context::Context()
: rcl_context_(nullptr), shutdown_reason_("") {}
: rcl_context_(nullptr),
shutdown_reason_(""),
logging_configure_mutex_(nullptr)
{}
Context::~Context()
{
@@ -94,6 +114,30 @@ Context::init(
rcl_context_.reset();
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to initialize rcl");
}
if (init_options.auto_initialize_logging()) {
logging_configure_mutex_ = get_global_logging_configure_mutex();
if (!logging_configure_mutex_) {
throw std::runtime_error("global logging configure mutex is 'nullptr'");
}
std::lock_guard<std::mutex> guard(*logging_configure_mutex_);
size_t & count = get_logging_reference_count();
if (0u == count) {
ret = rcl_logging_configure(
&rcl_context_->global_arguments,
rcl_init_options_get_allocator(init_options_.get_rcl_init_options()));
if (RCL_RET_OK != ret) {
rcl_context_.reset();
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to configure logging");
}
} else {
RCLCPP_WARN(
rclcpp::get_logger("rclcpp"),
"logging was initialized more than once");
}
++count;
}
try {
std::vector<std::string> unparsed_ros_arguments = detail::get_unparsed_ros_arguments(
argc, argv, &(rcl_context_->global_arguments), rcl_get_default_allocator());
@@ -183,6 +227,22 @@ Context::shutdown(const std::string & reason)
++it;
}
}
// shutdown logger
if (logging_configure_mutex_) {
// logging was initialized by this context
std::lock_guard<std::mutex> guard(*logging_configure_mutex_);
size_t & count = get_logging_reference_count();
if (0u == --count) {
rcl_ret_t rcl_ret = rcl_logging_fini();
if (RCL_RET_OK != rcl_ret) {
RCUTILS_SAFE_FWRITE_TO_STDERR(
RCUTILS_STRINGIFY(__file__) ":"
RCUTILS_STRINGIFY(__LINE__)
" failed to fini logging");
rcl_reset_error();
}
}
}
return true;
}

View File

@@ -14,13 +14,13 @@
#include "rclcpp/contexts/default_context.hpp"
using rclcpp::contexts::default_context::DefaultContext;
using rclcpp::contexts::DefaultContext;
DefaultContext::DefaultContext()
{}
DefaultContext::SharedPtr
rclcpp::contexts::default_context::get_global_default_context()
rclcpp::contexts::get_global_default_context()
{
static DefaultContext::SharedPtr default_context = DefaultContext::make_shared();
return default_context;

View File

@@ -14,9 +14,9 @@
#include <utility>
#include "rclcpp/executable_list.hpp"
#include "rclcpp/experimental/executable_list.hpp"
using rclcpp::executor::ExecutableList;
using rclcpp::experimental::ExecutableList;
ExecutableList::ExecutableList()
: number_of_subscriptions(0),

View File

@@ -29,18 +29,18 @@
#include "rcutils/logging_macros.h"
using rclcpp::exceptions::throw_from_rcl_error;
using rclcpp::executor::AnyExecutable;
using rclcpp::executor::Executor;
using rclcpp::executor::ExecutorArgs;
using rclcpp::executor::FutureReturnCode;
using rclcpp::AnyExecutable;
using rclcpp::Executor;
using rclcpp::ExecutorOptions;
using rclcpp::FutureReturnCode;
Executor::Executor(const ExecutorArgs & args)
Executor::Executor(const rclcpp::ExecutorOptions & options)
: spinning(false),
memory_strategy_(args.memory_strategy)
memory_strategy_(options.memory_strategy)
{
rcl_guard_condition_options_t guard_condition_options = rcl_guard_condition_get_default_options();
rcl_ret_t ret = rcl_guard_condition_init(
&interrupt_guard_condition_, args.context->get_rcl_context().get(), guard_condition_options);
&interrupt_guard_condition_, options.context->get_rcl_context().get(), guard_condition_options);
if (RCL_RET_OK != ret) {
throw_from_rcl_error(ret, "Failed to create interrupt guard condition in Executor constructor");
}
@@ -49,14 +49,14 @@ Executor::Executor(const ExecutorArgs & args)
// and one for the executor's guard cond (interrupt_guard_condition_)
// Put the global ctrl-c guard condition in
memory_strategy_->add_guard_condition(args.context->get_interrupt_guard_condition(&wait_set_));
memory_strategy_->add_guard_condition(options.context->get_interrupt_guard_condition(&wait_set_));
// Put the executor's guard condition in
memory_strategy_->add_guard_condition(&interrupt_guard_condition_);
rcl_allocator_t allocator = memory_strategy_->get_allocator();
// Store the context for later use.
context_ = args.context;
context_ = options.context;
ret = rcl_wait_set_init(
&wait_set_,
@@ -350,8 +350,7 @@ Executor::execute_subscription(rclcpp::SubscriptionBase::SharedPtr subscription)
if (subscription->is_serialized()) {
// This is the case where a copy of the serialized message is taken from
// the middleware via inter-process communication.
std::shared_ptr<rcl_serialized_message_t> serialized_msg =
subscription->create_serialized_message();
std::shared_ptr<SerializedMessage> serialized_msg = subscription->create_serialized_message();
take_and_do_error_handling(
"taking a serialized message from topic",
subscription->get_topic_name(),
@@ -503,7 +502,7 @@ Executor::wait_for_work(std::chrono::nanoseconds timeout)
}
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
Executor::get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr group)
Executor::get_node_by_group(rclcpp::CallbackGroup::SharedPtr group)
{
if (!group) {
return nullptr;
@@ -523,7 +522,7 @@ Executor::get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr gro
return nullptr;
}
rclcpp::callback_group::CallbackGroup::SharedPtr
rclcpp::CallbackGroup::SharedPtr
Executor::get_group_by_timer(rclcpp::TimerBase::SharedPtr timer)
{
for (auto & weak_node : weak_nodes_) {
@@ -545,7 +544,7 @@ Executor::get_group_by_timer(rclcpp::TimerBase::SharedPtr timer)
}
}
}
return rclcpp::callback_group::CallbackGroup::SharedPtr();
return rclcpp::CallbackGroup::SharedPtr();
}
bool
@@ -626,29 +625,3 @@ Executor::get_next_executable(AnyExecutable & any_executable, std::chrono::nanos
}
return success;
}
std::ostream &
rclcpp::executor::operator<<(std::ostream & os, const FutureReturnCode & future_return_code)
{
return os << to_string(future_return_code);
}
std::string
rclcpp::executor::to_string(const FutureReturnCode & future_return_code)
{
using enum_type = std::underlying_type<FutureReturnCode>::type;
std::string prefix = "Unknown enum value (";
std::string ret_as_string = std::to_string(static_cast<enum_type>(future_return_code));
switch (future_return_code) {
case FutureReturnCode::SUCCESS:
prefix = "SUCCESS (";
break;
case FutureReturnCode::INTERRUPTED:
prefix = "INTERRUPTED (";
break;
case FutureReturnCode::TIMEOUT:
prefix = "TIMEOUT (";
break;
}
return prefix + ret_as_string + ")";
}

View File

@@ -25,11 +25,11 @@
using rclcpp::executors::MultiThreadedExecutor;
MultiThreadedExecutor::MultiThreadedExecutor(
const rclcpp::executor::ExecutorArgs & args,
const rclcpp::ExecutorOptions & options,
size_t number_of_threads,
bool yield_before_execute,
std::chrono::nanoseconds next_exec_timeout)
: executor::Executor(args),
: rclcpp::Executor(options),
yield_before_execute_(yield_before_execute),
next_exec_timeout_(next_exec_timeout)
{
@@ -74,7 +74,7 @@ void
MultiThreadedExecutor::run(size_t)
{
while (rclcpp::ok(this->context_) && spinning.load()) {
executor::AnyExecutable any_exec;
rclcpp::AnyExecutable any_exec;
{
std::lock_guard<std::mutex> wait_lock(wait_mutex_);
if (!rclcpp::ok(this->context_) || !spinning.load()) {

View File

@@ -18,8 +18,8 @@
using rclcpp::executors::SingleThreadedExecutor;
SingleThreadedExecutor::SingleThreadedExecutor(const rclcpp::executor::ExecutorArgs & args)
: executor::Executor(args) {}
SingleThreadedExecutor::SingleThreadedExecutor(const rclcpp::ExecutorOptions & options)
: rclcpp::Executor(options) {}
SingleThreadedExecutor::~SingleThreadedExecutor() {}
@@ -31,7 +31,7 @@ SingleThreadedExecutor::spin()
}
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
while (rclcpp::ok(this->context_) && spinning.load()) {
rclcpp::executor::AnyExecutable any_executable;
rclcpp::AnyExecutable any_executable;
if (get_next_executable(any_executable)) {
execute_any_executable(any_executable);
}

View File

@@ -46,7 +46,7 @@ StaticExecutorEntitiesCollector::init(
rcl_guard_condition_t * executor_guard_condition)
{
// Empty initialize executable list
exec_list_ = executor::ExecutableList();
exec_list_ = rclcpp::experimental::ExecutableList();
// Get executor's wait_set_ pointer
p_wait_set_ = p_wait_set;
// Get executor's memory strategy ptr

View File

@@ -19,11 +19,11 @@
#include "rclcpp/scope_exit.hpp"
using rclcpp::executors::StaticSingleThreadedExecutor;
using rclcpp::executor::ExecutableList;
using rclcpp::experimental::ExecutableList;
StaticSingleThreadedExecutor::StaticSingleThreadedExecutor(
const rclcpp::executor::ExecutorArgs & args)
: executor::Executor(args)
const rclcpp::ExecutorOptions & options)
: rclcpp::Executor(options)
{
entities_collector_ = std::make_shared<StaticExecutorEntitiesCollector>();
}

View File

@@ -0,0 +1,50 @@
// 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.
#include <iostream>
#include <string>
#include <type_traits>
#include "rclcpp/future_return_code.hpp"
namespace rclcpp
{
std::ostream &
operator<<(std::ostream & os, const rclcpp::FutureReturnCode & future_return_code)
{
return os << to_string(future_return_code);
}
std::string
to_string(const rclcpp::FutureReturnCode & future_return_code)
{
using enum_type = std::underlying_type<FutureReturnCode>::type;
std::string prefix = "Unknown enum value (";
std::string ret_as_string = std::to_string(static_cast<enum_type>(future_return_code));
switch (future_return_code) {
case FutureReturnCode::SUCCESS:
prefix = "SUCCESS (";
break;
case FutureReturnCode::INTERRUPTED:
prefix = "INTERRUPTED (";
break;
case FutureReturnCode::TIMEOUT:
prefix = "TIMEOUT (";
break;
}
return prefix + ret_as_string + ")";
}
} // namespace rclcpp

View File

@@ -46,6 +46,19 @@ InitOptions::InitOptions(const InitOptions & other)
shutdown_on_sigint = other.shutdown_on_sigint;
}
bool
InitOptions::auto_initialize_logging() const
{
return initialize_logging_;
}
InitOptions &
InitOptions::auto_initialize_logging(bool initialize_logging)
{
initialize_logging_ = initialize_logging;
return *this;
}
InitOptions &
InitOptions::operator=(const InitOptions & other)
{

View File

@@ -127,7 +127,7 @@ MemoryStrategy::get_timer_by_handle(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
MemoryStrategy::get_node_by_group(
rclcpp::callback_group::CallbackGroup::SharedPtr group,
rclcpp::CallbackGroup::SharedPtr group,
const WeakNodeList & weak_nodes)
{
if (!group) {
@@ -148,7 +148,7 @@ MemoryStrategy::get_node_by_group(
return nullptr;
}
rclcpp::callback_group::CallbackGroup::SharedPtr
rclcpp::CallbackGroup::SharedPtr
MemoryStrategy::get_group_by_subscription(
rclcpp::SubscriptionBase::SharedPtr subscription,
const WeakNodeList & weak_nodes)
@@ -175,7 +175,7 @@ MemoryStrategy::get_group_by_subscription(
return nullptr;
}
rclcpp::callback_group::CallbackGroup::SharedPtr
rclcpp::CallbackGroup::SharedPtr
MemoryStrategy::get_group_by_service(
rclcpp::ServiceBase::SharedPtr service,
const WeakNodeList & weak_nodes)
@@ -202,7 +202,7 @@ MemoryStrategy::get_group_by_service(
return nullptr;
}
rclcpp::callback_group::CallbackGroup::SharedPtr
rclcpp::CallbackGroup::SharedPtr
MemoryStrategy::get_group_by_client(
rclcpp::ClientBase::SharedPtr client,
const WeakNodeList & weak_nodes)
@@ -229,7 +229,7 @@ MemoryStrategy::get_group_by_client(
return nullptr;
}
rclcpp::callback_group::CallbackGroup::SharedPtr
rclcpp::CallbackGroup::SharedPtr
MemoryStrategy::get_group_by_timer(
rclcpp::TimerBase::SharedPtr timer,
const WeakNodeList & weak_nodes)
@@ -256,7 +256,7 @@ MemoryStrategy::get_group_by_timer(
return nullptr;
}
rclcpp::callback_group::CallbackGroup::SharedPtr
rclcpp::CallbackGroup::SharedPtr
MemoryStrategy::get_group_by_waitable(
rclcpp::Waitable::SharedPtr waitable,
const WeakNodeList & weak_nodes)

View File

@@ -108,7 +108,7 @@ Node::Node(
node_graph_(new rclcpp::node_interfaces::NodeGraph(node_base_.get())),
node_logging_(new rclcpp::node_interfaces::NodeLogging(node_base_.get())),
node_timers_(new rclcpp::node_interfaces::NodeTimers(node_base_.get())),
node_topics_(new rclcpp::node_interfaces::NodeTopics(node_base_.get())),
node_topics_(new rclcpp::node_interfaces::NodeTopics(node_base_.get(), node_timers_.get())),
node_services_(new rclcpp::node_interfaces::NodeServices(node_base_.get())),
node_clock_(new rclcpp::node_interfaces::NodeClock(
node_base_,
@@ -210,15 +210,14 @@ Node::get_logger() const
return node_logging_->get_logger();
}
rclcpp::callback_group::CallbackGroup::SharedPtr
Node::create_callback_group(
rclcpp::callback_group::CallbackGroupType group_type)
rclcpp::CallbackGroup::SharedPtr
Node::create_callback_group(rclcpp::CallbackGroupType group_type)
{
return node_base_->create_callback_group(group_type);
}
bool
Node::group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group)
Node::group_in_node(rclcpp::CallbackGroup::SharedPtr group)
{
return node_base_->callback_group_in_node(group);
}
@@ -377,7 +376,7 @@ Node::get_subscriptions_info_by_topic(const std::string & topic_name, bool no_ma
return node_graph_->get_subscriptions_info_by_topic(topic_name, no_mangle);
}
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
Node::get_callback_groups() const
{
return node_base_->get_callback_groups();

View File

@@ -133,7 +133,7 @@ NodeBase::NodeBase(
});
// Create the default callback group.
using rclcpp::callback_group::CallbackGroupType;
using rclcpp::CallbackGroupType;
default_callback_group_ = create_callback_group(CallbackGroupType::MutuallyExclusive);
// Indicate the notify_guard_condition is now valid.
@@ -208,24 +208,24 @@ NodeBase::assert_liveliness() const
return RCL_RET_OK == rcl_node_assert_liveliness(get_rcl_node_handle());
}
rclcpp::callback_group::CallbackGroup::SharedPtr
NodeBase::create_callback_group(rclcpp::callback_group::CallbackGroupType group_type)
rclcpp::CallbackGroup::SharedPtr
NodeBase::create_callback_group(rclcpp::CallbackGroupType group_type)
{
using rclcpp::callback_group::CallbackGroup;
using rclcpp::callback_group::CallbackGroupType;
using rclcpp::CallbackGroup;
using rclcpp::CallbackGroupType;
auto group = CallbackGroup::SharedPtr(new CallbackGroup(group_type));
callback_groups_.push_back(group);
return group;
}
rclcpp::callback_group::CallbackGroup::SharedPtr
rclcpp::CallbackGroup::SharedPtr
NodeBase::get_default_callback_group()
{
return default_callback_group_;
}
bool
NodeBase::callback_group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group)
NodeBase::callback_group_in_node(rclcpp::CallbackGroup::SharedPtr group)
{
bool group_belongs_to_this_node = false;
for (auto & weak_group : this->callback_groups_) {
@@ -237,7 +237,7 @@ NodeBase::callback_group_in_node(rclcpp::callback_group::CallbackGroup::SharedPt
return group_belongs_to_this_node;
}
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
NodeBase::get_callback_groups() const
{
return callback_groups_;

View File

@@ -107,11 +107,14 @@ NodeParameters::NodeParameters(
rcl_yaml_node_struct_fini(params);
});
rclcpp::ParameterMap initial_map = rclcpp::parameter_map_from(params);
for (auto iter = initial_map.begin(); initial_map.end() != iter; iter++) {
// TODO(cottsay) implement further wildcard matching
if (iter->first == "/**" || iter->first == combined_name_) {
// Enforce wildcard matching precedence
// TODO(cottsay) implement further wildcard matching
const std::vector<std::string> node_matching_names{"/**", combined_name_};
for (const auto & node_name : node_matching_names) {
if (initial_map.count(node_name) > 0) {
// Combine parameter yaml files, overwriting values in older ones
for (auto & param : iter->second) {
for (const rclcpp::Parameter & param : initial_map.at(node_name)) {
parameter_overrides_[param.get_name()] =
rclcpp::ParameterValue(param.get_value_message());
}

View File

@@ -28,7 +28,7 @@ NodeServices::~NodeServices()
void
NodeServices::add_service(
rclcpp::ServiceBase::SharedPtr service_base_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
rclcpp::CallbackGroup::SharedPtr group)
{
if (group) {
if (!node_base_->callback_group_in_node(group)) {
@@ -55,7 +55,7 @@ NodeServices::add_service(
void
NodeServices::add_client(
rclcpp::ClientBase::SharedPtr client_base_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
rclcpp::CallbackGroup::SharedPtr group)
{
if (group) {
if (!node_base_->callback_group_in_node(group)) {

View File

@@ -28,7 +28,7 @@ NodeTimers::~NodeTimers()
void
NodeTimers::add_timer(
rclcpp::TimerBase::SharedPtr timer,
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group)
rclcpp::CallbackGroup::SharedPtr callback_group)
{
if (callback_group) {
if (!node_base_->callback_group_in_node(callback_group)) {

View File

@@ -22,8 +22,10 @@ using rclcpp::exceptions::throw_from_rcl_error;
using rclcpp::node_interfaces::NodeTopics;
NodeTopics::NodeTopics(rclcpp::node_interfaces::NodeBaseInterface * node_base)
: node_base_(node_base)
NodeTopics::NodeTopics(
rclcpp::node_interfaces::NodeBaseInterface * node_base,
rclcpp::node_interfaces::NodeTimersInterface * node_timers)
: node_base_(node_base), node_timers_(node_timers)
{}
NodeTopics::~NodeTopics()
@@ -42,7 +44,7 @@ NodeTopics::create_publisher(
void
NodeTopics::add_publisher(
rclcpp::PublisherBase::SharedPtr publisher,
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group)
rclcpp::CallbackGroup::SharedPtr callback_group)
{
// Assign to a group.
if (callback_group) {
@@ -81,7 +83,7 @@ NodeTopics::create_subscription(
void
NodeTopics::add_subscription(
rclcpp::SubscriptionBase::SharedPtr subscription,
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group)
rclcpp::CallbackGroup::SharedPtr callback_group)
{
// Assign to a group.
if (callback_group) {
@@ -121,3 +123,9 @@ NodeTopics::get_node_base_interface() const
{
return node_base_;
}
rclcpp::node_interfaces::NodeTimersInterface *
NodeTopics::get_node_timers_interface() const
{
return node_timers_;
}

View File

@@ -28,7 +28,7 @@ NodeWaitables::~NodeWaitables()
void
NodeWaitables::add_waitable(
rclcpp::Waitable::SharedPtr waitable_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
rclcpp::CallbackGroup::SharedPtr group)
{
if (group) {
if (!node_base_->callback_group_in_node(group)) {
@@ -55,7 +55,7 @@ NodeWaitables::add_waitable(
void
NodeWaitables::remove_waitable(
rclcpp::Waitable::SharedPtr waitable_ptr,
rclcpp::callback_group::CallbackGroup::SharedPtr group) noexcept
rclcpp::CallbackGroup::SharedPtr group) noexcept
{
if (group) {
if (!node_base_->callback_group_in_node(group)) {

View File

@@ -31,7 +31,7 @@ AsyncParametersClient::AsyncParametersClient(
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
rclcpp::CallbackGroup::SharedPtr group)
: node_topics_interface_(node_topics_interface)
{
if (remote_node_name != "") {
@@ -103,7 +103,7 @@ AsyncParametersClient::AsyncParametersClient(
const rclcpp::Node::SharedPtr node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
rclcpp::CallbackGroup::SharedPtr group)
: AsyncParametersClient(
node->get_node_base_interface(),
node->get_node_topics_interface(),
@@ -118,7 +118,7 @@ AsyncParametersClient::AsyncParametersClient(
rclcpp::Node * node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile,
rclcpp::callback_group::CallbackGroup::SharedPtr group)
rclcpp::CallbackGroup::SharedPtr group)
: AsyncParametersClient(
node->get_node_base_interface(),
node->get_node_topics_interface(),
@@ -349,7 +349,7 @@ SyncParametersClient::SyncParametersClient(
{}
SyncParametersClient::SyncParametersClient(
rclcpp::executor::Executor::SharedPtr executor,
rclcpp::Executor::SharedPtr executor,
rclcpp::Node::SharedPtr node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile)
@@ -375,7 +375,7 @@ SyncParametersClient::SyncParametersClient(
{}
SyncParametersClient::SyncParametersClient(
rclcpp::executor::Executor::SharedPtr executor,
rclcpp::Executor::SharedPtr executor,
rclcpp::Node * node,
const std::string & remote_node_name,
const rmw_qos_profile_t & qos_profile)
@@ -390,7 +390,7 @@ SyncParametersClient::SyncParametersClient(
{}
SyncParametersClient::SyncParametersClient(
rclcpp::executor::Executor::SharedPtr executor,
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,
@@ -417,7 +417,7 @@ SyncParametersClient::get_parameters(const std::vector<std::string> & parameter_
if (
spin_node_until_future_complete(
*executor_, node_base_interface_,
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
f) == rclcpp::FutureReturnCode::SUCCESS)
{
return f.get();
}
@@ -443,7 +443,7 @@ SyncParametersClient::get_parameter_types(const std::vector<std::string> & param
if (
spin_node_until_future_complete(
*executor_, node_base_interface_,
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
f) == rclcpp::FutureReturnCode::SUCCESS)
{
return f.get();
}
@@ -460,7 +460,7 @@ SyncParametersClient::set_parameters(
if (
spin_node_until_future_complete(
*executor_, node_base_interface_,
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
f) == rclcpp::FutureReturnCode::SUCCESS)
{
return f.get();
}
@@ -477,7 +477,7 @@ SyncParametersClient::set_parameters_atomically(
if (
spin_node_until_future_complete(
*executor_, node_base_interface_,
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
f) == rclcpp::FutureReturnCode::SUCCESS)
{
return f.get();
}
@@ -496,7 +496,7 @@ SyncParametersClient::list_parameters(
if (
spin_node_until_future_complete(
*executor_, node_base_interface_,
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
f) == rclcpp::FutureReturnCode::SUCCESS)
{
return f.get();
}

View File

@@ -55,8 +55,11 @@ void SerializationBase::deserialize_message(
rcpputils::check_true(nullptr != type_support_, "Typesupport is nullpointer.");
rcpputils::check_true(nullptr != serialized_message, "Serialized message is nullpointer.");
rcpputils::check_true(
0 != serialized_message->capacity() && 0 != serialized_message->size(),
"Serialized message is wrongly initialized.");
0u != serialized_message->capacity(),
"Wrongly initialized. Serialized message has a capacity of zero.");
rcpputils::check_true(
0u != serialized_message->size(),
"Wrongly initialized. Serialized message has a size of zero.");
rcpputils::check_true(nullptr != ros_message, "ROS message is a nullpointer.");
const auto ret = rmw_deserialize(

View File

@@ -66,50 +66,51 @@ SerializedMessage::SerializedMessage(const rcl_serialized_message_t & other)
}
SerializedMessage::SerializedMessage(SerializedMessage && other)
: SerializedMessage(other.serialized_message_)
{
other.serialized_message_ = rmw_get_zero_initialized_serialized_message();
}
: serialized_message_(
std::exchange(other.serialized_message_, rmw_get_zero_initialized_serialized_message()))
{}
SerializedMessage::SerializedMessage(rcl_serialized_message_t && other)
: serialized_message_(other)
{
// reset buffer to prevent double free
other = rmw_get_zero_initialized_serialized_message();
}
: serialized_message_(
std::exchange(other, rmw_get_zero_initialized_serialized_message()))
{}
SerializedMessage & SerializedMessage::operator=(const SerializedMessage & other)
{
serialized_message_ = rmw_get_zero_initialized_serialized_message();
copy_rcl_message(other.serialized_message_, serialized_message_);
if (this != &other) {
serialized_message_ = rmw_get_zero_initialized_serialized_message();
copy_rcl_message(other.serialized_message_, serialized_message_);
}
return *this;
}
SerializedMessage & SerializedMessage::operator=(const rcl_serialized_message_t & other)
{
serialized_message_ = rmw_get_zero_initialized_serialized_message();
copy_rcl_message(other, serialized_message_);
if (&serialized_message_ != &other) {
serialized_message_ = rmw_get_zero_initialized_serialized_message();
copy_rcl_message(other, serialized_message_);
}
return *this;
}
SerializedMessage & SerializedMessage::operator=(SerializedMessage && other)
{
*this = other.serialized_message_;
other.serialized_message_ = rmw_get_zero_initialized_serialized_message();
if (this != &other) {
serialized_message_ =
std::exchange(other.serialized_message_, rmw_get_zero_initialized_serialized_message());
}
return *this;
}
SerializedMessage & SerializedMessage::operator=(rcl_serialized_message_t && other)
{
serialized_message_ = rmw_get_zero_initialized_serialized_message();
serialized_message_ = other;
// reset original to prevent double free
other = rmw_get_zero_initialized_serialized_message();
if (&serialized_message_ != &other) {
serialized_message_ =
std::exchange(other, rmw_get_zero_initialized_serialized_message());
}
return *this;
}
@@ -144,4 +145,20 @@ size_t SerializedMessage::capacity() const
{
return serialized_message_.buffer_capacity;
}
void SerializedMessage::reserve(size_t capacity)
{
auto ret = rmw_serialized_message_resize(&serialized_message_, capacity);
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret);
}
}
rcl_serialized_message_t SerializedMessage::release_rcl_serialized_message()
{
auto ret = serialized_message_;
serialized_message_ = rmw_get_zero_initialized_serialized_message();
return ret;
}
} // namespace rclcpp

View File

@@ -159,12 +159,12 @@ SubscriptionBase::take_type_erased(void * message_out, rclcpp::MessageInfo & mes
bool
SubscriptionBase::take_serialized(
rcl_serialized_message_t & message_out,
rclcpp::SerializedMessage & message_out,
rclcpp::MessageInfo & message_info_out)
{
rcl_ret_t ret = rcl_take_serialized_message(
this->get_subscription_handle().get(),
&message_out,
&message_out.get_rcl_serialized_message(),
&message_info_out.get_rmw_message_info(),
nullptr);
if (RCL_RET_SUBSCRIPTION_TAKE_FAILED == ret) {

View File

@@ -33,7 +33,7 @@ TimerBase::TimerBase(
: clock_(clock), timer_handle_(nullptr)
{
if (nullptr == context) {
context = rclcpp::contexts::default_context::get_global_default_context();
context = rclcpp::contexts::get_global_default_context();
}
auto rcl_context = context->get_rcl_context();

View File

@@ -30,7 +30,7 @@ namespace rclcpp
void
init(int argc, char const * const argv[], const InitOptions & init_options)
{
using contexts::default_context::get_global_default_context;
using rclcpp::contexts::get_global_default_context;
get_global_default_context()->init(argc, argv, init_options);
// Install the signal handlers.
install_signal_handlers();
@@ -125,7 +125,7 @@ remove_ros_arguments(int argc, char const * const argv[])
bool
ok(Context::SharedPtr context)
{
using contexts::default_context::get_global_default_context;
using rclcpp::contexts::get_global_default_context;
if (nullptr == context) {
context = get_global_default_context();
}
@@ -141,7 +141,7 @@ is_initialized(Context::SharedPtr context)
bool
shutdown(Context::SharedPtr context, const std::string & reason)
{
using contexts::default_context::get_global_default_context;
using rclcpp::contexts::get_global_default_context;
auto default_context = get_global_default_context();
if (nullptr == context) {
context = default_context;
@@ -156,7 +156,7 @@ shutdown(Context::SharedPtr context, const std::string & reason)
void
on_shutdown(std::function<void()> callback, Context::SharedPtr context)
{
using contexts::default_context::get_global_default_context;
using rclcpp::contexts::get_global_default_context;
if (nullptr == context) {
context = get_global_default_context();
}
@@ -166,7 +166,7 @@ on_shutdown(std::function<void()> callback, Context::SharedPtr context)
bool
sleep_for(const std::chrono::nanoseconds & nanoseconds, Context::SharedPtr context)
{
using contexts::default_context::get_global_default_context;
using rclcpp::contexts::get_global_default_context;
if (nullptr == context) {
context = get_global_default_context();
}

View File

@@ -51,14 +51,14 @@ TEST_F(TestMultiThreadedExecutor, timer_over_take) {
bool yield_before_execute = true;
rclcpp::executors::MultiThreadedExecutor executor(
rclcpp::executor::create_default_executor_arguments(), 2u, yield_before_execute);
rclcpp::ExecutorOptions(), 2u, yield_before_execute);
ASSERT_GT(executor.get_number_of_threads(), 1u);
std::shared_ptr<rclcpp::Node> node =
std::make_shared<rclcpp::Node>("test_multi_threaded_executor_timer_over_take");
auto cbg = node->create_callback_group(rclcpp::callback_group::CallbackGroupType::Reentrant);
auto cbg = node->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
rclcpp::Clock system_clock(RCL_STEADY_TIME);
std::mutex last_mutex;

View File

@@ -0,0 +1,3 @@
# Simple Header message with a timestamp field.
builtin_interfaces/Time stamp

View File

@@ -0,0 +1,3 @@
# Message containing a simple Header field.
Header header

View File

@@ -47,22 +47,38 @@ protected:
rclcpp::Node::SharedPtr TestGetNodeInterfaces::node = nullptr;
std::shared_ptr<NodeWrapper> TestGetNodeInterfaces::wrapped_node = nullptr;
TEST_F(TestGetNodeInterfaces, null_rclcpp_node_shared_ptr) {
rclcpp::Node::SharedPtr null_node;
EXPECT_THROW(
{
rclcpp::node_interfaces::get_node_topics_interface(null_node);
}, std::invalid_argument);
}
TEST_F(TestGetNodeInterfaces, rclcpp_node_shared_ptr) {
auto result = rclcpp::node_interfaces::get_node_topics_interface(this->node);
static_assert(
std::is_same<
rclcpp::node_interfaces::NodeTopicsInterface *,
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
decltype(result)
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
}
TEST_F(TestGetNodeInterfaces, null_node_shared_ptr) {
std::shared_ptr<NodeWrapper> null_node;
EXPECT_THROW(
{
rclcpp::node_interfaces::get_node_topics_interface(null_node);
}, std::invalid_argument);
}
TEST_F(TestGetNodeInterfaces, node_shared_ptr) {
auto result = rclcpp::node_interfaces::get_node_topics_interface(this->wrapped_node);
static_assert(
std::is_same<
rclcpp::node_interfaces::NodeTopicsInterface *,
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
decltype(result)
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
}
TEST_F(TestGetNodeInterfaces, rclcpp_node_reference) {
@@ -70,9 +86,9 @@ TEST_F(TestGetNodeInterfaces, rclcpp_node_reference) {
auto result = rclcpp::node_interfaces::get_node_topics_interface(node_reference);
static_assert(
std::is_same<
rclcpp::node_interfaces::NodeTopicsInterface *,
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
decltype(result)
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
}
TEST_F(TestGetNodeInterfaces, node_reference) {
@@ -80,9 +96,9 @@ TEST_F(TestGetNodeInterfaces, node_reference) {
auto result = rclcpp::node_interfaces::get_node_topics_interface(wrapped_node_reference);
static_assert(
std::is_same<
rclcpp::node_interfaces::NodeTopicsInterface *,
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
decltype(result)
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
}
TEST_F(TestGetNodeInterfaces, rclcpp_node_pointer) {
@@ -90,9 +106,17 @@ TEST_F(TestGetNodeInterfaces, rclcpp_node_pointer) {
auto result = rclcpp::node_interfaces::get_node_topics_interface(node_pointer);
static_assert(
std::is_same<
rclcpp::node_interfaces::NodeTopicsInterface *,
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
decltype(result)
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
}
TEST_F(TestGetNodeInterfaces, null_rclcpp_node_pointer) {
rclcpp::Node * null_node{nullptr};
EXPECT_THROW(
{
rclcpp::node_interfaces::get_node_topics_interface(null_node);
}, std::invalid_argument);
}
TEST_F(TestGetNodeInterfaces, node_pointer) {
@@ -100,9 +124,17 @@ TEST_F(TestGetNodeInterfaces, node_pointer) {
auto result = rclcpp::node_interfaces::get_node_topics_interface(wrapped_node_pointer);
static_assert(
std::is_same<
rclcpp::node_interfaces::NodeTopicsInterface *,
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
decltype(result)
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
}
TEST_F(TestGetNodeInterfaces, null_node_pointer) {
NodeWrapper * null_node{nullptr};
EXPECT_THROW(
{
rclcpp::node_interfaces::get_node_topics_interface(null_node);
}, std::invalid_argument);
}
TEST_F(TestGetNodeInterfaces, interface_shared_pointer) {
@@ -111,7 +143,7 @@ TEST_F(TestGetNodeInterfaces, interface_shared_pointer) {
auto result = rclcpp::node_interfaces::get_node_topics_interface(interface_shared_ptr);
static_assert(
std::is_same<
rclcpp::node_interfaces::NodeTopicsInterface *,
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
decltype(result)
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
}

View File

@@ -1,4 +1,8 @@
/**:
ros__parameters:
parameter_int: 21
parameter_bool: true
parameter_int: 42
parameter_string_array: [baz, baz, baz]
test_declare_parameter_node:
ros__parameters:
parameter_int: 21

View File

@@ -0,0 +1,78 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <gtest/gtest.h>
#include <memory>
#include <utility>
#include "rclcpp/contexts/default_context.hpp"
#include "rclcpp/node_interfaces/node_base_interface_traits.hpp"
#include "rclcpp/node_interfaces/node_base.hpp"
#include "rclcpp/node.hpp"
class MyNode
{
public:
std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface> get_node_base_interface() const
{
rclcpp::NodeOptions options;
return std::make_shared<rclcpp::node_interfaces::NodeBase>(
"my_node_name",
"my_node_namespace",
rclcpp::contexts::get_global_default_context(),
*options.get_rcl_node_options(),
options.use_intra_process_comms(),
options.enable_topic_statistics());
}
};
class WrongNode
{
public:
std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface> not_get_node_base_interface()
{
return nullptr;
}
};
template<class T, typename std::enable_if<
rclcpp::node_interfaces::has_node_base_interface<T>::value
>::type * = nullptr>
void get_node_name(const T & nodelike)
{
ASSERT_STREQ("my_node_name", nodelike.get_node_base_interface()->get_name());
}
class TestInterfaceTraits : public ::testing::Test
{
protected:
static void SetUpTestCase()
{
rclcpp::init(0, nullptr);
}
static void TearDownTestCase()
{
rclcpp::shutdown();
}
};
TEST_F(TestInterfaceTraits, has_node_base_interface) {
ASSERT_TRUE(rclcpp::node_interfaces::has_node_base_interface<MyNode>::value);
ASSERT_FALSE(rclcpp::node_interfaces::has_node_base_interface<WrongNode>::value);
ASSERT_TRUE(rclcpp::node_interfaces::has_node_base_interface<rclcpp::Node>::value);
get_node_name(MyNode());
}

View File

@@ -691,7 +691,7 @@ TEST_F(TestNode, declare_parameter_with_cli_overrides) {
no.arguments(
{
"--ros-args",
"-p", "parameter_bool:=true",
"-p", "parameter_bool:=false",
"-p", "parameter_int:=42",
"-p", "parameter_double:=0.42",
"-p", "parameter_string:=foo",
@@ -702,7 +702,8 @@ TEST_F(TestNode, declare_parameter_with_cli_overrides) {
"-p", "parameter_string_array:=[foo, bar]"
});
auto node = std::make_shared<rclcpp::Node>("test_declare_parameter_node"_unq, no);
// To match parameters YAML file content, use a well-known node name for this test only.
auto node = std::make_shared<rclcpp::Node>("test_declare_parameter_node", no);
{
rclcpp::ParameterValue value = node->declare_parameter("parameter_bool");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_BOOL);

View File

@@ -52,6 +52,7 @@ TEST(TestSerializedMessage, various_constructors) {
rcl_handle.buffer_length = content_size;
EXPECT_STREQ(content.c_str(), reinterpret_cast<char *>(rcl_handle.buffer));
EXPECT_EQ(content_size, serialized_message.capacity());
EXPECT_EQ(content_size, serialized_message.size());
// Copy Constructor
rclcpp::SerializedMessage other_serialized_message(serialized_message);
@@ -114,6 +115,31 @@ TEST(TestSerializedMessage, various_constructors_from_rcl) {
EXPECT_TRUE(nullptr != rcl_handle.buffer);
}
TEST(TestSerializedMessage, release) {
const std::string content = "Hello World";
const auto content_size = content.size() + 1; // accounting for null terminator
rcl_serialized_message_t released_handle = rmw_get_zero_initialized_serialized_message();
{
rclcpp::SerializedMessage serialized_msg(13);
// manually copy some content
auto & rcl_serialized_msg = serialized_msg.get_rcl_serialized_message();
std::memcpy(rcl_serialized_msg.buffer, content.c_str(), content.size());
rcl_serialized_msg.buffer[content.size()] = '\0';
rcl_serialized_msg.buffer_length = content_size;
EXPECT_EQ(13u, serialized_msg.capacity());
released_handle = serialized_msg.release_rcl_serialized_message();
// scope exit of serialized_msg
}
EXPECT_TRUE(nullptr != released_handle.buffer);
EXPECT_EQ(13u, released_handle.buffer_capacity);
EXPECT_EQ(content_size, released_handle.buffer_length);
// cleanup memory manually
EXPECT_EQ(RCL_RET_OK, rmw_serialized_message_fini(&released_handle));
}
TEST(TestSerializedMessage, serialization) {
using MessageT = test_msgs::msg::BasicTypes;
@@ -133,9 +159,9 @@ TEST(TestSerializedMessage, serialization) {
}
}
template<typename MessageT>
void test_empty_msg_serialize()
void serialize_default_ros_msg()
{
using MessageT = test_msgs::msg::BasicTypes;
rclcpp::Serialization<MessageT> serializer;
MessageT ros_msg;
rclcpp::SerializedMessage serialized_msg;
@@ -143,12 +169,40 @@ void test_empty_msg_serialize()
serializer.serialize_message(&ros_msg, &serialized_msg);
}
template<typename MessageT>
void test_empty_msg_deserialize()
void serialize_default_ros_msg_into_nullptr()
{
using MessageT = test_msgs::msg::BasicTypes;
rclcpp::Serialization<MessageT> serializer;
MessageT ros_msg;
serializer.serialize_message(&ros_msg, nullptr);
}
void deserialize_default_serialized_message()
{
using MessageT = test_msgs::msg::BasicTypes;
rclcpp::Serialization<MessageT> serializer;
MessageT ros_msg;
rclcpp::SerializedMessage serialized_msg;
serializer.deserialize_message(&serialized_msg, &ros_msg);
}
void deserialize_nullptr()
{
using MessageT = test_msgs::msg::BasicTypes;
rclcpp::Serialization<MessageT> serializer;
MessageT ros_msg;
rclcpp::SerializedMessage serialized_msg;
serializer.deserialize_message(&serialized_msg, &ros_msg);
}
TEST(TestSerializedMessage, serialization_empty_messages)
{
EXPECT_NO_THROW(serialize_default_ros_msg());
EXPECT_THROW(serialize_default_ros_msg_into_nullptr(), rcpputils::IllegalStateException);
EXPECT_THROW(serialize_default_ros_msg_into_nullptr(), rcpputils::IllegalStateException);
EXPECT_THROW(deserialize_default_serialized_message(), rcpputils::IllegalStateException);
EXPECT_THROW(deserialize_nullptr(), rcpputils::IllegalStateException);
}

View File

@@ -29,25 +29,25 @@ TEST(TestSerializedMessageAllocator, default_allocator) {
rclcpp::message_memory_strategy::MessageMemoryStrategy<DummyMessageT>::create_default();
auto msg0 = mem_strategy->borrow_serialized_message();
ASSERT_EQ(msg0->buffer_capacity, 0u);
ASSERT_EQ(msg0->capacity(), 0u);
mem_strategy->return_serialized_message(msg0);
auto msg100 = mem_strategy->borrow_serialized_message(100);
ASSERT_EQ(msg100->buffer_capacity, 100u);
ASSERT_EQ(msg100->capacity(), 100u);
mem_strategy->return_serialized_message(msg100);
auto msg200 = mem_strategy->borrow_serialized_message();
auto ret = rmw_serialized_message_resize(msg200.get(), 200);
auto ret = rmw_serialized_message_resize(&msg200->get_rcl_serialized_message(), 200);
ASSERT_EQ(RCL_RET_OK, ret);
EXPECT_EQ(0u, msg200->buffer_length);
EXPECT_EQ(200u, msg200->buffer_capacity);
EXPECT_EQ(0u, msg200->size());
EXPECT_EQ(200u, msg200->capacity());
mem_strategy->return_serialized_message(msg200);
auto msg1000 = mem_strategy->borrow_serialized_message(1000);
ASSERT_EQ(msg1000->buffer_capacity, 1000u);
ret = rmw_serialized_message_resize(msg1000.get(), 2000);
ASSERT_EQ(msg1000->capacity(), 1000u);
ret = rmw_serialized_message_resize(&msg1000->get_rcl_serialized_message(), 2000);
ASSERT_EQ(RCL_RET_OK, ret);
EXPECT_EQ(2000u, msg1000->buffer_capacity);
EXPECT_EQ(2000u, msg1000->capacity());
mem_strategy->return_serialized_message(msg1000);
}
@@ -61,7 +61,7 @@ TEST(TestSerializedMessageAllocator, borrow_from_subscription) {
[](std::shared_ptr<test_msgs::msg::Empty> test_msg) {(void) test_msg;});
auto msg0 = sub->create_serialized_message();
EXPECT_EQ(0u, msg0->buffer_capacity);
EXPECT_EQ(0u, msg0->capacity());
sub->return_serialized_message(msg0);
rclcpp::shutdown();

View File

@@ -299,10 +299,10 @@ TEST_F(TestSubscription, take) {
TEST_F(TestSubscription, take_serialized) {
initialize();
using test_msgs::msg::Empty;
auto do_nothing = [](std::shared_ptr<const rcl_serialized_message_t>) {FAIL();};
auto do_nothing = [](std::shared_ptr<const rclcpp::SerializedMessage>) {FAIL();};
{
auto sub = node->create_subscription<test_msgs::msg::Empty>("~/test_take", 1, do_nothing);
std::shared_ptr<rcl_serialized_message_t> msg = sub->create_serialized_message();
std::shared_ptr<rclcpp::SerializedMessage> msg = sub->create_serialized_message();
rclcpp::MessageInfo msg_info;
EXPECT_FALSE(sub->take_serialized(*msg, msg_info));
}
@@ -317,7 +317,7 @@ TEST_F(TestSubscription, take_serialized) {
test_msgs::msg::Empty msg;
pub->publish(msg);
}
std::shared_ptr<rcl_serialized_message_t> msg = sub->create_serialized_message();
std::shared_ptr<rclcpp::SerializedMessage> msg = sub->create_serialized_message();
rclcpp::MessageInfo msg_info;
bool message_recieved = false;
auto start = std::chrono::steady_clock::now();

View File

@@ -67,13 +67,13 @@ TEST(TestSubscriptionTraits, is_serialized_callback) {
// Test regular functions
auto cb1 = &serialized_callback_copy;
static_assert(
rclcpp::subscription_traits::is_serialized_callback<decltype(cb1)>::value == true,
"rcl_serialized_message_t in a first argument callback makes it a serialized callback");
rclcpp::subscription_traits::is_serialized_callback<decltype(cb1)>::value == false,
"passing a rcl_serialized_message_t * is not a serialized callback");
auto cb2 = &serialized_callback_shared_ptr;
static_assert(
rclcpp::subscription_traits::is_serialized_callback<decltype(cb2)>::value == true,
"std::shared_ptr<rcl_serialized_message_t> in a callback makes it a serialized callback");
rclcpp::subscription_traits::is_serialized_callback<decltype(cb2)>::value == false,
"passing a std::shared_ptr<rcl_serialized_message_t> is not a serialized callback");
auto cb3 = &not_serialized_callback;
static_assert(
@@ -90,8 +90,8 @@ TEST(TestSubscriptionTraits, is_serialized_callback) {
(void) unused;
};
static_assert(
rclcpp::subscription_traits::is_serialized_callback<decltype(cb5)>::value == true,
"rcl_serialized_message_t in a first argument callback makes it a serialized callback");
rclcpp::subscription_traits::is_serialized_callback<decltype(cb5)>::value == false,
"passing rcl_serialized_message_t is not a serialized callback");
using MessageT = test_msgs::msg::Empty;
using MessageTAllocator = std::allocator<void>;

View File

@@ -52,8 +52,8 @@ TEST(TestUtilities, init_with_args) {
}
TEST(TestUtilities, multi_init) {
auto context1 = std::make_shared<rclcpp::contexts::default_context::DefaultContext>();
auto context2 = std::make_shared<rclcpp::contexts::default_context::DefaultContext>();
auto context1 = std::make_shared<rclcpp::contexts::DefaultContext>();
auto context2 = std::make_shared<rclcpp::contexts::DefaultContext>();
EXPECT_FALSE(rclcpp::ok(context1));
EXPECT_FALSE(rclcpp::ok(context2));

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