Paparazzi UAS  v5.12_stable-4-g9b43e9b
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
vf_extended_float.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2009 Antoine Drouin <poinix@gmail.com>
3  * Copyright (C) 2012 Gautier Hattenberger
4  *
5  * This file is part of paparazzi.
6  *
7  * paparazzi is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * paparazzi is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with paparazzi; see the file COPYING. If not, write to
19  * the Free Software Foundation, 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 
35 #include "generated/airframe.h"
36 #include "std.h"
37 
38 #ifndef DEBUG_VFF_EXTENDED
39 #define DEBUG_VFF_EXTENDED 0
40 #else
41 PRINT_CONFIG_VAR(DEBUG_VFF_EXTENDED)
42 #endif
43 
44 #if DEBUG_VFF_EXTENDED
45 #include "mcu_periph/uart.h"
46 #include "pprzlink/messages.h"
48 #endif
49 
51 #ifndef VFF_EXTENDED_INIT_PXX
52 #define VFF_EXTENDED_INIT_PXX 1.0
53 #endif
54 
56 #ifndef VFF_EXTENDED_ACCEL_NOISE
57 #define VFF_EXTENDED_ACCEL_NOISE 0.5
58 #endif
59 
60 #define Qbiasbias 1e-7
61 #define Qoffoff 1e-4
62 #define R_BARO 1.
63 #define R_ALT 0.1
64 #define R_OFFSET 1.
65 
67 
68 #if PERIODIC_TELEMETRY
70 
71 static void send_vffe(struct transport_tx *trans, struct link_device *dev)
72 {
73  pprz_msg_send_VFF_EXTENDED(trans, dev, AC_ID,
75  &vff.z, &vff.zdot, &vff.zdotdot,
76  &vff.bias, &vff.offset);
77 }
78 #endif
79 
80 void vff_init_zero(void)
81 {
82  vff_init(0., 0., 0., 0.);
83 }
84 
85 void vff_init(float init_z, float init_zdot, float init_accel_bias, float init_baro_offset)
86 {
87  vff.z = init_z;
88  vff.zdot = init_zdot;
89  vff.bias = init_accel_bias;
90  vff.offset = init_baro_offset;
91  int i, j;
92  for (i = 0; i < VFF_STATE_SIZE; i++) {
93  for (j = 0; j < VFF_STATE_SIZE; j++) {
94  vff.P[i][j] = 0.;
95  }
96  vff.P[i][i] = VFF_EXTENDED_INIT_PXX;
97  }
98 
100  vff.r_baro = R_BARO;
101  vff.r_alt = R_ALT;
103 
104 #if PERIODIC_TELEMETRY
105  register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_VFF_EXTENDED, send_vffe);
106 #endif
107 }
108 
109 
132 void vff_propagate(float accel, float dt)
133 {
134  /* update state */
135  vff.zdotdot = accel + 9.81 - vff.bias;
136  vff.z = vff.z + dt * vff.zdot;
137  vff.zdot = vff.zdot + dt * vff.zdotdot;
138  /* update covariance */
139  const float FPF00 = vff.P[0][0] + dt * (vff.P[1][0] + vff.P[0][1] + dt * vff.P[1][1]);
140  const float FPF01 = vff.P[0][1] + dt * (vff.P[1][1] - vff.P[0][2] - dt * vff.P[1][2]);
141  const float FPF02 = vff.P[0][2] + dt * (vff.P[1][2]);
142  const float FPF10 = vff.P[1][0] + dt * (-vff.P[2][0] + vff.P[1][1] - dt * vff.P[2][1]);
143  const float FPF11 = vff.P[1][1] + dt * (-vff.P[2][1] - vff.P[1][2] + dt * vff.P[2][2]);
144  const float FPF12 = vff.P[1][2] + dt * (-vff.P[2][2]);
145  const float FPF20 = vff.P[2][0] + dt * (vff.P[2][1]);
146  const float FPF21 = vff.P[2][1] + dt * (-vff.P[2][2]);
147  const float FPF22 = vff.P[2][2];
148  const float FPF33 = vff.P[3][3];
149 
150  vff.P[0][0] = FPF00 + vff.accel_noise * dt * dt / 2.;
151  vff.P[0][1] = FPF01;
152  vff.P[0][2] = FPF02;
153  vff.P[1][0] = FPF10;
154  vff.P[1][1] = FPF11 + vff.accel_noise * dt;
155  vff.P[1][2] = FPF12;
156  vff.P[2][0] = FPF20;
157  vff.P[2][1] = FPF21;
158  vff.P[2][2] = FPF22 + Qbiasbias;
159  vff.P[3][3] = FPF33 + Qoffoff;
160 
161 #if DEBUG_VFF_EXTENDED
162  RunOnceEvery(10, send_vffe(&(DefaultChannel).trans_tx, &(DefaultDevice).device));
163 #endif
164 }
165 
181 static void update_baro_conf(float z_meas, float conf)
182 {
184 
185  const float y = z_meas - vff.z + vff.offset;
186  const float S = vff.P[0][0] - vff.P[0][3] - vff.P[3][0] + vff.P[3][3] + conf;
187  const float K0 = (vff.P[0][0] - vff.P[0][3]) * 1 / S;
188  const float K1 = (vff.P[1][0] - vff.P[1][3]) * 1 / S;
189  const float K2 = (vff.P[2][0] - vff.P[2][3]) * 1 / S;
190  const float K3 = (vff.P[3][0] - vff.P[3][3]) * 1 / S;
191 
192  vff.z = vff.z + K0 * y;
193  vff.zdot = vff.zdot + K1 * y;
194  vff.bias = vff.bias + K2 * y;
195  vff.offset = vff.offset + K3 * y;
196 
197  const float P0 = vff.P[0][0] - vff.P[3][0];
198  const float P1 = vff.P[0][1] - vff.P[3][1];
199  const float P2 = vff.P[0][2] - vff.P[3][2];
200  const float P3 = vff.P[0][3] - vff.P[3][3];
201 
202  vff.P[0][0] -= K0 * P0;
203  vff.P[0][1] -= K0 * P1;
204  vff.P[0][2] -= K0 * P2;
205  vff.P[0][3] -= K0 * P3;
206  vff.P[1][0] -= K1 * P0;
207  vff.P[1][1] -= K1 * P1;
208  vff.P[1][2] -= K1 * P2;
209  vff.P[1][3] -= K1 * P3;
210  vff.P[2][0] -= K2 * P0;
211  vff.P[2][1] -= K2 * P1;
212  vff.P[2][2] -= K2 * P2;
213  vff.P[2][3] -= K2 * P3;
214  vff.P[3][0] -= K3 * P0;
215  vff.P[3][1] -= K3 * P1;
216  vff.P[3][2] -= K3 * P2;
217  vff.P[3][3] -= K3 * P3;
218 
219 }
220 
222 {
223  update_baro_conf(z_meas, vff.r_baro);
224 }
225 
226 void vff_update_baro_conf(float z_meas, float conf)
227 {
228  update_baro_conf(z_meas, conf);
229 }
230 
245 static void update_alt_conf(float z_meas, float conf)
246 {
247  vff.z_meas = z_meas;
248 
249  const float y = z_meas - vff.z;
250  const float S = vff.P[0][0] + conf;
251  const float K0 = vff.P[0][0] * 1 / S;
252  const float K1 = vff.P[1][0] * 1 / S;
253  const float K2 = vff.P[2][0] * 1 / S;
254  const float K3 = vff.P[3][0] * 1 / S;
255 
256  vff.z = vff.z + K0 * y;
257  vff.zdot = vff.zdot + K1 * y;
258  vff.bias = vff.bias + K2 * y;
259  vff.offset = vff.offset + K3 * y;
260 
261  const float P0 = vff.P[0][0];
262  const float P1 = vff.P[0][1];
263  const float P2 = vff.P[0][2];
264  const float P3 = vff.P[0][3];
265 
266  vff.P[0][0] -= K0 * P0;
267  vff.P[0][1] -= K0 * P1;
268  vff.P[0][2] -= K0 * P2;
269  vff.P[0][3] -= K0 * P3;
270  vff.P[1][0] -= K1 * P0;
271  vff.P[1][1] -= K1 * P1;
272  vff.P[1][2] -= K1 * P2;
273  vff.P[1][3] -= K1 * P3;
274  vff.P[2][0] -= K2 * P0;
275  vff.P[2][1] -= K2 * P1;
276  vff.P[2][2] -= K2 * P2;
277  vff.P[2][3] -= K2 * P3;
278  vff.P[3][0] -= K3 * P0;
279  vff.P[3][1] -= K3 * P1;
280  vff.P[3][2] -= K3 * P2;
281  vff.P[3][3] -= K3 * P3;
282 }
283 
284 void vff_update_z(float z_meas)
285 {
286  update_alt_conf(z_meas, vff.r_alt);
287 }
288 
289 void vff_update_z_conf(float z_meas, float conf)
290 {
291  update_alt_conf(z_meas, conf);
292 }
293 
308 static void update_offset_conf(float offset, float conf)
309 {
310 
311  const float y = offset - vff.offset;
312  const float S = vff.P[3][3] + conf;
313  const float K0 = vff.P[0][3] * 1 / S;
314  const float K1 = vff.P[1][3] * 1 / S;
315  const float K2 = vff.P[2][3] * 1 / S;
316  const float K3 = vff.P[3][3] * 1 / S;
317 
318  vff.z = vff.z + K0 * y;
319  vff.zdot = vff.zdot + K1 * y;
320  vff.bias = vff.bias + K2 * y;
321  vff.offset = vff.offset + K3 * y;
322 
323  const float P0 = vff.P[3][0];
324  const float P1 = vff.P[3][1];
325  const float P2 = vff.P[3][2];
326  const float P3 = vff.P[3][3];
327 
328  vff.P[0][0] -= K0 * P0;
329  vff.P[0][1] -= K0 * P1;
330  vff.P[0][2] -= K0 * P2;
331  vff.P[0][3] -= K0 * P3;
332  vff.P[1][0] -= K1 * P0;
333  vff.P[1][1] -= K1 * P1;
334  vff.P[1][2] -= K1 * P2;
335  vff.P[1][3] -= K1 * P3;
336  vff.P[2][0] -= K2 * P0;
337  vff.P[2][1] -= K2 * P1;
338  vff.P[2][2] -= K2 * P2;
339  vff.P[2][3] -= K2 * P3;
340  vff.P[3][0] -= K3 * P0;
341  vff.P[3][1] -= K3 * P1;
342  vff.P[3][2] -= K3 * P2;
343  vff.P[3][3] -= K3 * P3;
344 }
345 
347 {
349 }
350 
351 
352 void vff_realign(float z_meas)
353 {
354  //vff.z = z_meas;
355  //vff.zdot = 0.;
356  //vff.offset = 0.;
357  vff_init(z_meas, 0., 0., 0.);
358 }
359 
360 /*
361  H = [0 1 0 0];
362  R = 0.1;
363  // state residual
364  yd = vzd - H * Xm;
365  // covariance residual
366  S = H*Pm*H' + R;
367  // kalman gain
368  K = Pm*H'*inv(S);
369  // update state
370  Xp = Xm + K*yd;
371  // update covariance
372  Pp = Pm - K*H*Pm;
373 */
374 static inline void update_vz_conf(float vz, float conf)
375 {
376  const float yd = vz - vff.zdot;
377  const float S = vff.P[1][1] + conf;
378  const float K0 = vff.P[0][1] * 1 / S;
379  const float K1 = vff.P[1][1] * 1 / S;
380  const float K2 = vff.P[2][1] * 1 / S;
381  const float K3 = vff.P[3][1] * 1 / S;
382 
383  vff.z = vff.z + K0 * yd;
384  vff.zdot = vff.zdot + K1 * yd;
385  vff.bias = vff.bias + K2 * yd;
386  vff.offset = vff.offset + K3 * yd;
387 
388  const float P0 = vff.P[1][0];
389  const float P1 = vff.P[1][1];
390  const float P2 = vff.P[1][2];
391  const float P3 = vff.P[1][3];
392 
393  vff.P[0][0] -= K0 * P0;
394  vff.P[0][1] -= K0 * P1;
395  vff.P[0][2] -= K0 * P2;
396  vff.P[0][3] -= K0 * P3;
397  vff.P[1][0] -= K1 * P0;
398  vff.P[1][1] -= K1 * P1;
399  vff.P[1][2] -= K1 * P2;
400  vff.P[1][3] -= K1 * P3;
401  vff.P[2][0] -= K2 * P0;
402  vff.P[2][1] -= K2 * P1;
403  vff.P[2][2] -= K2 * P2;
404  vff.P[2][3] -= K2 * P3;
405  vff.P[3][0] -= K3 * P0;
406  vff.P[3][1] -= K3 * P1;
407  vff.P[3][2] -= K3 * P2;
408  vff.P[3][3] -= K3 * P3;
409 }
410 
411 void vff_update_vz_conf(float vz_meas, float conf)
412 {
413  update_vz_conf(vz_meas, conf);
414 }
#define VFF_EXTENDED_ACCEL_NOISE
process noise covariance Q
static void update_baro_conf(float z_meas, float conf)
Update sensor "with" offset (baro).
#define K0
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
#define VFF_EXTENDED_INIT_PXX
initial covariance diagonal
float P[VFF_STATE_SIZE][VFF_STATE_SIZE]
covariance matrix
void vff_update_z_conf(float z_meas, float conf)
Interface for extended vertical filter (in float).
Periodic telemetry system header (includes downlink utility and generated code).
#define R_BARO
float bias
accel bias estimate in m/s^2
void vff_update_vz_conf(float vz_meas, float conf)
float z
z-position estimate in m (NED, z-down)
static void update_vz_conf(float vz, float conf)
static void send_vffe(struct transport_tx *trans, struct link_device *dev)
static void update_offset_conf(float offset, float conf)
Update sensor offset (baro).
static const float offset[]
void vff_update_z(float z_meas)
#define VFF_STATE_SIZE
void vff_update_baro_conf(float z_meas, float conf)
static void update_alt_conf(float z_meas, float conf)
Update sensor "without" offset (gps, sonar) H = [1 0 0 0]; // state residual y = rangemeter - H * Xm;...
float offset
baro offset estimate
void vff_update_offset(float offset)
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
void vff_init_zero(void)
float zdotdot
z-acceleration in m/s^2 (NED, z-down)
void vff_propagate(float accel, float dt)
Propagate the filter in time.
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:73
void vff_realign(float z_meas)
#define Qoffoff
float z_meas
last z measurement in m
struct VffExtended vff
float zdot
z-velocity estimate in m/s (NED, z-down)
#define R_ALT
#define R_OFFSET
void vff_update_baro(float z_meas)
float z_meas_baro
last z measurement from baro in m
void vff_init(float init_z, float init_zdot, float init_accel_bias, float init_baro_offset)
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition: telemetry.c:46
#define Qbiasbias
#define DEBUG_VFF_EXTENDED