20260915 - Fit R and Q out of the innovations, along the prediction interval - #34
Conversation
…nterval The records exist; nothing reads them. This reads them, and it exists now rather than after the capture because a day's analysis written while the data is sitting there is a day the calibration is not landing. R and Q cancel, so neither can be fitted alone and NIS moves the wrong way for both. What separates them is that only one grows with how long the filter had been predicting: var(nu | L) = R + a * L^p, with R the intercept. Fixing p makes the rest linear in R and a, so a grid over p reduces the whole thing to a 2x2 solve per candidate and it stays stdlib-only, which is what lets it be copied onto a node like live_score. p is the finding, not just a nuisance parameter. Live data said the model error grows as L^1.96 where white jerk, which is what Q implements, would be L^5. An exponent near 2 says no jerk value fits and the adaptive scale cannot converge, and that is a different repair from raising range_jerk. Scatter is also reported per axis against the S the filter claimed. NIS sums the two axes into one number, which is precisely how an oversized R and an undersized Q have been hiding in it. The innovation record now carries the occupancy map's verdict per detection, so the interference that is three quarters of the tracks at both nodes is dropped on evidence rather than on a track's Doppler holding still. The old heuristic stays for records written before the map landed, and it is worth less than it looks: it costs the genuine constant-Doppler aircraft too. Verified by synthesising records from a known R and a known velocity error and asserting both come back. From the plan's own measured figures it recovers 0.141 and 0.181 cells against 0.15 and 0.18, and an exponent of 2.05 against 1.96. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @Purple10101's task in 8m 23s —— View job Claude's review
Note: I was not able to execute Findings1.
This should key on 2. The "not enough spread to separate R from Q" message is dead code (calibrate.py:243, :277)
3. The real Doppler bin width is 4.
5.
Not flaggingThe added prose-style comments throughout SummaryThe core statistical approach is solid and the tests do genuinely validate recovery of known parameters rather than asserting the tool's own output back at itself, which is the right instinct. The most important fix is #1 — the |
The innovation records from #32 exist and nothing reads them. This reads them.
It is here before the capture rather than after it because a day of analysis written while the data sits on a node is a day the calibration is not landing. When the recording arrives this is one command.
How R and Q are separated
They cancel, which is why neither can be fitted alone and why NIS moves the wrong way for both. What separates them is that only one of the two grows with how long the filter had been predicting:
Ris the intercept. Fixingpmakes the rest linear inRanda, so a grid overpreduces the whole thing to a 2x2 solve per candidate, weighted by sample count. That keeps it stdlib-only, which is what lets it be copied onto a node and run under whatever python3 is there, the same constraintlive_scoreis written to.pis a finding in its own right, not a nuisance parameter. Live data said the model error grows asL^1.96; white jerk, which is whatQcurrently implements, would beL^5. An exponent near 2 says no single jerk value fits and the adaptive scale cannot converge, and that is a different repair from raisingrange_jerk.Spread is measured by MAD rather than standard deviation throughout. Calibration data comes off a live node, so it has mis-associations in it, and one of those should not be allowed to set the answer.
What it reports
Rin resolution cells is the number Phase 2 ships: onek, measured once, validated across sites. Pass more than one file and it prints the spread across every axis-site pair, since two axes agreeing in cell units is time-bandwidth duality holding and is the main evidence the measurement is sound.Scatter against claimed
Sis reported per axis deliberately. NIS sums both axes into one scalar, which is exactly how an oversizedRand an undersizedQhave been hiding inside it.Also here
The innovation record now carries
interfering, the occupancy map's verdict on that detection, so calibration drops the interference on evidence rather than inferring it. That matters at both live nodes, where three quarters of tracks are built on the tone and would otherwise be fitted to. The Doppler-holding-still heuristic stays for records written before #33 landed, and it is worth less than it looks: it costs the genuine constant-Doppler aircraft along with the tone, which biases what is left toward manoeuvring targets. Worth something forR, worth less forQ, and the docstring says so.Verification
ruff check(E, F, W) clean,ruff format --checkclean,pre-commit run --all-filesclean including the dead-code gate, 333 passed / 1 xfailed.The tests synthesise records from a known
Rand a known velocity error and assert both come back, rather than asserting the tool's own output back at it. Seeded with the plan's measured figures it recovers 0.141 and 0.181 cells against 0.15 and 0.18, and an exponent of 2.05 against 1.96. It also tellsL^5fromL^2, declines to fit when the prediction intervals are all the same (one equation, two unknowns), and one test runs a realTrackerinto anInnovationWriterand calibrates the file, so the field-name contract between the two is pinned rather than assumed.What this does not do
It measures. It changes no tracker constant:
RandQstill ship exactly as they were, and reshaping them is the next change, once there is a recording from both nodes to measure.🤖 Generated with Claude Code