1. 感知系统概述:传感器选型与布局
大家好,我是老张。在自动驾驶这个行当摸爬滚打了快十年,踩过的坑比吃过的盐还多。今天咱们聊聊感知系统的第一课——传感器选型与布局。说实话,这一步要是走偏了,后面算法调得再好也白搭。
1.1 传感器选型:各有各的脾气
先说说传感器。很多人觉得传感器越多越好,其实不是。我见过一个项目,堆了十几个摄像头,结果数据量太大,算力根本扛不住。选型这事儿,得看你的应用场景和成本预算。
摄像头
摄像头是感知系统的眼睛。它便宜、信息丰富,但怕黑、怕强光、怕雨雾。我个人习惯,L2级辅助驾驶用2-3个前视摄像头就够了,L4级至少得6个以上,环视加前视加侧视。
激光雷达
激光雷达是感知系统的"尺子"。它能精确测距,生成点云数据。但贵,而且怕雨雪天气。我记得2021年有个项目,激光雷达在暴雨天直接罢工,点云全是噪点。
选激光雷达,主要看线数和视场角。16线够用吗?说实话,做L4不够。我建议至少32线起步,64线更稳。当然,现在固态激光雷达便宜了,16线固态也能凑合。
毫米波雷达
毫米波雷达是感知系统的"老黄牛"。它不怕雨雾,测距远,但分辨率低。我经常跟团队说,毫米波雷达是"知道有东西,但不知道是什么东西"。
毫米波雷达的选型,主要看频段和角度分辨率。77GHz比24GHz好,角度分辨率小于5°的才算合格。嗯,这里要注意,毫米波雷达的俯仰角也很重要,不然过个减速带就丢目标了。
超声波雷达
超声波雷达是感知系统的"贴身保镖"。它只负责近场,3米以内。自动泊车、盲区监测全靠它。便宜,但怕脏、怕冰、怕雪。
我建议超声波雷达装6-8个,前后各4个。别省这个钱,我见过一个项目只装了4个,结果倒车时侧面刮了柱子。
1.2 传感器布局:位置决定命运
传感器选好了,怎么装?布局这事儿,说白了就是"视野最大化、盲区最小化"。我画了一张图,你们看看。
你看,前视摄像头装在挡风玻璃后面,激光雷达放车顶,毫米波雷达藏在前保险杠里。超声波雷达均匀分布在前后保险杠上。这样布局,视野重叠区最大,盲区最小。
1.3 感知系统架构设计
传感器装好了,怎么组织成一个系统?架构设计这事儿,说白了就是"数据怎么流、任务怎么分、算力怎么配"。
我常用的架构是分层式:
- 数据采集层:传感器原始数据,摄像头图像、激光雷达点云、毫米波雷达点迹、超声波雷达距离。
- 预处理层:去噪、校正、时间戳对齐。这一步很关键,我见过数据没对齐导致融合结果全是错的。
- 感知算法层:目标检测、跟踪、语义分割、可行驶区域识别。
- 融合层:多传感器融合,输出目标列表、障碍物信息、车道线信息。
- 决策输出层:给规划控制模块发消息。
你想想看,如果数据采集层和预处理层没做好,后面的算法再牛也白搭。我习惯在预处理层加一个"数据质量监控"模块,一旦发现传感器异常,立刻报警。
1.4 数据流与时间同步
数据流和时间同步,这是感知系统里最容易出问题的地方。为什么?因为每个传感器的采样频率不一样。摄像头30fps,激光雷达10fps,毫米波雷达20fps,超声波雷达50fps。你怎么把它们对齐?
我常用的方法是"硬件触发+软件插值"。硬件触发就是用一个PPS信号同时触发所有传感器,保证它们在同一时刻开始采样。软件插值就是根据时间戳,把不同频率的数据插值到同一个时间点上。
核心要点:时间同步的精度直接影响融合效果。我建议时间戳精度至少达到1ms,否则融合后的目标位置会偏差很大。
举个例子,摄像头在t0时刻拍到一辆车,激光雷达在t0+5ms时刻扫到同一辆车。如果时间戳没对齐,你会以为这是两辆车。我曾经在一个项目中,因为时间戳差了10ms,导致融合后的目标位置偏差了0.5米。你想想看,0.5米的偏差在高速上意味着什么?
数据流方面,我建议用"发布-订阅"模式。每个传感器节点发布自己的数据,感知算法节点订阅需要的数据。这样解耦,方便调试。我习惯用ROS2,它的DDS机制天然支持这种模式。
# 伪代码示例:数据流发布-订阅
class CameraNode:
def publish(self):
while True:
img = capture_image()
stamp = get_timestamp()
publish("/sensor/camera", img, stamp)
class LidarNode:
def publish(self):
while True:
pcd = capture_pointcloud()
stamp = get_timestamp()
publish("/sensor/lidar", pcd, stamp)
class FusionNode:
def __init__(self):
subscribe("/sensor/camera", self.camera_callback)
subscribe("/sensor/lidar", self.lidar_callback)
def camera_callback(self, img, stamp):
# 缓存图像
self.img_buffer[stamp] = img
def lidar_callback(self, pcd, stamp):
# 找到最近时间戳的图像
nearest_img = find_nearest(self.img_buffer, stamp)
# 执行融合
fused_result = fuse(pcd, nearest_img)
嗯,这里要注意,数据缓存不能太大,否则内存会爆。我一般只缓存最近1秒的数据,超过1秒的直接丢弃。
| 传感器类型 | 典型频率 | 数据量 | 时间同步方式 |
|---|---|---|---|
| 摄像头 | 30 fps | ~100 MB/s (4MP) | PPS硬件触发 |
| 激光雷达 | 10 fps | ~50 MB/s (64线) | PPS硬件触发 |
| 毫米波雷达 | 20 fps | ~1 MB/s | 软件时间戳 |
| 超声波雷达 | 50 fps | ~0.1 MB/s | 软件时间戳 |
最后说一句,感知系统不是堆硬件,而是系统工程。传感器选型、布局、架构、数据流,每一步都得精心设计。我见过太多项目,硬件堆得豪华,但系统一跑就崩,就是因为这些基础没打好。
好了,第一章就聊到这儿。记住,感知系统的核心是"看得准、算得快、融得稳"。下一章咱们聊聊目标检测的那些坑。