把传感器信号变成可供驾驶使用的世界状态——包括诚实地标出哪里没看到。
先看一次差点出事的两秒钟
回到我们那个路口。雨后傍晚,车在支路停止线前等着右转汇入主路。导航和定位已经把任务交代清楚了:目标车道在那儿,施工锥桶把入口向左挪了半个车道。现在系统要回答的是下一个问题:主路上到底有什么?
六路相机里,有一辆深色轿车正从主路的相邻车道向你要汇入的目标车道切过来——横向速度不大,但意图明显。就在这时,一辆公交车从它外侧经过,把它完全挡住了。整整两帧,相机里没有这辆轿车。
如果感知系统是"一帧一算"的——每帧独立跑一次检测,输出一堆检测框——那么这两帧里,深色轿车从输出里消失了。下游拿到的场景状态是:目标车道空闲。决策层据此判断可以起步汇入。第三帧,公交车过去了,轿车重新出现,位置比两帧前更深地插进了目标车道。
这就是本章要解决的问题的全貌。感知不是"识别出更多目标",而是回答三个层层递进的问题:
- 看到了什么——车、人、灯、车道线、锥桶各在哪里;
- 它们和几帧之前是什么关系——那辆轿车还是那辆轿车吗,它的速度是连续的吗;
- 哪里没看到——公交车后面不是"空",是"未知"。
第三个问题最容易被忽略,也最致命。整章读完你会发现,感知技术这十年的演进,很大程度上就是在把这三个问题一个一个补齐。
量产感知系统的四块拼图
先把结构摊开。教材按任务给感知列过六项(2D/3D 检测、跟踪、车道线/路沿、红绿灯、道路标识、Occupancy),但量产系统不是按六个任务组织的,而是按四个网络:
| 网络 | 负责什么 | 在我们的路口 |
|---|---|---|
| 动态检测网络 | 车、人、骑行者的 3D 检测 + 跟踪:位置、尺寸、朝向、速度、身份 | 主路车流、正在切入的深色轿车 |
| 静态感知网络 | 车道线、路沿、停止线、人行横道、道路标识——实时恢复局部道路结构 | 被锥桶改过的入口边界 |
| OCC 检测网络 | 空间占用状态:不问"是什么",只问"这块空间被占了没有" | 锥桶本身,以及公交车后面那块看不见的区域 |
| 红绿灯检测 | 信号灯的三维位置和颜色状态 | 右转信号灯 |
一个容易被低估的量产细节:就连红绿灯这一块,实际系统里也是两个模型。检测用 Sparse4D 这类 3D 检测模型——要知道那盏灯的三维位置,才能回答"这盏灯管不管我这条道";识别用 ShuffleNet 这类极轻量的分类模型——判断红黄绿,不需要重型网络。一重一轻,各干各的。
记住这个手感:感知系统不是一个大模型包打天下,而是四块拼图各有专门的解法,再共享同一套底层表征。本章下面四节,基本就是沿这四块展开:先讲共享表征怎么来(BEV),动态检测和跟踪顺着它讲;然后是静态感知、OCC,红绿灯的量产做法上面已经说完了。
从像素到俯视图:BEV 解决的是"平面不对"的问题
相机给的是图像平面:横竖都是像素。但驾驶需要的所有判断——距离多少米、在哪条车道、轨迹会不会冲突——都发生在俯视平面上。传统视觉任务是"图像平面进、图像平面出"(分割、检测都是如此),自动驾驶感知要做的是"图像平面进、俯视平面出"。这一步平面转换,就是 BEV(Bird's-Eye View,鸟瞰图)表征的全部含义。
难点在于相机没有深度。一个像素属于 10 米外的轿车还是 40 米外的货车,图像本身不告诉你。2020 年的 LSS 给出了一个此后被反复沿用的思路:既然深度不确定,就不猜一个值,而是为每个像素估一个深度分布——把每个像素"提升"(Lift)成一串沿视线方向排开的候选点,再用相机内外参把六路相机的所有候选点"拍"(Splat)到同一张俯视栅格上。从此车辆、车道、轨迹在同一个平面坐标系里说话。
这条路线跑通之后,改进立刻跟上。CaDDN 发现 LSS 的深度估计是无监督的、不稳定——可视化出来,特征在俯视图上呈放射状弥散;给深度加上监督之后,特征在物体真实位置聚成亮块。弥散还是聚焦,一组对比图就说清了"深度估计有没有监督"的差别。
顺便记一组数字,它是"感知范围"这个概念的具体形态:BEVDet 的 BEV 特征图是 128×128 的栅格,覆盖自车前后左右各 51.2 米,每格 0.8×0.8 米。有人问"这套感知方案范围多大、分辨率多少",答案就长这样。
到 2022 年,BEVFormer 换了个方向做同一件事:不再从图像"推"特征到俯视图,而是在俯视图上铺一层可学习的 query,让每个 query 主动"去"图像上采样自己需要的特征,并且把上一帧的 BEV 特征也融合进来,让时序成为表征的一部分。代价也很实在:BEVFormer 在 V100 上只能跑 2 帧每秒。学术榜单上的先进方案和车上能跑的方案之间,隔着一个数量级的算力差距——这个矛盾贯穿感知技术史,记住它,第七章讲端到端架构取舍时还会遇到。
对 2fps 的回答是 Sparse 路线:既然构造整张俯视特征图太贵,那就不构造。PETR 把三维位置信息直接编码进图像特征,让少量检测 query 直接在图像特征上工作;StreamPETR 更进一步,把时序融合从"特征图对特征图"改成"对象对对象"——只把每帧置信度最高的那批对象(比如 256 个)存进一个记忆队列,传给下一帧。传播几百个对象,比传播一整张 128×128 的特征图便宜得多。
现在回头看开场那两秒钟。深色轿车被公交挡住的两帧里,单帧检测器确实看不到它——但在对象级时序方案里,它上一帧的 query 还躺在记忆队列里,带着位置、速度和身份。遮挡结束后,新的检测结果和记忆里的它对上,ID 不变,横向速度曲线连续。下游看到的不是"一辆车消失又出现了一辆新车",而是"那辆车切过来了,而且切得更深了"。跟踪的价值不在正常帧,而在丢失的那几帧。
道路结构:地图给的和现场看的
感知的第二条战线是静态的:车道线、路沿、停止线、人行横道。这些信息有两个来源,而且两个来源正在此消彼长。
第一个来源是高精地图(HDMap),提前采集、离线制作。它的要求有多高?课件给了两个硬指标:建图误差不超过 ±30 厘米,制图自动化率要达到 95% 以上——剩下 5% 靠人工修。高速和高架还好,要覆盖到城区,就意味着持续的采集、制作和更新成本。总结成一句话:成本高、鲜度低、范围不足。我们场景里那排施工锥桶就是"鲜度"问题的具象:地图说入口在这里,现场昨天挪了。
第二个来源是在线感知:车开到哪儿,实时把局部道路结构"画"出来。这条路线的演进很快——HDMapNet(2021)用分割的思路做,VectorMapNet(2022)改成直接输出矢量点集,MapTR(2022)把它做成了端到端。MapTR 解决的一个问题特别能说明"工程里的真问题长什么样":一条车道线,从左往右描点和从右往左描点,是同一条线,但对网络来说是两个不同的答案。强制规定顺序,网络就得浪费容量去学一个不存在的"正确方向"。MapTR 的做法是让所有等价的描点顺序都算对——正序逆序、闭合多边形的任意起点,全部接受。歧义消除了,训练就顺了。
于是现在的分工是:标准导航地图指方向(A 到 B 的路网拓扑,便宜、够新),在线感知画细节(实时局部车道结构,跟着现场走)。我们的系统正是这样处理锥桶的:地图先验说入口在原位,在线建图看到边界向左挪了半个车道,以现场为准,把修正后的入口交给下游。
检测框装不下的世界:Occupancy
检测框有一个隐藏前提:它只认识类别表里有的东西。车、人、骑行者、锥桶——这些常见类别没问题。但道路上还有清扫机器人、横穿的狗群、掉落的沙发、异形的道路养护车。它们出现频率低、没有固定形状,类别表永远列不全。这类目标有个统称:通用障碍物(GOD, General Obstacle Detection)。在很长一段时间里,通用障碍物只能靠激光雷达做几何聚类,噪声很大。
Tesla 把这个问题重新定义成了一个可学习的任务,就是 Occupancy:不再问"这是什么",只问"这块空间被占了没有"。把车周空间切成三维小格子(voxel),每个格子输出一个状态。关键是,状态不是两种,是三种:
- occupied——有东西,不管它是什么;
- free——确认是空的;
- unobserved——没看到,不知道。
第三种状态直接回答了开场的问题。公交车后面那块区域,单帧检测的世界观里是"没有检测框 = 空闲",Occupancy 的世界观里是"unobserved = 不许当作空闲"。决策层拿到的信息从"可以走"变成了"那里是盲区"——后面第五章会看到,这一字之差就是"过早起步"和"再等一帧"的差别。
这个任务的成本也值得记一笔:给 nuScenes 的 850 个场景补一套 Occupancy 标注,先用算法自动生成伪标签,再人工修正,共花了约 4000 人工时,成本 10 到 15 万元——而且这只是一个学术数据集的量级。纯人工标注三维栅格不可行,"自动生成 + 人工修"是唯一现实的路径。另一个容易踩的坑是可见性:同一个格子可能激光雷达看得见、相机看不见(或者反过来),标注和评测时要分开定义两套可见性,否则你会惩罚模型"没预测出它根本不可能看到的东西"。
感知最终交付什么
把四条线收拢。这一章开始时,系统只有定位、地图和导航给的先验;现在,感知交付给下游的是一份结构化的场景状态:
- 主路车流和深色轿车的检测框、身份和速度——包括被遮挡两帧后依然连续的那条横向速度曲线;
- 信号灯的位置和颜色状态;
- 被锥桶修正过的入口边界和车道结构;
- 一张 Occupancy 栅格,其中公交车后方的区域被诚实地标为 unobserved;
- 以及以上所有输出的置信度。
注意这份交付物里没有"可以汇入"或"不能汇入"——那不是感知的职责。感知的职责是把世界状态说清楚,包括说清楚哪里没看清。一个把"没检测到"当成"不存在"的系统,和一个把"未观测"如实上报的系统,用的可能是同一批模型,差别只在表征里有没有给"不知道"留位置。
但"世界现在什么样"说清楚了,还有一个问题完全没碰:那辆切进来的轿车,下一秒会继续切,还是会缩回去?主路后车会让,还是不会让?场景状态是预测的输入,不是决策的答案。下一章,把当前场景延伸成多个可能的未来。
本章速查
| 概念 | 一句话 |
|---|---|
| 感知四网络 | 动态检测(检测+跟踪)、静态感知(车道线/路沿/标识)、OCC、红绿灯检测 |
| BEV | 把多相机特征投到以自车为中心的俯视栅格,让检测、地图、规划在同一平面坐标系工作 |
| LSS | 为每个像素估深度分布(Lift),按内外参拍到 BEV 栅格(Splat);深度不确定就保留分布 |
| Dense vs Sparse | 建不建完整 BEV 特征图;BEVFormer(Dense)V100 仅 2fps,PETR/StreamPETR(Sparse)为车载实时而生 |
| 对象级时序 | 只传播 top-K 对象的 query 而非整张特征图;遮挡时靠记忆队列维持目标身份 |
| HDMap 成本账 | 误差 ≤±30cm、自动化率 ≥95%;成本高、鲜度低、范围不足 |
| 在线建图 | HDMapNet→VectorMapNet→MapTR;MapTR 让点集的所有等价顺序都算对 |
| Occupancy 三态 | occupied / free / unobserved;把"不知道"从表征层面和"空闲"区分开 |
| 标注成本 | nuScenes 补 Occupancy 标注约 4000 人工时、10-15 万元,Auto & Human |
材料来源
| 课程 | 章节 | 页码 | 用在哪 |
|---|---|---|---|
| B | B-02 端到端感知:BEV Encoder | p6, p9-p24 | 感知任务清单、LSS/CaDDN/BEVDet/BEVFormer、±51.2m 规格、V100 2fps |
| B | B-02 端到端感知:BEV Encoder | p27-p35 | PETR、StreamPETR 记忆队列与对象级时序 |
| B | B-03 端到端感知:动静态感知 Decoder | p4-p29, p31-p37 | Sparse4D、HDMap 成本账(p12)、MapTR、Occupancy 三态与标注成本(p24)、Planner 输入清单(p37) |
| A | A-01 端到端任务概述 | p14-p20 | 感知三模块、交通灯双模型(Sparse4D+ShuffleNet, p17)、感知在端到端中的接口变化 |