Post

在 Jetson Nano B01 上使用 ROS 2 Humble 控制 Arduino 繼電器

在 Jetson Nano B01 上使用 ROS 2 Humble 控制 Arduino 繼電器

為什麼選擇 Foxglove 做視覺化

Jetson Nano B01 資源極度有限,卻要跑完整的 ROS 2 Humble + Arduino 繼電器控制 + Reed Switch 回報 + 遠端即時監控。

  • 原生支援 ROS 2
  • 直接吃 foxglove_msgs,自訂 Panel 方便,不需要手動自行規劃版面尺寸
  • 可同時監看 /platform/relay、/platform/reed_switch、/platform/arduino_health topic
  • 手機、筆電、平板遠端都能開,部署彈性高

示例GIF

環境準備

1
2
3
sudo docker run -it --rm --runtime nvidia --network host --privileged \
    -v ~/ros2_ws:/ws \
    dustynv/ros:humble-desktop-l4t-r32.7.1

重點錯誤記錄與排除

錯誤 1:apt 金鑰過期,無法安裝任何套件

現象

The following signatures couldn’t be verified because the public key is not available: NO_PUBKEY 7FA2AF80F9C2B8E9

解決指令

移除舊的密鑰和配置

1
2
sudo rm /usr/share/keyrings/ros-archive-keyring.gpg
sudo rm /etc/apt/sources.list.d/ros2.list

下載並安裝新 ROS 2 簽名密鑰

1
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg

RUN

1
sudo apt update

錯誤 2:Foxglove Bridge 編譯失敗

現象

stderr: foxglove bridge CMake Error at CMakeLists.txt:174 (message): Could not find catkin

解決指令

安裝(Github & RapidJSON)

1
2
3
4
5
6
7
cd /ws/src

git clone https://github.com/foxglove/foxglove-sdk.git

git clone https://github.com/facontidavide/rosx_introspection.git

apt-get install -y rapidjson-dev

處理(Insert and find) sensor_msgs

1
2
3
4
5
6
7
cd /ws/src/foxglove-sdk/ros/src/foxglove_bridge

sed -i '2i find_package(sensor_msgs REQUIRED)' CMakeLists.txt

sed -i '2i find_package(geometry_msgs REQUIRED)' CMakeLists.txt

head -n 5 CMakeLists.txt

Clean and RUN

1
2
3
4
5
6
7
8
cd /ws

rm -rf build/install/log/

source /opt/ros/humble/install/setup.bash


colcon build --symlink-install --base-paths src/rosx_introspection src/foxglove-sdk/ros/src/foxglove_bridge 

find / -name “foxglove_bridge” and “CMakeLists.txt” → 確保 pwd

錯誤 3:C++17 語言特性無法識別(std::optional、std::string_view 編譯錯誤)

現象

dustynv 映像預設的 GCC 版本太舊(7.5.0),不完整支援 C++17,rosx_introspection 和 foxglove_bridge 都大量使用 C++17 新特性。

解決指令

安裝設置(GCC 8)

1
2
3
4
apt-get install -y g++-8

export CC=gcc-8
export CXX=g++-8
  1. 使用 C++17 標準
  2. 不要把警告當錯誤
  3. 連結檔案系統函式庫
1
export CXXFLAGS="-std=c++17 -Wno-error -lstdc++fs"

Clean

1
2
3
4
5
cd /ws

#   清理緩存
rm -rf build/install/log/
rm -rf build/foxglove_bridge install/foxglove_bridge

手動補丁-1

1
2
3
4
echo '#include <cstddef>
#if __cplusplus < 201703L
namespace std { enum class byte : unsigned char {}; }
#endif' > patch.txt

手動補丁-2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SDK_INC_DIR="/ws/build/foxglove_bridge/_deps/foxglove_sdk-src/include/foxglove"


if [ -d "$SDK_INC_DIR" ]; then
    echo "找到 SDK 資料夾,開始修補"
    # 搜尋所有的 .hpp 檔案
    find "$SDK_INC_DIR" -name "*.hpp" | while read filename; do
        # 把 patch.txt 的內容接上原本的檔案,存成 temp
        cat patch.txt "$filename" > temp.hpp
        # 用 temp 覆蓋原本的檔案
        mv temp.hpp "$filename"
        echo "已修補: $filename"
    done
    echo "✅ 所有檔案修補完成!"
else
    echo "❌ 錯誤:找不到 build 資料夾。請確認你剛剛有執行過 colcon build 且沒有刪除 build/。"
fi

Environment setting(強制使用 C++17 編譯)

1
2
3
4
5
6
7
8
9
source /opt/ros/humble/install/setup.bash

colcon build --symlink-install \
  --base-paths src/rosx_introspection src/foxglove-sdk/ros/src/foxglove_bridge \
  --cmake-args \
  -DCMAKE_CXX_STANDARD=17 \
  -DCMAKE_CXX_FLAGS="-std=c++17"

export CXXFLAGS="-std=c++17"

缺失補入

1
2
3
4
5
cd /ws/src/foxglove-sdk/ros/src/foxglove_bridge

sed -i '2i set(CMAKE_CXX_STANDARD 17)' CMakeLists.txt
sed -i '3i set(CMAKE_CXX_STANDARD_REQUIRED ON)' CMakeLists.txt
sed -i '4i link_libraries(stdc++fs)' CMakeLists.txt

RUN

1
colcon build --symlink-install --base-paths src/rosx_introspection src/foxglove-sdk/ros/src/foxglove_bridge

Arduino 控制節點的設計思考與安全考量

目標是長期 7×24 小時穩定控制 4 路繼電器 + 讀取 Reed Switch。實作過程中最在意的幾個思考點如下:

  1. CPU 必須極低 → 放棄 10ms 輪詢,改用 serial.readline() 完全阻塞式讀取,CPU 長期 <1%
  2. 指令不能被任意注入 → 嚴格白名單,只接受 ‘1’~’4’ 四個字元
  3. 必須明確知道 Arduino 是否還活著 → 1 秒發送 PING,5 秒內無 HEARTBEAT 就標記不健康
  4. 斷線要自動重連並即時更新健康狀態 → 任何 SerialException 都觸發重連機制

結論

採用 Docker Environment → Upgrade development tools → Lock ROS 2 → Create closed loop 的部署策略,最終實現三個獨立 ROS 2 節點(Bridge、Controller Node、Visualizer Node)在資源受限的 Jetson Nano B01 上穩定運行。底層 Arduino 程式碼內建鎖定式 Failsafe 機制,確保通訊中斷時優先維護硬體安全。整個部署過程記錄的錯誤與解法,希望能幫助遇到類似問題的開發者快速排除障礙。

graph TD
    A[Docker Environment] --> B[Upgrade Development Tools]
    B --> C[Lock ROS 2 Humble]
    C --> D[Create Closed Loop]
    
    D --> E[Bridge Node<br/>Foxglove Bridge]
    D --> F[Controller Node<br/>Arduino Relay Control]
    D --> G[Visualizer Node<br/>Foxglove Studio]
    
    F --> H[Arduino 硬體層]
    H --> I[鎖定式 Failsafe 機制]
    
    E -.通訊協定.-> G
    F -.Serial 通訊.-> H
    
    style A fill:#b3d9ff,stroke:#0066cc,color:#000
    style B fill:#ffe6b3,stroke:#cc8800,color:#000
    style C fill:#ffb3d9,stroke:#cc0066,color:#000
    style D fill:#b3ffb3,stroke:#00cc00,color:#000
    style E fill:#ffcccc,stroke:#cc0000,color:#000
    style F fill:#ffcccc,stroke:#cc0000,color:#000
    style G fill:#ffcccc,stroke:#cc0000,color:#000
    style I fill:#ff9999,stroke:#990000,color:#000
This post is licensed under CC BY 4.0 by the author.