4、传感器仿真:配置激光雷达(LaserScan)和IMU传感器,在Gazebo中验证数据输出

传感器是机器人的眼睛和耳朵。没有它们,避障就是瞎撞。

这一章,我们来搞定两个最关键的传感器:激光雷达和IMU。我个人习惯先把它们配好,再去做避障算法。因为数据不准,后面全是白费功夫。

4.1 激光雷达(LaserScan)的配置

激光雷达在Gazebo里其实就是一个射线传感器。它发射一束束激光,碰到物体就返回距离信息。

嗯,这里要注意:Gazebo里的激光雷达是理想化的。它没有真实传感器的噪声和抖动。所以你在仿真里跑得好好的,上了真车可能就翻车了。我当年就吃过这个亏。

4.1.1 在URDF中定义激光雷达

我们先写一个简单的URDF片段。把它放到你的机器人模型里就行。

<link name="laser_link">
  <visual>
    <geometry>
      <cylinder length="0.05" radius="0.05"/>
    </geometry>
    <origin xyz="0 0 0" rpy="0 0 0"/>
  </visual>
</link>

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

<gazebo reference="laser_link">
  <sensor type="ray" name="head_laser">
    <pose>0 0 0 0 0 0</pose>
    <visualize>true</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.1</min>
        <max>10.0</max>
        <resolution>0.01</resolution>
      </range>
      <noise>
        <type>gaussian</type>
        <mean>0.0</mean>
        <stddev>0.01</stddev>
      </noise>
    </ray>
  </sensor>
</gazebo>

这段代码里,我设置了360度扫描,10米范围。为什么是360度?因为避障需要全向感知。你想想看,如果只有180度,侧面撞上墙都不知道。

我的小技巧: 把visualize设为true,你可以在Gazebo里看到激光射线。调试时特别有用。但跑正式仿真时记得关掉,否则会拖慢速度。

4.1.2 验证LaserScan数据

启动Gazebo后,用rostopic命令看看数据有没有出来。

rostopic echo /scan

你会看到类似这样的输出:

header:
  seq: 123
  stamp:
    secs: 1234567890
    nsecs: 123456789
  frame_id: "laser_link"
angle_min: -3.14159
angle_max: 3.14159
angle_increment: 0.0174533
time_increment: 0.0002778
scan_time: 0.1
range_min: 0.1
range_max: 10.0
ranges: [0.5, 0.5, 0.5, ...]

ranges数组就是距离数据。如果全是inf或者0,说明你的传感器没对准。我曾经有一次搞了半天,结果是激光雷达装反了,朝天上扫。

4.2 IMU传感器的配置

IMU提供角速度和线加速度。避障时,它帮你判断机器人是不是在打滑,或者是不是撞到了东西。

4.2.1 在URDF中定义IMU

IMU的配置比激光雷达简单。看代码:

<link name="imu_link">
  <visual>
    <geometry>
      <box size="0.02 0.02 0.02"/>
    </geometry>
  </visual>
</link>

<joint name="imu_joint" type="fixed">
  <parent link="base_link"/>
  <child link="imu_link"/>
  <origin xyz="0 0 0.05" rpy="0 0 0"/>
</joint>

<gazebo reference="imu_link">
  <sensor type="imu" name="imu_sensor">
    <pose>0 0 0 0 0 0</pose>
    <update_rate>50</update_rate>
    <imu>
      <noise>
        <type>gaussian</type>
        <rate>
          <mean>0.0</mean>
          <stddev>0.0002</stddev>
          <bias_mean>0.0</bias_mean>
          <bias_stddev>0.00001</bias_stddev>
        </rate>
        <accel>
          <mean>0.0</mean>
          <stddev>0.001</stddev>
          <bias_mean>0.0</bias_mean>
          <bias_stddev>0.0001</bias_stddev>
        </accel>
      </noise>
    </imu>
  </sensor>
</gazebo>

这里我加了噪声参数。为什么?因为真实IMU一定有噪声。如果你在仿真里不加噪声,后面做滤波算法时就会觉得「怎么这么简单」,一上真车就傻眼。

避坑指南: 我曾经在项目里忘了加IMU的噪声。结果卡尔曼滤波参数调得完美,上了真车直接发散。后来花了三天重新调参。所以,仿真时就把噪声加上,省得后面吃苦。

4.2.2 验证IMU数据

同样用rostopic查看:

rostopic echo /imu/data

输出示例:

header:
  seq: 456
  stamp:
    secs: 1234567890
    nsecs: 987654321
  frame_id: "imu_link"
orientation:
  x: 0.0
  y: 0.0
  z: 0.0
  w: 1.0
angular_velocity:
  x: 0.0
  y: 0.0
  z: 0.0
linear_acceleration:
  x: 0.0
  y: 0.0
  z: 9.81

注意看linear_acceleration的z轴。静止时应该是9.81,也就是重力加速度。如果不是,说明你的IMU坐标系没对准。我见过有人把z轴和x轴搞反了,结果机器人明明是平的,IMU却说它在侧翻。

4.3 传感器数据可视化

光看数字不够直观。我们用RViz来看。

rosrun rviz rviz

在RViz里:

  • 添加LaserScan话题,选择/scan
  • 添加Imu话题,选择/imu/data

你会看到激光雷达的点云和IMU的坐标轴。如果一切正常,激光雷达应该能扫出周围环境的轮廓,IMU的坐标轴应该稳定不动。

核心要点: 传感器配置的关键不是代码本身,而是验证数据是否正确。我每次都会花至少10分钟盯着数据看,确保没有异常值。

4.4 本章知识体系

下面这张图总结了传感器配置的核心逻辑:

传感器配置核心流程 1. URDF定义 link + joint + gazebo标签 2. Gazebo加载 启动仿真环境 3. 数据验证 rostopic echo 激光雷达 (LaserScan) • 360度扫描 • 范围:0.1 - 10米 • 更新率:10Hz IMU传感器 • 角速度 + 线加速度 • 更新率:50Hz • 含高斯噪声 验证通过 → 进入避障算法调优

说白了,传感器配置就是三步走:定义、加载、验证。每一步都不能跳过。我见过太多人急着调算法,结果传感器数据都是错的,浪费了好几天时间。

我的习惯: 每次修改传感器参数后,我都会让机器人原地转一圈,看看激光雷达的数据是不是平滑变化。如果出现跳变,说明参数有问题。

好了,传感器配好了,数据也验证了。接下来就可以放心地去做避障算法了。

可可精品资料库