rclcpp  beta1
C++ ROS Client Library API
service.hpp
Go to the documentation of this file.
1 // Copyright 2014 Open Source Robotics Foundation, Inc.
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__SERVICE_HPP_
16 #define RCLCPP__SERVICE_HPP_
17 
18 #include <functional>
19 #include <iostream>
20 #include <memory>
21 #include <sstream>
22 #include <string>
23 
24 #include "rcl/error_handling.h"
25 #include "rcl/service.h"
26 
28 #include "rclcpp/macros.hpp"
31 #include "rmw/error_handling.h"
32 #include "rmw/rmw.h"
33 
34 namespace rclcpp
35 {
36 namespace service
37 {
38 
40 {
41 public:
43 
46  std::shared_ptr<rcl_node_t> node_handle,
47  const std::string & service_name);
48 
50  explicit ServiceBase(
51  std::shared_ptr<rcl_node_t> node_handle);
52 
54  virtual ~ServiceBase();
55 
59 
61  const rcl_service_t *
63 
66  virtual void handle_request(
67  std::shared_ptr<rmw_request_id_t> request_header,
68  std::shared_ptr<void> request) = 0;
69 
70 protected:
71  RCLCPP_DISABLE_COPY(ServiceBase)
72 
73  std::shared_ptr<rcl_node_t> node_handle_;
74 
76  std::string service_name_;
77  bool owns_rcl_handle_ = true;
78 };
79 
80 using any_service_callback::AnyServiceCallback;
81 
82 template<typename ServiceT>
83 class Service : public ServiceBase
84 {
85 public:
87  void(
90 
92  void(
97 
99  std::shared_ptr<rcl_node_t> node_handle,
100  const std::string & service_name,
101  AnyServiceCallback<ServiceT> any_callback,
102  rcl_service_options_t & service_options)
103  : ServiceBase(node_handle, service_name), any_callback_(any_callback)
104  {
105  using rosidl_typesupport_cpp::get_service_type_support_handle;
106  auto service_type_support_handle = get_service_type_support_handle<ServiceT>();
107 
108  // rcl does the static memory allocation here
110  *service_handle_ = rcl_get_zero_initialized_service();
111 
112  if (rcl_service_init(
113  service_handle_, node_handle.get(), service_type_support_handle, service_name.c_str(),
114  &service_options) != RCL_RET_OK)
115  {
116  throw std::runtime_error(std::string("could not create service: ") +
118  }
119  }
120 
122  std::shared_ptr<rcl_node_t> node_handle,
123  rcl_service_t * service_handle,
124  AnyServiceCallback<ServiceT> any_callback)
125  : ServiceBase(node_handle),
126  any_callback_(any_callback)
127  {
128  // check if service handle was initialized
129  // TODO(karsten1987): Take this verification
130  // directly in rcl_*_t
131  // see: https://github.com/ros2/rcl/issues/81
132  if (!service_handle->impl) {
133  // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
134  throw std::runtime_error(
135  std::string("rcl_service_t in constructor argument must be initialized beforehand."));
136  // *INDENT-ON*
137  }
138  service_handle_ = service_handle;
140  owns_rcl_handle_ = false;
141  }
142 
143  Service() = delete;
144 
145  virtual ~Service()
146  {
147  // check if you have ownership of the handle
148  if (owns_rcl_handle_) {
151  ss << "Error in destruction of rcl service_handle_ handle: " <<
152  rcl_get_error_string_safe() << '\n';
153  (std::cerr << ss.str()).flush();
154  }
155  }
156  }
157 
159  {
160  return std::shared_ptr<void>(new typename ServiceT::Request());
161  }
162 
164  {
165  // TODO(wjwwood): This should probably use rmw_request_id's allocator.
166  // (since it is a C type)
168  }
169 
171  std::shared_ptr<void> request)
172  {
173  auto typed_request = std::static_pointer_cast<typename ServiceT::Request>(request);
174  auto response = std::shared_ptr<typename ServiceT::Response>(new typename ServiceT::Response);
175  any_callback_.dispatch(request_header, typed_request, response);
176  send_response(request_header, response);
177  }
178 
182  {
183  rcl_ret_t status = rcl_send_response(get_service_handle(), req_id.get(), response.get());
184 
185  if (status != RCL_RET_OK) {
186  // *INDENT-OFF* (prevent uncrustify from making unnecessary indents here)
187  throw std::runtime_error(
188  std::string("failed to send response: ") + rcl_get_error_string_safe());
189  // *INDENT-ON*
190  }
191  }
192 
193 private:
195 
196  AnyServiceCallback<ServiceT> any_callback_;
197 };
198 
199 } // namespace service
200 } // namespace rclcpp
201 
202 #endif // RCLCPP__SERVICE_HPP_
const char * rcl_service_get_service_name(const rcl_service_t *service)
virtual ~Service()
Definition: service.hpp:145
virtual void handle_request(std::shared_ptr< rmw_request_id_t > request_header, std::shared_ptr< void > request)=0
rcl_ret_t rcl_service_init(rcl_service_t *service, const rcl_node_t *node, const rosidl_service_type_support_t *type_support, const char *service_name, const rcl_service_options_t *options)
std::shared_ptr< rmw_request_id_t > create_request_header()
Definition: service.hpp:163
#define RCLCPP_DISABLE_COPY(...)
Definition: macros.hpp:26
rmw_ret_t rcl_ret_t
rcl_service_t * service_handle_
Definition: service.hpp:75
const rcl_service_t * get_service_handle()
struct rcl_service_impl_t * impl
Definition: allocator_common.hpp:24
void send_response(std::shared_ptr< rmw_request_id_t > req_id, std::shared_ptr< typename ServiceT::Response > response)
Definition: service.hpp:179
#define RCL_RET_OK
void handle_request(std::shared_ptr< rmw_request_id_t > request_header, std::shared_ptr< void > request)
Definition: service.hpp:170
virtual std::shared_ptr< void > create_request()=0
rcl_ret_t rcl_send_response(const rcl_service_t *service, rmw_request_id_t *response_header, void *ros_response)
#define RCLCPP_SMART_PTR_DEFINITIONS(...)
Definition: macros.hpp:36
ServiceBase(std::shared_ptr< rcl_node_t > node_handle, const std::string &service_name)
Definition: service.hpp:83
bool owns_rcl_handle_
Definition: service.hpp:77
T str(T... args)
T static_pointer_cast(T... args)
#define rcl_get_error_string_safe
rcl_ret_t rcl_service_fini(rcl_service_t *service, rcl_node_t *node)
#define RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(...)
Definition: macros.hpp:51
virtual std::shared_ptr< rmw_request_id_t > create_request_header()=0
T get(T... args)
#define RCLCPP_PUBLIC
Definition: visibility_control.hpp:50
Definition: service.hpp:39
std::shared_ptr< rcl_node_t > node_handle_
Definition: service.hpp:73
rcl_service_t rcl_get_zero_initialized_service(void)
Service(std::shared_ptr< rcl_node_t > node_handle, rcl_service_t *service_handle, AnyServiceCallback< ServiceT > any_callback)
Definition: service.hpp:121
std::shared_ptr< void > create_request()
Definition: service.hpp:158
std::string service_name_
Definition: service.hpp:76
Definition: any_service_callback.hpp:34