Compare commits

...

36 Commits

Author SHA1 Message Date
Karsten Knese
3293603396 0.7.7 2019-07-31 15:46:10 -07:00
Karsten Knese
50ec1e568a refine changelog text
Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-07-31 15:38:03 -07:00
Karsten Knese
607e290732 generate changelog
Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-07-31 15:11:58 -07:00
Scott K Logan
47ce42bc3f Use params from node '/**' from parameter YAML file (#805)
The short-term goal of this change is to enable the creation of a
parameter YAML file which is applied to each node, regardless of node
name or namespace.

Future work is to support all wildcard syntax in node names in
parameter YAML files.

This is a backport of #762 for Dashing.

Signed-off-by: Scott K Logan <logans@cottsay.net>
2019-07-31 14:05:01 -07:00
Scott K Logan
d2f052ee3d Fix a comparison with a sign mismatch (#804)
This is a backport of #771 for Dashing.

Signed-off-by: Scott K Logan <logans@cottsay.net>
2019-07-31 11:05:00 -07:00
Gonzo
b86127d721 changed on_parameter_event qos profile to rmw_qos_profile_parameter_events (#774) (#798)
Signed-off-by: alberto <alberto.soragna@gmail.com>
2019-07-30 15:06:44 -03:00
Michel Hidalgo
5cb6a6eeb5 Make TimeSource ignore use_sim_time events coming from other nodes. (#799) (#803)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
2019-07-30 12:44:39 -03:00
Karsten Knese
f41e33c2a7 use default parameter descriptor in parameters interface (#765) (#794)
* use default parameter descriptor in parameters interface

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

* use default parameter for value

Signed-off-by: Karsten Knese <karsten@openrobotics.org>
2019-07-29 11:24:19 -07:00
Esteve Fernandez
10c34ee9e5 Added support for const member functions (#763)
* Added support for const member functions

Signed-off-by: Esteve Fernandez <esteve@apache.org>

* Added signature for Windows

Signed-off-by: Esteve Fernandez <esteve@apache.org>

* Fix style

Signed-off-by: Esteve Fernandez <esteve@apache.org>

* Attempt at fixing function_traits for macOS

Signed-off-by: Esteve Fernandez <esteve@apache.org>
2019-07-29 10:44:27 -07:00
Dirk Thomas
6d3cbd39d1 Add default value to options in LifecycleNode construnctor. Update API documentation. (#775) (#801)
Signed-off-by: Esteve Fernandez <esteve@apache.org>
2019-07-26 15:39:05 -07:00
Chris Lalancette
bfee90ab7a 0.7.6 2019-06-12 20:13:10 +00:00
Chris Lalancette
1927f7e40e Changelog.
Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2019-06-12 20:12:58 +00:00
ivanpauno
f73d80e79c Ignore parameters overrides in set parameter methods when allowing undeclared parameters (#756)
* Ignore parameters overrides in set parameter methods when allowing undeclared parameters

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>

* Address reviewer comment

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-06-12 16:02:01 -04:00
Shane Loretz
e2e35570d5 Add rclcpp::create_timer() (#757)
* Add rclcpp::create_timer()

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Friendly overload with node-like object

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* forward<CallbackT>

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>

* Make sure test with NodeWrapper compiles

Signed-off-by: Shane Loretz <sloretz@osrfoundation.org>
2019-06-12 16:02:01 -04:00
Alberto Soragna
5c395d6651 checking origin of intra-process msg before taking them (#753)
Signed-off-by: alberto <alberto.soragna@gmail.com>
2019-06-12 16:02:01 -04:00
Jacob Perron
24080a458d 0.7.5 2019-05-30 17:31:20 -07:00
ivanpauno
8ff51833ad Avoid 'Intra process message no longer being stored when trying to ha… (#749)
Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-05-30 15:54:02 -03:00
Michael Carroll
347f8d0b1d 0.7.4
Signed-off-by: Michael Carroll <michael@openrobotics.org>
2019-05-29 18:53:14 -05:00
William Woodall
ecc95009f1 Rename parameter options (#745)
* rename initial_parameters in NodeOptions to parameter_overrides

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

* rename automatically_declare_initial_parameters to automatically_declare_parameters_from_overrides

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

* some additional renames I missed

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

* add test for setting after declaring with parameter overrides

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

* fixup NodeOptions docs

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

Co-Authored-By: chapulina <louise@openrobotics.org>

* clarify relationship between allow_undeclared_parameters and parameter_overrides

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-05-29 12:12:42 -07:00
roderick-koehle
d2b2f9124e Bionic use of strerror_r (#742)
Since API 23 Android Bionic uses the GNU convention for strerror_r.
Following bionic/libc line 96,
  https://android.googlesource.com/platform/bionic.git/+/refs/heads/master/libc/include/string.h

Signed-off-by: roderick-koehle <50633232+roderick-koehle@users.noreply.github.com>
2019-05-29 11:15:50 -07:00
ivanpauno
ca01555936 Enforce parameter ranges (#735)
Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-05-29 12:03:06 -03:00
Alberto Soragna
0723a0a6fc removed not used parameter client (#740)
* removed not used parameter client

Signed-off-by: alberto <alberto.soragna@gmail.com>

* moved parameter include directives to time source cpp file

Signed-off-by: alberto <alberto.soragna@gmail.com>
2019-05-28 14:52:32 -07:00
Dirk Thomas
8553fbea7f ensure removal of guard conditions of expired nodes from memory strategy (#741)
* change memory strategy API from vector of nodes to list of nodes

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>

* store guard_condition of node in executor and ensure that it is removed from the memory strategy

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>

* add unit test

Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-05-24 15:31:31 -07:00
Jacob Perron
131a11bba5 Guard against calling null goal response callback (#738)
Also make sure to invoke the goal response callback before the result callback.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-05-23 21:00:58 -07:00
Jacob Perron
29308dc8bc Fix typo in log warning message (#737)
Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-05-23 16:10:36 -07:00
Dirk Thomas
06275105fc don't use global arguments for components loaded into the manager (#736)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-05-23 13:06:23 -07:00
ivanpauno
30df5cdf36 Throw nice errors when creating a publisher with intraprocess communication and incompatible qos policy (#729)
* Throw nice errors when creating a publisher with intraprocess communication and history keep all or history depth 0.

Signed-off-by: ivanpauno <ivanpauno@ekumenlabs.com>
2019-05-22 15:38:10 -03:00
William Woodall
1a662d46fb 0.7.3 2019-05-20 16:12:29 -07:00
William Woodall
4467ce9913 changelogs
Signed-off-by: William Woodall <william@osrfoundation.org>
2019-05-20 16:12:05 -07:00
Emerson Knapp
005131dba8 I realize why the original was spelled wrong, volatile is a c++ keyword. Modify to not require learning a misspelling, and note why it can't have that name (#725)
Signed-off-by: Emerson Knapp <eknapp@amazon.com>
2019-05-17 18:18:58 -07:00
Emerson Knapp
05c19028f4 volitile -> volatile (#724)
Signed-off-by: Emerson Knapp <eknapp@amazon.com>
2019-05-17 15:37:38 -07:00
Dirk Thomas
a8f4d391f2 fix clang warning (#723)
Signed-off-by: Dirk Thomas <dirk-thomas@users.noreply.github.com>
2019-05-17 09:26:16 -07:00
Alberto Soragna
0682ceb3e1 Created on_parameter_event static function (#688)
* created static functions

Signed-off-by: alsora <alberto.soragna@gmail.com>
Signed-off-by: alberto soragna <alberto.soragna@gmail.com>

* updated on_parameter_event to new subscriber api

Signed-off-by: alberto soragna <alberto.soragna@gmail.com>

* Update parameter_client.hpp

Reorderd typenames in template

Signed-off-by: alberto soragna <alberto.soragna@gmail.com>

* updated API also for Synchronous client and fixed linter errors

Signed-off-by: alberto soragna <alberto.soragna@gmail.com>

* added empty line at the end of files

Signed-off-by: alberto soragna <alberto.soragna@gmail.com>

* fixed linter error

Signed-off-by: alsora <alberto.soragna@gmail.com>

* added parameter client tests

Signed-off-by: alsora <alberto.soragna@gmail.com>

* added missing includes in unit test

Signed-off-by: alsora <alberto.soragna@gmail.com>
2019-05-16 13:45:10 -07:00
Jacob Perron
2152e0574b Guard against ParameterNotDeclaredException in parameter service callbacks (#718)
Fixes #705.

If the set_parameters() call fails, it's nice to be able to return a partial result.
Since there is no convenient method to obtain a partial result, we call set_parameters()
once for each parameter.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-05-15 16:10:53 -07:00
Michael Jeronimo
1081e75079 Add missing template functionality to lifecycle_node. (#707)
* Add missing template functionality to lifecycle_node.

Recent changes to the node_parameters interface was accompanied by additions to the
node.hpp header and implementation files. However, these additions were not also made
to the corresponding lifecycle node files. This PR includes the changes required for
the lifecycle node.

Going forward, I suggest that any code like this that supplements the basic node interfaces
should either be factored out into a separate header that both node and lifecycle_node
include, or that the supplemental code simply be included in the appropriate node_interface
file directly, if possible. That way we can avoid code duplication and its symptoms which
is node and lifecycle_node getting out of sync (which they have several times).

Signed-off-by: Michael Jeronimo <michael.jeronimo@intel.com>

* consolidate documentation to just be in rclcpp/node.hpp

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

* fix visibility macros

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

* deprecation methods that were also deprecated in rclcpp::Node

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

* fixup variable name

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

* add missing template method implementations

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

* add more methods that were not ported to lifecycle node originally

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

* fix cpplint

Signed-off-by: William Woodall <william@osrfoundation.org>
2019-05-15 15:15:40 -07:00
Prajakta Gokhale
b17bbf31b3 Fix heap-use-after-free and memory leaks reported from test_node.cpp (#719)
Fix AddressSanitizer errors reported by test_node.cpp unit test.

Signed-off-by: Prajakta Gokhale <prajaktg@amazon.com>
2019-05-14 21:08:33 -07:00
48 changed files with 1866 additions and 256 deletions

View File

@@ -2,6 +2,49 @@
Changelog for package rclcpp
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.7.7 (2019-07-31)
------------------
* Enabled the creation of a parameter YAML file which is applied to each node. (`#805 <https://github.com/ros2/rclcpp/issues/805>`_)
* Fixed a signed/unsigned integer comparison compiler warning. (`#804 <https://github.com/ros2/rclcpp/issues/804>`_)
* Changed the QoS profile used when subscribing to parameter events to match the publishing side, i.e. ``rmw_qos_profile_parameter_events``. (`#798 <https://github.com/ros2/rclcpp/issues/798>`_)
* Changed the logic in TimeSource to ignore use_sim_time parameter events coming from other nodes. (`#803 <https://github.com/ros2/rclcpp/issues/803>`_)
* Added missing default values in the NodeParametersInterface. (`#794 <https://github.com/ros2/rclcpp/issues/794>`_)
* Added support for const member callback functions. (`#763 <https://github.com/ros2/rclcpp/issues/763>`_)
* Contributors: Esteve Fernandez, Gonzo, Karsten Knese, Michel Hidalgo, Scott K Logan
0.7.6 (2019-06-12)
------------------
* Ignore parameters overrides in set parameter methods when allowing undeclared parameters (`#756 <https://github.com/ros2/rclcpp/issues/756>`_)
* Add rclcpp::create_timer() (`#757 <https://github.com/ros2/rclcpp/issues/757>`_)
* checking origin of intra-process msg before taking them (`#753 <https://github.com/ros2/rclcpp/issues/753>`_)
* Contributors: Alberto Soragna, Shane Loretz, ivanpauno
0.7.5 (2019-05-30)
------------------
* Avoid 'Intra process message no longer being stored when trying to handle it' warning (`#749 <https://github.com/ros2/rclcpp/issues/749>`_)
* Contributors: ivanpauno
0.7.4 (2019-05-29)
------------------
* Rename parameter options (`#745 <https://github.com/ros2/rclcpp/issues/745>`_)
* Bionic use of strerror_r (`#742 <https://github.com/ros2/rclcpp/issues/742>`_)
* Enforce parameter ranges (`#735 <https://github.com/ros2/rclcpp/issues/735>`_)
* removed not used parameter client (`#740 <https://github.com/ros2/rclcpp/issues/740>`_)
* ensure removal of guard conditions of expired nodes from memory strategy (`#741 <https://github.com/ros2/rclcpp/issues/741>`_)
* Fix typo in log warning message (`#737 <https://github.com/ros2/rclcpp/issues/737>`_)
* Throw nice errors when creating a publisher with intraprocess communication and incompatible qos policy (`#729 <https://github.com/ros2/rclcpp/issues/729>`_)
* Contributors: Alberto Soragna, Dirk Thomas, Jacob Perron, William Woodall, ivanpauno, roderick-koehle
0.7.3 (2019-05-20)
------------------
* Fixed misspelling, volitile -> volatile (`#724 <https://github.com/ros2/rclcpp/issues/724>`_), and then fixed that since it is a C++ keyword to be ``durability_volatile`` (`#725 <https://github.com/ros2/rclcpp/issues/725>`_)
* Fixed a clang warning (`#723 <https://github.com/ros2/rclcpp/issues/723>`_)
* Added ``on_parameter_event`` static method to the ``AsyncParametersClient`` (`#688 <https://github.com/ros2/rclcpp/issues/688>`_)
* Added a guard against ``ParameterNotDeclaredException`` throwing from within the parameter service callbacks. (`#718 <https://github.com/ros2/rclcpp/issues/718>`_)
* Added missing template functionality to lifecycle_node. (`#707 <https://github.com/ros2/rclcpp/issues/707>`_)
* Fixed heap-use-after-free and memory leaks reported from ``test_node.cpp`` (`#719 <https://github.com/ros2/rclcpp/issues/719>`_)
* Contributors: Alberto Soragna, Dirk Thomas, Emerson Knapp, Jacob Perron, Michael Jeronimo, Prajakta Gokhale
0.7.2 (2019-05-08)
------------------
* Added new way to specify QoS settings for publishers and subscriptions. (`#713 <https://github.com/ros2/rclcpp/issues/713>`_)

View File

@@ -155,6 +155,18 @@ if(BUILD_TESTING)
)
target_link_libraries(test_client ${PROJECT_NAME})
endif()
ament_add_gtest(test_create_timer test/test_create_timer.cpp)
if(TARGET test_create_timer)
ament_target_dependencies(test_create_timer
"rcl_interfaces"
"rmw"
"rcl"
"rosidl_generator_cpp"
"rosidl_typesupport_cpp"
)
target_link_libraries(test_create_timer ${PROJECT_NAME})
target_include_directories(test_create_timer PRIVATE test/)
endif()
ament_add_gtest(test_expand_topic_or_service_name test/test_expand_topic_or_service_name.cpp)
if(TARGET test_expand_topic_or_service_name)
ament_target_dependencies(test_expand_topic_or_service_name
@@ -242,6 +254,13 @@ if(BUILD_TESTING)
)
target_link_libraries(test_node_global_args ${PROJECT_NAME})
endif()
ament_add_gtest(test_parameter_client test/test_parameter_client.cpp)
if(TARGET test_parameter_client)
ament_target_dependencies(test_parameter_client
"rcl_interfaces"
)
target_link_libraries(test_parameter_client ${PROJECT_NAME})
endif()
ament_add_gtest(test_parameter_events_filter test/test_parameter_events_filter.cpp)
if(TARGET test_parameter_events_filter)
ament_target_dependencies(test_parameter_events_filter

View File

@@ -0,0 +1,73 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__CREATE_TIMER_HPP_
#define RCLCPP__CREATE_TIMER_HPP_
#include <memory>
#include <string>
#include <utility>
#include "rclcpp/duration.hpp"
# include "rclcpp/node_interfaces/get_node_base_interface.hpp"
# include "rclcpp/node_interfaces/get_node_timers_interface.hpp"
#include "rclcpp/node_interfaces/node_base_interface.hpp"
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
namespace rclcpp
{
/// Create a timer with a given clock
/// \internal
template<typename CallbackT>
typename rclcpp::TimerBase::SharedPtr
create_timer(
node_interfaces::NodeBaseInterface * node_base,
node_interfaces::NodeTimersInterface * node_timers,
rclcpp::Clock::SharedPtr clock,
rclcpp::Duration period,
CallbackT && callback,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
{
auto timer = rclcpp::GenericTimer<CallbackT>::make_shared(
clock,
period.to_chrono<std::chrono::nanoseconds>(),
std::forward<CallbackT>(callback),
node_base->get_context());
node_timers->add_timer(timer, group);
return timer;
}
/// Create a timer with a given clock
template<typename NodeT, typename CallbackT>
typename rclcpp::TimerBase::SharedPtr
create_timer(
NodeT node,
rclcpp::Clock::SharedPtr clock,
rclcpp::Duration period,
CallbackT && callback,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
{
return create_timer(
rclcpp::node_interfaces::get_node_base_interface(node),
rclcpp::node_interfaces::get_node_timers_interface(node),
clock,
period,
std::forward<CallbackT>(callback),
group);
}
} // namespace rclcpp
#endif // RCLCPP__CREATE_TIMER_HPP_

View File

@@ -364,7 +364,8 @@ protected:
private:
RCLCPP_DISABLE_COPY(Executor)
std::vector<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr> weak_nodes_;
std::list<const rcl_guard_condition_t *> guard_conditions_;
};
} // namespace executor

View File

@@ -96,6 +96,24 @@ struct function_traits<
: function_traits<ReturnTypeT(Args ...)>
{};
// std::bind for object const methods
template<typename ClassT, typename ReturnTypeT, typename ... Args, typename ... FArgs>
#if defined _LIBCPP_VERSION // libc++ (Clang)
struct function_traits<std::__bind<ReturnTypeT (ClassT::*)(Args ...) const, FArgs ...>>
#elif defined _GLIBCXX_RELEASE // glibc++ (GNU C++ >= 7.1)
struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(FArgs ...))(Args ...) const>>
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
struct function_traits<std::_Bind<std::_Mem_fn<ReturnTypeT (ClassT::*)(Args ...) const>(FArgs ...)>>
#elif defined _MSC_VER // MS Visual Studio
struct function_traits<
std::_Binder<std::_Unforced, ReturnTypeT(__cdecl ClassT::*)(Args ...) const, FArgs ...>
>
#else
#error "Unsupported C++ compiler / standard library"
#endif
: function_traits<ReturnTypeT(Args ...)>
{};
// std::bind for free functions
template<typename ReturnTypeT, typename ... Args, typename ... FArgs>
#if defined _LIBCPP_VERSION // libc++ (Clang)

View File

@@ -15,8 +15,8 @@
#ifndef RCLCPP__MEMORY_STRATEGY_HPP_
#define RCLCPP__MEMORY_STRATEGY_HPP_
#include <list>
#include <memory>
#include <vector>
#include "rcl/allocator.h"
#include "rcl/wait.h"
@@ -42,11 +42,11 @@ class RCLCPP_PUBLIC MemoryStrategy
{
public:
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(MemoryStrategy)
using WeakNodeVector = std::vector<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>;
using WeakNodeList = std::list<rclcpp::node_interfaces::NodeBaseInterface::WeakPtr>;
virtual ~MemoryStrategy() = default;
virtual bool collect_entities(const WeakNodeVector & weak_nodes) = 0;
virtual bool collect_entities(const WeakNodeList & weak_nodes) = 0;
virtual size_t number_of_ready_subscriptions() const = 0;
virtual size_t number_of_ready_services() const = 0;
@@ -67,22 +67,22 @@ public:
virtual void
get_next_subscription(
rclcpp::executor::AnyExecutable & any_exec,
const WeakNodeVector & weak_nodes) = 0;
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_service(
rclcpp::executor::AnyExecutable & any_exec,
const WeakNodeVector & weak_nodes) = 0;
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_client(
rclcpp::executor::AnyExecutable & any_exec,
const WeakNodeVector & weak_nodes) = 0;
const WeakNodeList & weak_nodes) = 0;
virtual void
get_next_waitable(
rclcpp::executor::AnyExecutable & any_exec,
const WeakNodeVector & weak_nodes) = 0;
const WeakNodeList & weak_nodes) = 0;
virtual rcl_allocator_t
get_allocator() = 0;
@@ -90,42 +90,42 @@ public:
static rclcpp::SubscriptionBase::SharedPtr
get_subscription_by_handle(
std::shared_ptr<const rcl_subscription_t> subscriber_handle,
const WeakNodeVector & weak_nodes);
const WeakNodeList & weak_nodes);
static rclcpp::ServiceBase::SharedPtr
get_service_by_handle(
std::shared_ptr<const rcl_service_t> service_handle,
const WeakNodeVector & weak_nodes);
const WeakNodeList & weak_nodes);
static rclcpp::ClientBase::SharedPtr
get_client_by_handle(
std::shared_ptr<const rcl_client_t> client_handle,
const WeakNodeVector & weak_nodes);
const WeakNodeList & weak_nodes);
static rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
get_node_by_group(
rclcpp::callback_group::CallbackGroup::SharedPtr group,
const WeakNodeVector & weak_nodes);
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
get_group_by_subscription(
rclcpp::SubscriptionBase::SharedPtr subscription,
const WeakNodeVector & weak_nodes);
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
get_group_by_service(
rclcpp::ServiceBase::SharedPtr service,
const WeakNodeVector & weak_nodes);
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
get_group_by_client(
rclcpp::ClientBase::SharedPtr client,
const WeakNodeVector & weak_nodes);
const WeakNodeList & weak_nodes);
static rclcpp::callback_group::CallbackGroup::SharedPtr
get_group_by_waitable(
rclcpp::Waitable::SharedPtr waitable,
const WeakNodeVector & weak_nodes);
const WeakNodeList & weak_nodes);
};
} // namespace memory_strategy

View File

@@ -516,6 +516,7 @@ public:
* rclcpp::NodeOptions::allow_undeclared_parameters set to true.
* If undeclared parameters are allowed, then the parameter is implicitly
* declared with the default parameter meta data before being set.
* Parameter overrides are ignored by set_parameter.
*
* This method will result in any callback registered with
* set_on_parameters_set_callback to be called.
@@ -940,7 +941,6 @@ public:
void
register_param_change_callback(CallbackT && callback);
/// Get the fully-qualified names of all available nodes.
/**
* The fully-qualified name includes the local namespace and name of the node.

View File

@@ -0,0 +1,147 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
#include <memory>
#include <utility>
#include <type_traits>
#include "rclcpp/node_interfaces/node_base_interface.hpp"
/// This header provides the get_node_base_interface() template function.
/**
* This function is useful for getting the NodeBaseInterface pointer from
* various kinds of Node-like classes.
*
* It's able to get the NodeBaseInterface pointer so long as the class
* has a method called ``get_node_base_interface()`` which returns
* either a pointer (const or not) to a NodeBaseInterface or a
* std::shared_ptr to a NodeBaseInterface.
*/
namespace rclcpp
{
namespace node_interfaces
{
namespace detail
{
// This is a meta-programming checker for if a given Node-like object has a
// getter called get_node_base_interface() which returns various types,
// e.g. const pointer or a shared pointer.
template<typename NodeType, typename ReturnType>
struct has_get_node_base_interface
{
private:
template<typename T>
static constexpr
auto
check(T *)->typename std::is_same<
decltype(std::declval<T>().get_node_base_interface()),
ReturnType
>::type;
template<typename>
static constexpr
std::false_type
check(...);
public:
using type = decltype(check<NodeType>(nullptr));
static constexpr bool value = type::value;
};
// If NodeType is a pointer to NodeBaseInterface already (just normal function overload).
inline
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface_from_pointer(rclcpp::node_interfaces::NodeBaseInterface * pointer)
{
return pointer;
}
// If NodeType has a method called get_node_base_interface() which returns a shared pointer.
template<
typename NodeType,
typename std::enable_if<has_get_node_base_interface<
typename std::remove_pointer<NodeType>::type,
std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface>
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface_from_pointer(NodeType node_pointer)
{
return node_pointer->get_node_base_interface().get();
}
// If NodeType has a method called get_node_base_interface() which returns a pointer.
template<
typename NodeType,
typename std::enable_if<has_get_node_base_interface<
typename std::remove_pointer<NodeType>::type,
rclcpp::node_interfaces::NodeBaseInterface *
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface_from_pointer(NodeType node_pointer)
{
return node_pointer->get_node_base_interface();
}
// Forward shared_ptr's to const node pointer signatures.
template<
typename NodeType,
typename std::enable_if<std::is_same<
NodeType,
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface_from_pointer(NodeType node_shared_pointer)
{
return get_node_base_interface_from_pointer(node_shared_pointer->get());
}
} // namespace detail
/// Get the NodeBaseInterface as a pointer from a pointer to a "Node like" object.
template<
typename NodeType,
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface(NodeType && node_pointer)
{
// Forward pointers to detail implmentation directly.
return detail::get_node_base_interface_from_pointer(std::forward<NodeType>(node_pointer));
}
/// Get the NodeBaseInterface as a pointer from a "Node like" object.
template<
typename NodeType,
typename std::enable_if<!std::is_pointer<NodeType>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeBaseInterface *
get_node_base_interface(NodeType && node_reference)
{
// Forward references to detail implmentation as a pointer.
return detail::get_node_base_interface_from_pointer(&node_reference);
}
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_

View File

@@ -0,0 +1,147 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
#include <memory>
#include <utility>
#include <type_traits>
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
/// This header provides the get_node_timers_interface() template function.
/**
* This function is useful for getting the NodeTimersInterface pointer from
* various kinds of Node-like classes.
*
* It's able to get the NodeTimersInterface pointer so long as the class
* has a method called ``get_node_timers_interface()`` which returns
* either a pointer (const or not) to a NodeTimersInterface or a
* std::shared_ptr to a NodeTimersInterface.
*/
namespace rclcpp
{
namespace node_interfaces
{
namespace detail
{
// This is a meta-programming checker for if a given Node-like object has a
// getter called get_node_timers_interface() which returns various types,
// e.g. const pointer or a shared pointer.
template<typename NodeType, typename ReturnType>
struct has_get_node_timers_interface
{
private:
template<typename T>
static constexpr
auto
check(T *)->typename std::is_same<
decltype(std::declval<T>().get_node_timers_interface()),
ReturnType
>::type;
template<typename>
static constexpr
std::false_type
check(...);
public:
using type = decltype(check<NodeType>(nullptr));
static constexpr bool value = type::value;
};
// If NodeType is a pointer to NodeTimersInterface already (just normal function overload).
inline
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface_from_pointer(rclcpp::node_interfaces::NodeTimersInterface * pointer)
{
return pointer;
}
// If NodeType has a method called get_node_timers_interface() which returns a shared pointer.
template<
typename NodeType,
typename std::enable_if<has_get_node_timers_interface<
typename std::remove_pointer<NodeType>::type,
std::shared_ptr<rclcpp::node_interfaces::NodeTimersInterface>
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface_from_pointer(NodeType node_pointer)
{
return node_pointer->get_node_timers_interface().get();
}
// If NodeType has a method called get_node_timers_interface() which returns a pointer.
template<
typename NodeType,
typename std::enable_if<has_get_node_timers_interface<
typename std::remove_pointer<NodeType>::type,
rclcpp::node_interfaces::NodeTimersInterface *
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface_from_pointer(NodeType node_pointer)
{
return node_pointer->get_node_timers_interface();
}
// Forward shared_ptr's to const node pointer signatures.
template<
typename NodeType,
typename std::enable_if<std::is_same<
NodeType,
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface_from_pointer(NodeType node_shared_pointer)
{
return get_node_timers_interface_from_pointer(node_shared_pointer->get());
}
} // namespace detail
/// Get the NodeTimersInterface as a pointer from a pointer to a "Node like" object.
template<
typename NodeType,
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface(NodeType && node_pointer)
{
// Forward pointers to detail implmentation directly.
return detail::get_node_timers_interface_from_pointer(std::forward<NodeType>(node_pointer));
}
/// Get the NodeTimersInterface as a pointer from a "Node like" object.
template<
typename NodeType,
typename std::enable_if<!std::is_pointer<NodeType>::value, int>::type = 0
>
rclcpp::node_interfaces::NodeTimersInterface *
get_node_timers_interface(NodeType && node_reference)
{
// Forward references to detail implmentation as a pointer.
return detail::get_node_timers_interface_from_pointer(&node_reference);
}
} // namespace node_interfaces
} // namespace rclcpp
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_

View File

@@ -63,13 +63,13 @@ public:
const node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
const node_interfaces::NodeServicesInterface::SharedPtr node_services,
const node_interfaces::NodeClockInterface::SharedPtr node_clock,
const std::vector<Parameter> & initial_parameters,
const std::vector<Parameter> & parameter_overrides,
bool start_parameter_services,
bool start_parameter_event_publisher,
const rclcpp::QoS & parameter_event_qos,
const rclcpp::PublisherOptionsBase & parameter_event_publisher_options,
bool allow_undeclared_parameters,
bool automatically_declare_initial_parameters);
bool automatically_declare_parameters_from_overrides);
RCLCPP_PUBLIC
virtual
@@ -143,7 +143,7 @@ public:
RCLCPP_PUBLIC
const std::map<std::string, rclcpp::ParameterValue> &
get_initial_parameter_values() const override;
get_parameter_overrides() const override;
private:
RCLCPP_DISABLE_COPY(NodeParameters)
@@ -154,7 +154,7 @@ private:
std::map<std::string, ParameterInfo> parameters_;
std::map<std::string, rclcpp::ParameterValue> initial_parameter_values_;
std::map<std::string, rclcpp::ParameterValue> parameter_overrides_;
bool allow_undeclared_ = false;

View File

@@ -51,8 +51,9 @@ public:
const rclcpp::ParameterValue &
declare_parameter(
const std::string & name,
const rclcpp::ParameterValue & default_value,
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor) = 0;
const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
rcl_interfaces::msg::ParameterDescriptor()) = 0;
/// Undeclare a parameter.
/**
@@ -183,7 +184,7 @@ public:
RCLCPP_PUBLIC
virtual
const std::map<std::string, rclcpp::ParameterValue> &
get_initial_parameter_values() const = 0;
get_parameter_overrides() const = 0;
};
} // namespace node_interfaces

View File

@@ -40,7 +40,7 @@ public:
*
* - context = rclcpp::contexts::default_context::get_global_default_context()
* - arguments = {}
* - initial_parameters = {}
* - parameter_overrides = {}
* - use_global_arguments = true
* - use_intra_process_comms = false
* - start_parameter_services = true
@@ -49,7 +49,7 @@ public:
* - with history setting and depth from rmw_qos_profile_parameter_events
* - parameter_event_publisher_options = rclcpp::PublisherOptionsBase
* - allow_undeclared_parameters = false
* - automatically_declare_initial_parameters = false
* - automatically_declare_parameters_from_overrides = false
* - allocator = rcl_get_default_allocator()
*
* \param[in] allocator allocator to use in construction of NodeOptions.
@@ -107,31 +107,31 @@ public:
NodeOptions &
arguments(const std::vector<std::string> & arguments);
/// Return a reference to the list of initial parameters.
/// Return a reference to the list of parameter overrides.
RCLCPP_PUBLIC
std::vector<rclcpp::Parameter> &
initial_parameters();
parameter_overrides();
RCLCPP_PUBLIC
const std::vector<rclcpp::Parameter> &
initial_parameters() const;
parameter_overrides() const;
/// Set the initial parameters, return this for parameter idiom.
/// Set the parameters overrides, return this for parameter idiom.
/**
* These initial parameter values are used to change the initial value
* These parameter overrides are used to change the initial value
* of declared parameters within the node, overriding hard coded default
* values if necessary.
*/
RCLCPP_PUBLIC
NodeOptions &
initial_parameters(const std::vector<rclcpp::Parameter> & initial_parameters);
parameter_overrides(const std::vector<rclcpp::Parameter> & parameter_overrides);
/// Append a single initial parameter, parameter idiom style.
/// Append a single parameter override, parameter idiom style.
template<typename ParameterT>
NodeOptions &
append_initial_parameter(const std::string & name, const ParameterT & value)
append_parameter_override(const std::string & name, const ParameterT & value)
{
this->initial_parameters().emplace_back(name, rclcpp::ParameterValue(value));
this->parameter_overrides().emplace_back(name, rclcpp::ParameterValue(value));
return *this;
}
@@ -247,29 +247,35 @@ public:
* If true, allow any parameter name to be set on the node without first
* being declared.
* Otherwise, setting an undeclared parameter will raise an exception.
*
* This option being true does not affect parameter_overrides, as the first
* set action will implicitly declare the parameter and therefore consider
* any parameter overrides.
*/
RCLCPP_PUBLIC
NodeOptions &
allow_undeclared_parameters(bool allow_undeclared_parameters);
/// Return the automatically_declare_initial_parameters flag.
/// Return the automatically_declare_parameters_from_overrides flag.
RCLCPP_PUBLIC
bool
automatically_declare_initial_parameters() const;
automatically_declare_parameters_from_overrides() const;
/// Set the automatically_declare_initial_parameters, return this.
/// Set the automatically_declare_parameters_from_overrides, return this.
/**
* If true, automatically iterate through the node's initial parameters and
* If true, automatically iterate through the node's parameter overrides and
* implicitly declare any that have not already been declared.
* Otherwise, parameters passed to the node's initial_parameters, and/or the
* global initial parameter values, which are not explicitly declared will
* not appear on the node at all.
* Otherwise, parameters passed to the node's parameter_overrides, and/or the
* global arguments (e.g. parameter overrides from a YAML file), which are
* not explicitly declared will not appear on the node at all, even if
* `allow_undeclared_parameters` is true.
* Already declared parameters will not be re-declared, and parameters
* declared in this way will use the default constructed ParameterDescriptor.
*/
RCLCPP_PUBLIC
NodeOptions &
automatically_declare_initial_parameters(bool automatically_declare_initial_parameters);
automatically_declare_parameters_from_overrides(
bool automatically_declare_parameters_from_overrides);
/// Return the rcl_allocator_t to be used.
RCLCPP_PUBLIC
@@ -302,7 +308,7 @@ private:
std::vector<std::string> arguments_ {};
std::vector<rclcpp::Parameter> initial_parameters_ {};
std::vector<rclcpp::Parameter> parameter_overrides_ {};
bool use_global_arguments_ {true};
@@ -320,7 +326,7 @@ private:
bool allow_undeclared_parameters_ {false};
bool automatically_declare_initial_parameters_ {false};
bool automatically_declare_parameters_from_overrides_ {false};
rcl_allocator_t allocator_ {rcl_get_default_allocator()};
};

View File

@@ -115,14 +115,41 @@ public:
on_parameter_event(
CallbackT && callback,
const rclcpp::QoS & qos = (
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_default))
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events))
),
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
))
{
return this->on_parameter_event(
this->node_topics_interface_,
callback,
qos,
options);
}
/**
* The NodeT type only needs to have a method called get_node_topics_interface()
* which returns a shared_ptr to a NodeTopicsInterface, or be a
* NodeTopicsInterface pointer itself.
*/
template<
typename CallbackT,
typename NodeT,
typename AllocatorT = std::allocator<void>>
static typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
on_parameter_event(
NodeT && node,
CallbackT && callback,
const rclcpp::QoS & qos = (
rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_parameter_events))
),
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
))
{
return rclcpp::create_subscription<rcl_interfaces::msg::ParameterEvent>(
this->node_topics_interface_,
node,
"parameter_events",
qos,
std::forward<CallbackT>(callback),
@@ -266,7 +293,26 @@ public:
typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
on_parameter_event(CallbackT && callback)
{
return async_parameters_client_->on_parameter_event(std::forward<CallbackT>(callback));
return async_parameters_client_->on_parameter_event(
std::forward<CallbackT>(callback));
}
/**
* The NodeT type only needs to have a method called get_node_topics_interface()
* which returns a shared_ptr to a NodeTopicsInterface, or be a
* NodeTopicsInterface pointer itself.
*/
template<
typename CallbackT,
typename NodeT>
static typename rclcpp::Subscription<rcl_interfaces::msg::ParameterEvent>::SharedPtr
on_parameter_event(
NodeT && node,
CallbackT && callback)
{
return AsyncParametersClient::on_parameter_event(
node,
std::forward<CallbackT>(callback));
}
RCLCPP_PUBLIC

View File

@@ -105,8 +105,11 @@ public:
durability(rmw_qos_durability_policy_t durability);
/// Set the durability setting to volatile.
/**
* Note that this cannot be named `volatile` because it is a C++ keyword.
*/
QoS &
volitile();
durability_volatile();
/// Set the durability setting to transient local.
QoS &

View File

@@ -150,7 +150,7 @@ public:
);
}
bool collect_entities(const WeakNodeVector & weak_nodes)
bool collect_entities(const WeakNodeList & weak_nodes)
{
bool has_invalid_weak_nodes = false;
for (auto & weak_node : weak_nodes) {
@@ -265,7 +265,7 @@ public:
virtual void
get_next_subscription(
executor::AnyExecutable & any_exec,
const WeakNodeVector & weak_nodes)
const WeakNodeList & weak_nodes)
{
auto it = subscription_handles_.begin();
while (it != subscription_handles_.end()) {
@@ -309,7 +309,7 @@ public:
virtual void
get_next_service(
executor::AnyExecutable & any_exec,
const WeakNodeVector & weak_nodes)
const WeakNodeList & weak_nodes)
{
auto it = service_handles_.begin();
while (it != service_handles_.end()) {
@@ -342,7 +342,7 @@ public:
}
virtual void
get_next_client(executor::AnyExecutable & any_exec, const WeakNodeVector & weak_nodes)
get_next_client(executor::AnyExecutable & any_exec, const WeakNodeList & weak_nodes)
{
auto it = client_handles_.begin();
while (it != client_handles_.end()) {
@@ -375,7 +375,7 @@ public:
}
virtual void
get_next_waitable(executor::AnyExecutable & any_exec, const WeakNodeVector & weak_nodes)
get_next_waitable(executor::AnyExecutable & any_exec, const WeakNodeList & weak_nodes)
{
auto it = waitable_handles_.begin();
while (it != waitable_handles_.end()) {

View File

@@ -170,6 +170,13 @@ public:
// However, this can only really happen if this node has it disabled, but the other doesn't.
return;
}
if (!matches_any_intra_process_publishers(&message_info.publisher_gid)) {
// This intra-process message has not been created by a publisher from this context.
// we should ignore this copy of the message.
return;
}
if (any_callback_.use_take_shared_method()) {
ConstMessageSharedPtr msg;
take_intra_process_message(
@@ -178,10 +185,11 @@ public:
intra_process_subscription_id_,
msg);
if (!msg) {
// This either occurred because the publisher no longer exists or the
// message requested is no longer being stored.
RCLCPP_WARN(get_logger("rclcpp"),
"Intra process message not longer being stored when trying to handle it");
// This can happen when having two nodes in different process both using intraprocess
// communication. It could happen too if the publisher no longer exists or the requested
// message is not longer being stored.
// TODO(ivanpauno): Print a warn message in the last two cases described above,
// but not in the first one.
return;
}
any_callback_.dispatch_intra_process(msg, message_info);
@@ -193,10 +201,11 @@ public:
intra_process_subscription_id_,
msg);
if (!msg) {
// This either occurred because the publisher no longer exists or the
// message requested is no longer being stored.
RCLCPP_WARN(get_logger("rclcpp"),
"Intra process message not longer being stored when trying to handle it");
// This can happen when having two nodes in different process both using intraprocess
// communication. It could happen too if the publisher no longer exists or the requested
// message is not longer being stored.
// TODO(ivanpauno): Print a warn message in the last two cases described above,
// but not in the first one.
return;
}
any_callback_.dispatch_intra_process(std::move(msg), message_info);

View File

@@ -25,8 +25,6 @@
#include "rcl_interfaces/msg/parameter_event.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/parameter_client.hpp"
#include "rclcpp/parameter_events_filter.hpp"
namespace rclcpp
@@ -100,9 +98,6 @@ private:
// Destroy the subscription for the clock topic
void destroy_clock_sub();
// Parameter Client pointer
std::shared_ptr<rclcpp::AsyncParametersClient> parameter_client_;
// Parameter Event subscription
using ParamMessageT = rcl_interfaces::msg::ParameterEvent;
using ParamSubscriptionT = rclcpp::Subscription<ParamMessageT, Alloc>;

View File

@@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>rclcpp</name>
<version>0.7.2</version>
<version>0.7.7</version>
<description>The ROS client library in C++.</description>
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
<license>Apache License 2.0</license>

View File

@@ -91,6 +91,10 @@ Executor::~Executor()
}
}
weak_nodes_.clear();
for (auto & guard_condition : guard_conditions_) {
memory_strategy_->remove_guard_condition(guard_condition);
}
guard_conditions_.clear();
// Finalize the wait set.
if (rcl_wait_set_fini(&wait_set_) != RCL_RET_OK) {
@@ -128,6 +132,7 @@ Executor::add_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_pt
}
}
weak_nodes_.push_back(node_ptr);
guard_conditions_.push_back(node_ptr->get_notify_guard_condition());
if (notify) {
// Interrupt waiting to handle new node
if (rcl_trigger_guard_condition(&interrupt_guard_condition_) != RCL_RET_OK) {
@@ -148,17 +153,21 @@ void
Executor::remove_node(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr, bool notify)
{
bool node_removed = false;
weak_nodes_.erase(
std::remove_if(
weak_nodes_.begin(), weak_nodes_.end(),
[&](rclcpp::node_interfaces::NodeBaseInterface::WeakPtr & i)
{
bool matched = (i.lock() == node_ptr);
node_removed |= matched;
return matched;
{
auto node_it = weak_nodes_.begin();
auto gc_it = guard_conditions_.begin();
while (node_it != weak_nodes_.end()) {
bool matched = (node_it->lock() == node_ptr);
if (matched) {
node_it = weak_nodes_.erase(node_it);
gc_it = guard_conditions_.erase(gc_it);
node_removed = true;
} else {
++node_it;
++gc_it;
}
)
);
}
}
std::atomic_bool & has_executor = node_ptr->get_associated_with_executor_atomic();
has_executor.store(false);
if (notify) {
@@ -420,15 +429,18 @@ Executor::wait_for_work(std::chrono::nanoseconds timeout)
// Clean up any invalid nodes, if they were detected
if (has_invalid_weak_nodes) {
weak_nodes_.erase(
remove_if(
weak_nodes_.begin(), weak_nodes_.end(),
[](rclcpp::node_interfaces::NodeBaseInterface::WeakPtr i)
{
return i.expired();
}
)
);
auto node_it = weak_nodes_.begin();
auto gc_it = guard_conditions_.begin();
while (node_it != weak_nodes_.end()) {
if (node_it->expired()) {
node_it = weak_nodes_.erase(node_it);
memory_strategy_->remove_guard_condition(*gc_it);
gc_it = guard_conditions_.erase(gc_it);
} else {
++node_it;
++gc_it;
}
}
}
// clear wait set
if (rcl_wait_set_clear(&wait_set_) != RCL_RET_OK) {

View File

@@ -20,7 +20,7 @@ using rclcpp::memory_strategy::MemoryStrategy;
rclcpp::SubscriptionBase::SharedPtr
MemoryStrategy::get_subscription_by_handle(
std::shared_ptr<const rcl_subscription_t> subscriber_handle,
const WeakNodeVector & weak_nodes)
const WeakNodeList & weak_nodes)
{
for (auto & weak_node : weak_nodes) {
auto node = weak_node.lock();
@@ -51,7 +51,7 @@ MemoryStrategy::get_subscription_by_handle(
rclcpp::ServiceBase::SharedPtr
MemoryStrategy::get_service_by_handle(
std::shared_ptr<const rcl_service_t> service_handle,
const WeakNodeVector & weak_nodes)
const WeakNodeList & weak_nodes)
{
for (auto & weak_node : weak_nodes) {
auto node = weak_node.lock();
@@ -77,7 +77,7 @@ MemoryStrategy::get_service_by_handle(
rclcpp::ClientBase::SharedPtr
MemoryStrategy::get_client_by_handle(
std::shared_ptr<const rcl_client_t> client_handle,
const WeakNodeVector & weak_nodes)
const WeakNodeList & weak_nodes)
{
for (auto & weak_node : weak_nodes) {
auto node = weak_node.lock();
@@ -103,7 +103,7 @@ MemoryStrategy::get_client_by_handle(
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
MemoryStrategy::get_node_by_group(
rclcpp::callback_group::CallbackGroup::SharedPtr group,
const WeakNodeVector & weak_nodes)
const WeakNodeList & weak_nodes)
{
if (!group) {
return nullptr;
@@ -126,7 +126,7 @@ MemoryStrategy::get_node_by_group(
rclcpp::callback_group::CallbackGroup::SharedPtr
MemoryStrategy::get_group_by_subscription(
rclcpp::SubscriptionBase::SharedPtr subscription,
const WeakNodeVector & weak_nodes)
const WeakNodeList & weak_nodes)
{
for (auto & weak_node : weak_nodes) {
auto node = weak_node.lock();
@@ -152,7 +152,7 @@ MemoryStrategy::get_group_by_subscription(
rclcpp::callback_group::CallbackGroup::SharedPtr
MemoryStrategy::get_group_by_service(
rclcpp::ServiceBase::SharedPtr service,
const WeakNodeVector & weak_nodes)
const WeakNodeList & weak_nodes)
{
for (auto & weak_node : weak_nodes) {
auto node = weak_node.lock();
@@ -178,7 +178,7 @@ MemoryStrategy::get_group_by_service(
rclcpp::callback_group::CallbackGroup::SharedPtr
MemoryStrategy::get_group_by_client(
rclcpp::ClientBase::SharedPtr client,
const WeakNodeVector & weak_nodes)
const WeakNodeList & weak_nodes)
{
for (auto & weak_node : weak_nodes) {
auto node = weak_node.lock();
@@ -204,7 +204,7 @@ MemoryStrategy::get_group_by_client(
rclcpp::callback_group::CallbackGroup::SharedPtr
MemoryStrategy::get_group_by_waitable(
rclcpp::Waitable::SharedPtr waitable,
const WeakNodeVector & weak_nodes)
const WeakNodeList & weak_nodes)
{
for (auto & weak_node : weak_nodes) {
auto node = weak_node.lock();

View File

@@ -132,13 +132,13 @@ Node::Node(
node_topics_,
node_services_,
node_clock_,
options.initial_parameters(),
options.parameter_overrides(),
options.start_parameter_services(),
options.start_parameter_event_publisher(),
options.parameter_event_qos(),
options.parameter_event_publisher_options(),
options.allow_undeclared_parameters(),
options.automatically_declare_initial_parameters()
options.automatically_declare_parameters_from_overrides()
)),
node_time_source_(new rclcpp::node_interfaces::NodeTimeSource(
node_base_,

View File

@@ -26,6 +26,9 @@
#include <rcl_yaml_param_parser/parser.h>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <map>
#include <memory>
#include <sstream>
@@ -48,13 +51,13 @@ NodeParameters::NodeParameters(
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics,
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services,
const rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock,
const std::vector<rclcpp::Parameter> & initial_parameters,
const std::vector<rclcpp::Parameter> & parameter_overrides,
bool start_parameter_services,
bool start_parameter_event_publisher,
const rclcpp::QoS & parameter_event_qos,
const rclcpp::PublisherOptionsBase & parameter_event_publisher_options,
bool allow_undeclared_parameters,
bool automatically_declare_initial_parameters)
bool automatically_declare_parameters_from_overrides)
: allow_undeclared_(allow_undeclared_parameters),
events_publisher_(nullptr),
node_logging_(node_logging),
@@ -141,28 +144,29 @@ NodeParameters::NodeParameters(
rclcpp::ParameterMap initial_map = rclcpp::parameter_map_from(yaml_params);
rcl_yaml_node_struct_fini(yaml_params);
auto iter = initial_map.find(combined_name_);
if (initial_map.end() == iter) {
continue;
}
// Combine parameter yaml files, overwriting values in older ones
for (auto & param : iter->second) {
initial_parameter_values_[param.get_name()] =
rclcpp::ParameterValue(param.get_value_message());
for (auto iter = initial_map.begin(); initial_map.end() != iter; iter++) {
// TODO(cottsay) implement further wildcard matching
if (iter->first == "/**" || iter->first == combined_name_) {
// Combine parameter yaml files, overwriting values in older ones
for (auto & param : iter->second) {
parameter_overrides_[param.get_name()] =
rclcpp::ParameterValue(param.get_value_message());
}
}
}
}
// initial values passed to constructor overwrite yaml file sources
for (auto & param : initial_parameters) {
initial_parameter_values_[param.get_name()] =
// parameter overrides passed to constructor will overwrite overrides from yaml file sources
for (auto & param : parameter_overrides) {
parameter_overrides_[param.get_name()] =
rclcpp::ParameterValue(param.get_value_message());
}
// If asked, initialize any parameters that ended up in the initial parameter values,
// but did not get declared explcitily by this point.
if (automatically_declare_initial_parameters) {
for (const auto & pair : this->get_initial_parameter_values()) {
if (automatically_declare_parameters_from_overrides) {
for (const auto & pair : this->get_parameter_overrides()) {
if (!this->has_parameter(pair.first)) {
this->declare_parameter(
pair.first,
@@ -185,6 +189,103 @@ __lockless_has_parameter(
return parameters.find(name) != parameters.end();
}
// see https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
RCLCPP_LOCAL
bool
__are_doubles_equal(double x, double y, size_t ulp = 100)
{
return std::abs(x - y) <= std::numeric_limits<double>::epsilon() * std::abs(x + y) * ulp;
}
RCLCPP_LOCAL
inline
void
format_reason(std::string & reason, const std::string & name, const char * range_type)
{
std::ostringstream ss;
ss << "Parameter {" << name << "} doesn't comply with " << range_type << " range.";
reason = ss.str();
}
RCLCPP_LOCAL
rcl_interfaces::msg::SetParametersResult
__check_parameter_value_in_range(
const rcl_interfaces::msg::ParameterDescriptor & descriptor,
const rclcpp::ParameterValue & value)
{
rcl_interfaces::msg::SetParametersResult result;
result.successful = true;
if (!descriptor.integer_range.empty() && value.get_type() == rclcpp::PARAMETER_INTEGER) {
int64_t v = value.get<int64_t>();
auto integer_range = descriptor.integer_range.at(0);
if (v == integer_range.from_value || v == integer_range.to_value) {
return result;
}
if ((v < integer_range.from_value) || (v > integer_range.to_value)) {
result.successful = false;
format_reason(result.reason, descriptor.name, "integer");
return result;
}
if (integer_range.step == 0) {
return result;
}
if (((v - integer_range.from_value) % integer_range.step) == 0) {
return result;
}
result.successful = false;
format_reason(result.reason, descriptor.name, "integer");
return result;
}
if (!descriptor.floating_point_range.empty() && value.get_type() == rclcpp::PARAMETER_DOUBLE) {
double v = value.get<double>();
auto fp_range = descriptor.floating_point_range.at(0);
if (__are_doubles_equal(v, fp_range.from_value) ||
__are_doubles_equal(v, fp_range.to_value))
{
return result;
}
if ((v < fp_range.from_value) || (v > fp_range.to_value)) {
result.successful = false;
format_reason(result.reason, descriptor.name, "floating point");
return result;
}
if (fp_range.step == 0.0) {
return result;
}
double rounded_div = std::round((v - fp_range.from_value) / fp_range.step);
if (__are_doubles_equal(v, fp_range.from_value + rounded_div * fp_range.step)) {
return result;
}
result.successful = false;
format_reason(result.reason, descriptor.name, "floating point");
return result;
}
return result;
}
// Return true if parameter values comply with the descriptors in parameter_infos.
RCLCPP_LOCAL
rcl_interfaces::msg::SetParametersResult
__check_parameters(
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameter_infos,
const std::vector<rclcpp::Parameter> & parameters)
{
rcl_interfaces::msg::SetParametersResult result;
result.successful = true;
for (const rclcpp::Parameter & parameter : parameters) {
const rcl_interfaces::msg::ParameterDescriptor & descriptor =
parameter_infos[parameter.get_name()].descriptor;
result = __check_parameter_value_in_range(
descriptor,
parameter.get_parameter_value());
if (!result.successful) {
break;
}
}
return result;
}
using OnParametersSetCallbackType =
rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;
@@ -201,7 +302,14 @@ __set_parameters_atomically_common(
if (on_set_parameters_callback) {
result = on_set_parameters_callback(parameters);
}
if (!result.successful) {
return result;
}
// Check if the value being set complies with the descriptor.
result = __check_parameters(parameter_infos, parameters);
if (!result.successful) {
return result;
}
// If accepted, actually set the values.
if (result.successful) {
for (size_t i = 0; i < parameters.size(); ++i) {
@@ -223,19 +331,20 @@ __declare_parameter_common(
const rclcpp::ParameterValue & default_value,
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> & parameters_out,
const std::map<std::string, rclcpp::ParameterValue> & initial_values,
const std::map<std::string, rclcpp::ParameterValue> & overrides,
OnParametersSetCallbackType on_set_parameters_callback,
rcl_interfaces::msg::ParameterEvent * parameter_event_out)
rcl_interfaces::msg::ParameterEvent * parameter_event_out,
bool use_overrides = true)
{
using rclcpp::node_interfaces::ParameterInfo;
std::map<std::string, ParameterInfo> parameter_infos {{name, ParameterInfo()}};
parameter_infos.at(name).descriptor = parameter_descriptor;
// Use the value from the initial_values if available, otherwise use the default.
// Use the value from the overrides if available, otherwise use the default.
const rclcpp::ParameterValue * initial_value = &default_value;
auto initial_value_it = initial_values.find(name);
if (initial_value_it != initial_values.end()) {
initial_value = &initial_value_it->second;
auto overrides_it = overrides.find(name);
if (use_overrides && overrides_it != overrides.end()) {
initial_value = &overrides_it->second;
}
// Check with the user's callback to see if the initial value can be set.
@@ -282,7 +391,7 @@ NodeParameters::declare_parameter(
default_value,
parameter_descriptor,
parameters_,
initial_parameter_values_,
parameter_overrides_,
on_parameters_set_callback_,
&parameter_event);
@@ -413,9 +522,10 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
parameter_to_be_declared->get_parameter_value(),
rcl_interfaces::msg::ParameterDescriptor(), // Implicit declare uses default descriptor.
staged_parameter_changes,
initial_parameter_values_,
parameter_overrides_,
nullptr, // callback is explicitly null, so that it is called only once, when setting below.
&parameter_event_msg);
&parameter_event_msg,
false);
if (!result.successful) {
// Declare failed, return knowing that nothing was changed because the
// staged changes were not applied.
@@ -493,10 +603,10 @@ NodeParameters::set_parameters_atomically(const std::vector<rclcpp::Parameter> &
// assumption: the parameter to be undeclared should be in the parameter infos map
assert(it != parameters_.end());
if (it != parameters_.end()) {
// Remove it and update the parameter event message.
parameters_.erase(it);
// Update the parameter event message and remove it.
parameter_event_msg.deleted_parameters.push_back(
rclcpp::Parameter(it->first, it->second.value).to_parameter_msg());
parameters_.erase(it);
}
}
@@ -733,7 +843,7 @@ NodeParameters::register_param_change_callback(ParametersCallbackFunction callba
#endif
const std::map<std::string, rclcpp::ParameterValue> &
NodeParameters::get_initial_parameter_values() const
NodeParameters::get_parameter_overrides() const
{
return initial_parameter_values_;
return parameter_overrides_;
}

View File

@@ -47,6 +47,14 @@ NodeTopics::create_publisher(
// Get the intra process manager instance for this context.
auto ipm = context->get_sub_context<rclcpp::intra_process_manager::IntraProcessManager>();
// Register the publisher with the intra process manager.
if (publisher_options.qos.history == RMW_QOS_POLICY_HISTORY_KEEP_ALL) {
throw std::invalid_argument(
"intraprocess communication is not allowed with keep all history qos policy");
}
if (publisher_options.qos.depth == 0) {
throw std::invalid_argument(
"intraprocess communication is not allowed with a zero qos history depth value");
}
uint64_t intra_process_publisher_id = ipm->add_publisher(publisher);
publisher->setup_intra_process(
intra_process_publisher_id,

View File

@@ -44,6 +44,9 @@ rcl_node_options_t_destructor(rcl_node_options_t * node_options)
"failed to finalize rcl node options: %s", rcl_get_error_string().str);
rcl_reset_error();
}
delete node_options;
node_options = nullptr;
}
}
} // namespace detail
@@ -64,14 +67,14 @@ NodeOptions::operator=(const NodeOptions & other)
if (this != &other) {
this->context_ = other.context_;
this->arguments_ = other.arguments_;
this->initial_parameters_ = other.initial_parameters_;
this->parameter_overrides_ = other.parameter_overrides_;
this->use_global_arguments_ = other.use_global_arguments_;
this->use_intra_process_comms_ = other.use_intra_process_comms_;
this->start_parameter_services_ = other.start_parameter_services_;
this->allocator_ = other.allocator_;
this->allow_undeclared_parameters_ = other.allow_undeclared_parameters_;
this->automatically_declare_initial_parameters_ =
other.automatically_declare_initial_parameters_;
this->automatically_declare_parameters_from_overrides_ =
other.automatically_declare_parameters_from_overrides_;
}
return *this;
}
@@ -95,7 +98,7 @@ NodeOptions::get_rcl_node_options() const
}
}
if (this->arguments_.size() > std::numeric_limits<int>::max()) {
if (this->arguments_.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
throw_from_rcl_error(RCL_RET_INVALID_ARGUMENT, "Too many args");
}
@@ -139,21 +142,21 @@ NodeOptions::arguments(const std::vector<std::string> & arguments)
}
std::vector<rclcpp::Parameter> &
NodeOptions::initial_parameters()
NodeOptions::parameter_overrides()
{
return this->initial_parameters_;
return this->parameter_overrides_;
}
const std::vector<rclcpp::Parameter> &
NodeOptions::initial_parameters() const
NodeOptions::parameter_overrides() const
{
return this->initial_parameters_;
return this->parameter_overrides_;
}
NodeOptions &
NodeOptions::initial_parameters(const std::vector<rclcpp::Parameter> & initial_parameters)
NodeOptions::parameter_overrides(const std::vector<rclcpp::Parameter> & parameter_overrides)
{
this->initial_parameters_ = initial_parameters;
this->parameter_overrides_ = parameter_overrides;
return *this;
}
@@ -251,16 +254,17 @@ NodeOptions::allow_undeclared_parameters(bool allow_undeclared_parameters)
}
bool
NodeOptions::automatically_declare_initial_parameters() const
NodeOptions::automatically_declare_parameters_from_overrides() const
{
return this->automatically_declare_initial_parameters_;
return this->automatically_declare_parameters_from_overrides_;
}
NodeOptions &
NodeOptions::automatically_declare_initial_parameters(
bool automatically_declare_initial_parameters)
NodeOptions::automatically_declare_parameters_from_overrides(
bool automatically_declare_parameters_from_overrides)
{
this->automatically_declare_initial_parameters_ = automatically_declare_initial_parameters;
this->automatically_declare_parameters_from_overrides_ =
automatically_declare_parameters_from_overrides;
return *this;
}

View File

@@ -57,11 +57,15 @@ ParameterService::ParameterService(
const std::shared_ptr<rcl_interfaces::srv::GetParameterTypes::Request> request,
std::shared_ptr<rcl_interfaces::srv::GetParameterTypes::Response> response)
{
auto types = node_params->get_parameter_types(request->names);
std::transform(types.cbegin(), types.cend(),
std::back_inserter(response->types), [](const uint8_t & type) {
return static_cast<rclcpp::ParameterType>(type);
});
try {
auto types = node_params->get_parameter_types(request->names);
std::transform(types.cbegin(), types.cend(),
std::back_inserter(response->types), [](const uint8_t & type) {
return static_cast<rclcpp::ParameterType>(type);
});
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to get parameter types: %s", ex.what());
}
},
qos_profile, nullptr);
@@ -73,12 +77,20 @@ ParameterService::ParameterService(
const std::shared_ptr<rcl_interfaces::srv::SetParameters::Request> request,
std::shared_ptr<rcl_interfaces::srv::SetParameters::Response> response)
{
std::vector<rclcpp::Parameter> pvariants;
// Set parameters one-by-one, since there's no way to return a partial result if
// set_parameters() fails.
auto result = rcl_interfaces::msg::SetParametersResult();
for (auto & p : request->parameters) {
pvariants.push_back(rclcpp::Parameter::from_parameter_msg(p));
try {
result = node_params->set_parameters_atomically(
{rclcpp::Parameter::from_parameter_msg(p)});
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to set parameter: %s", ex.what());
result.successful = false;
result.reason = ex.what();
}
response->results.push_back(result);
}
auto results = node_params->set_parameters(pvariants);
response->results = results;
},
qos_profile, nullptr);
@@ -96,8 +108,15 @@ ParameterService::ParameterService(
[](const rcl_interfaces::msg::Parameter & p) {
return rclcpp::Parameter::from_parameter_msg(p);
});
auto result = node_params->set_parameters_atomically(pvariants);
response->result = result;
try {
auto result = node_params->set_parameters_atomically(pvariants);
response->result = result;
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
RCLCPP_WARN(
rclcpp::get_logger("rclcpp"), "Failed to set parameters atomically: %s", ex.what());
response->result.successful = false;
response->result.reason = "One or more parameters wer not declared before setting";
}
},
qos_profile, nullptr);
@@ -109,8 +128,12 @@ ParameterService::ParameterService(
const std::shared_ptr<rcl_interfaces::srv::DescribeParameters::Request> request,
std::shared_ptr<rcl_interfaces::srv::DescribeParameters::Response> response)
{
auto descriptors = node_params->describe_parameters(request->names);
response->descriptors = descriptors;
try {
auto descriptors = node_params->describe_parameters(request->names);
response->descriptors = descriptors;
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to describe parameters: %s", ex.what());
}
},
qos_profile, nullptr);

View File

@@ -265,7 +265,7 @@ PublisherBase::setup_intra_process(
{
// Intraprocess configuration is not allowed with "durability" qos policy non "volatile".
if (this->get_actual_qos().durability != RMW_QOS_POLICY_DURABILITY_VOLATILE) {
throw exceptions::InvalidParametersException(
throw std::invalid_argument(
"intraprocess communication is not allowed with durability qos policy non-volatile");
}
const char * topic_name = this->get_topic_name();

View File

@@ -120,7 +120,7 @@ QoS::durability(rmw_qos_durability_policy_t durability)
}
QoS &
QoS::volitile()
QoS::durability_volatile()
{
return this->durability(RMW_QOS_POLICY_DURABILITY_VOLATILE);
}

View File

@@ -165,13 +165,15 @@ __safe_strerror(int errnum, char * buffer, size_t buffer_length)
{
#if defined(_WIN32)
strerror_s(buffer, buffer_length, errnum);
#elif (defined(_GNU_SOURCE) && !defined(ANDROID))
#elif defined(_GNU_SOURCE) && (!defined(ANDROID) || __ANDROID_API__ >= 23)
/* GNU-specific */
char * msg = strerror_r(errnum, buffer, buffer_length);
if (msg != buffer) {
strncpy(buffer, msg, buffer_length);
buffer[buffer_length - 1] = '\0';
}
#else
/* XSI-compliant */
int error_status = strerror_r(errnum, buffer, buffer_length);
if (error_status != 0) {
throw std::runtime_error("Failed to get error string for errno: " + std::to_string(errnum));

View File

@@ -25,6 +25,8 @@
#include "rclcpp/exceptions.hpp"
#include "rclcpp/logging.hpp"
#include "rclcpp/node.hpp"
#include "rclcpp/parameter_client.hpp"
#include "rclcpp/parameter_events_filter.hpp"
#include "rclcpp/time.hpp"
#include "rclcpp/time_source.hpp"
@@ -103,22 +105,16 @@ void TimeSource::attachNode(
}
// TODO(tfoote) use parameters interface not subscribe to events via topic ticketed #609
parameter_client_ = std::make_shared<rclcpp::AsyncParametersClient>(
node_base_,
parameter_subscription_ = rclcpp::AsyncParametersClient::on_parameter_event(
node_topics_,
node_graph_,
node_services_
);
parameter_subscription_ =
parameter_client_->on_parameter_event(std::bind(&TimeSource::on_parameter_event,
this, std::placeholders::_1));
std::bind(&TimeSource::on_parameter_event, this, std::placeholders::_1));
}
void TimeSource::detachNode()
{
this->ros_time_active_ = false;
clock_subscription_.reset();
parameter_client_.reset();
parameter_subscription_.reset();
node_base_.reset();
node_topics_.reset();
node_graph_.reset();
@@ -224,13 +220,17 @@ void TimeSource::destroy_clock_sub()
void TimeSource::on_parameter_event(const rcl_interfaces::msg::ParameterEvent::SharedPtr event)
{
// Filter out events on 'use_sim_time' parameter instances in other nodes.
if (event->node != node_base_->get_fully_qualified_name()) {
return;
}
// Filter for only 'use_sim_time' being added or changed.
rclcpp::ParameterEventsFilter filter(event, {"use_sim_time"},
{rclcpp::ParameterEventsFilter::EventType::NEW,
rclcpp::ParameterEventsFilter::EventType::CHANGED});
for (auto & it : filter.get_events()) {
if (it.second->value.type != ParameterType::PARAMETER_BOOL) {
RCLCPP_ERROR(logger_, "use_sim_time parameter set to something besides a bool");
RCLCPP_ERROR(logger_, "use_sim_time parameter cannot be set to anything but a bool");
continue;
}
if (it.second->value.bool_value) {

View File

@@ -0,0 +1,63 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <gtest/gtest.h>
#include <atomic>
#include <chrono>
#include <memory>
#include "rclcpp/create_timer.hpp"
#include "rclcpp/executors.hpp"
#include "rclcpp/node.hpp"
#include "node_interfaces/node_wrapper.hpp"
using namespace std::chrono_literals;
TEST(TestCreateTimer, timer_executes)
{
rclcpp::init(0, nullptr);
auto node = std::make_shared<rclcpp::Node>("test_create_timer_node");
std::atomic<bool> got_callback{false};
rclcpp::TimerBase::SharedPtr timer;
timer = rclcpp::create_timer(
node,
node->get_clock(),
rclcpp::Duration(0ms),
[&got_callback, &timer]() {
got_callback = true;
timer->cancel();
});
rclcpp::spin_some(node);
ASSERT_TRUE(got_callback);
rclcpp::shutdown();
}
TEST(TestCreateTimer, call_with_node_wrapper_compiles)
{
rclcpp::init(0, nullptr);
NodeWrapper node("test_create_timer_call_with_node_wrapper_compiles");
rclcpp::TimerBase::SharedPtr timer;
timer = rclcpp::create_timer(
node,
node.get_node_clock_interface()->get_clock(),
rclcpp::Duration(0ms),
[]() {});
rclcpp::shutdown();
}

View File

@@ -60,3 +60,10 @@ TEST_F(TestExecutors, detachOnDestruction) {
EXPECT_NO_THROW(executor.add_node(node));
}
}
// Make sure that the executor can automatically remove expired nodes correctly
TEST_F(TestExecutors, addTemporaryNode) {
rclcpp::executors::SingleThreadedExecutor executor;
executor.add_node(std::make_shared<rclcpp::Node>("temporary_node"));
EXPECT_NO_THROW(executor.spin_some());
}

View File

@@ -36,15 +36,15 @@ TEST_F(TestFindWeakNodes, allocator_strategy_with_weak_nodes) {
rclcpp::memory_strategies::allocator_memory_strategy::AllocatorMemoryStrategy<>>();
auto existing_node = rclcpp::Node::make_shared("existing_node");
auto dead_node = rclcpp::Node::make_shared("dead_node");
rclcpp::memory_strategy::MemoryStrategy::WeakNodeVector weak_nodes;
rclcpp::memory_strategy::MemoryStrategy::WeakNodeList weak_nodes;
weak_nodes.push_back(existing_node->get_node_base_interface());
weak_nodes.push_back(dead_node->get_node_base_interface());
// AND
// Delete dead_node, creating a dangling pointer in weak_nodes
dead_node.reset();
ASSERT_FALSE(weak_nodes[0].expired());
ASSERT_TRUE(weak_nodes[1].expired());
ASSERT_FALSE(weak_nodes.front().expired());
ASSERT_TRUE(weak_nodes.back().expired());
// WHEN
bool has_invalid_weak_nodes = memory_strategy->collect_entities(weak_nodes);
@@ -64,11 +64,11 @@ TEST_F(TestFindWeakNodes, allocator_strategy_no_weak_nodes) {
rclcpp::memory_strategies::allocator_memory_strategy::AllocatorMemoryStrategy<>>();
auto existing_node1 = rclcpp::Node::make_shared("existing_node1");
auto existing_node2 = rclcpp::Node::make_shared("existing_node2");
rclcpp::memory_strategy::MemoryStrategy::WeakNodeVector weak_nodes;
rclcpp::memory_strategy::MemoryStrategy::WeakNodeList weak_nodes;
weak_nodes.push_back(existing_node1->get_node_base_interface());
weak_nodes.push_back(existing_node2->get_node_base_interface());
ASSERT_FALSE(weak_nodes[0].expired());
ASSERT_FALSE(weak_nodes[1].expired());
ASSERT_FALSE(weak_nodes.front().expired());
ASSERT_FALSE(weak_nodes.back().expired());
// WHEN
bool has_invalid_weak_nodes = memory_strategy->collect_entities(weak_nodes);

View File

@@ -80,6 +80,12 @@ struct ObjectMember
return 7;
}
int callback_one_bool_const(bool a) const
{
(void)a;
return 7;
}
int callback_two_bools(bool a, bool b)
{
(void)a;
@@ -394,6 +400,16 @@ TEST(TestFunctionTraits, argument_types) {
rclcpp::function_traits::function_traits<decltype(bind_one_bool)>::template argument_type<0>
>::value, "Functor accepts a bool as first argument");
auto bind_one_bool_const = std::bind(
&ObjectMember::callback_one_bool_const, &object_member, std::placeholders::_1);
static_assert(
std::is_same<
bool,
rclcpp::function_traits::function_traits<decltype(bind_one_bool_const)>::template
argument_type<0>
>::value, "Functor accepts a bool as first argument");
auto bind_two_bools = std::bind(
&ObjectMember::callback_two_bools, &object_member, std::placeholders::_1,
std::placeholders::_2);
@@ -561,6 +577,14 @@ TEST(TestFunctionTraits, check_arguments) {
static_assert(
rclcpp::function_traits::check_arguments<decltype(bind_one_bool), bool>::value,
"Functor accepts a single bool as arguments");
auto bind_one_bool_const = std::bind(
&ObjectMember::callback_one_bool_const, &object_member, std::placeholders::_1);
// Test std::bind functions
static_assert(
rclcpp::function_traits::check_arguments<decltype(bind_one_bool_const), bool>::value,
"Functor accepts a single bool as arguments");
}
/*

View File

@@ -37,6 +37,9 @@ public:
PublisherBase()
: mock_topic_name(""), mock_queue_size(0) {}
virtual ~PublisherBase()
{}
const char * get_topic_name() const
{
return mock_topic_name.c_str();

View File

@@ -365,8 +365,10 @@ TEST_F(TestNode, declare_parameter_with_no_initial_values) {
TEST_F(TestNode, declare_parameter_with_initial_values) {
// test cases with initial values
rclcpp::NodeOptions no;
no.initial_parameters({
no.parameter_overrides({
{"parameter_no_default", 42},
{"parameter_no_default_set", 42},
{"parameter_no_default_set_cvref", 42},
{"parameter_and_default", 42},
{"parameter_custom", 42},
{"parameter_template", 42},
@@ -381,6 +383,25 @@ TEST_F(TestNode, declare_parameter_with_initial_values) {
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get<int>(), 42);
}
{
// no default, with initial, and set after
rclcpp::ParameterValue value = node->declare_parameter("parameter_no_default_set");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get<int>(), 42);
// check that the value is changed after a set
node->set_parameter({"parameter_no_default_set", 44});
EXPECT_EQ(node->get_parameter("parameter_no_default_set").get_value<int>(), 44);
}
{
// no default, with initial
const rclcpp::ParameterValue & value =
node->declare_parameter("parameter_no_default_set_cvref");
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get<int>(), 42);
// check that the value is changed after a set
node->set_parameter({"parameter_no_default_set_cvref", 44});
EXPECT_EQ(value.get<int>(), 44);
}
{
// int default, with initial
rclcpp::ParameterValue default_value(43);
@@ -695,12 +716,370 @@ TEST_F(TestNode, set_parameter_undeclared_parameters_not_allowed) {
EXPECT_FALSE(node->has_parameter(name));
}
{
// setting a parameter with integer range descriptor
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.integer_range.resize(1);
auto & integer_range = descriptor.integer_range.at(0);
integer_range.from_value = 10;
integer_range.to_value = 18;
integer_range.step = 2;
node->declare_parameter(name, 10, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get_value<int64_t>(), 10);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 14)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 14);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 18)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 15)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 20)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 8)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
}
{
// setting a parameter with integer range descriptor, from_value > to_value
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.integer_range.resize(1);
auto & integer_range = descriptor.integer_range.at(0);
integer_range.from_value = 20;
integer_range.to_value = 18;
integer_range.step = 1;
node->declare_parameter(name, 20, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get_value<int64_t>(), 20);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 18)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 19)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 10)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 25)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
}
{
// setting a parameter with integer range descriptor, from_value = to_value
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.integer_range.resize(1);
auto & integer_range = descriptor.integer_range.at(0);
integer_range.from_value = 18;
integer_range.to_value = 18;
integer_range.step = 1;
node->declare_parameter(name, 18, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get_value<int64_t>(), 18);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 17)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 19)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
}
{
// setting a parameter with integer range descriptor, step > distance(from_value, to_value)
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.integer_range.resize(1);
auto & integer_range = descriptor.integer_range.at(0);
integer_range.from_value = 18;
integer_range.to_value = 25;
integer_range.step = 10;
node->declare_parameter(name, 18, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get_value<int64_t>(), 18);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 25)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 17)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 19)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 26)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
}
{
// setting a parameter with integer range descriptor, distance not multiple of the step.
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.integer_range.resize(1);
auto & integer_range = descriptor.integer_range.at(0);
integer_range.from_value = 18;
integer_range.to_value = 28;
integer_range.step = 7;
node->declare_parameter(name, 18, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get_value<int64_t>(), 18);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 28)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 28);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 25)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 17)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 19)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 32)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 25);
}
{
// setting a parameter with integer range descriptor, step=0
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.integer_range.resize(1);
auto & integer_range = descriptor.integer_range.at(0);
integer_range.from_value = 10;
integer_range.to_value = 18;
integer_range.step = 0;
node->declare_parameter(name, 10, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get_value<int64_t>(), 10);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 11);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 15)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 15);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 18)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 19)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<int64_t>(), 18);
}
{
// setting a parameter with integer range descriptor and wrong default value will throw
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.integer_range.resize(1);
auto & integer_range = descriptor.integer_range.at(0);
integer_range.from_value = 10;
integer_range.to_value = 18;
integer_range.step = 2;
ASSERT_THROW(
node->declare_parameter(name, 42, descriptor),
rclcpp::exceptions::InvalidParameterValueException);
}
{
// setting a parameter with floating point range descriptor
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.floating_point_range.resize(1);
auto & floating_point_range = descriptor.floating_point_range.at(0);
floating_point_range.from_value = 10.0;
floating_point_range.to_value = 11.0;
floating_point_range.step = 0.2;
node->declare_parameter(name, 10.0, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
EXPECT_EQ(value.get_value<double>(), 10.0);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 10.2)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.2);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.3)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 12.0)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.4)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
}
{
// setting a parameter with floating point range descriptor, negative step
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.floating_point_range.resize(1);
auto & floating_point_range = descriptor.floating_point_range.at(0);
floating_point_range.from_value = 10.0;
floating_point_range.to_value = 11.0;
floating_point_range.step = -0.2;
node->declare_parameter(name, 10.0, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
EXPECT_EQ(value.get_value<double>(), 10.0);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 10.2)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.2);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.3)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 12.0)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.4)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
}
{
// setting a parameter with floating point range descriptor, from_value > to_value
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.floating_point_range.resize(1);
auto & floating_point_range = descriptor.floating_point_range.at(0);
floating_point_range.from_value = 11.0;
floating_point_range.to_value = 10.0;
floating_point_range.step = 0.2;
node->declare_parameter(name, 10.0, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
EXPECT_EQ(value.get_value<double>(), 10.0);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.2)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 12.0)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.4)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
}
{
// setting a parameter with floating point range descriptor, from_value = to_value
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.floating_point_range.resize(1);
auto & floating_point_range = descriptor.floating_point_range.at(0);
floating_point_range.from_value = 10.0;
floating_point_range.to_value = 10.0;
floating_point_range.step = 0.2;
node->declare_parameter(name, 10.0, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
EXPECT_EQ(value.get_value<double>(), 10.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.2)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 12.0)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.4)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.0);
}
{
// setting a parameter with floating point range descriptor, step > distance
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.floating_point_range.resize(1);
auto & floating_point_range = descriptor.floating_point_range.at(0);
floating_point_range.from_value = 10.0;
floating_point_range.to_value = 11.0;
floating_point_range.step = 2.2;
node->declare_parameter(name, 10.0, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
EXPECT_EQ(value.get_value<double>(), 10.0);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 12.2)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 7.8)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
}
{
// setting a parameter with floating point range descriptor, distance not multiple of the step.
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.floating_point_range.resize(1);
auto & floating_point_range = descriptor.floating_point_range.at(0);
floating_point_range.from_value = 10.0;
floating_point_range.to_value = 11.0;
floating_point_range.step = 0.7;
node->declare_parameter(name, 10.0, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
EXPECT_EQ(value.get_value<double>(), 10.0);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 10.7)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.7);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.4)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.7);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.3)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.7);
}
{
// setting a parameter with floating point range descriptor, step=0
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.floating_point_range.resize(1);
auto & floating_point_range = descriptor.floating_point_range.at(0);
floating_point_range.from_value = 10.0;
floating_point_range.to_value = 11.0;
floating_point_range.step = 0.0;
node->declare_parameter(name, 10.0, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE);
EXPECT_EQ(value.get_value<double>(), 10.0);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 10.0001)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.0001);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 10.5479051)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 10.5479051);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 11.0)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 11.001)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.999)).successful);
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
}
{
// setting a parameter with a different type is still possible
// when having a descriptor specifying a type (type is a status, not a constraint).
auto name = "parameter"_unq;
rcl_interfaces::msg::ParameterDescriptor descriptor;
descriptor.type = rclcpp::PARAMETER_INTEGER;
node->declare_parameter(name, 42, descriptor);
EXPECT_TRUE(node->has_parameter(name));
auto value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER);
EXPECT_EQ(value.get_value<int64_t>(), 42);
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, "asd")).successful);
EXPECT_TRUE(node->has_parameter(name));
value = node->get_parameter(name);
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_STRING);
EXPECT_EQ(value.get_value<std::string>(), "asd");
}
}
TEST_F(TestNode, set_parameter_undeclared_parameters_allowed) {
auto node = std::make_shared<rclcpp::Node>(
"test_set_parameter_node"_unq,
rclcpp::NodeOptions().allow_undeclared_parameters(true));
rclcpp::NodeOptions no;
no.parameter_overrides({
{"parameter_with_override", 30},
});
no.allow_undeclared_parameters(true);
auto node = std::make_shared<rclcpp::Node>("test_set_parameter_node"_unq, no);
{
// overrides are ignored when not declaring a parameter
auto name = "parameter_with_override";
EXPECT_FALSE(node->has_parameter(name));
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name, 43)).successful);
EXPECT_TRUE(node->has_parameter(name));
EXPECT_EQ(node->get_parameter(name).get_value<int>(), 43);
}
{
// normal use (declare first) still works with this true
auto name = "parameter"_unq;

View File

@@ -0,0 +1,155 @@
// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <gtest/gtest.h>
#include <string>
#include <memory>
#include "rclcpp/rclcpp.hpp"
#include "rcl_interfaces/msg/parameter_event.hpp"
class TestParameterClient : public ::testing::Test
{
public:
void OnMessage(const rcl_interfaces::msg::ParameterEvent::SharedPtr event)
{
(void)event;
}
protected:
static void SetUpTestCase()
{
rclcpp::init(0, nullptr);
}
void SetUp()
{
node = std::make_shared<rclcpp::Node>("test_parameter_client", "/ns");
}
void TearDown()
{
node.reset();
}
rclcpp::Node::SharedPtr node;
};
/*
Testing async parameter client construction and destruction.
*/
TEST_F(TestParameterClient, async_construction_and_destruction) {
{
auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(node);
(void)asynchronous_client;
}
{
auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(
node->get_node_base_interface(),
node->get_node_topics_interface(),
node->get_node_graph_interface(),
node->get_node_services_interface());
(void)asynchronous_client;
}
{
ASSERT_THROW({
std::make_shared<rclcpp::AsyncParametersClient>(node, "invalid_remote_node?");
}, rclcpp::exceptions::InvalidServiceNameError);
}
}
/*
Testing sync parameter client construction and destruction.
*/
TEST_F(TestParameterClient, sync_construction_and_destruction) {
{
auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(node);
(void)synchronous_client;
}
{
auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
node);
(void)synchronous_client;
}
{
auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
node->get_node_base_interface(),
node->get_node_topics_interface(),
node->get_node_graph_interface(),
node->get_node_services_interface());
(void)synchronous_client;
}
{
ASSERT_THROW({
std::make_shared<rclcpp::SyncParametersClient>(node, "invalid_remote_node?");
}, rclcpp::exceptions::InvalidServiceNameError);
}
}
/*
Testing different methods for parameter event subscription from asynchronous clients.
*/
TEST_F(TestParameterClient, async_parameter_event_subscription) {
auto callback = std::bind(&TestParameterClient::OnMessage, this, std::placeholders::_1);
{
auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(node);
auto event_sub = asynchronous_client->on_parameter_event(callback);
(void)event_sub;
}
{
auto event_sub = rclcpp::AsyncParametersClient::on_parameter_event(node, callback);
(void)event_sub;
}
{
auto event_sub = rclcpp::AsyncParametersClient::on_parameter_event(
node->get_node_topics_interface(),
callback);
(void)event_sub;
}
}
/*
Testing different methods for parameter event subscription from synchronous clients.
*/
TEST_F(TestParameterClient, sync_parameter_event_subscription) {
auto callback = std::bind(&TestParameterClient::OnMessage, this, std::placeholders::_1);
{
auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(node);
auto event_sub = synchronous_client->on_parameter_event(callback);
(void)event_sub;
}
{
auto event_sub = rclcpp::SyncParametersClient::on_parameter_event(node, callback);
(void)event_sub;
}
{
auto event_sub = rclcpp::SyncParametersClient::on_parameter_event(
node->get_node_topics_interface(),
callback);
(void)event_sub;
}
}

View File

@@ -16,6 +16,7 @@
#include <string>
#include <memory>
#include <vector>
#include "rclcpp/exceptions.hpp"
#include "rclcpp/rclcpp.hpp"
@@ -24,12 +25,13 @@
class TestPublisher : public ::testing::Test
{
protected:
public:
static void SetUpTestCase()
{
rclcpp::init(0, nullptr);
}
protected:
void initialize(const rclcpp::NodeOptions & node_options = rclcpp::NodeOptions())
{
node = std::make_shared<rclcpp::Node>("my_node", "/ns", node_options);
@@ -43,6 +45,25 @@ protected:
rclcpp::Node::SharedPtr node;
};
struct TestParameters
{
TestParameters(rclcpp::QoS qos, std::string description)
: qos(qos), description(description) {}
rclcpp::QoS qos;
std::string description;
};
std::ostream & operator<<(std::ostream & out, const TestParameters & params)
{
out << params.description;
return out;
}
class TestPublisherInvalidIntraprocessQos
: public TestPublisher,
public ::testing::WithParamInterface<TestParameters>
{};
class TestPublisherSub : public ::testing::Test
{
protected:
@@ -65,14 +86,6 @@ protected:
rclcpp::Node::SharedPtr subnode;
};
static constexpr rmw_qos_profile_t invalid_qos_profile()
{
rmw_qos_profile_t profile = rmw_qos_profile_default;
profile.depth = 1;
profile.durability = RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL;
return profile;
}
/*
Testing publisher construction and destruction.
*/
@@ -165,29 +178,43 @@ TEST_F(TestPublisher, various_creation_signatures) {
/*
Testing publisher with intraprocess enabled and invalid QoS
*/
TEST_F(TestPublisher, intraprocess_with_invalid_qos) {
TEST_P(TestPublisherInvalidIntraprocessQos, test_publisher_throws) {
initialize(rclcpp::NodeOptions().use_intra_process_comms(true));
rmw_qos_profile_t qos = invalid_qos_profile();
rclcpp::QoS qos = GetParam().qos;
using rcl_interfaces::msg::IntraProcessMessage;
{
#if !defined(_WIN32)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#else // !defined(_WIN32)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif
ASSERT_THROW(
{auto publisher = node->create_publisher<IntraProcessMessage>("topic", qos);},
rclcpp::exceptions::InvalidParametersException);
#if !defined(_WIN32)
# pragma GCC diagnostic pop
#else // !defined(_WIN32)
# pragma warning(pop)
#endif
std::invalid_argument);
}
}
static std::vector<TestParameters> invalid_qos_profiles()
{
std::vector<TestParameters> parameters;
parameters.reserve(3);
parameters.push_back(
TestParameters(
rclcpp::QoS(rclcpp::KeepLast(10)).transient_local(),
"transient_local_qos"));
parameters.push_back(
TestParameters(
rclcpp::QoS(rclcpp::KeepLast(0)),
"keep_last_qos_with_zero_history_depth"));
parameters.push_back(
TestParameters(
rclcpp::QoS(rclcpp::KeepAll()),
"keep_all_qos"));
return parameters;
}
INSTANTIATE_TEST_CASE_P(
TestPublisherThrows, TestPublisherInvalidIntraprocessQos,
::testing::ValuesIn(invalid_qos_profiles()),
::testing::PrintToStringParamName());
/*
Testing publisher construction and destruction for subnodes.
*/

View File

@@ -3,6 +3,23 @@ Changelog for package rclcpp_action
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.7.7 (2019-07-31)
------------------
0.7.6 (2019-06-12)
------------------
0.7.5 (2019-05-30)
------------------
0.7.4 (2019-05-29)
------------------
* Guard against calling null goal response callback (`#738 <https://github.com/ros2/rclcpp/issues/738>`_)
* Contributors: Jacob Perron
0.7.3 (2019-05-20)
------------------
0.7.2 (2019-05-08)
------------------
* Added return code to CancelGoal service response. (`#710 <https://github.com/ros2/rclcpp/issues/710>`_)

View File

@@ -368,21 +368,23 @@ public:
// Do not use std::make_shared as friendship cannot be forwarded.
std::shared_ptr<GoalHandle> goal_handle(
new GoalHandle(goal_info, options.feedback_callback, options.result_callback));
{
std::lock_guard<std::mutex> guard(goal_handles_mutex_);
goal_handles_[goal_handle->get_goal_id()] = goal_handle;
}
promise->set_value(goal_handle);
if (options.goal_response_callback) {
options.goal_response_callback(future);
}
if (options.result_callback) {
try {
this->make_result_aware(goal_handle);
} catch (...) {
promise->set_exception(std::current_exception());
options.goal_response_callback(future);
return;
}
}
std::lock_guard<std::mutex> guard(goal_handles_mutex_);
goal_handles_[goal_handle->get_goal_id()] = goal_handle;
promise->set_value(goal_handle);
if (options.goal_response_callback) {
options.goal_response_callback(future);
}
});
return future;
}

View File

@@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>rclcpp_action</name>
<version>0.7.2</version>
<version>0.7.7</version>
<description>Adds action APIs for C++.</description>
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
<license>Apache License 2.0</license>

View File

@@ -2,6 +2,24 @@
Changelog for package rclcpp_components
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.7.7 (2019-07-31)
------------------
0.7.6 (2019-06-12)
------------------
0.7.5 (2019-05-30)
------------------
0.7.4 (2019-05-29)
------------------
* Rename parameter options (`#745 <https://github.com/ros2/rclcpp/issues/745>`_)
* don't use global arguments for components loaded into the manager (`#736 <https://github.com/ros2/rclcpp/issues/736>`_)
* Contributors: Dirk Thomas, William Woodall
0.7.3 (2019-05-20)
------------------
0.7.2 (2019-05-08)
------------------
* Updated to support changes to ``Node::get_node_names()``. (`#698 <https://github.com/ros2/rclcpp/issues/698>`_)

View File

@@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>rclcpp_components</name>
<version>0.7.2</version>
<version>0.7.7</version>
<description>Package containing tools for dynamically loadable components</description>
<maintainer email="michael@openrobotics.org">Michael Carroll</maintainer>
<license>Apache License 2.0</license>

View File

@@ -149,7 +149,8 @@ ComponentManager::OnLoadNode(
}
auto options = rclcpp::NodeOptions()
.initial_parameters(parameters)
.use_global_arguments(false)
.parameter_overrides(parameters)
.arguments(remap_rules);
auto node_id = unique_id++;

View File

@@ -3,6 +3,27 @@ Changelog for package rclcpp_lifecycle
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.7.7 (2019-07-31)
------------------
* Added a default value to node options in LifecycleNode constructor to match node constructor. Updated API documentation. (`#801 <https://github.com/ros2/rclcpp/issues/801>`_)
* Contributors: Esteve Fernandez, Dirk Thomas
0.7.6 (2019-06-12)
------------------
0.7.5 (2019-05-30)
------------------
0.7.4 (2019-05-29)
------------------
* Rename parameter options (`#745 <https://github.com/ros2/rclcpp/issues/745>`_)
* Contributors: William Woodall
0.7.3 (2019-05-20)
------------------
* Added missing template functionality to lifecycle_node. (`#707 <https://github.com/ros2/rclcpp/issues/707>`_)
* Contributors: Michael Jeronimo
0.7.2 (2019-05-08)
------------------
* Added new way to specify QoS settings for publishers and subscriptions. (`#713 <https://github.com/ros2/rclcpp/issues/713>`_)

View File

@@ -15,10 +15,11 @@
#ifndef RCLCPP_LIFECYCLE__LIFECYCLE_NODE_HPP_
#define RCLCPP_LIFECYCLE__LIFECYCLE_NODE_HPP_
#include <string>
#include <map>
#include <vector>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "rcl/error_handling.h"
#include "rcl/node.h"
@@ -114,14 +115,13 @@ public:
/**
* \param[in] node_name Name of the node.
* \param[in] namespace_ Namespace of the node.
* \param[in] context The context for the node (usually represents the state of a process).
* \param[in] options Additional options to control creation of the node.
*/
RCLCPP_LIFECYCLE_PUBLIC
LifecycleNode(
const std::string & node_name,
const std::string & namespace_,
const rclcpp::NodeOptions & options);
const rclcpp::NodeOptions & options = rclcpp::NodeOptions());
RCLCPP_LIFECYCLE_PUBLIC
virtual ~LifecycleNode();
@@ -333,15 +333,100 @@ public:
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
/// Declare and initialize a parameter, return the effective value.
/**
* \sa rclcpp::Node::declare_parameter
*/
RCLCPP_LIFECYCLE_PUBLIC
const rclcpp::ParameterValue &
declare_parameter(
const std::string & name,
const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
rcl_interfaces::msg::ParameterDescriptor());
/// Declare and initialize a parameter with a type.
/**
* \sa rclcpp::Node::declare_parameter
*/
template<typename ParameterT>
auto
declare_parameter(
const std::string & name,
const ParameterT & default_value,
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor =
rcl_interfaces::msg::ParameterDescriptor());
/// Declare and initialize several parameters with the same namespace and type.
/**
* \sa rclcpp::Node::declare_parameters
*/
template<typename ParameterT>
std::vector<ParameterT>
declare_parameters(
const std::string & namespace_,
const std::map<std::string, ParameterT> & parameters);
/// Declare and initialize several parameters with the same namespace and type.
/**
* \sa rclcpp::Node::declare_parameters
*/
template<typename ParameterT>
std::vector<ParameterT>
declare_parameters(
const std::string & namespace_,
const std::map<
std::string,
std::pair<ParameterT, rcl_interfaces::msg::ParameterDescriptor>
> & parameters);
/// Undeclare a previously declared parameter.
/**
* \sa rclcpp::Node::undeclare_parameter
*/
RCLCPP_LIFECYCLE_PUBLIC
void
undeclare_parameter(const std::string & name);
/// Return true if a given parameter is declared.
/**
* \sa rclcpp::Node::has_parameter
*/
RCLCPP_LIFECYCLE_PUBLIC
bool
has_parameter(const std::string & name) const;
/// Set a single parameter.
/**
* \sa rclcpp::Node::set_parameter
*/
RCLCPP_LIFECYCLE_PUBLIC
rcl_interfaces::msg::SetParametersResult
set_parameter(const rclcpp::Parameter & parameter);
/// Set one or more parameters, one at a time.
/**
* \sa rclcpp::Node::set_parameters
*/
RCLCPP_LIFECYCLE_PUBLIC
std::vector<rcl_interfaces::msg::SetParametersResult>
set_parameters(const std::vector<rclcpp::Parameter> & parameters);
/// Set one or more parameters, all at once.
/**
* \sa rclcpp::Node::set_parameters_atomically
*/
RCLCPP_LIFECYCLE_PUBLIC
rcl_interfaces::msg::SetParametersResult
set_parameters_atomically(const std::vector<rclcpp::Parameter> & parameters);
/// Set one parameter, unless that parameter has already been set.
/**
* \sa rclcpp::Node::set_parameter_if_not_set
*/
template<typename ParameterT>
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
[[deprecated("use declare_parameter() instead")]]
void
set_parameter_if_not_set(
const std::string & name,
@@ -349,54 +434,46 @@ public:
/// Set a map of parameters with the same prefix.
/**
* For each key in the map, a parameter with a name of "name.key" will be set
* to the value in the map.
*
* \param[in] name The prefix of the parameters to set.
* \param[in] values The parameters to set in the given prefix.
* \sa rclcpp::Node::set_parameters_if_not_set
*/
template<typename MapValueT>
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
[[deprecated("use declare_parameters() instead")]]
void
set_parameters_if_not_set(
const std::string & name,
const std::map<std::string, MapValueT> & values);
RCLCPP_LIFECYCLE_PUBLIC
std::vector<rclcpp::Parameter>
get_parameters(const std::vector<std::string> & names) const;
/// Return the parameter by the given name.
/**
* \sa rclcpp::Node::get_parameter
*/
RCLCPP_LIFECYCLE_PUBLIC
rclcpp::Parameter
get_parameter(const std::string & name) const;
/// Get the value of a parameter by the given name, and return true if it was set.
/**
* \sa rclcpp::Node::get_parameter
*/
RCLCPP_LIFECYCLE_PUBLIC
bool
get_parameter(
const std::string & name,
rclcpp::Parameter & parameter) const;
/// Get the value of a parameter by the given name, and return true if it was set.
/**
* \sa rclcpp::Node::get_parameter
*/
template<typename ParameterT>
bool
get_parameter(const std::string & name, ParameterT & parameter) const;
/// Assign the value of the map parameter if set into the values argument.
/// Get the parameter value, or the "alternative_value" if not set, and assign it to "parameter".
/**
* Parameter names that are part of a map are of the form "name.member".
* This API gets all parameters that begin with "name", storing them into the
* map with the name of the parameter and their value.
* If there are no members in the named map, then the "values" argument is not changed.
*
* \param[in] name The prefix of the parameters to get.
* \param[out] values The map of output values, with one std::string,MapValueT
* per parameter.
* \returns true if values was changed, false otherwise
* \sa rclcpp::Node::get_parameter_or
*/
template<typename MapValueT>
bool
get_parameters(
const std::string & name,
std::map<std::string, MapValueT> & values) const;
template<typename ParameterT>
bool
get_parameter_or(
@@ -404,42 +481,88 @@ public:
ParameterT & value,
const ParameterT & alternative_value) const;
/// Return the parameters by the given parameter names.
/**
* \sa rclcpp::Node::get_parameters
*/
RCLCPP_LIFECYCLE_PUBLIC
std::vector<rclcpp::Parameter>
get_parameters(const std::vector<std::string> & names) const;
/// Get the parameter values for all parameters that have a given prefix.
/**
* \sa rclcpp::Node::get_parameters
*/
template<typename MapValueT>
bool
get_parameters(
const std::string & prefix,
std::map<std::string, MapValueT> & values) const;
/// Get the parameter value; if not set, set the "alternative value" and store it in the node.
/**
* If the parameter is set, then the "value" argument is assigned the value
* in the parameter.
* If the parameter is not set, then the "value" argument is assigned the "alternative_value",
* and the parameter is set to the "alternative_value" on the node.
*
* \param[in] name The name of the parameter to get.
* \param[out] value The output where the value of the parameter should be assigned.
* \param[in] alternative_value Value to be stored in output and parameter if the parameter was not set.
* \sa rclcpp::Node::get_parameter_or_set
*/
template<typename ParameterT>
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
[[deprecated("use declare_parameter() and it's return value instead")]]
void
get_parameter_or_set(
const std::string & name,
ParameterT & value,
const ParameterT & alternative_value);
/// Return the parameter descriptor for the given parameter name.
/**
* \sa rclcpp::Node::describe_parameter
*/
RCLCPP_LIFECYCLE_PUBLIC
rcl_interfaces::msg::ParameterDescriptor
describe_parameter(const std::string & name) const;
/// Return a vector of parameter descriptors, one for each of the given names.
/**
* \sa rclcpp::Node::describe_parameters
*/
RCLCPP_LIFECYCLE_PUBLIC
std::vector<rcl_interfaces::msg::ParameterDescriptor>
describe_parameters(const std::vector<std::string> & names) const;
/// Return a vector of parameter types, one for each of the given names.
/**
* \sa rclcpp::Node::get_parameter_types
*/
RCLCPP_LIFECYCLE_PUBLIC
std::vector<uint8_t>
get_parameter_types(const std::vector<std::string> & names) const;
/// Return a list of parameters with any of the given prefixes, up to the given depth.
/**
* \sa rclcpp::Node::list_parameters
*/
RCLCPP_LIFECYCLE_PUBLIC
rcl_interfaces::msg::ListParametersResult
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const;
using OnParametersSetCallbackType =
rclcpp::node_interfaces::NodeParametersInterface::OnParametersSetCallbackType;
/// Register a callback to be called anytime a parameter is about to be changed.
/**
* \sa rclcpp::Node::set_on_parameters_set_callback
*/
RCLCPP_LIFECYCLE_PUBLIC
rclcpp_lifecycle::LifecycleNode::OnParametersSetCallbackType
set_on_parameters_set_callback(
rclcpp_lifecycle::LifecycleNode::OnParametersSetCallbackType callback);
/// Register the callback for parameter changes
/**
* \param[in] callback User defined function which is expected to atomically set parameters.
* \note Repeated invocations of this function will overwrite previous callbacks
* \sa rclcpp::Node::register_param_change_callback
*/
template<typename CallbackT>
// cppcheck-suppress syntaxError // bug in cppcheck 1.82 for [[deprecated]] on templated function
[[deprecated("use set_on_parameters_set_callback() instead")]]
void
register_param_change_callback(CallbackT && callback);

View File

@@ -223,6 +223,62 @@ LifecycleNode::create_service(
service_name, std::forward<CallbackT>(callback), qos_profile, group);
}
template<typename ParameterT>
auto
LifecycleNode::declare_parameter(
const std::string & name,
const ParameterT & default_value,
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor)
{
return this->declare_parameter(
name,
rclcpp::ParameterValue(default_value),
parameter_descriptor
).get<ParameterT>();
}
template<typename ParameterT>
std::vector<ParameterT>
LifecycleNode::declare_parameters(
const std::string & namespace_,
const std::map<std::string, ParameterT> & parameters)
{
std::vector<ParameterT> result;
std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
std::transform(
parameters.begin(), parameters.end(), std::back_inserter(result),
[this, &normalized_namespace](auto element) {
return this->declare_parameter(normalized_namespace + element.first, element.second);
}
);
return result;
}
template<typename ParameterT>
std::vector<ParameterT>
LifecycleNode::declare_parameters(
const std::string & namespace_,
const std::map<
std::string,
std::pair<ParameterT, rcl_interfaces::msg::ParameterDescriptor>
> & parameters)
{
std::vector<ParameterT> result;
std::string normalized_namespace = namespace_.empty() ? "" : (namespace_ + ".");
std::transform(
parameters.begin(), parameters.end(), std::back_inserter(result),
[this, &normalized_namespace](auto element) {
return static_cast<ParameterT>(
this->declare_parameter(
normalized_namespace + element.first,
element.second.first,
element.second.second)
);
}
);
return result;
}
template<typename ParameterT>
bool
LifecycleNode::get_parameter(const std::string & name, ParameterT & parameter) const
@@ -283,11 +339,11 @@ LifecycleNode::set_parameters_if_not_set(
template<typename MapValueT>
bool
LifecycleNode::get_parameters(
const std::string & name,
const std::string & prefix,
std::map<std::string, MapValueT> & values) const
{
std::map<std::string, rclcpp::Parameter> params;
bool result = node_parameters_->get_parameters_by_prefix(name, params);
bool result = node_parameters_->get_parameters_by_prefix(prefix, params);
if (result) {
for (const auto & param : params) {
values[param.first] = param.second.get_value<MapValueT>();

View File

@@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>rclcpp_lifecycle</name>
<version>0.7.2</version>
<version>0.7.7</version>
<description>Package containing a prototype for lifecycle implementation</description>
<maintainer email="karsten@osrfoundation.org">Karsten Knese</maintainer>
<license>Apache License 2.0</license>

View File

@@ -91,13 +91,13 @@ LifecycleNode::LifecycleNode(
node_topics_,
node_services_,
node_clock_,
options.initial_parameters(),
options.parameter_overrides(),
options.start_parameter_services(),
options.start_parameter_event_publisher(),
options.parameter_event_qos(),
options.parameter_event_publisher_options(),
options.allow_undeclared_parameters(),
options.automatically_declare_initial_parameters()
options.automatically_declare_parameters_from_overrides()
)),
node_time_source_(new rclcpp::node_interfaces::NodeTimeSource(
node_base_,
@@ -154,6 +154,33 @@ LifecycleNode::create_callback_group(
return node_base_->create_callback_group(group_type);
}
const rclcpp::ParameterValue &
LifecycleNode::declare_parameter(
const std::string & name,
const rclcpp::ParameterValue & default_value,
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor)
{
return this->node_parameters_->declare_parameter(name, default_value, parameter_descriptor);
}
void
LifecycleNode::undeclare_parameter(const std::string & name)
{
this->node_parameters_->undeclare_parameter(name);
}
bool
LifecycleNode::has_parameter(const std::string & name) const
{
return this->node_parameters_->has_parameter(name);
}
rcl_interfaces::msg::SetParametersResult
LifecycleNode::set_parameter(const rclcpp::Parameter & parameter)
{
return this->set_parameters_atomically({parameter});
}
bool
LifecycleNode::group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group)
{
@@ -187,13 +214,27 @@ LifecycleNode::get_parameter(const std::string & name) const
return node_parameters_->get_parameter(name);
}
bool LifecycleNode::get_parameter(
bool
LifecycleNode::get_parameter(
const std::string & name,
rclcpp::Parameter & parameter) const
{
return node_parameters_->get_parameter(name, parameter);
}
rcl_interfaces::msg::ParameterDescriptor
LifecycleNode::describe_parameter(const std::string & name) const
{
auto result = node_parameters_->describe_parameters({name});
if (0 == result.size()) {
throw rclcpp::exceptions::ParameterNotDeclaredException(name);
}
if (result.size() > 1) {
throw std::runtime_error("number of described parameters unexpectedly more than one");
}
return result.front();
}
std::vector<rcl_interfaces::msg::ParameterDescriptor>
LifecycleNode::describe_parameters(
const std::vector<std::string> & names) const
@@ -215,6 +256,12 @@ LifecycleNode::list_parameters(
return node_parameters_->list_parameters(prefixes, depth);
}
rclcpp::Node::OnParametersSetCallbackType
LifecycleNode::set_on_parameters_set_callback(rclcpp::Node::OnParametersSetCallbackType callback)
{
return node_parameters_->set_on_parameters_set_callback(callback);
}
std::vector<std::string>
LifecycleNode::get_node_names() const
{