ARTICLE DETAIL

资讯详情

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

QGroundControl Fact System 深度解析:从 Fact 到 FactGroup 的自定义构建与元数据驱动 UI

QGroundControl Fact System 深度解析:从 Fact 到 FactGroup 的自定义构建与元数据驱动 UI 无人机智能硬件【免费下载链接】qgroundcontrolCross-platform ground control station for drones (Android, iOS, Mac OS, Linux, Windows)项目地址https://gitcode.com/gh_mirrors/qg/qgroundcontrol点击查看免费下载导读本文围绕 QGroundControlQGC开发指南中的 Fact System 章节展开完整讲解 Fact、FactMetaData、FactGroup 与 Fact Controls 四层架构的职责与协作方式并结合仓库源码src/FactSystem、src/FirmwarePlugin/FirmwarePlugin.h深入剖析自定义固件插件如何通过重写factGroups与adjustMetaData扩展用户自定义 Fact、调整已有 Fact 的元数据以及getFact()的两种寻址方式。读完本文你将掌握 QGC UI 自动生成的底层机制并能够编写属于自己的 Fact 扩展。概述Fact System 是什么QGC 的界面以“飞行控制台”著称其几乎所有界面控件数值输入框、开关、下拉框、滑块都不是手写死绑的而是由Fact System统一驱动、自动生成。正如 docs/en/qgc-dev-guide/fact_system.md 所述Fact System 提供了一组能力用于标准化并简化 QGC 用户界面的创建。这套体系由四个核心构件组成职责层层递进构件职责源码位置Fact系统中单个值如某个飞行参数、某个设置项的载体src/FactSystem/Fact.hFactMetaData描述该值“是什么、怎么显示、怎么校验”的元数据src/FactSystem/FactMetaData.hFact Control连接 Fact 与元数据的 QML UI 控件供用户修改/显示值src/FactSystem/FactControlsFactGroup将一组 Fact 组织成对象层级支持用户自定义 Factsrc/FactSystem/FactGroup.h理解这套分层后你会发现“数据 描述 控件模板”三者分离是 QGC 能够自动生成界面、同时允许不同固件PX4、ArduPilot 系注入自己特有参数的根本原因。Fact系统中的一个值核心定位Fact继承自QObject在 src/FactSystem/Fact.h 中被声明为QML_ELEMENT意味着它可以直接暴露给 QML 层使用。每个 Fact 代表系统中的一个值它至少包含name唯一名称如MaxAlttypeFactMetaData::ValueType_t类型如valueTypeInt32componentId关联的 MAVLink 组件 ID默认-1表示不关联组件rawValue / cookedValue原始值raw与经过单位换算、翻译后的“熟值”cooked。Raw 与 Cooked 的双域设计Fact最核心的设计是raw / cooked 双值域rawValue是未经翻译的原始值例如飞控下发的degE7、centiDegreescookedValue是经过元数据中 translator翻译器处理后的用户可读值如米、英尺、节。Fact::rawToCooked()src/FactSystem/Fact.h的注释明确指出在混合使用常量与 Fact 值时应当使用它而不是QmlUnitsConversion辅助函数以保证换算始终跟随该 Fact 自身的元数据。Q_PROPERTY 中value与rawValue都提供了读写接口setCookedValue会触发valueChanged信号setRawValue触发rawValueChanged二者是 QML 控件刷新与 MAVLink 回传的分界。常用 Q_PROPERTY 一览从 src/FactSystem/Fact.h 可以看到 Fact 对外暴露的属性非常丰富QML 控件主要依赖这些属性做自动生成与校验显示类label、shortDescription、longDescription、units、valueString、enumOrValueString、decimalPlaces校验类min/max类型默认范围、userMin/userMax用户自定义范围、validate()、clamp()枚举/位掩码类enumStrings、enumValues、enumIndex、bitmaskStrings、bitmaskValues、selectedBitmaskStrings行为类readOnly、writeOnly、hasControl、volatileValue、vehicleRebootRequired、qgcRebootRequired、increment状态类valueEqualsDefault、defaultValue、defaultValueAvailable。其中validate(const QString cookedValue, bool convertOnly)与clamp(const QString cookedValue)是 Q_INVOKABLE 方法供 QML 输入控件在用户输入时做“先转换、再校验、必要时钳制”的三步处理。FactMetaData驱动 UI 自动生成与校验的元数据为什么需要独立元数据对象src/FactSystem/FactMetaData.h 的类注释说明了设计意图元数据与 Fact 本身分离保存因为系统中可能存在同一 Fact 的多个实例但每个 Fact 只有唯一的 FactMetaData 实例。例如“高度”这个 Fact 可能同时出现在多个设置页中但它们的类型、单位、范围、枚举描述只需一份共享元数据。值类型体系FactMetaData::ValueType_tsrc/FactSystem/FactMetaData.h定义了 14 种值类型Uint8 / Int8 / Uint16 / Int16 / Uint32 / Int32 / Uint64 / Int64 / Float / Double / String / Bool / ElapsedTimeInSeconds / Custom注意两个特殊类型valueTypeElapsedTimeInSeconds内部以 double 存储但valueString显示为HH:MM:SS格式valueTypeCustom内部以QByteArray存储用于无法归入基础类型的值。类型字符串与枚举的互相转换由stringToType()/typeToString()完成src/FactSystem/FactMetaData.h这使 JSON 文件中的type: Int32能直接映射到valueTypeInt32。单位换算Translator机制FactMetaData内置大量翻译器src/FactSystem/FactMetaData.h覆盖了地面站场景几乎全部单位换算需求角度_degreesToRadians、_centiDegreesToDegrees、_userGimbalDegreesToMavlinkGimbalDegrees等温度_centiCelsiusToCelsius、_celsiusToFarenheit等距离/高度_metersToFeet、_centimetersToInches等面积平方米 ⇄ 平方公里 / 公顷 / 平方英尺 / 英亩 / 平方英里速度m/s ⇄ mph / km/h / 节重量克 ⇄ 千克 / 盎司 / 磅百分比_percentToNorm/_normToPercent。此外还有跟随用户 App 设置的单位翻译_setAppSettingsTranslators()src/FactSystem/FactMetaData.hFactMetaData会依据用户在设置中选择的水平距离、垂直距离、面积、速度、温度、重量单位UnitTypessrc/FactSystem/FactMetaData.h自动切换 cooked 单位与 translator。校验、钳制与自定义校验器FactMetaData提供三条核心校验路径convertAndValidateRaw()/convertAndValidateCooked()src/FactSystem/FactMetaData.h转换类型并对照 min/max 校验失败时通过errorString返回面向用户的错误信息clampValue()src/FactSystem/FactMetaData.h转换后把越界值钳制到cookedMin/cookedMaxsetCustomCookedValidator()src/FactSystem/FactMetaData.h安装自定义 cooked 值校验函数在标准校验器之前被调用返回空字符串表示校验通过否则返回向用户解释的错误字符串。min/max 体系同样区分两套类型固有范围_minForType/_maxForType与元数据声明的范围maxIsDefaultForType等属性用来判断元数据是否显式覆盖了默认范围src/FactSystem/FactMetaData.h。JSON 元数据字段全集FactMetaData通过createMapFromJsonFile()/createMapFromJsonArray()/createFromJsonObject()src/FactSystem/FactMetaData.h从 JSON 加载元数据。JSON 键名定义在 src/FactSystem/FactMetaData.h配合官方 schema src/FactSystem/factmetadata.schema.json 可得到完整字段清单JSON 键含义备注nameFact 名称必填^[a-zA-Z_][a-zA-Z0-9_]*$type值类型必填14 种类型之一小写units显示单位如m、m/s、deg、%、degE7min/max合法值范围含端点可选default/mobileDefault默认值mobileDefault为移动端单独指定decimalPlaces显示小数位0–15默认kDefaultDecimalPlaces 3enumStrings/enumValues枚举显示串与数值新格式为values数组bitmaskStrings/bitmaskValues位掩码显示串与数值新格式为bitmask数组shortDesc/longDesc短/长描述分别用于 UI 与帮助提示category/group分组信息默认Other/Miscvolatile高频变化标志影响 UI 刷新策略control是否有对应 UI 控件hasControlreadOnly/writeOnly读写权限increment步进值用于旋钮/带刻度滑块rebootRequired/qgcRebootRequired是否需重启飞控/QGCcomment/keywords注释与检索关键词同时 schema 规定 JSON 文件顶层支持version字段与QGC.MetaData.Facts数组、QGC.MetaData.Defines预定义常量映射src/FactSystem/FactMetaData.h后者可在元数据文件中复用公共定义。FactGroupFact 的组织容器FactGroupsrc/FactSystem/FactGroup.h把一组 Fact 组织成对象层级是“名 → Fact”映射_nameToFactMap与“名 → 子 FactGroup”映射_nameToFactGroupMap的持有者。其关键能力_addFact()/_addFactGroup()把 Fact 或子组挂接到当前组可指定名称默认使用 Fact 的name()/ objectNamefactNames()/factGroupNames()枚举组内 Fact 与子组名getFact(name)/getFactGroup(name)按名查找找不到会输出qWarning视为内部错误_updateAllValues()按updateRateMsecs周期刷新值0 表示立即更新实现高频遥测场景下的节流对应Fact::setSendValueChangedSignals的延迟信号机制src/FactSystem/Fact.hhandleMessage()允许 FactGroup 解析收到的 MAVLink 消息并填充值src/FactSystem/FactGroup.htelemetryAvailable标志该组值是否已收到遥测。构造函数FactGroup(int updateRateMsecs, const QString metaDataFile, QObject *parent nullptr, bool ignoreCamelCase false)src/FactSystem/FactGroup.h允许直接传入 JSON 元数据文件由_loadFromJsonArray()自动批量创建组内 Fact 及其元数据。Fact ControlsQML 控件层Fact Control是连接 Fact 与其元数据的 QML 控件。QGC 在 src/FactSystem/FactControls 下提供了覆盖各种交互形态的控件族控件用途FactTextField/FactTextFieldGrid/FactTextFieldRow单行文本/数值输入网格/行布局FactTextFieldSlider/FactTextFieldSlider2/FactValueSlider文本输入 滑块组合FactCheckBox/FactCheckBoxSlider布尔开关、开关 滑块FactComboBox枚举下拉框依赖enumStrings/enumValuesFactBitmask/FactBitMaskCheckBoxSlider位掩码多选FactLabel/LabelledFactLabel只读显示LabelledFactTextField/LabelledFactComboBox/LabelledFactIncrementer/LabelledFactBrowse带标题的封装控件AltitudeFactTextField高度专用输入自动应用垂直距离单位这些控件统一通过Fact的 Q_PROPERTY 读写值并通过FactMetaData完成校验与单位显示因此一套控件即可复用于任意 Fact。配套的FactPanelControllersrc/FactSystem/FactControls/FactPanelController.h为面板提供 Fact 查找与绑定能力。自定义构建扩展用户自定义 Fact原文档给出了事实系统的扩展入口全部集中在FirmwarePlugin 层。以下结合源码逐一展开。重写factGroups()注入固件专属 FactGroupsrc/FirmwarePlugin/FirmwarePlugin.h 中声明了虚函数/// Returns a pointer to a dictionary of firmware-specific FactGroups virtual QMapQString, FactGroup* *factGroups() { return nullptr; }默认实现返回nullptr。自定义固件插件如 APM 系列通过重写该方法返回“名称 → FactGroup”映射QGC 据此识别新增的 Fact 组。仓库中以ArduSubFirmwarePlugin为真实范例它在 src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.cc 实现了factGroups()并在头文件 src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.h 中以override声明。添加自定义 FactGroup 的方式是继承FactGroup类并在构造函数中通过FactGroup(updateRateMsecs, metaDataFile, ...)传入包含必要信息的 JSON 文件由 FactGroup 自动完成 Fact 与元数据的装载。重写adjustMetaData()调整已有 Fact 的元数据src/FirmwarePlugin/FirmwarePlugin.h/// Allows the Firmware plugin to override the facts meta data. /// param vehicleType - Type of current vehicle /// param metaData - MetaData for fact virtual void adjustMetaData(MAV_TYPE /*vehicleType*/, FactMetaData* /*metaData*/) {}该钩子在车辆事实创建时被调用用于按飞控类型改写既有 Fact 的元数据如调整范围、枚举、单位、默认值。ArduSubFirmwarePlugin::adjustMetaDatasrc/FirmwarePlugin/APM/ArduSubFirmwarePlugin.cc即是重写示例。调用链路可以在 src/Vehicle/Vehicle.cc 中找到证据_firmwarePlugin-adjustMetaData(vehicleType, getFact(factName)-metaData());即Vehicle在初始化事实时取得其FactMetaData指针交给固件插件进行定制化修改。值得注意的是SettingsManager也执行类似流程Fact构造时调用SettingsManager::adjustSettingMetaData见 src/FactSystem/Fact.h因此自定义构建对设置类 Fact 也有调整入口。getFact()的两种寻址方式原文档强调与车辆关联的 Fact包括固件插件factGroups()返回组内的 Fact可通过两种路径访问getFact(factName)直接访问组内顶层 FactgetFact(factGroupName.factName)用点号限定组名后访问。Vehicle中确实实现了这种分级访问。在 src/Vehicle/Vehicle.cc 中Vehicle先获取_firmwarePlugin-factGroups()返回的固件专属组在 src/Vehicle/Vehicle.cc 中遍历factGroups()并挂接各组的 Fact在 src/Vehicle/Vehicle.cc 中可以看到同时使用getFact(factName)与getFactGroup(groupName)-getFact(factName)两种方式汇总全部 Fact 值——这正是“组名.factName”寻址在实现层的等价形式。实践步骤小结要在自定义固件插件中加入用户自定义 Fact完整路径为继承FactGroup编写自定义组类构造时传入 JSON 元数据文件路径或手工_addFact添加 Fact重写固件插件继承FirmwarePlugin的factGroups()返回包含该组的新映射参考ArduSubFirmwarePlugin的写法src/FirmwarePlugin/APM/ArduSubFirmwarePlugin.cc如需修改现有 Fact 的元数据重写adjustMetaData(MAV_TYPE vehicleType, FactMetaData *metaData)按vehicleType分支改写metaData的属性在 QML 中通过getFact(factName)或getFact(groupName.factName)获取 Fact再配合 src/FactSystem/FactControls 中的任一控件完成展示与编辑。总结QGC 的 Fact System 用“一个值Fact 一份描述FactMetaData 一组控件模板Fact Controls 一个容器FactGroup”四层结构实现了界面生成的标准化与自动化元数据驱动 UI 生成与输入校验translator 处理单位换算factGroups()与adjustMetaData()为不同固件/自定义构建打开了两条扩展通道。对开发者而言掌握这套机制就等于掌握了向 QGC 注入任何自定义参数、并为它自动生成专业 UI 的完整方法论。进一步的源码细节可继续研读 src/FactSystem/Fact.cc、src/FactSystem/FactGroup.cc 与 src/FirmwarePlugin/FirmwarePlugin.cc。赞分享无人机智能硬件【免费下载链接】qgroundcontrolCross-platform ground control station for drones (Android, iOS, Mac OS, Linux, Windows)项目地址https://gitcode.com/gh_mirrors/qg/qgroundcontrol点击查看免费下载相关推荐Fact Check Report: [Concept Name]Fact Check Report: Concept Name File: docs/concepts/ slug .mdx Date: YYYY MM DD教程前端文档Puppet 实战基于 Hiera 5 与 YAML 后端的层次化数据分层与 Fact 驱动覆盖Puppet 实战基于 Hiera 5 与 YAML 后端的层次化数据分层与 Fact 驱动覆盖 导读 本文以 Puppet 仓库中的 examples/hi运维DevOpsIaCQGroundControl 自定义构建插件体系FirmwarePlugin / AutoPilotPlugin / QGCCorePlugin 深度定制指南QGroundControl 自定义构建插件体系FirmwarePlugin / AutoPilotPlugin / QGCCorePlugin 深度定制指南无人机智能硬件上一篇Kubescape架构图详解理解Kubernetes安全平台组件下一篇物联网设备代码库的可视化文档终极指南如何用DeepWiki-Open快速生成智能文档创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表