关于QGroundControl的软件架构的理解

news2024/11/27 4:28:55

首先QGC是基于QT平台开发,个人理解软件架构即为项目前后端结构,以及前后端数据交互的逻辑。下面是对QGroundControl源码的一些个人理解,写这个博客只是为了记录下来,防止时间久了忘记,过程中看了一些大佬的博客来帮助理解,感谢一下大佬:

火山上的企鹅

阿木实验室

望天边星宿

前言

  • 前端qml结构

QGC的前端主要为五个主要页面和一个顶栏:

MainToolBar(顶栏)

AppSetting.qml

SetupView.qml

PlanView.qml

FlightDispalyView.qml

AnalyzeView.qml

  • 后端类结构

 前端显示与后端逻辑进行数据交互,即实现了QGC地面站功能。

架构理解

架构理解可以从QGC的运行main函数开始逐步理解。

  • main.cc

在main.cc中有几个关键程序

创建QGCApplication实例,QGCApplication是QGroundControl中的核心类,提供了应用程序的生命周期管理、连接管理、飞行日志管理、地图和任务管理、设置和配置管理,以及警报和通知管理等功能。它扮演着关键角色。这个类只提供了唯一的实例,另外提供了一个访问它的全局函数QGCApplication* qgcApp(void){}

QGCApplication* app = new QGCApplication(argc, argv, runUnitTests);

在_initCommon()中将C++类注册,在前端qml中可以调用,实现前后端数据交互。在

qgroundcontrolQmlGlobalSingletonFactory中将QGroundControlQmlGlobal类实例化为单例工厂QGroundControl。
app->_initCommon()
{
    static const char* kRefOnly         = "Reference only";
    static const char* kQGroundControl  = "QGroundControl";
    static const char* kQGCControllers  = "QGroundControl.Controllers";
    static const char* kQGCVehicle      = "QGroundControl.Vehicle";

    QSettings settings;

    // Register our Qml objects

    qmlRegisterType<QGCPalette>     ("QGroundControl.Palette", 1, 0, "QGCPalette");
    qmlRegisterType<QGCMapPalette>  ("QGroundControl.Palette", 1, 0, "QGCMapPalette");

    qmlRegisterUncreatableType<Vehicle>                 (kQGCVehicle,                       1, 0, "Vehicle",                    kRefOnly);
    qmlRegisterUncreatableType<MissionManager>          (kQGCVehicle,                       1, 0, "MissionManager",             kRefOnly);
    qmlRegisterUncreatableType<ParameterManager>        (kQGCVehicle,                       1, 0, "ParameterManager",           kRefOnly);
    qmlRegisterUncreatableType<VehicleObjectAvoidance>  (kQGCVehicle,                       1, 0, "VehicleObjectAvoidance",     kRefOnly);
    qmlRegisterUncreatableType<QGCCameraManager>        (kQGCVehicle,                       1, 0, "QGCCameraManager",           kRefOnly);
    qmlRegisterUncreatableType<QGCCameraControl>        (kQGCVehicle,                       1, 0, "QGCCameraControl",           kRefOnly);
    qmlRegisterUncreatableType<QGCVideoStreamInfo>      (kQGCVehicle,                       1, 0, "QGCVideoStreamInfo",         kRefOnly);
    qmlRegisterUncreatableType<LinkInterface>           (kQGCVehicle,                       1, 0, "LinkInterface",              kRefOnly);
    qmlRegisterUncreatableType<MissionController>       (kQGCControllers,                   1, 0, "MissionController",          kRefOnly);
    qmlRegisterUncreatableType<GeoFenceController>      (kQGCControllers,                   1, 0, "GeoFenceController",         kRefOnly);
    qmlRegisterUncreatableType<RallyPointController>    (kQGCControllers,                   1, 0, "RallyPointController",       kRefOnly);

    qmlRegisterUncreatableType<MissionItem>         (kQGroundControl,                       1, 0, "MissionItem",                kRefOnly);
    qmlRegisterUncreatableType<VisualMissionItem>   (kQGroundControl,                       1, 0, "VisualMissionItem",          kRefOnly);
    qmlRegisterUncreatableType<CoordinateVector>    (kQGroundControl,                       1, 0, "CoordinateVector",           kRefOnly);
    qmlRegisterUncreatableType<QmlObjectListModel>  (kQGroundControl,                       1, 0, "QmlObjectListModel",         kRefOnly);
    qmlRegisterUncreatableType<MissionCommandTree>  (kQGroundControl,                       1, 0, "MissionCommandTree",         kRefOnly);
    qmlRegisterUncreatableType<CameraCalc>          (kQGroundControl,                       1, 0, "CameraCalc",                 kRefOnly);
    qmlRegisterUncreatableType<LogReplayLink>       (kQGroundControl,                       1, 0, "LogReplayLink",              kRefOnly);
    qmlRegisterType<LogReplayLinkController>        (kQGroundControl,                       1, 0, "LogReplayLinkController");
#if defined(QGC_ENABLE_MAVLINK_INSPECTOR)
    qmlRegisterUncreatableType<MAVLinkChartController> (kQGroundControl,                    1, 0, "MAVLinkChart",               kRefOnly);
#endif
#if defined(QGC_ENABLE_PAIRING)
    qmlRegisterUncreatableType<PairingManager>      (kQGroundControl,                       1, 0, "PairingManager",             kRefOnly);
#endif

    qmlRegisterUncreatableType<AutoPilotPlugin>     ("QGroundControl.AutoPilotPlugin",      1, 0, "AutoPilotPlugin",            kRefOnly);
    qmlRegisterUncreatableType<VehicleComponent>    ("QGroundControl.AutoPilotPlugin",      1, 0, "VehicleComponent",           kRefOnly);
    qmlRegisterUncreatableType<JoystickManager>     ("QGroundControl.JoystickManager",      1, 0, "JoystickManager",            kRefOnly);
    qmlRegisterUncreatableType<Joystick>            ("QGroundControl.JoystickManager",      1, 0, "Joystick",                   kRefOnly);
    qmlRegisterUncreatableType<QGCPositionManager>  ("QGroundControl.QGCPositionManager",   1, 0, "QGCPositionManager",         kRefOnly);
    qmlRegisterUncreatableType<FactValueSliderListModel>("QGroundControl.FactControls",     1, 0, "FactValueSliderListModel",   kRefOnly);

    qmlRegisterUncreatableType<QGCMapPolygon>       ("QGroundControl.FlightMap",            1, 0, "QGCMapPolygon",              kRefOnly);
    qmlRegisterUncreatableType<QGCGeoBoundingCube>  ("QGroundControl.FlightMap",            1, 0, "QGCGeoBoundingCube",         kRefOnly);
    qmlRegisterUncreatableType<TrajectoryPoints>    ("QGroundControl.FlightMap",            1, 0, "TrajectoryPoints",           kRefOnly);

    qmlRegisterType<QGCMapCircle>                   ("QGroundControl.FlightMap",            1, 0, "QGCMapCircle");

    qmlRegisterType<ParameterEditorController>      (kQGCControllers,                       1, 0, "ParameterEditorController");
    qmlRegisterType<ESP8266ComponentController>     (kQGCControllers,                       1, 0, "ESP8266ComponentController");
    qmlRegisterType<ScreenToolsController>          (kQGCControllers,                       1, 0, "ScreenToolsController");
    qmlRegisterType<PlanMasterController>           (kQGCControllers,                       1, 0, "PlanMasterController");
    qmlRegisterType<ValuesWidgetController>         (kQGCControllers,                       1, 0, "ValuesWidgetController");
    qmlRegisterType<QGCFileDialogController>        (kQGCControllers,                       1, 0, "QGCFileDialogController");
    qmlRegisterType<RCChannelMonitorController>     (kQGCControllers,                       1, 0, "RCChannelMonitorController");
    qmlRegisterType<JoystickConfigController>       (kQGCControllers,                       1, 0, "JoystickConfigController");
    qmlRegisterType<LogDownloadController>          (kQGCControllers,                       1, 0, "LogDownloadController");
    qmlRegisterType<SyslinkComponentController>     (kQGCControllers,                       1, 0, "SyslinkComponentController");
    qmlRegisterType<EditPositionDialogController>   (kQGCControllers,                       1, 0, "EditPositionDialogController");

#ifndef __mobile__
#ifndef NO_SERIAL_LINK
    qmlRegisterType<FirmwareUpgradeController>      (kQGCControllers,                       1, 0, "FirmwareUpgradeController");
#endif
#endif
    qmlRegisterType<GeoTagController>               (kQGCControllers,                       1, 0, "GeoTagController");
    qmlRegisterType<MavlinkConsoleController>       (kQGCControllers,                       1, 0, "MavlinkConsoleController");
#if defined(QGC_ENABLE_MAVLINK_INSPECTOR)
    qmlRegisterType<MAVLinkInspectorController>     (kQGCControllers,                       1, 0, "MAVLinkInspectorController");
#endif
    // Register Qml Singletons
    qmlRegisterSingletonType<QGroundControlQmlGlobal>   ("QGroundControl",                          1, 0, "QGroundControl",         qgroundcontrolQmlGlobalSingletonFactory);
    qmlRegisterSingletonType<ScreenToolsController>     ("QGroundControl.ScreenToolsController",    1, 0, "ScreenToolsController",  screenToolsControllerSingletonFactory);
    qmlRegisterSingletonType<ShapeFileHelper>           ("QGroundControl.ShapeFileHelper",          1, 0, "ShapeFileHelper",        shapeFileHelperSingletonFactory);
}

在_initForNormalAppBoot()中进行启动初始化,加载qml文件。

app->_initForNormalAppBoot()

QQmlApplicationEngine* QGCCorePlugin::createRootWindow(QObject *parent)
{
    QQmlApplicationEngine* pEngine = new QQmlApplicationEngine(parent);
    pEngine->addImportPath("qrc:/qml");
    // 注册为对象在qml中直接使用,不需要import
    pEngine->rootContext()->setContextProperty("joystickManager", qgcApp()->toolbox()->joystickManager());
    pEngine->rootContext()->setContextProperty("debugMessageModel", AppMessages::getModel());
    pEngine->load(QUrl(QStringLiteral("qrc:/qml/MainRootWindow.qml")));
    return pEngine;
}
  • 整体架构

想要搞明白整体架构就需要理解QGCApplication类、QGCToolBox类、QGroundControlQmlGlobal类和QGCtool类。

QGCApplication类中新建了QGCToolbox类,在QGCToolbox类初始化时需要传入QGCApplication类,这样通过qgcAPP()->toolBox()就可以获取到功能类的所有属性。

QGCToolBox类是一个大的工具类,QGC的所有功能类都在这个toolBox中进行实例化,使用toolBox提供的接口即可调用类的属性和方法。

在QGroundControlQmlGlobal中通过Q_PROPERTY将功能类的属性和方法共前端可以调用,setToolbox()方法将所有功能类使用指针地址连接到QGCToolBox定义的功能类,所以QGroundControlQmlGlobal是前端获取后端数据的总接口。上边的单例工厂实例化将QGroundControlQmlGlobal实例化为QGroundControl,则前端qml通过import 即可实现调用C++类。

还有一个QGCTool类,所有的功能类都继承了QGCTool。在QGCTool类型定义了QGCApplication* _app;和QGCToolbox* _toolbox;和(QGCApplication* app, QGCToolbox* toolbox)方法,即每个功能类都都有QGCApplication和QGCToolbox,并且都指向同一个QGCApplication和QGCToolbox,即QGCApplication中的_app和_toolBox.这样实现了各个功能类的互通。

QGCToolbox::QGCToolbox(QGCApplication* app)
{
    // SettingsManager must be first so settings are available to any subsequent tools
    _settingsManager        = new SettingsManager           (app, this);
    //-- Scan and load plugins
    _scanAndLoadPlugins(app);
    _audioOutput            = new AudioOutput               (app, this);
    _factSystem             = new FactSystem                (app, this);
    _firmwarePluginManager  = new FirmwarePluginManager     (app, this);
#ifndef __mobile__
    _gpsManager             = new GPSManager                (app, this);
#endif
    _imageProvider          = new QGCImageProvider          (app, this);
    _joystickManager        = new JoystickManager           (app, this);
    _linkManager            = new LinkManager               (app, this);
    _mavlinkProtocol        = new MAVLinkProtocol           (app, this);
    _missionCommandTree     = new MissionCommandTree        (app, this);
    _multiVehicleManager    = new MultiVehicleManager       (app, this);
    _mapEngineManager       = new QGCMapEngineManager       (app, this);
    _uasMessageHandler      = new UASMessageHandler         (app, this);
    _qgcPositionManager     = new QGCPositionManager        (app, this);
    _followMe               = new FollowMe                  (app, this);
    _videoManager           = new VideoManager              (app, this);
    _mavlinkLogManager      = new MAVLinkLogManager         (app, this);
    _adsbVehicleManager     = new ADSBVehicleManager        (app, this);
#if defined(QGC_ENABLE_PAIRING)
    _pairingManager         = new PairingManager            (app, this);
#endif
    //-- Airmap Manager
    //-- This should be "pluggable" so an arbitrary AirSpace manager can be used
    //-- For now, we instantiate the one and only AirMap provider
#if defined(QGC_AIRMAP_ENABLED)
    _airspaceManager        = new AirMapManager             (app, this);
#else
    _airspaceManager        = new AirspaceManager           (app, this);
#endif
#if defined(QGC_GST_TAISYNC_ENABLED)
    _taisyncManager         = new TaisyncManager            (app, this);
#endif
#if defined(QGC_GST_MICROHARD_ENABLED)
    _microhardManager       = new MicrohardManager          (app, this);
#endif
}

void QGCToolbox::setChildToolboxes(void)
{
    // SettingsManager must be first so settings are available to any subsequent tools
    _settingsManager->setToolbox(this);
    _corePlugin->setToolbox(this);
    _audioOutput->setToolbox(this);
    _factSystem->setToolbox(this);
    _firmwarePluginManager->setToolbox(this);
#ifndef __mobile__
    _gpsManager->setToolbox(this);
#endif
    _imageProvider->setToolbox(this);
    _joystickManager->setToolbox(this);
    _linkManager->setToolbox(this);
    _mavlinkProtocol->setToolbox(this);
    _missionCommandTree->setToolbox(this);
    _multiVehicleManager->setToolbox(this);
    _mapEngineManager->setToolbox(this);
    _uasMessageHandler->setToolbox(this);
    _followMe->setToolbox(this);
    _qgcPositionManager->setToolbox(this);
    _videoManager->setToolbox(this);
    _mavlinkLogManager->setToolbox(this);
    _airspaceManager->setToolbox(this);
    _adsbVehicleManager->setToolbox(this);
#if defined(QGC_GST_TAISYNC_ENABLED)
    _taisyncManager->setToolbox(this);
#endif
#if defined(QGC_GST_MICROHARD_ENABLED)
    _microhardManager->setToolbox(this);
#endif
#if defined(QGC_ENABLE_PAIRING)
    _pairingManager->setToolbox(this);
#endif
}

void QGCToolbox::_scanAndLoadPlugins(QGCApplication* app)
{
#if defined (QGC_CUSTOM_BUILD)
    //-- Create custom plugin (Static)
    _corePlugin = (QGCCorePlugin*) new CUSTOMCLASS(app, app->toolbox());
    if(_corePlugin) {
        return;
    }
#endif
    //-- No plugins found, use default instance
    _corePlugin = new QGCCorePlugin(app, app->toolbox());
}

在前端获取后端类的属性的总借口即为QGroundControl,例如

property var   _vehicle:          QGroundControl.multiVehicleManager.getVehicleById(1)

在功能类中向获取其他功能类的属性即使用qgcApp()->toolbox(),如果功能类继承了QGCTool则直接可以使用_toolbox->...即可。

_mavlink = qgcApp()->toolbox()->mavlinkProtocol();
_mavlinkProtocol =           _toolbox->mavlinkProtocol();

其实只要理解这几个总文件之间的关系后,就理解了QGC的整体结构。_app和_toolbox是QGC整个软件的总接口,_app和_toolbox都在QGCApplication类中,然后所有功能类都在QGCToolBox类中新建,想要获取功能类的属性就需要通过_toolbox。然后QGroundControlQmlGlobal中通过指针地址获取到了所有功能类,然后又通过Q_PROPERTY将类以属性的形式开放给前端,再加上单例模式直接在前端import QGroundControl即可获取到后端属性。这样即完成了前后端数据连通,也解决了各个功能类之间的属性获取。

以上是个人理解,很多地理解的不是太透彻,等有新的理解再更新。有错误的地方也望大佬指正,共同进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/598371.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

服务运营 |摘要: Healthcare Management Science 近期论文汇总

推文作者&#xff1a;李舒湉 罗毓灵 编者按 Healthcare Management Science 近期论文汇总 Healthcare Management Science 论文精选&#xff08;三月下&#xff09; 1Monitoring policy in the context of preventive treatment of cardiovascular disease https://link.sprin…

SQL——视图检查选项 local

create table stue ( id int auto_increment primary key comment 客户编号, name varchar(20) comment 客户名称, mima varchar(100) comment客户密码 , phonr varchar(20) comment 客户电话, xb char(2) …

【目录】《电路》上下、《电力电子学》、《数字电路》

1、知乎----作为电力电子专业的学生&#xff0c;有哪些专业书籍值得反复阅读&#xff1f; 一门课 / 一本书 经不经典&#xff0c;直接去 中国大学MOOC 上搜一搜就知道了 《电路》 电路主要讲&#xff1a;电压、电阻、电容的一些计算公式 《电力电子学》 https://www.zhih…

Hexo 搭建博客并推送GitHub

初始Hexo npm install hexo-cli -g hexo init blog cd blog npm install hexo server浏览器访问&#xff1a;http://localhost:4000/ 设置GitHub 1、首先要注册一个Github账号&#xff0c;新建一个name.github.io的仓库&#xff0c;也就是new repository。 因为博主之前创建…

Sui主网升级至V1.2.0版本

升级要点 [API行为调整] — 因rpc方法导致的UserInputError、 SuiRpcInputError、SuiError::TransactionNotFound以及SuiError::TransactionsNotFound报错&#xff0c;现在返回错误代码为32602&#xff0c;取代了32000。此信息已在#11833 #11928中更正。 修复了get_coin_meta…

Python实战基础18-文件操作

1、文件的打开和关闭 1.1 操作文件的整体过程 打开文件&#xff0c;或者新建立一个文件读/写数据关闭文件 1.2 打开文件 在python&#xff0c;使用open函数&#xff0c;可以打开一个已经存在的文件&#xff0c;或者创建一个新文件。 open(文件路径&#xff0c;访问模式) …

【教程】在 Visual Studio 2015 上对 C++ 进行单元测试

更新中 目录 前言环境Visual Studio 2015 提供的单元测试工具创建 C 测试框架在测试项目内测试一个函数测试另一个 Project 的函数参考 前言 本文的测试环境是 Visual Studio 2015&#xff0c;高级别版本&#xff08;如&#xff0c;2017&#xff0c;2022&#xff09;的操作略有…

SpringBoot + 规则引擎 URule,太强了!

一、背景 前段时间&#xff0c;在做项目重构的时候&#xff0c;遇到很多地方需要做很多的条件判断。当然可以用很多的if-else判断去解决&#xff0c;但是当时也不清楚怎么回事&#xff0c;就想玩点别的。于是乎&#xff0c;就去调研了规则引擎。 当然&#xff0c;市面上有很多…

[unity]如何并行for循环

序 并行for循环 计算着色器里可以弄&#xff0c;但是那个得先了解一堆api&#xff0c;比如什么setBuffer unity 的 job system好像也可以弄&#xff0c;但是那个也得先了解一堆api 这些都是大而全的&#xff0c;有没有那种&#xff0c;没那么神通广大但是比较容易上手的&am…

【CocosCreator入门】CocosCreator组件 | TiledTile(地图块)组件

&#x1f4e2;博客主页&#xff1a;肩匣与橘&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由肩匣与橘编写&#xff0c;首发于CSDN&#x1f649;&#x1f4e2;生活依旧是美好而又温柔的&#xff0c;你也是✨ …

HIve技术详解(一)

第1章 Hive基本概念 1.1 Hive 1.1.1 Hive的产生背景 在那一年的大数据开源社区&#xff0c;我们有了HDFS来存储海量数据、MapReduce来对海量数据进行分布式并行计算、Yarn来实现资源管理和作业调度。但是面对海量数据和负责的业务逻辑&#xff0c;开发人员要编写MR来对数据进…

3.3 最长公共子序列

博主简介&#xff1a;一个爱打游戏的计算机专业学生博主主页&#xff1a; 夏驰和徐策所属专栏&#xff1a;算法设计与分析 1.什么是子序列&#xff1f; 我的理解&#xff1a; 在字符串或序列中&#xff0c;子序列是指从原始序列中删除零个或多个元素后得到的序列&#xff0c;…

Spring Boot如何实现分布式事务的协调和管理

Spring Boot如何实现分布式事务的协调和管理 在分布式系统中&#xff0c;事务是非常重要的一部分&#xff0c;可以保证多个操作在一个原子性的操作中完成&#xff0c;确保数据的一致性和可靠性。在分布式系统中&#xff0c;分布式事务需要考虑多个服务之间的数据一致性和事务提…

论文排版!

目录 Visio画图后&#xff0c;粘贴到word白边太宽&#xff1f; 【IEEE论文投稿word中双栏情况下插入单栏效果图片】 论文排版之Word双栏排版问题解决 Word公式居中&#xff0c;公式序号靠右&#xff08;制表位实现&#xff09; 请问word如何实现这种长公式的排版&#xff1…

MVCC 实现原理

&#x1f49f;这里是CS大白话专场&#xff0c;让枯燥的学习变得有趣&#xff01; &#x1f49f;没有对象不要怕&#xff0c;我们new一个出来&#xff0c;每天对ta说不尽情话&#xff01; &#x1f49f;好记性不如烂键盘&#xff0c;自己总结不如收藏别人&#xff01; &#x1f…

Pycharm 安装PyQt5

第一步: 新建项目文件夹 新建项目 新建一个 Pyqt5Tools 的文件夹 这里放到了 D盘 安装成功 第二步: 安装相关包 安装PyQt5 pip3 install -i https://pypi.douban.com/simple PyQt5,PyQt5-tools时间根据网速 更新下pip python.exe -m pip install --upgrade pip -i https:…

tensorRT推理相关及遇到的坑

tebsorRT是什么 tensorRT是NVIDIA出的一个高性能深度学习推理&#xff08;inference&#xff09;优化器&#xff0c;可以为深度学习应用提供低延迟、高吞吐率的部署推理。TensorRT可用于对超大规模数据中心、嵌入式平台或自动驾驶平台进行推理加速。TensorRT现已能支持TensorF…

数据库隔离级别

1. 数据库隔离级别 1.1 事务 事务只是一个改变&#xff0c;是一些操作的集合&#xff1b;用专业的术语讲&#xff0c;他就是一个程序的执行单元&#xff1b;事务本身其实并不包含这4个特性&#xff0c;只是我们需要通过某些手段&#xff0c;尽可能的让这个执行单元满足这四个特…

Java学习路线(20)——多线程

一、线程&#xff08;Thread&#xff09; 1、概念&#xff1a; 是一个程序内部的一条执行路径 2、分类 单线程&#xff1a; 程序中只有一条执行路径多线程&#xff1a; 程序中有多条执行路径 二、多线程的创建 1、Thread的概念&#xff1a; Java通过java.lang.Thread类代表…

HTTP 教程2

HTTP 消息结构 HTTP是基于客户端/服务端&#xff08;C/S&#xff09;的架构模型&#xff0c;通过一个可靠的链接来交换信息&#xff0c;是一个无状态的请求/响应协议。 一个HTTP"客户端"是一个应用程序&#xff08;Web浏览器或其他任何客户端&#xff09;&#xff…