跳到主要内容

Gazebo 仿真开发

Gazebo 仿真概述

本教程使用镜像内置的 House 场景。Gazebo 负责模拟 UGV Rover、环境和传感器数据,RViz 用于查看地图、定位和导航结果。预配置镜像已经包含 Ubuntu 22.04、ROS 2 Humble、Gazebo Classic 11、UGV ROS 2 工作空间和运行依赖。

提示

当前预配置镜像和 UGV 仿真功能基于 Gazebo Classic 11。界面顶部显示的生命周期提示不影响本教程中的仿真操作;不要在本教程流程中自行替换为新版 Gazebo。

首次使用快速开始

首次使用时,只需导入镜像、配置 MobaXterm Gazebo Session,并通过 WSLg 启动仿真。

检查或启用 WSL2

在 Windows PowerShell 中执行:

wsl --status

如果命令正常显示 WSL 状态,且默认版本为 2,进入“下载并导入预配置镜像”。只有命令报错或 WSL2 尚未启用时,才执行以下步骤。

WSL2 尚未启用时展开
  1. 在 Windows "开始" 菜单中右键单击 PowerShell,选择 "以管理员身份运行"。

    以管理员身份打开 Windows PowerShell

  2. 如果 WSL 相关 Windows 可选组件尚未启用,终端可能显示 Wsl/WSL_E_WSL_OPTIONAL_COMPONENT_REQUIRED

    WSL 可选组件未启用提示

  3. 在管理员 PowerShell 中启用 "适用于 Linux 的 Windows 子系统":

    dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
  4. 启用 "虚拟机平台":

    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

    在 PowerShell 中启用 WSL2 相关功能

  5. 也可以打开 "控制面板" > "程序" > "启用或关闭 Windows 功能",勾选 "适用于 Linux 的 Windows 子系统" 和 "虚拟机平台"。PowerShell 命令和图形界面选择一种方式即可。

    在 Windows 功能中启用 WSL2

  6. 重启 Windows。

  7. 重启后,以管理员身份打开 Windows PowerShell,更新 WSL 并将默认版本设为 WSL2:

    wsl --update
    wsl --set-default-version 2
提示

预配置镜像自身已经包含 Ubuntu 22.04,因此不需要另行安装 Ubuntu 发行版。

下载并导入预配置镜像

下载 UGV Gazebo Humble 预配置镜像,提取码为 WXDZ

当前正式镜像为 UGV-Gazebo-Humble-20260805-v1.1.tar,发布于 2026-08-05,已经包含 Windows 浏览器实体手柄桥接功能。导入后不需要执行 git pullcolcon build,也不需要安装额外的 apt、pip 或 npm 依赖。

首次安装

在 Windows PowerShell 中进入镜像下载目录,设置导入变量并检查 Hash。$InstallPath 是导入后 WSL2 运行数据的保存位置,必须使用新建或空目录,不得复用旧发行版的数据目录,也不得与其它发行版共用目录。$DistroName 不得与已有发行版重名。

$DistroName = "UGV-Gazebo-Humble"
$InstallPath = "C:\WSL\UGV-Gazebo-Humble"
$ImagePath = (Resolve-Path ".\UGV-Gazebo-Humble-20260805-v1.1.tar").Path

Get-FileHash $ImagePath -Algorithm SHA256

PowerShell 输出的 Hash 可用于确认文件下载完整。当前未提供新镜像的固定 SHA256 值,暂不列出固定校验值。

备注

SHA256 哈希值相当于镜像文件的数字指纹,用于检查文件是否下载完整、是否被意外修改。

注意

如果后续获得新镜像的 SHA256,请先完成校验,再继续导入。下载不完整或文件损坏时,不要继续导入。

确认 Hash 一致后,在同一 Windows PowerShell 中执行导入:

New-Item -ItemType Directory -Force $InstallPath
wsl --import $DistroName $InstallPath $ImagePath --version 2

wsl --list --verbose

输出中应包含:

UGV-Gazebo-Humble Stopped 2

WSL2 发行版列表中的 UGV-Gazebo-Humble

开发者:替换已有旧版

替换旧版前,先将地图、数据库和个人文件复制到 Windows 中的其它目录。在 Windows PowerShell 中终止发行版并导出完整备份:

wsl --terminate UGV-Gazebo-Humble

wsl --export `
UGV-Gazebo-Humble `
.\UGV-Gazebo-Humble-before-update.tar

确认备份文件存在且保存位置正确后,再执行注销。

注销旧发行版

以下命令会永久删除 UGV-Gazebo-Humble 发行版中的全部数据。只有在地图、数据库和个人文件已经备份后才能执行:

wsl --unregister UGV-Gazebo-Humble

注销完成后,按照“首次安装”流程重新导入镜像。重新导入时使用新建或空的 $InstallPath;如果原目录仍包含文件,请修改 $InstallPath,使用另一个空目录。本文不提供自动删除目录的命令。

配置 Gazebo WSLg Session

先完成 ROS 2 教程:安装 MobaXterm,然后在 MobaXterm 中为 Gazebo 创建专用 Shell Session。

  1. 打开 MobaXterm,点击 SessionSession 用于新建和保存一个终端会话。

  2. 选择 Shell,不要选择 WSL。这里通过 Windows PowerShell 启动 WSL2,不使用 MobaXterm 的原生 WSL 会话。

  3. Terminal shell 选择 Windows PowerShell。PowerShell 负责执行启动 WSL2 的命令。

  4. Startup directory 留空。进入 WSL2 后,命令中的 --cd /home/ag 会设置 Linux 工作目录。

  5. 在 Windows PowerShell 中确认镜像导入后的 WSL2 发行版名称:

    wsl -l -v

    查看列表中的 NAMEVERSION。选择 VERSION2 的目标发行版,并记下它的 NAME。命令中的 UGV-Gazebo-Humble 只是当前镜像的示例名称;如果列表中的名称不同,请将 -d 后面的名称替换为实际名称。这里填写的是 WSL2 发行版名称,不是 .tar 镜像文件的保存路径。

  6. Advanced Shell settings 的启动命令中按以下格式填写一整行:

    & "$env:WINDIR\System32\wsl.exe" -d <WSL2发行版名称> -u <Linux用户名> --cd /home/<Linux用户目录>

    将尖括号中的内容替换为实际值,不要直接复制尖括号。<WSL2发行版名称> 使用上一步 wsl -l -v 查到的 NAME<Linux用户名> 使用镜像中的登录用户名,<Linux用户目录> 使用对应的 Home 目录名称。

    当前镜像的示例命令如下:

    & "$env:WINDIR\System32\wsl.exe" -d UGV-Gazebo-Humble -u ag --cd /home/ag

    其中,& 用于让 PowerShell 执行程序,$env:WINDIR\System32\wsl.exe 是 Windows 的 WSL2 启动程序,-d 指定 WSL2 发行版,-u ag 指定登录用户,--cd /home/ag 指定进入后的 Linux 目录。当前镜像默认使用用户 ag;如果镜像中的用户名不同,请同时修改 -u 后的用户名和 --cd 后对应的用户目录。

    MobaXterm Shell、Windows PowerShell 和启动命令设置

  7. Execute macro at session start 保持 <none>,表示不额外执行宏命令。

  8. Terminal charset 选择 UTF-8 (Unicode),避免终端文字显示乱码。

    MobaXterm Terminal charset 设置

  9. Terminal type 保持 xterm,用于保持常用终端程序的兼容性。

  10. 在 Bookmark settings 中将 Session name 设置为 UGV-Gazebo-Humble-WSLg,用于保存和识别该会话;Start session in 选择 Normal tab,表示在普通标签页中打开;Lock terminal title 可保持勾选,用于固定标签页标题。

MobaXterm Bookmark 设置

  1. 保存 Session。
  2. 双击保存的 UGV-Gazebo-Humble-WSLg Session 进入 WSL2。需要多个终端时,重复双击该 Session,每次会打开新的 MobaXterm 标签页。
  3. 在启动的标签页中执行环境检查:
pwd
echo "DISPLAY=$DISPLAY"
echo "WAYLAND_DISPLAY=$WAYLAND_DISPLAY"
echo "XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR"
test -d /mnt/wslg && echo "WSLg_OK"
  1. 预期结果如下:
/home/ag
DISPLAY=:0
WAYLAND_DISPLAY=wayland-0
XDG_RUNTIME_DIR=/run/user/1000
WSLg_OK

MobaXterm WSLg 环境检查结果

注意

Gazebo 使用 Windows WSLg 显示图形窗口,不需要启动 VcXsrv、XLaunch 或 MobaXterm X Server;MobaXterm 右上角的 X Server 可保持关闭。不要使用 MobaXterm 原生 WSL Session,也不要手动修改 DISPLAY

打开 UGV 仿真终端

  1. 打开 MobaXterm,双击左侧保存的 UGV-Gazebo-Humble-WSLg Session。
  2. 启动后进入 /home/ag。需要第二、第三个终端时,再次双击相同 Session,分别用于 Gazebo、browser gamepad bridge、topic 检查、SLAM、Nav2 或 RTAB-Map。

启动 UGV Gazebo 仿真

预配置镜像已经包含 use_vcxsrv_gazebo.sh。该脚本现在只负责加载 Gazebo 模型和场景资源路径,不配置 Windows 主机 IP 或 DISPLAY;图形窗口由 WSLg 提供。

在 UGV-Gazebo-Humble 终端中执行:

cd /home/ag/ws/ugv_ws
unset ROS_DOMAIN_ID
source /opt/ros/humble/setup.bash
source install/setup.bash
source use_vcxsrv_gazebo.sh
export UGV_MODEL=ugv_rover

ros2 launch ugv_gazebo bringup.launch.py

source /opt/ros/humble/setup.bash 加载 ROS 2 Humble,source install/setup.bash 加载 UGV 工作空间,source use_vcxsrv_gazebo.sh 加载镜像内置 Gazebo 模型和场景资源路径,UGV_MODEL=ugv_rover 选择 UGV Rover 模型。该脚本不再配置或覆盖 DISPLAY,图形显示由 WSLg 提供。

运行结果:

  • Gazebo 窗口显示在 Windows 桌面;
  • House 场景加载完成;
  • UGV Rover 模型出现在场景中;
  • 启动终端依次显示 Waiting for service /spawn_entity, timeout = 120Calling service /spawn_entitySuccessfully spawned entity [ugv_rover]
提示

冷启动时,Gazebo 服务初始化可能需要较长时间,120 秒内完成启动均属正常。在终端明确显示失败前,不要重复启动第二个 Gazebo。ALSA 音频设备错误不影响仿真;Gazebo Classic 窗口顶部的生命周期结束提示也不表示启动失败。

Gazebo House 场景和 UGV Rover 模型

Gazebo 窗口和 UGV Rover 模型正常显示后,首次配置已经完成。需要继续核对镜像、工作空间和 ROS 2 数据时,再执行下一节的可选检查。

展开可选检查

检查镜像与工作空间

在新的 UGV-Gazebo-Humble 终端中执行:

cd ~/ws/ugv_ws
source /opt/ros/humble/setup.bash
source install/setup.bash

whoami
echo "$HOME"
echo "$ROS_DISTRO"
gazebo --version
ros2 pkg prefix ugv_gazebo

test -d ~/ws/ugv_ws && echo "ugv_ws exists"
test -f ~/ws/ugv_ws/install/setup.bash && echo "workspace installed"

输出依次包含 ag/home/aghumble、Gazebo 11.10.2、/home/ag/ws/ugv_ws/install/ugv_gazebougv_ws existsworkspace installed

UGV-Gazebo-Humble 镜像环境检查结果

检查图形环境

在同一个终端中执行:

echo "$DISPLAY"
echo "$WAYLAND_DISPLAY"
echo "$XDG_RUNTIME_DIR"
test -d /mnt/wslg && echo "WSLg_OK"
echo "$GAZEBO_MODEL_PATH"
echo "$GAZEBO_RESOURCE_PATH"

预期 DISPLAY:0WAYLAND_DISPLAYwayland-0XDG_RUNTIME_DIR/run/user/1000,并输出 WSLg_OKGAZEBO_MODEL_PATH 应包含 ugv_gazebomodels 目录,GAZEBO_RESOURCE_PATH 应包含 ugv_gazeboworlds 目录和 /usr/share/gazebo-11。这些命令用于启动成功后的环境检查,不是创建或修复脚本的步骤。

检查 ROS 2 节点和 topic

备注

UGV Gazebo 启动入口会同时启动多个进程:gzserver 负责物理与传感器仿真,gzclient 显示 Gazebo 场景,spawn_entity.py 将 UGV Rover 模型加入仿真世界,robot_state_publisher 发布机器人 TF。

保持 Gazebo 启动终端运行,在新的 UGV-Gazebo-Humble 终端中执行:

cd ~/ws/ugv_ws
source /opt/ros/humble/setup.bash
source install/setup.bash

ros2 node list
ros2 topic list
ros2 service list

timeout 5 ros2 topic hz /clock
timeout 5 ros2 topic hz /scan

话题列表中应出现 /clock/tf/tf_static/odom/scan/cmd_vel 等接口,/clock/scan 持续更新。timeout 5 会在 5 秒后自动结束命令;如果使用不带 timeoutros2 topic hz,按 Ctrl + C 停止查看。

日常启动

首次配置完成后,后续启动 Gazebo 只需执行以下步骤:

  1. 打开 MobaXterm,双击保存的 UGV-Gazebo-Humble-WSLg Session。

  2. 需要多个终端时,再次双击相同 Session,打开新的 MobaXterm 标签页。

  3. 在 Gazebo 标签页中执行:

    cd /home/ag/ws/ugv_ws
    unset ROS_DOMAIN_ID
    source /opt/ros/humble/setup.bash
    source install/setup.bash
    source use_vcxsrv_gazebo.sh
    export UGV_MODEL=ugv_rover

    ros2 launch ugv_gazebo bringup.launch.py

键盘与手柄控制

本节用于在 Gazebo 中复现键盘控制和 TGZ-850M 实体手柄控制。同一时间只运行一种手动控制。

使用键盘控制

  1. 保持 Gazebo 运行,另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 run ugv_tools keyboard_ctrl
  2. 保持键盘控制终端处于活动状态,按以下按键低速控制 UGV Rover:

    按键动作
    I前进
    ,后退
    J左转
    L右转
    K 或空格停止

    Gazebo 中的 UGV Rover 应按照按键方向移动。每次短距离移动后按 K 或空格,确认车辆停止后再继续。

    键盘控制终端与 Gazebo 中的 UGV Rover 运动状态

  3. 停车后在键盘控制终端按 Ctrl + C,退出键盘控制。

按键后 UGV Rover 不运动时检查 topic

保持键盘控制终端运行,另开一个 UGV-Gazebo-Humble 图形化终端并执行:

cd ~/ws/ugv_ws
source /opt/ros/humble/setup.bash
source install/setup.bash

ros2 topic info /cmd_vel
ros2 topic echo /cmd_vel

回到键盘控制终端操作按键,检查 /cmd_vel 是否随输入变化。检查完成后按 Ctrl + C 停止 topic 输出。

使用手柄控制

本节使用 UGV 配套的 TGZ-850M 2.4 GHz 实体手柄。USB 接收器由 Windows 管理,网页通过 Windows Gamepad API 读取实体手柄,再由预配置镜像中的 browser gamepad bridge 将数据发布到 ROS 2。

TGZ-850M 实体手柄
↓ 2.4 GHz
Windows USB 接收器和 Windows XInput 驱动

Windows Edge / Chrome Gamepad API
↓ HTTP
WSL2 browser gamepad bridge → /joy → joy_ctrl → /cmd_vel → Gazebo UGV Rover

本流程读取 Windows 中已连接的实体手柄,不使用网页虚拟摇杆。接收器无需通过 usbipd 连接到 WSL2,预配置镜像已包含所需功能,无需额外安装或重新编译。

提示

该流程仅用于本教程的 WSL2 Gazebo 仿真,不影响实体 UGV 原有的手柄控制方式。同一时间只运行一种手动控制。

使用实体手柄控制 UGV Rover

  1. 完成使用前准备:将 TGZ-850M 的 2.4 GHz USB 接收器插入 Windows 电脑,打开手柄电源,确认手柄指示灯稳定。在 Windows PowerShell 中执行:

    usbipd list

    在输出中找到 045e:028e 支持 Windows 的 XBOX 360 手柄,正常状态应为 Not shared

    usbipd list 中由 Windows 管理的 TGZ-850M USB 接收器

    如果状态显示为 Shared (forced)Attached,说明接收器仍被旧 usbipd 流程占用。以管理员身份打开 Windows PowerShell,执行:

    usbipd unbind --hardware-id 045e:028e

    重新插拔接收器后,再次执行 usbipd list,确认状态变为 Not shared

    在 Windows PowerShell 中执行:

    Start-Process joy.cpl

    在“游戏控制器”窗口中选择 Xbox 360 Controller,点击“属性”,再进入“测试”选项卡。分别推动左、右摇杆,按下方向键和主要按键,确认测试页面中的十字标记、轴或按钮状态随操作变化。测试完成后关闭“属性”和“游戏控制器”窗口,避免其它程序持续占用设备。

    游戏控制器窗口

    Windows“游戏控制器”中的 TGZ-850M 输入测试

    Xbox 360 Controller 是接收器向 Windows 报告的设备名称,不表示 TGZ-850M 是微软原装 Xbox 360 手柄。

  2. 保持 Gazebo 运行,确认键盘控制已经停止。另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd /home/ag/ws/ugv_ws
    unset ROS_DOMAIN_ID
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 launch ugv_tools teleop_twist_joy.launch.py input_mode:=browser

    日志显示 browser 输入模式、http://localhost:8765browser gamepad bridgejoy_ctrl,表示 bridge 已启动。

    browser gamepad bridge 启动日志和控制页面地址

  3. 在 Windows Edge 或 Chrome 中打开 http://localhost:8765。只保留一个控制页面,然后点击“开始读取实体手柄”。确认页面显示接收器检测状态、网页与 WSL bridge 通信状态,以及控制输出状态。

    TGZ-850M browser gamepad bridge 控制页面

    提示

    控制期间保持该页面为当前活动标签页。切换到其它标签页、最小化或关闭页面时,系统会触发安全停车。

    页面显示“手柄本体状态:浏览器无法可靠判断”不表示发生故障。接收器已检测或 bridge 通信正常,都不表示手柄本体已经开机。应以控制输出和车辆是否停止为准。

  4. 观察控制页面中的原始数据:

    • 设备 ID 显示 Xbox 360 Controller
    • mapping 显示 standard
    • axes 长度为 4
    • buttons 长度为 17
    • 推动左、右摇杆时,原始 axes 数值发生变化;
    • 松开摇杆后,axes 回到接近 0
    • 按键操作时,对应 buttons 数值发生变化。

    不需要记忆所有 axes 下标。本机验证的方向参考如下,推动幅度不同时数值可能不是 -11:左摇杆向上时 axes[1] 为负值,向下时为正值;右摇杆向左时 axes[2] 为负值,向右时为正值;松开后接近 0

  5. 小幅操作手柄,确认 Gazebo 中 UGV Rover 的运动方向:

    操作预期
    左摇杆向上UGV Rover 前进
    左摇杆向下UGV Rover 后退
    右摇杆向左UGV Rover 左转
    右摇杆向右UGV Rover 右转
    松开摇杆UGV Rover 停车

    前进和转向可以组合,摇杆推动幅度影响速度。第一次操作时先小幅推动。

  6. 验证安全停车:

    • 让 UGV Rover 移动后松开摇杆,确认车辆停车;
    • 让 UGV Rover 低速移动后切换到其它标签页,确认车辆停车;
    • 关闭控制页面,确认车辆停车;
    • 拔出 USB 接收器,确认车辆停车;
    • 保持摇杆非零时关闭手柄电源,确认车辆停车;
    • 重新打开手柄并操作,确认可以恢复控制。

    手柄关闭后,页面仍可能显示“USB 接收器:已检测”或 bridge 通信正常,这不代表车辆仍在运动。不需要刷新网页才能停车,应以页面“控制输出”和 Gazebo 中车辆实际状态为准。控制输出应持续反映当前输入,不应周期性在运动和中立之间跳变。

手柄页面正常但 UGV Rover 不运动时检查 topic

另开一个 UGV-Gazebo-Humble 图形化终端,执行:

cd /home/ag/ws/ugv_ws
unset ROS_DOMAIN_ID
source /opt/ros/humble/setup.bash
source install/setup.bash

ros2 topic info /joy
ros2 topic info /cmd_vel

检查 /joy:先推动并保持一个摇杆方向,再执行:

ros2 topic echo /joy --once

预期 axes 中出现非零值。

检查 /cmd_vel:继续保持运动方向,再执行:

ros2 topic echo /cmd_vel --once

预期 linear.xangular.z 中出现非零值。松开摇杆后重新执行:

ros2 topic echo /cmd_vel --once
  • /joy 不变化:先检查浏览器页面和 Windows joy.cpl
  • /joy 变化但 /cmd_vel 不变化:检查 joy_ctrl 是否运行;
  • /cmd_vel 变化但车辆不动:检查 Gazebo 底盘控制节点;
  • 不需要修改代码或重新构建。

停止手柄控制:

  1. 松开摇杆并确认 UGV Rover 已停止。
  2. 关闭 Windows 中的控制页面。
  3. browser gamepad bridge 终端按 Ctrl + C

在 Gazebo 中复现 SLAM

SLAM 原理和实体 UGV 操作已在前面的 ROS 2 教程中介绍。本节只列出 Gazebo House 场景中的对应入口和观察结果。整个章节保持同一个 Gazebo 运行;切换算法前,停止上一套 SLAM、RViz 和手动控制。

Gmapping 建图

  1. 保持 Gazebo 运行,另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 launch ugv_gazebo gmapping.launch.py

    正常时会打开 RViz,窗口中显示 UGV Rover 模型、LaserScan 和正在生成的二维地图。

    Gmapping 启动后的 RViz 二维建图界面

  2. 另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 run ugv_tools keyboard_ctrl

    保持键盘控制终端处于活动状态,低速移动 UGV Rover。注意 Gazebo 中的车辆运动,避免遗漏区域、撞墙或翻车;同时观察 RViz 中的地图逐步扩展。

    按键动作
    I前进
    ,后退
    J左转
    L右转
    K 或空格停止
    提示

    在 Gazebo 和 RViz 中,可使用鼠标滚轮缩放视图,按住鼠标中键拖动调整显示位置。

    Gmapping 建图时的 Gazebo、键盘控制终端和 RViz

  3. 地图覆盖目标区域后,先结束键盘控制,保持 Gmapping 和 RViz 运行。另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    MAP_DIR="$HOME/ws/ugv_ws/src/ugv_main/ugv_gazebo/maps"
    mkdir -p "$MAP_DIR"
    ros2 run nav2_map_server map_saver_cli -f "$MAP_DIR/map"
    ls -lh "$MAP_DIR/map.pgm" "$MAP_DIR/map.yaml"

    保存过程中,终端会显示地图数据和元数据的写入路径,并输出 Map saved successfully

    Gmapping 地图保存成功日志

    随后的文件列表中应显示 map.pgmmap.yaml,且两个文件大小不为 0

    Gmapping 保存后的地图文件

    保存后在 Gmapping 终端按 Ctrl + C,停止 Gmapping 和 RViz,保留 Gazebo 运行

Cartographer 建图

  1. 保持 Gazebo 运行,停止上一套 SLAM 和 RViz。另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 launch ugv_gazebo cartographer.launch.py

    正常时会打开 RViz,窗口中显示 UGV Rover 模型、LaserScan、地图和建图轨迹。

    Cartographer 启动后的 RViz 建图界面

  2. 另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 run ugv_tools keyboard_ctrl

    保持键盘控制终端处于活动状态,低速移动 UGV Rover,观察 RViz 中的地图和轨迹持续更新。

    按键动作
    I前进
    ,后退
    J左转
    L右转
    K 或空格停止
  3. 地图覆盖目标区域后,先结束键盘控制,保持 Cartographer 和 RViz 运行。另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    MAP_DIR="$HOME/ws/ugv_ws/src/ugv_main/ugv_gazebo/maps"
    mkdir -p "$MAP_DIR"
    ros2 run nav2_map_server map_saver_cli -f "$MAP_DIR/map"
    ros2 service call /write_state \
    cartographer_ros_msgs/srv/WriteState \
    "{filename: '$MAP_DIR/map.pbstream'}"
    ls -lh \
    "$MAP_DIR/map.pgm" \
    "$MAP_DIR/map.yaml" \
    "$MAP_DIR/map.pbstream"

    三个文件存在并且大小不为 0,表示二维地图和 Cartographer 状态已经保存。保存后在 Cartographer 终端按 Ctrl + C,停止 Cartographer 和 RViz,保留 Gazebo 运行

二维地图保存位置

Gmapping 和 Cartographer 会将地图保存到 ~/ws/ugv_ws/src/ugv_main/ugv_gazebo/maps/。镜像内置导航默认使用安装目录中与 House 场景匹配的地图,因此保存成功不表示 Nav2 已切换到新地图。当前教程继续使用镜像内置地图;不要直接修改安装目录,也不需要重新构建工作空间。

地图不更新或保存失败时检查

另开一个 UGV-Gazebo-Humble 图形化终端并执行:

cd ~/ws/ugv_ws
source /opt/ros/humble/setup.bash
source install/setup.bash

ros2 topic hz /map
ros2 run tf2_ros tf2_echo map base_footprint

两个命令会持续输出,检查完成后按 Ctrl + C。如果 /map 没有更新,先确认对应 SLAM 终端仍在运行;如果保存失败,检查保存终端中的错误和目标目录权限。

RTAB-Map RGB-D 建图

RTAB-Map 用相机、深度相机和激光雷达数据生成三维点云地图,建图结果保存在 ~/.ros/rtabmap.db

注意

该启动入口会删除默认旧数据库。已有数据库需要保留时,先在 UGV-Gazebo-Humble 终端中执行:

mkdir -p ~/rtabmap_backup

if [ -f ~/.ros/rtabmap.db ]; then
cp ~/.ros/rtabmap.db \
~/rtabmap_backup/rtabmap-$(date +%Y%m%d-%H%M%S).db
fi
提示

Gazebo 成功生成 UGV Rover 后,建议等待约 5~10 秒再启动 RTAB-Map。启动初期如果短暂出现相机 TF 未就绪提示,可停止 RTAB-Map,确认 Gazebo 与机器人 TF 正常后重新启动;不需要修改 URDF、SDF 或启动参数。

  1. 保持 Gazebo 运行,停止上一套 SLAM 和 RViz。另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 launch ugv_gazebo rtabmap_rgbd.launch.py

    正常时会打开 RTAB-Map 可视化窗口(程序名为 rtabmap_viz),其中显示相机画面、三维点云地图、里程计和建图轨迹。初始画面中可看到相机数据和已经接收的点云。

    RTAB-Map 启动后的可视化窗口

  2. 另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 run ugv_tools keyboard_ctrl

    保持键盘控制终端处于活动状态,低速移动 UGV Rover。RTAB-Map 可视化窗口中的点云地图和轨迹应随车辆移动逐步更新。

    按键动作
    I前进
    ,后退
    J左转
    L右转
    K 或空格停止

    RTAB-Map 建图时的 Gazebo、键盘控制终端和可视化窗口

  3. 建图结束后,先停止键盘控制,再在 RTAB-Map 终端按 Ctrl + C。等待数据库写入完成,然后执行:

    ls -lh ~/.ros/rtabmap.db

    数据库存在并且大小不为 0,表示建图数据已经保存。保留 Gazebo 运行

定位与导航

本节用于在 Gazebo 中快速复现实体 UGV 教程中的定位和导航操作,继续使用镜像内置的 House 场景地图。

使用已有二维地图进行 AMCL + Nav2 导航

  1. 保持 Gazebo 运行,确认键盘控制、browser 手柄控制和其它 SLAM、定位、Nav2 节点已经停止。另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 launch ugv_gazebo nav.launch.py \
    use_localization:=amcl \
    use_localplan:=teb

    正常时会加载 House 场景对应的地图并打开 RViz。

  2. 在 RViz 中点击 2D Pose Estimate,在地图中 UGV Rover 所在位置按下鼠标并沿车头方向拖动,松开鼠标后完成初始位置设置。

    在 RViz 中设置 UGV Rover 的 AMCL 初始位置

    等待粒子聚集到 UGV Rover 周围,并确认 LaserScan 与地图中的墙壁轮廓基本对齐。出现明显偏差时,重新设置位置和方向。

    AMCL 粒子向 UGV Rover 周围聚集

  3. 在 RViz 中点击 Nav2 Goal,在已知可通行区域设置一个近距离目标。RViz 中出现规划路径后,UGV Rover 应沿路径移动并在到达目标后停止。

    Nav2 控制 UGV Rover 沿规划路径移动

    UGV Rover 到达 Nav2 导航目标

  4. 结束时先在 RViz 中取消当前目标,确认 UGV Rover 停止,再在 Nav2 终端按 Ctrl + C

切换为 DWA 局部控制

停止上一组 Nav2 后,将启动命令中的局部控制参数改为:

use_localplan:=dwa

其它操作与 TEB 相同。

SLAM Toolbox 与 Nav2 同步建图和导航

该流程用于综合演示同步建图和导航,不再重复介绍 SLAM Toolbox 和 Nav2 原理。

  1. 保持 Gazebo 运行,停止其它 SLAM、定位、Nav2、RViz 和手动控制。另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 launch ugv_gazebo slam_nav.launch.py

    正常时会打开 RViz 建图导航窗口。窗口中显示机器人模型、激光雷达数据和初始地图,左侧 Navigation 状态显示为 active

    SLAM Toolbox 与 Nav2 启动后的 RViz 建图导航窗口

  2. 另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 run ugv_tools keyboard_ctrl

    保持键盘控制终端处于活动状态,低速移动 UGV Rover,观察 RViz 中的地图扩展。

    按键动作
    I前进
    ,后退
    J左转
    L右转
    K 或空格停止

    UGV Rover 移动后,Gazebo 中的激光扫描方向随车辆位置变化,RViz 中的空白区域逐步生成地图,墙壁轮廓和可通行区域随移动不断补充。

    使用键盘控制 UGV Rover 进行 SLAM Toolbox 同步建图

  3. 地图覆盖目标区域后,停止键盘控制。RViz 中应显示连续的墙壁轮廓和已探索区域。

    SLAM Toolbox 建图完成后的 RViz 地图

    在 RViz 中设置一个近距离 Nav2 Goal。出现规划路径后,UGV Rover 应沿路径向目标移动,左侧导航反馈会显示目标执行状态。

    SLAM Toolbox 与 Nav2 同步运行时 UGV Rover 向目标移动

  4. 结束时先取消导航目标并确认车辆停止,再在 SLAM Toolbox 与 Nav2 终端按 Ctrl + C

RTAB-Map Localization 定位验证

该进阶功能只使用已有 ~/.ros/rtabmap.db 验证定位,不会自动规划路径或控制车辆。

保持 Gazebo 运行,停止其它定位、SLAM 和 Nav2。另开一个 UGV-Gazebo-Humble 图形化终端并执行:

cd ~/ws/ugv_ws
source /opt/ros/humble/setup.bash
source install/setup.bash

ls -lh ~/.ros/rtabmap.db
ros2 launch ugv_gazebo rtabmap_localization_launch.py

数据库应存在并且大小不为 0。检查完成后,在 RTAB-Map 定位终端按 Ctrl + C

定位或导航没有正常显示时检查

另开 UGV-Gazebo-Humble 终端,执行:

cd ~/ws/ugv_ws
source /opt/ros/humble/setup.bash
source install/setup.bash

ros2 node list
ros2 topic list
ros2 lifecycle nodes
ros2 run tf2_ros tf2_echo map base_footprint

tf2_echo 会持续输出,检查完成后按 Ctrl + C 停止。

自动探索

本节用于在 Gazebo 中快速复现自动探索。运行期间不要同时使用键盘或手柄控制。

  1. 保持 Gazebo 运行,停止其它 SLAM、定位、Nav2、RViz 和手动控制。另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 launch ugv_gazebo slam_nav.launch.py

    等待 RViz 中出现机器人模型和初始地图。地图开始更新后,再启动自动探索。

    explore_lite 启动前的 RViz 建图导航界面

  2. 另开一个 UGV-Gazebo-Humble 图形化终端并执行:

    cd ~/ws/ugv_ws
    source /opt/ros/humble/setup.bash
    source install/setup.bash

    ros2 launch explore_lite explore.launch.py

    启动后,自动探索终端会输出当前探索和导航信息。RViz 中的地图和路径会逐步扩展,Gazebo 中的 UGV Rover 会自动移动。没有可探索区域时,系统可能不再产生新目标。

    Gazebo、RViz 和 explore_lite 自动探索过程

  3. 结束时先在自动探索终端按 Ctrl + C,再在 RViz 中取消当前目标并确认 UGV Rover 停止,最后在 SLAM 与 Nav2 终端按 Ctrl + C

停止与重新启动

本节说明 Gazebo、SLAM、Nav2、自动探索和控制节点的停止顺序,以及 Windows 重启后的恢复步骤。

正常停止

按照当前实际运行的功能从上层向底层停止。没有运行的终端跳过。

  1. 运行自动探索时,先在自动探索终端按 Ctrl + C,停止继续提交探索目标。

  2. 运行 Nav2 时,在 RViz 中取消当前目标。

  3. 松开键盘或实体手柄输入,确认 UGV Rover 不再运动。

  4. 使用 browser 手柄控制时,关闭 Windows 中的控制页面,在 browser gamepad bridge 终端按 Ctrl + C,然后执行:

    ss -ltnp | grep ':8765' || echo "port 8765 released"

    输出 port 8765 released 表示控制页面端口已经释放。使用键盘控制时,在键盘控制终端按 Ctrl + C

  5. 在 Nav2 终端按 Ctrl + C

  6. 在定位或 SLAM 终端按 Ctrl + C;RTAB-Map 建图结束时等待数据库写入完成。

  7. 最后回到 Gazebo 启动终端Ctrl + C,等待 5~10 秒。

运行结果:活动的控制、导航和 SLAM 节点停止,browser gamepad bridge 退出,gzclientgzserver 退出。

如果 Ctrl + C 后 Gazebo 仍未退出,在另一个 UGV-Gazebo-Humble 终端中执行备用停止工具:

source /opt/ros/humble/setup.bash
source /home/ag/ws/ugv_ws/install/setup.bash

ros2 run ugv_gazebo stop_gazebo.sh

该工具仅用于 Ctrl + C 失效的情况,不作为正常停止方式。执行后可检查 Gazebo 进程:

pgrep -a -x gzclient || echo "gzclient stopped"
pgrep -a -x gzserver || echo "gzserver stopped"
pgrep -a -f '[r]os2 launch ugv_gazebo' || echo "gazebo launch stopped"

输出 gzclient stoppedgzserver stoppedgazebo launch stopped,表示备用停止完成。不要使用 killall pythonpkill python,以免终止其它 ROS 2 节点;也不再将 Ctrl + \ 作为常规停止操作。

冷启动

  1. 按前面的正常停止顺序结束功能节点,最后在 Gazebo 启动标签页按 Ctrl + C,等待 Gazebo 进程退出;确认不再需要该标签页后再关闭。

  2. 需要完全停止 WSL2 时,在 Windows PowerShell 中执行:

    wsl --shutdown

wsl --shutdown 会停止所有正在运行的 WSL2 发行版,请先确认其它 WSL2 任务已经保存。

Windows 重启后,按照 日常启动 恢复 Gazebo 仿真。