☰
基于DS证据理论与信息矩阵融合的自动驾驶目标级融合实现
2026/10/22 6:27:49 网站建设 项目流程

开篇:雨夜里的两双“眼睛”,就是目标级融合要解决的问题

夜间雨天跑高架,摄像头被对面车灯一晃,前方目标轮廓直接糊掉;毫米波雷达倒是稳,却很难分辨前面那团回波是货车侧板还是一排隔离墩。这时候你问自动驾驶系统:“那到底是什么?”——传感器各自嘴硬,一个说“像车”,一个说“不确定”,还有一个干脆说“没看见”。多传感器目标级融合,干的就是这种事:把每个传感器对同一个目标的“判断”和“底气”收集起来,合出一个综合结论。而把这种判断和底气形式化、可计算、可对抗冲突的利器,就是Dempster-Shafer证据理论;如果再引入信息矩阵融合算法来管理各传感器的置信度与关联关系,整个融合框架在Matlab里就能步步复现。这篇文章写给正在做环境感知融合研究、或想在Matlab里实现目标级融合原型的朋友,我会把理论脉络、代码结构、以及我实际调参踩过的坑一次讲透。

1. 目标级融合的定位:别拿数据级、特征级的老思路硬套

1.1 传感器眼中的“目标”长什么样

在自动驾驶里,同一时刻会有多个传感器在看同一个物理对象。摄像头输出的是像素框,激光雷达输出的是三维点云聚类,毫米波雷达输出的是带有径向速度的稀疏点。所谓目标级融合,是在每个传感器各自完成了检测与跟踪之后,再把它们的“目标列表”拿来做关联和融合。换句话说,各传感器内部已经形成了“我认为前方35米有个目标,类别概率是卡车0.6、客车0.3、未知0.1”这样的判断,融合模块不再碰原始点云或者像素,处理的是更高层的语义证据。

我见过不少同学一上来就写“多传感器融合”的代码,结果把原始点云全塞进一个卡尔曼滤波器里,等数据量一上来,计算直接爆炸。这就是没分清层级。数据级融合需要严格的时空对齐和同一坐标系,特征级融合要处理高维特征空间,而目标级融合的核心是把每个传感器对同一目标的局部决策拿出来融合,它天生对异步数据更宽容,因为每个目标列表都已经是时间戳级别的抽象结果。

1.2 为什么说目标级融合更适合工程落地

原因很实际:其一,自动驾驶系统里各传感器都有自己的处理芯片和跟踪模块,目标级接口天然存在,你不需要侵入底层;其二,目标级融合对传输带宽、算力、内存的要求低一个数量级;其三,它允许不同传感器用不同内部算法,只要对外能给出“目标+属性+置信度”的通用结构。缺点也同样明显:上游一旦漏检,融合模块就巧妇难为无米之炊,所以工程上通常会配合一个“目标生命周期管理”模块来处理漏检、分裂、合并。

在我参与的某跨平台环境感知模拟项目里,最花时间的不是融合逻辑本身,而是目标关联——怎么确定摄像头说的“目标3”和激光雷达说的“目标2”是同一个物理目标。关联做错了,后面融合再漂亮都是白搭。这也是我把信息矩阵融合算法放在前面的原因:它在目标级融合里干的第一件事,就是为关联和置信度加权提供数学依据。

2. Dempster-Shafer证据理论:一个能坦然说“我不知道”的推理框架

2.1 从贝叶斯到DS:不确定性不再是“非黑即白”

做融合先要解决一个哲学问题:如何表示一个传感器对目标的“判断程度”。贝叶斯方法要求你给出完整的先验概率和似然,而且所有类别的概率之和必须等于1,这意味着传感器必须“强行表态”。但现实里雷达看到一个低速静止目标,它真的分不清那是行人还是路侧金属护栏,你非要它给出行人概率0.5、护栏概率0.5,这个表示本身就是一种虚假精确。

Dempster-Shafer理论(以下简称DS理论)换了一种玩法。它把证据放到一个幂集空间上,允许你给整个子集分配概率质量,也就是基本概率分配(BPA)。传感器可以说:“我认为目标属于行人的基本概率是0.4,属于车辆的基本概率是0.3,属于‘行人或车辆’这个子集的基本概率是0.2,剩下的0.1留给整个识别框架表示完全未知。”注意,这里的“行人或车辆”是一个子集,贝叶斯框架里根本没有这种表示。这就是DS理论对证据融合最大的贡献:它能显式表达“部分支持多个假设但无法区分”和“完全不知道”。

2.2 BPA、信任函数与似然函数怎么读

设识别框架为Θ,比如Θ={行人,车辆,骑行者,未知},一个BPA函数m满足两个条件:空集的BPA为0,Θ所有子集的BPA之和为1。对任意子集A,目标的信任度Bel(A)等于所有BPA所对应子集被A包含的那些集合的质量之和;似然度Pl(A)等于所有与A交集非空的子集的质量之和。Bel和Pl之间那个区间,就是“不确定性区间”,区间越窄说明证据越充分。

生活化类比:你家有三个朋友推荐餐厅,A朋友说“那家店不是川菜就是湘菜”,B朋友说“那家店是湘菜”,C朋友说“那家店我完全吃不准”。A和C的表述在贝叶斯体系里没法直接表达,但在DS体系里很容易。每个推荐语就是一条证据,你要做的就是把这些证据合起来得到综合判断,同时保留信息不足带来的不确定性。DS合成就干这个活。

2.3 Dempster合成规则:证据的“交叉验票”

两条独立证据m1和m2的合成规则为:

m(A) = (1 / (1 - K)) * sum_{B∩C=A} m1(B) * m2(C)

其中K = sum_{B∩C=∅} m1(B) * m2(C),表示两条证据冲突的总质量。K等于1就说明两条证据完全矛盾,合成规则无定义;K接近1时,合成结果会被放大得很敏感,这也是DS理论最著名的“高冲突问题”的由来,我在第5节会细说。

从直觉上看,这个式子是在做“交叉验票”:对所有能同时支持假设A的证据组合求加权和,再用冲突系数K归一化。实现起来非常直白,但注意计算复杂度会随着识别框架子集数指数增长。在自动驾驶目标类别不多(一般小于10类)的前提下,直接在幂集上建矩阵是可行的;如果类别很多,就得用分解近似策略,比如把Mass函数的焦元限制在单元素和整个框架这两种,退化成一种“带未知项的加权平均”,复杂度直接降下来。

3. 信息矩阵融合算法:给证据加“底气”的数学骨架

3.1 信息矩阵到底是什么

信息矩阵在工程上最常见的定义是协方差矩阵的逆。协方差矩阵描述估计的不确定性,信息矩阵就描述“信息的多少”:信息矩阵越大,代表这个估计的不确定性越小、越可信。在多传感器融合里,信息矩阵天然适合做加权,因为直接把信息矩阵相加对应的是假设各传感器观测独立时的最优融合权重。

这里有个直观类比:两个测量员分别估算一座桥的长度,A的量具精度高,给出的误差方差小,信息量大;B的量具粗糙,误差方差大,信息量小。你该怎么平均两个结果?不是简单取算术平均,而是按信息量加权——测量精度高的结果应该拥有更大权重。信息矩阵融合算法做的事情,就是把传感器对目标的跟踪协方差转换为信息矩阵,再做加权融合,得到综合估计及其置信度。

3.2 在目标级融合里,信息矩阵扮演三个角色

第一个角色是关联门控的度量基础。两个传感器目标是否关联,不能只看位置差,还要看它们各自的信息矩阵。常用的马氏距离d² = (z1 - z2)ᵀ (P1 + P2)⁻¹ (z1 - z2)中,就用到了协方差融合后的逆,本质就是信息矩阵在起作用。第二个角色是融合权重来源。在把两个传感器的位置估计合并时,最优做法是让融合后的信息矩阵等于两个信息矩阵之和,融合后的信息向量等于两个信息向量之和。第三个角色是后续DS证据BPA构建的置信度参考。传感器给目标类别打分时,往往还会附带一个总体的“测量质量”,比如雷达回波信噪比、摄像头跟踪稳定度。把信息矩阵的迹或行列式映射为BPA中的未知项权重,就能让融合系统在“传感器心里没底”时自动增加对未知类的保留。

3.3 信息矩阵与DS怎么衔接不打架

如果只做信息矩阵融合,你得到的是一堆连续量——位置、速度、加速度的精化估计;如果只做DS融合,你得到的是离散类别的不确定性度量。两者是互补的。我在实现时的衔接方式是:先跑一遍基于信息矩阵的目标关联与状态融合,为每个目标生成一个“质量分”;然后对各传感器上报的类别证据做BPA调整,质量分高则降低该证据中的“未知”权重,质量分低则提高“未知”权重;最后用DS合成规则融合各传感器的修正证据。

结合之后的效果我实测下来是:单独用信息矩阵融合时,位置估计确实平滑,但碰上类别矛盾(一个传感器说行人、另一个说护栏)完全没辙;单独用DS融合时,类别能定下来,但目标位置精度没有提升。两者一旦串起来,融合出的目标不仅位置稳定,类别决策还带了一个可解释的置信区间,这对下游规划模块做行为预测非常关键——比如“置信度低的目标”默认走保守避让策略。

4. Matlab实现拆解:从BPA到融合主循环的完整代码

4.1 环境准备与数据约定

Matlab是一个好的实验场所,不是因为它的运行效率高,而是因为它能把矩阵运算和可视化捏在一起,非常适合先用小规模数据验证融合逻辑。我在模拟项目X中用的是R2022b(其实2020以上都够用)。这里约定:每个传感器目标结构体包含id、位置均值、协方差矩阵、类别概率向量、时间戳五要素。类别概率向量定义为[行人,车辆,骑行者,未知]顺序。传感器上报的目标位于一个公共坐标系中,前面的关联模块输出的是“疑似同一目标”的匹配对。

4.2 BPA构建:从类别概率到Mass函数

把类别概率转成BPA不是简单的复制粘贴。概率要求各类之和等于1,但Mass函数允许给子集分配质量。一个稳妥做法:保留单元素类的完整概率质量,然后把原概率向量中“未知”那一项扩展为“整个识别框架”的质量,同时把低于某个阈值的小概率类合并到“未知”里。这样做的好处是可以压制那些非常不可靠的微弱响应。

function mass = prob2bpa(probVec, unknownW) % probVec: [p1, p2, p3, p4] 对应 [行人, 车辆, 骑行者, 未知] % unknownW: 额外分配给全集的权重,用于吸收低置信度 assert(abs(sum(probVec) - 1) < 1e-6, '概率向量未归一化'); mass = zeros(1, 4); % 这里用4个位置分别表示{行人},{车辆},{骑行者},{全集} for i = 1:3 mass(i) = max(0, probVec(i) - 0.05); % 低于0.05的部分归入未知 end mass(4) = probVec(4) + (sum(probVec(1:3)) - sum(mass(1:3))) + unknownW; mass = mass / sum(mass); % 重新归一化 end

这个函数故意简化了焦元集合,只保留四个焦元:三个单例类和一个全集。更完整的实现还要支持“行人∪骑行者”这样的组合焦元,但对大多数自动驾驶类别决策,单例+全集的结构已经能覆盖绝大多数应用,而且矩阵尺寸小、合成速度极快。

4.3 Dempster合成规则的矢量化实现

之前公式里的sum_{B∩C=A},在Matlab里最优雅的实现方式是“张量操作”:构造一个三维数组,第(i,j,k)个元素表示m1的第i个焦元与m2的第j个焦元相交得到第k类结果的质量贡献。虽然三维数组会有点空间开销,但自动驾驶的类别数通常不超过10,焦元数不超过2^10,这在实际中完全可接受。如果想更省内存,也可以用两层for循环,但矢量化写法能让你一眼看清合成过程的数学结构。

function m12 = dempsterCombine(m1, m2, focalSets, numClasses) % focalSets: 每个焦元对应的类别位标记,比如[1 0 0 0]表示行人 % numClasses: 类别数 n1 = size(m1, 2); n2 = size(m2, 2); interMat = zeros(n1, n2); confK = 0; m12 = zeros(1, n1); for i = 1:n1 for j = 1:n2 inter = focalSets(i, :) & focalSets(j, :); if ~any(inter) confK = confK + m1(i) * m2(j); else interIdx = find(inter); if length(interIdx) == 1 m12(interIdx) = m12(interIdx) + m1(i) * m2(j); else % 交集是多元素子集时,质量归到全集位置 m12(numClasses + 1) = m12(numClasses + 1) + m1(i) * m2(j); end end end end if confK >= 1 warning('证据完全冲突,合成结果无定义,改用加权平均'); m12 = 0.5 * m1 + 0.5 * m2; else m12 = m12 / (1 - confK); end end

这段代码没有优化到极致,但胜在语义清晰。这里有一个容易写错的细节:两个焦元相交为空集时,其乘积贡献要累加到冲突系数K上,不能扔进任何类别;相交结果是一个多元素子集时,如果合并后的框架里没有显式的多元素焦元,应该把所有多元素交集的质量统一归到全集,否则做归一化时会丢质量。我最初实现时忽略了后一点,导致合成后总质量小于1,排查了很久才发现是交集归并逻辑漏了分支。

4.4 信息矩阵加权与融合决策的完整主循环

主循环的逻辑按时间片推进。每个时间片先做目标关联,再计算信息矩阵融合后的位置估计,然后修正各传感器证据的未知权重,最后执行DS合成并做决策。

function fusedTargets = targetFusionMain(tracksCam, tracksRadar, tracksLidar, cfg) tAll = {tracksCam, tracksRadar, tracksLidar}; numSensors = 3; fusedTargets = []; for tIdx = 1:length(tAll{1}) % 第一步:以主传感器目标为中心找关联 refTrack = tAll{1}(tIdx); candidateList = []; for sIdx = 2:numSensors trackList = tAll{sIdx}; for j = 1:length(trackList) d2 = mahalDist(refTrack, trackList(j)); if d2 < cfg.gateThresh candidateList(end+1).sensor = sIdx; %#ok<SAGROW> candidateList(end).track = trackList(j); candidateList(end).dist = d2; end end end if isempty(candidateList) % 找不到关联目标时,保留主目标但降低置信度 refTrack.confidence = refTrack.confidence * 0.7; fusedTargets(end+1) = refTrack; %#ok<SAGROW> continue; end % 第二步:信息矩阵融合位置估计 state = refTrack.state; infoMatrix = inv(refTrack.cov); infoVector = infoMatrix * state; for c = 1:length(candidateList) t = candidateList(c).track; infoMatrix = infoMatrix + inv(t.cov); infoVector = infoVector + inv(t.cov) * t.state; end fusedState = infoMatrix \ infoVector; fusedCov = inv(infoMatrix); % 第三步:根据质量分修正证据未知权重 quality = 1 / (trace(fusedCov) + 1); mList = []; mList(1, :) = prob2bpa(refTrack.classProb, 0.2 - 0.1 * quality); for c = 1:length(candidateList) t = candidateList(c).track; mList(c+1, :) = prob2bpa(t.classProb, 0.2 - 0.1 * quality); end % 第四步:逐对执行DS合成 massFused = mList(1, :); for c = 2:size(mList, 1) massFused = dempsterCombine(massFused, mList(c, :), cfg.FocalSets, cfg.NumClasses); end % 决策:找出质量最大的焦元,若最大与次大差距过小则归为未知 [mMax, idxMax] = max(massFused); sortedMass = sort(massFused, 'descend'); if idxMax == cfg.NumClasses + 1 || (sortedMass(1) - sortedMass(2)) < cfg.decisionMargin label = cfg.UnknownLabel; else label = cfg.ClassLabels{idxMax}; end fusedTargets(end+1).id = refTrack.id; %#ok<SAGROW> fusedTargets(end).state = fusedState; fusedTargets(end).cov = fusedCov; fusedTargets(end).label = label; fusedTargets(end).mass = massFused; fusedTargets(end).quality = quality; end end

上面的代码刻意保持结构简单,便于在上面做各种变形实验。实际工程中,还要额外考虑时间戳对齐、航迹管理、传感器噪声特性的在线辨识等,但这些不会改变融合逻辑的核心骨架。

4.5 让代码跑起来的几个关键配置

我见过不少同学卡在“理论看懂了,代码跑不出预期结果”上。检查顺序通常是先看归一化,再看焦元索引,再看门限。下面这几个配置参数值得单独拿出来说。

  • gateThresh(关联门限):我一般取9到12。这个值的物理含义是马氏距离,对应卡方分布的某个置信度区间。设得太小会漏关联,目标被硬生生拆成两个;设得太大会错关联,把不同目标合在一起,融合出的类别乱七八糟。
  • decisionMargin(决策边界):常取0.05到0.1。如果两个候选类的合成质量差值小于这个量,说明证据不足以支撑分类,果断归为未知,给下游规划模块一个“我不确定”的提示,远比一个错误标签安全。
  • 传感器权重初始化:不要把所有传感器一视同仁。我建议根据各传感器在典型工况下的漏检率和误检率先给一个初始质量分,再通过信息矩阵的迹动态调整。

5. 实测中的三大坑:高冲突证据、性能退化和关联误判

5.1 高冲突证据:DS合成规则翻车的现场

效果炸裂的雷区来自一条实际场景:摄像头对着一辆半挂车报“车辆0.7、未知0.3”,毫米波雷达因为多径反射报“护栏0.6、未知0.4”。这两条证据的冲突系数K高达0.78以上。用标准Dempster合成规则跑完,结果是“车辆”和“护栏”的质量双双被压低,而“未知”质量飙升到0.9。这个结果反而不坏,至少系统“承认自己不知道”。但更极端的Zadeh悖论场景下,两条高冲突证据会得到违背直觉的结论——某证据很强地说A,另一证据很强地说B,合成后却给一个完全不相关的C不小质量。这是DS理论出名的病灶。

我最终在代码里加了一道保险:当K > 0.7时,不直接使用标准合成结果,而是退化为“加权平均+未知偏置”的处理。这个方案牺牲了DS理论的一些精妙性质,换来的是稳定和可解释。在有安全要求的场景里,“稳定可解释”比“理论上最优”重要得多。

5.2 关联误判带来的“级联翻车”

一个更隐蔽的坑:关联误判引发的后续全部误判。摄像头报的“目标5”实际上是车道右侧的灯杆,被错误地与毫米波雷达报的“目标2(前方卡车)”关联上。由于灯杆协方差很小、信息矩阵权重很高,它直接拉偏了融合状态,使融合后的“卡车”位置产生了约1.5米的偏移,DS证据里也被塞进了一份高置信度的“未知”。排查时只看融合输出你会觉得系统“发疯了”,实际上问题出在关联门限和目标轨迹预测上。

我的处理方式是:在关联阶段不只用位置,而是加一个速度一致性检验。先比较两个候选目标的速度向量,夹角超过30度或速度差超过限值,即使位置马氏距离很近也判为不关联。这样能极大减少把“静态杆子”和“移动车辆”凑成一对的错误。

5.3 性能退化:Matlab里最容易被忽略的细节

性能问题主要出在循环和矩阵重复求逆上。朴素写法里每个时间片都做inv(cov),社交距离不大的时候无所谓,但一旦目标数量上百、传感器数量达到5个,性能直接掉一个数量级。我的优化顺序是:第一,用信息矩阵的递推更新代替重复求逆;第二,用mex或代码生成加速合成规则里的三重循环;第三,把焦元集合理化成全矩阵索引。

还有一个容易被忽略的点是Matlab的cell数组扩容。目标数量动态变化时,我最初用循环里不断append字段来记录融和结果,慢得惊人。后来改成预先分配结构体数组或用containers.Map管理目标ID到状态的映射,才算把实时性提上来。

6. 小结之外的一点私货:这套融合框架该怎么继续拓展

不想再多说理论,只分享一个经验方向。目标级融合做到后面,瓶颈几乎不在融合算法本身,随时在我前面提到的目标生命周期管理和场景先验建模上。比如在城区十字路口,车辆会长期静止排队,导致雷达和摄像头的“静态目标”证据高度冗余,融合系统如果不做目标存活性和消失判断,就会拖出一大批“幽灵目标”。这个方向适合在融合框架里加上跟踪管理模块。

如果做研究课题,我建议在DS证据的冲突判别上多花心思:把“证据本身不一致”和“目标关联错误导致的不一致”区分开,是一个相当有价值的点。我在模拟项目X里用K值的时间序列做滑动窗口分析,发现高K往往预示着目标切换或遮挡,这个信号对下游决策非常有帮助,代码量也不大,值得一试。

最后再分享一个小技巧:写完融合代码后,先用一组手工构造的极端数据做单元验证——摄像头和雷达给出完全相反的目标类别,K接近1,未加入冲突保护的代码会立刻翻车。我每次改完融合逻辑都会先跑一遍这组“魔鬼测试”,耗时五分钟,省下的排查时间都是以天计的。这类融合系统的价值不在数学形式多漂亮,而在面对互相矛盾的传感器时,它能不能给出一个让人放心、可以追溯的答案。

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

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

立即咨询