re(flight): polling faster than the guest updates manufactures a clean curve
Fitting rate against instantaneous speed produced a tidy "rate rises with speed" relationship, with speeds up to 4795 when the craft's maximum is 1200. It is entirely an artefact: 20 Hz polling is faster than the guest updates these fields, so a per-read delta is either exactly zero (no update yet) or a whole frame's worth divided by a fraction of a frame. 111 of 352 reads were zero on BOTH channels -- position and attitude update on the same frame, so the two are perfectly correlated, and dividing each by the short wall dt produced the correlation out of nothing. Fix: aggregate over windows spanning many frames (0.5 s). A sum of |delta| over such a window is right however the updates fall inside it. This does NOT affect the swept-total probes (roll_axis.py, rate_probe.py) -- they already summed over the whole dwell, immune for the same reason. Only per-sample instantaneous rates were ever wrong, so no earlier number moves. The windowed re-run is NOT yet claimed as a result. It gives plausible magnitudes but still shows rate rising with speed, against the definition's PitchPlus_Min 150 > _Max 70, and it has two disqualifiers: it ran on an instance where the craft was already tumbling from the previous sweep, so pinning reported "WEAK -- craft may not be level", and the sweep started mid-range rather than at maximum. A clean answer needs a fresh flight with pinning CONFIDENT and nothing before it. Since what is in doubt is precisely what _Min/_Max mean, a measurement through a doubtful instrument cannot settle it. Both datasets kept, the bad one labelled, because the aliased curve is a good example of what a manufactured correlation looks like.
This commit is contained in:
353
docs/re/captures/rate-curve-aliased-BAD.csv
Normal file
353
docs/re/captures/rate-curve-aliased-BAD.csv
Normal file
@@ -0,0 +1,353 @@
|
||||
t,speed_units_per_wall_s,rate_deg_per_wall_s
|
||||
0.05,0.0,0.0
|
||||
0.101,4682.4,0.0
|
||||
0.154,1865.9,8.21
|
||||
0.205,1915.4,22.53
|
||||
0.273,1722.2,32.72
|
||||
0.323,2309.7,64.27
|
||||
0.374,0.0,0.0
|
||||
0.426,0.0,0.0
|
||||
0.476,0.0,0.0
|
||||
0.526,3781.4,166.09
|
||||
0.576,1133.2,56.22
|
||||
0.626,2228.8,125.61
|
||||
0.676,735.8,46.29
|
||||
0.726,2161.2,150.9
|
||||
0.777,0.0,0.0
|
||||
0.827,0.0,0.0
|
||||
0.877,0.0,0.0
|
||||
0.927,4795.2,363.58
|
||||
0.978,1400.3,105.58
|
||||
1.028,2080.9,159.73
|
||||
1.078,688.0,53.58
|
||||
1.129,1018.2,79.65
|
||||
1.179,0.0,0.0
|
||||
1.229,0.0,0.0
|
||||
1.279,3169.4,272.63
|
||||
1.332,1891.3,159.33
|
||||
1.382,656.8,55.51
|
||||
1.432,1958.3,167.87
|
||||
1.485,311.4,26.7
|
||||
1.535,0.0,0.0
|
||||
1.585,0.0,0.0
|
||||
1.637,2189.9,217.26
|
||||
1.687,1470.3,152.38
|
||||
1.737,1832.8,178.53
|
||||
1.788,611.6,57.44
|
||||
1.838,311.7,29.03
|
||||
1.889,0.0,0.0
|
||||
1.939,0.0,0.0
|
||||
1.989,2568.6,290.03
|
||||
2.039,1303.4,156.28
|
||||
2.09,1571.3,188.96
|
||||
2.173,987.0,114.66
|
||||
2.223,1389.3,157.19
|
||||
2.274,0.0,0.0
|
||||
2.324,0.0,0.0
|
||||
2.374,0.0,0.0
|
||||
2.425,3014.5,437.25
|
||||
2.476,851.8,137.78
|
||||
2.526,1720.0,282.99
|
||||
2.576,855.8,142.04
|
||||
2.626,1272.7,213.71
|
||||
2.676,420.4,71.25
|
||||
2.726,0.0,0.0
|
||||
2.776,0.0,0.0
|
||||
2.827,2337.7,393.95
|
||||
2.879,605.4,103.05
|
||||
2.929,1229.4,216.06
|
||||
2.979,798.9,145.37
|
||||
3.029,1356.7,257.13
|
||||
3.081,183.1,35.66
|
||||
3.131,0.0,0.0
|
||||
3.181,0.0,0.0
|
||||
3.231,1858.0,372.22
|
||||
3.281,541.0,112.82
|
||||
3.332,1372.1,301.88
|
||||
3.382,335.4,76.89
|
||||
3.432,658.3,154.84
|
||||
3.482,162.0,38.8
|
||||
3.536,0.0,0.0
|
||||
3.586,0.0,0.0
|
||||
3.636,1591.8,390.72
|
||||
3.686,311.3,78.69
|
||||
3.736,1215.5,316.75
|
||||
3.786,602.4,159.01
|
||||
3.839,429.8,113.96
|
||||
3.889,0.0,0.0
|
||||
3.939,0.0,0.0
|
||||
3.989,0.0,0.0
|
||||
4.04,1835.6,469.81
|
||||
4.09,311.3,78.92
|
||||
4.14,1251.2,315.27
|
||||
4.19,317.9,78.47
|
||||
4.24,320.5,78.42
|
||||
4.29,0.0,0.0
|
||||
4.341,0.0,0.0
|
||||
4.391,1352.5,313.43
|
||||
4.441,850.5,192.03
|
||||
4.492,1033.9,227.09
|
||||
4.542,1073.0,227.87
|
||||
4.592,551.1,113.43
|
||||
4.642,0.0,0.0
|
||||
4.692,0.0,0.0
|
||||
4.743,1735.5,337.79
|
||||
4.793,779.7,147.59
|
||||
4.843,1186.4,220.17
|
||||
4.893,808.4,146.17
|
||||
4.943,1018.0,181.41
|
||||
4.993,204.4,36.08
|
||||
5.043,0.0,0.0
|
||||
5.093,0.0,0.0
|
||||
5.144,0.0,0.0
|
||||
5.194,3438.2,575.96
|
||||
5.244,853.2,142.26
|
||||
5.294,1685.8,285.28
|
||||
5.344,1250.1,215.19
|
||||
5.394,825.0,144.01
|
||||
5.445,202.2,35.56
|
||||
5.495,0.0,0.0
|
||||
5.545,0.0,0.0
|
||||
5.596,2042.5,361.76
|
||||
5.674,762.2,138.77
|
||||
5.725,1171.7,219.95
|
||||
5.775,384.3,73.55
|
||||
5.826,0.0,0.0
|
||||
5.877,0.0,0.0
|
||||
5.927,0.0,0.0
|
||||
5.977,1528.0,296.2
|
||||
6.028,1281.9,256.26
|
||||
6.078,365.6,75.03
|
||||
6.128,1073.3,226.52
|
||||
6.178,176.0,37.88
|
||||
6.231,0.0,0.0
|
||||
6.281,0.0,0.0
|
||||
6.332,1720.1,372.76
|
||||
6.382,518.3,114.37
|
||||
6.432,1009.5,230.82
|
||||
6.484,480.0,112.96
|
||||
6.534,807.9,194.56
|
||||
6.584,159.3,38.98
|
||||
6.675,0.0,0.0
|
||||
6.725,1449.1,352.93
|
||||
6.775,477.0,117.26
|
||||
6.826,927.2,232.38
|
||||
6.877,306.8,77.6
|
||||
6.927,928.5,236.59
|
||||
6.977,154.5,39.37
|
||||
7.027,0.0,0.0
|
||||
7.077,0.0,0.0
|
||||
7.131,1353.2,333.31
|
||||
7.181,963.9,234.69
|
||||
7.231,1304.5,311.86
|
||||
7.281,332.6,77.62
|
||||
7.331,506.1,116.36
|
||||
7.381,0.0,0.0
|
||||
7.432,0.0,0.0
|
||||
7.482,0.0,0.0
|
||||
7.534,2615.1,556.47
|
||||
7.584,1101.8,225.72
|
||||
7.634,1108.3,222.17
|
||||
7.686,929.5,182.14
|
||||
7.736,576.3,111.11
|
||||
7.786,0.0,0.0
|
||||
7.836,0.0,0.0
|
||||
7.886,0.0,0.0
|
||||
7.936,2840.4,515.81
|
||||
7.987,807.7,144.56
|
||||
8.037,1214.6,217.75
|
||||
8.087,809.7,145.24
|
||||
8.137,606.3,108.89
|
||||
8.187,0.0,0.0
|
||||
8.237,0.0,0.0
|
||||
8.288,0.0,0.0
|
||||
8.339,2628.6,463.46
|
||||
8.389,811.4,144.9
|
||||
8.439,1198.5,218.35
|
||||
8.489,392.4,72.53
|
||||
8.539,784.5,146.63
|
||||
8.59,0.0,0.0
|
||||
8.64,0.0,0.0
|
||||
8.69,0.0,0.0
|
||||
8.741,2111.3,400.11
|
||||
8.791,946.6,185.46
|
||||
8.841,1110.6,224.19
|
||||
8.891,364.4,75.15
|
||||
8.941,720.3,150.86
|
||||
8.991,0.0,0.0
|
||||
9.042,0.0,0.0
|
||||
9.092,1792.7,378.77
|
||||
9.142,529.6,113.67
|
||||
9.193,1022.7,226.47
|
||||
9.273,624.6,143.36
|
||||
9.325,644.6,151.82
|
||||
9.375,0.0,0.0
|
||||
9.425,0.0,0.0
|
||||
9.476,1289.1,307.07
|
||||
9.526,1122.5,273.41
|
||||
9.577,311.7,76.8
|
||||
9.627,789.7,196.14
|
||||
9.677,156.4,38.99
|
||||
9.727,0.0,0.0
|
||||
9.778,0.0,0.0
|
||||
9.828,2131.2,510.02
|
||||
9.878,653.9,155.64
|
||||
9.928,983.1,233.48
|
||||
9.978,330.0,77.72
|
||||
10.028,496.6,116.32
|
||||
10.079,0.0,0.0
|
||||
10.129,0.0,0.0
|
||||
10.179,0.0,0.0
|
||||
10.23,2470.2,540.62
|
||||
10.282,672.7,144.51
|
||||
10.333,1067.2,227.85
|
||||
10.383,1076.8,227.17
|
||||
10.433,724.0,150.8
|
||||
10.483,0.0,0.0
|
||||
10.533,0.0,0.0
|
||||
10.583,0.0,0.0
|
||||
10.633,2272.0,451.3
|
||||
10.683,759.7,148.67
|
||||
10.734,762.5,148.52
|
||||
10.784,756.3,146.57
|
||||
10.834,770.1,148.16
|
||||
10.885,0.0,0.0
|
||||
10.935,0.0,0.0
|
||||
10.985,0.0,0.0
|
||||
11.035,2168.6,406.08
|
||||
11.085,984.6,183.61
|
||||
11.136,1178.3,220.07
|
||||
11.186,590.5,110.24
|
||||
11.236,393.0,73.44
|
||||
11.286,0.0,0.0
|
||||
11.336,0.0,0.0
|
||||
11.386,2007.6,367.45
|
||||
11.436,597.4,109.35
|
||||
11.486,1180.4,219.81
|
||||
11.537,1160.8,220.86
|
||||
11.587,575.3,111.02
|
||||
11.639,368.0,71.56
|
||||
11.689,0.0,0.0
|
||||
11.739,0.0,0.0
|
||||
11.789,2275.4,445.88
|
||||
11.879,415.2,83.5
|
||||
11.929,1448.9,300.69
|
||||
11.979,356.5,75.48
|
||||
12.031,0.0,0.0
|
||||
12.081,0.0,0.0
|
||||
12.131,1612.8,341.73
|
||||
12.184,504.1,108.0
|
||||
12.234,1042.0,228.85
|
||||
12.284,683.1,153.38
|
||||
12.334,674.3,153.83
|
||||
12.386,0.0,0.0
|
||||
12.473,0.0,0.0
|
||||
12.524,1701.7,386.01
|
||||
12.574,672.1,154.19
|
||||
12.625,974.9,227.26
|
||||
12.675,330.4,77.54
|
||||
12.725,986.1,232.99
|
||||
12.775,163.8,38.73
|
||||
12.825,0.0,0.0
|
||||
12.878,0.0,0.0
|
||||
12.928,0.0,0.0
|
||||
12.978,2405.7,542.85
|
||||
13.029,1022.4,230.5
|
||||
13.079,681.6,153.81
|
||||
13.129,1354.2,305.37
|
||||
13.179,343.9,76.77
|
||||
13.229,692.5,153.38
|
||||
13.28,0.0,0.0
|
||||
13.33,0.0,0.0
|
||||
13.38,0.0,0.0
|
||||
13.43,2362.5,496.01
|
||||
13.483,693.6,143.63
|
||||
13.533,1466.7,300.97
|
||||
13.583,555.0,112.79
|
||||
13.633,184.3,37.4
|
||||
13.683,0.0,0.0
|
||||
13.735,0.0,0.0
|
||||
13.785,1917.4,375.17
|
||||
13.838,542.8,105.29
|
||||
13.888,1144.2,222.78
|
||||
13.938,1513.8,297.05
|
||||
13.988,568.4,111.69
|
||||
14.038,378.0,74.42
|
||||
14.088,0.0,0.0
|
||||
14.139,0.0,0.0
|
||||
14.189,1933.6,372.51
|
||||
14.239,955.5,184.91
|
||||
14.289,756.9,148.61
|
||||
14.374,662.1,132.25
|
||||
14.424,554.7,112.16
|
||||
14.474,0.0,0.0
|
||||
14.524,0.0,0.0
|
||||
14.577,1603.7,323.84
|
||||
14.627,1276.0,263.01
|
||||
14.677,542.3,113.23
|
||||
14.727,714.5,150.87
|
||||
14.777,354.7,75.59
|
||||
14.83,0.0,0.0
|
||||
14.88,0.0,0.0
|
||||
14.93,1795.9,379.83
|
||||
14.98,355.3,75.74
|
||||
15.031,1386.0,301.97
|
||||
15.083,330.9,73.04
|
||||
15.133,688.3,153.24
|
||||
15.183,170.9,38.24
|
||||
15.234,0.0,0.0
|
||||
15.284,0.0,0.0
|
||||
15.334,0.0,0.0
|
||||
15.384,2304.1,499.06
|
||||
15.435,1027.8,225.69
|
||||
15.485,1024.9,230.47
|
||||
15.536,1000.9,229.21
|
||||
15.586,664.6,153.64
|
||||
15.636,665.2,154.54
|
||||
15.687,0.0,0.0
|
||||
15.737,0.0,0.0
|
||||
15.788,0.0,0.0
|
||||
15.84,2131.8,478.6
|
||||
15.89,856.1,192.06
|
||||
15.941,1025.4,230.39
|
||||
15.991,342.4,76.74
|
||||
16.043,663.2,148.34
|
||||
16.093,0.0,0.0
|
||||
16.143,0.0,0.0
|
||||
16.193,0.0,0.0
|
||||
16.246,2555.4,545.64
|
||||
16.296,895.5,189.56
|
||||
16.373,694.2,146.49
|
||||
16.424,1443.5,302.27
|
||||
16.476,0.0,0.0
|
||||
16.526,0.0,0.0
|
||||
16.577,0.0,0.0
|
||||
16.627,2074.2,414.87
|
||||
16.677,751.3,149.12
|
||||
16.727,1123.6,223.97
|
||||
16.777,374.5,74.66
|
||||
16.827,1122.8,223.93
|
||||
16.88,0.0,0.0
|
||||
16.93,0.0,0.0
|
||||
16.98,0.0,0.0
|
||||
17.03,2296.0,447.62
|
||||
17.08,379.9,74.23
|
||||
17.13,1503.9,297.32
|
||||
17.18,563.4,111.98
|
||||
17.233,538.0,107.34
|
||||
17.283,0.0,0.0
|
||||
17.333,0.0,0.0
|
||||
17.383,1890.3,373.65
|
||||
17.433,1119.5,223.93
|
||||
17.485,361.3,72.88
|
||||
17.535,1651.2,337.72
|
||||
17.585,365.1,75.24
|
||||
17.635,547.2,113.12
|
||||
17.686,0.0,0.0
|
||||
17.736,0.0,0.0
|
||||
17.786,0.0,0.0
|
||||
17.839,2490.6,503.11
|
||||
17.892,1033.4,213.33
|
||||
17.942,1073.2,226.83
|
||||
17.995,670.1,143.94
|
||||
18.045,1223.2,266.8
|
||||
|
40
docs/re/captures/rate-curve-windowed.csv
Normal file
40
docs/re/captures/rate-curve-windowed.csv
Normal file
@@ -0,0 +1,40 @@
|
||||
t,speed_units_per_wall_s,rate_deg_per_wall_s
|
||||
0.52,766.4,15.56
|
||||
1.06,875.3,81.57
|
||||
1.56,319.7,79.47
|
||||
2.08,589.5,124.0
|
||||
2.6,833.9,118.23
|
||||
3.1,846.4,144.01
|
||||
3.62,682.9,147.83
|
||||
4.12,442.3,114.32
|
||||
4.62,782.3,183.76
|
||||
5.13,869.9,160.12
|
||||
5.66,691.9,117.79
|
||||
6.18,770.1,146.5
|
||||
6.68,659.7,149.99
|
||||
7.19,546.7,135.85
|
||||
7.7,760.5,163.7
|
||||
8.2,645.7,121.72
|
||||
8.72,884.3,159.2
|
||||
9.26,546.3,107.3
|
||||
9.78,633.0,139.66
|
||||
10.28,716.1,169.56
|
||||
10.8,607.5,129.02
|
||||
11.32,866.0,156.23
|
||||
11.82,677.8,119.63
|
||||
12.32,537.0,103.57
|
||||
12.82,821.2,187.87
|
||||
13.34,545.6,133.44
|
||||
13.86,608.8,128.22
|
||||
14.38,778.1,141.08
|
||||
14.88,543.6,93.59
|
||||
15.38,935.1,176.36
|
||||
15.9,708.2,159.77
|
||||
16.4,439.7,105.71
|
||||
16.9,847.5,185.58
|
||||
17.42,584.5,112.34
|
||||
17.94,874.4,158.62
|
||||
18.44,733.0,149.31
|
||||
18.96,527.8,128.4
|
||||
19.46,642.2,156.88
|
||||
19.98,737.8,149.45
|
||||
|
@@ -545,3 +545,43 @@ better and gives the whole rate-vs-speed curve rather than two points.
|
||||
reimplementation that treats the throttle as setting a speed the craft simply holds
|
||||
will be wrong during manoeuvres. Data:
|
||||
[`captures/pitch-rate-speed-bleed.csv`](captures/pitch-rate-speed-bleed.csv).
|
||||
|
||||
|
||||
## ⚠️ Polling faster than the guest updates manufactures a curve
|
||||
|
||||
Trying to fit rate against *instantaneous* speed (`rate_curve.py`, one long hold so
|
||||
the speed-bleed sweeps the range) produced a beautifully clean result that is
|
||||
entirely an artefact:
|
||||
|
||||
```
|
||||
speed 0- 599 rate 29.4 speed 1199-1798 rate 279.8
|
||||
speed 599-1199 rate 174.9 speed 1798-2398 rate 317.5
|
||||
```
|
||||
|
||||
Rate rising with speed, and speeds to **4 795** when the craft's maximum is 1 200.
|
||||
The cause: **20 Hz polling is faster than the guest updates these fields**, so a
|
||||
per-read delta is either exactly zero (no update yet) or a whole frame's worth
|
||||
divided by a fraction of a frame. In that run **111 of 352 reads were zero on BOTH
|
||||
channels** — position and attitude update on the same frame, so the two are
|
||||
perfectly correlated, and dividing each by the short wall `dt` produced a tidy
|
||||
correlation out of nothing.
|
||||
|
||||
**Fix: aggregate over windows spanning many frames** (0.5 s here). The sum of
|
||||
`|Δ|` over a window is right however the updates fall inside it.
|
||||
|
||||
**This does NOT affect the swept-total probes** (`roll_axis.py`, `rate_probe.py`):
|
||||
they already summed over the whole dwell, which is immune for the same reason. Only
|
||||
per-sample instantaneous rates were ever wrong.
|
||||
|
||||
🟡 **The windowed re-run is not yet a result.** It gives plausible magnitudes
|
||||
(speed 320–935, rate 80–149 °/wall-s) but still shows rate *rising* with speed,
|
||||
against the definition's `AV_PitchPlus_Min` 150 > `_Max` 70. Two disqualifiers: it
|
||||
ran on an instance where the craft was already tumbling from the previous sweep, so
|
||||
the row pinning reported **WEAK — craft may not be level**, and the starting speed
|
||||
was mid-range rather than maximum. A clean answer needs a **fresh flight**, pinning
|
||||
CONFIDENT, one sweep, nothing before it. Recorded as an open question rather than a
|
||||
finding — the definitions' `_Min`/`_Max` meaning is exactly what is in doubt, so a
|
||||
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).
|
||||
|
||||
117
tools/re-capture/rate_curve.py
Executable file
117
tools/re-capture/rate_curve.py
Executable file
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Angular rate as a FUNCTION of speed — fitted, not sampled at two endpoints.
|
||||
|
||||
The two-point probe (`rate_probe.py`) assumed the craft held the speed its throttle
|
||||
selects. It does not: full pitch bleeds 1 193 -> 589 in eight seconds *with the
|
||||
throttle still at maximum*, so an 8-second average is taken over a moving speed and
|
||||
lands between two different caps. That is how a measured pitch rate came out 33 %
|
||||
ABOVE its own cap.
|
||||
|
||||
Turn the bug into the instrument. Because the speed bleeds on its own, one long hold
|
||||
sweeps the whole range, so sampling position *and* attitude together gives
|
||||
`(speed, rate)` pairs across it — the entire curve from a single phase, with no
|
||||
assumption about what speed the craft is at.
|
||||
|
||||
Speed comes from the position deltas (no HUD OCR needed). Both speed and rate are
|
||||
per wall-second here; the run's clock ratio converts both to game units afterwards
|
||||
and cancels out of the SHAPE of the curve.
|
||||
|
||||
⚠️ SAMPLE IN WINDOWS, NOT PER READ. Polling at 20 Hz is faster than the guest
|
||||
updates these fields, so a per-read delta is either exactly zero (no update yet) or
|
||||
a whole frame's worth divided by a fraction of a frame. In a first run 111 of 352
|
||||
reads were zero on BOTH channels — position and attitude update on the same frame,
|
||||
so the two are perfectly correlated, and dividing each by the short wall dt
|
||||
manufactured a clean "rate rises with speed" curve out of pure aliasing. Summing
|
||||
|delta| over a window that spans many frames is immune: the total is right however
|
||||
the updates fall inside it. (This is also why the swept-total probes were never
|
||||
affected — only per-sample instantaneous rates were.)
|
||||
|
||||
Usage: rate_curve.py <roll|pitch> <out.csv> [dwell_s]
|
||||
"""
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
import speed_law # noqa: E402
|
||||
from axis_probe import alive, pad_state, pin_rows, rows_at, dot # noqa: E402
|
||||
|
||||
DRIVER = {"roll": {"lx": 32767}, "pitch": {"ly": 32767}}
|
||||
|
||||
|
||||
def shot(n):
|
||||
subprocess.run(["screenshot", f"/sylph-home/re/shots/{n}.png"], capture_output=True)
|
||||
|
||||
|
||||
def pos_at(fd, off):
|
||||
return struct.unpack(">3f", os.pread(fd, 12, off))
|
||||
|
||||
|
||||
def main():
|
||||
axis, out_csv = sys.argv[1], sys.argv[2]
|
||||
dwell = float(sys.argv[3]) if len(sys.argv) > 3 else 16.0
|
||||
cfg = json.load(open("/tmp/nav-live.json"))
|
||||
w, off, nm = speed_law.find_player()
|
||||
if not w:
|
||||
sys.exit("player entity not found")
|
||||
f_i = cfg["fwd_row"]
|
||||
if not alive(w, off, cfg):
|
||||
sys.exit("craft is not moving")
|
||||
u_i, w_i = pin_rows(w, off, cfg)
|
||||
print(f"# locked on {nm}, sweeping {axis}")
|
||||
|
||||
# Start at maximum speed and let the turn bleed it: one hold, whole range.
|
||||
pad_state(rt=255)
|
||||
time.sleep(6.0)
|
||||
shot(f"curve_{axis}_a")
|
||||
prev_r, prev_p, prev_t = rows_at(w.fd, off, cfg), pos_at(w.fd, off), time.time()
|
||||
pad_state(rt=255, **DRIVER[axis])
|
||||
t0 = time.time()
|
||||
rows = []
|
||||
WIN = 0.5 # seconds per emitted point: many guest frames
|
||||
win_t0, win_path, win_swept = time.time(), 0.0, 0.0
|
||||
while time.time() - t0 < dwell:
|
||||
time.sleep(0.02)
|
||||
now = time.time()
|
||||
cur_r, cur_p = rows_at(w.fd, off, cfg), pos_at(w.fd, off)
|
||||
win_path += math.dist(cur_p, prev_p)
|
||||
if axis == "roll":
|
||||
d = math.atan2(dot(cur_r[u_i], prev_r[w_i]), dot(cur_r[u_i], prev_r[u_i]))
|
||||
else:
|
||||
d = math.atan2(dot(cur_r[f_i], prev_r[u_i]), dot(cur_r[f_i], prev_r[f_i]))
|
||||
win_swept += abs(math.degrees(d))
|
||||
prev_r, prev_p = cur_r, cur_p
|
||||
if now - win_t0 >= WIN:
|
||||
span = now - win_t0
|
||||
rows.append((round(now - t0, 2), round(win_path / span, 1),
|
||||
round(win_swept / span, 2)))
|
||||
win_t0, win_path, win_swept = now, 0.0, 0.0
|
||||
pad_state()
|
||||
shot(f"curve_{axis}_b")
|
||||
|
||||
with open(out_csv, "w") as f:
|
||||
f.write("t,speed_units_per_wall_s,rate_deg_per_wall_s\n")
|
||||
for r in rows:
|
||||
f.write(",".join(str(x) for x in r) + "\n")
|
||||
|
||||
# Bin by speed so the shape is visible without any curve-fitting assumption.
|
||||
print(f"# {len(rows)} windows of {WIN}s; rate binned by speed (per WALL second):")
|
||||
lo = min(r[1] for r in rows)
|
||||
hi = max(r[1] for r in rows)
|
||||
print(f"# speed swept {lo:.0f} -> {hi:.0f} units/wall-s")
|
||||
nb = 6
|
||||
for b in range(nb):
|
||||
a = lo + (hi - lo) * b / nb
|
||||
z = lo + (hi - lo) * (b + 1) / nb
|
||||
sel = [r[2] for r in rows if a <= r[1] < z]
|
||||
if sel:
|
||||
print(f"# speed {a:7.0f}-{z:7.0f} n={len(sel):3d} rate {sum(sel)/len(sel):6.1f}")
|
||||
print(f"# wrote {out_csv}; read HUD TIME off curve_{axis}_[ab] for the clock")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user