mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-05-17 09:47:35 +08:00
GPS Yaw: Always reset Yaw when GPS Yaw fusion is starting
Also avoid fusing fake mag data when an other source of yaw aiding is active, even if in MAG_TYPE_NONE mode.
This commit is contained in:
committed by
Mathieu Bresciani
parent
ff8b5ec69d
commit
3c6790f5d5
+2
-8
@@ -522,20 +522,14 @@ void Ekf::controlGpsFusion()
|
|||||||
if ((_params.fusion_mode & MASK_USE_GPSYAW)
|
if ((_params.fusion_mode & MASK_USE_GPSYAW)
|
||||||
&& ISFINITE(_gps_sample_delayed.yaw)
|
&& ISFINITE(_gps_sample_delayed.yaw)
|
||||||
&& _control_status.flags.tilt_align
|
&& _control_status.flags.tilt_align
|
||||||
&& (!_control_status.flags.gps_yaw || !_control_status.flags.yaw_align)
|
&& !_control_status.flags.gps_yaw
|
||||||
&& !_gps_hgt_intermittent) {
|
&& !_gps_hgt_intermittent) {
|
||||||
|
|
||||||
if (resetGpsAntYaw()) {
|
if (resetGpsAntYaw()) {
|
||||||
// flag the yaw as aligned
|
// flag the yaw as aligned
|
||||||
_control_status.flags.yaw_align = true;
|
_control_status.flags.yaw_align = true;
|
||||||
|
|
||||||
// turn on fusion of external vision yaw measurements and disable all other yaw fusion
|
startGpsYawFusion();
|
||||||
_control_status.flags.gps_yaw = true;
|
|
||||||
_control_status.flags.ev_yaw = false;
|
|
||||||
_control_status.flags.mag_dec = false;
|
|
||||||
|
|
||||||
stopMagHdgFusion();
|
|
||||||
stopMag3DFusion();
|
|
||||||
|
|
||||||
ECL_INFO_TIMESTAMPED("starting GPS yaw fusion");
|
ECL_INFO_TIMESTAMPED("starting GPS yaw fusion");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -693,7 +693,7 @@ private:
|
|||||||
void controlMagFusion();
|
void controlMagFusion();
|
||||||
void updateMagFilter();
|
void updateMagFilter();
|
||||||
|
|
||||||
bool canRunMagFusion() const;
|
bool noOtherYawAidingThanMag() const;
|
||||||
|
|
||||||
void checkHaglYawResetReq();
|
void checkHaglYawResetReq();
|
||||||
float getTerrainVPos() const;
|
float getTerrainVPos() const;
|
||||||
@@ -842,6 +842,7 @@ private:
|
|||||||
|
|
||||||
void stopGpsVelFusion();
|
void stopGpsVelFusion();
|
||||||
|
|
||||||
|
void startGpsYawFusion();
|
||||||
void stopGpsYawFusion();
|
void stopGpsYawFusion();
|
||||||
|
|
||||||
void stopEvFusion();
|
void stopEvFusion();
|
||||||
|
|||||||
@@ -1634,6 +1634,15 @@ void Ekf::stopGpsVelFusion()
|
|||||||
_gps_vel_test_ratio.setZero();
|
_gps_vel_test_ratio.setZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ekf::startGpsYawFusion()
|
||||||
|
{
|
||||||
|
_control_status.flags.mag_dec = false;
|
||||||
|
stopEvYawFusion();
|
||||||
|
stopMagHdgFusion();
|
||||||
|
stopMag3DFusion();
|
||||||
|
_control_status.flags.gps_yaw = true;
|
||||||
|
}
|
||||||
|
|
||||||
void Ekf::stopGpsYawFusion()
|
void Ekf::stopGpsYawFusion()
|
||||||
{
|
{
|
||||||
_control_status.flags.gps_yaw = false;
|
_control_status.flags.gps_yaw = false;
|
||||||
|
|||||||
+2
-11
@@ -303,20 +303,11 @@ bool Ekf::resetGpsAntYaw()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float predicted_yaw = atan2f(ant_vec_ef(1),ant_vec_ef(0));
|
|
||||||
|
|
||||||
// get measurement and correct for antenna array yaw offset
|
// get measurement and correct for antenna array yaw offset
|
||||||
const float measured_yaw = _gps_sample_delayed.yaw + _gps_yaw_offset;
|
const float measured_yaw = _gps_sample_delayed.yaw + _gps_yaw_offset;
|
||||||
|
|
||||||
// calculate the amount the yaw needs to be rotated by
|
const float yaw_variance = sq(fmaxf(_params.mag_heading_noise, 1.0e-2f));
|
||||||
const float yaw_delta = wrap_pi(measured_yaw - predicted_yaw);
|
resetQuatStateYaw(measured_yaw, yaw_variance, true);
|
||||||
|
|
||||||
// update the quaternion state estimates and corresponding covariances only if
|
|
||||||
// the change in angle has been large or the yaw is not yet aligned
|
|
||||||
if(fabsf(yaw_delta) > math::radians(15.0f) || !_control_status.flags.yaw_align) {
|
|
||||||
const float yaw_variance = sq(fmaxf(_params.mag_heading_noise, 1.0e-2f));
|
|
||||||
resetQuatStateYaw(measured_yaw, yaw_variance, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-9
@@ -46,12 +46,15 @@ void Ekf::controlMagFusion()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When operating without a magnetometer, yaw fusion is run selectively to prevent
|
// When operating without a magnetometer and no other source of yaw aiding is active,
|
||||||
// enable yaw gyro bias learning hen stationary on ground and to prevent uncontrolled
|
// yaw fusion is run selectively to enable yaw gyro bias learning when stationary on
|
||||||
// yaw variance growth
|
// ground and to prevent uncontrolled yaw variance growth
|
||||||
if (_params.mag_fusion_type == MAG_FUSE_TYPE_NONE) {
|
if (_params.mag_fusion_type == MAG_FUSE_TYPE_NONE) {
|
||||||
_yaw_use_inhibit = true;
|
if (noOtherYawAidingThanMag())
|
||||||
fuseHeading();
|
{
|
||||||
|
_yaw_use_inhibit = true;
|
||||||
|
fuseHeading();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +73,7 @@ void Ekf::controlMagFusion()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canRunMagFusion()) {
|
if (noOtherYawAidingThanMag() && _mag_data_ready) {
|
||||||
if (_control_status.flags.in_air) {
|
if (_control_status.flags.in_air) {
|
||||||
checkHaglYawResetReq();
|
checkHaglYawResetReq();
|
||||||
runInAirYawReset();
|
runInAirYawReset();
|
||||||
@@ -116,11 +119,10 @@ void Ekf::updateMagFilter()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ekf::canRunMagFusion() const
|
bool Ekf::noOtherYawAidingThanMag() const
|
||||||
{
|
{
|
||||||
// check for new magnetometer data that has fallen behind the fusion time horizon
|
|
||||||
// If we are using external vision data or GPS-heading for heading then no magnetometer fusion is used
|
// If we are using external vision data or GPS-heading for heading then no magnetometer fusion is used
|
||||||
return !_control_status.flags.ev_yaw && !_control_status.flags.gps_yaw && _mag_data_ready;
|
return !_control_status.flags.ev_yaw && !_control_status.flags.gps_yaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ekf::checkHaglYawResetReq()
|
void Ekf::checkHaglYawResetReq()
|
||||||
|
|||||||
+19
-13
@@ -88,26 +88,32 @@ TEST_F(EkfGpsHeadingTest, fusionStartWithReset)
|
|||||||
_sensor_simulator.runSeconds(11);
|
_sensor_simulator.runSeconds(11);
|
||||||
|
|
||||||
// THEN: after a while the fusion should be stopped
|
// THEN: after a while the fusion should be stopped
|
||||||
// TODO: THIS IS NOT HAPPENING
|
|
||||||
EXPECT_FALSE(_ekf_wrapper.isIntendingGpsHeadingFusion());
|
EXPECT_FALSE(_ekf_wrapper.isIntendingGpsHeadingFusion());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(EkfGpsHeadingTest, fusionStartWithoutReset)
|
TEST_F(EkfGpsHeadingTest, yawConvergence)
|
||||||
{
|
{
|
||||||
// GIVEN:EKF that fuses GPS
|
// GIVEN: an initial GPS yaw, not aligned with the current one
|
||||||
|
float gps_heading = _ekf_wrapper.getYawAngle() + math::radians(10.f);
|
||||||
// WHEN: enabling GPS heading fusion and heading difference is smaller than 15 degrees
|
|
||||||
const float gps_heading = _ekf_wrapper.getYawAngle() + math::radians(10.f);
|
|
||||||
_sensor_simulator._gps.setYaw(gps_heading);
|
_sensor_simulator._gps.setYaw(gps_heading);
|
||||||
|
|
||||||
|
// WHEN: the GPS yaw fusion is activated
|
||||||
_ekf_wrapper.enableGpsHeadingFusion();
|
_ekf_wrapper.enableGpsHeadingFusion();
|
||||||
const int initial_quat_reset_counter = _ekf_wrapper.getQuaternionResetCounter();
|
_sensor_simulator.runSeconds(5);
|
||||||
_sensor_simulator.runSeconds(0.2);
|
|
||||||
|
|
||||||
// THEN: GPS heading fusion should have started;
|
// THEN: the estimate is reset and stays close to the measurement
|
||||||
EXPECT_TRUE(_ekf_wrapper.isIntendingGpsHeadingFusion());
|
float yaw_est = _ekf_wrapper.getYawAngle();
|
||||||
|
EXPECT_NEAR(yaw_est, gps_heading, math::radians(0.05f))
|
||||||
|
<< "yaw est: " << math::degrees(yaw_est) << "gps yaw: " << math::degrees(gps_heading);
|
||||||
|
|
||||||
// AND: no reset to GPS heading should be performed
|
// AND WHEN: the the measurement changes
|
||||||
EXPECT_EQ(_ekf_wrapper.getQuaternionResetCounter(), initial_quat_reset_counter);
|
gps_heading += math::radians(2.f);
|
||||||
|
_sensor_simulator._gps.setYaw(gps_heading);
|
||||||
|
_sensor_simulator.runSeconds(6);
|
||||||
|
|
||||||
// TODO: investigate why heading is not converging exactly to GPS heading
|
// THEN: the estimate slowly converges to the new measurement
|
||||||
|
// Note that the process is slow, because the gyro did not detect any motion
|
||||||
|
yaw_est = _ekf_wrapper.getYawAngle();
|
||||||
|
EXPECT_NEAR(yaw_est, gps_heading, math::radians(0.5f))
|
||||||
|
<< "yaw est: " << math::degrees(yaw_est) << "gps yaw: " << math::degrees(gps_heading);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user