FactSystem设计思路

2023-05-16

Fact System 模块设计思路与学习总结


组成结构

FactSystem/ (事件系统/参数系统)

  • FactControls/ (事件控制)
    • FactPanelController (事件面板控制器)
  • Fact (事件)
  • FactGroup (事件组)
  • FactMetaData (事件元资料库)
  • FactSystem (事件系统)
  • FactSystemTestBase (事件系统测试基地)
  • FactSystemTestGeneric (事件系统通用测试)
  • FactSystemTestPX4 (事件系统PX4测试)
  • FactValidator (事件验证器)
  • ParameterManager (参数管理器)
  • ParameterManagerTest (测试参数管理器)
  • SettingsFact (事件设置)

官方开发者文档

FactSystem

Fact System提供了一套用于创建QGC界面的简化标准容器(capabilities)。

Fact

  • A Fact represents a single value within the system.
  • Fact表示系统中的一个单一值。【参数】

FactMetaData

每一个Fact都关联一个FactMetaData。它提供了Fact的具体信息,用于参数生成和验证。

FactControls

FactControls是与Fact相关联的QML界面控件,根据FactMetaData提供的信息修改/显示Fact值。

FactGroup

原文到此结束了。

具体实现思路

FactPanelController

事件面板控制器与QML事件控制器结合处理事件,引入无人飞行系统界面类(UASInterface)、自动驾驶仪插件(AutoPilotPlugin)、车辆类(Vehicle),在初始化时间控制面板时,如果存在vehicle则激活它,否则让vehicle脱机并推迟检查事件面板,最后从QML正确设置。在头文件中定义了一个checkForMissingFactPanel(检查面板失踪事件)的槽,以及其他成员函数:

  • setFactPanel(设置事件面板) 如果获得了事件面板的成员集,调用notifyPanelMissingParameter函数发送所有正在等待发送的失去的事件通知并清除延迟失踪的参数。
  • notifyPanelMissingParameter(通知面板缺少参数) 如果事件面板存在,调用QMetaObject的invokeMethod方法显示错误的覆盖参数。
  • notifyPanelErrorMsg(通知面板错误消息框) 方法与上个函数相似,在消息框中显示错误。
  • reportMissingParameter(报告失踪的参数) 如果缺少从派生类的构造函数传来的参数报告,则无法获得事件面板,只是记录列表失踪的事件,在这种情况下一旦面板是可用的,则调用notifyPanelMissingParameter函数。
  • allParametersExists(获取所有出现的参数) 传入组件id,如果存在vehicle且vehicle中某个参数不存在,报告缺失的参数并设置为false,否则为true。
  • checkForMissingFactPanel(检查面板缺失的事件) 如果不存在事件面板,则调用showInternalError函数 显示不正确的事件面板,事件面板控制器在事件面板上没有通过使用。
  • getParameterFact(获取参数事件) 传入组件id,如果存在vehicle且vehicle中参数存在,则fact的值设为该参数的值并调用QQmlEngine::setObjectOwnership,否则报告缺失的参数。
  • parameterExists(判断是否已存在参数) 如果vehicle中存在该组件id,返回true否则返回false。
  • showInternalError(显示内部错误) 传入错误信息,调用notifyPanelErrorMsg并显示。

Fact

Fact被用于保存系统中的单个值,定义了许多属性设置,以及转换前后的各项参数。引入QGCMAVLink头文件。有三种初始化方式,一为默认初始化,二为传入参数初始化,三为拷贝初始化。

在类中添加以下属性:

  • componentId(构件名称)
  • bitmaskStrings(位掩码字符串)
  • bitmaskValues(位掩码值)
  • decimalPlaces(小数位)
  • defaultValue(默认值)
  • defaultValueString(默认值的字符串)
  • defaultValueAvailable(可用默认值)
  • enumIndex(枚举索引)
  • enumStrings(枚举字符串)
  • enumStringValue(枚举字符串的值)
  • enumValues(枚举值)
  • group(组)
  • longDescription(详细描述)
  • max(最大值)
  • maxString(最大字符串)
  • maxIsDefaultForType(最大值的默认类型)
  • min(最小值)
  • minString(最小字符串)
  • minIsDefaultForType(最小值的默认类型)
  • name(名称)
  • rebootRequired(需要重新启动)
  • shortDescription(短描述)
  • units(计量单位)
  • value(值)
  • rawValue(原始数值)
  • valueEqualsDefault(值为默认)
  • valueString(值字符串)
  • enumOrValueString(枚举或值字符串)
  • increment(增量)
  • typeIsString(字符串类型)
  • typeIsBool(bool类型)

通过validate函数认证以上属性。

定义几个新的信号:

  • bitmaskStringsChanged(位掩码字符串改变)
  • bitmaskValuesChanged(位掩码值改变)
  • enumStringsChanged(枚举字符串改变)
  • enumValuesChanged(枚举值改变)
  • sendValueChangedSignalsChanged(发送的值改变则信号改变)。
  • valueChanged(值改变)
  • rawValueChanged(未处理值改变)
  • vehicleUpdated(车辆数据更新)
  • containerRawValueChanged(容器原始值的改变) 表示属性已更改时调用属性写访问器,这个信号是使用的容器实现。

该类包含许多判别获取各参数值或类型的函数,实现方法类似不一一列举。以及以下函数:

  • rawValueStringFullPrecision(原始值字符串完整的精度)
  • forceSetRawValue(强制发送新的值) 设置并发送新的值给车辆即使值是一样的。如果设置成功,发出containerRawValueChanged、rawValueChanged信号,否则发出元数据指针失踪的警告。
  • setRawValue(设置原始值) 实现方式与forceSetRawValue类似,发出同样信号。
  • setCookedValue(设置处理后的值) 将元数据设置为传入的值。
  • setEnumIndex(设置枚举索引)
  • setEnumStringValue(设置枚举字符串的值)
  • setSendValueChangedSignals(设置发送值改变的信号)
  • sendValueChangedSignals(获取发送值改变的信号)
  • deferredValueChangeSignal(获取延迟值变化的信号)
  • clearDeferredValueChangeSignal(清除延迟值变化的信号)
  • sendDeferredValueChangedSignal(发送延迟值变化的信号)
  • setMetaData(设置与事件相关联的元数据集)
  • containerSetRawValue(设置容器原始值) 将未处理的值设为传入的值,发出vehicleUpdated、rawValueChanged信号。
  • setName(设置名称) 通常不应该改变事件名,除非你知道你在做什么。
  • variantToString(转化为字符串) 使用switch关键字将各类型转化为字符串类型。
  • sendValueChangedSignal(发送值改变的信号)
  • enumIndex(枚举索引) 如果元数据存在,建立索引,将未处理的值存入枚举值索引,如果当前值不在列表中,手动添加它。发出enumStringsChanged、enumValuesChanged信号。如果成功建立,返回索引数量 即index的值,否则返回-1并报错。

FactGroup

FactGroup用于将事件分组到hieraracy对象,创建QMap用于储存Fact、FactGroup、FactMetaData。定义updateAllValues槽(更新所有值),以及下列函数:

  • FactGroup(初始化) 按照传入的更新率将所有数据更新并载入元数据文件。
  • getFact(获取事件) 如果名称包含.或者由两个部分组成则获取失败,FactGroup不存在也获取失败。如果事件的图结构包含传入的名称,将其赋给Fact。
  • getFactGroup(获取事件组) 如果事件组的图结构包含传入的名称,将其赋给factGroup。
  • addFact(添加事件) 如果在事件图中已经包含新增的事件名,则发出重复事件名警告。如果事件元数据的图中包含新增的事件名,将新增的事件设置为事件元数据图中的相应事件名。
  • addFactGroup(添加事件组)
  • updateAllValues(更新所有值) 更新所有值,并发送值改变了的信号。
  • loadMetaData(载入元数据) 在json文件中创建一个图用于保存json文件名。

FactMetaData

FactMetaData用于保存于事件相关的元数据,保存的元数据于Fact有关。这是保存在事件本身里的一个单独的对象,因为你可能有多个相同的实例事件。但是只会有一个元数据实例或各个事件。

在头文件中定义枚举数据类型和两种转换器,一种处理前的一种处理后的,用于将各类型转化为用户指定的相应类型。在转换指定的原始值时,对元数据进行验证,true则转换为正确的类型不验证元数据,false则说明转换失败传入的是错误的字符串。

并且建立一个应用程序设置的转换器结构体,用于保存两种转换器的相关参数。

主文件中,首先在所有事件对象中建立转换器,该转换器通过应用程序设置驱动。建立一个FactMetaData用于保存角速度陀螺仪的应从程序转换器的设置,并将各参数初始化为默认值。因大量函数实现方法类似,因此以下列出部分函数:

  • minForType(判断最小值的类型) 通过switch判断并处理相应的类型。
  • convertAndValidateRaw(转换和验证原始值)
  • convertAndValidateCooked(转换和验证处理后的值)
  • setBitmaskInfo(设置位掩码信息) 在设置完毕后调用setBuiltInTranslator建立标准的转换器。
  • addEnumInfo(添加枚举信息)
  • setEnumInfo(设置枚举信息)
  • setTranslators(设置转换器)
  • setBuiltInTranslator(设置并建立标准转换器) 如果枚举字符串中没有转换器,那么初始化一个默认的转换器,转换器没有设置的话,尝试用应用程序设置转换器。
  • degreesToRadians(弧度转角度) 类似单位转换不再列举。
  • stringToType(字符串转为类型) 通过QStringLiteral将”String”类似的字符串转为相应的valueTypeString类型。
  • typeToSize(类型转为大小) valueTypeUint8返回1,valueTypeUint16返回2,valueTypeUint32返回4,valueTypeDouble返回8。
  • setAppSettingsTranslators(将转换器设置为与应用程序设置一致) 只能转换真实数值。
  • findAppSettingsDistanceUnitsTranslation(找到应用程序设置距离单位的转换器)
  • findAppSettingsAreaUnitsTranslation(找到应用程序设置区域单位的转换器)
  • metersToAppSettingsDistanceUnits(将米设置为应用程序设置的距离单位)
  • appSettingsDistanceUnitsToMeters(将应用程序设置的距离单位设置为米)
  • appSettingsDistanceUnitsString(字符串设置为应用程序设置的距离单位)
  • squareMetersToAppSettingsAreaUnits(平方米设置为应用程序的面积单位)
  • decimalPlaces(小数的位置)从增量决定第一个小数位置,仅获取分数部分,如果没有分数部分,则没有小数部分,因此小数为0,否则向下取整。
  • createFromJsonObject(创建json对象) 通过一个关键的密钥来获取json对象中的信息。该函数较为复杂,没看明白。
  • createMapFromJsonFile(创建json文件的图结构) 同上,不是很懂。

FactSystem

FactSystem组件是一个拥有单个值的Fact。FactMetaData保存了与Fact有关的额外的目标数据,比如简介,最大值,最小值,量程等等。FactValidator对象是一个QML验证器,根据FactMetaData验证输入设置。然后客户端代码可以使用此系统将Facts的集合显示为QML代码。举一个例子,这是PX4ParameterMetaData对象,它是PX4 AutoPilot插件的一部分。它暴露固件参数到QML,以便可以将QML ui元素直接绑定到参数。

FactSystem继承QGCTool类,重载了QGCTool的setToolbox函数,注册Fact FactMetaData FactPanelController FactGroup类型到数据库,然后使用QGCTool来启动app。

FactSystemTestBase

FactSystemTest的基类为[PX4 | Generic]的单元测试。继承了UnitTest。定义了一个插件接口。

  • 通过init函数的qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()->autopilotPlugin()来初始化插件。
  • parameter_ default_ component_ id_ test函数用于事件系统中默认组件id的参数值的基本测试。
  • parameter_ specific_ component_ id_ test函数用于事件系统中具体组件id的参数值的基本测试。
  • qml_ test函数测试QML是否可以引用一个Fact。
  • qmlUpdate_ test函数测试QML能否获取更新的Fact值。

几个测试函数也不是很懂。

FactSystemTestGeneric

继承了FactSystemTestBase类,将初始化与清空两个函数设置为槽。其余四个测试函数均调用FactSystemTestBase的成员函数。使用init(MAV_AUTOPILOT_GENERIC);来初始化泛用的微型无人机自动驾驶仪。

FactSystemTestPX4

对PX4自动驾驶仪系统的FactSystem做单元测试。同样继承FactSystemTestBase,并调用其成员函数。通过init(MAV_AUTOPILOT_PX4);初始化PX4的微型无人机自动驾驶仪。

FactValidator

FactValidator继承了QValidator,并引入Fact类,事件验证器使用FactMetaData限制输入,包含读与写访问属性的成员函数,并从QValidator重载fixup与validate函数。定义一个用于验证器工作的Fact。

ParameterManager

ParameterManager继承QObject类,连接参数管理器用于加载或更新事件。无人机的一系列事件设置均与其相关。引入以下头文件:

  • #include “ParameterManager.h”
  • #include “QGCApplication.h”
  • #include “QGCLoggingCategory.h”
  • #include “QGCApplication.h”
  • #include “UASMessageHandler.h”
  • #include “FirmwarePlugin.h”
  • #include “UAS.h”
  • #include “JsonHelper.h”
  • #include

ParameterManagerTest

继承UnitTest类,定义四个槽:
  • noFailure(没有故障) 调用_ noFailureWorker(MockConfiguration::FailNone);
  • requestListNoResponse(请求列表没有响应)
  • requestListMissingParamSuccess(请求列表缺失成功的参数) 调用_ noFailureWorker(MockConfiguration::FailMissingParamOnInitialReqest);
  • requestListMissingParamFail(请求列表缺失失败的参数) MockLink无法发送初始请求参数,那么它的后续也将失败。准备一个参数信号,让vehicle能够指出失踪的参数。最后通知用户。

以及一个成员函数:

  • noFailureWorker(运行没有出故障) 测试失败的模式仍应导致参数加载成功。首先等待车辆得到创建,然后让进度条在载入期间更新,参数加载完成后我们获取参数已经准备好的信号。最后进度设置回0.

SettingsFact

继承Fact类,SettingsFact是拥有QSettings值的Fact。有两个成员变量,一个settingGroup设置组,一个visible是否可见。和一个槽,rawValueChanged(处理前值的改变)。在这个信号里,设置组为空的话,初始化一个新的设置组,并将值传入。初始化函数中,允许核心插件有一个覆盖默认值的机会,如果元数据存在,则显示。

QT部分常用类与工具

经过近期边读FactSystem的代码边查阅相关资料,初步了解QVariant,QString,QMap,QObject,QList,QVector,QtQuick,QML,Q_PROPERTY,Q_INVOKABLE的用法与用途。
  • QObject类 QObject是QT所有类的基类,QObject是Qt Object Model的核心。什么是Qt Object Model,主要包括如下的东西

    1. 信号和槽
    2. 良好的对象属性,如可查询
    3. 有力的事件和事件过滤器
    4. 国际化字符设计
    5. 定时器为GUI的事件提供毫秒级的支持
    6. 很优秀的对象树结构
    7. 当对象销毁时指针自动设置为0
    8. 一个动态的跨库工程结构
  • QVariant类 QVariant储存了大量的数据类型, 包括 QBrush、 QColor、 QCursor、QDateTime、QFont、QKeySequence、QPalette、QPen、QPixmap、QPoint、QRect、QRegion、 QSize和 QString,并且还有C++基本类型,如int、float等。QVariant还能保存很多集合类型,QMap

疑问与总结

学习FactSystem过程中的一些问题

  • qgcApp()->toolbox()->settingsManager()->unitsSettings()->speedUnits()->rawValue().toUInt())类似这样一长串的函数嵌套很难搞明白它的源头以及用处。
  • 涉及到其他未接触的自定义类或它的成员函数时,会无法理解,去查相应的类,里面又包含其他不懂的类,查得到还好,有的根本不知道这个类放在哪里。
  • 有些词怎么翻译都感觉很奇怪,似乎无法跟已有的理解关联上,显得格格不入,比如Fact在这个文件中翻译成事件就很奇怪,如果翻译成事件的话应该跟Qt自带的QEvent有所联系才对。
  • 很多参数存在的意义也不明白,为什么要定义这些参数,参数是用来干什么的,具体在程序运行中控制了什么部分,少了这个参数会发生什么错误,类似这种的问题。
  • 如果进行修改的话也是感觉无从下手,似乎已有的代码已经很完整了,甚至推掉某个函数再写一遍都有难度。
  • Qt自带的类库或者宏经过找各种资料,可以知道是什么意思,但是了解的不够深入,如何运用更是一头雾水。

因为是最后才做的这个问题总结,所以很多在看的过程中遇到的问题要么记不起来了要么通过查找资料解决了,所以就想起了这些。

小结

整体详细的看了两遍,对这个系统有初步的认识,但是只能知道某个文件里面有些什么,没有一个具体的印象,比如这个类在程序里起到什么作用,这个FactSystem在程序中实现了什么功能,打开程序只能看到运行的界面,对于像FactSystem这样抽象的东西,无法跟程序之间建立联系,修改某一部分代码也看不到什么效果。有种拿着词典查单词看英语阅读的感觉,但是对整体文章的意思理解不了。

起初几乎要一个一个查单词才能看得懂那些函数的用途或者英文注释的意思,现在倒是可以逐渐看懂那些重复率比较高的参数或者名词。除了比较长比较复杂的函数,大体上也能看懂函数的实现过程,虽然叫我写肯定写不出来就是了。在考虑是不是需要通过一些小程序来熟悉一下Qt的应用,不然总有种很飘的感觉。

初次使用MarkDown写文档,可能有些不规范的地方,以后需要继续改进。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FactSystem设计思路 的相关文章

随机推荐