4. 航空软件SIL仿真平台选型与搭建

飞控软件的SIL(Software-in-the-Loop)仿真,是把经过编译的飞控应用代码与飞控模型、被控对象模型、传感器/执行机构模型一起放在宿主机上运行,用虚拟时间推进闭环,从而在没有真实硬件的情况下验证控制律、模式切换和故障逻辑。本节的目标不是罗列所有工具,而是完成一个“最小可用”的SIL环境:能编译、能集成、能跑通一个定高或姿态保持的闭环用例,并能看到可判读的结果。

一、主流SIL工具链的取舍

工程上常见的组合有三类。第一类是MATLAB/Simulink + Embedded Coder + Simulink Test:模型即环境,自动生成被测代码,适合控制律早期验证,但飞控软件的真实C代码往往需要额外封装成S-Function或通过FMU接入。第二类是开源栈,如PX4/ArduPilot的jMAVSim、Gazebo、FlightGear组合,飞控代码直接编译为原生可执行文件,通过MAVLink与仿真器交互,最接近真实软件形态,适合回归测试。第三类是商业工具链,如SCALEXIO、dSPACE VEOS、Vector CANoe的SIL选项,接口规范、可追溯性好,但成本高、依赖授权。

对于“最小可用搭建”,推荐以PX4 SITL + Gazebo(或jMAVSim)为骨架,因为它天然满足三个条件:飞控代码是真实C/C++工程、编译产物就是被测对象、接口(MAVLink/uORB)与实机一致。若团队已有Simulink资产,则用FMU把模型作为被控对象接入,飞控代码仍走原生编译,避免“模型里跑模型”导致的可信度下降。

飞控软件SIL最小可用环境:编译—集成—接口—运行 宿主机(Ubuntu 22.04 / x86_64) 飞控应用代码 姿态/位置控制律 模式管理、故障逻辑 uORB 发布/订阅 make px4_sitl_default 编译产物 build/px4_sitl_default/ bin/px4(原生可执行) etc/init.d-posix/rcS ELF + 启动脚本 被控对象与传感器模型 Gazebo / jMAVSim 六自由度刚体 + 气动 IMU/GPS/气压计噪声 SDF/URDF 模型文件 编译 接口适配层(HIL/SIL 桥) MAVLink 消息 ↔ 仿真器传感器/执行机构接口 simulator_mavlink / lockstep 时间同步 运行与观测 QGroundControl / MAVSDK 指令 ulog 日志、姿态/高度曲线 判读依据 超调 ≤ 10%、稳态误差 ≤ 0.5 m 模式切换无异常、无看门狗复位

二、模型编译与集成

以PX4为例,编译命令本身很简单,但“最小可用”的关键在于确认产物和启动脚本正确:

cd ~/PX4-Autopilot
make px4_sitl_default gazebo
# 或仅编译不启动仿真
make px4_sitl_default

编译完成后,build/px4_sitl_default/bin/px4 就是被测飞控可执行文件,etc/init.d-posix/rcS 决定启动时加载哪些模块。集成时要注意两点:一是控制律参数(如 MPC_XY_P、MPC_Z_P)应通过参数文件或 param set 注入,而不是硬编码,便于回归时批量替换;二是若用Simulink模型作为被控对象,应导出FMU并让仿真器加载,飞控侧仍通过MAVLink收发,避免把控制律也放进Simulink导致“测的不是真实代码”。

三、接口适配

SIL的接口适配核心是“消息映射”和“时间同步”。飞控内部用uORB传递 sensor_combined、vehicle_attitude、actuator_controls 等主题;仿真器需要的是物理量(角速度、加速度、位置、电机转速)。桥接模块 simulator_mavlink 负责把仿真器的 HIL_SENSOR、HIL_GPS 消息转成uORB,再把 actuator_controls 转成 HIL_ACTUATOR_CONTROLS 发回仿真器。若使用lockstep模式,仿真器每推进一步都等待飞控完成一次控制周期,保证时序一致;若用实时模式,则需关注仿真步长与飞控主循环周期的匹配,避免积分漂移。

接口适配中常见的坑是坐标系和单位:MAVLink的 HIL_SENSOR 使用NED(北-东-地)坐标系,加速度单位m/s²,角速度rad/s;而部分模型输出的是ENU或机体轴,必须在桥接层显式转换。建议在桥接代码中集中定义转换函数,并在日志中打印原始值与转换值,便于排障。

四、环境配置脚本

为了让环境可复现,应把依赖安装、编译、启动、参数注入写成脚本。下面是一个最小示例,假设已安装ROS 2和Gazebo:

#!/usr/bin/env bash
set -e
export PX4_HOME=$HOME/PX4-Autopilot
export GAZEBO_MODEL_PATH=$PX4_HOME/Tools/sitl_gazebo/models

# 1. 编译
cd $PX4_HOME
make px4_sitl_default

# 2. 启动仿真器(后台)
gazebo --verbose Tools/sitl_gazebo/worlds/iris.world &
GAZEBO_PID=$!
sleep 3

# 3. 启动飞控并加载参数
build/px4_sitl_default/bin/px4 -d \
  -s etc/init.d-posix/rcS \
  -p 4560 &
PX4_PID=$!

# 4. 注入回归参数
sleep 5
param set MPC_Z_P 1.2
param set MPC_Z_VEL_P 0.8
param set MPC_ALT_MODE 2

# 5. 运行用例(示例:起飞到2m并悬停)
mavsdk_takeoff --alt 2.0
sleep 20

# 6. 收尾
kill $PX4_PID $GAZEBO_PID

脚本中 -d 表示后台运行,-s 指定启动脚本,-p 4560 是MAVLink端口。参数注入放在飞控启动之后、用例执行之前,确保生效。若需要批量回归,可把参数和用例写成CSV,由脚本循环读取并替换。

五、最小可用验证

环境搭好后,用一个定高悬停用例验证闭环是否真正跑通。操作上:启动仿真,发送起飞指令到2 m,等待20 s,观察高度曲线。判读依据可以设为:上升时间小于5 s、超调不超过10%(即峰值不超过2.2 m)、稳态误差在±0.5 m以内、姿态角波动小于3°。若高度持续发散或模式自动切回手动,优先检查 actuator_controls 是否被仿真器接收、HIL_SENSOR 时间戳是否单调递增、以及参数是否被正确加载。日志用 ulog2csv 导出后,重点看 vehicle_local_position.z 和 vehicle_attitude 两条曲线。

最小可用的标准不是“能启动”,而是“能复现一个可判读的闭环结果”。建议把启动脚本、参数文件、用例指令和判读阈值一起纳入版本管理,后续回归测试才能直接复用。