2 ******************************************************************************
3 * @addtogroup OpenPilotModules OpenPilot Modules
5 * @addtogroup State Estimation
6 * @brief Acquires sensor data and computes state estimate
9 * @file filteraltitude.c
10 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
11 * @brief Barometric altitude filter, calculates vertical speed and true
12 * altitude based on Barometric altitude and accelerometers
14 * @see The GNU Public License (GPL) Version 3
16 ******************************************************************************/
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 3 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28 * You should have received a copy of the GNU General Public License along
29 * with this program; if not, write to the Free Software Foundation, Inc.,
30 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include "inc/stateestimation.h"
34 #include <attitudestate.h>
35 #include <altitudefiltersettings.h>
36 #include <homelocation.h>
38 #include <CoordinateConversions.h>
42 // duration of accel bias initialization phase
43 #define INITIALIZATION_DURATION_MS 5000
45 #define STACK_REQUIRED 128
47 #define DT_ALPHA 1e-2f
50 #define DT_AVERAGE 1e-3f
51 static volatile bool reloadSettings
;
55 float altitudeState
; // state = altitude,velocity,accel_offset,accel
59 float pos
[3]; // position updates from other filters
60 float vel
[3]; // position updates from other filters
62 PiOSDeltatimeConfig dt1config
;
63 PiOSDeltatimeConfig dt2config
;
67 portTickType initTimer
;
68 AltitudeFilterSettingsData settings
;
76 static int32_t init(stateFilter
*self
);
77 static filterResult
filter(stateFilter
*self
, stateEstimation
*state
);
78 static void settingsUpdatedCb(UAVObjEvent
*ev
);
81 int32_t filterAltitudeInitialize(stateFilter
*handle
)
84 handle
->filter
= &filter
;
85 handle
->localdata
= pios_malloc(sizeof(struct data
));
86 AttitudeStateInitialize();
87 AltitudeFilterSettingsConnectCallback(&settingsUpdatedCb
);
88 reloadSettings
= true;
89 return STACK_REQUIRED
;
92 static int32_t init(stateFilter
*self
)
94 struct data
*this = (struct data
*)self
->localdata
;
96 this->altitudeState
= 0.0f
;
97 this->velocityState
= 0.0f
;
98 this->accelBiasState
= 0.0f
;
99 this->accelState
= 0.0f
;
106 PIOS_DELTATIME_Init(&this->dt1config
, DT_AVERAGE
, DT_MIN
, DT_MAX
, DT_ALPHA
);
107 PIOS_DELTATIME_Init(&this->dt2config
, DT_AVERAGE
, DT_MIN
, DT_MAX
, DT_ALPHA
);
108 this->baroLast
= 0.0f
;
109 this->accelLast
= 0.0f
;
111 HomeLocationg_eGet(&this->gravity
);
115 static filterResult
filter(stateFilter
*self
, stateEstimation
*state
)
117 struct data
*this = (struct data
*)self
->localdata
;
119 if (reloadSettings
) {
120 reloadSettings
= false;
121 AltitudeFilterSettingsGet(&this->settings
);
124 if (this->first_run
) {
125 // Initialize to current altitude reading at initial location
126 if (IS_SET(state
->updated
, SENSORUPDATES_baro
)) {
128 this->initTimer
= xTaskGetTickCount();
131 // save existing position and velocity updates so GPS will still work
132 if (IS_SET(state
->updated
, SENSORUPDATES_pos
)) {
133 this->pos
[0] = state
->pos
[0];
134 this->pos
[1] = state
->pos
[1];
135 this->pos
[2] = state
->pos
[2];
136 state
->pos
[2] = -this->altitudeState
;
138 if (IS_SET(state
->updated
, SENSORUPDATES_vel
)) {
139 this->vel
[0] = state
->vel
[0];
140 this->vel
[1] = state
->vel
[1];
141 this->vel
[2] = state
->vel
[2];
142 state
->vel
[2] = -this->velocityState
;
144 if (IS_SET(state
->updated
, SENSORUPDATES_accel
)) {
145 // rotate accels into global coordinate frame
146 AttitudeStateData att
;
147 AttitudeStateGet(&att
);
149 Quaternion2R(&att
.q1
, Rbe
);
150 float current
= -(Rbe
[0][2] * state
->accel
[0] + Rbe
[1][2] * state
->accel
[1] + Rbe
[2][2] * state
->accel
[2] + this->gravity
);
152 // low pass filter accelerometers
153 this->accelState
= (1.0f
- this->settings
.AccelLowPassKp
) * this->accelState
+ this->settings
.AccelLowPassKp
* current
;
154 if (((xTaskGetTickCount() - this->initTimer
) / portTICK_RATE_MS
) < INITIALIZATION_DURATION_MS
) {
155 // allow the offset to reach quickly the target value in case of small AccelDriftKi
156 this->accelBiasState
= (1.0f
- this->settings
.InitializationAccelDriftKi
) * this->accelBiasState
+ this->settings
.InitializationAccelDriftKi
* this->accelState
;
158 // correct accel offset (low pass zeroing)
159 this->accelBiasState
= (1.0f
- this->settings
.AccelDriftKi
) * this->accelBiasState
+ this->settings
.AccelDriftKi
* this->accelState
;
161 // correct velocity and position state (integration)
162 // low pass for average dT, compensate timing jitter from scheduler
164 float dT
= PIOS_DELTATIME_GetAverageSeconds(&this->dt1config
);
165 float speedLast
= this->velocityState
;
167 this->velocityState
+= 0.5f
* (this->accelLast
+ (this->accelState
- this->accelBiasState
)) * dT
;
168 this->accelLast
= this->accelState
- this->accelBiasState
;
170 this->altitudeState
+= 0.5f
* (speedLast
+ this->velocityState
) * dT
;
173 state
->pos
[0] = this->pos
[0];
174 state
->pos
[1] = this->pos
[1];
175 state
->pos
[2] = -this->altitudeState
;
176 state
->updated
|= SENSORUPDATES_pos
;
178 state
->vel
[0] = this->vel
[0];
179 state
->vel
[1] = this->vel
[1];
180 state
->vel
[2] = -this->velocityState
;
181 state
->updated
|= SENSORUPDATES_vel
;
183 if (IS_SET(state
->updated
, SENSORUPDATES_baro
)) {
184 // correct the altitude state (simple low pass)
185 this->altitudeState
= (1.0f
- this->settings
.BaroKp
) * this->altitudeState
+ this->settings
.BaroKp
* state
->baro
[0];
187 // correct the velocity state (low pass differentiation)
188 // low pass for average dT, compensate timing jitter from scheduler
189 float dT
= PIOS_DELTATIME_GetAverageSeconds(&this->dt2config
);
190 this->velocityState
= (1.0f
- (this->settings
.BaroKp
* this->settings
.BaroKp
)) * this->velocityState
+ (this->settings
.BaroKp
* this->settings
.BaroKp
) * (state
->baro
[0] - this->baroLast
) / dT
;
191 this->baroLast
= state
->baro
[0];
193 state
->pos
[0] = this->pos
[0];
194 state
->pos
[1] = this->pos
[1];
195 state
->pos
[2] = -this->altitudeState
;
196 state
->updated
|= SENSORUPDATES_pos
;
198 state
->vel
[0] = this->vel
[0];
199 state
->vel
[1] = this->vel
[1];
200 state
->vel
[2] = -this->velocityState
;
201 state
->updated
|= SENSORUPDATES_vel
;
205 return FILTERRESULT_OK
;
208 void settingsUpdatedCb(UAVObjEvent
*ev
)
210 if (ev
->obj
== AltitudeFilterSettingsHandle()) {
211 reloadSettings
= true;