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