ROS 2 rclcpp + rcl - rolling  rolling-20536064
ROS 2 C++ Client Library with ROS Client Library
service.cpp
1 // Copyright 2015 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 #include "rclcpp/service.hpp"
16 
17 #include <functional>
18 #include <memory>
19 #include <mutex>
20 #include <sstream>
21 #include <stdexcept>
22 #include <string>
23 
24 #include "rclcpp/any_service_callback.hpp"
25 #include "rclcpp/detail/cpp_callback_trampoline.hpp"
26 #include "rclcpp/logging.hpp"
27 #include "rclcpp/macros.hpp"
28 #include "rclcpp/qos.hpp"
29 #include "rmw/error_handling.h"
30 #include "rmw/impl/cpp/demangle.hpp"
31 #include "rmw/rmw.h"
32 
34 
35 ServiceBase::ServiceBase(const std::shared_ptr<rcl_node_t> & node_handle)
36 : node_handle_(node_handle),
37  node_logger_(rclcpp::get_node_logger(node_handle_.get()))
38 {}
39 
40 
41 bool
42 ServiceBase::take_type_erased_request(void * request_out, rmw_request_id_t & request_id_out)
43 {
45  this->get_service_handle().get(),
46  &request_id_out,
47  request_out);
48  if (RCL_RET_SERVICE_TAKE_FAILED == ret) {
49  return false;
50  } else if (RCL_RET_OK != ret) {
51  rclcpp::exceptions::throw_from_rcl_error(ret);
52  }
53  return true;
54 }
55 
56 const char *
58 {
60 }
61 
62 std::shared_ptr<rcl_service_t>
64 {
65  return service_handle_;
66 }
67 
68 std::shared_ptr<const rcl_service_t>
70 {
71  return service_handle_;
72 }
73 
74 rcl_node_t *
75 ServiceBase::get_rcl_node_handle()
76 {
77  return node_handle_.get();
78 }
79 
80 const rcl_node_t *
81 ServiceBase::get_rcl_node_handle() const
82 {
83  return node_handle_.get();
84 }
85 
86 bool
88 {
89  return in_use_by_wait_set_.exchange(in_use_state);
90 }
91 
94 {
95  const rmw_qos_profile_t * qos =
96  rcl_service_response_publisher_get_actual_qos(service_handle_.get());
97  if (!qos) {
98  auto msg =
99  std::string("failed to get service's response publisher qos settings: ") +
100  rcl_get_error_string().str;
101  rcl_reset_error();
102  throw std::runtime_error(msg);
103  }
104 
105  rclcpp::QoS response_publisher_qos =
107 
108  return response_publisher_qos;
109 }
110 
113 {
114  const rmw_qos_profile_t * qos =
116  if (!qos) {
117  auto msg =
118  std::string("failed to get service's request subscription qos settings: ") +
119  rcl_get_error_string().str;
120  rcl_reset_error();
121  throw std::runtime_error(msg);
122  }
123 
124  rclcpp::QoS request_subscription_qos =
126 
127  return request_subscription_qos;
128 }
129 
130 void
131 ServiceBase::set_on_new_request_callback(rcl_event_callback_t callback, const void * user_data)
132 {
134  service_handle_.get(),
135  callback,
136  user_data);
137 
138  if (RCL_RET_OK != ret) {
139  rclcpp::exceptions::throw_from_rcl_error(
140  ret, "failed to set the on new request callback for service");
141  }
142 }
143 
144 void
145 ServiceBase::set_on_new_request_callback(const std::function<void(size_t)> & callback)
146 {
147  if (!callback) {
148  throw std::invalid_argument(
149  "The callback passed to set_on_new_request_callback "
150  "is not callable.");
151  }
152 
153  auto new_callback =
154  [callback, this](size_t number_of_requests) {
155  try {
156  callback(number_of_requests);
157  } catch (const std::exception & exception) {
158  RCLCPP_ERROR_STREAM(
159  node_logger_,
160  "rclcpp::ServiceBase@" << this <<
161  " caught " << rmw::impl::cpp::demangle(exception) <<
162  " exception in user-provided callback for the 'on new request' callback: " <<
163  exception.what());
164  } catch (...) {
165  RCLCPP_ERROR_STREAM(
166  node_logger_,
167  "rclcpp::ServiceBase@" << this <<
168  " caught unhandled exception in user-provided callback " <<
169  "for the 'on new request' callback");
170  }
171  };
172 
173  std::lock_guard<std::recursive_mutex> lock(callback_mutex_);
174 
175  // Set it temporarily to the new callback, while we replace the old one.
176  // This two-step setting, prevents a gap where the old std::function has
177  // been replaced but the middleware hasn't been told about the new one yet.
179  rclcpp::detail::cpp_callback_trampoline<decltype(new_callback), const void *, size_t>,
180  static_cast<const void *>(&new_callback));
181 
182  // Store the std::function to keep it in scope, also overwrites the existing one.
183  on_new_request_callback_ = new_callback;
184 
185  // Set it again, now using the permanent storage.
187  rclcpp::detail::cpp_callback_trampoline<
188  decltype(on_new_request_callback_), const void *, size_t>,
189  static_cast<const void *>(&on_new_request_callback_));
190 }
191 
192 void
194 {
195  std::lock_guard<std::recursive_mutex> lock(callback_mutex_);
196  if (on_new_request_callback_) {
197  set_on_new_request_callback(nullptr, nullptr);
198  on_new_request_callback_ = nullptr;
199  }
200 }
Encapsulation of Quality of Service settings.
Definition: qos.hpp:114
RCLCPP_PUBLIC bool exchange_in_use_by_wait_set_state(bool in_use_state)
Exchange the "in use by wait set" state for this service.
Definition: service.cpp:87
RCLCPP_PUBLIC rclcpp::QoS get_request_subscription_actual_qos() const
Get the actual request subscription QoS settings, after the defaults have been determined.
Definition: service.cpp:112
RCLCPP_PUBLIC rclcpp::QoS get_response_publisher_actual_qos() const
Get the actual response publisher QoS settings, after the defaults have been determined.
Definition: service.cpp:93
RCLCPP_PUBLIC void clear_on_new_request_callback()
Unset the callback registered for new requests, if any.
Definition: service.cpp:193
RCLCPP_PUBLIC std::shared_ptr< rcl_service_t > get_service_handle()
Return the rcl_service_t service handle in a std::shared_ptr.
Definition: service.cpp:63
RCLCPP_PUBLIC void set_on_new_request_callback(const std::function< void(size_t)> &callback)
Set a callback to be called when each new request is received.
Definition: service.cpp:145
RCLCPP_PUBLIC const char * get_service_name()
Return the name of the service.
Definition: service.cpp:57
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
RCLCPP_PUBLIC Logger get_node_logger(const rcl_node_t *node)
Return a named logger using an rcl_node_t.
Definition: logger.cpp:43
RCL_PUBLIC RCL_WARN_UNUSED const rmw_qos_profile_t * rcl_service_request_subscription_get_actual_qos(const rcl_service_t *service)
Get the actual qos settings of the service's request subscription.
Definition: service.c:427
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_service_get_service_name(const rcl_service_t *service)
Get the topic name for the service.
Definition: service.c:288
RCL_PUBLIC RCL_WARN_UNUSED const rmw_qos_profile_t * rcl_service_response_publisher_get_actual_qos(const rcl_service_t *service)
Get the actual qos settings of the service's response publisher.
Definition: service.c:436
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_service_set_on_new_request_callback(const rcl_service_t *service, rcl_event_callback_t callback, const void *user_data)
Set the on new request callback function for the service.
Definition: service.c:445
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_take_request(const rcl_service_t *service, rmw_request_id_t *request_header, void *ros_request)
Backwards compatibility function to take a pending ROS request using a rcl service.
Definition: service.c:362
Structure which encapsulates a ROS Node.
Definition: node.h:45
static QoSInitialization from_rmw(const rmw_qos_profile_t &rmw_qos)
Create a QoSInitialization from an existing rmw_qos_profile_t, using its history and depth.
Definition: qos.cpp:70
#define RCL_RET_OK
Success return code.
Definition: types.h:27
#define RCL_RET_SERVICE_TAKE_FAILED
Failed to take a request from the service return code.
Definition: types.h:87
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:24