re(flight): clean pitch sweep -- magnitudes agree, the interpolation law does not

Fresh flight, row pinning CONFIDENT (margin 0.413), one sweep and nothing before
it. axis_probe now REFUSES to measure on a WEAK pin (ALLOW_WEAK_PIN=1 overrides)
since it is a precondition, not a warning: roll is immune to the up/right
labelling but pitch and yaw are not.

Clock x1.26. Binned by speed, both in game units, against the linear
interpolation of AV_PitchPlus_Min 150 (at MinimumVelocity 100) to _Max 70 (at
MaximumVelocity 1200):

    speed ~435   measured 100.8   predicted 125.6
    speed ~572            113.8             115.7
    speed ~709            126.3             105.7
    speed ~846             83.1              95.7
    speed ~983             72.7              85.8

Supported: the magnitudes (73-126 measured vs 86-126 predicted) and a falling
high-speed end. NOT supported: the interpolation law. Scatter is +-25%, the two
fastest bins hold 1 and 2 windows (the first moments before the speed bled), and
the slowest bin misses in the wrong direction.

The flaw is structural, not statistical: a sweep DRIVEN by the speed bleeding
cannot dwell at either extreme, which is exactly where the law is most testable.

What would settle it: hold a settled throttle and pitch for ~1 SECOND, so speed
barely moves inside the burst and each burst gives one honest (speed, rate) point;
repeat at LT / neutral / RT for three clean points at known speeds. Recorded as
the next design rather than attempted as a fifth variation of the same sweep.
This commit is contained in:
2026-08-13 23:12:50 +00:00
parent 0a84c1358e
commit a3f14710a4
3 changed files with 83 additions and 2 deletions

View File

@@ -122,8 +122,14 @@ def pin_rows(w, off, cfg):
up_i = max(cand, key=lambda r: abs(ys[r]))
right_i = [r for r in cand if r != up_i][0]
print(f"# row world-Y means: {[round(y,3) for y in ys]} (forward = row {f_i})")
print(f"# -> up = row {up_i}, right = row {right_i}"
f" {'CONFIDENT' if abs(ys[up_i]) - abs(ys[right_i]) > 0.3 else 'WEAK — craft may not be level'}")
margin = abs(ys[up_i]) - abs(ys[right_i])
ok = margin > 0.3
print(f"# -> up = row {up_i}, right = row {right_i} margin {margin:.3f} "
f"{'CONFIDENT' if ok else 'WEAK — craft is not level'}")
if not ok and os.environ.get("ALLOW_WEAK_PIN") != "1":
sys.exit("refusing to measure with a WEAK row pin — fly level first, or set "
"ALLOW_WEAK_PIN=1 if the caller genuinely does not care "
"(roll is immune to the labelling; pitch and yaw are not)")
return up_i, right_i