第一次把摄像头和毫米波雷达的目标级融合真正跑通时,我盯着屏幕上的红色警告框看了很久。视觉模型认为前方是一个行人,置信度0.9;同一时刻,雷达回波却显示这个目标的多普勒速度接近零,反射截面积也不像人体。两个传感器都在正常输出,谁对谁错?这个问题的答案,不是把两家置信度做个加权平均就完事的。它需要一套能把“不确定性”和“无知”明确分开、还能把多个传感器的证据合并到一起的机制——这正是Dempster-Shafer证据理论(D-S理论)擅长的事。
这篇文章围绕“信息矩阵融合算法 + Dempster-Shafer目标级融合”在自动驾驶环境感知里的应用,完整拆解Matlab实现思路:先讲清楚目标级融合解决什么问题,再推演D-S的数学底子,接着给出信息矩阵与证据理论的组合框架,最后落到代码、仿真和调试经验。适合正在做多传感器融合课题的学生,也适合车端感知模块的工程师做方案选型时参考。
1. 摄像头和雷达的“打架”现场:目标级融合要解决的三个问题
1.1 融合层级的选择:为什么是目标级而不是数据级
多传感器融合通常分三个层级。数据级融合直接把图像像素和点云坐标放到同一个空间里对齐、拼接,信息保留最完整,但对标定、时钟同步、计算带宽的要求极高,稍微有点震动或延迟,融合结果就碎成一团。特征级融合折中一些,提取中间特征再融合,问题是特征空间很难统一,摄像头特征和雷达点云特征压根不是一个维度。目标级融合则是在每个传感器内部先独立完成检测和跟踪,输出各自的目标列表,再把目标列表拿到融合模块里做关联和合并。
自动驾驶里目标级融合是工程上最稳妥的主流做法。每个传感器模块可以独立开发、独立标定、独立升级,融合模块只跟“目标”打交道,吃的是语义信息而不是底层数据。图像那条链出问题,雷达还能顶住;雷达进了隧道丢反射,摄像头也能覆盖。带宽压力小,模块之间解耦清晰,出问题也好定位。“目标级”三个字,本质上是把系统复杂度和传感器异构性挡在了融合模块之外。
1.2 目标级融合必须处理的三个子问题
目标级融合不是简单“把两个框叠在一起”。拿到两路目标列表后,你至少要回答三个问题:
- 关联:摄像头报的目标A和雷达报的目标B是不是同一个物体?关联错,后面全错。
- 状态估计:目标的连续物理量(位置、速度、航向)怎么合?两个传感器各有噪声,状态协方差怎么融合?
- 类别与存在性判定:目标是车、行人还是骑车人?这个目标到底存不存在?两路传感器给的类别置信度口径还不一样。
我在框架里把这三件事分开处理:连续状态用信息滤波器(Information Filter),离散类别和存在置信度用Dempster-Shafer证据理论。标题里的“信息矩阵融合算法”,在我这套实现里对应两层含义——一层是证据矩阵,把所有目标的BPA组织成矩阵做D-S合成;另一层是Fisher信息矩阵,用信息滤波器做运动状态的加法式融合。这两层配合起来,感知链路的“连续量”和“离散量”都覆盖了。
1.3 为什么贝叶斯框架在这个场景里不够用
很多人第一反应是用贝叶斯:给每个类别一个先验,然后用传感器似然更新后验。但实际工程里有两个尴尬。第一,摄像头分类网络输出的softmax概率不是严格意义上的似然,它常常过度自信,而且不同传感器的置信度标定尺度完全不同,两个“0.8”的含义不一样,直接乘进贝叶斯公式没有任何理论保证。第二,贝叶斯要求假设空间完备且互斥,你必须对“既不是车也不是行人也不是骑车人”的情况给出一个概率,这个“其他类”其实很难定义。
D-S理论换了个思路:它不说“这个目标有80%概率是车”,而是说“我有70%的把握支持它是车,还有20%我承认自己不知道”。这个“不知道”用m(Θ)表达,对应识别框架的全集Θ。贝叶斯里你被迫把“不知道”分摊到每个假设上,D-S可以诚实地把它留在原地。目标被遮挡、夜间图像退化、雷达多径反射这些情况,传感器自己都不知道目标是什么,这时候强行给一个概率分布反而是在制造伪精度。
2. Dempster-Shafer到底在算什么:从BPA到合成规则的手算过程
2.1 识别框架、焦元与BPA
D-S整个体系建立在识别框架Θ上。对目标级融合来说,Θ就是所有可能类别的集合,比如Θ={车辆V, 行人P, 骑车人C}。框架里的任意子集都叫焦元,包括单个类别,也包括组合,比如{V,P}表示“是车或行人,但分不清”,全集Θ表示“是这三个之一,但不知道是哪个”。
基本概率分配(BPA)就是往这些焦元上放质量的一个函数m:2^Θ→[0,1],满足两个条件:
- m(∅)=0,空集不能放质量。
- 所有焦元的质量之和为1。
从BPA可以推出两个更直观的量。信度函数Bel(A)=Σ_{B⊆A}m(B),表示“证据明确支持A的程度”;似真函数Pl(A)=Σ_{B∩A≠∅}m(B),表示“证据不反对A的最大程度”。区间[Bel(A), Pl(A)]就是目标属于A的置信区间。做感知的人可以把这理解成上下限:下限是实打实的支持,上限是“没有证据反对”,区间越窄说明证据越充分,区间越宽说明这个类别的判断越模糊。
2.2 Dempster合成规则:挑出共识,扔掉矛盾
D-S的核心是Dempster合成规则。两路独立证据m1和m2合成后,任意焦元A的新质量是:
m12(A) = [Σ_{B∩C=A} m1(B)·m2(C)] / (1-K)
其中冲突系数K=Σ_{B∩C=∅} m1(B)·m2(C),是所有被分到空集上的质量之和。分子把“两个证据的交集恰好落在A上”的那些质量加起来,分母(1-K)把冲突质量抹掉后重新归一化。
用大白话讲:把两个证据的质量表当成两个维度做交叉相乘,每一格代表“一个证据说B、另一个说C”的联合情况;两个说法一致就合并,一个明确一个无知就按明确的算,两个说法互相矛盾就扔进K这个“矛盾桶”里,最后把总质量重新拉到1。K越大,两路证据越不对付。
2.3 手算一个常规例子和一个冲突例子
假设摄像头输出BPA为m1:m(V)=0.5,m(P)=0.3,m(Θ)=0.2;雷达输出m2:m(V)=0.7,m(P)=0.1,m(Θ)=0.2。两路都认为目标更像是车,但摄像头心中行人的分量也不低。
| 交叉组合 | 联合质量 | 交集结果 |
|---|---|---|
| (V, V) | 0.35 | V |
| (V, P) | 0.05 | ∅ |
| (V, Θ) | 0.10 | V |
| (P, V) | 0.21 | ∅ |
| (P, P) | 0.03 | P |
| (P, Θ) | 0.06 | P |
| (Θ, V) | 0.14 | V |
| (Θ, P) | 0.02 | P |
| (Θ, Θ) | 0.04 | Θ |
冲突系数K=0.05+0.21=0.26。归一化后:m(V)=0.797,m(P)=0.149,m(Θ)=0.054。
这个结果很有信息量。摄像头单独看,对“车”的置信区间是[0.5,0.7];雷达单独看是[0.7,0.9];融合后变成[0.797,0.851]。均值往高处走,区间还收窄了——两个传感器互相补充,对车的判断比任何一个单传感器都笃定,同时残余的无知只有5.4%。
再给一个冲突场景:摄像头说它是行人,m1:m(V)=0.1,m(P)=0.8,m(Θ)=0.1;雷达说它是车,m2:m(V)=0.8,m(P)=0.1,m(Θ)=0.1。这时K=0.65,归一化后得到m(V)=0.486,m(P)=0.486,m(Θ)=0.029。两个类别打平,而且无知被压缩到几乎为零。这就是D-S最著名的反直觉问题:高冲突下,规则会强行“选边站”并表现得非常自信,这种结果在辅助驾驶里是不能直接用的。后面讲调试坑的时候会具体处理它。
3. 信息矩阵怎么和D-S接在一起:两层融合框架的设计
3.1 第一层:把BPA组织成证据矩阵
多目标场景下,每个传感器对每个目标都输出一条BPA,数据形态天然是个三维张量:目标数T × 焦元数N × 传感器数S。N=2^K,K是单元素假设个数,比如三类别时N=8。我用MATLAB里的三维数组E来放这个张量,E(t,:,s)就是第s个传感器对第t个目标的BPA行向量。
融合就是对每个目标t,沿着传感器这一维依次做D-S合成:
E = zeros(T, N, S); % 目标数 × 焦元数 × 传感器数 % ... 填充每个传感器的BPA ... E_fused = zeros(T, N); for t = 1:T m_cur = squeeze(E(t, :, 1)).'; for s = 2:S m_cur = ds_combine(m_cur, squeeze(E(t, :, s)).', INTER); end E_fused(t, :) = m_cur; end这就是“信息矩阵融合算法”的第一层含义:把每个目标的证据组织成矩阵,逐行做证据合成。好处是计算天然向量化,目标之间互不干扰,加目标只是多一行的事。
3.2 第二层:状态估计用信息滤波器
类别融合解决“是什么”,状态估计解决“在哪、多快”。对连续状态,我用信息滤波器而不是标准卡尔曼。信息滤波器的核心是信息矩阵Y=P^(-1)和信息状态向量ŷ=Y·x̂。它的测量更新有一个非常漂亮的性质:多个传感器更新只需要做加法。
Y_k = Y_pred + Σ_i H_i^T R_i^(-1) H_i
ŷ_k = ŷ_pred + Σ_i H_i^T R_i^(-1) z_i
每个传感器贡献一项“信息增量”,往累计矩阵里加就是了。标准卡尔曼每次都要先算增益K再更新协方差P,多传感器还得串行或批量处理;信息滤波器天然就是为多传感器加法融合设计的。另一个实用好处是初始化方便:信息矩阵从0开始就是“完全不知道”,协方差无限大,不需要像卡尔曼那样拍一个很大的初始P。代价是最后要把Y求逆才能拿回状态均值和协方差,所以工程上要注意P的正定性,数值不稳时改用带平方根形式的信息滤波器。
function [Y_hat, y_hat] = info_update(Y_pred, y_pred, H, R, z) information_contrib = H' * (R \ H); vector_contrib = H' * (R \ z); Y_hat = Y_pred + information_contrib; y_hat = y_pred + vector_contrib; end状态模型还是标准的匀速/匀加速运动学,预测步在信息域写稍微绕一点,但多传感器更新的清爽程度完全值回票价。
3.3 两条链怎么拼成完整数据流
整个融合模块的数据流是:各路传感器目标列表 → 时间对齐与关联 → 对匹配上的目标对,把状态预测到同一时刻,信息滤波器累加各传感器的量测贡献 → 用D-S合成各类别BPA → 目标管理(确认、降级、删除)→ 决策输出。
两路链路的输出在目标管理那里汇合:一个目标要“确认存在”,既要有足够高的融合后信度Bel,类别判断也得稳定。状态信息决定框的位置和速度,类别BPA决定框的标签和置信度。缺一条都不行——位置再准,类别判断是“未知”,下游规控模块照样不敢用。
4. Matlab实现:数据结构、核心函数与向量化取舍
4.1 工程结构与数据约定
我按下面这张表组织代码,每个模块独立成函数,主循环只做调度:
| 模块 | 职责 |
|---|---|
| main_fusion.m | 主循环,负责读取仿真数据、调用各模块 |
| sensor_camera_model.m | 生成摄像头目标列表和对应BPA |
| sensor_radar_model.m | 生成雷达目标列表和对应BPA |
| gate_association.m | 目标关联,输出匹配对和未匹配目标 |
| classifier_output_to_bpa.m | 分类概率转BPA |
| ds_combine.m | Dempster合成规则 |
| ds_decision.m | 判决,输出类别、信度、是否含糊 |
| info_update.m | 信息滤波器测量更新 |
| track_manager.m | 目标确认/删除逻辑 |
| plot_results.m | 可视化:目标框、BPA曲线、K时序 |
数据结构上,每个目标用结构体数组存:id、状态向量、协方差、BPA向量、生命周期、确认计数。BPA向量的索引约定统一成“焦元索引=位掩码+1”:索引1永远放空集占位,索引2^(i-1)+1放第i个单元素假设,索引2^K放全集Θ。以K=3为例,索引5对应位掩码4(二进制100),即{C};索引4对应位掩码3(011),即{V,P}复合焦元。虽然源BPA通常只往单元素和全集放质量,但复合焦元的槽位在代码里保留着,想表达“行人或骑车人分不清”这类中间态时,直接往对应位置放质量就行,不用改框架。
4.2 核心函数:交点查找表与D-S合成
D-S合成在代码层面的核心是把“两个焦元取交集”这件事预先算好。因为2^K个焦元可以用位掩码唯一编码,交集运算就变成了按位与。我把所有焦元对的交集结果预计算成一张查找表INTER,运行时直接查表,避免反复做位移和逻辑判断:
function INTER = build_intersection_table(K) % K: 单元素假设个数 % 返回 N×N 查找表, N = 2^K N = 2^K; masks = 0:(N-1); [I, J] = ndgrid(1:N, 1:N); INTER = bitand(masks(I), masks(J)) + 1; end有了这张表,合成函数用accumarray一步完成累加:
function [m_fused, K] = ds_combine(m1, m2, INTER) % m1, m2: 1×N 的BPA行向量, 首元素为空集占位 N = numel(m1); joint = reshape(m1, N, 1) .* reshape(m2, 1, N); % 联合质量矩阵 m_fused = accumarray(INTER(:), joint(:), [N, 1])'; K = m_fused(1); % 交集落在空集上的总质量 if K >= 1 - eps error('证据完全冲突: 检查目标关联与传感器标定'); end m_fused = m_fused / (1 - K); m_fused(1) = 0; end这个实现比我最早写的三层for循环版本快了不止一个量级。K=3时N=8,联合矩阵只有64格,怎么算都快;但代码风格是为K=5、N=32这种更大识别框架准备的,查找表+accumarray的思路能直接撑住。合成规则在数学上有交换律和结合律,但注意浮点逐次归一化的实现会在K接近1时放大顺序差异,所以工程上永远先判冲突再合成。
4.3 生成BPA与判决逻辑
传感器分类器输出的是概率,要转成BPA,关键是引入一个“可靠性折扣”系数reliability。分类概率乘上可靠性后放到对应单元素焦元上,剩下(1-reliability)全部放进全集Θ:
function m = classifier_output_to_bpa(class_prob, reliability, K) % class_prob: 1×K 分类网络输出概率(softmax之后) % reliability: 该传感器在当前环境下的可信度 N = 2^K; m = zeros(1, N); for i = 1:K idx = 2^(i-1) + 1; m(idx) = reliability * class_prob(i); end m(N) = 1 - reliability; % 剩余质量全部放全集, 代表"不知道" end这个折扣系数是整套代码里最重要的标定参数。白天摄像头好好工作,reliability可以给0.9;夜间图像退化,给0.6;雷达进隧道后多径反射变多,给0.7。它表达的是“我对这个传感器的信任程度”,跟传感器内部的分类置信度是两回事。
判决时不能直接把全集Θ当成一个类别来比大小。我的做法是:只让单元素假设参与最大信度竞争,全集质量单独作为“无知程度”监控:
function [label, bel, ambiguous] = ds_decision(m, K, bel_thresh, ignore_thresh) % 只把单元素假设作为类别候选, 全集只用来看无知程度 N = 2^K; singleton_idx = 2.^(0:(K-1)) + 1; singleton_bel = m(singleton_idx); [bel, label] = max(singleton_bel); unknown_mass = m(N); ambiguous = (bel < bel_thresh) || (unknown_mass > ignore_thresh); endbel_thresh和ignore_thresh我通常从0.5和0.2起步。融合后的最大单元素信度低于0.5,或者无知质量高于0.2,就判定为“类别不确定”,这时候宁可输出Unknown也不要硬给一个标签。
4.4 关联与时间对齐的落地
关联这块我用马氏距离加门控。摄像头目标状态zc、雷达目标状态zm,各自带协方差P_cam、P_radar,马氏距离d2=(zc-zm)^T (P_cam+P_radar)^(-1) (zc-zm)。门限取自由度2的95%卡方分位数5.991,距离超过门限的直接不配:
d2 = (zc - zm)' * ((P_cam + P_radar) \ (zc - zm)); if d2 < gate_d2 candidate_pairs(end+1, :) = [i, j, d2]; end候选对里再挑距离最小的作为唯一匹配,一挑多的目标一律先挂起,不进入融合。时间对齐比很多新手以为的重要得多:摄像头帧率和雷达帧率不一样,直接拿不同时刻的状态算马氏距离必然偏。我每个周期先把所有目标预测到融合时刻的最大时间戳,再做关联和更新,这个细节能直接砍掉一批莫名其妙的association jump。
4.5 主循环骨架
主循环每收到一帧传感器数据就执行:
- 读取摄像头、雷达目标列表。
- 把各传感器目标状态预测到公共时间戳。
- 门控关联,得到匹配对、未匹配摄像头目标、未匹配雷达目标。
- 对每个匹配对,用各自分类输出生成BPA。
- 对每个匹配目标,沿传感器维做D-S合成,得到融合BPA。
- 对匹配上的目标做信息滤波器更新;未匹配的目标保留原状态但增加未命中计数。
- 目标管理器根据融合信度和未命中计数决定确认、降级或删除。
- 写日志:K值、各目标BPA、判决结果,供可视化回放。
5. 仿真场景、结果解读与参数标定
5.1 三个典型的仿真场景
我用仿真数据跑了三个场景,分别对应目标级融合最容易遇到的三种局面。
| 场景 | 摄像头BPA (V/P/Θ) | 雷达BPA (V/P/Θ) | K值 |
|---|---|---|---|
| A 常规白天 | 0.50 / 0.30 / 0.20 | 0.70 / 0.10 / 0.20 | 0.26 |
| B 夜间摄像头退化 | 0.30 / 0.20 / 0.50 | 0.60 / 0.20 / 0.20 | 0.18 |
| C 逆光干扰 | 0.10 / 0.80 / 0.10 | 0.80 / 0.10 / 0.10 | 0.65 |
场景A就是第2节手算的例子,代表“两路传感器都靠谱但各有侧重”的正常状态。场景B里摄像头分类器整体变含糊,有50%的质量直接堆给了全集Θ,雷达还算正常。场景C里两路传感器彻底分裂,摄像头认为是行人,雷达认为是车,冲突系数飙到0.65。
5.2 结果怎么解读
三个场景的融合结果如下:
| 场景 | 融合后m(V) | 融合后m(P) | 融合后m(Θ) | 结论 |
|---|---|---|---|---|
| A | 0.797 | 0.149 | 0.054 | 置信度升高, 无知区间收窄 |
| B | 0.659 | 0.220 | 0.122 | 雷达主导, 但保留明显无知 |
| C | 0.486 | 0.486 | 0.029 | 高冲突下的过度自信, 必须降级 |
场景B特别值得琢磨。摄像头已经很不确定,但它对“行人”的那点微弱支持依然保留在融合结果里,m(P)从雷达单路的0.1升到0.22;同时m(Θ)=0.122比场景A高一倍多,系统诚实地告诉你“我知道得没那么准”。这种“保留无知”的行为在辅助驾驶里是安全特性:宁可让规划模块把目标当Unknown慢速处理,也不要强行把它认成一个类别后激进决策。
场景C就是标准的结果毒果。K=0.65说明两路传感器几乎完全矛盾,但D-S归一化后两个类别的信度却打平在0.486,无知只有2.9%——看起来“证据充分”,其实结论完全是归一化强制造出来的。我在融合模块里加了冲突保护:K超过0.5就放弃标准合成,改用预平均策略(两路BPA先平均再合成),或者直接把冲突质量并入全集Θ。这两种做法都能避免场景C的伪自信。实际仿真中,我还会把每个周期的K值单独画一条曲线,哪个目标出现K异常尖峰,基本就是关联错配或者某路传感器退化的信号。
5.3 参数标定的土办法
可靠性参数没有解析解,我从实际数据里标。方法是先录一段有真值标注的数据,统计每个传感器单独的分类准确率,把准确率当作reliability的初始值。摄像头白天准确率0.9,就设0.9;夜间降级到0.6。然后跑一遍融合,观察两类指标:融合后无知质量是否过高,以及融合后的分类准确率是否比单传感器更高。如果融合结果还打不过最靠谱的那路传感器,说明可靠性给错了,用网格搜索在0.5到0.95之间扫一遍,挑验证集上性能最好的组合。
阈值参数同样靠数据说话。bel_thresh和ignore_thresh调大,系统输出Unknown更多、误报更少;调小,系统更敢下结论但可能瞎报。对辅助驾驶场景,我倾向于把阈值调保守——虚警的代价远高于漏报。
6. 我在调试中踩过的坑:冲突、关联与全集语义
6.1 高冲突下的归一化爆炸
场景C不是特例,而是这个规则在冲突情况下的必然倾向。经典的反直觉例子我也复现过:两个来源分别以0.99和0.99支持互相矛盾的结论,还有一个微小的第三方概率,标准D-S合成后居然把那个第三方抬到接近1。原因是分母(1-K)被冲突质量压得极小,微小的差异被放大成压倒性结论。这种性质在目标级融合里非常危险,因为传感器偶尔出一次错、目标被遮挡一瞬间,都可能制造出高K值。
我的改法分两级:K在0.3到0.5之间,用预平均策略,先把两路BPA取平均再合成,抑制归一化放大效应;K超过0.5,直接把当前融合结果标记为“证据冲突”,输出保持上一帧的类别和Unknown标签,同时给目标管理一个“需要额外证据”的降级状态。决策层有冲突标志时,不允许输出高置信度类别。
6.2 关联错了,D-S学得再漂亮也没用
目标级融合有个前提:合成的是“同一个目标”的证据。关联一错,后面的D-S全是空中楼阁。我调试时遇到过一次诡异现象:一个本来很稳的车目标,某帧K值突然从0.2跳到0.7,融合类别在车和行人之间来回跳。查到最后是摄像头在那个区域出现了一个误检框,位置和雷达目标在门限内,就被关联到一起了。
处理办法有两个层面。算法层,关联用更保守的双向门限:两个目标互相选对方才确认匹配,一厢情愿的不算。调试层,日志里必须带上每帧的匹配对编号和K值,K曲线异常尖峰配合关联日志,很快就能定位到是哪一帧哪一对出了问题。这个经验我每次给新人讲融合都会强调:先怀疑关联,再怀疑证据模型。
6.3 全集Θ不是“其他类”
这是新手最容易犯的语义错误。m(Θ)表达的是“有证据存在,但不知道属于哪个类别”,它的正确定位是无知,不是“其他”这一类。如果把Θ放进类别判决里和其他单元素假设一起比大小,系统会在目标被遮挡时输出一堆“Unknown类”,然后下游模块就彻底不知道拿这个目标怎么办了。
我自己写判决时一直坚持:单元素假设只和单元素假设竞争,m(Θ)单独作为无知度监控。如果下游必须有一个硬类别输出(比如规控要求目标必须是车/人/骑手之一),我会在决策层用pignistic变换把m(Θ)按基数摊回单元素假设:BetP(ω)=Σ_{A∋ω} m(A)/|A|。但注意,pignistic变换只用于强制决策,不是融合结果本身,两回事。
6.4 连续帧融合的可信度膨胀
如果每一帧都用当前传感器BPA跟上一帧的累积BPA直接合成,几十帧之后你会发现类别信度趋近于1,无知趋近于0。表面看是“证据越积越多”,实际是双重重计算了相关证据——同一路传感器观测的相邻帧高度相关,每帧合成一次等于把相关性当成独立性用。
我的处理是给帧间合成加上遗忘因子。每轮先对上一帧累积BPA做指数折扣(把一部分质量还给Θ),再和当前帧合成。折扣率我一般取0.1到0.3,相当于对历史证据半衰期做了个软约束。这样既能利用时间累积平滑噪声,又不会在传感器短暂异常时累积出不可逆的偏执结论。
6.5 性能优化清单
MATLAB里跑仿真最常用的几个优化:焦点查找表INTER预计算一次全局复用,别在目标循环里反复生成;合成函数里别用嵌套循环,accumarray一步到位;热循环里别用cell数组,统一用数值数组;对象数超过50个时,把E的三维切片循环写成单步矩阵操作。
另外一定要会用tic/toc定位瓶颈。我最初版本在关联模块里用循环算所有目标对的距离,目标一多就卡;改成矩阵化马氏距离计算后整体耗时降了80%。真要上实车部署,这套逻辑也可以用MATLAB Coder生成嵌入式C代码,D-S合成部分因为纯粹是查表和累加,移植非常干净。
最后再分享一个我自己的调试习惯:K值曲线永远单独占一个subplot,横轴是帧号,每个目标一条线,颜色跟着目标ID走。这个曲线比融合置信度更能暴露问题——正常的感知过程K应该平稳在0.3以下,一旦某条线长期抬升或者突然尖峰,排序第一的怀疑对象永远是关联错配,其次是传感器标定退化。把这条曲线看熟了,整套融合系统的脾气也就摸清了大半。