mirror of
https://github.com/ArduPilot/ardupilot.git
synced 2026-10-02 10:23:25 +08:00
AP_NavEKF3: don't square the wind-state variance limit when seeding
WIND_VEL_VARIANCE_MAX is already a variance: the airspeed-present path constrains tasDataDelayed.tasVariance with it, and ConstrainVariances() clamps P[22][22] and P[23][23] to it directly. Three seeding paths nevertheless applied sq() to it, asking for a 160,000 m^2/s^2 (400m/s 1-sigma) covariance on the wind states: - the no-usable-airspeed branch of setWindMagStateLearningMode() - the no-valid-heading branch below it - the "allow EKF to relearn wind states rapidly" path, taken when the wind states stop being treated as truth This changes no estimator behaviour. All three seeds are clamped back to WIND_VEL_VARIANCE_MAX by ConstrainVariances() before any fusion step sees them: within one UpdateFilter() cycle controlFilterModes() seeds, CovariancePrediction() (which contains both the third site and the ConstrainVariances() call) runs next, and the fusion selectors run after it. A four-run alternating A/B on Plane.DeadreckoningNoAirSpeed shows the two arms indistinguishable in wind estimate, convergence time (283-287 simulated seconds in all four runs) and dead-reckoning divergence. The only observable difference is in logging: a seed landing on a frame where runUpdates is false is not clamped until the next prediction, so XKV2 can record 160,000 for that one sample where it now records 400. The value of the change is that it removes a units error that is invisible only because a later clamp masks it, and that would bite the moment the clamp moved, was relaxed, or a fourth site copied the pattern. The "use 2-sigma for faster initial convergence" comment on the first site is replaced: the seed is the constant itself (20m/s 1-sigma), identical to the bound the airspeed-present branch clamps to, and ConstrainVariances() would flatten any inflation regardless. The first two sites arrived together in59d31cc7d5("Rework non-airspeed wind estimation"), which introduced the constant and substituted it for a "typical wind speed" of 5.0f without dropping that speed's sq(); the third repeated the pattern inffde7f815c. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
committed by
Andrew Tridgell
co-authored by
Claude Fable 5.1
parent
c9ba77a861
commit
f9b1bacb39
@@ -92,7 +92,7 @@ void NavEKF3_core::setWindMagStateLearningMode()
|
||||
stateStruct.wind_vel.x = windSpeed * cosF(tempEuler.z);
|
||||
stateStruct.wind_vel.y = windSpeed * sinF(tempEuler.z);
|
||||
} else {
|
||||
trueAirspeedVariance = sq(WIND_VEL_VARIANCE_MAX); // use 2-sigma for faster initial convergence
|
||||
trueAirspeedVariance = WIND_VEL_VARIANCE_MAX; // no airspeed: seed at the wind-state variance limit
|
||||
}
|
||||
|
||||
// set the wind state variances to the measurement uncertainty
|
||||
@@ -105,7 +105,7 @@ void NavEKF3_core::setWindMagStateLearningMode()
|
||||
// set the variances using a typical max wind speed for small UAV operation
|
||||
zeroStatesVarCov(22, 23);
|
||||
for (uint8_t index=22; index<=23; index++) {
|
||||
Pmut[index][index] = sq(WIND_VEL_VARIANCE_MAX);
|
||||
Pmut[index][index] = WIND_VEL_VARIANCE_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1122,7 +1122,7 @@ void NavEKF3_core::CovariancePrediction(Vector3F *rotVarVecPtr)
|
||||
treatWindStatesAsTruth = false;
|
||||
if (windStateIsObservable) {
|
||||
// allow EKF to relearn wind states rapidly
|
||||
Pmut[23][23] = Pmut[22][22] = sq(WIND_VEL_VARIANCE_MAX);
|
||||
Pmut[23][23] = Pmut[22][22] = WIND_VEL_VARIANCE_MAX;
|
||||
}
|
||||
}
|
||||
ftype windVelVar = sq(dt * constrain_ftype(frontend->_windVelProcessNoise, 0.0f, 1.0f) * (1.0f + constrain_ftype(frontend->_wndVarHgtRateScale, 0.0f, 1.0f) * fabsF(hgtRate)));
|
||||
|
||||
Reference in New Issue
Block a user