Background

最近在學習 ROS,但目前手上沒有機器人。於是,想以手邊的 iPad 作為 ROS node,並在 mac 上面獲取對應的,諸如 IMU, Camera, Battery … etc 資訊,理解 ROS node sensor 搜集回來的數據跟對應的命令。

在這篇文章中,我們將

  1. 將 Macbook 作為 ROS node (使用 docker)
  2. 將 iPad 變成 ROS node (使用 Conduit)
  3. 傳送 iPad 上 sensor 的資料回 Macbook

將 Macbook 作為 ROS node (使用 docker)

根據 ROS 的文件中,有提到 在 macOS 上安裝 ROS2 的做法。然而,實際安裝時,遇到相當多套件 deprecated、版本相依等問題,經過與 Claude Code 來回幾趟後,在這個階段先果斷放棄,畢竟當前想看到的是,ROS2 送回的數據形式。

Docker Image 的做法 是最簡單上手的。

首先,創一個資料夾 ros2-ipad/,以及底下的 config/ 資料夾。 並且我們要準備三個檔案,如底下所示:Dockerfile, docker-compose.yml, config/zenoh_router.json5

ros2-ipad
|__ Dockerfile
|__ docker-compose.yml
|__ config/zenoh_router.json5

Dockerfile

FROM --platform=linux/arm64 ros:jazzy

RUN apt-get update && apt-get install -y \
    ros-jazzy-rmw-zenoh-cpp \
    && rm -rf /var/lib/apt/lists/*

RUN echo "/opt/ros/jazzy/opt/zenoh_cpp_vendor/lib" > /etc/ld.so.conf.d/zenoh.conf && ldconfig
  1. 使用 jazzy 發行版的 ros,若在 intel 版本的 macbook,請將 platform 改成 linux/amd64
  2. 安裝 ros-jazzy-rmw-zenoh-cpp 套件
  3. 修復函式庫路徑

docker-compose.yml

services:
  zenoh_router:
    build: .
    container_name: zenoh_router
    ports:
      - "7447:7447/tcp"
      - "7447:7447/udp"
    stdin_open: true
    tty: true
    environment:
      - ROS_DOMAIN_ID=0
      - RMW_IMPLEMENTATION=rmw_zenoh_cpp
      - LD_LIBRARY_PATH=/opt/ros/jazzy/opt/zenoh_cpp_vendor/lib
      - ZENOH_ROUTER_CONFIG_URI=./config/zenoh_router.json5
    volumes:
      - ./config:/config:ro
    command: >
      bash -c "source /opt/ros/jazzy/setup.bash &&
               ros2 run rmw_zenoh_cpp rmw_zenohd"
欄位說明
build: .使用當前目錄的 Dockerfile 建立映像檔
container_name容器名稱固定為 zenoh_router
ports將主機的 7447 port 映射到容器,TCP/UDP 都開放,讓 iPad 等外部裝置能連線
stdin_open / tty保持終端開啟,可互動操作
ROS_DOMAIN_ID=0ROS 2 網域 ID,同網域的節點才能互相通訊
RMW_IMPLEMENTATION指定使用 Zenoh 作為 ROS 2 的通訊中介層
LD_LIBRARY_PATH讓系統找得到 libzenohc.so 函式庫
ZENOH_ROUTER_CONFIG_URI指定 Zenoh 路由器的設定檔路徑
volumes將本機 ./config 資料夾掛載到容器內的 /config(唯讀)
command容器啟動後執行:載入 ROS 2 環境 → 啟動 Zenoh 路由器

config/zenoh_router.json5

{
  mode: "router",
  listen: {
    endpoints: [
      "tcp/0.0.0.0:7447"
    ],
  },
}
欄位說明
mode"router"路由器模式啟動,負責轉發所有節點的訊息
listen.endpoints"tcp/0.0.0.0:7447"監聽所有網路介面的 7447 port

因為 docker 沒有固定 IP,我們在這裡先將監聽的 IP address 設定成 0.0.0.0,來監聽所有的網路介面。

執行

ros2-ipad/ 資料夾底下,執行

docker compose build
docker compose up

將 iPad 變成 ROS node (使用 Conduit)

在 iPad 的 App Store 上,搜尋並安裝 Conduit, powered by ROS

設定 ROS Topic

在 Conduit 進來的首頁,可以設定我們想要 public 的 topic。 可以看到有 IMU, GPS, Camera, Battery 等 Topic 可做選擇。

設定 IP Address

在 Macbook 上,至系統設定「System settings > WiFi」底下,取得當前 WiFi 下,Macbook 的 IP address。

在 iPad 上回到 Conduit,點擊右上角的設定按鈕。 將「Zenoh Router > Router Address」設定為 macbook 的位置。

執行

點擊 Conduit 右下角,執行按鈕開始連線。

傳送 iPad 上 sensor 的資料回 Macbook

請注意,iPad 與 Macbook 需要在同一個 WiFi 網路底下

在 iPad 上按下執行後,回到 Macbook 上。

先透過 docker ps 確認當前執行的 container ID。

以 bash 執行進入該容器。

docker exec -it 2e76462241cb bash

啟用服務。

source /opt/ros/jazzy/setup.bash
export RMW_IMPLEMENTATION=rmw_zenoh_cpp

列出當前 subscribe 的 topic。

root@2e76462241cb:/# ros2 topic list

/conduit/camera/front/camera_info
/conduit/camera/front/image_raw/compressed
/parameter_events
/rosout
/tf_static

透過 ros2 topic echo <topic name> 指令, 查看 topic 資料。

root@2e76462241cb:/# ros2 topic echo <topic name>
%% ros2 topic echo /conduit/camera/front/image_raw/compressed %%

成功獲得相機資訊啦!

Conclusion

在這篇文章中,我們記錄了「如何在 Mac 上,將 iPad 作為 ROS2 的 sensor 並取得數據」。 數據流入底下所示:

iPad 
↓ 
tcp/<macbook ip address>:7447
↓ 
Docker port mapping 7447 → 7447 容器
↓ 
Zenoh 監聽 0.0.0.0:7447

學習了 ROS2 的指令,並取得 ROS node 的資訊。