7 #include <sys/socket.h>
9 #include <netinet/in.h>
12 #include <arpa/inet.h>
24 #include <sys/ioctl.h>
29 /* Navdata constant */
30 #define NAVDATA_SEQUENCE_DEFAULT 1
31 #define NAVDATA_PORT 5554
32 #define NAVDATA_HEADER 0x55667788
33 #define NAVDATA_BUFFER_SIZE 2048
35 typedef enum _navdata_tag_t {
37 NAVDATA_VISION_DETECT_TAG = 16,
38 NAVDATA_IPHONE_ANGLES_TAG = 18,
39 NAVDATA_CKS_TAG = 0xFFFF
42 typedef struct _matrix33_t
55 typedef struct _vector31_t {
67 typedef struct _navdata_option_t {
73 typedef struct _navdata_t {
75 uint32_t mykonos_state;
79 navdata_option_t options[1];
80 } __attribute__ ((packed)) navdata_t;
82 typedef struct _navdata_cks_t {
86 // Checksum for all navdatas (including options)
88 } __attribute__ ((packed)) navdata_cks_t;
90 typedef struct _navdata_demo_t {
94 uint32_t ctrl_state; /*!< instance of #def_mykonos_state_mask_t */
95 uint32_t vbat_flying_percentage; /*!< battery voltage filtered (mV) */
97 float32_t theta; /*!< UAV's attitude */
98 float32_t phi; /*!< UAV's attitude */
99 float32_t psi; /*!< UAV's attitude */
101 int32_t altitude; /*!< UAV's altitude */
103 float32_t vx; /*!< UAV's estimated linear velocity */
104 float32_t vy; /*!< UAV's estimated linear velocity */
105 float32_t vz; /*!< UAV's estimated linear velocity */
107 uint32_t num_frames; /*!< streamed frame index */
109 // Camera parameters compute by detection
110 matrix33_t detection_camera_rot;
111 matrix33_t detection_camera_homo;
112 vector31_t detection_camera_trans;
114 // Camera parameters compute by drone
115 matrix33_t drone_camera_rot;
116 vector31_t drone_camera_trans;
117 } __attribute__ ((packed)) navdata_demo_t;
119 typedef struct _navdata_iphone_angles_t {
128 } __attribute__ ((packed)) navdata_iphone_angles_t;
130 typedef struct _navdata_time_t {
135 } __attribute__ ((packed)) navdata_time_t;
137 typedef struct _navdata_vision_detect_t {
141 uint32_t nb_detected;
148 } __attribute__ ((packed)) navdata_vision_detect_t;
150 typedef struct _navdata_unpacked_t {
151 uint32_t mykonos_state;
154 navdata_demo_t navdata_demo;
155 navdata_iphone_angles_t navdata_iphone_angles;
156 navdata_vision_detect_t navdata_vision_detect;
157 } navdata_unpacked_t;
159 /* Private variables */
160 static pthread_t nav_thread = 0;
161 static int32_t nav_thread_alive = 1;
163 static void navdata_open_server (void);
164 static void navdata_write (int8_t *buffer, int32_t len);
165 static void mykonos_navdata_unpack_all(navdata_unpacked_t* navdata_unpacked, navdata_t* navdata, uint32_t* cks);
166 static void* navdata_loop(void *arg);
168 static inline int get_mask_from_state( uint32_t state, uint32_t mask )
170 return state & mask ? TRUE : FALSE;
173 static inline uint8_t* navdata_unpack_option( uint8_t* navdata_ptr, uint8_t* data, uint32_t size )
175 memcpy(data, navdata_ptr, size);
177 return (navdata_ptr + size);
181 static inline navdata_option_t* navdata_next_option( navdata_option_t* navdata_options_ptr )
185 ptr = (uint8_t*) navdata_options_ptr;
186 ptr += navdata_options_ptr->size;
188 return (navdata_option_t*) ptr;
191 navdata_option_t* navdata_search_option( navdata_option_t* navdata_options_ptr, uint32_t tag );
194 static inline uint32_t navdata_compute_cks( uint8_t* nv, int32_t size )
202 for( i = 0; i < size; i++ )
211 #define navdata_unpack( navdata_ptr, option ) (navdata_option_t*) navdata_unpack_option( (uint8_t*) navdata_ptr, \
212 (uint8_t*) &option, \
214 static void mykonos_navdata_unpack_all(navdata_unpacked_t* navdata_unpacked, navdata_t* navdata, uint32_t* cks)
216 navdata_cks_t navdata_cks = { 0 };
217 navdata_option_t* navdata_option_ptr;
219 navdata_option_ptr = (navdata_option_t*) &navdata->options[0];
221 memset( navdata_unpacked, 0, sizeof(*navdata_unpacked) );
223 navdata_unpacked->mykonos_state = navdata->mykonos_state;
224 navdata_unpacked->vision_defined = navdata->vision_defined;
226 while( navdata_option_ptr != NULL )
228 // Check if we have a valid option
229 if( navdata_option_ptr->size == 0 )
231 INFO ("One option is not a valid because its size is zero\n");
232 navdata_option_ptr = NULL;
236 switch( navdata_option_ptr->tag )
238 case NAVDATA_DEMO_TAG:
239 //INFO ("Demo tag\n");
240 navdata_option_ptr = navdata_unpack( navdata_option_ptr, navdata_unpacked->navdata_demo );
243 case NAVDATA_IPHONE_ANGLES_TAG:
244 navdata_option_ptr = navdata_unpack( navdata_option_ptr, navdata_unpacked->navdata_iphone_angles );
247 case NAVDATA_VISION_DETECT_TAG:
248 navdata_option_ptr = navdata_unpack( navdata_option_ptr, navdata_unpacked->navdata_vision_detect );
251 case NAVDATA_CKS_TAG:
252 navdata_option_ptr = navdata_unpack( navdata_option_ptr, navdata_cks );
253 *cks = navdata_cks.cks;
254 navdata_option_ptr = NULL; // End of structure
258 INFO ("Tag %d is not a valid navdata option tag\n", (int) navdata_option_ptr->tag);
259 navdata_option_ptr = NULL;
266 static int navdata_udp_socket = -1;
267 static void navdata_write (int8_t *buffer, int32_t len)
269 struct sockaddr_in to;
272 if (navdata_udp_socket < 0)
274 /// Open udp socket to broadcast at commands to other mykonos
275 struct sockaddr_in navdata_udp_addr;
277 memset( (char*)&navdata_udp_addr, 0, sizeof(navdata_udp_addr) );
279 navdata_udp_addr.sin_family = AF_INET;
280 navdata_udp_addr.sin_addr.s_addr = INADDR_ANY;
281 navdata_udp_addr.sin_port = htons(NAVDATA_PORT + 100);
283 navdata_udp_socket = socket( AF_INET, SOCK_DGRAM, 0 );
285 if( navdata_udp_socket >= 0 )
287 flags = fcntl(navdata_udp_socket, F_GETFL, 0);
292 flags = fcntl(navdata_udp_socket, F_SETFL, flags );
296 INFO("Get Socket Options failed\n");
299 if (bind(navdata_udp_socket, (struct sockaddr*)&navdata_udp_addr, sizeof(struct sockaddr)) < 0) {
300 INFO ("navdata_write:bind: %s\n", strerror(errno));
304 if( navdata_udp_socket >= 0 ) {
307 memset( (char*)&to, 0, sizeof(to) );
308 to.sin_family = AF_INET;
309 to.sin_addr.s_addr = inet_addr(WIFI_MYKONOS_IP); // BROADCAST address for subnet 192.168.1.xxx
310 to.sin_port = htons( NAVDATA_PORT );
312 res = sendto( navdata_udp_socket, (char*)buffer, len, 0, (struct sockaddr*)&to, sizeof(to) );
316 static void navdata_open_server (void)
319 navdata_write ((int8_t*)&one, sizeof( one ));
322 static void* navdata_loop(void *arg)
324 uint8_t msg[NAVDATA_BUFFER_SIZE];
325 navdata_unpacked_t navdata_unpacked;
326 unsigned int cks, navdata_cks, sequence = NAVDATA_SEQUENCE_DEFAULT-1;
327 int sockfd = -1, addr_in_size;
328 struct sockaddr_in *my_addr, *from;
330 INFO("NAVDATA thread starting (thread=%d)...\n", (int)pthread_self());
332 navdata_open_server();
334 addr_in_size = sizeof(struct sockaddr_in);
336 navdata_t* navdata = (navdata_t*) &msg[0];
338 from = (struct sockaddr_in *)malloc(addr_in_size);
339 my_addr = (struct sockaddr_in *)malloc(addr_in_size);
343 memset((char *)my_addr,(char)0,addr_in_size);
344 my_addr->sin_family = AF_INET;
345 my_addr->sin_addr.s_addr = htonl(INADDR_ANY);
346 my_addr->sin_port = htons( NAVDATA_PORT );
348 if((sockfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0){
349 INFO ("socket: %s\n", strerror(errno));
353 if(bind(sockfd, (struct sockaddr *)my_addr, addr_in_size) < 0){
354 INFO ("bind: %s\n", strerror(errno));
363 setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
366 INFO("Ready to receive\n");
368 while ( nav_thread_alive ) {
370 size = recvfrom (sockfd, &msg[0], NAVDATA_BUFFER_SIZE, 0, (struct sockaddr *)from,
371 (socklen_t *)&addr_in_size);
375 INFO ("Lost connection \n");
376 navdata_open_server();
377 sequence = NAVDATA_SEQUENCE_DEFAULT-1;
379 if( navdata->header == NAVDATA_HEADER )
381 mykonos_state = navdata->mykonos_state;
383 if( get_mask_from_state(navdata->mykonos_state, MYKONOS_COM_WATCHDOG_MASK) )
385 INFO ("[NAVDATA] Detect com watchdog\n");
386 sequence = NAVDATA_SEQUENCE_DEFAULT-1;
388 if( get_mask_from_state(navdata->mykonos_state, MYKONOS_NAVDATA_BOOTSTRAP) == FALSE )
390 const char cmds[] = "AT*COMWDG\r";
391 at_write ((int8_t*)cmds, strlen( cmds ));
395 if( navdata->sequence > sequence )
397 if ( get_mask_from_state( mykonos_state, MYKONOS_NAVDATA_DEMO_MASK ))
399 mykonos_navdata_unpack_all(&navdata_unpacked, navdata, &navdata_cks);
400 cks = navdata_compute_cks( &msg[0], size - sizeof(navdata_cks_t) );
402 if( cks == navdata_cks )
404 //INFO ("Unpack navdata\n");
410 INFO ("[Navdata] Sequence pb : %d (distant) / %d (local)\n", navdata->sequence, sequence);
413 sequence = navdata->sequence;
424 if (navdata_udp_socket >= 0){
425 close(navdata_udp_socket);
426 navdata_udp_socket = -1;
429 INFO("NAVDATA thread stopping\n");
433 /* Public functions */
434 void navdata_stop( void )
439 nav_thread_alive = 0;
440 pthread_join(nav_thread, NULL);
443 if (navdata_udp_socket >= 0){
444 close(navdata_udp_socket);
445 navdata_udp_socket = -1;
449 void navdata_run( void )
454 nav_thread_alive = 1;
455 if ( pthread_create( &nav_thread, NULL, navdata_loop, NULL ) )
457 INFO("pthread_create: %s\n", strerror(errno));