15 #ifndef RCLCPP__SERVICE_HPP_
16 #define RCLCPP__SERVICE_HPP_
27 #include "rcl/error_handling.h"
28 #include "rcl/event_callback.h"
30 #include "rcl/service_introspection.h"
32 #include "rmw/error_handling.h"
33 #include "rmw/impl/cpp/demangle.hpp"
36 #include "tracetools/tracetools.h"
38 #include "rclcpp/any_service_callback.hpp"
39 #include "rclcpp/clock.hpp"
40 #include "rclcpp/detail/cpp_callback_trampoline.hpp"
41 #include "rclcpp/exceptions.hpp"
42 #include "rclcpp/expand_topic_or_service_name.hpp"
43 #include "rclcpp/logging.hpp"
44 #include "rclcpp/macros.hpp"
45 #include "rclcpp/qos.hpp"
46 #include "rclcpp/type_support_decl.hpp"
47 #include "rclcpp/visibility_control.hpp"
55 RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(
ServiceBase)
58 explicit ServiceBase(
const std::shared_ptr<rcl_node_t> & node_handle);
75 std::shared_ptr<rcl_service_t>
84 std::shared_ptr<const rcl_service_t>
107 std::shared_ptr<void>
108 create_request() = 0;
111 std::shared_ptr<rmw_request_id_t>
112 create_request_header() = 0;
117 const std::shared_ptr<rmw_request_id_t> & request_header,
118 const std::shared_ptr<void> & request) = 0;
197 throw std::invalid_argument(
198 "The callback passed to set_on_new_request_callback "
203 [callback,
this](
size_t number_of_requests) {
205 callback(number_of_requests);
206 }
catch (
const std::exception & exception) {
209 "rclcpp::ServiceBase@" <<
this <<
210 " caught " << rmw::impl::cpp::demangle(exception) <<
211 " exception in user-provided callback for the 'on new request' callback: " <<
216 "rclcpp::ServiceBase@" <<
this <<
217 " caught unhandled exception in user-provided callback " <<
218 "for the 'on new request' callback");
222 std::lock_guard<std::recursive_mutex> lock(callback_mutex_);
228 rclcpp::detail::cpp_callback_trampoline<decltype(new_callback),
const void *,
size_t>,
229 static_cast<const void *
>(&new_callback));
232 on_new_request_callback_ = new_callback;
236 rclcpp::detail::cpp_callback_trampoline<
237 decltype(on_new_request_callback_),
const void *,
size_t>,
238 static_cast<const void *
>(&on_new_request_callback_));
245 std::lock_guard<std::recursive_mutex> lock(callback_mutex_);
246 if (on_new_request_callback_) {
248 on_new_request_callback_ =
nullptr;
257 get_rcl_node_handle();
261 get_rcl_node_handle()
const;
267 std::shared_ptr<rcl_node_t> node_handle_;
269 std::recursive_mutex callback_mutex_;
274 std::function<void(
size_t)> on_new_request_callback_{
nullptr};
276 std::shared_ptr<rcl_service_t> service_handle_;
277 bool owns_rcl_handle_ =
true;
281 std::atomic<bool> in_use_by_wait_set_{
false};
284 template<
typename ServiceT>
287 public std::enable_shared_from_this<Service<ServiceT>>
290 using ServiceType = ServiceT;
291 using CallbackType = std::function<
293 const std::shared_ptr<typename ServiceT::Request>,
294 std::shared_ptr<typename ServiceT::Response>)>;
296 using CallbackWithHeaderType = std::function<
298 const std::shared_ptr<rmw_request_id_t>,
299 const std::shared_ptr<typename ServiceT::Request>,
300 std::shared_ptr<typename ServiceT::Response>)>;
301 RCLCPP_SMART_PTR_DEFINITIONS(
Service)
316 const std::
string & service_name,
319 :
ServiceBase(node_handle), any_callback_(any_callback),
320 srv_type_support_handle_(rosidl_typesupport_cpp::get_service_type_support_handle<ServiceT>())
323 service_handle_ = std::shared_ptr<rcl_service_t>(
328 rclcpp::get_node_logger(handle.get()).get_child(
"rclcpp"),
329 "Error in destruction of rcl service handle: %s",
330 rcl_get_error_string().str);
338 service_handle_.get(),
340 srv_type_support_handle_,
341 service_name.c_str(),
345 auto rcl_node_handle = get_rcl_node_handle();
355 rclcpp::exceptions::throw_from_rcl_error(ret,
"could not create service");
357 TRACETOOLS_TRACEPOINT(
358 rclcpp_service_callback_added,
360 static_cast<const void *
>(&any_callback_));
361 #ifndef TRACETOOLS_DISABLED
362 any_callback_.register_callback_for_tracing();
377 const std::shared_ptr<rcl_node_t> & node_handle,
378 const std::shared_ptr<rcl_service_t> & service_handle,
380 :
ServiceBase(node_handle), any_callback_(std::move(any_callback)),
381 srv_type_support_handle_(rosidl_typesupport_cpp::get_service_type_support_handle<ServiceT>())
386 throw std::runtime_error(
387 std::string(
"rcl_service_t in constructor argument must be initialized beforehand."));
391 service_handle_ = service_handle;
392 TRACETOOLS_TRACEPOINT(
393 rclcpp_service_callback_added,
395 static_cast<const void *
>(&any_callback_));
396 #ifndef TRACETOOLS_DISABLED
397 any_callback_.register_callback_for_tracing();
412 const std::shared_ptr<rcl_node_t> & node_handle,
415 :
ServiceBase(node_handle), any_callback_(std::move(any_callback)),
416 srv_type_support_handle_(rosidl_typesupport_cpp::get_service_type_support_handle<ServiceT>())
421 throw std::runtime_error(
422 std::string(
"rcl_service_t in constructor argument must be initialized beforehand."));
427 service_handle_ = std::shared_ptr<rcl_service_t>(
new rcl_service_t);
428 service_handle_->impl = service_handle->
impl;
429 TRACETOOLS_TRACEPOINT(
430 rclcpp_service_callback_added,
432 static_cast<const void *
>(&any_callback_));
433 #ifndef TRACETOOLS_DISABLED
434 any_callback_.register_callback_for_tracing();
457 take_request(
typename ServiceT::Request & request_out, rmw_request_id_t & request_id_out)
462 std::shared_ptr<void>
463 create_request()
override
465 return std::make_shared<typename ServiceT::Request>();
468 std::shared_ptr<rmw_request_id_t>
469 create_request_header()
override
471 return std::make_shared<rmw_request_id_t>();
476 const std::shared_ptr<rmw_request_id_t> & request_header,
477 const std::shared_ptr<void> & request)
override
479 auto typed_request = std::static_pointer_cast<typename ServiceT::Request>(request);
480 auto response = any_callback_.dispatch(this->shared_from_this(), request_header, typed_request);
482 send_response(*request_header, *response);
487 send_response(rmw_request_id_t & req_id,
typename ServiceT::Response & response)
494 "failed to send response to %s (timeout): %s",
495 this->get_service_name(), rcl_get_error_string().str);
500 rclcpp::exceptions::throw_from_rcl_error(ret,
"failed to send response");
515 const Clock::SharedPtr & clock,
const QoS & qos_service_event_pub,
516 rcl_service_introspection_state_t introspection_state)
522 service_handle_.get(),
524 clock->get_clock_handle(),
525 srv_type_support_handle_,
527 introspection_state);
530 rclcpp::exceptions::throw_from_rcl_error(ret,
"failed to configure service introspection");
539 const rosidl_service_type_support_t * srv_type_support_handle_;
RCLCPP_PUBLIC Logger get_child(const std::string &suffix)
Return a logger that is a descendant of this logger.
Encapsulation of Quality of Service settings.
rmw_qos_profile_t & get_rmw_qos_profile()
Return the rmw qos profile.
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.
RCLCPP_PUBLIC rclcpp::QoS get_request_subscription_actual_qos() const
Get the actual request subscription QoS settings, after the defaults have been determined.
RCLCPP_PUBLIC rclcpp::QoS get_response_publisher_actual_qos() const
Get the actual response publisher QoS settings, after the defaults have been determined.
void clear_on_new_request_callback()
Unset the callback registered for new requests, if any.
RCLCPP_PUBLIC std::shared_ptr< rcl_service_t > get_service_handle()
Return the rcl_service_t service handle in a std::shared_ptr.
RCLCPP_PUBLIC bool take_type_erased_request(void *request_out, rmw_request_id_t &request_id_out)
Take the next request from the service as a type erased pointer.
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.
RCLCPP_PUBLIC const char * get_service_name()
Return the name of the service.
bool take_request(typename ServiceT::Request &request_out, rmw_request_id_t &request_id_out)
Take the next request from the service.
Service(const std::shared_ptr< rcl_node_t > &node_handle, rcl_service_t *service_handle, AnyServiceCallback< ServiceT > any_callback)
Default constructor.
Service(const std::shared_ptr< rcl_node_t > &node_handle, const std::shared_ptr< rcl_service_t > &service_handle, AnyServiceCallback< ServiceT > any_callback)
Default constructor.
void configure_introspection(const Clock::SharedPtr &clock, const QoS &qos_service_event_pub, rcl_service_introspection_state_t introspection_state)
Configure service introspection.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.
RCLCPP_PUBLIC std::string expand_topic_or_service_name(const std::string &name, const std::string &node_name, const std::string &namespace_, bool is_service=false)
Expand a topic or service name and throw if it is not valid.
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_name(const rcl_node_t *node)
Return the name of the node.
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_namespace(const rcl_node_t *node)
Return the namespace of the node.
RCL_PUBLIC RCL_WARN_UNUSED rcl_publisher_options_t rcl_publisher_get_default_options(void)
Return the default publisher options in a rcl_publisher_options_t.
RCL_PUBLIC RCL_WARN_UNUSED 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)
Initialize a rcl service.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_service_configure_service_introspection(rcl_service_t *service, rcl_node_t *node, rcl_clock_t *clock, const rosidl_service_type_support_t *type_support, const rcl_publisher_options_t publisher_options, rcl_service_introspection_state_t introspection_state)
Configure service introspection features for the service.
RCL_PUBLIC bool rcl_service_is_valid(const rcl_service_t *service)
Check that the service is valid.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_service_fini(rcl_service_t *service, rcl_node_t *node)
Finalize a rcl_service_t.
RCL_PUBLIC RCL_WARN_UNUSED rcl_service_t rcl_get_zero_initialized_service(void)
Return a rcl_service_t struct with members set to NULL.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_send_response(const rcl_service_t *service, rmw_request_id_t *response_header, void *ros_response)
Send a ROS response to a client using a service.
Structure which encapsulates a ROS Node.
Options available for a rcl publisher.
rmw_qos_profile_t qos
Middleware quality of service settings for the publisher.
Options available for a rcl service.
Structure which encapsulates a ROS Service.
rcl_service_impl_t * impl
Pointer to the service implementation.
#define RCL_RET_SERVICE_NAME_INVALID
Service name (same as topic name) does not pass validation.
#define RCL_RET_OK
Success return code.
#define RCL_RET_TIMEOUT
Timeout occurred return code.
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.