SoloGimbalEKF.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  1. #include <AP_HAL/AP_HAL.h>
  2. // uncomment this to force the optimisation of this code, note that
  3. // this makes debugging harder
  4. #if CONFIG_HAL_BOARD == HAL_BOARD_SITL || CONFIG_HAL_BOARD == HAL_BOARD_LINUX
  5. #pragma GCC optimize("O0")
  6. #else
  7. #pragma GCC optimize("O2")
  8. #endif
  9. #include "SoloGimbalEKF.h"
  10. #include <AP_Param/AP_Param.h>
  11. #include <AP_Vehicle/AP_Vehicle.h>
  12. #include <AP_NavEKF/AP_Nav_Common.h>
  13. #include <AP_AHRS/AP_AHRS.h>
  14. #include <stdio.h>
  15. extern const AP_HAL::HAL& hal;
  16. // Define tuning parameters
  17. const AP_Param::GroupInfo SoloGimbalEKF::var_info[] = {
  18. AP_GROUPEND
  19. };
  20. // Hash define constants
  21. #define GYRO_BIAS_LIMIT 0.349066f // maximum allowed gyro bias (rad/sec)
  22. // constructor
  23. SoloGimbalEKF::SoloGimbalEKF() :
  24. states(),
  25. state(*reinterpret_cast<struct state_elements *>(&states))
  26. {
  27. AP_Param::setup_object_defaults(this, var_info);
  28. reset();
  29. }
  30. // complete reset
  31. void SoloGimbalEKF::reset()
  32. {
  33. memset(&states,0,sizeof(states));
  34. memset((void *)&gSense,0,sizeof(gSense));
  35. memset(&Cov,0,sizeof(Cov));
  36. TiltCorrectionSquared = 0;
  37. StartTime_ms = 0;
  38. FiltInit = false;
  39. lastMagUpdate = 0;
  40. dtIMU = 0;
  41. innovationIncrement = 0;
  42. lastInnovation = 0;
  43. }
  44. // run a 9-state EKF used to calculate orientation
  45. void SoloGimbalEKF::RunEKF(float delta_time, const Vector3f &delta_angles, const Vector3f &delta_velocity, const Vector3f &joint_angles)
  46. {
  47. imuSampleTime_ms = AP_HAL::millis();
  48. dtIMU = delta_time;
  49. // initialise variables and constants
  50. if (!FiltInit) {
  51. // Note: the start time is initialised to 0 in the constructor
  52. if (StartTime_ms == 0) {
  53. StartTime_ms = imuSampleTime_ms;
  54. }
  55. // Set data to pre-initialsation defaults
  56. FiltInit = false;
  57. newDataMag = false;
  58. YawAligned = false;
  59. memset((void *)&state, 0, sizeof(state));
  60. state.quat[0] = 1.0f;
  61. bool main_ekf_healthy = false;
  62. nav_filter_status main_ekf_status;
  63. const AP_AHRS_NavEKF &_ahrs = AP::ahrs_navekf();
  64. if (_ahrs.get_filter_status(main_ekf_status)) {
  65. if (main_ekf_status.flags.attitude) {
  66. main_ekf_healthy = true;
  67. }
  68. }
  69. // Wait for gimbal to stabilise to body fixed position for a few seconds before starting small EKF
  70. // Also wait for navigation EKF to be healthy beasue we are using the velocity output data
  71. // This prevents jerky gimbal motion from degrading the EKF initial state estimates
  72. if (imuSampleTime_ms - StartTime_ms < 5000 || !main_ekf_healthy) {
  73. return;
  74. }
  75. Quaternion ned_to_vehicle_quat;
  76. ned_to_vehicle_quat.from_rotation_matrix(_ahrs.get_rotation_body_to_ned());
  77. Quaternion vehicle_to_gimbal_quat;
  78. vehicle_to_gimbal_quat.from_vector312(joint_angles.x,joint_angles.y,joint_angles.z);
  79. // calculate initial orientation
  80. state.quat = ned_to_vehicle_quat * vehicle_to_gimbal_quat;
  81. const float Sigma_velNED = 0.5f; // 1 sigma uncertainty in horizontal velocity components
  82. const float Sigma_dAngBias = 0.002f*dtIMU; // 1 Sigma uncertainty in delta angle bias (rad)
  83. const float Sigma_angErr = 0.1f; // 1 Sigma uncertainty in angular misalignment (rad)
  84. for (uint8_t i=0; i <= 2; i++) Cov[i][i] = sq(Sigma_angErr);
  85. for (uint8_t i=3; i <= 5; i++) Cov[i][i] = sq(Sigma_velNED);
  86. for (uint8_t i=6; i <= 8; i++) Cov[i][i] = sq(Sigma_dAngBias);
  87. FiltInit = true;
  88. hal.console->printf("\nSoloGimbalEKF Alignment Started\n");
  89. // Don't run the filter in this timestep because we have already used the delta velocity data to set an initial orientation
  90. return;
  91. }
  92. // We are using IMU data and joint angles from the gimbal
  93. gSense.gPsi = joint_angles.z; // yaw
  94. gSense.gPhi = joint_angles.x; // roll
  95. gSense.gTheta = joint_angles.y; // pitch
  96. cosPhi = cosf(gSense.gPhi);
  97. cosTheta = cosf(gSense.gTheta);
  98. sinPhi = sinf(gSense.gPhi);
  99. sinTheta = sinf(gSense.gTheta);
  100. sinPsi = sinf(gSense.gPsi);
  101. cosPsi = cosf(gSense.gPsi);
  102. gSense.delAng = delta_angles;
  103. gSense.delVel = delta_velocity;
  104. // predict states
  105. predictStates();
  106. // predict the covariance
  107. predictCovariance();
  108. // fuse SoloGimbalEKF velocity data
  109. fuseVelocity();
  110. // Align the heading once there has been enough time for the filter to settle and the tilt corrections have dropped below a threshold
  111. // Force it to align if too much time has lapsed
  112. if (((((imuSampleTime_ms - StartTime_ms) > 8000 && TiltCorrectionSquared < sq(1e-4f)) || (imuSampleTime_ms - StartTime_ms) > 30000)) && !YawAligned) {
  113. //calculate the initial heading using magnetometer, estimated tilt and declination
  114. alignHeading();
  115. YawAligned = true;
  116. hal.console->printf("\nSoloGimbalEKF Alignment Completed\n");
  117. }
  118. // Fuse magnetometer data if we have new measurements and an aligned heading
  119. readMagData();
  120. if (newDataMag && YawAligned) {
  121. fuseCompass();
  122. newDataMag = false;
  123. }
  124. }
  125. // state prediction
  126. void SoloGimbalEKF::predictStates()
  127. {
  128. static Vector3f gimDelAngCorrected;
  129. static Vector3f gimDelAngPrev;
  130. // NED gravity vector m/s^2
  131. const Vector3f gravityNED(0, 0, GRAVITY_MSS);
  132. // apply corrections for bias and coning errors
  133. // % * - and + operators have been overloaded
  134. gimDelAngCorrected = gSense.delAng - state.delAngBias - (gimDelAngPrev % gimDelAngCorrected) * 8.333333e-2f;
  135. gimDelAngPrev = gSense.delAng - state.delAngBias;
  136. // update the quaternions by rotating from the previous attitude through
  137. // the delta angle rotation quaternion
  138. state.quat.rotate(gimDelAngCorrected);
  139. // normalise the quaternions and update the quaternion states
  140. state.quat.normalize();
  141. // calculate the sensor to NED cosine matrix
  142. state.quat.rotation_matrix(Tsn);
  143. // transform body delta velocities to delta velocities in the nav frame
  144. // * and + operators have been overloaded
  145. Vector3f delVelNav = Tsn*gSense.delVel + gravityNED*dtIMU;
  146. // sum delta velocities to get velocity
  147. state.velocity += delVelNav;
  148. state.delAngBias.x = constrain_float(state.delAngBias.x, -GYRO_BIAS_LIMIT*dtIMU,GYRO_BIAS_LIMIT*dtIMU);
  149. state.delAngBias.y = constrain_float(state.delAngBias.y, -GYRO_BIAS_LIMIT*dtIMU,GYRO_BIAS_LIMIT*dtIMU);
  150. state.delAngBias.z = constrain_float(state.delAngBias.z, -GYRO_BIAS_LIMIT*dtIMU,GYRO_BIAS_LIMIT*dtIMU);
  151. }
  152. // covariance prediction using optimised algebraic toolbox expressions
  153. // equivalent to P = F*P*transpose(P) + G*imu_errors*transpose(G) +
  154. // gyro_bias_state_noise
  155. void SoloGimbalEKF::predictCovariance()
  156. {
  157. float delAngBiasVariance = sq(dtIMU*5E-6f);
  158. if (YawAligned && !hal.util->get_soft_armed()) {
  159. delAngBiasVariance *= 4.0f;
  160. }
  161. float daxNoise = sq(dtIMU*0.0087f);
  162. float dayNoise = sq(dtIMU*0.0087f);
  163. float dazNoise = sq(dtIMU*0.0087f);
  164. float dvxNoise = sq(dtIMU*0.5f);
  165. float dvyNoise = sq(dtIMU*0.5f);
  166. float dvzNoise = sq(dtIMU*0.5f);
  167. float dvx = gSense.delVel.x;
  168. float dvy = gSense.delVel.y;
  169. float dvz = gSense.delVel.z;
  170. float dax = gSense.delAng.x;
  171. float day = gSense.delAng.y;
  172. float daz = gSense.delAng.z;
  173. float q0 = state.quat[0];
  174. float q1 = state.quat[1];
  175. float q2 = state.quat[2];
  176. float q3 = state.quat[3];
  177. float dax_b = state.delAngBias.x;
  178. float day_b = state.delAngBias.y;
  179. float daz_b = state.delAngBias.z;
  180. float t1365 = dax*0.5f;
  181. float t1366 = dax_b*0.5f;
  182. float t1367 = t1365-t1366;
  183. float t1368 = day*0.5f;
  184. float t1369 = day_b*0.5f;
  185. float t1370 = t1368-t1369;
  186. float t1371 = daz*0.5f;
  187. float t1372 = daz_b*0.5f;
  188. float t1373 = t1371-t1372;
  189. float t1374 = q2*t1367*0.5f;
  190. float t1375 = q1*t1370*0.5f;
  191. float t1376 = q0*t1373*0.5f;
  192. float t1377 = q2*0.5f;
  193. float t1378 = q3*t1367*0.5f;
  194. float t1379 = q1*t1373*0.5f;
  195. float t1380 = q1*0.5f;
  196. float t1381 = q0*t1367*0.5f;
  197. float t1382 = q3*t1370*0.5f;
  198. float t1383 = q0*0.5f;
  199. float t1384 = q2*t1370*0.5f;
  200. float t1385 = q3*t1373*0.5f;
  201. float t1386 = q0*t1370*0.5f;
  202. float t1387 = q3*0.5f;
  203. float t1388 = q1*t1367*0.5f;
  204. float t1389 = q2*t1373*0.5f;
  205. float t1390 = t1374+t1375+t1376-t1387;
  206. float t1391 = t1377+t1378+t1379-t1386;
  207. float t1392 = q2*t1391*2.0f;
  208. float t1393 = t1380+t1381+t1382-t1389;
  209. float t1394 = q1*t1393*2.0f;
  210. float t1395 = t1383+t1384+t1385-t1388;
  211. float t1396 = q0*t1395*2.0f;
  212. float t1403 = q3*t1390*2.0f;
  213. float t1397 = t1392+t1394+t1396-t1403;
  214. float t1398 = sq(q0);
  215. float t1399 = sq(q1);
  216. float t1400 = sq(q2);
  217. float t1401 = sq(q3);
  218. float t1402 = t1398+t1399+t1400+t1401;
  219. float t1404 = t1374+t1375-t1376+t1387;
  220. float t1405 = t1377-t1378+t1379+t1386;
  221. float t1406 = q1*t1405*2.0f;
  222. float t1407 = -t1380+t1381+t1382+t1389;
  223. float t1408 = q2*t1407*2.0f;
  224. float t1409 = t1383-t1384+t1385+t1388;
  225. float t1410 = q3*t1409*2.0f;
  226. float t1420 = q0*t1404*2.0f;
  227. float t1411 = t1406+t1408+t1410-t1420;
  228. float t1412 = -t1377+t1378+t1379+t1386;
  229. float t1413 = q0*t1412*2.0f;
  230. float t1414 = t1374-t1375+t1376+t1387;
  231. float t1415 = t1383+t1384-t1385+t1388;
  232. float t1416 = q2*t1415*2.0f;
  233. float t1417 = t1380-t1381+t1382+t1389;
  234. float t1418 = q3*t1417*2.0f;
  235. float t1421 = q1*t1414*2.0f;
  236. float t1419 = t1413+t1416+t1418-t1421;
  237. float t1422 = Cov[0][0]*t1397;
  238. float t1423 = Cov[1][0]*t1411;
  239. float t1429 = Cov[6][0]*t1402;
  240. float t1430 = Cov[2][0]*t1419;
  241. float t1424 = t1422+t1423-t1429-t1430;
  242. float t1425 = Cov[0][1]*t1397;
  243. float t1426 = Cov[1][1]*t1411;
  244. float t1427 = Cov[0][2]*t1397;
  245. float t1428 = Cov[1][2]*t1411;
  246. float t1434 = Cov[6][1]*t1402;
  247. float t1435 = Cov[2][1]*t1419;
  248. float t1431 = t1425+t1426-t1434-t1435;
  249. float t1442 = Cov[6][2]*t1402;
  250. float t1443 = Cov[2][2]*t1419;
  251. float t1432 = t1427+t1428-t1442-t1443;
  252. float t1433 = t1398+t1399-t1400-t1401;
  253. float t1436 = q0*q2*2.0f;
  254. float t1437 = q1*q3*2.0f;
  255. float t1438 = t1436+t1437;
  256. float t1439 = q0*q3*2.0f;
  257. float t1441 = q1*q2*2.0f;
  258. float t1440 = t1439-t1441;
  259. float t1444 = t1398-t1399+t1400-t1401;
  260. float t1445 = q0*q1*2.0f;
  261. float t1449 = q2*q3*2.0f;
  262. float t1446 = t1445-t1449;
  263. float t1447 = t1439+t1441;
  264. float t1448 = t1398-t1399-t1400+t1401;
  265. float t1450 = t1445+t1449;
  266. float t1451 = t1436-t1437;
  267. float t1452 = Cov[0][6]*t1397;
  268. float t1453 = Cov[1][6]*t1411;
  269. float t1628 = Cov[6][6]*t1402;
  270. float t1454 = t1452+t1453-t1628-Cov[2][6]*t1419;
  271. float t1455 = Cov[0][7]*t1397;
  272. float t1456 = Cov[1][7]*t1411;
  273. float t1629 = Cov[6][7]*t1402;
  274. float t1457 = t1455+t1456-t1629-Cov[2][7]*t1419;
  275. float t1458 = Cov[0][8]*t1397;
  276. float t1459 = Cov[1][8]*t1411;
  277. float t1630 = Cov[6][8]*t1402;
  278. float t1460 = t1458+t1459-t1630-Cov[2][8]*t1419;
  279. float t1461 = q0*t1390*2.0f;
  280. float t1462 = q1*t1391*2.0f;
  281. float t1463 = q3*t1395*2.0f;
  282. float t1473 = q2*t1393*2.0f;
  283. float t1464 = t1461+t1462+t1463-t1473;
  284. float t1465 = q0*t1409*2.0f;
  285. float t1466 = q2*t1405*2.0f;
  286. float t1467 = q3*t1404*2.0f;
  287. float t1474 = q1*t1407*2.0f;
  288. float t1468 = t1465+t1466+t1467-t1474;
  289. float t1469 = q1*t1415*2.0f;
  290. float t1470 = q2*t1414*2.0f;
  291. float t1471 = q3*t1412*2.0f;
  292. float t1475 = q0*t1417*2.0f;
  293. float t1472 = t1469+t1470+t1471-t1475;
  294. float t1476 = Cov[7][0]*t1402;
  295. float t1477 = Cov[0][0]*t1464;
  296. float t1486 = Cov[1][0]*t1468;
  297. float t1487 = Cov[2][0]*t1472;
  298. float t1478 = t1476+t1477-t1486-t1487;
  299. float t1479 = Cov[7][1]*t1402;
  300. float t1480 = Cov[0][1]*t1464;
  301. float t1492 = Cov[1][1]*t1468;
  302. float t1493 = Cov[2][1]*t1472;
  303. float t1481 = t1479+t1480-t1492-t1493;
  304. float t1482 = Cov[7][2]*t1402;
  305. float t1483 = Cov[0][2]*t1464;
  306. float t1498 = Cov[1][2]*t1468;
  307. float t1499 = Cov[2][2]*t1472;
  308. float t1484 = t1482+t1483-t1498-t1499;
  309. float t1485 = sq(t1402);
  310. float t1488 = q1*t1390*2.0f;
  311. float t1489 = q2*t1395*2.0f;
  312. float t1490 = q3*t1393*2.0f;
  313. float t1533 = q0*t1391*2.0f;
  314. float t1491 = t1488+t1489+t1490-t1533;
  315. float t1494 = q0*t1407*2.0f;
  316. float t1495 = q1*t1409*2.0f;
  317. float t1496 = q2*t1404*2.0f;
  318. float t1534 = q3*t1405*2.0f;
  319. float t1497 = t1494+t1495+t1496-t1534;
  320. float t1500 = q0*t1415*2.0f;
  321. float t1501 = q1*t1417*2.0f;
  322. float t1502 = q3*t1414*2.0f;
  323. float t1535 = q2*t1412*2.0f;
  324. float t1503 = t1500+t1501+t1502-t1535;
  325. float t1504 = dvy*t1433;
  326. float t1505 = dvx*t1440;
  327. float t1506 = t1504+t1505;
  328. float t1507 = dvx*t1438;
  329. float t1508 = dvy*t1438;
  330. float t1509 = dvz*t1440;
  331. float t1510 = t1508+t1509;
  332. float t1511 = dvx*t1444;
  333. float t1551 = dvy*t1447;
  334. float t1512 = t1511-t1551;
  335. float t1513 = dvz*t1444;
  336. float t1514 = dvy*t1446;
  337. float t1515 = t1513+t1514;
  338. float t1516 = dvx*t1446;
  339. float t1517 = dvz*t1447;
  340. float t1518 = t1516+t1517;
  341. float t1519 = dvx*t1448;
  342. float t1520 = dvz*t1451;
  343. float t1521 = t1519+t1520;
  344. float t1522 = dvy*t1448;
  345. float t1552 = dvz*t1450;
  346. float t1523 = t1522-t1552;
  347. float t1524 = dvx*t1450;
  348. float t1525 = dvy*t1451;
  349. float t1526 = t1524+t1525;
  350. float t1527 = Cov[7][6]*t1402;
  351. float t1528 = Cov[0][6]*t1464;
  352. float t1529 = Cov[7][7]*t1402;
  353. float t1530 = Cov[0][7]*t1464;
  354. float t1531 = Cov[7][8]*t1402;
  355. float t1532 = Cov[0][8]*t1464;
  356. float t1536 = Cov[8][0]*t1402;
  357. float t1537 = Cov[1][0]*t1497;
  358. float t1545 = Cov[0][0]*t1491;
  359. float t1546 = Cov[2][0]*t1503;
  360. float t1538 = t1536+t1537-t1545-t1546;
  361. float t1539 = Cov[8][1]*t1402;
  362. float t1540 = Cov[1][1]*t1497;
  363. float t1547 = Cov[0][1]*t1491;
  364. float t1548 = Cov[2][1]*t1503;
  365. float t1541 = t1539+t1540-t1547-t1548;
  366. float t1542 = Cov[8][2]*t1402;
  367. float t1543 = Cov[1][2]*t1497;
  368. float t1549 = Cov[0][2]*t1491;
  369. float t1550 = Cov[2][2]*t1503;
  370. float t1544 = t1542+t1543-t1549-t1550;
  371. float t1553 = Cov[8][6]*t1402;
  372. float t1554 = Cov[1][6]*t1497;
  373. float t1555 = Cov[8][7]*t1402;
  374. float t1556 = Cov[1][7]*t1497;
  375. float t1557 = Cov[8][8]*t1402;
  376. float t1558 = Cov[1][8]*t1497;
  377. float t1560 = dvz*t1433;
  378. float t1559 = t1507-t1560;
  379. float t1561 = Cov[0][0]*t1510;
  380. float t1567 = Cov[2][0]*t1506;
  381. float t1568 = Cov[1][0]*t1559;
  382. float t1562 = Cov[3][0]+t1561-t1567-t1568;
  383. float t1563 = Cov[0][1]*t1510;
  384. float t1569 = Cov[2][1]*t1506;
  385. float t1570 = Cov[1][1]*t1559;
  386. float t1564 = Cov[3][1]+t1563-t1569-t1570;
  387. float t1565 = Cov[0][2]*t1510;
  388. float t1571 = Cov[2][2]*t1506;
  389. float t1572 = Cov[1][2]*t1559;
  390. float t1566 = Cov[3][2]+t1565-t1571-t1572;
  391. float t1573 = -t1507+t1560;
  392. float t1574 = Cov[1][0]*t1573;
  393. float t1575 = Cov[3][0]+t1561-t1567+t1574;
  394. float t1576 = Cov[1][1]*t1573;
  395. float t1577 = Cov[3][1]+t1563-t1569+t1576;
  396. float t1578 = Cov[1][2]*t1573;
  397. float t1579 = Cov[3][2]+t1565-t1571+t1578;
  398. float t1580 = Cov[0][6]*t1510;
  399. float t1581 = Cov[0][7]*t1510;
  400. float t1582 = Cov[0][8]*t1510;
  401. float t1583 = Cov[1][0]*t1518;
  402. float t1584 = Cov[2][0]*t1512;
  403. float t1592 = Cov[0][0]*t1515;
  404. float t1585 = Cov[4][0]+t1583+t1584-t1592;
  405. float t1586 = Cov[1][1]*t1518;
  406. float t1587 = Cov[2][1]*t1512;
  407. float t1593 = Cov[0][1]*t1515;
  408. float t1588 = Cov[4][1]+t1586+t1587-t1593;
  409. float t1589 = Cov[1][2]*t1518;
  410. float t1590 = Cov[2][2]*t1512;
  411. float t1594 = Cov[0][2]*t1515;
  412. float t1591 = Cov[4][2]+t1589+t1590-t1594;
  413. float t1595 = dvxNoise*t1433*t1447;
  414. float t1596 = Cov[1][6]*t1518;
  415. float t1597 = Cov[2][6]*t1512;
  416. float t1598 = Cov[4][6]+t1596+t1597-Cov[0][6]*t1515;
  417. float t1599 = Cov[1][7]*t1518;
  418. float t1600 = Cov[2][7]*t1512;
  419. float t1601 = Cov[4][7]+t1599+t1600-Cov[0][7]*t1515;
  420. float t1602 = Cov[1][8]*t1518;
  421. float t1603 = Cov[2][8]*t1512;
  422. float t1604 = Cov[4][8]+t1602+t1603-Cov[0][8]*t1515;
  423. float t1605 = Cov[2][0]*t1526;
  424. float t1606 = Cov[0][0]*t1523;
  425. float t1614 = Cov[1][0]*t1521;
  426. float t1607 = Cov[5][0]+t1605+t1606-t1614;
  427. float t1608 = Cov[2][1]*t1526;
  428. float t1609 = Cov[0][1]*t1523;
  429. float t1615 = Cov[1][1]*t1521;
  430. float t1610 = Cov[5][1]+t1608+t1609-t1615;
  431. float t1611 = Cov[2][2]*t1526;
  432. float t1612 = Cov[0][2]*t1523;
  433. float t1616 = Cov[1][2]*t1521;
  434. float t1613 = Cov[5][2]+t1611+t1612-t1616;
  435. float t1617 = dvzNoise*t1438*t1448;
  436. float t1618 = dvyNoise*t1444*t1450;
  437. float t1619 = Cov[2][6]*t1526;
  438. float t1620 = Cov[0][6]*t1523;
  439. float t1621 = Cov[5][6]+t1619+t1620-Cov[1][6]*t1521;
  440. float t1622 = Cov[2][7]*t1526;
  441. float t1623 = Cov[0][7]*t1523;
  442. float t1624 = Cov[5][7]+t1622+t1623-Cov[1][7]*t1521;
  443. float t1625 = Cov[2][8]*t1526;
  444. float t1626 = Cov[0][8]*t1523;
  445. float t1627 = Cov[5][8]+t1625+t1626-Cov[1][8]*t1521;
  446. float nextCov[9][9];
  447. nextCov[0][0] = daxNoise*t1485+t1397*t1424+t1411*t1431-t1419*t1432-t1402*t1454;
  448. nextCov[1][0] = -t1397*t1478-t1411*t1481+t1419*t1484+t1402*(t1527+t1528-Cov[1][6]*t1468-Cov[2][6]*t1472);
  449. nextCov[2][0] = -t1397*t1538-t1411*t1541+t1419*t1544+t1402*(t1553+t1554-Cov[0][6]*t1491-Cov[2][6]*t1503);
  450. nextCov[3][0] = -t1402*(Cov[3][6]+t1580-Cov[2][6]*t1506-Cov[1][6]*t1559)+t1397*t1562+t1411*t1564-t1419*t1566;
  451. nextCov[4][0] = t1397*t1585+t1411*t1588-t1402*t1598-t1419*t1591;
  452. nextCov[5][0] = t1397*t1607+t1411*t1610-t1402*t1621-t1419*t1613;
  453. nextCov[6][0] = -t1628+Cov[6][0]*t1397+Cov[6][1]*t1411-Cov[6][2]*t1419;
  454. nextCov[7][0] = -t1527+Cov[7][0]*t1397+Cov[7][1]*t1411-Cov[7][2]*t1419;
  455. nextCov[8][0] = -t1553+Cov[8][0]*t1397+Cov[8][1]*t1411-Cov[8][2]*t1419;
  456. nextCov[0][1] = -t1402*t1457-t1424*t1464+t1431*t1468+t1432*t1472;
  457. nextCov[1][1] = dayNoise*t1485+t1464*t1478-t1468*t1481-t1472*t1484+t1402*(t1529+t1530-Cov[1][7]*t1468-Cov[2][7]*t1472);
  458. nextCov[2][1] = t1464*t1538-t1468*t1541-t1472*t1544+t1402*(t1555+t1556-Cov[0][7]*t1491-Cov[2][7]*t1503);
  459. nextCov[3][1] = -t1402*(Cov[3][7]+t1581-Cov[2][7]*t1506-Cov[1][7]*t1559)-t1464*t1562+t1468*t1564+t1472*t1566;
  460. nextCov[4][1] = -t1402*t1601-t1464*t1585+t1468*t1588+t1472*t1591;
  461. nextCov[5][1] = -t1402*t1624-t1464*t1607+t1468*t1610+t1472*t1613;
  462. nextCov[6][1] = -t1629-Cov[6][0]*t1464+Cov[6][1]*t1468+Cov[6][2]*t1472;
  463. nextCov[7][1] = -t1529-Cov[7][0]*t1464+Cov[7][1]*t1468+Cov[7][2]*t1472;
  464. nextCov[8][1] = -t1555-Cov[8][0]*t1464+Cov[8][1]*t1468+Cov[8][2]*t1472;
  465. nextCov[0][2] = -t1402*t1460-t1431*t1497+t1432*t1503+t1491*(t1422+t1423-t1429-t1430);
  466. nextCov[1][2] = -t1478*t1491+t1481*t1497-t1484*t1503+t1402*(t1531+t1532-Cov[1][8]*t1468-Cov[2][8]*t1472);
  467. nextCov[2][2] = dazNoise*t1485-t1491*t1538+t1497*t1541-t1503*t1544+t1402*(t1557+t1558-Cov[0][8]*t1491-Cov[2][8]*t1503);
  468. nextCov[3][2] = -t1402*(Cov[3][8]+t1582-Cov[2][8]*t1506-Cov[1][8]*t1559)+t1491*t1562-t1497*t1564+t1503*t1566;
  469. nextCov[4][2] = -t1402*t1604+t1491*t1585-t1497*t1588+t1503*t1591;
  470. nextCov[5][2] = -t1402*t1627+t1491*t1607-t1497*t1610+t1503*t1613;
  471. nextCov[6][2] = -t1630+Cov[6][0]*t1491-Cov[6][1]*t1497+Cov[6][2]*t1503;
  472. nextCov[7][2] = -t1531+Cov[7][0]*t1491-Cov[7][1]*t1497+Cov[7][2]*t1503;
  473. nextCov[8][2] = -t1557+Cov[8][0]*t1491-Cov[8][1]*t1497+Cov[8][2]*t1503;
  474. nextCov[0][3] = Cov[0][3]*t1397+Cov[1][3]*t1411-Cov[2][3]*t1419-Cov[6][3]*t1402-t1432*t1506+t1510*(t1422+t1423-t1429-t1430)-t1559*(t1425+t1426-t1434-t1435);
  475. nextCov[1][3] = -Cov[0][3]*t1464-Cov[7][3]*t1402+Cov[1][3]*t1468+Cov[2][3]*t1472-t1478*t1510+t1484*t1506+t1481*t1559;
  476. nextCov[2][3] = -Cov[8][3]*t1402+Cov[0][3]*t1491-Cov[1][3]*t1497+Cov[2][3]*t1503-t1510*t1538+t1506*t1544+t1541*t1559;
  477. nextCov[3][3] = Cov[3][3]+Cov[0][3]*t1510-Cov[2][3]*t1506+Cov[1][3]*t1573-t1506*t1566+t1510*t1575+t1573*t1577+dvxNoise*sq(t1433)+dvyNoise*sq(t1440)+dvzNoise*sq(t1438);
  478. nextCov[4][3] = Cov[4][3]+t1595-Cov[0][3]*t1515+Cov[1][3]*t1518+Cov[2][3]*t1512+t1510*t1585-t1506*t1591+t1573*t1588-dvyNoise*t1440*t1444-dvzNoise*t1438*t1446;
  479. nextCov[5][3] = Cov[5][3]+t1617+Cov[0][3]*t1523-Cov[1][3]*t1521+Cov[2][3]*t1526+t1510*t1607-t1506*t1613+t1573*t1610-dvxNoise*t1433*t1451-dvyNoise*t1440*t1450;
  480. nextCov[6][3] = Cov[6][3]-Cov[6][2]*t1506+Cov[6][0]*t1510+Cov[6][1]*t1573;
  481. nextCov[7][3] = Cov[7][3]-Cov[7][2]*t1506+Cov[7][0]*t1510+Cov[7][1]*t1573;
  482. nextCov[8][3] = Cov[8][3]-Cov[8][2]*t1506+Cov[8][0]*t1510+Cov[8][1]*t1573;
  483. nextCov[0][4] = Cov[0][4]*t1397+Cov[1][4]*t1411-Cov[2][4]*t1419-Cov[6][4]*t1402-t1424*t1515+t1432*t1512+t1518*(t1425+t1426-t1434-t1435);
  484. nextCov[1][4] = -Cov[0][4]*t1464-Cov[7][4]*t1402+Cov[1][4]*t1468+Cov[2][4]*t1472+t1478*t1515-t1484*t1512-t1481*t1518;
  485. nextCov[2][4] = -Cov[8][4]*t1402+Cov[0][4]*t1491-Cov[1][4]*t1497+Cov[2][4]*t1503+t1515*t1538-t1512*t1544-t1518*t1541;
  486. nextCov[3][4] = Cov[3][4]+t1595+Cov[0][4]*t1510-Cov[2][4]*t1506+Cov[1][4]*t1573-t1515*t1575+t1512*t1579+t1518*t1577-dvyNoise*t1440*t1444-dvzNoise*t1438*t1446;
  487. nextCov[4][4] = Cov[4][4]-Cov[0][4]*t1515+Cov[1][4]*t1518+Cov[2][4]*t1512-t1515*t1585+t1512*t1591+t1518*t1588+dvxNoise*sq(t1447)+dvyNoise*sq(t1444)+dvzNoise*sq(t1446);
  488. nextCov[5][4] = Cov[5][4]+t1618+Cov[0][4]*t1523-Cov[1][4]*t1521+Cov[2][4]*t1526-t1515*t1607+t1512*t1613+t1518*t1610-dvxNoise*t1447*t1451-dvzNoise*t1446*t1448;
  489. nextCov[6][4] = Cov[6][4]+Cov[6][2]*t1512-Cov[6][0]*t1515+Cov[6][1]*t1518;
  490. nextCov[7][4] = Cov[7][4]+Cov[7][2]*t1512-Cov[7][0]*t1515+Cov[7][1]*t1518;
  491. nextCov[8][4] = Cov[8][4]+Cov[8][2]*t1512-Cov[8][0]*t1515+Cov[8][1]*t1518;
  492. nextCov[0][5] = Cov[0][5]*t1397+Cov[1][5]*t1411-Cov[2][5]*t1419-Cov[6][5]*t1402+t1424*t1523-t1431*t1521+t1526*(t1427+t1428-t1442-t1443);
  493. nextCov[1][5] = -Cov[0][5]*t1464-Cov[7][5]*t1402+Cov[1][5]*t1468+Cov[2][5]*t1472-t1478*t1523+t1481*t1521-t1484*t1526;
  494. nextCov[2][5] = -Cov[8][5]*t1402+Cov[0][5]*t1491-Cov[1][5]*t1497+Cov[2][5]*t1503-t1523*t1538+t1521*t1541-t1526*t1544;
  495. nextCov[3][5] = Cov[3][5]+t1617+Cov[0][5]*t1510-Cov[2][5]*t1506+Cov[1][5]*t1573-t1521*t1577+t1523*t1575+t1526*t1579-dvxNoise*t1433*t1451-dvyNoise*t1440*t1450;
  496. nextCov[4][5] = Cov[4][5]+t1618-Cov[0][5]*t1515+Cov[1][5]*t1518+Cov[2][5]*t1512+t1523*t1585-t1521*t1588+t1526*t1591-dvxNoise*t1447*t1451-dvzNoise*t1446*t1448;
  497. nextCov[5][5] = Cov[5][5]+Cov[0][5]*t1523-Cov[1][5]*t1521+Cov[2][5]*t1526+t1523*t1607-t1521*t1610+t1526*t1613+dvxNoise*sq(t1451)+dvyNoise*sq(t1450)+dvzNoise*sq(t1448);
  498. nextCov[6][5] = Cov[6][5]-Cov[6][1]*t1521+Cov[6][0]*t1523+Cov[6][2]*t1526;
  499. nextCov[7][5] = Cov[7][5]-Cov[7][1]*t1521+Cov[7][0]*t1523+Cov[7][2]*t1526;
  500. nextCov[8][5] = Cov[8][5]-Cov[8][1]*t1521+Cov[8][0]*t1523+Cov[8][2]*t1526;
  501. nextCov[0][6] = t1454;
  502. nextCov[1][6] = -t1527-t1528+Cov[1][6]*t1468+Cov[2][6]*t1472;
  503. nextCov[2][6] = -t1553-t1554+Cov[0][6]*t1491+Cov[2][6]*t1503;
  504. nextCov[3][6] = Cov[3][6]+t1580-Cov[2][6]*t1506+Cov[1][6]*t1573;
  505. nextCov[4][6] = t1598;
  506. nextCov[5][6] = t1621;
  507. nextCov[6][6] = Cov[6][6];
  508. nextCov[7][6] = Cov[7][6];
  509. nextCov[8][6] = Cov[8][6];
  510. nextCov[0][7] = t1457;
  511. nextCov[1][7] = -t1529-t1530+Cov[1][7]*t1468+Cov[2][7]*t1472;
  512. nextCov[2][7] = -t1555-t1556+Cov[0][7]*t1491+Cov[2][7]*t1503;
  513. nextCov[3][7] = Cov[3][7]+t1581-Cov[2][7]*t1506+Cov[1][7]*t1573;
  514. nextCov[4][7] = t1601;
  515. nextCov[5][7] = t1624;
  516. nextCov[6][7] = Cov[6][7];
  517. nextCov[7][7] = Cov[7][7];
  518. nextCov[8][7] = Cov[8][7];
  519. nextCov[0][8] = t1460;
  520. nextCov[1][8] = -t1531-t1532+Cov[1][8]*t1468+Cov[2][8]*t1472;
  521. nextCov[2][8] = -t1557-t1558+Cov[0][8]*t1491+Cov[2][8]*t1503;
  522. nextCov[3][8] = Cov[3][8]+t1582-Cov[2][8]*t1506+Cov[1][8]*t1573;
  523. nextCov[4][8] = t1604;
  524. nextCov[5][8] = t1627;
  525. nextCov[6][8] = Cov[6][8];
  526. nextCov[7][8] = Cov[7][8];
  527. nextCov[8][8] = Cov[8][8];
  528. // Add the gyro bias state noise
  529. for (uint8_t i=6;i<=8;i++) {
  530. nextCov[i][i] = nextCov[i][i] + delAngBiasVariance;
  531. }
  532. // copy predicted variances whilst constraining to be non-negative
  533. for (uint8_t index=0; index<=8; index++) {
  534. if (nextCov[index][index] < 0.0f) {
  535. Cov[index][index] = 0.0f;
  536. } else {
  537. Cov[index][index] = nextCov[index][index];
  538. }
  539. }
  540. // copy elements to covariance matrix whilst enforcing symmetry
  541. for (uint8_t rowIndex=1; rowIndex<=8; rowIndex++) {
  542. for (uint8_t colIndex=0; colIndex<=rowIndex-1; colIndex++) {
  543. Cov[rowIndex][colIndex] = 0.5f*(nextCov[rowIndex][colIndex] + nextCov[colIndex][rowIndex]);
  544. Cov[colIndex][rowIndex] = Cov[rowIndex][colIndex];
  545. }
  546. }
  547. }
  548. // Fuse the SoloGimbalEKF velocity estimates - this enables alevel reference to be maintained during constant turns
  549. void SoloGimbalEKF::fuseVelocity()
  550. {
  551. const AP_AHRS_NavEKF &_ahrs = AP::ahrs_navekf();
  552. if (!_ahrs.have_inertial_nav()) {
  553. return;
  554. }
  555. float R_OBS = 0.25f;
  556. float innovation[3];
  557. float varInnov[3];
  558. Vector3f angErrVec;
  559. uint8_t stateIndex;
  560. float K[9];
  561. // Fuse measurements sequentially
  562. for (uint8_t obsIndex=0;obsIndex<=2;obsIndex++) {
  563. stateIndex = 3 + obsIndex;
  564. // Calculate the velocity measurement innovation using the SoloGimbalEKF estimate as the observation
  565. // if heading isn't aligned, use zero velocity (static assumption)
  566. if (YawAligned) {
  567. Vector3f measVelNED = Vector3f(0,0,0);
  568. nav_filter_status main_ekf_status;
  569. if (_ahrs.get_filter_status(main_ekf_status)) {
  570. if (main_ekf_status.flags.horiz_vel) {
  571. _ahrs.get_velocity_NED(measVelNED);
  572. }
  573. }
  574. innovation[obsIndex] = state.velocity[obsIndex] - measVelNED[obsIndex];
  575. } else {
  576. innovation[obsIndex] = state.velocity[obsIndex];
  577. }
  578. // Zero the attitude error states - they represent the incremental error so must be zero before corrections are applied
  579. state.angErr.zero();
  580. // Calculate the innovation variance
  581. varInnov[obsIndex] = Cov[stateIndex][stateIndex] + R_OBS;
  582. // Calculate the Kalman gain and correct states, taking advantage of direct state observation
  583. for (uint8_t rowIndex=0;rowIndex<=8;rowIndex++) {
  584. K[rowIndex] = Cov[rowIndex][stateIndex]/varInnov[obsIndex];
  585. states[rowIndex] -= K[rowIndex] * innovation[obsIndex];
  586. }
  587. // Store tilt error estimate for external monitoring
  588. angErrVec = angErrVec + state.angErr;
  589. // the first 3 states represent the angular error vector where truth = estimate + error. This is is used to correct the estimated quaternion
  590. // Bring the quaternion state estimate back to 'truth' by adding the error
  591. state.quat.rotate(state.angErr);
  592. // re-normalise the quaternion
  593. state.quat.normalize();
  594. // Update the covariance
  595. for (uint8_t rowIndex=0;rowIndex<=8;rowIndex++) {
  596. for (uint8_t colIndex=0;colIndex<=8;colIndex++) {
  597. Cov[rowIndex][colIndex] = Cov[rowIndex][colIndex] - K[rowIndex]*Cov[stateIndex][colIndex];
  598. }
  599. }
  600. // force symmetry and constrain diagonals to be non-negative
  601. fixCovariance();
  602. }
  603. // calculate tilt component of angle correction
  604. TiltCorrectionSquared = sq(angErrVec.x) + sq(angErrVec.y);
  605. }
  606. // check for new magnetometer data and update store measurements if available
  607. void SoloGimbalEKF::readMagData()
  608. {
  609. const AP_AHRS_NavEKF &_ahrs = AP::ahrs_navekf();
  610. if (_ahrs.get_compass() &&
  611. _ahrs.get_compass()->use_for_yaw() &&
  612. _ahrs.get_compass()->last_update_usec() != lastMagUpdate) {
  613. // store time of last measurement update
  614. lastMagUpdate = _ahrs.get_compass()->last_update_usec();
  615. // read compass data and scale to improve numerical conditioning
  616. magData = _ahrs.get_compass()->get_field();
  617. // let other processes know that new compass data has arrived
  618. newDataMag = true;
  619. } else {
  620. newDataMag = false;
  621. }
  622. }
  623. // Fuse compass measurements from autopilot
  624. void SoloGimbalEKF::fuseCompass()
  625. {
  626. float q0 = state.quat[0];
  627. float q1 = state.quat[1];
  628. float q2 = state.quat[2];
  629. float q3 = state.quat[3];
  630. float magX = magData.x;
  631. float magY = magData.y;
  632. float magZ = magData.z;
  633. const float R_MAG = 3e-2f;
  634. // Calculate observation Jacobian
  635. float t5695 = sq(q0);
  636. float t5696 = sq(q1);
  637. float t5697 = sq(q2);
  638. float t5698 = sq(q3);
  639. float t5699 = t5695+t5696-t5697-t5698;
  640. float t5702 = q0*q2*2.0f;
  641. float t5703 = q1*q3*2.0f;
  642. float t5704 = t5702+t5703;
  643. float t5705 = q0*q3*2.0f;
  644. float t5707 = q1*q2*2.0f;
  645. float t5706 = t5705-t5707;
  646. float t5708 = cosTheta*sinPsi;
  647. float t5709 = sinPhi*sinTheta*cosPsi;
  648. float t5710 = t5708+t5709;
  649. float t5711 = t5705+t5707;
  650. float t5712 = sinTheta*sinPsi;
  651. float t5730 = cosTheta*sinPhi*cosPsi;
  652. float t5713 = t5712-t5730;
  653. float t5714 = q0*q1*2.0f;
  654. float t5720 = q2*q3*2.0f;
  655. float t5715 = t5714-t5720;
  656. float t5716 = t5695-t5696+t5697-t5698;
  657. float t5717 = sinTheta*cosPsi;
  658. float t5718 = cosTheta*sinPhi*sinPsi;
  659. float t5719 = t5717+t5718;
  660. float t5721 = cosTheta*cosPsi;
  661. float t5735 = sinPhi*sinTheta*sinPsi;
  662. float t5722 = t5721-t5735;
  663. float t5724 = sinPhi*t5706;
  664. float t5725 = cosPhi*sinTheta*t5699;
  665. float t5726 = cosPhi*cosTheta*t5704;
  666. float t5727 = t5724+t5725-t5726;
  667. float t5728 = magZ*t5727;
  668. float t5729 = t5699*t5710;
  669. float t5731 = t5704*t5713;
  670. float t5732 = cosPhi*cosPsi*t5706;
  671. float t5733 = t5729+t5731-t5732;
  672. float t5734 = magY*t5733;
  673. float t5736 = t5699*t5722;
  674. float t5737 = t5704*t5719;
  675. float t5738 = cosPhi*sinPsi*t5706;
  676. float t5739 = t5736+t5737+t5738;
  677. float t5740 = magX*t5739;
  678. float t5741 = -t5728+t5734+t5740;
  679. float t5742 = 1.0f/t5741;
  680. float t5743 = sinPhi*t5716;
  681. float t5744 = cosPhi*cosTheta*t5715;
  682. float t5745 = cosPhi*sinTheta*t5711;
  683. float t5746 = -t5743+t5744+t5745;
  684. float t5747 = magZ*t5746;
  685. float t5748 = t5710*t5711;
  686. float t5749 = t5713*t5715;
  687. float t5750 = cosPhi*cosPsi*t5716;
  688. float t5751 = t5748-t5749+t5750;
  689. float t5752 = magY*t5751;
  690. float t5753 = t5715*t5719;
  691. float t5754 = t5711*t5722;
  692. float t5755 = cosPhi*sinPsi*t5716;
  693. float t5756 = t5753-t5754+t5755;
  694. float t5757 = magX*t5756;
  695. float t5758 = t5747-t5752+t5757;
  696. float t5759 = t5742*t5758;
  697. float t5723 = tanf(t5759);
  698. float t5760 = sq(t5723);
  699. float t5761 = t5760+1.0f;
  700. float t5762 = 1.0f/sq(t5741);
  701. float H_MAG[3];
  702. H_MAG[0] = -t5761*(t5742*(magZ*(sinPhi*t5715+cosPhi*cosTheta*t5716)+magY*(t5713*t5716+cosPhi*cosPsi*t5715)+magX*(t5716*t5719-cosPhi*sinPsi*t5715))-t5758*t5762*(magZ*(sinPhi*t5704+cosPhi*cosTheta*t5706)+magY*(t5706*t5713+cosPhi*cosPsi*t5704)+magX*(t5706*t5719-cosPhi*sinPsi*t5704)));
  703. H_MAG[1] = t5761*(t5742*(magZ*(cosPhi*cosTheta*t5711-cosPhi*sinTheta*t5715)+magY*(t5711*t5713+t5710*t5715)+magX*(t5711*t5719+t5715*t5722))+t5758*t5762*(magZ*(cosPhi*cosTheta*t5699+cosPhi*sinTheta*t5704)+magY*(t5699*t5713-t5704*t5710)+magX*(t5699*t5719-t5704*t5722)));
  704. H_MAG[2] = t5761*(t5742*(-magZ*(sinPhi*t5711+cosPhi*sinTheta*t5716)+magY*(t5710*t5716-cosPhi*cosPsi*t5711)+magX*(t5716*t5722+cosPhi*sinPsi*t5711))-t5758*t5762*(magZ*(sinPhi*t5699-cosPhi*sinTheta*t5706)+magY*(t5706*t5710+cosPhi*t5699*cosPsi)+magX*(t5706*t5722-cosPhi*t5699*sinPsi)));
  705. // Calculate innovation variance and Kalman gains, taking advantage of the fact that only the first 3 elements in H are non zero
  706. float PH[3];
  707. float varInnov = R_MAG;
  708. for (uint8_t rowIndex=0;rowIndex<=2;rowIndex++) {
  709. PH[rowIndex] = 0.0f;
  710. for (uint8_t colIndex=0;colIndex<=2;colIndex++) {
  711. PH[rowIndex] += Cov[rowIndex][colIndex]*H_MAG[colIndex];
  712. }
  713. varInnov += H_MAG[rowIndex]*PH[rowIndex];
  714. }
  715. float K_MAG[9];
  716. float varInnovInv = 1.0f / varInnov;
  717. for (uint8_t rowIndex=0;rowIndex<=8;rowIndex++) {
  718. K_MAG[rowIndex] = 0.0f;
  719. for (uint8_t colIndex=0;colIndex<=2;colIndex++) {
  720. K_MAG[rowIndex] += Cov[rowIndex][colIndex]*H_MAG[colIndex];
  721. }
  722. K_MAG[rowIndex] *= varInnovInv;
  723. }
  724. // Calculate the innovation
  725. float innovation = calcMagHeadingInnov();
  726. // limit the innovation so that initial corrections are not too large
  727. if (innovation > 0.5f) {
  728. innovation = 0.5f;
  729. } else if (innovation < -0.5f) {
  730. innovation = -0.5f;
  731. }
  732. // correct the state vector
  733. state.angErr.zero();
  734. for (uint8_t i=0;i<=8;i++) {
  735. states[i] -= K_MAG[i] * innovation;
  736. }
  737. // the first 3 states represent the angular error vector where truth = estimate + error. This is is used to correct the estimated quaternion
  738. // Bring the quaternion state estimate back to 'truth' by adding the error
  739. state.quat.rotate(state.angErr);
  740. // re-normalise the quaternion
  741. state.quat.normalize();
  742. // correct the covariance using P = P - K*H*P taking advantage of the fact that only the first 3 elements in H are non zero
  743. float HP[9];
  744. for (uint8_t colIndex=0;colIndex<=8;colIndex++) {
  745. HP[colIndex] = 0.0f;
  746. for (uint8_t rowIndex=0;rowIndex<=2;rowIndex++) {
  747. HP[colIndex] += H_MAG[rowIndex]*Cov[rowIndex][colIndex];
  748. }
  749. }
  750. for (uint8_t rowIndex=0;rowIndex<=8;rowIndex++) {
  751. for (uint8_t colIndex=0;colIndex<=8;colIndex++) {
  752. Cov[rowIndex][colIndex] -= K_MAG[rowIndex] * HP[colIndex];
  753. }
  754. }
  755. // force symmetry and constrain diagonals to be non-negative
  756. fixCovariance();
  757. }
  758. // Perform an initial heading alignment using the magnetic field and assumed declination
  759. void SoloGimbalEKF::alignHeading()
  760. {
  761. // calculate the correction rotation vector in NED frame
  762. Vector3f deltaRotNED = Vector3f(0,0,-calcMagHeadingInnov());
  763. // rotate into sensor frame
  764. Vector3f angleCorrection = Tsn.transposed()*deltaRotNED;
  765. // apply the correction to the quaternion state
  766. // Bring the quaternion state estimate back to 'truth' by adding the error
  767. state.quat.rotate(angleCorrection);
  768. // re-normalize the quaternion
  769. state.quat.normalize();
  770. }
  771. // Calculate magnetic heading innovation
  772. float SoloGimbalEKF::calcMagHeadingInnov()
  773. {
  774. // Define rotation from magnetometer to sensor using a 312 rotation sequence
  775. Matrix3f Tms;
  776. Tms[0][0] = cosTheta*cosPsi-sinPsi*sinPhi*sinTheta;
  777. Tms[1][0] = -sinPsi*cosPhi;
  778. Tms[2][0] = cosPsi*sinTheta+cosTheta*sinPsi*sinPhi;
  779. Tms[0][1] = cosTheta*sinPsi+cosPsi*sinPhi*sinTheta;
  780. Tms[1][1] = cosPsi*cosPhi;
  781. Tms[2][1] = sinPsi*sinTheta-cosTheta*cosPsi*sinPhi;
  782. Tms[0][2] = -sinTheta*cosPhi;
  783. Tms[1][2] = sinPhi;
  784. Tms[2][2] = cosTheta*cosPhi;
  785. const AP_AHRS_NavEKF &_ahrs = AP::ahrs_navekf();
  786. // get earth magnetic field estimate from main ekf if available to take advantage of main ekf magnetic field learning
  787. Vector3f earth_magfield = Vector3f(0,0,0);
  788. _ahrs.get_mag_field_NED(earth_magfield);
  789. float declination;
  790. if (!earth_magfield.is_zero()) {
  791. declination = atan2f(earth_magfield.y,earth_magfield.x);
  792. } else {
  793. declination = _ahrs.get_compass()->get_declination();
  794. }
  795. Vector3f body_magfield = Vector3f(0,0,0);
  796. _ahrs.get_mag_field_correction(body_magfield);
  797. // Define rotation from magnetometer to NED axes
  798. Matrix3f Tmn = Tsn*Tms;
  799. // rotate magentic field measured at top plate into NED axes afer applying bias values learnt by main EKF
  800. Vector3f magMeasNED = Tmn*(magData - body_magfield);
  801. // calculate the innovation where the predicted measurement is the angle wrt magnetic north of the horizontal component of the measured field
  802. float innovation = atan2f(magMeasNED.y,magMeasNED.x) - declination;
  803. // wrap the innovation so it sits on the range from +-pi
  804. if (innovation > M_PI) {
  805. innovation = innovation - 2*M_PI;
  806. } else if (innovation < -M_PI) {
  807. innovation = innovation + 2*M_PI;
  808. }
  809. // Unwrap so that a large yaw gyro bias offset that causes the heading to wrap does not lead to continual uncontrolled heading drift
  810. if (innovation - lastInnovation > M_PI) {
  811. // Angle has wrapped in the positive direction to subtract an additional 2*Pi
  812. innovationIncrement -= 2*M_PI;
  813. } else if (innovation -innovationIncrement < -M_PI) {
  814. // Angle has wrapped in the negative direction so add an additional 2*Pi
  815. innovationIncrement += 2*M_PI;
  816. }
  817. lastInnovation = innovation;
  818. return innovation + innovationIncrement;
  819. }
  820. // Force symmmetry and non-negative diagonals on state covarinace matrix
  821. void SoloGimbalEKF::fixCovariance()
  822. {
  823. // force symmetry
  824. for (uint8_t rowIndex=1; rowIndex<=8; rowIndex++) {
  825. for (uint8_t colIndex=0; colIndex<=rowIndex-1; colIndex++) {
  826. Cov[rowIndex][colIndex] = 0.5f*(Cov[rowIndex][colIndex] + Cov[colIndex][rowIndex]);
  827. Cov[colIndex][rowIndex] = Cov[rowIndex][colIndex];
  828. }
  829. }
  830. // constrain diagonals to be non-negative
  831. for (uint8_t index=1; index<=8; index++) {
  832. if (Cov[index][index] < 0.0f) {
  833. Cov[index][index] = 0.0f;
  834. }
  835. }
  836. }
  837. // get gyro bias data
  838. void SoloGimbalEKF::getGyroBias(Vector3f &gyroBias) const
  839. {
  840. if (dtIMU < 1.0e-6f) {
  841. gyroBias.zero();
  842. } else {
  843. gyroBias = state.delAngBias / dtIMU;
  844. }
  845. }
  846. void SoloGimbalEKF::setGyroBias(const Vector3f &gyroBias)
  847. {
  848. if (dtIMU < 1.0e-6f) {
  849. return;
  850. }
  851. state.delAngBias = gyroBias * dtIMU;
  852. }
  853. // get quaternion data
  854. void SoloGimbalEKF::getQuat(Quaternion &quat) const
  855. {
  856. quat = state.quat;
  857. }
  858. // get filter status - true is aligned
  859. bool SoloGimbalEKF::getStatus() const
  860. {
  861. float run_time = AP_HAL::millis() - StartTime_ms;
  862. return YawAligned && (run_time > 15000);
  863. }