Compare commits
71 Commits
node_inter
...
dashing
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
403aac9662 | ||
|
|
e8cf066d7d | ||
|
|
c4c39a2069 | ||
|
|
b3ecbd5ff7 | ||
|
|
052936980e | ||
|
|
6e133c2ad7 | ||
|
|
1f0f8f6176 | ||
|
|
ab2484295a | ||
|
|
c214ddc57b | ||
|
|
d27ca8ee85 | ||
|
|
342f225053 | ||
|
|
3c198de5b2 | ||
|
|
8906c9eb7f | ||
|
|
9e98aa70d3 | ||
|
|
6471043a0b | ||
|
|
f8bba370dc | ||
|
|
d5040ae304 | ||
|
|
3e5b6a47ea | ||
|
|
8c3fbce10d | ||
|
|
fb6ab9ef70 | ||
|
|
7629f5b6d9 | ||
|
|
7cb2ececcb | ||
|
|
0f4fc08a93 | ||
|
|
82f6dfa6de | ||
|
|
fadd923aa0 | ||
|
|
f954ce5145 | ||
|
|
895145cfc9 | ||
|
|
3cdb3cb1bf | ||
|
|
5d5d3ce09d | ||
|
|
839ad201ac | ||
|
|
f3b0aa170c | ||
|
|
6e76503d9a | ||
|
|
b4629bf889 | ||
|
|
3f31ad0f55 | ||
|
|
25eeffdfcc | ||
|
|
3293603396 | ||
|
|
50ec1e568a | ||
|
|
607e290732 | ||
|
|
47ce42bc3f | ||
|
|
d2f052ee3d | ||
|
|
b86127d721 | ||
|
|
5cb6a6eeb5 | ||
|
|
f41e33c2a7 | ||
|
|
10c34ee9e5 | ||
|
|
6d3cbd39d1 | ||
|
|
bfee90ab7a | ||
|
|
1927f7e40e | ||
|
|
f73d80e79c | ||
|
|
e2e35570d5 | ||
|
|
5c395d6651 | ||
|
|
24080a458d | ||
|
|
8ff51833ad | ||
|
|
347f8d0b1d | ||
|
|
ecc95009f1 | ||
|
|
d2b2f9124e | ||
|
|
ca01555936 | ||
|
|
0723a0a6fc | ||
|
|
8553fbea7f | ||
|
|
131a11bba5 | ||
|
|
29308dc8bc | ||
|
|
06275105fc | ||
|
|
30df5cdf36 | ||
|
|
1a662d46fb | ||
|
|
4467ce9913 | ||
|
|
005131dba8 | ||
|
|
05c19028f4 | ||
|
|
a8f4d391f2 | ||
|
|
0682ceb3e1 | ||
|
|
2152e0574b | ||
|
|
1081e75079 | ||
|
|
b17bbf31b3 |
@@ -2,6 +2,97 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
0.7.16 (2021-05-21)
|
||||
-------------------
|
||||
* Fix documented example in create_publisher. (`#1558 <https://github.com/ros2/rclcpp/issues/1558>`_) (`#1560 <https://github.com/ros2/rclcpp/issues/1560>`_)
|
||||
* Fix NodeOptions copy constructor. (`#1376 <https://github.com/ros2/rclcpp/issues/1376>`_) (`#1466 <https://github.com/ros2/rclcpp/issues/1466>`_)
|
||||
* Contributors: Ivan Santiago Paunovic, Jacob Perron
|
||||
|
||||
0.7.15 (2020-11-24)
|
||||
-------------------
|
||||
* Fix implementation of NodeOptions::use_global_arguments(). (`#1176 <https://github.com/ros2/rclcpp/issues/1176>`_) (`#1206 <https://github.com/ros2/rclcpp/issues/1206>`_)
|
||||
* Fix conversion of negative durations to messages. (`#1188 <https://github.com/ros2/rclcpp/issues/1188>`_) (`#1207 <https://github.com/ros2/rclcpp/issues/1207>`_)
|
||||
* Type conversions fixes. (`#901 <https://github.com/ros2/rclcpp/issues/901>`_) (`#1209 <https://github.com/ros2/rclcpp/issues/1209>`_)
|
||||
* Add operator!= for duration (`#1236 <https://github.com/ros2/rclcpp/issues/1236>`_) (`#1277 <https://github.com/ros2/rclcpp/issues/1277>`_)
|
||||
* Contributors: Ivan Santiago Paunovic, Michel Hidalgo, Monika Idzik
|
||||
|
||||
0.7.14 (2020-07-10)
|
||||
-------------------
|
||||
* Fixed doxygen warnings. (`#1208 <https://github.com/ros2/rclcpp/issues/1208>`_)
|
||||
* Check if context is valid when looping in spin_some. (`#1167 <https://github.com/ros2/rclcpp/issues/1167>`_)
|
||||
* Fix spin_until_future_complete: check spinning value. (`#1023 <https://github.com/ros2/rclcpp/issues/1023>`_)
|
||||
* Fix exception on rcl_clock_init. (`#1195 <https://github.com/ros2/rclcpp/issues/1195>`_)
|
||||
* Fix lock-order-inversion (potential deadlock). (`#1138 <https://github.com/ros2/rclcpp/issues/1138>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, DongheeYe, Ivan Santiago Paunovic, tomoya
|
||||
|
||||
0.7.13 (2020-03-12)
|
||||
-------------------
|
||||
* Don't specify calling convention in std::_Binder template. (`#1015 <https://github.com/ros2/rclcpp/issues/1015>`_)
|
||||
* Contributors: Jacob Perron, Sean Kelly
|
||||
|
||||
0.7.12 (2019-12-05)
|
||||
-------------------
|
||||
|
||||
0.7.11 (2019-10-11)
|
||||
-------------------
|
||||
* Fix `get_node_*_interface` functions taking a pointer (`#870 <https://github.com/ros2/rclcpp/pull/870>`_).
|
||||
* Fix hang with timers in `MultiThreadedExecutor` (`#869 <https://github.com/ros2/rclcpp/pull/869>`_).
|
||||
* Contributors: Todd Malsbary, ivanpauno
|
||||
|
||||
0.7.10 (2019-09-23)
|
||||
-------------------
|
||||
|
||||
0.7.9 (2019-09-20)
|
||||
------------------
|
||||
* add mutex in add/remove_node and wait_for_work to protect concurrent use/change of memory_strategy\_ (`#837 <https://github.com/ros2/rclcpp/issues/837>`_) (`#857 <https://github.com/ros2/rclcpp/issues/857>`_)
|
||||
* Contributors: Zachary Michaels
|
||||
|
||||
0.7.8 (2019-09-06)
|
||||
------------------
|
||||
|
||||
0.7.7 (2019-07-31)
|
||||
------------------
|
||||
* Enabled the creation of a parameter YAML file which is applied to each node. (`#805 <https://github.com/ros2/rclcpp/issues/805>`_)
|
||||
* Fixed a signed/unsigned integer comparison compiler warning. (`#804 <https://github.com/ros2/rclcpp/issues/804>`_)
|
||||
* Changed the QoS profile used when subscribing to parameter events to match the publishing side, i.e. ``rmw_qos_profile_parameter_events``. (`#798 <https://github.com/ros2/rclcpp/issues/798>`_)
|
||||
* Changed the logic in TimeSource to ignore use_sim_time parameter events coming from other nodes. (`#803 <https://github.com/ros2/rclcpp/issues/803>`_)
|
||||
* Added missing default values in the NodeParametersInterface. (`#794 <https://github.com/ros2/rclcpp/issues/794>`_)
|
||||
* Added support for const member callback functions. (`#763 <https://github.com/ros2/rclcpp/issues/763>`_)
|
||||
* Contributors: Esteve Fernandez, Gonzo, Karsten Knese, Michel Hidalgo, Scott K Logan
|
||||
|
||||
0.7.6 (2019-06-12)
|
||||
------------------
|
||||
* Ignore parameters overrides in set parameter methods when allowing undeclared parameters (`#756 <https://github.com/ros2/rclcpp/issues/756>`_)
|
||||
* Add rclcpp::create_timer() (`#757 <https://github.com/ros2/rclcpp/issues/757>`_)
|
||||
* checking origin of intra-process msg before taking them (`#753 <https://github.com/ros2/rclcpp/issues/753>`_)
|
||||
* Contributors: Alberto Soragna, Shane Loretz, ivanpauno
|
||||
|
||||
0.7.5 (2019-05-30)
|
||||
------------------
|
||||
* Avoid 'Intra process message no longer being stored when trying to handle it' warning (`#749 <https://github.com/ros2/rclcpp/issues/749>`_)
|
||||
* Contributors: ivanpauno
|
||||
|
||||
0.7.4 (2019-05-29)
|
||||
------------------
|
||||
* Rename parameter options (`#745 <https://github.com/ros2/rclcpp/issues/745>`_)
|
||||
* Bionic use of strerror_r (`#742 <https://github.com/ros2/rclcpp/issues/742>`_)
|
||||
* Enforce parameter ranges (`#735 <https://github.com/ros2/rclcpp/issues/735>`_)
|
||||
* removed not used parameter client (`#740 <https://github.com/ros2/rclcpp/issues/740>`_)
|
||||
* ensure removal of guard conditions of expired nodes from memory strategy (`#741 <https://github.com/ros2/rclcpp/issues/741>`_)
|
||||
* Fix typo in log warning message (`#737 <https://github.com/ros2/rclcpp/issues/737>`_)
|
||||
* Throw nice errors when creating a publisher with intraprocess communication and incompatible qos policy (`#729 <https://github.com/ros2/rclcpp/issues/729>`_)
|
||||
* Contributors: Alberto Soragna, Dirk Thomas, Jacob Perron, William Woodall, ivanpauno, roderick-koehle
|
||||
|
||||
0.7.3 (2019-05-20)
|
||||
------------------
|
||||
* Fixed misspelling, volitile -> volatile (`#724 <https://github.com/ros2/rclcpp/issues/724>`_), and then fixed that since it is a C++ keyword to be ``durability_volatile`` (`#725 <https://github.com/ros2/rclcpp/issues/725>`_)
|
||||
* Fixed a clang warning (`#723 <https://github.com/ros2/rclcpp/issues/723>`_)
|
||||
* Added ``on_parameter_event`` static method to the ``AsyncParametersClient`` (`#688 <https://github.com/ros2/rclcpp/issues/688>`_)
|
||||
* Added a guard against ``ParameterNotDeclaredException`` throwing from within the parameter service callbacks. (`#718 <https://github.com/ros2/rclcpp/issues/718>`_)
|
||||
* Added missing template functionality to lifecycle_node. (`#707 <https://github.com/ros2/rclcpp/issues/707>`_)
|
||||
* Fixed heap-use-after-free and memory leaks reported from ``test_node.cpp`` (`#719 <https://github.com/ros2/rclcpp/issues/719>`_)
|
||||
* Contributors: Alberto Soragna, Dirk Thomas, Emerson Knapp, Jacob Perron, Michael Jeronimo, Prajakta Gokhale
|
||||
|
||||
0.7.2 (2019-05-08)
|
||||
------------------
|
||||
* Added new way to specify QoS settings for publishers and subscriptions. (`#713 <https://github.com/ros2/rclcpp/issues/713>`_)
|
||||
|
||||
@@ -19,7 +19,11 @@ if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
endif()
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||
# About -Wno-sign-conversion: With Clang, -Wconversion implies -Wsign-conversion. There are a number of
|
||||
# implicit sign conversions in rclcpp and gtest.cc, see https://ci.ros2.org/job/ci_osx/9265/.
|
||||
# Hence disabling -Wsign-conversion for now until all those have eventually been fixed.
|
||||
# (from https://github.com/ros2/rclcpp/pull/1188#issuecomment-650229140)
|
||||
add_compile_options(-Wall -Wextra -Wconversion -Wno-sign-conversion -Wpedantic)
|
||||
endif()
|
||||
|
||||
include_directories(include)
|
||||
@@ -155,6 +159,18 @@ if(BUILD_TESTING)
|
||||
)
|
||||
target_link_libraries(test_client ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_create_timer test/test_create_timer.cpp)
|
||||
if(TARGET test_create_timer)
|
||||
ament_target_dependencies(test_create_timer
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rcl"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_create_timer ${PROJECT_NAME})
|
||||
target_include_directories(test_create_timer PRIVATE test/)
|
||||
endif()
|
||||
ament_add_gtest(test_expand_topic_or_service_name test/test_expand_topic_or_service_name.cpp)
|
||||
if(TARGET test_expand_topic_or_service_name)
|
||||
ament_target_dependencies(test_expand_topic_or_service_name
|
||||
@@ -242,6 +258,13 @@ if(BUILD_TESTING)
|
||||
)
|
||||
target_link_libraries(test_node_global_args ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter_client test/test_parameter_client.cpp)
|
||||
if(TARGET test_parameter_client)
|
||||
ament_target_dependencies(test_parameter_client
|
||||
"rcl_interfaces"
|
||||
)
|
||||
target_link_libraries(test_parameter_client ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter_events_filter test/test_parameter_events_filter.cpp)
|
||||
if(TARGET test_parameter_events_filter)
|
||||
ament_target_dependencies(test_parameter_events_filter
|
||||
|
||||
@@ -105,9 +105,9 @@ public:
|
||||
*
|
||||
* Function is only applicable if the clock_type is `RCL_ROS_TIME`
|
||||
*
|
||||
* \param pre_callback. Must be non-throwing
|
||||
* \param post_callback. Must be non-throwing.
|
||||
* \param threshold. Callbacks will be triggered if the time jump is greater
|
||||
* \param pre_callback Must be non-throwing
|
||||
* \param post_callback Must be non-throwing.
|
||||
* \param threshold Callbacks will be triggered if the time jump is greater
|
||||
* then the threshold.
|
||||
* \throws anything rclcpp::exceptions::throw_from_rcl_error can throw.
|
||||
* \throws std::bad_alloc if the allocation of the JumpHandler fails.
|
||||
|
||||
73
rclcpp/include/rclcpp/create_timer.hpp
Normal file
73
rclcpp/include/rclcpp/create_timer.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__CREATE_TIMER_HPP_
|
||||
#define RCLCPP__CREATE_TIMER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/duration.hpp"
|
||||
# include "rclcpp/node_interfaces/get_node_base_interface.hpp"
|
||||
# include "rclcpp/node_interfaces/get_node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
/// Create a timer with a given clock
|
||||
/// \internal
|
||||
template<typename CallbackT>
|
||||
typename rclcpp::TimerBase::SharedPtr
|
||||
create_timer(
|
||||
node_interfaces::NodeBaseInterface * node_base,
|
||||
node_interfaces::NodeTimersInterface * node_timers,
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
auto timer = rclcpp::GenericTimer<CallbackT>::make_shared(
|
||||
clock,
|
||||
period.to_chrono<std::chrono::nanoseconds>(),
|
||||
std::forward<CallbackT>(callback),
|
||||
node_base->get_context());
|
||||
|
||||
node_timers->add_timer(timer, group);
|
||||
return timer;
|
||||
}
|
||||
|
||||
/// Create a timer with a given clock
|
||||
template<typename NodeT, typename CallbackT>
|
||||
typename rclcpp::TimerBase::SharedPtr
|
||||
create_timer(
|
||||
NodeT node,
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
return create_timer(
|
||||
rclcpp::node_interfaces::get_node_base_interface(node),
|
||||
rclcpp::node_interfaces::get_node_timers_interface(node),
|
||||
clock,
|
||||
period,
|
||||
std::forward<CallbackT>(callback),
|
||||
group);
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CREATE_TIMER_HPP_
|
||||
@@ -55,11 +55,14 @@ public:
|
||||
operator=(const Duration & rhs);
|
||||
|
||||
Duration &
|
||||
operator=(const builtin_interfaces::msg::Duration & Duration_msg);
|
||||
operator=(const builtin_interfaces::msg::Duration & duration_msg);
|
||||
|
||||
bool
|
||||
operator==(const rclcpp::Duration & rhs) const;
|
||||
|
||||
bool
|
||||
operator!=(const rclcpp::Duration & rhs) const;
|
||||
|
||||
bool
|
||||
operator<(const rclcpp::Duration & rhs) const;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -34,6 +35,7 @@
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rclcpp/scope_exit.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
@@ -242,9 +244,14 @@ public:
|
||||
}
|
||||
std::chrono::nanoseconds timeout_left = timeout_ns;
|
||||
|
||||
while (rclcpp::ok(this->context_)) {
|
||||
if (spinning.exchange(true)) {
|
||||
throw std::runtime_error("spin_until_future_complete() called while already spinning");
|
||||
}
|
||||
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
|
||||
while (rclcpp::ok(this->context_) && spinning.load()) {
|
||||
// Do one item of work.
|
||||
spin_once(timeout_left);
|
||||
spin_once_impl(timeout_left);
|
||||
|
||||
// Check if the future is set, return SUCCESS if it is.
|
||||
status = future.wait_for(std::chrono::seconds(0));
|
||||
if (status == std::future_status::ready) {
|
||||
@@ -355,6 +362,9 @@ protected:
|
||||
/// Wait set for managing entities that the rmw layer waits on.
|
||||
rcl_wait_set_t wait_set_ = rcl_get_zero_initialized_wait_set();
|
||||
|
||||
// Mutex to protect the subsequent memory_strategy_.
|
||||
std::mutex memory_strategy_mutex_;
|
||||
|
||||
/// The memory strategy: an interface for handling user-defined memory allocation strategies.
|
||||
memory_strategy::MemoryStrategy::SharedPtr memory_strategy_;
|
||||
|
||||
@@ -364,7 +374,12 @@ protected:
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(Executor)
|
||||
|
||||
std::vector<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin_once_impl(std::chrono::nanoseconds timeout);
|
||||
|
||||
std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
|
||||
std::list<const rcl_guard_condition_t *> guard_conditions_;
|
||||
};
|
||||
|
||||
} // namespace executor
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
* \param number_of_threads number of threads to have in the thread pool,
|
||||
* the default 0 will use the number of cpu cores found instead
|
||||
* \param yield_before_execute if true std::this_thread::yield() is called
|
||||
* \param timeout maximum time to wait
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
MultiThreadedExecutor(
|
||||
|
||||
@@ -88,8 +88,24 @@ struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(FArgs ...))(Args ...)>>
|
||||
struct function_traits<std::_Bind<std::_Mem_fn<ReturnTypeT (ClassT::*)(Args ...)>(FArgs ...)>>
|
||||
#elif defined _MSC_VER // MS Visual Studio
|
||||
struct function_traits<
|
||||
std::_Binder<std::_Unforced, ReturnTypeT(__cdecl ClassT::*)(Args ...), FArgs ...>
|
||||
>
|
||||
std::_Binder<std::_Unforced, ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
|
||||
#else
|
||||
#error "Unsupported C++ compiler / standard library"
|
||||
#endif
|
||||
: function_traits<ReturnTypeT(Args ...)>
|
||||
{};
|
||||
|
||||
// std::bind for object const methods
|
||||
template<typename ClassT, typename ReturnTypeT, typename ... Args, typename ... FArgs>
|
||||
#if defined _LIBCPP_VERSION // libc++ (Clang)
|
||||
struct function_traits<std::__bind<ReturnTypeT (ClassT::*)(Args ...) const, FArgs ...>>
|
||||
#elif defined _GLIBCXX_RELEASE // glibc++ (GNU C++ >= 7.1)
|
||||
struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(FArgs ...))(Args ...) const>>
|
||||
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
|
||||
struct function_traits<std::_Bind<std::_Mem_fn<ReturnTypeT (ClassT::*)(Args ...) const>(FArgs ...)>>
|
||||
#elif defined _MSC_VER // MS Visual Studio
|
||||
struct function_traits<
|
||||
std::_Binder<std::_Unforced, ReturnTypeT (ClassT::*)(Args ...) const, FArgs ...>>
|
||||
#else
|
||||
#error "Unsupported C++ compiler / standard library"
|
||||
#endif
|
||||
@@ -103,7 +119,7 @@ struct function_traits<std::__bind<ReturnTypeT( &)(Args ...), FArgs ...>>
|
||||
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
|
||||
struct function_traits<std::_Bind<ReturnTypeT(*(FArgs ...))(Args ...)>>
|
||||
#elif defined _MSC_VER // MS Visual Studio
|
||||
struct function_traits<std::_Binder<std::_Unforced, ReturnTypeT(__cdecl &)(Args ...), FArgs ...>>
|
||||
struct function_traits<std::_Binder<std::_Unforced, ReturnTypeT( &)(Args ...), FArgs ...>>
|
||||
#else
|
||||
#error "Unsupported C++ compiler / standard library"
|
||||
#endif
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
#ifndef RCLCPP__MEMORY_STRATEGY_HPP_
|
||||
#define RCLCPP__MEMORY_STRATEGY_HPP_
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/allocator.h"
|
||||
#include "rcl/wait.h"
|
||||
@@ -42,11 +42,11 @@ class RCLCPP_PUBLIC MemoryStrategy
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(MemoryStrategy)
|
||||
using WeakNodeVector = std::vector<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>;
|
||||
using WeakNodeList = std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>;
|
||||
|
||||
virtual ~MemoryStrategy() = default;
|
||||
|
||||
virtual bool collect_entities(const WeakNodeVector & weak_nodes) = 0;
|
||||
virtual bool collect_entities(const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual size_t number_of_ready_subscriptions() const = 0;
|
||||
virtual size_t number_of_ready_services() const = 0;
|
||||
@@ -67,22 +67,22 @@ public:
|
||||
virtual void
|
||||
get_next_subscription(
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
const WeakNodeVector & weak_nodes) = 0;
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_service(
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
const WeakNodeVector & weak_nodes) = 0;
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_client(
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
const WeakNodeVector & weak_nodes) = 0;
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_waitable(
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
const WeakNodeVector & weak_nodes) = 0;
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual rcl_allocator_t
|
||||
get_allocator() = 0;
|
||||
@@ -90,42 +90,42 @@ public:
|
||||
static rclcpp::SubscriptionBase::SharedPtr
|
||||
get_subscription_by_handle(
|
||||
std::shared_ptr<const rcl_subscription_t> subscriber_handle,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::ServiceBase::SharedPtr
|
||||
get_service_by_handle(
|
||||
std::shared_ptr<const rcl_service_t> service_handle,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::ClientBase::SharedPtr
|
||||
get_client_by_handle(
|
||||
std::shared_ptr<const rcl_client_t> client_handle,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
get_node_by_group(
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_group_by_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_group_by_service(
|
||||
rclcpp::ServiceBase::SharedPtr service,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_group_by_client(
|
||||
rclcpp::ClientBase::SharedPtr client,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
get_group_by_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable,
|
||||
const WeakNodeVector & weak_nodes);
|
||||
const WeakNodeList & weak_nodes);
|
||||
};
|
||||
|
||||
} // namespace memory_strategy
|
||||
|
||||
@@ -155,7 +155,7 @@ public:
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(10)); // implicitly KeepLast
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(KeepLast(10)));
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(KeepAll()));
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(1).best_effort().volatile());
|
||||
* pub = node->create_publisher<MsgT>("chatter", QoS(1).best_effort().durability_volatile());
|
||||
* {
|
||||
* rclcpp::QoS custom_qos(KeepLast(10), rmw_qos_profile_sensor_data);
|
||||
* pub = node->create_publisher<MsgT>("chatter", custom_qos);
|
||||
@@ -337,7 +337,13 @@ public:
|
||||
CallbackT callback,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/* Create and return a Client. */
|
||||
/// Create and return a Client.
|
||||
/**
|
||||
* \param[in] service_name The topic to service on.
|
||||
* \param[in] qos_profile rmw_qos_profile_t Quality of service profile for client.
|
||||
* \param[in] group Callback group to call the service.
|
||||
* \return Shared pointer to the created client.
|
||||
*/
|
||||
template<typename ServiceT>
|
||||
typename rclcpp::Client<ServiceT>::SharedPtr
|
||||
create_client(
|
||||
@@ -345,7 +351,14 @@ public:
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/* Create and return a Service. */
|
||||
/// Create and return a Service.
|
||||
/**
|
||||
* \param[in] service_name The topic to service on.
|
||||
* \param[in] callback User-defined callback function.
|
||||
* \param[in] qos_profile rmw_qos_profile_t Quality of service profile for client.
|
||||
* \param[in] group Callback group to call the service.
|
||||
* \return Shared pointer to the created service.
|
||||
*/
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
typename rclcpp::Service<ServiceT>::SharedPtr
|
||||
create_service(
|
||||
@@ -516,6 +529,7 @@ public:
|
||||
* rclcpp::NodeOptions::allow_undeclared_parameters set to true.
|
||||
* If undeclared parameters are allowed, then the parameter is implicitly
|
||||
* declared with the default parameter meta data before being set.
|
||||
* Parameter overrides are ignored by set_parameter.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* set_on_parameters_set_callback to be called.
|
||||
@@ -940,7 +954,6 @@ public:
|
||||
void
|
||||
register_param_change_callback(CallbackT && callback);
|
||||
|
||||
|
||||
/// Get the fully-qualified names of all available nodes.
|
||||
/**
|
||||
* The fully-qualified name includes the local namespace and name of the node.
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
|
||||
/// This header provides the get_node_base_interface() template function.
|
||||
/**
|
||||
* This function is useful for getting the NodeBaseInterface pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get the NodeBaseInterface pointer so long as the class
|
||||
* has a method called ``get_node_base_interface()`` which returns
|
||||
* either a pointer (const or not) to a NodeBaseInterface or a
|
||||
* std::shared_ptr to a NodeBaseInterface.
|
||||
*/
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This is a meta-programming checker for if a given Node-like object has a
|
||||
// getter called get_node_base_interface() which returns various types,
|
||||
// e.g. const pointer or a shared pointer.
|
||||
template<typename NodeType, typename ReturnType>
|
||||
struct has_get_node_base_interface
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static constexpr
|
||||
auto
|
||||
check(T *)->typename std::is_same<
|
||||
decltype(std::declval<T>().get_node_base_interface()),
|
||||
ReturnType
|
||||
>::type;
|
||||
|
||||
template<typename>
|
||||
static constexpr
|
||||
std::false_type
|
||||
check(...);
|
||||
|
||||
public:
|
||||
using type = decltype(check<NodeType>(nullptr));
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
// If NodeType is a pointer to NodeBaseInterface already (just normal function overload).
|
||||
inline
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(rclcpp::node_interfaces::NodeBaseInterface * pointer)
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_base_interface() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_base_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface>
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_base_interface().get();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_base_interface() which returns a pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_base_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_base_interface();
|
||||
}
|
||||
|
||||
// Forward shared_ptr's to const node pointer signatures.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_same<
|
||||
NodeType,
|
||||
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_shared_pointer)
|
||||
{
|
||||
return get_node_base_interface_from_pointer(node_shared_pointer->get());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the NodeBaseInterface as a pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface(NodeType node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
return detail::get_node_base_interface_from_pointer(node_pointer);
|
||||
}
|
||||
|
||||
/// Get the NodeBaseInterface as a pointer from a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<
|
||||
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface(NodeType && node_reference)
|
||||
{
|
||||
// Forward references to detail implmentation as a pointer.
|
||||
return detail::get_node_base_interface_from_pointer(&node_reference);
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
@@ -0,0 +1,149 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
|
||||
/// This header provides the get_node_timers_interface() template function.
|
||||
/**
|
||||
* This function is useful for getting the NodeTimersInterface pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get the NodeTimersInterface pointer so long as the class
|
||||
* has a method called ``get_node_timers_interface()`` which returns
|
||||
* either a pointer (const or not) to a NodeTimersInterface or a
|
||||
* std::shared_ptr to a NodeTimersInterface.
|
||||
*/
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This is a meta-programming checker for if a given Node-like object has a
|
||||
// getter called get_node_timers_interface() which returns various types,
|
||||
// e.g. const pointer or a shared pointer.
|
||||
template<typename NodeType, typename ReturnType>
|
||||
struct has_get_node_timers_interface
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static constexpr
|
||||
auto
|
||||
check(T *)->typename std::is_same<
|
||||
decltype(std::declval<T>().get_node_timers_interface()),
|
||||
ReturnType
|
||||
>::type;
|
||||
|
||||
template<typename>
|
||||
static constexpr
|
||||
std::false_type
|
||||
check(...);
|
||||
|
||||
public:
|
||||
using type = decltype(check<NodeType>(nullptr));
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
// If NodeType is a pointer to NodeTimersInterface already (just normal function overload).
|
||||
inline
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(rclcpp::node_interfaces::NodeTimersInterface * pointer)
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_timers_interface() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_timers_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTimersInterface>
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_timers_interface().get();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_timers_interface() which returns a pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_timers_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_timers_interface();
|
||||
}
|
||||
|
||||
// Forward shared_ptr's to const node pointer signatures.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_same<
|
||||
NodeType,
|
||||
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_shared_pointer)
|
||||
{
|
||||
return get_node_timers_interface_from_pointer(node_shared_pointer->get());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the NodeTimersInterface as a pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface(NodeType node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
return detail::get_node_timers_interface_from_pointer(node_pointer);
|
||||
}
|
||||
|
||||
/// Get the NodeTimersInterface as a pointer from a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<
|
||||
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface(NodeType && node_reference)
|
||||
{
|
||||
// Forward references to detail implmentation as a pointer.
|
||||
return detail::get_node_timers_interface_from_pointer(&node_reference);
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
@@ -123,16 +123,18 @@ template<
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface(NodeType && node_pointer)
|
||||
get_node_topics_interface(NodeType node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
return detail::get_node_topics_interface_from_pointer(std::forward<NodeType>(node_pointer));
|
||||
return detail::get_node_topics_interface_from_pointer(node_pointer);
|
||||
}
|
||||
|
||||
/// Get the NodeTopicsInterface as a pointer from a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<!std::is_pointer<NodeType>::value, int>::type = 0
|
||||
typename std::enable_if<
|
||||
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface(NodeType && node_reference)
|
||||
|
||||
@@ -63,13 +63,13 @@ public:
|
||||
const node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
|
||||
const node_interfaces::NodeServicesInterface::SharedPtr node_services,
|
||||
const node_interfaces::NodeClockInterface::SharedPtr node_clock,
|
||||
const std::vector<Parameter> & initial_parameters,
|
||||
const std::vector<Parameter> & parameter_overrides,
|
||||
bool start_parameter_services,
|
||||
bool start_parameter_event_publisher,
|
||||
const rclcpp::QoS & parameter_event_qos,
|
||||
const rclcpp::PublisherOptionsBase & parameter_event_publisher_options,
|
||||
bool allow_undeclared_parameters,
|
||||
bool automatically_declare_initial_parameters);
|
||||
bool automatically_declare_parameters_from_overrides);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::map<std::string, rclcpp::ParameterValue> &
|
||||
get_initial_parameter_values() const override;
|
||||
get_parameter_overrides() const override;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeParameters)
|
||||
@@ -154,7 +154,7 @@ private:
|
||||
|
||||
std::map<std::string, ParameterInfo> parameters_;
|
||||
|
||||
std::map<std::string, rclcpp::ParameterValue> initial_parameter_values_;
|
||||
std::map<std::string, rclcpp::ParameterValue> parameter_overrides_;
|
||||
|
||||
bool allow_undeclared_ = false;
|
||||
|
||||
|
||||
@@ -51,8 +51,9 @@ public:
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor) = 0;
|
||||
const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor()) = 0;
|
||||
|
||||
/// Undeclare a parameter.
|
||||
/**
|
||||
@@ -183,7 +184,7 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const std::map<std::string, rclcpp::ParameterValue> &
|
||||
get_initial_parameter_values() const = 0;
|
||||
get_parameter_overrides() const = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
*
|
||||
* - context = rclcpp::contexts::default_context::get_global_default_context()
|
||||
* - arguments = {}
|
||||
* - initial_parameters = {}
|
||||
* - parameter_overrides = {}
|
||||
* - use_global_arguments = true
|
||||
* - use_intra_process_comms = false
|
||||
* - start_parameter_services = true
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
* - with history setting and depth from rmw_qos_profile_parameter_events
|
||||
* - parameter_event_publisher_options = rclcpp::PublisherOptionsBase
|
||||
* - allow_undeclared_parameters = false
|
||||
* - automatically_declare_initial_parameters = false
|
||||
* - automatically_declare_parameters_from_overrides = false
|
||||
* - allocator = rcl_get_default_allocator()
|
||||
*
|
||||
* \param[in] allocator allocator to use in construction of NodeOptions.
|
||||
@@ -107,31 +107,31 @@ public:
|
||||
NodeOptions &
|
||||
arguments(const std::vector<std::string> & arguments);
|
||||
|
||||
/// Return a reference to the list of initial parameters.
|
||||
/// Return a reference to the list of parameter overrides.
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::Parameter> &
|
||||
initial_parameters();
|
||||
parameter_overrides();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::Parameter> &
|
||||
initial_parameters() const;
|
||||
parameter_overrides() const;
|
||||
|
||||
/// Set the initial parameters, return this for parameter idiom.
|
||||
/// Set the parameters overrides, return this for parameter idiom.
|
||||
/**
|
||||
* These initial parameter values are used to change the initial value
|
||||
* These parameter overrides are used to change the initial value
|
||||
* of declared parameters within the node, overriding hard coded default
|
||||
* values if necessary.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
NodeOptions &
|
||||
initial_parameters(const std::vector<rclcpp::Parameter> & initial_parameters);
|
||||
parameter_overrides(const std::vector<rclcpp::Parameter> & parameter_overrides);
|
||||
|
||||
/// Append a single initial parameter, parameter idiom style.
|
||||
/// Append a single parameter override, parameter idiom style.
|
||||
template<typename ParameterT>
|
||||
NodeOptions &
|
||||
append_initial_parameter(const std::string & name, const ParameterT & value)
|
||||
append_parameter_override(const std::string & name, const ParameterT & value)
|
||||
{
|
||||
this->initial_parameters().emplace_back(name, rclcpp::ParameterValue(value));
|
||||
this->parameter_overrides().emplace_back(name, rclcpp::ParameterValue(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -247,29 +247,35 @@ public:
|
||||
* If true, allow any parameter name to be set on the node without first
|
||||
* being declared.
|
||||
* Otherwise, setting an undeclared parameter will raise an exception.
|
||||
*
|
||||
* This option being true does not affect parameter_overrides, as the first
|
||||
* set action will implicitly declare the parameter and therefore consider
|
||||
* any parameter overrides.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
NodeOptions &
|
||||
allow_undeclared_parameters(bool allow_undeclared_parameters);
|
||||
|
||||
/// Return the automatically_declare_initial_parameters flag.
|
||||
/// Return the automatically_declare_parameters_from_overrides flag.
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
automatically_declare_initial_parameters() const;
|
||||
automatically_declare_parameters_from_overrides() const;
|
||||
|
||||
/// Set the automatically_declare_initial_parameters, return this.
|
||||
/// Set the automatically_declare_parameters_from_overrides, return this.
|
||||
/**
|
||||
* If true, automatically iterate through the node's initial parameters and
|
||||
* If true, automatically iterate through the node's parameter overrides and
|
||||
* implicitly declare any that have not already been declared.
|
||||
* Otherwise, parameters passed to the node's initial_parameters, and/or the
|
||||
* global initial parameter values, which are not explicitly declared will
|
||||
* not appear on the node at all.
|
||||
* Otherwise, parameters passed to the node's parameter_overrides, and/or the
|
||||
* global arguments (e.g. parameter overrides from a YAML file), which are
|
||||
* not explicitly declared will not appear on the node at all, even if
|
||||
* `allow_undeclared_parameters` is true.
|
||||
* Already declared parameters will not be re-declared, and parameters
|
||||
* declared in this way will use the default constructed ParameterDescriptor.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
NodeOptions &
|
||||
automatically_declare_initial_parameters(bool automatically_declare_initial_parameters);
|
||||
automatically_declare_parameters_from_overrides(
|
||||
bool automatically_declare_parameters_from_overrides);
|
||||
|
||||
/// Return the rcl_allocator_t to be used.
|
||||
RCLCPP_PUBLIC
|
||||
@@ -302,7 +308,7 @@ private:
|
||||
|
||||
std::vector<std::string> arguments_ {};
|
||||
|
||||
std::vector<rclcpp::Parameter> initial_parameters_ {};
|
||||
std::vector<rclcpp::Parameter> parameter_overrides_ {};
|
||||
|
||||
bool use_global_arguments_ {true};
|
||||
|
||||
@@ -320,7 +326,7 @@ private:
|
||||
|
||||
bool allow_undeclared_parameters_ {false};
|
||||
|
||||
bool automatically_declare_initial_parameters_ {false};
|
||||
bool automatically_declare_parameters_from_overrides_ {false};
|
||||
|
||||
rcl_allocator_t allocator_ {rcl_get_default_allocator()};
|
||||
};
|
||||
|
||||
@@ -46,6 +46,15 @@ class AsyncParametersClient
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(AsyncParametersClient)
|
||||
|
||||
/// Create an async parameters client.
|
||||
/**
|
||||
* \param[in] node_base_interface The node base interface of the corresponding node.
|
||||
* \param[in] node_topics_interface Node topic base interface.
|
||||
* \param[in] node_graph_interface The node graph interface of the corresponding node.
|
||||
* \param[in] node_services_interface Node service interface.
|
||||
* \param[in] remote_node_name (optional) name of the remote node
|
||||
* \param[in] qos_profile (optional) The rmw qos profile to use to subscribe
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
AsyncParametersClient(
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
|
||||
@@ -55,12 +64,24 @@ public:
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
* \param[in] node The async paramters client will be added to this node.
|
||||
* \param[in] remote_node_name (optional) name of the remote node
|
||||
* \param[in] qos_profile (optional) The rmw qos profile to use to subscribe
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
AsyncParametersClient(
|
||||
const rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
* \param[in] node The async paramters client will be added to this node.
|
||||
* \param[in] remote_node_name (optional) name of the remote node
|
||||
* \param[in] qos_profile (optional) The rmw qos profile to use to subscribe
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
AsyncParametersClient(
|
||||
rclcpp::Node * node,
|
||||
@@ -115,14 +136,41 @@ public:
|
||||
on_parameter_event(
|
||||
CallbackT && callback,
|
||||
const rclcpp::QoS & qos = (
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_default))
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events))
|
||||
),
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
))
|
||||
{
|
||||
return this->on_parameter_event(
|
||||
this->node_topics_interface_,
|
||||
callback,
|
||||
qos,
|
||||
options);
|
||||
}
|
||||
|
||||
/**
|
||||
* The NodeT type only needs to have a method called get_node_topics_interface()
|
||||
* which returns a shared_ptr to a NodeTopicsInterface, or be a
|
||||
* NodeTopicsInterface pointer itself.
|
||||
*/
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename NodeT,
|
||||
typename AllocatorT = std::allocator<void>>
|
||||
static typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
|
||||
on_parameter_event(
|
||||
NodeT && node,
|
||||
CallbackT && callback,
|
||||
const rclcpp::QoS & qos = (
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events))
|
||||
),
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
))
|
||||
{
|
||||
return rclcpp::create_subscription<rcl_interfaces::msg::ParameterEvent>(
|
||||
this->node_topics_interface_,
|
||||
node,
|
||||
"parameter_events",
|
||||
qos,
|
||||
std::forward<CallbackT>(callback),
|
||||
@@ -266,7 +314,26 @@ public:
|
||||
typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
|
||||
on_parameter_event(CallbackT && callback)
|
||||
{
|
||||
return async_parameters_client_->on_parameter_event(std::forward<CallbackT>(callback));
|
||||
return async_parameters_client_->on_parameter_event(
|
||||
std::forward<CallbackT>(callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* The NodeT type only needs to have a method called get_node_topics_interface()
|
||||
* which returns a shared_ptr to a NodeTopicsInterface, or be a
|
||||
* NodeTopicsInterface pointer itself.
|
||||
*/
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename NodeT>
|
||||
static typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
|
||||
on_parameter_event(
|
||||
NodeT && node,
|
||||
CallbackT && callback)
|
||||
{
|
||||
return AsyncParametersClient::on_parameter_event(
|
||||
node,
|
||||
std::forward<CallbackT>(callback));
|
||||
}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
@@ -105,8 +105,11 @@ public:
|
||||
durability(rmw_qos_durability_policy_t durability);
|
||||
|
||||
/// Set the durability setting to volatile.
|
||||
/**
|
||||
* Note that this cannot be named `volatile` because it is a C++ keyword.
|
||||
*/
|
||||
QoS &
|
||||
volitile();
|
||||
durability_volatile();
|
||||
|
||||
/// Set the durability setting to transient local.
|
||||
QoS &
|
||||
|
||||
@@ -156,6 +156,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// Default constructor.
|
||||
/**
|
||||
* The constructor for a Service is almost never called directly.
|
||||
* Instead, services should be instantiated through the function
|
||||
* rclcpp::create_service().
|
||||
*
|
||||
* \param[in] node_handle NodeBaseInterface pointer that is used in part of the setup.
|
||||
* \param[in] service_handle service handle.
|
||||
* \param[in] any_callback User defined callback to call when a client request is received.
|
||||
*/
|
||||
Service(
|
||||
std::shared_ptr<rcl_node_t> node_handle,
|
||||
std::shared_ptr<rcl_service_t> service_handle,
|
||||
@@ -174,6 +184,16 @@ public:
|
||||
service_handle_ = service_handle;
|
||||
}
|
||||
|
||||
/// Default constructor.
|
||||
/**
|
||||
* The constructor for a Service is almost never called directly.
|
||||
* Instead, services should be instantiated through the function
|
||||
* rclcpp::create_service().
|
||||
*
|
||||
* \param[in] node_handle NodeBaseInterface pointer that is used in part of the setup.
|
||||
* \param[in] service_handle service handle.
|
||||
* \param[in] any_callback User defined callback to call when a client request is received.
|
||||
*/
|
||||
Service(
|
||||
std::shared_ptr<rcl_node_t> node_handle,
|
||||
rcl_service_t * service_handle,
|
||||
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
bool collect_entities(const WeakNodeVector & weak_nodes)
|
||||
bool collect_entities(const WeakNodeList & weak_nodes)
|
||||
{
|
||||
bool has_invalid_weak_nodes = false;
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
@@ -265,7 +265,7 @@ public:
|
||||
virtual void
|
||||
get_next_subscription(
|
||||
executor::AnyExecutable & any_exec,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
const WeakNodeList & weak_nodes)
|
||||
{
|
||||
auto it = subscription_handles_.begin();
|
||||
while (it != subscription_handles_.end()) {
|
||||
@@ -309,7 +309,7 @@ public:
|
||||
virtual void
|
||||
get_next_service(
|
||||
executor::AnyExecutable & any_exec,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
const WeakNodeList & weak_nodes)
|
||||
{
|
||||
auto it = service_handles_.begin();
|
||||
while (it != service_handles_.end()) {
|
||||
@@ -342,7 +342,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void
|
||||
get_next_client(executor::AnyExecutable & any_exec, const WeakNodeVector & weak_nodes)
|
||||
get_next_client(executor::AnyExecutable & any_exec, const WeakNodeList & weak_nodes)
|
||||
{
|
||||
auto it = client_handles_.begin();
|
||||
while (it != client_handles_.end()) {
|
||||
@@ -375,7 +375,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void
|
||||
get_next_waitable(executor::AnyExecutable & any_exec, const WeakNodeVector & weak_nodes)
|
||||
get_next_waitable(executor::AnyExecutable & any_exec, const WeakNodeList & weak_nodes)
|
||||
{
|
||||
auto it = waitable_handles_.begin();
|
||||
while (it != waitable_handles_.end()) {
|
||||
|
||||
@@ -170,6 +170,13 @@ public:
|
||||
// However, this can only really happen if this node has it disabled, but the other doesn't.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!matches_any_intra_process_publishers(&message_info.publisher_gid)) {
|
||||
// This intra-process message has not been created by a publisher from this context.
|
||||
// we should ignore this copy of the message.
|
||||
return;
|
||||
}
|
||||
|
||||
if (any_callback_.use_take_shared_method()) {
|
||||
ConstMessageSharedPtr msg;
|
||||
take_intra_process_message(
|
||||
@@ -178,10 +185,11 @@ public:
|
||||
intra_process_subscription_id_,
|
||||
msg);
|
||||
if (!msg) {
|
||||
// This either occurred because the publisher no longer exists or the
|
||||
// message requested is no longer being stored.
|
||||
RCLCPP_WARN(get_logger("rclcpp"),
|
||||
"Intra process message not longer being stored when trying to handle it");
|
||||
// This can happen when having two nodes in different process both using intraprocess
|
||||
// communication. It could happen too if the publisher no longer exists or the requested
|
||||
// message is not longer being stored.
|
||||
// TODO(ivanpauno): Print a warn message in the last two cases described above,
|
||||
// but not in the first one.
|
||||
return;
|
||||
}
|
||||
any_callback_.dispatch_intra_process(msg, message_info);
|
||||
@@ -193,10 +201,11 @@ public:
|
||||
intra_process_subscription_id_,
|
||||
msg);
|
||||
if (!msg) {
|
||||
// This either occurred because the publisher no longer exists or the
|
||||
// message requested is no longer being stored.
|
||||
RCLCPP_WARN(get_logger("rclcpp"),
|
||||
"Intra process message not longer being stored when trying to handle it");
|
||||
// This can happen when having two nodes in different process both using intraprocess
|
||||
// communication. It could happen too if the publisher no longer exists or the requested
|
||||
// message is not longer being stored.
|
||||
// TODO(ivanpauno): Print a warn message in the last two cases described above,
|
||||
// but not in the first one.
|
||||
return;
|
||||
}
|
||||
any_callback_.dispatch_intra_process(std::move(msg), message_info);
|
||||
|
||||
@@ -65,7 +65,12 @@ struct SubscriptionFactory
|
||||
SetupIntraProcessFunction setup_intra_process;
|
||||
};
|
||||
|
||||
/// Return a SubscriptionFactory with functions for creating a SubscriptionT<MessageT, Alloc>.
|
||||
/// Return a SubscriptionFactory setup to create a SubscriptionT<MessageT, AllocatorT>.
|
||||
/**
|
||||
* \param[in] callback The user-defined callback function to receive a message
|
||||
* \param[in] options Additional options for the creation of the Subscription.
|
||||
* \param[in] msg_mem_strat The message memory strategy to use for allocating messages.
|
||||
*/
|
||||
template<
|
||||
typename MessageT,
|
||||
typename CallbackT,
|
||||
|
||||
@@ -34,17 +34,32 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
Time(int32_t seconds, uint32_t nanoseconds, rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
|
||||
|
||||
/// Time constructor
|
||||
/**
|
||||
* \param nanoseconds since time epoch
|
||||
* \param clock_type clock type
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit Time(int64_t nanoseconds = 0, rcl_clock_type_t clock = RCL_SYSTEM_TIME);
|
||||
explicit Time(int64_t nanoseconds = 0, rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
Time(const Time & rhs);
|
||||
|
||||
/// Time constructor
|
||||
/**
|
||||
* \param time_msg builtin_interfaces time message to copy
|
||||
* \param clock_type clock type
|
||||
* \throws std::runtime_error if seconds are negative
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
Time(
|
||||
const builtin_interfaces::msg::Time & time_msg,
|
||||
rcl_clock_type_t ros_time = RCL_ROS_TIME);
|
||||
rcl_clock_type_t clock_type = RCL_ROS_TIME);
|
||||
|
||||
/// Time constructor
|
||||
/**
|
||||
* \param time_point rcl_time_point_t structure to copy
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit Time(const rcl_time_point_t & time_point);
|
||||
|
||||
@@ -58,6 +73,12 @@ public:
|
||||
Time &
|
||||
operator=(const Time & rhs);
|
||||
|
||||
/**
|
||||
* Assign Time from a builtin_interfaces::msg::Time instance.
|
||||
* The clock_type will be reset to RCL_ROS_TIME.
|
||||
* Equivalent to *this = Time(time_msg, RCL_ROS_TIME).
|
||||
* \throws std::runtime_error if seconds are negative
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
Time &
|
||||
operator=(const builtin_interfaces::msg::Time & time_msg);
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
#include "rcl_interfaces/msg/parameter_event.hpp"
|
||||
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/parameter_client.hpp"
|
||||
#include "rclcpp/parameter_events_filter.hpp"
|
||||
|
||||
|
||||
namespace rclcpp
|
||||
@@ -100,9 +98,6 @@ private:
|
||||
// Destroy the subscription for the clock topic
|
||||
void destroy_clock_sub();
|
||||
|
||||
// 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>;
|
||||
|
||||
@@ -126,6 +126,7 @@ public:
|
||||
* \param[in] clock The clock providing the current time.
|
||||
* \param[in] period The interval at which the timer fires.
|
||||
* \param[in] callback User-specified callback function.
|
||||
* \param[in] context custom context to be used.
|
||||
*/
|
||||
explicit GenericTimer(
|
||||
Clock::SharedPtr clock, std::chrono::nanoseconds period, FunctorT && callback,
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
bool
|
||||
is_ready(rcl_wait_set_t *) = 0;
|
||||
is_ready(rcl_wait_set_t * wait_set) = 0;
|
||||
|
||||
/// Execute any entities of the Waitable that are ready.
|
||||
/**
|
||||
|
||||
@@ -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.7.2</version>
|
||||
<version>0.7.16</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -35,7 +35,7 @@ Clock::Clock(rcl_clock_type_t clock_type)
|
||||
allocator_ = rcl_get_default_allocator();
|
||||
auto ret = rcl_clock_init(clock_type, &rcl_clock_, &allocator_);
|
||||
if (ret != RCL_RET_OK) {
|
||||
exceptions::throw_from_rcl_error(ret, "could not get current time stamp");
|
||||
exceptions::throw_from_rcl_error(ret, "failed to initialize rcl clock");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,16 +47,14 @@ Duration::Duration(std::chrono::nanoseconds nanoseconds)
|
||||
rcl_duration_.nanoseconds = nanoseconds.count();
|
||||
}
|
||||
|
||||
Duration::Duration(const Duration & rhs)
|
||||
{
|
||||
rcl_duration_.nanoseconds = rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
Duration::Duration(const Duration & rhs) = default;
|
||||
|
||||
Duration::Duration(
|
||||
const builtin_interfaces::msg::Duration & duration_msg)
|
||||
{
|
||||
rcl_duration_.nanoseconds = RCL_S_TO_NS(static_cast<uint64_t>(duration_msg.sec));
|
||||
rcl_duration_.nanoseconds += duration_msg.nanosec;
|
||||
rcl_duration_.nanoseconds =
|
||||
RCL_S_TO_NS(static_cast<rcl_duration_value_t>(duration_msg.sec));
|
||||
rcl_duration_.nanoseconds += static_cast<rcl_duration_value_t>(duration_msg.nanosec);
|
||||
}
|
||||
|
||||
Duration::Duration(const rcl_duration_t & duration)
|
||||
@@ -68,24 +66,25 @@ Duration::Duration(const rcl_duration_t & duration)
|
||||
Duration::operator builtin_interfaces::msg::Duration() const
|
||||
{
|
||||
builtin_interfaces::msg::Duration msg_duration;
|
||||
msg_duration.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_duration_.nanoseconds));
|
||||
msg_duration.nanosec =
|
||||
static_cast<std::uint32_t>(rcl_duration_.nanoseconds % (1000 * 1000 * 1000));
|
||||
constexpr rcl_duration_value_t kDivisor = RCL_S_TO_NS(1);
|
||||
const auto result = std::div(rcl_duration_.nanoseconds, kDivisor);
|
||||
if (result.rem >= 0) {
|
||||
msg_duration.sec = static_cast<std::int32_t>(result.quot);
|
||||
msg_duration.nanosec = static_cast<std::uint32_t>(result.rem);
|
||||
} else {
|
||||
msg_duration.sec = static_cast<std::int32_t>(result.quot - 1);
|
||||
msg_duration.nanosec = static_cast<std::uint32_t>(kDivisor + result.rem);
|
||||
}
|
||||
return msg_duration;
|
||||
}
|
||||
|
||||
Duration &
|
||||
Duration::operator=(const Duration & rhs)
|
||||
{
|
||||
rcl_duration_.nanoseconds = rhs.rcl_duration_.nanoseconds;
|
||||
return *this;
|
||||
}
|
||||
Duration::operator=(const Duration & rhs) = default;
|
||||
|
||||
Duration &
|
||||
Duration::operator=(const builtin_interfaces::msg::Duration & duration_msg)
|
||||
{
|
||||
rcl_duration_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(duration_msg.sec));
|
||||
rcl_duration_.nanoseconds += duration_msg.nanosec;
|
||||
*this = Duration(duration_msg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -95,6 +94,12 @@ Duration::operator==(const rclcpp::Duration & rhs) const
|
||||
return rcl_duration_.nanoseconds == rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
|
||||
bool
|
||||
Duration::operator!=(const rclcpp::Duration & rhs) const
|
||||
{
|
||||
return rcl_duration_.nanoseconds != rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
|
||||
bool
|
||||
Duration::operator<(const rclcpp::Duration & rhs) const
|
||||
{
|
||||
@@ -122,15 +127,15 @@ Duration::operator>(const rclcpp::Duration & rhs) const
|
||||
void
|
||||
bounds_check_duration_sum(int64_t lhsns, int64_t rhsns, uint64_t max)
|
||||
{
|
||||
auto abs_lhs = (uint64_t)std::abs(lhsns);
|
||||
auto abs_rhs = (uint64_t)std::abs(rhsns);
|
||||
auto abs_lhs = static_cast<uint64_t>(std::abs(lhsns));
|
||||
auto abs_rhs = static_cast<uint64_t>(std::abs(rhsns));
|
||||
|
||||
if (lhsns > 0 && rhsns > 0) {
|
||||
if (abs_lhs + abs_rhs > (uint64_t) max) {
|
||||
if (abs_lhs + abs_rhs > max) {
|
||||
throw std::overflow_error("addition leads to int64_t overflow");
|
||||
}
|
||||
} else if (lhsns < 0 && rhsns < 0) {
|
||||
if (abs_lhs + abs_rhs > (uint64_t) max) {
|
||||
if (abs_lhs + abs_rhs > max) {
|
||||
throw std::underflow_error("addition leads to int64_t underflow");
|
||||
}
|
||||
}
|
||||
@@ -150,15 +155,15 @@ Duration::operator+(const rclcpp::Duration & rhs) const
|
||||
void
|
||||
bounds_check_duration_difference(int64_t lhsns, int64_t rhsns, uint64_t max)
|
||||
{
|
||||
auto abs_lhs = (uint64_t)std::abs(lhsns);
|
||||
auto abs_rhs = (uint64_t)std::abs(rhsns);
|
||||
auto abs_lhs = static_cast<uint64_t>(std::abs(lhsns));
|
||||
auto abs_rhs = static_cast<uint64_t>(std::abs(rhsns));
|
||||
|
||||
if (lhsns > 0 && rhsns < 0) {
|
||||
if (abs_lhs + abs_rhs > (uint64_t) max) {
|
||||
if (abs_lhs + abs_rhs > max) {
|
||||
throw std::overflow_error("duration subtraction leads to int64_t overflow");
|
||||
}
|
||||
} else if (lhsns < 0 && rhsns > 0) {
|
||||
if (abs_lhs + abs_rhs > (uint64_t) max) {
|
||||
if (abs_lhs + abs_rhs > max) {
|
||||
throw std::underflow_error("duration subtraction leads to int64_t underflow");
|
||||
}
|
||||
}
|
||||
@@ -181,8 +186,10 @@ bounds_check_duration_scale(int64_t dns, double scale, uint64_t max)
|
||||
{
|
||||
auto abs_dns = static_cast<uint64_t>(std::abs(dns));
|
||||
auto abs_scale = std::abs(scale);
|
||||
|
||||
if (abs_scale > 1.0 && abs_dns > static_cast<uint64_t>(max / abs_scale)) {
|
||||
if (abs_scale > 1.0 &&
|
||||
abs_dns >
|
||||
static_cast<uint64_t>(static_cast<long double>(max) / static_cast<long double>(abs_scale)))
|
||||
{
|
||||
if ((dns > 0 && scale > 0) || (dns < 0 && scale < 0)) {
|
||||
throw std::overflow_error("duration scaling leads to int64_t overflow");
|
||||
} else {
|
||||
@@ -201,7 +208,9 @@ Duration::operator*(double scale) const
|
||||
this->rcl_duration_.nanoseconds,
|
||||
scale,
|
||||
std::numeric_limits<rcl_duration_value_t>::max());
|
||||
return Duration(static_cast<rcl_duration_value_t>(rcl_duration_.nanoseconds * scale));
|
||||
long double scale_ld = static_cast<long double>(scale);
|
||||
return Duration(static_cast<rcl_duration_value_t>(
|
||||
static_cast<long double>(rcl_duration_.nanoseconds) * scale_ld));
|
||||
}
|
||||
|
||||
rcl_duration_value_t
|
||||
@@ -225,11 +234,15 @@ Duration::seconds() const
|
||||
rmw_time_t
|
||||
Duration::to_rmw_time() const
|
||||
{
|
||||
if (rcl_duration_.nanoseconds < 0) {
|
||||
throw std::runtime_error("rmw_time_t cannot be negative");
|
||||
}
|
||||
|
||||
// reuse conversion logic from msg creation
|
||||
builtin_interfaces::msg::Duration msg = *this;
|
||||
rmw_time_t result;
|
||||
result.sec = msg.sec;
|
||||
result.nsec = msg.nanosec;
|
||||
result.sec = static_cast<uint64_t>(msg.sec);
|
||||
result.nsec = static_cast<uint64_t>(msg.nanosec);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,10 @@ Executor::~Executor()
|
||||
}
|
||||
}
|
||||
weak_nodes_.clear();
|
||||
for (auto & guard_condition : guard_conditions_) {
|
||||
memory_strategy_->remove_guard_condition(guard_condition);
|
||||
}
|
||||
guard_conditions_.clear();
|
||||
|
||||
// Finalize the wait set.
|
||||
if (rcl_wait_set_fini(&wait_set_) != RCL_RET_OK) {
|
||||
@@ -128,6 +132,7 @@ Executor::add_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_pt
|
||||
}
|
||||
}
|
||||
weak_nodes_.push_back(node_ptr);
|
||||
guard_conditions_.push_back(node_ptr->get_notify_guard_condition());
|
||||
if (notify) {
|
||||
// Interrupt waiting to handle new node
|
||||
if (rcl_trigger_guard_condition(&interrupt_guard_condition_) != RCL_RET_OK) {
|
||||
@@ -135,6 +140,7 @@ Executor::add_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_pt
|
||||
}
|
||||
}
|
||||
// Add the node's notify condition to the guard condition handles
|
||||
std::unique_lock<std::mutex> lock(memory_strategy_mutex_);
|
||||
memory_strategy_->add_guard_condition(node_ptr->get_notify_guard_condition());
|
||||
}
|
||||
|
||||
@@ -148,17 +154,21 @@ void
|
||||
Executor::remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify)
|
||||
{
|
||||
bool node_removed = false;
|
||||
weak_nodes_.erase(
|
||||
std::remove_if(
|
||||
weak_nodes_.begin(), weak_nodes_.end(),
|
||||
[&](rclcpp::node_interfaces::NodeBaseInterface::WeakPtr & i)
|
||||
{
|
||||
bool matched = (i.lock() == node_ptr);
|
||||
node_removed |= matched;
|
||||
return matched;
|
||||
{
|
||||
auto node_it = weak_nodes_.begin();
|
||||
auto gc_it = guard_conditions_.begin();
|
||||
while (node_it != weak_nodes_.end()) {
|
||||
bool matched = (node_it->lock() == node_ptr);
|
||||
if (matched) {
|
||||
node_it = weak_nodes_.erase(node_it);
|
||||
gc_it = guard_conditions_.erase(gc_it);
|
||||
node_removed = true;
|
||||
} else {
|
||||
++node_it;
|
||||
++gc_it;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
std::atomic_bool & has_executor = node_ptr->get_associated_with_executor_atomic();
|
||||
has_executor.store(false);
|
||||
if (notify) {
|
||||
@@ -169,6 +179,7 @@ Executor::remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node
|
||||
}
|
||||
}
|
||||
}
|
||||
std::unique_lock<std::mutex> lock(memory_strategy_mutex_);
|
||||
memory_strategy_->remove_guard_condition(node_ptr->get_notify_guard_condition());
|
||||
}
|
||||
|
||||
@@ -223,7 +234,7 @@ Executor::spin_some(std::chrono::nanoseconds max_duration)
|
||||
throw std::runtime_error("spin_some() called while already spinning");
|
||||
}
|
||||
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
|
||||
while (spinning.load() && max_duration_not_elapsed()) {
|
||||
while (rclcpp::ok(context_) && spinning.load() && max_duration_not_elapsed()) {
|
||||
AnyExecutable any_exec;
|
||||
if (get_next_executable(any_exec, std::chrono::milliseconds::zero())) {
|
||||
execute_any_executable(any_exec);
|
||||
@@ -233,6 +244,15 @@ Executor::spin_some(std::chrono::nanoseconds max_duration)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Executor::spin_once_impl(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
AnyExecutable any_exec;
|
||||
if (get_next_executable(any_exec, timeout)) {
|
||||
execute_any_executable(any_exec);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Executor::spin_once(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
@@ -240,10 +260,7 @@ Executor::spin_once(std::chrono::nanoseconds timeout)
|
||||
throw std::runtime_error("spin_once() called while already spinning");
|
||||
}
|
||||
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
|
||||
AnyExecutable any_exec;
|
||||
if (get_next_executable(any_exec, timeout)) {
|
||||
execute_any_executable(any_exec);
|
||||
}
|
||||
spin_once_impl(timeout);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -414,40 +431,47 @@ Executor::execute_client(
|
||||
void
|
||||
Executor::wait_for_work(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
// Collect the subscriptions and timers to be waited on
|
||||
memory_strategy_->clear_handles();
|
||||
bool has_invalid_weak_nodes = memory_strategy_->collect_entities(weak_nodes_);
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(memory_strategy_mutex_);
|
||||
|
||||
// Clean up any invalid nodes, if they were detected
|
||||
if (has_invalid_weak_nodes) {
|
||||
weak_nodes_.erase(
|
||||
remove_if(
|
||||
weak_nodes_.begin(), weak_nodes_.end(),
|
||||
[](rclcpp::node_interfaces::NodeBaseInterface::WeakPtr i)
|
||||
{
|
||||
return i.expired();
|
||||
// Collect the subscriptions and timers to be waited on
|
||||
memory_strategy_->clear_handles();
|
||||
bool has_invalid_weak_nodes = memory_strategy_->collect_entities(weak_nodes_);
|
||||
|
||||
// Clean up any invalid nodes, if they were detected
|
||||
if (has_invalid_weak_nodes) {
|
||||
auto node_it = weak_nodes_.begin();
|
||||
auto gc_it = guard_conditions_.begin();
|
||||
while (node_it != weak_nodes_.end()) {
|
||||
if (node_it->expired()) {
|
||||
node_it = weak_nodes_.erase(node_it);
|
||||
memory_strategy_->remove_guard_condition(*gc_it);
|
||||
gc_it = guard_conditions_.erase(gc_it);
|
||||
} else {
|
||||
++node_it;
|
||||
++gc_it;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
// clear wait set
|
||||
if (rcl_wait_set_clear(&wait_set_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear wait set");
|
||||
}
|
||||
}
|
||||
}
|
||||
// clear wait set
|
||||
if (rcl_wait_set_clear(&wait_set_) != RCL_RET_OK) {
|
||||
throw std::runtime_error("Couldn't clear wait set");
|
||||
}
|
||||
|
||||
// The size of waitables are accounted for in size of the other entities
|
||||
rcl_ret_t ret = rcl_wait_set_resize(
|
||||
&wait_set_, memory_strategy_->number_of_ready_subscriptions(),
|
||||
memory_strategy_->number_of_guard_conditions(), memory_strategy_->number_of_ready_timers(),
|
||||
memory_strategy_->number_of_ready_clients(), memory_strategy_->number_of_ready_services(),
|
||||
memory_strategy_->number_of_ready_events());
|
||||
if (RCL_RET_OK != ret) {
|
||||
throw std::runtime_error(
|
||||
std::string("Couldn't resize the wait set : ") + rcl_get_error_string().str);
|
||||
}
|
||||
// The size of waitables are accounted for in size of the other entities
|
||||
rcl_ret_t ret = rcl_wait_set_resize(
|
||||
&wait_set_, memory_strategy_->number_of_ready_subscriptions(),
|
||||
memory_strategy_->number_of_guard_conditions(), memory_strategy_->number_of_ready_timers(),
|
||||
memory_strategy_->number_of_ready_clients(), memory_strategy_->number_of_ready_services(),
|
||||
memory_strategy_->number_of_ready_events());
|
||||
if (RCL_RET_OK != ret) {
|
||||
throw std::runtime_error(
|
||||
std::string("Couldn't resize the wait set : ") + rcl_get_error_string().str);
|
||||
}
|
||||
|
||||
if (!memory_strategy_->add_handles_to_wait_set(&wait_set_)) {
|
||||
throw std::runtime_error("Couldn't fill wait set");
|
||||
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(&wait_set_, std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count());
|
||||
|
||||
@@ -83,6 +83,11 @@ MultiThreadedExecutor::run(size_t)
|
||||
if (any_exec.timer) {
|
||||
// Guard against multiple threads getting the same timer.
|
||||
if (scheduled_timers_.count(any_exec.timer) != 0) {
|
||||
// Make sure that any_exec's callback group is reset before
|
||||
// the lock is released.
|
||||
if (any_exec.callback_group) {
|
||||
any_exec.callback_group->can_be_taken_from().store(true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
scheduled_timers_.insert(any_exec.timer);
|
||||
|
||||
@@ -20,7 +20,7 @@ using rclcpp::memory_strategy::MemoryStrategy;
|
||||
rclcpp::SubscriptionBase::SharedPtr
|
||||
MemoryStrategy::get_subscription_by_handle(
|
||||
std::shared_ptr<const rcl_subscription_t> subscriber_handle,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
const WeakNodeList & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
auto node = weak_node.lock();
|
||||
@@ -51,7 +51,7 @@ MemoryStrategy::get_subscription_by_handle(
|
||||
rclcpp::ServiceBase::SharedPtr
|
||||
MemoryStrategy::get_service_by_handle(
|
||||
std::shared_ptr<const rcl_service_t> service_handle,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
const WeakNodeList & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
auto node = weak_node.lock();
|
||||
@@ -77,7 +77,7 @@ MemoryStrategy::get_service_by_handle(
|
||||
rclcpp::ClientBase::SharedPtr
|
||||
MemoryStrategy::get_client_by_handle(
|
||||
std::shared_ptr<const rcl_client_t> client_handle,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
const WeakNodeList & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
auto node = weak_node.lock();
|
||||
@@ -103,7 +103,7 @@ MemoryStrategy::get_client_by_handle(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
MemoryStrategy::get_node_by_group(
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
const WeakNodeList & weak_nodes)
|
||||
{
|
||||
if (!group) {
|
||||
return nullptr;
|
||||
@@ -126,7 +126,7 @@ MemoryStrategy::get_node_by_group(
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
const WeakNodeList & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
auto node = weak_node.lock();
|
||||
@@ -152,7 +152,7 @@ MemoryStrategy::get_group_by_subscription(
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_service(
|
||||
rclcpp::ServiceBase::SharedPtr service,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
const WeakNodeList & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
auto node = weak_node.lock();
|
||||
@@ -178,7 +178,7 @@ MemoryStrategy::get_group_by_service(
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_client(
|
||||
rclcpp::ClientBase::SharedPtr client,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
const WeakNodeList & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
auto node = weak_node.lock();
|
||||
@@ -204,7 +204,7 @@ MemoryStrategy::get_group_by_client(
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable,
|
||||
const WeakNodeVector & weak_nodes)
|
||||
const WeakNodeList & weak_nodes)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes) {
|
||||
auto node = weak_node.lock();
|
||||
|
||||
@@ -132,13 +132,13 @@ Node::Node(
|
||||
node_topics_,
|
||||
node_services_,
|
||||
node_clock_,
|
||||
options.initial_parameters(),
|
||||
options.parameter_overrides(),
|
||||
options.start_parameter_services(),
|
||||
options.start_parameter_event_publisher(),
|
||||
options.parameter_event_qos(),
|
||||
options.parameter_event_publisher_options(),
|
||||
options.allow_undeclared_parameters(),
|
||||
options.automatically_declare_initial_parameters()
|
||||
options.automatically_declare_parameters_from_overrides()
|
||||
)),
|
||||
node_time_source_(new rclcpp::node_interfaces::NodeTimeSource(
|
||||
node_base_,
|
||||
|
||||
@@ -320,9 +320,11 @@ rclcpp::Event::SharedPtr
|
||||
NodeGraph::get_graph_event()
|
||||
{
|
||||
auto event = rclcpp::Event::make_shared();
|
||||
std::lock_guard<std::mutex> graph_changed_lock(graph_mutex_);
|
||||
graph_events_.push_back(event);
|
||||
graph_users_count_++;
|
||||
{
|
||||
std::lock_guard<std::mutex> graph_changed_lock(graph_mutex_);
|
||||
graph_events_.push_back(event);
|
||||
graph_users_count_++;
|
||||
}
|
||||
// on first call, add node to graph_listener_
|
||||
if (should_add_to_graph_listener_.exchange(false)) {
|
||||
graph_listener_->add_node(this);
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
|
||||
#include <rcl_yaml_param_parser/parser.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
@@ -48,13 +51,13 @@ NodeParameters::NodeParameters(
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services,
|
||||
const rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock,
|
||||
const std::vector<rclcpp::Parameter> & initial_parameters,
|
||||
const std::vector<rclcpp::Parameter> & parameter_overrides,
|
||||
bool start_parameter_services,
|
||||
bool start_parameter_event_publisher,
|
||||
const rclcpp::QoS & parameter_event_qos,
|
||||
const rclcpp::PublisherOptionsBase & parameter_event_publisher_options,
|
||||
bool allow_undeclared_parameters,
|
||||
bool automatically_declare_initial_parameters)
|
||||
bool automatically_declare_parameters_from_overrides)
|
||||
: allow_undeclared_(allow_undeclared_parameters),
|
||||
events_publisher_(nullptr),
|
||||
node_logging_(node_logging),
|
||||
@@ -141,28 +144,29 @@ NodeParameters::NodeParameters(
|
||||
|
||||
rclcpp::ParameterMap initial_map = rclcpp::parameter_map_from(yaml_params);
|
||||
rcl_yaml_node_struct_fini(yaml_params);
|
||||
auto iter = initial_map.find(combined_name_);
|
||||
if (initial_map.end() == iter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Combine parameter yaml files, overwriting values in older ones
|
||||
for (auto & param : iter->second) {
|
||||
initial_parameter_values_[param.get_name()] =
|
||||
rclcpp::ParameterValue(param.get_value_message());
|
||||
for (auto iter = initial_map.begin(); initial_map.end() != iter; iter++) {
|
||||
// TODO(cottsay) implement further wildcard matching
|
||||
if (iter->first == "/**" || iter->first == combined_name_) {
|
||||
// Combine parameter yaml files, overwriting values in older ones
|
||||
for (auto & param : iter->second) {
|
||||
parameter_overrides_[param.get_name()] =
|
||||
rclcpp::ParameterValue(param.get_value_message());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initial values passed to constructor overwrite yaml file sources
|
||||
for (auto & param : initial_parameters) {
|
||||
initial_parameter_values_[param.get_name()] =
|
||||
// parameter overrides passed to constructor will overwrite overrides from yaml file sources
|
||||
for (auto & param : parameter_overrides) {
|
||||
parameter_overrides_[param.get_name()] =
|
||||
rclcpp::ParameterValue(param.get_value_message());
|
||||
}
|
||||
|
||||
// If asked, initialize any parameters that ended up in the initial parameter values,
|
||||
// but did not get declared explcitily by this point.
|
||||
if (automatically_declare_initial_parameters) {
|
||||
for (const auto & pair : this->get_initial_parameter_values()) {
|
||||
if (automatically_declare_parameters_from_overrides) {
|
||||
for (const auto & pair : this->get_parameter_overrides()) {
|
||||
if (!this->has_parameter(pair.first)) {
|
||||
this->declare_parameter(
|
||||
pair.first,
|
||||
@@ -185,6 +189,103 @@ __lockless_has_parameter(
|
||||
return parameters.find(name) != parameters.end();
|
||||
}
|
||||
|
||||
// see https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
|
||||
RCLCPP_LOCAL
|
||||
bool
|
||||
__are_doubles_equal(double x, double y, double ulp = 100.0)
|
||||
{
|
||||
return std::abs(x - y) <= std::numeric_limits<double>::epsilon() * std::abs(x + y) * ulp;
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
inline
|
||||
void
|
||||
format_reason(std::string & reason, const std::string & name, const char * range_type)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "Parameter {" << name << "} doesn't comply with " << range_type << " range.";
|
||||
reason = ss.str();
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
__check_parameter_value_in_range(
|
||||
const rcl_interfaces::msg::ParameterDescriptor & descriptor,
|
||||
const rclcpp::ParameterValue & value)
|
||||
{
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
if (!descriptor.integer_range.empty() && value.get_type() == rclcpp::PARAMETER_INTEGER) {
|
||||
int64_t v = value.get<int64_t>();
|
||||
auto integer_range = descriptor.integer_range.at(0);
|
||||
if (v == integer_range.from_value || v == integer_range.to_value) {
|
||||
return result;
|
||||
}
|
||||
if ((v < integer_range.from_value) || (v > integer_range.to_value)) {
|
||||
result.successful = false;
|
||||
format_reason(result.reason, descriptor.name, "integer");
|
||||
return result;
|
||||
}
|
||||
if (integer_range.step == 0) {
|
||||
return result;
|
||||
}
|
||||
if (((v - integer_range.from_value) % integer_range.step) == 0) {
|
||||
return result;
|
||||
}
|
||||
result.successful = false;
|
||||
format_reason(result.reason, descriptor.name, "integer");
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!descriptor.floating_point_range.empty() && value.get_type() == rclcpp::PARAMETER_DOUBLE) {
|
||||
double v = value.get<double>();
|
||||
auto fp_range = descriptor.floating_point_range.at(0);
|
||||
if (__are_doubles_equal(v, fp_range.from_value) ||
|
||||
__are_doubles_equal(v, fp_range.to_value))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if ((v < fp_range.from_value) || (v > fp_range.to_value)) {
|
||||
result.successful = false;
|
||||
format_reason(result.reason, descriptor.name, "floating point");
|
||||
return result;
|
||||
}
|
||||
if (fp_range.step == 0.0) {
|
||||
return result;
|
||||
}
|
||||
double rounded_div = std::round((v - fp_range.from_value) / fp_range.step);
|
||||
if (__are_doubles_equal(v, fp_range.from_value + rounded_div * fp_range.step)) {
|
||||
return result;
|
||||
}
|
||||
result.successful = false;
|
||||
format_reason(result.reason, descriptor.name, "floating point");
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return true if parameter values comply with the descriptors in parameter_infos.
|
||||
RCLCPP_LOCAL
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
__check_parameters(
|
||||
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameter_infos,
|
||||
const std::vector<rclcpp::Parameter> & parameters)
|
||||
{
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
for (const rclcpp::Parameter & parameter : parameters) {
|
||||
const rcl_interfaces::msg::ParameterDescriptor & descriptor =
|
||||
parameter_infos[parameter.get_name()].descriptor;
|
||||
result = __check_parameter_value_in_range(
|
||||
descriptor,
|
||||
parameter.get_parameter_value());
|
||||
if (!result.successful) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
using OnParametersSetCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;
|
||||
|
||||
@@ -201,7 +302,14 @@ __set_parameters_atomically_common(
|
||||
if (on_set_parameters_callback) {
|
||||
result = on_set_parameters_callback(parameters);
|
||||
}
|
||||
|
||||
if (!result.successful) {
|
||||
return result;
|
||||
}
|
||||
// Check if the value being set complies with the descriptor.
|
||||
result = __check_parameters(parameter_infos, parameters);
|
||||
if (!result.successful) {
|
||||
return result;
|
||||
}
|
||||
// If accepted, actually set the values.
|
||||
if (result.successful) {
|
||||
for (size_t i = 0; i < parameters.size(); ++i) {
|
||||
@@ -223,19 +331,20 @@ __declare_parameter_common(
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
|
||||
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameters_out,
|
||||
const std::map<std::string, rclcpp::ParameterValue> & initial_values,
|
||||
const std::map<std::string, rclcpp::ParameterValue> & overrides,
|
||||
OnParametersSetCallbackType on_set_parameters_callback,
|
||||
rcl_interfaces::msg::ParameterEvent * parameter_event_out)
|
||||
rcl_interfaces::msg::ParameterEvent * parameter_event_out,
|
||||
bool use_overrides = true)
|
||||
{
|
||||
using rclcpp::node_interfaces::ParameterInfo;
|
||||
std::map<std::string, ParameterInfo> parameter_infos {{name, ParameterInfo()}};
|
||||
parameter_infos.at(name).descriptor = parameter_descriptor;
|
||||
|
||||
// Use the value from the initial_values if available, otherwise use the default.
|
||||
// Use the value from the overrides if available, otherwise use the default.
|
||||
const rclcpp::ParameterValue * initial_value = &default_value;
|
||||
auto initial_value_it = initial_values.find(name);
|
||||
if (initial_value_it != initial_values.end()) {
|
||||
initial_value = &initial_value_it->second;
|
||||
auto overrides_it = overrides.find(name);
|
||||
if (use_overrides && overrides_it != overrides.end()) {
|
||||
initial_value = &overrides_it->second;
|
||||
}
|
||||
|
||||
// Check with the user's callback to see if the initial value can be set.
|
||||
@@ -282,7 +391,7 @@ NodeParameters::declare_parameter(
|
||||
default_value,
|
||||
parameter_descriptor,
|
||||
parameters_,
|
||||
initial_parameter_values_,
|
||||
parameter_overrides_,
|
||||
on_parameters_set_callback_,
|
||||
¶meter_event);
|
||||
|
||||
@@ -413,9 +522,10 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
|
||||
parameter_to_be_declared->get_parameter_value(),
|
||||
rcl_interfaces::msg::ParameterDescriptor(), // Implicit declare uses default descriptor.
|
||||
staged_parameter_changes,
|
||||
initial_parameter_values_,
|
||||
parameter_overrides_,
|
||||
nullptr, // callback is explicitly null, so that it is called only once, when setting below.
|
||||
¶meter_event_msg);
|
||||
¶meter_event_msg,
|
||||
false);
|
||||
if (!result.successful) {
|
||||
// Declare failed, return knowing that nothing was changed because the
|
||||
// staged changes were not applied.
|
||||
@@ -493,10 +603,10 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
|
||||
// assumption: the parameter to be undeclared should be in the parameter infos map
|
||||
assert(it != parameters_.end());
|
||||
if (it != parameters_.end()) {
|
||||
// Remove it and update the parameter event message.
|
||||
parameters_.erase(it);
|
||||
// Update the parameter event message and remove it.
|
||||
parameter_event_msg.deleted_parameters.push_back(
|
||||
rclcpp::Parameter(it->first, it->second.value).to_parameter_msg());
|
||||
parameters_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -733,7 +843,7 @@ NodeParameters::register_param_change_callback(ParametersCallbackFunction callba
|
||||
#endif
|
||||
|
||||
const std::map<std::string, rclcpp::ParameterValue> &
|
||||
NodeParameters::get_initial_parameter_values() const
|
||||
NodeParameters::get_parameter_overrides() const
|
||||
{
|
||||
return initial_parameter_values_;
|
||||
return parameter_overrides_;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,14 @@ NodeTopics::create_publisher(
|
||||
// Get the intra process manager instance for this context.
|
||||
auto ipm = context->get_sub_context<rclcpp::intra_process_manager::IntraProcessManager>();
|
||||
// Register the publisher with the intra process manager.
|
||||
if (publisher_options.qos.history == RMW_QOS_POLICY_HISTORY_KEEP_ALL) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication is not allowed with keep all history qos policy");
|
||||
}
|
||||
if (publisher_options.qos.depth == 0) {
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication is not allowed with a zero qos history depth value");
|
||||
}
|
||||
uint64_t intra_process_publisher_id = ipm->add_publisher(publisher);
|
||||
publisher->setup_intra_process(
|
||||
intra_process_publisher_id,
|
||||
|
||||
@@ -44,6 +44,9 @@ rcl_node_options_t_destructor(rcl_node_options_t * node_options)
|
||||
"failed to finalize rcl node options: %s", rcl_get_error_string().str);
|
||||
rcl_reset_error();
|
||||
}
|
||||
|
||||
delete node_options;
|
||||
node_options = nullptr;
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
@@ -62,16 +65,20 @@ NodeOptions &
|
||||
NodeOptions::operator=(const NodeOptions & other)
|
||||
{
|
||||
if (this != &other) {
|
||||
this->node_options_.reset();
|
||||
this->context_ = other.context_;
|
||||
this->arguments_ = other.arguments_;
|
||||
this->initial_parameters_ = other.initial_parameters_;
|
||||
this->parameter_overrides_ = other.parameter_overrides_;
|
||||
this->use_global_arguments_ = other.use_global_arguments_;
|
||||
this->use_intra_process_comms_ = other.use_intra_process_comms_;
|
||||
this->start_parameter_services_ = other.start_parameter_services_;
|
||||
this->allocator_ = other.allocator_;
|
||||
this->start_parameter_event_publisher_ = other.start_parameter_event_publisher_;
|
||||
this->parameter_event_qos_ = other.parameter_event_qos_;
|
||||
this->parameter_event_publisher_options_ = other.parameter_event_publisher_options_;
|
||||
this->allow_undeclared_parameters_ = other.allow_undeclared_parameters_;
|
||||
this->automatically_declare_initial_parameters_ =
|
||||
other.automatically_declare_initial_parameters_;
|
||||
this->automatically_declare_parameters_from_overrides_ =
|
||||
other.automatically_declare_parameters_from_overrides_;
|
||||
this->allocator_ = other.allocator_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -95,7 +102,7 @@ NodeOptions::get_rcl_node_options() const
|
||||
}
|
||||
}
|
||||
|
||||
if (this->arguments_.size() > std::numeric_limits<int>::max()) {
|
||||
if (this->arguments_.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
|
||||
throw_from_rcl_error(RCL_RET_INVALID_ARGUMENT, "Too many args");
|
||||
}
|
||||
|
||||
@@ -139,28 +146,28 @@ NodeOptions::arguments(const std::vector<std::string> & arguments)
|
||||
}
|
||||
|
||||
std::vector<rclcpp::Parameter> &
|
||||
NodeOptions::initial_parameters()
|
||||
NodeOptions::parameter_overrides()
|
||||
{
|
||||
return this->initial_parameters_;
|
||||
return this->parameter_overrides_;
|
||||
}
|
||||
|
||||
const std::vector<rclcpp::Parameter> &
|
||||
NodeOptions::initial_parameters() const
|
||||
NodeOptions::parameter_overrides() const
|
||||
{
|
||||
return this->initial_parameters_;
|
||||
return this->parameter_overrides_;
|
||||
}
|
||||
|
||||
NodeOptions &
|
||||
NodeOptions::initial_parameters(const std::vector<rclcpp::Parameter> & initial_parameters)
|
||||
NodeOptions::parameter_overrides(const std::vector<rclcpp::Parameter> & parameter_overrides)
|
||||
{
|
||||
this->initial_parameters_ = initial_parameters;
|
||||
this->parameter_overrides_ = parameter_overrides;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
NodeOptions::use_global_arguments() const
|
||||
{
|
||||
return this->node_options_->use_global_arguments;
|
||||
return this->use_global_arguments_;
|
||||
}
|
||||
|
||||
NodeOptions &
|
||||
@@ -251,16 +258,17 @@ NodeOptions::allow_undeclared_parameters(bool allow_undeclared_parameters)
|
||||
}
|
||||
|
||||
bool
|
||||
NodeOptions::automatically_declare_initial_parameters() const
|
||||
NodeOptions::automatically_declare_parameters_from_overrides() const
|
||||
{
|
||||
return this->automatically_declare_initial_parameters_;
|
||||
return this->automatically_declare_parameters_from_overrides_;
|
||||
}
|
||||
|
||||
NodeOptions &
|
||||
NodeOptions::automatically_declare_initial_parameters(
|
||||
bool automatically_declare_initial_parameters)
|
||||
NodeOptions::automatically_declare_parameters_from_overrides(
|
||||
bool automatically_declare_parameters_from_overrides)
|
||||
{
|
||||
this->automatically_declare_initial_parameters_ = automatically_declare_initial_parameters;
|
||||
this->automatically_declare_parameters_from_overrides_ =
|
||||
automatically_declare_parameters_from_overrides;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -294,7 +302,7 @@ NodeOptions::get_domain_id_from_env() const
|
||||
_dupenv_s(&ros_domain_id, &ros_domain_id_size, env_var);
|
||||
#endif
|
||||
if (ros_domain_id) {
|
||||
uint32_t number = strtoul(ros_domain_id, NULL, 0);
|
||||
uint32_t number = static_cast<uint32_t>(strtoul(ros_domain_id, NULL, 0));
|
||||
if (number == (std::numeric_limits<uint32_t>::max)()) {
|
||||
#ifdef _WIN32
|
||||
// free the ros_domain_id before throwing, if getenv was used on Windows
|
||||
|
||||
@@ -146,7 +146,7 @@ AsyncParametersClient::get_parameters(
|
||||
auto & pvalues = cb_f.get()->values;
|
||||
|
||||
for (auto & pvalue : pvalues) {
|
||||
auto i = &pvalue - &pvalues[0];
|
||||
auto i = static_cast<size_t>(&pvalue - &pvalues[0]);
|
||||
rcl_interfaces::msg::Parameter parameter;
|
||||
parameter.name = request->names[i];
|
||||
parameter.value = pvalue;
|
||||
|
||||
@@ -57,11 +57,15 @@ ParameterService::ParameterService(
|
||||
const std::shared_ptr<rcl_interfaces::srv::GetParameterTypes::Request> request,
|
||||
std::shared_ptr<rcl_interfaces::srv::GetParameterTypes::Response> response)
|
||||
{
|
||||
auto types = node_params->get_parameter_types(request->names);
|
||||
std::transform(types.cbegin(), types.cend(),
|
||||
std::back_inserter(response->types), [](const uint8_t & type) {
|
||||
return static_cast<rclcpp::ParameterType>(type);
|
||||
});
|
||||
try {
|
||||
auto types = node_params->get_parameter_types(request->names);
|
||||
std::transform(types.cbegin(), types.cend(),
|
||||
std::back_inserter(response->types), [](const uint8_t & type) {
|
||||
return static_cast<rclcpp::ParameterType>(type);
|
||||
});
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to get parameter types: %s", ex.what());
|
||||
}
|
||||
},
|
||||
qos_profile, nullptr);
|
||||
|
||||
@@ -73,12 +77,20 @@ ParameterService::ParameterService(
|
||||
const std::shared_ptr<rcl_interfaces::srv::SetParameters::Request> request,
|
||||
std::shared_ptr<rcl_interfaces::srv::SetParameters::Response> response)
|
||||
{
|
||||
std::vector<rclcpp::Parameter> pvariants;
|
||||
// Set parameters one-by-one, since there's no way to return a partial result if
|
||||
// set_parameters() fails.
|
||||
auto result = rcl_interfaces::msg::SetParametersResult();
|
||||
for (auto & p : request->parameters) {
|
||||
pvariants.push_back(rclcpp::Parameter::from_parameter_msg(p));
|
||||
try {
|
||||
result = node_params->set_parameters_atomically(
|
||||
{rclcpp::Parameter::from_parameter_msg(p)});
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to set parameter: %s", ex.what());
|
||||
result.successful = false;
|
||||
result.reason = ex.what();
|
||||
}
|
||||
response->results.push_back(result);
|
||||
}
|
||||
auto results = node_params->set_parameters(pvariants);
|
||||
response->results = results;
|
||||
},
|
||||
qos_profile, nullptr);
|
||||
|
||||
@@ -96,8 +108,15 @@ ParameterService::ParameterService(
|
||||
[](const rcl_interfaces::msg::Parameter & p) {
|
||||
return rclcpp::Parameter::from_parameter_msg(p);
|
||||
});
|
||||
auto result = node_params->set_parameters_atomically(pvariants);
|
||||
response->result = result;
|
||||
try {
|
||||
auto result = node_params->set_parameters_atomically(pvariants);
|
||||
response->result = result;
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"), "Failed to set parameters atomically: %s", ex.what());
|
||||
response->result.successful = false;
|
||||
response->result.reason = "One or more parameters wer not declared before setting";
|
||||
}
|
||||
},
|
||||
qos_profile, nullptr);
|
||||
|
||||
@@ -109,8 +128,12 @@ ParameterService::ParameterService(
|
||||
const std::shared_ptr<rcl_interfaces::srv::DescribeParameters::Request> request,
|
||||
std::shared_ptr<rcl_interfaces::srv::DescribeParameters::Response> response)
|
||||
{
|
||||
auto descriptors = node_params->describe_parameters(request->names);
|
||||
response->descriptors = descriptors;
|
||||
try {
|
||||
auto descriptors = node_params->describe_parameters(request->names);
|
||||
response->descriptors = descriptors;
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to describe parameters: %s", ex.what());
|
||||
}
|
||||
},
|
||||
qos_profile, nullptr);
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ ParameterValue::ParameterValue(const int64_t int_value)
|
||||
|
||||
ParameterValue::ParameterValue(const float double_value)
|
||||
{
|
||||
value_.double_value = double_value;
|
||||
value_.double_value = static_cast<double>(double_value);
|
||||
value_.type = rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE;
|
||||
}
|
||||
|
||||
|
||||
@@ -265,7 +265,7 @@ PublisherBase::setup_intra_process(
|
||||
{
|
||||
// Intraprocess configuration is not allowed with "durability" qos policy non "volatile".
|
||||
if (this->get_actual_qos().durability != RMW_QOS_POLICY_DURABILITY_VOLATILE) {
|
||||
throw exceptions::InvalidParametersException(
|
||||
throw std::invalid_argument(
|
||||
"intraprocess communication is not allowed with durability qos policy non-volatile");
|
||||
}
|
||||
const char * topic_name = this->get_topic_name();
|
||||
|
||||
@@ -120,7 +120,7 @@ QoS::durability(rmw_qos_durability_policy_t durability)
|
||||
}
|
||||
|
||||
QoS &
|
||||
QoS::volitile()
|
||||
QoS::durability_volatile()
|
||||
{
|
||||
return this->durability(RMW_QOS_POLICY_DURABILITY_VOLATILE);
|
||||
}
|
||||
|
||||
@@ -165,13 +165,15 @@ __safe_strerror(int errnum, char * buffer, size_t buffer_length)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
strerror_s(buffer, buffer_length, errnum);
|
||||
#elif (defined(_GNU_SOURCE) && !defined(ANDROID))
|
||||
#elif defined(_GNU_SOURCE) && (!defined(ANDROID) || __ANDROID_API__ >= 23)
|
||||
/* GNU-specific */
|
||||
char * msg = strerror_r(errnum, buffer, buffer_length);
|
||||
if (msg != buffer) {
|
||||
strncpy(buffer, msg, buffer_length);
|
||||
buffer[buffer_length - 1] = '\0';
|
||||
}
|
||||
#else
|
||||
/* XSI-compliant */
|
||||
int error_status = strerror_r(errnum, buffer, buffer_length);
|
||||
if (error_status != 0) {
|
||||
throw std::runtime_error("Failed to get error string for errno: " + std::to_string(errnum));
|
||||
|
||||
@@ -62,17 +62,13 @@ Time::Time(int64_t nanoseconds, rcl_clock_type_t clock_type)
|
||||
rcl_time_.nanoseconds = nanoseconds;
|
||||
}
|
||||
|
||||
Time::Time(const Time & rhs)
|
||||
: rcl_time_(rhs.rcl_time_)
|
||||
{
|
||||
rcl_time_.nanoseconds = rhs.rcl_time_.nanoseconds;
|
||||
}
|
||||
Time::Time(const Time & rhs) = default;
|
||||
|
||||
Time::Time(
|
||||
const builtin_interfaces::msg::Time & time_msg,
|
||||
rcl_clock_type_t ros_time)
|
||||
rcl_clock_type_t clock_type)
|
||||
: rcl_time_(init_time_point(clock_type))
|
||||
{
|
||||
rcl_time_ = init_time_point(ros_time);
|
||||
if (time_msg.sec < 0) {
|
||||
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
|
||||
}
|
||||
@@ -94,31 +90,25 @@ Time::~Time()
|
||||
Time::operator builtin_interfaces::msg::Time() const
|
||||
{
|
||||
builtin_interfaces::msg::Time msg_time;
|
||||
msg_time.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_time_.nanoseconds));
|
||||
msg_time.nanosec = static_cast<std::uint32_t>(rcl_time_.nanoseconds % (1000 * 1000 * 1000));
|
||||
constexpr rcl_time_point_value_t kRemainder = RCL_S_TO_NS(1);
|
||||
const auto result = std::div(rcl_time_.nanoseconds, kRemainder);
|
||||
if (result.rem >= 0) {
|
||||
msg_time.sec = static_cast<std::int32_t>(result.quot);
|
||||
msg_time.nanosec = static_cast<std::uint32_t>(result.rem);
|
||||
} else {
|
||||
msg_time.sec = static_cast<std::int32_t>(result.quot - 1);
|
||||
msg_time.nanosec = static_cast<std::uint32_t>(kRemainder + result.rem);
|
||||
}
|
||||
return msg_time;
|
||||
}
|
||||
|
||||
Time &
|
||||
Time::operator=(const Time & rhs)
|
||||
{
|
||||
rcl_time_ = rhs.rcl_time_;
|
||||
return *this;
|
||||
}
|
||||
Time::operator=(const Time & rhs) = default;
|
||||
|
||||
Time &
|
||||
Time::operator=(const builtin_interfaces::msg::Time & time_msg)
|
||||
{
|
||||
if (time_msg.sec < 0) {
|
||||
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
|
||||
}
|
||||
|
||||
|
||||
rcl_clock_type_t ros_time = RCL_ROS_TIME;
|
||||
rcl_time_ = init_time_point(ros_time); // TODO(tfoote) hard coded ROS here
|
||||
|
||||
rcl_time_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(time_msg.sec));
|
||||
rcl_time_.nanoseconds += time_msg.nanosec;
|
||||
*this = Time(time_msg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/parameter_client.hpp"
|
||||
#include "rclcpp/parameter_events_filter.hpp"
|
||||
#include "rclcpp/time.hpp"
|
||||
#include "rclcpp/time_source.hpp"
|
||||
|
||||
@@ -103,22 +105,16 @@ void TimeSource::attachNode(
|
||||
}
|
||||
|
||||
// TODO(tfoote) use parameters interface not subscribe to events via topic ticketed #609
|
||||
parameter_client_ = std::make_shared<rclcpp::AsyncParametersClient>(
|
||||
node_base_,
|
||||
parameter_subscription_ = rclcpp::AsyncParametersClient::on_parameter_event(
|
||||
node_topics_,
|
||||
node_graph_,
|
||||
node_services_
|
||||
);
|
||||
parameter_subscription_ =
|
||||
parameter_client_->on_parameter_event(std::bind(&TimeSource::on_parameter_event,
|
||||
this, std::placeholders::_1));
|
||||
std::bind(&TimeSource::on_parameter_event, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void TimeSource::detachNode()
|
||||
{
|
||||
this->ros_time_active_ = false;
|
||||
clock_subscription_.reset();
|
||||
parameter_client_.reset();
|
||||
parameter_subscription_.reset();
|
||||
node_base_.reset();
|
||||
node_topics_.reset();
|
||||
node_graph_.reset();
|
||||
@@ -224,13 +220,17 @@ void TimeSource::destroy_clock_sub()
|
||||
|
||||
void TimeSource::on_parameter_event(const rcl_interfaces::msg::ParameterEvent::SharedPtr event)
|
||||
{
|
||||
// Filter out events on 'use_sim_time' parameter instances in other nodes.
|
||||
if (event->node != node_base_->get_fully_qualified_name()) {
|
||||
return;
|
||||
}
|
||||
// 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 != ParameterType::PARAMETER_BOOL) {
|
||||
RCLCPP_ERROR(logger_, "use_sim_time parameter set to something besides a bool");
|
||||
RCLCPP_ERROR(logger_, "use_sim_time parameter cannot be set to anything but a bool");
|
||||
continue;
|
||||
}
|
||||
if (it.second->value.bool_value) {
|
||||
|
||||
@@ -103,9 +103,9 @@ remove_ros_arguments(int argc, char const * const argv[])
|
||||
throw exceptions::RCLError(base_exc, "");
|
||||
}
|
||||
|
||||
std::vector<std::string> return_arguments(nonros_argc);
|
||||
std::vector<std::string> return_arguments(static_cast<size_t>(nonros_argc));
|
||||
|
||||
for (int ii = 0; ii < nonros_argc; ++ii) {
|
||||
for (size_t ii = 0; ii < static_cast<size_t>(nonros_argc); ++ii) {
|
||||
return_arguments[ii] = std::string(nonros_argv[ii]);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ TEST_F(TestMultiThreadedExecutor, timer_over_take) {
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(last_mutex);
|
||||
double diff = std::abs((now - last).nanoseconds()) / 1.0e9;
|
||||
double diff = static_cast<double>(std::abs((now - last).nanoseconds())) / 1.0e9;
|
||||
last = now;
|
||||
|
||||
if (diff < PERIOD - TOLERANCE || diff > PERIOD + TOLERANCE) {
|
||||
|
||||
@@ -85,6 +85,26 @@ TEST_F(TestGetNodeInterfaces, node_reference) {
|
||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, rclcpp_node_pointer) {
|
||||
rclcpp::Node * node_pointer = this->node.get();
|
||||
auto result = rclcpp::node_interfaces::get_node_topics_interface(node_pointer);
|
||||
static_assert(
|
||||
std::is_same<
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
||||
decltype(result)
|
||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, node_pointer) {
|
||||
NodeWrapper * wrapped_node_pointer = this->wrapped_node.get();
|
||||
auto result = rclcpp::node_interfaces::get_node_topics_interface(wrapped_node_pointer);
|
||||
static_assert(
|
||||
std::is_same<
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
||||
decltype(result)
|
||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, interface_shared_pointer) {
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface> interface_shared_ptr =
|
||||
this->node->get_node_topics_interface();
|
||||
|
||||
57
rclcpp/test/rclcpp/test_node_options.cpp
Normal file
57
rclcpp/test/rclcpp/test_node_options.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/allocator.h"
|
||||
#include "rcl/arguments.h"
|
||||
#include "rcl/remap.h"
|
||||
|
||||
#include "rclcpp/node_options.hpp"
|
||||
|
||||
|
||||
TEST(TestNodeOptions, use_global_arguments) {
|
||||
{
|
||||
auto options = rclcpp::NodeOptions();
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
|
||||
{
|
||||
auto options = rclcpp::NodeOptions().use_global_arguments(false);
|
||||
EXPECT_FALSE(options.use_global_arguments());
|
||||
EXPECT_FALSE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
|
||||
{
|
||||
auto options = rclcpp::NodeOptions().use_global_arguments(true);
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
|
||||
{
|
||||
auto options = rclcpp::NodeOptions();
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
options.use_global_arguments(false);
|
||||
EXPECT_FALSE(options.use_global_arguments());
|
||||
EXPECT_FALSE(options.get_rcl_node_options()->use_global_arguments);
|
||||
options.use_global_arguments(true);
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
}
|
||||
63
rclcpp/test/test_create_timer.cpp
Normal file
63
rclcpp/test/test_create_timer.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/create_timer.hpp"
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "node_interfaces/node_wrapper.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
TEST(TestCreateTimer, timer_executes)
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
auto node = std::make_shared<rclcpp::Node>("test_create_timer_node");
|
||||
|
||||
std::atomic<bool> got_callback{false};
|
||||
|
||||
rclcpp::TimerBase::SharedPtr timer;
|
||||
timer = rclcpp::create_timer(
|
||||
node,
|
||||
node->get_clock(),
|
||||
rclcpp::Duration(0ms),
|
||||
[&got_callback, &timer]() {
|
||||
got_callback = true;
|
||||
timer->cancel();
|
||||
});
|
||||
|
||||
rclcpp::spin_some(node);
|
||||
|
||||
ASSERT_TRUE(got_callback);
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
TEST(TestCreateTimer, call_with_node_wrapper_compiles)
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
NodeWrapper node("test_create_timer_call_with_node_wrapper_compiles");
|
||||
|
||||
rclcpp::TimerBase::SharedPtr timer;
|
||||
timer = rclcpp::create_timer(
|
||||
node,
|
||||
node.get_node_clock_interface()->get_clock(),
|
||||
rclcpp::Duration(0ms),
|
||||
[]() {});
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
@@ -32,11 +32,7 @@ class TestDuration : public ::testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
// TEST(TestDuration, conversions) {
|
||||
// TODO(tfoote) Implement conversion methods
|
||||
// }
|
||||
|
||||
TEST(TestDuration, operators) {
|
||||
TEST_F(TestDuration, operators) {
|
||||
rclcpp::Duration old(1, 0);
|
||||
rclcpp::Duration young(2, 0);
|
||||
|
||||
@@ -45,17 +41,18 @@ TEST(TestDuration, operators) {
|
||||
EXPECT_TRUE(old <= young);
|
||||
EXPECT_TRUE(young >= old);
|
||||
EXPECT_FALSE(young == old);
|
||||
EXPECT_TRUE(young != old);
|
||||
|
||||
rclcpp::Duration add = old + young;
|
||||
EXPECT_EQ(add.nanoseconds(), (rcl_duration_value_t)(old.nanoseconds() + young.nanoseconds()));
|
||||
EXPECT_EQ(add.nanoseconds(), old.nanoseconds() + young.nanoseconds());
|
||||
EXPECT_EQ(add, old + young);
|
||||
|
||||
rclcpp::Duration sub = young - old;
|
||||
EXPECT_EQ(sub.nanoseconds(), (rcl_duration_value_t)(young.nanoseconds() - old.nanoseconds()));
|
||||
EXPECT_EQ(sub.nanoseconds(), young.nanoseconds() - old.nanoseconds());
|
||||
EXPECT_EQ(sub, young - old);
|
||||
|
||||
rclcpp::Duration scale = old * 3;
|
||||
EXPECT_EQ(scale.nanoseconds(), (rcl_duration_value_t)(old.nanoseconds() * 3));
|
||||
EXPECT_EQ(scale.nanoseconds(), old.nanoseconds() * 3);
|
||||
|
||||
rclcpp::Duration time = rclcpp::Duration(0, 0);
|
||||
rclcpp::Duration copy_constructor_duration(time);
|
||||
@@ -67,7 +64,7 @@ TEST(TestDuration, operators) {
|
||||
EXPECT_TRUE(time == assignment_op_duration);
|
||||
}
|
||||
|
||||
TEST(TestDuration, chrono_overloads) {
|
||||
TEST_F(TestDuration, chrono_overloads) {
|
||||
int64_t ns = 123456789l;
|
||||
auto chrono_ns = std::chrono::nanoseconds(ns);
|
||||
auto d1 = rclcpp::Duration(ns);
|
||||
@@ -86,7 +83,7 @@ TEST(TestDuration, chrono_overloads) {
|
||||
EXPECT_EQ(chrono_float_seconds, d5.to_chrono<decltype(chrono_float_seconds)>());
|
||||
}
|
||||
|
||||
TEST(TestDuration, overflows) {
|
||||
TEST_F(TestDuration, overflows) {
|
||||
rclcpp::Duration max(std::numeric_limits<rcl_duration_value_t>::max());
|
||||
rclcpp::Duration min(std::numeric_limits<rcl_duration_value_t>::min());
|
||||
|
||||
@@ -107,7 +104,7 @@ TEST(TestDuration, overflows) {
|
||||
EXPECT_THROW(base_d_neg * 4, std::underflow_error);
|
||||
}
|
||||
|
||||
TEST(TestDuration, negative_duration) {
|
||||
TEST_F(TestDuration, negative_duration) {
|
||||
rclcpp::Duration assignable_duration = rclcpp::Duration(0) - rclcpp::Duration(5, 0);
|
||||
|
||||
{
|
||||
@@ -130,9 +127,106 @@ TEST(TestDuration, negative_duration) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestDuration, maximum_duration) {
|
||||
TEST_F(TestDuration, maximum_duration) {
|
||||
rclcpp::Duration max_duration = rclcpp::Duration::max();
|
||||
rclcpp::Duration max(std::numeric_limits<int32_t>::max(), 999999999);
|
||||
|
||||
EXPECT_EQ(max_duration, max);
|
||||
}
|
||||
|
||||
static const int64_t HALF_SEC_IN_NS = 500 * 1000 * 1000;
|
||||
static const int64_t ONE_SEC_IN_NS = 1000 * 1000 * 1000;
|
||||
static const int64_t ONE_AND_HALF_SEC_IN_NS = 3 * HALF_SEC_IN_NS;
|
||||
|
||||
TEST_F(TestDuration, std_chrono_constructors) {
|
||||
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration(0.0s));
|
||||
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration(0s));
|
||||
EXPECT_EQ(rclcpp::Duration(1, HALF_SEC_IN_NS), rclcpp::Duration(1.5s));
|
||||
EXPECT_EQ(rclcpp::Duration(-1, 0), rclcpp::Duration(-1s));
|
||||
}
|
||||
|
||||
TEST_F(TestDuration, conversions) {
|
||||
{
|
||||
const rclcpp::Duration duration(HALF_SEC_IN_NS);
|
||||
const auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, 0);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), HALF_SEC_IN_NS);
|
||||
|
||||
const auto rmw_time = duration.to_rmw_time();
|
||||
EXPECT_EQ(rmw_time.sec, 0u);
|
||||
EXPECT_EQ(rmw_time.nsec, static_cast<uint64_t>(HALF_SEC_IN_NS));
|
||||
|
||||
const auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Duration duration(ONE_SEC_IN_NS);
|
||||
const auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, 1);
|
||||
EXPECT_EQ(duration_msg.nanosec, 0u);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), ONE_SEC_IN_NS);
|
||||
|
||||
const auto rmw_time = duration.to_rmw_time();
|
||||
EXPECT_EQ(rmw_time.sec, 1u);
|
||||
EXPECT_EQ(rmw_time.nsec, 0u);
|
||||
|
||||
const auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), ONE_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Duration duration(ONE_AND_HALF_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, 1);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), ONE_AND_HALF_SEC_IN_NS);
|
||||
|
||||
auto rmw_time = duration.to_rmw_time();
|
||||
EXPECT_EQ(rmw_time.sec, 1u);
|
||||
EXPECT_EQ(rmw_time.nsec, static_cast<uint64_t>(HALF_SEC_IN_NS));
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), ONE_AND_HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
rclcpp::Duration duration(-HALF_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, -1);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -HALF_SEC_IN_NS);
|
||||
|
||||
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), -HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
rclcpp::Duration duration(-ONE_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, -1);
|
||||
EXPECT_EQ(duration_msg.nanosec, 0u);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -ONE_SEC_IN_NS);
|
||||
|
||||
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), -ONE_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
rclcpp::Duration duration(-ONE_AND_HALF_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, -2);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -ONE_AND_HALF_SEC_IN_NS);
|
||||
|
||||
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), -ONE_AND_HALF_SEC_IN_NS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,3 +60,10 @@ TEST_F(TestExecutors, detachOnDestruction) {
|
||||
EXPECT_NO_THROW(executor.add_node(node));
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that the executor can automatically remove expired nodes correctly
|
||||
TEST_F(TestExecutors, addTemporaryNode) {
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
executor.add_node(std::make_shared<rclcpp::Node>("temporary_node"));
|
||||
EXPECT_NO_THROW(executor.spin_some());
|
||||
}
|
||||
|
||||
@@ -36,15 +36,15 @@ TEST_F(TestFindWeakNodes, allocator_strategy_with_weak_nodes) {
|
||||
rclcpp::memory_strategies::allocator_memory_strategy::AllocatorMemoryStrategy<>>();
|
||||
auto existing_node = rclcpp::Node::make_shared("existing_node");
|
||||
auto dead_node = rclcpp::Node::make_shared("dead_node");
|
||||
rclcpp::memory_strategy::MemoryStrategy::WeakNodeVector weak_nodes;
|
||||
rclcpp::memory_strategy::MemoryStrategy::WeakNodeList weak_nodes;
|
||||
weak_nodes.push_back(existing_node->get_node_base_interface());
|
||||
weak_nodes.push_back(dead_node->get_node_base_interface());
|
||||
|
||||
// AND
|
||||
// Delete dead_node, creating a dangling pointer in weak_nodes
|
||||
dead_node.reset();
|
||||
ASSERT_FALSE(weak_nodes[0].expired());
|
||||
ASSERT_TRUE(weak_nodes[1].expired());
|
||||
ASSERT_FALSE(weak_nodes.front().expired());
|
||||
ASSERT_TRUE(weak_nodes.back().expired());
|
||||
|
||||
// WHEN
|
||||
bool has_invalid_weak_nodes = memory_strategy->collect_entities(weak_nodes);
|
||||
@@ -64,11 +64,11 @@ TEST_F(TestFindWeakNodes, allocator_strategy_no_weak_nodes) {
|
||||
rclcpp::memory_strategies::allocator_memory_strategy::AllocatorMemoryStrategy<>>();
|
||||
auto existing_node1 = rclcpp::Node::make_shared("existing_node1");
|
||||
auto existing_node2 = rclcpp::Node::make_shared("existing_node2");
|
||||
rclcpp::memory_strategy::MemoryStrategy::WeakNodeVector weak_nodes;
|
||||
rclcpp::memory_strategy::MemoryStrategy::WeakNodeList weak_nodes;
|
||||
weak_nodes.push_back(existing_node1->get_node_base_interface());
|
||||
weak_nodes.push_back(existing_node2->get_node_base_interface());
|
||||
ASSERT_FALSE(weak_nodes[0].expired());
|
||||
ASSERT_FALSE(weak_nodes[1].expired());
|
||||
ASSERT_FALSE(weak_nodes.front().expired());
|
||||
ASSERT_FALSE(weak_nodes.back().expired());
|
||||
|
||||
// WHEN
|
||||
bool has_invalid_weak_nodes = memory_strategy->collect_entities(weak_nodes);
|
||||
|
||||
@@ -80,6 +80,12 @@ struct ObjectMember
|
||||
return 7;
|
||||
}
|
||||
|
||||
int callback_one_bool_const(bool a) const
|
||||
{
|
||||
(void)a;
|
||||
return 7;
|
||||
}
|
||||
|
||||
int callback_two_bools(bool a, bool b)
|
||||
{
|
||||
(void)a;
|
||||
@@ -394,6 +400,16 @@ TEST(TestFunctionTraits, argument_types) {
|
||||
rclcpp::function_traits::function_traits<decltype(bind_one_bool)>::template argument_type<0>
|
||||
>::value, "Functor accepts a bool as first argument");
|
||||
|
||||
auto bind_one_bool_const = std::bind(
|
||||
&ObjectMember::callback_one_bool_const, &object_member, std::placeholders::_1);
|
||||
|
||||
static_assert(
|
||||
std::is_same<
|
||||
bool,
|
||||
rclcpp::function_traits::function_traits<decltype(bind_one_bool_const)>::template
|
||||
argument_type<0>
|
||||
>::value, "Functor accepts a bool as first argument");
|
||||
|
||||
auto bind_two_bools = std::bind(
|
||||
&ObjectMember::callback_two_bools, &object_member, std::placeholders::_1,
|
||||
std::placeholders::_2);
|
||||
@@ -561,6 +577,14 @@ TEST(TestFunctionTraits, check_arguments) {
|
||||
static_assert(
|
||||
rclcpp::function_traits::check_arguments<decltype(bind_one_bool), bool>::value,
|
||||
"Functor accepts a single bool as arguments");
|
||||
|
||||
auto bind_one_bool_const = std::bind(
|
||||
&ObjectMember::callback_one_bool_const, &object_member, std::placeholders::_1);
|
||||
|
||||
// Test std::bind functions
|
||||
static_assert(
|
||||
rclcpp::function_traits::check_arguments<decltype(bind_one_bool_const), bool>::value,
|
||||
"Functor accepts a single bool as arguments");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -37,6 +37,9 @@ public:
|
||||
PublisherBase()
|
||||
: mock_topic_name(""), mock_queue_size(0) {}
|
||||
|
||||
virtual ~PublisherBase()
|
||||
{}
|
||||
|
||||
const char * get_topic_name() const
|
||||
{
|
||||
return mock_topic_name.c_str();
|
||||
|
||||
@@ -365,8 +365,10 @@ TEST_F(TestNode, declare_parameter_with_no_initial_values) {
|
||||
TEST_F(TestNode, declare_parameter_with_initial_values) {
|
||||
// test cases with initial values
|
||||
rclcpp::NodeOptions no;
|
||||
no.initial_parameters({
|
||||
no.parameter_overrides({
|
||||
{"parameter_no_default", 42},
|
||||
{"parameter_no_default_set", 42},
|
||||
{"parameter_no_default_set_cvref", 42},
|
||||
{"parameter_and_default", 42},
|
||||
{"parameter_custom", 42},
|
||||
{"parameter_template", 42},
|
||||
@@ -381,6 +383,25 @@ TEST_F(TestNode, declare_parameter_with_initial_values) {
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
|
||||
EXPECT_EQ(value.get<int>(), 42);
|
||||
}
|
||||
{
|
||||
// no default, with initial, and set after
|
||||
rclcpp::ParameterValue value = node->declare_parameter("parameter_no_default_set");
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
|
||||
EXPECT_EQ(value.get<int>(), 42);
|
||||
// check that the value is changed after a set
|
||||
node->set_parameter({"parameter_no_default_set", 44});
|
||||
EXPECT_EQ(node->get_parameter("parameter_no_default_set").get_value<int>(), 44);
|
||||
}
|
||||
{
|
||||
// no default, with initial
|
||||
const rclcpp::ParameterValue & value =
|
||||
node->declare_parameter("parameter_no_default_set_cvref");
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
|
||||
EXPECT_EQ(value.get<int>(), 42);
|
||||
// check that the value is changed after a set
|
||||
node->set_parameter({"parameter_no_default_set_cvref", 44});
|
||||
EXPECT_EQ(value.get<int>(), 44);
|
||||
}
|
||||
{
|
||||
// int default, with initial
|
||||
rclcpp::ParameterValue default_value(43);
|
||||
@@ -695,12 +716,370 @@ TEST_F(TestNode, set_parameter_undeclared_parameters_not_allowed) {
|
||||
|
||||
EXPECT_FALSE(node->has_parameter(name));
|
||||
}
|
||||
{
|
||||
// setting a parameter with integer range descriptor
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 10;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 2;
|
||||
node->declare_parameter(name, 10, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
|
||||
EXPECT_EQ(value.get_value<int64_t>(), 10);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 14)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 14);
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 18)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 15)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 20)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 8)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
}
|
||||
{
|
||||
// setting a parameter with integer range descriptor, from_value > to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 20;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 1;
|
||||
node->declare_parameter(name, 20, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
|
||||
EXPECT_EQ(value.get_value<int64_t>(), 20);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 18)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 19)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 10)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 25)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
}
|
||||
{
|
||||
// setting a parameter with integer range descriptor, from_value = to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 18;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 1;
|
||||
node->declare_parameter(name, 18, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
|
||||
EXPECT_EQ(value.get_value<int64_t>(), 18);
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 17)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 19)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
}
|
||||
{
|
||||
// setting a parameter with integer range descriptor, step > distance(from_value, to_value)
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 18;
|
||||
integer_range.to_value = 25;
|
||||
integer_range.step = 10;
|
||||
node->declare_parameter(name, 18, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
|
||||
EXPECT_EQ(value.get_value<int64_t>(), 18);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 25)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 17)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 19)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 26)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
|
||||
}
|
||||
{
|
||||
// setting a parameter with integer range descriptor, distance not multiple of the step.
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 18;
|
||||
integer_range.to_value = 28;
|
||||
integer_range.step = 7;
|
||||
node->declare_parameter(name, 18, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
|
||||
EXPECT_EQ(value.get_value<int64_t>(), 18);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 28)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 28);
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 25)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 17)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 19)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 32)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
|
||||
}
|
||||
{
|
||||
// setting a parameter with integer range descriptor, step=0
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 10;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 0;
|
||||
node->declare_parameter(name, 10, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
|
||||
EXPECT_EQ(value.get_value<int64_t>(), 10);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 11);
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 15)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 15);
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 18)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 19)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
|
||||
}
|
||||
{
|
||||
// setting a parameter with integer range descriptor and wrong default value will throw
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 10;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 2;
|
||||
ASSERT_THROW(
|
||||
node->declare_parameter(name, 42, descriptor),
|
||||
rclcpp::exceptions::InvalidParameterValueException);
|
||||
}
|
||||
{
|
||||
// setting a parameter with floating point range descriptor
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 0.2;
|
||||
node->declare_parameter(name, 10.0, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
|
||||
EXPECT_EQ(value.get_value<double>(), 10.0);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 10.2)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.2);
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.3)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 12.0)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.4)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
}
|
||||
{
|
||||
// setting a parameter with floating point range descriptor, negative step
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = -0.2;
|
||||
node->declare_parameter(name, 10.0, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
|
||||
EXPECT_EQ(value.get_value<double>(), 10.0);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 10.2)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.2);
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.3)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 12.0)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.4)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
}
|
||||
{
|
||||
// setting a parameter with floating point range descriptor, from_value > to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 11.0;
|
||||
floating_point_range.to_value = 10.0;
|
||||
floating_point_range.step = 0.2;
|
||||
node->declare_parameter(name, 10.0, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
|
||||
EXPECT_EQ(value.get_value<double>(), 10.0);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.2)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 12.0)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.4)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
}
|
||||
{
|
||||
// setting a parameter with floating point range descriptor, from_value = to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 10.0;
|
||||
floating_point_range.step = 0.2;
|
||||
node->declare_parameter(name, 10.0, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
|
||||
EXPECT_EQ(value.get_value<double>(), 10.0);
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.2)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 12.0)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.4)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.0);
|
||||
}
|
||||
{
|
||||
// setting a parameter with floating point range descriptor, step > distance
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 2.2;
|
||||
node->declare_parameter(name, 10.0, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
|
||||
EXPECT_EQ(value.get_value<double>(), 10.0);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 12.2)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 7.8)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
}
|
||||
{
|
||||
// setting a parameter with floating point range descriptor, distance not multiple of the step.
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 0.7;
|
||||
node->declare_parameter(name, 10.0, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
|
||||
EXPECT_EQ(value.get_value<double>(), 10.0);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 10.7)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.7);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.4)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.7);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.3)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.7);
|
||||
}
|
||||
{
|
||||
// setting a parameter with floating point range descriptor, step=0
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 0.0;
|
||||
node->declare_parameter(name, 10.0, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
|
||||
EXPECT_EQ(value.get_value<double>(), 10.0);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 10.0001)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.0001);
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 10.5479051)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.5479051);
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.001)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.999)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
}
|
||||
{
|
||||
// setting a parameter with a different type is still possible
|
||||
// when having a descriptor specifying a type (type is a status, not a constraint).
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.type = rclcpp::PARAMETER_INTEGER;
|
||||
node->declare_parameter(name, 42, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
|
||||
EXPECT_EQ(value.get_value<int64_t>(), 42);
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, "asd")).successful);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_STRING);
|
||||
EXPECT_EQ(value.get_value<std::string>(), "asd");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestNode, set_parameter_undeclared_parameters_allowed) {
|
||||
auto node = std::make_shared<rclcpp::Node>(
|
||||
"test_set_parameter_node"_unq,
|
||||
rclcpp::NodeOptions().allow_undeclared_parameters(true));
|
||||
rclcpp::NodeOptions no;
|
||||
no.parameter_overrides({
|
||||
{"parameter_with_override", 30},
|
||||
});
|
||||
no.allow_undeclared_parameters(true);
|
||||
auto node = std::make_shared<rclcpp::Node>("test_set_parameter_node"_unq, no);
|
||||
{
|
||||
// overrides are ignored when not declaring a parameter
|
||||
auto name = "parameter_with_override";
|
||||
EXPECT_FALSE(node->has_parameter(name));
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 43)).successful);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int>(), 43);
|
||||
}
|
||||
{
|
||||
// normal use (declare first) still works with this true
|
||||
auto name = "parameter"_unq;
|
||||
|
||||
@@ -32,7 +32,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestParameter, not_set_variant) {
|
||||
TEST_F(TestParameter, not_set_variant) {
|
||||
// Direct instantiation
|
||||
rclcpp::Parameter not_set_variant;
|
||||
EXPECT_EQ(rclcpp::PARAMETER_NOT_SET, not_set_variant.get_type());
|
||||
@@ -57,7 +57,7 @@ TEST(TestParameter, not_set_variant) {
|
||||
rclcpp::Parameter::from_parameter_msg(not_set_param).get_type());
|
||||
}
|
||||
|
||||
TEST(TestParameter, bool_variant) {
|
||||
TEST_F(TestParameter, bool_variant) {
|
||||
// Direct instantiation
|
||||
rclcpp::Parameter bool_variant_true("bool_param", true);
|
||||
EXPECT_EQ("bool_param", bool_variant_true.get_name());
|
||||
@@ -111,7 +111,7 @@ TEST(TestParameter, bool_variant) {
|
||||
bool_variant_false.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, integer_variant) {
|
||||
TEST_F(TestParameter, integer_variant) {
|
||||
const int TEST_VALUE {42};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -155,7 +155,7 @@ TEST(TestParameter, integer_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, long_integer_variant) {
|
||||
TEST_F(TestParameter, long_integer_variant) {
|
||||
const int64_t TEST_VALUE {std::numeric_limits<int64_t>::max()};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -199,7 +199,7 @@ TEST(TestParameter, long_integer_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, float_variant) {
|
||||
TEST_F(TestParameter, float_variant) {
|
||||
const float TEST_VALUE {42.0f};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -243,7 +243,7 @@ TEST(TestParameter, float_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, double_variant) {
|
||||
TEST_F(TestParameter, double_variant) {
|
||||
const double TEST_VALUE {-42.1};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -287,7 +287,7 @@ TEST(TestParameter, double_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, string_variant) {
|
||||
TEST_F(TestParameter, string_variant) {
|
||||
const std::string TEST_VALUE {"ROS2"};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -330,7 +330,7 @@ TEST(TestParameter, string_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, byte_array_variant) {
|
||||
TEST_F(TestParameter, byte_array_variant) {
|
||||
const std::vector<uint8_t> TEST_VALUE {0x52, 0x4f, 0x53, 0x32};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -374,7 +374,7 @@ TEST(TestParameter, byte_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, bool_array_variant) {
|
||||
TEST_F(TestParameter, bool_array_variant) {
|
||||
const std::vector<bool> TEST_VALUE {false, true, true, false, false, true};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -418,7 +418,7 @@ TEST(TestParameter, bool_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, integer_array_variant) {
|
||||
TEST_F(TestParameter, integer_array_variant) {
|
||||
const std::vector<int> TEST_VALUE
|
||||
{42, -99, std::numeric_limits<int>::max(), std::numeric_limits<int>::lowest(), 0};
|
||||
|
||||
@@ -493,7 +493,7 @@ TEST(TestParameter, integer_array_variant) {
|
||||
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY);
|
||||
}
|
||||
|
||||
TEST(TestParameter, long_integer_array_variant) {
|
||||
TEST_F(TestParameter, long_integer_array_variant) {
|
||||
const std::vector<int64_t> TEST_VALUE
|
||||
{42, -99, std::numeric_limits<int64_t>::max(), std::numeric_limits<int64_t>::lowest(), 0};
|
||||
|
||||
@@ -541,7 +541,7 @@ TEST(TestParameter, long_integer_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, float_array_variant) {
|
||||
TEST_F(TestParameter, float_array_variant) {
|
||||
const std::vector<float> TEST_VALUE
|
||||
{42.1f, -99.1f, std::numeric_limits<float>::max(), std::numeric_limits<float>::lowest(), 0.1f};
|
||||
|
||||
@@ -616,7 +616,7 @@ TEST(TestParameter, float_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, double_array_variant) {
|
||||
TEST_F(TestParameter, double_array_variant) {
|
||||
const std::vector<double> TEST_VALUE
|
||||
{42.1, -99.1, std::numeric_limits<double>::max(), std::numeric_limits<double>::lowest(), 0.1};
|
||||
|
||||
@@ -664,7 +664,7 @@ TEST(TestParameter, double_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, string_array_variant) {
|
||||
TEST_F(TestParameter, string_array_variant) {
|
||||
const std::vector<std::string> TEST_VALUE {"R", "O", "S2"};
|
||||
|
||||
// Direct instantiation
|
||||
|
||||
155
rclcpp/test/test_parameter_client.cpp
Normal file
155
rclcpp/test/test_parameter_client.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
#include "rcl_interfaces/msg/parameter_event.hpp"
|
||||
|
||||
class TestParameterClient : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void OnMessage(const rcl_interfaces::msg::ParameterEvent::SharedPtr event)
|
||||
{
|
||||
(void)event;
|
||||
}
|
||||
|
||||
protected:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void SetUp()
|
||||
{
|
||||
node = std::make_shared<rclcpp::Node>("test_parameter_client", "/ns");
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
node.reset();
|
||||
}
|
||||
|
||||
rclcpp::Node::SharedPtr node;
|
||||
};
|
||||
|
||||
/*
|
||||
Testing async parameter client construction and destruction.
|
||||
*/
|
||||
TEST_F(TestParameterClient, async_construction_and_destruction) {
|
||||
{
|
||||
auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(node);
|
||||
(void)asynchronous_client;
|
||||
}
|
||||
|
||||
{
|
||||
auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface());
|
||||
(void)asynchronous_client;
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW({
|
||||
std::make_shared<rclcpp::AsyncParametersClient>(node, "invalid_remote_node?");
|
||||
}, rclcpp::exceptions::InvalidServiceNameError);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Testing sync parameter client construction and destruction.
|
||||
*/
|
||||
TEST_F(TestParameterClient, sync_construction_and_destruction) {
|
||||
{
|
||||
auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(node);
|
||||
(void)synchronous_client;
|
||||
}
|
||||
|
||||
{
|
||||
auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(
|
||||
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
|
||||
node);
|
||||
(void)synchronous_client;
|
||||
}
|
||||
|
||||
{
|
||||
auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(
|
||||
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface());
|
||||
(void)synchronous_client;
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW({
|
||||
std::make_shared<rclcpp::SyncParametersClient>(node, "invalid_remote_node?");
|
||||
}, rclcpp::exceptions::InvalidServiceNameError);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Testing different methods for parameter event subscription from asynchronous clients.
|
||||
*/
|
||||
TEST_F(TestParameterClient, async_parameter_event_subscription) {
|
||||
auto callback = std::bind(&TestParameterClient::OnMessage, this, std::placeholders::_1);
|
||||
{
|
||||
auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(node);
|
||||
auto event_sub = asynchronous_client->on_parameter_event(callback);
|
||||
(void)event_sub;
|
||||
}
|
||||
|
||||
{
|
||||
auto event_sub = rclcpp::AsyncParametersClient::on_parameter_event(node, callback);
|
||||
(void)event_sub;
|
||||
}
|
||||
|
||||
{
|
||||
auto event_sub = rclcpp::AsyncParametersClient::on_parameter_event(
|
||||
node->get_node_topics_interface(),
|
||||
callback);
|
||||
(void)event_sub;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Testing different methods for parameter event subscription from synchronous clients.
|
||||
*/
|
||||
TEST_F(TestParameterClient, sync_parameter_event_subscription) {
|
||||
auto callback = std::bind(&TestParameterClient::OnMessage, this, std::placeholders::_1);
|
||||
{
|
||||
auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(node);
|
||||
auto event_sub = synchronous_client->on_parameter_event(callback);
|
||||
(void)event_sub;
|
||||
}
|
||||
|
||||
{
|
||||
auto event_sub = rclcpp::SyncParametersClient::on_parameter_event(node, callback);
|
||||
(void)event_sub;
|
||||
}
|
||||
|
||||
{
|
||||
auto event_sub = rclcpp::SyncParametersClient::on_parameter_event(
|
||||
node->get_node_topics_interface(),
|
||||
callback);
|
||||
(void)event_sub;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
@@ -24,12 +25,13 @@
|
||||
|
||||
class TestPublisher : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
void initialize(const rclcpp::NodeOptions & node_options = rclcpp::NodeOptions())
|
||||
{
|
||||
node = std::make_shared<rclcpp::Node>("my_node", "/ns", node_options);
|
||||
@@ -43,6 +45,25 @@ protected:
|
||||
rclcpp::Node::SharedPtr node;
|
||||
};
|
||||
|
||||
struct TestParameters
|
||||
{
|
||||
TestParameters(rclcpp::QoS qos, std::string description)
|
||||
: qos(qos), description(description) {}
|
||||
rclcpp::QoS qos;
|
||||
std::string description;
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, const TestParameters & params)
|
||||
{
|
||||
out << params.description;
|
||||
return out;
|
||||
}
|
||||
|
||||
class TestPublisherInvalidIntraprocessQos
|
||||
: public TestPublisher,
|
||||
public ::testing::WithParamInterface<TestParameters>
|
||||
{};
|
||||
|
||||
class TestPublisherSub : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
@@ -65,14 +86,6 @@ protected:
|
||||
rclcpp::Node::SharedPtr subnode;
|
||||
};
|
||||
|
||||
static constexpr rmw_qos_profile_t invalid_qos_profile()
|
||||
{
|
||||
rmw_qos_profile_t profile = rmw_qos_profile_default;
|
||||
profile.depth = 1;
|
||||
profile.durability = RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL;
|
||||
return profile;
|
||||
}
|
||||
|
||||
/*
|
||||
Testing publisher construction and destruction.
|
||||
*/
|
||||
@@ -165,29 +178,43 @@ TEST_F(TestPublisher, various_creation_signatures) {
|
||||
/*
|
||||
Testing publisher with intraprocess enabled and invalid QoS
|
||||
*/
|
||||
TEST_F(TestPublisher, intraprocess_with_invalid_qos) {
|
||||
TEST_P(TestPublisherInvalidIntraprocessQos, test_publisher_throws) {
|
||||
initialize(rclcpp::NodeOptions().use_intra_process_comms(true));
|
||||
rmw_qos_profile_t qos = invalid_qos_profile();
|
||||
rclcpp::QoS qos = GetParam().qos;
|
||||
using rcl_interfaces::msg::IntraProcessMessage;
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
ASSERT_THROW(
|
||||
{auto publisher = node->create_publisher<IntraProcessMessage>("topic", qos);},
|
||||
rclcpp::exceptions::InvalidParametersException);
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
std::invalid_argument);
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<TestParameters> invalid_qos_profiles()
|
||||
{
|
||||
std::vector<TestParameters> parameters;
|
||||
|
||||
parameters.reserve(3);
|
||||
parameters.push_back(
|
||||
TestParameters(
|
||||
rclcpp::QoS(rclcpp::KeepLast(10)).transient_local(),
|
||||
"transient_local_qos"));
|
||||
parameters.push_back(
|
||||
TestParameters(
|
||||
rclcpp::QoS(rclcpp::KeepLast(0)),
|
||||
"keep_last_qos_with_zero_history_depth"));
|
||||
parameters.push_back(
|
||||
TestParameters(
|
||||
rclcpp::QoS(rclcpp::KeepAll()),
|
||||
"keep_all_qos"));
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
TestPublisherThrows, TestPublisherInvalidIntraprocessQos,
|
||||
::testing::ValuesIn(invalid_qos_profiles()),
|
||||
::testing::PrintToStringParamName());
|
||||
|
||||
/*
|
||||
Testing publisher construction and destruction for subnodes.
|
||||
*/
|
||||
|
||||
@@ -45,7 +45,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestTime, clock_type_access) {
|
||||
TEST_F(TestTime, clock_type_access) {
|
||||
rclcpp::Clock ros_clock(RCL_ROS_TIME);
|
||||
EXPECT_EQ(RCL_ROS_TIME, ros_clock.get_clock_type());
|
||||
|
||||
@@ -56,7 +56,7 @@ TEST(TestTime, clock_type_access) {
|
||||
EXPECT_EQ(RCL_STEADY_TIME, steady_clock.get_clock_type());
|
||||
}
|
||||
|
||||
TEST(TestTime, time_sources) {
|
||||
TEST_F(TestTime, time_sources) {
|
||||
using builtin_interfaces::msg::Time;
|
||||
rclcpp::Clock ros_clock(RCL_ROS_TIME);
|
||||
Time ros_now = ros_clock.now();
|
||||
@@ -74,42 +74,124 @@ TEST(TestTime, time_sources) {
|
||||
EXPECT_NE(0u, steady_now.nanosec);
|
||||
}
|
||||
|
||||
TEST(TestTime, conversions) {
|
||||
static const int64_t HALF_SEC_IN_NS = 500 * 1000 * 1000;
|
||||
static const int64_t ONE_SEC_IN_NS = 1000 * 1000 * 1000;
|
||||
static const int64_t ONE_AND_HALF_SEC_IN_NS = 3 * HALF_SEC_IN_NS;
|
||||
|
||||
TEST_F(TestTime, conversions) {
|
||||
rclcpp::Clock system_clock(RCL_SYSTEM_TIME);
|
||||
|
||||
rclcpp::Time now = system_clock.now();
|
||||
builtin_interfaces::msg::Time now_msg = now;
|
||||
{
|
||||
rclcpp::Time now = system_clock.now();
|
||||
builtin_interfaces::msg::Time now_msg = now;
|
||||
|
||||
rclcpp::Time now_again = now_msg;
|
||||
EXPECT_EQ(now.nanoseconds(), now_again.nanoseconds());
|
||||
rclcpp::Time now_again = now_msg;
|
||||
EXPECT_EQ(now.nanoseconds(), now_again.nanoseconds());
|
||||
}
|
||||
|
||||
builtin_interfaces::msg::Time msg;
|
||||
msg.sec = 12345;
|
||||
msg.nanosec = 67890;
|
||||
{
|
||||
rclcpp::Time positive_time = rclcpp::Time(12345, 67890u);
|
||||
|
||||
rclcpp::Time time = msg;
|
||||
EXPECT_EQ(
|
||||
RCL_S_TO_NS(static_cast<int64_t>(msg.sec)) + static_cast<int64_t>(msg.nanosec),
|
||||
time.nanoseconds());
|
||||
EXPECT_EQ(static_cast<int64_t>(msg.sec), RCL_NS_TO_S(time.nanoseconds()));
|
||||
builtin_interfaces::msg::Time msg = positive_time;
|
||||
EXPECT_EQ(msg.sec, 12345);
|
||||
EXPECT_EQ(msg.nanosec, 67890u);
|
||||
|
||||
builtin_interfaces::msg::Time negative_time_msg;
|
||||
negative_time_msg.sec = -1;
|
||||
negative_time_msg.nanosec = 1;
|
||||
rclcpp::Time time = msg;
|
||||
EXPECT_EQ(time.nanoseconds(), positive_time.nanoseconds());
|
||||
EXPECT_EQ(
|
||||
RCL_S_TO_NS(static_cast<int64_t>(msg.sec)) + static_cast<int64_t>(msg.nanosec),
|
||||
time.nanoseconds());
|
||||
EXPECT_EQ(static_cast<int64_t>(msg.sec), RCL_NS_TO_S(time.nanoseconds()));
|
||||
}
|
||||
|
||||
EXPECT_ANY_THROW({
|
||||
rclcpp::Time negative_time = negative_time_msg;
|
||||
});
|
||||
// throw on construction/assignment of negative times
|
||||
{
|
||||
builtin_interfaces::msg::Time negative_time_msg;
|
||||
negative_time_msg.sec = -1;
|
||||
negative_time_msg.nanosec = 1;
|
||||
|
||||
EXPECT_ANY_THROW(rclcpp::Time(-1, 1));
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time = negative_time_msg;
|
||||
});
|
||||
|
||||
EXPECT_ANY_THROW({
|
||||
rclcpp::Time assignment(1, 2);
|
||||
assignment = negative_time_msg;
|
||||
});
|
||||
EXPECT_ANY_THROW(rclcpp::Time(-1, 1));
|
||||
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time assignment(1, 2);
|
||||
assignment = negative_time_msg;
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Time time(HALF_SEC_IN_NS);
|
||||
const auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, 0);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Time time(ONE_SEC_IN_NS);
|
||||
const auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, 1);
|
||||
EXPECT_EQ(time_msg.nanosec, 0u);
|
||||
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), ONE_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Time time(ONE_AND_HALF_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, 1);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), ONE_AND_HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
// Can rclcpp::Time be negative or not? The following constructor works:
|
||||
rclcpp::Time time(-HALF_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, -1);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
|
||||
// The opposite conversion throws...
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time(time_msg);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// Can rclcpp::Time be negative or not? The following constructor works:
|
||||
rclcpp::Time time(-ONE_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, -1);
|
||||
EXPECT_EQ(time_msg.nanosec, 0u);
|
||||
|
||||
// The opposite conversion throws...
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time(time_msg);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// Can rclcpp::Time be negative or not? The following constructor works:
|
||||
rclcpp::Time time(-ONE_AND_HALF_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, -2);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
|
||||
// The opposite conversion throws...
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time(time_msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestTime, operators) {
|
||||
TEST_F(TestTime, operators) {
|
||||
rclcpp::Time old(1, 0);
|
||||
rclcpp::Time young(2, 0);
|
||||
|
||||
@@ -121,7 +203,7 @@ TEST(TestTime, operators) {
|
||||
EXPECT_TRUE(young != old);
|
||||
|
||||
rclcpp::Duration sub = young - old;
|
||||
EXPECT_EQ(sub.nanoseconds(), (rcl_duration_value_t)(young.nanoseconds() - old.nanoseconds()));
|
||||
EXPECT_EQ(sub.nanoseconds(), (young.nanoseconds() - old.nanoseconds()));
|
||||
EXPECT_EQ(sub, young - old);
|
||||
|
||||
rclcpp::Time system_time(0, 0, RCL_SYSTEM_TIME);
|
||||
@@ -160,7 +242,7 @@ TEST(TestTime, operators) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestTime, overflow_detectors) {
|
||||
TEST_F(TestTime, overflow_detectors) {
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Test logical_eq call first:
|
||||
EXPECT_TRUE(logical_eq(false, false));
|
||||
@@ -180,8 +262,8 @@ TEST(TestTime, overflow_detectors) {
|
||||
// 256 * 256 = 64K total loops, should be pretty fast on everything
|
||||
for (big_type_t y = min_val; y <= max_val; ++y) {
|
||||
for (big_type_t x = min_val; x <= max_val; ++x) {
|
||||
const big_type_t sum = x + y;
|
||||
const big_type_t diff = x - y;
|
||||
const big_type_t sum = static_cast<big_type_t>(x + y);
|
||||
const big_type_t diff = static_cast<big_type_t>(x - y);
|
||||
|
||||
const bool add_will_overflow =
|
||||
rclcpp::add_will_overflow(test_type_t(x), test_type_t(y));
|
||||
@@ -217,7 +299,7 @@ TEST(TestTime, overflow_detectors) {
|
||||
EXPECT_TRUE(rclcpp::sub_will_underflow<int64_t>(INT64_MIN, 1));
|
||||
}
|
||||
|
||||
TEST(TestTime, overflows) {
|
||||
TEST_F(TestTime, overflows) {
|
||||
rclcpp::Time max_time(std::numeric_limits<rcl_time_point_value_t>::max());
|
||||
rclcpp::Time min_time(std::numeric_limits<rcl_time_point_value_t>::min());
|
||||
rclcpp::Duration one(1);
|
||||
@@ -245,7 +327,7 @@ TEST(TestTime, overflows) {
|
||||
EXPECT_NO_THROW(one_time - two_time);
|
||||
}
|
||||
|
||||
TEST(TestTime, seconds) {
|
||||
TEST_F(TestTime, seconds) {
|
||||
EXPECT_DOUBLE_EQ(0.0, rclcpp::Time(0, 0).seconds());
|
||||
EXPECT_DOUBLE_EQ(4.5, rclcpp::Time(4, 500000000).seconds());
|
||||
EXPECT_DOUBLE_EQ(2.5, rclcpp::Time(0, 2500000000).seconds());
|
||||
|
||||
@@ -2,6 +2,56 @@
|
||||
Changelog for package rclcpp_action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
0.7.16 (2021-05-21)
|
||||
-------------------
|
||||
|
||||
0.7.15 (2020-11-24)
|
||||
-------------------
|
||||
* Fix typo in action client logger name. (`#1414 <https://github.com/ros2/rclcpp/issues/1414>`_)
|
||||
* Contributors: Seulbae Kim
|
||||
|
||||
0.7.14 (2020-07-10)
|
||||
-------------------
|
||||
* Fixed doxygen warnings. (`#1208 <https://github.com/ros2/rclcpp/issues/1208>`_)
|
||||
* Contributors: Alejandro Hernández Cordero
|
||||
|
||||
0.7.13 (2020-03-12)
|
||||
-------------------
|
||||
|
||||
0.7.12 (2019-12-05)
|
||||
-------------------
|
||||
* Fixed memory leak in action clients (`#934 <https://github.com/ros2/rclcpp/issues/934>`_)
|
||||
* Do not throw exception in action client if take fails (`#891 <https://github.com/ros2/rclcpp/issues/891>`_)
|
||||
* Contributors: Ivan Santiago Paunovic, Jacob Perron
|
||||
|
||||
0.7.11 (2019-10-11)
|
||||
-------------------
|
||||
|
||||
0.7.10 (2019-09-23)
|
||||
-------------------
|
||||
|
||||
0.7.9 (2019-09-20)
|
||||
------------------
|
||||
|
||||
0.7.8 (2019-09-06)
|
||||
------------------
|
||||
|
||||
0.7.7 (2019-07-31)
|
||||
------------------
|
||||
|
||||
0.7.6 (2019-06-12)
|
||||
------------------
|
||||
|
||||
0.7.5 (2019-05-30)
|
||||
------------------
|
||||
|
||||
0.7.4 (2019-05-29)
|
||||
------------------
|
||||
* Guard against calling null goal response callback (`#738 <https://github.com/ros2/rclcpp/issues/738>`_)
|
||||
* Contributors: Jacob Perron
|
||||
|
||||
0.7.3 (2019-05-20)
|
||||
------------------
|
||||
|
||||
0.7.2 (2019-05-08)
|
||||
------------------
|
||||
|
||||
@@ -368,21 +368,23 @@ public:
|
||||
// Do not use std::make_shared as friendship cannot be forwarded.
|
||||
std::shared_ptr<GoalHandle> goal_handle(
|
||||
new GoalHandle(goal_info, options.feedback_callback, options.result_callback));
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(goal_handles_mutex_);
|
||||
goal_handles_[goal_handle->get_goal_id()] = goal_handle;
|
||||
}
|
||||
promise->set_value(goal_handle);
|
||||
if (options.goal_response_callback) {
|
||||
options.goal_response_callback(future);
|
||||
}
|
||||
|
||||
if (options.result_callback) {
|
||||
try {
|
||||
this->make_result_aware(goal_handle);
|
||||
} catch (...) {
|
||||
promise->set_exception(std::current_exception());
|
||||
options.goal_response_callback(future);
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(goal_handles_mutex_);
|
||||
goal_handles_[goal_handle->get_goal_id()] = goal_handle;
|
||||
promise->set_value(goal_handle);
|
||||
if (options.goal_response_callback) {
|
||||
options.goal_response_callback(future);
|
||||
}
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
@@ -30,10 +30,10 @@ namespace rclcpp_action
|
||||
* This function is equivalent to \sa create_client()` however is using the individual
|
||||
* node interfaces to create the client.
|
||||
*
|
||||
* \param node_base_interface[in] The node base interface of the corresponding node.
|
||||
* \param node_graph_interface[in] The node graph interface of the corresponding node.
|
||||
* \param node_logging_interface[in] The node logging interface of the corresponding node.
|
||||
* \param node_waitables_interface[in] The node waitables interface of the corresponding node.
|
||||
* \param[in] node_base_interface The node base interface of the corresponding node.
|
||||
* \param[in] node_graph_interface The node graph interface of the corresponding node.
|
||||
* \param[in] node_logging_interface The node logging interface of the corresponding node.
|
||||
* \param[in] node_waitables_interface The node waitables interface of the corresponding node.
|
||||
* \param[in] name The action name.
|
||||
* \param[in] group The action client will be added to this callback group.
|
||||
* If `nullptr`, then the action client is added to the default callback group.
|
||||
|
||||
@@ -39,18 +39,18 @@ namespace rclcpp_action
|
||||
*
|
||||
* \sa Server::Server() for more information.
|
||||
*
|
||||
* \param node_base_interface[in] The node base interface of the corresponding node.
|
||||
* \param node_clock_interface[in] The node clock interface of the corresponding node.
|
||||
* \param node_logging_interface[in] The node logging interface of the corresponding node.
|
||||
* \param node_waitables_interface[in] The node waitables interface of the corresponding node.
|
||||
* \param name[in] The action name.
|
||||
* \param[in] node_base_interface The node base interface of the corresponding node.
|
||||
* \param[in] node_clock_interface The node clock interface of the corresponding node.
|
||||
* \param[in] node_logging_interface The node logging interface of the corresponding node.
|
||||
* \param[in] node_waitables_interface The node waitables interface of the corresponding node.
|
||||
* \param[in] name The action name.
|
||||
* \param[in] handle_goal A callback that decides if a goal should be accepted or rejected.
|
||||
* \param[in] handle_cancel A callback that decides if a goal should be attempted to be canceled.
|
||||
* The return from this callback only indicates if the server will try to cancel a goal.
|
||||
* It does not indicate if the goal was actually canceled.
|
||||
* \param[in] handle_accepted A callback that is called to give the user a handle to the goal.
|
||||
* \param[in] options options to pass to the underlying `rcl_action_server_t`.
|
||||
* \param group[in] The action server will be added to this callback group.
|
||||
* \param[in] group The action server will be added to this callback group.
|
||||
* If `nullptr`, then the action server is added to the default callback group.
|
||||
*/
|
||||
template<typename ActionT>
|
||||
@@ -117,15 +117,15 @@ create_server(
|
||||
*
|
||||
* \sa Server::Server() for more information.
|
||||
*
|
||||
* \param node[in] The action server will be added to this node.
|
||||
* \param name[in] The action name.
|
||||
* \param[in] node] The action server will be added to this node.
|
||||
* \param[in] name The action name.
|
||||
* \param[in] handle_goal A callback that decides if a goal should be accepted or rejected.
|
||||
* \param[in] handle_cancel A callback that decides if a goal should be attempted to be canceled.
|
||||
* The return from this callback only indicates if the server will try to cancel a goal.
|
||||
* It does not indicate if the goal was actually canceled.
|
||||
* \param[in] handle_accepted A callback that is called to give the user a handle to the goal.
|
||||
* \param[in] options options to pass to the underlying `rcl_action_server_t`.
|
||||
* \param group[in] The action server will be added to this callback group.
|
||||
* \param[in] group The action server will be added to this callback group.
|
||||
* If `nullptr`, then the action server is added to the default callback group.
|
||||
*/
|
||||
template<typename ActionT>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="2">
|
||||
<name>rclcpp_action</name>
|
||||
<version>0.7.2</version>
|
||||
<version>0.7.16</version>
|
||||
<description>Adds action APIs for C++.</description>
|
||||
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
const rcl_action_client_options_t & client_options)
|
||||
: node_graph_(node_graph),
|
||||
node_handle(node_base->get_shared_rcl_node_handle()),
|
||||
logger(node_logging->get_logger().get_child("rclcpp_acton")),
|
||||
logger(node_logging->get_logger().get_child("rclcpp_action")),
|
||||
random_bytes_generator(std::random_device{} ())
|
||||
{
|
||||
std::weak_ptr<rcl_node_t> weak_node_handle(node_handle);
|
||||
@@ -165,11 +165,11 @@ ClientBase::wait_for_action_server_nanoseconds(std::chrono::nanoseconds timeout)
|
||||
if (!node_ptr) {
|
||||
throw rclcpp::exceptions::InvalidNodeError();
|
||||
}
|
||||
auto event = node_ptr->get_graph_event();
|
||||
// check to see if the server is ready immediately
|
||||
if (this->action_server_is_ready()) {
|
||||
return true;
|
||||
}
|
||||
auto event = node_ptr->get_graph_event();
|
||||
if (timeout == std::chrono::nanoseconds(0)) {
|
||||
// check was non-blocking, return immediately
|
||||
return false;
|
||||
@@ -388,20 +388,20 @@ ClientBase::execute()
|
||||
rcl_ret_t ret = rcl_action_take_feedback(
|
||||
pimpl_->client_handle.get(), feedback_message.get());
|
||||
pimpl_->is_feedback_ready = false;
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking feedback");
|
||||
} else {
|
||||
if (RCL_RET_OK == ret) {
|
||||
this->handle_feedback_message(feedback_message);
|
||||
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking feedback");
|
||||
}
|
||||
} else if (pimpl_->is_status_ready) {
|
||||
std::shared_ptr<void> status_message = this->create_status_message();
|
||||
rcl_ret_t ret = rcl_action_take_status(
|
||||
pimpl_->client_handle.get(), status_message.get());
|
||||
pimpl_->is_status_ready = false;
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking status");
|
||||
} else {
|
||||
if (RCL_RET_OK == ret) {
|
||||
this->handle_status_message(status_message);
|
||||
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking status");
|
||||
}
|
||||
} else if (pimpl_->is_goal_response_ready) {
|
||||
rmw_request_id_t response_header;
|
||||
@@ -409,10 +409,10 @@ ClientBase::execute()
|
||||
rcl_ret_t ret = rcl_action_take_goal_response(
|
||||
pimpl_->client_handle.get(), &response_header, goal_response.get());
|
||||
pimpl_->is_goal_response_ready = false;
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking goal response");
|
||||
} else {
|
||||
if (RCL_RET_OK == ret) {
|
||||
this->handle_goal_response(response_header, goal_response);
|
||||
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking goal response");
|
||||
}
|
||||
} else if (pimpl_->is_result_response_ready) {
|
||||
rmw_request_id_t response_header;
|
||||
@@ -420,10 +420,10 @@ ClientBase::execute()
|
||||
rcl_ret_t ret = rcl_action_take_result_response(
|
||||
pimpl_->client_handle.get(), &response_header, result_response.get());
|
||||
pimpl_->is_result_response_ready = false;
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking result response");
|
||||
} else {
|
||||
if (RCL_RET_OK == ret) {
|
||||
this->handle_result_response(response_header, result_response);
|
||||
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking result response");
|
||||
}
|
||||
} else if (pimpl_->is_cancel_response_ready) {
|
||||
rmw_request_id_t response_header;
|
||||
@@ -431,10 +431,10 @@ ClientBase::execute()
|
||||
rcl_ret_t ret = rcl_action_take_cancel_response(
|
||||
pimpl_->client_handle.get(), &response_header, cancel_response.get());
|
||||
pimpl_->is_cancel_response_ready = false;
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking cancel response");
|
||||
} else {
|
||||
if (RCL_RET_OK == ret) {
|
||||
this->handle_cancel_response(response_header, cancel_response);
|
||||
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking cancel response");
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("Executing action client but nothing is ready");
|
||||
|
||||
@@ -2,6 +2,57 @@
|
||||
Changelog for package rclcpp_components
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
0.7.16 (2021-05-21)
|
||||
-------------------
|
||||
|
||||
0.7.15 (2020-11-24)
|
||||
-------------------
|
||||
|
||||
0.7.14 (2020-07-10)
|
||||
-------------------
|
||||
* Added rclcpp_components Doxyfile. (`#1201 <https://github.com/ros2/rclcpp/issues/1201>`_)
|
||||
* Contributors: Alejandro Hernández Cordero
|
||||
|
||||
0.7.13 (2020-03-12)
|
||||
-------------------
|
||||
* Remove absolute path from installed CMake code. (`#949 <https://github.com/ros2/rclcpp/issues/949>`_)
|
||||
* Contributors: Jacob Perron
|
||||
|
||||
0.7.12 (2019-12-05)
|
||||
-------------------
|
||||
* Backport rclcpp_components_register_node (`#935 <https://github.com/ros2/rclcpp/issues/935>`_)
|
||||
* Contributors: Shane Loretz
|
||||
|
||||
0.7.11 (2019-10-11)
|
||||
-------------------
|
||||
|
||||
0.7.10 (2019-09-23)
|
||||
-------------------
|
||||
|
||||
0.7.9 (2019-09-20)
|
||||
------------------
|
||||
|
||||
0.7.8 (2019-09-06)
|
||||
------------------
|
||||
|
||||
0.7.7 (2019-07-31)
|
||||
------------------
|
||||
|
||||
0.7.6 (2019-06-12)
|
||||
------------------
|
||||
|
||||
0.7.5 (2019-05-30)
|
||||
------------------
|
||||
|
||||
0.7.4 (2019-05-29)
|
||||
------------------
|
||||
* Rename parameter options (`#745 <https://github.com/ros2/rclcpp/issues/745>`_)
|
||||
* don't use global arguments for components loaded into the manager (`#736 <https://github.com/ros2/rclcpp/issues/736>`_)
|
||||
* Contributors: Dirk Thomas, William Woodall
|
||||
|
||||
0.7.3 (2019-05-20)
|
||||
------------------
|
||||
|
||||
0.7.2 (2019-05-08)
|
||||
------------------
|
||||
* Updated to support changes to ``Node::get_node_names()``. (`#698 <https://github.com/ros2/rclcpp/issues/698>`_)
|
||||
|
||||
@@ -41,6 +41,11 @@ ament_target_dependencies(component_container
|
||||
"rclcpp"
|
||||
)
|
||||
|
||||
set(node_main_template_install_dir "share/${PROJECT_NAME}")
|
||||
install(FILES
|
||||
src/node_main.cpp.in
|
||||
DESTINATION ${node_main_template_install_dir})
|
||||
|
||||
add_executable(
|
||||
component_container_mt
|
||||
src/component_container_mt.cpp
|
||||
@@ -119,4 +124,4 @@ install(
|
||||
ament_export_include_directories(include)
|
||||
ament_export_dependencies(class_loader)
|
||||
ament_export_dependencies(rclcpp)
|
||||
ament_package(CONFIG_EXTRAS rclcpp_components-extras.cmake)
|
||||
ament_package(CONFIG_EXTRAS rclcpp_components-extras.cmake.in)
|
||||
|
||||
33
rclcpp_components/Doxyfile
Normal file
33
rclcpp_components/Doxyfile
Normal file
@@ -0,0 +1,33 @@
|
||||
# All settings not listed here will use the Doxygen default values.
|
||||
|
||||
PROJECT_NAME = "rclcpp_components"
|
||||
PROJECT_NUMBER = master
|
||||
PROJECT_BRIEF = "Package containing tools for dynamically loadable components"
|
||||
|
||||
# Use these lines to include the generated logging.hpp (update install path if needed)
|
||||
# Otherwise just generate for the local (non-generated header files)
|
||||
INPUT = ./include
|
||||
|
||||
RECURSIVE = YES
|
||||
OUTPUT_DIRECTORY = doc_output
|
||||
|
||||
EXTRACT_ALL = YES
|
||||
SORT_MEMBER_DOCS = NO
|
||||
|
||||
GENERATE_LATEX = NO
|
||||
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
PREDEFINED = RCLCPP_COMPONENTS_PUBLIC=
|
||||
|
||||
# Tag files that do not exist will produce a warning and cross-project linking will not work.
|
||||
TAGFILES += "../../../../doxygen_tag_files/cppreference-doxygen-web.tag.xml=http://en.cppreference.com/w/"
|
||||
# Consider changing "latest" to the version you want to reference (e.g. beta1 or 1.0.0)
|
||||
TAGFILES += "../../../../doxygen_tag_files/class_loader.tag=http://docs.ros2.org/latest/api/class_loader/"
|
||||
TAGFILES += "../../../../doxygen_tag_files/rclcpp.tag=http://docs.ros2.org/latest/api/rclcpp/"
|
||||
TAGFILES += "../../../../doxygen_tag_files/rcl.tag=http://docs.ros2.org/latest/api/rcl/"
|
||||
TAGFILES += "../../../../doxygen_tag_files/rcutils.tag=http://docs.ros2.org/latest/api/rcutils/"
|
||||
TAGFILES += "../../../../doxygen_tag_files/rmw.tag=http://docs.ros2.org/latest/api/rmw/"
|
||||
# Uncomment to generate tag files for cross-project linking.
|
||||
GENERATE_TAGFILE = "../../../../doxygen_tag_files/rclcpp_components.tag"
|
||||
@@ -0,0 +1,52 @@
|
||||
# Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# usage: rclcpp_components_register_node(
|
||||
# <target> PLUGIN <component> EXECUTABLE <node>)
|
||||
#
|
||||
# Register an rclcpp component with the ament
|
||||
# resource index and create an executable.
|
||||
#
|
||||
# :param target: the shared library target
|
||||
# :type target: string
|
||||
# :param PLUGIN: the plugin name
|
||||
# :type PLUGIN: string
|
||||
# :type EXECUTABLE: the node's executable name
|
||||
# :type EXECUTABLE: string
|
||||
#
|
||||
macro(rclcpp_components_register_node target)
|
||||
cmake_parse_arguments(ARGS "" "PLUGIN;EXECUTABLE" "" ${ARGN})
|
||||
set(component ${ARGS_PLUGIN})
|
||||
set(node ${ARGS_EXECUTABLE})
|
||||
_rclcpp_components_register_package_hook()
|
||||
set(_path "lib")
|
||||
set(library_name "$<TARGET_FILE_NAME:${target}>")
|
||||
if(WIN32)
|
||||
set(_path "bin")
|
||||
endif()
|
||||
set(_RCLCPP_COMPONENTS__NODES
|
||||
"${_RCLCPP_COMPONENTS__NODES}${component};${_path}/$<TARGET_FILE_NAME:${target}>\n")
|
||||
configure_file(${rclcpp_components_NODE_TEMPLATE}
|
||||
${PROJECT_BINARY_DIR}/rclcpp_components/node_main_configured_${node}.cpp.in)
|
||||
file(GENERATE OUTPUT ${PROJECT_BINARY_DIR}/rclcpp_components/node_main_${node}.cpp
|
||||
INPUT ${PROJECT_BINARY_DIR}/rclcpp_components/node_main_configured_${node}.cpp.in)
|
||||
add_executable(${node} ${PROJECT_BINARY_DIR}/rclcpp_components/node_main_${node}.cpp)
|
||||
ament_target_dependencies(${node}
|
||||
"rclcpp"
|
||||
"class_loader"
|
||||
"rclcpp_components")
|
||||
install(TARGETS
|
||||
${node}
|
||||
DESTINATION lib/${PROJECT_NAME})
|
||||
endmacro()
|
||||
@@ -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_components</name>
|
||||
<version>0.7.2</version>
|
||||
<version>0.7.16</version>
|
||||
<description>Package containing tools for dynamically loadable components</description>
|
||||
<maintainer email="michael@openrobotics.org">Michael Carroll</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -25,5 +25,8 @@ macro(_rclcpp_components_register_package_hook)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
include("${rclcpp_components_DIR}/rclcpp_components_register_nodes.cmake")
|
||||
get_filename_component(@PROJECT_NAME@_SHARE_DIR "${@PROJECT_NAME@_DIR}" DIRECTORY)
|
||||
set(@PROJECT_NAME@_NODE_TEMPLATE "${@PROJECT_NAME@_SHARE_DIR}/node_main.cpp.in")
|
||||
|
||||
include("${rclcpp_components_DIR}/rclcpp_components_register_nodes.cmake")
|
||||
include("${rclcpp_components_DIR}/rclcpp_components_register_node.cmake")
|
||||
@@ -149,7 +149,8 @@ ComponentManager::OnLoadNode(
|
||||
}
|
||||
|
||||
auto options = rclcpp::NodeOptions()
|
||||
.initial_parameters(parameters)
|
||||
.use_global_arguments(false)
|
||||
.parameter_overrides(parameters)
|
||||
.arguments(remap_rules);
|
||||
|
||||
auto node_id = unique_id++;
|
||||
|
||||
66
rclcpp_components/src/node_main.cpp.in
Normal file
66
rclcpp_components/src/node_main.cpp.in
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "class_loader/class_loader.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "rclcpp_components/node_factory.hpp"
|
||||
#include "rclcpp_components/node_factory_template.hpp"
|
||||
|
||||
#define NODE_MAIN_LOGGER_NAME "@node@"
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
auto args = rclcpp::init_and_remove_ros_arguments(argc, argv);
|
||||
rclcpp::Logger logger = rclcpp::get_logger(NODE_MAIN_LOGGER_NAME);
|
||||
rclcpp::executors::SingleThreadedExecutor exec;
|
||||
rclcpp::NodeOptions options;
|
||||
options.arguments(args);
|
||||
std::vector<class_loader::ClassLoader * > loaders;
|
||||
std::vector<rclcpp_components::NodeInstanceWrapper> node_wrappers;
|
||||
|
||||
std::string library_name = "@library_name@";
|
||||
std::string class_name = "rclcpp_components::NodeFactoryTemplate<@component@>";
|
||||
|
||||
RCLCPP_DEBUG(logger, "Load library %s", library_name.c_str());
|
||||
auto loader = new class_loader::ClassLoader(library_name);
|
||||
auto classes = loader->getAvailableClasses<rclcpp_components::NodeFactory>();
|
||||
for (auto clazz : classes) {
|
||||
std::string name = clazz.c_str();
|
||||
if (!(name.compare(class_name))) {
|
||||
RCLCPP_DEBUG(logger, "Instantiate class %s", clazz.c_str());
|
||||
auto node_factory = loader->createInstance<rclcpp_components::NodeFactory>(clazz);
|
||||
auto wrapper = node_factory->create_node_instance(options);
|
||||
auto node = wrapper.get_node_base_interface();
|
||||
node_wrappers.push_back(wrapper);
|
||||
exec.add_node(node);
|
||||
}
|
||||
}
|
||||
loaders.push_back(loader);
|
||||
|
||||
|
||||
exec.spin();
|
||||
|
||||
for (auto wrapper : node_wrappers) {
|
||||
exec.remove_node(wrapper.get_node_base_interface());
|
||||
}
|
||||
node_wrappers.clear();
|
||||
|
||||
rclcpp::shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2,6 +2,61 @@
|
||||
Changelog for package rclcpp_lifecycle
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
0.7.16 (2021-05-21)
|
||||
-------------------
|
||||
|
||||
0.7.15 (2020-11-24)
|
||||
-------------------
|
||||
* Type conversions fixes. (`#901 <https://github.com/ros2/rclcpp/issues/901>`_) (`#1209 <https://github.com/ros2/rclcpp/issues/1209>`_)
|
||||
* Contributors: Michel Hidalgo, Monika Idzik
|
||||
|
||||
0.7.14 (2020-07-10)
|
||||
-------------------
|
||||
* Fixed doxygen warnings. (`#1208 <https://github.com/ros2/rclcpp/issues/1208>`_)
|
||||
* Contributors: Alejandro Hernández Cordero
|
||||
|
||||
0.7.13 (2020-03-12)
|
||||
-------------------
|
||||
|
||||
0.7.12 (2019-12-05)
|
||||
-------------------
|
||||
|
||||
0.7.11 (2019-10-11)
|
||||
-------------------
|
||||
|
||||
0.7.10 (2019-09-23)
|
||||
-------------------
|
||||
* reset error message before setting a new one, embed the original one (`#854 <https://github.com/ros2/rclcpp/issues/854>`_) (`#866 <https://github.com/ros2/rclcpp/issues/866>`_)
|
||||
* Contributors: Dirk Thomas, Zachary Michaels
|
||||
|
||||
0.7.9 (2019-09-20)
|
||||
------------------
|
||||
|
||||
0.7.8 (2019-09-06)
|
||||
------------------
|
||||
* Fixed error messages which were not printing to console. (`#777 <https://github.com/ros2/rclcpp/issues/777>`_) (`#847 <https://github.com/ros2/rclcpp/issues/847>`_)
|
||||
* Contributors: Jacob Perron
|
||||
|
||||
0.7.7 (2019-07-31)
|
||||
------------------
|
||||
* Added a default value to node options in LifecycleNode constructor to match node constructor. Updated API documentation. (`#801 <https://github.com/ros2/rclcpp/issues/801>`_)
|
||||
* Contributors: Esteve Fernandez, Dirk Thomas
|
||||
|
||||
0.7.6 (2019-06-12)
|
||||
------------------
|
||||
|
||||
0.7.5 (2019-05-30)
|
||||
------------------
|
||||
|
||||
0.7.4 (2019-05-29)
|
||||
------------------
|
||||
* Rename parameter options (`#745 <https://github.com/ros2/rclcpp/issues/745>`_)
|
||||
* Contributors: William Woodall
|
||||
|
||||
0.7.3 (2019-05-20)
|
||||
------------------
|
||||
* Added missing template functionality to lifecycle_node. (`#707 <https://github.com/ros2/rclcpp/issues/707>`_)
|
||||
* Contributors: Michael Jeronimo
|
||||
|
||||
0.7.2 (2019-05-08)
|
||||
------------------
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
#ifndef RCLCPP_LIFECYCLE__LIFECYCLE_NODE_HPP_
|
||||
#define RCLCPP_LIFECYCLE__LIFECYCLE_NODE_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/node.h"
|
||||
@@ -102,7 +103,6 @@ public:
|
||||
/// Create a new lifecycle node with the specified name.
|
||||
/**
|
||||
* \param[in] node_name Name of the node.
|
||||
* \param[in] namespace_ Namespace of the node.
|
||||
* \param[in] options Additional options to control creation of the node.
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
@@ -114,14 +114,13 @@ public:
|
||||
/**
|
||||
* \param[in] node_name Name of the node.
|
||||
* \param[in] namespace_ Namespace of the node.
|
||||
* \param[in] context The context for the node (usually represents the state of a process).
|
||||
* \param[in] options Additional options to control creation of the node.
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
LifecycleNode(
|
||||
const std::string & node_name,
|
||||
const std::string & namespace_,
|
||||
const rclcpp::NodeOptions & options);
|
||||
const rclcpp::NodeOptions & options = rclcpp::NodeOptions());
|
||||
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
virtual ~LifecycleNode();
|
||||
@@ -333,15 +332,100 @@ public:
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Declare and initialize a parameter, return the effective value.
|
||||
/**
|
||||
* \sa rclcpp::Node::declare_parameter
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
const rclcpp::ParameterValue &
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor());
|
||||
|
||||
/// Declare and initialize a parameter with a type.
|
||||
/**
|
||||
* \sa rclcpp::Node::declare_parameter
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
auto
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const ParameterT & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
|
||||
rcl_interfaces::msg::ParameterDescriptor());
|
||||
|
||||
/// Declare and initialize several parameters with the same namespace and type.
|
||||
/**
|
||||
* \sa rclcpp::Node::declare_parameters
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
std::vector<ParameterT>
|
||||
declare_parameters(
|
||||
const std::string & namespace_,
|
||||
const std::map<std::string, ParameterT> & parameters);
|
||||
|
||||
/// Declare and initialize several parameters with the same namespace and type.
|
||||
/**
|
||||
* \sa rclcpp::Node::declare_parameters
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
std::vector<ParameterT>
|
||||
declare_parameters(
|
||||
const std::string & namespace_,
|
||||
const std::map<
|
||||
std::string,
|
||||
std::pair<ParameterT, rcl_interfaces::msg::ParameterDescriptor>
|
||||
> & parameters);
|
||||
|
||||
/// Undeclare a previously declared parameter.
|
||||
/**
|
||||
* \sa rclcpp::Node::undeclare_parameter
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
void
|
||||
undeclare_parameter(const std::string & name);
|
||||
|
||||
/// Return true if a given parameter is declared.
|
||||
/**
|
||||
* \sa rclcpp::Node::has_parameter
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
bool
|
||||
has_parameter(const std::string & name) const;
|
||||
|
||||
/// Set a single parameter.
|
||||
/**
|
||||
* \sa rclcpp::Node::set_parameter
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
set_parameter(const rclcpp::Parameter & parameter);
|
||||
|
||||
/// Set one or more parameters, one at a time.
|
||||
/**
|
||||
* \sa rclcpp::Node::set_parameters
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
set_parameters(const std::vector<rclcpp::Parameter> & parameters);
|
||||
|
||||
/// Set one or more parameters, all at once.
|
||||
/**
|
||||
* \sa rclcpp::Node::set_parameters_atomically
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
set_parameters_atomically(const std::vector<rclcpp::Parameter> & parameters);
|
||||
|
||||
/// Set one parameter, unless that parameter has already been set.
|
||||
/**
|
||||
* \sa rclcpp::Node::set_parameter_if_not_set
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
|
||||
[[deprecated("use declare_parameter() instead")]]
|
||||
void
|
||||
set_parameter_if_not_set(
|
||||
const std::string & name,
|
||||
@@ -349,54 +433,46 @@ public:
|
||||
|
||||
/// Set a map of parameters with the same prefix.
|
||||
/**
|
||||
* For each key in the map, a parameter with a name of "name.key" will be set
|
||||
* to the value in the map.
|
||||
*
|
||||
* \param[in] name The prefix of the parameters to set.
|
||||
* \param[in] values The parameters to set in the given prefix.
|
||||
* \sa rclcpp::Node::set_parameters_if_not_set
|
||||
*/
|
||||
template<typename MapValueT>
|
||||
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
|
||||
[[deprecated("use declare_parameters() instead")]]
|
||||
void
|
||||
set_parameters_if_not_set(
|
||||
const std::string & name,
|
||||
const std::map<std::string, MapValueT> & values);
|
||||
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
std::vector<rclcpp::Parameter>
|
||||
get_parameters(const std::vector<std::string> & names) const;
|
||||
|
||||
/// Return the parameter by the given name.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_parameter
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
rclcpp::Parameter
|
||||
get_parameter(const std::string & name) const;
|
||||
|
||||
/// Get the value of a parameter by the given name, and return true if it was set.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_parameter
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
bool
|
||||
get_parameter(
|
||||
const std::string & name,
|
||||
rclcpp::Parameter & parameter) const;
|
||||
|
||||
/// Get the value of a parameter by the given name, and return true if it was set.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_parameter
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
bool
|
||||
get_parameter(const std::string & name, ParameterT & parameter) const;
|
||||
|
||||
/// Assign the value of the map parameter if set into the values argument.
|
||||
/// Get the parameter value, or the "alternative_value" if not set, and assign it to "parameter".
|
||||
/**
|
||||
* Parameter names that are part of a map are of the form "name.member".
|
||||
* This API gets all parameters that begin with "name", storing them into the
|
||||
* map with the name of the parameter and their value.
|
||||
* If there are no members in the named map, then the "values" argument is not changed.
|
||||
*
|
||||
* \param[in] name The prefix of the parameters to get.
|
||||
* \param[out] values The map of output values, with one std::string,MapValueT
|
||||
* per parameter.
|
||||
* \returns true if values was changed, false otherwise
|
||||
* \sa rclcpp::Node::get_parameter_or
|
||||
*/
|
||||
template<typename MapValueT>
|
||||
bool
|
||||
get_parameters(
|
||||
const std::string & name,
|
||||
std::map<std::string, MapValueT> & values) const;
|
||||
|
||||
template<typename ParameterT>
|
||||
bool
|
||||
get_parameter_or(
|
||||
@@ -404,42 +480,88 @@ public:
|
||||
ParameterT & value,
|
||||
const ParameterT & alternative_value) const;
|
||||
|
||||
/// Return the parameters by the given parameter names.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_parameters
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
std::vector<rclcpp::Parameter>
|
||||
get_parameters(const std::vector<std::string> & names) const;
|
||||
|
||||
/// Get the parameter values for all parameters that have a given prefix.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_parameters
|
||||
*/
|
||||
template<typename MapValueT>
|
||||
bool
|
||||
get_parameters(
|
||||
const std::string & prefix,
|
||||
std::map<std::string, MapValueT> & values) const;
|
||||
|
||||
/// Get the parameter value; if not set, set the "alternative value" and store it in the node.
|
||||
/**
|
||||
* If the parameter is set, then the "value" argument is assigned the value
|
||||
* in the parameter.
|
||||
* If the parameter is not set, then the "value" argument is assigned the "alternative_value",
|
||||
* and the parameter is set to the "alternative_value" on the node.
|
||||
*
|
||||
* \param[in] name The name of the parameter to get.
|
||||
* \param[out] value The output where the value of the parameter should be assigned.
|
||||
* \param[in] alternative_value Value to be stored in output and parameter if the parameter was not set.
|
||||
* \sa rclcpp::Node::get_parameter_or_set
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
|
||||
[[deprecated("use declare_parameter() and it's return value instead")]]
|
||||
void
|
||||
get_parameter_or_set(
|
||||
const std::string & name,
|
||||
ParameterT & value,
|
||||
const ParameterT & alternative_value);
|
||||
|
||||
/// Return the parameter descriptor for the given parameter name.
|
||||
/**
|
||||
* \sa rclcpp::Node::describe_parameter
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
rcl_interfaces::msg::ParameterDescriptor
|
||||
describe_parameter(const std::string & name) const;
|
||||
|
||||
/// Return a vector of parameter descriptors, one for each of the given names.
|
||||
/**
|
||||
* \sa rclcpp::Node::describe_parameters
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
std::vector<rcl_interfaces::msg::ParameterDescriptor>
|
||||
describe_parameters(const std::vector<std::string> & names) const;
|
||||
|
||||
/// Return a vector of parameter types, one for each of the given names.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_parameter_types
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
std::vector<uint8_t>
|
||||
get_parameter_types(const std::vector<std::string> & names) const;
|
||||
|
||||
/// Return a list of parameters with any of the given prefixes, up to the given depth.
|
||||
/**
|
||||
* \sa rclcpp::Node::list_parameters
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const;
|
||||
|
||||
using OnParametersSetCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;
|
||||
|
||||
/// Register a callback to be called anytime a parameter is about to be changed.
|
||||
/**
|
||||
* \sa rclcpp::Node::set_on_parameters_set_callback
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
rclcpp_lifecycle::LifecycleNode::OnParametersSetCallbackType
|
||||
set_on_parameters_set_callback(
|
||||
rclcpp_lifecycle::LifecycleNode::OnParametersSetCallbackType callback);
|
||||
|
||||
/// Register the callback for parameter changes
|
||||
/**
|
||||
* \param[in] callback User defined function which is expected to atomically set parameters.
|
||||
* \note Repeated invocations of this function will overwrite previous callbacks
|
||||
* \sa rclcpp::Node::register_param_change_callback
|
||||
*/
|
||||
template<typename CallbackT>
|
||||
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
|
||||
[[deprecated("use set_on_parameters_set_callback() instead")]]
|
||||
void
|
||||
register_param_change_callback(CallbackT && callback);
|
||||
|
||||
|
||||
@@ -223,6 +223,62 @@ LifecycleNode::create_service(
|
||||
service_name, std::forward<CallbackT>(callback), qos_profile, group);
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
auto
|
||||
LifecycleNode::declare_parameter(
|
||||
const std::string & name,
|
||||
const ParameterT & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor)
|
||||
{
|
||||
return this->declare_parameter(
|
||||
name,
|
||||
rclcpp::ParameterValue(default_value),
|
||||
parameter_descriptor
|
||||
).get<ParameterT>();
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
std::vector<ParameterT>
|
||||
LifecycleNode::declare_parameters(
|
||||
const std::string & namespace_,
|
||||
const std::map<std::string, ParameterT> & parameters)
|
||||
{
|
||||
std::vector<ParameterT> result;
|
||||
std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
|
||||
std::transform(
|
||||
parameters.begin(), parameters.end(), std::back_inserter(result),
|
||||
[this, &normalized_namespace](auto element) {
|
||||
return this->declare_parameter(normalized_namespace + element.first, element.second);
|
||||
}
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
std::vector<ParameterT>
|
||||
LifecycleNode::declare_parameters(
|
||||
const std::string & namespace_,
|
||||
const std::map<
|
||||
std::string,
|
||||
std::pair<ParameterT, rcl_interfaces::msg::ParameterDescriptor>
|
||||
> & parameters)
|
||||
{
|
||||
std::vector<ParameterT> result;
|
||||
std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
|
||||
std::transform(
|
||||
parameters.begin(), parameters.end(), std::back_inserter(result),
|
||||
[this, &normalized_namespace](auto element) {
|
||||
return static_cast<ParameterT>(
|
||||
this->declare_parameter(
|
||||
normalized_namespace + element.first,
|
||||
element.second.first,
|
||||
element.second.second)
|
||||
);
|
||||
}
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
bool
|
||||
LifecycleNode::get_parameter(const std::string & name, ParameterT & parameter) const
|
||||
@@ -283,11 +339,11 @@ LifecycleNode::set_parameters_if_not_set(
|
||||
template<typename MapValueT>
|
||||
bool
|
||||
LifecycleNode::get_parameters(
|
||||
const std::string & name,
|
||||
const std::string & prefix,
|
||||
std::map<std::string, MapValueT> & values) const
|
||||
{
|
||||
std::map<std::string, rclcpp::Parameter> params;
|
||||
bool result = node_parameters_->get_parameters_by_prefix(name, params);
|
||||
bool result = node_parameters_->get_parameters_by_prefix(prefix, params);
|
||||
if (result) {
|
||||
for (const auto & param : params) {
|
||||
values[param.first] = param.second.get_value<MapValueT>();
|
||||
|
||||
@@ -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_lifecycle</name>
|
||||
<version>0.7.2</version>
|
||||
<version>0.7.16</version>
|
||||
<description>Package containing a prototype for lifecycle implementation</description>
|
||||
<maintainer email="karsten@osrfoundation.org">Karsten Knese</maintainer>
|
||||
<license>Apache License 2.0</license>
|
||||
|
||||
@@ -91,13 +91,13 @@ LifecycleNode::LifecycleNode(
|
||||
node_topics_,
|
||||
node_services_,
|
||||
node_clock_,
|
||||
options.initial_parameters(),
|
||||
options.parameter_overrides(),
|
||||
options.start_parameter_services(),
|
||||
options.start_parameter_event_publisher(),
|
||||
options.parameter_event_qos(),
|
||||
options.parameter_event_publisher_options(),
|
||||
options.allow_undeclared_parameters(),
|
||||
options.automatically_declare_initial_parameters()
|
||||
options.automatically_declare_parameters_from_overrides()
|
||||
)),
|
||||
node_time_source_(new rclcpp::node_interfaces::NodeTimeSource(
|
||||
node_base_,
|
||||
@@ -154,6 +154,33 @@ LifecycleNode::create_callback_group(
|
||||
return node_base_->create_callback_group(group_type);
|
||||
}
|
||||
|
||||
const rclcpp::ParameterValue &
|
||||
LifecycleNode::declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor)
|
||||
{
|
||||
return this->node_parameters_->declare_parameter(name, default_value, parameter_descriptor);
|
||||
}
|
||||
|
||||
void
|
||||
LifecycleNode::undeclare_parameter(const std::string & name)
|
||||
{
|
||||
this->node_parameters_->undeclare_parameter(name);
|
||||
}
|
||||
|
||||
bool
|
||||
LifecycleNode::has_parameter(const std::string & name) const
|
||||
{
|
||||
return this->node_parameters_->has_parameter(name);
|
||||
}
|
||||
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
LifecycleNode::set_parameter(const rclcpp::Parameter & parameter)
|
||||
{
|
||||
return this->set_parameters_atomically({parameter});
|
||||
}
|
||||
|
||||
bool
|
||||
LifecycleNode::group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
@@ -187,13 +214,27 @@ LifecycleNode::get_parameter(const std::string & name) const
|
||||
return node_parameters_->get_parameter(name);
|
||||
}
|
||||
|
||||
bool LifecycleNode::get_parameter(
|
||||
bool
|
||||
LifecycleNode::get_parameter(
|
||||
const std::string & name,
|
||||
rclcpp::Parameter & parameter) const
|
||||
{
|
||||
return node_parameters_->get_parameter(name, parameter);
|
||||
}
|
||||
|
||||
rcl_interfaces::msg::ParameterDescriptor
|
||||
LifecycleNode::describe_parameter(const std::string & name) const
|
||||
{
|
||||
auto result = node_parameters_->describe_parameters({name});
|
||||
if (0 == result.size()) {
|
||||
throw rclcpp::exceptions::ParameterNotDeclaredException(name);
|
||||
}
|
||||
if (result.size() > 1) {
|
||||
throw std::runtime_error("number of described parameters unexpectedly more than one");
|
||||
}
|
||||
return result.front();
|
||||
}
|
||||
|
||||
std::vector<rcl_interfaces::msg::ParameterDescriptor>
|
||||
LifecycleNode::describe_parameters(
|
||||
const std::vector<std::string> & names) const
|
||||
@@ -215,6 +256,12 @@ LifecycleNode::list_parameters(
|
||||
return node_parameters_->list_parameters(prefixes, depth);
|
||||
}
|
||||
|
||||
rclcpp::Node::OnParametersSetCallbackType
|
||||
LifecycleNode::set_on_parameters_set_callback(rclcpp::Node::OnParametersSetCallbackType callback)
|
||||
{
|
||||
return node_parameters_->set_on_parameters_set_callback(callback);
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
LifecycleNode::get_node_names() const
|
||||
{
|
||||
|
||||
@@ -219,7 +219,7 @@ public:
|
||||
resp->success = false;
|
||||
return;
|
||||
}
|
||||
transition_id = rcl_transition->id;
|
||||
transition_id = static_cast<std::uint8_t>(rcl_transition->id);
|
||||
}
|
||||
|
||||
node_interfaces::LifecycleNodeInterface::CallbackReturn cb_return_code;
|
||||
@@ -284,11 +284,11 @@ public:
|
||||
for (uint8_t i = 0; i < state_machine_.current_state->valid_transition_size; ++i) {
|
||||
auto rcl_transition = state_machine_.current_state->valid_transitions[i];
|
||||
lifecycle_msgs::msg::TransitionDescription trans_desc;
|
||||
trans_desc.transition.id = rcl_transition.id;
|
||||
trans_desc.transition.id = static_cast<uint8_t>(rcl_transition.id);
|
||||
trans_desc.transition.label = rcl_transition.label;
|
||||
trans_desc.start_state.id = rcl_transition.start->id;
|
||||
trans_desc.start_state.id = static_cast<uint8_t>(rcl_transition.start->id);
|
||||
trans_desc.start_state.label = rcl_transition.start->label;
|
||||
trans_desc.goal_state.id = rcl_transition.goal->id;
|
||||
trans_desc.goal_state.id = static_cast<uint8_t>(rcl_transition.goal->id);
|
||||
trans_desc.goal_state.label = rcl_transition.goal->label;
|
||||
resp->available_transitions.push_back(trans_desc);
|
||||
}
|
||||
@@ -310,11 +310,11 @@ public:
|
||||
for (uint8_t i = 0; i < state_machine_.transition_map.transitions_size; ++i) {
|
||||
auto rcl_transition = state_machine_.transition_map.transitions[i];
|
||||
lifecycle_msgs::msg::TransitionDescription trans_desc;
|
||||
trans_desc.transition.id = rcl_transition.id;
|
||||
trans_desc.transition.id = static_cast<uint8_t>(rcl_transition.id);
|
||||
trans_desc.transition.label = rcl_transition.label;
|
||||
trans_desc.start_state.id = rcl_transition.start->id;
|
||||
trans_desc.start_state.id = static_cast<uint8_t>(rcl_transition.start->id);
|
||||
trans_desc.start_state.label = rcl_transition.start->label;
|
||||
trans_desc.goal_state.id = rcl_transition.goal->id;
|
||||
trans_desc.goal_state.id = static_cast<uint8_t>(rcl_transition.goal->id);
|
||||
trans_desc.goal_state.label = rcl_transition.goal->label;
|
||||
resp->available_transitions.push_back(trans_desc);
|
||||
}
|
||||
@@ -369,6 +369,7 @@ public:
|
||||
{
|
||||
RCUTILS_LOG_ERROR("Unable to start transition %u from current state %s: %s",
|
||||
transition_id, state_machine_.current_state->label, rcl_get_error_string().str);
|
||||
rcutils_reset_error();
|
||||
return RCL_RET_ERROR;
|
||||
}
|
||||
|
||||
@@ -389,8 +390,10 @@ public:
|
||||
if (rcl_lifecycle_trigger_transition_by_label(
|
||||
&state_machine_, transition_label, publish_update) != RCL_RET_OK)
|
||||
{
|
||||
RCUTILS_LOG_ERROR("Failed to finish transition %u. Current state is now: %s",
|
||||
transition_id, state_machine_.current_state->label);
|
||||
RCUTILS_LOG_ERROR(
|
||||
"Failed to finish transition %u. Current state is now: %s (%s)",
|
||||
transition_id, state_machine_.current_state->label, rcl_get_error_string().str);
|
||||
rcutils_reset_error();
|
||||
return RCL_RET_ERROR;
|
||||
}
|
||||
|
||||
@@ -404,7 +407,8 @@ public:
|
||||
if (rcl_lifecycle_trigger_transition_by_label(
|
||||
&state_machine_, error_cb_label, publish_update) != RCL_RET_OK)
|
||||
{
|
||||
RCUTILS_LOG_ERROR("Failed to call cleanup on error state");
|
||||
RCUTILS_LOG_ERROR("Failed to call cleanup on error state: %s", rcl_get_error_string().str);
|
||||
rcutils_reset_error();
|
||||
return RCL_RET_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -420,19 +424,14 @@ public:
|
||||
// in case no callback was attached, we forward directly
|
||||
auto cb_success = node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
|
||||
|
||||
auto it = cb_map_.find(cb_id);
|
||||
auto it = cb_map_.find(static_cast<uint8_t>(cb_id));
|
||||
if (it != cb_map_.end()) {
|
||||
auto callback = it->second;
|
||||
try {
|
||||
cb_success = callback(State(previous_state));
|
||||
} catch (const std::exception &) {
|
||||
// TODO(karsten1987): Windows CI doesn't let me print the msg here
|
||||
// the todo is to forward the exception to the on_error callback
|
||||
// RCUTILS_LOG_ERROR("Caught exception in callback for transition %d\n",
|
||||
// it->first);
|
||||
// RCUTILS_LOG_ERROR("Original error msg: %s\n", e.what());
|
||||
// maybe directly go for error handling here
|
||||
// and pass exception along with it
|
||||
} catch (const std::exception & e) {
|
||||
RCUTILS_LOG_ERROR("Caught exception in callback for transition %d", it->first);
|
||||
RCUTILS_LOG_ERROR("Original error: %s", e.what());
|
||||
cb_success = node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
|
||||
}
|
||||
}
|
||||
@@ -451,7 +450,7 @@ public:
|
||||
auto transition =
|
||||
rcl_lifecycle_get_transition_by_label(state_machine_.current_state, transition_label);
|
||||
if (transition) {
|
||||
change_state(transition->id, cb_return_code);
|
||||
change_state(static_cast<uint8_t>(transition->id), cb_return_code);
|
||||
}
|
||||
return get_current_state();
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ State::id() const
|
||||
if (!state_handle_) {
|
||||
throw std::runtime_error("Error in state! Internal state_handle is NULL.");
|
||||
}
|
||||
return state_handle_->id;
|
||||
return static_cast<uint8_t>(state_handle_->id);
|
||||
}
|
||||
|
||||
std::string
|
||||
|
||||
@@ -213,7 +213,7 @@ Transition::id() const
|
||||
if (!transition_handle_) {
|
||||
throw std::runtime_error("internal transition_handle is null");
|
||||
}
|
||||
return transition_handle_->id;
|
||||
return static_cast<uint8_t>(transition_handle_->id);
|
||||
}
|
||||
|
||||
std::string
|
||||
|
||||
Reference in New Issue
Block a user