3、传感器基础:激光雷达(LiDAR)工作原理与数据读取

各位同学,咱们今天聊聊激光雷达。说实话,在机器人感知这块,LiDAR 是我个人最偏爱的传感器。为什么?因为它直接、稳定、不跟你玩虚的。摄像头受光照影响大,超声波精度太糙,而激光雷达——你给它一束光,它告诉你一个精确的距离。就这么简单。

3.1 激光雷达是怎么测距的?

激光雷达的核心原理,说白了就是「飞行时间法」(Time of Flight, ToF)。你发射一束激光脉冲,打到物体上反射回来,接收器捕获回波。光速是已知的,那么距离 = 光速 × 飞行时间 / 2。

嗯,这里要注意:除以 2 是因为光走了个来回。我在项目里见过新手直接拿飞行时间乘光速,结果测出来的距离翻了一倍,还跑来问我为什么地图对不上……

核心公式:

d = (c × Δt) / 2

其中 d 是距离,c 是光速(约 3×10⁸ m/s),Δt 是激光脉冲的往返时间。

你想想看,如果测距精度要 1 厘米,时间测量精度就得达到 67 皮秒。这可不是闹着玩的,所以激光雷达内部用的都是高速计时芯片。

3.2 单线 vs 多线:你该选哪个?

我刚开始做机器人那会儿,市面上主流的还是单线激光雷达。比如经典的 RPLIDAR A1,转一圈扫一个平面,得到 360° 的距离数据。适合做室内导航、避障。

后来做室外项目,发现单线根本不够用——地面有个坑它扫不到,头顶有根树枝它也看不见。于是换上了 16 线、32 线的 Velodyne。多线 LiDAR 相当于把多个单线雷达上下堆叠,每一层扫一个平面,合起来就是一个三维点云。

类型 线数 典型应用 价格区间
单线 1 室内导航、扫地机 几百 ~ 两千
多线(低端) 4 ~ 16 AGV、服务机器人 几千 ~ 两万
多线(高端) 32 ~ 128 自动驾驶、测绘 几万 ~ 几十万

我个人建议:如果你只是做课设或小项目,先拿单线练手。别一上来就烧钱买 64 线,数据量大了你处理不过来,还容易把电脑跑死。

3.3 ROS 中如何读取 LiDAR 数据?

在 ROS 里,激光雷达的数据通过 sensor_msgs/LaserScan 消息发布。你订阅这个 topic,就能拿到一帧扫描数据。结构如下:

Header header
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    # 反射强度数组(可选)

举个例子,我常用的 RPLIDAR A2,angle_min 是 0,angle_max 是 2π,angle_increment 大约是 0.017 rad(约 1°)。也就是说 ranges 数组里有 360 个值,每个值对应一个方向上的距离。

小技巧: 如果你发现 ranges 里出现 Inf 或 NaN,别慌。那说明这个方向没有检测到物体(比如对着天空或超出量程)。处理时记得做过滤,否则后续算法会崩。

3.4 实战:写一个 LiDAR 数据订阅节点

咱们直接上代码。下面是一个简单的 ROS 节点,订阅 /scan topic,打印出正前方(0° 方向)的距离值。

#!/usr/bin/env python3
import rospy
from sensor_msgs.msg import LaserScan

def scan_callback(msg):
    # 取正前方的距离(索引为 0)
    front_distance = msg.ranges[0]
    rospy.loginfo("正前方距离: %.2f 米", front_distance)

def main():
    rospy.init_node('lidar_reader', anonymous=True)
    rospy.Subscriber('/scan', LaserScan, scan_callback)
    rospy.spin()

if __name__ == '__main__':
    main()

这段代码很简单,但我在实际项目中踩过一个坑:msg.ranges[0] 不一定对应正前方。因为有些雷达的 0° 是朝后的,或者朝左的。你得先看雷达的安装方向,或者用 angle_min 算一下偏移。

避坑指南: 我曾经在调试一款国产雷达时,发现正前方距离总是显示 0.3 米。查了半天,原来是雷达的 0° 指向了机器人本体。所以拿到新雷达,第一件事就是转一转它,看看数据变化对不对。

3.5 数据可视化:看一眼你的 LiDAR 在干嘛

光看数字不够直观。ROS 里用 rviz 可以实时显示激光扫描数据。你只需要:

  1. 启动你的 LiDAR 驱动(比如 roslaunch rplidar_ros rplidar.launch)
  2. 运行 rviz
  3. 添加一个 LaserScan 显示,topic 选 /scan

你会看到一圈红色的点,代表雷达检测到的障碍物轮廓。如果点云是乱的,先检查雷达是不是被遮挡了,或者电机转速是不是稳定。

我个人习惯在调试阶段同时打开 rviz 和终端打印。一个看宏观,一个看细节,两边对照着来,问题定位快得多。

3.6 本章知识体系

下面这张图帮你理清激光雷达的核心逻辑:

激光雷达知识体系 飞行时间法 (ToF) 单线 LiDAR 多线 LiDAR sensor_msgs/LaserScan sensor_msgs/PointCloud2 室内导航 / 避障 SLAM / 自动驾驶 从原理到数据格式,再到实际应用,层层递进

这张图把本章的核心脉络串起来了。你从 ToF 原理出发,理解单线和多线的区别,然后掌握 ROS 里的数据格式,最后落地到实际应用。每一步都有我踩过的坑和总结的经验,希望能帮你少走弯路。

好了,这一节就到这里。记住:激光雷达是你的「眼睛」,但眼睛再好,也得学会怎么看数据。多动手写代码,多盯着 rviz 看,慢慢就有感觉了。

可可精品资料库