4、SITL仿真环境:从原理到实战

SITL,全称 Software In The Loop,软件在环仿真。说白了,就是在一台电脑上跑一套完整的飞控软件,模拟出无人机在空中飞行的状态。你不需要硬件,不需要飞控板,甚至不需要螺旋桨。我刚开始接触 ArduPilot 时,第一件事就是搭 SITL 环境。为什么?因为调试效率高太多了。

你想想看,真机调试一次,从开电脑、连数传、上电、解锁、起飞到降落,至少十分钟。要是炸机了,还得修飞机。而 SITL 里,你敲几个命令,飞机就上天了。参数改错了?重启一下,几秒钟的事。我在项目里遇到过好几次,真机上不敢试的参数组合,先在 SITL 里跑一遍,确认没问题再上真机。这个习惯帮我省了不少维修费。

核心要点:SITL 不是模拟器,它是真实的飞控代码在 PC 上运行。你调用的 EKF、导航、控制算法,和真机完全一样。区别只在于传感器数据来自仿真模型,而不是真实物理世界。

4.1 SITL 原理:软件在环到底在环什么?

SITL 的架构其实不复杂。我画了一张图,你看完就明白了。

SITL 软件在环仿真架构图 SITL 软件在环仿真架构 用户输入(MAVProxy/RC) ArduPilot 飞控代码 EKF / 导航 / 控制 / 混控 仿真模型(JSBSim / Gazebo) 传感器仿真 / 物理引擎 MAVLink 通信 地面站(Mission Planner) 关键区别 真机:传感器 → 飞控 → 电机 SITL:仿真模型 → 飞控 → 仿真模型 代码完全一致,输入输出不同 我踩过的坑 SITL 里调好的 PID 上真机不一定稳

你看这个闭环:用户输入指令 → 飞控代码计算 → 仿真模型反馈传感器数据 → 飞控再计算。这个循环每秒跑 400 次(主循环频率)。我在项目中遇到过一个问题:SITL 里飞机飞得稳稳的,上真机就抖。后来发现是仿真模型的电机响应太理想了,真机电调有延迟。所以 SITL 适合验证逻辑,不适合直接抄参数。

4.2 启动 SITL:sim_vehicle.py 的正确姿势

启动 SITL 最常用的工具是 sim_vehicle.py。这个脚本在 ArduPilot 源码的 Tools/autotest/ 目录下。我个人习惯把它加到 PATH 里,这样在任何目录都能直接调用。

先看看最基本的启动命令:

# 启动四旋翼 SITL,默认使用 jsbsim 仿真模型
sim_vehicle.py -v ArduCopter --map --console

# 参数说明:
# -v ArduCopter  指定机型(ArduCopter / ArduPlane / ArduRover)
# --map          自动打开 MAVProxy 地图窗口
# --console      打开 MAVProxy 控制台窗口

我第一次跑这个命令时,等了大概 10 秒,终端里开始刷数据,地图窗口弹出来,控制台也出来了。那一刻还挺有成就感的。不过要注意,第一次启动会编译飞控代码,耗时比较长,大概 3-5 分钟。之后启动就快了,几秒钟的事。

小技巧:如果你只想快速验证,不加 --map 和 --console,启动会更快。我调试参数时经常只开终端,减少窗口切换的麻烦。

常用的启动参数我整理了一张表:

参数 作用 我的用法
-v ArduCopter 指定机型 四旋翼用 ArduCopter,固定翼用 ArduPlane
--map 打开地图窗口 调试航线时必开
--console 打开控制台 看日志和状态时用
-I0 指定实例编号 多机仿真时用 -I0, -I1, -I2
--speedup 10 加速仿真 长时间测试时用 10 倍速
--no-extra-ports 不开启额外端口 减少端口占用,单机调试推荐

4.3 连接 MAVProxy:你的命令行地面站

MAVProxy 是 ArduPilot 生态里一个很强大的命令行地面站。启动 SITL 后,它会自动在本地 14550 端口开启 MAVLink 通信。你可以用 MAVProxy 连接上去,也可以让 Mission Planner 连接。

我个人更习惯用 MAVProxy 做调试,因为它轻量、快速,而且支持脚本化操作。连接命令很简单:

# 在另一个终端窗口连接 SITL
mavproxy.py --master tcp:127.0.0.1:5760 --out udp:127.0.0.1:14550

# 参数说明:
# --master  指定 SITL 的 TCP 端口(默认 5760)
# --out     指定输出端口(地面站监听端口)

连接成功后,你会看到 MAVProxy 的提示符 STABILIZE>。这个提示符会显示当前的飞行模式。嗯,这里要注意:如果提示符没出来,说明连接有问题。我遇到过好几次,都是因为端口被占用了。检查一下有没有其他程序占用了 5760 或 14550 端口。

常见问题:如果你同时开了 Mission Planner,它会抢占 14550 端口。建议先关掉 Mission Planner,等 MAVProxy 连接成功后再开。或者让 Mission Planner 连接其他端口,比如 14551。

4.4 控制台交互:mode / arm / takeoff

连接成功后,你就可以在 MAVProxy 控制台里操控飞机了。这是最常用的三个命令:

# 1. 切换飞行模式
STABILIZE> mode GUIDED
# 或者简写
STABILIZE> mode guided

# 2. 解锁电机
STABILIZE> arm throttle
# 成功会返回:ARMED

# 3. 起飞到 10 米高度
STABILIZE> takeoff 10
# 成功会返回:Takeoff started

我第一次在 SITL 里起飞时,看着地图上的飞机图标缓缓上升,心里还挺激动的。不过后来有一次,我忘了先切 GUIDED 模式就直接 arm,结果飞机解锁后直接原地旋转——因为 STABILIZE 模式下没有 GPS 位置保持。所以,养成好习惯:先切 GUIDED,再 arm,最后 takeoff。

常用的控制命令:

  • mode GUIDED — 切换到 GUIDED 模式,这是执行任务和指令的基础模式
  • arm throttle — 解锁电机,前提是满足解锁条件(GPS 锁定、电池电压正常等)
  • takeoff 高度 — 起飞到指定高度(单位:米)
  • land — 降落
  • rc 3 1500 — 手动设置遥控器通道值(通道 3 是油门)
  • status — 查看当前状态(模式、GPS、电池等)

调试技巧:如果你想让飞机悬停在空中不动,可以先用 takeoff 10 飞到 10 米,然后切到 mode LOITER。飞机会自动保持位置和高度。我经常用这个状态来测试参数修改的效果。

4.5 参数实时修改:不用重启就能调参

SITL 的一大优势就是可以实时修改参数,不用重启。这在真机上是不可能的——真机改参数后必须重启飞控才能生效。但在 SITL 里,你可以边飞边改。

# 查看参数当前值
STABILIZE> param show RTL_ALT
# 返回:RTL_ALT = 1500(单位:厘米,即 15 米)

# 修改参数
STABILIZE> param set RTL_ALT 2000
# 返回:RTL_ALT = 2000

# 保存参数(可选)
STABILIZE> param save

我做过一个实验:让飞机在 LOITER 模式下悬停,然后实时修改 ATC_ANG_RLL_P(横滚角度 P 增益)。从 4.0 改到 8.0,你能明显看到飞机的横滚响应变快了。再改到 2.0,飞机变得软绵绵的。这种实时反馈对理解 PID 参数的作用非常有帮助。

常用的调试参数:

参数名 作用 典型值 修改效果
ATC_ANG_RLL_P 横滚角度 P 增益 4.0 - 8.0 越大响应越快,但可能震荡
ATC_ANG_PIT_P 俯仰角度 P 增益 4.0 - 8.0 同上
RTL_ALT RTL 返航高度 1500 - 3000(厘米) 返航时先爬升到该高度
WPNAV_SPEED 航点飞行速度 500 - 1000(厘米/秒) 控制任务飞行速度
LOG_BITMASK 日志记录掩码 0 - 65535 控制哪些数据写入日志

注意:虽然 SITL 支持实时改参,但有些参数修改后需要重新初始化才能生效。比如修改了 FRAME_CLASS(机型类型),必须重启 SITL。我建议改完参数后,用 param save 保存,然后重启 SITL 确认参数生效。

好了,SITL 的基本操作就这些。从原理到启动,从连接到控制,再到实时调参,这一套流程你走一遍,基本就能上手了。我个人建议你花点时间在 SITL 里多玩玩,试试不同的参数组合,看看飞机的响应变化。这种经验在真机调试时非常宝贵。