【ROS2】【ESP32S3纯透传方案】ESP32S3+WINDOWS+VMware+ROS2+YDLIDA X导航完整落地方案

【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 整体接线注意事项

  1. 所有组件共地,避免接地不良导致的信号干扰;
  2. 雷达供电优先选用独立 5V 电源,若与 ESP32 共用电源,需确保电源输出电流 ≥1A;
  3. 接线时避免线路交叉、拉扯,固定好杜邦线,防止小车运动时脱落;
  4. 雷达安装时,确保扫描方向朝向小车前方,后续可通过代码调整 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 远程建图

  1. 新开终端:
bash 复制代码
ros2 launch slam_toolbox online_async_launch.py
  1. 打开RVIZ可视化界面

在 RViz2 里添加:

Map(topic: /map)

LaserScan(topic: /scan)

TF

现在移动机器人 / 手持雷达走动,地图会自动生成

  1. 保存地图在当前目录
    确认 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)

都是在新终端中执行

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:

  1. 给机器人定初始位姿(关键!)
    点击上方 「2D Pose Estimate」
    在地图上点一下机器人当前位置
    拖动箭头朝向雷达前方
  2. 发送目标点
    点击上方 「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 代理)

七、注意事项(确保方案稳定落地)

  1. 电源稳定性是关键:雷达必须用 5V 稳定供电,电机用 7-12V 供电,避免共用电源导致的电压波动;
  2. WiFi 通信:确保 Ubuntu 和 ESP32 同网段,避免 WiFi 干扰(远离其他电子设备),建图/导航时尽量靠近路由器;
  3. 雷达安装:扫描方向朝向小车前方,安装高度适中(避免地面遮挡扫描),若安装方向相反,可修改代码中的 scan_msg.angle_minscan_msg.angle_max 互换;
  4. 地图保存:建图完成后,确保地图文件(my_car_map.pgmmy_car_map.yaml)保存在 Ubuntu 家目录,导航时脚本中的地图路径需与文件名一致;
  5. 安全操作:小车运动时,避免周围有障碍物或人员,远程控制时缓慢移动,防止小车碰撞损坏硬件。

八、参考链接

X2用户手册

https://oss.p.skytech.cn/2036899223840006144/714dab97c67cd3ebd494dd37b488d450.pdf
https://www.ydlidar.cn/download/category/user-manual

YDLidar-SDK

https://github.com/YDLIDAR/YDLidar-SDK/tree/master

YDLIDAR ROS2 Driver

https://github.com/YDLIDAR/ydlidar_ros2_driver

ROS2手册

https://docs.ros.org/en/humble/index.html

ydlidar X2 ubuntu 22.04调试记录

https://blog.csdn.net/qq_55437104/article/details/145790714

相关推荐
AxureMost2 小时前
MTools 0.0.12-beta 全能工具箱
windows·开源软件
天选硬件打工人3 小时前
第二十三篇:【硬件工程师筑基系列 5-2】PCB 设计核心基础 | 叠层设计、焊盘封装与 DFM 可制造性规范
单片机·嵌入式硬件·硬件架构·硬件工程·制造·基带工程
廷华电子4 小时前
STM32H743+AX58100学习板
stm32·嵌入式硬件·电机控制·ethercat·cia402
beyond阿亮4 小时前
OpenClaw在Windows上接入飞书完整指南
人工智能·windows·ai·openclaw
busideyang4 小时前
函数指针类型定义笔记
c语言·笔记·stm32·单片机·算法·嵌入式
大强同学6 小时前
MFCMouseEffect 鼠标可视化特效设置与操作教程
windows·鼠标手势
我的老子姓彭6 小时前
stm32串口hal库
stm32·单片机·嵌入式硬件
爱喝纯牛奶的柠檬6 小时前
【已验证】STM32F103的MPU6050应用一(驱动篇)
stm32·单片机·嵌入式硬件
是翔仔呐6 小时前
第10章 串口通信USART全解:轮询/中断/DMA三种收发模式与上位机通信实战
c语言·开发语言·stm32·单片机·嵌入式硬件·学习·gitee