用开源航迹数据核对一次远海演训的舰位,误差出在哪

上个月想核对一次远海演训的公开航迹,手头只有两样东西:海事部门公布的航行警告坐标,和某船舶追踪网站导出的 AIS 轨迹 CSV。数据量不大,三条船、七天、总共约两万行,时间戳是 UTC,坐标是 WGS84 十进制度。目标很朴素——把警告区坐标画出来,看轨迹有没有真的按公布的时间窗进出。

做法是先规整时间,再算距离。AIS 里同一船名会有 MMSI 不同的记录,先按 MMSI 去重,保留时间连续的那段:

import pandas as pd
df = pd.read_csv('ais.csv', parse_dates=['ts'])
df = df.sort_values(['mmsi','ts']).drop_duplicates(['mmsi','ts'])
df['gap'] = df.groupby('mmsi')['ts'].diff().dt.total_seconds()
df = df[df['gap'].fillna(0) < 3600]  # 断开超过一小时的段先扔掉

判进出区用射线法,简单够用:

def in_poly(lon, lat, poly):
    c = False
    for i in range(len(poly)):
        x1,y1 = poly[i]; x2,y2 = poly[(i+1)%len(poly)]
        if ((y1>lat)!=(y2>lat)) and (lon < (x2-x1)*(lat-y1)/(y2-y1)+x1):
            c = not c
    return c

结果第一版差得很离谱:船看起来提前六小时就进了警告区。查下来不是数据错,是我把警告里的“北京时间”直接当 UTC 用了,八小时时差一挪,进出全乱。第二版又发现坐标精度问题——AIS 有些点只到小数点后两位,0.01 度在纬度上约 1.1 公里,贴着边界算就会来回跳,所以边界附近 2 公里内的点我单独标出来,不参与判定。

为什么这么抠:航行警告是给航海者的法律文本,时间是生效窗口,坐标是区域边界,两样都不能含糊;而 AIS 是船端设备自动上报,受接收站覆盖和卫星过顶影响,存在丢点和延迟。这两类数据天生不同源,硬拼在一起,误差必然出现在“时间基准”和“边界精度”这两个接缝上。代价是这套流程只能做粗核对,不能当证据用。

失效的地方我也踩过:近岸接收站密集时轨迹很干净,一进远海就稀疏,插值出来的“进区时刻”完全是假的;还有船名和 MMSI 对不上的情况,同一艘船换过呼号,按名字匹配会漏。最坑的一次是把某网站的“最后位置”字段当成了实时点,其实是缓存。

你们核对公开航迹时,时间是先统一到 UTC 再比,还是直接按原始时区算?边界附近的点一般怎么处理?

0
赞同度 100% · 0 条评论 · 6 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。