ROS 2 rclcpp + rcl - jazzy  jazzy
ROS 2 C++ Client Library with ROS Client Library
generic_client.hpp
1 // Copyright 2023 Sony Group Corporation.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef RCLCPP__GENERIC_CLIENT_HPP_
16 #define RCLCPP__GENERIC_CLIENT_HPP_
17 
18 #include <map>
19 #include <memory>
20 #include <future>
21 #include <string>
22 #include <vector>
23 #include <utility>
24 
25 #include "rcl/client.h"
26 
27 #include "rclcpp/client.hpp"
28 #include "rclcpp/visibility_control.hpp"
29 #include "rcpputils/shared_library.hpp"
30 
31 #include "rosidl_typesupport_introspection_cpp/message_introspection.hpp"
32 
33 namespace rclcpp
34 {
35 class GenericClient : public ClientBase
36 {
37 public:
38  using Request = void *; // Serialized data pointer of request message
39  using Response = void *; // Serialized data pointer of response message
40 
41  using SharedResponse = std::shared_ptr<void>;
42 
43  using Promise = std::promise<SharedResponse>;
44  using SharedPromise = std::shared_ptr<Promise>;
45 
46  using Future = std::future<SharedResponse>;
47  using SharedFuture = std::shared_future<SharedResponse>;
48 
49  RCLCPP_SMART_PTR_DEFINITIONS(GenericClient)
50 
51 
60  : detail::FutureAndRequestId<Future>
61  {
63 
65  SharedFuture share() noexcept {return this->future.share();}
66 
68  FutureAndRequestId(FutureAndRequestId && other) noexcept = default;
70  FutureAndRequestId(const FutureAndRequestId & other) = delete;
72  FutureAndRequestId & operator=(FutureAndRequestId && other) noexcept = default;
74  FutureAndRequestId & operator=(const FutureAndRequestId & other) = delete;
76  ~FutureAndRequestId() = default;
77  };
78 
81  rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
82  const std::string & service_name,
83  const std::string & service_type,
84  rcl_client_options_t & client_options);
85 
86  RCLCPP_PUBLIC
87  SharedResponse
88  create_response() override;
89 
90  RCLCPP_PUBLIC
91  std::shared_ptr<rmw_request_id_t>
92  create_request_header() override;
93 
94  RCLCPP_PUBLIC
95  void
96  handle_response(
97  std::shared_ptr<rmw_request_id_t> request_header,
98  std::shared_ptr<void> response) override;
99 
101 
128  RCLCPP_PUBLIC
130  async_send_request(const Request request);
131 
133 
139  template<typename AllocatorT = std::allocator<int64_t>>
140  size_t
142  std::chrono::time_point<std::chrono::system_clock> time_point,
143  std::vector<int64_t, AllocatorT> * pruned_requests = nullptr)
144  {
145  return detail::prune_requests_older_than_impl(
146  pending_requests_,
147  pending_requests_mutex_,
148  time_point,
149  pruned_requests);
150  }
151 
152  RCLCPP_PUBLIC
153  size_t
154  prune_pending_requests();
155 
156  RCLCPP_PUBLIC
157  bool
158  remove_pending_request(
159  int64_t request_id);
160 
162 
174  RCLCPP_PUBLIC
175  bool
176  take_response(Response response_out, rmw_request_id_t & request_header_out)
177  {
178  return this->take_type_erased_response(response_out, request_header_out);
179  }
180 
181 protected:
182  using CallbackInfoVariant = std::variant<
183  std::promise<SharedResponse>>; // Use variant for extension
184 
185  int64_t
186  async_send_request_impl(
187  const Request request,
188  CallbackInfoVariant value);
189 
190  std::optional<CallbackInfoVariant>
191  get_and_erase_pending_request(
192  int64_t request_number);
193 
194  RCLCPP_DISABLE_COPY(GenericClient)
195 
196  std::map<int64_t, std::pair<
197  std::chrono::time_point<std::chrono::system_clock>,
198  CallbackInfoVariant>> pending_requests_;
199  std::mutex pending_requests_mutex_;
200 
201 private:
202  std::shared_ptr<rcpputils::SharedLibrary> ts_lib_;
203  const rosidl_typesupport_introspection_cpp::MessageMembers * response_members_;
204 };
205 } // namespace rclcpp
206 
207 #endif // RCLCPP__GENERIC_CLIENT_HPP_
RCLCPP_PUBLIC bool take_type_erased_response(void *response_out, rmw_request_id_t &request_header_out)
Take the next response for this client as a type erased pointer.
Definition: client.cpp:71
RCLCPP_PUBLIC FutureAndRequestId async_send_request(const Request request)
Send a request to the service server.
RCLCPP_PUBLIC bool take_response(Response response_out, rmw_request_id_t &request_header_out)
Take the next response for this client.
size_t prune_requests_older_than(std::chrono::time_point< std::chrono::system_clock > time_point, std::vector< int64_t, AllocatorT > *pruned_requests=nullptr)
Clean all pending requests older than a time_point.
Pure virtual interface class for the NodeBase part of the Node API.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
Options available for a rcl_client_t.
Definition: client.h:50
A convenient GenericClient::Future and request id pair.
FutureAndRequestId(FutureAndRequestId &&other) noexcept=default
Move constructor.
FutureAndRequestId(const FutureAndRequestId &other)=delete
Deleted copy constructor, each instance is a unique owner of the future.
FutureAndRequestId & operator=(const FutureAndRequestId &other)=delete
Deleted copy assignment, each instance is a unique owner of the future.
SharedFuture share() noexcept
See std::future::share().
FutureAndRequestId & operator=(FutureAndRequestId &&other) noexcept=default
Move assignment.