- 无人机
- 智能硬件
【免费下载链接】qgroundcontrol
Cross-platform ground control station for drones (Android, iOS, Mac OS, Linux, Windows)
本篇技术指南围绕 QGroundControl 自定义构建(Custom Build)的核心插件机制展开:通过继承FirmwarePlugin、AutoPilotPlugin与QGCCorePlugin三大类,在不改动上游代码的前提下,为定制版本定制固件行为、车辆设置页面与应用级界面。读完本文,你将掌握三大插件的职责边界、核心可覆写接口、CMake 注册流程,并能基于仓库中的custom-example示例落地一套自己的 QGC 定制构建。
一、自定义构建背后的插件架构
QGroundControl 的定制能力并非通过“改源码”实现,而是建立在三套成熟的插件体系之上(见 docs/zh/qgc-dev-guide/custom_build/custom_build.md):
| 插件类 | 控制范围 | 典型用途 |
|---|---|---|
QGCCorePlugin | 与“车辆无关”、与应用本身相关的部分 | 应用程序设置、调色板、品牌标识、QML 引擎、复杂任务项、计划创建器 |
FirmwarePlugin | 与具体固件(PX4 / ArduPilot)行为相关的部分 | 飞行模式、工具条指示器、云台能力、固件工厂 |
AutoPilotPlugin | 车辆设置(Vehicle Setup)页面集合 | 隐藏/调整设置页,简化 DIY 相关 UI |
创建定制版本的做法就是:为这三个标准插件创建子类,覆写适合自己使用场景的方法集合(见 custom_build.md)。上游 QGC 同时面向“从零自组装的 DIY 用户”和“使用成品无人机的商业用户”,因此界面承载了大量 DIY 专属功能;自定义构建可以把车辆信息预先固化(例如“固定使用 PX4 Pro + 多旋翼”),从而隐藏无关内容,为终端用户提供比通用版更简洁的体验。
除插件外,QGC 还提供资源覆盖(Resource Override)机制,用于替换较小的视觉元素,详见 resource_override.md。
二、QGCCorePlugin:应用级定制的入口
QGCCorePlugin 是“非固件相关”的通用扩展点。其官方头文件注释明确说明(见 src/API/QGCCorePlugin.h):覆写其虚方法即可新增或替换 UI 页面、飞行地图项、工具条指示器、视频管线组件、计划文件钩子等应用级行为;基类提供标准 QGC 实现,自定义构建通过子类在QGCApplication启动前完成注册。
该插件主要覆盖以下几类定制能力,与关联文档所述的“应用程序设置、调色板、品牌标识”一一对应:
1. 应用程序设置:调整与隐藏
adjustSettingMetaData()允许在设置项创建之前修改其元数据,并控制其是否对用户可见(见 src/API/QGCCorePlugin.h):
// 参数说明: // settingsGroup - QSettings 分组名 // metaData - 该设置项的元数据(可修改默认值等) // userVisible - true 表示在 UI 中显示;false 表示隐藏(使用默认值生效) virtual void adjustSettingMetaData(const QString &settingsGroup, FactMetaData &metaData, bool &userVisible);示例中的做法是:当设置组为AppSettings::settingsGroup时,把“离线编辑固件类”固定为 PX4、把“离线编辑车辆类”固定为多旋翼,并隐藏这两个选项(见 custom-example/src/CustomPlugin.cc):
if (metaData.name() == AppSettings::offlineEditingFirmwareClassName) { metaData.setRawDefaultValue(QGCMAVLink::FirmwareClassPX4); userVisible = false; return; } else if (metaData.name() == AppSettings::offlineEditingVehicleClassName) { metaData.setRawDefaultValue(QGCMAVLink::VehicleClassMultiRotor); userVisible = false; return; }这样即使用户在未连接飞机时创建计划,也会默认按 PX4 + 多旋翼来生成,符合“预先固化机型信息”的定制思路。
2. 调色板:品牌配色覆盖
paletteOverride()允许按颜色名称覆写QGCPalette中的任意颜色,并区分Dark/Light 主题与Enabled/Disabled 状态(见 src/API/QGCCorePlugin.h):
virtual void paletteOverride(const QString &colorName, QGCPalette::PaletteColorInfo_t &colorInfo);custom-example中覆盖了window、windowShade、text、button、buttonHighlight、primaryButton、mapButton、alertBackground、brandPrimary、brandAccent等二十余个颜色槽位,例如(见 custom-example/src/CustomPlugin.cc):
} else if (colorName == QStringLiteral("brandPrimary")) { colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupEnabled] = QColor("#4a2c6d"); colorInfo[QGCPalette::Dark][QGCPalette::ColorGroupDisabled] = QColor("#4a2c6d"); colorInfo[QGCPalette::Light][QGCPalette::ColorGroupEnabled] = QColor("#4a2c6d"); colorInfo[QGCPalette::Light][QGCPalette::ColorGroupDisabled] = QColor("#4a2c6d"); }从源码结构可以看出(见 custom-example/src/CustomPlugin.h),调色板与品牌设置均通过覆写 QGCCorePlugin 的虚方法完成,无需触碰上游 UI 代码。
3. 品牌标识与 QML 引擎接入
createQmlApplicationEngine():允许插件访问QQmlApplicationEngine,以便注册自定义 QML 模块、添加导入路径或注入上下文对象(见 src/API/QGCCorePlugin.h)。destroyQmlApplicationEngine():与前者对称,负责在引擎销毁前释放插件附加的每引擎状态(如 URL 拦截器),见 src/API/QGCCorePlugin.h。
示例中的实现(见 custom-example/src/CustomPlugin.cc)先调用基类创建引擎,再添加qrc:/qml/Custom/Widgets与qrc:/qml/Custom/Plan两个导入路径,并挂载一个CustomOverrideInterceptor——它会把qrc:/...路径映射到:/Custom...资源,实现“同名 QML 文件覆盖”,这正是品牌化与界面替换的技术基础。
4. 扩展计划系统:复杂任务项与计划创建器
QGCCorePlugin 还提供了扩展“计划(Plan)”体系的能力:
complexMissionItemNames():返回计划 UI 中显示的复杂任务项列表,每个条目是包含canonicalName(内部键)与translatedName(显示名)的 QVariantMap(见 src/API/QGCCorePlugin.h)。createComplexMissionItem():当任务项类型不在内置集合(Survey、CorridorScan、StructureScan、FixedWingLanding、VTOLLanding)中时被调用,是自定义任务项的工厂(见 src/API/QGCCorePlugin.h)。planCreators():返回“新建计划”对话框中可用的计划创建器(见 src/API/QGCCorePlugin.h)。
示例为其自定义的 “Perimeter Scan” 任务实现了全套链路:先在complexMissionItemNames()中把PerimeterScanComplexItem::canonicalName追加到标准列表末尾,再在createComplexMissionItem()中识别该类型并实例化,最后在planCreators()中追加PerimeterScanPlanCreator(见 custom-example/src/CustomPlugin.cc)。
5. 其他常用覆写点
从 src/API/QGCCorePlugin.h 还可以看到大量应用级钩子:
registerCustomSettings():在SettingsManager::init结束时注册自定义设置组,使生成的设置页可以通过QGroundControl.settingsManager.<accessor>引用(第 L89-L92 行);showAdvancedUIMessage():进入高级模式时的确认提示文案(第 L94-L95 行);stableVersionCheckFileUrl()/stableDownloadUrl():定制版本的版本检查与下载地址。默认主线实现会检查官方稳定版文件,而QGC_CUSTOM_BUILD编译下的默认实现返回空字符串表示不检查,定制版可覆写为自有服务器(第 L152-L166 行);mavlinkMessage():让插件看到通往车辆的全部 MAVLink 流量,返回 false 可阻止车辆处理该消息(第 L130-L132 行);preSaveToJson/postSaveToJson/preLoadFromJson/postLoadFromJson系列:在计划文件读写前后注入自定义 JSON 内容(第 L137-L150 行);customMapItems():向 FlightMap 添加自定义地图项(第 L134-L135 行);createVideoReceiver()/createVideoSink()/releaseVideoSink():替换视频接收与渲染管线(第 L123-L127 行)。
三、FirmwarePlugin:固件行为的定制
FirmwarePlugin 负责与特定固件强相关的行为,其配套工厂FirmwarePluginFactory决定定制版本支持哪些固件与机型。示例自定义工厂只声明支持 PX4 固件与多旋翼机型(见 custom-example/src/FirmwarePlugin/CustomFirmwarePluginFactory.cc):
QList<QGCMAVLink::FirmwareClass_t> CustomFirmwarePluginFactory::supportedFirmwareClasses() const { QList<QGCMAVLink::FirmwareClass_t> firmwareClasses; firmwareClasses.append(QGCMAVLink::FirmwareClassPX4); return firmwareClasses; } QList<QGCMAVLink::VehicleClass_t> CustomFirmwarePluginFactory::supportedVehicleClasses() const { QList<QGCMAVLink::VehicleClass_t> vehicleClasses; vehicleClasses.append(QGCMAVLink::VehicleClassMultiRotor); return vehicleClasses; }而firmwarePluginForAutopilot()只在检测到MAV_AUTOPILOT_PX4时返回自定义插件实例,其余固件返回空指针(见 custom-example/src/FirmwarePlugin/CustomFirmwarePluginFactory.cc)。
自定义的CustomFirmwarePlugin继承自PX4FirmwarePlugin,可覆写以下典型行为(见 custom-example/src/FirmwarePlugin/CustomFirmwarePlugin.h):
| 方法 | 作用 | 示例中的做法 |
|---|---|---|
autopilotPlugin() | 返回与该固件匹配的 AutoPilotPlugin 实例 | 返回CustomAutoPilotPlugin(见 custom-example/src/FirmwarePlugin/CustomFirmwarePlugin.cc) |
toolIndicators() | 控制工具条指示器列表 | 先取基类完整列表,再移除RCRSSIIndicator.qml,保证上游新增指示器不会丢失(第 L22-L33 行) |
hasGimbal() | 声明飞机是否携带云台及可转轴 | 返回 true,且 pitch/yaw 可转(第 L35-L42 行) |
updateAvailableFlightModes() | 限定用户可设置的飞行模式 | 仅允许 Hold(Loiter)、Return(RTL)、Mission 三种模式(第 L44-L57 行) |
其中飞行模式的限定逻辑如下(见 custom-example/src/FirmwarePlugin/CustomFirmwarePlugin.cc):
mode.canBeSet = (cMode == PX4CustomMode::AUTO_LOITER) || (cMode == PX4CustomMode::AUTO_RTL) || (cMode == PX4CustomMode::AUTO_MISSION);四、AutoPilotPlugin:车辆设置页面的定制
AutoPilotPlugin 控制 Vehicle Setup(车辆设置)中的页面集合。示例的CustomAutoPilotPlugin继承自PX4AutoPilotPlugin,覆写vehicleComponents()以隐藏绝大多数面向 DIY 的设置页——除非进入高级模式(见 custom-example/src/AutoPilotPlugin/CustomAutoPilotPlugin.h):
/// This allows us to hide most Vehicle Setup pages unless we are in Advanced Mode const QVariantList &vehicleComponents() final;该类的实现逻辑是:通过_advancedChanged()槽监听showAdvancedUI变化,当高级模式切换时重建页面列表(见 custom-example/src/AutoPilotPlugin/CustomAutoPilotPlugin.h)。这与关联文档“隐藏普通用户不应接触的内容”的目标完全一致——例如成品无人机的终端用户通常不需要 DIY 专用的设置页。
五、高级模式(Advanced Mode)与单固件支持
关联文档明确了两条与插件体系配套的机制:
1. 高级模式(Advanced Mode)
- 标准 QGC 构建始终运行在高级模式;自定义构建默认从“常规/非高级”模式启动;
- 自定义构建中可通过快速连续点击 Fly View 按钮 5 次开启高级模式,此时会弹出确认警告;
- 目的:把普通用户不应接触的内容(如 DIY 设置页)藏在高级模式之后。
示例中的做法是:CustomPlugin构造时把_showAdvancedUI置为false,并连接showAdvancedUIChanged信号(见 custom-example/src/CustomPlugin.cc);同时CustomOptions::showFirmwareUpgrade()覆写为仅在高级模式下返回 true,即“固件升级页只在高级模式显示”(见 custom-example/src/CustomPlugin.h)。
2. 单固件支持(Single Firmware Support)
自定义构建可以在CustomOverrides.cmake中关闭标准固件工厂,从而将 QGC 简化为单固件 UI(见 docs/zh/qgc-dev-guide/custom_build/custom_build.md):
QGC_DISABLE_APM_PLUGIN_FACTORY:不注册标准 ArduPilot 插件工厂;QGC_DISABLE_PX4_PLUGIN_FACTORY:不注册标准 PX4 插件工厂。
注意:所有固件插件代码始终会被编译进构建;禁用工厂只是把该固件从FirmwarePluginManager::supportedFirmwareClasses()返回的集合中移除,UI 在运行时自动适配——不支持的固件对应的设置、选择器与页面会被隐藏。QML 侧可通过QGroundControl.apmFirmwareSupported与QGroundControl.px4ProFirmwareSupported判断。若自定义构建实现了自己的FirmwarePluginFactory(如示例中基于 PX4 的工厂),则支持集合由该工厂的supportedFirmwareClasses()决定。
custom-example的 CustomOverrides.cmake 同时置位了两个开关,并配有自己的 PX4 工厂,实现“只支持 PX4 Pro + 多旋翼”的单一机型构建。
六、把插件接入自定义构建:CMake 注册流程
插件类本身需要被编译并注册进 QGC 构建。以 custom-example/CMakeLists.txt 为模板:
- 编译自定义源码:把
CustomPlugin.cc/h、CustomAutoPilotPlugin.cc/h、CustomFirmwarePlugin.cc/h、CustomFirmwarePluginFactory.cc/h以及自定义任务项、设置项源码加入CUSTOM_SOURCES(第 L199-L215 行); - 注册自定义类与宏:通过
CUSTOM_DEFINITIONS定义QGC_CUSTOM_BUILD、CUSTOMHEADER="CustomPlugin.h"与CUSTOMCLASS=CustomPlugin(第 L236-L241 行)。其中CUSTOMHEADER/CUSTOMCLASS就是 QGC 主程序在QGCApplication启动前实例化并注册核心插件的入口,这也是“子类在应用启动前注册”的实际落地方式; - 声明依赖库与头文件路径:通过
CUSTOM_LIBRARIES、CUSTOM_INCLUDE_DIRECTORIES交给父作用域(第 L221-L234 行); - 配置品牌变量:在 CustomOverrides.cmake 中设置
QGC_APP_NAME、QGC_ANDROID_PACKAGE_NAME、各平台图标路径(macOS 的.icns、Linux AppImage 的.svg、Windows 的.ico与安装头图)以及固件工厂开关; - 打包自定义资源与 QML 模块:用
qt_add_resources/qt_add_qml_module注册自定义图片、品牌 Logo、QML 覆盖文件与Custom.Widgets、Custom.Plan模块(CMakeLists.txt)。
构建步骤参照 custom-example/README.md:清理构建目录 → 将custom-example目录重命名为custom→ 进入custom构建 QGC。
七、如何学习与验证:从 custom-example 起步
关联文档建议的进阶路径是:先通读QGCCorePlugin.h、FirmwarePlugin.h、AutoPilotPlugin.h相关类(本仓库分别位于 src/API/QGCCorePlugin.h、src/FirmwarePlugin/FirmwarePlugin.h、src/AutoPilotPlugins/AutoPilotPlugin.h),了解可覆写的方法全集,再逐行阅读custom-example示例源码。该示例完整演示了五大能力(见 custom-example/README.md):
- 成品商业无人机场景:隐藏大部分车辆设置(由厂商预配置),仅在高级模式中保留完整体验;
- 自定义品牌:图片与调色板匹配企业视觉识别;
- 自定义界面:例如用自定义仪表控件替换标准 QGC UI;
- 覆写应用设置:隐藏用户不应更改的选项并调整默认值;
- 全注释源码:解释每段代码的目的与原因。
此外,相关的界面级定制(首次运行提示、工具栏、Fly View 覆盖层)可继续阅读同目录下的 first_run_prompts.md、toolbar.md 与 fly_view.md。
八、小结
QGroundControl 的自定义构建能力本质上是一套“以子类化代替改源码”的插件架构:QGCCorePlugin管应用级(设置、调色板、品牌、QML 引擎、计划扩展),FirmwarePlugin管固件行为(飞行模式、工具条指示器、云台、固件工厂),AutoPilotPlugin管车辆设置页面集合。三者配合CustomOverrides.cmake的工厂开关与高级模式机制,即可构建出“预配置机型 + 品牌化 UI + 简化界面”的专属地面站,同时通过继承基类保证能持续跟随上游更新。
- 无人机
- 智能硬件
【免费下载链接】qgroundcontrol
Cross-platform ground control station for drones (Android, iOS, Mac OS, Linux, Windows)
相关推荐
QGroundControl 自定义构建插件体系全解析:QGCCorePlugin、FirmwarePlugin 与 AutoPilotPlugin 定制指南
QGroundControl 自定义构建插件体系全解析:QGCCorePlugin、FirmwarePlugin 与 AutoPilotPlugin 定制指南
无人机智能硬件QGroundControl 固件插件架构深度解析:FirmwarePlugin、AutoPilotPlugin 与 QGCCorePlugin 扩展机制
QGroundControl 固件插件架构深度解析:FirmwarePlugin、AutoPilotPlugin 与 QGCCorePlugin 扩展机制 导读
无人机智能硬件QGroundControl 固件插件架构深度解析:FirmwarePlugin、AutoPilotPlugin 与 QGCCorePlugin 分层设计
QGroundControl 固件插件架构深度解析:FirmwarePlugin、AutoPilotPlugin 与 QGCCorePlugin 分层设计 QG
无人机智能硬件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考