Skip to content

Commit d42b60f

Browse files
committed
chore: release v3.1.0
1 parent 0924a09 commit d42b60f

2 files changed

Lines changed: 44 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,49 @@ All notable changes to pyModeS are documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/).
77

8+
## [3.1.0] — 2026-04-14
9+
10+
Streaming-robustness release. Adds defences against phantom positions
11+
at stream start and against DF20 CRC-collisions that attribute a
12+
Comm-B reply to the wrong aircraft.
13+
14+
### Added
15+
16+
- `PipeDecoder` bootstrap cluster analysis for the first position per
17+
ICAO: lat/lon emission is held until `_BOOTSTRAP_K` (=5) candidate
18+
positions agree under a motion-consistency check. Prevents an
19+
initial phantom frame from anchoring the rolling position history.
20+
On each decode the held result dicts are retro-filled once the
21+
cluster locks. Scattered buffers reset and accumulate a fresh K.
22+
- `PipeDecoder` altitude cross-check on DF20 Comm-B replies: if the
23+
message's 13-bit AC-code disagrees with the ICAO's most recent
24+
ADS-B-derived altitude by more than `_altitude_tolerance(dt)` (a
25+
linearly growing, floored-and-capped window), the BDS payload
26+
fields are stripped from the result and `altitude_mismatch=True`
27+
is set. The AC-code altitude itself is preserved so callers see
28+
why the frame was flagged.
29+
- `PipeDecoder.flush()` method that finalizes any still-bootstrapping
30+
ICAOs, running cluster analysis on whatever candidates are
31+
buffered (even if fewer than K) and retro-filling the held result
32+
dicts in place. Automatically called by the batch `decode(list,
33+
timestamps=list)` code path so batch callers get positions on
34+
every resolvable frame without having to reach into `PipeDecoder`.
35+
- Four new per-stream stat counters exposed via `PipeDecoder.stats`:
36+
`altitude_mismatch`, `position_rejected`, `bootstrap_held`,
37+
`bootstrap_reset`.
38+
39+
### Fixed
40+
41+
- `airborne_position_pair` now rejects CPR pairs that resolve to
42+
physically impossible latitudes (|lat| > 90). Root cause: real
43+
DF17 pairs that straddle a `cprNL` zone can slip past the
44+
pre-pair `NL(lat_even) == NL(lat_odd)` check and produce
45+
latitudes in [90, 270) — e.g. an aircraft climbing out of
46+
Amsterdam resolving to lat ≈ 113° over the Bering Sea.
47+
Observed on ICAO 485A33 (2025-04-13 19:34:57 UTC, OpenSky feed)
48+
— now rejected at the pair resolver rather than poisoning the
49+
receiver's position history.
50+
851
## [3.0.0] — 2026-04-13
952

1053
First release of the v3 ground-up rewrite. **Not backwards-compatible

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "pyModeS"
3-
version = "3.0.0"
3+
version = "3.1.0"
44
description = "Python Mode-S and ADS-B Decoder"
55
authors = [{ name = "Junzi Sun", email = "git@junzis.com" }]
66
license = { text = "GNU GPL v3" }

0 commit comments

Comments
 (0)