From 0682ceb3e136938c0245e4a91a31e2aea7331c8e Mon Sep 17 00:00:00 2001 From: Alberto Soragna Date: Thu, 16 May 2019 21:45:10 +0100 Subject: [PATCH] Created `on_parameter_event` static function (#688) * created static functions Signed-off-by: alsora Signed-off-by: alberto soragna * updated on_parameter_event to new subscriber api Signed-off-by: alberto soragna * Update parameter_client.hpp Reorderd typenames in template Signed-off-by: alberto soragna * updated API also for Synchronous client and fixed linter errors Signed-off-by: alberto soragna * added empty line at the end of files Signed-off-by: alberto soragna * fixed linter error Signed-off-by: alsora * added parameter client tests Signed-off-by: alsora * added missing includes in unit test Signed-off-by: alsora --- rclcpp/CMakeLists.txt | 7 + rclcpp/include/rclcpp/parameter_client.hpp | 50 ++++++- rclcpp/src/rclcpp/time_source.cpp | 10 +- rclcpp/test/test_parameter_client.cpp | 155 +++++++++++++++++++++ 4 files changed, 212 insertions(+), 10 deletions(-) create mode 100644 rclcpp/test/test_parameter_client.cpp diff --git a/rclcpp/CMakeLists.txt b/rclcpp/CMakeLists.txt index f2ee5e6..c218494 100644 --- a/rclcpp/CMakeLists.txt +++ b/rclcpp/CMakeLists.txt @@ -242,6 +242,13 @@ if(BUILD_TESTING) ) target_link_libraries(test_node_global_args ${PROJECT_NAME}) endif() + ament_add_gtest(test_parameter_client test/test_parameter_client.cpp) + if(TARGET test_parameter_client) + ament_target_dependencies(test_parameter_client + "rcl_interfaces" + ) + target_link_libraries(test_parameter_client ${PROJECT_NAME}) + endif() ament_add_gtest(test_parameter_events_filter test/test_parameter_events_filter.cpp) if(TARGET test_parameter_events_filter) ament_target_dependencies(test_parameter_events_filter diff --git a/rclcpp/include/rclcpp/parameter_client.hpp b/rclcpp/include/rclcpp/parameter_client.hpp index 8af9429..f44ae9a 100644 --- a/rclcpp/include/rclcpp/parameter_client.hpp +++ b/rclcpp/include/rclcpp/parameter_client.hpp @@ -121,8 +121,35 @@ public: rclcpp::SubscriptionOptionsWithAllocator() )) { - return rclcpp::create_subscription( + return this->on_parameter_event( this->node_topics_interface_, + callback, + qos, + options); + } + + /** + * The NodeT type only needs to have a method called get_node_topics_interface() + * which returns a shared_ptr to a NodeTopicsInterface, or be a + * NodeTopicsInterface pointer itself. + */ + template< + typename CallbackT, + typename NodeT, + typename AllocatorT = std::allocator> + static typename rclcpp::Subscription::SharedPtr + on_parameter_event( + NodeT && node, + CallbackT && callback, + const rclcpp::QoS & qos = ( + rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(rmw_qos_profile_default)) + ), + const rclcpp::SubscriptionOptionsWithAllocator & options = ( + rclcpp::SubscriptionOptionsWithAllocator() + )) + { + return rclcpp::create_subscription( + node, "parameter_events", qos, std::forward(callback), @@ -266,7 +293,26 @@ public: typename rclcpp::Subscription::SharedPtr on_parameter_event(CallbackT && callback) { - return async_parameters_client_->on_parameter_event(std::forward(callback)); + return async_parameters_client_->on_parameter_event( + std::forward(callback)); + } + + /** + * The NodeT type only needs to have a method called get_node_topics_interface() + * which returns a shared_ptr to a NodeTopicsInterface, or be a + * NodeTopicsInterface pointer itself. + */ + template< + typename CallbackT, + typename NodeT> + static typename rclcpp::Subscription::SharedPtr + on_parameter_event( + NodeT && node, + CallbackT && callback) + { + return AsyncParametersClient::on_parameter_event( + node, + std::forward(callback)); } RCLCPP_PUBLIC diff --git a/rclcpp/src/rclcpp/time_source.cpp b/rclcpp/src/rclcpp/time_source.cpp index 035a6ef..3639e10 100644 --- a/rclcpp/src/rclcpp/time_source.cpp +++ b/rclcpp/src/rclcpp/time_source.cpp @@ -103,15 +103,9 @@ void TimeSource::attachNode( } // TODO(tfoote) use parameters interface not subscribe to events via topic ticketed #609 - parameter_client_ = std::make_shared( - node_base_, + parameter_subscription_ = rclcpp::AsyncParametersClient::on_parameter_event( node_topics_, - node_graph_, - node_services_ - ); - parameter_subscription_ = - parameter_client_->on_parameter_event(std::bind(&TimeSource::on_parameter_event, - this, std::placeholders::_1)); + std::bind(&TimeSource::on_parameter_event, this, std::placeholders::_1)); } void TimeSource::detachNode() diff --git a/rclcpp/test/test_parameter_client.cpp b/rclcpp/test/test_parameter_client.cpp new file mode 100644 index 0000000..baae1ec --- /dev/null +++ b/rclcpp/test/test_parameter_client.cpp @@ -0,0 +1,155 @@ +// 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 + +#include +#include + +#include "rclcpp/rclcpp.hpp" + +#include "rcl_interfaces/msg/parameter_event.hpp" + +class TestParameterClient : public ::testing::Test +{ +public: + void OnMessage(const rcl_interfaces::msg::ParameterEvent::SharedPtr event) + { + (void)event; + } + +protected: + static void SetUpTestCase() + { + rclcpp::init(0, nullptr); + } + + void SetUp() + { + node = std::make_shared("test_parameter_client", "/ns"); + } + + void TearDown() + { + node.reset(); + } + + rclcpp::Node::SharedPtr node; +}; + +/* + Testing async parameter client construction and destruction. + */ +TEST_F(TestParameterClient, async_construction_and_destruction) { + { + auto asynchronous_client = std::make_shared(node); + (void)asynchronous_client; + } + + { + auto asynchronous_client = std::make_shared( + node->get_node_base_interface(), + node->get_node_topics_interface(), + node->get_node_graph_interface(), + node->get_node_services_interface()); + (void)asynchronous_client; + } + + { + ASSERT_THROW({ + std::make_shared(node, "invalid_remote_node?"); + }, rclcpp::exceptions::InvalidServiceNameError); + } +} + +/* + Testing sync parameter client construction and destruction. + */ +TEST_F(TestParameterClient, sync_construction_and_destruction) { + { + auto synchronous_client = std::make_shared(node); + (void)synchronous_client; + } + + { + auto synchronous_client = std::make_shared( + std::make_shared(), + node); + (void)synchronous_client; + } + + { + auto synchronous_client = std::make_shared( + std::make_shared(), + node->get_node_base_interface(), + node->get_node_topics_interface(), + node->get_node_graph_interface(), + node->get_node_services_interface()); + (void)synchronous_client; + } + + { + ASSERT_THROW({ + std::make_shared(node, "invalid_remote_node?"); + }, rclcpp::exceptions::InvalidServiceNameError); + } +} + +/* + Testing different methods for parameter event subscription from asynchronous clients. + */ +TEST_F(TestParameterClient, async_parameter_event_subscription) { + auto callback = std::bind(&TestParameterClient::OnMessage, this, std::placeholders::_1); + { + auto asynchronous_client = std::make_shared(node); + auto event_sub = asynchronous_client->on_parameter_event(callback); + (void)event_sub; + } + + { + auto event_sub = rclcpp::AsyncParametersClient::on_parameter_event(node, callback); + (void)event_sub; + } + + { + auto event_sub = rclcpp::AsyncParametersClient::on_parameter_event( + node->get_node_topics_interface(), + callback); + (void)event_sub; + } +} + +/* + Testing different methods for parameter event subscription from synchronous clients. + */ +TEST_F(TestParameterClient, sync_parameter_event_subscription) { + auto callback = std::bind(&TestParameterClient::OnMessage, this, std::placeholders::_1); + { + auto synchronous_client = std::make_shared(node); + auto event_sub = synchronous_client->on_parameter_event(callback); + (void)event_sub; + } + + { + auto event_sub = rclcpp::SyncParametersClient::on_parameter_event(node, callback); + (void)event_sub; + } + + { + auto event_sub = rclcpp::SyncParametersClient::on_parameter_event( + node->get_node_topics_interface(), + callback); + (void)event_sub; + } +}