22 #include "rcl/error_handling.h"
25 #include "rcutils/allocator.h"
26 #include "rcutils/error_handling.h"
27 #include "rcutils/macros.h"
28 #include "rcutils/time.h"
29 #include "rcutils/types.h"
30 #include "rmw/error_handling.h"
31 #include "rmw/get_node_info_and_types.h"
32 #include "rmw/get_service_names_and_types.h"
33 #include "rmw/get_topic_endpoint_info.h"
34 #include "rmw/get_topic_names_and_types.h"
35 #include "rmw/names_and_types.h"
37 #include "rmw/topic_endpoint_info_array.h"
38 #include "rmw/validate_namespace.h"
39 #include "rmw/validate_node_name.h"
44 __validate_node_name_and_namespace(
45 const char * node_name,
46 const char * node_namespace)
48 int validation_result = 0;
49 rmw_ret_t rmw_ret = rmw_validate_namespace(node_namespace, &validation_result, NULL);
51 if (RMW_RET_OK != rmw_ret) {
52 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
53 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
55 if (validation_result != RMW_NAMESPACE_VALID) {
56 const char * msg = rmw_namespace_validation_result_string(validation_result);
57 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"%s, result: %d", msg, validation_result);
61 validation_result = 0;
62 rmw_ret = rmw_validate_node_name(node_name, &validation_result, NULL);
63 if (RMW_RET_OK != rmw_ret) {
64 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
65 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
67 if (RMW_NODE_NAME_VALID != validation_result) {
68 const char * msg = rmw_node_name_validation_result_string(validation_result);
69 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"%s, result: %d", msg, validation_result);
81 const char * node_name,
82 const char * node_namespace,
93 const char * valid_namespace =
"/";
94 if (strlen(node_namespace) > 0) {
95 valid_namespace = node_namespace;
97 rmw_ret_t rmw_ret = rmw_names_and_types_check_zero(topic_names_and_types);
98 if (RMW_RET_OK != rmw_ret) {
99 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
101 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
105 rcutils_allocator_t rcutils_allocator = *allocator;
106 rmw_ret = rmw_get_publisher_names_and_types_by_node(
112 topic_names_and_types
114 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
122 const char * node_name,
123 const char * node_namespace,
134 const char * valid_namespace =
"/";
135 if (strlen(node_namespace) > 0) {
136 valid_namespace = node_namespace;
139 rmw_ret = rmw_names_and_types_check_zero(topic_names_and_types);
140 if (rmw_ret != RMW_RET_OK) {
141 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
143 rcutils_allocator_t rcutils_allocator = *allocator;
144 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
148 rmw_ret = rmw_get_subscriber_names_and_types_by_node(
154 topic_names_and_types
156 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
163 const char * node_name,
164 const char * node_namespace,
175 const char * valid_namespace =
"/";
176 if (strlen(node_namespace) > 0) {
177 valid_namespace = node_namespace;
180 rmw_ret = rmw_names_and_types_check_zero(service_names_and_types);
181 if (rmw_ret != RMW_RET_OK) {
182 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
184 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
188 rcutils_allocator_t rcutils_allocator = *allocator;
189 rmw_ret = rmw_get_service_names_and_types_by_node(
194 service_names_and_types
196 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
203 const char * node_name,
204 const char * node_namespace,
215 const char * valid_namespace =
"/";
216 if (strlen(node_namespace) > 0) {
217 valid_namespace = node_namespace;
220 rmw_ret = rmw_names_and_types_check_zero(service_names_and_types);
221 if (rmw_ret != RMW_RET_OK) {
222 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
224 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
228 rcutils_allocator_t rcutils_allocator = *allocator;
229 rmw_ret = rmw_get_client_names_and_types_by_node(
234 service_names_and_types
236 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
252 rmw_ret = rmw_names_and_types_check_zero(topic_names_and_types);
253 if (rmw_ret != RMW_RET_OK) {
254 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
256 rcutils_allocator_t rcutils_allocator = *allocator;
257 rmw_ret = rmw_get_topic_names_and_types(
261 topic_names_and_types
263 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
278 rmw_ret = rmw_names_and_types_check_zero(service_names_and_types);
279 if (rmw_ret != RMW_RET_OK) {
280 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
282 rcutils_allocator_t rcutils_allocator = *allocator;
283 rmw_ret = rmw_get_service_names_and_types(
286 service_names_and_types
288 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
301 rmw_ret_t rmw_ret = rmw_names_and_types_init(names_and_types, size, allocator);
302 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
311 rmw_ret_t rmw_ret = rmw_names_and_types_fini(topic_names_and_types);
312 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
319 rcutils_string_array_t * node_names,
320 rcutils_string_array_t * node_namespaces)
326 if (node_names->size != 0) {
327 RCL_SET_ERROR_MSG(
"node_names size is not zero");
330 if (node_names->data) {
331 RCL_SET_ERROR_MSG(
"node_names is not null");
335 if (node_namespaces->size != 0) {
336 RCL_SET_ERROR_MSG(
"node_namespaces size is not zero");
339 if (node_namespaces->data) {
340 RCL_SET_ERROR_MSG(
"node_namespaces is not null");
344 rmw_ret_t rmw_ret = rmw_get_node_names(
349 if (RMW_RET_OK != rmw_ret) {
350 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
354 for (
size_t i = 0u; i < node_names->size; ++i) {
355 if (!node_names->data[i]) {
356 RCL_SET_ERROR_MSG(
"NULL node name returned by the RMW layer");
359 if (!strcmp(node_names->data[i],
"")) {
360 RCL_SET_ERROR_MSG(
"empty node name returned by the RMW layer");
365 for (
size_t i = 0u; i < node_namespaces->size; ++i) {
366 if (!node_namespaces->data[i]) {
367 RCL_SET_ERROR_MSG(
"NULL node namespace returned by the RMW layer");
378 rcutils_string_array_t * node_names,
379 rcutils_string_array_t * node_namespaces,
380 rcutils_string_array_t * enclaves)
386 if (node_names->size != 0) {
387 RCL_SET_ERROR_MSG(
"node_names size is not zero");
390 if (node_names->data) {
391 RCL_SET_ERROR_MSG(
"node_names is not null");
395 if (node_namespaces->size != 0) {
396 RCL_SET_ERROR_MSG(
"node_namespaces size is not zero");
399 if (node_namespaces->data) {
400 RCL_SET_ERROR_MSG(
"node_namespaces is not null");
404 if (enclaves->size != 0) {
405 RCL_SET_ERROR_MSG(
"enclaves size is not zero");
408 if (enclaves->data) {
409 RCL_SET_ERROR_MSG(
"enclaves is not null");
413 rmw_ret_t rmw_ret = rmw_get_node_names_with_enclaves(
418 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
424 const char * topic_name,
437 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
443 const char * topic_name,
456 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
459 typedef rcl_ret_t (* count_entities_func_t)(
461 const char * topic_name,
465 _rcl_wait_for_entities(
468 const char * topic_name,
469 const size_t expected_count,
470 rcutils_duration_value_t timeout,
472 count_entities_func_t count_entities_func)
486 ret = count_entities_func(node, topic_name, &count);
491 if (expected_count <= count) {
499 &wait_set, 0, 1, 0, 0, 0, 0, node->
context, *allocator);
506 if (!guard_condition) {
521 rcutils_time_point_value_t start;
522 rcutils_ret_t time_ret = rcutils_system_time_now(&start);
523 if (time_ret != RCUTILS_RET_OK) {
524 rcutils_error_string_t error = rcutils_get_error_string();
525 rcutils_reset_error();
526 RCL_SET_ERROR_MSG(error.str);
535 wait_ret =
rcl_wait(&wait_set, timeout);
543 ret = count_entities_func(node, topic_name, &count);
548 if (expected_count <= count) {
555 rcutils_time_point_value_t now;
556 time_ret = rcutils_system_time_now(&now);
557 if (time_ret != RCUTILS_RET_OK) {
558 rcutils_error_string_t error = rcutils_get_error_string();
559 rcutils_reset_error();
560 RCL_SET_ERROR_MSG(error.str);
564 timeout = timeout - (now - start);
598 const char * topic_name,
599 const size_t expected_count,
600 rcutils_duration_value_t timeout,
603 return _rcl_wait_for_entities(
617 const char * topic_name,
618 const size_t expected_count,
619 rcutils_duration_value_t timeout,
622 return _rcl_wait_for_entities(
632 typedef rmw_ret_t (* get_topic_endpoint_info_func_t)(
633 const rmw_node_t * node,
634 rcutils_allocator_t * allocator,
635 const char * topic_name,
637 rmw_topic_endpoint_info_array_t * info_array);
640 __rcl_get_info_by_topic(
642 rcutils_allocator_t * allocator,
643 const char * topic_name,
645 rmw_topic_endpoint_info_array_t * info_array,
646 get_topic_endpoint_info_func_t get_topic_endpoint_info)
657 rmw_error_string_t error_string;
658 rmw_ret_t rmw_ret = rmw_topic_endpoint_info_array_check_zero(info_array);
659 if (rmw_ret != RMW_RET_OK) {
660 error_string = rmw_get_error_string();
662 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
663 "rmw_topic_endpoint_info_array_t must be zero initialized: %s,\n"
664 "Use rmw_get_zero_initialized_topic_endpoint_info_array",
666 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
668 rmw_ret = get_topic_endpoint_info(
674 if (rmw_ret != RMW_RET_OK) {
675 error_string = rmw_get_error_string();
677 RCL_SET_ERROR_MSG(error_string.str);
679 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
685 rcutils_allocator_t * allocator,
686 const char * topic_name,
688 rmw_topic_endpoint_info_array_t * publishers_info)
690 return __rcl_get_info_by_topic(
696 rmw_get_publishers_info_by_topic);
702 rcutils_allocator_t * allocator,
703 const char * topic_name,
705 rmw_topic_endpoint_info_array_t * subscriptions_info)
707 return __rcl_get_info_by_topic(
713 rmw_get_subscriptions_info_by_topic);
734 rmw_ret_t rmw_ret = rmw_service_server_is_available(
739 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
#define RCL_CHECK_ALLOCATOR(allocator, fail_statement)
Check that the given allocator is initialized.
#define RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, msg, fail_statement)
Check that the given allocator is initialized, or fail with a message.
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
RCL_PUBLIC RCL_WARN_UNUSED rmw_client_t * rcl_client_get_rmw_handle(const rcl_client_t *client)
Return the rmw client handle.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_subscriptions_info_by_topic(const rcl_node_t *node, rcutils_allocator_t *allocator, const char *topic_name, bool no_mangle, rcl_topic_endpoint_info_array_t *subscriptions_info)
Return a list of all subscriptions to a topic.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_names_and_types_fini(rcl_names_and_types_t *names_and_types)
Finalize a rcl_names_and_types_t object.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_node_names_with_enclaves(const rcl_node_t *node, rcl_allocator_t allocator, rcutils_string_array_t *node_names, rcutils_string_array_t *node_namespaces, rcutils_string_array_t *enclaves)
Return a list of available nodes in the ROS graph, including their enclave names.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_service_names_and_types(const rcl_node_t *node, rcl_allocator_t *allocator, rcl_names_and_types_t *service_names_and_types)
Return a list of service names and their types.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_client_names_and_types_by_node(const rcl_node_t *node, rcl_allocator_t *allocator, const char *node_name, const char *node_namespace, rcl_names_and_types_t *service_names_and_types)
Return a list of service client names and types associated with a node.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_service_server_is_available(const rcl_node_t *node, const rcl_client_t *client, bool *is_available)
Check if a service server is available for the given service client.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_publishers_info_by_topic(const rcl_node_t *node, rcutils_allocator_t *allocator, const char *topic_name, bool no_mangle, rcl_topic_endpoint_info_array_t *publishers_info)
Return a list of all publishers to a topic.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_names_and_types_init(rcl_names_and_types_t *names_and_types, size_t size, rcl_allocator_t *allocator)
Initialize a rcl_names_and_types_t object.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_service_names_and_types_by_node(const rcl_node_t *node, rcl_allocator_t *allocator, const char *node_name, const char *node_namespace, rcl_names_and_types_t *service_names_and_types)
Return a list of service names and types associated with a node.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_subscriber_names_and_types_by_node(const rcl_node_t *node, rcl_allocator_t *allocator, bool no_demangle, const char *node_name, const char *node_namespace, rcl_names_and_types_t *topic_names_and_types)
Return a list of topic names and types for subscriptions associated with a node.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_count_subscribers(const rcl_node_t *node, const char *topic_name, size_t *count)
Return the number of subscriptions on a given topic.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_for_publishers(const rcl_node_t *node, rcl_allocator_t *allocator, const char *topic_name, const size_t count, rcutils_duration_value_t timeout, bool *success)
Wait for there to be a specified number of publishers on a given topic.
rmw_names_and_types_t rcl_names_and_types_t
A structure that contains topic names and types.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_publisher_names_and_types_by_node(const rcl_node_t *node, rcl_allocator_t *allocator, bool no_demangle, const char *node_name, const char *node_namespace, rcl_names_and_types_t *topic_names_and_types)
Return a list of topic names and types for publishers associated with a node.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_for_subscribers(const rcl_node_t *node, rcl_allocator_t *allocator, const char *topic_name, const size_t count, rcutils_duration_value_t timeout, bool *success)
Wait for there to be a specified number of subscribers on a given topic.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_topic_names_and_types(const rcl_node_t *node, rcl_allocator_t *allocator, bool no_demangle, rcl_names_and_types_t *topic_names_and_types)
Return a list of topic names and their types.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_node_names(const rcl_node_t *node, rcl_allocator_t allocator, rcutils_string_array_t *node_names, rcutils_string_array_t *node_namespaces)
Return a list of available nodes in the ROS graph.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_count_publishers(const rcl_node_t *node, const char *topic_name, size_t *count)
Return the number of publishers on a given topic.
RCL_PUBLIC RCL_WARN_UNUSED const rcl_node_options_t * rcl_node_get_options(const rcl_node_t *node)
Return the rcl node options.
RCL_PUBLIC bool rcl_node_is_valid(const rcl_node_t *node)
Return true if the node is valid, else false.
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.
RCL_PUBLIC RCL_WARN_UNUSED rmw_node_t * rcl_node_get_rmw_handle(const rcl_node_t *node)
Return the rmw node handle.
Structure which encapsulates a ROS Client.
Handle for a rcl guard condition.
Structure which encapsulates the options for creating a rcl_node_t.
Structure which encapsulates a ROS Node.
rcl_context_t * context
Context associated with this node.
Container for subscription's, guard condition's, etc to be waited on.
#define RCL_RET_NODE_INVALID_NAMESPACE
Invalid node namespace return code.
#define RCL_RET_OK
Success return code.
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
#define RCL_RET_ERROR
Unspecified error return code.
#define RCL_RET_NODE_INVALID
Invalid rcl_node_t given return code.
#define RCL_RET_TIMEOUT
Timeout occurred return code.
#define RCL_RET_NODE_INVALID_NAME
Invalid node name return code.
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_init(rcl_wait_set_t *wait_set, size_t number_of_subscriptions, size_t number_of_guard_conditions, size_t number_of_timers, size_t number_of_clients, size_t number_of_services, size_t number_of_events, rcl_context_t *context, rcl_allocator_t allocator)
Initialize a rcl wait set with space for items to be waited on.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_clear(rcl_wait_set_t *wait_set)
Remove (sets to NULL) all entities in the wait set.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_fini(rcl_wait_set_t *wait_set)
Finalize a rcl wait set.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait(rcl_wait_set_t *wait_set, int64_t timeout)
Block until the wait set is ready or until the timeout has been exceeded.
RCL_PUBLIC RCL_WARN_UNUSED rcl_wait_set_t rcl_get_zero_initialized_wait_set(void)
Return a rcl_wait_set_t struct with members set to NULL.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_set_add_guard_condition(rcl_wait_set_t *wait_set, const rcl_guard_condition_t *guard_condition, size_t *index)
Store a pointer to the guard condition in the next empty spot in the set.