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>
29
30 template <class ServiceType>
31 ServiceClientHandler<ServiceType>::ServiceClientHandler(rclcpp::Node::SharedPtr& node, const std::string& address, const rclcpp::QoS& qos,
32 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,
39 const rclcpp::CallbackGroup::SharedPtr& callback_group)
40 : ServiceClientHandler(node, address, rclcpp::ServicesQoS(), callback_group)
41 {
42 }
43
44 //}
45
46 /* callSync(const ServiceType::Request& request, ServiceType::Response& response) //{ */
47
48 template <class ServiceType>
49 std::optional<std::shared_ptr<typename ServiceType::Response>>
50 ServiceClientHandler<ServiceType>::callSync(const std::shared_ptr<typename ServiceType::Request>& request)
51 {
52 if (!impl_)
53 {
54 RCLCPP_ERROR(rclcpp::get_logger("ServiceClientHandler"), "Not initialized, cannot use callSync()!");
55 return std::nullopt;
56 }
57 return impl_->callSync(request);
58 }
59
60 //}
61
62 /* callAsync(const ServiceType::Request& request, ServiceType::Response& response) //{ */
63
64 template <class ServiceType>
65 std::optional<std::shared_future<std::shared_ptr<typename ServiceType::Response>>>
66 ServiceClientHandler<ServiceType>::callAsync(const std::shared_ptr<typename ServiceType::Request>& request)
67 {
68 if (!impl_)
69 {
70 RCLCPP_ERROR(rclcpp::get_logger("ServiceClientHandler"), "Not initialized, cannot use callSync()!");
71 return std::nullopt;
72 }
73 return impl_->callAsync(request);
74 }
75
76 //}
77
78 // --------------------------------------------------------------
79 // | ServiceClientHandler::Impl |
80 // --------------------------------------------------------------
81
82 /* class ServiceClientHandler::impl //{ */
83
87 template <class ServiceType>
88 class ServiceClientHandler<ServiceType>::Impl
89 {
90
91 public:
100 Impl(rclcpp::Node::SharedPtr& node, const std::string& address, const rclcpp::QoS& qos, const rclcpp::CallbackGroup::SharedPtr& callback_group)
101 : callback_group_(callback_group), service_client_(node->create_client<ServiceType>(address, qos, callback_group))
102 {
103 }
104
112 std::optional<std::shared_ptr<typename ServiceType::Response>> callSync(const std::shared_ptr<typename ServiceType::Request>& request)
113 {
114 /* always check if the service is ready before calling */
115 if (!service_client_->service_is_ready())
116 return std::nullopt;
117
118 /* the future done callback is being run in a separate thread under the default callback group of the node */
119 const auto future_msg = service_client_->async_send_request(request).future.share();
120
121 /* it is a good practice to check if the future object is not already invalid after the call */
122 /* if valid() is false, the future has UNDEFINED behavior */
123 if (!future_msg.valid())
124 return std::nullopt;
125
126 // wait for the future to become available and then return
127 return future_msg.get();
128 }
129
137 std::optional<std::shared_future<std::shared_ptr<typename ServiceType::Response>>> callAsync(const std::shared_ptr<typename ServiceType::Request>& request)
138 {
139 /* always check if the service is ready before calling */
140 if (!service_client_->service_is_ready())
141 return std::nullopt;
142
143 const auto future = service_client_->async_send_request(request).future.share();
144
145 /* it is a good practice to check if the future object is not already invalid after the call */
146 /* if valid() is false, the future has UNDEFINED behavior */
147 if (!future.valid())
148 return std::nullopt;
149
150 return future;
151 }
152
153 private:
154 rclcpp::CallbackGroup::SharedPtr callback_group_;
155 typename rclcpp::Client<ServiceType>::SharedPtr service_client_;
156 };
157
158 //}
159
160} // namespace mrs_lib
implementation of the service client handler
Definition service_client_handler.hpp:89
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:137
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:112
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:100
user wrapper of the service client handler implementation
Definition service_client_handler.h:23
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:50
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:66
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.