進行中 Robotics ROS2 Embodied AI Edge AI

PawAI / Go2

我用 Unitree Go2、Jetson 與 ROS2 打造的多模態具身互動系統:從感知、語音與決策,到安全閘與可觀測工具。

PawAI 是我以 Unitree Go2 Pro 為載體,整合 NVIDIA Jetson、Intel RealSense D435、ROS2 與多模態 AI 所打造的具身互動機器狗。

我想做的不是把聊天機器人裝進機器狗,也不是把人臉、語音、手勢與物體辨識各自展示一次;我真正想解的問題是:機器人能不能把看見、聽見、理解、決策與行動串成一條可解釋、可降級,而且知道何時不該動的互動迴路?

完成硬體整合後的 PawAI:Go2 Pro 背負 Jetson、RealSense D435、RPLIDAR 與音訊設備

這張成品照背後,是八個多月的硬體改裝、模型選型、真機事故與系統重構。

一分鐘認識 PawAI#

PawAI 的核心可以濃縮成四步:

  1. 看見:由 D435 與感知模型辨識已註冊使用者、手勢、姿勢與近距離物體。
  2. 理解:把攝影機、語音與系統狀態整理成一致的 ROS2 事件。
  3. 決策:PawAI Brain 根據情境提出技能與回覆,但不直接控制機器狗。
  4. 行動:Interaction Executive 經過安全規則與狀態檢查後,才允許語音或實體動作送到 Go2。

PawAI 的設計底線:LLM 只能提案;production sport-motion 主線只能由 Executive 放行。音訊與 hard-stop 保留獨立路徑,而 hard-stop 仍需獨立審計與驗證。

先看完整 Demo#

這段影片會依序展示即時感知、語音互動、安全拒絕,以及 PawAI Studio 如何留下決策 Trace。它是 2026 年 6 月的系統快照,不代表下方列出的實驗能力都已達到產品等級。

完整 Demo:PawAI—基於多模態感知融合之自主尋物與具身互動。

我為什麼開始做 PawAI#

一開始,我接觸的是 Go2 的 ROS2 與 WebRTC 驅動。讓機器狗走動、取得感測資料或呼叫一個動作並不算最難;真正困難的是,當人臉、物體、姿勢、語音、導航與 LLM 同時加入後,到底由誰決定現在該做什麼?如果兩個模組同時要求機器狗動作,誰有最後控制權?雲端服務中斷、感知誤判或 LLM 說錯話時,系統又該怎麼退回安全狀態?

這些問題讓 PawAI 從一組功能原型,逐步變成一個完整系統工程專案。開發重心也從「再加一個模型」,轉向三件更重要的事:

  • 讓不同感知模組使用一致、可追蹤的事件契約。
  • 把決策與實體控制分開,避免 LLM 越過安全邊界。
  • 用證據與降級路徑描述能力,而不是只看 Demo 畫面有沒有成功。

這不是一開始就設計好的#

PawAI 啟動時,我仍是一個以 Web 與軟體開發為主、幾乎沒有機器人硬體整合經驗的學生。我們第一次挑戰機器人,就選了開發限制比 Go2 EDU 更多、主要依賴 WebRTC 與第三方 SDK 的 Go2 Pro

我粗估自己在這個專案投入超過 500 小時。只要晚上、週末或課業空檔能用,我幾乎都在接線、重跑、看 log、錄 bag、改參數,或把前一天看似可行的方案整個推翻。

從 2025 年 11 月到公開版前,repository 橫跨 138 個有提交紀錄的日子,留下超過 1,300 次由我提交的 commit;後來的 lessons-learned 又整理出 70 多個具名 failure modes。這些數字不能換算成工時或品質,卻留下了密集迭代的痕跡。

2025 年 11 月的一個週日,我從午餐後一路做到凌晨一點。日記裡寫著:「做到凌晨一點,卻覺得工程師可能真的是我的天職。」

從感知到行動:系統架構#

PawAI 是一個由十個主要 ROS2 套件組成的 workspace。感知、決策、行動與共享契約彼此分層,依賴方向朝向共用介面,而不是讓每個功能直接互相呼叫。

PawAI 系統架構:感知、決策、行動與共享契約

這張圖可以從下往上理解:Go2 Driver 與硬體負責「真的做事」;Executive 負責「允不允許做」;Brain 負責「現在最適合做什麼」;各個感知節點只負責把世界轉成事件。中間的 go2_interfacespawai_contracts 則像共同語言,規定事件、技能提案與執行結果應該長什麼樣子。

這個分層刻意避免兩種常見問題:第一,感知模組不能因為看到某個東西就直接命令機器狗;第二,新增一個模型時,不需要同時修改 Brain、Studio 與 Go2 Driver。每個 ROS2 node 可以獨立啟動、停止、測試與替換,整體系統仍透過固定契約協作。

感知層#

  • Face:人臉偵測、已註冊使用者辨識與追蹤。
  • Gesture / Pose:靜態手勢與人體姿勢事件。
  • Object:YOLO 物體偵測,結合 D435 深度取得近距離空間資訊。
  • Speech:ASR、固定指令意圖與語音輸入。

決策層#

  • PawAI Brain:整理世界狀態、對話脈絡與可用技能,提出下一步建議。
  • Interaction Executive:負責狀態機、安全閘與最終仲裁,是 production sport-motion 主線的中央 arbiter。

行動層#

  • 語音回覆:依序使用雲端與本地 TTS,失敗時能繼續降級。
  • Go2 Driver:透過 WebRTC 執行合法的機器狗動作。
  • Navigation:保留為有人監督的實驗能力,不列為目前已完成的公開成果。

真正跑在 PawAI 裡的模型#

PawAI 不是只寫「使用 AI」;每一條感知與語音路徑都有明確模型、執行位置、資源預算與 fallback。下面是 2026 年 6 月 Demo/公開版所採用的主線。

能力實際模型與管線執行位置為什麼這樣選目前邊界
人臉YuNet 2023mar 偵測 + SFace 2021dec embedding + IOU tracking/identity hysteresisJetson CPUYuNet 單模型 benchmark 71.3 FPS,不搶 YOLO 的 GPU低光、距離與 tracking 抖動仍會影響身分判斷
手勢MediaPipe Gesture Recognizer + 自製幾何/時序規則Jetson CPU實測約 7.2 FPS、GPU 0%,能和其他模型共存靜態手勢較可靠;動態 wave 尚未通過 baseline
姿勢MediaPipe Pose + COCO 17 點 adapter + 幾何分類器Jetson CPU實測約 18.5 FPS,不需把 GPU 塞滿awkward viewpoint 可能產生假 landmark;跌倒不作可靠照護宣稱
物體與顏色YOLO26n ONNX + onnxruntime-gpu TensorRT EP FP16 + OpenCV HSV 12 色Jetson GPU + CPU約 15 FPS;YOLO 負責類別,HSV 負責輕量顏色語意遠距小物與 cup/bottle 類別混淆仍是限制
ASRGPU Server SenseVoice → Jetson SenseVoice Local → Whisper Local遠端 GPU/Jetson雲端主線追求辨識品質,本地路徑保留降級能力麥克風、VAD、回音與網路仍會影響端到端表現
LLMOpenRouter openai/gpt-5.4-mini → 條件式 google/gemini-3-flash-preview → RuleBrainCloud/Jetson rules主線負責自然語言與 skill proposal;規則層保底LLM 永遠沒有直接 actuation 權限
TTS長句/情緒:google/gemini-3.1-flash-tts-preview → edge-tts → Piper;短句/安全:edge-tts → PiperCloud/Jetson CPU依品質、速度與離線可用性分流provider、音訊格式與 Go2 播放路徑都可能各自失敗
決策編排LangGraph Conversation Engine + Skill Registry + ExecutiveJetson把 world state、persona、記憶、模型決策與 trace 拆成可觀測節點LangGraph 只產生候選;production motion 由 Executive 放行

這張表看起來像最後答案,但模型選型曾經三次翻案。手勢/姿勢從 RTMPose 的 GPU 滿載,走到 DWPose 的 TensorRT 精度偏移與 JetPack 6 部署困境,最後才用實測推翻「MediaPipe 在 Jetson 不可行」的早期判斷。

真正的選型條件從來不只是單模型準確率,而是:在 8GB unified memory 上,當人臉、姿勢、手勢、物體與語音一起跑時,它還能不能活著?

一個事件如何變成動作#

以使用者對 PawAI 說「介紹你自己」為例,整條路徑不是一次 LLM call,而是六個可觀測步驟:

  1. Studio 或語音節點把輸入轉成 /event/speech_intent_recognized/brain/text_input
  2. Conversation Engine 整理輸入、短期對話、感知摘要、系統能力與目前狀態。
  3. LangGraph 產生自然語言回覆,以及一個可選的 skill proposal。
  4. Brain 檢查 allowlist、cooldown、確認條件與目前是否有其他 sequence 正在執行,再產生 SkillPlan
  5. Executive 重新用最新 world snapshot 驗證計畫,接著依序分派 SAYMOTIONNAV step。
  6. 每一步的 accepted、started、blocked、failed 或 completed 結果,都會回到 Brain 與 Studio。

因此,就算自然語言回覆可以播放,動作提案仍可能被拒絕。「有回答」與「有權移動機器狗」在 PawAI 裡是兩件分開的事。

LLM 為什麼不能直接控制機器狗#

在 PawAI 裡,Brain 不是「想做什麼就做什麼」的 Agent。它產生的是一份提案,真正執行前還要經過三層處理:

  1. Safety:先攔截危險、緊急或未授權的要求。
  2. Policy:根據目前狀態與允許的技能決定能不能執行。
  3. Expression:最後才決定要怎麼說、怎麼呈現在 Studio,以及是否送出合法動作。

PawAI Brain:Safety、Policy、Expression 與 Executive 的 production motion 仲裁

這個設計不是為了讓架構看起來比較複雜,而是因為機器人會真的移動。當模型產生錯誤內容、感知資料不足,或系統同時收到多個事件時,預設不動、拒絕越權,以及保留人工介入,比讓 Demo 看起來更聰明重要。

目前能公開確認的是:deterministic Safety Gate 與技能 allowlist 的機制存在,並有單元測試保護;這不等於 PawAI 已經不會幻覺,也不代表所有安全情境都完成了實機端到端驗證。

LangGraph 怎麼參與決策#

PawAI 使用 LangGraph 編排 Conversation Engine,但它負責的不是馬達控制,而是把原本塞在單一 LLM bridge 裡的責任拆成可觀測的決策節點。實作上共有 12 個 graph stages;下方把它們合併成九個較容易閱讀的概念階段。

早期版本的 llm_bridge_node 同時負責 ROS adapter、Persona、模型 fallback、對話歷史、環境資訊、JSON 解析與 TTS 輸出。程式一路成長到很難定位錯誤;有一次中文回答總是在逗號附近被截斷,最後才發現不是模型問題,而是 Jetson 的 stale install/ 還留著舊版截斷邏輯。這讓我決定把 conversation orchestration 獨立成 pawai_brain package。

LangGraph 把一輪對話拆成類似以下的 pipeline:

  1. Input normalization:統一文字、語音與事件輸入。
  2. Safety gate:先處理停止、緊急與禁止情境。
  3. World state:加入目前人臉、物體、姿勢、障礙與 TTS 狀態。
  4. Capability context:只把現在可用的 SkillContract 提供給模型。
  5. Memory / Persona:加入短期對話與 PawAI 的表達方式。
  6. LLM decision:產生 reply、可選的 skill 與參數。
  7. JSON validation / repair:結構錯誤時修復,失敗則回到規則式 canned response。
  8. Skill gate:由 Brain 判斷提案是 accepted、trace-only、blocked,或不在 allowlist。
  9. Output / trace:輸出回覆與提案,並把每一階段送到 Studio。

Conversation Engine 的輸出契約刻意很小:

{
"reply": "我是 PawAI,一隻正在學習理解環境的機器狗。",
"skill": "self_introduce",
"args": {}
}

reply 可以成為語音;skill 只是提案。像 show_status 這類低風險技能可以經 gate 後執行,而較長的動作序列可以只留下 trace,改由 Studio 按鈕在有人控制的情況下觸發。導航與高風險動作不會因為 LLM 提議就自動開放。

為什麼要有 Primary 與 Shadow Engine#

LangGraph 不是一次取代舊系統。開發期間,我用 feature flag 讓 legacy 與 LangGraph 分別擔任 primary 或 shadow:primary 是唯一能發布 /brain/chat_candidate 的 engine;shadow 收到相同輸入,但只輸出 trace 供比較。

這種遷移方式讓我可以先比較兩個 engine 的回覆、結構與錯誤,再決定是否切換主線。新架構失敗時,舊路徑仍能工作;而且 Brain 只依賴固定的 chat_candidate 契約,不需要知道候選結果來自哪一個 engine。

Edge、Cloud 與 Go2 怎麼協作#

PawAI 並不是把全部工作都丟到雲端,也不是要求 Jetson 獨自完成所有推論。部署被拆成四個角色:

位置主要工作斷線時的行為
Jetson Orin NanoROS2 runtime、感知、Brain、Executive、部分本地語音保留本地感知、規則與安全路徑
開發機/操作筆電PawAI Studio、投影與人工操作Studio 中斷不會繞過或改變 Executive
雲端模型服務高品質 ASR、LLM 與 TTS依序降級到替代模型、本地模型或 RuleBrain
Unitree Go2Sport API、Megaphone 與實體動作production sport 主線走 Executive;音訊與 hard-stop 有獨立路徑

ASR、LLM 與 TTS 都設計了多層 fallback。Jetson 麥克風路徑可從 SenseVoice cloud 退到 local/Whisper;LLM 可退到替代模型與 RuleBrain;TTS 可退到 edge-tts/Piper。安全層、allowlist 與 Executive 則留在本地 runtime。

這不等於完整斷網語音閉環已被驗證。Studio 的筆電收音路徑目前仍只走 cloud SenseVoice,離線時會成為單點故障;因此 offline-first 是架構方向,不是目前已通過 baseline 的公開能力。

Repository 仍保留 legacy/demo 直發 publisher;production flags 必須將它們關閉。這是尚未完全消失的技術債,不能把「設計約束」誤寫成整個 repo 已無例外。

在 production flags 關閉 legacy/demo publisher 時,Brain 停止便不會產生新 proposal;Executive 停止則會關閉一般 sport-motion 主線。音訊與 hard-stop 仍刻意獨立,後者尚需完成獨立審計與驗證。

PawAI Studio:讓機器狗不再是黑箱#

整合多模態系統後,最常遇到的問題不是「完全沒資料」,而是資料到了、某個模組也判斷了,但最後沒有動作。只看終端輸出,很難知道事件在哪一層被忽略、降級或擋下。

因此我做了 PawAI Studio:一個結合對話主控台、感知面板與決策 Trace 的操作介面。它讓操作者能同時看到感知事件、Brain 提案、Safety Gate 結果與 Executive 的最終決定。

PawAI Studio:即時感知、決策 Trace、Evidence 與人工介入

Studio 的價值不是用漂亮 UI 證明能力成功,而是保留一條可追查的證據鏈:機器狗為什麼有反應、為什麼沒有反應,以及是哪一層阻止了它。

目前做到什麼程度#

我不想用「支援很多功能」取代真正的驗證,所以 PawAI 把程式能力、開發觀察與可信的實測證據分開記錄。

能力目前狀態可以怎麼理解
已註冊使用者辨識受控條件通過單一已註冊使用者、有限距離與光線;不是門禁或通用身分驗證
近距離杯子辨識受控條件通過約 1 公尺、cup-only 場景;不宣稱 80 類物體都能穩定辨識
固定語音指令受控條件通過能把限定指令分類成系統意圖;不等於自由語音控制已可靠
Brain 安全閘機制與單元測試通過能擋未授權技能;尚不能宣稱 Brain 不會幻覺
動態揮手、語音停止尚未通過保留失敗紀錄,不作為目前成果展示
姿勢/跌倒情境證據不足可在 Studio 觀察開發訊號,但不作照護或安全宣稱
自主導航與動態避障實驗中只在有人監督、具備急停流程的環境測試,不宣稱完整自主導航

這張表不是缺點清單。對我來說,它記錄了 PawAI 最重要的一次轉變:從展示功能,走向只對證據允許的範圍負責。

這套架構,是被失敗逼出來的#

如果只看現在的架構圖,很容易誤以為我們一開始就知道 Brain、Executive、LangGraph 與 Safety Gate 應該放在哪裡。實際上,很多邊界都是在硬體真的失控、模型真的誤判、Demo 真的卡住之後才寫進系統。

  1. 2025-11-18|畫面正常,控制卻全死。 我們逐層查 SDP、ICE、DTLS、SCTP,最後才定位到 aiortc 1.14 與 STUN 的相容問題。降回 1.9、移除 STUN 後,DataChannel 才從超時變成約 0.5 秒連上。
  2. 2026-03-21|模型選型三次翻案。 RTMPose 在 Jetson 上吃掉 91–99% GPU;DWPose 轉 TensorRT 後關鍵點偏移。最後是實機 benchmark 證明 MediaPipe CPU 路線更適合多模型共存。
  3. 2026-03 至 04|軟體第一次撞上供電與機構。 Jetson、D435、麥克風與喇叭背上 Go2 後,行走震動、USB 接觸、19V 供電與電流 spike 讓 Jetson 累計斷電八次以上。熱熔膠、泡棉與束帶都成了系統的一部分。
  4. 2026-04 至 05|沒聲音不代表 API 不存在。 Go2 Megaphone 對錯誤 payload 只會 silent-ignore,我們一度以為韌體拿掉 API,繞了近兩週遠路。另一晚換了三個模型仍截斷,真因卻是 ROS2 stale install/
  5. 2026-05 至 06|「速度歸零」竟然不等於停車。 Go2 Sport Mode 會忽略過小的 Move{x},沿用上一個命令滑行。事故迫使我們改用 StopMove(1003)、節流、heartbeat,並把 production sport 主線收斂到單一 arbiter。
  6. 2026-06|每個功能會跑,系統仍可能塞車。 Face、cup、pose、gesture 同時搶 TTS、Brain state、Go2 body 與 WebRTC owner。於是才有 pending queue、cooldown、phase gate、trace 與 fail-closed baseline。

這些事故不是勳章。每一次碰撞與誤判,都代表當時的安全設計還不夠完整。真正值得留下的是:我們沒有把失敗剪掉,而是把它轉成契約、測試、仲裁規則與更窄的公開宣稱。

八個多月的工程演進#

2025 年 10 月:我們甚至不知道這台狗能不能開發#

Go2 Pro 沒有 Go2 EDU 那條完整的官方 unitree_sdk2unitree_ros2 開發路徑。我們最後選擇在社群的 WebRTC bridge 上擴充,但當時連錯誤操作是否會傷到機器人,都只能非常保守地摸索。

2025 年 10 月,剛開箱、仍折疊在原廠泡棉箱裡的 Go2 Pro

2025 年 10 月:這不是成品照,而是一群機器人新手第一次面對 Go2 Pro。

2025 年 11 月:先讓 Go2 站起來#

我從 abizovnuralem/go2_ros2_sdk、WebRTC DataChannel 與 Sport Mode API 出發。11 月 8 日,Windows 開發環境終於讓 Go2 第一次站起、坐下;十天後,又因 aiortc/STUN 相容問題幾乎完全失聯。

接下來是 Windows、Mac VM、Ubuntu、ROS2、RViz2、Foxglove、雙網卡與 DDS 的連環坑。壞掉的 ROS2 安裝包、VM crash、CycloneDDS 舊語法與 SCTP timeout 疊在一起,光網路拓撲就花了好幾天。

2025 年 12 月至 2026 年 1 月:第一版尋物與視覺導航#

這時的流程還很直接:拍照、交給模型理解,再產生移動指令。12 月 9 日,我為了取得一張影像,花了三小時才發現是 ros2 daemon 快取讓 DDS discovery 卡住。

12 月中旬,純視覺避障只能做到約 50–60% 的開發穩定度。我們嘗試 Depth Anything、校正 Go2 廣角鏡頭距離,也把 Mac VM、Windows 與遠端 GPU 之間的 tunnel 串起來。

2025-12-15|視覺導航 v1。這是客廳探索階段的歷史快照,不代表可靠、通用的自主導航。

2026 年 1 月,Go2 背部仍只有魔鬼氈、臨時固定件與外接線

每加一個感測器,就要重新面對重量、供電、走線、散熱與維修方式。

1 月 7 日的報告反而成為轉折。教授指出「拍照 → LLM → 移動」太慢,也不夠安全。我們因此把重心移向 Jetson、D435、ROS2 即時感知,以及更底層的動作安全。

2026 年 3 月:十六個模型之後,感知主線才成形#

Face、Speech、Gesture、Pose 與 Object 不是一次加入。3 月 19 日,我用一晚建立第一版 benchmark framework、adapter、reporter、gate 與測試;接著實測 16 個模型,才抓出套件、精度與資源競爭問題。

我們踩過 onnxruntime-cpu 覆蓋 GPU、NumPy 2.x 衝突、舊 YuNet 在新版 OpenCV crash,以及 RTMPose 把手部關鍵點標到臉上的問題。最後才收斂成 YuNet/SFace、MediaPipe、YOLO26n 與 SenseVoice。

語音也不是接上麥克風就完成。VAD、回音、Whisper 幻覺、Go2 喇叭與 5.3–14.5 秒延遲,逼我們把外接麥克風、USB 喇叭、ASR、TTS 與 Echo Gate 分開驗證。

2026-03-18|語音鏈早期測試。當時能發聲,距離穩定互動仍很遠。

2026 年 4 月:當軟體工程師開始拆機器狗#

Jetson、D435、RPLIDAR、麥克風與喇叭不會自己長到 Go2 背上。我們處理電壓、瞬間電流、USB 接觸、散熱、配重、視野與雷達方向,並由我自行 3D 列印背蓋與支架,才讓軟體有地方可以運行。

第一版 PawAI 感知硬體上機,包含 RPLIDAR、RealSense 與 edge compute box
第一版感知堆疊終於上機,但固定與走線仍充滿原型痕跡。
拆除 Go2 上蓋,處理內部線材、接頭與固定位置
第一次拆開上蓋,逐一確認接頭、線路、散熱空間與固定點。
Go2 裝上我自行 3D 列印的白色客製背蓋,背蓋上以魔鬼氈與束帶保留硬體固定位置
白色部分不是臨時泡棉,而是我為 Go2 自行 3D 列印的客製背蓋;上方的魔鬼氈與束帶則保留快速拆裝與反覆測試的空間。

2026-04-25|裝上自製 3D 列印背蓋後,Jetson、D435 與 RPLIDAR 終於能以完整堆疊站上 Go2。

這一個月也很殘酷:一次 pip install ultralytics 讓 Torch/NumPy 與所有模型一起壞掉;RPLIDAR 到貨後又遇到 ARM64 crash、Cartographer、雷達方向相反、支架搖晃與四張作廢地圖。

2026 年 5 月:Brain 與安全邊界被真機事故逼出來#

早期 llm_bridge_node.py 長到超過 1,100 行,同時處理 ROS、Persona、fallback、history、JSON 與 TTS。當錯誤開始無法定位,我才把 Conversation Engine 抽成 LangGraph,並讓新路徑先跑 shadow。

5 月 2 日的一次救援操作誤發 Damp(1001),Go2 馬達卸力摔倒。之後的短距導航又暴露 Move{x:0} 不停車、感測器方向與安全距離計算錯誤,迫使 StopMove、Topic 與 WebRTC control contract 成為硬規則。

驗收時也沒有奇蹟:人臉與語音相對穩定,物體很差,手勢會誤觸,姿勢定義不清。這些結果讓我們停止用「功能有寫」代表「能力可靠」。

2026 年 6 月:最大的敵人叫整合#

最後一個月,Conversation Engine、LangGraph、TTS、Go2 音訊、LiDAR 與五段 Demo 全部同時進場。Face、cup、pose、gesture 會爭奪 TTS、狀態與身體控制;功能不是相加,而是互相放大失敗面。

我們修過 10 秒抓不到 pose+cup 的融合窗、phase gate 靜默擋事件、重複問候、TTS cooldown、多個 /webrtc_req publisher,以及 LiDAR 啟動腳本漏掉 --ros-args、被誤判成硬體死亡。

6 月 4 日的 trusted baseline 讓樂觀敘事回到現實:15 項能力裡,只有人臉、固定語音指令與近距杯子通過窄版條件;wave 與 voice stop 失敗,其餘多項仍是 insufficient data,整體 readiness 是 not_ready

6 月 17 日,正式發表前一天的彩排仍然問題百出;6 月 18 日,現場卻順利完成 18 分鐘展示。我的日記最後只留下一句:

過程全錯,結果全對。

6 月 23 日,我們整理十個核心 ROS2 package、雙語文件結構與新手 bring-up 路徑,公開第一版 repository。它仍是多模態具身互動系統的雛形,不是完成的自主機器人產品。

我們怎麼開發這個系統#

PawAI 後期形成了一套比較保守,但很適合實體機器人的開發方式:

  1. 先隔離單一路徑:人臉、物體、語音、LiDAR 與 Go2 Driver 先各自證明可用,再進完整 stack。
  2. 先定契約再接功能:topic、event schema、SkillPlan 與 SkillResult 先固定,避免每個模組直接相依。
  3. 新系統先跑 shadow:讓 LangGraph 或新策略觀察同一份輸入,但在足夠穩定前不取得實體控制權。
  4. 所有 motion 先從 no-motion 證據開始:先確認 publisher、ownership、stop gate 與 world state,再進 HITL 小距離測試。
  5. 保留 fallback 與 rollback:雲端、本地、規則路徑和 feature flag 都必須能在現場快速退回。
  6. 用 evidence 決定文案:機制、觀察與通過基線是不同層次;網站只描述最後一層允許的範圍。

這套流程是在多次整合失敗後才逐漸形成。它讓 PawAI 從「功能很多的學生專題」,走向一個知道自己目前能證明什麼、也知道何時必須停下來的工程系統。

我在這個專案裡做了什麼#

PawAI 是團隊專題;這一頁聚焦我親自負責或深度參與的系統整合、Brain、語音、硬體 bring-up、測試與公開化工作。

我主要投入在把原本分散的硬體、感知模型與 AI 功能,整合成一條能被操作、觀測與驗證的系統:

  • 整合 Go2、Jetson、D435、語音裝置與 ROS2 runtime。
  • 建立多模態事件與決策流程,讓感知結果能安全地進入 Brain。
  • 設計 Brain、Executive 與 Safety Gate 的控制邊界。
  • 處理 ASR、LLM、TTS 與 Go2 音訊輸出的降級鏈。
  • 建立 PawAI Studio、Trace、CLI、Demo runbook 與 capability evidence。
  • 經歷導航、控制權衝突與現場 Demo 問題後,重新整理架構與公開文件。

我學到的三件事#

1. 多五個功能,不代表工作量只增加五倍#

單獨的人臉、語音或物體辨識可能都能運作;放進同一台會移動的機器人後,它們開始共享 GPU、相機、音訊、狀態與控制出口。真正困難的是協調,而不是模型數量。

2. 機制存在,不等於能力已被驗證#

有 Navigation Action、有 Safety Gate 或有 Studio 畫面,只能證明系統具備這條路徑;它不能自動證明真實環境下的成功率、可靠度或安全性。

3. 失敗也應該留在作品裡#

語音停止失敗、動態揮手未通過、導航測試走歪,這些都比一段剪輯過的成功影片更能說明我如何理解機器人系統。PawAI 最後留下的不只是功能,也包括停止宣稱、降級與重新驗證的方法。

接下來#

PawAI 還會繼續改善,但我會維持同一個原則:先建立可重現的證據,再擴張公開宣稱。

下一階段包含:

  • 補齊多使用者、多距離與不同光線的感知基線。
  • 改善語音停止、手勢與完整語音端到端測試。
  • 讓 Studio Evidence 與可信 baseline 直接連結。
  • 在 no-motion、急停與 HITL 條件下重新驗證導航能力。
  • 把架構、語音、感知、導航事故與 Demo 工程拆成獨立技術文章。

專案原始碼與公開文件:GitHub — roy4222/PawAI