
做飞控和无人机系统的人应该都经历过这个尴尬阶段PX4 固件在 QGroundControl 里能正常刷入地面站参数看着也全对可一上真机就各种“草率”翻车——电机不转、IMU 数据跳变、姿态解算发散甚至推油门瞬间直接翻转。纯软件仿真又太“干净”传感器模型基本等于没有控制律在仿真里稳如老狗放到真实 Pixhawk 上就被噪声和延迟拖垮。我自己的解法是用 Simulink 把飞机本体、传感器、甚至风场全部建模再把 PX4 跑在一块真实的 Pixhawk 飞控硬件上通过 MAVLink 的 HIL 协议把两者闭环接上。这就是题目里说的“Simulink 与 PX4 硬件在环仿真HIL”飞控是真硬件飞机是虚拟飞机但每一帧传感器数据、执行器输出、MAVLink 报文都是真实流动的。这套环境既能复用 PX4 官方生态又能把 Simulink 的建模能力拉满特别适合做控制算法验证、传感器故障注入和飞行栈集成测试。下面我按自己从零搭这套环境的顺序把架构、消息协议、踩坑点一次说清楚。1. 先搞清楚HIL 到底把哪一环“铁”在了回路里很多人听到“硬件在环”第一反应是我有真飞控跑 PX4再用 Simulink 算控制律把两个东西直接连起来。这个理解方向对但容易把两种完全不同的工作流混在一起所以我先花篇幅把概念掰开。第一种工作流叫RCP快速控制原型核心是“控制器原型”。你用 Simulink 搭控制算法通过外部模式或自动代码生成把算法跑在真实飞控硬件上替代或包裹原有固件。此时 Simulink 是“大脑”PX4 更多是底层驱动和硬件抽象。第二种工作流就是本文主角HIL核心是“飞机原型”。PX4 固件完完整整跑在真 Pixhawk 上Simulink 负责模拟出这架飞机在现实中会看到的传感器数据、物理响应和外部环境再把执行器指令接回动力学模型。换句话说PX4 以为自己在开真飞机其实它在开一个 Simulink 搭出来的“数字双胞胎”。这两种工作流常被混用但调试思路完全不同。RCP 问题多半在控制算法和代码生成HIL 问题多半在传感器建模和通信链路。我之所以坚持用 HIL 而不是 SITL核心原因有三个固件是真正跑在 ARM 芯片上的调度、内存、外设驱动、传感器融合的时间特性都和真机一致传感器数据是通过 MAVLink 报文注入的比 SITL 里直接改共享内存更接近真实链路可以很方便地接入真实执行机构或台架比如电机、舵机、CAN 总线设备做分级测试。对比项SITL 软件在环HIL 硬件在环真机试飞固件运行环境PC 上的仿真进程真实飞控硬件真实飞控硬件传感器来源模拟器直写Simulink 建模后经 MAVLink 注入真实 IMU/GPS执行机构无可接真实电机/舵机也可纯虚拟真实电机/螺旋桨调试成本最低中等高风险高成本适合场景逻辑验证、初学固件验证、硬件集成、故障注入最终实飞验收从这张表能看到HIL 是在“仿真可信度”和“调试代价”之间最平衡的点。对 PX4 这种开源飞控来说官方本来就留了 HIL 协议栈Simulink 又是一个通用建模仿真环境所以两者结合完全可行而且比很多人想象中简单。2. 搭建 HIL 工程前的软硬件清单要把这套环境跑起来先把材料备齐。硬件方面一块真实的 Pixhawk 系飞控是必须的Pixhawk 4、Pixhawk 6C、CUAV 系列都可以原则是主控芯片不要太老F4 以上的芯片带 HIL 都没问题但如果你同时开 QGC 和 Simulink飞控端最好有足够的串口和 USB 资源。另外一定要准备一根真正能传数据的 USB 线不是那种只能充电的线很多“连不上 PX4”的案例最后都发现是线材问题。PC 这边Simulink 仿真要吃不少 CPU尤其是动力学模型做了多体建模或者加了高保真传感器模型时。我自己常用配置是 i7 十二代以上、16G 内存MATLAB 用 R2021b 之后版本因为 UAV Toolbox 对 PX4 的 HIL 支持在后面的版本里更稳定。软件清单里除了 MATLAB/Simulink还需要装 UAV Toolbox如果你要做六自由度飞行器动力学可以再加 Aerospace Blockset地面站用 QGroundControlPX4 固件直接拉官方仓库版本建议选你 QGC 和 Simulink 都验证过的稳定分支比如 v1.13 或 v1.14不要一上来就追最新 main。这里特别说一个工具选型问题Simulink 接入 PX4 HIL 有两条路。一条是用 UAV Toolbox 自带的 PX4 HIL 相关模块最常见的就是 “PX4 HIL Sensor” 和 “PX4 HIL Actuator”它们在 Simulink 库浏览器里拖出来就能用内部已经封装好了 MAVLink 报文打包和解包适合快速跑通闭环。另一条是自己通过 UDP 收发模块手动构造 MAVLink HIL 报文这条适合没有工具箱授权、或者想深度定制协议的人。两条路我都试过前者的优点是省事缺点是被封装太严出问题时很难看到内部数据后者调试灵活但你需要自己维护字节序、CRC 校验和报文结构。如果是新手第一次跑通我建议先用官方块跑通后再慢慢换自制报文。QGroundControl 作为地面站在整个链路里不是配角它承担了 MAVLink 报文转发的任务。PX4 飞控通过 USB 连到电脑QGC 和飞控建立 MAVLink 连接后会把 Simulink 发来的仿真传感器数据转给 Pixhawk也会把 Pixhawk 的执行器输出转回 Simulink。因此 QGC 的版本和通信端口配置直接决定 HIL 能不能连上这也是很多人忽略的一点。3. 系统架构与 HIL 消息流向这一节决定你能不能跑通很多人在 Simulink 里搭好飞机模型又在 QGC 里打开了 HIL 开关却发现两边根本不说话。原因通常是没搞懂 HIL 消息到底是怎么流动的。先把整体链路画在脑子里Simulink 里的飞机动力学模型计算出当前姿态、位置、速度然后经过传感器模型生成 IMU、气压计、GPS 等数据这些数据被打包成 MAVLink 的 HIL 报文通过 UDP 发到 QGCQGC 再通过 USB 串口把这些报文转发给 PixhawkPX4 固件把这些“虚拟传感器”数据吃进去跑姿态估计和控制律计算电机指令电机指令通过 HIL_ACTUATOR_CONTROLS 报文发回 QGC再由 QGC 转发给 SimulinkSimulink 收到后更新动力学模型。一个完整的闭环就是这样。实际调试时我最常用的消息有四类MAVLink 消息方向作用HIL_SENSORSimulink → PX4注入 IMU、气压计、温度等原始传感器数据HIL_GPSSimulink → PX4注入 GPS 位置、速度、定位状态HIL_STATE_QUATERNIONSimulink → PX4注入由仿真得到的姿态四元数、角速度、加速度、地磁等状态HIL_ACTUATOR_CONTROLSPX4 → Simulink将 PX4 计算出的执行器控制量返回仿真模型很多资料会混用 HIL_SENSOR 和 HIL_STATE_QUATERNION。从实际效果看HIL_STATE_QUATERNION 携带的姿态状态更完整PX4 的姿态估计器可以直接拿到比较干净的姿态信息适合验证上层控制律HIL_SENSOR 走的是更底层的“原始传感器 → 估计器”链路适合验证传感器故障注入和容错算法。想贴近真实飞控行为建议先用 HIL_SENSOR HIL_GPS 的组合想快速调控制参数可以偷懒用 HIL_STATE_QUATERNION。时序是这个环节里最重要的参数。PX4 的传感器模块以固定频率发布 UORB 消息比如陀螺和加速度计通常跑 250Hz 到 1000Hz气压计 50Hz 左右GPS 在 5Hz 到 10Hz。Simulink 里发送 HIL_SENSOR 的频率必须和这些真实频率匹配否则飞控内部的状态估计器会拿捏不准时间戳导致姿态解算震荡。我的习惯是 Simulink 模型固定步长设到 1ms也就是仿真主循环 1kHz然后通过采样率不同的子模块分别发送不同频率的 HIL 报文这样和真实传感器刷新率更接近。另一个容易踩的细节是 UDP 通信端口。QGC 和 Simulink 之间走的 UDP 端口在 QGC 的 HIL 配置界面里会显示Simulink 里发送模块的远端 IP 要填运行 QGC 的那台电脑地址端口要填 QGC 监听端口。如果你用远程连接跑仿真或者把 Simulink 跑在另一台机器上网络环境变成跨设备转发就一定要先确认防火墙放行了对应 UDP 端口。不要用 WiFi 跑这个实测丢包率会让人崩溃网线直连最稳。4. 实操从 Simulink 模型到 PX4 HIL 完整闭环下面这段是我实际跑通的步骤按顺序执行基本能在一个工作日内把最小闭环拉起来。前提是你已经把 QGroundControl 和 Simulink 都装好Pixhawk 能正常刷入 PX4 固件并且能用 QGC 连接飞控。4.1 将 PX4 切换到 HIL 模式先用 USB 数据线把 Pixhawk 连到电脑打开 QGC确认能正常读取飞控状态然后进入 HIL 配置界面。QGC 不同版本的菜单位置略有差异但搜索 “HIL” 基本都能找到相关项。把 HIL 仿真开关打开后PX4 固件会进入等待外部传感器数据的模式此时飞控不会再读取板上真实 IMU而是等待 HIL_SENSOR 等报文灌进来。这个阶段飞控上的 LED 通常会变成黄色或蓝色闪烁不同版型表现不一样但 QGC 里飞控状态会从“连接正常”变成“等待仿真数据”。这里有个坑有些 Pixhawk 板子如果接了安全开关需要在切换 HIL 前解除安全模式否则 HIL 模式下执行器输出会被安全开关锁定遥控器也切不了模式。遇到过好几个人卡在这一步以为是协议问题结果按下安全开关直接解决。4.2 创建 Simulink 模型与仿真飞机Simulink 侧的第一步是搭一个能实时迭代的飞机模型。如果你不想从零写动力学可以先用 UAV Toolbox 官方示例里的 PX4 HIL 工程作为基底在 MATLAB 命令窗口输入openExample(uav/PX4HILSimulationExample)这行命令会打开一个已经封装好 PX4 HIL 通信模块的 Simulink 工程里面自带一架多旋翼的简化动力学模型以及 HIL 报文的发送接收模块。你可以先直接运行这个示例把整个链路跑通然后再换成本机想要验证的飞机模型。如果你和我一样习惯自己搭模型那么 Simulink 模型需要包含四个核心部分飞行动力学模块、传感器模型模块、HIL 报文输入模块、HIL 报文输出模块。求解器务必改为 fixed-step固定步长选 0.001 秒因为 HIL 通信要求严格定时变步长会导致报文发送间隔抖动飞控姿态估计会跟着抖。4.3 接入 HIL 通信模块使用 UAV Toolbox 的方式很直接从 Simulink 库浏览器找到 UAV Toolbox 下针对 PX4 的模块把 “PX4 HIL Sensor” 模块拖进模型它的输入是传感器数据总线输出会自动封装成 MAVLink HIL_SENSOR 报文并通过 UDP 发出去再把 “PX4 HIL Actuator” 模块拖进来它的输出是 PX4 返回的执行器控制量。这两个模块的参数里有 IP 地址和端口填 QGC 所在机器的地址和端口即可。如果是自制报文方案则需要用 Simulink 的 UDP Send 和 UDP Receive 模块自己写一个 MATLAB Function 完成数据打包。下面是我做过的简化版 HIL_SENSOR 打包函数骨架重点展示字段顺序不是完整代码function msg packHilSensor(gx, gy, gz, ax, ay, az, ... mx, my, mz, pressure, temperature) % 构造 MAVLink HIL_SENSOR 消息体消息ID107 % 实际还要包括 state fields、时间戳 us 等 buf zeros(1, 32, uint8); % 这里按 MAVLink 字节序填入 IMU、气压、温度等字段 % 填充完后在前面加上 MAVLink 帧头 0xFD、长度、序列号、系统ID等 msg [mavlinkHeader, buf]; end这里最核心的就是字段顺序和字节序。MAVLink 2 默认小端消息头里的消息 ID 必须对CRC extra 也要算对少一位或多一位都会在飞控端被静默丢弃。自己实现一次之后你会对 MAVLink 协议有格外深刻的理解。4.4 运行仿真完成闭环配置好后先启动 QGC 里的 HIL 模式再运行 Simulink 模型。正常情况下Simulink 会在几百毫秒内收到 PX4 返回的 HIL_ACTUATOR_CONTROLS 报文QGC 里的虚拟飞机姿态也会开始随模型变化。你可以给 Simulink 模型加一个遥控器输入信号模拟 PX4 切到自稳模式后执行器响应情况。如果 QGC 的飞机视图有姿态变化并且和 Simulink 内部状态一致就说明整个 HIL 环路已经工作。实际调试中我第一次跑通时 QGC 里飞机姿态稳定但推油门没有反应。排查后发现是 PX4 没有切到自稳模式HIL 模式下默认的可能还是手动模式飞控收到遥控器通道为零的执行器指令后保持怠速。后来我在 QGC 里切到自稳又给了正油门通道执行器输出才明显加大。5. 把模型做细动力学和传感器建模的几个关键点HIL 仿真可信度上限完全取决于 Simulink 里的飞机模型有多“真”。如果模型只是一个简化积分器那 HIL 跑得再流畅也只是心理安慰。以下几个建模细节直接影响 PX4 姿态估计和控制律的验证效果。5.1 刚体动力学模型不能省陀螺力矩多旋翼模型的最小集合是机体三个方向的受力、力矩、转动惯量矩阵以及电机转速到推力和反扭矩的映射。很多简化模型只算线加速度和角加速度但忽略了陀螺力矩——也就是转子高速旋转时机体角运动会引起的附加力矩。这个量在高速自旋和大机动时非常明显忽略后仿真出来的响应会偏“钝”PX4 在真机上可能表现完全不同。我常用的电机推力模型是T k_t * w^2 Q k_q * w^2其中 w 是电机转速k_t 和 k_q 分别是推力系数和反扭矩系数。这两个系数必须实测或从桨数据反推不能随便拍脑袋否则悬停油门和真实飞机对不上。电机本身还要加一阶惯性环节模拟电调和电机从指令到转速的延迟通常时间常数在 20ms 到 50ms。5.2 传感器模型要“脏”一点PX4 的姿态估计器是在真实噪声环境下设计的如果你给它的传感器数据是理想的、无噪声、无偏差的反而会掩盖算法对噪声的鲁棒性问题甚至让某些自适应增益跑飞。所以传感器建模一定要加噪声和偏差。具体来说陀螺仪加高斯白噪声和随机游走偏置加速度计加常值偏置和高频噪声磁力计加软硬磁干扰和随机偏置气压计加压力和高度噪声GPS 加位置速度噪声和更新周期延迟。UAV Toolbox 里有些传感器模型可以直接用但更多时候还是用 Simulink 里的 Random Number、Discrete-Time Integrator 自己搭。你还可以用 MATLAB 的 imuSensor 系统对象生成更真实的惯性测量数据再把它封装成 Simulink S-Function 或 MATLAB Function 块。5.3 执行器输出要和混控表对好PX4 的多旋翼混控器把控制量映射到某个执行器输出端口Simulink 端接收到的 HIL_ACTUATOR_CONTROLS 报文里通道顺序是按混控组排的不是简单的前后左右四个电机。你要在模型里按 PX4 的混控定义把四个或八个执行器通道对应到电机模型上否则飞机姿态容易乱。QGC 的电机测试界面可以帮你确认每个电机编号或者在 PX4 源码的 mixer 文件里直接查通道定义。这条容易被忽略但一旦错一个通道HIL 里表现出来的就是各种诡异漂移。6. 问题排查与避坑实录我把实际调试中遇到过的高频问题整理成一张速查表每条后面都有解决思路。现象可能原因处理办法QGC 能连飞控但启动 HIL 后无反应HIL 参数未写入飞控或固件版本不支持重新刷入匹配的 PX4 稳定版检查 MAV_HIL 参数Simulink 模型运行但 QGC 收不到 HIL 数据UDP 端口或 IP 配置错误先用 Wireshark 或 MATLAB 网络工具抓包确认 Simulink 报文是否发出QGC 有仿真数据但飞控姿态一直不动HIL_SENSOR 时间戳或更新率异常检查 Simulink 是否按固定周期发送时间戳字段是否用微秒填推油门后执行器输出无变化HIL_ACTUATOR_CONTROLS 路由错误或飞控处于手动模式在 QGC 切自稳模式检查遥测通道是否正常姿态估计发散传感器噪声模型不合理或模型频率太低降低噪声方差提高 HIL_SENSOR 发送频率电机输出抖动明显仿真步长过大或执行器指令有毛刺固定步长调到 1ms给执行器信号加低通滤波远程连接时经常断流UDP 丢包WiFi 链路不稳定改成有线直连降低发送频率第一类问题很多时候不是协议问题而是 QGC 自己把 USB 设备识别错。一个很实用的排错思路是分层检查。先关闭 HIL只用 QGroundControl 发一个测试 MAVLink 报文给飞控看飞控是否响应再用 Simulink 单独往 QGC 发一帧测试报文看 QGC 消息分析工具里是否能看到该帧最后再合起来跑 HIL。这样可以快速把问题定位到飞控端、通信层还是仿真模型。还有一个让我印象很深的坑HIL_SENSOR 消息里的 time_usec 字段必须用微秒时间戳而且最好和 Simulink 仿真时间对齐。我当时用上位机秒表时间填进去导致飞控里的姿态估计器时间补偿逻辑出错每次机动姿态都会瞬间跳变。改用仿真时间戳后立刻恢复正常。做 HIL 时时间戳就是一种“传感器”它比 IMU 数据还敏感。7. 一些我从实际调试里折腾出来的经验最后讲几点个人体会不属于标准接线步骤但能帮你少走很多弯路。第一刚起步时不要追求“完全真实”的传感器模型。先用低噪声模型把闭环跑通再逐步往 IMU 和 GPS 里加噪声、加延迟。否则模型噪声太大PX4 姿态估计器还没收敛你根本分不清是控制律问题还是仿真环境问题。第二Simulink 和 QGC 最好在同一台机器上跑不要为了“显得专业”把仿真放到服务器上。网络转发每多一跳时序抖动就多一分排查难度成倍增加。第三务必备份 QGC 的相关配置和 Simulink 工程版本因为 MATLAB 版本升级或 PX4 固件更新后HIL 接口偶尔会有偏移尤其是一些模块路径和参数名会变备份能让你快速回滚到可用状态。我现在的标准流程是先在 Simulink 里把动力学和传感器模型调到无真机也能自稳再进 HIL 跑一遍完整飞行任务最后才上真机。HIL 帮我拦住的问题比预想的多得多尤其是一次电调混控通道接反的问题真机测试可能直接把飞机摔了HIL 里只是姿态翻了一圈而已。这套环境里踩过的坑越多真机试飞心里就越有底。如果后续你想把模型做更可信还可以把真实风洞数据、CAN 总线设备、甚至转向台架这类真实执行机构都接进来那算是 HIL 的进阶玩法了。