@@ -442,6 +442,9 @@ void tiltSensorFactoryReset()
442
442
// Given a NMEA sentence, modify the sentence to use the latest tilt-compensated lat/lon/alt
443
443
// Modifies the sentence directly. Updates sentence CRC.
444
444
// Auto-detects sentence type and will only modify sentences that have lat/lon/alt (ie GGA yes, GSV no)
445
+ // Which sentences have altitude? Yes: GGA, GNS No: RMC, GLL
446
+ // Which sentences have undulation? Yes: GGA, GNS No: RMC, GLL
447
+ // See issue: https://github.com/sparkfun/SparkFun_RTK_Everywhere_Firmware/issues/334
445
448
void tiltApplyCompensation (char *nmeaSentence, int arraySize)
446
449
{
447
450
// Verify the sentence is null-terminated
@@ -481,22 +484,31 @@ void tiltApplyCompensation(char *nmeaSentence, int arraySize)
481
484
}
482
485
483
486
// Modify a GNS sentence with tilt compensation
484
- // $GNGGA,213441.00,4005.4176871,N,10511.1034563,W,1,12,99.99,1581.450,M,-21.361,M,,*7D - Original
485
- // $GNGGA,213441.00,4005.41769994,N,10507.40740734,W,1,12,99.99,1580.987,M,-21.361,M,,*7E - Modified
487
+ // $GNGNS,024034.00,4004.73854216,N,11614.19720023,E,ANAAA,28,0.8,1574.406,-8.4923,,,S*71 - Original
488
+ // $GNGNS,024034.00,4004.73854216,N,11614.19720023,E,ANAAA,28,0.8,1589.4793,-8.4923,,,S*7E - Modified
489
+ // 1580.987 is what is provided by the IMU and is the ellisoidal height
490
+ // 1580.987 is called 'ellipsoidal height' in SW Maps and includes the MSL + undulation
491
+ // To get mean sea level: 1580.987 - -8.4923 = 1589.4793
492
+ // 1589.4793 is the orthometric height in meters (MSL reference) that we need to insert into the NMEA sentence
493
+ // See issue: https://github.com/sparkfun/SparkFun_RTK_Everywhere_Firmware/issues/334
494
+ // https://support.virtual-surveyor.com/support/solutions/articles/1000261349-the-difference-between-ellipsoidal-geoid-and-orthometric-elevations-
486
495
void tiltApplyCompensationGNS (char *nmeaSentence, int arraySize)
487
496
{
488
497
char coordinateStringDDMM[strlen (" 10511.12345678" ) + 1 ] = {0 }; // UM980 outputs 8 decimals in GGA sentence
489
498
490
499
const int latitudeComma = 2 ;
491
500
const int longitudeComma = 4 ;
492
501
const int altitudeComma = 9 ;
502
+ const int undulationComma = 10 ;
493
503
494
504
uint8_t latitudeStart = 0 ;
495
505
uint8_t latitudeStop = 0 ;
496
506
uint8_t longitudeStart = 0 ;
497
507
uint8_t longitudeStop = 0 ;
498
508
uint8_t altitudeStart = 0 ;
499
509
uint8_t altitudeStop = 0 ;
510
+ uint8_t undulationStart = 0 ;
511
+ uint8_t undulationStop = 0 ;
500
512
uint8_t checksumStart = 0 ;
501
513
502
514
int commaCount = 0 ;
@@ -507,16 +519,20 @@ void tiltApplyCompensationGNS(char *nmeaSentence, int arraySize)
507
519
commaCount++;
508
520
if (commaCount == latitudeComma)
509
521
latitudeStart = x + 1 ;
510
- else if (commaCount == latitudeComma + 1 )
522
+ if (commaCount == latitudeComma + 1 )
511
523
latitudeStop = x;
512
- else if (commaCount == longitudeComma)
524
+ if (commaCount == longitudeComma)
513
525
longitudeStart = x + 1 ;
514
- else if (commaCount == longitudeComma + 1 )
526
+ if (commaCount == longitudeComma + 1 )
515
527
longitudeStop = x;
516
- else if (commaCount == altitudeComma)
528
+ if (commaCount == altitudeComma)
517
529
altitudeStart = x + 1 ;
518
- else if (commaCount == altitudeComma + 1 )
530
+ if (commaCount == altitudeComma + 1 )
519
531
altitudeStop = x;
532
+ if (commaCount == undulationComma)
533
+ undulationStart = x + 1 ;
534
+ if (commaCount == undulationComma + 1 )
535
+ undulationStop = x;
520
536
}
521
537
if (nmeaSentence[x] == ' *' )
522
538
{
@@ -526,12 +542,20 @@ void tiltApplyCompensationGNS(char *nmeaSentence, int arraySize)
526
542
}
527
543
528
544
if (latitudeStart == 0 || latitudeStop == 0 || longitudeStart == 0 || longitudeStop == 0 || altitudeStart == 0 ||
529
- altitudeStop == 0 || checksumStart == 0 )
545
+ altitudeStop == 0 || undulationStart == 0 || undulationStop == 0 || checksumStart == 0 )
530
546
{
531
547
systemPrintln (" Delineator not found" );
532
548
return ;
533
549
}
534
550
551
+ // Extract the undulation
552
+ char undulationStr[strlen (" -1602.3481" ) + 1 ]; // 4 decimals
553
+ strncpy (undulationStr, &nmeaSentence[undulationStart], undulationStop - undulationStart);
554
+ float undulation = (float )atof (undulationStr);
555
+
556
+ // Remove the undulation from the IMU's altitude
557
+ float orthometricHeight = tiltSensor->getNaviAltitude () - undulation;
558
+
535
559
char newSentence[150 ] = {0 };
536
560
537
561
if (sizeof (newSentence) < arraySize)
@@ -565,7 +589,7 @@ void tiltApplyCompensationGNS(char *nmeaSentence, int arraySize)
565
589
strncat (newSentence, nmeaSentence + longitudeStop, altitudeStart - longitudeStop);
566
590
567
591
// Convert altitude double to string
568
- snprintf (coordinateStringDDMM, sizeof (coordinateStringDDMM), " %0.3f" , tiltSensor-> getNaviAltitude () );
592
+ snprintf (coordinateStringDDMM, sizeof (coordinateStringDDMM), " %0.3f" , orthometricHeight );
569
593
570
594
// Add tilt-compensated Altitude
571
595
strncat (newSentence, coordinateStringDDMM, sizeof (newSentence) - 1 );
@@ -769,20 +793,29 @@ void tiltApplyCompensationRMC(char *nmeaSentence, int arraySize)
769
793
}
770
794
771
795
// Modify a GGA sentence with tilt compensation
772
- // $GNGGA,213441.00,4005.4176871,N,10511.1034563,W,1,12,99.99,1581.450,M,-21.361,M,,*7D - Original
773
- // $GNGGA,213441.00,4005.41769994,N,10507.40740734,W,1,12,99.99,1580.987,M,-21.361,M,,*7E - Modified
796
+ // $GNGGA,213441.00,4005.4176871,N,10511.1034563,W,1,12,99.99,1581.450,M,-21.3612,M,,*7D - Original
797
+ // $GNGGA,213441.00,4005.41769994,N,10507.40740734,W,1,12,99.99,1602.348,M,-21.3612,M,,*4C - Modified
798
+ // 1580.987 is what is provided by the IMU and is the ellisoidal height
799
+ // 'Ellipsoidal height' includes the MSL + undulation
800
+ // To get mean sea level: 1580.987 - -21.3612 = 1602.3482
801
+ // 1602.3482 is the orthometric height in meters (MSL reference) that we need to insert into the NMEA sentence
802
+ // See issue: https://github.com/sparkfun/SparkFun_RTK_Everywhere_Firmware/issues/334
803
+ // https://support.virtual-surveyor.com/support/solutions/articles/1000261349-the-difference-between-ellipsoidal-geoid-and-orthometric-elevations-
774
804
void tiltApplyCompensationGGA (char *nmeaSentence, int arraySize)
775
805
{
776
806
const int latitudeComma = 2 ;
777
807
const int longitudeComma = 4 ;
778
808
const int altitudeComma = 9 ;
809
+ const int undulationComma = 11 ;
779
810
780
811
uint8_t latitudeStart = 0 ;
781
812
uint8_t latitudeStop = 0 ;
782
813
uint8_t longitudeStart = 0 ;
783
814
uint8_t longitudeStop = 0 ;
784
815
uint8_t altitudeStart = 0 ;
785
816
uint8_t altitudeStop = 0 ;
817
+ uint8_t undulationStart = 0 ;
818
+ uint8_t undulationStop = 0 ;
786
819
uint8_t checksumStart = 0 ;
787
820
788
821
if (settings.enableImuCompensationDebug == true )
@@ -796,16 +829,20 @@ void tiltApplyCompensationGGA(char *nmeaSentence, int arraySize)
796
829
commaCount++;
797
830
if (commaCount == latitudeComma)
798
831
latitudeStart = x + 1 ;
799
- else if (commaCount == latitudeComma + 1 )
832
+ if (commaCount == latitudeComma + 1 )
800
833
latitudeStop = x;
801
- else if (commaCount == longitudeComma)
834
+ if (commaCount == longitudeComma)
802
835
longitudeStart = x + 1 ;
803
- else if (commaCount == longitudeComma + 1 )
836
+ if (commaCount == longitudeComma + 1 )
804
837
longitudeStop = x;
805
- else if (commaCount == altitudeComma)
838
+ if (commaCount == altitudeComma)
806
839
altitudeStart = x + 1 ;
807
- else if (commaCount == altitudeComma + 1 )
840
+ if (commaCount == altitudeComma + 1 )
808
841
altitudeStop = x;
842
+ if (commaCount == undulationComma)
843
+ undulationStart = x + 1 ;
844
+ if (commaCount == undulationComma + 1 )
845
+ undulationStop = x;
809
846
}
810
847
if (nmeaSentence[x] == ' *' )
811
848
{
@@ -815,12 +852,20 @@ void tiltApplyCompensationGGA(char *nmeaSentence, int arraySize)
815
852
}
816
853
817
854
if (latitudeStart == 0 || latitudeStop == 0 || longitudeStart == 0 || longitudeStop == 0 || altitudeStart == 0 ||
818
- altitudeStop == 0 || checksumStart == 0 )
855
+ altitudeStop == 0 || undulationStart == 0 || undulationStop == 0 || checksumStart == 0 )
819
856
{
820
857
systemPrintln (" Delineator not found" );
821
858
return ;
822
859
}
823
860
861
+ // Extract the undulation
862
+ char undulationStr[strlen (" -1602.3481" ) + 1 ]; // 4 decimals
863
+ strncpy (undulationStr, &nmeaSentence[undulationStart], undulationStop - undulationStart);
864
+ float undulation = (float )atof (undulationStr);
865
+
866
+ // Remove the undulation from the IMU's altitude
867
+ float orthometricHeight = tiltSensor->getNaviAltitude () - undulation;
868
+
824
869
char newSentence[150 ] = {0 };
825
870
826
871
if (sizeof (newSentence) < arraySize)
@@ -856,7 +901,7 @@ void tiltApplyCompensationGGA(char *nmeaSentence, int arraySize)
856
901
strncat (newSentence, nmeaSentence + longitudeStop, altitudeStart - longitudeStop);
857
902
858
903
// Convert altitude double to string
859
- snprintf (coordinateStringDDMM, sizeof (coordinateStringDDMM), " %0.3f" , tiltSensor-> getNaviAltitude () );
904
+ snprintf (coordinateStringDDMM, sizeof (coordinateStringDDMM), " %0.3f" , orthometricHeight );
860
905
861
906
// Add tilt-compensated Altitude
862
907
strncat (newSentence, coordinateStringDDMM, sizeof (newSentence) - 1 );
0 commit comments