mrs_lib
Various reusable classes, functions and utilities for use in MRS projects
Loading...
Searching...
No Matches
service_client_handler.hpp
Go to the documentation of this file.
1
6#pragma once
7
9
10namespace mrs_lib
11{
12
13 // --------------------------------------------------------------
14 // | ServiceClientHandler |
15 // --------------------------------------------------------------
16
17 /* ServiceClientHandler() constructors //{ */
18
19 template <class ServiceType>
20 ServiceClientHandler<ServiceType>::ServiceClientHandler(rclcpp::Node::SharedPtr& node, const std::string& address, const rclcpp::QoS& qos)
21 : impl_(std::make_shared<Impl>(node, address, qos, node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive)))
22 {
23 }
24
25 template <class ServiceType>
30
31 template <class ServiceType>
32 ServiceClientHandler<ServiceType>::ServiceClientHandler(rclcpp::Node::SharedPtr& node, const std::string& address, const rclcpp::QoS& qos, const rclcpp::CallbackGroup::SharedPtr& callback_group)
33 : impl_(std::make_shared<Impl>(node, address, qos, callback_group))
34 {
35 }
36
37 template <class ServiceType>
38 ServiceClientHandler<ServiceType>::ServiceClientHandler(rclcpp::Node::SharedPtr& node, const std::string& address, const rclcpp::CallbackGroup::SharedPtr& callback_group)
39 : ServiceClientHandler(node, address, rclcpp::ServicesQoS(), callback_group)
40 {
41 }
42
43 //}
44
45 /* callSync(const ServiceType::Request& request, ServiceType::Response& response) //{ */
46
47 template <class ServiceType>
48 std::optional<std::shared_ptr<typename ServiceType::Response>> ServiceClientHandler<ServiceType>::callSync(const std::shared_ptr<typename ServiceType::Request>& request)
49 {
50 if (!impl_)
51 {
52 RCLCPP_ERROR(rclcpp::get_logger("ServiceClientHandler"), "Not initialized, cannot use callSync()!");
53 return std::nullopt;
54 }
55 return impl_->callSync(request);
56 }
57
58 //}
59
60 /* callAsync(const ServiceType::Request& request, ServiceType::Response& response) //{ */
61
62 template <class ServiceType>
63 std::optional<std::shared_future<std::shared_ptr<typename ServiceType::Response>>> ServiceClientHandler<ServiceType>::callAsync(const std::shared_ptr<typename ServiceType::Request>& request)
64 {
65 if (!impl_)
66 {
67 RCLCPP_ERROR(rclcpp::get_logger("ServiceClientHandler"), "Not initialized, cannot use callSync()!");
68 return std::nullopt;
69 }
70 return impl_->callAsync(request);
71 }
72
73 //}
74
75 // --------------------------------------------------------------
76 // | ServiceClientHandler::Impl |
77 // --------------------------------------------------------------
78
79 /* class ServiceClientHandler::impl //{ */
80
84 template <class ServiceType>
85 class ServiceClientHandler<ServiceType>::Impl {
86
87 public:
88
97 Impl(rclcpp::Node::SharedPtr& node, const std::string& address, const rclcpp::QoS& qos, const rclcpp::CallbackGroup::SharedPtr& callback_group)
98 : callback_group_(callback_group),
99 service_client_(node->create_client<ServiceType>(address, qos, callback_group))
100 {
101 }
102
110 std::optional<std::shared_ptr<typename ServiceType::Response>> callSync(const std::shared_ptr<typename ServiceType::Request>& request)
111 {
112 /* always check if the service is ready before calling */
113 if (!service_client_->service_is_ready())
114 return std::nullopt;
115
116 /* the future done callback is being run in a separate thread under the default callback group of the node */
117 const auto future_msg = service_client_->async_send_request(request).future.share();
118
119 /* it is a good practice to check if the future object is not already invalid after the call */
120 /* if valid() is false, the future has UNDEFINED behavior */
121 if (!future_msg.valid())
122 return std::nullopt;
123
124 // wait for the future to become available and then return
125 return future_msg.get();
126 }
127
135 std::optional<std::shared_future<std::shared_ptr<typename ServiceType::Response>>> callAsync(const std::shared_ptr<typename ServiceType::Request>& request)
136 {
137 /* always check if the service is ready before calling */
138 if (!service_client_->service_is_ready())
139 return std::nullopt;
140
141 const auto future = service_client_->async_send_request(request).future.share();
142
143 /* it is a good practice to check if the future object is not already invalid after the call */
144 /* if valid() is false, the future has UNDEFINED behavior */
145 if (!future.valid())
146 return std::nullopt;
147
148 return future;
149 }
150
151 private:
152 rclcpp::CallbackGroup::SharedPtr callback_group_;
153 typename rclcpp::Client<ServiceType>::SharedPtr service_client_;
154 };
155
156 //}
157
158} // namespace mrs_lib
implementation of the service client handler
Definition service_client_handler.hpp:85
std::optional< std::shared_future< std::shared_ptr< typename ServiceType::Response > > > callAsync(const std::shared_ptr< typename ServiceType::Request > &request)
asynchronous service call
Definition service_client_handler.hpp:135
std::optional< std::shared_ptr< typename ServiceType::Response > > callSync(const std::shared_ptr< typename ServiceType::Request > &request)
"classic" synchronous service call
Definition service_client_handler.hpp:110
Impl(rclcpp::Node::SharedPtr &node, const std::string &address, const rclcpp::QoS &qos, const rclcpp::CallbackGroup::SharedPtr &callback_group)
constructor
Definition service_client_handler.hpp:97
user wrapper of the service client handler implementation
Definition service_client_handler.h:22
ServiceClientHandler()
Default constructor to avoid having to use pointers.
Definition service_client_handler.hpp:26
std::optional< std::shared_ptr< typename ServiceType::Response > > callSync(const std::shared_ptr< typename ServiceType::Request > &request)
Synchronous (blocking) call of the service.
Definition service_client_handler.hpp:48
std::optional< std::shared_future< std::shared_ptr< typename ServiceType::Response > > > callAsync(const std::shared_ptr< typename ServiceType::Request > &request)
Asynchronous (non-blocking) call of the service.
Definition service_client_handler.hpp:63
All mrs_lib functions, classes, variables and definitions are contained in this namespace.
Definition attitude_converter.h:24
Defines ServiceClientHandler and related convenience classes for upgrading the ROS service client.