从「工具组合」到「系统设计」,搞定后融合的执行逻辑与场景适配
在前两章中,我们拆解了后融合感知的两大核心工具:卡尔曼滤波(解决单目标状态的最优估计)、匈牙利算法(解决多目标的跨帧数据关联)。但在量产智驾的落地中,光有算法工具远远不够——我们需要一套完整的融合执行策略,来明确「什么时候融、怎么融、融完怎么管」,它直接决定了整个后融合系统的实时性、鲁棒性、算力效率,也是区分 demo 演示与量产落地方案的核心边界。
本文就围绕后融合策略的分类、核心逻辑、场景适配原则,结合量产工程落地的细节,给大家做一次完整的拆解。
一、按「是否记忆」划分:帧级独立融合 vs 轨迹级时序融合
这里的「记忆」,核心定义是融合系统是否维护跨帧的全局唯一 ID 轨迹列表,是否利用历史时序信息完成融合。这是后融合策略最核心的分类,直接决定了整个系统的底层架构。
1.1 无记忆策略:帧级独立融合
无记忆策略,也叫检测级后融合,是最基础的融合方案,核心是完全不依赖历史时序信息,每一帧的融合完全独立,仅基于当前时刻所有传感器的检测结果完成计算。
核心执行流程
- 数据接收:获取当前时刻激光雷达、摄像头、毫米波雷达输出的 3D 检测结果;
- 帧内关联:用匈牙利算法完成当前帧内跨传感器的检测匹配,确认哪些检测来自同一个目标;
- 单帧融合:对匹配到同一目标的多传感器检测,做加权平均或单帧卡尔曼更新,得到融合后的目标状态;
- 结果输出:直接将当前帧的融合结果输出给规控模块,帧与帧之间无任何状态传递,下一帧重新执行完整流程。
核心优缺点
| 优势 | 劣势 |
|---|---|
| 逻辑极简,可解释性极强,开发与调试成本极低 | 无全局 ID 维护,目标 ID 随帧剧烈抖动,极易出现 ID 跳变、ID 交换 |
| 计算量极小,算力消耗仅与当前帧检测数相关,无额外时序开销 | 无历史滤波,单帧传感器噪声、误检直接输出,目标状态平滑性极差 |
| 无历史错误累积,单帧故障不会传递到下一帧,功能安全验证难度低 | 无法处理遮挡、漏检,目标一旦被遮挡就会直接消失,鲁棒性极差 |
| 与传感器帧率解耦,支持任意数量传感器的即插即用 | 输出结果无法满足规控模块对轨迹连续性、可预测性的核心需求 |
适用场景
无记忆策略几乎不会作为量产智驾的主融合方案,仅适用于三类场景:
- 低算力嵌入式平台的低速场景(如自动泊车、封闭园区低速巡航);
- 多传感器融合的兜底冗余方案,主融合系统故障时的降级备份;
- 算法快速验证与 demo 演示,快速验证多传感器检测的融合效果。
1.2 有记忆策略:轨迹级时序融合
有记忆策略,也叫跟踪级后融合,是当前量产智驾的绝对主流方案,核心是维护一个跨帧的、带全局唯一 ID 的轨迹列表,每一帧的融合都基于历史轨迹的时序信息,结合当前传感器检测完成闭环更新。
它完美承接了前两章讲的卡尔曼滤波与匈牙利算法,是两大核心工具的落地载体。
量产标准执行流程
# 有记忆策略核心流程伪代码,与前序算法完全打通
global_track_list = [] # 全局唯一 ID 的轨迹列表,核心「记忆」载体
def fusion_frame_process(current_sensor_dets):
# 1. 轨迹预测:对所有历史轨迹,用卡尔曼滤波执行预测步,得到当前帧预测状态
track global_track_list:
track.kf.predict(dt=当前帧与上一帧的时间差)
cost_matrix = calculate_cost_matrix(global_track_list, current_sensor_dets)
matched_track_ids, matched_det_ids = hungarian_algorithm(cost_matrix)
track_id, det_id (matched_track_ids, matched_det_ids):
cost_matrix[track_id][det_id] < 匹配阈值:
global_track_list[track_id].kf.update(current_sensor_dets[det_id])
global_track_list[track_id].life_cycle_update(matched=)
track global_track_list:
track 匹配成功列表:
track.life_cycle_update(matched=)
det current_sensor_dets:
det 匹配成功列表:
global_track_list.append(Track(init_state=det))
global_track_list = [track track global_track_list track.is_dead]
valid_tracks = [track track global_track_list track.is_valid]
send_to_control_module(valid_tracks)

