Hacker News 中文摘要

RSS订阅

如何节省航空燃油 -- Saving Jet Fuel

一架波音(Boeing)787-9梦想客机从纽瓦克自由国际机场(EWR)直飞列奥纳多·达·芬奇-菲乌米奇诺机场(FCO),8.5小时航程可能消耗6.8万美元燃油。按风况调整航路可降低油耗,也许能省下数千美元。杰普逊(Jeppesen)等公司已有此类产品,而Scikit-decide结合代尔夫特理工大学(Delft University of Technology)一位教授的窄体与宽体油耗模型,以及美国国家海洋和大气管理局(NOAA)的风数据,给出了开源方案。

正文

一架波音 787-9 梦想客机从纽瓦克自由国际机场(EWR)直飞罗马达芬奇-菲乌米奇诺机场(FCO),8.5 小时的航程可能要烧掉 6.8 万美元的航油。根据风况调整航路可以降低油耗,也许能省下几千美元。

Jeppesen 这类公司在这个领域已有产品,但 Scikit-decide 加上代尔夫特理工大学一位教授构建的窄体与宽体油耗模型、以及 NOAA 的风数据,提供了一套开源方案。

Scikit-decide 已经开发了六年,是一个用于强化学习、自动规划和调度的框架。它可以优化航路、重新编排航空公司的人员排班,也能计算无人机集群的路径。

OpenAP 是由 Junzi Sun 博士开发的飞机性能模型和工具包。Sun 拥有空中交通管理博士学位,是荷兰代尔夫特理工大学的终身助理教授,除其他工作外还讲授这门课程。

Scikit-decide 的最优航路求解器可以配置不同的油耗模型。接下来比较两条用空客 A320 和 OpenAP 油耗模型飞出来的航路。

我的工作站

所有计算在一台 5.7 GHz 的 AMD Ryzen 9 9950X(16 核 32 线程)、96 GB DDR5 内存的机器上完成,系统通过 Windows 11 Pro 上的 Ubuntu 24 LTS 运行。

安装依赖

用 Python 3.12 和 jq。先添加 deadsnakes PPA,更新后安装 jq、python3-pip 和 python3.12-venv。

接着建立 Python 虚拟环境 ~/.flight_planning,安装 scikit-decide、OpenAP 以及同样由 Sun 博士开发的飞行轨迹工具包 OpenTop:

  • pip install 'scikit-decide[all]' 'openap[all]' opentop

以上至少需要 8 GB 存储空间。装好后用 pipdeptree 查看顶层依赖,其中包括 lz4 4.4.5、opentop 2.6.0、plado 0.1.6、pygeodesy 26.9.9、pygrib 2.1.8、ray 2.37.0、scikit-decide 1.1.1、torch-geometric 2.8.0.post1、unified-planning 1.2.0、z3-solver 5.1.0.0 等。

还会用到 DuckDB 及其 h3、JSON、Lindel、Parquet、Spatial 扩展。下载 DuckDB CLI v1.5.4、解压并赋予执行权限后,安装这些扩展,并在 ~/.duckdbrc 中设置每次启动自动加载。

地图用 QGIS 4.2.1 渲染。QGIS 是一款支持 Windows、macOS 和 Linux 的桌面应用,近年来人气上升,全球用户每月启动约 2200 万次。边界和地名来自 Natural Earth,海界来自 Marine Regions。

OpenAP 的机型

先克隆 OpenAP 仓库。除去单元测试和工具脚本,这个包里有 3,369 行 Python。

OpenAP 的模型依赖随代码库打包的大量数据集,覆盖各种机型。按厂商统计:波音 17 种、空客 13 种、巴西航空工业 5 种、湾流 1 种、塞斯纳 1 种。

以空客 A380-800 为例,它的属性包括:最大起飞重量 560000、最大着陆重量 386000、空重 277000、最大燃油容量 320000、最大运行速度 340、最大马赫数 0.89、升限 13100。载客量最大 853、低密度 410、高密度 620。机身长 72.72、高 8.41、宽 7.14。机翼面积 845、翼展 79.75、后掠角 33.5、厚弦比 0.08。襟翼为单缝式,λf 0.900、cf/c 0.150、Sf/S 0.150。巡航高度 12800、马赫 0.85、航程 14800。四台翼挂涡扇发动机,默认 GP7270,A380-841 用 Trent 970-84,A380-842 用 Trent 972-84,A380-861 用 GP7270。阻力方面,干净构型 cd0 0.016、k 0.050、e 0.855,起落架 0.012。

各飞行阶段的性能参数也有表可查,例如:起飞离地速度最优值 89.9(区间 75.4–104.4);起飞距离 2.56(1.35–3.78);初始爬升平均空速 88.0、平均垂直速率 5.65;爬升段爬升航程 296,恒定 CAS 163,恒定马赫 0.84,恒定 CAS 转换高度 3.3,恒定马赫转换高度 8.9;巡航航程 4348(892–20565),平均巡航 CAS 136、最大 145,平均巡航马赫 0.84、最大 0.87,初始巡航高度 11.55(9.3–12.23),平均巡航高度 11.73、最大 12.06;下降航程 310,恒定马赫 0.83,恒定 CAS 154,恒定马赫转换高度 10.1,恒定 CAS 转换高度 6.6;最后进近平均空速 73.0、平均垂直速率 -3.71、进近角 2.9;落地接地速度 70.0(62.1–78.0),刹车距离 2.26,平均刹车加速度 -1.01。

机型同义词表把一些少见型号映射到常见型号,例如 a124→b744、a306→a332、a310→a318、at72/at75/at76→e145、b733→b734、b735→b734、b762→b763、b77l→b77w、c25a/c525/c56x/pc24→c550、crj2→e145、crj9→e75l、e290→e190、glf5/gl5t/lj45→glf6、md11→b773、su95→e170。

飞机发动机

飞机通常至少有两种可选发动机,这个数据集里共列出 427 台。

以 Trent 970-84 为例:涵道比 8.45,最大推力 338700,总压比 38.0,类型 TF,制造商 Rolls-Royce plc,代号 18RR081。它的排放与燃油流量系数包括 eicoapp 1.16、eicoco 0.31、einoxco 29.42、ffco 2.157、ffidl 0.255、ff_to 2.605,LTO 燃油 965.0。

按厂商统计发动机数量:GE Aircraft Engines 108、CFM International 94、Pratt & Whitney 85、Rolls-Royce plc 62、International Aero Engines 13、Pratt & Whitney Canada 12、Rolls-Royce Corporation 11、Rolls-Royce Deutschland 8、Honeywell 8、Aviadvigatel 7,其余更少。

按类型统计:涡扇(TF)322 台、混合流涡扇(MTF)98 台、涡桨(TP)5 台、活塞(PS)1 台。

按最大推力排名,前几名是 GE90-115B(513900 N)、GE90-113B(504900)、GE90-110B1(492600)、Trent XWB-97(436748)、GE90-94B(430920)、GE90-92B(426720)、GE90-90B(419250)、Trent 895(413050)、Trent 892(411480)、PW4090(408300)。

油耗模型有默认值和按机型的覆盖值,例如 A320 用 CFM56-5B4/P,系数 c1 为 1.0453208160586924、c2 为 2.3633720747416573、c3 为 1.2378127479131922;B738 用 CFM56-7B26E,系数为 1.075484518912494、1.8777303165419037、1.8895522140156369;default 行的系数为 0.937564901246902、1.9767611682280135、1.3954794843472482。A318、A319、A321、A332、A333、B737、B739、CRJ9、E170、E190、E195、E75L 也各有取值。

机场与导航

包里自带近 14K 个机场的位置和代码,共 13,796 行,分布在 236 个不同的国家。机场数量最多的国家依次是巴西 2849、美国 2459、澳大利亚 2062、法国 441、加拿大 345、德国 325、英国 258、印度尼西亚 234、纳米比亚 176、委内瑞拉 168、俄罗斯 156、印度 148、阿根廷 143、瑞典 139、日本 126、意大利 118、新西兰 106、捷克 99、玻利维亚 98、南非 97。

导航点方面,fix.dat 收录了大量航路点,例如爱沙尼亚一带的 ALISA、AMOLI、ANAMA、EIKLA、EKLON、EVERI、GEKLI、GONOS、KANEP、KARLA、KEMET、KOLEV、KUKET、KUNUX、KUUST、LAEVA、LALSI、LAPSA、LATEG、LATKA。

导航台数据 nav.dat 有 26,775 行,包括 KARDLA NDB、KURESSAARE NDB、PARNU NDB、TARTU NDB、KURESSAARE VOR-DME、PARNU VOR-DME、VENTSPILS VOR-DME、VOHMA VOR-DME 等,各自带有频率、高度和磁偏角等参数。

图卢兹到柏林

接下来找一条从图卢兹-布拉尼亚克机场(LFBO / TLS)到柏林勃兰登堡机场(EDDB / BER)的最优航路。

代码里引入了 numpy、openap.aero 的 cas2mach、ft、kts,openap.extra.nav 的 airport,pygeodesy 的 LatLon,以及 scikit-decide 的 AircraftState、PerformanceModelEnum、PhaseEnum、RatingEnum、FlightPlanningDomain、WeatherDate、plotnetworkadapted 和 Astar 求解器。

启发式参数可以取 time、distance、lazyfuel、lazytime 或 None;不传的话,A* 会退化成类似 Dijkstra 的搜索。

飞机状态设为:机型 A320,性能模型用 OpenAP,总重 80,000 kg,初始高度 10,000 ft,此处马赫数由 250 kt 的 CAS 换算,处于爬升阶段,推力等级 MCL,重心 0.3。规划域参数为:巡航马赫 0.78、爬升马赫 0.7、下降马赫 0.65,前向点数 20、横向点数 10、爬升下降步数 5,飞行高度层取 30,000 至 38,000 ft、每 2,000 ft 一档,图宽度设为 medium,起点为纬度 43.629444、经度 1.363056,终点 EDDB,目标函数为油耗,启发式为 lazy_fuel,天气日期为 2026 年 5 月 1 日。

运行时,如果还没从 NOAA 取过天气数据、且航班日期在过去六个月内,就会下载 GRB2 文件。2026 年 5 月 1 日这一天有四个时次的文件,每个约 143–144 MB,每个文件都覆盖全球。以下是 gfs4202605011800000.grb2 的内容在 QGIS 中以地球仪形式渲染的结果。

GRIB2 天气文件在 QGIS 地球仪上的渲染

这是求解器的高度和地理搜索空间。

求解器的高度与地理搜索空间

这是求解器给出的最优航路。

图卢兹到柏林的最优航路

A* 在 0.28 秒内求解完成,19 步到达目标,飞行时间 7666.28 秒,耗油 5855.09 kg。

把航迹导出成 CSV,再用 DuckDB 按时间排序查看各阶段数据:

| 阶段 | 时间(s) | 高度(ft) | 质量(kg) | 马赫 | CAS | 燃油(kg) | |---|---|---|---|---|---|---| | CLIMB | 28800 | 0 | 80000 | 0.45 | 154 | 0 | | CLIMB | 29183 | 12000 | 79402 | 0.7 | 194 | 598 | | CLIMB | 29767 | 18000 | 78717 | 0.7 | 173 | 685 | | CLIMB | 30367 | 24000 | 78104 | 0.7 | 154 | 2 | | CLIMB | 30691 | 30000 | 77808 | 0.7 | 135 | 294 | | CRUISE | 31222 | 30000 | 77331 | 0.78 | 152 | 477 | | CRUISE | 31805 | 30000 | 76812 | 0.78 | 152 | 258 | | CRUISE | 32672 | 30000 | 76041 | 0.78 | 152 | 257 | | CRUISE | 33547 | 32000 | 75270 | 0.78 | 146 | 259 | | CRUISE | 34103 | 30000 | 74794 | 0.78 | 152 | 476 | | DESCENT | 34458 | 24031 | 74503 | 0.65 | 142 | 290 | | DESCENT | 35058 | 18063 | 73995 | 0.65 | 160 | 51 | | DESCENT | 35714 | 12094 | 73388 | 0.65 | 179 | 13 | | DESCENT | 36063 | 6126 | 73023 | 0.65 | 199 | 352 | | DESCENT | 36466 | 48 | 72534 | 0.65 | 221 | 488 |

再把航迹以 Parquet 格式导出(ZSTD 压缩、压缩级别 22、行组大小 15000),在 QGIS 中叠加地面风数据渲染。

航迹叠加地面风数据

图卢兹到华沙

接下来找一条从图卢兹-布拉尼亚克机场(LFBO / TLS)到华沙肖邦机场(EPWA / WAW)的最优航路。

这一次初始目标高度比上一例高得多(zpft 设为 18000.0,xgraph、ygraph、zgraph 分别为 5、5、10),结果飞机得以走一条直接得多的航线。

A* 在 29.45 秒内求解完成,14 步到达目标,飞行时间 6153.66 秒,耗油 5600.17 kg。

华沙距离图卢兹比柏林远 500 公里,但在给定风况下更快的爬升让飞机能走更直的路线,结果反而快了将近 45 分钟,油耗只有柏林航班的 76%。

图卢兹到华沙的最优航路

这条航路的各步数据如下:

| 阶段 | 时间(s) | 高度(ft) | 质量(kg) | 马赫 | CAS | 燃油(kg) | |---|---|---|---|---|---|---| | CLIMB | 28800 | 30000 | 80000 | 0.45 | 85 | 0 | | CRUISE | 29196 | 32000 | 79639 | 0.78 | 146 | 361 | | CRUISE | 29604 | 34000 | 79276 | 0.78 | 139 | 363 | | CRUISE | 30018 | 36000 | 78915 | 0.78 | 133 | 361 | | CRUISE | 30436 | 38000 | 78555 | 0.78 | 127 | 360 | | CRUISE | 30861 | 38000 | 78191 | 0.78 | 127 | 365 | | CRUISE | 31297 | 36000 | 77819 | 0.78 | 133 | 371 | | CRUISE | 31732 | 34000 | 77449 | 0.78 | 139 | 370 | | CRUISE | 32161 | 32000 | 77082 | 0.78 | 146 | 367 | | CRUISE | 32589 | 30000 | 76710 | 0.78 | 152 | 372 | | DESCENT | 33101 | 24066 | 76280 | 0.65 | 142 | 429 | | DESCENT | 33589 | 18131 | 75861 | 0.65 | 160 | 420 | | DESCENT | 34046 | 12197 | 75433 | 0.65 | 179 | 428 | | DESCENT | 34472 | 6262 | 74984 | 0.65 | 199 | 449 | | DESCENT | 34954 | 100 | 74400 | 0.65 | 221 | 584 |

空客 A320 对波音 737

OpenTop 可以和 OpenAP 配合使用,算出两座机场之间的飞行轨迹。

它的优化器需要一个网格成本文件。先下载项目提供的一个 142 MB 的 NetCDF 示例文件 contrail_original.nc。

成本文件可以是 Casadi 或 Parquet 格式。按官方文档中的示例做,最后生成了一个 246 KB 的 Casadi 文件。

处理过程是:用 xarray 打开数据集并选中 2015-12-18 这个时次;用一份标准气压层列表把气压换算成高度;把经度规整到 -180 至 180;只保留高度小于 15000 的记录;把列重命名为 latitude、longitude、cost;筛选经度在 -20 到 40、纬度在 30 到 70、且时间为 12 点的数据;按高度、纬度、经度排序后重塑成三维数组;用 sigma=1、mode="nearest" 做高斯滤波;最后用 cachedinterpolantfrom_dataframe 以 bspline 形式生成插值并写入 contrail.casadi。

查看文件内容会发现数据重复度很高,用 gzip -9 压缩后只剩 90,949 字节。

先算阿姆斯特丹史基浦(EHAM / AMS)到法兰克福(EDDF / FRA)在空客 A320 上的最优飞行:

  • 目标函数:0.3fuel+0.7grid
  • 求解成功,迭代 179 次,耗时 12.2 秒
  • 目标值 4.8768e+02,耗油 1625.6 kg,最高高度 19,891 ft,飞行时间 35.8 分钟

换成波音 737 做同样的计算:

  • 求解成功,迭代 141 次,耗时 9.9 秒
  • 目标值 4.8662e+02,耗油 1622.1 kg,最高高度 21,968 ft,飞行时间 39.2 分钟

评论

多数带航空背景的评论者对这套方案持否定态度,认为它把航空运行简化成了"天上只有一架飞机"的数学题,生成的很多航路根本不合法;少数人认可思路本身,并指出尾迹规避、数据来源等更值得深挖的方向。分歧的核心是:这到底是被现实约束困死的伪命题,还是确实戳中了行业里真实存在的浪费。

认为它无视 IFR 航路、海洋航线和 ETOPS 等硬约束

  • 航线必须在既定航路点之间截获、接受管制引导,同一航路不同方向还有不同高度层要求,管制不可能让飞机以千公里时速对头飞;有飞行员搜索原文后发现 IFR、NOTAM、海洋航线、RVSM、ETOPS、TFR 一个都没提到,意味着大量输出根本无法合法执行(较多人) > 我逐个搜了这些词,一个都没有——那不如让我家猫来点评神经外科。(@dmitrygr)

认为优化目标太窄,只算燃油不算钱和时间

  • 商业飞行规划软件早就在做这类优化,区别在于它把机组值勤时限、机时费、航路飞越费、保险维修时租、机场宵禁、历史拥堵延误一并纳入,更省油的路线可能更慢、甚至需要多配一套机组(较多人) > 这是"天上只有你一架飞机、且燃油是唯一成本"时的完美规划软件。(@buildsjets)

一眼就能看出"最优解"是病态的

  • 结果图里的最优路径剧烈锯齿,显然是网格分辨率太粗,可能还不止这一个建模问题(较多人)
  • 有人讽刺其成立前提是所有飞机都能按飞行员心意随意爬升下降、直接进场,且不必担心别人也在做同样的事,类比成品就是导航软件里的"忽略交通规则"选项(较多人)

质疑飞机和发动机性能数据是随意填的

  • 真实性能极度依赖飞机重量、高度、气温和空速,厂商手册动辄上千页密集表格;用一张固定的巡航与爬升速度表算出来的曲线再好看也不真实(少数人)

认为人类流程和监管结构注定让方案原地踏步

  • 航空业以抗拒变化著称,监管者和航司在结构上都反对改动既有流程,卖咨询不如等 AI 机场、AI 空管、AI 航司(少数人) > 想在这件事上把山挪动一毫米都难,还不如直接等 AI 机场、AI 空管和 AI 航司。(@contingencies)

认为单点数据说服力不够

  • 45 分钟、省 25% 燃油的单次结果很惊人,但需要一整年常规航班上真实风场和其他约束的分布数据,才能说明这个方案长期到底值多少(较多人)

认为尾迹规避是更值得关注的相关方向

  • 相关研究显示凝结尾迹约贡献 2% 的全球变暖潜势,而且相对容易规避,代价只是略微增加的燃油消耗(少数人)

有价值的补充

  • 一位家属是民航飞行员的人提到,因配载重量预测变更和加油过量,飞机经常在地面就把上千加仑燃油烧掉来调整落地重量,一次失误的浪费足够给他位于北极圈附近的房子供暖一年(@K0balt)
  • 有人发现空客把决策优化库做成了 scikit-decide 开源项目,乐见 scikit 品牌延续(@esafak)
  • 玩笑里也有情绪:有人提议直接用氛围编程干一个 ForeFlight 竞品,也有人干脆说别再假装商务出行是必要的(@Onavo、@MiroslavPokorny)