@@ -88,6 +88,9 @@ bool GPS::initialize()
8888 }
8989 this ->logger ->log (" Serial connection started." );
9090
91+ this ->logger ->log (" Setting GPS to pedestrian mode" );
92+ this ->enter_pedestrian_mode ();
93+
9194 this ->logger ->log (" Starting GPS frame thread..." );
9295 thread t (&GPS ::gps_thread, this );
9396 t.detach ();
@@ -338,3 +341,211 @@ void GPS::parse_RMC(const string& frame)
338341 this ->velocity .course = stof (s_data[8 ]);
339342 }
340343}
344+
345+ void GPS::enter_airborne_1g_mode ()
346+ {
347+ int gps_dynamic_model_set_success = 0 ;
348+ struct timeval time_now, time_start;
349+ long ms_now, ms_start;
350+
351+ unsigned char setdm6[] = {
352+ 0xB5 , 0x62 , 0x06 , 0x24 , 0x24 , 0x00 , 0xFF , 0xFF , 0x06 , // Byte at offset 2
353+ 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 , 0x27 , 0x00 , 0x00 , // determines new
354+ 0x05 , 0x00 , 0xFA , 0x00 , 0xFA , 0x00 , 0x64 , 0x00 , 0x2C , // operation mode.
355+ 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
356+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x16 , 0xDC
357+ };
358+ uint8_t sz_setdm6 = 44 ;
359+
360+ gettimeofday (&time_start, NULL );
361+ ms_start = (long )((time_start.tv_sec )*1000 + (time_start.tv_usec )/1000 );
362+ ms_now = ms_start;
363+
364+ while (!gps_dynamic_model_set_success && (ms_now - ms_start)<6000 ) // Prevent lock and
365+ { // timeout if not set
366+ gettimeofday (&time_now, NULL ); // after six seconds
367+ ms_now = (long )((time_now.tv_sec )*1000 + (time_now.tv_usec )/1000 );
368+
369+ this ->send_ublox_packet (setdm6, sz_setdm6);
370+ gps_dynamic_model_set_success = this ->receive_check_ublox_ack (setdm6);
371+ }
372+ if (gps_dynamic_model_set_success)
373+ {
374+ this ->logger ->log (" GPS entered airborne (<1g) mode successfully" );
375+ }
376+ else
377+ {
378+ this ->logger ->log (" GPS failed to enter airborne (<1g) mode" );
379+ }
380+ }
381+
382+ void GPS::enter_stationary_mode ()
383+ {
384+ int gps_dynamic_model_set_success = 0 ;
385+ struct timeval time_now, time_start;
386+ long ms_now, ms_start;
387+
388+ unsigned char setdm2[] = {
389+ 0xB5 , 0x62 , 0x02 , 0x24 , 0x24 , 0x00 , 0xFF , 0xFF , 0x06 , // Byte at offset 2
390+ 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 , 0x27 , 0x00 , 0x00 , // determines new
391+ 0x05 , 0x00 , 0xFA , 0x00 , 0xFA , 0x00 , 0x64 , 0x00 , 0x2C , // operation mode.
392+ 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
393+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x16 , 0xDC
394+ };
395+ uint8_t sz_setdm2 = 44 ;
396+
397+ gettimeofday (&time_start, NULL );
398+ ms_start = (long )((time_start.tv_sec )*1000 + (time_start.tv_usec )/1000 );
399+ ms_now = ms_start;
400+
401+ while (!gps_dynamic_model_set_success && (ms_now - ms_start)<6000 ) // Prevent lock and
402+ { // timeout if not set
403+ gettimeofday (&time_now, NULL ); // after six seconds
404+ ms_now = (long )((time_now.tv_sec )*1000 + (time_now.tv_usec )/1000 );
405+
406+ this ->send_ublox_packet (setdm2, sz_setdm2);
407+ gps_dynamic_model_set_success = this ->receive_check_ublox_ack (setdm2);
408+ }
409+
410+ if (gps_dynamic_model_set_success)
411+ {
412+ this ->logger ->log (" GPS entered stationary mode successfully" );
413+ }
414+ else
415+ {
416+ this ->logger ->log (" GPS failed to enter stationary mode" );
417+ }
418+ }
419+
420+ void GPS::enter_pedestrian_mode ()
421+ {
422+ int gps_dynamic_model_set_success = 0 ;
423+ struct timeval time_now, time_start;
424+ long ms_now, ms_start;
425+
426+ unsigned char setdm3[] = {
427+ 0xB5 , 0x62 , 0x03 , 0x24 , 0x24 , 0x00 , 0xFF , 0xFF , 0x06 , // Byte at offset 2
428+ 0x03 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 , 0x27 , 0x00 , 0x00 , // determines new
429+ 0x05 , 0x00 , 0xFA , 0x00 , 0xFA , 0x00 , 0x64 , 0x00 , 0x2C , // operation mode.
430+ 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
431+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x16 , 0xDC
432+ };
433+ uint8_t sz_setdm3 = 44 ;
434+
435+ gettimeofday (&time_start, NULL );
436+ ms_start = (long )((time_start.tv_sec )*1000 + (time_start.tv_usec )/1000 );
437+ ms_now = ms_start;
438+
439+ while (!gps_dynamic_model_set_success && (ms_now - ms_start)<6000 ) // Prevent lock and
440+ { // timeout if not set
441+ gettimeofday (&time_now, NULL ); // after six seconds
442+ ms_now = (long )((time_now.tv_sec )*1000 + (time_now.tv_usec )/1000 );
443+
444+ this ->send_ublox_packet (setdm3, sz_setdm3);
445+ gps_dynamic_model_set_success = this ->receive_check_ublox_ack (setdm3);
446+ }
447+
448+ if (gps_dynamic_model_set_success)
449+ {
450+ this ->logger ->log (" GPS entered pedestrian mode successfully" );
451+ }
452+ else
453+ {
454+ this ->logger ->log (" GPS failed to enter pedestrian mode" );
455+ }
456+ }
457+
458+
459+ void GPS::send_ublox_packet (unsigned char *message, uint8_t len)
460+ {
461+ if (this ->serial ->is_open ())
462+ {
463+ this ->serial ->flush ();
464+ this ->serial ->write ((unsigned char )0xFF );
465+ this_thread::sleep_for (500ms);
466+ for (unsigned int i = 0 ; i<len; i++){
467+ this ->serial ->write (message[i]);
468+ }
469+ }else
470+ {
471+ this ->logger ->log (" Tried to send a packet, but the serial is closed" );
472+ }
473+ }
474+
475+ bool GPS::receive_check_ublox_ack (unsigned char *message)
476+ {
477+ unsigned char ack_packet[10 ];
478+ unsigned int bytes_ordered;
479+ unsigned char byte;
480+ struct timeval time_now, time_start;
481+ long ms_now, ms_start;
482+
483+ ack_packet[0 ] = 0xB5 ;
484+ ack_packet[1 ] = 0x62 ;
485+ ack_packet[2 ] = 0x05 ;
486+ ack_packet[3 ] = 0x01 ;
487+ ack_packet[4 ] = 0x02 ;
488+ ack_packet[5 ] = 0x00 ;
489+ ack_packet[6 ] = message[2 ];
490+ ack_packet[7 ] = message[3 ];
491+ ack_packet[8 ] = 0x00 ;
492+ ack_packet[9 ] = 0x00 ;
493+
494+ for (unsigned int i = 0 ; i<8 ; i++){
495+ ack_packet[8 ]+= ack_packet[i];
496+ ack_packet[9 ]+= ack_packet[8 ];
497+ }
498+ bytes_ordered = 0 ;
499+
500+ gettimeofday (&time_start, NULL );
501+ ms_start = (long )((time_start.tv_sec )*1000 + (time_start.tv_usec )/1000 );
502+ ms_now = ms_start;
503+
504+ while (ms_now - ms_start <= 3000 ){ // Avoid lock by
505+ gettimeofday (&time_now, NULL ); // timing out after
506+ ms_now = (long )((time_now.tv_sec )*1000 + (time_now.tv_usec )/1000 ); // 3s
507+
508+ if (bytes_ordered > 9 )
509+ {
510+ return true ;
511+ }
512+
513+ if (this ->serial ->available ())
514+ {
515+ byte = (unsigned char )this ->serial ->read_char ();
516+ if (byte == ack_packet[bytes_ordered])
517+ {
518+ bytes_ordered++;
519+ }
520+ else
521+ {
522+ bytes_ordered = 0 ;
523+ }
524+ }
525+ }
526+ return false ;
527+ }
528+
529+ void GPS::notify_initialization ()
530+ {
531+ this ->logger ->log (" Initialization notified. Switching to pedestrian mode" );
532+ this ->enter_pedestrian_mode ();
533+ }
534+
535+ void GPS::notify_takeoff ()
536+ {
537+ this ->logger ->log (" Takeoff notified. Switching to airborne mode" );
538+ this ->enter_airborne_1g_mode ();
539+ }
540+
541+ void GPS::notify_safe_mode ()
542+ {
543+ this ->logger ->log (" Safe mode entry notified. Switching to airborne mode" );
544+ this ->enter_airborne_1g_mode ();
545+ }
546+
547+ void GPS::notify_landing ()
548+ {
549+ this ->logger ->log (" Landing notified. Switching to stationary mode" );
550+ this ->enter_stationary_mode ();
551+ }
0 commit comments