15 #ifndef NAV2_UTIL__SERVICE_CLIENT_HPP_
16 #define NAV2_UTIL__SERVICE_CLIENT_HPP_
21 #include "rclcpp/rclcpp.hpp"
30 template<
class ServiceT,
typename NodeT = rclcpp::Node::SharedPtr>
41 const std::string & service_name,
42 const NodeT & provided_node,
bool use_internal_executor =
false)
43 : service_name_(service_name), node_(provided_node), use_internal_executor_(use_internal_executor)
45 if (use_internal_executor) {
46 callback_group_ = node_->create_callback_group(
47 rclcpp::CallbackGroupType::MutuallyExclusive,
49 callback_group_executor_ = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
50 callback_group_executor_->add_callback_group(callback_group_,
51 node_->get_node_base_interface());
54 client_ = node_->template create_client<ServiceT>(
56 rclcpp::SystemDefaultsQoS(),
58 rcl_service_introspection_state_t introspection_state = RCL_SERVICE_INTROSPECTION_OFF;
59 if (!node_->has_parameter(
"service_introspection_mode")) {
60 node_->declare_parameter(
"service_introspection_mode",
"disabled");
62 std::string service_introspection_mode =
63 node_->get_parameter(
"service_introspection_mode").as_string();
64 if (service_introspection_mode ==
"metadata") {
65 introspection_state = RCL_SERVICE_INTROSPECTION_METADATA;
66 }
else if (service_introspection_mode ==
"contents") {
67 introspection_state = RCL_SERVICE_INTROSPECTION_CONTENTS;
70 this->client_->configure_introspection(
71 node_->get_clock(), rclcpp::SystemDefaultsQoS(), introspection_state);
74 using RequestType =
typename ServiceT::Request;
75 using ResponseType =
typename ServiceT::Response;
76 using SharedPtr = std::shared_ptr<ServiceClient<ServiceT, NodeT>>;
84 typename ResponseType::SharedPtr
invoke(
85 typename RequestType::SharedPtr & request,
86 const std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1))
88 while (!client_->wait_for_service(std::chrono::seconds(1))) {
90 throw std::runtime_error(
91 service_name_ +
" service client: interrupted while waiting for service");
94 node_->get_logger(),
"%s service client: waiting for service to appear...",
95 service_name_.c_str());
99 node_->get_logger(),
"%s service client: send async request",
100 service_name_.c_str());
101 auto future_result = client_->async_send_request(request);
104 client_->remove_pending_request(future_result);
105 throw std::runtime_error(service_name_ +
" service client: async_send_request failed");
108 return future_result.get();
118 typename RequestType::SharedPtr & request,
119 typename ResponseType::SharedPtr & response)
121 while (!client_->wait_for_service(std::chrono::seconds(1))) {
123 throw std::runtime_error(
124 service_name_ +
" service client: interrupted while waiting for service");
127 node_->get_logger(),
"%s service client: waiting for service to appear...",
128 service_name_.c_str());
132 node_->get_logger(),
"%s service client: send async request",
133 service_name_.c_str());
134 auto future_result = client_->async_send_request(request);
137 client_->remove_pending_request(future_result);
141 response = future_result.get();
142 return response.get();
150 std::shared_future<typename ResponseType::SharedPtr>
async_call(
151 typename RequestType::SharedPtr & request)
153 auto future_result = client_->async_send_request(request);
154 return future_result.share();
163 template<
typename CallbackT>
164 void async_call(
typename RequestType::SharedPtr request, CallbackT && callback)
166 client_->async_send_request(request, callback);
174 bool wait_for_service(
const std::chrono::nanoseconds timeout = std::chrono::nanoseconds::max())
176 return client_->wait_for_service(timeout);
186 template<
typename FutureT>
188 const FutureT & future,
189 const std::chrono::nanoseconds timeout = std::chrono::nanoseconds(-1))
191 if (use_internal_executor_) {
192 return callback_group_executor_->spin_until_future_complete(future, timeout);
194 return rclcpp::spin_until_future_complete(node_, future, timeout);
204 return service_name_;
208 std::string service_name_;
210 rclcpp::CallbackGroup::SharedPtr callback_group_{
nullptr};
211 rclcpp::executors::SingleThreadedExecutor::SharedPtr callback_group_executor_;
212 typename rclcpp::Client<ServiceT>::SharedPtr client_;
213 bool use_internal_executor_;
A simple wrapper on ROS2 services client.
std::shared_future< typename ResponseType::SharedPtr > async_call(typename RequestType::SharedPtr &request)
Asynchronously call the service.
bool invoke(typename RequestType::SharedPtr &request, typename ResponseType::SharedPtr &response)
Invoke the service and block until completed.
ServiceClient(const std::string &service_name, const NodeT &provided_node, bool use_internal_executor=false)
A constructor.
ResponseType::SharedPtr invoke(typename RequestType::SharedPtr &request, const std::chrono::nanoseconds timeout=std::chrono::nanoseconds(-1))
Invoke the service and block until completed or timed out.
void async_call(typename RequestType::SharedPtr request, CallbackT &&callback)
Asynchronously call the service with a callback.
rclcpp::FutureReturnCode spin_until_complete(const FutureT &future, const std::chrono::nanoseconds timeout=std::chrono::nanoseconds(-1))
Spins the executor until the provided future is complete or the timeout is reached.
std::string getServiceName()
Gets the service name.
bool wait_for_service(const std::chrono::nanoseconds timeout=std::chrono::nanoseconds::max())
Block until a service is available or timeout.