MavLink

[MavLink](MAVLink Versions · MAVLink Developer Guide)

1. 概述

MAVLink 是一种非常轻量级的消息协议,用于与无人机通信(以及机载无人机组件之间)。

MAVLink 遵循现代混合发布-订阅和点对点设计模式:数据流作为主题发送/发布,而配置子协议(如任务协议或参数协议)是点对点的重传。 消息在 XML 文件中定义。

每个 XML 文件都定义了特定 MAVLink 系统支持的消息集。大多数地面控制站和自动驾驶仪实现的参考消息集以 common.xml 定义(大多数方言都建立在此定义之上)。

代码生成器从这些 XML 消息定义中为特定编程语言创建软件库,然后无人机、地面控制站和其他 MAVLink 系统可以使用这些软件库进行通信。生成的库通常是 MIT 许可的,因此可以在任何闭源应用程序中无限制地使用,而无需发布闭源应用程序的源代码。

2. 版本说明

2.1. MAVLink 已经部署了多个版本:

MAVLink 2.0: 当前/推荐的主要版本。2017年初被主要用户采用。 MAVLink v1.0: 2013年左右广泛采用。许多遗留外设仍在使用。 MAVLink 2.0 c / c++ 和 Python 库向后兼容 MAVLink 1.0 (支持两种协议)。版本握手和协商版本说明了如何选择使用哪个版本。

确定协议/消息版本 库的MAVLink支持可以通过多种方式确定:

AUTOPILOT_VERSION。功能可以检查mav_protocol_capacity_mavlink2标志来验证MAVLink 2的支持。 PROTOCOL_VERSION。version包含MAVLink版本号乘以100:v1.0是100,v2.3是203等。 心跳。Mavlink_version字段包含次要版本号。这是在消息定义中定义的<version>字段(对于依赖于公共消息集的方言,common.xml中的版本)。 主版本可以从数据包开始标记字节确定:

MAVLink 1: 0xFE MAVLink 2: 0xFD

2.2. 版本握手

对mavlink2的支持在AUTOPILOT_VERSION消息中由MAV_PROTOCOL_CAPABILITY_MAVLINK2标志表示。

如果自动驾驶仪和GCS之间的通信链路完全透明,这就足够了。然而,大多数通信链路不是完全透明的,因为它们要么包含路由,要么在分组上实现固定长度的无线。为了测试链路,MAVLink 2握手协议发送一个MAVLink 2帧来测试完整的通信链。

为此,GCS发送COMMAND_LONG或COMMAND_INT消息,其命令ID为MAV_CMD_REQUEST_PROTOCOL_VERSION。

如果系统支持MAVLink 2和握手,它将响应PROTOCOL_VERSION编码为MAVLink 2数据包。如果它不支持MAVLink 2,它应该NACK命令。在命令接口没有正确实现的情况下,GCS应该退回到超时状态。

下面的图表说明了完整的序列。

3. 帧格式

介绍关于MAVLink报文序列化的详细信息,包括MAVLink v1和v2报文的过线格式、消息负载中各字段的排序以及用于保证发送方和接收方共享兼容消息定义的CRC_EXTRA。

它主要用于创建/维护MAVLink生成器的开发人员,MAVLink用户通常不需要理解序列化格式,因为编码/解码是由MAVLink库处理的。

本节给出了MAVLink报文的序列化消息格式(该格式受到CAN和SAE AS-4标准的启发)。

注意,多字节字段是以小端格式序列化的,并且MAVLink库默认配置为在小端硬件上运行。

3.1. Mavlink v1 数据格式

下面是MAVLink 1数据包的过线格式(内存中的表示可能有所不同)。

MAVLink v1 packet

字节索引C 版本内容数值解释
0uint8_t magic包开始标记0xFE特定于协议的文本起始(STX)标记,用于指示新数据包的开始。任何不了解协议版本的系统都将跳过数据包。
1uint8_t len有效载荷长度0 - 255指示以下“有效负载”部分的长度(针对特定消息固定)。
2uint8_t seq包序号0 - 255用于检测丢包。发送的每个消息的组件增量值。
3uint8_t sysid系统标识1 - 255发送消息的系统 (车辆)的ID。用于区分网络中的系统。注意广播地址0不能在这个字段中使用,因为它是一个无效的“源”地址。
4uint8_t compid组件ID1 - 255发送消息的组件 ID。用于区分“系统”中的组件(例如自动驾驶仪和摄像头)。在MAV_COMPONENT中使用合适的值。注意,广播地址 MAV_COMP_ID_ALL 不能在这个字段中使用,因为它是一个无效的地址。
5uint8_t msgid消息ID0 - 255有效载荷中消息类型 的ID。用于将数据解码回消息对象。
对于 n 字节的有效载荷: n=0: NA, n=1: 6, n>=2: 6 to (5+n)uint8_t payload[max 255]有效载荷数据消息数据。内容取决于消息类型(即消息ID)。
(n+6) to (n+7)uint16_t checksum校验和(低字节在前高字节在后)CRC-16/MCRF4XX用于消息(不包括magic字节)。包含CRC_EXTRA字节。
  • 对于无负载的确认报文,最小报文长度为8字节。

  • 最大数据包长度为263字节。

3.2. Mavlink v2 数据格式

下面是MAVLink 2数据包的线上格式(内存中的表示可能有所不同)。

字节索引C 版本内容数值解释
0uint8_t magic包开始标记0xFD特定于协议的文本起始(STX)标记,用于指示新数据包的开始。任何不了解协议版本的系统都将跳过数据包。
1uint8_t len有效载荷长度0 - 255指示以下有效负载 部分的长度。这可能会受到有效载荷截断的影响。
2uint8_t incompat_flags不相容旗帜MAVLink 兼容性必须理解的标志(如果实现不理解标志,则丢弃数据包)。
3uint8_t compat_flags兼容性旗帜如果不理解可以忽略的标志(即使不理解标志,实现仍然可以处理数据包)。
4uint8_t seq包序号0 - 255用于检测丢包。发送的每个消息的组件增量值。
5uint8_t sysid系统ID(发送方)1 - 255发送消息的系统 (车辆)的ID。用于区分网络中的系统。注意广播地址0不能在这个字段中使用,因为它是一个无效的“源”地址。
6uint8_t compid组件ID(发送方)1 - 255发送消息的组件 ID。用于区分“系统”中的“组件”(例如自动驾驶仪和摄像头)。在MAV_COMPONENT中使用合适的值。注意,广播地址`MAV_COMP_ID_ALL '不能在这个字段中使用,因为它是一个无效的地址。
7 to 9uint32_t msgid:24消息ID(低、中、高字节)0 - 16777215有效载荷中消息类型的ID。用于将数据解码回消息对象。
For n-byte payload: n=0: NA, n=1: 10, n>=2: 10 to (9+n)uint8_t payload[max 255]载荷消息数据。取决于消息类型(即消息ID)和内容。
(n+10) to (n+11)uint16_t checksum校验和(低字节,高字节)CRC-16/MCRF4XX用于消息(不包括magic字节)。包含CRC_EXTRA字节。
(n+12) to (n+25)uint8_t signature[13]签名(可选)签名,保证链路不被篡改。
  • 不带负载的确认报文最小长度为12字节。

  • 签名消息最大长度为280字节,使用整个负载。

3.3. incompat_flags (MAVLink 2)

不兼容标志用于指示MAVLink库必须支持的功能,以便能够处理数据包。这包括任何影响数据包格式/顺序的特性。

如果 incompat_flags 字段中无法识别, 则 MAVLink 必须丢弃

支持的不兼容标志包括(在编写时):

标记C标志特性
0x01MAVLINK_IFLAG_SIGNED数据包被签名(一个签名已经被附加到数据包上)。

3.4. compat_flags (MAVLink 2)

兼容性标志用于指示功能不会阻止MAVLink库处理数据包(即使功能不被理解)。这可能包括,例如,一个标志,表明一个包应该被视为“高优先级”(这样的消息可以由任何MAVLink实现处理,因为包的格式和结构不受影响)。

MAVLink实现可以安全地忽略它在compat_flags字段中不理解的标志。

3.5. Payload 格式

MAVLink不包括有效载荷本身的消息结构信息(为了减少开销)!相反,发送方和接收方必须对在线格式的消息字段的含义、顺序和大小有共同的理解。

消息在MAVLink包中编码:

  • msgstr(消息id)字段标识包中编码的特定消息。

  • 有效负载字段包含消息数据。

    • MAVLink对负载中的消息字段重新排序,以便进行在线传输(根据原始XML消息定义中的顺序)。

    • MAVLink 2在发送消息之前在有效载荷的末尾截断任何零填充的字节,并适当地设置包len字段(MAVLink 1总是发送所有字节)。

  • len字段包含有效负载数据的长度。

  • 一个CRC_EXTRA字节被添加到消息校验和中。接收方可以使用它来确认它是否与有效负载消息格式/定义兼容。

如果消息规范不兼容,MAVLink库应该在解码期间通知坏的CRC(例如,C库 mavlink_parse_char() 给出一个状态MAVLINK_FRAMING_BAD_CRC)。

3.6. 字段重新排序

消息有效负载字段重新排序以进行传输,如下所示:

  • 字段根据其原生数据大小排序:

    • (u)int64_t, double (8 bytes)

    • (u)int32_t, float (4)

    • (u)int16_t (2)

    • (u)int8_t, char (1)

  • 如果两个字段具有相同的长度,则它们的顺序将保持在数据字段大小排序之前的顺序

  • 数组是根据它们使用的数据类型处理的,而不是根据数组的总大小

  • 空中顺序与struct相同,因此表示重新排序的字段

  • CRC_EXTRA字段在重新排序之后计算,以确保在字段重新排序期间的错误将被错误的CRC捕获。提供的Python, C和c#参考实现经过测试,具有正确的字段重新排序,这只是自定义实现的问题。

上述重新排序的唯一例外是MAVLink 2扩展字段。扩展字段按xml声明顺序发送,不包括在CRC_EXTRA计算中。这允许将新的扩展字段附加到消息的末尾,而不会破坏二进制兼容性。

这种排序是唯一的,并且可以通过使用稳定的排序算法在协议生成器中轻松实现。使用排序的替代方法是要么使用低效的对齐,这对于典型的MAVLink应用程序的目标体系结构是不利的,要么按照变量大小的顺序而不是应用程序上下文的顺序进行函数调用。这将导致序列化函数的函数签名非常混乱。

3.7. 空字节有效载荷截断(MAVLink 2)

MAVLink 2 实现必须截断任何空(零填充)字节在序列化的有效载荷结束之前,它被发送。这与MAVLink 1形成对比,在 MAVLink 1 中,无论内容如何,都为所有字段发送字节。

如果一个实现接收到一个(不兼容的)MAVLink 2消息,后面的字节为零,那么它必须仍然支持对消息的解码(如果它是有效的),并提供路由/转发消息的方法。消息可以完全不加更改地转发(即,没有修剪的零和原始CRC),或者转发实现可以修剪零并重新计算CRC。

实际受影响的字段/保存的字节取决于消息及其内容(MAVLink字段重新排序意味着我们可以说的是,任何截断的字段通常是那些具有最小数据大小的字段,或扩展字段)。

3.8. CRC_EXTRA 计算

CRC_EXTRA CRC用于验证发送方和接收方是否对特定消息的线上格式有共同的理解。

校验和,两字节,采用CRC-16/MCRF4XX计算,校验计算的时候不但要算进去收到的1-n+6范围内的数据,还要加上一个CRC_EXTRA。

4. 消息签名(身份验证)

MAVLink 2增加了对消息签名的支持,它允许MAVLink系统验证消息来自可信来源。

本主题提供了消息签名的总体概述,这对使用现有MAVLink库的开发人员和新MAVLink代码生成器的编写人员都很有用。它解释了系统如何确定消息是否被签名以及签名是否有效,如何允许未签名的消息被接受,以及如何创建和共享用于创建签名的“秘密”。

使用现有 MAVLink 库的开发人员可以在这里找到更多详细信息:

4.1. Frame Format

对于已签名的数据包,不兼容标志字段0x01位设置为true,并且附加13字节的“签名”数据附加到数据包中。签名包格式如下所示。

MAVLink 2 Signed

签字的13字节为:

数据描述
linkID (8 bits)发送数据包的链接ID。通常与channel相同
timestamp (48 bits)2015年1月1日GMT时间以来的10个微秒时间戳。每个消息链接必须单步增加。请注意,如果数据包平均每秒100,000多个数据包,那么时间戳可能早于实际时间
signature (48 bits)基于完整的数据包、时间戳和秘密密钥,数据包有48位签名

linkId: 8位链接ID,确保了签名系统对多链接 MAVLink 系统的支持。 每个协议实现方都应该指定一个链接ID,指定它启用的 MAVLink 通信渠道,并将此ID置于链接ID字段中。 链接 ID 特别重要,因为不同链接(如WiFi,加上遥控无线电广播)之间可能存在巨大的潜在差异。

signature: 48位(6byte) 签名是 完整包的SHA-256 哈希值的前48位(不包括签名字段,但包括时间戳)。 密钥是 MAVLink 通道(即自动驾驶仪、地面站或 MAVLink API)两个终端储存的二进制数据的32字节。

这如下所示, 其中 + 表示串联, sha256_48() 是一个 sha256 实现, 它返回正常 sha256 输出的前 48位:

 signature = sha256_48(secret_key + header + payload + CRC + link-ID + timestamp)

Timestamp: 时间戳是48位,从2015年1月1日起,单位为10微秒。 对于1970/1/1以来可用的系统(unexpoch),可以使用1420070400 秒的偏移值参与计算(即2015/01/01到1970/01/01差了1420070400秒)。

生成的所有时间戳必须至少比同一会话中同一链接 (SystemID、组件 id、LinkID) 元组发送的上一个时间戳多1。 如果以每秒超过 100,000 个数据包的速率突发数据包,则时间戳可能会早于 GMT 时间。

MAVLink 启用的设备可能不知道当前的 GMT 时间,例如,如果没有可靠的时钟源,或者,如果它刚刚启动,并且尚未从GPS 或其他系统中获得时间。 系统应当执行以下规则,以获得可靠的时间戳:

  • 当前时间戳应定期储存在持久性储存中(最好至少每分钟一次);

  • 启动时使用的时间戳应该是系统时钟和存储时间戳的最大值;

  • 如果该系统没有一个 RTC 机制,则应当更新其在全球定位系统锁定时的时间戳;应该使用全球定位系统和存储时间戳的最大时间戳;

  • 从特定链接发送的每个消息中,时间戳应增加一个;

  • 当正确签名的信息被解码时,时间戳比当前时间戳大时,时间戳应替换。时间戳绝对不能来自错误签名的包(即使它们已经被 accepted)

  • 收到的信息上的时间戳,应当与前一个收到的同链接(linkID,srcSystem,Srcontents) 的时间戳进行对比,如果时间戳较小,则该消息被否决;

  • 如果先前没有收到具有给定 (linkID,srcSystem,SrcComponent) 的消息,则如果它比当前时间戳晚不超过 600 万(一分钟),则应接受该时间戳; 对于在持久存储中存储时间戳的设备, 实现方可以通过存储两个时间戳值来防止抢占条件。 在写入时, 应更新两个值中较小的值。 在读取时, 应使用两个值中较大的值。

4.1.1. 接受签名包

当签名的数据包到达时, 如果出现以下情况, 则应将其丢弃:

  • 时间戳比来自同一逻辑流的上一个数据包小,即时间更早, 其中逻辑流被定义为具有相同 (SystemID、ComponentID、LinkID) 元组的 MAVLink 数据包的序列;

  • 计算的48位签名与数据包中包含的签名不匹配;

  • 时间戳在本地系统的时间戳后面超过 1分钟 (6, 000, 000);

4.1.2. 接受未签名包

MAVLink 库应该提供一种机制, 允许系统有条件地接受未签名数据包。 接受这些数据包的规则将是实现方指定的, 可以基于参数设置、传输类型、消息类型、兼容性标志和非兼容性标记等的组合。 所有不符合系统特定的未签名数据包接受规则的数据包都必须被拒绝 (不利于鉴权验证)。

关于何时接受未签名数据包的一些建议:

  • 接受基于系统特定参数的所有未签名数据包;

  • 如果连接是通过 "安全通道" (例如本地 usb 电缆或本地有线以太网电缆), 则接受所有未签名的数据包;

  • RADIO_STATUS 数据包总是在不签名的情况下被接受 (以便使遥测数传的工作更轻松);

  • 在 "无签名模式" (可能由启动时按下的硬件按钮触发) 时接受所有未签名的数据包;

  • 接受所有未签名的数据包,直到收到签名的数据包(无条件),然后转到上面更受限制的签名规则;

4.1.3. 接受签名不正确的数据包

MAVLink 库应该提供一种机制, 允许系统有条件地接受签名不正确的数据包。 此功能可能有助于查找带有损坏的密钥的失联设备 (gcs 可以选择仍然显示位置信息, 尽管理想情况下使用不同的 "不受信任" 图标)。 接受错误签名数据包的系统应该提供一个非常明显的指示,表明连接是不安全/不安全的。格式错误的签名数据包表示配置错误、传输故障、协议故障或恶意操纵。

4.1.4. 密钥管理

密钥是32字节的二进制数据, 用于创建可由密钥的其他持有者验证的消息签名。 密钥应在网络中的一个系统 (通常是 GCS) 上创建, 并通过安全通道共享到其他受信任的设备。 系统必须具有共享密钥才能进行通信。 密钥应存储在持久存储设备中, 并且不得通过任何可公开访问的通信协议公开。 特别是, 密钥不得在可以用于公共日志分析的 MAVLink 参数、MAVLink 日志文件或数据闪存日志文件中公开。

生成密钥的方法取决于实现。 例如, 它可以通过以下方式生成:

  • 用户输入的字符串, 然后通过 sha-256 运行。

  • 随机密钥生成器。

密钥可以使用 SETUP_SIGNING 消息共享到其他设备。 该消息只能通过安全链接 (如 USB 或有线以太网) 发送, 作为直接消息发送到每个连接的 system_id/component_id。 必须设置接收系统来处理消息, 并将接收到的密钥存储到相应的永久存储中。

可以使用相同的安全方法来设置和重置系统的密钥(重置密钥不一定比首先设置它“更安全”)。

不应广播 SETUP_SIGNING 消息, 接收到的 SETUP_SIGNING 消息不得自动转发到其他活动的 MAVLink 设备/流通道。 这是为了避免通过安全链接 (如 usb) 收到的密钥通过不安全的链接 (例如 wifi) 自动转发到另一个系统的情况。

我们建议 GCS 实现生成密钥, 并通过安全链接 (例如 USB) 与连接的系统共享密钥。 可以将接收系统配置为忽略安全通道上的消息签名 (即接受所有签名、非签名或错误签名的数据包), 以便可以重置已丢失或损坏的密钥。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值