Repository navigation
Known lane: count co-sited receivers as one site, withhold single-site solves - #663
Conversation
…e solves Two receivers within the co-location radius (node_sites, NODE_FUZZ_SITE_KM, 150 m) share the receiver focus of every bistatic ellipse they measure, so their loci cross at half the angle their transmitters subtend at the target. An n=2 from them is not the n=2 two sites give. On test, a271b0 (two receivers 56 m apart) solved 4.95, 2.32 and 1.90 km off. Over 21 min of live known-lane history, co-sited n=2 attempts were ghosts 43% of the time against 5% for two-site pairs, and the ones published sat a median 0.76 km off against 0.11 km. - node_sites.count_sites: the public-geometry grouping over a given node set, pure (no snapshot, no DB). - known_lane._count_sites: sites among the claim set, from the solve's own node configs; stamped as n_sites on history records and accuracy samples. - Binding publish gate "single_site" (counter known_lane_publish_single_site, reported in solver-stats), checked before the rms gate. Measurement, label and sample are unchanged. - Single-site ghosts never re-anchor: a degenerate geometry repeats its wrong answer, so self-agreement is no evidence. - Fix the comment claiming n=2 solves always carry rms_delay 0.0; the rms gate applies at every n (test pins the 3.59 us n=2 case). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Claude finished @jehanazad's task in 2m 15s —— View job Review complete
SummaryThis is a well-scoped, well-tested fix. I read the full diff ( Correctness
Repo-instruction gates (per CLAUDE.md)
Nit (non-blocking)
Tests No correctness issues found. This looks ready to merge from a code standpoint. |
…tes (#671) #663 withheld every known-lane solve whose receivers shared a site. That reads the wrong variable. A node's delay puts the aircraft on a curve whose normal is the sum of the unit vectors from its transmitter and from its receiver, so two nodes on one roof cross at half the angle their TRANSMITTERS subtend at the aircraft: a good pair with towers either side of it, none with towers on one farm, and which of the two changes from one aircraft to the next. Receivers far apart are no fix either when the aircraft is distant enough that every focus lies one way, and the site rule published those. On test, 2026-10-02, the one real n=2 pair (receivers co-sited, towers 18 km apart, 981 solves in 26 min) was 3% ghosts where a microsecond of delay error is under 2 km of position, 8% from 2 to 3, 33% from 3 to 4 and 61% over 8. The site rule withheld all of them alike. - services/solve_geometry.delay_dop_km_per_us: the dilution of precision of the delay loci at a pinned altitude, sqrt(trace((sum g g^T)^-1)) over the nodes' horizontal bistatic-range gradients, in km per microsecond. It is the crossing angle's generalisation to any node count, so three or four receivers on one roof are judged by the same number as two. None when a node's geometry is unknown, which never demotes a solve. - Binding publish gate "weak_geometry" (KNOWN_PUBLISH_MAX_DELAY_DOP_KM_PER_US, 3.0, 0 disables; counter known_lane_publish_weak_geometry) in place of "single_site", evaluated at the transponder's position rather than the solve's. Checked before the rms gate. Measurement, label and sample are unchanged. - History records and accuracy samples carry delay_dop_km_per_us in place of n_sites. node_sites.count_sites had no other caller and goes. - Ghosts from a geometry the gate would withhold never re-anchor; a co-sited pair on separate towers now can. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Problem
On test (2026-09-30), real aircraft a271b0 was claimed by two real nodes (213 MHz and 201 MHz) whose receivers are 56 m apart and whose transmitters differ. The known lane counted that as n=2 and ran free solves: 4.95 km and 2.32 km off (labelled ghost), then 1.90 km off, which the rms_delay publish gate withheld at 3.59 µs.
Two receivers on one roof share the receiver focus of every bistatic ellipse they measure. The normal of each delay locus bisects the directions to the transmitter and the receiver, so with a common receiver the two loci cross at half the angle the two transmitters subtend at the target. At both co-sited pairs on test the transmitters sit on the same side, which makes that angle shallow, and at a pinned altitude the loci can graze or miss each other entirely. Counting such a pair as two independent nodes overstates the geometry.
The comment at the rms gate also said n=2 solves "carry 0.0". That is false: this one carried 3.59 µs.
Evidence (live known-lane history on test, 21 min, 5 671 attempts)
Sites were grouped by the published node positions. The fuzz shares one point per site under the #359 rule, so this is exactly the site grouping.
Change
node_sites.count_sites(positions): the public-geometry grouping (exact equality, thenNODE_FUZZ_SITE_KM, default 150 m) over a given node set. It is pure: no snapshot and no DB. No new constant.known_lane._count_sites: counts sites among the claim set from the solve's own node configs. An unplaced or unknown node counts as its own site, so the unknown case can never demote a solve.single_site: a solve whose claims come from fewer than two sites is still attempted, classified, sampled and recorded, but it is never published. The aircraft is left to the ADS-B display path, which a sibling PR onaircraft_feed.pycovers.known_lane_publish_single_site, reported asknown_lane.publish_single_sitein solver-stats.n_sitesis stamped on history records and accuracy samples.Unchanged:
n_sitesis there to bin them.vel_untrustedstill keys on node count.Dark lane: same defect, not fixed here
The dark lane counts
n_nodes = len(matched_node_ids)(retina-analytics association) with no site notion. In the same window, 3 725 of 4 481 dark-lane records were n=2 from a single site, almost all from one Atlanta pair, and mostly rejected (beam, n2_unconfirmed, rms). However, 11 were published: 4.2 % of all 264 dark publishes, every one 119–169 km from the nearest aircraft. This needs a follow-up in the dark lane or the association.Tests
test_known_lane.py::TestSingleSiteGate, 10 tests: the co-sited pair is withheld under both the stub and the real LM solver; a receiver 200 m away counts as a second site; 3 nodes at 2 sites still publish;NODE_FUZZ_SITE_KM=0narrows the gate to exact matches; an unplaced node counts as its own site; shadow mode never counts; the no-converge record carriesn_sites; re-anchoring is blocked.test_known_lane.py: new n=2 rms gate test.test_node_sites.py::TestCountSites.test_solver_stats.py: updated for the new key.The known_lane, solver_report, node_sites and accuracy test files all pass (22 files), and pre-commit is clean.
🤖 Generated with Claude Code