ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

无人机开发必备:SITL+MAVProxy+QGC模拟飞行环境搭建指南

无人机开发必备:SITL+MAVProxy+QGC模拟飞行环境搭建指南 搞无人机开发这些年我最大的教训就是千万别在没验证逻辑的情况下直接上真机。一次炸机轻则损失几千块重则把周围人都搭进去。所以现在我的工作习惯很固定——任何新的飞行任务、航点脚本、应急返航策略先在一套纯软件模拟环境里反复跑几十遍确认没问题再谈实飞。今天要聊的这套组合就是我用了很久、也踩过不少坑之后沉淀下来的模拟飞行方案DRONEKIT-SITL 负责在电脑上假装是一台完整的飞控MAVProxy 作为命令行链路调试工具QGroundControl 提供可视化地面站面板。三者配合能在一台普通电脑上完整走完起飞、巡航、航点任务、异常返航这一整套飞行流程。这套环境能帮你解决什么问题一句话概括不花钱、不冒险、不占场地就能把飞控上要跑的逻辑先彻底跑熟。它特别适合三类人正在学 MAVLink 协议和 ArduPilot 架构的入门玩家、需要为测绘或巡检任务编写自动飞行脚本的开发者、以及想测试地面站航线和参数调优功能的工程人员。下面我就把这套环境的搭建过程、链路原理、真实踩坑记录全部写下来跟着操作你也能在半小时内拥有一套属于自己的“空中模拟场”。1. 模拟飞行环境搭建前先看懂这条数据链路很多人一上来就急着装软件结果 SITL 起来了、QGC 也装了但就是连不上最后卡在“为什么没反应”上。根源在于没搞清楚这三个组件到底怎么协同工作。我先花点篇幅把架构讲透后面你排查问题会省很多力气。1.1 不飞真机为什么还要这么认真地搭环境先聊聊 SITL 到底是什么。SITL 全称 Software In The Loop软件在环仿真。它不是一个普通的三维飞行游戏也不是简单的“模拟器”而是把 ArduPilot 或 PX4 这类真实飞控固件编译成能在普通操作系统里直接运行的二进制程序。你通过 MAVLink 协议跟它通信时它输出的心跳包、姿态数据、GPS 坐标、电机转速全部是真实飞控代码处理出来的结果——只是传感器数据被虚拟模型代替了。这意味着什么你在真实飞机上跑的同一个 ArduCopter 固件在电脑上跑的是同一条代码路径。你今天在 SITL 里验证过的模式切换、RC 覆盖、地理围栏逻辑上真机后行为基本一致。差别只在于真实世界有风、有磁场干扰、有 GPS 漂移而 SITL 里这些都可以建模和注入。所以用 SITL 做逻辑验证是可靠的它是从“代码写完”到“真机起飞”之间最重要的一道关卡。那 MAVProxy 和 QGroundControl 又是什么角色MAVProxy 是一个基于命令行的 MAVLink 地面站轻量、灵活适合调试协议和链路。QGroundControl习惯叫 QGC是更完善的可视化地面站负责航线规划、参数调参、仪表显示。它们不参与仿真计算只负责跟 SITL 通信、监控和控制。简单说SITL 是“被仿真的飞机”MAVProxy 和 QGC 是“地面端”。这两者可以同时存在、同时连接也可以只选其一。实际使用时我通常让 MAVProxy 常驻因为它诊断链路和注入故障指令非常方便。1.2 三个组件如何串成一条完整的仿真链路搞懂数据流是这套环境最核心的部分。ArduPilot SITL 启动后默认会在本机打开两个通信入口一个是 TCP 端口 5760专门给 MAVProxy 或 DroneKit 这类需要主动发起连接的客户端使用另一个是 UDP 端口 14550用于向地面站广播遥测数据。MAVProxy 连接 SITL 之后又可以作为一个“数据转卖商”把自己收到的 MAVLink 数据包再转发给其他端口这样 QGC 就能通过 MAVProxy 间接拿到数据。我常用的链路是这样的SITL 监听tcp:127.0.0.1:5760MAVProxy 用--master tcp:127.0.0.1:5760连接 SITLMAVProxy 通过--out 127.0.0.1:14550将数据转发到 UDP 14550QGC 新建一个 UDP 连接监听127.0.0.1:14550就能看到飞机了还有一种更粗暴的方式SITL 启动时直接加--out 127.0.0.1:14551QGC 监听 14551绕开 MAVProxy。这种方式适合只测地面站功能、不需要命令行干预的场景。但我个人建议不要省掉 MAVProxy因为它在排查“心跳断了”“数据没转发”“消息类型不对”这些问题时简直是神器。后面我在故障排查部分会详细举例子。端口和数据流心里有数之后安装和启动就变成了一件顺理成章的事。2. 环境部署从零跑通 SITL MAVProxy QGC搭建这套环境依赖的工具并不多Python 3、pip、DroneKit-SITL、MAVProxy以及一个 QGroundControl 桌面端。整个过程我按“安装依赖 → 启动 SITL → 连接 MAVProxy → 检查健康状态”四步来走。2.1 依赖安装与版本选择先说大前提强烈建议在 Linux 环境下跑这套东西尤其是 SITL。Windows 虽然也能跑但经常会遇到路径含中文、防火墙拦截、超时连接这类莫名其妙的怪问题。如果手头只有 Windows 电脑优先开启 WSLWindows Subsystem for Linux在 Ubuntu 环境里操作。我这边的操作全部基于 Ubuntu 22.04。Python 环境推荐用虚拟环境避免把系统搞乱。命令如下sudo apt update sudo apt install -y python3 python3-pip python3-venv mkdir ~/drone-sim cd ~/drone-sim python3 -m venv venv source venv/bin/activate接着安装核心工具pip install dronekit dronekit-sitl mavproxy pymavlink这里有个版本选择的关键点dronekit-sitl会自动下载并缓存对应版本的 ArduPilot 固件默认机型是 ArduCopter。下载完成后它会提示你 SITL 二进制放在哪个目录。如果你之前装过旧版建议先pip uninstall dronekit-sitl再重装否则可能启动旧固件。MAVProxy 本身依赖 pymavlink在某些新架构机器上可能出现编译失败。如果遇到这种情况先装好编译工具链再重试sudo apt install -y build-essential python3-dev libxml2-dev libxslt1-devQGroundControl 的安装就简单多了去官方仓库下载对应系统的 AppImage 或安装包。Linux 下给 AppImage 加上执行权限即可chmod x QGroundControl.AppImage ./QGroundControl.AppImage2.2 启动 SITL 模拟器与 home 点设置依赖装好后第一步就是启动 SITL。我喜欢在启动时指定好 home 点坐标因为 SITL 默认的 home 点固定在一个海外坐标如果你的任务脚本里写死了相对位置默认坐标会导致数据看起来很奇怪。我常用的启动命令是dronekit-sitl copter-3.3 --home31.2304,121.4737,10,0 --out127.0.0.1:14550拆开解释一下copter-3.3指定 ArduPilot 机型与版本。copter 表示多旋翼3.3 是 ArduPilot 的经典稳定版本也可以换成plane-3.3模拟固定翼或rover-3.3模拟小车。--home后跟四个参数依次是纬度、经度、海拔高度、朝向角。我这里是上海某地的坐标海拔 10 米朝向 0 度。设置成你本地的位置写任务脚本时更直观。--out额外输出一个 UDP 遥测端口。SITL 默认已经有 5760 和 14550 了这里再加一个 14551留给 QGC 备用。启动成功后终端会滚动打印模拟飞控的启动日志包括传感器校准、GPS 锁定、EKF 初始化等。等到日志稳定出现EKF2 IMU0 is using GPS之类的内容说明飞控已经进入待命状态。此时再开一个终端窗口进入虚拟环境准备连接 MAVProxy。2.3 MAVProxy 连接与链路健康检查MAVProxy 连接 SITL最核心的命令就这一条mavproxy.py --mastertcp:127.0.0.1:5760 --out127.0.0.1:14550--master指定数据源--out指定转发目标。如果你想同时把数据转发给 QGC 和另一个调试脚本可以再加一个--out。MAVProxy 启动后下方会有一个STABILIZE之类的命令行提示符。此时在里面输入status你会看到类似这样的输出APM: ArduCopter V3.3 GPS: GPS OK, fix 3 Vcc: 4.97 Rel: 0.00字段含义可以直接看字面GPS 锁定状态、供电电压、相对高度。如果GPS显示fix 3而没有报错说明 SITL 和 MAVProxy 之间的链路已经通了。再用module list查看当前加载的模块help查看可用命令。我习惯在 MAVProxy 里先执行几个基础命令验证控制能力STABILIZE mode GUIDED STABILIZE arm throttle STABILIZE takeoff 10如果一切正常飞控会从 STABILIZE 切到 GUIDED电机解锁并自动起飞到 10 米高度。我用这种方式确认 MAVProxy 已经拥有完整的“地面站权限”。注意arm throttle后会看到Throttle armed的提示直接起飞之前建议先取消STABILIZE mode LAND等飞机落地后再进行下一步。这一步走通就说明整个命令行链路已经 OK剩下的就是让 QGC 进来看可视化界面了。3. 让 QGroundControl 接管模拟飞行的可视化监控命令行能干活但对大多数人来说千里之外看不见飞机心里还是不踏实。QGC 的价值就是把整个仿真环境变成一个可视化的操控台你能看到飞机在地图上的位置、姿态仪、空速地速、电池电压还能在地图上画航线、传任务、切换飞行模式。下面讲 QGC 的连接、界面验证和航线规划。3.1 添加连接UDP 还是 TCPQGC 连接 SITL 有两条路直接连 SITL 的 UDP 14550或者连 MAVProxy 转发出来的端口。两种方式我都在用场景不同而已。如果你只开了 SITL没有启动 MAVProxy可以在 QGC 右上角点开“应用设置”进入“通信连接”添加一个连接类型UDP监听端口14550保存并连接后QGC 应该能在几秒内识别到 SITL 飞控顶部状态灯变绿并显示 ArduCopter V3.3 的固件版本。如果你和我一样常驻 MAVProxy则更简单。MAVProxy 已经通过--out127.0.0.1:14550把数据转发出来了QGC 同样监听 14550 就行。这里有个容易踩的坑如果 MAVProxy 和 QGC 都在同一台电脑上QGC 用 UDP 监听MAVProxy 也是 UDP 转发一般来说没问题但 Windows 防火墙会把 UDP 广播拦截导致 QGC 端怎么都收不到心跳。解决方法是给防火墙放行那几个 UDP 端口或者干脆在 MAVProxy 里转发到一个 TCP 端口QGC 用 TCP 客户端方式连接。我一般测试时直接放行 UDP固定开发环境后就改成 TCP稳定很多。3.2 在 QGC 里验证传感器数据与姿态同步连接成功后先不要急着规划航线。观察一下界面右侧的仪表盘高度SITL 默认会模拟气压计起飞前应该显示 0 米或接近于 0。GPS 坐标应该对应你通过--home设置的坐标点地图上的飞机图标稳稳停在那里。姿态角roll、pitch、yaw 在静止状态下应该全部归零或接近零。电池电量SITL 默认模拟一个满电电池电压 12V 以上不会变化。这些看起来不起眼的数据其实是检验链路是否完整最直接的指标。有一次我在新电脑上搭环境QGC 看到飞机却怎么都不动高度一直是 0后来一查是 SITL 的 EKF 没有收敛日志里提示磁力计异常重启 SITL 重新校准就好了。验证数据正常后我通常会在 MAVProxy 里发送一条控制指令看看 QGC 仪表是否实时变化STABILIZE mode GUIDED STABILIZE arm throttle STABILIZE takeoff 5QGC 的仪表盘上高度开始上升姿态也随着模拟电机的动力输出发生变化。到这一步可视化链路就算完全打通了。3.3 任务规划与自动飞行验证QGC 最大的价值之一就是航点任务规划。在 SITL 模拟环境里规划航线跟在真机里操作流程一模一样。点击左侧工具栏的“飞行计划”在地图上飞机现在的位置附近点几个航点设置每个航点的高度比如 30 米保存并上传任务。此时注意看 MAVProxy 终端的输出会滚动显示Got MAVLink msg: MISSION_COUNT、MISSION_ITEM_INT之类的内容说明任务已经通过 MAVLink 协议上传到了 SITL 飞控。上传完成后切到 QGC 的“飞行界面”在模式选择里选择“自动”AUTO飞机就会依次飞向每个航点。地图上会实时绘制出飞机的飞行轨迹你能看到它起飞、转弯、平飞、降落的全过程。这个过程中 QGC 就相当于一个实时的空管雷达SITL 则相当于完整执行飞控逻辑的“虚拟真机”。这里我特别建议新手在模拟环境里多试几次航线规划因为很多真实飞行的操作习惯——比如起飞前检查 home 点、确认任务上传完整、保证航点高度合理——就是在这种反复演练里培养出来的。4. 实战完整跑一遍模拟自主航线与应急返回环境通了功能也看过了接下来的实战部分是整套方法最有价值的地方。我会用一个真实场景来描述编写一个 DroneKit 飞行脚本自动起飞、按航点飞行、最后返回起飞点并降落然后再人为注入 GPS 故障验证应急返航逻辑。4.1 起飞前检查清单虽然只是模拟环境但我还是习惯走一遍检查流程目的是养成肌肉记忆真机上才不会慌。我通常在启动任何飞行任务之前在 MAVProxy 里执行这些检查STABILIZE status STABILIZE gps STABILIZE battery STABILIZE ekfstatus确认飞控版本和心跳正常。gps确认 GPS fix 正常星数模拟值通常为 10 以上HDOP 小于 1。battery确认电压、电流检查无异常。ekf确认姿态估计没有出现严重漂移。同时确认 QGC 地图上的 home 点位置正确。这个 home 点很重要因为自动返航RTL的降落点就是它如果设错了应急返航就会落错地方。4.2 编写并执行 DroneKit 自动飞行脚本DroneKit 是 MAVLink 的 Python SDK可以让你用几行代码控制一整个飞行流程。下面是我用来测试 SITL 环境的一套最小脚本from dronekit import connect, VehicleMode import time connection_string tcp:127.0.0.1:5760 print(Connecting to vehicle on %s % connection_string) vehicle connect(connection_string, wait_readyTrue) print(Global Location: %s % vehicle.location.global_frame) # 设置 GUIDED 模式并解锁 vehicle.mode VehicleMode(GUIDED) vehicle.armed True while not vehicle.armed: print(Waiting for arming...) time.sleep(1) print(Armed!) # 起飞到 20 米 vehicle.simple_takeoff(20) while True: alt vehicle.location.global_relative_frame.alt print(Altitude: %.1f % alt) if alt 20 * 0.95: print(Reached target altitude) break time.sleep(1) # 向前飞行 10 秒 vehicle.airframe None # 占位保持脚本结构完整 vehicle.simple_goto(vehicle.location.global_frame, groundspeed5) time.sleep(10) # 返航并降落 print(Returning to launch) vehicle.mode VehicleMode(RTL) while True: if vehicle.location.global_relative_frame.alt 1: print(Landed) break time.sleep(1) vehicle.close() print(Test completed)注意simple_goto的参数是一个LocationGlobalRelative对象我这里为了保持示例简短只用了当前点让飞机悬停实际任务中可以构造一个偏移航点比如from dronekit import LocationGlobalRelative point LocationGlobalRelative(lat, lon, 30)跑这个脚本之前确认你已经启动了 SITL 和 MAVProxy。然后执行python test_flight.py你会看到脚本逐行打印坐标和高度同时 MAVProxy 和 QGC 同步显示飞机状态。如果脚本运行中出现Command Failed或超时多半是 SITL 还在初始化 EKF等几秒再重试即可。4.3 注入故障GPS 丢失与应急返航验证模拟环境里最能锻炼人的地方就是可以肆无忌惮地制造故障。我常用 MAVProxy 来禁掉 GPS看看飞控和脚本会怎么反应。过程是这样的飞机先正常起飞到 20 米悬停稳定后我在 MAVProxy 里执行STABILIZE param set GPS_TYPE 0 STABILIZE rebootGPS_TYPE 0表示禁用 GPS 模块重启飞控后相当于模拟器完全没了 GPS 信号。这个时候观察 QGC 上的现象GPS 图标变灰位置不再更新速度读数变为 0。此时如果依赖 GPS 的自动模式比如 AUTO、RTL还在运行飞控通常会给出警告或切换到自稳具体行为取决于参数配置。那怎么应急处理我在实际测试中通常会先在脚本里监听 GPS 丢失事件然后让飞机直接切换回 GUIDED 模式并执行原地降落def gps_callback(self, attr_name, value): if vehicle.gps_0.fix_type 2: print(GPS lost!) vehicle.mode VehicleMode(GUIDED) vehicle.mode VehicleMode(LAND) vehicle.add_attribute_listener(gps_0, gps_callback)这样一套流程跑下来你就会深刻理解 GPS 在飞控里有多重要以及“失去定位后立刻原地降落”为什么是多数场景下最安全的兜底策略。这套验证在真机上代价极高但在 SITL 里也就几十秒的事。5. 常见故障排查连接失败、数据异常、兼容性的处理办法最后这块内容我整理了自己在这套组合上踩过的大多数坑。按问题类型分了三类每一类都直接给处理方法遇到问题时可以当成速查表用。5.1 连接失败类问题QGC 一直显示“等待心跳”。优先检查 SITL 是否启动成功日志是否有异常再检查 MAVProxy 的status是否正常。如果 MAVProxy 正常但 QGC 还是看不到就检查 UDP 端口。在 Linux 下可以用ss -ulpn | grep 14550确认 14550 端口有没有进程在监听。如果什么都没有多半是 MAVProxy 的--out参数没生效重启 MAVProxy 时加上--out127.0.0.1:14550即可。DroneKit 脚本 connect 直接卡死。大概率是 SITL 还没就绪。DroneKit 的wait_readyTrue会等待 MAVLink 心跳和关键消息如果 SITL 的 EKF 还没收敛就会一直等下去。解决方法是稍等几秒再跑脚本或者在connect()前加一个sleep(5)。Windows 下 UPD 连接不稳定。这个我前面提到过多办是防火墙拦截。除了放行端口更稳妥的方式是让 MAVProxy 额外输出一个 TCP 端口STABILIZE output add 127.0.0.1:14560然后在 QGC 里添加 TCP 连接地址127.0.0.1、端口14560立刻稳定。5.2 数据异常类问题高度一直跳、GPS 坐标乱飞。通常是因为 SITL 的传感器模型没有正确初始化。请确认启动 SITL 时没有--no-rc之类的限制参数并且等待日志出现EKF2 IMU0 is using GPS之后再开始飞。起飞后姿态乱摆甚至自翻。先检查电机方向是否一致。在 SITL 里没有物理电机方向问题多半来自 SITL 的参数配置。可以重置参数STABILIZE param set ARMING_CHECK 0 STABILIZE reboot这只是模拟环境下的排查手段真机千万别这样做。位置数据静止但高度在变。这个是 GPS 和气压计数据不一致导致的。做一次完整的传感器校准STABILIZE module load compass STABILIZE compass cal5.3 版本兼容与性能问题DroneKit 脚本提示某些属性不存在。不同 ArduPilot 版本号的 MavLink 消息类型略有差异。SITL 的copter-3.3和 DroneKit 的新版 SDK 配合时有时候vehicle.ekf_ok这类属性会不兼容。优先把 dronekit 和 pymavlink 升级到最新或者固定使用官方示例里兼容的版本组合。电脑跑 SITL 很卡QGC 操作有延迟。SITL 和 QGC 同机运行对 CPU 有一定压力。推荐在启动 QGC 前先调低操作系统性能模式并且在 SITL 启动时限制仿真频率dronekit-sitl copter-3.3 --speedup5--speedup表示仿真速度倍数默认是 1 倍速改成 5 倍后任务执行速度会加快但 QGC 显示会感觉比较“快进”。调试逻辑时用 1 倍跑长航线验证用 5 倍效率高很多。多次启动 SITL 后端口被占用。这个我会直接杀掉残留进程再重启lsof -i :5760 kill -9 PID如果是在 Windows 上换成netstat -ano | findstr 5760然后taskkill /F /PID。我个人在实际操作中的体会是这套模拟环境最大的价值不是让你“学会用 QGC”而是让你在零成本、零风险的前提下把飞行逻辑、应急策略、通信机制全部验证一遍。你可以在一个下午内反复飞一百次、拉掉十次 GPS、切换二十次模式这在真机上几乎是不可想象的。搭建这个环境装的软件不多真正的门槛在于理解 MAVLink 数据流和飞控的行为逻辑——而一旦你把 SITL MAVProxy QGC 这条链路吃透再上手真机心里会踏实很多。最后再分享一个小技巧把常用的 SITL 启动命令和 MAVProxy 连接命令写成一个 shell 脚本一键启动整套环境省去每次敲命令的时间。我自己的脚本里还会加一个gnome-terminal同时拉起 QGC真正做到了“一条命令模拟飞行”。这套流程用熟了之后你会发现写无人机代码的迭代速度能比之前快出一个量级。
返回列表