Compare commits
9 Commits
29.5.7
...
fujitatomo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
546f3ae655 | ||
|
|
4f507751e1 | ||
|
|
7bd14d812c | ||
|
|
e97d569f75 | ||
|
|
f81caaca49 | ||
|
|
127a10e8c8 | ||
|
|
b1ec85df16 | ||
|
|
c89a2b1013 | ||
|
|
1a282064a9 |
@@ -2,59 +2,11 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
29.5.7 (2026-02-09)
|
||||
29.6.0 (2025-04-25)
|
||||
-------------------
|
||||
* include the 1st spin that might throw the exception. (`#3042 <https://github.com/ros2/rclcpp/issues/3042>`_) (`#3044 <https://github.com/ros2/rclcpp/issues/3044>`_)
|
||||
* print warning message on owner node if the parameter operation fails. (`#3037 <https://github.com/ros2/rclcpp/issues/3037>`_) (`#3038 <https://github.com/ros2/rclcpp/issues/3038>`_)
|
||||
* remove test_static_executor_entities_collector.cpp (`#3041 <https://github.com/ros2/rclcpp/issues/3041>`_) (`#3045 <https://github.com/ros2/rclcpp/issues/3045>`_)
|
||||
* fix context in wait for message wait set (`#3030 <https://github.com/ros2/rclcpp/issues/3030>`_) (`#3031 <https://github.com/ros2/rclcpp/issues/3031>`_)
|
||||
* Improve the robustness of the TopicEndpointInfo constructor (`#3013 <https://github.com/ros2/rclcpp/issues/3013>`_) (`#3014 <https://github.com/ros2/rclcpp/issues/3014>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.6 (2025-12-23)
|
||||
-------------------
|
||||
* Unified Node Interfaces: Add const version of get_node_x_interface() (`#3006 <https://github.com/ros2/rclcpp/issues/3006>`_) (`#3008 <https://github.com/ros2/rclcpp/issues/3008>`_)
|
||||
* remove I/O from signal handler. (`#3000 <https://github.com/ros2/rclcpp/issues/3000>`_)
|
||||
* correct test function descriptions (`#2970 <https://github.com/ros2/rclcpp/issues/2970>`_) (`#2992 <https://github.com/ros2/rclcpp/issues/2992>`_)
|
||||
* Contributors: Tomoya Fujita, mergify[bot]
|
||||
|
||||
29.5.5 (2025-11-18)
|
||||
-------------------
|
||||
* Fix REP url locations (`#2987 <https://github.com/ros2/rclcpp/issues/2987>`_) (`#2989 <https://github.com/ros2/rclcpp/issues/2989>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.4 (2025-10-21)
|
||||
-------------------
|
||||
|
||||
29.5.3 (2025-09-11)
|
||||
-------------------
|
||||
* Fix: improve exception context for parameter_value_from (`#2917 <https://github.com/ros2/rclcpp/issues/2917>`_) (`#2919 <https://github.com/ros2/rclcpp/issues/2919>`_)
|
||||
* Allow for implicitly convertable loggers as well (`#2922 <https://github.com/ros2/rclcpp/issues/2922>`_) (`#2936 <https://github.com/ros2/rclcpp/issues/2936>`_)
|
||||
* Fix `start_type_description_service` param handling (`#2897 <https://github.com/ros2/rclcpp/issues/2897>`_) (`#2908 <https://github.com/ros2/rclcpp/issues/2908>`_)
|
||||
* Add qos parameter for wait_for_message function (`#2903 <https://github.com/ros2/rclcpp/issues/2903>`_) (`#2905 <https://github.com/ros2/rclcpp/issues/2905>`_)
|
||||
* Expose `typesupport_helpers` API needed for the Rosbag2 (`#2858 <https://github.com/ros2/rclcpp/issues/2858>`_) (`#2901 <https://github.com/ros2/rclcpp/issues/2901>`_)
|
||||
* Fujitatomoya/test append parameter override (`#2896 <https://github.com/ros2/rclcpp/issues/2896>`_) (`#2899 <https://github.com/ros2/rclcpp/issues/2899>`_)
|
||||
* Add overload of `append_parameter_override` (`#2891 <https://github.com/ros2/rclcpp/issues/2891>`_) (`#2894 <https://github.com/ros2/rclcpp/issues/2894>`_)
|
||||
* Contributors: Tim Clephas, mergify[bot]
|
||||
|
||||
29.5.2 (2025-07-07)
|
||||
-------------------
|
||||
* Shutdown deadlock fix jazzy (`#2887 <https://github.com/ros2/rclcpp/issues/2887>`_) (`#2888 <https://github.com/ros2/rclcpp/issues/2888>`_)
|
||||
* Fix test_publisher_with_system_default_qos (`#2881 <https://github.com/ros2/rclcpp/issues/2881>`_) (`#2884 <https://github.com/ros2/rclcpp/issues/2884>`_)
|
||||
* Contributors: Tomoya Fujita, Janosch Machowinski
|
||||
|
||||
29.5.1 (2025-06-23)
|
||||
-------------------
|
||||
* Removed warning test_qos (`#2859 <https://github.com/ros2/rclcpp/issues/2859>`_) (`#2873 <https://github.com/ros2/rclcpp/issues/2873>`_)
|
||||
* Fix for memory leaks in rclcpp::SerializedMessage (`#2861 <https://github.com/ros2/rclcpp/issues/2861>`_) (`#2863 <https://github.com/ros2/rclcpp/issues/2863>`_)
|
||||
* get_all_data_impl() does not handle null pointers properly, causing segmentation fault (backport `#2840 <https://github.com/ros2/rclcpp/issues/2840>`_) (`#2850 <https://github.com/ros2/rclcpp/issues/2850>`_)
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
|
||||
* QoSInitialization::from_rmw does not validate invalid history policy values, leading to silent failures (`#2841 <https://github.com/ros2/rclcpp/issues/2841>`_) (`#2846 <https://github.com/ros2/rclcpp/issues/2846>`_)
|
||||
* Add missing 's' to 'NodeParametersInterface' in doc/comment (`#2831 <https://github.com/ros2/rclcpp/issues/2831>`_) (`#2833 <https://github.com/ros2/rclcpp/issues/2833>`_)
|
||||
* subordinate node consistent behavior and update docstring. (`#2822 <https://github.com/ros2/rclcpp/issues/2822>`_) (`#2830 <https://github.com/ros2/rclcpp/issues/2830>`_)
|
||||
* throws std::invalid_argument if ParameterEvent is NULL. (`#2814 <https://github.com/ros2/rclcpp/issues/2814>`_)
|
||||
* Removed clang warnings (`#2823 <https://github.com/ros2/rclcpp/issues/2823>`_)
|
||||
* Contributors: Alejandro Hernández Cordero, Tomoya Fujita, mergify[bot]
|
||||
* Contributors: Alejandro Hernández Cordero, Tomoya Fujita
|
||||
|
||||
29.5.0 (2025-04-18)
|
||||
-------------------
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
This document is a declaration of software quality for the `rclcpp` package, based on the guidelines in [REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
This document is a declaration of software quality for the `rclcpp` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
# rclcpp Quality Declaration
|
||||
|
||||
The package `rclcpp` claims to be in the **Quality Level 1** category when it is used with a **Quality Level 1** middleware.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
## Version Policy [1]
|
||||
|
||||
@@ -55,7 +55,7 @@ All pull requests will be peer-reviewed, check [ROS 2 Developer Guide](https://d
|
||||
|
||||
### Continuous Integration [2.iv]
|
||||
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://reps.openrobotics.org/rep-2000/#support-tiers)
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://www.ros.org/reps/rep-2000.html#support-tiers)
|
||||
|
||||
Currently nightly results can be seen here:
|
||||
|
||||
@@ -213,7 +213,7 @@ It is **Quality Level 1**, see its [Quality Declaration document](https://github
|
||||
|
||||
## Platform Support [6]
|
||||
|
||||
`rclcpp` supports all of the tier 1 platforms as described in [REP-2000](https://reps.openrobotics.org/rep-2000/#support-tiers), and tests each change against all of them.
|
||||
`rclcpp` supports all of the tier 1 platforms as described in [REP-2000](https://www.ros.org/reps/rep-2000.html#support-tiers), and tests each change against all of them.
|
||||
|
||||
Currently nightly build status can be seen here:
|
||||
* [linux-aarch64_release](https://ci.ros2.org/view/nightly/job/nightly_linux-aarch64_release/lastBuild/rclcpp/)
|
||||
@@ -225,4 +225,4 @@ Currently nightly build status can be seen here:
|
||||
|
||||
### Vulnerability Disclosure Policy [7.i]
|
||||
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://reps.openrobotics.org/rep-2006/).
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://www.ros.org/reps/rep-2006.html).
|
||||
|
||||
@@ -200,21 +200,6 @@ public:
|
||||
bool
|
||||
ros_time_is_active();
|
||||
|
||||
/**
|
||||
* Deprecated. This API is broken, as there is no way to get a deep
|
||||
* copy of a clock. Therefore one can experience spurious wakeups triggered
|
||||
* by some other instance of a clock.
|
||||
*
|
||||
* Cancels an ongoing or future sleep operation of one thread.
|
||||
*
|
||||
* This function can be used by one thread, to wakeup another thread that is
|
||||
* blocked using any of the sleep_ or wait_ methods of this class.
|
||||
*/
|
||||
[[deprecated("Use ClockConditionalVariable")]]
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
cancel_sleep_or_wait();
|
||||
|
||||
/// Return the rcl_clock_t clock handle
|
||||
RCLCPP_PUBLIC
|
||||
rcl_clock_t *
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -69,7 +70,7 @@ public:
|
||||
*/
|
||||
void enqueue(BufferT request) override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
write_index_ = next_(write_index_);
|
||||
ring_buffer_[write_index_] = std::move(request);
|
||||
@@ -95,7 +96,7 @@ public:
|
||||
*/
|
||||
BufferT dequeue() override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
if (!has_data_()) {
|
||||
return BufferT();
|
||||
@@ -134,7 +135,7 @@ public:
|
||||
*/
|
||||
inline size_t next(size_t val)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::unique_lock lock(mutex_);
|
||||
return next_(val);
|
||||
}
|
||||
|
||||
@@ -146,7 +147,7 @@ public:
|
||||
*/
|
||||
inline bool has_data() const override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::shared_lock lock(mutex_);
|
||||
return has_data_();
|
||||
}
|
||||
|
||||
@@ -159,7 +160,7 @@ public:
|
||||
*/
|
||||
inline bool is_full() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::shared_lock lock(mutex_);
|
||||
return is_full_();
|
||||
}
|
||||
|
||||
@@ -171,13 +172,15 @@ public:
|
||||
*/
|
||||
size_t available_capacity() const override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::shared_lock lock(mutex_);
|
||||
return available_capacity_();
|
||||
}
|
||||
|
||||
void clear() override
|
||||
{
|
||||
TRACETOOLS_TRACEPOINT(rclcpp_ring_buffer_clear, static_cast<const void *>(this));
|
||||
std::unique_lock lock(mutex_);
|
||||
clear_();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -227,6 +230,14 @@ private:
|
||||
return capacity_ - size_;
|
||||
}
|
||||
|
||||
inline void clear_()
|
||||
{
|
||||
ring_buffer_.clear();
|
||||
size_ = 0;
|
||||
read_index_ = 0;
|
||||
write_index_ = capacity_ - 1;
|
||||
}
|
||||
|
||||
/// Traits for checking if a type is std::unique_ptr
|
||||
template<typename ...>
|
||||
struct is_std_unique_ptr final : std::false_type {};
|
||||
@@ -251,17 +262,13 @@ private:
|
||||
void> * = nullptr>
|
||||
std::vector<BufferT> get_all_data_impl()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::unique_lock lock(mutex_);
|
||||
std::vector<BufferT> result_vtr;
|
||||
result_vtr.reserve(size_);
|
||||
for (size_t id = 0; id < size_; ++id) {
|
||||
const auto & elem(ring_buffer_[(read_index_ + id) % capacity_]);
|
||||
if (elem != nullptr) {
|
||||
result_vtr.emplace_back(new typename is_std_unique_ptr<T>::Ptr_type(
|
||||
*elem));
|
||||
} else {
|
||||
result_vtr.emplace_back(nullptr);
|
||||
}
|
||||
result_vtr.emplace_back(
|
||||
new typename is_std_unique_ptr<T>::Ptr_type(
|
||||
*(ring_buffer_[(read_index_ + id) % capacity_])));
|
||||
}
|
||||
return result_vtr;
|
||||
}
|
||||
@@ -270,7 +277,7 @@ private:
|
||||
std::is_copy_constructible<T>::value, void> * = nullptr>
|
||||
std::vector<BufferT> get_all_data_impl()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::unique_lock lock(mutex_);
|
||||
std::vector<BufferT> result_vtr;
|
||||
result_vtr.reserve(size_);
|
||||
for (size_t id = 0; id < size_; ++id) {
|
||||
@@ -296,7 +303,7 @@ private:
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t capacity_;
|
||||
const size_t capacity_;
|
||||
|
||||
std::vector<BufferT> ring_buffer_;
|
||||
|
||||
@@ -304,7 +311,7 @@ private:
|
||||
size_t read_index_;
|
||||
size_t size_;
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
mutable std::shared_mutex mutex_;
|
||||
};
|
||||
|
||||
} // namespace buffers
|
||||
|
||||
@@ -78,34 +78,6 @@ RCLCPP_PUBLIC
|
||||
Logger
|
||||
get_node_logger(const rcl_node_t * node);
|
||||
|
||||
// TODO(ahcorde): Remove deprecated class on the next release (in Rolling after Kilted).
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
/// Get the current logging directory.
|
||||
/**
|
||||
* For more details of how the logging directory is determined,
|
||||
* see rcl_logging_get_logging_directory().
|
||||
*
|
||||
* \returns the logging directory being used.
|
||||
* \throws rclcpp::exceptions::RCLError if an unexpected error occurs.
|
||||
*/
|
||||
[[deprecated("use rclcpp::get_log_directory instead of rclcpp::get_logging_directory")]]
|
||||
RCLCPP_PUBLIC
|
||||
rcpputils::fs::path
|
||||
get_logging_directory();
|
||||
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/// Get the current logging directory.
|
||||
/**
|
||||
* For more details of how the logging directory is determined,
|
||||
|
||||
@@ -199,12 +199,6 @@ init_tuple(NodeT & n)
|
||||
{ \
|
||||
return StorageClassT::template get<NodeInterfaceType>(); \
|
||||
} \
|
||||
\
|
||||
std::shared_ptr<const NodeInterfaceType> \
|
||||
get_node_ ## NodeInterfaceName ## _interface() const \
|
||||
{ \
|
||||
return StorageClassT::template get<NodeInterfaceType>(); \
|
||||
} \
|
||||
}; \
|
||||
} // namespace rclcpp::node_interfaces::detail
|
||||
// *INDENT-ON*
|
||||
|
||||
@@ -53,17 +53,13 @@ public:
|
||||
/// Construct a TopicEndpointInfo from a rcl_topic_endpoint_info_t.
|
||||
RCLCPP_PUBLIC
|
||||
explicit TopicEndpointInfo(const rcl_topic_endpoint_info_t & info)
|
||||
: endpoint_type_(static_cast<rclcpp::EndpointType>(info.endpoint_type)),
|
||||
: node_name_(info.node_name),
|
||||
node_namespace_(info.node_namespace),
|
||||
topic_type_(info.topic_type),
|
||||
endpoint_type_(static_cast<rclcpp::EndpointType>(info.endpoint_type)),
|
||||
qos_profile_({info.qos_profile.history, info.qos_profile.depth}, info.qos_profile),
|
||||
topic_type_hash_(info.topic_type_hash)
|
||||
{
|
||||
if (!info.node_name || !info.node_namespace || !info.topic_type) {
|
||||
throw std::invalid_argument("Constructor TopicEndpointInfo with invalid topic endpoint info");
|
||||
}
|
||||
node_name_ = info.node_name;
|
||||
node_namespace_ = info.node_namespace;
|
||||
topic_type_ = info.topic_type;
|
||||
|
||||
std::copy(info.endpoint_gid, info.endpoint_gid + RMW_GID_STORAGE_SIZE, endpoint_gid_.begin());
|
||||
}
|
||||
|
||||
|
||||
@@ -146,14 +146,6 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Append a single parameter override, parameter idiom style.
|
||||
NodeOptions &
|
||||
append_parameter_override(const rclcpp::Parameter & param)
|
||||
{
|
||||
this->parameter_overrides().push_back(param);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Return the use_global_arguments flag.
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
|
||||
@@ -29,48 +29,26 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// \brief Extract the package name, middle module, and type name from a full type string.
|
||||
/// \details This function takes a full type string (e.g., "std_msgs/msg/String") and extracts
|
||||
/// the package name, middle module (if any), and type name. The middle module is the part
|
||||
/// between the package name and the type name, which is typically used for message types.
|
||||
/// For example, for "std_msgs/msg/String", it returns ("std_msgs", "msg", "String").
|
||||
/// \param[in] full_type
|
||||
/// \throws std::runtime_error if the input full type string is malformed or does not follow the
|
||||
/// expected format.
|
||||
/// \return A tuple containing the package name, middle module (if any), and type name.
|
||||
RCLCPP_PUBLIC
|
||||
std::tuple<std::string, std::string, std::string>
|
||||
extract_type_identifier(const std::string & full_type);
|
||||
|
||||
/// \brief Look for the library in the ament prefix paths and return the path to the type support
|
||||
/// library.
|
||||
/// \param[in] package_name The name of the package containing the type support library,
|
||||
/// e.g. "std_msgs".
|
||||
/// \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
|
||||
/// \throws std::runtime_error if the library is not found.
|
||||
/// \return The path to the type support library.
|
||||
RCLCPP_PUBLIC
|
||||
std::string get_typesupport_library_path(
|
||||
const std::string & package_name, const std::string & typesupport_identifier);
|
||||
|
||||
/// \brief Load the type support library for the given type.
|
||||
/// \param[in] type The topic type, e.g. "std_msgs/msg/String"
|
||||
/// \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
|
||||
/// \throws std::runtime_error if the library is not found or cannot be loaded.
|
||||
/// \return A shared library
|
||||
/// Load the type support library for the given type.
|
||||
/**
|
||||
* \param[in] type The topic type, e.g. "std_msgs/msg/String"
|
||||
* \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
|
||||
* \return A shared library
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_ptr<rcpputils::SharedLibrary>
|
||||
get_typesupport_library(const std::string & type, const std::string & typesupport_identifier);
|
||||
|
||||
/// \brief Extracts the message type support handle from the library.
|
||||
/// \note The library needs to match the topic type. The shared library must stay loaded for the
|
||||
/// lifetime of the result.
|
||||
/// \param[in] type The topic type, e.g. "std_msgs/msg/String"
|
||||
/// \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
|
||||
/// \param[in] library The shared type support library
|
||||
/// \throws std::runtime_error if the symbol of type not found in the library.
|
||||
/// \return A message type support handle
|
||||
/// Extract the message type support handle from the library.
|
||||
/**
|
||||
* The library needs to match the topic type. The shared library must stay loaded for the lifetime of the result.
|
||||
*
|
||||
* \param[in] type The topic type, e.g. "std_msgs/msg/String"
|
||||
* \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
|
||||
* \param[in] library The shared type support library
|
||||
* \throws std::runtime_error if the symbol of type not found in the library.
|
||||
* \return A message type support handle
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_message_type_support_t *
|
||||
get_message_typesupport_handle(
|
||||
@@ -78,14 +56,16 @@ get_message_typesupport_handle(
|
||||
const std::string & typesupport_identifier,
|
||||
rcpputils::SharedLibrary & library);
|
||||
|
||||
/// \brief Extracts the service type support handle from the library.
|
||||
/// \note The library needs to match the service type. The shared library must stay loaded for the
|
||||
/// lifetime of the result.
|
||||
/// \param[in] type The service type, e.g. "std_srvs/srv/Empty"
|
||||
/// \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
|
||||
/// \param[in] library The shared type support library
|
||||
/// \throws std::runtime_error if the symbol of type not found in the library.
|
||||
/// \return A service type support handle
|
||||
/// Extract the service type support handle from the library.
|
||||
/**
|
||||
* The library needs to match the service type. The shared library must stay loaded for the lifetime of the result.
|
||||
*
|
||||
* \param[in] type The service type, e.g. "std_srvs/srv/Empty"
|
||||
* \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
|
||||
* \param[in] library The shared type support library
|
||||
* \throws std::runtime_error if the symbol of type not found in the library.
|
||||
* \return A service type support handle
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_service_type_support_t *
|
||||
get_service_typesupport_handle(
|
||||
@@ -93,14 +73,17 @@ get_service_typesupport_handle(
|
||||
const std::string & typesupport_identifier,
|
||||
rcpputils::SharedLibrary & library);
|
||||
|
||||
/// \brief Extracts the action type support handle from the library.
|
||||
/// \note The library needs to match the action type. The shared library must stay loaded for the
|
||||
/// lifetime of the result.
|
||||
/// \param[in] type The action type, e.g. "example_interfaces/action/Fibonacci"
|
||||
/// \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
|
||||
/// \param[in] library The shared type support library
|
||||
/// \throws std::runtime_error if the symbol of type not found in the library.
|
||||
/// \return A action type support handle
|
||||
/// Extract the action type support handle from the library.
|
||||
/**
|
||||
* The library needs to match the action type. The shared library must stay loaded for the lifetime
|
||||
* of the result.
|
||||
*
|
||||
* \param[in] type The action type, e.g. "example_interfaces/action/Fibonacci"
|
||||
* \param[in] typesupport_identifier Type support identifier, typically "rosidl_typesupport_cpp"
|
||||
* \param[in] library The shared type support library
|
||||
* \throws std::runtime_error if the symbol of type not found in the library.
|
||||
* \return A action type support handle
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_action_type_support_t *
|
||||
get_action_typesupport_handle(
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#ifndef RCLCPP__WAIT_FOR_MESSAGE_HPP_
|
||||
#define RCLCPP__WAIT_FOR_MESSAGE_HPP_
|
||||
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -24,7 +23,6 @@
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rclcpp/wait_set.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
@@ -56,7 +54,7 @@ bool wait_for_message(
|
||||
}
|
||||
});
|
||||
|
||||
rclcpp::WaitSet wait_set({}, {}, {}, {}, {}, {}, context);
|
||||
rclcpp::WaitSet wait_set;
|
||||
wait_set.add_subscription(subscription);
|
||||
RCPPUTILS_SCOPE_EXIT(wait_set.remove_subscription(subscription); );
|
||||
wait_set.add_guard_condition(gc);
|
||||
@@ -81,11 +79,10 @@ bool wait_for_message(
|
||||
/**
|
||||
* Wait for the next incoming message to arrive on a specified topic before the specified timeout.
|
||||
*
|
||||
* \param[out] out is the message to be filled when a new message is arriving
|
||||
* \param[out] out is the message to be filled when a new message is arriving.
|
||||
* \param[in] node the node pointer to initialize the subscription on.
|
||||
* \param[in] topic the topic to wait for messages.
|
||||
* \param[in] time_to_wait parameter specifying the timeout before returning.
|
||||
* \param[in] qos parameter specifying QoS settings for the subscription.
|
||||
* \return true if a message was successfully received, false if message could not
|
||||
* be obtained or shutdown was triggered asynchronously on the context.
|
||||
*/
|
||||
@@ -94,10 +91,9 @@ bool wait_for_message(
|
||||
MsgT & out,
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const std::string & topic,
|
||||
std::chrono::duration<Rep, Period> time_to_wait = std::chrono::duration<Rep, Period>(-1),
|
||||
const rclcpp::QoS & qos = rclcpp::SystemDefaultsQoS())
|
||||
std::chrono::duration<Rep, Period> time_to_wait = std::chrono::duration<Rep, Period>(-1))
|
||||
{
|
||||
auto sub = node->create_subscription<MsgT>(topic, qos, [](const std::shared_ptr<const MsgT>) {});
|
||||
auto sub = node->create_subscription<MsgT>(topic, 1, [](const std::shared_ptr<const MsgT>) {});
|
||||
return wait_for_message<MsgT, Rep, Period>(
|
||||
out, sub, node->get_node_options().context(), time_to_wait);
|
||||
}
|
||||
|
||||
@@ -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>29.5.7</version>
|
||||
<version>29.6.0</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -124,7 +124,8 @@ def get_rclcpp_suffix_from_features(features):
|
||||
) \
|
||||
do { \
|
||||
static_assert( \
|
||||
::std::is_convertible_v<decltype(logger), ::rclcpp::Logger>, \
|
||||
::std::is_same<typename std::remove_cv_t<typename std::remove_reference_t<decltype(logger)>>, \
|
||||
typename ::rclcpp::Logger>::value, \
|
||||
"First argument to logging macros must be an rclcpp::Logger"); \
|
||||
@[ if 'throttle' in feature_combination]@ \
|
||||
auto get_time_point = [&c=clock](rcutils_time_point_value_t * time_point) -> rcutils_ret_t { \
|
||||
|
||||
@@ -83,16 +83,6 @@ Clock::now() const
|
||||
return now;
|
||||
}
|
||||
|
||||
void
|
||||
Clock::cancel_sleep_or_wait()
|
||||
{
|
||||
{
|
||||
std::unique_lock lock(impl_->wait_mutex_);
|
||||
impl_->stop_sleeping_ = true;
|
||||
}
|
||||
impl_->cv_.notify_one();
|
||||
}
|
||||
|
||||
bool
|
||||
Clock::sleep_until(
|
||||
Time until,
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "rclcpp/context.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
@@ -143,52 +142,11 @@ rclcpp_logging_output_handler(
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
/**
|
||||
* Global storage for pre and post shutdown recursive mutexes.
|
||||
* Note, this is a ABI compatibility hack.
|
||||
*/
|
||||
class MutexLookup
|
||||
{
|
||||
std::mutex m;
|
||||
|
||||
struct MutexHolder
|
||||
{
|
||||
std::recursive_mutex on_shutdown_callbacks_mutex_;
|
||||
std::recursive_mutex pre_shutdown_callbacks_mutex_;
|
||||
};
|
||||
|
||||
std::map<const Context *, std::unique_ptr<MutexHolder>> mutexMap;
|
||||
|
||||
public:
|
||||
MutexHolder & getMutexes(const Context *forContext)
|
||||
{
|
||||
auto it = mutexMap.find(forContext);
|
||||
if(it == mutexMap.end()) {
|
||||
it = mutexMap.emplace(forContext, std::make_unique<MutexHolder>()).first;
|
||||
}
|
||||
|
||||
return *(it->second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only supposed to be called on deletion of context
|
||||
*/
|
||||
void removeMutexes(const Context *forContext)
|
||||
{
|
||||
mutexMap.erase(forContext);
|
||||
}
|
||||
};
|
||||
|
||||
MutexLookup mutexStorage;
|
||||
|
||||
Context::Context()
|
||||
: rcl_context_(nullptr),
|
||||
shutdown_reason_(""),
|
||||
logging_mutex_(nullptr)
|
||||
{
|
||||
// allocate mutexes
|
||||
mutexStorage.getMutexes(this);
|
||||
}
|
||||
{}
|
||||
|
||||
Context::~Context()
|
||||
{
|
||||
@@ -207,9 +165,6 @@ Context::~Context()
|
||||
} catch (...) {
|
||||
RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "unhandled exception in ~Context()");
|
||||
}
|
||||
|
||||
// delete mutexes
|
||||
mutexStorage.removeMutexes(this);
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
@@ -355,17 +310,9 @@ Context::shutdown(const std::string & reason)
|
||||
|
||||
// call each pre-shutdown callback
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock{mutexStorage.getMutexes(
|
||||
this).pre_shutdown_callbacks_mutex_};
|
||||
// callbacks may delete other callbacks during the execution,
|
||||
// therefore we need to save a copy and check before execution
|
||||
// if the next callback is still present
|
||||
auto cpy = pre_shutdown_callbacks_;
|
||||
for (const auto & callback : cpy) {
|
||||
auto it = std::find(pre_shutdown_callbacks_.begin(), pre_shutdown_callbacks_.end(), callback);
|
||||
if(it != pre_shutdown_callbacks_.end()) {
|
||||
(*callback)();
|
||||
}
|
||||
std::lock_guard<std::mutex> lock{pre_shutdown_callbacks_mutex_};
|
||||
for (const auto & callback : pre_shutdown_callbacks_) {
|
||||
(*callback)();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,17 +325,9 @@ Context::shutdown(const std::string & reason)
|
||||
shutdown_reason_ = reason;
|
||||
// call each shutdown callback
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutexStorage.getMutexes(
|
||||
this).on_shutdown_callbacks_mutex_);
|
||||
// callbacks may delete other callbacks during the execution,
|
||||
// therefore we need to save a copy and check before execution
|
||||
// if the next callback is still present
|
||||
auto cpy = on_shutdown_callbacks_;
|
||||
for (const auto & callback : cpy) {
|
||||
auto it = std::find(on_shutdown_callbacks_.begin(), on_shutdown_callbacks_.end(), callback);
|
||||
if(it != on_shutdown_callbacks_.end()) {
|
||||
(*callback)();
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(on_shutdown_callbacks_mutex_);
|
||||
for (const auto & callback : on_shutdown_callbacks_) {
|
||||
(*callback)();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,12 +398,10 @@ Context::add_shutdown_callback(
|
||||
shutdown_type == ShutdownType::pre_shutdown || shutdown_type == ShutdownType::on_shutdown);
|
||||
|
||||
if constexpr (shutdown_type == ShutdownType::pre_shutdown) {
|
||||
std::lock_guard<std::recursive_mutex> lock(mutexStorage.getMutexes(
|
||||
this).pre_shutdown_callbacks_mutex_);
|
||||
std::lock_guard<std::mutex> lock(pre_shutdown_callbacks_mutex_);
|
||||
pre_shutdown_callbacks_.emplace_back(callback_shared_ptr);
|
||||
} else {
|
||||
std::lock_guard<std::recursive_mutex> lock(mutexStorage.getMutexes(
|
||||
this).on_shutdown_callbacks_mutex_);
|
||||
std::lock_guard<std::mutex> lock(on_shutdown_callbacks_mutex_);
|
||||
on_shutdown_callbacks_.emplace_back(callback_shared_ptr);
|
||||
}
|
||||
|
||||
@@ -484,7 +421,7 @@ Context::remove_shutdown_callback(
|
||||
}
|
||||
|
||||
const auto remove_callback = [&callback_shared_ptr](auto & mutex, auto & callback_vector) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
const std::lock_guard<std::mutex> lock(mutex);
|
||||
auto iter = callback_vector.begin();
|
||||
for (; iter != callback_vector.end(); iter++) {
|
||||
if ((*iter).get() == callback_shared_ptr.get()) {
|
||||
@@ -495,7 +432,6 @@ Context::remove_shutdown_callback(
|
||||
return false;
|
||||
}
|
||||
callback_vector.erase(iter);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -503,11 +439,9 @@ Context::remove_shutdown_callback(
|
||||
shutdown_type == ShutdownType::pre_shutdown || shutdown_type == ShutdownType::on_shutdown);
|
||||
|
||||
if constexpr (shutdown_type == ShutdownType::pre_shutdown) {
|
||||
return remove_callback(mutexStorage.getMutexes(this).pre_shutdown_callbacks_mutex_,
|
||||
pre_shutdown_callbacks_);
|
||||
return remove_callback(pre_shutdown_callbacks_mutex_, pre_shutdown_callbacks_);
|
||||
} else {
|
||||
return remove_callback(mutexStorage.getMutexes(this).on_shutdown_callbacks_mutex_,
|
||||
on_shutdown_callbacks_);
|
||||
return remove_callback(on_shutdown_callbacks_mutex_, on_shutdown_callbacks_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,7 +462,7 @@ std::vector<rclcpp::Context::ShutdownCallback>
|
||||
Context::get_shutdown_callback() const
|
||||
{
|
||||
const auto get_callback_vector = [](auto & mutex, auto & callback_set) {
|
||||
const std::lock_guard<std::recursive_mutex> lock(mutex);
|
||||
const std::lock_guard<std::mutex> lock(mutex);
|
||||
std::vector<rclcpp::Context::ShutdownCallback> callbacks;
|
||||
for (auto & callback : callback_set) {
|
||||
callbacks.push_back(*callback);
|
||||
@@ -540,11 +474,9 @@ Context::get_shutdown_callback() const
|
||||
shutdown_type == ShutdownType::pre_shutdown || shutdown_type == ShutdownType::on_shutdown);
|
||||
|
||||
if constexpr (shutdown_type == ShutdownType::pre_shutdown) {
|
||||
return get_callback_vector(mutexStorage.getMutexes(this).pre_shutdown_callbacks_mutex_,
|
||||
pre_shutdown_callbacks_);
|
||||
return get_callback_vector(pre_shutdown_callbacks_mutex_, pre_shutdown_callbacks_);
|
||||
} else {
|
||||
return get_callback_vector(mutexStorage.getMutexes(this).on_shutdown_callbacks_mutex_,
|
||||
on_shutdown_callbacks_);
|
||||
return get_callback_vector(on_shutdown_callbacks_mutex_, on_shutdown_callbacks_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,34 +55,6 @@ get_node_logger(const rcl_node_t * node)
|
||||
return rclcpp::get_logger(logger_name);
|
||||
}
|
||||
|
||||
// TODO(ahcorde): Remove deprecated class on the next release (in Rolling after Kilted).
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
rcpputils::fs::path
|
||||
get_logging_directory()
|
||||
{
|
||||
char * log_dir = NULL;
|
||||
auto allocator = rcutils_get_default_allocator();
|
||||
rcl_logging_ret_t ret = rcl_logging_get_logging_directory(allocator, &log_dir);
|
||||
if (RCL_LOGGING_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
std::string path{log_dir};
|
||||
allocator.deallocate(log_dir, allocator.state);
|
||||
return path;
|
||||
}
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
std::filesystem::path
|
||||
get_log_directory()
|
||||
{
|
||||
|
||||
@@ -192,6 +192,65 @@ format_range_reason(const std::string & name, const char * range_type)
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
__check_integer_range(
|
||||
const rcl_interfaces::msg::ParameterDescriptor & descriptor,
|
||||
const int64_t value)
|
||||
{
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
auto integer_range = descriptor.integer_range.at(0);
|
||||
if (value == integer_range.from_value || value == integer_range.to_value) {
|
||||
return result;
|
||||
}
|
||||
if ((value < integer_range.from_value) || (value > integer_range.to_value)) {
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "integer");
|
||||
return result;
|
||||
}
|
||||
if (integer_range.step == 0) {
|
||||
return result;
|
||||
}
|
||||
if (((value - integer_range.from_value) % integer_range.step) == 0) {
|
||||
return result;
|
||||
}
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "integer");
|
||||
return result;
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
__check_double_range(
|
||||
const rcl_interfaces::msg::ParameterDescriptor & descriptor,
|
||||
const double value)
|
||||
{
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
auto fp_range = descriptor.floating_point_range.at(0);
|
||||
if (__are_doubles_equal(value, fp_range.from_value) || __are_doubles_equal(value,
|
||||
fp_range.to_value))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if ((value < fp_range.from_value) || (value > fp_range.to_value)) {
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "floating point");
|
||||
return result;
|
||||
}
|
||||
if (fp_range.step == 0.0) {
|
||||
return result;
|
||||
}
|
||||
double rounded_div = std::round((value - fp_range.from_value) / fp_range.step);
|
||||
if (__are_doubles_equal(value, fp_range.from_value + rounded_div * fp_range.step)) {
|
||||
return result;
|
||||
}
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "floating point");
|
||||
return result;
|
||||
}
|
||||
|
||||
RCLCPP_LOCAL
|
||||
rcl_interfaces::msg::SetParametersResult
|
||||
__check_parameter_value_in_range(
|
||||
@@ -201,49 +260,39 @@ __check_parameter_value_in_range(
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
if (!descriptor.integer_range.empty() && value.get_type() == rclcpp::PARAMETER_INTEGER) {
|
||||
int64_t v = value.get<int64_t>();
|
||||
auto integer_range = descriptor.integer_range.at(0);
|
||||
if (v == integer_range.from_value || v == integer_range.to_value) {
|
||||
return result;
|
||||
result = __check_integer_range(descriptor, value.get<int64_t>());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!descriptor.integer_range.empty() && value.get_type() == rclcpp::PARAMETER_INTEGER_ARRAY) {
|
||||
std::vector<int64_t> val_array = value.get<std::vector<int64_t>>();
|
||||
for (const int64_t & val : val_array) {
|
||||
result = __check_integer_range(descriptor, val);
|
||||
if (!result.successful) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if ((v < integer_range.from_value) || (v > integer_range.to_value)) {
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "integer");
|
||||
return result;
|
||||
}
|
||||
if (integer_range.step == 0) {
|
||||
return result;
|
||||
}
|
||||
if (((v - integer_range.from_value) % integer_range.step) == 0) {
|
||||
return result;
|
||||
}
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "integer");
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!descriptor.floating_point_range.empty() && value.get_type() == rclcpp::PARAMETER_DOUBLE) {
|
||||
double v = value.get<double>();
|
||||
auto fp_range = descriptor.floating_point_range.at(0);
|
||||
if (__are_doubles_equal(v, fp_range.from_value) || __are_doubles_equal(v, fp_range.to_value)) {
|
||||
return result;
|
||||
}
|
||||
if ((v < fp_range.from_value) || (v > fp_range.to_value)) {
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "floating point");
|
||||
return result;
|
||||
}
|
||||
if (fp_range.step == 0.0) {
|
||||
return result;
|
||||
}
|
||||
double rounded_div = std::round((v - fp_range.from_value) / fp_range.step);
|
||||
if (__are_doubles_equal(v, fp_range.from_value + rounded_div * fp_range.step)) {
|
||||
return result;
|
||||
}
|
||||
result.successful = false;
|
||||
result.reason = format_range_reason(descriptor.name, "floating point");
|
||||
result = __check_double_range(descriptor, value.get<double>());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!descriptor.floating_point_range.empty() &&
|
||||
value.get_type() == rclcpp::PARAMETER_DOUBLE_ARRAY)
|
||||
{
|
||||
std::vector<double> val_array = value.get<std::vector<double>>();
|
||||
for (const double & val : val_array) {
|
||||
result = __check_double_range(descriptor, val);
|
||||
if (!result.successful) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,11 +65,11 @@ public:
|
||||
: logger_(node_logging->get_logger()),
|
||||
node_base_(node_base)
|
||||
{
|
||||
rclcpp::ParameterValue enable_param;
|
||||
const std::string enable_param_name = "start_type_description_service";
|
||||
|
||||
if (!node_parameters->has_parameter(enable_param_name)) {
|
||||
enable_param = node_parameters->declare_parameter(
|
||||
bool enabled = false;
|
||||
try {
|
||||
auto enable_param = node_parameters->declare_parameter(
|
||||
enable_param_name,
|
||||
rclcpp::ParameterValue(true),
|
||||
rcl_interfaces::msg::ParameterDescriptor()
|
||||
@@ -77,21 +77,13 @@ public:
|
||||
.set__type(rclcpp::PARAMETER_BOOL)
|
||||
.set__description("Start the ~/get_type_description service for this node.")
|
||||
.set__read_only(true));
|
||||
} else {
|
||||
enable_param = node_parameters->get_parameter(enable_param_name).get_parameter_value();
|
||||
}
|
||||
if (enable_param.get_type() != rclcpp::PARAMETER_BOOL) {
|
||||
RCLCPP_ERROR(
|
||||
logger_,
|
||||
"Invalid type '%s' for parameter 'start_type_description_service', should be 'bool'",
|
||||
rclcpp::to_string(enable_param.get_type()).c_str());
|
||||
std::ostringstream ss;
|
||||
ss << "Wrong parameter type, parameter {" << enable_param_name << "} is of type {bool}, "
|
||||
<< "setting it to {" << to_string(enable_param.get_type()) << "} is not allowed.";
|
||||
throw rclcpp::exceptions::InvalidParameterTypeException(enable_param_name, ss.str());
|
||||
enabled = enable_param.get<bool>();
|
||||
} catch (const rclcpp::exceptions::InvalidParameterTypeException & exc) {
|
||||
RCLCPP_ERROR(logger_, "%s", exc.what());
|
||||
throw;
|
||||
}
|
||||
|
||||
if (enable_param.get<bool>()) {
|
||||
if (enabled) {
|
||||
auto * rcl_node = node_base->get_rcl_node_handle();
|
||||
std::shared_ptr<rcl_service_t> rcl_srv(
|
||||
new rcl_service_t,
|
||||
|
||||
@@ -81,15 +81,7 @@ rclcpp::parameter_map_from(const rcl_params_t * const c_params, const char * nod
|
||||
throw InvalidParametersException(message);
|
||||
}
|
||||
const rcl_variant_t * const c_param_value = &(c_params_node->parameter_values[p]);
|
||||
ParameterValue value;
|
||||
try {
|
||||
value = parameter_value_from(c_param_value);
|
||||
} catch (const InvalidParameterValueException & e) {
|
||||
throw InvalidParameterValueException(
|
||||
std::string("parameter_value_from failed for parameter '") +
|
||||
c_param_name + "': " + e.what());
|
||||
}
|
||||
params_node.emplace_back(c_param_name, value);
|
||||
params_node.emplace_back(c_param_name, parameter_value_from(c_param_value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,9 +47,9 @@ ParameterService::ParameterService(
|
||||
response->values.push_back(param.get_value_message());
|
||||
}
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to get parameters: %s", ex.what());
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp"), "Failed to get parameters: %s", ex.what());
|
||||
} catch (const rclcpp::exceptions::ParameterUninitializedException & ex) {
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to get parameters: %s", ex.what());
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp"), "Failed to get parameters: %s", ex.what());
|
||||
}
|
||||
},
|
||||
qos_profile, nullptr);
|
||||
@@ -70,7 +70,7 @@ ParameterService::ParameterService(
|
||||
return static_cast<rclcpp::ParameterType>(type);
|
||||
});
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to get parameter types: %s", ex.what());
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp"), "Failed to get parameter types: %s", ex.what());
|
||||
}
|
||||
},
|
||||
qos_profile, nullptr);
|
||||
@@ -91,7 +91,7 @@ ParameterService::ParameterService(
|
||||
result = node_params->set_parameters_atomically(
|
||||
{rclcpp::Parameter::from_parameter_msg(p)});
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to set parameter: %s", ex.what());
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp"), "Failed to set parameter: %s", ex.what());
|
||||
result.successful = false;
|
||||
result.reason = ex.what();
|
||||
}
|
||||
@@ -119,7 +119,7 @@ ParameterService::ParameterService(
|
||||
auto result = node_params->set_parameters_atomically(pvariants);
|
||||
response->result = result;
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_WARN(
|
||||
RCLCPP_DEBUG(
|
||||
rclcpp::get_logger("rclcpp"), "Failed to set parameters atomically: %s", ex.what());
|
||||
response->result.successful = false;
|
||||
response->result.reason = "One or more parameters were not declared before setting";
|
||||
@@ -139,7 +139,7 @@ ParameterService::ParameterService(
|
||||
auto descriptors = node_params->describe_parameters(request->names);
|
||||
response->descriptors = descriptors;
|
||||
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
|
||||
RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "Failed to describe parameters: %s", ex.what());
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp"), "Failed to describe parameters: %s", ex.what());
|
||||
}
|
||||
},
|
||||
qos_profile, nullptr);
|
||||
|
||||
@@ -69,10 +69,8 @@ QoSInitialization::from_rmw(const rmw_qos_profile_t & rmw_qos)
|
||||
return KeepLast(rmw_qos.depth, false);
|
||||
case RMW_QOS_POLICY_HISTORY_KEEP_LAST:
|
||||
case RMW_QOS_POLICY_HISTORY_UNKNOWN:
|
||||
return KeepLast(rmw_qos.depth);
|
||||
default:
|
||||
throw std::invalid_argument(
|
||||
"Invalid history policy enum value passed to QoSInitialization::from_rmw");
|
||||
return KeepLast(rmw_qos.depth);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,13 +26,8 @@ namespace rclcpp
|
||||
|
||||
inline void copy_rcl_message(const rcl_serialized_message_t & from, rcl_serialized_message_t & to)
|
||||
{
|
||||
auto ret = RCL_RET_ERROR;
|
||||
if (nullptr == to.buffer) {
|
||||
ret = rmw_serialized_message_init(&to, from.buffer_capacity, &from.allocator);
|
||||
} else {
|
||||
ret = rmw_serialized_message_resize(&to, from.buffer_capacity);
|
||||
}
|
||||
|
||||
const auto ret = rmw_serialized_message_init(
|
||||
&to, from.buffer_capacity, &from.allocator);
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
@@ -83,6 +78,7 @@ SerializedMessage::SerializedMessage(rcl_serialized_message_t && other)
|
||||
SerializedMessage & SerializedMessage::operator=(const SerializedMessage & other)
|
||||
{
|
||||
if (this != &other) {
|
||||
serialized_message_ = rmw_get_zero_initialized_serialized_message();
|
||||
copy_rcl_message(other.serialized_message_, serialized_message_);
|
||||
}
|
||||
|
||||
@@ -92,6 +88,7 @@ SerializedMessage & SerializedMessage::operator=(const SerializedMessage & other
|
||||
SerializedMessage & SerializedMessage::operator=(const rcl_serialized_message_t & other)
|
||||
{
|
||||
if (&serialized_message_ != &other) {
|
||||
serialized_message_ = rmw_get_zero_initialized_serialized_message();
|
||||
copy_rcl_message(other, serialized_message_);
|
||||
}
|
||||
|
||||
@@ -101,14 +98,6 @@ SerializedMessage & SerializedMessage::operator=(const rcl_serialized_message_t
|
||||
SerializedMessage & SerializedMessage::operator=(SerializedMessage && other)
|
||||
{
|
||||
if (this != &other) {
|
||||
if (nullptr != serialized_message_.buffer) {
|
||||
const auto fini_ret = rmw_serialized_message_fini(&serialized_message_);
|
||||
if (RCL_RET_OK != fini_ret) {
|
||||
RCLCPP_ERROR(
|
||||
get_logger("rclcpp"),
|
||||
"Failed to destroy serialized message: %s", rcl_get_error_string().str);
|
||||
}
|
||||
}
|
||||
serialized_message_ =
|
||||
std::exchange(other.serialized_message_, rmw_get_zero_initialized_serialized_message());
|
||||
}
|
||||
@@ -119,14 +108,6 @@ SerializedMessage & SerializedMessage::operator=(SerializedMessage && other)
|
||||
SerializedMessage & SerializedMessage::operator=(rcl_serialized_message_t && other)
|
||||
{
|
||||
if (&serialized_message_ != &other) {
|
||||
if (nullptr != serialized_message_.buffer) {
|
||||
const auto fini_ret = rmw_serialized_message_fini(&serialized_message_);
|
||||
if (RCL_RET_OK != fini_ret) {
|
||||
RCLCPP_ERROR(
|
||||
get_logger("rclcpp"),
|
||||
"Failed to destroy serialized message: %s", rcl_get_error_string().str);
|
||||
}
|
||||
}
|
||||
serialized_message_ =
|
||||
std::exchange(other, rmw_get_zero_initialized_serialized_message());
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ void
|
||||
SignalHandler::signal_handler(
|
||||
int signum, siginfo_t * siginfo, void * context)
|
||||
{
|
||||
RCLCPP_INFO(SignalHandler::get_logger(), "signal_handler(signum=%d)", signum);
|
||||
auto & instance = SignalHandler::get_global_signal_handler();
|
||||
|
||||
auto old_signal_handler = instance.get_old_signal_handler(signum);
|
||||
@@ -90,6 +91,7 @@ SignalHandler::signal_handler(
|
||||
void
|
||||
SignalHandler::signal_handler(int signum)
|
||||
{
|
||||
RCLCPP_INFO(SignalHandler::get_logger(), "signal_handler(signum=%d)", signum);
|
||||
auto & instance = SignalHandler::get_global_signal_handler();
|
||||
auto old_signal_handler = instance.get_old_signal_handler(signum);
|
||||
if (
|
||||
@@ -247,6 +249,9 @@ SignalHandler::signal_handler_common()
|
||||
{
|
||||
auto & instance = SignalHandler::get_global_signal_handler();
|
||||
instance.signal_received_.store(true);
|
||||
RCLCPP_DEBUG(
|
||||
get_logger(),
|
||||
"signal_handler(): notifying deferred signal handler");
|
||||
instance.notify_signal_handler();
|
||||
}
|
||||
|
||||
@@ -255,7 +260,6 @@ SignalHandler::deferred_signal_handler()
|
||||
{
|
||||
while (true) {
|
||||
if (signal_received_.exchange(false)) {
|
||||
RCLCPP_INFO(SignalHandler::get_logger(), "signal_handler(SIGINT/SIGTERM)");
|
||||
RCLCPP_DEBUG(get_logger(), "deferred_signal_handler(): shutting down");
|
||||
for (auto context_ptr : rclcpp::get_contexts()) {
|
||||
if (context_ptr->get_init_options().shutdown_on_signal) {
|
||||
|
||||
@@ -35,6 +35,62 @@ namespace rclcpp
|
||||
namespace
|
||||
{
|
||||
|
||||
// Look for the library in the ament prefix paths.
|
||||
std::string get_typesupport_library_path(
|
||||
const std::string & package_name, const std::string & typesupport_identifier)
|
||||
{
|
||||
const char * dynamic_library_folder;
|
||||
#ifdef _WIN32
|
||||
dynamic_library_folder = "/bin/";
|
||||
#elif __APPLE__
|
||||
dynamic_library_folder = "/lib/";
|
||||
#else
|
||||
dynamic_library_folder = "/lib/";
|
||||
#endif
|
||||
|
||||
std::string package_prefix;
|
||||
try {
|
||||
package_prefix = ament_index_cpp::get_package_prefix(package_name);
|
||||
} catch (ament_index_cpp::PackageNotFoundError & e) {
|
||||
throw std::runtime_error(e.what());
|
||||
}
|
||||
|
||||
const std::string library_path = rcpputils::path_for_library(
|
||||
package_prefix + dynamic_library_folder,
|
||||
package_name + "__" + typesupport_identifier);
|
||||
if (library_path.empty()) {
|
||||
throw std::runtime_error(
|
||||
"Typesupport library for " + package_name + " does not exist in '" + package_prefix +
|
||||
"'.");
|
||||
}
|
||||
return library_path;
|
||||
}
|
||||
|
||||
std::tuple<std::string, std::string, std::string>
|
||||
extract_type_identifier(const std::string & full_type)
|
||||
{
|
||||
char type_separator = '/';
|
||||
auto sep_position_back = full_type.find_last_of(type_separator);
|
||||
auto sep_position_front = full_type.find_first_of(type_separator);
|
||||
if (sep_position_back == std::string::npos ||
|
||||
sep_position_back == 0 ||
|
||||
sep_position_back == full_type.length() - 1)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Message type is not of the form package/type and cannot be processed");
|
||||
}
|
||||
|
||||
std::string package_name = full_type.substr(0, sep_position_front);
|
||||
std::string middle_module = "";
|
||||
if (sep_position_back - sep_position_front > 0) {
|
||||
middle_module =
|
||||
full_type.substr(sep_position_front + 1, sep_position_back - sep_position_front - 1);
|
||||
}
|
||||
std::string type_name = full_type.substr(sep_position_back + 1);
|
||||
|
||||
return std::make_tuple(package_name, middle_module, type_name);
|
||||
}
|
||||
|
||||
const void * get_typesupport_handle_impl(
|
||||
const std::string & type,
|
||||
const std::string & typesupport_identifier,
|
||||
@@ -75,61 +131,6 @@ const void * get_typesupport_handle_impl(
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
std::tuple<std::string, std::string, std::string>
|
||||
extract_type_identifier(const std::string & full_type)
|
||||
{
|
||||
char type_separator = '/';
|
||||
auto sep_position_back = full_type.find_last_of(type_separator);
|
||||
auto sep_position_front = full_type.find_first_of(type_separator);
|
||||
if (sep_position_back == std::string::npos ||
|
||||
sep_position_back == 0 ||
|
||||
sep_position_back == full_type.length() - 1)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Message type is not of the form package/type and cannot be processed");
|
||||
}
|
||||
|
||||
std::string package_name = full_type.substr(0, sep_position_front);
|
||||
std::string middle_module = "";
|
||||
if (sep_position_back - sep_position_front > 0) {
|
||||
middle_module =
|
||||
full_type.substr(sep_position_front + 1, sep_position_back - sep_position_front - 1);
|
||||
}
|
||||
std::string type_name = full_type.substr(sep_position_back + 1);
|
||||
|
||||
return std::make_tuple(package_name, middle_module, type_name);
|
||||
}
|
||||
|
||||
std::string get_typesupport_library_path(
|
||||
const std::string & package_name, const std::string & typesupport_identifier)
|
||||
{
|
||||
const char * dynamic_library_folder;
|
||||
#ifdef _WIN32
|
||||
dynamic_library_folder = "/bin/";
|
||||
#elif __APPLE__
|
||||
dynamic_library_folder = "/lib/";
|
||||
#else
|
||||
dynamic_library_folder = "/lib/";
|
||||
#endif
|
||||
|
||||
std::string package_prefix;
|
||||
try {
|
||||
package_prefix = ament_index_cpp::get_package_prefix(package_name);
|
||||
} catch (ament_index_cpp::PackageNotFoundError & e) {
|
||||
throw std::runtime_error(e.what());
|
||||
}
|
||||
|
||||
const std::string library_path = rcpputils::path_for_library(
|
||||
package_prefix + dynamic_library_folder,
|
||||
package_name + "__" + typesupport_identifier);
|
||||
if (library_path.empty()) {
|
||||
throw std::runtime_error(
|
||||
"Typesupport library for " + package_name + " does not exist in '" + package_prefix +
|
||||
"'.");
|
||||
}
|
||||
return library_path;
|
||||
}
|
||||
|
||||
std::shared_ptr<rcpputils::SharedLibrary>
|
||||
get_typesupport_library(const std::string & type, const std::string & typesupport_identifier)
|
||||
{
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@@ -57,11 +57,6 @@ ament_add_test_label(test_client mimick)
|
||||
if(TARGET test_client)
|
||||
target_link_libraries(test_client ${PROJECT_NAME} mimick ${rcl_interfaces_TARGETS} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_clock test_clock.cpp)
|
||||
ament_add_test_label(test_clock mimick)
|
||||
if(TARGET test_clock)
|
||||
target_link_libraries(test_clock ${PROJECT_NAME} mimick ${rcl_interfaces_TARGETS} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_clock_conditional test_clock_conditional.cpp)
|
||||
ament_add_test_label(test_clock_conditional mimick)
|
||||
if(TARGET test_clock_conditional)
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/experimental/executors/events_executor/events_executor_event_types.hpp"
|
||||
|
||||
@@ -0,0 +1,617 @@
|
||||
// Copyright 2020 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
#include "rcpputils/scope_exit.hpp"
|
||||
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
#include "test_msgs/srv/empty.hpp"
|
||||
|
||||
#include "../../mocking_utils/patch.hpp"
|
||||
#include "../../utils/rclcpp_gtest_macros.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct NumberOfEntities
|
||||
{
|
||||
size_t subscriptions = 0;
|
||||
size_t timers = 0;
|
||||
size_t services = 0;
|
||||
size_t clients = 0;
|
||||
size_t waitables = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<NumberOfEntities> get_number_of_default_entities(rclcpp::Node::SharedPtr node)
|
||||
{
|
||||
auto number_of_entities = std::make_unique<NumberOfEntities>();
|
||||
node->for_each_callback_group(
|
||||
[&number_of_entities](rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
if (!group->can_be_taken_from().load()) {
|
||||
return;
|
||||
}
|
||||
group->find_subscription_ptrs_if(
|
||||
[&number_of_entities](rclcpp::SubscriptionBase::SharedPtr &)
|
||||
{
|
||||
number_of_entities->subscriptions++; return false;
|
||||
});
|
||||
group->find_timer_ptrs_if(
|
||||
[&number_of_entities](rclcpp::TimerBase::SharedPtr &)
|
||||
{
|
||||
number_of_entities->timers++; return false;
|
||||
});
|
||||
group->find_service_ptrs_if(
|
||||
[&number_of_entities](rclcpp::ServiceBase::SharedPtr &)
|
||||
{
|
||||
number_of_entities->services++; return false;
|
||||
});
|
||||
group->find_client_ptrs_if(
|
||||
[&number_of_entities](rclcpp::ClientBase::SharedPtr &)
|
||||
{
|
||||
number_of_entities->clients++; return false;
|
||||
});
|
||||
group->find_waitable_ptrs_if(
|
||||
[&number_of_entities](rclcpp::Waitable::SharedPtr &)
|
||||
{
|
||||
number_of_entities->waitables++; return false;
|
||||
});
|
||||
});
|
||||
|
||||
return number_of_entities;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class TestStaticExecutorEntitiesCollector : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
entities_collector_ =
|
||||
std::make_shared<rclcpp::executors::StaticExecutorEntitiesCollector>();
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
rclcpp::executors::StaticExecutorEntitiesCollector::SharedPtr entities_collector_;
|
||||
};
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, construct_destruct) {
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_clients());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_waitables());
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_remove_node) {
|
||||
auto node1 = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
EXPECT_NO_THROW(entities_collector_->add_node(node1->get_node_base_interface()));
|
||||
|
||||
// Check adding second time
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->add_node(node1->get_node_base_interface()),
|
||||
std::runtime_error("Node has already been added to an executor."));
|
||||
|
||||
auto node2 = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
EXPECT_FALSE(entities_collector_->remove_node(node2->get_node_base_interface()));
|
||||
EXPECT_NO_THROW(entities_collector_->add_node(node2->get_node_base_interface()));
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node1->get_node_base_interface()));
|
||||
EXPECT_FALSE(entities_collector_->remove_node(node1->get_node_base_interface()));
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node2->get_node_base_interface()));
|
||||
|
||||
auto node3 = std::make_shared<rclcpp::Node>("node3", "ns");
|
||||
node3->get_node_base_interface()->get_associated_with_executor_atomic().exchange(true);
|
||||
EXPECT_FALSE(entities_collector_->remove_node(node3->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, init_bad_arguments) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
// Check memory strategy is nullptr
|
||||
rclcpp::memory_strategy::MemoryStrategy::SharedPtr memory_strategy = nullptr;
|
||||
EXPECT_THROW(
|
||||
entities_collector_->init(&wait_set, memory_strategy),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_remove_basic_node) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
const auto expected_number_of_entities = get_number_of_default_entities(node);
|
||||
EXPECT_NE(nullptr, expected_number_of_entities);
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
EXPECT_EQ(
|
||||
expected_number_of_entities->subscriptions,
|
||||
entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(expected_number_of_entities->timers, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(expected_number_of_entities->services, entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(expected_number_of_entities->clients, entities_collector_->get_number_of_clients());
|
||||
// One extra for the executor
|
||||
EXPECT_EQ(
|
||||
1u + expected_number_of_entities->waitables,
|
||||
entities_collector_->get_number_of_waitables());
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_clients());
|
||||
|
||||
// Still one for the executor
|
||||
EXPECT_EQ(1u, entities_collector_->get_number_of_waitables());
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_remove_node_out_of_scope) {
|
||||
rclcpp::Context::SharedPtr shared_context = nullptr;
|
||||
{
|
||||
auto node1 = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
auto node2 = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
auto node3 = std::make_shared<rclcpp::Node>("node3", "ns");
|
||||
entities_collector_->add_node(node1->get_node_base_interface());
|
||||
entities_collector_->add_node(node2->get_node_base_interface());
|
||||
entities_collector_->add_node(node3->get_node_base_interface());
|
||||
shared_context = node1->get_node_base_interface()->get_context();
|
||||
}
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
// Expect weak_node pointers to be cleaned up and used
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_clients());
|
||||
|
||||
// Still one for the executor
|
||||
EXPECT_EQ(1u, entities_collector_->get_number_of_waitables());
|
||||
}
|
||||
|
||||
class TestWaitable : public rclcpp::Waitable
|
||||
{
|
||||
public:
|
||||
void add_to_wait_set(rcl_wait_set_t &) override {}
|
||||
|
||||
bool is_ready(const rcl_wait_set_t &) override {return true;}
|
||||
|
||||
std::shared_ptr<void>
|
||||
take_data() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
void
|
||||
execute(const std::shared_ptr<void> &) override {}
|
||||
};
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_remove_node_with_entities) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
auto expected_number_of_entities = get_number_of_default_entities(node);
|
||||
EXPECT_NE(nullptr, expected_number_of_entities);
|
||||
|
||||
// Create 1 of each entity type
|
||||
auto subscription =
|
||||
node->create_subscription<test_msgs::msg::Empty>(
|
||||
"topic", rclcpp::QoS(10), [](test_msgs::msg::Empty::ConstSharedPtr) {});
|
||||
auto timer =
|
||||
node->create_wall_timer(std::chrono::seconds(60), []() {});
|
||||
auto service =
|
||||
node->create_service<test_msgs::srv::Empty>(
|
||||
"service",
|
||||
[](
|
||||
const test_msgs::srv::Empty::Request::SharedPtr,
|
||||
test_msgs::srv::Empty::Response::SharedPtr) {});
|
||||
auto client = node->create_client<test_msgs::srv::Empty>("service");
|
||||
auto waitable = std::make_shared<TestWaitable>();
|
||||
|
||||
// Adding a subscription could add another waitable, so we need to get the
|
||||
// current number of waitables just before adding the new waitable.
|
||||
expected_number_of_entities->waitables = get_number_of_default_entities(node)->waitables;
|
||||
node->get_node_waitables_interface()->add_waitable(waitable, nullptr);
|
||||
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
EXPECT_EQ(
|
||||
1u + expected_number_of_entities->subscriptions,
|
||||
entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(1u + expected_number_of_entities->timers, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(
|
||||
1u + expected_number_of_entities->services,
|
||||
entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(
|
||||
1u + expected_number_of_entities->clients,
|
||||
entities_collector_->get_number_of_clients());
|
||||
|
||||
// One extra for the executor
|
||||
EXPECT_EQ(
|
||||
2u + expected_number_of_entities->waitables,
|
||||
entities_collector_->get_number_of_waitables());
|
||||
|
||||
entities_collector_->remove_node(node->get_node_base_interface());
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_subscriptions());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_timers());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_services());
|
||||
EXPECT_EQ(0u, entities_collector_->get_number_of_clients());
|
||||
// Still one for the executor
|
||||
EXPECT_EQ(1u, entities_collector_->get_number_of_waitables());
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_callback_group) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 1u);
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_callback_group_after_add_node) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface()),
|
||||
std::runtime_error("Callback group has already been added to an executor."));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_callback_group_twice) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 1u);
|
||||
cb_group->get_associated_with_executor_atomic().exchange(false);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface()),
|
||||
std::runtime_error("Callback group was already added to executor."));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, prepare_wait_set_rcl_wait_set_clear_error) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_wait_set_clear, RCL_RET_ERROR);
|
||||
std::shared_ptr<void> data = entities_collector_->take_data();
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->execute(data),
|
||||
std::runtime_error("Couldn't clear wait set"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, prepare_wait_set_rcl_wait_set_resize_error) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_wait_set_resize, RCL_RET_ERROR);
|
||||
std::shared_ptr<void> data = entities_collector_->take_data();
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->execute(data),
|
||||
std::runtime_error("Couldn't resize the wait set: error not set"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, refresh_wait_set_not_initialized) {
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->refresh_wait_set(std::chrono::nanoseconds(1000)),
|
||||
std::runtime_error("Couldn't clear wait set"));
|
||||
rcl_reset_error();
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, refresh_wait_set_rcl_wait_failed) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_wait, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->refresh_wait_set(std::chrono::nanoseconds(1000)),
|
||||
std::runtime_error("rcl_wait() failed: error not set"));
|
||||
}
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, refresh_wait_set_add_handles_to_wait_set_failed) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
// Create 1 of each entity type
|
||||
auto subscription =
|
||||
node->create_subscription<test_msgs::msg::Empty>(
|
||||
"topic", rclcpp::QoS(10), [](test_msgs::msg::Empty::ConstSharedPtr) {});
|
||||
auto timer =
|
||||
node->create_wall_timer(std::chrono::seconds(60), []() {});
|
||||
auto service =
|
||||
node->create_service<test_msgs::srv::Empty>(
|
||||
"service",
|
||||
[](
|
||||
const test_msgs::srv::Empty::Request::SharedPtr,
|
||||
test_msgs::srv::Empty::Response::SharedPtr) {});
|
||||
auto client = node->create_client<test_msgs::srv::Empty>("service");
|
||||
auto waitable = std::make_shared<TestWaitable>();
|
||||
|
||||
node->get_node_waitables_interface()->add_waitable(waitable, nullptr);
|
||||
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return(
|
||||
"lib:rclcpp", rcl_wait_set_add_subscription,
|
||||
RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->refresh_wait_set(std::chrono::nanoseconds(1000)),
|
||||
std::runtime_error("Couldn't fill wait set"));
|
||||
}
|
||||
|
||||
entities_collector_->remove_node(node->get_node_base_interface());
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, add_to_wait_set_nullptr) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, fill_memory_strategy_invalid_group) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 2u);
|
||||
|
||||
cb_group.reset();
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 1u);
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, remove_callback_group_after_node) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 1u);
|
||||
|
||||
node.reset();
|
||||
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->remove_callback_group(cb_group),
|
||||
std::runtime_error("Node must not be deleted before its callback group(s)."));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, remove_callback_group_twice) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
ASSERT_EQ(entities_collector_->get_all_callback_groups().size(), 1u);
|
||||
|
||||
entities_collector_->remove_callback_group(cb_group);
|
||||
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
entities_collector_->remove_callback_group(cb_group),
|
||||
std::runtime_error("Callback group needs to be associated with executor."));
|
||||
}
|
||||
|
||||
TEST_F(TestStaticExecutorEntitiesCollector, remove_node_opposite_order) {
|
||||
auto node1 = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
EXPECT_NO_THROW(entities_collector_->add_node(node1->get_node_base_interface()));
|
||||
|
||||
auto node2 = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
EXPECT_NO_THROW(entities_collector_->add_node(node2->get_node_base_interface()));
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node2->get_node_base_interface()));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
TestStaticExecutorEntitiesCollector,
|
||||
add_callback_groups_from_nodes_associated_to_executor_add) {
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
rclcpp::CallbackGroup::SharedPtr cb_group = node->create_callback_group(
|
||||
rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
entities_collector_->add_callback_group(cb_group, node->get_node_base_interface());
|
||||
entities_collector_->add_node(node->get_node_base_interface());
|
||||
|
||||
rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set();
|
||||
rcl_allocator_t allocator = rcl_get_default_allocator();
|
||||
auto shared_context = node->get_node_base_interface()->get_context();
|
||||
rcl_context_t * context = shared_context->get_rcl_context().get();
|
||||
EXPECT_EQ(
|
||||
RCL_RET_OK,
|
||||
rcl_wait_set_init(&wait_set, 100, 100, 100, 100, 100, 100, context, allocator));
|
||||
RCPPUTILS_SCOPE_EXIT({EXPECT_EQ(RCL_RET_OK, rcl_wait_set_fini(&wait_set));});
|
||||
|
||||
auto memory_strategy = rclcpp::memory_strategies::create_default_strategy();
|
||||
rclcpp::GuardCondition guard_condition(shared_context);
|
||||
|
||||
entities_collector_->init(&wait_set, memory_strategy);
|
||||
RCPPUTILS_SCOPE_EXIT(entities_collector_->fini());
|
||||
|
||||
cb_group->get_associated_with_executor_atomic().exchange(false);
|
||||
std::shared_ptr<void> data = entities_collector_->take_data();
|
||||
entities_collector_->execute(data);
|
||||
|
||||
EXPECT_TRUE(entities_collector_->remove_node(node->get_node_base_interface()));
|
||||
}
|
||||
@@ -13,7 +13,6 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
@@ -192,7 +192,7 @@ TEST_F(TestNodeInterfaces, ni_init) {
|
||||
/*
|
||||
Testing macro'ed getters.
|
||||
*/
|
||||
TEST_F(TestNodeInterfaces, ni_all_init_non_const) {
|
||||
TEST_F(TestNodeInterfaces, ni_all_init) {
|
||||
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
|
||||
|
||||
using rclcpp::node_interfaces::NodeInterfaces;
|
||||
@@ -252,64 +252,3 @@ TEST_F(TestNodeInterfaces, ni_all_init_non_const) {
|
||||
time_source = ni.get_node_time_source_interface();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestNodeInterfaces, ni_all_init_const) {
|
||||
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
|
||||
|
||||
using rclcpp::node_interfaces::NodeInterfaces;
|
||||
using rclcpp::node_interfaces::NodeBaseInterface;
|
||||
using rclcpp::node_interfaces::NodeClockInterface;
|
||||
using rclcpp::node_interfaces::NodeGraphInterface;
|
||||
using rclcpp::node_interfaces::NodeLoggingInterface;
|
||||
using rclcpp::node_interfaces::NodeTimersInterface;
|
||||
using rclcpp::node_interfaces::NodeTopicsInterface;
|
||||
using rclcpp::node_interfaces::NodeServicesInterface;
|
||||
using rclcpp::node_interfaces::NodeWaitablesInterface;
|
||||
using rclcpp::node_interfaces::NodeParametersInterface;
|
||||
using rclcpp::node_interfaces::NodeTimeSourceInterface;
|
||||
|
||||
const auto ni = rclcpp::node_interfaces::NodeInterfaces<ALL_RCLCPP_NODE_INTERFACES>(*node);
|
||||
|
||||
{
|
||||
auto base = ni.get<NodeBaseInterface>();
|
||||
base = ni.get_node_base_interface();
|
||||
EXPECT_STREQ(base->get_name(), "my_node"); // Test for functionality
|
||||
}
|
||||
{
|
||||
auto clock = ni.get<NodeClockInterface>();
|
||||
clock = ni.get_node_clock_interface();
|
||||
clock->get_clock();
|
||||
}
|
||||
{
|
||||
auto graph = ni.get<NodeGraphInterface>();
|
||||
graph = ni.get_node_graph_interface();
|
||||
}
|
||||
{
|
||||
auto logging = ni.get<NodeLoggingInterface>();
|
||||
logging = ni.get_node_logging_interface();
|
||||
}
|
||||
{
|
||||
auto timers = ni.get<NodeTimersInterface>();
|
||||
timers = ni.get_node_timers_interface();
|
||||
}
|
||||
{
|
||||
auto topics = ni.get<NodeTopicsInterface>();
|
||||
topics = ni.get_node_topics_interface();
|
||||
}
|
||||
{
|
||||
auto services = ni.get<NodeServicesInterface>();
|
||||
services = ni.get_node_services_interface();
|
||||
}
|
||||
{
|
||||
auto waitables = ni.get<NodeWaitablesInterface>();
|
||||
waitables = ni.get_node_waitables_interface();
|
||||
}
|
||||
{
|
||||
auto parameters = ni.get<NodeParametersInterface>();
|
||||
parameters = ni.get_node_parameters_interface();
|
||||
}
|
||||
{
|
||||
auto time_source = ni.get<NodeTimeSourceInterface>();
|
||||
time_source = ni.get_node_time_source_interface();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ TEST_F(TestNodeParameters, list_parameters)
|
||||
list_result5.names.end());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, parameter_overrides_with_value)
|
||||
TEST_F(TestNodeParameters, parameter_overrides)
|
||||
{
|
||||
rclcpp::NodeOptions node_options;
|
||||
node_options.automatically_declare_parameters_from_overrides(true);
|
||||
@@ -146,24 +146,6 @@ TEST_F(TestNodeParameters, parameter_overrides_with_value)
|
||||
EXPECT_EQ(2u, parameter_overrides.size());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, parameter_overrides_with_parameter)
|
||||
{
|
||||
rclcpp::NodeOptions node_options;
|
||||
node_options.automatically_declare_parameters_from_overrides(true);
|
||||
node_options.append_parameter_override(rclcpp::Parameter("param1", true));
|
||||
node_options.append_parameter_override(rclcpp::Parameter("param2", 42));
|
||||
|
||||
std::shared_ptr<rclcpp::Node> node2 = std::make_shared<rclcpp::Node>("node2", "ns", node_options);
|
||||
|
||||
auto * node_parameters_interface =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||
node2->get_node_parameters_interface().get());
|
||||
ASSERT_NE(nullptr, node_parameters_interface);
|
||||
|
||||
const auto & parameter_overrides = node_parameters_interface->get_parameter_overrides();
|
||||
EXPECT_EQ(2u, parameter_overrides.size());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, set_parameters) {
|
||||
rclcpp::NodeOptions node_options;
|
||||
node_options.allow_undeclared_parameters(true);
|
||||
|
||||
@@ -37,38 +37,6 @@ TEST_F(TestNodeTypeDescriptions, interface_created)
|
||||
ASSERT_NE(nullptr, node.get_node_type_descriptions_interface());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeTypeDescriptions, automatically_declare_parameters_from_overrides)
|
||||
{
|
||||
rclcpp::NodeOptions node_options;
|
||||
node_options.automatically_declare_parameters_from_overrides(true);
|
||||
node_options.append_parameter_override("start_type_description_service", false);
|
||||
ASSERT_NO_THROW(
|
||||
{
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns", node_options);
|
||||
(void) node;
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(TestNodeTypeDescriptions, bad_parameter_type)
|
||||
{
|
||||
rclcpp::NodeOptions node_options;
|
||||
node_options.append_parameter_override("start_type_description_service", "unexpected_type");
|
||||
|
||||
ASSERT_THROW(
|
||||
{
|
||||
node_options.automatically_declare_parameters_from_overrides(false);
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns", node_options);
|
||||
(void) node;
|
||||
}, rclcpp::exceptions::InvalidParameterTypeException);
|
||||
|
||||
ASSERT_THROW(
|
||||
{
|
||||
node_options.automatically_declare_parameters_from_overrides(true);
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns", node_options);
|
||||
(void) node;
|
||||
}, rclcpp::exceptions::InvalidParameterTypeException);
|
||||
}
|
||||
|
||||
TEST_F(TestNodeTypeDescriptions, disabled_no_service)
|
||||
{
|
||||
rclcpp::NodeOptions node_options;
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
// Copyright 2024 Cellumation GmbH
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <rcpputils/compile_warnings.hpp>
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/time.h"
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "rclcpp/time_source.hpp"
|
||||
|
||||
#include "../utils/rclcpp_gtest_macros.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
class TestClockWakeup : public ::testing::TestWithParam<rcl_clock_type_e>
|
||||
{
|
||||
public:
|
||||
void test_wakeup_before_sleep(const rclcpp::Clock::SharedPtr & clock)
|
||||
{
|
||||
std::atomic_bool thread_finished = false;
|
||||
|
||||
std::thread wait_thread = std::thread(
|
||||
[&clock, &thread_finished]()
|
||||
{
|
||||
// make sure the thread starts sleeping late
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
clock->sleep_until(clock->now() + std::chrono::seconds(3));
|
||||
thread_finished = true;
|
||||
});
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_START
|
||||
// notify the clock, that the sleep shall be interrupted
|
||||
clock->cancel_sleep_or_wait();
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_STOP
|
||||
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
auto cur_time = start_time;
|
||||
while (!thread_finished && start_time + std::chrono::seconds(1) > cur_time) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
cur_time = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
wait_thread.join();
|
||||
|
||||
EXPECT_TRUE(thread_finished);
|
||||
EXPECT_LT(cur_time, start_time + std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
void test_wakeup_after_sleep(const rclcpp::Clock::SharedPtr & clock)
|
||||
{
|
||||
std::atomic_bool thread_finished = false;
|
||||
|
||||
std::thread wait_thread = std::thread(
|
||||
[&clock, &thread_finished]()
|
||||
{
|
||||
clock->sleep_until(clock->now() + std::chrono::seconds(3));
|
||||
thread_finished = true;
|
||||
});
|
||||
|
||||
// make sure the thread is already sleeping before we send the cancel
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_START
|
||||
// notify the clock, that the sleep shall be interrupted
|
||||
clock->cancel_sleep_or_wait();
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_STOP
|
||||
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
auto cur_time = start_time;
|
||||
while (!thread_finished && start_time + std::chrono::seconds(1) > cur_time) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
cur_time = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
wait_thread.join();
|
||||
|
||||
EXPECT_TRUE(thread_finished);
|
||||
EXPECT_LT(cur_time, start_time + std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
protected:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
void SetUp()
|
||||
{
|
||||
node = std::make_shared<rclcpp::Node>("my_node");
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
node.reset();
|
||||
}
|
||||
|
||||
rclcpp::Node::SharedPtr node;
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Clocks,
|
||||
TestClockWakeup,
|
||||
::testing::Values(
|
||||
RCL_SYSTEM_TIME, RCL_ROS_TIME, RCL_STEADY_TIME
|
||||
));
|
||||
|
||||
TEST_P(TestClockWakeup, wakeup_sleep) {
|
||||
auto clock = std::make_shared<rclcpp::Clock>(GetParam());
|
||||
test_wakeup_after_sleep(clock);
|
||||
test_wakeup_before_sleep(clock);
|
||||
}
|
||||
|
||||
TEST_F(TestClockWakeup, wakeup_sleep_ros_time_active) {
|
||||
node->set_parameter({"use_sim_time", true});
|
||||
auto clock = std::make_shared<rclcpp::Clock>(RCL_ROS_TIME);
|
||||
rclcpp::TimeSource time_source(node);
|
||||
time_source.attachClock(clock);
|
||||
|
||||
EXPECT_TRUE(clock->ros_time_is_active());
|
||||
|
||||
test_wakeup_after_sleep(clock);
|
||||
test_wakeup_before_sleep(clock);
|
||||
}
|
||||
|
||||
TEST_F(TestClockWakeup, no_wakeup_on_sim_time) {
|
||||
node->set_parameter({"use_sim_time", true});
|
||||
auto clock = std::make_shared<rclcpp::Clock>(RCL_ROS_TIME);
|
||||
rclcpp::TimeSource time_source(node);
|
||||
time_source.attachClock(clock);
|
||||
|
||||
EXPECT_TRUE(clock->ros_time_is_active());
|
||||
|
||||
std::atomic_bool thread_finished = false;
|
||||
|
||||
std::thread wait_thread = std::thread(
|
||||
[&clock, &thread_finished]()
|
||||
{
|
||||
// make sure the thread starts sleeping late
|
||||
clock->sleep_until(clock->now() + std::chrono::milliseconds(10));
|
||||
thread_finished = true;
|
||||
});
|
||||
|
||||
// make sure, that the sim time clock does not wakeup, as no clock is provided
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
EXPECT_FALSE(thread_finished);
|
||||
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_START
|
||||
// notify the clock, that the sleep shall be interrupted
|
||||
clock->cancel_sleep_or_wait();
|
||||
RCPPUTILS_DEPRECATION_WARNING_OFF_STOP
|
||||
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
auto cur_time = start_time;
|
||||
while (!thread_finished && start_time + std::chrono::seconds(1) > cur_time) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
cur_time = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
wait_thread.join();
|
||||
|
||||
EXPECT_TRUE(thread_finished);
|
||||
EXPECT_LT(cur_time, start_time + std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
TEST_F(TestClockWakeup, multiple_threads_wait_on_one_clock) {
|
||||
auto clock = std::make_shared<rclcpp::Clock>(RCL_ROS_TIME);
|
||||
|
||||
std::vector<std::atomic_bool> thread_finished(10);
|
||||
for (std::atomic_bool & finished : thread_finished) {
|
||||
finished = false;
|
||||
}
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
for (size_t nr = 0; nr < thread_finished.size(); nr++) {
|
||||
threads.push_back(
|
||||
std::thread(
|
||||
[&clock, &thread_finished, nr]()
|
||||
{
|
||||
// make sure the thread starts sleeping late
|
||||
clock->sleep_until(clock->now() + std::chrono::seconds(10));
|
||||
thread_finished[nr] = true;
|
||||
}));
|
||||
}
|
||||
|
||||
// wait a bit so all threads can execute the sleep_until
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
|
||||
for (const std::atomic_bool & finished : thread_finished) {
|
||||
EXPECT_FALSE(finished);
|
||||
}
|
||||
|
||||
rclcpp::shutdown();
|
||||
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
auto cur_time = start_time;
|
||||
bool threads_finished = false;
|
||||
while (!threads_finished && start_time + std::chrono::seconds(1) > cur_time) {
|
||||
threads_finished = true;
|
||||
for (const std::atomic_bool & finished : thread_finished) {
|
||||
if (!finished) {
|
||||
threads_finished = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
cur_time = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
for (const std::atomic_bool & finished : thread_finished) {
|
||||
EXPECT_TRUE(finished);
|
||||
}
|
||||
|
||||
for (auto & thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
|
||||
EXPECT_LT(cur_time, start_time + std::chrono::seconds(1));
|
||||
}
|
||||
@@ -342,12 +342,12 @@ TEST_F(TestExecutor, spin_all_fail_wait_set_clear) {
|
||||
subscription =
|
||||
rclcpp::create_subscription<test_msgs::msg::Empty>(
|
||||
node_topics, "test", rclcpp::QoS(10), std::move(callback));
|
||||
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_wait_set_clear, RCL_RET_ERROR);
|
||||
|
||||
dummy.spin_all(std::chrono::milliseconds(1));
|
||||
// second spin_all triggers rcl_wait_set_clear that should be called
|
||||
// whenever a waitset gets rebuild and it was not changed in size.
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
// the first spin might trigger the rebuild, but only the second triggers
|
||||
// it for sure, therefore we spin two times
|
||||
dummy.spin_all(std::chrono::milliseconds(1));
|
||||
dummy.spin_all(std::chrono::milliseconds(1)),
|
||||
std::runtime_error("Couldn't clear the wait set: error not set"));
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
/*
|
||||
Construtctor
|
||||
Constructor
|
||||
*/
|
||||
TEST(TestIntraProcessBuffer, constructor) {
|
||||
using MessageT = char;
|
||||
|
||||
@@ -535,7 +535,7 @@ TEST(TestIntraProcessManager, add_pub_sub) {
|
||||
* - Remove the first subscription from ipm and add a new one.
|
||||
* - Publishes a unique_ptr message with a subscription not requesting ownership.
|
||||
* - The received message is expected to be the same, the first subscription do not receive it.
|
||||
* - Publishes a unique_ptr message with a subscription not requesting ownership.
|
||||
* - Publishes a shared_ptr message with a subscription not requesting ownership.
|
||||
* - The received message is expected to be the same.
|
||||
*/
|
||||
TEST(TestIntraProcessManager, single_subscription) {
|
||||
@@ -587,9 +587,9 @@ TEST(TestIntraProcessManager, single_subscription) {
|
||||
* - One is expected to receive the published message, while the other will receive a copy.
|
||||
* - Publishes a unique_ptr message with 2 subscriptions not requesting ownership.
|
||||
* - Both received messages are expected to be the same as the published one.
|
||||
* - Publishes a unique_ptr message with 2 subscriptions requesting ownership.
|
||||
* - Publishes a shared_ptr message with 2 subscriptions requesting ownership.
|
||||
* - Both received messages are expected to be a copy of the published one.
|
||||
* - Publishes a unique_ptr message with 2 subscriptions not requesting ownership.
|
||||
* - Publishes a shared_ptr message with 2 subscriptions not requesting ownership.
|
||||
* - Both received messages are expected to be the same as the published one.
|
||||
*/
|
||||
TEST(TestIntraProcessManager, multiple_subscriptions_same_type) {
|
||||
@@ -694,9 +694,9 @@ TEST(TestIntraProcessManager, multiple_subscriptions_same_type) {
|
||||
* - The 2 subscriptions not requesting ownership are expected to both receive the same copy
|
||||
* of the message, one of the subscription requesting ownership is expected to receive a
|
||||
* different copy, while the last is expected to receive the published message.
|
||||
* - Publishes a unique_ptr message with 1 subscription requesting ownership and 1 not.
|
||||
* - The subscription requesting ownership is expected to receive the published message, while
|
||||
* the other is expected to receive a copy of the message
|
||||
* - Publishes a shared_ptr message with 1 subscription requesting ownership and 1 not.
|
||||
* - The subscription requesting ownership is expected to receive a copy of the message, while
|
||||
* the other is expected to receive the published message
|
||||
*/
|
||||
TEST(TestIntraProcessManager, multiple_subscriptions_different_type) {
|
||||
using IntraProcessManagerT = rclcpp::experimental::IntraProcessManager;
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -253,19 +253,9 @@ bool log_function_const_ref(const rclcpp::Logger & logger)
|
||||
return true;
|
||||
}
|
||||
|
||||
class DerivedLogger : public rclcpp::Logger
|
||||
{
|
||||
public:
|
||||
explicit DerivedLogger(const rclcpp::Logger & logger)
|
||||
: rclcpp::Logger(logger) {}
|
||||
};
|
||||
|
||||
TEST_F(TestLoggingMacros, test_log_from_node) {
|
||||
auto logger = rclcpp::get_logger("test_logging_logger");
|
||||
EXPECT_TRUE(log_function(logger));
|
||||
EXPECT_TRUE(log_function_const(logger));
|
||||
EXPECT_TRUE(log_function_const_ref(logger));
|
||||
|
||||
DerivedLogger derived_logger(logger);
|
||||
RCLCPP_INFO(derived_logger, "successful log from derived logger");
|
||||
}
|
||||
|
||||
@@ -1365,6 +1365,203 @@ TEST_F(TestNode, set_parameter_undeclared_parameters_not_allowed) {
|
||||
node->declare_parameter(name, 42, descriptor),
|
||||
rclcpp::exceptions::InvalidParameterValueException);
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 10;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 2;
|
||||
node->declare_parameter(name, std::vector<int64_t>{10, 12, 14, 16, 18}, descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(), std::vector<int64_t>({10, 12, 14, 16, 18}));
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({12, 14, 10}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({12, 14, 10}));
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({10, 10, 10}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({10, 10, 10}));
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({18}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({15}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({20}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({8}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({12, 8, 18}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor, from_value > to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 20;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 1;
|
||||
node->declare_parameter(name, std::vector<int64_t>({18, 20}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(), std::vector<int64_t>({18, 20}));
|
||||
|
||||
EXPECT_TRUE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({20, 18}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({20, 18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({18, 19, 20}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({20, 18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({10}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({20, 18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({25}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({20, 18}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor, from_value = to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 18;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 1;
|
||||
node->declare_parameter(name, std::vector<int64_t>({18}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(), std::vector<int64_t>({18}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({17}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({19}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor,
|
||||
// step > distance(from_value, to_value)
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 18;
|
||||
integer_range.to_value = 25;
|
||||
integer_range.step = 10;
|
||||
node->declare_parameter(name, std::vector<int64_t>({18, 25}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(), std::vector<int64_t>({18, 25}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({17}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({19}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({28}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor, distance not multiple of the step.
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 18;
|
||||
integer_range.to_value = 28;
|
||||
integer_range.step = 7;
|
||||
node->declare_parameter(name, std::vector<int64_t>({18, 25, 28}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(), std::vector<int64_t>({18, 25, 28}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({17}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25, 28}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({19}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25, 28}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({32}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({18, 25, 28}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor, step=0
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 10;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 0;
|
||||
node->declare_parameter(name, std::vector<int64_t>({10, 11, 12, 13, 14, 15, 16, 17, 18}),
|
||||
descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_INTEGER_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({10, 11, 12, 13, 14, 15, 16, 17, 18}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({9}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({10, 11, 12, 13, 14, 15, 16, 17, 18}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<int64_t>({19}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<int64_t>>(),
|
||||
std::vector<int64_t>({10, 11, 12, 13, 14, 15, 16, 17, 18}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with integer range descriptor and wrong default value will throw
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.integer_range.resize(1);
|
||||
auto & integer_range = descriptor.integer_range.at(0);
|
||||
integer_range.from_value = 10;
|
||||
integer_range.to_value = 18;
|
||||
integer_range.step = 2;
|
||||
ASSERT_THROW(
|
||||
node->declare_parameter(name, std::vector<int64_t>({10, 11, 12, 13, 14, 15, 16, 17, 18}),
|
||||
descriptor),
|
||||
rclcpp::exceptions::InvalidParameterValueException);
|
||||
}
|
||||
{
|
||||
// setting a parameter with floating point range descriptor
|
||||
auto name = "parameter"_unq;
|
||||
@@ -1535,6 +1732,201 @@ TEST_F(TestNode, set_parameter_undeclared_parameters_not_allowed) {
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name, 9.999)).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<double>(), 11.0);
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 0.2;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 10.4, 11.0, 10.8, 10.2, 10.6}),
|
||||
descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.4, 11.0, 10.8, 10.2, 10.6}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({10.3}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.4, 11.0, 10.8, 10.2, 10.6}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.0}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.4, 11.0, 10.8, 10.2, 10.6}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.4}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.4, 11.0, 10.8, 10.2, 10.6}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor, negative step
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = -0.2;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 10.2, 10.4, 10.6, 10.8, 11.0}),
|
||||
descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.2, 10.4, 10.6, 10.8, 11.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({10.3}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.2, 10.4, 10.6, 10.8, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.0}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.2, 10.4, 10.6, 10.8, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.4}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.2, 10.4, 10.6, 10.8, 11.0}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor, from_value > to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 11.0;
|
||||
floating_point_range.to_value = 10.0;
|
||||
floating_point_range.step = 0.2;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 11.0}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(), std::vector<double>({10.0, 11.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({10.2}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.0}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.4}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 11.0}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor, from_value = to_value
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 10.0;
|
||||
floating_point_range.step = 0.2;
|
||||
node->declare_parameter(name, std::vector<double>({10.0}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(), std::vector<double>({10.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({11.2}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.0}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.4}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor, step > distance
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 2.2;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 11.0}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(), std::vector<double>({10.0, 11.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.2}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({7.8}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 11.0}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor,
|
||||
// distance not multiple of the step.
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 0.7;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 10.7, 11.0}), descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(), std::vector<double>({10.0, 10.7, 11.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({12.2}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.7, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({11.4}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.7, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.3}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.7, 11.0}));
|
||||
}
|
||||
{
|
||||
// setting an array parameter with floating point range descriptor, step=0
|
||||
auto name = "parameter"_unq;
|
||||
rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
descriptor.floating_point_range.resize(1);
|
||||
auto & floating_point_range = descriptor.floating_point_range.at(0);
|
||||
floating_point_range.from_value = 10.0;
|
||||
floating_point_range.to_value = 11.0;
|
||||
floating_point_range.step = 0.0;
|
||||
node->declare_parameter(name, std::vector<double>({10.0, 10.0001, 10.5479051, 11.0}),
|
||||
descriptor);
|
||||
EXPECT_TRUE(node->has_parameter(name));
|
||||
auto value = node->get_parameter(name);
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_DOUBLE_ARRAY);
|
||||
EXPECT_EQ(value.get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.0001, 10.5479051, 11.0}));
|
||||
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({11.001}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.0001, 10.5479051, 11.0}));
|
||||
EXPECT_FALSE(node->set_parameter(rclcpp::Parameter(name,
|
||||
std::vector<double>({9.999}))).successful);
|
||||
EXPECT_EQ(node->get_parameter(name).get_value<std::vector<double>>(),
|
||||
std::vector<double>({10.0, 10.0001, 10.5479051, 11.0}));
|
||||
}
|
||||
{
|
||||
// setting a parameter with a different type is still possible
|
||||
// when having a descriptor specifying a type (type is a status, not a constraint).
|
||||
|
||||
@@ -258,10 +258,8 @@ TEST(TestNodeOptions, append_parameter_override) {
|
||||
auto options = rclcpp::NodeOptions().arguments(expected_args).use_global_arguments(false);
|
||||
rclcpp::Parameter parameter("some_parameter", 10);
|
||||
options.append_parameter_override("some_parameter", 10);
|
||||
options.append_parameter_override(parameter);
|
||||
EXPECT_EQ(2u, options.parameter_overrides().size());
|
||||
EXPECT_EQ(1u, options.parameter_overrides().size());
|
||||
EXPECT_EQ(std::string("some_parameter"), options.parameter_overrides()[0].get_name());
|
||||
EXPECT_EQ(std::string("some_parameter"), options.parameter_overrides()[1].get_name());
|
||||
}
|
||||
|
||||
TEST(TestNodeOptions, rcl_node_options_fini_error) {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@@ -199,7 +199,7 @@ TEST_F(TestPublisher, test_publisher_with_system_default_qos) {
|
||||
using test_msgs::msg::Empty;
|
||||
ASSERT_NO_THROW(
|
||||
{
|
||||
auto publisher = node->create_publisher<Empty>("topic", rclcpp::SystemDefaultsQoS(), options);
|
||||
auto publisher = node->create_publisher<Empty>("topic", rclcpp::SystemDefaultsQoS());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -272,15 +272,3 @@ TEST(TestQoS, qos_check_compatible)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestQoS, from_rmw_validity)
|
||||
{
|
||||
rmw_qos_profile_t invalid_qos;
|
||||
memset(&invalid_qos, 0, sizeof(invalid_qos));
|
||||
unsigned int n = 999;
|
||||
memcpy(&invalid_qos.history, &n, sizeof(n));
|
||||
|
||||
EXPECT_THROW({
|
||||
rclcpp::QoSInitialization::from_rmw(invalid_qos);
|
||||
}, std::invalid_argument);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "rclcpp/experimental/buffers/ring_buffer_implementation.hpp"
|
||||
|
||||
/*
|
||||
* Construtctor
|
||||
* Constructor
|
||||
*/
|
||||
TEST(TestRingBufferImplementation, constructor) {
|
||||
// Cannot create a buffer of size zero.
|
||||
@@ -140,14 +140,27 @@ TEST(TestRingBufferImplementation, basic_usage_unique_ptr) {
|
||||
EXPECT_EQ(false, rb.is_full());
|
||||
}
|
||||
|
||||
TEST(TestRingBufferImplementation, handle_nullptr_deletion) {
|
||||
rclcpp::experimental::buffers::RingBufferImplementation<std::unique_ptr<int>> rb(3);
|
||||
rb.enqueue(std::make_unique<int>(42));
|
||||
rb.enqueue(nullptr); // intentionally enqueuing nullptr
|
||||
rb.enqueue(std::make_unique<int>(84));
|
||||
auto all_data = rb.get_all_data();
|
||||
EXPECT_EQ(3u, all_data.size());
|
||||
EXPECT_EQ(42, *(all_data[0]));
|
||||
EXPECT_EQ(nullptr, all_data[1]);
|
||||
EXPECT_EQ(84, *(all_data[2]));
|
||||
TEST(TestRingBufferImplementation, test_buffer_clear) {
|
||||
rclcpp::experimental::buffers::RingBufferImplementation<char> rb(2);
|
||||
rb.enqueue('a');
|
||||
rb.enqueue('b');
|
||||
|
||||
EXPECT_EQ(true, rb.has_data());
|
||||
EXPECT_EQ(true, rb.is_full());
|
||||
const auto all_data_vec = rb.get_all_data();
|
||||
EXPECT_EQ(2u, all_data_vec.capacity());
|
||||
EXPECT_EQ(2u, all_data_vec.size());
|
||||
rb.clear();
|
||||
EXPECT_EQ(false, rb.has_data());
|
||||
EXPECT_EQ(false, rb.is_full());
|
||||
const auto all_data_vec_empty = rb.get_all_data();
|
||||
EXPECT_EQ(0u, all_data_vec_empty.capacity());
|
||||
EXPECT_EQ(0u, all_data_vec_empty.size());
|
||||
rb.enqueue('c');
|
||||
rb.enqueue('d');
|
||||
const auto c = rb.dequeue();
|
||||
const auto d = rb.dequeue();
|
||||
|
||||
EXPECT_EQ('c', c);
|
||||
EXPECT_EQ('d', d);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <rcl/service_introspection.h>
|
||||
#include <rmw/rmw.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -108,58 +107,3 @@ TEST(TestUtilities, wait_for_message_twice_one_sub) {
|
||||
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
TEST(TestUtilities, wait_for_last_message) {
|
||||
rclcpp::init(0, nullptr);
|
||||
|
||||
auto node = std::make_shared<rclcpp::Node>("wait_for_last_message_node");
|
||||
auto qos = rclcpp::QoS(1).reliable().transient_local();
|
||||
|
||||
using MsgT = test_msgs::msg::Strings;
|
||||
auto pub = node->create_publisher<MsgT>("wait_for_last_message_topic", qos);
|
||||
pub->publish(*get_messages_strings()[0]);
|
||||
|
||||
MsgT out;
|
||||
auto received = false;
|
||||
auto wait = std::async(
|
||||
[&]() {
|
||||
auto ret = rclcpp::wait_for_message(out, node, "wait_for_last_message_topic", 5s, qos);
|
||||
EXPECT_TRUE(ret);
|
||||
received = true;
|
||||
});
|
||||
|
||||
ASSERT_NO_THROW(wait.get());
|
||||
ASSERT_TRUE(received);
|
||||
EXPECT_EQ(out, *get_messages_strings()[0]);
|
||||
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
TEST(TestUtilities, wait_for_message_custom_context) {
|
||||
auto context = std::make_shared<rclcpp::Context>();
|
||||
context->init(0, nullptr);
|
||||
|
||||
auto node_opt = rclcpp::NodeOptions().context(context);
|
||||
auto node = std::make_shared<rclcpp::Node>("wait_for_message_custom_context_node", node_opt);
|
||||
|
||||
using MsgT = test_msgs::msg::Strings;
|
||||
auto pub = node->create_publisher<MsgT>("wait_for_message_topic", 10);
|
||||
|
||||
MsgT out;
|
||||
auto received = false;
|
||||
auto wait = std::async(
|
||||
[&]() {
|
||||
auto ret = rclcpp::wait_for_message(out, node, "wait_for_message_topic", 5s);
|
||||
EXPECT_TRUE(ret);
|
||||
received = true;
|
||||
});
|
||||
|
||||
for (auto i = 0u; i < 10 && received == false; ++i) {
|
||||
pub->publish(*get_messages_strings()[0]);
|
||||
std::this_thread::sleep_for(1s);
|
||||
}
|
||||
ASSERT_TRUE(received);
|
||||
EXPECT_EQ(out, *get_messages_strings()[0]);
|
||||
|
||||
context->shutdown("test complete");
|
||||
}
|
||||
|
||||
@@ -3,37 +3,8 @@ Changelog for package rclcpp_action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
29.5.7 (2026-02-09)
|
||||
29.6.0 (2025-04-25)
|
||||
-------------------
|
||||
* Update exception documentation for goal cancellation in ServerGoalHandle (`#3019 <https://github.com/ros2/rclcpp/issues/3019>`_) (`#3022 <https://github.com/ros2/rclcpp/issues/3022>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.6 (2025-12-23)
|
||||
-------------------
|
||||
|
||||
29.5.5 (2025-11-18)
|
||||
-------------------
|
||||
* Fix REP url locations (`#2987 <https://github.com/ros2/rclcpp/issues/2987>`_) (`#2989 <https://github.com/ros2/rclcpp/issues/2989>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.4 (2025-10-21)
|
||||
-------------------
|
||||
* it misses the iterator second to lock the weakptr. (`#2958 <https://github.com/ros2/rclcpp/issues/2958>`_) (`#2959 <https://github.com/ros2/rclcpp/issues/2959>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.3 (2025-09-11)
|
||||
-------------------
|
||||
* fix cmake deprecation (`#2914 <https://github.com/ros2/rclcpp/issues/2914>`_) (`#2915 <https://github.com/ros2/rclcpp/issues/2915>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.2 (2025-07-07)
|
||||
-------------------
|
||||
|
||||
29.5.1 (2025-06-23)
|
||||
-------------------
|
||||
* Replace std::default_random_engine with std::mt19937 (rolling) (`#2843 <https://github.com/ros2/rclcpp/issues/2843>`_) (`#2866 <https://github.com/ros2/rclcpp/issues/2866>`_)
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.0 (2025-04-18)
|
||||
-------------------
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(rclcpp_action)
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
This document is a declaration of software quality for the `rclcpp_action` package, based on the guidelines in [REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
This document is a declaration of software quality for the `rclcpp_action` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
# rclcpp_action Quality Declaration
|
||||
|
||||
The package `rclcpp_action` claims to be in the **Quality Level 1** category when it is used with a **Quality Level 1** middleware.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
## Version Policy [1]
|
||||
|
||||
@@ -53,7 +53,7 @@ All pull requests will be peer-reviewed, check [ROS 2 Developer Guide](https://d
|
||||
|
||||
### Continuous Integration [2.iv]
|
||||
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://reps.openrobotics.org/rep-2000/#support-tiers)
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://www.ros.org/reps/rep-2000.html#support-tiers)
|
||||
|
||||
Currently nightly results can be seen here:
|
||||
|
||||
@@ -179,7 +179,7 @@ It is **Quality Level 1**, see its [Quality Declaration document](https://github
|
||||
|
||||
## Platform Support [6]
|
||||
|
||||
`rclcpp_action` supports all of the tier 1 platforms as described in [REP-2000](https://reps.openrobotics.org/rep-2000/#support-tiers), and tests each change against all of them.
|
||||
`rclcpp_action` supports all of the tier 1 platforms as described in [REP-2000](https://www.ros.org/reps/rep-2000.html#support-tiers), and tests each change against all of them.
|
||||
|
||||
Currently nightly build status can be seen here:
|
||||
* [linux-aarch64_release](https://ci.ros2.org/view/nightly/job/nightly_linux-aarch64_release/lastBuild/rclcpp_action/)
|
||||
@@ -191,4 +191,4 @@ Currently nightly build status can be seen here:
|
||||
|
||||
### Vulnerability Disclosure Policy [7.i]
|
||||
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://reps.openrobotics.org/rep-2006/).
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://www.ros.org/reps/rep-2006.html).
|
||||
|
||||
@@ -350,7 +350,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
goal_handle = it->second.lock();
|
||||
goal_handle = it->lock();
|
||||
}
|
||||
|
||||
if (goal_handle) {
|
||||
|
||||
@@ -200,7 +200,7 @@ public:
|
||||
* This is a terminal state, no more methods should be called on a goal handle after this is
|
||||
* called.
|
||||
*
|
||||
* \throws rclcpp::exceptions::RCLError If a cancel request for this goal has not been received.
|
||||
* \throws rclcpp::exceptions::RCLError If the goal is in any state besides executing.
|
||||
*
|
||||
* \param[in] result_msg the final result to send to clients.
|
||||
*/
|
||||
|
||||
@@ -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>29.5.7</version>
|
||||
<version>29.6.0</version>
|
||||
<description>Adds action APIs for C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
std::recursive_mutex cancel_requests_mutex;
|
||||
|
||||
std::independent_bits_engine<
|
||||
std::mt19937, 8, unsigned int> random_bytes_generator;
|
||||
std::default_random_engine, 8, unsigned int> random_bytes_generator;
|
||||
};
|
||||
|
||||
ClientBase::ClientBase(
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ TEST(TestActionTypes, goal_uuid_to_hashed_uuid_random) {
|
||||
// Use std::random_device to seed the generator of goal IDs.
|
||||
std::random_device rd;
|
||||
std::independent_bits_engine<
|
||||
std::mt19937, 8, decltype(rd())> random_bytes_generator(rd());
|
||||
std::default_random_engine, 8, decltype(rd())> random_bytes_generator(rd());
|
||||
|
||||
std::vector<size_t> hashed_guuids;
|
||||
constexpr size_t iterations = 1000;
|
||||
|
||||
@@ -2,33 +2,9 @@
|
||||
Changelog for package rclcpp_components
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
29.5.7 (2026-02-09)
|
||||
29.6.0 (2025-04-25)
|
||||
-------------------
|
||||
|
||||
29.5.6 (2025-12-23)
|
||||
-------------------
|
||||
|
||||
29.5.5 (2025-11-18)
|
||||
-------------------
|
||||
* Fix REP url locations (`#2987 <https://github.com/ros2/rclcpp/issues/2987>`_) (`#2989 <https://github.com/ros2/rclcpp/issues/2989>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.4 (2025-10-21)
|
||||
-------------------
|
||||
|
||||
29.5.3 (2025-09-11)
|
||||
-------------------
|
||||
* fix cmake deprecation (`#2914 <https://github.com/ros2/rclcpp/issues/2914>`_) (`#2915 <https://github.com/ros2/rclcpp/issues/2915>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.2 (2025-07-07)
|
||||
-------------------
|
||||
|
||||
29.5.1 (2025-06-23)
|
||||
-------------------
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.0 (2025-04-18)
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(rclcpp_components)
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
This document is a declaration of software quality for the `rclcpp_components` package, based on the guidelines in [REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
This document is a declaration of software quality for the `rclcpp_components` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
# rclcpp_components Quality Declaration
|
||||
|
||||
The package `rclcpp_components` claims to be in the **Quality Level 1** category.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
## Version Policy [1]
|
||||
|
||||
@@ -53,7 +53,7 @@ All pull requests will be peer-reviewed, check [ROS 2 Developer Guide](https://d
|
||||
|
||||
### Continuous Integration [2.iv]
|
||||
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://reps.openrobotics.org/rep-2000/#support-tiers)
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://www.ros.org/reps/rep-2000.html#support-tiers)
|
||||
|
||||
Currently nightly results can be seen here:
|
||||
|
||||
@@ -191,7 +191,7 @@ It is **Quality Level 1**, see its [Quality Declaration document](https://github
|
||||
|
||||
## Platform Support [6]
|
||||
|
||||
`rclcpp_components` supports all of the tier 1 platforms as described in [REP-2000](https://reps.openrobotics.org/rep-2000/#support-tiers), and tests each change against all of them.
|
||||
`rclcpp_components` supports all of the tier 1 platforms as described in [REP-2000](https://www.ros.org/reps/rep-2000.html#support-tiers), and tests each change against all of them.
|
||||
|
||||
Currently nightly build status can be seen here:
|
||||
* [linux-aarch64_release](https://ci.ros2.org/view/nightly/job/nightly_linux-aarch64_release/lastBuild/rclcpp_components/)
|
||||
@@ -203,4 +203,4 @@ Currently nightly build status can be seen here:
|
||||
|
||||
### Vulnerability Disclosure Policy [7.i]
|
||||
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://reps.openrobotics.org/rep-2006/).
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://www.ros.org/reps/rep-2006.html).
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="2">
|
||||
<name>rclcpp_components</name>
|
||||
<version>29.5.7</version>
|
||||
<version>29.6.0</version>
|
||||
<description>Package containing tools for dynamically loadable components</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -3,35 +3,9 @@ Changelog for package rclcpp_lifecycle
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
29.5.7 (2026-02-09)
|
||||
29.6.0 (2025-04-25)
|
||||
-------------------
|
||||
|
||||
29.5.6 (2025-12-23)
|
||||
-------------------
|
||||
|
||||
29.5.5 (2025-11-18)
|
||||
-------------------
|
||||
* Fix REP url locations (`#2987 <https://github.com/ros2/rclcpp/issues/2987>`_) (`#2989 <https://github.com/ros2/rclcpp/issues/2989>`_)
|
||||
* Add get_parameter_or overload returning value or alternative (`#2973 <https://github.com/ros2/rclcpp/issues/2973>`_) (`#2976 <https://github.com/ros2/rclcpp/issues/2976>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.4 (2025-10-21)
|
||||
-------------------
|
||||
|
||||
29.5.3 (2025-09-11)
|
||||
-------------------
|
||||
* Clearer warning message, the old one lacked information and was perhaps misleading (`#2927 <https://github.com/ros2/rclcpp/issues/2927>`_) (`#2931 <https://github.com/ros2/rclcpp/issues/2931>`_)
|
||||
* fix cmake deprecation (`#2914 <https://github.com/ros2/rclcpp/issues/2914>`_) (`#2915 <https://github.com/ros2/rclcpp/issues/2915>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.2 (2025-07-07)
|
||||
-------------------
|
||||
|
||||
29.5.1 (2025-06-23)
|
||||
-------------------
|
||||
* Added missing chrono includes (`#2854 <https://github.com/ros2/rclcpp/issues/2854>`_) (`#2855 <https://github.com/ros2/rclcpp/issues/2855>`_)
|
||||
* Contributors: mergify[bot]
|
||||
|
||||
29.5.0 (2025-04-18)
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(rclcpp_lifecycle)
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
This document is a declaration of software quality for the `rclcpp_lifecycle` package, based on the guidelines in [REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
This document is a declaration of software quality for the `rclcpp_lifecycle` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
# rclcpp_lifecycle Quality Declaration
|
||||
|
||||
The package `rclcpp_lifecycle` claims to be in the **Quality Level 1** category when used with a **Quality Level 1** middleware.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://reps.openrobotics.org/rep-2004/).
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Requirements for Quality Level 1 in REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
## Version Policy [1]
|
||||
|
||||
@@ -53,7 +53,7 @@ All pull requests will be peer-reviewed, check [ROS 2 Developer Guide](https://d
|
||||
|
||||
### Continuous Integration [2.iv]
|
||||
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://reps.openrobotics.org/rep-2000/#support-tiers)
|
||||
All pull requests must pass CI on all [tier 1 platforms](https://www.ros.org/reps/rep-2000.html#support-tiers)
|
||||
|
||||
Currently nightly results can be seen here:
|
||||
|
||||
@@ -191,7 +191,7 @@ It is **Quality Level 1**, see its [Quality Declaration document](https://github
|
||||
|
||||
## Platform Support [6]
|
||||
|
||||
`rclcpp_lifecycle` supports all of the tier 1 platforms as described in [REP-2000](https://reps.openrobotics.org/rep-2000/#support-tiers), and tests each change against all of them.
|
||||
`rclcpp_lifecycle` supports all of the tier 1 platforms as described in [REP-2000](https://www.ros.org/reps/rep-2000.html#support-tiers), and tests each change against all of them.
|
||||
|
||||
Currently nightly build status can be seen here:
|
||||
* [linux-aarch64_release](https://ci.ros2.org/view/nightly/job/nightly_linux-aarch64_release/lastBuild/rclcpp_lifecycle/)
|
||||
@@ -203,4 +203,4 @@ Currently nightly build status can be seen here:
|
||||
|
||||
### Vulnerability Disclosure Policy [7.i]
|
||||
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://reps.openrobotics.org/rep-2006/).
|
||||
This package conforms to the Vulnerability Disclosure Policy in [REP-2006](https://www.ros.org/reps/rep-2006.html).
|
||||
|
||||
@@ -486,16 +486,6 @@ public:
|
||||
ParameterT & value,
|
||||
const ParameterT & alternative_value) const;
|
||||
|
||||
/// Return the parameter value, or the "alternative_value" if not set.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_parameter_or
|
||||
*/
|
||||
template<typename ParameterT>
|
||||
ParameterT
|
||||
get_parameter_or(
|
||||
const std::string & name,
|
||||
const ParameterT & alternative_value) const;
|
||||
|
||||
/// Return the parameters by the given parameter names.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_parameters
|
||||
|
||||
@@ -306,16 +306,5 @@ LifecycleNode::get_parameter_or(
|
||||
return got_parameter;
|
||||
}
|
||||
|
||||
template<typename ParameterT>
|
||||
ParameterT
|
||||
LifecycleNode::get_parameter_or(
|
||||
const std::string & name,
|
||||
const ParameterT & alternative_value) const
|
||||
{
|
||||
ParameterT parameter;
|
||||
get_parameter_or(name, parameter, alternative_value);
|
||||
return parameter;
|
||||
}
|
||||
|
||||
} // namespace rclcpp_lifecycle
|
||||
#endif // RCLCPP_LIFECYCLE__LIFECYCLE_NODE_IMPL_HPP_
|
||||
|
||||
@@ -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>29.5.7</version>
|
||||
<version>29.6.0</version>
|
||||
<description>Package containing a prototype for lifecycle implementation</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -390,7 +390,6 @@ LifecycleNode::LifecycleNodeInterfaceImpl::change_state(
|
||||
constexpr bool publish_update = true;
|
||||
State initial_state;
|
||||
unsigned int current_state_id;
|
||||
const rcl_lifecycle_transition_t * original_transition{nullptr};
|
||||
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(state_machine_mutex_);
|
||||
@@ -406,18 +405,18 @@ LifecycleNode::LifecycleNodeInterfaceImpl::change_state(
|
||||
// keep the initial state to pass to a transition callback
|
||||
initial_state = State(state_machine_.current_state);
|
||||
|
||||
original_transition =
|
||||
rcl_lifecycle_get_transition_by_id(state_machine_.current_state, transition_id);
|
||||
|
||||
|
||||
if (
|
||||
rcl_lifecycle_trigger_transition_by_id(
|
||||
&state_machine_, transition_id, publish_update) != RCL_RET_OK)
|
||||
{
|
||||
const char * transition_label = rcl_lifecycle_get_transition_label_by_id(
|
||||
&state_machine_.transition_map, transition_id);
|
||||
RCLCPP_ERROR(
|
||||
node_logging_interface_->get_logger(),
|
||||
"Unable to start transition %u from current state %s: %s",
|
||||
transition_id, state_machine_.current_state->label, rcl_get_error_string().str);
|
||||
"Unable to start transition %u (%s) from current state %s: %s",
|
||||
transition_id,
|
||||
transition_label ? transition_label : "unknown transition",
|
||||
state_machine_.current_state->label, rcl_get_error_string().str);
|
||||
rcutils_reset_error();
|
||||
return RCL_RET_ERROR;
|
||||
}
|
||||
@@ -460,15 +459,12 @@ LifecycleNode::LifecycleNodeInterfaceImpl::change_state(
|
||||
// Update the internal current_state_
|
||||
current_state_ = State(state_machine_.current_state);
|
||||
|
||||
// error handling
|
||||
// error handling ?!
|
||||
// TODO(karsten1987): iterate over possible ret value
|
||||
if (cb_return_code == node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR) {
|
||||
if (original_transition) {
|
||||
RCLCPP_WARN(
|
||||
node_logging_interface_->get_logger(),
|
||||
"Callback returned ERROR during the transition: %s", original_transition->label);
|
||||
}
|
||||
|
||||
RCLCPP_WARN(
|
||||
node_logging_interface_->get_logger(),
|
||||
"Error occurred while doing error handling.");
|
||||
|
||||
auto error_cb_code = execute_callback(current_state_id, initial_state);
|
||||
auto error_cb_label = get_label_for_return_code(error_cb_code);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
@@ -840,26 +839,6 @@ TEST_F(TestDefaultStateMachine, check_parameters) {
|
||||
EXPECT_TRUE(parameter.as_bool());
|
||||
}
|
||||
|
||||
TEST_F(TestDefaultStateMachine, test_get_parameter_or) {
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
|
||||
const std::string param_name = "test_param";
|
||||
int param_int = -999;
|
||||
|
||||
// Parameter does not exist, should return "or" value
|
||||
EXPECT_FALSE(test_node->get_parameter_or(param_name, param_int, 123));
|
||||
EXPECT_EQ(param_int, 123);
|
||||
EXPECT_EQ(test_node->get_parameter_or(param_name, 456), 456);
|
||||
|
||||
// Declare param_int
|
||||
test_node->declare_parameter(param_name, rclcpp::ParameterValue(789));
|
||||
|
||||
// Parameter exists, should return existing value
|
||||
EXPECT_TRUE(test_node->get_parameter_or(param_name, param_int, 123));
|
||||
EXPECT_EQ(param_int, 789);
|
||||
EXPECT_EQ(test_node->get_parameter_or(param_name, 456), 789);
|
||||
}
|
||||
|
||||
TEST_F(TestDefaultStateMachine, test_getters) {
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
auto options = test_node->get_node_options();
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
Reference in New Issue
Block a user