用 ClickHouse 分析来自飞机的全球天气数据

图片

本文字数:3823;估计阅读时间:10 分钟

作者:Alexey Milovidov

本文在公众号【ClickHouseInc】首发

图片

最近我读到一篇由 Niklas Oberhuber 撰写的博客文章(https://obrhubr.org/adsb-weather-model),他展示了如何从飞机的遥测数据中推导出天气信息。尽管飞机不会直接广播温度或风速数据,但我们可以通过其他参数实时推算出这些信息。受到启发,我决定复现这些计算过程,并呈现出一些有趣的可视化结果!

ADS-B Massive Visualizer 系统会收集飞机的遥测数据,例如位置、高度、速度和航向,并将其存储在 ClickHouse 数据库中。目前系统已经累计超过 1500 亿条数据,并持续实时增长。该服务支持基于这些海量数据生成自定义报告。

关于该服务的更多信息,可以参考我们之前的博客文章。(https://clickhouse.com/blog/interactive-visualization-analytics-adsb-flight-data-with-clickhouse)

图片

传感器

飞机配备了多种空气压力传感器,称为“皮托管”(pitot tubes),用于测量飞机在空气中的运动状态。通过静压可以得出飞行高度,而动压则可以反映飞机相对于空气的速度(即空速)。这些传感器对于飞行动态控制至关重要。

此外,飞机还搭载了各种导航系统,用于测量相对于地球的高度、速度和航向。虽然这些测量对飞行操控影响较小,但在导航过程中却非常关键。

通过对比不同系统的测量结果,我们可以推导出更多有价值的数据。例如,将空速与相对于地面的几何速度进行比较,就能计算出顺风或逆风的速度;将气压测得的高度与几何高度对比,可以了解局部气压的变化情况,甚至可能推测出温度;将相对于空气的航向与几何航向对比,还能判断风的方向。

可视化

假设我们希望在地图上可视化飞机的航向角度(范围为 0 到 360 度),该如何呈现?我们可以使用色相环来映射不同角度到不同颜色的色调。为实现这一目标,ClickHouse 提供了用于颜色空间转换的函数:colorOKLCHToSRGB 和 colorSRGBToOKLCH。

目前大多数显示器和显卡使用的颜色空间为 sRGB,它包含红、绿、蓝三个通道,并经过 Gamma 校正(即通道的变化是非线性的),这样可以在较暗区域提供更高的分辨率,因为人眼对暗色变化更为敏感。

另一种颜色空间是 OKLCH,它由三个通道组成:亮度(Lightness)、色度(Chroma)和色相(Hue)。这个颜色空间呈圆柱形结构,其中亮度和色度是线性维度(通常范围在 0 到 1 之间,某些值可能超出设备支持范围),而色相是一个圆形维度(表示 0 到 360 度的角度)。OKLCH 被设计为线性空间(即在线性渐变时视觉效果平滑自然,因此得名),并且具备感知均匀性(意味着两种颜色的平均值在视觉上也会被认为是中间值;当亮度和色度保持不变,仅改变色相时,人眼仍会感知为相同亮度的颜色)。

接下来,我们就用这种颜色空间来可视化飞机的航向数据。

图片

气压

我们来筛选高度至少为 10,000 英尺的飞机数据,并绘制某一天的飞行高度与几何高度(geometric_altitude)之间的差值图像:

图片

图像效果出人意料地精美!更有趣的是,选择不同日期时,图像会呈现出显著变化。

图片

下面是从 2025 年 4 月 2 日开始,连续 25 天内美国地区气压差异的可视化结果。每一帧代表一个 24 小时的滑动时间窗口,帧之间间隔 6 小时。

我并没有尝试基于这些数据推算出实际温度。维基百科上的温度推导公式较为复杂,我没有选择使用它。Niklas Oberhuber 同样没有使用该公式,而是建立了自己的模型。而我已经对这些可视化图像的美观效果感到满意。

偏航角

当有强烈且持续的侧风时,飞机会略微朝风向偏转飞行,以抵消风力对航向的影响。这种飞行姿态即使在着陆时也能保持,被称为“偏航飞行”(crabbing)。在 ADS-B 数据中,有两个相关字段:track_degrees 表示飞机相对于地面的航迹角,而 aircraft_true_heading 表示飞机相对于气流的真实航向。将两者相减即可计算出“偏航角”。我们将这一偏航角数据进行了可视化处理:

图片

遗憾的是,这类数据在美国多数地区并不公开,但在欧盟国家则可以获取。很可能是由于相关地区的数据隐私或开放规定不同所致。

现在我们尝试计算风的方向和速度。这个过程需要借助一些三角函数计算,要理解这些公式可能需要借助纸和笔。

以下是我们前面步骤中计算出的“偏航角”(又称“漂移角”):

positiveModulo(track_degrees - aircraft_true_heading + 180, 360) - 180 AS drift_angle,

风速的计算方式可以通过构建一个三角形来完成:已知地速(ground_speed)和空速(aircraft_tas)为两边,夹角为漂移角 drift_angle,根据余弦定理,可以计算出第三边的长度,这就是风速的大小(即两个速度向量之间的差异):

sqrt(
    pow(ground_speed, 2) + pow(aircraft_tas, 2) -
    2 * ground_speed * aircraft_tas * cos(radians(drift_angle))
) AS wind_speed,

采用类似方法,也可以推算出风的绝对方向角:

positiveModulo(track_degrees +
    if(drift_angle < 0, -1, 1) * degrees(acos(
        greatest(-1, least(1,
            (pow(ground_speed, 2) + pow(wind_speed, 2) - pow(aircraft_tas, 2)) /
            (2 * ground_speed * if(wind_speed > 0.1, wind_speed, 1))
        ))
    )) + 180, 360
) AS wind_direction,

我们希望在地图上展示风的方向。但一个像素区域内往往包含多个数据点,此时需要进行聚合处理以计算平均风向。然而,角度的平均值不能通过简单的算术平均获得。例如,10 度和 350 度的平均值应为 0 度,而不是 180 度。

更进一步地,我们还希望使用风速作为权重来计算加权平均风向,让风速越大的数据对平均值影响更大。

为实现这一目标,可以将风向和风速视为风矢量的极坐标形式。由于平均值只能在线性坐标空间中合理定义,因此需要先将极坐标(方向、速度)转换为笛卡尔坐标(x,y),然后分别对 x 和 y 分量求平均,最后再将结果转换回极坐标,得到平均风向角:

positiveModulo(degrees(atan2(
    avg(sin(radians(wind_direction)) * wind_speed),
    avg(cos(radians(wind_direction)) * wind_speed)
)), 360) AS avg_wind_direction,

在获取风向和风速之后,自然而然地可以将风向映射为颜色的色相,将风速映射为颜色的亮度进行可视化:

图片

我将最终生成的图像与实际天气可视化网站 https://earth.nullschool.net/ 进行了对比,结果几乎完全一致,验证了方法的有效性。

图片

以下是从 2025 年 1 月 1 日起,欧洲地区连续 25 天的风场变化可视化结果。每帧表示一个 24 小时滑动窗口,帧间以 6 小时递进。

总结

ADS-B 是一项极具价值的数据源,配合 ClickHouse 的实时查询能力,可以发挥出巨大的数据洞察潜力。

附录:如何制作可视化视频。首先准备查询语句,并复制粘贴到 adsb.exposed。打开浏览器控制台,执行如下脚本:

frame = 0; const id = setInterval(() => { query_elem.value = query_elem.value.replace(/(\d+) AS frame/, ${frame} AS frame); updateMap(); if (frame >= 100) { clearInterval(id) }; ++frame; }, 10000)。

第一次运行是为了将图像缓存到本地。完成后,将刷新间隔设置为 1 秒,启动 recordmydesktop 并再次运行。生成的视频可以通过以下 ffmpeg 命令进行处理:

ffmpeg -y -i out.ogv -ss 4.5 -to 105 -filter:v "crop=2149:1218:893:666,thumbnail=15,setpts=0.1*PTS" -qscale:v 10 -an pressure.ogv

其中,裁剪区域和时间参数通过手动查看视频画面并使用图像编辑器中的选区工具获取。该命令由 AI 工具协助生成。

征稿启示

面向社区长期正文,文章内容包括但不限于关于 ClickHouse 的技术研究、项目实践和创新做法等。建议行文风格干货输出&图文并茂。质量合格的文章将会发布在本公众号,优秀者也有机会推荐到 ClickHouse 官网。请将文章稿件的 WORD 版本发邮件至:Tracy.Wang@clickhouse.com

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值