Holocron · contact correlation
A grid search only finds every duplicate if the neighbourhood it scans is
at least as wide as the distance gate. A degree of longitude is
2.75 km at 34.5°N but only 1.09 km at 71°N, so a
fixed 3×3 ring of 0.03° cells stops covering a 2886 m gate
— everywhere in the theatre, and worst in the north. The gates say
duplicate; the index never presents the pair. Drag the second
contact below and watch the two disagree.
Contact A is fixed at centre. Drag B anywhere on the plot. Grid cells are drawn true to scale, so they visibly narrow as you raise the latitude.
Every sampled pair below is a genuine duplicate: inside the distance gate, matching heading and speed. The only question is whether the search ring ever puts the two in the same comparison.
240 duplicate pairs sampled per latitude, separations spread across the gate, sub-cell phase varied.
Each of these is an executable test in
src/utils/trackFusion.test.ts. The first three are what fusion
is for; the rest are the judgement calls.
| Behaviour | Prototype | Reworked |
|---|---|---|
| Search neighbourhood | Fixed 3×3 cells — narrower than the gate at every European latitude | Ring derived from the gate at the worst latitude it will scan |
| Absent heading / speed | NaN > 2 is false, so the gate silently passed | Reported unmeasurable; motionPolicy decides, and refuses by default |
| Which report survives | Whichever the map iterated first — could flip between frames | Union-find by minimum identifier; a pure function of the set |
| Retiring a track | Cleanup guarded by a predicate that always returned false — cells never released | One reconciliation point; a stale entry is structurally impossible |
| Cost per message | Full rescan and flag reset for every asset, on every message | Index updated per asset; clustering throttled to one pass per 150 ms |
| React state | Descriptions mutated inside the setState updater | Pure updater; identity preserved when no verdict changed |