Compare commits
23 Commits
crystal
...
check_para
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36ca813813 | ||
|
|
8f0705b08b | ||
|
|
2e32bc300c | ||
|
|
7e5e75a748 | ||
|
|
c94a1bf286 | ||
|
|
17b3b971b3 | ||
|
|
c026f89650 | ||
|
|
1eecfe73cc | ||
|
|
2e20bcb844 | ||
|
|
be9f07a414 | ||
|
|
3f344549b9 | ||
|
|
58fd8edee1 | ||
|
|
b0ac4453a3 | ||
|
|
3845f03d8a | ||
|
|
6651abcbe9 | ||
|
|
e86de20b7a | ||
|
|
bf03325e0a | ||
|
|
c0a6b474d7 | ||
|
|
99dd0313ab | ||
|
|
1e91face39 | ||
|
|
5c92811739 | ||
|
|
22abd62e31 | ||
|
|
eb2081bb25 |
@@ -401,6 +401,17 @@ if(BUILD_TESTING)
|
||||
"rcl")
|
||||
target_link_libraries(test_multi_threaded_executor ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_local_parameters test/test_local_parameters.cpp)
|
||||
if(TARGET test_local_parameters)
|
||||
target_include_directories(test_local_parameters PUBLIC
|
||||
${rcl_interfaces_INCLUDE_DIRS}
|
||||
${rmw_INCLUDE_DIRS}
|
||||
${rosidl_generator_cpp_INCLUDE_DIRS}
|
||||
${rosidl_typesupport_cpp_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_libraries(test_local_parameters ${PROJECT_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ament_package(
|
||||
|
||||
@@ -49,14 +49,14 @@ template<typename FunctionT>
|
||||
struct function_traits
|
||||
{
|
||||
using arguments = typename tuple_tail<
|
||||
typename function_traits<decltype( & FunctionT::operator())>::arguments>::type;
|
||||
typename function_traits<decltype( &FunctionT::operator())>::arguments>::type;
|
||||
|
||||
static constexpr std::size_t arity = std::tuple_size<arguments>::value;
|
||||
|
||||
template<std::size_t N>
|
||||
using argument_type = typename std::tuple_element<N, arguments>::type;
|
||||
|
||||
using return_type = typename function_traits<decltype( & FunctionT::operator())>::return_type;
|
||||
using return_type = typename function_traits<decltype( &FunctionT::operator())>::return_type;
|
||||
};
|
||||
|
||||
// Free functions
|
||||
@@ -81,7 +81,7 @@ struct function_traits<ReturnTypeT (*)(Args ...)>: function_traits<ReturnTypeT(A
|
||||
// std::bind for object methods
|
||||
template<typename ClassT, typename ReturnTypeT, typename ... Args, typename ... FArgs>
|
||||
#if defined _LIBCPP_VERSION // libc++ (Clang)
|
||||
struct function_traits<std::__1::__bind<ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
|
||||
struct function_traits<std::__bind<ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
|
||||
#elif defined _GLIBCXX_RELEASE // glibc++ (GNU C++ >= 7.1)
|
||||
struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(FArgs ...))(Args ...)>>
|
||||
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
|
||||
@@ -99,7 +99,7 @@ struct function_traits<
|
||||
// std::bind for free functions
|
||||
template<typename ReturnTypeT, typename ... Args, typename ... FArgs>
|
||||
#if defined _LIBCPP_VERSION // libc++ (Clang)
|
||||
struct function_traits<std::__1::__bind<ReturnTypeT( &)(Args ...), FArgs ...>>
|
||||
struct function_traits<std::__bind<ReturnTypeT( &)(Args ...), FArgs ...>>
|
||||
#elif defined __GLIBCXX__ // glibc++ (GNU C++)
|
||||
struct function_traits<std::_Bind<ReturnTypeT(*(FArgs ...))(Args ...)>>
|
||||
#elif defined _MSC_VER // MS Visual Studio
|
||||
|
||||
@@ -95,6 +95,7 @@ public:
|
||||
* pipeline to pass messages between nodes in the same process using shared memory.
|
||||
* \param[in] start_parameter_services True to setup ROS interfaces for accessing parameters
|
||||
* in the node.
|
||||
* \param[in] allow_undeclared_parameters True to allow any parameter name to be set on the node.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
Node(
|
||||
@@ -105,7 +106,8 @@ public:
|
||||
const std::vector<Parameter> & initial_parameters,
|
||||
bool use_global_arguments = true,
|
||||
bool use_intra_process_comms = false,
|
||||
bool start_parameter_services = true);
|
||||
bool start_parameter_services = true,
|
||||
bool allow_undeclared_parameters = false);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~Node();
|
||||
@@ -265,6 +267,36 @@ 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.
|
||||
/**
|
||||
* This method is used to declare that a parameter exists on this node.
|
||||
* If a run-time user has provided an an initial value then it will be set in this method,
|
||||
* otherwise the default_value will be set.
|
||||
* \param[in] name the name of the parameter
|
||||
* \param[in] default_value An initial value to be used if a run-time user did not override it.
|
||||
* \param[in] read_only if True then this parameter may not be changed after initialization.
|
||||
* \throws std::runtime_error if parameter has already been declared.
|
||||
* \throws std::runtime_error if a parameter name is invalid.
|
||||
* \throws rclcpp::exceptions::InvalidParameterValueException if initial value fails to be set.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
|
||||
bool read_only = false);
|
||||
|
||||
/// Declare and initialize a parameter with a type.
|
||||
/**
|
||||
* See the non-templated declare_parameter() on this class for details.
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
void
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const ParameterT & default_value,
|
||||
bool read_only = false);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
set_parameters(const std::vector<rclcpp::Parameter> & parameters);
|
||||
@@ -279,6 +311,20 @@ public:
|
||||
const std::string & name,
|
||||
const ParameterT & value);
|
||||
|
||||
/// 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.
|
||||
*/
|
||||
template<typename MapValueT>
|
||||
void
|
||||
set_parameters_if_not_set(
|
||||
const std::string & name,
|
||||
const std::map<std::string, MapValueT> & values);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::Parameter>
|
||||
get_parameters(const std::vector<std::string> & names) const;
|
||||
@@ -305,6 +351,24 @@ public:
|
||||
bool
|
||||
get_parameter(const std::string & name, ParameterT & parameter) const;
|
||||
|
||||
/// Assign the value of the map parameter if set into the values argument.
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
template<typename MapValueT>
|
||||
bool
|
||||
get_parameters(
|
||||
const std::string & name,
|
||||
std::map<std::string, MapValueT> & values) const;
|
||||
|
||||
/// Get the parameter value, or the "alternative value" if not set, and assign it to "value".
|
||||
/**
|
||||
* If the parameter was not set, then the "value" argument is assigned
|
||||
|
||||
@@ -210,6 +210,16 @@ Node::register_param_change_callback(CallbackT && callback)
|
||||
this->node_parameters_->register_param_change_callback(std::forward<CallbackT>(callback));
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
void
|
||||
Node::declare_parameter(
|
||||
const std::string & name,
|
||||
const ParameterT & default_value,
|
||||
bool read_only)
|
||||
{
|
||||
this->declare_parameter(name, rclcpp::ParameterValue(default_value), read_only);
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
void
|
||||
Node::set_parameter_if_not_set(
|
||||
@@ -224,6 +234,28 @@ Node::set_parameter_if_not_set(
|
||||
}
|
||||
}
|
||||
|
||||
// this is a partially-specialized version of set_parameter_if_not_set above,
|
||||
// where our concrete type for ParameterT is std::map, but the to-be-determined
|
||||
// type is the value in the map.
|
||||
template<typename MapValueT>
|
||||
void
|
||||
Node::set_parameters_if_not_set(
|
||||
const std::string & name,
|
||||
const std::map<std::string, MapValueT> & values)
|
||||
{
|
||||
std::vector<rclcpp::Parameter> params;
|
||||
|
||||
for (const auto & val : values) {
|
||||
std::string param_name = name + "." + val.first;
|
||||
rclcpp::Parameter parameter;
|
||||
if (!this->get_parameter(param_name, parameter)) {
|
||||
params.push_back(rclcpp::Parameter(param_name, val.second));
|
||||
}
|
||||
}
|
||||
|
||||
this->set_parameters(params);
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
bool
|
||||
Node::get_parameter(const std::string & name, ParameterT & value) const
|
||||
@@ -237,6 +269,26 @@ Node::get_parameter(const std::string & name, ParameterT & value) const
|
||||
return result;
|
||||
}
|
||||
|
||||
// this is a partially-specialized version of get_parameter above,
|
||||
// where our concrete type for ParameterT is std::map, but the to-be-determined
|
||||
// type is the value in the map.
|
||||
template<typename MapValueT>
|
||||
bool
|
||||
Node::get_parameters(
|
||||
const std::string & name,
|
||||
std::map<std::string, MapValueT> & values) const
|
||||
{
|
||||
std::map<std::string, rclcpp::Parameter> params;
|
||||
bool result = node_parameters_->get_parameters_by_prefix(name, params);
|
||||
if (result) {
|
||||
for (const auto & param : params) {
|
||||
values[param.first] = param.second.get_value<MapValueT>();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
bool
|
||||
Node::get_parameter_or(
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
// Copyright 2018 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_PARAMETERS_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_NODE_PARAMETERS_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
|
||||
|
||||
/// This header provides the get_node_parameters_interface() template function.
|
||||
/**
|
||||
* This function is useful for getting the NodeParametersInterface pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get the NodeParametersInterface pointer so long as the class
|
||||
* has a method called ``get_node_parameters_interface()`` which returns
|
||||
* either a pointer (const or not) to a NodeParametersInterface or a
|
||||
* std::shared_ptr to a NodeParametersInterface.
|
||||
*/
|
||||
|
||||
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_parameters_interface() which returns various types,
|
||||
// e.g. const pointer or a shared pointer.
|
||||
template<typename NodeType, typename ReturnType>
|
||||
struct has_get_node_parameters_interface
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static constexpr
|
||||
auto
|
||||
check(T *)->typename std::is_same<
|
||||
decltype(std::declval<T>().get_node_parameters_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 NodeParametersInterface already (just normal function overload).
|
||||
inline
|
||||
const rclcpp::node_interfaces::NodeParametersInterface *
|
||||
get_node_parameters_interface_from_pointer(
|
||||
const rclcpp::node_interfaces::NodeParametersInterface * pointer)
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_parameters_interface() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_parameters_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeParametersInterface>
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
const rclcpp::node_interfaces::NodeParametersInterface *
|
||||
get_node_parameters_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_parameters_interface().get();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_parameters_interface() which returns a pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_parameters_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
rclcpp::node_interfaces::NodeParametersInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
const rclcpp::node_interfaces::NodeParametersInterface *
|
||||
get_node_parameters_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_parameters_interface();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_parameters_interface() which returns a const pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_parameters_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
const rclcpp::node_interfaces::NodeParametersInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
const rclcpp::node_interfaces::NodeParametersInterface *
|
||||
get_node_parameters_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_parameters_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
|
||||
>
|
||||
const rclcpp::node_interfaces::NodeParametersInterface *
|
||||
get_node_parameters_interface_from_pointer(NodeType node_shared_pointer)
|
||||
{
|
||||
return get_node_parameters_interface_from_pointer(node_shared_pointer->get());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the NodeParametersInterface as a const pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
const rclcpp::node_interfaces::NodeParametersInterface *
|
||||
get_node_parameters_interface(NodeType && node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
return detail::get_node_parameters_interface_from_pointer(std::forward<NodeType>(node_pointer));
|
||||
}
|
||||
|
||||
/// Get the NodeParametersInterface as a const pointer from a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<!std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
const rclcpp::node_interfaces::NodeParametersInterface *
|
||||
get_node_parameters_interface(NodeType && node_reference)
|
||||
{
|
||||
// Forward const-references to detail implmentation as a pointer.
|
||||
return detail::get_node_parameters_interface_from_pointer(&node_reference);
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_PARAMETERS_INTERFACE_HPP_
|
||||
@@ -61,6 +61,7 @@ private:
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_;
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_;
|
||||
rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_;
|
||||
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters_;
|
||||
rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_;
|
||||
|
||||
rclcpp::Clock::SharedPtr ros_clock_;
|
||||
|
||||
@@ -40,6 +40,19 @@ namespace rclcpp
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
// Internal struct for holding useful info about parameters
|
||||
struct ParameterInfo
|
||||
{
|
||||
/// True if a user called declare_parameter()
|
||||
bool is_declared = false;
|
||||
|
||||
/// Current value of the parameter.
|
||||
rclcpp::ParameterValue value;
|
||||
|
||||
/// A description of the parameter
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
};
|
||||
|
||||
/// Implementation of the NodeParameters part of the Node API.
|
||||
class NodeParameters : public NodeParametersInterface
|
||||
{
|
||||
@@ -54,60 +67,65 @@ public:
|
||||
const node_interfaces::NodeClockInterface::SharedPtr node_clock,
|
||||
const std::vector<Parameter> & initial_parameters,
|
||||
bool use_intra_process,
|
||||
bool start_parameter_services);
|
||||
bool start_parameter_services,
|
||||
bool allow_undeclared_parameters);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
~NodeParameters();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
bool read_only) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
set_parameters(
|
||||
const std::vector<rclcpp::Parameter> & parameters);
|
||||
const std::vector<rclcpp::Parameter> & parameters) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
set_parameters_atomically(
|
||||
const std::vector<rclcpp::Parameter> & parameters);
|
||||
const std::vector<rclcpp::Parameter> & parameters) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::vector<rclcpp::Parameter>
|
||||
get_parameters(const std::vector<std::string> & names) const;
|
||||
get_parameters(const std::vector<std::string> & names) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::Parameter
|
||||
get_parameter(const std::string & name) const;
|
||||
get_parameter(const std::string & name) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
bool
|
||||
get_parameter(
|
||||
const std::string & name,
|
||||
rclcpp::Parameter & parameter) const;
|
||||
rclcpp::Parameter & parameter) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
get_parameters_by_prefix(
|
||||
const std::string & prefix,
|
||||
std::map<std::string, rclcpp::Parameter> & parameters) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::vector<rcl_interfaces::msg::ParameterDescriptor>
|
||||
describe_parameters(const std::vector<std::string> & names) const;
|
||||
describe_parameters(const std::vector<std::string> & names) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::vector<uint8_t>
|
||||
get_parameter_types(const std::vector<std::string> & names) const;
|
||||
get_parameter_types(const std::vector<std::string> & names) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const;
|
||||
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
register_param_change_callback(ParametersCallbackFunction callback);
|
||||
register_param_change_callback(ParametersCallbackFunction callback) override;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeParameters)
|
||||
@@ -116,7 +134,11 @@ private:
|
||||
|
||||
ParametersCallbackFunction parameters_callback_ = nullptr;
|
||||
|
||||
std::map<std::string, rclcpp::Parameter> parameters_;
|
||||
std::map<std::string, ParameterInfo> parameters_;
|
||||
|
||||
std::map<std::string, rclcpp::ParameterValue> initial_parameter_values_;
|
||||
|
||||
bool allow_undeclared_ = false;
|
||||
|
||||
Publisher<rcl_interfaces::msg::ParameterEvent>::SharedPtr events_publisher_;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#ifndef RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_INTERFACE_HPP_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -37,6 +38,25 @@ class NodeParametersInterface
|
||||
public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeParametersInterface)
|
||||
|
||||
/// Declare and initialize a parameter.
|
||||
/* This method is used to declare that a parameter exists on this node.
|
||||
* If a run-time user has provided an an initial value then it will be set in this method,
|
||||
* otherwise the default_value will be set.
|
||||
* \param[in] name the name of the parameter
|
||||
* \param[in] default_value An initial value to be used if a run-time user did not override it.
|
||||
* \param[in] read_only if True then this parameter may not be changed after initialization.
|
||||
* \throws std::runtime_error if parameter has already been declared.
|
||||
* \throws std::runtime_error if a parameter name is invalid.
|
||||
* \throws rclcpp::exceptions::InvalidParameterValueException if initial value fails to be set.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value = rclcpp::ParameterValue(),
|
||||
bool read_only = false) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
~NodeParametersInterface() = default;
|
||||
@@ -89,6 +109,20 @@ public:
|
||||
const std::string & name,
|
||||
rclcpp::Parameter & parameter) const = 0;
|
||||
|
||||
/// Get all parameters that have the specified prefix into the parameters map.
|
||||
/*
|
||||
* \param[in] prefix the name of the prefix to look for.
|
||||
* \param[out] parameters a map of parameters that matched the prefix.
|
||||
* \return true if any parameters with the prefix exists on the node, or
|
||||
* \return false otherwise.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
bool
|
||||
get_parameters_by_prefix(
|
||||
const std::string & prefix,
|
||||
std::map<std::string, rclcpp::Parameter> & parameters) const = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::vector<rcl_interfaces::msg::ParameterDescriptor>
|
||||
|
||||
@@ -28,6 +28,25 @@
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
class Parameter;
|
||||
|
||||
namespace node_interfaces
|
||||
{
|
||||
struct ParameterInfo;
|
||||
} // namespace node_interfaces
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This helper function is required because you cannot do specialization on a
|
||||
// class method, so instead we specialize this template function and call it
|
||||
// from the unspecialized, but dependent, class method.
|
||||
template<typename T>
|
||||
auto
|
||||
get_value_helper(const rclcpp::Parameter * parameter);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Structure to store an arbitrary parameter with templated get/set methods.
|
||||
class Parameter
|
||||
{
|
||||
@@ -44,6 +63,9 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit Parameter(const rclcpp::node_interfaces::ParameterInfo & parameter_info);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
ParameterType
|
||||
get_type() const;
|
||||
@@ -60,6 +82,11 @@ public:
|
||||
rcl_interfaces::msg::ParameterValue
|
||||
get_value_message() const;
|
||||
|
||||
/// Get the internal storage for the parameter value.
|
||||
RCLCPP_PUBLIC
|
||||
const rclcpp::ParameterValue &
|
||||
get_parameter_value() const;
|
||||
|
||||
/// Get value of parameter using rclcpp::ParameterType as template argument.
|
||||
template<ParameterType ParamT>
|
||||
decltype(auto)
|
||||
@@ -71,10 +98,7 @@ public:
|
||||
/// Get value of parameter using c++ types as template argument.
|
||||
template<typename T>
|
||||
decltype(auto)
|
||||
get_value() const
|
||||
{
|
||||
return value_.get<T>();
|
||||
}
|
||||
get_value() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
@@ -142,6 +166,49 @@ RCLCPP_PUBLIC
|
||||
std::ostream &
|
||||
operator<<(std::ostream & os, const std::vector<Parameter> & parameters);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
auto
|
||||
get_value_helper(const rclcpp::Parameter * parameter)
|
||||
{
|
||||
return parameter->get_parameter_value().get<T>();
|
||||
}
|
||||
|
||||
// Specialization allowing Parameter::get() to return a const ref to the parameter value object.
|
||||
template<>
|
||||
inline
|
||||
auto
|
||||
get_value_helper<rclcpp::ParameterValue>(const rclcpp::Parameter * parameter)
|
||||
{
|
||||
return parameter->get_parameter_value();
|
||||
}
|
||||
|
||||
// Specialization allowing Parameter::get() to return a const ref to the parameter itself.
|
||||
template<>
|
||||
inline
|
||||
auto
|
||||
get_value_helper<rclcpp::Parameter>(const rclcpp::Parameter * parameter)
|
||||
{
|
||||
// Use this labmda to ensure it's a const reference being returned (and not a copy).
|
||||
auto type_enforcing_lambda =
|
||||
[¶meter]() -> const rclcpp::Parameter & {
|
||||
return *parameter;
|
||||
};
|
||||
return type_enforcing_lambda();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
decltype(auto)
|
||||
Parameter::get_value() const
|
||||
{
|
||||
// use the helper to specialize for the ParameterValue and Parameter cases.
|
||||
return detail::get_value_helper<T>(this);
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
namespace std
|
||||
|
||||
@@ -185,6 +185,29 @@ public:
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit SyncParametersClient(
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
|
||||
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::Parameter>
|
||||
get_parameters(const std::vector<std::string> & parameter_names);
|
||||
@@ -268,7 +291,7 @@ public:
|
||||
|
||||
private:
|
||||
rclcpp::executor::Executor::SharedPtr executor_;
|
||||
rclcpp::Node::SharedPtr node_;
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface_;
|
||||
AsyncParametersClient::SharedPtr async_parameters_client_;
|
||||
};
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
enum ParameterType
|
||||
|
||||
enum ParameterType : uint8_t
|
||||
{
|
||||
PARAMETER_NOT_SET = rcl_interfaces::msg::ParameterType::PARAMETER_NOT_SET,
|
||||
PARAMETER_BOOL = rcl_interfaces::msg::ParameterType::PARAMETER_BOOL,
|
||||
@@ -45,11 +46,11 @@ enum ParameterType
|
||||
/// Return the name of a parameter type
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
to_string(const ParameterType type);
|
||||
to_string(ParameterType type);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::ostream &
|
||||
operator<<(std::ostream & os, const ParameterType type);
|
||||
operator<<(std::ostream & os, ParameterType type);
|
||||
|
||||
/// Indicate the parameter type does not match the expected type.
|
||||
class ParameterTypeException : public std::runtime_error
|
||||
|
||||
115
rclcpp/include/rclcpp/unused_parameters_checker.hpp
Normal file
115
rclcpp/include/rclcpp/unused_parameters_checker.hpp
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright 2018 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__UNUSED_PARAMETERS_CHECKER_HPP_
|
||||
#define RCLCPP__UNUSED_PARAMETERS_CHECKER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/node_interfaces/get_node_parameters_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_parameters_interface.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Check a Node-like class for unused parameters.
|
||||
/**
|
||||
* This class can be used to detect misconfigurations and typos by ensuring all
|
||||
* initial parameter values that were passed to the Node-like object were used.
|
||||
* So this class's methods are used after or during Node construction and after
|
||||
* all parameters have been declared.
|
||||
*
|
||||
* This class must not outlive the Node that it's being used with.
|
||||
*/
|
||||
class UnusedParametersChecker
|
||||
{
|
||||
public:
|
||||
template<typename NodeType>
|
||||
explicit UnusedParametersChecker(NodeType && node_like)
|
||||
: node_parameters_interface_(
|
||||
rclcpp::node_interfaces::get_node_parameters_interface(std::forward<NodeType>(node_like)))
|
||||
{}
|
||||
|
||||
/// Warn if any initial parameter values have not been used.
|
||||
/**
|
||||
* This function will complain with a RCLCPP_WARN if any provided initial
|
||||
* parameter values have not been used.
|
||||
*
|
||||
* \throws std::bad_alloc when trying to create an error message
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
check_and_warn() const;
|
||||
|
||||
/// Throw an UnusedParameterExecption if any initial parameter values have not been used.
|
||||
/**
|
||||
* This function will throw an exception if any provided initial
|
||||
* parameter values have not been used.
|
||||
*
|
||||
* \throws std::bad_alloc when trying to create an error message
|
||||
* \throws rclcpp::UnusedParametersException when there are unused parameters
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
check_and_throw() const;
|
||||
|
||||
/// Return the number of unused initial parameter values.
|
||||
/**
|
||||
* Similar to get_unused_initial_parameter_values(), but it returns the
|
||||
* number of unused parameter values rather than a vector of the unused
|
||||
* parameters (which involves allocating storage for the copies).
|
||||
* This function is faster and avoids memory allocation while checking for a
|
||||
* problem, and if one is detected then get_unused_initial_parameter_values()
|
||||
* may be used to format a useful error message.
|
||||
*
|
||||
* \returns the number of unused initial parameter values
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_unused_initial_parameter_values() const;
|
||||
|
||||
/// Return the list of unused initial parameter values.
|
||||
/**
|
||||
* A common case where this returns a non-empty vector, is when someone makes
|
||||
* a typo when setting the parameters from outside the node.
|
||||
* For example, if they use `ip_addr` rather than the expected `ip_address`.
|
||||
*
|
||||
* \returns vector of parameters which where passed to the node but where
|
||||
* not declared before this function was called.
|
||||
* \throws std::bad_alloc
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::vector<rclcpp::Parameter>
|
||||
get_unused_initial_parameter_values() const;
|
||||
|
||||
private:
|
||||
const rclcpp::node_interfaces::NodeParametersInterface * node_parameters_interface_;
|
||||
};
|
||||
|
||||
/// Thrown when throw_if_unused_initialized_parameter_values() finds unused parameters.
|
||||
class UnusedParametersException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit UnusedParametersException(const std::vector<rclcpp::Parameter> & unused_parameters);
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__UNUSED_PARAMETERS_CHECKER_HPP_
|
||||
@@ -60,9 +60,8 @@ Executor::Executor(const ExecutorArgs & args)
|
||||
// Store the context for later use.
|
||||
context_ = args.context;
|
||||
|
||||
if (rcl_wait_set_init(
|
||||
&wait_set_, 0, 2, 0, 0, 0, allocator) != RCL_RET_OK)
|
||||
{
|
||||
ret = rcl_wait_set_init(&wait_set_, 0, 2, 0, 0, 0, context_->get_rcl_context().get(), allocator);
|
||||
if (RCL_RET_OK != ret) {
|
||||
RCUTILS_LOG_ERROR_NAMED(
|
||||
"rclcpp",
|
||||
"failed to create wait set: %s", rcl_get_error_string().str);
|
||||
|
||||
@@ -79,6 +79,7 @@ GraphListener::start_if_not_started()
|
||||
0, // number_of_timers
|
||||
0, // number_of_clients
|
||||
0, // number_of_services
|
||||
this->parent_context_->get_rcl_context().get(),
|
||||
rcl_get_default_allocator());
|
||||
if (RCL_RET_OK != ret) {
|
||||
throw_from_rcl_error(ret, "failed to initialize wait set");
|
||||
|
||||
@@ -60,7 +60,8 @@ Node::Node(
|
||||
const std::vector<rclcpp::Parameter> & initial_parameters,
|
||||
bool use_global_arguments,
|
||||
bool use_intra_process_comms,
|
||||
bool start_parameter_services)
|
||||
bool start_parameter_services,
|
||||
bool allow_undeclared_parameters)
|
||||
: node_base_(new rclcpp::node_interfaces::NodeBase(
|
||||
node_name, namespace_, context, arguments, use_global_arguments)),
|
||||
node_graph_(new rclcpp::node_interfaces::NodeGraph(node_base_.get())),
|
||||
@@ -82,7 +83,8 @@ Node::Node(
|
||||
node_clock_,
|
||||
initial_parameters,
|
||||
use_intra_process_comms,
|
||||
start_parameter_services
|
||||
start_parameter_services,
|
||||
allow_undeclared_parameters
|
||||
)),
|
||||
node_time_source_(new rclcpp::node_interfaces::NodeTimeSource(
|
||||
node_base_,
|
||||
@@ -132,6 +134,15 @@ Node::group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
return node_base_->callback_group_in_node(group);
|
||||
}
|
||||
|
||||
void
|
||||
Node::declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
bool read_only)
|
||||
{
|
||||
return this->node_parameters_->declare_parameter(name, default_value, read_only);
|
||||
}
|
||||
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
Node::set_parameters(
|
||||
const std::vector<rclcpp::Parameter> & parameters)
|
||||
|
||||
@@ -39,8 +39,9 @@ NodeParameters::NodeParameters(
|
||||
const rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock,
|
||||
const std::vector<rclcpp::Parameter> & initial_parameters,
|
||||
bool use_intra_process,
|
||||
bool start_parameter_services)
|
||||
: node_clock_(node_clock)
|
||||
bool start_parameter_services,
|
||||
bool allow_undeclared_parameters)
|
||||
: allow_undeclared_(allow_undeclared_parameters), node_clock_(node_clock)
|
||||
{
|
||||
using MessageT = rcl_interfaces::msg::ParameterEvent;
|
||||
using PublisherT = rclcpp::Publisher<MessageT>;
|
||||
@@ -114,8 +115,6 @@ NodeParameters::NodeParameters(
|
||||
combined_name_ = node_namespace + '/' + node_name;
|
||||
}
|
||||
|
||||
std::map<std::string, rclcpp::Parameter> parameters;
|
||||
|
||||
// TODO(sloretz) use rcl to parse yaml when circular dependency is solved
|
||||
// See https://github.com/ros2/rcl/issues/252
|
||||
for (const std::string & yaml_path : yaml_paths) {
|
||||
@@ -140,25 +139,19 @@ NodeParameters::NodeParameters(
|
||||
|
||||
// Combine parameter yaml files, overwriting values in older ones
|
||||
for (auto & param : iter->second) {
|
||||
parameters[param.get_name()] = param;
|
||||
initial_parameter_values_[param.get_name()] =
|
||||
rclcpp::ParameterValue(param.get_value_message());
|
||||
}
|
||||
}
|
||||
|
||||
// initial values passed to constructor overwrite yaml file sources
|
||||
for (auto & param : initial_parameters) {
|
||||
parameters[param.get_name()] = param;
|
||||
initial_parameter_values_[param.get_name()] =
|
||||
rclcpp::ParameterValue(param.get_value_message());
|
||||
}
|
||||
|
||||
std::vector<rclcpp::Parameter> combined_values;
|
||||
combined_values.reserve(parameters.size());
|
||||
for (auto & kv : parameters) {
|
||||
combined_values.emplace_back(kv.second);
|
||||
}
|
||||
|
||||
// TODO(sloretz) store initial values and use them when a parameter is created ros2/rclcpp#475
|
||||
// Set initial parameter values
|
||||
if (!combined_values.empty()) {
|
||||
rcl_interfaces::msg::SetParametersResult result = set_parameters_atomically(combined_values);
|
||||
if (!initial_parameters.empty() && allow_undeclared_) {
|
||||
rcl_interfaces::msg::SetParametersResult result = set_parameters_atomically(initial_parameters);
|
||||
if (!result.successful) {
|
||||
throw std::runtime_error("Failed to set initial parameters");
|
||||
}
|
||||
@@ -168,6 +161,59 @@ NodeParameters::NodeParameters(
|
||||
NodeParameters::~NodeParameters()
|
||||
{}
|
||||
|
||||
void
|
||||
NodeParameters::declare_parameter(
|
||||
const std::string & name,
|
||||
const rclcpp::ParameterValue & default_value,
|
||||
bool read_only)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
// TODO(sloretz) parameter name validation
|
||||
if (name.empty()) {
|
||||
throw std::runtime_error("parameter name must not be empty");
|
||||
}
|
||||
|
||||
// Error if this parameter has already been declared and is different
|
||||
auto param_iter = parameters_.find(name);
|
||||
if (param_iter != parameters_.end() && param_iter->second.is_declared) {
|
||||
if (
|
||||
param_iter->second.descriptor.type != default_value.get_type() ||
|
||||
param_iter->second.descriptor.read_only != read_only)
|
||||
{
|
||||
throw std::runtime_error("parameter '" + name + "' exists with conflicting description");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if run-time user passed an initial value, else use the default.
|
||||
rclcpp::ParameterValue initial_value = default_value;
|
||||
auto value_iter = initial_parameter_values_.find(name);
|
||||
if (value_iter != initial_parameter_values_.end()) {
|
||||
initial_value = value_iter->second;
|
||||
}
|
||||
|
||||
// Save a description of the parameter
|
||||
rcl_interfaces::msg::ParameterDescriptor desc;
|
||||
desc.name = name;
|
||||
desc.type = initial_value.get_type();
|
||||
desc.read_only = read_only;
|
||||
|
||||
rclcpp::node_interfaces::ParameterInfo pinfo;
|
||||
pinfo.is_declared = true;
|
||||
pinfo.value = initial_value;
|
||||
pinfo.descriptor = desc;
|
||||
|
||||
// Add declared parameters to storage, even when they're not set.
|
||||
parameters_[name] = pinfo;
|
||||
|
||||
// If it has an actual value then add it to 'new_parameters' event
|
||||
if (rclcpp::ParameterType::PARAMETER_NOT_SET != initial_value.get_type()) {
|
||||
auto parameter_event = std::make_shared<rcl_interfaces::msg::ParameterEvent>();
|
||||
parameter_event->new_parameters.push_back(
|
||||
rclcpp::Parameter(name, initial_value).to_parameter_msg());
|
||||
events_publisher_->publish(parameter_event);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||
NodeParameters::set_parameters(
|
||||
const std::vector<rclcpp::Parameter> & parameters)
|
||||
@@ -185,7 +231,7 @@ NodeParameters::set_parameters_atomically(
|
||||
const std::vector<rclcpp::Parameter> & parameters)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::map<std::string, rclcpp::Parameter> tmp_map;
|
||||
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> tmp_map;
|
||||
auto parameter_event = std::make_shared<rcl_interfaces::msg::ParameterEvent>();
|
||||
|
||||
parameter_event->node = combined_name_;
|
||||
@@ -202,33 +248,79 @@ NodeParameters::set_parameters_atomically(
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> to_delete;
|
||||
|
||||
for (auto p : parameters) {
|
||||
if (p.get_type() == rclcpp::ParameterType::PARAMETER_NOT_SET) {
|
||||
if (parameters_.find(p.get_name()) != parameters_.end()) {
|
||||
// case: parameter was set before, and input is "NOT_SET"
|
||||
// therefore we will erase the parameter from parameters_ later
|
||||
auto param_iter = parameters_.find(p.get_name());
|
||||
bool exists = parameters_.end() != param_iter;
|
||||
bool want_to_delete = p.get_type() == rclcpp::ParameterType::PARAMETER_NOT_SET;
|
||||
|
||||
if (exists) {
|
||||
if (param_iter->second.descriptor.read_only) {
|
||||
result.successful = false;
|
||||
result.reason = "read_only parameter: '" + p.get_name() + "'";
|
||||
return result;
|
||||
}
|
||||
if (want_to_delete) {
|
||||
parameter_event->deleted_parameters.push_back(p.to_parameter_msg());
|
||||
if (param_iter->second.is_declared) {
|
||||
// clear declared parameter value, but don't delete it
|
||||
rclcpp::node_interfaces::ParameterInfo cleared_param_info = param_iter->second;
|
||||
cleared_param_info.value = rclcpp::ParameterValue();
|
||||
tmp_map[p.get_name()] = cleared_param_info;
|
||||
} else {
|
||||
// Truly delete an undeclared parameter
|
||||
to_delete.push_back(p.get_name());
|
||||
}
|
||||
} else {
|
||||
if (param_iter->second.value.get_type() == rclcpp::ParameterType::PARAMETER_NOT_SET) {
|
||||
// case: setting a value on a declared parameter that currently is unset
|
||||
parameter_event->new_parameters.push_back(p.to_parameter_msg());
|
||||
} else {
|
||||
// case: changing a parameter value
|
||||
parameter_event->changed_parameters.push_back(p.to_parameter_msg());
|
||||
}
|
||||
rclcpp::node_interfaces::ParameterInfo changed_param_info = param_iter->second;
|
||||
// TODO(sloretz) Add accessor for ParameterValue on Parameter class
|
||||
changed_param_info.value = rclcpp::ParameterValue(p.get_value_message());
|
||||
tmp_map[p.get_name()] = changed_param_info;
|
||||
}
|
||||
} else {
|
||||
if (parameters_.find(p.get_name()) == parameters_.end()) {
|
||||
// case: parameter not set before, and input is something other than "NOT_SET"
|
||||
parameter_event->new_parameters.push_back(p.to_parameter_msg());
|
||||
// case: parameter does not exist already
|
||||
if (!allow_undeclared_) {
|
||||
result.successful = false;
|
||||
result.reason = "undeclared parameter: '" + p.get_name() + "'";
|
||||
return result;
|
||||
} else if (want_to_delete) {
|
||||
result.successful = false;
|
||||
result.reason = "deleting parameter: '" + p.get_name() + "' that does not exist";
|
||||
return result;
|
||||
} else {
|
||||
// case: parameter was set before, and input is something other than "NOT_SET"
|
||||
parameter_event->changed_parameters.push_back(p.to_parameter_msg());
|
||||
// Create new undeclared parameter
|
||||
parameter_event->new_parameters.push_back(p.to_parameter_msg());
|
||||
|
||||
rcl_interfaces::msg::ParameterDescriptor desc;
|
||||
desc.name = p.get_name();
|
||||
desc.type = p.get_type();
|
||||
desc.read_only = false;
|
||||
|
||||
rclcpp::node_interfaces::ParameterInfo new_param_info;
|
||||
new_param_info.is_declared = false;
|
||||
// TODO(sloretz) Add accessor for ParameterValue on Parameter class
|
||||
new_param_info.value = rclcpp::ParameterValue(p.get_value_message());
|
||||
new_param_info.descriptor = desc;
|
||||
|
||||
tmp_map[p.get_name()] = new_param_info;
|
||||
}
|
||||
tmp_map[p.get_name()] = p;
|
||||
}
|
||||
}
|
||||
// std::map::insert will not overwrite elements, so we'll keep the new
|
||||
// ones and add only those that already exist in the Node's internal map
|
||||
tmp_map.insert(parameters_.begin(), parameters_.end());
|
||||
|
||||
// remove explicitly deleted parameters
|
||||
for (auto p : parameters) {
|
||||
if (p.get_type() == rclcpp::ParameterType::PARAMETER_NOT_SET) {
|
||||
tmp_map.erase(p.get_name());
|
||||
}
|
||||
// remove truly deleted parameters
|
||||
for (const std::string & param_name : to_delete) {
|
||||
tmp_map.erase(param_name);
|
||||
}
|
||||
|
||||
std::swap(tmp_map, parameters_);
|
||||
@@ -246,11 +338,11 @@ NodeParameters::get_parameters(const std::vector<std::string> & names) const
|
||||
|
||||
for (auto & name : names) {
|
||||
if (std::any_of(parameters_.cbegin(), parameters_.cend(),
|
||||
[&name](const std::pair<std::string, rclcpp::Parameter> & kv) {
|
||||
[&name](const std::pair<std::string, rclcpp::node_interfaces::ParameterInfo> & kv) {
|
||||
return name == kv.first;
|
||||
}))
|
||||
{
|
||||
results.push_back(parameters_.at(name));
|
||||
results.emplace_back(name, parameters_.at(name).value);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
@@ -275,14 +367,39 @@ NodeParameters::get_parameter(
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
if (parameters_.count(name)) {
|
||||
parameter = parameters_.at(name);
|
||||
auto param_iter = parameters_.find(name);
|
||||
if (
|
||||
parameters_.end() != param_iter &&
|
||||
param_iter->second.value.get_type() != rclcpp::ParameterType::PARAMETER_NOT_SET)
|
||||
{
|
||||
parameter = {name, param_iter->second.value};
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
NodeParameters::get_parameters_by_prefix(
|
||||
const std::string & prefix,
|
||||
std::map<std::string, rclcpp::Parameter> & parameters) const
|
||||
{
|
||||
std::string prefix_with_dot = prefix + ".";
|
||||
bool ret = false;
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
for (const auto & param : parameters_) {
|
||||
if (param.first.find(prefix_with_dot) == 0 && param.first.length() > prefix_with_dot.length()) {
|
||||
// Found one!
|
||||
parameters[param.first.substr(prefix_with_dot.length())] = rclcpp::Parameter(param.second);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<rcl_interfaces::msg::ParameterDescriptor>
|
||||
NodeParameters::describe_parameters(const std::vector<std::string> & names) const
|
||||
{
|
||||
@@ -293,10 +410,7 @@ NodeParameters::describe_parameters(const std::vector<std::string> & names) cons
|
||||
return name == kv.first;
|
||||
}))
|
||||
{
|
||||
rcl_interfaces::msg::ParameterDescriptor parameter_descriptor;
|
||||
parameter_descriptor.name = kv.first;
|
||||
parameter_descriptor.type = kv.second.get_type();
|
||||
results.push_back(parameter_descriptor);
|
||||
results.push_back(kv.second.descriptor);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
@@ -312,7 +426,7 @@ NodeParameters::get_parameter_types(const std::vector<std::string> & names) cons
|
||||
return name == kv.first;
|
||||
}))
|
||||
{
|
||||
results.push_back(kv.second.get_type());
|
||||
results.push_back(kv.second.value.get_type());
|
||||
} else {
|
||||
results.push_back(rcl_interfaces::msg::ParameterType::PARAMETER_NOT_SET);
|
||||
}
|
||||
|
||||
@@ -12,12 +12,14 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "rclcpp/parameter.hpp"
|
||||
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/node_interfaces/node_parameters.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
|
||||
using rclcpp::ParameterType;
|
||||
@@ -33,6 +35,11 @@ Parameter::Parameter(const std::string & name, const rclcpp::ParameterValue & va
|
||||
{
|
||||
}
|
||||
|
||||
Parameter::Parameter(const rclcpp::node_interfaces::ParameterInfo & parameter_info)
|
||||
: Parameter(parameter_info.descriptor.name, parameter_info.value)
|
||||
{
|
||||
}
|
||||
|
||||
ParameterType
|
||||
Parameter::get_type() const
|
||||
{
|
||||
@@ -57,6 +64,12 @@ Parameter::get_value_message() const
|
||||
return value_.to_value_msg();
|
||||
}
|
||||
|
||||
const rclcpp::ParameterValue &
|
||||
Parameter::get_parameter_value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
bool
|
||||
Parameter::as_bool() const
|
||||
{
|
||||
|
||||
@@ -350,10 +350,60 @@ SyncParametersClient::SyncParametersClient(
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: executor_(executor), node_(node)
|
||||
: SyncParametersClient(
|
||||
executor,
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface(),
|
||||
remote_node_name,
|
||||
qos_profile)
|
||||
{}
|
||||
|
||||
SyncParametersClient::SyncParametersClient(
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: SyncParametersClient(
|
||||
std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
|
||||
node,
|
||||
remote_node_name,
|
||||
qos_profile)
|
||||
{}
|
||||
|
||||
SyncParametersClient::SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: SyncParametersClient(
|
||||
executor,
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
node->get_node_graph_interface(),
|
||||
node->get_node_services_interface(),
|
||||
remote_node_name,
|
||||
qos_profile)
|
||||
{}
|
||||
|
||||
SyncParametersClient::SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
|
||||
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
: executor_(executor), node_base_interface_(node_base_interface)
|
||||
{
|
||||
async_parameters_client_ =
|
||||
std::make_shared<AsyncParametersClient>(node, remote_node_name, qos_profile);
|
||||
std::make_shared<AsyncParametersClient>(
|
||||
node_base_interface,
|
||||
node_topics_interface,
|
||||
node_graph_interface,
|
||||
node_services_interface,
|
||||
remote_node_name,
|
||||
qos_profile);
|
||||
}
|
||||
|
||||
std::vector<rclcpp::Parameter>
|
||||
@@ -361,7 +411,7 @@ SyncParametersClient::get_parameters(const std::vector<std::string> & parameter_
|
||||
{
|
||||
auto f = async_parameters_client_->get_parameters(parameter_names);
|
||||
using rclcpp::executors::spin_node_until_future_complete;
|
||||
if (spin_node_until_future_complete(*executor_, node_->get_node_base_interface(), f) ==
|
||||
if (spin_node_until_future_complete(*executor_, node_base_interface_, f) ==
|
||||
rclcpp::executor::FutureReturnCode::SUCCESS)
|
||||
{
|
||||
return f.get();
|
||||
@@ -385,7 +435,7 @@ SyncParametersClient::get_parameter_types(const std::vector<std::string> & param
|
||||
auto f = async_parameters_client_->get_parameter_types(parameter_names);
|
||||
|
||||
using rclcpp::executors::spin_node_until_future_complete;
|
||||
if (spin_node_until_future_complete(*executor_, node_->get_node_base_interface(), f) ==
|
||||
if (spin_node_until_future_complete(*executor_, node_base_interface_, f) ==
|
||||
rclcpp::executor::FutureReturnCode::SUCCESS)
|
||||
{
|
||||
return f.get();
|
||||
@@ -399,9 +449,8 @@ SyncParametersClient::set_parameters(
|
||||
{
|
||||
auto f = async_parameters_client_->set_parameters(parameters);
|
||||
|
||||
auto node_base_interface = node_->get_node_base_interface();
|
||||
using rclcpp::executors::spin_node_until_future_complete;
|
||||
if (spin_node_until_future_complete(*executor_, node_base_interface, f) ==
|
||||
if (spin_node_until_future_complete(*executor_, node_base_interface_, f) ==
|
||||
rclcpp::executor::FutureReturnCode::SUCCESS)
|
||||
{
|
||||
return f.get();
|
||||
@@ -416,7 +465,7 @@ SyncParametersClient::set_parameters_atomically(
|
||||
auto f = async_parameters_client_->set_parameters_atomically(parameters);
|
||||
|
||||
using rclcpp::executors::spin_node_until_future_complete;
|
||||
if (spin_node_until_future_complete(*executor_, node_->get_node_base_interface(), f) ==
|
||||
if (spin_node_until_future_complete(*executor_, node_base_interface_, f) ==
|
||||
rclcpp::executor::FutureReturnCode::SUCCESS)
|
||||
{
|
||||
return f.get();
|
||||
@@ -433,7 +482,7 @@ SyncParametersClient::list_parameters(
|
||||
auto f = async_parameters_client_->list_parameters(parameter_prefixes, depth);
|
||||
|
||||
using rclcpp::executors::spin_node_until_future_complete;
|
||||
if (spin_node_until_future_complete(*executor_, node_->get_node_base_interface(), f) ==
|
||||
if (spin_node_until_future_complete(*executor_, node_base_interface_, f) ==
|
||||
rclcpp::executor::FutureReturnCode::SUCCESS)
|
||||
{
|
||||
return f.get();
|
||||
|
||||
71
rclcpp/test/test_local_parameters.cpp
Normal file
71
rclcpp/test/test_local_parameters.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2018 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 <cstdio>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
TEST(test_local_parameters, set_parameter_if_not_set) {
|
||||
auto node = rclcpp::Node::make_shared("test_local_parameters_set_parameter_if_not_set");
|
||||
|
||||
{
|
||||
// try to set a map of parameters
|
||||
std::map<std::string, double> bar_map{
|
||||
{"x", 0.5},
|
||||
{"y", 1.0},
|
||||
};
|
||||
node->set_parameters_if_not_set("bar", bar_map);
|
||||
double bar_x_value;
|
||||
ASSERT_TRUE(node->get_parameter("bar.x", bar_x_value));
|
||||
EXPECT_EQ(bar_x_value, 0.5);
|
||||
double bar_y_value;
|
||||
ASSERT_TRUE(node->get_parameter("bar.y", bar_y_value));
|
||||
EXPECT_EQ(bar_y_value, 1.0);
|
||||
std::map<std::string, double> new_map;
|
||||
ASSERT_TRUE(node->get_parameters("bar", new_map));
|
||||
ASSERT_EQ(new_map.size(), 2U);
|
||||
EXPECT_EQ(new_map["x"], 0.5);
|
||||
EXPECT_EQ(new_map["y"], 1.0);
|
||||
}
|
||||
|
||||
{
|
||||
// try to get a map of parameters that doesn't exist
|
||||
std::map<std::string, double> no_exist_map;
|
||||
ASSERT_FALSE(node->get_parameters("no_exist", no_exist_map));
|
||||
}
|
||||
|
||||
{
|
||||
// set parameters for a map with different types, then try to get them back as a map
|
||||
node->set_parameter_if_not_set("baz.x", 1.0);
|
||||
node->set_parameter_if_not_set("baz.y", "hello");
|
||||
std::map<std::string, double> baz_map;
|
||||
EXPECT_THROW(node->get_parameters("baz", baz_map), rclcpp::ParameterTypeException);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
::setvbuf(stdout, NULL, _IONBF, BUFSIZ);
|
||||
|
||||
// NOTE: use custom main to ensure that rclcpp::init is called only once
|
||||
rclcpp::init(argc, argv);
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
int ret = RUN_ALL_TESTS();
|
||||
rclcpp::shutdown();
|
||||
return ret;
|
||||
}
|
||||
@@ -44,10 +44,11 @@ TEST_F(TestNodeWithInitialValues, no_initial_values) {
|
||||
auto node = rclcpp::Node::make_shared(
|
||||
"node_name", "", context, arguments, initial_values, use_global_arguments, use_intra_process);
|
||||
auto list_params_result = node->list_parameters({}, 0);
|
||||
EXPECT_EQ(0u, list_params_result.names.size());
|
||||
// Has use_sim_time parameter
|
||||
EXPECT_EQ(1u, list_params_result.names.size());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeWithInitialValues, multiple_initial_values) {
|
||||
TEST_F(TestNodeWithInitialValues, multiple_undeclared_initial_values) {
|
||||
auto context = rclcpp::contexts::default_context::get_global_default_context();
|
||||
const std::vector<std::string> arguments = {};
|
||||
const std::vector<rclcpp::Parameter> initial_values = {
|
||||
@@ -60,7 +61,53 @@ TEST_F(TestNodeWithInitialValues, multiple_initial_values) {
|
||||
auto node = rclcpp::Node::make_shared(
|
||||
"node_name", "", context, arguments, initial_values, use_global_arguments, use_intra_process);
|
||||
auto list_params_result = node->list_parameters({}, 0);
|
||||
EXPECT_EQ(3u, list_params_result.names.size());
|
||||
// Has use_sim_time parameter
|
||||
EXPECT_EQ(1u, list_params_result.names.size());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeWithInitialValues, multiple_declared_initial_values) {
|
||||
auto context = rclcpp::contexts::default_context::get_global_default_context();
|
||||
const std::vector<std::string> arguments = {};
|
||||
const std::vector<rclcpp::Parameter> initial_values = {
|
||||
rclcpp::Parameter("foo", true),
|
||||
rclcpp::Parameter("bar", "hello world"),
|
||||
rclcpp::Parameter("baz", std::vector<double>{3.14, 2.718})
|
||||
};
|
||||
const bool use_global_arguments = false;
|
||||
const bool use_intra_process = false;
|
||||
auto node = rclcpp::Node::make_shared(
|
||||
"node_name", "", context, arguments, initial_values, use_global_arguments, use_intra_process);
|
||||
|
||||
node->declare_parameter("foo");
|
||||
node->declare_parameter("bar");
|
||||
node->declare_parameter("baz");
|
||||
|
||||
auto list_params_result = node->list_parameters({}, 0);
|
||||
EXPECT_TRUE(node->get_parameter("foo").get_value<bool>());
|
||||
EXPECT_STREQ("hello world", node->get_parameter("bar").get_value<std::string>().c_str());
|
||||
std::vector<double> double_array = node->get_parameter("baz").get_value<std::vector<double>>();
|
||||
ASSERT_EQ(2u, double_array.size());
|
||||
EXPECT_DOUBLE_EQ(3.14, double_array.at(0));
|
||||
EXPECT_DOUBLE_EQ(2.718, double_array.at(1));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeWithInitialValues, multiple_undeclared_initial_values_allowed) {
|
||||
auto context = rclcpp::contexts::default_context::get_global_default_context();
|
||||
const std::vector<std::string> arguments = {};
|
||||
const std::vector<rclcpp::Parameter> initial_values = {
|
||||
rclcpp::Parameter("foo", true),
|
||||
rclcpp::Parameter("bar", "hello world"),
|
||||
rclcpp::Parameter("baz", std::vector<double>{3.14, 2.718})
|
||||
};
|
||||
const bool use_global_arguments = false;
|
||||
const bool use_intra_process = false;
|
||||
const bool start_param_services = true;
|
||||
const bool allow_undeclared_params = true;
|
||||
auto node = rclcpp::Node::make_shared(
|
||||
"node_name", "", context, arguments, initial_values, use_global_arguments, use_intra_process,
|
||||
start_param_services, allow_undeclared_params);
|
||||
|
||||
auto list_params_result = node->list_parameters({}, 0);
|
||||
EXPECT_TRUE(node->get_parameter("foo").get_value<bool>());
|
||||
EXPECT_STREQ("hello world", node->get_parameter("bar").get_value<std::string>().c_str());
|
||||
std::vector<double> double_array = node->get_parameter("baz").get_value<std::vector<double>>();
|
||||
|
||||
@@ -111,30 +111,19 @@ bool
|
||||
ServerGoalHandleBase::try_canceling() noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(rcl_handle_mutex_);
|
||||
// Check if the goal reached a terminal state already
|
||||
const bool active = rcl_action_goal_handle_is_active(rcl_handle_.get());
|
||||
if (!active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rcl_ret_t ret;
|
||||
|
||||
// Get the current state
|
||||
rcl_action_goal_state_t state = GOAL_STATE_UNKNOWN;
|
||||
ret = rcl_action_goal_handle_get_status(rcl_handle_.get(), &state);
|
||||
if (RCL_RET_OK != ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it's not already canceling then transition to that state
|
||||
if (GOAL_STATE_CANCELING != state) {
|
||||
// Check if the goal is cancelable
|
||||
const bool is_cancelable = rcl_action_goal_handle_is_cancelable(rcl_handle_.get());
|
||||
if (is_cancelable) {
|
||||
// Transition to CANCELING
|
||||
ret = rcl_action_update_goal_state(rcl_handle_.get(), GOAL_EVENT_CANCEL);
|
||||
if (RCL_RET_OK != ret) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the state again
|
||||
rcl_action_goal_state_t state = GOAL_STATE_UNKNOWN;
|
||||
// Get the current state
|
||||
ret = rcl_action_goal_handle_get_status(rcl_handle_.get(), &state);
|
||||
if (RCL_RET_OK != ret) {
|
||||
return false;
|
||||
|
||||
@@ -97,6 +97,7 @@ public:
|
||||
* pipeline to pass messages between nodes in the same process using shared memory.
|
||||
* \param[in] start_parameter_services True to setup ROS interfaces for accessing parameters
|
||||
* in the node.
|
||||
* \param[in] allow_undeclared_parameters True to allow any parameter name to be set on the node.
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
LifecycleNode(
|
||||
@@ -107,7 +108,8 @@ public:
|
||||
const std::vector<rclcpp::Parameter> & initial_parameters,
|
||||
bool use_global_arguments = true,
|
||||
bool use_intra_process_comms = false,
|
||||
bool start_parameter_services = true);
|
||||
bool start_parameter_services = true,
|
||||
bool allow_undeclared_parameters = false);
|
||||
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
virtual ~LifecycleNode();
|
||||
|
||||
@@ -66,7 +66,8 @@ LifecycleNode::LifecycleNode(
|
||||
const std::vector<rclcpp::Parameter> & initial_parameters,
|
||||
bool use_global_arguments,
|
||||
bool use_intra_process_comms,
|
||||
bool start_parameter_services)
|
||||
bool start_parameter_services,
|
||||
bool allow_undeclared_parameters)
|
||||
: node_base_(new rclcpp::node_interfaces::NodeBase(
|
||||
node_name, namespace_, context, arguments, use_global_arguments)),
|
||||
node_graph_(new rclcpp::node_interfaces::NodeGraph(node_base_.get())),
|
||||
@@ -88,7 +89,8 @@ LifecycleNode::LifecycleNode(
|
||||
node_clock_,
|
||||
initial_parameters,
|
||||
use_intra_process_comms,
|
||||
start_parameter_services
|
||||
start_parameter_services,
|
||||
allow_undeclared_parameters
|
||||
)),
|
||||
node_waitables_(new rclcpp::node_interfaces::NodeWaitables(node_base_.get())),
|
||||
use_intra_process_comms_(use_intra_process_comms),
|
||||
|
||||
Reference in New Issue
Block a user