23 #include "rcl/error_handling.h"
27 #include "rcutils/allocator.h"
28 #include "rcutils/error_handling.h"
29 #include "rcutils/macros.h"
30 #include "rcutils/time.h"
31 #include "rcutils/types.h"
33 #include "rmw/error_handling.h"
34 #include "rmw/get_node_info_and_types.h"
35 #include "rmw/get_service_endpoint_info.h"
36 #include "rmw/get_service_names_and_types.h"
37 #include "rmw/get_topic_endpoint_info.h"
38 #include "rmw/get_topic_names_and_types.h"
39 #include "rmw/names_and_types.h"
41 #include "rmw/service_endpoint_info_array.h"
42 #include "rmw/topic_endpoint_info_array.h"
43 #include "rmw/validate_namespace.h"
44 #include "rmw/validate_node_name.h"
49 __validate_node_name_and_namespace(
50 const char * node_name,
51 const char * node_namespace)
53 int validation_result = 0;
54 rmw_ret_t rmw_ret = rmw_validate_namespace(node_namespace, &validation_result, NULL);
56 if (RMW_RET_OK != rmw_ret) {
57 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
58 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
60 if (validation_result != RMW_NAMESPACE_VALID) {
61 const char * msg = rmw_namespace_validation_result_string(validation_result);
62 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"%s, result: %d", msg, validation_result);
66 validation_result = 0;
67 rmw_ret = rmw_validate_node_name(node_name, &validation_result, NULL);
68 if (RMW_RET_OK != rmw_ret) {
69 RCL_SET_ERROR_MSG(rmw_get_error_string().str);
70 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
72 if (RMW_NODE_NAME_VALID != validation_result) {
73 const char * msg = rmw_node_name_validation_result_string(validation_result);
74 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"%s, result: %d", msg, validation_result);
86 const char * node_name,
87 const char * node_namespace,
98 const char * valid_namespace =
"/";
99 if (strlen(node_namespace) > 0) {
100 valid_namespace = node_namespace;
102 rmw_ret_t rmw_ret = rmw_names_and_types_check_zero(topic_names_and_types);
103 if (RMW_RET_OK != rmw_ret) {
104 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
106 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
110 rcutils_allocator_t rcutils_allocator = *allocator;
111 rmw_ret = rmw_get_publisher_names_and_types_by_node(
117 topic_names_and_types
119 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
127 const char * node_name,
128 const char * node_namespace,
139 const char * valid_namespace =
"/";
140 if (strlen(node_namespace) > 0) {
141 valid_namespace = node_namespace;
144 rmw_ret = rmw_names_and_types_check_zero(topic_names_and_types);
145 if (rmw_ret != RMW_RET_OK) {
146 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
148 rcutils_allocator_t rcutils_allocator = *allocator;
149 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
153 rmw_ret = rmw_get_subscriber_names_and_types_by_node(
159 topic_names_and_types
161 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
168 const char * node_name,
169 const char * node_namespace,
180 const char * valid_namespace =
"/";
181 if (strlen(node_namespace) > 0) {
182 valid_namespace = node_namespace;
185 rmw_ret = rmw_names_and_types_check_zero(service_names_and_types);
186 if (rmw_ret != RMW_RET_OK) {
187 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
189 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
193 rcutils_allocator_t rcutils_allocator = *allocator;
194 rmw_ret = rmw_get_service_names_and_types_by_node(
199 service_names_and_types
201 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
208 const char * node_name,
209 const char * node_namespace,
220 const char * valid_namespace =
"/";
221 if (strlen(node_namespace) > 0) {
222 valid_namespace = node_namespace;
225 rmw_ret = rmw_names_and_types_check_zero(service_names_and_types);
226 if (rmw_ret != RMW_RET_OK) {
227 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
229 rcl_ret_t rcl_ret = __validate_node_name_and_namespace(node_name, valid_namespace);
233 rcutils_allocator_t rcutils_allocator = *allocator;
234 rmw_ret = rmw_get_client_names_and_types_by_node(
239 service_names_and_types
241 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
257 rmw_ret = rmw_names_and_types_check_zero(topic_names_and_types);
258 if (rmw_ret != RMW_RET_OK) {
259 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
261 rcutils_allocator_t rcutils_allocator = *allocator;
262 rmw_ret = rmw_get_topic_names_and_types(
266 topic_names_and_types
268 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
283 rmw_ret = rmw_names_and_types_check_zero(service_names_and_types);
284 if (rmw_ret != RMW_RET_OK) {
285 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
287 rcutils_allocator_t rcutils_allocator = *allocator;
288 rmw_ret = rmw_get_service_names_and_types(
291 service_names_and_types
293 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
306 rmw_ret_t rmw_ret = rmw_names_and_types_init(names_and_types, size, allocator);
307 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
316 rmw_ret_t rmw_ret = rmw_names_and_types_fini(topic_names_and_types);
317 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
324 rcutils_string_array_t * node_names,
325 rcutils_string_array_t * node_namespaces)
331 if (node_names->size != 0) {
332 RCL_SET_ERROR_MSG(
"node_names size is not zero");
335 if (node_names->data) {
336 RCL_SET_ERROR_MSG(
"node_names is not null");
340 if (node_namespaces->size != 0) {
341 RCL_SET_ERROR_MSG(
"node_namespaces size is not zero");
344 if (node_namespaces->data) {
345 RCL_SET_ERROR_MSG(
"node_namespaces is not null");
349 rmw_ret_t rmw_ret = rmw_get_node_names(
354 if (RMW_RET_OK != rmw_ret) {
355 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
359 for (
size_t i = 0u; i < node_names->size; ++i) {
360 if (!node_names->data[i]) {
361 RCL_SET_ERROR_MSG(
"NULL node name returned by the RMW layer");
364 if (!strcmp(node_names->data[i],
"")) {
365 RCL_SET_ERROR_MSG(
"empty node name returned by the RMW layer");
370 for (
size_t i = 0u; i < node_namespaces->size; ++i) {
371 if (!node_namespaces->data[i]) {
372 RCL_SET_ERROR_MSG(
"NULL node namespace returned by the RMW layer");
383 rcutils_string_array_t * node_names,
384 rcutils_string_array_t * node_namespaces,
385 rcutils_string_array_t * enclaves)
391 if (node_names->size != 0) {
392 RCL_SET_ERROR_MSG(
"node_names size is not zero");
395 if (node_names->data) {
396 RCL_SET_ERROR_MSG(
"node_names is not null");
400 if (node_namespaces->size != 0) {
401 RCL_SET_ERROR_MSG(
"node_namespaces size is not zero");
404 if (node_namespaces->data) {
405 RCL_SET_ERROR_MSG(
"node_namespaces is not null");
409 if (enclaves->size != 0) {
410 RCL_SET_ERROR_MSG(
"enclaves size is not zero");
413 if (enclaves->data) {
414 RCL_SET_ERROR_MSG(
"enclaves is not null");
418 rmw_ret_t rmw_ret = rmw_get_node_names_with_enclaves(
423 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
429 const char * topic_name,
442 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
448 const char * topic_name,
461 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
467 const char * service_name,
480 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
486 const char * service_name,
499 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
502 typedef rcl_ret_t (* count_entities_func_t)(
504 const char * topic_name,
508 _rcl_wait_for_entities(
511 const char * topic_name,
512 const size_t expected_count,
513 rcutils_duration_value_t timeout,
515 count_entities_func_t count_entities_func)
529 ret = count_entities_func(node, topic_name, &count);
534 if (expected_count <= count) {
542 &wait_set, 0, 1, 0, 0, 0, 0, node->
context, *allocator);
549 if (!guard_condition) {
564 rcutils_time_point_value_t start;
565 rcutils_ret_t time_ret = rcutils_system_time_now(&start);
566 if (time_ret != RCUTILS_RET_OK) {
567 rcutils_error_string_t error = rcutils_get_error_string();
568 rcutils_reset_error();
569 RCL_SET_ERROR_MSG(error.str);
578 wait_ret =
rcl_wait(&wait_set, timeout);
586 ret = count_entities_func(node, topic_name, &count);
591 if (expected_count <= count) {
598 rcutils_time_point_value_t now;
599 time_ret = rcutils_system_time_now(&now);
600 if (time_ret != RCUTILS_RET_OK) {
601 rcutils_error_string_t error = rcutils_get_error_string();
602 rcutils_reset_error();
603 RCL_SET_ERROR_MSG(error.str);
607 timeout = timeout - (now - start);
641 const char * topic_name,
642 const size_t expected_count,
643 rcutils_duration_value_t timeout,
646 return _rcl_wait_for_entities(
660 const char * topic_name,
661 const size_t expected_count,
662 rcutils_duration_value_t timeout,
665 return _rcl_wait_for_entities(
680 const char * service_name,
681 const size_t expected_count,
682 rcutils_duration_value_t timeout,
685 return _rcl_wait_for_entities(
699 const char * service_name,
700 const size_t expected_count,
701 rcutils_duration_value_t timeout,
704 return _rcl_wait_for_entities(
714 typedef rmw_ret_t (* get_topic_endpoint_info_func_t)(
715 const rmw_node_t * node,
716 rcutils_allocator_t * allocator,
717 const char * topic_name,
719 rmw_topic_endpoint_info_array_t * info_array);
722 __rcl_get_info_by_topic(
724 rcutils_allocator_t * allocator,
725 const char * topic_name,
727 rmw_topic_endpoint_info_array_t * info_array,
728 get_topic_endpoint_info_func_t get_topic_endpoint_info)
739 rmw_error_string_t error_string;
740 rmw_ret_t rmw_ret = rmw_topic_endpoint_info_array_check_zero(info_array);
741 if (rmw_ret != RMW_RET_OK) {
742 error_string = rmw_get_error_string();
744 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
745 "rmw_topic_endpoint_info_array_t must be zero initialized: %s,\n"
746 "Use rmw_get_zero_initialized_topic_endpoint_info_array",
748 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
750 rmw_ret = get_topic_endpoint_info(
756 if (rmw_ret != RMW_RET_OK) {
757 error_string = rmw_get_error_string();
759 RCL_SET_ERROR_MSG(error_string.str);
761 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
767 rcutils_allocator_t * allocator,
768 const char * topic_name,
770 rmw_topic_endpoint_info_array_t * publishers_info)
772 return __rcl_get_info_by_topic(
778 rmw_get_publishers_info_by_topic);
784 rcutils_allocator_t * allocator,
785 const char * topic_name,
787 rmw_topic_endpoint_info_array_t * subscriptions_info)
789 return __rcl_get_info_by_topic(
795 rmw_get_subscriptions_info_by_topic);
798 typedef rmw_ret_t (* get_service_endpoint_info_func_t)(
799 const rmw_node_t * node,
800 rcutils_allocator_t * allocator,
801 const char * service_name,
803 rmw_service_endpoint_info_array_t * info_array);
806 __rcl_get_info_by_service(
808 rcutils_allocator_t * allocator,
809 const char * service_name,
811 rmw_service_endpoint_info_array_t * info_array,
812 get_service_endpoint_info_func_t get_service_endpoint_info)
823 rmw_error_string_t error_string;
824 rmw_ret_t rmw_ret = rmw_service_endpoint_info_array_check_zero(info_array);
825 if (rmw_ret != RMW_RET_OK) {
826 error_string = rmw_get_error_string();
828 RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
829 "rmw_service_endpoint_info_array_t must be zero initialized: %s,\n"
830 "Use rmw_get_zero_initialized_service_endpoint_info_array",
832 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
834 rmw_ret = get_service_endpoint_info(
840 if (rmw_ret != RMW_RET_OK) {
841 error_string = rmw_get_error_string();
843 RCL_SET_ERROR_MSG(error_string.str);
845 return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
851 rcutils_allocator_t * allocator,
852 const char * service_name,
854 rmw_service_endpoint_info_array_t * clients_info)
856 return __rcl_get_info_by_service(
862 rmw_get_clients_info_by_service);
868 rcutils_allocator_t * allocator,
869 const char * service_name,
871 rmw_service_endpoint_info_array_t * servers_info)
873 return __rcl_get_info_by_service(
879 rmw_get_servers_info_by_service);
900 rmw_ret_t rmw_ret = rmw_service_server_is_available(
905 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.