ROS 2 rclcpp + rcl - rolling  rolling-e7363f10
ROS 2 C++ Client Library with ROS Client Library
logging_rosout.c
1 // Copyright 2018-2019 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/logging_rosout.h"
16 
17 #include <stdarg.h>
18 #include <stdbool.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <string.h>
22 
23 #include "rcl/allocator.h"
24 #include "rcl/common.h"
25 #include "rcl/error_handling.h"
26 #include "rcl/node.h"
27 #include "rcl/publisher.h"
28 #include "rcl/time.h"
29 #include "rcl/types.h"
30 #include "rcl_interfaces/msg/log.h"
31 #include "rcutils/error_handling.h"
32 #include "rcutils/format_string.h"
33 #include "rcutils/logging.h"
34 #include "rcutils/logging_macros.h"
35 #include "rcutils/time.h"
36 #include "rcutils/types/char_array.h"
37 #include "rcutils/types/hash_map.h"
38 #include "rcutils/types/rcutils_ret.h"
39 #include "rosidl_runtime_c/string_functions.h"
40 
41 #define ROSOUT_TOPIC_NAME "/rosout"
42 
43 typedef struct rosout_map_entry_t
44 {
45  rcl_node_t * node;
46  rcl_publisher_t publisher;
48 
49 static rcutils_hash_map_t __logger_map;
50 static bool __is_initialized = false;
51 static rcl_allocator_t __rosout_allocator;
52 
54 {
55  // name is to store the allocated memory, and then finalize it at the end
56  char * name;
57  // count is something like a reference count that removes the entry if it is 0
58  uint64_t * count;
60 
61 static rcutils_hash_map_t __sublogger_map;
62 
64 {
65  RCL_CHECK_ARGUMENT_FOR_NULL(allocator, RCL_RET_INVALID_ARGUMENT);
66  rcl_ret_t status = RCL_RET_OK;
67  if (__is_initialized) {
68  return RCL_RET_OK;
69  }
70  __logger_map = rcutils_get_zero_initialized_hash_map();
71  status = rcl_convert_rcutils_ret_to_rcl_ret(
72  rcutils_hash_map_init(
73  &__logger_map, 2, sizeof(const char *), sizeof(rosout_map_entry_t),
74  rcutils_hash_map_string_hash_func, rcutils_hash_map_string_cmp_func, allocator));
75  if (RCL_RET_OK != status) {
76  return status;
77  }
78 
79  __sublogger_map = rcutils_get_zero_initialized_hash_map();
80  status = rcl_convert_rcutils_ret_to_rcl_ret(
81  rcutils_hash_map_init(
82  &__sublogger_map, 2, sizeof(const char *), sizeof(rosout_sublogger_entry_t),
83  rcutils_hash_map_string_hash_func, rcutils_hash_map_string_cmp_func, allocator));
84  if (RCL_RET_OK != status) {
85  rcl_ret_t fini_status = rcl_convert_rcutils_ret_to_rcl_ret(
86  rcutils_hash_map_fini(&__logger_map));
87  if (RCL_RET_OK != fini_status) {
88  RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to finalize the hash map for logger: ");
89  RCUTILS_SAFE_FWRITE_TO_STDERR(rcl_get_error_string().str);
90  rcl_reset_error();
91  RCUTILS_SAFE_FWRITE_TO_STDERR("\n");
92  }
93  return status;
94  }
95 
96  __rosout_allocator = *allocator;
97  __is_initialized = true;
98 
99  return status;
100 }
101 
102 static rcl_ret_t
103 _rcl_logging_rosout_remove_logger_map(rcl_node_t * node)
104 {
105  RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
106 
107  rcl_ret_t status = RCL_RET_OK;
108  char * previous_key = NULL;
109  char * key = NULL;
110  rosout_map_entry_t entry;
111  rcutils_ret_t hashmap_ret = rcutils_hash_map_get_next_key_and_data(
112  &__logger_map, NULL, &key, &entry);
113  while (RCL_RET_OK == status && RCUTILS_RET_OK == hashmap_ret) {
114  if (entry.node == node) {
115  status = rcl_convert_rcutils_ret_to_rcl_ret(rcutils_hash_map_unset(&__logger_map, &key));
116  previous_key = NULL;
117  } else {
118  previous_key = key;
119  }
120  if (RCL_RET_OK == status) {
121  hashmap_ret = rcutils_hash_map_get_next_key_and_data(
122  &__logger_map, previous_key ? &previous_key : NULL, &key, &entry);
123  }
124  }
125  return RCL_RET_OK;
126 }
127 
128 static rcl_ret_t
129 _rcl_logging_rosout_clear_logger_map_item(void * value)
130 {
131  rosout_map_entry_t * entry = (rosout_map_entry_t *)value;
132  // Teardown publisher
133  rcl_ret_t status = rcl_publisher_fini(&entry->publisher, entry->node);
134  if (RCL_RET_OK == status) {
135  // delete all entries using this node
136  status = rcl_convert_rcutils_ret_to_rcl_ret(
137  _rcl_logging_rosout_remove_logger_map(entry->node));
138  }
139 
140  return status;
141 }
142 
143 static rcl_ret_t
144 _rcl_logging_rosout_clear_sublogger_map_item(void * value)
145 {
147  rcl_ret_t status = rcl_convert_rcutils_ret_to_rcl_ret(
148  rcutils_hash_map_unset(&__sublogger_map, &entry->name));
149  __rosout_allocator.deallocate(entry->name, __rosout_allocator.state);
150  __rosout_allocator.deallocate(entry->count, __rosout_allocator.state);
151 
152  return status;
153 }
154 
155 static rcl_ret_t
156 _rcl_logging_rosout_clear_hashmap(
157  rcutils_hash_map_t * map, rcl_ret_t (* predicate)(void *), void * entry)
158 {
159  rcl_ret_t status = RCL_RET_OK;
160  char * key = NULL;
161 
162  rcutils_ret_t hashmap_ret = rcutils_hash_map_get_next_key_and_data(
163  map, NULL, &key, entry);
164  while (RCUTILS_RET_OK == hashmap_ret) {
165  status = predicate(entry);
166  if (RCL_RET_OK != status) {
167  break;
168  }
169 
170  hashmap_ret = rcutils_hash_map_get_next_key_and_data(map, NULL, &key, entry);
171  }
172  if (RCUTILS_RET_HASH_MAP_NO_MORE_ENTRIES != hashmap_ret) {
173  status = rcl_convert_rcutils_ret_to_rcl_ret(hashmap_ret);
174  }
175 
176  if (RCL_RET_OK == status) {
177  status = rcl_convert_rcutils_ret_to_rcl_ret(rcutils_hash_map_fini(map));
178  }
179 
180  return status;
181 }
182 
184 {
185  if (!__is_initialized) {
186  return RCL_RET_OK;
187  }
188  rcl_ret_t status = RCL_RET_OK;
189  rosout_map_entry_t entry;
190  rosout_sublogger_entry_t sublogger_entry;
191 
192  status = _rcl_logging_rosout_clear_hashmap(
193  &__logger_map, _rcl_logging_rosout_clear_logger_map_item, &entry);
194  if (RCL_RET_OK != status) {
195  return status;
196  }
197 
198  status = _rcl_logging_rosout_clear_hashmap(
199  &__sublogger_map, _rcl_logging_rosout_clear_sublogger_map_item, &sublogger_entry);
200  if (RCL_RET_OK != status) {
201  return status;
202  }
203 
204  __is_initialized = false;
205 
206  return status;
207 }
208 
210 {
211  if (!__is_initialized) {
212  return RCL_RET_OK;
213  }
214 
215  const char * logger_name = NULL;
216  rosout_map_entry_t new_entry;
217  rcl_ret_t status = RCL_RET_OK;
218 
219  // Verify input and make sure it's not already initialized
220  RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_NODE_INVALID);
221  logger_name = rcl_node_get_logger_name(node);
222  if (NULL == logger_name) {
223  // rcl_node_get_logger_name already set the error
224  return RCL_RET_ERROR;
225  }
226  if (rcutils_hash_map_key_exists(&__logger_map, &logger_name)) {
227  // @TODO(nburek) Update behavior to either enforce unique names or work with non-unique
228  // names based on the outcome here: https://github.com/ros2/design/issues/187
229  const char * node_name = rcl_node_get_name(node);
230  if (NULL == node_name) {
231  node_name = "unknown node";
232  }
233 
234  RCUTILS_LOG_WARN_NAMED(
235  "rcl.logging_rosout",
236  "Publisher already registered for node name: '%s'. If this is due to multiple nodes "
237  "with the same name then all logs for the logger named '%s' will go out over "
238  "the existing publisher. As soon as any node with that name is destructed "
239  "it will unregister the publisher, preventing any further logs for that name from "
240  "being published on the rosout topic.",
241  node_name,
242  logger_name);
243  return RCL_RET_OK;
244  }
245 
246  // Create a new Log message publisher on the node
247  const rosidl_message_type_support_t * type_support =
248  rosidl_typesupport_c__get_message_type_support_handle__rcl_interfaces__msg__Log();
250 
251  // Late joining subscriptions get the user's setting of rosout qos options.
252  const rcl_node_options_t * node_options = rcl_node_get_options(node);
253  RCL_CHECK_FOR_NULL_WITH_MSG(node_options, "Node options was null.", return RCL_RET_ERROR);
254 
255  options.qos = node_options->rosout_qos;
256  options.allocator = node_options->allocator;
257  new_entry.publisher = rcl_get_zero_initialized_publisher();
258  status =
259  rcl_publisher_init(&new_entry.publisher, node, type_support, ROSOUT_TOPIC_NAME, &options);
260 
261  // Add the new publisher to the map
262  if (RCL_RET_OK == status) {
263  new_entry.node = node;
264  status = rcl_convert_rcutils_ret_to_rcl_ret(
265  rcutils_hash_map_set(&__logger_map, &logger_name, &new_entry));
266  if (RCL_RET_OK != status) {
267  RCL_SET_ERROR_MSG("Failed to add publisher to map.");
268  // We failed to add to the map so destroy the publisher that we created
269  rcl_ret_t fini_status = rcl_publisher_fini(&new_entry.publisher, new_entry.node);
270  // ignore the return status in favor of the failure from set
271  RCL_UNUSED(fini_status);
272  }
273  }
274 
275  return status;
276 }
277 
279 {
280  if (!__is_initialized) {
281  return RCL_RET_OK;
282  }
283 
284  rosout_map_entry_t entry;
285  const char * logger_name = NULL;
286  rcl_ret_t status = RCL_RET_OK;
287 
288  // Verify input and make sure it's initialized
289  RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_NODE_INVALID);
290  logger_name = rcl_node_get_logger_name(node);
291  if (NULL == logger_name) {
292  return RCL_RET_ERROR;
293  }
294  if (!rcutils_hash_map_key_exists(&__logger_map, &logger_name)) {
295  return RCL_RET_OK;
296  }
297 
298  // fini the publisher and remove the entry from the map
299  status = rcl_convert_rcutils_ret_to_rcl_ret(
300  rcutils_hash_map_get(&__logger_map, &logger_name, &entry));
301  if (RCL_RET_OK == status && node == entry.node) {
302  status = rcl_publisher_fini(&entry.publisher, entry.node);
303  }
304  if (RCL_RET_OK == status) {
305  // delete all entries using this node
306  status = rcl_convert_rcutils_ret_to_rcl_ret(_rcl_logging_rosout_remove_logger_map(entry.node));
307  }
308 
309  return status;
310 }
311 
312 static void shallow_assign(rosidl_runtime_c__String * target, const char * source)
313 {
314  target->data = (char *)source;
315  size_t len = strlen(source);
316  target->size = len;
317  target->capacity = len + 1;
318 }
319 
321  const rcutils_log_location_t * location,
322  int severity,
323  const char * name,
324  rcutils_time_point_value_t timestamp,
325  const char * format,
326  va_list * args)
327 {
328  rosout_map_entry_t entry;
329  rcl_ret_t status = RCL_RET_OK;
330  if (!__is_initialized) {
331  return;
332  }
333  rcutils_ret_t rcutils_ret = rcutils_hash_map_get(&__logger_map, &name, &entry);
334  if (RCUTILS_RET_OK == rcutils_ret) {
335  char msg_buf[1024] = "";
336  rcutils_char_array_t msg_array = {
337  .buffer = msg_buf,
338  .owns_buffer = false,
339  .buffer_length = 0u,
340  .buffer_capacity = sizeof(msg_buf),
341  .allocator = __rosout_allocator
342  };
343 
344  status = rcl_convert_rcutils_ret_to_rcl_ret(
345  rcutils_char_array_vsprintf(&msg_array, format, *args));
346  if (RCL_RET_OK != status) {
347  RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to format log string: ");
348  RCUTILS_SAFE_FWRITE_TO_STDERR(rcl_get_error_string().str);
349  rcl_reset_error();
350  RCUTILS_SAFE_FWRITE_TO_STDERR("\n");
351  } else {
352  rcl_interfaces__msg__Log log_message;
353  log_message.stamp.sec = (int32_t) RCL_NS_TO_S(timestamp);
354  log_message.stamp.nanosec = (timestamp % RCL_S_TO_NS(1));
355  log_message.level = severity;
356  log_message.line = (int32_t) location->line_number;
357  shallow_assign(&log_message.name, name);
358  shallow_assign(&log_message.msg, msg_array.buffer);
359  shallow_assign(&log_message.file, location->file_name);
360  shallow_assign(&log_message.function, location->function_name);
361  status = rcl_publish(&entry.publisher, &log_message, NULL);
362  if (RCL_RET_OK != status) {
363  RCUTILS_SAFE_FWRITE_TO_STDERR("Failed to publish log message to rosout: ");
364  RCUTILS_SAFE_FWRITE_TO_STDERR(rcl_get_error_string().str);
365  rcl_reset_error();
366  RCUTILS_SAFE_FWRITE_TO_STDERR("\n");
367  }
368  }
369 
370  status = rcl_convert_rcutils_ret_to_rcl_ret(rcutils_char_array_fini(&msg_array));
371  if (RCL_RET_OK != status) {
372  RCUTILS_SAFE_FWRITE_TO_STDERR("failed to fini char_array: ");
373  RCUTILS_SAFE_FWRITE_TO_STDERR(rcl_get_error_string().str);
374  rcl_reset_error();
375  RCUTILS_SAFE_FWRITE_TO_STDERR("\n");
376  }
377  }
378 }
379 
380 static rcl_ret_t
381 _rcl_logging_rosout_get_full_sublogger_name(
382  const char * logger_name, const char * sublogger_name, char ** full_sublogger_name)
383 {
384  RCL_CHECK_ARGUMENT_FOR_NULL(logger_name, RCL_RET_INVALID_ARGUMENT);
385  RCL_CHECK_ARGUMENT_FOR_NULL(sublogger_name, RCL_RET_INVALID_ARGUMENT);
386  RCL_CHECK_ARGUMENT_FOR_NULL(full_sublogger_name, RCL_RET_INVALID_ARGUMENT);
387 
388  if (logger_name[0] == '\0' || sublogger_name[0] == '\0') {
389  RCL_SET_ERROR_MSG("logger name or sub-logger name can't be empty.");
391  }
392 
393  *full_sublogger_name = rcutils_format_string(
394  __rosout_allocator, "%s%s%s",
395  logger_name, RCUTILS_LOGGING_SEPARATOR_STRING, sublogger_name);
396  if (NULL == *full_sublogger_name) {
397  RCL_SET_ERROR_MSG("Failed to allocate a full sublogger name.");
398  return RCL_RET_BAD_ALLOC;
399  }
400 
401  return RCL_RET_OK;
402 }
403 
404 rcl_ret_t
406  const char * logger_name, const char * sublogger_name)
407 {
408  if (!__is_initialized) {
409  return RCL_RET_OK;
410  }
411 
412  rcl_ret_t status = RCL_RET_OK;
413  char * full_sublogger_name = NULL;
414  uint64_t * sublogger_count = NULL;
415  rosout_map_entry_t entry;
416  rosout_sublogger_entry_t sublogger_entry;
417 
418  RCL_CHECK_ARGUMENT_FOR_NULL(logger_name, RCL_RET_INVALID_ARGUMENT);
419  RCL_CHECK_ARGUMENT_FOR_NULL(sublogger_name, RCL_RET_INVALID_ARGUMENT);
420  rcutils_ret_t rcutils_ret = rcutils_hash_map_get(&__logger_map, &logger_name, &entry);
421  if (RCUTILS_RET_OK != rcutils_ret) {
422  if (RCUTILS_RET_NOT_FOUND == rcutils_ret) {
423  RCL_SET_ERROR_MSG_WITH_FORMAT_STRING("Failed to get logger entry for '%s'.", logger_name);
424  }
425  return rcl_convert_rcutils_ret_to_rcl_ret(rcutils_ret);
426  }
427 
428  status =
429  _rcl_logging_rosout_get_full_sublogger_name(logger_name, sublogger_name, &full_sublogger_name);
430  if (RCL_RET_OK != status) {
431  // Error already set
432  return status;
433  }
434 
435  if (rcutils_hash_map_key_exists(&__logger_map, &full_sublogger_name)) {
436  // To get the entry and increase the reference count
437  status = rcl_convert_rcutils_ret_to_rcl_ret(
438  rcutils_hash_map_get(&__sublogger_map, &full_sublogger_name, &sublogger_entry));
439  if (RCL_RET_OK != status) {
440  RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
441  "Failed to get item from sublogger map for '%s'.", full_sublogger_name);
442  goto cleanup;
443  }
444  *sublogger_entry.count += 1;
445  goto cleanup;
446  }
447 
448  status = rcl_convert_rcutils_ret_to_rcl_ret(
449  rcutils_hash_map_set(&__logger_map, &full_sublogger_name, &entry));
450  if (RCL_RET_OK != status) {
451  RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
452  "Failed to add publisher to map for logger '%s'.", full_sublogger_name);
453  goto cleanup;
454  }
455 
456  sublogger_entry.name = full_sublogger_name;
457  sublogger_count = __rosout_allocator.allocate(sizeof(uint64_t), __rosout_allocator.state);
458  if (!sublogger_count) {
459  RCL_SET_ERROR_MSG(
460  "Failed to allocate memory for count of sublogger entry.");
461  goto cleanup;
462  }
463  sublogger_entry.count = sublogger_count;
464  *sublogger_entry.count = 1;
465 
466  status = rcl_convert_rcutils_ret_to_rcl_ret(
467  rcutils_hash_map_set(&__sublogger_map, &full_sublogger_name, &sublogger_entry));
468  if (RCL_RET_OK != status) {
469  // revert the previor set operation for __logger_map
470  rcutils_ret_t rcutils_ret = rcutils_hash_map_unset(&__logger_map, &full_sublogger_name);
471  if (RCUTILS_RET_OK != rcutils_ret) {
472  RCUTILS_SAFE_FWRITE_TO_STDERR("failed to unset hashmap: ");
473  RCUTILS_SAFE_FWRITE_TO_STDERR(rcl_get_error_string().str);
474  rcl_reset_error();
475  RCUTILS_SAFE_FWRITE_TO_STDERR("\n");
476  }
477  goto cleanup_count;
478  }
479 
480  return status;
481 
482 cleanup_count:
483  __rosout_allocator.deallocate(sublogger_count, __rosout_allocator.state);
484 cleanup:
485  __rosout_allocator.deallocate(full_sublogger_name, __rosout_allocator.state);
486  return status;
487 }
488 
489 rcl_ret_t
491  const char * logger_name, const char * sublogger_name)
492 {
493  if (!__is_initialized) {
494  return RCL_RET_OK;
495  }
496 
497  rcl_ret_t status = RCL_RET_OK;
498  char * full_sublogger_name = NULL;
499  rosout_sublogger_entry_t sublogger_entry;
500  RCL_CHECK_ARGUMENT_FOR_NULL(logger_name, RCL_RET_INVALID_ARGUMENT);
501  RCL_CHECK_ARGUMENT_FOR_NULL(sublogger_name, RCL_RET_INVALID_ARGUMENT);
502 
503  status =
504  _rcl_logging_rosout_get_full_sublogger_name(logger_name, sublogger_name, &full_sublogger_name);
505  if (RCL_RET_OK != status) {
506  // Error already set
507  return status;
508  }
509 
510  if (!rcutils_hash_map_key_exists(&__logger_map, &full_sublogger_name)) {
511  status = RCL_RET_NOT_FOUND;
512  RCL_SET_ERROR_MSG_WITH_FORMAT_STRING("Logger for '%s' not found.", full_sublogger_name);
513  goto cleanup;
514  }
515 
516  // remove the entry from the map
517  status = rcl_convert_rcutils_ret_to_rcl_ret(
518  rcutils_hash_map_get(&__sublogger_map, &full_sublogger_name, &sublogger_entry));
519  if (RCL_RET_OK != status) {
520  RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
521  "Failed to get item from sublogger map for '%s'.", full_sublogger_name);
522  goto cleanup;
523  }
524 
525  *sublogger_entry.count -= 1;
526  if (*sublogger_entry.count == 0) {
527  status = rcl_convert_rcutils_ret_to_rcl_ret(
528  rcutils_hash_map_unset(&__logger_map, &full_sublogger_name));
529  if (RCL_RET_OK == status) {
530  status = rcl_convert_rcutils_ret_to_rcl_ret(
531  rcutils_hash_map_unset(&__sublogger_map, &full_sublogger_name));
532  __rosout_allocator.deallocate(sublogger_entry.name, __rosout_allocator.state);
533  __rosout_allocator.deallocate(sublogger_entry.count, __rosout_allocator.state);
534  }
535  }
536 
537 cleanup:
538  __rosout_allocator.deallocate(full_sublogger_name, __rosout_allocator.state);
539  return status;
540 }
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
Definition: allocator.h:31
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_logging_rosout_add_sublogger(const char *logger_name, const char *sublogger_name)
Add a subordinate logger based on a logger.
RCL_PUBLIC void rcl_logging_rosout_output_handler(const rcutils_log_location_t *location, int severity, const char *name, rcutils_time_point_value_t timestamp, const char *format, va_list *args)
The output handler outputs log messages to rosout topics.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_logging_rosout_init_publisher_for_node(rcl_node_t *node)
Creates a rosout publisher for a node and registers it to be used by the logging system.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_logging_rosout_fini_publisher_for_node(rcl_node_t *node)
Deregisters a rosout publisher for a node and cleans up allocated resources.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_logging_rosout_fini(void)
Uninitializes the rcl_logging_rosout features.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_logging_rosout_init(const rcl_allocator_t *allocator)
Initializes the rcl_logging_rosout features.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_logging_rosout_remove_sublogger(const char *logger_name, const char *sublogger_name)
Remove a subordinate logger and cleans up allocated resources.
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:447
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:420
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:497
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publisher_init(rcl_publisher_t *publisher, const rcl_node_t *node, const rosidl_message_type_support_t *type_support, const char *topic_name, const rcl_publisher_options_t *options)
Initialize a rcl publisher.
Definition: publisher.c:56
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publish(const rcl_publisher_t *publisher, const void *ros_message, rmw_publisher_allocation_t *allocation)
Publish a ROS message on a topic using a publisher.
Definition: publisher.c:279
RCL_PUBLIC RCL_WARN_UNUSED rcl_publisher_options_t rcl_publisher_get_default_options(void)
Return the default publisher options in a rcl_publisher_options_t.
Definition: publisher.c:228
RCL_PUBLIC RCL_WARN_UNUSED rcl_publisher_t rcl_get_zero_initialized_publisher(void)
Return a rcl_publisher_t struct with members set to NULL.
Definition: publisher.c:48
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publisher_fini(rcl_publisher_t *publisher, rcl_node_t *node)
Finalize a rcl_publisher_t.
Definition: publisher.c:187
Structure which encapsulates the options for creating a rcl_node_t.
Definition: node_options.h:41
rmw_qos_profile_t rosout_qos
Middleware quality of service settings for /rosout.
Definition: node_options.h:62
rcl_allocator_t allocator
If true, no parameter infrastructure will be setup.
Definition: node_options.h:50
Structure which encapsulates a ROS Node.
Definition: node.h:49
Options available for a rcl publisher.
Definition: publisher.h:51
rmw_qos_profile_t qos
Middleware quality of service settings for the publisher.
Definition: publisher.h:53
rcl_allocator_t allocator
Custom allocator for the publisher, used for incidental allocations.
Definition: publisher.h:56
Structure which encapsulates a ROS Publisher.
Definition: publisher.h:44
#define RCL_NS_TO_S
Convenience macro to convert nanoseconds to seconds.
Definition: time.h:42
#define RCL_S_TO_NS
Convenience macro to convert seconds to nanoseconds.
Definition: time.h:35
#define RCL_RET_NOT_FOUND
Resource not found.
Definition: types.h:56
#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_NODE_INVALID
Invalid rcl_node_t given return code.
Definition: types.h:60
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:25