【ESP32S3纯透传方案】ESP32S3+WINDOWS+VMware+ROS2+YDLIDA X导航完整落地方案
-
- 一、方案概述
- 二、核心软硬件清单(精准适配端子线雷达)
- 三、硬件接线(核心步骤,精准无误)
-
- [3.1 核心接线:YDLIDAR X2 ↔ ESP32-S3(端子线直连)](#3.1 核心接线:YDLIDAR X2 ↔ ESP32-S3(端子线直连))
- [3.2 YDLIDAR X2安装在小车的位置](#3.2 YDLIDAR X2安装在小车的位置)
- [3.3 电机接线(ESP32-S3 ↔ 电机驱动模块)](#3.3 电机接线(ESP32-S3 ↔ 电机驱动模块))
- [3.4 整体接线注意事项](#3.4 整体接线注意事项)
- 四、软件环境配置
-
- [4.1 esp32-s3纯透传代码,烧录到板子里](#4.1 esp32-s3纯透传代码,烧录到板子里)
- [4.2 PC安装依赖:pip install pyserial](#4.2 PC安装依赖:pip install pyserial)
- [4.3 修改驱动力x2.yaml文件里的串口](#4.3 修改驱动力x2.yaml文件里的串口)
- [4.4 启动YDLidar X2](#4.4 启动YDLidar X2)
- [4.5 启动RVIZ](#4.5 启动RVIZ)
- [4.6 发布必须的 TF(雷达 ↔ 机身)](#4.6 发布必须的 TF(雷达 ↔ 机身))
- 五、SLAM建图和导航
-
- [5.1 创建ROS2 控制小车转发节点](#5.1 创建ROS2 控制小车转发节点)
- [5.1 SLAM 远程建图](#5.1 SLAM 远程建图)
- [5.2 启动自主导航 Nav2](#5.2 启动自主导航 Nav2)
- [5.3 在 RViz2 点 2D Goal 实现自动导航](#5.3 在 RViz2 点 2D Goal 实现自动导航)
- [5.4 一键启动脚本](#5.4 一键启动脚本)
- 六、常见问题排查
- 七、注意事项(确保方案稳定落地)
- 八、参考链接
一、方案概述
参考发布的另外一篇文章https://youyouhome.blog.csdn.net/article/details/159570433?spm=1001.2014.3001.5502,核心就是:
ESP32-S3:UART读X2原始串口数据 → WiFi(UDP/TCP)透传原始字节流到PC
PC:运行Python脚本创建虚拟串口 → ydlidar_ros2_driver直接读虚拟串口 → 输出/scan点云 → SLAM/Nav2
二、核心软硬件清单(精准适配端子线雷达)
| 类别 | 组件名称 | 规格/型号 | 作用 | 关键注意事项 |
|---|---|---|---|---|
| 车载端 | ESP32-S3 开发板 | 任意型号(≥4MB Flash) | 小车主控,驱动雷达、电机,无线传输 ROS2 数据 | 需引出 UART2(GPIO8=TX2、GPIO9=RX2) |
| 车载端 | YDLIDAR X2 激光雷达 | 端子线版(TX/RX/GND/5V) | 环境感知,采集激光点云数据 | 直出端子线,无需 USB 转串口模块,必须 5V 供电 |
| 车载端 | 电机驱动模块 | DRV8833(推荐)/ L298N | 驱动直流电机,接收 ESP32 控制信号 | 适配 ESP32 GPIO 控制,供电 7-12V(给电机) |
| 车载端 | 直流减速电机 | 带编码器(推荐) | 小车动力来源,编码器可提供里程计数据(导航优化) | 无编码器可正常导航,精度略低 |
| 车载端 | 电源系统 | 5V 2A 电源(雷达+ESP32)、7-12V 电源(电机) | 为车载所有组件供电 | 雷达严禁 3.3V 供电,避免数据异常或损坏 |
| 车载端 | 小车底盘 | 两轮差分底盘 | 机械载体,需测量轮距/轴距(导航参数优化可选) | 确保电机安装牢固,运动顺畅 |
| 远程端 | 电脑 | Windows 系统(支持 VMware) | 运行虚拟机、ROS2 导航相关软件 | 需开启 CPU 虚拟化(BIOS 中设置) |
| 远程端 | 虚拟机软件 | VMware Workstation 16/17 | 安装 Ubuntu 系统,实现 ROS2 运行环境 | 支持 USB 3.0(调试 ESP32 时用)、桥接网络 |
| 远程端 | 操作系统 | Ubuntu 22.04 LTS 桌面版 | ROS2 Humble 官方适配系统 | 分配 ≥4G 内存、≥40G 硬盘,确保流畅运行 |
| 辅助配件 | 杜邦线 | 公对公、公对母 | 连接 ESP32 与雷达、电机驱动 | 建议选用优质杜邦线,避免接触不良 |
| 辅助配件 | WiFi 网络 | 家用/实验室路由器 | ESP32 与 Ubuntu 无线通信载体 | 确保两者处于同一网段(如 192.168.1.x) |
三、硬件接线(核心步骤,精准无误)
3.1 核心接线:YDLIDAR X2 ↔ ESP32-S3(端子线直连)
YDLIDAR X2 端子线为 4 芯(VCC/TX/RX/GND),ESP32-S3 的 UART2(GPIO8=TX2、GPIO9=RX2)直接对接,无需电平转换(X2 支持 3.3V/5V 串口通信,ESP32-S3 GPIO 为 3.3V)。
| YDLIDAR X2 端子线(颜色参考) | ESP32-S3 引脚 | 功能 | 关键提醒 |
|---|---|---|---|
| VCC(红) | 5V | 雷达供电 | 必须接 5V!3.3V 会导致雷达供电不足、数据丢失 |
| GND(黑) | GND | 共地 | 必须可靠连接,否则串口乱码、雷达无法启动 |
| TX(黄) | RX2(GPIO9) | 雷达 → ESP32 传输扫描数据 | 交叉对接(雷达 TX 对应 ESP32 RX) |
| RX(绿) | TX2(GPIO8) | ESP32 → 雷达传输控制指令 | 交叉对接(ESP32 TX 对应雷达 RX) |
3.2 YDLIDAR X2安装在小车的位置
把 X2 的零位(电机一头的方向就是正前方)对准小车前进方向
3.3 电机接线(ESP32-S3 ↔ 电机驱动模块)
沿用原有电机接线逻辑,仅明确引脚对应关系(可根据自身硬件修改代码中的引脚定义),确保电机正反转、速度控制正常。
| 电机驱动模块接口 | ESP32-S3 引脚 | 功能 |
|---|---|---|
| L_PWM(左轮速度) | GPIO10 | 控制左轮转速(PWM 信号) |
| L_DIR(左轮方向) | GPIO11 | 控制左轮正反转 |
| R_PWM(右轮速度) | GPIO12 | 控制右轮转速(PWM 信号) |
| R_DIR(右轮方向) | GPIO13 | 控制右轮正反转 |
| 电机驱动供电 | 7-12V 电源 | 为电机提供动力(与 ESP32/雷达供电分离) |
| 电机驱动 GND | GND | 与 ESP32、雷达共地 |
3.4 整体接线注意事项
- 所有组件共地,避免接地不良导致的信号干扰;
- 雷达供电优先选用独立 5V 电源,若与 ESP32 共用电源,需确保电源输出电流 ≥1A;
- 接线时避免线路交叉、拉扯,固定好杜邦线,防止小车运动时脱落;
- 雷达安装时,确保扫描方向朝向小车前方,后续可通过代码调整
inverted参数修正安装方向。
四、软件环境配置
参考链接https://blog.csdn.net/m0_60688978/article/details/158729488准备好操作系统、ROS2、YDLidar SDK、YDLidar Driver的安装、创建好ros空间、连接好雷达设备。
4.1 esp32-s3纯透传代码,烧录到板子里
见代码https://gitee.com/likexiang/like-code/blob/master/ESP32-S3-CAM/ROS2/esp32-carControll.ino
4.2 PC安装依赖: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)
4.3 修改驱动力x2.yaml文件里的串口
src/ydlidar_ros2_driver/params/X2.yaml
bash
ydlidar_ros2_driver_node:
ros__parameters:
port: /dev/xxxx
frame_id: laser_frame
...
4.4 启动YDLidar X2
指定配置文件连接
bash
ros2 launch ydlidar_ros2_driver ydlidar_launch.py params_file:=src/ydlidar_ros2_driver/params/X2.yaml
或者
bash
ros2 launch ydlidar_ros2_driver ydlidar_launch.py (默认使用的是params/ydlidar.yaml)
需要修改ydlidar_launch.py内在param_file里修改为X2.yaml启动
4.5 启动RVIZ
bash
ros2 launch ydlidar_ros2_driver ydlidar_launch_view.py
观察 Ubuntu 的 RViz 界面,会出现雷达点云(红色/蓝色点,代表周围环境),说明无线通信正常、雷达工作正常。
4.6 发布必须的 TF(雷达 ↔ 机身)
bash
ros2 run tf2_ros static_transform_publisher 0 0 0.15 0 0 0 base_link laser_link
# 0.15 = 雷达高度 15cm,可不改。在前轮两个驱动轮的轴心连线中心点到雷达旋转中心的距离
五、SLAM建图和导航
5.1 创建ROS2 控制小车转发节点
创建一个python文件,ros2_serial_bridge.py。主要是订阅 ROS2 导航速度指令 /cmd_vel,然后转为 UDP 发给 ESP32让小车自动前进、左转、右转。
python
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
import socket
import threading
import time
# ESP32 的 IP地址(烧录时串口监视器看)
ESP32_IP = "192.168.1.XX"
ESP32_PORT = 8889
# ===================== 【关键优化】普通电机专用 =====================
EXECUTE_TIME = 0.25 # 每次指令只执行 0.25 秒(250ms)
# 如果你车反应慢 → 调到 0.3
# 如果你车太快 → 调到 0.15
# ==================================================================
class CmdVelToUDP(Node):
def __init__(self):
super().__init__('cmdvel_to_udp')
self.sub = self.create_subscription(Twist, "/cmd_vel", self.callback, 10)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.last_cmd = "stop"
self.last_time = 0
self.get_logger().info("✅ ROS2 cmd_vel → ESP32 转发启动(普通电机优化版)")
self.get_logger().info(f"🎯 目标 ESP32: {ESP32_IP}:{ESP32_PORT}")
self.get_logger().info(f"⏱ 指令执行时长: {EXECUTE_TIME}s")
def callback(self, msg):
linear = msg.linear.x
angular = msg.angular.z
current_cmd = "stop"
# 解析速度指令
if linear > 0.1:
current_cmd = "forward"
elif linear < -0.1:
current_cmd = "backward"
elif angular > 0.2:
current_cmd = "left"
elif angular < -0.2:
current_cmd = "right"
else:
current_cmd = "stop"
# 防抖:指令变化才发送
now = time.time()
if current_cmd != self.last_cmd or (now - self.last_time > EXECUTE_TIME):
self.send_cmd(current_cmd)
self.last_cmd = current_cmd
self.last_time = now
# 【核心优化】执行固定时间后自动停止
if current_cmd != "stop":
threading.Timer(EXECUTE_TIME, self.stop_motor).start()
def send_cmd(self, cmd):
try:
self.sock.sendto(cmd.encode(), (ESP32_IP, ESP32_PORT))
self.get_logger().info(f"➡️ {cmd}")
except:
pass
def stop_motor(self):
self.send_cmd("stop")
def main():
rclpy.init()
node = CmdVelToUDP()
rclpy.spin(node)
if __name__ == '__main__':
main()
启动这个python文件
source /opt/ros/humble/setup.bash
python ros2_serial_bridge.py
5.1 SLAM 远程建图
- 新开终端:
bash
ros2 launch slam_toolbox online_async_launch.py
- 打开RVIZ可视化界面
在 RViz2 里添加:
Map(topic: /map)
LaserScan(topic: /scan)
TF
现在移动机器人 / 手持雷达走动,地图会自动生成
- 保存地图在当前目录
确认 RViz 中已显示雷达点云;新开一个 Ubuntu 终端,启动键盘控制节点,远程控制小车移动建图:
bash
source /opt/ros/humble/setup.bash
ros2 run teleop_twist_keyboard teleop_twist_keyboard
按终端提示,用键盘控制小车:
w:前进,s:后退,a:左转,d:右转,x:停止;
控制小车缓慢移动,覆盖需要导航的区域(如房间、走廊),确保地图完整,避免遗漏角落;
建图完成后,保存地图(新开终端,执行以下命令):
bash
ros2 run nav2_map_server map_saver_cli -f my_house
会在当前目录生成:
my_house.pgm
my_house.yaml
关闭 SLAM 终端(Ctrl+C)
5.2 启动自主导航 Nav2
都是在新终端中执行
bash
#启动导航 + 加载地图
ros2 launch nav2_bringup bringup_launch.py map:=my_house.yaml use_sim_time:=false
#启动导航行为服务器
ros2 launch nav2_bringup navigation_launch.py use_sim_time:=false
参数优化,适配普通的减速电机
nav2_params.yaml
yaml
bt_xml_filename: "navigate_w_replanning_and_recovery.xml"
plugin_lib_names:
- nav2_compute_path_to_pose_action_bt_node
- nav2_follow_path_action_bt_node
- nav2_back_up_action_bt_node
- nav2_wait_action_bt_node
- nav2_spin_action_bt_node
- nav2_clear_costmap_service_bt_node
- nav2_is_stuck_condition_bt_node
- nav2_goal_reached_condition_bt_node
- nav2_initial_pose_received_condition_bt_node
- nav2_goal_updated_condition_bt_node
# 控制器(核心:差速控制 + 无编码器适配)
controller_server:
ros__parameters:
use_sim_time: false
controller_frequency: 20.0
min_x_velocity_threshold: 0.05
min_y_velocity_threshold: 0.0
min_theta_velocity_threshold: 0.05
# 小车速度限制(普通电机一定要限制低!)
max_vel_x: 0.22
min_vel_x: -0.12
max_vel_y: 0.0
max_vel_theta: 0.55
min_vel_theta: -0.55
# 加速度限制(关键!防止打滑、冲太快)
acc_lim_x: 0.25
acc_lim_y: 0.0
acc_lim_theta: 0.35
decel_lim_x: -0.35
decel_lim_y: 0.0
decel_lim_theta: -0.4
# 无编码器必开:平滑减速、柔和控制
xy_goal_tolerance: 0.12
yaw_goal_tolerance: 0.18
rotate_to_goal_heading: true
# DWB 核心参数(适配差速小车)
critics: ["RotateToGoal", "Oscillation", "BaseObstacle", "PathAlign", "PathDist", "GoalAlign", "GoalDist"]
scale_rotate_to_goal: 3.2
scale_path_align: 0.5
scale_path_dist: 0.4
scale_goal_align: 0.6
scale_goal_dist: 0.5
scale_oscillation: 1.2
scale_obstacle: 1.0
# 禁止剧烈抖动、频繁转向
oscillation_timeout: 2.0
oscillation_distance: 0.15
oscillation_angle: 0.4
# 规划器
planner_server:
ros__parameters:
use_sim_time: false
planner_frequency: 1.0
expected_planner_frequency: 1.0
planner: "SmacPlanner"
smooth_path: true
tolerance: 0.3
# 代价地图(雷达避障)
global_costmap:
ros__parameters:
use_sim_time: false
global_frame: map
robot_base_frame: base_link
transform_tolerance: 0.5
update_frequency: 2.0
publish_frequency: 1.0
static_map: true
rolling_window: false
footprint: "[[0.12, 0.11], [0.12, -0.11], [-0.15, -0.11], [-0.15, 0.11]]"
inflation_radius: 0.45
cost_scaling_factor: 8.0
local_costmap:
ros__parameters:
use_sim_time: false
global_frame: odom
robot_base_frame: base_link
transform_tolerance: 0.5
update_frequency: 5.0
publish_frequency: 2.0
static_map: false
rolling_window: true
rolling_window_radius: 1.2
footprint: "[[0.12, 0.11], [0.12, -0.11], [-0.15, -0.11], [-0.15, 0.11]]"
inflation_radius: 0.35
cost_scaling_factor: 10.0
# 行为树
behavior_server:
ros__parameters:
use_sim_time: false
action_server_result_timeout: 10.0
spin_vel: 0.4
spin_dist: 0.0
wait_time: 1.0
backup_vel: -0.1
backup_dist: 0.15
启动导航时指定这个配置文件
bash
ros2 launch nav2_bringup bringup_launch.py \
map:=my_house.yaml \
use_sim_time:=false \
params_file:=/home/你的用户名/nav2_params.yaml
5.3 在 RViz2 点 2D Goal 实现自动导航
回到 RViz2:
- 给机器人定初始位姿(关键!)
点击上方 「2D Pose Estimate」
在地图上点一下机器人当前位置
拖动箭头朝向雷达前方- 发送目标点
点击上方 「Nav2 Goal」 / 「2D Goal」
在地图上点一个目标点
拖动箭头设定朝向
5.4 一键启动脚本
bash
#!/bin/bash
# 自动驾驶小车 全套一键启动脚本
# 功能:虚拟串口 + 雷达驱动 + TF + SLAM + 导航 + ROS2控制桥 + RViz
# 适配:ESP32-S3 + YDLIDAR X2 + 无编码减速电机 + ROS2 Humble
echo "============================================="
echo " 自动驾驶小车 一键启动脚本"
echo "============================================="
# 1. 加载 ROS2 基础环境(必须!)
source /opt/ros/humble/setup.bash
# 2. 加载你的工作空间(必须!)
source ~/ros2_ws/install/setup.bash
echo "✅ 环境加载完成,开始启动所有模块..."
sleep 1
# ==============================================
# 打开多个终端,自动依次启动
# ==============================================
# 1. 虚拟串口(UDP → 虚拟串口)
gnome-terminal --tab --title="1-虚拟串口" -- bash -c "
echo '正在启动: 虚拟串口转发'
python3 ~/udp_to_virtual_serial.py
exec bash
"
sleep 3
# 2. 雷达驱动 YDLIDAR
gnome-terminal --tab --title="2-雷达驱动" -- bash -c "
echo '正在启动: 雷达驱动'
ros2 launch ydlidar_ros2_driver ydlidar_launch.py params_file:=src/ydlidar_ros2_driver/params/X2.yaml
exec bash
"
sleep 4
# 3. TF 坐标变换(雷达 ↔ 小车)
gnome-terminal --tab --title="3-TF坐标" -- bash -c "
echo '正在启动: TF坐标变换'
ros2 run tf2_ros static_transform_publisher 0 0 0.15 0 0 0 base_link laser_link
exec bash
"
sleep 1
# 4. SLAM 建图
gnome-terminal --tab --title="4-SLAM建图" -- bash -c "
echo '正在启动: SLAM 建图'
ros2 launch slam_toolbox online_async_launch.py
exec bash
"
sleep 4
# 5. NAV2 导航(带无编码电机优化参数)
gnome-terminal --tab --title="5-NAV2导航" -- bash -c "
echo '正在启动: NAV2 导航'
ros2 launch nav2_bringup bringup_launch.py map:=my_house.yaml params_file:=~/nav2_params.yaml use_sim_time:=false
exec bash
"
sleep 5
# 6. ROS2 控制桥(/cmd_vel → ESP32)
gnome-terminal --tab --title="6-ROS2控制桥" -- bash -c "
echo '正在启动: ROS2 控制桥'
python3 ~/ros2_serial_bridge.py
exec bash
"
sleep 1
# 7. RViz 可视化
gnome-terminal --tab --title="7-RViz可视化" -- bash -c "
echo '正在启动: RViz 可视化'
rviz2
exec bash
"
echo ""
echo "============================================="
echo " 所有模块启动完成!"
echo " 请在 RViz 中设置 2D Pose Estimate"
echo " 然后点 2D Goal 即可实现自动导航"
echo "============================================="
六、常见问题排查
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| SLAM 建图模糊、丢点 | 1. 雷达安装不牢固,小车运动时晃动;2. 雷达扫描频率过高;3. WiFi 通信不稳定 | 1. 固定好雷达,避免晃动;2. 将代码中的 SCAN_FREQ 改为 5-7Hz;3. 靠近路由器,减少 WiFi 干扰 |
| 导航路径规划失败 | 1. 小车初始位姿标定错误;2. 地图保存失败;3. TF 变换参数错误;4. 无里程计数据(可选) | 1. 重新标定小车初始位姿(2D Pose Estimate);2. 重新保存地图,确保地图文件存在;3. 调整 TF 变换的 x/y/z 参数(匹配雷达实际安装位置);4. 若有编码器,添加里程计发布功能 |
| Ubuntu 无法接收 ESP32 数据 | 1. Ubuntu 防火墙未关闭;2. AGENT_IP 设置错误;3. 端口冲突 | 1. 执行 sudo ufw disable 关闭防火墙;2. 用 ifconfig 重新查看 Ubuntu IP,修改 ESP32 代码;3. 确保端口 8888 未被占用(关闭其他 MicroROS 代理) |
七、注意事项(确保方案稳定落地)
- 电源稳定性是关键:雷达必须用 5V 稳定供电,电机用 7-12V 供电,避免共用电源导致的电压波动;
- WiFi 通信:确保 Ubuntu 和 ESP32 同网段,避免 WiFi 干扰(远离其他电子设备),建图/导航时尽量靠近路由器;
- 雷达安装:扫描方向朝向小车前方,安装高度适中(避免地面遮挡扫描),若安装方向相反,可修改代码中的
scan_msg.angle_min和scan_msg.angle_max互换; - 地图保存:建图完成后,确保地图文件(
my_car_map.pgm和my_car_map.yaml)保存在 Ubuntu 家目录,导航时脚本中的地图路径需与文件名一致; - 安全操作:小车运动时,避免周围有障碍物或人员,远程控制时缓慢移动,防止小车碰撞损坏硬件。
八、参考链接
X2用户手册
https://oss.p.skytech.cn/2036899223840006144/714dab97c67cd3ebd494dd37b488d450.pdf
https://www.ydlidar.cn/download/category/user-manual
YDLidar-SDK
YDLIDAR ROS2 Driver
ROS2手册
ydlidar X2 ubuntu 22.04调试记录