Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d2b32b5c3 | ||
|
|
21f8a22311 | ||
|
|
2bb1dc2c71 | ||
|
|
d9b2744057 | ||
|
|
a19ad2134b | ||
|
|
26f6efa840 | ||
|
|
d08d9cf5ff | ||
|
|
2446fd000b | ||
|
|
411dbe8212 | ||
|
|
de841d9c8b | ||
|
|
9c098e544e | ||
|
|
0f331f90a9 | ||
|
|
620fcf1e05 | ||
|
|
d407a5e331 | ||
|
|
7f411371b3 | ||
|
|
76e2b2677b | ||
|
|
5049c45f85 | ||
|
|
4691063a61 | ||
|
|
f294488e17 | ||
|
|
8a02e3934c | ||
|
|
fff009a751 | ||
|
|
2204e44305 | ||
|
|
fcbe64cff4 | ||
|
|
c366e531fa | ||
|
|
5ffc963e1a | ||
|
|
7f7ffcf6ed | ||
|
|
13abc1beed | ||
|
|
e77c1fe550 | ||
|
|
00b9d0a018 | ||
|
|
77c7aaf917 | ||
|
|
9019a8d9b7 | ||
|
|
0644f220a2 | ||
|
|
32438a6a67 | ||
|
|
d6bd8baac5 | ||
|
|
623c3eb874 | ||
|
|
7c1143dc15 | ||
|
|
9ff864c6ae | ||
|
|
13182b5aad | ||
|
|
9284d7cefa | ||
|
|
c42745c5ba | ||
|
|
ea31f94eb4 | ||
|
|
f496291e81 | ||
|
|
dd6fad6d42 | ||
|
|
38734d769a | ||
|
|
e103b8d37e | ||
|
|
253d395d4e | ||
|
|
d5e5141b3d | ||
|
|
a0148dfd5d | ||
|
|
5e152d77d8 | ||
|
|
fa732b9ee8 | ||
|
|
bc435776a2 | ||
|
|
43cf0be15c | ||
|
|
fd58bddb05 | ||
|
|
e7f06398db | ||
|
|
ba175922d3 | ||
|
|
77db1ed25b | ||
|
|
403f305b15 | ||
|
|
fd229d72ff |
@@ -2,6 +2,68 @@
|
||||
Changelog for package rclcpp
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
25.0.0 (2023-12-26)
|
||||
-------------------
|
||||
* Updated GenericSubscription to AnySubscriptionCallback (`#1928 <https://github.com/ros2/rclcpp/issues/1928>`_)
|
||||
* make type support helper supported for service (`#2209 <https://github.com/ros2/rclcpp/issues/2209>`_)
|
||||
* Adding QoS to subscription options (`#2323 <https://github.com/ros2/rclcpp/issues/2323>`_)
|
||||
* Switch to target_link_libraries. (`#2374 <https://github.com/ros2/rclcpp/issues/2374>`_)
|
||||
* aligh with rcl that a rosout publisher of a node might not exist (`#2357 <https://github.com/ros2/rclcpp/issues/2357>`_)
|
||||
* Fix data race in EventHandlerBase (`#2349 <https://github.com/ros2/rclcpp/issues/2349>`_)
|
||||
* Support users holding onto shared pointers in the message memory pool (`#2336 <https://github.com/ros2/rclcpp/issues/2336>`_)
|
||||
* Contributors: Chen Lihui, Chris Lalancette, DensoADAS, Lucas Wendland, mauropasse
|
||||
|
||||
24.0.0 (2023-11-06)
|
||||
-------------------
|
||||
* fix (signal_handler.hpp): spelling (`#2356 <https://github.com/ros2/rclcpp/issues/2356>`_)
|
||||
* Updates to not use std::move in some places. (`#2353 <https://github.com/ros2/rclcpp/issues/2353>`_)
|
||||
* rclcpp::Time::max() clock type support. (`#2352 <https://github.com/ros2/rclcpp/issues/2352>`_)
|
||||
* Serialized Messages with Topic Statistics (`#2274 <https://github.com/ros2/rclcpp/issues/2274>`_)
|
||||
* Add a custom deleter when constructing rcl_service_t (`#2351 <https://github.com/ros2/rclcpp/issues/2351>`_)
|
||||
* Disable the loaned messages inside the executor. (`#2335 <https://github.com/ros2/rclcpp/issues/2335>`_)
|
||||
* Use message_info in SubscriptionTopicStatistics instead of typed message (`#2337 <https://github.com/ros2/rclcpp/issues/2337>`_)
|
||||
* Add missing 'enable_rosout' comments (`#2345 <https://github.com/ros2/rclcpp/issues/2345>`_)
|
||||
* Adjust rclcpp usage of type description service (`#2344 <https://github.com/ros2/rclcpp/issues/2344>`_)
|
||||
* address rate related flaky tests. (`#2329 <https://github.com/ros2/rclcpp/issues/2329>`_)
|
||||
* Fixes pointed out by the clang analyzer. (`#2339 <https://github.com/ros2/rclcpp/issues/2339>`_)
|
||||
* Remove useless ROSRate class (`#2326 <https://github.com/ros2/rclcpp/issues/2326>`_)
|
||||
* Contributors: Alexey Merzlyakov, Chris Lalancette, Jiaqi Li, Lucas Wendland, Michael Carroll, Michael Orlov, Tomoya Fujita, Zard-C
|
||||
|
||||
23.2.0 (2023-10-09)
|
||||
-------------------
|
||||
* add clients & services count (`#2072 <https://github.com/ros2/rclcpp/issues/2072>`_)
|
||||
* remove invalid sized allocation test for SerializedMessage. (`#2330 <https://github.com/ros2/rclcpp/issues/2330>`_)
|
||||
* Adding API to copy all parameters from one node to another (`#2304 <https://github.com/ros2/rclcpp/issues/2304>`_)
|
||||
* Contributors: Minju, Lee, Steve Macenski, Tomoya Fujita
|
||||
|
||||
23.1.0 (2023-10-04)
|
||||
-------------------
|
||||
* Add locking to protect the TimeSource::NodeState::node_base\_ (`#2320 <https://github.com/ros2/rclcpp/issues/2320>`_)
|
||||
* Update SignalHandler get_global_signal_handler to avoid complex types in static memory (`#2316 <https://github.com/ros2/rclcpp/issues/2316>`_)
|
||||
* Removing Old Connext Tests (`#2313 <https://github.com/ros2/rclcpp/issues/2313>`_)
|
||||
* Documentation for list_parameters (`#2315 <https://github.com/ros2/rclcpp/issues/2315>`_)
|
||||
* Decouple rosout publisher init from node init. (`#2174 <https://github.com/ros2/rclcpp/issues/2174>`_)
|
||||
* fix the depth to relative in list_parameters (`#2300 <https://github.com/ros2/rclcpp/issues/2300>`_)
|
||||
* Contributors: Chris Lalancette, Lucas Wendland, Minju, Lee, Tomoya Fujita, Tully Foote
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Fix the return type of Rate::period. (`#2301 <https://github.com/ros2/rclcpp/issues/2301>`_)
|
||||
* Update API docs links in package READMEs (`#2302 <https://github.com/ros2/rclcpp/issues/2302>`_)
|
||||
* Cleanup flaky timers_manager tests. (`#2299 <https://github.com/ros2/rclcpp/issues/2299>`_)
|
||||
* Contributors: Chris Lalancette, Christophe Bedard
|
||||
|
||||
22.2.0 (2023-09-07)
|
||||
-------------------
|
||||
* Topic correct typeadapter deduction (`#2294 <https://github.com/ros2/rclcpp/issues/2294>`_)
|
||||
* Fix C++20 allocator construct deprecation (`#2292 <https://github.com/ros2/rclcpp/issues/2292>`_)
|
||||
* Make Rate to select the clock to work with (`#2123 <https://github.com/ros2/rclcpp/issues/2123>`_)
|
||||
* Correct the position of a comment. (`#2290 <https://github.com/ros2/rclcpp/issues/2290>`_)
|
||||
* Remove unnecessary lambda captures in the tests. (`#2289 <https://github.com/ros2/rclcpp/issues/2289>`_)
|
||||
* Add rcl_logging_interface as an explicit dependency. (`#2284 <https://github.com/ros2/rclcpp/issues/2284>`_)
|
||||
* Revamp list_parameters to be more efficient and easier to read. (`#2282 <https://github.com/ros2/rclcpp/issues/2282>`_)
|
||||
* Contributors: AiVerisimilitude, Alexey Merzlyakov, Chen Lihui, Chris Lalancette, Jiaqi Li
|
||||
|
||||
22.1.0 (2023-08-21)
|
||||
-------------------
|
||||
* Do not crash Executor when send_response fails due to client failure. (`#2276 <https://github.com/ros2/rclcpp/issues/2276>`_)
|
||||
|
||||
@@ -10,11 +10,14 @@ find_package(builtin_interfaces REQUIRED)
|
||||
find_package(libstatistics_collector REQUIRED)
|
||||
find_package(rcl REQUIRED)
|
||||
find_package(rcl_interfaces REQUIRED)
|
||||
find_package(rcl_logging_interface REQUIRED)
|
||||
find_package(rcl_yaml_param_parser REQUIRED)
|
||||
find_package(rcpputils REQUIRED)
|
||||
find_package(rcutils REQUIRED)
|
||||
find_package(rmw REQUIRED)
|
||||
find_package(rosgraph_msgs REQUIRED)
|
||||
find_package(rosidl_dynamic_typesupport REQUIRED)
|
||||
find_package(rosidl_runtime_c REQUIRED)
|
||||
find_package(rosidl_runtime_cpp REQUIRED)
|
||||
find_package(rosidl_typesupport_c REQUIRED)
|
||||
find_package(rosidl_typesupport_cpp REQUIRED)
|
||||
@@ -106,6 +109,7 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/qos.cpp
|
||||
src/rclcpp/event_handler.cpp
|
||||
src/rclcpp/qos_overriding_options.cpp
|
||||
src/rclcpp/rate.cpp
|
||||
src/rclcpp/serialization.cpp
|
||||
src/rclcpp/serialized_message.cpp
|
||||
src/rclcpp/service.cpp
|
||||
@@ -200,22 +204,28 @@ target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")
|
||||
target_link_libraries(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT})
|
||||
# specific order: dependents before dependencies
|
||||
ament_target_dependencies(${PROJECT_NAME}
|
||||
"ament_index_cpp"
|
||||
"libstatistics_collector"
|
||||
"rcl"
|
||||
"rcl_interfaces"
|
||||
"rcl_yaml_param_parser"
|
||||
"rcpputils"
|
||||
"rcutils"
|
||||
"builtin_interfaces"
|
||||
"rosgraph_msgs"
|
||||
"rosidl_typesupport_cpp"
|
||||
"rosidl_runtime_cpp"
|
||||
"statistics_msgs"
|
||||
"tracetools"
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
${builtin_interfaces_TARGETS}
|
||||
libstatistics_collector::libstatistics_collector
|
||||
rcl::rcl
|
||||
${rcl_interfaces_TARGETS}
|
||||
rcl_yaml_param_parser::rcl_yaml_param_parser
|
||||
rcpputils::rcpputils
|
||||
rcutils::rcutils
|
||||
rmw::rmw
|
||||
${rosgraph_msgs_TARGETS}
|
||||
rosidl_dynamic_typesupport::rosidl_dynamic_typesupport
|
||||
rosidl_runtime_c::rosidl_runtime_c
|
||||
rosidl_runtime_cpp::rosidl_runtime_cpp
|
||||
rosidl_typesupport_cpp::rosidl_typesupport_cpp
|
||||
${statistics_msgs_TARGETS}
|
||||
tracetools::tracetools
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
ament_index_cpp::ament_index_cpp
|
||||
rcl_logging_interface::rcl_logging_interface
|
||||
)
|
||||
|
||||
# Causes the visibility macros to use dllexport rather than dllimport,
|
||||
@@ -237,20 +247,23 @@ ament_export_libraries(${PROJECT_NAME})
|
||||
# Export modern CMake targets
|
||||
ament_export_targets(${PROJECT_NAME})
|
||||
|
||||
# specific order: dependents before dependencies
|
||||
ament_export_dependencies(ament_index_cpp)
|
||||
ament_export_dependencies(libstatistics_collector)
|
||||
ament_export_dependencies(rcl)
|
||||
ament_export_dependencies(rcpputils)
|
||||
ament_export_dependencies(rcutils)
|
||||
ament_export_dependencies(builtin_interfaces)
|
||||
ament_export_dependencies(rosgraph_msgs)
|
||||
ament_export_dependencies(rosidl_typesupport_cpp)
|
||||
ament_export_dependencies(rosidl_typesupport_c)
|
||||
ament_export_dependencies(rosidl_runtime_cpp)
|
||||
ament_export_dependencies(rcl_yaml_param_parser)
|
||||
ament_export_dependencies(statistics_msgs)
|
||||
ament_export_dependencies(tracetools)
|
||||
ament_export_dependencies(
|
||||
builtin_interfaces
|
||||
libstatistics_collector
|
||||
rcl
|
||||
rcl_interfaces
|
||||
rcl_yaml_param_parser
|
||||
rcpputils
|
||||
rcutils
|
||||
rmw
|
||||
rosgraph_msgs
|
||||
rosidl_dynamic_typesupport
|
||||
rosidl_runtime_c
|
||||
rosidl_runtime_cpp
|
||||
rosidl_typesupport_cpp
|
||||
statistics_msgs
|
||||
tracetools
|
||||
)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
find_package(ament_lint_auto REQUIRED)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
The ROS client library in C++.
|
||||
|
||||
Visit the [rclcpp API documentation](http://docs.ros2.org/latest/api/rclcpp/) for a complete list of its main components and features.
|
||||
The link to the latest rclcpp API documentation, which includes a complete list of its main components and features, can be found on the rclcpp package info page, at the [ROS Index](https://index.ros.org/p/rclcpp/).
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "rclcpp/detail/subscription_callback_type_helper.hpp"
|
||||
#include "rclcpp/function_traits.hpp"
|
||||
#include "rclcpp/message_info.hpp"
|
||||
#include "rclcpp/serialization.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
#include "rclcpp/type_adapter.hpp"
|
||||
|
||||
@@ -158,13 +159,14 @@ struct AnySubscriptionCallbackPossibleTypes
|
||||
template<
|
||||
typename MessageT,
|
||||
typename AllocatorT,
|
||||
bool is_adapted_type = rclcpp::TypeAdapter<MessageT>::is_specialized::value
|
||||
bool is_adapted_type = rclcpp::TypeAdapter<MessageT>::is_specialized::value,
|
||||
bool is_serialized_type = serialization_traits::is_serialized_message_class<MessageT>::value
|
||||
>
|
||||
struct AnySubscriptionCallbackHelper;
|
||||
|
||||
/// Specialization for when MessageT is not a TypeAdapter.
|
||||
template<typename MessageT, typename AllocatorT>
|
||||
struct AnySubscriptionCallbackHelper<MessageT, AllocatorT, false>
|
||||
struct AnySubscriptionCallbackHelper<MessageT, AllocatorT, false, false>
|
||||
{
|
||||
using CallbackTypes = AnySubscriptionCallbackPossibleTypes<MessageT, AllocatorT>;
|
||||
|
||||
@@ -194,7 +196,7 @@ struct AnySubscriptionCallbackHelper<MessageT, AllocatorT, false>
|
||||
|
||||
/// Specialization for when MessageT is a TypeAdapter.
|
||||
template<typename MessageT, typename AllocatorT>
|
||||
struct AnySubscriptionCallbackHelper<MessageT, AllocatorT, true>
|
||||
struct AnySubscriptionCallbackHelper<MessageT, AllocatorT, true, false>
|
||||
{
|
||||
using CallbackTypes = AnySubscriptionCallbackPossibleTypes<MessageT, AllocatorT>;
|
||||
|
||||
@@ -232,6 +234,26 @@ struct AnySubscriptionCallbackHelper<MessageT, AllocatorT, true>
|
||||
>;
|
||||
};
|
||||
|
||||
/// Specialization for when MessageT is a SerializedMessage to exclude duplicated declarations.
|
||||
template<typename MessageT, typename AllocatorT>
|
||||
struct AnySubscriptionCallbackHelper<MessageT, AllocatorT, false, true>
|
||||
{
|
||||
using CallbackTypes = AnySubscriptionCallbackPossibleTypes<MessageT, AllocatorT>;
|
||||
|
||||
using variant_type = std::variant<
|
||||
typename CallbackTypes::ConstRefSerializedMessageCallback,
|
||||
typename CallbackTypes::ConstRefSerializedMessageWithInfoCallback,
|
||||
typename CallbackTypes::UniquePtrSerializedMessageCallback,
|
||||
typename CallbackTypes::UniquePtrSerializedMessageWithInfoCallback,
|
||||
typename CallbackTypes::SharedConstPtrSerializedMessageCallback,
|
||||
typename CallbackTypes::SharedConstPtrSerializedMessageWithInfoCallback,
|
||||
typename CallbackTypes::ConstRefSharedConstPtrSerializedMessageCallback,
|
||||
typename CallbackTypes::ConstRefSharedConstPtrSerializedMessageWithInfoCallback,
|
||||
typename CallbackTypes::SharedPtrSerializedMessageCallback,
|
||||
typename CallbackTypes::SharedPtrSerializedMessageWithInfoCallback
|
||||
>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<
|
||||
@@ -487,7 +509,9 @@ public:
|
||||
}
|
||||
|
||||
// Dispatch when input is a ros message and the output could be anything.
|
||||
void
|
||||
template<typename TMsg = ROSMessageType>
|
||||
typename std::enable_if<!serialization_traits::is_serialized_message_class<TMsg>::value,
|
||||
void>::type
|
||||
dispatch(
|
||||
std::shared_ptr<ROSMessageType> message,
|
||||
const rclcpp::MessageInfo & message_info)
|
||||
@@ -589,7 +613,7 @@ public:
|
||||
// Dispatch when input is a serialized message and the output could be anything.
|
||||
void
|
||||
dispatch(
|
||||
std::shared_ptr<rclcpp::SerializedMessage> serialized_message,
|
||||
std::shared_ptr<const rclcpp::SerializedMessage> serialized_message,
|
||||
const rclcpp::MessageInfo & message_info)
|
||||
{
|
||||
TRACETOOLS_TRACEPOINT(callback_start, static_cast<const void *>(this), false);
|
||||
|
||||
82
rclcpp/include/rclcpp/copy_all_parameter_values.hpp
Normal file
82
rclcpp/include/rclcpp/copy_all_parameter_values.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright 2023 Open Navigation LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__COPY_ALL_PARAMETER_VALUES_HPP_
|
||||
#define RCLCPP__COPY_ALL_PARAMETER_VALUES_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl_interfaces/srv/list_parameters.hpp"
|
||||
#include "rcl_interfaces/msg/parameter_descriptor.hpp"
|
||||
#include "rcl_interfaces/msg/set_parameters_result.hpp"
|
||||
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/**
|
||||
* Copy all parameters from one source node to another destination node.
|
||||
* May throw exceptions if parameters from source are uninitialized or undeclared.
|
||||
* \param source Node to copy parameters from
|
||||
* \param destination Node to copy parameters to
|
||||
* \param override_existing_params Default false. Whether to override existing destination params
|
||||
* if both the source and destination contain the same parameter.
|
||||
*/
|
||||
template<typename NodeT1, typename NodeT2>
|
||||
void
|
||||
copy_all_parameter_values(
|
||||
const NodeT1 & source, const NodeT2 & destination, const bool override_existing_params = false)
|
||||
{
|
||||
using Parameters = std::vector<rclcpp::Parameter>;
|
||||
using Descriptions = std::vector<rcl_interfaces::msg::ParameterDescriptor>;
|
||||
auto source_params = source->get_node_parameters_interface();
|
||||
auto dest_params = destination->get_node_parameters_interface();
|
||||
rclcpp::Logger logger = destination->get_node_logging_interface()->get_logger();
|
||||
|
||||
std::vector<std::string> param_names = source_params->list_parameters({}, 0).names;
|
||||
Parameters params = source_params->get_parameters(param_names);
|
||||
Descriptions descriptions = source_params->describe_parameters(param_names);
|
||||
|
||||
for (unsigned int idx = 0; idx != params.size(); idx++) {
|
||||
if (!dest_params->has_parameter(params[idx].get_name())) {
|
||||
dest_params->declare_parameter(
|
||||
params[idx].get_name(), params[idx].get_parameter_value(), descriptions[idx]);
|
||||
} else if (override_existing_params) {
|
||||
try {
|
||||
rcl_interfaces::msg::SetParametersResult result =
|
||||
dest_params->set_parameters_atomically({params[idx]});
|
||||
if (!result.successful) {
|
||||
// Parameter update rejected or read-only
|
||||
RCLCPP_WARN(
|
||||
logger,
|
||||
"Unable to set parameter (%s): %s!",
|
||||
params[idx].get_name().c_str(), result.reason.c_str());
|
||||
}
|
||||
} catch (const rclcpp::exceptions::InvalidParameterTypeException & e) {
|
||||
RCLCPP_WARN(
|
||||
logger,
|
||||
"Unable to set parameter (%s): incompatable parameter type (%s)!",
|
||||
params[idx].get_name().c_str(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__COPY_ALL_PARAMETER_VALUES_HPP_
|
||||
@@ -45,13 +45,15 @@ namespace rclcpp
|
||||
* Not all publisher options are currently respected, the only relevant options for this
|
||||
* publisher are `event_callbacks`, `use_default_callbacks`, and `%callback_group`.
|
||||
*/
|
||||
template<typename AllocatorT = std::allocator<void>>
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename AllocatorT = std::allocator<void>>
|
||||
std::shared_ptr<GenericSubscription> create_generic_subscription(
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr topics_interface,
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> callback,
|
||||
CallbackT && callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
)
|
||||
@@ -60,13 +62,20 @@ std::shared_ptr<GenericSubscription> create_generic_subscription(
|
||||
auto ts_lib = rclcpp::get_typesupport_library(
|
||||
topic_type, "rosidl_typesupport_cpp");
|
||||
|
||||
auto allocator = options.get_allocator();
|
||||
|
||||
using rclcpp::AnySubscriptionCallback;
|
||||
AnySubscriptionCallback<rclcpp::SerializedMessage, AllocatorT>
|
||||
any_subscription_callback(*allocator);
|
||||
any_subscription_callback.set(std::forward<CallbackT>(callback));
|
||||
|
||||
auto subscription = std::make_shared<GenericSubscription>(
|
||||
topics_interface->get_node_base_interface(),
|
||||
std::move(ts_lib),
|
||||
topic_name,
|
||||
topic_type,
|
||||
qos,
|
||||
callback,
|
||||
any_subscription_callback,
|
||||
options);
|
||||
|
||||
topics_interface->add_subscription(subscription, options.callback_group);
|
||||
|
||||
@@ -50,8 +50,8 @@ template<
|
||||
typename SubscriptionT,
|
||||
typename MessageMemoryStrategyT,
|
||||
typename NodeParametersT,
|
||||
typename NodeTopicsT,
|
||||
typename ROSMessageType = typename SubscriptionT::ROSMessageType>
|
||||
typename NodeTopicsT
|
||||
>
|
||||
typename std::shared_ptr<SubscriptionT>
|
||||
create_subscription(
|
||||
NodeParametersT & node_parameters,
|
||||
@@ -70,7 +70,7 @@ create_subscription(
|
||||
using rclcpp::node_interfaces::get_node_topics_interface;
|
||||
auto node_topics_interface = get_node_topics_interface(node_topics);
|
||||
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>>
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics>
|
||||
subscription_topic_stats = nullptr;
|
||||
|
||||
if (rclcpp::detail::resolve_enable_topic_statistics(
|
||||
@@ -80,8 +80,7 @@ create_subscription(
|
||||
if (options.topic_stats_options.publish_period <= std::chrono::milliseconds(0)) {
|
||||
throw std::invalid_argument(
|
||||
"topic_stats_options.publish_period must be greater than 0, specified value of " +
|
||||
std::to_string(options.topic_stats_options.publish_period.count()) +
|
||||
" ms");
|
||||
std::to_string(options.topic_stats_options.publish_period.count()) + " ms");
|
||||
}
|
||||
|
||||
std::shared_ptr<Publisher<statistics_msgs::msg::MetricsMessage>>
|
||||
@@ -89,14 +88,14 @@ create_subscription(
|
||||
node_parameters,
|
||||
node_topics_interface,
|
||||
options.topic_stats_options.publish_topic,
|
||||
qos);
|
||||
options.topic_stats_options.qos);
|
||||
|
||||
subscription_topic_stats = std::make_shared<
|
||||
rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>
|
||||
>(node_topics_interface->get_node_base_interface()->get_name(), publisher);
|
||||
subscription_topic_stats =
|
||||
std::make_shared<rclcpp::topic_statistics::SubscriptionTopicStatistics>(
|
||||
node_topics_interface->get_node_base_interface()->get_name(), publisher);
|
||||
|
||||
std::weak_ptr<
|
||||
rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>
|
||||
rclcpp::topic_statistics::SubscriptionTopicStatistics
|
||||
> weak_subscription_topic_stats(subscription_topic_stats);
|
||||
auto sub_call_back = [weak_subscription_topic_stats]() {
|
||||
auto subscription_topic_stats = weak_subscription_topic_stats.lock();
|
||||
|
||||
@@ -260,6 +260,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
~EventHandler()
|
||||
{
|
||||
// Since the rmw event listener holds a reference to the
|
||||
// "on ready" callback, we need to clear it on destruction of this class.
|
||||
// This clearing is not needed for other rclcpp entities like pub/subs, since
|
||||
// they do own the underlying rmw entities, which are destroyed
|
||||
// on their rclcpp destructors, thus no risk of dangling pointers.
|
||||
clear_on_ready_callback();
|
||||
}
|
||||
|
||||
/// Take data so that the callback cannot be scheduled again
|
||||
std::shared_ptr<void>
|
||||
take_data() override
|
||||
|
||||
@@ -467,7 +467,7 @@ private:
|
||||
auto ptr = MessageAllocTraits::allocate(allocator, 1);
|
||||
MessageAllocTraits::construct(allocator, ptr, *message);
|
||||
|
||||
subscription->provide_intra_process_data(std::move(MessageUniquePtr(ptr, deleter)));
|
||||
subscription->provide_intra_process_data(MessageUniquePtr(ptr, deleter));
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -486,13 +486,13 @@ private:
|
||||
"subscription use different allocator types, which is not supported");
|
||||
}
|
||||
|
||||
if constexpr (rclcpp::TypeAdapter<MessageT>::is_specialized::value) {
|
||||
if constexpr (rclcpp::TypeAdapter<MessageT, ROSMessageType>::is_specialized::value) {
|
||||
ROSMessageTypeAllocator ros_message_alloc(allocator);
|
||||
auto ptr = ros_message_alloc.allocate(1);
|
||||
ros_message_alloc.construct(ptr);
|
||||
auto ptr = ROSMessageTypeAllocatorTraits::allocate(ros_message_alloc, 1);
|
||||
ROSMessageTypeAllocatorTraits::construct(ros_message_alloc, ptr);
|
||||
ROSMessageTypeDeleter deleter;
|
||||
allocator::set_allocator_for_deleter(&deleter, &allocator);
|
||||
rclcpp::TypeAdapter<MessageT>::convert_to_ros_message(*message, *ptr);
|
||||
rclcpp::TypeAdapter<MessageT, ROSMessageType>::convert_to_ros_message(*message, *ptr);
|
||||
auto ros_msg = std::unique_ptr<ROSMessageType, ROSMessageTypeDeleter>(ptr, deleter);
|
||||
ros_message_subscription->provide_intra_process_message(std::move(ros_msg));
|
||||
} else {
|
||||
@@ -510,7 +510,7 @@ private:
|
||||
MessageAllocTraits::construct(allocator, ptr, *message);
|
||||
|
||||
ros_message_subscription->provide_intra_process_message(
|
||||
std::move(MessageUniquePtr(ptr, deleter)));
|
||||
MessageUniquePtr(ptr, deleter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,7 +527,7 @@ private:
|
||||
void execute_ready_timers_unsafe();
|
||||
|
||||
// Callback to be called when timer is ready
|
||||
std::function<void(const rclcpp::TimerBase *)> on_ready_callback_ = nullptr;
|
||||
std::function<void(const rclcpp::TimerBase *)> on_ready_callback_;
|
||||
|
||||
// Thread used to run the timers execution task
|
||||
std::thread timers_thread_;
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
: rclcpp::PublisherBase(
|
||||
node_base,
|
||||
topic_name,
|
||||
*rclcpp::get_typesupport_handle(topic_type, "rosidl_typesupport_cpp", *ts_lib),
|
||||
*rclcpp::get_message_typesupport_handle(topic_type, "rosidl_typesupport_cpp", *ts_lib),
|
||||
options.template to_rcl_publisher_options<rclcpp::SerializedMessage>(qos),
|
||||
// NOTE(methylDragon): Passing these args separately is necessary for event binding
|
||||
options.event_callbacks,
|
||||
|
||||
@@ -74,18 +74,21 @@ public:
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
// TODO(nnmm): Add variant for callback with message info. See issue #1604.
|
||||
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> callback,
|
||||
AnySubscriptionCallback<rclcpp::SerializedMessage, AllocatorT> callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options)
|
||||
: SubscriptionBase(
|
||||
node_base,
|
||||
*rclcpp::get_typesupport_handle(topic_type, "rosidl_typesupport_cpp", *ts_lib),
|
||||
*rclcpp::get_message_typesupport_handle(topic_type, "rosidl_typesupport_cpp", *ts_lib),
|
||||
topic_name,
|
||||
options.to_rcl_subscription_options(qos),
|
||||
options.event_callbacks,
|
||||
options.use_default_callbacks,
|
||||
DeliveredMessageKind::SERIALIZED_MESSAGE),
|
||||
callback_(callback),
|
||||
callback_([callback](
|
||||
std::shared_ptr<const rclcpp::SerializedMessage> serialized_message,
|
||||
const rclcpp::MessageInfo & message_info) mutable {
|
||||
callback.dispatch(serialized_message, message_info);
|
||||
}),
|
||||
ts_lib_(ts_lib)
|
||||
{}
|
||||
|
||||
@@ -151,7 +154,9 @@ public:
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(GenericSubscription)
|
||||
|
||||
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> callback_;
|
||||
std::function<void(
|
||||
std::shared_ptr<const rclcpp::SerializedMessage>,
|
||||
const rclcpp::MessageInfo)> callback_;
|
||||
// The type support library should stay loaded, so it is stored in the GenericSubscription
|
||||
std::shared_ptr<rcpputils::SharedLibrary> ts_lib_;
|
||||
};
|
||||
|
||||
@@ -126,9 +126,6 @@ private:
|
||||
std::shared_ptr<std::pair<std::string, std::string>> logger_sublogger_pairname_ = nullptr;
|
||||
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
Logger(const Logger &) = default;
|
||||
|
||||
/// Get the name of this logger.
|
||||
/**
|
||||
* \return the full name of the logger including any prefixes, or
|
||||
|
||||
@@ -358,12 +358,14 @@ public:
|
||||
* `%callback_group`.
|
||||
* \return Shared pointer to the created generic subscription.
|
||||
*/
|
||||
template<typename AllocatorT = std::allocator<void>>
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename AllocatorT = std::allocator<void>>
|
||||
std::shared_ptr<rclcpp::GenericSubscription> create_generic_subscription(
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> callback,
|
||||
CallbackT && callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options = (
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>()
|
||||
)
|
||||
@@ -972,7 +974,16 @@ public:
|
||||
|
||||
/// Return a list of parameters with any of the given prefixes, up to the given depth.
|
||||
/**
|
||||
* \todo: properly document and test this method.
|
||||
* Parameters are separated into a hierarchy using the "." (dot) character.
|
||||
* The "prefixes" argument is a way to select only particular parts of the hierarchy.
|
||||
*
|
||||
* \param[in] prefixes The list of prefixes that should be searched for within the
|
||||
* current parameters. If this vector of prefixes is empty, then list_parameters
|
||||
* will return all parameters.
|
||||
* \param[in] depth An unsigned integer that represents the recursive depth to search.
|
||||
* If this depth = 0, then all parameters that fit the prefixes will be returned.
|
||||
* \returns A ListParametersResult message which contains both an array of unique prefixes
|
||||
* and an array of names that were matched to the prefixes given.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
rcl_interfaces::msg::ListParametersResult
|
||||
@@ -1305,6 +1316,26 @@ public:
|
||||
size_t
|
||||
count_subscribers(const std::string & topic_name) const;
|
||||
|
||||
/// Return the number of clients created for a given service.
|
||||
/**
|
||||
* \param[in] service_name the actual service name used; it will not be automatically remapped.
|
||||
* \return number of clients that have been created for the given service.
|
||||
* \throws std::runtime_error if clients could not be counted
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_clients(const std::string & service_name) const;
|
||||
|
||||
/// Return the number of services created for a given service.
|
||||
/**
|
||||
* \param[in] service_name the actual service name used; it will not be automatically remapped.
|
||||
* \return number of services that have been created for the given service.
|
||||
* \throws std::runtime_error if services could not be counted
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_services(const std::string & service_name) const;
|
||||
|
||||
/// Return the topic endpoint information about publishers on a given topic.
|
||||
/**
|
||||
* The returned parameter is a list of topic endpoint information, where each item will contain
|
||||
|
||||
@@ -221,13 +221,13 @@ Node::create_generic_publisher(
|
||||
);
|
||||
}
|
||||
|
||||
template<typename AllocatorT>
|
||||
template<typename CallbackT, typename AllocatorT>
|
||||
std::shared_ptr<rclcpp::GenericSubscription>
|
||||
Node::create_generic_subscription(
|
||||
const std::string & topic_name,
|
||||
const std::string & topic_type,
|
||||
const rclcpp::QoS & qos,
|
||||
std::function<void(std::shared_ptr<rclcpp::SerializedMessage>)> callback,
|
||||
CallbackT && callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options)
|
||||
{
|
||||
return rclcpp::create_generic_subscription(
|
||||
@@ -235,7 +235,7 @@ Node::create_generic_subscription(
|
||||
extend_name_with_sub_namespace(topic_name, this->get_sub_namespace()),
|
||||
topic_type,
|
||||
qos,
|
||||
std::move(callback),
|
||||
std::forward<CallbackT>(callback),
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,6 +113,14 @@ public:
|
||||
size_t
|
||||
count_subscribers(const std::string & topic_name) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_clients(const std::string & service_name) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
size_t
|
||||
count_services(const std::string & service_name) const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rcl_guard_condition_t *
|
||||
get_graph_guard_condition() const override;
|
||||
|
||||
@@ -305,6 +305,24 @@ public:
|
||||
size_t
|
||||
count_subscribers(const std::string & topic_name) const = 0;
|
||||
|
||||
/// Return the number of clients created for a given service.
|
||||
/*
|
||||
* \param[in] service_name the actual service name used; it will not be automatically remapped.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
size_t
|
||||
count_clients(const std::string & service_name) const = 0;
|
||||
|
||||
/// Return the number of services created for a given service.
|
||||
/*
|
||||
* \param[in] service_name the actual service name used; it will not be automatically remapped.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
size_t
|
||||
count_services(const std::string & service_name) const = 0;
|
||||
|
||||
/// Return the rcl guard condition which is triggered when the ROS graph changes.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
|
||||
@@ -43,6 +43,7 @@ public:
|
||||
* - arguments = {}
|
||||
* - parameter_overrides = {}
|
||||
* - use_global_arguments = true
|
||||
* - enable_rosout = true
|
||||
* - use_intra_process_comms = false
|
||||
* - enable_topic_statistics = false
|
||||
* - start_parameter_services = true
|
||||
|
||||
@@ -390,7 +390,7 @@ public:
|
||||
if (this->can_loan_messages()) {
|
||||
// we release the ownership from the rclpp::LoanedMessage instance
|
||||
// and let the middleware clean up the memory.
|
||||
this->do_loaned_message_publish(std::move(loaned_msg.release()));
|
||||
this->do_loaned_message_publish(loaned_msg.release());
|
||||
} else {
|
||||
// we don't release the ownership, let the middleware copy the ros message
|
||||
// and thus the destructor of rclcpp::LoanedMessage cleans up the memory.
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
#include "rclcpp/clock.hpp"
|
||||
#include "rclcpp/duration.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/utilities.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
@@ -31,9 +33,20 @@ class RateBase
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(RateBase)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~RateBase() {}
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual bool sleep() = 0;
|
||||
|
||||
[[deprecated("use get_type() instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
virtual bool is_steady() const = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual rcl_clock_type_t get_type() const = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
||||
@@ -42,14 +55,13 @@ using std::chrono::duration_cast;
|
||||
using std::chrono::nanoseconds;
|
||||
|
||||
template<class Clock = std::chrono::high_resolution_clock>
|
||||
class GenericRate : public RateBase
|
||||
class [[deprecated("use rclcpp::Rate class instead of GenericRate")]] GenericRate : public RateBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(GenericRate)
|
||||
|
||||
explicit GenericRate(double rate)
|
||||
: GenericRate<Clock>(
|
||||
duration_cast<nanoseconds>(duration<double>(1.0 / rate)))
|
||||
: period_(duration_cast<nanoseconds>(duration<double>(1.0 / rate))), last_interval_(Clock::now())
|
||||
{}
|
||||
explicit GenericRate(std::chrono::nanoseconds period)
|
||||
: period_(period), last_interval_(Clock::now())
|
||||
@@ -87,12 +99,18 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
[[deprecated("use get_type() instead")]]
|
||||
virtual bool
|
||||
is_steady() const
|
||||
{
|
||||
return Clock::is_steady;
|
||||
}
|
||||
|
||||
virtual rcl_clock_type_t get_type() const
|
||||
{
|
||||
return Clock::is_steady ? RCL_STEADY_TIME : RCL_SYSTEM_TIME;
|
||||
}
|
||||
|
||||
virtual void
|
||||
reset()
|
||||
{
|
||||
@@ -112,8 +130,59 @@ private:
|
||||
std::chrono::time_point<Clock, ClockDurationNano> last_interval_;
|
||||
};
|
||||
|
||||
using Rate = GenericRate<std::chrono::system_clock>;
|
||||
using WallRate = GenericRate<std::chrono::steady_clock>;
|
||||
class Rate : public RateBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(Rate)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit Rate(
|
||||
const double rate,
|
||||
Clock::SharedPtr clock = std::make_shared<Clock>(RCL_SYSTEM_TIME));
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit Rate(
|
||||
const Duration & period,
|
||||
Clock::SharedPtr clock = std::make_shared<Clock>(RCL_SYSTEM_TIME));
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual bool
|
||||
sleep();
|
||||
|
||||
[[deprecated("use get_type() instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
virtual bool
|
||||
is_steady() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual rcl_clock_type_t
|
||||
get_type() const;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual void
|
||||
reset();
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::chrono::nanoseconds
|
||||
period() const;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(Rate)
|
||||
|
||||
Clock::SharedPtr clock_;
|
||||
Duration period_;
|
||||
Time last_interval_;
|
||||
};
|
||||
|
||||
class WallRate : public Rate
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
explicit WallRate(const double rate);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit WallRate(const Duration & period);
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
* - rclcpp::ParameterValue
|
||||
* - rclcpp::AsyncParametersClient
|
||||
* - rclcpp::SyncParametersClient
|
||||
* - rclcpp::copy_all_parameter_values()
|
||||
* - rclcpp/parameter.hpp
|
||||
* - rclcpp/parameter_value.hpp
|
||||
* - rclcpp/parameter_client.hpp
|
||||
@@ -95,6 +96,9 @@
|
||||
* - Get the number of publishers or subscribers on a topic:
|
||||
* - rclcpp::Node::count_publishers()
|
||||
* - rclcpp::Node::count_subscribers()
|
||||
* - Get the number of clients or servers on a service:
|
||||
* - rclcpp::Node::count_clients()
|
||||
* - rclcpp::Node::count_services()
|
||||
*
|
||||
* And components related to logging:
|
||||
*
|
||||
@@ -164,6 +168,7 @@
|
||||
#include <csignal>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/copy_all_parameter_values.hpp"
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rclcpp/guard_condition.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
|
||||
@@ -15,10 +15,17 @@
|
||||
#ifndef RCLCPP__STRATEGIES__MESSAGE_POOL_MEMORY_STRATEGY_HPP_
|
||||
#define RCLCPP__STRATEGIES__MESSAGE_POOL_MEMORY_STRATEGY_HPP_
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rosidl_runtime_cpp/traits.hpp"
|
||||
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/message_memory_strategy.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
@@ -50,13 +57,24 @@ class MessagePoolMemoryStrategy
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(MessagePoolMemoryStrategy)
|
||||
|
||||
/// Default constructor
|
||||
MessagePoolMemoryStrategy()
|
||||
: next_array_index_(0)
|
||||
{
|
||||
pool_mutex_ = std::make_shared<std::mutex>();
|
||||
|
||||
pool_ = std::shared_ptr<std::array<MessageT *, Size>>(
|
||||
new std::array<MessageT *, Size>,
|
||||
[](std::array<MessageT *, Size> * arr) {
|
||||
for (size_t i = 0; i < Size; ++i) {
|
||||
free((*arr)[i]);
|
||||
}
|
||||
delete arr;
|
||||
});
|
||||
|
||||
free_list_ = std::make_shared<CircularArray<Size>>();
|
||||
|
||||
for (size_t i = 0; i < Size; ++i) {
|
||||
pool_[i].msg_ptr_ = std::make_shared<MessageT>();
|
||||
pool_[i].used = false;
|
||||
(*pool_)[i] = static_cast<MessageT *>(malloc(sizeof(MessageT)));
|
||||
free_list_->push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,43 +86,85 @@ public:
|
||||
*/
|
||||
std::shared_ptr<MessageT> borrow_message()
|
||||
{
|
||||
size_t current_index = next_array_index_;
|
||||
next_array_index_ = (next_array_index_ + 1) % Size;
|
||||
if (pool_[current_index].used) {
|
||||
throw std::runtime_error("Tried to access message that was still in use! Abort.");
|
||||
std::lock_guard<std::mutex> lock(*pool_mutex_);
|
||||
if (free_list_->size() == 0) {
|
||||
throw std::runtime_error("No more free slots in the pool");
|
||||
}
|
||||
pool_[current_index].msg_ptr_->~MessageT();
|
||||
new (pool_[current_index].msg_ptr_.get())MessageT;
|
||||
|
||||
pool_[current_index].used = true;
|
||||
return pool_[current_index].msg_ptr_;
|
||||
size_t current_index = free_list_->pop_front();
|
||||
|
||||
return std::shared_ptr<MessageT>(
|
||||
new((*pool_)[current_index]) MessageT(),
|
||||
[pool = this->pool_, pool_mutex = this->pool_mutex_,
|
||||
free_list = this->free_list_](MessageT * p) {
|
||||
std::lock_guard<std::mutex> lock(*pool_mutex);
|
||||
for (size_t i = 0; i < Size; ++i) {
|
||||
if ((*pool)[i] == p) {
|
||||
p->~MessageT();
|
||||
free_list->push_back(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Return a message to the message pool.
|
||||
/**
|
||||
* Manage metadata in the message pool ring buffer to release the message.
|
||||
* This does nothing since the message isn't returned to the pool until the user has dropped
|
||||
* all references.
|
||||
* \param[in] msg Shared pointer to the message to return.
|
||||
*/
|
||||
void return_message(std::shared_ptr<MessageT> & msg)
|
||||
{
|
||||
for (size_t i = 0; i < Size; ++i) {
|
||||
if (pool_[i].msg_ptr_ == msg) {
|
||||
pool_[i].used = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("Unrecognized message ptr in return_message.");
|
||||
(void)msg;
|
||||
}
|
||||
|
||||
protected:
|
||||
struct PoolMember
|
||||
template<size_t N>
|
||||
class CircularArray
|
||||
{
|
||||
std::shared_ptr<MessageT> msg_ptr_;
|
||||
bool used;
|
||||
public:
|
||||
void push_back(const size_t v)
|
||||
{
|
||||
if (size_ + 1 > N) {
|
||||
throw std::runtime_error("Tried to push too many items into the array");
|
||||
}
|
||||
array_[(front_ + size_) % N] = v;
|
||||
++size_;
|
||||
}
|
||||
|
||||
size_t pop_front()
|
||||
{
|
||||
if (size_ < 1) {
|
||||
throw std::runtime_error("Tried to pop item from empty array");
|
||||
}
|
||||
|
||||
size_t val = array_[front_];
|
||||
|
||||
front_ = (front_ + 1) % N;
|
||||
--size_;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t front_ = 0;
|
||||
size_t size_ = 0;
|
||||
std::array<size_t, N> array_;
|
||||
};
|
||||
|
||||
std::array<PoolMember, Size> pool_;
|
||||
size_t next_array_index_;
|
||||
// It's very important that these are shared_ptrs, since users of this class might hold a
|
||||
// reference to a pool item longer than the lifetime of the class. In that scenario, the
|
||||
// shared_ptr ensures that the lifetime of these variables outlives this class, and hence ensures
|
||||
// the custom destructor for each pool item can successfully run.
|
||||
std::shared_ptr<std::mutex> pool_mutex_;
|
||||
std::shared_ptr<std::array<MessageT *, Size>> pool_;
|
||||
std::shared_ptr<CircularArray<Size>> free_list_;
|
||||
};
|
||||
|
||||
} // namespace message_pool_memory_strategy
|
||||
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
|
||||
private:
|
||||
using SubscriptionTopicStatisticsSharedPtr =
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>>;
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics>;
|
||||
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(Subscription)
|
||||
@@ -316,7 +316,7 @@ public:
|
||||
if (subscription_topic_statistics_) {
|
||||
const auto nanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(now);
|
||||
const auto time = rclcpp::Time(nanos.time_since_epoch().count());
|
||||
subscription_topic_statistics_->handle_message(*typed_message, time);
|
||||
subscription_topic_statistics_->handle_message(message_info.get_rmw_message_info(), time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,8 +325,20 @@ public:
|
||||
const std::shared_ptr<rclcpp::SerializedMessage> & serialized_message,
|
||||
const rclcpp::MessageInfo & message_info) override
|
||||
{
|
||||
// TODO(wjwwood): enable topic statistics for serialized messages
|
||||
std::chrono::time_point<std::chrono::system_clock> now;
|
||||
if (subscription_topic_statistics_) {
|
||||
// get current time before executing callback to
|
||||
// exclude callback duration from topic statistics result.
|
||||
now = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
any_callback_.dispatch(serialized_message, message_info);
|
||||
|
||||
if (subscription_topic_statistics_) {
|
||||
const auto nanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(now);
|
||||
const auto time = rclcpp::Time(nanos.time_since_epoch().count());
|
||||
subscription_topic_statistics_->handle_message(message_info.get_rmw_message_info(), time);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -357,7 +369,7 @@ public:
|
||||
if (subscription_topic_statistics_) {
|
||||
const auto nanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(now);
|
||||
const auto time = rclcpp::Time(nanos.time_since_epoch().count());
|
||||
subscription_topic_statistics_->handle_message(*typed_message, time);
|
||||
subscription_topic_statistics_->handle_message(message_info.get_rmw_message_info(), time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,15 +75,14 @@ template<
|
||||
typename CallbackT,
|
||||
typename AllocatorT,
|
||||
typename SubscriptionT = rclcpp::Subscription<MessageT, AllocatorT>,
|
||||
typename MessageMemoryStrategyT = typename SubscriptionT::MessageMemoryStrategyType,
|
||||
typename ROSMessageType = typename SubscriptionT::ROSMessageType
|
||||
typename MessageMemoryStrategyT = typename SubscriptionT::MessageMemoryStrategyType
|
||||
>
|
||||
SubscriptionFactory
|
||||
create_subscription_factory(
|
||||
CallbackT && callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
|
||||
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat,
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<ROSMessageType>>
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics>
|
||||
subscription_topic_stats = nullptr
|
||||
)
|
||||
{
|
||||
|
||||
@@ -77,6 +77,10 @@ struct SubscriptionOptionsBase
|
||||
// Topic statistics publication period in ms. Defaults to one second.
|
||||
// Only values greater than zero are allowed.
|
||||
std::chrono::milliseconds publish_period{std::chrono::seconds(1)};
|
||||
|
||||
// An optional QoS which can provide topic_statistics with a stable QoS separate from
|
||||
// the subscription's current QoS settings which could be unstable.
|
||||
rclcpp::QoS qos = SystemDefaultsQoS();
|
||||
};
|
||||
|
||||
TopicStatisticsOptions topic_stats_options;
|
||||
|
||||
@@ -189,7 +189,7 @@ public:
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
static Time
|
||||
max();
|
||||
max(rcl_clock_type_t clock_type = RCL_SYSTEM_TIME); // NOLINT
|
||||
|
||||
/// Get the seconds since epoch
|
||||
/**
|
||||
|
||||
@@ -48,21 +48,12 @@ using libstatistics_collector::moving_average_statistics::StatisticData;
|
||||
/**
|
||||
* Class used to collect, measure, and publish topic statistics data. Current statistics
|
||||
* supported for subscribers are received message age and received message period.
|
||||
*
|
||||
* \tparam CallbackMessageT the subscribed message type
|
||||
*/
|
||||
template<typename CallbackMessageT>
|
||||
*/
|
||||
class SubscriptionTopicStatistics
|
||||
{
|
||||
using TopicStatsCollector =
|
||||
libstatistics_collector::topic_statistics_collector::TopicStatisticsCollector<
|
||||
CallbackMessageT>;
|
||||
using ReceivedMessageAge =
|
||||
libstatistics_collector::topic_statistics_collector::ReceivedMessageAgeCollector<
|
||||
CallbackMessageT>;
|
||||
using ReceivedMessagePeriod =
|
||||
libstatistics_collector::topic_statistics_collector::ReceivedMessagePeriodCollector<
|
||||
CallbackMessageT>;
|
||||
using TopicStatsCollector = libstatistics_collector::TopicStatisticsCollector;
|
||||
using ReceivedMessageAge = libstatistics_collector::ReceivedMessageAgeCollector;
|
||||
using ReceivedMessagePeriod = libstatistics_collector::ReceivedMessagePeriodCollector;
|
||||
|
||||
public:
|
||||
/// Construct a SubscriptionTopicStatistics object.
|
||||
@@ -101,16 +92,16 @@ public:
|
||||
/**
|
||||
* This method acquires a lock to prevent race conditions to collectors list.
|
||||
*
|
||||
* \param received_message the message received by the subscription
|
||||
* \param message_info the message info corresponding to the received message
|
||||
* \param now_nanoseconds current time in nanoseconds
|
||||
*/
|
||||
virtual void handle_message(
|
||||
const CallbackMessageT & received_message,
|
||||
const rmw_message_info_t & message_info,
|
||||
const rclcpp::Time now_nanoseconds) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
for (const auto & collector : subscriber_statistics_collectors_) {
|
||||
collector->OnMessageReceived(received_message, now_nanoseconds.nanoseconds());
|
||||
collector->OnMessageReceived(message_info, now_nanoseconds.nanoseconds());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "rcpputils/shared_library.hpp"
|
||||
#include "rosidl_runtime_cpp/message_type_support_decl.hpp"
|
||||
#include "rosidl_runtime_cpp/service_type_support_decl.hpp"
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
@@ -40,11 +41,15 @@ get_typesupport_library(const std::string & type, const std::string & typesuppor
|
||||
/// Extract the 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.
|
||||
*
|
||||
* \deprecated Use get_message_typesupport_handle() instead
|
||||
*
|
||||
* \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
|
||||
* \return A type support handle
|
||||
*/
|
||||
[[deprecated("Use `get_message_typesupport_handle` instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_message_type_support_t *
|
||||
get_typesupport_handle(
|
||||
@@ -52,6 +57,40 @@ get_typesupport_handle(
|
||||
const std::string & typesupport_identifier,
|
||||
rcpputils::SharedLibrary & library);
|
||||
|
||||
/// 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(
|
||||
const std::string & type,
|
||||
const std::string & typesupport_identifier,
|
||||
rcpputils::SharedLibrary & library);
|
||||
|
||||
/// Extract the service 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 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(
|
||||
const std::string & type,
|
||||
const std::string & typesupport_identifier,
|
||||
rcpputils::SharedLibrary & library);
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__TYPESUPPORT_HELPERS_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</name>
|
||||
<version>22.1.0</version>
|
||||
<version>25.0.0</version>
|
||||
<description>The ROS client library in C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
@@ -22,6 +22,7 @@
|
||||
<build_depend>builtin_interfaces</build_depend>
|
||||
<build_depend>rcl_interfaces</build_depend>
|
||||
<build_depend>rosgraph_msgs</build_depend>
|
||||
<build_depend>rosidl_runtime_c</build_depend>
|
||||
<build_depend>rosidl_runtime_cpp</build_depend>
|
||||
<build_depend>rosidl_typesupport_c</build_depend>
|
||||
<build_depend>rosidl_typesupport_cpp</build_depend>
|
||||
@@ -29,12 +30,14 @@
|
||||
<build_export_depend>builtin_interfaces</build_export_depend>
|
||||
<build_export_depend>rcl_interfaces</build_export_depend>
|
||||
<build_export_depend>rosgraph_msgs</build_export_depend>
|
||||
<build_export_depend>rosidl_runtime_c</build_export_depend>
|
||||
<build_export_depend>rosidl_runtime_cpp</build_export_depend>
|
||||
<build_export_depend>rosidl_typesupport_c</build_export_depend>
|
||||
<build_export_depend>rosidl_typesupport_cpp</build_export_depend>
|
||||
|
||||
<depend>libstatistics_collector</depend>
|
||||
<depend>rcl</depend>
|
||||
<depend>rcl_logging_interface</depend>
|
||||
<depend>rcl_yaml_param_parser</depend>
|
||||
<depend>rcpputils</depend>
|
||||
<depend>rcutils</depend>
|
||||
|
||||
@@ -125,7 +125,6 @@ bool
|
||||
ClientBase::wait_for_service_nanoseconds(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
// make an event to reuse, rather than create a new one each time
|
||||
auto node_ptr = node_graph_.lock();
|
||||
if (!node_ptr) {
|
||||
throw InvalidNodeError();
|
||||
@@ -138,6 +137,7 @@ ClientBase::wait_for_service_nanoseconds(std::chrono::nanoseconds timeout)
|
||||
// check was non-blocking, return immediately
|
||||
return false;
|
||||
}
|
||||
// make an event to reuse, rather than create a new one each time
|
||||
auto event = node_ptr->get_graph_event();
|
||||
// update the time even on the first loop to account for time spent in the first call
|
||||
// to this->server_is_ready()
|
||||
|
||||
@@ -462,7 +462,7 @@ template<Context::ShutdownType shutdown_type>
|
||||
std::vector<rclcpp::Context::ShutdownCallback>
|
||||
Context::get_shutdown_callback() const
|
||||
{
|
||||
const auto get_callback_vector = [this](auto & mutex, auto & callback_set) {
|
||||
const auto get_callback_vector = [](auto & mutex, auto & callback_set) {
|
||||
const std::lock_guard<std::mutex> lock(mutex);
|
||||
std::vector<rclcpp::Context::ShutdownCallback> callbacks;
|
||||
for (auto & callback : callback_set) {
|
||||
@@ -496,7 +496,7 @@ Context::sleep_for(const std::chrono::nanoseconds & nanoseconds)
|
||||
std::unique_lock<std::mutex> lock(interrupt_mutex_);
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
// this will release the lock while waiting
|
||||
interrupt_condition_variable_.wait_for(lock, nanoseconds);
|
||||
interrupt_condition_variable_.wait_for(lock, time_left);
|
||||
time_left -= std::chrono::steady_clock::now() - start;
|
||||
}
|
||||
} while (time_left > std::chrono::nanoseconds::zero() && this->is_valid());
|
||||
|
||||
@@ -39,13 +39,6 @@ UnsupportedEventTypeException::UnsupportedEventTypeException(
|
||||
|
||||
EventHandlerBase::~EventHandlerBase()
|
||||
{
|
||||
// Since the rmw event listener holds a reference to
|
||||
// this callback, we need to clear it on destruction of this class.
|
||||
// This clearing is not needed for other rclcpp entities like pub/subs, since
|
||||
// they do own the underlying rmw entities, which are destroyed
|
||||
// on their rclcpp destructors, thus no risk of dangling pointers.
|
||||
clear_on_ready_callback();
|
||||
|
||||
if (rcl_event_fini(&event_handle_) != RCL_RET_OK) {
|
||||
RCUTILS_LOG_ERROR_NAMED(
|
||||
"rclcpp",
|
||||
|
||||
@@ -669,6 +669,11 @@ Executor::execute_subscription(rclcpp::SubscriptionBase::SharedPtr subscription)
|
||||
subscription->get_topic_name(),
|
||||
[&]() {return subscription->take_type_erased(message.get(), message_info);},
|
||||
[&]() {subscription->handle_message(message, message_info);});
|
||||
// TODO(clalancette): In the case that the user is using the MessageMemoryPool,
|
||||
// and they take a shared_ptr reference to the message in the callback, this can
|
||||
// inadvertently return the message to the pool when the user is still using it.
|
||||
// This is a bug that needs to be fixed in the pool, and we should probably have
|
||||
// a custom deleter for the message that actually does the return_message().
|
||||
subscription->return_message(message);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -28,9 +28,9 @@ using rclcpp::experimental::TimersManager;
|
||||
TimersManager::TimersManager(
|
||||
std::shared_ptr<rclcpp::Context> context,
|
||||
std::function<void(const rclcpp::TimerBase *)> on_ready_callback)
|
||||
: on_ready_callback_(on_ready_callback),
|
||||
context_(context)
|
||||
{
|
||||
context_ = context;
|
||||
on_ready_callback_ = on_ready_callback;
|
||||
}
|
||||
|
||||
TimersManager::~TimersManager()
|
||||
|
||||
@@ -49,9 +49,9 @@ GenericSubscription::handle_message(
|
||||
void
|
||||
GenericSubscription::handle_serialized_message(
|
||||
const std::shared_ptr<rclcpp::SerializedMessage> & message,
|
||||
const rclcpp::MessageInfo &)
|
||||
const rclcpp::MessageInfo & message_info)
|
||||
{
|
||||
callback_(message);
|
||||
callback_(message, message_info);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "rcl_logging_interface/rcl_logging_interface.h"
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/logging_rosout.h"
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
@@ -80,10 +81,12 @@ Logger::get_child(const std::string & suffix)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(*logging_mutex);
|
||||
rcl_ret = rcl_logging_rosout_add_sublogger((*name_).c_str(), suffix.c_str());
|
||||
if (RCL_RET_OK != rcl_ret) {
|
||||
if (RCL_RET_NOT_FOUND == rcl_ret) {
|
||||
rcl_reset_error();
|
||||
} else if (RCL_RET_OK != rcl_ret) {
|
||||
exceptions::throw_from_rcl_error(
|
||||
rcl_ret, "failed to call rcl_logging_rosout_add_sublogger",
|
||||
rcutils_get_error_state(), rcutils_reset_error);
|
||||
rcl_get_error_state(), rcl_reset_error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,9 +101,7 @@ Logger::get_child(const std::string & suffix)
|
||||
logger_sublogger_pairname_ptr->second.c_str());
|
||||
delete logger_sublogger_pairname_ptr;
|
||||
if (RCL_RET_OK != rcl_ret) {
|
||||
exceptions::throw_from_rcl_error(
|
||||
rcl_ret, "failed to call rcl_logging_rosout_remove_sublogger",
|
||||
rcutils_get_error_state(), rcutils_reset_error);
|
||||
rcl_reset_error();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -522,6 +522,18 @@ Node::count_subscribers(const std::string & topic_name) const
|
||||
return node_graph_->count_subscribers(topic_name);
|
||||
}
|
||||
|
||||
size_t
|
||||
Node::count_clients(const std::string & service_name) const
|
||||
{
|
||||
return node_graph_->count_clients(service_name);
|
||||
}
|
||||
|
||||
size_t
|
||||
Node::count_services(const std::string & service_name) const
|
||||
{
|
||||
return node_graph_->count_services(service_name);
|
||||
}
|
||||
|
||||
std::vector<rclcpp::TopicEndpointInfo>
|
||||
Node::get_publishers_info_by_topic(const std::string & topic_name, bool no_mangle) const
|
||||
{
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "rcl/arguments.h"
|
||||
#include "rcl/node_type_cache.h"
|
||||
#include "rcl/logging.h"
|
||||
#include "rcl/logging_rosout.h"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rcutils/logging_macros.h"
|
||||
#include "rmw/validate_namespace.h"
|
||||
@@ -55,17 +57,12 @@ NodeBase::NodeBase(
|
||||
std::shared_ptr<std::recursive_mutex> logging_mutex = get_global_logging_mutex();
|
||||
|
||||
rcl_ret_t ret;
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(*logging_mutex);
|
||||
// TODO(ivanpauno): /rosout Qos should be reconfigurable.
|
||||
// TODO(ivanpauno): Instead of mutually excluding rcl_node_init with the global logger mutex,
|
||||
// rcl_logging_rosout_init_publisher_for_node could be decoupled from there and be called
|
||||
// here directly.
|
||||
ret = rcl_node_init(
|
||||
rcl_node.get(),
|
||||
node_name.c_str(), namespace_.c_str(),
|
||||
context_->get_rcl_context().get(), &rcl_node_options);
|
||||
}
|
||||
|
||||
// TODO(ivanpauno): /rosout Qos should be reconfigurable.
|
||||
ret = rcl_node_init(
|
||||
rcl_node.get(),
|
||||
node_name.c_str(), namespace_.c_str(),
|
||||
context_->get_rcl_context().get(), &rcl_node_options);
|
||||
if (ret != RCL_RET_OK) {
|
||||
if (ret == RCL_RET_NODE_INVALID_NAME) {
|
||||
rcl_reset_error(); // discard rcl_node_init error
|
||||
@@ -115,13 +112,29 @@ NodeBase::NodeBase(
|
||||
throw_from_rcl_error(ret, "failed to initialize rcl node");
|
||||
}
|
||||
|
||||
// The initialization for the rosout publisher
|
||||
if (rcl_logging_rosout_enabled() && rcl_node_options.enable_rosout) {
|
||||
std::lock_guard<std::recursive_mutex> guard(*logging_mutex);
|
||||
ret = rcl_logging_rosout_init_publisher_for_node(rcl_node.get());
|
||||
if (ret != RCL_RET_OK) {
|
||||
throw_from_rcl_error(ret, "failed to initialize rosout publisher");
|
||||
}
|
||||
}
|
||||
|
||||
node_handle_.reset(
|
||||
rcl_node.release(),
|
||||
[logging_mutex](rcl_node_t * node) -> void {
|
||||
std::lock_guard<std::recursive_mutex> guard(*logging_mutex);
|
||||
// TODO(ivanpauno): Instead of mutually excluding rcl_node_fini with the global logger mutex,
|
||||
// rcl_logging_rosout_fini_publisher_for_node could be decoupled from there and be called
|
||||
// here directly.
|
||||
[logging_mutex, rcl_node_options](rcl_node_t * node) -> void {
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(*logging_mutex);
|
||||
if (rcl_logging_rosout_enabled() && rcl_node_options.enable_rosout) {
|
||||
rcl_ret_t ret = rcl_logging_rosout_fini_publisher_for_node(node);
|
||||
if (ret != RCL_RET_OK) {
|
||||
RCUTILS_LOG_ERROR_NAMED(
|
||||
"rclcpp",
|
||||
"Error in destruction of rosout publisher: %s", rcl_get_error_string().str);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rcl_node_fini(node) != RCL_RET_OK) {
|
||||
RCUTILS_LOG_ERROR_NAMED(
|
||||
"rclcpp",
|
||||
|
||||
@@ -498,6 +498,50 @@ NodeGraph::count_subscribers(const std::string & topic_name) const
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t
|
||||
NodeGraph::count_clients(const std::string & service_name) const
|
||||
{
|
||||
auto rcl_node_handle = node_base_->get_rcl_node_handle();
|
||||
|
||||
auto fqdn = rclcpp::expand_topic_or_service_name(
|
||||
service_name,
|
||||
rcl_node_get_name(rcl_node_handle),
|
||||
rcl_node_get_namespace(rcl_node_handle),
|
||||
true);
|
||||
|
||||
size_t count;
|
||||
auto ret = rcl_count_clients(rcl_node_handle, fqdn.c_str(), &count);
|
||||
if (ret != RMW_RET_OK) {
|
||||
// *INDENT-OFF*
|
||||
throw std::runtime_error(
|
||||
std::string("could not count clients: ") + rmw_get_error_string().str);
|
||||
// *INDENT-ON*
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t
|
||||
NodeGraph::count_services(const std::string & service_name) const
|
||||
{
|
||||
auto rcl_node_handle = node_base_->get_rcl_node_handle();
|
||||
|
||||
auto fqdn = rclcpp::expand_topic_or_service_name(
|
||||
service_name,
|
||||
rcl_node_get_name(rcl_node_handle),
|
||||
rcl_node_get_namespace(rcl_node_handle),
|
||||
true);
|
||||
|
||||
size_t count;
|
||||
auto ret = rcl_count_services(rcl_node_handle, fqdn.c_str(), &count);
|
||||
if (ret != RMW_RET_OK) {
|
||||
// *INDENT-OFF*
|
||||
throw std::runtime_error(
|
||||
std::string("could not count services: ") + rmw_get_error_string().str);
|
||||
// *INDENT-ON*
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
const rcl_guard_condition_t *
|
||||
NodeGraph::get_graph_guard_condition() const
|
||||
{
|
||||
|
||||
@@ -1038,37 +1038,50 @@ NodeParameters::list_parameters(const std::vector<std::string> & prefixes, uint6
|
||||
// TODO(mikaelarguedas) define parameter separator different from "/" to avoid ambiguity
|
||||
// using "." for now
|
||||
const char * separator = ".";
|
||||
for (auto & kv : parameters_) {
|
||||
bool get_all = (prefixes.size() == 0) &&
|
||||
((depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) ||
|
||||
(static_cast<uint64_t>(std::count(kv.first.begin(), kv.first.end(), *separator)) < depth));
|
||||
bool prefix_matches = std::any_of(
|
||||
prefixes.cbegin(), prefixes.cend(),
|
||||
[&kv, &depth, &separator](const std::string & prefix) {
|
||||
if (kv.first == prefix) {
|
||||
return true;
|
||||
} else if (kv.first.find(prefix + separator) == 0) {
|
||||
size_t length = prefix.length();
|
||||
std::string substr = kv.first.substr(length);
|
||||
// Cast as unsigned integer to avoid warning
|
||||
return (depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) ||
|
||||
(static_cast<uint64_t>(std::count(substr.begin(), substr.end(), *separator)) < depth);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (get_all || prefix_matches) {
|
||||
result.names.push_back(kv.first);
|
||||
size_t last_separator = kv.first.find_last_of(separator);
|
||||
if (std::string::npos != last_separator) {
|
||||
std::string prefix = kv.first.substr(0, last_separator);
|
||||
if (
|
||||
std::find(result.prefixes.cbegin(), result.prefixes.cend(), prefix) ==
|
||||
result.prefixes.cend())
|
||||
{
|
||||
result.prefixes.push_back(prefix);
|
||||
|
||||
auto separators_less_than_depth = [&depth, &separator](const std::string & str) -> bool {
|
||||
return static_cast<uint64_t>(std::count(str.begin(), str.end(), *separator)) < depth;
|
||||
};
|
||||
|
||||
bool recursive = (prefixes.size() == 0) &&
|
||||
(depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE);
|
||||
|
||||
for (const std::pair<const std::string, ParameterInfo> & kv : parameters_) {
|
||||
if (!recursive) {
|
||||
bool get_all = (prefixes.size() == 0) && separators_less_than_depth(kv.first);
|
||||
if (!get_all) {
|
||||
bool prefix_matches = std::any_of(
|
||||
prefixes.cbegin(), prefixes.cend(),
|
||||
[&kv, &depth, &separator, &separators_less_than_depth](const std::string & prefix) {
|
||||
if (kv.first == prefix) {
|
||||
return true;
|
||||
} else if (kv.first.find(prefix + separator) == 0) {
|
||||
if (depth == rcl_interfaces::srv::ListParameters::Request::DEPTH_RECURSIVE) {
|
||||
return true;
|
||||
}
|
||||
std::string substr = kv.first.substr(prefix.length() + 1);
|
||||
return separators_less_than_depth(substr);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!prefix_matches) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.names.push_back(kv.first);
|
||||
size_t last_separator = kv.first.find_last_of(separator);
|
||||
if (std::string::npos != last_separator) {
|
||||
std::string prefix = kv.first.substr(0, last_separator);
|
||||
if (
|
||||
std::find(result.prefixes.cbegin(), result.prefixes.cend(), prefix) ==
|
||||
result.prefixes.cend())
|
||||
{
|
||||
result.prefixes.push_back(prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -84,23 +84,31 @@ public:
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
auto rcl_node = node_base->get_rcl_node_handle();
|
||||
rcl_ret_t rcl_ret = rcl_node_type_description_service_init(rcl_node);
|
||||
auto * rcl_node = node_base->get_rcl_node_handle();
|
||||
std::shared_ptr<rcl_service_t> rcl_srv(
|
||||
new rcl_service_t,
|
||||
[rcl_node, logger = this->logger_](rcl_service_t * service)
|
||||
{
|
||||
if (rcl_service_fini(service, rcl_node) != RCL_RET_OK) {
|
||||
RCLCPP_ERROR(
|
||||
logger,
|
||||
"Error in destruction of rcl service handle [~/get_type_description]: %s",
|
||||
rcl_get_error_string().str);
|
||||
rcl_reset_error();
|
||||
}
|
||||
delete service;
|
||||
});
|
||||
*rcl_srv = rcl_get_zero_initialized_service();
|
||||
rcl_ret_t rcl_ret = rcl_node_type_description_service_init(rcl_srv.get(), rcl_node);
|
||||
|
||||
if (rcl_ret != RCL_RET_OK) {
|
||||
RCLCPP_ERROR(
|
||||
logger_, "Failed to initialize ~/get_type_description_service: %s",
|
||||
logger_, "Failed to initialize ~/get_type_description service: %s",
|
||||
rcl_get_error_string().str);
|
||||
throw std::runtime_error(
|
||||
"Failed to initialize ~/get_type_description service.");
|
||||
}
|
||||
|
||||
rcl_service_t * rcl_srv = nullptr;
|
||||
rcl_ret = rcl_node_get_type_description_service(rcl_node, &rcl_srv);
|
||||
if (rcl_ret != RCL_RET_OK) {
|
||||
throw std::runtime_error(
|
||||
"Failed to get initialized ~/get_type_description service from rcl.");
|
||||
}
|
||||
|
||||
rclcpp::AnyServiceCallback<ServiceT> cb;
|
||||
cb.set(
|
||||
[this](
|
||||
@@ -124,18 +132,6 @@ public:
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
~NodeTypeDescriptionsImpl()
|
||||
{
|
||||
if (
|
||||
type_description_srv_ &&
|
||||
RCL_RET_OK != rcl_node_type_description_service_fini(node_base_->get_rcl_node_handle()))
|
||||
{
|
||||
RCLCPP_ERROR(
|
||||
logger_,
|
||||
"Error in shutdown of get_type_description service: %s", rcl_get_error_string().str);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
NodeTypeDescriptions::NodeTypeDescriptions(
|
||||
|
||||
106
rclcpp/src/rclcpp/rate.cpp
Normal file
106
rclcpp/src/rclcpp/rate.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright 2023 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 "rclcpp/rate.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
Rate::Rate(
|
||||
const double rate, Clock::SharedPtr clock)
|
||||
: clock_(clock), period_(0, 0), last_interval_(clock_->now())
|
||||
{
|
||||
if (rate <= 0.0) {
|
||||
throw std::invalid_argument{"rate must be greater than 0"};
|
||||
}
|
||||
period_ = Duration::from_seconds(1.0 / rate);
|
||||
}
|
||||
|
||||
Rate::Rate(
|
||||
const Duration & period, Clock::SharedPtr clock)
|
||||
: clock_(clock), period_(period), last_interval_(clock_->now())
|
||||
{
|
||||
if (period <= Duration(0, 0)) {
|
||||
throw std::invalid_argument{"period must be greater than 0"};
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Rate::sleep()
|
||||
{
|
||||
// Time coming into sleep
|
||||
auto now = clock_->now();
|
||||
// Time of next interval
|
||||
auto next_interval = last_interval_ + period_;
|
||||
// Detect backwards time flow
|
||||
if (now < last_interval_) {
|
||||
// Best thing to do is to set the next_interval to now + period
|
||||
next_interval = now + period_;
|
||||
}
|
||||
// Update the interval
|
||||
last_interval_ += period_;
|
||||
// If the time_to_sleep is negative or zero, don't sleep
|
||||
if (next_interval <= now) {
|
||||
// If an entire cycle was missed then reset next interval.
|
||||
// This might happen if the loop took more than a cycle.
|
||||
// Or if time jumps forward.
|
||||
if (now > next_interval + period_) {
|
||||
last_interval_ = now + period_;
|
||||
}
|
||||
// Either way do not sleep and return false
|
||||
return false;
|
||||
}
|
||||
// Calculate the time to sleep
|
||||
auto time_to_sleep = next_interval - now;
|
||||
// Sleep (will get interrupted by ctrl-c, may not sleep full time)
|
||||
clock_->sleep_for(time_to_sleep);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Rate::is_steady() const
|
||||
{
|
||||
return clock_->get_clock_type() == RCL_STEADY_TIME;
|
||||
}
|
||||
|
||||
rcl_clock_type_t
|
||||
Rate::get_type() const
|
||||
{
|
||||
return clock_->get_clock_type();
|
||||
}
|
||||
|
||||
void
|
||||
Rate::reset()
|
||||
{
|
||||
last_interval_ = clock_->now();
|
||||
}
|
||||
|
||||
std::chrono::nanoseconds
|
||||
Rate::period() const
|
||||
{
|
||||
return std::chrono::nanoseconds(period_.nanoseconds());
|
||||
}
|
||||
|
||||
WallRate::WallRate(const double rate)
|
||||
: Rate(rate, std::make_shared<Clock>(RCL_STEADY_TIME))
|
||||
{}
|
||||
|
||||
WallRate::WallRate(const Duration & period)
|
||||
: Rate(period, std::make_shared<Clock>(RCL_STEADY_TIME))
|
||||
{}
|
||||
|
||||
} // namespace rclcpp
|
||||
@@ -113,7 +113,7 @@ SignalHandler::get_logger()
|
||||
SignalHandler &
|
||||
SignalHandler::get_global_signal_handler()
|
||||
{
|
||||
static SignalHandler signal_handler;
|
||||
static SignalHandler & signal_handler = *new SignalHandler();
|
||||
return signal_handler;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
bool
|
||||
install(SignalHandlerOptions signal_handler_options = SignalHandlerOptions::All);
|
||||
|
||||
/// Uninstall the signal handler for SIGINT/SIGTERM and join the dedicated singal handling
|
||||
/// Uninstall the signal handler for SIGINT/SIGTERM and join the dedicated signal handling
|
||||
/// thread.
|
||||
/**
|
||||
* Also restores the previous signal handler.
|
||||
@@ -189,7 +189,7 @@ private:
|
||||
|
||||
// Whether or not a signal has been received.
|
||||
std::atomic_bool signal_received_ = false;
|
||||
// A thread to which singal handling tasks are deferred.
|
||||
// A thread to which signal handling tasks are deferred.
|
||||
std::thread signal_handler_thread_;
|
||||
|
||||
// A mutex used to synchronize the install() and uninstall() methods.
|
||||
|
||||
@@ -298,7 +298,20 @@ SubscriptionBase::setup_intra_process(
|
||||
bool
|
||||
SubscriptionBase::can_loan_messages() const
|
||||
{
|
||||
return rcl_subscription_can_loan_messages(subscription_handle_.get());
|
||||
bool retval = rcl_subscription_can_loan_messages(subscription_handle_.get());
|
||||
if (retval) {
|
||||
// TODO(clalancette): The loaned message interface is currently not safe to use with
|
||||
// shared_ptr callbacks. If a user takes a copy of the shared_ptr, it can get freed from
|
||||
// underneath them via rcl_return_loaned_message_from_subscription(). The correct solution is
|
||||
// to return the loaned message in a custom deleter, but that needs to be carefully handled
|
||||
// with locking. Warn the user about this until we fix it.
|
||||
RCLCPP_WARN_ONCE(
|
||||
this->node_logger_,
|
||||
"Loaned messages are only safe with const ref subscription callbacks. "
|
||||
"If you are using any other kind of subscriptions, "
|
||||
"set the ROS_DISABLE_LOANED_MESSAGES environment variable to 1 (the default).");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
rclcpp::Waitable::SharedPtr
|
||||
|
||||
@@ -276,9 +276,9 @@ Time::operator-=(const rclcpp::Duration & rhs)
|
||||
}
|
||||
|
||||
Time
|
||||
Time::max()
|
||||
Time::max(rcl_clock_type_t clock_type)
|
||||
{
|
||||
return Time(std::numeric_limits<int32_t>::max(), 999999999);
|
||||
return Time(std::numeric_limits<int32_t>::max(), 999999999, clock_type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -236,6 +236,7 @@ public:
|
||||
rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock_interface,
|
||||
rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters_interface)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(node_base_lock_);
|
||||
node_base_ = node_base_interface;
|
||||
node_topics_ = node_topics_interface;
|
||||
node_graph_ = node_graph_interface;
|
||||
@@ -280,17 +281,14 @@ public:
|
||||
parameter_subscription_ = rclcpp::AsyncParametersClient::on_parameter_event(
|
||||
node_topics_,
|
||||
[this](std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event) {
|
||||
if (node_base_ != nullptr) {
|
||||
this->on_parameter_event(event);
|
||||
}
|
||||
// Do nothing if node_base_ is nullptr because it means the TimeSource is now
|
||||
// without an attached node
|
||||
this->on_parameter_event(event);
|
||||
});
|
||||
}
|
||||
|
||||
// Detach the attached node
|
||||
void detachNode()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(node_base_lock_);
|
||||
// destroy_clock_sub() *must* be first here, to ensure that the executor
|
||||
// can't possibly call any of the callbacks as we are cleaning up.
|
||||
destroy_clock_sub();
|
||||
@@ -327,6 +325,7 @@ private:
|
||||
std::thread clock_executor_thread_;
|
||||
|
||||
// Preserve the node reference
|
||||
std::mutex node_base_lock_;
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_{nullptr};
|
||||
rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_{nullptr};
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_{nullptr};
|
||||
@@ -464,6 +463,14 @@ private:
|
||||
// Callback for parameter updates
|
||||
void on_parameter_event(std::shared_ptr<const rcl_interfaces::msg::ParameterEvent> event)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(node_base_lock_);
|
||||
|
||||
if (node_base_ == nullptr) {
|
||||
// Do nothing if node_base_ is nullptr because it means the TimeSource is now
|
||||
// without an attached node
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter out events on 'use_sim_time' parameter instances in other nodes.
|
||||
if (event->node != node_base_->get_fully_qualified_name()) {
|
||||
return;
|
||||
|
||||
@@ -91,6 +91,44 @@ extract_type_identifier(const std::string & full_type)
|
||||
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,
|
||||
const std::string & typesupport_name,
|
||||
const std::string & symbol_part_name,
|
||||
const std::string & middle_module_additional,
|
||||
rcpputils::SharedLibrary & library)
|
||||
{
|
||||
std::string package_name;
|
||||
std::string middle_module;
|
||||
std::string type_name;
|
||||
std::tie(package_name, middle_module, type_name) = extract_type_identifier(type);
|
||||
|
||||
if (middle_module.empty()) {
|
||||
middle_module = middle_module_additional;
|
||||
}
|
||||
|
||||
auto mk_error = [&package_name, &type_name, &typesupport_name](auto reason) {
|
||||
std::stringstream rcutils_dynamic_loading_error;
|
||||
rcutils_dynamic_loading_error <<
|
||||
"Something went wrong loading the typesupport library for " <<
|
||||
typesupport_name << " type " << package_name <<
|
||||
"/" << type_name << ". " << reason;
|
||||
return rcutils_dynamic_loading_error.str();
|
||||
};
|
||||
|
||||
try {
|
||||
std::string symbol_name = typesupport_identifier + symbol_part_name +
|
||||
package_name + "__" + middle_module + "__" + type_name;
|
||||
const void * (* get_ts)() = nullptr;
|
||||
// This will throw runtime_error if the symbol was not found.
|
||||
get_ts = reinterpret_cast<decltype(get_ts)>(library.get_symbol(symbol_name));
|
||||
return get_ts();
|
||||
} catch (std::runtime_error &) {
|
||||
throw std::runtime_error{mk_error("Library could not be found.")};
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
std::shared_ptr<rcpputils::SharedLibrary>
|
||||
@@ -101,36 +139,42 @@ get_typesupport_library(const std::string & type, const std::string & typesuppor
|
||||
return std::make_shared<rcpputils::SharedLibrary>(library_path);
|
||||
}
|
||||
|
||||
const rosidl_message_type_support_t *
|
||||
get_typesupport_handle(
|
||||
const rosidl_message_type_support_t * get_typesupport_handle(
|
||||
const std::string & type,
|
||||
const std::string & typesupport_identifier,
|
||||
rcpputils::SharedLibrary & library)
|
||||
{
|
||||
std::string package_name;
|
||||
std::string middle_module;
|
||||
std::string type_name;
|
||||
std::tie(package_name, middle_module, type_name) = extract_type_identifier(type);
|
||||
return get_message_typesupport_handle(type, typesupport_identifier, library);
|
||||
}
|
||||
|
||||
auto mk_error = [&package_name, &type_name](auto reason) {
|
||||
std::stringstream rcutils_dynamic_loading_error;
|
||||
rcutils_dynamic_loading_error <<
|
||||
"Something went wrong loading the typesupport library for message type " << package_name <<
|
||||
"/" << type_name << ". " << reason;
|
||||
return rcutils_dynamic_loading_error.str();
|
||||
};
|
||||
const rosidl_message_type_support_t * get_message_typesupport_handle(
|
||||
const std::string & type,
|
||||
const std::string & typesupport_identifier,
|
||||
rcpputils::SharedLibrary & library)
|
||||
{
|
||||
static const std::string typesupport_name = "message";
|
||||
static const std::string symbol_part_name = "__get_message_type_support_handle__";
|
||||
static const std::string middle_module_additional = "msg";
|
||||
|
||||
try {
|
||||
std::string symbol_name = typesupport_identifier + "__get_message_type_support_handle__" +
|
||||
package_name + "__" + (middle_module.empty() ? "msg" : middle_module) + "__" + type_name;
|
||||
return static_cast<const rosidl_message_type_support_t *>(get_typesupport_handle_impl(
|
||||
type, typesupport_identifier, typesupport_name, symbol_part_name,
|
||||
middle_module_additional, library
|
||||
));
|
||||
}
|
||||
|
||||
const rosidl_message_type_support_t * (* get_ts)() = nullptr;
|
||||
// This will throw runtime_error if the symbol was not found.
|
||||
get_ts = reinterpret_cast<decltype(get_ts)>(library.get_symbol(symbol_name));
|
||||
return get_ts();
|
||||
} catch (std::runtime_error &) {
|
||||
throw std::runtime_error{mk_error("Library could not be found.")};
|
||||
}
|
||||
const rosidl_service_type_support_t * get_service_typesupport_handle(
|
||||
const std::string & type,
|
||||
const std::string & typesupport_identifier,
|
||||
rcpputils::SharedLibrary & library)
|
||||
{
|
||||
static const std::string typesupport_name = "service";
|
||||
static const std::string symbol_part_name = "__get_service_type_support_handle__";
|
||||
static const std::string middle_module_additional = "srv";
|
||||
|
||||
return static_cast<const rosidl_service_type_support_t *>(get_typesupport_handle_impl(
|
||||
type, typesupport_identifier, typesupport_name, symbol_part_name,
|
||||
middle_module_additional, library
|
||||
));
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -7,14 +7,12 @@ find_package(performance_test_fixture REQUIRED)
|
||||
|
||||
add_performance_test(benchmark_client benchmark_client.cpp)
|
||||
if(TARGET benchmark_client)
|
||||
target_link_libraries(benchmark_client ${PROJECT_NAME})
|
||||
ament_target_dependencies(benchmark_client test_msgs rcl_interfaces)
|
||||
target_link_libraries(benchmark_client ${PROJECT_NAME} ${rcl_interfaces_TARGETS} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
add_performance_test(benchmark_executor benchmark_executor.cpp)
|
||||
if(TARGET benchmark_executor)
|
||||
target_link_libraries(benchmark_executor ${PROJECT_NAME})
|
||||
ament_target_dependencies(benchmark_executor test_msgs)
|
||||
target_link_libraries(benchmark_executor ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
add_performance_test(benchmark_init_shutdown benchmark_init_shutdown.cpp)
|
||||
@@ -39,6 +37,5 @@ endif()
|
||||
|
||||
add_performance_test(benchmark_service benchmark_service.cpp)
|
||||
if(TARGET benchmark_service)
|
||||
target_link_libraries(benchmark_service ${PROJECT_NAME})
|
||||
ament_target_dependencies(benchmark_service test_msgs rcl_interfaces)
|
||||
target_link_libraries(benchmark_service ${PROJECT_NAME} ${rcl_interfaces_TARGETS} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
@@ -34,71 +34,38 @@ if(TARGET test_exceptions)
|
||||
target_link_libraries(test_exceptions ${PROJECT_NAME} mimick)
|
||||
endif()
|
||||
|
||||
# Increasing timeout because connext can take a long time to destroy nodes
|
||||
# TODO(brawner) remove when destroying Node for Connext is resolved. See:
|
||||
# https://github.com/ros2/rclcpp/issues/1250
|
||||
ament_add_gtest(
|
||||
test_allocator_memory_strategy
|
||||
strategies/test_allocator_memory_strategy.cpp
|
||||
TIMEOUT 360)
|
||||
ament_add_gtest(test_allocator_memory_strategy strategies/test_allocator_memory_strategy.cpp)
|
||||
if(TARGET test_allocator_memory_strategy)
|
||||
ament_target_dependencies(test_allocator_memory_strategy
|
||||
"rcl"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_allocator_memory_strategy ${PROJECT_NAME})
|
||||
target_link_libraries(test_allocator_memory_strategy ${PROJECT_NAME} rcpputils::rcpputils ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_message_pool_memory_strategy strategies/test_message_pool_memory_strategy.cpp)
|
||||
if(TARGET test_message_pool_memory_strategy)
|
||||
ament_target_dependencies(test_message_pool_memory_strategy
|
||||
"rcl"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_message_pool_memory_strategy ${PROJECT_NAME})
|
||||
target_link_libraries(test_message_pool_memory_strategy ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_any_service_callback test_any_service_callback.cpp)
|
||||
if(TARGET test_any_service_callback)
|
||||
ament_target_dependencies(test_any_service_callback
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_any_service_callback ${PROJECT_NAME})
|
||||
target_link_libraries(test_any_service_callback ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_any_subscription_callback test_any_subscription_callback.cpp)
|
||||
if(TARGET test_any_subscription_callback)
|
||||
ament_target_dependencies(test_any_subscription_callback
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_any_subscription_callback ${PROJECT_NAME})
|
||||
target_link_libraries(test_any_subscription_callback ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_client test_client.cpp)
|
||||
if(TARGET test_client)
|
||||
ament_target_dependencies(test_client
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_client ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_client ${PROJECT_NAME} mimick ${rcl_interfaces_TARGETS} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_copy_all_parameter_values test_copy_all_parameter_values.cpp)
|
||||
if(TARGET test_copy_all_parameter_values)
|
||||
target_link_libraries(test_copy_all_parameter_values ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_create_timer test_create_timer.cpp)
|
||||
if(TARGET test_create_timer)
|
||||
ament_target_dependencies(test_create_timer
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rcl"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_create_timer ${PROJECT_NAME})
|
||||
target_include_directories(test_create_timer PRIVATE ./)
|
||||
endif()
|
||||
ament_add_gtest(test_create_subscription test_create_subscription.cpp)
|
||||
if(TARGET test_create_subscription)
|
||||
target_link_libraries(test_create_subscription ${PROJECT_NAME})
|
||||
ament_target_dependencies(test_create_subscription
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_create_subscription ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
function(test_add_callback_groups_to_executor_for_rmw_implementation)
|
||||
set(rmw_implementation_env_var RMW_IMPLEMENTATION=${rmw_implementation})
|
||||
@@ -107,32 +74,17 @@ function(test_add_callback_groups_to_executor_for_rmw_implementation)
|
||||
TIMEOUT 120
|
||||
)
|
||||
if(TARGET test_add_callback_groups_to_executor${target_suffix})
|
||||
target_link_libraries(test_add_callback_groups_to_executor${target_suffix} ${PROJECT_NAME})
|
||||
ament_target_dependencies(test_add_callback_groups_to_executor${target_suffix}
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_add_callback_groups_to_executor${target_suffix} ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
endfunction()
|
||||
call_for_each_rmw_implementation(test_add_callback_groups_to_executor_for_rmw_implementation)
|
||||
ament_add_gtest(test_expand_topic_or_service_name test_expand_topic_or_service_name.cpp)
|
||||
if(TARGET test_expand_topic_or_service_name)
|
||||
ament_target_dependencies(test_expand_topic_or_service_name
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_expand_topic_or_service_name ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_expand_topic_or_service_name ${PROJECT_NAME} mimick rcl::rcl rmw::rmw)
|
||||
endif()
|
||||
ament_add_gtest(test_function_traits test_function_traits.cpp)
|
||||
if(TARGET test_function_traits)
|
||||
target_include_directories(test_function_traits PUBLIC ../../include)
|
||||
ament_target_dependencies(test_function_traits
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_function_traits ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(
|
||||
test_future_return_code
|
||||
@@ -142,72 +94,33 @@ if(TARGET test_future_return_code)
|
||||
endif()
|
||||
ament_add_gmock(test_intra_process_manager test_intra_process_manager.cpp)
|
||||
if(TARGET test_intra_process_manager)
|
||||
ament_target_dependencies(test_intra_process_manager
|
||||
"rcl"
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_intra_process_manager ${PROJECT_NAME})
|
||||
target_link_libraries(test_intra_process_manager ${PROJECT_NAME} ${rcl_interfaces_TARGETS} rmw::rmw)
|
||||
endif()
|
||||
ament_add_gmock(test_intra_process_manager_with_allocators test_intra_process_manager_with_allocators.cpp)
|
||||
if(TARGET test_intra_process_manager_with_allocators)
|
||||
ament_target_dependencies(test_intra_process_manager_with_allocators
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_intra_process_manager_with_allocators ${PROJECT_NAME})
|
||||
target_link_libraries(test_intra_process_manager_with_allocators ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_ring_buffer_implementation test_ring_buffer_implementation.cpp)
|
||||
if(TARGET test_ring_buffer_implementation)
|
||||
ament_target_dependencies(test_ring_buffer_implementation
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_ring_buffer_implementation ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_intra_process_buffer test_intra_process_buffer.cpp)
|
||||
if(TARGET test_intra_process_buffer)
|
||||
ament_target_dependencies(test_intra_process_buffer
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_intra_process_buffer ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_loaned_message test_loaned_message.cpp)
|
||||
ament_target_dependencies(test_loaned_message
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_loaned_message ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_loaned_message ${PROJECT_NAME} mimick ${test_msgs_TARGETS})
|
||||
|
||||
ament_add_gtest(test_memory_strategy test_memory_strategy.cpp)
|
||||
ament_target_dependencies(test_memory_strategy
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_memory_strategy ${PROJECT_NAME})
|
||||
target_link_libraries(test_memory_strategy ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
|
||||
ament_add_gtest(test_message_memory_strategy test_message_memory_strategy.cpp)
|
||||
ament_target_dependencies(test_message_memory_strategy
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_message_memory_strategy ${PROJECT_NAME})
|
||||
target_link_libraries(test_message_memory_strategy ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
|
||||
ament_add_gtest(test_node test_node.cpp TIMEOUT 240)
|
||||
if(TARGET test_node)
|
||||
ament_target_dependencies(test_node
|
||||
"rcl_interfaces"
|
||||
"rcpputils"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_node ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_node ${PROJECT_NAME} mimick rcpputils::rcpputils rmw::rmw ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_node_interfaces__get_node_interfaces
|
||||
@@ -218,7 +131,7 @@ endif()
|
||||
ament_add_gtest(test_node_interfaces__node_base
|
||||
node_interfaces/test_node_base.cpp)
|
||||
if(TARGET test_node_interfaces__node_base)
|
||||
target_link_libraries(test_node_interfaces__node_base ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_node_interfaces__node_base ${PROJECT_NAME} mimick rcl::rcl rmw::rmw)
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_clock
|
||||
node_interfaces/test_node_clock.cpp)
|
||||
@@ -229,48 +142,42 @@ ament_add_gtest(test_node_interfaces__node_graph
|
||||
node_interfaces/test_node_graph.cpp
|
||||
TIMEOUT 120)
|
||||
if(TARGET test_node_interfaces__node_graph)
|
||||
ament_target_dependencies(
|
||||
test_node_interfaces__node_graph
|
||||
"test_msgs")
|
||||
target_link_libraries(test_node_interfaces__node_graph ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_node_interfaces__node_graph ${PROJECT_NAME} mimick rcl::rcl ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_interfaces
|
||||
node_interfaces/test_node_interfaces.cpp)
|
||||
if(TARGET test_node_interfaces__node_interfaces)
|
||||
target_link_libraries(test_node_interfaces__node_interfaces ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_node_interfaces__node_interfaces ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_parameters
|
||||
node_interfaces/test_node_parameters.cpp)
|
||||
if(TARGET test_node_interfaces__node_parameters)
|
||||
target_link_libraries(test_node_interfaces__node_parameters ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_node_interfaces__node_parameters ${PROJECT_NAME} mimick rcpputils::rcpputils)
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_services
|
||||
node_interfaces/test_node_services.cpp)
|
||||
if(TARGET test_node_interfaces__node_services)
|
||||
target_link_libraries(test_node_interfaces__node_services ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_node_interfaces__node_services ${PROJECT_NAME} mimick rcl::rcl)
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_timers
|
||||
node_interfaces/test_node_timers.cpp)
|
||||
if(TARGET test_node_interfaces__node_timers)
|
||||
target_link_libraries(test_node_interfaces__node_timers ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_node_interfaces__node_timers ${PROJECT_NAME} mimick rcl::rcl)
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_topics
|
||||
node_interfaces/test_node_topics.cpp)
|
||||
if(TARGET test_node_interfaces__node_topics)
|
||||
ament_target_dependencies(
|
||||
test_node_interfaces__node_topics
|
||||
"test_msgs")
|
||||
target_link_libraries(test_node_interfaces__node_topics ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_node_interfaces__node_topics ${PROJECT_NAME} mimick rcl::rcl ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_type_descriptions
|
||||
node_interfaces/test_node_type_descriptions.cpp)
|
||||
if(TARGET test_node_interfaces__node_type_descriptions)
|
||||
target_link_libraries(test_node_interfaces__node_type_descriptions ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_node_interfaces__node_type_descriptions ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_waitables
|
||||
node_interfaces/test_node_waitables.cpp)
|
||||
if(TARGET test_node_interfaces__node_waitables)
|
||||
target_link_libraries(test_node_interfaces__node_waitables ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_node_interfaces__node_waitables ${PROJECT_NAME} mimick rcl::rcl)
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__test_template_utils # Compile time test
|
||||
node_interfaces/detail/test_template_utils.cpp)
|
||||
@@ -301,82 +208,43 @@ endif()
|
||||
|
||||
ament_add_gtest(test_node_global_args test_node_global_args.cpp)
|
||||
if(TARGET test_node_global_args)
|
||||
ament_target_dependencies(test_node_global_args
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_node_global_args ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_node_options test_node_options.cpp)
|
||||
if(TARGET test_node_options)
|
||||
ament_target_dependencies(test_node_options "rcl")
|
||||
target_link_libraries(test_node_options ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_node_options ${PROJECT_NAME} mimick rcl::rcl)
|
||||
endif()
|
||||
ament_add_gtest(test_init_options test_init_options.cpp)
|
||||
if(TARGET test_init_options)
|
||||
ament_target_dependencies(test_init_options "rcl")
|
||||
target_link_libraries(test_init_options ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_init_options ${PROJECT_NAME} mimick rcl::rcl)
|
||||
endif()
|
||||
ament_add_gmock(test_parameter_client test_parameter_client.cpp)
|
||||
if(TARGET test_parameter_client)
|
||||
ament_target_dependencies(test_parameter_client
|
||||
"rcl_interfaces"
|
||||
)
|
||||
target_link_libraries(test_parameter_client ${PROJECT_NAME})
|
||||
target_link_libraries(test_parameter_client ${PROJECT_NAME} ${rcl_interfaces_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter_service test_parameter_service.cpp)
|
||||
if(TARGET test_parameter_service)
|
||||
ament_target_dependencies(test_parameter_service
|
||||
"rcl_interfaces"
|
||||
)
|
||||
target_link_libraries(test_parameter_service ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter_events_filter test_parameter_events_filter.cpp)
|
||||
if(TARGET test_parameter_events_filter)
|
||||
ament_target_dependencies(test_parameter_events_filter
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_parameter_events_filter ${PROJECT_NAME})
|
||||
target_link_libraries(test_parameter_events_filter ${PROJECT_NAME} ${rcl_interfaces_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter test_parameter.cpp)
|
||||
if(TARGET test_parameter)
|
||||
ament_target_dependencies(test_parameter
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_parameter ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter_event_handler test_parameter_event_handler.cpp)
|
||||
if(TARGET test_parameter_event_handler)
|
||||
ament_target_dependencies(test_parameter_event_handler
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_generator_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_parameter_event_handler ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_parameter_map test_parameter_map.cpp)
|
||||
if(TARGET test_parameter_map)
|
||||
target_link_libraries(test_parameter_map ${PROJECT_NAME})
|
||||
target_link_libraries(test_parameter_map ${PROJECT_NAME} rcl::rcl rcl_yaml_param_parser::rcl_yaml_param_parser rcutils::rcutils)
|
||||
endif()
|
||||
ament_add_gtest(test_publisher test_publisher.cpp TIMEOUT 120)
|
||||
if(TARGET test_publisher)
|
||||
ament_target_dependencies(test_publisher
|
||||
"rcl"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_publisher ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_publisher ${PROJECT_NAME} mimick rcl::rcl rcutils::rcutils ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
set(append_library_dirs "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
@@ -406,32 +274,22 @@ ament_add_gtest(test_subscription_publisher_with_same_type_adapter test_subscrip
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}"
|
||||
)
|
||||
if(TARGET test_subscription_publisher_with_same_type_adapter)
|
||||
ament_target_dependencies(test_subscription_publisher_with_same_type_adapter
|
||||
"statistics_msgs"
|
||||
)
|
||||
target_link_libraries(test_subscription_publisher_with_same_type_adapter
|
||||
${PROJECT_NAME}
|
||||
${cpp_typesupport_target})
|
||||
${cpp_typesupport_target}
|
||||
${statistics_msgs_TARGETS}
|
||||
)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_publisher_subscription_count_api test_publisher_subscription_count_api.cpp)
|
||||
if(TARGET test_publisher_subscription_count_api)
|
||||
ament_target_dependencies(test_publisher_subscription_count_api
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_publisher_subscription_count_api ${PROJECT_NAME})
|
||||
target_link_libraries(test_publisher_subscription_count_api ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_qos test_qos.cpp)
|
||||
if(TARGET test_qos)
|
||||
ament_target_dependencies(test_qos
|
||||
"rmw"
|
||||
)
|
||||
target_link_libraries(test_qos
|
||||
${PROJECT_NAME}
|
||||
rmw::rmw
|
||||
)
|
||||
endif()
|
||||
function(test_generic_pubsub_for_rmw_implementation)
|
||||
@@ -440,12 +298,7 @@ function(test_generic_pubsub_for_rmw_implementation)
|
||||
ENV ${rmw_implementation_env_var}
|
||||
)
|
||||
if(TARGET test_generic_pubsub${target_suffix})
|
||||
target_link_libraries(test_generic_pubsub${target_suffix} ${PROJECT_NAME})
|
||||
ament_target_dependencies(test_generic_pubsub${target_suffix}
|
||||
"rcpputils"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_generic_pubsub${target_suffix} ${PROJECT_NAME} rcl::rcl ${test_msgs_TARGETS})
|
||||
endif()
|
||||
endfunction()
|
||||
call_for_each_rmw_implementation(test_generic_pubsub_for_rmw_implementation)
|
||||
@@ -456,153 +309,79 @@ function(test_qos_event_for_rmw_implementation)
|
||||
ENV ${rmw_implementation_env_var}
|
||||
)
|
||||
if(TARGET test_qos_event${target_suffix})
|
||||
target_link_libraries(test_qos_event${target_suffix} ${PROJECT_NAME} mimick)
|
||||
ament_target_dependencies(test_qos_event${target_suffix}
|
||||
"rmw"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_qos_event${target_suffix} ${PROJECT_NAME} mimick rcutils::rcutils rmw::rmw ${test_msgs_TARGETS})
|
||||
endif()
|
||||
endfunction()
|
||||
call_for_each_rmw_implementation(test_qos_event_for_rmw_implementation)
|
||||
|
||||
ament_add_gmock(test_qos_overriding_options test_qos_overriding_options.cpp)
|
||||
if(TARGET test_qos_overriding_options)
|
||||
target_link_libraries(test_qos_overriding_options
|
||||
${PROJECT_NAME}
|
||||
)
|
||||
target_link_libraries(test_qos_overriding_options ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gmock(test_qos_parameters test_qos_parameters.cpp)
|
||||
if(TARGET test_qos_parameters)
|
||||
target_link_libraries(test_qos_parameters
|
||||
${PROJECT_NAME}
|
||||
)
|
||||
target_link_libraries(test_qos_parameters ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_rate test_rate.cpp)
|
||||
if(TARGET test_rate)
|
||||
ament_target_dependencies(test_rate
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
)
|
||||
target_link_libraries(test_rate
|
||||
${PROJECT_NAME}
|
||||
)
|
||||
target_link_libraries(test_rate ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_serialized_message_allocator test_serialized_message_allocator.cpp)
|
||||
if(TARGET test_serialized_message_allocator)
|
||||
ament_target_dependencies(test_serialized_message_allocator
|
||||
test_msgs
|
||||
)
|
||||
target_link_libraries(test_serialized_message_allocator
|
||||
${PROJECT_NAME}
|
||||
)
|
||||
target_link_libraries(test_serialized_message_allocator ${PROJECT_NAME} rcl::rcl ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_serialized_message test_serialized_message.cpp)
|
||||
if(TARGET test_serialized_message)
|
||||
ament_target_dependencies(test_serialized_message
|
||||
test_msgs
|
||||
)
|
||||
target_link_libraries(test_serialized_message
|
||||
${PROJECT_NAME}
|
||||
)
|
||||
target_link_libraries(test_serialized_message ${PROJECT_NAME} rcpputils::rcpputils ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_service test_service.cpp)
|
||||
if(TARGET test_service)
|
||||
ament_target_dependencies(test_service
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_service ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_service ${PROJECT_NAME} mimick ${rcl_interfaces_TARGES} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gmock(test_service_introspection test_service_introspection.cpp)
|
||||
if(TARGET test_service)
|
||||
ament_target_dependencies(test_service_introspection
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_service_introspection ${PROJECT_NAME} mimick)
|
||||
if(TARGET test_service_introspection)
|
||||
target_link_libraries(test_service_introspection ${PROJECT_NAME} mimick ${service_msgs_TARGETS} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
# Creating and destroying nodes is slow with Connext, so this needs larger timeout.
|
||||
ament_add_gtest(test_subscription test_subscription.cpp TIMEOUT 120)
|
||||
if(TARGET test_subscription)
|
||||
ament_target_dependencies(test_subscription
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_subscription ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_subscription ${PROJECT_NAME} mimick ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_subscription_publisher_count_api test_subscription_publisher_count_api.cpp)
|
||||
if(TARGET test_subscription_publisher_count_api)
|
||||
ament_target_dependencies(test_subscription_publisher_count_api
|
||||
"rcl_interfaces"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_subscription_publisher_count_api ${PROJECT_NAME})
|
||||
target_link_libraries(test_subscription_publisher_count_api ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_subscription_traits test_subscription_traits.cpp)
|
||||
if(TARGET test_subscription_traits)
|
||||
ament_target_dependencies(test_subscription_traits
|
||||
"rcl"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_subscription_traits ${PROJECT_NAME})
|
||||
target_link_libraries(test_subscription_traits ${PROJECT_NAME} rcl::rcl ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gtest(test_type_support test_type_support.cpp)
|
||||
if(TARGET test_type_support)
|
||||
ament_target_dependencies(test_type_support
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_type_support ${PROJECT_NAME})
|
||||
target_link_libraries(test_type_support ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
ament_add_gmock(test_typesupport_helpers test_typesupport_helpers.cpp)
|
||||
if(TARGET test_typesupport_helpers)
|
||||
target_link_libraries(test_typesupport_helpers ${PROJECT_NAME})
|
||||
target_link_libraries(test_typesupport_helpers ${PROJECT_NAME} rcpputils::rcpputils)
|
||||
endif()
|
||||
ament_add_gtest(test_find_weak_nodes test_find_weak_nodes.cpp)
|
||||
if(TARGET test_find_weak_nodes)
|
||||
ament_target_dependencies(test_find_weak_nodes
|
||||
"rcl"
|
||||
)
|
||||
target_link_libraries(test_find_weak_nodes ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_externally_defined_services test_externally_defined_services.cpp)
|
||||
ament_target_dependencies(test_externally_defined_services
|
||||
"rcl"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_externally_defined_services ${PROJECT_NAME})
|
||||
target_link_libraries(test_externally_defined_services ${PROJECT_NAME} rcl::rcl ${test_msgs_TARGETS})
|
||||
|
||||
ament_add_gtest(test_duration test_duration.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_duration)
|
||||
ament_target_dependencies(test_duration
|
||||
"rcl")
|
||||
target_link_libraries(test_duration ${PROJECT_NAME})
|
||||
target_link_libraries(test_duration ${PROJECT_NAME} rcl::rcl)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_logger test_logger.cpp)
|
||||
target_link_libraries(test_logger ${PROJECT_NAME})
|
||||
target_link_libraries(test_logger ${PROJECT_NAME} rcutils::rcutils)
|
||||
|
||||
ament_add_gmock(test_logging test_logging.cpp)
|
||||
target_link_libraries(test_logging ${PROJECT_NAME})
|
||||
target_link_libraries(test_logging ${PROJECT_NAME} rcutils::rcutils)
|
||||
|
||||
ament_add_gmock(test_context test_context.cpp)
|
||||
target_link_libraries(test_context ${PROJECT_NAME})
|
||||
@@ -610,134 +389,96 @@ target_link_libraries(test_context ${PROJECT_NAME})
|
||||
ament_add_gtest(test_time test_time.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_time)
|
||||
ament_target_dependencies(test_time
|
||||
"rcl")
|
||||
target_link_libraries(test_time ${PROJECT_NAME})
|
||||
target_link_libraries(test_time ${PROJECT_NAME} rcl::rcl rcutils::rcutils)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_timer test_timer.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_timer)
|
||||
ament_target_dependencies(test_timer
|
||||
"rcl")
|
||||
target_link_libraries(test_timer ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_timer ${PROJECT_NAME} mimick rcl::rcl)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_timers_manager test_timers_manager.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_timers_manager)
|
||||
ament_target_dependencies(test_timers_manager
|
||||
"rcl")
|
||||
target_link_libraries(test_timers_manager ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_timers_manager ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_time_source test_time_source.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_time_source)
|
||||
ament_target_dependencies(test_time_source
|
||||
"rcl")
|
||||
target_link_libraries(test_time_source ${PROJECT_NAME})
|
||||
target_link_libraries(test_time_source ${PROJECT_NAME} rcl::rcl)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_utilities test_utilities.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_utilities)
|
||||
ament_target_dependencies(test_utilities
|
||||
"rcl")
|
||||
target_link_libraries(test_utilities ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_utilities ${PROJECT_NAME} mimick rcl::rcl)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_wait_for_message test_wait_for_message.cpp)
|
||||
if(TARGET test_wait_for_message)
|
||||
ament_target_dependencies(test_wait_for_message
|
||||
"test_msgs")
|
||||
target_link_libraries(test_wait_for_message ${PROJECT_NAME})
|
||||
target_link_libraries(test_wait_for_message ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_logger_service test_logger_service.cpp)
|
||||
if(TARGET test_logger_service)
|
||||
ament_target_dependencies(test_logger_service
|
||||
"rcl_interfaces")
|
||||
target_link_libraries(test_logger_service ${PROJECT_NAME})
|
||||
target_link_libraries(test_logger_service ${PROJECT_NAME} ${rcl_interfaces_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_interface_traits test_interface_traits.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_interface_traits)
|
||||
ament_target_dependencies(test_interface_traits
|
||||
"rcl")
|
||||
target_link_libraries(test_interface_traits ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
# TODO(brawner) remove when destroying Node for Connext is resolved. See:
|
||||
# https://github.com/ros2/rclcpp/issues/1250
|
||||
ament_add_gtest(
|
||||
test_executors
|
||||
executors/test_executors.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}"
|
||||
TIMEOUT 180)
|
||||
if(TARGET test_executors)
|
||||
ament_target_dependencies(test_executors
|
||||
"rcl"
|
||||
"test_msgs")
|
||||
target_link_libraries(test_executors ${PROJECT_NAME})
|
||||
target_link_libraries(test_executors ${PROJECT_NAME} rcl::rcl ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_static_single_threaded_executor executors/test_static_single_threaded_executor.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_static_single_threaded_executor)
|
||||
ament_target_dependencies(test_static_single_threaded_executor
|
||||
"test_msgs")
|
||||
target_link_libraries(test_static_single_threaded_executor ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_static_single_threaded_executor ${PROJECT_NAME} mimick ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_multi_threaded_executor executors/test_multi_threaded_executor.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_multi_threaded_executor)
|
||||
ament_target_dependencies(test_multi_threaded_executor
|
||||
"rcl")
|
||||
target_link_libraries(test_multi_threaded_executor ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_static_executor_entities_collector executors/test_static_executor_entities_collector.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}" TIMEOUT 120)
|
||||
if(TARGET test_static_executor_entities_collector)
|
||||
ament_target_dependencies(test_static_executor_entities_collector
|
||||
"rcl"
|
||||
"test_msgs")
|
||||
target_link_libraries(test_static_executor_entities_collector ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_static_executor_entities_collector ${PROJECT_NAME} mimick rcpputils::rcpputils ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_entities_collector executors/test_entities_collector.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}" TIMEOUT 120)
|
||||
if(TARGET test_entities_collector)
|
||||
ament_target_dependencies(test_entities_collector
|
||||
"rcl"
|
||||
"test_msgs")
|
||||
target_link_libraries(test_entities_collector ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_entities_collector ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_executor_notify_waitable executors/test_executor_notify_waitable.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}" TIMEOUT 120)
|
||||
if(TARGET test_executor_notify_waitable)
|
||||
ament_target_dependencies(test_executor_notify_waitable
|
||||
"rcl"
|
||||
"test_msgs")
|
||||
target_link_libraries(test_executor_notify_waitable ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_executor_notify_waitable ${PROJECT_NAME} mimick rcpputils::rcpputils)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_events_executor executors/test_events_executor.cpp TIMEOUT 5)
|
||||
if(TARGET test_events_executor)
|
||||
ament_target_dependencies(test_events_executor
|
||||
"test_msgs")
|
||||
target_link_libraries(test_events_executor ${PROJECT_NAME})
|
||||
target_link_libraries(test_events_executor ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_events_queue executors/test_events_queue.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_events_queue)
|
||||
ament_target_dependencies(test_events_queue
|
||||
"test_msgs")
|
||||
target_link_libraries(test_events_queue ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
@@ -750,76 +491,60 @@ endif()
|
||||
ament_add_gtest(test_wait_set test_wait_set.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_wait_set)
|
||||
ament_target_dependencies(test_wait_set "test_msgs")
|
||||
target_link_libraries(test_wait_set ${PROJECT_NAME})
|
||||
target_link_libraries(test_wait_set ${PROJECT_NAME} ${rcl_interfaces_TARGETS} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_subscription_topic_statistics topic_statistics/test_subscription_topic_statistics.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}"
|
||||
)
|
||||
if(TARGET test_subscription_topic_statistics)
|
||||
ament_target_dependencies(test_subscription_topic_statistics
|
||||
"builtin_interfaces"
|
||||
"libstatistics_collector"
|
||||
"rcl_interfaces"
|
||||
"rcutils"
|
||||
"rmw"
|
||||
"rosidl_runtime_cpp"
|
||||
"rosidl_typesupport_cpp"
|
||||
"statistics_msgs"
|
||||
"test_msgs")
|
||||
target_link_libraries(test_subscription_topic_statistics
|
||||
${PROJECT_NAME}
|
||||
${cpp_typesupport_target})
|
||||
libstatistics_collector::libstatistics_collector
|
||||
${statistics_msgs_TARGETS}
|
||||
${test_msgs_TARGETS}
|
||||
)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_subscription_options test_subscription_options.cpp)
|
||||
if(TARGET test_subscription_options)
|
||||
ament_target_dependencies(test_subscription_options "rcl")
|
||||
target_link_libraries(test_subscription_options ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_dynamic_storage wait_set_policies/test_dynamic_storage.cpp)
|
||||
if(TARGET test_dynamic_storage)
|
||||
ament_target_dependencies(test_dynamic_storage "rcl" "test_msgs")
|
||||
target_link_libraries(test_dynamic_storage ${PROJECT_NAME})
|
||||
target_link_libraries(test_dynamic_storage ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_storage_policy_common wait_set_policies/test_storage_policy_common.cpp)
|
||||
if(TARGET test_storage_policy_common)
|
||||
ament_target_dependencies(test_storage_policy_common "rcl" "test_msgs")
|
||||
target_link_libraries(test_storage_policy_common ${PROJECT_NAME} mimick)
|
||||
target_link_libraries(test_storage_policy_common ${PROJECT_NAME} mimick ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_static_storage wait_set_policies/test_static_storage.cpp)
|
||||
if(TARGET test_static_storage)
|
||||
ament_target_dependencies(test_static_storage "rcl" "test_msgs")
|
||||
target_link_libraries(test_static_storage ${PROJECT_NAME})
|
||||
target_link_libraries(test_static_storage ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_thread_safe_synchronization wait_set_policies/test_thread_safe_synchronization.cpp)
|
||||
if(TARGET test_thread_safe_synchronization)
|
||||
ament_target_dependencies(test_thread_safe_synchronization "rcl" "test_msgs")
|
||||
target_link_libraries(test_thread_safe_synchronization ${PROJECT_NAME})
|
||||
target_link_libraries(test_thread_safe_synchronization ${PROJECT_NAME} ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_rosout_qos test_rosout_qos.cpp)
|
||||
if(TARGET test_rosout_qos)
|
||||
ament_target_dependencies(test_rosout_qos "rcl")
|
||||
target_link_libraries(test_rosout_qos ${PROJECT_NAME})
|
||||
target_link_libraries(test_rosout_qos ${PROJECT_NAME} rcl::rcl rmw::rmw)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_rosout_subscription test_rosout_subscription.cpp)
|
||||
if(TARGET test_rosout_subscription)
|
||||
ament_target_dependencies(test_rosout_subscription "rcl")
|
||||
target_link_libraries(test_rosout_subscription ${PROJECT_NAME})
|
||||
target_link_libraries(test_rosout_subscription ${PROJECT_NAME} ${rcl_interfaces_TARGETS})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_executor test_executor.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}"
|
||||
TIMEOUT 120)
|
||||
if(TARGET test_executor)
|
||||
ament_target_dependencies(test_executor "rcl")
|
||||
target_link_libraries(test_executor ${PROJECT_NAME} mimick)
|
||||
endif()
|
||||
|
||||
@@ -836,12 +561,7 @@ function(test_subscription_content_filter_for_rmw_implementation)
|
||||
TIMEOUT 120
|
||||
)
|
||||
if(TARGET test_subscription_content_filter${target_suffix})
|
||||
target_link_libraries(test_subscription_content_filter${target_suffix} ${PROJECT_NAME} mimick)
|
||||
ament_target_dependencies(test_subscription_content_filter${target_suffix}
|
||||
"rcpputils"
|
||||
"rosidl_typesupport_cpp"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_subscription_content_filter${target_suffix} ${PROJECT_NAME} mimick ${test_msgs_TARGETS})
|
||||
endif()
|
||||
endfunction()
|
||||
call_for_each_rmw_implementation(test_subscription_content_filter_for_rmw_implementation)
|
||||
|
||||
@@ -60,7 +60,7 @@ TEST_F(TestEventsExecutor, run_pub_sub)
|
||||
executor.add_node(node);
|
||||
|
||||
bool spin_exited = false;
|
||||
std::thread spinner([&spin_exited, &executor, this]() {
|
||||
std::thread spinner([&spin_exited, &executor]() {
|
||||
executor.spin();
|
||||
spin_exited = true;
|
||||
});
|
||||
@@ -107,7 +107,7 @@ TEST_F(TestEventsExecutor, run_clients_servers)
|
||||
executor.add_node(node);
|
||||
|
||||
bool spin_exited = false;
|
||||
std::thread spinner([&spin_exited, &executor, this]() {
|
||||
std::thread spinner([&spin_exited, &executor]() {
|
||||
executor.spin();
|
||||
spin_exited = true;
|
||||
});
|
||||
@@ -346,7 +346,7 @@ TEST_F(TestEventsExecutor, cancel_while_timers_running)
|
||||
});
|
||||
|
||||
|
||||
std::thread spinner([&executor, this]() {executor.spin();});
|
||||
std::thread spinner([&executor]() {executor.spin();});
|
||||
|
||||
std::this_thread::sleep_for(10ms);
|
||||
// Call cancel while t1 callback is still being executed
|
||||
@@ -373,7 +373,7 @@ TEST_F(TestEventsExecutor, cancel_while_timers_waiting)
|
||||
executor.add_node(node);
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
std::thread spinner([&executor, this]() {executor.spin();});
|
||||
std::thread spinner([&executor]() {executor.spin();});
|
||||
|
||||
std::this_thread::sleep_for(10ms);
|
||||
executor.cancel();
|
||||
@@ -395,7 +395,7 @@ TEST_F(TestEventsExecutor, destroy_entities)
|
||||
2ms, [&]() {publisher->publish(std::make_unique<test_msgs::msg::Empty>());});
|
||||
EventsExecutor executor_pub;
|
||||
executor_pub.add_node(node_pub);
|
||||
std::thread spinner([&executor_pub, this]() {executor_pub.spin();});
|
||||
std::thread spinner([&executor_pub]() {executor_pub.spin();});
|
||||
|
||||
// Create a node with two different subscriptions to the topic
|
||||
auto node_sub = std::make_shared<rclcpp::Node>("node_sub");
|
||||
|
||||
@@ -644,6 +644,7 @@ TYPED_TEST(TestExecutors, testRaceConditionAddNode)
|
||||
break;
|
||||
}
|
||||
total += k * (i + 42);
|
||||
(void)total;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -779,7 +780,7 @@ TYPED_TEST(TestIntraprocessExecutors, testIntraprocessRetrigger) {
|
||||
// that publishers aren't continuing to publish.
|
||||
// This was previously broken in that intraprocess guard conditions were only triggered on
|
||||
// publish and the test was added to prevent future regressions.
|
||||
const size_t kNumMessages = 100;
|
||||
static constexpr size_t kNumMessages = 100;
|
||||
|
||||
using ExecutorType = TypeParam;
|
||||
ExecutorType executor;
|
||||
@@ -808,11 +809,9 @@ TYPED_TEST(TestIntraprocessExecutors, testIntraprocessRetrigger) {
|
||||
// Fire a timer every 10ms up to 5 seconds waiting for subscriptions to be read.
|
||||
loops = 0;
|
||||
auto timer = this->node->create_wall_timer(
|
||||
std::chrono::milliseconds(10), [this, &executor, &loops, &kNumMessages]() {
|
||||
std::chrono::milliseconds(10), [this, &executor, &loops]() {
|
||||
loops++;
|
||||
if (kNumMessages == this->callback_count.load() ||
|
||||
loops == 500)
|
||||
{
|
||||
if (kNumMessages == this->callback_count.load() || loops == 500) {
|
||||
executor.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -129,6 +129,9 @@ TEST_F(TestNodeGraph, construct_from_node)
|
||||
|
||||
EXPECT_EQ(0u, node_graph()->count_publishers("not_a_topic"));
|
||||
EXPECT_EQ(0u, node_graph()->count_subscribers("not_a_topic"));
|
||||
EXPECT_EQ(0u, node_graph()->count_clients("not_a_service"));
|
||||
EXPECT_EQ(0u, node_graph()->count_services("not_a_service"));
|
||||
|
||||
EXPECT_NE(nullptr, node_graph()->get_graph_guard_condition());
|
||||
|
||||
// get_graph_event is non-const
|
||||
@@ -534,6 +537,22 @@ TEST_F(TestNodeGraph, count_subscribers_rcl_error)
|
||||
std::runtime_error("could not count subscribers: error not set"));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, count_clients_rcl_error)
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_count_clients, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
node_graph()->count_clients("service"),
|
||||
std::runtime_error("could not count clients: error not set"));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, count_services_rcl_error)
|
||||
{
|
||||
auto mock = mocking_utils::patch_and_return("lib:rclcpp", rcl_count_services, RCL_RET_ERROR);
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
node_graph()->count_services("service"),
|
||||
std::runtime_error("could not count services: error not set"));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, notify_shutdown)
|
||||
{
|
||||
EXPECT_NO_THROW(node()->get_node_graph_interface()->notify_shutdown());
|
||||
|
||||
@@ -95,15 +95,15 @@ TEST_F(TestNodeParameters, list_parameters)
|
||||
std::find(list_result2.names.begin(), list_result2.names.end(), parameter_name),
|
||||
list_result2.names.end());
|
||||
|
||||
// Check prefixes
|
||||
// Check prefixes and the depth relative to the given prefixes
|
||||
const std::string parameter_name2 = "prefix.new_parameter";
|
||||
const rclcpp::ParameterValue value2(true);
|
||||
const rcl_interfaces::msg::ParameterDescriptor descriptor2;
|
||||
const auto added_parameter_value2 =
|
||||
node_parameters->declare_parameter(parameter_name2, value2, descriptor2, false);
|
||||
EXPECT_EQ(value.get<bool>(), added_parameter_value.get<bool>());
|
||||
EXPECT_EQ(value2.get<bool>(), added_parameter_value2.get<bool>());
|
||||
prefixes = {"prefix"};
|
||||
auto list_result3 = node_parameters->list_parameters(prefixes, 2u);
|
||||
auto list_result3 = node_parameters->list_parameters(prefixes, 1u);
|
||||
EXPECT_EQ(1u, list_result3.names.size());
|
||||
EXPECT_NE(
|
||||
std::find(list_result3.names.begin(), list_result3.names.end(), parameter_name2),
|
||||
@@ -116,6 +116,13 @@ TEST_F(TestNodeParameters, list_parameters)
|
||||
EXPECT_NE(
|
||||
std::find(list_result4.names.begin(), list_result4.names.end(), parameter_name),
|
||||
list_result4.names.end());
|
||||
|
||||
// Return all parameters when the depth = 0
|
||||
auto list_result5 = node_parameters->list_parameters(prefixes, 0u);
|
||||
EXPECT_EQ(1u, list_result5.names.size());
|
||||
EXPECT_NE(
|
||||
std::find(list_result5.names.begin(), list_result5.names.end(), parameter_name),
|
||||
list_result5.names.end());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, parameter_overrides)
|
||||
|
||||
@@ -43,10 +43,9 @@ TEST_F(TestNodeTypeDescriptions, disabled_no_service)
|
||||
node_options.append_parameter_override("start_type_description_service", false);
|
||||
rclcpp::Node node{"node", "ns", node_options};
|
||||
|
||||
rcl_node_t * rcl_node = node.get_node_base_interface()->get_rcl_node_handle();
|
||||
rcl_service_t * srv = nullptr;
|
||||
rcl_ret_t ret = rcl_node_get_type_description_service(rcl_node, &srv);
|
||||
ASSERT_EQ(RCL_RET_NOT_INIT, ret);
|
||||
auto services = node.get_node_graph_interface()->get_service_names_and_types_by_node(
|
||||
"node", "/ns");
|
||||
EXPECT_TRUE(services.find("/ns/node/get_type_description") == services.end());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeTypeDescriptions, enabled_creates_service)
|
||||
@@ -55,9 +54,8 @@ TEST_F(TestNodeTypeDescriptions, enabled_creates_service)
|
||||
node_options.append_parameter_override("start_type_description_service", true);
|
||||
rclcpp::Node node{"node", "ns", node_options};
|
||||
|
||||
rcl_node_t * rcl_node = node.get_node_base_interface()->get_rcl_node_handle();
|
||||
rcl_service_t * srv = nullptr;
|
||||
rcl_ret_t ret = rcl_node_get_type_description_service(rcl_node, &srv);
|
||||
ASSERT_EQ(RCL_RET_OK, ret);
|
||||
ASSERT_NE(nullptr, srv);
|
||||
auto services = node.get_node_graph_interface()->get_service_names_and_types_by_node(
|
||||
"node", "/ns");
|
||||
|
||||
EXPECT_TRUE(services.find("/ns/node/get_type_description") != services.end());
|
||||
}
|
||||
|
||||
@@ -56,18 +56,28 @@ TEST_F(TestMessagePoolMemoryStrategy, borrow_too_many) {
|
||||
// Size is 1, borrowing second time should fail
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
message_memory_strategy_->borrow_message(),
|
||||
std::runtime_error("Tried to access message that was still in use! Abort."));
|
||||
std::runtime_error("No more free slots in the pool"));
|
||||
EXPECT_NO_THROW(message_memory_strategy_->return_message(message));
|
||||
}
|
||||
|
||||
TEST_F(TestMessagePoolMemoryStrategy, return_unrecognized) {
|
||||
auto message = message_memory_strategy_->borrow_message();
|
||||
ASSERT_NE(nullptr, message);
|
||||
TEST_F(TestMessagePoolMemoryStrategy, borrow_hold_reference) {
|
||||
{
|
||||
auto message = message_memory_strategy_->borrow_message();
|
||||
ASSERT_NE(nullptr, message);
|
||||
|
||||
auto unrecognized = std::make_shared<test_msgs::msg::Empty>();
|
||||
// Unrecognized does not belong to pool
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
message_memory_strategy_->return_message(unrecognized),
|
||||
std::runtime_error("Unrecognized message ptr in return_message."));
|
||||
EXPECT_NO_THROW(message_memory_strategy_->return_message(message));
|
||||
// Return it.
|
||||
EXPECT_NO_THROW(message_memory_strategy_->return_message(message));
|
||||
|
||||
// But we are still holding the reference, so we expect that there is still no room in the pool.
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
message_memory_strategy_->borrow_message(),
|
||||
std::runtime_error("No more free slots in the pool"));
|
||||
}
|
||||
|
||||
// Now that we've dropped the reference (left the scope), we expect to be able to borrow again.
|
||||
|
||||
auto message2 = message_memory_strategy_->borrow_message();
|
||||
ASSERT_NE(nullptr, message2);
|
||||
|
||||
EXPECT_NO_THROW(message_memory_strategy_->return_message(message2));
|
||||
}
|
||||
|
||||
88
rclcpp/test/rclcpp/test_copy_all_parameter_values.cpp
Normal file
88
rclcpp/test/rclcpp/test_copy_all_parameter_values.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2023 Open Navigation LLC
|
||||
//
|
||||
// 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 "rclcpp/copy_all_parameter_values.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
class TestNode : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestNode, TestParamCopying)
|
||||
{
|
||||
auto node1 = std::make_shared<rclcpp::Node>("test_node1");
|
||||
auto node2 = std::make_shared<rclcpp::Node>("test_node2");
|
||||
|
||||
// Tests for (1) multiple types, (2) recursion, (3) overriding values
|
||||
node1->declare_parameter("Foo1", rclcpp::ParameterValue(std::string(("bar1"))));
|
||||
node1->declare_parameter("Foo2", rclcpp::ParameterValue(0.123));
|
||||
node1->declare_parameter("Foo", rclcpp::ParameterValue(std::string(("bar"))));
|
||||
node1->declare_parameter("Foo.bar", rclcpp::ParameterValue(std::string(("steve"))));
|
||||
node2->declare_parameter("Foo", rclcpp::ParameterValue(std::string(("barz2"))));
|
||||
|
||||
// Show Node2 is empty of Node1's parameters, but contains its own
|
||||
EXPECT_FALSE(node2->has_parameter("Foo1"));
|
||||
EXPECT_FALSE(node2->has_parameter("Foo2"));
|
||||
EXPECT_FALSE(node2->has_parameter("Foo.bar"));
|
||||
EXPECT_TRUE(node2->has_parameter("Foo"));
|
||||
EXPECT_EQ(node2->get_parameter("Foo").as_string(), std::string("barz2"));
|
||||
|
||||
bool override = false;
|
||||
rclcpp::copy_all_parameter_values(node1, node2, override);
|
||||
|
||||
// Test new parameters exist, of expected value, and original param is not overridden
|
||||
EXPECT_TRUE(node2->has_parameter("Foo1"));
|
||||
EXPECT_EQ(node2->get_parameter("Foo1").as_string(), std::string("bar1"));
|
||||
EXPECT_TRUE(node2->has_parameter("Foo2"));
|
||||
EXPECT_EQ(node2->get_parameter("Foo2").as_double(), 0.123);
|
||||
EXPECT_TRUE(node2->has_parameter("Foo.bar"));
|
||||
EXPECT_EQ(node2->get_parameter("Foo.bar").as_string(), std::string("steve"));
|
||||
EXPECT_TRUE(node2->has_parameter("Foo"));
|
||||
EXPECT_EQ(node2->get_parameter("Foo").as_string(), std::string("barz2"));
|
||||
|
||||
// Test if parameter overrides are permissible that Node2's value is overridden
|
||||
override = true;
|
||||
rclcpp::copy_all_parameter_values(node1, node2, override);
|
||||
EXPECT_EQ(node2->get_parameter("Foo").as_string(), std::string("bar"));
|
||||
}
|
||||
|
||||
TEST_F(TestNode, TestParamCopyingExceptions)
|
||||
{
|
||||
auto node1 = std::make_shared<rclcpp::Node>("test_node1");
|
||||
auto node2 = std::make_shared<rclcpp::Node>("test_node2");
|
||||
|
||||
// Tests for Parameter value conflicts handled
|
||||
node1->declare_parameter("Foo", rclcpp::ParameterValue(std::string(("bar"))));
|
||||
node2->declare_parameter("Foo", rclcpp::ParameterValue(0.123));
|
||||
|
||||
bool override = true;
|
||||
EXPECT_NO_THROW(
|
||||
rclcpp::copy_all_parameter_values(node1, node2, override));
|
||||
|
||||
// Tests for Parameter read-only handled
|
||||
node1->declare_parameter("Foo1", rclcpp::ParameterValue(std::string(("bar"))));
|
||||
node2->declare_parameter("Foo1", rclcpp::ParameterValue(0.123));
|
||||
EXPECT_NO_THROW(rclcpp::copy_all_parameter_values(node1, node2, override));
|
||||
}
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
size_t counter = 0;
|
||||
auto subscription = node_->create_generic_subscription(
|
||||
topic_name, type, rclcpp::QoS(1),
|
||||
[&counter, &messages, this](std::shared_ptr<rclcpp::SerializedMessage> message) {
|
||||
[&counter, &messages, this](const std::shared_ptr<const rclcpp::SerializedMessage> message) {
|
||||
T2 deserialized_message;
|
||||
rclcpp::Serialization<T2> serializer;
|
||||
serializer.deserialize_message(message.get(), &deserialized_message);
|
||||
@@ -236,7 +236,7 @@ TEST_F(RclcppGenericNodeFixture, generic_subscription_uses_qos)
|
||||
auto publisher = node_->create_publisher<test_msgs::msg::Strings>(topic_name, qos);
|
||||
auto subscription = node_->create_generic_subscription(
|
||||
topic_name, topic_type, qos,
|
||||
[](std::shared_ptr<rclcpp::SerializedMessage>/* message */) {});
|
||||
[](std::shared_ptr<const rclcpp::SerializedMessage>/* message */) {});
|
||||
auto connected = [publisher, subscription]() -> bool {
|
||||
return publisher->get_subscription_count() && subscription->get_publisher_count();
|
||||
};
|
||||
@@ -263,3 +263,49 @@ TEST_F(RclcppGenericNodeFixture, generic_publisher_uses_qos)
|
||||
// It normally takes < 20ms, 5s chosen as "a very long time"
|
||||
ASSERT_TRUE(wait_for(connected, 5s));
|
||||
}
|
||||
|
||||
TEST_F(RclcppGenericNodeFixture, generic_subscription_different_callbacks)
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
std::string topic_name = "string_topic";
|
||||
std::string topic_type = "test_msgs/msg/Strings";
|
||||
rclcpp::QoS qos = rclcpp::QoS(1);
|
||||
|
||||
auto publisher = node_->create_publisher<test_msgs::msg::Strings>(topic_name, qos);
|
||||
|
||||
// Test shared_ptr for const messages
|
||||
{
|
||||
auto subscription = node_->create_generic_subscription(
|
||||
topic_name, topic_type, qos,
|
||||
[](const std::shared_ptr<const rclcpp::SerializedMessage>/* message */) {});
|
||||
auto connected = [publisher, subscription]() -> bool {
|
||||
return publisher->get_subscription_count() && subscription->get_publisher_count();
|
||||
};
|
||||
// It normally takes < 20ms, 5s chosen as "a very long time"
|
||||
ASSERT_TRUE(wait_for(connected, 5s));
|
||||
}
|
||||
|
||||
// Test unique_ptr
|
||||
{
|
||||
auto subscription = node_->create_generic_subscription(
|
||||
topic_name, topic_type, qos,
|
||||
[](std::unique_ptr<rclcpp::SerializedMessage>/* message */) {});
|
||||
auto connected = [publisher, subscription]() -> bool {
|
||||
return publisher->get_subscription_count() && subscription->get_publisher_count();
|
||||
};
|
||||
// It normally takes < 20ms, 5s chosen as "a very long time"
|
||||
ASSERT_TRUE(wait_for(connected, 5s));
|
||||
}
|
||||
|
||||
// Test message callback
|
||||
{
|
||||
auto subscription = node_->create_generic_subscription(
|
||||
topic_name, topic_type, qos,
|
||||
[](rclcpp::SerializedMessage /* message */) {});
|
||||
auto connected = [publisher, subscription]() -> bool {
|
||||
return publisher->get_subscription_count() && subscription->get_publisher_count();
|
||||
};
|
||||
// It normally takes < 20ms, 5s chosen as "a very long time"
|
||||
ASSERT_TRUE(wait_for(connected, 5s));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ public:
|
||||
}
|
||||
|
||||
bool
|
||||
use_take_shared_method() const
|
||||
use_take_shared_method() const override
|
||||
{
|
||||
return take_shared_method;
|
||||
}
|
||||
|
||||
@@ -3311,6 +3311,9 @@ TEST_F(TestNode, get_entity_names) {
|
||||
const auto service_names_and_types = node->get_service_names_and_types();
|
||||
EXPECT_EQ(service_names_and_types.end(), service_names_and_types.find("service"));
|
||||
|
||||
EXPECT_EQ(0u, node->count_clients("service"));
|
||||
EXPECT_EQ(0u, node->count_services("service"));
|
||||
|
||||
const auto service_names_and_types_by_node =
|
||||
node->get_service_names_and_types_by_node("node", "/ns");
|
||||
EXPECT_EQ(
|
||||
|
||||
@@ -482,7 +482,7 @@ public:
|
||||
|
||||
void publish_loaned_message(rclcpp::LoanedMessage<MessageT, AllocatorT> && loaned_msg)
|
||||
{
|
||||
this->do_loaned_message_publish(std::move(loaned_msg.release()));
|
||||
this->do_loaned_message_publish(loaned_msg.release());
|
||||
}
|
||||
|
||||
void call_default_incompatible_qos_callback(rclcpp::QOSOfferedIncompatibleQoSInfo & event) const
|
||||
|
||||
@@ -152,33 +152,54 @@ TEST_F(TestPublisher, conversion_exception_is_passed_up) {
|
||||
}
|
||||
}
|
||||
|
||||
using UseTakeSharedMethod = bool;
|
||||
class TestPublisherFixture
|
||||
: public TestPublisher,
|
||||
public ::testing::WithParamInterface<UseTakeSharedMethod>
|
||||
{
|
||||
};
|
||||
|
||||
/*
|
||||
* Testing that publisher sends type adapted types and ROS message types with intra proccess communications.
|
||||
*/
|
||||
TEST_F(
|
||||
TestPublisher,
|
||||
TEST_P(
|
||||
TestPublisherFixture,
|
||||
check_type_adapted_message_is_sent_and_received_intra_process) {
|
||||
using StringTypeAdapter = rclcpp::TypeAdapter<std::string, rclcpp::msg::String>;
|
||||
const std::string message_data = "Message Data";
|
||||
const std::string topic_name = "topic_name";
|
||||
bool is_received;
|
||||
|
||||
auto callback =
|
||||
[message_data, &is_received](
|
||||
const rclcpp::msg::String::ConstSharedPtr msg,
|
||||
const rclcpp::MessageInfo & message_info
|
||||
) -> void
|
||||
{
|
||||
is_received = true;
|
||||
ASSERT_STREQ(message_data.c_str(), msg->data.c_str());
|
||||
ASSERT_TRUE(message_info.get_rmw_message_info().from_intra_process);
|
||||
};
|
||||
|
||||
auto node = rclcpp::Node::make_shared(
|
||||
"test_intra_process",
|
||||
rclcpp::NodeOptions().use_intra_process_comms(true));
|
||||
auto pub = node->create_publisher<StringTypeAdapter>(topic_name, 10);
|
||||
auto sub = node->create_subscription<rclcpp::msg::String>(topic_name, 1, callback);
|
||||
rclcpp::Subscription<rclcpp::msg::String>::SharedPtr sub;
|
||||
if (GetParam()) {
|
||||
auto callback =
|
||||
[message_data, &is_received](
|
||||
const rclcpp::msg::String::ConstSharedPtr msg,
|
||||
const rclcpp::MessageInfo & message_info
|
||||
) -> void
|
||||
{
|
||||
is_received = true;
|
||||
ASSERT_STREQ(message_data.c_str(), msg->data.c_str());
|
||||
ASSERT_TRUE(message_info.get_rmw_message_info().from_intra_process);
|
||||
};
|
||||
sub = node->create_subscription<rclcpp::msg::String>(topic_name, 1, callback);
|
||||
} else {
|
||||
auto callback_unique =
|
||||
[message_data, &is_received](
|
||||
rclcpp::msg::String::UniquePtr msg,
|
||||
const rclcpp::MessageInfo & message_info
|
||||
) -> void
|
||||
{
|
||||
is_received = true;
|
||||
ASSERT_STREQ(message_data.c_str(), msg->data.c_str());
|
||||
ASSERT_TRUE(message_info.get_rmw_message_info().from_intra_process);
|
||||
};
|
||||
sub = node->create_subscription<rclcpp::msg::String>(topic_name, 1, callback_unique);
|
||||
}
|
||||
|
||||
auto wait_for_message_to_be_received = [&is_received, &node]() {
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
@@ -239,6 +260,14 @@ TEST_F(
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
TestPublisherFixtureWithParam,
|
||||
TestPublisherFixture,
|
||||
::testing::Values(
|
||||
true, // use take shared method
|
||||
false // not use take shared method
|
||||
));
|
||||
|
||||
/*
|
||||
* Testing that publisher sends type adapted types and ROS message types with inter proccess communications.
|
||||
*/
|
||||
|
||||
@@ -14,14 +14,31 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/rate.hpp"
|
||||
|
||||
#include "../utils/rclcpp_gtest_macros.hpp"
|
||||
|
||||
class TestRate : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Basic tests for the Rate and WallRate classes.
|
||||
*/
|
||||
TEST(TestRate, rate_basics) {
|
||||
TEST_F(TestRate, rate_basics) {
|
||||
auto period = std::chrono::milliseconds(1000);
|
||||
auto offset = std::chrono::milliseconds(500);
|
||||
auto epsilon = std::chrono::milliseconds(100);
|
||||
@@ -29,8 +46,23 @@ TEST(TestRate, rate_basics) {
|
||||
|
||||
auto start = std::chrono::system_clock::now();
|
||||
rclcpp::Rate r(period);
|
||||
EXPECT_EQ(period, r.period());
|
||||
EXPECT_EQ(rclcpp::Duration(period), r.period());
|
||||
// suppress deprecated warnings
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
ASSERT_FALSE(r.is_steady());
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
ASSERT_EQ(RCL_SYSTEM_TIME, r.get_type());
|
||||
ASSERT_TRUE(r.sleep());
|
||||
auto one = std::chrono::system_clock::now();
|
||||
auto delta = one - start;
|
||||
@@ -61,7 +93,7 @@ TEST(TestRate, rate_basics) {
|
||||
ASSERT_TRUE(epsilon > delta);
|
||||
}
|
||||
|
||||
TEST(TestRate, wall_rate_basics) {
|
||||
TEST_F(TestRate, wall_rate_basics) {
|
||||
auto period = std::chrono::milliseconds(100);
|
||||
auto offset = std::chrono::milliseconds(50);
|
||||
auto epsilon = std::chrono::milliseconds(1);
|
||||
@@ -69,8 +101,25 @@ TEST(TestRate, wall_rate_basics) {
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
rclcpp::WallRate r(period);
|
||||
EXPECT_EQ(period, r.period());
|
||||
EXPECT_EQ(rclcpp::Duration(period), r.period());
|
||||
// suppress deprecated warnings
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
ASSERT_TRUE(r.is_steady());
|
||||
// suppress deprecated warnings
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
ASSERT_EQ(RCL_STEADY_TIME, r.get_type());
|
||||
ASSERT_TRUE(r.sleep());
|
||||
auto one = std::chrono::steady_clock::now();
|
||||
auto delta = one - start;
|
||||
@@ -101,21 +150,221 @@ TEST(TestRate, wall_rate_basics) {
|
||||
EXPECT_GT(epsilon, delta);
|
||||
}
|
||||
|
||||
TEST(TestRate, from_double) {
|
||||
/*
|
||||
Basic test for the deprecated GenericRate class.
|
||||
*/
|
||||
TEST_F(TestRate, generic_rate) {
|
||||
auto period = std::chrono::milliseconds(100);
|
||||
auto offset = std::chrono::milliseconds(50);
|
||||
auto epsilon = std::chrono::milliseconds(1);
|
||||
double overrun_ratio = 1.5;
|
||||
|
||||
{
|
||||
rclcpp::WallRate rate(1.0);
|
||||
EXPECT_EQ(std::chrono::seconds(1), rate.period());
|
||||
auto start = std::chrono::system_clock::now();
|
||||
|
||||
// suppress deprecated warnings
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
rclcpp::GenericRate<std::chrono::system_clock> gr(period);
|
||||
ASSERT_FALSE(gr.is_steady());
|
||||
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
ASSERT_EQ(gr.get_type(), RCL_SYSTEM_TIME);
|
||||
EXPECT_EQ(period, gr.period());
|
||||
ASSERT_TRUE(gr.sleep());
|
||||
auto one = std::chrono::system_clock::now();
|
||||
auto delta = one - start;
|
||||
EXPECT_LT(period, delta + epsilon);
|
||||
EXPECT_GT(period * overrun_ratio, delta);
|
||||
|
||||
rclcpp::sleep_for(offset);
|
||||
ASSERT_TRUE(gr.sleep());
|
||||
auto two = std::chrono::system_clock::now();
|
||||
delta = two - start;
|
||||
EXPECT_LT(2 * period, delta);
|
||||
EXPECT_GT(2 * period * overrun_ratio, delta);
|
||||
|
||||
rclcpp::sleep_for(offset);
|
||||
auto two_offset = std::chrono::system_clock::now();
|
||||
gr.reset();
|
||||
ASSERT_TRUE(gr.sleep());
|
||||
auto three = std::chrono::system_clock::now();
|
||||
delta = three - two_offset;
|
||||
EXPECT_LT(period, delta + epsilon);
|
||||
EXPECT_GT(period * overrun_ratio, delta);
|
||||
|
||||
rclcpp::sleep_for(offset + period);
|
||||
auto four = std::chrono::system_clock::now();
|
||||
ASSERT_FALSE(gr.sleep());
|
||||
auto five = std::chrono::system_clock::now();
|
||||
delta = five - four;
|
||||
ASSERT_TRUE(epsilon > delta);
|
||||
}
|
||||
|
||||
{
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
|
||||
// suppress deprecated warnings
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
rclcpp::GenericRate<std::chrono::steady_clock> gr(period);
|
||||
ASSERT_TRUE(gr.is_steady());
|
||||
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
ASSERT_EQ(gr.get_type(), RCL_STEADY_TIME);
|
||||
EXPECT_EQ(period, gr.period());
|
||||
ASSERT_TRUE(gr.sleep());
|
||||
auto one = std::chrono::steady_clock::now();
|
||||
auto delta = one - start;
|
||||
EXPECT_LT(period, delta);
|
||||
EXPECT_GT(period * overrun_ratio, delta);
|
||||
|
||||
rclcpp::sleep_for(offset);
|
||||
ASSERT_TRUE(gr.sleep());
|
||||
auto two = std::chrono::steady_clock::now();
|
||||
delta = two - start;
|
||||
EXPECT_LT(2 * period, delta + epsilon);
|
||||
EXPECT_GT(2 * period * overrun_ratio, delta);
|
||||
|
||||
rclcpp::sleep_for(offset);
|
||||
auto two_offset = std::chrono::steady_clock::now();
|
||||
gr.reset();
|
||||
ASSERT_TRUE(gr.sleep());
|
||||
auto three = std::chrono::steady_clock::now();
|
||||
delta = three - two_offset;
|
||||
EXPECT_LT(period, delta);
|
||||
EXPECT_GT(period * overrun_ratio, delta);
|
||||
|
||||
rclcpp::sleep_for(offset + period);
|
||||
auto four = std::chrono::steady_clock::now();
|
||||
ASSERT_FALSE(gr.sleep());
|
||||
auto five = std::chrono::steady_clock::now();
|
||||
delta = five - four;
|
||||
EXPECT_GT(epsilon, delta);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestRate, from_double) {
|
||||
{
|
||||
rclcpp::Rate rate(1.0);
|
||||
EXPECT_EQ(rclcpp::Duration(std::chrono::seconds(1)), rate.period());
|
||||
}
|
||||
{
|
||||
rclcpp::WallRate rate(2.0);
|
||||
EXPECT_EQ(std::chrono::milliseconds(500), rate.period());
|
||||
rclcpp::Rate rate(2.0);
|
||||
EXPECT_EQ(rclcpp::Duration(std::chrono::milliseconds(500)), rate.period());
|
||||
}
|
||||
{
|
||||
rclcpp::WallRate rate(0.5);
|
||||
EXPECT_EQ(std::chrono::seconds(2), rate.period());
|
||||
EXPECT_EQ(rclcpp::Duration(std::chrono::seconds(2)), rate.period());
|
||||
}
|
||||
{
|
||||
rclcpp::WallRate rate(4.0);
|
||||
EXPECT_EQ(std::chrono::milliseconds(250), rate.period());
|
||||
EXPECT_EQ(rclcpp::Duration(std::chrono::milliseconds(250)), rate.period());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestRate, clock_types) {
|
||||
{
|
||||
rclcpp::Rate rate(1.0, std::make_shared<rclcpp::Clock>(RCL_SYSTEM_TIME));
|
||||
// suppress deprecated warnings
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
EXPECT_FALSE(rate.is_steady());
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
EXPECT_EQ(RCL_SYSTEM_TIME, rate.get_type());
|
||||
}
|
||||
{
|
||||
rclcpp::Rate rate(1.0, std::make_shared<rclcpp::Clock>(RCL_STEADY_TIME));
|
||||
// suppress deprecated warnings
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
EXPECT_TRUE(rate.is_steady());
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
EXPECT_EQ(RCL_STEADY_TIME, rate.get_type());
|
||||
}
|
||||
{
|
||||
rclcpp::Rate rate(1.0, std::make_shared<rclcpp::Clock>(RCL_ROS_TIME));
|
||||
// suppress deprecated warnings
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
EXPECT_FALSE(rate.is_steady());
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
EXPECT_EQ(RCL_ROS_TIME, rate.get_type());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestRate, incorrect_constuctor) {
|
||||
// Constructor with 0-frequency
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
rclcpp::Rate rate(0.0),
|
||||
std::invalid_argument("rate must be greater than 0"));
|
||||
|
||||
// Constructor with negative frequency
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
rclcpp::Rate rate(-1.0),
|
||||
std::invalid_argument("rate must be greater than 0"));
|
||||
|
||||
// Constructor with 0-duration
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
rclcpp::Rate rate(rclcpp::Duration(0, 0)),
|
||||
std::invalid_argument("period must be greater than 0"));
|
||||
|
||||
// Constructor with negative duration
|
||||
RCLCPP_EXPECT_THROW_EQ(
|
||||
rclcpp::Rate rate(rclcpp::Duration(-1, 0)),
|
||||
std::invalid_argument("period must be greater than 0"));
|
||||
}
|
||||
|
||||
@@ -178,3 +178,13 @@ TEST_F(TestRosoutSubscription, test_rosoutsubscription_getchild_hierarchy) {
|
||||
EXPECT_TRUE(future.get());
|
||||
received_msg_promise = {};
|
||||
}
|
||||
|
||||
TEST_F(TestRosoutSubscription, test_rosoutsubscription_node_rosout_disabled) {
|
||||
rclcpp::NodeOptions options = rclcpp::NodeOptions().enable_rosout(false);
|
||||
auto node = std::make_shared<rclcpp::Node>("my_node", options);
|
||||
auto log_func = [&node] {
|
||||
auto logger = node->get_logger().get_child("child");
|
||||
RCLCPP_INFO(logger, "test");
|
||||
};
|
||||
ASSERT_NO_THROW(log_func());
|
||||
}
|
||||
|
||||
@@ -145,11 +145,6 @@ TEST(TestSerializedMessage, reserve) {
|
||||
// Resize using reserve method
|
||||
serialized_msg.reserve(15);
|
||||
EXPECT_EQ(15u, serialized_msg.capacity());
|
||||
|
||||
// Use invalid value throws exception
|
||||
EXPECT_THROW(
|
||||
{serialized_msg.reserve(-1);},
|
||||
rclcpp::exceptions::RCLBadAlloc);
|
||||
}
|
||||
|
||||
TEST(TestSerializedMessage, serialization) {
|
||||
|
||||
@@ -60,14 +60,17 @@ TEST_F(TestSubscriptionOptions, topic_statistics_options_default_and_set) {
|
||||
EXPECT_EQ(options.topic_stats_options.state, rclcpp::TopicStatisticsState::NodeDefault);
|
||||
EXPECT_EQ(options.topic_stats_options.publish_topic, defaultPublishTopic);
|
||||
EXPECT_EQ(options.topic_stats_options.publish_period, 1s);
|
||||
EXPECT_EQ(options.topic_stats_options.qos, rclcpp::SystemDefaultsQoS());
|
||||
|
||||
options.topic_stats_options.state = rclcpp::TopicStatisticsState::Enable;
|
||||
options.topic_stats_options.publish_topic = "topic_statistics";
|
||||
options.topic_stats_options.publish_period = 5min;
|
||||
options.topic_stats_options.qos = rclcpp::BestAvailableQoS();
|
||||
|
||||
EXPECT_EQ(options.topic_stats_options.state, rclcpp::TopicStatisticsState::Enable);
|
||||
EXPECT_EQ(options.topic_stats_options.publish_topic, "topic_statistics");
|
||||
EXPECT_EQ(options.topic_stats_options.publish_period, 5min);
|
||||
EXPECT_EQ(options.topic_stats_options.qos, rclcpp::BestAvailableQoS());
|
||||
}
|
||||
|
||||
TEST_F(TestSubscriptionOptions, topic_statistics_options_node_default_mode) {
|
||||
|
||||
@@ -363,10 +363,27 @@ TEST_F(TestTime, seconds) {
|
||||
}
|
||||
|
||||
TEST_F(TestTime, test_max) {
|
||||
const rclcpp::Time time_max = rclcpp::Time::max();
|
||||
const rclcpp::Time max_time(std::numeric_limits<int32_t>::max(), 999999999);
|
||||
EXPECT_DOUBLE_EQ(max_time.seconds(), time_max.seconds());
|
||||
EXPECT_EQ(max_time.nanoseconds(), time_max.nanoseconds());
|
||||
// Same clock types
|
||||
for (rcl_clock_type_t type = RCL_ROS_TIME;
|
||||
type != RCL_STEADY_TIME; type = static_cast<rcl_clock_type_t>(type + 1))
|
||||
{
|
||||
const rclcpp::Time time_max = rclcpp::Time::max(type);
|
||||
const rclcpp::Time max_time(std::numeric_limits<int32_t>::max(), 999999999, type);
|
||||
EXPECT_DOUBLE_EQ(max_time.seconds(), time_max.seconds());
|
||||
EXPECT_EQ(max_time.nanoseconds(), time_max.nanoseconds());
|
||||
}
|
||||
// Different clock types
|
||||
{
|
||||
const rclcpp::Time time_max = rclcpp::Time::max(RCL_ROS_TIME);
|
||||
const rclcpp::Time max_time(std::numeric_limits<int32_t>::max(), 999999999, RCL_STEADY_TIME);
|
||||
EXPECT_ANY_THROW((void)(time_max == max_time));
|
||||
EXPECT_ANY_THROW((void)(time_max != max_time));
|
||||
EXPECT_ANY_THROW((void)(time_max <= max_time));
|
||||
EXPECT_ANY_THROW((void)(time_max >= max_time));
|
||||
EXPECT_ANY_THROW((void)(time_max < max_time));
|
||||
EXPECT_ANY_THROW((void)(time_max > max_time));
|
||||
EXPECT_ANY_THROW((void)(time_max - max_time));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestTime, test_constructor_from_rcl_time_point) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
@@ -65,8 +66,10 @@ TEST_F(TestTimersManager, empty_manager)
|
||||
TEST_F(TestTimersManager, add_run_remove_timer)
|
||||
{
|
||||
size_t t_runs = 0;
|
||||
std::chrono::milliseconds timer_period(10);
|
||||
|
||||
auto t = TimerT::make_shared(
|
||||
10ms,
|
||||
timer_period,
|
||||
[&t_runs]() {
|
||||
t_runs++;
|
||||
},
|
||||
@@ -79,7 +82,7 @@ TEST_F(TestTimersManager, add_run_remove_timer)
|
||||
timers_manager->add_timer(t);
|
||||
|
||||
// Sleep for more 3 times the timer period
|
||||
std::this_thread::sleep_for(30ms);
|
||||
std::this_thread::sleep_for(3 * timer_period);
|
||||
|
||||
// The timer is executed only once, even if we slept 3 times the period
|
||||
execute_all_ready_timers(timers_manager);
|
||||
@@ -191,67 +194,6 @@ TEST_F(TestTimersManager, head_not_ready)
|
||||
EXPECT_EQ(0u, t_runs);
|
||||
}
|
||||
|
||||
TEST_F(TestTimersManager, timers_order)
|
||||
{
|
||||
auto timers_manager = std::make_shared<TimersManager>(
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
size_t t1_runs = 0;
|
||||
auto t1 = TimerT::make_shared(
|
||||
10ms,
|
||||
[&t1_runs]() {
|
||||
t1_runs++;
|
||||
},
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
size_t t2_runs = 0;
|
||||
auto t2 = TimerT::make_shared(
|
||||
30ms,
|
||||
[&t2_runs]() {
|
||||
t2_runs++;
|
||||
},
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
size_t t3_runs = 0;
|
||||
auto t3 = TimerT::make_shared(
|
||||
100ms,
|
||||
[&t3_runs]() {
|
||||
t3_runs++;
|
||||
},
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
// Add timers in a random order
|
||||
timers_manager->add_timer(t2);
|
||||
timers_manager->add_timer(t3);
|
||||
timers_manager->add_timer(t1);
|
||||
|
||||
std::this_thread::sleep_for(10ms);
|
||||
execute_all_ready_timers(timers_manager);
|
||||
EXPECT_EQ(1u, t1_runs);
|
||||
EXPECT_EQ(0u, t2_runs);
|
||||
EXPECT_EQ(0u, t3_runs);
|
||||
|
||||
std::this_thread::sleep_for(30ms);
|
||||
execute_all_ready_timers(timers_manager);
|
||||
EXPECT_EQ(2u, t1_runs);
|
||||
EXPECT_EQ(1u, t2_runs);
|
||||
EXPECT_EQ(0u, t3_runs);
|
||||
|
||||
std::this_thread::sleep_for(100ms);
|
||||
execute_all_ready_timers(timers_manager);
|
||||
EXPECT_EQ(3u, t1_runs);
|
||||
EXPECT_EQ(2u, t2_runs);
|
||||
EXPECT_EQ(1u, t3_runs);
|
||||
|
||||
timers_manager->remove_timer(t1);
|
||||
|
||||
std::this_thread::sleep_for(30ms);
|
||||
execute_all_ready_timers(timers_manager);
|
||||
EXPECT_EQ(3u, t1_runs);
|
||||
EXPECT_EQ(3u, t2_runs);
|
||||
EXPECT_EQ(1u, t3_runs);
|
||||
}
|
||||
|
||||
TEST_F(TestTimersManager, start_stop_timers_thread)
|
||||
{
|
||||
auto timers_manager = std::make_shared<TimersManager>(
|
||||
@@ -274,7 +216,7 @@ TEST_F(TestTimersManager, timers_thread)
|
||||
auto timers_manager = std::make_shared<TimersManager>(
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
size_t t1_runs = 0;
|
||||
int t1_runs = 0;
|
||||
auto t1 = TimerT::make_shared(
|
||||
1ms,
|
||||
[&t1_runs]() {
|
||||
@@ -282,7 +224,7 @@ TEST_F(TestTimersManager, timers_thread)
|
||||
},
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
size_t t2_runs = 0;
|
||||
int t2_runs = 0;
|
||||
auto t2 = TimerT::make_shared(
|
||||
1ms,
|
||||
[&t2_runs]() {
|
||||
@@ -296,12 +238,12 @@ TEST_F(TestTimersManager, timers_thread)
|
||||
|
||||
// Run timers thread for a while
|
||||
timers_manager->start();
|
||||
std::this_thread::sleep_for(5ms);
|
||||
std::this_thread::sleep_for(50ms);
|
||||
timers_manager->stop();
|
||||
|
||||
EXPECT_LT(1u, t1_runs);
|
||||
EXPECT_LT(1u, t2_runs);
|
||||
EXPECT_EQ(t1_runs, t2_runs);
|
||||
EXPECT_LE(std::abs(t1_runs - t2_runs), 1);
|
||||
}
|
||||
|
||||
TEST_F(TestTimersManager, destructor)
|
||||
@@ -365,13 +307,13 @@ TEST_F(TestTimersManager, add_remove_while_thread_running)
|
||||
timers_manager->start();
|
||||
|
||||
// After a while remove t1 and add t2
|
||||
std::this_thread::sleep_for(5ms);
|
||||
std::this_thread::sleep_for(50ms);
|
||||
timers_manager->remove_timer(t1);
|
||||
size_t tmp_t1 = t1_runs;
|
||||
timers_manager->add_timer(t2);
|
||||
|
||||
// Wait some more time and then stop
|
||||
std::this_thread::sleep_for(5ms);
|
||||
std::this_thread::sleep_for(50ms);
|
||||
timers_manager->stop();
|
||||
|
||||
// t1 has stopped running
|
||||
|
||||
@@ -50,7 +50,7 @@ TEST(TypesupportHelpersTest, returns_c_type_info_for_valid_legacy_library) {
|
||||
try {
|
||||
auto library = rclcpp::get_typesupport_library(
|
||||
"test_msgs/BasicTypes", "rosidl_typesupport_cpp");
|
||||
auto string_typesupport = rclcpp::get_typesupport_handle(
|
||||
auto string_typesupport = rclcpp::get_message_typesupport_handle(
|
||||
"test_msgs/BasicTypes", "rosidl_typesupport_cpp", *library);
|
||||
|
||||
EXPECT_THAT(
|
||||
@@ -65,7 +65,7 @@ TEST(TypesupportHelpersTest, returns_c_type_info_for_valid_library) {
|
||||
try {
|
||||
auto library = rclcpp::get_typesupport_library(
|
||||
"test_msgs/msg/BasicTypes", "rosidl_typesupport_cpp");
|
||||
auto string_typesupport = rclcpp::get_typesupport_handle(
|
||||
auto string_typesupport = rclcpp::get_message_typesupport_handle(
|
||||
"test_msgs/msg/BasicTypes", "rosidl_typesupport_cpp", *library);
|
||||
|
||||
EXPECT_THAT(
|
||||
@@ -75,3 +75,52 @@ TEST(TypesupportHelpersTest, returns_c_type_info_for_valid_library) {
|
||||
FAIL() << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TypesupportHelpersTest, returns_service_type_info_for_valid_legacy_library) {
|
||||
try {
|
||||
auto library = rclcpp::get_typesupport_library(
|
||||
"test_msgs/Empty", "rosidl_typesupport_cpp");
|
||||
auto empty_typesupport = rclcpp::get_service_typesupport_handle(
|
||||
"test_msgs/Empty", "rosidl_typesupport_cpp", *library);
|
||||
|
||||
EXPECT_THAT(
|
||||
std::string(empty_typesupport->typesupport_identifier),
|
||||
ContainsRegex("rosidl_typesupport"));
|
||||
} catch (const std::runtime_error & e) {
|
||||
FAIL() << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TypesupportHelpersTest, returns_service_type_info_for_valid_library) {
|
||||
try {
|
||||
auto library = rclcpp::get_typesupport_library(
|
||||
"test_msgs/srv/Empty", "rosidl_typesupport_cpp");
|
||||
auto empty_typesupport = rclcpp::get_service_typesupport_handle(
|
||||
"test_msgs/srv/Empty", "rosidl_typesupport_cpp", *library);
|
||||
|
||||
EXPECT_THAT(
|
||||
std::string(empty_typesupport->typesupport_identifier),
|
||||
ContainsRegex("rosidl_typesupport"));
|
||||
} catch (const std::runtime_error & e) {
|
||||
FAIL() << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TypesupportHelpersTest, test_throw_exception_with_invalid_type) {
|
||||
// message
|
||||
std::string invalid_type = "test_msgs/msg/InvalidType";
|
||||
auto library = rclcpp::get_typesupport_library(invalid_type, "rosidl_typesupport_cpp");
|
||||
EXPECT_THROW(
|
||||
rclcpp::get_message_typesupport_handle(invalid_type, "rosidl_typesupport_cpp", *library),
|
||||
std::runtime_error);
|
||||
EXPECT_THROW(
|
||||
rclcpp::get_service_typesupport_handle(invalid_type, "rosidl_typesupport_cpp", *library),
|
||||
std::runtime_error);
|
||||
|
||||
// service
|
||||
invalid_type = "test_msgs/srv/InvalidType";
|
||||
library = rclcpp::get_typesupport_library(invalid_type, "rosidl_typesupport_cpp");
|
||||
EXPECT_THROW(
|
||||
rclcpp::get_service_typesupport_handle(invalid_type, "rosidl_typesupport_cpp", *library),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@@ -22,12 +21,12 @@
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "libstatistics_collector/moving_average_statistics/types.hpp"
|
||||
|
||||
#include "rclcpp/create_publisher.hpp"
|
||||
#include "rclcpp/msg/message_with_header.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
@@ -36,10 +35,10 @@
|
||||
#include "rclcpp/topic_statistics/subscription_topic_statistics.hpp"
|
||||
|
||||
#include "statistics_msgs/msg/metrics_message.hpp"
|
||||
#include "statistics_msgs/msg/statistic_data_point.hpp"
|
||||
#include "statistics_msgs/msg/statistic_data_type.hpp"
|
||||
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
#include "test_msgs/msg/strings.hpp"
|
||||
|
||||
#include "test_topic_stats_utils.hpp"
|
||||
|
||||
@@ -67,7 +66,6 @@ constexpr const std::chrono::seconds kUnstableMessageAgeWindowDuration{
|
||||
constexpr const std::chrono::seconds kUnstableMessageAgeOffset{std::chrono::seconds{1}};
|
||||
} // namespace
|
||||
|
||||
using rclcpp::msg::MessageWithHeader;
|
||||
using test_msgs::msg::Empty;
|
||||
using rclcpp::topic_statistics::SubscriptionTopicStatistics;
|
||||
using statistics_msgs::msg::MetricsMessage;
|
||||
@@ -76,114 +74,73 @@ using statistics_msgs::msg::StatisticDataType;
|
||||
using libstatistics_collector::moving_average_statistics::StatisticData;
|
||||
|
||||
/**
|
||||
* Wrapper class to test and expose parts of the SubscriptionTopicStatistics<T> class.
|
||||
* \tparam CallbackMessageT
|
||||
* Wrapper class to test and expose parts of the SubscriptionTopicStatistics class.
|
||||
*/
|
||||
template<typename CallbackMessageT>
|
||||
class TestSubscriptionTopicStatistics : public SubscriptionTopicStatistics<CallbackMessageT>
|
||||
class TestSubscriptionTopicStatistics : public SubscriptionTopicStatistics
|
||||
{
|
||||
public:
|
||||
TestSubscriptionTopicStatistics(
|
||||
const std::string & node_name,
|
||||
rclcpp::Publisher<statistics_msgs::msg::MetricsMessage>::SharedPtr publisher)
|
||||
: SubscriptionTopicStatistics<CallbackMessageT>(node_name, publisher)
|
||||
: SubscriptionTopicStatistics(node_name, std::move(publisher))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~TestSubscriptionTopicStatistics() = default;
|
||||
~TestSubscriptionTopicStatistics() override = default;
|
||||
|
||||
/// Exposed for testing
|
||||
std::vector<StatisticData> get_current_collector_data() const
|
||||
{
|
||||
return SubscriptionTopicStatistics<CallbackMessageT>::get_current_collector_data();
|
||||
}
|
||||
using SubscriptionTopicStatistics::get_current_collector_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Empty publisher node: used to publish empty messages
|
||||
* PublisherNode wrapper: used to create publisher node
|
||||
*/
|
||||
class EmptyPublisher : public rclcpp::Node
|
||||
template<typename MessageT>
|
||||
class PublisherNode : public rclcpp::Node
|
||||
{
|
||||
public:
|
||||
EmptyPublisher(
|
||||
PublisherNode(
|
||||
const std::string & name, const std::string & topic,
|
||||
const std::chrono::milliseconds & publish_period = std::chrono::milliseconds{100})
|
||||
: Node(name)
|
||||
{
|
||||
publisher_ = create_publisher<Empty>(topic, 10);
|
||||
publisher_ = create_publisher<MessageT>(topic, 10);
|
||||
publish_timer_ = this->create_wall_timer(
|
||||
publish_period, [this]() {
|
||||
this->publish_message();
|
||||
});
|
||||
}
|
||||
|
||||
virtual ~EmptyPublisher() = default;
|
||||
~PublisherNode() override = default;
|
||||
|
||||
private:
|
||||
void publish_message()
|
||||
{
|
||||
auto msg = Empty{};
|
||||
auto msg = MessageT{};
|
||||
publisher_->publish(msg);
|
||||
}
|
||||
|
||||
rclcpp::Publisher<Empty>::SharedPtr publisher_;
|
||||
typename rclcpp::Publisher<MessageT>::SharedPtr publisher_;
|
||||
rclcpp::TimerBase::SharedPtr publish_timer_;
|
||||
};
|
||||
|
||||
/**
|
||||
* MessageWithHeader publisher node: used to publish MessageWithHeader with `header` value set
|
||||
*/
|
||||
class MessageWithHeaderPublisher : public rclcpp::Node
|
||||
{
|
||||
public:
|
||||
MessageWithHeaderPublisher(
|
||||
const std::string & name, const std::string & topic,
|
||||
const std::chrono::milliseconds & publish_period = std::chrono::milliseconds{100})
|
||||
: Node(name)
|
||||
{
|
||||
publisher_ = create_publisher<MessageWithHeader>(topic, 10);
|
||||
publish_timer_ = this->create_wall_timer(
|
||||
publish_period, [this]() {
|
||||
this->publish_message();
|
||||
});
|
||||
uniform_dist_ = std::uniform_int_distribution<uint32_t>{1000000, 100000000};
|
||||
}
|
||||
|
||||
virtual ~MessageWithHeaderPublisher() = default;
|
||||
|
||||
private:
|
||||
void publish_message()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937 gen{rd()};
|
||||
uint32_t d = uniform_dist_(gen);
|
||||
auto msg = MessageWithHeader{};
|
||||
// Subtract ~1 second (add some noise for a non-zero standard deviation)
|
||||
// so the received message age calculation is always > 0
|
||||
msg.header.stamp = this->now() - rclcpp::Duration{1, d};
|
||||
publisher_->publish(msg);
|
||||
}
|
||||
|
||||
rclcpp::Publisher<MessageWithHeader>::SharedPtr publisher_;
|
||||
rclcpp::TimerBase::SharedPtr publish_timer_;
|
||||
std::uniform_int_distribution<uint32_t> uniform_dist_;
|
||||
};
|
||||
|
||||
/**
|
||||
* TransitionMessageStamp publisher node : used to publish MessageWithHeader with `header` value set
|
||||
* TransitionMessageStamp publisher emulator node : used to emulate publishing messages by
|
||||
* directly calling rclcpp::Subscription::handle_message(msg_shared_ptr, message_info).
|
||||
* The message age results change during the test.
|
||||
*/
|
||||
|
||||
class TransitionMessageStampPublisher : public rclcpp::Node
|
||||
template<typename MessageT>
|
||||
class TransitionMessageStampPublisherEmulator : public rclcpp::Node
|
||||
{
|
||||
public:
|
||||
TransitionMessageStampPublisher(
|
||||
const std::string & name, const std::string & topic,
|
||||
TransitionMessageStampPublisherEmulator(
|
||||
const std::string & name,
|
||||
const std::chrono::seconds transition_duration, const std::chrono::seconds message_age_offset,
|
||||
typename rclcpp::Subscription<MessageT>::SharedPtr subscription,
|
||||
const std::chrono::milliseconds & publish_period = std::chrono::milliseconds{100})
|
||||
: Node(name), transition_duration_(transition_duration), message_age_offset_(message_age_offset)
|
||||
: Node(name), transition_duration_(transition_duration), message_age_offset_(message_age_offset),
|
||||
subscription_(std::move(subscription))
|
||||
{
|
||||
publisher_ = create_publisher<MessageWithHeader>(topic, 10);
|
||||
publish_timer_ = this->create_wall_timer(publish_period, [this]() {this->publish_message();});
|
||||
start_time_ = this->now();
|
||||
}
|
||||
@@ -191,84 +148,66 @@ public:
|
||||
private:
|
||||
void publish_message()
|
||||
{
|
||||
auto msg = MessageWithHeader{};
|
||||
std::shared_ptr<void> msg_shared_ptr = std::make_shared<MessageT>();
|
||||
rmw_message_info_t rmw_message_info = rmw_get_zero_initialized_message_info();
|
||||
|
||||
auto now = this->now();
|
||||
auto elapsed_time = now - start_time_;
|
||||
if (elapsed_time < transition_duration_) {
|
||||
// Apply only to the topic statistics in the first half
|
||||
// Subtract offset so message_age is always >= offset.
|
||||
msg.header.stamp = now - message_age_offset_;
|
||||
rmw_message_info.source_timestamp = (now - message_age_offset_).nanoseconds();
|
||||
} else {
|
||||
msg.header.stamp = now;
|
||||
rmw_message_info.source_timestamp = now.nanoseconds();
|
||||
}
|
||||
publisher_->publish(msg);
|
||||
rclcpp::MessageInfo message_info{rmw_message_info};
|
||||
subscription_->handle_message(msg_shared_ptr, message_info);
|
||||
}
|
||||
|
||||
std::chrono::seconds transition_duration_;
|
||||
std::chrono::seconds message_age_offset_;
|
||||
typename rclcpp::Subscription<MessageT>::SharedPtr subscription_;
|
||||
rclcpp::Time start_time_;
|
||||
|
||||
rclcpp::Publisher<MessageWithHeader>::SharedPtr publisher_;
|
||||
rclcpp::TimerBase::SharedPtr publish_timer_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Empty subscriber node: used to create subscriber topic statistics requirements
|
||||
* Message subscriber node: used to create subscriber with enabled topic statistics collectors
|
||||
*
|
||||
*/
|
||||
class EmptySubscriber : public rclcpp::Node
|
||||
template<typename MessageT>
|
||||
class SubscriberWithTopicStatistics : public rclcpp::Node
|
||||
{
|
||||
public:
|
||||
EmptySubscriber(const std::string & name, const std::string & topic)
|
||||
SubscriberWithTopicStatistics(
|
||||
const std::string & name, const std::string & topic,
|
||||
std::chrono::milliseconds publish_period = defaultStatisticsPublishPeriod)
|
||||
: Node(name)
|
||||
{
|
||||
// manually enable topic statistics via options
|
||||
// Manually enable topic statistics via options
|
||||
auto options = rclcpp::SubscriptionOptions();
|
||||
options.topic_stats_options.state = rclcpp::TopicStatisticsState::Enable;
|
||||
options.topic_stats_options.publish_period = publish_period;
|
||||
|
||||
auto callback = [](Empty::UniquePtr msg) {
|
||||
auto callback = [](typename MessageT::UniquePtr msg) {
|
||||
(void) msg;
|
||||
};
|
||||
subscription_ = create_subscription<Empty,
|
||||
std::function<void(Empty::UniquePtr)>>(
|
||||
subscription_ = create_subscription<MessageT,
|
||||
std::function<void(typename MessageT::UniquePtr)>>(
|
||||
topic,
|
||||
rclcpp::QoS(rclcpp::KeepAll()),
|
||||
callback,
|
||||
options);
|
||||
}
|
||||
virtual ~EmptySubscriber() = default;
|
||||
~SubscriberWithTopicStatistics() override = default;
|
||||
|
||||
private:
|
||||
rclcpp::Subscription<Empty>::SharedPtr subscription_;
|
||||
};
|
||||
|
||||
/**
|
||||
* MessageWithHeader subscriber node: used to create subscriber topic statistics requirements
|
||||
*/
|
||||
class MessageWithHeaderSubscriber : public rclcpp::Node
|
||||
{
|
||||
public:
|
||||
MessageWithHeaderSubscriber(const std::string & name, const std::string & topic)
|
||||
: Node(name)
|
||||
typename rclcpp::Subscription<MessageT>::SharedPtr get_subscription()
|
||||
{
|
||||
// manually enable topic statistics via options
|
||||
auto options = rclcpp::SubscriptionOptions();
|
||||
options.topic_stats_options.state = rclcpp::TopicStatisticsState::Enable;
|
||||
options.topic_stats_options.publish_period = defaultStatisticsPublishPeriod;
|
||||
|
||||
auto callback = [](MessageWithHeader::UniquePtr msg) {
|
||||
(void) msg;
|
||||
};
|
||||
subscription_ = create_subscription<MessageWithHeader,
|
||||
std::function<void(MessageWithHeader::UniquePtr)>>(
|
||||
topic,
|
||||
rclcpp::QoS(rclcpp::KeepAll()),
|
||||
callback,
|
||||
options);
|
||||
return subscription_;
|
||||
}
|
||||
virtual ~MessageWithHeaderSubscriber() = default;
|
||||
|
||||
private:
|
||||
rclcpp::Subscription<MessageWithHeader>::SharedPtr subscription_;
|
||||
typename rclcpp::Subscription<MessageT>::SharedPtr subscription_;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -277,43 +216,17 @@ private:
|
||||
class TestSubscriptionTopicStatisticsFixture : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp()
|
||||
void SetUp() override
|
||||
{
|
||||
rclcpp::init(0 /* argc */, nullptr /* argv */);
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
void TearDown() override
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a received statistics message is empty (no data was observed)
|
||||
* \param message_to_check
|
||||
*/
|
||||
void check_if_statistics_message_is_empty(const MetricsMessage & message_to_check)
|
||||
{
|
||||
for (const auto & stats_point : message_to_check.statistics) {
|
||||
const auto type = stats_point.data_type;
|
||||
switch (type) {
|
||||
case StatisticDataType::STATISTICS_DATA_TYPE_SAMPLE_COUNT:
|
||||
EXPECT_EQ(0, stats_point.data) << "unexpected sample count" << stats_point.data;
|
||||
break;
|
||||
case StatisticDataType::STATISTICS_DATA_TYPE_AVERAGE:
|
||||
case StatisticDataType::STATISTICS_DATA_TYPE_MINIMUM:
|
||||
case StatisticDataType::STATISTICS_DATA_TYPE_MAXIMUM:
|
||||
case StatisticDataType::STATISTICS_DATA_TYPE_STDDEV:
|
||||
EXPECT_TRUE(std::isnan(stats_point.data)) << "unexpected value" << stats_point.data <<
|
||||
" for type:" << type;
|
||||
break;
|
||||
default:
|
||||
FAIL() << "received unknown statistics type: " << std::dec <<
|
||||
static_cast<unsigned int>(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a received statistics message observed data and contains some calculation
|
||||
* \param message_to_check
|
||||
@@ -348,28 +261,13 @@ void check_if_statistic_message_is_populated(const MetricsMessage & message_to_c
|
||||
/**
|
||||
* Test an invalid argument is thrown for a bad input publish period.
|
||||
*/
|
||||
TEST(TestSubscriptionTopicStatistics, test_invalid_publish_period)
|
||||
TEST_F(TestSubscriptionTopicStatisticsFixture, test_invalid_publish_period)
|
||||
{
|
||||
rclcpp::init(0 /* argc */, nullptr /* argv */);
|
||||
|
||||
auto node = std::make_shared<rclcpp::Node>("test_period_node");
|
||||
|
||||
auto options = rclcpp::SubscriptionOptions();
|
||||
options.topic_stats_options.state = rclcpp::TopicStatisticsState::Enable;
|
||||
options.topic_stats_options.publish_period = std::chrono::milliseconds(0);
|
||||
|
||||
auto callback = [](Empty::UniquePtr msg) {
|
||||
(void) msg;
|
||||
};
|
||||
|
||||
ASSERT_THROW(
|
||||
(node->create_subscription<Empty, std::function<void(Empty::UniquePtr)>>(
|
||||
"should_throw_invalid_arg",
|
||||
rclcpp::QoS(rclcpp::KeepAll()),
|
||||
callback,
|
||||
options)), std::invalid_argument);
|
||||
|
||||
rclcpp::shutdown();
|
||||
SubscriberWithTopicStatistics<Empty>(
|
||||
"test_period_node", "should_throw_invalid_arg", std::chrono::milliseconds(0)
|
||||
),
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,7 +276,7 @@ TEST(TestSubscriptionTopicStatistics, test_invalid_publish_period)
|
||||
*/
|
||||
TEST_F(TestSubscriptionTopicStatisticsFixture, test_manual_construction)
|
||||
{
|
||||
auto empty_subscriber = std::make_shared<EmptySubscriber>(
|
||||
auto empty_subscriber = std::make_shared<SubscriberWithTopicStatistics<Empty>>(
|
||||
kTestSubNodeName,
|
||||
kTestSubStatsEmptyTopic);
|
||||
|
||||
@@ -389,7 +287,7 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_manual_construction)
|
||||
10);
|
||||
|
||||
// Construct a separate instance
|
||||
auto sub_topic_stats = std::make_unique<TestSubscriptionTopicStatistics<Empty>>(
|
||||
auto sub_topic_stats = std::make_unique<TestSubscriptionTopicStatistics>(
|
||||
empty_subscriber->get_name(),
|
||||
topic_stats_publisher);
|
||||
|
||||
@@ -410,7 +308,7 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_manual_construction)
|
||||
TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_no_header)
|
||||
{
|
||||
// Create an empty publisher
|
||||
auto empty_publisher = std::make_shared<EmptyPublisher>(
|
||||
auto empty_publisher = std::make_shared<PublisherNode<Empty>>(
|
||||
kTestPubNodeName,
|
||||
kTestSubStatsEmptyTopic);
|
||||
// empty_subscriber has a topic statistics instance as part of its subscription
|
||||
@@ -422,7 +320,7 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_no
|
||||
"/statistics",
|
||||
kNumExpectedMessages);
|
||||
|
||||
auto empty_subscriber = std::make_shared<EmptySubscriber>(
|
||||
auto empty_subscriber = std::make_shared<SubscriberWithTopicStatistics<Empty>>(
|
||||
kTestSubNodeName,
|
||||
kTestSubStatsEmptyTopic);
|
||||
|
||||
@@ -432,74 +330,7 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_no
|
||||
ex.add_node(empty_subscriber);
|
||||
|
||||
// Spin and get future
|
||||
ex.spin_until_future_complete(
|
||||
statistics_listener->GetFuture(),
|
||||
kTestTimeout);
|
||||
|
||||
// Compare message counts, sample count should be the same as published and received count
|
||||
EXPECT_EQ(kNumExpectedMessages, statistics_listener->GetNumberOfMessagesReceived());
|
||||
|
||||
// Check the received message total count
|
||||
const auto received_messages = statistics_listener->GetReceivedMessages();
|
||||
EXPECT_EQ(kNumExpectedMessages, received_messages.size());
|
||||
|
||||
// check the type of statistics that were received and their counts
|
||||
uint64_t message_age_count{0};
|
||||
uint64_t message_period_count{0};
|
||||
|
||||
std::set<std::string> received_metrics;
|
||||
for (const auto & msg : received_messages) {
|
||||
if (msg.metrics_source == "message_age") {
|
||||
message_age_count++;
|
||||
}
|
||||
if (msg.metrics_source == "message_period") {
|
||||
message_period_count++;
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(kNumExpectedMessageAgeMessages, message_age_count);
|
||||
EXPECT_EQ(kNumExpectedMessagePeriodMessages, message_period_count);
|
||||
|
||||
// Check the collected statistics for message period.
|
||||
// Message age statistics will not be calculated because Empty messages
|
||||
// don't have a `header` with timestamp. This means that we expect to receive a `message_age`
|
||||
// and `message_period` message for each empty message published.
|
||||
for (const auto & msg : received_messages) {
|
||||
if (msg.metrics_source == kMessageAgeSourceLabel) {
|
||||
check_if_statistics_message_is_empty(msg);
|
||||
} else if (msg.metrics_source == kMessagePeriodSourceLabel) {
|
||||
check_if_statistic_message_is_populated(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_with_header)
|
||||
{
|
||||
// Create a MessageWithHeader publisher
|
||||
auto msg_with_header_publisher = std::make_shared<MessageWithHeaderPublisher>(
|
||||
kTestPubNodeName,
|
||||
kTestSubStatsTopic);
|
||||
// empty_subscriber has a topic statistics instance as part of its subscription
|
||||
// this will listen to and generate statistics for the empty message
|
||||
|
||||
// Create a listener for topic statistics messages
|
||||
auto statistics_listener = std::make_shared<rclcpp::topic_statistics::MetricsMessageSubscriber>(
|
||||
"test_receive_stats_for_message_with_header",
|
||||
"/statistics",
|
||||
kNumExpectedMessages);
|
||||
|
||||
auto msg_with_header_subscriber = std::make_shared<MessageWithHeaderSubscriber>(
|
||||
kTestSubNodeName,
|
||||
kTestSubStatsTopic);
|
||||
|
||||
rclcpp::executors::SingleThreadedExecutor ex;
|
||||
ex.add_node(msg_with_header_publisher);
|
||||
ex.add_node(statistics_listener);
|
||||
ex.add_node(msg_with_header_subscriber);
|
||||
|
||||
// Spin and get future
|
||||
ex.spin_until_future_complete(
|
||||
statistics_listener->GetFuture(),
|
||||
kTestTimeout);
|
||||
ex.spin_until_future_complete(statistics_listener->GetFuture(), kTestTimeout);
|
||||
|
||||
// Compare message counts, sample count should be the same as published and received count
|
||||
EXPECT_EQ(kNumExpectedMessages, statistics_listener->GetNumberOfMessagesReceived());
|
||||
@@ -524,6 +355,7 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_wi
|
||||
EXPECT_EQ(kNumExpectedMessageAgeMessages, message_age_count);
|
||||
EXPECT_EQ(kNumExpectedMessagePeriodMessages, message_period_count);
|
||||
|
||||
// Check the collected statistics for message period.
|
||||
for (const auto & msg : received_messages) {
|
||||
check_if_statistic_message_is_populated(msg);
|
||||
}
|
||||
@@ -531,23 +363,27 @@ TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_for_message_wi
|
||||
|
||||
TEST_F(TestSubscriptionTopicStatisticsFixture, test_receive_stats_include_window_reset)
|
||||
{
|
||||
// Create a MessageWithHeader publisher
|
||||
auto msg_with_header_publisher = std::make_shared<TransitionMessageStampPublisher>(
|
||||
kTestPubNodeName, kTestSubStatsTopic, kUnstableMessageAgeWindowDuration,
|
||||
kUnstableMessageAgeOffset);
|
||||
|
||||
// msg_with_header_subscriber has a topic statistics instance as part of its
|
||||
// msg_subscriber_with_topic_statistics has a topic statistics instance as part of its
|
||||
// subscription this will listen to and generate statistics
|
||||
auto msg_with_header_subscriber =
|
||||
std::make_shared<MessageWithHeaderSubscriber>(kTestSubNodeName, kTestSubStatsTopic);
|
||||
auto msg_subscriber_with_topic_statistics =
|
||||
std::make_shared<SubscriberWithTopicStatistics<test_msgs::msg::Strings>>(
|
||||
kTestSubNodeName,
|
||||
kTestSubStatsTopic);
|
||||
|
||||
// Create a message publisher
|
||||
auto msg_publisher =
|
||||
std::make_shared<TransitionMessageStampPublisherEmulator<test_msgs::msg::Strings>>(
|
||||
kTestPubNodeName, kUnstableMessageAgeWindowDuration,
|
||||
kUnstableMessageAgeOffset, msg_subscriber_with_topic_statistics->get_subscription());
|
||||
|
||||
// Create a listener for topic statistics messages
|
||||
auto statistics_listener = std::make_shared<rclcpp::topic_statistics::MetricsMessageSubscriber>(
|
||||
"test_receive_stats_include_window_reset", "/statistics", kNumExpectedMessages);
|
||||
|
||||
rclcpp::executors::SingleThreadedExecutor ex;
|
||||
ex.add_node(msg_with_header_publisher);
|
||||
ex.add_node(msg_publisher);
|
||||
ex.add_node(statistics_listener);
|
||||
ex.add_node(msg_with_header_subscriber);
|
||||
ex.add_node(msg_subscriber_with_topic_statistics);
|
||||
|
||||
// Spin and get future
|
||||
ex.spin_until_future_complete(statistics_listener->GetFuture(), kTestTimeout);
|
||||
|
||||
@@ -3,6 +3,33 @@ Changelog for package rclcpp_action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
25.0.0 (2023-12-26)
|
||||
-------------------
|
||||
* Switch to target_link_libraries. (`#2374 <https://github.com/ros2/rclcpp/issues/2374>`_)
|
||||
* Contributors: Chris Lalancette
|
||||
|
||||
24.0.0 (2023-11-06)
|
||||
-------------------
|
||||
|
||||
23.2.0 (2023-10-09)
|
||||
-------------------
|
||||
|
||||
23.1.0 (2023-10-04)
|
||||
-------------------
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Update API docs links in package READMEs (`#2302 <https://github.com/ros2/rclcpp/issues/2302>`_)
|
||||
* fix(ClientGoalHandle): Made mutex recursive to prevent deadlocks (`#2267 <https://github.com/ros2/rclcpp/issues/2267>`_)
|
||||
* Contributors: Christophe Bedard, jmachowinski
|
||||
|
||||
22.2.0 (2023-09-07)
|
||||
-------------------
|
||||
* Correct the position of a comment. (`#2290 <https://github.com/ros2/rclcpp/issues/2290>`_)
|
||||
* Fix a typo in a comment. (`#2283 <https://github.com/ros2/rclcpp/issues/2283>`_)
|
||||
* doc fix: call `canceled` only after goal state is in canceling. (`#2266 <https://github.com/ros2/rclcpp/issues/2266>`_)
|
||||
* Contributors: Chris Lalancette, Jiaqi Li, Tomoya Fujita
|
||||
|
||||
22.1.0 (2023-08-21)
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ project(rclcpp_action)
|
||||
find_package(ament_cmake_ros REQUIRED)
|
||||
find_package(action_msgs REQUIRED)
|
||||
find_package(rclcpp REQUIRED)
|
||||
find_package(rcl REQUIRED)
|
||||
find_package(rcl_action REQUIRED)
|
||||
find_package(rcpputils REQUIRED)
|
||||
find_package(rosidl_runtime_c REQUIRED)
|
||||
@@ -21,28 +22,26 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
)
|
||||
endif()
|
||||
|
||||
set(${PROJECT_NAME}_SRCS
|
||||
add_library(${PROJECT_NAME}
|
||||
src/client.cpp
|
||||
src/qos.cpp
|
||||
src/server.cpp
|
||||
src/server_goal_handle.cpp
|
||||
src/types.cpp
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME}
|
||||
${${PROJECT_NAME}_SRCS})
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")
|
||||
|
||||
ament_target_dependencies(${PROJECT_NAME}
|
||||
"action_msgs"
|
||||
"rcl_action"
|
||||
"rclcpp"
|
||||
"rcpputils"
|
||||
"rosidl_runtime_c"
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
${action_msgs_TARGETS}
|
||||
rcl::rcl
|
||||
rcl_action::rcl_action
|
||||
rclcpp::rclcpp
|
||||
rosidl_runtime_c::rosidl_runtime_c
|
||||
)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
rcpputils::rcpputils
|
||||
)
|
||||
|
||||
# Causes the visibility macros to use dllexport rather than dllimport,
|
||||
@@ -69,12 +68,7 @@ ament_export_libraries(${PROJECT_NAME})
|
||||
# Export modern CMake targets
|
||||
ament_export_targets(${PROJECT_NAME})
|
||||
|
||||
# specific order: dependents before dependencies
|
||||
ament_export_dependencies(ament_cmake)
|
||||
ament_export_dependencies(action_msgs)
|
||||
ament_export_dependencies(rclcpp)
|
||||
ament_export_dependencies(rcl_action)
|
||||
ament_export_dependencies(rosidl_runtime_c)
|
||||
ament_export_dependencies(action_msgs rcl_action rclcpp rosidl_runtime_c)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
find_package(ament_cmake_gtest REQUIRED)
|
||||
@@ -87,58 +81,52 @@ if(BUILD_TESTING)
|
||||
|
||||
ament_add_gtest(test_client test/test_client.cpp TIMEOUT 180)
|
||||
if(TARGET test_client)
|
||||
ament_target_dependencies(test_client
|
||||
"rcutils"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_client
|
||||
${PROJECT_NAME}
|
||||
mimick
|
||||
rcl::rcl
|
||||
rcl_action::rcl_action
|
||||
rclcpp::rclcpp
|
||||
rcutils::rcutils
|
||||
${test_msgs_TARGETS}
|
||||
)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_server test/test_server.cpp TIMEOUT 180)
|
||||
if(TARGET test_server)
|
||||
ament_target_dependencies(test_server
|
||||
"rcpputils"
|
||||
"rcutils"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_server
|
||||
${PROJECT_NAME}
|
||||
mimick
|
||||
rcl_action::rcl_action
|
||||
rclcpp::rclcpp
|
||||
${test_msgs_TARGETS}
|
||||
)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_server_goal_handle test/test_server_goal_handle.cpp)
|
||||
if(TARGET test_server_goal_handle)
|
||||
ament_target_dependencies(test_server_goal_handle
|
||||
"rcutils"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_server_goal_handle
|
||||
${PROJECT_NAME}
|
||||
${action_msgs_TARGETS}
|
||||
mimick
|
||||
rclcpp::rclcpp
|
||||
${test_msgs_TARGETS}
|
||||
)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_traits test/test_traits.cpp)
|
||||
if(TARGET test_traits)
|
||||
ament_target_dependencies(test_traits
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_traits
|
||||
${PROJECT_NAME}
|
||||
${test_msgs_TARGETS}
|
||||
)
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_types test/test_types.cpp)
|
||||
if(TARGET test_types)
|
||||
ament_target_dependencies(test_types
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_types
|
||||
${PROJECT_NAME}
|
||||
${test_msgs_TARGETS}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
Adds action APIs for C++.
|
||||
|
||||
Visit the [rclcpp_action API documentation](http://docs.ros2.org/latest/api/rclcpp_action/) for a complete list of its main components and features. For more information about Actions in ROS 2, see the [design document](http://design.ros2.org/articles/actions.html).
|
||||
The link to the latest rclcpp_action API documentation, which includes a complete list of its main components and features, can be found on the rclcpp_action package info page, at the [ROS Index](https://index.ros.org/p/rclcpp_action/).
|
||||
For more information about Actions in ROS 2, see the [design document](http://design.ros2.org/articles/actions.html).
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ private:
|
||||
ResultCallback result_callback_{nullptr};
|
||||
int8_t status_{GoalStatus::STATUS_ACCEPTED};
|
||||
|
||||
std::mutex handle_mutex_;
|
||||
std::recursive_mutex handle_mutex_;
|
||||
};
|
||||
} // namespace rclcpp_action
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ template<typename ActionT>
|
||||
std::shared_future<typename ClientGoalHandle<ActionT>::WrappedResult>
|
||||
ClientGoalHandle<ActionT>::async_get_result()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
if (!is_result_aware_) {
|
||||
throw exceptions::UnawareGoalHandleError();
|
||||
}
|
||||
@@ -70,7 +70,7 @@ template<typename ActionT>
|
||||
void
|
||||
ClientGoalHandle<ActionT>::set_result(const WrappedResult & wrapped_result)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
status_ = static_cast<int8_t>(wrapped_result.code);
|
||||
result_promise_.set_value(wrapped_result);
|
||||
if (result_callback_) {
|
||||
@@ -82,7 +82,7 @@ template<typename ActionT>
|
||||
void
|
||||
ClientGoalHandle<ActionT>::set_feedback_callback(FeedbackCallback callback)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
feedback_callback_ = callback;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ template<typename ActionT>
|
||||
void
|
||||
ClientGoalHandle<ActionT>::set_result_callback(ResultCallback callback)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
result_callback_ = callback;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ template<typename ActionT>
|
||||
int8_t
|
||||
ClientGoalHandle<ActionT>::get_status()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
return status_;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ template<typename ActionT>
|
||||
void
|
||||
ClientGoalHandle<ActionT>::set_status(int8_t status)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
status_ = status;
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ template<typename ActionT>
|
||||
bool
|
||||
ClientGoalHandle<ActionT>::is_feedback_aware()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
return feedback_callback_ != nullptr;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ template<typename ActionT>
|
||||
bool
|
||||
ClientGoalHandle<ActionT>::is_result_aware()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
return is_result_aware_;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ template<typename ActionT>
|
||||
bool
|
||||
ClientGoalHandle<ActionT>::set_result_awareness(bool awareness)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
bool previous = is_result_aware_;
|
||||
is_result_aware_ = awareness;
|
||||
return previous;
|
||||
@@ -140,7 +140,7 @@ template<typename ActionT>
|
||||
void
|
||||
ClientGoalHandle<ActionT>::invalidate(const exceptions::UnawareGoalHandleError & ex)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
// Guard against multiple calls
|
||||
if (is_invalidated()) {
|
||||
return;
|
||||
@@ -168,7 +168,7 @@ ClientGoalHandle<ActionT>::call_feedback_callback(
|
||||
RCLCPP_ERROR(rclcpp::get_logger("rclcpp_action"), "Sent feedback to wrong goal handle.");
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(handle_mutex_);
|
||||
std::lock_guard<std::recursive_mutex> guard(handle_mutex_);
|
||||
if (nullptr == feedback_callback_) {
|
||||
// Normal, some feedback messages may arrive after the goal result.
|
||||
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp_action"), "Received feedback but goal ignores it.");
|
||||
|
||||
@@ -128,7 +128,7 @@ class Server;
|
||||
* accepted.
|
||||
* A `Server` will create an instance and give it to the user in their `handle_accepted` callback.
|
||||
*
|
||||
* Internally, this class is responsible for coverting between the C++ action type and generic
|
||||
* Internally, this class is responsible for converting between the C++ action type and generic
|
||||
* types for `rclcpp_action::ServerGoalHandleBase`.
|
||||
*/
|
||||
template<typename ActionT>
|
||||
@@ -196,7 +196,7 @@ public:
|
||||
|
||||
/// Indicate that a goal has been canceled.
|
||||
/**
|
||||
* Only call this if the goal is executing or pending, but has been canceled.
|
||||
* Only call this if the goal is canceling.
|
||||
* This is a terminal state, no more methods should be called on a goal handle after this is
|
||||
* called.
|
||||
*
|
||||
|
||||
@@ -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>22.1.0</version>
|
||||
<version>25.0.0</version>
|
||||
<description>Adds action APIs for C++.</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
@@ -23,6 +23,7 @@
|
||||
<depend>action_msgs</depend>
|
||||
<depend>rclcpp</depend>
|
||||
<depend>rcl_action</depend>
|
||||
<depend>rcl</depend>
|
||||
<depend>rcpputils</depend>
|
||||
|
||||
<depend>ament_cmake</depend>
|
||||
|
||||
@@ -163,7 +163,6 @@ bool
|
||||
ClientBase::wait_for_action_server_nanoseconds(std::chrono::nanoseconds timeout)
|
||||
{
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
// make an event to reuse, rather than create a new one each time
|
||||
auto node_ptr = pimpl_->node_graph_.lock();
|
||||
if (!node_ptr) {
|
||||
throw rclcpp::exceptions::InvalidNodeError();
|
||||
@@ -172,6 +171,7 @@ ClientBase::wait_for_action_server_nanoseconds(std::chrono::nanoseconds timeout)
|
||||
if (this->action_server_is_ready()) {
|
||||
return true;
|
||||
}
|
||||
// make an event to reuse, rather than create a new one each time
|
||||
auto event = node_ptr->get_graph_event();
|
||||
if (timeout == std::chrono::nanoseconds(0)) {
|
||||
// check was non-blocking, return immediately
|
||||
|
||||
@@ -9,8 +9,7 @@ add_performance_test(
|
||||
benchmark_action_client.cpp
|
||||
TIMEOUT 240)
|
||||
if(TARGET benchmark_action_client)
|
||||
target_link_libraries(benchmark_action_client ${PROJECT_NAME})
|
||||
ament_target_dependencies(benchmark_action_client rclcpp test_msgs)
|
||||
target_link_libraries(benchmark_action_client ${PROJECT_NAME} rclcpp::rclcpp ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
add_performance_test(
|
||||
@@ -18,6 +17,5 @@ add_performance_test(
|
||||
benchmark_action_server.cpp
|
||||
TIMEOUT 120)
|
||||
if(TARGET benchmark_action_server)
|
||||
target_link_libraries(benchmark_action_server ${PROJECT_NAME})
|
||||
ament_target_dependencies(benchmark_action_server rclcpp test_msgs)
|
||||
target_link_libraries(benchmark_action_server ${PROJECT_NAME} rclcpp::rclcpp ${test_msgs_TARGETS})
|
||||
endif()
|
||||
|
||||
@@ -852,6 +852,86 @@ TEST_F(TestClientAgainstServer, async_cancel_some_goals_with_callback)
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_CANCELED, goal_handle0->get_status());
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, deadlock_in_callbacks)
|
||||
{
|
||||
std::atomic<bool> feedback_callback_called = false;
|
||||
std::atomic<bool> response_callback_called = false;
|
||||
std::atomic<bool> result_callback_called = false;
|
||||
std::atomic<bool> no_deadlock = false;
|
||||
|
||||
std::thread tr = std::thread(
|
||||
[&]() {
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
|
||||
ActionGoal goal;
|
||||
|
||||
using GoalHandle = rclcpp_action::ClientGoalHandle<ActionType>;
|
||||
rclcpp_action::Client<ActionType>::SendGoalOptions ops;
|
||||
ops.feedback_callback =
|
||||
[&feedback_callback_called](const GoalHandle::SharedPtr handle,
|
||||
ActionType::Feedback::ConstSharedPtr) {
|
||||
// call functions on the handle that acquire the lock
|
||||
handle->get_status();
|
||||
handle->is_feedback_aware();
|
||||
handle->is_result_aware();
|
||||
|
||||
feedback_callback_called = true;
|
||||
};
|
||||
ops.goal_response_callback = [&response_callback_called](
|
||||
const GoalHandle::SharedPtr & handle) {
|
||||
// call functions on the handle that acquire the lock
|
||||
handle->get_status();
|
||||
handle->is_feedback_aware();
|
||||
handle->is_result_aware();
|
||||
|
||||
response_callback_called = true;
|
||||
};
|
||||
ops.result_callback = [&result_callback_called](
|
||||
const GoalHandle::WrappedResult &) {
|
||||
result_callback_called = true;
|
||||
};
|
||||
|
||||
goal.order = 6;
|
||||
auto future_goal_handle = action_client->async_send_goal(goal, ops);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
|
||||
ASSERT_TRUE(goal_handle);
|
||||
|
||||
ASSERT_EQ(RCL_RET_OK, rcl_set_ros_time_override(clock.get_clock_handle(), RCL_S_TO_NS(2)));
|
||||
|
||||
auto result_future = action_client->async_get_result(goal_handle);
|
||||
dual_spin_until_future_complete(result_future);
|
||||
|
||||
EXPECT_TRUE(result_future.valid());
|
||||
auto result = result_future.get();
|
||||
|
||||
no_deadlock = true;
|
||||
});
|
||||
|
||||
auto start_time = std::chrono::system_clock::now();
|
||||
|
||||
while (std::chrono::system_clock::now() - start_time < std::chrono::milliseconds(2000) &&
|
||||
!no_deadlock)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
|
||||
if (no_deadlock) {
|
||||
tr.join();
|
||||
} else {
|
||||
// In case of a failure, the thread is assumed to be in a deadlock.
|
||||
// We detach the thread so we don't block further tests.
|
||||
tr.detach();
|
||||
}
|
||||
|
||||
EXPECT_TRUE(no_deadlock);
|
||||
EXPECT_TRUE(response_callback_called);
|
||||
EXPECT_TRUE(result_callback_called);
|
||||
EXPECT_TRUE(feedback_callback_called);
|
||||
}
|
||||
|
||||
TEST_F(TestClientAgainstServer, send_rcl_errors)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
|
||||
@@ -2,6 +2,32 @@
|
||||
Changelog for package rclcpp_components
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
25.0.0 (2023-12-26)
|
||||
-------------------
|
||||
* Switch to target_link_libraries. (`#2374 <https://github.com/ros2/rclcpp/issues/2374>`_)
|
||||
* feat(rclcpp_components): support events executor in node main template (`#2366 <https://github.com/ros2/rclcpp/issues/2366>`_)
|
||||
* fix(rclcpp_components): increase the service queue sizes in component_container (`#2363 <https://github.com/ros2/rclcpp/issues/2363>`_)
|
||||
* Contributors: Chris Lalancette, Daisuke Nishimatsu, M. Fatih Cırıt
|
||||
|
||||
24.0.0 (2023-11-06)
|
||||
-------------------
|
||||
|
||||
23.2.0 (2023-10-09)
|
||||
-------------------
|
||||
|
||||
23.1.0 (2023-10-04)
|
||||
-------------------
|
||||
* Add missing header required by the rclcpp::NodeOptions type (`#2324 <https://github.com/ros2/rclcpp/issues/2324>`_)
|
||||
* Contributors: Ignacio Vizzo
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Update API docs links in package READMEs (`#2302 <https://github.com/ros2/rclcpp/issues/2302>`_)
|
||||
* Contributors: Christophe Bedard
|
||||
|
||||
22.2.0 (2023-09-07)
|
||||
-------------------
|
||||
|
||||
22.1.0 (2023-08-21)
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ find_package(composition_interfaces REQUIRED)
|
||||
find_package(rclcpp REQUIRED)
|
||||
find_package(rcpputils REQUIRED)
|
||||
|
||||
# Add an interface library that can be dependend upon by libraries who register components
|
||||
# Add an interface library that can be depended upon by libraries who register components
|
||||
add_library(component INTERFACE)
|
||||
target_include_directories(component INTERFACE
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
@@ -38,12 +38,14 @@ add_library(
|
||||
target_include_directories(component_manager PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>")
|
||||
ament_target_dependencies(component_manager
|
||||
"ament_index_cpp"
|
||||
"class_loader"
|
||||
"composition_interfaces"
|
||||
"rclcpp"
|
||||
"rcpputils"
|
||||
target_link_libraries(component_manager PUBLIC
|
||||
${composition_interfaces_TARGETS}
|
||||
rclcpp::rclcpp
|
||||
)
|
||||
target_link_libraries(component_manager PRIVATE
|
||||
ament_index_cpp::ament_index_cpp
|
||||
class_loader::class_loader
|
||||
rcpputils::rcpputils
|
||||
)
|
||||
target_compile_definitions(component_manager
|
||||
PRIVATE "RCLCPP_COMPONENTS_BUILDING_LIBRARY")
|
||||
@@ -52,10 +54,7 @@ add_executable(
|
||||
component_container
|
||||
src/component_container.cpp
|
||||
)
|
||||
target_link_libraries(component_container component_manager)
|
||||
ament_target_dependencies(component_container
|
||||
"rclcpp"
|
||||
)
|
||||
target_link_libraries(component_container component_manager rclcpp::rclcpp)
|
||||
|
||||
set(node_main_template_install_dir "share/${PROJECT_NAME}")
|
||||
install(FILES
|
||||
@@ -66,20 +65,13 @@ add_executable(
|
||||
component_container_mt
|
||||
src/component_container_mt.cpp
|
||||
)
|
||||
target_link_libraries(component_container_mt component_manager)
|
||||
ament_target_dependencies(component_container_mt
|
||||
"rclcpp"
|
||||
)
|
||||
target_link_libraries(component_container_mt component_manager rclcpp::rclcpp)
|
||||
|
||||
add_executable(
|
||||
component_container_isolated
|
||||
src/component_container_isolated.cpp
|
||||
)
|
||||
target_link_libraries(component_container_isolated component_manager)
|
||||
ament_target_dependencies(component_container_isolated
|
||||
"rclcpp"
|
||||
)
|
||||
|
||||
target_link_libraries(component_container_isolated component_manager rclcpp::rclcpp)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_libraries(component_container "stdc++fs")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Package containing tools for dynamically loadable components.
|
||||
|
||||
Visit the [rclcpp_components API documentation](http://docs.ros2.org/latest/api/rclcpp_components/) for a complete list of its main components and features.
|
||||
The link to the latest rclcpp_components API documentation, which includes a complete list of its main components and features, can be found on the rclcpp_components package info page, at the [ROS Index](https://index.ros.org/p/rclcpp_components/).
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
|
||||
@@ -70,10 +70,11 @@ macro(rclcpp_components_register_node target)
|
||||
file(GENERATE OUTPUT ${PROJECT_BINARY_DIR}/rclcpp_components/node_main_${node}.cpp
|
||||
INPUT ${PROJECT_BINARY_DIR}/rclcpp_components/node_main_configured_${node}.cpp.in)
|
||||
add_executable(${node} ${PROJECT_BINARY_DIR}/rclcpp_components/node_main_${node}.cpp)
|
||||
ament_target_dependencies(${node}
|
||||
"rclcpp"
|
||||
"class_loader"
|
||||
"rclcpp_components")
|
||||
target_link_libraries(${node}
|
||||
class_loader::class_loader
|
||||
rclcpp::rclcpp
|
||||
rclcpp_components::component
|
||||
)
|
||||
install(TARGETS
|
||||
${node}
|
||||
DESTINATION lib/${PROJECT_NAME})
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#ifndef RCLCPP_COMPONENTS__NODE_FACTORY_HPP__
|
||||
#define RCLCPP_COMPONENTS__NODE_FACTORY_HPP__
|
||||
|
||||
#include "rclcpp/node_options.hpp"
|
||||
#include "rclcpp_components/node_instance_wrapper.hpp"
|
||||
|
||||
namespace rclcpp_components
|
||||
|
||||
@@ -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>22.1.0</version>
|
||||
<version>25.0.0</version>
|
||||
<description>Package containing tools for dynamically loadable components</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -39,10 +39,12 @@ ComponentManager::ComponentManager(
|
||||
{
|
||||
loadNode_srv_ = create_service<LoadNode>(
|
||||
"~/_container/load_node",
|
||||
std::bind(&ComponentManager::on_load_node, this, _1, _2, _3));
|
||||
std::bind(&ComponentManager::on_load_node, this, _1, _2, _3),
|
||||
rclcpp::ServicesQoS().keep_last(200));
|
||||
unloadNode_srv_ = create_service<UnloadNode>(
|
||||
"~/_container/unload_node",
|
||||
std::bind(&ComponentManager::on_unload_node, this, _1, _2, _3));
|
||||
std::bind(&ComponentManager::on_unload_node, this, _1, _2, _3),
|
||||
rclcpp::ServicesQoS().keep_last(200));
|
||||
listNodes_srv_ = create_service<ListNodes>(
|
||||
"~/_container/list_nodes",
|
||||
std::bind(&ComponentManager::on_list_nodes, this, _1, _2, _3));
|
||||
|
||||
@@ -23,11 +23,14 @@
|
||||
|
||||
#define NODE_MAIN_LOGGER_NAME "@node@"
|
||||
|
||||
using namespace rclcpp::executors;
|
||||
using namespace rclcpp::experimental::executors;
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
auto args = rclcpp::init_and_remove_ros_arguments(argc, argv);
|
||||
rclcpp::Logger logger = rclcpp::get_logger(NODE_MAIN_LOGGER_NAME);
|
||||
rclcpp::executors::@executor@ exec;
|
||||
@executor@ exec;
|
||||
rclcpp::NodeOptions options;
|
||||
options.arguments(args);
|
||||
std::vector<rclcpp_components::NodeInstanceWrapper> node_wrappers;
|
||||
|
||||
@@ -3,6 +3,32 @@ Changelog for package rclcpp_lifecycle
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
25.0.0 (2023-12-26)
|
||||
-------------------
|
||||
|
||||
24.0.0 (2023-11-06)
|
||||
-------------------
|
||||
* Fix rclcpp_lifecycle inclusion on Windows. (`#2331 <https://github.com/ros2/rclcpp/issues/2331>`_)
|
||||
* Contributors: Chris Lalancette
|
||||
|
||||
23.2.0 (2023-10-09)
|
||||
-------------------
|
||||
* add clients & services count (`#2072 <https://github.com/ros2/rclcpp/issues/2072>`_)
|
||||
* Contributors: Minju, Lee
|
||||
|
||||
23.1.0 (2023-10-04)
|
||||
-------------------
|
||||
|
||||
23.0.0 (2023-09-08)
|
||||
-------------------
|
||||
* Update API docs links in package READMEs (`#2302 <https://github.com/ros2/rclcpp/issues/2302>`_)
|
||||
* Contributors: Christophe Bedard
|
||||
|
||||
22.2.0 (2023-09-07)
|
||||
-------------------
|
||||
* add logger level service to lifecycle node. (`#2277 <https://github.com/ros2/rclcpp/issues/2277>`_)
|
||||
* Contributors: Tomoya Fujita
|
||||
|
||||
22.1.0 (2023-08-21)
|
||||
-------------------
|
||||
* Stop using constref signature of benchmark DoNotOptimize. (`#2238 <https://github.com/ros2/rclcpp/issues/2238>`_)
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
Package containing a prototype for lifecycle implementation.
|
||||
|
||||
Visit the [rclcpp_lifecycle API documentation](http://docs.ros2.org/latest/api/rclcpp_lifecycle/) for a complete list of its main components and features. For more information about LifeCycle in ROS 2, see the [design document](http://design.ros2.org/articles/node_lifecycle.html).
|
||||
The link to the latest rclcpp_lifecycle API documentation, which includes a complete list of its main components and features, can be found on the rclcpp_lifecycle package info page, at the [ROS Index](https://index.ros.org/p/rclcpp_lifecycle/).
|
||||
For more information about LifeCycle in ROS 2, see the [design document](http://design.ros2.org/articles/node_lifecycle.html).
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
|
||||
@@ -690,6 +690,22 @@ public:
|
||||
size_t
|
||||
count_subscribers(const std::string & topic_name) const;
|
||||
|
||||
/// Return the number of clients created for a given service.
|
||||
/**
|
||||
* \sa rclcpp::Node::count_clients
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
size_t
|
||||
count_clients(const std::string & service_name) const;
|
||||
|
||||
/// Return the number of services created for a given service.
|
||||
/**
|
||||
* \sa rclcpp::Node::count_services
|
||||
*/
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
size_t
|
||||
count_services(const std::string & service_name) const;
|
||||
|
||||
/// Return the topic endpoint information about publishers on a given topic.
|
||||
/**
|
||||
* \sa rclcpp::Node::get_publishers_info_by_topic
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
#include "rclcpp_lifecycle/visibility_control.h"
|
||||
#include "rclcpp/node_interfaces/detail/node_interfaces_helpers.hpp"
|
||||
|
||||
// When windows.h is included, ERROR is defined as a macro. So the use of it later in this file,
|
||||
// even as an enum, causes compilation errors. Work around this by undefining the macro here,
|
||||
// and then redefining when this header is finished being included.
|
||||
#if defined(_WIN32)
|
||||
#pragma push_macro("ERROR")
|
||||
#undef ERROR
|
||||
#endif
|
||||
|
||||
namespace rclcpp_lifecycle
|
||||
{
|
||||
namespace node_interfaces
|
||||
@@ -108,6 +116,10 @@ public:
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp_lifecycle
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma pop_macro("ERROR")
|
||||
#endif
|
||||
|
||||
RCLCPP_NODE_INTERFACE_HELPERS_SUPPORT(
|
||||
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface, lifecycle_node)
|
||||
|
||||
|
||||
@@ -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>22.1.0</version>
|
||||
<version>25.0.0</version>
|
||||
<description>Package containing a prototype for lifecycle implementation</description>
|
||||
|
||||
<maintainer email="ivanpauno@ekumenlabs.com">Ivan Paunovic</maintainer>
|
||||
|
||||
@@ -144,6 +144,10 @@ LifecycleNode::LifecycleNode(
|
||||
&LifecycleNodeInterface::on_deactivate, this,
|
||||
std::placeholders::_1));
|
||||
register_on_error(std::bind(&LifecycleNodeInterface::on_error, this, std::placeholders::_1));
|
||||
|
||||
if (options.enable_logger_service()) {
|
||||
node_logging_->create_logger_services(node_services_);
|
||||
}
|
||||
}
|
||||
|
||||
LifecycleNode::~LifecycleNode()
|
||||
@@ -382,6 +386,18 @@ LifecycleNode::count_subscribers(const std::string & topic_name) const
|
||||
return node_graph_->count_subscribers(topic_name);
|
||||
}
|
||||
|
||||
size_t
|
||||
LifecycleNode::count_clients(const std::string & service_name) const
|
||||
{
|
||||
return node_graph_->count_clients(service_name);
|
||||
}
|
||||
|
||||
size_t
|
||||
LifecycleNode::count_services(const std::string & service_name) const
|
||||
{
|
||||
return node_graph_->count_services(service_name);
|
||||
}
|
||||
|
||||
std::vector<rclcpp::TopicEndpointInfo>
|
||||
LifecycleNode::get_publishers_info_by_topic(const std::string & topic_name, bool no_mangle) const
|
||||
{
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "lifecycle_msgs/msg/transition.hpp"
|
||||
|
||||
#include "rcl_lifecycle/rcl_lifecycle.h"
|
||||
#include "rcl_interfaces/srv/get_logger_levels.hpp"
|
||||
#include "rcl_interfaces/srv/set_logger_levels.hpp"
|
||||
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "rclcpp_lifecycle/lifecycle_node.hpp"
|
||||
@@ -34,6 +36,8 @@
|
||||
using lifecycle_msgs::msg::State;
|
||||
using lifecycle_msgs::msg::Transition;
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static const std::chrono::nanoseconds DEFAULT_EVENT_TIMEOUT = std::chrono::seconds(3);
|
||||
static const std::chrono::nanoseconds DEFAULT_EVENT_SLEEP_PERIOD = std::chrono::milliseconds(100);
|
||||
|
||||
@@ -249,6 +253,35 @@ TEST_F(TestDefaultStateMachine, empty_initializer_rcl_errors) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestDefaultStateMachine, check_logger_services_exist) {
|
||||
// Logger level services are disabled
|
||||
{
|
||||
rclcpp::NodeOptions options = rclcpp::NodeOptions();
|
||||
options.enable_logger_service(false);
|
||||
auto node = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
|
||||
"test_logger_service", "/test", options);
|
||||
auto get_client = node->create_client<rcl_interfaces::srv::GetLoggerLevels>(
|
||||
"/test/test_logger_service/get_logger_levels");
|
||||
ASSERT_FALSE(get_client->wait_for_service(2s));
|
||||
auto set_client = node->create_client<rcl_interfaces::srv::SetLoggerLevels>(
|
||||
"/test/test_logger_service/set_logger_levels");
|
||||
ASSERT_FALSE(set_client->wait_for_service(2s));
|
||||
}
|
||||
// Logger level services are enabled
|
||||
{
|
||||
rclcpp::NodeOptions options = rclcpp::NodeOptions();
|
||||
options.enable_logger_service(true);
|
||||
auto node = std::make_shared<rclcpp_lifecycle::LifecycleNode>(
|
||||
"test_logger_service", "/test", options);
|
||||
auto get_client = node->create_client<rcl_interfaces::srv::GetLoggerLevels>(
|
||||
"/test/test_logger_service/get_logger_levels");
|
||||
ASSERT_TRUE(get_client->wait_for_service(2s));
|
||||
auto set_client = node->create_client<rcl_interfaces::srv::SetLoggerLevels>(
|
||||
"/test/test_logger_service/set_logger_levels");
|
||||
ASSERT_TRUE(set_client->wait_for_service(2s));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestDefaultStateMachine, trigger_transition) {
|
||||
auto test_node = std::make_shared<EmptyLifecycleNode>("testnode");
|
||||
|
||||
@@ -693,6 +726,17 @@ TEST_F(TestDefaultStateMachine, test_graph_services) {
|
||||
EXPECT_STREQ(
|
||||
service_names_and_types["/testnode/get_transition_graph"][0].c_str(),
|
||||
"lifecycle_msgs/srv/GetAvailableTransitions");
|
||||
|
||||
EXPECT_EQ(0u, test_node->count_clients("/testnode/change_state"));
|
||||
EXPECT_EQ(0u, test_node->count_clients("/testnode/get_available_states"));
|
||||
EXPECT_EQ(0u, test_node->count_clients("/testnode/get_available_transitions"));
|
||||
EXPECT_EQ(0u, test_node->count_clients("/testnode/get_state"));
|
||||
EXPECT_EQ(0u, test_node->count_clients("/testnode/get_transition_graph"));
|
||||
EXPECT_EQ(1u, test_node->count_services("/testnode/change_state"));
|
||||
EXPECT_EQ(1u, test_node->count_services("/testnode/get_available_states"));
|
||||
EXPECT_EQ(1u, test_node->count_services("/testnode/get_available_transitions"));
|
||||
EXPECT_EQ(1u, test_node->count_services("/testnode/get_state"));
|
||||
EXPECT_EQ(1u, test_node->count_services("/testnode/get_transition_graph"));
|
||||
}
|
||||
|
||||
TEST_F(TestDefaultStateMachine, test_graph_services_by_node) {
|
||||
|
||||
Reference in New Issue
Block a user