Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
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"
33 #include "modules/imu/imu.h"
34 #include "modules/ins/ins.h"
35 #include "generated/flight_plan.h"
36 #include "modules/core/abi.h"
37 
38 #if 0
39 #include <stdio.h>
40 #define DEBUG_PRINT(...) printf(__VA_ARGS__)
41 #else
42 #define DEBUG_PRINT(...) {}
43 #endif
44 
45 #ifdef INS_EXT_VISION_ROTATION
46 struct FloatQuat ins_ext_vision_rot;
47 #endif
48 
51 struct InsExtPose {
52  /* Inputs */
53  struct FloatRates gyros_f;
54  struct FloatVect3 accels_f;
57 
58  struct FloatVect3 ev_pos;
59  struct FloatVect3 ev_vel;
60  struct FloatEulers ev_att;
61  struct FloatQuat ev_quat;
63  float ev_time;
64 
65  /* Origin */
66  struct LtpDef_i ltp_def;
67 
68  /* output LTP NED */
69  struct NedCoor_i ltp_pos;
70  struct NedCoor_i ltp_speed;
71  struct NedCoor_i ltp_accel;
72 };
73 struct InsExtPose ins_ext_pos;
74 
75 
77 {
78 
79  struct LlaCoor_i llh_nav0; /* Height above the ellipsoid */
80  llh_nav0.lat = NAV_LAT0;
81  llh_nav0.lon = NAV_LON0;
82  /* NAV_ALT0 = ground alt above msl, NAV_MSL0 = geoid-height (msl) over ellipsoid */
83  llh_nav0.alt = NAV_ALT0 + NAV_MSL0;
84 
85  struct EcefCoor_i ecef_nav0;
86  ecef_of_lla_i(&ecef_nav0, &llh_nav0);
87 
89  ins_ext_pos.ltp_def.hmsl = NAV_ALT0;
91  /* update local ENU coordinates of global waypoints */
93 }
94 
95 
99 #if PERIODIC_TELEMETRY
101 
102 static void send_ins(struct transport_tx *trans, struct link_device *dev)
103 {
104  pprz_msg_send_INS(trans, dev, AC_ID,
108 }
109 
110 static void send_ins_z(struct transport_tx *trans, struct link_device *dev)
111 {
112  static float fake_baro_z = 0.0;
113  pprz_msg_send_INS_Z(trans, dev, AC_ID,
114  (float *)&fake_baro_z, &ins_ext_pos.ltp_pos.z,
116 }
117 
118 static void send_ins_ref(struct transport_tx *trans, struct link_device *dev)
119 {
120  static float fake_qfe = 0.0;
121  pprz_msg_send_INS_REF(trans, dev, AC_ID,
124  &ins_ext_pos.ltp_def.hmsl, (float *)&fake_qfe);
125 }
126 
127 static void send_external_pose_down(struct transport_tx *trans, struct link_device *dev)
128 {
129  pprz_msg_send_EXTERNAL_POSE_DOWN(trans, dev, AC_ID,
131  &ins_ext_pos.ev_pos.x,
132  &ins_ext_pos.ev_pos.y,
134  &ins_ext_pos.ev_vel.x,
135  &ins_ext_pos.ev_vel.y,
136  &ins_ext_pos.ev_vel.z,
141 }
142 static void send_ahrs_bias(struct transport_tx *trans, struct link_device *dev)
143 {
144  float dummy0 = 0.0;
145  pprz_msg_send_AHRS_BIAS(trans, dev, AC_ID,
146  &ekf_X[9],
147  &ekf_X[10],
148  &ekf_X[11],
149  &ekf_X[12],
150  &ekf_X[13],
151  &ekf_X[14],
152  &dummy0,
153  &dummy0,
154  &dummy0);
155 }
156 #endif
157 
158 
163 #ifndef INS_EXT_POSE_IMU_ID
164 #define INS_EXT_POSE_IMU_ID ABI_BROADCAST
165 #endif
166 PRINT_CONFIG_VAR(INS_EXT_POSE_IMU_ID)
167 
170 
171 static void accel_cb(uint8_t sender_id, uint32_t stamp, struct Int32Vect3 *accel);
172 static void gyro_cb(uint8_t sender_id, uint32_t stamp, struct Int32Rates *gyro);
173 
174 
175 
176 static void gyro_cb(uint8_t sender_id __attribute__((unused)),
177  uint32_t stamp __attribute__((unused)),
178  struct Int32Rates *gyro)
179 {
181  ins_ext_pos.has_new_gyro = true;
182 }
183 
184 static void accel_cb(uint8_t sender_id __attribute__((unused)),
185  uint32_t stamp __attribute__((unused)),
186  struct Int32Vect3 *accel)
187 {
189  ins_ext_pos.has_new_acc = true;
190 }
191 
192 
198 {
199  if (DL_EXTERNAL_POSE_ac_id(buf) != AC_ID) { return; } // not for this aircraft
200 
201  float enu_x = DL_EXTERNAL_POSE_enu_x(buf);
202  float enu_y = DL_EXTERNAL_POSE_enu_y(buf);
203  float enu_z = DL_EXTERNAL_POSE_enu_z(buf);
204  float enu_xd = DL_EXTERNAL_POSE_enu_xd(buf);
205  float enu_yd = DL_EXTERNAL_POSE_enu_yd(buf);
206  float enu_zd = DL_EXTERNAL_POSE_enu_zd(buf);
207  float quat_i = DL_EXTERNAL_POSE_body_qi(buf);
208  float quat_x = DL_EXTERNAL_POSE_body_qx(buf);
209  float quat_y = DL_EXTERNAL_POSE_body_qy(buf);
210  float quat_z = DL_EXTERNAL_POSE_body_qz(buf);
211 
212  DEBUG_PRINT("EXT_UPDATE\n");
213 
214  struct FloatQuat orient;
215  struct FloatEulers orient_eulers;
216 
217  // Transformation of External Pose. Optitrack motive 2.X Yup
218  orient.qi = quat_i ;
219  orient.qx = quat_y ;
220  orient.qy = quat_x ;
221  orient.qz = -quat_z;
222 
223 #ifdef INS_EXT_VISION_ROTATION
224  // Rotate the quaternion
225  struct FloatQuat rot_q;
226  float_quat_comp(&rot_q, &orient, &ins_ext_vision_rot);
227  orient.qi = rot_q.qi;
228  orient.qx = rot_q.qx;
229  orient.qy = rot_q.qy;
230  orient.qz = rot_q.qz;
231 #endif
232 
233  float_eulers_of_quat(&orient_eulers, &orient);
234 
236  ins_ext_pos.ev_pos.x = enu_y;
237  ins_ext_pos.ev_pos.y = enu_x;
238  ins_ext_pos.ev_pos.z = -enu_z;
239  ins_ext_pos.ev_vel.x = enu_yd;
240  ins_ext_pos.ev_vel.y = enu_xd;
241  ins_ext_pos.ev_vel.z = -enu_zd;
242  ins_ext_pos.ev_att.phi = orient_eulers.phi;
243  ins_ext_pos.ev_att.theta = orient_eulers.theta;
244  ins_ext_pos.ev_att.psi = orient_eulers.psi;
245  ins_ext_pos.ev_quat.qi = orient.qi;
246  ins_ext_pos.ev_quat.qx = orient.qx;
247  ins_ext_pos.ev_quat.qy = orient.qy;
248  ins_ext_pos.ev_quat.qz = orient.qz;
249 
251 
253 }
254 
256 {
257  // Ext pos does not allow geoinit: FP origin only
258 }
259 
261 {
262  // Ext pos does not allow geoinit: FP origin only
263 }
264 
265 
269 static inline void ekf_init(void);
270 static inline void ekf_run(void);
271 
277 {
278 
279  // Initialize inputs
280  ins_ext_pos.has_new_acc = false;
281  ins_ext_pos.has_new_gyro = false;
283 
284  // Get External Pose Origin From Flightplan
286 
287  // Provide telemetry
288 #if PERIODIC_TELEMETRY
292  register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_EXTERNAL_POSE_DOWN, send_external_pose_down);
294 #endif
295 
296  // Get IMU through ABI
297  AbiBindMsgIMU_ACCEL(INS_EXT_POSE_IMU_ID, &accel_ev, accel_cb);
298  AbiBindMsgIMU_GYRO(INS_EXT_POSE_IMU_ID, &gyro_ev, gyro_cb);
299  // Get External Pose through datalink message: setup in xml
300 
301  // Initialize EKF
302  ekf_init();
303 }
304 
306 {
307  ekf_run();
308 }
309 
310 
311 
312 
313 /***************************************************
314  * Kalman Filter.
315  */
316 
317 
318 
319 static inline void ekf_f(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], float out[EKF_NUM_STATES]);
320 static inline void ekf_F(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS],
321  float out[EKF_NUM_STATES][EKF_NUM_STATES]);
322 static inline void ekf_L(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS],
323  float out[EKF_NUM_STATES][EKF_NUM_INPUTS]);
324 
325 static inline void ekf_f_rk4(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], const float dt,
326  float out[EKF_NUM_STATES]);
327 
328 static inline void ekf_step(const float U[EKF_NUM_INPUTS], const float Z[EKF_NUM_OUTPUTS], const float dt);
329 static inline void ekf_prediction_step(const float U[EKF_NUM_INPUTS], const float dt);
330 static inline void ekf_measurement_step(const float Z[EKF_NUM_OUTPUTS]);
331 
332 
333 
340 
341 float ekf_H[EKF_NUM_OUTPUTS][EKF_NUM_STATES] = {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}};
342 
343 
344 float t0;
345 float t1;
346 
347 void ekf_set_diag(float **a, float *b, int n);
348 void ekf_set_diag(float **a, float *b, int n)
349 {
350  int i, j;
351  for (i = 0 ; i < n; i++) {
352  for (j = 0 ; j < n; j++) {
353  if (i == j) {
354  a[i][j] = b[i];
355  } else {
356  a[i][j] = 0.0;
357  }
358  }
359  }
360 }
361 
362 
363 
364 static inline void ekf_init(void)
365 {
366 
367  DEBUG_PRINT("ekf init");
368  float X0[EKF_NUM_STATES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
369  float U0[EKF_NUM_INPUTS] = {0, 0, 0, 0, 0, 0};
370  float Z0[EKF_NUM_OUTPUTS] = {0, 0, 0, 0, 0, 0};
371 
372  float Pdiag[EKF_NUM_STATES] = {1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.};
373  float Qdiag[EKF_NUM_INPUTS] = {1.0, 1.0, 1.0, 0.0173, 4.878e-4, 3.547e-4};//{0.0325, 0.4494, 0.5087, 0.0173, 4.878e-4, 3.547e-4};
374 
375  float Rdiag[EKF_NUM_OUTPUTS] = {8.372e-6, 3.832e-6, 4.761e-6, 2.830e-4, 8.684e-6, 7.013e-6};
376 
380 
381  ekf_set_diag(ekf_P_, Pdiag, EKF_NUM_STATES);
382  ekf_set_diag(ekf_Q_, Qdiag, EKF_NUM_INPUTS);
383  ekf_set_diag(ekf_R_, Rdiag, EKF_NUM_OUTPUTS);
387 }
388 
389 static inline void ekf_f(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], float out[EKF_NUM_STATES])
390 {
391  float x0 = cos(X[8]);
392  float x1 = U[0] - X[9];
393  float x2 = cos(X[7]);
394  float x3 = x1 * x2;
395  float x4 = U[2] - X[11];
396  float x5 = sin(X[6]);
397  float x6 = sin(X[8]);
398  float x7 = x5 * x6;
399  float x8 = sin(X[7]);
400  float x9 = cos(X[6]);
401  float x10 = x0 * x9;
402  float x11 = U[1] - X[10];
403  float x12 = x6 * x9;
404  float x13 = x0 * x5;
405  float x14 = tan(X[7]);
406  float x15 = U[4] - X[13];
407  float x16 = x15 * x5;
408  float x17 = U[5] - X[14];
409  float x18 = x17 * x9;
410  float x19 = 1.0 / x2;
411  out[0] = X[3];
412  out[1] = X[4];
413  out[2] = X[5];
414  out[3] = x0 * x3 + x11 * (-x12 + x13 * x8) + x4 * (x10 * x8 + x7);
415  out[4] = x11 * (x10 + x7 * x8) + x3 * x6 + x4 * (x12 * x8 - x13);
416  out[5] = -x1 * x8 + x11 * x2 * x5 + x2 * x4 * x9 + 9.8100000000000005;
417  out[6] = U[3] - X[12] + x14 * x16 + x14 * x18;
418  out[7] = x15 * x9 - x17 * x5;
419  out[8] = x16 * x19 + x18 * x19;
420  out[9] = 0;
421  out[10] = 0;
422  out[11] = 0;
423  out[12] = 0;
424  out[13] = 0;
425  out[14] = 0;
426 }
427 
428 static inline void ekf_F(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS],
429  float out[EKF_NUM_STATES][EKF_NUM_STATES])
430 {
431  float x0 = U[1] - X[10];
432  float x1 = sin(X[6]);
433  float x2 = sin(X[8]);
434  float x3 = x1 * x2;
435  float x4 = sin(X[7]);
436  float x5 = cos(X[6]);
437  float x6 = cos(X[8]);
438  float x7 = x5 * x6;
439  float x8 = x4 * x7;
440  float x9 = x3 + x8;
441  float x10 = U[2] - X[11];
442  float x11 = x2 * x5;
443  float x12 = x1 * x6;
444  float x13 = x12 * x4;
445  float x14 = x11 - x13;
446  float x15 = U[0] - X[9];
447  float x16 = x15 * x4;
448  float x17 = cos(X[7]);
449  float x18 = x0 * x17;
450  float x19 = x10 * x17;
451  float x20 = x17 * x2;
452  float x21 = x11 * x4;
453  float x22 = x12 - x21;
454  float x23 = -x3 * x4 - x7;
455  float x24 = x17 * x6;
456  float x25 = x17 * x5;
457  float x26 = x1 * x17;
458  float x27 = x4 * x5;
459  float x28 = U[4] - X[13];
460  float x29 = tan(X[7]);
461  float x30 = x29 * x5;
462  float x31 = U[5] - X[14];
463  float x32 = x1 * x29;
464  float x33 = pow(x29, 2) + 1;
465  float x34 = x1 * x28;
466  float x35 = 1.0 / x17;
467  float x36 = x35 * x5;
468  float x37 = x1 * x35;
469  float x38 = pow(x17, -2);
470  out[0][0] = 0;
471  out[0][1] = 0;
472  out[0][2] = 0;
473  out[0][3] = 1;
474  out[0][4] = 0;
475  out[0][5] = 0;
476  out[0][6] = 0;
477  out[0][7] = 0;
478  out[0][8] = 0;
479  out[0][9] = 0;
480  out[0][10] = 0;
481  out[0][11] = 0;
482  out[0][12] = 0;
483  out[0][13] = 0;
484  out[0][14] = 0;
485  out[1][0] = 0;
486  out[1][1] = 0;
487  out[1][2] = 0;
488  out[1][3] = 0;
489  out[1][4] = 1;
490  out[1][5] = 0;
491  out[1][6] = 0;
492  out[1][7] = 0;
493  out[1][8] = 0;
494  out[1][9] = 0;
495  out[1][10] = 0;
496  out[1][11] = 0;
497  out[1][12] = 0;
498  out[1][13] = 0;
499  out[1][14] = 0;
500  out[2][0] = 0;
501  out[2][1] = 0;
502  out[2][2] = 0;
503  out[2][3] = 0;
504  out[2][4] = 0;
505  out[2][5] = 1;
506  out[2][6] = 0;
507  out[2][7] = 0;
508  out[2][8] = 0;
509  out[2][9] = 0;
510  out[2][10] = 0;
511  out[2][11] = 0;
512  out[2][12] = 0;
513  out[2][13] = 0;
514  out[2][14] = 0;
515  out[3][0] = 0;
516  out[3][1] = 0;
517  out[3][2] = 0;
518  out[3][3] = 0;
519  out[3][4] = 0;
520  out[3][5] = 0;
521  out[3][6] = x0 * x9 + x10 * x14;
522  out[3][7] = x12 * x18 - x16 * x6 + x19 * x7;
523  out[3][8] = x0 * x23 + x10 * x22 - x15 * x20;
524  out[3][9] = -x24;
525  out[3][10] = x14;
526  out[3][11] = -x3 - x8;
527  out[3][12] = 0;
528  out[3][13] = 0;
529  out[3][14] = 0;
530  out[4][0] = 0;
531  out[4][1] = 0;
532  out[4][2] = 0;
533  out[4][3] = 0;
534  out[4][4] = 0;
535  out[4][5] = 0;
536  out[4][6] = x0 * (-x12 + x21) + x10 * x23;
537  out[4][7] = x11 * x19 - x16 * x2 + x18 * x3;
538  out[4][8] = x0 * (-x11 + x13) + x10 * x9 + x15 * x24;
539  out[4][9] = -x20;
540  out[4][10] = x23;
541  out[4][11] = x22;
542  out[4][12] = 0;
543  out[4][13] = 0;
544  out[4][14] = 0;
545  out[5][0] = 0;
546  out[5][1] = 0;
547  out[5][2] = 0;
548  out[5][3] = 0;
549  out[5][4] = 0;
550  out[5][5] = 0;
551  out[5][6] = x0 * x25 - x10 * x26;
552  out[5][7] = -x0 * x1 * x4 - x10 * x27 + x17 * (-U[0] + X[9]);
553  out[5][8] = 0;
554  out[5][9] = x4;
555  out[5][10] = -x26;
556  out[5][11] = -x25;
557  out[5][12] = 0;
558  out[5][13] = 0;
559  out[5][14] = 0;
560  out[6][0] = 0;
561  out[6][1] = 0;
562  out[6][2] = 0;
563  out[6][3] = 0;
564  out[6][4] = 0;
565  out[6][5] = 0;
566  out[6][6] = x28 * x30 - x31 * x32;
567  out[6][7] = x31 * x33 * x5 + x33 * x34;
568  out[6][8] = 0;
569  out[6][9] = 0;
570  out[6][10] = 0;
571  out[6][11] = 0;
572  out[6][12] = -1;
573  out[6][13] = -x32;
574  out[6][14] = -x30;
575  out[7][0] = 0;
576  out[7][1] = 0;
577  out[7][2] = 0;
578  out[7][3] = 0;
579  out[7][4] = 0;
580  out[7][5] = 0;
581  out[7][6] = -x34 + x5 * (-U[5] + X[14]);
582  out[7][7] = 0;
583  out[7][8] = 0;
584  out[7][9] = 0;
585  out[7][10] = 0;
586  out[7][11] = 0;
587  out[7][12] = 0;
588  out[7][13] = -x5;
589  out[7][14] = x1;
590  out[8][0] = 0;
591  out[8][1] = 0;
592  out[8][2] = 0;
593  out[8][3] = 0;
594  out[8][4] = 0;
595  out[8][5] = 0;
596  out[8][6] = x28 * x36 - x31 * x37;
597  out[8][7] = x27 * x31 * x38 + x34 * x38 * x4;
598  out[8][8] = 0;
599  out[8][9] = 0;
600  out[8][10] = 0;
601  out[8][11] = 0;
602  out[8][12] = 0;
603  out[8][13] = -x37;
604  out[8][14] = -x36;
605  out[9][0] = 0;
606  out[9][1] = 0;
607  out[9][2] = 0;
608  out[9][3] = 0;
609  out[9][4] = 0;
610  out[9][5] = 0;
611  out[9][6] = 0;
612  out[9][7] = 0;
613  out[9][8] = 0;
614  out[9][9] = 0;
615  out[9][10] = 0;
616  out[9][11] = 0;
617  out[9][12] = 0;
618  out[9][13] = 0;
619  out[9][14] = 0;
620  out[10][0] = 0;
621  out[10][1] = 0;
622  out[10][2] = 0;
623  out[10][3] = 0;
624  out[10][4] = 0;
625  out[10][5] = 0;
626  out[10][6] = 0;
627  out[10][7] = 0;
628  out[10][8] = 0;
629  out[10][9] = 0;
630  out[10][10] = 0;
631  out[10][11] = 0;
632  out[10][12] = 0;
633  out[10][13] = 0;
634  out[10][14] = 0;
635  out[11][0] = 0;
636  out[11][1] = 0;
637  out[11][2] = 0;
638  out[11][3] = 0;
639  out[11][4] = 0;
640  out[11][5] = 0;
641  out[11][6] = 0;
642  out[11][7] = 0;
643  out[11][8] = 0;
644  out[11][9] = 0;
645  out[11][10] = 0;
646  out[11][11] = 0;
647  out[11][12] = 0;
648  out[11][13] = 0;
649  out[11][14] = 0;
650  out[12][0] = 0;
651  out[12][1] = 0;
652  out[12][2] = 0;
653  out[12][3] = 0;
654  out[12][4] = 0;
655  out[12][5] = 0;
656  out[12][6] = 0;
657  out[12][7] = 0;
658  out[12][8] = 0;
659  out[12][9] = 0;
660  out[12][10] = 0;
661  out[12][11] = 0;
662  out[12][12] = 0;
663  out[12][13] = 0;
664  out[12][14] = 0;
665  out[13][0] = 0;
666  out[13][1] = 0;
667  out[13][2] = 0;
668  out[13][3] = 0;
669  out[13][4] = 0;
670  out[13][5] = 0;
671  out[13][6] = 0;
672  out[13][7] = 0;
673  out[13][8] = 0;
674  out[13][9] = 0;
675  out[13][10] = 0;
676  out[13][11] = 0;
677  out[13][12] = 0;
678  out[13][13] = 0;
679  out[13][14] = 0;
680  out[14][0] = 0;
681  out[14][1] = 0;
682  out[14][2] = 0;
683  out[14][3] = 0;
684  out[14][4] = 0;
685  out[14][5] = 0;
686  out[14][6] = 0;
687  out[14][7] = 0;
688  out[14][8] = 0;
689  out[14][9] = 0;
690  out[14][10] = 0;
691  out[14][11] = 0;
692  out[14][12] = 0;
693  out[14][13] = 0;
694  out[14][14] = 0;
695 }
696 
697 static inline void ekf_L(const float X[EKF_NUM_STATES], __attribute__((unused)) const float U[EKF_NUM_INPUTS],
698  float out[EKF_NUM_STATES][EKF_NUM_INPUTS])
699 {
700  float x0 = cos(X[7]);
701  float x1 = cos(X[8]);
702  float x2 = sin(X[8]);
703  float x3 = cos(X[6]);
704  float x4 = x2 * x3;
705  float x5 = sin(X[7]);
706  float x6 = sin(X[6]);
707  float x7 = x1 * x6;
708  float x8 = x2 * x6;
709  float x9 = x1 * x3;
710  float x10 = tan(X[7]);
711  float x11 = 1.0 / x0;
712  out[0][0] = 0;
713  out[0][1] = 0;
714  out[0][2] = 0;
715  out[0][3] = 0;
716  out[0][4] = 0;
717  out[0][5] = 0;
718  out[1][0] = 0;
719  out[1][1] = 0;
720  out[1][2] = 0;
721  out[1][3] = 0;
722  out[1][4] = 0;
723  out[1][5] = 0;
724  out[2][0] = 0;
725  out[2][1] = 0;
726  out[2][2] = 0;
727  out[2][3] = 0;
728  out[2][4] = 0;
729  out[2][5] = 0;
730  out[3][0] = -x0 * x1;
731  out[3][1] = x4 - x5 * x7;
732  out[3][2] = -x5 * x9 - x8;
733  out[3][3] = 0;
734  out[3][4] = 0;
735  out[3][5] = 0;
736  out[4][0] = -x0 * x2;
737  out[4][1] = -x5 * x8 - x9;
738  out[4][2] = -x4 * x5 + x7;
739  out[4][3] = 0;
740  out[4][4] = 0;
741  out[4][5] = 0;
742  out[5][0] = x5;
743  out[5][1] = -x0 * x6;
744  out[5][2] = -x0 * x3;
745  out[5][3] = 0;
746  out[5][4] = 0;
747  out[5][5] = 0;
748  out[6][0] = 0;
749  out[6][1] = 0;
750  out[6][2] = 0;
751  out[6][3] = -1;
752  out[6][4] = -x10 * x6;
753  out[6][5] = -x10 * x3;
754  out[7][0] = 0;
755  out[7][1] = 0;
756  out[7][2] = 0;
757  out[7][3] = 0;
758  out[7][4] = -x3;
759  out[7][5] = x6;
760  out[8][0] = 0;
761  out[8][1] = 0;
762  out[8][2] = 0;
763  out[8][3] = 0;
764  out[8][4] = -x11 * x6;
765  out[8][5] = -x11 * x3;
766  out[9][0] = 0;
767  out[9][1] = 0;
768  out[9][2] = 0;
769  out[9][3] = 0;
770  out[9][4] = 0;
771  out[9][5] = 0;
772  out[10][0] = 0;
773  out[10][1] = 0;
774  out[10][2] = 0;
775  out[10][3] = 0;
776  out[10][4] = 0;
777  out[10][5] = 0;
778  out[11][0] = 0;
779  out[11][1] = 0;
780  out[11][2] = 0;
781  out[11][3] = 0;
782  out[11][4] = 0;
783  out[11][5] = 0;
784  out[12][0] = 0;
785  out[12][1] = 0;
786  out[12][2] = 0;
787  out[12][3] = 0;
788  out[12][4] = 0;
789  out[12][5] = 0;
790  out[13][0] = 0;
791  out[13][1] = 0;
792  out[13][2] = 0;
793  out[13][3] = 0;
794  out[13][4] = 0;
795  out[13][5] = 0;
796  out[14][0] = 0;
797  out[14][1] = 0;
798  out[14][2] = 0;
799  out[14][3] = 0;
800  out[14][4] = 0;
801  out[14][5] = 0;
802 }
803 
804 
805 
806 static inline void ekf_f_rk4(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], const float dt,
807  float out[EKF_NUM_STATES])
808 {
809  float k1[EKF_NUM_STATES];
810  float k2[EKF_NUM_STATES];
811  float k3[EKF_NUM_STATES];
812  float k4[EKF_NUM_STATES];
813 
814  float Xtmp[EKF_NUM_STATES];
815 
816  // k1 = f(X,U)
817  ekf_f(X, U, k1);
818 
819  // Xtmp = X+dt*k1/2
820  float_vect_smul(Xtmp, k1, dt / 2, EKF_NUM_STATES);
822 
823  // k2 = f(Xtmp,U)
824  ekf_f(Xtmp, U, k2);
825 
826  // Xtmp = X+dt*k2/2
827  float_vect_smul(Xtmp, k2, dt / 2, EKF_NUM_STATES);
829 
830  // k3 = f(Xtmp,U)
831  ekf_f(Xtmp, U, k3);
832 
833  // Xtmp = X+dt*k3
834  float_vect_smul(Xtmp, k3, dt, EKF_NUM_STATES);
836 
837  // k4 = f(Xtmp,U)
838  ekf_f(Xtmp, U, k4);
839 
840  // out = k2+k3
841  float_vect_sum(out, k2, k3, EKF_NUM_STATES);
842  // out *= 2
844  // out += k1
845  float_vect_add(out, k1, EKF_NUM_STATES);
846  // out += k4
847  float_vect_add(out, k4, EKF_NUM_STATES);
848  // out *= dt/6
849  float_vect_scale(out, dt / 6, EKF_NUM_STATES);
850  // out += X
852 }
853 
854 
855 static inline void ekf_step(const float U[EKF_NUM_INPUTS], const float Z[EKF_NUM_OUTPUTS], const float dt)
856 {
857  // [1] Predicted (a priori) state estimate:
858  float Xkk_1[EKF_NUM_STATES];
859  ekf_f_rk4(ekf_X, U, dt, Xkk_1);
860 
861 
862  // [2] Get matrices
863  float F[EKF_NUM_STATES][EKF_NUM_STATES];
864  float L[EKF_NUM_STATES][EKF_NUM_INPUTS];
865  ekf_F(ekf_X, U, F);
866  ekf_L(ekf_X, U, L);
867 
868 
869  // [3] Continuous to discrete
870  // Fd = eye(N) + F*dt + F*F*dt**2/2 = I + [I+F*dt/2]*F*dt
871  // Ld = L*dt+F*L*dt**2/2 = [I+F*dt/2]*L*dt
872  float Fd[EKF_NUM_STATES][EKF_NUM_STATES];
873  float Ld[EKF_NUM_STATES][EKF_NUM_INPUTS];
874  float tmp[EKF_NUM_STATES][EKF_NUM_STATES];
875 
880  MAKE_MATRIX_PTR(tmp_, tmp, EKF_NUM_STATES);
881 
882  // tmp = I+F*dt/2
885 
886  // Ld = tmp*L*dt
889 
890  // Fd = tmp*F*dt
893 
894  // Fd += I
895  int i;
896  for (i = 0; i < EKF_NUM_STATES; i++) {
897  Fd[i][i] += 1;
898  }
899 
900 
901  // [4] Predicted covariance estimate:
902  // Pkk_1 = Fd*P*Fd.T + Ld*Q*Ld.T
903  float Pkk_1[EKF_NUM_STATES][EKF_NUM_STATES];
904  float LdT[EKF_NUM_INPUTS][EKF_NUM_STATES];
905  float QLdT[EKF_NUM_INPUTS][EKF_NUM_STATES];
906 
907  MAKE_MATRIX_PTR(Pkk_1_, Pkk_1, EKF_NUM_STATES);
910  MAKE_MATRIX_PTR(LdT_, LdT, EKF_NUM_INPUTS);
911  MAKE_MATRIX_PTR(QLdT_, QLdT, EKF_NUM_INPUTS);
912 
913  // Fd = Fd.T
915 
916  // tmp = P*Fd
918 
919  // Fd = Fd.T
921 
922  // Pkk_1 = Fd*tmp
924 
925  // LdT = Ld.T
927 
928  // QLdT = Q*LdT
930 
931  // tmp = Ld*QLdT
933 
934  // Pkk_1 += tmp
936 
937 
938  // [5] Measurement residual:
939  // yk = Z - H*Xkk_1
940  float yk[EKF_NUM_OUTPUTS];
941 
943 
947 
948 
949  // [6] Residual covariance:
950  // Sk = H*Pkk_1*H.T + R
951  float Sk[EKF_NUM_OUTPUTS][EKF_NUM_OUTPUTS];
952  float PHT[EKF_NUM_STATES][EKF_NUM_OUTPUTS];
953 
955  MAKE_MATRIX_PTR(PHT_, PHT, EKF_NUM_STATES);
957 
958  // PHT = Pkk_1*H.T
961 
962  // Sk = H*PHT
964 
965  // Sk += R
967 
968 
969  // [7] Near-optimal Kalman gain:
970  // K = Pkk_1*H.T*inv(Sk)
971  float Sk_inv[EKF_NUM_OUTPUTS][EKF_NUM_OUTPUTS];
973 
974  MAKE_MATRIX_PTR(Sk_inv_, Sk_inv, EKF_NUM_OUTPUTS);
976 
977  // Sk_inv = inv(Sk)
978  float_mat_invert(Sk_inv_, Sk_, EKF_NUM_OUTPUTS);
979 
980  // K = PHT*Sk_inv
982 
983 
984  // [8] Updated state estimate
985  // Xkk = Xkk_1 + K*yk
988 
989 
990  // [9] Updated covariance estimate:
991  // Pkk = (I - K*H)*Pkk_1
992 
993  // tmp = K*H
995 
996  // tmp *= -1
998 
999  // tmp += I
1000  for (i = 0; i < EKF_NUM_STATES; i++) {
1001  tmp_[i][i] += 1;
1002  }
1003  // P = tmp*Pkk_1
1004  float_mat_mul(ekf_P_, tmp_, Pkk_1_, EKF_NUM_STATES, EKF_NUM_STATES, EKF_NUM_STATES);
1005 }
1006 
1007 static inline void ekf_prediction_step(const float U[EKF_NUM_INPUTS], const float dt)
1008 {
1009  // [1] Predicted (a priori) state estimate:
1010  float Xkk_1[EKF_NUM_STATES];
1011  // Xkk_1 = f(X,U)
1012  ekf_f(ekf_X, U, Xkk_1);
1013  // Xkk_1 *= dt
1014  float_vect_scale(Xkk_1, dt, EKF_NUM_STATES);
1015  // Xkk_1 += X
1017 
1018 
1019  // [2] Get matrices
1020  float F[EKF_NUM_STATES][EKF_NUM_STATES];
1021  float Ld[EKF_NUM_STATES][EKF_NUM_INPUTS];
1022  ekf_F(ekf_X, U, F);
1023  ekf_L(ekf_X, U, Ld);
1024 
1025 
1026  // [3] Continuous to discrete
1027  // Fd = eye(N) + F*dt
1028  // Ld = L*dt
1029  float Fd[EKF_NUM_STATES][EKF_NUM_STATES];
1030 
1032  MAKE_MATRIX_PTR(Fd_, Fd, EKF_NUM_STATES);
1033  MAKE_MATRIX_PTR(Ld_, Ld, EKF_NUM_STATES);
1034 
1035  // Fd = I+F*dt/2
1038 
1039  // Ld = Ld*dt
1041 
1042 
1043  // [4] Predicted covariance estimate:
1044  // Pkk_1 = Fd*P*Fd.T + Ld*Q*Ld.T
1045  float Pkk_1[EKF_NUM_STATES][EKF_NUM_STATES];
1046  float LdT[EKF_NUM_INPUTS][EKF_NUM_STATES];
1047  float QLdT[EKF_NUM_INPUTS][EKF_NUM_STATES];
1048  float tmp[EKF_NUM_STATES][EKF_NUM_STATES];
1049 
1050  MAKE_MATRIX_PTR(Pkk_1_, Pkk_1, EKF_NUM_STATES);
1053  MAKE_MATRIX_PTR(LdT_, LdT, EKF_NUM_INPUTS);
1054  MAKE_MATRIX_PTR(QLdT_, QLdT, EKF_NUM_INPUTS);
1055  MAKE_MATRIX_PTR(tmp_, tmp, EKF_NUM_STATES);
1056 
1057  // Fd = Fd.T
1059 
1060  // tmp = P*Fd
1062 
1063  // Fd = Fd.T
1065 
1066  // Pkk_1 = Fd*tmp
1068 
1069  // LdT = Ld.T
1071 
1072  // QLdT = Q*LdT
1074 
1075  // tmp = Ld*QLdT
1077 
1078  // Pkk_1 += tmp
1080 
1081  // X = Xkk_1
1083 
1084  // P = Pkk_1
1085  float_mat_copy(ekf_P_, Pkk_1_, EKF_NUM_STATES, EKF_NUM_STATES);
1086 }
1087 
1088 static inline void ekf_measurement_step(const float Z[EKF_NUM_OUTPUTS])
1089 {
1090  // Xkk_1 = X
1091  float Xkk_1[EKF_NUM_STATES];
1093 
1094  // Pkk_1 = P
1095  float Pkk_1[EKF_NUM_STATES][EKF_NUM_STATES];
1096  MAKE_MATRIX_PTR(Pkk_1_, Pkk_1, EKF_NUM_STATES);
1098  float_mat_copy(Pkk_1_, ekf_P_, EKF_NUM_STATES, EKF_NUM_STATES);
1099 
1100  // [5] Measurement residual:
1101  // yk = Z - H*Xkk_1
1102  float yk[EKF_NUM_OUTPUTS];
1103 
1105 
1106  float_mat_vect_mul(yk, ekf_H_, Xkk_1, EKF_NUM_OUTPUTS, EKF_NUM_STATES);
1109 
1110 
1111  // [6] Residual covariance:
1112  // Sk = H*Pkk_1*H.T + R
1113  float Sk[EKF_NUM_OUTPUTS][EKF_NUM_OUTPUTS];
1114  float PHT[EKF_NUM_STATES][EKF_NUM_OUTPUTS];
1115 
1116  MAKE_MATRIX_PTR(Sk_, Sk, EKF_NUM_OUTPUTS);
1117  MAKE_MATRIX_PTR(PHT_, PHT, EKF_NUM_STATES);
1119 
1120  // PHT = Pkk_1*H.T
1123 
1124  // Sk = H*PHT
1126 
1127  // Sk += R
1129 
1130 
1131  // [7] Near-optimal Kalman gain:
1132  // K = Pkk_1*H.T*inv(Sk)
1133  float Sk_inv[EKF_NUM_OUTPUTS][EKF_NUM_OUTPUTS];
1135 
1136  MAKE_MATRIX_PTR(Sk_inv_, Sk_inv, EKF_NUM_OUTPUTS);
1138 
1139  // Sk_inv = inv(Sk)
1140  float_mat_invert(Sk_inv_, Sk_, EKF_NUM_OUTPUTS);
1141 
1142  // K = PHT*Sk_inv
1144 
1145 
1146  // [8] Updated state estimate
1147  // Xkk = Xkk_1 + K*yk
1150 
1151 
1152  // [9] Updated covariance estimate:
1153  // Pkk = (I - K*H)*Pkk_1
1154  float tmp[EKF_NUM_STATES][EKF_NUM_STATES];
1155  MAKE_MATRIX_PTR(tmp_, tmp, EKF_NUM_STATES);
1156 
1157  // tmp = K*H
1159 
1160  // tmp *= -1
1162 
1163  // tmp += I
1164  int i;
1165  for (i = 0; i < EKF_NUM_STATES; i++) {
1166  tmp_[i][i] += 1;
1167  }
1168  // P = tmp*Pkk_1
1169  float_mat_mul(ekf_P_, tmp_, Pkk_1_, EKF_NUM_STATES, EKF_NUM_STATES, EKF_NUM_STATES);
1170 }
1171 
1172 
1173 
1174 
1175 
1176 static inline void ekf_run(void)
1177 {
1178  static bool start = false;
1179 
1180 
1181  // Time
1182  t1 = get_sys_time_float();
1183  float dt = t1 - t0;
1184  t0 = t1;
1185 
1186  // Only Start If External Pose is Available
1187  if (!start) {
1188  // ekf starts at the first ev update
1190  start = true;
1191 
1192  // initial guess
1193  ekf_X[0] = ins_ext_pos.ev_pos.x;
1194  ekf_X[1] = ins_ext_pos.ev_pos.y;
1195  ekf_X[2] = ins_ext_pos.ev_pos.z;
1196  ekf_X[6] = ins_ext_pos.ev_att.phi;
1198  ekf_X[8] = ins_ext_pos.ev_att.psi;
1199  }
1200  }
1201 
1202  // set input values
1203  if (ins_ext_pos.has_new_acc) {
1204  ekf_U[0] = ins_ext_pos.accels_f.x;
1205  ekf_U[1] = ins_ext_pos.accels_f.y;
1206  ekf_U[2] = ins_ext_pos.accels_f.z;
1207  ins_ext_pos.has_new_acc = false;
1208  } else {
1209  DEBUG_PRINT("ekf missing acc\n");
1210  }
1211  if (ins_ext_pos.has_new_gyro) {
1212  ekf_U[3] = ins_ext_pos.gyros_f.p;
1213  ekf_U[4] = ins_ext_pos.gyros_f.q;
1214  ekf_U[5] = ins_ext_pos.gyros_f.r;
1215  ins_ext_pos.has_new_gyro = false;
1216  } else {
1217  DEBUG_PRINT("ekf missing gyro\n");
1218  }
1219 
1220  if (start) {
1221 
1222  // prediction step
1223  DEBUG_PRINT("ekf prediction step U = %f, %f, %f, %f, %f, %f dt = %f \n", ekf_U[0], ekf_U[1], ekf_U[2], ekf_U[3],
1224  ekf_U[4], ekf_U[5], dt);
1226 
1227  // measurement step
1229 
1230  //fix psi
1231  static float last_psi = 0;
1232  float delta_psi = ins_ext_pos.ev_att.psi - last_psi;
1233  last_psi = ins_ext_pos.ev_att.psi;
1234 
1235  if (delta_psi > M_PI) {
1236  delta_psi -= 2 * M_PI;
1237  } else if (delta_psi < -M_PI) {
1238  delta_psi += 2 * M_PI;
1239  }
1240 
1241 
1242  ekf_Z[0] = ins_ext_pos.ev_pos.x;
1243  ekf_Z[1] = ins_ext_pos.ev_pos.y;
1244  ekf_Z[2] = ins_ext_pos.ev_pos.z;
1245  ekf_Z[3] = ins_ext_pos.ev_att.phi;
1247  ekf_Z[5] += delta_psi;
1248  ins_ext_pos.has_new_ext_pose = false;
1249 
1250  DEBUG_PRINT("ekf measurement step Z = %f, %f, %f, %f \n", ekf_Z[0], ekf_Z[1], ekf_Z[2], ekf_Z[3]);
1252  }
1253  }
1254 
1255  // Export Results
1256  struct NedCoor_f ned_pos;
1257  ned_pos.x = ekf_X[0];
1258  ned_pos.y = ekf_X[1];
1259  ned_pos.z = ekf_X[2];
1260 
1261  struct NedCoor_f ned_speed;
1262  ned_speed.x = ekf_X[3];
1263  ned_speed.y = ekf_X[4];
1264  ned_speed.z = ekf_X[5];
1265 
1266  struct FloatEulers ned_to_body_eulers;
1267  ned_to_body_eulers.phi = ekf_X[6];
1268  ned_to_body_eulers.theta = ekf_X[7];
1269  ned_to_body_eulers.psi = ekf_X[8];
1270 
1271  struct FloatRates rates = { ekf_U[3] - ekf_X[12], ekf_U[4] - ekf_X[13], ekf_U[5] - ekf_X[14] };
1272 
1273  struct FloatVect3 accel;
1274  struct FloatVect3 accel_ned_f;
1275  accel.x = ekf_U[0] - ekf_X[9];
1276  accel.y = ekf_U[1] - ekf_X[10];
1277  accel.z = ekf_U[2] - ekf_X[11];
1278 
1279  // Export Body Accelerations (without bias)
1280  struct Int32Vect3 accel_i;
1281  ACCELS_BFP_OF_REAL(accel_i, accel);
1282  stateSetAccelBody_i(&accel_i);
1283 
1284 
1285  struct FloatRMat *ned_to_body_rmat_f = stateGetNedToBodyRMat_f();
1286  float_rmat_transp_vmult(&accel_ned_f, ned_to_body_rmat_f, &accel);
1287  accel_ned_f.z += 9.81;
1288 
1289  stateSetPositionNed_f(&ned_pos);
1290  stateSetSpeedNed_f(&ned_speed);
1291  stateSetNedToBodyEulers_f(&ned_to_body_eulers);
1292  stateSetBodyRates_f(&rates);
1293  stateSetAccelNed_f((struct NedCoor_f *)&accel_ned_f);
1294 
1295 }
1296 
1297 
1298 
1303 void ins_ext_pos_log_header(FILE *file)
1304 {
1305  fprintf(file,
1306  "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,");
1307  fprintf(file, "ekf_U1,ekf_U2,ekf_U3,ekf_U4,ekf_U5,ekf_U6,");
1308  fprintf(file, "ekf_Z1,ekf_Z2,ekf_Z3,ekf_Z4,");
1309 }
1310 
1311 void ins_ext_pos_log_data(FILE *file)
1312 {
1313  fprintf(file, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,", ekf_X[0], ekf_X[1], ekf_X[2], ekf_X[3], ekf_X[4],
1314  ekf_X[5], ekf_X[6], ekf_X[7], ekf_X[8], ekf_X[9], ekf_X[10], ekf_X[11], ekf_X[12], ekf_X[13], ekf_X[14]);
1315  fprintf(file, "%f,%f,%f,%f,%f,%f,", ekf_U[0], ekf_U[1], ekf_U[2], ekf_U[3], ekf_U[4], ekf_U[5]);
1316  fprintf(file, "%f,%f,%f,%f,", ekf_Z[0], ekf_Z[1], ekf_Z[2], ekf_Z[3]);
1317 }
Main include for ABI (AirBorneInterface).
Event structure to store callbacks in a linked list.
Definition: abi_common.h:67
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
Definition: sys_time_arch.c:71
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
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
static void float_mat_vect_mul(float *o, float **a, float *b, int m, int n)
o = a * b
static void float_vect_scale(float *a, const float s, const int n)
a *= s
static void float_mat_sum_scaled(float **a, float **b, float k, int m, int n)
a += k*b, where k is a scalar value
static void float_mat_mul_copy(float **o, float **a, float **b, int m, int n, int l)
o = a * b
static void float_mat_copy(float **a, float **b, int m, int n)
a = b
static void float_vect_copy(float *a, const float *b, const int n)
a = b
static void float_mat_mul(float **o, float **a, float **b, int m, int n, int l)
o = a * b
static void float_mat_transpose(float **o, float **a, int n, int m)
transpose non-square matrix
#define MAKE_MATRIX_PTR(_ptr, _mat, _rows)
Make a pointer to a matrix of _rows lines.
void float_mat_invert(float **o, float **mat, int n)
Calculate inverse of any n x n matrix (passed as C array) o = mat^-1 Algorithm verified with Matlab.
void float_rmat_transp_vmult(struct FloatVect3 *vb, struct FloatRMat *m_b2a, struct FloatVect3 *va)
rotate 3D vector by transposed rotation matrix.
void float_eulers_of_quat(struct FloatEulers *e, struct FloatQuat *q)
euler rotation 'ZYX'
static void float_mat_transpose_square(float **a, int n)
transpose square matrix
void float_quat_comp(struct FloatQuat *a2c, struct FloatQuat *a2b, struct FloatQuat *b2c)
Composition (multiplication) of two quaternions.
static void float_mat_diagonal_scal(float **o, float v, int n)
Make an n x n identity matrix (for matrix passed as array)
static void float_mat_scale(float **a, float k, int m, int n)
a *= k, where k is a scalar value
euler angles
Roation quaternion.
rotation matrix
angular rates
#define ACCELS_BFP_OF_REAL(_ef, _ei)
Definition: pprz_algebra.h:801
#define RATES_FLOAT_OF_BFP(_rf, _ri)
Definition: pprz_algebra.h:759
#define ACCELS_FLOAT_OF_BFP(_ef, _ei)
Definition: pprz_algebra.h:795
angular rates
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(struct NedCoor_f *ned_accel)
Set acceleration in NED coordinates (float).
Definition: state.h:1002
static struct FloatRMat * stateGetNedToBodyRMat_f(void)
Get vehicle body attitude rotation matrix (float).
Definition: state.h:1137
static void stateSetNedToBodyEulers_f(struct FloatEulers *ned_to_body_eulers)
Set vehicle body attitude from euler angles (float).
Definition: state.h:1105
static void stateSetPositionNed_f(struct NedCoor_f *ned_pos)
Set position from local NED coordinates (float).
Definition: state.h:598
static void stateSetLocalOrigin_i(struct LtpDef_i *ltp_def)
Set the local (flat earth) coordinate frame origin (int).
Definition: state.h:457
static void stateSetBodyRates_f(struct FloatRates *body_rate)
Set vehicle body angular rate (float).
Definition: state.h:1181
static void stateSetAccelBody_i(struct Int32Vect3 *body_accel)
Set acceleration in Body coordinates (int).
Definition: state.h:855
static void stateSetSpeedNed_f(struct NedCoor_f *ned_speed)
Set ground speed in local NED coordinates (float).
Definition: state.h:809
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])
Definition: ins_ext_pose.c:697
struct InsExtPose ins_ext_pos
Definition: ins_ext_pose.c:73
struct FloatRates gyros_f
Definition: ins_ext_pose.c:53
struct FloatEulers ev_att
Definition: ins_ext_pose.c:60
void ins_reset_local_origin(void)
INS local origin reset.
Definition: ins_ext_pose.c:255
static void ekf_f_rk4(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], const float dt, float out[EKF_NUM_STATES])
Definition: ins_ext_pose.c:806
struct FloatVect3 ev_vel
Definition: ins_ext_pose.c:59
static void send_ins(struct transport_tx *trans, struct link_device *dev)
Provide telemetry.
Definition: ins_ext_pose.c:102
void ins_ext_pose_msg_update(uint8_t *buf)
Import External Pose Message.
Definition: ins_ext_pose.c:197
static void ekf_F(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], float out[EKF_NUM_STATES][EKF_NUM_STATES])
Definition: ins_ext_pose.c:428
void ins_ext_pos_log_data(FILE *file)
float ekf_P[EKF_NUM_STATES][EKF_NUM_STATES]
Definition: ins_ext_pose.c:337
float ekf_R[EKF_NUM_OUTPUTS][EKF_NUM_OUTPUTS]
Definition: ins_ext_pose.c:339
struct LtpDef_i ltp_def
Definition: ins_ext_pose.c:66
static abi_event accel_ev
Definition: ins_ext_pose.c:168
static void gyro_cb(uint8_t sender_id, uint32_t stamp, struct Int32Rates *gyro)
Definition: ins_ext_pose.c:176
struct FloatQuat ev_quat
Definition: ins_ext_pose.c:61
struct NedCoor_i ltp_pos
Definition: ins_ext_pose.c:69
static void ekf_init(void)
EKF protos.
Definition: ins_ext_pose.c:364
struct FloatVect3 accels_f
Definition: ins_ext_pose.c:54
static void ins_ext_pose_init_from_flightplan(void)
Definition: ins_ext_pose.c:76
bool has_new_gyro
Definition: ins_ext_pose.c:55
float ekf_U[EKF_NUM_INPUTS]
Definition: ins_ext_pose.c:335
void ekf_set_diag(float **a, float *b, int n)
Definition: ins_ext_pose.c:348
float t0
Definition: ins_ext_pose.c:344
void ins_ext_pose_init(void)
Module.
Definition: ins_ext_pose.c:276
struct NedCoor_i ltp_speed
Definition: ins_ext_pose.c:70
static void ekf_measurement_step(const float Z[EKF_NUM_OUTPUTS])
static abi_event gyro_ev
Definition: ins_ext_pose.c:169
static void send_ins_ref(struct transport_tx *trans, struct link_device *dev)
Definition: ins_ext_pose.c:118
bool has_new_ext_pose
Definition: ins_ext_pose.c:62
struct FloatVect3 ev_pos
Definition: ins_ext_pose.c:58
struct NedCoor_i ltp_accel
Definition: ins_ext_pose.c:71
static void send_ins_z(struct transport_tx *trans, struct link_device *dev)
Definition: ins_ext_pose.c:110
float ekf_Q[EKF_NUM_INPUTS][EKF_NUM_INPUTS]
Definition: ins_ext_pose.c:338
bool has_new_acc
Definition: ins_ext_pose.c:56
#define DEBUG_PRINT(...)
Definition: ins_ext_pose.c:42
void ins_ext_pose_run(void)
Definition: ins_ext_pose.c:305
void ins_reset_altitude_ref(void)
INS altitude reference reset.
Definition: ins_ext_pose.c:260
#define INS_EXT_POSE_IMU_ID
Import Gyro and Acc from ABI.
Definition: ins_ext_pose.c:164
float ev_time
Definition: ins_ext_pose.c:63
static void accel_cb(uint8_t sender_id, uint32_t stamp, struct Int32Vect3 *accel)
Definition: ins_ext_pose.c:184
float t1
Definition: ins_ext_pose.c:345
static void ekf_step(const float U[EKF_NUM_INPUTS], const float Z[EKF_NUM_OUTPUTS], const float dt)
Definition: ins_ext_pose.c:855
void ins_ext_pos_log_header(FILE *file)
Logging.
float ekf_Z[EKF_NUM_OUTPUTS]
Definition: ins_ext_pose.c:336
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)
Definition: ins_ext_pose.c:127
static void ekf_f(const float X[EKF_NUM_STATES], const float U[EKF_NUM_INPUTS], float out[EKF_NUM_STATES])
Definition: ins_ext_pose.c:389
static void ekf_run(void)
float ekf_X[EKF_NUM_STATES]
Definition: ins_ext_pose.c:334
float ekf_H[EKF_NUM_OUTPUTS][EKF_NUM_STATES]
Definition: ins_ext_pose.c:341
static void send_ahrs_bias(struct transport_tx *trans, struct link_device *dev)
Definition: ins_ext_pose.c:142
Data for telemetry and LTP origin.
Definition: ins_ext_pose.c:51
Integrated Navigation System interface.
#define EKF_NUM_OUTPUTS
Definition: ins_ext_pose.h:37
#define EKF_NUM_INPUTS
Definition: ins_ext_pose.h:36
#define EKF_NUM_STATES
Definition: ins_ext_pose.h:35
void waypoints_localize_all(void)
update local ENU coordinates of global waypoints
Definition: waypoints.c:357
Paparazzi floating point algebra.
float z
in meters
float x
in meters
float y
in meters
vector in North East Down coordinates Units: meters
API to get/set the generic vehicle states.
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:74
static float get_sys_time_float(void)
Get the time in seconds since startup.
Definition: sys_time.h:138
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_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 int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98
float b
Definition: wedgebug.c:202