NTRIP、NMEA 与 RTCM:网络 RTK 数据链路完整解析
最近在对接网络 RTK 服务的过程中,踩了不少坑,也厘清了很多之前模糊的概念。这篇文章把 NTRIP 握手、GGA 点单、RTCM 帧结构、MSM 消息等核心知识点系统整理出来,希望能帮到同样在调试 NTRIP 客户端的同学。
一、先分清两层,这是最容易混的地方
整个链路可以拆成三层:
┌─ 定位数据层 ────────────────────────────────┐ │ 上行(客户端→平台):NMEA 0183 的 $GNGGA │ │ 下行(平台→客户端):RTCM 10403.2 (RTCM3) │ ├─ 传输层 ───────────────────────────────────┤ │ NTRIP(用 HTTP/1.1 的语义做握手, │ │ 握手完就退化成裸 TCP 字节流) │ ├─ 承载层 ───────────────────────────────────┤ │ TCP/IP │ └────────────────────────────────────────────┘
关键认知:NTRIP 只管“怎么把数据搬过去”,不管“搬的是什么”。GGA 和 RTCM 是另外两个完全独立的标准,NTRIP 只是把它们塞进同一条 TCP 连接里。
二、NTRIP 层:握手与传输
2.1 标准文本
-
NTRIP 1.0 = RTCM Paper 200-2004
-
NTRIP 2.0 = RTCM 10410.1(免费公开,可从 RTCM 官网下载)
2.2 握手过程
NTRIP 握手本质上是一次 HTTP GET:
GET /RTCM33_GNSS HTTP/1.1 Host: 1.13.81.142:2103 Ntrip-Version: Ntrip/2.0 Authorization: Basic ZW10ZXN0MDE6MTIzNDU2
-
URL 路径 = 挂载点(mountpoint)
-
认证方式 = HTTP Basic
-
版本头 =
Ntrip/2.0
2.3 两个实作细节
-
状态码判断:只需判断首行是否包含
"200",因为 NTRIP 1.0 返回ICY 200 OK,2.0 返回HTTP/1.1 200 OK。 -
握手后退化:读到空行即响应头结束,之后同一 socket 上就是裸的 RTCM 字节流,不再有任何 HTTP 分帧。因此收流循环需要自己数帧长,不能用
http库。
2.4 SOURCETABLE
向 caster 发送 GET /,会返回 SOURCETABLE,里面每条 STR 记录描述了一个挂载点:
STR;RTCM33_GNSS;...;RTCM3.2;1005-1033(10),1074-1084-1094-1114-1124(1);2;GNSS;POPNET;CHN;0.0;0.0;1;1;POP Platform;none;B;N;500;POP
关键字段:
| 字段 | 值 | 含义 |
|---|---|---|
| format | RTCM3.2 | 下行数据格式 |
| format-details | 1005-1033(10),1074-...(1) | 报文清单 + 周期 |
| nmea | 1 | 需要客户端提供 NMEA 输入 |
| network | POPNET | 网络名 |
| generator | POP Platform | 生成软件 |
SOURCETABLE 是平台对自身数据流的“自述”,不是平台发送数据的“依据”。 平台本来就按预设策略发数据,SOURCETABLE 只是提前告诉你这个策略是什么。
三、NMEA GGA:VRS 服务的“点单”机制
3.1 为什么要发 GGA?
挂载点分两类:
| 类型 | 例子 | 客户端发 GGA 会怎样 |
|---|---|---|
| 广播型 | 单个物理基准站直接往外播 | GGA 被忽略,数据照发 |
| 网络/VRS 型 | 我们连的这个 | 不发 GGA 就一个字节都不给你 |
原因:网络 RTK 服务的做法是——你告诉它你在哪,它用周边几个物理基准站实时合成一个“虚拟基准站”(VRS)放在你的位置附近,然后把那个虚拟站的观测值发给你。
GGA 就是点单:告诉网络 RTK 服务“我要哪个点的改正数”。
3.2 GGA 报文结构
$GNGGA,034407.29,3006.00000,N,10254.00000,E,1,00,1.0,89.497,M,-9.513,M,0.0,0000*7d
| # | 字段 | 含义 |
|---|---|---|
| 0 | $GNGGA | GN=组合GNSS;GGA=定位数据 |
| 1 | 034407.29 | UTC 时间 03:44:07.29 |
| 2 | 3006.00000 | 纬度 30°06.00000′ = 30.1° |
| 3 | N | 北纬 |
| 4 | 10254.00000 | 经度 102°54.00000′ = 102.9° |
| 5 | E | 东经 |
| 6 | 1 | 定位质量(1=单点定位) |
| 7 | 00 | 使用卫星数 |
| 8 | 1.0 | HDOP |
| 9 | 89.497 | 海拔高 |
| 10 | M | 单位:米 |
| 11 | -9.513 | 大地水准面差距 |
| 12 | M | 单位:米 |
| 13 | 0.0 | 差分龄期 |
| 14 | 0000 | 差分参考站 ID |
| 15 | *7d | 校验和 |
3.3 两个实现细节
-
纬度/经度格式:必须是
ddmm.mmmmm(度+分),不是十进制度。分钟必须是两位整数,格式化宽度为精度+3。 -
高度字段:平台合成 VRS 时可能不关心客户端给的高度,只使用平面位置。
3.4 发送时机
握手成功立刻发第一条,之后每 3 秒重发一次维持位置。
四、RTCM 帧结构
4.1 通用帧格式
┌───────── 3 字节头 ─────────┐┌── 载荷 N 字节 ──┐┌─ 3 字节 ─┐
│ D3 │ 6位保留 │ 10位长度=N ││ 报文数据 ││ CRC-24Q │
└────────────────────────────┘└─────────────────┘└──────────┘
总帧长 = N + 6,CRC 覆盖前 (N+3) 字节
-
D3:前导码 -
6 位保留:固定为 0
-
10 位长度
N:载荷字节数 -
载荷:完整的 RTCM 消息内容
-
CRC-24Q:校验码
4.2 常见 RTCM 消息类别
| 类别 | 典型消息号 | 用途 |
|---|---|---|
| MSM(多信号消息) | 1071-1127 | 多系统观测数据 |
| 传统观测消息 | 1001-1012 | 早期单系统观测数据 |
| 参考站信息 | 1005, 1006, 1033 | 基准站坐标、天线描述 |
| 网络 RTK 消息 | 1014-1031 | VRS/FKP 网络改正 |
| SSR 消息 | 1057-1068, 1240-1270 | 状态空间域改正 |
| 辅助消息 | 1013, 1230 | 系统参数、时间偏移 |
五、MSM 消息结构
MSM 是 RTCM 中唯一一种用掩码机制统一支持所有 GNSS 系统观测数据的消息类型。
5.1 通用结构
一个 MSM 消息由三部分组成:
报文头 (Header)
| 字段 | 位宽 | 说明 |
|---|---|---|
| 消息编号 (DF002) | 12 bit | 指明系统 + MSM 等级(如 1074=GPS MSM4) |
| 参考站ID (DF003) | 12 bit | 基准站标识 |
| 历元时间 | 30 bit | 观测数据时间标签 |
| 多消息标志 | 1 bit | 是否拆分到多条消息 |
| IODS | 3 bit | 数据站 Issue 号 |
| 预留字段 | 7 bit | 保留位 |
| 时钟标志 | 各 2 bit | 基准站时钟状态 |
| 平滑标志与间隔 | 1+3 bit | 载波平滑信息 |
| 卫星掩码 (DF394) | 64 bit | 核心字段,标记哪些卫星有数据 |
| 信号掩码 (DF395) | 32 bit | 核心字段,标记哪些信号有数据 |
| 单元掩码 (DF396) | 可变 | 标记哪些“卫星×信号”组合有效 |
卫星数据段
为卫星掩码标记为 1 的每颗卫星,提供:
-
粗略伪距
-
粗略伪距变化率
-
扩展卫星信息
信号数据段
为每个有效的“卫星×信号”组合提供:
-
精细伪距
-
精细载波相位
-
多普勒
-
载噪比 (CNR)
-
锁定时间
5.2 MSM1 到 MSM7 的区别
| 类型 | 包含的观测值 | 主要用途 |
|---|---|---|
| MSM1 | 仅伪距 | 低精度导航 |
| MSM2 | 仅载波相位 | 特定研究 |
| MSM3 | 伪距 + 载波相位 | 基础 RTK |
| MSM4 | 伪距 + 载波相位 + CNR | 常用,平衡数据量与精度 |
| MSM5 | 伪距 + 载波相位 + CNR + 多普勒 | 需要速度信息 |
| MSM6 | 同 MSM4,但分辨率更高 | 高精度静态测量 |
| MSM7 | 同 MSM5,但分辨率更高 | 最全,精度最高 |
5.3 MSM 与其他 RTCM 消息的区别
| 对比项 | MSM | 传统观测(1001-1012) | SSR(1057-1068) | 参考站信息(1005) |
|---|---|---|---|---|
| 内容 | 多系统观测值 | 单系统观测值 | 状态空间域改正数 | 基准站坐标 |
| 多系统支持 | 统一格式 | 每系统独立格式 | 统一格式 | 不适用 |
| 信号灵活性 | 掩码机制,任意组合 | 固定字段 | 不适用 | 不适用 |
| 用途 | 相对定位 | 老旧 RTK | PPP/PPP-RTK | 提供基准站位置 |
5.4 MSM 在 RTCM 帧中的位置
MSM 消息整体作为 RTCM 帧的载荷部分,被封装在“长度字段”和“CRC”之间。RTCM 帧头只负责告诉接收方“这包货有多长”,MSM 消息自己负责告诉接收方“这包货里有什么”。
六、典型报文语义
落进 redis 的五类报文:
| 报文 | 周期 | 语义 |
|---|---|---|
| 1005 | 10 s | 参考站坐标(VRS 的 ARP 地心坐标 + 站号) |
| 1074 | 1 s | GPS 的 MSM4 观测量 |
| 1084 | 1 s | GLONASS 的 MSM4 观测量 |
| 1094 | 1 s | Galileo 的 MSM4 观测量 |
| 1124 | 1 s | BeiDou 的 MSM4 观测量 |
1005 是 10 秒一条,而写库是 1 秒一次,必须缓存复用,不能等它。
七、业务逻辑:谁在“决策”?
NTRIP 协议本身并没有定义“客户端发送 GGA,服务器据此下发对应差分数据”这个业务流程。
分工如下:
| 角色 | 职责 |
|---|---|
| NTRIP 协议 | 只负责“传输管道”:建立连接、认证、搬运字节流 |
| NMEA GGA | 只负责“表达位置”:独立的报文标准,不是 NTRIP 的一部分 |
| VRS 服务逻辑 | 真正的“业务决策者”:解析 GGA、合成 VRS、生成差分数据 |
SOURCETABLE 中的 nmea=1 标志,不是 NTRIP 协议的规定,而是服务提供商自己声明“我这个挂载点需要 GGA”。
八、参考资料
| 资料 | 说明 |
|---|---|
| NTRIP 2.0 标准(RTCM 10410.1) | RTCM 官网免费下载,握手和 SOURCETABLE 定义 |
| RTKLIB(开源 GNSS 库) | NMEA 解析和 RTCM3 成帧的参考实现 |
| NMEA 0183 / RTCM 10403.x | 付费标准,但字段定义在开源实现中广泛存在 |
九、总结
┌──────────────────────────────────────────────────────────┐ │ 网络 RTK 数据链路 │ ├──────────────────────────────────────────────────────────┤ │ │ │ 客户端 平台 │ │ │ │ │ │ │─── NTRIP 握手 (HTTP GET) ───→│ │ │ │←── 200 OK ───────────────────│ │ │ │ │ │ │ │─── GGA (NMEA) ──────────────→│ ← 点单位置 │ │ │ │ ← 合成 VRS │ │ │←── RTCM 帧 (含 MSM) ─────────│ ← 下发差分数据 │ │ │←── RTCM 帧 (含 MSM) ─────────│ │ │ │←── RTCM 帧 (含 MSM) ─────────│ │ │ │ │ │ │ ▼ ▼ │ │ RTK 解算 持续推送 │ │ │ └──────────────────────────────────────────────────────────┘
核心要点:
-
NTRIP = 传输管道,只管搬运
-
NMEA GGA = 位置表达,VRS 的“点单”
-
RTCM = 数据格式,帧结构固定
-
MSM = RTCM 中最灵活的观测数据载体,掩码机制支持多系统多信号
-
SOURCETABLE = 平台自述,告诉你“我会发什么”
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/zx642288904/article/details/165614425



