激光雷达基础与ROS驱动:从原理到实战

各位同学好,我是老张。今天咱们聊聊激光雷达的基础知识,以及怎么在ROS里把它用起来。说实话,我最早接触激光雷达的时候,也被那些技术术语搞得一头雾水。但别担心,咱们一步步来,把原理搞懂,把驱动调通,后面做导航就顺了。

激光雷达工作原理:TOF vs 三角法

市面上主流的激光雷达,工作原理其实就两大类:TOF(飞行时间法)和三角法。我当年在项目里选型时,就吃过亏——选错了原理,导致在室外强光下数据全飘了。所以这块你得搞清楚。

核心区别一句话:TOF测距离靠光速×时间,三角法靠几何相似三角形。

TOF(飞行时间法)

TOF的原理很简单:发射一束激光脉冲,打到物体上反射回来,接收器记录时间差。距离 = 光速 × 时间差 / 2。嗯,初中物理就够用了。

  • 优点:测量距离远(几十米到上百米),精度高,受环境光影响小。
  • 缺点:成本高,电路复杂,对时间测量精度要求极高(皮秒级)。
  • 典型代表:Velodyne、Hesai、Ouster 等机械式或固态激光雷达。

三角法

三角法呢,是发射器与接收器之间有个固定基线。激光打到物体上,接收器上的成像位置会偏移。通过几何关系,就能算出距离。说白了,就是初中几何里的相似三角形。

  • 优点:成本低,近距离精度高(厘米级甚至毫米级)。
  • 缺点:测量距离短(通常10米以内),远距离精度下降快,易受环境光干扰。
  • 典型代表:RPLIDAR A系列、Sick TiM系列等。
对比项 TOF 三角法
测距原理 光飞行时间 几何三角
测量距离 远(>30m) 近(<10m)
近距离精度 厘米级 毫米级
远距离精度 稳定 下降明显
环境光影响 小 大
成本 高 低
典型应用 自动驾驶、室外导航 室内扫地机、AGV

我的建议:如果你做室内小场景(比如扫地机器人),三角法性价比很高。但要做室外无人车或园区物流,老老实实上TOF。我曾经在强光下用三角法雷达做室外导航,数据直接崩了,排查了三天才发现是原理问题。

ROS中LaserScan消息结构

不管什么原理的激光雷达,在ROS里最终都统一成 sensor_msgs/LaserScan 消息。这个结构你得背下来,因为后面所有算法都靠它。

# sensor_msgs/LaserScan.msg
std_msgs/Header header          # 时间戳和坐标系ID
float32 angle_min               # 扫描起始角度(弧度)
float32 angle_max               # 扫描结束角度(弧度)
float32 angle_increment         # 角度分辨率(弧度)
float32 time_increment          # 每帧时间间隔(秒)
float32 scan_time               # 扫描周期(秒)
float32 range_min               # 最小有效距离(米)
float32 range_max               # 最大有效距离(米)
float32[] ranges                # 距离数据数组(米)
float32[] intensities           # 反射强度数据(可选)

这里有几个坑,我当年踩过:

  • 角度范围:angle_min 和 angle_max 通常是 [-π, π] 或 [0, 2π],但不同雷达不一样。比如 RPLIDAR 是 [0, 2π],而 Velodyne 是 [-π, π]。你写代码时千万别写死。
  • ranges数组长度:理论上应该是 (angle_max - angle_min) / angle_increment + 1。但有些雷达会多一个或少一个点,你得检查。
  • 无效值:ranges 里的 inf 或 NaN 表示没测到。处理时记得过滤,不然算法会炸。

注意:intensities 字段不是所有雷达都发。有些雷达(比如老款 RPLIDAR)就不支持。如果你代码里强依赖 intensities,记得先检查数组长度。

使用sensor_msgs驱动雷达

ROS里驱动激光雷达,说白了就是写一个节点,把雷达的原始数据转成 LaserScan 消息发出去。大部分厂商都提供了现成驱动,但有时候你得自己改改。

我以最常见的 RPLIDAR A2 为例,演示一下怎么用官方驱动:

# 安装驱动
sudo apt install ros-noetic-rplidar-ros

# 启动雷达节点
roslaunch rplidar_ros rplidar.launch

# 查看话题
rostopic list
# 应该能看到 /scan 话题

# 打印数据
rostopic echo /scan

如果你用的是其他雷达,比如思岚 S系列、Velodyne、Hesai,流程类似:

  1. 找到对应的 ROS 驱动包(通常叫 xxx_ros 或 xxx_driver)。
  2. 安装依赖(可能包括串口库、网络库等)。
  3. 修改 launch 文件里的参数(串口号、IP地址、坐标系等)。
  4. 启动节点,检查 /scan 话题是否有数据。

一个小技巧:我习惯在启动雷达后,先用 rostopic hz /scan 看看频率对不对。如果频率不对,可能是串口波特率设错了,或者 USB 线太长导致丢包。

可视化点云数据

光看数字没意思,咱们得把数据可视化出来。ROS里最常用的工具是 RViz。你想想看,激光雷达扫出来的点云在 RViz 里显示出来,那种感觉还是很爽的。

启动 RViz 并显示激光数据:

# 启动 RViz
rosrun rviz rviz

# 在 RViz 界面中:
# 1. 添加 "LaserScan" 显示类型
# 2. 选择话题为 /scan
# 3. 设置坐标系为 laser_frame(或雷达对应的 frame_id)

如果你想把 LaserScan 转成 PointCloud2(点云),方便做更高级的处理,可以用 laser_geometry 包:

# 安装
sudo apt install ros-noetic-laser-geometry

# 使用 laser_scan_to_point_cloud 节点
rosrun laser_geometry laser_scan_to_point_cloud scan:=/scan cloud:=/cloud

这样你就能在 RViz 里同时看到激光扫描线和点云了。我个人习惯用点云模式,因为可以旋转视角,看得更清楚。

避坑指南:我曾经在 RViz 里看不到点云,排查了半天发现是 frame_id 没对上。雷达发的 frame_id 是 "laser",但 RViz 的 Fixed Frame 设成了 "map"。记住:Fixed Frame 必须和雷达的 frame_id 一致,或者有 TF 变换关系。

本章知识体系

下面这张图总结了本章的核心逻辑,你可以对照着复习:

激光雷达基础与ROS驱动知识体系 激光雷达工作原理 TOF(飞行时间法) 三角法 sensor_msgs/LaserScan 消息结构 ROS驱动:启动节点、配置参数 可视化:RViz + LaserScan/PointCloud2 后续章节:建图、定位、导航 核心流程:原理 → 消息 → 驱动 → 可视化 → 应用