Publish a synthetic node's declared cone as its detection area (#32 onto main) - #33
Merged
Merged
Conversation
get_node_summary publishes to_polygon(evidence_only=True) for every node. That is right for real hardware — a real node's beam_azimuth_deg and beam_width_deg are unsurveyed configuration, so drawing them would claim coverage nobody measured — but it is wrong for a simulator node. The simulator emits a detection only for an aircraft inside the node's declared cone (retina_simulation/world.py::_aircraft_in_detection_cone), so for those nodes the cone IS the detection area by definition, and the evidence is the unreliable half: the calibration points come from ADS-B hexes bound to tracks and roughly a third of those binds are to the wrong aircraft. Measured on test 2026-09-13, synth-GVL-SCAT-0032 (42 deg beam) held 3,037 calibration points of which 47% lay outside its wedge (34% ignoring the two edge bins), 55 out-of-wedge bins had opened, and the published polygon covered 71 of 72 bearings. Every synthetic node on the test map draws as a disc. So: EmpiricalCoverageState.declared_wedge_polygon() draws the prior azimuth and width at _reach_at on each bearing — already the bistatic ellipse when a differential limit and the TX are known, else the circle, which is exactly the simulator's own range rule — with no clamp, no bins and no min-points gate. An omni prior gets a full ring; a directional one an apex-closed wedge with both edges exact. NodeAnalyticsManager.register_node grows a keyword-only declared_geometry_is_truth flag (default False, asserted per registration, so a re-registration without it drops the node again), and get_node_summary publishes the declared wedge for a flagged node and the evidence-only shape for everyone else. The FOV diagnostics block is skipped for a flagged node — it describes the learned wedge, which such a node does not publish — while n_points/n_filled_bins stay in the payload: the evidence is still accumulated and still worth reporting, it just is not drawn. Every summary now names its "polygon_source" (declared / evidence / learned) so the map can say which it is showing rather than guess. A flag change invalidates the 60 s summaries cache the same way a rebuilt detection area does; retire_node, _reset_for_tests and the "cannot place this node" path all clear it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Publish a synthetic node's declared cone as its detection area
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lands #32 on
main. #32 was merged into its stacked base branchfeat/evidence-only-coveragerather than retargeted tomainfirst (the repo does not delete branches on merge, so GitHub did not retarget it). This PR carries only #32's two commits; #28 is already onmainvia its merge commit.Merged with a merge commit so the head
6df7c3dthat offworldlabs/retina-server#367 pins as thelibs/retina-analyticssubmodule stays reachable frommain.🤖 Generated with Claude Code