Compare commits

..

8 Commits

Author SHA1 Message Date
Jacob Perron
2d6db19c0d 0.6.5 2019-12-05 14:08:46 -08:00
Jacob Perron
05a8e5c751 [rclcpp_action] Do not throw exception in action client if take fails (#888) (#905)
As documented in rcl_action, a return code of RCL_RET_ACTION_CLIENT_TAKE_FAILED does not mean that
an error occurred.

Signed-off-by: Jacob Perron <jacob@openrobotics.org>
2019-11-26 12:30:50 -08:00
Steven! Ragnarök
7f23bea7a3 0.6.4 2019-04-05 21:56:38 -07:00
Jacob Perron
f7bb006f75 Backport #637 - Wait for action server before sending goal (#686)
Resolves #638

Co-authored-by: Shane Loretz <shane.loretz@gmail.com>
2019-04-05 14:43:40 -04:00
Steven! Ragnarök
e32d17980d 0.6.3 2019-02-08 10:55:03 -08:00
Chris Lalancette
cd6f195c60 Get parameter map (#575) (crystal-backport) (#619)
* Get parameter map (#575)

* Add in the ability to get parameters in a map.

Any parameters that have a "." in them will be considered to
be part of a "map" (though they can also be get and set
individually).  This PR adds two new template specializations
to the public node API so that it can take a map, and store
the list of values (so setting the parameter with a name of
"foo" and a key of "x" will end up with a parameter of "foo.x").
It also adds an API to get all of the keys corresponding to
a prefix, and returing that as a map (so a get of "foo" will
get all parameters that begin with "foo.").  Note that all
parameters within the map must have the same type, otherwise
an rclcpp::ParameterTypeException will be thrown.

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

* Fix style problems pointed out by uncrustify/cpplint.

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

* Move tests for set_parameter_if_not_set/get_parameter map to rclcpp.

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

* Rename get_parameter -> get_parameters.

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

* Add in documentation from review.

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

* Use list_parameters instead of get_parameters_by_prefix.

This way, we don't break ABI in crystal.

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

* Fix style problems.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2019-01-29 16:05:47 -05:00
Steven! Ragnarök
77a3385473 Merge pull request #616 from ros2/crystal-backport-613
Backport #613 to crystal branch.
2019-01-09 15:50:17 -08:00
Jacob Perron
8b176288e5 Fix errors from uncrustify v0.68 (#613) 2019-01-08 15:18:48 -08:00
29 changed files with 180 additions and 828 deletions

View File

@@ -2,6 +2,20 @@
Changelog for package rclcpp
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.6.5 (2019-12-05)
------------------
0.6.4 (2019-04-06)
------------------
0.6.3 (2019-02-08)
------------------
* Added the ability to get parameters in a map. (`#575 <https://github.com/ros2/rclcpp/issues/575>`_)
* Backported by (`#619 <https://github.com/ros2/rclcpp/issues/619>`_) for Crystal.
* Fix errors from uncrustify v0.68 (`#613 <https://github.com/ros2/rclcpp/issues/613>`_)
* Backported by `#616 <https://github.com/ros2/rclcpp/issues/616>`_ for Crystal.
* Contributors: Chris Lalancette, Jacob Perron, Steven! Ragnarök
0.6.2 (2018-12-13)
------------------
* Updated to use signal safe synchronization with platform specific semaphores (`#607 <https://github.com/ros2/rclcpp/issues/607>`_)

View File

@@ -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::__bind<ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
struct function_traits<std::__1::__bind<ReturnTypeT (ClassT::*)(Args ...), FArgs ...>>
#elif defined _GLIBCXX_RELEASE // glibc++ (GNU C++ >= 7.1)
struct function_traits<std::_Bind<ReturnTypeT(ClassT::*(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::__bind<ReturnTypeT( &)(Args ...), FArgs ...>>
struct function_traits<std::__1::__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

View File

@@ -95,7 +95,6 @@ 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(
@@ -106,8 +105,7 @@ public:
const std::vector<Parameter> & initial_parameters,
bool use_global_arguments = true,
bool use_intra_process_comms = false,
bool start_parameter_services = true,
bool allow_undeclared_parameters = false);
bool start_parameter_services = true);
RCLCPP_PUBLIC
virtual ~Node();
@@ -267,36 +265,6 @@ 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);

View File

@@ -210,16 +210,6 @@ 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(
@@ -278,15 +268,17 @@ 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>();
}
bool retval = false;
std::vector<std::string> prefix{name};
std::string name_with_dot = name + ".";
rcl_interfaces::msg::ListParametersResult result = node_parameters_->list_parameters(prefix, 0);
for (const auto & param : result.names) {
values[param.substr(name_with_dot.length())] =
node_parameters_->get_parameter(param).get_value<MapValueT>();
retval = true;
}
return result;
return retval;
}
template<typename ParameterT>

View File

@@ -1,162 +0,0 @@
// 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_

View File

@@ -61,7 +61,6 @@ 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_;

View File

@@ -40,19 +40,6 @@ 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
{
@@ -67,65 +54,60 @@ public:
const node_interfaces::NodeClockInterface::SharedPtr node_clock,
const std::vector<Parameter> & initial_parameters,
bool use_intra_process,
bool start_parameter_services,
bool allow_undeclared_parameters);
bool start_parameter_services);
RCLCPP_PUBLIC
virtual
~NodeParameters();
RCLCPP_PUBLIC
void
declare_parameter(
const std::string & name,
const rclcpp::ParameterValue & default_value,
bool read_only) override;
RCLCPP_PUBLIC
virtual
std::vector<rcl_interfaces::msg::SetParametersResult>
set_parameters(
const std::vector<rclcpp::Parameter> & parameters) override;
const std::vector<rclcpp::Parameter> & parameters);
RCLCPP_PUBLIC
virtual
rcl_interfaces::msg::SetParametersResult
set_parameters_atomically(
const std::vector<rclcpp::Parameter> & parameters) override;
const std::vector<rclcpp::Parameter> & parameters);
RCLCPP_PUBLIC
virtual
std::vector<rclcpp::Parameter>
get_parameters(const std::vector<std::string> & names) const override;
get_parameters(const std::vector<std::string> & names) const;
RCLCPP_PUBLIC
virtual
rclcpp::Parameter
get_parameter(const std::string & name) const override;
get_parameter(const std::string & name) const;
RCLCPP_PUBLIC
virtual
bool
get_parameter(
const std::string & name,
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::Parameter & parameter) const;
RCLCPP_PUBLIC
virtual
std::vector<rcl_interfaces::msg::ParameterDescriptor>
describe_parameters(const std::vector<std::string> & names) const override;
describe_parameters(const std::vector<std::string> & names) const;
RCLCPP_PUBLIC
virtual
std::vector<uint8_t>
get_parameter_types(const std::vector<std::string> & names) const override;
get_parameter_types(const std::vector<std::string> & names) const;
RCLCPP_PUBLIC
virtual
rcl_interfaces::msg::ListParametersResult
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const override;
list_parameters(const std::vector<std::string> & prefixes, uint64_t depth) const;
RCLCPP_PUBLIC
virtual
void
register_param_change_callback(ParametersCallbackFunction callback) override;
register_param_change_callback(ParametersCallbackFunction callback);
private:
RCLCPP_DISABLE_COPY(NodeParameters)
@@ -134,11 +116,7 @@ private:
ParametersCallbackFunction parameters_callback_ = nullptr;
std::map<std::string, ParameterInfo> parameters_;
std::map<std::string, rclcpp::ParameterValue> initial_parameter_values_;
bool allow_undeclared_ = false;
std::map<std::string, rclcpp::Parameter> parameters_;
Publisher<rcl_interfaces::msg::ParameterEvent>::SharedPtr events_publisher_;

View File

@@ -15,7 +15,6 @@
#ifndef RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_INTERFACE_HPP_
#define RCLCPP__NODE_INTERFACES__NODE_PARAMETERS_INTERFACE_HPP_
#include <map>
#include <string>
#include <vector>
@@ -38,25 +37,6 @@ 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;
@@ -109,20 +89,6 @@ 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>

View File

@@ -28,25 +28,6 @@
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
{
@@ -63,9 +44,6 @@ public:
{
}
RCLCPP_PUBLIC
explicit Parameter(const rclcpp::node_interfaces::ParameterInfo & parameter_info);
RCLCPP_PUBLIC
ParameterType
get_type() const;
@@ -82,11 +60,6 @@ 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)
@@ -98,7 +71,10 @@ public:
/// Get value of parameter using c++ types as template argument.
template<typename T>
decltype(auto)
get_value() const;
get_value() const
{
return value_.get<T>();
}
RCLCPP_PUBLIC
bool
@@ -166,49 +142,6 @@ 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 =
[&parameter]() -> 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

View File

@@ -185,29 +185,6 @@ 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);
@@ -291,7 +268,7 @@ public:
private:
rclcpp::executor::Executor::SharedPtr executor_;
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface_;
rclcpp::Node::SharedPtr node_;
AsyncParametersClient::SharedPtr async_parameters_client_;
};

View File

@@ -28,8 +28,7 @@
namespace rclcpp
{
enum ParameterType : uint8_t
enum ParameterType
{
PARAMETER_NOT_SET = rcl_interfaces::msg::ParameterType::PARAMETER_NOT_SET,
PARAMETER_BOOL = rcl_interfaces::msg::ParameterType::PARAMETER_BOOL,
@@ -46,11 +45,11 @@ enum ParameterType : uint8_t
/// Return the name of a parameter type
RCLCPP_PUBLIC
std::string
to_string(ParameterType type);
to_string(const ParameterType type);
RCLCPP_PUBLIC
std::ostream &
operator<<(std::ostream & os, ParameterType type);
operator<<(std::ostream & os, const ParameterType type);
/// Indicate the parameter type does not match the expected type.
class ParameterTypeException : public std::runtime_error

View File

@@ -1,115 +0,0 @@
// 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_

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.6.2</version>
<version>0.6.5</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

@@ -60,8 +60,9 @@ Executor::Executor(const ExecutorArgs & args)
// Store the context for later use.
context_ = args.context;
ret = rcl_wait_set_init(&wait_set_, 0, 2, 0, 0, 0, context_->get_rcl_context().get(), allocator);
if (RCL_RET_OK != ret) {
if (rcl_wait_set_init(
&wait_set_, 0, 2, 0, 0, 0, allocator) != RCL_RET_OK)
{
RCUTILS_LOG_ERROR_NAMED(
"rclcpp",
"failed to create wait set: %s", rcl_get_error_string().str);

View File

@@ -79,7 +79,6 @@ 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");

View File

@@ -60,8 +60,7 @@ Node::Node(
const std::vector<rclcpp::Parameter> & initial_parameters,
bool use_global_arguments,
bool use_intra_process_comms,
bool start_parameter_services,
bool allow_undeclared_parameters)
bool start_parameter_services)
: 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())),
@@ -83,8 +82,7 @@ Node::Node(
node_clock_,
initial_parameters,
use_intra_process_comms,
start_parameter_services,
allow_undeclared_parameters
start_parameter_services
)),
node_time_source_(new rclcpp::node_interfaces::NodeTimeSource(
node_base_,
@@ -134,15 +132,6 @@ 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)

View File

@@ -39,9 +39,8 @@ 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,
bool allow_undeclared_parameters)
: allow_undeclared_(allow_undeclared_parameters), node_clock_(node_clock)
bool start_parameter_services)
: node_clock_(node_clock)
{
using MessageT = rcl_interfaces::msg::ParameterEvent;
using PublisherT = rclcpp::Publisher<MessageT>;
@@ -115,6 +114,8 @@ 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) {
@@ -139,19 +140,25 @@ NodeParameters::NodeParameters(
// 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());
parameters[param.get_name()] = param;
}
}
// initial values passed to constructor overwrite yaml file sources
for (auto & param : initial_parameters) {
initial_parameter_values_[param.get_name()] =
rclcpp::ParameterValue(param.get_value_message());
parameters[param.get_name()] = param;
}
if (!initial_parameters.empty() && allow_undeclared_) {
rcl_interfaces::msg::SetParametersResult result = set_parameters_atomically(initial_parameters);
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 (!result.successful) {
throw std::runtime_error("Failed to set initial parameters");
}
@@ -161,59 +168,6 @@ 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)
@@ -231,7 +185,7 @@ NodeParameters::set_parameters_atomically(
const std::vector<rclcpp::Parameter> & parameters)
{
std::lock_guard<std::mutex> lock(mutex_);
std::map<std::string, rclcpp::node_interfaces::ParameterInfo> tmp_map;
std::map<std::string, rclcpp::Parameter> tmp_map;
auto parameter_event = std::make_shared<rcl_interfaces::msg::ParameterEvent>();
parameter_event->node = combined_name_;
@@ -248,79 +202,33 @@ NodeParameters::set_parameters_atomically(
return result;
}
std::vector<std::string> to_delete;
for (auto p : parameters) {
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) {
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
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 {
// 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 {
// Create new undeclared parameter
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());
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;
} else {
// case: parameter was set before, and input is something other than "NOT_SET"
parameter_event->changed_parameters.push_back(p.to_parameter_msg());
}
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 truly deleted parameters
for (const std::string & param_name : to_delete) {
tmp_map.erase(param_name);
// remove explicitly deleted parameters
for (auto p : parameters) {
if (p.get_type() == rclcpp::ParameterType::PARAMETER_NOT_SET) {
tmp_map.erase(p.get_name());
}
}
std::swap(tmp_map, parameters_);
@@ -338,11 +246,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::node_interfaces::ParameterInfo> & kv) {
[&name](const std::pair<std::string, rclcpp::Parameter> & kv) {
return name == kv.first;
}))
{
results.emplace_back(name, parameters_.at(name).value);
results.push_back(parameters_.at(name));
}
}
return results;
@@ -367,39 +275,14 @@ NodeParameters::get_parameter(
{
std::lock_guard<std::mutex> lock(mutex_);
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};
if (parameters_.count(name)) {
parameter = parameters_.at(name);
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
{
@@ -410,7 +293,10 @@ NodeParameters::describe_parameters(const std::vector<std::string> & names) cons
return name == kv.first;
}))
{
results.push_back(kv.second.descriptor);
rcl_interfaces::msg::ParameterDescriptor parameter_descriptor;
parameter_descriptor.name = kv.first;
parameter_descriptor.type = kv.second.get_type();
results.push_back(parameter_descriptor);
}
}
return results;
@@ -426,7 +312,7 @@ NodeParameters::get_parameter_types(const std::vector<std::string> & names) cons
return name == kv.first;
}))
{
results.push_back(kv.second.value.get_type());
results.push_back(kv.second.get_type());
} else {
results.push_back(rcl_interfaces::msg::ParameterType::PARAMETER_NOT_SET);
}

View File

@@ -12,14 +12,12 @@
// 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/node_interfaces/node_parameters.hpp"
#include "rclcpp/parameter.hpp"
#include "rclcpp/utilities.hpp"
using rclcpp::ParameterType;
@@ -35,11 +33,6 @@ 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
{
@@ -64,12 +57,6 @@ 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
{

View File

@@ -350,60 +350,10 @@ SyncParametersClient::SyncParametersClient(
rclcpp::Node::SharedPtr 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::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)
: executor_(executor), node_(node)
{
async_parameters_client_ =
std::make_shared<AsyncParametersClient>(
node_base_interface,
node_topics_interface,
node_graph_interface,
node_services_interface,
remote_node_name,
qos_profile);
std::make_shared<AsyncParametersClient>(node, remote_node_name, qos_profile);
}
std::vector<rclcpp::Parameter>
@@ -411,7 +361,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_base_interface_, f) ==
if (spin_node_until_future_complete(*executor_, node_->get_node_base_interface(), f) ==
rclcpp::executor::FutureReturnCode::SUCCESS)
{
return f.get();
@@ -435,7 +385,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_base_interface_, f) ==
if (spin_node_until_future_complete(*executor_, node_->get_node_base_interface(), f) ==
rclcpp::executor::FutureReturnCode::SUCCESS)
{
return f.get();
@@ -449,8 +399,9 @@ 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();
@@ -465,7 +416,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_base_interface_, f) ==
if (spin_node_until_future_complete(*executor_, node_->get_node_base_interface(), f) ==
rclcpp::executor::FutureReturnCode::SUCCESS)
{
return f.get();
@@ -482,7 +433,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_base_interface_, f) ==
if (spin_node_until_future_complete(*executor_, node_->get_node_base_interface(), f) ==
rclcpp::executor::FutureReturnCode::SUCCESS)
{
return f.get();

View File

@@ -44,11 +44,10 @@ 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);
// Has use_sim_time parameter
EXPECT_EQ(1u, list_params_result.names.size());
EXPECT_EQ(0u, list_params_result.names.size());
}
TEST_F(TestNodeWithInitialValues, multiple_undeclared_initial_values) {
TEST_F(TestNodeWithInitialValues, multiple_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 = {
@@ -61,53 +60,7 @@ TEST_F(TestNodeWithInitialValues, multiple_undeclared_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);
// 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_EQ(3u, list_params_result.names.size());
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>>();

View File

@@ -2,6 +2,19 @@
Changelog for package rclcpp_action
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.6.5 (2019-12-05)
------------------
* Do not throw exception in action client if take fails (`#888 <https://github.com/ros2/rclcpp/issues/888>`_) (`#905 <https://github.com/ros2/rclcpp/issues/905>`_)
* Contributors: Jacob Perron
0.6.4 (2019-04-05)
------------------
* Wait for action server before sending goal (`#686 <https://github.com/ros2/rclcpp/issues/686>`_)
* Contributors: Jacob Perron, Shane Loretz
0.6.3 (2019-02-08)
------------------
0.6.2 (2018-12-13)
------------------

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.6.2</version>
<version>0.6.5</version>
<description>Adds action APIs for C++.</description>
<maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
<license>Apache License 2.0</license>

View File

@@ -388,20 +388,20 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_feedback(
pimpl_->client_handle.get(), feedback_message.get());
pimpl_->is_feedback_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking feedback");
} else {
if (RCL_RET_OK == ret) {
this->handle_feedback_message(feedback_message);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking feedback");
}
} else if (pimpl_->is_status_ready) {
std::shared_ptr<void> status_message = this->create_status_message();
rcl_ret_t ret = rcl_action_take_status(
pimpl_->client_handle.get(), status_message.get());
pimpl_->is_status_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking status");
} else {
if (RCL_RET_OK == ret) {
this->handle_status_message(status_message);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking status");
}
} else if (pimpl_->is_goal_response_ready) {
rmw_request_id_t response_header;
@@ -409,10 +409,10 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_goal_response(
pimpl_->client_handle.get(), &response_header, goal_response.get());
pimpl_->is_goal_response_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking goal response");
} else {
if (RCL_RET_OK == ret) {
this->handle_goal_response(response_header, goal_response);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking goal response");
}
} else if (pimpl_->is_result_response_ready) {
rmw_request_id_t response_header;
@@ -420,10 +420,10 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_result_response(
pimpl_->client_handle.get(), &response_header, result_response.get());
pimpl_->is_result_response_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking result response");
} else {
if (RCL_RET_OK == ret) {
this->handle_result_response(response_header, result_response);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking result response");
}
} else if (pimpl_->is_cancel_response_ready) {
rmw_request_id_t response_header;
@@ -431,10 +431,10 @@ ClientBase::execute()
rcl_ret_t ret = rcl_action_take_cancel_response(
pimpl_->client_handle.get(), &response_header, cancel_response.get());
pimpl_->is_cancel_response_ready = false;
if (RCL_RET_OK != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking cancel response");
} else {
if (RCL_RET_OK == ret) {
this->handle_cancel_response(response_header, cancel_response);
} else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
rclcpp::exceptions::throw_from_rcl_error(ret, "error taking cancel response");
}
} else {
throw std::runtime_error("Executing action client but nothing is ready");

View File

@@ -111,19 +111,30 @@ 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;
// 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
// 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) {
ret = rcl_action_update_goal_state(rcl_handle_.get(), GOAL_EVENT_CANCEL);
if (RCL_RET_OK != ret) {
return false;
}
}
rcl_action_goal_state_t state = GOAL_STATE_UNKNOWN;
// Get the current state
// Get the state again
ret = rcl_action_goal_handle_get_status(rcl_handle_.get(), &state);
if (RCL_RET_OK != ret) {
return false;

View File

@@ -47,6 +47,8 @@
using namespace std::chrono_literals;
const auto WAIT_FOR_SERVER_TIMEOUT = 10s;
class TestClient : public ::testing::Test
{
protected:
@@ -269,6 +271,7 @@ TEST_F(TestClient, construction_and_destruction)
TEST_F(TestClient, async_send_goal_but_ignore_feedback_and_result)
{
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
ActionGoal bad_goal;
bad_goal.order = -5;
@@ -290,6 +293,7 @@ TEST_F(TestClient, async_send_goal_but_ignore_feedback_and_result)
TEST_F(TestClient, async_send_goal_and_ignore_feedback_but_wait_for_result)
{
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
ActionGoal goal;
goal.order = 5;
@@ -311,6 +315,7 @@ TEST_F(TestClient, async_send_goal_and_ignore_feedback_but_wait_for_result)
TEST_F(TestClient, async_send_goal_with_feedback_and_result)
{
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
ActionGoal goal;
goal.order = 4;
@@ -342,6 +347,7 @@ TEST_F(TestClient, async_send_goal_with_feedback_and_result)
TEST_F(TestClient, async_cancel_one_goal)
{
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
ActionGoal goal;
goal.order = 5;
@@ -359,6 +365,7 @@ TEST_F(TestClient, async_cancel_one_goal)
TEST_F(TestClient, async_cancel_all_goals)
{
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
ActionGoal goal;
goal.order = 6;
@@ -393,6 +400,7 @@ TEST_F(TestClient, async_cancel_all_goals)
TEST_F(TestClient, async_cancel_some_goals)
{
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
ActionGoal goal;
goal.order = 6;

View File

@@ -2,6 +2,15 @@
Changelog for package rclcpp_lifecycle
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
0.6.5 (2019-12-05)
------------------
0.6.4 (2019-04-06)
------------------
0.6.3 (2019-02-08)
------------------
0.6.2 (2018-12-13)
------------------

View File

@@ -97,7 +97,6 @@ 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(
@@ -108,8 +107,7 @@ 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 allow_undeclared_parameters = false);
bool start_parameter_services = true);
RCLCPP_LIFECYCLE_PUBLIC
virtual ~LifecycleNode();

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.6.2</version>
<version>0.6.5</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

@@ -66,8 +66,7 @@ LifecycleNode::LifecycleNode(
const std::vector<rclcpp::Parameter> & initial_parameters,
bool use_global_arguments,
bool use_intra_process_comms,
bool start_parameter_services,
bool allow_undeclared_parameters)
bool start_parameter_services)
: 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())),
@@ -89,8 +88,7 @@ LifecycleNode::LifecycleNode(
node_clock_,
initial_parameters,
use_intra_process_comms,
start_parameter_services,
allow_undeclared_parameters
start_parameter_services
)),
node_waitables_(new rclcpp::node_interfaces::NodeWaitables(node_base_.get())),
use_intra_process_comms_(use_intra_process_comms),