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

@@ -0,0 +1,40 @@
t,speed_units_per_wall_s,rate_deg_per_wall_s
0.52,1498.8,37.47
1.03,1276.1,91.64
1.53,1045.5,90.49
2.05,1133.7,118.83
2.55,885.4,129.88
3.06,777.7,127.51
3.57,788.1,174.38
4.07,546.7,157.56
4.57,536.2,124.41
5.09,946.8,161.62
5.59,821.9,138.76
6.09,636.7,131.35
6.61,529.3,133.56
7.13,674.7,162.01
7.63,669.2,125.78
8.17,746.4,127.35
8.67,821.1,154.31
9.17,569.7,135.57
9.67,645.2,167.18
10.19,720.0,150.99
10.69,698.6,123.63
11.21,717.0,125.53
11.72,826.9,165.47
12.23,471.3,114.2
12.77,594.0,146.56
13.29,858.3,174.73
13.79,734.8,130.83
14.31,502.8,91.53
14.81,822.9,168.67
15.31,696.2,166.37
15.83,462.2,109.81
16.33,791.0,162.87
16.85,854.4,155.88
17.37,536.8,98.26
17.89,873.1,182.24
18.41,630.0,155.61
18.93,584.1,129.64
19.43,699.6,132.45
19.97,805.1,142.68
1 t speed_units_per_wall_s rate_deg_per_wall_s
2 0.52 1498.8 37.47
3 1.03 1276.1 91.64
4 1.53 1045.5 90.49
5 2.05 1133.7 118.83
6 2.55 885.4 129.88
7 3.06 777.7 127.51
8 3.57 788.1 174.38
9 4.07 546.7 157.56
10 4.57 536.2 124.41
11 5.09 946.8 161.62
12 5.59 821.9 138.76
13 6.09 636.7 131.35
14 6.61 529.3 133.56
15 7.13 674.7 162.01
16 7.63 669.2 125.78
17 8.17 746.4 127.35
18 8.67 821.1 154.31
19 9.17 569.7 135.57
20 9.67 645.2 167.18
21 10.19 720.0 150.99
22 10.69 698.6 123.63
23 11.21 717.0 125.53
24 11.72 826.9 165.47
25 12.23 471.3 114.2
26 12.77 594.0 146.56
27 13.29 858.3 174.73
28 13.79 734.8 130.83
29 14.31 502.8 91.53
30 14.81 822.9 168.67
31 15.31 696.2 166.37
32 15.83 462.2 109.81
33 16.33 791.0 162.87
34 16.85 854.4 155.88
35 17.37 536.8 98.26
36 17.89 873.1 182.24
37 18.41 630.0 155.61
38 18.93 584.1 129.64
39 19.43 699.6 132.45
40 19.97 805.1 142.68

View File

@@ -585,3 +585,38 @@ measurement taken through a doubtful instrument cannot settle it.
Data: [aliased, for reference](captures/rate-curve-aliased-BAD.csv) ·
[windowed](captures/rate-curve-windowed.csv).
## The clean sweep: magnitudes agree, the LAW does not follow 🟡
Fresh flight, row pinning **CONFIDENT** (margin 0.413), one sweep and nothing before
it — the conditions the previous attempt lacked. Clock 01:16.08 → 01:41.46 (×1.26).
Binned by speed, both converted to game units:
| speed (game) | measured °/game-s | linear interpolation of the caps |
|---|---|---|
| ~435 | 100.8 | 125.6 |
| ~572 | 113.8 | 115.7 |
| ~709 | 126.3 | 105.7 |
| ~846 | 83.1 | 95.7 |
| ~983 | 72.7 | 85.8 |
(prediction = `AV_PitchPlus_Min` 150 at `MinimumVelocity` 100 → `_Max` 70 at
`MaximumVelocity` 1200, interpolated linearly.)
**What this supports:** the magnitudes are right — measured 73126 °/game-s across
speeds 4001 050 against a predicted 86126 — and the high-speed end falls, as a
speed-dependent cap should.
**What it does not support:** the interpolation *law*. The scatter is ±25 %, the two
fastest bins hold only 1 and 2 windows each (they are the first moments before the
speed bled), and the slowest bin disagrees in the wrong direction (100.8 measured vs
125.6 predicted). A sweep that is *driven* by the speed bleeding cannot spend long at
either extreme, which is exactly where the law is most testable.
**The design that would settle it**, and why this one cannot: hold a *settled*
throttle, pitch for only **~1 second**, and read the rate — the speed barely moves
inside a 1 s burst, so each burst yields one honest `(speed, rate)` point. Repeat at
`LT` / neutral / `RT` for three clean points at known speeds, instead of one smeared
sweep. Data:
[`captures/pitch-rate-curve-clean.csv`](captures/pitch-rate-curve-clean.csv).

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