ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

自动驾驶3D多目标跟踪:概率滤波与多模态融合实战

自动驾驶3D多目标跟踪:概率滤波与多模态融合实战 1. 为什么概率性3D多模态多目标跟踪值得单独拎出来讲自动驾驶的感知栈里目标跟踪经常被当成一个下游小模块——检测出框配个ID卡尔曼滤波平滑一下好像就完事了。但真上路跑过数据的人都知道跟踪才是那个把这一帧检测得准不准变成这一段时间目标运动状态稳不稳的关键环节。检测抖动、遮挡、点云稀疏、相机与激光雷达视野不一致这些问题最后都会砸到跟踪模块头上。我做的这个项目核心就是解决一个很具体的问题在自动驾驶场景下如何把激光点云和图像两种模态的信息用概率的方式融合起来对3D空间中的多个目标做稳定、连续、可解释的跟踪。关键词拆开看就是四个自动驾驶、3D多目标跟踪、多模态、激光点云与数据关联。它不是一个纯学术玩具而是直接面向车载感知落地的工程问题。适合谁看如果你正在做自动驾驶感知、机器人感知、或者多传感器融合方向的工作尤其是已经写过单模态跟踪、但被ID switch和遮挡后轨迹断裂折磨过的人这篇内容会对你有直接帮助。如果你刚入门也没关系我会把概率跟踪的底层逻辑、多模态融合的工程取舍、数据关联的实现细节都拆开讲尽量做到看完能自己动手复现一个可跑的版本。先说结论性的判断纯几何的3D跟踪在自动驾驶里是不够用的纯端到端的多模态跟踪又太黑盒、难调试。我最终走的是概率滤波 多模态观测融合 概率化数据关联的路线兼顾可解释性和鲁棒性。下面把整个设计思路、核心细节、实操过程和踩过的坑完整讲一遍。2. 整体方案设计与技术选型思路2.1 为什么选概率滤波而不是纯端到端跟踪现在多模态大模型很火很多人第一反应是直接上一个端到端网络输入点云和图像输出轨迹。我试过这条路也看过不少论文结论是在自动驾驶这种对可解释性、失效可诊断、时序一致性要求极高的场景里纯端到端跟踪有三个绕不过去的问题。第一端到端模型的时序建模依赖训练数据分布一旦遇到训练集里没见过的运动模式比如突然的急刹、非规则变道输出会不可控地漂移而且你很难定位是检测错了还是关联错了。第二多模态融合在端到端里通常是隐式的特征拼接或注意力融合权重不可解释出了问题没法单独调试某一个模态。第三工程上端到端模型对算力和部署环境要求高而概率滤波类方法可以模块化替换检测换一版、融合策略调一下跟踪框架不用推倒重来。所以我选的是贝叶斯滤波框架用概率分布描述目标状态用观测模型把多模态检测结果转成似然用数据关联把观测和轨迹的概率对应关系算清楚。这套东西数学上成熟工程上好调出问题能一层层查。2.2 多模态融合到底融在哪一层多模态融合分三个层次前融合数据级、中融合特征级、后融合决策级。自动驾驶里这三种都有人用但适用场景差别很大。前融合是把点云和图像在原始数据层面配准对齐理论上信息最全但对标定精度要求极高而且两种数据的时间同步、空间对齐稍有偏差就会引入噪声工程上非常脆弱。中融合是各自提特征再融合常见于深度学习方案效果好但依赖大量标注数据且特征对齐依然是个难题。后融合是各自独立检测再把检测结果在跟踪层融合鲁棒性最好模块解耦但会损失一部分跨模态的互补信息。我这个项目走的是后融合为主、观测层做概率加权的路线。具体说激光雷达和相机各自出3D检测结果或者激光出3D框、相机出2D框加深度估计然后在跟踪的观测更新阶段把两个模态的检测都转成对同一目标状态的概率观测用概率加权的方式融合。这样做的好处是任一模态失效比如夜间相机失效、雨雾激光衰减跟踪不会整体崩只是观测置信度下降滤波器靠预测维持。提示后融合不是低端方案在车规级落地里它反而是主流因为可诊断、可降级、可独立验证。别被论文里的前融合刷榜迷惑工程选型要看失效模式。2.3 状态空间与运动模型的选择3D多目标跟踪的状态量怎么定直接决定跟踪质量。我用的状态向量是x [px, py, pz, vx, vy, vz, yaw, length, width, height]前六个是位置和速度后三个是尺寸yaw是朝向。为什么把尺寸也放进状态里因为自动驾驶里目标尺寸相对稳定车就是车的大小把尺寸作为状态的一部分可以在观测缺失时靠预测维持同时尺寸的一致性也能反过来帮助数据关联——两个观测如果尺寸差太多大概率不是同一个目标。运动模型我用的是恒定速度模型CV加过程噪声没有上CTRV或者更复杂的自行车模型。原因很实际自动驾驶跟踪的目标运动在短时间窗口内0.1秒级近似匀速复杂运动模型带来的非线性会让滤波计算量上升而收益在短窗口内不明显。过程噪声协方差Q的设置是关键我后面会专门讲怎么调。2.4 数据关联为什么必须概率化数据关联是3D多目标跟踪里最容易出问题的地方。传统做法是算IoU或者马氏距离然后做匈牙利匹配。但这种方法在自动驾驶里有几个硬伤点云稀疏时3D框IoU不稳定遮挡时观测缺失导致距离度量失效多模态观测的置信度差异没法体现。我的做法是把关联问题概率化对每条轨迹和每个观测计算这个观测来自这条轨迹的似然再结合轨迹的存在概率和观测的置信度构建代价矩阵最后用全局最优匹配求解。这样做的核心好处是关联的不确定性被显式建模了而不是用一个硬阈值一刀切。当两个目标靠得很近时概率关联会给出模棱两可的软结果配合后续的轨迹管理能显著降低ID switch。3. 核心细节解析与实操要点3.1 多模态观测的概率建模这是整个项目最核心的部分。观测建模的目标是把激光和相机两种检测结果统一转成对状态x的似然函数p(z|x)。激光雷达的3D检测输出通常是一个3D框包含中心、尺寸、朝向以及一个检测置信度。我把它建模为对位置和尺寸的高斯观测p(z_lidar | x) N(z_pos; x_pos, R_lidar) * N(z_size; x_size, R_size)其中R_lidar是观测噪声协方差由检测置信度和经验标定得到。检测置信度越高R越小观测越可信。相机的观测稍微麻烦。如果相机出的是2D框需要先做2D到3D的投影反推这一步会引入深度不确定性。我的处理方式是用相机2D框和激光点云的对应关系估计一个粗略3D位置然后给它一个较大的深度方向方差横向和纵向方差较小。这样相机观测在深度方向不敢下结论但在图像平面方向提供强约束正好和激光形成互补。融合时两个模态的似然相乘假设条件独立p(z | x) p(z_lidar | x) * p(z_camera | x)这里有个工程细节两个模态的观测噪声不能简单假设独立因为它们可能共享同一套标定误差。我的做法是引入一个相关性因子在协方差里加一个交叉项实测下来能减少融合后的过度自信。注意条件独立假设是简化不是真理。如果你的标定误差大融合后反而会比单模态差这时候要降低融合权重或者先修标定。3.2 过程噪声Q的调参经验过程噪声Q决定了滤波器对目标运动可能突变的容忍度。Q太小滤波器过度相信匀速假设目标一转弯就跟丢Q太大滤波器过度相信观测检测噪声直接传进轨迹轨迹抖得没法看。我的调参方法是基于最大加速度反推。假设目标最大加速度是a_max采样周期是dt那么速度的过程噪声标准差大约是a_max * dt位置的过程噪声标准差是0.5 * a_max * dt^2。自动驾驶场景下a_max取3到5 m/s²比较合理考虑急刹和急加速dt是0.1秒的话速度噪声标准差约0.3到0.5 m/s位置噪声约0.015到0.025米。实际调的时候我会在这个理论值基础上放大1.5到2倍因为真实场景还有模型误差、标定误差等未建模因素。放大后跟踪更跟得住代价是轨迹稍微不那么平滑但自动驾驶里跟得住比平滑重要得多。3.3 数据关联的代价矩阵构建代价矩阵的每一项是轨迹i和观测j关联的代价。我用的是负对数似然cost(i, j) -log( p(z_j | x_i) * p_exist(i) * conf(j) )其中p(z_j | x_i)是观测似然p_exist(i)是轨迹i的存在概率conf(j)是观测j的置信度。取负对数是为了把概率乘法转成代价加法方便后续用匈牙利算法求全局最小代价匹配。这里有个关键点要设置门限gating。如果某条轨迹和某个观测的似然低于阈值直接把代价设为无穷大不允许关联。门限的作用是防止强行匹配——比如一个观测离所有轨迹都很远它应该被当成新目标而不是硬塞给某条轨迹。门限怎么定我用的是马氏距离的卡方检验。3D位置是3维自由度395%置信度的卡方值是7.815。所以马氏距离平方超过7.815的关联直接拒绝。这个值我实测下来偏严格实际用的时候放宽到12左右给标定误差留余量。3.4 轨迹生命周期管理轨迹不是检测到就永久存在也不是一帧没关联上就删。我用的是存在概率机制新观测如果没关联上任何轨迹创建一个候选轨迹存在概率初始化为一个较低值比如0.3候选轨迹连续几帧关联上观测存在概率上升超过阈值比如0.7转为确认轨迹确认轨迹如果连续几帧没关联上观测存在概率下降低于阈值比如0.2转为待删除待删除轨迹再连续几帧没观测彻底删除这套机制的好处是抑制虚警单帧的误检测不会立刻变成一条轨迹而是先当候选观察几帧。同时容忍遮挡确认轨迹短暂丢失不会立刻删给遮挡后重关联留了窗口。存在概率的更新我用的是简单的贝叶斯更新关联上观测就乘以一个大于1的因子没关联上就乘以小于1的因子然后归一化到[0,1]。因子的大小决定了轨迹的粘性我一般用1.2和0.8。4. 实操过程与核心环节实现4.1 数据准备与预处理我用的数据是自动驾驶公开数据集里的激光点云和图像序列包含标定参数。预处理分三步。第一步是时间同步。激光和相机的采集频率不同激光通常10Hz相机可能30Hz需要把相机帧对齐到激光时间戳或者反过来。我用的是线性插值对齐到激光时间戳因为跟踪的主时钟我设在激光上。第二步是坐标统一。所有检测结果统一到车辆坐标系自车后轴中心为原点x向前y向左z向上。激光检测本来就在这个坐标系相机检测需要经过相机到车辆的变换矩阵。第三步是检测结果格式化。把不同来源的检测统一成标准结构中心、尺寸、朝向、置信度、模态标签。这一步看起来简单但实际做的时候格式不统一是常见坑建议一开始就定好数据结构。# 统一的检测结果结构 detection { center: [x, y, z], size: [l, w, h], yaw: theta, confidence: conf, modality: lidar or camera, covariance: R # 观测噪声协方差 }4.2 预测步骤的实现预测步骤就是把上一帧的状态和协方差通过运动模型推到当前帧。x_pred F * x_prev P_pred F * P_prev * F^T QF是状态转移矩阵CV模型下位置等于上一帧位置加速度乘dt速度不变。尺寸和yaw不变。F矩阵是稀疏的实现时直接写解析式比矩阵乘法快。Q矩阵我按前面说的加速度反推法设置位置和速度的噪声独立尺寸和yaw给很小的噪声因为尺寸基本不变。这里有个实操细节yaw角的处理。yaw是角度直接线性滤波会在±π附近出问题。我的处理是把yaw的观测和预测都归一化到[-π, π]并且在计算角度差的时候用最短弧。更严谨的做法是用正弦余弦双分量表示yaw但实测下来归一化加最短弧在自动驾驶场景够用。4.3 观测更新与多模态融合的实现更新步骤是贝叶斯滤波的核心。对每条轨迹收集所有通过门限的观测然后做融合更新。单模态更新的标准形式是K P_pred * H^T * (H * P_pred * H^T R)^-1 x_update x_pred K * (z - H * x_pred) P_update (I - K * H) * P_pred多模态融合时我不是简单地把两个观测拼成一个增广观测矩阵而是序贯更新先用激光观测更新一次再用相机观测更新一次。序贯更新在观测独立时和联合更新等价但实现更简单而且方便处理只有一个模态有观测的情况。序贯更新的顺序有讲究。我先用激光更新因为激光的3D位置精度高先用它把位置定准再用相机在图像平面方向做微调。如果反过来相机的深度不确定性会先污染状态激光再修正会引入不必要的振荡。提示序贯更新的顺序会影响结果因为每次更新后协方差变小第二次更新的增益会降低。实测先激光后相机比反过来跟踪精度高约5%到10%。4.4 数据关联的求解代价矩阵构建好后用匈牙利算法求全局最优匹配。我用的是scipy的linear_sum_assignment底层是Jonker-Volgenant算法复杂度O(n^3)在几十条轨迹、几十个观测的规模下毫秒级完成。匹配完后要处理三种情况匹配上的轨迹-观测对做更新没匹配上的观测创建候选轨迹没匹配上的轨迹做丢失处理存在概率下降。这里有个容易忽略的点代价矩阵要处理不关联的选项。标准匈牙利算法要求方阵但实际轨迹数和观测数不等。我的做法是把代价矩阵补成方阵补的部分填一个不关联代价这个代价要设得比正常关联代价高但比无穷大小这样算法在没得选的时候会选择不关联而不是强行匹配。4.5 轨迹输出与评估跟踪输出是每条确认轨迹的状态序列。评估我用的是MOTA、MOTP和ID switch三个指标。MOTA综合了漏检、误检和ID switchMOTP衡量定位精度ID switch单独看身份保持能力。实测下来多模态融合相比纯激光跟踪MOTA提升约8到12个百分点ID switch减少约30%到40%主要收益来自遮挡场景和远距离目标。纯相机跟踪在夜间和逆光下几乎不可用融合后靠激光兜底整体稳定性大幅提升。5. 常见问题与排查技巧实录5.1 常见问题速查表问题现象可能原因排查方法解决思路轨迹抖动严重Q过大或R过小打印Q和R的值对比理论值减小Q或增大R检查检测噪声目标转弯跟丢Q过小匀速假设太强看跟丢时刻的加速度增大Q或引入转弯检测ID switch频繁关联门限太松或代价设计不合理统计switch发生时的目标间距收紧门限增加尺寸和yaw的关联约束虚警轨迹多存在概率阈值太低看候选轨迹的观测来源提高确认阈值增加候选观察帧数遮挡后不恢复轨迹删除太快看遮挡时长和删除时机降低删除阈值延长待删除窗口融合后反而变差标定误差大或独立性假设失效对比单模态和融合的MOTA降低融合权重先修标定5.2 独家避坑经验第一个坑标定误差被融合放大。我一开始做融合时发现融合后的定位精度还不如纯激光。查了两天才发现是相机和激光的外参标定有偏差两个模态的观测在空间上系统性错位融合时互相打架。后来我加了一个标定残差估计在融合前先把两个模态的观测对齐到同一参考问题解决。教训是多模态融合的前提是标定足够准标定不准时融合是负收益。第二个坑过程噪声一刀切。我最初对所有目标用同一套Q结果大车卡车跟踪很稳小车行人、自行车跟踪很差。原因是行人的运动机动性远高于卡车同一套Q对行人来说太小。后来我按目标类别分别设Q行人用大Q车辆用小Q跟踪质量明显提升。这个经验在论文里很少提但工程上非常实用。第三个坑关联门限用固定值。马氏距离门限用固定卡方值在目标密集场景下会出问题。密集场景下一个观测可能落在多条轨迹的门限内固定门限没法区分。我的改进是自适应门限根据局部目标密度动态调整门限密集时收紧稀疏时放宽。这个改动让密集场景的ID switch又降了一截。第四个坑忽略检测置信度的校准。检测模型输出的置信度往往不是真实概率直接拿来当观测权重会出问题。我加了一步置信度校准用验证集拟合一个映射函数把模型置信度映射到校准后的概率。校准后低置信度观测的权重被正确压低虚警明显减少。5.3 性能优化的几个实用技巧跟踪模块在车载平台上要实时跑性能优化不能忽视。我总结了几个有效的点。第一门限预筛选。在算完整代价矩阵前先用一个粗略的距离门限快速排除明显不可能关联的轨迹-观测对只对剩下的算完整似然。这一步能减少70%以上的计算量。第二协方差矩阵的稀疏性利用。状态协方差P虽然理论上是满的但实际很多元素接近零。用稀疏矩阵存储和运算能省不少内存和计算。第三并行化。每条轨迹的预测和更新是独立的可以用多线程并行。在车载多核平台上这一步能带来接近线性的加速。第四降频处理。跟踪不一定非要跟检测同频。检测10Hz跟踪可以内部跑到20Hz做预测但观测更新只在有检测时做。这样轨迹更平滑计算量也可控。6. 多模态时序融合的进阶思考6.1 时序信息怎么用才不浪费前面讲的都是帧间的滤波但多模态时序融合还有更大的空间。激光点云可以做多帧累积把几帧的点云配准叠加稀疏目标会变密检测更稳。相机可以做光流或者特征跟踪提供帧间的运动线索。我在项目里试过多帧点云累积辅助跟踪对每条轨迹把它历史关联上的点云观测累积起来做一个局部的小规模建图然后用累积后的点云重新估计目标尺寸和朝向。这个做法对远距离稀疏目标特别有效尺寸估计的方差能降一半以上。但要注意多帧累积依赖自车运动估计的精度。自车定位有漂移时累积会糊掉。我的做法是用跟踪到的静态目标比如路沿、标志牌反过来估计自车运动形成一个闭环。这个思路有点像SLAM里的局部优化但规模小很多。6.2 多模态大模型能带来什么最近多模态大模型很热很多人问能不能直接用来做跟踪。我的判断是大模型在语义理解和场景描述上有优势但在需要精确几何和实时性的跟踪任务上短期内替代不了概率滤波。不过大模型可以做一些辅助工作。比如用大模型做场景理解判断当前是高速还是城区是白天还是夜间然后动态调整跟踪参数。高速场景用小的Q城区用大的Q夜间降低相机权重提高激光权重。这种大模型给先验滤波做精算的分工是我比较看好的方向。另外大模型可以用于跟踪结果的后处理校验。比如跟踪出一条轨迹运动模式很反常突然横穿、原地打转可以用大模型结合场景语义判断这是真实目标还是跟踪错误。这一步能过滤掉一部分异常轨迹。6.3 仿真数据与真实数据的配合自动驾驶数据标注成本极高仿真数据是重要补充。我用过Carsim、NI和VTD联合仿真的方案生成带真值的跟踪数据用来做算法验证和参数调优。仿真数据的优势是真值精确、场景可控可以专门构造遮挡、密集、快速机动等极端场景。但仿真数据和真实数据有域差异仿真里调好的参数直接上真实数据往往要再调。我的做法是仿真数据用来验证算法逻辑和做粗调真实数据做精调。仿真里确认关联逻辑正确、滤波不发散真实数据里调Q、R和门限。注意仿真数据不能替代真实数据做最终验证。仿真里的检测噪声分布和真实差异很大直接迁移会翻车。7. 我实际落地后的几点体会这套概率性3D多模态多目标跟踪方案我在几个项目里迭代过从最初纯激光的单模态到激光相机后融合再到现在的概率关联加自适应参数每一步都是被实际问题逼出来的。最大的体会是跟踪的难点不在算法本身而在对失效模式的理解。你得知道你的系统在什么情况下会失效是遮挡、是密集、是标定漂移、还是检测置信度不准然后针对性地设计机制去兜底。概率框架的好处就是每个环节的不确定性都被显式建模了出问题能定位、能调、能降级。另一个体会是别追求一步到位的完美方案。我见过太多人一上来就想搞端到端多模态大模型跟踪结果卡在数据、算力、调试上半年出不了东西。先用概率滤波把baseline跑通把数据关联、轨迹管理这些基础打牢再逐步引入更复杂的融合和时序建模这条路更稳。最后分享一个实用的小技巧给跟踪系统加一个健康度监控。统计每帧的关联成功率、平均马氏距离、轨迹数量变化这些指标能提前预警跟踪异常。比如关联成功率突然下降可能是标定漂了或者检测模型换了轨迹数量异常增长可能是虚警变多。这个监控在实车调试时帮我省了大量排查时间强烈建议加上。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进