Compare commits
105 Commits
release-be
...
ardent
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bea1a52e24 | ||
|
|
3e0fa4be66 | ||
|
|
6d13bcb0fc | ||
|
|
c40f3c25c6 | ||
|
|
d823982f22 | ||
|
|
6129a12df5 | ||
|
|
713ee8059c | ||
|
|
2e4e85f141 | ||
|
|
d989bd15c1 | ||
|
|
bc47fa83dc | ||
|
|
8177771773 | ||
|
|
e9f0328ec8 | ||
|
|
284dc17918 | ||
|
|
3b06aa3721 | ||
|
|
3426696541 | ||
|
|
7bbf5f6e5b | ||
|
|
5e64191e10 | ||
|
|
5e565c7e75 | ||
|
|
9be9d66da5 | ||
|
|
5c57de016f | ||
|
|
eed5999221 | ||
|
|
e08428c79b | ||
|
|
a215d2d22e | ||
|
|
24f39700c6 | ||
|
|
989084b3de | ||
|
|
70d2b4b739 | ||
|
|
c182f5805e | ||
|
|
022b2b1b80 | ||
|
|
070b3125c1 | ||
|
|
c70f2f1452 | ||
|
|
acd231abab | ||
|
|
38c750b876 | ||
|
|
e1f4568bc7 | ||
|
|
5813ba54db | ||
|
|
ca5fb57126 | ||
|
|
4a2e9d8af9 | ||
|
|
ed26865b71 | ||
|
|
a8aa556df0 | ||
|
|
b68b761462 | ||
|
|
1c42a75f43 | ||
|
|
2c5ab49e7c | ||
|
|
a5f94ac412 | ||
|
|
de14d54322 | ||
|
|
b1ed15ebc7 | ||
|
|
f175726b0e | ||
|
|
b28648c61d | ||
|
|
8e2e64e82a | ||
|
|
6f3020ce23 | ||
|
|
688c83a44c | ||
|
|
124500511b | ||
|
|
98dded0ba5 | ||
|
|
89c43e78c8 | ||
|
|
d7b7d7491f | ||
|
|
be985a652b | ||
|
|
c15db0b675 | ||
|
|
cd839663b4 | ||
|
|
5e7aa50af6 | ||
|
|
48b19af04a | ||
|
|
2c3336510d | ||
|
|
def973e3dd | ||
|
|
d090ddc358 | ||
|
|
388a3ca5be | ||
|
|
9281e32f82 | ||
|
|
a41245e6bf | ||
|
|
0c26dd99b6 | ||
|
|
40b09b5b14 | ||
|
|
9dd3d4c3c5 | ||
|
|
9c008267ef | ||
|
|
b8d72d682a | ||
|
|
5a99bbdc6e | ||
|
|
99441d8494 | ||
|
|
756ef6886d | ||
|
|
f396ff2bac | ||
|
|
2847e4aefd | ||
|
|
a4f00dc574 | ||
|
|
c0a78bac37 | ||
|
|
bfa09fb78c | ||
|
|
454d38776c | ||
|
|
b90676871d | ||
|
|
708903e5df | ||
|
|
5777bbee79 | ||
|
|
100417a98d | ||
|
|
675ad04c76 | ||
|
|
3e6a6d2781 | ||
|
|
d2112b294b | ||
|
|
81b8255e61 | ||
|
|
e6e1848b97 | ||
|
|
dbe674deb7 | ||
|
|
c07aee5cf0 | ||
|
|
2009ca676b | ||
|
|
71f5b7fe5b | ||
|
|
ce146cfdba | ||
|
|
dc6b15983a | ||
|
|
4d8b60feb5 | ||
|
|
78dfef75b4 | ||
|
|
8ca02c9d37 | ||
|
|
fee3118bdd | ||
|
|
9603db7b7d | ||
|
|
e3d4995383 | ||
|
|
197c17ae99 | ||
|
|
d9673a556d | ||
|
|
c0af872c18 | ||
|
|
9e309db793 | ||
|
|
321e0b61b0 | ||
|
|
0515e7aaf2 |
44
.github/ISSUE_TEMPLATE.md
vendored
Normal file
44
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<!--
|
||||
For general questions, please post on discourse: https://discourse.ros.org/c/ng-ros
|
||||
Not sure if this is the right repository? Open an issue on https://github.com/ros2/ros2/issues
|
||||
For Bug report or feature requests, please fill out the relevant category below
|
||||
-->
|
||||
|
||||
## Bug report
|
||||
|
||||
**Required Info:**
|
||||
|
||||
- Operating System:
|
||||
- <!-- OS and version (e.g. Windows 10, Ubuntu 16.04...) -->
|
||||
- Installation type:
|
||||
- <!-- binaries or from source -->
|
||||
- Version or commit hash:
|
||||
- <!-- Output of git rev-parse HEAD, release version, or repos file -->
|
||||
- DDS implementation:
|
||||
- <!-- rmw_implementation used (e.g. Fast-RTPS, RTI Connext, etc -->
|
||||
- Client library (if applicable):
|
||||
- <!-- e.g. rclcpp, rclpy, or N/A -->
|
||||
|
||||
#### Steps to reproduce issue
|
||||
<!-- Detailed instructions on how to reliably reproduce this issue http://sscce.org/
|
||||
``` code that can be copy-pasted is preferred ``` -->
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
#### Expected behavior
|
||||
|
||||
#### Actual behavior
|
||||
|
||||
#### Additional information
|
||||
|
||||
<!-- If you are reporting a bug delete everything below
|
||||
If you are requesting a feature deleted everything above this line -->
|
||||
----
|
||||
## Feature request
|
||||
|
||||
#### Feature description
|
||||
<!-- Description in a few sentences what the feature consists of and what problem it will solve -->
|
||||
|
||||
#### Implementation considerations
|
||||
<!-- Relevant information on how the feature could be implemented and pros and cons of the different solutions -->
|
||||
1
rclcpp/.gitignore
vendored
Normal file
1
rclcpp/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
doc_output
|
||||
@@ -3,17 +3,26 @@ cmake_minimum_required(VERSION 3.5)
|
||||
project(rclcpp)
|
||||
|
||||
find_package(ament_cmake REQUIRED)
|
||||
find_package(builtin_interfaces REQUIRED)
|
||||
find_package(rcl REQUIRED)
|
||||
find_package(rcl_interfaces REQUIRED)
|
||||
find_package(rmw REQUIRED)
|
||||
find_package(rmw_implementation REQUIRED)
|
||||
find_package(rmw_implementation_cmake REQUIRED)
|
||||
find_package(rosidl_generator_cpp REQUIRED)
|
||||
find_package(rosidl_typesupport_c REQUIRED)
|
||||
find_package(rosidl_typesupport_cpp REQUIRED)
|
||||
|
||||
# Default to C++14
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
endif()
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++14")
|
||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||
# we dont use add_compile_options with pedantic in message packages
|
||||
# because the Python C extensions dont comply with it
|
||||
# TODO(mikaelarguedas) change to add_compile_options
|
||||
# once this is not a message package anymore
|
||||
# https://github.com/ros2/system_tests/issues/191
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")
|
||||
endif()
|
||||
|
||||
include_directories(include)
|
||||
@@ -22,66 +31,93 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/any_executable.cpp
|
||||
src/rclcpp/callback_group.cpp
|
||||
src/rclcpp/client.cpp
|
||||
src/rclcpp/clock.cpp
|
||||
src/rclcpp/context.cpp
|
||||
src/rclcpp/contexts/default_context.cpp
|
||||
src/rclcpp/duration.cpp
|
||||
src/rclcpp/event.cpp
|
||||
src/rclcpp/exceptions.cpp
|
||||
src/rclcpp/executor.cpp
|
||||
src/rclcpp/executors.cpp
|
||||
src/rclcpp/expand_topic_or_service_name.cpp
|
||||
src/rclcpp/executors/multi_threaded_executor.cpp
|
||||
src/rclcpp/executors/single_threaded_executor.cpp
|
||||
src/rclcpp/graph_listener.cpp
|
||||
src/rclcpp/intra_process_manager.cpp
|
||||
src/rclcpp/intra_process_manager_impl.cpp
|
||||
src/rclcpp/logger.cpp
|
||||
src/rclcpp/memory_strategies.cpp
|
||||
src/rclcpp/memory_strategy.cpp
|
||||
src/rclcpp/node.cpp
|
||||
src/rclcpp/node_interfaces/node_base.cpp
|
||||
src/rclcpp/node_interfaces/node_clock.cpp
|
||||
src/rclcpp/node_interfaces/node_graph.cpp
|
||||
src/rclcpp/node_interfaces/node_logging.cpp
|
||||
src/rclcpp/node_interfaces/node_parameters.cpp
|
||||
src/rclcpp/node_interfaces/node_services.cpp
|
||||
src/rclcpp/node_interfaces/node_timers.cpp
|
||||
src/rclcpp/node_interfaces/node_topics.cpp
|
||||
src/rclcpp/parameter.cpp
|
||||
src/rclcpp/parameter_client.cpp
|
||||
src/rclcpp/parameter_events_filter.cpp
|
||||
src/rclcpp/parameter_service.cpp
|
||||
src/rclcpp/publisher.cpp
|
||||
src/rclcpp/service.cpp
|
||||
src/rclcpp/subscription.cpp
|
||||
src/rclcpp/time.cpp
|
||||
src/rclcpp/time_source.cpp
|
||||
src/rclcpp/timer.cpp
|
||||
src/rclcpp/type_support.cpp
|
||||
src/rclcpp/utilities.cpp
|
||||
)
|
||||
|
||||
macro(target)
|
||||
if(NOT target_suffix STREQUAL "")
|
||||
get_rcl_information("${rmw_implementation}" "rcl${target_suffix}")
|
||||
endif()
|
||||
add_library(${PROJECT_NAME}${target_suffix} SHARED
|
||||
${${PROJECT_NAME}_SRCS})
|
||||
ament_target_dependencies(${PROJECT_NAME}${target_suffix}
|
||||
"rcl${target_suffix}"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp")
|
||||
# "watch" template for changes
|
||||
configure_file(
|
||||
"resource/logging.hpp.em"
|
||||
"logging.hpp.em.watch"
|
||||
COPYONLY
|
||||
)
|
||||
# generate header with logging macros
|
||||
set(python_code
|
||||
"import em"
|
||||
"em.invoke(['-o', 'include/rclcpp/logging.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/logging.hpp.em'])")
|
||||
string(REPLACE ";" "$<SEMICOLON>" python_code "${python_code}")
|
||||
add_custom_command(OUTPUT include/rclcpp/logging.hpp
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp"
|
||||
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_code}"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/logging.hpp.em.watch"
|
||||
COMMENT "Expanding logging.hpp.em"
|
||||
VERBATIM
|
||||
)
|
||||
list(APPEND ${PROJECT_NAME}_SRCS
|
||||
include/rclcpp/logging.hpp)
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
|
||||
# Causes the visibility macros to use dllexport rather than dllimport,
|
||||
# which is appropriate when building the dll but not consuming it.
|
||||
target_compile_definitions(${PROJECT_NAME}${target_suffix}
|
||||
PRIVATE "RCLCPP_BUILDING_LIBRARY")
|
||||
add_library(${PROJECT_NAME} SHARED
|
||||
${${PROJECT_NAME}_SRCS})
|
||||
ament_target_dependencies(${PROJECT_NAME}
|
||||
"builtin_interfaces"
|
||||
"rcl"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp")
|
||||
|
||||
install(
|
||||
TARGETS ${PROJECT_NAME}${target_suffix}
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
RUNTIME DESTINATION bin
|
||||
)
|
||||
endmacro()
|
||||
# Causes the visibility macros to use dllexport rather than dllimport,
|
||||
# which is appropriate when building the dll but not consuming it.
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE "RCLCPP_BUILDING_LIBRARY")
|
||||
|
||||
call_for_each_rmw_implementation(target GENERATE_DEFAULT)
|
||||
install(
|
||||
TARGETS ${PROJECT_NAME}
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
RUNTIME DESTINATION bin
|
||||
)
|
||||
|
||||
ament_export_dependencies(ament_cmake)
|
||||
ament_export_dependencies(builtin_interfaces)
|
||||
ament_export_dependencies(rcl)
|
||||
ament_export_dependencies(rosidl_generator_cpp)
|
||||
ament_export_dependencies(rosidl_typesupport_c)
|
||||
ament_export_dependencies(rosidl_typesupport_cpp)
|
||||
|
||||
ament_export_include_directories(include)
|
||||
@@ -92,6 +128,28 @@ if(BUILD_TESTING)
|
||||
find_package(ament_lint_auto REQUIRED)
|
||||
ament_lint_auto_find_test_dependencies()
|
||||
|
||||
find_package(rmw_implementation_cmake REQUIRED)
|
||||
|
||||
ament_add_gtest(test_client test/test_client.cpp)
|
||||
if(TARGET test_client)
|
||||
target_include_directories(test_client PUBLIC
|
||||
${rcl_interfaces_INCLUDE_DIRS}
|
||||
${rmw_INCLUDE_DIRS}
|
||||
${rosidl_generator_cpp_INCLUDE_DIRS}
|
||||
${rosidl_typesupport_cpp_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_libraries(test_client ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_expand_topic_or_service_name test/test_expand_topic_or_service_name.cpp)
|
||||
if(TARGET test_expand_topic_or_service_name)
|
||||
target_include_directories(test_expand_topic_or_service_name PUBLIC
|
||||
${rcl_interfaces_INCLUDE_DIRS}
|
||||
${rmw_INCLUDE_DIRS}
|
||||
${rosidl_generator_cpp_INCLUDE_DIRS}
|
||||
${rosidl_typesupport_cpp_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_libraries(test_expand_topic_or_service_name ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_function_traits test/test_function_traits.cpp)
|
||||
if(TARGET test_function_traits)
|
||||
target_include_directories(test_function_traits PUBLIC
|
||||
@@ -121,6 +179,36 @@ if(BUILD_TESTING)
|
||||
${rosidl_typesupport_cpp_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
ament_add_gtest(test_node test/test_node.cpp)
|
||||
if(TARGET test_node)
|
||||
target_include_directories(test_node PUBLIC
|
||||
${rcl_interfaces_INCLUDE_DIRS}
|
||||
${rmw_INCLUDE_DIRS}
|
||||
${rosidl_generator_cpp_INCLUDE_DIRS}
|
||||
${rosidl_typesupport_cpp_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_libraries(test_node ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter_events_filter test/test_parameter_events_filter.cpp)
|
||||
if(TARGET test_parameter_events_filter)
|
||||
target_include_directories(test_parameter_events_filter PUBLIC
|
||||
${rcl_interfaces_INCLUDE_DIRS}
|
||||
${rmw_INCLUDE_DIRS}
|
||||
${rosidl_generator_cpp_INCLUDE_DIRS}
|
||||
${rosidl_typesupport_cpp_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_libraries(test_parameter_events_filter ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_publisher test/test_publisher.cpp)
|
||||
if(TARGET test_publisher)
|
||||
target_include_directories(test_publisher PUBLIC
|
||||
${rcl_interfaces_INCLUDE_DIRS}
|
||||
${rmw_INCLUDE_DIRS}
|
||||
${rosidl_generator_cpp_INCLUDE_DIRS}
|
||||
${rosidl_typesupport_cpp_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_libraries(test_publisher ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_rate test/test_rate.cpp
|
||||
ENV RCL_ASSERT_RMW_ID_MATCHES=${rmw_implementation})
|
||||
if(TARGET test_rate)
|
||||
@@ -134,6 +222,26 @@ if(BUILD_TESTING)
|
||||
${PROJECT_NAME}
|
||||
)
|
||||
endif()
|
||||
ament_add_gtest(test_service test/test_service.cpp)
|
||||
if(TARGET test_service)
|
||||
target_include_directories(test_service PUBLIC
|
||||
${rcl_interfaces_INCLUDE_DIRS}
|
||||
${rmw_INCLUDE_DIRS}
|
||||
${rosidl_generator_cpp_INCLUDE_DIRS}
|
||||
${rosidl_typesupport_cpp_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_libraries(test_service ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_subscription test/test_subscription.cpp)
|
||||
if(TARGET test_subscription)
|
||||
target_include_directories(test_subscription PUBLIC
|
||||
${rcl_interfaces_INCLUDE_DIRS}
|
||||
${rmw_INCLUDE_DIRS}
|
||||
${rosidl_generator_cpp_INCLUDE_DIRS}
|
||||
${rosidl_typesupport_cpp_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_libraries(test_subscription ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_find_weak_nodes test/test_find_weak_nodes.cpp)
|
||||
if(TARGET test_find_weak_nodes)
|
||||
target_include_directories(test_find_weak_nodes PUBLIC
|
||||
@@ -155,7 +263,7 @@ if(BUILD_TESTING)
|
||||
|
||||
set(append_library_dirs "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
if(WIN32)
|
||||
set(append_library_dirs "${append_library_dirs}/$<CONFIGURATION>")
|
||||
set(append_library_dirs "${append_library_dirs}/$<CONFIG>")
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_externally_defined_services test/test_externally_defined_services.cpp
|
||||
@@ -174,6 +282,44 @@ if(BUILD_TESTING)
|
||||
mock_msgs ${typesupport_impl_c})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_duration test/test_duration.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_duration)
|
||||
ament_target_dependencies(test_duration
|
||||
"rcl")
|
||||
target_link_libraries(test_duration ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_executor test/test_executor.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_executor)
|
||||
ament_target_dependencies(test_executor
|
||||
"rcl")
|
||||
target_link_libraries(test_executor ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_logger test/test_logger.cpp)
|
||||
target_link_libraries(test_logger ${PROJECT_NAME})
|
||||
|
||||
ament_add_gmock(test_logging test/test_logging.cpp)
|
||||
target_link_libraries(test_logging ${PROJECT_NAME})
|
||||
|
||||
ament_add_gtest(test_time test/test_time.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_time)
|
||||
ament_target_dependencies(test_time
|
||||
"rcl")
|
||||
target_link_libraries(test_time ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_time_source test/test_time_source.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_time_source)
|
||||
ament_target_dependencies(test_time_source
|
||||
"rcl")
|
||||
target_link_libraries(test_time_source ${PROJECT_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ament_package(
|
||||
@@ -186,6 +332,6 @@ install(
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY include/
|
||||
DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/
|
||||
DESTINATION include
|
||||
)
|
||||
|
||||
33
rclcpp/Doxyfile
Normal file
33
rclcpp/Doxyfile
Normal file
@@ -0,0 +1,33 @@
|
||||
# All settings not listed here will use the Doxygen default values.
|
||||
|
||||
PROJECT_NAME = "rclcpp"
|
||||
PROJECT_NUMBER = master
|
||||
PROJECT_BRIEF = "C++ ROS Client Library API"
|
||||
|
||||
# Use these lines to include the generated logging.hpp (update install path if needed)
|
||||
#INPUT = ../../../../install_isolated/rclcpp/include
|
||||
#STRIP_FROM_PATH = /Users/william/ros2_ws/install_isolated/rclcpp/include
|
||||
# Otherwise just generate for the local (non-generated header files)
|
||||
INPUT = ./include
|
||||
|
||||
RECURSIVE = YES
|
||||
OUTPUT_DIRECTORY = doc_output
|
||||
|
||||
EXTRACT_ALL = YES
|
||||
SORT_MEMBER_DOCS = NO
|
||||
|
||||
GENERATE_LATEX = NO
|
||||
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
PREDEFINED = RCLCPP_PUBLIC=
|
||||
|
||||
# Tag files that do not exist will produce a warning and cross-project linking will not work.
|
||||
TAGFILES += "../../../../doxygen_tag_files/cppreference-doxygen-web.tag.xml=http://en.cppreference.com/w/"
|
||||
# Consider changing "latest" to the version you want to reference (e.g. beta1 or 1.0.0)
|
||||
TAGFILES += "../../../../doxygen_tag_files/rcl.tag=http://docs.ros2.org/latest/api/rcl/"
|
||||
TAGFILES += "../../../../doxygen_tag_files/rmw.tag=http://docs.ros2.org/latest/api/rmw/"
|
||||
TAGFILES += "../../../../doxygen_tag_files/rcutils.tag=http://docs.ros2.org/latest/api/rcutils/"
|
||||
# Uncomment to generate tag files for cross-project linking.
|
||||
#GENERATE_TAGFILE = "../../../../doxygen_tag_files/rclcpp.tag"
|
||||
@@ -1,93 +0,0 @@
|
||||
# Copyright 2015 Open Source Robotics Foundation, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# Get all information about rclcpp for a specific RMW implementation.
|
||||
#
|
||||
# It sets the common variables _DEFINITIONS, _INCLUDE_DIRS and _LIBRARIES
|
||||
# with the given prefix.
|
||||
#
|
||||
# :param rmw_implementation: the RMW implementation name
|
||||
# :type rmw_implementation: string
|
||||
# :param var_prefix: the prefix of all output variable names
|
||||
# :type var_prefix: string
|
||||
#
|
||||
macro(get_rclcpp_information rmw_implementation var_prefix)
|
||||
# pretend to be a "package"
|
||||
# so that the variables can be used by various functions / macros
|
||||
set(${var_prefix}_FOUND TRUE)
|
||||
|
||||
# Get rcl using the existing macro
|
||||
if(NOT target_suffix STREQUAL "")
|
||||
get_rcl_information("${rmw_implementation}" "rcl${target_suffix}")
|
||||
endif()
|
||||
|
||||
# include directories
|
||||
normalize_path(${var_prefix}_INCLUDE_DIRS
|
||||
"${rclcpp_DIR}/../../../include")
|
||||
|
||||
# libraries
|
||||
set(_libs)
|
||||
# search for library relative to this CMake file
|
||||
set(_library_target "rclcpp")
|
||||
get_available_rmw_implementations(_rmw_impls)
|
||||
list(LENGTH _rmw_impls _rmw_impls_length)
|
||||
if(_rmw_impls_length GREATER 1)
|
||||
set(_library_target "${_library_target}__${rmw_implementation}")
|
||||
endif()
|
||||
set(_lib "NOTFOUND")
|
||||
find_library(
|
||||
_lib NAMES "${_library_target}"
|
||||
PATHS "${rclcpp_DIR}/../../../lib"
|
||||
NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH
|
||||
)
|
||||
if(NOT _lib)
|
||||
# warn about not existing library and ignore it
|
||||
message(WARNING "Package 'rclcpp' doesn't contain the library '${_library_target}'")
|
||||
elseif(NOT IS_ABSOLUTE "${_lib}")
|
||||
# the found library must be an absolute path
|
||||
message(FATAL_ERROR "Package 'rclcpp' found the library '${_library_target}' at '${_lib}' which is not an absolute path")
|
||||
elseif(NOT EXISTS "${_lib}")
|
||||
# the found library must exist
|
||||
message(FATAL_ERROR "Package 'rclcpp' found the library '${_lib}' which doesn't exist")
|
||||
else()
|
||||
list(APPEND _libs "${_lib}")
|
||||
endif()
|
||||
|
||||
# dependencies
|
||||
set(_exported_dependencies
|
||||
"rcl_interfaces"
|
||||
"rcl${target_suffix}"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp")
|
||||
set(${var_prefix}_DEFINITIONS)
|
||||
foreach(_dep ${_exported_dependencies})
|
||||
if(NOT ${_dep}_FOUND)
|
||||
find_package("${_dep}" QUIET REQUIRED)
|
||||
endif()
|
||||
if(${_dep}_DEFINITIONS)
|
||||
list_append_unique(${var_prefix}_DEFINITIONS "${${_dep}_DEFINITIONS}")
|
||||
endif()
|
||||
if(${_dep}_INCLUDE_DIRS)
|
||||
list_append_unique(${var_prefix}_INCLUDE_DIRS "${${_dep}_INCLUDE_DIRS}")
|
||||
endif()
|
||||
if(${_dep}_LIBRARIES)
|
||||
list(APPEND _libs "${${_dep}_LIBRARIES}")
|
||||
endif()
|
||||
endforeach()
|
||||
if(_libs)
|
||||
ament_libraries_deduplicate(_libs "${_libs}")
|
||||
endif()
|
||||
set(${var_prefix}_LIBRARIES "${_libs}")
|
||||
endmacro()
|
||||
@@ -64,8 +64,9 @@ void * retyped_reallocate(void * untyped_pointer, size_t size, void * untyped_al
|
||||
|
||||
|
||||
// Convert a std::allocator_traits-formatted Allocator into an rcl allocator
|
||||
template<typename T, typename Alloc,
|
||||
typename std::enable_if<!std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
|
||||
template<
|
||||
typename T, typename Alloc,
|
||||
typename std::enable_if<!std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
|
||||
rcl_allocator_t get_rcl_allocator(Alloc & allocator)
|
||||
{
|
||||
rcl_allocator_t rcl_allocator = rcl_get_default_allocator();
|
||||
@@ -81,8 +82,9 @@ rcl_allocator_t get_rcl_allocator(Alloc & allocator)
|
||||
}
|
||||
|
||||
// TODO(jacquelinekay) Workaround for an incomplete implementation of std::allocator<void>
|
||||
template<typename T, typename Alloc,
|
||||
typename std::enable_if<std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
|
||||
template<
|
||||
typename T, typename Alloc,
|
||||
typename std::enable_if<std::is_same<Alloc, std::allocator<void>>::value>::type * = nullptr>
|
||||
rcl_allocator_t get_rcl_allocator(Alloc & allocator)
|
||||
{
|
||||
(void)allocator;
|
||||
|
||||
@@ -42,11 +42,11 @@ struct AnyExecutable
|
||||
virtual ~AnyExecutable();
|
||||
|
||||
// Only one of the following pointers will be set.
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription;
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription_intra_process;
|
||||
rclcpp::timer::TimerBase::SharedPtr timer;
|
||||
rclcpp::service::ServiceBase::SharedPtr service;
|
||||
rclcpp::client::ClientBase::SharedPtr client;
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription;
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription_intra_process;
|
||||
rclcpp::TimerBase::SharedPtr timer;
|
||||
rclcpp::ServiceBase::SharedPtr service;
|
||||
rclcpp::ClientBase::SharedPtr client;
|
||||
// These are used to keep the scope on the containing items
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group;
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base;
|
||||
|
||||
@@ -27,18 +27,17 @@
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace any_service_callback
|
||||
{
|
||||
|
||||
template<typename ServiceT>
|
||||
class AnyServiceCallback
|
||||
{
|
||||
private:
|
||||
using SharedPtrCallback = std::function<void(
|
||||
using SharedPtrCallback = std::function<
|
||||
void(
|
||||
const std::shared_ptr<typename ServiceT::Request>,
|
||||
std::shared_ptr<typename ServiceT::Response>
|
||||
)>;
|
||||
using SharedPtrWithRequestHeaderCallback = std::function<void(
|
||||
using SharedPtrWithRequestHeaderCallback = std::function<
|
||||
void(
|
||||
const std::shared_ptr<rmw_request_id_t>,
|
||||
const std::shared_ptr<typename ServiceT::Request>,
|
||||
std::shared_ptr<typename ServiceT::Response>
|
||||
@@ -98,7 +97,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace any_service_callback
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__ANY_SERVICE_CALLBACK_HPP_
|
||||
|
||||
@@ -30,9 +30,6 @@
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace any_subscription_callback
|
||||
{
|
||||
|
||||
template<typename MessageT, typename Alloc>
|
||||
class AnySubscriptionCallback
|
||||
{
|
||||
@@ -209,7 +206,6 @@ private:
|
||||
MessageDeleter message_deleter_;
|
||||
};
|
||||
|
||||
} // namespace any_subscription_callback
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__ANY_SUBSCRIPTION_CALLBACK_HPP_
|
||||
|
||||
@@ -59,19 +59,19 @@ public:
|
||||
explicit CallbackGroup(CallbackGroupType group_type);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::subscription::SubscriptionBase::WeakPtr> &
|
||||
const std::vector<rclcpp::SubscriptionBase::WeakPtr> &
|
||||
get_subscription_ptrs() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::timer::TimerBase::WeakPtr> &
|
||||
const std::vector<rclcpp::TimerBase::WeakPtr> &
|
||||
get_timer_ptrs() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::service::ServiceBase::WeakPtr> &
|
||||
const std::vector<rclcpp::ServiceBase::WeakPtr> &
|
||||
get_service_ptrs() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::client::ClientBase::WeakPtr> &
|
||||
const std::vector<rclcpp::ClientBase::WeakPtr> &
|
||||
get_client_ptrs() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
@@ -87,27 +87,27 @@ protected:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_subscription(const rclcpp::subscription::SubscriptionBase::SharedPtr subscription_ptr);
|
||||
add_subscription(const rclcpp::SubscriptionBase::SharedPtr subscription_ptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_timer(const rclcpp::timer::TimerBase::SharedPtr timer_ptr);
|
||||
add_timer(const rclcpp::TimerBase::SharedPtr timer_ptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_service(const rclcpp::service::ServiceBase::SharedPtr service_ptr);
|
||||
add_service(const rclcpp::ServiceBase::SharedPtr service_ptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
add_client(const rclcpp::client::ClientBase::SharedPtr client_ptr);
|
||||
add_client(const rclcpp::ClientBase::SharedPtr client_ptr);
|
||||
|
||||
CallbackGroupType type_;
|
||||
// Mutex to protect the subsequent vectors of pointers.
|
||||
mutable std::mutex mutex_;
|
||||
std::vector<rclcpp::subscription::SubscriptionBase::WeakPtr> subscription_ptrs_;
|
||||
std::vector<rclcpp::timer::TimerBase::WeakPtr> timer_ptrs_;
|
||||
std::vector<rclcpp::service::ServiceBase::WeakPtr> service_ptrs_;
|
||||
std::vector<rclcpp::client::ClientBase::WeakPtr> client_ptrs_;
|
||||
std::vector<rclcpp::SubscriptionBase::WeakPtr> subscription_ptrs_;
|
||||
std::vector<rclcpp::TimerBase::WeakPtr> timer_ptrs_;
|
||||
std::vector<rclcpp::ServiceBase::WeakPtr> service_ptrs_;
|
||||
std::vector<rclcpp::ClientBase::WeakPtr> client_ptrs_;
|
||||
std::atomic_bool can_be_taken_from_;
|
||||
};
|
||||
|
||||
|
||||
@@ -27,11 +27,13 @@
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/wait.h"
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/function_traits.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp/expand_topic_or_service_name.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rmw/error_handling.h"
|
||||
@@ -45,9 +47,6 @@ namespace node_interfaces
|
||||
class NodeBaseInterface;
|
||||
} // namespace node_interfaces
|
||||
|
||||
namespace client
|
||||
{
|
||||
|
||||
class ClientBase
|
||||
{
|
||||
public:
|
||||
@@ -66,6 +65,10 @@ public:
|
||||
const std::string &
|
||||
get_service_name() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rcl_client_t *
|
||||
get_client_handle();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rcl_client_t *
|
||||
get_client_handle() const;
|
||||
@@ -98,6 +101,10 @@ protected:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rcl_node_t *
|
||||
get_rcl_node_handle();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rcl_node_t *
|
||||
get_rcl_node_handle() const;
|
||||
|
||||
rclcpp::node_interfaces::NodeGraphInterface::WeakPtr node_graph_;
|
||||
@@ -138,14 +145,24 @@ public:
|
||||
using rosidl_typesupport_cpp::get_service_type_support_handle;
|
||||
auto service_type_support_handle =
|
||||
get_service_type_support_handle<ServiceT>();
|
||||
if (rcl_client_init(&client_handle_, this->get_rcl_node_handle(),
|
||||
service_type_support_handle, service_name.c_str(), &client_options) != RCL_RET_OK)
|
||||
{
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
throw std::runtime_error(
|
||||
std::string("could not create client: ") +
|
||||
rcl_get_error_string_safe());
|
||||
// *INDENT-ON*
|
||||
rcl_ret_t ret = rcl_client_init(
|
||||
&client_handle_,
|
||||
this->get_rcl_node_handle(),
|
||||
service_type_support_handle,
|
||||
service_name.c_str(),
|
||||
&client_options);
|
||||
if (ret != RCL_RET_OK) {
|
||||
if (ret == RCL_RET_SERVICE_NAME_INVALID) {
|
||||
auto rcl_node_handle = this->get_rcl_node_handle();
|
||||
// this will throw on any validation problem
|
||||
rcl_reset_error();
|
||||
expand_topic_or_service_name(
|
||||
service_name,
|
||||
rcl_node_get_name(rcl_node_handle),
|
||||
rcl_node_get_namespace(rcl_node_handle),
|
||||
true);
|
||||
}
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "could not create client");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +170,8 @@ public:
|
||||
{
|
||||
if (rcl_client_fini(&client_handle_, this->get_rcl_node_handle()) != RCL_RET_OK) {
|
||||
fprintf(stderr,
|
||||
"Error in destruction of rmw client handle: %s\n", rmw_get_error_string_safe());
|
||||
"Error in destruction of rcl client handle: %s\n", rcl_get_error_string_safe());
|
||||
rcl_reset_error();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,10 +190,11 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
handle_response(std::shared_ptr<rmw_request_id_t> request_header,
|
||||
handle_response(
|
||||
std::shared_ptr<rmw_request_id_t> request_header,
|
||||
std::shared_ptr<void> response)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(pending_requests_mutex_);
|
||||
std::unique_lock<std::mutex> lock(pending_requests_mutex_);
|
||||
auto typed_response = std::static_pointer_cast<typename ServiceT::Response>(response);
|
||||
int64_t sequence_number = request_header->sequence_number;
|
||||
// TODO(esteve) this should throw instead since it is not expected to happen in the first place
|
||||
@@ -188,6 +207,9 @@ public:
|
||||
auto callback = std::get<1>(tuple);
|
||||
auto future = std::get<2>(tuple);
|
||||
this->pending_requests_.erase(sequence_number);
|
||||
// Unlock here to allow the service to be called recursively from one of its callbacks.
|
||||
lock.unlock();
|
||||
|
||||
call_promise->set_value(typed_response);
|
||||
callback(future);
|
||||
}
|
||||
@@ -212,11 +234,9 @@ public:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(pending_requests_mutex_);
|
||||
int64_t sequence_number;
|
||||
if (RCL_RET_OK != rcl_send_request(get_client_handle(), request.get(), &sequence_number)) {
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
throw std::runtime_error(
|
||||
std::string("failed to send request: ") + rcl_get_error_string_safe());
|
||||
// *INDENT-ON*
|
||||
rcl_ret_t ret = rcl_send_request(get_client_handle(), request.get(), &sequence_number);
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to send request");
|
||||
}
|
||||
|
||||
SharedPromise call_promise = std::make_shared<Promise>();
|
||||
@@ -259,7 +279,6 @@ private:
|
||||
std::mutex pending_requests_mutex_;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CLIENT_HPP_
|
||||
|
||||
145
rclcpp/include/rclcpp/clock.hpp
Normal file
145
rclcpp/include/rclcpp/clock.hpp
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__CLOCK_HPP_
|
||||
#define RCLCPP__CLOCK_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/time.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rcl/time.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
class TimeSource;
|
||||
|
||||
/// A struct to represent a timejump.
|
||||
/**
|
||||
* It represents the time jump duration and whether it changed clock type.
|
||||
*/
|
||||
struct TimeJump
|
||||
{
|
||||
typedef enum ClockChange_t
|
||||
{
|
||||
ROS_TIME_NO_CHANGE, ///< The time type before and after the jump is ROS_TIME
|
||||
ROS_TIME_ACTIVATED, ///< The time type switched to ROS_TIME from SYSTEM_TIME
|
||||
ROS_TIME_DEACTIVATED, ///< The time type switched to SYSTEM_TIME from ROS_TIME
|
||||
SYSTEM_TIME_NO_CHANGE ///< The time type before and after the jump is SYSTEM_TIME
|
||||
} ClockChange_t;
|
||||
|
||||
ClockChange_t jump_type_; ///< The change in clock_type if there is one.
|
||||
rcl_duration_t delta_; ///< The change in time value.
|
||||
};
|
||||
|
||||
/// A class to store a threshold for a TimeJump.
|
||||
/**
|
||||
* This class can be used to evaluate a time jump's magnitude.
|
||||
*/
|
||||
class JumpThreshold
|
||||
{
|
||||
public:
|
||||
uint64_t min_forward_; ///< The minimum jump forward to be considered exceeded..
|
||||
uint64_t min_backward_; ///< The minimum backwards jump to be considered exceeded.
|
||||
bool on_clock_change_; ///< Whether to trigger on any clock type change.
|
||||
|
||||
// Test if the threshold is exceeded by a TimeJump
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
is_exceeded(const TimeJump & jump);
|
||||
};
|
||||
|
||||
class JumpHandler
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(JumpHandler)
|
||||
JumpHandler(
|
||||
std::function<void()> pre_callback,
|
||||
std::function<void(TimeJump)> post_callback,
|
||||
JumpThreshold & threshold);
|
||||
|
||||
std::function<void()> pre_callback;
|
||||
std::function<void(const TimeJump &)> post_callback;
|
||||
JumpThreshold notice_threshold;
|
||||
};
|
||||
|
||||
class Clock
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(Clock)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit Clock(rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
~Clock();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Time
|
||||
now();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
ros_time_is_active();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rcl_clock_type_t
|
||||
get_clock_type();
|
||||
|
||||
// Add a callback to invoke if the jump threshold is exceeded.
|
||||
/**
|
||||
* These callback functions must remain valid as long as the
|
||||
* returned shared pointer is valid.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
JumpHandler::SharedPtr
|
||||
create_jump_callback(
|
||||
std::function<void()> pre_callback,
|
||||
std::function<void(const TimeJump &)> post_callback,
|
||||
JumpThreshold & threshold);
|
||||
|
||||
private:
|
||||
// A method for TimeSource to get a list of callbacks to invoke while updating
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<JumpHandler::SharedPtr>
|
||||
get_triggered_callback_handlers(const TimeJump & jump);
|
||||
|
||||
// Invoke callbacks that are valid and outside threshold.
|
||||
RCLCPP_PUBLIC
|
||||
static void invoke_prejump_callbacks(
|
||||
const std::vector<JumpHandler::SharedPtr> & callbacks);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
static void invoke_postjump_callbacks(
|
||||
const std::vector<JumpHandler::SharedPtr> & callbacks,
|
||||
const TimeJump & jump);
|
||||
|
||||
/// Internal storage backed by rcl
|
||||
rcl_clock_t rcl_clock_;
|
||||
friend TimeSource; /// Allow TimeSource to access the rcl_clock_ datatype.
|
||||
rcl_allocator_t allocator_;
|
||||
|
||||
std::mutex callback_list_mutex_;
|
||||
std::vector<std::weak_ptr<JumpHandler>> active_jump_handlers_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CLOCK_HPP_
|
||||
@@ -30,9 +30,6 @@
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace context
|
||||
{
|
||||
|
||||
class Context
|
||||
{
|
||||
public:
|
||||
@@ -52,13 +49,11 @@ public:
|
||||
auto it = sub_contexts_.find(type_i);
|
||||
if (it == sub_contexts_.end()) {
|
||||
// It doesn't exist yet, make it
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
sub_context = std::shared_ptr<SubContext>(
|
||||
new SubContext(std::forward<Args>(args) ...),
|
||||
[] (SubContext * sub_context_ptr) {
|
||||
[](SubContext * sub_context_ptr) {
|
||||
delete sub_context_ptr;
|
||||
});
|
||||
// *INDENT-ON*
|
||||
sub_contexts_[type_i] = sub_context;
|
||||
} else {
|
||||
// It exists, get it out and cast it.
|
||||
@@ -74,7 +69,6 @@ private:
|
||||
std::mutex mutex_;
|
||||
};
|
||||
|
||||
} // namespace context
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CONTEXT_HPP_
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace contexts
|
||||
namespace default_context
|
||||
{
|
||||
|
||||
class DefaultContext : public rclcpp::context::Context
|
||||
class DefaultContext : public rclcpp::Context
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(DefaultContext)
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace rclcpp
|
||||
{
|
||||
|
||||
template<typename MessageT, typename CallbackT, typename AllocatorT, typename SubscriptionT>
|
||||
typename rclcpp::subscription::Subscription<MessageT, AllocatorT>::SharedPtr
|
||||
typename rclcpp::Subscription<MessageT, AllocatorT>::SharedPtr
|
||||
create_subscription(
|
||||
rclcpp::node_interfaces::NodeTopicsInterface * node_topics,
|
||||
const std::string & topic_name,
|
||||
|
||||
102
rclcpp/include/rclcpp/duration.hpp
Normal file
102
rclcpp/include/rclcpp/duration.hpp
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__DURATION_HPP_
|
||||
#define RCLCPP__DURATION_HPP_
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "builtin_interfaces/msg/duration.hpp"
|
||||
#include "rcl/time.h"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
class Duration
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
Duration(int32_t seconds, uint32_t nanoseconds);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit Duration(
|
||||
rcl_duration_value_t nanoseconds);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit Duration(
|
||||
std::chrono::nanoseconds nanoseconds);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Duration(
|
||||
const builtin_interfaces::msg::Duration & duration_msg);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit Duration(const rcl_duration_t & duration);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Duration(const Duration & rhs);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~Duration();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
operator builtin_interfaces::msg::Duration() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Duration &
|
||||
operator=(const Duration & rhs);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Duration &
|
||||
operator=(const builtin_interfaces::msg::Duration & Duration_msg);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
operator==(const rclcpp::Duration & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
operator<(const rclcpp::Duration & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
operator<=(const rclcpp::Duration & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
operator>=(const rclcpp::Duration & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
operator>(const rclcpp::Duration & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Duration
|
||||
operator+(const rclcpp::Duration & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Duration
|
||||
operator-(const rclcpp::Duration & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rcl_duration_value_t
|
||||
nanoseconds() const;
|
||||
|
||||
private:
|
||||
rcl_duration_t rcl_duration_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__DURATION_HPP_
|
||||
@@ -23,8 +23,6 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace event
|
||||
{
|
||||
|
||||
class Event
|
||||
{
|
||||
@@ -52,7 +50,6 @@ private:
|
||||
std::atomic_bool state_;
|
||||
};
|
||||
|
||||
} // namespace event
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EVENT_HPP_
|
||||
|
||||
@@ -35,18 +35,88 @@ public:
|
||||
: 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 reset_error if true rcl_reset_error() is called before returning
|
||||
* \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
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
throw_from_rcl_error(rcl_ret_t ret, const std::string & prefix = "", bool reset_error = true);
|
||||
throw_from_rcl_error(
|
||||
rcl_ret_t ret,
|
||||
const std::string & prefix = "",
|
||||
const rcl_error_state_t * error_state = nullptr,
|
||||
void (*reset_error)() = rcl_reset_error);
|
||||
|
||||
class RCLErrorBase
|
||||
{
|
||||
|
||||
@@ -38,10 +38,7 @@ namespace rclcpp
|
||||
{
|
||||
|
||||
// Forward declaration is used in convenience method signature.
|
||||
namespace node
|
||||
{
|
||||
class Node;
|
||||
} // namespace node
|
||||
|
||||
namespace executor
|
||||
{
|
||||
@@ -124,7 +121,7 @@ public:
|
||||
/// Convenience function which takes Node and forwards NodeBaseInterface.
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
add_node(std::shared_ptr<rclcpp::node::Node> node_ptr, bool notify = true);
|
||||
add_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true);
|
||||
|
||||
/// Remove a node from the executor.
|
||||
/**
|
||||
@@ -140,7 +137,7 @@ public:
|
||||
/// Convenience function which takes Node and forwards NodeBaseInterface.
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
remove_node(std::shared_ptr<rclcpp::node::Node> node_ptr, bool notify = true);
|
||||
remove_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify = true);
|
||||
|
||||
/// Add a node to executor, execute the next available unit of work, and remove the node.
|
||||
/**
|
||||
@@ -151,7 +148,8 @@ public:
|
||||
*/
|
||||
template<typename T = std::milli>
|
||||
void
|
||||
spin_node_once(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
|
||||
spin_node_once(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node,
|
||||
std::chrono::duration<int64_t, T> timeout = std::chrono::duration<int64_t, T>(-1))
|
||||
{
|
||||
return spin_node_once_nanoseconds(
|
||||
@@ -161,9 +159,10 @@ public:
|
||||
}
|
||||
|
||||
/// Convenience function which takes Node and forwards NodeBaseInterface.
|
||||
template<typename NodeT = rclcpp::node::Node, typename T = std::milli>
|
||||
template<typename NodeT = rclcpp::Node, typename T = std::milli>
|
||||
void
|
||||
spin_node_once(std::shared_ptr<NodeT> node,
|
||||
spin_node_once(
|
||||
std::shared_ptr<NodeT> node,
|
||||
std::chrono::duration<int64_t, T> timeout = std::chrono::duration<int64_t, T>(-1))
|
||||
{
|
||||
return spin_node_once_nanoseconds(
|
||||
@@ -183,7 +182,7 @@ public:
|
||||
/// Convenience function which takes Node and forwards NodeBaseInterface.
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_node_some(std::shared_ptr<rclcpp::node::Node> node);
|
||||
spin_node_some(std::shared_ptr<rclcpp::Node> node);
|
||||
|
||||
/// Complete all available queued work without blocking.
|
||||
/**
|
||||
@@ -202,14 +201,13 @@ public:
|
||||
|
||||
/// Spin (blocking) until the future is complete, it times out waiting, or rclcpp is interrupted.
|
||||
/**
|
||||
* \param[in] executor The executor which will spin the node.
|
||||
* \param[in] node_ptr The node to spin.
|
||||
* \param[in] future The future to wait on. If SUCCESS, the future is safe to access after this
|
||||
function.
|
||||
* function.
|
||||
* \param[in] timeout Optional timeout parameter, which gets passed to Executor::spin_node_once.
|
||||
-1 is block forever, 0 is non-blocking.
|
||||
If the time spent inside the blocking loop exceeds this timeout, return a TIMEOUT return code.
|
||||
* \return The return code, one of SUCCESS, INTERRUPTED, or TIMEOUT.
|
||||
* `-1` is block forever, `0` is non-blocking.
|
||||
* If the time spent inside the blocking loop exceeds this timeout, return a TIMEOUT return
|
||||
* code.
|
||||
* \return The return code, one of `SUCCESS`, `INTERRUPTED`, or `TIMEOUT`.
|
||||
*/
|
||||
template<typename ResponseT, typename TimeT = std::milli>
|
||||
FutureReturnCode
|
||||
@@ -235,7 +233,7 @@ public:
|
||||
}
|
||||
std::chrono::nanoseconds timeout_left = timeout_ns;
|
||||
|
||||
while (rclcpp::utilities::ok()) {
|
||||
while (rclcpp::ok()) {
|
||||
// Do one item of work.
|
||||
spin_once(timeout_left);
|
||||
// Check if the future is set, return SUCCESS if it is.
|
||||
@@ -294,24 +292,24 @@ protected:
|
||||
RCLCPP_PUBLIC
|
||||
static void
|
||||
execute_subscription(
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription);
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
static void
|
||||
execute_intra_process_subscription(
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription);
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
static void
|
||||
execute_timer(rclcpp::timer::TimerBase::SharedPtr timer);
|
||||
execute_timer(rclcpp::TimerBase::SharedPtr timer);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
static void
|
||||
execute_service(rclcpp::service::ServiceBase::SharedPtr service);
|
||||
execute_service(rclcpp::ServiceBase::SharedPtr service);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
static void
|
||||
execute_client(rclcpp::client::ClientBase::SharedPtr client);
|
||||
execute_client(rclcpp::ClientBase::SharedPtr client);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
@@ -323,7 +321,7 @@ protected:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_group_by_timer(rclcpp::timer::TimerBase::SharedPtr timer);
|
||||
get_group_by_timer(rclcpp::TimerBase::SharedPtr timer);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
@@ -343,8 +341,8 @@ protected:
|
||||
/// Guard condition for signaling the rmw layer to wake up for special events.
|
||||
rcl_guard_condition_t interrupt_guard_condition_ = rcl_get_zero_initialized_guard_condition();
|
||||
|
||||
/// Waitset for managing entities that the rmw layer waits on.
|
||||
rcl_wait_set_t waitset_ = rcl_get_zero_initialized_wait_set();
|
||||
/// Wait set for managing entities that the rmw layer waits on.
|
||||
rcl_wait_set_t wait_set_ = rcl_get_zero_initialized_wait_set();
|
||||
|
||||
/// The memory strategy: an interface for handling user-defined memory allocation strategies.
|
||||
memory_strategy::MemoryStrategy::SharedPtr memory_strategy_;
|
||||
|
||||
@@ -28,40 +28,42 @@ namespace rclcpp
|
||||
{
|
||||
|
||||
/// Create a default single-threaded executor and execute any immediately available work.
|
||||
// \param[in] node_ptr Shared pointer to the node to spin.
|
||||
/** \param[in] node_ptr Shared pointer to the node to spin. */
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_some(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_some(rclcpp::node::Node::SharedPtr node_ptr);
|
||||
spin_some(rclcpp::Node::SharedPtr node_ptr);
|
||||
|
||||
/// Create a default single-threaded executor and spin the specified node.
|
||||
// \param[in] node_ptr Shared pointer to the node to spin.
|
||||
/** \param[in] node_ptr Shared pointer to the node to spin. */
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin(rclcpp::node::Node::SharedPtr node_ptr);
|
||||
spin(rclcpp::Node::SharedPtr node_ptr);
|
||||
|
||||
namespace executors
|
||||
{
|
||||
|
||||
using rclcpp::executors::multi_threaded_executor::MultiThreadedExecutor;
|
||||
using rclcpp::executors::single_threaded_executor::SingleThreadedExecutor;
|
||||
using rclcpp::executors::MultiThreadedExecutor;
|
||||
using rclcpp::executors::SingleThreadedExecutor;
|
||||
|
||||
/// Spin (blocking) until the future is complete, it times out waiting, or rclcpp is interrupted.
|
||||
/**
|
||||
* \param[in] executor The executor which will spin the node.
|
||||
* \param[in] node_ptr The node to spin.
|
||||
* \param[in] future The future to wait on. If SUCCESS, the future is safe to access after this function
|
||||
* \param[in] timeout Optional timeout parameter, which gets passed to Executor::spin_node_once.
|
||||
-1 is block forever, 0 is non-blocking.
|
||||
If the time spent inside the blocking loop exceeds this timeout, return a TIMEOUT return code.
|
||||
* \return The return code, one of SUCCESS, INTERRUPTED, or TIMEOUT.
|
||||
* \param[in] future The future to wait on. If `SUCCESS`, the future is safe to
|
||||
* access after this function
|
||||
* \param[in] timeout Optional timeout parameter, which gets passed to
|
||||
* Executor::spin_node_once.
|
||||
* `-1` is block forever, `0` is non-blocking.
|
||||
* If the time spent inside the blocking loop exceeds this timeout, return a `TIMEOUT` return code.
|
||||
* \return The return code, one of `SUCCESS`, `INTERRUPTED`, or `TIMEOUT`.
|
||||
*/
|
||||
template<typename ResponseT, typename TimeT = std::milli>
|
||||
rclcpp::executor::FutureReturnCode
|
||||
@@ -79,7 +81,7 @@ spin_node_until_future_complete(
|
||||
return retcode;
|
||||
}
|
||||
|
||||
template<typename NodeT = rclcpp::node::Node, typename ResponseT, typename TimeT = std::milli>
|
||||
template<typename NodeT = rclcpp::Node, typename ResponseT, typename TimeT = std::milli>
|
||||
rclcpp::executor::FutureReturnCode
|
||||
spin_node_until_future_complete(
|
||||
rclcpp::executor::Executor & executor,
|
||||
@@ -107,7 +109,7 @@ spin_until_future_complete(
|
||||
return executors::spin_node_until_future_complete<FutureT>(executor, node_ptr, future, timeout);
|
||||
}
|
||||
|
||||
template<typename NodeT = rclcpp::node::Node, typename FutureT, typename TimeT = std::milli>
|
||||
template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeT = std::milli>
|
||||
rclcpp::executor::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
std::shared_ptr<NodeT> node_ptr,
|
||||
|
||||
@@ -28,8 +28,6 @@ namespace rclcpp
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
namespace multi_threaded_executor
|
||||
{
|
||||
|
||||
class MultiThreadedExecutor : public executor::Executor
|
||||
{
|
||||
@@ -63,7 +61,6 @@ private:
|
||||
size_t number_of_threads_;
|
||||
};
|
||||
|
||||
} // namespace multi_threaded_executor
|
||||
} // namespace executors
|
||||
} // namespace rclcpp
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@ namespace rclcpp
|
||||
{
|
||||
namespace executors
|
||||
{
|
||||
namespace single_threaded_executor
|
||||
{
|
||||
|
||||
/// Single-threaded executor implementation
|
||||
// This is the default executor created by rclcpp::spin.
|
||||
@@ -64,7 +62,6 @@ private:
|
||||
RCLCPP_DISABLE_COPY(SingleThreadedExecutor)
|
||||
};
|
||||
|
||||
} // namespace single_threaded_executor
|
||||
} // namespace executors
|
||||
} // namespace rclcpp
|
||||
|
||||
|
||||
63
rclcpp/include/rclcpp/expand_topic_or_service_name.hpp
Normal file
63
rclcpp/include/rclcpp/expand_topic_or_service_name.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXPAND_TOPIC_OR_SERVICE_NAME_HPP_
|
||||
#define RCLCPP__EXPAND_TOPIC_OR_SERVICE_NAME_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Expand a topic or service name and throw if it is not valid.
|
||||
/**
|
||||
* This function can be used to "just" validate a topic or service name too,
|
||||
* since expanding the topic name is required to fully validate a name.
|
||||
*
|
||||
* If the name is invalid, then InvalidTopicNameError is thrown or
|
||||
* InvalidServiceNameError if is_service is true.
|
||||
*
|
||||
* This function can take any form of a topic or service name, i.e. it does not
|
||||
* have to be a fully qualified name.
|
||||
* The node name and namespace are used to expand it if necessary while
|
||||
* validating it.
|
||||
*
|
||||
* Expansion is done with rcl_expand_topic_name.
|
||||
* The validation is doen with rcl_validate_topic_name and
|
||||
* rmw_validate_full_topic_name, so details about failures can be found in the
|
||||
* documentation for those functions.
|
||||
*
|
||||
* \param name the topic or service name to be validated
|
||||
* \param node_name the name of the node associated with the name
|
||||
* \param namespace_ the namespace of the node associated with the name
|
||||
* \param is_service if true InvalidServiceNameError is thrown instead
|
||||
* \returns expanded (and validated) topic name
|
||||
* \throws InvalidTopicNameError if name is invalid and is_service is false
|
||||
* \throws InvalidServiceNameError if name is invalid and is_service is true
|
||||
* \throws std::bad_alloc if memory cannot be allocated
|
||||
* \throws RCLError if an unexpect error occurs
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
expand_topic_or_service_name(
|
||||
const std::string & name,
|
||||
const std::string & node_name,
|
||||
const std::string & namespace_,
|
||||
bool is_service = false);
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXPAND_TOPIC_OR_SERVICE_NAME_HPP_
|
||||
@@ -82,6 +82,8 @@ struct function_traits<ReturnTypeT (*)(Args ...)>: function_traits<ReturnTypeT(A
|
||||
template<typename ClassT, typename ReturnTypeT, typename ... Args, typename ... FArgs>
|
||||
#if defined _LIBCPP_VERSION // libc++ (Clang)
|
||||
struct function_traits<std::__1::__bind<ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
|
||||
#elif defined _GLIBCXX_RELEASE // glibc++ (GNU C++ >= 7.1)
|
||||
struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(ClassT *, FArgs ...))(Args ...)>>
|
||||
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
|
||||
struct function_traits<std::_Bind<std::_Mem_fn<ReturnTypeT (ClassT::*)(Args ...)>(FArgs ...)>>
|
||||
#elif defined _MSC_VER // MS Visual Studio
|
||||
|
||||
@@ -68,7 +68,8 @@ public:
|
||||
virtual ~GraphListener();
|
||||
|
||||
/// Start the graph listener's listen thread if it hasn't been started.
|
||||
/* This function is thread-safe.
|
||||
/**
|
||||
* This function is thread-safe.
|
||||
*
|
||||
* \throws GraphListenerShutdownError if the GraphListener is shutdown
|
||||
*/
|
||||
@@ -78,7 +79,7 @@ public:
|
||||
start_if_not_started();
|
||||
|
||||
/// Add a node to the graph listener's list of nodes.
|
||||
/*
|
||||
/**
|
||||
* \throws GraphListenerShutdownError if the GraphListener is shutdown
|
||||
* \throws NodeAlreadyAddedError if the given node is already in the list
|
||||
* \throws std::invalid_argument if node is nullptr
|
||||
@@ -90,7 +91,8 @@ public:
|
||||
add_node(rclcpp::node_interfaces::NodeGraphInterface * node_graph);
|
||||
|
||||
/// Return true if the given node is in the graph listener's list of nodes.
|
||||
/* Also return false if given nullptr.
|
||||
/**
|
||||
* Also return false if given nullptr.
|
||||
*
|
||||
* \throws std::system_error anything std::mutex::lock() throws
|
||||
*/
|
||||
@@ -100,7 +102,8 @@ public:
|
||||
has_node(rclcpp::node_interfaces::NodeGraphInterface * node_graph);
|
||||
|
||||
/// Remove a node from the graph listener's list of nodes.
|
||||
/*
|
||||
/**
|
||||
*
|
||||
* \throws NodeNotFoundError if the given node is not in the list
|
||||
* \throws std::invalid_argument if node is nullptr
|
||||
* \throws std::system_error anything std::mutex::lock() throws
|
||||
@@ -111,7 +114,8 @@ public:
|
||||
remove_node(rclcpp::node_interfaces::NodeGraphInterface * node_graph);
|
||||
|
||||
/// Stop the listening thread.
|
||||
/* The thread cannot be restarted, and the class is defunct after calling.
|
||||
/**
|
||||
* The thread cannot be restarted, and the class is defunct after calling.
|
||||
* This function is called by the ~GraphListener() and does nothing if
|
||||
* shutdown() was already called.
|
||||
* This function exists separately from the ~GraphListener() so that it can
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <set>
|
||||
|
||||
@@ -40,7 +41,8 @@ namespace intra_process_manager
|
||||
{
|
||||
|
||||
/// This class facilitates intra process communication between nodes.
|
||||
/* This class is used in the creation of publishers and subscriptions.
|
||||
/**
|
||||
* This class is used in the creation of publishers and subscriptions.
|
||||
* A singleton instance of this class is owned by a rclcpp::Context and a
|
||||
* rclcpp::Node can use an associated Context to get an instance of this class.
|
||||
* Nodes which do not have a common Context will not exchange intra process
|
||||
@@ -54,7 +56,7 @@ namespace intra_process_manager
|
||||
* When a publisher is created, it advertises on the topic the user provided,
|
||||
* as well as a "shadowing" topic of type rcl_interfaces/IntraProcessMessage.
|
||||
* For instance, if the user specified the topic '/namespace/chatter', then the
|
||||
* corresponding intra process topic might be '/namespace/chatter__intra'.
|
||||
* corresponding intra process topic might be '/namespace/chatter/_intra'.
|
||||
* The publisher is also allocated an id which is unique among all publishers
|
||||
* and subscriptions in this process.
|
||||
* Additionally, when registered with this class a ring buffer is created and
|
||||
@@ -133,7 +135,8 @@ public:
|
||||
virtual ~IntraProcessManager();
|
||||
|
||||
/// Register a subscription with the manager, returns subscriptions unique id.
|
||||
/* In addition to generating a unique intra process id for the subscription,
|
||||
/**
|
||||
* In addition to generating a unique intra process id for the subscription,
|
||||
* this method also stores the topic name of the subscription.
|
||||
*
|
||||
* This method is normally called during the creation of a subscription,
|
||||
@@ -146,10 +149,11 @@ public:
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
uint64_t
|
||||
add_subscription(subscription::SubscriptionBase::SharedPtr subscription);
|
||||
add_subscription(SubscriptionBase::SharedPtr subscription);
|
||||
|
||||
/// Unregister a subscription using the subscription's unique id.
|
||||
/* This method does not allocate memory.
|
||||
/**
|
||||
* This method does not allocate memory.
|
||||
*
|
||||
* \param intra_process_subscription_id id of the subscription to remove.
|
||||
*/
|
||||
@@ -158,7 +162,8 @@ public:
|
||||
remove_subscription(uint64_t intra_process_subscription_id);
|
||||
|
||||
/// Register a publisher with the manager, returns the publisher unique id.
|
||||
/* In addition to generating and returning a unique id for the publisher,
|
||||
/**
|
||||
* In addition to generating and returning a unique id for the publisher,
|
||||
* this method creates internal ring buffer storage for "in-flight" intra
|
||||
* process messages which are stored when store_intra_process_message is
|
||||
* called with this publisher's unique id.
|
||||
@@ -181,20 +186,23 @@ public:
|
||||
*/
|
||||
template<typename MessageT, typename Alloc>
|
||||
uint64_t
|
||||
add_publisher(typename publisher::Publisher<MessageT, Alloc>::SharedPtr publisher,
|
||||
add_publisher(
|
||||
typename Publisher<MessageT, Alloc>::SharedPtr publisher,
|
||||
size_t buffer_size = 0)
|
||||
{
|
||||
auto id = IntraProcessManager::get_next_unique_id();
|
||||
size_t size = buffer_size > 0 ? buffer_size : publisher->get_queue_size();
|
||||
auto mrb = mapped_ring_buffer::MappedRingBuffer<MessageT,
|
||||
typename publisher::Publisher<MessageT, Alloc>::MessageAlloc>::make_shared(
|
||||
size, publisher->get_allocator());
|
||||
auto mrb = mapped_ring_buffer::MappedRingBuffer<
|
||||
MessageT,
|
||||
typename Publisher<MessageT, Alloc>::MessageAlloc
|
||||
>::make_shared(size, publisher->get_allocator());
|
||||
impl_->add_publisher(id, publisher, mrb, size);
|
||||
return id;
|
||||
}
|
||||
|
||||
/// Unregister a publisher using the publisher's unique id.
|
||||
/* This method does not allocate memory.
|
||||
/**
|
||||
* This method does not allocate memory.
|
||||
*
|
||||
* \param intra_process_publisher_id id of the publisher to remove.
|
||||
*/
|
||||
@@ -203,7 +211,8 @@ public:
|
||||
remove_publisher(uint64_t intra_process_publisher_id);
|
||||
|
||||
/// Store a message in the manager, and return the message sequence number.
|
||||
/* The given message is stored in internal storage using the given publisher
|
||||
/**
|
||||
* The given message is stored in internal storage using the given publisher
|
||||
* id and the newly generated message sequence, which is also returned.
|
||||
* The combination of publisher id and message sequence number can later
|
||||
* be used with a subscription id to retrieve the message by calling
|
||||
@@ -232,8 +241,9 @@ public:
|
||||
* \param message the message that is being stored.
|
||||
* \return the message sequence number.
|
||||
*/
|
||||
template<typename MessageT, typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>>
|
||||
template<
|
||||
typename MessageT, typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>>
|
||||
uint64_t
|
||||
store_intra_process_message(
|
||||
uint64_t intra_process_publisher_id,
|
||||
@@ -261,7 +271,8 @@ public:
|
||||
}
|
||||
|
||||
/// Take an intra process message.
|
||||
/* The intra_process_publisher_id and message_sequence_number parameters
|
||||
/**
|
||||
* The intra_process_publisher_id and message_sequence_number parameters
|
||||
* uniquely identify a message instance, which should be taken.
|
||||
*
|
||||
* The requesting_subscriptions_intra_process_id parameter is used to make
|
||||
@@ -294,8 +305,9 @@ public:
|
||||
* \param requesting_subscriptions_intra_process_id the subscription's id.
|
||||
* \param message the message typed unique_ptr used to return the message.
|
||||
*/
|
||||
template<typename MessageT, typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>>
|
||||
template<
|
||||
typename MessageT, typename Alloc = std::allocator<void>,
|
||||
typename Deleter = std::default_delete<MessageT>>
|
||||
void
|
||||
take_intra_process_message(
|
||||
uint64_t intra_process_publisher_id,
|
||||
@@ -308,6 +320,7 @@ public:
|
||||
message = nullptr;
|
||||
|
||||
size_t target_subs_size = 0;
|
||||
std::lock_guard<std::mutex> lock(take_mutex_);
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer = impl_->take_intra_process_message(
|
||||
intra_process_publisher_id,
|
||||
message_sequence_number,
|
||||
@@ -339,6 +352,7 @@ private:
|
||||
get_next_unique_id();
|
||||
|
||||
IntraProcessManagerImplBase::SharedPtr impl_;
|
||||
std::mutex take_mutex_;
|
||||
};
|
||||
|
||||
} // namespace intra_process_manager
|
||||
|
||||
@@ -48,13 +48,14 @@ public:
|
||||
~IntraProcessManagerImplBase() = default;
|
||||
|
||||
virtual void
|
||||
add_subscription(uint64_t id, subscription::SubscriptionBase::SharedPtr subscription) = 0;
|
||||
add_subscription(uint64_t id, SubscriptionBase::SharedPtr subscription) = 0;
|
||||
|
||||
virtual void
|
||||
remove_subscription(uint64_t intra_process_subscription_id) = 0;
|
||||
|
||||
virtual void add_publisher(uint64_t id,
|
||||
publisher::PublisherBase::WeakPtr publisher,
|
||||
virtual void add_publisher(
|
||||
uint64_t id,
|
||||
PublisherBase::WeakPtr publisher,
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr mrb,
|
||||
size_t size) = 0;
|
||||
|
||||
@@ -70,7 +71,8 @@ public:
|
||||
store_intra_process_message(uint64_t intra_process_publisher_id, uint64_t message_seq) = 0;
|
||||
|
||||
virtual mapped_ring_buffer::MappedRingBufferBase::SharedPtr
|
||||
take_intra_process_message(uint64_t intra_process_publisher_id,
|
||||
take_intra_process_message(
|
||||
uint64_t intra_process_publisher_id,
|
||||
uint64_t message_sequence_number,
|
||||
uint64_t requesting_subscriptions_intra_process_id,
|
||||
size_t & size) = 0;
|
||||
@@ -90,7 +92,7 @@ public:
|
||||
~IntraProcessManagerImpl() = default;
|
||||
|
||||
void
|
||||
add_subscription(uint64_t id, subscription::SubscriptionBase::SharedPtr subscription)
|
||||
add_subscription(uint64_t id, SubscriptionBase::SharedPtr subscription)
|
||||
{
|
||||
subscriptions_[id] = subscription;
|
||||
// subscription->get_topic_name() -> const char * can be used as the key,
|
||||
@@ -114,8 +116,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void add_publisher(uint64_t id,
|
||||
publisher::PublisherBase::WeakPtr publisher,
|
||||
void add_publisher(
|
||||
uint64_t id,
|
||||
PublisherBase::WeakPtr publisher,
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr mrb,
|
||||
size_t size)
|
||||
{
|
||||
@@ -189,7 +192,8 @@ public:
|
||||
}
|
||||
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr
|
||||
take_intra_process_message(uint64_t intra_process_publisher_id,
|
||||
take_intra_process_message(
|
||||
uint64_t intra_process_publisher_id,
|
||||
uint64_t message_sequence_number,
|
||||
uint64_t requesting_subscriptions_intra_process_id,
|
||||
size_t & size
|
||||
@@ -253,9 +257,10 @@ private:
|
||||
RebindAlloc<uint64_t> uint64_allocator;
|
||||
|
||||
using AllocSet = std::set<uint64_t, std::less<uint64_t>, RebindAlloc<uint64_t>>;
|
||||
using SubscriptionMap = std::unordered_map<uint64_t, subscription::SubscriptionBase::WeakPtr,
|
||||
using SubscriptionMap = std::unordered_map<
|
||||
uint64_t, SubscriptionBase::WeakPtr,
|
||||
std::hash<uint64_t>, std::equal_to<uint64_t>,
|
||||
RebindAlloc<std::pair<const uint64_t, subscription::SubscriptionBase::WeakPtr>>>;
|
||||
RebindAlloc<std::pair<const uint64_t, SubscriptionBase::WeakPtr>>>;
|
||||
|
||||
struct strcmp_wrapper : public std::binary_function<const char *, const char *, bool>
|
||||
{
|
||||
@@ -269,7 +274,7 @@ private:
|
||||
const char *,
|
||||
AllocSet,
|
||||
strcmp_wrapper,
|
||||
RebindAlloc<std::pair<const std::string, AllocSet>>>;
|
||||
RebindAlloc<std::pair<const char * const, AllocSet>>>;
|
||||
|
||||
SubscriptionMap subscriptions_;
|
||||
|
||||
@@ -281,17 +286,19 @@ private:
|
||||
|
||||
PublisherInfo() = default;
|
||||
|
||||
publisher::PublisherBase::WeakPtr publisher;
|
||||
PublisherBase::WeakPtr publisher;
|
||||
std::atomic<uint64_t> sequence_number;
|
||||
mapped_ring_buffer::MappedRingBufferBase::SharedPtr buffer;
|
||||
|
||||
using TargetSubscriptionsMap = std::unordered_map<uint64_t, AllocSet,
|
||||
using TargetSubscriptionsMap = std::unordered_map<
|
||||
uint64_t, AllocSet,
|
||||
std::hash<uint64_t>, std::equal_to<uint64_t>,
|
||||
RebindAlloc<std::pair<const uint64_t, AllocSet>>>;
|
||||
TargetSubscriptionsMap target_subscriptions_by_message_sequence;
|
||||
};
|
||||
|
||||
using PublisherMap = std::unordered_map<uint64_t, PublisherInfo,
|
||||
using PublisherMap = std::unordered_map<
|
||||
uint64_t, PublisherInfo,
|
||||
std::hash<uint64_t>, std::equal_to<uint64_t>,
|
||||
RebindAlloc<std::pair<const uint64_t, PublisherInfo>>>;
|
||||
|
||||
|
||||
131
rclcpp/include/rclcpp/logger.hpp
Normal file
131
rclcpp/include/rclcpp/logger.hpp
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__LOGGER_HPP_
|
||||
#define RCLCPP__LOGGER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOGGING_ENABLED
|
||||
* When this define evaluates to true (default), logger factory functions will
|
||||
* behave normally.
|
||||
* When false, logger factory functions will create dummy loggers to avoid
|
||||
* computational expense in manipulating objects.
|
||||
* This should be used in combination with `RCLCPP_LOG_MIN_SEVERITY` to compile
|
||||
* out logging macros.
|
||||
*/
|
||||
// TODO(dhood): determine this automatically from `RCLCPP_LOG_MIN_SEVERITY`
|
||||
#ifndef RCLCPP_LOGGING_ENABLED
|
||||
#define RCLCPP_LOGGING_ENABLED 1
|
||||
#endif
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
// Forward declaration is used for friend statement.
|
||||
namespace node_interfaces
|
||||
{
|
||||
class NodeLogging;
|
||||
}
|
||||
|
||||
class Logger;
|
||||
|
||||
/// Return a named logger.
|
||||
/**
|
||||
* The returned logger's name will include any naming conventions, such as a
|
||||
* name prefix.
|
||||
* Currently there are no such naming conventions but they may be introduced in
|
||||
* the future.
|
||||
*
|
||||
* \param[in] name the name of the logger
|
||||
* \return a logger with the fully-qualified name including naming conventions, or
|
||||
* \return a dummy logger if logging is disabled.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
Logger
|
||||
get_logger(const std::string & name);
|
||||
|
||||
class Logger
|
||||
{
|
||||
private:
|
||||
friend Logger rclcpp::get_logger(const std::string & name);
|
||||
friend ::rclcpp::node_interfaces::NodeLogging;
|
||||
|
||||
/// Constructor of a dummy logger.
|
||||
/**
|
||||
* This is used when logging is disabled: see `RCLCPP_LOGGING_ENABLED`.
|
||||
* This cannot be called directly, see `rclcpp::get_logger` instead.
|
||||
*/
|
||||
Logger()
|
||||
: name_(nullptr) {}
|
||||
|
||||
/// Constructor of a named logger.
|
||||
/**
|
||||
* This cannot be called directly, see `rclcpp::get_logger` instead.
|
||||
*/
|
||||
explicit Logger(const std::string & name)
|
||||
: name_(new std::string(name)) {}
|
||||
|
||||
std::shared_ptr<const std::string> name_;
|
||||
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
Logger(const Logger &) = default;
|
||||
|
||||
/// Get the name of this logger.
|
||||
/**
|
||||
* \return the full name of the logger including any prefixes, or
|
||||
* \return `nullptr` if this logger is invalid (e.g. because logging is
|
||||
* disabled).
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
const char *
|
||||
get_name() const
|
||||
{
|
||||
if (!name_) {
|
||||
return nullptr;
|
||||
}
|
||||
return name_->c_str();
|
||||
}
|
||||
|
||||
/// Return a logger that is a descendant of this logger.
|
||||
/**
|
||||
* The child logger's full name will include any hierarchy conventions that
|
||||
* indicate it is a descendant of this logger.
|
||||
* For example, ```get_logger('abc').get_child('def')``` will return a logger
|
||||
* with name `abc.def`.
|
||||
*
|
||||
* \param[in] suffix the child logger's suffix
|
||||
* \return a logger with the fully-qualified name including the suffix, or
|
||||
* \return a dummy logger if this logger is invalid (e.g. because logging is
|
||||
* disabled).
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
Logger
|
||||
get_child(const std::string & suffix)
|
||||
{
|
||||
if (!name_) {
|
||||
return Logger();
|
||||
}
|
||||
return Logger(*name_ + "." + suffix);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__LOGGER_HPP_
|
||||
@@ -18,7 +18,8 @@
|
||||
#ifndef RCLCPP__MACROS_HPP_
|
||||
#define RCLCPP__MACROS_HPP_
|
||||
|
||||
/* Disables the copy constructor and operator= for the given class.
|
||||
/**
|
||||
* Disables the copy constructor and operator= for the given class.
|
||||
*
|
||||
* Use in the private section of the class.
|
||||
*/
|
||||
@@ -26,38 +27,41 @@
|
||||
__VA_ARGS__(const __VA_ARGS__ &) = delete; \
|
||||
__VA_ARGS__ & operator=(const __VA_ARGS__ &) = delete;
|
||||
|
||||
/* Defines aliases and static functions for using the Class with smart pointers.
|
||||
/**
|
||||
* Defines aliases and static functions for using the Class with smart pointers.
|
||||
*
|
||||
* Use in the public section of the class.
|
||||
* Make sure to include <memory> in the header when using this.
|
||||
* Make sure to include `<memory>` in the header when using this.
|
||||
*/
|
||||
#define RCLCPP_SMART_PTR_DEFINITIONS(...) \
|
||||
RCLCPP_SHARED_PTR_DEFINITIONS(__VA_ARGS__) \
|
||||
RCLCPP_WEAK_PTR_DEFINITIONS(__VA_ARGS__) \
|
||||
RCLCPP_UNIQUE_PTR_DEFINITIONS(__VA_ARGS__)
|
||||
|
||||
/* Defines aliases and static functions for using the Class with smart pointers.
|
||||
/**
|
||||
* Defines aliases and static functions for using the Class with smart pointers.
|
||||
*
|
||||
* Same as RCLCPP_SMART_PTR_DEFINITIONS expect it excludes the static
|
||||
* Same as RCLCPP_SMART_PTR_DEFINITIONS except it excludes the static
|
||||
* Class::make_unique() method definition which does not work on classes which
|
||||
* are not CopyConstructable.
|
||||
*
|
||||
* Use in the public section of the class.
|
||||
* Make sure to include <memory> in the header when using this.
|
||||
* Make sure to include `<memory>` in the header when using this.
|
||||
*/
|
||||
#define RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(...) \
|
||||
RCLCPP_SHARED_PTR_DEFINITIONS(__VA_ARGS__) \
|
||||
RCLCPP_WEAK_PTR_DEFINITIONS(__VA_ARGS__) \
|
||||
__RCLCPP_UNIQUE_PTR_ALIAS(__VA_ARGS__)
|
||||
|
||||
/* Defines aliases only for using the Class with smart pointers.
|
||||
/**
|
||||
* Defines aliases only for using the Class with smart pointers.
|
||||
*
|
||||
* Same as RCLCPP_SMART_PTR_DEFINITIONS expect it excludes the static
|
||||
* Same as RCLCPP_SMART_PTR_DEFINITIONS except it excludes the static
|
||||
* method definitions which do not work on pure virtual classes and classes
|
||||
* which are not CopyConstructable.
|
||||
*
|
||||
* Use in the public section of the class.
|
||||
* Make sure to include <memory> in the header when using this.
|
||||
* Make sure to include `<memory>` in the header when using this.
|
||||
*/
|
||||
#define RCLCPP_SMART_PTR_ALIASES_ONLY(...) \
|
||||
__RCLCPP_SHARED_PTR_ALIAS(__VA_ARGS__) \
|
||||
@@ -106,6 +110,4 @@
|
||||
#define RCLCPP_STRING_JOIN(arg1, arg2) RCLCPP_DO_STRING_JOIN(arg1, arg2)
|
||||
#define RCLCPP_DO_STRING_JOIN(arg1, arg2) arg1 ## arg2
|
||||
|
||||
#define RCLCPP_INFO(Args) std::cout << Args << std::endl;
|
||||
|
||||
#endif // RCLCPP__MACROS_HPP_
|
||||
|
||||
@@ -39,7 +39,8 @@ public:
|
||||
};
|
||||
|
||||
/// Ring buffer container of unique_ptr's of T, which can be accessed by a key.
|
||||
/* T must be a CopyConstructable and CopyAssignable.
|
||||
/**
|
||||
* T must be a CopyConstructable and CopyAssignable.
|
||||
* This class can be used in a container by using the base class MappedRingBufferBase.
|
||||
* This class must have a positive, non-zero size.
|
||||
* This class cannot be resized nor can it reserve additional space after construction.
|
||||
@@ -66,9 +67,11 @@ public:
|
||||
using ElemUniquePtr = std::unique_ptr<T, ElemDeleter>;
|
||||
|
||||
/// Constructor.
|
||||
/* The constructor will allocate memory while reserving space.
|
||||
/**
|
||||
* The constructor will allocate memory while reserving space.
|
||||
*
|
||||
* \param size size of the ring buffer; must be positive and non-zero.
|
||||
* \param allocator optional custom allocator
|
||||
*/
|
||||
explicit MappedRingBuffer(size_t size, std::shared_ptr<Alloc> allocator = nullptr)
|
||||
: elements_(size), head_(0)
|
||||
@@ -86,7 +89,8 @@ public:
|
||||
virtual ~MappedRingBuffer() {}
|
||||
|
||||
/// Return a copy of the value stored in the ring buffer at the given key.
|
||||
/* The key is matched if an element in the ring buffer has a matching key.
|
||||
/**
|
||||
* The key is matched if an element in the ring buffer has a matching key.
|
||||
* This method will allocate in order to return a copy.
|
||||
*
|
||||
* The key is not guaranteed to be unique, see the class docs for more.
|
||||
@@ -110,7 +114,8 @@ public:
|
||||
}
|
||||
|
||||
/// Return ownership of the value stored in the ring buffer, leaving a copy.
|
||||
/* The key is matched if an element in the ring bufer has a matching key.
|
||||
/**
|
||||
* The key is matched if an element in the ring bufer has a matching key.
|
||||
* This method will allocate in order to store a copy.
|
||||
*
|
||||
* The key is not guaranteed to be unique, see the class docs for more.
|
||||
@@ -147,7 +152,8 @@ public:
|
||||
}
|
||||
|
||||
/// Return ownership of the value stored in the ring buffer at the given key.
|
||||
/* The key is matched if an element in the ring buffer has a matching key.
|
||||
/**
|
||||
* The key is matched if an element in the ring buffer has a matching key.
|
||||
*
|
||||
* The key is not guaranteed to be unique, see the class docs for more.
|
||||
*
|
||||
@@ -169,7 +175,8 @@ public:
|
||||
}
|
||||
|
||||
/// Insert a key-value pair, displacing an existing pair if necessary.
|
||||
/* The key's uniqueness is not checked on insertion.
|
||||
/**
|
||||
* The key's uniqueness is not checked on insertion.
|
||||
* It is up to the user to ensure the key is unique.
|
||||
* This method should not allocate memory.
|
||||
*
|
||||
@@ -221,11 +228,11 @@ private:
|
||||
typename std::vector<element, VectorAlloc>::iterator
|
||||
get_iterator_of_key(uint64_t key)
|
||||
{
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
auto it = std::find_if(elements_.begin(), elements_.end(), [key](element & e) -> bool {
|
||||
return e.key == key && e.in_use;
|
||||
});
|
||||
// *INDENT-ON*
|
||||
auto it = std::find_if(
|
||||
elements_.begin(), elements_.end(),
|
||||
[key](element & e) -> bool {
|
||||
return e.key == key && e.in_use;
|
||||
});
|
||||
return it;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
virtual size_t number_of_ready_timers() const = 0;
|
||||
virtual size_t number_of_guard_conditions() const = 0;
|
||||
|
||||
virtual bool add_handles_to_waitset(rcl_wait_set_t * wait_set) = 0;
|
||||
virtual bool add_handles_to_wait_set(rcl_wait_set_t * wait_set) = 0;
|
||||
virtual void clear_handles() = 0;
|
||||
virtual void remove_null_handles(rcl_wait_set_t * wait_set) = 0;
|
||||
|
||||
@@ -64,46 +64,52 @@ public:
|
||||
virtual void remove_guard_condition(const rcl_guard_condition_t * guard_condition) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_subscription(rclcpp::executor::AnyExecutable::SharedPtr any_exec,
|
||||
get_next_subscription(
|
||||
rclcpp::executor::AnyExecutable::SharedPtr any_exec,
|
||||
const WeakNodeVector & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_service(rclcpp::executor::AnyExecutable::SharedPtr any_exec,
|
||||
get_next_service(
|
||||
rclcpp::executor::AnyExecutable::SharedPtr any_exec,
|
||||
const WeakNodeVector & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_client(rclcpp::executor::AnyExecutable::SharedPtr any_exec,
|
||||
get_next_client(
|
||||
rclcpp::executor::AnyExecutable::SharedPtr any_exec,
|
||||
const WeakNodeVector & weak_nodes) = 0;
|
||||
|
||||
virtual rcl_allocator_t
|
||||
get_allocator() = 0;
|
||||
|
||||
static rclcpp::subscription::SubscriptionBase::SharedPtr
|
||||
get_subscription_by_handle(const rcl_subscription_t * subscriber_handle,
|
||||
static rclcpp::SubscriptionBase::SharedPtr
|
||||
get_subscription_by_handle(
|
||||
const rcl_subscription_t * subscriber_handle,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
|
||||
static rclcpp::service::ServiceBase::SharedPtr
|
||||
static rclcpp::ServiceBase::SharedPtr
|
||||
get_service_by_handle(const rcl_service_t * service_handle, const WeakNodeVector & weak_nodes);
|
||||
|
||||
static rclcpp::client::ClientBase::SharedPtr
|
||||
static rclcpp::ClientBase::SharedPtr
|
||||
get_client_by_handle(const rcl_client_t * client_handle, const WeakNodeVector & weak_nodes);
|
||||
|
||||
static rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
get_node_by_group(
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_group_by_subscription(
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_group_by_service(
|
||||
rclcpp::service::ServiceBase::SharedPtr service,
|
||||
rclcpp::ServiceBase::SharedPtr service,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_group_by_client(rclcpp::client::ClientBase::SharedPtr client,
|
||||
get_group_by_client(
|
||||
rclcpp::ClientBase::SharedPtr client,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
};
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace message_memory_strategy
|
||||
{
|
||||
|
||||
/// Default allocation strategy for messages received by subscriptions.
|
||||
// A message memory strategy must be templated on the type of the subscription it belongs to.
|
||||
/** A message memory strategy must be templated on the type of the subscription it belongs to. */
|
||||
template<typename MessageT, typename Alloc = std::allocator<void>>
|
||||
class MessageMemoryStrategy
|
||||
{
|
||||
@@ -56,14 +56,14 @@ public:
|
||||
}
|
||||
|
||||
/// By default, dynamically allocate a new message.
|
||||
// \return Shared pointer to the new message.
|
||||
/** \return Shared pointer to the new message. */
|
||||
virtual std::shared_ptr<MessageT> borrow_message()
|
||||
{
|
||||
return std::allocate_shared<MessageT, MessageAlloc>(*message_allocator_.get());
|
||||
}
|
||||
|
||||
/// Release ownership of the message, which will deallocate it if it has no more owners.
|
||||
// \param[in] Shared pointer to the message we are returning.
|
||||
/** \param[in] msg Shared pointer to the message we are returning. */
|
||||
virtual void return_message(std::shared_ptr<MessageT> & msg)
|
||||
{
|
||||
msg.reset();
|
||||
|
||||
@@ -35,12 +35,16 @@
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/client.hpp"
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/context.hpp"
|
||||
#include "rclcpp/event.hpp"
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/message_memory_strategy.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_clock_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_services_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
@@ -49,15 +53,13 @@
|
||||
#include "rclcpp/publisher.hpp"
|
||||
#include "rclcpp/service.hpp"
|
||||
#include "rclcpp/subscription.hpp"
|
||||
#include "rclcpp/time.hpp"
|
||||
#include "rclcpp/timer.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace node
|
||||
{
|
||||
|
||||
/// Node is the single point of entry for creating publishers and subscribers.
|
||||
class Node : public std::enable_shared_from_this<Node>
|
||||
{
|
||||
@@ -67,33 +69,52 @@ public:
|
||||
/// Create a new node with the specified name.
|
||||
/**
|
||||
* \param[in] node_name Name of the node.
|
||||
* \param[in] namespace_ Namespace of the node.
|
||||
* \param[in] use_intra_process_comms True to use the optimized intra-process communication
|
||||
* pipeline to pass messages between nodes in the same process using shared memory.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit Node(const std::string & node_name, bool use_intra_process_comms = false);
|
||||
explicit Node(
|
||||
const std::string & node_name,
|
||||
const std::string & namespace_ = "",
|
||||
bool use_intra_process_comms = false);
|
||||
|
||||
/// Create a node based on the node name and a rclcpp::context::Context.
|
||||
/// Create a node based on the node name and a rclcpp::Context.
|
||||
/**
|
||||
* \param[in] node_name Name of the node.
|
||||
* \param[in] namespace_ Namespace of the node.
|
||||
* \param[in] context The context for the node (usually represents the state of a process).
|
||||
* \param[in] use_intra_process_comms True to use the optimized intra-process communication
|
||||
* pipeline to pass messages between nodes in the same process using shared memory.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
Node(
|
||||
const std::string & node_name, rclcpp::context::Context::SharedPtr context,
|
||||
const std::string & node_name,
|
||||
const std::string & namespace_,
|
||||
rclcpp::Context::SharedPtr context,
|
||||
bool use_intra_process_comms = false);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~Node();
|
||||
|
||||
/// Get the name of the node.
|
||||
// \return The name of the node.
|
||||
/** \return The name of the node. */
|
||||
RCLCPP_PUBLIC
|
||||
const char *
|
||||
get_name() const;
|
||||
|
||||
/// Get the namespace of the node.
|
||||
/** \return The namespace of the node. */
|
||||
RCLCPP_PUBLIC
|
||||
const char *
|
||||
get_namespace() const;
|
||||
|
||||
/// Get the logger of the node.
|
||||
/** \return The logger of the node. */
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::Logger
|
||||
get_logger() const;
|
||||
|
||||
/// Create and return a callback group.
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
@@ -108,11 +129,12 @@ public:
|
||||
/**
|
||||
* \param[in] topic_name The topic for this publisher to publish on.
|
||||
* \param[in] qos_history_depth The depth of the publisher message queue.
|
||||
* \param[in] allocator Optional custom allocator.
|
||||
* \return Shared pointer to the created publisher.
|
||||
*/
|
||||
template<
|
||||
typename MessageT, typename Alloc = std::allocator<void>,
|
||||
typename PublisherT = ::rclcpp::publisher::Publisher<MessageT, Alloc>>
|
||||
typename PublisherT = ::rclcpp::Publisher<MessageT, Alloc>>
|
||||
std::shared_ptr<PublisherT>
|
||||
create_publisher(
|
||||
const std::string & topic_name, size_t qos_history_depth,
|
||||
@@ -122,11 +144,12 @@ public:
|
||||
/**
|
||||
* \param[in] topic_name The topic for this publisher to publish on.
|
||||
* \param[in] qos_profile The quality of service profile to pass on to the rmw implementation.
|
||||
* \param[in] allocator Optional custom allocator.
|
||||
* \return Shared pointer to the created publisher.
|
||||
*/
|
||||
template<
|
||||
typename MessageT, typename Alloc = std::allocator<void>,
|
||||
typename PublisherT = ::rclcpp::publisher::Publisher<MessageT, Alloc>>
|
||||
typename PublisherT = ::rclcpp::Publisher<MessageT, Alloc>>
|
||||
std::shared_ptr<PublisherT>
|
||||
create_publisher(
|
||||
const std::string & topic_name,
|
||||
@@ -141,6 +164,7 @@ public:
|
||||
* \param[in] group The callback group for this subscription. NULL for no callback group.
|
||||
* \param[in] ignore_local_publications True to ignore local publications.
|
||||
* \param[in] msg_mem_strat The message memory strategy to use for allocating messages.
|
||||
* \param[in] allocator Optional custom allocator.
|
||||
* \return Shared pointer to the created subscription.
|
||||
*/
|
||||
/* TODO(jacquelinekay):
|
||||
@@ -151,7 +175,7 @@ public:
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename SubscriptionT = rclcpp::subscription::Subscription<MessageT, Alloc>>
|
||||
typename SubscriptionT = rclcpp::Subscription<MessageT, Alloc>>
|
||||
std::shared_ptr<SubscriptionT>
|
||||
create_subscription(
|
||||
const std::string & topic_name,
|
||||
@@ -171,6 +195,7 @@ public:
|
||||
* \param[in] group The callback group for this subscription. NULL for no callback group.
|
||||
* \param[in] ignore_local_publications True to ignore local publications.
|
||||
* \param[in] msg_mem_strat The message memory strategy to use for allocating messages.
|
||||
* \param[in] allocator Optional custom allocator.
|
||||
* \return Shared pointer to the created subscription.
|
||||
*/
|
||||
/* TODO(jacquelinekay):
|
||||
@@ -181,7 +206,7 @@ public:
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename SubscriptionT = rclcpp::subscription::Subscription<MessageT, Alloc>>
|
||||
typename SubscriptionT = rclcpp::Subscription<MessageT, Alloc>>
|
||||
std::shared_ptr<SubscriptionT>
|
||||
create_subscription(
|
||||
const std::string & topic_name,
|
||||
@@ -200,7 +225,7 @@ public:
|
||||
* \param[in] group Callback group to execute this timer's callback in.
|
||||
*/
|
||||
template<typename DurationT = std::milli, typename CallbackT>
|
||||
typename rclcpp::timer::WallTimer<CallbackT>::SharedPtr
|
||||
typename rclcpp::WallTimer<CallbackT>::SharedPtr
|
||||
create_wall_timer(
|
||||
std::chrono::duration<int64_t, DurationT> period,
|
||||
CallbackT callback,
|
||||
@@ -208,7 +233,7 @@ public:
|
||||
|
||||
/* Create and return a Client. */
|
||||
template<typename ServiceT>
|
||||
typename rclcpp::client::Client<ServiceT>::SharedPtr
|
||||
typename rclcpp::Client<ServiceT>::SharedPtr
|
||||
create_client(
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
|
||||
@@ -216,7 +241,7 @@ public:
|
||||
|
||||
/* Create and return a Service. */
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
typename rclcpp::service::Service<ServiceT>::SharedPtr
|
||||
typename rclcpp::Service<ServiceT>::SharedPtr
|
||||
create_service(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
@@ -231,6 +256,12 @@ public:
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
set_parameters_atomically(const std::vector<rclcpp::parameter::ParameterVariant> & parameters);
|
||||
|
||||
template<typename ParameterT>
|
||||
void
|
||||
set_parameter_if_not_set(
|
||||
const std::string & name,
|
||||
const ParameterT & value);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::parameter::ParameterVariant>
|
||||
get_parameters(const std::vector<std::string> & names) const;
|
||||
@@ -245,10 +276,36 @@ public:
|
||||
const std::string & name,
|
||||
rclcpp::parameter::ParameterVariant & parameter) const;
|
||||
|
||||
/// Assign the value of the parameter if set into the parameter argument.
|
||||
/**
|
||||
* If the parameter was not set, then the "parameter" argument is never assigned a value.
|
||||
*
|
||||
* \param[in] name The name of the parameter to get.
|
||||
* \param[out] parameter The output where the value of the parameter should be assigned.
|
||||
* \returns true if the parameter was set, false otherwise
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
bool
|
||||
get_parameter(const std::string & name, ParameterT & parameter) const;
|
||||
|
||||
/// Get the parameter value, or the "alternative value" if not set, and assign it to "value".
|
||||
/**
|
||||
* If the parameter was not set, then the "value" argument is assigned
|
||||
* the "alternative_value".
|
||||
* In all cases, the parameter remains not set after this function is called.
|
||||
*
|
||||
* \param[in] name The name of the parameter to get.
|
||||
* \param[out] value The output where the value of the parameter should be assigned.
|
||||
* \param[in] alternative_value Value to be stored in output if the parameter was not set.
|
||||
* \returns true if the parameter was set, false otherwise
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
bool
|
||||
get_parameter_or(
|
||||
const std::string & name,
|
||||
ParameterT & value,
|
||||
const ParameterT & alternative_value) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rcl_interfaces::msg::ParameterDescriptor>
|
||||
describe_parameters(const std::vector<std::string> & names) const;
|
||||
@@ -263,7 +320,8 @@ public:
|
||||
|
||||
/// Register the callback for parameter changes
|
||||
/**
|
||||
* \param[in] User defined callback function, It is expected to atomically set parameters.
|
||||
* \param[in] callback User defined callback function.
|
||||
* It is expected to atomically set parameters.
|
||||
* \note Repeated invocations of this function will overwrite previous callbacks
|
||||
*/
|
||||
template<typename CallbackT>
|
||||
@@ -271,9 +329,13 @@ public:
|
||||
register_param_change_callback(CallbackT && callback);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::map<std::string, std::string>
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_topic_names_and_types() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_service_names_and_types() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_publishers(const std::string & topic_name) const;
|
||||
@@ -288,11 +350,12 @@ public:
|
||||
* out of scope.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::event::Event::SharedPtr
|
||||
rclcpp::Event::SharedPtr
|
||||
get_graph_event();
|
||||
|
||||
/// Wait for a graph event to occur by waiting on an Event to become set.
|
||||
/* The given Event must be acquire through the get_graph_event() method.
|
||||
/**
|
||||
* The given Event must be acquire through the get_graph_event() method.
|
||||
*
|
||||
* \throws InvalidEventError if the given event is nullptr
|
||||
* \throws EventNotRegisteredError if the given event was not acquired with
|
||||
@@ -301,14 +364,27 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
wait_for_graph_change(
|
||||
rclcpp::event::Event::SharedPtr event,
|
||||
rclcpp::Event::SharedPtr event,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::Clock::SharedPtr
|
||||
get_clock();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Time
|
||||
now();
|
||||
|
||||
/// Return the Node's internal NodeBaseInterface implementation.
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
get_node_base_interface();
|
||||
|
||||
/// Return the Node's internal NodeClockInterface implementation.
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::node_interfaces::NodeClockInterface::SharedPtr
|
||||
get_node_clock_interface();
|
||||
|
||||
/// Return the Node's internal NodeGraphInterface implementation.
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr
|
||||
@@ -343,15 +419,16 @@ private:
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_;
|
||||
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_;
|
||||
rclcpp::node_interfaces::NodeTimersInterface::SharedPtr node_timers_;
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_;
|
||||
rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_;
|
||||
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters_;
|
||||
rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock_;
|
||||
|
||||
bool use_intra_process_comms_;
|
||||
};
|
||||
|
||||
} // namespace node
|
||||
} // namespace rclcpp
|
||||
|
||||
#ifndef RCLCPP__NODE_IMPL_HPP_
|
||||
|
||||
@@ -49,8 +49,6 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node
|
||||
{
|
||||
|
||||
template<typename MessageT, typename Alloc, typename PublisherT>
|
||||
std::shared_ptr<PublisherT>
|
||||
@@ -141,13 +139,13 @@ Node::create_subscription(
|
||||
}
|
||||
|
||||
template<typename DurationT, typename CallbackT>
|
||||
typename rclcpp::timer::WallTimer<CallbackT>::SharedPtr
|
||||
typename rclcpp::WallTimer<CallbackT>::SharedPtr
|
||||
Node::create_wall_timer(
|
||||
std::chrono::duration<int64_t, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
auto timer = rclcpp::timer::WallTimer<CallbackT>::make_shared(
|
||||
auto timer = rclcpp::WallTimer<CallbackT>::make_shared(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(period),
|
||||
std::move(callback));
|
||||
node_timers_->add_timer(timer, group);
|
||||
@@ -155,7 +153,7 @@ Node::create_wall_timer(
|
||||
}
|
||||
|
||||
template<typename ServiceT>
|
||||
typename client::Client<ServiceT>::SharedPtr
|
||||
typename Client<ServiceT>::SharedPtr
|
||||
Node::create_client(
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
@@ -164,8 +162,8 @@ Node::create_client(
|
||||
rcl_client_options_t options = rcl_client_get_default_options();
|
||||
options.qos = qos_profile;
|
||||
|
||||
using rclcpp::client::Client;
|
||||
using rclcpp::client::ClientBase;
|
||||
using rclcpp::Client;
|
||||
using rclcpp::ClientBase;
|
||||
|
||||
auto cli = Client<ServiceT>::make_shared(
|
||||
node_base_.get(),
|
||||
@@ -179,23 +177,23 @@ Node::create_client(
|
||||
}
|
||||
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
typename rclcpp::service::Service<ServiceT>::SharedPtr
|
||||
typename rclcpp::Service<ServiceT>::SharedPtr
|
||||
Node::create_service(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
rclcpp::service::AnyServiceCallback<ServiceT> any_service_callback;
|
||||
rclcpp::AnyServiceCallback<ServiceT> any_service_callback;
|
||||
any_service_callback.set(std::forward<CallbackT>(callback));
|
||||
|
||||
rcl_service_options_t service_options = rcl_service_get_default_options();
|
||||
service_options.qos = qos_profile;
|
||||
|
||||
auto serv = service::Service<ServiceT>::make_shared(
|
||||
auto serv = Service<ServiceT>::make_shared(
|
||||
node_base_->get_shared_rcl_node_handle(),
|
||||
service_name, any_service_callback, service_options);
|
||||
auto serv_base_ptr = std::dynamic_pointer_cast<service::ServiceBase>(serv);
|
||||
auto serv_base_ptr = std::dynamic_pointer_cast<ServiceBase>(serv);
|
||||
node_services_->add_service(serv_base_ptr, group);
|
||||
return serv;
|
||||
}
|
||||
@@ -208,17 +206,46 @@ Node::register_param_change_callback(CallbackT && callback)
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
bool
|
||||
Node::get_parameter(const std::string & name, ParameterT & parameter) const
|
||||
void
|
||||
Node::set_parameter_if_not_set(
|
||||
const std::string & name,
|
||||
const ParameterT & value)
|
||||
{
|
||||
rclcpp::parameter::ParameterVariant parameter_variant(name, parameter);
|
||||
rclcpp::parameter::ParameterVariant parameter_variant;
|
||||
if (!this->get_parameter(name, parameter_variant)) {
|
||||
this->set_parameters({
|
||||
rclcpp::parameter::ParameterVariant(name, value),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
bool
|
||||
Node::get_parameter(const std::string & name, ParameterT & value) const
|
||||
{
|
||||
rclcpp::parameter::ParameterVariant parameter_variant;
|
||||
bool result = get_parameter(name, parameter_variant);
|
||||
parameter = parameter_variant.get_value<ParameterT>();
|
||||
if (result) {
|
||||
value = parameter_variant.get_value<ParameterT>();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace node
|
||||
template<typename ParameterT>
|
||||
bool
|
||||
Node::get_parameter_or(
|
||||
const std::string & name,
|
||||
ParameterT & value,
|
||||
const ParameterT & alternative_value) const
|
||||
{
|
||||
bool got_parameter = get_parameter(name, value);
|
||||
if (!got_parameter) {
|
||||
value = alternative_value;
|
||||
}
|
||||
return got_parameter;
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_IMPL_HPP_
|
||||
|
||||
@@ -36,7 +36,10 @@ public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeBaseInterface)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
NodeBase(const std::string & node_name, rclcpp::context::Context::SharedPtr context);
|
||||
NodeBase(
|
||||
const std::string & node_name,
|
||||
const std::string & namespace_,
|
||||
rclcpp::Context::SharedPtr context);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
@@ -49,7 +52,12 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::context::Context::SharedPtr
|
||||
const char *
|
||||
get_namespace() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Context::SharedPtr
|
||||
get_context();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
@@ -110,7 +118,7 @@ public:
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeBase)
|
||||
|
||||
rclcpp::context::Context::SharedPtr context_;
|
||||
rclcpp::Context::SharedPtr context_;
|
||||
|
||||
std::shared_ptr<rcl_node_t> node_handle_;
|
||||
|
||||
|
||||
@@ -39,17 +39,24 @@ public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeBaseInterface)
|
||||
|
||||
/// Return the name of the node.
|
||||
// \return The name of the node.
|
||||
/** \return The name of the node. */
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const char *
|
||||
get_name() const = 0;
|
||||
|
||||
/// Return the context of the node.
|
||||
// \return SharedPtr to the node's context.
|
||||
/// Return the namespace of the node.
|
||||
/** \return The namespace of the node. */
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::context::Context::SharedPtr
|
||||
const char *
|
||||
get_namespace() const = 0;
|
||||
|
||||
/// Return the context of the node.
|
||||
/** \return SharedPtr to the node's context. */
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Context::SharedPtr
|
||||
get_context() = 0;
|
||||
|
||||
/// Return the rcl_node_t node handle (non-const version).
|
||||
@@ -65,7 +72,8 @@ public:
|
||||
get_rcl_node_handle() const = 0;
|
||||
|
||||
/// Return the rcl_node_t node handle in a std::shared_ptr.
|
||||
/* This handle remains valid after the Node is destroyed.
|
||||
/**
|
||||
* This handle remains valid after the Node is destroyed.
|
||||
* The actual rcl node is not finalized until it is out of scope everywhere.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
@@ -74,7 +82,8 @@ public:
|
||||
get_shared_rcl_node_handle() = 0;
|
||||
|
||||
/// Return the rcl_node_t node handle in a std::shared_ptr.
|
||||
/* This handle remains valid after the Node is destroyed.
|
||||
/**
|
||||
* This handle remains valid after the Node is destroyed.
|
||||
* The actual rcl node is not finalized until it is out of scope everywhere.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
@@ -113,7 +122,8 @@ public:
|
||||
get_associated_with_executor_atomic() = 0;
|
||||
|
||||
/// Return guard condition that should be notified when the internal node state changes.
|
||||
/* For example, this should be notified when a publisher is added or removed.
|
||||
/**
|
||||
* For example, this should be notified when a publisher is added or removed.
|
||||
*
|
||||
* \return the rcl_guard_condition_t if it is valid, else nullptr
|
||||
*/
|
||||
@@ -123,7 +133,7 @@ public:
|
||||
get_notify_guard_condition() = 0;
|
||||
|
||||
/// Acquire and return a scoped lock that protects the notify guard condition.
|
||||
/* This should be used when triggering the notify guard condition. */
|
||||
/** This should be used when triggering the notify guard condition. */
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::unique_lock<std::recursive_mutex>
|
||||
|
||||
71
rclcpp/include/rclcpp/node_interfaces/node_clock.hpp
Normal file
71
rclcpp/include/rclcpp/node_interfaces/node_clock.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_CLOCK_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_CLOCK_HPP_
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_clock_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
#include "rclcpp/time_source.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
/// Implementation of the NodeClock part of the Node API.
|
||||
class NodeClock : public NodeClockInterface
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeClock)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit NodeClock(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
|
||||
rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
~NodeClock();
|
||||
|
||||
/// Get a clock which will be kept up to date by the node.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Clock::SharedPtr
|
||||
get_clock();
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeClock)
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_;
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_;
|
||||
rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_;
|
||||
|
||||
rclcpp::Clock::SharedPtr ros_clock_;
|
||||
rclcpp::TimeSource time_source_;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__NODE_CLOCK_HPP_
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_CLOCK_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_CLOCK_INTERFACE_HPP_
|
||||
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
/// Pure virtual interface class for the NodeClock part of the Node API.
|
||||
class NodeClockInterface
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeClockInterface)
|
||||
|
||||
/// Get a ROS clock which will be kept up to date by the node.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Clock::SharedPtr
|
||||
get_clock() = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__NODE_CLOCK_INTERFACE_HPP_
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2016 Open Source Robotics Foundation, Inc.
|
||||
// Copyright 2016-2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -56,8 +56,18 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::map<std::string, std::string>
|
||||
get_topic_names_and_types() const;
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_topic_names_and_types(bool no_demangle = false) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_service_names_and_types() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::vector<std::string>
|
||||
get_node_names() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
@@ -86,14 +96,14 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::event::Event::SharedPtr
|
||||
rclcpp::Event::SharedPtr
|
||||
get_graph_event();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
wait_for_graph_change(
|
||||
rclcpp::event::Event::SharedPtr event,
|
||||
rclcpp::Event::SharedPtr event,
|
||||
std::chrono::nanoseconds timeout);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
@@ -117,9 +127,9 @@ private:
|
||||
/// For notifying waiting threads (wait_for_graph_change()) on changes (notify_graph_change()).
|
||||
std::condition_variable graph_cv_;
|
||||
/// Weak references to graph events out on loan.
|
||||
std::vector<rclcpp::event::Event::WeakPtr> graph_events_;
|
||||
std::vector<rclcpp::Event::WeakPtr> graph_events_;
|
||||
/// Number of graph events out on loan, used to determine if the graph should be monitored.
|
||||
/* graph_users_count_ is atomic so that it can be accessed without acquiring the graph_mutex_ */
|
||||
/** graph_users_count_ is atomic so that it can be accessed without acquiring the graph_mutex_ */
|
||||
std::atomic_size_t graph_users_count_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2016 Open Source Robotics Foundation, Inc.
|
||||
// Copyright 2016-2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/guard_condition.h"
|
||||
|
||||
@@ -36,14 +37,34 @@ class NodeGraphInterface
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeGraphInterface)
|
||||
|
||||
/// Return a map of existing topic names (string) to topic types (string).
|
||||
/* A topic is considered to exist when at least one publisher or subscriber
|
||||
/// Return a map of existing topic names to list of topic types.
|
||||
/**
|
||||
* A topic is considered to exist when at least one publisher or subscriber
|
||||
* exists for it, whether they be local or remote to this process.
|
||||
*
|
||||
* \param[in] no_demangle if true, topic names and types are not demangled
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::map<std::string, std::string>
|
||||
get_topic_names_and_types() const = 0;
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_topic_names_and_types(bool no_demangle = false) const = 0;
|
||||
|
||||
/// Return a map of existing service names to list of service types.
|
||||
/**
|
||||
* A service is considered to exist when at least one service server or
|
||||
* service client exists for it, whether they be local or remote to this
|
||||
* process.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
get_service_names_and_types() const = 0;
|
||||
|
||||
/// Return a vector of existing node names (string).
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::vector<std::string>
|
||||
get_node_names() const = 0;
|
||||
|
||||
/// Return the number of publishers that are advertised on a given topic.
|
||||
RCLCPP_PUBLIC
|
||||
@@ -64,7 +85,8 @@ public:
|
||||
get_graph_guard_condition() const = 0;
|
||||
|
||||
/// Notify threads waiting on graph changes.
|
||||
/* Affects threads waiting on the notify guard condition, see:
|
||||
/**
|
||||
* Affects threads waiting on the notify guard condition, see:
|
||||
* get_notify_guard_condition(), as well as the threads waiting on graph
|
||||
* changes using a graph Event, see: wait_for_graph_change().
|
||||
*
|
||||
@@ -84,17 +106,19 @@ public:
|
||||
notify_shutdown() = 0;
|
||||
|
||||
/// Return a graph event, which will be set anytime a graph change occurs.
|
||||
/* The graph Event object is a loan which must be returned.
|
||||
/**
|
||||
* The graph Event object is a loan which must be returned.
|
||||
* The Event object is scoped and therefore to return the load just let it go
|
||||
* out of scope.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::event::Event::SharedPtr
|
||||
rclcpp::Event::SharedPtr
|
||||
get_graph_event() = 0;
|
||||
|
||||
/// Wait for a graph event to occur by waiting on an Event to become set.
|
||||
/* The given Event must be acquire through the get_graph_event() method.
|
||||
/**
|
||||
* The given Event must be acquire through the get_graph_event() method.
|
||||
*
|
||||
* \throws InvalidEventError if the given event is nullptr
|
||||
* \throws EventNotRegisteredError if the given event was not acquired with
|
||||
@@ -104,11 +128,12 @@ public:
|
||||
virtual
|
||||
void
|
||||
wait_for_graph_change(
|
||||
rclcpp::event::Event::SharedPtr event,
|
||||
rclcpp::Event::SharedPtr event,
|
||||
std::chrono::nanoseconds timeout) = 0;
|
||||
|
||||
/// Return the number of on loan graph events, see get_graph_event().
|
||||
/* This is typically only used by the rclcpp::graph_listener::GraphListener.
|
||||
/**
|
||||
* This is typically only used by the rclcpp::graph_listener::GraphListener.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
|
||||
61
rclcpp/include/rclcpp/node_interfaces/node_logging.hpp
Normal file
61
rclcpp/include/rclcpp/node_interfaces/node_logging.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_LOGGING_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_LOGGING_HPP_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
/// Implementation of the NodeLogging part of the Node API.
|
||||
class NodeLogging : public NodeLoggingInterface
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeLoggingInterface)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit NodeLogging(rclcpp::node_interfaces::NodeBaseInterface * node_base);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
~NodeLogging();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Logger
|
||||
get_logger() const;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeLogging)
|
||||
|
||||
/// Handle to the NodeBaseInterface given in the constructor.
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
|
||||
|
||||
rclcpp::Logger logger_;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__NODE_LOGGING_HPP_
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_LOGGING_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_LOGGING_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
/// Pure virtual interface class for the NodeLogging part of the Node API.
|
||||
class NodeLoggingInterface
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeLoggingInterface)
|
||||
|
||||
/// Return the logger of the node.
|
||||
/** \return The logger of the node. */
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Logger
|
||||
get_logger() const = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__NODE_LOGGING_INTERFACE_HPP_
|
||||
@@ -113,7 +113,7 @@ private:
|
||||
|
||||
std::map<std::string, rclcpp::parameter::ParameterVariant> parameters_;
|
||||
|
||||
publisher::Publisher<rcl_interfaces::msg::ParameterEvent>::SharedPtr events_publisher_;
|
||||
Publisher<rcl_interfaces::msg::ParameterEvent>::SharedPtr events_publisher_;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -81,8 +81,8 @@ public:
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const = 0;
|
||||
|
||||
using ParametersCallbackFunction =
|
||||
std::function<rcl_interfaces::msg::SetParametersResult(
|
||||
using ParametersCallbackFunction = std::function<
|
||||
rcl_interfaces::msg::SetParametersResult(
|
||||
const std::vector<rclcpp::parameter::ParameterVariant> &)>;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
@@ -45,14 +45,14 @@ public:
|
||||
virtual
|
||||
void
|
||||
add_client(
|
||||
rclcpp::client::ClientBase::SharedPtr client_base_ptr,
|
||||
rclcpp::ClientBase::SharedPtr client_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
add_service(
|
||||
rclcpp::service::ServiceBase::SharedPtr service_base_ptr,
|
||||
rclcpp::ServiceBase::SharedPtr service_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group);
|
||||
|
||||
private:
|
||||
|
||||
@@ -36,14 +36,14 @@ public:
|
||||
virtual
|
||||
void
|
||||
add_client(
|
||||
rclcpp::client::ClientBase::SharedPtr client_base_ptr,
|
||||
rclcpp::ClientBase::SharedPtr client_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
add_service(
|
||||
rclcpp::service::ServiceBase::SharedPtr service_base_ptr,
|
||||
rclcpp::ServiceBase::SharedPtr service_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
virtual
|
||||
void
|
||||
add_timer(
|
||||
rclcpp::timer::TimerBase::SharedPtr timer,
|
||||
rclcpp::TimerBase::SharedPtr timer,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group);
|
||||
|
||||
private:
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
virtual
|
||||
void
|
||||
add_timer(
|
||||
rclcpp::timer::TimerBase::SharedPtr timer,
|
||||
rclcpp::TimerBase::SharedPtr timer,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::publisher::PublisherBase::SharedPtr
|
||||
rclcpp::PublisherBase::SharedPtr
|
||||
create_publisher(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::PublisherFactory & publisher_factory,
|
||||
@@ -58,11 +58,11 @@ public:
|
||||
virtual
|
||||
void
|
||||
add_publisher(
|
||||
rclcpp::publisher::PublisherBase::SharedPtr publisher);
|
||||
rclcpp::PublisherBase::SharedPtr publisher);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr
|
||||
rclcpp::SubscriptionBase::SharedPtr
|
||||
create_subscription(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::SubscriptionFactory & subscription_factory,
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
virtual
|
||||
void
|
||||
add_subscription(
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group);
|
||||
|
||||
private:
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::publisher::PublisherBase::SharedPtr
|
||||
rclcpp::PublisherBase::SharedPtr
|
||||
create_publisher(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::PublisherFactory & publisher_factory,
|
||||
@@ -53,11 +53,11 @@ public:
|
||||
virtual
|
||||
void
|
||||
add_publisher(
|
||||
rclcpp::publisher::PublisherBase::SharedPtr publisher) = 0;
|
||||
rclcpp::PublisherBase::SharedPtr publisher) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr
|
||||
rclcpp::SubscriptionBase::SharedPtr
|
||||
create_subscription(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::SubscriptionFactory & subscription_factory,
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
virtual
|
||||
void
|
||||
add_subscription(
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
/* Return a json encoded version of the parameter intended for a dict. */
|
||||
/// Return a json encoded version of the parameter intended for a dict.
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
_to_json_dict_entry(const ParameterVariant & param);
|
||||
@@ -235,12 +235,12 @@ operator<<(std::ostream & os, const std::vector<ParameterVariant> & parameters);
|
||||
namespace std
|
||||
{
|
||||
|
||||
/* Return a json encoded version of the parameter intended for a list. */
|
||||
/// Return a json encoded version of the parameter intended for a list.
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
to_string(const rclcpp::parameter::ParameterVariant & param);
|
||||
|
||||
/* Return a json encoded version of a vector of parameters, as a string*/
|
||||
/// Return a json encoded version of a vector of parameters, as a string.
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
to_string(const std::vector<rclcpp::parameter::ParameterVariant> & parameters);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#ifndef RCLCPP__PARAMETER_CLIENT_HPP_
|
||||
#define RCLCPP__PARAMETER_CLIENT_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -29,6 +30,7 @@
|
||||
#include "rcl_interfaces/srv/set_parameters.hpp"
|
||||
#include "rcl_interfaces/srv/set_parameters_atomically.hpp"
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rclcpp/create_subscription.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
@@ -38,8 +40,6 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace parameter_client
|
||||
{
|
||||
|
||||
class AsyncParametersClient
|
||||
{
|
||||
@@ -48,7 +48,22 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
AsyncParametersClient(
|
||||
const rclcpp::node::Node::SharedPtr node,
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
|
||||
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
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_PUBLIC
|
||||
AsyncParametersClient(
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
@@ -93,24 +108,60 @@ public:
|
||||
void(std::shared_future<rcl_interfaces::msg::ListParametersResult>)
|
||||
> callback = nullptr);
|
||||
|
||||
template<typename CallbackT>
|
||||
typename rclcpp::subscription::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename Alloc = std::allocator<void>,
|
||||
typename SubscriptionT =
|
||||
rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent, Alloc>>
|
||||
typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
|
||||
on_parameter_event(CallbackT && callback)
|
||||
{
|
||||
return node_->create_subscription<rcl_interfaces::msg::ParameterEvent>(
|
||||
"parameter_events", std::forward<CallbackT>(callback), rmw_qos_profile_parameter_events);
|
||||
using rclcpp::message_memory_strategy::MessageMemoryStrategy;
|
||||
auto msg_mem_strat =
|
||||
MessageMemoryStrategy<rcl_interfaces::msg::ParameterEvent, Alloc>::create_default();
|
||||
|
||||
return rclcpp::create_subscription<
|
||||
rcl_interfaces::msg::ParameterEvent, CallbackT, Alloc, SubscriptionT>(
|
||||
this->node_topics_interface_.get(),
|
||||
"parameter_events",
|
||||
std::forward<CallbackT>(callback),
|
||||
rmw_qos_profile_default,
|
||||
nullptr, // group,
|
||||
false, // ignore_local_publications,
|
||||
false, // use_intra_process_comms_,
|
||||
msg_mem_strat,
|
||||
std::make_shared<Alloc>());
|
||||
}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
service_is_ready() const;
|
||||
|
||||
template<typename RatioT = std::milli>
|
||||
bool
|
||||
wait_for_service(
|
||||
std::chrono::duration<int64_t, RatioT> timeout = std::chrono::duration<int64_t, RatioT>(-1))
|
||||
{
|
||||
return wait_for_service_nanoseconds(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
|
||||
);
|
||||
}
|
||||
|
||||
protected:
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
wait_for_service_nanoseconds(std::chrono::nanoseconds timeout);
|
||||
|
||||
private:
|
||||
const rclcpp::node::Node::SharedPtr node_;
|
||||
rclcpp::client::Client<rcl_interfaces::srv::GetParameters>::SharedPtr get_parameters_client_;
|
||||
rclcpp::client::Client<rcl_interfaces::srv::GetParameterTypes>::SharedPtr
|
||||
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface_;
|
||||
rclcpp::Client<rcl_interfaces::srv::GetParameters>::SharedPtr get_parameters_client_;
|
||||
rclcpp::Client<rcl_interfaces::srv::GetParameterTypes>::SharedPtr
|
||||
get_parameter_types_client_;
|
||||
rclcpp::client::Client<rcl_interfaces::srv::SetParameters>::SharedPtr set_parameters_client_;
|
||||
rclcpp::client::Client<rcl_interfaces::srv::SetParametersAtomically>::SharedPtr
|
||||
rclcpp::Client<rcl_interfaces::srv::SetParameters>::SharedPtr set_parameters_client_;
|
||||
rclcpp::Client<rcl_interfaces::srv::SetParametersAtomically>::SharedPtr
|
||||
set_parameters_atomically_client_;
|
||||
rclcpp::client::Client<rcl_interfaces::srv::ListParameters>::SharedPtr list_parameters_client_;
|
||||
rclcpp::client::Client<rcl_interfaces::srv::DescribeParameters>::SharedPtr
|
||||
rclcpp::Client<rcl_interfaces::srv::ListParameters>::SharedPtr list_parameters_client_;
|
||||
rclcpp::Client<rcl_interfaces::srv::DescribeParameters>::SharedPtr
|
||||
describe_parameters_client_;
|
||||
std::string remote_node_name_;
|
||||
};
|
||||
@@ -122,13 +173,15 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit SyncParametersClient(
|
||||
rclcpp::node::Node::SharedPtr node,
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
rclcpp::node::Node::SharedPtr node,
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
@@ -158,20 +211,18 @@ public:
|
||||
T
|
||||
get_parameter(const std::string & parameter_name, const T & default_value)
|
||||
{
|
||||
// *INDENT-OFF*
|
||||
return get_parameter_impl(parameter_name,
|
||||
std::function<T()>([&default_value]() -> T {return default_value; }));
|
||||
// *INDENT-ON*
|
||||
return get_parameter_impl(
|
||||
parameter_name,
|
||||
std::function<T()>([&default_value]() -> T {return default_value;}));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T
|
||||
get_parameter(const std::string & parameter_name)
|
||||
{
|
||||
// *INDENT-OFF*
|
||||
return get_parameter_impl(parameter_name,
|
||||
std::function<T()>([]() -> T {throw std::runtime_error("Parameter not set"); }));
|
||||
// *INDENT-ON*
|
||||
return get_parameter_impl(
|
||||
parameter_name,
|
||||
std::function<T()>([]() -> T {throw std::runtime_error("Parameter not set");}));
|
||||
}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
@@ -193,19 +244,33 @@ public:
|
||||
uint64_t depth);
|
||||
|
||||
template<typename CallbackT>
|
||||
typename rclcpp::subscription::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
|
||||
typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
|
||||
on_parameter_event(CallbackT && callback)
|
||||
{
|
||||
return async_parameters_client_->on_parameter_event(std::forward<CallbackT>(callback));
|
||||
}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
service_is_ready() const
|
||||
{
|
||||
return async_parameters_client_->service_is_ready();
|
||||
}
|
||||
|
||||
template<typename RatioT = std::milli>
|
||||
bool
|
||||
wait_for_service(
|
||||
std::chrono::duration<int64_t, RatioT> timeout = std::chrono::duration<int64_t, RatioT>(-1))
|
||||
{
|
||||
return async_parameters_client_->wait_for_service(timeout);
|
||||
}
|
||||
|
||||
private:
|
||||
rclcpp::executor::Executor::SharedPtr executor_;
|
||||
rclcpp::node::Node::SharedPtr node_;
|
||||
rclcpp::Node::SharedPtr node_;
|
||||
AsyncParametersClient::SharedPtr async_parameters_client_;
|
||||
};
|
||||
|
||||
} // namespace parameter_client
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__PARAMETER_CLIENT_HPP_
|
||||
|
||||
78
rclcpp/include/rclcpp/parameter_events_filter.hpp
Normal file
78
rclcpp/include/rclcpp/parameter_events_filter.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__PARAMETER_EVENTS_FILTER_HPP_
|
||||
#define RCLCPP__PARAMETER_EVENTS_FILTER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl_interfaces/msg/parameter.hpp"
|
||||
#include "rcl_interfaces/msg/parameter_event.hpp"
|
||||
#include "rcl_interfaces/msg/parameter_value.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rmw/rmw.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
class ParameterEventsFilter
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(ParameterEventsFilter)
|
||||
enum class EventType {NEW, DELETED, CHANGED}; ///< An enum for the type of event.
|
||||
/// Used for the listed results
|
||||
using EventPair = std::pair<EventType, rcl_interfaces::msg::Parameter *>;
|
||||
|
||||
/// Construct a filtered view of a parameter event.
|
||||
/**
|
||||
* \param[in] event The parameter event message to filter.
|
||||
* \param[in] names A list of parameter names of interest.
|
||||
* \param[in] types A list of the types of parameter events of iterest.
|
||||
* EventType NEW, DELETED, or CHANGED
|
||||
*
|
||||
* Example Usage:
|
||||
* If you have recieved a parameter event and are only interested in parameters foo and
|
||||
* bar being added or changed but don't care about deletion.
|
||||
* auto res = rclcpp::ParameterEventsFilter(
|
||||
* event_shared_ptr,
|
||||
* {"foo", "bar"},
|
||||
* {rclcpp::ParameterEventsFilter::EventType::NEW, rclcpp::ParameterEventsFilter::EventType::CHANGED});
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
ParameterEventsFilter(
|
||||
rcl_interfaces::msg::ParameterEvent::SharedPtr event,
|
||||
const std::vector<std::string> & names,
|
||||
const std::vector<EventType> & types);
|
||||
|
||||
/// Get the result of the filter
|
||||
/**
|
||||
* \return A std::vector<EventPair> of all matching parameter changes in this event.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<EventPair> & get_events() const;
|
||||
|
||||
private:
|
||||
// access only allowed via const accessor.
|
||||
std::vector<EventPair> result_; ///< Storage of the resultant vector
|
||||
rcl_interfaces::msg::ParameterEvent::SharedPtr event_; ///< Keep event in scope
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__PARAMETER_EVENTS_FILTER_HPP_
|
||||
@@ -32,8 +32,6 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace parameter_service
|
||||
{
|
||||
|
||||
class ParameterService
|
||||
{
|
||||
@@ -42,23 +40,22 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit ParameterService(
|
||||
const rclcpp::node::Node::SharedPtr node,
|
||||
const rclcpp::Node::SharedPtr node,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
private:
|
||||
const rclcpp::node::Node::SharedPtr node_;
|
||||
rclcpp::service::Service<rcl_interfaces::srv::GetParameters>::SharedPtr get_parameters_service_;
|
||||
rclcpp::service::Service<rcl_interfaces::srv::GetParameterTypes>::SharedPtr
|
||||
const rclcpp::Node::SharedPtr node_;
|
||||
rclcpp::Service<rcl_interfaces::srv::GetParameters>::SharedPtr get_parameters_service_;
|
||||
rclcpp::Service<rcl_interfaces::srv::GetParameterTypes>::SharedPtr
|
||||
get_parameter_types_service_;
|
||||
rclcpp::service::Service<rcl_interfaces::srv::SetParameters>::SharedPtr set_parameters_service_;
|
||||
rclcpp::service::Service<rcl_interfaces::srv::SetParametersAtomically>::SharedPtr
|
||||
rclcpp::Service<rcl_interfaces::srv::SetParameters>::SharedPtr set_parameters_service_;
|
||||
rclcpp::Service<rcl_interfaces::srv::SetParametersAtomically>::SharedPtr
|
||||
set_parameters_atomically_service_;
|
||||
rclcpp::service::Service<rcl_interfaces::srv::DescribeParameters>::SharedPtr
|
||||
rclcpp::Service<rcl_interfaces::srv::DescribeParameters>::SharedPtr
|
||||
describe_parameters_service_;
|
||||
rclcpp::service::Service<rcl_interfaces::srv::ListParameters>::SharedPtr list_parameters_service_;
|
||||
rclcpp::Service<rcl_interfaces::srv::ListParameters>::SharedPtr list_parameters_service_;
|
||||
};
|
||||
|
||||
} // namespace parameter_service
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__PARAMETER_SERVICE_HPP_
|
||||
|
||||
@@ -45,12 +45,9 @@ namespace node_interfaces
|
||||
class NodeTopicsInterface;
|
||||
}
|
||||
|
||||
namespace publisher
|
||||
{
|
||||
|
||||
class PublisherBase
|
||||
{
|
||||
friend rclcpp::node_interfaces::NodeTopicsInterface;
|
||||
friend ::rclcpp::node_interfaces::NodeTopicsInterface;
|
||||
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(PublisherBase)
|
||||
@@ -75,29 +72,41 @@ public:
|
||||
virtual ~PublisherBase();
|
||||
|
||||
/// Get the topic that this publisher publishes on.
|
||||
// \return The topic name.
|
||||
/** \return The topic name. */
|
||||
RCLCPP_PUBLIC
|
||||
const char *
|
||||
get_topic_name() const;
|
||||
|
||||
/// Get the queue size for this publisher.
|
||||
// \return The queue size.
|
||||
/** \return The queue size. */
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
get_queue_size() const;
|
||||
|
||||
/// Get the global identifier for this publisher (used in rmw and by DDS).
|
||||
// \return The gid.
|
||||
/** \return The gid. */
|
||||
RCLCPP_PUBLIC
|
||||
const rmw_gid_t &
|
||||
get_gid() const;
|
||||
|
||||
/// Get the global identifier for this publisher used by intra-process communication.
|
||||
// \return The intra-process gid.
|
||||
/** \return The intra-process gid. */
|
||||
RCLCPP_PUBLIC
|
||||
const rmw_gid_t &
|
||||
get_intra_process_gid() const;
|
||||
|
||||
/// Get the rcl publisher handle.
|
||||
/** \return The rcl publisher handle. */
|
||||
RCLCPP_PUBLIC
|
||||
rcl_publisher_t *
|
||||
get_publisher_handle();
|
||||
|
||||
/// Get the rcl publisher handle.
|
||||
/** \return The rcl publisher handle. */
|
||||
RCLCPP_PUBLIC
|
||||
const rcl_publisher_t *
|
||||
get_publisher_handle() const;
|
||||
|
||||
/// Compare this publisher to a gid.
|
||||
/**
|
||||
* Note that this function calls the next function.
|
||||
@@ -261,6 +270,15 @@ public:
|
||||
return this->publish(unique_msg);
|
||||
}
|
||||
|
||||
virtual void
|
||||
publish(const MessageT * msg)
|
||||
{
|
||||
if (!msg) {
|
||||
throw std::runtime_error("msg argument is nullptr");
|
||||
}
|
||||
return this->publish(*msg);
|
||||
}
|
||||
|
||||
std::shared_ptr<MessageAlloc> get_allocator() const
|
||||
{
|
||||
return message_allocator_;
|
||||
@@ -284,8 +302,6 @@ protected:
|
||||
MessageDeleter message_deleter_;
|
||||
};
|
||||
|
||||
} // namespace publisher
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__PUBLISHER_HPP_
|
||||
|
||||
@@ -32,7 +32,8 @@ namespace rclcpp
|
||||
{
|
||||
|
||||
/// Factory with functions used to create a MessageT specific PublisherT.
|
||||
/* This factory class is used to encapsulate the template generated functions
|
||||
/**
|
||||
* This factory class is used to encapsulate the template generated functions
|
||||
* which are used during the creation of a Message type specific publisher
|
||||
* within a non-templated class.
|
||||
*
|
||||
@@ -45,7 +46,7 @@ struct PublisherFactory
|
||||
{
|
||||
// Creates a PublisherT<MessageT, ...> publisher object and returns it as a PublisherBase.
|
||||
using PublisherFactoryFunction = std::function<
|
||||
rclcpp::publisher::PublisherBase::SharedPtr(
|
||||
rclcpp::PublisherBase::SharedPtr(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
const std::string & topic_name,
|
||||
rcl_publisher_options_t & publisher_options)>;
|
||||
@@ -57,7 +58,7 @@ struct PublisherFactory
|
||||
using AddPublisherToIntraProcessManagerFunction = std::function<
|
||||
uint64_t(
|
||||
rclcpp::intra_process_manager::IntraProcessManager * ipm,
|
||||
rclcpp::publisher::PublisherBase::SharedPtr publisher)>;
|
||||
rclcpp::PublisherBase::SharedPtr publisher)>;
|
||||
|
||||
AddPublisherToIntraProcessManagerFunction add_publisher_to_intra_process_manager;
|
||||
|
||||
@@ -65,7 +66,7 @@ struct PublisherFactory
|
||||
// PublisherT::publish() and which handles the intra process transmission of
|
||||
// the message being published.
|
||||
using SharedPublishCallbackFactoryFunction = std::function<
|
||||
rclcpp::publisher::PublisherBase::StoreMessageCallbackT(
|
||||
rclcpp::PublisherBase::StoreMessageCallbackT(
|
||||
rclcpp::intra_process_manager::IntraProcessManager::SharedPtr ipm)>;
|
||||
|
||||
SharedPublishCallbackFactoryFunction create_shared_publish_callback;
|
||||
@@ -95,13 +96,13 @@ create_publisher_factory(std::shared_ptr<Alloc> allocator)
|
||||
factory.add_publisher_to_intra_process_manager =
|
||||
[](
|
||||
rclcpp::intra_process_manager::IntraProcessManager * ipm,
|
||||
rclcpp::publisher::PublisherBase::SharedPtr publisher) -> uint64_t
|
||||
rclcpp::PublisherBase::SharedPtr publisher) -> uint64_t
|
||||
{
|
||||
return ipm->add_publisher<MessageT, Alloc>(std::dynamic_pointer_cast<PublisherT>(publisher));
|
||||
};
|
||||
|
||||
// function to create a shared publish callback std::function
|
||||
using StoreMessageCallbackT = rclcpp::publisher::PublisherBase::StoreMessageCallbackT;
|
||||
using StoreMessageCallbackT = rclcpp::PublisherBase::StoreMessageCallbackT;
|
||||
factory.create_shared_publish_callback =
|
||||
[](rclcpp::intra_process_manager::IntraProcessManager::SharedPtr ipm) -> StoreMessageCallbackT
|
||||
{
|
||||
@@ -128,7 +129,7 @@ create_publisher_factory(std::shared_ptr<Alloc> allocator)
|
||||
"' is incompatible from the publisher type '" + message_type_info.name() + "'");
|
||||
}
|
||||
MessageT * typed_message_ptr = static_cast<MessageT *>(msg);
|
||||
using MessageDeleter = typename publisher::Publisher<MessageT, Alloc>::MessageDeleter;
|
||||
using MessageDeleter = typename Publisher<MessageT, Alloc>::MessageDeleter;
|
||||
std::unique_ptr<MessageT, MessageDeleter> unique_msg(typed_message_ptr);
|
||||
uint64_t message_seq =
|
||||
ipm->store_intra_process_message<MessageT, Alloc>(publisher_id, unique_msg);
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace rate
|
||||
{
|
||||
|
||||
class RateBase
|
||||
{
|
||||
@@ -84,7 +82,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
// Sleep (will get interrupted by ctrl-c, may not sleep full time)
|
||||
rclcpp::utilities::sleep_for(time_to_sleep);
|
||||
rclcpp::sleep_for(time_to_sleep);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -116,7 +114,6 @@ private:
|
||||
using Rate = GenericRate<std::chrono::system_clock>;
|
||||
using WallRate = GenericRate<std::chrono::steady_clock>;
|
||||
|
||||
} // namespace rate
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__RATE_HPP_
|
||||
|
||||
@@ -12,6 +12,127 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/** \mainpage rclcpp: ROS Client Library for C++
|
||||
*
|
||||
* `rclcpp` provides the canonical C++ API for interacting with ROS.
|
||||
* It consists of these main components:
|
||||
*
|
||||
* - Node
|
||||
* - rclcpp::Node
|
||||
* - rclcpp/node.hpp
|
||||
* - Publisher
|
||||
* - rclcpp::Node::create_publisher()
|
||||
* - rclcpp::Publisher
|
||||
* - rclcpp::Publisher::publish()
|
||||
* - rclcpp/publisher.hpp
|
||||
* - Subscription
|
||||
* - rclcpp::Node::create_subscription()
|
||||
* - rclcpp::Subscription
|
||||
* - rclcpp/subscription.hpp
|
||||
* - Service Client
|
||||
* - rclcpp::Node::create_client()
|
||||
* - rclcpp::Client
|
||||
* - rclcpp/client.hpp
|
||||
* - Service Server
|
||||
* - rclcpp::Node::create_service()
|
||||
* - rclcpp::Service
|
||||
* - rclcpp/service.hpp
|
||||
* - Timer
|
||||
* - rclcpp::Node::create_wall_timer()
|
||||
* - rclcpp::WallTimer
|
||||
* - rclcpp::TimerBase
|
||||
* - rclcpp/timer.hpp
|
||||
* - Parameters:
|
||||
* - rclcpp::Node::set_parameters()
|
||||
* - rclcpp::Node::get_parameters()
|
||||
* - rclcpp::Node::get_parameter()
|
||||
* - rclcpp::Node::describe_parameters()
|
||||
* - rclcpp::Node::list_parameters()
|
||||
* - rclcpp::Node::register_param_change_callback()
|
||||
* - rclcpp::parameter::ParameterVariant
|
||||
* - rclcpp::AsyncParametersClient
|
||||
* - rclcpp::SyncParametersClient
|
||||
* - rclcpp/parameter.hpp
|
||||
* - rclcpp/parameter_client.hpp
|
||||
* - rclcpp/parameter_service.hpp
|
||||
* - Rate:
|
||||
* - rclcpp::Rate
|
||||
* - rclcpp::WallRate
|
||||
* - rclcpp/rate.hpp
|
||||
*
|
||||
* There are also some components which help control the execution of callbacks:
|
||||
*
|
||||
* - Executors (responsible for execution of callbacks through a blocking spin):
|
||||
* - rclcpp::spin()
|
||||
* - rclcpp::spin_some()
|
||||
* - rclcpp::spin_until_future_complete()
|
||||
* - rclcpp::executors::SingleThreadedExecutor
|
||||
* - rclcpp::executors::SingleThreadedExecutor::add_node()
|
||||
* - rclcpp::executors::SingleThreadedExecutor::spin()
|
||||
* - rclcpp::executors::MultiThreadedExecutor
|
||||
* - rclcpp::executors::MultiThreadedExecutor::add_node()
|
||||
* - rclcpp::executors::MultiThreadedExecutor::spin()
|
||||
* - rclcpp/executor.hpp
|
||||
* - rclcpp/executors.hpp
|
||||
* - rclcpp/executors/single_threaded_executor.hpp
|
||||
* - rclcpp/executors/multi_threaded_executor.hpp
|
||||
* - CallbackGroups (mechanism for enforcing concurrency rules for callbacks):
|
||||
* - rclcpp::Node::create_callback_group()
|
||||
* - rclcpp::callback_group::CallbackGroup
|
||||
* - rclcpp/callback_group.hpp
|
||||
*
|
||||
* Additionally, there are some methods for introspecting the ROS graph:
|
||||
*
|
||||
* - Graph Events (a waitable event object that wakes up when the graph changes):
|
||||
* - rclcpp::Node::get_graph_event()
|
||||
* - rclcpp::Node::wait_for_graph_change()
|
||||
* - rclcpp::Event
|
||||
* - List topic names and types:
|
||||
* - rclcpp::Node::get_topic_names_and_types()
|
||||
* - Get the number of publishers or subscribers on a topic:
|
||||
* - rclcpp::Node::count_publishers()
|
||||
* - rclcpp::Node::count_subscribers()
|
||||
*
|
||||
* And components related to logging:
|
||||
*
|
||||
* - Logging macros:
|
||||
* - Some examples (not exhaustive):
|
||||
* - RCLCPP_DEBUG()
|
||||
* - RCLCPP_INFO()
|
||||
* - RCLCPP_WARN_ONCE()
|
||||
* - RCLCPP_ERROR_SKIPFIRST()
|
||||
* - rclcpp/logging.hpp
|
||||
* - Logger:
|
||||
* - rclcpp::Logger
|
||||
* - rclcpp/logger.hpp
|
||||
* - rclcpp::Node::get_logger()
|
||||
*
|
||||
* Finally, there are many internal API's and utilities:
|
||||
*
|
||||
* - Exceptions:
|
||||
* - rclcpp/exceptions.hpp
|
||||
* - Allocator related items:
|
||||
* - rclcpp/allocator/allocator_common.hpp
|
||||
* - rclcpp/allocator/allocator_deleter.hpp
|
||||
* - Memory management tools:
|
||||
* - rclcpp/memory_strategies.hpp
|
||||
* - rclcpp/memory_strategy.hpp
|
||||
* - rclcpp/message_memory_strategy.hpp
|
||||
* - rclcpp/strategies/allocator_memory_strategy.hpp
|
||||
* - rclcpp/strategies/message_pool_memory_strategy.hpp
|
||||
* - Context object which is shared amongst multiple Nodes:
|
||||
* - rclcpp::Context
|
||||
* - rclcpp/context.hpp
|
||||
* - rclcpp/contexts/default_context.hpp
|
||||
* - Various utilities:
|
||||
* - rclcpp/function_traits.hpp
|
||||
* - rclcpp/macros.hpp
|
||||
* - rclcpp/scope_exit.hpp
|
||||
* - rclcpp/time.hpp
|
||||
* - rclcpp/utilities.hpp
|
||||
* - rclcpp/visibility_control.hpp
|
||||
*/
|
||||
|
||||
#ifndef RCLCPP__RCLCPP_HPP_
|
||||
#define RCLCPP__RCLCPP_HPP_
|
||||
|
||||
@@ -19,34 +140,14 @@
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/parameter_client.hpp"
|
||||
#include "rclcpp/parameter_service.hpp"
|
||||
#include "rclcpp/rate.hpp"
|
||||
#include "rclcpp/time.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
// Namespace escalations.
|
||||
// For example, this next line escalates type "rclcpp:node::Node" to "rclcpp::Node"
|
||||
using rclcpp::node::Node;
|
||||
using rclcpp::publisher::Publisher;
|
||||
using rclcpp::subscription::SubscriptionBase;
|
||||
using rclcpp::subscription::Subscription;
|
||||
using rclcpp::rate::GenericRate;
|
||||
using rclcpp::rate::WallRate;
|
||||
using rclcpp::timer::GenericTimer;
|
||||
using rclcpp::timer::TimerBase;
|
||||
using rclcpp::timer::WallTimer;
|
||||
using ContextSharedPtr = rclcpp::context::Context::SharedPtr;
|
||||
using rclcpp::utilities::ok;
|
||||
using rclcpp::utilities::shutdown;
|
||||
using rclcpp::utilities::init;
|
||||
using rclcpp::utilities::sleep_for;
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__RCLCPP_HPP_
|
||||
|
||||
@@ -31,7 +31,7 @@ struct ScopeExit
|
||||
{
|
||||
explicit ScopeExit(Callable callable)
|
||||
: callable_(callable) {}
|
||||
~ScopeExit() {callable_(); }
|
||||
~ScopeExit() {callable_();}
|
||||
|
||||
private:
|
||||
Callable callable_;
|
||||
@@ -47,6 +47,6 @@ make_scope_exit(Callable callable)
|
||||
} // namespace rclcpp
|
||||
|
||||
#define RCLCPP_SCOPE_EXIT(code) \
|
||||
auto RCLCPP_STRING_JOIN(scope_exit_, __LINE__) = rclcpp::make_scope_exit([&]() {code; })
|
||||
auto RCLCPP_STRING_JOIN(scope_exit_, __LINE__) = rclcpp::make_scope_exit([&]() {code;})
|
||||
|
||||
#endif // RCLCPP__SCOPE_EXIT_HPP_
|
||||
|
||||
@@ -25,16 +25,16 @@
|
||||
#include "rcl/service.h"
|
||||
|
||||
#include "rclcpp/any_service_callback.hpp"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/expand_topic_or_service_name.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rmw/error_handling.h"
|
||||
#include "rmw/rmw.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace service
|
||||
{
|
||||
|
||||
class ServiceBase
|
||||
{
|
||||
@@ -58,9 +58,13 @@ public:
|
||||
get_service_name();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rcl_service_t *
|
||||
rcl_service_t *
|
||||
get_service_handle();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rcl_service_t *
|
||||
get_service_handle() const;
|
||||
|
||||
virtual std::shared_ptr<void> create_request() = 0;
|
||||
virtual std::shared_ptr<rmw_request_id_t> create_request_header() = 0;
|
||||
virtual void handle_request(
|
||||
@@ -70,6 +74,14 @@ public:
|
||||
protected:
|
||||
RCLCPP_DISABLE_COPY(ServiceBase)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rcl_node_t *
|
||||
get_rcl_node_handle();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rcl_node_t *
|
||||
get_rcl_node_handle() const;
|
||||
|
||||
std::shared_ptr<rcl_node_t> node_handle_;
|
||||
|
||||
rcl_service_t * service_handle_ = nullptr;
|
||||
@@ -77,8 +89,6 @@ protected:
|
||||
bool owns_rcl_handle_ = true;
|
||||
};
|
||||
|
||||
using any_service_callback::AnyServiceCallback;
|
||||
|
||||
template<typename ServiceT>
|
||||
class Service : public ServiceBase
|
||||
{
|
||||
@@ -109,12 +119,25 @@ public:
|
||||
service_handle_ = new rcl_service_t;
|
||||
*service_handle_ = rcl_get_zero_initialized_service();
|
||||
|
||||
if (rcl_service_init(
|
||||
service_handle_, node_handle.get(), service_type_support_handle, service_name.c_str(),
|
||||
&service_options) != RCL_RET_OK)
|
||||
{
|
||||
throw std::runtime_error(std::string("could not create service: ") +
|
||||
rcl_get_error_string_safe());
|
||||
rcl_ret_t ret = rcl_service_init(
|
||||
service_handle_,
|
||||
node_handle.get(),
|
||||
service_type_support_handle,
|
||||
service_name.c_str(),
|
||||
&service_options);
|
||||
if (ret != RCL_RET_OK) {
|
||||
if (ret == RCL_RET_SERVICE_NAME_INVALID) {
|
||||
auto rcl_node_handle = get_rcl_node_handle();
|
||||
// this will throw on any validation problem
|
||||
rcl_reset_error();
|
||||
expand_topic_or_service_name(
|
||||
service_name,
|
||||
rcl_node_get_name(rcl_node_handle),
|
||||
rcl_node_get_namespace(rcl_node_handle),
|
||||
true);
|
||||
}
|
||||
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "could not create service");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +174,9 @@ public:
|
||||
ss << "Error in destruction of rcl service_handle_ handle: " <<
|
||||
rcl_get_error_string_safe() << '\n';
|
||||
(std::cerr << ss.str()).flush();
|
||||
rcl_reset_error();
|
||||
}
|
||||
delete service_handle_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +192,8 @@ public:
|
||||
return std::shared_ptr<rmw_request_id_t>(new rmw_request_id_t);
|
||||
}
|
||||
|
||||
void handle_request(std::shared_ptr<rmw_request_id_t> request_header,
|
||||
void handle_request(
|
||||
std::shared_ptr<rmw_request_id_t> request_header,
|
||||
std::shared_ptr<void> request)
|
||||
{
|
||||
auto typed_request = std::static_pointer_cast<typename ServiceT::Request>(request);
|
||||
@@ -183,10 +209,7 @@ public:
|
||||
rcl_ret_t status = rcl_send_response(get_service_handle(), req_id.get(), response.get());
|
||||
|
||||
if (status != RCL_RET_OK) {
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
throw std::runtime_error(
|
||||
std::string("failed to send response: ") + rcl_get_error_string_safe());
|
||||
// *INDENT-ON*
|
||||
rclcpp::exceptions::throw_from_rcl_error(status, "failed to send response");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +219,6 @@ private:
|
||||
AnyServiceCallback<ServiceT> any_callback_;
|
||||
};
|
||||
|
||||
} // namespace service
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__SERVICE_HPP_
|
||||
|
||||
@@ -183,39 +183,39 @@ public:
|
||||
return has_invalid_weak_nodes;
|
||||
}
|
||||
|
||||
bool add_handles_to_waitset(rcl_wait_set_t * wait_set)
|
||||
bool add_handles_to_wait_set(rcl_wait_set_t * wait_set)
|
||||
{
|
||||
for (auto subscription : subscription_handles_) {
|
||||
if (rcl_wait_set_add_subscription(wait_set, subscription) != RCL_RET_OK) {
|
||||
fprintf(stderr, "Couldn't add subscription to waitset: %s\n", rcl_get_error_string_safe());
|
||||
fprintf(stderr, "Couldn't add subscription to wait set: %s\n", rcl_get_error_string_safe());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto client : client_handles_) {
|
||||
if (rcl_wait_set_add_client(wait_set, client) != RCL_RET_OK) {
|
||||
fprintf(stderr, "Couldn't add client to waitset: %s\n", rcl_get_error_string_safe());
|
||||
fprintf(stderr, "Couldn't add client to wait set: %s\n", rcl_get_error_string_safe());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto service : service_handles_) {
|
||||
if (rcl_wait_set_add_service(wait_set, service) != RCL_RET_OK) {
|
||||
fprintf(stderr, "Couldn't add service to waitset: %s\n", rcl_get_error_string_safe());
|
||||
fprintf(stderr, "Couldn't add service to wait set: %s\n", rcl_get_error_string_safe());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto timer : timer_handles_) {
|
||||
if (rcl_wait_set_add_timer(wait_set, timer) != RCL_RET_OK) {
|
||||
fprintf(stderr, "Couldn't add timer to waitset: %s\n", rcl_get_error_string_safe());
|
||||
fprintf(stderr, "Couldn't add timer to wait set: %s\n", rcl_get_error_string_safe());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto guard_condition : guard_conditions_) {
|
||||
if (rcl_wait_set_add_guard_condition(wait_set, guard_condition) != RCL_RET_OK) {
|
||||
fprintf(stderr, "Couldn't add guard_condition to waitset: %s\n",
|
||||
fprintf(stderr, "Couldn't add guard_condition to wait set: %s\n",
|
||||
rcl_get_error_string_safe());
|
||||
return false;
|
||||
}
|
||||
@@ -231,7 +231,8 @@ public:
|
||||
}
|
||||
|
||||
virtual void
|
||||
get_next_subscription(executor::AnyExecutable::SharedPtr any_exec,
|
||||
get_next_subscription(
|
||||
executor::AnyExecutable::SharedPtr any_exec,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
{
|
||||
auto it = subscription_handles_.begin();
|
||||
@@ -274,7 +275,8 @@ public:
|
||||
}
|
||||
|
||||
virtual void
|
||||
get_next_service(executor::AnyExecutable::SharedPtr any_exec,
|
||||
get_next_service(
|
||||
executor::AnyExecutable::SharedPtr any_exec,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
{
|
||||
auto it = service_handles_.begin();
|
||||
|
||||
@@ -29,10 +29,12 @@
|
||||
|
||||
#include "rcl_interfaces/msg/intra_process_message.hpp"
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/message_memory_strategy.hpp"
|
||||
#include "rclcpp/any_subscription_callback.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/expand_topic_or_service_name.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
@@ -43,9 +45,6 @@ namespace node_interfaces
|
||||
class NodeTopicsInterface;
|
||||
} // namespace node_interfaces
|
||||
|
||||
namespace subscription
|
||||
{
|
||||
|
||||
/// Virtual base class for subscriptions. This pattern allows us to iterate over different template
|
||||
/// specializations of Subscription, among other things.
|
||||
class SubscriptionBase
|
||||
@@ -76,6 +75,10 @@ public:
|
||||
const char *
|
||||
get_topic_name() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rcl_subscription_t *
|
||||
get_subscription_handle();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rcl_subscription_t *
|
||||
get_subscription_handle() const;
|
||||
@@ -85,7 +88,7 @@ public:
|
||||
get_intra_process_subscription_handle() const;
|
||||
|
||||
/// Borrow a new message.
|
||||
// \return Shared pointer to the fresh message.
|
||||
/** \return Shared pointer to the fresh message. */
|
||||
virtual std::shared_ptr<void>
|
||||
create_message() = 0;
|
||||
/// Check if we need to handle the message, and execute the callback if we do.
|
||||
@@ -97,9 +100,10 @@ public:
|
||||
handle_message(std::shared_ptr<void> & message, const rmw_message_info_t & message_info) = 0;
|
||||
|
||||
/// Return the message borrowed in create_message.
|
||||
// \param[in] Shared pointer to the returned message.
|
||||
/** \param[in] message Shared pointer to the returned message. */
|
||||
virtual void
|
||||
return_message(std::shared_ptr<void> & message) = 0;
|
||||
|
||||
virtual void
|
||||
handle_intra_process_message(
|
||||
rcl_interfaces::msg::IntraProcessMessage & ipm,
|
||||
@@ -114,8 +118,6 @@ private:
|
||||
RCLCPP_DISABLE_COPY(SubscriptionBase)
|
||||
};
|
||||
|
||||
using any_subscription_callback::AnySubscriptionCallback;
|
||||
|
||||
/// Subscription implementation, templated on the type of message this subscription receives.
|
||||
template<typename MessageT, typename Alloc = std::allocator<void>>
|
||||
class Subscription : public SubscriptionBase
|
||||
@@ -192,6 +194,8 @@ public:
|
||||
any_callback_.dispatch(typed_message, message_info);
|
||||
}
|
||||
|
||||
/// Return the loaned message.
|
||||
/** \param message message to be returned */
|
||||
void return_message(std::shared_ptr<void> & message)
|
||||
{
|
||||
auto typed_message = std::static_pointer_cast<MessageT>(message);
|
||||
@@ -235,16 +239,25 @@ public:
|
||||
MatchesAnyPublishersCallbackType matches_any_publisher_callback,
|
||||
const rcl_subscription_options_t & intra_process_options)
|
||||
{
|
||||
if (rcl_subscription_init(
|
||||
&intra_process_subscription_handle_, node_handle_.get(),
|
||||
rclcpp::type_support::get_intra_process_message_msg_type_support(),
|
||||
(std::string(get_topic_name()) + "__intra").c_str(),
|
||||
&intra_process_options) != RCL_RET_OK)
|
||||
{
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
throw std::runtime_error(
|
||||
std::string("could not create intra process subscription: ") + rcl_get_error_string_safe());
|
||||
// *INDENT-ON*
|
||||
std::string intra_process_topic_name = std::string(get_topic_name()) + "/_intra";
|
||||
rcl_ret_t ret = rcl_subscription_init(
|
||||
&intra_process_subscription_handle_,
|
||||
node_handle_.get(),
|
||||
rclcpp::type_support::get_intra_process_message_msg_type_support(),
|
||||
intra_process_topic_name.c_str(),
|
||||
&intra_process_options);
|
||||
if (ret != RCL_RET_OK) {
|
||||
if (ret == RCL_RET_TOPIC_NAME_INVALID) {
|
||||
auto rcl_node_handle = node_handle_.get();
|
||||
// this will throw on any validation problem
|
||||
rcl_reset_error();
|
||||
expand_topic_or_service_name(
|
||||
intra_process_topic_name,
|
||||
rcl_node_get_name(rcl_node_handle),
|
||||
rcl_node_get_namespace(rcl_node_handle));
|
||||
}
|
||||
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "could not create intra process subscription");
|
||||
}
|
||||
|
||||
intra_process_subscription_id_ = intra_process_subscription_id;
|
||||
@@ -267,14 +280,13 @@ private:
|
||||
|
||||
AnySubscriptionCallback<MessageT, Alloc> any_callback_;
|
||||
typename message_memory_strategy::MessageMemoryStrategy<MessageT, Alloc>::SharedPtr
|
||||
message_memory_strategy_;
|
||||
message_memory_strategy_;
|
||||
|
||||
GetMessageCallbackType get_intra_process_message_callback_;
|
||||
MatchesAnyPublishersCallbackType matches_any_intra_process_publishers_;
|
||||
uint64_t intra_process_subscription_id_;
|
||||
};
|
||||
|
||||
} // namespace subscription
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__SUBSCRIPTION_HPP_
|
||||
|
||||
@@ -33,7 +33,8 @@ namespace rclcpp
|
||||
{
|
||||
|
||||
/// Factory with functions used to create a Subscription<MessageT>.
|
||||
/* This factory class is used to encapsulate the template generated functions
|
||||
/**
|
||||
* This factory class is used to encapsulate the template generated functions
|
||||
* which are used during the creation of a Message type specific subscription
|
||||
* within a non-templated class.
|
||||
*
|
||||
@@ -46,7 +47,7 @@ struct SubscriptionFactory
|
||||
{
|
||||
// Creates a Subscription<MessageT> object and returns it as a SubscriptionBase.
|
||||
using SubscriptionFactoryFunction = std::function<
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr(
|
||||
rclcpp::SubscriptionBase::SharedPtr(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
const std::string & topic_name,
|
||||
rcl_subscription_options_t & subscription_options)>;
|
||||
@@ -54,9 +55,10 @@ struct SubscriptionFactory
|
||||
SubscriptionFactoryFunction create_typed_subscription;
|
||||
|
||||
// Function that takes a MessageT from the intra process manager
|
||||
using SetupIntraProcessFunction = std::function<void(
|
||||
using SetupIntraProcessFunction = std::function<
|
||||
void(
|
||||
rclcpp::intra_process_manager::IntraProcessManager::SharedPtr ipm,
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
const rcl_subscription_options_t & subscription_options)>;
|
||||
|
||||
SetupIntraProcessFunction setup_intra_process;
|
||||
@@ -73,12 +75,12 @@ create_subscription_factory(
|
||||
{
|
||||
SubscriptionFactory factory;
|
||||
|
||||
using rclcpp::subscription::AnySubscriptionCallback;
|
||||
using rclcpp::AnySubscriptionCallback;
|
||||
AnySubscriptionCallback<MessageT, Alloc> any_subscription_callback(allocator);
|
||||
any_subscription_callback.set(std::forward<CallbackT>(callback));
|
||||
|
||||
auto message_alloc =
|
||||
std::make_shared<typename subscription::Subscription<MessageT, Alloc>::MessageAlloc>();
|
||||
std::make_shared<typename Subscription<MessageT, Alloc>::MessageAlloc>();
|
||||
|
||||
// factory function that creates a MessageT specific SubscriptionT
|
||||
factory.create_typed_subscription =
|
||||
@@ -86,13 +88,13 @@ create_subscription_factory(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
const std::string & topic_name,
|
||||
rcl_subscription_options_t & subscription_options
|
||||
) -> rclcpp::subscription::SubscriptionBase::SharedPtr
|
||||
) -> rclcpp::SubscriptionBase::SharedPtr
|
||||
{
|
||||
subscription_options.allocator =
|
||||
rclcpp::allocator::get_rcl_allocator<MessageT>(*message_alloc.get());
|
||||
|
||||
using rclcpp::subscription::Subscription;
|
||||
using rclcpp::subscription::SubscriptionBase;
|
||||
using rclcpp::Subscription;
|
||||
using rclcpp::SubscriptionBase;
|
||||
|
||||
auto sub = Subscription<MessageT, Alloc>::make_shared(
|
||||
node_base->get_shared_rcl_node_handle(),
|
||||
@@ -108,7 +110,7 @@ create_subscription_factory(
|
||||
factory.setup_intra_process =
|
||||
[message_alloc](
|
||||
rclcpp::intra_process_manager::IntraProcessManager::SharedPtr ipm,
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
const rcl_subscription_options_t & subscription_options)
|
||||
{
|
||||
rclcpp::intra_process_manager::IntraProcessManager::WeakPtr weak_ipm = ipm;
|
||||
@@ -126,7 +128,7 @@ create_subscription_factory(
|
||||
uint64_t publisher_id,
|
||||
uint64_t message_sequence,
|
||||
uint64_t subscription_id,
|
||||
typename rclcpp::subscription::Subscription<MessageT, Alloc>::MessageUniquePtr & message)
|
||||
typename rclcpp::Subscription<MessageT, Alloc>::MessageUniquePtr & message)
|
||||
{
|
||||
auto ipm = weak_ipm.lock();
|
||||
if (!ipm) {
|
||||
|
||||
119
rclcpp/include/rclcpp/time.hpp
Normal file
119
rclcpp/include/rclcpp/time.hpp
Normal file
@@ -0,0 +1,119 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__TIME_HPP_
|
||||
#define RCLCPP__TIME_HPP_
|
||||
|
||||
#include "builtin_interfaces/msg/time.hpp"
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rcl/time.h"
|
||||
|
||||
#include "rclcpp/duration.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
class Clock;
|
||||
|
||||
class Time
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
Time(int32_t seconds, uint32_t nanoseconds, rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit Time(uint64_t nanoseconds = 0, rcl_clock_type_t clock = RCL_SYSTEM_TIME);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Time(const Time & rhs);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Time(
|
||||
const builtin_interfaces::msg::Time & time_msg,
|
||||
rcl_clock_type_t ros_time = RCL_ROS_TIME);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit Time(const rcl_time_point_t & time_point);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~Time();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
operator builtin_interfaces::msg::Time() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Time &
|
||||
operator=(const Time & rhs);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Time &
|
||||
operator=(const builtin_interfaces::msg::Time & time_msg);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
operator==(const rclcpp::Time & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
operator!=(const rclcpp::Time & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
operator<(const rclcpp::Time & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
operator<=(const rclcpp::Time & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
operator>=(const rclcpp::Time & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
operator>(const rclcpp::Time & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Time
|
||||
operator+(const rclcpp::Duration & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Duration
|
||||
operator-(const rclcpp::Time & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Time
|
||||
operator-(const rclcpp::Duration & rhs) const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rcl_time_point_value_t
|
||||
nanoseconds() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rcl_clock_type_t
|
||||
get_clock_type() const;
|
||||
|
||||
private:
|
||||
rcl_time_point_t rcl_time_;
|
||||
friend Clock; // Allow clock to manipulate internal data
|
||||
};
|
||||
|
||||
Time
|
||||
operator+(const rclcpp::Duration & lhs, const rclcpp::Time & rhs);
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__TIME_HPP_
|
||||
128
rclcpp/include/rclcpp/time_source.hpp
Normal file
128
rclcpp/include/rclcpp/time_source.hpp
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__TIME_SOURCE_HPP_
|
||||
#define RCLCPP__TIME_SOURCE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/time.h"
|
||||
|
||||
#include "builtin_interfaces/msg/time.hpp"
|
||||
#include "rcl_interfaces/msg/parameter_event.hpp"
|
||||
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/parameter_client.hpp"
|
||||
#include "rclcpp/parameter_events_filter.hpp"
|
||||
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
class Clock;
|
||||
|
||||
class TimeSource
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
explicit TimeSource(rclcpp::Node::SharedPtr node);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
TimeSource();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void attachNode(rclcpp::Node::SharedPtr node);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void attachNode(
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
|
||||
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void detachNode();
|
||||
|
||||
/// Attach a clock to the time source to be updated
|
||||
/**
|
||||
* \throws std::invalid_argument if node is nullptr
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void attachClock(rclcpp::Clock::SharedPtr clock);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void detachClock(rclcpp::Clock::SharedPtr clock);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
~TimeSource();
|
||||
|
||||
private:
|
||||
// Preserve the node reference
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_;
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_;
|
||||
rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_;
|
||||
|
||||
// The subscription for the clock callback
|
||||
using MessageT = builtin_interfaces::msg::Time;
|
||||
using Alloc = std::allocator<void>;
|
||||
using SubscriptionT = rclcpp::Subscription<MessageT, Alloc>;
|
||||
std::shared_ptr<SubscriptionT> clock_subscription_;
|
||||
|
||||
// The clock callback itself
|
||||
void clock_cb(const builtin_interfaces::msg::Time::SharedPtr msg);
|
||||
|
||||
// Parameter Client pointer
|
||||
std::shared_ptr<rclcpp::AsyncParametersClient> parameter_client_;
|
||||
|
||||
// Parameter Event subscription
|
||||
using ParamMessageT = rcl_interfaces::msg::ParameterEvent;
|
||||
using ParamSubscriptionT = rclcpp::Subscription<ParamMessageT, Alloc>;
|
||||
std::shared_ptr<ParamSubscriptionT> parameter_subscription_;
|
||||
|
||||
// Callback for parameter updates
|
||||
void on_parameter_event(const rcl_interfaces::msg::ParameterEvent::SharedPtr event);
|
||||
|
||||
// An enum to hold the parameter state
|
||||
enum UseSimTimeParameterState {UNSET, SET_TRUE, SET_FALSE};
|
||||
UseSimTimeParameterState parameter_state_;
|
||||
|
||||
// An internal method to use in the clock callback that iterates and enables all clocks
|
||||
void enable_ros_time();
|
||||
// An internal method to use in the clock callback that iterates and disables all clocks
|
||||
void disable_ros_time();
|
||||
|
||||
// Internal helper functions used inside iterators
|
||||
static void enable_ros_time(rclcpp::Clock::SharedPtr clock);
|
||||
static void disable_ros_time(rclcpp::Clock::SharedPtr clock);
|
||||
static void set_clock(
|
||||
const builtin_interfaces::msg::Time::SharedPtr msg,
|
||||
bool set_ros_time_enabled,
|
||||
rclcpp::Clock::SharedPtr clock);
|
||||
|
||||
// Local storage of validity of ROS time
|
||||
// This is needed when new clocks are added.
|
||||
bool ros_time_active_;
|
||||
// Last set message to be passed to newly registered clocks
|
||||
builtin_interfaces::msg::Time::SharedPtr last_msg_set_;
|
||||
|
||||
// A lock to protect iterating the associated_clocks_ field.
|
||||
std::mutex clock_list_lock_;
|
||||
// A vector to store references to associated clocks.
|
||||
std::vector<rclcpp::Clock::SharedPtr> associated_clocks_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__TIME_SOURCE_HPP_
|
||||
@@ -37,8 +37,6 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace timer
|
||||
{
|
||||
|
||||
class TimerBase
|
||||
{
|
||||
@@ -55,6 +53,10 @@ public:
|
||||
void
|
||||
cancel();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
reset();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
execute_callback() = 0;
|
||||
@@ -64,13 +66,13 @@ public:
|
||||
get_timer_handle();
|
||||
|
||||
/// Check how long the timer has until its next scheduled callback.
|
||||
// \return A std::chrono::duration representing the relative time until the next callback.
|
||||
/** \return A std::chrono::duration representing the relative time until the next callback. */
|
||||
RCLCPP_PUBLIC
|
||||
std::chrono::nanoseconds
|
||||
time_until_trigger();
|
||||
|
||||
/// Is the clock steady (i.e. is the time between ticks constant?)
|
||||
// \return True if the clock used by this timer is steady.
|
||||
/** \return True if the clock used by this timer is steady. */
|
||||
virtual bool is_steady() = 0;
|
||||
|
||||
/// Check if the timer is ready to trigger the callback.
|
||||
@@ -178,7 +180,6 @@ protected:
|
||||
template<typename CallbackType>
|
||||
using WallTimer = GenericTimer<CallbackType, std::chrono::steady_clock>;
|
||||
|
||||
} // namespace timer
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__TIMER_HPP_
|
||||
|
||||
@@ -44,8 +44,6 @@ std::string to_string(T value)
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace utilities
|
||||
{
|
||||
|
||||
/// Initialize communications via the rmw implementation and set up a global signal handler.
|
||||
/**
|
||||
@@ -57,7 +55,7 @@ void
|
||||
init(int argc, char * argv[]);
|
||||
|
||||
/// Check rclcpp's status.
|
||||
// \return True if SIGINT hasn't fired yet, false otherwise.
|
||||
/** \return True if SIGINT hasn't fired yet, false otherwise. */
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
ok();
|
||||
@@ -68,39 +66,39 @@ void
|
||||
shutdown();
|
||||
|
||||
/// Register a function to be called when shutdown is called.
|
||||
/* Calling the callbacks is the last thing shutdown() does. */
|
||||
/** Calling the callbacks is the last thing shutdown() does. */
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
on_shutdown(std::function<void(void)> callback);
|
||||
|
||||
/// Get a handle to the rmw guard condition that manages the signal handler.
|
||||
/**
|
||||
* The first time that this function is called for a given waitset a new guard
|
||||
* The first time that this function is called for a given wait set a new guard
|
||||
* condition will be created and returned; thereafter the same guard condition
|
||||
* will be returned for the same waitset. This mechanism is designed to ensure
|
||||
* that the same guard condition is not reused across waitsets (e.g., when
|
||||
* will be returned for the same wait set. This mechanism is designed to ensure
|
||||
* that the same guard condition is not reused across wait sets (e.g., when
|
||||
* using multiple executors in the same process). Will throw an exception if
|
||||
* initialization of the guard condition fails.
|
||||
* \param[waitset] waitset Pointer to the rcl_wait_set_t that will be using the
|
||||
* \param wait_set Pointer to the rcl_wait_set_t that will be using the
|
||||
* resulting guard condition.
|
||||
* \return Pointer to the guard condition.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rcl_guard_condition_t *
|
||||
get_sigint_guard_condition(rcl_wait_set_t * waitset);
|
||||
get_sigint_guard_condition(rcl_wait_set_t * wait_set);
|
||||
|
||||
/// Release the previously allocated guard condition that manages the signal handler.
|
||||
/**
|
||||
* If you previously called get_sigint_guard_condition() for a given waitset
|
||||
* If you previously called get_sigint_guard_condition() for a given wait set
|
||||
* to get a sigint guard condition, then you should call release_sigint_guard_condition()
|
||||
* when you're done, to free that condition. Will throw an exception if
|
||||
* get_sigint_guard_condition() wasn't previously called for the given waitset.
|
||||
* \param[waitset] waitset Pointer to the rcl_wait_set_t that was using the
|
||||
* get_sigint_guard_condition() wasn't previously called for the given wait set.
|
||||
* \param wait_set Pointer to the rcl_wait_set_t that was using the
|
||||
* resulting guard condition.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
release_sigint_guard_condition(rcl_wait_set_t * waitset);
|
||||
release_sigint_guard_condition(rcl_wait_set_t * wait_set);
|
||||
|
||||
/// Use the global condition variable to block for the specified amount of time.
|
||||
/**
|
||||
@@ -111,7 +109,6 @@ RCLCPP_PUBLIC
|
||||
bool
|
||||
sleep_for(const std::chrono::nanoseconds & nanoseconds);
|
||||
|
||||
} // namespace utilities
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__UTILITIES_HPP_
|
||||
|
||||
@@ -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.0.0</version>
|
||||
<version>0.4.0</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
@@ -11,12 +11,15 @@
|
||||
|
||||
<build_export_depend>rmw</build_export_depend>
|
||||
|
||||
<build_depend>builtin_interfaces</build_depend>
|
||||
<build_depend>rcl_interfaces</build_depend>
|
||||
<build_depend>rmw_implementation_cmake</build_depend>
|
||||
<build_depend>rosidl_generator_cpp</build_depend>
|
||||
<build_depend>rosidl_typesupport_c</build_depend>
|
||||
<build_depend>rosidl_typesupport_cpp</build_depend>
|
||||
<build_export_depend>builtin_interfaces</build_export_depend>
|
||||
<build_export_depend>rcl_interfaces</build_export_depend>
|
||||
<build_export_depend>rosidl_generator_cpp</build_export_depend>
|
||||
<build_export_depend>rosidl_typesupport_c</build_export_depend>
|
||||
<build_export_depend>rosidl_typesupport_cpp</build_export_depend>
|
||||
|
||||
<depend>rcl</depend>
|
||||
@@ -24,10 +27,12 @@
|
||||
|
||||
<exec_depend>ament_cmake</exec_depend>
|
||||
|
||||
<test_depend>ament_cmake_gmock</test_depend>
|
||||
<test_depend>ament_cmake_gtest</test_depend>
|
||||
<test_depend>ament_lint_auto</test_depend>
|
||||
<test_depend>ament_lint_common</test_depend>
|
||||
<test_depend>rmw</test_depend>
|
||||
<test_depend>rmw_implementation_cmake</test_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_cmake</build_type>
|
||||
|
||||
@@ -25,6 +25,5 @@ macro(_rclcpp_register_package_hook)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
include("${rclcpp_DIR}/get_rclcpp_information.cmake")
|
||||
include("${rclcpp_DIR}/rclcpp_create_node_main.cmake")
|
||||
include("${rclcpp_DIR}/rclcpp_register_node_plugins.cmake")
|
||||
|
||||
105
rclcpp/resource/logging.hpp.em
Normal file
105
rclcpp/resource/logging.hpp.em
Normal file
@@ -0,0 +1,105 @@
|
||||
// generated from rclcpp/resource/logging.hpp.em
|
||||
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__LOGGING_HPP_
|
||||
#define RCLCPP__LOGGING_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rcutils/logging_macros.h"
|
||||
|
||||
// These are used for compiling out logging macros lower than a minimum severity.
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_DEBUG 0
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_INFO 1
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_WARN 2
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_ERROR 3
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_FATAL 4
|
||||
#define RCLCPP_LOG_MIN_SEVERITY_NONE 5
|
||||
|
||||
/**
|
||||
* \def RCLCPP_LOG_MIN_SEVERITY
|
||||
* Define RCLCPP_LOG_MIN_SEVERITY=RCLCPP_LOG_MIN_SEVERITY_[DEBUG|INFO|WARN|ERROR|FATAL]
|
||||
* in your build options to compile out anything below that severity.
|
||||
* Use RCLCPP_LOG_MIN_SEVERITY_NONE to compile out all macros.
|
||||
*/
|
||||
#ifndef RCLCPP_LOG_MIN_SEVERITY
|
||||
#define RCLCPP_LOG_MIN_SEVERITY RCLCPP_LOG_MIN_SEVERITY_DEBUG
|
||||
#endif
|
||||
|
||||
@{
|
||||
from rcutils.logging import feature_combinations
|
||||
from rcutils.logging import get_macro_parameters
|
||||
from rcutils.logging import get_suffix_from_features
|
||||
from rcutils.logging import severities
|
||||
|
||||
# TODO(dhood): Implement the throttle macro using time sources available in rclcpp
|
||||
excluded_features = ['named', 'throttle']
|
||||
def is_supported_feature_combination(feature_combination):
|
||||
is_excluded = any([ef in feature_combination for ef in excluded_features])
|
||||
return not is_excluded
|
||||
}@
|
||||
@[for severity in severities]@
|
||||
/** @@name Logging macros for severity @(severity).
|
||||
*/
|
||||
///@@{
|
||||
#if (RCLCPP_LOG_MIN_SEVERITY > RCLCPP_LOG_MIN_SEVERITY_@(severity))
|
||||
// empty logging macros for severity @(severity) when being disabled at compile time
|
||||
@[ for feature_combination in [fc for fc in feature_combinations if is_supported_feature_combination(fc)]]@
|
||||
@{suffix = get_suffix_from_features(feature_combination)}@
|
||||
/// Empty logging macro due to the preprocessor definition of RCLCPP_LOG_MIN_SEVERITY.
|
||||
#define RCLCPP_@(severity)@(suffix)(...)
|
||||
@[ end for]@
|
||||
|
||||
#else
|
||||
@[ for feature_combination in [fc for fc in feature_combinations if is_supported_feature_combination(fc)]]@
|
||||
@{suffix = get_suffix_from_features(feature_combination)}@
|
||||
/**
|
||||
* \def RCLCPP_@(severity)@(suffix)
|
||||
* Log a message with severity @(severity)@
|
||||
@[ if feature_combinations[feature_combination].doc_lines]@
|
||||
with the following conditions:
|
||||
@[ else]@
|
||||
.
|
||||
@[ end if]@
|
||||
@[ for doc_line in feature_combinations[feature_combination].doc_lines]@
|
||||
* @(doc_line)
|
||||
@[ end for]@
|
||||
* \param logger The `rclcpp::Logger` to use
|
||||
@[ for param_name, doc_line in feature_combinations[feature_combination].params.items()]@
|
||||
* \param @(param_name) @(doc_line)
|
||||
@[ end for]@
|
||||
* \param ... The format string, followed by the variable arguments for the format string
|
||||
*/
|
||||
#define RCLCPP_@(severity)@(suffix)(logger, @(''.join([p + ', ' for p in get_macro_parameters(feature_combination).keys()]))...) \
|
||||
static_assert( \
|
||||
::std::is_same<std::remove_reference<decltype(logger)>::type, ::rclcpp::Logger>::value, \
|
||||
"First argument to logging macros must be an rclcpp::Logger"); \
|
||||
RCUTILS_LOG_@(severity)@(suffix)_NAMED( \
|
||||
@{params = get_macro_parameters(feature_combination).keys()}@
|
||||
@[ if params]@
|
||||
@(''.join([' ' + p + ', \\\n' for p in params]))@
|
||||
@[ end if]@
|
||||
logger.get_name(), \
|
||||
__VA_ARGS__)
|
||||
|
||||
@[ end for]@
|
||||
#endif
|
||||
///@@}
|
||||
|
||||
@[end for]@
|
||||
|
||||
#endif // RCLCPP__LOGGING_HPP_
|
||||
@@ -23,28 +23,28 @@ CallbackGroup::CallbackGroup(CallbackGroupType group_type)
|
||||
: type_(group_type), can_be_taken_from_(true)
|
||||
{}
|
||||
|
||||
const std::vector<rclcpp::subscription::SubscriptionBase::WeakPtr> &
|
||||
const std::vector<rclcpp::SubscriptionBase::WeakPtr> &
|
||||
CallbackGroup::get_subscription_ptrs() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return subscription_ptrs_;
|
||||
}
|
||||
|
||||
const std::vector<rclcpp::timer::TimerBase::WeakPtr> &
|
||||
const std::vector<rclcpp::TimerBase::WeakPtr> &
|
||||
CallbackGroup::get_timer_ptrs() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return timer_ptrs_;
|
||||
}
|
||||
|
||||
const std::vector<rclcpp::service::ServiceBase::WeakPtr> &
|
||||
const std::vector<rclcpp::ServiceBase::WeakPtr> &
|
||||
CallbackGroup::get_service_ptrs() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
return service_ptrs_;
|
||||
}
|
||||
|
||||
const std::vector<rclcpp::client::ClientBase::WeakPtr> &
|
||||
const std::vector<rclcpp::ClientBase::WeakPtr> &
|
||||
CallbackGroup::get_client_ptrs() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
@@ -65,28 +65,28 @@ CallbackGroup::type() const
|
||||
|
||||
void
|
||||
CallbackGroup::add_subscription(
|
||||
const rclcpp::subscription::SubscriptionBase::SharedPtr subscription_ptr)
|
||||
const rclcpp::SubscriptionBase::SharedPtr subscription_ptr)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
subscription_ptrs_.push_back(subscription_ptr);
|
||||
}
|
||||
|
||||
void
|
||||
CallbackGroup::add_timer(const rclcpp::timer::TimerBase::SharedPtr timer_ptr)
|
||||
CallbackGroup::add_timer(const rclcpp::TimerBase::SharedPtr timer_ptr)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
timer_ptrs_.push_back(timer_ptr);
|
||||
}
|
||||
|
||||
void
|
||||
CallbackGroup::add_service(const rclcpp::service::ServiceBase::SharedPtr service_ptr)
|
||||
CallbackGroup::add_service(const rclcpp::ServiceBase::SharedPtr service_ptr)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
service_ptrs_.push_back(service_ptr);
|
||||
}
|
||||
|
||||
void
|
||||
CallbackGroup::add_client(const rclcpp::client::ClientBase::SharedPtr client_ptr)
|
||||
CallbackGroup::add_client(const rclcpp::ClientBase::SharedPtr client_ptr)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
client_ptrs_.push_back(client_ptr);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
|
||||
using rclcpp::client::ClientBase;
|
||||
using rclcpp::ClientBase;
|
||||
using rclcpp::exceptions::InvalidNodeError;
|
||||
using rclcpp::exceptions::throw_from_rcl_error;
|
||||
|
||||
@@ -48,6 +48,12 @@ ClientBase::get_service_name() const
|
||||
return this->service_name_;
|
||||
}
|
||||
|
||||
rcl_client_t *
|
||||
ClientBase::get_client_handle()
|
||||
{
|
||||
return &client_handle_;
|
||||
}
|
||||
|
||||
const rcl_client_t *
|
||||
ClientBase::get_client_handle() const
|
||||
{
|
||||
@@ -70,6 +76,12 @@ bool
|
||||
ClientBase::wait_for_service_nanoseconds(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
// make an event to reuse, rather than create a new one each time
|
||||
auto node_ptr = node_graph_.lock();
|
||||
if (!node_ptr) {
|
||||
throw InvalidNodeError();
|
||||
}
|
||||
auto event = node_ptr->get_graph_event();
|
||||
// check to see if the server is ready immediately
|
||||
if (this->service_is_ready()) {
|
||||
return true;
|
||||
@@ -78,12 +90,6 @@ ClientBase::wait_for_service_nanoseconds(std::chrono::nanoseconds timeout)
|
||||
// check was non-blocking, return immediately
|
||||
return false;
|
||||
}
|
||||
// make an event to reuse, rather than create a new one each time
|
||||
auto node_ptr = node_graph_.lock();
|
||||
if (!node_ptr) {
|
||||
throw InvalidNodeError();
|
||||
}
|
||||
auto event = node_ptr->get_graph_event();
|
||||
// update the time even on the first loop to account for time spent in the first call
|
||||
// to this->server_is_ready()
|
||||
std::chrono::nanoseconds time_to_wait = timeout - (std::chrono::steady_clock::now() - start);
|
||||
@@ -93,9 +99,8 @@ ClientBase::wait_for_service_nanoseconds(std::chrono::nanoseconds timeout)
|
||||
time_to_wait = std::chrono::nanoseconds(0);
|
||||
}
|
||||
// continue forever if timeout is negative, otherwise continue until out of time_to_wait
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
do {
|
||||
if (!rclcpp::utilities::ok()) {
|
||||
if (!rclcpp::ok()) {
|
||||
return false;
|
||||
}
|
||||
node_ptr->wait_for_graph_change(event, time_to_wait);
|
||||
@@ -109,12 +114,17 @@ ClientBase::wait_for_service_nanoseconds(std::chrono::nanoseconds timeout)
|
||||
}
|
||||
// server is not ready, loop if there is time left
|
||||
time_to_wait = timeout - (std::chrono::steady_clock::now() - start);
|
||||
} while (timeout < std::chrono::nanoseconds(0) || time_to_wait > std::chrono::nanoseconds(0));
|
||||
// *INDENT-ON*
|
||||
} while (time_to_wait > std::chrono::nanoseconds(0) || timeout < std::chrono::nanoseconds(0));
|
||||
return false; // timeout exceeded while waiting for the server to be ready
|
||||
}
|
||||
|
||||
rcl_node_t *
|
||||
ClientBase::get_rcl_node_handle()
|
||||
{
|
||||
return node_handle_.get();
|
||||
}
|
||||
|
||||
const rcl_node_t *
|
||||
ClientBase::get_rcl_node_handle() const
|
||||
{
|
||||
return node_handle_.get();
|
||||
|
||||
170
rclcpp/src/rclcpp/clock.cpp
Normal file
170
rclcpp/src/rclcpp/clock.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "rclcpp/clock.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "builtin_interfaces/msg/time.hpp"
|
||||
|
||||
#include "rcl/time.h"
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
|
||||
#include "rcutils/logging_macros.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
bool
|
||||
JumpThreshold::is_exceeded(const TimeJump & jump)
|
||||
{
|
||||
if (on_clock_change_ &&
|
||||
(jump.jump_type_ == TimeJump::ClockChange_t::ROS_TIME_ACTIVATED ||
|
||||
jump.jump_type_ == TimeJump::ClockChange_t::ROS_TIME_DEACTIVATED))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ((uint64_t)jump.delta_.nanoseconds > min_forward_ ||
|
||||
(uint64_t)jump.delta_.nanoseconds < min_backward_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
JumpHandler::JumpHandler(
|
||||
std::function<void()> pre_callback,
|
||||
std::function<void(TimeJump)> post_callback,
|
||||
JumpThreshold & threshold)
|
||||
: pre_callback(pre_callback),
|
||||
post_callback(post_callback),
|
||||
notice_threshold(threshold)
|
||||
{}
|
||||
|
||||
Clock::Clock(rcl_clock_type_t clock_type)
|
||||
{
|
||||
allocator_ = rcl_get_default_allocator();
|
||||
auto ret = rcl_clock_init(clock_type, &rcl_clock_, &allocator_);
|
||||
if (ret != RCL_RET_OK) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(
|
||||
ret, "could not get current time stamp");
|
||||
}
|
||||
}
|
||||
|
||||
Clock::~Clock()
|
||||
{
|
||||
auto ret = rcl_clock_fini(&rcl_clock_);
|
||||
if (ret != RCL_RET_OK) {
|
||||
RCUTILS_LOG_ERROR("Failed to fini rcl clock.");
|
||||
}
|
||||
}
|
||||
|
||||
Time
|
||||
Clock::now()
|
||||
{
|
||||
Time now(0, 0, rcl_clock_.type);
|
||||
|
||||
auto ret = rcl_clock_get_now(&rcl_clock_, &now.rcl_time_);
|
||||
if (ret != RCL_RET_OK) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(
|
||||
ret, "could not get current time stamp");
|
||||
}
|
||||
|
||||
return now;
|
||||
}
|
||||
|
||||
bool
|
||||
Clock::ros_time_is_active()
|
||||
{
|
||||
if (!rcl_clock_valid(&rcl_clock_)) {
|
||||
RCUTILS_LOG_ERROR("ROS time not valid!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_enabled;
|
||||
auto ret = rcl_is_enabled_ros_time_override(&rcl_clock_, &is_enabled);
|
||||
if (ret != RCL_RET_OK) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(
|
||||
ret, "Failed to check ros_time_override_status");
|
||||
}
|
||||
return is_enabled;
|
||||
}
|
||||
|
||||
rcl_clock_type_t
|
||||
Clock::get_clock_type()
|
||||
{
|
||||
return rcl_clock_.type;
|
||||
}
|
||||
|
||||
rclcpp::JumpHandler::SharedPtr
|
||||
Clock::create_jump_callback(
|
||||
std::function<void()> pre_callback,
|
||||
std::function<void(const TimeJump &)> post_callback,
|
||||
JumpThreshold & threshold)
|
||||
{
|
||||
// JumpHandler jump_callback;
|
||||
auto jump_callback =
|
||||
std::make_shared<rclcpp::JumpHandler>(pre_callback, post_callback, threshold);
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(callback_list_mutex_);
|
||||
active_jump_handlers_.push_back(jump_callback);
|
||||
}
|
||||
return jump_callback;
|
||||
}
|
||||
|
||||
std::vector<JumpHandler::SharedPtr>
|
||||
Clock::get_triggered_callback_handlers(const TimeJump & jump)
|
||||
{
|
||||
std::vector<JumpHandler::SharedPtr> callbacks;
|
||||
std::lock_guard<std::mutex> guard(callback_list_mutex_);
|
||||
active_jump_handlers_.erase(
|
||||
std::remove_if(
|
||||
active_jump_handlers_.begin(),
|
||||
active_jump_handlers_.end(),
|
||||
[&callbacks, &jump](const std::weak_ptr<JumpHandler> & wjcb) {
|
||||
if (auto jcb = wjcb.lock()) {
|
||||
if (jcb->notice_threshold.is_exceeded(jump)) {
|
||||
callbacks.push_back(jcb);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Lock failed so clear the weak pointer.
|
||||
return true;
|
||||
}),
|
||||
active_jump_handlers_.end());
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
void
|
||||
Clock::invoke_prejump_callbacks(
|
||||
const std::vector<JumpHandler::SharedPtr> & callbacks)
|
||||
{
|
||||
for (const auto cb : callbacks) {
|
||||
cb->pre_callback();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Clock::invoke_postjump_callbacks(
|
||||
const std::vector<JumpHandler::SharedPtr> & callbacks,
|
||||
const TimeJump & jump)
|
||||
{
|
||||
for (auto cb : callbacks) {
|
||||
cb->post_callback(jump);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
@@ -14,6 +14,6 @@
|
||||
|
||||
#include "rclcpp/context.hpp"
|
||||
|
||||
using rclcpp::context::Context;
|
||||
using rclcpp::Context;
|
||||
|
||||
Context::Context() {}
|
||||
|
||||
191
rclcpp/src/rclcpp/duration.cpp
Normal file
191
rclcpp/src/rclcpp/duration.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/time.hpp"
|
||||
|
||||
#include "builtin_interfaces/msg/duration.hpp"
|
||||
|
||||
#include "rcl/time.h"
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
|
||||
#include "rcutils/logging_macros.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
Duration::Duration(int32_t seconds, uint32_t nanoseconds)
|
||||
{
|
||||
rcl_duration_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(seconds));
|
||||
rcl_duration_.nanoseconds += nanoseconds;
|
||||
}
|
||||
|
||||
Duration::Duration(int64_t nanoseconds)
|
||||
{
|
||||
rcl_duration_.nanoseconds = nanoseconds;
|
||||
}
|
||||
|
||||
Duration::Duration(std::chrono::nanoseconds nanoseconds)
|
||||
{
|
||||
rcl_duration_.nanoseconds = nanoseconds.count();
|
||||
}
|
||||
|
||||
Duration::Duration(const Duration & rhs)
|
||||
{
|
||||
rcl_duration_.nanoseconds = rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
|
||||
Duration::Duration(
|
||||
const builtin_interfaces::msg::Duration & duration_msg)
|
||||
{
|
||||
rcl_duration_.nanoseconds = RCL_S_TO_NS(static_cast<uint64_t>(duration_msg.sec));
|
||||
rcl_duration_.nanoseconds += duration_msg.nanosec;
|
||||
}
|
||||
|
||||
Duration::Duration(const rcl_duration_t & duration)
|
||||
: rcl_duration_(duration)
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
Duration::~Duration()
|
||||
{
|
||||
}
|
||||
|
||||
Duration::operator builtin_interfaces::msg::Duration() const
|
||||
{
|
||||
builtin_interfaces::msg::Duration msg_duration;
|
||||
msg_duration.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_duration_.nanoseconds));
|
||||
msg_duration.nanosec =
|
||||
static_cast<std::uint32_t>(rcl_duration_.nanoseconds % (1000 * 1000 * 1000));
|
||||
return msg_duration;
|
||||
}
|
||||
|
||||
Duration &
|
||||
Duration::operator=(const Duration & rhs)
|
||||
{
|
||||
rcl_duration_.nanoseconds = rhs.rcl_duration_.nanoseconds;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Duration &
|
||||
Duration::operator=(const builtin_interfaces::msg::Duration & duration_msg)
|
||||
{
|
||||
if (duration_msg.sec < 0) {
|
||||
throw std::runtime_error("cannot store a negative duration point in rclcpp::Duration");
|
||||
}
|
||||
rcl_duration_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(duration_msg.sec));
|
||||
rcl_duration_.nanoseconds += duration_msg.nanosec;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
Duration::operator==(const rclcpp::Duration & rhs) const
|
||||
{
|
||||
return rcl_duration_.nanoseconds == rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
|
||||
bool
|
||||
Duration::operator<(const rclcpp::Duration & rhs) const
|
||||
{
|
||||
return rcl_duration_.nanoseconds < rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
|
||||
bool
|
||||
Duration::operator<=(const rclcpp::Duration & rhs) const
|
||||
{
|
||||
return rcl_duration_.nanoseconds <= rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
|
||||
bool
|
||||
Duration::operator>=(const rclcpp::Duration & rhs) const
|
||||
{
|
||||
return rcl_duration_.nanoseconds >= rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
|
||||
bool
|
||||
Duration::operator>(const rclcpp::Duration & rhs) const
|
||||
{
|
||||
return rcl_duration_.nanoseconds > rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
|
||||
void
|
||||
bounds_check_duration_sum(int64_t lhsns, int64_t rhsns, uint64_t max)
|
||||
{
|
||||
auto abs_lhs = (uint64_t)std::abs(lhsns);
|
||||
auto abs_rhs = (uint64_t)std::abs(rhsns);
|
||||
|
||||
if (lhsns > 0 && rhsns > 0) {
|
||||
if (abs_lhs + abs_rhs > (uint64_t) max) {
|
||||
throw std::overflow_error("addition leads to int64_t overflow");
|
||||
}
|
||||
} else if (lhsns < 0 && rhsns < 0) {
|
||||
if (abs_lhs + abs_rhs > (uint64_t) max) {
|
||||
throw std::underflow_error("addition leads to int64_t underflow");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Duration
|
||||
Duration::operator+(const rclcpp::Duration & rhs) const
|
||||
{
|
||||
bounds_check_duration_sum(
|
||||
this->rcl_duration_.nanoseconds,
|
||||
rhs.rcl_duration_.nanoseconds,
|
||||
std::numeric_limits<rcl_duration_value_t>::max());
|
||||
return Duration(
|
||||
rcl_duration_.nanoseconds + rhs.rcl_duration_.nanoseconds);
|
||||
}
|
||||
|
||||
void
|
||||
bounds_check_duration_difference(int64_t lhsns, int64_t rhsns, uint64_t max)
|
||||
{
|
||||
auto abs_lhs = (uint64_t)std::abs(lhsns);
|
||||
auto abs_rhs = (uint64_t)std::abs(rhsns);
|
||||
|
||||
if (lhsns > 0 && rhsns < 0) {
|
||||
if (abs_lhs + abs_rhs > (uint64_t) max) {
|
||||
throw std::overflow_error("duration subtraction leads to int64_t overflow");
|
||||
}
|
||||
} else if (lhsns < 0 && rhsns > 0) {
|
||||
if (abs_lhs + abs_rhs > (uint64_t) max) {
|
||||
throw std::underflow_error("duration subtraction leads to int64_t underflow");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Duration
|
||||
Duration::operator-(const rclcpp::Duration & rhs) const
|
||||
{
|
||||
bounds_check_duration_difference(
|
||||
this->rcl_duration_.nanoseconds,
|
||||
rhs.rcl_duration_.nanoseconds,
|
||||
std::numeric_limits<rcl_duration_value_t>::max());
|
||||
|
||||
return Duration(
|
||||
rcl_duration_.nanoseconds - rhs.rcl_duration_.nanoseconds);
|
||||
}
|
||||
|
||||
rcl_duration_value_t
|
||||
Duration::nanoseconds() const
|
||||
{
|
||||
return rcl_duration_.nanoseconds;
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace event
|
||||
{
|
||||
|
||||
Event::Event()
|
||||
: state_(false) {}
|
||||
@@ -40,5 +38,4 @@ Event::check_and_clear()
|
||||
return state_.exchange(false);
|
||||
}
|
||||
|
||||
} // namespace event
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -18,18 +18,40 @@
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace exceptions
|
||||
{
|
||||
|
||||
std::string
|
||||
NameValidationError::format_error(
|
||||
const char * name_type,
|
||||
const char * name,
|
||||
const char * error_msg,
|
||||
size_t invalid_index)
|
||||
{
|
||||
std::string msg = "";
|
||||
msg += "Invalid "s + name_type + ": " + error_msg + ":\n";
|
||||
msg += " '"s + name + "'\n";
|
||||
msg += " "s + std::string(invalid_index, ' ') + "^\n";
|
||||
return msg;
|
||||
}
|
||||
|
||||
void
|
||||
throw_from_rcl_error(rcl_ret_t ret, const std::string & prefix, bool reset_error)
|
||||
throw_from_rcl_error(
|
||||
rcl_ret_t ret,
|
||||
const std::string & prefix,
|
||||
const rcl_error_state_t * error_state,
|
||||
void (*reset_error)())
|
||||
{
|
||||
if (RCL_RET_OK == ret) {
|
||||
throw std::invalid_argument("ret is RCL_RET_OK");
|
||||
}
|
||||
const rcl_error_state_t * error_state = rcl_get_error_state();
|
||||
if (!error_state) {
|
||||
error_state = rcl_get_error_state();
|
||||
}
|
||||
if (!error_state) {
|
||||
throw std::runtime_error("rcl error state is not set");
|
||||
}
|
||||
@@ -39,7 +61,7 @@ throw_from_rcl_error(rcl_ret_t ret, const std::string & prefix, bool reset_error
|
||||
}
|
||||
RCLErrorBase base_exc(ret, error_state);
|
||||
if (reset_error) {
|
||||
rcl_reset_error();
|
||||
reset_error();
|
||||
}
|
||||
switch (ret) {
|
||||
case RCL_RET_BAD_ALLOC:
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "rcl/allocator.h"
|
||||
#include "rcl/error_handling.h"
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/executor.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/scope_exit.hpp"
|
||||
@@ -49,41 +50,55 @@ 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(rclcpp::utilities::get_sigint_guard_condition(&waitset_));
|
||||
memory_strategy_->add_guard_condition(rclcpp::get_sigint_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();
|
||||
|
||||
if (rcl_wait_set_init(
|
||||
&waitset_, 0, 2, 0, 0, 0, allocator) != RCL_RET_OK)
|
||||
&wait_set_, 0, 2, 0, 0, 0, allocator) != RCL_RET_OK)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[rclcpp::error] failed to create waitset: %s\n", rcl_get_error_string_safe());
|
||||
"[rclcpp::error] failed to create wait set: %s\n", rcl_get_error_string_safe());
|
||||
rcl_reset_error();
|
||||
if (rcl_guard_condition_fini(&interrupt_guard_condition_) != RCL_RET_OK) {
|
||||
fprintf(stderr,
|
||||
"[rclcpp::error] failed to destroy guard condition: %s\n", rcl_get_error_string_safe());
|
||||
rcl_reset_error();
|
||||
}
|
||||
throw std::runtime_error("Failed to create waitset in Executor constructor");
|
||||
throw std::runtime_error("Failed to create wait set in Executor constructor");
|
||||
}
|
||||
}
|
||||
|
||||
Executor::~Executor()
|
||||
{
|
||||
// Finalize the waitset.
|
||||
if (rcl_wait_set_fini(&waitset_) != RCL_RET_OK) {
|
||||
// Disassocate all nodes
|
||||
for (auto & weak_node : weak_nodes_) {
|
||||
auto node = weak_node.lock();
|
||||
if (node) {
|
||||
std::atomic_bool & has_executor = node->get_associated_with_executor_atomic();
|
||||
has_executor.store(false);
|
||||
}
|
||||
}
|
||||
weak_nodes_.clear();
|
||||
|
||||
// Finalize the wait set.
|
||||
if (rcl_wait_set_fini(&wait_set_) != RCL_RET_OK) {
|
||||
fprintf(stderr,
|
||||
"[rclcpp::error] failed to destroy waitset: %s\n", rcl_get_error_string_safe());
|
||||
"[rclcpp::error] failed to destroy wait set: %s\n", rcl_get_error_string_safe());
|
||||
rcl_reset_error();
|
||||
}
|
||||
// Finalize the interrupt guard condition.
|
||||
if (rcl_guard_condition_fini(&interrupt_guard_condition_) != RCL_RET_OK) {
|
||||
fprintf(stderr,
|
||||
"[rclcpp::error] failed to destroy guard condition: %s\n", rcl_get_error_string_safe());
|
||||
rcl_reset_error();
|
||||
}
|
||||
// Remove and release the sigint guard condition
|
||||
memory_strategy_->remove_guard_condition(
|
||||
rclcpp::utilities::get_sigint_guard_condition(&waitset_));
|
||||
rclcpp::utilities::release_sigint_guard_condition(&waitset_);
|
||||
rclcpp::get_sigint_guard_condition(&wait_set_));
|
||||
rclcpp::release_sigint_guard_condition(&wait_set_);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -114,7 +129,7 @@ Executor::add_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_pt
|
||||
}
|
||||
|
||||
void
|
||||
Executor::add_node(std::shared_ptr<rclcpp::node::Node> node_ptr, bool notify)
|
||||
Executor::add_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify)
|
||||
{
|
||||
this->add_node(node_ptr->get_node_base_interface(), notify);
|
||||
}
|
||||
@@ -126,14 +141,12 @@ Executor::remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node
|
||||
weak_nodes_.erase(
|
||||
std::remove_if(
|
||||
weak_nodes_.begin(), weak_nodes_.end(),
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
[&](rclcpp::node_interfaces::NodeBaseInterface::WeakPtr & i)
|
||||
{
|
||||
bool matched = (i.lock() == node_ptr);
|
||||
node_removed |= matched;
|
||||
return matched;
|
||||
}
|
||||
// *INDENT-ON*
|
||||
)
|
||||
);
|
||||
std::atomic_bool & has_executor = node_ptr->get_associated_with_executor_atomic();
|
||||
@@ -150,7 +163,7 @@ Executor::remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node
|
||||
}
|
||||
|
||||
void
|
||||
Executor::remove_node(std::shared_ptr<rclcpp::node::Node> node_ptr, bool notify)
|
||||
Executor::remove_node(std::shared_ptr<rclcpp::Node> node_ptr, bool notify)
|
||||
{
|
||||
this->remove_node(node_ptr->get_node_base_interface(), notify);
|
||||
}
|
||||
@@ -175,7 +188,7 @@ Executor::spin_node_some(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr n
|
||||
}
|
||||
|
||||
void
|
||||
Executor::spin_node_some(std::shared_ptr<rclcpp::node::Node> node)
|
||||
Executor::spin_node_some(std::shared_ptr<rclcpp::Node> node)
|
||||
{
|
||||
this->spin_node_some(node->get_node_base_interface());
|
||||
}
|
||||
@@ -256,7 +269,7 @@ Executor::execute_any_executable(AnyExecutable::SharedPtr any_exec)
|
||||
|
||||
void
|
||||
Executor::execute_subscription(
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription)
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription)
|
||||
{
|
||||
std::shared_ptr<void> message = subscription->create_message();
|
||||
rmw_message_info_t message_info;
|
||||
@@ -270,13 +283,14 @@ Executor::execute_subscription(
|
||||
fprintf(stderr,
|
||||
"[rclcpp::error] take failed for subscription on topic '%s': %s\n",
|
||||
subscription->get_topic_name(), rcl_get_error_string_safe());
|
||||
rcl_reset_error();
|
||||
}
|
||||
subscription->return_message(message);
|
||||
}
|
||||
|
||||
void
|
||||
Executor::execute_intra_process_subscription(
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription)
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription)
|
||||
{
|
||||
rcl_interfaces::msg::IntraProcessMessage ipm;
|
||||
rmw_message_info_t message_info;
|
||||
@@ -292,19 +306,20 @@ Executor::execute_intra_process_subscription(
|
||||
fprintf(stderr,
|
||||
"[rclcpp::error] take failed for intra process subscription on topic '%s': %s\n",
|
||||
subscription->get_topic_name(), rcl_get_error_string_safe());
|
||||
rcl_reset_error();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Executor::execute_timer(
|
||||
rclcpp::timer::TimerBase::SharedPtr timer)
|
||||
rclcpp::TimerBase::SharedPtr timer)
|
||||
{
|
||||
timer->execute_callback();
|
||||
}
|
||||
|
||||
void
|
||||
Executor::execute_service(
|
||||
rclcpp::service::ServiceBase::SharedPtr service)
|
||||
rclcpp::ServiceBase::SharedPtr service)
|
||||
{
|
||||
auto request_header = service->create_request_header();
|
||||
std::shared_ptr<void> request = service->create_request();
|
||||
@@ -318,12 +333,13 @@ Executor::execute_service(
|
||||
fprintf(stderr,
|
||||
"[rclcpp::error] take request failed for server of service '%s': %s\n",
|
||||
service->get_service_name().c_str(), rcl_get_error_string_safe());
|
||||
rcl_reset_error();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Executor::execute_client(
|
||||
rclcpp::client::ClientBase::SharedPtr client)
|
||||
rclcpp::ClientBase::SharedPtr client)
|
||||
{
|
||||
auto request_header = client->create_request_header();
|
||||
std::shared_ptr<void> response = client->create_response();
|
||||
@@ -333,10 +349,11 @@ Executor::execute_client(
|
||||
response.get());
|
||||
if (status == RCL_RET_OK) {
|
||||
client->handle_response(request_header, response);
|
||||
} else if (status != RCL_RET_SERVICE_TAKE_FAILED) {
|
||||
} else if (status != RCL_RET_CLIENT_TAKE_FAILED) {
|
||||
fprintf(stderr,
|
||||
"[rclcpp::error] take response failed for client of service '%s': %s\n",
|
||||
client->get_service_name().c_str(), rcl_get_error_string_safe());
|
||||
rcl_reset_error();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,84 +369,83 @@ Executor::wait_for_work(std::chrono::nanoseconds timeout)
|
||||
weak_nodes_.erase(
|
||||
remove_if(
|
||||
weak_nodes_.begin(), weak_nodes_.end(),
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
[](rclcpp::node_interfaces::NodeBaseInterface::WeakPtr i)
|
||||
{
|
||||
return i.expired();
|
||||
}
|
||||
// *INDENT-ON*
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (rcl_wait_set_resize_subscriptions(
|
||||
&waitset_, memory_strategy_->number_of_ready_subscriptions()) != RCL_RET_OK)
|
||||
&wait_set_, memory_strategy_->number_of_ready_subscriptions()) != RCL_RET_OK)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("Couldn't resize the number of subscriptions in waitset : ") +
|
||||
std::string("Couldn't resize the number of subscriptions in wait set : ") +
|
||||
rcl_get_error_string_safe());
|
||||
}
|
||||
|
||||
if (rcl_wait_set_resize_services(
|
||||
&waitset_, memory_strategy_->number_of_ready_services()) != RCL_RET_OK)
|
||||
&wait_set_, memory_strategy_->number_of_ready_services()) != RCL_RET_OK)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("Couldn't resize the number of services in waitset : ") +
|
||||
std::string("Couldn't resize the number of services in wait set : ") +
|
||||
rcl_get_error_string_safe());
|
||||
}
|
||||
|
||||
if (rcl_wait_set_resize_clients(
|
||||
&waitset_, memory_strategy_->number_of_ready_clients()) != RCL_RET_OK)
|
||||
&wait_set_, memory_strategy_->number_of_ready_clients()) != RCL_RET_OK)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("Couldn't resize the number of clients in waitset : ") +
|
||||
std::string("Couldn't resize the number of clients in wait set : ") +
|
||||
rcl_get_error_string_safe());
|
||||
}
|
||||
|
||||
if (rcl_wait_set_resize_guard_conditions(
|
||||
&waitset_, memory_strategy_->number_of_guard_conditions()) != RCL_RET_OK)
|
||||
&wait_set_, memory_strategy_->number_of_guard_conditions()) != RCL_RET_OK)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("Couldn't resize the number of guard_conditions in waitset : ") +
|
||||
std::string("Couldn't resize the number of guard_conditions in wait set : ") +
|
||||
rcl_get_error_string_safe());
|
||||
}
|
||||
|
||||
if (rcl_wait_set_resize_timers(
|
||||
&waitset_, memory_strategy_->number_of_ready_timers()) != RCL_RET_OK)
|
||||
&wait_set_, memory_strategy_->number_of_ready_timers()) != RCL_RET_OK)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("Couldn't resize the number of timers in waitset : ") +
|
||||
std::string("Couldn't resize the number of timers in wait set : ") +
|
||||
rcl_get_error_string_safe());
|
||||
}
|
||||
|
||||
if (!memory_strategy_->add_handles_to_waitset(&waitset_)) {
|
||||
throw std::runtime_error("Couldn't fill waitset");
|
||||
if (!memory_strategy_->add_handles_to_wait_set(&wait_set_)) {
|
||||
throw std::runtime_error("Couldn't fill wait set");
|
||||
}
|
||||
rcl_ret_t status =
|
||||
rcl_wait(&waitset_, std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count());
|
||||
rcl_wait(&wait_set_, std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count());
|
||||
if (status == RCL_RET_WAIT_SET_EMPTY) {
|
||||
fprintf(stderr, "Warning: empty waitset received in rcl_wait(). This should never happen.\n");
|
||||
fprintf(stderr, "Warning: empty wait set received in rcl_wait(). This should never happen.\n");
|
||||
} else if (status != RCL_RET_OK && status != RCL_RET_TIMEOUT) {
|
||||
throw std::runtime_error(std::string("rcl_wait() failed: ") + rcl_get_error_string_safe());
|
||||
using rclcpp::exceptions::throw_from_rcl_error;
|
||||
throw_from_rcl_error(status, "rcl_wait() failed");
|
||||
}
|
||||
|
||||
// check the null handles in the waitset and remove them from the handles in memory strategy
|
||||
// check the null handles in the wait set and remove them from the handles in memory strategy
|
||||
// for callback-based entities
|
||||
memory_strategy_->remove_null_handles(&waitset_);
|
||||
if (rcl_wait_set_clear_subscriptions(&waitset_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear subscriptions from waitset");
|
||||
memory_strategy_->remove_null_handles(&wait_set_);
|
||||
if (rcl_wait_set_clear_subscriptions(&wait_set_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear subscriptions from wait set");
|
||||
}
|
||||
if (rcl_wait_set_clear_services(&waitset_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear servicess from waitset");
|
||||
if (rcl_wait_set_clear_services(&wait_set_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear servicess from wait set");
|
||||
}
|
||||
if (rcl_wait_set_clear_clients(&waitset_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear clients from waitset");
|
||||
if (rcl_wait_set_clear_clients(&wait_set_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear clients from wait set");
|
||||
}
|
||||
if (rcl_wait_set_clear_guard_conditions(&waitset_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear guard conditions from waitset");
|
||||
if (rcl_wait_set_clear_guard_conditions(&wait_set_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear guard conditions from wait set");
|
||||
}
|
||||
if (rcl_wait_set_clear_timers(&waitset_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear timers from waitset");
|
||||
if (rcl_wait_set_clear_timers(&wait_set_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear timers from wait set");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,7 +471,7 @@ Executor::get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr gro
|
||||
}
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
Executor::get_group_by_timer(rclcpp::timer::TimerBase::SharedPtr timer)
|
||||
Executor::get_group_by_timer(rclcpp::TimerBase::SharedPtr timer)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes_) {
|
||||
auto node = weak_node.lock();
|
||||
|
||||
@@ -22,7 +22,7 @@ rclcpp::spin_some(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr
|
||||
}
|
||||
|
||||
void
|
||||
rclcpp::spin_some(rclcpp::node::Node::SharedPtr node_ptr)
|
||||
rclcpp::spin_some(rclcpp::Node::SharedPtr node_ptr)
|
||||
{
|
||||
rclcpp::spin_some(node_ptr->get_node_base_interface());
|
||||
}
|
||||
@@ -37,7 +37,7 @@ rclcpp::spin(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr)
|
||||
}
|
||||
|
||||
void
|
||||
rclcpp::spin(rclcpp::node::Node::SharedPtr node_ptr)
|
||||
rclcpp::spin(rclcpp::Node::SharedPtr node_ptr)
|
||||
{
|
||||
rclcpp::spin(node_ptr->get_node_base_interface());
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp/scope_exit.hpp"
|
||||
|
||||
using rclcpp::executors::multi_threaded_executor::MultiThreadedExecutor;
|
||||
using rclcpp::executors::MultiThreadedExecutor;
|
||||
|
||||
MultiThreadedExecutor::MultiThreadedExecutor(const rclcpp::executor::ExecutorArgs & args)
|
||||
: executor::Executor(args)
|
||||
@@ -66,11 +66,11 @@ MultiThreadedExecutor::get_number_of_threads()
|
||||
void
|
||||
MultiThreadedExecutor::run(size_t)
|
||||
{
|
||||
while (rclcpp::utilities::ok() && spinning.load()) {
|
||||
while (rclcpp::ok() && spinning.load()) {
|
||||
executor::AnyExecutable::SharedPtr any_exec;
|
||||
{
|
||||
std::lock_guard<std::mutex> wait_lock(wait_mutex_);
|
||||
if (!rclcpp::utilities::ok() || !spinning.load()) {
|
||||
if (!rclcpp::ok() || !spinning.load()) {
|
||||
return;
|
||||
}
|
||||
any_exec = get_next_executable();
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "rclcpp/executors/single_threaded_executor.hpp"
|
||||
#include "rclcpp/scope_exit.hpp"
|
||||
|
||||
using rclcpp::executors::single_threaded_executor::SingleThreadedExecutor;
|
||||
using rclcpp::executors::SingleThreadedExecutor;
|
||||
|
||||
SingleThreadedExecutor::SingleThreadedExecutor(const rclcpp::executor::ExecutorArgs & args)
|
||||
: executor::Executor(args) {}
|
||||
@@ -26,10 +26,10 @@ void
|
||||
SingleThreadedExecutor::spin()
|
||||
{
|
||||
if (spinning.exchange(true)) {
|
||||
throw std::runtime_error("spin_some() called while already spinning");
|
||||
throw std::runtime_error("spin() called while already spinning");
|
||||
}
|
||||
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
|
||||
while (rclcpp::utilities::ok() && spinning.load()) {
|
||||
while (rclcpp::ok() && spinning.load()) {
|
||||
auto any_exec = get_next_executable();
|
||||
execute_any_executable(any_exec);
|
||||
}
|
||||
|
||||
197
rclcpp/src/rclcpp/expand_topic_or_service_name.cpp
Normal file
197
rclcpp/src/rclcpp/expand_topic_or_service_name.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "rclcpp/expand_topic_or_service_name.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "rcl/expand_topic_name.h"
|
||||
#include "rcl/validate_topic_name.h"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/scope_exit.hpp"
|
||||
#include "rcutils/types/string_map.h"
|
||||
#include "rmw/error_handling.h"
|
||||
#include "rmw/validate_namespace.h"
|
||||
#include "rmw/validate_node_name.h"
|
||||
#include "rmw/validate_full_topic_name.h"
|
||||
|
||||
using rclcpp::exceptions::throw_from_rcl_error;
|
||||
|
||||
std::string
|
||||
rclcpp::expand_topic_or_service_name(
|
||||
const std::string & name,
|
||||
const std::string & node_name,
|
||||
const std::string & namespace_,
|
||||
bool is_service)
|
||||
{
|
||||
char * expanded_topic = nullptr;
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
rcutils_allocator_t rcutils_allocator = rcutils_get_default_allocator();
|
||||
rcutils_string_map_t substitutions_map = rcutils_get_zero_initialized_string_map();
|
||||
|
||||
rcutils_ret_t rcutils_ret = rcutils_string_map_init(&substitutions_map, 0, rcutils_allocator);
|
||||
if (rcutils_ret != RCUTILS_RET_OK) {
|
||||
if (rcutils_ret == RCUTILS_RET_BAD_ALLOC) {
|
||||
throw_from_rcl_error(RCL_RET_BAD_ALLOC, "", rcutils_get_error_state(), rcutils_reset_error);
|
||||
} else {
|
||||
throw_from_rcl_error(RCL_RET_ERROR, "", rcutils_get_error_state(), rcutils_reset_error);
|
||||
}
|
||||
}
|
||||
rcl_ret_t ret = rcl_get_default_topic_name_substitutions(&substitutions_map);
|
||||
if (ret != RCL_RET_OK) {
|
||||
rcutils_error_state_t error_state;
|
||||
if (rcutils_error_state_copy(rcl_get_error_state(), &error_state) != RCUTILS_RET_OK) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
auto error_state_scope_exit = rclcpp::make_scope_exit(
|
||||
[&error_state]() {
|
||||
rcutils_error_state_fini(&error_state);
|
||||
});
|
||||
// finalize the string map before throwing
|
||||
rcutils_ret = rcutils_string_map_fini(&substitutions_map);
|
||||
if (rcutils_ret != RCUTILS_RET_OK) {
|
||||
fprintf(stderr,
|
||||
"[rclcpp|" RCUTILS_STRINGIFY(__FILE__) ":" RCUTILS_STRINGIFY(__LINE__) "]: "
|
||||
"failed to fini string_map (%d) during error handling: %s\n",
|
||||
rcutils_ret,
|
||||
rcutils_get_error_string_safe());
|
||||
rcutils_reset_error();
|
||||
}
|
||||
throw_from_rcl_error(ret, "", &error_state);
|
||||
}
|
||||
|
||||
ret = rcl_expand_topic_name(
|
||||
name.c_str(),
|
||||
node_name.c_str(),
|
||||
namespace_.c_str(),
|
||||
&substitutions_map,
|
||||
allocator,
|
||||
&expanded_topic);
|
||||
|
||||
std::string result;
|
||||
if (ret == RCL_RET_OK) {
|
||||
result = expanded_topic;
|
||||
allocator.deallocate(expanded_topic, allocator.state);
|
||||
}
|
||||
|
||||
rcutils_ret = rcutils_string_map_fini(&substitutions_map);
|
||||
if (rcutils_ret != RCUTILS_RET_OK) {
|
||||
throw_from_rcl_error(RCL_RET_ERROR, "", rcutils_get_error_state(), rcutils_reset_error);
|
||||
}
|
||||
|
||||
// expansion failed
|
||||
if (ret != RCL_RET_OK) {
|
||||
// if invalid topic or unknown substitution
|
||||
if (ret == RCL_RET_TOPIC_NAME_INVALID || ret == RCL_RET_UNKNOWN_SUBSTITUTION) {
|
||||
rcl_reset_error(); // explicitly discard error from rcl_expand_topic_name()
|
||||
int validation_result;
|
||||
size_t invalid_index;
|
||||
rcl_ret_t ret = rcl_validate_topic_name(name.c_str(), &validation_result, &invalid_index);
|
||||
if (ret != RCL_RET_OK) {
|
||||
throw_from_rcl_error(ret);
|
||||
}
|
||||
|
||||
if (validation_result == RCL_TOPIC_NAME_VALID) {
|
||||
throw std::runtime_error("topic name unexpectedly valid");
|
||||
}
|
||||
const char * validation_message = rcl_topic_name_validation_result_string(validation_result);
|
||||
if (!validation_message) {
|
||||
throw std::runtime_error("unable to get validation error message");
|
||||
}
|
||||
if (is_service) {
|
||||
using rclcpp::exceptions::InvalidServiceNameError;
|
||||
throw InvalidServiceNameError(name.c_str(), validation_message, invalid_index);
|
||||
} else {
|
||||
using rclcpp::exceptions::InvalidTopicNameError;
|
||||
throw InvalidTopicNameError(name.c_str(), validation_message, invalid_index);
|
||||
}
|
||||
// if invalid node name
|
||||
} else if (ret == RCL_RET_NODE_INVALID_NAME) {
|
||||
rcl_reset_error(); // explicitly discard error from rcl_expand_topic_name()
|
||||
int validation_result;
|
||||
size_t invalid_index;
|
||||
rmw_ret_t rmw_ret =
|
||||
rmw_validate_node_name(node_name.c_str(), &validation_result, &invalid_index);
|
||||
if (rmw_ret != RMW_RET_OK) {
|
||||
if (rmw_ret == RMW_RET_INVALID_ARGUMENT) {
|
||||
throw_from_rcl_error(
|
||||
RCL_RET_INVALID_ARGUMENT, "failed to validate node name",
|
||||
rmw_get_error_state(), rmw_reset_error);
|
||||
}
|
||||
throw_from_rcl_error(
|
||||
RCL_RET_ERROR, "failed to validate node name",
|
||||
rmw_get_error_state(), rmw_reset_error);
|
||||
}
|
||||
throw rclcpp::exceptions::InvalidNodeNameError(
|
||||
node_name.c_str(),
|
||||
rmw_node_name_validation_result_string(validation_result),
|
||||
invalid_index);
|
||||
// if invalid namespace
|
||||
} else if (ret == RCL_RET_NODE_INVALID_NAMESPACE) {
|
||||
rcl_reset_error(); // explicitly discard error from rcl_expand_topic_name()
|
||||
int validation_result;
|
||||
size_t invalid_index;
|
||||
rmw_ret_t rmw_ret =
|
||||
rmw_validate_namespace(namespace_.c_str(), &validation_result, &invalid_index);
|
||||
if (rmw_ret != RMW_RET_OK) {
|
||||
if (rmw_ret == RMW_RET_INVALID_ARGUMENT) {
|
||||
throw_from_rcl_error(
|
||||
RCL_RET_INVALID_ARGUMENT, "failed to validate namespace",
|
||||
rmw_get_error_state(), rmw_reset_error);
|
||||
}
|
||||
throw_from_rcl_error(
|
||||
RCL_RET_ERROR, "failed to validate namespace",
|
||||
rmw_get_error_state(), rmw_reset_error);
|
||||
}
|
||||
throw rclcpp::exceptions::InvalidNamespaceError(
|
||||
namespace_.c_str(),
|
||||
rmw_namespace_validation_result_string(validation_result),
|
||||
invalid_index);
|
||||
// something else happened
|
||||
} else {
|
||||
throw_from_rcl_error(ret);
|
||||
}
|
||||
}
|
||||
|
||||
// expand succeeded, but full name validation may fail still
|
||||
int validation_result;
|
||||
size_t invalid_index;
|
||||
rmw_ret_t rmw_ret =
|
||||
rmw_validate_full_topic_name(result.c_str(), &validation_result, &invalid_index);
|
||||
if (rmw_ret != RMW_RET_OK) {
|
||||
if (rmw_ret == RMW_RET_INVALID_ARGUMENT) {
|
||||
throw_from_rcl_error(
|
||||
RCL_RET_INVALID_ARGUMENT, "failed to validate full topic name",
|
||||
rmw_get_error_state(), rmw_reset_error);
|
||||
}
|
||||
throw_from_rcl_error(
|
||||
RCL_RET_ERROR, "failed to validate full topic name",
|
||||
rmw_get_error_state(), rmw_reset_error);
|
||||
}
|
||||
if (validation_result != RMW_TOPIC_VALID) {
|
||||
if (is_service) {
|
||||
throw rclcpp::exceptions::InvalidServiceNameError(
|
||||
result.c_str(),
|
||||
rmw_full_topic_name_validation_result_string(validation_result),
|
||||
invalid_index);
|
||||
} else {
|
||||
throw rclcpp::exceptions::InvalidTopicNameError(
|
||||
result.c_str(),
|
||||
rmw_full_topic_name_validation_result_string(validation_result),
|
||||
invalid_index);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -43,7 +43,7 @@ GraphListener::GraphListener()
|
||||
throw_from_rcl_error(ret, "failed to create interrupt guard condition");
|
||||
}
|
||||
|
||||
shutdown_guard_condition_ = rclcpp::utilities::get_sigint_guard_condition(&wait_set_);
|
||||
shutdown_guard_condition_ = rclcpp::get_sigint_guard_condition(&wait_set_);
|
||||
}
|
||||
|
||||
GraphListener::~GraphListener()
|
||||
@@ -75,12 +75,13 @@ GraphListener::start_if_not_started()
|
||||
// This is important to ensure that the wait set is finalized before
|
||||
// destruction of static objects occurs.
|
||||
std::weak_ptr<GraphListener> weak_this = shared_from_this();
|
||||
rclcpp::utilities::on_shutdown([weak_this]() {
|
||||
auto shared_this = weak_this.lock();
|
||||
if (shared_this) {
|
||||
shared_this->shutdown();
|
||||
}
|
||||
});
|
||||
rclcpp::on_shutdown(
|
||||
[weak_this]() {
|
||||
auto shared_this = weak_this.lock();
|
||||
if (shared_this) {
|
||||
shared_this->shutdown();
|
||||
}
|
||||
});
|
||||
// Start the listener thread.
|
||||
listener_thread_ = std::thread(&GraphListener::run, this);
|
||||
is_started_ = true;
|
||||
@@ -334,7 +335,7 @@ GraphListener::shutdown()
|
||||
throw_from_rcl_error(ret, "failed to finalize interrupt guard condition");
|
||||
}
|
||||
if (shutdown_guard_condition_) {
|
||||
rclcpp::utilities::release_sigint_guard_condition(&wait_set_);
|
||||
rclcpp::release_sigint_guard_condition(&wait_set_);
|
||||
shutdown_guard_condition_ = nullptr;
|
||||
}
|
||||
if (is_started_) {
|
||||
|
||||
@@ -31,7 +31,7 @@ IntraProcessManager::~IntraProcessManager()
|
||||
|
||||
uint64_t
|
||||
IntraProcessManager::add_subscription(
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription)
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription)
|
||||
{
|
||||
auto id = IntraProcessManager::get_next_unique_id();
|
||||
impl_->add_subscription(id, subscription);
|
||||
|
||||
33
rclcpp/src/rclcpp/logger.cpp
Normal file
33
rclcpp/src/rclcpp/logger.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/logger.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
rclcpp::Logger
|
||||
get_logger(const std::string & name)
|
||||
{
|
||||
#if RCLCPP_LOGGING_ENABLED
|
||||
return rclcpp::Logger(name);
|
||||
#else
|
||||
(void)name;
|
||||
return rclcpp::Logger();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
using rclcpp::memory_strategy::MemoryStrategy;
|
||||
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr
|
||||
rclcpp::SubscriptionBase::SharedPtr
|
||||
MemoryStrategy::get_subscription_by_handle(
|
||||
const rcl_subscription_t * subscriber_handle, const WeakNodeVector & weak_nodes)
|
||||
{
|
||||
@@ -46,8 +46,9 @@ MemoryStrategy::get_subscription_by_handle(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rclcpp::service::ServiceBase::SharedPtr
|
||||
MemoryStrategy::get_service_by_handle(const rcl_service_t * service_handle,
|
||||
rclcpp::ServiceBase::SharedPtr
|
||||
MemoryStrategy::get_service_by_handle(
|
||||
const rcl_service_t * service_handle,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
@@ -71,8 +72,9 @@ MemoryStrategy::get_service_by_handle(const rcl_service_t * service_handle,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rclcpp::client::ClientBase::SharedPtr
|
||||
MemoryStrategy::get_client_by_handle(const rcl_client_t * client_handle,
|
||||
rclcpp::ClientBase::SharedPtr
|
||||
MemoryStrategy::get_client_by_handle(
|
||||
const rcl_client_t * client_handle,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
@@ -97,7 +99,8 @@ MemoryStrategy::get_client_by_handle(const rcl_client_t * client_handle,
|
||||
}
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
MemoryStrategy::get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
MemoryStrategy::get_node_by_group(
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
{
|
||||
if (!group) {
|
||||
@@ -120,7 +123,7 @@ MemoryStrategy::get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedP
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_subscription(
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
@@ -146,7 +149,7 @@ MemoryStrategy::get_group_by_subscription(
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_service(
|
||||
rclcpp::service::ServiceBase::SharedPtr service,
|
||||
rclcpp::ServiceBase::SharedPtr service,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
@@ -172,7 +175,7 @@ MemoryStrategy::get_group_by_service(
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_client(
|
||||
rclcpp::client::ClientBase::SharedPtr client,
|
||||
rclcpp::ClientBase::SharedPtr client,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
|
||||
@@ -24,28 +24,36 @@
|
||||
#include "rclcpp/graph_listener.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base.hpp"
|
||||
#include "rclcpp/node_interfaces/node_clock.hpp"
|
||||
#include "rclcpp/node_interfaces/node_graph.hpp"
|
||||
#include "rclcpp/node_interfaces/node_logging.hpp"
|
||||
#include "rclcpp/node_interfaces/node_parameters.hpp"
|
||||
#include "rclcpp/node_interfaces/node_services.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics.hpp"
|
||||
|
||||
using rclcpp::node::Node;
|
||||
using rclcpp::Node;
|
||||
using rclcpp::exceptions::throw_from_rcl_error;
|
||||
|
||||
Node::Node(const std::string & node_name, bool use_intra_process_comms)
|
||||
Node::Node(
|
||||
const std::string & node_name,
|
||||
const std::string & namespace_,
|
||||
bool use_intra_process_comms)
|
||||
: Node(
|
||||
node_name,
|
||||
namespace_,
|
||||
rclcpp::contexts::default_context::get_global_default_context(),
|
||||
use_intra_process_comms)
|
||||
{}
|
||||
|
||||
Node::Node(
|
||||
const std::string & node_name,
|
||||
rclcpp::context::Context::SharedPtr context,
|
||||
const std::string & namespace_,
|
||||
rclcpp::Context::SharedPtr context,
|
||||
bool use_intra_process_comms)
|
||||
: node_base_(new rclcpp::node_interfaces::NodeBase(node_name, context)),
|
||||
: node_base_(new rclcpp::node_interfaces::NodeBase(node_name, namespace_, context)),
|
||||
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_services_(new rclcpp::node_interfaces::NodeServices(node_base_.get())),
|
||||
@@ -53,6 +61,12 @@ Node::Node(
|
||||
node_topics_.get(),
|
||||
use_intra_process_comms
|
||||
)),
|
||||
node_clock_(new rclcpp::node_interfaces::NodeClock(
|
||||
node_base_,
|
||||
node_topics_,
|
||||
node_graph_,
|
||||
node_services_
|
||||
)),
|
||||
use_intra_process_comms_(use_intra_process_comms)
|
||||
{
|
||||
}
|
||||
@@ -66,6 +80,18 @@ Node::get_name() const
|
||||
return node_base_->get_name();
|
||||
}
|
||||
|
||||
const char *
|
||||
Node::get_namespace() const
|
||||
{
|
||||
return node_base_->get_namespace();
|
||||
}
|
||||
|
||||
rclcpp::Logger
|
||||
Node::get_logger() const
|
||||
{
|
||||
return node_logging_->get_logger();
|
||||
}
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
Node::create_callback_group(
|
||||
rclcpp::callback_group::CallbackGroupType group_type)
|
||||
@@ -106,7 +132,8 @@ Node::get_parameter(const std::string & name) const
|
||||
return node_parameters_->get_parameter(name);
|
||||
}
|
||||
|
||||
bool Node::get_parameter(const std::string & name,
|
||||
bool Node::get_parameter(
|
||||
const std::string & name,
|
||||
rclcpp::parameter::ParameterVariant & parameter) const
|
||||
{
|
||||
return node_parameters_->get_parameter(name, parameter);
|
||||
@@ -133,12 +160,18 @@ Node::list_parameters(
|
||||
return node_parameters_->list_parameters(prefixes, depth);
|
||||
}
|
||||
|
||||
std::map<std::string, std::string>
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
Node::get_topic_names_and_types() const
|
||||
{
|
||||
return node_graph_->get_topic_names_and_types();
|
||||
}
|
||||
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
Node::get_service_names_and_types() const
|
||||
{
|
||||
return node_graph_->get_service_names_and_types();
|
||||
}
|
||||
|
||||
size_t
|
||||
Node::count_publishers(const std::string & topic_name) const
|
||||
{
|
||||
@@ -157,7 +190,7 @@ Node::get_callback_groups() const
|
||||
return node_base_->get_callback_groups();
|
||||
}
|
||||
|
||||
rclcpp::event::Event::SharedPtr
|
||||
rclcpp::Event::SharedPtr
|
||||
Node::get_graph_event()
|
||||
{
|
||||
return node_graph_->get_graph_event();
|
||||
@@ -165,18 +198,36 @@ Node::get_graph_event()
|
||||
|
||||
void
|
||||
Node::wait_for_graph_change(
|
||||
rclcpp::event::Event::SharedPtr event,
|
||||
rclcpp::Event::SharedPtr event,
|
||||
std::chrono::nanoseconds timeout)
|
||||
{
|
||||
node_graph_->wait_for_graph_change(event, timeout);
|
||||
}
|
||||
|
||||
rclcpp::Clock::SharedPtr
|
||||
Node::get_clock()
|
||||
{
|
||||
return node_clock_->get_clock();
|
||||
}
|
||||
|
||||
rclcpp::Time
|
||||
Node::now()
|
||||
{
|
||||
return node_clock_->get_clock()->now();
|
||||
}
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
Node::get_node_base_interface()
|
||||
{
|
||||
return node_base_;
|
||||
}
|
||||
|
||||
rclcpp::node_interfaces::NodeClockInterface::SharedPtr
|
||||
Node::get_node_clock_interface()
|
||||
{
|
||||
return node_clock_;
|
||||
}
|
||||
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr
|
||||
Node::get_node_graph_interface()
|
||||
{
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "rclcpp/node_interfaces/node_base.hpp"
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rmw/validate_node_name.h"
|
||||
#include "rmw/validate_namespace.h"
|
||||
|
||||
using rclcpp::exceptions::throw_from_rcl_error;
|
||||
|
||||
@@ -27,7 +29,8 @@ using rclcpp::node_interfaces::NodeBase;
|
||||
|
||||
NodeBase::NodeBase(
|
||||
const std::string & node_name,
|
||||
rclcpp::context::Context::SharedPtr context)
|
||||
const std::string & namespace_,
|
||||
rclcpp::Context::SharedPtr context)
|
||||
: context_(context),
|
||||
node_handle_(nullptr),
|
||||
default_callback_group_(nullptr),
|
||||
@@ -84,21 +87,61 @@ NodeBase::NodeBase(
|
||||
rcl_node_options_t options = rcl_node_get_default_options();
|
||||
// TODO(wjwwood): pass the Allocator to the options
|
||||
options.domain_id = domain_id;
|
||||
ret = rcl_node_init(rcl_node, node_name.c_str(), &options);
|
||||
ret = rcl_node_init(rcl_node, node_name.c_str(), namespace_.c_str(), &options);
|
||||
if (ret != RCL_RET_OK) {
|
||||
// Finalize the interrupt guard condition.
|
||||
finalize_notify_guard_condition();
|
||||
|
||||
delete rcl_node;
|
||||
|
||||
if (ret == RCL_RET_NODE_INVALID_NAME) {
|
||||
rcl_reset_error(); // discard rcl_node_init error
|
||||
int validation_result;
|
||||
size_t invalid_index;
|
||||
rmw_ret_t rmw_ret =
|
||||
rmw_validate_node_name(node_name.c_str(), &validation_result, &invalid_index);
|
||||
if (rmw_ret != RMW_RET_OK) {
|
||||
if (rmw_ret == RMW_RET_INVALID_ARGUMENT) {
|
||||
throw_from_rcl_error(RCL_RET_INVALID_ARGUMENT, "failed to validate node name");
|
||||
}
|
||||
throw_from_rcl_error(RCL_RET_ERROR, "failed to validate node name");
|
||||
}
|
||||
throw rclcpp::exceptions::InvalidNodeNameError(
|
||||
node_name.c_str(),
|
||||
rmw_node_name_validation_result_string(validation_result),
|
||||
invalid_index);
|
||||
}
|
||||
|
||||
if (ret == RCL_RET_NODE_INVALID_NAMESPACE) {
|
||||
rcl_reset_error(); // discard rcl_node_init error
|
||||
int validation_result;
|
||||
size_t invalid_index;
|
||||
rmw_ret_t rmw_ret =
|
||||
rmw_validate_namespace(namespace_.c_str(), &validation_result, &invalid_index);
|
||||
if (rmw_ret != RMW_RET_OK) {
|
||||
if (rmw_ret == RMW_RET_INVALID_ARGUMENT) {
|
||||
throw_from_rcl_error(RCL_RET_INVALID_ARGUMENT, "failed to validate namespace");
|
||||
}
|
||||
throw_from_rcl_error(RCL_RET_ERROR, "failed to validate namespace");
|
||||
}
|
||||
throw rclcpp::exceptions::InvalidNamespaceError(
|
||||
namespace_.c_str(),
|
||||
rmw_namespace_validation_result_string(validation_result),
|
||||
invalid_index);
|
||||
}
|
||||
|
||||
throw_from_rcl_error(ret, "failed to initialize rcl node");
|
||||
}
|
||||
|
||||
node_handle_.reset(rcl_node, [](rcl_node_t * node) -> void {
|
||||
if (rcl_node_fini(node) != RCL_RET_OK) {
|
||||
fprintf(
|
||||
stderr, "Error in destruction of rcl node handle: %s\n", rcl_get_error_string_safe());
|
||||
}
|
||||
delete node;
|
||||
});
|
||||
node_handle_.reset(
|
||||
rcl_node,
|
||||
[](rcl_node_t * node) -> void {
|
||||
if (rcl_node_fini(node) != RCL_RET_OK) {
|
||||
fprintf(
|
||||
stderr, "Error in destruction of rcl node handle: %s\n", rcl_get_error_string_safe());
|
||||
}
|
||||
delete node;
|
||||
});
|
||||
|
||||
// Create the default callback group.
|
||||
using rclcpp::callback_group::CallbackGroupType;
|
||||
@@ -127,7 +170,13 @@ NodeBase::get_name() const
|
||||
return rcl_node_get_name(node_handle_.get());
|
||||
}
|
||||
|
||||
rclcpp::context::Context::SharedPtr
|
||||
const char *
|
||||
NodeBase::get_namespace() const
|
||||
{
|
||||
return rcl_node_get_namespace(node_handle_.get());
|
||||
}
|
||||
|
||||
rclcpp::Context::SharedPtr
|
||||
NodeBase::get_context()
|
||||
{
|
||||
return context_;
|
||||
|
||||
48
rclcpp/src/rclcpp/node_interfaces/node_clock.cpp
Normal file
48
rclcpp/src/rclcpp/node_interfaces/node_clock.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "rclcpp/node_interfaces/node_clock.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
using rclcpp::node_interfaces::NodeClock;
|
||||
|
||||
NodeClock::NodeClock(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
|
||||
rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services)
|
||||
: node_base_(node_base),
|
||||
node_topics_(node_topics),
|
||||
node_graph_(node_graph),
|
||||
node_services_(node_services),
|
||||
ros_clock_(std::make_shared<rclcpp::Clock>(RCL_ROS_TIME))
|
||||
{
|
||||
time_source_.attachNode(
|
||||
node_base_,
|
||||
node_topics_,
|
||||
node_graph_,
|
||||
node_services_);
|
||||
time_source_.attachClock(ros_clock_);
|
||||
}
|
||||
|
||||
NodeClock::~NodeClock()
|
||||
{}
|
||||
|
||||
std::shared_ptr<rclcpp::Clock>
|
||||
NodeClock::get_clock()
|
||||
{
|
||||
return ros_clock_;
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/graph.h"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
@@ -44,44 +45,137 @@ NodeGraph::~NodeGraph()
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, std::string>
|
||||
NodeGraph::get_topic_names_and_types() const
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
NodeGraph::get_topic_names_and_types(bool no_demangle) const
|
||||
{
|
||||
rcl_topic_names_and_types_t topic_names_and_types =
|
||||
rcl_get_zero_initialized_topic_names_and_types();
|
||||
rcl_names_and_types_t topic_names_and_types = rcl_get_zero_initialized_names_and_types();
|
||||
|
||||
auto ret = rcl_get_topic_names_and_types(node_base_->get_rcl_node_handle(),
|
||||
&topic_names_and_types);
|
||||
if (ret != RMW_RET_OK) {
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto ret = rcl_get_topic_names_and_types(
|
||||
node_base_->get_rcl_node_handle(),
|
||||
&allocator,
|
||||
no_demangle,
|
||||
&topic_names_and_types);
|
||||
if (ret != RCL_RET_OK) {
|
||||
auto error_msg = std::string("failed to get topic names and types: ") +
|
||||
rcl_get_error_string_safe();
|
||||
rcl_reset_error();
|
||||
if (rcl_names_and_types_fini(&topic_names_and_types) != RCL_RET_OK) {
|
||||
error_msg += std::string(", failed also to cleanup topic names and types, leaking memory: ") +
|
||||
rcl_get_error_string_safe();
|
||||
}
|
||||
throw std::runtime_error(error_msg + rcl_get_error_string_safe());
|
||||
}
|
||||
|
||||
std::map<std::string, std::vector<std::string>> topics_and_types;
|
||||
for (size_t i = 0; i < topic_names_and_types.names.size; ++i) {
|
||||
std::string topic_name = topic_names_and_types.names.data[i];
|
||||
for (size_t j = 0; j < topic_names_and_types.types[i].size; ++j) {
|
||||
topics_and_types[topic_name].emplace_back(topic_names_and_types.types[i].data[j]);
|
||||
}
|
||||
}
|
||||
|
||||
ret = rcl_names_and_types_fini(&topic_names_and_types);
|
||||
if (ret != RCL_RET_OK) {
|
||||
// *INDENT-OFF*
|
||||
throw std::runtime_error(
|
||||
std::string("could not get topic names and types: ") + rmw_get_error_string_safe());
|
||||
std::string("could not destroy topic names and types: ") + rcl_get_error_string_safe());
|
||||
// *INDENT-ON*
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> topics;
|
||||
for (size_t i = 0; i < topic_names_and_types.topic_count; ++i) {
|
||||
topics[topic_names_and_types.topic_names[i]] = topic_names_and_types.type_names[i];
|
||||
return topics_and_types;
|
||||
}
|
||||
|
||||
std::map<std::string, std::vector<std::string>>
|
||||
NodeGraph::get_service_names_and_types() const
|
||||
{
|
||||
rcl_names_and_types_t service_names_and_types = rcl_get_zero_initialized_names_and_types();
|
||||
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto ret = rcl_get_service_names_and_types(
|
||||
node_base_->get_rcl_node_handle(),
|
||||
&allocator,
|
||||
&service_names_and_types);
|
||||
if (ret != RCL_RET_OK) {
|
||||
auto error_msg = std::string("failed to get service names and types: ") +
|
||||
rcl_get_error_string_safe();
|
||||
rcl_reset_error();
|
||||
if (rcl_names_and_types_fini(&service_names_and_types) != RCL_RET_OK) {
|
||||
error_msg +=
|
||||
std::string(", failed also to cleanup service names and types, leaking memory: ") +
|
||||
rcl_get_error_string_safe();
|
||||
}
|
||||
throw std::runtime_error(error_msg + rcl_get_error_string_safe());
|
||||
}
|
||||
|
||||
ret = rmw_destroy_topic_names_and_types(&topic_names_and_types);
|
||||
if (ret != RMW_RET_OK) {
|
||||
std::map<std::string, std::vector<std::string>> services_and_types;
|
||||
for (size_t i = 0; i < service_names_and_types.names.size; ++i) {
|
||||
std::string service_name = service_names_and_types.names.data[i];
|
||||
for (size_t j = 0; j < service_names_and_types.types[i].size; ++j) {
|
||||
services_and_types[service_name].emplace_back(service_names_and_types.types[i].data[j]);
|
||||
}
|
||||
}
|
||||
|
||||
ret = rcl_names_and_types_fini(&service_names_and_types);
|
||||
if (ret != RCL_RET_OK) {
|
||||
// *INDENT-OFF*
|
||||
throw std::runtime_error(
|
||||
std::string("could not destroy topic names and types: ") + rmw_get_error_string_safe());
|
||||
std::string("could not destroy service names and types: ") + rcl_get_error_string_safe());
|
||||
// *INDENT-ON*
|
||||
}
|
||||
|
||||
return topics;
|
||||
return services_and_types;
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
NodeGraph::get_node_names() const
|
||||
{
|
||||
rcutils_string_array_t node_names_c =
|
||||
rcutils_get_zero_initialized_string_array();
|
||||
|
||||
auto allocator = rcl_get_default_allocator();
|
||||
auto ret = rcl_get_node_names(
|
||||
node_base_->get_rcl_node_handle(),
|
||||
allocator,
|
||||
&node_names_c);
|
||||
if (ret != RCL_RET_OK) {
|
||||
auto error_msg = std::string("failed to get node names: ") + rcl_get_error_string_safe();
|
||||
rcl_reset_error();
|
||||
if (rcutils_string_array_fini(&node_names_c) != RCUTILS_RET_OK) {
|
||||
error_msg += std::string(", failed also to cleanup node names, leaking memory: ") +
|
||||
rcl_get_error_string_safe();
|
||||
}
|
||||
// TODO(karsten1987): Append rcutils_error_message once it's in master
|
||||
throw std::runtime_error(error_msg);
|
||||
}
|
||||
|
||||
std::vector<std::string> node_names(&node_names_c.data[0],
|
||||
&node_names_c.data[0 + node_names_c.size]);
|
||||
ret = rcutils_string_array_fini(&node_names_c);
|
||||
if (ret != RCUTILS_RET_OK) {
|
||||
// *INDENT-OFF*
|
||||
// TODO(karsten1987): Append rcutils_error_message once it's in master
|
||||
throw std::runtime_error(
|
||||
std::string("could not destroy node names: "));
|
||||
// *INDENT-ON*
|
||||
}
|
||||
|
||||
return node_names;
|
||||
}
|
||||
|
||||
size_t
|
||||
NodeGraph::count_publishers(const std::string & topic_name) const
|
||||
{
|
||||
auto rmw_node_handle = rcl_node_get_rmw_handle(node_base_->get_rcl_node_handle());
|
||||
auto fqdn = rclcpp::expand_topic_or_service_name(
|
||||
topic_name,
|
||||
rmw_node_handle->name,
|
||||
rmw_node_handle->namespace_,
|
||||
false); // false = not a service
|
||||
|
||||
size_t count;
|
||||
// TODO(wjwwood): use the rcl equivalent methods
|
||||
auto ret = rmw_count_publishers(rcl_node_get_rmw_handle(node_base_->get_rcl_node_handle()),
|
||||
topic_name.c_str(), &count);
|
||||
auto ret = rmw_count_publishers(rmw_node_handle, fqdn.c_str(), &count);
|
||||
if (ret != RMW_RET_OK) {
|
||||
// *INDENT-OFF*
|
||||
throw std::runtime_error(
|
||||
@@ -94,10 +188,16 @@ NodeGraph::count_publishers(const std::string & topic_name) const
|
||||
size_t
|
||||
NodeGraph::count_subscribers(const std::string & topic_name) const
|
||||
{
|
||||
auto rmw_node_handle = rcl_node_get_rmw_handle(node_base_->get_rcl_node_handle());
|
||||
auto fqdn = rclcpp::expand_topic_or_service_name(
|
||||
topic_name,
|
||||
rmw_node_handle->name,
|
||||
rmw_node_handle->namespace_,
|
||||
false); // false = not a service
|
||||
|
||||
size_t count;
|
||||
// TODO(wjwwood): use the rcl equivalent methods
|
||||
auto ret = rmw_count_subscribers(rcl_node_get_rmw_handle(node_base_->get_rcl_node_handle()),
|
||||
topic_name.c_str(), &count);
|
||||
auto ret = rmw_count_subscribers(rmw_node_handle, fqdn.c_str(), &count);
|
||||
if (ret != RMW_RET_OK) {
|
||||
// *INDENT-OFF*
|
||||
throw std::runtime_error(
|
||||
@@ -133,9 +233,9 @@ NodeGraph::notify_graph_change()
|
||||
std::remove_if(
|
||||
graph_events_.begin(),
|
||||
graph_events_.end(),
|
||||
[](const rclcpp::event::Event::WeakPtr & wptr) {
|
||||
return wptr.expired();
|
||||
}),
|
||||
[](const rclcpp::Event::WeakPtr & wptr) {
|
||||
return wptr.expired();
|
||||
}),
|
||||
graph_events_.end());
|
||||
// update graph_users_count_
|
||||
graph_users_count_.store(graph_events_.size());
|
||||
@@ -158,24 +258,24 @@ NodeGraph::notify_shutdown()
|
||||
graph_cv_.notify_all();
|
||||
}
|
||||
|
||||
rclcpp::event::Event::SharedPtr
|
||||
rclcpp::Event::SharedPtr
|
||||
NodeGraph::get_graph_event()
|
||||
{
|
||||
auto event = rclcpp::event::Event::make_shared();
|
||||
auto event = rclcpp::Event::make_shared();
|
||||
std::lock_guard<std::mutex> graph_changed_lock(graph_mutex_);
|
||||
graph_events_.push_back(event);
|
||||
graph_users_count_++;
|
||||
// on first call, add node to graph_listener_
|
||||
if (should_add_to_graph_listener_.exchange(false)) {
|
||||
graph_listener_->add_node(this);
|
||||
graph_listener_->start_if_not_started();
|
||||
}
|
||||
graph_events_.push_back(event);
|
||||
graph_users_count_++;
|
||||
return event;
|
||||
}
|
||||
|
||||
void
|
||||
NodeGraph::wait_for_graph_change(
|
||||
rclcpp::event::Event::SharedPtr event,
|
||||
rclcpp::Event::SharedPtr event,
|
||||
std::chrono::nanoseconds timeout)
|
||||
{
|
||||
using rclcpp::exceptions::InvalidEventError;
|
||||
@@ -196,10 +296,13 @@ NodeGraph::wait_for_graph_change(
|
||||
throw EventNotRegisteredError();
|
||||
}
|
||||
}
|
||||
auto pred = [&event]() {
|
||||
return event->check() || !rclcpp::ok();
|
||||
};
|
||||
std::unique_lock<std::mutex> graph_lock(graph_mutex_);
|
||||
graph_cv_.wait_for(graph_lock, timeout, [&event]() {
|
||||
return event->check() || !rclcpp::utilities::ok();
|
||||
});
|
||||
if (!pred()) {
|
||||
graph_cv_.wait_for(graph_lock, timeout, pred);
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
|
||||
34
rclcpp/src/rclcpp/node_interfaces/node_logging.cpp
Normal file
34
rclcpp/src/rclcpp/node_interfaces/node_logging.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "rclcpp/node_interfaces/node_logging.hpp"
|
||||
|
||||
using rclcpp::node_interfaces::NodeLogging;
|
||||
|
||||
NodeLogging::NodeLogging(rclcpp::node_interfaces::NodeBaseInterface * node_base)
|
||||
: node_base_(node_base)
|
||||
{
|
||||
// TODO(dhood): use the namespace (slashes converted to dots)
|
||||
logger_ = rclcpp::get_logger(node_base_->get_name());
|
||||
}
|
||||
|
||||
NodeLogging::~NodeLogging()
|
||||
{
|
||||
}
|
||||
|
||||
rclcpp::Logger
|
||||
NodeLogging::get_logger() const
|
||||
{
|
||||
return logger_;
|
||||
}
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "rcl_interfaces/srv/list_parameters.hpp"
|
||||
#include "rclcpp/create_publisher.hpp"
|
||||
#include "rcutils/logging_macros.h"
|
||||
#include "rmw/qos_profiles.h"
|
||||
|
||||
using rclcpp::node_interfaces::NodeParameters;
|
||||
@@ -32,7 +33,7 @@ NodeParameters::NodeParameters(
|
||||
: node_topics_(node_topics)
|
||||
{
|
||||
using MessageT = rcl_interfaces::msg::ParameterEvent;
|
||||
using PublisherT = rclcpp::publisher::Publisher<MessageT>;
|
||||
using PublisherT = rclcpp::Publisher<MessageT>;
|
||||
using AllocatorT = std::allocator<void>;
|
||||
// TODO(wjwwood): expose this allocator through the Parameter interface.
|
||||
auto allocator = std::make_shared<AllocatorT>();
|
||||
@@ -83,11 +84,18 @@ NodeParameters::set_parameters_atomically(
|
||||
for (auto p : parameters) {
|
||||
if (parameters_.find(p.get_name()) == parameters_.end()) {
|
||||
if (p.get_type() != rclcpp::parameter::ParameterType::PARAMETER_NOT_SET) {
|
||||
// case: parameter not set before, and input is something other than "NOT_SET"
|
||||
parameter_event->new_parameters.push_back(p.to_parameter());
|
||||
}
|
||||
} else if (p.get_type() != rclcpp::parameter::ParameterType::PARAMETER_NOT_SET) {
|
||||
// case: parameter was set before, and input is something other than "NOT_SET"
|
||||
parameter_event->changed_parameters.push_back(p.to_parameter());
|
||||
} else {
|
||||
// case: parameter was set before, and input is "NOT_SET"
|
||||
// therefore we will "unset" the previously set parameter
|
||||
// it is not necessary to erase the parameter from parameters_
|
||||
// because the new value for this key (p.get_name()) will be a
|
||||
// ParameterVariant with type "NOT_SET"
|
||||
parameter_event->deleted_parameters.push_back(p.to_parameter());
|
||||
}
|
||||
tmp_map[p.get_name()] = p;
|
||||
@@ -111,8 +119,8 @@ NodeParameters::get_parameters(const std::vector<std::string> & names) const
|
||||
for (auto & name : names) {
|
||||
if (std::any_of(parameters_.cbegin(), parameters_.cend(),
|
||||
[&name](const std::pair<std::string, rclcpp::parameter::ParameterVariant> & kv) {
|
||||
return name == kv.first;
|
||||
}))
|
||||
return name == kv.first;
|
||||
}))
|
||||
{
|
||||
results.push_back(parameters_.at(name));
|
||||
}
|
||||
@@ -154,8 +162,8 @@ NodeParameters::describe_parameters(const std::vector<std::string> & names) cons
|
||||
std::vector<rcl_interfaces::msg::ParameterDescriptor> results;
|
||||
for (auto & kv : parameters_) {
|
||||
if (std::any_of(names.cbegin(), names.cend(), [&kv](const std::string & name) {
|
||||
return name == kv.first;
|
||||
}))
|
||||
return name == kv.first;
|
||||
}))
|
||||
{
|
||||
rcl_interfaces::msg::ParameterDescriptor parameter_descriptor;
|
||||
parameter_descriptor.name = kv.first;
|
||||
@@ -173,8 +181,8 @@ NodeParameters::get_parameter_types(const std::vector<std::string> & names) cons
|
||||
std::vector<uint8_t> results;
|
||||
for (auto & kv : parameters_) {
|
||||
if (std::any_of(names.cbegin(), names.cend(), [&kv](const std::string & name) {
|
||||
return name == kv.first;
|
||||
}))
|
||||
return name == kv.first;
|
||||
}))
|
||||
{
|
||||
results.push_back(kv.second.get_type());
|
||||
} else {
|
||||
@@ -190,26 +198,29 @@ NodeParameters::list_parameters(const std::vector<std::string> & prefixes, uint6
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
rcl_interfaces::msg::ListParametersResult result;
|
||||
|
||||
// TODO(esteve): define parameter separator, use "." for now
|
||||
// TODO(mikaelarguedas) define parameter separator different from "/" to avoid ambiguity
|
||||
// using "." for now
|
||||
const char * separator = ".";
|
||||
for (auto & kv : parameters_) {
|
||||
if (((prefixes.size() == 0) &&
|
||||
bool get_all = (prefixes.size() == 0) &&
|
||||
((depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) ||
|
||||
(static_cast<uint64_t>(std::count(kv.first.begin(), kv.first.end(), '.')) < depth))) ||
|
||||
(std::any_of(prefixes.cbegin(), prefixes.cend(), [&kv, &depth](const std::string & prefix) {
|
||||
if (kv.first == prefix) {
|
||||
return true;
|
||||
} else if (kv.first.find(prefix + ".") == 0) {
|
||||
size_t length = prefix.length();
|
||||
std::string substr = kv.first.substr(length);
|
||||
// Cast as unsigned integer to avoid warning
|
||||
return (depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) ||
|
||||
(static_cast<uint64_t>(std::count(substr.begin(), substr.end(), '.')) < depth);
|
||||
}
|
||||
return false;
|
||||
})))
|
||||
{
|
||||
(static_cast<uint64_t>(std::count(kv.first.begin(), kv.first.end(), *separator)) < depth));
|
||||
bool prefix_matches = std::any_of(prefixes.cbegin(), prefixes.cend(),
|
||||
[&kv, &depth, &separator](const std::string & prefix) {
|
||||
if (kv.first == prefix) {
|
||||
return true;
|
||||
} else if (kv.first.find(prefix + separator) == 0) {
|
||||
size_t length = prefix.length();
|
||||
std::string substr = kv.first.substr(length);
|
||||
// Cast as unsigned integer to avoid warning
|
||||
return (depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) ||
|
||||
(static_cast<uint64_t>(std::count(substr.begin(), substr.end(), *separator)) < depth);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (get_all || prefix_matches) {
|
||||
result.names.push_back(kv.first);
|
||||
size_t last_separator = kv.first.find_last_of('.');
|
||||
size_t last_separator = kv.first.find_last_of(separator);
|
||||
if (std::string::npos != last_separator) {
|
||||
std::string prefix = kv.first.substr(0, last_separator);
|
||||
if (std::find(result.prefixes.cbegin(), result.prefixes.cend(), prefix) ==
|
||||
@@ -226,5 +237,9 @@ NodeParameters::list_parameters(const std::vector<std::string> & prefixes, uint6
|
||||
void
|
||||
NodeParameters::register_param_change_callback(ParametersCallbackFunction callback)
|
||||
{
|
||||
if (parameters_callback_) {
|
||||
RCUTILS_LOG_WARN("param_change_callback already registered, "
|
||||
"overwriting previous callback")
|
||||
}
|
||||
parameters_callback_ = callback;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ NodeServices::~NodeServices()
|
||||
|
||||
void
|
||||
NodeServices::add_service(
|
||||
rclcpp::service::ServiceBase::SharedPtr service_base_ptr,
|
||||
rclcpp::ServiceBase::SharedPtr service_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
if (group) {
|
||||
@@ -45,7 +45,8 @@ NodeServices::add_service(
|
||||
auto notify_guard_condition_lock = node_base_->acquire_notify_guard_condition_lock();
|
||||
if (rcl_trigger_guard_condition(node_base_->get_notify_guard_condition()) != RCL_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("Failed to notify waitset on service creation: ") + rmw_get_error_string()
|
||||
std::string(
|
||||
"Failed to notify wait set on service creation: ") + rmw_get_error_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -53,7 +54,7 @@ NodeServices::add_service(
|
||||
|
||||
void
|
||||
NodeServices::add_client(
|
||||
rclcpp::client::ClientBase::SharedPtr client_base_ptr,
|
||||
rclcpp::ClientBase::SharedPtr client_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
if (group) {
|
||||
@@ -71,7 +72,7 @@ NodeServices::add_client(
|
||||
auto notify_guard_condition_lock = node_base_->acquire_notify_guard_condition_lock();
|
||||
if (rcl_trigger_guard_condition(node_base_->get_notify_guard_condition()) != RCL_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("Failed to notify waitset on client creation: ") + rmw_get_error_string()
|
||||
std::string("Failed to notify wait set on client creation: ") + rmw_get_error_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ NodeTimers::~NodeTimers()
|
||||
|
||||
void
|
||||
NodeTimers::add_timer(
|
||||
rclcpp::timer::TimerBase::SharedPtr timer,
|
||||
rclcpp::TimerBase::SharedPtr timer,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group)
|
||||
{
|
||||
if (callback_group) {
|
||||
@@ -42,6 +42,6 @@ NodeTimers::add_timer(
|
||||
if (rcl_trigger_guard_condition(node_base_->get_notify_guard_condition()) != RCL_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string(
|
||||
"Failed to notify waitset on timer creation: ") + rmw_get_error_string());
|
||||
"Failed to notify wait set on timer creation: ") + rmw_get_error_string());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ NodeTopics::NodeTopics(rclcpp::node_interfaces::NodeBaseInterface * node_base)
|
||||
NodeTopics::~NodeTopics()
|
||||
{}
|
||||
|
||||
rclcpp::publisher::PublisherBase::SharedPtr
|
||||
rclcpp::PublisherBase::SharedPtr
|
||||
NodeTopics::create_publisher(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::PublisherFactory & publisher_factory,
|
||||
@@ -63,7 +63,7 @@ NodeTopics::create_publisher(
|
||||
|
||||
void
|
||||
NodeTopics::add_publisher(
|
||||
rclcpp::publisher::PublisherBase::SharedPtr publisher)
|
||||
rclcpp::PublisherBase::SharedPtr publisher)
|
||||
{
|
||||
// The publisher is not added to a callback group or anthing like that for now.
|
||||
// It may be stored within the NodeTopics class or the NodeBase class in the future.
|
||||
@@ -74,12 +74,12 @@ NodeTopics::add_publisher(
|
||||
if (rcl_trigger_guard_condition(node_base_->get_notify_guard_condition()) != RCL_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string(
|
||||
"Failed to notify waitset on publisher creation: ") + rmw_get_error_string());
|
||||
"Failed to notify wait set on publisher creation: ") + rmw_get_error_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr
|
||||
rclcpp::SubscriptionBase::SharedPtr
|
||||
NodeTopics::create_subscription(
|
||||
const std::string & topic_name,
|
||||
const rclcpp::SubscriptionFactory & subscription_factory,
|
||||
@@ -104,7 +104,7 @@ NodeTopics::create_subscription(
|
||||
|
||||
void
|
||||
NodeTopics::add_subscription(
|
||||
rclcpp::subscription::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group)
|
||||
{
|
||||
// Assign to a group.
|
||||
@@ -124,7 +124,7 @@ NodeTopics::add_subscription(
|
||||
if (rcl_trigger_guard_condition(node_base_->get_notify_guard_condition()) != RCL_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string(
|
||||
"Failed to notify waitset on subscription creation: ") + rmw_get_error_string()
|
||||
"Failed to notify wait set on subscription creation: ") + rmw_get_error_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,32 +19,101 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using rclcpp::parameter_client::AsyncParametersClient;
|
||||
using rclcpp::parameter_client::SyncParametersClient;
|
||||
#include "./parameter_service_names.hpp"
|
||||
|
||||
using rclcpp::AsyncParametersClient;
|
||||
using rclcpp::SyncParametersClient;
|
||||
|
||||
AsyncParametersClient::AsyncParametersClient(
|
||||
const rclcpp::node::Node::SharedPtr node,
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
|
||||
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: node_(node)
|
||||
: node_topics_interface_(node_topics_interface)
|
||||
{
|
||||
if (remote_node_name != "") {
|
||||
remote_node_name_ = remote_node_name;
|
||||
} else {
|
||||
remote_node_name_ = node_->get_name();
|
||||
remote_node_name_ = node_base_interface->get_name();
|
||||
}
|
||||
get_parameters_client_ = node_->create_client<rcl_interfaces::srv::GetParameters>(
|
||||
remote_node_name_ + "__get_parameters", qos_profile);
|
||||
get_parameter_types_client_ = node_->create_client<rcl_interfaces::srv::GetParameterTypes>(
|
||||
remote_node_name_ + "__get_parameter_types", qos_profile);
|
||||
set_parameters_client_ = node_->create_client<rcl_interfaces::srv::SetParameters>(
|
||||
remote_node_name_ + "__set_parameters", qos_profile);
|
||||
list_parameters_client_ = node_->create_client<rcl_interfaces::srv::ListParameters>(
|
||||
remote_node_name_ + "__list_parameters", qos_profile);
|
||||
describe_parameters_client_ = node_->create_client<rcl_interfaces::srv::DescribeParameters>(
|
||||
remote_node_name_ + "__describe_parameters", qos_profile);
|
||||
|
||||
rcl_client_options_t options = rcl_client_get_default_options();
|
||||
options.qos = qos_profile;
|
||||
|
||||
using rclcpp::Client;
|
||||
using rclcpp::ClientBase;
|
||||
|
||||
get_parameters_client_ = Client<rcl_interfaces::srv::GetParameters>::make_shared(
|
||||
node_base_interface.get(),
|
||||
node_graph_interface,
|
||||
remote_node_name_ + "/" + parameter_service_names::get_parameters,
|
||||
options);
|
||||
auto get_parameters_base = std::dynamic_pointer_cast<ClientBase>(get_parameters_client_);
|
||||
node_services_interface->add_client(get_parameters_base, nullptr);
|
||||
|
||||
get_parameter_types_client_ = Client<rcl_interfaces::srv::GetParameterTypes>::make_shared(
|
||||
node_base_interface.get(),
|
||||
node_graph_interface,
|
||||
remote_node_name_ + "/" + parameter_service_names::get_parameter_types,
|
||||
options);
|
||||
auto get_parameter_types_base =
|
||||
std::dynamic_pointer_cast<ClientBase>(get_parameter_types_client_);
|
||||
node_services_interface->add_client(get_parameter_types_base, nullptr);
|
||||
|
||||
set_parameters_client_ = Client<rcl_interfaces::srv::SetParameters>::make_shared(
|
||||
node_base_interface.get(),
|
||||
node_graph_interface,
|
||||
remote_node_name_ + "/" + parameter_service_names::set_parameters,
|
||||
options);
|
||||
auto set_parameters_base = std::dynamic_pointer_cast<ClientBase>(set_parameters_client_);
|
||||
node_services_interface->add_client(set_parameters_base, nullptr);
|
||||
|
||||
list_parameters_client_ = Client<rcl_interfaces::srv::ListParameters>::make_shared(
|
||||
node_base_interface.get(),
|
||||
node_graph_interface,
|
||||
remote_node_name_ + "/" + parameter_service_names::list_parameters,
|
||||
options);
|
||||
auto list_parameters_base = std::dynamic_pointer_cast<ClientBase>(list_parameters_client_);
|
||||
node_services_interface->add_client(list_parameters_base, nullptr);
|
||||
|
||||
describe_parameters_client_ = Client<rcl_interfaces::srv::DescribeParameters>::make_shared(
|
||||
node_base_interface.get(),
|
||||
node_graph_interface,
|
||||
remote_node_name_ + "/" + parameter_service_names::describe_parameters,
|
||||
options);
|
||||
auto describe_parameters_base =
|
||||
std::dynamic_pointer_cast<ClientBase>(describe_parameters_client_);
|
||||
node_services_interface->add_client(describe_parameters_base, nullptr);
|
||||
}
|
||||
|
||||
AsyncParametersClient::AsyncParametersClient(
|
||||
const rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: AsyncParametersClient(
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface(),
|
||||
remote_node_name,
|
||||
qos_profile)
|
||||
{}
|
||||
|
||||
AsyncParametersClient::AsyncParametersClient(
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: AsyncParametersClient(
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface(),
|
||||
remote_node_name,
|
||||
qos_profile)
|
||||
{}
|
||||
|
||||
std::shared_future<std::vector<rclcpp::parameter::ParameterVariant>>
|
||||
AsyncParametersClient::get_parameters(
|
||||
const std::vector<std::string> & names,
|
||||
@@ -59,11 +128,10 @@ AsyncParametersClient::get_parameters(
|
||||
auto request = std::make_shared<rcl_interfaces::srv::GetParameters::Request>();
|
||||
request->names = names;
|
||||
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
get_parameters_client_->async_send_request(
|
||||
request,
|
||||
[request, promise_result, future_result, &callback](
|
||||
rclcpp::client::Client<rcl_interfaces::srv::GetParameters>::SharedFuture cb_f)
|
||||
[request, promise_result, future_result, callback](
|
||||
rclcpp::Client<rcl_interfaces::srv::GetParameters>::SharedFuture cb_f)
|
||||
{
|
||||
std::vector<rclcpp::parameter::ParameterVariant> parameter_variants;
|
||||
auto & pvalues = cb_f.get()->values;
|
||||
@@ -83,7 +151,6 @@ AsyncParametersClient::get_parameters(
|
||||
}
|
||||
}
|
||||
);
|
||||
// *INDENT-ON*
|
||||
|
||||
return future_result;
|
||||
}
|
||||
@@ -102,11 +169,10 @@ AsyncParametersClient::get_parameter_types(
|
||||
auto request = std::make_shared<rcl_interfaces::srv::GetParameterTypes::Request>();
|
||||
request->names = names;
|
||||
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
get_parameter_types_client_->async_send_request(
|
||||
request,
|
||||
[promise_result, future_result, &callback](
|
||||
rclcpp::client::Client<rcl_interfaces::srv::GetParameterTypes>::SharedFuture cb_f)
|
||||
[promise_result, future_result, callback](
|
||||
rclcpp::Client<rcl_interfaces::srv::GetParameterTypes>::SharedFuture cb_f)
|
||||
{
|
||||
std::vector<rclcpp::parameter::ParameterType> types;
|
||||
auto & pts = cb_f.get()->types;
|
||||
@@ -119,7 +185,6 @@ AsyncParametersClient::get_parameter_types(
|
||||
}
|
||||
}
|
||||
);
|
||||
// *INDENT-ON*
|
||||
|
||||
return future_result;
|
||||
}
|
||||
@@ -137,7 +202,6 @@ AsyncParametersClient::set_parameters(
|
||||
|
||||
auto request = std::make_shared<rcl_interfaces::srv::SetParameters::Request>();
|
||||
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
std::transform(parameters.begin(), parameters.end(), std::back_inserter(request->parameters),
|
||||
[](rclcpp::parameter::ParameterVariant p) {
|
||||
return p.to_parameter();
|
||||
@@ -146,8 +210,8 @@ AsyncParametersClient::set_parameters(
|
||||
|
||||
set_parameters_client_->async_send_request(
|
||||
request,
|
||||
[promise_result, future_result, &callback](
|
||||
rclcpp::client::Client<rcl_interfaces::srv::SetParameters>::SharedFuture cb_f)
|
||||
[promise_result, future_result, callback](
|
||||
rclcpp::Client<rcl_interfaces::srv::SetParameters>::SharedFuture cb_f)
|
||||
{
|
||||
promise_result->set_value(cb_f.get()->results);
|
||||
if (callback != nullptr) {
|
||||
@@ -155,7 +219,6 @@ AsyncParametersClient::set_parameters(
|
||||
}
|
||||
}
|
||||
);
|
||||
// *INDENT-ON*
|
||||
|
||||
return future_result;
|
||||
}
|
||||
@@ -173,7 +236,6 @@ AsyncParametersClient::set_parameters_atomically(
|
||||
|
||||
auto request = std::make_shared<rcl_interfaces::srv::SetParametersAtomically::Request>();
|
||||
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
std::transform(parameters.begin(), parameters.end(), std::back_inserter(request->parameters),
|
||||
[](rclcpp::parameter::ParameterVariant p) {
|
||||
return p.to_parameter();
|
||||
@@ -182,8 +244,8 @@ AsyncParametersClient::set_parameters_atomically(
|
||||
|
||||
set_parameters_atomically_client_->async_send_request(
|
||||
request,
|
||||
[promise_result, future_result, &callback](
|
||||
rclcpp::client::Client<rcl_interfaces::srv::SetParametersAtomically>::SharedFuture cb_f)
|
||||
[promise_result, future_result, callback](
|
||||
rclcpp::Client<rcl_interfaces::srv::SetParametersAtomically>::SharedFuture cb_f)
|
||||
{
|
||||
promise_result->set_value(cb_f.get()->result);
|
||||
if (callback != nullptr) {
|
||||
@@ -191,7 +253,6 @@ AsyncParametersClient::set_parameters_atomically(
|
||||
}
|
||||
}
|
||||
);
|
||||
// *INDENT-ON*
|
||||
|
||||
return future_result;
|
||||
}
|
||||
@@ -212,11 +273,10 @@ AsyncParametersClient::list_parameters(
|
||||
request->prefixes = prefixes;
|
||||
request->depth = depth;
|
||||
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
list_parameters_client_->async_send_request(
|
||||
request,
|
||||
[promise_result, future_result, &callback](
|
||||
rclcpp::client::Client<rcl_interfaces::srv::ListParameters>::SharedFuture cb_f)
|
||||
[promise_result, future_result, callback](
|
||||
rclcpp::Client<rcl_interfaces::srv::ListParameters>::SharedFuture cb_f)
|
||||
{
|
||||
promise_result->set_value(cb_f.get()->result);
|
||||
if (callback != nullptr) {
|
||||
@@ -224,27 +284,67 @@ AsyncParametersClient::list_parameters(
|
||||
}
|
||||
}
|
||||
);
|
||||
// *INDENT-ON*
|
||||
|
||||
return future_result;
|
||||
}
|
||||
|
||||
SyncParametersClient::SyncParametersClient(
|
||||
rclcpp::node::Node::SharedPtr node,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: node_(node)
|
||||
bool
|
||||
AsyncParametersClient::service_is_ready() const
|
||||
{
|
||||
executor_ = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
|
||||
async_parameters_client_ = std::make_shared<AsyncParametersClient>(node, "", qos_profile);
|
||||
return
|
||||
get_parameters_client_->service_is_ready() &&
|
||||
get_parameter_types_client_->service_is_ready() &&
|
||||
set_parameters_client_->service_is_ready() &&
|
||||
list_parameters_client_->service_is_ready() &&
|
||||
describe_parameters_client_->service_is_ready();
|
||||
}
|
||||
|
||||
bool
|
||||
AsyncParametersClient::wait_for_service_nanoseconds(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
const std::vector<std::shared_ptr<rclcpp::ClientBase>> clients = {
|
||||
get_parameters_client_,
|
||||
get_parameter_types_client_,
|
||||
set_parameters_client_,
|
||||
list_parameters_client_,
|
||||
describe_parameters_client_
|
||||
};
|
||||
for (auto & client : clients) {
|
||||
auto stamp = std::chrono::steady_clock::now();
|
||||
if (!client->wait_for_service(timeout)) {
|
||||
return false;
|
||||
}
|
||||
if (timeout > std::chrono::nanoseconds::zero()) {
|
||||
timeout -= std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::steady_clock::now() - stamp);
|
||||
if (timeout < std::chrono::nanoseconds::zero()) {
|
||||
timeout = std::chrono::nanoseconds::zero();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SyncParametersClient::SyncParametersClient(
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: SyncParametersClient(
|
||||
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
|
||||
node,
|
||||
remote_node_name,
|
||||
qos_profile)
|
||||
{}
|
||||
|
||||
SyncParametersClient::SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
rclcpp::node::Node::SharedPtr node,
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: executor_(executor), node_(node)
|
||||
{
|
||||
async_parameters_client_ = std::make_shared<AsyncParametersClient>(node, "", qos_profile);
|
||||
async_parameters_client_ =
|
||||
std::make_shared<AsyncParametersClient>(node, remote_node_name, qos_profile);
|
||||
}
|
||||
|
||||
std::vector<rclcpp::parameter::ParameterVariant>
|
||||
|
||||
60
rclcpp/src/rclcpp/parameter_events_filter.cpp
Normal file
60
rclcpp/src/rclcpp/parameter_events_filter.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "rclcpp/parameter_events_filter.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using rclcpp::ParameterEventsFilter;
|
||||
using EventType = rclcpp::ParameterEventsFilter::EventType;
|
||||
using EventPair = rclcpp::ParameterEventsFilter::EventPair;
|
||||
|
||||
ParameterEventsFilter::ParameterEventsFilter(
|
||||
rcl_interfaces::msg::ParameterEvent::SharedPtr event,
|
||||
const std::vector<std::string> & names,
|
||||
const std::vector<EventType> & types)
|
||||
: event_(event)
|
||||
{
|
||||
if (std::find(types.begin(), types.end(), EventType::NEW) != types.end()) {
|
||||
for (auto & new_parameter : event->new_parameters) {
|
||||
if (std::find(names.begin(), names.end(), new_parameter.name) != names.end()) {
|
||||
result_.push_back(
|
||||
EventPair(EventType::NEW, &new_parameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (std::find(types.begin(), types.end(), EventType::CHANGED) != types.end()) {
|
||||
for (auto & changed_parameter : event->changed_parameters) {
|
||||
if (std::find(names.begin(), names.end(), changed_parameter.name) != names.end()) {
|
||||
result_.push_back(
|
||||
EventPair(EventType::CHANGED, &changed_parameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (std::find(types.begin(), types.end(), EventType::DELETED) != types.end()) {
|
||||
for (auto & deleted_parameter : event->deleted_parameters) {
|
||||
if (std::find(names.begin(), names.end(), deleted_parameter.name) != names.end()) {
|
||||
result_.push_back(
|
||||
EventPair(EventType::DELETED, &deleted_parameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<EventPair> &
|
||||
ParameterEventsFilter::get_events() const
|
||||
{
|
||||
return result_;
|
||||
}
|
||||
@@ -19,17 +19,18 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using rclcpp::parameter_service::ParameterService;
|
||||
#include "./parameter_service_names.hpp"
|
||||
|
||||
using rclcpp::ParameterService;
|
||||
|
||||
ParameterService::ParameterService(
|
||||
const rclcpp::node::Node::SharedPtr node,
|
||||
const rclcpp::Node::SharedPtr node,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: node_(node)
|
||||
{
|
||||
std::weak_ptr<rclcpp::node::Node> captured_node = node_;
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
std::weak_ptr<rclcpp::Node> captured_node = node_;
|
||||
get_parameters_service_ = node_->create_service<rcl_interfaces::srv::GetParameters>(
|
||||
std::string(node_->get_name()) + "__get_parameters",
|
||||
std::string(node_->get_name()) + "/" + parameter_service_names::get_parameters,
|
||||
[captured_node](
|
||||
const std::shared_ptr<rmw_request_id_t>,
|
||||
const std::shared_ptr<rcl_interfaces::srv::GetParameters::Request> request,
|
||||
@@ -44,11 +45,10 @@ ParameterService::ParameterService(
|
||||
response->values.push_back(pvariant.get_parameter_value());
|
||||
}
|
||||
},
|
||||
qos_profile
|
||||
);
|
||||
qos_profile);
|
||||
|
||||
get_parameter_types_service_ = node_->create_service<rcl_interfaces::srv::GetParameterTypes>(
|
||||
std::string(node_->get_name()) + "__get_parameter_types",
|
||||
std::string(node_->get_name()) + "/" + parameter_service_names::get_parameter_types,
|
||||
[captured_node](
|
||||
const std::shared_ptr<rmw_request_id_t>,
|
||||
const std::shared_ptr<rcl_interfaces::srv::GetParameterTypes::Request> request,
|
||||
@@ -64,11 +64,10 @@ ParameterService::ParameterService(
|
||||
return static_cast<rclcpp::parameter::ParameterType>(type);
|
||||
});
|
||||
},
|
||||
qos_profile
|
||||
);
|
||||
qos_profile);
|
||||
|
||||
set_parameters_service_ = node_->create_service<rcl_interfaces::srv::SetParameters>(
|
||||
std::string(node_->get_name()) + "__set_parameters",
|
||||
std::string(node_->get_name()) + "/" + parameter_service_names::set_parameters,
|
||||
[captured_node](
|
||||
const std::shared_ptr<rmw_request_id_t>,
|
||||
const std::shared_ptr<rcl_interfaces::srv::SetParameters::Request> request,
|
||||
@@ -85,12 +84,11 @@ ParameterService::ParameterService(
|
||||
auto results = node->set_parameters(pvariants);
|
||||
response->results = results;
|
||||
},
|
||||
qos_profile
|
||||
);
|
||||
qos_profile);
|
||||
|
||||
set_parameters_atomically_service_ =
|
||||
node_->create_service<rcl_interfaces::srv::SetParametersAtomically>(
|
||||
std::string(node_->get_name()) + "__set_parameters_atomically",
|
||||
std::string(node_->get_name()) + "/" + parameter_service_names::set_parameters_atomically,
|
||||
[captured_node](
|
||||
const std::shared_ptr<rmw_request_id_t>,
|
||||
const std::shared_ptr<rcl_interfaces::srv::SetParametersAtomically::Request> request,
|
||||
@@ -104,17 +102,15 @@ ParameterService::ParameterService(
|
||||
std::transform(request->parameters.cbegin(), request->parameters.cend(),
|
||||
std::back_inserter(pvariants),
|
||||
[](const rcl_interfaces::msg::Parameter & p) {
|
||||
return rclcpp::parameter::ParameterVariant::
|
||||
from_parameter(p);
|
||||
return rclcpp::parameter::ParameterVariant::from_parameter(p);
|
||||
});
|
||||
auto result = node->set_parameters_atomically(pvariants);
|
||||
response->result = result;
|
||||
},
|
||||
qos_profile
|
||||
);
|
||||
qos_profile);
|
||||
|
||||
describe_parameters_service_ = node_->create_service<rcl_interfaces::srv::DescribeParameters>(
|
||||
std::string(node_->get_name()) + "__describe_parameters",
|
||||
std::string(node_->get_name()) + "/" + parameter_service_names::describe_parameters,
|
||||
[captured_node](
|
||||
const std::shared_ptr<rmw_request_id_t>,
|
||||
const std::shared_ptr<rcl_interfaces::srv::DescribeParameters::Request> request,
|
||||
@@ -127,11 +123,10 @@ ParameterService::ParameterService(
|
||||
auto descriptors = node->describe_parameters(request->names);
|
||||
response->descriptors = descriptors;
|
||||
},
|
||||
qos_profile
|
||||
);
|
||||
qos_profile);
|
||||
|
||||
list_parameters_service_ = node_->create_service<rcl_interfaces::srv::ListParameters>(
|
||||
std::string(node_->get_name()) + "__list_parameters",
|
||||
std::string(node_->get_name()) + "/" + parameter_service_names::list_parameters,
|
||||
[captured_node](
|
||||
const std::shared_ptr<rmw_request_id_t>,
|
||||
const std::shared_ptr<rcl_interfaces::srv::ListParameters::Request> request,
|
||||
@@ -144,7 +139,5 @@ ParameterService::ParameterService(
|
||||
auto result = node->list_parameters(request->prefixes, request->depth);
|
||||
response->result = result;
|
||||
},
|
||||
qos_profile
|
||||
);
|
||||
// *INDENT-ON*
|
||||
qos_profile);
|
||||
}
|
||||
|
||||
33
rclcpp/src/rclcpp/parameter_service_names.hpp
Normal file
33
rclcpp/src/rclcpp/parameter_service_names.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__PARAMETER_SERVICE_NAMES_HPP_
|
||||
#define RCLCPP__PARAMETER_SERVICE_NAMES_HPP_
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace parameter_service_names
|
||||
{
|
||||
|
||||
static constexpr const char * get_parameters = "get_parameters";
|
||||
static constexpr const char * get_parameter_types = "get_parameter_types";
|
||||
static constexpr const char * set_parameters = "set_parameters";
|
||||
static constexpr const char * set_parameters_atomically = "set_parameters_atomically";
|
||||
static constexpr const char * describe_parameters = "describe_parameters";
|
||||
static constexpr const char * list_parameters = "list_parameters";
|
||||
|
||||
} // namespace parameter_service_names
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__PARAMETER_SERVICE_NAMES_HPP_
|
||||
@@ -28,10 +28,12 @@
|
||||
|
||||
#include "rclcpp/allocator/allocator_common.hpp"
|
||||
#include "rclcpp/allocator/allocator_deleter.hpp"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/expand_topic_or_service_name.hpp"
|
||||
|
||||
using rclcpp::publisher::PublisherBase;
|
||||
using rclcpp::PublisherBase;
|
||||
|
||||
PublisherBase::PublisherBase(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
@@ -41,25 +43,36 @@ PublisherBase::PublisherBase(
|
||||
: rcl_node_handle_(node_base->get_shared_rcl_node_handle()),
|
||||
intra_process_publisher_id_(0), store_intra_process_message_(nullptr)
|
||||
{
|
||||
if (rcl_publisher_init(
|
||||
&publisher_handle_, rcl_node_handle_.get(), &type_support,
|
||||
topic.c_str(), &publisher_options) != RCL_RET_OK)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("could not create publisher: ") +
|
||||
rcl_get_error_string_safe());
|
||||
rcl_ret_t ret = rcl_publisher_init(
|
||||
&publisher_handle_,
|
||||
rcl_node_handle_.get(),
|
||||
&type_support,
|
||||
topic.c_str(),
|
||||
&publisher_options);
|
||||
if (ret != RCL_RET_OK) {
|
||||
if (ret == RCL_RET_TOPIC_NAME_INVALID) {
|
||||
auto rcl_node_handle = rcl_node_handle_.get();
|
||||
// this will throw on any validation problem
|
||||
rcl_reset_error();
|
||||
expand_topic_or_service_name(
|
||||
topic,
|
||||
rcl_node_get_name(rcl_node_handle),
|
||||
rcl_node_get_namespace(rcl_node_handle));
|
||||
}
|
||||
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "could not create publisher");
|
||||
}
|
||||
// Life time of this object is tied to the publisher handle.
|
||||
rmw_publisher_t * publisher_rmw_handle = rcl_publisher_get_rmw_handle(&publisher_handle_);
|
||||
if (!publisher_rmw_handle) {
|
||||
throw std::runtime_error(
|
||||
std::string("failed to get rmw handle: ") + rcl_get_error_string_safe());
|
||||
auto msg = std::string("failed to get rmw handle: ") + rcl_get_error_string_safe();
|
||||
rcl_reset_error();
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
if (rmw_get_gid_for_publisher(publisher_rmw_handle, &rmw_gid_) != RMW_RET_OK) {
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
throw std::runtime_error(
|
||||
std::string("failed to get publisher gid: ") + rmw_get_error_string_safe());
|
||||
// *INDENT-ON*
|
||||
auto msg = std::string("failed to get publisher gid: ") + rmw_get_error_string_safe();
|
||||
rmw_reset_error();
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +83,7 @@ PublisherBase::~PublisherBase()
|
||||
stderr,
|
||||
"Error in destruction of intra process rcl publisher handle: %s\n",
|
||||
rcl_get_error_string_safe());
|
||||
rcl_reset_error();
|
||||
}
|
||||
|
||||
if (rcl_publisher_fini(&publisher_handle_, rcl_node_handle_.get()) != RCL_RET_OK) {
|
||||
@@ -77,6 +91,7 @@ PublisherBase::~PublisherBase()
|
||||
stderr,
|
||||
"Error in destruction of rcl publisher handle: %s\n",
|
||||
rcl_get_error_string_safe());
|
||||
rcl_reset_error();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +106,9 @@ PublisherBase::get_queue_size() const
|
||||
{
|
||||
const rcl_publisher_options_t * publisher_options = rcl_publisher_get_options(&publisher_handle_);
|
||||
if (!publisher_options) {
|
||||
throw std::runtime_error(
|
||||
std::string("failed to get publisher options: ") + rcl_get_error_string_safe());
|
||||
auto msg = std::string("failed to get publisher options: ") + rcl_get_error_string_safe();
|
||||
rcl_reset_error();
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
return publisher_options->qos.depth;
|
||||
}
|
||||
@@ -109,6 +125,18 @@ PublisherBase::get_intra_process_gid() const
|
||||
return intra_process_rmw_gid_;
|
||||
}
|
||||
|
||||
rcl_publisher_t *
|
||||
PublisherBase::get_publisher_handle()
|
||||
{
|
||||
return &publisher_handle_;
|
||||
}
|
||||
|
||||
const rcl_publisher_t *
|
||||
PublisherBase::get_publisher_handle() const
|
||||
{
|
||||
return &publisher_handle_;
|
||||
}
|
||||
|
||||
bool
|
||||
PublisherBase::operator==(const rmw_gid_t & gid) const
|
||||
{
|
||||
@@ -121,14 +149,16 @@ PublisherBase::operator==(const rmw_gid_t * gid) const
|
||||
bool result = false;
|
||||
auto ret = rmw_compare_gids_equal(gid, &this->get_gid(), &result);
|
||||
if (ret != RMW_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("failed to compare gids: ") + rmw_get_error_string_safe());
|
||||
auto msg = std::string("failed to compare gids: ") + rmw_get_error_string_safe();
|
||||
rmw_reset_error();
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
if (!result) {
|
||||
ret = rmw_compare_gids_equal(gid, &this->get_intra_process_gid(), &result);
|
||||
if (ret != RMW_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
std::string("failed to compare gids: ") + rmw_get_error_string_safe());
|
||||
auto msg = std::string("failed to compare gids: ") + rmw_get_error_string_safe();
|
||||
rmw_reset_error();
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -140,15 +170,25 @@ PublisherBase::setup_intra_process(
|
||||
StoreMessageCallbackT callback,
|
||||
const rcl_publisher_options_t & intra_process_options)
|
||||
{
|
||||
auto intra_process_topic_name = std::string(this->get_topic_name()) + "__intra";
|
||||
if (rcl_publisher_init(
|
||||
&intra_process_publisher_handle_, rcl_node_handle_.get(),
|
||||
rclcpp::type_support::get_intra_process_message_msg_type_support(),
|
||||
intra_process_topic_name.c_str(), &intra_process_options) != RCL_RET_OK)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("could not create intra process publisher: ") +
|
||||
rcl_get_error_string_safe());
|
||||
auto intra_process_topic_name = std::string(this->get_topic_name()) + "/_intra";
|
||||
rcl_ret_t ret = rcl_publisher_init(
|
||||
&intra_process_publisher_handle_,
|
||||
rcl_node_handle_.get(),
|
||||
rclcpp::type_support::get_intra_process_message_msg_type_support(),
|
||||
intra_process_topic_name.c_str(),
|
||||
&intra_process_options);
|
||||
if (ret != RCL_RET_OK) {
|
||||
if (ret == RCL_RET_TOPIC_NAME_INVALID) {
|
||||
auto rcl_node_handle = rcl_node_handle_.get();
|
||||
// this will throw on any validation problem
|
||||
rcl_reset_error();
|
||||
expand_topic_or_service_name(
|
||||
intra_process_topic_name,
|
||||
rcl_node_get_name(rcl_node_handle),
|
||||
rcl_node_get_namespace(rcl_node_handle));
|
||||
}
|
||||
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "could not create intra process publisher");
|
||||
}
|
||||
|
||||
intra_process_publisher_id_ = intra_process_publisher_id;
|
||||
@@ -157,16 +197,16 @@ PublisherBase::setup_intra_process(
|
||||
rmw_publisher_t * publisher_rmw_handle = rcl_publisher_get_rmw_handle(
|
||||
&intra_process_publisher_handle_);
|
||||
if (publisher_rmw_handle == nullptr) {
|
||||
throw std::runtime_error(std::string(
|
||||
"Failed to get rmw publisher handle") + rcl_get_error_string_safe());
|
||||
auto msg = std::string("Failed to get rmw publisher handle") + rcl_get_error_string_safe();
|
||||
rcl_reset_error();
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
auto ret = rmw_get_gid_for_publisher(
|
||||
auto rmw_ret = rmw_get_gid_for_publisher(
|
||||
publisher_rmw_handle, &intra_process_rmw_gid_);
|
||||
if (ret != RMW_RET_OK) {
|
||||
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
|
||||
throw std::runtime_error(
|
||||
std::string("failed to create intra process publisher gid: ") +
|
||||
rmw_get_error_string_safe());
|
||||
// *INDENT-ON*
|
||||
if (rmw_ret != RMW_RET_OK) {
|
||||
auto msg =
|
||||
std::string("failed to create intra process publisher gid: ") + rmw_get_error_string_safe();
|
||||
rmw_reset_error();
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user