Repository navigation
fix(pipe): motion-check orphan pair resolutions on locked ICAOs - #206
Open
mikehartley wants to merge 1 commit into
Open
mikehartley wants to merge 1 commit into
mikehartley wants to merge 1 commit into
Conversation
When a CPR frame pairs with more than one fresh opposite, the older opposites are resolved as orphan pairs, independently of the primary, and their results were written back sharing the primary's motion verdict. An orphan built from a corrupted (but CRC-valid) older frame can resolve far from the primary, e.g. a latitude-zone or longitude-zone error, and reached the caller unchecked. For locked ICAOs each orphan resolution now goes through the same motion check as the primary; a failing one is cleared and counted in position_rejected. Bootstrapping ICAOs are unchanged.
This branch has not been deployed
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.
While decoding my own receiver's feed with PipeDecoder I found occasional positions thousands of km from the aircraft's track. They come from orphan CPR pairs.
When an airborne position frame arrives with more than one fresh opposite-parity frame pending, _handle_cpr_pair resolves the most recent one as the primary pair and the older ones as orphan pairs. For an ICAO that has passed bootstrap, only the primary resolution goes through _motion_consistent, and the orphans share its verdict. An orphan resolves independently, though: if its older frame is corrupted (CRC-valid, CPR bits wrong), it can land far from the primary and is still written into that frame's result.
Example, aircraft 4CAA5F tracked near 52.47 N, 0.92 W: two even frames are pending when an odd one arrives. The older even, 8D4CAA5F608BB333B439270755FB, is corrupted. The primary pair is correct and passes the motion check; the orphan resolves at 70.77 N, 78.21 E and is returned unchecked. I have seen the same on an aggregated feed, where two receivers relayed different versions of one frame at the same moment, with the orphan's longitude exactly one zone (10deg) out.
Proposed change:
For locked ICAOs, when the primary is accepted, run each orphan's resolution through _motion_consistent as well, clear the ones that fail and count them in position_rejected, as for a rejected primary. Bootstrapping ICAOs are unchanged, and accepted orphans still do not enter the position history, as before.
Test:
test_orphan_pair_checked_on_its_own in TestPositionMotionConsistency uses the three real frames above. It fails on current main (the corrupted frame's latitude is 70.77) and passes with the change. The rest of the suite is unaffected.
Consideration:
This should not cost genuine positions. A genuine orphan is a real position from at most pair_window (10s) before a primary that has just passed the motion check, so it is within a few km of it, far inside the check's allowance (1500 kt plus 2 km by default, measured to the primary's later timestamp). In practice only a mis-resolved orphan fails, such as one built from a corrupted frame, or from a pair straddling a latitude-zone boundary, which is wrong anyway.