5656#endif
5757
5858#include "io/gps.h"
59+ #include "io/beeper.h"
5960
6061#include "sensors/acceleration.h"
6162#include "sensors/barometer.h"
8586FASTRAM fpVector3_t imuMeasuredAccelBF ;
8687FASTRAM fpVector3_t imuMeasuredRotationBF ;
8788//centrifugal force compensated using gps
88- FASTRAM fpVector3_t compansatedGravityBF ;// cm/s/s
89+ FASTRAM fpVector3_t compensatedGravityBF ;// cm/s/s
8990
9091STATIC_FASTRAM float smallAngleCosZ ;
9192
@@ -173,8 +174,7 @@ void imuConfigure(void)
173174 * 1000× per second; the kP gains only change when the user saves settings,
174175 * so computing it here (called once per save) avoids one add, one multiply,
175176 * and one divide on every PID cycle. */
176- imuRuntimeConfig .dcm_i_limit = DEGREES_TO_RADIANS (2.0f )
177- * (imuRuntimeConfig .dcm_kp_acc + imuRuntimeConfig .dcm_kp_mag ) * 0.5f ;
177+ imuRuntimeConfig .dcm_i_limit = DEGREES_TO_RADIANS (2.0f ) * (imuRuntimeConfig .dcm_kp_acc + imuRuntimeConfig .dcm_kp_mag ) * 0.5f ;
178178}
179179
180180void imuInit (void )
@@ -192,7 +192,7 @@ void imuInit(void)
192192 // Create magnetic declination matrix
193193#ifdef USE_MAG
194194 const int deg = compassConfig ()-> mag_declination / 100 ;
195- const int min = compassConfig ()-> mag_declination % 100 ;
195+ const int min = compassConfig ()-> mag_declination % 100 ;
196196#else
197197 const int deg = 0 ;
198198 const int min = 0 ;
@@ -362,7 +362,7 @@ static float imuCalculateMcCogAccWeight(void)
362362{
363363 fpVector3_t accBFNorm ;
364364 vectorScale (& accBFNorm , & imuMeasuredAccelBFFiltered , 1.0f / GRAVITY_CMSS );
365- float wCoGAcc = constrainf ((accBFNorm .z - 1.0f )* 2 , 0.0f , 1.0f ); //z direction is verified via SITL
365+ float wCoGAcc = constrainf ((accBFNorm .z - 1.0f ) * 2.0f , 0.0f , 1.0f ); //z direction is verified via SITL
366366 wCoGAcc = wCoGAcc * imuCalculateAccelerometerWeightRateIgnore (4.0f ); //reduce weight when fast angular rate, gps acc is considered lagging
367367 return wCoGAcc ;
368368}
@@ -437,7 +437,7 @@ static void imuMahonyAHRSupdate(float dt, const fpVector3_t * gyroBF, const fpVe
437437 //vForward as trust vector
438438 if (STATE (MULTIROTOR ) && (!isMixerTransitionMixing )){
439439 vForward .z = 1.0f ;
440- }else {
440+ } else {
441441 vForward .x = 1.0f ;
442442 }
443443 fpVector3_t vHeadingEF ;
@@ -448,23 +448,22 @@ static void imuMahonyAHRSupdate(float dt, const fpVector3_t * gyroBF, const fpVe
448448 float airSpeed = gpsSol .groundSpeed ;
449449 #if defined(USE_WIND_ESTIMATOR )
450450 // remove wind elements in vCoGlocal for better heading estimation
451- if (isEstimatedWindSpeedValid () && imuConfig ()-> gps_yaw_windcomp )
452- {
451+ if (isEstimatedWindSpeedValid () && imuConfig ()-> gps_yaw_windcomp ) {
453452 vectorScale (& vCoGlocal , & vCoGlocal , gpsSol .groundSpeed );
454453 vCoGlocal .x += getEstimatedWindSpeed (X );
455454 vCoGlocal .y -= getEstimatedWindSpeed (Y );
456455 airSpeed = fast_fsqrtf (vectorNormSquared (& vCoGlocal ));
457456 }
458457 #endif
459- wCoG *= scaleRangef (constrainf ((airSpeed + gpsSol .groundSpeed )/ 2 , 400 , 1000 ), 400 , 1000 , 0.0f , 1.0f );
458+ wCoG *= scaleRangef (constrainf ((airSpeed + gpsSol .groundSpeed ) / 2.0f , 400.0f , 1000.0f ), 400.0f , 1000.0f , 0.0f , 1.0f );
460459 } else { //vCOG is not avaliable and vCOGAcc is avaliable, set the weight of vCOG to zero
461460 wCoG = 0.0f ;
462461 }
463- if (STATE (MULTIROTOR )){
462+ if (STATE (MULTIROTOR )) {
464463 //when multicopter`s orientation or speed is changing rapidly. less weight on gps heading
465464 wCoG *= imuCalculateMcCogWeight ();
466465 //handle acc based vector
467- if (vCOGAcc ){
466+ if (vCOGAcc ) {
468467 float wCoGAcc = imuCalculateMcCogAccWeight ();//stronger weight on acc if body frame z axis greate than 1G
469468 if (wCoGAcc > wCoG ){
470469 //when copter is accelerating use gps acc vector instead of gps speed vector
@@ -627,8 +626,7 @@ STATIC_UNIT_TESTED void imuUpdateEulerAngles(void)
627626 attitude .values .yaw = RADIANS_TO_DECIDEGREES (- atan2_approx (rMat [1 ][0 ], rMat [0 ][0 ]));
628627 }
629628
630- if (attitude .values .yaw < 0 )
631- attitude .values .yaw += 3600 ;
629+ if (attitude .values .yaw < 0 ) attitude .values .yaw += 3600 ;
632630
633631 /* Update small angle state */
634632 if (calculateCosTiltAngle () > smallAngleCosZ ) {
@@ -667,23 +665,17 @@ static float imuCalculateAccelerometerWeightRateIgnore(const float acc_ignore_sl
667665 // Default - don't apply rate/ignore scaling
668666 float accWeight_RateIgnore = 1.0f ;
669667
670- if (ARMING_FLAG (ARMED ) && imuConfig ()-> acc_ignore_rate )
671- {
668+ if (ARMING_FLAG (ARMED ) && imuConfig ()-> acc_ignore_rate ) {
672669 float rotRateMagnitude = fast_fsqrtf (vectorNormSquared (& imuMeasuredRotationBFFiltered ));
673670 rotRateMagnitude = rotRateMagnitude / (acc_ignore_slope_multipiler + 0.001f );
674- if ( imuConfig () -> acc_ignore_slope )
675- {
671+
672+ if ( imuConfig () -> acc_ignore_slope ) {
676673 const float rateSlopeMin = DEGREES_TO_RADIANS ((imuConfig ()-> acc_ignore_rate - imuConfig ()-> acc_ignore_slope ));
677674 const float rateSlopeMax = DEGREES_TO_RADIANS ((imuConfig ()-> acc_ignore_rate + imuConfig ()-> acc_ignore_slope ));
678675
679676 accWeight_RateIgnore = scaleRangef (constrainf (rotRateMagnitude , rateSlopeMin , rateSlopeMax ), rateSlopeMin , rateSlopeMax , 1.0f , 0.0f );
680- }
681- else
682- {
683- if (rotRateMagnitude > DEGREES_TO_RADIANS (imuConfig ()-> acc_ignore_rate ))
684- {
685- accWeight_RateIgnore = 0.0f ;
686- }
677+ } else if (rotRateMagnitude > DEGREES_TO_RADIANS (imuConfig ()-> acc_ignore_rate )) {
678+ accWeight_RateIgnore = 0.0f ;
687679 }
688680 }
689681
@@ -696,7 +688,7 @@ static void imuCalculateFilters(float dT)
696688 imuMeasuredRotationBFFiltered .x = pt1FilterApply4 (& rotRateFilterX , imuMeasuredRotationBF .x , IMU_ROTATION_LPF , dT );
697689 imuMeasuredRotationBFFiltered .y = pt1FilterApply4 (& rotRateFilterY , imuMeasuredRotationBF .y , IMU_ROTATION_LPF , dT );
698690 imuMeasuredRotationBFFiltered .z = pt1FilterApply4 (& rotRateFilterZ , imuMeasuredRotationBF .z , IMU_ROTATION_LPF , dT );
699-
691+
700692 imuMeasuredAccelBFFiltered .x = pt1FilterApply4 (& accelFilterX , imuMeasuredAccelBF .x , IMU_ROTATION_LPF , dT );
701693 imuMeasuredAccelBFFiltered .y = pt1FilterApply4 (& accelFilterY , imuMeasuredAccelBF .y , IMU_ROTATION_LPF , dT );
702694 imuMeasuredAccelBFFiltered .z = pt1FilterApply4 (& accelFilterZ , imuMeasuredAccelBF .z , IMU_ROTATION_LPF , dT );
@@ -718,8 +710,7 @@ static void imuCalculateGPSacceleration(fpVector3_t *vEstAccelEF,fpVector3_t *vE
718710
719711 // on first gps data acquired, time_delta_ms will be large, vEstcentrifugalAccelBF will be minimal to disable the compensation
720712 rtcTime_t time_delta_ms = currenttime - lastGPSNewDataTime ;
721- if (lastGPSHeartbeat != gpsSol .flags .gpsHeartbeat && time_delta_ms > 0 )
722- {
713+ if (lastGPSHeartbeat != gpsSol .flags .gpsHeartbeat && time_delta_ms > 0 ) {
723714 // on new gps frame, update accEF and estimate centrifugal accleration
724715 vEstAccelEF -> x = - (currentGPSvel .x - lastGPSvel .x ) / (MS2S (time_delta_ms )); // the x axis of accerometer is pointing backward
725716 vEstAccelEF -> y = (currentGPSvel .y - lastGPSvel .y ) / (MS2S (time_delta_ms ));
@@ -734,11 +725,11 @@ static void imuCalculateGPSacceleration(fpVector3_t *vEstAccelEF,fpVector3_t *vE
734725}
735726
736727static void imuCalculateTurnRateacceleration (fpVector3_t * vEstcentrifugalAccelBF , float dT , float * acc_ignore_slope_multipiler )
737- {
728+ {
738729 //fixed wing only
739730 static float lastspeed = -1.0f ;
740731 float currentspeed = 0 ;
741- if (isGPSTrustworthy ()){
732+ if (isGPSTrustworthy ()) {
742733 //first speed choice is gps
743734 static bool lastGPSHeartbeat ;
744735 static pt1Filter_t GPS3DspeedFilter ;
@@ -752,8 +743,7 @@ static void imuCalculateTurnRateacceleration(fpVector3_t *vEstcentrifugalAccelBF
752743 * acc_ignore_slope_multipiler = 4.0f ;
753744 }
754745#ifdef USE_PITOT
755- else if (sensors (SENSOR_PITOT ) && pitotIsHealthy ())
756- {
746+ else if (sensors (SENSOR_PITOT ) && pitotIsHealthy ()) {
757747 // second choice is pitot
758748 currentspeed = getAirspeedEstimate ();
759749 * acc_ignore_slope_multipiler = 2.0f ;
@@ -776,7 +766,7 @@ fpQuaternion_t* getTailSitterQuaternion(bool normal2tail){
776766 static bool firstRun = true;
777767 static fpQuaternion_t qNormal2Tail ;
778768 static fpQuaternion_t qTail2Normal ;
779- if (firstRun ){
769+ if (firstRun ) {
780770 fpAxisAngle_t axisAngle ;
781771 axisAngle .axis .x = 0 ;
782772 axisAngle .axis .y = 1 ;
@@ -792,7 +782,7 @@ fpQuaternion_t* getTailSitterQuaternion(bool normal2tail){
792782void imuUpdateTailSitter (void )
793783{
794784 static bool lastTailSitter = false;
795- if (((bool )STATE (TAILSITTER )) != lastTailSitter ){
785+ if (((bool )STATE (TAILSITTER )) != lastTailSitter ) {
796786 fpQuaternion_t * rotation_for_tailsitter = getTailSitterQuaternion (STATE (TAILSITTER ));
797787 quaternionMultiply (& orientation , & orientation , rotation_for_tailsitter );
798788 }
@@ -842,65 +832,76 @@ static void imuCalculateEstimatedAttitude(float dT)
842832 resetHeadingHoldTarget (DECIDEGREES_TO_DEGREES (attitude .values .yaw ));
843833 }
844834 } else if (!ARMING_FLAG (ARMED )) {
845- gpsHeadingInitialized = false;
835+ if (STATE (AIRPLANE )) {
836+ gpsHeadingInitialized = false; // required for fixed wing flight detection to work correctly
837+ } else if (!sensors (SENSOR_MAG ) && STATE (CALIBRATE_MAG )) {
838+ // When no compass available allow yaw to be set to 0 (North) as required using compass calibration stick command
839+ DISABLE_STATE (CALIBRATE_MAG );
840+ beeper (BEEPER_ACTION_SUCCESS );
841+
842+ // Re-initialize quaternion from known Roll, Pitch with yaw set to 0 (North)
843+ imuComputeQuaternionFromRPY (attitude .values .roll , attitude .values .pitch , 0 );
844+ gpsHeadingInitialized = true;
845+ }
846846 }
847847
848848 imuCalculateFilters (dT );
849+
849850 // centrifugal force compensation
850851 static fpVector3_t vEstcentrifugalAccelBF_velned ;
851852 static fpVector3_t vEstcentrifugalAccelBF_turnrate ;
852853 float acc_ignore_slope_multipiler = 1.0f ; // when using gps centrifugal_force_compensation, AccelerometerWeightRateIgnore slope will be multiplied by this value
853- if ( isGPSTrustworthy ())
854- {
854+
855+ if ( isGPSTrustworthy ()) {
855856 imuCalculateGPSacceleration (& vCOGAcc , & vEstcentrifugalAccelBF_velned , & acc_ignore_slope_multipiler );
856857 useCOGAcc = true; //currently only for multicopter
857858 }
858- if ( STATE ( AIRPLANE ))
859- {
859+
860+ if ( STATE ( AIRPLANE )) {
860861 imuCalculateTurnRateacceleration (& vEstcentrifugalAccelBF_turnrate , dT , & acc_ignore_slope_multipiler );
861862 }
862- if ( imuConfig () -> inertia_comp_method == COMPMETHOD_ADAPTIVE && isGPSTrustworthy () && STATE ( AIRPLANE ))
863- {
863+
864+ if ( imuConfig () -> inertia_comp_method == COMPMETHOD_ADAPTIVE && isGPSTrustworthy () && STATE ( AIRPLANE )) {
864865 //pick the best centrifugal acceleration between velned and turnrate
865- fpVector3_t compansatedGravityBF_velned ;
866- vectorAdd (& compansatedGravityBF_velned , & imuMeasuredAccelBF , & vEstcentrifugalAccelBF_velned );
867- float velned_error = fabsf (fast_fsqrtf (vectorNormSquared (& compansatedGravityBF_velned )) - GRAVITY_CMSS );
866+ fpVector3_t compensatedGravityBF_velned ;
867+ vectorAdd (& compensatedGravityBF_velned , & imuMeasuredAccelBF , & vEstcentrifugalAccelBF_velned );
868+ float velned_error = fabsf (fast_fsqrtf (vectorNormSquared (& compensatedGravityBF_velned )) - GRAVITY_CMSS );
868869
869- fpVector3_t compansatedGravityBF_turnrate ;
870- vectorAdd (& compansatedGravityBF_turnrate , & imuMeasuredAccelBF , & vEstcentrifugalAccelBF_turnrate );
871- float turnrate_error = fabsf (fast_fsqrtf (vectorNormSquared (& compansatedGravityBF_turnrate )) - GRAVITY_CMSS );
870+ fpVector3_t compensatedGravityBF_turnrate ;
871+ vectorAdd (& compensatedGravityBF_turnrate , & imuMeasuredAccelBF , & vEstcentrifugalAccelBF_turnrate );
872+ float turnrate_error = fabsf (fast_fsqrtf (vectorNormSquared (& compensatedGravityBF_turnrate )) - GRAVITY_CMSS );
872873
873- compansatedGravityBF = velned_error > turnrate_error ? compansatedGravityBF_turnrate : compansatedGravityBF_velned ;
874+ compensatedGravityBF = velned_error > turnrate_error ? compensatedGravityBF_turnrate : compensatedGravityBF_velned ;
874875 }
875876 else if (((imuConfig ()-> inertia_comp_method == COMPMETHOD_VELNED ) || (imuConfig ()-> inertia_comp_method == COMPMETHOD_ADAPTIVE )) && isGPSTrustworthy ())
876877 {
877878 //velned centrifugal force compensation, quad will use this method
878- vectorAdd (& compansatedGravityBF , & imuMeasuredAccelBF , & vEstcentrifugalAccelBF_velned );
879+ vectorAdd (& compensatedGravityBF , & imuMeasuredAccelBF , & vEstcentrifugalAccelBF_velned );
879880 }
880881 else if (STATE (AIRPLANE ))
881882 {
882883 //turnrate centrifugal force compensation
883- vectorAdd (& compansatedGravityBF , & imuMeasuredAccelBF , & vEstcentrifugalAccelBF_turnrate );
884+ vectorAdd (& compensatedGravityBF , & imuMeasuredAccelBF , & vEstcentrifugalAccelBF_turnrate );
884885 }
885886 else
886887 {
887- compansatedGravityBF = imuMeasuredAccelBF ;
888+ compensatedGravityBF = imuMeasuredAccelBF ;
888889 }
889890#else
890891 // In absence of GPS MAG is the only option
891892 if (canUseMAG ) {
892893 useMag = true;
893894 }
894- compansatedGravityBF = imuMeasuredAccelBF
895+ compensatedGravityBF = imuMeasuredAccelBF ;
895896#endif
896- float accWeight = imuGetPGainScaleFactor () * imuCalculateAccelerometerWeightNearness (& compansatedGravityBF );
897+ float accWeight = imuGetPGainScaleFactor () * imuCalculateAccelerometerWeightNearness (& compensatedGravityBF );
897898 accWeight = accWeight * imuCalculateAccelerometerWeightRateIgnore (acc_ignore_slope_multipiler );
898899 const bool useAcc = (accWeight > 0.001f );
899900
900901 const float magWeight = imuGetPGainScaleFactor () * 1.0f ;
901902 fpVector3_t measuredMagBF = {.v = {mag .magADC [X ], mag .magADC [Y ], mag .magADC [Z ]}};
902903 imuMahonyAHRSupdate (dT , & imuMeasuredRotationBF ,
903- useAcc ? & compansatedGravityBF : NULL ,
904+ useAcc ? & compensatedGravityBF : NULL ,
904905 useMag ? & measuredMagBF : NULL ,
905906 useCOG ? & vCOG : NULL ,
906907 useCOGAcc ? & vCOGAcc : NULL ,
@@ -950,7 +951,6 @@ void imuUpdateAttitude(timeUs_t currentTimeUs)
950951 acc .accADCf [Z ] = 0.0f ;
951952 }
952953}
953-
954954
955955bool isImuReady (void )
956956{
@@ -966,9 +966,13 @@ float calculateCosTiltAngle(void)
966966{
967967 return 1.0f - 2.0f * sq (orientation .q1 ) - 2.0f * sq (orientation .q2 );
968968}
969-
969+ #if defined(USE_GPS )
970+ bool isYawZeroResetAllowed (void )
971+ {
972+ return !ARMING_FLAG (ARMED ) && !STATE (AIRPLANE ) && sensors (SENSOR_GPS ) && !sensors (SENSOR_MAG );
973+ }
974+ #endif
970975#if defined(SITL_BUILD ) || defined (USE_SIMULATOR )
971-
972976void imuSetAttitudeRPY (int16_t roll , int16_t pitch , int16_t yaw )
973977{
974978 attitude .values .roll = roll ;
0 commit comments