Generate node interfaces' getters and traits. (#1069)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com> Co-authored-by: Karsten Knese <karsten@openrobotics.org>
This commit is contained in:
parent
c9319dafc2
commit
bb8c8ff2c0
9 changed files with 340 additions and 466 deletions
|
@ -101,19 +101,65 @@ configure_file(
|
||||||
COPYONLY
|
COPYONLY
|
||||||
)
|
)
|
||||||
# generate header with logging macros
|
# generate header with logging macros
|
||||||
set(python_code
|
set(python_code_logging
|
||||||
"import em"
|
"import em"
|
||||||
"em.invoke(['-o', 'include/rclcpp/logging.hpp', '${CMAKE_CURRENT_SOURCE_DIR}/resource/logging.hpp.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
|
add_custom_command(OUTPUT include/rclcpp/logging.hpp
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp"
|
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"
|
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/logging.hpp.em.watch"
|
||||||
COMMENT "Expanding logging.hpp.em"
|
COMMENT "Expanding logging.hpp.em"
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
list(APPEND ${PROJECT_NAME}_SRCS
|
list(APPEND ${PROJECT_NAME}_SRCS
|
||||||
include/rclcpp/logging.hpp)
|
include/rclcpp/logging.hpp)
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}/include")
|
include_directories("${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||||
|
|
||||||
add_library(${PROJECT_NAME}
|
add_library(${PROJECT_NAME}
|
||||||
|
@ -532,6 +578,14 @@ if(BUILD_TESTING)
|
||||||
target_link_libraries(test_init ${PROJECT_NAME})
|
target_link_libraries(test_init ${PROJECT_NAME})
|
||||||
endif()
|
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
|
ament_add_gtest(test_multi_threaded_executor test/executors/test_multi_threaded_executor.cpp
|
||||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||||
if(TARGET test_multi_threaded_executor)
|
if(TARGET test_multi_threaded_executor)
|
||||||
|
|
|
@ -32,8 +32,8 @@ namespace rclcpp
|
||||||
template<typename CallbackT>
|
template<typename CallbackT>
|
||||||
typename rclcpp::TimerBase::SharedPtr
|
typename rclcpp::TimerBase::SharedPtr
|
||||||
create_timer(
|
create_timer(
|
||||||
node_interfaces::NodeBaseInterface * node_base,
|
std::shared_ptr<node_interfaces::NodeBaseInterface> node_base,
|
||||||
node_interfaces::NodeTimersInterface * node_timers,
|
std::shared_ptr<node_interfaces::NodeTimersInterface> node_timers,
|
||||||
rclcpp::Clock::SharedPtr clock,
|
rclcpp::Clock::SharedPtr clock,
|
||||||
rclcpp::Duration period,
|
rclcpp::Duration period,
|
||||||
CallbackT && callback,
|
CallbackT && callback,
|
||||||
|
|
|
@ -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_
|
|
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_
|
|
@ -47,22 +47,38 @@ protected:
|
||||||
rclcpp::Node::SharedPtr TestGetNodeInterfaces::node = nullptr;
|
rclcpp::Node::SharedPtr TestGetNodeInterfaces::node = nullptr;
|
||||||
std::shared_ptr<NodeWrapper> TestGetNodeInterfaces::wrapped_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) {
|
TEST_F(TestGetNodeInterfaces, rclcpp_node_shared_ptr) {
|
||||||
auto result = rclcpp::node_interfaces::get_node_topics_interface(this->node);
|
auto result = rclcpp::node_interfaces::get_node_topics_interface(this->node);
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_same<
|
std::is_same<
|
||||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||||
decltype(result)
|
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) {
|
TEST_F(TestGetNodeInterfaces, node_shared_ptr) {
|
||||||
auto result = rclcpp::node_interfaces::get_node_topics_interface(this->wrapped_node);
|
auto result = rclcpp::node_interfaces::get_node_topics_interface(this->wrapped_node);
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_same<
|
std::is_same<
|
||||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||||
decltype(result)
|
decltype(result)
|
||||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestGetNodeInterfaces, rclcpp_node_reference) {
|
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);
|
auto result = rclcpp::node_interfaces::get_node_topics_interface(node_reference);
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_same<
|
std::is_same<
|
||||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||||
decltype(result)
|
decltype(result)
|
||||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestGetNodeInterfaces, node_reference) {
|
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);
|
auto result = rclcpp::node_interfaces::get_node_topics_interface(wrapped_node_reference);
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_same<
|
std::is_same<
|
||||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||||
decltype(result)
|
decltype(result)
|
||||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestGetNodeInterfaces, rclcpp_node_pointer) {
|
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);
|
auto result = rclcpp::node_interfaces::get_node_topics_interface(node_pointer);
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_same<
|
std::is_same<
|
||||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||||
decltype(result)
|
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) {
|
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);
|
auto result = rclcpp::node_interfaces::get_node_topics_interface(wrapped_node_pointer);
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_same<
|
std::is_same<
|
||||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||||
decltype(result)
|
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) {
|
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);
|
auto result = rclcpp::node_interfaces::get_node_topics_interface(interface_shared_ptr);
|
||||||
static_assert(
|
static_assert(
|
||||||
std::is_same<
|
std::is_same<
|
||||||
rclcpp::node_interfaces::NodeTopicsInterface *,
|
std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>,
|
||||||
decltype(result)
|
decltype(result)
|
||||||
>::value, "expected rclcpp::node_interfaces::NodeTopicsInterface *");
|
>::value, "expected std::shared_ptr<rclcpp::node_interfaces::NodeTopicsInterface>");
|
||||||
}
|
}
|
||||||
|
|
77
rclcpp/test/test_interface_traits.cpp
Normal file
77
rclcpp/test/test_interface_traits.cpp
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
// 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::default_context::get_global_default_context(),
|
||||||
|
*options.get_rcl_node_options(),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue