1. SITL仿真环境深度搭建:从源码编译ArduPilot SITL,配置自定义机型与传感器模型
各位同学,欢迎来到《进阶SITL仿真》的第一章。
做飞控开发,尤其是姿态调参,最怕什么?怕炸机。真机炸一次,几千块没了,还得提心吊胆查日志。所以我的习惯是——先在SITL里把参数跑透,再上真机。今天我们就从最底层开始,把SITL环境彻底搭明白。
1.1 为什么非要自己编译SITL?
很多人图省事,直接下载别人编译好的二进制文件。说实话,日常用用没问题。但你要做自定义机型、改传感器模型、甚至调底层姿态估计算法,没有源码在手,寸步难行。
我自己踩过这个坑。有一次想给四旋翼加一个非对称的载荷分布,结果二进制SITL根本不支持自定义混控器。折腾了两天,最后还是老老实实从源码编译。嗯,从那以后,我每换一台电脑,第一件事就是拉源码编译一遍。
核心观点:源码编译让你拥有对仿真环境的完全控制权。你可以修改任何一行C++代码,然后立刻看到效果。
1.2 环境准备:Ubuntu + 依赖库
我推荐用 Ubuntu 22.04 LTS。其他发行版也行,但依赖包名可能不一样,自己折腾去。
先把基础工具装上:
sudo apt update
sudo apt install git wget python3-pip python3-dev
sudo apt install build-essential pkg-config
sudo apt install libtool autoconf automake
然后是ArduPilot编译的核心依赖:
sudo apt install g++-arm-linux-gnueabihf
sudo apt install libc6-armhf-cross libc6-dev-armhf-cross
sudo apt install libpython3.10-dev
小技巧:如果你网络不好,建议先配好国内pip镜像。我习惯用清华源:pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
1.3 拉取源码与编译流程
找个干净的目录,开始拉代码:
git clone https://github.com/ArduPilot/ardupilot.git
cd ardupilot
git submodule update --init --recursive
这一步会下载所有子模块,包括MAVLink、DroneKit等。网络慢的话,可以分步执行:
git submodule initgit submodule update --recursive
接下来安装Python依赖:
pip install -r requirements.txt
然后编译SITL。以四旋翼为例:
./waf configure --board sitl
./waf build --target bin/arducopter
第一次编译大概要10-15分钟。别急,去泡杯咖啡。编译成功后,你会看到类似这样的输出:
Waf: Leaving directory `/home/user/ardupilot/build/sitl'
'build' finished successfully (12m 34s)
注意:如果编译报错,90%是依赖没装全。检查一下 g++-arm-linux-gnueabihf 和 libpython3.10-dev 是否真的装上了。我曾经因为少装了一个 libtool,卡了整整一下午。
1.4 启动你的第一个SITL实例
编译成功后,启动仿真:
cd ardupilot
./Tools/autotest/sim_vehicle.py -v ArduCopter --map --console
你会看到三个窗口弹出来:
- 终端窗口:显示飞控启动日志
- 地图窗口:显示飞机当前位置
- 控制台:可以输入MAVLink命令
输入 arm throttle 解锁,然后推油门。飞机应该能飞起来了。如果不行,检查一下仿真时间是否在走——有时候系统时间同步问题会导致仿真卡住。
1.5 自定义机型:从零写一个混控器
这才是本章的重头戏。默认的SITL只支持标准四旋翼、固定翼等常见机型。但你要做姿态调参策略研究,往往需要奇奇怪怪的构型。
举个例子:我想做一个 X型四旋翼,但电机安装角度不是标准的45度,而是30度。怎么办?
找到混控器文件:libraries/AP_Motors/AP_MotorsMatrix.cpp
在 setup_motors() 函数里,添加你自己的机型:
// 自定义30度X型四旋翼
case MOTOR_FRAME_CUSTOM_X30: {
add_motor(AP_MOTORS_MOT_1, -0.5, 0.5, 1.0, 1); // 右前
add_motor(AP_MOTORS_MOT_2, 0.5, -0.5, 1.0, 2); // 左后
add_motor(AP_MOTORS_MOT_3, -0.5, -0.5, 1.0, 3); // 左前
add_motor(AP_MOTORS_MOT_4, 0.5, 0.5, 1.0, 4); // 右后
break;
}
然后重新编译:
./waf build --target bin/arducopter
启动时指定机型:
./Tools/autotest/sim_vehicle.py -v ArduCopter --frame=custom_x30
关键点:混控器矩阵的四个参数分别是:Roll系数、Pitch系数、Yaw系数、电机编号。正负号决定旋转方向,数值大小决定力矩权重。
1.6 传感器模型配置:让仿真更真实
默认的SITL传感器太理想了。没有噪声,没有延迟,没有漂移。这会导致你在仿真里调好的参数,上真机就炸。
我建议你至少改三个地方:
| 传感器 | 默认参数 | 推荐修改值 | 说明 |
|---|---|---|---|
| IMU加速度计 | 无噪声 | SIM_ACCEL_NOISE=0.1 |
模拟真实加速度计噪声 |
| IMU陀螺仪 | 无噪声 | SIM_GYRO_NOISE=0.05 |
模拟真实陀螺仪噪声 |
| GPS | 理想定位 | SIM_GPS_NOISE=1.0 |
模拟GPS水平误差1米 |
| 气压计 | 无延迟 | SIM_BARO_DELAY=0.1 |
模拟气压计100ms延迟 |
这些参数可以在启动时通过 --sim-param 传入:
./Tools/autotest/sim_vehicle.py -v ArduCopter \
--sim-param SIM_ACCEL_NOISE=0.1 \
--sim-param SIM_GYRO_NOISE=0.05 \
--sim-param SIM_GPS_NOISE=1.0
我的经验:先加小噪声,再慢慢加大。加太猛的话,你会发现飞机根本稳不住——那不是你PID的问题,是传感器太烂了。我一般从真机实测的噪声水平开始,然后上浮20%作为安全余量。
1.7 本章知识体系总览
下面这张图,帮你把整个SITL环境搭建的逻辑串起来:
1.8 避坑指南
最后,分享几个我踩过的坑:
- 子模块下载失败:国内网络经常连不上github。解决办法是用代理,或者提前把子模块的仓库clone好,手动放到对应目录。
- 编译报错找不到头文件:检查一下
git submodule status,看看子模块是不是空的。我遇到过好几次子模块没拉全的情况。 - 仿真启动后飞机不动:看看终端有没有报
EKF check fail。通常是传感器噪声设太大,或者GPS信号没模拟好。先关掉所有噪声,确认基础仿真能跑,再一点点加回去。 - 自定义机型不生效:确认你修改的是
AP_MotorsMatrix.cpp而不是AP_MotorsMatrix.h。别问我怎么知道的...