ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

基于MATLAB的雷达与AIS航迹融合:时空对齐与滤波实现

基于MATLAB的雷达与AIS航迹融合:时空对齐与滤波实现

雷达和AIS,是水上交通监控里最常用也最容易“打架”的两类信息来源。雷达每个扫描周期都能给出目标的位置,但不知道这条船是谁;AIS每隔几秒到几分钟报一次船名、航速、航向,但目标一旦关机或者报文延迟,监控画面就会出现一条“隐身船”。把两者的航迹融合成一条准确、连续、带身份的目标轨迹,是这个领域绕不开的核心工作。我最近用一个基于MATLAB的雷达与AIS航迹融合处理项目,把从数据预处理、时空对齐、航迹关联到融合滤波的完整链路跑通了一遍,这里把思路、代码和踩过的坑一起整理出来。内容主要面向海事雷达工程师、做水上交通信息处理的学生,以及正在写多传感器融合代码的朋友;如果你只想快速跑通一个Demo,也可以直接照着核心逻辑改。

1. 融合需求剖析与整体策略

1.1 雷达与AIS的互补关系,以及为什么非融合不可

雷达是主动传感器,自己发射电磁波、接收回波,好处是不依赖目标配合,任何有雷达反射面的目标都能被探测到;坏处也很明显,它只给“这里有个东西”,不给“这是谁”。在近岸、弯曲航道、雨雪天气下,雷达点迹里还混着大量海杂波和假回波,距离误差随距离增大而增大,方位误差在远区会被放大成好几倍的横向偏差。

AIS则完全是另一套逻辑。它通过船载设备主动广播本船的静态信息(船名、MMSI、船长船宽)和动态信息(经纬度、对地航速、对地航向),定位用的是GNSS,位置精度通常在几米到十几米,远远好于雷达。但它是“合作式”系统,船上没装设备、设备关机或报文被干扰时,就一点数据都没有。而且AIS更新率随航行状态变化,锚泊船可能几分钟才发一条,船多了报文还可能排队延迟。

我实际调试时遇到过这种情况:监控画面里一个雷达回波和一个AIS目标相距约200米,看起来是两条船,实际上雷达回波的位置噪声偏大、AIS定位又很准,两者指向的其实是同一艘船。如果这时候直接拿两个位置做平均,身份和位置都会一起漂掉。所以融合系统的第一件事不是算平均,而是先回答:“这两个测量到底是不是同一个目标?”这个问题答错了,后面所有的滤波和加权都没有意义。

1.2 融合质量的评价指标

融合做得好不好,不能靠肉眼和感觉。我自己的习惯是先把评价指标定下来,再动手写算法。做过这个方向的同行应该都有同感:没有量化指标,调试时很难说清楚一个改动是变好了还是变坏了。

指标工程含义怎么衡量
位置误差融合航迹与真值的偏差与高精度定位或人工标定真值比较,取均方根误差
身份保持率航迹号和MMSI绑定的稳定程度统计一段时间内身份未跳变的轨迹占比
轨迹完整率目标可连续跟踪的程度目标全程未断裂、未丢失的轨迹占比
航向航速跳变率融合输出的平滑程度相邻两次更新中航向或航速突变超过设定阈值的次数
误关联率关联算法张冠李戴的比例错误配对点迹数占总关联次数的比例

这些指标不需要做得很重,一个简单的离线统计脚本就够了。每次改动算法或参数后,跑同一段回放数据,对比这些数字的变化,比凭感觉判断可靠得多。

2. 航迹关联前的时空对齐处理

2.1 坐标统一:把经纬度与极坐标放到同一平面上

雷达原始输出通常是极坐标,距离和方位角;AIS输出是WGS84经纬度加对地速度、对地航向。要把两者做关联,第一步是放到同一个平面坐标系里。工程上最常用的公共参考系是以雷达站为原点的本地切平面直角坐标,也就是东向x、北向y的ENU坐标系。

小范围水域(几十公里以内)可以用等距近似转换,公式很简单:

function [x, y] = ll2xy(lat, lon, lat0, lon0) % 简化等距转换,适合几十公里内的监控场景 R = 6371000; % 地球近似半径,单位m x = (lon - lon0) * pi/180 * R * cos(lat0*pi/180); y = (lat - lat0) * pi/180 * R; end

这段代码够用,但要注意两点。第一,参考点lat0、lon0一定要选在监控区域中心,偏离太远时等距近似的误差会明显变大。第二,更严谨的场景建议直接用投影转换,把经纬度投影到UTM坐标,MATLAB里用自带函数创建投影对象后做正向转换,这样在大范围、高纬度区域也不会出问题。

雷达极坐标转直角坐标也要统一口径:

x = rho * sin(theta); % theta从正北顺时针,单位弧度 y = rho * cos(theta);

不同雷达设备输出的方位角定义可能不一样,有的是从正北顺时针,有的是从正东逆时针,转坐标前必须确认设备手册里的角度定义,否则整个关联都会错位。

2.2 时间同步:用运动模型把航迹外推到同一时刻

AIS和雷达的采样时刻几乎不可能完全一致。雷达扫描周期通常是2到6秒,AIS更新周期从几秒到几分钟不等,二者在同一时刻点上的概率很低。时间差小于一个阈值时可以直接忽略,大于阈值就必须做外推。

外推用最朴素的运动模型就够了,假设目标在短时间内外推窗口内保持匀速直线运动:

function [x_est, y_est] = extrapolate(x0, y0, v, cog, dt) % v为对地航速,单位m/s;cog为对地航向,单位弧度;dt为外推时间差,单位s x_est = x0 + v * sin(cog) * dt; y_est = y0 + v * cos(cog) * dt; end

这里的方向定义要跟坐标转换保持一致。如果目标航速接近零,比如锚泊船,直接沿用旧位置,不要硬外推。外推时间越长,位置误差越大,所以一般建议外推窗口不超过10到30秒。AIS的SOG和COG本身就是GNSS解算出来的平滑值,短时间外推的精度还可以;雷达点迹如果也要做时间对齐,它的速度估计噪声大,外推时要加约束,防止位置被推到离谱的地方。

时间对齐做完后,每个待关联的点都必须打上“测量时间戳”和“外推后的位置”,后续关联用的是外推后的位置,但原始测量值要保留下来,方便排查问题。

3. 航迹关联判定与融合滤波实现

3.1 关联门限与最近邻分配

关联判定的核心逻辑是:在公共坐标系下,计算雷达航迹点和AIS航迹点之间的距离、速度差、航向差,然后判断它们是否属于同一个目标。

位置门限可以用误差传播的思路来定。设雷达测距误差标准差为σ_R,AIS定位误差标准差为σ_A,那么两者差的方差是两者方差之和,取3倍标准差作为门限,覆盖大约99.7%的随机误差,同时给目标机动留一点余量:

G_p = 3 * sqrt(σ_R^2 + σ_A^2)

举个例子,σ_R取50米,σ_A取10米,则G_p约为153米。实际工程里,为了应对目标机动和航迹外推误差,我一般会把门限再放宽到300米左右,再配合速度和航向门限做细筛。速度门限取Δv ≤ 5节,航向门限取Δφ ≤ 30度,这两个约束能挡掉大量近距平行航行的错误配对。

匹配策略上,简单场景用最近邻就够了;多目标交叉、编队航行的场景,强烈建议用全局最优分配,避免出现一个AIS目标同时匹配两个雷达目标这种冲突。MATLAB里可以用匹配函数做最小代价指派,代价矩阵就是距离矩阵,超过门限的项设置成大数或者直接排除:

function [pairs] = associate_gnn(Xr, Xa, gate) % Xr: 雷达点迹坐标 [Nx2],Xa: AIS点迹坐标 [Mx2] N = size(Xr,1); M = size(Xa,1); D = sqrt((Xr(:,1) - Xa(:,1)').^2 + (Xr(:,2) - Xa(:,2)').^2); % 超过门限的代价置为很大的数,让求解器不要选它 D(D > gate) = 1e9; [assignment, ~] = matchpairs(D, 'min'); % assignment列出的是有效配对的索引 pairs = assignment; end

没装优化工具箱的读者也别急,这个最小距离分配用两层循环加一个占位标记也能写,性能差别在点迹数量不大的场景下完全体现不出来。提醒一句:不要每帧都对全部点迹做一次全量关联,那样容易造成身份抖动。推荐以AIS航迹为“锚”,雷达点迹来配对更新;AIS没有覆盖到的目标,雷达点迹可以独立建航迹,以后再尝试关联。

3.2 位置融合:从加权平均到卡尔曼滤波

关联配对成功后,才轮到真正的“融合”。需要说清楚的是,融合不是简单的坐标平均,而是按误差逆加权。雷达位置误差σ_R远大于AIS的σ_A,但AIS更新慢,所以融合结果应当偏向“当前时刻更可信”的信息源。

加权融合公式如下:

x_f = (σ_A^2 * x_r + σ_R^2 * x_a) / (σ_R^2 + σ_A^2) y_f = (σ_A^2 * y_r + σ_R^2 * y_a) / (σ_R^2 + σ_A^2)

这个公式本质是最小方差估计。MATLAB实现起来就是几行:

function [xf, yf] = fuse_weighted(xr, yr, xa, ya, sigmaR, sigmaA) wR = sigmaA^2 / (sigmaR^2 + sigmaA^2); wA = sigmaR^2 / (sigmaR^2 + sigmaA^2); xf = wR * xr + wA * xa; yf = wR * yr + wA * ya; end

想更进一步,可以用常速度模型做卡尔曼滤波,状态取[x, y, vx, vy],雷达和AIS作为两类量测输入。MATLAB自带跟踪滤波函数可以直接调用,但我更建议自己把滤波核心写一遍,状态转移矩阵和量测更新逻辑才不会变成黑盒。量测更新部分的核心代码大概是:

function [x_est, P_est] = kf_update(x_pred, P_pred, z, H, R) K = P_pred * H' / (H * P_pred * H' + R); x_est = x_pred + K * (z - H * x_pred); P_est = (eye(size(P_pred)) - K * H) * P_pred; end

预测部分就是状态转移矩阵乘状态、状态协方差乘转移矩阵转置再加过程噪声协方差。工程上Q取多大、R取多大,跟场景强相关,不要迷信某个固定数值,要根据回放数据里的跳动幅度来调。

3.3 航向航速融合与航迹身份管理

位置融合之外,SOG和COG的融合也有讲究。AIS的SOG、COG来自GNSS解算,统计特性比雷达点迹差分出来的速度稳得多,所以在AIS报文“新鲜”的时候,直接用AIS的SOG和COG作为融合输出,不做额外计算。

AIS报文超过一定时间后就不新鲜了,比如超过30秒,这时需要用雷达点迹的位置差分估算速度航向作为辅助。雷达差分速度噪声大,我一般会再做一次中值滤波,把跳变点压掉。这里的原则是:优先用可信源,备用源做兜底。

身份绑定是融合系统里容易被忽略却很重要的环节。融合航迹号与AIS的MMSI绑定后,即使AIS信号中断,航迹身份也要保持住,不能等AIS重新出现时又当成新目标。身份管理的核心就是“绑定一次,保持到底”,直到确认目标离开或长时间失联。

4. MATLAB工程实现与调试心得

4.1 数据输入与模拟数据生成

调试融合算法最怕没有数据。项目早期如果拿不到真实雷达和AIS记录,可以先写一个模拟数据生成器,把传感器的时序特征造出来。模拟器要还原三个关键特征:雷达扫描周期短但噪声大,AIS更新周期长且不一定规律,两个传感器的时间戳不同步。

function gen_demo() t = 0:1:300; % 仿真时间轴,单位秒 % 目标匀速直线运动,位置单位为米 x_true = 1000 + 5 * t; y_true = 2000 + 3 * t; % AIS每10秒上报一次,定位噪声小 aisT = t(1:10:end); aisX = x_true(1:10:end) + randn(size(aisT)) * 10; aisY = y_true(1:10:end) + randn(size(aisT)) * 10; % 雷达每3秒扫描一次,位置噪声大 radT = t(1:3:end); radX = x_true(1:3:end) + randn(size(radT)) * 30; radY = y_true(1:3:end) + randn(size(radT)) * 30; save('demo.mat', 'aisT','aisX','aisY','radT','radX','radY', 'x_true','y_true'); end

这个模拟器生成的数据足够把关联、融合、航迹管理整条链路跑通。建议模拟场景里再放一条近距离平行航行的干扰船,专门用来验证关联算法在多目标场景下的表现。

4.2 关键参数配置与调试顺序

我把这套融合系统里最关键的参数整理成了一张表,初值是基于普通VTS监控场景的经验值,实际使用时需要按具体数据调整。

参数推荐初值说明
坐标参考点监控区域中心影响坐标转换精度
时间对齐窗口2秒小于窗口直接用,大于窗口外推
位置关联门限300至800米按σ组合计算,再留机动余量
速度门限5节防止误关联
航向门限30度防止大角度错误配对
AIS新鲜度阈值30秒超过阈值的AIS信息不参与融合
航迹保持周期5个雷达周期防止轨迹频繁断裂
航迹起始条件连续3次关联成功防止杂波起批
外推时长上限30秒防止外推发散

调试顺序也很重要。我建议先从坐标转换入手,画一张俯视图,把雷达点、AIS点、转换后的点叠在一起看,确认没有系统性偏移;然后调时间对齐,观察轨迹是否出现锯齿;接着调关联门限,确认配对关系符合直觉;最后才动滤波器参数。不要一上来就调卡尔曼的Q和R,问题定位会很痛苦。

4.3 可视化调试三板斧

融合算法的调试,可视化比看日志高效得多。我常用的有三招。

第一招:把所有原始点和融合轨迹画在一张图上。雷达点用圆圈、AIS点用三角、融合轨迹用连续的线,不同目标用不同颜色。一眼就能看出关联错误和位置偏移,比对着数字猜快太多了。

第二招:打印关联矩阵。每次关联计算后,把配对双方的航迹编号、距离、速度差、航向差输出到命令行,人工检查有没有一对多、跳号、距离异常等状况。

第三招:画轨迹生命周期视图。横轴是时间,纵轴是航迹号,一条目标的生命过程就是一条水平线,断裂和跳变在这个视图里十分直观。目标分裂、丢失、身份跳变的时刻都能一眼定位。

这三招配合起来,基本能把算法跑飞的原因锁定到具体环节。

5. 典型问题与排查实录

5.1 五个高频问题与处理思路

问题之一:多目标交叉时身份乱跳。这是关联门限设得过大造成的。我把位置门限从3σ收紧到2.5σ,同时强制航向门限,误关联率明显下降。如果场景里经常出现近距离并行船,可以再加一个船长门限做辅助判断。

问题之二:融合轨迹来回摆动。雷达点噪声偏大,加权系数没有反映误差变化。处理办法是对雷达点先做一次α-β平滑,再把平滑后的位置参与融合。α取0.7、β取0.1左右,效果比较温和,不会把真实机动削掉。

问题之三:融合轨迹整体滞后。AIS报文的传输延迟会导致轨迹整体偏向历史位置。短外推解决不了系统性的滞后,我在项目里记录AIS报文“发送时刻”与“接收时刻”的时间差,估算固定延迟后做补偿,滞后问题基本消除。

问题之四:目标短暂丢失后重新出现被当成新目标。这是航迹生命周期参数设置不合理。把航迹保持时间拉长,在丢失阶段用AIS信息或运动外推维持航迹,再用连续计数逻辑把“短暂消失”和“真正离开”区分开。

问题之五:近岸杂波引起的假航迹。雷达在近岸会产生大量假回波,单点起批很容易把杂波当成船。对策是航迹起始必须满足连续3次关联成功,并且加最小航速约束,静止杂波一般过不了这个条件。

5.2 问题排查速查表

现象可能原因处理动作
身份跳变位置门限过大、特征约束弱收缩门限,增加航速航向门限
轨迹摆动雷达噪声大、加权失衡先平滑雷达点,按误差更新权重
整体滞后AIS链路传输延迟估算延迟并补偿,优先采用新鲜源
轨迹分裂航迹保持周期太短加长“丢失保持”时间,放宽重新关联条件
误匹配局部最近邻冲突改用全局最优分配,排除一对多

6. 写在最后的一些体会

融合算法做出来不难,难的是在真实数据环境下一直不坏。回看这个项目,我大部分时间其实花在数据清洗和参数调试上——AIS字段缺失、雷达野值、时间戳不齐,这些问题不处理干净,再漂亮的滤波公式输出也是垃圾。另一个体会是,调试时一定要保留可追溯的中间结果,每次改动参数都能复现问题,否则调参只能靠猜。这套基于MATLAB的实现思路,覆盖了普通VTS监控场景的典型需求,如果后续要做高动态编队或者复杂航道多目标,还需要引入更强的数据关联方法,比如概率数据关联或带航迹管理能力的多假设跟踪。希望这份记录能帮正在做同类工作的朋友少踩几个坑。

RELATED READING

延伸阅读

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