Repository navigation
Match detections to where each aircraft is, not where it was - #76
Merged
Merged
Conversation
The detection-to-ADS-B matcher compared every detection against each aircraft's position as last reported. With a feed about 1 s fresh that was close enough; adsb.retina.fm positions reach blah2-api 1-15 s old, and near the baseline an airliner's Doppler moves ~5 Hz/s, so the age alone put real aircraft outside the 5 Hz tolerance. On jonathan-node-1 an overflight seen at SNR 11-20 never matched, and tagged tracks fell from ~230 a day to almost none. Each aircraft is now projected to the detection's timestamp before matching, once per frame, using the existing constant-velocity extrapolatePosition. The matcher allows positions up to 20 s old (the overlay keeps its 10 s), drops records it cannot project, and passes the barometric climb rate through as geom_rate so a climbing aircraft gets the right Doppler. Matches carry a new position_age field. Position times now come from the payload's own `now` minus seen_pos. The tar1090 proxy sets `now` to when it fetched the data, so measuring seen_pos from our own clock made every cached position look younger than it was. The /api/adsb2dd overlay uses the same stamp. Measured live on jn1, 1200 frames, old and new matcher run side by side on the same frames and feed: 4 -> 140 matched detections, 2 -> 6 aircraft, one overflight matched continuously as its Doppler swept +158 to -182 Hz. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
What
The detection-to-ADS-B matcher in
api/server.jscompared each detection against every aircraft's position as last reported. It now projects each aircraft to the detection's timestamp first. It uses the existing constant-velocityextrapolatePosition, once per frame.Why
The matcher only worked while the feed was about 1 s fresh. Since retina-node v0.4.7.0 (2026-09-27), nodes take positions from adsb.retina.fm, which reach blah2-api 1-15 s old. Near the baseline an airliner's Doppler changes by about 5 Hz/s, so position age alone puts real aircraft outside the 5 Hz tolerance.
On jonathan-node-1:
seen_pos.Changes
lib/extrapolation.jsaircraftAtTimestamp()projects every aircraft to the detection time. It drops aircraft it can't project (too old, or no speed or heading, which bistatic.js needs for a Doppler anyway). Records with no position time are passed through unchanged.MATCH_MAX_POSITION_AGE_S). The/api/adsb2ddoverlay keeps its 10 s limit (MAX_EXTRAPOLATION_S). Half of adsb.retina.fm's positions were over 10 s old on jn1.geom_rate, the only rate field bistatic.js reads.nowminusseen_pos(stampPositionTimes()). The tar1090 proxy setsnowto its fetch time, so measuring from our own clock made cached positions look younger than they were. The overlay uses the same stamp.position_agefield (s). All existing fields are unchanged, butlat/lon/altare now the projected position.Testing
api/test_adsb_position_age.js, 28 checks.nowhandling.test_alt_baro_fallback,test_tar1090_extrapolation,test_bistatic,test_timestamp_units,test_tracker_forward.Live side-by-side on jn1. The old and new matchers ran on the same 1200 frames and the same feed, read-only inside the running container:
One overflight (JBU385) matched continuously as its Doppler swept +158 to -182 Hz.
Deployed to jn1 as a hand-swapped hot-patch since 2026-10-05 15:15 UTC and confirmed working live. The overlay still places 82-85% of aircraft.
Known gaps
20261002-blah2-api-performancebranch, which moves this matcher intolib/adsb_match.js. Whichever merges second needs a small rebase, and that branch's equivalence test will need updating, since this change alters matching deliberately.Docs
None changed. blah2-arm has no prose docs covering the matcher (
doc/is generated Doxygen output only), so the reasoning lives in the code comments and this PR.🤖 Generated with Claude Code