2. 仿真环境搭建:操作系统选择、X-Plane、FlightGear 与 MATLAB/Simulink 连接

好,咱们直接进入正题。仿真环境搭建这件事,说白了就是给你的飞行模式测试找个靠谱的「窝」。我见过太多项目,代码写得漂亮,结果环境没搭对,数据全白跑。所以这一章,咱们把每一步都踩实了。

2.1 操作系统选型:Windows 还是 Linux?

这个问题,几乎每个新入行的同事都会问我。我的回答很简单:看你的主战场在哪。

对比维度 Windows Linux (Ubuntu 20.04/22.04 LTS)
驱动兼容性 即插即用,尤其是摇杆、油门杆等外设 部分专业外设需手动编译驱动
X-Plane 原生支持 官方主推平台,安装最省心 需通过 Steam Play 或 Wine,性能有损耗
MATLAB/Simulink 集成 官方工具箱全兼容,TCP/UDP 接口稳定 需额外配置编译器,实时内核更易部署
实时性需求 一般,适合原型验证 可通过 PREEMPT_RT 补丁实现硬实时
我个人习惯 前期快速验证、调试 UI 时用 跑自动化测试、长时间仿真时用
我的建议:如果你刚入门,或者团队里 Windows 生态更成熟,直接上 Windows 11。别在环境搭建上消耗太多意志力。等你需要跑 24 小时以上的蒙特卡洛仿真时,再切到 Linux 也不迟。

2.2 安装 X-Plane:别光点「下一步」

X-Plane 的安装包从官网下载,大概 60-80 GB。嗯,这里要注意,千万别装在 C 盘。我在项目中遇到过有人把 X-Plane 塞进系统盘,结果跑仿真时磁盘 I/O 爆满,整个系统卡死。后来我们统一规约:所有仿真软件装 D 盘或专门的 SSD 分区。

安装完成后,有几个关键配置你得手动调一下:

  1. 启动参数设置:在 X-Plane 快捷方式属性里,目标路径后加上 --allow_remote_control=1。这样外部程序才能通过 UDP 协议控制飞机。
  2. 网络配置:打开 Settings → Data Output,找到「Generic Data Output」选项卡。把「IP address」设为本机局域网 IP(比如 192.168.1.100),端口默认 49000 就行。
  3. 飞行模型精度:在 Operations & Warnings 里,把「Flight model per frame」从默认的 2 改成 4 或 6。帧率会降一点,但气动数据平滑很多。
避坑指南:我曾经因为忘记关闭 Windows 防火墙,导致 MATLAB 死活收不到 X-Plane 的数据包。折腾了两小时才发现。所以装完 X-Plane 后,记得在防火墙里放行 X-Plane.exe 的 UDP 入站规则。

2.3 配置 FlightGear:开源方案的灵活与代价

FlightGear 是开源界的良心。它的优势在于你可以完全控制仿真的每一层。但代价就是——配置起来稍微麻烦点。

我个人习惯用 FlightGear 做 故障注入测试。因为它的 FDM(Flight Dynamics Model)是开源的,你可以直接改 C++ 源码来模拟舵面卡死、传感器漂移等场景。这在 X-Plane 里反而不好实现。

配置步骤大致如下:

  • 下载安装:从官网获取稳定版(目前推荐 2020.3.19)。安装路径不要有中文和空格。
  • 启动脚本:不要直接双击 exe。用命令行启动,方便传参。举个例子:
fgfs --aircraft=777-200ER \
     --generic=socket,in,30,127.0.0.1,5500,tcp,myprotocol \
     --generic=socket,out,30,127.0.0.1,5600,tcp,myprotocol \
     --fdm=jsb \
     --timeofday=noon

这里 --generic 参数定义了输入输出 socket。30 是更新频率(Hz),5500 和 5600 是端口。你可以根据 MATLAB 那边的监听端口来调整。

关键点:FlightGear 的坐标系是 NED(北东地),而 MATLAB 的航空工具箱默认用 ENU(东北天)。如果你不做坐标转换,出来的姿态数据全是反的。我当年第一次联调时,看着俯仰角数据愣了半天。

2.4 连接 MATLAB/Simulink:让数据流动起来

这一步是整个环境搭建的核心。说白了,就是让 X-Plane 或 FlightGear 把飞机状态发出来,MATLAB 收到后算控制律,再发回去。

我推荐用 UDP 协议,原因很简单:延迟低、实现简单、跨平台。TCP 虽然可靠,但在仿真中一旦丢包重传,时序就乱了。

2.4.1 在 Simulink 中搭建 UDP 收发模块

打开 Simulink,在库浏览器里搜索:

  • UDP Receive:接收来自 X-Plane/FlightGear 的数据包。数据格式通常是 8 字节 double 数组,按特定顺序排列(比如 1-3 是位置,4-6 是姿态角,7-9 是速度……)。
  • UDP Send:把控制指令(舵面偏角、油门开度)发回仿真器。

一个典型的 Simulink 模型结构如下:

+-------------------+      +-------------------+      +-------------------+
| UDP Receive       | ---> | 数据解析 & 坐标转换 | ---> | 控制律计算        |
| (端口 49000)      |      | (NED -> ENU)      |      | (PID/LQR/... )    |
+-------------------+      +-------------------+      +-------------------+
                                                           |
                                                           v
+-------------------+      +-------------------+      +-------------------+
| UDP Send          | <--- | 指令打包          | <--- | 限幅 & 优先级管理  |
| (端口 49001)      |      | (double 数组)     |      | (舵面行程保护)    |
+-------------------+      +-------------------+      +-------------------+
调试技巧:先用 Wireshark 抓包确认 X-Plane 在发数据。然后在 Simulink 里加一个 Display 模块,直接看 UDP Receive 的输出。如果全是 0 或 NaN,八成是端口没对上,或者字节序反了(X-Plane 用大端,MATLAB 默认小端,需要 swapbytes)。

2.4.2 数据协议对齐

X-Plane 和 FlightGear 的数据格式不一样。我整理了一个对照表,方便你查:

数据项 X-Plane 索引 (DataRef) FlightGear 属性路径 单位
纬度 sim/flightmodel/position/latitude /position/latitude-deg 度
经度 sim/flightmodel/position/longitude /position/longitude-deg 度
高度 sim/flightmodel/position/elevation /position/altitude-ft 英尺 (需转米)
滚转角 sim/flightmodel/position/phi /orientation/roll-deg 度
俯仰角 sim/flightmodel/position/theta /orientation/pitch-deg 度
偏航角 sim/flightmodel/position/psi /orientation/heading-deg 度
空速 sim/flightmodel/position/true_airspeed /velocities/airspeed-kt 节
注意:X-Plane 输出的高度是海拔高度(MSL),而 FlightGear 默认输出的是相对机场高度(AGL)。如果你在做自动着陆测试,这个差异会导致高度误差几十米。我建议统一用 MSL,然后在 Simulink 里做差值。

2.5 整体架构一览

下面这张图,是我在项目里一直贴在工位上的。它把整个仿真环境的通信关系画清楚了:

仿真环境整体架构图 X-Plane 12 UDP 输出: 49000 UDP 输入: 49001 MATLAB/Simulink 控制律计算 数据记录 & 可视化 FlightGear TCP 输入: 5500 TCP 输出: 5600 UDP 数据流 控制指令 TCP 数据流 控制指令 说明 X-Plane 和 FlightGear 可同时运行,但同一时刻只选一个作为主仿真器。 数据记录 & 分析 .mat / .csv / 日志文件

你看,整个架构其实不复杂。左边是仿真器(X-Plane 或 FlightGear),中间是大脑(MATLAB/Simulink),下面是黑匣子(数据记录)。数据流是双向的,延迟控制在 10ms 以内就算合格。

2.6 快速验证:跑一个简单的平飞测试

环境搭好之后,别急着搞复杂控制律。先跑一个最简单的平飞测试,验证链路通不通。

步骤很简单:

  1. 在 X-Plane 里选一架默认的 Cessna 172,放在跑道上。
  2. 启动 Simulink 模型,UDP Receive 模块应该能收到数据。看 Display 上的数值,如果高度在变化(比如 100 米左右),说明链路通了。
  3. 在 Simulink 里手动给一个固定的升降舵偏角(比如 -2 度),通过 UDP Send 发回去。如果 X-Plane 里的飞机开始抬头,恭喜你,闭环打通了。
我的经验:第一次联调时,我建议把 Simulink 的仿真步长设成固定步长(比如 0.01 秒),别用变步长。变步长在数据交互时容易出时序问题,排查起来很头疼。