GNU General Public License v3.0

技术解读

以下内容由 GitRead 中文社区 编辑团队基于项目 README 与官方资料整理, 结合中文开发者的常见使用场景补充技术选型建议。具体以项目官方文档为准。

深度分析:pyModeS —— 解码 Mode S 和 ADS-B 信号的利器

项目背景与痛点

在航空领域,Mode S 和 ADS-B 信号是空中交通管理和监视系统不可或缺的一部分。它们不仅用于飞机的识别和监视,还在飞行数据的收集与分析中发挥着重要作用。然而,数据的高密度与复杂性,使得对这些信号的解码和解析成为了一项技术挑战。正是在这个背景下,pyModeS 应运而生,提供了强大的 Python API 用于解码和处理 Mode S 和 ADS-B 数据,为这一领域的发展注入了新的活力。

核心技术揭秘

pyModeS 通过精确的信号解析算法,针对 Mode S 和 ADS-B 的二进制数据结构,实现了高效的数据解码与处理。这套库的设计集成了多种数据解码模式,支持多种信号格式,如 DF17/DF11/DF16 等,并实现了与民航标准 CYY 数据格式的兼容性。

数据流架构

以下简单展示了 pyModeS 的数据流架构,帮助理解其关键的工作流程:

graph TD A[接收数据] --> B{"数据类型?"} B -->|"DF11|DF16" | C[解码DF11/DF16] C --> D[转换为CYY数据] B -->|"DF17" | E[解码DF17] E --> F[处理ADS-B数据] D --> G[数据处理] F --> G G --> H[输出结果]

这一流程设计确保了从原始的信号数据到最终业务数据转换的高效和准确。

功能亮点与差异

pyModeS 在同类工具中脱颖而出,其亮点在于:

  1. 高度灵活性:支持多种 Mode S 和 ADS-B 数据格式的灵活处理。
  2. 高可靠性:经过大量测试和实践验证,确保数据处理过程中的准确性。
  3. 易用性:提供简洁直观的 API 接口,使得用户能够迅速上手并高效利用其功能。

相比其他同类工具,pyModeS 以其实用性、强大的功能支持和不断更新的特性,确立了其在航空数据处理领域的独特地位。

应用场景与落地建议

在生产环境中利用 pyModeS,需注意以下几点:

  • 数据来源的复杂性可能会带来一些挑战,建议在部署前进行充分的测试。
  • 针对需要高时效性的应用场景,应充分考虑系统性能,合理配置计算资源。

pyModeS 特别适合应用于航空交通监控系统、飞行数据记录、空中交通情报管理系统等。

综合评价

pyModeS 在处理 Mode S 和 ADS-B 信号解码方面表现优秀,具有高度的灵活性和可靠性。值得一提的是,项目持续活跃的维护和丰富的功能为用户提供了强大的支持。同时,面对航空数据处理的精细化需求,该库不断优化,带来更优的体验。

不过,与一切工具一样,pyModeS 也有不足之处。对于不同的数据源,数据预处理可能会有一些复杂性。总体来说,它是一个非常值得推荐的航空数据处理库。

关于

GitHub 原始描述(英文)

Python decoder for Mode S and ADS-B signals

描述取自 GitHub 官方 API,保持仓库作者书写的原文。

简要分析

热度分
1053
价值分
458
活跃状态
活跃

语言占比

Python
Shell

Release

README

pyModeS

Fast decoder for Mode-S and ADS-B messages in Python. Ground-up v3 rewrite of pyModeS with a single unified decode() function.

license

Install

pip install "pyModeS>=3"

Python 3.11+ required.

Usage examples

Single-message decode

The decode() function returns a Decoded dict with every decodable field populated in one pass.

from pyModeS import decode

result = decode("8D406B902015A678D4D220AA4BDA")
print(result)
# {
#     'df': 17,
#     'icao': '406B90',
#     'crc_valid': True,
#     'typecode': 4,
#     'bds': '0,8',
#     'callsign': 'EZY85MH',
#     'category': 0,
#     'wake_vortex': 'No category information',
# }

Batch decode (mixed message types)

Pass a list of hex strings and parallel timestamps in seconds. Any mix of downlink formats, typecodes, and Comm-B registers is fine — the dispatcher routes each message to the right decoder and uses the timestamps to resolve CPR pairs and disambiguate ambiguous Comm-B registers.

from pyModeS import decode

results = decode(
    [
        "8D406B902015A678D4D220AA4BDA",  # DF17 BDS 0,8 identification
        "8D485020994409940838175B284F",  # DF17 BDS 0,9 airborne velocity
        "8D40058B58C901375147EFD09357",  # DF17 BDS 0,5 airborne pos (even)
        "8D40058B58C904A87F402D3B8C59",  # DF17 BDS 0,5 airborne pos (odd)
        "A000178D10010080F50000D5893C",  # DF20 BDS 1,0 data link capability
        "A8000D9FA55A032DBFFC000D8123",  # DF21 BDS 6,0 heading & speed
    ],
    timestamps=[1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
)
assert results[0]["callsign"] == "EZY85MH"
assert results[1]["groundspeed"] == 159
assert results[3]["latitude"] is not None  # CPR pair resolved

Surface position with airport reference

Surface CPR needs a reference within ~45 NM. Pass an ICAO airport code (looked up in the shipped airport database) or an explicit (lat, lon) tuple.

from pyModeS import decode

# Real DF18 surface movement on LFBO (Toulouse-Blagnac).
r = decode("903a23ff426a4e65f7487a775d17", surface_ref="LFBO")
print(r["latitude"], r["longitude"])  # 43.6264..., 1.3747...

Streaming decoder

PipeDecoder is stateful — it holds per-ICAO state across calls, matches CPR pairs automatically, evicts stale aircraft after a TTL, and flags DF20/21 messages as icao_verified when their CRC-derived ICAO was seen recently in clean DF17/18 plaintext.

Pass timestamps in seconds from a consistent clock.

from pyModeS import PipeDecoder

pipe = PipeDecoder(surface_ref="EHAM")
for msg, timestamp in stream:
    decoded = pipe.decode(msg, timestamp=timestamp)
    if decoded.get("latitude") is not None:
        print(decoded["icao"], decoded["latitude"], decoded["longitude"])

See docs/quickstart.md for the full tour (full-dict mode, error handling, attribute access).

Low-level helpers

For ad-hoc message inspection that doesn’t need a full decode, pyModeS.util exposes thin wrappers around the bit/hex/CRC primitives: hex2bin, bin2int, hex2int, bin2hex, crc, df, icao, typecode, altcode, idcode, cprNL.

from pyModeS.util import hex2bin, crc, icao, typecode

msg = "8D406B902015A678D4D220AA4BDA"
hex2bin(msg)[:16]   # '1000110101000000'
crc(msg)            # 0 — valid DF17
icao(msg)           # '406B90'
typecode(msg)       # 4 — ADS-B identification

CLI

pyModeS ships with a modes command-line tool for ad-hoc decoding and live streaming.

modes decode — one-shot and file mode

# Decode one hex message (pretty-printed JSON)
modes decode 8D406B902015A678D4D220AA4BDA

# Decode several messages inline — comma-separated, emits JSON lines
modes decode 8D40058B58C901375147EFD09357,8D40058B58C904A87F402D3B8C59,8D406B902015A678D4D220AA4BDA

# With airborne CPR reference (single message only)
modes decode 8D40058B58C901375147EFD09357 --reference 49.0 6.0

# Compact JSON piped to jq
modes decode 8D406B902015A678D4D220AA4BDA --compact | jq .

# Decode a file of hex messages (one per line OR timestamp,hex CSV)
modes decode --file captures/flight.log

# Stdin + surface CPR
cat taxi.log | modes decode --file - --surface-ref LFBO

modes live — streaming TCP source

# Stream decoded JSON lines from a dump1090-style beast feed
modes live --network localhost:10006

# Tee output to a file
modes live --network host:10006 --dump-to flight.jsonl

# Interactive live aircraft table (requires pyModeS[tui] extra)
pip install "pyModeS[tui]"
modes live --network host:10006 --tui

Mode-S Beast binary format is supported (dump1090 and compatible feeds). See docs/quickstart.md for the full command reference.

Features

  • Unified decode() returns every decodable field in one dict
  • Batch mode preserves list length (errors become error-dicts, not exceptions)
  • PipeDecoder for streams: per-ICAO state, global and local CPR position decoding, TTL eviction, DF20/21 ICAO verification via trusted-set promotion
  • full_dict=True populates every key in the canonical 123-field schema for pandas / parquet workflows
  • known= aircraft state disambiguates Comm-B BDS 5,0/6,0 ambiguity
  • include_meteo=True opts into heuristic Comm-B BDS 4,4/4,5 inference
  • Airport ICAO database for surface CPR resolution (surface_ref="EHAM")
  • Type-checked under mypy strict across all source files
  • Golden-file oracle regression test against pyModeS 2.21.1

Supported messages

  • DF4 / DF20: altitude code (surveillance altitude reply)
  • DF5 / DF21: identity code (squawk)
  • DF11: all-call reply (partial — II/SI decoding deferred)
  • DF17 / DF18 ADS-B:
    • TC 1-4 (BDS 0,8): identification + category
    • TC 5-8 (BDS 0,6): surface position
    • TC 9-18 (BDS 0,5): airborne position (barometric altitude)
    • TC 19 (BDS 0,9): airborne velocity (all 4 subtypes)
    • TC 20-22 (BDS 0,5): airborne position (GNSS altitude)
    • TC 28 (BDS 6,1): aircraft status
    • TC 29 (BDS 6,2): target state and status
    • TC 31 (BDS 6,5): operational status
  • DF20 / DF21 Comm-B:
    • BDS 1,0: data link capability
    • BDS 1,7: common-usage GICB capability
    • BDS 2,0: aircraft identification
    • BDS 3,0: ACAS active resolution advisory
    • BDS 4,0: selected vertical intention
    • BDS 4,4: meteorological routine air report
    • BDS 4,5: meteorological hazard report
    • BDS 5,0: track and turn report
    • BDS 6,0: heading and speed report

BDS 4,4 and 4,5 are heuristic and disabled by default. Enable them with decode(..., include_meteo=True) or PipeDecoder(include_meteo=True) when these meteorological registers are expected on the input feed.

Migrating from pyModeS 2.x

pyModeS 3 is not backwards-compatible with pyModeS 2.x. The function-per-field API (pms.adsb.callsign(msg), …) is replaced by a single decode() returning a dict. See the migration guide for the full equivalence table.

If you aren’t ready to migrate:

pip install "pyModeS<3"

v3 replaces v2 on the same PyPI slot and import name, so pip install -U pyModeS upgrades existing v2 users to v3 (and triggers the v2-API removal shims — see the migration guide). Pinning <3 keeps you on the 2.x line.

Documentation

The full docs live under docs/ and are published via MkDocs + Material. To rebuild locally:

# One-shot build (strict mode fails on warnings). Output → site/
uv run --with mkdocs-material --with mkdocs-include-markdown-plugin --with "mkdocstrings[python]" mkdocs build --clean --strict

# Live-reload dev server at http://127.0.0.1:8000
uv run --with mkdocs-material --with mkdocs-include-markdown-plugin --with "mkdocstrings[python]" mkdocs serve

Attribution

pyModeS is a project created by Junzi Sun, who works at TU Delft, Aerospace Engineering Faculty. It is supported by many contributors from different institutions.

If you use pyModeS in academic work, please cite:

@article{sun2019pyModeS,
    author={J. {Sun} and H. {V\^u} and J. {Ellerbroek} and J. M. {Hoekstra}},
    journal={IEEE Transactions on Intelligent Transportation Systems},
    title={pyModeS: Decoding Mode-S Surveillance Data for Open Air Transportation Research},
    year={2019},
    doi={10.1109/TITS.2019.2914770},
    ISSN={1524-9050},
}

评论

暂无评论