4、激光雷达Gazebo插件:gazebo_plugins的Laser传感器配置、修改SDF/URDF模型文件、可视化雷达数据(rviz2)

好,咱们进入正题。这一章要解决一个核心问题:怎么让Gazebo里的虚拟激光雷达真正转起来,并且把数据送到ROS 2里,最后在rviz2上看到那熟悉的点云。

说白了,就是给仿真机器人装上一双「电子眼」。我刚开始搞仿真的时候,以为加个雷达模型就行了,结果折腾半天,Gazebo里啥数据都没有。后来才明白,缺的是那个关键的「插件」——它才是连接仿真世界和ROS 2的桥梁。

核心逻辑:Gazebo负责物理仿真,但本身不发布ROS话题。gazebo_plugins就像个翻译官,把Gazebo内部的激光数据打包成ROS 2的消息,再通过话题发出去。

4.1 gazebo_plugins的Laser传感器配置

Gazebo官方提供了一套插件库,叫gazebo_plugins。咱们要用的激光雷达插件,全名是libgazebo_ros_ray_sensor.so。嗯,名字有点长,但记住它就行。

配置这个插件,通常是在URDF或SDF文件里加一段XML。我个人习惯把它放在标签里,这样跟机器人模型的视觉、碰撞属性分开,结构更清晰。

下面是一个最基础的配置模板,我直接贴出来:

<gazebo reference="laser_link">
  <sensor type="ray" name="head_laser">
    <pose>0 0 0 0 0 0</pose>
    <visualize>false</visualize>
    <update_rate>10</update_rate>
    <ray>
      <scan>
        <horizontal>
          <samples>360</samples>
          <resolution>1</resolution>
          <min_angle>-3.14159</min_angle>
          <max_angle>3.14159</max_angle>
        </horizontal>
      </scan>
      <range>
        <min>0.10</min>
        <max>10.0</max>
        <resolution>0.01</resolution>
      </range>
      <noise>
        <type>gaussian</type>
        <mean>0.0</mean>
        <stddev>0.01</stddev>
      </noise>
    </ray>
    <plugin name="gazebo_ros_ray_sensor" filename="libgazebo_ros_ray_sensor.so">
      <ros>
        <namespace>/</namespace>
        <remapping>~/out:=scan</remapping>
      </ros>
      <output_type>sensor_msgs/LaserScan</output_type>
      <frame_name>laser_link</frame_name>
    </plugin>
  </sensor>
</gazebo>

这里有几个参数,我重点说一下:

  • samples:水平扫描的点数。360点就是每度一个点,精度够用。我曾经为了省性能设成180,结果建图时墙角老是缺一块。
  • min_angle / max_angle:扫描范围,单位是弧度。±π就是360度全覆盖。如果你用单线雷达,比如只有270度视野,就改成对应的弧度值。
  • update_rate:更新频率。10Hz是常规设置,跑导航够用了。设太高(比如50Hz)反而容易把CPU吃满。
  • noise:噪声模型。仿真里加一点高斯噪声,数据会更真实。stddev设0.01,相当于1cm的误差,比较贴近真实雷达。

小技巧:调试阶段可以把<visualize>设为true,这样Gazebo里会画出激光射线,方便你确认雷达朝向和范围对不对。正式跑的时候再关掉,省资源。

4.2 修改SDF/URDF模型文件

有了插件配置,还得把它塞进机器人模型里。URDF和SDF两种格式我都用过,这里分别说一下。

4.2.1 在URDF中添加

URDF是ROS 1时代的主流,ROS 2也兼容。你需要在标签内,先定义好雷达的link和joint:

<link name="laser_link">
  <visual>
    <geometry>
      <cylinder length="0.05" radius="0.03"/>
    </geometry>
    <material name="red"/>
  </visual>
  <collision>
    <geometry>
      <cylinder length="0.05" radius="0.03"/>
    </geometry>
  </collision>
</link>

<joint name="laser_joint" type="fixed">
  <parent link="base_link"/>
  <child link="laser_link"/>
  <origin xyz="0.1 0 0.2" rpy="0 0 0"/>
</joint>

然后,把上一节的配置块直接追加到文件末尾。注意reference="laser_link"要跟link的名字一致。

4.2.2 在SDF中添加

SDF是Gazebo的原生格式,功能更强大。如果你用spawn_entity.py加载模型,SDF会更方便。结构类似,但标签略有不同:

<model name="my_robot">
  <link name="laser_link">
    <visual>...</visual>
    <collision>...</collision>
    <sensor name="head_laser" type="ray">
      <!-- 这里直接嵌入传感器配置 -->
      <ray>...</ray>
      <plugin>...</plugin>
    </sensor>
  </link>
</model>

我个人更推荐用URDF + 扩展的方式。原因很简单:URDF的生态更成熟,很多现成的机器人模型(比如TurtleBot3)都是这么干的,你抄作业也方便。

注意:URDF文件里,标签必须放在标签内部,但可以放在所有link和joint之后。另外,别忘了在launch文件里加载gazebo_ros2_control和robot_state_publisher,否则雷达的tf树会断掉。

4.3 可视化雷达数据(rviz2)

配置写好了,模型加载了,怎么知道雷达有没有在工作?打开rviz2看一眼就知道了。

启动rviz2的命令很简单:

rviz2

然后在界面里:

  1. 点击左下角的「Add」按钮。
  2. 在弹出窗口里选择「By topic」标签页。
  3. 找到/scan话题,类型是sensor_msgs/LaserScan。
  4. 双击它,或者选中后点「OK」。

这时候你应该能看到一圈红色的点,那就是激光雷达的数据。如果看不到,检查以下几点:

  • Fixed Frame:在rviz2左上角的「Global Options」里,把Fixed Frame设为laser_link或base_link。默认是map,仿真里没有map帧,所以会报错。
  • 话题名是否匹配:确认你的插件里<remapping>~/out:=scan</remapping>写对了。如果话题名不对,rviz2里看不到数据。
  • 雷达是否被遮挡:Gazebo里如果雷达被机器人自己的模型挡住了,射线会打在自己身上。我遇到过一回,折腾半天才发现是雷达装在了底盘内部。

调试技巧:在终端里执行ros2 topic echo /scan,如果能刷出数据,说明雷达插件工作正常。如果没数据,先检查Gazebo是否在运行,再检查插件是否加载成功(看Gazebo启动时的日志)。

4.4 本章知识体系

下面这张图,帮你把整个流程串起来:

激光雷达Gazebo插件配置与数据流 激光雷达Gazebo插件配置与数据流 URDF/SDF 模型 gazebo_plugins libgazebo_ros_ray_sensor.so Gazebo 仿真环境 ROS 2 话题 /scan (LaserScan) rviz2 可视化 关键检查点 1. Fixed Frame = laser_link 2. 话题名匹配 /scan 3. 雷达未被自身遮挡

从图里可以看得很清楚:模型文件定义雷达的物理属性,插件负责把仿真数据转成ROS话题,最后rviz2负责展示。这三者缺一不可。

4.5 常见问题与避坑

问题现象 可能原因 解决办法
rviz2里看不到/scan话题 插件未加载或话题名不匹配 检查Gazebo启动日志,确认libgazebo_ros_ray_sensor.so加载成功;检查remapping配置
雷达数据全是inf或nan 雷达被自身模型遮挡,或超出量程 调整雷达安装位置;检查<min>和<max>范围
Gazebo启动报错:找不到插件 gazebo_plugins包未安装 执行sudo apt install ros-humble-gazebo-ros-pkgs
雷达数据更新很慢 update_rate设置过低 提高到10Hz或20Hz;同时检查CPU负载

我曾经踩过一个坑:在URDF里把雷达的写错了,导致雷达装在底盘下面。结果Gazebo里雷达射线全打在地面上,rviz2里看到一圈密密麻麻的点,但就是没有障碍物信息。后来用visualize=true一看,才发现射线全朝下。所以,调试时一定要开可视化,一眼就能看出问题。