虽然当前 WSL2 通过 WSLg 已支持直接运行 Gazebo,即使启用了 GPU 硬件加速,其图形性能仍显著受限,导致仿真过程非常卡顿。因此,更推荐的方式是将 Gazebo 运行在原生 Ubuntu 系统上。如果你不想配置双系统,也可以采用以下替代方案:在 Windows 原生环境中运行 Gazebo 仿真器,同时在 WSL2 中运行 ROS 2 节点控制 Gazebo。

Gazebo 新版本采用了类似 ROS 2 的分布式架构——其内部组件以独立节点形式运行,并通过 topic 或 service 进行通信。得益于此架构,只要网络配置正确,WSL2 中的 ROS2 节点便能发现并订阅/调用 Windows 上 Gazebo 发布的 topic 和 service,从而实现跨平台协同仿真与控制。

Windows 安装 Gazebo

Gazebo 官方安装教程:https://gazebosim.org/docs/harmonic/install_windows/

这里使用 pixi 来安装

  1. 安装 pixi ,可以下载二进制,或者用 scoop 安装

    1
    
    scoop install pixi
  2. 创建一个文件夹,作为 gazebo 的安装目录,这里放到 D:/Applications/Manual/gazebo

  3. 在文件夹下新建一个 pixi.toml 文件,里面写上下面的内容

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    [workspace]
    channels = ["conda-forge"]
    name = "gazebo"
    platforms = ["win-64"]
    version = "0.1.0"
    
    [target.win-64.activation.env]
    PYTHONUTF8="1"
    GZ_PARTITION="xbot"
    
    [dependencies]
    libgz-cmake3 = "*"
    libgz-common5 = "*"
    libgz-fuel-tools9 = "*"
    libgz-sim8 = "*"
    libgz-gui8 = "*"
    libgz-launch7 = "*"
    libgz-math7 = "*"
    libgz-msgs10 = "*"
    libgz-physics7 = "*"
    libgz-plugin2 = "*"
    libgz-rendering8 = "*"
    libgz-sensors8 = "*"
    libgz-tools2 = "*"
    libgz-transport13 = "*"
    libgz-utils2 = "*"
    libsdformat14 = "*"

    env 下包括这个环境下启用的环境变量:

    • PYTHONUTF8 : 强制 Python 默认使用 UTF8 编码,必须添加,不然会安装失败
    • GZ_PARTITION : 指定 Gazebo 节点的分区名称,相同分区名称的节点才能互相发现,既在 WSL2 环境中也要指定同样的 GZ_PARTITION
  4. 在目录下运行 pixi install 开始安装

  5. 运行 pixi shell 以当前环境开启一个 shell

  6. 运行 gz sim -s 启动 Gazebo 服务

  7. 重新开一个 shell ,运行 gz sim -g 启动 Gazebo UI

快速启动 Gazebo

使用 pixi 安装的软件每次要进入对应目录,使用 pixi shell 或者 pixi run 才能运行 Gazebo ,下面制作一个脚本一键启动。

  1. 将下面的脚本保存在 export_env.ps1

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    $OutputScript = "run_gazebo.ps1"
    
    $envVars = Get-ChildItem env: | Sort-Object Name
    
    $scriptLines = @()
    $scriptLines += "# Environment variables exported at $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
    $scriptLines += "# Using ${env:...} syntax to support special characters in names."
    $scriptLines += ""
    
    foreach ($var in $envVars) {
        # 转义值中的双引号和反引号
        $escapedValue = $var.Value -replace '"', '`"' -replace '`', '``'
    
        # 使用 ${env:...} 语法包裹变量名(支持括号、空格等)
        $line = '${env:' + $var.Name + '} = "' + $escapedValue + '"'
        $scriptLines += $line
    }
    
    # 写入文件(UTF-8 无 BOM)
    $scriptLines | Out-File -FilePath $OutputScript -Encoding UTF8
    
    Write-Host "✅ 已成功导出到: $(Resolve-Path $OutputScript)" -ForegroundColor Green
  2. 在 powershell 中使用 pixi shell 进入 gazebo

  3. 进入 shell 后运行 export_envs.ps1 ,会生成 run_gazebo.ps1 ,里面设置了当前 shell 的所有环境变量

  4. run_gazebo.ps1 脚本后面加上 gazebo 启动的命令

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    
    # 启动 gazebo
    
    param(
        [Parameter(ValueFromRemainingArguments = $true)]
        [string[]]$ServerArgs
    )
    
    if ($null -eq $ServerArgs) {
        $ServerArgs = @()
    }
    
    $serverProc = $null
    $guiProc = $null
    
    
    try {
        # 构造完整参数列表
        $fullServerArgs = @("sim", "-s") + $ServerArgs
        $guiArgs = @("sim", "-g")
    
        $serverProc = Start-Process -FilePath "gz" -ArgumentList $fullServerArgs -PassThru -NoNewWindow  -RedirectStandardOutput "$env:TEMP\gz_server.log" -RedirectStandardError "$env:TEMP\gz_server.err"
    
        $guiProc = Start-Process -FilePath "gz" -ArgumentList $guiArgs -PassThru -NoNewWindow -RedirectStandardOutput "$env:TEMP\gz_gui.log" -RedirectStandardError "$env:TEMP\gz_gui.err"
    
        # 持续等待(允许 Ctrl+C 中断)
        while ($true) {
            Start-Sleep -Milliseconds 500
        }
    }
    catch {
        # 捕获 Ctrl+C (ActionPreferenceStopException) 或其他异常
        if ($_.Exception -is [System.Management.Automation.ActionPreferenceStopException]) {
            Write-Host "`n🛑 收到中断信号 (Ctrl+C),正在关闭进程..." -ForegroundColor Yellow
        } else {
            Write-Error "💥 发生错误: $($_.Exception.Message)"
        }
    }
    finally {
        # === 3. 清理子进程 ===
        foreach ($proc in @($serverProc, $guiProc)) {
            if ($proc -and -not $proc.HasExited) {
                try {
                    Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue
                }
                catch {
                    # 忽略清理错误
                }
            }
        }
    }

然后我们就可以右键 run_gazebo.ps1 ,然后使用 powershell 运行来快速启动 Gazebo 了

WSL2 配置

网络配置

要想 WSL2 中能正常发现 Windows 上 Gazebo 的节点,WSL2 的网络不能为镜像网络,既下面的配置不能为 mirrored ,可以设置为 NAT

1
2
[wsl2]
networkingMode=nat

安装 Gazebo

按照官方文档安装即可:https://gazebosim.org/docs/harmonic/install_ubuntu/

Gazebo 配置

在终端设置环境变量 GZ_PARTITION , 值与 Windows 上一致

1
export GZ_PARTITION="xbot"

如果 Windows 启动了 Gazebo ,现在运行 gazebo topic -l 应该可以看到对应的话题如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
/clock
/gazebo/resource_paths
/gui/camera/pose
/gui/currently_tracked
/gui/track
/stats
/world/default/clock
/world/default/dynamic_pose/info
/world/default/pose/info
/world/default/scene/deletion
/world/default/scene/info
/world/default/state
/world/default/stats
/world/default/light_config
/world/default/material_color

测试

  1. 在 Windows 上启动 Gazebo 中自带的 diff_drive.sdf 例子

    1
    
    run_gazebo.ps1 diff_drive.sdf
  2. 在 WSL2 用 gz topic -l 应该可以看到对应话题

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    /clock
    /gazebo/resource_paths
    /gui/camera/pose
    /gui/currently_tracked
    /gui/track
    /model/vehicle_blue/odometry
    /model/vehicle_blue/tf
    /model/vehicle_green/odometry
    /model/vehicle_green/tf
    /stats
    /world/diff_drive/clock
    /world/diff_drive/dynamic_pose/info
    /world/diff_drive/pose/info
    /world/diff_drive/scene/deletion
    /world/diff_drive/scene/info
    /world/diff_drive/state
    /world/diff_drive/stats
    /model/vehicle_blue/cmd_vel
    /model/vehicle_blue/enable
    /model/vehicle_green/cmd_vel
    /model/vehicle_green/enable
    /world/diff_drive/light_config
    /world/diff_drive/material_color
  1. 在 WSL2 上使用 gz topic 命令发布 /model/vehicle_blue/cmd_vel 话题就可以控制小车
    1
    2
    
    gz topic -t /model/vehicle_blue/cmd_vel -m gz.msgs.Twist \
      -p 'linear: {x: 1.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.5}'

ROS2 Launch 启动

WSL2 可以直接运行 Windows 程序,因此可以在 Launch 文件中启动运行 Gazebo 的脚本

1
2
import subprocess
subprocess.Popen(["powershell.exe", "run_gazebo.ps1"])

注意: 当前这种方式启动后 WSL2 终端输出格式会乱掉,并且要按两次 Ctrl-C 才能停止 Launch