calibration: throttle reads rest (0), not full, at the detent
Faithful port of a legacy quirk made harmful by axis routing: _throttleLast initialized to Center and the lT==0 hold path meant the first poll at rest compounded 16383*32 -> clamped 32766 = FULL throttle until the lever moved past the deadzone (under the old routing this held LeftTrigger at 255 - fire-secondary - from power-on). lT==0 now zeroes like the deadzone branch and _throttleLast initializes to 0, the sanctioned rest value ResetAll/ ResetThrottle already used. Three regression tests replace the one that asserted the old behavior. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -128,11 +128,39 @@ public class AxisCalibratorTests
|
||||
Assert.Equal(AxisOutputs.Center, cal.Update(Report(x: 0)).X);
|
||||
}
|
||||
|
||||
// --- Detent regression (legacy quirk deliberately fixed) -----------------
|
||||
|
||||
[Fact]
|
||||
public void Outputs_AreClampedToAxisRange()
|
||||
public void Throttle_FirstPollAtRest_IsZero_NotPinned()
|
||||
{
|
||||
// The init-state throttle quirk yields a value far over range on the first
|
||||
// poll at rest; the documented 0..Max clamp guards it.
|
||||
Assert.Equal(AxisOutputs.Max, new AxisCalibrator().Update(Report(throttle: 0)).Z);
|
||||
// Regression: the legacy Center init + detent-hold compounded through the
|
||||
// ×32 rescale and pinned Z at Max on the very first poll at rest — full
|
||||
// reverse on a Centered thumb route, full thrust on a UnipolarPositive one
|
||||
// (Descent). Rest must read 0 with no reset and stay there.
|
||||
var cal = new AxisCalibrator();
|
||||
Assert.Equal(0, cal.Update(Report(throttle: 0)).Z);
|
||||
Assert.Equal(0, cal.Update(Report(throttle: 0)).Z);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Throttle_ReleaseExactlyOntoStart_ReturnsToZero_NoSpike()
|
||||
{
|
||||
// Regression: a release landing exactly on the tracked start (lT == 0)
|
||||
// used to hold the last moving value, which the ×32 rescale turned into a
|
||||
// one-poll full-throttle spike until jitter broke it.
|
||||
var cal = new AxisCalibrator();
|
||||
Assert.Equal(0, cal.Update(Report(throttle: 0)).Z); // seed start at rest
|
||||
Assert.Equal(16000, cal.Update(Report(throttle: -400)).Z); // pushed halfway
|
||||
Assert.Equal(0, cal.Update(Report(throttle: 0)).Z); // release onto start
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Throttle_SampleAboveRunningMax_ReadsAsRest()
|
||||
{
|
||||
// Samples above the tracked start re-base the auto-range (lT == 0 again)
|
||||
// and must read as rest, not re-enter the legacy hold path.
|
||||
var cal = new AxisCalibrator();
|
||||
cal.Update(Report(throttle: -400)); // power-on with lever pushed: becomes the start
|
||||
Assert.Equal(0, cal.Update(Report(throttle: -100)).Z); // above max → re-based, rest
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user