Controls: the .CTL positional-id off-by-one -- CONFIRMED live and FIXED (step 2a)
The streamed L4 mapping resource carries the binary's positional attribute ids (stick=3, throttle=4) but MechControlsMapper chained from Subsystem::NextAttributeID == 2 -- every streamed record resolved ONE MEMBER LATE (attr 4 -> pedalsPosition, verified via the new permanent BT_CTRLMAP_LOG diagnostic in CreateStreamedMappings). A latent real-pod bug: the serial RIO throttle would drive the pedals member; the dev keyboard bridge masked it. Fix per the mechweap/mech attrPad idiom: ids pinned to the binary numbering, id-2 gap padded, static_assert-locked. Torso + weapon chains verified already aligned. Regression: BT_FORCE_THROTTLE headless walk clean (speedDemand=61.501 through authentic InterpretControls, gait cycles, no faults). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,3 +19,42 @@ first); this file carries the step-by-step detail, evidence, and verification tr
|
||||
(purity build); `-DBT_GLASS=ON` and ON/ON configures print correct gate state; the
|
||||
BT_STEAM-without-BT_GLASS negative test FATAL_ERRORs. Full 3-config BUILD matrix becomes
|
||||
meaningful from step 2 (first gated code) and is re-run there.
|
||||
|
||||
## 2026-07-17 — Step 2a: the .CTL positional-attribute off-by-one — CONFIRMED and FIXED (ungated)
|
||||
|
||||
**The bug [T2, live-verified]:** the streamed `.CTL` "L4" mapping resource carries the 1995
|
||||
binary's positional attribute ids (stick=3, throttle=4, ...), resolved at install time by
|
||||
`Simulation::GetAttributePointer(id)` → `AttributeIndexSet::Find(id)` = `attributeIndex[id-1]`
|
||||
(positional). `MechControlsMapper` chained its enum on `Subsystem::NextAttributeID == 2`, but
|
||||
the binary's chain reaches 3 (one base attribute we don't publish) — so EVERY streamed mapper
|
||||
record landed one member late.
|
||||
|
||||
**Evidence (new `BT_CTRLMAP_LOG=1` diagnostic in `LBE4ControlsManager::CreateStreamedMappings`,
|
||||
`engine/MUNGA_L4/L4CTRL.cpp` — permanent, env-gated, default off).** Before the fix
|
||||
(`build-pod` Debug, `-egg DEV.EGG`, dev platform):
|
||||
```
|
||||
rec 0 subsys 0 group 1(Joy) elem 0 attrID 3 -> +0xe4 (= throttlePosition: WRONG, stick intended)
|
||||
rec 1 subsys 0 group 0(Scalar) elem 0 attrID 4 -> +0xe8 (= pedalsPosition: WRONG, throttle intended)
|
||||
rec 2 subsys 0 group 3(Button) elem 63 attrID 6 -> +0xf0 (= speedDemand: WRONG, reverse intended)
|
||||
rec 4-6 attrID 10/11/12 -> lookRight/lookBehind/lookDown (one late; LookLeft/Right/Behind intended)
|
||||
```
|
||||
Spacing attr3→attr4 was 4 bytes (Scalar) where stick→throttle must be 8 (ControlsJoystick).
|
||||
The weapons chain (attrID 19 → +0x31c TriggerState) was already correct — mechweap was
|
||||
pad-aligned in task #16 (gotcha #11). Torso (subsys 17) also aligned (MechSubsystem publishes
|
||||
binary id 2). ONLY the mapper chain (subsys 0) was off. On the dev box the keyboard INPUT
|
||||
BRIDGE (writes the mapper members directly, after the engine push) masked it; on a REAL POD the
|
||||
serial RIO throttle scalar would have driven `pedalsPosition` and the stick x/y would have
|
||||
driven throttle+pedals — the Phase-8 landmine prior art predicted.
|
||||
|
||||
**The fix (ungated, pod-correctness — user-approved 2026-07-17):** `mechmppr.hpp` pins the enum
|
||||
to the binary numbering (`MechControlsMapperPadFirstAttributeID = 2`, stick=3 ... PilotArray=
|
||||
0x16); `mechmppr.cpp` pads id 2 with a valid never-bound entry (the mech.cpp attrPad idiom) and
|
||||
locks the base + pinned ids with `static_assert`s. `L4MechControlsMapper::TargetRangeExponent`
|
||||
(chained) moves 0x16→0x17, matching the binary's own arithmetic; it is bound by name (audio
|
||||
zoom-blip), so no consumer shifts.
|
||||
|
||||
**After the fix:** `attrID 3 -> +0xdc` (stick), `attrID 4 -> +0xe4` (throttle, 8-byte spacing
|
||||
✓), `attrID 6 -> +0xec` (reverse), `10/11/12 -> +0xfc/+0x100/+0x104` (the look trio); torso +
|
||||
weapons unchanged. Regression: headless forced-walk run (`BT_FORCE_THROTTLE=1`) drives normally
|
||||
— `[mppr] thr=1 -> speedDemand=61.501`, gait cycles, position advances, 31/31 subsystems
|
||||
simulated, no faults.
|
||||
|
||||
Reference in New Issue
Block a user