🔍 一、什麼是 eProsima Micro XRCE-DDS?
名稱 | 說明 |
---|---|
XRCE-DDS | eXtremely Resource Constrained Environment DDS,是 OMG DDS 的子協定 |
用途 | 讓微控制器(如 STM32)這種資源有限的裝置,也能參與 DDS 資料流(如 ROS 2 中使用的 DDS) |
架構 | 採用 Client / Agent 模式,Client 跑在 MCU,Agent 跑在主機/樹莓派等具備 ROS 2 的系統上 |
🧱 二、Micro XRCE-DDS 的組成
📦 Micro XRCE-DDS Client(你在 STM32 上運行的程式)
-
小巧輕便、可裁剪(可用
CMake
調整功能) -
透過序列埠(Serial)或網路(UDP)向 Agent 發送請求
-
可執行的操作:
-
建立 DDS Participant
-
建立 Publisher / Subscriber
-
傳送 topic 訊息 / 接收 topic 資料
-
📦 Micro XRCE-DDS Agent(跑在 PC / Linux 的「轉譯伺服器」)
-
接收 Client 送來的請求
-
幫 Client 在 DDS 中建立實體,如:
-
Participant
-
Publisher
、Subscriber
-
Topic
-
-
是 ROS 2 和 micro-ROS 中的「中介者」
💬 支援的傳輸方式:
傳輸協定 | 是否支援 |
---|---|
Serial (UART) ✅ | |
UDPv4 / UDPv6 ✅ | |
TCPv4 / TCPv6 ✅ | |
自訂 Transport ✅ |
🔄 三、資料流程概念圖
⚙️ 四、如何應用在 RRC 控制板
✅ 對應情境:
動作 | XRCE-DDS 對應機制 |
---|---|
接收 /cmd_vel 指令控制馬達 | create_subscriber("cmd_vel") |
回傳 IMU 資料、馬達速度 | create_publisher("imu/data") |
傳輸通道 | UART (/dev/ttyACM0 ) |
傳送格式 | DDS-XRCE 編碼封包 |
🚀 五、實作指引關鍵工具
1. 使用 micro-ROS build system
快速產生 firmware:
2. 編譯與部署
3. 啟動 Agent
🧰 六、學習資源與官方手冊
資源名稱 | 連結 |
---|---|
🔗 Start Page | https://micro-xrce-dds.readthedocs.io |
🔗 GitHub Repo | https://github.com/eProsima/Micro-XRCE-DDS |
🔗 ROS 2 Integration Docs | https://micro.ros.org/docs |
📘 DDS 標準定義(XRCE) | OMG XRCE-DDS |
📣 小結
-
🧠 Micro XRCE-DDS 是 micro-ROS 與 ROS 2 的資料橋梁,幫助資源受限的 STM32 類裝置參與 ROS 通訊
-
⚙️ Client 在 MCU 上運行,Agent 在 ROS 主機上作為代理
-
🔌 你在 RRC 上跑的 micro-ROS,實際上就是透過 XRCE-DDS 與 ROS 網路互動
/* === app.c === */
#include <rcl/rcl.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <geometry_msgs/msg/twist.h>
#include "differential_chassis.h"
rcl_subscription_t cmd_vel_sub;
geometry_msgs__msg__Twist cmd_vel_msg;
void cmd_vel_callback(const void * msgin) {
const geometry_msgs__msg__Twist * msg = (const geometry_msgs__msg__Twist *)msgin;
float linear = msg->linear.x;
float angular = msg->angular.z;
diff_chassis_move(linear * 1000, 0, angular * 1000); // RRC 控制函式
}
void appMain(void * arg) {
rcl_allocator_t allocator = rcl_get_default_allocator();
rclc_support_t support;
rcl_node_t node;
rclc_executor_t executor;
rclc_support_init(&support, 0, NULL, &allocator);
rcl_node_init_default(&node, "rrc_chassis_node", "", &support);
rcl_subscription_init_default(
&cmd_vel_sub,
&node,
ROSIDL_GET_MSG_TYPE_SUPPORT(geometry_msgs, msg, Twist),
"cmd_vel");
rclc_executor_init(&executor, &support.context, 1, &allocator);
rclc_executor_add_subscription(&executor, &cmd_vel_sub, &cmd_vel_msg, &cmd_vel_callback, ON_NEW_DATA);
while (1) {
rclc_executor_spin_some(&executor, RCL_MS_TO_NS(10));
vTaskDelay(pdMS_TO_TICKS(10));
}
}
沒有留言:
張貼留言