mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-24 12:33:33 +08:00
Make covariance matrices of type matrix::SquareMatrix
and use functions from Matrix to reset covariances.
This commit is contained in:
committed by
Paul Riseborough
parent
a4a694dd87
commit
459b76f9fd
+74
-203
@@ -59,7 +59,7 @@ bool Ekf::resetVelocity()
|
||||
_state.vel = _gps_sample_delayed.vel;
|
||||
|
||||
// use GPS accuracy to reset variances
|
||||
setDiag(P, 4, 6, sq(_gps_sample_delayed.sacc));
|
||||
P.uncorrelateCovarianceSetVariance<3>(4, sq(_gps_sample_delayed.sacc));
|
||||
|
||||
} else if (_control_status.flags.opt_flow) {
|
||||
ECL_INFO_TIMESTAMPED("reset velocity to flow");
|
||||
@@ -90,28 +90,23 @@ bool Ekf::resetVelocity()
|
||||
_state.vel(1) = 0.0f;
|
||||
}
|
||||
|
||||
// reset the velocity covariance terms
|
||||
zeroRows(P, 4, 5);
|
||||
zeroCols(P, 4, 5);
|
||||
|
||||
// reset the horizontal velocity variance using the optical flow noise variance
|
||||
P[5][5] = P[4][4] = sq(range) * calcOptFlowMeasVar();
|
||||
P.uncorrelateCovarianceSetVariance<2>(4, sq(range) * calcOptFlowMeasVar());
|
||||
|
||||
} else if (_control_status.flags.ev_vel) {
|
||||
ECL_INFO_TIMESTAMPED("reset velocity to ev velocity");
|
||||
Vector3f _ev_vel = _ev_sample_delayed.vel;
|
||||
if(_params.fusion_mode & MASK_ROTATE_EV){
|
||||
_ev_vel = _ev_rot_mat *_ev_sample_delayed.vel;
|
||||
}
|
||||
_state.vel(0) = _ev_vel(0);
|
||||
_state.vel(1) = _ev_vel(1);
|
||||
_state.vel(2) = _ev_vel(2);
|
||||
setDiag(P, 4, 6, sq(_ev_sample_delayed.velErr));
|
||||
_state.vel = _ev_vel;
|
||||
P.uncorrelateCovarianceSetVariance<3>(4, sq(_ev_sample_delayed.velErr));
|
||||
} else {
|
||||
ECL_INFO_TIMESTAMPED("reset velocity to zero");
|
||||
// Used when falling back to non-aiding mode of operation
|
||||
_state.vel(0) = 0.0f;
|
||||
_state.vel(1) = 0.0f;
|
||||
setDiag(P, 4, 5, 25.0f);
|
||||
P.uncorrelateCovarianceSetVariance<2>(4, 25.0f);
|
||||
}
|
||||
|
||||
// calculate the change in velocity and apply to the output predictor state history
|
||||
@@ -156,7 +151,7 @@ bool Ekf::resetPosition()
|
||||
_state.pos(1) = _gps_sample_delayed.pos(1);
|
||||
|
||||
// use GPS accuracy to reset variances
|
||||
setDiag(P, 7, 8, sq(_gps_sample_delayed.hacc));
|
||||
P.uncorrelateCovarianceSetVariance<2>(7, sq(_gps_sample_delayed.hacc));
|
||||
|
||||
} else if (_control_status.flags.ev_pos) {
|
||||
ECL_INFO_TIMESTAMPED("reset position to ev position");
|
||||
@@ -170,7 +165,7 @@ bool Ekf::resetPosition()
|
||||
_state.pos(1) = _ev_pos(1);
|
||||
|
||||
// use EV accuracy to reset variances
|
||||
setDiag(P, 7, 8, sq(_ev_sample_delayed.posErr));
|
||||
P.uncorrelateCovarianceSetVariance<2>(7, sq(_ev_sample_delayed.posErr));
|
||||
|
||||
} else if (_control_status.flags.opt_flow) {
|
||||
ECL_INFO_TIMESTAMPED("reset position to last known position");
|
||||
@@ -188,15 +183,14 @@ bool Ekf::resetPosition()
|
||||
}
|
||||
|
||||
// estimate is relative to initial position in this mode, so we start with zero error.
|
||||
zeroCols(P,7,8);
|
||||
zeroRows(P,7,8);
|
||||
P.uncorrelateCovarianceSetVariance<2>(7, 0.0f);
|
||||
|
||||
} else {
|
||||
ECL_INFO_TIMESTAMPED("reset position to last known position");
|
||||
// Used when falling back to non-aiding mode of operation
|
||||
_state.pos(0) = _last_known_posNE(0);
|
||||
_state.pos(1) = _last_known_posNE(1);
|
||||
setDiag(P, 7, 8, sq(_params.pos_noaid_noise));
|
||||
P.uncorrelateCovarianceSetVariance<2>(7, sq(_params.pos_noaid_noise));
|
||||
}
|
||||
|
||||
// calculate the change in position and apply to the output predictor state history
|
||||
@@ -239,12 +233,8 @@ void Ekf::resetHeight()
|
||||
// update the state and associated variance
|
||||
_state.pos(2) = new_pos_down;
|
||||
|
||||
// reset the associated covariance values
|
||||
zeroRows(P, 9, 9);
|
||||
zeroCols(P, 9, 9);
|
||||
|
||||
// the state variance is the same as the observation
|
||||
P[9][9] = sq(_params.range_noise);
|
||||
P.uncorrelateCovarianceSetVariance<1>(9, sq(_params.range_noise));
|
||||
|
||||
vert_pos_reset = true;
|
||||
|
||||
@@ -259,12 +249,8 @@ void Ekf::resetHeight()
|
||||
if (_time_last_imu - baro_newest.time_us < 2 * BARO_MAX_INTERVAL) {
|
||||
_state.pos(2) = _hgt_sensor_offset - baro_newest.hgt + _baro_hgt_offset;
|
||||
|
||||
// reset the associated covariance values
|
||||
zeroRows(P, 9, 9);
|
||||
zeroCols(P, 9, 9);
|
||||
|
||||
// the state variance is the same as the observation
|
||||
P[9][9] = sq(_params.baro_noise);
|
||||
P.uncorrelateCovarianceSetVariance<1>(9, sq(_params.baro_noise));
|
||||
|
||||
vert_pos_reset = true;
|
||||
|
||||
@@ -277,12 +263,8 @@ void Ekf::resetHeight()
|
||||
if (_time_last_imu - gps_newest.time_us < 2 * GPS_MAX_INTERVAL) {
|
||||
_state.pos(2) = _hgt_sensor_offset - gps_newest.hgt + _gps_alt_ref;
|
||||
|
||||
// reset the associated covariance values
|
||||
zeroRows(P, 9, 9);
|
||||
zeroCols(P, 9, 9);
|
||||
|
||||
// the state variance is the same as the observation
|
||||
P[9][9] = sq(gps_newest.hacc);
|
||||
P.uncorrelateCovarianceSetVariance<1>(9, sq(gps_newest.hacc));
|
||||
|
||||
vert_pos_reset = true;
|
||||
|
||||
@@ -313,17 +295,13 @@ void Ekf::resetHeight()
|
||||
|
||||
}
|
||||
|
||||
// reset the vertical velocity covariance values
|
||||
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)) {
|
||||
// If we are using GPS, then use it to reset the vertical velocity
|
||||
_state.vel(2) = gps_newest.vel(2);
|
||||
|
||||
// the state variance is the same as the observation
|
||||
P[6][6] = sq(1.5f * gps_newest.sacc);
|
||||
P.uncorrelateCovarianceSetVariance<1>(6, sq(1.5f * gps_newest.sacc));
|
||||
|
||||
} else {
|
||||
// we don't know what the vertical velocity is, so set it to zero
|
||||
@@ -331,7 +309,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[6][6] = 10.0f;
|
||||
P.uncorrelateCovarianceSetVariance<1>(6, 10.0f);
|
||||
|
||||
}
|
||||
|
||||
@@ -490,7 +468,7 @@ bool Ekf::realignYawGPS()
|
||||
_state.mag_I = _R_to_earth * _mag_sample_delayed.mag;
|
||||
|
||||
// use the combined EKF and GPS speed variance to calculate a rough estimate of the yaw error after alignment
|
||||
float SpdErrorVariance = sq(_gps_sample_delayed.sacc) + P[4][4] + P[5][5];
|
||||
float SpdErrorVariance = sq(_gps_sample_delayed.sacc) + P(4,4) + P(5,5);
|
||||
float sineYawError = math::constrain(sqrtf(SpdErrorVariance) / gpsSpeed, 0.0f, 1.0f);
|
||||
|
||||
// adjust the quaternion covariances estimated yaw error
|
||||
@@ -501,7 +479,7 @@ bool Ekf::realignYawGPS()
|
||||
|
||||
if (_control_status.flags.mag_3D) {
|
||||
for (uint8_t index = 16; index <= 21; index ++) {
|
||||
P[index][index] = sq(_params.mag_noise);
|
||||
P(index,index) = sq(_params.mag_noise);
|
||||
}
|
||||
|
||||
// save covariance data for re-use when auto-switching between heading and 3-axis fusion
|
||||
@@ -539,7 +517,7 @@ bool Ekf::realignYawGPS()
|
||||
|
||||
if (_control_status.flags.mag_3D) {
|
||||
for (uint8_t index = 16; index <= 21; index ++) {
|
||||
P[index][index] = sq(_params.mag_noise);
|
||||
P(index,index) = sq(_params.mag_noise);
|
||||
}
|
||||
|
||||
// save covariance data for re-use when auto-switching between heading and 3-axis fusion
|
||||
@@ -698,7 +676,7 @@ bool Ekf::resetMagHeading(const Vector3f &mag_init, bool increase_yaw_var, bool
|
||||
|
||||
if (_control_status.flags.mag_3D) {
|
||||
for (uint8_t index = 16; index <= 21; index ++) {
|
||||
P[index][index] = sq(_params.mag_noise);
|
||||
P(index,index) = sq(_params.mag_noise);
|
||||
}
|
||||
|
||||
// save covariance data for re-use when auto-switching between heading and 3-axis fusion
|
||||
@@ -778,18 +756,6 @@ float Ekf::getMagDeclination()
|
||||
}
|
||||
}
|
||||
|
||||
// This function forces the covariance matrix to be symmetric
|
||||
void Ekf::makeSymmetrical(float (&cov_mat)[_k_num_states][_k_num_states], uint8_t first, uint8_t last)
|
||||
{
|
||||
for (unsigned row = first; row <= last; row++) {
|
||||
for (unsigned column = 0; column < row; column++) {
|
||||
float tmp = (cov_mat[row][column] + cov_mat[column][row]) / 2;
|
||||
cov_mat[row][column] = tmp;
|
||||
cov_mat[column][row] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Ekf::constrainStates()
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
@@ -1156,7 +1122,7 @@ void Ekf::get_ekf_gpos_accuracy(float *ekf_eph, float *ekf_epv)
|
||||
// report absolute accuracy taking into account the uncertainty in location of the origin
|
||||
// If not aiding, return 0 for horizontal position estimate as no estimate is available
|
||||
// TODO - allow for baro drift in vertical position error
|
||||
float hpos_err = sqrtf(P[7][7] + P[8][8] + sq(_gps_origin_eph));
|
||||
float hpos_err = sqrtf(P(7,7) + P(8,8) + sq(_gps_origin_eph));
|
||||
|
||||
// If we are dead-reckoning, use the innovations as a conservative alternate measure of the horizontal position error
|
||||
// The reason is that complete rejection of measurements is often caused by heading misalignment or inertial sensing errors
|
||||
@@ -1169,14 +1135,14 @@ void Ekf::get_ekf_gpos_accuracy(float *ekf_eph, float *ekf_epv)
|
||||
}
|
||||
|
||||
*ekf_eph = hpos_err;
|
||||
*ekf_epv = sqrtf(P[9][9] + sq(_gps_origin_epv));
|
||||
*ekf_epv = sqrtf(P(9,9) + sq(_gps_origin_epv));
|
||||
}
|
||||
|
||||
// get the 1-sigma horizontal and vertical position uncertainty of the ekf local position
|
||||
void Ekf::get_ekf_lpos_accuracy(float *ekf_eph, float *ekf_epv)
|
||||
{
|
||||
// TODO - allow for baro drift in vertical position error
|
||||
float hpos_err = sqrtf(P[7][7] + P[8][8]);
|
||||
float hpos_err = sqrtf(P(7,7) + P(8,8));
|
||||
|
||||
// If we are dead-reckoning, use the innovations as a conservative alternate measure of the horizontal position error
|
||||
// The reason is that complete rejection of measurements is often caused by heading misalignment or inertial sensing errors
|
||||
@@ -1186,13 +1152,13 @@ void Ekf::get_ekf_lpos_accuracy(float *ekf_eph, float *ekf_epv)
|
||||
}
|
||||
|
||||
*ekf_eph = hpos_err;
|
||||
*ekf_epv = sqrtf(P[9][9]);
|
||||
*ekf_epv = sqrtf(P(9,9));
|
||||
}
|
||||
|
||||
// get the 1-sigma horizontal and vertical velocity uncertainty
|
||||
void Ekf::get_ekf_vel_accuracy(float *ekf_evh, float *ekf_evv)
|
||||
{
|
||||
float hvel_err = sqrtf(P[4][4] + P[5][5]);
|
||||
float hvel_err = sqrtf(P(4,4) + P(5,5));
|
||||
|
||||
// If we are dead-reckoning, use the innovations as a conservative alternate measure of the horizontal velocity error
|
||||
// The reason is that complete rejection of measurements is often caused by heading misalignment or inertial sensing errors
|
||||
@@ -1219,7 +1185,7 @@ void Ekf::get_ekf_vel_accuracy(float *ekf_evh, float *ekf_evv)
|
||||
}
|
||||
|
||||
*ekf_evh = hvel_err;
|
||||
*ekf_evv = sqrtf(P[6][6]);
|
||||
*ekf_evv = sqrtf(P(6,6));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1283,23 +1249,16 @@ bool Ekf::reset_imu_bias()
|
||||
_state.delta_ang_bias.zero();
|
||||
_state.delta_vel_bias.zero();
|
||||
|
||||
// Zero the corresponding covariances
|
||||
zeroCols(P, 10, 15);
|
||||
zeroRows(P, 10, 15);
|
||||
|
||||
// Set the corresponding variances to the values use for initial alignment
|
||||
float dt = FILTER_UPDATE_PERIOD_S;
|
||||
P[12][12] = P[11][11] = P[10][10] = sq(_params.switch_on_gyro_bias * dt);
|
||||
P[15][15] = P[14][14] = P[13][13] = sq(_params.switch_on_accel_bias * dt);
|
||||
// Zero the corresponding covariances and set
|
||||
// variances to the values use for initial alignment
|
||||
P.uncorrelateCovarianceSetVariance<3>(10, sq(_params.switch_on_gyro_bias * FILTER_UPDATE_PERIOD_S));
|
||||
P.uncorrelateCovarianceSetVariance<3>(13, sq(_params.switch_on_accel_bias * FILTER_UPDATE_PERIOD_S));
|
||||
_last_imu_bias_cov_reset_us = _imu_sample_delayed.time_us;
|
||||
|
||||
// Set previous frame values
|
||||
_prev_dvel_bias_var(0) = P[13][13];
|
||||
_prev_dvel_bias_var(1) = P[14][14];
|
||||
_prev_dvel_bias_var(2) = P[15][15];
|
||||
_prev_dvel_bias_var = P.slice<3,3>(13,13).diag();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// get EKF innovation consistency check status information comprising of:
|
||||
@@ -1390,84 +1349,14 @@ void Ekf::fuse(float *K, float innovation)
|
||||
}
|
||||
}
|
||||
|
||||
// zero specified range of rows in the state covariance matrix
|
||||
void Ekf::zeroRows(float (&cov_mat)[_k_num_states][_k_num_states], uint8_t first, uint8_t last)
|
||||
{
|
||||
uint8_t row;
|
||||
|
||||
for (row = first; row <= last; row++) {
|
||||
memset(&cov_mat[row][0], 0, sizeof(cov_mat[0][0]) * 24);
|
||||
}
|
||||
}
|
||||
|
||||
// zero specified range of columns in the state covariance matrix
|
||||
void Ekf::zeroCols(float (&cov_mat)[_k_num_states][_k_num_states], uint8_t first, uint8_t last)
|
||||
{
|
||||
uint8_t row;
|
||||
|
||||
for (row = 0; row <= 23; row++) {
|
||||
memset(&cov_mat[row][first], 0, sizeof(cov_mat[0][0]) * (1 + last - first));
|
||||
}
|
||||
}
|
||||
|
||||
void Ekf::zeroOffDiag(float (&cov_mat)[_k_num_states][_k_num_states], uint8_t first, uint8_t last)
|
||||
{
|
||||
// save diagonal elements
|
||||
uint8_t row;
|
||||
float variances[_k_num_states];
|
||||
|
||||
for (row = first; row <= last; row++) {
|
||||
variances[row] = cov_mat[row][row];
|
||||
}
|
||||
|
||||
// zero rows and columns
|
||||
zeroRows(cov_mat, first, last);
|
||||
zeroCols(cov_mat, first, last);
|
||||
|
||||
// restore diagonals
|
||||
for (row = first; row <= last; row++) {
|
||||
cov_mat[row][row] = variances[row];
|
||||
}
|
||||
}
|
||||
|
||||
void Ekf::uncorrelateQuatStates()
|
||||
{
|
||||
// save 4x4 elements
|
||||
uint32_t row;
|
||||
uint32_t col;
|
||||
float variances[4][4];
|
||||
for (row = 0; row < 4; row++) {
|
||||
for (col = 0; col < 4; col++) {
|
||||
variances[row][col] = P[row][col];
|
||||
}
|
||||
}
|
||||
|
||||
// zero rows and columns
|
||||
zeroRows(P, 0, 3);
|
||||
zeroCols(P, 0, 3);
|
||||
|
||||
// restore 4x4 elements
|
||||
for (row = 0; row < 4; row++) {
|
||||
for (col = 0; col < 4; col++) {
|
||||
P[row][col] = variances[row][col];
|
||||
}
|
||||
}
|
||||
P.uncorrelateCovariance<4>(0);
|
||||
}
|
||||
|
||||
void Ekf::setDiag(float (&cov_mat)[_k_num_states][_k_num_states], uint8_t first, uint8_t last, float variance)
|
||||
{
|
||||
// zero rows and columns
|
||||
zeroRows(cov_mat, first, last);
|
||||
zeroCols(cov_mat, first, last);
|
||||
|
||||
// set diagonals
|
||||
uint8_t row;
|
||||
|
||||
for (row = first; row <= last; row++) {
|
||||
cov_mat[row][row] = variance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Ekf::global_position_is_valid()
|
||||
{
|
||||
@@ -1562,13 +1451,11 @@ Vector3f Ekf::calcRotVecVariances()
|
||||
float t15 = q3*t6*2.0f;
|
||||
float t16 = q0*q3*t3*t8*2.0f;
|
||||
float t17 = t15+t16;
|
||||
rot_var_vec(0) = t10*(P[0][0]*t10+P[1][0]*t3*t11*2.0f)+t3*t11*(P[0][1]*t10+P[1][1]*t3*t11*2.0f)*2.0f;
|
||||
rot_var_vec(1) = t14*(P[0][0]*t14+P[2][0]*t3*t11*2.0f)+t3*t11*(P[0][2]*t14+P[2][2]*t3*t11*2.0f)*2.0f;
|
||||
rot_var_vec(2) = t17*(P[0][0]*t17+P[3][0]*t3*t11*2.0f)+t3*t11*(P[0][3]*t17+P[3][3]*t3*t11*2.0f)*2.0f;
|
||||
rot_var_vec(0) = t10*(P(0,0)*t10+P(1,0)*t3*t11*2.0f)+t3*t11*(P(0,1)*t10+P(1,1)*t3*t11*2.0f)*2.0f;
|
||||
rot_var_vec(1) = t14*(P(0,0)*t14+P(2,0)*t3*t11*2.0f)+t3*t11*(P(0,2)*t14+P(2,2)*t3*t11*2.0f)*2.0f;
|
||||
rot_var_vec(2) = t17*(P(0,0)*t17+P(3,0)*t3*t11*2.0f)+t3*t11*(P(0,3)*t17+P(3,3)*t3*t11*2.0f)*2.0f;
|
||||
} else {
|
||||
rot_var_vec(0) = 4.0f * P[1][1];
|
||||
rot_var_vec(1) = 4.0f * P[2][2];
|
||||
rot_var_vec(2) = 4.0f * P[3][3];
|
||||
rot_var_vec = 4.0f * P.slice<3,3>(1,1).diag();
|
||||
}
|
||||
|
||||
return rot_var_vec;
|
||||
@@ -1644,46 +1531,30 @@ void Ekf::initialiseQuatCovariances(Vector3f &rot_vec_var)
|
||||
float t44 = t17-t36;
|
||||
|
||||
// zero all the quaternion covariances
|
||||
zeroRows(P, 0, 3);
|
||||
zeroCols(P, 0, 3);
|
||||
P.uncorrelateCovarianceSetVariance<4>(0, 0.0f);
|
||||
|
||||
// Update the quaternion internal covariances using auto-code generated using matlab symbolic toolbox
|
||||
P[0][0] = rot_vec_var(0)*t2*t9*t10*0.25f+rot_vec_var(1)*t4*t9*t10*0.25f+rot_vec_var(2)*t5*t9*t10*0.25f;
|
||||
P[0][1] = t22;
|
||||
P[0][2] = t35+rotX*rot_vec_var(0)*t3*t11*(t15-rotX*rotY*t10*t12*0.5f)*0.5f-rotY*rot_vec_var(1)*t3*t11*t30*0.5f;
|
||||
P[0][3] = rotX*rot_vec_var(0)*t3*t11*(t16-rotX*rotZ*t10*t12*0.5f)*0.5f+rotY*rot_vec_var(1)*t3*t11*(t17-rotY*rotZ*t10*t12*0.5f)*0.5f-rotZ*rot_vec_var(2)*t3*t11*t33*0.5f;
|
||||
P[1][0] = t22;
|
||||
P[1][1] = rot_vec_var(0)*(t19*t19)+rot_vec_var(1)*(t24*t24)+rot_vec_var(2)*(t26*t26);
|
||||
P[1][2] = rot_vec_var(2)*(t16-t25)*(t17-rotY*rotZ*t10*t12*0.5f)-rot_vec_var(0)*t19*t28-rot_vec_var(1)*t28*t30;
|
||||
P[1][3] = rot_vec_var(1)*(t15-t23)*(t17-rotY*rotZ*t10*t12*0.5f)-rot_vec_var(0)*t19*t31-rot_vec_var(2)*t31*t33;
|
||||
P[2][0] = t35-rotY*rot_vec_var(1)*t3*t11*t30*0.5f+rotX*rot_vec_var(0)*t3*t11*(t15-t23)*0.5f;
|
||||
P[2][1] = rot_vec_var(2)*(t16-t25)*(t17-t36)-rot_vec_var(0)*t19*t28-rot_vec_var(1)*t28*t30;
|
||||
P[2][2] = rot_vec_var(1)*(t30*t30)+rot_vec_var(0)*(t37*t37)+rot_vec_var(2)*(t38*t38);
|
||||
P[2][3] = t42;
|
||||
P[3][0] = rotZ*rot_vec_var(2)*t3*t11*t33*(-0.5f)+rotX*rot_vec_var(0)*t3*t11*(t16-t25)*0.5f+rotY*rot_vec_var(1)*t3*t11*(t17-t36)*0.5f;
|
||||
P[3][1] = rot_vec_var(1)*(t15-t23)*(t17-t36)-rot_vec_var(0)*t19*t31-rot_vec_var(2)*t31*t33;
|
||||
P[3][2] = t42;
|
||||
P[3][3] = rot_vec_var(2)*(t33*t33)+rot_vec_var(0)*(t43*t43)+rot_vec_var(1)*(t44*t44);
|
||||
P(0,0) = rot_vec_var(0)*t2*t9*t10*0.25f+rot_vec_var(1)*t4*t9*t10*0.25f+rot_vec_var(2)*t5*t9*t10*0.25f;
|
||||
P(0,1) = t22;
|
||||
P(0,2) = t35+rotX*rot_vec_var(0)*t3*t11*(t15-rotX*rotY*t10*t12*0.5f)*0.5f-rotY*rot_vec_var(1)*t3*t11*t30*0.5f;
|
||||
P(0,3) = rotX*rot_vec_var(0)*t3*t11*(t16-rotX*rotZ*t10*t12*0.5f)*0.5f+rotY*rot_vec_var(1)*t3*t11*(t17-rotY*rotZ*t10*t12*0.5f)*0.5f-rotZ*rot_vec_var(2)*t3*t11*t33*0.5f;
|
||||
P(1,0) = t22;
|
||||
P(1,1) = rot_vec_var(0)*(t19*t19)+rot_vec_var(1)*(t24*t24)+rot_vec_var(2)*(t26*t26);
|
||||
P(1,2) = rot_vec_var(2)*(t16-t25)*(t17-rotY*rotZ*t10*t12*0.5f)-rot_vec_var(0)*t19*t28-rot_vec_var(1)*t28*t30;
|
||||
P(1,3) = rot_vec_var(1)*(t15-t23)*(t17-rotY*rotZ*t10*t12*0.5f)-rot_vec_var(0)*t19*t31-rot_vec_var(2)*t31*t33;
|
||||
P(2,0) = t35-rotY*rot_vec_var(1)*t3*t11*t30*0.5f+rotX*rot_vec_var(0)*t3*t11*(t15-t23)*0.5f;
|
||||
P(2,1) = rot_vec_var(2)*(t16-t25)*(t17-t36)-rot_vec_var(0)*t19*t28-rot_vec_var(1)*t28*t30;
|
||||
P(2,2) = rot_vec_var(1)*(t30*t30)+rot_vec_var(0)*(t37*t37)+rot_vec_var(2)*(t38*t38);
|
||||
P(2,3) = t42;
|
||||
P(3,0) = rotZ*rot_vec_var(2)*t3*t11*t33*(-0.5f)+rotX*rot_vec_var(0)*t3*t11*(t16-t25)*0.5f+rotY*rot_vec_var(1)*t3*t11*(t17-t36)*0.5f;
|
||||
P(3,1) = rot_vec_var(1)*(t15-t23)*(t17-t36)-rot_vec_var(0)*t19*t31-rot_vec_var(2)*t31*t33;
|
||||
P(3,2) = t42;
|
||||
P(3,3) = rot_vec_var(2)*(t33*t33)+rot_vec_var(0)*(t43*t43)+rot_vec_var(1)*(t44*t44);
|
||||
|
||||
} else {
|
||||
// the equations are badly conditioned so use a small angle approximation
|
||||
P[0][0] = 0.0f;
|
||||
P[0][1] = 0.0f;
|
||||
P[0][2] = 0.0f;
|
||||
P[0][3] = 0.0f;
|
||||
P[1][0] = 0.0f;
|
||||
P[1][1] = 0.25f * rot_vec_var(0);
|
||||
P[1][2] = 0.0f;
|
||||
P[1][3] = 0.0f;
|
||||
P[2][0] = 0.0f;
|
||||
P[2][1] = 0.0f;
|
||||
P[2][2] = 0.25f * rot_vec_var(1);
|
||||
P[2][3] = 0.0f;
|
||||
P[3][0] = 0.0f;
|
||||
P[3][1] = 0.0f;
|
||||
P[3][2] = 0.0f;
|
||||
P[3][3] = 0.25f * rot_vec_var(2);
|
||||
|
||||
P.uncorrelateCovarianceSetVariance<1>(0, 0.0f);
|
||||
P.uncorrelateCovarianceSetVariance<3>(1, 0.25f * rot_vec_var);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1856,22 +1727,22 @@ void Ekf::increaseQuatYawErrVariance(float yaw_variance)
|
||||
|
||||
// Add covariances for additonal yaw uncertainty to existing covariances.
|
||||
// This assumes that the additional yaw error is uncorrrelated to existing errors
|
||||
P[0][0] += yaw_variance*sq(SQ[2]);
|
||||
P[0][1] += yaw_variance*SQ[1]*SQ[2];
|
||||
P[1][1] += yaw_variance*sq(SQ[1]);
|
||||
P[0][2] += yaw_variance*SQ[0]*SQ[2];
|
||||
P[1][2] += yaw_variance*SQ[0]*SQ[1];
|
||||
P[2][2] += yaw_variance*sq(SQ[0]);
|
||||
P[0][3] -= yaw_variance*SQ[2]*SQ[3];
|
||||
P[1][3] -= yaw_variance*SQ[1]*SQ[3];
|
||||
P[2][3] -= yaw_variance*SQ[0]*SQ[3];
|
||||
P[3][3] += yaw_variance*sq(SQ[3]);
|
||||
P[1][0] += yaw_variance*SQ[1]*SQ[2];
|
||||
P[2][0] += yaw_variance*SQ[0]*SQ[2];
|
||||
P[2][1] += yaw_variance*SQ[0]*SQ[1];
|
||||
P[3][0] -= yaw_variance*SQ[2]*SQ[3];
|
||||
P[3][1] -= yaw_variance*SQ[1]*SQ[3];
|
||||
P[3][2] -= yaw_variance*SQ[0]*SQ[3];
|
||||
P(0,0) += yaw_variance*sq(SQ[2]);
|
||||
P(0,1) += yaw_variance*SQ[1]*SQ[2];
|
||||
P(1,1) += yaw_variance*sq(SQ[1]);
|
||||
P(0,2) += yaw_variance*SQ[0]*SQ[2];
|
||||
P(1,2) += yaw_variance*SQ[0]*SQ[1];
|
||||
P(2,2) += yaw_variance*sq(SQ[0]);
|
||||
P(0,3) -= yaw_variance*SQ[2]*SQ[3];
|
||||
P(1,3) -= yaw_variance*SQ[1]*SQ[3];
|
||||
P(2,3) -= yaw_variance*SQ[0]*SQ[3];
|
||||
P(3,3) += yaw_variance*sq(SQ[3]);
|
||||
P(1,0) += yaw_variance*SQ[1]*SQ[2];
|
||||
P(2,0) += yaw_variance*SQ[0]*SQ[2];
|
||||
P(2,1) += yaw_variance*SQ[0]*SQ[1];
|
||||
P(3,0) -= yaw_variance*SQ[2]*SQ[3];
|
||||
P(3,1) -= yaw_variance*SQ[1]*SQ[3];
|
||||
P(3,2) -= yaw_variance*SQ[0]*SQ[3];
|
||||
}
|
||||
|
||||
// save covariance data for re-use when auto-switching between heading and 3-axis fusion
|
||||
@@ -1879,13 +1750,13 @@ void Ekf::saveMagCovData()
|
||||
{
|
||||
// save variances for the D earth axis and XYZ body axis field
|
||||
for (uint8_t index = 0; index <= 3; index ++) {
|
||||
_saved_mag_bf_variance[index] = P[index + 18][index + 18];
|
||||
_saved_mag_bf_variance[index] = P(index + 18,index + 18);
|
||||
}
|
||||
|
||||
// save the NE axis covariance sub-matrix
|
||||
for (uint8_t row = 0; row <= 1; row ++) {
|
||||
for (uint8_t col = 0; col <= 1; col ++) {
|
||||
_saved_mag_ef_covmat[row][col] = P[row + 16][col + 16];
|
||||
_saved_mag_ef_covmat[row][col] = P(row + 16,col + 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1894,12 +1765,12 @@ void Ekf::loadMagCovData()
|
||||
{
|
||||
// re-instate variances for the D earth axis and XYZ body axis field
|
||||
for (uint8_t index = 0; index <= 3; index ++) {
|
||||
P[index + 18][index + 18] = _saved_mag_bf_variance[index];
|
||||
P(index + 18,index + 18) = _saved_mag_bf_variance[index];
|
||||
}
|
||||
// re-instate the NE axis covariance sub-matrix
|
||||
for (uint8_t row = 0; row <= 1; row ++) {
|
||||
for (uint8_t col = 0; col <= 1; col ++) {
|
||||
P[row + 16][col + 16] = _saved_mag_ef_covmat[row][col];
|
||||
P(row + 16,col + 16) = _saved_mag_ef_covmat[row][col];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user