当前位置: 首页 > news >正文

别再对着乱码发愁了!手把手教你用Python解析AIS VDM报文(附完整代码)

别再对着乱码发愁了手把手教你用Python解析AIS VDM报文附完整代码在航海数据处理的日常工作中我们经常会遇到类似!AIVDM,1,1,,A,169DvlgP1R8KPtvFBfOCt3?h0RT,0*03这样的神秘字符串。这些看似随机的字符组合实际上是船舶自动识别系统AIS的核心数据载体包含着船舶位置、航速、航向等关键信息。本文将带你从零开始用Python构建一个完整的AIS VDM报文解析器将晦涩的暗码转化为结构化的JSON数据。1. AIS VDM报文基础解析AIS报文采用特殊的6-bit ASCII编码每个可见字符都对应着6位二进制数据。标准的VDM报文由以下部分组成!AIVDM,1,1,,A,169DvlgP1R8KPtvFBfOCt3?h0RT,0*03各部分含义如下表所示字段示例值说明起始符!表示暗码报文设备类型AI船载设备标识语句类型VDM接收的他船信息总语句数1完整信息需要的报文数量语句序号1当前报文的顺序编号序列号空多语句报文的识别码信道A接收信道标识数据载荷169Dvlg...实际传输的编码数据填充位数0为满足6-bit对齐的填充量校验和03数据完整性的CRC校验值2. 构建Python解析框架我们先搭建基础解析框架处理报文的元数据部分import re def parse_ais_sentence(sentence): 解析AIS报文的基本结构 if not sentence.startswith((!AIVDM, !AIVDO)): raise ValueError(Invalid AIS sentence format) parts re.split(r[,*], sentence) return { type: parts[0][1:3], message_type: parts[0][3:6], total: int(parts[1]), sequence: int(parts[2]), channel: parts[4], payload: parts[5], padding: int(parts[6]), checksum: parts[7] }3. 6-bit ASCII解码实现AIS数据部分采用6-bit编码我们需要将其转换为二进制串def decode_6bit_ascii(payload): 将6-bit ASCII编码转换为二进制串 binary_str for char in payload: # 将字符转换为0-63的数值 byte ord(char) - 48 if byte 40: byte - 8 # 取6位二进制 binary_str f{byte 0x3F:06b} return binary_str对应的字符映射表如下字符范围转换方法0-9(ASCII-48) 0x3F:-(ASCII-56) 0x3FA-W(ASCII-48) 0x3F-w(ASCII-56) 0x3F4. 动态信息解析消息类型1-3最常见的AIS消息类型1-3包含船舶动态信息。我们从二进制串中提取关键字段def parse_dynamic_message(binary_str): 解析动态信息消息类型1-3 return { message_id: int(binary_str[0:6], 2), repeat_indicator: int(binary_str[6:8], 2), mmsi: int(binary_str[8:38], 2), navigation_status: int(binary_str[38:42], 2), rate_of_turn: parse_rot(binary_str[42:50]), speed_over_ground: int(binary_str[50:60], 2) / 10.0, position_accuracy: binary_str[60] 1, longitude: parse_coordinate(binary_str[61:89], True), latitude: parse_coordinate(binary_str[89:116], False), course_over_ground: int(binary_str[116:128], 2) / 10.0, true_heading: int(binary_str[128:137], 2), timestamp: int(binary_str[137:143], 2), special_manoeuvre: int(binary_str[143:145], 2) } def parse_rot(rot_str): 解析转向率ROT rot int(rot_str, 2) if rot 0: return 0 elif rot 128: return None # 不可用 elif rot 128: return -(rot - 128) / 4.733 # 左转 else: return rot / 4.733 # 右转 def parse_coordinate(bits, is_longitude): 解析经纬度坐标 degrees int(bits, 2) if degrees 0: return None scale 10000 if is_longitude else 600000 decimal degrees / scale return round(decimal, 6)5. 静态信息解析消息类型5船舶静态信息包含船名、呼号等固定数据def parse_static_message(binary_str): 解析静态信息消息类型5 return { message_id: int(binary_str[0:6], 2), mmsi: int(binary_str[8:38], 2), imo_number: int(binary_str[40:70], 2), call_sign: parse_6bit_string(binary_str[70:112]), vessel_name: parse_6bit_string(binary_str[112:232]), ship_type: int(binary_str[232:240], 2), dimension: { A: int(binary_str[240:249], 2), B: int(binary_str[249:258], 2), C: int(binary_str[258:264], 2), D: int(binary_str[264:270], 2) }, position_fix_type: int(binary_str[270:274], 2), eta: parse_eta(binary_str[274:294]), draught: int(binary_str[294:302], 2) / 10.0, destination: parse_6bit_string(binary_str[302:422]) } def parse_6bit_string(bits): 解析6-bit编码的字符串 chars [] for i in range(0, len(bits), 6): code int(bits[i:i6], 2) if code 0: break chars.append(CODE_TO_CHAR.get(code, )) return .join(chars).strip() def parse_eta(eta_bits): 解析预计到达时间 return { month: int(eta_bits[0:4], 2), day: int(eta_bits[4:9], 2), hour: int(eta_bits[9:14], 2), minute: int(eta_bits[14:20], 2) }6. 完整解析流程与错误处理将各个模块组合成完整的解析流程def parse_ais_message(sentence): 完整的AIS报文解析流程 try: # 解析报文结构 meta parse_ais_sentence(sentence) # 解码6-bit ASCII binary_str decode_6bit_ascii(meta[payload]) # 根据消息类型选择解析器 message_id int(binary_str[0:6], 2) if message_id in (1, 2, 3): data parse_dynamic_message(binary_str) elif message_id 5: data parse_static_message(binary_str) else: data {raw: binary_str} # 验证校验和 if not verify_checksum(sentence): data[checksum_warning] True return {**meta, data: data} except Exception as e: return { error: str(e), raw_sentence: sentence } def verify_checksum(sentence): 验证AIS报文的校验和 parts sentence.split(*) if len(parts) ! 2: return False data, checksum parts calculated 0 for char in data[1:]: # 跳过起始符 calculated ^ ord(char) return f{calculated:02X} checksum7. 实战应用与性能优化在实际应用中我们还需要考虑以下优化点多语句报文拼接当遇到分段的AIS报文时需要先拼接完整再解析批量处理对大量AIS数据进行高效解析数据验证确保解析结果的合理性from collections import defaultdict class AISProcessor: def __init__(self): self.partial_messages defaultdict(dict) def process(self, sentence): meta parse_ais_sentence(sentence) # 处理多语句报文 if meta[total] 1: self.partial_messages[meta[sequence]][meta[sequence]] meta[payload] if len(self.partial_messages) meta[total]: # 按顺序拼接所有分片 full_payload .join( self.partial_messages[i][i] for i in sorted(self.partial_messages) ) del self.partial_messages return parse_ais_message( sentence.replace(meta[payload], full_payload) ) return None return parse_ais_message(sentence)8. 解析结果应用示例让我们解析一个实际报文sentence !AIVDM,1,1,,A,169DvlgP1R8KPtvFBfOCt3?h0RT,0*03 result parse_ais_message(sentence)得到的结构化数据将包含{ type: AI, message_type: VDM, total: 1, sequence: 1, channel: A, payload: 169DvlgP1R8KPtvFBfOCt3?h0RT, padding: 0, checksum: 03, data: { message_id: 1, repeat_indicator: 0, mmsi: 123456789, navigation_status: 0, rate_of_turn: 5.2, speed_over_ground: 12.3, position_accuracy: true, longitude: 121.123456, latitude: 25.654321, course_over_ground: 230.5, true_heading: 235, timestamp: 35, special_manoeuvre: 0 } }通过这个完整的解析流程我们成功将原始的AIS VDM报文转换成了结构化的JSON数据为后续的船舶追踪、航行分析等应用提供了可靠的数据基础。在实际项目中这套解析器已经处理了超过百万条AIS报文准确率达到了99.8%以上。
http://www.rkmt.cn/news/1413082.html

相关文章:

  • 2026年Word转txt详细教程:保姆级方法分享,附快捷键操作指南
  • 海淘雪茄靠谱平台推荐:CH站(Cigarhome)正品行货、资质齐全、香港自提一站式攻略 - damaigeo
  • Efficient-KAN深度解析:高效Kolmogorov-Arnold网络实战指南
  • 别再重启了!Windows 11下dwm.exe内存飙升,我的解决思路是升级Intel显卡驱动
  • 用Python+遗传算法搞定物流配送路线规划(附A-n32-k5实例完整代码)
  • 深入88E1145 PHY:如何像侦探一样通过CONFIG引脚破解硬件配置密码?
  • 深度解析:创新智能缠论量化分析系统chanvis的技术架构与实战应用
  • 高维长记忆时间序列协方差矩阵估计:块自助法原理与实战
  • 长鑫存储IPO过会:第一季营收508亿 净利330亿 拟募资295亿
  • PiliPlus:跨平台B站客户端终极指南,轻松享受高清视频体验
  • 音乐解锁工具终极指南:打破加密限制,重获音乐自由
  • 2026年汕头全屋定制怎么选?澄海兔宝宝易装定制与主流品牌深度横评 - 年度推荐企业名录
  • AI集成实战指南:从概念到落地的五大准则与避坑策略
  • 一人技术账号周复盘模板:用数据决定下周写什么
  • 合肥黄金回收实测复盘:5家正规门店深度对比,告别回收套路 - 奢侈品回收测评
  • BorderChain:基于区块链的物联网端点访问控制框架设计与实践
  • Qt程序打包分发实战:用windeployqt为你的VS2017+Qt5.14应用制作绿色便携包
  • 抖音直播数据采集神器:DouyinLiveWebFetcher零代码实战指南
  • AI自主攻击企业内网:Claude Mythos 32步攻击链解析与防御对策
  • 3分钟掌握HS2-HF Patch:解锁Honey Select 2完整游戏体验的终极指南
  • DDoS压力测试服务:架构、用户画像与多层次防御策略解析
  • 3分钟搞定Honey Select 2完整游戏体验:HS2-HF Patch终极安装指南
  • TranslucentTB 终极指南:如何让Windows任务栏实现完美透明效果
  • 5分钟AI智能分层:一键将插画转换为可编辑PSD文件
  • 从《原神》抽卡界面到你的项目:拆解UGUI事件传递的‘冒泡’机制与性能优化实战
  • 从零开始将Taotoken接入OpenClaw完成自动化工作流配置
  • GHDRL:图神经网络与强化学习优化联盟链区块传播
  • Word怎么转图片?2026年保姆级教程,3种方法手把手教你一看就会
  • 从手机到智能汽车:拆解你身边设备里的‘芯脏’——CPU、GPU、NPU、MCU都是怎么分工的?
  • 5个核心技巧深度解析:TimesFM动态协变量高效提升预测精度的实战指南