想象你走进深夜的机场塔台。雷达屏幕上几十个光点缓缓移动,管制员不会只喊一句“那边有飞机”,而是给每个光点分配一个航班号:CZ3456 正在爬升,MU5122 正在减速,3U8882 即将进入我的区域。这个从“看见一个光点”到“知道它是谁、要去哪、会不会和谁相遇”的过程,就是动态障碍物跟踪的缩影。 自动驾驶汽车也有一座自己的“塔台”。激光雷达、摄像头、毫米波雷达每几十毫秒送来一批检测框或点云,但这些只是“这一帧看到了一个对象”,并不知道上一帧的同一个对象在哪里。动态障碍物跟踪要做的,就是把零散的观测串成连续、带身份信息的轨迹,并预测它下一步的位置。本文就以“塔台管制员”为主角,带你从概念、算法、评估到工程调优,完整理解这项自动驾驶感知系统的关键能力。
对 AI 从业者而言,动态障碍物跟踪是打通“感知-预测-规划”链条的必经之路。理解它,你才能从“会用检测模型”进阶到“能设计完整自动驾驶感知系统”。
可视化演示
演示多目标检测关联、卡尔曼滤波状态估计与轨迹预测三大环节,直观展示自动驾驶如何在连续帧中锁定并预测障碍物运动。
本节配有交互动效(进入视口后自动加载,约 3KB)。
检测关联 检测框与轨迹匹配 匈牙利算法 分配ID实现跨帧持续跟踪
跟踪基础概念
深夜的机场塔台,雷达屏幕上几十个光点缓缓移动。管制员不会只喊一声“那边有飞机”,而是给每个光点分配一个航班号:CZ3456 正在爬升,MU5122 正在减速……这个从“看见”到“知道是谁、要去哪”的过程,就是动态障碍物跟踪的缩影。
自动驾驶汽车也有自己的“雷达屏幕”。激光雷达、摄像头、毫米波雷达每几十毫秒送来一批检测框或点云,但它们只是“这帧看见了一个对象”,并不知道上一帧的同一个对象在哪里。动态障碍物跟踪要做的,就是把这些零散观测串成连续、带身份信息的轨迹。
在感知系统里,跟踪位于检测之后、轨迹预测与规划之前。它维护一个 Track 列表,每个 Track 拥有唯一 ID、位置速度、历史轨迹和置信度。动态障碍物指会主动或被动移动的交通参与者,包括车辆、行人、骑行者;静态障碍物通常交给地图与语义分割处理。跟踪器的输出状态可以表示为一个向量:
就像管制员靠航班号组织所有调度动作,跟踪器靠 ID 让后续预测、关联、规划都有抓手。没有 ID,传感器数据只是一地散落的珠子;有了跟踪,珠子才被串成项链。
- 状态向量\( \mathbf{x}_k \) 表示第 \( k \) 帧目标的完整运动状态,是一个四维列向量。
- 位置坐标\( x_k,\ y_k \) 是目标在自车坐标系或图像坐标系下的位置。
- 运动速度\( v_{x,k},\ v_{y,k} \) 是 \( x \)、\( y \) 方向的速度,用于预测下一帧位置。
- 转置符号\( T \) 表示把行向量转成列向量,方便矩阵运算。
感知输入解析
塔台管制员从不只依赖一台雷达,还有 ADS-B 广播、天气雷达、肉眼观察。每种信息源都有自己的脾气:雷达看得远但不够细,ADS-B 有身份却可能失效。自动驾驶的感知系统同样如此。
摄像头像管制员的眼睛,纹理与颜色丰富,能分辨交通灯、车道线和行人;但在黑夜、逆光、雨雾中会看不清,单目也没有可靠深度。激光雷达像高精度三维扫描仪,通过发射激光获得点云,能准确测距,但雨雪天气会衰减、成本较高。毫米波雷达更像传统雷达,测距测速可靠,全天候工作,但角度分辨率低,难以区分路边的栏杆和行人。
这些感知源经过目标检测后,输出“检测框”或“目标点”,在跟踪系统中称为观测(Measurement)。不同传感器输出维度不同:图像是 2D 框,激光雷达是 3D 框或聚类中心,毫米波雷达是目标点加径向速度。跟踪器必须理解每个观测的坐标系和噪声水平,才能做好后续的关联与滤波。
没有完美的传感器,只有互补的组合。就像塔台把雷达高度、ADS-B 计划、飞行员语音交叉印证,自动驾驶也需要在时间同步和坐标统一后,把多源观测揉进同一个跟踪框架。
数据关联配对
雷达屏幕上每帧都会冒出新的光点,管制员首先要回答:这个新光点,是刚才那架飞机的新位置,还是一架刚进入区域的新飞机?这个“认领”的过程,就是数据关联。
数据关联发生在已有轨迹与新检测之间。每条轨迹会给出一个预测位置,每个检测也有自己的位置;关联算法计算它们之间的相似度,比如中心距离或 IoU(交并比)。最简单的做法是最近邻匹配:每个检测找离它最近的轨迹;更稳健的做法是全局匹配。
当多个目标挤在一起时,最近邻可能互相打架。工程上常用贪心策略:先按代价从小到大排序,优先绑定最确信的一对;想要全局最优则用匈牙利算法,把关联问题建模成二分图最小代价匹配:
关联就像塔台逐一点名:点对了,轨迹延续;点错了,两架飞机的身份就会张冠李戴,后续所有预判都失去意义。数据关联是跟踪防混淆的第一道防线。
\min \sum_{i=1}^{m}\sum_{j=1}^{n} c_{ij} x_{ij}\quad \text{s.t.}\quad\sum_{i=1}^{m} x_{ij} \le 1,\quad\sum_{j=1}^{n} x_{ij} \le 1,\quadx_{ij} \in \{0,1\}- 代价矩阵\( c_{ij} \) 表示第 \( i \) 条轨迹与第 \( j \) 个检测之间的不相似度,通常用 \( 1 - \text{IoU} \) 或距离表示。
- 决策变量\( x_{ij} = 1 \) 表示把轨迹 \( i \) 与检测 \( j \) 配对。
- 行约束每个检测最多被一条轨迹认领,防止一对多。
- 列约束每条轨迹最多匹配一个检测,防止分身。
- 目标函数使所有配对的总代价最小,也就是让身份错配的总风险最低。
运动状态估计
管制员看到飞机当前位置后,会按照速度和航向估算几秒后的位置。卡尔曼滤波做的就是这件事:先按运动模型往前推一步,再用新的观测修正,反复循环。
在自动驾驶中,目标通常用匀速运动模型近似,认为短时间内速度基本不变。状态方程和测量方程写成:
卡尔曼滤波的核心是“预测”与“校正”交替。校正公式可以写成:
卡尔曼滤波之所以被广泛使用,是因为它把“模型预测的不确定度”和“传感器测量的不确定度”放在同一把尺子上比较。预测噪声大、观测准,就多信观测;反之多信预测。就像塔台不会因为一次雷达回波抖动就大幅改变航线判断,卡尔曼滤波也在“惯性预测”和“新鲜观测”之间取折中,让轨迹平滑而灵敏。
- 预测状态\( \hat{\mathbf{x}}_k^- \) 是根据上一帧推出来的先验位置。
- 观测残差\( \mathbf{z}_k - \mathbf{H}\hat{\mathbf{x}}_k^- \) 是“实际观测”与“预测观测”的差距。
- 卡尔曼增益\( \mathbf{K}_k \) 是一个权衡系数,决定相信观测多一点还是相信预测多一点。
- 修正状态\( \hat{\mathbf{x}}_k \) 是融合后的后验状态,也就是最终输出的平滑跟踪结果。
轨迹生命周期
一架身份不明的飞机突然出现在雷达边缘,管制员不会马上给它正式航班号,而是先标“未知机”,连续几帧确认后才建立档案。轨迹生命周期遵循同样的谨慎逻辑。
跟踪器收到首个检测时,不会立刻输出给下游,而是创建 Tentative(暂定)轨迹。只有当它连续若干帧都被关联成功,才升级为 Confirmed(确认)。被确认后,每一帧成功关联都会“续命”;一旦没有匹配观测,轨迹进入 Lost(丢失)状态。
真正困难的是遮挡。目标被大车或路边建筑挡住三五帧时,跟踪器仍会用运动模型继续预测,这叫 Coasting(滑行预测),同时把失配计数加一。如果目标重新出现且落在预测门内,就恢复关联,ID 保持不变。超过阈值仍找不到,才删除轨迹。
生命周期的核心是“保守确认、宽容保持、果断删除”。就像塔台档案管理:没有足够证据不建档,证据确凿不轻易销档,确认彻底离开才归档。
- 暂定轨迹命中次数不足 \( N_{\text{confirm}} \) 时,只保留不完全可信的候选身份。
- 确认轨迹连续命中达到阈值后,正式交付给下游规划模块。
- 丢失轨迹连续丢失观测次数超过 \( N_{\text{delete}} \),轨迹被删除并释放 ID。
多目标评估指标
如何评价一位管制员干得好不好?不能只看雷达上有没有飞机,还要看他有没有跟丢、有没有把 A 机当成 B 机。自动驾驶跟踪也需要一套“考核表”。
多目标跟踪最常用的指标是 MOTA(多目标跟踪准确度),它把三类错误统一折算:误检 FP、漏检 FN 和身份切换 IDS。公式如下:
MOTA 高不代表完美:它可能仍伴随大量 ID Switch,而规划层最怕身份乱跳——一辆车忽然变成另一辆车,紧急制动就会误判。所以工程上还会单独看 IDS 和 MOTP(目标位置精度),并关注算法能否在 20~30 Hz 甚至更高帧率下实时运行。
评价指标就是塔台考核的“红黑榜”:既看总准度,也看身份错乱次数。只有多指标一起看,才不会被一个漂亮分数骗过去。
- 误检 FP本来没有目标,检测器却输出一个框。
- 漏检 FN目标存在但没被检出。
- 身份切换 IDS同一个目标的 ID 发生跳变,例如被重新编号。
- 真值数量 GT人工标注的标准目标总数。
- 归一化与补数把三类错误总数除以 GT,再用 1 减去,得到 0~1 之间的准确率。
实战调优策略
再好的管制流程也要靠反复演练和参数微调。自动驾驶跟踪器同样要在开放道路前,经历大量仿真、封闭场地和路测迭代。
先调关联阈值。IoU 阈值设得高,两个框稍微分开就被当成新目标,轨迹碎成一段段;设得低,两个不同目标会被并成一个,ID 混淆。工程上通常用验证集的 MOTA 和 IDS 做参数扫描,找到平衡点。
更难啃的是遮挡、切入、密集人群。这时只靠单传感器不够,需要把相机、毫米波雷达、激光雷达融合:先做时间戳对齐和坐标标定,再把多源观测送入同一跟踪器。白天依赖相机细节,黑夜或雨雾依赖雷达和激光雷达。融合不是简单相加,而是各取所长。
工程迭代方法像塔台复盘:把路测中的 bad case 录下来回放,看关联矩阵、滤波增益、轨迹状态,找到错跟或丢跟的根因,再更新参数或模型,重新回到 MOTA/IDS 榜单验证。这样循环下去,跟踪系统才会越来越接近一个冷静老练的“虚拟管制员”。
AI 应用场景
城市路口行人跟踪
阶段:感知融合与动态跟踪
解决的问题:传统单帧检测只能给出当前帧的检测框,无法判断画面里连续出现的行人是同一个人还是不同的人。路口行人互相遮挡、姿态变化大,单帧检测容易出现漏检和跳变。动态障碍物跟踪通过数据关联和卡尔曼滤波,维持每个行人的 ID,并平滑位置轨迹,让下游 AEB 或规划模块能判断“这个人是否在朝车辆移动”。
具体案例:一辆自动驾驶汽车在左转路口遇到三组过街行人。其中一个行人被前方广告牌遮挡了 4 帧,跟踪器进入 Coasting 状态,用匀速模型持续外推;行人重新出现后,跟踪器在预测门内找回他,ID 保持不变,车辆平稳减速让行,没有急刹。
高速 NOA 邻车切入预警
阶段:动态目标管理与预测
解决的问题:高速场景下,旁车道车辆频繁切入,检测器偶尔会漏掉被 A 柱遮挡的车辆。传统方法只输出“当前有没有车”,难以判断“这辆车是不是刚才那辆在逼近的车”。跟踪系统为每个邻车维护轨迹和速度,提前判断切入意图。
具体案例:某车型的高速领航辅助在行驶中,一辆白色 SUV 从右侧车道快速切入。跟踪器连续 8 帧关联成功,确认轨迹后把该车的横向速度传给预测模块,系统提前 1.2 秒减速,避免不必要的紧急制动。
Python 演示
import random def iou(box1, box2): x1 = max(box1[0], box2[0]) y1 = max(box1[1], box2[1]) x2 = min(box1[0] + box1[2], box2[0] + box2[2]) y2 = min(box1[1] + box1[3], box2[1] + box2[3]) inter = max(0.0, x2 - x1) * max(0.0, y2 - y1) area1 = box1[2] * box1[3] area2 = box2[2] * box2[3] return inter / (area1 + area2 - inter + 1e-9) class Track: def __init__(self, box): self.box = list(box) self.vx = 0.0 self.vy = 0.0 self.hit_count = 0 self.lost_count = 0 def update(self, det): self.vx = det[0] - self.box[0] self.vy = det[1] - self.box[1] self.box = list(det) self.hit_count += 1 self.lost_count = 0 class TrackManager: def __init__(self): self.tracks = [] def update(self, detections, iou_thresh=0.3): assigned = [False] * len(detections) for track in self.tracks: best_iou = iou_thresh best_idx = -1 for i, det in enumerate(detections): if assigned[i]: continue score = iou(track.box, det) if score > best_iou: best_iou = score best_idx = i if best_idx >= 0: assigned[best_idx] = True track.update(detections[best_idx]) else: track.lost_count += 1 for i, det in enumerate(detections): if not assigned[i]: self.tracks.append(Track(det)) self.tracks = [t for t in self.tracks if t.lost_count <= 5] if __name__ == "__main__": random.seed(42) manager = TrackManager() truth = [[10, 10], [60, 40], [110, 70]] for step in range(8): dets = [] for i, pos in enumerate(truth): truth[i] = [pos[0] + 2, pos[1] + 1] dets.append([ truth[i][0] + random.uniform(-1.0, 1.0), truth[i][1] + random.uniform(-1.0, 1.0), 8, 8 ]) manager.update(dets) print("step", step, "track_count", len(manager.tracks))
return inter / (area1 + area2 - inter + 1e-9)计算两个检测框的交并比 IoU,值越接近 1,说明两个框越像同一个目标。if score > best_iou:在未分配的检测中找 IoU 最大的候选,体现贪心关联策略。track.update(detections[best_idx])找到匹配后,用新检测更新轨迹状态,相当于“管制员确认这架飞机的新位置”。self.tracks.append(Track(det))没有匹配到任何旧轨迹的检测,会被创建为新轨迹,也就是“新光点建档”。self.tracks = [t for t in self.tracks if t.lost_count <= 5]连续丢失超过 5 帧的轨迹被删除,对应轨迹生命周期中的删除策略。
常见误区
误区我认为跟踪和检测是一样的,模型每次输出检测框,把这些框连起来就是跟踪。
正解检测只回答“这一帧哪里有障碍物”,不回答“它是不是上一帧那个物体”。跟踪器需要在检测结果之上做数据关联、状态估计和轨迹管理,才能维持 ID 的连续。就像管制员不能只看雷达上有没有光点,还要知道每个光点是哪架飞机。
为何常见:很多目标检测视频会直接在画面上叠加 ID 和轨迹,看起来像是检测模型自己完成的,容易让人忽略背后的跟踪模块。
误区既然有卡尔曼滤波预测,目标被挡住也没关系,模型能一直算出准确位置。
正解卡尔曼滤波是有不确定度的预测。没有新观测输入时,预测协方差会不断增大,位置会越来越不可信。工程上必须配合轨迹生命周期,设置丢失上限,不能无限“脑补”。
为何常见:科普文章常把卡尔曼滤波描述成“预测神器”,忽略了它同样依赖观测来校正确实存在的不确定性。
误区模型评估报告里 MOTA 到了 95%,我就认为跟踪系统已经完美无缺。
正解MOTA 把 FP、FN、IDS 折算成一个综合分,但它不反映轨迹是否平滑,也不反映预测框的位置精度。规划模块真正关心的 ID 稳定性,还要单独看 ID Switch;位置精度要看 MOTP。
为何常见:MOTA 是论文里最常见的单指标,读者容易把它当成“唯一答案”,忽略它背后的多个分项。
误区只要把摄像头、激光雷达、毫米波雷达全装上,跟踪效果肯定会自动变好。
正解多传感器融合必须先做时间戳对齐和坐标系标定。如果标定有误差,同一个目标在两种传感器里会变成两个不同的观测,反而增加关联混淆。融合是系统工程,不是简单堆硬件。
为何常见:“多即好”是常见直觉,但感知系统更看重的是一致、可靠、可校准的输入。
面试题
Q1. 动态障碍物跟踪中“跟踪”最核心的目标是?
- A.逐帧检测目标
- B.跨帧维持身份← 正确答案
- C.识别静态道路
- D.提高相机帧率
答案:B。跟踪的本质不是“每帧找出目标”,而是把不同帧的同一个目标关联起来,维持稳定的 ID。检测只是跟踪的输入。
Q2. 毫米波雷达相对相机的主要优势是?
- A.色彩与纹理信息
- B.全天候测距测速← 正确答案
- C.点云稠密且便宜
- D.能识别车道线
答案:B。毫米波雷达在雨雾黑夜等恶劣天气下仍能测距测速,这是它最大的价值。相机虽然纹理丰富,但受光照影响大。
Q3. 数据关联要解决的问题是?
- A.新观测匹配旧轨迹← 正确答案
- B.检测框颜色增强
- C.提高传感器帧率
- D.训练检测模型参数
答案:A。数据关联的核心是判断“这个新观测属于哪条旧轨迹”,就像塔台辨识雷达光点是哪架飞机。
Q4. 新目标首帧出现时,跟踪器通常先创建什么轨迹?
- A.暂定轨迹← 正确答案
- B.确认轨迹
- C.删除轨迹
- D.融合轨迹
答案:A。为避免单帧误检污染系统,新目标先建 Tentative 暂定轨迹,连续几帧确认后才升级为 Confirmed。
Q5. 下列哪些属于轨迹生命周期状态?
- A.暂定与确认← 正确答案
- B.更新与保持← 正确答案
- C.遮挡与丢失← 正确答案
- D.融合与规划
答案:ABC。轨迹有暂定、确认、保持、丢失、删除等状态;融合与规划属于下游模块,不是轨迹自身的生命周期状态。
Q6. MOTA 中的三类误差是?
- A.误检漏检与ID切换← 正确答案
- B.相机标定与时间同步
- C.目标大小与运动速度
- D.图像亮度与颜色对比
答案:A。MOTA 综合了 FP(误检)、FN(漏检)和 IDS(身份切换),用真值总数归一化后得到跟踪准确度。
Q7. 多传感器融合前必须处理哪些问题?
- A.时间戳对齐← 正确答案
- B.坐标系标定← 正确答案
- C.检测框颜色
- D.车道线颜色
答案:AB。摄像头、激光雷达、毫米波雷达采样时刻和坐标系不同,如果时间戳和标定不一致,同一个目标会变成两个观测,导致关联混乱。
Q8. 匈牙利算法在数据关联中的主要作用是?
- A.全局最优配对← 正确答案
- B.局部最近配对
- C.随机均匀配对
- D.按时间排序配对
答案:A。匈牙利算法通过优化总代价矩阵,得到全局最优的一对一匹配,比逐个最近邻更稳健,适合密集场景。
Q9. 目标被长时间遮挡后重新出现,最容易出现哪类问题?
- A.身份切换错误← 正确答案
- B.相机内参漂移
- C.激光雷达积灰
- D.道路结构变化
答案:A。长时间遮挡后,预测位置可能偏离真实位置,重出现时可能被关联到新轨迹,导致 ID Switch。这正是 IDS 指标要重点监控的问题。
Q10. 关于多目标跟踪评估,正确的说法是?
- A.MOTA高不等于无ID切换← 正确答案
- B.IDSwitch记录跳变次数← 正确答案
- C.只看检测精度即可
- D.关联错误导致跳变← 正确答案
答案:ABD。MOTA 是综合指标,高不代表没有身份切换;ID Switch 专门统计身份跳变;数据关联是导致 ID 跳变的主要来源。跟踪评估不能只看检测精度。