Compare commits

...

66 Commits

Author SHA1 Message Date
Mikael Arguedas
bea1a52e24 0.4.0 2017-12-08 18:06:51 -08:00
Karsten Knese
3e0fa4be66 deallocate state and transition handles after call to fini (#424)
* deallocate state and transition handles after call to fini

* deallocate also when error occured
2017-12-06 17:26:18 -08:00
Karsten Knese
6d13bcb0fc Fix 394 (#419)
* copy and assignment operator for state

copy and assignment operator for transition

remove unused const_casts

address comments

check for null in copy constructor

up

use init and fini functions from rcl

remove unused include

* explicitly zero initialize state and transitions

* add todo comment for follow up
2017-12-05 22:51:52 -08:00
Karsten Knese
c40f3c25c6 Fix 393 (#418)
* correctly copy state label

* correctly copy transition label

* uncrustify

* address comments

* up

* use init and fini functions from rcl
2017-12-05 20:22:57 -08:00
dhood
d823982f22 Allow logger to be passed into macros as a reference (#423)
* Remove reference for logger so it can be rclcpp::Logger &

This is the type when captured by reference in a lambda; windows can't
resolve it without.

* Wrap lines
2017-12-05 15:12:20 -08:00
dhood
6129a12df5 Remove namespaces and namespace escalation e.g. node:: (#416)
* Remove publisher:: namespace

* Remove subscription:: namespace

* Remove client:: namespace

* Remove service:: namespace

* Remove parameter_client:: namespace

* Remove parameter_service:: namespace

* Remove rate:: namespace

* Remove timer:: namespace

* Remove node:: namespace

* Remove any_service_callback:: namespace

* Remove any_subscription_callback:: namespace

* Remove event:: namespace

* Remove ContextSharedPtr escalation

Users can use the  directive themselves if they want

* Remove single_threaded_executor:: namespace

* Remove multi_threaded_executor:: namespace

* Remove context:: namespace

* node:: removal from new logger additions

* Fix linter issues that has been triggered with uncrustify

* Remove utilities:: namespace
2017-12-05 15:02:00 -08:00
Tully Foote
713ee8059c Mirror clock API from Node to LifecycleNode (#417)
* Mirror clock API from Node to LifecycleNode

Follow up to #407

* adding headers for completeness
2017-12-05 00:25:28 -08:00
dhood
2e4e85f141 Add Logger class and give one to nodes (#411)
* Add Logger class and give one to nodes

* Try to improve compiler errors when non-Logger is passed to macros

* Add define for 'disabling' loggers

* Add/update tests

* Linter fix

* Documentation

* Windows fix

* Move free functions to source file (windows was upset)

* Fix windows by changing prototype ordering

* Store node logger in NodeBase

* Windows is not happy with this EXPECT_ANY_THROW

* Move get_logger to a NodeLogger interface

* Move Logger into 'logger' namespace

* Move helper function for macro errors into macro header

* Remove 'logger' namespace

* Return type on separate line

* Update copyright year

* Give lifecycle nodes a logger

* Add test for lifecycle node logger

Move the default_state_machine tests to another file because having
different test fixtures was causing init to be called twice.

* Switch to static_assert for logger check

* global ns scope in macro calls

just in case

* Revert "Add test for lifecycle node logger" (make diff smaller)

demos use the loggers and we don't test other node stuff in lifecycle_node

* Update for rcutils function name change

* Add reference to Node::get_logger() in doxygen

* Rename NodeLoggerInterface to NodeLoggingInterface
2017-12-04 16:07:29 -08:00
dhood
d989bd15c1 Prevent callback from being captured as a reference (#414) 2017-12-03 19:26:30 -08:00
dhood
bc47fa83dc Rename severity_threshold -> level (#412) 2017-12-03 18:40:28 -08:00
dhood
8177771773 Allow creating parameter client from constructor of Node subclass (#413) 2017-12-03 17:12:43 -08:00
dhood
e9f0328ec8 Allow client to trigger another service call from its callback (#415) 2017-12-03 17:11:50 -08:00
Tully Foote
284dc17918 Add a clock interface to the Node API (#407)
node clock interface lower level abstraction
Update node and node interface to expose get_clock and now.
add unit tests to cover node clock API
2017-11-30 14:07:23 -08:00
dhood
3b06aa3721 Escalate more namespaces e.g. rclcpp::Service (#410) 2017-11-30 13:27:44 -08:00
Tully Foote
3426696541 provide a class to filter parameter events conveniently based on name and type of parameter event (#391)
adding test for parameter events filter
2017-11-29 11:11:18 -08:00
Mikael Arguedas
7bbf5f6e5b waitset -> wait_set (#408)
* waitset -> wait_set

* cpplint

* use wait set in doc

* doc fixup
2017-11-27 13:30:07 -08:00
Tully Foote
5e64191e10 Resolve erase race condition. (#406)
Fixes #401

Extend time source tests to allocate and deallocate callback handlers.
2017-11-21 20:44:28 -08:00
Tully Foote
5e565c7e75 detach nodes from executors in destruction. (#404) 2017-11-21 11:42:44 -08:00
Hunter Allen
9be9d66da5 Remove const modifier to prevent compiler error for GCC 8. (#403) 2017-11-20 15:54:53 -05:00
Tully Foote
5c57de016f work around windows failing debug test. Ticketing full debugging separately. (#402) 2017-11-19 20:09:41 -08:00
William Woodall
eed5999221 small doc touchup (#400) 2017-11-17 16:06:06 -08:00
Mikael Arguedas
e08428c79b include cstdlib for std::abs function (#399) 2017-11-17 11:26:52 -08:00
Tully Foote
a215d2d22e update rclcpp to use the refactored TimeSource Clock logic (#371)
This implements a TimeSource in rclcpp, adds the Clock class.
2017-11-16 17:26:56 -08:00
dhood
24f39700c6 Implement rclcpp-specific logging macros [taking name not object] (#389) 2017-11-15 14:14:09 -08:00
Karsten Knese
989084b3de move callback (#387) 2017-10-15 22:40:03 -07:00
G.A. vd. Hoorn
70d2b4b739 macros: fix two minor typos in doxygen. (#386) 2017-10-13 12:08:10 -07:00
G.A. vd. Hoorn
c182f5805e lifecycle: fix minor typo in LC pub Doxygen (#384) 2017-10-13 06:25:20 -07:00
Karsten Knese
022b2b1b80 sync parameter takes optional remote node name (#380) 2017-10-02 11:46:00 -07:00
Dirk Thomas
070b3125c1 Merge pull request #382 from ros2/remove_indent_off
remove obsolete INDENT-OFF usage
2017-09-29 14:24:31 -07:00
Dirk Thomas
c70f2f1452 Merge pull request #381 from ros2/uncrustify_master
update style to match latest uncrustify
2017-09-29 11:12:43 -07:00
Dirk Thomas
acd231abab remove obsolete INDENT-OFF usage 2017-09-29 10:34:52 -07:00
Dirk Thomas
38c750b876 update style to match latest uncrustify 2017-09-28 15:38:40 -07:00
Shane Loretz
e1f4568bc7 Fix static assertion on xcode 9 (#379)
* Change allocator type to match map key
2017-09-27 19:09:20 -07:00
William Woodall
5813ba54db use throw_from_rcl_error() for error state cleanup (#376) 2017-09-19 14:13:28 -07:00
William Woodall
ca5fb57126 Improvements to rclcpp::Time (#375)
* enable Time to be trivially constructible

This is required to use it in a Qt Signal/Slot.

* operator= should return T &

See: https://stackoverflow.com/questions/9072169/why-should-the-assignment-operator-return-a-reference-to-the-object

* add operator!=
2017-09-19 08:32:10 -07:00
dhood
4a2e9d8af9 Reset rcl errors (#374) 2017-09-14 11:03:24 -07:00
Dirk Thomas
ed26865b71 0.0.3 2017-09-13 15:07:07 -07:00
dhood
a8aa556df0 Check for the client error code, not server (#373) 2017-09-12 08:59:13 -07:00
Mikael Arguedas
b68b761462 restore . as parameter separator (#372) 2017-09-12 08:43:42 -07:00
Karsten Knese
1c42a75f43 parameter client takes node interfaces (#368)
* parameter client takes node interfaces

* correct wrong copy paste

* correctly fetch node name

* use node_topics_interface for creating parameter event

* fix typos
2017-09-05 15:04:36 -07:00
Karsten Knese
2c5ab49e7c change parameter separator to forward slash (#367)
* change parameter separator to forward slash

* add separator to prefix

* const char separator
2017-09-05 11:46:31 -07:00
Dirk Thomas
a5f94ac412 Merge pull request #369 from csukuangfj/fix-test-typo
fix a typo.
2017-09-04 08:22:42 -07:00
KUANG Fangjun
de14d54322 fix a typo. 2017-09-04 16:10:45 +02:00
Karsten Knese
b1ed15ebc7 use forward slashes instead of double underscores (#364)
* use forward slashes instead of double underscores

* define parameter service suffixes in commonly shared header

* style

* forgot list_parameters

* correct license year
2017-09-01 10:00:29 -07:00
Dirk Thomas
f175726b0e Merge pull request #366 from ros2/reset_error_code_init_failed
reset error code before throwing in rclcpp::utilities::init
2017-08-31 16:44:01 -07:00
Dirk Thomas
b28648c61d reset error code before throwing in rclcpp::utilities::init 2017-08-31 16:41:05 -07:00
Karsten Knese
8e2e64e82a freeing Time members in destructor, adding copy constructor / assignment operator (#362)
* copy constructor for fixing windows debug

* remove debug prints

* style

* correctly free resources in destructor

* correct copy and assignment operators

* explicit call to copy constructor
2017-08-24 15:21:01 -07:00
Dirk Thomas
6f3020ce23 Merge pull request #361 from ros2/demo_nodes_cpp_native
expose rcl handles
2017-08-24 09:41:13 -07:00
Dirk Thomas
688c83a44c expose rcl handles 2017-08-23 14:29:37 -07:00
dhood
124500511b Add wait_for_service and service_is_ready for SyncParametersClient (#356) 2017-08-16 22:28:53 -07:00
Mikael Arguedas
98dded0ba5 add issue template 2017-08-14 18:04:51 -07:00
dhood
89c43e78c8 Merge pull request #353 from ros2/restore_old_signal_handler
Restore old signal handler after shutdown
2017-08-11 14:02:54 -07:00
dhood
d7b7d7491f Factor out guard condition triggering 2017-08-11 10:31:40 -07:00
dhood
be985a652b Restore old signal handler on shutdown 2017-08-11 10:31:40 -07:00
dhood
c15db0b675 Factor out signal handler swapping 2017-08-11 10:31:40 -07:00
Chris Lalancette
cd839663b4 Fix memory leaks in rclcpp (#354)
* Make sure to delete service_handle when in the Service() destructor.

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

* Make sure to delete the allocated rcl_node on error paths.

This all happens *before* we setup the shared_ptr destructor,
so we have to hand delete in the error paths.

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

* Move delete rcl_node up.

It turns out that we are always going to throw in that block,
and we never access rcl_node, so just delete it very early
on.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2017-08-11 05:45:25 -07:00
Dirk Thomas
5e7aa50af6 Merge pull request #355 from ros2/fix_race_condition
lock around taking the buffer and deciding to get a copy of the message or popping it
2017-08-10 17:28:49 -07:00
Dirk Thomas
48b19af04a lock around taking the buffer and deciding to get a copy of the message or popping it 2017-08-10 14:51:17 -07:00
Mikael Arguedas
2c3336510d typo 2017-08-08 15:27:32 -07:00
Karsten Knese
def973e3dd time operators (#351)
* time operators

* explicitely cast to uint64_t and prevent overflow

* check for negative seconds .. again

* split into hpp/cpp

* export symbols

* change test macro

* fix unsigned comparison

* address comments

* test for specific exception

* Fix typo
2017-08-08 15:18:17 -07:00
Karsten Knese
d090ddc358 fix return value when calling lifecycle service (#350) 2017-08-04 12:57:12 -07:00
Karsten Knese
388a3ca5be use rcl api for rclcpp time (#348)
* use rcl api for rclcpp time

* address comments
2017-08-03 20:33:32 -07:00
Karsten Knese
9281e32f82 rename RCL_LIFECYCLE_RET_T to lifecycle_msgs::msgs::Transition::TRANSITION_CALLBACK_* (#345) 2017-08-02 14:04:34 -07:00
Esteve Fernandez
a41245e6bf Added support to function_traits for std::bind in GCC >= 7.1 (#346)
* Added support to function_traits for std::bind in GCC >= 7.1

* linter fixup
2017-08-01 16:16:39 -04:00
Karsten Knese
0c26dd99b6 expose error handling for state changes (#344)
* remove fprintf, use logging

* expose lifecycle error code

* address comments
2017-07-27 07:55:15 -07:00
Dirk Thomas
40b09b5b14 added wait method to AsyncParametersClient (#342)
* added wait and ready methods to AsyncParametersClient

* style only

* style only

* remove RCLCPP_PUBLIC from template methods

* style
2017-07-10 10:22:08 -07:00
134 changed files with 5290 additions and 1027 deletions

44
.github/ISSUE_TEMPLATE.md vendored Normal file
View 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 -->

View File

@@ -31,8 +31,10 @@ 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
@@ -43,26 +45,54 @@ set(${PROJECT_NAME}_SRCS
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
)
# "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")
add_library(${PROJECT_NAME} SHARED
${${PROJECT_NAME}_SRCS})
ament_target_dependencies(${PROJECT_NAME}
@@ -159,6 +189,16 @@ if(BUILD_TESTING)
)
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
@@ -243,6 +283,28 @@ if(BUILD_TESTING)
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)
@@ -250,6 +312,14 @@ if(BUILD_TESTING)
"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(
@@ -262,6 +332,6 @@ install(
)
install(
DIRECTORY include/
DIRECTORY include/ ${CMAKE_CURRENT_BINARY_DIR}/include/
DESTINATION include
)

View File

@@ -4,7 +4,12 @@ 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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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_;
};

View File

@@ -47,9 +47,6 @@ namespace node_interfaces
class NodeBaseInterface;
} // namespace node_interfaces
namespace client
{
class ClientBase
{
public:
@@ -68,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;
@@ -100,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_;
@@ -185,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
@@ -201,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);
}
@@ -270,7 +279,6 @@ private:
std::mutex pending_requests_mutex_;
};
} // namespace client
} // namespace rclcpp
#endif // RCLCPP__CLIENT_HPP_

View File

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

View File

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

View File

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

View File

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

View 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_

View File

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

View File

@@ -116,7 +116,7 @@ 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);
void (*reset_error)() = rcl_reset_error);
class RCLErrorBase
{

View File

@@ -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.
/**
@@ -234,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.
@@ -293,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
@@ -322,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
@@ -342,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_;

View File

@@ -35,7 +35,7 @@ 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. */
@@ -45,13 +45,13 @@ 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.
/**
@@ -81,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,
@@ -109,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,

View File

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

View File

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

View File

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

View File

@@ -23,6 +23,7 @@
#include <exception>
#include <map>
#include <memory>
#include <mutex>
#include <unordered_map>
#include <set>
@@ -148,7 +149,7 @@ 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.
/**
@@ -185,14 +186,16 @@ 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;
}
@@ -238,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,
@@ -301,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,
@@ -315,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,
@@ -346,6 +352,7 @@ private:
get_next_unique_id();
IntraProcessManagerImplBase::SharedPtr impl_;
std::mutex take_mutex_;
};
} // namespace intra_process_manager

View File

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

View 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_

View File

@@ -41,7 +41,7 @@
/**
* 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.
*
@@ -56,7 +56,7 @@
/**
* 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.
*
@@ -110,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_

View File

@@ -228,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;
}

View File

@@ -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);
};

View File

@@ -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>
{
@@ -77,7 +79,7 @@ public:
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.
@@ -89,7 +91,7 @@ public:
Node(
const std::string & node_name,
const std::string & namespace_,
rclcpp::context::Context::SharedPtr context,
rclcpp::Context::SharedPtr context,
bool use_intra_process_comms = false);
RCLCPP_PUBLIC
@@ -107,6 +109,12 @@ 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
@@ -126,7 +134,7 @@ public:
*/
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,
@@ -141,7 +149,7 @@ public:
*/
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,
@@ -167,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,
@@ -198,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,
@@ -217,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,
@@ -225,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,
@@ -233,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,
@@ -342,7 +350,7 @@ 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.
@@ -356,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
@@ -398,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_

View File

@@ -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;
}
@@ -216,8 +214,8 @@ Node::set_parameter_if_not_set(
rclcpp::parameter::ParameterVariant parameter_variant;
if (!this->get_parameter(name, parameter_variant)) {
this->set_parameters({
rclcpp::parameter::ParameterVariant(name, value),
});
rclcpp::parameter::ParameterVariant(name, value),
});
}
}
@@ -248,7 +246,6 @@ Node::get_parameter_or(
return got_parameter;
}
} // namespace node
} // namespace rclcpp
#endif // RCLCPP__NODE_IMPL_HPP_

View File

@@ -39,7 +39,7 @@ public:
NodeBase(
const std::string & node_name,
const std::string & namespace_,
rclcpp::context::Context::SharedPtr context);
rclcpp::Context::SharedPtr context);
RCLCPP_PUBLIC
virtual
@@ -57,7 +57,7 @@ public:
RCLCPP_PUBLIC
virtual
rclcpp::context::Context::SharedPtr
rclcpp::Context::SharedPtr
get_context();
RCLCPP_PUBLIC
@@ -118,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_;

View File

@@ -56,7 +56,7 @@ public:
/** \return SharedPtr to the node's context. */
RCLCPP_PUBLIC
virtual
rclcpp::context::Context::SharedPtr
rclcpp::Context::SharedPtr
get_context() = 0;
/// Return the rcl_node_t node handle (non-const version).

View 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_

View File

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

View File

@@ -96,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
@@ -127,7 +127,7 @@ 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_ */
std::atomic_size_t graph_users_count_;

View File

@@ -113,7 +113,7 @@ public:
*/
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.
@@ -128,7 +128,7 @@ 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().

View 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_

View File

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

View File

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

View File

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

View File

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

View File

@@ -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;
};

View File

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

View File

@@ -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;
};

View File

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

View File

@@ -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;
};

View File

@@ -15,6 +15,7 @@
#ifndef RCLCPP__PARAMETER_CLIENT_HPP_
#define RCLCPP__PARAMETER_CLIENT_HPP_
#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -29,6 +30,7 @@
#include "rcl_interfaces/srv/set_parameters.hpp"
#include "rcl_interfaces/srv/set_parameters_atomically.hpp"
#include "rclcpp/executors.hpp"
#include "rclcpp/create_subscription.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/parameter.hpp"
@@ -38,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_

View 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_

View File

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

View File

@@ -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)
@@ -98,6 +95,18 @@ 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.
@@ -293,8 +302,6 @@ protected:
MessageDeleter message_deleter_;
};
} // namespace publisher
} // namespace rclcpp
#endif // RCLCPP__PUBLISHER_HPP_

View File

@@ -46,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)>;
@@ -58,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;
@@ -66,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;
@@ -96,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
{
@@ -129,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);

View File

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

View File

@@ -17,47 +17,47 @@
* `rclcpp` provides the canonical C++ API for interacting with ROS.
* It consists of these main components:
*
* - Nodes
* - rclcpp::node::Node
* - Node
* - rclcpp::Node
* - rclcpp/node.hpp
* - Publisher
* - rclcpp::node::Node::create_publisher()
* - rclcpp::publisher::Publisher
* - rclcpp::publisher::Publisher::publish()
* - rclcpp::Node::create_publisher()
* - rclcpp::Publisher
* - rclcpp::Publisher::publish()
* - rclcpp/publisher.hpp
* - Subscription
* - rclcpp::node::Node::create_subscription()
* - rclcpp::subscription::Subscription
* - rclcpp::Node::create_subscription()
* - rclcpp::Subscription
* - rclcpp/subscription.hpp
* - Service Client
* - rclcpp::node::Node::create_client()
* - rclcpp::client::Client
* - rclcpp::Node::create_client()
* - rclcpp::Client
* - rclcpp/client.hpp
* - Service Server
* - rclcpp::node::Node::create_service()
* - rclcpp::service::Service
* - rclcpp::Node::create_service()
* - rclcpp::Service
* - rclcpp/service.hpp
* - Timer
* - rclcpp::node::Node::create_wall_timer()
* - rclcpp::timer::WallTimer
* - rclcpp::timer::TimerBase
* - rclcpp::Node::create_wall_timer()
* - rclcpp::WallTimer
* - rclcpp::TimerBase
* - rclcpp/timer.hpp
* - Parameters:
* - rclcpp::node::Node::set_parameters()
* - rclcpp::node::Node::get_parameters()
* - rclcpp::node::Node::get_parameter()
* - rclcpp::node::Node::describe_parameters()
* - rclcpp::node::Node::list_parameters()
* - rclcpp::node::Node::register_param_change_callback()
* - 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::parameter_client::AsyncParametersClient
* - rclcpp::parameter_client::SyncParametersClient
* - rclcpp::AsyncParametersClient
* - rclcpp::SyncParametersClient
* - rclcpp/parameter.hpp
* - rclcpp/parameter_client.hpp
* - rclcpp/parameter_service.hpp
* - Rate:
* - rclcpp::rate::Rate
* - rclcpp::rate::WallRate
* - rclcpp::Rate
* - rclcpp::WallRate
* - rclcpp/rate.hpp
*
* There are also some components which help control the execution of callbacks:
@@ -66,32 +66,46 @@
* - rclcpp::spin()
* - rclcpp::spin_some()
* - rclcpp::spin_until_future_complete()
* - rclcpp::executors::single_threaded_executor::SingleThreadedExecutor
* - rclcpp::executors::single_threaded_executor::SingleThreadedExecutor::add_node()
* - rclcpp::executors::single_threaded_executor::SingleThreadedExecutor::spin()
* - rclcpp::executors::multi_threaded_executor::MultiThreadedExecutor
* - rclcpp::executors::multi_threaded_executor::MultiThreadedExecutor::add_node()
* - rclcpp::executors::multi_threaded_executor::MultiThreadedExecutor::spin()
* - 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::Node::create_callback_group()
* - 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::Node::get_graph_event()
* - rclcpp::node::Node::wait_for_graph_change()
* - rclcpp::event::Event
* - rclcpp::Node::get_graph_event()
* - rclcpp::Node::wait_for_graph_change()
* - rclcpp::Event
* - List topic names and types:
* - rclcpp::node::Node::get_topic_names_and_types()
* - rclcpp::Node::get_topic_names_and_types()
* - Get the number of publishers or subscribers on a topic:
* - rclcpp::node::Node::count_publishers()
* - rclcpp::node::Node::count_subscribers()
* - 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:
*
@@ -107,7 +121,7 @@
* - rclcpp/strategies/allocator_memory_strategy.hpp
* - rclcpp/strategies/message_pool_memory_strategy.hpp
* - Context object which is shared amongst multiple Nodes:
* - rclcpp::context::Context
* - rclcpp::Context
* - rclcpp/context.hpp
* - rclcpp/contexts/default_context.hpp
* - Various utilities:
@@ -126,6 +140,7 @@
#include <memory>
#include "rclcpp/executors.hpp"
#include "rclcpp/logging.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/parameter.hpp"
#include "rclcpp/parameter_client.hpp"
@@ -135,26 +150,4 @@
#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_

View File

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

View File

@@ -35,8 +35,6 @@
namespace rclcpp
{
namespace service
{
class ServiceBase
{
@@ -60,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(
@@ -74,6 +76,10 @@ protected:
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_;
@@ -83,8 +89,6 @@ protected:
bool owns_rcl_handle_ = true;
};
using any_service_callback::AnyServiceCallback;
template<typename ServiceT>
class Service : public ServiceBase
{
@@ -172,6 +176,7 @@ public:
(std::cerr << ss.str()).flush();
rcl_reset_error();
}
delete service_handle_;
}
}
@@ -187,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);
@@ -213,7 +219,6 @@ private:
AnyServiceCallback<ServiceT> any_callback_;
};
} // namespace service
} // namespace rclcpp
#endif // RCLCPP__SERVICE_HPP_

View File

@@ -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();

View File

@@ -45,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
@@ -78,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;
@@ -117,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
@@ -281,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_

View File

@@ -47,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)>;
@@ -55,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;
@@ -74,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 =
@@ -87,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(),
@@ -109,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;
@@ -127,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) {

View File

@@ -15,58 +15,105 @@
#ifndef RCLCPP__TIME_HPP_
#define RCLCPP__TIME_HPP_
#include <utility>
#include "builtin_interfaces/msg/time.hpp"
#include "rcl/time.h"
#include "rcutils/time.h"
#include "rclcpp/exceptions.hpp"
#include "rclcpp/visibility_control.hpp"
#include "rcl/time.h"
#include "rclcpp/duration.hpp"
namespace rclcpp
{
class Clock;
class Time
{
public:
template<rcl_time_source_type_t ClockT = RCL_SYSTEM_TIME>
static Time
now()
{
rcutils_time_point_value_t rcutils_now = 0;
rcutils_ret_t ret = RCUTILS_RET_ERROR;
if (ClockT == RCL_ROS_TIME) {
throw std::runtime_error("RCL_ROS_TIME is currently not implemented.");
ret = false;
} else if (ClockT == RCL_SYSTEM_TIME) {
ret = rcutils_system_time_now(&rcutils_now);
} else if (ClockT == RCL_STEADY_TIME) {
ret = rcutils_steady_time_now(&rcutils_now);
}
if (ret != RCUTILS_RET_OK) {
rclcpp::exceptions::throw_from_rcl_error(
ret, "Could not get current time: ");
}
RCLCPP_PUBLIC
Time(int32_t seconds, uint32_t nanoseconds, rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
return Time(std::move(rcutils_now));
}
RCLCPP_PUBLIC
explicit Time(uint64_t nanoseconds = 0, rcl_clock_type_t clock = RCL_SYSTEM_TIME);
operator builtin_interfaces::msg::Time() const
{
builtin_interfaces::msg::Time msg_time;
msg_time.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_time_));
msg_time.nanosec = static_cast<std::uint32_t>(rcl_time_ % (1000 * 1000 * 1000));
return msg_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_value_t rcl_time_;
explicit Time(rcl_time_point_value_t && rcl_time)
: rcl_time_(std::forward<decltype(rcl_time)>(rcl_time))
{}
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_

View 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_

View File

@@ -37,8 +37,6 @@
namespace rclcpp
{
namespace timer
{
class TimerBase
{
@@ -182,7 +180,6 @@ protected:
template<typename CallbackType>
using WallTimer = GenericTimer<CallbackType, std::chrono::steady_clock>;
} // namespace timer
} // namespace rclcpp
#endif // RCLCPP__TIMER_HPP_

View File

@@ -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.
/**
@@ -75,32 +73,32 @@ 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 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 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_

View File

@@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>rclcpp</name>
<version>0.0.2</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>
@@ -27,6 +27,7 @@
<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>

View 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_

View File

@@ -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);

View File

@@ -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
{
@@ -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
View 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

View File

@@ -14,6 +14,6 @@
#include "rclcpp/context.hpp"
using rclcpp::context::Context;
using rclcpp::Context;
Context::Context() {}

View 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

View File

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

View File

@@ -44,7 +44,7 @@ throw_from_rcl_error(
rcl_ret_t ret,
const std::string & prefix,
const rcl_error_state_t * error_state,
void (* reset_error)())
void (*reset_error)())
{
if (RCL_RET_OK == ret) {
throw std::invalid_argument("ret is RCL_RET_OK");

View File

@@ -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();

View File

@@ -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());
}

View File

@@ -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();

View File

@@ -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) {}
@@ -29,7 +29,7 @@ SingleThreadedExecutor::spin()
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);
}

View File

@@ -54,9 +54,10 @@ rclcpp::expand_topic_or_service_name(
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);
});
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) {

View File

@@ -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_) {

View File

@@ -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);

View 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

View File

@@ -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) {

View File

@@ -24,13 +24,15 @@
#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(
@@ -47,10 +49,11 @@ Node::Node(
Node::Node(
const std::string & node_name,
const std::string & namespace_,
rclcpp::context::Context::SharedPtr context,
rclcpp::Context::SharedPtr context,
bool use_intra_process_comms)
: 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())),
@@ -58,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)
{
}
@@ -77,6 +86,12 @@ 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)
@@ -117,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);
@@ -174,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();
@@ -182,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()
{

View File

@@ -30,7 +30,7 @@ using rclcpp::node_interfaces::NodeBase;
NodeBase::NodeBase(
const std::string & node_name,
const std::string & namespace_,
rclcpp::context::Context::SharedPtr context)
rclcpp::Context::SharedPtr context)
: context_(context),
node_handle_(nullptr),
default_callback_group_(nullptr),
@@ -92,6 +92,8 @@ NodeBase::NodeBase(
// 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;
@@ -131,13 +133,15 @@ NodeBase::NodeBase(
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;
@@ -172,7 +176,7 @@ NodeBase::get_namespace() const
return rcl_node_get_namespace(node_handle_.get());
}
rclcpp::context::Context::SharedPtr
rclcpp::Context::SharedPtr
NodeBase::get_context()
{
return context_;

View 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_;
}

View File

@@ -233,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());
@@ -258,10 +258,10 @@ 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_++;
@@ -275,7 +275,7 @@ NodeGraph::get_graph_event()
void
NodeGraph::wait_for_graph_change(
rclcpp::event::Event::SharedPtr event,
rclcpp::Event::SharedPtr event,
std::chrono::nanoseconds timeout)
{
using rclcpp::exceptions::InvalidEventError;
@@ -297,7 +297,7 @@ NodeGraph::wait_for_graph_change(
}
}
auto pred = [&event]() {
return event->check() || !rclcpp::utilities::ok();
return event->check() || !rclcpp::ok();
};
std::unique_lock<std::mutex> graph_lock(graph_mutex_);
if (!pred()) {

View 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_;
}

View File

@@ -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>();
@@ -118,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));
}
@@ -161,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;
@@ -180,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 {
@@ -197,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) ==
@@ -234,8 +238,8 @@ void
NodeParameters::register_param_change_callback(ParametersCallbackFunction callback)
{
if (parameters_callback_) {
fprintf(stderr, "Warning: param_change_callback already registered, "
"overwriting previous callback\n");
RCUTILS_LOG_WARN("param_change_callback already registered, "
"overwriting previous callback")
}
parameters_callback_ = callback;
}

View File

@@ -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()
);
}
}

View File

@@ -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());
}
}

View File

@@ -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()
);
}
}

View File

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

View 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_;
}

View File

@@ -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);
}

View 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_

View File

@@ -33,7 +33,7 @@
#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,
@@ -125,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
{

View File

@@ -25,7 +25,7 @@
#include "rmw/error_handling.h"
#include "rmw/rmw.h"
using rclcpp::service::ServiceBase;
using rclcpp::ServiceBase;
ServiceBase::ServiceBase(
std::shared_ptr<rcl_node_t> node_handle,
@@ -46,13 +46,25 @@ ServiceBase::get_service_name()
return this->service_name_;
}
const rcl_service_t *
rcl_service_t *
ServiceBase::get_service_handle()
{
return service_handle_;
}
const rcl_service_t *
ServiceBase::get_service_handle() const
{
return service_handle_;
}
rcl_node_t *
ServiceBase::get_rcl_node_handle()
{
return node_handle_.get();
}
const rcl_node_t *
ServiceBase::get_rcl_node_handle() const
{
return node_handle_.get();

View File

@@ -25,7 +25,7 @@
#include "rmw/rmw.h"
using rclcpp::subscription::SubscriptionBase;
using rclcpp::SubscriptionBase;
SubscriptionBase::SubscriptionBase(
std::shared_ptr<rcl_node_t> node_handle,
@@ -79,6 +79,12 @@ SubscriptionBase::get_topic_name() const
return rcl_subscription_get_topic_name(&subscription_handle_);
}
rcl_subscription_t *
SubscriptionBase::get_subscription_handle()
{
return &subscription_handle_;
}
const rcl_subscription_t *
SubscriptionBase::get_subscription_handle() const
{

255
rclcpp/src/rclcpp/time.cpp Normal file
View File

@@ -0,0 +1,255 @@
// 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 <limits>
#include <utility>
#include "rclcpp/clock.hpp"
#include "rclcpp/duration.hpp"
#include "builtin_interfaces/msg/time.hpp"
#include "rcl/time.h"
#include "rclcpp/exceptions.hpp"
#include "rcutils/logging_macros.h"
namespace
{
rcl_time_point_t
init_time_point(rcl_clock_type_t & clock_type)
{
rcl_time_point_t time_point;
time_point.clock_type = clock_type;
return time_point;
}
} // namespace
namespace rclcpp
{
Time::Time(int32_t seconds, uint32_t nanoseconds, rcl_clock_type_t clock_type)
: rcl_time_(init_time_point(clock_type))
{
if (seconds < 0) {
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
}
rcl_time_.nanoseconds = RCL_S_TO_NS(static_cast<uint64_t>(seconds));
rcl_time_.nanoseconds += nanoseconds;
}
Time::Time(uint64_t nanoseconds, rcl_clock_type_t clock_type)
: rcl_time_(init_time_point(clock_type))
{
rcl_time_.nanoseconds = nanoseconds;
}
Time::Time(const Time & rhs)
: rcl_time_(rhs.rcl_time_)
{
rcl_time_.nanoseconds = rhs.rcl_time_.nanoseconds;
}
Time::Time(
const builtin_interfaces::msg::Time & time_msg,
rcl_clock_type_t ros_time)
{
rcl_time_ = init_time_point(ros_time);
if (time_msg.sec < 0) {
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
}
rcl_time_.nanoseconds = RCL_S_TO_NS(static_cast<uint64_t>(time_msg.sec));
rcl_time_.nanoseconds += time_msg.nanosec;
}
Time::Time(const rcl_time_point_t & time_point)
: rcl_time_(time_point)
{
// noop
}
Time::~Time()
{
}
Time::operator builtin_interfaces::msg::Time() const
{
builtin_interfaces::msg::Time msg_time;
msg_time.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_time_.nanoseconds));
msg_time.nanosec = static_cast<std::uint32_t>(rcl_time_.nanoseconds % (1000 * 1000 * 1000));
return msg_time;
}
Time &
Time::operator=(const Time & rhs)
{
rcl_time_ = rhs.rcl_time_;
return *this;
}
Time &
Time::operator=(const builtin_interfaces::msg::Time & time_msg)
{
if (time_msg.sec < 0) {
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
}
rcl_clock_type_t ros_time = RCL_ROS_TIME;
rcl_time_ = init_time_point(ros_time); // TODO(tfoote) hard coded ROS here
rcl_time_.nanoseconds = RCL_S_TO_NS(static_cast<uint64_t>(time_msg.sec));
rcl_time_.nanoseconds += time_msg.nanosec;
return *this;
}
bool
Time::operator==(const rclcpp::Time & rhs) const
{
if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
throw std::runtime_error("can't compare times with different time sources");
}
return rcl_time_.nanoseconds == rhs.rcl_time_.nanoseconds;
}
bool
Time::operator!=(const rclcpp::Time & rhs) const
{
return !(*this == rhs);
}
bool
Time::operator<(const rclcpp::Time & rhs) const
{
if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
throw std::runtime_error("can't compare times with different time sources");
}
return rcl_time_.nanoseconds < rhs.rcl_time_.nanoseconds;
}
bool
Time::operator<=(const rclcpp::Time & rhs) const
{
if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
throw std::runtime_error("can't compare times with different time sources");
}
return rcl_time_.nanoseconds <= rhs.rcl_time_.nanoseconds;
}
bool
Time::operator>=(const rclcpp::Time & rhs) const
{
if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
throw std::runtime_error("can't compare times with different time sources");
}
return rcl_time_.nanoseconds >= rhs.rcl_time_.nanoseconds;
}
bool
Time::operator>(const rclcpp::Time & rhs) const
{
if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
throw std::runtime_error("can't compare times with different time sources");
}
return rcl_time_.nanoseconds > rhs.rcl_time_.nanoseconds;
}
Time
Time::operator+(const rclcpp::Duration & rhs) const
{
if (rhs.nanoseconds() > 0 && (uint64_t)rhs.nanoseconds() >
std::numeric_limits<rcl_time_point_value_t>::max() -
(rcl_time_point_value_t)this->nanoseconds())
{
throw std::overflow_error("addition leads to uint64_t overflow");
}
return Time(this->nanoseconds() + rhs.nanoseconds(), this->get_clock_type());
}
Duration
Time::operator-(const rclcpp::Time & rhs) const
{
if (rcl_time_.clock_type != rhs.rcl_time_.clock_type) {
throw std::runtime_error("can't subtract times with different time sources");
}
if (rcl_time_.nanoseconds >
(uint64_t)std::numeric_limits<rcl_duration_value_t>::max() + rhs.rcl_time_.nanoseconds)
{
throw std::underflow_error("time subtraction leads to int64_t overflow");
}
if (rcl_time_.nanoseconds < rhs.rcl_time_.nanoseconds) {
rcl_time_point_value_t negative_delta = rhs.rcl_time_.nanoseconds - rcl_time_.nanoseconds;
if (negative_delta > (uint64_t) std::numeric_limits<rcl_duration_value_t>::min()) {
throw std::underflow_error("time subtraction leads to int64_t underflow");
}
}
return Duration(rcl_time_.nanoseconds - rhs.rcl_time_.nanoseconds);
}
Time
Time::operator-(const rclcpp::Duration & rhs) const
{
if (rhs.nanoseconds() > 0 && rcl_time_.nanoseconds >
std::numeric_limits<rcl_time_point_value_t>::max() - (uint64_t)rhs.nanoseconds())
{
throw std::underflow_error("time subtraction leads to uint64_t overflow");
}
if (rcl_time_.nanoseconds < (uint64_t) std::numeric_limits<rcl_duration_value_t>::max() &&
(int64_t)rcl_time_.nanoseconds < (int64_t)rhs.nanoseconds())
{
throw std::underflow_error("time subtraction leads to uint64_t underflow");
}
return Time(rcl_time_.nanoseconds - rhs.nanoseconds(), rcl_time_.clock_type);
}
uint64_t
Time::nanoseconds() const
{
return rcl_time_.nanoseconds;
}
rcl_clock_type_t
Time::get_clock_type() const
{
return rcl_time_.clock_type;
}
Time
operator+(const rclcpp::Duration & lhs, const rclcpp::Time & rhs)
{
if (rhs.nanoseconds() >
std::numeric_limits<rcl_time_point_value_t>::max() - (rcl_time_point_value_t)lhs.nanoseconds())
{
throw std::overflow_error("addition leads to uint64_t overflow");
}
return Time(lhs.nanoseconds() + rhs.nanoseconds(), rhs.get_clock_type());
}
} // namespace rclcpp

View File

@@ -0,0 +1,296 @@
// 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 <memory>
#include <string>
#include <utility>
#include <vector>
#include "builtin_interfaces/msg/time.hpp"
#include "rcl/time.h"
#include "rcutils/logging_macros.h"
#include "rclcpp/clock.hpp"
#include "rclcpp/exceptions.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/time.hpp"
#include "rclcpp/time_source.hpp"
namespace rclcpp
{
TimeSource::TimeSource(std::shared_ptr<rclcpp::Node> node)
: ros_time_active_(false)
{
this->attachNode(node);
}
TimeSource::TimeSource()
: ros_time_active_(false)
{
}
void TimeSource::attachNode(rclcpp::Node::SharedPtr node)
{
attachNode(
node->get_node_base_interface(),
node->get_node_topics_interface(),
node->get_node_graph_interface(),
node->get_node_services_interface());
}
void TimeSource::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)
{
node_base_ = node_base_interface;
node_topics_ = node_topics_interface;
node_graph_ = node_graph_interface;
node_services_ = node_services_interface;
// TODO(tfoote): Update QOS
const std::string & topic_name = "/clock";
rclcpp::callback_group::CallbackGroup::SharedPtr group;
using rclcpp::message_memory_strategy::MessageMemoryStrategy;
auto msg_mem_strat = MessageMemoryStrategy<MessageT, Alloc>::create_default();
auto allocator = std::make_shared<Alloc>();
auto cb = std::bind(&TimeSource::clock_cb, this, std::placeholders::_1);
clock_subscription_ = rclcpp::create_subscription<MessageT, decltype(cb), Alloc, SubscriptionT>(
node_topics_.get(),
topic_name,
std::move(cb),
rmw_qos_profile_default,
group,
false,
false,
msg_mem_strat,
allocator);
parameter_client_ = std::make_shared<rclcpp::AsyncParametersClient>(
node_base_,
node_topics_,
node_graph_,
node_services_
);
parameter_subscription_ =
parameter_client_->on_parameter_event(std::bind(&TimeSource::on_parameter_event,
this, std::placeholders::_1));
}
void TimeSource::detachNode()
{
this->ros_time_active_ = false;
clock_subscription_.reset();
parameter_client_.reset();
node_base_.reset();
node_topics_.reset();
node_graph_.reset();
node_services_.reset();
disable_ros_time();
}
void TimeSource::attachClock(std::shared_ptr<rclcpp::Clock> clock)
{
if (clock->get_clock_type() != RCL_ROS_TIME) {
throw std::invalid_argument("Cannot attach clock to a time source that's not a ROS clock");
}
std::lock_guard<std::mutex> guard(clock_list_lock_);
associated_clocks_.push_back(clock);
// Set the clock if there's already data for it
if (last_msg_set_) {
set_clock(last_msg_set_, ros_time_active_, clock);
}
}
void TimeSource::detachClock(std::shared_ptr<rclcpp::Clock> clock)
{
std::lock_guard<std::mutex> guard(clock_list_lock_);
auto result = std::find(associated_clocks_.begin(), associated_clocks_.end(), clock);
if (result != associated_clocks_.end()) {
associated_clocks_.erase(result);
} else {
RCUTILS_LOG_ERROR("Failed to remove clock");
}
}
TimeSource::~TimeSource()
{
if (node_base_ || node_topics_ || node_graph_ || node_services_) {
this->detachNode();
}
}
void TimeSource::set_clock(
const builtin_interfaces::msg::Time::SharedPtr msg, bool set_ros_time_enabled,
std::shared_ptr<rclcpp::Clock> clock)
{
// Compute diff
rclcpp::Time msg_time = rclcpp::Time(*msg);
rclcpp::Time now = clock->now();
auto diff = now - msg_time;
rclcpp::TimeJump jump;
jump.delta_.nanoseconds = diff.nanoseconds();
// Compute jump type
if (clock->ros_time_is_active()) {
if (set_ros_time_enabled) {
jump.jump_type_ = TimeJump::ClockChange_t::ROS_TIME_NO_CHANGE;
} else {
jump.jump_type_ = TimeJump::ClockChange_t::ROS_TIME_DEACTIVATED;
}
} else if (!clock->ros_time_is_active()) {
if (set_ros_time_enabled) {
jump.jump_type_ = TimeJump::ClockChange_t::ROS_TIME_ACTIVATED;
} else {
jump.jump_type_ = TimeJump::ClockChange_t::SYSTEM_TIME_NO_CHANGE;
}
}
if (jump.jump_type_ == TimeJump::ClockChange_t::SYSTEM_TIME_NO_CHANGE) {
// No change/no updates don't act.
return;
}
auto active_callbacks = clock->get_triggered_callback_handlers(jump);
clock->invoke_prejump_callbacks(active_callbacks);
// Do change
if (jump.jump_type_ == TimeJump::ClockChange_t::ROS_TIME_DEACTIVATED) {
disable_ros_time(clock);
} else if (jump.jump_type_ == TimeJump::ClockChange_t::ROS_TIME_ACTIVATED) {
enable_ros_time(clock);
}
if (jump.jump_type_ == TimeJump::ClockChange_t::ROS_TIME_ACTIVATED ||
jump.jump_type_ == TimeJump::ClockChange_t::ROS_TIME_NO_CHANGE)
{
auto ret = rcl_set_ros_time_override(&(clock->rcl_clock_), msg_time.nanoseconds());
if (ret != RCL_RET_OK) {
rclcpp::exceptions::throw_from_rcl_error(
ret, "Failed to set ros_time_override_status");
}
}
// Post change callbacks
clock->invoke_postjump_callbacks(active_callbacks, jump);
}
void TimeSource::clock_cb(const builtin_interfaces::msg::Time::SharedPtr msg)
{
if (!this->ros_time_active_) {
enable_ros_time();
}
// Cache the last message in case a new clock is attached.
last_msg_set_ = msg;
std::lock_guard<std::mutex> guard(clock_list_lock_);
for (auto it = associated_clocks_.begin(); it != associated_clocks_.end(); ++it) {
set_clock(msg, true, *it);
}
}
void TimeSource::on_parameter_event(const rcl_interfaces::msg::ParameterEvent::SharedPtr event)
{
// Filter for only 'use_sim_time' being added or changed.
rclcpp::ParameterEventsFilter filter(event, {"use_sim_time"},
{rclcpp::ParameterEventsFilter::EventType::NEW,
rclcpp::ParameterEventsFilter::EventType::CHANGED});
for (auto & it : filter.get_events()) {
if (it.second->value.type != parameter::ParameterType::PARAMETER_BOOL) {
RCUTILS_LOG_ERROR("use_sim_time parameter set to something besides a bool");
continue;
}
if (it.second->value.bool_value) {
parameter_state_ = SET_TRUE;
enable_ros_time();
} else {
parameter_state_ = SET_FALSE;
disable_ros_time();
}
}
// Handle the case that use_sim_time was deleted.
rclcpp::ParameterEventsFilter deleted(event, {"use_sim_time"},
{rclcpp::ParameterEventsFilter::EventType::DELETED});
for (auto & it : deleted.get_events()) {
(void) it; // if there is a match it's already matched, don't bother reading it.
// If the parameter is deleted mark it as unset but dont' change state.
parameter_state_ = UNSET;
}
}
void TimeSource::enable_ros_time(std::shared_ptr<rclcpp::Clock> clock)
{
auto ret = rcl_enable_ros_time_override(&clock->rcl_clock_);
if (ret != RCL_RET_OK) {
rclcpp::exceptions::throw_from_rcl_error(
ret, "Failed to enable ros_time_override_status");
}
}
void TimeSource::disable_ros_time(std::shared_ptr<rclcpp::Clock> clock)
{
auto ret = rcl_disable_ros_time_override(&clock->rcl_clock_);
if (ret != RCL_RET_OK) {
rclcpp::exceptions::throw_from_rcl_error(
ret, "Failed to enable ros_time_override_status");
}
}
void TimeSource::enable_ros_time()
{
if (ros_time_active_) {
// already enabled no-op
return;
}
// Local storage
ros_time_active_ = true;
// Update all attached clocks
std::lock_guard<std::mutex> guard(clock_list_lock_);
for (auto it = associated_clocks_.begin(); it != associated_clocks_.end(); ++it) {
auto msg = std::make_shared<builtin_interfaces::msg::Time>();
msg->sec = 0;
msg->nanosec = 0;
set_clock(msg, true, *it);
}
}
void TimeSource::disable_ros_time()
{
if (!ros_time_active_) {
// already disabled no-op
return;
}
// Local storage
ros_time_active_ = false;
// Update all attached clocks
std::lock_guard<std::mutex> guard(clock_list_lock_);
for (auto it = associated_clocks_.begin(); it != associated_clocks_.end(); ++it) {
auto msg = std::make_shared<builtin_interfaces::msg::Time>();
set_clock(msg, false, *it);
}
}
} // namespace rclcpp

View File

@@ -17,7 +17,7 @@
#include <chrono>
#include <string>
using rclcpp::timer::TimerBase;
using rclcpp::TimerBase;
TimerBase::TimerBase(std::chrono::nanoseconds period)
{

View File

@@ -50,76 +50,26 @@ static std::mutex g_interrupt_mutex;
#ifdef HAS_SIGACTION
static struct sigaction old_action;
#else
static void (* old_signal_handler)(int) = 0;
typedef void (* signal_handler_t)(int);
static signal_handler_t old_signal_handler = 0;
#endif
void
#ifdef HAS_SIGACTION
signal_handler(int signal_value, siginfo_t * siginfo, void * context)
struct sigaction
set_sigaction(int signal_value, const struct sigaction & action)
#else
signal_handler(int signal_value)
signal_handler_t
set_signal_handler(int signal_value, signal_handler_t signal_handler)
#endif
{
// TODO(wjwwood): remove? move to console logging at some point?
printf("signal_handler(%d)\n", signal_value);
#ifdef HAS_SIGACTION
if (old_action.sa_flags & SA_SIGINFO) {
if (old_action.sa_sigaction != NULL) {
old_action.sa_sigaction(signal_value, siginfo, context);
}
} else {
// *INDENT-OFF*
if (
old_action.sa_handler != NULL && // Is set
old_action.sa_handler != SIG_DFL && // Is not default
old_action.sa_handler != SIG_IGN) // Is not ignored
// *INDENT-ON*
{
old_action.sa_handler(signal_value);
}
}
#else
if (old_signal_handler) {
old_signal_handler(signal_value);
}
#endif
g_signal_status = signal_value;
{
std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
for (auto & kv : g_sigint_guard_cond_handles) {
rcl_ret_t status = rcl_trigger_guard_condition(&(kv.second));
if (status != RCL_RET_OK) {
fprintf(stderr,
"[rclcpp::error] failed to trigger guard condition: %s\n", rcl_get_error_string_safe());
}
}
}
g_is_interrupted.store(true);
g_interrupt_condition_variable.notify_all();
}
void
rclcpp::utilities::init(int argc, char * argv[])
{
g_is_interrupted.store(false);
if (rcl_init(argc, argv, rcl_get_default_allocator()) != RCL_RET_OK) {
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
throw std::runtime_error(
std::string("failed to initialize rmw implementation: ") + rcl_get_error_string_safe());
// *INDENT-ON*
}
#ifdef HAS_SIGACTION
struct sigaction action;
memset(&action, 0, sizeof(action));
sigemptyset(&action.sa_mask);
action.sa_sigaction = ::signal_handler;
action.sa_flags = SA_SIGINFO;
ssize_t ret = sigaction(SIGINT, &action, &old_action);
struct sigaction old_action;
ssize_t ret = sigaction(signal_value, &action, &old_action);
if (ret == -1)
#else
::old_signal_handler = std::signal(SIGINT, ::signal_handler);
signal_handler_t old_signal_handler = std::signal(signal_value, signal_handler);
// NOLINTNEXTLINE(readability/braces)
if (::old_signal_handler == SIG_ERR)
if (old_signal_handler == SIG_ERR)
#endif
{
const size_t error_length = 1024;
@@ -147,10 +97,99 @@ rclcpp::utilities::init(int argc, char * argv[])
error_string);
// *INDENT-ON*
}
#ifdef HAS_SIGACTION
return old_action;
#else
return old_signal_handler;
#endif
}
void
trigger_interrupt_guard_condition(int signal_value)
{
g_signal_status = signal_value;
{
std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
for (auto & kv : g_sigint_guard_cond_handles) {
rcl_ret_t status = rcl_trigger_guard_condition(&(kv.second));
if (status != RCL_RET_OK) {
fprintf(stderr,
"[rclcpp::error] failed to trigger guard condition: %s\n", rcl_get_error_string_safe());
}
}
}
g_is_interrupted.store(true);
g_interrupt_condition_variable.notify_all();
}
void
#ifdef HAS_SIGACTION
signal_handler(int signal_value, siginfo_t * siginfo, void * context)
#else
signal_handler(int signal_value)
#endif
{
// TODO(wjwwood): remove? move to console logging at some point?
printf("signal_handler(%d)\n", signal_value);
#ifdef HAS_SIGACTION
if (old_action.sa_flags & SA_SIGINFO) {
if (old_action.sa_sigaction != NULL) {
old_action.sa_sigaction(signal_value, siginfo, context);
}
} else {
if (
old_action.sa_handler != NULL && // Is set
old_action.sa_handler != SIG_DFL && // Is not default
old_action.sa_handler != SIG_IGN) // Is not ignored
{
old_action.sa_handler(signal_value);
}
}
#else
if (old_signal_handler) {
old_signal_handler(signal_value);
}
#endif
trigger_interrupt_guard_condition(signal_value);
}
void
rclcpp::init(int argc, char * argv[])
{
g_is_interrupted.store(false);
if (rcl_init(argc, argv, rcl_get_default_allocator()) != RCL_RET_OK) {
std::string msg = "failed to initialize rmw implementation: ";
msg += rcl_get_error_string_safe();
rcl_reset_error();
throw std::runtime_error(msg);
}
#ifdef HAS_SIGACTION
struct sigaction action;
memset(&action, 0, sizeof(action));
sigemptyset(&action.sa_mask);
action.sa_sigaction = ::signal_handler;
action.sa_flags = SA_SIGINFO;
::old_action = set_sigaction(SIGINT, action);
// Register an on_shutdown hook to restore the old action.
rclcpp::on_shutdown(
[]() {
set_sigaction(SIGINT, ::old_action);
});
#else
::old_signal_handler = set_signal_handler(SIGINT, ::signal_handler);
// Register an on_shutdown hook to restore the old signal handler.
rclcpp::on_shutdown(
[]() {
set_signal_handler(SIGINT, ::old_signal_handler);
});
#endif
}
bool
rclcpp::utilities::ok()
rclcpp::ok()
{
return ::g_signal_status == 0;
}
@@ -159,21 +198,10 @@ static std::mutex on_shutdown_mutex_;
static std::vector<std::function<void(void)>> on_shutdown_callbacks_;
void
rclcpp::utilities::shutdown()
rclcpp::shutdown()
{
g_signal_status = SIGINT;
{
std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
for (auto & kv : g_sigint_guard_cond_handles) {
if (rcl_trigger_guard_condition(&(kv.second)) != RCL_RET_OK) {
fprintf(stderr,
"[rclcpp::error] failed to trigger sigint guard condition: %s\n",
rcl_get_error_string_safe());
}
}
}
g_is_interrupted.store(true);
g_interrupt_condition_variable.notify_all();
trigger_interrupt_guard_condition(SIGINT);
{
std::lock_guard<std::mutex> lock(on_shutdown_mutex_);
for (auto & on_shutdown_callback : on_shutdown_callbacks_) {
@@ -183,17 +211,17 @@ rclcpp::utilities::shutdown()
}
void
rclcpp::utilities::on_shutdown(std::function<void(void)> callback)
rclcpp::on_shutdown(std::function<void(void)> callback)
{
std::lock_guard<std::mutex> lock(on_shutdown_mutex_);
on_shutdown_callbacks_.push_back(callback);
}
rcl_guard_condition_t *
rclcpp::utilities::get_sigint_guard_condition(rcl_wait_set_t * waitset)
rclcpp::get_sigint_guard_condition(rcl_wait_set_t * wait_set)
{
std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
auto kv = g_sigint_guard_cond_handles.find(waitset);
auto kv = g_sigint_guard_cond_handles.find(wait_set);
if (kv != g_sigint_guard_cond_handles.end()) {
return &kv->second;
} else {
@@ -206,16 +234,16 @@ rclcpp::utilities::get_sigint_guard_condition(rcl_wait_set_t * waitset)
"Couldn't initialize guard condition: ") + rcl_get_error_string_safe());
// *INDENT-ON*
}
g_sigint_guard_cond_handles[waitset] = handle;
return &g_sigint_guard_cond_handles[waitset];
g_sigint_guard_cond_handles[wait_set] = handle;
return &g_sigint_guard_cond_handles[wait_set];
}
}
void
rclcpp::utilities::release_sigint_guard_condition(rcl_wait_set_t * waitset)
rclcpp::release_sigint_guard_condition(rcl_wait_set_t * wait_set)
{
std::lock_guard<std::mutex> lock(g_sigint_guard_cond_handles_mutex);
auto kv = g_sigint_guard_cond_handles.find(waitset);
auto kv = g_sigint_guard_cond_handles.find(wait_set);
if (kv != g_sigint_guard_cond_handles.end()) {
if (rcl_guard_condition_fini(&kv->second) != RCL_RET_OK) {
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
@@ -228,13 +256,13 @@ rclcpp::utilities::release_sigint_guard_condition(rcl_wait_set_t * waitset)
} else {
// *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
throw std::runtime_error(std::string(
"Tried to release sigint guard condition for nonexistent waitset"));
"Tried to release sigint guard condition for nonexistent wait set"));
// *INDENT-ON*
}
}
bool
rclcpp::utilities::sleep_for(const std::chrono::nanoseconds & nanoseconds)
rclcpp::sleep_for(const std::chrono::nanoseconds & nanoseconds)
{
std::chrono::nanoseconds time_left = nanoseconds;
{

View File

@@ -32,7 +32,7 @@ protected:
void SetUp()
{
node = std::make_shared<rclcpp::node::Node>("my_node", "/ns");
node = std::make_shared<rclcpp::Node>("my_node", "/ns");
}
void TearDown()
@@ -40,7 +40,7 @@ protected:
node.reset();
}
rclcpp::node::Node::SharedPtr node;
rclcpp::Node::SharedPtr node;
};
/*

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