☰
无人驾驶感知进阶:从点云到多传感器融合的工程实践
2026/10/21 3:13:41 网站建设 项目流程

1. 进阶篇开篇:为什么感知是无人驾驶里"最难啃的骨头"

很多人以为做无人驾驶,重点在于控制算法和路径规划,车辆只要能感知到"前方有东西"就能躲开。实际真正上手跑过 Apollo 仿真、或者在实车上盯过感知模块输出的人,都会明白一件事:感知是整个自动驾驶链路里不确定性最大、最容易"翻车"、也最依赖工程沉淀的部分。

我在学完 Apollo 入门篇之后,对它的总体架构已经有了基本印象——高精地图、定位、感知、预测、规划、控制、底盘通信,每个模块各司其职。但进入进阶篇的感知部分之后,才发现之前对"感知"的理解太浅了。

入门篇里传感器只需要在仿真环境里给出干净的障碍物坐标,到了进阶篇,你要处理的是真实世界里的点云噪音、曝光过度的相机画面、拉链式并排行驶的重型卡车、黄昏时逆光下的行人……每一个案例都在提醒你:感知不是"识别出物体"那么简单,而是要在一帧一帧不完美的数据里,逼近一个可用的世界模型。

这篇笔记我重点整理了感知部分的几个核心模块:

  • 从传感器数据到障碍物输出的整体链路;
  • 激光雷达感知的预处理、分割与检测;
  • 视觉感知的红绿灯、车道线、可行驶区域;
  • 多传感器融合的匹配逻辑与ID管理;
  • 还有部署过程中真正折磨人的工程细节。

如果你也在跟 Apollo 课程,这篇笔记比较适合作为你的"第二遍阅读提纲"——第一遍跟着课程视频走,第二遍再带着笔记里的问题去翻源码和调试工具。

2. 感知整体链路拆解:从传感器原始数据到下游可用的障碍物结果

2.1 感知模块在整套架构里的位置

在 Apollo 的软件框架里,感知模块位于传感器驱动和下游预测/规划模块之间。你可以把它想象成一个流水线的"质检工位":

传感器(激光雷达、相机、毫米波雷达)负责采集物理世界的信息,感知模块负责把这些信息加工成统一的、有时间戳的、带语义的"道路物体清单",交给预测模块去推测这些物体接下来要干什么,再由规划模块决定车辆该怎么开。

这里关键是"统一"两个字。三个传感器的数据格式完全不一样:

  • 激光雷达输出的是点云——一堆带有空间坐标和反射强度的点;
  • 相机输出的是图像——二维像素矩阵;
  • 毫米波雷达输出的是目标级数据——直接给出目标的距离、速度、角度。

感知模块要做的第一件事,并不是"识别",而是把不同传感器得到的信息对应到同一个物理目标上。如果这一步没做好,下游收到的可能是一份自相矛盾的障碍物清单:激光雷达说前方5米有静止物体,视觉说前方5米有行人,融合模块如果不处理这种冲突,就会导致决策模块无所适从。

2.2 感知输出的核心数据结构:障碍物与红绿灯状态

课程里反复强调一个概念:感知模块的产出不是一个"画面",而是一个"结构化描述"。用 Apollo 里的术语来说,就是障碍物(Obstacle)和交通信号灯状态(TrafficLight)。

一个障碍物条目包含的内容很直接:

  • 唯一ID(跟踪用,确保是同一个物体);
  • 类型(小轿车、卡车、行人、自行车、未知);
  • 三维框的位置、大小、朝向;
  • 速度与加速度;
  • 与自车的相对距离;
  • 置信度。

红绿灯状态则包含灯组的位置、颜色状态(红/黄/绿/黑/未知)、以及对应的置信度。注意这里的"位置"不是相机图像上的像素位置,而是地图坐标系下的三维位置——这一点特别容易被新手忽略,感知不仅要识别出"前方有红灯",还要告诉规划模块"这个红灯在哪条车道线旁、距离多远"。

2.3 相机、激光雷达、毫米波雷达的职责分配

进阶篇课程没有让人只依赖某一种传感器,而是强调各传感器各司其职、互为冗余。我整理了一下它们的分工定位:

传感器优势劣势在Apollo感知里的主要职责
激光雷达距离准、三维信息直接、不受光照影响雨天/雾天性能下降、成本高、点云稀疏时目标容易中断三维目标检测、可行驶区域边界、目标测距
相机语义信息丰富、能识别颜色和纹理强光/逆光/暗光容易失效、单目距离估算误差大车道线、红绿灯、行人/交通标志、2D检测
毫米波雷达全天候工作、直接测速、成本低角度分辨率低、点迹稀疏、难以识别静止目标类别目标测速、远距离感知、雨雾天气兜底

我在实车调试时有个体会:三个传感器同时丢掉同一个近距离目标的情况极少,但任意两个同时失效就很容易出问题。所以 Apollo 感知模块在设计时,并没有简单地把所有数据丢进一个"大网络"里,而是分别做检测、再做融合,这样可以在单个传感器失效时平滑降级。

3. 激光雷达感知的核心链路:从点云预处理到三维目标检测

3.1 预处理的第一步:地面滤除不是可选项

激光雷达一帧点云里,绝大多数点都落在地面上。如果不对地面点做处理,目标检测和聚类会面临两个灾难性问题:

  • 地面点和障碍物点混在一起,聚类算法会把路面和路沿连成一片;
  • 远处低矮物体的点云会被地面点"淹没",目标根本分割不出来。

Apollo 里经典的做法是基于高度和平整度做地面滤除。课程里提到的思路很朴素:一个点如果在一个局部区域内比周围的点低很多,它大概率属于地面;如果相邻点的高度差突变剧烈,那这附近大概率有障碍物边界。

实际操作中,不同雷达线束密度差异很大——64线雷达地面点非常密集,4线雷达则稀疏很多。Apollo 的做法并不是只在某一个固定高度阈值上切一刀,而是通过动态估计地面平面模型来分离地面点。你会发现同样的路面,在上下坡时如果还用一个固定高度阈值,结果会非常难看。

3.2 ROI 区域过滤:算力很贵,不管不该管的点

激光雷达能看到的范围很广,但车辆真正需要关心的区域主要集中在自车周围的一定范围。Apollo 课程中专门提到了ROI(Region of Interest)过滤这一步,也就是根据高精地图信息,把点云里位于道路边界之外的点直接裁掉。

这一步的作用有两个:

  1. 减少计算量——与其让检测网络对所有点做推理,不如先裁掉大部分无关点;
  2. 减少误检——路边的树木、护栏、行人道上的非机动车,如果不在当前车道的ROI里,优先级就会被降低。

你还得注意 ROI 不能设置得太紧。窄路、施工改道、临时路障都会让车辆实际运行区域偏离高精地图标定范围。课程里给的建议是:ROI 范围应该是动态的,低速复杂场景下适当扩大,高速结构化道路下可以收紧。我在自己跑仿真时对这一点感受很深:ROI 范围过小,车辆在临近路口的右转场景经常会丢掉路沿上的锥桶,导致规划模块觉得"无路可走"。

3.3 点云分割与目标检测:聚类、PointPillars、CenterPoint

在点云完成了地面滤除和 ROI 过滤之后,就进入了核心检测阶段。Apollo 提供了两条技术路线,课程里都有涉及:

第一条是传统聚类路线。对点云做密度聚类(类似欧几里得聚类),把空间上聚集的点归为一类,再给每个聚类拟合一个三维包围框。这条路线的优点是简单、可控、CPU友好,缺点是聚类参数对场景敏感——密度阈值设大了会把一辆车和旁边的行人合成一团,设小了又容易把一个卡车拆成好几块。

第二条是基于深度学习的点云检测路线。Apollo 里集成过 PointPillars 这类基于体素的检测网络,后来也逐步演进到 CenterPoint 这类 anchor-free 方案。PointPillars 的思路是把三维点云切成一堆竖直柱体(pillar),每个 pillar 内聚合点云特征,再丢给 2D 卷积网络处理,最终输出三维框。CenterPoint 则更进一步,不依赖预设 anchor 框,而是直接预测物体中心点,再回归其他属性。

这里我要多说一句:课程里点云检测部分的重点不是让你从零训练模型,而是帮你理解"检测结果如何映射回真实坐标"。网络输出的三维框中心通常是在体素坐标或自车坐标下,要转换到世界坐标系,必须串联外参、内参、时间戳对齐等一整套变换。很多人刚开始调试时觉得"模型识别率够了",一上车就崩,多半是坐标系转换在某个环节出了问题。

3.4 点云感知的边界情况:稀疏、遮挡、雨雾

激光雷达并不是万能的。课程里有几个专门讨论点云感知失效的场景:

  • 远距离目标点云稀疏:一辆 50 米外的小轿车可能只扫到几个点,聚类算法很难把它和噪声区分开,深度模型也容易漏检。这时候就需要靠视觉融合或者毫米波雷达补位。
  • 近距离大目标遮挡:一辆卡车斜停在路边,它旁边的行人可能完全被遮挡,点云里根本没有任何信息。感知模块输出不了"看不见的东西",只能通过预测模块的轨迹推断来补。
  • 雨雾天气:雨滴和雾霾会产生大量噪声点,地面滤除和聚类都会变得不稳定。Apollo 的做法通常是降低对激光雷达远距离输出的信任度,更多依赖毫米波雷达。

我的建议是:不要试图用单一传感器解决所有问题,学会看"传感器可信度"这个隐藏维度。融合模块之后的输出里,每种传感器对目标的检测置信度其实是分开保留的,这为下游决策提供了重要的判断依据。

4. 视觉感知:不仅仅是"认出物体"

4.1 2D 检测与 3D 检测的配合

相机在 Apollo 感知体系里的作用,绝不仅仅是"看"到什么就输出什么。它主要负责几类任务:

  • 2D目标检测(图像上画出障碍物的框)
  • 3D目标检测(从单目或多目图像回归障碍物的三维尺寸和位置)
  • 车道线检测
  • 红绿灯检测与识别
  • 可行驶区域分割

2D 检测目前已经比较成熟。Apollo 里常用的做法是基于深度学习的检测网络(比如 YOLO 系列或其变体)在图像上框出目标,然后通过相机的外参和地面几何约束,把 2D 框投影到三维空间。

但注意,单目 3D 检测的精度天然有限。同一个 2D 框,物体可能是"近处的小轿车",也可能是"远处的卡车"。课程里明确指出了这一点:单目 3D 检测主要用来提供语义类别和粗略位置,精确测距还是要靠激光雷达或双目视差。

4.2 红绿灯识别的难点:定位、时序、颜色

红绿灯模块是进阶篇里一个很有意思的案例,因为它的难点不在"识别红色还是绿色",而在时空关联。

首先是定位问题:相机图像里的红绿灯只是一个很小的色块,而且同一个路口的红绿灯可能有多组,分别对应不同车道。感知模块需要结合高精地图,先预测当前车道上哪个红绿灯跟自己相关,再在图像里找到它。

然后是时序问题:红绿灯有周期,相机每一帧都在变,如果某一帧识别成了黄色,下一帧识别成了红色,这中间到底是切换还是误检?Apollo 的做法是引入一个小的状态机,要求连续多帧确认同一个状态才输出切换结果,避免单帧误检导致决策模块急刹车。

最后是颜色识别本身:红色在夜晚会偏暗,黄色在强光下会偏白,不同相机的自动白平衡还会影响颜色输出。课程里的经验是:在训练数据里要故意加入大量不同天气、不同时长、不同相机的红绿灯样本,否则模型在实车上会给你"惊喜"。

我自己跑仿真时遇到过一种情况:路口的红绿灯在画面里只占很小区域,视觉模型漏检了,但地图上的信号灯位置是已知的。Apollo 的做法在这种情况下会把该信号灯状态标成"未知",宁可让规划模块保守处理,也不会硬猜一个颜色。这种"不确定就说不确定"的设计哲学,我觉得是感知工程里特别重要的一课。

4.3 车道线与可行驶区域:给规划一条"路权"边界

车道线检测也是视觉感知的核心任务。它不像障碍物检测那样输出一个框,而是输出一系列曲线点集,描述车道线的位置、类型(实线、虚线、双黄线)和置信度。

可行驶区域分割则更偏向图像分割任务——把画面里的道路区域和路牙、绿化带区分开,输出一个区域掩码,再投影到自车坐标系。课程里提醒了一个细节:可行驶区域的边界不能直接当作障碍物边界用。道路边缘可能有一小段草皮,也可能有一块低矮路缘石,图像分割模型看到的是"非路面"就认为是边界,但实际车辆可能压过去也没事。所以规划模块通常会把可行驶区域边界往里缩一段距离,预留安全裕量。

5. 多传感器融合:ID跟踪与置信度管理的较量

5.1 为什么需要融合:单传感器的"盲区"各不相同

融合(Fusion)模块是感知部分的"总集成商"。它的输入是激光雷达检测结果、视觉检测结果、雷达目标数据,输出是一份统一且一致的障碍物列表。

融合的难点不在"同一个物体被三个传感器都检测到时取平均值",而在一个物体只被其中一个传感器检测到时怎么办。比如:

  • 视觉检测到行人,但激光雷达因为遮挡没看到;
  • 毫米波雷达检测到远处快速接近的车辆,但视觉因为逆光没看到;
  • 激光雷达检测到静止的交通锥,但视觉因为目标太小没看到。

每一种情况都意味着:如果直接丢弃单一传感器结果,就可能漏掉关键目标;如果直接采信单一传感器结果,又可能把"误检"带进决策链路。

5.2 融合策略:从匹配到跟踪的生命周期管理

Apollo 的融合模块大体上做了三件事:

  1. 匹配(Association):判断两帧之间的障碍物是否属于同一个物理目标。常用的方法包括基于距离、基于 IOU(交并比)、基于特征相似度的匹配。
  2. 状态估计(Estimation):对匹配成功的障碍物,用滤波算法(比如卡尔曼滤波)融合多传感器的测量值,估计出更稳定的位置、速度、加速度。
  3. 生命周期管理(Track Management):维护每个障碍物的 ID,知道它什么时候"出生"、什么时候"消失"。

课程里专门提到,ID 稳定性是融合模块的重要指标。规划模块在做出"避让"决策时,依赖的是障碍物的一段历史轨迹,如果 ID 频繁跳变——同一辆车一会儿是 ID12 一会儿是 ID57——预测模块就无法建立稳定轨迹,决策自然就会抖动。

5.3 传感器失效与降级策略

实车里传感器一定会失效。镜头被泥点遮住、雷达通信偶发丢包、激光雷达电机故障……Apollo 是怎么处理的?课程里讲了几个原则。

  • 降级而不是中断:一个传感器失效时,融合模块不会报"感知故障"退出,而是自动切换到剩余传感器的结果,并降低整体置信度。
  • 超时判定:同一个目标如果连续多帧没有被任何传感器更新,就会进入"推测队友"状态,位置速度按照上一帧的趋势外推一段短时间,再标记为"消失"。这里的时间窗口很关键,太短会导致目标忽隐忽现,太长会掩盖真正的危险。
  • 异常状态上报:感知模块自身无法处理的情况(比如主机算力过载、传感器时间不同步)会上报到系统层面,由安全模块决定是否降速靠边。

我在这部分最大的收获是意识转变:感知不是"识别得越多越好",而是"在不确定中维持一份尽量可信的共识"。融合模块的真正价值,是让决策模块始终有一份可用的数据,哪怕这份数据带上了"置信度不高"的标签。

6. 实际调试感知模块时容易踩的坑

6.1 坐标系和时间戳是万恶之源

我接触 Apollo 感知以后,踩过最大的坑就是坐标系。至少遇到过三次"检测结果看起来对、但实际上在乱跳"的问题,最后定位到都是因为某个坐标系用错了。

先说坐标系。感知模块内部至少存在四类坐标:传感器坐标、车辆坐标、世界坐标、地图坐标。传感器外参的作用,就是把点云从激光雷达坐标系转到车辆坐标系。外参标定的微小误差,在远处会被放大成很大的位置偏差。你拿一个 10 米外的路障验证外参,可能只差了 2 厘米;同样的外参误差放到 80 米外的车辆上,位置可能偏了半米。

再说时间戳。不同传感器、不同处理链路的数据,到达融合模块的时间都不一样。如果直接拿一帧 100ms 前的激光雷达数据和一帧 20ms 前的视觉数据做匹配,高速场景下的同一辆障碍车可能已经在空间上移动了 1~2 米。所以 Apollo 里才有一大堆时间对齐的机制。每次调试感知问题,先检查时间戳是不是对齐的,通常能排除一半的"诡异现象"。

6.2 可视化调试:别只盯着数值

课程里花了不少时间讲可视化工具的使用,我当时觉得"不就是画几个框么",后来发现可视化对于感知调试是不可替代的。

一个推荐的做法是:在回放数据里同时显示点云俯视图、相机图像、检测输出的 3D 框和 ID 号、以及速度矢量。这样你能一眼看出问题到底出现在哪个环节:

  • 如果点云里目标很清晰,但网络没检测出来——检查模型部署和输入预处理;
  • 如果网络检测出了目标但 3D 框位置偏移——检查坐标变换和外参;
  • 如果 3D 框位置正确但 ID 一直在跳——检查融合匹配阈值和跟踪生命周期管理。

很多问题靠读代码是看不出来的,但看到可视化的一瞬间就明白了。

6.3 参数调优的顺序:先链路后算法

初学者拿到感知模块,特别喜欢直接调模型阈值。但我自己的经验是:先把整个链路跑通、跑稳,再回头调单点参数。

比如检测网络输出的置信度阈值,调高了会漏检,调低了会误检。但在实际项目里,这个阈值往往不是最先要调的——你应该先确认数据流一遍畅通、时间戳对齐、坐标系没问题,然后才轮到它。如果数据流没跑通,就算把模型调到最优,融合模块输出的障碍物列表也照样是乱的。

6.4 真车测试和仿真测试的差异

最后提醒一下:仿真环境里跑得再好,实车测试仍然会发现新问题。仿真数据没有传感器噪声、没有曝光问题、没有震动和延迟,感知算法在仿真环境里的表现通常会比实车"好看"。真正让我觉得涨经验的,还是在实车或者描述精确的回放数据上反复看感知模块在各种边缘场景下的表现。

7. 感知进阶的学习路线建议

如果你跟我一样,在入门篇之后打算深入感知部分,我的建议是按照"广度优先、深度随后"的顺序学:

  1. 先建立全景图——弄明白数据从传感器到融合输出的每一步,重点是数据的走向和模块间的接口;
  2. 再挑一个方向深入——要么做点云感知,要么做视觉感知,要么做融合,把一个方向的核心算法学透,而不是每个方向都浅尝辄止;
  3. 多看感知失败案例——课程里讲的每个"失效场景"都值得单独写篇笔记分析,因为这些才是感知工程真正要解决的问题。

我在实际学习中的体会是,感知模块没有一个"终极答案"。点云检测、视觉识别、传感器融合,每个方向上都有无数人在迭代更新。更重要的能力,是形成自己的调试方法论:出了问题知道往哪个环节查、用什么工具验证、怎么通过对比实验缩小范围。

下一篇笔记我会接着写预测与规划部分,把"感知到世界模型之后,车辆如何决策下一步动作"这条链路补全。如果你也在跟这套课程,欢迎一起交流学习中遇到的坑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询