control mode: REPRODUCE the "centering fought my control" fight, and prove the fix in Sauron's config
Follow-up to 4ccc2a7, which fixed the mechanism but could not reproduce the
field symptom. His fuller wording -- the centering "FOUGHT" his control, not
"the torso died" -- is what cracked it.
WHY "FOUGHT" IS THE PRECISE SYMPTOM. TorsoSimulation's frame order is
1. digital twist commands -> currentTwist += d; recenterActive = 0
2. centerCommand > 0 -> recenterActive = 1 (re-armed)
3. analog twist axis != 0 -> currentTwist += d; recenterActive = 0
4. if (recenterActive) -> Recenter(dt) (drags toward 0)
Desktop/glass torso input is ANALOG (Q/E -> gBTTwistAxis -> stickPosition.x), so
with centerCommand stuck the torso HOLDS while you are actively pushing (step 3
clears the arm) and snaps back the instant you ease off (step 2's arm survives
into step 4). You can only hold it off-centre by pushing continuously. That is
"the centering fought my control", exactly.
WHY IT ONLY BITES THE GLASS/POD BUILD -- and why the first bench came back clean.
The ONLY caller of ClearRecenterCommand() sits INSIDE the desktop key-bridge
block, gated on `gBTDrive.forced || !BTRIODevicePresent()`. With a RIO present
-- and on glass builds PadRIO IS the rioPointer -- the bridge is OFF and NOTHING
ever clears centerCommand, so one pass through Basic pins it at 1 for good. A
plain desktop build clears it every frame and self-recovers.
The first modecycle.sh run needed BT_KEY_BRIDGE=1 to make the mode-cycle hook
run at all -- and that same flag switched on the only thing that clears the cell,
masking the bug under test. The hook is now deliberately OUTSIDE that block so
the bench can run the RIO-present configuration.
MEASURED A/B, bridge OFF (Sauron's config), BT_TWIST_PULSE deflect/release:
LEGACY FIXED
ctrCmd=1 samples 310 (latched for good) 0
twist during RELEASE decays 0.443->0, HOLDS 2.44346
0.900->0.436 (recen=1)
recen=1 samples permanently armed 14 (one-shot per Basic
entry, then self-clears)
So the authentic one-shot re-centre still happens on entering Basic; it just
settles instead of fighting the pilot forever.
New bench hook BT_TWIST_PULSE=<n>: deflect the analog twist axis for n ticks
then RELEASE for n ticks, repeating. BT_LOCK_SWEEP never releases, so it cannot
show this symptom at all -- the release window IS the measurement.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018SgmXGNMXavXiafKXf9MDC
This commit is contained in:
co-authored by
Claude Opus 5
parent
4ccc2a7eec
commit
9657fbb11e
@@ -618,6 +618,30 @@ void
|
||||
if (lsw != 0 && s_lockSweep <= 0.0f) s_lockSweep = 0.12f;
|
||||
if (s_lockSweep > 1.0f) s_lockSweep = 1.0f;
|
||||
}
|
||||
// BENCH (BT_TWIST_PULSE=<n>): deflect the analog twist axis for n ticks,
|
||||
// then RELEASE it for n ticks, repeating. BT_LOCK_SWEEP never releases,
|
||||
// so it cannot show the reported symptom: with a stuck centerCommand the
|
||||
// torso holds while you are actively pushing (the analog arm clears
|
||||
// recenterActive) and snaps back the moment you let go (centerCommand
|
||||
// re-arms it) -- "the torso centering FOUGHT my control". Measure the
|
||||
// RELEASE windows: currentTwist should HOLD, not decay toward 0.
|
||||
{
|
||||
static const char *s_tp = getenv("BT_TWIST_PULSE");
|
||||
if (s_tp != 0)
|
||||
{
|
||||
static int s_tpN = 0;
|
||||
int period = atoi(s_tp);
|
||||
if (period < 1) period = 120;
|
||||
const int phase = (s_tpN++ / period) % 2;
|
||||
analogTwistAxis = phase ? 0.0f : 0.6f;
|
||||
if ((s_tpN % 30) == 0)
|
||||
DEBUG_STREAM << "[twistpulse] phase=" << (phase ? "RELEASE" : "deflect")
|
||||
<< " axis=" << analogTwistAxis
|
||||
<< " twist=" << currentTwist
|
||||
<< " ctrCmd=" << centerCommand
|
||||
<< " recen=" << recenterActive << "\n" << std::flush;
|
||||
}
|
||||
}
|
||||
if (s_lockSweep > 0.0f)
|
||||
{
|
||||
effectiveTwistRate = baseTwistRate;
|
||||
|
||||
Reference in New Issue
Block a user