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
|
reimplementation that treats the throttle as setting a speed the craft simply holds
|
||||||
will be wrong during manoeuvres. Data:
|
will be wrong during manoeuvres. Data:
|
||||||
[`captures/pitch-rate-speed-bleed.csv`](captures/pitch-rate-speed-bleed.csv).
|
[`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