AGV的廠商如此多,各家發展各自的通訊協定,互不相容是很常見也很合理的現象。但筆者最近就接觸到這麼一個協定,希望一統各廠車子與車隊系統,使其可以互相支援,那就是VDA5050。這篇文章不會詳細說明VDA5050 v2協定的所有細節,而是用筆者理解的角度來介紹,讓不熟悉的人可以快速掌握基礎架構和流程。
大綱
- 什麼是VDA5050
- 協定要求與規格
- 對不同角色帶來什麼好處
- 協定規範概要
- 移動交握流程說明
- 動作交握流程說明
- 整合常見問題
什麼是VDA5050?
由德國汽車工業協會 (VDA) 與 物料搬運和內部物流協會 (VDMA) 合作定義的AGV通訊協定,包含
- 通訊技術與相關參數
- 通訊格式
- 交握流程
- 車輛移動流程
- 車輛動作流程
協定的內容公開在 Github 上的 VDA5050 專案,目的是希望做到跨廠商的車隊系統和 AGV 可以互相支援,可以買 A 廠商的車隊,去控制 B 和 C 廠商的 AGV。事實上,在2023年的 AGV Mesh-Up 活動上有實際展示了這個成果,如下影片:
這個協定覆蓋的範疇僅限於車隊系統和 AGV 之間的交握流程,對於車隊系統來說,不會涉及到管理和運作層面的機制,像是任務優先順序、交管的演算法等等,只要你的演算結果依照他的格式和流程傳給 AGV,就算符合,對於AGV來說亦然,不涉及運動控制演算法、是否包含地圖甚至是路徑來自車隊或 AGV 等作法。
協定要求與規格
依照官方的定義,此協定必須
- 使用 MQTT 3.1.1以上的版本,並訂閱特定的 Topic
- 使用 JSON 格式傳輸,屬性名稱以英文為主,確保可讀性
- AGV 必須定期或在狀態變更時回傳狀態
並且具備規格如下
- 可控制至少1000台車
- 連線失敗和訊息丟失不影響協定運作
當AGV的MQTT斷線時,車隊可以知道車子斷線,如果有重複訊息或是漏訊息,可從內容判斷處理避免例外狀況。 - 對各種車輛允許不同程度的支援
協定內有定義Optional屬性,可依 AGV 規格決定是否使用,針對動作的部分,也有定義清楚各 AGV 支援程度,避免傳送指令給不支援的 AGV 造成錯誤,要自訂動作也是沒問題的。
對不同角色帶來什麼好處
使用者:
- 通用協定提高了廠商選擇性,車輛和車隊系統不再綑綁銷售。若僅 A 廠商 AGV 具備所需特性,即便其車隊系統功能較弱,仍可選用其他品牌的車隊系統整合。
- VDA5050 增加了交握流程的透明度,以往車隊與 AGV 的交握流程通常不可見,協定也被各廠商視為機密,整合只能依賴廠商提供的工具,受限頗多。使用 VDA5050 後,交握流程以明碼傳輸,廠內自行開發的程式也可透過 MQTT 即時掌握 AGV 動態。
AGV 開發商:
- 不用再自行摸索交握流程,有現成的協定可以參考,對於一些容錯或是異常的 case 都可以借鑑
- 可以專精一個面向,專心研發 AGV,或是車隊系統,如果協定使用者基數夠大,就不用擔心相容的問題
協定規範概要
VDA5050 對於不同功能目定義了MQTT 的 Topic ,格式如下:
{interfaceName}/{majorVersion}/{manufacturer}/{serialNumber}/{topic}
ex: uagv/v2/KIT/0001/order
| 名稱 | 說明 |
|---|---|
| interfaceName | 使用介面,沒有明確的定義,依需求定義即可 |
| majorVersion | 協定的主要版號,開頭須為v,因應主版號相同即相容,所以不管車子是2.0.0還是2.1.0都會使用相同的主版號 |
| manufacturer | 各廠車子會用自己的名稱,不同廠牌也可共存 |
| serialNumber | 車子的序號 ID,理論上是唯一碼 |
| topic | 協定定義的各個主題,像是 order、state 等各有各的目的 |
topic主要包含以下幾個面向
| 名稱 | 說明 |
|---|---|
| order | 車隊發送給車子的任務細節,包含路徑上點 (Node) 和線 (Edge),有詳細定義各點線參數,包含座標、角度、預計執行的 action 等 |
| instantActions | 不受限於地圖位置的 action,收到後立即執行,理論上不能和 order 中的 action 衝突,例如 order 中的 action 要上升機構,但 instantAction 卻要下降機構 |
| state | AGV 的當下位置、座標、action 執行狀態、錯誤警告、電量等訊息,也可自行擴充內容到到 information 欄位,但須注意車隊不得依賴該欄位來進行邏輯判斷,僅作為呈現使用 |
| visualization | 僅包含 AGV 當下位置,降低資料量配合高頻率傳輸讓 UI 上車輛位置更平滑 |
| connection | 車子的連線狀態,由車子發送上線訊息,當車子與 MQTT host 斷線時,藉由 LastWill 機制讓 broker 發送斷線訊息,確保車隊掌握連線狀態 |
| factsheet | 車子的規格,包含尺寸、車子類型、機構類型、支援的 actionType 等等,還有車子速度、加速度、高度上限等資訊,讓車隊可以分辨對應任務的車子 |
不論是哪一個 topic,內容都會包含這些固定屬性,方便接收端解析和判斷
| 屬性 | 說明 |
|---|---|
| headerId | 數字號碼,依每個 topic 區分,每發送一則訊息便會加 1 |
| timestamp | 時間戳 (ISO 8601, UTC); YYYY-MM-DDTHH:mm:ss.ffZ (e.g., “2017-04-15T11:40:03.12Z"). |
| version | 協定版本,[Major].[Minor].[Patch] (e.g., 1.3.2). |
| manufacturer | 各廠車子會用自己的名稱 |
| serialNumber | 車子的序號 ID |
關於state=>errors錯誤資訊部分,官方並未明定車子的錯誤類型,由各車子自行定義,僅有定義少部分警告訊息,用來告知車隊 order 被拒絕或者 order 的位置有誤等
移動交握流程說明
這邊以官方的圖片來說明,首先是地圖,地圖的組成為最基礎的點 (Node) 和線 (Edge),其中傳輸時,又會分為 AGV 已獲得路權 (Base) 允許行走和未獲得路權 (Horizon) 不得行走,AGV 會移動到 Base 的最後一個點,然後等待下一個任務更新資訊 (orderUpdate)。

車隊端
任務發起端為車隊系統,透過 Topic order 向目標車輛發出任務,重點內容如下,詳細的欄位請參照官網
| 屬性 | 說明 |
|---|---|
| orderId | 任務的唯一碼,只有一個目的地,不允許一個order多個目的地 |
| orderUpdateId | 任務更新唯一碼,任務有可能會分成多筆資料分批傳給 AGV,當任務路徑很長,只能先將,又或者部分其中一個點 (Node) 或線 (Edge) 被其他車占用時,需要分多筆 orderUpdate 來傳輸,每一筆不包含上一次的路徑,AGV 端需自行縫合 |
| Base nodes | 車隊已將路權分配給 AGV 的點,會包含各點個ID和順序編號,該點的座標以及 AGV 車頭角度,在該點要執行的 action,後續不允許變更路線 |
| Base edges | 車隊已將路權分配給 AGV 的線,會包含各線個 ID 和順序編號,該線的起訖 Node、允許最高速度、車頭角度,在該點要執行的 action,後續不允許變更路線 |
| Horizon nodes | 屬性同上,但尚未取得該點的路權,車隊有可能在下一次 orderUpdate 變更路線 |
| Horizon edges | 屬性同上,但尚未取得該點的路權,車隊有可能在下一次 orderUpdate 變更路線 |
AGV端
AGV 端會藉由 Topic State 內容讓車隊確認是否收到 Order,是否正在行駛,目前走到哪個位置,還有多少路未完成,以下列出移動相關重點的屬性與說明,完整的欄位請參照官網
| 屬性 | 說明 |
|---|---|
| orderId | AGV 最後接受的 orderId |
| orderUpdateId | AGV 最後接受的 orderUpdatedId |
| lastNodeId | AGV 最後經過的點,即便已經離開,只要還沒到下一個點,就是維持上一次的點 |
| lastNodeSequenceId | 最後經過點的順序,路徑若有重複的點,可用此順序來判斷 |
| nodeStates | 從 order 收到,還未走到的node清單,一旦走到該點,更新 lastNodeId 時,便會從此清單移除 |
| edgeStates | 從 order 收到,還未走到的edge清單,一旦走下一個點,更新 lastNodeId 時,便會從此清單移除 |
| agvPosition | AGV 的當前座標、角度 |
| driving | 是否正在行駛 |

協定特性
- 網路異常不中斷:當 AGV 網路斷線時,會依既有的 Base 路徑行駛,因路權已取得,不會發生路徑衝突。行駛結束後,AGV 會停在最後一點等待新路徑。連線恢復時,AGV 會以當前點回報狀態,即使中途各點狀態未回傳,車隊系統仍能以最後狀態更新資料並繼續發送 OrderUpdate。
- 資料異常回報機制:當 AGV 接收到不合理的 Order 時,例如起始地點非當前位置或仍在執行上一筆 Order,AGV 會啟動 Rejection 機制,在 errors=>warning 訊息中回報錯誤,並拒絕處理該 Order。
動作交握流程說明
VDA5050 中的 action 泛指 AGV 執行的動作,主要包括車體操作如充電、等待、暫停、初始化位置、物件偵測、精準對位、取消任務等。若車上具備可控設備,則涵蓋取放貨物等操作。以上提到的 action 均已在 VDA5050 中預定義,若需自定義 action 也可依格式擴充。
action的執行時機
action 可預先定義於地圖上的 Node 和 Edge,AGV 到達該位置時自動執行對應的 action。若需動態指定 action,可透過 topic instantActions 傳送,不受地點限制,AGV 會立即執行。
action的重要屬性
| 屬性 | 說明 |
|---|---|
| actionType | 各種 action 的類型,可自行定義 |
| actionId | 用來追蹤特定 action 的狀態,建議使用 UUID |
| blockingType | action 的執行方式,分為以下幾種: NONE:此 action 可與其他 action 並行執行,且車輛可同時行駛 SOFT:此 action 可與其他 action 並行執行,但車輛不可行駛 HARD:此 action 不可與其他 action 並行執行,且車輛不可行駛 |
| actionParameters | 該 action 所需的相關參數,以 key value 的方式傳輸,並未定義明確的參數名稱 |
action的狀態
AGV 收到 action 後,會在 state 中回報 actionStates=>actionStatus,定義如下,狀態機可以參照官網
| 狀態 | 說明 |
|---|---|
| WAITING | AGV 已接收到指令,但尚未到達觸發的 Node 或未進入啟動的 Edge |
| INITIALIZING | 已觸發 action,正在進行準備工作 |
| RUNNING | action 正在執行中 |
| PAUSED | action 因為 pause instantAction 或外部觸發(例如 AGV 上的暫停按鈕)而被暫停 |
| FINISHED | action 執行完成,結果會通過 resultDescription 回報 |
| FAILED | action 無法完成,需在 errors 內回報原因 |
action的流程

- 左欄:地圖無action時,AGV 依照路徑移動
- edgeStates 會包含當前正在走的線 e1
- 一旦到了點 n2,e1 就會移除
- 同理,一旦到 n2 後,n2 就會從 nodeStates 中移除
- 中欄:當 action 的 blockingType 為 NONE 時
- 移動和 action 可以同時進行,但執行時機仍以地點為主
- 可以允許 n2 上的 action 執行當下移動到 e3
- 右欄:當 node 上的 action 的 blockingType 為 SOFT 或 HARD 時
- 到達 n2 後,需停車等待 n2 的 action 完成
- 完成後才能往 e3 前進
協定特性
- 網路異常不中斷:斷線當下 AGV 仍可以執行已接收的 action,車隊收到最後一筆的 state 可以判定先前的 action 執行結果
- 資料異常回報機制:當 AGV 收到無法執行或互斥操作的action時,可以直接回報FAILED,並在errors回報錯誤讓車隊系統知悉
整合常見問題
我要的 AGV 資訊沒有在協定定義中,是否全部都放在 state=>information 內就可以了
只要是不涉及流程和邏輯判斷的部分,純顯示類型的都可以放在 information 內,若是有自己的完整流程,例如升級 AGV 內的軟體,可以使用 action 的流程,但如果中間有更多複雜機制,則建議另外使用其他管道通訊,最後結果回傳在 actionStatus 即可,不要任意擴充協定的格式,避免其他品牌車輛不相容
協定內沒有定義 AGV 本身狀態,我要如何判斷
VDA5050將AGV的狀態定義彈性留給車隊系統自行決定,可依照 nodeStates、edgeStates、driving、actionStates 等資訊來判斷,以 open source 的車隊系統 openTCS 為例,AGV 狀態的對照方式如下:
- UNKNOWN:AGV 未連線
- UNAVAILABLE:state=>operatingMode 為車隊無法控制時
- EXECUTING:state 有未完成的點、線或 action 時
- IDLE:不符合其他狀態皆為此狀態
- ERROR:state 有任何 FATAL 等級的 error
所以整合部分狀態還是以車隊系統定義的為主
Reference: StateMapping.java
