Glass lever: port the pod-build GAIT DETENT to the PadRIO throttle slew

Human re-test on the fresh build: zero-stop OK, but the lever could PARK inside
the walk/run hysteresis band (walkStrideLength@0x534 .. reverseSpeedMax@0x538)
where the gait SM has no stable state -- walk<->run hunt, EngineShiftFwd/Rev
retriggering ("mixed walk/run mode + repeated acceleration sample").  The
pod-build keyboard lever already snaps out of the band to the NEARER edge at
key-rest (mech4.cpp GAIT DETENT); the PadRIO slew channel lacked it.

Faithful port, not an invention: mech4.cpp publishes the band in lever units
every driven frame (gBTGaitDetentLo/Hi seam, same guards + the same +0.002
engage margin); L4PADRIO Poll() applies the identical nearer-edge snap to the
Throttle channel when the slew rests (no slew key held, no pad slew axis
deflected).  Sweeping through the band while held stays continuous (the
authentic moving lever, one authentic shift).

Verified (DEV.EGG glass, graduated parks each ~0.10 of the sweep,
BT_GAIT_TRACE+BT_MPPR_TRACE): band [0.358026,0.50388) = demand 22.02-30.87;
in-band parks snap both directions (0.4137->lo, 0.465126->hi); no at-rest
sample in the band; exactly ONE walk->run clip (state 10) up and ONE run->walk
(state 14) down across the whole sweep; zero-stop unaffected; pod build
rebuilt + BT_AUTODRIVE smoke clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-20 10:57:34 -05:00
co-authored by Claude Fable 5
parent 1535e3e48d
commit 6ad1e074cc
5 changed files with 121 additions and 1 deletions
+44
View File
@@ -443,8 +443,10 @@ void
float slewDelta[PadBindingProfile::ChannelCount];
int deflectHeld[PadBindingProfile::ChannelCount];
int slewHeld[PadBindingProfile::ChannelCount];
memset(slewDelta, 0, sizeof(slewDelta));
memset(deflectHeld, 0, sizeof(deflectHeld));
memset(slewHeld, 0, sizeof(slewHeld));
for (int k = 0; k < bindings.keyBindingCount; ++k)
{
@@ -482,6 +484,7 @@ void
case PadBindingProfile::ActionAxisSlew:
if (held)
{
slewHeld[binding.action.channel] = 1;
slewDelta[binding.action.channel] +=
binding.action.rate * dt;
}
@@ -588,6 +591,10 @@ void
}
if (binding.slew)
{
if (raw != 0.0f)
{
slewHeld[binding.channel] = 1;
}
channelValue[binding.channel] += raw * binding.slewRate * dt;
}
else if (raw != 0.0f)
@@ -602,6 +609,43 @@ void
}
}
//
//-----------------------------------------------------------------
// GAIT DETENT (keyboard/pad accommodation, ported from the pod-build
// lever -- mech4.cpp "GAIT DETENT", 2026-07-20 glass regression): the
// gait SM has NO stable state for a demand between the walk cycle's
// cap (walkStrideLength @0x534) and the run engage speed
// (reverseSpeedMax @0x538) -- a lever PARKED in that band hunts
// walk <-> run forever, retriggering the authored EngineShiftFwd/Rev
// samples each swing. The pod's PHYSICAL throttle plausibly rested
// only at mechanical notches [T4]; reproduce the pod-build bridge's
// accommodation EXACTLY: when the throttle slew is AT REST (no slew
// key held, no pad slew axis deflected), snap the lever out of the
// dead band to the NEARER edge. Sweeping THROUGH the band while
// held stays continuous -- an authentic moving lever, firing the one
// authentic shift. The band arrives in lever units from the player
// mech via the mech4.cpp seam (hi <= lo = no band known yet).
//-----------------------------------------------------------------
//
{
extern float gBTGaitDetentLo, gBTGaitDetentHi; // mech4.cpp seam
const float band_lo = gBTGaitDetentLo;
const float band_hi = gBTGaitDetentHi;
float &lever = channelValue[PadBindingProfile::ChannelThrottle];
if (!slewHeld[PadBindingProfile::ChannelThrottle]
&& band_hi > band_lo
&& lever > band_lo && lever < band_hi)
{
const float snapped =
(lever - band_lo < (band_hi - band_lo) * 0.5f) ? band_lo : band_hi;
{ static int s_dLog = 0; if (getenv("BT_GAIT_TRACE") && s_dLog++ < 40)
DEBUG_STREAM << "[gaitdetent] pad lever " << lever
<< " in dead band [" << band_lo << "," << band_hi
<< ") -> " << snapped << "\n" << std::flush; }
lever = snapped;
}
}
//
//-----------------------------------------------------------------
// Clamp and publish the control surface. Throttle is the 0..1