跳至主要内容

Troubleshooting

本頁提供一套系統化的 ROS 2 問題排查清單,涵蓋最常遇到的情況:Topic 消失、Type Mismatch、QoS 不相容、Domain ID 衝突、DDS Discovery 問題、Container Networking、Timestamp / Clock 問題、TF 錯誤,以及 Permission 問題。

每個章節都會提供對應指令,讓你在進入下一個檢查項目前,先確認或排除目前這個可能原因。

概述​

大多數 ROS 2 問題都可以歸類到少數幾種類型。只要知道應該從哪裡開始檢查,通常都能透過命令列快速縮小問題範圍。

建議依照下方對應章節的順序逐項檢查,在同一個章節中由上往下進行,而不是直接猜測原因。

為什麼重要​

「不能運作」本身並不是可直接採取行動的資訊。

一套簡短、可重複執行的 Diagnostic Sequence,可以把模糊的現象逐步縮小成明確且可修正的原因,也通常比反覆嘗試修改程式碼或設定更有效率。

Topic 消失​

預期應該存在的 Node、Topic、Service 或 Action 完全沒有出現在系統中。

  1. 確認目前 Terminal 已經 source ROS 2 環境:

    printenv ROS_DISTRO
    which ros2

    可參考 CLI 基礎操作。

  2. 確認 Node 實際上正在執行,而不是啟動後立即 Crash:

    ros2 node list

    如果沒有看到該 Node,請檢查啟動它的 Terminal 是否有 Stack Trace 或 Error。

  3. 確認 ROS_DOMAIN_ID 一致:執行 Node 的 Terminal 與執行 CLI 的 Terminal 必須使用相同的 ROS_DOMAIN_ID。可參考下方 Domain ID。

  4. 確認 Topic 完整解析後的名稱與 Namespace:

    ros2 topic list

    程式碼中使用的 Relative Topic Name,可能會根據 Node 所在的 Namespace 被解析成不同的 Fully Qualified Name。

  5. 如果 Topic 已經存在,但 echo 沒有任何輸出,檢查 QoS 是否不相容。可參考下方 QoS Mismatch。

Type Mismatch​

兩個 Node 看起來使用相同的 Topic 或 Service Name,但無法交換資料;或 CLI Call 回報 Type Error。

ros2 topic type /some_topic
ros2 interface show <package>/msg/<Type>
  • 通訊雙方的 Package Name 與 Type Name 必須完全一致。例如 std_msgs/msg/String 與具有相同欄位的 Custom Message 並不是同一個 Type。
  • 如果使用自訂 Interface Package,在修改任何 .msg、.srv 或 .action 檔案後,請確認已重新 Build,並重新 source Overlay。使用到舊的 Generated Code 是常見的「以前可以,現在不行」原因。
  • 對 Service / Action,可使用 ros2 interface show 檢查 Request / Response 或 Goal / Result / Feedback 結構,再逐一比對 Client 實際送出的欄位。

QoS Mismatch​

Publisher 與 Subscriber 都存在於相同 Topic 上,但資料沒有成功傳遞。

ros2 topic info /some_topic -v

這個指令會列出該 Topic 上每一個 Publisher 與 Subscriber 的 QoS Profile,包括 Reliability、Durability、History 與 Depth。

常見的不相容情況包括:

Setting會造成 Delivery 失敗的不相容情況
ReliabilityPublisher 使用 BEST_EFFORT,Subscriber 使用 RELIABLE(Subscriber 要求的保證高於 Publisher 能提供的等級)
DurabilityPublisher 使用 VOLATILE,Subscriber 使用 TRANSIENT_LOCAL(Subscriber 預期 Late-joining 時能取得最後一筆資料,但 Publisher 不會保留)

解決方式是讓 Publisher 與 Subscriber 的 QoS Profile 彼此相容。

兩邊不需要完全相同,但 Publisher 提供的 QoS Guarantee 必須能滿足 Subscriber 所要求的 Profile。

Domain ID​

Node 理論上應該彼此可見,但即使在相同 Network 中仍然看不到,而且沒有其他明顯原因。

printenv ROS_DOMAIN_ID
  • 應該參與相同 ROS 2 DDS Domain 的 Node,通常需要使用相同的 ROS_DOMAIN_ID;未設定時預設為 0。Domain ID 一致是一般 Discovery 的必要條件,但如果 Network、Middleware、Firewall 或 Discovery Setting 不相容,仍不保證一定能通訊。
  • Advantech Robotic Suite 提供 Helper Script,可用來一致地修改設定;請參考 ROS 2 Domain ID。
  • Host 與 Container Shell 都要分別確認。Container 不一定會自動繼承 Host 的 Environment Variable。

DDS Discovery​

Node 已經使用相同 Domain ID,但仍然無法彼此發現,尤其是在跨機器、Wi-Fi 或 VPN 環境中。

  • Multicast-based Discovery 是大多數 RMW / DDS Implementation 的預設方式,但可能受到 Network Configuration、Firewall 或部分 Virtual / VPN Network Adapter 阻擋。先確認相關機器之間具備基本 Network Connectivity,例如使用 ping。

  • 檢查目前使用的 RMW Implementation,因為這會影響 Discovery Behavior 與可使用的調整方式:

    printenv RMW_IMPLEMENTATION
  • ros2 doctor 可以進行多項基本 Environment 與 Network 檢查,是合理的第一步:

    ros2 doctor --report
  • 如果 Node 分布在多台機器上,請確認 Firewall Rule 允許 DDS Traffic。實際使用的 Port 與 Protocol 取決於目前使用的 RMW Implementation,請參考該 Implementation 的文件,不要假設所有環境都使用相同 Port Range。

Containers​

Advantech Robotic Suite 在部分 Platform 上會於 Container 中執行 ROS 2,因此 Container Boundary 也可能帶來額外的 Discovery 與 Environment 問題。

  • 確認 Container 的 Network Mode 能支援所需的 DDS Discovery Traffic。對 Local Discovery 而言,Host Networking 通常是最直接的設定;Bridged Networking 則往往需要額外設定。

  • Host 上設定的 Environment Variable,例如 ROS_DOMAIN_ID、RMW_IMPLEMENTATION,不會自動出現在 Container 內,除非啟動 Container 時明確傳入,或在 Container Shell 中重新設定。兩邊都應獨立確認:

    docker exec -it <container_name> bash -c 'printenv ROS_DOMAIN_ID'
  • 如果 Container 內的 Node 看不到 Host 上或另一個 Container 中的 Node,先確認它們使用相同 Domain ID 與適當的 Network Mode,再進一步檢查更複雜的問題。

Timestamp 與 Clock​

與時間相關的功能,例如 TF Lookup、Message Filtering 或 Synchronized Playback,行為不如預期。

  • 確認相關 Node 是否預期使用 Simulated Time。如果某個 Node 的 use_sim_time 為 true,但系統中沒有任何來源發布 /clock,該 Node 的 Clock 將不會正常前進。可參考 Rosbag。
  • 如果 Timestamp 會跨多台機器進行比較,請確認各機器的 System Clock 已合理同步。過大的 Clock Skew 可能會產生看起來像 TF 或 QoS 問題的現象。
  • 如果出現 "extrapolation into the future/past" 類型的 TF Error,請參考下方 TF Issues。

TF Issues​

完整的 Frame 與 Transform 說明可參考 TF2。

快速檢查流程:

ros2 run tf2_ros tf2_echo <source_frame> <target_frame>
ros2 run tf2_tools view_frames
  • "Frame does not exist" — 尚未有任何來源發布該 Frame ID 的 Transform。請檢查拼字,並確認對應 Publishing Node 正在執行。
  • "Lookup would require extrapolation" — 要查詢的 Timestamp 超出 TF2 保留的 Buffer 範圍。如果不需要特定歷史時間,應改為要求最新可用 Transform。
  • RViz 中的 RobotModel 凍結、破碎或抖動 — 檢查是否有缺少或互相衝突的 TF、Timestamp / Simulated Time 問題,以及缺少或不一致的 /joint_states。如果正在播放 Bag,也要確認 Recorded TF 是否與 Live Node(例如 robot_state_publisher)產生的 Transform 重疊。

Permissions​

指令出現 Permission Denied,而不是 ROS 2 本身的錯誤。

  • Script-based Node 缺少 Executable Bit:對檔案執行 chmod +x。透過 setup.py / colcon 安裝的 Python Entry Point 通常不需要這一步,但手動執行的 Script 有時需要。

  • Device Access:Serial Port、USB Camera、CAN Interface 等硬體通常需要使用者加入特定 Group(例如 dialout),或設定 udev Rule。請依實際 Hardware Driver 文件確認所需 Group 或 Rule。

  • Container Volume / User Mismatch:Container 內建立的檔案可能屬於與 Host User 不同的 UID,導致 Host 端之後無法編輯或刪除。

  • rosdep Permission Error:rosdep init 通常需要較高權限,因為它會建立 System-level Configuration:

    sudo rosdep init

    Run rosdep update as the normal user:

    rosdep update

常用指令​

# Environment
printenv ROS_DISTRO
printenv ROS_DOMAIN_ID
printenv RMW_IMPLEMENTATION
ros2 doctor --report

# Graph
ros2 node list
ros2 topic list -t
ros2 topic info <topic> -v
ros2 service list -t
ros2 action list -t

# TF
ros2 run tf2_ros tf2_echo <source_frame> <target_frame>
ros2 run tf2_tools view_frames

重點整理​

  • 依照問題類型逐步排查,例如 Missing Topic、Type Mismatch、QoS、Domain ID、DDS Discovery、Container、Timestamp、TF 與 Permission,而不是針對每一次問題各自猜測。
  • ros2 topic info -v 與 ros2 doctor --report 可以獨立解決相當多「為什麼不能運作」類型的問題。
  • 需要彼此 Discovery 的 Node 通常必須使用相同的 ROS_DOMAIN_ID。RMW Implementation 與 Discovery / Transport Setting 也必須彼此相容。使用相同 RMW Implementation 通常可以簡化 Troubleshooting,但並不是絕對必要條件。
  • TF 與 Playback 問題可能來自 Missing Transform、Timing Issue 或互相衝突的 TF Authority。播放 Bag 時,請確保重疊的 Transform 不會同時由多個 Source 產生。

下一步​

如果問題已經解決,可以回到 ROS 2 學習地圖;如果需要更深入了解特定主題,可以重新查看 ROS 2 Domain ID、TF2 或 Rosbag。