通过ROS2使用YDLIDAR X2进行SLAM、自主导航方案选择
-
- 背景
-
- 一、方案总览(两种主流实现)
-
- 方案A:纯透传(最简,推荐入门)
- [方案B:Micro-ROS(标准ROS 2架构,适合完整导航)](#方案B:Micro-ROS(标准ROS 2架构,适合完整导航))
- 二、硬件连接(关键)
- 三、软件实现(方案A:透传+虚拟串口)
-
- [1. ESP32-S3 代码(Arduino/ESP-IDF)](#1. ESP32-S3 代码(Arduino/ESP-IDF))
- [2. PC端:虚拟串口桥接(Python)](#2. PC端:虚拟串口桥接(Python))
- [3. PC端:启动ydlidar_ros2_driver](#3. PC端:启动ydlidar_ros2_driver)
- 四、方案B:Micro-ROS(推荐完整导航)
-
- [1. ESP32-S3 端(Micro-ROS)](#1. ESP32-S3 端(Micro-ROS))
- [2. PC端:启动Micro-ROS Agent](#2. PC端:启动Micro-ROS Agent)
- 五、关键注意事项
- 六、ydlidar_ros2_driver、Micro-ROS、UDP透传关系
背景
ESP32S3的智能小车连接了YDLIDAR X2激光雷达,如何通过ROS2使用YDLIDAR X2进行SLAM、自主导航。
一、方案总览(两种主流实现)
方案A:纯透传(最简,推荐入门)
- ESP32-S3:UART读X2原始串口数据 → WiFi(UDP/TCP)透传原始字节流到PC
- PC :运行Python脚本创建虚拟串口 → ydlidar_ros2_driver直接读虚拟串口 → 输出/scan点云 → SLAM/Nav2
方案B:Micro-ROS(标准ROS 2架构,适合完整导航)
- ESP32-S3:UART读X2 → 解析成sensor_msgs/LaserScan → 通过Micro-ROS(XRCE-DDS)发布/scan到PC
- PC:运行Micro-ROS Agent → 自动转发为标准ROS 2话题 → 直接给SLAM/Nav2使用
二、硬件连接(关键)
YDLIDAR X2(端子线版)→ ESP32-S3(无需电平转换,3.3V兼容)
| YDLIDAR X2 | ESP32-S3 | 说明 |
|---|---|---|
| VCC | 5V | X2必须5V供电 |
| GND | GND | 共地 |
| TX | GPIO9 (UART2_RX) | 雷达发 → ESP收 |
| RX | GPIO8 (UART2_TX) | ESP发 → 雷达收(可选) |
- 串口参数:115200 8N1(8数据位、1停止位、无校验)
三、软件实现(方案A:透传+虚拟串口)
1. ESP32-S3 代码(Arduino/ESP-IDF)
- 功能:UART读X2原始数据 → WiFi UDP发送到PC
cpp
// 核心片段:UART读取 + WiFi UDP透传
#include <WiFi.h>
#include <HardwareSerial.h>
HardwareSerial LidarSerial(2); // UART2
const char* ssid = "你的WiFi";
const char* password = "密码";
const char* pcIP = "192.168.1.100"; // PC IP
const int pcPort = 8888;
WiFiUDP udp;
void setup() {
LidarSerial.begin(115200, SERIAL_8N1, 9, 8); // RX=9, TX=8
WiFi.begin(ssid, password);
udp.beginPacket(pcIP, pcPort);
}
void loop() {
if (LidarSerial.available()) {
byte buf[256];
int len = LidarSerial.readBytes(buf, sizeof(buf));
udp.write(buf, len);
udp.endPacket();
udp.beginPacket(pcIP, pcPort);
}
}
2. PC端:虚拟串口桥接(Python)
- 安装依赖:
pip install pyserial - 脚本:接收UDP数据 → 写入虚拟串口(/tmp/ydlidar_virtual)
python
import socket
import serial
import pty
import os
# 创建虚拟串口
master, slave = pty.openpty()
virtual_port = os.ttyname(slave)
print(f"虚拟串口: {virtual_port}")
# UDP监听
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("0.0.0.0", 8888))
while True:
data, _ = sock.recvfrom(1024)
os.write(master, data)
3. PC端:启动ydlidar_ros2_driver
- 修改配置:
ydlidar_ros2/params/ydlidar.yaml
yaml
ydlidar_node:
ros__parameters:
port: /dev/pts/xxx # 替换为上面的虚拟串口
baudrate: 115200
lidar_type: 1 # X2对应型号
frame_id: laser_frame
- 编译运行:
bash
colcon build
source install/setup.bash
ros2 launch ydlidar_ros2 ydlidar.launch.py
- 验证:
ros2 topic echo /scan应看到点云数据
四、方案B:Micro-ROS(推荐完整导航)
1. ESP32-S3 端(Micro-ROS)
- 依赖:
micro_ros_arduino库 - 代码:读取X2 → 解析为LaserScan → 发布/scan
cpp
#include <micro_ros_arduino.h>
#include <sensor_msgs/msg/laser_scan.h>
// ... 省略WiFi与UART初始化
sensor_msgs__msg__LaserScan scan_msg;
rcl_publisher_t scan_pub;
void setup() {
// 初始化Micro-ROS Agent(PC IP:8888)
set_microros_wifi_transports("PC_IP", 8888);
// 初始化LaserScan消息(角度、距离范围等)
// ... 省略X2数据解析逻辑
}
void loop() {
// 读取并填充scan_msg
rcl_publish(&scan_pub, &scan_msg, NULL);
delay(50);
}
2. PC端:启动Micro-ROS Agent
bash
docker run -it --rm --net=host microros/micro-ros-agent:humble udp4 --port 8888
- 直接订阅
/scan即可用于SLAM Toolbox与Nav2
五、关键注意事项
- 供电:X2必须5V供电,ESP32-S3 3.3V GPIO可直连TX/RX
- 时间同步:WiFi延迟会导致建图重影,建议ESP32带时间戳发布,PC用该时间戳
- 带宽:X2数据约10KB/s,WiFi UDP足够;Micro-ROS更高效
- 虚拟串口权限 :
sudo chmod 666 /dev/pts/xxx
六、ydlidar_ros2_driver、Micro-ROS、UDP透传关系
- ydlidar_ros2_driver :真正的雷达驱动,负责解析雷达协议、发指令、出 /scan。
- UDP 透传 :只是无线串口线,只传原始数据,不解析、不处理。
- Micro-ROS :是ESP32 直接发 ROS2 消息,自己当驱动,完全绕开官方驱动。
- ydlidar_ros2_driver
地位:唯一能真正读懂 YDLIDAR X2 协议的角色
- 给雷达发启动指令
- 解析雷达的二进制数据
- 输出 ROS2 标准
/scan - 必须从**串口(物理或虚拟)**读原始数据
- UDP 透传
地位:无线延长的串口线
- ESP32 只做一件事:
串口收到什么 → WiFi 原封不动发给 PC - 不解析、不处理、不知道雷达是什么
- 作用:让 PC 上的 ydlidar_ros2_driver 以为雷达是直连的
- Micro-ROS
地位:ESP32 自己变成"雷达驱动节点"
- ESP32 自己解析雷达协议
- 自己封装成
/scan消息 - 通过 WiFi 直接发给 PC
- PC 上的 micro-ros-agent 只负责转发消息
- 完全不需要 ydlidar_ros2_driver
该选哪个?
- 想最简单、稳定、不折腾 → UDP 透传 + ydlidar_ros2_driver
- 想玩高级架构、自己解析协议 → Micro-ROS
- 有线直连 → 直接用 ydlidar_ros2_driver