Skip to content

Commit 319a7d1

Browse files
f5sohfilnet
authored andcommitted
Merged in f5soh/librepilot/LP-482_Mag_Kp (pull request #439)
LP-482 Mag Kp + LP-534 Mag source EKF Approved-by: Alessio Morale <alessiomorale@gmail.com> Approved-by: Philippe Renon <philippe_renon@yahoo.fr> Approved-by: Lalanne Laurent <f5soh@free.fr> Approved-by: Brian Webb <webbbn@gmail.com>
2 parents 726c882 + 1b624d7 commit 319a7d1

3 files changed

Lines changed: 40 additions & 25 deletions

File tree

flight/modules/StateEstimation/filtercf.c

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
* @{
88
*
99
* @file filtercf.c
10-
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
10+
* @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
11+
* The OpenPilot Team, http://www.openpilot.org Copyright (C) 2013.
1112
* @brief Complementary filter to calculate Attitude from Accels and Gyros
1213
* and optionally magnetometers:
1314
* WARNING: Will drift if the mean acceleration force doesn't point
@@ -49,7 +50,14 @@
4950

5051
#define CALIBRATION_DELAY_MS 4000
5152
#define CALIBRATION_DURATION_MS 6000
53+
#define RELOADSETTINGS_DELAY_MS 1000
54+
#define CONVERGENCE_MAGKP 20.0f
5255
#define VARIANCE_WINDOW_SIZE 40
56+
57+
#define UNDONE 0
58+
#define DONE 1
59+
#define RUN 2
60+
5361
// Private types
5462
struct data {
5563
AttitudeSettingsData attitudeSettings;
@@ -68,6 +76,7 @@ struct data {
6876
float rollPitchBiasRate;
6977
int32_t timeval;
7078
int32_t starttime;
79+
int32_t inittime;
7180
uint8_t init;
7281
bool magCalibrated;
7382
pw_variance_t gyro_var[3];
@@ -248,7 +257,7 @@ static filterResult complementaryFilter(struct data *this, float gyro[3], float
248257

249258
AttitudeStateData attitudeState; // base on previous state
250259
AttitudeStateGet(&attitudeState);
251-
this->init = 0;
260+
this->init = UNDONE;
252261

253262
// Set initial attitude. Use accels to determine roll and pitch, rotate magnetic measurement accordingly,
254263
// so pseudo "north" vector can be estimated even if the board is not level
@@ -288,7 +297,7 @@ static filterResult complementaryFilter(struct data *this, float gyro[3], float
288297
return FILTERRESULT_OK; // must return OK on initial initialization, so attitude will init with a valid quaternion
289298
}
290299
// check whether copter is steady
291-
if (this->init == 0 && this->attitudeSettings.InitialZeroWhenBoardSteady == ATTITUDESETTINGS_INITIALZEROWHENBOARDSTEADY_TRUE) {
300+
if (this->init == UNDONE && this->attitudeSettings.InitialZeroWhenBoardSteady == ATTITUDESETTINGS_INITIALZEROWHENBOARDSTEADY_TRUE) {
292301
pseudo_windowed_variance_push_sample(&this->gyro_var[0], gyro[0]);
293302
pseudo_windowed_variance_push_sample(&this->gyro_var[1], gyro[1]);
294303
pseudo_windowed_variance_push_sample(&this->gyro_var[2], gyro[2]);
@@ -304,36 +313,40 @@ static filterResult complementaryFilter(struct data *this, float gyro[3], float
304313
}
305314

306315

307-
if (this->init == 0 && xTaskGetTickCount() - this->starttime < CALIBRATION_DELAY_MS / portTICK_RATE_MS) {
316+
if (this->init == UNDONE && xTaskGetTickCount() - this->starttime < CALIBRATION_DELAY_MS / portTICK_RATE_MS) {
308317
// wait 4 seconds for the user to get his hands off in case the board was just powered
309318
this->timeval = PIOS_DELAY_GetRaw();
310319
return FILTERRESULT_ERROR;
311-
} else if (this->init == 0 && xTaskGetTickCount() - this->starttime < (CALIBRATION_DELAY_MS + CALIBRATION_DURATION_MS) / portTICK_RATE_MS) {
320+
} else if (this->init == UNDONE && xTaskGetTickCount() - this->starttime < (CALIBRATION_DELAY_MS + CALIBRATION_DURATION_MS) / portTICK_RATE_MS) {
312321
// For first 6 seconds use accels to get gyro bias
313322
this->attitudeSettings.AccelKp = 1.0f;
314323
this->attitudeSettings.AccelKi = 0.0f;
315324
this->attitudeSettings.YawBiasRate = 0.23f;
316325
this->accel_filter_enabled = false;
317326
this->rollPitchBiasRate = 0.01f;
318-
this->attitudeSettings.MagKp = this->magCalibrated ? 1.0f : 0.0f;
327+
this->attitudeSettings.MagKp = this->magCalibrated ? CONVERGENCE_MAGKP : 0.0f;
319328
PIOS_NOTIFY_StartNotification(NOTIFY_DRAW_ATTENTION, NOTIFY_PRIORITY_REGULAR);
320329
} else if ((this->attitudeSettings.ZeroDuringArming == ATTITUDESETTINGS_ZERODURINGARMING_TRUE) && (flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMING)) {
321330
this->attitudeSettings.AccelKp = 1.0f;
322331
this->attitudeSettings.AccelKi = 0.0f;
323332
this->attitudeSettings.YawBiasRate = 0.23f;
324333
this->accel_filter_enabled = false;
325334
this->rollPitchBiasRate = 0.01f;
326-
this->attitudeSettings.MagKp = this->magCalibrated ? 1.0f : 0.0f;
327-
this->init = 0;
335+
this->attitudeSettings.MagKp = this->magCalibrated ? CONVERGENCE_MAGKP : 0.0f;
336+
this->init = UNDONE;
328337
PIOS_NOTIFY_StartNotification(NOTIFY_DRAW_ATTENTION, NOTIFY_PRIORITY_REGULAR);
329-
} else if (this->init == 0) {
330-
// Reload settings (all the rates)
331-
AttitudeSettingsGet(&this->attitudeSettings);
338+
} else if (this->init == UNDONE) {
332339
this->rollPitchBiasRate = 0.0f;
333340
if (this->accel_alpha > 0.0f) {
334341
this->accel_filter_enabled = true;
335342
}
336-
this->init = 1;
343+
this->inittime = xTaskGetTickCount();
344+
this->init = DONE;
345+
// Allow running filter with custom MagKp for some time before reload settings
346+
} else if (this->init == DONE && (!this->magCalibrated || (xTaskGetTickCount() - this->inittime > RELOADSETTINGS_DELAY_MS / portTICK_RATE_MS))) {
347+
// Reload settings (all the rates)
348+
AttitudeSettingsGet(&this->attitudeSettings);
349+
this->init = RUN;
337350
}
338351

339352
// Compute the dT using the cpu clock
@@ -423,7 +436,7 @@ static filterResult complementaryFilter(struct data *this, float gyro[3], float
423436
this->gyroBias[0] -= accel_err[0] * this->attitudeSettings.AccelKi - gyro[0] * this->rollPitchBiasRate;
424437
this->gyroBias[1] -= accel_err[1] * this->attitudeSettings.AccelKi - gyro[1] * this->rollPitchBiasRate;
425438
if (this->useMag) {
426-
this->gyroBias[2] -= -mag_err[2] * this->attitudeSettings.MagKi - gyro[2] * this->rollPitchBiasRate;
439+
this->gyroBias[2] -= mag_err[2] * this->attitudeSettings.MagKi - gyro[2] * this->rollPitchBiasRate;
427440
} else {
428441
this->gyroBias[2] -= -gyro[2] * this->rollPitchBiasRate;
429442
}
@@ -473,7 +486,7 @@ static filterResult complementaryFilter(struct data *this, float gyro[3], float
473486
return FILTERRESULT_WARNING;
474487
}
475488

476-
if (this->init) {
489+
if (this->init != UNDONE) {
477490
return FILTERRESULT_OK;
478491
} else {
479492
return FILTERRESULT_CRITICAL; // return "critical" for now, so users can see the zeroing period, switch to more graceful notification later

flight/modules/StateEstimation/filterekf.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,6 @@ static filterResult filter(stateFilter *self, stateEstimation *state)
223223
UNSET_MASK(state->updated, SENSORUPDATES_vel);
224224
UNSET_MASK(state->updated, SENSORUPDATES_attitude);
225225
UNSET_MASK(state->updated, SENSORUPDATES_gyro);
226-
UNSET_MASK(state->updated, SENSORUPDATES_mag);
227226
return FILTERRESULT_OK;
228227
}
229228

@@ -387,15 +386,18 @@ static filterResult filter(stateFilter *self, stateEstimation *state)
387386
local_down[2] *= MagStrength;
388387
rot_mult(R, local_down, this->work.mag);
389388
}
389+
// From Eric: "exporting it in MagState was meant for debugging, but I think it makes a
390+
// lot of sense to have a "corrected" magnetometer reading available in the system."
391+
// TODO: Should move above calc to filtermag, updating from here cause trouble with the state->MagStatus (LP-534)
390392
// debug rotated mags
391-
state->mag[0] = this->work.mag[0];
392-
state->mag[1] = this->work.mag[1];
393-
state->mag[2] = this->work.mag[2];
394-
state->updated |= SENSORUPDATES_mag;
395-
} else {
396-
// mag state is delayed until EKF processed it, allows overriding/debugging magnetometer estimate
397-
UNSET_MASK(state->updated, SENSORUPDATES_mag);
398-
}
393+
// state->mag[0] = this->work.mag[0];
394+
// state->mag[1] = this->work.mag[1];
395+
// state->mag[2] = this->work.mag[2];
396+
// state->updated |= SENSORUPDATES_mag;
397+
} // else {
398+
// mag state is delayed until EKF processed it, allows overriding/debugging magnetometer estimate
399+
// UNSET_MASK(state->updated, SENSORUPDATES_mag);
400+
// }
399401

400402
if (IS_SET(this->work.updated, SENSORUPDATES_baro)) {
401403
sensors |= BARO_SENSOR;

shared/uavobjectdefinition/attitudesettings.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
<field name="BoardLevelTrim" units="deg" type="float" elementnames="Roll,Pitch" defaultvalue="0,0"/>
66
<field name="AccelKp" units="channel" type="float" elements="1" defaultvalue="0.05"/>
77
<field name="AccelKi" units="channel" type="float" elements="1" defaultvalue="0.0001"/>
8-
<field name="MagKi" units="" type="float" elements="1" defaultvalue="0.000001"/>
9-
<field name="MagKp" units="" type="float" elements="1" defaultvalue="0.01"/>
8+
<field name="MagKi" units="" type="float" elements="1" defaultvalue="0.00005"/>
9+
<field name="MagKp" units="" type="float" elements="1" defaultvalue="1.0"/>
1010
<field name="AccelTau" units="" type="float" elements="1" defaultvalue="0.05"/>
1111
<field name="YawBiasRate" units="channel" type="float" elements="1" defaultvalue="0.000001"/>
1212
<field name="ZeroDuringArming" units="channel" type="enum" elements="1" options="False,True" defaultvalue="True"/>

0 commit comments

Comments
 (0)