# 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 的語言。
---