EKF: test new derivation

Use direct attitude parameterisation
Discard scale factors
Add accel bias
This commit is contained in:
Paul Riseborough
2016-05-05 21:23:03 +10:00
parent 22d18d638c
commit fe9f88a8b4
12 changed files with 928 additions and 1498 deletions
+46 -41
View File
@@ -108,11 +108,11 @@ void Ekf::resetHeight()
_state.pos(2) = new_pos_down;
// reset the associated covariance values
zeroRows(P, 8, 8);
zeroCols(P, 8, 8);
zeroRows(P, 9, 9);
zeroCols(P, 9, 9);
// the state variance is the same as the observation
P[8][8] = sq(_params.range_noise);
P[9][9] = sq(_params.range_noise);
vert_pos_reset = true;
@@ -132,11 +132,11 @@ void Ekf::resetHeight()
_state.pos(2) = _hgt_sensor_offset - baro_newest.hgt + _baro_hgt_offset;
// reset the associated covariance values
zeroRows(P, 8, 8);
zeroCols(P, 8, 8);
zeroRows(P, 9, 9);
zeroCols(P, 9, 9);
// the state variance is th esame as the observation
P[8][8] = sq(_params.baro_noise);
P[9][9] = sq(_params.baro_noise);
vert_pos_reset = true;
@@ -150,11 +150,11 @@ void Ekf::resetHeight()
_state.pos(2) = _hgt_sensor_offset - gps_newest.hgt + _gps_alt_ref;
// reset the associated covarince values
zeroRows(P, 8, 8);
zeroCols(P, 8, 8);
zeroRows(P, 9, 9);
zeroCols(P, 9, 9);
// the state variance is the same as the observation
P[8][8] = sq(gps_newest.hacc);
P[9][9] = sq(gps_newest.hacc);
vert_pos_reset = true;
@@ -168,8 +168,8 @@ void Ekf::resetHeight()
}
// reset the vertical velocity covariance values
zeroRows(P, 5, 5);
zeroCols(P, 5, 5);
zeroRows(P, 6, 6);
zeroCols(P, 6, 6);
// reset the vertical velocity state
if (_control_status.flags.gps && (_time_last_imu - gps_newest.time_us < 2 * GPS_MAX_INTERVAL)) {
@@ -177,7 +177,7 @@ void Ekf::resetHeight()
_state.vel(2) = gps_newest.vel(2);
// the state variance is the same as the observation
P[5][5] = sq(1.5f * gps_newest.sacc);
P[6][6] = sq(1.5f * gps_newest.sacc);
} else {
// we don't know what the vertical velocity is, so set it to zero
@@ -185,7 +185,7 @@ void Ekf::resetHeight()
// Set the variance to a value large enough to allow the state to converge quickly
// that does not destabilise the filter
P[5][5] = fminf(sq(_state.vel(2)),100.0f);
P[6][6] = fminf(sq(_state.vel(2)),100.0f);
}
vert_vel_reset = true;
@@ -248,11 +248,11 @@ bool Ekf::resetMagHeading(Vector3f &mag_init)
// we don't change the output attitude to avoid jumps
_state.quat_nominal = Quaternion(euler_init);
// reset the angle error variances because the yaw angle could have changed by a significant amount
// reset the quaternion variances because the yaw angle could have changed by a significant amount
// by setting them to zero we avoid 'kicks' in angle when 3-D fusion starts and the imu process noise
// will grow them again.
zeroRows(P, 0, 2);
zeroCols(P, 0, 2);
zeroRows(P, 0, 3);
zeroCols(P, 0, 3);
// calculate initial earth magnetic field states
matrix::Dcm<float> R_to_earth(euler_init);
@@ -305,8 +305,8 @@ void Ekf::makeSymmetrical()
void Ekf::constrainStates()
{
for (int i = 0; i < 3; i++) {
_state.ang_error(i) = math::constrain(_state.ang_error(i), -1.0f, 1.0f);
for (int i = 0; i < 4; i++) {
_state.quat_nominal(i) = math::constrain(_state.quat_nominal(i), -1.0f, 1.0f);
}
for (int i = 0; i < 3; i++) {
@@ -322,11 +322,9 @@ void Ekf::constrainStates()
}
for (int i = 0; i < 3; i++) {
_state.gyro_scale(i) = math::constrain(_state.gyro_scale(i), 0.95f, 1.05f);
_state.accel_bias(i) = math::constrain(_state.accel_bias(i), -1.0f * _dt_imu_avg, 1.0f * _dt_imu_avg);
}
_state.accel_z_bias = math::constrain(_state.accel_z_bias, -1.0f * _dt_imu_avg, 1.0f * _dt_imu_avg);
for (int i = 0; i < 3; i++) {
_state.mag_I(i) = math::constrain(_state.mag_I(i), -1.0f, 1.0f);
}
@@ -407,28 +405,26 @@ void Ekf::get_gps_check_status(uint16_t *val)
// get the state vector at the delayed time horizon
void Ekf::get_state_delayed(float *state)
{
for (int i = 0; i < 3; i++) {
state[i] = _state.ang_error(i);
for (int i = 0; i < 4; i++) {
state[i] = _state.quat_nominal(i);
}
for (int i = 0; i < 3; i++) {
state[i + 3] = _state.vel(i);
state[i + 4] = _state.vel(i);
}
for (int i = 0; i < 3; i++) {
state[i + 6] = _state.pos(i);
state[i + 7] = _state.pos(i);
}
for (int i = 0; i < 3; i++) {
state[i + 9] = _state.gyro_bias(i);
state[i + 10] = _state.gyro_bias(i);
}
for (int i = 0; i < 3; i++) {
state[i + 12] = _state.gyro_scale(i);
state[i + 13] = _state.accel_bias(i);
}
state[15] = _state.accel_z_bias;
for (int i = 0; i < 3; i++) {
state[i + 16] = _state.mag_I(i);
}
@@ -442,6 +438,16 @@ void Ekf::get_state_delayed(float *state)
}
}
// get the accelerometer bias
void Ekf::get_accel_bias(float bias[3])
{
float temp[3];
temp[0] = _state.accel_bias(0) /_dt_ekf_avg;
temp[1] = _state.accel_bias(1) /_dt_ekf_avg;
temp[2] = _state.accel_bias(2) /_dt_ekf_avg;
memcpy(bias, temp, 3 * sizeof(float));
}
// get the diagonal elements of the covariance matrix
void Ekf::get_covariances(float *covariances)
{
@@ -463,8 +469,8 @@ void Ekf::get_ekf_accuracy(float *ekf_eph, float *ekf_epv, bool *dead_reckoning)
{
// report absolute accuracy taking into account the uncertainty in location of the origin
// TODO we a need a way to allow for baro drift error
float temp1 = sqrtf(P[6][6] + P[7][7] + sq(_gps_origin_eph));
float temp2 = sqrtf(P[8][8] + sq(_gps_origin_epv));
float temp1 = sqrtf(P[7][7] + P[8][8] + sq(_gps_origin_eph));
float temp2 = sqrtf(P[9][9] + sq(_gps_origin_epv));
memcpy(ekf_eph, &temp1, sizeof(float));
memcpy(ekf_epv, &temp2, sizeof(float));
@@ -476,28 +482,27 @@ void Ekf::get_ekf_accuracy(float *ekf_eph, float *ekf_epv, bool *dead_reckoning)
// fuse measurement
void Ekf::fuse(float *K, float innovation)
{
for (unsigned i = 0; i < 4; i++) {
_state.quat_nominal(i) = _state.quat_nominal(i) - K[i] * innovation;
}
_state.quat_nominal.normalize();
for (unsigned i = 0; i < 3; i++) {
_state.ang_error(i) = _state.ang_error(i) - K[i] * innovation;
_state.vel(i) = _state.vel(i) - K[i + 4] * innovation;
}
for (unsigned i = 0; i < 3; i++) {
_state.vel(i) = _state.vel(i) - K[i + 3] * innovation;
_state.pos(i) = _state.pos(i) - K[i + 7] * innovation;
}
for (unsigned i = 0; i < 3; i++) {
_state.pos(i) = _state.pos(i) - K[i + 6] * innovation;
_state.gyro_bias(i) = _state.gyro_bias(i) - K[i + 10] * innovation;
}
for (unsigned i = 0; i < 3; i++) {
_state.gyro_bias(i) = _state.gyro_bias(i) - K[i + 9] * innovation;
_state.accel_bias(i) = _state.accel_bias(i) - K[i + 13] * innovation;
}
for (unsigned i = 0; i < 3; i++) {
_state.gyro_scale(i) = _state.gyro_scale(i) - K[i + 12] * innovation;
}
_state.accel_z_bias -= K[15] * innovation;
for (unsigned i = 0; i < 3; i++) {
_state.mag_I(i) = _state.mag_I(i) - K[i + 16] * innovation;
}