ROS 2 rclcpp + rcl - lyrical  lyrical
ROS 2 C++ Client Library with ROS Client Library
node.c
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 "rcl/node.h"
16 
17 #include <limits.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include "rcl/arguments.h"
23 #include "rcl/error_handling.h"
24 #include "rcl/init_options.h"
25 #include "rcl/logging.h"
26 #include "rcl/logging_rosout.h"
27 #include "rcl/node_type_cache.h"
28 #include "rcl/rcl.h"
29 #include "rcl/remap.h"
30 #include "rcl/security.h"
31 
32 #include "rcutils/env.h"
33 #include "rcutils/filesystem.h"
34 #include "rcutils/find.h"
35 #include "rcutils/format_string.h"
36 #include "rcutils/logging_macros.h"
37 #include "rcutils/macros.h"
38 #include "rcutils/repl_str.h"
39 #include "rcutils/snprintf.h"
40 #include "rcutils/strdup.h"
41 #include "rcutils/types/hash_map.h"
42 
43 #include "rmw/error_handling.h"
44 #include "rmw/security_options.h"
45 #include "rmw/rmw.h"
46 #include "rmw/validate_namespace.h"
47 #include "rmw/validate_node_name.h"
48 #include "rosidl_runtime_c/string_functions.h"
49 #include "rosidl_runtime_c/type_description/type_description__functions.h"
50 #include "rosidl_runtime_c/type_description/type_source__functions.h"
51 #include "tracetools/tracetools.h"
52 #include "type_description_interfaces/srv/get_type_description.h"
53 
54 #include "./context_impl.h"
55 #include "./node_impl.h"
56 
57 const char * const RCL_DISABLE_LOANED_MESSAGES_ENV_VAR = "ROS_DISABLE_LOANED_MESSAGES";
58 
60 
69 const char * rcl_create_node_logger_name(
70  const char * node_name,
71  const char * node_namespace,
72  const rcl_allocator_t * allocator)
73 {
74  // If the namespace is the root namespace ("/"), the logger name is just the node name.
75  if (strlen(node_namespace) == 1) {
76  return rcutils_strdup(node_name, *allocator);
77  }
78 
79  // Convert the forward slashes in the namespace to the separator used for logger names.
80  // The input namespace has already been expanded and therefore will always be absolute,
81  // i.e. it will start with a forward slash, which we want to ignore.
82  const char * ns_with_separators = rcutils_repl_str(
83  node_namespace + 1, // Ignore the leading forward slash.
84  "/", RCUTILS_LOGGING_SEPARATOR_STRING,
85  allocator);
86  if (NULL == ns_with_separators) {
87  return NULL;
88  }
89 
90  // Join the namespace and node name to create the logger name.
91  char * node_logger_name = rcutils_format_string(
92  *allocator, "%s%s%s", ns_with_separators, RCUTILS_LOGGING_SEPARATOR_STRING, node_name);
93  allocator->deallocate((char *)ns_with_separators, allocator->state);
94  return node_logger_name;
95 }
96 
99 {
100  // All members are initialized to 0 or NULL by C99 6.7.8/10.
101  static rcl_node_t null_node;
102  return null_node;
103 }
104 
105 rcl_ret_t
107  rcl_node_t * node,
108  const char * name,
109  const char * namespace_,
110  rcl_context_t * context,
111  const rcl_node_options_t * options)
112 {
113  const rmw_guard_condition_t * rmw_graph_guard_condition = NULL;
114  rcl_guard_condition_options_t graph_guard_condition_options =
116  rcl_ret_t ret;
117  rcl_ret_t fail_ret = RCL_RET_ERROR;
118  char * remapped_node_name = NULL;
119  const char * local_namespace_ = NULL;
120 
121  // Check options and allocator first, so allocator can be used for errors.
122  RCL_CHECK_ARGUMENT_FOR_NULL(options, RCL_RET_INVALID_ARGUMENT);
123  const rcl_allocator_t * allocator = &options->allocator;
124  RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
125 
126  RCL_CHECK_ARGUMENT_FOR_NULL(name, RCL_RET_INVALID_ARGUMENT);
127  RCL_CHECK_ARGUMENT_FOR_NULL(namespace_, RCL_RET_INVALID_ARGUMENT);
128  RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
129  RCUTILS_LOG_DEBUG_NAMED(
130  ROS_PACKAGE_NAME, "Initializing node '%s' in namespace '%s'", name, namespace_);
131  if (node->impl) {
132  RCL_SET_ERROR_MSG("node already initialized, or struct memory was unintialized");
133  return RCL_RET_ALREADY_INIT;
134  }
135  // Make sure rcl has been initialized.
136  RCL_CHECK_FOR_NULL_WITH_MSG(
137  context, "given context in options is NULL", return RCL_RET_INVALID_ARGUMENT);
138  if (!rcl_context_is_valid(context)) {
139  RCL_SET_ERROR_MSG(
140  "the given context is not valid, "
141  "either rcl_init() was not called or rcl_shutdown() was called.");
142  return RCL_RET_NOT_INIT;
143  }
144  // Make sure the node name is valid before allocating memory.
145  int validation_result = 0;
146  ret = rmw_validate_node_name(name, &validation_result, NULL);
147  if (ret != RMW_RET_OK) {
148  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
149  return ret;
150  }
151  if (validation_result != RMW_NODE_NAME_VALID) {
152  const char * msg = rmw_node_name_validation_result_string(validation_result);
153  RCL_SET_ERROR_MSG(msg);
155  }
156 
157  // Process the namespace.
158  if (namespace_[0] == '\0') {
159  // If the namespace is just an empty string, replace with "/"
160  local_namespace_ = rcutils_strdup("/", *allocator);
161  } else if (namespace_[0] == '/') {
162  local_namespace_ = rcutils_strdup(namespace_, *allocator);
163  } else {
164  // If the namespace does not start with a /, add one.
165  local_namespace_ = rcutils_format_string(*allocator, "/%s", namespace_);
166  }
167  RCL_CHECK_FOR_NULL_WITH_MSG(
168  local_namespace_,
169  "failed to format node namespace string",
170  return RCL_RET_BAD_ALLOC);
171 
172  // Make sure the node namespace is valid.
173  validation_result = 0;
174  ret = rmw_validate_namespace(local_namespace_, &validation_result, NULL);
175  if (ret != RMW_RET_OK) {
176  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
177  goto fail;
178  }
179  if (validation_result != RMW_NAMESPACE_VALID) {
180  const char * msg = rmw_namespace_validation_result_string(validation_result);
181  RCL_SET_ERROR_MSG_WITH_FORMAT_STRING("%s, result: %d", msg, validation_result);
182 
184  goto fail;
185  }
186 
187  // Allocate space for the implementation struct.
188  node->impl = (rcl_node_impl_t *)allocator->zero_allocate(
189  1, sizeof(rcl_node_impl_t), allocator->state);
190  RCL_CHECK_FOR_NULL_WITH_MSG(
191  node->impl, "allocating memory failed", ret = RCL_RET_BAD_ALLOC; goto fail);
192  node->impl->options = rcl_node_get_default_options();
193  node->impl->registered_types_by_type_hash = rcutils_get_zero_initialized_hash_map();
194  node->context = context;
195  // Initialize node impl.
196  ret = rcl_node_options_copy(options, &(node->impl->options));
197  if (RCL_RET_OK != ret) {
198  goto fail;
199  }
200 
201  // Remap the node name and namespace if remap rules are given
202  rcl_arguments_t * global_args = NULL;
203  if (node->impl->options.use_global_arguments) {
204  global_args = &(node->context->global_arguments);
205  }
206  ret = rcl_remap_node_name(
207  &(node->impl->options.arguments), global_args, name, *allocator,
208  &remapped_node_name);
209  if (RCL_RET_OK != ret) {
210  goto fail;
211  }
212  if (NULL != remapped_node_name) {
213  name = remapped_node_name;
214  }
215 
216  char * remapped_namespace = NULL;
218  &(node->impl->options.arguments), global_args, name,
219  *allocator, &remapped_namespace);
220  if (RCL_RET_OK != ret) {
221  goto fail;
222  }
223  if (NULL != remapped_namespace) {
224  allocator->deallocate((char *)local_namespace_, allocator->state);
225  local_namespace_ = remapped_namespace;
226  }
227 
228  // compute fully qualfied name of the node.
229  if ('/' == local_namespace_[strlen(local_namespace_) - 1]) {
230  node->impl->fq_name = rcutils_format_string(*allocator, "%s%s", local_namespace_, name);
231  } else {
232  node->impl->fq_name = rcutils_format_string(*allocator, "%s/%s", local_namespace_, name);
233  }
234  RCL_CHECK_FOR_NULL_WITH_MSG(
235  node->impl->fq_name, "creating fully qualified name failed",
236  ret = RCL_RET_BAD_ALLOC; goto fail);
237 
238  // node logger name
239  node->impl->logger_name = rcl_create_node_logger_name(name, local_namespace_, allocator);
240  RCL_CHECK_FOR_NULL_WITH_MSG(
241  node->impl->logger_name, "creating logger name failed", ret = RCL_RET_ERROR; goto fail);
242 
243  RCUTILS_LOG_DEBUG_NAMED(
244  ROS_PACKAGE_NAME, "Using domain ID of '%zu'", context->impl->rmw_context.actual_domain_id);
245 
246  node->impl->rmw_node_handle = rmw_create_node(
247  &(node->context->impl->rmw_context),
248  name, local_namespace_);
249  if (NULL == node->impl->rmw_node_handle) {
250  // Preserve the error set by rmw_create_node rather than overwriting it.
251  RCL_EXPECT_ERROR_IS_SET(RCL_RET_ERROR);
252  ret = RCL_RET_ERROR;
253  goto fail;
254  }
255 
256  // graph guard condition
257  rmw_graph_guard_condition = rmw_node_get_graph_guard_condition(node->impl->rmw_node_handle);
258  if (NULL == rmw_graph_guard_condition) {
259  // Preserve the error set by rmw_node_get_graph_guard_condition.
260  RCL_EXPECT_ERROR_IS_SET(RCL_RET_ERROR);
261  ret = RCL_RET_ERROR;
262  goto fail;
263  }
264 
265  node->impl->graph_guard_condition = (rcl_guard_condition_t *)allocator->allocate(
266  sizeof(rcl_guard_condition_t), allocator->state);
267  RCL_CHECK_FOR_NULL_WITH_MSG(
268  node->impl->graph_guard_condition, "allocating memory failed",
269  ret = RCL_RET_BAD_ALLOC; goto fail);
270  *node->impl->graph_guard_condition = rcl_get_zero_initialized_guard_condition();
271  graph_guard_condition_options.allocator = *allocator;
273  node->impl->graph_guard_condition,
274  rmw_graph_guard_condition,
275  context,
276  graph_guard_condition_options);
277  if (ret != RCL_RET_OK) {
278  // error message already set
279  goto fail;
280  }
281 
282  // To capture all types from builtin topics and services, the type cache needs to be initialized
283  // before any publishers/subscriptions/services/etc can be created
284  ret = rcl_node_type_cache_init(node);
285  if (ret != RCL_RET_OK) {
286  goto fail;
287  }
288 
289  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Node initialized");
290  TRACETOOLS_TRACEPOINT(
292  (const void *)node,
293  (const void *)rcl_node_get_rmw_handle(node),
294  rcl_node_get_name(node),
295  rcl_node_get_namespace(node));
296 
297  allocator->deallocate(remapped_node_name, allocator->state);
298  allocator->deallocate((char *)local_namespace_, allocator->state);
299 
300  return RCL_RET_OK;
301 
302 fail:
303  if (node->impl) {
304  if (NULL != node->impl->registered_types_by_type_hash.impl) {
305  fail_ret = rcl_node_type_cache_fini(node);
306  RCUTILS_LOG_ERROR_EXPRESSION_NAMED(
307  (fail_ret != RCL_RET_OK),
308  ROS_PACKAGE_NAME, "Failed to fini type cache for node: %s", rcl_get_error_string().str);
309  }
310 
311  if (node->impl->graph_guard_condition) {
312  fail_ret = rcl_guard_condition_fini(node->impl->graph_guard_condition);
313  RCUTILS_LOG_ERROR_EXPRESSION_NAMED(
314  fail_ret != RCL_RET_OK, ROS_PACKAGE_NAME,
315  "failed to fini guard condition in error recovery: %s", rcl_get_error_string().str);
316 
317  allocator->deallocate(node->impl->graph_guard_condition, allocator->state);
318  }
319 
320  if (node->impl->rmw_node_handle) {
321  fail_ret = rmw_destroy_node(node->impl->rmw_node_handle);
322  RCUTILS_LOG_ERROR_EXPRESSION_NAMED(
323  fail_ret != RMW_RET_OK, ROS_PACKAGE_NAME,
324  "failed to fini rmw node in error recovery: %s", rmw_get_error_string().str);
325  }
326 
327  allocator->deallocate((char *)node->impl->logger_name, allocator->state);
328 
329  allocator->deallocate((char *)node->impl->fq_name, allocator->state);
330 
331  fail_ret = rcl_node_options_fini(&(node->impl->options));
332  RCUTILS_LOG_ERROR_EXPRESSION_NAMED(
333  fail_ret != RCL_RET_OK, ROS_PACKAGE_NAME,
334  "failed to fini node options: %s", rcl_get_error_string().str);
335 
336  allocator->deallocate(node->impl, allocator->state);
337  }
338 
339  allocator->deallocate(remapped_node_name, allocator->state);
340 
341  allocator->deallocate((char *)local_namespace_, allocator->state);
342 
344 
345  return ret;
346 }
347 
348 rcl_ret_t
350 {
351  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Finalizing node");
352  RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_NODE_INVALID);
353  if (!node->impl) {
354  // Repeat calls to fini or calling fini on a zero initialized node is ok.
355  return RCL_RET_OK;
356  }
357  rcl_allocator_t allocator = node->impl->options.allocator;
358  rcl_ret_t result = RCL_RET_OK;
359  rcl_ret_t rcl_ret = RCL_RET_OK;
360  rcl_ret = rcl_node_type_cache_fini(node);
361  if (rcl_ret != RCL_RET_OK) {
362  RCL_SET_ERROR_MSG("Unable to fini type cache for node.");
363  result = RCL_RET_ERROR;
364  }
365  rmw_ret_t rmw_ret = rmw_destroy_node(node->impl->rmw_node_handle);
366  if (rmw_ret != RMW_RET_OK) {
367  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
368  result = RCL_RET_ERROR;
369  }
370  rcl_ret = rcl_guard_condition_fini(node->impl->graph_guard_condition);
371  if (rcl_ret != RCL_RET_OK) {
372  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
373  result = RCL_RET_ERROR;
374  }
375  allocator.deallocate(node->impl->graph_guard_condition, allocator.state);
376  // assuming that allocate and deallocate are ok since they are checked in init
377  allocator.deallocate((char *)node->impl->logger_name, allocator.state);
378  allocator.deallocate((char *)node->impl->fq_name, allocator.state);
379  if (NULL != node->impl->options.arguments.impl) {
380  rcl_ret_t ret = rcl_arguments_fini(&(node->impl->options.arguments));
381  if (ret != RCL_RET_OK) {
382  return ret;
383  }
384  }
385  allocator.deallocate(node->impl, allocator.state);
386  node->impl = NULL;
387  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Node finalized");
388  return result;
389 }
390 
391 bool
393 {
394  RCL_CHECK_FOR_NULL_WITH_MSG(node, "rcl node pointer is invalid", return false);
395  RCL_CHECK_FOR_NULL_WITH_MSG(node->impl, "rcl node implementation is invalid", return false);
396  RCL_CHECK_FOR_NULL_WITH_MSG(
397  node->impl->rmw_node_handle, "rcl node's rmw handle is invalid", return false);
398  return true;
399 }
400 
401 bool
403 {
404  bool result = rcl_node_is_valid_except_context(node);
405  if (!result) {
406  return result;
407  }
408  if (!rcl_context_is_valid(node->context)) {
409  RCL_SET_ERROR_MSG("rcl node's context is invalid");
410  return false;
411  }
412  return true;
413 }
414 
415 const char *
417 {
419  return NULL; // error already set
420  }
421  return node->impl->rmw_node_handle->name;
422 }
423 
424 const char *
426 {
428  return NULL; // error already set
429  }
430  return node->impl->rmw_node_handle->namespace_;
431 }
432 
433 const char *
435 {
437  return NULL; // error already set
438  }
439  return node->impl->fq_name;
440 }
441 
442 const rcl_node_options_t *
444 {
446  return NULL; // error already set
447  }
448  return &node->impl->options;
449 }
450 
451 rcl_ret_t
452 rcl_node_get_domain_id(const rcl_node_t * node, size_t * domain_id)
453 {
454  if (!rcl_node_is_valid(node)) {
455  return RCL_RET_NODE_INVALID;
456  }
457  RCL_CHECK_ARGUMENT_FOR_NULL(domain_id, RCL_RET_INVALID_ARGUMENT);
458  rcl_ret_t ret = rcl_context_get_domain_id(node->context, domain_id);
459  if (RCL_RET_OK != ret) {
460  return ret;
461  }
462  return RCL_RET_OK;
463 }
464 
465 rmw_node_t *
467 {
469  return NULL; // error already set
470  }
471  return node->impl->rmw_node_handle;
472 }
473 
474 uint64_t
476 {
478  return 0; // error already set
479  }
480  return rcl_context_get_instance_id(node->context);
481 }
482 
483 const rcl_guard_condition_t *
485 {
487  return NULL; // error already set
488  }
489  return node->impl->graph_guard_condition;
490 }
491 
492 const char *
494 {
496  return NULL; // error already set
497  }
498  return node->impl->logger_name;
499 }
500 
501 rcl_ret_t
502 rcl_get_disable_loaned_message(bool * disable_loaned_message)
503 {
504  const char * env_val = NULL;
505  const char * env_error_str = NULL;
506 
507  RCL_CHECK_ARGUMENT_FOR_NULL(disable_loaned_message, RCL_RET_INVALID_ARGUMENT);
508 
509  env_error_str = rcutils_get_env(RCL_DISABLE_LOANED_MESSAGES_ENV_VAR, &env_val);
510  if (NULL != env_error_str) {
511  RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
512  "Error getting env var: '" RCUTILS_STRINGIFY(RCL_DISABLE_LOANED_MESSAGES_ENV_VAR) "': %s\n",
513  env_error_str);
514  return RCL_RET_ERROR;
515  }
516 
517  *disable_loaned_message = (strcmp(env_val, "1") == 0);
518  return RCL_RET_OK;
519 }
520 
522  rcl_node_t * node,
523  const rmw_request_id_t * request_header,
524  const type_description_interfaces__srv__GetTypeDescription_Request * request,
525  type_description_interfaces__srv__GetTypeDescription_Response * response)
526 {
527  rcl_type_info_t type_info;
528  RCL_CHECK_FOR_NULL_WITH_MSG(node, "invalid node handle", return;);
529  RCL_CHECK_FOR_NULL_WITH_MSG(node->impl, "invalid node", return;);
530  RCL_CHECK_FOR_NULL_WITH_MSG(request_header, "invalid request header", return;);
531  RCL_CHECK_FOR_NULL_WITH_MSG(request, "null request pointer", return;);
532  RCL_CHECK_FOR_NULL_WITH_MSG(response, "null response pointer", return;);
533 
534  if (!type_description_interfaces__srv__GetTypeDescription_Response__init(response)) {
535  RCUTILS_LOG_ERROR_NAMED(
536  ROS_PACKAGE_NAME,
537  "Failed to initialize service response.");
538  return;
539  }
540  response->successful = false;
541 
542  rosidl_type_hash_t type_hash;
543  if (RCUTILS_RET_OK !=
544  rosidl_parse_type_hash_string(request->type_hash.data, &type_hash))
545  {
546  RCUTILS_LOG_ERROR_NAMED(
547  ROS_PACKAGE_NAME, "Failed to parse type hash '%s'",
548  request->type_hash.data);
549  rosidl_runtime_c__String__assign(
550  &response->failure_reason,
551  "Failed to parse type hash");
552  return;
553  }
554 
555  if (RCUTILS_RET_OK !=
556  rcl_node_type_cache_get_type_info(node, &type_hash, &type_info))
557  {
558  rosidl_runtime_c__String__assign(
559  &response->failure_reason,
560  "Type not currently in use by this node");
561  return;
562  }
563 
564  if (!type_description_interfaces__msg__TypeDescription__copy(
565  type_info.type_description, &response->type_description))
566  {
567  rosidl_runtime_c__String__assign(
568  &response->failure_reason,
569  "Failed to populate TypeDescription to response.");
570  return;
571  }
572 
573  if (request->include_type_sources) {
574  if (!type_description_interfaces__msg__TypeSource__Sequence__copy(
575  type_info.type_sources, &response->type_sources))
576  {
577  rosidl_runtime_c__String__assign(
578  &response->failure_reason,
579  "Failed to populate TypeSource_Sequence to response.");
580  return;
581  }
582  }
583 
584  response->successful = true;
585 }
586 
588  rcl_service_t * service,
589  const rcl_node_t * node)
590 {
591  RCL_CHECK_ARGUMENT_FOR_NULL(service, RCL_RET_INVALID_ARGUMENT);
592  RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
593  RCL_CHECK_ARGUMENT_FOR_NULL(node->impl, RCL_RET_NODE_INVALID);
594 
595  if (rcl_service_is_valid(service)) {
596  return RCL_RET_ALREADY_INIT;
597  }
598  rcl_reset_error(); // Reset the error message set by rcl_service_is_valid()
599 
600  char * service_name = NULL;
601  const rosidl_service_type_support_t * type_support =
602  ROSIDL_GET_SRV_TYPE_SUPPORT(
603  type_description_interfaces, srv,
604  GetTypeDescription);
606  rcl_allocator_t allocator = node->context->impl->allocator;
607 
608  // Construct service name
610  node, "~/get_type_description",
611  allocator, true, true, &service_name);
612  if (RCL_RET_OK != ret) {
613  RCL_SET_ERROR_MSG(
614  "Failed to construct ~/get_type_description service name");
615  return ret;
616  }
617 
618  // Initialize service
619  ret = rcl_service_init(
620  service, node,
621  type_support, service_name, &service_ops);
622  allocator.deallocate(service_name, allocator.state);
623 
624  return ret;
625 }
#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 RCL_WARN_UNUSED rcl_ret_t rcl_arguments_fini(rcl_arguments_t *args)
Reclaim resources held inside rcl_arguments_t structure.
RCL_PUBLIC RCL_WARN_UNUSED rcl_context_instance_id_t rcl_context_get_instance_id(const rcl_context_t *context)
Returns an unsigned integer that is unique to the given context, or 0 if invalid.
Definition: context.c:76
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_context_get_domain_id(rcl_context_t *context, size_t *domain_id)
Returns the context domain id.
Definition: context.c:83
RCL_PUBLIC RCL_WARN_UNUSED bool rcl_context_is_valid(const rcl_context_t *context)
Return true if the given context is currently valid, otherwise false.
Definition: context.c:94
RCL_PUBLIC RCL_WARN_UNUSED rcl_guard_condition_t rcl_get_zero_initialized_guard_condition(void)
Return a rcl_guard_condition_t struct with members set to NULL.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_guard_condition_fini(rcl_guard_condition_t *guard_condition)
Finalize a rcl_guard_condition_t.
RCL_PUBLIC RCL_WARN_UNUSED rcl_guard_condition_options_t rcl_guard_condition_get_default_options(void)
Return the default options in a rcl_guard_condition_options_t struct.
rcl_ret_t rcl_guard_condition_init_from_rmw(rcl_guard_condition_t *guard_condition, const rmw_guard_condition_t *rmw_guard_condition, rcl_context_t *context, const rcl_guard_condition_options_t options)
Same as rcl_guard_condition_init(), but reusing an existing rmw handle.
RCL_PUBLIC RCL_WARN_UNUSED const rcl_node_options_t * rcl_node_get_options(const rcl_node_t *node)
Return the rcl node options.
Definition: node.c:443
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_type_description_service_init(rcl_service_t *service, const rcl_node_t *node)
Initialize the node's ~/get_type_description service.
Definition: node.c:587
RCL_PUBLIC RCL_WARN_UNUSED rcl_node_t rcl_get_zero_initialized_node(void)
Return a rcl_node_t struct with members initialized to NULL.
Definition: node.c:98
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_name(const rcl_node_t *node)
Return the name of the node.
Definition: node.c:416
RCL_PUBLIC bool rcl_node_is_valid(const rcl_node_t *node)
Return true if the node is valid, else false.
Definition: node.c:402
RCL_PUBLIC rcl_ret_t rcl_get_disable_loaned_message(bool *disable_loaned_message)
Check if loaned message is disabled, according to the environment variable.
Definition: node.c:502
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_fini(rcl_node_t *node)
Finalize a rcl_node_t.
Definition: node.c:349
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_namespace(const rcl_node_t *node)
Return the namespace of the node.
Definition: node.c:425
RCL_PUBLIC RCL_WARN_UNUSED const rcl_guard_condition_t * rcl_node_get_graph_guard_condition(const rcl_node_t *node)
Return a guard condition which is triggered when the ROS graph changes.
Definition: node.c:484
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:466
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_fully_qualified_name(const rcl_node_t *node)
Return the fully qualified name of the node.
Definition: node.c:434
RCL_PUBLIC void rcl_node_type_description_service_handle_request(rcl_node_t *node, const rmw_request_id_t *request_header, const type_description_interfaces__srv__GetTypeDescription_Request *request, type_description_interfaces__srv__GetTypeDescription_Response *response)
Process a single pending request to the GetTypeDescription service.
Definition: node.c:521
RCL_PUBLIC RCL_WARN_UNUSED uint64_t rcl_node_get_rcl_instance_id(const rcl_node_t *node)
Return the associated rcl instance id.
Definition: node.c:475
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_get_domain_id(const rcl_node_t *node, size_t *domain_id)
Return the ROS domain ID that the node is using.
Definition: node.c:452
RCL_PUBLIC RCL_WARN_UNUSED const char * rcl_node_get_logger_name(const rcl_node_t *node)
Return the logger name of the node.
Definition: node.c:493
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_init(rcl_node_t *node, const char *name, const char *namespace_, rcl_context_t *context, const rcl_node_options_t *options)
Initialize a ROS node.
Definition: node.c:106
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:392
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_options_copy(const rcl_node_options_t *options, rcl_node_options_t *options_out)
Copy one options structure into another.
Definition: node_options.c:46
RCL_PUBLIC rcl_node_options_t rcl_node_get_default_options(void)
Return the default node options in a rcl_node_options_t.
Definition: node_options.c:32
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_node_options_fini(rcl_node_options_t *options)
Finalize the given node_options.
Definition: node_options.c:73
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_remap_node_namespace(const rcl_arguments_t *local_arguments, const rcl_arguments_t *global_arguments, const char *node_name, rcl_allocator_t allocator, char **output_namespace)
Remap a namespace based on given rules.
Definition: remap.c:313
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_remap_node_name(const rcl_arguments_t *local_arguments, const rcl_arguments_t *global_arguments, const char *node_name, rcl_allocator_t allocator, char **output_name)
Remap a node name based on given rules.
Definition: remap.c:293
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:76
RCL_PUBLIC bool rcl_service_is_valid(const rcl_service_t *service)
Check that the service is valid.
Definition: service.c:416
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:277
Hold output of parsing command line arguments.
Definition: arguments.h:36
rcl_arguments_impl_t * impl
Private implementation pointer.
Definition: arguments.h:38
rmw_context_t rmw_context
rmw context.
Definition: context_impl.h:40
rcl_allocator_t allocator
Allocator used during init and shutdown.
Definition: context_impl.h:32
Encapsulates the non-global state of an init/shutdown cycle.
Definition: context.h:114
rcl_context_impl_t * impl
Implementation specific pointer.
Definition: context.h:120
rcl_arguments_t global_arguments
Global arguments for all nodes which share this context.
Definition: context.h:117
Options available for a rcl guard condition.
rcl_allocator_t allocator
Custom allocator for the guard condition, used for internal allocations.
Handle for a rcl guard condition.
Structure which encapsulates the options for creating a rcl_node_t.
Definition: node_options.h:35
bool use_global_arguments
If false then only use arguments in this struct, otherwise use global arguments also.
Definition: node_options.h:47
rcl_arguments_t arguments
Command line arguments that apply only to this node.
Definition: node_options.h:50
rcl_allocator_t allocator
If true, no parameter infrastructure will be setup.
Definition: node_options.h:44
Structure which encapsulates a ROS Node.
Definition: node.h:45
rcl_node_impl_t * impl
Private implementation pointer.
Definition: node.h:50
rcl_context_t * context
Context associated with this node.
Definition: node.h:47
Options available for a rcl service.
Definition: service.h:50
Structure which encapsulates a ROS Service.
Definition: service.h:43
#define RCL_RET_NODE_INVALID_NAMESPACE
Invalid node namespace return code.
Definition: types.h:63
#define RCL_RET_NOT_INIT
rcl_init() not yet called return code.
Definition: types.h:43
#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_NODE_INVALID
Invalid rcl_node_t given return code.
Definition: types.h:59
#define RCL_RET_NODE_INVALID_NAME
Invalid node name return code.
Definition: types.h:61
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:24