# micro-ROS 理論篇 ## 一、ROS 2 架構 ### 1. ROS 2 的設計理念與定位 ROS(Robot Operating System)最早是為了讓機器人開發更模組化而誕生的。 它不是傳統意義上的「作業系統」,而是一套**通訊框架與軟體生態**, 讓不同模組之間可以以標準化方式交換資料、共享資源、協同運作。 ROS 2 是 ROS 的第二代,最大的改革是將整個通訊底層改寫為 **DDS(Data Distribution Service)**。 這讓 ROS 2 能在不同平台上運行,也能支援更嚴格的即時性與可靠性需求。 ROS 2 的核心思想有三個: 1. **模組化(Modularity)** 系統由許多節點(Node)組成,每個節點只負責一件事。 節點之間不需要知道對方的細節,只需知道 Topic 名稱與訊息格式。 2. **分散式(Distributed)** 節點可以分散在不同裝置上,例如一個在電腦上、另一個在樹莓派上。 只要在同一個 DDS 網路中,節點就能互相發現並通訊。 3. **可重用性(Reusability)** 任何人寫的節點,只要遵守 ROS 訊息規範,就能被別的專案直接使用。 --- ### 2. Node、Topic、Publisher、Subscriber 架構 #### (1) Node Node 是 ROS 世界裡的「程式單元」。 你可以把它想成一個在 ROS 網路中執行的進程(process)。 每個 Node 都有自己的名稱與功能,例如: | Node 名稱 | 功能 | | ------------------ | ------ | | `/camera_node` | 負責影像擷取 | | `/motor_node` | 控制馬達轉速 | | `/navigation_node` | 負責路徑規劃 | 所有 Node 都由 `rclpy`(Python)或 `rclcpp`(C++) 建立與管理。 --- #### (2) Topic Topic 是 ROS 的「資料通道」。 它定義了一個訊息的主題名稱與格式。 節點之間透過發佈與訂閱 Topic 進行資料交換。 例如: ``` Topic: /sensor/temperature Type: std_msgs/Float32 ``` 任何節點都可以發布這個 Topic,也可以同時有多個節點訂閱它。 --- #### (3) Publisher Publisher 是負責「發送資料」的角色。 在 Python 中用 `create_publisher()` 建立。 基本語法: ```python self.publisher = self.create_publisher(Float32, '/sensor/temperature', 10) ``` 這段程式會: * 宣告一個名為 `/sensor/temperature` 的 Topic * 使用 `Float32` 訊息型別 * Queue 大小為 10(即緩衝最多 10 筆資料) Publisher 會使用 `publish(msg)` 將資料送出。 --- #### (4) Subscriber Subscriber 則是「接收資料」的一方。 它訂閱一個 Topic,並在每次收到新訊息時執行 callback 函式。 ```python self.subscription = self.create_subscription(Float32, '/sensor/temperature', self.listener_callback, 10) ``` 其中: * 第 1 個參數是訊息型別 * 第 2 個是 Topic 名稱 * 第 3 個是 callback 函式(當收到資料時執行) * 第 4 個是 Queue 大小 Callback 函式格式通常如下: ```python def listener_callback(self, msg): self.get_logger().info(f'Received: {msg.data}') ``` 這樣 ROS 2 節點就能被動接收並處理資料。 --- ### 3. 通訊協定 DDS 的運作原理 DDS(Data Distribution Service)是 ROS 2 通訊的核心。 它是一種 **Publish–Subscribe 中介層協定**,專為分散式即時系統設計。 它的幾個特性: 1. **自動節點發現** 節點不需手動指定 IP 或 Port。 DDS 會自動偵測同一網路中的 Publisher 與 Subscriber,建立通訊連線。 2. **即時性與可靠性控制** DDS 提供 QoS(Quality of Service)設定,讓使用者可以決定: * 要不要保證資料送達 * 要保留幾筆歷史資料 * 延遲或頻寬的取捨 3. **去中心化(Decentralized)** DDS 沒有中央伺服器。 所有節點都是平等的「Peer」,這讓系統更穩定,也容易擴展。 --- ### 4. QoS(Quality of Service)設定 QoS 是 DDS 的關鍵機制之一,直接影響通訊的可靠度與效率。 常見參數如下: | 參數名稱 | 意義 | 常用值 | | ----------- | -------- | ------------------------------------------- | | Reliability | 資料可靠度 | `Reliable`(保證送達) / `Best Effort`(允許丟包) | | Durability | 是否保留舊資料 | `Volatile`(不保留) / `Transient Local`(保留最近一次) | | History | 保留幾筆訊息 | `Keep Last`、`Keep All` | | Depth | Queue 大小 | 數值,例如 10 | 範例: ```python from rclpy.qos import QoSProfile, QoSReliabilityPolicy qos = QoSProfile(depth=10) qos.reliability = QoSReliabilityPolicy.RELIABLE self.create_subscription(String, '/topic', self.cb, qos) ``` --- ### 5. ROS 2 的優勢與限制 | 面向 | 優勢 | 限制 | | --------- | -------------------------- | ---------------- | | **可擴充性** | 支援多語言(Python / C++ / Java) | 效能取決於 DDS 實作 | | **開發便利性** | 有完整 CLI 工具與 rqt 可視化 | 建構與依賴管理複雜 | | **穩定性** | DDS 架構可靠、去中心化 | 高資源消耗(CPU / RAM) | | **適用對象** | 桌上型機器人、工業自動化、AI 模組 | 無法直接用於 MCU 或裸機系統 | 這個「無法直接用於微控制器」的限制,就是 micro-ROS 出現的理由。 --- ### 6. 為什麼 ROS 2 無法直接用於微控制器 原因主要有三點: 1. **記憶體限制** DDS 的封包協定複雜,包含可靠性、封包重傳、緩衝佇列等機制。 一般微控制器(像 ESP32、STM32)只有幾百 KB 的 RAM,根本撐不住。 2. **作業系統依賴** ROS 2 依賴 POSIX 系統呼叫(執行緒、定時器、socket)。 微控制器多數只有簡單的 RTOS 或無 OS,缺乏這些 API。 3. **效能與即時性問題** ROS 2 是設計給多進程、非即時環境。 在 MCU 上,任務需要硬即時反應(例如 PWM 控制、感測中斷), ROS 2 太「重」而且延遲過高。 因此需要一個「**具 ROS 2 通訊相容性,但能跑在微控制器**」的框架——這就是 micro-ROS。 --- ### 7. 小結 ROS 2 解決了機器人開發的軟體協作問題,但它面向的是運算力夠的主機或 SBC(Single Board Computer)。 它提供完整的通訊功能,但在邊緣設備上代價太高。 接下來,micro-ROS 的角色就是: > 把 ROS 2 的溝通能力延伸到記憶體幾百 KB 的小板子上, > 讓「前線感測」與「後端運算」能講同一種語言。 --- ## 二、micro-ROS 架構與設計理念 ### 1. micro-ROS 的誕生背景 ROS 2 是個強大的框架,但它的前提是「主機」: 有作業系統、有網路堆疊、有記憶體,能跑 DDS。 可是現實裡,大量的機器人與 IoT 應用都依賴 **微控制器(MCU)**: ESP32、STM32、LinkIt 7697、Arduino… 它們的記憶體只有幾百 KB、運算力不到主機的千分之一。 問題在於: > 這些小板子負責了機器人最關鍵的「感測」與「控制」, > 卻無法直接參與 ROS 2 生態系。 於是,**micro-ROS(micro Robot Operating System)** 應運而生。 它由多個歐洲研究單位(如 eProsima、Bosch、Acutronic Robotics)與 ROS 2 官方共同開發, 目標是將 ROS 2 的通訊架構「縮小」到能在 MCU 上執行, 同時保持 **介面相容、資料結構一致、通訊可互通**。 換句話說: > micro-ROS 是 ROS 2 的「嵌入式延伸層」。 --- ### 2. micro-ROS 與 ROS 2 的整合概念 micro-ROS 並不是獨立的新系統,而是 ROS 2 的子集。 它的運作理念非常明確: 「讓微控制器成為 ROS 2 網路中的節點(Node)」。 整體結構可用這張關係圖表示: ``` [ Microcontroller (ESP32 / STM32) ] ↑ Micro XRCE-DDS │ [ micro-ROS Agent (Ubuntu / Jetson) ] ↓ DDS [ ROS 2 Network (Host PC) ] ``` * **Client(micro-ROS Node)**:跑在 MCU 上,使用簡化版 ROS 2 API。 * **Agent**:跑在主機端,負責協定轉換(Micro XRCE-DDS ↔ DDS)。 * **Host Node(ROS 2 節點)**:跑在 ROS 2 網路中,與 Agent 通訊。 這樣設計的好處是: * 保留 ROS 2 的生態(msg 格式、topic、service) * 減輕 MCU 的負擔,通訊邏輯交給 Agent 處理 * 讓小裝置可以無縫加入 ROS 2 網路 --- ### 3. micro-ROS 的架構分層 micro-ROS 不是「一個程式」,而是一整個堆疊(stack), 設計時考慮到即時系統、跨平台與資源受限等限制。 以下是 micro-ROS 軟體堆疊的典型結構(由下而上): ``` +-----------------------------------+ | micro-ROS Application Layer | ← 開發者撰寫的應用程式(C / Python) +-----------------------------------+ | RCL / RCLC Layer | ← ROS Client Library(簡化的 API) +-----------------------------------+ | RMW (ROS Middleware) Interface | ← 連接到 XRCE-DDS 通訊層 +-----------------------------------+ | Micro XRCE-DDS Client Stack | ← 負責封包編碼與傳輸協定 +-----------------------------------+ | Transport Layer (UART / UDP) | ← 實體通訊界面 +-----------------------------------+ | RTOS / Hardware Abstraction | ← FreeRTOS / Zephyr / Arduino Core +-----------------------------------+ | MCU Hardware | +-----------------------------------+ ``` #### 說明: * **Application Layer**:你寫的程式碼。 就像 ROS 2 節點,但用的是 micro-ROS API。 * **RCL / RCLC**:ROS Client Library(C 版本為 `rclc`)。 提供建立 Node、Publisher、Subscriber 的函式。 * **RMW Interface**:中介層,連接 micro-ROS 與 XRCE-DDS。 * **Micro XRCE-DDS Client**:真正處理封包傳輸與序列化。 * **Transport Layer**:決定通訊方式(UDP、Serial、Wi-Fi)。 * **RTOS**:確保即時任務能正常執行。 這樣設計讓 micro-ROS 在任何支援 FreeRTOS 的晶片上都能執行。 --- ### 4. Micro XRCE-DDS 通訊協定 micro-ROS 採用 **Micro XRCE-DDS(Micro Extremely Resource Constrained Environment DDS)** 作為通訊核心。 它是 DDS 的精簡版,由 eProsima 公司開發,專門給微控制器使用。 #### (1) 名稱解釋 * **XRCE**:代表「資源極度受限環境」。 * **DDS**:延續 ROS 2 的資料分配協定理念。 #### (2) 運作方式 在 ROS 2 中,節點之間透過 DDS 直接通訊。 但在 micro-ROS,MCU 不具備 DDS 功能,因此它的通訊是「代理式」的: ``` Client (MCU) --XRCE-DDS--> Agent --DDS--> ROS 2 節點 ``` Client 不直接與 ROS 2 節點連線,而是向 Agent 發送 XRCE 封包。 Agent 解析封包後,再用標準 DDS 向 ROS 2 節點轉送。 這樣做的好處: * MCU 不必理解 DDS 的完整協定。 * 封包輕量化,節省記憶體與頻寬。 * Agent 可以服務多個 micro-ROS Client。 #### (3) 傳輸協定支援 Micro XRCE-DDS 可搭配多種傳輸介面: | 介面 | 使用情境 | | ------------- | ------------------------------ | | UDP | 主機與 MCU 連線穩定(Wi-Fi / Ethernet) | | Serial (UART) | 有線連接,速率穩定、低延遲 | | CAN / SPI | 工業應用或多控制板串接 | | USB | 高速傳輸或除錯使用 | --- ### 5. micro-ROS Client、Agent、Host 的角色分工 #### (1) micro-ROS Client(跑在 MCU) * 執行使用者程式 * 包含 Node、Publisher、Subscriber * 使用 micro-ROS API(`rclc`、`rclpy`) * 將所有封包送給 Agent 處理 #### (2) micro-ROS Agent(跑在主機) * 負責連接 MCU 與 ROS 2 * 解析 XRCE-DDS 封包 * 使用 DDS 協定與 ROS 2 節點通訊 * 可同時服務多個 Client * 常駐執行指令範例: ```bash micro-ros-agent udp4 --port 8888 -v6 ``` #### (3) ROS 2 Host Node(主機端節點) * 普通的 ROS 2 節點,無須修改。 * 透過 DDS 與 Agent 通訊,就能收到 MCU 發來的資料。 #### (4) 範例流程: 以「溫度感測」為例: ``` [ ESP32 + DHT11 Sensor ] → micro-ROS Client 發布 Topic /sensor/temperature ↓ [ micro-ROS Agent ] → 轉為 DDS 封包 → 傳入 ROS 2 Topic ↓ [ Ubuntu ROS 2 Node ] → 訂閱 /sensor/temperature → 顯示數值 ``` --- ### 6. 為什麼 micro-ROS 能跑在微控制器上 micro-ROS 能夠在 MCU 上生存,是因為它的核心架構針對三件事徹底優化: #### (1) 記憶體使用極低 * 移除 ROS 2 的動態記憶體配置與 XML 解析。 * 採固定緩衝區(Static buffer allocation)。 * 封包結構簡化,不支援所有 DDS 功能,但保留主要的 Publish-Subscribe 功能。 #### (2) 執行緒與 RTOS 整合 * ROS 2 原生使用多執行緒架構;micro-ROS 改為單任務 + callback 事件。 * 與 FreeRTOS 整合,可在 Task 裡運行 rclc executor(相當於 ROS 2 的 spin loop)。 * 支援任務排程、定時器與中斷。 #### (3) 封包序列化與壓縮 * 使用 XRCE-DDS 的二進位封包格式(比 DDS 小約 80%)。 * 內建 eProsima Fast CDR 序列化函式庫(極低延遲)。 #### (4) 運行環境靈活 * micro-ROS 可在 FreeRTOS、Zephyr、Nuttx、Arduino Core 執行。 * 同時支援 Wi-Fi、Ethernet、UART、USB 等傳輸介面。 --- ### 7. micro-ROS 的設計理念小結 micro-ROS 的核心哲學,可以用一句話總結: > “Bring ROS 2 to microcontrollers.” > —— 讓最前線的感測與控制節點,直接融入 ROS 生態。 它不是取代 ROS 2,而是延伸它的邊界。 它的存在意義在於: * 讓每個感測器、馬達控制器都能變成 ROS 節點 * 讓主機不必處理底層硬體 * 讓分散式機器人系統的所有裝置都說「同一種語言」 --- ### 8. micro-ROS 與 ROS 2 的對應關係表 | 概念 | 在 ROS 2 中 | 在 micro-ROS 中 | 備註 | | --------- | ----------------------- | --------------------------- | ----------- | | 節點(Node) | `rclpy` / `rclcpp` 節點 | `rclc` 節點 | 功能相同但實作簡化 | | 通訊協定 | DDS | Micro XRCE-DDS | 透過 Agent 轉換 | | 執行環境 | Linux / Windows / macOS | FreeRTOS / Zephyr / Arduino | 無 OS 亦可 | | 資料型別 | std_msgs / sensor_msgs | 相容 ROS 2 格式 | IDL 編譯支援 | | Executor | 多執行緒 spin | 單執行緒事件排程 | 簡化版本 | | Launch 機制 | `.launch.py` | 不支援(需手動啟動) | MCU 不具備作業系統 | --- ### 9. micro-ROS 架構視覺化概覽 ``` +----------------------------+ | ROS 2 Network | | (DDS, Python, C++, etc.) | +-------------+--------------+ ↑ │ DDS │ +-------------+--------------+ | micro-ROS Agent | | (Translate XRCE-DDS→DDS) | +-------------+--------------+ ↑ │ XRCE-DDS │ +-------------+--------------+ | micro-ROS Client (MCU) | | Node + Publisher + RTOS API| +----------------------------+ ``` 這張圖是理解 micro-ROS 最關鍵的思維: **Agent 是橋梁,Client 是節點,Host 是大腦。** --- ### 10. 小結:從架構理解 micro-ROS 的價值 * **角色定位明確:** micro-ROS 是「邊緣節點框架」,專注感測與控制。 * **與 ROS 2 完全兼容:** 使用相同的訊息格式與通訊模型。 * **技術本質:** 不是全新作業系統,而是 ROS 2 的輕量延伸層。 * **開發意義:** 讓開發者能在 MCU 上使用熟悉的 ROS API, 不需再重寫感測器通訊協定或手動管理 UART 資料流。 --- ## 三、資料流與封包傳輸 ### 1. 概述:micro-ROS 資料流的全貌 在 micro-ROS 系統裡,資料不是「直接」從一個節點傳到另一個節點。 它要經過一整套橋接與轉換流程,才能讓主機端 ROS 2 節點理解。 最簡化的流程是這樣的: ``` [ micro-ROS Client (MCU) ] ↓ (Micro XRCE-DDS) [ micro-ROS Agent ] ↓ (DDS) [ ROS 2 Node (Host) ] ``` 這三層分別扮演: * **Client**:產生或接收資料(Publisher / Subscriber) * **Agent**:轉換協定,管理通訊狀態 * **Host Node**:執行 ROS 2 處理邏輯(分析、視覺化、控制) micro-ROS 的傳輸機制是「半雙工」的: MCU → Agent 是 XRCE-DDS 封包; Agent → Host 是 DDS 封包。 這樣的設計可以讓每個環節都專注於自己擅長的事: MCU 管理感測與即時控制、Agent 處理封包翻譯、Host 專注高階運算。 --- ### 2. XRCE-DDS 封包的角色與結構 在 ROS 2 中,DDS 封包本身包含非常多控制資訊:可靠性、時間戳、優先權、歷史緩衝等。 這在 MCU 上太重。micro-ROS 因此改用 **Micro XRCE-DDS** 協定。 XRCE-DDS 的核心概念是「Client–Agent 模型」。 #### (1) Client–Agent 模式 * **Client**(在 MCU 上)只需要知道: * 我要發送哪個 Topic * 我要接收哪個 Topic * 封包資料(payload) * **Agent**(在主機上)負責: * 解析 XRCE 封包 * 轉成 DDS 封包 * 發布到 ROS 2 Topic * 把 ROS 2 的回應再轉回 XRCE 封包給 MCU 這樣 MCU 端可以只保存「極少量狀態資訊」,通常不超過幾 KB。 #### (2) XRCE 封包結構簡介 XRCE 封包非常精簡,一個封包大致長這樣(概念化後的欄位): | 欄位 | 功能 | | --------------- | ----------------------------- | | `header` | 封包標頭,含 Client ID、Session ID | | `submessage_id` | 表示封包類型(CREATE, WRITE, READ 等) | | `object_id` | 對應的 Publisher / Subscriber 物件 | | `payload` | 實際傳輸的資料內容 | | `crc` | 檢查碼(確保資料完整性) | 範例概念: ``` Header [Client=0x01, Session=0x02] Submessage: WRITE_DATA Object_ID: Publisher_1 Payload: "temperature=26.4" CRC: 0xA3 ``` Agent 收到後,會把這個 payload 解析出訊息內容,再封裝成 DDS 格式發布。 --- ### 3. 資料流實例:Ping-Pong 傳輸路徑 這是一個最經典的 micro-ROS 測試範例: Client 傳送「ping」,Host 回傳「pong」。 透過這個例子,我們可以完整看一次資料流。 #### (1) Client 端(MCU) 1. 使用 micro-ROS API 建立 Publisher: `create_publisher(String, "/microROS/ping", 10)` 2. 將字串 "ping #1" 打包成 XRCE-DDS 封包。 3. 封包經由 UART / UDP 傳給 Agent。 #### (2) Agent 1. 收到封包 → 確認 Client ID。 2. 解析出 Topic `/microROS/ping`。 3. 將 payload 轉成 DDS 格式,發布到 ROS 2 Network。 #### (3) Host(ROS 2 節點) 1. 收到 `/microROS/ping` 的訊息。 2. 執行 callback:回傳 `/microROS/pong`。 3. ROS 2 節點使用 DDS 封包發布回應。 #### (4) Agent(回傳階段) 1. 接收 `/microROS/pong` 的 DDS 封包。 2. 將其轉回 XRCE-DDS 格式。 3. 發送回 MCU Client。 #### (5) Client(接收) 1. micro-ROS 解析 XRCE-DDS 封包。 2. 呼叫 callback 顯示結果: ``` [Client] Received: pong for ping #1 ``` --- ### 4. 資料流的四個階段 整個 micro-ROS 的資料傳輸,可以明確分成以下四個階段: | 階段 | 發送者 | 接收者 | 協定 | 備註 | | ------- | ---------------- | ---------------- | -------------- | --------------- | | Stage 1 | micro-ROS Client | micro-ROS Agent | Micro XRCE-DDS | MCU 發送感測資料 | | Stage 2 | micro-ROS Agent | ROS 2 Network | DDS | Agent 轉換封包 | | Stage 3 | ROS 2 Node | micro-ROS Agent | DDS | 主機節點回傳控制命令 | | Stage 4 | micro-ROS Agent | micro-ROS Client | Micro XRCE-DDS | Agent 回傳封包至 MCU | 四個階段是雙向對應的,確保 MCU 與主機之間能同步狀態。 --- ### 5. 節點命名與 Topic 對應規範 micro-ROS 完全遵守 ROS 2 的命名規則。 這保證了 micro-ROS 與 ROS 2 節點可以共用相同的命名空間與 Topic。 | 元素 | 規則 | 範例 | | --------- | ---------------------- | ---------------------- | | Node 名稱 | 只能用小寫字母、數字與底線 | `micro_sensor_node` | | Topic 名稱 | 必須以 `/` 開頭 | `/sensor/temperature` | | Namespace | 可用於分組 | `/robot/front_sensor` | | QoS | 與 ROS 2 相同,可調整可靠性與緩衝大小 | Reliable / Best Effort | 若你在 MCU 上宣告: ```c rclc_publisher_init_default(&publisher, &node, ... "/microROS/temp"); ``` 那在 ROS 2 主機上執行: ```bash ros2 topic echo /microROS/temp ``` 就能直接接收到來自 MCU 的資料。 --- ### 6. Agent 如何管理多個 Client micro-ROS Agent 並不是一對一的,它可以同時服務多個微控制器。 每個 Client 連線時都會被分配一個唯一 ID。 Agent 的工作模式如下: 1. 接收封包 → 讀取 Client ID 2. 驗證 Session 是否存在(若不存在則建立) 3. 維護 Client 狀態表: * 活動中節點(Active Nodes) * 已建立的 Publisher / Subscriber * QoS 配置 4. 每當 Agent 收到 Client 封包,會查表找到對應 DDS 物件。 範例(Agent 狀態表概念): | Client ID | Node 名稱 | Topics 發布 | Topics 訂閱 | | --------- | ------------- | ----------------- | ------------ | | 0x01 | `temp_sensor` | `/sensor/temp` | - | | 0x02 | `motor_ctrl` | `/motor/feedback` | `/motor/cmd` | --- ### 7. micro-ROS 傳輸層(Transport Layer) micro-ROS 的靈活性來自它可替換的傳輸層。 根據應用情境,你可以選擇不同介面。 | 介面 | 特點 | 適用場合 | | ----------------- | ---------- | ---------------- | | **UDP** | 無線網路傳輸,速度快 | Wi-Fi / Ethernet | | **Serial (UART)** | 有線、穩定、延遲低 | MCU ↔ 主機近距離連線 | | **CAN** | 抗干擾能力強 | 車用、工業現場 | | **USB** | 高速、除錯方便 | 開發階段 | | **SPI/I2C** | 低速但簡單 | 板對板通訊 | Transport 層與 XRCE-DDS 是獨立的, 只要提供收送封包的函式指標(`send()`, `recv()`), micro-ROS 就能運作在任何介面上。 --- ### 8. 資料封包轉換範例(深入流程) 以下是「MCU 發送資料 → 主機節點接收」的實際邏輯: ``` Step 1: MCU 端呼叫 publish() ↓ Step 2: rclc → RMW Interface → XRCE Client ↓ Step 3: XRCE Client 將資料序列化為 XRCE 封包 ↓ Step 4: 傳送封包(UART/UDP) ↓ Step 5: Agent 接收 → 反序列化封包 ↓ Step 6: Agent 轉換成 DDS 封包 ↓ Step 7: DDS 通知 ROS 2 Node 有新資料 ↓ Step 8: Node callback 執行,顯示或回應資料 ``` 整條路徑大約只需幾毫秒,取決於傳輸介面與封包大小。 --- ### 9. micro-ROS 封包大小與效能 XRCE-DDS 封包大小通常在 50–150 bytes。 即使加上 header,也遠小於 ROS 2 DDS 的 1–2 KB 封包。 這意味著: * micro-ROS 適合即時回報感測資料(高頻低量) * 不適合大量影像或語音傳輸(封包過多會堵塞) 實際效能測試(ESP32 over UART): | 測試項目 | 效能 | | ---- | ---------------- | | 傳輸速率 | 約 10–20 msgs/sec | | 平均延遲 | 約 40–80 ms | | 最大封包 | 約 256 bytes | --- ### 10. micro-ROS 的資料同步與錯誤修復 micro-ROS Agent 會在通訊過程中自動維護 session 狀態。 如果封包丟失或 Client 掛掉,Agent 會在下一次封包時觸發重建程序。 具體行為包括: * **心跳(Heartbeat)機制**:Agent 定期確認 Client 是否仍存活。 * **重傳(Retransmit)機制**:若 CRC 檢查失敗或 timeout,會重新請求封包。 * **Session 重建**:若 Client 重新上線,Agent 可根據先前設定快速恢復。 這些機制確保即使在不穩定連線下(例如 Wi-Fi), micro-ROS 仍能保持通訊穩定。 --- ### 11. 多 Topic 與多節點資料流整合 micro-ROS Client 可同時管理多個 Topic: ```c rclc_publisher_init_default(&pub_temp, &node, ..., "/sensor/temp"); rclc_publisher_init_default(&pub_humid, &node, ..., "/sensor/humid"); ``` Agent 會在 DDS 網路中註冊多個 Publisher,並同步更新。 在主機上,你可以同時監看多個資料流: ```bash ros2 topic echo /sensor/temp ros2 topic echo /sensor/humid ``` 這讓 micro-ROS 不只是單一感測器節點,而是「多感測模組」。 例如一個 MCU 同時管理溫度、濕度、光照感測器, 每個感測值對應不同 Topic。 --- ### 12. micro-ROS 資料流總結 完整的 micro-ROS 傳輸循環: ``` MCU publish → XRCE-DDS serialize → Agent translate → DDS publish → Host Node receive → DDS reply → Agent translate back → MCU receive ``` | 層級 | 協定 | 主要任務 | | ---------- | ----------------- | ------- | | MCU | Micro XRCE-DDS | 封包產生與接收 | | Agent | XRCE-DDS ↔ DDS 轉換 | 封包解析與轉發 | | ROS 2 Node | DDS | 資料處理與回應 | 核心理念: > MCU 不需要懂 DDS,但仍能參與 DDS 網路。 > micro-ROS 讓它透過 Agent「說出 ROS 的語言」。 --- ### 13. 小結:資料流背後的意義 micro-ROS 的傳輸機制展現出一種「角色分離」的設計哲學: * **MCU:** 專注於「產生資料」。 * **Agent:** 專注於「轉譯資料」。 * **Host:** 專注於「理解資料」。 這個模型讓微控制器能以最小負擔參與複雜的分散式系統。 資料從感測端一路穿過 Agent 到主機,再回到控制端, 形成一個完整的閉環(closed loop)。 這也是 ROS 2 與 micro-ROS 能在現代機器人、IoT 與邊緣計算中共存的關鍵。 --- ## 四、ROS 2 與 micro-ROS 的比較分析 ### 1. 比較前的觀念整理 ROS 2 和 micro-ROS 不是競爭關係,而是「同一棵樹的不同枝幹」。 兩者共享相同的設計哲學──**分散式節點架構 + Publish/Subscribe 通訊模型**, 差別在於它們服務的硬體層級與資源環境。 | 層級 | 典型裝置 | 任務類型 | | ------------- | -------------- | --------------- | | **ROS 2** | 主機、Jetson、樹莓派 | 高階計算、AI 推論、任務協調 | | **micro-ROS** | MCU、感測器板、驅動控制器 | 邊緣控制、即時感測、訊號處理 | 兩者透過 **micro-ROS Agent** 共享同一個通訊空間,使整體成為一個統一的 ROS 2 生態系。 --- ### 2. 架構層級比較 #### (1) 總覽圖 ``` +-------------------------------+ | ROS 2 Network | | (DDS, rclpy/rclcpp Nodes) | +---------------+---------------+ ↑ DDS 封包 ↑ +---------------+---------------+ | micro-ROS Agent | | (DDS ↔ Micro XRCE-DDS) | +---------------+---------------+ ↑ XRCE-DDS 封包 ↑ +---------------+---------------+ | micro-ROS Client (MCU) | | (rclc API, RTOS, Sensors) | +-------------------------------+ ``` #### (2) 分層比較表 | 分層 | ROS 2 | micro-ROS | | -------------- | ---------------------------- | --------------------------- | | 應用層 | Node (Python/C++) | Node (C/C++) | | Client Library | `rclpy` / `rclcpp` | `rclc` / `rcl` | | Middleware | DDS (Fast RTPS, Cyclone DDS) | Micro XRCE-DDS | | 傳輸層 | TCP/UDP | UART/UDP/SPI/CAN | | 作業系統 | Linux / Windows | FreeRTOS / Zephyr / Arduino | | 資源需求 | 高(>512 MB RAM) | 極低(<512 KB RAM) | --- ### 3. 通訊協定差異 #### ROS 2:DDS(Data Distribution Service) * **全功能分散式協定**。 * 節點自動發現 (Discovery)。 * 支援多種 QoS 與安全機制。 * 適合大型系統、高頻資料流。 #### micro-ROS:Micro XRCE-DDS * **輕量化代理式通訊**。 * 以 **Client–Agent** 結構取代節點間直接互聯。 * 省去 Discovery、Security 等複雜程序。 * MCU 只需負責封包生成與解析,計算負擔極低。 | 面向 | DDS | Micro XRCE-DDS | | ----- | ------------ | -------------- | | 模式 | Peer-to-Peer | Client–Agent | | 資料可靠性 | 完整 QoS 支援 | 精簡 QoS | | 節點發現 | 自動 | 由 Agent 管理 | | 封包大小 | 1 KB–2 KB | 約 50–150 bytes | | 通訊負擔 | 高 | 極低 | --- ### 4. 開發環境與工具鏈比較 | 項目 | ROS 2 | micro-ROS | | ---- | --------------------------------------- | ---------------------------- | | 建構工具 | `colcon`, `ament_cmake`, `ament_python` | `colcon` + `micro_ros_setup` | | 套件管理 | `rosdep`, `rosinstall` | 同 ROS 2 架構 | | 編譯平台 | 原生編譯 (x86/ARM64) | 交叉編譯 (arm-none-eabi gcc) | | 開發語言 | Python / C++ | C (支援 C++) | | 啟動方式 | `ros2 run`, launch file | 在 MCU 初始化函式中呼叫 | | 除錯方式 | rqt、CLI、rviz | UART log、Agent verbose 模式 | | 模擬測試 | Gazebo / RViz | 可在 Ubuntu 模擬 Client 節點 | micro-ROS 保持與 ROS 2 幾乎相同的建構邏輯, 讓開發者能用熟悉的 colcon 環境同時管理兩邊專案。 --- ### 5. 效能與資源比較 | 指標 | ROS 2 (Node on Linux) | micro-ROS (Node on MCU) | | ------ | --------------------- | ----------------------- | | 記憶體需求 | 約 300–800 MB | 約 100–400 KB | | CPU 負載 | 中高 | 低 | | 平均延遲 | < 10 ms (UDP) | 40–100 ms (UART) | | 最大封包 | 幾 MB | 256 bytes | | 可連線節點數 | 幾百個 | 受 Agent 管理限制(數十個) | | 即時性 | 軟即時 | 硬即時(依 RTOS) | ROS 2 側重「吞吐量」;micro-ROS 側重「可預測性與低資源消耗」。 --- ### 6. 應用定位與系統角色 | 系統層級 | ROS 2 的角色 | micro-ROS 的角色 | | ------------ | ----------------- | ------------- | | **上層:任務決策** | AI 模型推論、路徑規劃、資料分析 | 不適用 | | **中層:通訊協調** | 節點間整合、狀態監控 | 透過 Agent 介入 | | **下層:感測與控制** | 需外部控制板協助 | 直接運行在 MCU | 在真實系統裡,常見的結構是: ``` AI/Decision (ROS 2) → Control Command Topic ↓ micro-ROS Client (MCU) ↓ Sensor Feedback Topic → ROS 2 Monitor ``` --- ### 7. 功能取捨與相容性分析 | 功能 | ROS 2 | micro-ROS | 備註 | | ---------------------- | --------- | ---------- | --------------------- | | Publisher / Subscriber | ✔ | ✔ | 完全相容 | | Service | ✔ | ✔ | 支援但功能有限 | | Action | ✔ | ✖ | 尚未支援 | | Parameter Server | ✔ | ✖ | 不實作 | | Launch System | ✔ | ✖ | MCU 無 OS | | QoS | 全面支援 | 精簡版 | 僅 Reliability / Depth | | Discovery | 自動 | 由 Agent 管理 | 無廣播負擔 | | Security | 可擴充 | ✖ | 無安全層 | | Diagnostics | rqt / CLI | 需自訂 | 由 Host 負責 | 這些差異說明了:micro-ROS 著重在「能運作」,而非「功能齊全」。 --- ### 8. 實際整合案例 #### 案例 1:智慧小車 * 主機 (Jetson Nano):ROS 2 節點負責影像辨識與路徑規劃。 * 子板 (STM32 + FreeRTOS):micro-ROS Client 控制馬達、回報里程。 * 通訊介面:UART。 * 資料流: ``` /camera/image_raw → AI 處理節點 /cmd_vel → micro-ROS 控制節點 /odom ← micro-ROS 回傳節點 ``` #### 案例 2:工業感測網 * MCU 節點各自感測溫度、壓力。 * 主機 ROS 2 節點彙整資料並視覺化。 * micro-ROS Agent 常駐主機,管理數十個 Client。 #### 案例 3:教育用途 * 用 ESP32 開發板搭建 micro-ROS Client。 * 學生在 Ubuntu 端用 Python 撰寫 ROS 2 Node。 * 即時看到感測值與回應命令。 --- ### 9. 開發思維的轉換 在 ROS 2 裡,開發者思考「多模組協作」。 在 micro-ROS 裡,開發者思考「資源最佳化」。 | 思維 | ROS 2 | micro-ROS | | ---- | ------------------ | -------------- | | 任務重點 | 整體架構設計 | 單節點效率 | | 程式習慣 | 多執行緒 / 大量 Callback | 單執行緒 / 簡化事件循環 | | 錯誤處理 | 豐富例外處理機制 | 偏重穩定、靜態配置 | | 測試方式 | 模擬與視覺化 | UART Log 與即時觀察 | 在嵌入式開發中,**每一筆記憶體配置、每一次封包傳輸都要被量化**。 這是 micro-ROS 開發與桌面級 ROS 2 最大的文化差異。 --- ### 10. 綜合比較表 | 面向 | ROS 2 | micro-ROS | 差異核心 | | ----- | ------------ | ----------------- | -------- | | 通訊核心 | DDS | Micro XRCE-DDS | Agent 橋接 | | 執行環境 | 高階作業系統 | RTOS / Bare Metal | 不同層級 | | 程式語言 | Python / C++ | C / C++ | 語法層級 | | 通訊模型 | Peer-to-Peer | Client–Agent | 架構差異 | | 封包大小 | 大 | 小 | 資源配置 | | 記憶體需求 | 高 | 低 | 適用平台 | | 功能完整度 | 高 | 精簡 | 可用性 | | 即時性 | 軟即時 | 硬即時 | 回應速度 | | 擴充性 | 優 | 受限 | 平台差異 | | 應用面 | AI、導航、雲端 | 感測、控制、IoT | 系統分工 | --- ### 11. 小結:兩者的共生關係 ROS 2 與 micro-ROS 的關係可以這樣總結: > **ROS 2 是整體智慧的「中樞」,micro-ROS 是即時反應的「神經末梢」。** 它們在系統中各司其職: * **ROS 2**:做決策、整合資料、提供全域控制。 * **micro-ROS**:負責接收感測、執行控制命令、即時回報。 兩者透過 Agent 橋接成一個閉環系統: ``` Decision (ROS 2) ↓ command micro-ROS Client → Actuator ↑ feedback ``` 這樣的架構讓大型機器人或 IoT 系統可以同時擁有: * ROS 2 的彈性與資料處理能力, * micro-ROS 的即時性與低耗能特性。 --- ## 五、訊息型別與客製化通訊 ### 1. 為什麼訊息型別很重要 在 ROS 2 / micro-ROS 世界裡,**訊息型別(Message Type)是節點之間通訊的共同語言**。 每個 Topic 都有固定的資料結構, Publisher 和 Subscriber 只有在使用相同的訊息定義時才能理解彼此的封包內容。 範例: ```text Topic: /sensor/temperature Type: std_msgs/msg/Float32 ``` Publisher 傳送一個 `Float32`,Subscriber 也必須用 `Float32` 接收,否則會報錯。 micro-ROS 與 ROS 2 在這點完全一致: 它們都使用 **IDL(Interface Definition Language)** 來定義訊息結構, 再透過編譯器自動生成 C / C++ / Python 對應的程式碼。 --- ### 2. ROS 2 訊息定義的基本語法 在 ROS 2 中,訊息檔(`.msg`)是一種簡單結構定義格式。 範例:建立一個名為 `Temperature.msg` 的自訂型別: ```msg float32 value string unit ``` 這代表每則訊息都有兩個欄位: * 一個浮點數 `value` * 一個字串 `unit` ROS 在建置時會自動將 `.msg` 檔轉換為中介描述檔 `.idl`, 再進一步產生對應語言的類別(C、C++、Python)。 --- ### 3. 訊息型別的轉譯流程 整個轉譯鏈如下: ``` Temperature.msg ↓ IDL (Interface Definition Language) ↓ C / C++ 結構定義 ↓ micro-ROS 編譯結果 (micro_ros_msgs) ``` micro-ROS 會在編譯過程中讀取相同的 IDL 檔案, 因此 ROS 2 和 micro-ROS 兩端能共享相同結構。 --- ### 4. ROS 2 標準訊息庫(std_msgs, sensor_msgs 等) 在一般應用裡,你不一定需要自訂訊息, ROS 已經內建了數百種常用結構, micro-ROS 也完全相容這些型別。 | 套件 | 說明 | 常見訊息 | | ----------------- | ------ | ---------------------------- | | `std_msgs` | 基礎資料型別 | Bool, Int32, Float32, String | | `geometry_msgs` | 幾何資訊 | Vector3, Pose, Twist | | `sensor_msgs` | 感測資料 | Imu, Image, LaserScan | | `nav_msgs` | 導航資訊 | Odometry, Path | | `diagnostic_msgs` | 狀態監控 | KeyValue, DiagnosticArray | 在 micro-ROS 中,這些型別都會在建置時自動轉換為 C 結構。 --- ### 5. micro-ROS 對訊息的支援範圍 micro-ROS 可以使用任何「純資料結構(POD, Plain Old Data)」的型別。 但它**不支援動態記憶體分配或複雜容器**(例如 `std::vector`、`map`)。 支援範圍如下: | 類型 | 支援狀態 | 備註 | | ------------------------------ | ------- | ---------------------------- | | 整數型(int8, int16, int32, int64) | ✔ | 全支援 | | 浮點型(float32, float64) | ✔ | 全支援 | | 布林值(bool) | ✔ | | | 字串(string) | ⚠️ 有限支援 | 長度需固定或限制上限 | | 陣列(定長) | ✔ | 編譯期固定大小 | | 陣列(動長) | ⚠️ 有限支援 | 須使用 `rosidl_runtime_c__*` 型別 | | 物件巢狀 | ✔ | 需先定義子訊息 | 範例: 可以在 micro-ROS 用這種定義: ```msg float32[3] accel ``` 但不能使用: ```msg float32[] accel # 動態長度不保證支援 ``` --- ### 6. 自訂訊息型別的建立步驟 以「溫度 + 濕度」為例,建立一個新的 `EnvData.msg`。 #### (1) 建立目錄結構 ``` my_msgs/ ├── msg/ │ ├── EnvData.msg ├── package.xml └── CMakeLists.txt ``` #### (2) 編寫 `EnvData.msg` ```msg float32 temperature float32 humidity ``` #### (3) 編輯 `CMakeLists.txt` ```cmake find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} "msg/EnvData.msg" ) ``` #### (4) 在 micro-ROS Client 專案中引用 在 C 程式碼裡: ```c #include "my_msgs/msg/env_data.h" my_msgs__msg__EnvData data; data.temperature = 25.3; data.humidity = 40.2; rcl_publish(&publisher, &data, NULL); ``` --- ### 7. 資料同步與版本一致性 micro-ROS Client 與 ROS 2 節點使用相同的 `.msg` 定義, 所以**兩邊必須用同一份編譯出的介面檔案**。 建議在同一個工作空間內管理: ``` src/ ├── my_msgs/ # 自訂訊息 ├── micro_ros_client/ # MCU 專案 └── ros2_host_node/ # 主機節點 ``` Host 端與 Client 端在建構時都 include 來自 `my_msgs` 的頭檔, 確保結構完全一致。 --- ### 8. IDL 與跨語言對應 ROS 2 的 `.msg` 實際上在底層轉換為 IDL(Interface Definition Language)。 這使得 ROS 能同時生成多語言綁定: | ROS 2 型別 | C 對應 | Python 對應 | | ------------ | -------------------------- | ------------- | | `float32` | `float` | `float` | | `int32` | `int32_t` | `int` | | `string` | `rosidl_runtime_c__String` | `str` | | `float32[3]` | `float data[3]` | `list[float]` | 在 micro-ROS 裡,使用的是 C 版本的封裝。 它會把每個欄位展開成純 C 結構,方便 MCU 操作。 範例(自動產生的 C 定義): ```c typedef struct my_msgs__msg__EnvData { float temperature; float humidity; } my_msgs__msg__EnvData; ``` --- ### 9. 記憶體配置與訊息初始化 由於 MCU 沒有動態記憶體, micro-ROS 的訊息必須在使用前明確初始化。 ```c my_msgs__msg__EnvData msg; my_msgs__msg__EnvData__init(&msg); msg.temperature = 26.5; msg.humidity = 42.1; rcl_publish(&pub, &msg, NULL); my_msgs__msg__EnvData__fini(&msg); ``` 若使用標準型別(如 `std_msgs/msg/String`), 則需使用 `rosidl_runtime_c__String__assign()` 來設定字串內容: ```c std_msgs__msg__String str; std_msgs__msg__String__init(&str); rosidl_runtime_c__String__assign(&str.data, "Hello micro-ROS"); ``` --- ### 10. 訊息壓縮與效能考量 micro-ROS 為了減少封包負擔, 在序列化時會使用 eProsima Fast-CDR 的緊湊模式。 **最佳化原則:** 1. 儘量使用定長型別(float、int)。 2. 避免字串與可變長陣列。 3. 將結構控制在 256 bytes 以內。 這樣可確保傳輸速率與延遲穩定, 特別是在 UART 或低速網路上運作時。 --- ### 11. micro-ROS 不支援的特殊結構 * **Dynamic Nested Types**:巢狀結構中若包含動態長度字串會導致錯誤。 * **Union / Variant**:IDL 支援但 micro-ROS 不實作。 * **Time / Duration**:需用 `builtin_interfaces/msg/Time` 替代。 若需要傳時間戳,正確寫法: ```msg builtin_interfaces/Time stamp float32 data ``` --- ### 12. 例:整合自訂訊息的 Ping-Pong 系統 你可以把 Ping-Pong 範例改成使用自訂訊息: ```msg string msg int32 counter ``` Host Node: ```python from my_msgs.msg import PingData ... data = PingData() data.msg = "ping" data.counter = self.counter self.publisher.publish(data) ``` micro-ROS Client: ```c #include "my_msgs/msg/ping_data.h" ... my_msgs__msg__PingData rx_msg; my_msgs__msg__PingData__init(&rx_msg); printf("Received: %s #%d\n", rx_msg.msg.data, rx_msg.counter); ``` 兩邊都能自動解析結構,無需手動序列化。 --- ### 13. 小結 1. ROS 2 與 micro-ROS 共享相同的訊息定義機制(IDL → 語言封裝)。 2. micro-ROS 僅支援靜態、定長、POD 型態。 3. 所有自訂 `.msg` 檔必須同時存在於主機與 MCU 專案中。 4. 編譯時會自動生成對應的 C 結構與序列化程式。 5. 透過這一機制,micro-ROS 能以極低負擔實現複雜資料交換。 --- ## 六、系統整合與開發環境 ### 1. 為什麼要「整合開發環境」 micro-ROS 的本質是 ROS 2 的延伸模組, 但它同時要跑在兩個完全不同的世界上: * **主機端(Host)**:ROS 2 + Ubuntu + DDS * **微控制器端(Client)**:FreeRTOS / Zephyr / Arduino 要讓兩邊合作順利,你需要建立一個能同時管理、編譯、測試的環境, 這就是「整合開發環境(Integrated Development Workspace)」的目的。 它能讓: 1. micro-ROS Client 與 ROS 2 Host 共用同一份 `.msg` 定義。 2. Host 端與 Client 端都能用 `colcon build` 一次建構。 3. Agent 可以自動在 Host 啟動,進行測試與模擬。 --- ### 2. 系統整體結構 整個開發環境通常由三個主要部分構成: ``` +---------------------------------------------+ | ROS 2 主機端 (Host) | |---------------------------------------------| | OS: Ubuntu 22.04 | | ROS 2: Humble Hawksbill | | Tool: colcon,micro_ros_setup,micro-ros-agent| |---------------------------------------------| | 節點角色:Subscriber / Controller / Agent | +---------------------------------------------+ ⇅ UDP / UART / Serial +---------------------------------------------+ | micro-ROS 客戶端 (MCU) | |---------------------------------------------| | OS: FreeRTOS / Zephyr / Arduino Core | | Lib: micro-ROS rclc / rcl / XRCE-DDS | |---------------------------------------------| | 節點角色:Publisher / Sensor / MotorCtrl | +---------------------------------------------+ ``` 兩邊透過 Agent 通訊,維持同步的 ROS 2 Topic 資料流。 --- ### 3. ROS 2 版本與 micro-ROS 對應 ROS 2 每個發行版對應一個 micro-ROS 版本。 官方明確要求 **版本必須匹配**,否則訊息結構或 API 可能不相容。 | ROS 2 版本 | micro-ROS 對應版本 | Ubuntu 推薦版本 | 支援狀態 | | ------------------- | -------------- | ------------- | ------- | | Foxy Fitzroy | Foxy | 20.04 LTS | LTS(舊) | | Galactic Geochelone | Galactic | 20.04 / 22.04 | 穩定 | | Humble Hawksbill | Humble | 22.04 LTS | LTS(推薦) | | Iron Irwini | Iron | 22.04 / 24.04 | 最新 | | Jazzy Jalisco | Jazzy | 24.04 LTS | 開發中 | 實務上目前最穩定的是 **Humble + micro-ROS Humble**, 幾乎所有範例與教學都以這對版本為主。 --- ### 4. 建立工作空間(Workspace) 在主機端(Ubuntu)建立 ROS 2 Workspace: ```bash mkdir -p ~/micro_ros_ws/src cd ~/micro_ros_ws ``` 載入 ROS 2 環境: ```bash source /opt/ros/humble/setup.bash ``` --- ### 5. 安裝 micro-ROS 開發工具 micro-ROS 提供官方的 `micro_ros_setup` 套件, 可自動建立、交叉編譯、模擬 micro-ROS Client。 ```bash sudo apt install ros-humble-micro-ros-setup ``` --- ### 6. 初始化 micro-ROS 專案 切換到工作目錄: ```bash cd ~/micro_ros_ws ros2 run micro_ros_setup create_firmware_ws.sh freertos esp32 ``` 這個指令會: 1. 建立 micro-ROS firmware 專案。 2. 自動下載對應的 FreeRTOS / ESP-IDF / micro-ROS libraries。 3. 建立 MCU 編譯環境。 --- ### 7. 建構 micro-ROS Firmware ```bash cd firmware ros2 run micro_ros_setup build_firmware.sh ``` 這一步會: * 編譯 MCU 專案。 * 產生 micro-ROS 客戶端二進位檔(例如 `micro_ros_esp32.bin`)。 --- ### 8. 主機端啟動 micro-ROS Agent 在 Host 端開新終端機,啟動 Agent: ```bash source /opt/ros/humble/setup.bash micro-ros-agent udp4 --port 8888 -v6 ``` 說明: | 參數 | 功能 | | ------------- | -------------- | | `udp4` | 使用 IPv4 UDP 傳輸 | | `--port 8888` | 指定通訊埠 | | `-v6` | 顯示封包細節 | 若使用 UART: ```bash micro-ros-agent serial --dev /dev/ttyUSB0 -b 115200 ``` --- ### 9. 檢查通訊狀態 啟動 Agent 後,你應該會看到: ``` [INFO] Micro XRCE-DDS Agent running... [INFO] Client connected, ID: 0x01 ``` 這代表 MCU 已成功連線。 接著在另一個終端機: ```bash ros2 topic list ``` 若有 `/microROS/ping` 或 `/microROS/temp` 等 Topic 出現,就代表資料流已建立。 --- ### 10. 整合自訂訊息與 Workspace 同步 若有自訂 `.msg` 型別(例如 `EnvData.msg`), 建議統一放在 Workspace 裡的 `my_msgs` 專案中: ``` micro_ros_ws/ ├── src/ │ ├── my_msgs/ │ │ ├── msg/EnvData.msg │ │ ├── CMakeLists.txt │ │ └── package.xml │ ├── micro_ros_firmware/ │ ├── host_controller/ ``` 然後在 MCU 端與 Host 端的 `CMakeLists.txt` 都加上: ```cmake find_package(my_msgs REQUIRED) ament_target_dependencies(target_name my_msgs) ``` 這樣一旦重建 Workspace, Host 與 Client 就會同時擁有相同的訊息結構。 --- ### 11. FreeRTOS 與 micro-ROS 整合 micro-ROS Client 通常執行在 FreeRTOS 的任務中。 範例架構: ```c void appMain(void *argument) { rclc_support_t support; rclc_support_init(&support, 0, NULL, &allocator); ... for(;;) { rclc_executor_spin_some(&executor, RCL_MS_TO_NS(100)); vTaskDelay(pdMS_TO_TICKS(100)); } } ``` 這樣設計讓 micro-ROS 能與其他任務(例如感測器採樣、LED 控制) 在 RTOS 的 Task 排程中共存,保證即時性。 --- ### 12. 在 Ubuntu 上模擬 micro-ROS Client 如果沒有 MCU,也可以直接在電腦上模擬: ```bash ros2 run micro_ros_setup configure_firmware.sh host ros2 run micro_ros_setup build_firmware.sh ros2 run micro_ros_setup run_firmware.sh ``` 此模式會用 C 節點模擬 micro-ROS Client, 可搭配 Agent 測試封包流動與功能正確性。 --- ### 13. 常見環境錯誤與排除 | 問題 | 原因 | 解決方案 | | ------------------------- | ---------------- | ------------------------ | | `Agent connection failed` | MCU 未連線或 port 錯誤 | 檢查 `--port` 或 USB 裝置名稱 | | `build_firmware.sh` 失敗 | 缺少 toolchain | 安裝 ESP-IDF 或 ARM GCC | | Topic 收不到資料 | QoS 設定不符 | 在 Host 與 Client 使用相同 QoS | | 訊息解析錯誤 | `.msg` 不一致 | 確保兩端使用同一套 `my_msgs` 套件 | --- ### 14. 多節點整合(Launch 範例) 在 ROS 2 端可以建立 `micro_ros_system.launch.py`, 同時啟動 Agent、控制節點與視覺化節點: ```python from launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): return LaunchDescription([ Node(package='micro_ros_agent', executable='micro_ros_agent', arguments=['udp4', '--port', '8888']), Node(package='host_controller', executable='controller_node'), Node(package='rqt_gui', executable='rqt_gui') ]) ``` 執行: ```bash ros2 launch my_system micro_ros_system.launch.py ``` 即可自動啟動整個 micro-ROS 網路。 --- ### 15. 各版本函式庫對應與相容性 | 套件名稱 | ROS 2 對應 | 功能 | | --------------------- | ---------------- | ----------- | | `rclpy` | ROS 2 Host 端 | Python 節點開發 | | `rclcpp` | ROS 2 Host 端 | C++ 節點開發 | | `rclc` | micro-ROS Client | C 節點開發 | | `micro_ros_agent` | ROS 2 Host 端 | Agent 程式 | | `micro_ros_setup` | ROS 2 Host 端 | 自動建構與模擬工具 | | `microxrcedds_client` | MCU 端 | 封包協定層 | 只要版本相符,這些套件會自動整合。 --- ### 16. 環境維護與升級 建議每次建構前重新載入環境: ```bash source /opt/ros/humble/setup.bash colcon build --symlink-install source install/setup.bash ``` micro-ROS 升級時也需重建 firmware: ```bash ros2 run micro_ros_setup update_firmware.sh ``` 這樣能避免 `rosidl` 與 `rclc` 不相容的問題。 --- ### 17. 小結 * micro-ROS 的開發需要同時考慮主機與 MCU 端。 * 透過 Workspace 整合可共用訊息與編譯環境。 * `micro_ros_setup` 是最重要的建構工具。 * Host 與 Client 必須保持版本一致。 * 可使用 Ubuntu 模擬環境快速測試封包流。 整體開發流程如下: ``` 撰寫程式(Host / MCU) ↓ 共用訊息(.msg) ↓ colcon build(同步建構) ↓ 啟動 micro-ROS Agent ↓ 驗證資料流(ros2 topic echo) ``` --- ## 七、實務應用場域(Practical Applications of micro-ROS) ### 1. 為什麼 micro-ROS 適合實務應用 micro-ROS 的定位,就是讓「感測與控制」的最底層設備能說 ROS 的語言。 在現代系統裡,大型主機處理決策(AI、導航、資料融合), 小型控制器負責即時任務(驅動馬達、讀感測器、傳遞資料)。 這兩層如果沒有共通通訊架構,就要手動設計 UART、I2C、MQTT 等協定。 micro-ROS 解決了這個痛點,它讓這些小裝置直接變成 ROS 節點。 --- ### 一、IoT 與感測網(Internet of Things) #### 1. 應用場景 智慧農業、智慧建築、環境監測、能源管理系統等, 通常有上百個感測節點(溫度、濕度、氣體、光照), 資料需要集中到主機再上傳雲端。 micro-ROS 可以讓每個感測器板都成為一個「ROS 2 節點」, 自動以 Topic 發布資料到主機,不必再做自訂通訊協定。 #### 2. 系統架構圖 ``` +---------------------------+ | ROS 2 Host Node | |---------------------------| | Aggregator / Cloud Bridge | | micro-ROS Agent (UDP) | +-------------+-------------+ ↑ Wi-Fi / Ethernet ↑ +-------------+-------------+ | micro-ROS Clients (MCUs) | |---------------------------| | Temp Node | /sensor/temp| | Humid Node | /sensor/hum | | Light Node | /sensor/lux | +---------------------------+ ``` #### 3. 資料流解釋 1. 每個 MCU 節點(如 ESP32)使用 micro-ROS 以 UDP 傳送感測資料: `/sensor/temp`, `/sensor/hum`, `/sensor/lux`。 2. 主機上的 micro-ROS Agent 收到封包並轉成 DDS。 3. ROS 2 Host Node 聚合資料,並可直接以 Python 發布到雲端 API。 範例(主機端 Python 節點): ```python def callback(data): publish_to_cloud(data.temperature, data.humidity) ``` #### 4. 優點 | 面向 | micro-ROS 帶來的優勢 | | --- | ------------------------------- | | 通訊 | 不需自訂協定,直接用 Topic 傳輸 | | 整合 | 可直接接入 ROS 2 雲端橋接(如 MQTT Bridge) | | 可擴展 | 新增感測器只需新增節點 | | 成本 | MCU 價格低、功耗低、可長期運作 | #### 5. 延伸應用 * 智慧電表(Energy metering) * 冷鏈監控(Cold-chain monitoring) * 城市噪音監測 * IoT 資料即時儀表板(整合 RViz / rqt) --- ### 二、機器人與自動化系統(Robotics) #### 1. 應用場景 在機器人系統中,主機(Jetson、NUC)通常負責導航與 AI, 而下層控制板(STM32、ESP32)負責馬達與感測。 這種「主控+子控制器」架構是 micro-ROS 的完美舞台。 #### 2. 系統架構圖 ``` +----------------------------------+ | ROS 2 Host (AI) | |----------------------------------| | Navigation / Vision / Planning | | micro-ROS Agent (serial) | +---------------+------------------+ | UART | +---------------+------------------+ | micro-ROS Client (MCU) | |----------------------------------| | Motor Controller / Encoder Node | | Ultrasonic Sensor Node | +----------------------------------+ ``` #### 3. 資料流 1. Host Node 發布 `/cmd_vel`(速度命令)。 2. MCU 端的 micro-ROS Subscriber 收到命令 → 控制馬達 PWM。 3. MCU 端的 micro-ROS Publisher 發布 `/odom`(里程資訊)。 4. Host 端的 Navigation Node 根據 `/odom` 計算位置。 #### 4. 範例主機端 Python 節點 ```python from geometry_msgs.msg import Twist def move_forward(pub): msg = Twist() msg.linear.x = 0.3 msg.angular.z = 0.0 pub.publish(msg) ``` micro-ROS 端(C 程式): ```c rcl_subscription_t sub; rclc_subscription_init_default(&sub, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(geometry_msgs, msg, Twist), "/cmd_vel"); ``` 這樣 MCU 就能直接理解 ROS 2 的控制訊息。 #### 5. 延伸應用 * ROS 2 自走車:主機負責 SLAM、MCU 控制驅動。 * 智慧機械臂:ROS 2 做運動規劃,micro-ROS 控制馬達伺服。 * 自動搬運車(AGV):ROS 2 統籌路徑、micro-ROS 執行底層驅動。 --- ### 三、工業控制與邊緣運算(Industrial / Edge Applications) #### 1. 應用場景 在工業自動化中,感測器與控制器分散各地。 傳統做法是使用 Modbus、CAN、PROFINET。 但現在 ROS 2 被引入工控領域, micro-ROS 讓現有的微控制器可以在不改硬體的情況下, 直接成為 ROS 節點參與資料交換。 #### 2. 系統結構 ``` +---------------------------------+ | ROS 2 Host (Edge PC) | |---------------------------------| | Process Monitor Node | | micro-ROS Agent (CAN/UDP) | +---------------------------------+ ↑ CAN Bus / Ethernet ↑ +---------------+---------------+ | micro-ROS Client (STM32) | |-------------------------------| | Pressure Sensor Node | | Valve Controller Node | +-------------------------------+ ``` #### 3. 資料流 * 每個 micro-ROS 節點發佈感測資料: `/sensor/pressure`, `/sensor/flowrate`。 * Host Node 訂閱後整合並作邏輯判斷, 若超出範圍,發送 `/cmd/valve` 回控制器節點。 #### 4. micro-ROS 在工控的優勢 | 面向 | 優勢 | | ---- | --------------------- | | 可靠性 | DDS 架構 + QoS 保證資料到達 | | 可擴充性 | 新設備僅需掛上 Agent | | 整合性 | 支援多介面(CAN, UART, UDP) | | 即時性 | FreeRTOS 排程,毫秒級反應 | #### 5. 實務應用案例 * 智慧工廠設備監控(機械壓力、溫度回饋) * 電力變壓站數據收集與診斷 * 自動化流水線控制(以 micro-ROS 取代 PLC 分層) --- ### 四、教育與研究應用(Education & Research) #### 1. micro-ROS 作為教學工具 因為 micro-ROS 可以在低成本硬體上執行(ESP32、Arduino Nano), 學校與研究單位廣泛使用它來教學「嵌入式 ROS」。 學生不需要昂貴的開發板,只要一台筆電與一片 ESP32, 就能在課堂上體驗從感測、封包、到 ROS 通訊的整個過程。 #### 2. 典型課程架構 | 單元 | 教學內容 | 實作成果 | | ----- | ------------ | ---------------- | | 第 1 週 | ROS 2 架構 | Hello World Node | | 第 2 週 | micro-ROS 簡介 | Client 連線 Agent | | 第 3 週 | Topic 通訊 | MCU 傳感測資料到 PC | | 第 4 週 | Service 實作 | MCU 接收指令控制 LED | | 第 5 週 | IoT 延伸 | 資料上傳雲端平台 | | 第 6 週 | 整合專題 | 完成感測 + 控制專案 | #### 3. 實驗室常見專題 * **導盲車(GuideBot)**:micro-ROS 控制距離感測與避障;ROS 2 主機進行語音辨識與路徑規劃。 * **智慧農場模擬系統**:多個 micro-ROS Client 模擬溫濕度感測;ROS 2 聚合資料後顯示即時趨勢圖。 * **IoT Security 專題**:研究 micro-ROS Agent 資料驗證與加密。 #### 4. 教育應用的價值 * 讓學生同時學習 **嵌入式程式設計 + ROS 架構思維**。 * 實際理解分散式系統、封包通訊與即時控制。 * micro-ROS 是 ROS 2 教學鏈的「前哨站」, 幫助學習者從基礎的 Node 邏輯跨入系統整合思維。 --- ### 五、micro-ROS 的跨領域價值 micro-ROS 不只屬於機器人領域。 它的輕量特性讓它成為 **IoT、AIoT、邊緣運算** 的核心通訊層。 | 領域 | 應用 | 角色 | | -------- | ----------- | ---- | | IoT | 感測器網路、智慧城市 | 邊緣節點 | | Robotics | 自走車、機械手臂 | 驅動控制 | | 工控 | 智慧工廠、遠端監控 | 即時感測 | | 教育 | 嵌入式與 ROS 教學 | 實驗平台 | 在這些場合,micro-ROS 讓「感測端」、「控制端」、「決策端」 可以統一在一個 ROS 2 通訊生態裡運作。 --- ### 6. 小結 1. micro-ROS 已從單純的嵌入式通訊框架,成為 **ROS 2 的邊緣延伸層**。 2. 在 IoT、機器人與工控場域中,它負責「即時、低功耗、標準化」的資料傳輸。 3. 它使開發者能用一套 ROS 工具鏈貫穿從 AI 到硬體的整個開發流程。 4. 它在教育與研究上的普及,正讓 ROS 走入嵌入式與物聯網時代。 --- ## 八、理論篇總結(Summary of the micro-ROS Theoretical Series) ### 1. micro-ROS 為何誕生 micro-ROS 並不是 ROS 2 的替代品,而是 ROS 2 的「邊緣延伸層」。 ROS 2 專注於高階作業系統與強大運算平台(例如 Jetson、x86、雲端伺服器), 但現實世界的大多數設備是微控制器(MCU), 記憶體僅數百 KB,卻是系統的感測與控制基礎。 micro-ROS 讓這些 MCU 也能以 **ROS 的語言** 參與系統, 透過輕量化協定 Micro XRCE-DDS 與 Agent 橋接, 實現「從感測器到雲端」的完整通訊閉環。 --- ### 2. 架構重點回顧 micro-ROS 的三層結構: ``` ROS 2 Node ←DDS→ micro-ROS Agent ←XRCE-DDS→ micro-ROS Client ``` | 組件 | 執行環境 | 功能 | | -------------------- | --------------------- | --------- | | **ROS 2 Node** | Ubuntu / Jetson / x86 | 資料處理與決策 | | **micro-ROS Agent** | Host (Ubuntu) | 封包轉譯、連線管理 | | **micro-ROS Client** | MCU / FreeRTOS | 感測與控制節點 | 這個設計確保了高效能(Host)與即時性(MCU)可以共存, 兩邊透過 Agent 交換封包而不需改協定。 --- ### 3. 通訊與封包哲學 micro-ROS 採用的 **Micro XRCE-DDS** 是 DDS 的極簡版本: * 用 Client–Agent 模式取代節點間直連。 * 用固定大小封包(50–150 bytes)降低傳輸負擔。 * 用靜態記憶體配置確保即時性。 Agent 的角色相當於「翻譯官」, 讓不同層級的裝置都能參與相同 DDS 網路。 --- ### 4. 與 ROS 2 的關係 | 面向 | ROS 2 | micro-ROS | | ---- | --------------- | --------------------------- | | 功能範圍 | 完整生態(AI、導航、服務) | 嵌入式通訊與控制 | | 通訊協定 | DDS | Micro XRCE-DDS | | 語言支援 | Python / C++ | C / C++ | | 作業系統 | Linux / Windows | FreeRTOS / Zephyr / Arduino | | 封包方向 | 節點對節點 | Client–Agent | | 資源需求 | 高 | 低 | micro-ROS 專注於「即時與節能」, 讓 ROS 架構能延伸到每一顆感測器與執行器。 --- ### 5. 訊息型別與資料一致性 * ROS 2 與 micro-ROS 共用 `.msg` / `.idl` 機制。 * 所有訊息在編譯階段轉成固定的 C 結構。 * micro-ROS 僅支援定長與靜態資料型別(避免動態記憶體)。 * 主機與 MCU 必須使用相同版本的訊息定義。 這種靜態資料交換方式,是 micro-ROS 能在 100KB RAM 環境下穩定運作的關鍵。 --- ### 6. 系統整合流程 建立一個完整 micro-ROS 系統的步驟: 1. 在 Ubuntu 建立 ROS 2 + micro-ROS Workspace。 2. 使用 `micro_ros_setup` 產生 MCU 專案與工具鏈。 3. 建構 Firmware 並燒錄至 MCU。 4. 啟動 micro-ROS Agent(UDP / Serial)。 5. 用 `ros2 topic echo` 驗證通訊。 6. 整合自訂訊息、QoS 與多節點架構。 這套流程可同時支援開發、模擬與實體硬體部署。 --- ### 7. 實務應用總覽 | 領域 | micro-ROS 的角色 | | ----------- | -------------------- | | **IoT 感測網** | 邊緣節點,負責資料收集與傳輸 | | **智慧機器人** | 馬達控制、里程回報、避障偵測 | | **工業控制** | 即時監測、閥門控制、機械狀態分析 | | **教育研究** | 嵌入式 ROS 教學、封包模擬、網路實驗 | 在這些系統裡,micro-ROS 讓「硬體端」與「軟體端」以同樣的 ROS 語言協作。 --- ### 8. 技術演進與未來方向 * **QoS 擴充**:逐步支援更多 DDS 參數(例如可靠性重傳)。 * **安全通訊**:整合 DDS Security Plugin,提供資料加密與認證。 * **跨語言支援**:未來可能透過 MicroPython 或 Cython Bridge 實驗性加入 Python 綁定。 * **AI at the Edge**:結合微型 AI 模型(如 TinyML)於 micro-ROS 節點上運行。 這些發展代表 micro-ROS 將成為「低功耗 AI 裝置」與「分散式 ROS 系統」的橋樑。 --- ### 9. 全篇總結 micro-ROS 的價值在於「連結」。 > 它把嵌入式裝置與雲端計算之間的鴻溝, > 用 ROS 架構的共同語言縫合起來。 學會 micro-ROS,代表你能掌握: * ROS 架構的內部機制(Node、Topic、DDS)。 * 嵌入式系統的限制與優化思維。 * 分散式系統的通訊模式與整合技術。 最終目標不只是讓 MCU 發送資料, 而是建立一個 **統一、可擴展、即時反應的智慧系統**。 --- ### 10. 延伸閱讀與參考 * [Official micro-ROS Documentation](https://micro.ros.org/docs/) * [ROS 2 Humble API Reference](https://docs.ros.org/en/humble/) * [eProsima Micro XRCE-DDS Specification](https://github.com/eProsima/Micro-XRCE-DDS) * [rclc API Reference (C)](https://github.com/ros2/rclc) * [micro-ROS Tutorials (Official GitHub)](https://github.com/micro-ROS/micro-ROS-demos) --- ### 11. 結語 micro-ROS 不是一項「小技術」, 而是一座讓嵌入式世界進入 ROS 宇宙的橋梁。 它讓感測器不再只是資料來源,而是分散式網路中的「智慧節點」。 這也是現代嵌入式工程與機器人學融合的象徵。 > 從微控制器到雲端,每一層都說 ROS 的語言。 ---