1+ /*FreeRtos includes*/
2+ #include "FreeRTOS.h"
3+ #include "task.h"
4+ #include "static_mem.h"
5+
6+ #include <rcl/rcl.h>
7+ #include <sensor_msgs/msg/laser_echo.h>
8+ #include <std_msgs/msg/float32.h>
9+ #include <geometry_msgs/msg/point32.h>
10+
11+ #include <rcutils/allocator.h>
12+ #include <rmw_uros/options.h>
13+
14+
15+ #include "config.h"
16+ #include "log.h"
17+ #include "crc.h"
18+ #include "worker.h"
19+ #include "num.h"
20+ #include "debug.h"
21+ #include "radiolink.h"
22+ #include <time.h>
23+
24+ #include "microrosapp.h"
25+
26+ #include "crtp.h"
27+ #include "configblock.h"
28+
29+ #define RCCHECK (clean ) if((rc != RCL_RET_OK)){DEBUG_PRINT("Failed status on line %d: %d. Aborting.\n",__LINE__,(int)rc); goto clean;}
30+ #define RCSOFTCHECK () if((rc != RCL_RET_OK)){DEBUG_PRINT("Failed status on line %d: %d. Continuing.\n",__LINE__,(int)rc);}
31+
32+ void microros_primary (void * params );
33+ void microros_secondary (void * params );
34+
35+ float sensor_data [2 ];
36+ sensor_msgs__msg__LaserEcho sensor_topic ;
37+ static bool sensor_data_ready ;
38+
39+ static int pitchid , rollid , yawid ;
40+ static int Xid , Yid , Zid ;
41+
42+ // Note: please set APP_STACKSIZE = 100 and CFLAGS += -DFREERTOS_HEAP_SIZE=12100 in Makefile before build
43+
44+ STATIC_MEM_TASK_ALLOC (microros_primary , 1000 );
45+ STATIC_MEM_TASK_ALLOC (microros_secondary , 1000 );
46+ static bool created_primary = false;
47+
48+ void appMain (){
49+ BaseType_t rc __attribute__((unused ));
50+ // TaskHandle_t task_primary, task_secondary;
51+
52+ absoluteUsedMemory = 0 ;
53+ usedMemory = 0 ;
54+
55+ rcl_allocator_t freeRTOS_allocator = rcutils_get_zero_initialized_allocator ();
56+ freeRTOS_allocator .allocate = __crazyflie_allocate ;
57+ freeRTOS_allocator .deallocate = __crazyflie_deallocate ;
58+ freeRTOS_allocator .reallocate = __crazyflie_reallocate ;
59+ freeRTOS_allocator .zero_allocate = __crazyflie_zero_allocate ;
60+
61+ if (!rcutils_set_default_allocator (& freeRTOS_allocator )) {
62+ DEBUG_PRINT ("Error on default allocators (line %d)\n" ,__LINE__ );
63+ vTaskSuspend ( NULL );
64+ }
65+
66+
67+ sensor_topic .echoes .capacity = 2 ;
68+ sensor_topic .echoes .size = 2 ;
69+ sensor_topic .echoes .data = sensor_data ;
70+
71+ STATIC_MEM_TASK_CREATE (microros_primary , microros_primary , "microROSprimary" , NULL , 3 );
72+ STATIC_MEM_TASK_CREATE (microros_secondary , microros_secondary , "microROSsecondary" , NULL , 3 );
73+ }
74+
75+ void microros_primary (void * params ){
76+ while (1 ){
77+
78+ // ####################### RADIO INIT #######################
79+
80+ int radio_connected = logGetVarId ("radio" , "isConnected" );
81+ while (!logGetUint (radio_connected )) vTaskDelay (100 );
82+ // DEBUG_PRINT("Radio connected\n");
83+
84+ // ####################### MICROROS INIT #######################
85+
86+ DEBUG_PRINT ("Free heap pre uROS: %d bytes\n" , xPortGetFreeHeapSize ());
87+ vTaskDelay (50 );
88+
89+ rcl_context_t context ;
90+ rcl_init_options_t init_options ;
91+ rcl_ret_t rc ;
92+ rcl_ret_t rc_aux __attribute__((unused ));
93+
94+ init_options = rcl_get_zero_initialized_init_options ();
95+ rc = rcl_init_options_init (& init_options , rcutils_get_default_allocator ());
96+ RCCHECK (clean1 )
97+
98+ rmw_init_options_t * rmw_options = rcl_init_options_get_rmw_init_options (& init_options );
99+ rc = rmw_uros_options_set_serial_device ("65" , rmw_options );
100+ rc = rmw_uros_options_set_client_key (0xBA5EBA11 , rmw_options );
101+
102+ context = rcl_get_zero_initialized_context ();
103+
104+ rc = rcl_init (0 , NULL , & init_options , & context );
105+ rc_aux = rcl_init_options_fini (& init_options );
106+ RCCHECK (clean1 )
107+
108+ rcl_node_t node = rcl_get_zero_initialized_node ();
109+ rcl_node_options_t node_ops = rcl_node_get_default_options ();
110+
111+ rc = rcl_node_init (& node , "crazyflie_node_1" , "" , & context , & node_ops );
112+ RCCHECK (clean1 )
113+
114+ // Create publisher 1
115+ rcl_publisher_t pub_sensors_temp = rcl_get_zero_initialized_publisher ();
116+ rcl_publisher_options_t pub_opt_sensors_temp = rcl_publisher_get_default_options ();
117+ pub_opt_sensors_temp .qos .reliability = RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT ;
118+
119+ rc = rcl_publisher_init (
120+ & pub_sensors_temp ,
121+ & node ,
122+ ROSIDL_GET_MSG_TYPE_SUPPORT (std_msgs , msg , Float32 ),
123+ "/weather_station/temperature" ,
124+ & pub_opt_sensors_temp );
125+
126+ if (rc != RCL_RET_OK ){
127+ rc_aux = rcl_node_fini (& node );
128+ }
129+ RCCHECK (clean1 )
130+
131+ // Create publisher 2
132+ rcl_publisher_t pub_sensors_hum = rcl_get_zero_initialized_publisher ();
133+ rcl_publisher_options_t pub_opt_sensors_hum = rcl_publisher_get_default_options ();
134+ pub_opt_sensors_hum .qos .reliability = RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT ;
135+
136+ rc = rcl_publisher_init (
137+ & pub_sensors_hum ,
138+ & node ,
139+ ROSIDL_GET_MSG_TYPE_SUPPORT (std_msgs , msg , Float32 ),
140+ "/weather_station/humidity" ,
141+ & pub_opt_sensors_hum );
142+
143+ if (rc != RCL_RET_OK ){
144+ rc_aux = rcl_node_fini (& node );
145+ }
146+ RCCHECK (clean1 )
147+
148+ // Create publisher 3
149+ rcl_publisher_t pub_odom = rcl_get_zero_initialized_publisher ();
150+ rcl_publisher_options_t pub_opt_odom = rcl_publisher_get_default_options ();
151+ pub_opt_odom .qos .reliability = RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT ;
152+
153+ rc = rcl_publisher_init (
154+ & pub_odom ,
155+ & node ,
156+ ROSIDL_GET_MSG_TYPE_SUPPORT (geometry_msgs , msg , Point32 ),
157+ "/drone/odometry" ,
158+ & pub_opt_odom );
159+ RCCHECK (clean1 )
160+
161+ // Create publisher 4
162+ rcl_publisher_t pub_attitude = rcl_get_zero_initialized_publisher ();
163+ rcl_publisher_options_t pub_opt_att = rcl_publisher_get_default_options ();
164+ pub_opt_att .qos .reliability = RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT ;
165+
166+ rc = rcl_publisher_init (
167+ & pub_attitude ,
168+ & node ,
169+ ROSIDL_GET_MSG_TYPE_SUPPORT (geometry_msgs , msg , Point32 ),
170+ "/drone/attitude" ,
171+ & pub_opt_att );
172+ RCCHECK (clean1 )
173+
174+ DEBUG_PRINT ("Free heap post uROS configuration: %d bytes\n" , xPortGetFreeHeapSize ());
175+ DEBUG_PRINT ("uROS Used Memory %d bytes\n" , usedMemory );
176+ DEBUG_PRINT ("uROS Absolute Used Memory %d bytes\n" , absoluteUsedMemory );
177+
178+ created_primary = true;
179+ // ####################### MAIN LOOP #######################
180+
181+ // Init messages
182+ geometry_msgs__msg__Point32 pose ;
183+ geometry_msgs__msg__Point32__init (& pose );
184+ geometry_msgs__msg__Point32 odom ;
185+ geometry_msgs__msg__Point32__init (& odom );
186+
187+ //Get pitch, roll and yaw value
188+ pitchid = logGetVarId ("stateEstimate" , "pitch" );
189+ rollid = logGetVarId ("stateEstimate" , "roll" );
190+ yawid = logGetVarId ("stateEstimate" , "yaw" );
191+
192+ //Get X,Y and Z value
193+ Xid = logGetVarId ("stateEstimate" , "x" );
194+ Yid = logGetVarId ("stateEstimate" , "y" );
195+ Zid = logGetVarId ("stateEstimate" , "z" );
196+
197+ while (1 ){
198+
199+ if (sensor_data_ready ){
200+ std_msgs__msg__Float32 aux_msg ;
201+
202+ aux_msg .data = sensor_topic .echoes .data [0 ];
203+ rc = rcl_publish ( & pub_sensors_temp , (const void * ) & aux_msg , NULL );
204+
205+ aux_msg .data = sensor_topic .echoes .data [1 ];
206+ rc = rcl_publish ( & pub_sensors_hum , (const void * ) & aux_msg , NULL );
207+
208+ sensor_data_ready = 0 ;
209+ }
210+
211+ pose .x = logGetFloat (pitchid );
212+ pose .y = logGetFloat (rollid );
213+ pose .z = logGetFloat (yawid );
214+ odom .x = logGetFloat (Xid );
215+ odom .y = logGetFloat (Yid );
216+ odom .z = logGetFloat (Zid );
217+
218+ rc = rcl_publish ( & pub_attitude , (const void * ) & pose , NULL );
219+ RCSOFTCHECK ()
220+
221+ rc = rcl_publish ( & pub_odom , (const void * ) & odom , NULL );
222+ RCSOFTCHECK ()
223+
224+ vTaskDelay (100 /portTICK_RATE_MS );
225+ }
226+
227+ rc = rcl_node_fini (& node );
228+ clean1 :
229+ rc = rcl_shutdown (& context );
230+ DEBUG_PRINT ("Connection lost on primary, retriying\n" );
231+ }
232+
233+ vTaskSuspend ( NULL );
234+ }
235+
236+ void microros_secondary (void * params ){
237+ while (!created_primary ){
238+ vTaskDelay (100 );
239+ }
240+
241+ while (1 ){
242+ // ####################### RADIO INIT #######################
243+
244+ int radio_connected = logGetVarId ("radio" , "isConnected" );
245+ while (!logGetUint (radio_connected )) vTaskDelay (100 );
246+ // DEBUG_PRINT("Radio connected\n");
247+
248+ // ####################### MICROROS INIT #######################
249+
250+ DEBUG_PRINT ("Free heap pre uROS: %d bytes\n" , xPortGetFreeHeapSize ());
251+ vTaskDelay (50 );
252+
253+ rcl_context_t context ;
254+ rcl_init_options_t init_options ;
255+ rcl_ret_t rc ;
256+ rcl_ret_t rc_aux __attribute__((unused ));
257+
258+ init_options = rcl_get_zero_initialized_init_options ();
259+ rc = rcl_init_options_init (& init_options , rcutils_get_default_allocator ());
260+ RCCHECK (clean2 )
261+
262+ rmw_init_options_t * rmw_options = rcl_init_options_get_rmw_init_options (& init_options );
263+ rc = rmw_uros_options_set_serial_device ("30" , rmw_options );
264+ rc = rmw_uros_options_set_client_key (0xDEADBEEF , rmw_options );
265+
266+ context = rcl_get_zero_initialized_context ();
267+
268+ rc = rcl_init (0 , NULL , & init_options , & context );
269+ rc_aux = rcl_init_options_fini (& init_options );
270+ RCCHECK (clean2 )
271+
272+ rcl_node_t node = rcl_get_zero_initialized_node ();
273+ rcl_node_options_t node_ops = rcl_node_get_default_options ();
274+
275+ rc = rcl_node_init (& node , "crazyflie_node_2" , "" , & context , & node_ops );
276+ RCCHECK (clean2 )
277+
278+ // Create subscription 2
279+ const char * echo_topic_name = "Float__Sequence" ;
280+
281+ rcl_subscription_t sub_sensors = rcl_get_zero_initialized_subscription ();
282+ const rosidl_message_type_support_t * sub_type_support = ROSIDL_GET_MSG_TYPE_SUPPORT (sensor_msgs , msg , LaserEcho );
283+ rcl_subscription_options_t subscription_ops = rcl_subscription_get_default_options ();
284+ subscription_ops .qos .reliability = RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT ;
285+
286+ rc = rcl_subscription_init (
287+ & sub_sensors ,
288+ & node ,
289+ sub_type_support ,
290+ echo_topic_name ,
291+ & subscription_ops );
292+ RCCHECK (clean2 )
293+
294+ // Create wait set
295+ rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set ();
296+ rc = rcl_wait_set_init (& wait_set , 1 , 0 , 0 , 0 , 0 , 0 , & context , rcl_get_default_allocator ());
297+ RCCHECK (clean2 )
298+
299+ if (rc != RCL_RET_OK ){
300+ rc_aux = rcl_node_fini (& node );
301+ }
302+ RCCHECK (clean2 )
303+
304+ DEBUG_PRINT ("Free heap post uROS configuration: %d bytes\n" , xPortGetFreeHeapSize ());
305+ DEBUG_PRINT ("uROS Used Memory %d bytes\n" , usedMemory );
306+ DEBUG_PRINT ("uROS Absolute Used Memory %d bytes\n" , absoluteUsedMemory );
307+
308+ // ####################### MAIN LOOP #######################
309+
310+ while (1 ){
311+
312+ rc = rcl_wait_set_clear (& wait_set );
313+ RCSOFTCHECK ()
314+
315+ rc = rcl_wait_set_add_subscription (& wait_set , & sub_sensors , NULL );
316+ RCSOFTCHECK ()
317+
318+ rc = rcl_wait (& wait_set , RCL_MS_TO_NS (10 ));
319+ // RCSOFTCHECK()
320+
321+ if (wait_set .subscriptions [0 ]){
322+ sensor_msgs__msg__LaserEcho rcv ;
323+ float rcv_data [2 ];
324+
325+ rcv .echoes .capacity = 2 ;
326+ rcv .echoes .size = 2 ;
327+ rcv .echoes .data = rcv_data ;
328+
329+ rc = rcl_take (& sub_sensors , & rcv , NULL , NULL );
330+
331+ if (rc == RCL_RET_OK ) {
332+ memcpy (& sensor_topic , & rcv , sizeof (sensor_msgs__msg__LaserEcho ));
333+ sensor_data_ready = 1 ;
334+ }
335+ }
336+
337+ vTaskDelay (100 /portTICK_RATE_MS );
338+ }
339+
340+ rc = rcl_subscription_fini (& sub_sensors , & node );
341+ rc = rcl_node_fini (& node );
342+ clean2 :
343+ rc = rcl_shutdown (& context );
344+ DEBUG_PRINT ("Connection lost on secondary, retriying\n" );
345+ }
346+
347+ vTaskSuspend ( NULL );
348+ }
0 commit comments