3. DroneCAN协议核心

DroneCAN 的互操作性并不来自“大家约定俗成”,而是来自一套可编译、可校验、可版本化的接口描述体系。DSDL(DroneCAN Specification Description Language)就是这套体系的基石:它用文本描述消息、服务、数据类型和常量,再由代码生成器产出各语言的结构体与序列化代码。理解 DSDL,等于拿到了 DroneCAN 通信的“合同文本”。

一、DSDL 的定位与编译链路

DSDL 文件通常以 .uavcan 为扩展名,按命名空间和版本组织,例如 uavcan.equipment.esc.Status。每个文件描述一个消息或服务,并声明其固定 ID(subject ID 或 service ID)。DSDL 不是运行时协议,而是编译期契约:它先被解析为抽象语法树,再生成 C++、Python 等语言的类型定义和编解码函数。

在一致性测试中,DSDL 的作用尤为关键:测试用例需要根据 DSDL 生成激励报文,并解析被测设备的响应。如果 DSDL 版本不一致,即使物理层连通,语义层也会“鸡同鸭讲”。因此,测试工程必须锁定 DSDL 仓库版本,并记录每个消息的签名。

DSDL 编译链路与一致性测试 DSDL 源文件 .uavcan / 命名空间 DSDL 编译器 语法解析 / 类型检查 生成代码 C++ / Python 结构体 测试用例 激励 / 断言 DSDL 核心组成 数据类型 uint8 / int16 / float32 数组 / 定长 / 变长 复合类型嵌套 消息定义 字段名 + 类型 常量 / 默认值 固定 Subject ID 服务定义 请求 Request 响应 Response 固定 Service ID 签名与版本 数据类型签名 版本兼容性 测试基线锁定

二、数据类型:从标量到复合

DSDL 的数据类型分为标量、数组和复合类型。标量包括有符号/无符号整数(int8、uint16、uint64 等)、浮点数(float16、float32、float64)以及布尔类型。数组分为定长数组和变长数组,变长数组在编码时带有长度前缀,这是 DroneCAN 帧长度动态变化的主要原因。

复合类型允许在一个消息中嵌套另一个消息,例如 uavcan.equipment.esc.Status 中可能包含 uavcan.Timestamp 字段。这种嵌套在编码时按字段顺序展开,不额外增加类型标签,因此 DSDL 的字段顺序和类型必须严格一致,否则解析会错位。

# 示例:一个简化的 DSDL 消息定义
uint32 timestamp
float32 voltage
float32 current
uint8[4] error_flags
uint8 esc_index

在一致性测试中,数据类型边界是重点:测试用例应覆盖最小值、最大值、零值、变长数组空值以及复合类型嵌套深度。很多设备在 uint8 溢出或变长数组长度为 0 时出现异常,这正是 DSDL 类型约束要验证的地方。

三、消息定义与服务定义

消息定义描述“广播什么”,服务定义描述“请求-响应什么”。消息通过 Subject ID 标识,服务通过 Service ID 标识。DSDL 文件头部通常包含固定 ID 声明,例如 @subject_id 1234 或 @service_id 5678。这些 ID 在 DroneCAN 网络中必须唯一,否则会出现总线冲突或路由错误。

服务定义由请求和响应两部分组成,中间用 --- 分隔。请求和响应各自拥有独立字段,编译器会分别生成两个结构体。测试服务时,需要构造请求并等待响应,同时校验响应中的字段是否符合预期。

对比项 消息定义 服务定义
通信模式 广播 / 发布订阅 请求-响应
标识符 Subject ID Service ID
DSDL 结构 单一字段列表 Request --- Response
测试重点 周期、字段范围、签名 超时、错误码、响应匹配
典型示例 uavcan.equipment.esc.Status uavcan.protocol.GetNodeInfo

四、案例场景:用 DSDL 驱动一致性测试

假设我们要测试一个 ESC 节点的 uavcan.equipment.esc.Status 消息。测试流程如下:

  1. 从锁定的 DSDL 仓库中提取该消息定义,确认 Subject ID 和字段类型。
  2. 使用 DSDL 编译器生成 Python 测试桩,构造订阅者。
  3. 向被测节点发送 RPM 指令,触发其周期发布 Status 消息。
  4. 解析收到的报文,校验 timestamp 单调递增、voltage 在合理范围、error_flags 符合预期。
  5. 记录 DSDL 签名,确保测试基线与设备固件版本匹配。
建议在测试工程中维护一份 dsdl_manifest.json,记录每个消息/服务的名称、ID、签名和版本,作为一致性测试的“合同附件”。

五、常见误区与复盘

误区一:只关注 ID,忽略字段顺序。 DroneCAN 编码不携带字段名,字段顺序错位会导致解析出完全错误的值。测试时必须逐字段比对。

误区二:变长数组长度未校验。 变长数组在编码时带有长度前缀,如果设备发送的长度超过 DSDL 定义的最大值,接收端可能越界。测试用例应包含超长数组和空数组。

误区三:服务响应超时未处理。 服务定义中响应可能永远不返回,测试必须设置超时并验证设备在超时后的行为,例如重试或报错。

DSDL 版本不一致是 DroneCAN 一致性测试中最隐蔽的故障源。建议在测试启动阶段先执行一次“DSDL 签名握手”,确认测试端与设备端的接口描述完全一致,再进入功能测试。

掌握 DSDL 的数据类型、消息定义和服务定义,是编写可靠一致性测试用例的前提。只有把接口契约固化下来,后续的物理层、传输层和应用层测试才有稳定的语义基础。