壹悟科技实现VDA5050协议大约有两年了,我们实现了基于该协议的调度系统,并在几款自研的 AGV 车体实现了该协议。
同时也和国内外数家 AGV 厂商实现了标准对接,这期间大家互相促进学习。在这个过程中我们将协议一次实现,多次对接(不同的协议版本,不同的厂家,不同的车型),每一次都会有更深的领悟。
本系列旨在分享我们在这个过程中对 VDA5050 协议的理解和实现。
本文试图从通讯角度探幽协议,对VDA5050语焉不详或需要留意的地方加以拆解。
消息可靠性策略
为了减少通信开销,MQTT QoS 级别 0(尽力而为)将用于order、state、factsheet和visualization等topic。“connection” topic 应使用 QoS 级别 1(至少一次)。
这是一个容易被忽略的细节,在协议里也只有一句话带过,没有解释为什么。
VDA5050 作为一个通讯协议,除了基础功能外,状态一致性是协议要解决的一个重要问题。这个问题在软件行业的分布式系统中已经被广泛的研究和分析,以Paxos论文为代表,衍生出大量的中间件、协议和框架来解决这个问题。
在 AGV 领域的通讯对可靠性的要求和软件行业略有不同;举例说明它们的差别。
在一个交易场景中,一个支付请求或支付确认一旦被发送到消息队列中,那么确保消费者能够收到消息,加上消费方的幂等机制;再加一个死信队列做兜底,基本上可以认为这是一条可靠的链路(基于 RPC 调用原理类似)
在 AGV 的场景下,AGV 的状态实时变化。基于某个时刻的 AGV 实时状态 (坐标,角度,速度,机构装置状态等 ) 主控做出了决策,如果 AGV 由于任何原因(可能断网,重启,被人工干预,比如挪动过位置)错过了当前下发的Order,那么作为通讯协议的 VDA5050 一味的追求 ”使命必达“ 没有任何价值和意义,换句话说,提高消息可靠性没有意义,甚至有害(比如,即使关机了也坚持不懈的重发,哪怕 AGV 关机维修过了半个月重新入网,坚持让它把历史任务完成)。
因此,我们回到 VDA5050 协议的 QoS 定义:
为了减少通信开销,MQTT QoS 级别 0(尽力而为)将用于order、state、factsheet和visualization等topic。“connection” topic 应使用 QoS 级别 1(至少一次)。
用简单的说就是order丢了就丢了,有什么大不了的呢?如果需要重发,那么合理的方式是 MC 根据当前的实时状态,重新构造一个新的order下发,而不是坚持重发老的order。
为什么connection的 QoS 级别是 1 呢?因为connection是 AGV 接入 broker 的第一条消息,MC 如果依赖 connection 来建立后续的流程,如果要严谨实现,如果错过了这个消息,那么就会导致后续的流程无法建立。(不严谨的实现,如果收到一个state但是发现没有这个 agv 的上下文,在一定的时效内可以把这个state本身当做一个conneciton ONLINE)
如果 MC 收到多个 connection 会怎么样呢?无所谓, MC 可以只处理一个,QoS=2 没有必要。
等待戈多
作为 AGV 调度系统最常被问到的问题是: 为什么 AGV 会停在路上不动了?
这个原因可能有无数个,我们先不考虑硬件相关的故障。站在通讯的视角,最常见的原因是在壹悟内部被称为“死等”的现象:
- • 调度系统认为已经给 AGV 下发了指令,接下来会持续的等待完成
- • AGV 没有收到指令(或收到后重启了),一直等待
以通讯的视角来看,或者协议的状态机有问题,或者协议的实现有问题。我们看下 VDA5050 的协议对这个问题是否有解。
在传统的分布式系统中,系统之间的调用有上下游关系;且有各种重传、超时机制的支持,比如Hystrix,Sentinel等;另外每次的调用几乎都是独立/幂等,不会有上下文的依赖。
在 AGV 调度中,如果不确定叉车是否收到和执行了取货指令,无脑的执行重发;严重的情况下会导致车货损毁。
在 VDA5050 协议里提供了充分的消除“死等”的机制:
-
• 1 AGV 上报的 state 里有 orderId 字段,用于标识当前执行的指令,MC 可以通过比较自身持有的最新下发的orderId和上报的orderId是否一致来判断 AGV 是否收到了指令
- • 1.1 如果 AGV 上报的state里包含nodeStates/edgeStates/actionStates,且有任何一个包含没有结束的状态,那么可以认为 AGV 正在执行指令,这时 MC 可以选择等待,也可以选择取消指令(通过cancelOrder)
- • 1.2 如果 AGV 上报的state里的状态都是结束状态(协议 6.11 FINISHED/FAILED),那么可以认为 AGV 是静止待命状态,这时 MC 可以选择重新下发当前指令,也可以废弃当前指令重新构造和下发。
注意,在 VDA5050 协议中的Figure 8 AGV 接受 order 或 路段追加的过程 一图中,只介绍了 AGV 收到了新的 Order 后的处理流程。上述过程是站在 MC 的角度,对收到 AGV 上报的state 后如何处理当前 Order 的过程。
总结
本文从两个微不足道的细节入手,分析了VDA5050协议对消息可靠性的选择的内在原因,以及如何基于协议的机制消除“死等”的问题。
文/栾瑞鹏