ROS 2 rclcpp + rcl - jazzy  jazzy
ROS 2 C++ Client Library with ROS Client Library
service.c
1 // Copyright 2016 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 #ifdef __cplusplus
16 extern "C"
17 {
18 #endif
19 
20 #include "rcl/service.h"
21 
22 #include <stdio.h>
23 #include <string.h>
24 
25 #include "rcl/error_handling.h"
26 #include "rcl/node.h"
27 #include "rcl/node_type_cache.h"
28 #include "rcl/publisher.h"
29 #include "rcl/time.h"
30 #include "rcl/types.h"
31 #include "rcutils/logging_macros.h"
32 #include "rcutils/macros.h"
33 #include "rmw/error_handling.h"
34 #include "rmw/rmw.h"
35 #include "service_msgs/msg/service_event_info.h"
36 #include "tracetools/tracetools.h"
37 
38 #include "rosidl_runtime_c/service_type_support_struct.h"
39 
40 #include "./common.h"
41 #include "./service_event_publisher.h"
42 
44 {
45  rcl_service_options_t options;
46  rmw_qos_profile_t actual_request_subscription_qos;
47  rmw_qos_profile_t actual_response_publisher_qos;
48  rmw_service_t * rmw_handle;
49  rcl_service_event_publisher_t * service_event_publisher;
50  char * remapped_service_name;
51  rosidl_type_hash_t type_hash;
52 };
53 
56 {
57  static rcl_service_t null_service = {0};
58  return null_service;
59 }
60 
61 static
63 unconfigure_service_introspection(
64  rcl_node_t * node,
65  struct rcl_service_impl_s * service_impl,
66  rcl_allocator_t * allocator)
67 {
68  if (service_impl == NULL) {
69  return RCL_RET_ERROR;
70  }
71 
72  if (service_impl->service_event_publisher == NULL) {
73  return RCL_RET_OK;
74  }
75 
76  rcl_ret_t ret = rcl_service_event_publisher_fini(service_impl->service_event_publisher, node);
77 
78  allocator->deallocate(service_impl->service_event_publisher, allocator->state);
79  service_impl->service_event_publisher = NULL;
80 
81  return ret;
82 }
83 
86  rcl_service_t * service,
87  const rcl_node_t * node,
88  const rosidl_service_type_support_t * type_support,
89  const char * service_name,
90  const rcl_service_options_t * options)
91 {
92  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT);
93  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_ALREADY_INIT);
94  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_NODE_INVALID);
95  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_BAD_ALLOC);
96  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_ERROR);
97  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_SERVICE_NAME_INVALID);
98 
99  // Check options and allocator first, so the allocator can be used in errors.
100  RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT);
101  rcl_allocator_t * allocator = (rcl_allocator_t *)&options->allocator;
102  RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
103 
104  RCL_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT);
105  if (!rcl_node_is_valid(node)) {
106  return RCL_RET_NODE_INVALID; // error already set
107  }
108  RCL_CHECK_ARGUMENT_FOR_NULL(type_support, RCL_RET_INVALID_ARGUMENT);
109  RCL_CHECK_ARGUMENT_FOR_NULL(service_name, RCL_RET_INVALID_ARGUMENT);
110  RCUTILS_LOG_DEBUG_NAMED(
111  ROS_PACKAGE_NAME, "Initializing service for service name '%s'", service_name);
112  if (service->impl) {
113  RCL_SET_ERROR_MSG("service already initialized, or memory was unintialized");
114  return RCL_RET_ALREADY_INIT;
115  }
116 
117  // Allocate space for the implementation struct.
118  service->impl = (rcl_service_impl_t *)allocator->zero_allocate(
119  1, sizeof(rcl_service_impl_t), allocator->state);
120  RCL_CHECK_FOR_NULL_WITH_MSG(
121  service->impl, "allocating memory failed",
122  return RCL_RET_BAD_ALLOC;);
123 
124  // Expand and remap the given service name.
126  node,
127  service_name,
128  *allocator,
129  true,
130  false,
131  &service->impl->remapped_service_name);
132  if (ret != RCL_RET_OK) {
135  } else if (ret != RCL_RET_BAD_ALLOC) {
136  ret = RCL_RET_ERROR;
137  }
138  goto free_service_impl;
139  }
140  RCUTILS_LOG_DEBUG_NAMED(
141  ROS_PACKAGE_NAME, "Expanded and remapped service name '%s'",
142  service->impl->remapped_service_name);
143 
144  if (RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL == options->qos.durability) {
145  RCUTILS_LOG_WARN_NAMED(
146  ROS_PACKAGE_NAME,
147  "Warning: Setting QoS durability to 'transient local' for service servers "
148  "can cause them to receive requests from clients that have since terminated.");
149  }
150  // Fill out implementation struct.
151  // rmw handle (create rmw service)
152  // TODO(wjwwood): pass along the allocator to rmw when it supports it
153  service->impl->rmw_handle = rmw_create_service(
155  type_support,
156  service->impl->remapped_service_name,
157  &options->qos);
158  if (!service->impl->rmw_handle) {
159  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
160  ret = RCL_RET_ERROR;
161  goto free_remapped_service_name;
162  }
163 
164  // get actual qos, and store it
165  rmw_ret_t rmw_ret = rmw_service_request_subscription_get_actual_qos(
166  service->impl->rmw_handle,
167  &service->impl->actual_request_subscription_qos);
168  if (RMW_RET_OK != rmw_ret) {
169  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
170  ret = rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
171  goto destroy_service;
172  }
173 
174  rmw_ret = rmw_service_response_publisher_get_actual_qos(
175  service->impl->rmw_handle,
176  &service->impl->actual_response_publisher_qos);
177  if (RMW_RET_OK != rmw_ret) {
178  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
179  ret = rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
180  goto destroy_service;
181  }
182 
183  // ROS specific namespacing conventions is not retrieved by get_actual_qos
184  service->impl->actual_request_subscription_qos.avoid_ros_namespace_conventions =
185  options->qos.avoid_ros_namespace_conventions;
186  service->impl->actual_response_publisher_qos.avoid_ros_namespace_conventions =
187  options->qos.avoid_ros_namespace_conventions;
188 
189  // options
190  service->impl->options = *options;
191 
192  if (RCL_RET_OK != rcl_node_type_cache_register_type(
193  node, type_support->get_type_hash_func(type_support),
194  type_support->get_type_description_func(type_support),
195  type_support->get_type_description_sources_func(type_support)))
196  {
197  rcutils_reset_error();
198  RCL_SET_ERROR_MSG("Failed to register type for service");
199  ret = RCL_RET_ERROR;
200  goto destroy_service;
201  }
202  service->impl->type_hash = *type_support->get_type_hash_func(type_support);
203 
204  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Service initialized");
205  TRACETOOLS_TRACEPOINT(
207  (const void *)service,
208  (const void *)node,
209  (const void *)service->impl->rmw_handle,
210  service->impl->remapped_service_name);
211 
212  return RCL_RET_OK;
213 
214 destroy_service:
215  rmw_ret = rmw_destroy_service(rcl_node_get_rmw_handle(node), service->impl->rmw_handle);
216  if (RMW_RET_OK != rmw_ret) {
217  RCUTILS_SAFE_FWRITE_TO_STDERR(rmw_get_error_string().str);
218  RCUTILS_SAFE_FWRITE_TO_STDERR("\n");
219  }
220 
221 free_remapped_service_name:
222  allocator->deallocate(service->impl->remapped_service_name, allocator->state);
223  service->impl->remapped_service_name = NULL;
224 
225 free_service_impl:
226  allocator->deallocate(service->impl, allocator->state);
227  service->impl = NULL;
228 
229  return ret;
230 }
231 
232 rcl_ret_t
234 {
235  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_SERVICE_INVALID);
236  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_NODE_INVALID);
237  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT);
238  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_ERROR);
239 
240  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Finalizing service");
241  RCL_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_SERVICE_INVALID);
243  return RCL_RET_NODE_INVALID; // error already set
244  }
245 
246  rcl_ret_t result = RCL_RET_OK;
247  if (service->impl) {
248  rcl_allocator_t allocator = service->impl->options.allocator;
249  rmw_node_t * rmw_node = rcl_node_get_rmw_handle(node);
250  if (!rmw_node) {
252  }
253 
254  rcl_ret_t rcl_ret = unconfigure_service_introspection(node, service->impl, &allocator);
255  if (RCL_RET_OK != rcl_ret) {
256  RCL_SET_ERROR_MSG(rcl_get_error_string().str);
257  result = rcl_ret;
258  }
259 
260  rmw_ret_t ret = rmw_destroy_service(rmw_node, service->impl->rmw_handle);
261  if (ret != RMW_RET_OK) {
262  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
263  result = RCL_RET_ERROR;
264  }
265 
266  if (
267  ROSIDL_TYPE_HASH_VERSION_UNSET != service->impl->type_hash.version &&
268  RCL_RET_OK != rcl_node_type_cache_unregister_type(node, &service->impl->type_hash))
269  {
270  RCUTILS_SAFE_FWRITE_TO_STDERR(rcl_get_error_string().str);
271  result = RCL_RET_ERROR;
272  }
273 
274  allocator.deallocate(service->impl->remapped_service_name, allocator.state);
275  service->impl->remapped_service_name = NULL;
276 
277  allocator.deallocate(service->impl, allocator.state);
278  service->impl = NULL;
279  }
280  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Service finalized");
281  return result;
282 }
283 
286 {
287  // !!! MAKE SURE THAT CHANGES TO THESE DEFAULTS ARE REFLECTED IN THE HEADER DOC STRING
288  static rcl_service_options_t default_options;
289  // Must set the allocator and qos after because they are not a compile time constant.
290  default_options.qos = rmw_qos_profile_services_default;
291  default_options.allocator = rcl_get_default_allocator();
292  return default_options;
293 }
294 
295 const char *
297 {
298  const rcl_service_options_t * options = rcl_service_get_options(service);
299  if (!options) {
300  return NULL;
301  }
302  RCL_CHECK_FOR_NULL_WITH_MSG(service->impl->rmw_handle, "service is invalid", return NULL);
303  return service->impl->rmw_handle->service_name;
304 }
305 
306 const rcl_service_options_t *
308 {
309  if (!rcl_service_is_valid(service)) {
310  return NULL; // error already set
311  }
312  return &service->impl->options;
313 }
314 
315 rmw_service_t *
317 {
318  if (!rcl_service_is_valid(service)) {
319  return NULL; // error already set
320  }
321  return service->impl->rmw_handle;
322 }
323 
324 rcl_ret_t
326  const rcl_service_t * service,
327  rmw_service_info_t * request_header,
328  void * ros_request)
329 {
330  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Service server taking service request");
331  if (!rcl_service_is_valid(service)) {
332  return RCL_RET_SERVICE_INVALID; // error already set
333  }
334  RCL_CHECK_ARGUMENT_FOR_NULL(request_header, RCL_RET_INVALID_ARGUMENT);
335  RCL_CHECK_ARGUMENT_FOR_NULL(ros_request, RCL_RET_INVALID_ARGUMENT);
336  const rcl_service_options_t * options = rcl_service_get_options(service);
337  RCL_CHECK_FOR_NULL_WITH_MSG(options, "Failed to get service options", return RCL_RET_ERROR);
338 
339  bool taken = false;
340  rmw_ret_t ret = rmw_take_request(
341  service->impl->rmw_handle, request_header, ros_request, &taken);
342  if (RMW_RET_OK != ret) {
343  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
344  if (RMW_RET_BAD_ALLOC == ret) {
345  return RCL_RET_BAD_ALLOC;
346  }
347  return RCL_RET_ERROR;
348  }
349  RCUTILS_LOG_DEBUG_NAMED(
350  ROS_PACKAGE_NAME, "Service take request succeeded: %s", taken ? "true" : "false");
351  if (!taken) {
353  }
354  if (service->impl->service_event_publisher != NULL) {
355  rcl_ret_t rclret = rcl_send_service_event_message(
356  service->impl->service_event_publisher,
357  service_msgs__msg__ServiceEventInfo__REQUEST_RECEIVED,
358  ros_request,
359  request_header->request_id.sequence_number,
360  request_header->request_id.writer_guid);
361  if (RCL_RET_OK != rclret) {
362  RCL_SET_ERROR_MSG(rcl_get_error_string().str);
363  return rclret;
364  }
365  }
366  return RCL_RET_OK;
367 }
368 
369 rcl_ret_t
371  const rcl_service_t * service,
372  rmw_request_id_t * request_header,
373  void * ros_request)
374 {
375  rmw_service_info_t header;
376  header.request_id = *request_header;
377  rcl_ret_t ret = rcl_take_request_with_info(service, &header, ros_request);
378  *request_header = header.request_id;
379  return ret;
380 }
381 
382 rcl_ret_t
384  const rcl_service_t * service,
385  rmw_request_id_t * request_header,
386  void * ros_response)
387 {
388  rcl_ret_t ret;
389  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Sending service response");
390  if (!rcl_service_is_valid(service)) {
391  return RCL_RET_SERVICE_INVALID; // error already set
392  }
393  RCL_CHECK_ARGUMENT_FOR_NULL(request_header, RCL_RET_INVALID_ARGUMENT);
394  RCL_CHECK_ARGUMENT_FOR_NULL(ros_response, RCL_RET_INVALID_ARGUMENT);
395  const rcl_service_options_t * options = rcl_service_get_options(service);
396  RCL_CHECK_FOR_NULL_WITH_MSG(options, "Failed to get service options", return RCL_RET_ERROR);
397 
398  ret = rmw_send_response(service->impl->rmw_handle, request_header, ros_response);
399  if (ret != RMW_RET_OK) {
400  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
401  if (ret == RMW_RET_TIMEOUT) {
402  return RCL_RET_TIMEOUT;
403  }
404  return RCL_RET_ERROR;
405  }
406 
407  // publish out the introspected content
408  if (service->impl->service_event_publisher != NULL) {
409  ret = rcl_send_service_event_message(
410  service->impl->service_event_publisher,
411  service_msgs__msg__ServiceEventInfo__RESPONSE_SENT,
412  ros_response,
413  request_header->sequence_number,
414  request_header->writer_guid);
415  if (RCL_RET_OK != ret) {
416  RCL_SET_ERROR_MSG(rcl_get_error_string().str);
417  return ret;
418  }
419  }
420  return RCL_RET_OK;
421 }
422 
423 bool
425 {
426  RCL_CHECK_FOR_NULL_WITH_MSG(service, "service pointer is invalid", return false);
427  RCL_CHECK_FOR_NULL_WITH_MSG(
428  service->impl, "service's implementation is invalid", return false);
429  RCL_CHECK_FOR_NULL_WITH_MSG(
430  service->impl->rmw_handle, "service's rmw handle is invalid", return false);
431  return true;
432 }
433 
434 const rmw_qos_profile_t *
436 {
437  if (!rcl_service_is_valid(service)) {
438  return NULL;
439  }
440  return &service->impl->actual_request_subscription_qos;
441 }
442 
443 const rmw_qos_profile_t *
445 {
446  if (!rcl_service_is_valid(service)) {
447  return NULL;
448  }
449  return &service->impl->actual_response_publisher_qos;
450 }
451 
452 rcl_ret_t
454  const rcl_service_t * service,
455  rcl_event_callback_t callback,
456  const void * user_data)
457 {
458  if (!rcl_service_is_valid(service)) {
459  // error state already set
461  }
462 
463  return rmw_service_set_on_new_request_callback(
464  service->impl->rmw_handle,
465  callback,
466  user_data);
467 }
468 
469 rcl_ret_t
471  rcl_service_t * service,
472  rcl_node_t * node,
473  rcl_clock_t * clock,
474  const rosidl_service_type_support_t * type_support,
475  const rcl_publisher_options_t publisher_options,
476  rcl_service_introspection_state_t introspection_state)
477 {
478  if (!rcl_service_is_valid(service)) {
479  return RCL_RET_SERVICE_INVALID; // error already set
480  }
481  RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
482  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
483  RCL_CHECK_ARGUMENT_FOR_NULL(type_support, RCL_RET_INVALID_ARGUMENT);
484 
485  rcl_allocator_t allocator = service->impl->options.allocator;
486 
487  if (introspection_state == RCL_SERVICE_INTROSPECTION_OFF) {
488  return unconfigure_service_introspection(node, service->impl, &allocator);
489  }
490 
491  if (service->impl->service_event_publisher == NULL) {
492  // We haven't been introspecting, so we need to allocate the service event publisher
493 
494  service->impl->service_event_publisher = allocator.allocate(
495  sizeof(rcl_service_event_publisher_t), allocator.state);
496  RCL_CHECK_FOR_NULL_WITH_MSG(
497  service->impl->service_event_publisher, "allocating memory failed",
498  return RCL_RET_BAD_ALLOC;);
499 
500  *service->impl->service_event_publisher = rcl_get_zero_initialized_service_event_publisher();
501  rcl_ret_t ret = rcl_service_event_publisher_init(
502  service->impl->service_event_publisher, node, clock, publisher_options,
503  service->impl->remapped_service_name, type_support);
504  if (RCL_RET_OK != ret) {
505  allocator.deallocate(service->impl->service_event_publisher, allocator.state);
506  service->impl->service_event_publisher = NULL;
507  return ret;
508  }
509  }
510 
511  return rcl_service_event_publisher_change_state(
512  service->impl->service_event_publisher, introspection_state);
513 }
514 
515 #ifdef __cplusplus
516 }
517 #endif
#define rcl_get_default_allocator
Return a properly initialized rcl_allocator_t with default values.
Definition: allocator.h:37
#define RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, msg, fail_statement)
Check that the given allocator is initialized, or fail with a message.
Definition: allocator.h:56
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
Definition: allocator.h:31
RCL_PUBLIC bool rcl_node_is_valid(const rcl_node_t *node)
Return true if the node is valid, else false.
Definition: node.c:397
RCL_PUBLIC RCL_WARN_UNUSED rmw_node_t * rcl_node_get_rmw_handle(const rcl_node_t *node)
Return the rmw node handle.
Definition: node.c:461
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_resolve_name(const rcl_node_t *node, const char *input_name, rcl_allocator_t allocator, bool is_service, bool only_expand, char **output_name)
Expand a given name into a fully-qualified topic name and apply remapping rules.
RCL_PUBLIC bool rcl_node_is_valid_except_context(const rcl_node_t *node)
Return true if node is valid, except for the context being valid.
Definition: node.c:387
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:435
RCL_PUBLIC RCL_WARN_UNUSED rmw_service_t * rcl_service_get_rmw_handle(const rcl_service_t *service)
Return the rmw service handle.
Definition: service.c:316
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:296
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:444
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.
Definition: service.c:85
RCL_PUBLIC RCL_WARN_UNUSED const rcl_service_options_t * rcl_service_get_options(const rcl_service_t *service)
Return the rcl service options.
Definition: service.c:307
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.
Definition: service.c:470
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_take_request_with_info(const rcl_service_t *service, rmw_service_info_t *request_header, void *ros_request)
Take a pending ROS request using a rcl service.
Definition: service.c:325
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:453
RCL_PUBLIC bool rcl_service_is_valid(const rcl_service_t *service)
Check that the service is valid.
Definition: service.c:424
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_service_fini(rcl_service_t *service, rcl_node_t *node)
Finalize a rcl_service_t.
Definition: service.c:233
RCL_PUBLIC RCL_WARN_UNUSED rcl_service_options_t rcl_service_get_default_options(void)
Return the default service options in a rcl_service_options_t.
Definition: service.c:285
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.
Definition: service.c:55
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:370
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.
Definition: service.c:383
Encapsulation of a time source.
Definition: time.h:138
Structure which encapsulates a ROS Node.
Definition: node.h:45
Options available for a rcl publisher.
Definition: publisher.h:44
Options available for a rcl service.
Definition: service.h:50
rmw_qos_profile_t qos
Middleware quality of service settings for the service.
Definition: service.h:52
rcl_allocator_t allocator
Custom allocator for the service, used for incidental allocations.
Definition: service.h:55
Structure which encapsulates a ROS Service.
Definition: service.h:43
rcl_service_impl_t * impl
Pointer to the service implementation.
Definition: service.h:45
#define RCL_RET_SERVICE_INVALID
Invalid rcl_service_t given return code.
Definition: types.h:85
#define RCL_RET_UNKNOWN_SUBSTITUTION
Topic name substitution is unknown.
Definition: types.h:51
#define RCL_RET_SERVICE_NAME_INVALID
Service name (same as topic name) does not pass validation.
Definition: types.h:49
#define RCL_RET_ALREADY_INIT
rcl_init() already called return code.
Definition: types.h:41
#define RCL_RET_OK
Success return code.
Definition: types.h:27
#define RCL_RET_BAD_ALLOC
Failed to allocate memory return code.
Definition: types.h:33
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
Definition: types.h:35
#define RCL_RET_ERROR
Unspecified error return code.
Definition: types.h:29
#define RCL_RET_SERVICE_TAKE_FAILED
Failed to take a request from the service return code.
Definition: types.h:87
#define RCL_RET_NODE_INVALID
Invalid rcl_node_t given return code.
Definition: types.h:59
#define RCL_RET_TIMEOUT
Timeout occurred return code.
Definition: types.h:31
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:24