激光雷达

激光雷达(Light Detection And Ranging),缩写LiDAR,翻译一下叫——激光探测与测距。

激光雷达原理

激光雷达的原理也很简单,就像蝙蝠的定位方法一样,蝙蝠定位大家都知道吧,像下面这样子的回声定位。

普通的单线激光雷达一般有一个发射器,一个接收器,发射器发出激光射线到前方的目标上,物品会将激光反射回来,然后激光雷达的接受器可以检测到反射的激光。

通过计算发送和反馈之间的时间间隔,乘上激光的速度,就可以计算出激光飞行的距离,该计算方法成为TOF(飞行时间法Time of flight,也称时差法)。

除了TOF之外还有其他方法进行测距,比如三角法,这里就不拓展了放一篇文章,大家自行阅读。

目前市面上的激光雷达,几乎都是采用三角测距,比如思岚的:

需要注意的是虽然只有一个发射器和一个接受器,激光雷达通过电机可以进行旋转,这样就可以达到对周围环境360度测距的目的。

Gazebo激光雷达插件

因为激光雷达是属于射线类传感器,该类传感在在Gazebo插件中都被封装成了一个动态库libgazebo_ros_ray_sensor.so

接着我们来看看LiDAR的话题消息接口sensor_msgs/msg/LaserScan

ros2 interface show  sensor_msgs/msg/LaserScan

header:

  • std_msgs/Header header:消息头,包含时间戳(stamp)和坐标系(frame_id)信息。时间戳表示此激光扫描数据的获取时间,坐标系表示数据相对于哪个参考系进行描述。

angle_min:

  • float32 angle_min:扫描开始的角度(弧度)。这是激光雷达扫描范围的最小角度。

angle_max:

  • float32 angle_max:扫描结束的角度(弧度)。这是激光雷达扫描范围的最大角度。

angle_increment:

  • float32 angle_increment:相邻激光束之间的角度增量(弧度)。这是激光雷达在扫描过程中,相邻两个测量点之间的角度差。

time_increment:

  • float32 time_increment:连续测量之间的时间增量(秒)。如果激光雷达在移动,这个值将用于插值 3D 点的位置。

scan_time:

  • float32 scan_time:完成一次完整扫描所需的时间(秒)。这有助于了解激光雷达的扫描频率。

range_min:

  • float32 range_min:激光雷达能够检测到的最小距离(米)。这是激光雷达能够可靠测量的最短距离。

range_max:

float32 range_max:激光雷达能够检测到的最大距离(米)。这是激光雷达能够可靠测量的最远距离。

ranges:

  • float32[] ranges:测量的距离数据数组(米)。数组中的每个元素表示对应角度的测量距离值。注意:小于 range_min 或大于 range_max 的值应被丢弃。

intensities:

  • float32[] intensities:测量的强度数据数组(设备特定单位)。如果设备不提供强度数据,请保持数组为空。

雷达的数据结构有些复杂,但通过注释和名字相信你可以看的七七八八,看不懂也没关系,一般情况下我们不会直接的对雷达的数据做操作。小鱼这里也就先skip。

为FishBot添加雷达插件

有了前面的经验,我们需要在URDF添加以下内容即可

  <gazebo reference="laser_link">
      <sensor name="laser_sensor" type="ray">
      <always_on>true</always_on>
      <visualize>true</visualize>
      <update_rate>5</update_rate>
      <pose>0 0 0.075 0 0 0</pose>
      <ray>
          <scan>
            <horizontal>
              <samples>360</samples>
              <resolution>1.000000</resolution>
              <min_angle>0.000000</min_angle>
              <max_angle>6.280000</max_angle>
            </horizontal>
          </scan>
          <range>
            <min>0.120000</min>
            <max>3.5</max>
            <resolution>0.015000</resolution>
          </range>
          <noise>
            <type>gaussian</type>
            <mean>0.0</mean>
            <stddev>0.01</stddev>
          </noise>
      </ray>

      <plugin name="laserscan" filename="libgazebo_ros_ray_sensor.so">
        <ros>
          <remapping>~/out:=scan</remapping>
        </ros>
        <output_type>sensor_msgs/LaserScan</output_type>
        <frame_name>laser_link</frame_name>
      </plugin>
      </sensor>
    </gazebo>

可以看到:

  1. 雷达也可以设置更新频率update_rate,这里设置为5

  2. 雷达可以设置分辨率,设置为1,采样数量360个,最终生成的点云数量就是360

  3. 雷达也有噪声,模型为gaussian

  4. 雷达有扫描范围range,这里配置成0.12-3.5,0.015分辨率

  5. 雷达的pose就是雷达的joint中位置的设置值

编译测试

编译

colcon build --packages-select fishbot_description
source install/setup.bash

运行

ros2 launch fishbot_description gazebo.launch.py

查看话题

ros2 topic list
ros2 topic info /scan

ros2 topic echo /scan

接着我们尝试使用rviz2进行可视化激光雷达数据

添加和修改RVIZ2的如下:(通过LaserScan插件可以看到激光数据)

相信你改完之后依然是看不到任何激光雷达的数据的,反看topic的echo出来的数据,不是0就是inf(无限大),再看看gazebo你会发现,激光雷达并没有达到任何一个物体上。

所以我们可以手动的给激光雷达周围添加一下东西,点击Gazebo工具栏的正方体,圆球或者圆柱,随意放置几个到我们激光雷达的最大扫描半径内。

接着我们再看一下RVIZ2,这里小鱼把size改大了10倍0.01->0.1。

总结

到这里我们就把fishbot的各个传感器都仿真出来了,第九章的内容也暂且告一段落,迎接我们的是第十章,也就是fishbot的导航仿真,nav2了。

如果你想先本教程一步学习Nav2,可以到nav2中文网哦~