1+ #include <rcl/rcl.h>
2+ #include <rcl/error_handling.h>
3+ #include <rclc/rclc.h>
4+ #include <rclc/executor.h>
5+
6+ #include <std_msgs/msg/string.h>
7+
8+ #include <stdio.h>
9+ #include <unistd.h>
10+
11+ #include <rmw_uros/options.h>
12+
13+ #include <rosidl_runtime_c/string_functions.h>
14+
15+ #define RCCHECK (fn ) \
16+ {\
17+ rcl_ret_t temp_rc = fn;\
18+ if (RCL_RET_OK != temp_rc) {\
19+ printf("Failed status on line %d: %d. Aborting.\n", __LINE__, (int)temp_rc);\
20+ return 1;\
21+ }\
22+ }
23+
24+ #define RCSOFTCHECK (fn ) \
25+ {\
26+ rcl_ret_t temp_rc = fn;\
27+ if(RCL_RET_OK != temp_rc) {\
28+ printf("Failed status on line %d: %d. Continuing.\n", __LINE__, (int)temp_rc);\
29+ }\
30+ }
31+
32+ rcl_publisher_t publisher ;
33+ std_msgs__msg__String msg ;
34+
35+ int usage ()
36+ {
37+ printf ("Usage: ping_uros_agent <mode>\nModes:\n" );
38+ printf ("\t* 'basic': checks that the micro-ROS Agent is up or down, and exits\n" );
39+ printf ("\t* 'interactive': starts a basic micro-ROS application " );
40+ printf ("if the Agent is up, or waits for the user to start it in a loop\n" );
41+ return 1 ;
42+ }
43+
44+ void timer_callback (rcl_timer_t * timer , int64_t last_call_time )
45+ {
46+ (void ) last_call_time ;
47+ if (NULL != timer ) {
48+ RCSOFTCHECK (rcl_publish (& publisher , & msg , NULL ));
49+ printf ("Sent: '%s'\n" , msg .data .data );
50+
51+ /**
52+ * If agent suddently goes down, we will exit the application.
53+ * This proves that `rmw_uros_ping_agent` functionality can be used
54+ * also when a micro-ROS node is already up and running (and hence, the
55+ * transport has been initialized in the RMW context).
56+ */
57+ printf ("\nPinging agent again...\n" );
58+ if (RMW_RET_OK != rmw_uros_ping_agent (100 , 1 )) {
59+ printf ("micro-ROS agent has stopped. Exiting...\n" );
60+ exit (1 );
61+ } else {
62+ printf ("Agent is still up!\n\n" );
63+ }
64+ }
65+ }
66+
67+ int main (int argc , char * * argv )
68+ {
69+ /**
70+ * Parse arguments
71+ */
72+ if (2 != argc ) {
73+ return usage ();
74+ }
75+
76+ const char * mode = argv [1 ];
77+
78+ /**
79+ * Basic mode
80+ */
81+ if (0 == strcmp ("basic" , mode )) {
82+ /**
83+ * Ping should work even without a micro-ROS node active.
84+ */
85+ rmw_ret_t ping_result = rmw_uros_ping_agent (1000 , 5 );
86+
87+ if (RMW_RET_OK == ping_result ) {
88+ printf ("Success! micro-ROS Agent is up.\n" );
89+ return 0 ;
90+ } else {
91+ printf ("Sorry, the micro-ROS Agent is not available.\n" );
92+ return 1 ;
93+ }
94+ } else if (0 == strcmp ("interactive" , mode )) {
95+ /**
96+ * Loop until micro-ROS Agent is up
97+ */
98+ while (RMW_RET_OK != rmw_uros_ping_agent (1000 , 1 )) {
99+ printf ("Please, start your micro-ROS Agent first\n" );
100+ }
101+
102+ /**
103+ * Start the micro-ROS basic application
104+ */
105+ rcl_allocator_t allocator = rcl_get_default_allocator ();
106+ rclc_support_t support ;
107+
108+ // Create init options
109+ RCCHECK (rclc_support_init (& support , 0 , NULL , & allocator ));
110+
111+ // Create node
112+ rcl_node_t node ;
113+ RCCHECK (rclc_node_init_default (
114+ & node , "ping_uros_agent_publisher" , "" , & support ));
115+
116+ // Create publisher
117+ RCCHECK (rclc_publisher_init_default (
118+ & publisher ,
119+ & node ,
120+ ROSIDL_GET_MSG_TYPE_SUPPORT (std_msgs , msg , String ),
121+ "ping_uros_agent_topic" ));
122+
123+ // Create timer
124+ rcl_timer_t timer ;
125+ const unsigned int timer_timeout = 1000 ;
126+ RCCHECK (rclc_timer_init_default (
127+ & timer ,
128+ & support ,
129+ RCL_MS_TO_NS (timer_timeout ),
130+ timer_callback ));
131+
132+ // Create executor
133+ rclc_executor_t executor ;
134+ RCCHECK (rclc_executor_init (& executor , & support .context , 1 , & allocator ));
135+ RCCHECK (rclc_executor_add_timer (& executor , & timer ));
136+
137+ // Init data
138+ (void ) rosidl_runtime_c__String__init (& msg .data );
139+ (void ) rosidl_runtime_c__String__assign (
140+ & msg .data ,
141+ "This is a message sent after pinging micro-ROS Agent" );
142+
143+ // Spin executor
144+ rclc_executor_spin (& executor );
145+
146+ // Free micro-ROS resources before exiting
147+ (void ) rosidl_runtime_c__String__fini (& msg .data );
148+
149+ RCCHECK (rclc_executor_fini (& executor ));
150+ RCCHECK (rcl_publisher_fini (& publisher , & node ));
151+ RCCHECK (rcl_node_fini (& node ));
152+ RCCHECK (rclc_support_fini (& support ));
153+ } else {
154+ return usage ();
155+ }
156+
157+ return 0 ;
158+ }
0 commit comments