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