3. 传感器与感知:激光雷达、深度相机、超声波传感器在避障中的应用

做机器人避障,说白了就是让机器人「看见」并「躲开」障碍物。

但「看见」这件事,远比想象中复杂。我刚开始做机器人那会儿,以为装个激光雷达就万事大吉了。结果呢?玻璃墙撞了三次,黑色地毯上的小物件一个都没检测到。嗯,从那以后我才明白——没有万能的传感器,只有合理的组合

3.1 激光雷达:精度之王,但也有脾气

激光雷达(LiDAR)是目前最主流的避障传感器。它通过发射激光束并测量反射时间,来获取周围环境的点云数据。

核心原理:TOF(Time of Flight)测距。激光发射→碰到物体反射→接收器接收。光速已知,时间一测,距离就出来了。

我个人习惯把激光雷达分成两类:

  • 单线激光雷达:只扫描一个平面。适合室内扫地机、AGV小车。便宜,但只能检测同一高度上的障碍物。
  • 多线激光雷达:扫描多个平面(16线、32线、64线)。适合自动驾驶、复杂环境。贵,但能构建3D环境。

我在项目中遇到过一个问题:激光雷达对透明物体几乎无效。玻璃、亚克力板,激光直接穿透,反射信号极弱。结果就是——机器人直直地撞向玻璃门。

避坑指南:我曾经在实验室里用单线激光雷达做避障,结果机器人把落地玻璃窗当成了「空旷区域」,差点冲出去。后来我加了一组超声波传感器专门检测透明障碍物,问题才解决。

激光雷达的另一个问题是镜面反射。光滑的金属表面、镜面,会让激光发生镜面反射,导致测距数据出现「飞点」——明明有障碍物,却显示为空旷区域。

3.2 深度相机:看得更全,但怕光

深度相机(RGB-D Camera)能同时提供彩色图像和深度信息。常见的方案有两种:

技术方案 原理 代表产品 优缺点
结构光 投射红外光斑,通过变形计算深度 Kinect v1、Intel RealSense 室内精度高,室外受阳光干扰严重
TOF 发射红外脉冲,测量飞行时间 Kinect v2、Azure Kinect 速度快,但分辨率较低

深度相机最大的优势是能获取三维信息。激光雷达只能扫一个平面,但深度相机能看到桌子的高度、椅子的形状、甚至悬空的障碍物。

但它的短板也很明显——怕强光。你想想看,在室外阳光下,红外信号直接被太阳光淹没,深度数据全是噪声。我有个朋友做户外巡检机器人,用了深度相机,结果一到中午就「瞎」了。后来他换成了激光雷达+超声波的组合。

我的经验:深度相机最适合室内、光照可控的环境。如果你要做室外避障,老老实实用激光雷达。如果预算有限,可以考虑单线激光雷达+深度相机的组合——激光雷达负责平面避障,深度相机负责检测悬空障碍物(比如桌沿、货架横梁)。

3.3 超声波传感器:便宜但「笨」

超声波传感器,原理很简单:发射超声波(人耳听不到的高频声波),碰到物体反射回来,通过时间差计算距离。

它的优点很突出:

  • 便宜:一个HC-SR04模块才几块钱
  • 不受光学干扰:玻璃、镜面、透明物体都能检测
  • 不怕灰尘和光照:在恶劣环境下依然可用

但缺点也让人头疼:

  • 精度低:一般只能到厘米级
  • 有盲区:太近的物体(<2cm)检测不到
  • 容易串扰:多个超声波同时工作会互相干扰
  • 波束角宽:你不知道障碍物具体在哪个方向,只知道「大概在这个扇形区域内」

为什么会这样?因为超声波是声波,它会扩散。发射出去的声波是一个锥形,而不是一束细线。所以超声波传感器只能告诉你「前方有障碍物」,但说不清「在左边还是右边」。

实用技巧:超声波传感器最适合做近距离补盲。比如在机器人底盘四周装4-6个超声波,专门检测30cm以内的障碍物。激光雷达和深度相机负责远距离,超声波负责「最后一米」的安全。

3.4 传感器融合:1+1>2

单一传感器都有缺陷。真正的工程实践,是多传感器融合

我常用的融合策略是这样的:

  1. 激光雷达做主传感器:提供全局的2D障碍物信息,用于路径规划和实时避障
  2. 深度相机做辅助:检测悬空障碍物和低矮障碍物(比如地上的书包、门槛)
  3. 超声波做补盲:检测透明物体和近距离障碍物

在ROS中,传感器融合通常通过message_filters实现时间同步,然后用costmap_2d把不同传感器的数据融合到一张代价地图中。

# 一个简单的传感器融合示例(Python伪代码)
import rospy
from sensor_msgs.msg import LaserScan, PointCloud2
from sensor_fusion import SensorFusion

def callback(laser_data, depth_data):
    # 激光雷达数据
    obstacles_2d = extract_obstacles_from_laser(laser_data)
    # 深度相机数据
    obstacles_3d = extract_obstacles_from_depth(depth_data)
    # 融合到代价地图
    costmap = fusion.update(obstacles_2d, obstacles_3d)
    # 发布给路径规划模块
    pub.publish(costmap)

# 时间同步
sub_laser = message_filters.Subscriber('/scan', LaserScan)
sub_depth = message_filters.Subscriber('/depth/points', PointCloud2)
ts = message_filters.ApproximateTimeSynchronizer(
    [sub_laser, sub_depth], queue_size=10, slop=0.1)
ts.registerCallback(callback)

注意:时间同步很重要。如果激光雷达和深度相机的时间戳对不上,融合出来的地图会出现「鬼影」——明明障碍物已经移动了,地图上还留着旧数据。

3.5 实战中的传感器选型建议

说了这么多,到底该怎么选?我根据项目经验,给几个参考方案:

应用场景 推荐传感器组合 预算范围
室内扫地机 单线激光雷达 + 超声波 x4 500-2000元
室内服务机器人 单线激光雷达 + 深度相机 + 超声波 x6 3000-8000元
室外巡检机器人 多线激光雷达 + 超声波 x8 + GPS 1万-5万元
自动驾驶 多线激光雷达 x2 + 毫米波雷达 + 摄像头 10万+

最后说一句:传感器只是工具,算法才是灵魂。再好的传感器,如果数据处理不好、融合策略不对,照样会撞墙。反过来,用便宜的传感器配合好的算法,也能做出不错的避障效果。

我见过有人用两个超声波传感器加一个Arduino,就做出了能自动避障的小车。虽然精度不高,但思路对了——先跑起来,再优化

重要提醒:无论用什么传感器,一定要做传感器标定。激光雷达和深度相机的外参(安装位置和角度)必须精确。我见过太多人跳过标定,结果融合出来的地图全是错位的。标定工具ROS里都有,别偷懒。