Paparazzi UAS v7.1_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
ins_ext_pose.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2023 MAVLab
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
28#include <time.h>
29
30#include "ins_ext_pose.h"
31#include "state.h"
32#include "math/pprz_algebra.h"
34#include "modules/imu/imu.h"
35#include "modules/ahrs/ahrs.h"
36#include "modules/ins/ins.h"
37#include "generated/flight_plan.h"
38#include "modules/core/abi.h"
39
40#ifndef INS_EXT_POSE_P0
41#define INS_EXT_POSE_P0 {1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.}
42#endif
43
44#ifndef INS_EXT_POSE_Q_NOISE
45#define INS_EXT_POSE_Q_NOISE {1.0, 1.0, 1.0, 0.0173, 4.878e-4, 3.547e-4}
46#endif
47
48#ifndef INS_EXT_POSE_R_NOISE
49#define INS_EXT_POSE_R_NOISE {8.372e-6, 3.832e-6, 4.761e-6, 2.830e-4, 8.684e-6, 7.013e-6}
50#endif
51
57#ifndef INS_EXT_POSE_MAX_AGE
58#define INS_EXT_POSE_MAX_AGE 30.f
59#endif
60
62#ifndef INS_EXT_POSE_AGE_DRIFT
63#define INS_EXT_POSE_AGE_DRIFT 0.01f
64#endif
65
67#ifndef INS_EXT_POSE_AGE_RESYNC
68#define INS_EXT_POSE_AGE_RESYNC 1000
69#endif
70
74#ifndef INS_EXT_POSE_AGE_RESET_TIME
75#define INS_EXT_POSE_AGE_RESET_TIME 300
76#endif
77
81#ifndef INS_EXT_POSE_GATE_PSI
82#define INS_EXT_POSE_GATE_PSI RadOfDeg(40.f)
83#endif
84
85#ifndef INS_EXT_POSE_GATE_TILT
86#define INS_EXT_POSE_GATE_TILT RadOfDeg(15.f)
87#endif
88
90#ifndef INS_EXT_POSE_GATE_RESET_NB
91#define INS_EXT_POSE_GATE_RESET_NB 10
92#endif
93
95#ifndef INS_EXT_POSE_TIMEOUT
96#define INS_EXT_POSE_TIMEOUT 0.5f
97#endif
98
102
103#if INS_EXT_POSE_DEBUG_PRINT
104#include <stdio.h>
105#define DEBUG_PRINT(...) printf(__VA_ARGS__)
106#else
107#define DEBUG_PRINT(...) {}
108#endif
109
110#ifdef INS_EXT_VISION_ROTATION
112#endif
113
117 /* Inputs */
122
128 float ev_time;
129
130 /* External pose age and gating */
131 bool ts_valid;
135 float delay_min;
136 float ev_age;
142
143 /* Origin */
145
146 /* output LTP NED */
150
151 /* status */
153};
154
156
157
159{
160 struct LlaCoor_i llh_nav0; /* Height above the ellipsoid */
162 llh_nav0.lon = NAV_LON0;
163 /* NAV_ALT0 = ground alt above msl, NAV_MSL0 = geoid-height (msl) over ellipsoid */
164 llh_nav0.alt = NAV_ALT0 + NAV_MSL0;
165
166 struct EcefCoor_i ecef_nav0;
168
172 /* update local ENU coordinates of global waypoints */
174}
175
176
180#if PERIODIC_TELEMETRY
182
190
191static void send_ins_z(struct transport_tx *trans, struct link_device *dev)
192{
193 static float fake_baro_z = 0.0;
195 (float *)&fake_baro_z, &ins_ext_pose.ltp_pos.z,
197}
198
207
208static void send_filter_status(struct transport_tx *trans, struct link_device *dev)
209{
212 uint16_t value = ins_ext_pose.nb_stale + ins_ext_pose.nb_gated; // rejected poses
213
214 if (ins_ext_pose.started) {
216 state_filter_mode = 3; // OK
217 } else {
218 state_filter_mode = 4; // GPS_LOST, no recent external pose fused
219 }
220 }
222}
223
239
240static void send_ahrs_bias(struct transport_tx *trans, struct link_device *dev)
241{
242 float dummy0 = 0.0;
244 &ekf_X[9],
245 &ekf_X[10],
246 &ekf_X[11],
247 &ekf_X[12],
248 &ekf_X[13],
249 &ekf_X[14],
250 &dummy0,
251 &dummy0,
252 &dummy0);
253}
254#endif
255
256
261#ifndef INS_EXT_POSE_IMU_ID
262#define INS_EXT_POSE_IMU_ID ABI_BROADCAST
263#endif
265
268
271
272
274 uint32_t stamp __attribute__((unused)),
275 struct Int32Rates *gyro)
276{
279}
280
282 uint32_t stamp __attribute__((unused)),
283 struct Int32Vect3 *accel)
284{
287}
288
289
301{
302 if (ts == 0 || ins_ext_pose_max_age <= 0.f) {
303 ins_ext_pose.ev_age = 0.f;
304 return true;
305 }
306
308 uint32_t delay = now - ts;
310
311 // first pose, or sender clock restarted
313 ins_ext_pose.ts_valid = true;
318 ins_ext_pose.ev_age = 0.f;
319 return true;
320 }
321
322 // duplicate or out of order
323 if ((int32_t)(ts - ins_ext_pose.ts_last) <= 0) {
324 return false;
325 }
327
328 // lowest delay, allowed to rise slowly to follow clock drift
331
334 return false;
335 }
336 // lasting delay increase: take it as the new lowest delay
338 }
340 return true;
341}
342
344{
345 if (DL_EXTERNAL_POSE_ac_id(buf) != AC_ID) { return; } // not for this aircraft
346
349 return;
350 }
351
352 struct EnuCoor_f enu_pos, enu_vel;
359 float quat_i = DL_EXTERNAL_POSE_body_qi(buf);
360 float quat_x = DL_EXTERNAL_POSE_body_qx(buf);
361 float quat_y = DL_EXTERNAL_POSE_body_qy(buf);
362 float quat_z = DL_EXTERNAL_POSE_body_qz(buf);
363
364 DEBUG_PRINT("EXT_UPDATE\n");
365
366 struct FloatQuat orient;
368
369 // Transformation of External Pose. Optitrack motive 2.X Yup
370 orient.qi = quat_i ;
371 orient.qx = quat_y ;
372 orient.qy = quat_x ;
373 orient.qz = -quat_z;
374
375#ifdef INS_EXT_VISION_ROTATION
376 // Rotate the quaternion
377 struct FloatQuat rot_q;
379 QUAT_COPY(orient, rot_q);
380#endif
381
383
389
391
393}
394
398static void ekf_init(void);
399static void ekf_run(void);
400
442
444{
445 ekf_run();
446}
447
448
449
450
451/***************************************************
452 * Kalman Filter.
453 */
454static void ekf_f(const float X[EKF_NUM_STATES],
455 const float U[EKF_NUM_INPUTS],
456 float out[EKF_NUM_STATES]);
457static void ekf_F(const float X[EKF_NUM_STATES],
458 const float U[EKF_NUM_INPUTS],
459 float out[EKF_NUM_STATES][EKF_NUM_STATES]);
460static void ekf_L(const float X[EKF_NUM_STATES],
461 const float U[EKF_NUM_INPUTS],
462 float out[EKF_NUM_STATES][EKF_NUM_INPUTS]);
463
464static void ekf_prediction_step(const float U[EKF_NUM_INPUTS], const float dt);
465static void ekf_measurement_step(const float Z[EKF_NUM_OUTPUTS]);
466
467
468
470static float ekf_U[EKF_NUM_INPUTS];
471static float ekf_Z[EKF_NUM_OUTPUTS];
475
477 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
478 {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
479 {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
480 {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
481 {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
482 {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}};
483
484
485static float t0;
486static float t1;
487
488static void ekf_set_diag(float **a, float *b, int n)
489{
490 int i, j;
491 for (i = 0 ; i < n; i++) {
492 for (j = 0 ; j < n; j++) {
493 if (i == j) {
494 a[i][j] = b[i];
495 } else {
496 a[i][j] = 0.0;
497 }
498 }
499 }
500}
501
502
503
504static void ekf_init(void)
505{
506
507 DEBUG_PRINT("ekf init");
508 float X0[EKF_NUM_STATES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
509 float U0[EKF_NUM_INPUTS] = {0, 0, 0, 0, 0, 0};
510 float Z0[EKF_NUM_OUTPUTS] = {0, 0, 0, 0, 0, 0};
511
515
519
526}
527
528static void ekf_f(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], float out[EKF_NUM_STATES])
529{
530 const float x0 = cosf(X[EKF_X_PSI]);
531 const float x1 = U[EKF_U_ACC_X] - X[EKF_X_A_BIAS_X];
532 const float x2 = cosf(X[EKF_X_THETA]);
533 const float x3 = x1 * x2;
534 const float x4 = U[EKF_U_ACC_Z] - X[EKF_X_A_BIAS_Z];
535 const float x5 = sinf(X[EKF_X_PHI]);
536 const float x6 = sinf(X[EKF_X_PSI]);
537 const float x7 = x5 * x6;
538 const float x8 = sinf(X[EKF_X_THETA]);
539 const float x9 = cosf(X[EKF_X_PHI]);
540 const float x10 = x0 * x9;
541 const float x11 = U[EKF_U_ACC_Y] - X[EKF_X_A_BIAS_Y];
542 const float x12 = x6 * x9;
543 const float x13 = x0 * x5;
544 const float x14 = tanf(X[EKF_X_THETA]);
545 const float x15 = U[EKF_U_GYRO_Q] - X[EKF_X_G_BIAS_Q];
546 const float x16 = x15 * x5;
547 const float x17 = U[EKF_U_GYRO_R] - X[EKF_X_G_BIAS_R];
548 const float x18 = x17 * x9;
549 const float x19 = 1.0f / x2; // FIXME prevent div by zero
550 out[EKF_X_POS_X] = X[EKF_X_VEL_X];
551 out[EKF_X_POS_Y] = X[EKF_X_VEL_Y];
552 out[EKF_X_POS_Z] = X[EKF_X_VEL_Z];
553 out[EKF_X_VEL_X] = x0 * x3 + x11 * (-x12 + x13 * x8) + x4 * (x10 * x8 + x7);
554 out[EKF_X_VEL_Y] = x11 * (x10 + x7 * x8) + x3 * x6 + x4 * (x12 * x8 - x13);
555 out[EKF_X_VEL_Z] = -x1 * x8 + x11 * x2 * x5 + x2 * x4 * x9 + 9.81f;
556 out[EKF_X_PHI] = U[EKF_U_GYRO_P] - X[EKF_X_G_BIAS_P] + x14 * x16 + x14 * x18;
557 out[EKF_X_THETA] = x15 * x9 - x17 * x5;
558 out[EKF_X_PSI] = x16 * x19 + x18 * x19;
559 out[EKF_X_A_BIAS_X] = 0.f;
560 out[EKF_X_A_BIAS_Y] = 0.f;
561 out[EKF_X_A_BIAS_Z] = 0.f;
562 out[EKF_X_G_BIAS_P] = 0.f;
563 out[EKF_X_G_BIAS_Q] = 0.f;
564 out[EKF_X_G_BIAS_R] = 0.f;
565}
566
567static void ekf_F(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS],
568 float out[EKF_NUM_STATES][EKF_NUM_STATES])
569{
570 const float x0 = U[EKF_U_ACC_Y] - X[EKF_X_A_BIAS_Y];
571 const float x1 = sinf(X[EKF_X_PHI]);
572 const float x2 = sinf(X[EKF_X_PSI]);
573 const float x3 = x1 * x2;
574 const float x4 = sinf(X[EKF_X_THETA]);
575 const float x5 = cosf(X[EKF_X_PHI]);
576 const float x6 = cosf(X[EKF_X_PSI]);
577 const float x7 = x5 * x6;
578 const float x8 = x4 * x7;
579 const float x9 = x3 + x8;
580 const float x10 = U[EKF_U_ACC_Z] - X[EKF_X_A_BIAS_Z];
581 const float x11 = x2 * x5;
582 const float x12 = x1 * x6;
583 const float x13 = x12 * x4;
584 const float x14 = x11 - x13;
585 const float x15 = U[EKF_U_ACC_X] - X[EKF_X_A_BIAS_X];
586 const float x16 = x15 * x4;
587 const float x17 = cosf(X[EKF_X_THETA]);
588 const float x18 = x0 * x17;
589 const float x19 = x10 * x17;
590 const float x20 = x17 * x2;
591 const float x21 = x11 * x4;
592 const float x22 = x12 - x21;
593 const float x23 = -x3 * x4 - x7;
594 const float x24 = x17 * x6;
595 const float x25 = x17 * x5;
596 const float x26 = x1 * x17;
597 const float x27 = x4 * x5;
598 const float x28 = U[EKF_U_GYRO_Q] - X[EKF_X_G_BIAS_Q];
599 const float x29 = tanf(X[EKF_X_THETA]);
600 const float x30 = x29 * x5;
601 const float x31 = U[EKF_U_GYRO_R] - X[EKF_X_G_BIAS_R];
602 const float x32 = x1 * x29;
603 const float x33 = powf(x29, 2.f) + 1.f;
604 const float x34 = x1 * x28;
605 const float x35 = 1.0f / x17;
606 const float x36 = x35 * x5;
607 const float x37 = x1 * x35;
608 const float x38 = powf(x17, -2.f);
609
610 memset(out, 0, (EKF_NUM_STATES*EKF_NUM_STATES) * (sizeof **out));
611 out[EKF_X_POS_X][EKF_X_VEL_X] = 1.f;
612 out[EKF_X_POS_Y][EKF_X_VEL_Y] = 1.f;
613 out[EKF_X_POS_Z][EKF_X_VEL_Z] = 1.f;
614 out[EKF_X_VEL_X][EKF_X_PHI] = x0 * x9 + x10 * x14;
615 out[EKF_X_VEL_X][EKF_X_THETA] = x12 * x18 - x16 * x6 + x19 * x7;
616 out[EKF_X_VEL_X][EKF_X_PSI] = x0 * x23 + x10 * x22 - x15 * x20;
619 out[EKF_X_VEL_X][EKF_X_A_BIAS_Z] = -x3 - x8;
620 out[EKF_X_VEL_Y][EKF_X_PHI] = x0 * (-x12 + x21) + x10 * x23;
621 out[EKF_X_VEL_Y][EKF_X_THETA] = x11 * x19 - x16 * x2 + x18 * x3;
622 out[EKF_X_VEL_Y][EKF_X_PSI] = x0 * (-x11 + x13) + x10 * x9 + x15 * x24;
626 out[EKF_X_VEL_Z][EKF_X_PHI] = x0 * x25 - x10 * x26;
627 out[EKF_X_VEL_Z][EKF_X_THETA] = -x0 * x1 * x4 - x10 * x27 + x17 * (-U[EKF_U_ACC_X] + X[EKF_X_A_BIAS_X]);
631 out[EKF_X_PHI][EKF_X_PHI] = x28 * x30 - x31 * x32;
632 out[EKF_X_PHI][EKF_X_THETA] = x31 * x33 * x5 + x33 * x34;
633 out[EKF_X_PHI][EKF_X_G_BIAS_P] = -1.f;
638 out[EKF_X_THETA][EKF_X_G_BIAS_R] = x1;
639 out[EKF_X_PSI][EKF_X_PHI] = x28 * x36 - x31 * x37;
640 out[EKF_X_PSI][EKF_X_THETA] = x27 * x31 * x38 + x34 * x38 * x4;
643}
644
645static void ekf_L(const float X[EKF_NUM_STATES], __attribute__((unused)) const float U[EKF_NUM_INPUTS],
646 float out[EKF_NUM_STATES][EKF_NUM_INPUTS])
647{
648 const float x0 = cosf(X[EKF_X_THETA]);
649 const float x1 = cosf(X[EKF_X_PSI]);
650 const float x2 = sinf(X[EKF_X_PSI]);
651 const float x3 = cosf(X[EKF_X_PHI]);
652 const float x4 = x2 * x3;
653 const float x5 = sinf(X[EKF_X_THETA]);
654 const float x6 = sinf(X[EKF_X_PHI]);
655 const float x7 = x1 * x6;
656 const float x8 = x2 * x6;
657 const float x9 = x1 * x3;
658 const float x10 = tanf(X[EKF_X_THETA]);
659 const float x11 = 1.f / x0; // FIXME protect against div by 0
660
661 memset(out, 0, (EKF_NUM_STATES*EKF_NUM_INPUTS) * (sizeof **out));
662 out[EKF_X_VEL_X][EKF_Z_POS_X] = -x0 * x1;
663 out[EKF_X_VEL_X][EKF_Z_POS_Y] = x4 - x5 * x7;
664 out[EKF_X_VEL_X][EKF_Z_POS_Z] = -x5 * x9 - x8;
665 out[EKF_X_VEL_Y][EKF_Z_POS_X] = -x0 * x2;
666 out[EKF_X_VEL_Y][EKF_Z_POS_Y] = -x5 * x8 - x9;
667 out[EKF_X_VEL_Y][EKF_Z_POS_Z] = -x4 * x5 + x7;
668 out[EKF_X_VEL_Z][EKF_Z_POS_X] = x5;
669 out[EKF_X_VEL_Z][EKF_Z_POS_Y] = -x0 * x6;
670 out[EKF_X_VEL_Z][EKF_Z_POS_Z] = -x0 * x3;
671 out[EKF_X_PHI][EKF_Z_PHI] = -1.f;
672 out[EKF_X_PHI][EKF_Z_THETA] = -x10 * x6;
673 out[EKF_X_PHI][EKF_Z_PSI] = -x10 * x3;
674 out[EKF_X_THETA][EKF_Z_THETA] = -x3;
675 out[EKF_X_THETA][EKF_Z_PSI] = x6;
676 out[EKF_X_PSI][EKF_Z_THETA] = -x11 * x6;
677 out[EKF_X_PSI][EKF_Z_PSI] = -x11 * x3;
678}
679
680
681#if INS_EXT_POSE_USE_RK4
682
683static void ekf_f_rk4(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], const float dt,
684 float out[EKF_NUM_STATES])
685{
686 float k1[EKF_NUM_STATES];
687 float k2[EKF_NUM_STATES];
688 float k3[EKF_NUM_STATES];
689 float k4[EKF_NUM_STATES];
690
691 float Xtmp[EKF_NUM_STATES];
692
693 // k1 = f(X,U)
694 ekf_f(X, U, k1);
695
696 // Xtmp = X+dt*k1/2
697 float_vect_smul(Xtmp, k1, dt / 2.f, EKF_NUM_STATES);
699
700 // k2 = f(Xtmp,U)
701 ekf_f(Xtmp, U, k2);
702
703 // Xtmp = X+dt*k2/2
704 float_vect_smul(Xtmp, k2, dt / 2.f, EKF_NUM_STATES);
706
707 // k3 = f(Xtmp,U)
708 ekf_f(Xtmp, U, k3);
709
710 // Xtmp = X+dt*k3
713
714 // k4 = f(Xtmp,U)
715 ekf_f(Xtmp, U, k4);
716
717 // out = k2+k3
718 float_vect_sum(out, k2, k3, EKF_NUM_STATES);
719 // out *= 2
721 // out += k1
723 // out += k4
725 // out *= dt/6
726 float_vect_scale(out, dt / 6.f, EKF_NUM_STATES);
727 // out += X
729}
730
731#endif
732
733static void ekf_prediction_step(const float U[EKF_NUM_INPUTS], const float dt)
734{
737
738#if INS_EXT_POSE_USE_RK4
739 // [1] Predicted (a priori) state estimate:
740 float Xkk_1[EKF_NUM_STATES];
741 ekf_f_rk4(ekf_X, U, dt, Xkk_1);
742
743 // [2] Get matrices
746 ekf_F(ekf_X, U, F);
747 ekf_L(ekf_X, U, L);
748
749
750 // [3] Continuous to discrete
751 // Fd = eye(N) + F*dt + F*F*dt**2/2 = I + [I+F*dt/2]*F*dt
752 // Ld = L*dt+F*L*dt**2/2 = [I+F*dt/2]*L*dt
755
760
761 // tmp = I+F*dt/2
764
765 // Ld = tmp*L*dt
768
769 // Fd = tmp*F*dt
772
773 // Fd += I
774 int i;
775 for (i = 0; i < EKF_NUM_STATES; i++) {
776 Fd[i][i] += 1.f;
777 }
778
779#else
780
781 // [1] Predicted (a priori) state estimate:
782 float Xkk_1[EKF_NUM_STATES];
783 // Xkk_1 = f(X,U)
784 ekf_f(ekf_X, U, Xkk_1);
785 // Xkk_1 *= dt
787 // Xkk_1 += X
789
790
791 // [2] Get matrices
794 ekf_F(ekf_X, U, F);
795 ekf_L(ekf_X, U, Ld);
796
797
798 // [3] Continuous to discrete
799 // Fd = eye(N) + F*dt
800 // Ld = L*dt
802
806
807 // Fd = I+F*dt
810
811 // Ld = Ld*dt
813#endif
814
815 // [4] Predicted covariance estimate:
816 // Pkk_1 = Fd*P*Fd.T + Ld*Q*Ld.T
820
826
827 // Fd = Fd.T
829
830 // tmp = P*Fd
832
833 // Fd = Fd.T
835
836 // Pkk_1 = Fd*tmp
838
839 // LdT = Ld.T
841
842 // QLdT = Q*LdT
844
845 // tmp = Ld*QLdT
847
848 // Pkk_1 += tmp
850
851 // Store state and covariance
852
853 // X = Xkk_1
855
856 // P = Pkk_1
858}
859
860static void ekf_measurement_step(const float Z[EKF_NUM_OUTPUTS])
861{
862 // Xkk_1 = X
863 float Xkk_1[EKF_NUM_STATES];
865
866 // Pkk_1 = P
871
872 // [5] Measurement residual:
873 // yk = Z - H*Xkk_1
874 float yk[EKF_NUM_OUTPUTS];
875
877
881
882
883 // [6] Residual covariance:
884 // Sk = H*Pkk_1*H.T + R
887
891
892 // PHT = Pkk_1*H.T
895
896 // Sk = H*PHT
898
899 // Sk += R
901
902
903 // [7] Near-optimal Kalman gain:
904 // K = Pkk_1*H.T*inv(Sk)
907
910
911 // Sk_inv = inv(Sk)
913
914 // K = PHT*Sk_inv
916
917
918 // [8] Updated state estimate
919 // Xkk = Xkk_1 + K*yk
922
923
924 // [9] Updated covariance estimate:
925 // Pkk = (I - K*H)*Pkk_1
928
929 // tmp = K*H
931
932 // tmp *= -1
934
935 // tmp += I
936 int i;
937 for (i = 0; i < EKF_NUM_STATES; i++) {
938 tmp_[i][i] += 1.f;
939 }
940 // P = tmp*Pkk_1
942}
943
944
946static float ekf_psi_meas(void)
947{
950 return ekf_X[EKF_X_PSI] + dpsi;
951}
952
967
968static void ekf_run(void)
969{
970 // Time
972 float dt = t1 - t0;
973 t0 = t1;
974
975 // Only Start If External Pose is Available
976 if (!ins_ext_pose.started) {
977 // ekf starts at the first ev update
979 ins_ext_pose.started = true;
980
981 // initial guess
983 }
984 }
985
986 // set input values
992 } else {
993 DEBUG_PRINT("ekf missing acc\n");
994 }
1000 } else {
1001 DEBUG_PRINT("ekf missing gyro\n");
1002 }
1003
1004 if (ins_ext_pose.started) {
1005
1006 // prediction step
1008
1009 DEBUG_PRINT("ekf prediction step U = %f, %f, %f, %f, %f, %f dt = %f \n",
1010 ekf_U[0], ekf_U[1], ekf_U[2], ekf_U[3], ekf_U[4], ekf_U[5], dt);
1011
1012 // measurement step
1015
1016 // heading measurement unwrapped around the predicted heading
1017 float psi_meas = ekf_psi_meas();
1018
1019 // innovation gates: a large attitude innovation (e.g. a delayed pose during fast
1020 // rotation) also corrupts the other states through the cross-covariances
1021 float dphi = ins_ext_pose.ev_att.phi - ekf_X[EKF_X_PHI];
1022 float dtheta = ins_ext_pose.ev_att.theta - ekf_X[EKF_X_THETA];
1024 FLOAT_ANGLE_NORMALIZE(dtheta);
1027
1028 if (gated) {
1031 // estimate considered diverged if consistently rejected
1037 }
1038 } else {
1041
1045 ekf_Z[EKF_Z_PHI] = ekf_X[EKF_X_PHI] + dphi;
1048
1050
1051 DEBUG_PRINT("ekf measurement step Z = %f, %f, %f, %f \n",
1052 ekf_Z[0], ekf_Z[1], ekf_Z[2], ekf_Z[3]);
1053 }
1054 }
1055 }
1056
1057 // Keep the heading state in [-pi, pi] (it only enters the model through sin/cos):
1058 // an ever growing float heading loses resolution after many turns
1060
1061 // Export Results
1062 struct NedCoor_f ned_pos;
1067
1068 struct NedCoor_f ned_speed;
1073
1078
1079 struct FloatRates rates;
1083
1084 struct FloatVect3 body_accel;
1085 body_accel.x = ekf_U[EKF_U_ACC_X] - ekf_X[EKF_X_A_BIAS_X];
1086 body_accel.y = ekf_U[EKF_U_ACC_Y] - ekf_X[EKF_X_A_BIAS_Y];
1087 body_accel.z = ekf_U[EKF_U_ACC_Z] - ekf_X[EKF_X_A_BIAS_Z];
1088 struct Int32Vect3 body_accel_i;
1089 ACCELS_BFP_OF_REAL(body_accel_i, body_accel);
1090
1091 struct FloatVect3 ned_accel_v;
1095 ned_accel_v.z += 9.81f;
1097 struct NedCoor_f ned_accel;
1099
1106
1107}
1108
1109
1110
1116{
1117 fprintf(file,
1118 "ekf_X1,ekf_X2,ekf_X3,ekf_X4,ekf_X5,ekf_X6,ekf_X7,ekf_X8,ekf_X9,ekf_X10,ekf_X11,ekf_X12,ekf_X13,ekf_X14,ekf_X15,");
1119 fprintf(file, "ekf_U1,ekf_U2,ekf_U3,ekf_U4,ekf_U5,ekf_U6,");
1120 fprintf(file, "ekf_Z1,ekf_Z2,ekf_Z3,ekf_Z4,");
1121}
1122
1124{
1125 fprintf(file, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,",
1126 ekf_X[0], ekf_X[1], ekf_X[2], ekf_X[3], ekf_X[4],
1127 ekf_X[5], ekf_X[6], ekf_X[7], ekf_X[8], ekf_X[9],
1128 ekf_X[10], ekf_X[11], ekf_X[12], ekf_X[13], ekf_X[14]);
1129 fprintf(file, "%f,%f,%f,%f,%f,%f,",
1130 ekf_U[0], ekf_U[1], ekf_U[2], ekf_U[3], ekf_U[4], ekf_U[5]);
1131 fprintf(file, "%f,%f,%f,%f,", ekf_Z[0], ekf_Z[1], ekf_Z[2], ekf_Z[3]);
1132}
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition abi_common.h:68
#define AHRS_COMP_ID_GENERIC
Definition ahrs.h:36
#define delay(ms)
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
uint32_t get_sys_time_msec(void)
Get the time in milliseconds since startup.
static struct uart_periph * dev
#define Min(x, y)
Definition esc_dshot.c:110
float q
in rad/s
float phi
in radians
float p
in rad/s
float r
in rad/s
float theta
in radians
float psi
in radians
static void float_vect_add(float *a, const float *b, const int n)
a += b
#define FLOAT_ANGLE_NORMALIZE(_a)
static void float_vect_sum(float *o, const float *a, const float *b, const int n)
o = a + b
static void float_vect_smul(float *o, const float *a, const float s, const int n)
o = a * s
void float_mat_invert(float **o, float **mat, const int n)
Calculate inverse of any n x n matrix (passed as C array) o = mat^-1 Algorithm verified with Matlab.
static void float_mat_transpose(float **o, float **a, const int n, const int m)
transpose non-square matrix
#define float_rmat_of_eulers
static void float_mat_scale(float **a, float k, const int m, const int n)
a *= k, where k is a scalar value
static void float_vect_scale(float *a, const float s, const int n)
a *= s
static void float_mat_mul(float **o, float **a, float **b, const int m, const int n, const int l)
o = a * b
static void float_mat_transpose_square(float **a, const int n)
transpose square matrix
static void float_mat_copy(float **a, float **b, const int m, const int n)
a = b
static void float_mat_diagonal_scal(float **o, float v, const int n)
Make an n x n identity matrix (for matrix passed as array)
void float_quat_comp(struct FloatQuat *a2c, const struct FloatQuat *a2b, const struct FloatQuat *b2c)
Composition (multiplication) of two quaternions.
static void float_mat_vect_mul(float *o, float **a, const float *b, const int m, const int n)
o = a * b
static void float_vect_copy(float *a, const float *b, const int n)
a = b
static void float_mat_sum_scaled(float **a, float **b, const float k, const int m, const int n)
a += k*b, where k is a scalar value
void float_eulers_of_quat(struct FloatEulers *e, const struct FloatQuat *q)
euler rotation 'ZYX'
#define MAKE_MATRIX_PTR(_ptr, _mat, _rows)
Make a pointer to a matrix of _rows lines.
void float_rmat_transp_vmult(struct FloatVect3 *vb, const struct FloatRMat *m_b2a, const struct FloatVect3 *va)
rotate 3D vector by transposed rotation matrix.
static void float_mat_mul_copy(float **o, float **a, float **b, const int m, const int n, const int l)
o = a * b
euler angles
Roation quaternion.
rotation matrix
angular rates
#define POSITIONS_BFP_OF_REAL(_ef, _ei)
#define EULERS_COPY(_a, _b)
#define QUAT_COPY(_qo, _qi)
#define SPEEDS_BFP_OF_REAL(_ef, _ei)
#define VECT3_COPY(_a, _b)
#define ACCELS_BFP_OF_REAL(_ef, _ei)
#define RATES_FLOAT_OF_BFP(_rf, _ri)
#define ACCELS_FLOAT_OF_BFP(_ef, _ei)
angular rates
#define ENU_OF_TO_NED(_po, _pi)
int32_t lat
in degrees*1e7
int32_t hmsl
Height above mean sea level in mm.
int32_t alt
in millimeters above WGS84 reference ellipsoid
int32_t z
Down.
int32_t z
in centimeters
struct LlaCoor_i lla
Reference point in lla.
int32_t x
in centimeters
int32_t y
East.
struct EcefCoor_i ecef
Reference point in ecef.
int32_t y
in centimeters
int32_t lon
in degrees*1e7
int32_t x
North.
void ecef_of_lla_i(struct EcefCoor_i *out, struct LlaCoor_i *in)
Convert a LLA to ECEF.
void ltp_def_from_ecef_i(struct LtpDef_i *def, struct EcefCoor_i *ecef)
vector in EarthCenteredEarthFixed coordinates
vector in Latitude, Longitude and Altitude
definition of the local (flat earth) coordinate system
vector in North East Down coordinates
static void stateSetAccelNed_f(uint16_t id, struct NedCoor_f *ned_accel)
Set acceleration in NED coordinates (float).
Definition state.h:1155
static void stateSetAccelBody_i(uint16_t id, struct Int32Vect3 *body_accel)
Set acceleration in Body coordinates (int).
Definition state.h:1175
static void stateSetNedToBodyEulers_f(uint16_t id, struct FloatEulers *ned_to_body_eulers)
Set vehicle body attitude from euler angles (float).
Definition state.h:1275
static void stateSetPositionNed_f(uint16_t id, struct NedCoor_f *ned_pos)
Set position from local NED coordinates (float).
Definition state.h:718
static void stateSetLocalOrigin_i(uint16_t id, struct LtpDef_i *ltp_def)
Set the local (flat earth) coordinate frame origin (int).
Definition state.h:519
static void stateSetBodyRates_f(uint16_t id, struct FloatRates *body_rate)
Set vehicle body angular rate (float).
Definition state.h:1360
static void stateSetSpeedNed_f(uint16_t id, struct NedCoor_f *ned_speed)
Set ground speed in local NED coordinates (float).
Definition state.h:947
Inertial Measurement Unit interface.
Integrated Navigation System interface.
static void ekf_L(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], float out[EKF_NUM_STATES][EKF_NUM_INPUTS])
struct FloatRates gyros_f
struct FloatEulers ev_att
static void ekf_reset_on_pose(void)
Set position and attitude to the external pose and restore the initial covariance.
#define INS_EXT_POSE_GATE_PSI
Innovation gates [rad], 0 to disable.
float ins_ext_pose_gate_tilt
#define INS_EXT_POSE_TIMEOUT
Time without fused pose after which the filter status is reported as lost [s].
struct FloatVect3 ev_vel
static void send_ins(struct transport_tx *trans, struct link_device *dev)
Provide telemetry.
void ins_ext_pose_msg_update(uint8_t *buf)
static void ekf_F(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], float out[EKF_NUM_STATES][EKF_NUM_STATES])
struct InsExtPose ins_ext_pose
static float ekf_P[EKF_NUM_STATES][EKF_NUM_STATES]
static float ekf_R[EKF_NUM_OUTPUTS][EKF_NUM_OUTPUTS]
#define INS_EXT_POSE_R_NOISE
struct LtpDef_i ltp_def
float ins_ext_pose_max_age
#define INS_EXT_POSE_P0
static abi_event accel_ev
static void gyro_cb(uint8_t sender_id, uint32_t stamp, struct Int32Rates *gyro)
void ins_ext_pose_log_data(FILE *file)
struct FloatQuat ev_quat
struct NedCoor_i ltp_pos
static void ekf_init(void)
EKF protos.
struct FloatVect3 accels_f
static void ins_ext_pose_init_from_flightplan(void)
bool has_new_gyro
static float ekf_U[EKF_NUM_INPUTS]
static float t0
uint16_t nb_gated
poses dropped by the innovation gates
void ins_ext_pose_init(void)
Module.
struct NedCoor_i ltp_speed
static void ekf_measurement_step(const float Z[EKF_NUM_OUTPUTS])
static abi_event gyro_ev
float delay_min
lowest recent receive delay, relative to delay_ref [ms]
static void send_ins_ref(struct transport_tx *trans, struct link_device *dev)
bool has_new_ext_pose
struct FloatVect3 ev_pos
struct NedCoor_i ltp_accel
static void send_ins_z(struct transport_tx *trans, struct link_device *dev)
static float ekf_Q[EKF_NUM_INPUTS][EKF_NUM_INPUTS]
uint32_t age_ok_time
receive time of the last pose with a valid age [ms]
#define INS_EXT_POSE_GATE_TILT
#define INS_EXT_POSE_AGE_DRIFT
Rate at which the lowest delay may rise [ms per received pose], to follow clock drift.
#define INS_EXT_POSE_Q_NOISE
void ins_ext_pose_log_header(FILE *file)
Logging.
static void send_filter_status(struct transport_tx *trans, struct link_device *dev)
#define INS_EXT_POSE_GATE_RESET_NB
Number of consecutive gated poses after which the filter is reset on the pose.
#define DEBUG_PRINT(...)
#define INS_EXT_POSE_MAX_AGE
Maximum age of an external pose [ms], 0 to disable the check.
#define INS_EXT_POSE_AGE_RESET_TIME
Time with all poses too old after which the lowest delay is reset [ms].
void ins_ext_pose_run(void)
float ev_age
age of the last pose [ms]
#define INS_EXT_POSE_IMU_ID
Import Gyro and Acc from ABI.
uint16_t nb_reset
filter resets after repeated gating
static void accel_cb(uint8_t sender_id, uint32_t stamp, struct Int32Vect3 *accel)
static float t1
#define INS_EXT_POSE_AGE_RESYNC
Delay jump above which the sender clock is considered restarted [ms].
bool ts_valid
capture time reference initialized
static bool ins_ext_pose_check_age(uint32_t ts)
Import External Pose Message.
uint16_t nb_stale
poses dropped for age or order
static float ekf_psi_meas(void)
Heading measurement close to the (unwrapped) heading state.
float ins_ext_pose_gate_psi
static void ekf_set_diag(float **a, float *b, int n)
uint8_t gate_cnt
consecutive gated poses
static float ekf_Z[EKF_NUM_OUTPUTS]
static void ekf_prediction_step(const float U[EKF_NUM_INPUTS], const float dt)
static void send_external_pose_down(struct transport_tx *trans, struct link_device *dev)
uint32_t ts_last
last accepted capture time [ms]
static void ekf_f(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], float out[EKF_NUM_STATES])
static void ekf_run(void)
float ekf_X[EKF_NUM_STATES]
uint32_t delay_ref
receive delay reference (includes clock offset) [ms]
static float ekf_H[EKF_NUM_OUTPUTS][EKF_NUM_STATES]
float last_fused
time of the last fused pose [s]
static void send_ahrs_bias(struct transport_tx *trans, struct link_device *dev)
Data for telemetry and LTP origin.
Integrated Navigation System interface.
@ EKF_X_VEL_Z
@ EKF_X_VEL_X
@ EKF_X_VEL_Y
@ EKF_X_A_BIAS_Z
@ EKF_X_PSI
@ EKF_X_A_BIAS_X
@ EKF_X_G_BIAS_R
@ EKF_X_G_BIAS_Q
@ EKF_X_G_BIAS_P
@ EKF_NUM_STATES
@ EKF_X_THETA
@ EKF_X_POS_Y
@ EKF_X_POS_X
@ EKF_X_A_BIAS_Y
@ EKF_X_POS_Z
@ EKF_X_PHI
@ EKF_U_ACC_Z
@ EKF_NUM_INPUTS
@ EKF_U_GYRO_R
@ EKF_U_ACC_Y
@ EKF_U_GYRO_P
@ EKF_U_ACC_X
@ EKF_U_GYRO_Q
@ EKF_Z_POS_Z
@ EKF_Z_PHI
@ EKF_Z_POS_X
@ EKF_Z_PSI
@ EKF_NUM_OUTPUTS
@ EKF_Z_THETA
@ EKF_Z_POS_Y
uint16_t foo
Definition main_demo5.c:58
void waypoints_localize_all(void)
update local ENU coordinates of global waypoints
Definition waypoints.c:376
PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF)
Paparazzi generic algebra macros.
Paparazzi floating point algebra.
float x
in meters
float x
in meters
vector in East North Up coordinates Units: meters
vector in North East Down coordinates Units: meters
API to get/set the generic vehicle states.
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition sys_time.h:174
int16_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint16_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition telemetry.c:51
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition telemetry.h:66
static float K[9]
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
int int32_t
Typedef defining 32 bit int type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
float b
Definition wedgebug.c:202