diff --git a/src/modules/ekf2/EKF/ekf.cpp b/src/modules/ekf2/EKF/ekf.cpp index 39ba5389fb..5ee6ee34e5 100644 --- a/src/modules/ekf2/EKF/ekf.cpp +++ b/src/modules/ekf2/EKF/ekf.cpp @@ -196,7 +196,19 @@ bool Ekf::initialiseFilter() // calculate the initial magnetic field and yaw alignment // but do not mark the yaw alignement complete as it needs to be // reset once the leveling phase is done - resetMagHeading(false, false); + if ((_params.mag_fusion_type <= MagFuseType::MAG_3D) && (_mag_counter != 0)) { + // rotate the magnetometer measurements into earth frame using a zero yaw angle + // the angle of the projection onto the horizontal gives the yaw angle + const Vector3f mag_earth_pred = updateYawInRotMat(0.f, _R_to_earth) * _mag_lpf.getState(); + float yaw_new = -atan2f(mag_earth_pred(1), mag_earth_pred(0)) + getMagDeclination(); + + // update quaternion states and corresponding covarainces + resetQuatStateYaw(yaw_new, 0.f, false); + + // set the earth magnetic field states using the updated rotation + _state.mag_I = _R_to_earth * _mag_lpf.getState(); + _state.mag_B.zero(); + } // initialise the state covariance matrix now we have starting values for all the states initialiseCovariance(); diff --git a/src/modules/ekf2/EKF/ekf.h b/src/modules/ekf2/EKF/ekf.h index 59fe2faa93..3264e85631 100644 --- a/src/modules/ekf2/EKF/ekf.h +++ b/src/modules/ekf2/EKF/ekf.h @@ -723,7 +723,7 @@ private: // reset the heading and magnetic field states using the declination and magnetometer measurements // return true if successful - bool resetMagHeading(bool increase_yaw_var = true, bool update_buffer = true); + bool resetMagHeading(); // reset the heading using the external vision measurements // return true if successful diff --git a/src/modules/ekf2/EKF/ekf_helper.cpp b/src/modules/ekf2/EKF/ekf_helper.cpp index 717775f4e9..d417cb35eb 100644 --- a/src/modules/ekf2/EKF/ekf_helper.cpp +++ b/src/modules/ekf2/EKF/ekf_helper.cpp @@ -460,25 +460,24 @@ bool Ekf::realignYawGPS(const Vector3f &mag) } // Reset heading and magnetic field states -bool Ekf::resetMagHeading(bool increase_yaw_var, bool update_buffer) +bool Ekf::resetMagHeading() { // prevent a reset being performed more than once on the same frame if (_imu_sample_delayed.time_us == _flt_mag_align_start_time) { return true; } + const Vector3f mag_init = _mag_lpf.getState(); + + const bool mag_available = (_mag_counter != 0) && isRecent(_time_last_mag, 500000) + && !magFieldStrengthDisturbed(mag_init); + // low pass filtered mag required - if (_mag_counter == 0) { + if (!mag_available) { return false; } - const Vector3f mag_init = _mag_lpf.getState(); - - // calculate the observed yaw angle and yaw variance - float yaw_new; - float yaw_new_variance = 0.0f; - - const bool heading_required_for_navigation = _control_status.flags.gps || _control_status.flags.ev_pos; + const bool heading_required_for_navigation = _control_status.flags.gps; if ((_params.mag_fusion_type <= MagFuseType::MAG_3D) || ((_params.mag_fusion_type == MagFuseType::INDOOR) && heading_required_for_navigation)) { @@ -487,33 +486,26 @@ bool Ekf::resetMagHeading(bool increase_yaw_var, bool update_buffer) // the angle of the projection onto the horizontal gives the yaw angle const Vector3f mag_earth_pred = R_to_earth * mag_init; - yaw_new = -atan2f(mag_earth_pred(1), mag_earth_pred(0)) + getMagDeclination(); - if (increase_yaw_var) { - yaw_new_variance = sq(fmaxf(_params.mag_heading_noise, 1.0e-2f)); - } - - } else if (_params.mag_fusion_type == MagFuseType::INDOOR) { - // we are operating temporarily without knowing the earth frame yaw angle - return true; + // calculate the observed yaw angle and yaw variance + float yaw_new = -atan2f(mag_earth_pred(1), mag_earth_pred(0)) + getMagDeclination(); + float yaw_new_variance = sq(fmaxf(_params.mag_heading_noise, 1.e-2f)); - } else { - // there is no magnetic yaw observation - return false; - } + // update quaternion states and corresponding covarainces + resetQuatStateYaw(yaw_new, yaw_new_variance); - // update quaternion states and corresponding covarainces - resetQuatStateYaw(yaw_new, yaw_new_variance, update_buffer); + // set the earth magnetic field states using the updated rotation + _state.mag_I = _R_to_earth * mag_init; - // set the earth magnetic field states using the updated rotation - _state.mag_I = _R_to_earth * mag_init; + resetMagCov(); - resetMagCov(); + // record the time for the magnetic field alignment event + _flt_mag_align_start_time = _imu_sample_delayed.time_us; - // record the time for the magnetic field alignment event - _flt_mag_align_start_time = _imu_sample_delayed.time_us; + return true; + } - return true; + return false; } bool Ekf::resetYawToEv() @@ -1277,8 +1269,11 @@ void Ekf::stopMagHdgFusion() void Ekf::startMagHdgFusion() { - stopMag3DFusion(); - _control_status.flags.mag_hdg = true; + if (!_control_status.flags.mag_hdg) { + stopMag3DFusion(); + ECL_INFO("starting mag heading fusion"); + _control_status.flags.mag_hdg = true; + } } void Ekf::startMag3DFusion() @@ -1721,7 +1716,10 @@ void Ekf::stopEvVelFusion() void Ekf::stopEvYawFusion() { - _control_status.flags.ev_yaw = false; + if (_control_status.flags.ev_yaw) { + ECL_INFO("stopping EV yaw fusion"); + _control_status.flags.ev_yaw = false; + } } void Ekf::stopAuxVelFusion() @@ -1776,7 +1774,6 @@ void Ekf::resetQuatStateYaw(float yaw, float yaw_variance, bool update_buffer) // apply the change in attitude quaternion to our newest quaternion estimate // which was already taken out from the output buffer _output_new.quat_nominal = _state_reset_status.quat_change * _output_new.quat_nominal; - } _last_static_yaw = NAN;