当前位置: 首页 > article >正文

QGC地图界面自定义数据面板开发实战

1. 理解QGC地图界面自定义数据面板的需求第一次接触QGroundControlQGC地图界面自定义数据面板开发时我完全被各种技术术语绕晕了。后来在实际项目中才发现这个功能对于无人机开发者来说简直是刚需。想象一下你正在开发一个农业植保无人机除了常规的飞行高度、速度外还需要实时显示喷洒量、作业面积等专业数据。这时候默认的QGC界面就显得力不从心了。QGC的地图界面默认显示的是基础飞行数据比如高度、速度、GPS信息等。但实际业务中我们往往需要展示更多自定义数据。比如环境监测无人机需要显示PM2.5、温湿度等传感器数据测绘无人机需要实时显示拍摄张数、覆盖面积物流无人机需要展示货物重量、配送状态这些需求都需要我们扩展QGC的地图数据显示能力。好消息是QGC提供了完善的扩展机制允许开发者通过FactGroup体系添加自定义数据。我去年给一个光伏巡检项目做开发时就成功实现了组件温度、缺陷数量等专业数据的实时展示。2. 搭建开发环境与基础准备工欲善其事必先利其器。在开始编码前我们需要准备好开发环境。根据我的经验最稳定的组合是Ubuntu 18.04 LTS20.04也行但需要处理更多依赖问题Qt 5.13.2开发套件QGC 4.1.16源码安装Qt时有个小技巧建议使用官方在线安装器勾选以下组件Qt 5.13.2 → Desktop gcc 64-bitQt ChartsQt Quick 2D Renderer我第一次搭建环境时因为漏装了Qt Charts导致编译时各种奇怪的链接错误。后来发现QGC的很多可视化组件都依赖这个模块。另外建议预留至少30GB磁盘空间因为Qt和QGC的编译会产生大量中间文件。获取QGC源码后先别急着修改。我建议先尝试编译原始版本确保基础环境没问题。编译命令很简单mkdir build cd build qmake ../qgroundcontrol.pro make -j$(nproc)如果编译成功你会看到生成的qgroundcontrol可执行文件。这时候运行它应该能看到完整的QGC界面。这个验证步骤很重要可以避免后续开发中遇到环境问题。3. 创建自定义FactGroup数据组FactGroup是QGC中管理数据的基本单元相当于一个数据容器。我们要显示自定义数据首先得创建自己的FactGroup。以显示四个测试数据为例我们需要创建两个文件TestInfoFactGroup.h和TestInfoFactGroup.cc。在头文件中我们定义数据结构和处理逻辑// TestInfoFactGroup.h #pragma once #include FactGroup.h #include QGCMAVLink.h class TestInfoFactGroup : public FactGroup { Q_OBJECT public: TestInfoFactGroup(QObject* parent nullptr); Q_PROPERTY(Fact* temperature READ temperature CONSTANT) Q_PROPERTY(Fact* humidity READ humidity CONSTANT) Q_PROPERTY(Fact* pressure READ pressure CONSTANT) Q_PROPERTY(Fact* airQuality READ airQuality CONSTANT) Fact* temperature() { return _temperatureFact; } Fact* humidity() { return _humidityFact; } Fact* pressure() { return _pressureFact; } Fact* airQuality() { return _airQualityFact; } void handleMessage(Vehicle* vehicle, mavlink_message_t message) override; private: Fact _temperatureFact; Fact _humidityFact; Fact _pressureFact; Fact _airQualityFact; static const char* _temperatureFactName; static const char* _humidityFactName; static const char* _pressureFactName; static const char* _airQualityFactName; };实现文件中我们需要初始化各个Fact并处理MAVLink消息// TestInfoFactGroup.cc #include TestInfoFactGroup.h #include Vehicle.h const char* TestInfoFactGroup::_temperatureFactName temperature; const char* TestInfoFactGroup::_humidityFactName humidity; const char* TestInfoFactGroup::_pressureFactName pressure; const char* TestInfoFactGroup::_airQualityFactName airQuality; TestInfoFactGroup::TestInfoFactGroup(QObject* parent) : FactGroup(1000, :/json/Vehicle/TestInfoFact.json, parent) , _temperatureFact(0, _temperatureFactName, FactMetaData::valueTypeDouble) , _humidityFact(0, _humidityFactName, FactMetaData::valueTypeDouble) , _pressureFact(0, _pressureFactName, FactMetaData::valueTypeDouble) , _airQualityFact(0, _airQualityFactName, FactMetaData::valueTypeUint32) { _addFact(_temperatureFact, _temperatureFactName); _addFact(_humidityFact, _humidityFactName); _addFact(_pressureFact, _pressureFactName); _addFact(_airQualityFact, _airQualityFactName); // 初始化默认值 _temperatureFact.setRawValue(qQNaN()); _humidityFact.setRawValue(qQNaN()); _pressureFact.setRawValue(qQNaN()); _airQualityFact.setRawValue(0); } void TestInfoFactGroup::handleMessage(Vehicle*, mavlink_message_t message) { if (message.msgid ! MAVLINK_MSG_ID_SCALED_PRESSURE) { return; } mavlink_scaled_pressure_t pressure; mavlink_msg_scaled_pressure_decode(message, pressure); temperature()-setRawValue(pressure.temperature / 100.0f); pressure()-setRawValue(pressure.press_abs); _setTelemetryAvailable(true); }这里有几个关键点需要注意Fact的valueType必须与数据类型匹配比如浮点数用valueTypeDouble整数用valueTypeUint32更新频率构造函数中的1000表示数据刷新间隔单位毫秒handleMessage方法中需要过滤和解析特定的MAVLink消息4. 集成FactGroup到QGC主框架创建好FactGroup后我们需要把它集成到QGC的主框架中。这个过程就像给房子安装新的水电线路需要找到正确的接入点。首先修改Vehicle.h添加我们的FactGroup// 在文件头部添加包含 #include TestInfoFactGroup.h // 在类定义中添加成员变量 TestInfoFactGroup _testInfoFactGroup; // 添加静态名称定义 static const char* _testInfoFactGroupName; // 添加访问方法 FactGroup* testInfoFactGroup() { return _testInfoFactGroup; } // 添加Q_PROPERTY声明 Q_PROPERTY(FactGroup* testInfo READ testInfoFactGroup CONSTANT)然后在Vehicle.cc中进行初始化// 定义静态名称 const char* Vehicle::_testInfoFactGroupName testInfo; // 在构造函数初始化列表中添加 , _testInfoFactGroup(this) // 在初始化方法中添加注册 _addFactGroup(_testInfoFactGroup, _testInfoFactGroupName);这里最容易出错的是初始化顺序。我遇到过因为初始化顺序不对导致的段错误。记住一个原则基础组件先初始化依赖组件后初始化。如果遇到崩溃问题可以检查构造函数初始化列表的顺序。最后别忘了在qgroundcontrol.pro中添加我们的源文件# 在HEADERS部分添加 HEADERS \ src/Vehicle/TestInfoFactGroup.h \ ... # 在SOURCES部分添加 SOURCES \ src/Vehicle/TestInfoFactGroup.cc \ ...5. 设计数据元信息与JSON配置QGC使用JSON文件来定义数据的显示属性这就像给数据穿衣服决定它们在前端如何展示。创建TestInfoFact.json文件{ version: 1, fileType: FactMetaData, QGC.MetaData.Facts: [ { name: temperature, shortDesc: 温度, type: double, decimalPlaces: 1, units: °C }, { name: humidity, shortDesc: 湿度, type: double, decimalPlaces: 1, units: % }, { name: pressure, shortDesc: 气压, type: double, decimalPlaces: 2, units: hPa }, { name: airQuality, shortDesc: 空气质量, type: uint32, units: AQI } ] }这个配置文件有几个关键字段name必须与代码中的Fact名称完全一致shortDesc前端显示的标签文本type数据类型与代码中的valueType对应decimalPlaces小数位数仅数值类型有效units单位符号会显示在值后面把JSON文件添加到资源系统中也很重要。打开qgroundcontrol.qrc文件添加我们的JSON文件qresource prefix/ ... file aliasVehicle/TestInfoFact.jsonsrc/Vehicle/TestInfoFact.json/file ... /qresource这里alias的路径必须与FactGroup构造函数中指定的路径一致。我遇到过因为路径大小写不一致导致找不到文件的问题在Linux环境下尤其要注意。6. 前端界面集成与数据绑定数据准备好了现在要让它们在地图界面上显示出来。QGC使用QML作为前端技术我们需要修改地图页面的QML文件。找到src/uis/Vehicle/VehicleValues.qml文件添加我们的数据显示组件// 在适当位置添加我们的数据显示项 VehicleValuesGroup { name: qsTr(环境数据) width: parent.width VehicleValuesRow { VehicleValuesColumn { FactValue { fact: vehicle.testInfo.temperature showUnits: true } Label { text: qsTr(温度) } } VehicleValuesColumn { FactValue { fact: vehicle.testInfo.humidity showUnits: true } Label { text: qsTr(湿度) } } } VehicleValuesRow { VehicleValuesColumn { FactValue { fact: vehicle.testInfo.pressure showUnits: true } Label { text: qsTr(气压) } } VehicleValuesColumn { FactValue { fact: vehicle.testInfo.airQuality showUnits: true } Label { text: qsTr(空气质量) } } } }QML的布局系统需要一些时间来适应。我的经验是VehicleValuesGroup是一个垂直容器VehicleValuesRow代表一行VehicleValuesColumn代表一行中的一列每列通常包含一个FactValue和一个Label调试QML界面时可以使用Qt Creator的QML调试器。设置环境变量QML_DEBUGtrue后启动QGC就能在Qt Creator中实时查看和修改QML属性。7. 测试与调试技巧完成代码编写后就是紧张的测试阶段了。我总结了一套有效的测试方法编译检查make clean qmake ../qgroundcontrol.pro make -j$(nproc)如果编译失败重点关注头文件包含是否正确初始化顺序是否合理是否有拼写错误运行时测试启动QGC并连接飞控或模拟器在地图界面检查自定义数据是否显示发送测试MAVLink消息验证数据更新常见问题排查数据不显示检查JSON文件路径是否正确Q_PROPERTY声明是否完整数据显示NaN检查handleMessage是否被调用数据解析是否正确界面布局错乱检查QML层次结构确保宽度设置合理一个实用的调试技巧是在代码中添加qDebug()输出qDebug() 收到MAVLink消息msgid: message.msgid;可以在启动QGC时加上参数查看日志./qgroundcontrol --logging:full8. 进阶优化与扩展思路基础功能实现后可以考虑进一步优化数据持久化// 在FactGroup中添加保存/加载方法 void saveToSettings(QSettings settings); void loadFromSettings(QSettings settings);动态数据更新// 使用ChartView实现实时曲线 ChartView { LineSeries { name: 温度变化 axisX: ValueAxis { min: 0; max: 100 } axisY: ValueAxis { min: -20; max: 50 } // 动态添加数据点 } }多语言支持{ shortDesc: { en: Temperature, zh: 温度 } }性能优化合理设置更新频率避免不必要的重绘使用Qt的模型/视图框架处理大量数据考虑使用OpenGL加速图形渲染在实际项目中我还遇到过需要动态显示/隐藏某些数据的需求。这可以通过QML的visible属性和Fact的可用性状态来实现FactValue { fact: vehicle.testInfo.temperature visible: fact.available }

相关文章:

QGC地图界面自定义数据面板开发实战

1. 理解QGC地图界面自定义数据面板的需求 第一次接触QGroundControl(QGC)地图界面自定义数据面板开发时,我完全被各种技术术语绕晕了。后来在实际项目中才发现,这个功能对于无人机开发者来说简直是刚需。想象一下,你正…...

CVAE实战:用PyTorch实现条件变分自编码器生成多风格人脸(附完整代码)

CVAE实战:用PyTorch实现条件变分自编码器生成多风格人脸(附完整代码) 在计算机视觉领域,生成多样化的人脸图像一直是个有趣且具有挑战性的任务。传统VAE虽然能生成人脸,但往往缺乏对生成结果风格的控制。想象一下&…...

VEGA_BMI088库详解:嵌入式六轴IMU硬件同步与鲁棒驱动开发

1. VEGA_BMI088库深度解析:面向嵌入式系统的高鲁棒性六轴IMU驱动开发指南1.1 BMI088芯片架构与工程价值定位Bosch Sensortec BMI088并非传统意义上的简单传感器,而是一款专为严苛动态环境设计的系统级封装(SiP)惯性测量单元。其核…...

Jimeng LoRA在C语言教学中的应用:智能代码分析与指导

Jimeng LoRA在C语言教学中的应用:智能代码分析与指导 1. 引言 C语言作为计算机科学教育的基石,一直是编程入门教学的重点和难点。传统的C语言教学面临着诸多挑战:学生代码错误五花八门,教师批改工作量巨大;个性化指导…...

麦橘超然Flux本地部署全攻略:环境配置到生成第一张图

麦橘超然Flux本地部署全攻略:环境配置到生成第一张图 你是否曾对AI绘画跃跃欲试,却被复杂的部署流程、庞大的模型下载和苛刻的硬件要求劝退?有没有一种方案,能让普通玩家也能在自己的电脑上,快速体验当前最先进的图像…...

py每日spider案例之网yiyun搜索接口

import requests url=https://api.s0o1.com/API/wyy_music?msg=唯一 response=requests.get(url) for item in response.json().get(data...

CS5490电能计量芯片UART驱动与校准实战指南

1. CS5490电能计量芯片驱动库技术解析与嵌入式工程实践CS5490是Cirrus Logic公司推出的高精度单相电能计量SoC芯片,集成ΔΣ模数转换器、数字信号处理器(DSP)、电压/电流通道增益校准电路、温度传感器及UART通信接口。该芯片专为智能电表、能…...

音乐教育新工具:AcousticSense AI实战,辅助音乐风格教学

音乐教育新工具:AcousticSense AI实战,辅助音乐风格教学 1. 音乐教学中的风格识别挑战 1.1 传统音乐教学的痛点 在音乐教育领域,风格识别一直是教学难点。传统方式依赖教师个人经验,通过反复播放示范曲目让学生感受不同风格特点…...

【PCIE709-F】基于复旦微JFM7VX690T80 FPGA的全国产化多通道光纤数据处理平台在雷达信号处理中的应用

1. PCIE709-F板卡的核心优势解析 第一次接触PCIE709-F板卡是在去年参与某型雷达系统升级项目时,当时我们需要处理8通道光纤传来的实时雷达数据,传统方案遇到严重的带宽瓶颈。这款基于复旦微JFM7VX690T80 FPGA的全国产化平台,最让我印象深刻的…...

Simulink 电机控制之单电阻采样三相电流重构算法仿真总结

Simulink 电机控制:单电阻采样三相电流重构算法仿真总结。 采用移相方法,另外还有别的电流重构算法,单电阻采样,脉冲插入法在电机控制领域,单电阻采样三相电流重构算法因其成本效益高而备受关注。今天就来和大家唠唠在…...

VLC播放RTSP流常见问题及解决方案

1. VLC播放RTSP流的基础操作指南 RTSP(Real Time Streaming Protocol)是一种广泛应用于监控摄像头、视频会议系统等场景的流媒体传输协议。作为一款开源跨平台的播放器,VLC对RTSP协议有着良好的支持。先说说最基本的操作流程,这对…...

重构黑苹果配置逻辑:OpCore-Simplify驱动的AMD平台EFI制作技术突破

重构黑苹果配置逻辑:OpCore-Simplify驱动的AMD平台EFI制作技术突破 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 在x86架构与Apple生态的…...

Realistic Vision V5.1镜像免配置特性:Streamlit界面开箱即用无需conda环境

Realistic Vision V5.1镜像免配置特性:Streamlit界面开箱即用无需conda环境 1. 项目概述 Realistic Vision V5.1虚拟摄影棚是一款基于Stable Diffusion 1.5生态顶级写实模型开发的本地化工具。这个解决方案最大的特点就是完全免配置,无需搭建conda环境…...

Google TranslateGemma:27B多语言图文翻译新体验

Google TranslateGemma:27B多语言图文翻译新体验 【免费下载链接】translategemma-27b-it 项目地址: https://ai.gitcode.com/hf_mirrors/google/translategemma-27b-it 导语:Google推出基于Gemma 3架构的TranslateGemma-27B-IT模型,…...

狂卷AI熬过生死关,小鹏的阳谋已成?

点击下方卡片,关注“自动驾驶之心”公众号戳我-> 领取自动驾驶近30个方向学习路线作者 | 自动驾驶之心团队编辑 | 自动驾驶之心>>自动驾驶前沿信息获取→自动驾驶之心知识星球2026年的早春,空气里还透着些许寒意,车市的价格硝烟还未…...

OE无人船:事件触发下的非线性模型预测控制

OE 无人船 事件触发 非线性模型预测控制站在甲板上盯着OE无人船的实时轨迹曲线,手里的冰美式已经见底。这玩意儿在复杂海况下的控制响应总带着点玄学味道——传统周期采样控制就像拿着菜刀切牛排,既浪费算力又不够优雅。今天咱们试试事件触发机制NMPC的暴…...

Qwen2.5-0.5B Instruct法律文书生成:合同条款智能起草

Qwen2.5-0.5B Instruct法律文书生成:合同条款智能起草 1. 引言:法律文书起草的智能化变革 想象一下这样的场景:一位法务专员需要在短时间内起草一份复杂的商业合同,面对密密麻麻的法律条款和格式要求,常常需要花费数…...

AMT102磁性编码器驱动设计与实时角度反馈实现

1. AMT102编码器驱动技术解析:面向嵌入式实时控制的高精度角度反馈实现1.1 器件定位与工程价值AMT102是CUI Devices公司推出的单圈绝对值磁性编码器模块,采用霍尔效应传感原理,通过内置ASIC对旋转磁场进行数字化解码,输出标准SPI或…...

基于 PLC1200 的自动化流水线设计探索

基于plc1200自动化流水线设计 TIA Portal V15.1中的PLC1200和HMI_1[TP1200 Comfort]组态环境联机仿真运行系统(不用实物PLC)入下图: 1、有TIA Portal V15.1的设计程序; 2、有相应的HMI组态控制界面; 3、有相应的参考设…...

Steam七天交易锁,CS2饰品商人的资金周转困局与实战应对策略

Steam七天交易锁:CS2饰品商人的资金周转困局与实战应对策略 当Steam平台在7月15日突然宣布实施"七天交易保护"新规时,整个CS2饰品交易市场仿佛被按下了暂停键。对于依赖快速周转获利的饰品商人来说,这不仅仅是一次规则调整&#x…...

二十五. 智能驾驶之基于点云分割与聚类的实时障碍物检测优化

1. 智能驾驶中的障碍物检测技术概览 在智能驾驶系统中,障碍物检测是最基础也是最重要的功能之一。想象一下,当你在高速公路上以120km/h的速度行驶时,系统需要在毫秒级别内识别出前方突然出现的障碍物并做出反应。这就像要求一个超级运动员在0…...

Web安全入门:如何用Burp Suite检测和防御弱口令漏洞(附实战案例)

Web安全实战:Burp Suite弱口令检测与防御全指南 弱口令漏洞就像给家门装了一把塑料锁——看似有防护,实则一捅就破。作为Web安全领域最常见也最危险的漏洞之一,弱口令每年导致数百万账户被盗。本文将带您深入实战,从零掌握使用Bur…...

AMD移动CPU功耗控制全攻略:RyzenAdj命令行参数详解与Python自动化脚本

AMD移动CPU功耗控制全攻略:RyzenAdj命令行参数详解与Python自动化脚本 1. 理解RyzenAdj的核心价值 对于追求极致性能与能效平衡的技术用户来说,AMD Ryzen移动处理器的功耗管理一直是个值得深入研究的课题。不同于桌面平台,移动版Ryzen处理器在…...

造相 Z-Image 应用场景:IP形象延展设计|从线稿到多风格角色图生成

造相 Z-Image 应用场景:IP形象延展设计|从线稿到多风格角色图生成 1. 引言:IP形象设计的痛点与解决方案 IP形象设计是品牌建设和内容创作中的重要环节,但传统设计流程存在诸多痛点。设计师需要从线稿开始,反复修改配…...

2025国内Docker镜像加速全攻略:精选源与配置实战

1. 为什么需要Docker镜像加速? 如果你在国内使用Docker拉取镜像时经常遇到速度慢、超时甚至失败的情况,这很正常。由于网络环境的特殊性,直接连接Docker官方仓库(Docker Hub)往往会遇到各种问题。我刚开始用Docker时&a…...

5种主流实名认证API接口实战对比:从三网手机核验到活体人脸识别H5

5种主流实名认证API接口深度评测与技术实现指南 在金融科技和互联网产品高速发展的今天,用户身份核验已成为各类应用的基础设施。从简单的手机号验证到复杂的生物特征识别,开发者需要根据业务场景选择最适合的认证方案。本文将深入剖析五种主流实名认证A…...

艾尔登法环 d3d11.dll 错误修复教程:不重装系统无损存档

正在加载游戏,结果屏幕一弹窗,赫然写着“1.dll”找不到或者有问题,游戏瞬间关闭。别慌,这通常不是显卡坏了,也不是存档没了,而是Windows系统里负责图形显示的一个关键文件出了问题。我们完全不需要重装系统…...

WuliArt Qwen-Image Turbo镜像优势解析:免编译、免依赖、开箱即用设计哲学

WuliArt Qwen-Image Turbo镜像优势解析:免编译、免依赖、开箱即用设计哲学 1. 项目概述 WuliArt Qwen-Image Turbo是一个专为个人GPU环境设计的轻量级文本生成图像系统。这个镜像基于阿里通义千问的Qwen-Image-2512文生图底座,深度融合了Wuli-Art专属的…...

多线程环境下malloc死锁的5种常见场景及避坑指南(含__lll_lock_wait_private分析)

多线程环境下malloc死锁的深度解析与实战规避策略 引言:当内存分配遇上并发陷阱 在现代C/C高性能编程中,内存管理就像高空走钢丝——既要保证效率,又要维持平衡。而malloc作为基础的内存分配函数,在多线程环境下的行为却暗藏杀机…...

StarUML实战:手把手教你绘制电商系统数据流图(含常见错误排查)

StarUML实战:手把手教你绘制电商系统数据流图(含常见错误排查) 在软件工程领域,数据流图(Data Flow Diagram, DFD)是系统分析阶段不可或缺的工具。对于电商系统这类复杂业务场景,清晰的数据流图…...