Compare commits
20 Commits
revert_nod
...
use_errors
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd3e247229 | ||
|
|
c1b80bd367 | ||
|
|
814298480c | ||
|
|
45f3976453 | ||
|
|
e0bf4a9c20 | ||
|
|
04f3c33de5 | ||
|
|
df3c2ffa8a | ||
|
|
52ae3e0337 | ||
|
|
80e8dcad02 | ||
|
|
e64022f753 | ||
|
|
c3d599fc8c | ||
|
|
cdeed8903d | ||
|
|
46cfe84b14 | ||
|
|
bb91b6c2ef | ||
|
|
4eab2a3c60 | ||
|
|
bb8c8ff2c0 | ||
|
|
c9319dafc2 | ||
|
|
0f0a4a8e39 | ||
|
|
649d72f835 | ||
|
|
679196880e |
@@ -12,6 +12,7 @@ find_package(rcpputils REQUIRED)
|
||||
find_package(rcutils REQUIRED)
|
||||
find_package(rmw REQUIRED)
|
||||
find_package(rosgraph_msgs REQUIRED)
|
||||
find_package(rosidl_default_generators REQUIRED)
|
||||
find_package(rosidl_runtime_cpp REQUIRED)
|
||||
find_package(rosidl_typesupport_c REQUIRED)
|
||||
find_package(rosidl_typesupport_cpp REQUIRED)
|
||||
@@ -26,8 +27,6 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
|
||||
include_directories(include)
|
||||
|
||||
set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/any_executable.cpp
|
||||
src/rclcpp/callback_group.cpp
|
||||
@@ -41,7 +40,7 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/detail/utilities.cpp
|
||||
src/rclcpp/duration.cpp
|
||||
src/rclcpp/event.cpp
|
||||
src/rclcpp/exceptions.cpp
|
||||
src/rclcpp/exceptions/exceptions.cpp
|
||||
src/rclcpp/executable_list.cpp
|
||||
src/rclcpp/executor.cpp
|
||||
src/rclcpp/executors.cpp
|
||||
@@ -50,6 +49,7 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/executors/single_threaded_executor.cpp
|
||||
src/rclcpp/executors/static_executor_entities_collector.cpp
|
||||
src/rclcpp/executors/static_single_threaded_executor.cpp
|
||||
src/rclcpp/future_return_code.cpp
|
||||
src/rclcpp/graph_listener.cpp
|
||||
src/rclcpp/guard_condition.cpp
|
||||
src/rclcpp/init_options.cpp
|
||||
@@ -79,6 +79,8 @@ set(${PROJECT_NAME}_SRCS
|
||||
src/rclcpp/publisher_base.cpp
|
||||
src/rclcpp/qos.cpp
|
||||
src/rclcpp/qos_event.cpp
|
||||
src/rclcpp/serialization.cpp
|
||||
src/rclcpp/serialized_message.cpp
|
||||
src/rclcpp/service.cpp
|
||||
src/rclcpp/signal_handler.cpp
|
||||
src/rclcpp/subscription_base.cpp
|
||||
@@ -99,23 +101,71 @@ configure_file(
|
||||
COPYONLY
|
||||
)
|
||||
# generate header with logging macros
|
||||
set(python_code
|
||||
set(python_code_logging
|
||||
"import em"
|
||||
"em.invoke(['-o', 'include/rclcpp/logging.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/logging.hpp.em'])")
|
||||
string(REPLACE ";" "$<SEMICOLON>" python_code "${python_code}")
|
||||
string(REPLACE ";" "$<SEMICOLON>" python_code_logging "${python_code_logging}")
|
||||
add_custom_command(OUTPUT include/rclcpp/logging.hpp
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp"
|
||||
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_code}"
|
||||
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_code_logging}"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/logging.hpp.em.watch"
|
||||
COMMENT "Expanding logging.hpp.em"
|
||||
VERBATIM
|
||||
)
|
||||
list(APPEND ${PROJECT_NAME}_SRCS
|
||||
include/rclcpp/logging.hpp)
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
|
||||
file(GLOB interface_files "include/rclcpp/node_interfaces/node_*_interface.hpp")
|
||||
foreach(interface_file ${interface_files})
|
||||
get_filename_component(interface_name ${interface_file} NAME_WE)
|
||||
|
||||
# "watch" template for changes
|
||||
configure_file(
|
||||
"resource/interface_traits.hpp.em"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${interface_name}_traits.hpp.em.watch"
|
||||
COPYONLY
|
||||
)
|
||||
set(python_${interface_name}_traits
|
||||
"import em"
|
||||
"em.invoke(['-D', 'interface_name = \\'${interface_name}\\'', '-o', 'include/rclcpp/node_interfaces/${interface_name}_traits.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/interface_traits.hpp.em'])")
|
||||
string(REPLACE ";" "$<SEMICOLON>" python_${interface_name}_traits "${python_${interface_name}_traits}")
|
||||
add_custom_command(OUTPUT include/rclcpp/node_interfaces/${interface_name}_traits.hpp
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp/node_interfaces"
|
||||
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_${interface_name}_traits}"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${interface_name}_traits.hpp.em.watch"
|
||||
COMMENT "Expanding interface_traits.hpp.em into ${interface_name}_traits.hpp"
|
||||
VERBATIM
|
||||
)
|
||||
list(APPEND ${PROJECT_NAME}_SRCS
|
||||
include/rclcpp/node_interfaces/${interface_name}_traits.hpp)
|
||||
|
||||
# "watch" template for changes
|
||||
configure_file(
|
||||
"resource/get_interface.hpp.em"
|
||||
"get_${interface_name}.hpp.em.watch"
|
||||
COPYONLY
|
||||
)
|
||||
set(python_get_${interface_name}
|
||||
"import em"
|
||||
"em.invoke(['-D', 'interface_name = \\'${interface_name}\\'', '-o', 'include/rclcpp/node_interfaces/get_${interface_name}.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/get_interface.hpp.em'])")
|
||||
string(REPLACE ";" "$<SEMICOLON>" python_get_${interface_name} "${python_get_${interface_name}}")
|
||||
add_custom_command(OUTPUT include/rclcpp/node_interfaces/get_${interface_name}.hpp
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp/node_interfaces"
|
||||
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_get_${interface_name}}"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/get_${interface_name}.hpp.em.watch"
|
||||
COMMENT "Expanding get_interface.hpp.em into get_${interface_file}.hpp"
|
||||
VERBATIM
|
||||
)
|
||||
list(APPEND ${PROJECT_NAME}_SRCS
|
||||
include/rclcpp/node_interfaces/get_${interface_name}.hpp)
|
||||
endforeach()
|
||||
|
||||
add_library(${PROJECT_NAME}
|
||||
${${PROJECT_NAME}_SRCS})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:include>")
|
||||
# specific order: dependents before dependencies
|
||||
ament_target_dependencies(${PROJECT_NAME}
|
||||
"libstatistics_collector"
|
||||
@@ -137,7 +187,7 @@ target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE "RCLCPP_BUILDING_LIBRARY")
|
||||
|
||||
install(
|
||||
TARGETS ${PROJECT_NAME}
|
||||
TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
RUNTIME DESTINATION bin
|
||||
@@ -146,6 +196,7 @@ install(
|
||||
# specific order: dependents before dependencies
|
||||
ament_export_include_directories(include)
|
||||
ament_export_libraries(${PROJECT_NAME})
|
||||
ament_export_targets(${PROJECT_NAME})
|
||||
|
||||
ament_export_dependencies(libstatistics_collector)
|
||||
ament_export_dependencies(rcl)
|
||||
@@ -173,6 +224,14 @@ if(BUILD_TESTING)
|
||||
|
||||
add_definitions(-DTEST_RESOURCES_DIRECTORY="${CMAKE_CURRENT_BINARY_DIR}/test/resources")
|
||||
|
||||
rosidl_generate_interfaces(${PROJECT_NAME}_test_msgs
|
||||
test/msg/Header.msg
|
||||
test/msg/MessageWithHeader.msg
|
||||
DEPENDENCIES builtin_interfaces
|
||||
LIBRARY_NAME ${PROJECT_NAME}
|
||||
SKIP_INSTALL
|
||||
)
|
||||
|
||||
ament_add_gtest(test_client test/test_client.cpp)
|
||||
if(TARGET test_client)
|
||||
ament_target_dependencies(test_client
|
||||
@@ -207,6 +266,7 @@ if(BUILD_TESTING)
|
||||
endif()
|
||||
ament_add_gtest(test_function_traits test/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"
|
||||
@@ -399,6 +459,15 @@ if(BUILD_TESTING)
|
||||
${PROJECT_NAME}
|
||||
)
|
||||
endif()
|
||||
ament_add_gtest(test_serialized_message test/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}
|
||||
)
|
||||
endif()
|
||||
ament_add_gtest(test_service test/test_service.cpp)
|
||||
if(TARGET test_service)
|
||||
ament_target_dependencies(test_service
|
||||
@@ -437,6 +506,7 @@ if(BUILD_TESTING)
|
||||
"rcl"
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_subscription_traits ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_find_weak_nodes test/test_find_weak_nodes.cpp)
|
||||
if(TARGET test_find_weak_nodes)
|
||||
@@ -520,6 +590,14 @@ if(BUILD_TESTING)
|
||||
target_link_libraries(test_init ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_interface_traits test/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()
|
||||
|
||||
ament_add_gtest(test_multi_threaded_executor test/executors/test_multi_threaded_executor.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_multi_threaded_executor)
|
||||
@@ -541,9 +619,12 @@ if(BUILD_TESTING)
|
||||
target_link_libraries(test_wait_set ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_subscription_topic_statistics test/topic_statistics/test_subscription_topic_statistics.cpp)
|
||||
ament_add_gtest(test_subscription_topic_statistics test/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"
|
||||
@@ -552,6 +633,7 @@ if(BUILD_TESTING)
|
||||
"rosidl_typesupport_cpp"
|
||||
"statistics_msgs"
|
||||
"test_msgs")
|
||||
rosidl_target_interfaces(test_subscription_topic_statistics ${PROJECT_NAME}_test_msgs "rosidl_typesupport_cpp")
|
||||
target_link_libraries(test_subscription_topic_statistics ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace executor
|
||||
{
|
||||
|
||||
struct AnyExecutable
|
||||
{
|
||||
@@ -47,10 +45,15 @@ struct AnyExecutable
|
||||
rclcpp::ClientBase::SharedPtr client;
|
||||
rclcpp::Waitable::SharedPtr waitable;
|
||||
// These are used to keep the scope on the containing items
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group;
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group;
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base;
|
||||
};
|
||||
|
||||
namespace executor
|
||||
{
|
||||
|
||||
using AnyExecutable [[deprecated("use rclcpp::AnyExecutable instead")]] = AnyExecutable;
|
||||
|
||||
} // namespace executor
|
||||
} // namespace rclcpp
|
||||
|
||||
|
||||
@@ -40,9 +40,6 @@ class NodeTopics;
|
||||
class NodeWaitables;
|
||||
} // namespace node_interfaces
|
||||
|
||||
namespace callback_group
|
||||
{
|
||||
|
||||
enum class CallbackGroupType
|
||||
{
|
||||
MutuallyExclusive,
|
||||
@@ -162,6 +159,12 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
namespace callback_group
|
||||
{
|
||||
|
||||
using CallbackGroupType [[deprecated("use rclcpp::CallbackGroupType instead")]] = CallbackGroupType;
|
||||
using CallbackGroup [[deprecated("use rclcpp::CallbackGroup instead")]] = CallbackGroup;
|
||||
|
||||
} // namespace callback_group
|
||||
} // namespace rclcpp
|
||||
|
||||
|
||||
@@ -338,6 +338,9 @@ private:
|
||||
rclcpp::InitOptions init_options_;
|
||||
std::string shutdown_reason_;
|
||||
|
||||
// Keep shared ownership of global logging configure mutex.
|
||||
std::shared_ptr<std::mutex> logging_configure_mutex_;
|
||||
|
||||
std::unordered_map<std::type_index, std::shared_ptr<void>> sub_contexts_;
|
||||
// This mutex is recursive so that the constructor of a sub context may
|
||||
// attempt to acquire another sub context.
|
||||
|
||||
@@ -22,8 +22,6 @@ namespace rclcpp
|
||||
{
|
||||
namespace contexts
|
||||
{
|
||||
namespace default_context
|
||||
{
|
||||
|
||||
class DefaultContext : public rclcpp::Context
|
||||
{
|
||||
@@ -38,6 +36,21 @@ RCLCPP_PUBLIC
|
||||
DefaultContext::SharedPtr
|
||||
get_global_default_context();
|
||||
|
||||
namespace default_context
|
||||
{
|
||||
|
||||
using DefaultContext
|
||||
[[deprecated("use rclcpp::contexts::DefaultContext instead")]] = DefaultContext;
|
||||
|
||||
[[deprecated("use rclcpp::contexts::get_global_default_context() instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
inline
|
||||
DefaultContext::SharedPtr
|
||||
get_global_default_context()
|
||||
{
|
||||
return rclcpp::contexts::get_global_default_context();
|
||||
}
|
||||
|
||||
} // namespace default_context
|
||||
} // namespace contexts
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -35,7 +35,7 @@ create_client(
|
||||
std::shared_ptr<node_interfaces::NodeServicesInterface> node_services,
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
rcl_client_options_t options = rcl_client_get_default_options();
|
||||
options.qos = qos_profile;
|
||||
|
||||
@@ -37,7 +37,7 @@ create_service(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
rclcpp::AnyServiceCallback<ServiceT> any_service_callback;
|
||||
any_service_callback.set(std::forward<CallbackT>(callback));
|
||||
|
||||
@@ -15,15 +15,25 @@
|
||||
#ifndef RCLCPP__CREATE_SUBSCRIPTION_HPP_
|
||||
#define RCLCPP__CREATE_SUBSCRIPTION_HPP_
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/detail/resolve_enable_topic_statistics.hpp"
|
||||
|
||||
#include "rclcpp/node_interfaces/get_node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/get_node_topics_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
|
||||
#include "rclcpp/create_timer.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/subscription_factory.hpp"
|
||||
#include "rclcpp/subscription_options.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/timer.hpp"
|
||||
#include "rclcpp/topic_statistics/subscription_topic_statistics.hpp"
|
||||
#include "rmw/qos_profiles.h"
|
||||
|
||||
namespace rclcpp
|
||||
@@ -64,10 +74,46 @@ create_subscription(
|
||||
using rclcpp::node_interfaces::get_node_topics_interface;
|
||||
auto node_topics = get_node_topics_interface(std::forward<NodeT>(node));
|
||||
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>>
|
||||
subscription_topic_stats = nullptr;
|
||||
|
||||
if (rclcpp::detail::resolve_enable_topic_statistics(
|
||||
options,
|
||||
*node_topics->get_node_base_interface()))
|
||||
{
|
||||
std::shared_ptr<Publisher<statistics_msgs::msg::MetricsMessage>> publisher =
|
||||
create_publisher<statistics_msgs::msg::MetricsMessage>(
|
||||
node,
|
||||
options.topic_stats_options.publish_topic,
|
||||
qos);
|
||||
|
||||
subscription_topic_stats = std::make_shared<
|
||||
rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>
|
||||
>(node_topics->get_node_base_interface()->get_name(), publisher);
|
||||
|
||||
auto sub_call_back = [subscription_topic_stats]() {
|
||||
subscription_topic_stats->publish_message();
|
||||
};
|
||||
|
||||
auto node_timer_interface = node_topics->get_node_timers_interface();
|
||||
|
||||
auto timer = create_wall_timer(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
options.topic_stats_options.publish_period),
|
||||
sub_call_back,
|
||||
options.callback_group,
|
||||
node_topics->get_node_base_interface(),
|
||||
node_timer_interface
|
||||
);
|
||||
|
||||
subscription_topic_stats->set_publisher_timer(timer);
|
||||
}
|
||||
|
||||
auto factory = rclcpp::create_subscription_factory<MessageT>(
|
||||
std::forward<CallbackT>(callback),
|
||||
options,
|
||||
msg_mem_strat
|
||||
msg_mem_strat,
|
||||
subscription_topic_stats
|
||||
);
|
||||
|
||||
auto sub = node_topics->create_subscription(topic_name, factory, qos);
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#ifndef RCLCPP__CREATE_TIMER_HPP_
|
||||
#define RCLCPP__CREATE_TIMER_HPP_
|
||||
|
||||
#include <chrono>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -32,12 +34,12 @@ namespace rclcpp
|
||||
template<typename CallbackT>
|
||||
typename rclcpp::TimerBase::SharedPtr
|
||||
create_timer(
|
||||
node_interfaces::NodeBaseInterface * node_base,
|
||||
node_interfaces::NodeTimersInterface * node_timers,
|
||||
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
|
||||
std::shared_ptr<node_interfaces::NodeTimersInterface> node_timers,
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
auto timer = rclcpp::GenericTimer<CallbackT>::make_shared(
|
||||
clock,
|
||||
@@ -57,7 +59,7 @@ create_timer(
|
||||
rclcpp::Clock::SharedPtr clock,
|
||||
rclcpp::Duration period,
|
||||
CallbackT && callback,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr)
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr)
|
||||
{
|
||||
return create_timer(
|
||||
rclcpp::node_interfaces::get_node_base_interface(node),
|
||||
@@ -68,6 +70,46 @@ create_timer(
|
||||
group);
|
||||
}
|
||||
|
||||
/// Convenience method to create a timer with node resources.
|
||||
/**
|
||||
*
|
||||
* \tparam DurationRepT
|
||||
* \tparam DurationT
|
||||
* \tparam CallbackT
|
||||
* \param period period to exectute callback
|
||||
* \param callback callback to execute via the timer period
|
||||
* \param group
|
||||
* \param node_base
|
||||
* \param node_timers
|
||||
* \return
|
||||
* \throws std::invalid argument if either node_base or node_timers
|
||||
* are null
|
||||
*/
|
||||
template<typename DurationRepT, typename DurationT, typename CallbackT>
|
||||
typename rclcpp::WallTimer<CallbackT>::SharedPtr
|
||||
create_wall_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::CallbackGroup::SharedPtr group,
|
||||
node_interfaces::NodeBaseInterface * node_base,
|
||||
node_interfaces::NodeTimersInterface * node_timers)
|
||||
{
|
||||
if (node_base == nullptr) {
|
||||
throw std::invalid_argument{"input node_base cannot be null"};
|
||||
}
|
||||
|
||||
if (node_timers == nullptr) {
|
||||
throw std::invalid_argument{"input node_timers cannot be null"};
|
||||
}
|
||||
|
||||
auto timer = rclcpp::WallTimer<CallbackT>::make_shared(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(period),
|
||||
std::move(callback),
|
||||
node_base->get_context());
|
||||
node_timers->add_timer(timer, group);
|
||||
return timer;
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__CREATE_TIMER_HPP_
|
||||
|
||||
@@ -42,7 +42,6 @@ resolve_enable_topic_statistics(const OptionsT & options, const NodeBaseT & node
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unrecognized EnableTopicStatistics value");
|
||||
break;
|
||||
}
|
||||
|
||||
return topic_stats_enabled;
|
||||
|
||||
@@ -15,265 +15,6 @@
|
||||
#ifndef RCLCPP__EXCEPTIONS_HPP_
|
||||
#define RCLCPP__EXCEPTIONS_HPP_
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/types.h"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rcpputils/join.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace exceptions
|
||||
{
|
||||
|
||||
/// Thrown when a method is trying to use a node, but it is invalid.
|
||||
class InvalidNodeError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
InvalidNodeError()
|
||||
: std::runtime_error("node is invalid") {}
|
||||
};
|
||||
|
||||
/// Thrown when a any kind of name (node, namespace, topic, etc.) is invalid.
|
||||
class NameValidationError : public std::invalid_argument
|
||||
{
|
||||
public:
|
||||
NameValidationError(
|
||||
const char * name_type_,
|
||||
const char * name_,
|
||||
const char * error_msg_,
|
||||
size_t invalid_index_)
|
||||
: std::invalid_argument(format_error(name_type_, name_, error_msg_, invalid_index_)),
|
||||
name_type(name_type_), name(name_), error_msg(error_msg_), invalid_index(invalid_index_)
|
||||
{}
|
||||
|
||||
static std::string
|
||||
format_error(
|
||||
const char * name_type,
|
||||
const char * name,
|
||||
const char * error_msg,
|
||||
size_t invalid_index);
|
||||
|
||||
const std::string name_type;
|
||||
const std::string name;
|
||||
const std::string error_msg;
|
||||
const size_t invalid_index;
|
||||
};
|
||||
|
||||
/// Thrown when a node name is invalid.
|
||||
class InvalidNodeNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidNodeNameError(const char * node_name, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("node name", node_name, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a node namespace is invalid.
|
||||
class InvalidNamespaceError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidNamespaceError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("namespace", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a topic name is invalid.
|
||||
class InvalidTopicNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidTopicNameError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("topic name", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a service name is invalid.
|
||||
class InvalidServiceNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidServiceNameError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("service name", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Throw a C++ std::exception which was created based on an rcl error.
|
||||
/**
|
||||
* Passing nullptr for reset_error is safe and will avoid calling any function
|
||||
* to reset the error.
|
||||
*
|
||||
* \param ret the return code for the current error state
|
||||
* \param prefix string to prefix to the error if applicable (not all errors have custom messages)
|
||||
* \param error_state error state to create exception from, if nullptr rcl_get_error_state is used
|
||||
* \param reset_error function to be called before throwing which whill clear the error state
|
||||
* \throws std::invalid_argument if ret is RCL_RET_OK
|
||||
* \throws std::runtime_error if the rcl_get_error_state returns 0
|
||||
* \throws RCLErrorBase some child class exception based on ret
|
||||
*/
|
||||
/* *INDENT-OFF* */ // Uncrustify cannot yet understand [[noreturn]] properly
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
throw_from_rcl_error [[noreturn]] (
|
||||
rcl_ret_t ret,
|
||||
const std::string & prefix = "",
|
||||
const rcl_error_state_t * error_state = nullptr,
|
||||
void (* reset_error)() = rcl_reset_error);
|
||||
/* *INDENT-ON* */
|
||||
|
||||
class RCLErrorBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLErrorBase(rcl_ret_t ret, const rcl_error_state_t * error_state);
|
||||
virtual ~RCLErrorBase() {}
|
||||
|
||||
rcl_ret_t ret;
|
||||
std::string message;
|
||||
std::string file;
|
||||
size_t line;
|
||||
std::string formatted_message;
|
||||
};
|
||||
|
||||
/// Created when the return code does not match one of the other specialized exceptions.
|
||||
class RCLError : public RCLErrorBase, public std::runtime_error
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLError(rcl_ret_t ret, const rcl_error_state_t * error_state, const std::string & prefix);
|
||||
RCLCPP_PUBLIC
|
||||
RCLError(const RCLErrorBase & base_exc, const std::string & prefix);
|
||||
};
|
||||
|
||||
/// Created when the ret is RCL_RET_BAD_ALLOC.
|
||||
class RCLBadAlloc : public RCLErrorBase, public std::bad_alloc
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLBadAlloc(rcl_ret_t ret, const rcl_error_state_t * error_state);
|
||||
RCLCPP_PUBLIC
|
||||
explicit RCLBadAlloc(const RCLErrorBase & base_exc);
|
||||
};
|
||||
|
||||
/// Created when the ret is RCL_RET_INVALID_ARGUMENT.
|
||||
class RCLInvalidArgument : public RCLErrorBase, public std::invalid_argument
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidArgument(
|
||||
rcl_ret_t ret,
|
||||
const rcl_error_state_t * error_state,
|
||||
const std::string & prefix);
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidArgument(const RCLErrorBase & base_exc, const std::string & prefix);
|
||||
};
|
||||
|
||||
/// Created when the ret is RCL_RET_INVALID_ROS_ARGS.
|
||||
class RCLInvalidROSArgsError : public RCLErrorBase, public std::runtime_error
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidROSArgsError(
|
||||
rcl_ret_t ret, const rcl_error_state_t * error_state, const std::string & prefix);
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidROSArgsError(const RCLErrorBase & base_exc, const std::string & prefix);
|
||||
};
|
||||
|
||||
/// Thrown when unparsed ROS specific arguments are found.
|
||||
class UnknownROSArgsError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit UnknownROSArgsError(std::vector<std::string> && unknown_ros_args_in)
|
||||
: std::runtime_error(
|
||||
"found unknown ROS arguments: '" + rcpputils::join(unknown_ros_args_in, "', '") + "'"),
|
||||
unknown_ros_args(unknown_ros_args_in)
|
||||
{
|
||||
}
|
||||
|
||||
const std::vector<std::string> unknown_ros_args;
|
||||
};
|
||||
|
||||
/// Thrown when an invalid rclcpp::Event object or SharedPtr is encountered.
|
||||
class InvalidEventError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
InvalidEventError()
|
||||
: std::runtime_error("event is invalid") {}
|
||||
};
|
||||
|
||||
/// Thrown when an unregistered rclcpp::Event is encountered where a registered one was expected.
|
||||
class EventNotRegisteredError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
EventNotRegisteredError()
|
||||
: std::runtime_error("event already registered") {}
|
||||
};
|
||||
|
||||
/// Thrown if passed parameters are inconsistent or invalid
|
||||
class InvalidParametersException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if passed parameter value is invalid.
|
||||
class InvalidParameterValueException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if requested parameter type is invalid.
|
||||
/**
|
||||
* Essentially the same as rclcpp::ParameterTypeException, but with parameter
|
||||
* name in the error message.
|
||||
*/
|
||||
class InvalidParameterTypeException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/// Construct an instance.
|
||||
/**
|
||||
* \param[in] name the name of the parameter.
|
||||
* \param[in] message custom exception message.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
InvalidParameterTypeException(const std::string & name, const std::string message)
|
||||
: std::runtime_error("parameter '" + name + "' has invalid type: " + message)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown if parameter is already declared.
|
||||
class ParameterAlreadyDeclaredException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is not declared, e.g. either set or get was called without first declaring.
|
||||
class ParameterNotDeclaredException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is immutable and therefore cannot be undeclared.
|
||||
class ParameterImmutableException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is modified while in a set callback.
|
||||
class ParameterModifiedInCallbackException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
} // namespace exceptions
|
||||
} // namespace rclcpp
|
||||
#include "rclcpp/exceptions/exceptions.hpp"
|
||||
|
||||
#endif // RCLCPP__EXCEPTIONS_HPP_
|
||||
|
||||
279
rclcpp/include/rclcpp/exceptions/exceptions.hpp
Normal file
279
rclcpp/include/rclcpp/exceptions/exceptions.hpp
Normal file
@@ -0,0 +1,279 @@
|
||||
// Copyright 2016 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXCEPTIONS__EXCEPTIONS_HPP_
|
||||
#define RCLCPP__EXCEPTIONS__EXCEPTIONS_HPP_
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/types.h"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rcpputils/join.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace exceptions
|
||||
{
|
||||
|
||||
/// Thrown when a method is trying to use a node, but it is invalid.
|
||||
class InvalidNodeError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
InvalidNodeError()
|
||||
: std::runtime_error("node is invalid") {}
|
||||
};
|
||||
|
||||
/// Thrown when a any kind of name (node, namespace, topic, etc.) is invalid.
|
||||
class NameValidationError : public std::invalid_argument
|
||||
{
|
||||
public:
|
||||
NameValidationError(
|
||||
const char * name_type_,
|
||||
const char * name_,
|
||||
const char * error_msg_,
|
||||
size_t invalid_index_)
|
||||
: std::invalid_argument(format_error(name_type_, name_, error_msg_, invalid_index_)),
|
||||
name_type(name_type_), name(name_), error_msg(error_msg_), invalid_index(invalid_index_)
|
||||
{}
|
||||
|
||||
static std::string
|
||||
format_error(
|
||||
const char * name_type,
|
||||
const char * name,
|
||||
const char * error_msg,
|
||||
size_t invalid_index);
|
||||
|
||||
const std::string name_type;
|
||||
const std::string name;
|
||||
const std::string error_msg;
|
||||
const size_t invalid_index;
|
||||
};
|
||||
|
||||
/// Thrown when a node name is invalid.
|
||||
class InvalidNodeNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidNodeNameError(const char * node_name, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("node name", node_name, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a node namespace is invalid.
|
||||
class InvalidNamespaceError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidNamespaceError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("namespace", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a topic name is invalid.
|
||||
class InvalidTopicNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidTopicNameError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("topic name", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown when a service name is invalid.
|
||||
class InvalidServiceNameError : public NameValidationError
|
||||
{
|
||||
public:
|
||||
InvalidServiceNameError(const char * namespace_, const char * error_msg, size_t invalid_index)
|
||||
: NameValidationError("service name", namespace_, error_msg, invalid_index)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Throw a C++ std::exception which was created based on an rcl error.
|
||||
/**
|
||||
* Passing nullptr for reset_error is safe and will avoid calling any function
|
||||
* to reset the error.
|
||||
*
|
||||
* \param ret the return code for the current error state
|
||||
* \param prefix string to prefix to the error if applicable (not all errors have custom messages)
|
||||
* \param error_state error state to create exception from, if nullptr rcl_get_error_state is used
|
||||
* \param reset_error function to be called before throwing which whill clear the error state
|
||||
* \throws std::invalid_argument if ret is RCL_RET_OK
|
||||
* \throws std::runtime_error if the rcl_get_error_state returns 0
|
||||
* \throws RCLErrorBase some child class exception based on ret
|
||||
*/
|
||||
/* *INDENT-OFF* */ // Uncrustify cannot yet understand [[noreturn]] properly
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
throw_from_rcl_error [[noreturn]] (
|
||||
rcl_ret_t ret,
|
||||
const std::string & prefix = "",
|
||||
const rcl_error_state_t * error_state = nullptr,
|
||||
void (* reset_error)() = rcl_reset_error);
|
||||
/* *INDENT-ON* */
|
||||
|
||||
class RCLErrorBase
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLErrorBase(rcl_ret_t ret, const rcl_error_state_t * error_state);
|
||||
virtual ~RCLErrorBase() {}
|
||||
|
||||
rcl_ret_t ret;
|
||||
std::string message;
|
||||
std::string file;
|
||||
size_t line;
|
||||
std::string formatted_message;
|
||||
};
|
||||
|
||||
/// Created when the return code does not match one of the other specialized exceptions.
|
||||
class RCLError : public RCLErrorBase, public std::runtime_error
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLError(rcl_ret_t ret, const rcl_error_state_t * error_state, const std::string & prefix);
|
||||
RCLCPP_PUBLIC
|
||||
RCLError(const RCLErrorBase & base_exc, const std::string & prefix);
|
||||
};
|
||||
|
||||
/// Created when the ret is RCL_RET_BAD_ALLOC.
|
||||
class RCLBadAlloc : public RCLErrorBase, public std::bad_alloc
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLBadAlloc(rcl_ret_t ret, const rcl_error_state_t * error_state);
|
||||
RCLCPP_PUBLIC
|
||||
explicit RCLBadAlloc(const RCLErrorBase & base_exc);
|
||||
};
|
||||
|
||||
/// Created when the ret is RCL_RET_INVALID_ARGUMENT.
|
||||
class RCLInvalidArgument : public RCLErrorBase, public std::invalid_argument
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidArgument(
|
||||
rcl_ret_t ret,
|
||||
const rcl_error_state_t * error_state,
|
||||
const std::string & prefix);
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidArgument(const RCLErrorBase & base_exc, const std::string & prefix);
|
||||
};
|
||||
|
||||
/// Created when the ret is RCL_RET_INVALID_ROS_ARGS.
|
||||
class RCLInvalidROSArgsError : public RCLErrorBase, public std::runtime_error
|
||||
{
|
||||
public:
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidROSArgsError(
|
||||
rcl_ret_t ret, const rcl_error_state_t * error_state, const std::string & prefix);
|
||||
RCLCPP_PUBLIC
|
||||
RCLInvalidROSArgsError(const RCLErrorBase & base_exc, const std::string & prefix);
|
||||
};
|
||||
|
||||
/// Thrown when unparsed ROS specific arguments are found.
|
||||
class UnknownROSArgsError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit UnknownROSArgsError(std::vector<std::string> && unknown_ros_args_in)
|
||||
: std::runtime_error(
|
||||
"found unknown ROS arguments: '" + rcpputils::join(unknown_ros_args_in, "', '") + "'"),
|
||||
unknown_ros_args(unknown_ros_args_in)
|
||||
{
|
||||
}
|
||||
|
||||
const std::vector<std::string> unknown_ros_args;
|
||||
};
|
||||
|
||||
/// Thrown when an invalid rclcpp::Event object or SharedPtr is encountered.
|
||||
class InvalidEventError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
InvalidEventError()
|
||||
: std::runtime_error("event is invalid") {}
|
||||
};
|
||||
|
||||
/// Thrown when an unregistered rclcpp::Event is encountered where a registered one was expected.
|
||||
class EventNotRegisteredError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
EventNotRegisteredError()
|
||||
: std::runtime_error("event already registered") {}
|
||||
};
|
||||
|
||||
/// Thrown if passed parameters are inconsistent or invalid
|
||||
class InvalidParametersException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if passed parameter value is invalid.
|
||||
class InvalidParameterValueException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if requested parameter type is invalid.
|
||||
/**
|
||||
* Essentially the same as rclcpp::ParameterTypeException, but with parameter
|
||||
* name in the error message.
|
||||
*/
|
||||
class InvalidParameterTypeException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
/// Construct an instance.
|
||||
/**
|
||||
* \param[in] name the name of the parameter.
|
||||
* \param[in] message custom exception message.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
InvalidParameterTypeException(const std::string & name, const std::string message)
|
||||
: std::runtime_error("parameter '" + name + "' has invalid type: " + message)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Thrown if parameter is already declared.
|
||||
class ParameterAlreadyDeclaredException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is not declared, e.g. either set or get was called without first declaring.
|
||||
class ParameterNotDeclaredException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is immutable and therefore cannot be undeclared.
|
||||
class ParameterImmutableException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/// Thrown if parameter is modified while in a set callback.
|
||||
class ParameterModifiedInCallbackException : public std::runtime_error
|
||||
{
|
||||
// Inherit constructors from runtime_error.
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
} // namespace exceptions
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXCEPTIONS__EXCEPTIONS_HPP_
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "rcl/wait.h"
|
||||
|
||||
#include "rclcpp/contexts/default_context.hpp"
|
||||
#include "rclcpp/executor_options.hpp"
|
||||
#include "rclcpp/future_return_code.hpp"
|
||||
#include "rclcpp/memory_strategies.hpp"
|
||||
#include "rclcpp/memory_strategy.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
@@ -42,48 +44,6 @@ namespace rclcpp
|
||||
// Forward declaration is used in convenience method signature.
|
||||
class Node;
|
||||
|
||||
namespace executor
|
||||
{
|
||||
|
||||
/// Return codes to be used with spin_until_future_complete.
|
||||
/**
|
||||
* SUCCESS: The future is complete and can be accessed with "get" without blocking.
|
||||
* This does not indicate that the operation succeeded; "get" may still throw an exception.
|
||||
* INTERRUPTED: The future is not complete, spinning was interrupted by Ctrl-C or another error.
|
||||
* TIMEOUT: Spinning timed out.
|
||||
*/
|
||||
enum class FutureReturnCode {SUCCESS, INTERRUPTED, TIMEOUT};
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::ostream &
|
||||
operator<<(std::ostream & os, const FutureReturnCode & future_return_code);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
to_string(const FutureReturnCode & future_return_code);
|
||||
|
||||
///
|
||||
/**
|
||||
* Options to be passed to the executor constructor.
|
||||
*/
|
||||
struct ExecutorArgs
|
||||
{
|
||||
ExecutorArgs()
|
||||
: memory_strategy(memory_strategies::create_default_strategy()),
|
||||
context(rclcpp::contexts::default_context::get_global_default_context()),
|
||||
max_conditions(0)
|
||||
{}
|
||||
|
||||
memory_strategy::MemoryStrategy::SharedPtr memory_strategy;
|
||||
std::shared_ptr<rclcpp::Context> context;
|
||||
size_t max_conditions;
|
||||
};
|
||||
|
||||
static inline ExecutorArgs create_default_executor_arguments()
|
||||
{
|
||||
return ExecutorArgs();
|
||||
}
|
||||
|
||||
/// Coordinate the order and timing of available communication tasks.
|
||||
/**
|
||||
* Executor provides spin functions (including spin_node_once and spin_some).
|
||||
@@ -100,9 +60,11 @@ public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(Executor)
|
||||
|
||||
/// Default constructor.
|
||||
// \param[in] ms The memory strategy to be used with this executor.
|
||||
/**
|
||||
* \param[in] options Options used to configure the executor.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit Executor(const ExecutorArgs & args = ExecutorArgs());
|
||||
explicit Executor(const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
|
||||
|
||||
/// Default destructor.
|
||||
RCLCPP_PUBLIC
|
||||
@@ -323,10 +285,10 @@ protected:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr group);
|
||||
get_node_by_group(rclcpp::CallbackGroup::SharedPtr group);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_timer(rclcpp::TimerBase::SharedPtr timer);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
@@ -363,6 +325,11 @@ protected:
|
||||
std::list<const rcl_guard_condition_t *> guard_conditions_;
|
||||
};
|
||||
|
||||
namespace executor
|
||||
{
|
||||
|
||||
using Executor [[deprecated("use rclcpp::Executor instead")]] = rclcpp::Executor;
|
||||
|
||||
} // namespace executor
|
||||
} // namespace rclcpp
|
||||
|
||||
|
||||
57
rclcpp/include/rclcpp/executor_options.hpp
Normal file
57
rclcpp/include/rclcpp/executor_options.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2014-2020 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXECUTOR_OPTIONS_HPP_
|
||||
#define RCLCPP__EXECUTOR_OPTIONS_HPP_
|
||||
|
||||
#include "rclcpp/context.hpp"
|
||||
#include "rclcpp/contexts/default_context.hpp"
|
||||
#include "rclcpp/memory_strategies.hpp"
|
||||
#include "rclcpp/memory_strategy.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Options to be passed to the executor constructor.
|
||||
struct ExecutorOptions
|
||||
{
|
||||
ExecutorOptions()
|
||||
: memory_strategy(rclcpp::memory_strategies::create_default_strategy()),
|
||||
context(rclcpp::contexts::get_global_default_context()),
|
||||
max_conditions(0)
|
||||
{}
|
||||
|
||||
rclcpp::memory_strategy::MemoryStrategy::SharedPtr memory_strategy;
|
||||
rclcpp::Context::SharedPtr context;
|
||||
size_t max_conditions;
|
||||
};
|
||||
|
||||
namespace executor
|
||||
{
|
||||
|
||||
using ExecutorArgs [[deprecated("use rclcpp::ExecutorOptions instead")]] = ExecutorOptions;
|
||||
|
||||
[[deprecated("use rclcpp::ExecutorOptions() instead")]]
|
||||
inline
|
||||
rclcpp::ExecutorOptions
|
||||
create_default_executor_arguments()
|
||||
{
|
||||
return rclcpp::ExecutorOptions();
|
||||
}
|
||||
|
||||
} // namespace executor
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXECUTOR_OPTIONS_HPP_
|
||||
@@ -67,9 +67,9 @@ using rclcpp::executors::SingleThreadedExecutor;
|
||||
* \return The return code, one of `SUCCESS`, `INTERRUPTED`, or `TIMEOUT`.
|
||||
*/
|
||||
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
rclcpp::executor::FutureReturnCode
|
||||
rclcpp::FutureReturnCode
|
||||
spin_node_until_future_complete(
|
||||
rclcpp::executor::Executor & executor,
|
||||
rclcpp::Executor & executor,
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
const std::shared_future<ResponseT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
@@ -84,9 +84,9 @@ spin_node_until_future_complete(
|
||||
|
||||
template<typename NodeT = rclcpp::Node, typename ResponseT, typename TimeRepT = int64_t,
|
||||
typename TimeT = std::milli>
|
||||
rclcpp::executor::FutureReturnCode
|
||||
rclcpp::FutureReturnCode
|
||||
spin_node_until_future_complete(
|
||||
rclcpp::executor::Executor & executor,
|
||||
rclcpp::Executor & executor,
|
||||
std::shared_ptr<NodeT> node_ptr,
|
||||
const std::shared_future<ResponseT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
@@ -101,7 +101,7 @@ spin_node_until_future_complete(
|
||||
} // namespace executors
|
||||
|
||||
template<typename FutureT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
rclcpp::executor::FutureReturnCode
|
||||
rclcpp::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_ptr,
|
||||
const std::shared_future<FutureT> & future,
|
||||
@@ -113,7 +113,7 @@ spin_until_future_complete(
|
||||
|
||||
template<typename NodeT = rclcpp::Node, typename FutureT, typename TimeRepT = int64_t,
|
||||
typename TimeT = std::milli>
|
||||
rclcpp::executor::FutureReturnCode
|
||||
rclcpp::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
std::shared_ptr<NodeT> node_ptr,
|
||||
const std::shared_future<FutureT> & future,
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace rclcpp
|
||||
namespace executors
|
||||
{
|
||||
|
||||
class MultiThreadedExecutor : public executor::Executor
|
||||
class MultiThreadedExecutor : public rclcpp::Executor
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(MultiThreadedExecutor)
|
||||
@@ -45,14 +45,14 @@ public:
|
||||
* This is useful for reproducing some bugs related to taking work more than
|
||||
* once.
|
||||
*
|
||||
* \param args common arguments for all executors
|
||||
* \param options common options for all executors
|
||||
* \param number_of_threads number of threads to have in the thread pool,
|
||||
* the default 0 will use the number of cpu cores found instead
|
||||
* \param yield_before_execute if true std::this_thread::yield() is called
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
MultiThreadedExecutor(
|
||||
const executor::ExecutorArgs & args = executor::ExecutorArgs(),
|
||||
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions(),
|
||||
size_t number_of_threads = 0,
|
||||
bool yield_before_execute = false,
|
||||
std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1));
|
||||
|
||||
@@ -35,25 +35,31 @@ namespace rclcpp
|
||||
namespace executors
|
||||
{
|
||||
|
||||
/// Single-threaded executor implementation
|
||||
// This is the default executor created by rclcpp::spin.
|
||||
class SingleThreadedExecutor : public executor::Executor
|
||||
/// Single-threaded executor implementation.
|
||||
/**
|
||||
* This is the default executor created by rclcpp::spin.
|
||||
*/
|
||||
class SingleThreadedExecutor : public rclcpp::Executor
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(SingleThreadedExecutor)
|
||||
|
||||
/// Default constructor. See the default constructor for Executor.
|
||||
RCLCPP_PUBLIC
|
||||
SingleThreadedExecutor(
|
||||
const executor::ExecutorArgs & args = executor::ExecutorArgs());
|
||||
explicit SingleThreadedExecutor(
|
||||
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
|
||||
|
||||
/// Default destrcutor.
|
||||
/// Default destructor.
|
||||
RCLCPP_PUBLIC
|
||||
virtual ~SingleThreadedExecutor();
|
||||
|
||||
/// Single-threaded implementation of spin.
|
||||
// This function will block until work comes in, execute it, and keep blocking.
|
||||
// It will only be interrupt by a CTRL-C (managed by the global signal handler).
|
||||
/**
|
||||
* This function will block until work comes in, execute it, and then repeat
|
||||
* the process until canceled.
|
||||
* It may be interrupt by a call to rclcpp::Executor::cancel() or by ctrl-c
|
||||
* if the associated context is configured to shutdown on SIGINT.
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
void
|
||||
spin() override;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "rcl/guard_condition.h"
|
||||
#include "rcl/wait.h"
|
||||
|
||||
#include "rclcpp/executable_list.hpp"
|
||||
#include "rclcpp/experimental/executable_list.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/memory_strategy.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
@@ -159,7 +159,7 @@ private:
|
||||
rcl_wait_set_t * p_wait_set_ = nullptr;
|
||||
|
||||
/// Executable list: timers, subscribers, clients, services and waitables
|
||||
rclcpp::executor::ExecutableList exec_list_;
|
||||
rclcpp::experimental::ExecutableList exec_list_;
|
||||
};
|
||||
|
||||
} // namespace executors
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
|
||||
#include "rmw/rmw.h"
|
||||
|
||||
#include "rclcpp/executable_list.hpp"
|
||||
#include "rclcpp/executor.hpp"
|
||||
#include "rclcpp/executors/static_executor_entities_collector.hpp"
|
||||
#include "rclcpp/experimental/executable_list.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/memory_strategies.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
@@ -54,7 +54,7 @@ namespace executors
|
||||
* exec.spin();
|
||||
* exec.remove_node(node);
|
||||
*/
|
||||
class StaticSingleThreadedExecutor : public executor::Executor
|
||||
class StaticSingleThreadedExecutor : public rclcpp::Executor
|
||||
{
|
||||
public:
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(StaticSingleThreadedExecutor)
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
/// Default constructor. See the default constructor for Executor.
|
||||
RCLCPP_PUBLIC
|
||||
explicit StaticSingleThreadedExecutor(
|
||||
const executor::ExecutorArgs & args = executor::ExecutorArgs());
|
||||
const rclcpp::ExecutorOptions & options = rclcpp::ExecutorOptions());
|
||||
|
||||
/// Default destrcutor.
|
||||
RCLCPP_PUBLIC
|
||||
@@ -131,14 +131,14 @@ public:
|
||||
* exec.spin_until_future_complete(future);
|
||||
*/
|
||||
template<typename ResponseT, typename TimeRepT = int64_t, typename TimeT = std::milli>
|
||||
rclcpp::executor::FutureReturnCode
|
||||
rclcpp::FutureReturnCode
|
||||
spin_until_future_complete(
|
||||
std::shared_future<ResponseT> & future,
|
||||
std::chrono::duration<TimeRepT, TimeT> timeout = std::chrono::duration<TimeRepT, TimeT>(-1))
|
||||
{
|
||||
std::future_status status = future.wait_for(std::chrono::seconds(0));
|
||||
if (status == std::future_status::ready) {
|
||||
return rclcpp::executor::FutureReturnCode::SUCCESS;
|
||||
return rclcpp::FutureReturnCode::SUCCESS;
|
||||
}
|
||||
|
||||
auto end_time = std::chrono::steady_clock::now();
|
||||
@@ -159,7 +159,7 @@ public:
|
||||
// Check if the future is set, return SUCCESS if it is.
|
||||
status = future.wait_for(std::chrono::seconds(0));
|
||||
if (status == std::future_status::ready) {
|
||||
return rclcpp::executor::FutureReturnCode::SUCCESS;
|
||||
return rclcpp::FutureReturnCode::SUCCESS;
|
||||
}
|
||||
// If the original timeout is < 0, then this is blocking, never TIMEOUT.
|
||||
if (timeout_ns < std::chrono::nanoseconds::zero()) {
|
||||
@@ -168,14 +168,14 @@ public:
|
||||
// Otherwise check if we still have time to wait, return TIMEOUT if not.
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
if (now >= end_time) {
|
||||
return rclcpp::executor::FutureReturnCode::TIMEOUT;
|
||||
return rclcpp::FutureReturnCode::TIMEOUT;
|
||||
}
|
||||
// Subtract the elapsed time from the original timeout.
|
||||
timeout_left = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - now);
|
||||
}
|
||||
|
||||
// The future did not complete before ok() returned false, return INTERRUPTED.
|
||||
return rclcpp::executor::FutureReturnCode::INTERRUPTED;
|
||||
return rclcpp::FutureReturnCode::INTERRUPTED;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__EXECUTABLE_LIST_HPP_
|
||||
#define RCLCPP__EXECUTABLE_LIST_HPP_
|
||||
#ifndef RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_
|
||||
#define RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace executor
|
||||
namespace experimental
|
||||
{
|
||||
|
||||
/// This class contains subscriptionbase, timerbase, etc. which can be used to run callbacks.
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
size_t number_of_waitables;
|
||||
};
|
||||
|
||||
} // namespace executor
|
||||
} // namespace experimental
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__EXECUTABLE_LIST_HPP_
|
||||
#endif // RCLCPP__EXPERIMENTAL__EXECUTABLE_LIST_HPP_
|
||||
61
rclcpp/include/rclcpp/future_return_code.hpp
Normal file
61
rclcpp/include/rclcpp/future_return_code.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright 2014 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__FUTURE_RETURN_CODE_HPP_
|
||||
#define RCLCPP__FUTURE_RETURN_CODE_HPP_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Return codes to be used with spin_until_future_complete.
|
||||
/**
|
||||
* SUCCESS: The future is complete and can be accessed with "get" without blocking.
|
||||
* This does not indicate that the operation succeeded; "get" may still throw an exception.
|
||||
* INTERRUPTED: The future is not complete, spinning was interrupted by Ctrl-C or another error.
|
||||
* TIMEOUT: Spinning timed out.
|
||||
*/
|
||||
enum class FutureReturnCode {SUCCESS, INTERRUPTED, TIMEOUT};
|
||||
|
||||
/// Stream operator for FutureReturnCode.
|
||||
RCLCPP_PUBLIC
|
||||
std::ostream &
|
||||
operator<<(std::ostream & os, const FutureReturnCode & future_return_code);
|
||||
|
||||
/// String conversion function for FutureReturnCode.
|
||||
RCLCPP_PUBLIC
|
||||
std::string
|
||||
to_string(const FutureReturnCode & future_return_code);
|
||||
|
||||
namespace executor
|
||||
{
|
||||
|
||||
using FutureReturnCode [[deprecated("use rclcpp::FutureReturnCode instead")]] = FutureReturnCode;
|
||||
|
||||
[[deprecated("use rclcpp::to_string(const rclcpp::FutureReturnCode &) instead")]]
|
||||
inline
|
||||
std::string
|
||||
to_string(const rclcpp::FutureReturnCode & future_return_code)
|
||||
{
|
||||
return rclcpp::to_string(future_return_code);
|
||||
}
|
||||
|
||||
} // namespace executor
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__FUTURE_RETURN_CODE_HPP_
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
explicit GuardCondition(
|
||||
rclcpp::Context::SharedPtr context =
|
||||
rclcpp::contexts::default_context::get_global_default_context());
|
||||
rclcpp::contexts::get_global_default_context());
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
|
||||
@@ -42,6 +42,16 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
InitOptions(const InitOptions & other);
|
||||
|
||||
/// Return `true` if logging should be initialized when `rclcpp::Context::init` is called.
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
auto_initialize_logging() const;
|
||||
|
||||
/// Set flag indicating if logging should be initialized or not.
|
||||
RCLCPP_PUBLIC
|
||||
InitOptions &
|
||||
auto_initialize_logging(bool initialize_logging);
|
||||
|
||||
/// Assignment operator.
|
||||
RCLCPP_PUBLIC
|
||||
InitOptions &
|
||||
@@ -62,6 +72,7 @@ protected:
|
||||
|
||||
private:
|
||||
std::unique_ptr<rcl_init_options_t> init_options_;
|
||||
bool initialize_logging_{true};
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -67,27 +67,27 @@ public:
|
||||
|
||||
virtual void
|
||||
get_next_subscription(
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_service(
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_client(
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_timer(
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual void
|
||||
get_next_waitable(
|
||||
rclcpp::executor::AnyExecutable & any_exec,
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) = 0;
|
||||
|
||||
virtual rcl_allocator_t
|
||||
@@ -115,30 +115,30 @@ public:
|
||||
|
||||
static rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
get_node_by_group(
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
rclcpp::CallbackGroup::SharedPtr group,
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_service(
|
||||
rclcpp::ServiceBase::SharedPtr service,
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_client(
|
||||
rclcpp::ClientBase::SharedPtr client,
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_timer(
|
||||
rclcpp::TimerBase::SharedPtr timer,
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
static rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
static rclcpp::CallbackGroup::SharedPtr
|
||||
get_group_by_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable,
|
||||
const WeakNodeList & weak_nodes);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "rclcpp/allocator/allocator_common.hpp"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rcutils/logging_macros.h"
|
||||
@@ -46,10 +47,10 @@ public:
|
||||
using MessageAlloc = typename MessageAllocTraits::allocator_type;
|
||||
using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;
|
||||
|
||||
using SerializedMessageAllocTraits = allocator::AllocRebind<rcl_serialized_message_t, Alloc>;
|
||||
using SerializedMessageAllocTraits = allocator::AllocRebind<rclcpp::SerializedMessage, Alloc>;
|
||||
using SerializedMessageAlloc = typename SerializedMessageAllocTraits::allocator_type;
|
||||
using SerializedMessageDeleter =
|
||||
allocator::Deleter<SerializedMessageAlloc, rcl_serialized_message_t>;
|
||||
allocator::Deleter<SerializedMessageAlloc, rclcpp::SerializedMessage>;
|
||||
|
||||
using BufferAllocTraits = allocator::AllocRebind<char, Alloc>;
|
||||
using BufferAlloc = typename BufferAllocTraits::allocator_type;
|
||||
@@ -86,31 +87,12 @@ public:
|
||||
return std::allocate_shared<MessageT, MessageAlloc>(*message_allocator_.get());
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message(size_t capacity)
|
||||
virtual std::shared_ptr<rclcpp::SerializedMessage> borrow_serialized_message(size_t capacity)
|
||||
{
|
||||
auto msg = new rcl_serialized_message_t;
|
||||
*msg = rmw_get_zero_initialized_serialized_message();
|
||||
auto ret = rmw_serialized_message_init(msg, capacity, &rcutils_allocator_);
|
||||
if (ret != RCL_RET_OK) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
|
||||
auto serialized_msg = std::shared_ptr<rcl_serialized_message_t>(
|
||||
msg,
|
||||
[](rmw_serialized_message_t * msg) {
|
||||
auto fini_ret = rmw_serialized_message_fini(msg);
|
||||
delete msg;
|
||||
if (fini_ret != RCL_RET_OK) {
|
||||
RCUTILS_LOG_ERROR_NAMED(
|
||||
"rclcpp",
|
||||
"failed to destroy serialized message: %s", rcl_get_error_string().str);
|
||||
}
|
||||
});
|
||||
|
||||
return serialized_msg;
|
||||
return std::make_shared<rclcpp::SerializedMessage>(capacity);
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message()
|
||||
virtual std::shared_ptr<rclcpp::SerializedMessage> borrow_serialized_message()
|
||||
{
|
||||
return borrow_serialized_message(default_buffer_capacity_);
|
||||
}
|
||||
@@ -127,7 +109,8 @@ public:
|
||||
msg.reset();
|
||||
}
|
||||
|
||||
virtual void return_serialized_message(std::shared_ptr<rcl_serialized_message_t> & serialized_msg)
|
||||
virtual void return_serialized_message(
|
||||
std::shared_ptr<rclcpp::SerializedMessage> & serialized_msg)
|
||||
{
|
||||
serialized_msg.reset();
|
||||
}
|
||||
|
||||
@@ -135,12 +135,12 @@ public:
|
||||
|
||||
/// Create and return a callback group.
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
create_callback_group(rclcpp::callback_group::CallbackGroupType group_type);
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
create_callback_group(rclcpp::CallbackGroupType group_type);
|
||||
|
||||
/// Return the list of callback groups in the node.
|
||||
RCLCPP_PUBLIC
|
||||
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
|
||||
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
|
||||
get_callback_groups() const;
|
||||
|
||||
/// Create and return a Publisher.
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
create_wall_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/* Create and return a Client. */
|
||||
template<typename ServiceT>
|
||||
@@ -235,7 +235,7 @@ public:
|
||||
create_client(
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/* Create and return a Service. */
|
||||
template<typename ServiceT, typename CallbackT>
|
||||
@@ -244,7 +244,7 @@ public:
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_services_default,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
/// Declare and initialize a parameter, return the effective value.
|
||||
/**
|
||||
@@ -1142,7 +1142,7 @@ private:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
group_in_node(callback_group::CallbackGroup::SharedPtr group);
|
||||
group_in_node(CallbackGroup::SharedPtr group);
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
|
||||
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <rmw/rmw.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
@@ -37,10 +38,12 @@
|
||||
#include "rclcpp/create_client.hpp"
|
||||
#include "rclcpp/create_publisher.hpp"
|
||||
#include "rclcpp/create_service.hpp"
|
||||
#include "rclcpp/create_timer.hpp"
|
||||
#include "rclcpp/create_subscription.hpp"
|
||||
#include "rclcpp/detail/resolve_enable_topic_statistics.hpp"
|
||||
#include "rclcpp/parameter.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/timer.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
@@ -106,14 +109,14 @@ typename rclcpp::WallTimer<CallbackT>::SharedPtr
|
||||
Node::create_wall_timer(
|
||||
std::chrono::duration<DurationRepT, DurationT> period,
|
||||
CallbackT callback,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
auto timer = rclcpp::WallTimer<CallbackT>::make_shared(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(period),
|
||||
return rclcpp::create_wall_timer(
|
||||
period,
|
||||
std::move(callback),
|
||||
this->node_base_->get_context());
|
||||
node_timers_->add_timer(timer, group);
|
||||
return timer;
|
||||
group,
|
||||
this->node_base_.get(),
|
||||
this->node_timers_.get());
|
||||
}
|
||||
|
||||
template<typename ServiceT>
|
||||
@@ -121,7 +124,7 @@ typename Client<ServiceT>::SharedPtr
|
||||
Node::create_client(
|
||||
const std::string & service_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return rclcpp::create_client<ServiceT>(
|
||||
node_base_,
|
||||
@@ -138,7 +141,7 @@ Node::create_service(
|
||||
const std::string & service_name,
|
||||
CallbackT && callback,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return rclcpp::create_service<ServiceT, CallbackT>(
|
||||
node_base_,
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
|
||||
/// This header provides the get_node_base_interface() template function.
|
||||
/**
|
||||
* This function is useful for getting the NodeBaseInterface pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get the NodeBaseInterface pointer so long as the class
|
||||
* has a method called ``get_node_base_interface()`` which returns
|
||||
* either a pointer (const or not) to a NodeBaseInterface or a
|
||||
* std::shared_ptr to a NodeBaseInterface.
|
||||
*/
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This is a meta-programming checker for if a given Node-like object has a
|
||||
// getter called get_node_base_interface() which returns various types,
|
||||
// e.g. const pointer or a shared pointer.
|
||||
template<typename NodeType, typename ReturnType>
|
||||
struct has_get_node_base_interface
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static constexpr
|
||||
auto
|
||||
check(T *)->typename std::is_same<
|
||||
decltype(std::declval<T>().get_node_base_interface()),
|
||||
ReturnType
|
||||
>::type;
|
||||
|
||||
template<typename>
|
||||
static constexpr
|
||||
std::false_type
|
||||
check(...);
|
||||
|
||||
public:
|
||||
using type = decltype(check<NodeType>(nullptr));
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
// If NodeType is a pointer to NodeBaseInterface already (just normal function overload).
|
||||
inline
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(rclcpp::node_interfaces::NodeBaseInterface * pointer)
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_base_interface() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_base_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface>
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_base_interface().get();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_base_interface() which returns a pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_base_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_base_interface();
|
||||
}
|
||||
|
||||
// Forward shared_ptr's to const node pointer signatures.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_same<
|
||||
NodeType,
|
||||
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface_from_pointer(NodeType node_shared_pointer)
|
||||
{
|
||||
return get_node_base_interface_from_pointer(node_shared_pointer->get());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the NodeBaseInterface as a pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface(NodeType node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
return detail::get_node_base_interface_from_pointer(node_pointer);
|
||||
}
|
||||
|
||||
/// Get the NodeBaseInterface as a pointer from a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<
|
||||
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface(NodeType && node_reference)
|
||||
{
|
||||
// Forward references to detail implmentation as a pointer.
|
||||
return detail::get_node_base_interface_from_pointer(&node_reference);
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_BASE_INTERFACE_HPP_
|
||||
@@ -1,149 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
|
||||
/// This header provides the get_node_timers_interface() template function.
|
||||
/**
|
||||
* This function is useful for getting the NodeTimersInterface pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get the NodeTimersInterface pointer so long as the class
|
||||
* has a method called ``get_node_timers_interface()`` which returns
|
||||
* either a pointer (const or not) to a NodeTimersInterface or a
|
||||
* std::shared_ptr to a NodeTimersInterface.
|
||||
*/
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This is a meta-programming checker for if a given Node-like object has a
|
||||
// getter called get_node_timers_interface() which returns various types,
|
||||
// e.g. const pointer or a shared pointer.
|
||||
template<typename NodeType, typename ReturnType>
|
||||
struct has_get_node_timers_interface
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static constexpr
|
||||
auto
|
||||
check(T *)->typename std::is_same<
|
||||
decltype(std::declval<T>().get_node_timers_interface()),
|
||||
ReturnType
|
||||
>::type;
|
||||
|
||||
template<typename>
|
||||
static constexpr
|
||||
std::false_type
|
||||
check(...);
|
||||
|
||||
public:
|
||||
using type = decltype(check<NodeType>(nullptr));
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
// If NodeType is a pointer to NodeTimersInterface already (just normal function overload).
|
||||
inline
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(rclcpp::node_interfaces::NodeTimersInterface * pointer)
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_timers_interface() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_timers_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTimersInterface>
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_timers_interface().get();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_timers_interface() which returns a pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_timers_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_timers_interface();
|
||||
}
|
||||
|
||||
// Forward shared_ptr's to const node pointer signatures.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_same<
|
||||
NodeType,
|
||||
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface_from_pointer(NodeType node_shared_pointer)
|
||||
{
|
||||
return get_node_timers_interface_from_pointer(node_shared_pointer->get());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the NodeTimersInterface as a pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface(NodeType node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
return detail::get_node_timers_interface_from_pointer(node_pointer);
|
||||
}
|
||||
|
||||
/// Get the NodeTimersInterface as a pointer from a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<
|
||||
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface(NodeType && node_reference)
|
||||
{
|
||||
// Forward references to detail implmentation as a pointer.
|
||||
return detail::get_node_timers_interface_from_pointer(&node_reference);
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_TIMERS_INTERFACE_HPP_
|
||||
@@ -1,149 +0,0 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__GET_NODE_TOPICS_INTERFACE_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_NODE_TOPICS_INTERFACE_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
|
||||
/// This header provides the get_node_topics_interface() template function.
|
||||
/**
|
||||
* This function is useful for getting the NodeTopicsInterface pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get the NodeTopicsInterface pointer so long as the class
|
||||
* has a method called ``get_node_topics_interface()`` which returns
|
||||
* either a pointer (const or not) to a NodeTopicsInterface or a
|
||||
* std::shared_ptr to a NodeTopicsInterface.
|
||||
*/
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This is a meta-programming checker for if a given Node-like object has a
|
||||
// getter called get_node_topics_interface() which returns various types,
|
||||
// e.g. const pointer or a shared pointer.
|
||||
template<typename NodeType, typename ReturnType>
|
||||
struct has_get_node_topics_interface
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
static constexpr
|
||||
auto
|
||||
check(T *)->typename std::is_same<
|
||||
decltype(std::declval<T>().get_node_topics_interface()),
|
||||
ReturnType
|
||||
>::type;
|
||||
|
||||
template<typename>
|
||||
static constexpr
|
||||
std::false_type
|
||||
check(...);
|
||||
|
||||
public:
|
||||
using type = decltype(check<NodeType>(nullptr));
|
||||
static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
// If NodeType is a pointer to NodeTopicsInterface already (just normal function overload).
|
||||
inline
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface_from_pointer(rclcpp::node_interfaces::NodeTopicsInterface * pointer)
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_topics_interface() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_topics_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_topics_interface().get();
|
||||
}
|
||||
|
||||
// If NodeType has a method called get_node_topics_interface() which returns a pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_get_node_topics_interface<
|
||||
typename std::remove_pointer<NodeType>::type,
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
return node_pointer->get_node_topics_interface();
|
||||
}
|
||||
|
||||
// Forward shared_ptr's to const node pointer signatures.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_same<
|
||||
NodeType,
|
||||
typename std::shared_ptr<typename std::remove_pointer<NodeType>::type::element_type> *
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface_from_pointer(NodeType node_shared_pointer)
|
||||
{
|
||||
return get_node_topics_interface_from_pointer(node_shared_pointer->get());
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the NodeTopicsInterface as a pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<std::is_pointer<NodeType>::value, int>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface(NodeType node_pointer)
|
||||
{
|
||||
// Forward pointers to detail implmentation directly.
|
||||
return detail::get_node_topics_interface_from_pointer(node_pointer);
|
||||
}
|
||||
|
||||
/// Get the NodeTopicsInterface as a pointer from a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<
|
||||
!std::is_pointer<typename std::remove_reference<NodeType>::type>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *
|
||||
get_node_topics_interface(NodeType && node_reference)
|
||||
{
|
||||
// Forward references to detail implmentation as a pointer.
|
||||
return detail::get_node_topics_interface_from_pointer(&node_reference);
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_NODE_TOPICS_INTERFACE_HPP_
|
||||
@@ -96,22 +96,22 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
create_callback_group(rclcpp::callback_group::CallbackGroupType group_type) override;
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
create_callback_group(rclcpp::CallbackGroupType group_type) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
get_default_callback_group() override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
bool
|
||||
callback_group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group) override;
|
||||
callback_group_in_node(rclcpp::CallbackGroup::SharedPtr group) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
|
||||
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
|
||||
get_callback_groups() const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
@@ -146,8 +146,8 @@ private:
|
||||
|
||||
std::shared_ptr<rcl_node_t> node_handle_;
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr default_callback_group_;
|
||||
std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> callback_groups_;
|
||||
rclcpp::CallbackGroup::SharedPtr default_callback_group_;
|
||||
std::vector<rclcpp::CallbackGroup::WeakPtr> callback_groups_;
|
||||
|
||||
std::atomic_bool associated_with_executor_;
|
||||
|
||||
|
||||
@@ -111,25 +111,25 @@ public:
|
||||
/// Create and return a callback group.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
create_callback_group(rclcpp::callback_group::CallbackGroupType group_type) = 0;
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
create_callback_group(rclcpp::CallbackGroupType group_type) = 0;
|
||||
|
||||
/// Return the default callback group.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
get_default_callback_group() = 0;
|
||||
|
||||
/// Return true if the given callback group is associated with this node.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
bool
|
||||
callback_group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
|
||||
callback_group_in_node(rclcpp::CallbackGroup::SharedPtr group) = 0;
|
||||
|
||||
/// Return list of callback groups associated with this node.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
|
||||
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
|
||||
get_callback_groups() const = 0;
|
||||
|
||||
/// Return the atomic bool which is used to ensure only one executor is used.
|
||||
|
||||
@@ -46,14 +46,14 @@ public:
|
||||
void
|
||||
add_client(
|
||||
rclcpp::ClientBase::SharedPtr client_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) override;
|
||||
rclcpp::CallbackGroup::SharedPtr group) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
void
|
||||
add_service(
|
||||
rclcpp::ServiceBase::SharedPtr service_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) override;
|
||||
rclcpp::CallbackGroup::SharedPtr group) override;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeServices)
|
||||
|
||||
@@ -41,14 +41,14 @@ public:
|
||||
void
|
||||
add_client(
|
||||
rclcpp::ClientBase::SharedPtr client_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
|
||||
rclcpp::CallbackGroup::SharedPtr group) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
add_service(
|
||||
rclcpp::ServiceBase::SharedPtr service_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
|
||||
rclcpp::CallbackGroup::SharedPtr group) = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
void
|
||||
add_timer(
|
||||
rclcpp::TimerBase::SharedPtr timer,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) override;
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) override;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeTimers)
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
void
|
||||
add_timer(
|
||||
rclcpp::TimerBase::SharedPtr timer,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
#include "rclcpp/publisher.hpp"
|
||||
#include "rclcpp/publisher_factory.hpp"
|
||||
@@ -39,7 +40,9 @@ public:
|
||||
RCLCPP_SMART_PTR_ALIASES_ONLY(NodeTopicsInterface)
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
explicit NodeTopics(rclcpp::node_interfaces::NodeBaseInterface * node_base);
|
||||
NodeTopics(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
rclcpp::node_interfaces::NodeTimersInterface * node_timers);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
~NodeTopics() override;
|
||||
@@ -55,7 +58,7 @@ public:
|
||||
void
|
||||
add_publisher(
|
||||
rclcpp::PublisherBase::SharedPtr publisher,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) override;
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::SubscriptionBase::SharedPtr
|
||||
@@ -68,16 +71,21 @@ public:
|
||||
void
|
||||
add_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) override;
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface() const override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface() const override;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeTopics)
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base_;
|
||||
rclcpp::node_interfaces::NodeTimersInterface * node_timers_;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "rclcpp/callback_group.hpp"
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
#include "rclcpp/publisher.hpp"
|
||||
#include "rclcpp/publisher_factory.hpp"
|
||||
#include "rclcpp/subscription.hpp"
|
||||
@@ -59,7 +60,7 @@ public:
|
||||
void
|
||||
add_publisher(
|
||||
rclcpp::PublisherBase::SharedPtr publisher,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
@@ -74,12 +75,17 @@ public:
|
||||
void
|
||||
add_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::node_interfaces::NodeBaseInterface *
|
||||
get_node_base_interface() const = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
get_node_timers_interface() const = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -45,14 +45,14 @@ public:
|
||||
void
|
||||
add_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) override;
|
||||
rclcpp::CallbackGroup::SharedPtr group) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
|
||||
void
|
||||
remove_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) noexcept override;
|
||||
rclcpp::CallbackGroup::SharedPtr group) noexcept override;
|
||||
|
||||
private:
|
||||
RCLCPP_DISABLE_COPY(NodeWaitables)
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
void
|
||||
add_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) = 0;
|
||||
rclcpp::CallbackGroup::SharedPtr group) = 0;
|
||||
|
||||
/// \note this function should not throw because it may be called in destructors
|
||||
RCLCPP_PUBLIC
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
void
|
||||
remove_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) noexcept = 0;
|
||||
rclcpp::CallbackGroup::SharedPtr group) noexcept = 0;
|
||||
};
|
||||
|
||||
} // namespace node_interfaces
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
/**
|
||||
* Default values for the node options:
|
||||
*
|
||||
* - context = rclcpp::contexts::default_context::get_global_default_context()
|
||||
* - context = rclcpp::contexts::get_global_default_context()
|
||||
* - arguments = {}
|
||||
* - parameter_overrides = {}
|
||||
* - use_global_arguments = true
|
||||
@@ -338,7 +338,7 @@ private:
|
||||
// documentation in this class.
|
||||
|
||||
rclcpp::Context::SharedPtr context_ {
|
||||
rclcpp::contexts::default_context::get_global_default_context()};
|
||||
rclcpp::contexts::get_global_default_context()};
|
||||
|
||||
std::vector<std::string> arguments_ {};
|
||||
|
||||
|
||||
@@ -54,21 +54,21 @@ public:
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
AsyncParametersClient(
|
||||
const rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
AsyncParametersClient(
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group = nullptr);
|
||||
rclcpp::CallbackGroup::SharedPtr group = nullptr);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
std::shared_future<std::vector<rclcpp::Parameter>>
|
||||
@@ -205,7 +205,7 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
@@ -218,14 +218,14 @@ public:
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name = "",
|
||||
const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters);
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
|
||||
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
@@ -339,7 +339,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
rclcpp::executor::Executor::SharedPtr executor_;
|
||||
rclcpp::Executor::SharedPtr executor_;
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface_;
|
||||
AsyncParametersClient::SharedPtr async_parameters_client_;
|
||||
};
|
||||
|
||||
@@ -217,6 +217,12 @@ public:
|
||||
return this->do_serialized_publish(&serialized_msg);
|
||||
}
|
||||
|
||||
void
|
||||
publish(const SerializedMessage & serialized_msg)
|
||||
{
|
||||
return this->do_serialized_publish(&serialized_msg.get_rcl_serialized_message());
|
||||
}
|
||||
|
||||
/// Publish an instance of a LoanedMessage.
|
||||
/**
|
||||
* When publishing a loaned message, the memory for this ROS message will be deallocated
|
||||
|
||||
@@ -30,10 +30,7 @@
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
namespace callback_group
|
||||
{
|
||||
class CallbackGroup;
|
||||
} // namespace callback_group
|
||||
|
||||
/// Non-templated part of PublisherOptionsWithAllocator<Allocator>.
|
||||
struct PublisherOptionsBase
|
||||
@@ -48,7 +45,7 @@ struct PublisherOptionsBase
|
||||
bool use_default_callbacks = true;
|
||||
|
||||
/// Callback group in which the waitable items from the publisher should be placed.
|
||||
std::shared_ptr<rclcpp::callback_group::CallbackGroup> callback_group;
|
||||
std::shared_ptr<rclcpp::CallbackGroup> callback_group;
|
||||
|
||||
/// Optional RMW implementation specific payload to be used during creation of the publisher.
|
||||
std::shared_ptr<rclcpp::detail::RMWImplementationSpecificPublisherPayload>
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
* - rclcpp/executors/multi_threaded_executor.hpp
|
||||
* - CallbackGroups (mechanism for enforcing concurrency rules for callbacks):
|
||||
* - rclcpp::Node::create_callback_group()
|
||||
* - rclcpp::callback_group::CallbackGroup
|
||||
* - rclcpp::CallbackGroup
|
||||
* - rclcpp/callback_group.hpp
|
||||
*
|
||||
* Additionally, there are some methods for introspecting the ROS graph:
|
||||
|
||||
98
rclcpp/include/rclcpp/serialization.hpp
Normal file
98
rclcpp/include/rclcpp/serialization.hpp
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2020 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__SERIALIZATION_HPP_
|
||||
#define RCLCPP__SERIALIZATION_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
#include "rcl/types.h"
|
||||
|
||||
#include "rosidl_runtime_c/message_type_support_struct.h"
|
||||
|
||||
#include "rosidl_typesupport_cpp/message_type_support.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
class SerializedMessage;
|
||||
|
||||
namespace serialization_traits
|
||||
{
|
||||
// trait to check if type is the object oriented serialized message
|
||||
template<typename T>
|
||||
struct is_serialized_message_class : std::false_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_serialized_message_class<SerializedMessage>: std::true_type
|
||||
{};
|
||||
} // namespace serialization_traits
|
||||
|
||||
/// Interface to (de)serialize a message
|
||||
class RCLCPP_PUBLIC_TYPE SerializationBase
|
||||
{
|
||||
public:
|
||||
/// Constructor of SerializationBase
|
||||
/**
|
||||
* \param[in] type_support handle for the message type support
|
||||
* to be used for serialization and deserialization.
|
||||
*/
|
||||
explicit SerializationBase(const rosidl_message_type_support_t * type_support);
|
||||
|
||||
/// Destructor of SerializationBase
|
||||
virtual ~SerializationBase() = default;
|
||||
|
||||
/// Serialize a ROS2 message to a serialized stream
|
||||
/**
|
||||
* \param[in] message The ROS2 message which is read and serialized by rmw.
|
||||
* \param[out] serialized_message The serialized message.
|
||||
*/
|
||||
void serialize_message(
|
||||
const void * ros_message, SerializedMessage * serialized_message) const;
|
||||
|
||||
/// Deserialize a serialized stream to a ROS message
|
||||
/**
|
||||
* \param[in] serialized_message The serialized message to be converted to ROS2 by rmw.
|
||||
* \param[out] message The deserialized ROS2 message.
|
||||
*/
|
||||
void deserialize_message(
|
||||
const SerializedMessage * serialized_message, void * ros_message) const;
|
||||
|
||||
private:
|
||||
const rosidl_message_type_support_t * type_support_;
|
||||
};
|
||||
|
||||
/// Default implementation to (de)serialize a message by using rmw_(de)serialize
|
||||
template<typename MessageT>
|
||||
class Serialization : public SerializationBase
|
||||
{
|
||||
public:
|
||||
/// Constructor of Serialization
|
||||
Serialization()
|
||||
: SerializationBase(rosidl_typesupport_cpp::get_message_type_support_handle<MessageT>())
|
||||
{
|
||||
static_assert(
|
||||
!serialization_traits::is_serialized_message_class<MessageT>::value,
|
||||
"Serialization of serialized message to serialized message is not possible.");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__SERIALIZATION_HPP_
|
||||
121
rclcpp/include/rclcpp/serialized_message.hpp
Normal file
121
rclcpp/include/rclcpp/serialized_message.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright 2020 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef RCLCPP__SERIALIZED_MESSAGE_HPP_
|
||||
#define RCLCPP__SERIALIZED_MESSAGE_HPP_
|
||||
|
||||
#include "rcl/allocator.h"
|
||||
#include "rcl/types.h"
|
||||
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
/// Object oriented version of rcl_serialized_message_t with destructor to avoid memory leaks
|
||||
class RCLCPP_PUBLIC_TYPE SerializedMessage
|
||||
{
|
||||
public:
|
||||
/// Default constructor for a SerializedMessage
|
||||
/**
|
||||
* Default constructs a serialized message and initalizes it
|
||||
* with initial capacity of 0.
|
||||
* The allocator defaults to `rcl_get_default_allocator()`.
|
||||
*
|
||||
* \param[in] allocator The allocator to be used for the initialization.
|
||||
*/
|
||||
explicit SerializedMessage(
|
||||
const rcl_allocator_t & allocator = rcl_get_default_allocator());
|
||||
|
||||
/// Default constructor for a SerializedMessage
|
||||
/**
|
||||
* Default constructs a serialized message and initalizes it
|
||||
* with the provided capacity.
|
||||
* The allocator defaults to `rcl_get_default_allocator()`.
|
||||
*
|
||||
* \param[in] initial_capacity The amount of memory to be allocated.
|
||||
* \param[in] allocator The allocator to be used for the initialization.
|
||||
*/
|
||||
SerializedMessage(
|
||||
size_t initial_capacity,
|
||||
const rcl_allocator_t & allocator = rcl_get_default_allocator());
|
||||
|
||||
/// Copy Constructor for a SerializedMessage
|
||||
SerializedMessage(const SerializedMessage & other);
|
||||
|
||||
/// Constructor for a SerializedMessage from a rcl_serialized_message_t
|
||||
explicit SerializedMessage(const rcl_serialized_message_t & other);
|
||||
|
||||
/// Move Constructor for a SerializedMessage
|
||||
SerializedMessage(SerializedMessage && other);
|
||||
|
||||
/// Constructor for a SerializedMessage from a moved rcl_serialized_message_t
|
||||
explicit SerializedMessage(rcl_serialized_message_t && other);
|
||||
|
||||
/// Copy assignment operator
|
||||
SerializedMessage & operator=(const SerializedMessage & other);
|
||||
|
||||
/// Copy assignment operator from a rcl_serialized_message_t
|
||||
SerializedMessage & operator=(const rcl_serialized_message_t & other);
|
||||
|
||||
/// Move assignment operator
|
||||
SerializedMessage & operator=(SerializedMessage && other);
|
||||
|
||||
/// Move assignment operator from a rcl_serialized_message_t
|
||||
SerializedMessage & operator=(rcl_serialized_message_t && other);
|
||||
|
||||
/// Destructor for a SerializedMessage
|
||||
virtual ~SerializedMessage();
|
||||
|
||||
/// Get the underlying rcl_serialized_t handle
|
||||
rcl_serialized_message_t & get_rcl_serialized_message();
|
||||
|
||||
// Get a const handle to the underlying rcl_serialized_message_t
|
||||
const rcl_serialized_message_t & get_rcl_serialized_message() const;
|
||||
|
||||
/// Get the size of the serialized data buffer
|
||||
/**
|
||||
* Note, this is different from the actual amount of allocated memory.
|
||||
* This can be obtained via a call to `capacity`.
|
||||
*/
|
||||
size_t size() const;
|
||||
|
||||
/// Get the size of allocated memory for the data buffer
|
||||
/**
|
||||
* Note, this is different from the amount of content in the buffer.
|
||||
* This can be obtained via a call to `size`.
|
||||
*/
|
||||
size_t capacity() const;
|
||||
|
||||
/// Allocate memory in the data buffer
|
||||
/**
|
||||
* The data buffer of the underlying rcl_serialized_message_t will be resized.
|
||||
* This might change the data layout and invalidates all pointers to the data.
|
||||
*/
|
||||
void reserve(size_t capacity);
|
||||
|
||||
/// Release the underlying rcl_serialized_message_t
|
||||
/**
|
||||
* The memory (i.e. the data buffer) of the serialized message will no longer
|
||||
* be managed by this instance and the memory won't be deallocated on destruction.
|
||||
*/
|
||||
rcl_serialized_message_t release_rcl_serialized_message();
|
||||
|
||||
private:
|
||||
rcl_serialized_message_t serialized_message_;
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__SERIALIZED_MESSAGE_HPP_
|
||||
@@ -263,7 +263,7 @@ public:
|
||||
|
||||
void
|
||||
get_next_subscription(
|
||||
executor::AnyExecutable & any_exec,
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) override
|
||||
{
|
||||
auto it = subscription_handles_.begin();
|
||||
@@ -298,7 +298,7 @@ public:
|
||||
|
||||
void
|
||||
get_next_service(
|
||||
executor::AnyExecutable & any_exec,
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) override
|
||||
{
|
||||
auto it = service_handles_.begin();
|
||||
@@ -332,7 +332,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
get_next_client(executor::AnyExecutable & any_exec, const WeakNodeList & weak_nodes) override
|
||||
get_next_client(rclcpp::AnyExecutable & any_exec, const WeakNodeList & weak_nodes) override
|
||||
{
|
||||
auto it = client_handles_.begin();
|
||||
while (it != client_handles_.end()) {
|
||||
@@ -366,7 +366,7 @@ public:
|
||||
|
||||
void
|
||||
get_next_timer(
|
||||
executor::AnyExecutable & any_exec,
|
||||
rclcpp::AnyExecutable & any_exec,
|
||||
const WeakNodeList & weak_nodes) override
|
||||
{
|
||||
auto it = timer_handles_.begin();
|
||||
@@ -400,7 +400,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
get_next_waitable(executor::AnyExecutable & any_exec, const WeakNodeList & weak_nodes) override
|
||||
get_next_waitable(rclcpp::AnyExecutable & any_exec, const WeakNodeList & weak_nodes) override
|
||||
{
|
||||
auto it = waitable_handles_.begin();
|
||||
while (it != waitable_handles_.end()) {
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "rosidl_runtime_cpp/traits.hpp"
|
||||
|
||||
#include "rclcpp/macros.hpp"
|
||||
#include "rclcpp/message_memory_strategy.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <rmw/error_handling.h>
|
||||
#include <rmw/rmw.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@@ -25,7 +26,6 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
|
||||
#include "rcl/error_handling.h"
|
||||
#include "rcl/subscription.h"
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rclcpp/waitable.hpp"
|
||||
#include "rclcpp/topic_statistics/subscription_topic_statistics.hpp"
|
||||
#include "tracetools/tracetools.h"
|
||||
|
||||
namespace rclcpp
|
||||
@@ -75,6 +76,8 @@ public:
|
||||
using MessageDeleter = allocator::Deleter<MessageAllocator, CallbackMessageT>;
|
||||
using ConstMessageSharedPtr = std::shared_ptr<const CallbackMessageT>;
|
||||
using MessageUniquePtr = std::unique_ptr<CallbackMessageT, MessageDeleter>;
|
||||
using SubscriptionTopicStatisticsSharedPtr =
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>>;
|
||||
|
||||
RCLCPP_SMART_PTR_DEFINITIONS(Subscription)
|
||||
|
||||
@@ -98,7 +101,8 @@ public:
|
||||
const rclcpp::QoS & qos,
|
||||
AnySubscriptionCallback<CallbackMessageT, AllocatorT> callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
|
||||
typename MessageMemoryStrategyT::SharedPtr message_memory_strategy)
|
||||
typename MessageMemoryStrategyT::SharedPtr message_memory_strategy,
|
||||
SubscriptionTopicStatisticsSharedPtr subscription_topic_statistics = nullptr)
|
||||
: SubscriptionBase(
|
||||
node_base,
|
||||
type_support_handle,
|
||||
@@ -180,6 +184,10 @@ public:
|
||||
this->setup_intra_process(intra_process_subscription_id, ipm);
|
||||
}
|
||||
|
||||
if (subscription_topic_statistics != nullptr) {
|
||||
this->subscription_topic_statistics_ = std::move(subscription_topic_statistics);
|
||||
}
|
||||
|
||||
TRACEPOINT(
|
||||
rclcpp_subscription_init,
|
||||
(const void *)get_subscription_handle().get(),
|
||||
@@ -242,7 +250,7 @@ public:
|
||||
return message_memory_strategy_->borrow_message();
|
||||
}
|
||||
|
||||
std::shared_ptr<rcl_serialized_message_t>
|
||||
std::shared_ptr<rclcpp::SerializedMessage>
|
||||
create_serialized_message() override
|
||||
{
|
||||
return message_memory_strategy_->borrow_serialized_message();
|
||||
@@ -260,6 +268,13 @@ public:
|
||||
}
|
||||
auto typed_message = std::static_pointer_cast<CallbackMessageT>(message);
|
||||
any_callback_.dispatch(typed_message, message_info);
|
||||
|
||||
if (subscription_topic_statistics_) {
|
||||
const auto nanos = std::chrono::time_point_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::system_clock::now());
|
||||
const auto time = rclcpp::Time(nanos.time_since_epoch().count());
|
||||
subscription_topic_statistics_->handle_message(*typed_message, time);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -284,7 +299,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
return_serialized_message(std::shared_ptr<rcl_serialized_message_t> & message) override
|
||||
return_serialized_message(std::shared_ptr<rclcpp::SerializedMessage> & message) override
|
||||
{
|
||||
message_memory_strategy_->return_serialized_message(message);
|
||||
}
|
||||
@@ -307,6 +322,8 @@ private:
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> options_;
|
||||
typename message_memory_strategy::MessageMemoryStrategy<CallbackMessageT, AllocatorT>::SharedPtr
|
||||
message_memory_strategy_;
|
||||
/// Component which computes and publishes topic statistics for this subscriber
|
||||
SubscriptionTopicStatisticsSharedPtr subscription_topic_statistics_{nullptr};
|
||||
};
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "rclcpp/message_info.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/qos_event.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
#include "rclcpp/type_support_decl.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
|
||||
@@ -151,7 +152,7 @@ public:
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
bool
|
||||
take_serialized(rcl_serialized_message_t & message_out, rclcpp::MessageInfo & message_info_out);
|
||||
take_serialized(rclcpp::SerializedMessage & message_out, rclcpp::MessageInfo & message_info_out);
|
||||
|
||||
/// Borrow a new message.
|
||||
/** \return Shared pointer to the fresh message. */
|
||||
@@ -164,7 +165,7 @@ public:
|
||||
/** \return Shared pointer to a rcl_message_serialized_t. */
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
std::shared_ptr<rcl_serialized_message_t>
|
||||
std::shared_ptr<rclcpp::SerializedMessage>
|
||||
create_serialized_message() = 0;
|
||||
|
||||
/// Check if we need to handle the message, and execute the callback if we do.
|
||||
@@ -194,7 +195,7 @@ public:
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
void
|
||||
return_serialized_message(std::shared_ptr<rcl_serialized_message_t> & message) = 0;
|
||||
return_serialized_message(std::shared_ptr<rclcpp::SerializedMessage> & message) = 0;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const rosidl_message_type_support_t &
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "rclcpp/subscription_options.hpp"
|
||||
#include "rclcpp/subscription_traits.hpp"
|
||||
#include "rclcpp/visibility_control.hpp"
|
||||
#include "rclcpp/topic_statistics/subscription_topic_statistics.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
@@ -78,7 +79,10 @@ SubscriptionFactory
|
||||
create_subscription_factory(
|
||||
CallbackT && callback,
|
||||
const rclcpp::SubscriptionOptionsWithAllocator<AllocatorT> & options,
|
||||
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat)
|
||||
typename MessageMemoryStrategyT::SharedPtr msg_mem_strat,
|
||||
std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<CallbackMessageT>>
|
||||
subscription_topic_stats = nullptr
|
||||
)
|
||||
{
|
||||
auto allocator = options.get_allocator();
|
||||
|
||||
@@ -88,7 +92,7 @@ create_subscription_factory(
|
||||
|
||||
SubscriptionFactory factory {
|
||||
// factory function that creates a MessageT specific SubscriptionT
|
||||
[options, msg_mem_strat, any_subscription_callback](
|
||||
[options, msg_mem_strat, any_subscription_callback, subscription_topic_stats](
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
const std::string & topic_name,
|
||||
const rclcpp::QoS & qos
|
||||
@@ -104,7 +108,8 @@ create_subscription_factory(
|
||||
qos,
|
||||
any_subscription_callback,
|
||||
options,
|
||||
msg_mem_strat);
|
||||
msg_mem_strat,
|
||||
subscription_topic_stats);
|
||||
// This is used for setting up things like intra process comms which
|
||||
// require this->shared_from_this() which cannot be called from
|
||||
// the constructor.
|
||||
|
||||
@@ -45,7 +45,7 @@ struct SubscriptionOptionsBase
|
||||
bool ignore_local_publications = false;
|
||||
|
||||
/// The callback group for this subscription. NULL to use the default callback group.
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group = nullptr;
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group = nullptr;
|
||||
|
||||
/// Setting to explicitly set intraprocess communications.
|
||||
IntraProcessSetting use_intra_process_comm = IntraProcessSetting::NodeDefault;
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/function_traits.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
#include "rclcpp/subscription_options.hpp"
|
||||
#include "rcl/types.h"
|
||||
|
||||
namespace rclcpp
|
||||
@@ -41,11 +43,11 @@ struct is_serialized_subscription_argument : std::false_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_serialized_subscription_argument<rcl_serialized_message_t>: std::true_type
|
||||
struct is_serialized_subscription_argument<SerializedMessage>: std::true_type
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct is_serialized_subscription_argument<std::shared_ptr<rcl_serialized_message_t>>
|
||||
struct is_serialized_subscription_argument<std::shared_ptr<SerializedMessage>>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
@@ -75,6 +77,7 @@ struct extract_message_type<std::unique_ptr<MessageT, Deleter>>: extract_message
|
||||
|
||||
template<
|
||||
typename CallbackT,
|
||||
typename AllocatorT = std::allocator<void>,
|
||||
// Do not attempt if CallbackT is an integer (mistaken for depth)
|
||||
typename = std::enable_if_t<!std::is_integral<
|
||||
std::remove_cv_t<std::remove_reference_t<CallbackT>>>::value>,
|
||||
@@ -85,6 +88,10 @@ template<
|
||||
// Do not attempt if CallbackT is a rmw_qos_profile_t (mistaken for qos profile)
|
||||
typename = std::enable_if_t<!std::is_same<
|
||||
rmw_qos_profile_t,
|
||||
std::remove_cv_t<std::remove_reference_t<CallbackT>>>::value>,
|
||||
// Do not attempt if CallbackT is a rclcpp::SubscriptionOptionsWithAllocator
|
||||
typename = std::enable_if_t<!std::is_same<
|
||||
rclcpp::SubscriptionOptionsWithAllocator<AllocatorT>,
|
||||
std::remove_cv_t<std::remove_reference_t<CallbackT>>>::value>
|
||||
>
|
||||
struct has_message_type : extract_message_type<
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "libstatistics_collector/collector/generate_statistics_message.hpp"
|
||||
#include "libstatistics_collector/moving_average_statistics/types.hpp"
|
||||
#include "libstatistics_collector/topic_statistics_collector/constants.hpp"
|
||||
#include "libstatistics_collector/topic_statistics_collector/received_message_age.hpp"
|
||||
#include "libstatistics_collector/topic_statistics_collector/received_message_period.hpp"
|
||||
|
||||
#include "rcl/time.h"
|
||||
@@ -56,6 +57,9 @@ 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>;
|
||||
@@ -94,6 +98,8 @@ public:
|
||||
|
||||
/// Handle a message received by the subscription to collect statistics.
|
||||
/**
|
||||
* This method acquires a lock to prevent race conditions to collectors list.
|
||||
*
|
||||
* \param received_message the message received by the subscription
|
||||
* \param now_nanoseconds current time in nanoseconds
|
||||
*/
|
||||
@@ -101,6 +107,7 @@ public:
|
||||
const CallbackMessageT & received_message,
|
||||
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());
|
||||
}
|
||||
@@ -116,21 +123,32 @@ public:
|
||||
}
|
||||
|
||||
/// Publish a populated MetricsStatisticsMessage.
|
||||
/**
|
||||
* This method acquires a lock to prevent race conditions to collectors list.
|
||||
*/
|
||||
virtual void publish_message()
|
||||
{
|
||||
std::vector<MetricsMessage> msgs;
|
||||
rclcpp::Time window_end{get_current_nanoseconds_since_epoch()};
|
||||
|
||||
for (auto & collector : subscriber_statistics_collectors_) {
|
||||
const auto collected_stats = collector->GetStatisticsResults();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
for (auto & collector : subscriber_statistics_collectors_) {
|
||||
const auto collected_stats = collector->GetStatisticsResults();
|
||||
|
||||
auto message = libstatistics_collector::collector::GenerateStatisticMessage(
|
||||
node_name_,
|
||||
collector->GetMetricName(),
|
||||
collector->GetMetricUnit(),
|
||||
window_start_,
|
||||
window_end,
|
||||
collected_stats);
|
||||
publisher_->publish(message);
|
||||
auto message = libstatistics_collector::collector::GenerateStatisticMessage(
|
||||
node_name_,
|
||||
collector->GetMetricName(),
|
||||
collector->GetMetricUnit(),
|
||||
window_start_,
|
||||
window_end,
|
||||
collected_stats);
|
||||
msgs.push_back(message);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto & msg : msgs) {
|
||||
publisher_->publish(msg);
|
||||
}
|
||||
window_start_ = window_end;
|
||||
}
|
||||
@@ -138,11 +156,14 @@ public:
|
||||
protected:
|
||||
/// Return a vector of all the currently collected data.
|
||||
/**
|
||||
* This method acquires a lock to prevent race conditions to collectors list.
|
||||
*
|
||||
* \return a vector of all the collected data
|
||||
*/
|
||||
std::vector<StatisticData> get_current_collector_data() const
|
||||
{
|
||||
std::vector<StatisticData> data;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
for (const auto & collector : subscriber_statistics_collectors_) {
|
||||
data.push_back(collector->GetStatisticsResults());
|
||||
}
|
||||
@@ -151,23 +172,39 @@ protected:
|
||||
|
||||
private:
|
||||
/// Construct and start all collectors and set window_start_.
|
||||
/**
|
||||
* This method acquires a lock to prevent race conditions to collectors list.
|
||||
*/
|
||||
void bring_up()
|
||||
{
|
||||
auto received_message_age = std::make_unique<ReceivedMessageAge>();
|
||||
received_message_age->Start();
|
||||
subscriber_statistics_collectors_.emplace_back(std::move(received_message_age));
|
||||
|
||||
auto received_message_period = std::make_unique<ReceivedMessagePeriod>();
|
||||
received_message_period->Start();
|
||||
subscriber_statistics_collectors_.emplace_back(std::move(received_message_period));
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
subscriber_statistics_collectors_.emplace_back(std::move(received_message_period));
|
||||
}
|
||||
|
||||
window_start_ = rclcpp::Time(get_current_nanoseconds_since_epoch());
|
||||
}
|
||||
|
||||
/// Stop all collectors, clear measurements, stop publishing timer, and reset publisher.
|
||||
/**
|
||||
* This method acquires a lock to prevent race conditions to collectors list.
|
||||
*/
|
||||
void tear_down()
|
||||
{
|
||||
for (auto & collector : subscriber_statistics_collectors_) {
|
||||
collector->Stop();
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
for (auto & collector : subscriber_statistics_collectors_) {
|
||||
collector->Stop();
|
||||
}
|
||||
|
||||
subscriber_statistics_collectors_.clear();
|
||||
subscriber_statistics_collectors_.clear();
|
||||
}
|
||||
|
||||
if (publisher_timer_) {
|
||||
publisher_timer_->cancel();
|
||||
@@ -187,6 +224,8 @@ private:
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
|
||||
}
|
||||
|
||||
/// Mutex to protect the subsequence vectors
|
||||
mutable std::mutex mutex_;
|
||||
/// Collection of statistics collectors
|
||||
std::vector<std::unique_ptr<TopicStatsCollector>> subscriber_statistics_collectors_{};
|
||||
/// Node name used to generate topic statistics messages to be published
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace rclcpp
|
||||
/// Initialize communications via the rmw implementation and set up a global signal handler.
|
||||
/**
|
||||
* Initializes the global context which is accessible via the function
|
||||
* rclcpp::contexts::default_context::get_global_default_context().
|
||||
* rclcpp::contexts::get_global_default_context().
|
||||
* Also, installs the global signal handlers with the function
|
||||
* rclcpp::install_signal_handlers().
|
||||
*
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
const typename StoragePolicy::ServicesIterable & services = {},
|
||||
const typename StoragePolicy::WaitablesIterable & waitables = {},
|
||||
rclcpp::Context::SharedPtr context =
|
||||
rclcpp::contexts::default_context::get_global_default_context())
|
||||
rclcpp::contexts::get_global_default_context())
|
||||
: SynchronizationPolicy(context),
|
||||
StoragePolicy(
|
||||
subscriptions,
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
<test_depend>ament_lint_common</test_depend>
|
||||
<test_depend>rmw</test_depend>
|
||||
<test_depend>rmw_implementation_cmake</test_depend>
|
||||
<test_depend>rosidl_default_generators</test_depend>
|
||||
<test_depend>test_msgs</test_depend>
|
||||
|
||||
<export>
|
||||
|
||||
111
rclcpp/resource/get_interface.hpp.em
Normal file
111
rclcpp/resource/get_interface.hpp.em
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright 2020 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
@{
|
||||
uppercase_interface_name = interface_name.upper()
|
||||
}@
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__GET_@(uppercase_interface_name)_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__GET_@(uppercase_interface_name)_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rcpputils/pointer_traits.hpp"
|
||||
|
||||
#include "rclcpp/node_interfaces/@(interface_name).hpp"
|
||||
#include "rclcpp/node_interfaces/@(interface_name)_traits.hpp"
|
||||
|
||||
@{
|
||||
interface_typename = ''.join([part.capitalize() for part in interface_name.split('_')])
|
||||
}@
|
||||
|
||||
/// This header provides the get_@(interface_name)() template function.
|
||||
/**
|
||||
* This function is useful for getting the @(interface_typename) pointer from
|
||||
* various kinds of Node-like classes.
|
||||
*
|
||||
* It's able to get a std::shared_ptr to a @(interface_typename) so long as the class
|
||||
* has a method called ``get_@(interface_name)()`` which returns one.
|
||||
*/
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// If NodeType has a method called get_@(interface_name)() which returns a shared pointer.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<has_@(interface_name)<
|
||||
typename rcpputils::remove_pointer<NodeType>::type
|
||||
>::value, int>::type = 0
|
||||
>
|
||||
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)>
|
||||
get_@(interface_name)_from_pointer(NodeType node_pointer)
|
||||
{
|
||||
if (!node_pointer) {
|
||||
throw std::invalid_argument("node cannot be nullptr");
|
||||
}
|
||||
return node_pointer->get_@(interface_name)();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Get the @(interface_typename) as a shared pointer from a pointer to a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<
|
||||
rcpputils::is_pointer<NodeType>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
inline
|
||||
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)>
|
||||
get_@(interface_name)(NodeType && node)
|
||||
{
|
||||
// Forward pointers to detail implementation directly.
|
||||
return detail::get_@(interface_name)_from_pointer(node);
|
||||
}
|
||||
|
||||
/// Get the @(interface_typename) as a shared pointer from a "Node like" object.
|
||||
template<
|
||||
typename NodeType,
|
||||
typename std::enable_if<
|
||||
!rcpputils::is_pointer<NodeType>::value, int
|
||||
>::type = 0
|
||||
>
|
||||
inline
|
||||
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)>
|
||||
get_@(interface_name)(NodeType && node)
|
||||
{
|
||||
// Forward references to detail implementation as a pointer.
|
||||
return detail::get_@(interface_name)_from_pointer(&node);
|
||||
}
|
||||
|
||||
/// Keep the @(interface_typename) a shared pointer.
|
||||
inline
|
||||
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)>
|
||||
get_@(interface_name)(
|
||||
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)> & node_interface)
|
||||
{
|
||||
return node_interface;
|
||||
}
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__GET_@(uppercase_interface_name)_HPP_
|
||||
47
rclcpp/resource/interface_traits.hpp.em
Normal file
47
rclcpp/resource/interface_traits.hpp.em
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2020 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
@{
|
||||
uppercase_interface_name = interface_name.upper()
|
||||
interface_typename = ''.join([part.capitalize() for part in interface_name.split('_')])
|
||||
}@
|
||||
|
||||
#ifndef RCLCPP__NODE_INTERFACES__@(uppercase_interface_name)_TRAITS_HPP_
|
||||
#define RCLCPP__NODE_INTERFACES__@(uppercase_interface_name)_TRAITS_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/node_interfaces/@(interface_name).hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
namespace node_interfaces
|
||||
{
|
||||
|
||||
template<class T, typename = void>
|
||||
struct has_@(interface_name) : std::false_type
|
||||
{};
|
||||
|
||||
template<class T>
|
||||
struct has_@(interface_name)<
|
||||
T, typename std::enable_if<
|
||||
std::is_same<
|
||||
std::shared_ptr<rclcpp::node_interfaces::@(interface_typename)>,
|
||||
decltype(std::declval<T>().get_@(interface_name)())>::value>::type> : std::true_type
|
||||
{};
|
||||
|
||||
} // namespace node_interfaces
|
||||
} // namespace rclcpp
|
||||
|
||||
#endif // RCLCPP__NODE_INTERFACES__@(uppercase_interface_name)_TRAITS_HPP_
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include "rclcpp/any_executable.hpp"
|
||||
|
||||
using rclcpp::executor::AnyExecutable;
|
||||
using rclcpp::AnyExecutable;
|
||||
|
||||
AnyExecutable::AnyExecutable()
|
||||
: subscription(nullptr),
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
using rclcpp::callback_group::CallbackGroup;
|
||||
using rclcpp::callback_group::CallbackGroupType;
|
||||
using rclcpp::CallbackGroup;
|
||||
using rclcpp::CallbackGroupType;
|
||||
|
||||
CallbackGroup::CallbackGroup(CallbackGroupType group_type)
|
||||
: type_(group_type), can_be_taken_from_(true)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "rcl/init.h"
|
||||
#include "rcl/logging.h"
|
||||
#include "rclcpp/detail/utilities.hpp"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
@@ -34,8 +35,27 @@ static std::vector<std::weak_ptr<rclcpp::Context>> g_contexts;
|
||||
|
||||
using rclcpp::Context;
|
||||
|
||||
static
|
||||
std::shared_ptr<std::mutex>
|
||||
get_global_logging_configure_mutex()
|
||||
{
|
||||
static auto mutex = std::make_shared<std::mutex>();
|
||||
return mutex;
|
||||
}
|
||||
|
||||
static
|
||||
size_t &
|
||||
get_logging_reference_count()
|
||||
{
|
||||
static size_t ref_count = 0;
|
||||
return ref_count;
|
||||
}
|
||||
|
||||
Context::Context()
|
||||
: rcl_context_(nullptr), shutdown_reason_("") {}
|
||||
: rcl_context_(nullptr),
|
||||
shutdown_reason_(""),
|
||||
logging_configure_mutex_(nullptr)
|
||||
{}
|
||||
|
||||
Context::~Context()
|
||||
{
|
||||
@@ -94,6 +114,30 @@ Context::init(
|
||||
rcl_context_.reset();
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to initialize rcl");
|
||||
}
|
||||
|
||||
if (init_options.auto_initialize_logging()) {
|
||||
logging_configure_mutex_ = get_global_logging_configure_mutex();
|
||||
if (!logging_configure_mutex_) {
|
||||
throw std::runtime_error("global logging configure mutex is 'nullptr'");
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(*logging_configure_mutex_);
|
||||
size_t & count = get_logging_reference_count();
|
||||
if (0u == count) {
|
||||
ret = rcl_logging_configure(
|
||||
&rcl_context_->global_arguments,
|
||||
rcl_init_options_get_allocator(init_options_.get_rcl_init_options()));
|
||||
if (RCL_RET_OK != ret) {
|
||||
rcl_context_.reset();
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to configure logging");
|
||||
}
|
||||
} else {
|
||||
RCLCPP_WARN(
|
||||
rclcpp::get_logger("rclcpp"),
|
||||
"logging was initialized more than once");
|
||||
}
|
||||
++count;
|
||||
}
|
||||
|
||||
try {
|
||||
std::vector<std::string> unparsed_ros_arguments = detail::get_unparsed_ros_arguments(
|
||||
argc, argv, &(rcl_context_->global_arguments), rcl_get_default_allocator());
|
||||
@@ -183,6 +227,22 @@ Context::shutdown(const std::string & reason)
|
||||
++it;
|
||||
}
|
||||
}
|
||||
// shutdown logger
|
||||
if (logging_configure_mutex_) {
|
||||
// logging was initialized by this context
|
||||
std::lock_guard<std::mutex> guard(*logging_configure_mutex_);
|
||||
size_t & count = get_logging_reference_count();
|
||||
if (0u == --count) {
|
||||
rcl_ret_t rcl_ret = rcl_logging_fini();
|
||||
if (RCL_RET_OK != rcl_ret) {
|
||||
RCUTILS_SAFE_FWRITE_TO_STDERR(
|
||||
RCUTILS_STRINGIFY(__file__) ":"
|
||||
RCUTILS_STRINGIFY(__LINE__)
|
||||
" failed to fini logging");
|
||||
rcl_reset_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
|
||||
#include "rclcpp/contexts/default_context.hpp"
|
||||
|
||||
using rclcpp::contexts::default_context::DefaultContext;
|
||||
using rclcpp::contexts::DefaultContext;
|
||||
|
||||
DefaultContext::DefaultContext()
|
||||
{}
|
||||
|
||||
DefaultContext::SharedPtr
|
||||
rclcpp::contexts::default_context::get_global_default_context()
|
||||
rclcpp::contexts::get_global_default_context()
|
||||
{
|
||||
static DefaultContext::SharedPtr default_context = DefaultContext::make_shared();
|
||||
return default_context;
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/executable_list.hpp"
|
||||
#include "rclcpp/experimental/executable_list.hpp"
|
||||
|
||||
using rclcpp::executor::ExecutableList;
|
||||
using rclcpp::experimental::ExecutableList;
|
||||
|
||||
ExecutableList::ExecutableList()
|
||||
: number_of_subscriptions(0),
|
||||
|
||||
@@ -29,18 +29,18 @@
|
||||
#include "rcutils/logging_macros.h"
|
||||
|
||||
using rclcpp::exceptions::throw_from_rcl_error;
|
||||
using rclcpp::executor::AnyExecutable;
|
||||
using rclcpp::executor::Executor;
|
||||
using rclcpp::executor::ExecutorArgs;
|
||||
using rclcpp::executor::FutureReturnCode;
|
||||
using rclcpp::AnyExecutable;
|
||||
using rclcpp::Executor;
|
||||
using rclcpp::ExecutorOptions;
|
||||
using rclcpp::FutureReturnCode;
|
||||
|
||||
Executor::Executor(const ExecutorArgs & args)
|
||||
Executor::Executor(const rclcpp::ExecutorOptions & options)
|
||||
: spinning(false),
|
||||
memory_strategy_(args.memory_strategy)
|
||||
memory_strategy_(options.memory_strategy)
|
||||
{
|
||||
rcl_guard_condition_options_t guard_condition_options = rcl_guard_condition_get_default_options();
|
||||
rcl_ret_t ret = rcl_guard_condition_init(
|
||||
&interrupt_guard_condition_, args.context->get_rcl_context().get(), guard_condition_options);
|
||||
&interrupt_guard_condition_, options.context->get_rcl_context().get(), guard_condition_options);
|
||||
if (RCL_RET_OK != ret) {
|
||||
throw_from_rcl_error(ret, "Failed to create interrupt guard condition in Executor constructor");
|
||||
}
|
||||
@@ -49,14 +49,14 @@ Executor::Executor(const ExecutorArgs & args)
|
||||
// and one for the executor's guard cond (interrupt_guard_condition_)
|
||||
|
||||
// Put the global ctrl-c guard condition in
|
||||
memory_strategy_->add_guard_condition(args.context->get_interrupt_guard_condition(&wait_set_));
|
||||
memory_strategy_->add_guard_condition(options.context->get_interrupt_guard_condition(&wait_set_));
|
||||
|
||||
// Put the executor's guard condition in
|
||||
memory_strategy_->add_guard_condition(&interrupt_guard_condition_);
|
||||
rcl_allocator_t allocator = memory_strategy_->get_allocator();
|
||||
|
||||
// Store the context for later use.
|
||||
context_ = args.context;
|
||||
context_ = options.context;
|
||||
|
||||
ret = rcl_wait_set_init(
|
||||
&wait_set_,
|
||||
@@ -350,8 +350,7 @@ Executor::execute_subscription(rclcpp::SubscriptionBase::SharedPtr subscription)
|
||||
if (subscription->is_serialized()) {
|
||||
// This is the case where a copy of the serialized message is taken from
|
||||
// the middleware via inter-process communication.
|
||||
std::shared_ptr<rcl_serialized_message_t> serialized_msg =
|
||||
subscription->create_serialized_message();
|
||||
std::shared_ptr<SerializedMessage> serialized_msg = subscription->create_serialized_message();
|
||||
take_and_do_error_handling(
|
||||
"taking a serialized message from topic",
|
||||
subscription->get_topic_name(),
|
||||
@@ -503,7 +502,7 @@ Executor::wait_for_work(std::chrono::nanoseconds timeout)
|
||||
}
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
Executor::get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
Executor::get_node_by_group(rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
if (!group) {
|
||||
return nullptr;
|
||||
@@ -523,7 +522,7 @@ Executor::get_node_by_group(rclcpp::callback_group::CallbackGroup::SharedPtr gro
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
Executor::get_group_by_timer(rclcpp::TimerBase::SharedPtr timer)
|
||||
{
|
||||
for (auto & weak_node : weak_nodes_) {
|
||||
@@ -545,7 +544,7 @@ Executor::get_group_by_timer(rclcpp::TimerBase::SharedPtr timer)
|
||||
}
|
||||
}
|
||||
}
|
||||
return rclcpp::callback_group::CallbackGroup::SharedPtr();
|
||||
return rclcpp::CallbackGroup::SharedPtr();
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -626,29 +625,3 @@ Executor::get_next_executable(AnyExecutable & any_executable, std::chrono::nanos
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
std::ostream &
|
||||
rclcpp::executor::operator<<(std::ostream & os, const FutureReturnCode & future_return_code)
|
||||
{
|
||||
return os << to_string(future_return_code);
|
||||
}
|
||||
|
||||
std::string
|
||||
rclcpp::executor::to_string(const FutureReturnCode & future_return_code)
|
||||
{
|
||||
using enum_type = std::underlying_type<FutureReturnCode>::type;
|
||||
std::string prefix = "Unknown enum value (";
|
||||
std::string ret_as_string = std::to_string(static_cast<enum_type>(future_return_code));
|
||||
switch (future_return_code) {
|
||||
case FutureReturnCode::SUCCESS:
|
||||
prefix = "SUCCESS (";
|
||||
break;
|
||||
case FutureReturnCode::INTERRUPTED:
|
||||
prefix = "INTERRUPTED (";
|
||||
break;
|
||||
case FutureReturnCode::TIMEOUT:
|
||||
prefix = "TIMEOUT (";
|
||||
break;
|
||||
}
|
||||
return prefix + ret_as_string + ")";
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
using rclcpp::executors::MultiThreadedExecutor;
|
||||
|
||||
MultiThreadedExecutor::MultiThreadedExecutor(
|
||||
const rclcpp::executor::ExecutorArgs & args,
|
||||
const rclcpp::ExecutorOptions & options,
|
||||
size_t number_of_threads,
|
||||
bool yield_before_execute,
|
||||
std::chrono::nanoseconds next_exec_timeout)
|
||||
: executor::Executor(args),
|
||||
: rclcpp::Executor(options),
|
||||
yield_before_execute_(yield_before_execute),
|
||||
next_exec_timeout_(next_exec_timeout)
|
||||
{
|
||||
@@ -74,7 +74,7 @@ void
|
||||
MultiThreadedExecutor::run(size_t)
|
||||
{
|
||||
while (rclcpp::ok(this->context_) && spinning.load()) {
|
||||
executor::AnyExecutable any_exec;
|
||||
rclcpp::AnyExecutable any_exec;
|
||||
{
|
||||
std::lock_guard<std::mutex> wait_lock(wait_mutex_);
|
||||
if (!rclcpp::ok(this->context_) || !spinning.load()) {
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
using rclcpp::executors::SingleThreadedExecutor;
|
||||
|
||||
SingleThreadedExecutor::SingleThreadedExecutor(const rclcpp::executor::ExecutorArgs & args)
|
||||
: executor::Executor(args) {}
|
||||
SingleThreadedExecutor::SingleThreadedExecutor(const rclcpp::ExecutorOptions & options)
|
||||
: rclcpp::Executor(options) {}
|
||||
|
||||
SingleThreadedExecutor::~SingleThreadedExecutor() {}
|
||||
|
||||
@@ -31,7 +31,7 @@ SingleThreadedExecutor::spin()
|
||||
}
|
||||
RCLCPP_SCOPE_EXIT(this->spinning.store(false); );
|
||||
while (rclcpp::ok(this->context_) && spinning.load()) {
|
||||
rclcpp::executor::AnyExecutable any_executable;
|
||||
rclcpp::AnyExecutable any_executable;
|
||||
if (get_next_executable(any_executable)) {
|
||||
execute_any_executable(any_executable);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ StaticExecutorEntitiesCollector::init(
|
||||
rcl_guard_condition_t * executor_guard_condition)
|
||||
{
|
||||
// Empty initialize executable list
|
||||
exec_list_ = executor::ExecutableList();
|
||||
exec_list_ = rclcpp::experimental::ExecutableList();
|
||||
// Get executor's wait_set_ pointer
|
||||
p_wait_set_ = p_wait_set;
|
||||
// Get executor's memory strategy ptr
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
#include "rclcpp/scope_exit.hpp"
|
||||
|
||||
using rclcpp::executors::StaticSingleThreadedExecutor;
|
||||
using rclcpp::executor::ExecutableList;
|
||||
using rclcpp::experimental::ExecutableList;
|
||||
|
||||
StaticSingleThreadedExecutor::StaticSingleThreadedExecutor(
|
||||
const rclcpp::executor::ExecutorArgs & args)
|
||||
: executor::Executor(args)
|
||||
const rclcpp::ExecutorOptions & options)
|
||||
: rclcpp::Executor(options)
|
||||
{
|
||||
entities_collector_ = std::make_shared<StaticExecutorEntitiesCollector>();
|
||||
}
|
||||
|
||||
50
rclcpp/src/rclcpp/future_return_code.cpp
Normal file
50
rclcpp/src/rclcpp/future_return_code.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2015 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 <iostream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rclcpp/future_return_code.hpp"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
std::ostream &
|
||||
operator<<(std::ostream & os, const rclcpp::FutureReturnCode & future_return_code)
|
||||
{
|
||||
return os << to_string(future_return_code);
|
||||
}
|
||||
|
||||
std::string
|
||||
to_string(const rclcpp::FutureReturnCode & future_return_code)
|
||||
{
|
||||
using enum_type = std::underlying_type<FutureReturnCode>::type;
|
||||
std::string prefix = "Unknown enum value (";
|
||||
std::string ret_as_string = std::to_string(static_cast<enum_type>(future_return_code));
|
||||
switch (future_return_code) {
|
||||
case FutureReturnCode::SUCCESS:
|
||||
prefix = "SUCCESS (";
|
||||
break;
|
||||
case FutureReturnCode::INTERRUPTED:
|
||||
prefix = "INTERRUPTED (";
|
||||
break;
|
||||
case FutureReturnCode::TIMEOUT:
|
||||
prefix = "TIMEOUT (";
|
||||
break;
|
||||
}
|
||||
return prefix + ret_as_string + ")";
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
@@ -46,6 +46,19 @@ InitOptions::InitOptions(const InitOptions & other)
|
||||
shutdown_on_sigint = other.shutdown_on_sigint;
|
||||
}
|
||||
|
||||
bool
|
||||
InitOptions::auto_initialize_logging() const
|
||||
{
|
||||
return initialize_logging_;
|
||||
}
|
||||
|
||||
InitOptions &
|
||||
InitOptions::auto_initialize_logging(bool initialize_logging)
|
||||
{
|
||||
initialize_logging_ = initialize_logging;
|
||||
return *this;
|
||||
}
|
||||
|
||||
InitOptions &
|
||||
InitOptions::operator=(const InitOptions & other)
|
||||
{
|
||||
|
||||
@@ -127,7 +127,7 @@ MemoryStrategy::get_timer_by_handle(
|
||||
|
||||
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr
|
||||
MemoryStrategy::get_node_by_group(
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group,
|
||||
rclcpp::CallbackGroup::SharedPtr group,
|
||||
const WeakNodeList & weak_nodes)
|
||||
{
|
||||
if (!group) {
|
||||
@@ -148,7 +148,7 @@ MemoryStrategy::get_node_by_group(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
const WeakNodeList & weak_nodes)
|
||||
@@ -175,7 +175,7 @@ MemoryStrategy::get_group_by_subscription(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_service(
|
||||
rclcpp::ServiceBase::SharedPtr service,
|
||||
const WeakNodeList & weak_nodes)
|
||||
@@ -202,7 +202,7 @@ MemoryStrategy::get_group_by_service(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_client(
|
||||
rclcpp::ClientBase::SharedPtr client,
|
||||
const WeakNodeList & weak_nodes)
|
||||
@@ -229,7 +229,7 @@ MemoryStrategy::get_group_by_client(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_timer(
|
||||
rclcpp::TimerBase::SharedPtr timer,
|
||||
const WeakNodeList & weak_nodes)
|
||||
@@ -256,7 +256,7 @@ MemoryStrategy::get_group_by_timer(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
MemoryStrategy::get_group_by_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable,
|
||||
const WeakNodeList & weak_nodes)
|
||||
|
||||
@@ -108,7 +108,7 @@ Node::Node(
|
||||
node_graph_(new rclcpp::node_interfaces::NodeGraph(node_base_.get())),
|
||||
node_logging_(new rclcpp::node_interfaces::NodeLogging(node_base_.get())),
|
||||
node_timers_(new rclcpp::node_interfaces::NodeTimers(node_base_.get())),
|
||||
node_topics_(new rclcpp::node_interfaces::NodeTopics(node_base_.get())),
|
||||
node_topics_(new rclcpp::node_interfaces::NodeTopics(node_base_.get(), node_timers_.get())),
|
||||
node_services_(new rclcpp::node_interfaces::NodeServices(node_base_.get())),
|
||||
node_clock_(new rclcpp::node_interfaces::NodeClock(
|
||||
node_base_,
|
||||
@@ -210,15 +210,14 @@ Node::get_logger() const
|
||||
return node_logging_->get_logger();
|
||||
}
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
Node::create_callback_group(
|
||||
rclcpp::callback_group::CallbackGroupType group_type)
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
Node::create_callback_group(rclcpp::CallbackGroupType group_type)
|
||||
{
|
||||
return node_base_->create_callback_group(group_type);
|
||||
}
|
||||
|
||||
bool
|
||||
Node::group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
Node::group_in_node(rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
return node_base_->callback_group_in_node(group);
|
||||
}
|
||||
@@ -377,7 +376,7 @@ Node::get_subscriptions_info_by_topic(const std::string & topic_name, bool no_ma
|
||||
return node_graph_->get_subscriptions_info_by_topic(topic_name, no_mangle);
|
||||
}
|
||||
|
||||
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
|
||||
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
|
||||
Node::get_callback_groups() const
|
||||
{
|
||||
return node_base_->get_callback_groups();
|
||||
|
||||
@@ -133,7 +133,7 @@ NodeBase::NodeBase(
|
||||
});
|
||||
|
||||
// Create the default callback group.
|
||||
using rclcpp::callback_group::CallbackGroupType;
|
||||
using rclcpp::CallbackGroupType;
|
||||
default_callback_group_ = create_callback_group(CallbackGroupType::MutuallyExclusive);
|
||||
|
||||
// Indicate the notify_guard_condition is now valid.
|
||||
@@ -208,24 +208,24 @@ NodeBase::assert_liveliness() const
|
||||
return RCL_RET_OK == rcl_node_assert_liveliness(get_rcl_node_handle());
|
||||
}
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
NodeBase::create_callback_group(rclcpp::callback_group::CallbackGroupType group_type)
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
NodeBase::create_callback_group(rclcpp::CallbackGroupType group_type)
|
||||
{
|
||||
using rclcpp::callback_group::CallbackGroup;
|
||||
using rclcpp::callback_group::CallbackGroupType;
|
||||
using rclcpp::CallbackGroup;
|
||||
using rclcpp::CallbackGroupType;
|
||||
auto group = CallbackGroup::SharedPtr(new CallbackGroup(group_type));
|
||||
callback_groups_.push_back(group);
|
||||
return group;
|
||||
}
|
||||
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr
|
||||
rclcpp::CallbackGroup::SharedPtr
|
||||
NodeBase::get_default_callback_group()
|
||||
{
|
||||
return default_callback_group_;
|
||||
}
|
||||
|
||||
bool
|
||||
NodeBase::callback_group_in_node(rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
NodeBase::callback_group_in_node(rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
bool group_belongs_to_this_node = false;
|
||||
for (auto & weak_group : this->callback_groups_) {
|
||||
@@ -237,7 +237,7 @@ NodeBase::callback_group_in_node(rclcpp::callback_group::CallbackGroup::SharedPt
|
||||
return group_belongs_to_this_node;
|
||||
}
|
||||
|
||||
const std::vector<rclcpp::callback_group::CallbackGroup::WeakPtr> &
|
||||
const std::vector<rclcpp::CallbackGroup::WeakPtr> &
|
||||
NodeBase::get_callback_groups() const
|
||||
{
|
||||
return callback_groups_;
|
||||
|
||||
@@ -107,11 +107,14 @@ NodeParameters::NodeParameters(
|
||||
rcl_yaml_node_struct_fini(params);
|
||||
});
|
||||
rclcpp::ParameterMap initial_map = rclcpp::parameter_map_from(params);
|
||||
for (auto iter = initial_map.begin(); initial_map.end() != iter; iter++) {
|
||||
// TODO(cottsay) implement further wildcard matching
|
||||
if (iter->first == "/**" || iter->first == combined_name_) {
|
||||
|
||||
// Enforce wildcard matching precedence
|
||||
// TODO(cottsay) implement further wildcard matching
|
||||
const std::vector<std::string> node_matching_names{"/**", combined_name_};
|
||||
for (const auto & node_name : node_matching_names) {
|
||||
if (initial_map.count(node_name) > 0) {
|
||||
// Combine parameter yaml files, overwriting values in older ones
|
||||
for (auto & param : iter->second) {
|
||||
for (const rclcpp::Parameter & param : initial_map.at(node_name)) {
|
||||
parameter_overrides_[param.get_name()] =
|
||||
rclcpp::ParameterValue(param.get_value_message());
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ NodeServices::~NodeServices()
|
||||
void
|
||||
NodeServices::add_service(
|
||||
rclcpp::ServiceBase::SharedPtr service_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
if (group) {
|
||||
if (!node_base_->callback_group_in_node(group)) {
|
||||
@@ -55,7 +55,7 @@ NodeServices::add_service(
|
||||
void
|
||||
NodeServices::add_client(
|
||||
rclcpp::ClientBase::SharedPtr client_base_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
if (group) {
|
||||
if (!node_base_->callback_group_in_node(group)) {
|
||||
|
||||
@@ -28,7 +28,7 @@ NodeTimers::~NodeTimers()
|
||||
void
|
||||
NodeTimers::add_timer(
|
||||
rclcpp::TimerBase::SharedPtr timer,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group)
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group)
|
||||
{
|
||||
if (callback_group) {
|
||||
if (!node_base_->callback_group_in_node(callback_group)) {
|
||||
|
||||
@@ -22,8 +22,10 @@ using rclcpp::exceptions::throw_from_rcl_error;
|
||||
|
||||
using rclcpp::node_interfaces::NodeTopics;
|
||||
|
||||
NodeTopics::NodeTopics(rclcpp::node_interfaces::NodeBaseInterface * node_base)
|
||||
: node_base_(node_base)
|
||||
NodeTopics::NodeTopics(
|
||||
rclcpp::node_interfaces::NodeBaseInterface * node_base,
|
||||
rclcpp::node_interfaces::NodeTimersInterface * node_timers)
|
||||
: node_base_(node_base), node_timers_(node_timers)
|
||||
{}
|
||||
|
||||
NodeTopics::~NodeTopics()
|
||||
@@ -42,7 +44,7 @@ NodeTopics::create_publisher(
|
||||
void
|
||||
NodeTopics::add_publisher(
|
||||
rclcpp::PublisherBase::SharedPtr publisher,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group)
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group)
|
||||
{
|
||||
// Assign to a group.
|
||||
if (callback_group) {
|
||||
@@ -81,7 +83,7 @@ NodeTopics::create_subscription(
|
||||
void
|
||||
NodeTopics::add_subscription(
|
||||
rclcpp::SubscriptionBase::SharedPtr subscription,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr callback_group)
|
||||
rclcpp::CallbackGroup::SharedPtr callback_group)
|
||||
{
|
||||
// Assign to a group.
|
||||
if (callback_group) {
|
||||
@@ -121,3 +123,9 @@ NodeTopics::get_node_base_interface() const
|
||||
{
|
||||
return node_base_;
|
||||
}
|
||||
|
||||
rclcpp::node_interfaces::NodeTimersInterface *
|
||||
NodeTopics::get_node_timers_interface() const
|
||||
{
|
||||
return node_timers_;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ NodeWaitables::~NodeWaitables()
|
||||
void
|
||||
NodeWaitables::add_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
{
|
||||
if (group) {
|
||||
if (!node_base_->callback_group_in_node(group)) {
|
||||
@@ -55,7 +55,7 @@ NodeWaitables::add_waitable(
|
||||
void
|
||||
NodeWaitables::remove_waitable(
|
||||
rclcpp::Waitable::SharedPtr waitable_ptr,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group) noexcept
|
||||
rclcpp::CallbackGroup::SharedPtr group) noexcept
|
||||
{
|
||||
if (group) {
|
||||
if (!node_base_->callback_group_in_node(group)) {
|
||||
|
||||
@@ -31,7 +31,7 @@ AsyncParametersClient::AsyncParametersClient(
|
||||
const rclcpp::node_interfaces::NodeServicesInterface::SharedPtr node_services_interface,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
: node_topics_interface_(node_topics_interface)
|
||||
{
|
||||
if (remote_node_name != "") {
|
||||
@@ -103,7 +103,7 @@ AsyncParametersClient::AsyncParametersClient(
|
||||
const rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
: AsyncParametersClient(
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
@@ -118,7 +118,7 @@ AsyncParametersClient::AsyncParametersClient(
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile,
|
||||
rclcpp::callback_group::CallbackGroup::SharedPtr group)
|
||||
rclcpp::CallbackGroup::SharedPtr group)
|
||||
: AsyncParametersClient(
|
||||
node->get_node_base_interface(),
|
||||
node->get_node_topics_interface(),
|
||||
@@ -349,7 +349,7 @@ SyncParametersClient::SyncParametersClient(
|
||||
{}
|
||||
|
||||
SyncParametersClient::SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
rclcpp::Node::SharedPtr node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
@@ -375,7 +375,7 @@ SyncParametersClient::SyncParametersClient(
|
||||
{}
|
||||
|
||||
SyncParametersClient::SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
rclcpp::Node * node,
|
||||
const std::string & remote_node_name,
|
||||
const rmw_qos_profile_t & qos_profile)
|
||||
@@ -390,7 +390,7 @@ SyncParametersClient::SyncParametersClient(
|
||||
{}
|
||||
|
||||
SyncParametersClient::SyncParametersClient(
|
||||
rclcpp::executor::Executor::SharedPtr executor,
|
||||
rclcpp::Executor::SharedPtr executor,
|
||||
const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface,
|
||||
const rclcpp::node_interfaces::NodeTopicsInterface::SharedPtr node_topics_interface,
|
||||
const rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph_interface,
|
||||
@@ -417,7 +417,7 @@ SyncParametersClient::get_parameters(const std::vector<std::string> & parameter_
|
||||
if (
|
||||
spin_node_until_future_complete(
|
||||
*executor_, node_base_interface_,
|
||||
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
|
||||
f) == rclcpp::FutureReturnCode::SUCCESS)
|
||||
{
|
||||
return f.get();
|
||||
}
|
||||
@@ -443,7 +443,7 @@ SyncParametersClient::get_parameter_types(const std::vector<std::string> & param
|
||||
if (
|
||||
spin_node_until_future_complete(
|
||||
*executor_, node_base_interface_,
|
||||
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
|
||||
f) == rclcpp::FutureReturnCode::SUCCESS)
|
||||
{
|
||||
return f.get();
|
||||
}
|
||||
@@ -460,7 +460,7 @@ SyncParametersClient::set_parameters(
|
||||
if (
|
||||
spin_node_until_future_complete(
|
||||
*executor_, node_base_interface_,
|
||||
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
|
||||
f) == rclcpp::FutureReturnCode::SUCCESS)
|
||||
{
|
||||
return f.get();
|
||||
}
|
||||
@@ -477,7 +477,7 @@ SyncParametersClient::set_parameters_atomically(
|
||||
if (
|
||||
spin_node_until_future_complete(
|
||||
*executor_, node_base_interface_,
|
||||
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
|
||||
f) == rclcpp::FutureReturnCode::SUCCESS)
|
||||
{
|
||||
return f.get();
|
||||
}
|
||||
@@ -496,7 +496,7 @@ SyncParametersClient::list_parameters(
|
||||
if (
|
||||
spin_node_until_future_complete(
|
||||
*executor_, node_base_interface_,
|
||||
f) == rclcpp::executor::FutureReturnCode::SUCCESS)
|
||||
f) == rclcpp::FutureReturnCode::SUCCESS)
|
||||
{
|
||||
return f.get();
|
||||
}
|
||||
|
||||
72
rclcpp/src/rclcpp/serialization.cpp
Normal file
72
rclcpp/src/rclcpp/serialization.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright 2020 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "rclcpp/serialization.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
|
||||
#include "rcpputils/asserts.hpp"
|
||||
|
||||
#include "rmw/rmw.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
SerializationBase::SerializationBase(const rosidl_message_type_support_t * type_support)
|
||||
: type_support_(type_support)
|
||||
{
|
||||
rcpputils::check_true(nullptr != type_support, "Typesupport is nullpointer.");
|
||||
}
|
||||
|
||||
void SerializationBase::serialize_message(
|
||||
const void * ros_message, SerializedMessage * serialized_message) const
|
||||
{
|
||||
rcpputils::check_true(nullptr != type_support_, "Typesupport is nullpointer.");
|
||||
rcpputils::check_true(nullptr != ros_message, "ROS message is nullpointer.");
|
||||
rcpputils::check_true(nullptr != serialized_message, "Serialized message is nullpointer.");
|
||||
|
||||
const auto ret = rmw_serialize(
|
||||
ros_message,
|
||||
type_support_,
|
||||
&serialized_message->get_rcl_serialized_message());
|
||||
if (ret != RMW_RET_OK) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "Failed to serialize ROS message.");
|
||||
}
|
||||
}
|
||||
|
||||
void SerializationBase::deserialize_message(
|
||||
const SerializedMessage * serialized_message, void * ros_message) const
|
||||
{
|
||||
rcpputils::check_true(nullptr != type_support_, "Typesupport is nullpointer.");
|
||||
rcpputils::check_true(nullptr != serialized_message, "Serialized message is nullpointer.");
|
||||
rcpputils::check_true(
|
||||
0u != serialized_message->capacity(),
|
||||
"Wrongly initialized. Serialized message has a capacity of zero.");
|
||||
rcpputils::check_true(
|
||||
0u != serialized_message->size(),
|
||||
"Wrongly initialized. Serialized message has a size of zero.");
|
||||
rcpputils::check_true(nullptr != ros_message, "ROS message is a nullpointer.");
|
||||
|
||||
const auto ret = rmw_deserialize(
|
||||
&serialized_message->get_rcl_serialized_message(), type_support_, ros_message);
|
||||
if (ret != RMW_RET_OK) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "Failed to deserialize ROS message.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
164
rclcpp/src/rclcpp/serialized_message.cpp
Normal file
164
rclcpp/src/rclcpp/serialized_message.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
// Copyright 2020 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
|
||||
#include "rmw/types.h"
|
||||
|
||||
namespace rclcpp
|
||||
{
|
||||
|
||||
inline void copy_rcl_message(const rcl_serialized_message_t & from, rcl_serialized_message_t & to)
|
||||
{
|
||||
const auto ret = rmw_serialized_message_init(
|
||||
&to, from.buffer_capacity, &from.allocator);
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
|
||||
// do not call memcpy if the pointer is "static"
|
||||
if (to.buffer != from.buffer) {
|
||||
std::memcpy(to.buffer, from.buffer, from.buffer_length);
|
||||
}
|
||||
to.buffer_length = from.buffer_length;
|
||||
}
|
||||
|
||||
/// Object oriented version of rcl_serialized_message_t with destructor to avoid memory leaks
|
||||
SerializedMessage::SerializedMessage(const rcl_allocator_t & allocator)
|
||||
: SerializedMessage(0u, allocator)
|
||||
{}
|
||||
|
||||
SerializedMessage::SerializedMessage(
|
||||
size_t initial_capacity, const rcl_allocator_t & allocator)
|
||||
: serialized_message_(rmw_get_zero_initialized_serialized_message())
|
||||
{
|
||||
const auto ret = rmw_serialized_message_init(
|
||||
&serialized_message_, initial_capacity, &allocator);
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
}
|
||||
|
||||
SerializedMessage::SerializedMessage(const SerializedMessage & other)
|
||||
: SerializedMessage(other.serialized_message_)
|
||||
{}
|
||||
|
||||
SerializedMessage::SerializedMessage(const rcl_serialized_message_t & other)
|
||||
: serialized_message_(rmw_get_zero_initialized_serialized_message())
|
||||
{
|
||||
copy_rcl_message(other, serialized_message_);
|
||||
}
|
||||
|
||||
SerializedMessage::SerializedMessage(SerializedMessage && other)
|
||||
: serialized_message_(
|
||||
std::exchange(other.serialized_message_, rmw_get_zero_initialized_serialized_message()))
|
||||
{}
|
||||
|
||||
SerializedMessage::SerializedMessage(rcl_serialized_message_t && other)
|
||||
: serialized_message_(
|
||||
std::exchange(other, rmw_get_zero_initialized_serialized_message()))
|
||||
{}
|
||||
|
||||
SerializedMessage & SerializedMessage::operator=(const SerializedMessage & other)
|
||||
{
|
||||
if (this != &other) {
|
||||
serialized_message_ = rmw_get_zero_initialized_serialized_message();
|
||||
copy_rcl_message(other.serialized_message_, serialized_message_);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SerializedMessage & SerializedMessage::operator=(const rcl_serialized_message_t & other)
|
||||
{
|
||||
if (&serialized_message_ != &other) {
|
||||
serialized_message_ = rmw_get_zero_initialized_serialized_message();
|
||||
copy_rcl_message(other, serialized_message_);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SerializedMessage & SerializedMessage::operator=(SerializedMessage && other)
|
||||
{
|
||||
if (this != &other) {
|
||||
serialized_message_ =
|
||||
std::exchange(other.serialized_message_, rmw_get_zero_initialized_serialized_message());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SerializedMessage & SerializedMessage::operator=(rcl_serialized_message_t && other)
|
||||
{
|
||||
if (&serialized_message_ != &other) {
|
||||
serialized_message_ =
|
||||
std::exchange(other, rmw_get_zero_initialized_serialized_message());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SerializedMessage::~SerializedMessage()
|
||||
{
|
||||
if (nullptr != serialized_message_.buffer) {
|
||||
const auto fini_ret = rmw_serialized_message_fini(&serialized_message_);
|
||||
if (RCL_RET_OK != fini_ret) {
|
||||
RCLCPP_ERROR(
|
||||
get_logger("rclcpp"),
|
||||
"Failed to destroy serialized message: %s", rcl_get_error_string().str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rcl_serialized_message_t & SerializedMessage::get_rcl_serialized_message()
|
||||
{
|
||||
return serialized_message_;
|
||||
}
|
||||
|
||||
const rcl_serialized_message_t & SerializedMessage::get_rcl_serialized_message() const
|
||||
{
|
||||
return serialized_message_;
|
||||
}
|
||||
|
||||
size_t SerializedMessage::size() const
|
||||
{
|
||||
return serialized_message_.buffer_length;
|
||||
}
|
||||
|
||||
size_t SerializedMessage::capacity() const
|
||||
{
|
||||
return serialized_message_.buffer_capacity;
|
||||
}
|
||||
|
||||
void SerializedMessage::reserve(size_t capacity)
|
||||
{
|
||||
auto ret = rmw_serialized_message_resize(&serialized_message_, capacity);
|
||||
if (RCL_RET_OK != ret) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret);
|
||||
}
|
||||
}
|
||||
|
||||
rcl_serialized_message_t SerializedMessage::release_rcl_serialized_message()
|
||||
{
|
||||
auto ret = serialized_message_;
|
||||
serialized_message_ = rmw_get_zero_initialized_serialized_message();
|
||||
|
||||
return ret;
|
||||
}
|
||||
} // namespace rclcpp
|
||||
@@ -159,12 +159,12 @@ SubscriptionBase::take_type_erased(void * message_out, rclcpp::MessageInfo & mes
|
||||
|
||||
bool
|
||||
SubscriptionBase::take_serialized(
|
||||
rcl_serialized_message_t & message_out,
|
||||
rclcpp::SerializedMessage & message_out,
|
||||
rclcpp::MessageInfo & message_info_out)
|
||||
{
|
||||
rcl_ret_t ret = rcl_take_serialized_message(
|
||||
this->get_subscription_handle().get(),
|
||||
&message_out,
|
||||
&message_out.get_rcl_serialized_message(),
|
||||
&message_info_out.get_rmw_message_info(),
|
||||
nullptr);
|
||||
if (RCL_RET_SUBSCRIPTION_TAKE_FAILED == ret) {
|
||||
|
||||
@@ -33,7 +33,7 @@ TimerBase::TimerBase(
|
||||
: clock_(clock), timer_handle_(nullptr)
|
||||
{
|
||||
if (nullptr == context) {
|
||||
context = rclcpp::contexts::default_context::get_global_default_context();
|
||||
context = rclcpp::contexts::get_global_default_context();
|
||||
}
|
||||
|
||||
auto rcl_context = context->get_rcl_context();
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace rclcpp
|
||||
void
|
||||
init(int argc, char const * const argv[], const InitOptions & init_options)
|
||||
{
|
||||
using contexts::default_context::get_global_default_context;
|
||||
using rclcpp::contexts::get_global_default_context;
|
||||
get_global_default_context()->init(argc, argv, init_options);
|
||||
// Install the signal handlers.
|
||||
install_signal_handlers();
|
||||
@@ -125,7 +125,7 @@ remove_ros_arguments(int argc, char const * const argv[])
|
||||
bool
|
||||
ok(Context::SharedPtr context)
|
||||
{
|
||||
using contexts::default_context::get_global_default_context;
|
||||
using rclcpp::contexts::get_global_default_context;
|
||||
if (nullptr == context) {
|
||||
context = get_global_default_context();
|
||||
}
|
||||
@@ -141,7 +141,7 @@ is_initialized(Context::SharedPtr context)
|
||||
bool
|
||||
shutdown(Context::SharedPtr context, const std::string & reason)
|
||||
{
|
||||
using contexts::default_context::get_global_default_context;
|
||||
using rclcpp::contexts::get_global_default_context;
|
||||
auto default_context = get_global_default_context();
|
||||
if (nullptr == context) {
|
||||
context = default_context;
|
||||
@@ -156,7 +156,7 @@ shutdown(Context::SharedPtr context, const std::string & reason)
|
||||
void
|
||||
on_shutdown(std::function<void()> callback, Context::SharedPtr context)
|
||||
{
|
||||
using contexts::default_context::get_global_default_context;
|
||||
using rclcpp::contexts::get_global_default_context;
|
||||
if (nullptr == context) {
|
||||
context = get_global_default_context();
|
||||
}
|
||||
@@ -166,7 +166,7 @@ on_shutdown(std::function<void()> callback, Context::SharedPtr context)
|
||||
bool
|
||||
sleep_for(const std::chrono::nanoseconds & nanoseconds, Context::SharedPtr context)
|
||||
{
|
||||
using contexts::default_context::get_global_default_context;
|
||||
using rclcpp::contexts::get_global_default_context;
|
||||
if (nullptr == context) {
|
||||
context = get_global_default_context();
|
||||
}
|
||||
|
||||
@@ -51,14 +51,14 @@ TEST_F(TestMultiThreadedExecutor, timer_over_take) {
|
||||
bool yield_before_execute = true;
|
||||
|
||||
rclcpp::executors::MultiThreadedExecutor executor(
|
||||
rclcpp::executor::create_default_executor_arguments(), 2u, yield_before_execute);
|
||||
rclcpp::ExecutorOptions(), 2u, yield_before_execute);
|
||||
|
||||
ASSERT_GT(executor.get_number_of_threads(), 1u);
|
||||
|
||||
std::shared_ptr<rclcpp::Node> node =
|
||||
std::make_shared<rclcpp::Node>("test_multi_threaded_executor_timer_over_take");
|
||||
|
||||
auto cbg = node->create_callback_group(rclcpp::callback_group::CallbackGroupType::Reentrant);
|
||||
auto cbg = node->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
|
||||
|
||||
rclcpp::Clock system_clock(RCL_STEADY_TIME);
|
||||
std::mutex last_mutex;
|
||||
|
||||
3
rclcpp/test/msg/Header.msg
Normal file
3
rclcpp/test/msg/Header.msg
Normal file
@@ -0,0 +1,3 @@
|
||||
# Simple Header message with a timestamp field.
|
||||
|
||||
builtin_interfaces/Time stamp
|
||||
3
rclcpp/test/msg/MessageWithHeader.msg
Normal file
3
rclcpp/test/msg/MessageWithHeader.msg
Normal file
@@ -0,0 +1,3 @@
|
||||
# Message containing a simple Header field.
|
||||
|
||||
Header header
|
||||
@@ -47,22 +47,38 @@ protected:
|
||||
rclcpp::Node::SharedPtr TestGetNodeInterfaces::node = nullptr;
|
||||
std::shared_ptr<NodeWrapper> TestGetNodeInterfaces::wrapped_node = nullptr;
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, null_rclcpp_node_shared_ptr) {
|
||||
rclcpp::Node::SharedPtr null_node;
|
||||
EXPECT_THROW(
|
||||
{
|
||||
rclcpp::node_interfaces::get_node_topics_interface(null_node);
|
||||
}, std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, rclcpp_node_shared_ptr) {
|
||||
auto result = rclcpp::node_interfaces::get_node_topics_interface(this->node);
|
||||
static_assert(
|
||||
std::is_same<
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||
decltype(result)
|
||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
||||
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, null_node_shared_ptr) {
|
||||
std::shared_ptr<NodeWrapper> null_node;
|
||||
EXPECT_THROW(
|
||||
{
|
||||
rclcpp::node_interfaces::get_node_topics_interface(null_node);
|
||||
}, std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, node_shared_ptr) {
|
||||
auto result = rclcpp::node_interfaces::get_node_topics_interface(this->wrapped_node);
|
||||
static_assert(
|
||||
std::is_same<
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||
decltype(result)
|
||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
||||
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, rclcpp_node_reference) {
|
||||
@@ -70,9 +86,9 @@ TEST_F(TestGetNodeInterfaces, rclcpp_node_reference) {
|
||||
auto result = rclcpp::node_interfaces::get_node_topics_interface(node_reference);
|
||||
static_assert(
|
||||
std::is_same<
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||
decltype(result)
|
||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
||||
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, node_reference) {
|
||||
@@ -80,9 +96,9 @@ TEST_F(TestGetNodeInterfaces, node_reference) {
|
||||
auto result = rclcpp::node_interfaces::get_node_topics_interface(wrapped_node_reference);
|
||||
static_assert(
|
||||
std::is_same<
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||
decltype(result)
|
||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
||||
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, rclcpp_node_pointer) {
|
||||
@@ -90,9 +106,17 @@ TEST_F(TestGetNodeInterfaces, rclcpp_node_pointer) {
|
||||
auto result = rclcpp::node_interfaces::get_node_topics_interface(node_pointer);
|
||||
static_assert(
|
||||
std::is_same<
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||
decltype(result)
|
||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
||||
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, null_rclcpp_node_pointer) {
|
||||
rclcpp::Node * null_node{nullptr};
|
||||
EXPECT_THROW(
|
||||
{
|
||||
rclcpp::node_interfaces::get_node_topics_interface(null_node);
|
||||
}, std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, node_pointer) {
|
||||
@@ -100,9 +124,17 @@ TEST_F(TestGetNodeInterfaces, node_pointer) {
|
||||
auto result = rclcpp::node_interfaces::get_node_topics_interface(wrapped_node_pointer);
|
||||
static_assert(
|
||||
std::is_same<
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||
decltype(result)
|
||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
||||
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, null_node_pointer) {
|
||||
NodeWrapper * null_node{nullptr};
|
||||
EXPECT_THROW(
|
||||
{
|
||||
rclcpp::node_interfaces::get_node_topics_interface(null_node);
|
||||
}, std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST_F(TestGetNodeInterfaces, interface_shared_pointer) {
|
||||
@@ -111,7 +143,7 @@ TEST_F(TestGetNodeInterfaces, interface_shared_pointer) {
|
||||
auto result = rclcpp::node_interfaces::get_node_topics_interface(interface_shared_ptr);
|
||||
static_assert(
|
||||
std::is_same<
|
||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||
decltype(result)
|
||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
||||
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
/**:
|
||||
ros__parameters:
|
||||
parameter_int: 21
|
||||
parameter_bool: true
|
||||
parameter_int: 42
|
||||
parameter_string_array: [baz, baz, baz]
|
||||
test_declare_parameter_node:
|
||||
ros__parameters:
|
||||
parameter_int: 21
|
||||
|
||||
78
rclcpp/test/test_interface_traits.cpp
Normal file
78
rclcpp/test/test_interface_traits.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/contexts/default_context.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base_interface_traits.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
|
||||
class MyNode
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface> get_node_base_interface() const
|
||||
{
|
||||
rclcpp::NodeOptions options;
|
||||
return std::make_shared<rclcpp::node_interfaces::NodeBase>(
|
||||
"my_node_name",
|
||||
"my_node_namespace",
|
||||
rclcpp::contexts::get_global_default_context(),
|
||||
*options.get_rcl_node_options(),
|
||||
options.use_intra_process_comms(),
|
||||
options.enable_topic_statistics());
|
||||
}
|
||||
};
|
||||
|
||||
class WrongNode
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface> not_get_node_base_interface()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, typename std::enable_if<
|
||||
rclcpp::node_interfaces::has_node_base_interface<T>::value
|
||||
>::type * = nullptr>
|
||||
void get_node_name(const T & nodelike)
|
||||
{
|
||||
ASSERT_STREQ("my_node_name", nodelike.get_node_base_interface()->get_name());
|
||||
}
|
||||
|
||||
class TestInterfaceTraits : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestInterfaceTraits, has_node_base_interface) {
|
||||
ASSERT_TRUE(rclcpp::node_interfaces::has_node_base_interface<MyNode>::value);
|
||||
ASSERT_FALSE(rclcpp::node_interfaces::has_node_base_interface<WrongNode>::value);
|
||||
ASSERT_TRUE(rclcpp::node_interfaces::has_node_base_interface<rclcpp::Node>::value);
|
||||
|
||||
get_node_name(MyNode());
|
||||
}
|
||||
@@ -691,7 +691,7 @@ TEST_F(TestNode, declare_parameter_with_cli_overrides) {
|
||||
no.arguments(
|
||||
{
|
||||
"--ros-args",
|
||||
"-p", "parameter_bool:=true",
|
||||
"-p", "parameter_bool:=false",
|
||||
"-p", "parameter_int:=42",
|
||||
"-p", "parameter_double:=0.42",
|
||||
"-p", "parameter_string:=foo",
|
||||
@@ -702,7 +702,8 @@ TEST_F(TestNode, declare_parameter_with_cli_overrides) {
|
||||
"-p", "parameter_string_array:=[foo, bar]"
|
||||
});
|
||||
|
||||
auto node = std::make_shared<rclcpp::Node>("test_declare_parameter_node"_unq, no);
|
||||
// To match parameters YAML file content, use a well-known node name for this test only.
|
||||
auto node = std::make_shared<rclcpp::Node>("test_declare_parameter_node", no);
|
||||
{
|
||||
rclcpp::ParameterValue value = node->declare_parameter("parameter_bool");
|
||||
EXPECT_EQ(value.get_type(), rclcpp::PARAMETER_BOOL);
|
||||
|
||||
208
rclcpp/test/test_serialized_message.cpp
Normal file
208
rclcpp/test/test_serialized_message.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
// Copyright 2020 Open Source Robotics Foundation, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/serialization.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
#include "rcpputils/asserts.hpp"
|
||||
|
||||
#include "test_msgs/message_fixtures.hpp"
|
||||
#include "test_msgs/msg/basic_types.hpp"
|
||||
|
||||
TEST(TestSerializedMessage, empty_initialize) {
|
||||
rclcpp::SerializedMessage serialized_message;
|
||||
EXPECT_EQ(0u, serialized_message.size());
|
||||
EXPECT_EQ(0u, serialized_message.capacity());
|
||||
}
|
||||
|
||||
TEST(TestSerializedMessage, initialize_with_capacity) {
|
||||
rclcpp::SerializedMessage serialized_message(13);
|
||||
EXPECT_EQ(0u, serialized_message.size());
|
||||
EXPECT_EQ(13u, serialized_message.capacity());
|
||||
}
|
||||
|
||||
TEST(TestSerializedMessage, various_constructors) {
|
||||
const std::string content = "Hello World";
|
||||
const auto content_size = content.size() + 1; // accounting for null terminator
|
||||
|
||||
rclcpp::SerializedMessage serialized_message(content_size);
|
||||
// manually copy some content
|
||||
auto & rcl_handle = serialized_message.get_rcl_serialized_message();
|
||||
std::memcpy(rcl_handle.buffer, content.c_str(), content.size());
|
||||
rcl_handle.buffer[content.size()] = '\0';
|
||||
rcl_handle.buffer_length = content_size;
|
||||
EXPECT_STREQ(content.c_str(), reinterpret_cast<char *>(rcl_handle.buffer));
|
||||
EXPECT_EQ(content_size, serialized_message.capacity());
|
||||
EXPECT_EQ(content_size, serialized_message.size());
|
||||
|
||||
// Copy Constructor
|
||||
rclcpp::SerializedMessage other_serialized_message(serialized_message);
|
||||
EXPECT_EQ(content_size, other_serialized_message.capacity());
|
||||
EXPECT_EQ(content_size, other_serialized_message.size());
|
||||
auto & other_rcl_handle = other_serialized_message.get_rcl_serialized_message();
|
||||
EXPECT_STREQ(
|
||||
reinterpret_cast<char *>(rcl_handle.buffer),
|
||||
reinterpret_cast<char *>(other_rcl_handle.buffer));
|
||||
|
||||
// Move Constructor
|
||||
rclcpp::SerializedMessage yet_another_serialized_message(std::move(other_serialized_message));
|
||||
auto & yet_another_rcl_handle = yet_another_serialized_message.get_rcl_serialized_message();
|
||||
EXPECT_TRUE(nullptr == other_rcl_handle.buffer);
|
||||
EXPECT_EQ(0u, other_serialized_message.capacity());
|
||||
EXPECT_EQ(0u, other_serialized_message.size());
|
||||
EXPECT_TRUE(nullptr != yet_another_rcl_handle.buffer);
|
||||
EXPECT_EQ(content_size, yet_another_serialized_message.size());
|
||||
EXPECT_EQ(content_size, yet_another_serialized_message.capacity());
|
||||
}
|
||||
|
||||
TEST(TestSerializedMessage, various_constructors_from_rcl) {
|
||||
const std::string content = "Hello World";
|
||||
const auto content_size = content.size() + 1; // accounting for null terminator
|
||||
|
||||
auto default_allocator = rcl_get_default_allocator();
|
||||
|
||||
auto rcl_serialized_msg = rmw_get_zero_initialized_serialized_message();
|
||||
auto ret = rmw_serialized_message_init(&rcl_serialized_msg, 13, &default_allocator);
|
||||
ASSERT_EQ(RCL_RET_OK, ret);
|
||||
// manually copy some content
|
||||
std::memcpy(rcl_serialized_msg.buffer, content.c_str(), content.size());
|
||||
rcl_serialized_msg.buffer[content.size()] = '\0';
|
||||
rcl_serialized_msg.buffer_length = content_size;
|
||||
EXPECT_EQ(13u, rcl_serialized_msg.buffer_capacity);
|
||||
|
||||
// Copy Constructor from rcl_serialized_message_t
|
||||
rclcpp::SerializedMessage serialized_message(rcl_serialized_msg);
|
||||
EXPECT_EQ(13u, serialized_message.capacity());
|
||||
EXPECT_EQ(content_size, serialized_message.size());
|
||||
|
||||
// Move Constructor from rcl_serialized_message_t
|
||||
rclcpp::SerializedMessage another_serialized_message(std::move(rcl_serialized_msg));
|
||||
EXPECT_TRUE(nullptr == rcl_serialized_msg.buffer);
|
||||
EXPECT_EQ(0u, rcl_serialized_msg.buffer_capacity);
|
||||
EXPECT_EQ(0u, rcl_serialized_msg.buffer_length);
|
||||
EXPECT_EQ(13u, another_serialized_message.capacity());
|
||||
EXPECT_EQ(content_size, another_serialized_message.size());
|
||||
|
||||
// Verify that despite being fini'd, the copy is real
|
||||
ret = rmw_serialized_message_fini(&rcl_serialized_msg);
|
||||
ASSERT_EQ(RCUTILS_RET_INVALID_ARGUMENT, ret); // Buffer is null, because it was moved
|
||||
EXPECT_EQ(nullptr, rcl_serialized_msg.buffer);
|
||||
EXPECT_EQ(0u, rcl_serialized_msg.buffer_capacity);
|
||||
EXPECT_EQ(0u, rcl_serialized_msg.buffer_length);
|
||||
EXPECT_EQ(13u, serialized_message.capacity());
|
||||
EXPECT_EQ(content_size, serialized_message.size());
|
||||
|
||||
auto rcl_handle = serialized_message.get_rcl_serialized_message();
|
||||
EXPECT_TRUE(nullptr != rcl_handle.buffer);
|
||||
}
|
||||
|
||||
TEST(TestSerializedMessage, release) {
|
||||
const std::string content = "Hello World";
|
||||
const auto content_size = content.size() + 1; // accounting for null terminator
|
||||
|
||||
rcl_serialized_message_t released_handle = rmw_get_zero_initialized_serialized_message();
|
||||
{
|
||||
rclcpp::SerializedMessage serialized_msg(13);
|
||||
// manually copy some content
|
||||
auto & rcl_serialized_msg = serialized_msg.get_rcl_serialized_message();
|
||||
std::memcpy(rcl_serialized_msg.buffer, content.c_str(), content.size());
|
||||
rcl_serialized_msg.buffer[content.size()] = '\0';
|
||||
rcl_serialized_msg.buffer_length = content_size;
|
||||
EXPECT_EQ(13u, serialized_msg.capacity());
|
||||
|
||||
released_handle = serialized_msg.release_rcl_serialized_message();
|
||||
// scope exit of serialized_msg
|
||||
}
|
||||
|
||||
EXPECT_TRUE(nullptr != released_handle.buffer);
|
||||
EXPECT_EQ(13u, released_handle.buffer_capacity);
|
||||
EXPECT_EQ(content_size, released_handle.buffer_length);
|
||||
// cleanup memory manually
|
||||
EXPECT_EQ(RCL_RET_OK, rmw_serialized_message_fini(&released_handle));
|
||||
}
|
||||
|
||||
TEST(TestSerializedMessage, serialization) {
|
||||
using MessageT = test_msgs::msg::BasicTypes;
|
||||
|
||||
rclcpp::Serialization<MessageT> serializer;
|
||||
|
||||
auto basic_type_ros_msgs = get_messages_basic_types();
|
||||
for (const auto & ros_msg : basic_type_ros_msgs) {
|
||||
// convert ros msg to serialized msg
|
||||
rclcpp::SerializedMessage serialized_msg;
|
||||
serializer.serialize_message(ros_msg.get(), &serialized_msg);
|
||||
|
||||
// convert serialized msg back to ros msg
|
||||
MessageT deserialized_ros_msg;
|
||||
serializer.deserialize_message(&serialized_msg, &deserialized_ros_msg);
|
||||
|
||||
EXPECT_EQ(*ros_msg, deserialized_ros_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void serialize_default_ros_msg()
|
||||
{
|
||||
using MessageT = test_msgs::msg::BasicTypes;
|
||||
rclcpp::Serialization<MessageT> serializer;
|
||||
MessageT ros_msg;
|
||||
rclcpp::SerializedMessage serialized_msg;
|
||||
|
||||
serializer.serialize_message(&ros_msg, &serialized_msg);
|
||||
}
|
||||
|
||||
void serialize_default_ros_msg_into_nullptr()
|
||||
{
|
||||
using MessageT = test_msgs::msg::BasicTypes;
|
||||
rclcpp::Serialization<MessageT> serializer;
|
||||
MessageT ros_msg;
|
||||
|
||||
serializer.serialize_message(&ros_msg, nullptr);
|
||||
}
|
||||
|
||||
void deserialize_default_serialized_message()
|
||||
{
|
||||
using MessageT = test_msgs::msg::BasicTypes;
|
||||
rclcpp::Serialization<MessageT> serializer;
|
||||
MessageT ros_msg;
|
||||
rclcpp::SerializedMessage serialized_msg;
|
||||
|
||||
serializer.deserialize_message(&serialized_msg, &ros_msg);
|
||||
}
|
||||
|
||||
void deserialize_nullptr()
|
||||
{
|
||||
using MessageT = test_msgs::msg::BasicTypes;
|
||||
rclcpp::Serialization<MessageT> serializer;
|
||||
MessageT ros_msg;
|
||||
rclcpp::SerializedMessage serialized_msg;
|
||||
|
||||
serializer.deserialize_message(&serialized_msg, &ros_msg);
|
||||
}
|
||||
|
||||
TEST(TestSerializedMessage, serialization_empty_messages)
|
||||
{
|
||||
EXPECT_NO_THROW(serialize_default_ros_msg());
|
||||
EXPECT_THROW(serialize_default_ros_msg_into_nullptr(), rcpputils::IllegalStateException);
|
||||
EXPECT_THROW(serialize_default_ros_msg_into_nullptr(), rcpputils::IllegalStateException);
|
||||
EXPECT_THROW(deserialize_default_serialized_message(), rcpputils::IllegalStateException);
|
||||
EXPECT_THROW(deserialize_nullptr(), rcpputils::IllegalStateException);
|
||||
}
|
||||
@@ -29,25 +29,25 @@ TEST(TestSerializedMessageAllocator, default_allocator) {
|
||||
rclcpp::message_memory_strategy::MessageMemoryStrategy<DummyMessageT>::create_default();
|
||||
|
||||
auto msg0 = mem_strategy->borrow_serialized_message();
|
||||
ASSERT_EQ(msg0->buffer_capacity, 0u);
|
||||
ASSERT_EQ(msg0->capacity(), 0u);
|
||||
mem_strategy->return_serialized_message(msg0);
|
||||
|
||||
auto msg100 = mem_strategy->borrow_serialized_message(100);
|
||||
ASSERT_EQ(msg100->buffer_capacity, 100u);
|
||||
ASSERT_EQ(msg100->capacity(), 100u);
|
||||
mem_strategy->return_serialized_message(msg100);
|
||||
|
||||
auto msg200 = mem_strategy->borrow_serialized_message();
|
||||
auto ret = rmw_serialized_message_resize(msg200.get(), 200);
|
||||
auto ret = rmw_serialized_message_resize(&msg200->get_rcl_serialized_message(), 200);
|
||||
ASSERT_EQ(RCL_RET_OK, ret);
|
||||
EXPECT_EQ(0u, msg200->buffer_length);
|
||||
EXPECT_EQ(200u, msg200->buffer_capacity);
|
||||
EXPECT_EQ(0u, msg200->size());
|
||||
EXPECT_EQ(200u, msg200->capacity());
|
||||
mem_strategy->return_serialized_message(msg200);
|
||||
|
||||
auto msg1000 = mem_strategy->borrow_serialized_message(1000);
|
||||
ASSERT_EQ(msg1000->buffer_capacity, 1000u);
|
||||
ret = rmw_serialized_message_resize(msg1000.get(), 2000);
|
||||
ASSERT_EQ(msg1000->capacity(), 1000u);
|
||||
ret = rmw_serialized_message_resize(&msg1000->get_rcl_serialized_message(), 2000);
|
||||
ASSERT_EQ(RCL_RET_OK, ret);
|
||||
EXPECT_EQ(2000u, msg1000->buffer_capacity);
|
||||
EXPECT_EQ(2000u, msg1000->capacity());
|
||||
mem_strategy->return_serialized_message(msg1000);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ TEST(TestSerializedMessageAllocator, borrow_from_subscription) {
|
||||
[](std::shared_ptr<test_msgs::msg::Empty> test_msg) {(void) test_msg;});
|
||||
|
||||
auto msg0 = sub->create_serialized_message();
|
||||
EXPECT_EQ(0u, msg0->buffer_capacity);
|
||||
EXPECT_EQ(0u, msg0->capacity());
|
||||
sub->return_serialized_message(msg0);
|
||||
|
||||
rclcpp::shutdown();
|
||||
|
||||
@@ -299,10 +299,10 @@ TEST_F(TestSubscription, take) {
|
||||
TEST_F(TestSubscription, take_serialized) {
|
||||
initialize();
|
||||
using test_msgs::msg::Empty;
|
||||
auto do_nothing = [](std::shared_ptr<const rcl_serialized_message_t>) {FAIL();};
|
||||
auto do_nothing = [](std::shared_ptr<const rclcpp::SerializedMessage>) {FAIL();};
|
||||
{
|
||||
auto sub = node->create_subscription<test_msgs::msg::Empty>("~/test_take", 1, do_nothing);
|
||||
std::shared_ptr<rcl_serialized_message_t> msg = sub->create_serialized_message();
|
||||
std::shared_ptr<rclcpp::SerializedMessage> msg = sub->create_serialized_message();
|
||||
rclcpp::MessageInfo msg_info;
|
||||
EXPECT_FALSE(sub->take_serialized(*msg, msg_info));
|
||||
}
|
||||
@@ -317,7 +317,7 @@ TEST_F(TestSubscription, take_serialized) {
|
||||
test_msgs::msg::Empty msg;
|
||||
pub->publish(msg);
|
||||
}
|
||||
std::shared_ptr<rcl_serialized_message_t> msg = sub->create_serialized_message();
|
||||
std::shared_ptr<rclcpp::SerializedMessage> msg = sub->create_serialized_message();
|
||||
rclcpp::MessageInfo msg_info;
|
||||
bool message_recieved = false;
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "rcl/types.h"
|
||||
|
||||
#include "rclcpp/allocator/allocator_common.hpp"
|
||||
#include "rclcpp/serialized_message.hpp"
|
||||
#include "rclcpp/subscription_traits.hpp"
|
||||
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
@@ -52,17 +53,27 @@ void not_serialized_unique_ptr_callback(
|
||||
(void) unused;
|
||||
}
|
||||
|
||||
void rclcpp_serialized_callback_copy(rclcpp::SerializedMessage unused)
|
||||
{
|
||||
(void) unused;
|
||||
}
|
||||
|
||||
void rclcpp_serialized_callback_shared_ptr(std::shared_ptr<rclcpp::SerializedMessage> unused)
|
||||
{
|
||||
(void) unused;
|
||||
}
|
||||
|
||||
TEST(TestSubscriptionTraits, is_serialized_callback) {
|
||||
// Test regular functions
|
||||
auto cb1 = &serialized_callback_copy;
|
||||
static_assert(
|
||||
rclcpp::subscription_traits::is_serialized_callback<decltype(cb1)>::value == true,
|
||||
"rcl_serialized_message_t in a first argument callback makes it a serialized callback");
|
||||
rclcpp::subscription_traits::is_serialized_callback<decltype(cb1)>::value == false,
|
||||
"passing a rcl_serialized_message_t * is not a serialized callback");
|
||||
|
||||
auto cb2 = &serialized_callback_shared_ptr;
|
||||
static_assert(
|
||||
rclcpp::subscription_traits::is_serialized_callback<decltype(cb2)>::value == true,
|
||||
"std::shared_ptr<rcl_serialized_message_t> in a callback makes it a serialized callback");
|
||||
rclcpp::subscription_traits::is_serialized_callback<decltype(cb2)>::value == false,
|
||||
"passing a std::shared_ptr<rcl_serialized_message_t> is not a serialized callback");
|
||||
|
||||
auto cb3 = ¬_serialized_callback;
|
||||
static_assert(
|
||||
@@ -79,8 +90,8 @@ TEST(TestSubscriptionTraits, is_serialized_callback) {
|
||||
(void) unused;
|
||||
};
|
||||
static_assert(
|
||||
rclcpp::subscription_traits::is_serialized_callback<decltype(cb5)>::value == true,
|
||||
"rcl_serialized_message_t in a first argument callback makes it a serialized callback");
|
||||
rclcpp::subscription_traits::is_serialized_callback<decltype(cb5)>::value == false,
|
||||
"passing rcl_serialized_message_t is not a serialized callback");
|
||||
|
||||
using MessageT = test_msgs::msg::Empty;
|
||||
using MessageTAllocator = std::allocator<void>;
|
||||
@@ -97,6 +108,16 @@ TEST(TestSubscriptionTraits, is_serialized_callback) {
|
||||
static_assert(
|
||||
rclcpp::subscription_traits::is_serialized_callback<decltype(cb7)>::value == false,
|
||||
"passing a fancy unique_ptr of test_msgs::msg::Empty is not a serialized callback");
|
||||
|
||||
auto cb8 = &rclcpp_serialized_callback_copy;
|
||||
static_assert(
|
||||
rclcpp::subscription_traits::is_serialized_callback<decltype(cb8)>::value == true,
|
||||
"rclcpp::SerializedMessage in a first argument callback makes it a serialized callback");
|
||||
|
||||
auto cb9 = &rclcpp_serialized_callback_shared_ptr;
|
||||
static_assert(
|
||||
rclcpp::subscription_traits::is_serialized_callback<decltype(cb9)>::value == true,
|
||||
"std::shared_ptr<rclcpp::SerializedMessage> in a callback makes it a serialized callback");
|
||||
}
|
||||
|
||||
TEST(TestSubscriptionTraits, callback_messages) {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
@@ -45,6 +46,10 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestTime, force_segfault) {
|
||||
raise(SIGSEGV);
|
||||
}
|
||||
|
||||
TEST(TestTime, clock_type_access) {
|
||||
rclcpp::Clock ros_clock(RCL_ROS_TIME);
|
||||
EXPECT_EQ(RCL_ROS_TIME, ros_clock.get_clock_type());
|
||||
|
||||
@@ -52,8 +52,8 @@ TEST(TestUtilities, init_with_args) {
|
||||
}
|
||||
|
||||
TEST(TestUtilities, multi_init) {
|
||||
auto context1 = std::make_shared<rclcpp::contexts::default_context::DefaultContext>();
|
||||
auto context2 = std::make_shared<rclcpp::contexts::default_context::DefaultContext>();
|
||||
auto context1 = std::make_shared<rclcpp::contexts::DefaultContext>();
|
||||
auto context2 = std::make_shared<rclcpp::contexts::DefaultContext>();
|
||||
|
||||
EXPECT_FALSE(rclcpp::ok(context1));
|
||||
EXPECT_FALSE(rclcpp::ok(context2));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user