1. 多传感器融合到底在解决什么问题
1.1 从一个生活场景说起
你闭着眼睛用手去摸桌上的杯子,你能判断出杯子的位置、大概形状、是冷是热。这个过程里,你的皮肤提供了温度和触感,你的肌肉和关节提供了位置感,你的耳朵可能还听到了杯子被碰到时的声音。大脑把这些信息揉在一起,你就对"杯子"有了一个完整的认知。
多传感器信息融合干的就是类似的事情。一个机器人、一辆自动驾驶车、一架无人机,它们身上装着激光雷达、摄像头、毫米波雷达、惯性测量单元、全球导航卫星系统接收机等一堆传感器。每个传感器都在用自己的方式"看"这个世界,但每个都有自己的盲区和缺陷。融合的目的,就是让这些传感器互相补位,最终输出一个比任何单一传感器都更可靠、更完整的环境认知。
我刚开始接触这块的时候,最大的困惑是:既然激光雷达测距那么准,为什么还要费劲去融合摄像头?后来在实际项目里踩了坑才明白,激光雷达在雨天、雾天衰减严重,摄像头在强光逆光下直接致盲,毫米波雷达对金属敏感但对静止物体分辨力差。没有哪个传感器是全天候全场景的六边形战士,融合不是锦上添花,而是刚需。
1.2 融合的层次划分:你在哪一层做文章
多传感器融合按照信息抽象的层次,通常分为三个级别,这个划分方式最早由美国学者提出,后来成为行业通用框架。
数据级融合,也叫像素级或信号级融合。所有传感器原始数据还没经过太多处理就直接汇到一起。比如两个摄像头同时拍一张图,把像素对齐后做加权平均去噪。这种融合信息损失最小,但对通信带宽和算力要求极高,而且要求传感器是同质的——你没法把激光雷达的点云和摄像头的像素直接做平均。实际工程里用得比较少,主要出现在图像处理领域。
特征级融合,这是目前工程实践中最常用的层次。每个传感器先各自提取特征——摄像头提取车道线、行人框、交通标志;激光雷达提取障碍物聚类、可通行区域;毫米波雷达提取目标距离和速度。然后把这些特征向量送到融合模块做关联和合并。好处是数据量大幅压缩,异构传感器也能融合,实时性好。缺点是在特征提取阶段已经丢失了一部分原始信息,如果某个传感器特征提取出错,后面很难纠正。
决策级融合,每个传感器独立完成感知任务,各自输出目标列表和置信度,最后在决策层面做投票或加权。比如摄像头说"前方有行人,置信度0.8",激光雷达说"前方有障碍物,置信度0.9",融合中心综合判断。这种层次容错性最强,一个传感器完全挂掉也不影响其他传感器工作,但信息利用率最低,精度上限也最低。
实际项目中,纯用某一个层次的情况很少。常见做法是特征级为主、决策级为辅。比如目标检测用特征级融合拿到更准的框,同时保留各传感器的独立决策做故障降级。
1.3 为什么现在融合变得这么重要
早些年单传感器方案也能凑合用。比如早期的自动泊车,靠超声波雷达就够了;早期的车道保持,一个前视摄像头也能跑。但现在场景越来越复杂,要求越来越高。
L2级辅助驾驶往L3甚至更高级别走,系统必须能在传感器故障时依然保证安全。这就意味着不能把宝押在一个传感器上。另外,单一传感器在某些场景下的物理极限是绕不过去的——摄像头的深度估计天生不准,激光雷达在雨雾天测距会偏,毫米波雷达的角度分辨率受天线孔径限制。融合是从物理层面解决这些问题的唯一出路。
还有一个现实因素:算力便宜了。五年前跑一个多传感器融合 pipeline 需要工控机加GPU,现在一块嵌入式板子就能扛下来。硬件成本下降让融合方案从实验室走向了量产车。
2. 融合系统的核心架构与关键模块
2.1 一个典型融合系统的数据流
不管什么应用场景,多传感器融合系统的骨架大体一致,我把它拆成五个环节。
传感器标定与时空对齐是第一步,也是最容易被忽视但最要命的一步。空间标定解决的是"每个传感器在车体坐标系下的位置和朝向",时间标定解决的是"不同传感器的时间戳怎么对齐"。如果两个传感器的时间戳差了50毫秒,在高速场景下目标已经移动了一米多,融合出来的结果直接是错的。
数据预处理包括去噪、滤波、坐标变换。激光雷达点云要做体素滤波降采样,摄像头图像要做畸变校正,惯性测量单元数据要做零偏补偿。这一步的质量直接决定后面融合的上限。
特征提取与目标检测是各传感器独立完成的。摄像头跑神经网络出2D框,激光雷达做点云聚类出3D框,毫米波雷达输出距离-速度-角度信息。每个传感器输出的目标列表格式不同,需要统一到同一个数据结构。
数据关联是融合的核心难点。摄像头看到前方有个目标,激光雷达也看到前方有个目标,你怎么知道这俩是同一个东西?这就是数据关联要解决的问题。常用方法有最近邻匹配、联合概率数据关联、多假设跟踪等。
状态估计与融合输出是最后一步。把关联上的目标信息用卡尔曼滤波、粒子滤波或图优化方法合并,输出最终的目标状态估计。
2.2 时空对齐:融合的地基
空间标定我踩过的坑最多。摄像头和激光雷达的外参标定,理论上可以用标定板做,但实际装车后由于震动、温度变化,外参会漂移。我见过一个项目,标定完跑了两周,摄像头和激光雷达的俯仰角偏了0.3度,在50米外就是26厘米的误差,直接导致融合目标位置跳变。
工程上的做法是:出厂前用高精度标定间做一次精确标定,然后在线跑标定算法做实时修正。在线标定通常利用道路上的自然特征——车道线、路沿、交通标志——来估计外参的微小变化。
时间对齐更微妙。每个传感器有自己的时钟,硬件触发采集的时刻和软件打时间戳的时刻可能差几毫秒到几十毫秒。做法一般有两种:硬同步和软同步。硬同步是用同一个触发信号同时触发所有传感器采集,从源头保证时间一致,但需要硬件支持。软同步是各传感器独立采集,事后根据时间戳做插值对齐。硬同步精度高但灵活性差,软同步灵活但对时间戳精度要求极高。
我个人的经验是:如果传感器支持硬同步,一定用硬同步。软同步在低速场景下凑合能用,一旦目标运动快或者传感器频率差异大,插值误差会迅速放大。
2.3 数据关联:谁和谁是同一个目标
数据关联的本质是一个分配问题。假设摄像头检测到M个目标,激光雷达检测到N个目标,你要找到一个最优的匹配方案,使得整体匹配代价最小。
最简单的做法是最近邻——对每个摄像头目标,找距离最近的激光雷达目标。但这种方法在目标密集或者有虚警漏检时很容易出错。比如前方并排两辆车,最近邻可能把左边摄像头目标和右边激光雷达目标配上。
更鲁棒的做法是全局最近邻,用匈牙利算法求全局最优匹配。再往上还有联合概率数据关联,考虑所有可能的关联组合,用概率加权。计算量依次递增,效果也依次提升。
实际工程里,全局最近邻加门限过滤是性价比最高的方案。先根据目标类型、距离、速度差设置一个关联门限,门限外的直接排除,门限内的用匈牙利算法求最优匹配。这样既保证了鲁棒性,计算量也可控。
关联特征的选择也有讲究。位置和速度是最基本的,但还可以加入目标尺寸、朝向、类别等信息。比如摄像头识别出是卡车,激光雷达聚类出的目标尺寸也符合卡车特征,那关联置信度就高。如果摄像头说是轿车,激光雷达聚类出5米长的目标,那就要怀疑关联是否正确。
2.4 状态估计:卡尔曼滤波为什么是常青树
融合的最后一步是把关联上的多源信息合并成单一的状态估计。卡尔曼滤波及其变种是绝对的主流。
卡尔曼滤波的核心思想是:用预测和观测两个信息源做加权平均,权重由各自的噪声协方差决定。预测来自系统动力学模型,观测来自传感器。谁的噪声小,谁的话语权就大。
在多传感器融合里,卡尔曼滤波的用法通常有两种。一种是序贯更新:先用激光雷达观测更新一次状态,再用摄像头观测更新一次。另一种是扩维观测:把所有传感器的观测拼成一个大的观测向量,一次性更新。序贯更新计算量小,但要求各传感器观测噪声不相关;扩维观测理论上更优,但计算量大。
扩展卡尔曼滤波处理非线性系统,通过一阶泰勒展开做线性化。无迹卡尔曼滤波通过sigma点传播均值和协方差,对强非线性系统效果更好。粒子滤波适用于非高斯非线性场景,但计算量随粒子数线性增长,实时性差。
我实际项目里,激光雷达和毫米波雷达的融合用扩展卡尔曼滤波就够了,因为观测模型接近线性。摄像头和激光雷达的融合如果涉及角度观测,无迹卡尔曼滤波会更稳。粒子滤波只在极少数场景用过,比如目标被遮挡后重新捕获。
3. 从零搭建一个融合模块的实操记录
3.1 硬件选型与数据接口
假设我们要做一个低速无人配送车的感知融合模块,场景是园区道路,速度不超过20公里每小时。传感器配置如下:
| 传感器 | 型号代称 | 频率 | 输出接口 | 主要用途 |
|---|---|---|---|---|
| 16线激光雷达 | 雷达A | 10赫兹 | 以太网UDP | 360度障碍物检测 |
| 单目摄像头 | 相机B | 30赫兹 | USB3.0 | 车道线、交通标志识别 |
| 毫米波雷达 | 雷达C | 20赫兹 | CAN总线 | 中远距离目标测速 |
| 惯性测量单元 | 惯导D | 100赫兹 | 串口 | 车体姿态和加速度 |
选16线激光雷达而不是32线或64线,是因为园区低速场景不需要那么高的垂直分辨率,16线在10米内已经能提供足够的点云密度,成本却低了一大截。摄像头选单目而不是双目,是因为深度估计主要靠激光雷达,摄像头专注做语义识别。毫米波雷达选77吉赫兹频段,比24吉赫兹的角分辨率好很多。
数据接口的统一是个麻烦事。激光雷达走UDP,摄像头走USB,毫米波雷达走CAN,惯导走串口。需要一个中间层把这些数据统一成内部消息格式。我用的是机器人操作系统里的消息机制,每个传感器一个驱动节点,发布标准化的消息类型。
如果你的项目不用机器人操作系统,也可以自己写一个数据总线,核心是定义好统一的时间戳格式和坐标系约定。时间戳统一用Unix时间,坐标系统一用右手系,原点在车体后轴中心。
3.2 标定流程与实操细节
标定分两步:内参标定和外参标定。
摄像头内参标定用棋盘格,采集20到30张不同角度的图片,用张正友标定法求解焦距、主点、畸变系数。这一步比较成熟,开源工具很多。注意棋盘格要覆盖图像各个区域,特别是边缘,否则畸变系数在边缘区域不准。
激光雷达和摄像头的外参标定,我用的是基于标定板的方法。一块带有四个圆形孔洞的标定板,激光雷达扫描到孔洞边缘,摄像头识别孔洞中心,通过对应点对求解外参。实际操作中,标定板要放在距离传感器5到10米的位置,太近点云太密反而不好提取边缘,太远点云太稀。
毫米波雷达和激光雷达的外参标定最难,因为毫米波雷达的角度分辨率低,输出的目标位置本身就有较大不确定性。我的做法是:在雷达视场里放三个角反射器,激光雷达精确测量角反射器位置,毫米波雷达输出目标位置,通过多帧平均降低随机误差,然后求解外参。
时间标定用一个简单的办法:让一个发光二极管以固定频率闪烁,摄像头和激光雷达同时采集,通过检测闪烁时刻的偏移量来估计时间差。精度能到毫秒级,对于低速场景够用了。
3.3 融合代码的核心逻辑
下面用伪代码展示融合模块的主循环。实际代码用C++写的,这里简化成Python风格方便理解。
# 融合主循环,运行频率与激光雷达一致,10赫兹 def fusion_loop(): while True: # 1. 获取各传感器最新数据 lidar_objects = get_lidar_objects() # 激光雷达目标列表 camera_objects = get_camera_objects() # 摄像头目标列表 radar_objects = get_radar_objects() # 毫米波雷达目标列表 ego_pose = get_ego_pose() # 车体姿态 # 2. 时间对齐,把所有目标的时间戳统一到当前时刻 lidar_objects = time_align(lidar_objects, current_time) camera_objects = time_align(camera_objects, current_time) radar_objects = time_align(radar_objects, current_time) # 3. 坐标变换,把所有目标变换到车体坐标系 lidar_objects = transform_to_ego(lidar_objects, ego_pose) camera_objects = transform_to_ego(camera_objects, ego_pose) radar_objects = transform_to_ego(radar_objects, ego_pose) # 4. 数据关联,找出各传感器目标之间的对应关系 associations = data_association( lidar_objects, camera_objects, radar_objects ) # 5. 状态估计,对关联上的目标做卡尔曼滤波 fused_objects = [] for assoc in associations: fused = kalman_update(assoc) fused_objects.append(fused) # 6. 输出融合结果 publish_fused_objects(fused_objects) sleep(0.1) # 10赫兹这段代码里,时间对齐和坐标变换是预处理,数据关联和状态估计是核心。实际工程中,卡尔曼滤波的预测步骤要放在循环开头,用上一时刻的状态和运动模型预测当前时刻状态,然后再用观测更新。
卡尔曼滤波的参数调优是个细活。过程噪声协方差Q矩阵反映你对运动模型的不信任程度,观测噪声协方差R矩阵反映你对传感器的不信任程度。Q设大了,滤波器更相信观测,响应快但抖动大;Q设小了,滤波器更相信预测,平滑但滞后。我一般先用经验值跑,然后根据实际轨迹和真值的对比来调。
3.4 关联门限的设定与调参
关联门限的设定直接影响融合效果。门限太松,容易把不同目标关联到一起;门限太紧,同一个目标在不同传感器间关联不上,融合退化成单传感器。
我的做法是:位置门限设为传感器定位误差的3倍标准差。比如激光雷达定位误差0.1米,摄像头定位误差0.5米,那位置门限设为1.5米左右。速度门限设为速度测量误差的3倍标准差。角度门限类似。
但固定门限在目标密集时不够用。更好的做法是自适应门限:根据目标距离调整。距离越远,传感器的定位误差越大,门限也应该越大。我用的公式是:门限等于基础门限加上距离乘以一个系数。系数通过实际数据拟合得到。
还有一个技巧:用马氏距离代替欧氏距离。马氏距离考虑了协方差矩阵,能更好地反映统计意义上的"接近程度"。计算量稍大,但关联正确率明显提升。
4. 融合系统常见问题与排查实录
4.1 融合目标位置跳变
这是最常见的问题。表现是融合输出的目标位置在相邻帧之间突然跳了几十厘米甚至一米。
原因通常有三个。第一是时间对齐没做好,不同传感器的时间戳偏差导致目标位置对不上。排查方法是把各传感器单独输出的目标位置画在时间轴上,看同一目标的位置曲线是否平滑,如果某个传感器的曲线有台阶状跳变,说明时间戳有问题。
第二是数据关联出错,上一帧关联的是目标A,这一帧关联到了目标B,导致状态估计被拉偏。排查方法是把关联结果可视化,看关联线是否稳定。如果关联线频繁切换,说明关联门限太松或者关联特征不够。
第三是卡尔曼滤波的参数不合适,观测噪声设得太小,滤波器过度相信观测,观测一抖输出就抖。解决办法是适当增大观测噪声协方差,或者对观测做低通滤波。
我遇到过一次特别隐蔽的跳变,查了两天才发现是激光雷达的驱动节点在处理点云时,偶尔会丢帧,导致时间戳错位。后来在驱动层加了帧序号校验,问题解决。
4.2 融合目标丢失
表现是某个目标在单传感器里一直能看到,但融合输出里时有时无。
最常见的原因是关联失败。比如摄像头看到了目标,但激光雷达因为遮挡没看到,关联时找不到对应的激光雷达目标,融合模块可能就把这个目标丢弃了。解决办法是设计一个"仅观测更新"模式:当只有一个传感器有观测时,依然用这个观测更新状态,只是置信度降低。
另一个原因是卡尔曼滤波的发散。如果目标长时间只有预测没有观测,协方差矩阵会越来越大,最终滤波器发散,目标被判定为丢失。解决办法是设置一个最大预测帧数,超过这个帧数还没有观测就删除目标。
还有一种情况是目标被其他目标遮挡,关联时被错误地合并到了其他目标上。这需要更精细的关联逻辑,比如考虑目标尺寸和朝向的匹配度。
4.3 传感器故障时的降级策略
融合系统的一个核心优势是容错,但前提是你设计了降级策略。
我的做法是给每个传感器一个健康状态标志。健康状态通过几个指标判断:数据频率是否正常、数据内容是否合理、与其他传感器的一致性是否达标。比如激光雷达突然输出大量噪点,或者毫米波雷达的目标数量突然翻倍,都可能是故障征兆。
一旦某个传感器被标记为故障,融合模块自动切换到降级模式。如果是激光雷达故障,融合退化为摄像头加毫米波雷达;如果是摄像头故障,退化为激光雷达加毫米波雷达。降级后的融合结果置信度会降低,下游的规划控制模块需要相应调整策略,比如降低车速、增大安全距离。
降级策略一定要在系统设计初期就考虑,不要等到出了问题再补。我见过一个项目,融合模块没有降级逻辑,激光雷达一挂整个感知就瘫了,车直接停在路中间。
4.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决措施 |
|---|---|---|---|
| 融合目标位置跳变 | 时间对齐偏差 | 对比各传感器目标位置曲线 | 校准时间戳,启用硬同步 |
| 融合目标位置跳变 | 关联错误 | 可视化关联结果 | 收紧关联门限,增加关联特征 |
| 融合目标丢失 | 关联失败 | 检查单传感器是否持续检测到 | 启用仅观测更新模式 |
| 融合目标丢失 | 滤波器发散 | 检查协方差矩阵是否增大 | 设置最大预测帧数 |
| 融合目标重影 | 关联门限太松 | 检查是否有重复目标 | 收紧门限,增加尺寸匹配 |
| 融合结果滞后 | 过程噪声太小 | 对比融合轨迹和真值 | 增大过程噪声协方差 |
| 融合结果抖动 | 观测噪声太小 | 分析观测残差 | 增大观测噪声协方差 |
| 传感器故障未降级 | 健康监测缺失 | 检查健康状态标志 | 增加健康监测和降级逻辑 |
4.5 几个容易被忽视的细节
坐标系约定要统一。我见过一个项目,激光雷达驱动用的左手系,摄像头驱动用的右手系,融合时坐标变换直接算错。后来在项目规范里明确写了:所有传感器驱动输出必须统一到右手系,原点在车体后轴中心,X向前,Y向左,Z向上。
时间戳要用采集时刻而不是处理时刻。有些驱动在数据处理的最后才打时间戳,导致时间戳比实际采集时刻晚了十几毫秒。融合时用这个时间戳做对齐,误差就大了。正确做法是在数据采集的中断服务程序里就打时间戳。
标定参数要版本管理。每次标定完把参数存成一个带时间戳的文件,融合模块启动时加载最新版本。我吃过亏,标定完忘了更新参数文件,跑了一周才发现用的是旧参数。
融合结果要带置信度。下游模块需要知道融合结果有多可靠。置信度可以综合各传感器的检测置信度、关联质量、滤波器协方差来计算。没有置信度的融合输出,下游没法做风险决策。
日志要记全。融合模块的输入输出、中间关联结果、滤波器状态都要记日志。出问题时没有日志,排查就是盲人摸象。我一般用二进制格式记原始数据,用文本格式记关键事件,方便回放和分析。
5. 融合方案的选型对比与进阶方向
5.1 不同融合架构的取舍
前面讲的集中式融合,所有传感器数据汇到一个中心节点处理。优点是全局信息完整,融合结果最优。缺点是中心节点算力要求高,一旦挂掉整个系统瘫痪。
分布式融合是每个传感器或每组传感器有自己的处理节点,输出局部融合结果,再送到中心节点做二次融合。优点是算力分散,容错性好。缺点是局部融合已经损失了信息,二次融合的上限受限。
混合式融合是两者的折中。关键传感器用集中式,次要传感器用分布式。实际量产项目里,混合式用得最多。
选哪种架构,核心看两个因素:算力预算和功能安全等级。算力充足且安全等级要求不高,集中式最简单。算力紧张或者要求高安全等级,分布式或混合式更合适。
5.2 从滤波到优化的范式转变
传统融合用卡尔曼滤波,本质是递推的贝叶斯估计。近年来,基于图优化的融合方法越来越流行。
图优化的思路是:把所有时刻的传感器观测和状态变量建成一个图,观测是边,状态是节点,通过最小化所有边的残差来求解最优状态序列。这种方法可以全局优化,不受递推顺序影响,精度更高。缺点是计算量大,需要求解大规模稀疏矩阵。
实际工程里,滤波和图优化各有适用场景。实时性要求高的用滤波,精度要求高的用图优化。有些系统用滤波做在线估计,用图优化做离线标定和轨迹优化。
5.3 深度学习在融合中的角色
深度学习正在改变融合的玩法。传统融合靠人工设计特征和关联规则,深度学习可以直接从原始数据学到融合表示。
比如点云和图像的融合,传统做法是分别提取特征再关联。现在可以用神经网络把点云投影到图像平面,和图像特征在同一个网络里做注意力融合。这种端到端的方式在目标检测任务上已经超过了传统方法。
但深度学习融合也有短板。可解释性差,出了问题不好排查。对训练数据分布敏感,换个场景可能就失效。计算量大,嵌入式平台部署困难。
我的看法是:深度学习适合做特征提取和初步融合,传统方法适合做状态估计和跟踪。两者结合,取长补短。
5.4 我个人的经验总结
搞了几年多传感器融合,最大的体会是:融合的上限由标定决定,融合的下限由关联决定,融合的稳定性由状态估计决定。
标定不准,后面怎么融合都是错的。关联不对,融合结果就是垃圾进垃圾出。状态估计参数不好,融合输出要么抖要么滞后。
另一个体会是:不要追求一步到位。先把两个传感器融合跑通,再加第三个。每加一个传感器,标定、关联、状态估计都要重新调。贪多嚼不烂。
最后,测试要覆盖极端场景。晴天跑得好不代表雨天能跑,白天跑得好不代表晚上能跑。我一般会专门设计一组极端场景测试用例:强光、逆光、雨雾、隧道进出、目标密集、传感器遮挡。这些场景才是融合系统真正的试金石。