QGC 固件升级与硬件适配7.0 总体架构QGC 4.0 将「固件烧录」与「运行时硬件/协议适配」分为两条相对独立的链路┌─────────────────────────────────────────────────────────────────┐ │ 离线烧录链路USB 串口 │ │ FirmwareUpgrade.qml → FirmwareUpgradeController │ │ → PX4FirmwareUpgradeThread → Bootloader → QSerialPort │ └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ │ 在线运行链路MAVLink 连接后 │ │ MultiVehicleManager → Vehicle │ │ → FirmwarePluginManager → FirmwarePluginPX4/APM/Generic│ │ → AutoPilotPlugin → VehicleComponent[]传感器/机架/电台… │ │ → ParameterManager *ParameterMetaData │ └─────────────────────────────────────────────────────────────────┘设计原则FirmwarePlugin飞行栈PX4 / ArduPilot相关的全部差异逻辑应集中在此AutoPilotPluginVehicleComponentSetup 向导、传感器校准、机架选择等 UI/参数逻辑Vehicle与MissionManager等保持MAVLink 通用差异通过 Plugin 钩子注入涉及的主要设计模式模式体现Plugin 模式FirmwarePlugin/AutoPilotPlugin抽象飞行栈差异Factory 注册表FirmwarePluginFactory构造时自注册到FirmwarePluginFactoryRegisterSingleton懒加载各 Factory 内_pluginInstance单例复用MVCFirmwareUpgradeControllerCFirmwareUpgrade.qmlViewWorker ThreadPX4FirmwareUpgradeThreadController在独立线程执行串口 I/OStrategy按 URI/板型/协议选择不同固件 URL、Bootloader 命令集Template MethodVehicleComponent定义 setup 流程骨架子类实现具体 QML/参数AdapteradjustIncomingMavlinkMessage修正 APM 与标准 MAVLink 差异Hash Map 配置_rgFMUV5Firmware等 boardId → URL 映射表涉及语法与技术CQObject、Q_PROPERTY、Q_INVOKABLE、Q_ENUM、signals/slotsQt SerialQSerialPort、QSerialPortInfoJSON/XMLQJsonDocument.px4/.apj/manifest、QXmlStreamReader参数元数据Intel Hex.ihx解析SiK RadioMAVLinkmavlink_message_t、MAV_AUTOPILOT、MAV_TYPEQMLSetupPage、FirmwareUpgradeController注册为QGroundControl.Controllers7.1 飞控固件烧录流程开发7.1.1 模块与文件索引文件职责VehicleSetup/FirmwareUpgrade.qml固件升级 UISetup → FirmwareVehicleSetup/FirmwareUpgradeController.h/.ccMVC 控制器选固件、下载、调度烧录VehicleSetup/PX4FirmwareUpgradeThread.h/.cc独立线程找板、同步 Bootloader、擦除/编程/校验VehicleSetup/Bootloader.h/.ccPX4 Bootloader 二进制协议实现VehicleSetup/FirmwareImage.h/.cc固件镜像解析.bin/.px4/.apj/.ihxcomm/QGCSerialPortInfo.h/.ccUSB VID/PID 识别板型comm/USBBoardInfo.json板型 VID/PID 配置表Settings/FirmwareUpgradeSettings.*APM ChibiOS、机型偏好等7.1.2 用户操作流程状态机Plug USB → startBoardSearch() → 扫描串口 (canFlash) → 发现板 (foundBoard) → UI 显示板名 → 用户选 Stack(PX4/APM) 版本(Stable/Beta/Dev) 机型 → flash() → 等待 Bootloader (foundBootloader) → 解析 board_id / flash_size → 查 Hash 得固件 URL → QGCFileDownload 下载 → FirmwareImage::load() 校验 board_id、解压元数据 → ThreadController::flash() → erase → program → verify → reboot → flashComplete → 恢复 LinkManager 连接入口startBoardSearch()关键行为void FirmwareUpgradeController::startBoardSearch(void) { LinkManager* linkMgr qgcApp()-toolbox()-linkManager(); linkMgr-setConnectionsSuspended(tr(Connect not allowed during Firmware Upgrade.)); ... _threadController-startFindBoardLoop(); }烧录期间禁止新建 MAVLink 连接避免与 Bootloader 串口冲突。7.1.3 USB 板型识别QGCSerialPortInfo::getBoardInfo()读取:/json/USBBoardInfo.jsonboardInfo: [ { vendorID: 9900, productID: 16, boardClass: Pixhawk, name: PX4 FMU V1 }, { vendorID: 9900, productID: 17, boardClass: Pixhawk, name: PX4 FMU V2 }, ... { vendorID: 9900, productID: 50, boardClass: Pixhawk, name: PX4 FMU V5 },匹配逻辑先VIDPID失败则description/manufacturer 正则 fallback。canFlash()仅对三类板返回 truebool QGCSerialPortInfo::canFlash(void) const { ... switch(boardType){ case QGCSerialPortInfo::BoardTypePixhawk: case QGCSerialPortInfo::BoardTypePX4Flow: case QGCSerialPortInfo::BoardTypeSiKRadio: return true;新增可烧录硬件的第一步在USBBoardInfo.json增加 VID/PID 条目并在Bootloader.h增加boardID*常量若为新 PX4 板型。7.1.4 Bootloader 通信协议Bootloader类实现 PX4 官方 Bootloader 协议也用于 3DR Radio 变体协议字节节选符号值含义PROTO_INSYNC0x12同步前缀PROTO_EOC0x20命令结束PROTO_OK/PROTO_FAILED0x10 / 0x11响应PROTO_GET_SYNC0x21建立同步PROTO_CHIP_ERASE0x23全片擦除PROTO_PROG_MULTI0x27多块写入最大 64 字节4 字节对齐PROTO_GET_CRC0x29CRC 校验Bootloader ≥3PROTO_BOOT0x30重启进应用烧录核心循环.bin格式while (bytesSent imageSize) { ... if (_write(port, PROTO_PROG_MULTI)) { if (_write(port, (uint8_t)bytesToSend)) { if (_write(port, imageBuf, bytesToSend)) { if (_write(port, PROTO_EOC)) { if (_getCommandResponse(port)) { failed false; } } } } } ... _imageCRC QGC::crc32((uint8_t *)imageBuf, bytesToSend, _imageCRC); emit updateProgress(bytesSent, imageSize); }校验策略Bootloader ≤2 或.ihx逐字节PROTO_READ_MULTI回读比对Bootloader ≥3 且.binPROTO_GET_CRC与预计算 CRC 比较完成后reboot()发送PROTO_BOOTBoard ID 常量与固件包内board_id对应static const int boardIDPX4FMUV2 9; static const int boardIDPX4FMUV4 11; static const int boardIDPX4FMUV5 50; static const int boardIDPX4FMUV3 255; // V2 大 Flash 模拟 ID static const int boardIDDurandalV1 139; ...7.1.5 独立线程 WorkerPX4FirmwareUpgradeThreadController将耗时串口操作移出 UI 线程Controller (主线程) Worker (子线程) startFindBoardLoop ──signal──► _findBoardOnce() flash(image) ──signal──► _flash(): erase→program→verify cancel ──signal──► 关闭端口 ◄── foundBootloader / updateProgress / flashComplete找 Bootloader 流程枚举QGCSerialPortInfo::availablePorts()过滤canFlash()首次发现 emitfoundBoardUI 等待用户确认/选固件第二次循环非 firstAttempt打开串口 →Bootloader::sync()→getPX4BoardInfo()读INFO_BL_REV / INFO_BOARD_ID / INFO_FLASH_SIZESiK Radio 特殊路径先发/ATUPDATE强制进 Bootloader完整烧录_flash()if (_erase()) { if (_bootloader-program(_bootloaderPort, _controller-image())) { ... } if (_bootloader-verify(_bootloaderPort, _controller-image())) { ... } } emit _reboot(); emit flashComplete();7.1.6 固件镜像格式FirmwareImage扩展名格式用途.bin原始二进制直接编程.px4JSON 包装PX4 传统含 base64 镜像 压缩 parameter/airframe XML.apjJSON 包装ArduPilot ChibiOS同.px4结构MAV_AUTOPILOTAPM.ihxIntel Hex3DR SiK Radio.px4/.apj加载流程QJsonDocument doc QJsonDocument::fromJson(bytes); ... uint32_t firmwareBoardId (uint32_t)px4Json.value(_jsonBoardIdKey).toInt(); if (!isCompatible(_boardId, firmwareBoardId)) { emit statusMessage(...); return false; }兼容规则示例FMUv3board_id255可烧 FMUv2id9固件AUAV X2.1 同理。解压后的parameter XML写入缓存并注册到ParameterManager::cacheMetaDataFile()使烧录后 Setup 界面立即可用最新参数元数据无需等飞控在线。7.1.7 固件 URL 来源1PX4 静态 Hash 表_initFirmwareHash()为每块板维护QHashFirmwareIdentifier, QStringKeyAutoPilotStackTypeFirmwareBuildTypeFirmwareVehicleTypeValueS3 URL如http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v5_default.px4FMUv2/V3/V4/V5、Durandal、KakuteF7 等各有独立 Hash。2PX4 GitHub Releases 动态版本_determinePX4StableVersion()拉取https://api.github.com/repos/PX4/Firmware/releases解析 stable/beta 标签。3ArduPilot manifest.jsonvoid FirmwareUpgradeController::_downloadArduPilotManifest(void) { ... downloader-download(QStringLiteral(http://firmware.ardupilot.org/manifest.json)); }解析字段board_id、mav-type、url、mav-firmware-version-type、USBID、bootloader_str、brand_name等动态构建_rgManifestFirmwareInfo供 ChibiOS 板按名称列表选择固件。4SingleFirmwareModeCustom 构建可通过QGCOptions::firmwareUpgradeSingleURL()指定单一 URL跳过用户选择。7.1.8 Controller 与 QML 绑定FirmwareUpgradeController暴露给 QML 的属性示例boardPort/boardDescription/pixhawkBoardselectedFirmwareBuildTypeStable/Beta/Dev/CustomapmFirmwareNames/apmFirmwareUrlsAPM manifest 动态列表progressBar/statusLogQQuickItem 指针C 直接setProperty(value, ...)QML 调用FirmwareUpgradeController { onFlashComplete: ... } // Q_INVOKABLE: controller.startBoardSearch() controller.flash(AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware)7.1.9 扩展烧录流程的开发指南若需支持新 Bootloader 协议或新文件格式扩展FirmwareImage::load()增加解析分支在Bootloader中实现新命令集或新建XxxBootloader类修改PX4FirmwareUpgradeThreadWorker::_findBootloader()的打开/同步逻辑在FirmwareUpgradeController::_initFirmwareHash()或 manifest 解析处增加 URL更新USBBoardInfo.json与Bootloader::boardID*常量若仅需支持新 PX4 兼容板沿用 PX4 Bootloader通常只需 JSON Hash URL无需改协议代码。7.2 新增机型、外设传感器适配7.2.1 运行时对象模型Vehicle 创建 └─ _firmwarePlugin FirmwarePluginManager::firmwarePluginForAutopilot(type, mavType) └─ _firmwarePlugin-initializeVehicle(this) └─ ParameterManager 就绪后 └─ AutoPilotPlugin::vehicleComponents() └─ AirframeComponent / SensorsComponent / RadioComponent / ... └─ 各 Component 绑定 setup QML Fact 参数名Vehicle 中获取 Pluginvoid Vehicle::_commonInit() { _firmwarePlugin _firmwarePluginManager-firmwarePluginForAutopilot(_firmwareType, _vehicleType);7.2.2 FirmwarePluginFactory 注册机制全局静态 Factory 对象在构造时自注册FirmwarePluginFactory::FirmwarePluginFactory(void) { FirmwarePluginFactoryRegister::instance()-registerPluginFactory(this); }PX4 FactoryQListMAV_AUTOPILOT PX4FirmwarePluginFactory::supportedFirmwareTypes(void) const { list.append(MAV_AUTOPILOT_PX4);APM Factory按 MAV_TYPE 分派switch (vehicleType) { case MAV_TYPE_QUADROTOR: case MAV_TYPE_HELICOPTER: return _arduCopterPluginInstance; case MAV_TYPE_FIXED_WING: case MAV_TYPE_VTOL_QUADROTOR: return _arduPlanePluginInstance; case MAV_TYPE_GROUND_ROVER: return _arduRoverPluginInstance; case MAV_TYPE_SUBMARINE: return _arduSubPluginInstance;新增「机型」在 QGC 语义下通常指新的MAV_TYPE组合 → 新建或扩展ArduXxxFirmwarePlugin新的机架/airframe→ PX4AirframeComponentPX4AirframeLoaderXML新的Setup 步骤/外设→ 新建VehicleComponent子类7.2.3 AutoPilotPlugin 与 VehicleComponentVehicleComponent 抽象接口virtual QString name(void) const 0; virtual bool requiresSetup(void) const 0; virtual bool setupComplete(void) const 0; virtual QUrl setupSource(void) const 0; // 完整 Setup 面板 QML virtual QUrl summaryQmlSource(void) const 0; // 摘要卡片 QML virtual QStringList setupCompleteChangedTriggerList(void) const 0;PX4 Setup 组件列表示例Component职责关键参数 FactAirframeComponent机架/机型选择SYS_AUTOSTART,SYS_AUTOCONFIGSensorsComponentIMU/罗盘/气压计/空速计校准CAL_*,SENS_*PX4RadioComponent遥控校准RC_*FlightModesComponent飞行模式映射RC_MAP_*PowerComponent电池/电源BAT_*MotorComponent电机测试PWM_*SafetyComponent返航/地理围栏RTL_*,GF_*PX4TuningComponentPID 调参各控制器增益APM 对应APMSensorsComponent、APMAirframeComponent、APMMotorComponent、APMSubFrameComponentROV 框架、APMLightsComponent等。7.2.4 新增外设/传感器适配步骤PX4 为例步骤 1确认参数名与校准命令PX4 传感器校准通过 MAVLinkMAV_CMD_PREFLIGHT_CALIBRATION或参数读写完成QGCSensorsComponent的 QML 触发 C 发送命令。新传感器需确认固件暴露的参数名如SENS_EN_XXX和校准流程。步骤 2扩展 SensorsComponent修改setupCompleteChangedTriggerList()增加新参数在setupComplete()中检查校准状态参数如CAL_ACC0_ID非零表示已校准在SensorsSetup.qml或对应 QML增加 UI 入口步骤 3参数元数据Parameter MetaDataPX4 使用 XML 描述参数短名、单位、枚举、增量void loadParameterFactMetaDataFile (const QString metaDataFile); FactMetaData* getMetaDataForFact (const QString name, MAV_TYPE vehicleType); void addMetaDataToFact (Fact* fact, MAV_TYPE vehicleType);元数据来源飞控在线ParameterManager向飞控请求离线/烧录后.px4包内parameter_xml解压缓存内置编译资源:/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml新增参数 UI 显示在固件 Parameter XML 中加入定义即可被 Fact 系统自动识别若需特殊控件扩展FactMetaData的enumStrings或自定义 QML FactControl。步骤 4机架/Airframe 元数据PX4AutoPilotPlugin构造时_airframeFacts new PX4AirframeLoader(this, _vehicle-uas(), this); PX4AirframeLoader::loadAirframeMetaData();Airframe XML 定义SYS_AUTOSTARTID 与机型名称映射。新增 PX4 机架需在 PX4 固件侧airframes/添加QGC 通过烧录包或在线同步 XML 自动更新列表。步骤 5FactGroup 扩展遥测显示新传感器若通过 MAVLink 消息上报非参数在Vehicle或专用XxxFactGroup中解析消息并暴露Fact供 Fly 视图仪表板使用。例如_distanceSensorFactGroup、_battery1FactGroup。7.2.5 APM 传感器与机型差异APM 的APMAutoPilotPlugin::vehicleComponents()按vehicleType 参数存在性动态组装直升机APMHeliComponent潜水器APMSubFrameComponent、APMLightsComponent相机APMCameraComponent检测CAM1_TYPE等ESP8266 WiFiESP8266Componentif ( _vehicle-supportsRadio() ) { _radioComponent new APMRadioComponent(_vehicle, this);supportsRadio()来自FirmwarePlugin::supportsRadio()虚函数可按机型关闭 RC Setup。7.2.6 USB 外设自动连接LinkManager扫描串口时调用QGCSerialPortInfo::getBoardInfo()对 RTK GPS、SiK Radio 等可自动创建连接。新增 USB 外设类型在USBBoardInfo.json增加boardClass如RTK GPS在LinkManager自动连接逻辑中增加对应处理7.2.7 Custom 定制示例custom-example/展示最小定制路径QListMAV_AUTOPILOT CustomFirmwarePluginFactory::supportedFirmwareTypes() const { list.append(MAV_AUTOPILOT_PX4);继承PX4FirmwarePlugin/PX4AutoPilotPluginOverride 飞行模式、任务命令、Setup 组件列表无需 fork 整个 QGC。7.2.8 新增机型适配检查清单层次修改位置说明USB 识别USBBoardInfo.jsonVID/PID → 板名烧录Bootloader.hboard ID Firmware Hash固件 URL协议XxxFirmwarePlugin飞行模式、GUIDED、任务SetupVehicleComponent QML校准/配置 UI参数PX4/APM Parameter XML名称/单位/枚举机架Airframe XMLSYS_AUTOSTART任务MavCmdInfo*.json航线命令 UI连接LinkManager自动连接规则7.3 不同飞控协议兼容改造QGC 4.0 核心 MAVLink 处理保持栈无关协议差异通过 FirmwarePlugin 钩子消化。7.3.1 插件选择与 FallbackFirmwarePlugin* FirmwarePluginManager::firmwarePluginForAutopilot(MAV_AUTOPILOT firmwareType, MAV_TYPE vehicleType) { FirmwarePluginFactory* factory _findPluginFactory(firmwareType); if (factory) { plugin factory-firmwarePluginForAutopilot(firmwareType, vehicleType); } if (!plugin) { if (!_genericFirmwarePlugin) { _genericFirmwarePlugin new FirmwarePlugin; } plugin _genericFirmwarePlugin; } return plugin; }未知 Autopilot 回退Generic FirmwarePlugin提供基础 MAVLink 能力无 PX4/APM 特有 Guided 等功能。7.3.2 MAVLink 消息适配钩子Vehicle 收消息前if (!_firmwarePlugin-adjustIncomingMavlinkMessage(this, message)) {返回false则丢弃该消息用于过滤重复 STATUSTEXT 等。Vehicle 发消息前_firmwarePlugin-adjustOutgoingMavlinkMessage(this, link, message);APM 入站适配典型bool APMFirmwarePlugin::adjustIncomingMavlinkMessage(Vehicle* vehicle, mavlink_message_t* message) { if (message-msgid MAVLINK_MSG_ID_HEARTBEAT) { _handleIncomingHeartbeat(vehicle, message); return true; } if (_ardupilotComponentMap[vehicle-id()][message-compid]) { switch (message-msgid) { case MAVLINK_MSG_ID_PARAM_VALUE: _handleIncomingParamValue(vehicle, message); break; case MAVLINK_MSG_ID_STATUSTEXT: return _handleIncomingStatusText(vehicle, message, false); ... } } return true; }APM 兼容要点组件识别通过 HEARTBEAT 的autopilot字段维护_ardupilotComponentMap仅对 ArduPilot 组件做方言转换STATUSTEXT 严重级别旧版 APM 使用非标准 severity 编码_adjustSeverity()映射到 MAV_SEVERITY 标准值PARAM_VALUE参数名可能带后缀或索引差异_handleIncomingParamValue规范化RC_CHANNELS vs RC_CHANNELS_RAW合并处理不同版本消息出站 PARAM_SET_handleOutgoingParamSet处理 APM 参数名/类型差异PX4 入站适配bool PX4FirmwarePlugin::adjustIncomingMavlinkMessage(Vehicle* vehicle, mavlink_message_t* message) { if (message-compid MAV_COMP_ID_UDP_BRIDGE) { return true; } switch (message-msgid) { case MAVLINK_MSG_ID_AUTOPILOT_VERSION: _handleAutopilotVersion(vehicle, message); break; } return true; }主要处理版本过低警告、AUTOPILOT_VERSION解析PX4 较贴近标准 MAVLink适配量小于 APM。7.3.3 飞行模式映射各栈实现flightMode(base_mode, custom_mode)与setFlightMode(name, base, custom)。APM Copter使用APMCopterMode枚举 APMCustomMode映射表setEnumToStringMapping({ { STABILIZE, Stabilize}, { ACRO, Acro}, { GUIDED, Guided}, { LOITER, Loiter}, { RTL, RTL}, ... });PX4使用union px4_custom_mode位域解析custom_mode支持MAIN_MODE/SUB_MODE。Fly 视图下拉列表来自FirmwarePlugin::flightModes(vehicle)各子类按固件能力返回不同列表。7.3.4 能力位Capabilitiestypedef enum { SetFlightModeCapability 1 0, PauseVehicleCapability 1 1, GuidedModeCapability 1 2, OrbitModeCapability 1 3, TakeoffVehicleCapability 1 4, ROIModeCapability 1 5, } FirmwareCapabilities;UI 与 Joystick 通过isCapable(vehicle, GuidedModeCapability)决定是否显示 Guided Takeoff、Orbit 等按钮避免对不支持栈发送无效命令。7.3.5 参数名版本 remapAPM 重点APM 跨版本常重命名参数。FirmwarePlugin定义三层 Maptypedef QMapQString, QString remapParamNameMap_t; typedef QMapint, remapParamNameMap_t remapParamNameMinorVersionRemapMap_t; typedef QMapint, remapParamNameMinorVersionRemapMap_t remapParamNameMajorVersionMap_t;ArduCopterFirmwarePlugin::paramNameRemapMajorVersionMap()在静态初始化中填充如 3.5 版本CHUKE_ → CHUTE_类映射。ParameterManager请求参数前查表转换保证 QGC 内部统一使用新名称。7.3.6 任务命令树MissionCommandTree任务编辑器命令列表按MAV_AUTOPILOT × MAV_TYPE二维索引for (MAV_AUTOPILOT firmwareType: _toolbox-firmwarePluginManager()-supportedFirmwareTypes()) { FirmwarePlugin* plugin ...-firmwarePluginForAutopilot(firmwareType, MAV_TYPE_QUADROTOR); for(MAV_TYPE vehicleType: vehicleTypes) { QString overrideFile plugin-missionCommandOverrides(vehicleType); if (!overrideFile.isEmpty()) { _staticCommandTree[firmwareType][vehicleType] new MissionCommandList(overrideFile, ...); } } }各 Plugin 返回 JSON 路径如:/json/MavCmdInfoMultiRotor.json定义命令显示名、参数 Fact 元数据、是否支持。新增协议命令 UI在对应MavCmdInfo*.json增加条目或在 Custom Plugin 中 overridemissionCommandOverrides()。7.3.7 地理围栏 / Rally / Follow MeGeoFenceManager/RallyPointManager基类 MAVLink 通用Plugin 提供supported()与格式差异FollowMePX4 支持Follow Me模式字符串APM 部分版本通过 Plugin 扩展7.3.8 编译期协议裁剪#if !defined(NO_ARDUPILOT_DIALECT) _downloadArduPilotManifest(); #endifNO_ARDUPILOT_DIALECT宏可构建纯 PX4 版本移除 APM manifest、APM 固件 URL 等减小体积。7.3.9 协议兼容改造实践指南场景推荐改造点新 MAVLink 消息字段与标准不符adjustIncomingMavlinkMessage解码后重写发送命令被拒adjustOutgoingMavlinkMessage或 Plugin 专用 send 方法新飞行模式子类flightModessetFlightMode custom_mode 位定义参数 renameparamNameRemapMajorVersionMap新任务命令MavCmdInfo*.json MissionController 验证逻辑完全新飞控栈新建XxxFirmwarePluginFactoryXxxAutoPilotPlugin 全局静态 Factory 实例仅改品牌/隐藏 APMCustomQGCCorePluginCustomFirmwarePlugin继承 PX47.4 FirmwareUpgradeSettings 配置Fact作用apmChibiOS优先 ChibiOS vs NuttX 固件路径apmVehicleType默认 APM 机型过滤Copter/Plane/Rover/Sub变更时触发_buildAPMFirmwareNames()刷新 manifest 匹配列表。7.5 关键类方法速查类方法作用FirmwareUpgradeControllerstartBoardSearch()/flash()UI 入口FirmwareUpgradeController_initFirmwareHash()PX4 URL 表FirmwareUpgradeController_downloadArduPilotManifest()APM 动态固件PX4FirmwareUpgradeThreadWorker_findBootloader()同步 BootloaderPX4FirmwareUpgradeThreadWorker_flash()擦写校验Bootloadersync/erase/program/verify协议实现FirmwareImageload()/isCompatible()镜像解析QGCSerialPortInfocanFlash()/getBoardInfo()USB 识别FirmwarePluginManagerfirmwarePluginForAutopilot()运行时选栈FirmwarePluginadjustIncomingMavlinkMessage()协议适配AutoPilotPluginvehicleComponents()Setup 组件VehicleComponentsetupComplete()校准完成判定MissionCommandTreegetMissionCommands()任务命令 UI7.6 本章小结QGroundControl 4.0 的固件升级子系统采用Controller Worker Thread Bootloader 协议三层架构通过 USB VID/PIDUSBBoardInfo.json识别 Pixhawk/PX4Flow/SiK 设备经 PX4 Bootloader 二进制协议完成擦除、分块编程与 CRC/回读校验。固件来源包括 PX4 S3 静态表、GitHub Releases、ArduPilotmanifest.json动态清单.px4/.apj包同时携带参数与机架元数据烧录后即可更新 Setup 界面。机型与外设适配依托FirmwarePluginFactory → FirmwarePlugin → AutoPilotPlugin → VehicleComponent插件链参数/display 由 Fact 系统 Parameter XML 驱动传感器校准/机架选择通过 QML Setup 面板与 MAVLink 命令完成。新增硬件通常需同步修改 JSON 板型表、Parameter/Airframe 元数据及对应 Component。协议兼容遵循「Vehicle 通用、Plugin 消化差异」原则APM 侧通过 heartbeat 组件映射、STATUSTEXT 严重级别修正、参数 remap 等机制对齐 MAVLink 标准PX4 侧适配较轻。任务命令、飞行模式、Guided 能力均通过 Plugin 虚函数与 JSON 配置扩展Custom 示例提供了不修改主干的定制路径。
QGC 固件升级与硬件适配
QGC 固件升级与硬件适配7.0 总体架构QGC 4.0 将「固件烧录」与「运行时硬件/协议适配」分为两条相对独立的链路┌─────────────────────────────────────────────────────────────────┐ │ 离线烧录链路USB 串口 │ │ FirmwareUpgrade.qml → FirmwareUpgradeController │ │ → PX4FirmwareUpgradeThread → Bootloader → QSerialPort │ └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────┐ │ 在线运行链路MAVLink 连接后 │ │ MultiVehicleManager → Vehicle │ │ → FirmwarePluginManager → FirmwarePluginPX4/APM/Generic│ │ → AutoPilotPlugin → VehicleComponent[]传感器/机架/电台… │ │ → ParameterManager *ParameterMetaData │ └─────────────────────────────────────────────────────────────────┘设计原则FirmwarePlugin飞行栈PX4 / ArduPilot相关的全部差异逻辑应集中在此AutoPilotPluginVehicleComponentSetup 向导、传感器校准、机架选择等 UI/参数逻辑Vehicle与MissionManager等保持MAVLink 通用差异通过 Plugin 钩子注入涉及的主要设计模式模式体现Plugin 模式FirmwarePlugin/AutoPilotPlugin抽象飞行栈差异Factory 注册表FirmwarePluginFactory构造时自注册到FirmwarePluginFactoryRegisterSingleton懒加载各 Factory 内_pluginInstance单例复用MVCFirmwareUpgradeControllerCFirmwareUpgrade.qmlViewWorker ThreadPX4FirmwareUpgradeThreadController在独立线程执行串口 I/OStrategy按 URI/板型/协议选择不同固件 URL、Bootloader 命令集Template MethodVehicleComponent定义 setup 流程骨架子类实现具体 QML/参数AdapteradjustIncomingMavlinkMessage修正 APM 与标准 MAVLink 差异Hash Map 配置_rgFMUV5Firmware等 boardId → URL 映射表涉及语法与技术CQObject、Q_PROPERTY、Q_INVOKABLE、Q_ENUM、signals/slotsQt SerialQSerialPort、QSerialPortInfoJSON/XMLQJsonDocument.px4/.apj/manifest、QXmlStreamReader参数元数据Intel Hex.ihx解析SiK RadioMAVLinkmavlink_message_t、MAV_AUTOPILOT、MAV_TYPEQMLSetupPage、FirmwareUpgradeController注册为QGroundControl.Controllers7.1 飞控固件烧录流程开发7.1.1 模块与文件索引文件职责VehicleSetup/FirmwareUpgrade.qml固件升级 UISetup → FirmwareVehicleSetup/FirmwareUpgradeController.h/.ccMVC 控制器选固件、下载、调度烧录VehicleSetup/PX4FirmwareUpgradeThread.h/.cc独立线程找板、同步 Bootloader、擦除/编程/校验VehicleSetup/Bootloader.h/.ccPX4 Bootloader 二进制协议实现VehicleSetup/FirmwareImage.h/.cc固件镜像解析.bin/.px4/.apj/.ihxcomm/QGCSerialPortInfo.h/.ccUSB VID/PID 识别板型comm/USBBoardInfo.json板型 VID/PID 配置表Settings/FirmwareUpgradeSettings.*APM ChibiOS、机型偏好等7.1.2 用户操作流程状态机Plug USB → startBoardSearch() → 扫描串口 (canFlash) → 发现板 (foundBoard) → UI 显示板名 → 用户选 Stack(PX4/APM) 版本(Stable/Beta/Dev) 机型 → flash() → 等待 Bootloader (foundBootloader) → 解析 board_id / flash_size → 查 Hash 得固件 URL → QGCFileDownload 下载 → FirmwareImage::load() 校验 board_id、解压元数据 → ThreadController::flash() → erase → program → verify → reboot → flashComplete → 恢复 LinkManager 连接入口startBoardSearch()关键行为void FirmwareUpgradeController::startBoardSearch(void) { LinkManager* linkMgr qgcApp()-toolbox()-linkManager(); linkMgr-setConnectionsSuspended(tr(Connect not allowed during Firmware Upgrade.)); ... _threadController-startFindBoardLoop(); }烧录期间禁止新建 MAVLink 连接避免与 Bootloader 串口冲突。7.1.3 USB 板型识别QGCSerialPortInfo::getBoardInfo()读取:/json/USBBoardInfo.jsonboardInfo: [ { vendorID: 9900, productID: 16, boardClass: Pixhawk, name: PX4 FMU V1 }, { vendorID: 9900, productID: 17, boardClass: Pixhawk, name: PX4 FMU V2 }, ... { vendorID: 9900, productID: 50, boardClass: Pixhawk, name: PX4 FMU V5 },匹配逻辑先VIDPID失败则description/manufacturer 正则 fallback。canFlash()仅对三类板返回 truebool QGCSerialPortInfo::canFlash(void) const { ... switch(boardType){ case QGCSerialPortInfo::BoardTypePixhawk: case QGCSerialPortInfo::BoardTypePX4Flow: case QGCSerialPortInfo::BoardTypeSiKRadio: return true;新增可烧录硬件的第一步在USBBoardInfo.json增加 VID/PID 条目并在Bootloader.h增加boardID*常量若为新 PX4 板型。7.1.4 Bootloader 通信协议Bootloader类实现 PX4 官方 Bootloader 协议也用于 3DR Radio 变体协议字节节选符号值含义PROTO_INSYNC0x12同步前缀PROTO_EOC0x20命令结束PROTO_OK/PROTO_FAILED0x10 / 0x11响应PROTO_GET_SYNC0x21建立同步PROTO_CHIP_ERASE0x23全片擦除PROTO_PROG_MULTI0x27多块写入最大 64 字节4 字节对齐PROTO_GET_CRC0x29CRC 校验Bootloader ≥3PROTO_BOOT0x30重启进应用烧录核心循环.bin格式while (bytesSent imageSize) { ... if (_write(port, PROTO_PROG_MULTI)) { if (_write(port, (uint8_t)bytesToSend)) { if (_write(port, imageBuf, bytesToSend)) { if (_write(port, PROTO_EOC)) { if (_getCommandResponse(port)) { failed false; } } } } } ... _imageCRC QGC::crc32((uint8_t *)imageBuf, bytesToSend, _imageCRC); emit updateProgress(bytesSent, imageSize); }校验策略Bootloader ≤2 或.ihx逐字节PROTO_READ_MULTI回读比对Bootloader ≥3 且.binPROTO_GET_CRC与预计算 CRC 比较完成后reboot()发送PROTO_BOOTBoard ID 常量与固件包内board_id对应static const int boardIDPX4FMUV2 9; static const int boardIDPX4FMUV4 11; static const int boardIDPX4FMUV5 50; static const int boardIDPX4FMUV3 255; // V2 大 Flash 模拟 ID static const int boardIDDurandalV1 139; ...7.1.5 独立线程 WorkerPX4FirmwareUpgradeThreadController将耗时串口操作移出 UI 线程Controller (主线程) Worker (子线程) startFindBoardLoop ──signal──► _findBoardOnce() flash(image) ──signal──► _flash(): erase→program→verify cancel ──signal──► 关闭端口 ◄── foundBootloader / updateProgress / flashComplete找 Bootloader 流程枚举QGCSerialPortInfo::availablePorts()过滤canFlash()首次发现 emitfoundBoardUI 等待用户确认/选固件第二次循环非 firstAttempt打开串口 →Bootloader::sync()→getPX4BoardInfo()读INFO_BL_REV / INFO_BOARD_ID / INFO_FLASH_SIZESiK Radio 特殊路径先发/ATUPDATE强制进 Bootloader完整烧录_flash()if (_erase()) { if (_bootloader-program(_bootloaderPort, _controller-image())) { ... } if (_bootloader-verify(_bootloaderPort, _controller-image())) { ... } } emit _reboot(); emit flashComplete();7.1.6 固件镜像格式FirmwareImage扩展名格式用途.bin原始二进制直接编程.px4JSON 包装PX4 传统含 base64 镜像 压缩 parameter/airframe XML.apjJSON 包装ArduPilot ChibiOS同.px4结构MAV_AUTOPILOTAPM.ihxIntel Hex3DR SiK Radio.px4/.apj加载流程QJsonDocument doc QJsonDocument::fromJson(bytes); ... uint32_t firmwareBoardId (uint32_t)px4Json.value(_jsonBoardIdKey).toInt(); if (!isCompatible(_boardId, firmwareBoardId)) { emit statusMessage(...); return false; }兼容规则示例FMUv3board_id255可烧 FMUv2id9固件AUAV X2.1 同理。解压后的parameter XML写入缓存并注册到ParameterManager::cacheMetaDataFile()使烧录后 Setup 界面立即可用最新参数元数据无需等飞控在线。7.1.7 固件 URL 来源1PX4 静态 Hash 表_initFirmwareHash()为每块板维护QHashFirmwareIdentifier, QStringKeyAutoPilotStackTypeFirmwareBuildTypeFirmwareVehicleTypeValueS3 URL如http://px4-travis.s3.amazonaws.com/Firmware/stable/px4fmu-v5_default.px4FMUv2/V3/V4/V5、Durandal、KakuteF7 等各有独立 Hash。2PX4 GitHub Releases 动态版本_determinePX4StableVersion()拉取https://api.github.com/repos/PX4/Firmware/releases解析 stable/beta 标签。3ArduPilot manifest.jsonvoid FirmwareUpgradeController::_downloadArduPilotManifest(void) { ... downloader-download(QStringLiteral(http://firmware.ardupilot.org/manifest.json)); }解析字段board_id、mav-type、url、mav-firmware-version-type、USBID、bootloader_str、brand_name等动态构建_rgManifestFirmwareInfo供 ChibiOS 板按名称列表选择固件。4SingleFirmwareModeCustom 构建可通过QGCOptions::firmwareUpgradeSingleURL()指定单一 URL跳过用户选择。7.1.8 Controller 与 QML 绑定FirmwareUpgradeController暴露给 QML 的属性示例boardPort/boardDescription/pixhawkBoardselectedFirmwareBuildTypeStable/Beta/Dev/CustomapmFirmwareNames/apmFirmwareUrlsAPM manifest 动态列表progressBar/statusLogQQuickItem 指针C 直接setProperty(value, ...)QML 调用FirmwareUpgradeController { onFlashComplete: ... } // Q_INVOKABLE: controller.startBoardSearch() controller.flash(AutoPilotStackPX4, StableFirmware, DefaultVehicleFirmware)7.1.9 扩展烧录流程的开发指南若需支持新 Bootloader 协议或新文件格式扩展FirmwareImage::load()增加解析分支在Bootloader中实现新命令集或新建XxxBootloader类修改PX4FirmwareUpgradeThreadWorker::_findBootloader()的打开/同步逻辑在FirmwareUpgradeController::_initFirmwareHash()或 manifest 解析处增加 URL更新USBBoardInfo.json与Bootloader::boardID*常量若仅需支持新 PX4 兼容板沿用 PX4 Bootloader通常只需 JSON Hash URL无需改协议代码。7.2 新增机型、外设传感器适配7.2.1 运行时对象模型Vehicle 创建 └─ _firmwarePlugin FirmwarePluginManager::firmwarePluginForAutopilot(type, mavType) └─ _firmwarePlugin-initializeVehicle(this) └─ ParameterManager 就绪后 └─ AutoPilotPlugin::vehicleComponents() └─ AirframeComponent / SensorsComponent / RadioComponent / ... └─ 各 Component 绑定 setup QML Fact 参数名Vehicle 中获取 Pluginvoid Vehicle::_commonInit() { _firmwarePlugin _firmwarePluginManager-firmwarePluginForAutopilot(_firmwareType, _vehicleType);7.2.2 FirmwarePluginFactory 注册机制全局静态 Factory 对象在构造时自注册FirmwarePluginFactory::FirmwarePluginFactory(void) { FirmwarePluginFactoryRegister::instance()-registerPluginFactory(this); }PX4 FactoryQListMAV_AUTOPILOT PX4FirmwarePluginFactory::supportedFirmwareTypes(void) const { list.append(MAV_AUTOPILOT_PX4);APM Factory按 MAV_TYPE 分派switch (vehicleType) { case MAV_TYPE_QUADROTOR: case MAV_TYPE_HELICOPTER: return _arduCopterPluginInstance; case MAV_TYPE_FIXED_WING: case MAV_TYPE_VTOL_QUADROTOR: return _arduPlanePluginInstance; case MAV_TYPE_GROUND_ROVER: return _arduRoverPluginInstance; case MAV_TYPE_SUBMARINE: return _arduSubPluginInstance;新增「机型」在 QGC 语义下通常指新的MAV_TYPE组合 → 新建或扩展ArduXxxFirmwarePlugin新的机架/airframe→ PX4AirframeComponentPX4AirframeLoaderXML新的Setup 步骤/外设→ 新建VehicleComponent子类7.2.3 AutoPilotPlugin 与 VehicleComponentVehicleComponent 抽象接口virtual QString name(void) const 0; virtual bool requiresSetup(void) const 0; virtual bool setupComplete(void) const 0; virtual QUrl setupSource(void) const 0; // 完整 Setup 面板 QML virtual QUrl summaryQmlSource(void) const 0; // 摘要卡片 QML virtual QStringList setupCompleteChangedTriggerList(void) const 0;PX4 Setup 组件列表示例Component职责关键参数 FactAirframeComponent机架/机型选择SYS_AUTOSTART,SYS_AUTOCONFIGSensorsComponentIMU/罗盘/气压计/空速计校准CAL_*,SENS_*PX4RadioComponent遥控校准RC_*FlightModesComponent飞行模式映射RC_MAP_*PowerComponent电池/电源BAT_*MotorComponent电机测试PWM_*SafetyComponent返航/地理围栏RTL_*,GF_*PX4TuningComponentPID 调参各控制器增益APM 对应APMSensorsComponent、APMAirframeComponent、APMMotorComponent、APMSubFrameComponentROV 框架、APMLightsComponent等。7.2.4 新增外设/传感器适配步骤PX4 为例步骤 1确认参数名与校准命令PX4 传感器校准通过 MAVLinkMAV_CMD_PREFLIGHT_CALIBRATION或参数读写完成QGCSensorsComponent的 QML 触发 C 发送命令。新传感器需确认固件暴露的参数名如SENS_EN_XXX和校准流程。步骤 2扩展 SensorsComponent修改setupCompleteChangedTriggerList()增加新参数在setupComplete()中检查校准状态参数如CAL_ACC0_ID非零表示已校准在SensorsSetup.qml或对应 QML增加 UI 入口步骤 3参数元数据Parameter MetaDataPX4 使用 XML 描述参数短名、单位、枚举、增量void loadParameterFactMetaDataFile (const QString metaDataFile); FactMetaData* getMetaDataForFact (const QString name, MAV_TYPE vehicleType); void addMetaDataToFact (Fact* fact, MAV_TYPE vehicleType);元数据来源飞控在线ParameterManager向飞控请求离线/烧录后.px4包内parameter_xml解压缓存内置编译资源:/FirmwarePlugin/PX4/PX4ParameterFactMetaData.xml新增参数 UI 显示在固件 Parameter XML 中加入定义即可被 Fact 系统自动识别若需特殊控件扩展FactMetaData的enumStrings或自定义 QML FactControl。步骤 4机架/Airframe 元数据PX4AutoPilotPlugin构造时_airframeFacts new PX4AirframeLoader(this, _vehicle-uas(), this); PX4AirframeLoader::loadAirframeMetaData();Airframe XML 定义SYS_AUTOSTARTID 与机型名称映射。新增 PX4 机架需在 PX4 固件侧airframes/添加QGC 通过烧录包或在线同步 XML 自动更新列表。步骤 5FactGroup 扩展遥测显示新传感器若通过 MAVLink 消息上报非参数在Vehicle或专用XxxFactGroup中解析消息并暴露Fact供 Fly 视图仪表板使用。例如_distanceSensorFactGroup、_battery1FactGroup。7.2.5 APM 传感器与机型差异APM 的APMAutoPilotPlugin::vehicleComponents()按vehicleType 参数存在性动态组装直升机APMHeliComponent潜水器APMSubFrameComponent、APMLightsComponent相机APMCameraComponent检测CAM1_TYPE等ESP8266 WiFiESP8266Componentif ( _vehicle-supportsRadio() ) { _radioComponent new APMRadioComponent(_vehicle, this);supportsRadio()来自FirmwarePlugin::supportsRadio()虚函数可按机型关闭 RC Setup。7.2.6 USB 外设自动连接LinkManager扫描串口时调用QGCSerialPortInfo::getBoardInfo()对 RTK GPS、SiK Radio 等可自动创建连接。新增 USB 外设类型在USBBoardInfo.json增加boardClass如RTK GPS在LinkManager自动连接逻辑中增加对应处理7.2.7 Custom 定制示例custom-example/展示最小定制路径QListMAV_AUTOPILOT CustomFirmwarePluginFactory::supportedFirmwareTypes() const { list.append(MAV_AUTOPILOT_PX4);继承PX4FirmwarePlugin/PX4AutoPilotPluginOverride 飞行模式、任务命令、Setup 组件列表无需 fork 整个 QGC。7.2.8 新增机型适配检查清单层次修改位置说明USB 识别USBBoardInfo.jsonVID/PID → 板名烧录Bootloader.hboard ID Firmware Hash固件 URL协议XxxFirmwarePlugin飞行模式、GUIDED、任务SetupVehicleComponent QML校准/配置 UI参数PX4/APM Parameter XML名称/单位/枚举机架Airframe XMLSYS_AUTOSTART任务MavCmdInfo*.json航线命令 UI连接LinkManager自动连接规则7.3 不同飞控协议兼容改造QGC 4.0 核心 MAVLink 处理保持栈无关协议差异通过 FirmwarePlugin 钩子消化。7.3.1 插件选择与 FallbackFirmwarePlugin* FirmwarePluginManager::firmwarePluginForAutopilot(MAV_AUTOPILOT firmwareType, MAV_TYPE vehicleType) { FirmwarePluginFactory* factory _findPluginFactory(firmwareType); if (factory) { plugin factory-firmwarePluginForAutopilot(firmwareType, vehicleType); } if (!plugin) { if (!_genericFirmwarePlugin) { _genericFirmwarePlugin new FirmwarePlugin; } plugin _genericFirmwarePlugin; } return plugin; }未知 Autopilot 回退Generic FirmwarePlugin提供基础 MAVLink 能力无 PX4/APM 特有 Guided 等功能。7.3.2 MAVLink 消息适配钩子Vehicle 收消息前if (!_firmwarePlugin-adjustIncomingMavlinkMessage(this, message)) {返回false则丢弃该消息用于过滤重复 STATUSTEXT 等。Vehicle 发消息前_firmwarePlugin-adjustOutgoingMavlinkMessage(this, link, message);APM 入站适配典型bool APMFirmwarePlugin::adjustIncomingMavlinkMessage(Vehicle* vehicle, mavlink_message_t* message) { if (message-msgid MAVLINK_MSG_ID_HEARTBEAT) { _handleIncomingHeartbeat(vehicle, message); return true; } if (_ardupilotComponentMap[vehicle-id()][message-compid]) { switch (message-msgid) { case MAVLINK_MSG_ID_PARAM_VALUE: _handleIncomingParamValue(vehicle, message); break; case MAVLINK_MSG_ID_STATUSTEXT: return _handleIncomingStatusText(vehicle, message, false); ... } } return true; }APM 兼容要点组件识别通过 HEARTBEAT 的autopilot字段维护_ardupilotComponentMap仅对 ArduPilot 组件做方言转换STATUSTEXT 严重级别旧版 APM 使用非标准 severity 编码_adjustSeverity()映射到 MAV_SEVERITY 标准值PARAM_VALUE参数名可能带后缀或索引差异_handleIncomingParamValue规范化RC_CHANNELS vs RC_CHANNELS_RAW合并处理不同版本消息出站 PARAM_SET_handleOutgoingParamSet处理 APM 参数名/类型差异PX4 入站适配bool PX4FirmwarePlugin::adjustIncomingMavlinkMessage(Vehicle* vehicle, mavlink_message_t* message) { if (message-compid MAV_COMP_ID_UDP_BRIDGE) { return true; } switch (message-msgid) { case MAVLINK_MSG_ID_AUTOPILOT_VERSION: _handleAutopilotVersion(vehicle, message); break; } return true; }主要处理版本过低警告、AUTOPILOT_VERSION解析PX4 较贴近标准 MAVLink适配量小于 APM。7.3.3 飞行模式映射各栈实现flightMode(base_mode, custom_mode)与setFlightMode(name, base, custom)。APM Copter使用APMCopterMode枚举 APMCustomMode映射表setEnumToStringMapping({ { STABILIZE, Stabilize}, { ACRO, Acro}, { GUIDED, Guided}, { LOITER, Loiter}, { RTL, RTL}, ... });PX4使用union px4_custom_mode位域解析custom_mode支持MAIN_MODE/SUB_MODE。Fly 视图下拉列表来自FirmwarePlugin::flightModes(vehicle)各子类按固件能力返回不同列表。7.3.4 能力位Capabilitiestypedef enum { SetFlightModeCapability 1 0, PauseVehicleCapability 1 1, GuidedModeCapability 1 2, OrbitModeCapability 1 3, TakeoffVehicleCapability 1 4, ROIModeCapability 1 5, } FirmwareCapabilities;UI 与 Joystick 通过isCapable(vehicle, GuidedModeCapability)决定是否显示 Guided Takeoff、Orbit 等按钮避免对不支持栈发送无效命令。7.3.5 参数名版本 remapAPM 重点APM 跨版本常重命名参数。FirmwarePlugin定义三层 Maptypedef QMapQString, QString remapParamNameMap_t; typedef QMapint, remapParamNameMap_t remapParamNameMinorVersionRemapMap_t; typedef QMapint, remapParamNameMinorVersionRemapMap_t remapParamNameMajorVersionMap_t;ArduCopterFirmwarePlugin::paramNameRemapMajorVersionMap()在静态初始化中填充如 3.5 版本CHUKE_ → CHUTE_类映射。ParameterManager请求参数前查表转换保证 QGC 内部统一使用新名称。7.3.6 任务命令树MissionCommandTree任务编辑器命令列表按MAV_AUTOPILOT × MAV_TYPE二维索引for (MAV_AUTOPILOT firmwareType: _toolbox-firmwarePluginManager()-supportedFirmwareTypes()) { FirmwarePlugin* plugin ...-firmwarePluginForAutopilot(firmwareType, MAV_TYPE_QUADROTOR); for(MAV_TYPE vehicleType: vehicleTypes) { QString overrideFile plugin-missionCommandOverrides(vehicleType); if (!overrideFile.isEmpty()) { _staticCommandTree[firmwareType][vehicleType] new MissionCommandList(overrideFile, ...); } } }各 Plugin 返回 JSON 路径如:/json/MavCmdInfoMultiRotor.json定义命令显示名、参数 Fact 元数据、是否支持。新增协议命令 UI在对应MavCmdInfo*.json增加条目或在 Custom Plugin 中 overridemissionCommandOverrides()。7.3.7 地理围栏 / Rally / Follow MeGeoFenceManager/RallyPointManager基类 MAVLink 通用Plugin 提供supported()与格式差异FollowMePX4 支持Follow Me模式字符串APM 部分版本通过 Plugin 扩展7.3.8 编译期协议裁剪#if !defined(NO_ARDUPILOT_DIALECT) _downloadArduPilotManifest(); #endifNO_ARDUPILOT_DIALECT宏可构建纯 PX4 版本移除 APM manifest、APM 固件 URL 等减小体积。7.3.9 协议兼容改造实践指南场景推荐改造点新 MAVLink 消息字段与标准不符adjustIncomingMavlinkMessage解码后重写发送命令被拒adjustOutgoingMavlinkMessage或 Plugin 专用 send 方法新飞行模式子类flightModessetFlightMode custom_mode 位定义参数 renameparamNameRemapMajorVersionMap新任务命令MavCmdInfo*.json MissionController 验证逻辑完全新飞控栈新建XxxFirmwarePluginFactoryXxxAutoPilotPlugin 全局静态 Factory 实例仅改品牌/隐藏 APMCustomQGCCorePluginCustomFirmwarePlugin继承 PX47.4 FirmwareUpgradeSettings 配置Fact作用apmChibiOS优先 ChibiOS vs NuttX 固件路径apmVehicleType默认 APM 机型过滤Copter/Plane/Rover/Sub变更时触发_buildAPMFirmwareNames()刷新 manifest 匹配列表。7.5 关键类方法速查类方法作用FirmwareUpgradeControllerstartBoardSearch()/flash()UI 入口FirmwareUpgradeController_initFirmwareHash()PX4 URL 表FirmwareUpgradeController_downloadArduPilotManifest()APM 动态固件PX4FirmwareUpgradeThreadWorker_findBootloader()同步 BootloaderPX4FirmwareUpgradeThreadWorker_flash()擦写校验Bootloadersync/erase/program/verify协议实现FirmwareImageload()/isCompatible()镜像解析QGCSerialPortInfocanFlash()/getBoardInfo()USB 识别FirmwarePluginManagerfirmwarePluginForAutopilot()运行时选栈FirmwarePluginadjustIncomingMavlinkMessage()协议适配AutoPilotPluginvehicleComponents()Setup 组件VehicleComponentsetupComplete()校准完成判定MissionCommandTreegetMissionCommands()任务命令 UI7.6 本章小结QGroundControl 4.0 的固件升级子系统采用Controller Worker Thread Bootloader 协议三层架构通过 USB VID/PIDUSBBoardInfo.json识别 Pixhawk/PX4Flow/SiK 设备经 PX4 Bootloader 二进制协议完成擦除、分块编程与 CRC/回读校验。固件来源包括 PX4 S3 静态表、GitHub Releases、ArduPilotmanifest.json动态清单.px4/.apj包同时携带参数与机架元数据烧录后即可更新 Setup 界面。机型与外设适配依托FirmwarePluginFactory → FirmwarePlugin → AutoPilotPlugin → VehicleComponent插件链参数/display 由 Fact 系统 Parameter XML 驱动传感器校准/机架选择通过 QML Setup 面板与 MAVLink 命令完成。新增硬件通常需同步修改 JSON 板型表、Parameter/Airframe 元数据及对应 Component。协议兼容遵循「Vehicle 通用、Plugin 消化差异」原则APM 侧通过 heartbeat 组件映射、STATUSTEXT 严重级别修正、参数 remap 等机制对齐 MAVLink 标准PX4 侧适配较轻。任务命令、飞行模式、Guided 能力均通过 Plugin 虚函数与 JSON 配置扩展Custom 示例提供了不修改主干的定制路径。