Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7bc05da5d1 | ||
|
|
4744fb6f50 | ||
|
|
d0e1e837b5 | ||
|
|
92d4f3e347 | ||
|
|
ea8daa3784 | ||
|
|
df994e435d | ||
|
|
93222cc2cd | ||
|
|
11b5f8db21 | ||
|
|
6167a575b3 | ||
|
|
dab9f5e0a3 | ||
|
|
3d69031d2a | ||
|
|
b953bdddf8 | ||
|
|
64e4c72791 | ||
|
|
f6056beaa0 | ||
|
|
37b589dc85 | ||
|
|
6dd3a0377b | ||
|
|
33dae5d679 | ||
|
|
f43a9198eb | ||
|
|
3c8e89d17c | ||
|
|
546ddf87fe | ||
|
|
dbded5c0d6 | ||
|
|
86a9d5882e | ||
|
|
8e6a6fb32d | ||
|
|
b3f57033a9 | ||
|
|
38581cc860 | ||
|
|
790e529ba3 | ||
|
|
5c688303b3 | ||
|
|
02802bcc38 | ||
|
|
491475f232 | ||
|
|
b8b64b4c08 | ||
|
|
ee67c211c5 | ||
|
|
82ddd44140 | ||
|
|
a1980678ae |
13
.github/workflows/mirror-rolling-to-master.yaml
vendored
Normal file
13
.github/workflows/mirror-rolling-to-master.yaml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
name: Mirror rolling to master
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ rolling ]
|
||||
|
||||
jobs:
|
||||
mirror-to-master:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: zofrex/mirror-branch@v1
|
||||
with:
|
||||
target-branch: master
|
||||
@@ -2,6 +2,46 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
17.0.0 (2022-09-13)
|
||||
-------------------
|
||||
* Make ParameterService and Sync/AsyncParameterClient accept rclcpp::QoS (`#1978 <https://github.com/ros2/rclcpp/issues/1978>`_)
|
||||
* support regex match for parameter client (`#1992 <https://github.com/ros2/rclcpp/issues/1992>`_)
|
||||
* operator+= and operator-= for Duration (`#1988 <https://github.com/ros2/rclcpp/issues/1988>`_)
|
||||
* Revert "Revert "Add a create_timer method to Node and `LifecycleNode` classes (`#1975 <https://github.com/ros2/rclcpp/issues/1975>`_)" (`#2009 <https://github.com/ros2/rclcpp/issues/2009>`_) (`#2010 <https://github.com/ros2/rclcpp/issues/2010>`_)
|
||||
* force compiler warning if callback handles not captured (`#2000 <https://github.com/ros2/rclcpp/issues/2000>`_)
|
||||
* Revert "Add a `create_timer` method to `Node` and `LifecycleNode` classes (`#1975 <https://github.com/ros2/rclcpp/issues/1975>`_)" (`#2009 <https://github.com/ros2/rclcpp/issues/2009>`_)
|
||||
* Add a `create_timer` method to `Node` and `LifecycleNode` classes (`#1975 <https://github.com/ros2/rclcpp/issues/1975>`_)
|
||||
* [docs] add note about callback lifetime for {on, post}_set_parameter_callback (`#1981 <https://github.com/ros2/rclcpp/issues/1981>`_)
|
||||
* fix memory leak (`#1994 <https://github.com/ros2/rclcpp/issues/1994>`_)
|
||||
* Support pre-set and post-set parameter callbacks in addition to on-set-parameter-callback. (`#1947 <https://github.com/ros2/rclcpp/issues/1947>`_)
|
||||
* Make create_service accept rclcpp::QoS (`#1969 <https://github.com/ros2/rclcpp/issues/1969>`_)
|
||||
* Make create_client accept rclcpp::QoS (`#1964 <https://github.com/ros2/rclcpp/issues/1964>`_)
|
||||
* Fix the documentation for rclcpp::ok to be accurate. (`#1965 <https://github.com/ros2/rclcpp/issues/1965>`_)
|
||||
* use regex for wildcard matching (`#1839 <https://github.com/ros2/rclcpp/issues/1839>`_)
|
||||
* Revert "Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (`#1821 <https://github.com/ros2/rclcpp/issues/1821>`_) (`#1874 <https://github.com/ros2/rclcpp/issues/1874>`_)" (`#1956 <https://github.com/ros2/rclcpp/issues/1956>`_)
|
||||
* Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (`#1821 <https://github.com/ros2/rclcpp/issues/1821>`_) (`#1874 <https://github.com/ros2/rclcpp/issues/1874>`_)
|
||||
* test adjustment for LoanedMessage. (`#1951 <https://github.com/ros2/rclcpp/issues/1951>`_)
|
||||
* fix virtual dispatch issues identified by clang-tidy (`#1816 <https://github.com/ros2/rclcpp/issues/1816>`_)
|
||||
* Remove unused on_parameters_set_callback\_ (`#1945 <https://github.com/ros2/rclcpp/issues/1945>`_)
|
||||
* Fix subscription.is_serialized() for callbacks with message info (`#1950 <https://github.com/ros2/rclcpp/issues/1950>`_)
|
||||
* wait for subscriptions on another thread. (`#1940 <https://github.com/ros2/rclcpp/issues/1940>`_)
|
||||
* Fix documentation of `RCLCPP\_[INFO,WARN,...]` (`#1943 <https://github.com/ros2/rclcpp/issues/1943>`_)
|
||||
* Always trigger guard condition waitset (`#1923 <https://github.com/ros2/rclcpp/issues/1923>`_)
|
||||
* Add statistics for handle_loaned_message (`#1927 <https://github.com/ros2/rclcpp/issues/1927>`_)
|
||||
* Drop wrong template specialization (`#1926 <https://github.com/ros2/rclcpp/issues/1926>`_)
|
||||
* Contributors: Alberto Soragna, Andrew Symington, Barry Xu, Brian, Chen Lihui, Chris Lalancette, Daniel Reuter, Deepanshu Bansal, Hubert Liberacki, Ivan Santiago Paunovic, Jochen Sprickerhof, Nikolai Morin, Shane Loretz, Tomoya Fujita, Tyler Weaver, William Woodall, schrodinbug
|
||||
|
||||
16.2.0 (2022-05-03)
|
||||
-------------------
|
||||
* Update get_parameter_from_event to follow the function description (`#1922 <https://github.com/ros2/rclcpp/issues/1922>`_)
|
||||
* Add 'best available' QoS enum values and methods (`#1920 <https://github.com/ros2/rclcpp/issues/1920>`_)
|
||||
* Contributors: Barry Xu, Jacob Perron
|
||||
|
||||
16.1.0 (2022-04-29)
|
||||
-------------------
|
||||
* use reinterpret_cast for function pointer conversion. (`#1919 <https://github.com/ros2/rclcpp/issues/1919>`_)
|
||||
* Contributors: Tomoya Fujita
|
||||
|
||||
16.0.1 (2022-04-13)
|
||||
-------------------
|
||||
* remove DEFINE_CONTENT_FILTER cmake option (`#1914 <https://github.com/ros2/rclcpp/issues/1914>`_)
|
||||
|
||||
BIN
rclcpp/doc/param_callback_design.png
Normal file
BIN
rclcpp/doc/param_callback_design.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 164 KiB |
29
rclcpp/doc/proposed_node_parameter_callbacks.md
Normal file
29
rclcpp/doc/proposed_node_parameter_callbacks.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Proposed node parameters callback Design
|
||||
|
||||
## Introduction:
|
||||
|
||||
The original requirement came in **gazebo_ros_pkgs** for setting individual wheel slip parameters based on global wheel slip value [link to original issue](https://github.com/ros-simulation/gazebo_ros_pkgs/pull/1365).
|
||||
|
||||
The main requirement is to set one or more parameters after another parameter is set successfully.
|
||||
|
||||
Additionally, it would be nice if users could be notified locally (via a callback) when parameters have been set successfully (i.e. post validation).
|
||||
|
||||
Related discussion can be found in [#609](https://github.com/ros2/rclcpp/issues/609) [#1789](https://github.com/ros2/rclcpp/pull/1789)
|
||||
|
||||
With the current parameters API, the `add_on_set_parameters_callback` is intended for validation of parameter values before they are set, it should **not** cause any side-effects.
|
||||
|
||||
There is also the `ParameterEventHandler` that publishes changes to node parameters on `/parameter_events` topic for external nodes to see. Though the node could subscribe to the `/parameter_events` topic to be notified of changes to its own parameters, it is less than ideal since there is a delay caused by waiting for an executor to process the callback.
|
||||
|
||||
We propose adding a `PostSetParametersCallbackHandle` for successful parameter set similar to `OnSetParametersCallbackHandle` for parameter validation. Also, we propose adding a `PreSetParametersCallbackHandle` useful for modifying list of parameters being set.
|
||||
|
||||
The validation callback is often abused to trigger side effects in the code, for instance updating class attributes even before a parameter has been set successfully. Instead of relying on the `/parameter_events` topic to be notified of parameter changes, users can register a callback with a new API, `add_post_set_parameters_callback`.
|
||||
|
||||
It is possible to use the proposed `add_post_set_parameters_callback` for setting additional parameters, but this might result in infinite recursion and does not allow those additional parameters to be set atomically with the original parameter(s) changed.
|
||||
To workaround these issues, we propose adding a "pre set" callback type that can be registered with `add_pre_set_parameters_callback`, which will be triggered before the validation callbacks and can be used to modify the parameter list.
|
||||
|
||||

|
||||
|
||||
## Alternatives
|
||||
|
||||
* Users could call `set_parameter` while processing a message from the `/parameter_events` topic, however, there is extra overhead in having to create subscription (as noted earlier).
|
||||
* Users could call `set_parameter` inside the "on set" parameters callback, however it is not well-defined how side-effects should handle cases where parameter validation fails.
|
||||
@@ -950,7 +950,13 @@ public:
|
||||
std::holds_alternative<UniquePtrSerializedMessageCallback>(callback_variant_) ||
|
||||
std::holds_alternative<SharedConstPtrSerializedMessageCallback>(callback_variant_) ||
|
||||
std::holds_alternative<ConstRefSharedConstPtrSerializedMessageCallback>(callback_variant_) ||
|
||||
std::holds_alternative<SharedPtrSerializedMessageCallback>(callback_variant_);
|
||||
std::holds_alternative<SharedPtrSerializedMessageCallback>(callback_variant_) ||
|
||||
std::holds_alternative<ConstRefSerializedMessageWithInfoCallback>(callback_variant_) ||
|
||||
std::holds_alternative<UniquePtrSerializedMessageWithInfoCallback>(callback_variant_) ||
|
||||
std::holds_alternative<SharedConstPtrSerializedMessageWithInfoCallback>(callback_variant_) ||
|
||||
std::holds_alternative<ConstRefSharedConstPtrSerializedMessageWithInfoCallback>(
|
||||
callback_variant_) ||
|
||||
std::holds_alternative<SharedPtrSerializedMessageWithInfoCallback>(callback_variant_);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -183,6 +183,11 @@ public:
|
||||
*
|
||||
* This function is thread-safe.
|
||||
*
|
||||
* Note that if you override this method, but leave shutdown to be called in
|
||||
* the destruction of this base class, it will not call the overridden
|
||||
* version from your base class.
|
||||
* So you need to ensure you call your class's shutdown() in its destructor.
|
||||
*
|
||||
* \param[in] reason the description of why shutdown happened
|
||||
* \return true if shutdown was successful, false if context was already shutdown
|
||||
* \throw various exceptions derived from rclcpp::exceptions::RCLError, if rcl_shutdown fails
|
||||
@@ -318,7 +323,6 @@ public:
|
||||
|
||||
/// Interrupt any blocking sleep_for calls, causing them to return immediately and return true.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
interrupt_all_sleep_for();
|
||||
|
||||
@@ -351,7 +355,6 @@ protected:
|
||||
// Called by constructor and destructor to clean up by finalizing the
|
||||
// shutdown rcl context and preparing for a new init cycle.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
clean_up();
|
||||
|
||||
|
||||
@@ -20,10 +20,40 @@
|
||||
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_services_interface.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rmw/rmw.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
/// Create a service client with a given type.
|
||||
/**
|
||||
* \param[in] node_base NodeBaseInterface implementation of the node on which
|
||||
* to create the client.
|
||||
* \param[in] node_graph NodeGraphInterface implementation of the node on which
|
||||
* to create the client.
|
||||
* \param[in] node_services NodeServicesInterface implementation of the node on
|
||||
* which to create the client.
|
||||
* \param[in] service_name The name on which the service is accessible.
|
||||
* \param[in] qos Quality of service profile for client.
|
||||
* \param[in] group Callback group to handle the reply to service calls.
|
||||
* \return Shared pointer to the created client.
|
||||
*/
|
||||
template<typename ServiceT>
|
||||
typename rclcpp::Client<ServiceT>::SharedPtr
|
||||
create_client(
|
||||
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
|
||||
std::shared_ptr<node_interfaces::NodeGraphInterface> node_graph,
|
||||
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
|
||||
const std::string & service_name,
|
||||
const rclcpp::QoS & qos = rclcpp::ServicesQoS(),
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
return create_client<ServiceT>(
|
||||
node_base, node_graph, node_services,
|
||||
service_name,
|
||||
qos.get_rmw_qos_profile(),
|
||||
group);
|
||||
}
|
||||
|
||||
/// Create a service client with a given type.
|
||||
/// \internal
|
||||
|
||||
@@ -26,6 +26,32 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
/// Create a service with a given type.
|
||||
/**
|
||||
* \param[in] node_base NodeBaseInterface implementation of the node on which
|
||||
* to create the service.
|
||||
* \param[in] node_services NodeServicesInterface implementation of the node on
|
||||
* which to create the service.
|
||||
* \param[in] service_name The name on which the service is accessible.
|
||||
* \param[in] callback The callback to call when the service gets a request.
|
||||
* \param[in] qos Quality of service profile for the service.
|
||||
* \param[in] group Callback group to handle the reply to service calls.
|
||||
* \return Shared pointer to the created service.
|
||||
*/
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
typename rclcpp::Service<ServiceT>::SharedPtr
|
||||
create_service(
|
||||
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
|
||||
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rclcpp::QoS & qos,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return create_service<ServiceT, CallbackT>(
|
||||
node_base, node_services, service_name,
|
||||
std::forward<CallbackT>(callback), qos.get_rmw_qos_profile(), group);
|
||||
}
|
||||
|
||||
/// Create a service with a given type.
|
||||
/// \internal
|
||||
|
||||
@@ -23,85 +23,29 @@
|
||||
|
||||
#include "rclcpp/duration.hpp"
|
||||
#include "rclcpp/node_interfaces/get_node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/get_node_clock_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/get_node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_clock_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(
|
||||
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
|
||||
std::shared_ptr<node_interfaces::NodeTimersInterface> node_timers,
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
namespace detail
|
||||
{
|
||||
auto timer = rclcpp::GenericTimer<CallbackT>::make_shared(
|
||||
clock,
|
||||
period.to_chrono<std::chrono::nanoseconds>(),
|
||||
std::forward<CallbackT>(callback),
|
||||
node_base->get_context());
|
||||
|
||||
node_timers->add_timer(timer, group);
|
||||
return timer;
|
||||
}
|
||||
|
||||
/// Create a timer with a given clock
|
||||
template<typename NodeT, typename CallbackT>
|
||||
typename rclcpp::TimerBase::SharedPtr
|
||||
create_timer(
|
||||
NodeT node,
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
return create_timer(
|
||||
rclcpp::node_interfaces::get_node_base_interface(node),
|
||||
rclcpp::node_interfaces::get_node_timers_interface(node),
|
||||
clock,
|
||||
period,
|
||||
std::forward<CallbackT>(callback),
|
||||
group);
|
||||
}
|
||||
|
||||
/// Convenience method to create a timer with node resources.
|
||||
/// Perform a safe cast to a timer period in nanoseconds
|
||||
/**
|
||||
*
|
||||
* \tparam DurationRepT
|
||||
* \tparam DurationT
|
||||
* \tparam CallbackT
|
||||
* \param period period to execute callback. This duration must be 0 <= period < nanoseconds::max()
|
||||
* \param callback callback to execute via the timer period
|
||||
* \param group
|
||||
* \param node_base
|
||||
* \param node_timers
|
||||
* \return
|
||||
* \throws std::invalid argument if either node_base or node_timers
|
||||
* are null, or period is negative or too large
|
||||
* \return period, expressed as chrono::duration::nanoseconds
|
||||
* \throws std::invalid_argument if period is negative or too large
|
||||
*/
|
||||
template<typename DurationRepT, typename DurationT, typename CallbackT>
|
||||
typename rclcpp::WallTimer<CallbackT>::SharedPtr
|
||||
create_wall_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group,
|
||||
node_interfaces::NodeBaseInterface * node_base,
|
||||
node_interfaces::NodeTimersInterface * node_timers)
|
||||
template<typename DurationRepT, typename DurationT>
|
||||
std::chrono::nanoseconds
|
||||
safe_cast_to_period_in_ns(std::chrono::duration<DurationRepT, DurationT> period)
|
||||
{
|
||||
if (node_base == nullptr) {
|
||||
throw std::invalid_argument{"input node_base cannot be null"};
|
||||
}
|
||||
|
||||
if (node_timers == nullptr) {
|
||||
throw std::invalid_argument{"input node_timers cannot be null"};
|
||||
}
|
||||
|
||||
if (period < std::chrono::duration<DurationRepT, DurationT>::zero()) {
|
||||
throw std::invalid_argument{"timer period cannot be negative"};
|
||||
}
|
||||
@@ -132,12 +76,135 @@ create_wall_timer(
|
||||
"Casting timer period to nanoseconds resulted in integer overflow."};
|
||||
}
|
||||
|
||||
return period_ns;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/// Create a timer with a given clock
|
||||
/// \internal
|
||||
template<typename CallbackT>
|
||||
typename rclcpp::TimerBase::SharedPtr
|
||||
create_timer(
|
||||
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
|
||||
std::shared_ptr<node_interfaces::NodeTimersInterface> node_timers,
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
return create_timer(
|
||||
clock,
|
||||
period.to_chrono<std::chrono::nanoseconds>(),
|
||||
std::forward<CallbackT>(callback),
|
||||
group,
|
||||
node_base.get(),
|
||||
node_timers.get());
|
||||
}
|
||||
|
||||
/// Create a timer with a given clock
|
||||
template<typename NodeT, typename CallbackT>
|
||||
typename rclcpp::TimerBase::SharedPtr
|
||||
create_timer(
|
||||
NodeT node,
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
return create_timer(
|
||||
clock,
|
||||
period.to_chrono<std::chrono::nanoseconds>(),
|
||||
std::forward<CallbackT>(callback),
|
||||
group,
|
||||
rclcpp::node_interfaces::get_node_base_interface(node).get(),
|
||||
rclcpp::node_interfaces::get_node_timers_interface(node).get());
|
||||
}
|
||||
|
||||
/// Convenience method to create a general timer with node resources.
|
||||
/**
|
||||
*
|
||||
* \tparam DurationRepT
|
||||
* \tparam DurationT
|
||||
* \tparam CallbackT
|
||||
* \param clock clock to be used
|
||||
* \param period period to execute callback. This duration must be 0 <= period < nanoseconds::max()
|
||||
* \param callback callback to execute via the timer period
|
||||
* \param group callback group
|
||||
* \param node_base node base interface
|
||||
* \param node_timers node timer interface
|
||||
* \return shared pointer to a generic timer
|
||||
* \throws std::invalid_argument if either clock, node_base or node_timers
|
||||
* are nullptr, or period is negative or too large
|
||||
*/
|
||||
template<typename DurationRepT, typename DurationT, typename CallbackT>
|
||||
typename rclcpp::GenericTimer<CallbackT>::SharedPtr
|
||||
create_timer(
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group,
|
||||
node_interfaces::NodeBaseInterface * node_base,
|
||||
node_interfaces::NodeTimersInterface * node_timers)
|
||||
{
|
||||
if (clock == nullptr) {
|
||||
throw std::invalid_argument{"clock cannot be null"};
|
||||
}
|
||||
if (node_base == nullptr) {
|
||||
throw std::invalid_argument{"input node_base cannot be null"};
|
||||
}
|
||||
if (node_timers == nullptr) {
|
||||
throw std::invalid_argument{"input node_timers cannot be null"};
|
||||
}
|
||||
|
||||
const std::chrono::nanoseconds period_ns = detail::safe_cast_to_period_in_ns(period);
|
||||
|
||||
// Add a new generic timer.
|
||||
auto timer = rclcpp::GenericTimer<CallbackT>::make_shared(
|
||||
std::move(clock), period_ns, std::move(callback), node_base->get_context());
|
||||
node_timers->add_timer(timer, group);
|
||||
return timer;
|
||||
}
|
||||
|
||||
/// Convenience method to create a wall timer with node resources.
|
||||
/**
|
||||
*
|
||||
* \tparam DurationRepT
|
||||
* \tparam DurationT
|
||||
* \tparam CallbackT
|
||||
* \param period period to execute callback. This duration must be 0 <= period < nanoseconds::max()
|
||||
* \param callback callback to execute via the timer period
|
||||
* \param group callback group
|
||||
* \param node_base node base interface
|
||||
* \param node_timers node timer interface
|
||||
* \return shared pointer to a wall timer
|
||||
* \throws std::invalid_argument if either node_base or node_timers
|
||||
* are null, or period is negative or too large
|
||||
*/
|
||||
template<typename DurationRepT, typename DurationT, typename CallbackT>
|
||||
typename rclcpp::WallTimer<CallbackT>::SharedPtr
|
||||
create_wall_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group,
|
||||
node_interfaces::NodeBaseInterface * node_base,
|
||||
node_interfaces::NodeTimersInterface * node_timers)
|
||||
{
|
||||
if (node_base == nullptr) {
|
||||
throw std::invalid_argument{"input node_base cannot be null"};
|
||||
}
|
||||
|
||||
if (node_timers == nullptr) {
|
||||
throw std::invalid_argument{"input node_timers cannot be null"};
|
||||
}
|
||||
|
||||
const std::chrono::nanoseconds period_ns = detail::safe_cast_to_period_in_ns(period);
|
||||
|
||||
// Add a new wall timer.
|
||||
auto timer = rclcpp::WallTimer<CallbackT>::make_shared(
|
||||
period_ns, std::move(callback), node_base->get_context());
|
||||
node_timers->add_timer(timer, group);
|
||||
return timer;
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CREATE_TIMER_HPP_
|
||||
|
||||
@@ -92,9 +92,13 @@ public:
|
||||
Duration
|
||||
operator+(const rclcpp::Duration & rhs) const;
|
||||
|
||||
Duration & operator+=(const rclcpp::Duration & rhs);
|
||||
|
||||
Duration
|
||||
operator-(const rclcpp::Duration & rhs) const;
|
||||
|
||||
Duration & operator-=(const rclcpp::Duration & rhs);
|
||||
|
||||
/// Get the maximum representable value.
|
||||
/**
|
||||
* \return the maximum representable value
|
||||
@@ -106,6 +110,9 @@ public:
|
||||
Duration
|
||||
operator*(double scale) const;
|
||||
|
||||
Duration &
|
||||
operator*=(double scale);
|
||||
|
||||
/// Get duration in nanosecods
|
||||
/**
|
||||
* \return the duration in nanoseconds as a rcl_duration_value_t.
|
||||
|
||||
@@ -128,6 +128,11 @@ public:
|
||||
* If start_if_not_started() was never called, this function still succeeds,
|
||||
* but start_if_not_started() still cannot be called after this function.
|
||||
*
|
||||
* Note that if you override this method, but leave shutdown to be called in
|
||||
* the destruction of this base class, it will not call the overridden
|
||||
* version from your base class.
|
||||
* So you need to ensure you call your class's shutdown() in its destructor.
|
||||
*
|
||||
* \throws rclcpp::execptions::RCLError from rcl_guard_condition_fini()
|
||||
* \throws rclcpp::execptions::RCLError from rcl_wait_set_fini()
|
||||
* \throws std::system_error anything std::mutex::lock() throws
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
const rcl_guard_condition_t &
|
||||
get_rcl_guard_condition() const;
|
||||
|
||||
/// Notify the wait set waiting on this condition, if any, that the condition had been met.
|
||||
/// Signal that the condition has been met, notifying both the wait set and listeners, if any.
|
||||
/**
|
||||
* This function is thread-safe, and may be called concurrently with waiting
|
||||
* on this guard condition in a wait set.
|
||||
@@ -107,6 +107,22 @@ public:
|
||||
void
|
||||
add_to_wait_set(rcl_wait_set_t * wait_set);
|
||||
|
||||
/// Set a callback to be called whenever the guard condition is triggered.
|
||||
/**
|
||||
* The callback receives a size_t which is the number of times the guard condition was triggered
|
||||
* since the last time this callback was called.
|
||||
* Normally this is 1, but can be > 1 if the guard condition was triggered before any
|
||||
* callback was set.
|
||||
*
|
||||
* Calling it again will clear any previously set callback.
|
||||
*
|
||||
* This function is thread-safe.
|
||||
*
|
||||
* If you want more information available in the callback, like the guard condition
|
||||
* or other information, you may use a lambda with captures or std::bind.
|
||||
*
|
||||
* \param[in] callback functor to be called when the guard condition is triggered
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
set_on_trigger_callback(std::function<void(size_t)> callback);
|
||||
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
)
|
||||
);
|
||||
|
||||
/// Create a timer.
|
||||
/// Create a wall timer that uses the wall clock to drive the callback.
|
||||
/**
|
||||
* \param[in] period Time interval between triggers of the callback.
|
||||
* \param[in] callback User-defined callback function.
|
||||
@@ -240,18 +240,47 @@ public:
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create a timer that uses the node clock to drive the callback.
|
||||
/**
|
||||
* \param[in] period Time interval between triggers of the callback.
|
||||
* \param[in] callback User-defined callback function.
|
||||
* \param[in] group Callback group to execute this timer's callback in.
|
||||
*/
|
||||
template<typename DurationRepT = int64_t, typename DurationT = std::milli, typename CallbackT>
|
||||
typename rclcpp::GenericTimer<CallbackT>::SharedPtr
|
||||
create_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// 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.
|
||||
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
|
||||
*/
|
||||
template<typename ServiceT>
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
typename rclcpp::Client<ServiceT>::SharedPtr
|
||||
create_client(
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a Client.
|
||||
/**
|
||||
* \param[in] service_name The name on which the service is accessible.
|
||||
* \param[in] qos Quality of service profile for client.
|
||||
* \param[in] group Callback group to handle the reply to service calls.
|
||||
* \return Shared pointer to the created client.
|
||||
*/
|
||||
template<typename ServiceT>
|
||||
typename rclcpp::Client<ServiceT>::SharedPtr
|
||||
create_client(
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
|
||||
const rclcpp::QoS & qos = rclcpp::ServicesQoS(),
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a Service.
|
||||
@@ -261,13 +290,31 @@ public:
|
||||
* \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.
|
||||
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
|
||||
*/
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
typename rclcpp::Service<ServiceT>::SharedPtr
|
||||
create_service(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a Service.
|
||||
/**
|
||||
* \param[in] service_name The topic to service on.
|
||||
* \param[in] callback User-defined callback function.
|
||||
* \param[in] qos Quality of service profile for the service.
|
||||
* \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(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
|
||||
const rclcpp::QoS & qos = rclcpp::ServicesQoS(),
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a GenericPublisher.
|
||||
@@ -336,11 +383,21 @@ public:
|
||||
*
|
||||
* If `ignore_override` is `true`, the parameter override will be ignored.
|
||||
*
|
||||
* This method, if successful, will result in any callback registered with
|
||||
* add_on_set_parameters_callback to be called.
|
||||
* This method will result in any callback registered with
|
||||
* `add_on_set_parameters_callback` and `add_post_set_parameters_callback`
|
||||
* to be called for the parameter being set.
|
||||
*
|
||||
* If a callback was registered previously with `add_on_set_parameters_callback`,
|
||||
* it will be called prior to setting the parameter for the node.
|
||||
* If that callback prevents the initial value for the parameter from being
|
||||
* set then rclcpp::exceptions::InvalidParameterValueException is thrown.
|
||||
*
|
||||
* If a callback was registered previously with `add_post_set_parameters_callback`,
|
||||
* it will be called after setting the parameter successfully for the node.
|
||||
*
|
||||
* This method will _not_ result in any callbacks registered with
|
||||
* `add_pre_set_parameters_callback` to be called.
|
||||
*
|
||||
* The returned reference will remain valid until the parameter is
|
||||
* undeclared.
|
||||
*
|
||||
@@ -457,11 +514,22 @@ public:
|
||||
* If `ignore_overrides` is `true`, all the overrides of the parameters declared
|
||||
* by the function call will be ignored.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* `add_on_set_parameters_callback` and `add_post_set_parameters_callback`
|
||||
* to be called once for each parameter.
|
||||
*
|
||||
* This method, if successful, will result in any callback registered with
|
||||
* add_on_set_parameters_callback to be called, once for each parameter.
|
||||
* `add_on_set_parameters_callback` to be called, once for each parameter.
|
||||
* If that callback prevents the initial value for any parameter from being
|
||||
* set then rclcpp::exceptions::InvalidParameterValueException is thrown.
|
||||
*
|
||||
* If a callback was registered previously with `add_post_set_parameters_callback`,
|
||||
* it will be called after setting the parameters successfully for the node,
|
||||
* once for each parameter.
|
||||
*
|
||||
* This method will _not_ result in any callbacks registered with
|
||||
* `add_pre_set_parameters_callback` to be called.
|
||||
*
|
||||
* \param[in] namespace_ The namespace in which to declare the parameters.
|
||||
* \param[in] parameters The parameters to set in the given namespace.
|
||||
* \param[in] ignore_overrides When `true`, the parameters overrides are ignored.
|
||||
@@ -499,8 +567,9 @@ public:
|
||||
|
||||
/// Undeclare a previously declared parameter.
|
||||
/**
|
||||
* This method will not cause a callback registered with
|
||||
* add_on_set_parameters_callback to be called.
|
||||
* This method will _not_ cause a callback registered with any of the
|
||||
* `add_pre_set_parameters_callback`, `add_on_set_parameters_callback` and
|
||||
* `add_post_set_parameters_callback` to be called.
|
||||
*
|
||||
* \param[in] name The name of the parameter to be undeclared.
|
||||
* \throws rclcpp::exceptions::ParameterNotDeclaredException if the parameter
|
||||
@@ -534,11 +603,24 @@ public:
|
||||
* Parameter overrides are ignored by set_parameter.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* add_on_set_parameters_callback to be called.
|
||||
* `add_pre_set_parameters_callback`, add_on_set_parameters_callback` and
|
||||
* `add_post_set_parameters_callback` to be called once for the parameter
|
||||
* being set.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* `add_on_set_parameters_callback` to be called.
|
||||
* If the callback prevents the parameter from being set, then it will be
|
||||
* reflected in the SetParametersResult that is returned, but no exception
|
||||
* will be thrown.
|
||||
*
|
||||
* If a callback was registered previously with `add_pre_set_parameters_callback`,
|
||||
* it will be called once prior to the validation of the parameter for the node.
|
||||
* If this callback makes modified parameter list empty, then it will be reflected
|
||||
* in the returned result; no exceptions will be raised in this case.
|
||||
*
|
||||
* If a callback was registered previously with `add_post_set_parameters_callback`,
|
||||
* it will be called once after setting the parameter successfully for the node.
|
||||
*
|
||||
* If the value type of the parameter is rclcpp::PARAMETER_NOT_SET, and the
|
||||
* existing parameter type is something else, then the parameter will be
|
||||
* implicitly undeclared.
|
||||
@@ -575,11 +657,25 @@ public:
|
||||
* corresponding SetParametersResult in the vector returned by this function.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* add_on_set_parameters_callback to be called, once for each parameter.
|
||||
* `add_pre_set_parameters_callback`, `add_on_set_parameters_callback` and
|
||||
* `add_post_set_parameters_callback` to be called once for each parameter.
|
||||
|
||||
* If a callback was registered previously with `add_pre_set_parameters_callback`,
|
||||
* it will be called prior to the validation of parameters for the node,
|
||||
* once for each parameter.
|
||||
* If this callback makes modified parameter list empty, then it will be reflected
|
||||
* in the returned result; no exceptions will be raised in this case.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* `add_on_set_parameters_callback` to be called, once for each parameter.
|
||||
* If the callback prevents the parameter from being set, then, as mentioned
|
||||
* before, it will be reflected in the corresponding SetParametersResult
|
||||
* that is returned, but no exception will be thrown.
|
||||
*
|
||||
* If a callback was registered previously with `add_post_set_parameters_callback`,
|
||||
* it will be called after setting the parameters successfully for the node,
|
||||
* once for each parameter.
|
||||
*
|
||||
* Like set_parameter() this method will implicitly undeclare parameters
|
||||
* with the type rclcpp::PARAMETER_NOT_SET.
|
||||
*
|
||||
@@ -606,11 +702,25 @@ public:
|
||||
* If the exception is thrown then none of the parameters will have been set.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* add_on_set_parameters_callback to be called, just one time.
|
||||
* `add_pre_set_parameters_callback`, `add_on_set_parameters_callback` and
|
||||
* `add_post_set_parameters_callback` to be called only 'once' for all parameters.
|
||||
*
|
||||
* If a callback was registered previously with `add_pre_set_parameters_callback`,
|
||||
* it will be called prior to the validation of node parameters, just one time
|
||||
* for all parameters.
|
||||
* If this callback makes modified parameter list empty, then it will be reflected
|
||||
* in the returned result; no exceptions will be raised in this case.
|
||||
*
|
||||
* This method will result in any callback registered with
|
||||
* 'add_on_set_parameters_callback' to be called, just one time.
|
||||
* If the callback prevents the parameters from being set, then it will be
|
||||
* reflected in the SetParametersResult which is returned, but no exception
|
||||
* will be thrown.
|
||||
*
|
||||
* If a callback was registered previously with `add_post_set_parameters_callback`,
|
||||
* it will be called after setting the node parameters successfully, just one time
|
||||
* for all parameters.
|
||||
*
|
||||
* If you pass multiple rclcpp::Parameter instances with the same name, then
|
||||
* only the last one in the vector (forward iteration) will be set.
|
||||
*
|
||||
@@ -859,12 +969,85 @@ public:
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const;
|
||||
|
||||
using PreSetParametersCallbackHandle =
|
||||
rclcpp::node_interfaces::PreSetParametersCallbackHandle;
|
||||
using PreSetParametersCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::PreSetParametersCallbackType;
|
||||
|
||||
using OnSetParametersCallbackHandle =
|
||||
rclcpp::node_interfaces::OnSetParametersCallbackHandle;
|
||||
using OnParametersSetCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;
|
||||
using OnSetParametersCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::OnSetParametersCallbackType;
|
||||
using OnParametersSetCallbackType [[deprecated("use OnSetParametersCallbackType instead")]] =
|
||||
OnSetParametersCallbackType;
|
||||
|
||||
/// Add a callback for when parameters are being set.
|
||||
using PostSetParametersCallbackHandle =
|
||||
rclcpp::node_interfaces::PostSetParametersCallbackHandle;
|
||||
using PostSetParametersCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::PostSetParametersCallbackType;
|
||||
|
||||
/// Add a callback that gets triggered before parameters are validated.
|
||||
/**
|
||||
* This callback can be used to modify the original list of parameters being
|
||||
* set by the user.
|
||||
*
|
||||
* The modified list of parameters is then forwarded to the "on set parameter"
|
||||
* callback for validation.
|
||||
*
|
||||
* The callback is called whenever any of the `set_parameter*` methods are called
|
||||
* or when a set parameter service request is received.
|
||||
*
|
||||
* The callback takes a reference to the vector of parameters to be set.
|
||||
*
|
||||
* The vector of parameters may be modified by the callback.
|
||||
*
|
||||
* One of the use case of "pre set callback" can be updating additional parameters
|
||||
* conditioned on changes to a parameter.
|
||||
*
|
||||
* Users should retain a copy of the returned shared pointer, as the callback
|
||||
* is valid only as long as the smart pointer is alive.
|
||||
*
|
||||
* For an example callback:
|
||||
*
|
||||
*```cpp
|
||||
* void
|
||||
* preSetParameterCallback(std::vector<rclcpp::Parameter> & parameters)
|
||||
* {
|
||||
* for (auto & param : parameters) {
|
||||
* if (param.get_name() == "param1") {
|
||||
* parameters.push_back(rclcpp::Parameter("param2", 4.0));
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* The above callback appends 'param2' to the list of parameters to be set if
|
||||
* 'param1' is being set by the user.
|
||||
*
|
||||
* All parameters in the vector will be set atomically.
|
||||
*
|
||||
* Note that the callback is only called while setting parameters with `set_parameter`,
|
||||
* `set_parameters`, `set_parameters_atomically`, or externally with a parameters service.
|
||||
*
|
||||
* The callback is not called when parameters are declared with `declare_parameter`
|
||||
* or `declare_parameters`.
|
||||
*
|
||||
* The callback is not called when parameters are undeclared with `undeclare_parameter`.
|
||||
*
|
||||
* An empty modified parameter list from the callback will result in "set_parameter*"
|
||||
* returning an unsuccessful result.
|
||||
*
|
||||
* The `remove_pre_set_parameters_callback` can be used to deregister the callback.
|
||||
*
|
||||
* \param callback The callback to register.
|
||||
* \returns A shared pointer. The callback is valid as long as the smart pointer is alive.
|
||||
* \throws std::bad_alloc if the allocation of the PreSetParametersCallbackHandle fails.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
PreSetParametersCallbackHandle::SharedPtr
|
||||
add_pre_set_parameters_callback(PreSetParametersCallbackType callback);
|
||||
|
||||
/// Add a callback to validate parameters before they are set.
|
||||
/**
|
||||
* The callback signature is designed to allow handling of any of the above
|
||||
* `set_parameter*` or `declare_parameter*` methods, and so it takes a const
|
||||
@@ -872,6 +1055,9 @@ public:
|
||||
* rcl_interfaces::msg::SetParametersResult to indicate whether or not the
|
||||
* parameter should be set or not, and if not why.
|
||||
*
|
||||
* Users should retain a copy of the returned shared pointer, as the callback
|
||||
* is valid only as long as the smart pointer is alive.
|
||||
*
|
||||
* For an example callback:
|
||||
*
|
||||
* ```cpp
|
||||
@@ -903,6 +1089,8 @@ public:
|
||||
* this callback, so when checking a new value against the existing one, you
|
||||
* must account for the case where the parameter is not yet set.
|
||||
*
|
||||
* The callback is not called when parameters are undeclared with `undeclare_parameter`.
|
||||
*
|
||||
* Some constraints like read_only are enforced before the callback is called.
|
||||
*
|
||||
* The callback may introspect other already set parameters (by calling any
|
||||
@@ -931,7 +1119,80 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
OnSetParametersCallbackHandle::SharedPtr
|
||||
add_on_set_parameters_callback(OnParametersSetCallbackType callback);
|
||||
add_on_set_parameters_callback(OnSetParametersCallbackType callback);
|
||||
|
||||
/// Add a callback that gets triggered after parameters are set successfully.
|
||||
/**
|
||||
* The callback is called when any of the `set_parameter*` or `declare_parameter*`
|
||||
* methods are successful.
|
||||
*
|
||||
* Users should retain a copy of the returned shared pointer, as the callback
|
||||
* is valid only as long as the smart pointer is alive.
|
||||
*
|
||||
* The callback takes a reference to a const vector of parameters that have been
|
||||
* set successfully.
|
||||
*
|
||||
* The post callback can be valuable as a place to cause side-effects based on
|
||||
* parameter changes.
|
||||
* For instance updating internally tracked class attributes once parameters
|
||||
* have been changed successfully.
|
||||
*
|
||||
* For an example callback:
|
||||
*
|
||||
* ```cpp
|
||||
* void
|
||||
* postSetParameterCallback(const std::vector<rclcpp::Parameter> & parameters)
|
||||
* {
|
||||
* for(const auto & param:parameters) {
|
||||
* // the internal class member can be changed after
|
||||
* // successful change to param1 or param2
|
||||
* if(param.get_name() == "param1") {
|
||||
* internal_tracked_class_parameter_1_ = param.get_value<double>();
|
||||
* }
|
||||
* else if(param.get_name() == "param2") {
|
||||
* internal_tracked_class_parameter_2_ = param.get_value<double>();
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The above callback takes a const reference to list of parameters that have been
|
||||
* set successfully and as a result of this updates the internally tracked class attributes
|
||||
* `internal_tracked_class_parameter_1_` and `internal_tracked_class_parameter_2_`
|
||||
* respectively.
|
||||
*
|
||||
* This callback should not modify parameters.
|
||||
*
|
||||
* The callback is called when parameters are declared with `declare_parameter`
|
||||
* or `declare_parameters`. See `declare_parameter` or `declare_parameters` above.
|
||||
*
|
||||
* The callback is not called when parameters are undeclared with `undeclare_parameter`.
|
||||
*
|
||||
* If you want to make changes to parameters based on changes to another, use
|
||||
* `add_pre_set_parameters_callback`.
|
||||
*
|
||||
* The `remove_post_set_parameters_callback` can be used to deregister the callback.
|
||||
*
|
||||
* \param callback The callback to register.
|
||||
* \returns A shared pointer. The callback is valid as long as the smart pointer is alive.
|
||||
* \throws std::bad_alloc if the allocation of the OnSetParametersCallbackHandle fails.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
PostSetParametersCallbackHandle::SharedPtr
|
||||
add_post_set_parameters_callback(PostSetParametersCallbackType callback);
|
||||
|
||||
/// Remove a callback registered with `add_pre_set_parameters_callback`.
|
||||
/**
|
||||
* Delete a handler returned by `add_pre_set_parameters_callback`.
|
||||
*
|
||||
* \param handler The callback handler to remove.
|
||||
* \throws std::runtime_error if the handler was not created with `add_pre_set_parameters_callback`,
|
||||
* or if it has been removed before.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_pre_set_parameters_callback(const PreSetParametersCallbackHandle * const handler);
|
||||
|
||||
/// Remove a callback registered with `add_on_set_parameters_callback`.
|
||||
/**
|
||||
@@ -960,6 +1221,18 @@ public:
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler);
|
||||
|
||||
/// Remove a callback registered with `add_post_set_parameters_callback`.
|
||||
/**
|
||||
* Delete a handler returned by `add_post_set_parameters_callback`.
|
||||
*
|
||||
* \param handler The callback handler to remove.
|
||||
* \throws std::runtime_error if the handler was not created with `add_post_set_parameters_callback`,
|
||||
* or if it has been removed before.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_post_set_parameters_callback(const PostSetParametersCallbackHandle * const handler);
|
||||
|
||||
/// Get the fully-qualified names of all available nodes.
|
||||
/**
|
||||
* The fully-qualified name includes the local namespace and name of the node.
|
||||
|
||||
@@ -120,6 +120,38 @@ Node::create_wall_timer(
|
||||
this->node_timers_.get());
|
||||
}
|
||||
|
||||
template<typename DurationRepT, typename DurationT, typename CallbackT>
|
||||
typename rclcpp::GenericTimer<CallbackT>::SharedPtr
|
||||
Node::create_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return rclcpp::create_timer(
|
||||
this->get_clock(),
|
||||
period,
|
||||
std::move(callback),
|
||||
group,
|
||||
this->node_base_.get(),
|
||||
this->node_timers_.get());
|
||||
}
|
||||
|
||||
template<typename ServiceT>
|
||||
typename Client<ServiceT>::SharedPtr
|
||||
Node::create_client(
|
||||
const std::string & service_name,
|
||||
const rclcpp::QoS & qos,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return rclcpp::create_client<ServiceT>(
|
||||
node_base_,
|
||||
node_graph_,
|
||||
node_services_,
|
||||
extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
|
||||
qos,
|
||||
group);
|
||||
}
|
||||
|
||||
template<typename ServiceT>
|
||||
typename Client<ServiceT>::SharedPtr
|
||||
Node::create_client(
|
||||
@@ -136,6 +168,23 @@ Node::create_client(
|
||||
group);
|
||||
}
|
||||
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
typename rclcpp::Service<ServiceT>::SharedPtr
|
||||
Node::create_service(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rclcpp::QoS & qos,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return rclcpp::create_service<ServiceT, CallbackT>(
|
||||
node_base_,
|
||||
node_services_,
|
||||
extend_name_with_sub_namespace(service_name, this->get_sub_namespace()),
|
||||
std::forward<CallbackT>(callback),
|
||||
qos,
|
||||
group);
|
||||
}
|
||||
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
typename rclcpp::Service<ServiceT>::SharedPtr
|
||||
Node::create_service(
|
||||
|
||||
@@ -39,6 +39,13 @@ class NodeBase : public NodeBaseInterface, public std::enable_shared_from_this<N
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeBase)
|
||||
|
||||
/// Constructor.
|
||||
/**
|
||||
* If nullptr (default) is given for the default_callback_group, one will
|
||||
* be created by the constructor using the create_callback_group() method,
|
||||
* but virtual dispatch will not occur so overrides of that method will not
|
||||
* be used.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
NodeBase(
|
||||
const std::string & node_name,
|
||||
@@ -46,7 +53,8 @@ public:
|
||||
rclcpp::Context::SharedPtr context,
|
||||
const rcl_node_options_t & rcl_node_options,
|
||||
bool use_intra_process_default,
|
||||
bool enable_topic_statistics_default);
|
||||
bool enable_topic_statistics_default,
|
||||
rclcpp::CallbackGroup::SharedPtr default_callback_group = nullptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
|
||||
@@ -37,14 +37,18 @@ public:
|
||||
~NodeLoggingInterface() = default;
|
||||
|
||||
/// Return the logger of the node.
|
||||
/** \return The logger of the node. */
|
||||
/**
|
||||
* \return The logger of the node.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Logger
|
||||
get_logger() const = 0;
|
||||
|
||||
/// Return the logger name associated with the node.
|
||||
/** \return The logger name associated with the node. */
|
||||
/**
|
||||
* \return The logger name associated with the node.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const char *
|
||||
|
||||
@@ -84,6 +84,16 @@ class NodeParameters : public NodeParametersInterface
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeParameters)
|
||||
|
||||
/// Constructor.
|
||||
/**
|
||||
* If using automatically_declare_parameters_from_overrides, overrides of
|
||||
* get_parameter_overrides(), has_parameter(), declare_parameter() will not
|
||||
* be respected.
|
||||
* If this is an issue, pass false for
|
||||
* automatically_declare_parameters_from_overrides and invoke
|
||||
* perform_automatically_declare_parameters_from_overrides() manually after
|
||||
* construction.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
NodeParameters(
|
||||
const node_interfaces::NodeBaseInterface::SharedPtr node_base,
|
||||
@@ -171,20 +181,48 @@ public:
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
PreSetParametersCallbackHandle::SharedPtr
|
||||
add_pre_set_parameters_callback(PreSetParametersCallbackType callback) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
OnSetParametersCallbackHandle::SharedPtr
|
||||
add_on_set_parameters_callback(OnParametersSetCallbackType callback) override;
|
||||
add_on_set_parameters_callback(OnSetParametersCallbackType callback) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
PostSetParametersCallbackHandle::SharedPtr
|
||||
add_post_set_parameters_callback(PostSetParametersCallbackType callback) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_post_set_parameters_callback(const PostSetParametersCallbackHandle * const handler)
|
||||
override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
remove_pre_set_parameters_callback(const PreSetParametersCallbackHandle * const handler) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::map<std::string, rclcpp::ParameterValue> &
|
||||
get_parameter_overrides() const override;
|
||||
|
||||
using CallbacksContainerType = std::list<OnSetParametersCallbackHandle::WeakPtr>;
|
||||
using PreSetCallbacksHandleContainer = std::list<PreSetParametersCallbackHandle::WeakPtr>;
|
||||
using OnSetCallbacksHandleContainer = std::list<OnSetParametersCallbackHandle::WeakPtr>;
|
||||
using PostSetCallbacksHandleContainer = std::list<PostSetParametersCallbackHandle::WeakPtr>;
|
||||
using CallbacksContainerType [[deprecated("use OnSetCallbacksHandleContainer instead")]] =
|
||||
OnSetCallbacksHandleContainer;
|
||||
|
||||
protected:
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
perform_automatically_declare_parameters_from_overrides();
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeParameters)
|
||||
@@ -196,9 +234,11 @@ private:
|
||||
// declare_parameter, etc). In those cases, this will be set to false.
|
||||
bool parameter_modification_enabled_{true};
|
||||
|
||||
OnParametersSetCallbackType on_parameters_set_callback_ = nullptr;
|
||||
PreSetCallbacksHandleContainer pre_set_parameters_callback_container_;
|
||||
|
||||
CallbacksContainerType on_parameters_set_callback_container_;
|
||||
OnSetCallbacksHandleContainer on_set_parameters_callback_container_;
|
||||
|
||||
PostSetCallbacksHandleContainer post_set_parameters_callback_container_;
|
||||
|
||||
std::map<std::string, ParameterInfo> parameters_;
|
||||
|
||||
|
||||
@@ -33,16 +33,38 @@ namespace rclcpp
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
struct PreSetParametersCallbackHandle
|
||||
{
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(PreSetParametersCallbackHandle)
|
||||
|
||||
using PreSetParametersCallbackType =
|
||||
std::function<void (std::vector<rclcpp::Parameter> &)>;
|
||||
|
||||
PreSetParametersCallbackType callback;
|
||||
};
|
||||
|
||||
struct OnSetParametersCallbackHandle
|
||||
{
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(OnSetParametersCallbackHandle)
|
||||
|
||||
using OnParametersSetCallbackType =
|
||||
using OnSetParametersCallbackType =
|
||||
std::function<
|
||||
rcl_interfaces::msg::SetParametersResult(
|
||||
const std::vector<rclcpp::Parameter> &)>;
|
||||
using OnParametersSetCallbackType [[deprecated("use OnSetParametersCallbackType instead")]] =
|
||||
OnSetParametersCallbackType;
|
||||
|
||||
OnParametersSetCallbackType callback;
|
||||
OnSetParametersCallbackType callback;
|
||||
};
|
||||
|
||||
struct PostSetParametersCallbackHandle
|
||||
{
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(PostSetParametersCallbackHandle)
|
||||
|
||||
using PostSetParametersCallbackType =
|
||||
std::function<void (const std::vector<rclcpp::Parameter> &)>;
|
||||
|
||||
PostSetParametersCallbackType callback;
|
||||
};
|
||||
|
||||
/// Pure virtual interface class for the NodeParameters part of the Node API.
|
||||
@@ -185,16 +207,46 @@ public:
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const = 0;
|
||||
|
||||
using OnParametersSetCallbackType = OnSetParametersCallbackHandle::OnParametersSetCallbackType;
|
||||
using OnSetParametersCallbackType = OnSetParametersCallbackHandle::OnSetParametersCallbackType;
|
||||
using PostSetParametersCallbackType =
|
||||
PostSetParametersCallbackHandle::PostSetParametersCallbackType;
|
||||
using PreSetParametersCallbackType = PreSetParametersCallbackHandle::PreSetParametersCallbackType;
|
||||
|
||||
/// Add a callback for when parameters are being set.
|
||||
/// Add a callback that gets triggered before parameters are validated.
|
||||
/**
|
||||
* \sa rclcpp::Node::add_pre_set_parameters_callback
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
PreSetParametersCallbackHandle::SharedPtr
|
||||
add_pre_set_parameters_callback(PreSetParametersCallbackType callback) = 0;
|
||||
|
||||
/// Add a callback to validate parameters before they are set.
|
||||
/**
|
||||
* \sa rclcpp::Node::add_on_set_parameters_callback
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
OnSetParametersCallbackHandle::SharedPtr
|
||||
add_on_set_parameters_callback(OnParametersSetCallbackType callback) = 0;
|
||||
add_on_set_parameters_callback(OnSetParametersCallbackType callback) = 0;
|
||||
|
||||
/// Add a callback that gets triggered after parameters are set successfully.
|
||||
/**
|
||||
* \sa rclcpp::Node::add_post_set_parameters_callback
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
PostSetParametersCallbackHandle::SharedPtr
|
||||
add_post_set_parameters_callback(PostSetParametersCallbackType callback) = 0;
|
||||
|
||||
/// Remove a callback registered with `add_pre_set_parameters_callback`.
|
||||
/**
|
||||
* \sa rclcpp::Node::remove_pre_set_parameters_callback
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
remove_pre_set_parameters_callback(const PreSetParametersCallbackHandle * const handler) = 0;
|
||||
|
||||
/// Remove a callback registered with `add_on_set_parameters_callback`.
|
||||
/**
|
||||
@@ -205,6 +257,15 @@ public:
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler) = 0;
|
||||
|
||||
/// Remove a callback registered with `add_post_set_parameters_callback`.
|
||||
/**
|
||||
* \sa rclcpp::Node::remove_post_set_parameters_callback
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
remove_post_set_parameters_callback(const PostSetParametersCallbackHandle * const handler) = 0;
|
||||
|
||||
/// Return the initial parameter values used by the NodeParameters to override default values.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/parameter_map.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rmw/rmw.h"
|
||||
@@ -51,6 +52,37 @@ 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 Name of the remote node
|
||||
* \param[in] qos_profile The rmw qos profile to use to subscribe
|
||||
* \param[in] group (optional) The async parameter client will be added to this callback group.
|
||||
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
|
||||
*/
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
RCLCPP_PUBLIC
|
||||
AsyncParametersClient(
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
|
||||
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
: AsyncParametersClient(
|
||||
node_base_interface,
|
||||
node_topics_interface,
|
||||
node_graph_interface,
|
||||
node_services_interface,
|
||||
remote_node_name,
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)),
|
||||
group)
|
||||
{}
|
||||
|
||||
/// Create an async parameters client.
|
||||
/**
|
||||
* \param[in] node_base_interface The node base interface of the corresponding node.
|
||||
@@ -58,7 +90,7 @@ public:
|
||||
* \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
|
||||
* \param[in] qos_profile (optional) The qos profile to use to subscribe
|
||||
* \param[in] group (optional) The async parameter client will be added to this callback group.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
@@ -68,21 +100,45 @@ public:
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
|
||||
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS(),
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
* \param[in] node The async paramters client will be added to this node.
|
||||
* \param[in] node The async parameters client will be added to this node.
|
||||
* \param[in] remote_node_name name of the remote node
|
||||
* \param[in] qos_profile The rmw qos profile to use to subscribe
|
||||
* \param[in] group (optional) The async parameter client will be added to this callback group.
|
||||
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
|
||||
*/
|
||||
template<typename NodeT>
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
AsyncParametersClient(
|
||||
const std::shared_ptr<NodeT> node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
: AsyncParametersClient(
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface(),
|
||||
remote_node_name,
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)),
|
||||
group)
|
||||
{}
|
||||
|
||||
/**
|
||||
* \param[in] node The async parameters 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
|
||||
* \param[in] qos_profile (optional) The qos profile to use to subscribe
|
||||
* \param[in] group (optional) The async parameter client will be added to this callback group.
|
||||
*/
|
||||
template<typename NodeT>
|
||||
explicit AsyncParametersClient(
|
||||
const std::shared_ptr<NodeT> node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
|
||||
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS(),
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
: AsyncParametersClient(
|
||||
node->get_node_base_interface(),
|
||||
@@ -96,16 +152,40 @@ public:
|
||||
|
||||
/// Constructor
|
||||
/**
|
||||
* \param[in] node The async paramters client will be added to this node.
|
||||
* \param[in] node The async parameters client will be added to this node.
|
||||
* \param[in] remote_node_name Name of the remote node
|
||||
* \param[in] qos_profile The rmw qos profile to use to subscribe
|
||||
* \param[in] group (optional) The async parameter client will be added to this callback group.
|
||||
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
|
||||
*/
|
||||
template<typename NodeT>
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
AsyncParametersClient(
|
||||
NodeT * node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
: AsyncParametersClient(
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface(),
|
||||
remote_node_name,
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)),
|
||||
group)
|
||||
{}
|
||||
|
||||
/**
|
||||
* \param[in] node The async parameters 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
|
||||
* \param[in] qos_profile (optional) The qos profile to use to subscribe
|
||||
* \param[in] group (optional) The async parameter client will be added to this callback group.
|
||||
*/
|
||||
template<typename NodeT>
|
||||
explicit AsyncParametersClient(
|
||||
NodeT * node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
|
||||
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS(),
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
: AsyncParametersClient(
|
||||
node->get_node_base_interface(),
|
||||
@@ -185,6 +265,9 @@ public:
|
||||
/**
|
||||
* This function filters the parameters to be set based on the node name.
|
||||
*
|
||||
* If two duplicate keys exist in node names belongs to one FQN, there is no guarantee
|
||||
* which one could be set.
|
||||
*
|
||||
* \param parameter_map named parameters to be loaded
|
||||
* \return the future of the set_parameter service used to load the parameters
|
||||
* \throw InvalidParametersException if there is no parameter to set
|
||||
@@ -208,9 +291,7 @@ public:
|
||||
typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
|
||||
on_parameter_event(
|
||||
CallbackT && callback,
|
||||
const rclcpp::QoS & qos = (
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events))
|
||||
),
|
||||
const rclcpp::QoS & qos = rclcpp::ParameterEventsQoS(),
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
))
|
||||
@@ -235,9 +316,7 @@ public:
|
||||
on_parameter_event(
|
||||
NodeT && node,
|
||||
CallbackT && callback,
|
||||
const rclcpp::QoS & qos = (
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events))
|
||||
),
|
||||
const rclcpp::QoS & qos = rclcpp::ParameterEventsQoS(),
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
))
|
||||
@@ -304,11 +383,24 @@ class SyncParametersClient
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(SyncParametersClient)
|
||||
|
||||
template<typename NodeT>
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
SyncParametersClient(
|
||||
std::shared_ptr<NodeT> node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: SyncParametersClient(
|
||||
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
|
||||
node,
|
||||
remote_node_name,
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)))
|
||||
{}
|
||||
|
||||
template<typename NodeT>
|
||||
explicit SyncParametersClient(
|
||||
std::shared_ptr<NodeT> node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters)
|
||||
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS())
|
||||
: SyncParametersClient(
|
||||
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
|
||||
node,
|
||||
@@ -316,12 +408,29 @@ public:
|
||||
qos_profile)
|
||||
{}
|
||||
|
||||
template<typename NodeT>
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
SyncParametersClient(
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
std::shared_ptr<NodeT> node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: SyncParametersClient(
|
||||
executor,
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface(),
|
||||
remote_node_name,
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)))
|
||||
{}
|
||||
|
||||
template<typename NodeT>
|
||||
SyncParametersClient(
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
std::shared_ptr<NodeT> node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters)
|
||||
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS())
|
||||
: SyncParametersClient(
|
||||
executor,
|
||||
node->get_node_base_interface(),
|
||||
@@ -332,11 +441,24 @@ public:
|
||||
qos_profile)
|
||||
{}
|
||||
|
||||
template<typename NodeT>
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
SyncParametersClient(
|
||||
NodeT * node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: SyncParametersClient(
|
||||
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
|
||||
node,
|
||||
remote_node_name,
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)))
|
||||
{}
|
||||
|
||||
template<typename NodeT>
|
||||
explicit SyncParametersClient(
|
||||
NodeT * node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters)
|
||||
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS())
|
||||
: SyncParametersClient(
|
||||
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
|
||||
node,
|
||||
@@ -344,12 +466,29 @@ public:
|
||||
qos_profile)
|
||||
{}
|
||||
|
||||
template<typename NodeT>
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
SyncParametersClient(
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
NodeT * node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: SyncParametersClient(
|
||||
executor,
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface(),
|
||||
remote_node_name,
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)))
|
||||
{}
|
||||
|
||||
template<typename NodeT>
|
||||
SyncParametersClient(
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
NodeT * node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters)
|
||||
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS())
|
||||
: SyncParametersClient(
|
||||
executor,
|
||||
node->get_node_base_interface(),
|
||||
@@ -360,6 +499,28 @@ public:
|
||||
qos_profile)
|
||||
{}
|
||||
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
RCLCPP_PUBLIC
|
||||
SyncParametersClient(
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
|
||||
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: executor_(executor), node_base_interface_(node_base_interface)
|
||||
{
|
||||
async_parameters_client_ =
|
||||
std::make_shared<AsyncParametersClient>(
|
||||
node_base_interface,
|
||||
node_topics_interface,
|
||||
node_graph_interface,
|
||||
node_services_interface,
|
||||
remote_node_name,
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)));
|
||||
}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
SyncParametersClient(
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
@@ -368,7 +529,7 @@ public:
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters)
|
||||
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS())
|
||||
: executor_(executor), node_base_interface_(node_base_interface)
|
||||
{
|
||||
async_parameters_client_ =
|
||||
|
||||
@@ -86,6 +86,9 @@ struct ParameterEventCallbackHandle
|
||||
* the ROS node supplied in the ParameterEventHandler constructor.
|
||||
* The callback, a lambda function in this case, simply prints out the value of the parameter.
|
||||
*
|
||||
* Note: the object returned from add_parameter_callback must be captured or the callback will
|
||||
* be immediately unregistered.
|
||||
*
|
||||
* You may also monitor for changes to parameters in other nodes by supplying the node
|
||||
* name to add_parameter_callback:
|
||||
*
|
||||
@@ -103,8 +106,8 @@ struct ParameterEventCallbackHandle
|
||||
* In this case, the callback will be invoked whenever "some_remote_param_name" changes
|
||||
* on remote node "some_remote_node_name".
|
||||
*
|
||||
* To remove a parameter callback, call remove_parameter_callback, passing the handle returned
|
||||
* from add_parameter_callback:
|
||||
* To remove a parameter callback, reset the callback handle smart pointer or call
|
||||
* remove_parameter_callback, passing the handle returned from add_parameter_callback:
|
||||
*
|
||||
* param_handler->remove_parameter_callback(handle2);
|
||||
*
|
||||
@@ -152,9 +155,12 @@ struct ParameterEventCallbackHandle
|
||||
* For both parameter callbacks and parameter event callbacks, when multiple callbacks are added,
|
||||
* the callbacks are invoked last-in, first-called order (LIFO).
|
||||
*
|
||||
* To remove a parameter event callback, use:
|
||||
* Note: the callback handle returned from add_parameter_event_callback must be captured or
|
||||
* the callback will immediately be unregistered.
|
||||
*
|
||||
* param_handler->remove_event_parameter_callback(handle);
|
||||
* To remove a parameter event callback, reset the callback smart pointer or use:
|
||||
*
|
||||
* param_handler->remove_event_parameter_callback(handle3);
|
||||
*/
|
||||
class ParameterEventHandler
|
||||
{
|
||||
@@ -189,10 +195,14 @@ public:
|
||||
/**
|
||||
* This function may be called multiple times to set multiple parameter event callbacks.
|
||||
*
|
||||
* Note: if the returned callback handle smart pointer is not captured, the callback is
|
||||
* immediatedly unregistered. A compiler warning should be generated to warn of this.
|
||||
*
|
||||
* \param[in] callback Function callback to be invoked on parameter updates.
|
||||
* \returns A handle used to refer to the callback.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
ParameterEventCallbackHandle::SharedPtr
|
||||
add_parameter_event_callback(
|
||||
ParameterEventCallbackType callback);
|
||||
@@ -212,12 +222,17 @@ public:
|
||||
/**
|
||||
* If a node_name is not provided, defaults to the current node.
|
||||
*
|
||||
* Note: if the returned callback handle smart pointer is not captured, the callback
|
||||
* is immediately unregistered. A compiler warning should be generated to warn
|
||||
* of this.
|
||||
*
|
||||
* \param[in] parameter_name Name of parameter to monitor.
|
||||
* \param[in] callback Function callback to be invoked upon parameter update.
|
||||
* \param[in] node_name Name of node which hosts the parameter.
|
||||
* \returns A handle used to refer to the callback.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
ParameterCallbackHandle::SharedPtr
|
||||
add_parameter_callback(
|
||||
const std::string & parameter_name,
|
||||
@@ -268,6 +283,7 @@ public:
|
||||
* \param[in] parameter_name Name of parameter.
|
||||
* \param[in] node_name Name of node which hosts the parameter.
|
||||
* \returns The resultant rclcpp::Parameter from the event.
|
||||
* \throws std::runtime_error if input node name doesn't match the node name in parameter event.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
static rclcpp::Parameter
|
||||
|
||||
@@ -35,11 +35,13 @@ using ParameterMap = std::unordered_map<std::string, std::vector<Parameter>>;
|
||||
|
||||
/// Convert parameters from rcl_yaml_param_parser into C++ class instances.
|
||||
/// \param[in] c_params C structures containing parameters for multiple nodes.
|
||||
/// \param[in] node_fqn a Fully Qualified Name of node, default value is nullptr.
|
||||
/// If it's not nullptr, return the relative node parameters belonging to this node_fqn.
|
||||
/// \returns a map where the keys are fully qualified node names and values a list of parameters.
|
||||
/// \throws InvalidParametersException if the `rcl_params_t` is inconsistent or invalid.
|
||||
RCLCPP_PUBLIC
|
||||
ParameterMap
|
||||
parameter_map_from(const rcl_params_t * const c_params);
|
||||
parameter_map_from(const rcl_params_t * const c_params, const char * node_fqn = nullptr);
|
||||
|
||||
/// Convert parameter value from rcl_yaml_param_parser into a C++ class instance.
|
||||
/// \param[in] c_value C structure containing a value of a parameter.
|
||||
@@ -51,11 +53,20 @@ parameter_value_from(const rcl_variant_t * const c_value);
|
||||
|
||||
/// Get the ParameterMap from a yaml file.
|
||||
/// \param[in] yaml_filename full name of the yaml file.
|
||||
/// \param[in] node_fqn a Fully Qualified Name of node, default value is nullptr.
|
||||
/// \returns an instance of a parameter map
|
||||
/// \throws from rcl error of rcl_parse_yaml_file()
|
||||
RCLCPP_PUBLIC
|
||||
ParameterMap
|
||||
parameter_map_from_yaml_file(const std::string & yaml_filename);
|
||||
parameter_map_from_yaml_file(const std::string & yaml_filename, const char * node_fqn = nullptr);
|
||||
|
||||
/// Get the Parameters from ParameterMap.
|
||||
/// \param[in] parameter_map a parameter map.
|
||||
/// \param[in] node_fqn a Fully Qualified Name of node, default value is nullptr.
|
||||
/// \returns a list of a parameter
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<Parameter>
|
||||
parameters_from_map(const ParameterMap & parameter_map, const char * node_fqn = nullptr);
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rmw/rmw.h"
|
||||
|
||||
@@ -39,12 +40,26 @@ class ParameterService
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(ParameterService)
|
||||
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
RCLCPP_PUBLIC
|
||||
explicit ParameterService(
|
||||
ParameterService(
|
||||
const std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
|
||||
const std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
|
||||
rclcpp::node_interfaces::NodeParametersInterface * node_params,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: ParameterService(
|
||||
node_base,
|
||||
node_services,
|
||||
node_params,
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile)))
|
||||
{}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
ParameterService(
|
||||
const std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
|
||||
const std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
|
||||
rclcpp::node_interfaces::NodeParametersInterface * node_params,
|
||||
const rclcpp::QoS & qos_profile = rclcpp::ParametersQoS());
|
||||
|
||||
private:
|
||||
rclcpp::Service<rcl_interfaces::srv::GetParameters>::SharedPtr get_parameters_service_;
|
||||
|
||||
@@ -72,7 +72,7 @@ struct PublisherOptionsWithAllocator : public PublisherOptionsBase
|
||||
/// Optional custom allocator.
|
||||
std::shared_ptr<Allocator> allocator = nullptr;
|
||||
|
||||
PublisherOptionsWithAllocator<Allocator>() {}
|
||||
PublisherOptionsWithAllocator() {}
|
||||
|
||||
/// Constructor using base class as input.
|
||||
explicit PublisherOptionsWithAllocator(const PublisherOptionsBase & publisher_options_base)
|
||||
|
||||
@@ -44,6 +44,7 @@ enum class ReliabilityPolicy
|
||||
BestEffort = RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT,
|
||||
Reliable = RMW_QOS_POLICY_RELIABILITY_RELIABLE,
|
||||
SystemDefault = RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT,
|
||||
BestAvailable = RMW_QOS_POLICY_RELIABILITY_BEST_AVAILABLE,
|
||||
Unknown = RMW_QOS_POLICY_RELIABILITY_UNKNOWN,
|
||||
};
|
||||
|
||||
@@ -52,6 +53,7 @@ enum class DurabilityPolicy
|
||||
Volatile = RMW_QOS_POLICY_DURABILITY_VOLATILE,
|
||||
TransientLocal = RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL,
|
||||
SystemDefault = RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT,
|
||||
BestAvailable = RMW_QOS_POLICY_DURABILITY_BEST_AVAILABLE,
|
||||
Unknown = RMW_QOS_POLICY_DURABILITY_UNKNOWN,
|
||||
};
|
||||
|
||||
@@ -60,6 +62,7 @@ enum class LivelinessPolicy
|
||||
Automatic = RMW_QOS_POLICY_LIVELINESS_AUTOMATIC,
|
||||
ManualByTopic = RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC,
|
||||
SystemDefault = RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT,
|
||||
BestAvailable = RMW_QOS_POLICY_LIVELINESS_BEST_AVAILABLE,
|
||||
Unknown = RMW_QOS_POLICY_LIVELINESS_UNKNOWN,
|
||||
};
|
||||
|
||||
@@ -180,6 +183,10 @@ public:
|
||||
QoS &
|
||||
best_effort();
|
||||
|
||||
/// Set the reliability setting to best available.
|
||||
QoS &
|
||||
reliability_best_available();
|
||||
|
||||
/// Set the durability setting.
|
||||
QoS &
|
||||
durability(rmw_qos_durability_policy_t durability);
|
||||
@@ -199,6 +206,10 @@ public:
|
||||
QoS &
|
||||
transient_local();
|
||||
|
||||
/// Set the durability setting to best available.
|
||||
QoS &
|
||||
durability_best_available();
|
||||
|
||||
/// Set the deadline setting.
|
||||
QoS &
|
||||
deadline(rmw_time_t deadline);
|
||||
@@ -488,6 +499,36 @@ public:
|
||||
));
|
||||
};
|
||||
|
||||
/**
|
||||
* Best available QoS class
|
||||
*
|
||||
* Match majority of endpoints currently available while maintaining the highest level of service.
|
||||
* Policies are chosen at the time of creating a subscription or publisher.
|
||||
* The middleware is not expected to update policies after creating a subscription or publisher,
|
||||
* even if one or more policies are incompatible with newly discovered endpoints.
|
||||
* Therefore, this profile should be used with care since non-deterministic behavior can occur due
|
||||
* to races with discovery.
|
||||
*
|
||||
* - History: Keep last,
|
||||
* - Depth: 10,
|
||||
* - Reliability: Best available,
|
||||
* - Durability: Best available,
|
||||
* - Deadline: Best available,
|
||||
* - Lifespan: Default,
|
||||
* - Liveliness: Best available,
|
||||
* - Liveliness lease duration: Best available,
|
||||
* - avoid ros namespace conventions: false
|
||||
*/
|
||||
class RCLCPP_PUBLIC BestAvailableQoS : public QoS
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
BestAvailableQoS(
|
||||
const QoSInitialization & qos_initialization = (
|
||||
QoSInitialization::from_rmw(rmw_qos_profile_best_available)
|
||||
));
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__QOS_HPP_
|
||||
|
||||
@@ -363,11 +363,31 @@ public:
|
||||
void * loaned_message,
|
||||
const rclcpp::MessageInfo & message_info) override
|
||||
{
|
||||
if (matches_any_intra_process_publishers(&message_info.get_rmw_message_info().publisher_gid)) {
|
||||
// In this case, the message will be delivered via intra process and
|
||||
// we should ignore this copy of the message.
|
||||
return;
|
||||
}
|
||||
|
||||
auto typed_message = static_cast<ROSMessageType *>(loaned_message);
|
||||
// message is loaned, so we have to make sure that the deleter does not deallocate the message
|
||||
auto sptr = std::shared_ptr<ROSMessageType>(
|
||||
typed_message, [](ROSMessageType * msg) {(void) msg;});
|
||||
|
||||
std::chrono::time_point<std::chrono::system_clock> now;
|
||||
if (subscription_topic_statistics_) {
|
||||
// get current time before executing callback to
|
||||
// exclude callback duration from topic statistics result.
|
||||
now = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
any_callback_.dispatch(sptr, message_info);
|
||||
|
||||
if (subscription_topic_statistics_) {
|
||||
const auto nanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(now);
|
||||
const auto time = rclcpp::Time(nanos.time_since_epoch().count());
|
||||
subscription_topic_statistics_->handle_message(*typed_message, time);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the borrowed message.
|
||||
|
||||
@@ -97,7 +97,7 @@ struct SubscriptionOptionsWithAllocator : public SubscriptionOptionsBase
|
||||
/// Optional custom allocator.
|
||||
std::shared_ptr<Allocator> allocator = nullptr;
|
||||
|
||||
SubscriptionOptionsWithAllocator<Allocator>() {}
|
||||
SubscriptionOptionsWithAllocator() {}
|
||||
|
||||
/// Constructor using base class as input.
|
||||
explicit SubscriptionOptionsWithAllocator(
|
||||
|
||||
@@ -189,10 +189,10 @@ public:
|
||||
TRACEPOINT(
|
||||
rclcpp_timer_callback_added,
|
||||
static_cast<const void *>(get_timer_handle().get()),
|
||||
static_cast<const void *>(&callback_));
|
||||
reinterpret_cast<const void *>(&callback_));
|
||||
TRACEPOINT(
|
||||
rclcpp_callback_register,
|
||||
static_cast<const void *>(&callback_),
|
||||
reinterpret_cast<const void *>(&callback_),
|
||||
tracetools::get_symbol(callback_));
|
||||
}
|
||||
|
||||
@@ -226,9 +226,9 @@ public:
|
||||
void
|
||||
execute_callback() override
|
||||
{
|
||||
TRACEPOINT(callback_start, static_cast<const void *>(&callback_), false);
|
||||
TRACEPOINT(callback_start, reinterpret_cast<const void *>(&callback_), false);
|
||||
execute_callback_delegate<>();
|
||||
TRACEPOINT(callback_end, static_cast<const void *>(&callback_));
|
||||
TRACEPOINT(callback_end, reinterpret_cast<const void *>(&callback_));
|
||||
}
|
||||
|
||||
// void specialization
|
||||
|
||||
@@ -169,7 +169,7 @@ remove_ros_arguments(int argc, char const * const * argv);
|
||||
* the context initialized by rclcpp::init().
|
||||
*
|
||||
* \param[in] context Optional check for shutdown of this Context.
|
||||
* \return true if shutdown has been called, false otherwise
|
||||
* \return false if shutdown has been called, true otherwise
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
|
||||
@@ -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>16.0.1</version>
|
||||
<version>17.0.0</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||
|
||||
@@ -114,7 +114,6 @@ def get_rclcpp_suffix_from_features(features):
|
||||
@[ end for]@
|
||||
@[ if 'stream' not in feature_combination]@
|
||||
* \param ... The format string, followed by the variable arguments for the format string.
|
||||
* It also accepts a single argument of type std::string.
|
||||
@[ end if]@
|
||||
*/
|
||||
@{params = rclcpp_feature_combinations[feature_combination].params.keys()}@
|
||||
|
||||
@@ -154,7 +154,9 @@ Context::~Context()
|
||||
// this will not prevent errors, but will maybe make them easier to reproduce
|
||||
std::lock_guard<std::recursive_mutex> lock(init_mutex_);
|
||||
try {
|
||||
this->shutdown("context destructor was called while still not shutdown");
|
||||
// Cannot rely on virtual dispatch in a destructor, so explicitly use the
|
||||
// shutdown() provided by this base class.
|
||||
Context::shutdown("context destructor was called while still not shutdown");
|
||||
// at this point it is shutdown and cannot reinit
|
||||
// clean_up will finalize the rcl context
|
||||
this->clean_up();
|
||||
|
||||
@@ -51,18 +51,13 @@ rclcpp::detail::resolve_parameter_overrides(
|
||||
[params]() {
|
||||
rcl_yaml_node_struct_fini(params);
|
||||
});
|
||||
rclcpp::ParameterMap initial_map = rclcpp::parameter_map_from(params);
|
||||
rclcpp::ParameterMap initial_map = rclcpp::parameter_map_from(params, node_fqn.c_str());
|
||||
|
||||
// Enforce wildcard matching precedence
|
||||
// TODO(cottsay) implement further wildcard matching
|
||||
const std::array<std::string, 2> node_matching_names{"/**", node_fqn};
|
||||
for (const auto & node_name : node_matching_names) {
|
||||
if (initial_map.count(node_name) > 0) {
|
||||
// Combine parameter yaml files, overwriting values in older ones
|
||||
for (const rclcpp::Parameter & param : initial_map.at(node_name)) {
|
||||
result[param.get_name()] =
|
||||
rclcpp::ParameterValue(param.get_value_message());
|
||||
}
|
||||
if (initial_map.count(node_fqn) > 0) {
|
||||
// Combine parameter yaml files, overwriting values in older ones
|
||||
for (const rclcpp::Parameter & param : initial_map.at(node_fqn)) {
|
||||
result[param.get_name()] =
|
||||
rclcpp::ParameterValue(param.get_value_message());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +161,13 @@ Duration::operator+(const rclcpp::Duration & rhs) const
|
||||
rcl_duration_.nanoseconds + rhs.rcl_duration_.nanoseconds);
|
||||
}
|
||||
|
||||
Duration &
|
||||
Duration::operator+=(const rclcpp::Duration & rhs)
|
||||
{
|
||||
*this = *this + rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
bounds_check_duration_difference(int64_t lhsns, int64_t rhsns, uint64_t max)
|
||||
{
|
||||
@@ -190,6 +197,13 @@ Duration::operator-(const rclcpp::Duration & rhs) const
|
||||
rcl_duration_.nanoseconds - rhs.rcl_duration_.nanoseconds);
|
||||
}
|
||||
|
||||
Duration &
|
||||
Duration::operator-=(const rclcpp::Duration & rhs)
|
||||
{
|
||||
*this = *this - rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
bounds_check_duration_scale(int64_t dns, double scale, uint64_t max)
|
||||
{
|
||||
@@ -222,6 +236,13 @@ Duration::operator*(double scale) const
|
||||
static_cast<long double>(rcl_duration_.nanoseconds) * scale_ld));
|
||||
}
|
||||
|
||||
Duration &
|
||||
Duration::operator*=(double scale)
|
||||
{
|
||||
*this = *this * scale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rcl_duration_value_t
|
||||
Duration::nanoseconds() const
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ GraphListener::GraphListener(const std::shared_ptr<Context> & parent_context)
|
||||
|
||||
GraphListener::~GraphListener()
|
||||
{
|
||||
this->shutdown(std::nothrow);
|
||||
GraphListener::shutdown(std::nothrow);
|
||||
}
|
||||
|
||||
void GraphListener::init_wait_set()
|
||||
|
||||
@@ -74,16 +74,19 @@ GuardCondition::get_rcl_guard_condition() const
|
||||
void
|
||||
GuardCondition::trigger()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(reentrant_mutex_);
|
||||
rcl_ret_t ret = rcl_trigger_guard_condition(&rcl_guard_condition_);
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
|
||||
if (on_trigger_callback_) {
|
||||
on_trigger_callback_(1);
|
||||
} else {
|
||||
rcl_ret_t ret = rcl_trigger_guard_condition(&rcl_guard_condition_);
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(reentrant_mutex_);
|
||||
|
||||
if (on_trigger_callback_) {
|
||||
on_trigger_callback_(1);
|
||||
} else {
|
||||
unread_count_++;
|
||||
}
|
||||
unread_count_++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,10 +128,9 @@ GuardCondition::set_on_trigger_callback(std::function<void(size_t)> callback)
|
||||
callback(unread_count_);
|
||||
unread_count_ = 0;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
on_trigger_callback_ = nullptr;
|
||||
}
|
||||
|
||||
on_trigger_callback_ = nullptr;
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -353,7 +353,7 @@ Node::has_parameter(const std::string & name) const
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
Node::set_parameter(const rclcpp::Parameter & parameter)
|
||||
{
|
||||
return this->set_parameters_atomically({parameter});
|
||||
return node_parameters_->set_parameters_atomically({parameter});
|
||||
}
|
||||
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
@@ -418,16 +418,40 @@ Node::list_parameters(const std::vector<std::string> & prefixes, uint64_t depth)
|
||||
return node_parameters_->list_parameters(prefixes, depth);
|
||||
}
|
||||
|
||||
rclcpp::Node::PreSetParametersCallbackHandle::SharedPtr
|
||||
Node::add_pre_set_parameters_callback(PreSetParametersCallbackType callback)
|
||||
{
|
||||
return node_parameters_->add_pre_set_parameters_callback(callback);
|
||||
}
|
||||
|
||||
rclcpp::Node::OnSetParametersCallbackHandle::SharedPtr
|
||||
Node::add_on_set_parameters_callback(OnParametersSetCallbackType callback)
|
||||
Node::add_on_set_parameters_callback(OnSetParametersCallbackType callback)
|
||||
{
|
||||
return node_parameters_->add_on_set_parameters_callback(callback);
|
||||
}
|
||||
|
||||
void
|
||||
Node::remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const callback)
|
||||
rclcpp::Node::PostSetParametersCallbackHandle::SharedPtr
|
||||
Node::add_post_set_parameters_callback(PostSetParametersCallbackType callback)
|
||||
{
|
||||
return node_parameters_->remove_on_set_parameters_callback(callback);
|
||||
return node_parameters_->add_post_set_parameters_callback(callback);
|
||||
}
|
||||
|
||||
void
|
||||
Node::remove_pre_set_parameters_callback(const PreSetParametersCallbackHandle * const handler)
|
||||
{
|
||||
node_parameters_->remove_pre_set_parameters_callback(handler);
|
||||
}
|
||||
|
||||
void
|
||||
Node::remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler)
|
||||
{
|
||||
node_parameters_->remove_on_set_parameters_callback(handler);
|
||||
}
|
||||
|
||||
void
|
||||
Node::remove_post_set_parameters_callback(const PostSetParametersCallbackHandle * const handler)
|
||||
{
|
||||
node_parameters_->remove_post_set_parameters_callback(handler);
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
|
||||
@@ -37,12 +37,13 @@ NodeBase::NodeBase(
|
||||
rclcpp::Context::SharedPtr context,
|
||||
const rcl_node_options_t & rcl_node_options,
|
||||
bool use_intra_process_default,
|
||||
bool enable_topic_statistics_default)
|
||||
bool enable_topic_statistics_default,
|
||||
rclcpp::CallbackGroup::SharedPtr default_callback_group)
|
||||
: context_(context),
|
||||
use_intra_process_default_(use_intra_process_default),
|
||||
enable_topic_statistics_default_(enable_topic_statistics_default),
|
||||
node_handle_(nullptr),
|
||||
default_callback_group_(nullptr),
|
||||
default_callback_group_(default_callback_group),
|
||||
associated_with_executor_(false),
|
||||
notify_guard_condition_(context),
|
||||
notify_guard_condition_is_valid_(false)
|
||||
@@ -128,9 +129,12 @@ NodeBase::NodeBase(
|
||||
delete node;
|
||||
});
|
||||
|
||||
// Create the default callback group.
|
||||
using rclcpp::CallbackGroupType;
|
||||
default_callback_group_ = create_callback_group(CallbackGroupType::MutuallyExclusive);
|
||||
// Create the default callback group, if needed.
|
||||
if (nullptr == default_callback_group_) {
|
||||
using rclcpp::CallbackGroupType;
|
||||
default_callback_group_ =
|
||||
NodeBase::create_callback_group(CallbackGroupType::MutuallyExclusive);
|
||||
}
|
||||
|
||||
// Indicate the notify_guard_condition is now valid.
|
||||
notify_guard_condition_is_valid_ = true;
|
||||
|
||||
@@ -19,7 +19,7 @@ using rclcpp::node_interfaces::NodeLogging;
|
||||
NodeLogging::NodeLogging(rclcpp::node_interfaces::NodeBaseInterface * node_base)
|
||||
: node_base_(node_base)
|
||||
{
|
||||
logger_ = rclcpp::get_logger(this->get_logger_name());
|
||||
logger_ = rclcpp::get_logger(NodeLogging::get_logger_name());
|
||||
}
|
||||
|
||||
NodeLogging::~NodeLogging()
|
||||
|
||||
@@ -39,6 +39,31 @@
|
||||
|
||||
using rclcpp::node_interfaces::NodeParameters;
|
||||
|
||||
RCLCPP_LOCAL
|
||||
void
|
||||
local_perform_automatically_declare_parameters_from_overrides(
|
||||
const std::map<std::string, rclcpp::ParameterValue> & parameter_overrides,
|
||||
std::function<bool(const std::string &)> has_parameter,
|
||||
std::function<void(
|
||||
const std::string &,
|
||||
const rclcpp::ParameterValue &,
|
||||
const rcl_interfaces::msg::ParameterDescriptor &,
|
||||
bool)>
|
||||
declare_parameter)
|
||||
{
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.dynamic_typing = true;
|
||||
for (const auto & pair : parameter_overrides) {
|
||||
if (!has_parameter(pair.first)) {
|
||||
declare_parameter(
|
||||
pair.first,
|
||||
pair.second,
|
||||
descriptor,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NodeParameters::NodeParameters(
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
|
||||
const rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
|
||||
@@ -101,20 +126,43 @@ NodeParameters::NodeParameters(
|
||||
// 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_parameters_from_overrides) {
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.dynamic_typing = true;
|
||||
for (const auto & pair : this->get_parameter_overrides()) {
|
||||
if (!this->has_parameter(pair.first)) {
|
||||
this->declare_parameter(
|
||||
pair.first,
|
||||
pair.second,
|
||||
descriptor,
|
||||
true);
|
||||
using namespace std::placeholders;
|
||||
local_perform_automatically_declare_parameters_from_overrides(
|
||||
this->get_parameter_overrides(),
|
||||
std::bind(&NodeParameters::has_parameter, this, _1),
|
||||
[this](
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
|
||||
bool ignore_override)
|
||||
{
|
||||
NodeParameters::declare_parameter(
|
||||
name, default_value, parameter_descriptor, ignore_override);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NodeParameters::perform_automatically_declare_parameters_from_overrides()
|
||||
{
|
||||
local_perform_automatically_declare_parameters_from_overrides(
|
||||
this->get_parameter_overrides(),
|
||||
[this](const std::string & name) {
|
||||
return this->has_parameter(name);
|
||||
},
|
||||
[this](
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
|
||||
bool ignore_override)
|
||||
{
|
||||
this->declare_parameter(
|
||||
name, default_value, parameter_descriptor, ignore_override);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
NodeParameters::~NodeParameters()
|
||||
{}
|
||||
|
||||
@@ -257,19 +305,54 @@ __check_parameters(
|
||||
return result;
|
||||
}
|
||||
|
||||
using OnParametersSetCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;
|
||||
using CallbacksContainerType =
|
||||
rclcpp::node_interfaces::NodeParameters::CallbacksContainerType;
|
||||
using PreSetParametersCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::PreSetParametersCallbackType;
|
||||
using PreSetParametersCallbackHandle =
|
||||
rclcpp::node_interfaces::PreSetParametersCallbackHandle;
|
||||
using PreSetCallbacksHandleContainer =
|
||||
rclcpp::node_interfaces::NodeParameters::PreSetCallbacksHandleContainer;
|
||||
|
||||
using OnSetParametersCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::OnSetParametersCallbackType;
|
||||
using OnSetParametersCallbackHandle =
|
||||
rclcpp::node_interfaces::OnSetParametersCallbackHandle;
|
||||
using OnSetCallbacksHandleContainer =
|
||||
rclcpp::node_interfaces::NodeParameters::OnSetCallbacksHandleContainer;
|
||||
|
||||
using PostSetParametersCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::PostSetParametersCallbackType;
|
||||
using PostSetParametersCallbackHandle =
|
||||
rclcpp::node_interfaces::PostSetParametersCallbackHandle;
|
||||
using PostSetCallbacksHandleContainer =
|
||||
rclcpp::node_interfaces::NodeParameters::PostSetCallbacksHandleContainer;
|
||||
|
||||
RCLCPP_LOCAL
|
||||
void
|
||||
__call_pre_set_parameters_callbacks(
|
||||
std::vector<rclcpp::Parameter> & parameters,
|
||||
PreSetCallbacksHandleContainer & callback_container)
|
||||
{
|
||||
if (callback_container.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = callback_container.begin();
|
||||
while (it != callback_container.end()) {
|
||||
auto shared_handle = it->lock();
|
||||
if (nullptr != shared_handle) {
|
||||
shared_handle->callback(parameters);
|
||||
it++;
|
||||
} else {
|
||||
it = callback_container.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
__call_on_parameters_set_callbacks(
|
||||
__call_on_set_parameters_callbacks(
|
||||
const std::vector<rclcpp::Parameter> & parameters,
|
||||
CallbacksContainerType & callback_container,
|
||||
const OnParametersSetCallbackType & callback)
|
||||
OnSetCallbacksHandleContainer & callback_container)
|
||||
{
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
@@ -286,19 +369,37 @@ __call_on_parameters_set_callbacks(
|
||||
it = callback_container.erase(it);
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
result = callback(parameters);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
void __call_post_set_parameters_callbacks(
|
||||
const std::vector<rclcpp::Parameter> & parameters,
|
||||
PostSetCallbacksHandleContainer & callback_container)
|
||||
{
|
||||
if (callback_container.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = callback_container.begin();
|
||||
while (it != callback_container.end()) {
|
||||
auto shared_handle = it->lock();
|
||||
if (nullptr != shared_handle) {
|
||||
shared_handle->callback(parameters);
|
||||
it++;
|
||||
} else {
|
||||
it = callback_container.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
__set_parameters_atomically_common(
|
||||
const std::vector<rclcpp::Parameter> & parameters,
|
||||
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameter_infos,
|
||||
CallbacksContainerType & callback_container,
|
||||
const OnParametersSetCallbackType & callback,
|
||||
OnSetCallbacksHandleContainer & on_set_callback_container,
|
||||
PostSetCallbacksHandleContainer & post_set_callback_container,
|
||||
bool allow_undeclared = false)
|
||||
{
|
||||
// Check if the value being set complies with the descriptor.
|
||||
@@ -307,9 +408,9 @@ __set_parameters_atomically_common(
|
||||
if (!result.successful) {
|
||||
return result;
|
||||
}
|
||||
// Call the user callback to see if the new value(s) are allowed.
|
||||
// Call the user callbacks to see if the new value(s) are allowed.
|
||||
result =
|
||||
__call_on_parameters_set_callbacks(parameters, callback_container, callback);
|
||||
__call_on_set_parameters_callbacks(parameters, on_set_callback_container);
|
||||
if (!result.successful) {
|
||||
return result;
|
||||
}
|
||||
@@ -321,6 +422,8 @@ __set_parameters_atomically_common(
|
||||
parameter_infos[name].descriptor.type = parameters[i].get_type();
|
||||
parameter_infos[name].value = parameters[i].get_parameter_value();
|
||||
}
|
||||
// Call the user post set parameter callback
|
||||
__call_post_set_parameters_callbacks(parameters, post_set_callback_container);
|
||||
}
|
||||
|
||||
// Either way, return the result.
|
||||
@@ -335,8 +438,8 @@ __declare_parameter_common(
|
||||
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
|
||||
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameters_out,
|
||||
const std::map<std::string, rclcpp::ParameterValue> & overrides,
|
||||
CallbacksContainerType & callback_container,
|
||||
const OnParametersSetCallbackType & callback,
|
||||
OnSetCallbacksHandleContainer & on_set_callback_container,
|
||||
PostSetCallbacksHandleContainer & post_set_callback_container,
|
||||
rcl_interfaces::msg::ParameterEvent * parameter_event_out,
|
||||
bool ignore_override = false)
|
||||
{
|
||||
@@ -366,14 +469,15 @@ __declare_parameter_common(
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check with the user's callback to see if the initial value can be set.
|
||||
// Check with the user's callbacks to see if the initial value can be set.
|
||||
std::vector<rclcpp::Parameter> parameter_wrappers {rclcpp::Parameter(name, *initial_value)};
|
||||
// This function also takes care of default vs initial value.
|
||||
auto result = __set_parameters_atomically_common(
|
||||
parameter_wrappers,
|
||||
parameter_infos,
|
||||
callback_container,
|
||||
callback);
|
||||
on_set_callback_container,
|
||||
post_set_callback_container
|
||||
);
|
||||
|
||||
if (!result.successful) {
|
||||
return result;
|
||||
@@ -400,8 +504,8 @@ declare_parameter_helper(
|
||||
bool ignore_override,
|
||||
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameters,
|
||||
const std::map<std::string, rclcpp::ParameterValue> & overrides,
|
||||
CallbacksContainerType & callback_container,
|
||||
const OnParametersSetCallbackType & callback,
|
||||
OnSetCallbacksHandleContainer & on_set_callback_container,
|
||||
PostSetCallbacksHandleContainer & post_set_callback_container,
|
||||
rclcpp::Publisher<rcl_interfaces::msg::ParameterEvent> * events_publisher,
|
||||
const std::string & combined_name,
|
||||
rclcpp::node_interfaces::NodeClockInterface & node_clock)
|
||||
@@ -437,8 +541,8 @@ declare_parameter_helper(
|
||||
parameter_descriptor,
|
||||
parameters,
|
||||
overrides,
|
||||
callback_container,
|
||||
callback,
|
||||
on_set_callback_container,
|
||||
post_set_callback_container,
|
||||
¶meter_event,
|
||||
ignore_override);
|
||||
|
||||
@@ -485,8 +589,8 @@ NodeParameters::declare_parameter(
|
||||
ignore_override,
|
||||
parameters_,
|
||||
parameter_overrides_,
|
||||
on_parameters_set_callback_container_,
|
||||
on_parameters_set_callback_,
|
||||
on_set_parameters_callback_container_,
|
||||
post_set_parameters_callback_container_,
|
||||
events_publisher_.get(),
|
||||
combined_name_,
|
||||
*node_clock_);
|
||||
@@ -521,8 +625,8 @@ NodeParameters::declare_parameter(
|
||||
ignore_override,
|
||||
parameters_,
|
||||
parameter_overrides_,
|
||||
on_parameters_set_callback_container_,
|
||||
on_parameters_set_callback_,
|
||||
on_set_parameters_callback_container_,
|
||||
post_set_parameters_callback_container_,
|
||||
events_publisher_.get(),
|
||||
combined_name_,
|
||||
*node_clock_);
|
||||
@@ -596,12 +700,27 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
|
||||
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
|
||||
// call any user registered pre set parameter callbacks
|
||||
// this callback can make changes to the original parameters list
|
||||
// also check if the changed parameter list is empty or not, if empty return
|
||||
std::vector<rclcpp::Parameter> parameters_after_pre_set_callback(parameters);
|
||||
__call_pre_set_parameters_callbacks(
|
||||
parameters_after_pre_set_callback,
|
||||
pre_set_parameters_callback_container_);
|
||||
|
||||
if (parameters_after_pre_set_callback.empty()) {
|
||||
result.successful = false;
|
||||
result.reason = "parameter list cannot be empty, this might be due to "
|
||||
"pre_set_parameters_callback modifying the original parameters list.";
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check if any of the parameters are read-only, or if any parameters are not
|
||||
// declared.
|
||||
// If not declared, keep track of them in order to declare them later, when
|
||||
// undeclared parameters are allowed, and if they're not allowed, fail.
|
||||
std::vector<const rclcpp::Parameter *> parameters_to_be_declared;
|
||||
for (const auto & parameter : parameters) {
|
||||
for (const auto & parameter : parameters_after_pre_set_callback) {
|
||||
const std::string & name = parameter.get_name();
|
||||
|
||||
// Check to make sure the parameter name is valid.
|
||||
@@ -636,12 +755,13 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
|
||||
|
||||
// Declare parameters into a temporary "staging area", incase one of the declares fail.
|
||||
// We will use the staged changes as input to the "set atomically" action.
|
||||
// We explicitly avoid calling the user callback here, so that it may be called once, with
|
||||
// We explicitly avoid calling the user callbacks here, so that it may be called once, with
|
||||
// all the other parameters to be set (already declared parameters).
|
||||
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> staged_parameter_changes;
|
||||
rcl_interfaces::msg::ParameterEvent parameter_event_msg;
|
||||
parameter_event_msg.node = combined_name_;
|
||||
CallbacksContainerType empty_callback_container;
|
||||
OnSetCallbacksHandleContainer empty_on_set_callback_container;
|
||||
PostSetCallbacksHandleContainer empty_post_set_callback_container;
|
||||
|
||||
// Implicit declare uses dynamic type descriptor.
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
@@ -656,8 +776,8 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
|
||||
staged_parameter_changes,
|
||||
parameter_overrides_,
|
||||
// Only call callbacks once below
|
||||
empty_callback_container, // callback_container is explicitly empty
|
||||
nullptr, // callback is explicitly null.
|
||||
empty_on_set_callback_container, // callback_container is explicitly empty
|
||||
empty_post_set_callback_container, // callback_container is explicitly empty
|
||||
¶meter_event_msg,
|
||||
true);
|
||||
if (!result.successful) {
|
||||
@@ -670,12 +790,14 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
|
||||
// If there were implicitly declared parameters, then we may need to copy the input parameters
|
||||
// and then assign the value that was selected after the declare (could be affected by the
|
||||
// initial parameter values).
|
||||
const std::vector<rclcpp::Parameter> * parameters_to_be_set = ¶meters;
|
||||
const std::vector<rclcpp::Parameter> * parameters_to_be_set = ¶meters_after_pre_set_callback;
|
||||
std::vector<rclcpp::Parameter> parameters_copy;
|
||||
if (0 != staged_parameter_changes.size()) { // If there were any implicitly declared parameters.
|
||||
bool any_initial_values_used = false;
|
||||
for (const auto & staged_parameter_change : staged_parameter_changes) {
|
||||
auto it = __find_parameter_by_name(parameters, staged_parameter_change.first);
|
||||
auto it = __find_parameter_by_name(
|
||||
parameters_after_pre_set_callback,
|
||||
staged_parameter_change.first);
|
||||
if (it->get_parameter_value() != staged_parameter_change.second.value) {
|
||||
// In this case, the value of the staged parameter differs from the
|
||||
// input from the user, and therefore we need to update things before setting.
|
||||
@@ -685,7 +807,7 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
|
||||
}
|
||||
}
|
||||
if (any_initial_values_used) {
|
||||
parameters_copy = parameters;
|
||||
parameters_copy = parameters_after_pre_set_callback;
|
||||
for (const auto & staged_parameter_change : staged_parameter_changes) {
|
||||
auto it = __find_parameter_by_name(parameters_copy, staged_parameter_change.first);
|
||||
*it = Parameter(staged_parameter_change.first, staged_parameter_change.second.value);
|
||||
@@ -717,11 +839,10 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
|
||||
*parameters_to_be_set,
|
||||
// they are actually set on the official parameter storage
|
||||
parameters_,
|
||||
// this will get called once, with all the parameters to be set
|
||||
on_parameters_set_callback_container_,
|
||||
// These callbacks are called once. When a callback returns an unsuccessful result,
|
||||
// the remaining aren't called.
|
||||
on_parameters_set_callback_,
|
||||
// the remaining aren't called
|
||||
on_set_parameters_callback_container_,
|
||||
post_set_parameters_callback_container_,
|
||||
allow_undeclared_); // allow undeclared
|
||||
|
||||
// If not successful, then stop here.
|
||||
@@ -777,7 +898,6 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
|
||||
parameter_event_msg.stamp = node_clock_->get_clock()->now();
|
||||
events_publisher_->publish(parameter_event_msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -963,6 +1083,26 @@ NodeParameters::list_parameters(const std::vector<std::string> & prefixes, uint6
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
NodeParameters::remove_pre_set_parameters_callback(
|
||||
const PreSetParametersCallbackHandle * const handle)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
|
||||
|
||||
auto it = std::find_if(
|
||||
pre_set_parameters_callback_container_.begin(),
|
||||
pre_set_parameters_callback_container_.end(),
|
||||
[handle](const auto & weak_handle) {
|
||||
return handle == weak_handle.lock().get();
|
||||
});
|
||||
if (it != pre_set_parameters_callback_container_.end()) {
|
||||
pre_set_parameters_callback_container_.erase(it);
|
||||
} else {
|
||||
throw std::runtime_error("Pre set parameter callback doesn't exist");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NodeParameters::remove_on_set_parameters_callback(
|
||||
const OnSetParametersCallbackHandle * const handle)
|
||||
@@ -971,20 +1111,53 @@ NodeParameters::remove_on_set_parameters_callback(
|
||||
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
|
||||
|
||||
auto it = std::find_if(
|
||||
on_parameters_set_callback_container_.begin(),
|
||||
on_parameters_set_callback_container_.end(),
|
||||
on_set_parameters_callback_container_.begin(),
|
||||
on_set_parameters_callback_container_.end(),
|
||||
[handle](const auto & weak_handle) {
|
||||
return handle == weak_handle.lock().get();
|
||||
});
|
||||
if (it != on_parameters_set_callback_container_.end()) {
|
||||
on_parameters_set_callback_container_.erase(it);
|
||||
if (it != on_set_parameters_callback_container_.end()) {
|
||||
on_set_parameters_callback_container_.erase(it);
|
||||
} else {
|
||||
throw std::runtime_error("Callback doesn't exist");
|
||||
throw std::runtime_error("On set parameter callback doesn't exist");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NodeParameters::remove_post_set_parameters_callback(
|
||||
const PostSetParametersCallbackHandle * const handle)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
|
||||
|
||||
auto it = std::find_if(
|
||||
post_set_parameters_callback_container_.begin(),
|
||||
post_set_parameters_callback_container_.end(),
|
||||
[handle](const auto & weak_handle) {
|
||||
return handle == weak_handle.lock().get();
|
||||
});
|
||||
if (it != post_set_parameters_callback_container_.end()) {
|
||||
post_set_parameters_callback_container_.erase(it);
|
||||
} else {
|
||||
throw std::runtime_error("Post set parameter callback doesn't exist");
|
||||
}
|
||||
}
|
||||
|
||||
PreSetParametersCallbackHandle::SharedPtr
|
||||
NodeParameters::add_pre_set_parameters_callback(PreSetParametersCallbackType callback)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
|
||||
|
||||
auto handle = std::make_shared<PreSetParametersCallbackHandle>();
|
||||
handle->callback = callback;
|
||||
// the last callback registered is executed first.
|
||||
pre_set_parameters_callback_container_.emplace_front(handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
OnSetParametersCallbackHandle::SharedPtr
|
||||
NodeParameters::add_on_set_parameters_callback(OnParametersSetCallbackType callback)
|
||||
NodeParameters::add_on_set_parameters_callback(OnSetParametersCallbackType callback)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
|
||||
@@ -992,7 +1165,21 @@ NodeParameters::add_on_set_parameters_callback(OnParametersSetCallbackType callb
|
||||
auto handle = std::make_shared<OnSetParametersCallbackHandle>();
|
||||
handle->callback = callback;
|
||||
// the last callback registered is executed first.
|
||||
on_parameters_set_callback_container_.emplace_front(handle);
|
||||
on_set_parameters_callback_container_.emplace_front(handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
PostSetParametersCallbackHandle::SharedPtr
|
||||
NodeParameters::add_post_set_parameters_callback(
|
||||
PostSetParametersCallbackType callback)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
|
||||
|
||||
auto handle = std::make_shared<PostSetParametersCallbackHandle>();
|
||||
handle->callback = callback;
|
||||
// the last callback registered is executed first.
|
||||
post_set_parameters_callback_container_.emplace_front(handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ AsyncParametersClient::AsyncParametersClient(
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
const rclcpp::QoS & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
: node_topics_interface_(node_topics_interface)
|
||||
{
|
||||
@@ -46,7 +46,7 @@ AsyncParametersClient::AsyncParametersClient(
|
||||
}
|
||||
|
||||
rcl_client_options_t options = rcl_client_get_default_options();
|
||||
options.qos = qos_profile;
|
||||
options.qos = qos_profile.get_rmw_qos_profile();
|
||||
|
||||
using rclcpp::Client;
|
||||
using rclcpp::ClientBase;
|
||||
@@ -290,28 +290,24 @@ std::shared_future<std::vector<rcl_interfaces::msg::SetParametersResult>>
|
||||
AsyncParametersClient::load_parameters(
|
||||
const std::string & yaml_filename)
|
||||
{
|
||||
rclcpp::ParameterMap parameter_map = rclcpp::parameter_map_from_yaml_file(yaml_filename);
|
||||
return this->load_parameters(parameter_map);
|
||||
rclcpp::ParameterMap parameter_map =
|
||||
rclcpp::parameter_map_from_yaml_file(yaml_filename, remote_node_name_.c_str());
|
||||
|
||||
auto iter = parameter_map.find(remote_node_name_);
|
||||
if (iter == parameter_map.end() || iter->second.size() == 0) {
|
||||
throw rclcpp::exceptions::InvalidParametersException("No valid parameter");
|
||||
}
|
||||
auto future_result = set_parameters(iter->second);
|
||||
|
||||
return future_result;
|
||||
}
|
||||
|
||||
std::shared_future<std::vector<rcl_interfaces::msg::SetParametersResult>>
|
||||
AsyncParametersClient::load_parameters(
|
||||
const rclcpp::ParameterMap & parameter_map)
|
||||
{
|
||||
std::vector<rclcpp::Parameter> parameters;
|
||||
std::string remote_name = remote_node_name_.substr(remote_node_name_.substr(1).find("/") + 2);
|
||||
for (const auto & params : parameter_map) {
|
||||
std::string node_full_name = params.first;
|
||||
std::string node_name = node_full_name.substr(node_full_name.find("/*/") + 3);
|
||||
if (node_full_name == remote_node_name_ ||
|
||||
node_full_name == "/**" ||
|
||||
(node_name == remote_name))
|
||||
{
|
||||
for (const auto & param : params.second) {
|
||||
parameters.push_back(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<rclcpp::Parameter> parameters =
|
||||
rclcpp::parameters_from_map(parameter_map, remote_node_name_.c_str());
|
||||
|
||||
if (parameters.size() == 0) {
|
||||
throw rclcpp::exceptions::InvalidParametersException("No valid parameter");
|
||||
|
||||
@@ -133,9 +133,13 @@ ParameterEventHandler::get_parameter_from_event(
|
||||
{
|
||||
rclcpp::Parameter p;
|
||||
if (!get_parameter_from_event(event, p, parameter_name, node_name)) {
|
||||
throw std::runtime_error(
|
||||
"Parameter '" + parameter_name + "' of node '" + node_name +
|
||||
"' is not part of parameter event");
|
||||
if (event.node == node_name) {
|
||||
return rclcpp::Parameter(parameter_name, rclcpp::PARAMETER_NOT_SET);
|
||||
} else {
|
||||
throw std::runtime_error(
|
||||
"The node name '" + node_name + "' of parameter '" + parameter_name +
|
||||
+"' doesn't match the node name '" + event.node + "' in parameter event");
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -13,8 +13,11 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <string>
|
||||
#include <regex>
|
||||
#include <vector>
|
||||
|
||||
#include "rcpputils/find_and_replace.hpp"
|
||||
#include "rcpputils/scope_exit.hpp"
|
||||
#include "rclcpp/parameter_map.hpp"
|
||||
|
||||
using rclcpp::exceptions::InvalidParametersException;
|
||||
@@ -22,8 +25,15 @@ using rclcpp::exceptions::InvalidParameterValueException;
|
||||
using rclcpp::ParameterMap;
|
||||
using rclcpp::ParameterValue;
|
||||
|
||||
static bool is_node_name_matched(const std::string & node_name, const char * node_fqn)
|
||||
{
|
||||
// Update the regular expression ["/*" -> "(/\\w+)" and "/**" -> "(/\\w+)*"]
|
||||
std::string regex = rcpputils::find_and_replace(node_name, "/*", "(/\\w+)");
|
||||
return std::regex_match(node_fqn, std::regex(regex));
|
||||
}
|
||||
|
||||
ParameterMap
|
||||
rclcpp::parameter_map_from(const rcl_params_t * const c_params)
|
||||
rclcpp::parameter_map_from(const rcl_params_t * const c_params, const char * node_fqn)
|
||||
{
|
||||
if (NULL == c_params) {
|
||||
throw InvalidParametersException("parameters struct is NULL");
|
||||
@@ -49,6 +59,15 @@ rclcpp::parameter_map_from(const rcl_params_t * const c_params)
|
||||
node_name = c_node_name;
|
||||
}
|
||||
|
||||
if (node_fqn) {
|
||||
if (!is_node_name_matched(node_name, node_fqn)) {
|
||||
// No need to parse the items because the user just care about node_fqn
|
||||
continue;
|
||||
}
|
||||
|
||||
node_name = node_fqn;
|
||||
}
|
||||
|
||||
const rcl_node_params_t * const c_params_node = &(c_params->params[n]);
|
||||
|
||||
std::vector<Parameter> & params_node = parameters[node_name];
|
||||
@@ -65,6 +84,7 @@ rclcpp::parameter_map_from(const rcl_params_t * const c_params)
|
||||
params_node.emplace_back(c_param_name, parameter_value_from(c_param_value));
|
||||
}
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@@ -128,13 +148,31 @@ rclcpp::parameter_value_from(const rcl_variant_t * const c_param_value)
|
||||
}
|
||||
|
||||
ParameterMap
|
||||
rclcpp::parameter_map_from_yaml_file(const std::string & yaml_filename)
|
||||
rclcpp::parameter_map_from_yaml_file(const std::string & yaml_filename, const char * node_fqn)
|
||||
{
|
||||
rcutils_allocator_t allocator = rcutils_get_default_allocator();
|
||||
rcl_params_t * rcl_parameters = rcl_yaml_node_struct_init(allocator);
|
||||
RCPPUTILS_SCOPE_EXIT(rcl_yaml_node_struct_fini(rcl_parameters); );
|
||||
const char * path = yaml_filename.c_str();
|
||||
if (!rcl_parse_yaml_file(path, rcl_parameters)) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(RCL_RET_ERROR);
|
||||
}
|
||||
return rclcpp::parameter_map_from(rcl_parameters);
|
||||
|
||||
return rclcpp::parameter_map_from(rcl_parameters, node_fqn);
|
||||
}
|
||||
|
||||
std::vector<rclcpp::Parameter>
|
||||
rclcpp::parameters_from_map(const ParameterMap & parameter_map, const char * node_fqn)
|
||||
{
|
||||
std::vector<rclcpp::Parameter> parameters;
|
||||
std::string node_name_old;
|
||||
for (auto & [node_name, node_parameters] : parameter_map) {
|
||||
if (node_fqn && !is_node_name_matched(node_name, node_fqn)) {
|
||||
// No need to parse the items because the user just care about node_fqn
|
||||
continue;
|
||||
}
|
||||
parameters.insert(parameters.end(), node_parameters.begin(), node_parameters.end());
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ ParameterService::ParameterService(
|
||||
const std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface> node_base,
|
||||
const std::shared_ptr<rclcpp::node_interfaces::NodeServicesInterface> node_services,
|
||||
rclcpp::node_interfaces::NodeParametersInterface * node_params,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
const rclcpp::QoS & qos_profile)
|
||||
{
|
||||
const std::string node_name = node_base->get_name();
|
||||
|
||||
|
||||
@@ -150,6 +150,12 @@ QoS::best_effort()
|
||||
return this->reliability(RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT);
|
||||
}
|
||||
|
||||
QoS &
|
||||
QoS::reliability_best_available()
|
||||
{
|
||||
return this->reliability(RMW_QOS_POLICY_RELIABILITY_BEST_AVAILABLE);
|
||||
}
|
||||
|
||||
QoS &
|
||||
QoS::durability(rmw_qos_durability_policy_t durability)
|
||||
{
|
||||
@@ -176,6 +182,12 @@ QoS::transient_local()
|
||||
return this->durability(RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL);
|
||||
}
|
||||
|
||||
QoS &
|
||||
QoS::durability_best_available()
|
||||
{
|
||||
return this->durability(RMW_QOS_POLICY_DURABILITY_BEST_AVAILABLE);
|
||||
}
|
||||
|
||||
QoS &
|
||||
QoS::deadline(rmw_time_t deadline)
|
||||
{
|
||||
@@ -380,4 +392,8 @@ SystemDefaultsQoS::SystemDefaultsQoS(const QoSInitialization & qos_initializatio
|
||||
: QoS(qos_initialization, rmw_qos_profile_system_default)
|
||||
{}
|
||||
|
||||
BestAvailableQoS::BestAvailableQoS(const QoSInitialization & qos_initialization)
|
||||
: QoS(qos_initialization, rmw_qos_profile_best_available)
|
||||
{}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -299,7 +299,7 @@ if(TARGET test_init_options)
|
||||
ament_target_dependencies(test_init_options "rcl")
|
||||
target_link_libraries(test_init_options ${PROJECT_NAME} mimick)
|
||||
endif()
|
||||
ament_add_gtest(test_parameter_client test_parameter_client.cpp)
|
||||
ament_add_gmock(test_parameter_client test_parameter_client.cpp)
|
||||
if(TARGET test_parameter_client)
|
||||
ament_target_dependencies(test_parameter_client
|
||||
"rcl_interfaces"
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include "../../mocking_utils/patch.hpp"
|
||||
#include "../../utils/rclcpp_gtest_macros.hpp"
|
||||
|
||||
#include "rcpputils/filesystem_helper.hpp"
|
||||
|
||||
class TestNodeParameters : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
@@ -47,6 +49,7 @@ public:
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||
node->get_node_parameters_interface().get());
|
||||
ASSERT_NE(nullptr, node_parameters);
|
||||
test_resources_path /= "test_node_parameters";
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
@@ -57,6 +60,8 @@ public:
|
||||
protected:
|
||||
std::shared_ptr<rclcpp::Node> node;
|
||||
rclcpp::node_interfaces::NodeParameters * node_parameters;
|
||||
|
||||
rcpputils::fs::path test_resources_path{TEST_RESOURCES_DIRECTORY};
|
||||
};
|
||||
|
||||
TEST_F(TestNodeParameters, construct_destruct_rcl_errors) {
|
||||
@@ -170,7 +175,7 @@ TEST_F(TestNodeParameters, set_parameters) {
|
||||
EXPECT_TRUE(result[0].successful);
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, add_remove_parameters_callback) {
|
||||
TEST_F(TestNodeParameters, add_remove_on_set_parameters_callback) {
|
||||
rcl_interfaces::msg::ParameterDescriptor bool_descriptor;
|
||||
bool_descriptor.name = "bool_parameter";
|
||||
bool_descriptor.type = rcl_interfaces::msg::ParameterType::PARAMETER_BOOL;
|
||||
@@ -197,5 +202,248 @@ TEST_F(TestNodeParameters, add_remove_parameters_callback) {
|
||||
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
node_parameters->remove_on_set_parameters_callback(handle.get()),
|
||||
std::runtime_error("Callback doesn't exist"));
|
||||
std::runtime_error("On set parameter callback doesn't exist"));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, add_remove_pre_set_parameters_callback) {
|
||||
// `add_pre_set_parameters_callback` used to modify parameters list.
|
||||
auto modify_parameter_list_callback = [](std::vector<rclcpp::Parameter> & parameters) {
|
||||
for (const auto & param : parameters) {
|
||||
if (param.get_name() == "param1") {
|
||||
parameters.emplace_back("param2", 2.0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// `add_pre_set_parameters_callback` used to make the parameters list empty.
|
||||
auto empty_parameter_list_callback = [](std::vector<rclcpp::Parameter> & parameters) {
|
||||
parameters = {};
|
||||
};
|
||||
|
||||
auto handle1 =
|
||||
node_parameters->add_pre_set_parameters_callback(modify_parameter_list_callback);
|
||||
|
||||
double default_value = 0.0;
|
||||
node_parameters->declare_parameter(
|
||||
"param1", rclcpp::ParameterValue(default_value));
|
||||
node_parameters->declare_parameter(
|
||||
"param2", rclcpp::ParameterValue(default_value));
|
||||
|
||||
// verify that `declare_parameter` does not call any of the callbacks registered with
|
||||
// `add_pre_set_parameters_callback`
|
||||
EXPECT_TRUE(node_parameters->has_parameter("param1"));
|
||||
EXPECT_EQ(node_parameters->get_parameter("param1").get_value<double>(), default_value);
|
||||
EXPECT_TRUE(node_parameters->has_parameter("param2"));
|
||||
EXPECT_EQ(node_parameters->get_parameter("param2").get_value<double>(), default_value);
|
||||
|
||||
// verify that the `param2` was set successfully conditioned on setting of
|
||||
// `param1`
|
||||
const std::vector<rclcpp::Parameter> parameters_to_be_set = {
|
||||
rclcpp::Parameter("param1", 1.0)};
|
||||
auto result = node_parameters->set_parameters(parameters_to_be_set);
|
||||
// we expect the result size to be same as the original "parameters_to_be_set"
|
||||
// since the pre set parameter callback will set the modified param list atomically.
|
||||
ASSERT_EQ(1u, result.size());
|
||||
EXPECT_TRUE(result[0].successful);
|
||||
EXPECT_TRUE(node_parameters->has_parameter("param1"));
|
||||
EXPECT_EQ(node_parameters->get_parameter("param1").get_value<double>(), 1.0);
|
||||
EXPECT_TRUE(node_parameters->has_parameter("param2"));
|
||||
EXPECT_EQ(node_parameters->get_parameter("param2").get_value<double>(), 2.0);
|
||||
EXPECT_NO_THROW(node_parameters->remove_pre_set_parameters_callback(handle1.get()));
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
node_parameters->remove_pre_set_parameters_callback(handle1.get()),
|
||||
std::runtime_error("Pre set parameter callback doesn't exist"));
|
||||
|
||||
// verify that the result should be unsuccessful if the pre set callback makes
|
||||
// parameter list empty
|
||||
auto handle2 =
|
||||
node_parameters->add_pre_set_parameters_callback(empty_parameter_list_callback);
|
||||
auto results = node_parameters->set_parameters(parameters_to_be_set);
|
||||
|
||||
std::string reason = "parameter list cannot be empty, this might be due to "
|
||||
"pre_set_parameters_callback modifying the original parameters list.";
|
||||
EXPECT_FALSE(results[0].successful);
|
||||
EXPECT_EQ(results[0].reason, reason);
|
||||
EXPECT_NO_THROW(node_parameters->remove_pre_set_parameters_callback(handle2.get()));
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
node_parameters->remove_pre_set_parameters_callback(handle2.get()),
|
||||
std::runtime_error("Pre set parameter callback doesn't exist"));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, add_remove_post_set_parameters_callback) {
|
||||
rcl_interfaces::msg::ParameterDescriptor param1_descriptor;
|
||||
param1_descriptor.name = "double_parameter1";
|
||||
param1_descriptor.type = rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE;
|
||||
param1_descriptor.read_only = false;
|
||||
|
||||
rcl_interfaces::msg::ParameterDescriptor param2_descriptor;
|
||||
param2_descriptor.name = "double_parameter2";
|
||||
param2_descriptor.type = rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE;
|
||||
param2_descriptor.read_only = false;
|
||||
|
||||
double variable_tracking_param1_internally = node_parameters->declare_parameter(
|
||||
"param1", rclcpp::ParameterValue(0.0), param1_descriptor, false).get<double>();
|
||||
double variable_tracking_param2_internally = node_parameters->declare_parameter(
|
||||
"param2", rclcpp::ParameterValue(0.0), param2_descriptor, false).get<double>();
|
||||
|
||||
EXPECT_EQ(variable_tracking_param1_internally, 0.0);
|
||||
EXPECT_EQ(variable_tracking_param2_internally, 0.0);
|
||||
|
||||
const std::vector<rclcpp::Parameter> parameters_to_be_set = {
|
||||
rclcpp::Parameter("param1", 1.0),
|
||||
rclcpp::Parameter("param2", 2.0)};
|
||||
|
||||
// register a callback for successful set parameter and change the internally tracked variables.
|
||||
auto callback = [&](const std::vector<rclcpp::Parameter> & parameters) {
|
||||
for (const auto & param : parameters) {
|
||||
if (param.get_name() == "param1") {
|
||||
variable_tracking_param1_internally = param.get_value<double>();
|
||||
} else if (param.get_name() == "param2") {
|
||||
variable_tracking_param2_internally = param.get_value<double>();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto handle = node_parameters->add_post_set_parameters_callback(callback);
|
||||
auto result = node_parameters->set_parameters(parameters_to_be_set);
|
||||
ASSERT_EQ(2u, result.size());
|
||||
EXPECT_TRUE(result[0].successful);
|
||||
EXPECT_TRUE(result[1].successful);
|
||||
EXPECT_TRUE(node_parameters->has_parameter("param1"));
|
||||
EXPECT_TRUE(node_parameters->has_parameter("param2"));
|
||||
EXPECT_EQ(variable_tracking_param1_internally, 1.0);
|
||||
EXPECT_EQ(variable_tracking_param2_internally, 2.0);
|
||||
|
||||
EXPECT_NO_THROW(node_parameters->remove_post_set_parameters_callback(handle.get()));
|
||||
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
node_parameters->remove_post_set_parameters_callback(handle.get()),
|
||||
std::runtime_error("Post set parameter callback doesn't exist"));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, wildcard_with_namespace)
|
||||
{
|
||||
rclcpp::NodeOptions opts;
|
||||
opts.arguments(
|
||||
{
|
||||
"--ros-args",
|
||||
"--params-file", (test_resources_path / "wildcards.yaml").string()
|
||||
});
|
||||
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node2", "ns", opts);
|
||||
|
||||
auto * node_parameters =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||
node->get_node_parameters_interface().get());
|
||||
ASSERT_NE(nullptr, node_parameters);
|
||||
|
||||
const auto & parameter_overrides = node_parameters->get_parameter_overrides();
|
||||
EXPECT_EQ(7u, parameter_overrides.size());
|
||||
EXPECT_EQ(parameter_overrides.at("full_wild").get<std::string>(), "full_wild");
|
||||
EXPECT_EQ(parameter_overrides.at("namespace_wild").get<std::string>(), "namespace_wild");
|
||||
EXPECT_EQ(
|
||||
parameter_overrides.at("namespace_wild_another").get<std::string>(),
|
||||
"namespace_wild_another");
|
||||
EXPECT_EQ(
|
||||
parameter_overrides.at("namespace_wild_one_star").get<std::string>(),
|
||||
"namespace_wild_one_star");
|
||||
EXPECT_EQ(parameter_overrides.at("node_wild_in_ns").get<std::string>(), "node_wild_in_ns");
|
||||
EXPECT_EQ(
|
||||
parameter_overrides.at("node_wild_in_ns_another").get<std::string>(),
|
||||
"node_wild_in_ns_another");
|
||||
EXPECT_EQ(parameter_overrides.at("explicit_in_ns").get<std::string>(), "explicit_in_ns");
|
||||
EXPECT_EQ(parameter_overrides.count("should_not_appear"), 0u);
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, wildcard_no_namespace)
|
||||
{
|
||||
rclcpp::NodeOptions opts;
|
||||
opts.arguments(
|
||||
{
|
||||
"--ros-args",
|
||||
"--params-file", (test_resources_path / "wildcards.yaml").string()
|
||||
});
|
||||
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node2", opts);
|
||||
|
||||
auto * node_parameters =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||
node->get_node_parameters_interface().get());
|
||||
ASSERT_NE(nullptr, node_parameters);
|
||||
|
||||
const auto & parameter_overrides = node_parameters->get_parameter_overrides();
|
||||
EXPECT_EQ(5u, parameter_overrides.size());
|
||||
EXPECT_EQ(parameter_overrides.at("full_wild").get<std::string>(), "full_wild");
|
||||
EXPECT_EQ(parameter_overrides.at("namespace_wild").get<std::string>(), "namespace_wild");
|
||||
EXPECT_EQ(
|
||||
parameter_overrides.at("namespace_wild_another").get<std::string>(),
|
||||
"namespace_wild_another");
|
||||
EXPECT_EQ(parameter_overrides.at("node_wild_no_ns").get<std::string>(), "node_wild_no_ns");
|
||||
EXPECT_EQ(parameter_overrides.at("explicit_no_ns").get<std::string>(), "explicit_no_ns");
|
||||
EXPECT_EQ(parameter_overrides.count("should_not_appear"), 0u);
|
||||
// "/*" match exactly one token, not expect to get `namespace_wild_one_star`
|
||||
EXPECT_EQ(parameter_overrides.count("namespace_wild_one_star"), 0u);
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, params_by_order)
|
||||
{
|
||||
rclcpp::NodeOptions opts;
|
||||
opts.arguments(
|
||||
{
|
||||
"--ros-args",
|
||||
"--params-file", (test_resources_path / "params_by_order.yaml").string()
|
||||
});
|
||||
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node2", "ns", opts);
|
||||
|
||||
auto * node_parameters =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||
node->get_node_parameters_interface().get());
|
||||
ASSERT_NE(nullptr, node_parameters);
|
||||
|
||||
const auto & parameter_overrides = node_parameters->get_parameter_overrides();
|
||||
EXPECT_EQ(3u, parameter_overrides.size());
|
||||
EXPECT_EQ(parameter_overrides.at("a_value").get<std::string>(), "last_one_win");
|
||||
EXPECT_EQ(parameter_overrides.at("foo").get<std::string>(), "foo");
|
||||
EXPECT_EQ(parameter_overrides.at("bar").get<std::string>(), "bar");
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, complicated_wildcards)
|
||||
{
|
||||
rclcpp::NodeOptions opts;
|
||||
opts.arguments(
|
||||
{
|
||||
"--ros-args",
|
||||
"--params-file", (test_resources_path / "complicated_wildcards.yaml").string()
|
||||
});
|
||||
|
||||
{
|
||||
// regex matched: /**/foo/*/bar
|
||||
std::shared_ptr<rclcpp::Node> node =
|
||||
std::make_shared<rclcpp::Node>("node2", "/a/b/c/foo/d/bar", opts);
|
||||
|
||||
auto * node_parameters =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||
node->get_node_parameters_interface().get());
|
||||
ASSERT_NE(nullptr, node_parameters);
|
||||
|
||||
const auto & parameter_overrides = node_parameters->get_parameter_overrides();
|
||||
EXPECT_EQ(2u, parameter_overrides.size());
|
||||
EXPECT_EQ(parameter_overrides.at("foo").get<std::string>(), "foo");
|
||||
EXPECT_EQ(parameter_overrides.at("bar").get<std::string>(), "bar");
|
||||
}
|
||||
|
||||
{
|
||||
// regex not matched: /**/foo/*/bar
|
||||
std::shared_ptr<rclcpp::Node> node =
|
||||
std::make_shared<rclcpp::Node>("node2", "/a/b/c/foo/bar", opts);
|
||||
|
||||
auto * node_parameters =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||
node->get_node_parameters_interface().get());
|
||||
ASSERT_NE(nullptr, node_parameters);
|
||||
|
||||
const auto & parameter_overrides = node_parameters->get_parameter_overrides();
|
||||
EXPECT_EQ(0u, parameter_overrides.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ protected:
|
||||
|
||||
services_.push_back(
|
||||
node_with_service->create_service<test_msgs::srv::Empty>(
|
||||
"service", std::move(service_callback), rmw_qos_profile_services_default, callback_group));
|
||||
"service", std::move(service_callback), rclcpp::ServicesQoS(), callback_group));
|
||||
return node_with_service;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ protected:
|
||||
|
||||
clients_.push_back(
|
||||
node_with_client->create_client<test_msgs::srv::Empty>(
|
||||
"service", rmw_qos_profile_services_default, callback_group));
|
||||
"service", rclcpp::ServicesQoS(), callback_group));
|
||||
return node_with_client;
|
||||
}
|
||||
|
||||
@@ -793,7 +793,7 @@ TEST_F(TestAllocatorMemoryStrategy, get_next_service_out_of_scope) {
|
||||
[](const test_msgs::srv::Empty::Request::SharedPtr,
|
||||
test_msgs::srv::Empty::Response::SharedPtr) {};
|
||||
auto service = node->create_service<test_msgs::srv::Empty>(
|
||||
"service", std::move(service_callback), rmw_qos_profile_services_default, callback_group);
|
||||
"service", std::move(service_callback), rclcpp::ServicesQoS(), callback_group);
|
||||
|
||||
node->for_each_callback_group(
|
||||
[node, &weak_groups_to_nodes](rclcpp::CallbackGroup::SharedPtr group_ptr)
|
||||
@@ -831,7 +831,7 @@ TEST_F(TestAllocatorMemoryStrategy, get_next_client_out_of_scope) {
|
||||
node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
auto client = node->create_client<test_msgs::srv::Empty>(
|
||||
"service", rmw_qos_profile_services_default, callback_group);
|
||||
"service", rclcpp::ServicesQoS(), callback_group);
|
||||
|
||||
weak_groups_to_nodes.insert(
|
||||
std::pair<rclcpp::CallbackGroup::WeakPtr,
|
||||
|
||||
@@ -93,6 +93,111 @@ TEST_F(TestAnySubscriptionCallback, construct_destruct) {
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc2(allocator);
|
||||
}
|
||||
|
||||
TEST_F(TestAnySubscriptionCallback, is_serialized_message_callback) {
|
||||
{
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc;
|
||||
asc.set([](const rclcpp::SerializedMessage &) {});
|
||||
EXPECT_TRUE(asc.is_serialized_message_callback());
|
||||
EXPECT_NO_THROW(
|
||||
asc.dispatch(
|
||||
std::make_shared<rclcpp::SerializedMessage>(),
|
||||
rclcpp::MessageInfo{}));
|
||||
}
|
||||
{
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc;
|
||||
asc.set([](const rclcpp::SerializedMessage &, const rclcpp::MessageInfo &) {});
|
||||
EXPECT_TRUE(asc.is_serialized_message_callback());
|
||||
EXPECT_NO_THROW(
|
||||
asc.dispatch(
|
||||
std::make_shared<rclcpp::SerializedMessage>(),
|
||||
rclcpp::MessageInfo{}));
|
||||
}
|
||||
{
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc;
|
||||
asc.set([](const rclcpp::SerializedMessage &, const rclcpp::MessageInfo &) {});
|
||||
EXPECT_TRUE(asc.is_serialized_message_callback());
|
||||
EXPECT_NO_THROW(
|
||||
asc.dispatch(
|
||||
std::make_shared<rclcpp::SerializedMessage>(),
|
||||
rclcpp::MessageInfo{}));
|
||||
}
|
||||
{
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc;
|
||||
asc.set([](std::unique_ptr<rclcpp::SerializedMessage>) {});
|
||||
EXPECT_TRUE(asc.is_serialized_message_callback());
|
||||
EXPECT_NO_THROW(
|
||||
asc.dispatch(
|
||||
std::make_shared<rclcpp::SerializedMessage>(),
|
||||
rclcpp::MessageInfo{}));
|
||||
}
|
||||
{
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc;
|
||||
asc.set([](std::unique_ptr<rclcpp::SerializedMessage>, const rclcpp::MessageInfo &) {});
|
||||
EXPECT_TRUE(asc.is_serialized_message_callback());
|
||||
EXPECT_NO_THROW(
|
||||
asc.dispatch(
|
||||
std::make_shared<rclcpp::SerializedMessage>(),
|
||||
rclcpp::MessageInfo{}));
|
||||
}
|
||||
{
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc;
|
||||
asc.set([](std::shared_ptr<const rclcpp::SerializedMessage>) {});
|
||||
EXPECT_TRUE(asc.is_serialized_message_callback());
|
||||
EXPECT_NO_THROW(
|
||||
asc.dispatch(
|
||||
std::make_shared<rclcpp::SerializedMessage>(),
|
||||
rclcpp::MessageInfo{}));
|
||||
}
|
||||
{
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc;
|
||||
asc.set([](std::shared_ptr<const rclcpp::SerializedMessage>, const rclcpp::MessageInfo &) {});
|
||||
EXPECT_TRUE(asc.is_serialized_message_callback());
|
||||
EXPECT_NO_THROW(
|
||||
asc.dispatch(
|
||||
std::make_shared<rclcpp::SerializedMessage>(),
|
||||
rclcpp::MessageInfo{}));
|
||||
}
|
||||
{
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc;
|
||||
asc.set([](const std::shared_ptr<const rclcpp::SerializedMessage> &) {});
|
||||
EXPECT_TRUE(asc.is_serialized_message_callback());
|
||||
EXPECT_NO_THROW(
|
||||
asc.dispatch(
|
||||
std::make_shared<rclcpp::SerializedMessage>(),
|
||||
rclcpp::MessageInfo{}));
|
||||
}
|
||||
{
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc;
|
||||
asc.set(
|
||||
[](
|
||||
const std::shared_ptr<const rclcpp::SerializedMessage> &,
|
||||
const rclcpp::MessageInfo &) {});
|
||||
EXPECT_TRUE(asc.is_serialized_message_callback());
|
||||
EXPECT_NO_THROW(
|
||||
asc.dispatch(
|
||||
std::make_shared<rclcpp::SerializedMessage>(),
|
||||
rclcpp::MessageInfo{}));
|
||||
}
|
||||
{
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc;
|
||||
asc.set([](std::shared_ptr<rclcpp::SerializedMessage>) {});
|
||||
EXPECT_TRUE(asc.is_serialized_message_callback());
|
||||
EXPECT_NO_THROW(
|
||||
asc.dispatch(
|
||||
std::make_shared<rclcpp::SerializedMessage>(),
|
||||
rclcpp::MessageInfo{}));
|
||||
}
|
||||
{
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty> asc;
|
||||
asc.set([](std::shared_ptr<rclcpp::SerializedMessage>, const rclcpp::MessageInfo &) {});
|
||||
EXPECT_TRUE(asc.is_serialized_message_callback());
|
||||
EXPECT_NO_THROW(
|
||||
asc.dispatch(
|
||||
std::make_shared<rclcpp::SerializedMessage>(),
|
||||
rclcpp::MessageInfo{}));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestAnySubscriptionCallback, unset_dispatch_throw) {
|
||||
EXPECT_THROW(
|
||||
any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_),
|
||||
|
||||
@@ -92,6 +92,30 @@ TEST_F(TestClient, construction_and_destruction) {
|
||||
{
|
||||
auto client = node->create_client<ListParameters>("service");
|
||||
}
|
||||
{
|
||||
// suppress deprecated function warning
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
auto client = node->create_client<ListParameters>(
|
||||
"service", rmw_qos_profile_services_default);
|
||||
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
{
|
||||
auto client = node->create_client<ListParameters>(
|
||||
"service", rclcpp::ServicesQoS());
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(
|
||||
@@ -123,6 +147,27 @@ TEST_F(TestClient, construction_with_free_function) {
|
||||
nullptr);
|
||||
}, rclcpp::exceptions::InvalidServiceNameError);
|
||||
}
|
||||
{
|
||||
auto client = rclcpp::create_client<rcl_interfaces::srv::ListParameters>(
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface(),
|
||||
"service",
|
||||
rclcpp::ServicesQoS(),
|
||||
nullptr);
|
||||
}
|
||||
{
|
||||
ASSERT_THROW(
|
||||
{
|
||||
auto client = rclcpp::create_client<rcl_interfaces::srv::ListParameters>(
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface(),
|
||||
"invalid_?service",
|
||||
rclcpp::ServicesQoS(),
|
||||
nullptr);
|
||||
}, rclcpp::exceptions::InvalidServiceNameError);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestClient, construct_with_rcl_error) {
|
||||
@@ -351,8 +396,8 @@ TEST_F(TestClient, on_new_response_callback) {
|
||||
auto client_node = std::make_shared<rclcpp::Node>("client_node", "ns");
|
||||
auto server_node = std::make_shared<rclcpp::Node>("server_node", "ns");
|
||||
|
||||
rmw_qos_profile_t client_qos = rmw_qos_profile_services_default;
|
||||
client_qos.depth = 3;
|
||||
rclcpp::ServicesQoS client_qos;
|
||||
client_qos.keep_last(3);
|
||||
auto client = client_node->create_client<test_msgs::srv::Empty>("test_service", client_qos);
|
||||
std::atomic<size_t> server_requests_count {0};
|
||||
auto server_callback = [&server_requests_count](
|
||||
@@ -455,32 +500,30 @@ TEST_F(TestClient, rcl_client_response_subscription_get_actual_qos_error) {
|
||||
}
|
||||
|
||||
TEST_F(TestClient, client_qos) {
|
||||
rmw_qos_profile_t qos_profile = rmw_qos_profile_services_default;
|
||||
qos_profile.liveliness = RMW_QOS_POLICY_LIVELINESS_AUTOMATIC;
|
||||
uint64_t duration = 1;
|
||||
qos_profile.deadline = {duration, duration};
|
||||
qos_profile.lifespan = {duration, duration};
|
||||
qos_profile.liveliness_lease_duration = {duration, duration};
|
||||
rclcpp::ServicesQoS qos_profile;
|
||||
qos_profile.liveliness(rclcpp::LivelinessPolicy::Automatic);
|
||||
rclcpp::Duration duration(std::chrono::nanoseconds(1));
|
||||
qos_profile.deadline(duration);
|
||||
qos_profile.lifespan(duration);
|
||||
qos_profile.liveliness_lease_duration(duration);
|
||||
|
||||
auto client =
|
||||
node->create_client<test_msgs::srv::Empty>("client", qos_profile);
|
||||
|
||||
auto init_qos =
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile), qos_profile);
|
||||
auto rp_qos = client->get_request_publisher_actual_qos();
|
||||
auto rs_qos = client->get_response_subscription_actual_qos();
|
||||
|
||||
EXPECT_EQ(init_qos, rp_qos);
|
||||
EXPECT_EQ(qos_profile, rp_qos);
|
||||
// Lifespan has no meaning for subscription/readers
|
||||
rs_qos.lifespan(qos_profile.lifespan);
|
||||
EXPECT_EQ(init_qos, rs_qos);
|
||||
rs_qos.lifespan(qos_profile.lifespan());
|
||||
EXPECT_EQ(qos_profile, rs_qos);
|
||||
}
|
||||
|
||||
TEST_F(TestClient, client_qos_depth) {
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
rmw_qos_profile_t client_qos_profile = rmw_qos_profile_default;
|
||||
client_qos_profile.depth = 2;
|
||||
rclcpp::ServicesQoS client_qos_profile;
|
||||
client_qos_profile.keep_last(2);
|
||||
|
||||
auto client = node->create_client<test_msgs::srv::Empty>("test_qos_depth", client_qos_profile);
|
||||
|
||||
@@ -491,10 +534,10 @@ TEST_F(TestClient, client_qos_depth) {
|
||||
|
||||
auto server_node = std::make_shared<rclcpp::Node>("server_node", "/ns");
|
||||
|
||||
rmw_qos_profile_t server_qos_profile = rmw_qos_profile_default;
|
||||
rclcpp::QoS server_qos(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_default));
|
||||
|
||||
auto server = server_node->create_service<test_msgs::srv::Empty>(
|
||||
"test_qos_depth", std::move(server_callback), server_qos_profile);
|
||||
"test_qos_depth", std::move(server_callback), server_qos);
|
||||
|
||||
auto request = std::make_shared<test_msgs::srv::Empty::Request>();
|
||||
::testing::AssertionResult request_result = ::testing::AssertionSuccess();
|
||||
@@ -522,10 +565,10 @@ TEST_F(TestClient, client_qos_depth) {
|
||||
std::this_thread::sleep_for(2ms);
|
||||
}
|
||||
|
||||
EXPECT_GT(server_cb_count_, client_qos_profile.depth);
|
||||
EXPECT_GT(server_cb_count_, client_qos_profile.depth());
|
||||
|
||||
start = std::chrono::steady_clock::now();
|
||||
while ((client_cb_count_ < client_qos_profile.depth) &&
|
||||
while ((client_cb_count_ < client_qos_profile.depth()) &&
|
||||
(std::chrono::steady_clock::now() - start) < 1s)
|
||||
{
|
||||
rclcpp::spin_some(node);
|
||||
@@ -535,5 +578,5 @@ TEST_F(TestClient, client_qos_depth) {
|
||||
// so more client callbacks might be called than expected.
|
||||
rclcpp::spin_some(node);
|
||||
|
||||
EXPECT_EQ(client_cb_count_, client_qos_profile.depth);
|
||||
EXPECT_EQ(client_cb_count_, client_qos_profile.depth());
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ TEST(TestCreateTimer, call_with_node_wrapper_compiles)
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
TEST(TestCreateTimer, call_wall_timer_with_bad_arguments)
|
||||
TEST(TestCreateWallTimer, call_wall_timer_with_bad_arguments)
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
NodeWrapper node("test_create_wall_timers_with_bad_arguments");
|
||||
@@ -116,3 +116,80 @@ TEST(TestCreateTimer, call_wall_timer_with_bad_arguments)
|
||||
std::invalid_argument);
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
TEST(TestCreateTimer, call_timer_with_bad_arguments)
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
NodeWrapper node("test_create_timers_with_bad_arguments");
|
||||
auto callback = []() {};
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr;
|
||||
auto node_interface =
|
||||
rclcpp::node_interfaces::get_node_base_interface(node).get();
|
||||
auto timers_interface =
|
||||
rclcpp::node_interfaces::get_node_timers_interface(node).get();
|
||||
|
||||
auto clock = node.get_node_clock_interface()->get_clock();
|
||||
|
||||
// Negative period
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_timer(
|
||||
clock, -1ms, callback, group, node_interface, timers_interface),
|
||||
std::invalid_argument);
|
||||
|
||||
// Very negative period
|
||||
constexpr auto nanoseconds_min = std::chrono::nanoseconds::min();
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_timer(
|
||||
clock, nanoseconds_min, callback, group, node_interface, timers_interface),
|
||||
std::invalid_argument);
|
||||
|
||||
// Period must be less than nanoseconds::max()
|
||||
constexpr auto nanoseconds_max = std::chrono::nanoseconds::min();
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_timer(
|
||||
clock, nanoseconds_max, callback, group, node_interface, timers_interface),
|
||||
std::invalid_argument);
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
rclcpp::create_timer(
|
||||
clock, nanoseconds_max - 1us, callback, group, node_interface, timers_interface));
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
rclcpp::create_timer(clock, 0ms, callback, group, node_interface, timers_interface));
|
||||
|
||||
// Period must be less than nanoseconds::max()
|
||||
constexpr auto hours_max = std::chrono::hours::max();
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_timer(
|
||||
clock, hours_max, callback, group, node_interface, timers_interface),
|
||||
std::invalid_argument);
|
||||
|
||||
// node_interface is null
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_timer(clock, 1ms, callback, group, nullptr, timers_interface),
|
||||
std::invalid_argument);
|
||||
|
||||
// timers_interface is null
|
||||
EXPECT_THROW(
|
||||
rclcpp::create_timer(clock, 1ms, callback, group, node_interface, nullptr),
|
||||
std::invalid_argument);
|
||||
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
static void test_timer_callback(void) {}
|
||||
|
||||
TEST(TestCreateTimer, timer_function_pointer)
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
auto node = std::make_shared<rclcpp::Node>("timer_function_pointer_node");
|
||||
|
||||
// make sure build succeeds with function pointer instead of lambda
|
||||
auto some_timer = rclcpp::create_timer(
|
||||
node,
|
||||
node->get_clock(),
|
||||
rclcpp::Duration(0ms),
|
||||
test_timer_callback);
|
||||
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
@@ -52,9 +52,23 @@ TEST_F(TestDuration, operators) {
|
||||
EXPECT_EQ(sub.nanoseconds(), young.nanoseconds() - old.nanoseconds());
|
||||
EXPECT_EQ(sub, young - old);
|
||||
|
||||
rclcpp::Duration addequal = old;
|
||||
addequal += young;
|
||||
EXPECT_EQ(addequal.nanoseconds(), old.nanoseconds() + young.nanoseconds());
|
||||
EXPECT_EQ(addequal, old + young);
|
||||
|
||||
rclcpp::Duration subequal = young;
|
||||
subequal -= old;
|
||||
EXPECT_EQ(subequal.nanoseconds(), young.nanoseconds() - old.nanoseconds());
|
||||
EXPECT_EQ(subequal, young - old);
|
||||
|
||||
rclcpp::Duration scale = old * 3;
|
||||
EXPECT_EQ(scale.nanoseconds(), old.nanoseconds() * 3);
|
||||
|
||||
rclcpp::Duration scaleequal = old;
|
||||
scaleequal *= 3;
|
||||
EXPECT_EQ(scaleequal.nanoseconds(), old.nanoseconds() * 3);
|
||||
|
||||
rclcpp::Duration time = rclcpp::Duration(0, 0);
|
||||
rclcpp::Duration copy_constructor_duration(time);
|
||||
rclcpp::Duration assignment_op_duration = rclcpp::Duration(1, 0);
|
||||
|
||||
@@ -190,7 +190,7 @@ TEST_F(RclcppGenericNodeFixture, publish_loaned_msg_work)
|
||||
|
||||
if (publisher->can_loan_messages()) {
|
||||
auto subscriber_future_ = std::async(
|
||||
std::launch::deferred, [this, topic_name, type] {
|
||||
std::launch::async, [this, topic_name, type] {
|
||||
return subscribe_raw_messages<int64_t, test_msgs::msg::BasicTypes>(
|
||||
1, topic_name, type);
|
||||
});
|
||||
|
||||
@@ -164,3 +164,21 @@ TEST_F(TestGuardCondition, set_on_trigger_callback) {
|
||||
EXPECT_EQ(c1.load(), 2u);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Testing that callback and waitset are both notified by triggering gc
|
||||
*/
|
||||
TEST_F(TestGuardCondition, callback_and_waitset) {
|
||||
auto gc = std::make_shared<rclcpp::GuardCondition>();
|
||||
std::atomic<size_t> c1 {0};
|
||||
auto increase_c1_cb = [&c1](size_t count_msgs) {c1 += count_msgs;};
|
||||
gc->set_on_trigger_callback(increase_c1_cb);
|
||||
|
||||
rclcpp::WaitSet wait_set;
|
||||
wait_set.add_guard_condition(gc);
|
||||
|
||||
gc->trigger();
|
||||
|
||||
EXPECT_EQ(rclcpp::WaitResultKind::Ready, wait_set.wait(std::chrono::seconds(1)).kind());
|
||||
EXPECT_EQ(c1.load(), 1u);
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ TEST_F(TestMemoryStrategy, get_service_by_handle) {
|
||||
{
|
||||
auto service = node->create_service<test_msgs::srv::Empty>(
|
||||
"service", std::move(service_callback),
|
||||
rmw_qos_profile_services_default, callback_group);
|
||||
rclcpp::ServicesQoS(), callback_group);
|
||||
|
||||
service_handle = service->get_service_handle();
|
||||
|
||||
@@ -197,7 +197,7 @@ TEST_F(TestMemoryStrategy, get_client_by_handle) {
|
||||
node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
{
|
||||
auto client = node->create_client<test_msgs::srv::Empty>(
|
||||
"service", rmw_qos_profile_services_default, callback_group);
|
||||
"service", rclcpp::ServicesQoS(), callback_group);
|
||||
|
||||
client_handle = client->get_client_handle();
|
||||
weak_groups_to_nodes.insert(
|
||||
@@ -396,7 +396,7 @@ TEST_F(TestMemoryStrategy, get_group_by_service) {
|
||||
|
||||
service = node->create_service<test_msgs::srv::Empty>(
|
||||
"service", std::move(service_callback),
|
||||
rmw_qos_profile_services_default, callback_group);
|
||||
rclcpp::ServicesQoS(), callback_group);
|
||||
weak_groups_to_nodes.insert(
|
||||
std::pair<rclcpp::CallbackGroup::WeakPtr,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>(
|
||||
@@ -435,7 +435,7 @@ TEST_F(TestMemoryStrategy, get_group_by_client) {
|
||||
node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
client = node->create_client<test_msgs::srv::Empty>(
|
||||
"service", rmw_qos_profile_services_default, callback_group);
|
||||
"service", rclcpp::ServicesQoS(), callback_group);
|
||||
weak_groups_to_nodes.insert(
|
||||
std::pair<rclcpp::CallbackGroup::WeakPtr,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>(
|
||||
|
||||
@@ -1444,6 +1444,36 @@ TEST_F(TestNode, set_parameter_undeclared_parameters_not_allowed) {
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_STRING);
|
||||
EXPECT_EQ(value.get_value<std::string>(), "asd");
|
||||
}
|
||||
{
|
||||
// adding a parameter in "pre set parameter" callback, when that
|
||||
// parameter has not been declared before will throw
|
||||
auto name1 = "parameter"_unq;
|
||||
auto name2 = "parameter"_unq;
|
||||
auto default_value = 0; // default value of name1 param
|
||||
|
||||
// declare name1 parameter only
|
||||
node->declare_parameter(name1, default_value);
|
||||
|
||||
// add undeclared parameter with name2 to modified list of parameters
|
||||
auto pre_set_parameters =
|
||||
[&](std::vector<rclcpp::Parameter> & parameters) {
|
||||
for (const auto & param : parameters) {
|
||||
if (param.get_name() == name1) {
|
||||
parameters.emplace_back(rclcpp::Parameter(name2, 2));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto handler = node->add_pre_set_parameters_callback(pre_set_parameters);
|
||||
EXPECT_THROW(
|
||||
node->set_parameter(rclcpp::Parameter(name1, 4)),
|
||||
rclcpp::exceptions::ParameterNotDeclaredException);
|
||||
EXPECT_TRUE(node->has_parameter(name1));
|
||||
EXPECT_EQ(node->get_parameter(name1).get_value<int>(), default_value);
|
||||
EXPECT_FALSE(node->has_parameter(name2));
|
||||
RCPPUTILS_SCOPE_EXIT(
|
||||
{node->remove_pre_set_parameters_callback(handler.get());}); // always reset
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestNode, set_parameter_undeclared_parameters_allowed) {
|
||||
@@ -1481,6 +1511,36 @@ TEST_F(TestNode, set_parameter_undeclared_parameters_allowed) {
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<int>(), 43);
|
||||
}
|
||||
{
|
||||
// adding a parameter in "pre set parameter" callback, when that
|
||||
// parameter has not been declared will not throw if undeclared
|
||||
// parameters are allowed
|
||||
auto name1 = "parameter"_unq;
|
||||
auto name2 = "parameter"_unq;
|
||||
|
||||
// declare name1 parameter only
|
||||
node->declare_parameter(name1, 0);
|
||||
|
||||
// add undeclared parameter with name2 to modified list of parameters
|
||||
auto pre_set_parameters =
|
||||
[&](std::vector<rclcpp::Parameter> & parameters) {
|
||||
for (const auto & param : parameters) {
|
||||
if (param.get_name() == name1) {
|
||||
parameters.emplace_back(rclcpp::Parameter(name2, 2));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto handler = node->add_pre_set_parameters_callback(pre_set_parameters);
|
||||
auto result = node->set_parameter(rclcpp::Parameter(name1, 1));
|
||||
EXPECT_TRUE(result.successful);
|
||||
EXPECT_TRUE(node->has_parameter(name1));
|
||||
EXPECT_TRUE(node->has_parameter(name2));
|
||||
EXPECT_EQ(node->get_parameter(name1).get_value<int>(), 1);
|
||||
EXPECT_EQ(node->get_parameter(name2).get_value<int>(), 2);
|
||||
RCPPUTILS_SCOPE_EXIT(
|
||||
{node->remove_pre_set_parameters_callback(handler.get());}); // always reset
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestNode, set_parameters_undeclared_parameters_not_allowed) {
|
||||
@@ -1625,6 +1685,51 @@ TEST_F(TestNode, set_parameters_undeclared_parameters_not_allowed) {
|
||||
|
||||
EXPECT_FALSE(node->has_parameter(name));
|
||||
}
|
||||
{
|
||||
// adding a parameter in "pre set parameter" callback when that
|
||||
// parameter has not been declared before will throw. However, when
|
||||
// multiple params are being set using "set_parameters", the params
|
||||
// which are not conditioned on each other in "pre set callback" will
|
||||
// still be set successfully. This is the desired behaviour since
|
||||
// "set_parameters" sets params non atomically.
|
||||
auto name1 = "parameter"_unq;
|
||||
auto name2 = "parameter"_unq;
|
||||
auto name3 = "parameter"_unq;
|
||||
auto default_value = 0;
|
||||
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.type = rclcpp::PARAMETER_INTEGER;
|
||||
|
||||
// declare name1 and name2 parameter only
|
||||
node->declare_parameter(name1, default_value, descriptor);
|
||||
node->declare_parameter(name2, default_value, descriptor);
|
||||
|
||||
// add undeclared parameter with name3 to modified list of parameters
|
||||
// conditioned of name2 param
|
||||
auto pre_set_parameters =
|
||||
[&](std::vector<rclcpp::Parameter> & parameters) {
|
||||
for (const auto & param : parameters) {
|
||||
if (param.get_name() == name2) {
|
||||
parameters.emplace_back(rclcpp::Parameter(name3, 3));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto handler = node->add_pre_set_parameters_callback(pre_set_parameters);
|
||||
EXPECT_THROW(
|
||||
node->set_parameters({rclcpp::Parameter(name1, 1), rclcpp::Parameter(name2, 2)}),
|
||||
rclcpp::exceptions::ParameterNotDeclaredException);
|
||||
EXPECT_TRUE(node->has_parameter(name1));
|
||||
EXPECT_TRUE(node->has_parameter(name2));
|
||||
EXPECT_FALSE(node->has_parameter(name3));
|
||||
|
||||
// we still expect the value of name1 param to be set successfully, since
|
||||
// the setting of name2 param is only conditioned on setting of name3 param
|
||||
EXPECT_EQ(node->get_parameter(name1).get_value<int>(), 1);
|
||||
EXPECT_EQ(node->get_parameter(name2).get_value<int>(), default_value);
|
||||
RCPPUTILS_SCOPE_EXIT(
|
||||
{node->remove_pre_set_parameters_callback(handler.get());}); // always reset
|
||||
}
|
||||
}
|
||||
|
||||
// test set_parameters with undeclared allowed
|
||||
@@ -1673,6 +1778,48 @@ TEST_F(TestNode, set_parameters_undeclared_parameters_allowed) {
|
||||
EXPECT_EQ(node->get_parameter(name1).get_value<int>(), 42);
|
||||
EXPECT_EQ(node->get_parameter(name2).get_value<std::string>(), "test");
|
||||
}
|
||||
{
|
||||
// adding a parameter in "pre set parameter" callback when that
|
||||
// parameter has not been declared before will not throw when
|
||||
// undeclared parameters are allowed.
|
||||
auto name1 = "parameter"_unq;
|
||||
auto name2 = "parameter"_unq;
|
||||
auto name3 = "parameter"_unq;
|
||||
auto default_value = 0;
|
||||
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.type = rclcpp::PARAMETER_INTEGER;
|
||||
|
||||
// declare name1 and name2 parameter only
|
||||
node->declare_parameter(name1, default_value, descriptor);
|
||||
node->declare_parameter(name2, default_value, descriptor);
|
||||
|
||||
// add undeclared parameter with name3 to modified list of parameters
|
||||
// conditioned of name2 param
|
||||
auto pre_set_parameters =
|
||||
[&](std::vector<rclcpp::Parameter> & parameters) {
|
||||
for (const auto & param : parameters) {
|
||||
if (param.get_name() == name2) {
|
||||
parameters.emplace_back(rclcpp::Parameter(name3, 3));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto handler = node->add_pre_set_parameters_callback(pre_set_parameters);
|
||||
auto results = node->set_parameters({rclcpp::Parameter(name1, 1), rclcpp::Parameter(name2, 2)});
|
||||
EXPECT_EQ(2u, results.size());
|
||||
EXPECT_TRUE(results[0].successful);
|
||||
EXPECT_TRUE(results[1].successful);
|
||||
EXPECT_TRUE(node->has_parameter(name1));
|
||||
EXPECT_TRUE(node->has_parameter(name2));
|
||||
EXPECT_TRUE(node->has_parameter(name3));
|
||||
EXPECT_EQ(node->get_parameter(name1).get_value<int>(), 1);
|
||||
EXPECT_EQ(node->get_parameter(name2).get_value<int>(), 2);
|
||||
EXPECT_EQ(node->get_parameter(name3).get_value<int>(), 3);
|
||||
|
||||
RCPPUTILS_SCOPE_EXIT(
|
||||
{node->remove_pre_set_parameters_callback(handler.get());}); // always reset
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestNode, set_parameters_atomically_undeclared_parameters_not_allowed) {
|
||||
@@ -1815,6 +1962,48 @@ TEST_F(TestNode, set_parameters_atomically_undeclared_parameters_not_allowed) {
|
||||
|
||||
EXPECT_FALSE(node->has_parameter(name));
|
||||
}
|
||||
{
|
||||
// adding a parameter in "pre set parameter" callback when that
|
||||
// parameter has not been declared before will throw and since
|
||||
// multiple params are being set using "set_parameters_atomically",
|
||||
// a failure in set of one param will result in all params being
|
||||
// set unsuccessfully.
|
||||
auto name1 = "parameter"_unq;
|
||||
auto name2 = "parameter"_unq;
|
||||
auto name3 = "parameter"_unq;
|
||||
auto default_value = 0;
|
||||
|
||||
// declare name1 and name2 parameter only
|
||||
node->declare_parameter(name1, default_value);
|
||||
node->declare_parameter(name2, default_value);
|
||||
|
||||
// add undeclared parameter with name3 to modified list of parameters
|
||||
// conditioned of name2 param
|
||||
auto pre_set_parameters =
|
||||
[&](std::vector<rclcpp::Parameter> & parameters) {
|
||||
for (const auto & param : parameters) {
|
||||
if (param.get_name() == name2) {
|
||||
parameters.emplace_back(rclcpp::Parameter(name3, 3));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto handler = node->add_pre_set_parameters_callback(pre_set_parameters);
|
||||
EXPECT_THROW(
|
||||
node->set_parameters_atomically(
|
||||
{rclcpp::Parameter(name1, 1),
|
||||
rclcpp::Parameter(name2, 2)}),
|
||||
rclcpp::exceptions::ParameterNotDeclaredException);
|
||||
EXPECT_TRUE(node->has_parameter(name1));
|
||||
EXPECT_TRUE(node->has_parameter(name2));
|
||||
EXPECT_FALSE(node->has_parameter(name3));
|
||||
|
||||
// the values of all the params is still default.
|
||||
EXPECT_EQ(node->get_parameter(name1).get_value<int>(), default_value);
|
||||
EXPECT_EQ(node->get_parameter(name2).get_value<int>(), default_value);
|
||||
RCPPUTILS_SCOPE_EXIT(
|
||||
{node->remove_pre_set_parameters_callback(handler.get());}); // always reset
|
||||
}
|
||||
}
|
||||
|
||||
// test set_parameters with undeclared allowed
|
||||
@@ -1903,6 +2092,45 @@ TEST_F(TestNode, set_parameters_atomically_undeclared_parameters_allowed) {
|
||||
EXPECT_FALSE(node->has_parameter(name2)); // important! name2 remains undeclared
|
||||
EXPECT_EQ(node->get_parameter(name3).get_value<std::string>(), "test");
|
||||
}
|
||||
{
|
||||
// adding a parameter in "pre set parameter" callback when that
|
||||
// parameter has not been declared before will not throw when
|
||||
// undeclared parameters are allowed.
|
||||
auto name1 = "parameter"_unq;
|
||||
auto name2 = "parameter"_unq;
|
||||
auto name3 = "parameter"_unq;
|
||||
auto default_value = 0;
|
||||
|
||||
// declare name1 and name2 parameter only
|
||||
node->declare_parameter(name1, default_value);
|
||||
node->declare_parameter(name2, default_value);
|
||||
|
||||
// add undeclared parameter with name3 to modified list of parameters
|
||||
// conditioned of name2 param
|
||||
auto pre_set_parameters =
|
||||
[&](std::vector<rclcpp::Parameter> & parameters) {
|
||||
for (const auto & param : parameters) {
|
||||
if (param.get_name() == name2) {
|
||||
parameters.emplace_back(rclcpp::Parameter(name3, 3));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto handler = node->add_pre_set_parameters_callback(pre_set_parameters);
|
||||
auto result = node->set_parameters_atomically(
|
||||
{rclcpp::Parameter(name1, 1),
|
||||
rclcpp::Parameter(name2, 2)});
|
||||
EXPECT_TRUE(result.successful);
|
||||
EXPECT_TRUE(node->has_parameter(name1));
|
||||
EXPECT_TRUE(node->has_parameter(name2));
|
||||
EXPECT_TRUE(node->has_parameter(name3));
|
||||
EXPECT_EQ(node->get_parameter(name1).get_value<int>(), 1);
|
||||
EXPECT_EQ(node->get_parameter(name2).get_value<int>(), 2);
|
||||
EXPECT_EQ(node->get_parameter(name3).get_value<int>(), 3);
|
||||
|
||||
RCPPUTILS_SCOPE_EXIT(
|
||||
{node->remove_pre_set_parameters_callback(handler.get());}); // always reset
|
||||
}
|
||||
}
|
||||
|
||||
// test get_parameter with undeclared not allowed
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
@@ -948,3 +948,138 @@ TEST_F(TestParameterClient, sync_parameter_load_parameters) {
|
||||
auto list_parameters = synchronous_client->list_parameters({}, 3);
|
||||
ASSERT_EQ(list_parameters.names.size(), static_cast<uint64_t>(5));
|
||||
}
|
||||
|
||||
/*
|
||||
Coverage for async load_parameters with complicated regex expression
|
||||
*/
|
||||
TEST_F(TestParameterClient, async_parameter_load_parameters_complicated_regex) {
|
||||
auto load_node = std::make_shared<rclcpp::Node>(
|
||||
"load_node",
|
||||
"namespace",
|
||||
rclcpp::NodeOptions().allow_undeclared_parameters(true));
|
||||
auto asynchronous_client =
|
||||
std::make_shared<rclcpp::AsyncParametersClient>(load_node, "/namespace/load_node");
|
||||
// load parameters
|
||||
rcpputils::fs::path test_resources_path{TEST_RESOURCES_DIRECTORY};
|
||||
const std::string parameters_filepath = (
|
||||
test_resources_path / "test_node" / "load_complicated_parameters.yaml").string();
|
||||
auto load_future = asynchronous_client->load_parameters(parameters_filepath);
|
||||
auto result_code = rclcpp::spin_until_future_complete(
|
||||
load_node, load_future, std::chrono::milliseconds(100));
|
||||
ASSERT_EQ(result_code, rclcpp::FutureReturnCode::SUCCESS);
|
||||
ASSERT_EQ(load_future.get()[0].successful, true);
|
||||
// list parameters
|
||||
auto list_parameters = asynchronous_client->list_parameters({}, 3);
|
||||
rclcpp::spin_until_future_complete(
|
||||
load_node, list_parameters, std::chrono::milliseconds(100));
|
||||
ASSERT_EQ(list_parameters.get().names.size(), static_cast<uint64_t>(6));
|
||||
// to check the parameter "a_value"
|
||||
std::string param_name = "a_value";
|
||||
auto param = load_node->get_parameter(param_name);
|
||||
ASSERT_EQ(param.get_value<std::string>(), "last_one_win");
|
||||
}
|
||||
|
||||
/*
|
||||
Coverage for async load_parameters to load file without valid parameters
|
||||
*/
|
||||
TEST_F(TestParameterClient, async_parameter_load_no_valid_parameter) {
|
||||
auto load_node = std::make_shared<rclcpp::Node>(
|
||||
"load_node",
|
||||
"namespace",
|
||||
rclcpp::NodeOptions().allow_undeclared_parameters(true));
|
||||
auto asynchronous_client =
|
||||
std::make_shared<rclcpp::AsyncParametersClient>(load_node, "/namespace/load_node");
|
||||
// load parameters
|
||||
rcpputils::fs::path test_resources_path{TEST_RESOURCES_DIRECTORY};
|
||||
const std::string parameters_filepath = (
|
||||
test_resources_path / "test_node" / "no_valid_parameters.yaml").string();
|
||||
EXPECT_THROW(
|
||||
asynchronous_client->load_parameters(parameters_filepath),
|
||||
rclcpp::exceptions::InvalidParametersException);
|
||||
}
|
||||
|
||||
/*
|
||||
Coverage for async load_parameters from maps with complicated regex expression
|
||||
*/
|
||||
TEST_F(TestParameterClient, async_parameter_load_parameters_from_map) {
|
||||
auto load_node = std::make_shared<rclcpp::Node>(
|
||||
"load_node",
|
||||
"namespace",
|
||||
rclcpp::NodeOptions().allow_undeclared_parameters(true));
|
||||
auto asynchronous_client =
|
||||
std::make_shared<rclcpp::AsyncParametersClient>(load_node, "/namespace/load_node");
|
||||
// load parameters
|
||||
rclcpp::ParameterMap parameter_map = {
|
||||
{"/**",
|
||||
{
|
||||
{"bar", 5},
|
||||
{"foo", 3.5},
|
||||
{"a_value", "first"}
|
||||
}
|
||||
},
|
||||
{"/*/load_node",
|
||||
{
|
||||
{"bar_foo", "ok"},
|
||||
{"a_value", "second"}
|
||||
}
|
||||
},
|
||||
{"/namespace/load_node",
|
||||
{
|
||||
{"foo_bar", true},
|
||||
{"a_value", "third"}
|
||||
}
|
||||
},
|
||||
{"/bar",
|
||||
{
|
||||
{"fatal", 10}
|
||||
}
|
||||
},
|
||||
{"/**/namespace/*",
|
||||
{
|
||||
{"a_value", "not_win"}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto load_future = asynchronous_client->load_parameters(parameter_map);
|
||||
auto result_code = rclcpp::spin_until_future_complete(
|
||||
load_node, load_future, std::chrono::milliseconds(100));
|
||||
ASSERT_EQ(result_code, rclcpp::FutureReturnCode::SUCCESS);
|
||||
ASSERT_EQ(load_future.get()[0].successful, true);
|
||||
// list parameters
|
||||
auto list_parameters = asynchronous_client->list_parameters({}, 3);
|
||||
rclcpp::spin_until_future_complete(
|
||||
load_node, list_parameters, std::chrono::milliseconds(100));
|
||||
ASSERT_EQ(list_parameters.get().names.size(), static_cast<uint64_t>(6));
|
||||
// to check the parameter "a_value"
|
||||
std::string param_name = "a_value";
|
||||
auto param = load_node->get_parameter(param_name);
|
||||
// rclcpp::ParameterMap is an unordered map, no guarantee which value will be set for `a_value`.
|
||||
EXPECT_THAT(
|
||||
(std::array{"first", "second", "third", "not_win"}),
|
||||
testing::Contains(param.get_value<std::string>()));
|
||||
}
|
||||
|
||||
/*
|
||||
Coverage for async load_parameters from maps without valid parameters
|
||||
*/
|
||||
TEST_F(TestParameterClient, async_parameter_load_from_map_no_valid_parameter) {
|
||||
auto load_node = std::make_shared<rclcpp::Node>(
|
||||
"load_node",
|
||||
"namespace",
|
||||
rclcpp::NodeOptions().allow_undeclared_parameters(true));
|
||||
auto asynchronous_client =
|
||||
std::make_shared<rclcpp::AsyncParametersClient>(load_node, "/namespace/load_node");
|
||||
// load parameters
|
||||
rclcpp::ParameterMap parameter_map = {
|
||||
{"/no/valid/parameters/node",
|
||||
{
|
||||
{"bar", 5},
|
||||
{"bar", 3.5}
|
||||
}
|
||||
}
|
||||
};
|
||||
EXPECT_THROW(
|
||||
asynchronous_client->load_parameters(parameter_map),
|
||||
rclcpp::exceptions::InvalidParametersException);
|
||||
}
|
||||
|
||||
@@ -202,9 +202,17 @@ TEST_F(TestNode, GetParameterFromEvent)
|
||||
EXPECT_THROW(
|
||||
ParameterEventHandler::get_parameter_from_event(*multiple, "my_int", wrong_name),
|
||||
std::runtime_error);
|
||||
// Throws if parameter not part of event
|
||||
|
||||
// Parameter not part of event
|
||||
// with correct node
|
||||
rclcpp::Parameter expect_notset_ret("my_notset", rclcpp::PARAMETER_NOT_SET);
|
||||
rclcpp::Parameter ret;
|
||||
EXPECT_NO_THROW(
|
||||
ret = ParameterEventHandler::get_parameter_from_event(*multiple, "my_notset", node_name););
|
||||
EXPECT_EQ(ret, expect_notset_ret);
|
||||
// with incorrect node
|
||||
EXPECT_THROW(
|
||||
ParameterEventHandler::get_parameter_from_event(*diff_ns_bool, "my_int", node_name),
|
||||
ParameterEventHandler::get_parameter_from_event(*multiple, "my_notset", wrong_name),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/parameter_map.hpp"
|
||||
@@ -353,3 +354,132 @@ TEST(Test_parameter_map_from, string_array_param_value)
|
||||
c_params->params[0].parameter_values[0].string_array_value = NULL;
|
||||
rcl_yaml_node_struct_fini(c_params);
|
||||
}
|
||||
|
||||
TEST(Test_parameter_map_from, one_node_one_param_by_node_fqn)
|
||||
{
|
||||
rcl_params_t * c_params = make_params({"foo"});
|
||||
make_node_params(c_params, 0, {"string_param"});
|
||||
|
||||
std::string hello_world = "hello world";
|
||||
char * c_hello_world = new char[hello_world.length() + 1];
|
||||
std::snprintf(c_hello_world, hello_world.size() + 1, "%s", hello_world.c_str());
|
||||
c_params->params[0].parameter_values[0].string_value = c_hello_world;
|
||||
|
||||
rclcpp::ParameterMap map = rclcpp::parameter_map_from(c_params, "/foo");
|
||||
const std::vector<rclcpp::Parameter> & params = map.at("/foo");
|
||||
EXPECT_STREQ("string_param", params.at(0).get_name().c_str());
|
||||
EXPECT_STREQ(hello_world.c_str(), params.at(0).get_value<std::string>().c_str());
|
||||
|
||||
c_params->params[0].parameter_values[0].string_value = NULL;
|
||||
delete[] c_hello_world;
|
||||
rcl_yaml_node_struct_fini(c_params);
|
||||
}
|
||||
|
||||
TEST(Test_parameter_map_from, multi_nodes_same_param_name_by_node_fqn)
|
||||
{
|
||||
std::vector<std::string> node_names_keys = {
|
||||
"/**", // index: 0
|
||||
"/*", // index: 1
|
||||
"/**/node", // index: 2
|
||||
"/*/node", // index: 3
|
||||
"/ns/node" // index: 4
|
||||
};
|
||||
|
||||
rcl_params_t * c_params = make_params(node_names_keys);
|
||||
|
||||
std::vector<char *> param_values;
|
||||
for (size_t i = 0; i < node_names_keys.size(); ++i) {
|
||||
make_node_params(c_params, i, {"string_param"});
|
||||
std::string hello_world = "hello world" + std::to_string(i);
|
||||
char * c_hello_world = new char[hello_world.length() + 1];
|
||||
std::snprintf(c_hello_world, hello_world.size() + 1, "%s", hello_world.c_str());
|
||||
c_params->params[i].parameter_values[0].string_value = c_hello_world;
|
||||
param_values.push_back(c_hello_world);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::vector<size_t>> node_fqn_expected = {
|
||||
{"/ns/foo/another_node", {0}},
|
||||
{"/another", {0, 1}},
|
||||
{"/node", {0, 1, 2}},
|
||||
{"/another_ns/node", {0, 2, 3}},
|
||||
{"/ns/node", {0, 2, 3, 4}},
|
||||
};
|
||||
|
||||
for (auto & kv : node_fqn_expected) {
|
||||
rclcpp::ParameterMap map = rclcpp::parameter_map_from(c_params, kv.first.c_str());
|
||||
const std::vector<rclcpp::Parameter> & params = map.at(kv.first);
|
||||
|
||||
EXPECT_EQ(kv.second.size(), params.size());
|
||||
for (size_t i = 0; i < params.size(); ++i) {
|
||||
std::string param_value = "hello world" + std::to_string(kv.second[i]);
|
||||
EXPECT_STREQ("string_param", params.at(i).get_name().c_str());
|
||||
EXPECT_STREQ(param_value.c_str(), params.at(i).get_value<std::string>().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < node_names_keys.size(); ++i) {
|
||||
c_params->params[i].parameter_values[0].string_value = NULL;
|
||||
}
|
||||
for (auto c_hello_world : param_values) {
|
||||
delete[] c_hello_world;
|
||||
}
|
||||
rcl_yaml_node_struct_fini(c_params);
|
||||
}
|
||||
|
||||
TEST(Test_parameter_map_from, multi_nodes_diff_param_name_by_node_fqn)
|
||||
{
|
||||
std::vector<std::string> node_names_keys = {
|
||||
"/**", // index: 0
|
||||
"/*", // index: 1
|
||||
"/**/node", // index: 2
|
||||
"/*/node", // index: 3
|
||||
"/ns/**", // index: 4
|
||||
"/ns/*", // index: 5
|
||||
"/ns/**/node", // index: 6
|
||||
"/ns/*/node", // index: 7
|
||||
"/ns/**/a/*/node", // index: 8
|
||||
"/ns/node" // index: 9
|
||||
};
|
||||
|
||||
rcl_params_t * c_params = make_params(node_names_keys);
|
||||
|
||||
for (size_t i = 0; i < node_names_keys.size(); ++i) {
|
||||
std::string param_name = "string_param" + std::to_string(i);
|
||||
make_node_params(c_params, i, {param_name});
|
||||
}
|
||||
|
||||
std::string hello_world = "hello world";
|
||||
char * c_hello_world = new char[hello_world.length() + 1];
|
||||
std::snprintf(c_hello_world, hello_world.size() + 1, "%s", hello_world.c_str());
|
||||
|
||||
for (size_t i = 0; i < node_names_keys.size(); ++i) {
|
||||
c_params->params[i].parameter_values[0].string_value = c_hello_world;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::vector<size_t>> node_fqn_expected = {
|
||||
{"/ns/node", {0, 2, 3, 4, 5, 6, 9}},
|
||||
{"/node", {0, 1, 2}},
|
||||
{"/ns/foo/node", {0, 2, 4, 6, 7}},
|
||||
{"/ns/foo/a/node", {0, 2, 4, 6}},
|
||||
{"/ns/foo/a/bar/node", {0, 2, 4, 6, 8}},
|
||||
{"/ns/a/bar/node", {0, 2, 4, 6, 8}},
|
||||
{"/ns/foo/zoo/a/bar/node", {0, 2, 4, 6, 8}},
|
||||
};
|
||||
|
||||
for (auto & kv : node_fqn_expected) {
|
||||
rclcpp::ParameterMap map = rclcpp::parameter_map_from(c_params, kv.first.c_str());
|
||||
const std::vector<rclcpp::Parameter> & params = map.at(kv.first);
|
||||
EXPECT_EQ(kv.second.size(), params.size());
|
||||
for (size_t i = 0; i < params.size(); ++i) {
|
||||
std::string param_name = "string_param" + std::to_string(kv.second[i]);
|
||||
EXPECT_STREQ(param_name.c_str(), params.at(i).get_name().c_str());
|
||||
EXPECT_STREQ(hello_world.c_str(), params.at(i).get_value<std::string>().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < node_names_keys.size(); ++i) {
|
||||
c_params->params[i].parameter_values[0].string_value = NULL;
|
||||
}
|
||||
delete[] c_hello_world;
|
||||
rcl_yaml_node_struct_fini(c_params);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
#include "rcutils/env.h"
|
||||
|
||||
#include "../mocking_utils/patch.hpp"
|
||||
#include "../utils/rclcpp_gtest_macros.hpp"
|
||||
|
||||
@@ -413,10 +415,18 @@ TEST_F(TestPublisher, intra_process_publish_failures) {
|
||||
|
||||
{
|
||||
rclcpp::LoanedMessage<test_msgs::msg::Empty> loaned_msg(*publisher, allocator);
|
||||
loaned_msg.release();
|
||||
auto msg = loaned_msg.release(); // this will unmanage the ownership of the message
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
publisher->publish(std::move(loaned_msg)),
|
||||
std::runtime_error("loaned message is not valid"));
|
||||
// if the message is actually loaned from the middleware but not be published,
|
||||
// it is user responsibility to return the message to the middleware manually
|
||||
if (publisher->can_loan_messages()) {
|
||||
ASSERT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_return_loaned_message_from_publisher(
|
||||
publisher->get_publisher_handle().get(), msg.get()));
|
||||
}
|
||||
}
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
node->create_publisher<test_msgs::msg::Empty>(
|
||||
@@ -485,6 +495,11 @@ public:
|
||||
TEST_F(TestPublisher, do_loaned_message_publish_error) {
|
||||
initialize();
|
||||
using PublisherT = TestPublisherProtectedMethods<test_msgs::msg::Empty, std::allocator<void>>;
|
||||
// This test only passes when message is allocated on heap, not middleware.
|
||||
// Since `do_loaned_message_publish()` will fail, there is no way to return the message
|
||||
// to the middleware.
|
||||
// This eventually fails to destroy publisher handle in the implementation.
|
||||
ASSERT_TRUE(rcutils_set_env("ROS_DISABLE_LOANED_MESSAGES", "1"));
|
||||
auto publisher =
|
||||
node->create_publisher<test_msgs::msg::Empty, std::allocator<void>, PublisherT>("topic", 10);
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ TEST(TestQoS, setters_and_getters) {
|
||||
qos.reliable();
|
||||
EXPECT_EQ(rclcpp::ReliabilityPolicy::Reliable, qos.reliability());
|
||||
|
||||
qos.reliability_best_available();
|
||||
EXPECT_EQ(rclcpp::ReliabilityPolicy::BestAvailable, qos.reliability());
|
||||
|
||||
qos.reliability(rclcpp::ReliabilityPolicy::BestEffort);
|
||||
EXPECT_EQ(rclcpp::ReliabilityPolicy::BestEffort, qos.reliability());
|
||||
|
||||
@@ -102,6 +105,9 @@ TEST(TestQoS, setters_and_getters) {
|
||||
qos.transient_local();
|
||||
EXPECT_EQ(rclcpp::DurabilityPolicy::TransientLocal, qos.durability());
|
||||
|
||||
qos.durability_best_available();
|
||||
EXPECT_EQ(rclcpp::DurabilityPolicy::BestAvailable, qos.durability());
|
||||
|
||||
qos.durability(rclcpp::DurabilityPolicy::Volatile);
|
||||
EXPECT_EQ(rclcpp::DurabilityPolicy::Volatile, qos.durability());
|
||||
|
||||
@@ -183,6 +189,9 @@ TEST(TestQoS, DerivedTypes) {
|
||||
const rclcpp::KeepLast expected_initialization(RMW_QOS_POLICY_DEPTH_SYSTEM_DEFAULT);
|
||||
const rclcpp::QoS expected_default(expected_initialization);
|
||||
EXPECT_EQ(expected_default.get_rmw_qos_profile(), system_default_qos.get_rmw_qos_profile());
|
||||
|
||||
rclcpp::BestAvailableQoS best_available_qos;
|
||||
EXPECT_EQ(rmw_qos_profile_best_available, best_available_qos.get_rmw_qos_profile());
|
||||
}
|
||||
|
||||
TEST(TestQoS, policy_name_from_kind) {
|
||||
|
||||
@@ -246,8 +246,8 @@ TEST_F(TestService, on_new_request_callback) {
|
||||
auto server_callback =
|
||||
[](const test_msgs::srv::Empty::Request::SharedPtr,
|
||||
test_msgs::srv::Empty::Response::SharedPtr) {FAIL();};
|
||||
rmw_qos_profile_t service_qos = rmw_qos_profile_services_default;
|
||||
service_qos.depth = 3;
|
||||
rclcpp::ServicesQoS service_qos;
|
||||
service_qos.keep_last(3);
|
||||
auto server = node->create_service<test_msgs::srv::Empty>(
|
||||
"~/test_service", server_callback, service_qos);
|
||||
|
||||
@@ -338,28 +338,25 @@ TEST_F(TestService, rcl_service_request_subscription_get_actual_qos_error) {
|
||||
|
||||
|
||||
TEST_F(TestService, server_qos) {
|
||||
rmw_qos_profile_t qos_profile = rmw_qos_profile_services_default;
|
||||
qos_profile.liveliness = RMW_QOS_POLICY_LIVELINESS_AUTOMATIC;
|
||||
uint64_t duration = 1;
|
||||
qos_profile.deadline = {duration, duration};
|
||||
qos_profile.lifespan = {duration, duration};
|
||||
qos_profile.liveliness_lease_duration = {duration, duration};
|
||||
rclcpp::ServicesQoS qos_profile;
|
||||
qos_profile.liveliness(rclcpp::LivelinessPolicy::Automatic);
|
||||
rclcpp::Duration duration(std::chrono::nanoseconds(1));
|
||||
qos_profile.deadline(duration);
|
||||
qos_profile.lifespan(duration);
|
||||
qos_profile.liveliness_lease_duration(duration);
|
||||
|
||||
auto callback = [](const test_msgs::srv::Empty::Request::SharedPtr,
|
||||
test_msgs::srv::Empty::Response::SharedPtr) {};
|
||||
|
||||
auto server = node->create_service<test_msgs::srv::Empty>(
|
||||
"service", callback,
|
||||
qos_profile);
|
||||
auto init_qos =
|
||||
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile), qos_profile);
|
||||
"service", callback, qos_profile);
|
||||
auto rs_qos = server->get_request_subscription_actual_qos();
|
||||
auto rp_qos = server->get_response_publisher_actual_qos();
|
||||
|
||||
EXPECT_EQ(init_qos, rp_qos);
|
||||
EXPECT_EQ(qos_profile, rp_qos);
|
||||
// Lifespan has no meaning for subscription/readers
|
||||
rs_qos.lifespan(qos_profile.lifespan);
|
||||
EXPECT_EQ(init_qos, rs_qos);
|
||||
rs_qos.lifespan(qos_profile.lifespan());
|
||||
EXPECT_EQ(qos_profile, rs_qos);
|
||||
}
|
||||
|
||||
TEST_F(TestService, server_qos_depth) {
|
||||
@@ -372,13 +369,12 @@ TEST_F(TestService, server_qos_depth) {
|
||||
|
||||
auto server_node = std::make_shared<rclcpp::Node>("server_node", "/ns");
|
||||
|
||||
rmw_qos_profile_t server_qos_profile = rmw_qos_profile_default;
|
||||
server_qos_profile.depth = 2;
|
||||
rclcpp::QoS server_qos_profile(2);
|
||||
|
||||
auto server = server_node->create_service<test_msgs::srv::Empty>(
|
||||
"test_qos_depth", std::move(server_callback), server_qos_profile);
|
||||
|
||||
rmw_qos_profile_t client_qos_profile = rmw_qos_profile_default;
|
||||
rclcpp::QoS client_qos_profile(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_default));
|
||||
auto client = node->create_client<test_msgs::srv::Empty>("test_qos_depth", client_qos_profile);
|
||||
|
||||
::testing::AssertionResult request_result = ::testing::AssertionSuccess();
|
||||
@@ -398,7 +394,7 @@ TEST_F(TestService, server_qos_depth) {
|
||||
}
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
while ((server_cb_count_ < server_qos_profile.depth) &&
|
||||
while ((server_cb_count_ < server_qos_profile.depth()) &&
|
||||
(std::chrono::steady_clock::now() - start) < 1s)
|
||||
{
|
||||
rclcpp::spin_some(server_node);
|
||||
@@ -409,5 +405,5 @@ TEST_F(TestService, server_qos_depth) {
|
||||
// so more server responses might be processed than expected.
|
||||
rclcpp::spin_some(server_node);
|
||||
|
||||
EXPECT_EQ(server_cb_count_, server_qos_profile.depth);
|
||||
EXPECT_EQ(server_cb_count_, server_qos_profile.depth());
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ void spin_until_time(
|
||||
|
||||
executor.spin_once(10ms);
|
||||
|
||||
if (clock->now().nanoseconds() == end_time.count()) {
|
||||
if (clock->now().nanoseconds() >= end_time.count()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ void spin_until_ros_time_updated(
|
||||
executor.add_node(node);
|
||||
|
||||
auto start = std::chrono::system_clock::now();
|
||||
while (std::chrono::system_clock::now() < (start + 1s)) {
|
||||
while (std::chrono::system_clock::now() < (start + 2s)) {
|
||||
if (!rclcpp::ok()) {
|
||||
break; // Break for ctrl-c
|
||||
}
|
||||
@@ -630,7 +630,8 @@ class SimClockPublisherNode : public rclcpp::Node
|
||||
{
|
||||
public:
|
||||
SimClockPublisherNode()
|
||||
: rclcpp::Node("sim_clock_publisher_node")
|
||||
: rclcpp::Node("sim_clock_publisher_node"),
|
||||
pub_time_(0, 0)
|
||||
{
|
||||
// Create a clock publisher
|
||||
clock_pub_ = this->create_publisher<rosgraph_msgs::msg::Clock>(
|
||||
@@ -645,10 +646,6 @@ public:
|
||||
&SimClockPublisherNode::timer_callback,
|
||||
this)
|
||||
);
|
||||
|
||||
// Init clock msg to zero
|
||||
clock_msg_.clock.sec = 0;
|
||||
clock_msg_.clock.nanosec = 0;
|
||||
}
|
||||
|
||||
~SimClockPublisherNode()
|
||||
@@ -671,13 +668,15 @@ public:
|
||||
private:
|
||||
void timer_callback()
|
||||
{
|
||||
// Increment clock msg and publish it
|
||||
clock_msg_.clock.nanosec += 1000000;
|
||||
// Increment the time, update the clock msg and publish it
|
||||
pub_time_ += rclcpp::Duration(0, 1000000);
|
||||
clock_msg_.clock = pub_time_;
|
||||
clock_pub_->publish(clock_msg_);
|
||||
}
|
||||
|
||||
rclcpp::Publisher<rosgraph_msgs::msg::Clock>::SharedPtr clock_pub_;
|
||||
rclcpp::TimerBase::SharedPtr pub_timer_;
|
||||
rclcpp::Time pub_time_;
|
||||
rosgraph_msgs::msg::Clock clock_msg_;
|
||||
std::thread node_thread_;
|
||||
rclcpp::executors::SingleThreadedExecutor node_executor;
|
||||
@@ -695,7 +694,7 @@ public:
|
||||
this->set_parameter(rclcpp::Parameter("use_sim_time", true));
|
||||
|
||||
// Create a 100ms timer
|
||||
timer_ = this->create_wall_timer(
|
||||
timer_ = this->create_timer(
|
||||
std::chrono::milliseconds(100),
|
||||
std::bind(
|
||||
&ClockThreadTestingNode::timer_callback,
|
||||
@@ -735,29 +734,33 @@ private:
|
||||
bool is_callback_frozen_ = true;
|
||||
};
|
||||
|
||||
TEST_F(TestTimeSource, check_sim_time_updated_in_callback_if_use_clock_thread) {
|
||||
// Test if clock time of a node with
|
||||
// parameter use_sim_time = true and option use_clock_thread = true
|
||||
// is updated while node is not spinning
|
||||
// (in a timer callback)
|
||||
// TODO(ivanpauno): This test was using a wall timer, when it was supposed to use sim time.
|
||||
// It was also using `use_clock_tread = false`, when it was supposed to be `true`.
|
||||
// Fixing the test to work as originally intended makes it super flaky.
|
||||
// Disabling it until the test is fixed.
|
||||
// TEST_F(TestTimeSource, check_sim_time_updated_in_callback_if_use_clock_thread) {
|
||||
// // Test if clock time of a node with
|
||||
// // parameter use_sim_time = true and option use_clock_thread = true
|
||||
// // is updated while node is not spinning
|
||||
// // (in a timer callback)
|
||||
|
||||
// Create a "sim time" publisher and spin it
|
||||
SimClockPublisherNode pub_node;
|
||||
pub_node.SpinNode();
|
||||
// // Create a "sim time" publisher and spin it
|
||||
// SimClockPublisherNode pub_node;
|
||||
// pub_node.SpinNode();
|
||||
|
||||
// Spin node for 2 seconds
|
||||
ClockThreadTestingNode clock_thread_testing_node;
|
||||
auto steady_clock = rclcpp::Clock(RCL_STEADY_TIME);
|
||||
auto start_time = steady_clock.now();
|
||||
while (rclcpp::ok() &&
|
||||
(steady_clock.now() - start_time).seconds() < 2.0)
|
||||
{
|
||||
rclcpp::spin_some(clock_thread_testing_node.get_node_base_interface());
|
||||
}
|
||||
// // Spin node for 2 seconds
|
||||
// ClockThreadTestingNode clock_thread_testing_node;
|
||||
// auto steady_clock = rclcpp::Clock(RCL_STEADY_TIME);
|
||||
// auto start_time = steady_clock.now();
|
||||
// while (rclcpp::ok() &&
|
||||
// (steady_clock.now() - start_time).seconds() < 2.0)
|
||||
// {
|
||||
// rclcpp::spin_some(clock_thread_testing_node.get_node_base_interface());
|
||||
// }
|
||||
|
||||
// Node should have get out of timer callback
|
||||
ASSERT_FALSE(clock_thread_testing_node.GetIsCallbackFrozen());
|
||||
}
|
||||
// // Node should have get out of timer callback
|
||||
// ASSERT_FALSE(clock_thread_testing_node.GetIsCallbackFrozen());
|
||||
// }
|
||||
|
||||
TEST_F(TestTimeSource, clock_sleep_until_with_ros_time_basic) {
|
||||
SimClockPublisherNode pub_node;
|
||||
|
||||
@@ -30,8 +30,15 @@
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
/// We want to test everything for both the wall and generic timer.
|
||||
enum class TimerType
|
||||
{
|
||||
WALL_TIMER,
|
||||
GENERIC_TIMER,
|
||||
};
|
||||
|
||||
/// Timer testing bring up and teardown
|
||||
class TestTimer : public ::testing::Test
|
||||
class TestTimer : public ::testing::TestWithParam<TimerType>
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
@@ -44,10 +51,7 @@ protected:
|
||||
|
||||
test_node = std::make_shared<rclcpp::Node>("test_timer_node");
|
||||
|
||||
timer = test_node->create_wall_timer(
|
||||
100ms,
|
||||
[this]() -> void
|
||||
{
|
||||
auto timer_callback = [this]() -> void {
|
||||
this->has_timer_run.store(true);
|
||||
|
||||
if (this->cancel_timer.load()) {
|
||||
@@ -55,10 +59,20 @@ protected:
|
||||
}
|
||||
// prevent any tests running timer from blocking
|
||||
this->executor->cancel();
|
||||
}
|
||||
);
|
||||
EXPECT_TRUE(timer->is_steady());
|
||||
};
|
||||
|
||||
// Store the timer type for use in TEST_P declarations.
|
||||
timer_type = GetParam();
|
||||
switch (timer_type) {
|
||||
case TimerType::WALL_TIMER:
|
||||
timer = test_node->create_wall_timer(100ms, timer_callback);
|
||||
EXPECT_TRUE(timer->is_steady());
|
||||
break;
|
||||
case TimerType::GENERIC_TIMER:
|
||||
timer = test_node->create_timer(100ms, timer_callback);
|
||||
EXPECT_FALSE(timer->is_steady());
|
||||
break;
|
||||
}
|
||||
executor->add_node(test_node);
|
||||
// don't start spinning, let the test dictate when
|
||||
}
|
||||
@@ -72,6 +86,7 @@ protected:
|
||||
}
|
||||
|
||||
// set to true if the timer callback executed, false otherwise
|
||||
TimerType timer_type;
|
||||
std::atomic<bool> has_timer_run;
|
||||
// flag used to cancel the timer in the timer callback. If true cancel the timer, otherwise
|
||||
// cancel the executor (preventing any tests from blocking)
|
||||
@@ -91,7 +106,7 @@ void test_initial_conditions(
|
||||
}
|
||||
|
||||
/// Simple test
|
||||
TEST_F(TestTimer, test_simple_cancel)
|
||||
TEST_P(TestTimer, test_simple_cancel)
|
||||
{
|
||||
// expect clean state, don't run otherwise
|
||||
test_initial_conditions(timer, has_timer_run);
|
||||
@@ -104,7 +119,7 @@ TEST_F(TestTimer, test_simple_cancel)
|
||||
}
|
||||
|
||||
/// Test state when using reset
|
||||
TEST_F(TestTimer, test_is_canceled_reset)
|
||||
TEST_P(TestTimer, test_is_canceled_reset)
|
||||
{
|
||||
// expect clean state, don't run otherwise
|
||||
test_initial_conditions(timer, has_timer_run);
|
||||
@@ -129,7 +144,7 @@ TEST_F(TestTimer, test_is_canceled_reset)
|
||||
}
|
||||
|
||||
/// Run and check state, cancel the executor
|
||||
TEST_F(TestTimer, test_run_cancel_executor)
|
||||
TEST_P(TestTimer, test_run_cancel_executor)
|
||||
{
|
||||
// expect clean state, don't run otherwise
|
||||
test_initial_conditions(timer, has_timer_run);
|
||||
@@ -146,7 +161,7 @@ TEST_F(TestTimer, test_run_cancel_executor)
|
||||
}
|
||||
|
||||
/// Run and check state, cancel the timer
|
||||
TEST_F(TestTimer, test_run_cancel_timer)
|
||||
TEST_P(TestTimer, test_run_cancel_timer)
|
||||
{
|
||||
// expect clean state, don't run otherwise
|
||||
test_initial_conditions(timer, has_timer_run);
|
||||
@@ -159,7 +174,7 @@ TEST_F(TestTimer, test_run_cancel_timer)
|
||||
EXPECT_TRUE(timer->is_canceled());
|
||||
}
|
||||
|
||||
TEST_F(TestTimer, test_bad_arguments) {
|
||||
TEST_P(TestTimer, test_bad_arguments) {
|
||||
auto node_base = rclcpp::node_interfaces::get_node_base_interface(test_node);
|
||||
auto context = node_base->get_context();
|
||||
|
||||
@@ -198,13 +213,19 @@ TEST_F(TestTimer, test_bad_arguments) {
|
||||
rclcpp::exceptions::RCLError);
|
||||
}
|
||||
|
||||
TEST_F(TestTimer, callback_with_timer) {
|
||||
TEST_P(TestTimer, callback_with_timer) {
|
||||
rclcpp::TimerBase * timer_ptr = nullptr;
|
||||
timer = test_node->create_wall_timer(
|
||||
std::chrono::milliseconds(1),
|
||||
[&timer_ptr](rclcpp::TimerBase & timer) {
|
||||
auto timer_callback = [&timer_ptr](rclcpp::TimerBase & timer) {
|
||||
timer_ptr = &timer;
|
||||
});
|
||||
};
|
||||
switch (timer_type) {
|
||||
case TimerType::WALL_TIMER:
|
||||
timer = test_node->create_wall_timer(1ms, timer_callback);
|
||||
break;
|
||||
case TimerType::GENERIC_TIMER:
|
||||
timer = test_node->create_timer(1ms, timer_callback);
|
||||
break;
|
||||
}
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
while (nullptr == timer_ptr &&
|
||||
(std::chrono::steady_clock::now() - start) < std::chrono::milliseconds(100))
|
||||
@@ -216,13 +237,19 @@ TEST_F(TestTimer, callback_with_timer) {
|
||||
EXPECT_FALSE(timer_ptr->is_ready());
|
||||
}
|
||||
|
||||
TEST_F(TestTimer, callback_with_period_zero) {
|
||||
TEST_P(TestTimer, callback_with_period_zero) {
|
||||
rclcpp::TimerBase * timer_ptr = nullptr;
|
||||
timer = test_node->create_wall_timer(
|
||||
std::chrono::milliseconds(0),
|
||||
[&timer_ptr](rclcpp::TimerBase & timer) {
|
||||
auto timer_callback = [&timer_ptr](rclcpp::TimerBase & timer) {
|
||||
timer_ptr = &timer;
|
||||
});
|
||||
};
|
||||
switch (timer_type) {
|
||||
case TimerType::WALL_TIMER:
|
||||
timer = test_node->create_wall_timer(0ms, timer_callback);
|
||||
break;
|
||||
case TimerType::GENERIC_TIMER:
|
||||
timer = test_node->create_timer(0ms, timer_callback);
|
||||
break;
|
||||
}
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
while (nullptr == timer_ptr &&
|
||||
(std::chrono::steady_clock::now() - start) < std::chrono::milliseconds(100))
|
||||
@@ -235,7 +262,7 @@ TEST_F(TestTimer, callback_with_period_zero) {
|
||||
}
|
||||
|
||||
/// Test internal failures using mocks
|
||||
TEST_F(TestTimer, test_failures_with_exceptions)
|
||||
TEST_P(TestTimer, test_failures_with_exceptions)
|
||||
{
|
||||
// expect clean state, don't run otherwise
|
||||
test_initial_conditions(timer, has_timer_run);
|
||||
@@ -245,8 +272,16 @@ TEST_F(TestTimer, test_failures_with_exceptions)
|
||||
auto mock = mocking_utils::inject_on_return("lib:rclcpp", rcl_timer_fini, RCL_RET_ERROR);
|
||||
EXPECT_NO_THROW(
|
||||
{
|
||||
timer_to_test_destructor =
|
||||
test_node->create_wall_timer(std::chrono::milliseconds(0), [](void) {});
|
||||
switch (timer_type) {
|
||||
case TimerType::WALL_TIMER:
|
||||
timer_to_test_destructor =
|
||||
test_node->create_wall_timer(std::chrono::milliseconds(0), [](void) {});
|
||||
break;
|
||||
case TimerType::GENERIC_TIMER:
|
||||
timer_to_test_destructor =
|
||||
test_node->create_timer(std::chrono::milliseconds(0), [](void) {});
|
||||
break;
|
||||
}
|
||||
timer_to_test_destructor.reset();
|
||||
});
|
||||
}
|
||||
@@ -283,3 +318,19 @@ TEST_F(TestTimer, test_failures_with_exceptions)
|
||||
std::runtime_error("Timer could not get time until next call: error not set"));
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
PerTimerType, TestTimer,
|
||||
::testing::Values(TimerType::WALL_TIMER, TimerType::GENERIC_TIMER),
|
||||
[](const ::testing::TestParamInfo<TimerType> & info) -> std::string {
|
||||
switch (info.param) {
|
||||
case TimerType::WALL_TIMER:
|
||||
return std::string("wall_timer");
|
||||
case TimerType::GENERIC_TIMER:
|
||||
return std::string("generic_timer");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return std::string("unknown");
|
||||
}
|
||||
);
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/**:
|
||||
ros__parameters:
|
||||
bar: 5
|
||||
foo: 3.5
|
||||
a_value: "first"
|
||||
|
||||
/*:
|
||||
load_node:
|
||||
ros__parameters:
|
||||
bar_foo: "ok"
|
||||
a_value: "second"
|
||||
|
||||
namespace:
|
||||
load_node:
|
||||
ros__parameters:
|
||||
foo_bar: true
|
||||
a_value: "third"
|
||||
|
||||
bar:
|
||||
ros__parameters:
|
||||
fatal: 10
|
||||
|
||||
/**/namespace/*:
|
||||
ros__parameters:
|
||||
a_value: "last_one_win"
|
||||
4
rclcpp/test/resources/test_node/no_valid_parameters.yaml
Normal file
4
rclcpp/test/resources/test_node/no_valid_parameters.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
/no/valid/parameters/node:
|
||||
ros__parameters:
|
||||
bar: 5
|
||||
foo: 3.5
|
||||
@@ -0,0 +1,5 @@
|
||||
/**/foo/*/bar:
|
||||
node2:
|
||||
ros__parameters:
|
||||
foo: "foo"
|
||||
bar: "bar"
|
||||
@@ -0,0 +1,16 @@
|
||||
/**:
|
||||
node2:
|
||||
ros__parameters:
|
||||
a_value: "first"
|
||||
foo: "foo"
|
||||
|
||||
/ns:
|
||||
node2:
|
||||
ros__parameters:
|
||||
a_value: "second"
|
||||
bar: "bar"
|
||||
|
||||
/*:
|
||||
node2:
|
||||
ros__parameters:
|
||||
a_value: "last_one_win"
|
||||
57
rclcpp/test/resources/test_node_parameters/wildcards.yaml
Normal file
57
rclcpp/test/resources/test_node_parameters/wildcards.yaml
Normal file
@@ -0,0 +1,57 @@
|
||||
/**:
|
||||
ros__parameters:
|
||||
full_wild: "full_wild"
|
||||
|
||||
/**:
|
||||
node2:
|
||||
ros__parameters:
|
||||
namespace_wild: "namespace_wild"
|
||||
|
||||
/**/node2:
|
||||
ros__parameters:
|
||||
namespace_wild_another: "namespace_wild_another"
|
||||
|
||||
/*:
|
||||
node2:
|
||||
ros__parameters:
|
||||
namespace_wild_one_star: "namespace_wild_one_star"
|
||||
|
||||
ns:
|
||||
"*":
|
||||
ros__parameters:
|
||||
node_wild_in_ns: "node_wild_in_ns"
|
||||
|
||||
/ns/*:
|
||||
ros__parameters:
|
||||
node_wild_in_ns_another: "node_wild_in_ns_another"
|
||||
|
||||
ns:
|
||||
node2:
|
||||
ros__parameters:
|
||||
explicit_in_ns: "explicit_in_ns"
|
||||
|
||||
"*":
|
||||
ros__parameters:
|
||||
node_wild_no_ns: "node_wild_no_ns"
|
||||
|
||||
node2:
|
||||
ros__parameters:
|
||||
explicit_no_ns: "explicit_no_ns"
|
||||
|
||||
ns:
|
||||
nodeX:
|
||||
ros__parameters:
|
||||
should_not_appear: "incorrect_node_name"
|
||||
|
||||
/**/nodeX:
|
||||
ros__parameters:
|
||||
should_not_appear: "incorrect_node_name"
|
||||
|
||||
nsX:
|
||||
node2:
|
||||
ros__parameters:
|
||||
should_not_appear: "incorrect_namespace"
|
||||
|
||||
/nsX/*:
|
||||
ros__parameters:
|
||||
should_not_appear: "incorrect_namespace"
|
||||
@@ -3,6 +3,18 @@ Changelog for package rclcpp_action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
17.0.0 (2022-09-13)
|
||||
-------------------
|
||||
* Revert "Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (`#1821 <https://github.com/ros2/rclcpp/issues/1821>`_) (`#1874 <https://github.com/ros2/rclcpp/issues/1874>`_)" (`#1956 <https://github.com/ros2/rclcpp/issues/1956>`_)
|
||||
* Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (`#1821 <https://github.com/ros2/rclcpp/issues/1821>`_) (`#1874 <https://github.com/ros2/rclcpp/issues/1874>`_)
|
||||
* Contributors: Hubert Liberacki, William Woodall
|
||||
|
||||
16.2.0 (2022-05-03)
|
||||
-------------------
|
||||
|
||||
16.1.0 (2022-04-29)
|
||||
-------------------
|
||||
|
||||
16.0.1 (2022-04-13)
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -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>16.0.1</version>
|
||||
<version>17.0.0</version>
|
||||
<description>Adds action APIs for C++.</description>
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||
|
||||
@@ -2,6 +2,18 @@
|
||||
Changelog for package rclcpp_components
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
17.0.0 (2022-09-13)
|
||||
-------------------
|
||||
* Revert "Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (`#1821 <https://github.com/ros2/rclcpp/issues/1821>`_) (`#1874 <https://github.com/ros2/rclcpp/issues/1874>`_)" (`#1956 <https://github.com/ros2/rclcpp/issues/1956>`_)
|
||||
* Introduce executors new spin_for method, replace spin_until_future_complete with spin_until_complete. (`#1821 <https://github.com/ros2/rclcpp/issues/1821>`_) (`#1874 <https://github.com/ros2/rclcpp/issues/1874>`_)
|
||||
* Contributors: Hubert Liberacki, William Woodall
|
||||
|
||||
16.2.0 (2022-05-03)
|
||||
-------------------
|
||||
|
||||
16.1.0 (2022-04-29)
|
||||
-------------------
|
||||
|
||||
16.0.1 (2022-04-13)
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -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>16.0.1</version>
|
||||
<version>17.0.0</version>
|
||||
<description>Package containing tools for dynamically loadable components</description>
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||
|
||||
@@ -3,6 +3,22 @@ Changelog for package rclcpp_lifecycle
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
17.0.0 (2022-09-13)
|
||||
-------------------
|
||||
* Revert "Revert "Add a create_timer method to Node and `LifecycleNode` classes (`#1975 <https://github.com/ros2/rclcpp/issues/1975>`_)" (`#2009 <https://github.com/ros2/rclcpp/issues/2009>`_) (`#2010 <https://github.com/ros2/rclcpp/issues/2010>`_)
|
||||
* Revert "Add a `create_timer` method to `Node` and `LifecycleNode` classes (`#1975 <https://github.com/ros2/rclcpp/issues/1975>`_)" (`#2009 <https://github.com/ros2/rclcpp/issues/2009>`_)
|
||||
* Add a `create_timer` method to `Node` and `LifecycleNode` classes (`#1975 <https://github.com/ros2/rclcpp/issues/1975>`_)
|
||||
* Support pre-set and post-set parameter callbacks in addition to on-set-parameter-callback. (`#1947 <https://github.com/ros2/rclcpp/issues/1947>`_)
|
||||
* Make create_service accept rclcpp::QoS (`#1969 <https://github.com/ros2/rclcpp/issues/1969>`_)
|
||||
* Make create_client accept rclcpp::QoS (`#1964 <https://github.com/ros2/rclcpp/issues/1964>`_)
|
||||
* Contributors: Andrew Symington, Deepanshu Bansal, Ivan Santiago Paunovic, Shane Loretz
|
||||
|
||||
16.2.0 (2022-05-03)
|
||||
-------------------
|
||||
|
||||
16.1.0 (2022-04-29)
|
||||
-------------------
|
||||
|
||||
16.0.1 (2022-04-13)
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -109,6 +109,22 @@ if(BUILD_TESTING)
|
||||
)
|
||||
target_link_libraries(test_lifecycle_service_client ${PROJECT_NAME} mimick)
|
||||
endif()
|
||||
ament_add_gtest(test_client test/test_client.cpp TIMEOUT 120)
|
||||
if(TARGET test_client)
|
||||
target_link_libraries(test_client
|
||||
${PROJECT_NAME}
|
||||
mimick
|
||||
${rcl_interfaces_TARGETS}
|
||||
rclcpp::rclcpp)
|
||||
endif()
|
||||
ament_add_gtest(test_service test/test_service.cpp TIMEOUT 120)
|
||||
if(TARGET test_service)
|
||||
target_link_libraries(test_service
|
||||
${PROJECT_NAME}
|
||||
mimick
|
||||
${test_msgs_TARGETS}
|
||||
rclcpp::rclcpp)
|
||||
endif()
|
||||
ament_add_gtest(test_state_machine_info test/test_state_machine_info.cpp)
|
||||
if(TARGET test_state_machine_info)
|
||||
ament_target_dependencies(test_state_machine_info
|
||||
|
||||
@@ -242,7 +242,7 @@ public:
|
||||
)
|
||||
);
|
||||
|
||||
/// Create a timer.
|
||||
/// Create a timer that uses the wall clock to drive the callback.
|
||||
/**
|
||||
* \param[in] period Time interval between triggers of the callback.
|
||||
* \param[in] callback User-defined callback function.
|
||||
@@ -255,15 +255,58 @@ public:
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create a timer that uses the node clock to drive the callback.
|
||||
/**
|
||||
* \param[in] period Time interval between triggers of the callback.
|
||||
* \param[in] callback User-defined callback function.
|
||||
* \param[in] group Callback group to execute this timer's callback in.
|
||||
*/
|
||||
template<typename DurationRepT = int64_t, typename DurationT = std::milli, typename CallbackT>
|
||||
typename rclcpp::GenericTimer<CallbackT>::SharedPtr
|
||||
create_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a Client.
|
||||
/**
|
||||
* \sa rclcpp::Node::create_client
|
||||
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
|
||||
*/
|
||||
template<typename ServiceT>
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
typename rclcpp::Client<ServiceT>::SharedPtr
|
||||
create_client(
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a Client.
|
||||
/**
|
||||
* \param[in] service_name The name on which the service is accessible.
|
||||
* \param[in] qos Quality of service profile for client.
|
||||
* \param[in] group Callback group to handle the reply to service calls.
|
||||
* \return Shared pointer to the created client.
|
||||
*/
|
||||
template<typename ServiceT>
|
||||
typename rclcpp::Client<ServiceT>::SharedPtr
|
||||
create_client(
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
|
||||
const rclcpp::QoS & qos = rclcpp::ServicesQoS(),
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a Service.
|
||||
/**
|
||||
* \sa rclcpp::Node::create_service
|
||||
* \deprecated use rclcpp::QoS instead of rmw_qos_profile_t
|
||||
*/
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
[[deprecated("use rclcpp::QoS instead of rmw_qos_profile_t")]]
|
||||
typename rclcpp::Service<ServiceT>::SharedPtr
|
||||
create_service(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a Service.
|
||||
@@ -275,7 +318,7 @@ public:
|
||||
create_service(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
|
||||
const rclcpp::QoS & qos = rclcpp::ServicesQoS(),
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Create and return a GenericPublisher.
|
||||
@@ -508,10 +551,32 @@ public:
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const;
|
||||
|
||||
using PreSetParametersCallbackHandle =
|
||||
rclcpp::node_interfaces::PreSetParametersCallbackHandle;
|
||||
using PreSetParametersCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::PreSetParametersCallbackType;
|
||||
|
||||
using OnSetParametersCallbackHandle =
|
||||
rclcpp::node_interfaces::OnSetParametersCallbackHandle;
|
||||
using OnParametersSetCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;
|
||||
using OnSetParametersCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::OnSetParametersCallbackType;
|
||||
using OnParametersSetCallbackType [[deprecated("use OnSetParametersCallbackType instead")]] =
|
||||
OnSetParametersCallbackType;
|
||||
|
||||
using PostSetParametersCallbackHandle =
|
||||
rclcpp::node_interfaces::PostSetParametersCallbackHandle;
|
||||
using PostSetParametersCallbackType =
|
||||
rclcpp::node_interfaces::NodeParametersInterface::PostSetParametersCallbackType;
|
||||
|
||||
/// Add a callback that gets triggered before parameters are validated.
|
||||
/**
|
||||
* \sa rclcpp::Node::add_pre_set_parameters_callback
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
rclcpp_lifecycle::LifecycleNode::PreSetParametersCallbackHandle::SharedPtr
|
||||
add_pre_set_parameters_callback(
|
||||
rclcpp_lifecycle::LifecycleNode::PreSetParametersCallbackType callback);
|
||||
|
||||
/// Add a callback for when parameters are being set.
|
||||
/**
|
||||
@@ -521,7 +586,26 @@ public:
|
||||
RCUTILS_WARN_UNUSED
|
||||
rclcpp_lifecycle::LifecycleNode::OnSetParametersCallbackHandle::SharedPtr
|
||||
add_on_set_parameters_callback(
|
||||
rclcpp_lifecycle::LifecycleNode::OnParametersSetCallbackType callback);
|
||||
rclcpp_lifecycle::LifecycleNode::OnSetParametersCallbackType callback);
|
||||
|
||||
/// Add a callback that gets triggered after parameters are set successfully.
|
||||
/**
|
||||
* \sa rclcpp::Node::add_post_set_parameters_callback
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
RCUTILS_WARN_UNUSED
|
||||
rclcpp_lifecycle::LifecycleNode::PostSetParametersCallbackHandle::SharedPtr
|
||||
add_post_set_parameters_callback(
|
||||
rclcpp_lifecycle::LifecycleNode::PostSetParametersCallbackType callback);
|
||||
|
||||
/// Remove a callback registered with `add_pre_set_parameters_callback`.
|
||||
/**
|
||||
* \sa rclcpp::Node::remove_pre_set_parameters_callback
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
void
|
||||
remove_pre_set_parameters_callback(
|
||||
const rclcpp_lifecycle::LifecycleNode::PreSetParametersCallbackHandle * const handler);
|
||||
|
||||
/// Remove a callback registered with `add_on_set_parameters_callback`.
|
||||
/**
|
||||
@@ -532,6 +616,15 @@ public:
|
||||
remove_on_set_parameters_callback(
|
||||
const rclcpp_lifecycle::LifecycleNode::OnSetParametersCallbackHandle * const handler);
|
||||
|
||||
/// Remove a callback registered with `add_post_set_parameters_callback`.
|
||||
/**
|
||||
* \sa rclcpp::Node::remove_post_set_parameters_callback
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
void
|
||||
remove_post_set_parameters_callback(
|
||||
const rclcpp_lifecycle::LifecycleNode::PostSetParametersCallbackHandle * const handler);
|
||||
|
||||
/// Return a vector of existing node names (string).
|
||||
/**
|
||||
* \sa rclcpp::Node::get_node_names
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/contexts/default_context.hpp"
|
||||
#include "rclcpp/create_client.hpp"
|
||||
#include "rclcpp/create_generic_publisher.hpp"
|
||||
#include "rclcpp/create_generic_subscription.hpp"
|
||||
#include "rclcpp/create_publisher.hpp"
|
||||
@@ -89,11 +90,28 @@ LifecycleNode::create_wall_timer(
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
auto timer = rclcpp::WallTimer<CallbackT>::make_shared(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(period),
|
||||
std::move(callback), this->node_base_->get_context());
|
||||
node_timers_->add_timer(timer, group);
|
||||
return timer;
|
||||
return rclcpp::create_wall_timer(
|
||||
period,
|
||||
std::move(callback),
|
||||
group,
|
||||
this->node_base_.get(),
|
||||
this->node_timers_.get());
|
||||
}
|
||||
|
||||
template<typename DurationRepT, typename DurationT, typename CallbackT>
|
||||
typename rclcpp::GenericTimer<CallbackT>::SharedPtr
|
||||
LifecycleNode::create_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return rclcpp::create_timer(
|
||||
this->get_clock(),
|
||||
period,
|
||||
std::move(callback),
|
||||
group,
|
||||
this->node_base_.get(),
|
||||
this->node_timers_.get());
|
||||
}
|
||||
|
||||
template<typename ServiceT>
|
||||
@@ -103,21 +121,21 @@ LifecycleNode::create_client(
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
rcl_client_options_t options = rcl_client_get_default_options();
|
||||
options.qos = qos_profile;
|
||||
return rclcpp::create_client<ServiceT>(
|
||||
node_base_, node_graph_, node_services_,
|
||||
service_name, qos_profile, group);
|
||||
}
|
||||
|
||||
using rclcpp::Client;
|
||||
using rclcpp::ClientBase;
|
||||
|
||||
auto cli = Client<ServiceT>::make_shared(
|
||||
node_base_.get(),
|
||||
node_graph_,
|
||||
service_name,
|
||||
options);
|
||||
|
||||
auto cli_base_ptr = std::dynamic_pointer_cast<ClientBase>(cli);
|
||||
node_services_->add_client(cli_base_ptr, group);
|
||||
return cli;
|
||||
template<typename ServiceT>
|
||||
typename rclcpp::Client<ServiceT>::SharedPtr
|
||||
LifecycleNode::create_client(
|
||||
const std::string & service_name,
|
||||
const rclcpp::QoS & qos,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return rclcpp::create_client<ServiceT>(
|
||||
node_base_, node_graph_, node_services_,
|
||||
service_name, qos, group);
|
||||
}
|
||||
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
@@ -133,6 +151,19 @@ LifecycleNode::create_service(
|
||||
service_name, std::forward<CallbackT>(callback), qos_profile, group);
|
||||
}
|
||||
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
typename rclcpp::Service<ServiceT>::SharedPtr
|
||||
LifecycleNode::create_service(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rclcpp::QoS & qos,
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return rclcpp::create_service<ServiceT, CallbackT>(
|
||||
node_base_, node_services_,
|
||||
service_name, std::forward<CallbackT>(callback), qos, group);
|
||||
}
|
||||
|
||||
template<typename AllocatorT>
|
||||
std::shared_ptr<rclcpp::GenericPublisher>
|
||||
LifecycleNode::create_generic_publisher(
|
||||
|
||||
@@ -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>16.0.1</version>
|
||||
<version>17.0.0</version>
|
||||
<description>Package containing a prototype for lifecycle implementation</description>
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
<maintainer email="jacob@openrobotics.org">Jacob Perron</maintainer>
|
||||
|
||||
@@ -283,12 +283,31 @@ LifecycleNode::list_parameters(
|
||||
return node_parameters_->list_parameters(prefixes, depth);
|
||||
}
|
||||
|
||||
rclcpp::Node::PreSetParametersCallbackHandle::SharedPtr
|
||||
LifecycleNode::add_pre_set_parameters_callback(PreSetParametersCallbackType callback)
|
||||
{
|
||||
return node_parameters_->add_pre_set_parameters_callback(callback);
|
||||
}
|
||||
|
||||
rclcpp::Node::OnSetParametersCallbackHandle::SharedPtr
|
||||
LifecycleNode::add_on_set_parameters_callback(OnParametersSetCallbackType callback)
|
||||
LifecycleNode::add_on_set_parameters_callback(OnSetParametersCallbackType callback)
|
||||
{
|
||||
return node_parameters_->add_on_set_parameters_callback(callback);
|
||||
}
|
||||
|
||||
rclcpp::Node::PostSetParametersCallbackHandle::SharedPtr
|
||||
LifecycleNode::add_post_set_parameters_callback(PostSetParametersCallbackType callback)
|
||||
{
|
||||
return node_parameters_->add_post_set_parameters_callback(callback);
|
||||
}
|
||||
|
||||
void
|
||||
LifecycleNode::remove_pre_set_parameters_callback(
|
||||
const PreSetParametersCallbackHandle * const callback)
|
||||
{
|
||||
node_parameters_->remove_pre_set_parameters_callback(callback);
|
||||
}
|
||||
|
||||
void
|
||||
LifecycleNode::remove_on_set_parameters_callback(
|
||||
const OnSetParametersCallbackHandle * const callback)
|
||||
@@ -296,6 +315,13 @@ LifecycleNode::remove_on_set_parameters_callback(
|
||||
node_parameters_->remove_on_set_parameters_callback(callback);
|
||||
}
|
||||
|
||||
void
|
||||
LifecycleNode::remove_post_set_parameters_callback(
|
||||
const PostSetParametersCallbackHandle * const callback)
|
||||
{
|
||||
node_parameters_->remove_post_set_parameters_callback(callback);
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
LifecycleNode::get_node_names() const
|
||||
{
|
||||
|
||||
143
rclcpp_lifecycle/test/test_client.cpp
Normal file
143
rclcpp_lifecycle/test/test_client.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright 2022 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 <utility>
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "rclcpp_lifecycle/lifecycle_node.hpp"
|
||||
|
||||
#include "rcl_interfaces/srv/list_parameters.hpp"
|
||||
|
||||
|
||||
class TestClient : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
void SetUp()
|
||||
{
|
||||
node_ = std::make_shared<rclcpp_lifecycle::LifecycleNode>("my_lifecycle_node", "/ns");
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
node_.reset();
|
||||
}
|
||||
|
||||
rclcpp_lifecycle::LifecycleNode::SharedPtr node_;
|
||||
};
|
||||
|
||||
/*
|
||||
Testing client construction and destruction.
|
||||
*/
|
||||
TEST_F(TestClient, construction_and_destruction) {
|
||||
using rcl_interfaces::srv::ListParameters;
|
||||
{
|
||||
auto client = node_->create_client<ListParameters>("service");
|
||||
EXPECT_TRUE(client);
|
||||
}
|
||||
{
|
||||
// suppress deprecated function warning
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
auto client = node_->create_client<ListParameters>(
|
||||
"service", rmw_qos_profile_services_default);
|
||||
EXPECT_TRUE(client);
|
||||
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
{
|
||||
auto client = node_->create_client<ListParameters>(
|
||||
"service", rclcpp::ServicesQoS());
|
||||
EXPECT_TRUE(client);
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(
|
||||
{
|
||||
auto client = node_->create_client<ListParameters>("invalid_service?");
|
||||
}, rclcpp::exceptions::InvalidServiceNameError);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestClient, construction_with_free_function) {
|
||||
{
|
||||
auto client = rclcpp::create_client<rcl_interfaces::srv::ListParameters>(
|
||||
node_->get_node_base_interface(),
|
||||
node_->get_node_graph_interface(),
|
||||
node_->get_node_services_interface(),
|
||||
"service",
|
||||
rmw_qos_profile_services_default,
|
||||
nullptr);
|
||||
EXPECT_TRUE(client);
|
||||
}
|
||||
{
|
||||
ASSERT_THROW(
|
||||
{
|
||||
auto client = rclcpp::create_client<rcl_interfaces::srv::ListParameters>(
|
||||
node_->get_node_base_interface(),
|
||||
node_->get_node_graph_interface(),
|
||||
node_->get_node_services_interface(),
|
||||
"invalid_?service",
|
||||
rmw_qos_profile_services_default,
|
||||
nullptr);
|
||||
}, rclcpp::exceptions::InvalidServiceNameError);
|
||||
}
|
||||
{
|
||||
auto client = rclcpp::create_client<rcl_interfaces::srv::ListParameters>(
|
||||
node_->get_node_base_interface(),
|
||||
node_->get_node_graph_interface(),
|
||||
node_->get_node_services_interface(),
|
||||
"service",
|
||||
rclcpp::ServicesQoS(),
|
||||
nullptr);
|
||||
EXPECT_TRUE(client);
|
||||
}
|
||||
{
|
||||
ASSERT_THROW(
|
||||
{
|
||||
auto client = rclcpp::create_client<rcl_interfaces::srv::ListParameters>(
|
||||
node_->get_node_base_interface(),
|
||||
node_->get_node_graph_interface(),
|
||||
node_->get_node_services_interface(),
|
||||
"invalid_?service",
|
||||
rclcpp::ServicesQoS(),
|
||||
nullptr);
|
||||
}, rclcpp::exceptions::InvalidServiceNameError);
|
||||
}
|
||||
}
|
||||
@@ -42,10 +42,17 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
/// We want to test everything for both the wall and generic timer.
|
||||
enum class TimerType
|
||||
{
|
||||
WALL_TIMER,
|
||||
GENERIC_TIMER,
|
||||
};
|
||||
|
||||
class EmptyLifecycleNode : public rclcpp_lifecycle::LifecycleNode
|
||||
{
|
||||
public:
|
||||
explicit EmptyLifecycleNode(const std::string & node_name)
|
||||
explicit EmptyLifecycleNode(const std::string & node_name, const TimerType & timer_type)
|
||||
: rclcpp_lifecycle::LifecycleNode(node_name)
|
||||
{
|
||||
rclcpp::PublisherOptionsWithAllocator<std::allocator<void>> options;
|
||||
@@ -55,8 +62,20 @@ public:
|
||||
add_managed_entity(publisher_);
|
||||
|
||||
// For coverage this is being added here
|
||||
auto timer = create_wall_timer(std::chrono::seconds(1), []() {});
|
||||
add_timer_handle(timer);
|
||||
switch (timer_type) {
|
||||
case TimerType::WALL_TIMER:
|
||||
{
|
||||
auto timer = create_wall_timer(std::chrono::seconds(1), []() {});
|
||||
add_timer_handle(timer);
|
||||
break;
|
||||
}
|
||||
case TimerType::GENERIC_TIMER:
|
||||
{
|
||||
auto timer = create_timer(std::chrono::seconds(1), []() {});
|
||||
add_timer_handle(timer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<test_msgs::msg::Empty>> publisher()
|
||||
@@ -68,13 +87,13 @@ private:
|
||||
std::shared_ptr<rclcpp_lifecycle::LifecyclePublisher<test_msgs::msg::Empty>> publisher_;
|
||||
};
|
||||
|
||||
class TestLifecyclePublisher : public ::testing::Test
|
||||
class TestLifecyclePublisher : public ::testing::TestWithParam<TimerType>
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
node_ = std::make_shared<EmptyLifecycleNode>("node");
|
||||
node_ = std::make_shared<EmptyLifecycleNode>("node", GetParam());
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
@@ -86,7 +105,7 @@ protected:
|
||||
std::shared_ptr<EmptyLifecycleNode> node_;
|
||||
};
|
||||
|
||||
TEST_F(TestLifecyclePublisher, publish_managed_by_node) {
|
||||
TEST_P(TestLifecyclePublisher, publish_managed_by_node) {
|
||||
// transition via LifecycleNode
|
||||
auto success = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
|
||||
auto reset_key = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
|
||||
@@ -125,7 +144,7 @@ TEST_F(TestLifecyclePublisher, publish_managed_by_node) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestLifecyclePublisher, publish) {
|
||||
TEST_P(TestLifecyclePublisher, publish) {
|
||||
// transition via LifecyclePublisher
|
||||
node_->publisher()->on_deactivate();
|
||||
EXPECT_FALSE(node_->publisher()->is_activated());
|
||||
@@ -148,3 +167,19 @@ TEST_F(TestLifecyclePublisher, publish) {
|
||||
EXPECT_NO_THROW(node_->publisher()->publish(std::move(msg_ptr)));
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
PerTimerType, TestLifecyclePublisher,
|
||||
::testing::Values(TimerType::WALL_TIMER, TimerType::GENERIC_TIMER),
|
||||
[](const ::testing::TestParamInfo<TimerType> & info) -> std::string {
|
||||
switch (info.param) {
|
||||
case TimerType::WALL_TIMER:
|
||||
return std::string("wall_timer");
|
||||
case TimerType::GENERIC_TIMER:
|
||||
return std::string("generic_timer");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return std::string("unknown");
|
||||
}
|
||||
);
|
||||
|
||||
100
rclcpp_lifecycle/test/test_service.cpp
Normal file
100
rclcpp_lifecycle/test/test_service.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright 2022 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 <utility>
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "rclcpp_lifecycle/lifecycle_node.hpp"
|
||||
|
||||
#include "test_msgs/srv/empty.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
class TestService : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
void SetUp()
|
||||
{
|
||||
node = std::make_shared<rclcpp_lifecycle::LifecycleNode>("my_lifecycle_node", "/ns");
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
node.reset();
|
||||
}
|
||||
|
||||
rclcpp_lifecycle::LifecycleNode::SharedPtr node;
|
||||
};
|
||||
|
||||
/*
|
||||
Testing service construction and destruction.
|
||||
*/
|
||||
TEST_F(TestService, construction_and_destruction) {
|
||||
using test_msgs::srv::Empty;
|
||||
auto callback =
|
||||
[](const Empty::Request::SharedPtr, Empty::Response::SharedPtr) {
|
||||
};
|
||||
{
|
||||
auto service = node->create_service<Empty>("service", callback);
|
||||
EXPECT_NE(nullptr, service->get_service_handle());
|
||||
const rclcpp::ServiceBase * const_service_base = service.get();
|
||||
EXPECT_NE(nullptr, const_service_base->get_service_handle());
|
||||
}
|
||||
{
|
||||
// suppress deprecated function warning
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
auto service = node->create_service<Empty>(
|
||||
"service", callback, rmw_qos_profile_services_default);
|
||||
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
EXPECT_NE(nullptr, service->get_service_handle());
|
||||
const rclcpp::ServiceBase * const_service_base = service.get();
|
||||
EXPECT_NE(nullptr, const_service_base->get_service_handle());
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT_THROW(
|
||||
{
|
||||
auto service = node->create_service<Empty>("invalid_service?", callback);
|
||||
}, rclcpp::exceptions::InvalidServiceNameError);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user