26 #include "rcl/error_handling.h"
31 #include "rcutils/allocator.h"
32 #include "rcutils/error_handling.h"
33 #include "rcutils/macros.h"
34 #include "rcutils/time.h"
35 #include "rcutils/types.h"
37 #include "rmw/error_handling.h"
38 #include "rmw/get_node_info_and_types.h"
39 #include "rmw/get_service_endpoint_info.h"
40 #include "rmw/get_service_names_and_types.h"
41 #include "rmw/get_topic_endpoint_info.h"
42 #include "rmw/get_topic_names_and_types.h"
43 #include "rmw/names_and_types.h"
44 #include "rmw/ret_types.h"
46 #include "rmw/service_endpoint_info_array.h"
47 #include "rmw/topic_endpoint_info_array.h"
48 #include "rmw/types.h"
49 #include "rmw/validate_namespace.h"
50 #include "rmw/validate_node_name.h"
55 __validate_node_name_and_namespace(
56 const char * node_name,
57 const char * node_namespace)
59 int validation_result = 0;
60 rmw_ret_t rmw_ret = rmw_validate_namespace(node_namespace, &validation_result, NULL);
62 if (RMW_RET_OK != rmw_ret) {
63 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
64 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
66 if (validation_result != RMW_NAMESPACE_VALID) {
67 const char * msg = rmw_namespace_validation_result_string(validation_result);
68 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"%s, result: %d", msg, validation_result);
72 validation_result = 0;
73 rmw_ret = rmw_validate_node_name(node_name, &validation_result, NULL);
74 if (RMW_RET_OK != rmw_ret) {
75 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
76 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
78 if (RMW_NODE_NAME_VALID != validation_result) {
79 const char * msg = rmw_node_name_validation_result_string(validation_result);
80 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"%s, result: %d", msg, validation_result);
92 const char * node_name,
93 const char * node_namespace,
104 const char * valid_namespace =
"/";
105 if (strlen(node_namespace) > 0) {
106 valid_namespace = node_namespace;
108 rmw_ret_t rmw_ret = rmw_names_and_types_check_zero(topic_names_and_types);
109 if (RMW_RET_OK != rmw_ret) {
110 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
112 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
116 rcutils_allocator_t rcutils_allocator = *allocator;
117 rmw_ret = rmw_get_publisher_names_and_types_by_node(
123 topic_names_and_types
125 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
133 const char * node_name,
134 const char * node_namespace,
145 const char * valid_namespace =
"/";
146 if (strlen(node_namespace) > 0) {
147 valid_namespace = node_namespace;
150 rmw_ret = rmw_names_and_types_check_zero(topic_names_and_types);
151 if (rmw_ret != RMW_RET_OK) {
152 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
154 rcutils_allocator_t rcutils_allocator = *allocator;
155 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
159 rmw_ret = rmw_get_subscriber_names_and_types_by_node(
165 topic_names_and_types
167 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
174 const char * node_name,
175 const char * node_namespace,
186 const char * valid_namespace =
"/";
187 if (strlen(node_namespace) > 0) {
188 valid_namespace = node_namespace;
191 rmw_ret = rmw_names_and_types_check_zero(service_names_and_types);
192 if (rmw_ret != RMW_RET_OK) {
193 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
195 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
199 rcutils_allocator_t rcutils_allocator = *allocator;
200 rmw_ret = rmw_get_service_names_and_types_by_node(
205 service_names_and_types
207 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
214 const char * node_name,
215 const char * node_namespace,
226 const char * valid_namespace =
"/";
227 if (strlen(node_namespace) > 0) {
228 valid_namespace = node_namespace;
231 rmw_ret = rmw_names_and_types_check_zero(service_names_and_types);
232 if (rmw_ret != RMW_RET_OK) {
233 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
235 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
239 rcutils_allocator_t rcutils_allocator = *allocator;
240 rmw_ret = rmw_get_client_names_and_types_by_node(
245 service_names_and_types
247 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
263 rmw_ret = rmw_names_and_types_check_zero(topic_names_and_types);
264 if (rmw_ret != RMW_RET_OK) {
265 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
267 rcutils_allocator_t rcutils_allocator = *allocator;
268 rmw_ret = rmw_get_topic_names_and_types(
272 topic_names_and_types
274 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
289 rmw_ret = rmw_names_and_types_check_zero(service_names_and_types);
290 if (rmw_ret != RMW_RET_OK) {
291 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
293 rcutils_allocator_t rcutils_allocator = *allocator;
294 rmw_ret = rmw_get_service_names_and_types(
297 service_names_and_types
299 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
312 rmw_ret_t rmw_ret = rmw_names_and_types_init(names_and_types, size, allocator);
313 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
322 rmw_ret_t rmw_ret = rmw_names_and_types_fini(topic_names_and_types);
323 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
330 rcutils_string_array_t * node_names,
331 rcutils_string_array_t * node_namespaces)
337 if (node_names->size != 0) {
338 RCL_SET_ERROR_MSG(
"node_names size is not zero");
341 if (node_names->data) {
342 RCL_SET_ERROR_MSG(
"node_names is not null");
346 if (node_namespaces->size != 0) {
347 RCL_SET_ERROR_MSG(
"node_namespaces size is not zero");
350 if (node_namespaces->data) {
351 RCL_SET_ERROR_MSG(
"node_namespaces is not null");
355 rmw_ret_t rmw_ret = rmw_get_node_names(
360 if (RMW_RET_OK != rmw_ret) {
361 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
365 for (
size_t i = 0u; i < node_names->size; ++i) {
366 if (!node_names->data[i]) {
367 RCL_SET_ERROR_MSG(
"NULL node name returned by the RMW layer");
370 if (!strcmp(node_names->data[i],
"")) {
371 RCL_SET_ERROR_MSG(
"empty node name returned by the RMW layer");
376 for (
size_t i = 0u; i < node_namespaces->size; ++i) {
377 if (!node_namespaces->data[i]) {
378 RCL_SET_ERROR_MSG(
"NULL node namespace returned by the RMW layer");
389 rcutils_string_array_t * node_names,
390 rcutils_string_array_t * node_namespaces,
391 rcutils_string_array_t * enclaves)
397 if (node_names->size != 0) {
398 RCL_SET_ERROR_MSG(
"node_names size is not zero");
401 if (node_names->data) {
402 RCL_SET_ERROR_MSG(
"node_names is not null");
406 if (node_namespaces->size != 0) {
407 RCL_SET_ERROR_MSG(
"node_namespaces size is not zero");
410 if (node_namespaces->data) {
411 RCL_SET_ERROR_MSG(
"node_namespaces is not null");
415 if (enclaves->size != 0) {
416 RCL_SET_ERROR_MSG(
"enclaves size is not zero");
419 if (enclaves->data) {
420 RCL_SET_ERROR_MSG(
"enclaves is not null");
424 rmw_ret_t rmw_ret = rmw_get_node_names_with_enclaves(
429 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
435 const char * topic_name,
448 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
454 const char * topic_name,
467 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
473 const char * service_name,
486 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
492 const char * service_name,
505 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
508 typedef rcl_ret_t (* count_entities_func_t)(
510 const char * topic_name,
514 _rcl_wait_for_entities(
517 const char * topic_name,
518 const size_t expected_count,
519 rcutils_duration_value_t timeout,
521 count_entities_func_t count_entities_func)
535 ret = count_entities_func(node, topic_name, &count);
540 if (expected_count <= count) {
548 &wait_set, 0, 1, 0, 0, 0, 0, node->
context, *allocator);
555 if (!guard_condition) {
570 rcutils_time_point_value_t start;
571 rcutils_ret_t time_ret = rcutils_system_time_now(&start);
572 if (time_ret != RCUTILS_RET_OK) {
573 rcutils_error_string_t error = rcutils_get_error_string();
574 rcutils_reset_error();
575 RCL_SET_ERROR_MSG(error.str);
584 wait_ret =
rcl_wait(&wait_set, timeout);
592 ret = count_entities_func(node, topic_name, &count);
597 if (expected_count <= count) {
604 rcutils_time_point_value_t now;
605 time_ret = rcutils_system_time_now(&now);
606 if (time_ret != RCUTILS_RET_OK) {
607 rcutils_error_string_t error = rcutils_get_error_string();
608 rcutils_reset_error();
609 RCL_SET_ERROR_MSG(error.str);
613 timeout = timeout - (now - start);
647 const char * topic_name,
648 const size_t expected_count,
649 rcutils_duration_value_t timeout,
652 return _rcl_wait_for_entities(
666 const char * topic_name,
667 const size_t expected_count,
668 rcutils_duration_value_t timeout,
671 return _rcl_wait_for_entities(
686 const char * service_name,
687 const size_t expected_count,
688 rcutils_duration_value_t timeout,
691 return _rcl_wait_for_entities(
705 const char * service_name,
706 const size_t expected_count,
707 rcutils_duration_value_t timeout,
710 return _rcl_wait_for_entities(
720 typedef rmw_ret_t (* get_topic_endpoint_info_func_t)(
721 const rmw_node_t * node,
722 rcutils_allocator_t * allocator,
723 const char * topic_name,
725 rmw_topic_endpoint_info_array_t * info_array);
728 __rcl_get_info_by_topic(
730 rcutils_allocator_t * allocator,
731 const char * topic_name,
733 rmw_topic_endpoint_info_array_t * info_array,
734 get_topic_endpoint_info_func_t get_topic_endpoint_info)
745 rmw_error_string_t error_string;
746 rmw_ret_t rmw_ret = rmw_topic_endpoint_info_array_check_zero(info_array);
747 if (rmw_ret != RMW_RET_OK) {
748 error_string = rmw_get_error_string();
750 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
751 "rmw_topic_endpoint_info_array_t must be zero initialized: %s,\n"
752 "Use rmw_get_zero_initialized_topic_endpoint_info_array",
754 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
756 rmw_ret = get_topic_endpoint_info(
762 if (rmw_ret != RMW_RET_OK) {
763 error_string = rmw_get_error_string();
765 RCL_SET_ERROR_MSG(error_string.str);
767 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
773 rcutils_allocator_t * allocator,
774 const char * topic_name,
776 rmw_topic_endpoint_info_array_t * publishers_info)
778 return __rcl_get_info_by_topic(
784 rmw_get_publishers_info_by_topic);
790 rcutils_allocator_t * allocator,
791 const char * topic_name,
793 rmw_topic_endpoint_info_array_t * subscriptions_info)
795 return __rcl_get_info_by_topic(
801 rmw_get_subscriptions_info_by_topic);
804 typedef rmw_ret_t (* get_service_endpoint_info_func_t)(
805 const rmw_node_t * node,
806 rcutils_allocator_t * allocator,
807 const char * service_name,
809 rmw_service_endpoint_info_array_t * info_array);
812 __rcl_get_info_by_service(
814 rcutils_allocator_t * allocator,
815 const char * service_name,
817 rmw_service_endpoint_info_array_t * info_array,
818 get_service_endpoint_info_func_t get_service_endpoint_info)
829 rmw_error_string_t error_string;
830 rmw_ret_t rmw_ret = rmw_service_endpoint_info_array_check_zero(info_array);
831 if (rmw_ret != RMW_RET_OK) {
832 error_string = rmw_get_error_string();
834 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
835 "rmw_service_endpoint_info_array_t must be zero initialized: %s,\n"
836 "Use rmw_get_zero_initialized_service_endpoint_info_array",
838 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
840 rmw_ret = get_service_endpoint_info(
846 if (rmw_ret != RMW_RET_OK) {
847 error_string = rmw_get_error_string();
849 RCL_SET_ERROR_MSG(error_string.str);
851 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
857 rcutils_allocator_t * allocator,
858 const char * service_name,
860 rmw_service_endpoint_info_array_t * clients_info)
862 return __rcl_get_info_by_service(
868 rmw_get_clients_info_by_service);
874 rcutils_allocator_t * allocator,
875 const char * service_name,
877 rmw_service_endpoint_info_array_t * servers_info)
879 return __rcl_get_info_by_service(
885 rmw_get_servers_info_by_service);
906 rmw_ret_t rmw_ret = rmw_service_server_is_available(
911 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_servers_info_by_service(const rcl_node_t *node, rcutils_allocator_t *allocator, const char *service_name, bool no_mangle, rcl_service_endpoint_info_array_t *servers_info)
Return a list of all servers to a service.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_for_servers(const rcl_node_t *node, rcl_allocator_t *allocator, const char *service_name, const size_t count, rcutils_duration_value_t timeout, bool *success)
Wait for there to be a specified number of servers on a given service.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_count_services(const rcl_node_t *node, const char *service_name, size_t *count)
Return the number of servers on a given service.
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 node names and their associated namespaces and enclaves in the ROS graph.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_wait_for_clients(const rcl_node_t *node, rcl_allocator_t *allocator, const char *service_name, const size_t count, rcutils_duration_value_t timeout, bool *success)
Wait for there to be a specified number of clients on a given service.
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.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_count_clients(const rcl_node_t *node, const char *service_name, size_t *count)
Return the number of clients on a given service.
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 node names and their associated namespaces in the ROS graph.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_get_clients_info_by_service(const rcl_node_t *node, rcutils_allocator_t *allocator, const char *service_name, bool no_mangle, rcl_service_endpoint_info_array_t *clients_info)
Return a list of all clients to a service.
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.