简介:面向无人机开发者与二次开发人员的QGC学习资料合集,系统覆盖地面站基础操作、软件框架、MAVLink通信协议、界面汉化与自定义、简洁Qt地面站开发、多机优化等内容,适合从入门到进阶的QGroundControl学习者。资源共38个文件,以7个PDF手册、25张PNG截图和3个HTML文档为主,另附2个ZIP示例工程和1个RAR包,整体约688.2MB,便于按章节查阅和对照练习。已有4079人参与学习,多数内容来自阿木实验室的开发手册及作者整理的实战笔记,包含任务规划、地图GIS、视频流处理、插件机制、调试测试等二次开发要点。通过这套资料,读者可以理解QGC的源码结构和扩展方式,快速完成环境搭建、功能定制与排错,是一份兼顾理论与实操的无人机地面站开发参考。 最近整理硬盘,翻出了一个早年间自己归档的压缩包,名字就叫QGC学习资料.rar。里面攒的东西很杂:有截了一半的官方文档,有当时从各种论坛扒下来的人肉排错笔记,还有几个改到一半的 QML 界面源文件。重新翻看这些内容,发现虽然网上关于 QGroundControl 的教程已经比前两年多了不少,但大部分资料要么只讲了“怎么安装”,要么直接甩给你一个“编译脚本”让你自己跑,中间那段最折磨人的“这玩意儿到底是怎么把飞机控制起来的”反而没人讲清楚。
QGC(QGroundControl)是 PX4 和 ArduPilot 两大飞控体系里最常用的跨平台地面站。它不只是个“遥控器替代品”,而是集飞行监控、任务规划、参数调参、日志分析于一体的综合地面站软件。更关键的是,它基于 Qt/QML 开发,源码完全开源,这也让它成了很多人做无人机地面站二次开发的首选起点。但恰恰因为它是个“成熟大项目”,新手上手时面对巨大的代码仓库、复杂的外部依赖、一大堆专有名词,很容易被劝退。
这篇博文不打算重复“下一步下一步”的安装教程,而是想以一个摸过 QGC 代码、做过后端定制的人的视角,聊聊学习 QGC 时真正需要抓住的主线、Ubuntu 22.04 下编译和实验环境的那些坑,以及二次开发从哪几个地方切入最划算。如果你手里也有一份类似的“QGC 学习资料”,希望这份拆解能帮你把它变成能真正跑起来的技能。
1. 先摸清 QGC 的底细:它是地面站,更是一套完整框架
1.1 不是所有地面站都叫 QGC
在接触 QGC 之前,我一度以为地面站就是“一个能显示地图、能看姿态、能发指令的窗口程序”,直到认真读完源码才发现,这种理解太肤浅了。QGC 是一个标准的三层架构软件,它的复杂度在于,这三层每层单独拿出来都能形成一门技术方向:
- 界面层:全部基于 QML(Qt Modeling Language)编写,负责地图显示、仪表盘、按钮交互、飞行数据可视化。这部分是大家最容易看到、也最容易动手修改的,只改前端的话,甚至不需要懂 C++ 太多。
- 逻辑层:C++ 写成的核心逻辑,包括飞行状态机、航点任务管理、参数缓存、串口/网络连接管理、日志记录、崩溃报告等。二次开发中真正影响飞行行为的部分都在这一层。
- 通信层:基于 MAVLink 协议(Micro Air Vehicle Link),负责地面站与飞控之间的消息收发。MAVLink 是个序列化协议,每条消息都有固定的 message ID 和字段定义。QGC 通过 MAVLink 来订阅飞控数据、发送控制指令。
这意味着,如果你只是想“给 QGC 加个按钮”或“换个主题色”,用 QML 就够了;但如果你想“增加一种飞控不支持的新指令”,就必须动到协议层和 C++ 层。
1.2 学习 QGC 之前你要有的底子
很多初学者直接冲进 QGC 代码库,然后两天后放弃,问题往往出在“底子”上。抛开飞行原理不谈,单纯从软件工程角度看,你需要具备:
- Qt 基础知识:至少要理解 signal/slot 机制、QObject 生命周期管理、QML 与 C++ 的上下文交互方式。QGC 是大型 Qt 项目,不熟悉这套机制,连代码都找不到入口。
- C++ 基本阅读能力:不用你写多复杂的 C++,但至少要能看懂类继承关系、函数指针、Lambda 表达式和 Qt 的元对象系统。QGC 里各种
qobject_cast、qmlRegisterType会频繁出现。 - MAVLink 基础概念:哪怕只知道消息头里包含的 seq、sysid、compid 字段作用,理解代码时也能省很多力气。
我一直建议想学 QGC 的朋友:先别急着下源码,先花三天把 Qt 的官方入门文档和 QML 语法过一遍。这不是在绕远路,而是在给之后排查编译错误和运行事故省时间。
2. Ubuntu 22.04 环境搭建:源码编译不是玄学,但依赖是真坑
2.1 二进制安装和源码编译怎么选
QGC 官方为 Linux 提供了编译好的二进制包,下载下来直接就能跑,对于“只要用地面站、不打算改代码”的用户,这是最优解。但学习资料这个场景下,我的建议始终是:必须走一遍源码编译。
原因很简单:只有自己从源码构建过一次,你才会真正意识到底层依赖有哪些,才知道改了 QML 文件后需要重新编译那几个模块,才能在未来做二次开发时,不把时间浪费在“为什么我改了代码看不到效果”这种基础问题上。而且 QGC 的源码编译本身就是一个难得的 Qt 工程实战样本。
2.2 编译 QGC 必须处理的依赖坑
如果你用的是 Ubuntu 22.04,编译 QGC 时会遇到一个典型的“版本地狱”问题:QGC 官方对 Qt 版本有明确要求,而系统自带的 Qt 版本、Qt 官方安装包的版本、以及 QGC 编译脚本期望的版本,三者经常对不上。
我自己在 Ubuntu 22.04 上编译 QGC 4.2.x 版本时,踩过的坑按“造成损失”排序如下:
- Qt 版本不对导致 qmake 报错。QGC 4.2 系列要求 Qt 5.15.2 及以上。Ubuntu 22.04 软件源默认提供的是 Qt 5.15.3,理论上满足要求,但如果你用 Ubuntu 20.04 的旧教程,装了 Qt 5.12,编译时会直接出现一堆跟 QML 模块相关的错误。
- 缺少 GStreamer 组件导致视频流无法编译。QGC 的飞机视频回传依赖 GStreamer,如果没有安装相关开发包,
qmake阶段不会报警,但运行后打开视频页面就会崩溃。这个 bug 排查起来极其隐蔽。 - 缺少 serialport 和 charts 模块。QGC 依赖 Qt 的串口模块和图表模块,Ubuntu 软件源里的 Qt 可能没带上对应 dev 包,编译到 90% 才报错。
我最推荐的依赖安装方式,是直接照着官方 wiki 在 Ubuntu 22.04 下用 apt 安装(下面是常用依赖集合),然后手动下载 Qt 5.15.2 离线安装包。注意:不要只装qtbase5-dev,要让 QGC 能编译通过,至少还需要位置模块、串口、SVG 等:
sudo apt update sudo apt install git qtbase5-dev qtdeclarative5-dev qtpositioning5-dev \ qtlocation5-dev libqt5serialport5-dev libqt5svg5-dev \ libqt5opengl5-dev libgstreamer1.0-dev \ libgstreamer-plugins-base1.0-dev libsdl2-dev \ libxkbcommon-x11-0 libxcb-xinerama0 libqt5quickcontrols2-5 \ libqt5quicktemplates2-5 libqt5quick5 libqt5charts5-dev \ qml-module-qtlocation qml-module-qtpositioning依赖安装完成后,编译步骤相对常规:
git clone --recursive https://github.com/mavlink/qgroundcontrol.git cd qgroundcontrol mkdir build && cd build qmake ../qgroundcontrol.pro make -j$(nproc)这里有一个我个人的经验提示:qmake命令一定要确认是 Qt 5 的 qmake,而不是 Apt 装的 Qt 4 残留。检查方式很简单:
qmake -v如果显示Qt version 4.x,说明你系统里还有旧版 qmake,需要手动指定 Qt 5 的 qmake 路径,或者export PATH=/opt/Qt/5.15.2/gcc_64/bin:$PATH。这个细节卡住过很多人。
3. 源码结构拆解:一份 QGC 学习资料应该抓的主线
3.1 界面层、逻辑层和通信层谁是谁
拿到 QGC 源码后,你首先会在根目录下看到一堆文件和文件夹,最让人头大的是它并不像很多教程里说的那样“按界面和逻辑严格分目录”,而是有一些历史上沉淀下来的杂糅。根据我反复阅读源码的经验,核心目录主线可以分成三条:
qgroundcontrol.qrc:这是 Qt 资源文件的入口,所有 QML 界面文件都通过它被编译进二进制。如果你想找“地图页面在哪”“设置页面在哪”,顺着这个.qrc文件就能找到对应.qml文件。src/下的 C++ 代码:其中src/Vehicle存放飞行器抽象类,src/Comm负责 MAVLink 连接管理,src/PlanView、src/FlyView、src/Setup这三级分别对应用户界面的任务规划页、飞行页面、设置页面。注意,这些目录里既有 QML 文件也有 C++ 文件,它们是混合编排的。src/MAVLink:这一块单独拿出来说,因为 MAVLink 的生成代码、协议版本、子模块更新,是二次开发时最容易被搞坏的部分。
很多初学者拿到源码后喜欢从main.cpp开始读,这不算错,但 QGC 的初始化逻辑非常长,涉及一堆单例模式和插件系统,直接读很容易迷失。我更推荐的路线是:先跑起来,然后从界面上“点哪里”对应到“源码里哪个文件”,再逐层往下钻。比如你打开 QGC 后左侧有四个主标签页,这对应 QML 里的MainRootWindow.qml和对应的四个页面组件。找到这个入口后,界面层的阅读就会顺风顺水。
3.2 MAVLink 通信这条命脉怎么读
MAVLink 地面站和飞控之间的消息,本质上就是“一堆结构化的字节流”。QGC 中与 MAVLink 相关的代码散落在几个位置:
src/MAVLink/QGCMAVLink.h:定义了协议版本、目标系统 ID 等参数。src/MAVLink/MAVLinkCommon.h:将生成的 MAVLink 头文件引入 C++ 工程。src/Comm/LinkManager.cc和src/Comm/SerialLink.cc:负责底层串口、TCP、UDP 连接的建立与数据收发。src/Vehicle里的Vehicle.cc:对收到 MAVLink 消息做具体业务处理,比如更新姿态、距离传感器数据、发送航点指令。
读 MAVLink 相关代码时,我强烈建议对着 Wireshark 抓包或者 QGC 自带的日志来看。你可以打开 QGC 的日志输出(通过命令行参数--logging开启),看看每收到一条HEARTBEAT消息后地面站做了什么、每发一条COMMAND_LONG之前信号从哪个函数触发。这种“消息流级”的阅读,比机械看代码有效得多。
4. 二次开发的四个常见切入点
4.1 改界面:QML 定制比你想的简单
QGC 的一大优点就是 QML 直接参与界面渲染,而且修改 QML 后不需要重写 C++,很多时候只需要重新编译甚至热加载预览就能看到效果。以我自己做过的定制为例,想给主页面加一个“自定义报警音”按钮,只需要在对应的 QML 文件里添加一个控件,再用信号连接到 C++ 侧一个已有方法或自定义方法。
最常用的修改入口是:
MainRootWindow.qml:主窗口,所有页面的容器。FlyView下的FlyView.qml:飞行界面,很多团队会在这里加自定义 HUD 元素。SetupView下的页面:地面站的参数配置、传感器校准界面,适合做机型定制。
有个细节需要提醒:QGC 的 QML 文件最终是编译进 Qt 资源文件里的,改完 QML 后,如果直接make,可能因为依赖关系没有触发重新编译而看不到效果。最稳妥的方式是删掉 build 目录下的qgroundcontrol.qrc相关中间产物,或者彻底make clean再编译。这个坑我至少遇到过三次。
4.2 加功能:从插件入手是正路
QGC 有一个插件机制(QGCPlugin/CustomPlugin),专门为了支持二次开发。官方设计这套机制,是希望开发者尽量不修改核心代码,而是通过插件扩展功能。举个例子:你的地面站需要对接一款自定义传感器,并且要在界面上实时显示它的读数,如果你直接改src/Vehicle里的核心逻辑,后续 QGC 升级时你就要手动解决每个版本的冲突;但如果写在插件里,升级时就从容得多。
不过需要说明的是,QGC 的插件机制文档不算完善,而且不同大版本之间接口变化较大。如果你用的是 4.2 版本,那么插件机制的入口在src/PluginManager,你可以从CustomPlugin.h这个抽象类开始看,然后注册到QGCApplication.cc里。
4.3 自定义通信协议与 MAVLink 扩展
这是二次开发里门槛最高、也最有价值的部分。如果你想在 QGC 和飞控之间增加一条自定义消息(比如传输一种新的传感器数据),要做的事大致分三步:
- 在 MAVLink 的消息 XML 定义文件中添加新消息,然后通过 MAVLink 的生成器重新生成 C++ 头文件。QGC 仓库里用的 MAVLink 子模块通常有预生成文件,直接改 XML 再重新生成也行。
- 在 C++ 端注册这条新消息,在收到该消息时做出处理逻辑。
- 如果需要 UI 展示,再在 QML 端绑定数据。
这个流程的坑在于:QGC 里的 MAVLink 头文件不是单一版本,有些消息可能在官方common.xml里没有定义,需要你手动确认你添加后生成的代码路径是否与 QGC 的 include 路径一致。我最初就吃过这个亏,生成了新头文件,但 include 的还是旧路径,导致编译时明明写了新消息却提示“符号未定义”。
4.4 编译发布与调试技巧
二次开发到了后期,会涉及到“调试”和“发布”两个问题。
调试阶段,我最常用的三个工具:
--logging启动参数:开启 QGC 的日志输出,能看到收发报文的详细过程,定位通信问题时有奇效。- Qt Creator 的 QML Debugger:如果你用 Qt Creator 打开 QGC 工程,可以在 QML 文件里下断点,查属性值、调样式,非常直观。
- MAVLink Inspector:QGC 的 Analyze 页面自带 MAVLink Inspector 工具,能实时查看所有收发消息的内容,二次开发时几乎离不开它。
发布阶段,Linux 下一般用linuxdeployqt工具打包;如果你只是在 Ubuntu 22.04 上自己跑,直接运行源码编译出来的build/qgroundcontrol二进制就行。但要注意,如果系统里缺少某些 Qt 库的运行时,会有“could not load plugin”之类的报错,这种情况下排查的方向不是重新编译,而是检查LD_LIBRARY_PATH和 Qt 插件的安装路径。
5. 我整理学习资料时的筛选思路和避坑心得
5.1 哪些资料值得进收藏夹
我那份QGC学习资料.rar最终整理成几个模块:源码编译记录、QML 界面修改笔记、MAVLink 协议速查、以及一个单独的“历史问题排查”文档。现在回过头看,真正有价值、值得推荐给后来者的资料,大概有以下几类:
- 官方 wiki 的 Developer Guide。虽然更新速度一般,但很多框架性、架构性的解释仍然是最权威的。
- Qt 官方文档中关于 QML 与 C++ 集成的部分。QGC 大量依赖 context property 和注册类型,不搞懂这块,读 QML 代码会很吃力。
- 真实的 issue 讨论。QGC 的 GitHub issue 区域有很多“低级但致命”的问题,比如某版本在 Ubuntu 下编译依赖缺失、某个串口驱动冲突,这些在官方教程里是找不到的。
我的筛选原则很简单:资料必须能解决“我从 A 到 B 过程中遇到的真实问题”,否则一律进回收站。不要因为标题里有 QGC 三个字母就存下来“以后再看”,“以后”基本就是“永远不看”。
5.2 最容易劝退新手的几个坑
结合我自己和带过的新人经验,以下这几个坑最容易劝退新手,提前打个预防针:
- 迷信“一键脚本”。网上有人分享编译 QGC 的自动化脚本,看起来很省事,但这类脚本大多绑定了作者自己的环境路径,换个机器跑就直接翻车。不如老老实实手动跑三条命令,出了问题还能定位。
- 改代码后不重编直接跑旧二进制。这听起来很蠢,但很多人都犯过。改了 C++ 逻辑后没重新 make,运行半天后灵魂发问“为什么我没看到效果”。
- 拿 QGC 直接当产品用,而不考虑许可证问题。QGC 本身是开源项目,但如果你基于它做商业产品,必须留意其开源许可证对产品形态的限制。学习研究无所谓,商用前一定要理清合规边界。
6. 最后分享一个我自己的学习方法
QGC 这种大型开源项目,最忌讳的就是“从头到尾按顺序读”。我自己的经验是“倒着学”:先确定一个你想实现的小需求,比如“在地图上显示飞机的云台朝向”,然后顺着这个需求,沿着 QML 控件 → 信号绑定 → C++ 方法 → MAVLink 消息 这样一条链路逆向去读代码。以问题带代码,效率远高于漫无目的地翻源码。
学习资料本身只是地图,真正让你从“看得懂”变“改得动”的,一定是动手编译、动手改、动手踩坑的过程。只要把上面这些主线抓住,再啃下 Qt 和 MAVLink 这两块硬骨头,你手里那份QGC学习资料.rar就能变成真正属于你自己的二次开发能力。希望这些经验能帮你少走一点弯路。
本文还有配套的精品资源,点击获取