news 2026/10/15 15:42:31

QGroundControl 自定义构建插件机制:QGCCorePlugin / FirmwarePlugin / AutoPilotPlugin 深度解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
QGroundControl 自定义构建插件机制:QGCCorePlugin / FirmwarePlugin / AutoPilotPlugin 深度解析
  • 无人机
  • 智能硬件

【免费下载链接】qgroundcontrol

Cross-platform ground control station for drones (Android, iOS, Mac OS, Linux, Windows)

项目地址:https://gitcode.com/gh_mirrors/qg/qgroundcontrol
点击查看免费下载

本篇技术指南围绕 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 为模板:

  1. 编译自定义源码:把CustomPlugin.cc/h、CustomAutoPilotPlugin.cc/h、CustomFirmwarePlugin.cc/h、CustomFirmwarePluginFactory.cc/h以及自定义任务项、设置项源码加入CUSTOM_SOURCES(第 L199-L215 行);
  2. 注册自定义类与宏:通过CUSTOM_DEFINITIONS定义QGC_CUSTOM_BUILD、CUSTOMHEADER="CustomPlugin.h"与CUSTOMCLASS=CustomPlugin(第 L236-L241 行)。其中CUSTOMHEADER/CUSTOMCLASS就是 QGC 主程序在QGCApplication启动前实例化并注册核心插件的入口,这也是“子类在应用启动前注册”的实际落地方式;
  3. 声明依赖库与头文件路径:通过CUSTOM_LIBRARIES、CUSTOM_INCLUDE_DIRECTORIES交给父作用域(第 L221-L234 行);
  4. 配置品牌变量:在 CustomOverrides.cmake 中设置QGC_APP_NAME、QGC_ANDROID_PACKAGE_NAME、各平台图标路径(macOS 的.icns、Linux AppImage 的.svg、Windows 的.ico与安装头图)以及固件工厂开关;
  5. 打包自定义资源与 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)

项目地址:https://gitcode.com/gh_mirrors/qg/qgroundcontrol
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 15:42:01

深度解析MobileNet:轻量级网络原理与部署实战

1. 为什么需要轻量级网络&#xff1a;算力与场景的现实约束很多朋友第一次看到 MobileNet 这个名字&#xff0c;第一反应是"这不就是个给手机用的分类网络吗"&#xff0c;这句话对了一半。MobileNet 确实最早是面向移动端、嵌入式场景设计的&#xff0c;但它真正解决…

作者头像 李华
网站建设 2026/10/15 15:41:52

私域工具选型实战指南:从需求梳理到落地避坑

开头 私域这个词被讲了太多年&#xff0c;但真正落地的时候&#xff0c;绝大多数团队卡住的不是内容、不是活动&#xff0c;而是工具选型。有的公司一年换了三套系统&#xff0c;数据迁来迁去&#xff0c;运营节奏全被打乱&#xff1b;有的公司买了一套大而全的旗舰产品&#x…

作者头像 李华
网站建设 2026/10/15 15:41:51

思途旅游CMS V5/V6手机端LBS模块部署与避坑指南

简介&#xff1a;思途旅游CMS V6.0破解版安装包&#xff0c;附带app_mobilelbsV5.0手机端模块&#xff0c;兼容老版本系统。面向旅游行业网站开发者、二次开发人员及需要快速搭建旅游服务后台的中小团队&#xff0c;解决基于开源CMS整合移动端LBS定位导航、周边推荐等功能的问题…

作者头像 李华
网站建设 2026/10/15 15:41:45

米津玄師×野田洋次郎《PLACEBO》罗马音歌词翻译与解析

1. 写在前面&#xff1a;一份特殊的“歌词作业”前阵子朋友发来一首歌&#xff0c;问我能不能帮忙把罗马音和翻译整理出来。我点开一听&#xff0c;前奏刚过就愣住了——这编曲和唱腔的组合太熟悉了&#xff0c;但两个人同框又让人觉得不太真实。仔细一看歌手栏&#xff0c;果然…

作者头像 李华
网站建设 2026/10/15 15:41:11

Windows视频解码器K-Lite 1957 Mega安装排错指南

在Windows上看不了视频这件事&#xff0c;多少带点玄学。同样的MP4在手机上正常播放&#xff0c;拖到电脑上就提示缺解码器&#xff1b;换了个播放器能出声了&#xff0c;画面却是绿的&#xff1b;好不容易画面正常&#xff0c;字幕又变成乱码。这些年跟这些问题纠缠下来&#…

作者头像 李华
网站建设 2026/10/15 15:41:02

hx711压力传感器51单片机代码实战:从跳数到稳定称重

简介&#xff1a;这份资源是面向51单片机初学者与电子制作爱好者的HX711压力传感器驱动代码包&#xff0c;用于搭建电子秤、配料称重等需要高精度重量检测的小型项目。包内共12个文件&#xff0c;约18KB&#xff0c;以Keil工程文件为主&#xff1a;包含uvproj工程配置、uvopt调…

作者头像 李华