123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176 |
- #include <AP_HAL/AP_HAL.h>
- #include "AP_NavEKF2.h"
- #include "AP_NavEKF2_core.h"
- #include <AP_AHRS/AP_AHRS.h>
- #include <AP_Vehicle/AP_Vehicle.h>
- #include <GCS_MAVLink/GCS.h>
- #include <stdio.h>
- extern const AP_HAL::HAL& hal;
- void NavEKF2_core::controlMagYawReset()
- {
-
-
-
- if (assume_zero_sideslip() && !finalInflightYawInit && inFlight ) {
- gpsYawResetRequest = true;
- return;
- } else {
- gpsYawResetRequest = false;
- }
-
- Vector3f deltaRotVecTemp;
- Quaternion deltaQuatTemp;
- bool flightResetAllowed = false;
- bool initialResetAllowed = false;
- if (!finalInflightYawInit) {
-
- deltaQuatTemp = stateStruct.quat / prevQuatMagReset;
- prevQuatMagReset = stateStruct.quat;
-
- deltaQuatTemp.to_axis_angle(deltaRotVecTemp);
-
- bool angRateOK = deltaRotVecTemp.length() < 0.1745f;
- initialResetAllowed = angRateOK;
- flightResetAllowed = angRateOK && !onGround;
- }
-
- bool finalResetRequest = false;
- bool interimResetRequest = false;
- if (flightResetAllowed && !assume_zero_sideslip()) {
-
-
- finalResetRequest = (stateStruct.position.z - posDownAtTakeoff) < -EKF2_MAG_FINAL_RESET_ALT;
-
- bool hgtIncreasing = (posDownAtLastMagReset-stateStruct.position.z) > 0.5f;
- float yawInnovIncrease = fabsf(innovYaw) - fabsf(yawInnovAtLastMagReset);
-
- bool yawInnovIncreasing = yawInnovIncrease > 0.25f;
-
- deltaQuatTemp = quatAtLastMagReset / stateStruct.quat;
- deltaQuatTemp.to_axis_angle(deltaRotVecTemp);
- bool largeAngleChange = deltaRotVecTemp.length() > yawInnovIncrease;
-
-
- interimResetRequest = hgtIncreasing && yawInnovIncreasing && !largeAngleChange;
- }
-
- bool initialResetRequest = initialResetAllowed && !yawAlignComplete;
-
- magYawResetRequest = magYawResetRequest ||
- initialResetRequest ||
- interimResetRequest ||
- finalResetRequest;
-
- if (magYawResetRequest || magStateResetRequest || extNavYawResetRequest) {
-
- if (extNavYawResetRequest) {
-
- Vector3f eulerAnglesOld;
- stateStruct.quat.to_euler(eulerAnglesOld.x, eulerAnglesOld.y, eulerAnglesOld.z);
-
- Quaternion prevQuat = stateStruct.quat;
-
- Vector3f eulerAnglesNew;
- extNavDataDelayed.quat.to_euler(eulerAnglesNew.x, eulerAnglesNew.y, eulerAnglesNew.z);
-
- stateStruct.quat.from_euler(eulerAnglesOld.x, eulerAnglesOld.y, eulerAnglesNew.z);
-
- prevQuat = stateStruct.quat/prevQuat;
- StoreQuatRotate(prevQuat);
-
- if (!yawAlignComplete) {
- gcs().send_text(MAV_SEVERITY_INFO, "EKF2 IMU%u ext nav yaw alignment complete",(unsigned)imu_index);
- }
-
-
- yawAlignComplete = true;
- finalInflightYawInit = true;
-
- extNavYawResetRequest = false;
- } else if (magYawResetRequest || magStateResetRequest) {
-
- Vector3f eulerAngles;
- stateStruct.quat.to_euler(eulerAngles.x, eulerAngles.y, eulerAngles.z);
-
-
- Quaternion newQuat = calcQuatAndFieldStates(eulerAngles.x, eulerAngles.y);
- if (magYawResetRequest) {
-
- Quaternion prevQuat = stateStruct.quat;
-
- stateStruct.quat = newQuat;
-
- prevQuat = stateStruct.quat/prevQuat;
- StoreQuatRotate(prevQuat);
-
- if (!yawAlignComplete) {
- gcs().send_text(MAV_SEVERITY_INFO, "EKF2 IMU%u initial yaw alignment complete",(unsigned)imu_index);
- }
-
- if (finalResetRequest) {
- gcs().send_text(MAV_SEVERITY_INFO, "EKF2 IMU%u in-flight yaw alignment complete",(unsigned)imu_index);
- } else if (interimResetRequest) {
- gcs().send_text(MAV_SEVERITY_WARNING, "EKF2 IMU%u ground mag anomaly, yaw re-aligned",(unsigned)imu_index);
- }
-
- recordYawReset();
-
- magYawResetRequest = false;
-
-
- if (interimResetRequest) {
- finalInflightYawInit = false;
- finalInflightMagInit = false;
- }
- }
- }
- }
- }
- void NavEKF2_core::realignYawGPS()
- {
- if ((sq(gpsDataDelayed.vel.x) + sq(gpsDataDelayed.vel.y)) > 25.0f) {
-
- Vector3f eulerAngles;
- stateStruct.quat.to_euler(eulerAngles.x, eulerAngles.y, eulerAngles.z);
-
- float velYaw = atan2f(stateStruct.velocity.y,stateStruct.velocity.x);
-
- float gpsYaw = atan2f(gpsDataDelayed.vel.y,gpsDataDelayed.vel.x);
-
- float yawErr = MAX(fabsf(wrap_PI(gpsYaw - velYaw)),fabsf(wrap_PI(gpsYaw - eulerAngles.z)));
-
- badMagYaw = ((yawErr > 0.7854f) && (velTestRatio > 1.0f) && (PV_AidingMode == AID_ABSOLUTE)) || !yawAlignComplete;
-
- if (badMagYaw) {
-
- stateStruct.quat.from_euler(eulerAngles.x, eulerAngles.y, gpsYaw);
-
- ResetVelocity();
- ResetPosition();
-
- gcs().send_text(MAV_SEVERITY_INFO, "EKF2 IMU%u yaw aligned to GPS velocity",(unsigned)imu_index);
-
- zeroAttCovOnly();
-
- recordYawReset();
-
- gpsYawResetRequest = false;
- magYawResetRequest = false;
- if (use_compass()) {
-
- magStateResetRequest = true;
-
- allMagSensorsFailed = false;
- }
- }
- }
- }
- void NavEKF2_core::SelectMagFusion()
- {
-
- hal.util->perf_begin(_perf_FuseMagnetometer);
-
-
- magFusePerformed = false;
-
- readMagData();
-
- if (magHealth) {
- magTimeout = false;
- lastHealthyMagTime_ms = imuSampleTime_ms;
- } else if ((imuSampleTime_ms - lastHealthyMagTime_ms) > frontend->magFailTimeLimit_ms && use_compass()) {
- magTimeout = true;
- }
-
- magDataToFuse = storedMag.recall(magDataDelayed,imuDataDelayed.time_ms);
-
- if (magDataToFuse && use_compass()) {
- controlMagYawReset();
- }
-
-
- bool dataReady = (magDataToFuse && statesInitialised && use_compass() && yawAlignComplete);
- if (dataReady) {
-
- if(inhibitMagStates || magStateResetRequest || !magStateInitComplete) {
- fuseEulerYaw();
-
- magTestRatio.zero();
- } else {
-
-
-
- if (PV_AidingMode != AID_ABSOLUTE ||
- (frontend->_mag_ef_limit > 0 && have_table_earth_field)) {
- FuseDeclination(0.34f);
- }
-
- for (mag_state.obsIndex = 0; mag_state.obsIndex <= 2; mag_state.obsIndex++) {
- hal.util->perf_begin(_perf_test[0]);
- FuseMagnetometer();
- hal.util->perf_end(_perf_test[0]);
-
- if (!magHealth) {
- break;
- }
- }
-
- yawTestRatio = 0.0f;
- }
- }
-
-
- if (!use_compass()) {
- if (onGround && (imuSampleTime_ms - lastYawTime_ms > 1000)) {
- fuseEulerYaw();
- magTestRatio.zero();
- yawTestRatio = 0.0f;
- }
- }
-
-
- if (!magFieldLearned && finalInflightMagInit) {
- magFieldLearned = (P[16][16] < sq(0.01f)) && (P[17][17] < sq(0.01f)) && (P[18][18] < sq(0.01f));
- }
-
- if (magFieldLearned && !inhibitMagStates) {
- earthMagFieldVar.x = P[16][16];
- earthMagFieldVar.y = P[17][17];
- earthMagFieldVar.z = P[18][18];
- bodyMagFieldVar.x = P[19][19];
- bodyMagFieldVar.y = P[20][20];
- bodyMagFieldVar.z = P[21][21];
- }
-
- hal.util->perf_end(_perf_FuseMagnetometer);
- }
- void NavEKF2_core::FuseMagnetometer()
- {
- hal.util->perf_begin(_perf_test[1]);
-
-
- ftype &q0 = mag_state.q0;
- ftype &q1 = mag_state.q1;
- ftype &q2 = mag_state.q2;
- ftype &q3 = mag_state.q3;
- ftype &magN = mag_state.magN;
- ftype &magE = mag_state.magE;
- ftype &magD = mag_state.magD;
- ftype &magXbias = mag_state.magXbias;
- ftype &magYbias = mag_state.magYbias;
- ftype &magZbias = mag_state.magZbias;
- uint8_t &obsIndex = mag_state.obsIndex;
- Matrix3f &DCM = mag_state.DCM;
- Vector3f &MagPred = mag_state.MagPred;
- ftype &R_MAG = mag_state.R_MAG;
- ftype *SH_MAG = &mag_state.SH_MAG[0];
- Vector24 H_MAG;
- Vector6 SK_MX;
- Vector6 SK_MY;
- Vector6 SK_MZ;
- hal.util->perf_end(_perf_test[1]);
-
-
-
-
-
-
-
-
- if (obsIndex == 0)
- {
- hal.util->perf_begin(_perf_test[2]);
-
- q0 = stateStruct.quat[0];
- q1 = stateStruct.quat[1];
- q2 = stateStruct.quat[2];
- q3 = stateStruct.quat[3];
- magN = stateStruct.earth_magfield[0];
- magE = stateStruct.earth_magfield[1];
- magD = stateStruct.earth_magfield[2];
- magXbias = stateStruct.body_magfield[0];
- magYbias = stateStruct.body_magfield[1];
- magZbias = stateStruct.body_magfield[2];
-
-
- DCM[0][0] = q0*q0 + q1*q1 - q2*q2 - q3*q3;
- DCM[0][1] = 2.0f*(q1*q2 + q0*q3);
- DCM[0][2] = 2.0f*(q1*q3-q0*q2);
- DCM[1][0] = 2.0f*(q1*q2 - q0*q3);
- DCM[1][1] = q0*q0 - q1*q1 + q2*q2 - q3*q3;
- DCM[1][2] = 2.0f*(q2*q3 + q0*q1);
- DCM[2][0] = 2.0f*(q1*q3 + q0*q2);
- DCM[2][1] = 2.0f*(q2*q3 - q0*q1);
- DCM[2][2] = q0*q0 - q1*q1 - q2*q2 + q3*q3;
- MagPred[0] = DCM[0][0]*magN + DCM[0][1]*magE + DCM[0][2]*magD + magXbias;
- MagPred[1] = DCM[1][0]*magN + DCM[1][1]*magE + DCM[1][2]*magD + magYbias;
- MagPred[2] = DCM[2][0]*magN + DCM[2][1]*magE + DCM[2][2]*magD + magZbias;
-
- for (uint8_t i = 0; i<=2; i++) {
- innovMag[i] = MagPred[i] - magDataDelayed.mag[i];
- }
-
- R_MAG = sq(constrain_float(frontend->_magNoise, 0.01f, 0.5f)) + sq(frontend->magVarRateScale*delAngCorrected.length() / imuDataDelayed.delAngDT);
-
- SH_MAG[0] = sq(q0) - sq(q1) + sq(q2) - sq(q3);
- SH_MAG[1] = sq(q0) + sq(q1) - sq(q2) - sq(q3);
- SH_MAG[2] = sq(q0) - sq(q1) - sq(q2) + sq(q3);
- SH_MAG[3] = 2.0f*q0*q1 + 2.0f*q2*q3;
- SH_MAG[4] = 2.0f*q0*q3 + 2.0f*q1*q2;
- SH_MAG[5] = 2.0f*q0*q2 + 2.0f*q1*q3;
- SH_MAG[6] = magE*(2.0f*q0*q1 - 2.0f*q2*q3);
- SH_MAG[7] = 2.0f*q1*q3 - 2.0f*q0*q2;
- SH_MAG[8] = 2.0f*q0*q3;
-
-
- varInnovMag[0] = (P[19][19] + R_MAG - P[1][19]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[16][19]*SH_MAG[1] + P[17][19]*SH_MAG[4] + P[18][19]*SH_MAG[7] + P[2][19]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2)) - (magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5])*(P[19][1] - P[1][1]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[16][1]*SH_MAG[1] + P[17][1]*SH_MAG[4] + P[18][1]*SH_MAG[7] + P[2][1]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2))) + SH_MAG[1]*(P[19][16] - P[1][16]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[16][16]*SH_MAG[1] + P[17][16]*SH_MAG[4] + P[18][16]*SH_MAG[7] + P[2][16]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2))) + SH_MAG[4]*(P[19][17] - P[1][17]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[16][17]*SH_MAG[1] + P[17][17]*SH_MAG[4] + P[18][17]*SH_MAG[7] + P[2][17]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2))) + SH_MAG[7]*(P[19][18] - P[1][18]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[16][18]*SH_MAG[1] + P[17][18]*SH_MAG[4] + P[18][18]*SH_MAG[7] + P[2][18]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2))) + (magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2))*(P[19][2] - P[1][2]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[16][2]*SH_MAG[1] + P[17][2]*SH_MAG[4] + P[18][2]*SH_MAG[7] + P[2][2]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2))));
- if (varInnovMag[0] >= R_MAG) {
- faultStatus.bad_xmag = false;
- } else {
-
-
- CovarianceInit();
- obsIndex = 1;
- faultStatus.bad_xmag = true;
- hal.util->perf_end(_perf_test[2]);
- return;
- }
-
- varInnovMag[1] = (P[20][20] + R_MAG + P[0][20]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[17][20]*SH_MAG[0] + P[18][20]*SH_MAG[3] - (SH_MAG[8] - 2.0f*q1*q2)*(P[20][16] + P[0][16]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[17][16]*SH_MAG[0] + P[18][16]*SH_MAG[3] - P[2][16]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) - P[16][16]*(SH_MAG[8] - 2.0f*q1*q2)) - P[2][20]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) + (magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5])*(P[20][0] + P[0][0]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[17][0]*SH_MAG[0] + P[18][0]*SH_MAG[3] - P[2][0]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) - P[16][0]*(SH_MAG[8] - 2.0f*q1*q2)) + SH_MAG[0]*(P[20][17] + P[0][17]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[17][17]*SH_MAG[0] + P[18][17]*SH_MAG[3] - P[2][17]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) - P[16][17]*(SH_MAG[8] - 2.0f*q1*q2)) + SH_MAG[3]*(P[20][18] + P[0][18]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[17][18]*SH_MAG[0] + P[18][18]*SH_MAG[3] - P[2][18]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) - P[16][18]*(SH_MAG[8] - 2.0f*q1*q2)) - P[16][20]*(SH_MAG[8] - 2.0f*q1*q2) - (magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1])*(P[20][2] + P[0][2]*(magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5]) + P[17][2]*SH_MAG[0] + P[18][2]*SH_MAG[3] - P[2][2]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) - P[16][2]*(SH_MAG[8] - 2.0f*q1*q2)));
- if (varInnovMag[1] >= R_MAG) {
- faultStatus.bad_ymag = false;
- } else {
-
-
- CovarianceInit();
- obsIndex = 2;
- faultStatus.bad_ymag = true;
- hal.util->perf_end(_perf_test[2]);
- return;
- }
-
- varInnovMag[2] = (P[21][21] + R_MAG + P[16][21]*SH_MAG[5] + P[18][21]*SH_MAG[2] - (2.0f*q0*q1 - 2.0f*q2*q3)*(P[21][17] + P[16][17]*SH_MAG[5] + P[18][17]*SH_MAG[2] - P[0][17]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2)) + P[1][17]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) - P[17][17]*(2.0f*q0*q1 - 2.0f*q2*q3)) - P[0][21]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2)) + P[1][21]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) + SH_MAG[5]*(P[21][16] + P[16][16]*SH_MAG[5] + P[18][16]*SH_MAG[2] - P[0][16]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2)) + P[1][16]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) - P[17][16]*(2.0f*q0*q1 - 2.0f*q2*q3)) + SH_MAG[2]*(P[21][18] + P[16][18]*SH_MAG[5] + P[18][18]*SH_MAG[2] - P[0][18]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2)) + P[1][18]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) - P[17][18]*(2.0f*q0*q1 - 2.0f*q2*q3)) - (magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2))*(P[21][0] + P[16][0]*SH_MAG[5] + P[18][0]*SH_MAG[2] - P[0][0]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2)) + P[1][0]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) - P[17][0]*(2.0f*q0*q1 - 2.0f*q2*q3)) - P[17][21]*(2.0f*q0*q1 - 2.0f*q2*q3) + (magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1])*(P[21][1] + P[16][1]*SH_MAG[5] + P[18][1]*SH_MAG[2] - P[0][1]*(magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2)) + P[1][1]*(magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1]) - P[17][1]*(2.0f*q0*q1 - 2.0f*q2*q3)));
- if (varInnovMag[2] >= R_MAG) {
- faultStatus.bad_zmag = false;
- } else {
-
-
- CovarianceInit();
- obsIndex = 3;
- faultStatus.bad_zmag = true;
- hal.util->perf_end(_perf_test[2]);
- return;
- }
-
- for (uint8_t i = 0; i<=2; i++) {
- magTestRatio[i] = sq(innovMag[i]) / (sq(MAX(0.01f * (float)frontend->_magInnovGate, 1.0f)) * varInnovMag[i]);
- }
-
- magHealth = (magTestRatio[0] < 1.0f && magTestRatio[1] < 1.0f && magTestRatio[2] < 1.0f);
-
- if (!magHealth) {
- hal.util->perf_end(_perf_test[2]);
- return;
- }
- for (uint8_t i = 0; i<=stateIndexLim; i++) H_MAG[i] = 0.0f;
- H_MAG[1] = SH_MAG[6] - magD*SH_MAG[2] - magN*SH_MAG[5];
- H_MAG[2] = magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2);
- H_MAG[16] = SH_MAG[1];
- H_MAG[17] = SH_MAG[4];
- H_MAG[18] = SH_MAG[7];
- H_MAG[19] = 1.0f;
-
- SK_MX[0] = 1.0f / varInnovMag[0];
- SK_MX[1] = magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2);
- SK_MX[2] = magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5];
- SK_MX[3] = SH_MAG[7];
- Kfusion[0] = SK_MX[0]*(P[0][19] + P[0][16]*SH_MAG[1] + P[0][17]*SH_MAG[4] - P[0][1]*SK_MX[2] + P[0][2]*SK_MX[1] + P[0][18]*SK_MX[3]);
- Kfusion[1] = SK_MX[0]*(P[1][19] + P[1][16]*SH_MAG[1] + P[1][17]*SH_MAG[4] - P[1][1]*SK_MX[2] + P[1][2]*SK_MX[1] + P[1][18]*SK_MX[3]);
- Kfusion[2] = SK_MX[0]*(P[2][19] + P[2][16]*SH_MAG[1] + P[2][17]*SH_MAG[4] - P[2][1]*SK_MX[2] + P[2][2]*SK_MX[1] + P[2][18]*SK_MX[3]);
- Kfusion[3] = SK_MX[0]*(P[3][19] + P[3][16]*SH_MAG[1] + P[3][17]*SH_MAG[4] - P[3][1]*SK_MX[2] + P[3][2]*SK_MX[1] + P[3][18]*SK_MX[3]);
- Kfusion[4] = SK_MX[0]*(P[4][19] + P[4][16]*SH_MAG[1] + P[4][17]*SH_MAG[4] - P[4][1]*SK_MX[2] + P[4][2]*SK_MX[1] + P[4][18]*SK_MX[3]);
- Kfusion[5] = SK_MX[0]*(P[5][19] + P[5][16]*SH_MAG[1] + P[5][17]*SH_MAG[4] - P[5][1]*SK_MX[2] + P[5][2]*SK_MX[1] + P[5][18]*SK_MX[3]);
- Kfusion[6] = SK_MX[0]*(P[6][19] + P[6][16]*SH_MAG[1] + P[6][17]*SH_MAG[4] - P[6][1]*SK_MX[2] + P[6][2]*SK_MX[1] + P[6][18]*SK_MX[3]);
- Kfusion[7] = SK_MX[0]*(P[7][19] + P[7][16]*SH_MAG[1] + P[7][17]*SH_MAG[4] - P[7][1]*SK_MX[2] + P[7][2]*SK_MX[1] + P[7][18]*SK_MX[3]);
- Kfusion[8] = SK_MX[0]*(P[8][19] + P[8][16]*SH_MAG[1] + P[8][17]*SH_MAG[4] - P[8][1]*SK_MX[2] + P[8][2]*SK_MX[1] + P[8][18]*SK_MX[3]);
- Kfusion[9] = SK_MX[0]*(P[9][19] + P[9][16]*SH_MAG[1] + P[9][17]*SH_MAG[4] - P[9][1]*SK_MX[2] + P[9][2]*SK_MX[1] + P[9][18]*SK_MX[3]);
- Kfusion[10] = SK_MX[0]*(P[10][19] + P[10][16]*SH_MAG[1] + P[10][17]*SH_MAG[4] - P[10][1]*SK_MX[2] + P[10][2]*SK_MX[1] + P[10][18]*SK_MX[3]);
- Kfusion[11] = SK_MX[0]*(P[11][19] + P[11][16]*SH_MAG[1] + P[11][17]*SH_MAG[4] - P[11][1]*SK_MX[2] + P[11][2]*SK_MX[1] + P[11][18]*SK_MX[3]);
- Kfusion[12] = SK_MX[0]*(P[12][19] + P[12][16]*SH_MAG[1] + P[12][17]*SH_MAG[4] - P[12][1]*SK_MX[2] + P[12][2]*SK_MX[1] + P[12][18]*SK_MX[3]);
- Kfusion[13] = SK_MX[0]*(P[13][19] + P[13][16]*SH_MAG[1] + P[13][17]*SH_MAG[4] - P[13][1]*SK_MX[2] + P[13][2]*SK_MX[1] + P[13][18]*SK_MX[3]);
- Kfusion[14] = SK_MX[0]*(P[14][19] + P[14][16]*SH_MAG[1] + P[14][17]*SH_MAG[4] - P[14][1]*SK_MX[2] + P[14][2]*SK_MX[1] + P[14][18]*SK_MX[3]);
- Kfusion[15] = SK_MX[0]*(P[15][19] + P[15][16]*SH_MAG[1] + P[15][17]*SH_MAG[4] - P[15][1]*SK_MX[2] + P[15][2]*SK_MX[1] + P[15][18]*SK_MX[3]);
-
-
- if (!inhibitWindStates) {
- Kfusion[22] = SK_MX[0]*(P[22][19] + P[22][16]*SH_MAG[1] + P[22][17]*SH_MAG[4] - P[22][1]*SK_MX[2] + P[22][2]*SK_MX[1] + P[22][18]*SK_MX[3]);
- Kfusion[23] = SK_MX[0]*(P[23][19] + P[23][16]*SH_MAG[1] + P[23][17]*SH_MAG[4] - P[23][1]*SK_MX[2] + P[23][2]*SK_MX[1] + P[23][18]*SK_MX[3]);
- } else {
- Kfusion[22] = 0.0f;
- Kfusion[23] = 0.0f;
- }
-
- if (!inhibitMagStates) {
- Kfusion[16] = SK_MX[0]*(P[16][19] + P[16][16]*SH_MAG[1] + P[16][17]*SH_MAG[4] - P[16][1]*SK_MX[2] + P[16][2]*SK_MX[1] + P[16][18]*SK_MX[3]);
- Kfusion[17] = SK_MX[0]*(P[17][19] + P[17][16]*SH_MAG[1] + P[17][17]*SH_MAG[4] - P[17][1]*SK_MX[2] + P[17][2]*SK_MX[1] + P[17][18]*SK_MX[3]);
- Kfusion[18] = SK_MX[0]*(P[18][19] + P[18][16]*SH_MAG[1] + P[18][17]*SH_MAG[4] - P[18][1]*SK_MX[2] + P[18][2]*SK_MX[1] + P[18][18]*SK_MX[3]);
- Kfusion[19] = SK_MX[0]*(P[19][19] + P[19][16]*SH_MAG[1] + P[19][17]*SH_MAG[4] - P[19][1]*SK_MX[2] + P[19][2]*SK_MX[1] + P[19][18]*SK_MX[3]);
- Kfusion[20] = SK_MX[0]*(P[20][19] + P[20][16]*SH_MAG[1] + P[20][17]*SH_MAG[4] - P[20][1]*SK_MX[2] + P[20][2]*SK_MX[1] + P[20][18]*SK_MX[3]);
- Kfusion[21] = SK_MX[0]*(P[21][19] + P[21][16]*SH_MAG[1] + P[21][17]*SH_MAG[4] - P[21][1]*SK_MX[2] + P[21][2]*SK_MX[1] + P[21][18]*SK_MX[3]);
- } else {
- for (uint8_t i=16; i<=21; i++) {
- Kfusion[i] = 0.0f;
- }
- }
-
- obsIndex = 0;
-
-
- magFusePerformed = true;
- magFuseRequired = true;
- hal.util->perf_end(_perf_test[2]);
- }
- else if (obsIndex == 1)
- {
- hal.util->perf_begin(_perf_test[3]);
-
- for (uint8_t i = 0; i<=stateIndexLim; i++) H_MAG[i] = 0.0f;
- H_MAG[0] = magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5];
- H_MAG[2] = - magE*SH_MAG[4] - magD*SH_MAG[7] - magN*SH_MAG[1];
- H_MAG[16] = 2.0f*q1*q2 - SH_MAG[8];
- H_MAG[17] = SH_MAG[0];
- H_MAG[18] = SH_MAG[3];
- H_MAG[20] = 1.0f;
-
- SK_MY[0] = 1.0f / varInnovMag[1];
- SK_MY[1] = magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1];
- SK_MY[2] = magD*SH_MAG[2] - SH_MAG[6] + magN*SH_MAG[5];
- SK_MY[3] = SH_MAG[8] - 2.0f*q1*q2;
- Kfusion[0] = SK_MY[0]*(P[0][20] + P[0][17]*SH_MAG[0] + P[0][18]*SH_MAG[3] + P[0][0]*SK_MY[2] - P[0][2]*SK_MY[1] - P[0][16]*SK_MY[3]);
- Kfusion[1] = SK_MY[0]*(P[1][20] + P[1][17]*SH_MAG[0] + P[1][18]*SH_MAG[3] + P[1][0]*SK_MY[2] - P[1][2]*SK_MY[1] - P[1][16]*SK_MY[3]);
- Kfusion[2] = SK_MY[0]*(P[2][20] + P[2][17]*SH_MAG[0] + P[2][18]*SH_MAG[3] + P[2][0]*SK_MY[2] - P[2][2]*SK_MY[1] - P[2][16]*SK_MY[3]);
- Kfusion[3] = SK_MY[0]*(P[3][20] + P[3][17]*SH_MAG[0] + P[3][18]*SH_MAG[3] + P[3][0]*SK_MY[2] - P[3][2]*SK_MY[1] - P[3][16]*SK_MY[3]);
- Kfusion[4] = SK_MY[0]*(P[4][20] + P[4][17]*SH_MAG[0] + P[4][18]*SH_MAG[3] + P[4][0]*SK_MY[2] - P[4][2]*SK_MY[1] - P[4][16]*SK_MY[3]);
- Kfusion[5] = SK_MY[0]*(P[5][20] + P[5][17]*SH_MAG[0] + P[5][18]*SH_MAG[3] + P[5][0]*SK_MY[2] - P[5][2]*SK_MY[1] - P[5][16]*SK_MY[3]);
- Kfusion[6] = SK_MY[0]*(P[6][20] + P[6][17]*SH_MAG[0] + P[6][18]*SH_MAG[3] + P[6][0]*SK_MY[2] - P[6][2]*SK_MY[1] - P[6][16]*SK_MY[3]);
- Kfusion[7] = SK_MY[0]*(P[7][20] + P[7][17]*SH_MAG[0] + P[7][18]*SH_MAG[3] + P[7][0]*SK_MY[2] - P[7][2]*SK_MY[1] - P[7][16]*SK_MY[3]);
- Kfusion[8] = SK_MY[0]*(P[8][20] + P[8][17]*SH_MAG[0] + P[8][18]*SH_MAG[3] + P[8][0]*SK_MY[2] - P[8][2]*SK_MY[1] - P[8][16]*SK_MY[3]);
- Kfusion[9] = SK_MY[0]*(P[9][20] + P[9][17]*SH_MAG[0] + P[9][18]*SH_MAG[3] + P[9][0]*SK_MY[2] - P[9][2]*SK_MY[1] - P[9][16]*SK_MY[3]);
- Kfusion[10] = SK_MY[0]*(P[10][20] + P[10][17]*SH_MAG[0] + P[10][18]*SH_MAG[3] + P[10][0]*SK_MY[2] - P[10][2]*SK_MY[1] - P[10][16]*SK_MY[3]);
- Kfusion[11] = SK_MY[0]*(P[11][20] + P[11][17]*SH_MAG[0] + P[11][18]*SH_MAG[3] + P[11][0]*SK_MY[2] - P[11][2]*SK_MY[1] - P[11][16]*SK_MY[3]);
- Kfusion[12] = SK_MY[0]*(P[12][20] + P[12][17]*SH_MAG[0] + P[12][18]*SH_MAG[3] + P[12][0]*SK_MY[2] - P[12][2]*SK_MY[1] - P[12][16]*SK_MY[3]);
- Kfusion[13] = SK_MY[0]*(P[13][20] + P[13][17]*SH_MAG[0] + P[13][18]*SH_MAG[3] + P[13][0]*SK_MY[2] - P[13][2]*SK_MY[1] - P[13][16]*SK_MY[3]);
- Kfusion[14] = SK_MY[0]*(P[14][20] + P[14][17]*SH_MAG[0] + P[14][18]*SH_MAG[3] + P[14][0]*SK_MY[2] - P[14][2]*SK_MY[1] - P[14][16]*SK_MY[3]);
- Kfusion[15] = SK_MY[0]*(P[15][20] + P[15][17]*SH_MAG[0] + P[15][18]*SH_MAG[3] + P[15][0]*SK_MY[2] - P[15][2]*SK_MY[1] - P[15][16]*SK_MY[3]);
-
- if (!inhibitWindStates) {
- Kfusion[22] = SK_MY[0]*(P[22][20] + P[22][17]*SH_MAG[0] + P[22][18]*SH_MAG[3] + P[22][0]*SK_MY[2] - P[22][2]*SK_MY[1] - P[22][16]*SK_MY[3]);
- Kfusion[23] = SK_MY[0]*(P[23][20] + P[23][17]*SH_MAG[0] + P[23][18]*SH_MAG[3] + P[23][0]*SK_MY[2] - P[23][2]*SK_MY[1] - P[23][16]*SK_MY[3]);
- } else {
- Kfusion[22] = 0.0f;
- Kfusion[23] = 0.0f;
- }
-
- if (!inhibitMagStates) {
- Kfusion[16] = SK_MY[0]*(P[16][20] + P[16][17]*SH_MAG[0] + P[16][18]*SH_MAG[3] + P[16][0]*SK_MY[2] - P[16][2]*SK_MY[1] - P[16][16]*SK_MY[3]);
- Kfusion[17] = SK_MY[0]*(P[17][20] + P[17][17]*SH_MAG[0] + P[17][18]*SH_MAG[3] + P[17][0]*SK_MY[2] - P[17][2]*SK_MY[1] - P[17][16]*SK_MY[3]);
- Kfusion[18] = SK_MY[0]*(P[18][20] + P[18][17]*SH_MAG[0] + P[18][18]*SH_MAG[3] + P[18][0]*SK_MY[2] - P[18][2]*SK_MY[1] - P[18][16]*SK_MY[3]);
- Kfusion[19] = SK_MY[0]*(P[19][20] + P[19][17]*SH_MAG[0] + P[19][18]*SH_MAG[3] + P[19][0]*SK_MY[2] - P[19][2]*SK_MY[1] - P[19][16]*SK_MY[3]);
- Kfusion[20] = SK_MY[0]*(P[20][20] + P[20][17]*SH_MAG[0] + P[20][18]*SH_MAG[3] + P[20][0]*SK_MY[2] - P[20][2]*SK_MY[1] - P[20][16]*SK_MY[3]);
- Kfusion[21] = SK_MY[0]*(P[21][20] + P[21][17]*SH_MAG[0] + P[21][18]*SH_MAG[3] + P[21][0]*SK_MY[2] - P[21][2]*SK_MY[1] - P[21][16]*SK_MY[3]);
- } else {
- for (uint8_t i=16; i<=21; i++) {
- Kfusion[i] = 0.0f;
- }
- }
-
-
- magFusePerformed = true;
- magFuseRequired = true;
- hal.util->perf_end(_perf_test[3]);
- }
- else if (obsIndex == 2)
- {
- hal.util->perf_begin(_perf_test[4]);
-
- for (uint8_t i = 0; i<=stateIndexLim; i++) H_MAG[i] = 0.0f;
- H_MAG[0] = magN*(SH_MAG[8] - 2.0f*q1*q2) - magD*SH_MAG[3] - magE*SH_MAG[0];
- H_MAG[1] = magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1];
- H_MAG[16] = SH_MAG[5];
- H_MAG[17] = 2.0f*q2*q3 - 2.0f*q0*q1;
- H_MAG[18] = SH_MAG[2];
- H_MAG[21] = 1.0f;
-
- SK_MZ[0] = 1.0f / varInnovMag[2];
- SK_MZ[1] = magE*SH_MAG[0] + magD*SH_MAG[3] - magN*(SH_MAG[8] - 2.0f*q1*q2);
- SK_MZ[2] = magE*SH_MAG[4] + magD*SH_MAG[7] + magN*SH_MAG[1];
- SK_MZ[3] = 2.0f*q0*q1 - 2.0f*q2*q3;
- Kfusion[0] = SK_MZ[0]*(P[0][21] + P[0][18]*SH_MAG[2] + P[0][16]*SH_MAG[5] - P[0][0]*SK_MZ[1] + P[0][1]*SK_MZ[2] - P[0][17]*SK_MZ[3]);
- Kfusion[1] = SK_MZ[0]*(P[1][21] + P[1][18]*SH_MAG[2] + P[1][16]*SH_MAG[5] - P[1][0]*SK_MZ[1] + P[1][1]*SK_MZ[2] - P[1][17]*SK_MZ[3]);
- Kfusion[2] = SK_MZ[0]*(P[2][21] + P[2][18]*SH_MAG[2] + P[2][16]*SH_MAG[5] - P[2][0]*SK_MZ[1] + P[2][1]*SK_MZ[2] - P[2][17]*SK_MZ[3]);
- Kfusion[3] = SK_MZ[0]*(P[3][21] + P[3][18]*SH_MAG[2] + P[3][16]*SH_MAG[5] - P[3][0]*SK_MZ[1] + P[3][1]*SK_MZ[2] - P[3][17]*SK_MZ[3]);
- Kfusion[4] = SK_MZ[0]*(P[4][21] + P[4][18]*SH_MAG[2] + P[4][16]*SH_MAG[5] - P[4][0]*SK_MZ[1] + P[4][1]*SK_MZ[2] - P[4][17]*SK_MZ[3]);
- Kfusion[5] = SK_MZ[0]*(P[5][21] + P[5][18]*SH_MAG[2] + P[5][16]*SH_MAG[5] - P[5][0]*SK_MZ[1] + P[5][1]*SK_MZ[2] - P[5][17]*SK_MZ[3]);
- Kfusion[6] = SK_MZ[0]*(P[6][21] + P[6][18]*SH_MAG[2] + P[6][16]*SH_MAG[5] - P[6][0]*SK_MZ[1] + P[6][1]*SK_MZ[2] - P[6][17]*SK_MZ[3]);
- Kfusion[7] = SK_MZ[0]*(P[7][21] + P[7][18]*SH_MAG[2] + P[7][16]*SH_MAG[5] - P[7][0]*SK_MZ[1] + P[7][1]*SK_MZ[2] - P[7][17]*SK_MZ[3]);
- Kfusion[8] = SK_MZ[0]*(P[8][21] + P[8][18]*SH_MAG[2] + P[8][16]*SH_MAG[5] - P[8][0]*SK_MZ[1] + P[8][1]*SK_MZ[2] - P[8][17]*SK_MZ[3]);
- Kfusion[9] = SK_MZ[0]*(P[9][21] + P[9][18]*SH_MAG[2] + P[9][16]*SH_MAG[5] - P[9][0]*SK_MZ[1] + P[9][1]*SK_MZ[2] - P[9][17]*SK_MZ[3]);
- Kfusion[10] = SK_MZ[0]*(P[10][21] + P[10][18]*SH_MAG[2] + P[10][16]*SH_MAG[5] - P[10][0]*SK_MZ[1] + P[10][1]*SK_MZ[2] - P[10][17]*SK_MZ[3]);
- Kfusion[11] = SK_MZ[0]*(P[11][21] + P[11][18]*SH_MAG[2] + P[11][16]*SH_MAG[5] - P[11][0]*SK_MZ[1] + P[11][1]*SK_MZ[2] - P[11][17]*SK_MZ[3]);
- Kfusion[12] = SK_MZ[0]*(P[12][21] + P[12][18]*SH_MAG[2] + P[12][16]*SH_MAG[5] - P[12][0]*SK_MZ[1] + P[12][1]*SK_MZ[2] - P[12][17]*SK_MZ[3]);
- Kfusion[13] = SK_MZ[0]*(P[13][21] + P[13][18]*SH_MAG[2] + P[13][16]*SH_MAG[5] - P[13][0]*SK_MZ[1] + P[13][1]*SK_MZ[2] - P[13][17]*SK_MZ[3]);
- Kfusion[14] = SK_MZ[0]*(P[14][21] + P[14][18]*SH_MAG[2] + P[14][16]*SH_MAG[5] - P[14][0]*SK_MZ[1] + P[14][1]*SK_MZ[2] - P[14][17]*SK_MZ[3]);
- Kfusion[15] = SK_MZ[0]*(P[15][21] + P[15][18]*SH_MAG[2] + P[15][16]*SH_MAG[5] - P[15][0]*SK_MZ[1] + P[15][1]*SK_MZ[2] - P[15][17]*SK_MZ[3]);
-
- if (!inhibitWindStates) {
- Kfusion[22] = SK_MZ[0]*(P[22][21] + P[22][18]*SH_MAG[2] + P[22][16]*SH_MAG[5] - P[22][0]*SK_MZ[1] + P[22][1]*SK_MZ[2] - P[22][17]*SK_MZ[3]);
- Kfusion[23] = SK_MZ[0]*(P[23][21] + P[23][18]*SH_MAG[2] + P[23][16]*SH_MAG[5] - P[23][0]*SK_MZ[1] + P[23][1]*SK_MZ[2] - P[23][17]*SK_MZ[3]);
- } else {
- Kfusion[22] = 0.0f;
- Kfusion[23] = 0.0f;
- }
-
- if (!inhibitMagStates) {
- Kfusion[16] = SK_MZ[0]*(P[16][21] + P[16][18]*SH_MAG[2] + P[16][16]*SH_MAG[5] - P[16][0]*SK_MZ[1] + P[16][1]*SK_MZ[2] - P[16][17]*SK_MZ[3]);
- Kfusion[17] = SK_MZ[0]*(P[17][21] + P[17][18]*SH_MAG[2] + P[17][16]*SH_MAG[5] - P[17][0]*SK_MZ[1] + P[17][1]*SK_MZ[2] - P[17][17]*SK_MZ[3]);
- Kfusion[18] = SK_MZ[0]*(P[18][21] + P[18][18]*SH_MAG[2] + P[18][16]*SH_MAG[5] - P[18][0]*SK_MZ[1] + P[18][1]*SK_MZ[2] - P[18][17]*SK_MZ[3]);
- Kfusion[19] = SK_MZ[0]*(P[19][21] + P[19][18]*SH_MAG[2] + P[19][16]*SH_MAG[5] - P[19][0]*SK_MZ[1] + P[19][1]*SK_MZ[2] - P[19][17]*SK_MZ[3]);
- Kfusion[20] = SK_MZ[0]*(P[20][21] + P[20][18]*SH_MAG[2] + P[20][16]*SH_MAG[5] - P[20][0]*SK_MZ[1] + P[20][1]*SK_MZ[2] - P[20][17]*SK_MZ[3]);
- Kfusion[21] = SK_MZ[0]*(P[21][21] + P[21][18]*SH_MAG[2] + P[21][16]*SH_MAG[5] - P[21][0]*SK_MZ[1] + P[21][1]*SK_MZ[2] - P[21][17]*SK_MZ[3]);
- } else {
- for (uint8_t i=16; i<=21; i++) {
- Kfusion[i] = 0.0f;
- }
- }
-
-
- magFusePerformed = true;
- magFuseRequired = false;
- hal.util->perf_end(_perf_test[4]);
- }
- hal.util->perf_begin(_perf_test[5]);
-
-
-
- for (unsigned i = 0; i<=stateIndexLim; i++) {
- for (unsigned j = 0; j<=2; j++) {
- KH[i][j] = Kfusion[i] * H_MAG[j];
- }
- for (unsigned j = 3; j<=15; j++) {
- KH[i][j] = 0.0f;
- }
- for (unsigned j = 16; j<=21; j++) {
- KH[i][j] = Kfusion[i] * H_MAG[j];
- }
- for (unsigned j = 22; j<=23; j++) {
- KH[i][j] = 0.0f;
- }
- }
- for (unsigned j = 0; j<=stateIndexLim; j++) {
- for (unsigned i = 0; i<=stateIndexLim; i++) {
- ftype res = 0;
- res += KH[i][0] * P[0][j];
- res += KH[i][1] * P[1][j];
- res += KH[i][2] * P[2][j];
- res += KH[i][16] * P[16][j];
- res += KH[i][17] * P[17][j];
- res += KH[i][18] * P[18][j];
- res += KH[i][19] * P[19][j];
- res += KH[i][20] * P[20][j];
- res += KH[i][21] * P[21][j];
- KHP[i][j] = res;
- }
- }
-
- bool healthyFusion = true;
- for (uint8_t i= 0; i<=stateIndexLim; i++) {
- if (KHP[i][i] > P[i][i]) {
- healthyFusion = false;
- }
- }
- if (healthyFusion) {
-
- for (uint8_t i= 0; i<=stateIndexLim; i++) {
- for (uint8_t j= 0; j<=stateIndexLim; j++) {
- P[i][j] = P[i][j] - KHP[i][j];
- }
- }
-
- ForceSymmetry();
- ConstrainVariances();
-
-
- stateStruct.angErr.zero();
-
- for (uint8_t j= 0; j<=stateIndexLim; j++) {
- statesArray[j] = statesArray[j] - Kfusion[j] * innovMag[obsIndex];
- }
-
- if (have_table_earth_field && frontend->_mag_ef_limit > 0) {
- MagTableConstrain();
- }
-
-
- stateStruct.quat.rotate(stateStruct.angErr);
- } else {
-
- if (obsIndex == 0) {
- faultStatus.bad_xmag = true;
- } else if (obsIndex == 1) {
- faultStatus.bad_ymag = true;
- } else if (obsIndex == 2) {
- faultStatus.bad_zmag = true;
- }
- CovarianceInit();
- hal.util->perf_end(_perf_test[5]);
- return;
- }
- hal.util->perf_end(_perf_test[5]);
- }
- void NavEKF2_core::fuseEulerYaw()
- {
- float q0 = stateStruct.quat[0];
- float q1 = stateStruct.quat[1];
- float q2 = stateStruct.quat[2];
- float q3 = stateStruct.quat[3];
-
- const float R_YAW = sq(frontend->_yawNoise);
-
-
- float predicted_yaw;
- float measured_yaw;
- float H_YAW[3];
- Matrix3f Tbn_zeroYaw;
- if (fabsf(prevTnb[0][2]) < fabsf(prevTnb[1][2])) {
-
- float t2 = q0*q0;
- float t3 = q1*q1;
- float t4 = q2*q2;
- float t5 = q3*q3;
- float t6 = t2+t3-t4-t5;
- float t7 = q0*q3*2.0f;
- float t8 = q1*q2*2.0f;
- float t9 = t7+t8;
- float t10 = sq(t6);
- if (t10 > 1e-6f) {
- t10 = 1.0f / t10;
- } else {
- return;
- }
- float t11 = t9*t9;
- float t12 = t10*t11;
- float t13 = t12+1.0f;
- float t14;
- if (fabsf(t13) > 1e-3f) {
- t14 = 1.0f/t13;
- } else {
- return;
- }
- float t15 = 1.0f/t6;
- H_YAW[0] = 0.0f;
- H_YAW[1] = t14*(t15*(q0*q1*2.0f-q2*q3*2.0f)+t9*t10*(q0*q2*2.0f+q1*q3*2.0f));
- H_YAW[2] = t14*(t15*(t2-t3+t4-t5)+t9*t10*(t7-t8));
-
- Vector3f euler321;
- stateStruct.quat.to_euler(euler321.x, euler321.y, euler321.z);
- predicted_yaw = euler321.z;
- if (use_compass() && yawAlignComplete && magStateInitComplete) {
-
- Tbn_zeroYaw.from_euler(euler321.x, euler321.y, 0.0f);
- Vector3f magMeasNED = Tbn_zeroYaw*magDataDelayed.mag;
- measured_yaw = wrap_PI(-atan2f(magMeasNED.y, magMeasNED.x) + MagDeclination());
- } else if (extNavUsedForYaw) {
-
- extNavDataDelayed.quat.to_euler(euler321.x, euler321.y, euler321.z);
- measured_yaw = euler321.z;
- } else {
-
- measured_yaw = predicted_yaw;
- }
- } else {
-
- float t2 = q0*q0;
- float t3 = q1*q1;
- float t4 = q2*q2;
- float t5 = q3*q3;
- float t6 = t2-t3+t4-t5;
- float t7 = q0*q3*2.0f;
- float t10 = q1*q2*2.0f;
- float t8 = t7-t10;
- float t9 = sq(t6);
- if (t9 > 1e-6f) {
- t9 = 1.0f/t9;
- } else {
- return;
- }
- float t11 = t8*t8;
- float t12 = t9*t11;
- float t13 = t12+1.0f;
- float t14;
- if (fabsf(t13) > 1e-3f) {
- t14 = 1.0f/t13;
- } else {
- return;
- }
- float t15 = 1.0f/t6;
- H_YAW[0] = -t14*(t15*(q0*q2*2.0+q1*q3*2.0)-t8*t9*(q0*q1*2.0-q2*q3*2.0));
- H_YAW[1] = 0.0f;
- H_YAW[2] = t14*(t15*(t2+t3-t4-t5)+t8*t9*(t7+t10));
-
- Vector3f euler312 = stateStruct.quat.to_vector312();
- predicted_yaw = euler312.z;
- if (use_compass() && yawAlignComplete && magStateInitComplete) {
-
- Tbn_zeroYaw.from_euler312(euler312.x, euler312.y, 0.0f);
- Vector3f magMeasNED = Tbn_zeroYaw*magDataDelayed.mag;
- measured_yaw = wrap_PI(-atan2f(magMeasNED.y, magMeasNED.x) + MagDeclination());
- } else if (extNavUsedForYaw) {
-
- euler312 = extNavDataDelayed.quat.to_vector312();
- measured_yaw = euler312.z;
- } else {
-
- measured_yaw = predicted_yaw;
- }
- }
-
- float innovation = wrap_PI(predicted_yaw - measured_yaw);
-
- innovYaw = innovation;
-
- float PH[3];
- float varInnov = R_YAW;
- for (uint8_t rowIndex=0; rowIndex<=2; rowIndex++) {
- PH[rowIndex] = 0.0f;
- for (uint8_t colIndex=0; colIndex<=2; colIndex++) {
- PH[rowIndex] += P[rowIndex][colIndex]*H_YAW[colIndex];
- }
- varInnov += H_YAW[rowIndex]*PH[rowIndex];
- }
- float varInnovInv;
- if (varInnov >= R_YAW) {
- varInnovInv = 1.0f / varInnov;
-
- faultStatus.bad_yaw = false;
- } else {
-
-
- CovarianceInit();
-
- faultStatus.bad_yaw = true;
- return;
- }
-
- for (uint8_t rowIndex=0; rowIndex<=stateIndexLim; rowIndex++) {
- Kfusion[rowIndex] = 0.0f;
- for (uint8_t colIndex=0; colIndex<=2; colIndex++) {
- Kfusion[rowIndex] += P[rowIndex][colIndex]*H_YAW[colIndex];
- }
- Kfusion[rowIndex] *= varInnovInv;
- }
-
- yawTestRatio = sq(innovation) / (sq(MAX(0.01f * (float)frontend->_yawInnovGate, 1.0f)) * varInnov);
-
- if (yawTestRatio > 1.0f) {
- magHealth = false;
-
-
- if (inFlight) {
- return;
- }
- } else {
- magHealth = true;
- }
-
- if (innovation > 0.5f) {
- innovation = 0.5f;
- } else if (innovation < -0.5f) {
- innovation = -0.5f;
- }
-
-
- for (uint8_t row = 0; row <= stateIndexLim; row++) {
- for (uint8_t column = 0; column <= 2; column++) {
- KH[row][column] = Kfusion[row] * H_YAW[column];
- }
- }
- for (uint8_t row = 0; row <= stateIndexLim; row++) {
- for (uint8_t column = 0; column <= stateIndexLim; column++) {
- float tmp = KH[row][0] * P[0][column];
- tmp += KH[row][1] * P[1][column];
- tmp += KH[row][2] * P[2][column];
- KHP[row][column] = tmp;
- }
- }
-
- bool healthyFusion = true;
- for (uint8_t i= 0; i<=stateIndexLim; i++) {
- if (KHP[i][i] > P[i][i]) {
- healthyFusion = false;
- }
- }
- if (healthyFusion) {
-
- for (uint8_t i= 0; i<=stateIndexLim; i++) {
- for (uint8_t j= 0; j<=stateIndexLim; j++) {
- P[i][j] = P[i][j] - KHP[i][j];
- }
- }
-
- ForceSymmetry();
- ConstrainVariances();
-
- stateStruct.angErr.zero();
-
- for (uint8_t i=0; i<=stateIndexLim; i++) {
- statesArray[i] -= Kfusion[i] * innovation;
- }
-
-
- stateStruct.quat.rotate(stateStruct.angErr);
-
- faultStatus.bad_yaw = false;
- lastYawTime_ms = imuSampleTime_ms;
- } else {
-
- faultStatus.bad_yaw = true;
- }
- }
- void NavEKF2_core::FuseDeclination(float declErr)
- {
-
- const float R_DECL = sq(declErr);
-
- float magN = stateStruct.earth_magfield.x;
- float magE = stateStruct.earth_magfield.y;
-
- if (magN < 1e-3f) {
- return;
- }
-
- float t2 = magE*magE;
- float t3 = magN*magN;
- float t4 = t2+t3;
- float t5 = 1.0f/t4;
- float t22 = magE*t5;
- float t23 = magN*t5;
- float t6 = P[16][16]*t22;
- float t13 = P[17][16]*t23;
- float t7 = t6-t13;
- float t8 = t22*t7;
- float t9 = P[16][17]*t22;
- float t14 = P[17][17]*t23;
- float t10 = t9-t14;
- float t15 = t23*t10;
- float t11 = R_DECL+t8-t15;
- if (t11 < R_DECL) {
- return;
- }
- float t12 = 1.0f/t11;
- float H_MAG[24];
- H_MAG[16] = -magE*t5;
- H_MAG[17] = magN*t5;
- for (uint8_t i=0; i<=15; i++) {
- Kfusion[i] = -t12*(P[i][16]*t22-P[i][17]*t23);
- }
- Kfusion[16] = -t12*(t6-P[16][17]*t23);
- Kfusion[17] = t12*(t14-P[17][16]*t22);
- for (uint8_t i=17; i<=23; i++) {
- Kfusion[i] = -t12*(P[i][16]*t22-P[i][17]*t23);
- }
-
- float magDecAng = MagDeclination();
-
- float innovation = atan2f(magE , magN) - magDecAng;
-
- if (innovation > 0.5f) {
- innovation = 0.5f;
- } else if (innovation < -0.5f) {
- innovation = -0.5f;
- }
-
-
-
- for (unsigned i = 0; i<=stateIndexLim; i++) {
- for (unsigned j = 0; j<=15; j++) {
- KH[i][j] = 0.0f;
- }
- KH[i][16] = Kfusion[i] * H_MAG[16];
- KH[i][17] = Kfusion[i] * H_MAG[17];
- for (unsigned j = 18; j<=23; j++) {
- KH[i][j] = 0.0f;
- }
- }
- for (unsigned j = 0; j<=stateIndexLim; j++) {
- for (unsigned i = 0; i<=stateIndexLim; i++) {
- KHP[i][j] = KH[i][16] * P[16][j] + KH[i][17] * P[17][j];
- }
- }
-
- bool healthyFusion = true;
- for (uint8_t i= 0; i<=stateIndexLim; i++) {
- if (KHP[i][i] > P[i][i]) {
- healthyFusion = false;
- }
- }
- if (healthyFusion) {
-
- for (uint8_t i= 0; i<=stateIndexLim; i++) {
- for (uint8_t j= 0; j<=stateIndexLim; j++) {
- P[i][j] = P[i][j] - KHP[i][j];
- }
- }
-
- ForceSymmetry();
- ConstrainVariances();
-
- stateStruct.angErr.zero();
-
- for (uint8_t j= 0; j<=stateIndexLim; j++) {
- statesArray[j] = statesArray[j] - Kfusion[j] * innovation;
- }
-
-
- stateStruct.quat.rotate(stateStruct.angErr);
-
- faultStatus.bad_decl = false;
- } else {
-
- faultStatus.bad_decl = true;
- }
- }
- void NavEKF2_core::alignMagStateDeclination()
- {
-
- if (magFieldLearned) {
- return;
- }
-
- float magDecAng = MagDeclination();
-
- Vector3f initMagNED = stateStruct.earth_magfield;
- float magLengthNE = norm(initMagNED.x,initMagNED.y);
- stateStruct.earth_magfield.x = magLengthNE * cosf(magDecAng);
- stateStruct.earth_magfield.y = magLengthNE * sinf(magDecAng);
- if (!inhibitMagStates) {
-
- float var_16 = P[16][16];
- float var_17 = P[17][17];
- zeroRows(P,16,17);
- zeroCols(P,16,17);
- P[16][16] = var_16;
- P[17][17] = var_17;
-
-
- FuseDeclination(0.1f);
- }
- }
- void NavEKF2_core::recordMagReset()
- {
- magStateInitComplete = true;
- if (inFlight) {
- finalInflightMagInit = true;
- }
-
-
- posDownAtLastMagReset = stateStruct.position.z;
- quatAtLastMagReset = stateStruct.quat;
- yawInnovAtLastMagReset = innovYaw;
- }
|