QGC 通信模块架构梳理
QGC 的通信模块 (comms
) 是其核心支柱,负责与无人机(自动驾驶仪)及其他外部设备(如地面站、中继器等)的所有底层数据交换。其设计核心是抽象化和模块化,以支持多种链路类型、协议和多飞行器操作。
一、 核心设计哲学
- 链路抽象: 将物理连接(如串口、UDP)抽象为统一的逻辑“链路”(
Link
),向上层应用提供一致的接口。 - 协议与传输分离: MAVLink 协议处理与数据传输完全解耦。链路只负责字节流的传输,协议层负责解析和封装。
- 多线程与异步I/O: 所有可能阻塞的 I/O 操作(如读写串口、网络套接字)都在独立的工作线程中完成,确保用户界面(UI)始终保持流畅响应。
- 中心化管理: 通过一个中央管理器(
LinkManager
)统一管理所有链路的生命周期和配置。
二、 核心组件层级与关系
下图清晰地展示了 QGC 通信模块各核心组件间的层级与数据流转关系:
flowchart TDsubgraph A [应用层 / UI层]direction LRMainWindow[主窗口/界面]Vehicle[Vehicle对象<br>(代表一架无人机)]endsubgraph B [协议层]direction LRMAVLinkProtocol[MAVLinkProtocol<br>单例全局协议处理器]endsubgraph C [链路管理层]direction LRLinkManager[LinkManager<br>链路管理器]LinkConf[LinkConfiguration<br>链路配置抽象类]endsubgraph D [链路实现层]direction LRLinkInterface[LinkInterface<br>链路接口抽象基类]LinkInterface -- 派生 --> SerialLinkLinkInterface -- 派生 --> UDPLinkLinkInterface -- 派生 --> TCPLinkLinkInterface -- 派生 --> BluetoothLinkLinkInterface -- 派生 --> MockLinkendA -- 1. 请求创建/连接链路 --> CC -- 2. 实例化具体链路 --> DD -- 3. 上报连接状态/字节数据 --> CC -- 4. 转发字节数据 --> BB -- 5. 解析为MAVLink消息<br>并分配至对应Vehicle --> AB -- 6. 将待发送的MAVLink消息<br>编码为字节数据 --> CC -- 7. 通过相应链路发出 --> D
三、 详细组件功能解析
1. 链路管理层 (Link Management Layer)
-
LinkManager
(单例模式)- 功能: 整个通信模块的“大脑”,负责协调所有链路活动。
- 职责:
- 生命周期管理: 创建、添加、删除、连接、断开所有
LinkInterface
实例。 - 配置持久化: 加载和保存所有链路的配置信息(通过
LinkConfiguration
子类)。 - 自动连接: 管理开机或运行时按预设配置自动建立连接。
- 状态广播: 当链路连接/断开或有数据活动时,向全系统发送通知(Qt信号)。
- 多飞行器支持: 与
MAVLinkProtocol
协作,管理MAVLink
通道与特定Vehicle
对象的映射关系。
- 生命周期管理: 创建、添加、删除、连接、断开所有
-
LinkConfiguration
(抽象基类)- 功能: 存储某种类型链路的配置参数(如名称、连接类型)。
- 派生类:
SerialConfiguration
(端口、波特率),UDPConfiguration
(主机IP、端口),TCPConfiguration
等。每个LinkInterface
子类都有对应的配置子类。
2. 链路实现层 (Link Implementation Layer)
-
LinkInterface
(抽象基类)- 功能: 定义所有具体链路必须实现的统一接口。这是“抽象化”设计的关键。
- 核心接口:
connect()
/disconnect()
writeBytes()
/readBytes()
- 发送
connected()
,disconnected()
,bytesReceived()
等信号。
- 特性:
- 多线程: 通常会在
connect()
时启动一个专属的QThread
(工作线程),所有I/O操作在该线程中进行。 - 数据流: 仅处理原始字节流,不涉及任何协议解析。
- 多线程: 通常会在
-
具体链路实现 (派生自
LinkInterface
)SerialLink
: 基于QSerialPort
,用于物理串口、USB转串口、数传电台等。UDPLink
: 用于UDP网络通信。可配置为客户端(指向特定主机端口)或服务器(监听特定端口)。TCPLink
: 用于TCP网络通信。目前主要实现为客户端(连接到自动驾驶仪的TCP服务器)。BluetoothLink
: 用于蓝牙RFCOMM通信(模拟串口)。LogReplayLink
: 用于回放.tlog
格式的MAVLink日志文件,用于调试和演示。MockLink
: 用于单元测试和CI/CD,完全模拟一个自动驾驶仪的行为,可以仿真各种飞行状态和故障。
3. 协议层 (Protocol Layer)
MAVLinkProtocol
(单例模式)- 功能: MAVLink消息的中央交换机和处理器。它从所有链路接收字节流,并将其转换为有意义的MAVLink消息。
- 核心职责:
- 协议解析: 从原始字节流中识别并解包MAVLink消息(v1.0和v2.0)。
- 协议封装: 将应用程序的MAVLink消息封装成字节流,通过指定链路发送。
- 消息路由: 根据消息中的
sysid
/compid
,将消息路由到对应的Vehicle
对象。 - 日志记录: 实时将收发的所有MAVLink消息记录到
.tlog
文件中。 - 统计信息: 计算并更新丢包率、数据速率等链路质量指标。
- 与链路管理器的交互: 它监听
LinkManager
的bytesReceived
信号以获取数据,并通过LinkManager
的接口发送数据。
四、 关键工作流程
-
启动与初始化:
LinkManager
和MAVLinkProtocol
作为单例被创建。LinkManager
从设置中加载已保存的链路配置列表。
-
连接建立:
- 用户(或自动连接配置)通过
LinkManager
请求连接一个配置。 LinkManager
根据配置类型创建对应的LinkInterface
子类实例(如SerialLink
)。- 调用
LinkInterface::connect()
,启动工作线程并建立物理连接。 - 连接成功后,链路发出
connected()
信号。
- 用户(或自动连接配置)通过
-
数据接收 (
Downlink
):SerialLink
的工作线程从串口读取到字节数据。- 线程通过
bytesReceived(LinkInterface*, QByteArray)
信号将数据块发出。 LinkManager
接收此信号,并将其转发给MAVLinkProtocol
。MAVLinkProtocol
解析字节流,生成完整的MAVLink消息对象。MAVLinkProtocol
根据消息的sysid
查找对应的Vehicle
对象,并将消息传递给该对象进行处理。
-
数据发送 (
Uplink
):- 应用程序(如UI上的点击操作)或
Vehicle
对象需要发送命令(如起飞)。 - 命令被组装成MAVLink消息,传递给
MAVLinkProtocol::sendMessage()
。 MAVLinkProtocol
将消息编码为字节流。MAVLinkProtocol
通过LinkManager
查询应使用哪个链路发送(通常根据当前激活的飞行器确定链路),然后调用LinkInterface::writeBytes()
。- 字节数据被送入链路的工作线程队列,由该线程异步写入物理连接。
- 应用程序(如UI上的点击操作)或
五、 总结与优势
QGC 的通信架构是一个经典的高内聚、低耦合设计范例:
- 可扩展性: 添加一种新的链路类型(如WebSockets)只需继承
LinkInterface
和LinkConfiguration
,并在管理器注册即可,无需改动上层应用和协议逻辑。 - 可靠性: 工作线程模式将耗时、阻塞的I/O操作与UI线程隔离,保证了软件的实时性和响应能力。
- 一致性: 上层应用(如飞行仪表、地图、设置页面)完全无需关心数据来自串口还是WiFi,它们只与统一的MAVLink消息接口交互。
- 功能强大: 完整支持多飞行器、日志回放、模拟测试等复杂场景,架构清晰地将这些功能的支持责任划分到不同的模块中。