Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
ins_alt_float.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2012 The Paparazzi Team
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 
29 #include "modules/core/abi.h"
30 #include "state.h"
31 
32 #include <inttypes.h>
33 #include <math.h>
34 
35 #include "state.h"
36 #include "mcu_periph/sys_time.h"
37 #include "modules/gps/gps.h"
39 
40 #include "generated/airframe.h"
41 #include "generated/modules.h"
42 
43 #ifdef DEBUG_ALT_KALMAN
44 #include "mcu_periph/uart.h"
46 #endif
47 
48 #ifndef USE_INS_NAV_INIT
49 #define USE_INS_NAV_INIT TRUE
50 PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
51 #endif
52 
53 struct InsAltFloat ins_altf;
54 
55 #if USE_BAROMETER
56 #include "modules/sensors/baro.h"
57 #include "math/pprz_isa.h"
58 
59 PRINT_CONFIG_MSG("USE_BAROMETER is TRUE: Using baro for altitude estimation.")
60 
61 // Baro event on ABI
62 #ifndef INS_ALT_BARO_ID
63 #if USE_BARO_BOARD
64 #define INS_ALT_BARO_ID BARO_BOARD_SENDER_ID
65 #else
66 #define INS_ALT_BARO_ID ABI_BROADCAST
67 #endif
68 #endif
70 
72 static void baro_cb(uint8_t sender_id, uint32_t stamp, float pressure);
73 #endif /* USE_BAROMETER */
74 
78 #ifndef INS_ALT_GPS_ID
79 #define INS_ALT_GPS_ID GPS_MULTI_ID
80 #endif
83 static void gps_cb(uint8_t sender_id, uint32_t stamp, struct GpsState *gps_s);
84 
85 #ifndef INS_ALT_IMU_ID
86 #define INS_ALT_IMU_ID ABI_BROADCAST
87 #endif
89 static void accel_cb(uint8_t sender_id, uint32_t stamp, struct Int32Vect3 *accel);
90 
92 static void reset_cb(uint8_t sender_id, uint8_t flag);
93 
94 static void alt_kalman_reset(void);
95 static void alt_kalman_init(void);
96 static void alt_kalman(float z_meas, float dt);
97 
98 void ins_alt_float_update_gps(struct GpsState *gps_s);
99 
101 {
102 #if USE_INS_NAV_INIT
104  stateSetLocalUtmOrigin_f(MODULE_INS_ALT_FLOAT_ID, &utm0);
106 
107  stateSetPositionUtm_f(MODULE_INS_ALT_FLOAT_ID, &utm0);
108 #else
110 #endif
111 
112  alt_kalman_init();
113 
114 #if USE_BAROMETER
115  ins_altf.qfe = 0.0f;
116  ins_altf.baro_initialized = false;
117  ins_altf.baro_alt = 0.0f;
118 #endif
119  ins_altf.reset_alt_ref = false;
120 
121  // why do we have this here?
122  alt_kalman(0.0f, 0.1);
123 
124 #if USE_BAROMETER
125  // Bind to BARO_ABS message
126  AbiBindMsgBARO_ABS(INS_ALT_BARO_ID, &baro_ev, baro_cb);
127 #endif
128  AbiBindMsgGPS(INS_ALT_GPS_ID, &gps_ev, gps_cb);
129  AbiBindMsgIMU_ACCEL(INS_ALT_IMU_ID, &accel_ev, accel_cb);
130  AbiBindMsgINS_RESET(ABI_BROADCAST, &reset_ev, reset_cb);
131 }
132 
133 static void reset_ref(void)
134 {
135  // get utm pos
136  struct UtmCoor_f utm = utm_float_from_gps(&gps, 0);
137  // reset state UTM ref
138  stateSetLocalUtmOrigin_f(MODULE_INS_ALT_FLOAT_ID, &utm);
140  // reset filter flag
141  ins_altf.reset_alt_ref = true;
142 }
143 
144 static void reset_vertical_ref(void)
145 {
146  struct UtmCoor_f utm = *stateGetUtmOrigin_f();
147  // ground_alt
148  utm.alt = gps.hmsl / 1000.0f;
149  // reset state UTM ref
150  stateSetLocalUtmOrigin_f(MODULE_INS_ALT_FLOAT_ID, &utm);
151  // reset filter flag
152  ins_altf.reset_alt_ref = true;
153 }
154 
155 static void reset_cb(uint8_t sender_id UNUSED, uint8_t flag)
156 {
157  switch (flag) {
158  case INS_RESET_REF:
159  reset_ref();
160  break;
163  break;
164  default:
165  // unsupported cases
166  break;
167  }
168 }
169 
170 #if USE_BAROMETER
171 void ins_alt_float_update_baro(float pressure)
172 {
173  // timestamp in usec when last callback was received
174  static uint32_t last_ts = 0;
175  // current timestamp
176  uint32_t now_ts = get_sys_time_usec();
177  // dt between this and last callback in seconds
178  float dt = (float)(now_ts - last_ts) / 1e6;
179  last_ts = now_ts;
180 
181  // bound dt (assume baro freq 1Hz-500Hz
182  Bound(dt, 0.002, 1.0)
183 
184  if (!ins_altf.baro_initialized) {
185  ins_altf.qfe = pressure;
186  ins_altf.baro_initialized = true;
187  }
188  if (ins_altf.reset_alt_ref) {
189  ins_altf.reset_alt_ref = false;
191  ins_altf.alt_dot = 0.0f;
192  ins_altf.qfe = pressure;
194  } else { /* not realigning, so normal update with baro measurement */
196  /* run the filter */
198  /* set new altitude, just copy old horizontal position */
199  struct UtmCoor_f utm;
201  utm.alt = ins_altf.alt;
202  stateSetPositionUtm_f(MODULE_INS_ALT_FLOAT_ID, &utm);
203  struct NedCoor_f ned_vel;
204  ned_vel = *stateGetSpeedNed_f();
205  ned_vel.z = -ins_altf.alt_dot;
206  stateSetSpeedNed_f(MODULE_INS_ALT_FLOAT_ID, &ned_vel);
207  }
208 }
209 #else
210 void ins_alt_float_update_baro(float pressure __attribute__((unused)))
211 {
212 }
213 #endif
214 
215 
216 void ins_alt_float_update_gps(struct GpsState *gps_s __attribute__((unused)))
217 {
218 #if USE_GPS
219  if (gps_s->fix < GPS_FIX_3D) {
220  return;
221  }
222 
224  reset_ref(MODULE_INS_ALT_FLOAT_ID);
225  }
226 
227  struct UtmCoor_f utm = utm_float_from_gps(gps_s, nav_utm_zone0);
228  struct NedCoor_f ned_vel = ned_vel_float_from_gps(gps_s);
229 
230 #if !USE_BAROMETER
231 #ifdef GPS_DT
232  const float dt = GPS_DT;
233 #else
234  // timestamp in usec when last callback was received
235  static uint32_t last_ts = 0;
236  // current timestamp
237  uint32_t now_ts = get_sys_time_usec();
238  // dt between this and last callback in seconds
239  float dt = (float)(now_ts - last_ts) / 1e6;
240  last_ts = now_ts;
241 
242  // bound dt (assume GPS freq between 0.5Hz and 50Hz)
243  Bound(dt, 0.02, 2)
244 #endif
245 
246  if (ins_altf.reset_alt_ref) {
247  ins_altf.reset_alt_ref = false;
248  ins_altf.alt = utm.alt;
249  ins_altf.alt_dot = 0.0f;
251  } else {
252  alt_kalman(utm.alt, dt);
253  ins_altf.alt_dot = -ned_vel.z;
254  }
255 #endif // !USE_BAROMETER
256 
257  utm.alt = ins_altf.alt;
258  // set position
259  stateSetPositionUtm_f(MODULE_INS_ALT_FLOAT_ID, &utm);
260 
261  ned_vel.z = -ins_altf.alt_dot; // vz (down) from filter
262  // set velocity
263  stateSetSpeedNed_f(MODULE_INS_ALT_FLOAT_ID, &ned_vel);
264 
265 #endif
266 }
267 
268 
269 #define GPS_SIGMA2 1.
270 #define GPS_R 2.
271 
272 static float p[2][2];
273 
274 static void alt_kalman_reset(void)
275 {
276  p[0][0] = 1.0f;
277  p[0][1] = 0.0f;
278  p[1][0] = 0.0f;
279  p[1][1] = 1.0f;
280 }
281 
282 static void alt_kalman_init(void)
283 {
285 }
286 
287 static void alt_kalman(float z_meas, float dt)
288 {
289  float R = GPS_R;
290  float SIGMA2 = GPS_SIGMA2;
291 
292 #if USE_BAROMETER
293 #ifdef SITL
294  R = 0.5;
295  SIGMA2 = 0.1;
296 #elif USE_BARO_MS5534A
297  if (alt_baro_enabled) {
298  R = baro_MS5534A_r;
299  SIGMA2 = baro_MS5534A_sigma2;
300  }
301 #elif USE_BARO_ETS
302  if (baro_ets_enabled) {
303  R = baro_ets_r;
304  SIGMA2 = baro_ets_sigma2;
305  }
306 #elif USE_BARO_MS5611
307  if (baro_ms5611_enabled) {
308  R = baro_ms5611_r;
309  SIGMA2 = baro_ms5611_sigma2;
310  }
311 #elif USE_BARO_AMSYS
312  if (baro_amsys_enabled) {
313  R = baro_amsys_r;
314  SIGMA2 = baro_amsys_sigma2;
315  }
316 #elif USE_BARO_BMP
317  if (baro_bmp_enabled) {
318  R = baro_bmp_r;
319  SIGMA2 = baro_bmp_sigma2;
320  }
321 #endif
322 #endif // USE_BAROMETER
323 
324  float q[2][2];
325  q[0][0] = dt * dt * dt * dt / 4.;
326  q[0][1] = dt * dt * dt / 2.;
327  q[1][0] = dt * dt * dt / 2.;
328  q[1][1] = dt * dt;
329 
330 
331  /* predict */
332  ins_altf.alt += ins_altf.alt_dot * dt;
333  p[0][0] = p[0][0] + p[1][0] * dt + dt * (p[0][1] + p[1][1] * dt) + SIGMA2 * q[0][0];
334  p[0][1] = p[0][1] + p[1][1] * dt + SIGMA2 * q[0][1];
335  p[1][0] = p[1][0] + p[1][1] * dt + SIGMA2 * q[1][0];
336  p[1][1] = p[1][1] + SIGMA2 * q[1][1];
337 
338  /* error estimate */
339  float e = p[0][0] + R;
340 
341  if (fabs(e) > 1e-5) {
342  float k_0 = p[0][0] / e;
343  float k_1 = p[1][0] / e;
344  e = z_meas - ins_altf.alt;
345 
346  /* correction */
347  ins_altf.alt += k_0 * e;
348  ins_altf.alt_dot += k_1 * e;
349 
350  p[1][0] = -p[0][0] * k_1 + p[1][0];
351  p[1][1] = -p[0][1] * k_1 + p[1][1];
352  p[0][0] = p[0][0] * (1 - k_0);
353  p[0][1] = p[0][1] * (1 - k_0);
354  }
355 
356 #ifdef DEBUG_ALT_KALMAN
357  DOWNLINK_SEND_ALT_KALMAN(DefaultChannel, DefaultDevice, &(p[0][0]), &(p[0][1]), &(p[1][0]), &(p[1][1]));
358 #endif
359 }
360 
361 #if USE_BAROMETER
362 static void baro_cb(uint8_t __attribute__((unused)) sender_id, __attribute__((unused)) uint32_t stamp, float pressure)
363 {
364  ins_alt_float_update_baro(pressure);
365 }
366 #endif
367 
368 static void gps_cb(uint8_t sender_id __attribute__((unused)),
369  uint32_t stamp __attribute__((unused)),
370  struct GpsState *gps_s)
371 {
373 }
374 
375 static void accel_cb(uint8_t sender_id __attribute__((unused)),
376  uint32_t stamp __attribute__((unused)),
377  struct Int32Vect3 *accel)
378 {
379  // untilt accel and remove gravity
380  struct Int32Vect3 accel_ned;
381  stateSetAccelBody_i(MODULE_INS_ALT_FLOAT_ID, accel);
382  struct Int32RMat *ned_to_body_rmat = stateGetNedToBodyRMat_i();
383  int32_rmat_transp_vmult(&accel_ned, ned_to_body_rmat, accel);
384  accel_ned.z += ACCEL_BFP_OF_REAL(9.81);
385  stateSetAccelNed_i(MODULE_INS_ALT_FLOAT_ID, (struct NedCoor_i *)&accel_ned);
386 }
Main include for ABI (AirBorneInterface).
#define ABI_BROADCAST
Broadcast address.
Definition: abi_common.h:58
Event structure to store callbacks in a linked list.
Definition: abi_common.h:67
Common barometric sensor implementation.
float baro_MS5534A_sigma2
Definition: baro_MS5534A.c:48
bool alt_baro_enabled
Definition: baro_MS5534A.c:45
float baro_MS5534A_r
Definition: baro_MS5534A.c:47
float baro_amsys_r
Definition: baro_amsys.c:78
float baro_amsys_sigma2
Definition: baro_amsys.c:79
bool baro_amsys_enabled
Definition: baro_amsys.c:77
bool baro_bmp_enabled
Definition: baro_bmp.c:54
float baro_bmp_r
Definition: baro_bmp.c:55
float baro_bmp_sigma2
Definition: baro_bmp.c:56
float baro_ets_r
Definition: baro_ets.c:108
bool baro_ets_enabled
Definition: baro_ets.c:107
float baro_ets_sigma2
Definition: baro_ets.c:109
float baro_ms5611_sigma2
bool baro_ms5611_enabled
float baro_ms5611_r
uint32_t last_ts
Definition: bluegiga.c:131
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
Definition: sys_time_arch.c:71
uint8_t last_wp UNUSED
int32_t nav_utm_east0
Definition: common_nav.c:48
uint8_t nav_utm_zone0
Definition: common_nav.c:50
float ground_alt
size == nb_waypoint, waypoint 0 is a dummy waypoint
Definition: common_nav.c:46
int32_t nav_utm_north0
Definition: common_nav.c:49
struct UtmCoor_f utm_float_from_gps(struct GpsState *gps_s, uint8_t zone)
Convenience functions to get utm position from GPS state.
Definition: gps.c:577
struct NedCoor_f ned_vel_float_from_gps(struct GpsState *gps_s)
Get GPS ned velocity (float) Converted on the fly if not available.
Definition: gps.c:544
struct GpsState gps
global GPS state
Definition: gps.c:74
Device independent GPS code (interface)
int32_t hmsl
height above mean sea level (MSL) in mm
Definition: gps.h:94
#define GPS_FIX_3D
3D GPS fix
Definition: gps.h:44
data structure for GPS information
Definition: gps.h:87
#define ACCEL_BFP_OF_REAL(_af)
void int32_rmat_transp_vmult(struct Int32Vect3 *vb, struct Int32RMat *m_b2a, struct Int32Vect3 *va)
rotate 3D vector by transposed rotation matrix.
rotation matrix
#define UTM_COPY(_u1, _u2)
Definition: pprz_geodetic.h:71
vector in North East Down coordinates
static float pprz_isa_height_of_pressure(float pressure, float ref_p)
Get relative altitude from pressure (using simplified equation).
Definition: pprz_isa.h:102
static void stateSetAccelNed_i(uint16_t id, struct NedCoor_i *ned_accel)
Set acceleration in NED coordinates (int).
Definition: state.h:1127
static void stateSetAccelBody_i(uint16_t id, struct Int32Vect3 *body_accel)
Set acceleration in Body coordinates (int).
Definition: state.h:1167
static struct Int32RMat * stateGetNedToBodyRMat_i(void)
Get vehicle body attitude rotation matrix (int).
Definition: state.h:1282
static struct UtmCoor_f * stateGetUtmOrigin_f(void)
Get the coordinate UTM frame origin (int)
Definition: state.h:576
static struct UtmCoor_f * stateGetPositionUtm_f(void)
Get position in UTM coordinates (float).
Definition: state.h:821
static void stateSetPositionUtm_f(uint16_t id, struct UtmCoor_f *utm_pos)
Set position from UTM coordinates (float).
Definition: state.h:698
static void stateSetLocalUtmOrigin_f(uint16_t id, struct UtmCoor_f *utm_def)
Set the local (flat earth) coordinate frame origin from UTM (float).
Definition: state.h:541
static void stateSetSpeedNed_f(uint16_t id, struct NedCoor_f *ned_speed)
Set ground speed in local NED coordinates (float).
Definition: state.h:947
static struct NedCoor_f * stateGetSpeedNed_f(void)
Get ground speed in local NED coordinates (float).
Definition: state.h:1049
#define INS_RESET_VERTICAL_REF
Definition: ins.h:37
#define INS_RESET_REF
flags for INS reset
Definition: ins.h:36
static void reset_vertical_ref(void)
#define GPS_SIGMA2
static void gps_cb(uint8_t sender_id, uint32_t stamp, struct GpsState *gps_s)
static void reset_cb(uint8_t sender_id, uint8_t flag)
#define INS_ALT_IMU_ID
Definition: ins_alt_float.c:86
static void reset_ref(void)
static abi_event accel_ev
Definition: ins_alt_float.c:88
#define INS_ALT_GPS_ID
ABI binding for gps data.
Definition: ins_alt_float.c:79
static void alt_kalman_init(void)
static abi_event reset_ev
Definition: ins_alt_float.c:91
#define GPS_R
abi_event baro_ev
Definition: ins_alt_float.c:71
static void alt_kalman(float z_meas, float dt)
static void baro_cb(uint8_t sender_id, uint32_t stamp, float pressure)
static float p[2][2]
struct InsAltFloat ins_altf
Definition: ins_alt_float.c:53
static void accel_cb(uint8_t sender_id, uint32_t stamp, struct Int32Vect3 *accel)
#define INS_ALT_BARO_ID
Definition: ins_alt_float.c:66
void ins_alt_float_update_gps(struct GpsState *gps_s)
void ins_alt_float_init(void)
static void alt_kalman_reset(void)
static abi_event gps_ev
Definition: ins_alt_float.c:82
void ins_alt_float_update_baro(float pressure)
Filters altitude and climb rate for fixedwings.
float alt_dot
estimated vertical speed in m/s (positive-up)
Definition: ins_alt_float.h:39
bool reset_alt_ref
flag to request reset of altitude reference to current alt
Definition: ins_alt_float.h:41
float alt
estimated altitude above MSL in meters
Definition: ins_alt_float.h:38
bool baro_initialized
Definition: ins_alt_float.h:47
float baro_alt
Definition: ins_alt_float.h:46
bool origin_initialized
TRUE if UTM origin was initialized.
Definition: ins_alt_float.h:42
Ins implementation state (altitude, float)
Definition: ins_alt_float.h:37
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
Fixedwing Navigation library.
PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF)
float alt
in meters (above WGS84 reference ellipsoid or above MSL)
float z
in meters
vector in North East Down coordinates Units: meters
position in UTM coordinates Units: meters
Paparazzi atmospheric pressure conversion utilities.
API to get/set the generic vehicle states.
Architecture independent timing functions.
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
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