Hotdry.

Article

从天空到天花板:ADS-B航迹实时投影系统构建指南

基于RTL-SDR接收航空ADS-B信号,通过坐标转换与投影映射技术,将实时飞机航迹渲染至室内天花板的完整技术方案

2026-06-03systems

将头顶飞过的航班实时投射到卧室天花板,这种将外部世界数据引入私人空间的尝试,本质上是一套跨学科的系统工程:从射频信号捕获到地理坐标转换,再到投影几何校正。本文提供一条从硬件组装到软件集成的完整技术路径,帮助搭建可运行的 ADS-B 航迹投影系统。

硬件层:信号捕获的基础设施

核心组件仅需三件:RTL-SDR 软件定义无线电模块(约 20-30 美元,R820T2 芯片方案)、1090MHz 专用天线、以及运行 Linux 的树莓派或旧笔记本。1090MHz 是 ADS-B Out 的国际标准频率,飞机每秒广播两次位置报文,包含经纬度、高度、速度、呼号等字段。

天线 placement 决定接收半径。室内窗边架设可捕获 30-50 公里范围内的航班;若将天线延伸至阳台或屋顶,配合低噪声放大器(LNA),接收范围可扩展至 150-200 公里。注意避开金属遮挡物和强电磁干扰源,如 Wi-Fi 路由器和微波炉。

信号解码:从射频到结构化数据

dump1090 是社区标准解码器,支持 RTL-SDR 硬件直通。运行 dump1090 --net --json 启动 JSON 数据流服务,默认在 30003 端口输出实时航班对象。每条记录包含 latlonaltitudeflight(呼号)、track(航向角)等字段。

建议启用 --metric 参数统一使用公制单位,避免后续单位转换错误。数据更新频率约每秒 1-2 次,取决于飞机距离和信号强度。对于投影系统,可设置过滤条件仅保留 latlon 有效且高度低于 15000 英尺的进近航班,减少数据量并聚焦可视目标。

坐标转换:从 WGS84 到本地 ENU

ADS-B 输出的是 WGS84 椭球坐标,需要转换为以接收点为中心的本地 ENU(东 - 北 - 上)笛卡尔坐标系,才能进行后续的投影计算。

转换公式采用地理坐标到本地切平面的映射:

import math

def wgs84_to_enu(lat, lon, alt, lat0, lon0, alt0):
    """将WGS84坐标转换为本地ENU坐标(单位:米)"""
    R = 6371000  # 地球平均半径
    
    # 转换为弧度
    lat_rad, lon_rad = math.radians(lat), math.radians(lon)
    lat0_rad, lon0_rad = math.radians(lat0), math.radians(lon0)
    
    # 本地ENU坐标(简化球面近似,短距离误差<0.1%)
    east = R * math.cos(lat0_rad) * (lon_rad - lon0_rad)
    north = R * (lat_rad - lat0_rad)
    up = alt - alt0
    
    return east, north, up

以接收点为原点 (0, 0, 0),正东为 X 轴正方向,正北为 Y 轴正方向。 ceilings 投影通常只关心水平面分布,因此主要使用 (east, north) 二维坐标。

投影映射:天花板平面的几何校正

天花板投影面临两个核心问题:投影仪通常以倾斜角度向上投射,产生梯形畸变;需要将不规则的本地坐标范围映射到矩形投影画面。

步骤一:确定天花板投影区域

测量投影仪光心到天花板的垂直距离 h,以及投影仪镜头的水平 / 垂直偏移量。假设使用短焦投影仪在 3 米距离投射 2 米 ×1.5 米的画面,天花板上的投影区域是一个四边形(非矩形),需要建立从屏幕坐标 (u, v) 到世界坐标 (x, y, z) 的映射。

步骤二:单应矩阵(Homography)校正

对于平面天花板,3×3 单应矩阵 H 可将投影画面坐标映射到物理天花板坐标。通过四点标定法获取对应点:在天花板上标记四个角点,测量其物理坐标,同时在投影画面中获取对应的像素坐标,使用 OpenCV 的 findHomography 求解矩阵。

import cv2
import numpy as np

# 天花板物理坐标(米)
world_pts = np.array([[0, 0], [2, 0], [2, 1.5], [0, 1.5]], dtype=np.float32)
# 投影画面像素坐标
image_pts = np.array([[100, 100], [1820, 120], [1800, 980], [120, 960]], dtype=np.float32)

H, _ = cv2.findHomography(image_pts, world_pts)

步骤三:航迹到投影坐标的映射

将 ENU 坐标 (east, north) 归一化到投影区域的显示范围:

def enu_to_projected(east, north, range_m=50000):
    """将ENU坐标(米)归一化到[0,1]范围,range_m为最大显示半径"""
    x_norm = (east / range_m + 1) / 2  # 映射到[0,1]
    y_norm = (north / range_m + 1) / 2
    return x_norm, y_norm

然后应用单应矩阵 H 将归一化坐标变换为投影画面像素坐标,通过投影仪输出。

实时渲染:WebGL 航迹可视化

建议使用浏览器作为渲染层,通过 WebSocket 接收 dump1090 数据,使用 Canvas 2D 或 WebGL 绘制航迹。核心渲染逻辑包括:

  1. 航迹缓存:维护一个字典 trails[flight_id] = [(x1,y1), (x2,y2), ...],存储每架飞机最近 30 个位置点
  2. 渐隐效果:使用半透明覆盖层 ctx.fillStyle = 'rgba(0,0,0,0.1)' 实现航迹拖尾效果
  3. 方向指示:根据 track 航向角绘制小箭头,增强可读性

性能优化要点:限制同时渲染的飞机数量(如最多 50 架),对超出投影范围的飞机进行裁剪,使用 requestAnimationFrame 确保 60fps 流畅度。

系统整合与调试清单

硬件检查

  • RTL-SDR 插入 USB 后运行 rtl_test 检测硬件
  • 天线连接牢固,SMA 接口无松动
  • 树莓派供电充足(建议 2.5A 以上电源)

信号验证

  • 运行 dump1090 --interactive 查看控制台航班列表
  • 对比 FlightRadar24 验证位置数据准确性
  • 检查 JSON 输出格式是否符合预期

投影校准

  • 投射网格测试图案到天花板,检查直线是否平直
  • 从多个观察位置验证航迹位置与真实方位的一致性
  • 调整 range_m 参数匹配期望的视野范围

局限与扩展方向

信号接收受限于视距传播,高层建筑密集区域可能出现多径干扰导致位置跳变。投影精度依赖单应矩阵标定质量,若天花板有横梁或不平整,需改用网格变形(mesh warping)替代单应变换。

扩展方向包括:叠加气象雷达数据渲染云层、接入机场进近灯光系统数据、或使用多接收站实现多点定位(MLAT)提高精度。


参考来源

  • RTL-SDR 社区 ADS-B 教程与 dump1090 文档
  • 投影映射几何校正技术综述(Perspective Correction Techniques for Projection Mapping)

systems

内容声明:本文无广告投放、无付费植入。

如有事实性问题,欢迎发送勘误至 i@hotdrydog.com