文章目录

  • 名词简写
  • GPGGA GNGGA
    • 格式说明
    • Linux PTY 虚拟串口对
    • Linux GPGGA 模拟器
  • NTRIP
    • NTRIP2.x vs NTRIP1.0
    • NTRIP2.0 Server/Caster/Client 模拟器
    • Base64
    • Client不发GPGGA的通信过程
    • Client只发一次GPGGA
    • Client周期发GPGGA
    • 一个帐号两个应用不可用的演示
  • RTCM
    • Wireshark千寻NTRIP抓包
    • 串口 CAN 传输说明
    • RTCM电文解析 pyrtcm
    • RTCM各版本演进
    • RTCM Packet 包格式(帧结构)
    • 查表法算CRC24

名词简写

  • GNSS(global navigation satellite system) 全球导航卫星系统
  • GPS(Global Positioning System) 全球定位系统
  • DGPS(Differential Global Position System) 差分全球定位系统, 分三类位置差分、伪距差分和相位差分(RTK)
  • RTK(Real Time Kinematic) 实时动态载波相位差分技术
  • NTRIP(Networked Transport of RTCM via Internet Protocol) 基于互联网的 RTCM 网络传输协议 所有的 RTK数据格式(NCT,RTCM,CMR,CMR+等等)都能被传输, 是CORS服务接入的协议. BASE充当 NTRIP Server, 很多BASE连到NTRIP Caster, Rover充当NTRIP Client
  • NMEA(National Marine Electronics Association) 美国国家海洋电子协会 或者 国家海洋电子协会, 常用的NMEA-0183 3.x, 4.x版本, 定义接收机输出的标准信息语句, 如 $GPGGA, $GPRMC
  • RTCM(Radio Technical Commission for Maritime Services) 海事无线电技术委员会, 常用的RTCM 3.x协议, 定义了 GPS/RTK/多星系等的消息类型
  • CORS(Continuously Operating Reference Stations) 连续运行参考站, 一般 CORS系统至少是: BASE + ROVER, 基站可以自建或使用服务商, ROVER是漫游端(漫游站/流动站/移动站 的叫法应该都可以)
  • DTU(Data Transfer unit) 数据传输单元, 将串口数据转换为IP数据或将IP数据转换为串口数据通过有线/无线通信网络(4G/5G/WiFi/LoRa/Zigbee/ETH/CAN…)进行传送的终端设备

GPGGA GNGGA

格式说明

GP: GPS

GN: GNSS, 一般是GPS和北斗混合, 或掺杂Glonass, Galileo

常见的 GPRMC和GNRMC, GPGGA和GNGGA, 写法不同(GP*, GN*), 格式相似. 可以通过串口等配置GPS接收器的输出(GP*, GN*)

GPGGA或GNGGA一般是GPS/GNSS接收器发出来的, 通常是串口, 现在为了车规很多串口拿到后转成CAN了. 这个数据发到CORS服务器, 然后服务器就会返回差分数据.

格式是 NMEA 定的, 参考

  • GPGGA (novatel.com)
  • GPGGA格式详解 | 豌豆荚博客 (lehoon.cn)
  • 关于0x0d和0x0a回车换行\r和\n - bingcaihuang - 博客园 (cnblogs.com)
$GPGGA,134658.00,5106.9792,N,11402.3003,W,2,09,1.0,1048.47,M,-16.27,M,08,0000*60
- $GPGGA: Log Header, 起始引导符及语句格式说明
- 134658.00: UTC时间(比北京时间慢8小时), 格式为hhmmss.sss, 24小时制, hh总是2位数
- 5106.9792: 纬度, 格式为ddmm.mmmm
- N: 纬度半球, 北纬N, 南纬S
- 11402.3003: 经度, 格式为dddmm.mmmm
- W: 经度半球, 东经E, 西经W
- 2: GPS状态, 0初始化,1单点定位,2码差分/伪差分,3无效PPS,4RTK固定歧义解,5RTK浮点解,6航位推算模式,7人工输入固定值,8模拟模式,9WAAS差分, 数据是不是差分数据就看这个了
- 09: 使用卫星数量, 00~12
- 1.0: HDOP, 水平精度因子, 0.5~99.9, 越小质量越好
- 1048.47: 椭球高, -9999.9~9999.9米
- M: 米
- -16.27: 大地水准面高度异常值, -9999.9~9999.9米
- M: 米
- 08: 差分GPS数据期限(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空, 没有空格), 最大99s
- 0000: 差分参考基站标号, 0000~1023, 不是差分定位将为空, 没有空格, 存在差分但是0000的情况
- *: 语句结束标志
- 60: 从$开始到*之间的所有ASCII码的异或校验, 不包含$和*
- <CR> 回车符,结束标记, 0x0A, \r
- <LF> 换行符,结束标记, 0x0D, \n

异或校验的C代码举例

#include <stdio.h>
#include <stdint.h>uint8_t cal_xor(uint8_t *data, uint8_t len)
{uint8_t i;uint8_t xor = 0;for (i = 0; i < len; i++){xor ^= data[i];}return xor;
}int main(void)
{// char str[] = "$GPGGA,172814.0,3723.46587704,N,12202.26957864,W,2,6,1.2,18.893,M,-25.669,M,2.0,0031*4F";char str[] = "$GPGGA,115739.00,4158.8441367,N,09147.4416929,W,4,13,0.9,255.747,M,-32.00,M,01,0000*6E";uint8_t xor = cal_xor((uint8_t *)str + 1, sizeof(str) / sizeof(str[0]) - 5); // skip $ and *6E and \0printf("xor: %02X\n", xor);                                                  // xor: 6Ereturn 0;
}

Linux PTY 虚拟串口对

很多GPGGA数据是从串口发出来的, 模拟的话可以虚拟出一对串口.

代码来自(原作者也不知道是哪个):

  • ser2net/mkpty.py at master · qchats/ser2net (github.com)
  • ruiyunli/ttytool (github.com)
  • Linux下的虚拟终端(可用于在本机上模拟串口进行调试)_h小白请指教的博客-CSDN博客

关于pty(全称pseudo terminal, 伪终端), 参考:

  • Linux 伪终端(pty) - sparkdev - 博客园 (cnblogs.com)
#! /usr/bin/env python
#coding=utf-8import pty
import os
import selectdef mkpty():#  Open the pseudo terminalmaster1, slave = pty.openpty()slaveName1 = os.ttyname(slave)master2, slave = pty.openpty()slaveName2 = os.ttyname(slave)print '\nslave device names: ', slaveName1, slaveName2return master1, master2if __name__ == "__main__":master1, master2 = mkpty()while True:rl, wl, el = select.select([master1,master2], [], [], 1)for master in rl:data = os.read(master, 128)print "read %d data." % len(data)if master==master1:os.write(master2, data)else:os.write(master1, data)

代码就是造了两个pty, 把一个读的写到另一个去, 运行

$ python mkpty.py
slave device names:  /dev/pts/9 /dev/pts/10

打印出的 /dev/pts/9/dev/pts/10 就是一对虚拟串口, 可以相互收发, 用minicom测试

sudo minicom -b 115200 -D /dev/pts/9
sudo minicom -b 115200 -D /dev/pts/10

Linux GPGGA 模拟器

这个Github上有很多, 如:

  • zzjoey/GenGPGGA: GPS - GPGGA Message Simulator (github.com)

NTRIP

Ntrip Server: 通过某种途径获得到RTK差分信息,然后传送给 Ntrip Caster.

Ntrip Caster:接收Ntrip Server的差分数据。给ntrip client发送GPS差分数据。

Ntrip Client: 向Ntrip Caster申请GPS差分数据,最终实现RTK定位。

NTRIP2.x vs NTRIP1.0

NTRIP2.0协议是ntrip1.0的基础上,修改了不符合 HTTP 1.1 协议的一些地方:

  • 用POST替换SOURCE
  • 全部时间戳采用GMT(Greenwich Mean Time, 格林威治时间)
  • 使用分块传输编码(chunked transfer encoding), 不需要额外的长度指示
  • 解决代理服务器/防火墙/的问题

NTRIP2.0向下兼容, 又增加了一些实时性好的协议或特性:

  • UDP 单播
  • RTSP-UDP协议
  • 源表过滤(Sourcetable filtering), 解决显示或内存受限的问题, 最小化传输成本和时间

SSL for NTRIP:

  • 传输数据的加密(包括用户名和密码)
  • 服务器或数据提供商的身份验证
  • 用户身份验证
  • 用户设备身份验证
  • 通信隐私
  • SSL 已建立 Internet 标准

参考:

  • ntrip协议_wandersky0822的博客-程序员秘密_ntrip - 程序员秘密 (cxymm.net)
  • NTRIP1.0协议文档: Microsoft Word - NtripDocumentationExtract.doc (esa.int)
  • Ntrip Modernization and Professional Ntrip Caster (alberding.eu)
  • [PowerPoint-Präsentation (iku.edu.tr)](http://cors-tr.iku.edu.tr/images/Christian_Waese - NTRIP - Purpose and Perspectives.pdf)

虽然NTRIP2很好, 但下面还是以NTRIP1为例, 资料多, 流程简单粗暴, 也更容易理解.

TCP -> HTTP 1.1 -> NTRIP 1.0(不完全兼容HTTP 1.1)

了解TCP的3次握手四次挥手, HTTP的SOURCE, GET, 200 OK等将很容易理解NTRIP.

NTRIP2.0 Server/Caster/Client 模拟器

sevensx/ntrip: Simple ntrip caster/client/server example programs, using the NTRIP2.0 protocol (github.com)

对照他的博客看 NTRIP通信协议之NTRIPCaster | Work and Learning Journey (sevensx.github.io)

无需任何硬件或服务, 使用127.0.0.1进行本机通信, 端口8090, 简直人才…

$ make
$ ./ntrip_caster
$ ./ntrip_server
$ ./ntrip_client# Client收到然后打印出的RTCM
D3 00 40 41 2E 06 44 19 1E F5 00 A4 00 00 10 B6 11 08 C2 E8 1D 58 1A 72 C8 46 CD 1A 08 EA 81 2C 3E DC 1B BB D9 5D 90 61 E8 05 2F FB 89 9A 4D CC EB FE 4C 25 28 FB 6C DA 7F 61 8E 60 9C BF FB 6A 2D 30 02 19 8F 73# 解析出来是1042电文, 北斗卫星星历数据
<RTCM(1042, DF002=1042, DF488=56, DF489=802, DF490=0, DF491=-0.0, DF492=29, DF493=262800, DF494=0.0, DF495=0.0, DF496=0.00012996, DF497=29, DF498=58.6875, DF499=0.0, DF500=0.78233034, DF501=2.13e-06, DF502=0.00458138, DF503=2.645e-05, DF504=6493.56399345, DF505=262800, DF506=-1.3e-07, DF507=0.80137482, DF508=-2e-07, DF509=0.29031317, DF510=-600.046875, DF511=-0.95136995, DF512=-0.0, DF513=-30.1, DF514=0.0, DF515=1)># 38720 server
# 8090 caster?
# 39130 client
# server发给caster的差分数据被caster原封不动转给了client
$ sudo tcpdump -X -i lo port 8090
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
18:06:58.755481 IP localhost.39130 > localhost.8090: Flags [S], seq 2200508889, win 65495, options [mss 65495,sackOK,TS val 3891838375 ecr 0,nop,wscale 7], length 00x0000:  4500 003c fc70 4000 4006 4049 7f00 0001  E..<.p@.@.@I....0x0010:  7f00 0001 98da 1f9a 8329 19d9 0000 0000  .........)......0x0020:  a002 ffd7 fe30 0000 0204 ffd7 0402 080a  .....0..........0x0030:  e7f8 bda7 0000 0000 0103 0307            ............
18:06:58.755488 IP localhost.8090 > localhost.39130: Flags [S.], seq 2521087539, ack 2200508890, win 65483, options [mss 65495,sackOK,TS val 3891838375 ecr 3891838375,nop,wscale 7], length 00x0000:  4500 003c 0000 4000 4006 3cba 7f00 0001  E..<..@.@.<.....0x0010:  7f00 0001 1f9a 98da 9644 be33 8329 19da  .........D.3.)..0x0020:  a012 ffcb fe30 0000 0204 ffd7 0402 080a  .....0..........0x0030:  e7f8 bda7 e7f8 bda7 0103 0307            ............
18:06:58.755494 IP localhost.39130 > localhost.8090: Flags [.], ack 1, win 512, options [nop,nop,TS val 3891838375 ecr 3891838375], length 00x0000:  4500 0034 fc71 4000 4006 4050 7f00 0001  E..4.q@.@.@P....0x0010:  7f00 0001 98da 1f9a 8329 19da 9644 be34  .........)...D.40x0020:  8010 0200 fe28 0000 0101 080a e7f8 bda7  .....(..........0x0030:  e7f8 bda7                                ....
18:06:58.755533 IP localhost.39130 > localhost.8090: Flags [P.], seq 1:176, ack 1, win 512, options [nop,nop,TS val 3891838376 ecr 3891838375], length 1750x0000:  4500 00e3 fc72 4000 4006 3fa0 7f00 0001  E....r@.@.?.....0x0010:  7f00 0001 98da 1f9a 8329 19da 9644 be34  .........)...D.40x0020:  8018 0200 fed7 0000 0101 080a e7f8 bda8  ................0x0030:  e7f8 bda7 4745 5420 2f52 5443 4d33 3220  ....GET./RTCM32.0x0040:  4854 5450 2f31 2e31 0d0a 5573 6572 2d41  HTTP/1.1..User-A0x0050:  6765 6e74 3a20 4e54 5249 5020 4e54 5249  gent:.NTRIP.NTRI0x0060:  5043 6c69 656e 742f 404e 5452 4950 5f56  PClient/@NTRIP_V0x0070:  4552 5349 4f4e 5f4d 414a 4f52 402e 404e  ERSION_MAJOR@.@N0x0080:  5452 4950 5f56 4552 5349 4f4e 5f4d 494e  TRIP_VERSION_MIN0x0090:  4f52 402e 404e 5452 4950 5f56 4552 5349  OR@.@NTRIP_VERSI0x00a0:  4f4e 5f50 4154 4348 402e 4047 4954 5f48  ON_PATCH@.@GIT_H0x00b0:  4153 4840 0d0a 4175 7468 6f72 697a 6174  ASH@..Authorizat0x00c0:  696f 6e3a 2042 6173 6963 2064 4756 7a64  ion:.Basic.dGVzd0x00d0:  4441 784f 6a45 794d 7a51 314e 673d 3d0d  DAxOjEyMzQ1Ng==.0x00e0:  0a0d 0a                                  ...
18:06:59.177309 IP localhost.38720 > localhost.8090: Flags [P.], seq 358293405:358293475, ack 2768753666, win 512, options [nop,nop,TS val 3891838797 ecr 3891837797], length 700x0000:  4500 007a 32fa 4000 4006 0982 7f00 0001  E..z2.@.@.......0x0010:  7f00 0001 9740 1f9a 155b 1f9d a507 d402  .....@...[......0x0020:  8018 0200 fe6e 0000 0101 080a e7f8 bf4d  .....n.........M0x0030:  e7f8 bb65 d300 4041 2e06 4419 1ef5 00a4  ...e..@A..D.....0x0040:  0000 10b6 1108 c2e8 1d58 1a72 c846 cd1a  .........X.r.F..0x0050:  08ea 812c 3edc 1bbb d95d 9061 e805 2ffb  ...,>....].a../.0x0060:  899a 4dcc ebfe 4c25 28fb 6cda 7f61 8e60  ..M...L%(.l..a.`0x0070:  9cbf fb6a 2d30 0219 8f73                 ...j-0...s
18:06:59.177332 IP localhost.8090 > localhost.38720: Flags [.], ack 70, win 512, options [nop,nop,TS val 3891838797 ecr 3891838797], length 00x0000:  4500 0034 ac52 4000 4006 906f 7f00 0001  E..4.R@.@..o....0x0010:  7f00 0001 1f9a 9740 a507 d402 155b 1fe3  .......@.....[..0x0020:  8010 0200 fe28 0000 0101 080a e7f8 bf4d  .....(.........M0x0030:  e7f8 bf4d                                ...M
18:06:59.177387 IP localhost.8090 > localhost.39130: Flags [P.], seq 18:88, ack 176, win 512, options [nop,nop,TS val 3891838797 ecr 3891838376], length 700x0000:  4500 007a 08a0 4000 4006 33dc 7f00 0001  E..z..@.@.3.....0x0010:  7f00 0001 1f9a 98da 9644 be45 8329 1a89  .........D.E.)..0x0020:  8018 0200 fe6e 0000 0101 080a e7f8 bf4d  .....n.........M0x0030:  e7f8 bda8 d300 4041 2e06 4419 1ef5 00a4  ......@A..D.....0x0040:  0000 10b6 1108 c2e8 1d58 1a72 c846 cd1a  .........X.r.F..0x0050:  08ea 812c 3edc 1bbb d95d 9061 e805 2ffb  ...,>....].a../.0x0060:  899a 4dcc ebfe 4c25 28fb 6cda 7f61 8e60  ..M...L%(.l..a.`0x0070:  9cbf fb6a 2d30 0219 8f73                 ...j-0...s
18:06:59.177391 IP localhost.39130 > localhost.8090: Flags [.], ack 88, win 512, options [nop,nop,TS val 3891838797 ecr 3891838797], length 00x0000:  4500 0034 fc74 4000 4006 404d 7f00 0001  E..4.t@.@.@M....0x0010:  7f00 0001 98da 1f9a 8329 1a89 9644 be8b  .........)...D..0x0020:  8010 0200 fe28 0000 0101 080a e7f8 bf4d  .....(.........M0x0030:  e7f8 bf4d                                ...M
18:06:59.755752 IP localhost.39130 > localhost.8090: Flags [P.], seq 176:262, ack 88, win 512, options [nop,nop,TS val 3891839376 ecr 3891838797], length 860x0000:  4500 008a fc75 4000 4006 3ff6 7f00 0001  E....u@.@.?.....0x0010:  7f00 0001 98da 1f9a 8329 1a89 9644 be8b  .........)...D..0x0020:  8018 0200 fe7e 0000 0101 080a e7f8 c190  .....~..........0x0030:  e7f8 bf4d 2447 5047 4741 2c31 3030 3635  ...M$GPGGA,100650x0040:  392e 3030 2c32 3233 342e 3338 3636 3030  9.00,2234.3866000x0050:  302c 4e2c 3131 3335 362e 3934 3330 3030  0,N,11356.9430000x0060:  302c 452c 312c 3130 2c31 2e32 2c31 302e  0,E,1,10,1.2,10.0x0070:  3030 3030 2c4d 2c2d 322e 3836 302c 4d2c  0000,M,-2.860,M,0x0080:  2c30 3030 302a 3737 0d0a                 ,0000*77..
18:06:59.755776 IP localhost.8090 > localhost.39130: Flags [.], ack 262, win 512, options [nop,nop,TS val 3891839376 ecr 3891839376], length 00x0000:  4500 0034 08a1 4000 4006 3421 7f00 0001  E..4..@.@.4!....0x0010:  7f00 0001 1f9a 98da 9644 be8b 8329 1adf  .........D...)..0x0020:  8010 0200 fe28 0000 0101 080a e7f8 c190  .....(..........0x0030:  e7f8 c190                                ....
18:07:00.177507 IP localhost.38720 > localhost.8090: Flags [P.], seq 70:140, ack 1, win 512, options [nop,nop,TS val 3891839797 ecr 3891838797], length 700x0000:  4500 007a 32fb 4000 4006 0981 7f00 0001  E..z2.@.@.......0x0010:  7f00 0001 9740 1f9a 155b 1fe3 a507 d402  .....@...[......0x0020:  8018 0200 fe6e 0000 0101 080a e7f8 c335  .....n.........50x0030:  e7f8 bf4d d300 4041 2e06 4419 1ef5 00a4  ...M..@A..D.....0x0040:  0000 10b6 1108 c2e8 1d58 1a72 c846 cd1a  .........X.r.F..0x0050:  08ea 812c 3edc 1bbb d95d 9061 e805 2ffb  ...,>....].a../.0x0060:  899a 4dcc ebfe 4c25 28fb 6cda 7f61 8e60  ..M...L%(.l..a.`0x0070:  9cbf fb6a 2d30 0219 8f73                 ...j-0...s

如果只是测试和千寻NTRIP通信的话, 使用ntrip_client就可以了, 参考:

  • 如何使用千寻知寸_千寻知寸-千寻位置帮中心 (qxwz.com)

把相关信息填入ntrip/examples/ntrip_client.cc

  std::string ip = "203.107.45.154";  //千寻IPint port = 8001; //8001:ITRF2008; 8002:WGS84; 8003:CGCS2000std::string user = "username"; //差分帐号std::string passwd = "password";   //差分密码std::string mountpoint = "AUTO";   //随时关注官方文档, 之前是RTCMxx, 现在AUTO

重新make运行即可

单Client的话, 这个用的也挺多的:

  • nunojpg/ntripclient: Ntrip Version 2.0 Command Line Client (github.com)

Base64

Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,转换后的字符串理论上将要比原来的长1/3(四字节对齐?), Base64能够将任何数据转换为易移植的字符串,避免了传输过程中的失真问题

一般是 明文数据通过MD5 、SHA等手段加密后,经过Base64编码为字符串后, 再传.

密码学 | Base64是加密算法吗? - 知乎 (zhihu.com)

Base64只是编码方式, 不是加密方式

NTRIP 1.0 中的用户名和密码只是简单的进行了Base64编码, 然后就明文传输出去了, 走的HTTP(另一个走HTTP的是GPGGA数据无需编码), 还不是HTTPS, 这其实是相当危险的行为, 可能意味着Connect时只要能抓包, 就能获取差分帐号和密码

# ntrip/examples/ntrip_client.ccstd::string ip = "127.0.0.1";int port = 8090;std::string user = "test01";std::string passwd = "123456";std::string mountpoint = "RTCM32";# ntrip/src/ntrip_client.ccstd::string user_passwd = user_ + ":" + passwd_;std::string user_passwd_base64;Base64Encode(user_passwd, &user_passwd_base64);ret = snprintf(buffer.get(), kBufferSize-1,"GET /%s HTTP/1.1\r\n""User-Agent: %s\r\n""Authorization: Basic %s\r\n""\r\n",mountpoint_.c_str(), kClientAgent, user_passwd_base64.c_str());$ sudo tcpdump -X -i lo port 809018:06:58.755533 IP localhost.39130 > localhost.8090: Flags [P.], seq 1:176, ack 1, win 512,  options [nop,nop,TS val 3891838376 ecr 3891838375], length 1750x0000:  4500 00e3 fc72 4000 4006 3fa0 7f00 0001  E....r@.@.?.....0x0010:  7f00 0001 98da 1f9a 8329 19da 9644 be34  .........)...D.40x0020:  8018 0200 fed7 0000 0101 080a e7f8 bda8  ................0x0030:  e7f8 bda7 4745 5420 2f52 5443 4d33 3220  ....GET./RTCM32.0x0040:  4854 5450 2f31 2e31 0d0a 5573 6572 2d41  HTTP/1.1..User-A0x0050:  6765 6e74 3a20 4e54 5249 5020 4e54 5249  gent:.NTRIP.NTRI0x0060:  5043 6c69 656e 742f 404e 5452 4950 5f56  PClient/@NTRIP_V0x0070:  4552 5349 4f4e 5f4d 414a 4f52 402e 404e  ERSION_MAJOR@.@N0x0080:  5452 4950 5f56 4552 5349 4f4e 5f4d 494e  TRIP_VERSION_MIN0x0090:  4f52 402e 404e 5452 4950 5f56 4552 5349  OR@.@NTRIP_VERSI0x00a0:  4f4e 5f50 4154 4348 402e 4047 4954 5f48  ON_PATCH@.@GIT_H0x00b0:  4153 4840 0d0a 4175 7468 6f72 697a 6174  ASH@..Authorizat0x00c0:  696f 6e3a 2042 6173 6963 2064 4756 7a64  ion:.Basic.dGVzd0x00d0:  4441 784f 6a45 794d 7a51 314e 673d 3d0d  DAxOjEyMzQ1Ng==.0x00e0:  0a0d 0a                                  ...

从中可以看到, Base64编码后的用户名:密码dGVzdDAxOjEyMzQ1Ng==, 粘贴到Base64 在线编码解码 | Base64 加密解密 - Base64.us

可怕

Python代码示例

#!/usr/bin/python3
import base64
encodedStr = "dGVzdDAxOjEyMzQ1Ng=="
# Standard Base64 Decoding
decodedBytes = base64.b64decode(encodedStr)
decodedStr = str(decodedBytes, "utf-8")
print(decodedStr)   # test01:123456

NTRIP 2.x 中给出了一些SSL的方法, 来避免明文传输用户名和密码

Client不发GPGGA的通信过程

  • 如果是自建基站, Ntrip建立连接后, Caster就可以一秒一次的一直给Client转RTCM数据
  • 如果是用的CORS服务商, 一个基站或虚拟基站只能覆盖几公里或几十公里, NtripClient不发GPGGA, 服务商很难知道你在哪, 也就没法建虚拟基站发RTCM数据, 下面截图说明了这个过程

连接过程(可能没有获取源列表的过程):

# Client HTTP 发
GET /挂载点 HTTP/1.1
User-Agent: NTRIP NTRIPClient/版本号
Authorization: Basic Base64编码(用户名:密码)
# Caster TCP 回
ICY 200 OK

可参考:

  • 图解HTTP(1)_CopperDong的博客-CSDN博客
  • (图文并茂,权威最详细)Wireshark抓包分析 TCP三次握手/四次挥手详解 - 腾讯云开发者社区-腾讯云 (tencent.com)
  • Ntrip通讯协议1.0 - hanford - 博客园 (cnblogs.com)

30s TCP Alive的设置(如果发GPGGA, 一直有RTCM回传, 就没有TCP Alive了)

  // TCP socket keepalive.int keepalive = 1;  // Enable keepalive attributes.int keepidle = 30;  // Time out for starting detection.int keepinterval = 5;  // Time interval for sending packets during detection.int keepcount = 3;  // Max times for sending packets during detection.setsockopt(socket_fd, SOL_SOCKET, SO_KEEPALIVE,&keepalive, sizeof(keepalive));setsockopt(socket_fd, SOL_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));setsockopt(socket_fd, SOL_TCP, TCP_KEEPINTVL,&keepinterval, sizeof(keepinterval));setsockopt(socket_fd, SOL_TCP, TCP_KEEPCNT, &keepcount, sizeof(keepcount));

Client只发一次GPGGA

对于CORS服务商, 至少要发一次GPGGA才会回RTCM. 只发一次的话, Client可不要乱动, 不建议只发一次.

连接过程不变

# Client HTTP 发
GET /挂载点 HTTP/1.1
User-Agent: NTRIP NTRIPClient/版本号
Authorization: Basic Base64编码(用户名:密码)
# Caster TCP 回
ICY 200 OK

TCP发GPGGA, 直接明码发, 注意最后要加上 0x0D, 0x0A

$GPGGA,024440.00,2234.3866000,N,11356.9430000,E,1,10,1.2,10.0000,M,-2.860,M,,0000*7A
24 47 50 47 47 41 2c 30 32 34
34 34 30 2e 30 30 2c 32 32 33 34 2e 33 38 36 36
30 30 30 2c 4e 2c 31 31 33 35 36 2e 39 34 33 30
30 30 30 2c 45 2c 31 2c 31 30 2c 31 2e 32 2c 31
30 2e 30 30 30 30 2c 4d 2c 2d 32 2e 38 36 30 2c
4d 2c 2c 30 30 30 30 2a 37 41 0d 0a

Client周期发GPGGA

这个是正常用的状态, 一般可以1s或更久(如10s)发一次GPGGA, 但即便GPGGA周期很短, CORS服务商可能10s才回一次1005/1033电文. 其它时间是 1s一次的 格洛纳斯/GPS/北斗/伽利略 的电文.

一个帐号两个应用不可用的演示

CORS服务商一般只允许一个帐号给一个应用使用(不排除有多用帐号), 新的应用会把旧的应用顶掉, 即旧的应用TCP连接会被关闭

RTCM

Wireshark千寻NTRIP抓包

千寻为例, Client的NTRIP通信过程

正常 NTRIP Client 收到1~3包TCP数据/s, 里面共包含有5/6/7条不等的RTCM电文:

  • 基站的1005电文
  • 接收器和天线的1033电文
  • GLONASS的1084电文(108x)
  • 北斗的1124电文(112x)
  • GPS的1074电文(107x)
  • Galileo的1094电文(109x)

基站一般可以收星30颗左右, 星数越多, 数据包越大, 但都会揉在1个包里, 中国地区打主力的肯定还是 北斗(20颗左右) 和 GPS(10颗左右), 剩下的GLONASS和Galileo很少, 3颗左右. 这些星数指基站或虚拟基站的, 而不是ROVER的

NTRIP Client转发GPGGA/GNGGA的频率可以在1s~10s, 但接收含RTCM电文的频率一般是1Hz.

每发一次GPGGA/GNGGA, 会收到1005, 1033电文

每条RTCM电文的开头都是 D3 0, 注意不是D3 00, 因为北斗星数多的时候, 可能会出现D3 01的情况, 最好用 帧头+长度 的迭代器来从每包NTRIP数据中分出一条条的RTCM电文, 只使用帧头 D3 0 不一定准确.

串口 CAN 传输说明

假设收到的数据量是 893 字节, 串口的通信速率是 9600bps, 那么至少约需要 893/960 = 0.93s 才能传完, 加上GPGGA的88字节左右的数据, 几乎满载了, 所以, 现在一般是 115200bps 或者 460800bps 用的比较多.

如果这个用500Kbps的CAN来传输, 走类似CANTP的协议(7字节有效/帧/250ms), 1000字节约需要 36ms才能传完, 如果有10Hz周期的其它数据(IMU, 档位轮速反馈 之类的), 总线肯定不能被占用这么久, 考虑到同一主机的发送队列很多没有CANID优先级一说, 所以建议加上流控, 或者CANTP的每帧件加一个间隔, 来保证其它数据帧的实时性, 毕竟RTCM算是非紧急数据, GNSS板卡或者惯导一般1s能收到就可以.

RTCM电文解析 pyrtcm

# 这是NTRIP Client收到的一帧920字节的数据
D3 00 13 3E D8 AB 03 FA 6E 82 93 49 0C 89 E2 22 0E 05 AA 3E 6C 41 47 1D 57 D3 00 1F 40 98 AB 0E 41 44 56 4E 55 4C 4C 41 4E 54 45 4E 4E 41 00 00 08 51 58 57 5A 20 56 52 53 00 00 40 C7 B8 D3 00 42 43 C8 AB 69 3D 5B 42 00 20 81 00 0C 00 00 00 00 00 30 C0 00 00 4C CA 2A 32 06 CE 67 D7 B9 EC 74 BA 0E 8E 22 5D A0 57 4B F7 AE 79 9E F4 8D 83 64 F4 0E EB 97 B1 E5 1E D4 AA 7F FF FF 81 8E 53 61 AE 80 4C 62 43 D3 01 1C 46 48 AB 44 76 BB C2 00 20 FA E4 89 00 00 00 00 00 20 82 01 01 73 9C E7 39 CE 73 9B DB DB E3 CC 03 D3 D3 F4 1B DB CA 8A A5 F6 85 C8 E6 12 7E D7 34 93 2C 6B C5 E2 F4 18 50 30 B9 01 52 CB CD 97 EC 2E 45 FA 6B F5 4F E3 F1 6B C2 F3 85 DF 87 E4 0F 90 1F 03 AA 17 49 9E 93 E0 70 80 EA 02 56 DB 1B BA DB 7A 87 05 1E 24 BC 59 FF F4 80 64 01 8E 3E 70 79 41 09 21 FA 23 F2 87 F9 11 6E 20 30 04 06 30 0D EC 80 20 1E 86 74 8A 1A 86 48 70 5A 7F CC 0D 80 3E F1 FF 77 E0 1D A2 40 59 D1 81 35 E6 0A 7D D8 2E 84 60 BD 9D 7C E1 C7 F2 05 DF C5 E9 C0 42 D6 01 4B 7E 05 BF 8F B2 EF 5E C2 FB 7B 22 E9 EE 7B AF B7 96 3E DB F3 00 A8 70 04 59 F0 14 B0 C1 37 40 85 39 F0 17 84 20 4F C0 01 16 80 84 90 EE 13 EE B0 44 A6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF E0 00 00 00 00 5B 6D D5 DD 85 F8 63 3D 56 5B 86 16 5D 7D 76 5D 0C 92 DB 75 D8 5F 85 D8 5D 64 F5 53 30 CA A6 AF D3 00 B6 46 48 AB 44 76 BB C2 00 20 80 00 00 12 83 40 00 00 20 80 01 01 7F FF FF A5 25 25 BC BC 29 B3 83 72 7F 69 55 E8 56 60 3C DA 99 D5 73 17 12 83 27 58 4F E0 96 4F F6 40 0E 00 41 FF EA 83 87 07 E8 12 00 1F 79 57 12 B4 85 88 8A ED 98 B1 36 E2 73 E4 CA 07 99 39 9E 6F C3 F9 D0 C3 E6 92 E8 53 44 C1 72 9A 85 F2 B8 15 26 50 0A 61 80 51 19 01 A8 9E 02 AB 98 09 1F 60 21 3D 80 85 10 02 FA 88 5F DD 41 91 E9 86 96 C0 18 56 88 64 73 C1 BE 79 87 5F AC 19 96 B7 FF FF FF FF FF FF FF FF FF FF FF F8 00 00 06 59 E3 7E 59 E3 7E 3A 61 86 19 61 76 3A 65 84 94 4D 18 C6 3C 47 D3 00 AB 43 28 AB 44 77 96 82 00 20 A4 15 28 84 00 00 00 00 20 20 01 00 6D F6 FB E4 84 84 C4 44 34 D4 C4 C4 8E BA 12 53 39 F0 E0 23 C7 24 33 27 2E 4E 5C CD 7B BA FF B5 FD 6D 34 DC 7A 49 A8 93 28 0A C0 17 BD 42 BA D4 F6 BD EC 95 DB 8C 67 B0 EB D1 E4 A1 31 82 84 F9 57 D3 E5 4B FF B8 33 9E F3 BB FA 52 3D E9 31 8F A6 F0 21 55 47 85 C6 8E 04 94 08 1B 98 DF 66 87 FD ED 39 F8 DC 57 D7 36 DF 5F D5 83 6F A6 10 36 48 41 18 C0 66 C9 81 DE 89 FF FF FF FF FF FF FF FF FF FF E0 00 00 B6 6B 2F A5 DB 2E 9F 0E 2A 7E D8 D2 A6 9B 6D CC DF CD 8C D3 00 7D 44 68 AB 44 77 96 80 00 20 88 58 00 00 40 00 00 00 20 01 01 00 7F FF 4F 56 4F 4E 59 2D 98 06 05 64 A8 45 06 8A 14 15 88 2C E0 61 B8 D1 F3 98 47 1C CE 89 E7 B9 CF 01 A0 83 38 8E 8D AD 35 20 D7 39 84 0A CE 10 BE 28 35 B2 C1 08 F1 04 5A DC 1F 2B A0 82 2A 22 17 40 FA 3A B5 E8 FE EF A6 3F 9E 0B 83 77 49 5B DD 96 AF FF FF FF FF FF FF FF 80 00 C3 4C AC BA CA AD AE CC 6F 9E CA 00 7D 4E 53

用 pyrtcm · PyPI 解析一下

#!/usr/bin/python3
# python3 -m pip install pyrtcm
from pyrtcm import RTCMReadermsgs = [b"\xD3\x00\x13\x3E\xD8\xAB\x03\xFA\x6E\x82\x93\x49\x0C\x89\xE2\x22\x0E\x05\xAA\x3E\x6C\x41\x47\x1D\x57",b"\xD3\x00\x1F\x40\x98\xAB\x0E\x41\x44\x56\x4E\x55\x4C\x4C\x41\x4E\x54\x45\x4E\x4E\x41\x00\x00\x08\x51\x58\x57\x5A\x20\x56\x52\x53\x00\x00\x40\xC7\xB8",b"\xD3\x00\x42\x43\xC8\xAB\x69\x3D\x5B\x42\x00\x20\x81\x00\x0C\x00\x00\x00\x00\x00\x30\xC0\x00\x00\x4C\xCA\x2A\x32\x06\xCE\x67\xD7\xB9\xEC\x74\xBA\x0E\x8E\x22\x5D\xA0\x57\x4B\xF7\xAE\x79\x9E\xF4\x8D\x83\x64\xF4\x0E\xEB\x97\xB1\xE5\x1E\xD4\xAA\x7F\xFF\xFF\x81\x8E\x53\x61\xAE\x80\x4C\x62\x43",b"\xD3\x01\x1C\x46\x48\xAB\x44\x76\xBB\xC2\x00\x20\xFA\xE4\x89\x00\x00\x00\x00\x00\x20\x82\x01\x01\x73\x9C\xE7\x39\xCE\x73\x9B\xDB\xDB\xE3\xCC\x03\xD3\xD3\xF4\x1B\xDB\xCA\x8A\xA5\xF6\x85\xC8\xE6\x12\x7E\xD7\x34\x93\x2C\x6B\xC5\xE2\xF4\x18\x50\x30\xB9\x01\x52\xCB\xCD\x97\xEC\x2E\x45\xFA\x6B\xF5\x4F\xE3\xF1\x6B\xC2\xF3\x85\xDF\x87\xE4\x0F\x90\x1F\x03\xAA\x17\x49\x9E\x93\xE0\x70\x80\xEA\x02\x56\xDB\x1B\xBA\xDB\x7A\x87\x05\x1E\x24\xBC\x59\xFF\xF4\x80\x64\x01\x8E\x3E\x70\x79\x41\x09\x21\xFA\x23\xF2\x87\xF9\x11\x6E\x20\x30\x04\x06\x30\x0D\xEC\x80\x20\x1E\x86\x74\x8A\x1A\x86\x48\x70\x5A\x7F\xCC\x0D\x80\x3E\xF1\xFF\x77\xE0\x1D\xA2\x40\x59\xD1\x81\x35\xE6\x0A\x7D\xD8\x2E\x84\x60\xBD\x9D\x7C\xE1\xC7\xF2\x05\xDF\xC5\xE9\xC0\x42\xD6\x01\x4B\x7E\x05\xBF\x8F\xB2\xEF\x5E\xC2\xFB\x7B\x22\xE9\xEE\x7B\xAF\xB7\x96\x3E\xDB\xF3\x00\xA8\x70\x04\x59\xF0\x14\xB0\xC1\x37\x40\x85\x39\xF0\x17\x84\x20\x4F\xC0\x01\x16\x80\x84\x90\xEE\x13\xEE\xB0\x44\xA6\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x00\x00\x00\x00\x5B\x6D\xD5\xDD\x85\xF8\x63\x3D\x56\x5B\x86\x16\x5D\x7D\x76\x5D\x0C\x92\xDB\x75\xD8\x5F\x85\xD8\x5D\x64\xF5\x53\x30\xCA\xA6\xAF",b"\xD3\x00\xB6\x46\x48\xAB\x44\x76\xBB\xC2\x00\x20\x80\x00\x00\x12\x83\x40\x00\x00\x20\x80\x01\x01\x7F\xFF\xFF\xA5\x25\x25\xBC\xBC\x29\xB3\x83\x72\x7F\x69\x55\xE8\x56\x60\x3C\xDA\x99\xD5\x73\x17\x12\x83\x27\x58\x4F\xE0\x96\x4F\xF6\x40\x0E\x00\x41\xFF\xEA\x83\x87\x07\xE8\x12\x00\x1F\x79\x57\x12\xB4\x85\x88\x8A\xED\x98\xB1\x36\xE2\x73\xE4\xCA\x07\x99\x39\x9E\x6F\xC3\xF9\xD0\xC3\xE6\x92\xE8\x53\x44\xC1\x72\x9A\x85\xF2\xB8\x15\x26\x50\x0A\x61\x80\x51\x19\x01\xA8\x9E\x02\xAB\x98\x09\x1F\x60\x21\x3D\x80\x85\x10\x02\xFA\x88\x5F\xDD\x41\x91\xE9\x86\x96\xC0\x18\x56\x88\x64\x73\xC1\xBE\x79\x87\x5F\xAC\x19\x96\xB7\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xF8\x00\x00\x06\x59\xE3\x7E\x59\xE3\x7E\x3A\x61\x86\x19\x61\x76\x3A\x65\x84\x94\x4D\x18\xC6\x3C\x47",b"\xD3\x00\xAB\x43\x28\xAB\x44\x77\x96\x82\x00\x20\xA4\x15\x28\x84\x00\x00\x00\x00\x20\x20\x01\x00\x6D\xF6\xFB\xE4\x84\x84\xC4\x44\x34\xD4\xC4\xC4\x8E\xBA\x12\x53\x39\xF0\xE0\x23\xC7\x24\x33\x27\x2E\x4E\x5C\xCD\x7B\xBA\xFF\xB5\xFD\x6D\x34\xDC\x7A\x49\xA8\x93\x28\x0A\xC0\x17\xBD\x42\xBA\xD4\xF6\xBD\xEC\x95\xDB\x8C\x67\xB0\xEB\xD1\xE4\xA1\x31\x82\x84\xF9\x57\xD3\xE5\x4B\xFF\xB8\x33\x9E\xF3\xBB\xFA\x52\x3D\xE9\x31\x8F\xA6\xF0\x21\x55\x47\x85\xC6\x8E\x04\x94\x08\x1B\x98\xDF\x66\x87\xFD\xED\x39\xF8\xDC\x57\xD7\x36\xDF\x5F\xD5\x83\x6F\xA6\x10\x36\x48\x41\x18\xC0\x66\xC9\x81\xDE\x89\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xE0\x00\x00\xB6\x6B\x2F\xA5\xDB\x2E\x9F\x0E\x2A\x7E\xD8\xD2\xA6\x9B\x6D\xCC\xDF\xCD\x8C",b"\xD3\x00\x7D\x44\x68\xAB\x44\x77\x96\x80\x00\x20\x88\x58\x00\x00\x40\x00\x00\x00\x20\x01\x01\x00\x7F\xFF\x4F\x56\x4F\x4E\x59\x2D\x98\x06\x05\x64\xA8\x45\x06\x8A\x14\x15\x88\x2C\xE0\x61\xB8\xD1\xF3\x98\x47\x1C\xCE\x89\xE7\xB9\xCF\x01\xA0\x83\x38\x8E\x8D\xAD\x35\x20\xD7\x39\x84\x0A\xCE\x10\xBE\x28\x35\xB2\xC1\x08\xF1\x04\x5A\xDC\x1F\x2B\xA0\x82\x2A\x22\x17\x40\xFA\x3A\xB5\xE8\xFE\xEF\xA6\x3F\x9E\x0B\x83\x77\x49\x5B\xDD\x96\xAF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x00\xC3\x4C\xAC\xBA\xCA\xAD\xAE\xCC\x6F\x9E\xCA\x00\x7D\x4E\x53"
]for msg in msgs:result = RTCMReader.parse(msg)if result:print(result)

结果如下

<RTCM(1005, DF002=1005, DF003=2219, DF021=0, DF022=1, DF023=1, DF024=1, DF141=1, DF025=-2391575.2631, DF142=0, DF001_1=0, DF026=5385290.5998, DF364=0, DF027=2433105.4145)><RTCM(1033, DF002=1033, DF003=2219, DF029=14, DF030_01=A, DF031_01=68, DF030_02=V, DF031_02=78, DF030_03=U, DF031_03=76, DF030_04=L, DF031_04=65, DF030_05=N, DF031_05=84, DF030_06=E, DF031_06=78, DF030_07=N, DF031_07=65, DF030_08=, DF031_08=0, DF030_09, DF031_09=81, DF030_10=X, DF031_10=87, DF030_11=Z, DF031_11=32, DF030_12=V, DF031_12=82, DF030_13=S, DF031_13=0, DF030_14=, DF031_14=0, DF032=0, DF227=0, DF229=0, DF231=0)><RTCM(1084, DF002=1084, DF003=2219, GNSSEpoch=441407184, DF393=1, DF409=0, DF001_7=0, DF411=1, DF412=0, DF417=0, DF418=1, DF394=144141576354922496, NSat=3, DF395=1635778560, NSig=4, DF396=2457, DF400_01=0.00052851, DF400_02=0.00024736, DF400_03=0.00087923, DF400_04=0.00072402, DF400_05=-0.00029826, DF400_06=-0.00053364, DF400_07=0.00054216, DF400_08=-0.00079799, DF400_09=8.321e-05, DF400_10=-0.00049227, DF400_11=0.00088346, DF400_12=0.00094467, DF401_01=0.00082478, DF401_02=0.00372403, DF401_03=0.00350836, DF401_04=0.0012501, DF401_05=0.00259399, DF401_06=-7.54e-06, DF401_07=-0.00163505, DF401_08=6.91e-06, DF401_09=0, DF401_10=0, DF401_11=0, DF401_12=0, DF402_01=0, DF402_02=0, DF402_03=0, DF402_04=0, DF402_05=0, DF402_06=0, DF402_07=0, DF402_08=0, DF402_09=0, DF402_10=0, DF402_11=0, DF402_12=0, DF420_01=0, DF420_02=0, DF420_03=0, DF420_04=0, DF420_05=0, DF420_06=0, DF420_07=0, DF420_08=0, DF420_09=0, DF420_10=0, DF420_11=0, DF420_12=0, DF403_01=0, DF403_02=0, DF403_03=0, DF403_04=0, DF403_05=0, DF403_06=0, DF403_07=0, DF403_08=0, DF403_09=0, DF403_10=0, DF403_11=0, DF403_12=0)><RTCM(1124, DF002=1124, DF003=2219, GNSSEpoch=287158000, DF393=1, DF409=0, DF001_7=0, DF411=1, DF412=0, DF417=0, DF418=1, DF394=17710706800820486144, NSat=12, DF395=1090781698, NSig=5, DF396=1041348455773926267, DF400_01=0.00094211, DF400_02=0.00046349, DF400_03=0.00023359, DF400_04=0.00060892, DF400_05=0.00042504, DF400_06=-0.00040787, DF400_07=0.00063306, DF400_08=-0.0007214, DF400_09=0.0002194, DF400_10=0.00030458, DF400_11=-0.0005368, DF400_12=0.00058508, DF400_13=-0.00030869, DF400_14=-0.00022161, DF400_15=9.274e-05, DF400_16=9.292e-05, DF400_17=0.00024539, DF400_18=0.0003413, DF400_19=0.00082964, DF400_20=-0.00060487, DF400_21=-0.00088537, DF400_22=0.00082362, DF400_23=-0.00067186, DF400_24=-2.784e-05, DF400_25=0.00091833, DF400_26=0.00042999, DF400_27=-2.867e-05, DF400_28=-0.00085264, DF400_29=0.00024599, DF400_30=2.795e-05, DF400_31=8.881e-05, DF400_32=0.00079072, DF400_33=0.00094646, DF400_34=6.145e-05, DF400_35=0.00061089, DF400_36=0.00069749, DF400_37=0.00042307, DF400_38=-0.00027865, DF400_39=0.00051504, DF400_40=0.00054574, DF400_41=-0.00079697, DF400_42=-0.00073248, DF400_43=-0.00070184, DF400_44=-0.00085431, DF400_45=0.00021732, DF400_46=0.00085807, DF400_47=-0.00072849, DF400_48=0.00055307, DF400_49=0.00052255, DF400_50=0.00030893, DF400_51=-0.00042313, DF400_52=-0.0005455, DF400_53=0.00073266, DF400_54=4.721e-05, DF400_55=5.311e-05, DF400_56=0.00024438, DF400_57=2.909e-05, DF400_58=0.00078797, DF400_59=0.00061667, DF400_60=0.00019169, DF401_01=-0.00095499, DF401_02=-0.00079265, DF401_03=0.00024012, DF401_04=-0.00012982, DF401_05=0.0018087, DF401_06=0.00137052, DF401_07=0.00118217, DF401_08=0.00256142, DF401_09=0.00283918, DF401_10=0.0028933, DF401_11=-0.00304496, DF401_12=-0.00341237, DF401_13=-0.00354534, DF401_14=0.00101984, DF401_15=0.00126454, DF401_16=0.00140339, DF401_17=0.00310883, DF401_18=0.00297519, DF401_19=0.00306287, DF401_20=0.00353592, DF401_21=0.00339275, DF401_22=0.00335616, DF401_23=0.00064254, DF401_24=0.00106233, DF401_25=0.00126284, DF401_26=-0.00306317, DF401_27=-0.00270867, DF401_28=-0.00207126, DF401_29=-0.00294495, DF401_30=-0.0035629, DF401_31=-0.00335339, DF401_32=-0.0029462, DF401_33=-0.0036223, DF401_34=-0.0, DF401_35=-0.0, DF401_36=-0.0, DF401_37=-0.0, DF401_38=-0.0, DF401_39=-0.0, DF401_40=-1.2e-07, DF401_41=0.0, DF401_42=5.45e-06, DF401_43=-0.00211386, DF401_44=0.00145758, DF401_45=0.00374373, DF401_46=-0.00186024, DF401_47=-0.00245109, DF401_48=-0.00072043, DF401_49=-0.0022302, DF401_50=0.00145756, DF401_51=0.00035627, DF401_52=-0.00520936, DF401_53=0, DF401_54=0, DF401_55=0, DF401_56=0, DF401_57=0, DF401_58=0, DF401_59=0, DF401_60=0, DF402_01=0, DF402_02=0, DF402_03=0, DF402_04=0, DF402_05=0, DF402_06=0, DF402_07=0, DF402_08=0, DF402_09=0, DF402_10=0, DF402_11=0, DF402_12=0, DF402_13=0, DF402_14=0, DF402_15=0, DF402_16=0, DF402_17=0, DF402_18=0, DF402_19=0, DF402_20=0, DF402_21=0, DF402_22=0, DF402_23=0, DF402_24=0, DF402_25=0, DF402_26=0, DF402_27=0, DF402_28=0, DF402_29=0, DF402_30=0, DF402_31=0, DF402_32=0, DF402_33=0, DF402_34=0, DF402_35=0, DF402_36=0, DF402_37=0, DF402_38=0, DF402_39=0, DF402_40=0, DF402_41=0, DF402_42=0, DF402_43=0, DF402_44=0, DF402_45=0, DF402_46=0, DF402_47=0, DF402_48=0, DF402_49=0, DF402_50=0, DF402_51=0, DF402_52=0, DF402_53=0, DF402_54=0, DF402_55=0, DF402_56=0, DF402_57=0, DF402_58=0, DF402_59=0, DF402_60=0, DF420_01=0, DF420_02=0, DF420_03=0, DF420_04=0, DF420_05=0, DF420_06=0, DF420_07=0, DF420_08=0, DF420_09=0, DF420_10=0, DF420_11=0, DF420_12=0, DF420_13=0, DF420_14=0, DF420_15=0, DF420_16=0, DF420_17=0, DF420_18=0, DF420_19=0, DF420_20=0, DF420_21=0, DF420_22=0, DF420_23=0, DF420_24=0, DF420_25=0, DF420_26=0, DF420_27=0, DF420_28=0, DF420_29=0, DF420_30=0, DF420_31=0, DF420_32=0, DF420_33=0, DF420_34=0, DF420_35=0, DF420_36=0, DF420_37=0, DF420_38=0, DF420_39=0, DF420_40=0, DF420_41=0, DF420_42=0, DF420_43=0, DF420_44=0, DF420_45=0, DF420_46=0, DF420_47=0, DF420_48=0, DF420_49=0, DF420_50=0, DF420_51=0, DF420_52=0, DF420_53=0, DF420_54=0, DF420_55=0, DF420_56=0, DF420_57=0, DF420_58=0, DF420_59=0, DF420_60=0, DF403_01=0, DF403_02=0, DF403_03=0, DF403_04=0, DF403_05=0, DF403_06=0, DF403_07=0, DF403_08=0, DF403_09=0, DF403_10=0, DF403_11=0, DF403_12=0, DF403_13=0, DF403_14=0, DF403_15=0, DF403_16=0, DF403_17=0, DF403_18=0, DF403_19=0, DF403_20=0, DF403_21=0, DF403_22=0, DF403_23=0, DF403_24=0, DF403_25=0, DF403_26=0, DF403_27=0, DF403_28=0, DF403_29=0, DF403_30=0, DF403_31=0, DF403_32=0, DF403_33=0, DF403_34=0, DF403_35=0, DF403_36=0, DF403_37=0, DF403_38=0, DF403_39=0, DF403_40=0, DF403_41=0, DF403_42=0, DF403_43=0, DF403_44=0, DF403_45=0, DF403_46=0, DF403_47=0, DF403_48=0, DF403_49=0, DF403_50=0, DF403_51=0, DF403_52=0, DF403_53=0, DF403_54=0, DF403_55=0, DF403_56=0, DF403_57=0, DF403_58=0, DF403_59=0, DF403_60=0)><RTCM(1124, DF002=1124, DF003=2219, GNSSEpoch=287158000, DF393=1, DF409=0, DF001_7=0, DF411=1, DF412=0, DF417=0, DF418=1, DF394=159022841856, NSat=6, DF395=1090519554, NSig=4, DF396=16777215, DF400_01=0.00056678, DF400_02=0.00028789, DF400_03=0.00071776, DF400_04=0.00083065, DF400_05=0.00084156, DF400_06=-7.188e-05, DF400_07=-0.00061601, DF400_08=0.00068283, DF400_09=0.00092852, DF400_10=-0.00077951, DF400_11=-0.00053757, DF400_12=-0.000453, DF400_13=0.00076991, DF400_14=-0.00093848, DF400_15=3.582e-05, DF400_16=0.00048709, DF400_17=-0.00097573, DF400_18=1.91e-06, DF400_19=-3.6e-07, DF400_20=-0.00072575, DF400_21=-0.00023663, DF400_22=-0.00096798, DF400_23=7.45e-06, DF400_24=-0.00020325, DF401_01=0.00114167, DF401_02=-0.00182278, DF401_03=-0.00234721, DF401_04=-0.00222545, DF401_05=-0.00166082, DF401_06=-0.00156822, DF401_07=-0.00152677, DF401_08=-0.00150989, DF401_09=-0.00155189, DF401_10=0.00127058, DF401_11=0.00141374, DF401_12=0.00145218, DF401_13=0.00129087, DF401_14=0.0001584, DF401_15=0.00030936, DF401_16=0.00040495, DF401_17=0.00016298, DF401_18=0.0001392, DF401_19=0.0001268, DF401_20=0.0001269, DF401_21=0.0001818, DF401_22=0.00146277, DF401_23=0.00153317, DF401_24=0.00160861, DF402_01=3, DF402_02=0, DF402_03=10, DF402_04=13, DF402_05=1, DF402_06=0, DF402_07=12, DF402_08=8, DF402_09=14, DF402_10=7, DF402_11=8, DF402_12=3, DF402_13=7, DF402_14=12, DF402_15=15, DF402_16=3, DF402_17=0, DF402_18=14, DF402_19=11, DF402_20=15, DF402_21=5, DF402_22=8, DF402_23=3, DF402_24=3, DF420_01=0, DF420_02=0, DF420_03=1, DF420_04=0, DF420_05=1, DF420_06=1, DF420_07=0, DF420_08=1, DF420_09=0, DF420_10=1, DF420_11=1, DF420_12=0, DF420_13=1, DF420_14=1, DF420_15=1, DF420_16=1, DF420_17=1, DF420_18=1, DF420_19=1, DF420_20=1, DF420_21=1, DF420_22=1, DF420_23=1, DF420_24=1, DF403_01=63, DF403_02=63, DF403_03=63, DF403_04=63, DF403_05=63, DF403_06=63, DF403_07=63, DF403_08=63, DF403_09=63, DF403_10=63, DF403_11=63, DF403_12=63, DF403_13=63, DF403_14=63, DF403_15=0, DF403_16=0, DF403_17=0, DF403_18=0, DF403_19=50, DF403_20=51, DF403_21=49, DF403_22=47, DF403_23=50, DF403_24=51)><RTCM(1074, DF002=1074, DF003=2219, GNSSEpoch=287172000, DF393=1, DF409=0, DF001_7=0, DF411=1, DF412=0, DF417=0, DF418=1, DF394=5200057814554247168, NSat=9, DF395=1077936640, NSig=3, DF396=115306430, DF400_01=0.00055146, DF400_02=0.00029093, DF400_03=0.00012833, DF400_04=-0.0006597, DF400_05=-0.00045353, DF400_06=0.00070977, DF400_07=-0.00081784, DF400_08=0.00047386, DF400_09=1.705e-05, DF400_10=0.00043583, DF400_11=-0.00039208, DF400_12=0.00070655, DF400_13=0.00070798, DF400_14=-0.00050461, DF400_15=-0.00048888, DF400_16=-0.00049078, DF400_17=-0.00034106, DF400_18=-0.00021499, DF400_19=0.00029474, DF400_20=0.0002923, DF400_21=8.202e-05, DF400_22=9.054e-05, DF400_23=0.00061554, DF400_24=0.00069135, DF400_25=0.00082296, DF400_26=0.00076813, DF400_27=0.00084066, DF401_01=-0.0014837, DF401_02=-0.00070354, DF401_03=0.00116543, DF401_04=0.00121435, DF401_05=-0.00269192, DF401_06=-4.28e-06, DF401_07=0.00353604, DF401_08=-0.00098198, DF401_09=0.00377874, DF401_10=-0.00171429, DF401_11=0.00012716, DF401_12=0.00183656, DF401_13=0.00085558, DF401_14=0.00012372, DF401_15=0.0008522, DF401_16=0.00195115, DF401_17=0.00353834, DF401_18=0.00134034, DF401_19=-0.00110102, DF401_20=-0.0025602, DF401_21=0.0023232, DF401_22=0.00110251, DF401_23=0.00073395, DF401_24=0.00232112, DF401_25=0.00061035, DF401_26=-0.0, DF401_27=-0.0, DF402_01=15, DF402_02=15, DF402_03=15, DF402_04=15, DF402_05=15, DF402_06=15, DF402_07=0, DF402_08=0, DF402_09=0, DF402_10=0, DF402_11=0, DF402_12=5, DF402_13=11, DF402_14=3, DF402_15=5, DF402_16=9, DF402_17=7, DF402_18=13, DF402_19=2, DF402_20=14, DF402_21=13, DF402_22=9, DF402_23=7, DF402_24=4, DF402_25=15, DF402_26=8, DF402_27=7, DF420_01=0, DF420_02=0, DF420_03=0, DF420_04=1, DF420_05=0, DF420_06=1, DF420_07=0, DF420_08=1, DF420_09=0, DF420_10=0, DF420_11=1, DF420_12=1, DF420_13=1, DF420_14=1, DF420_15=1, DF420_16=1, DF420_17=0, DF420_18=1, DF420_19=1, DF420_20=0, DF420_21=1, DF420_22=1, DF420_23=0, DF420_24=0, DF420_25=0, DF420_26=1, DF420_27=1, DF403_01=18, DF403_02=41, DF403_03=41, DF403_04=45, DF403_05=45, DF403_06=51, DF403_07=0, DF403_08=0, DF403_09=0, DF403_10=0, DF403_11=0, DF403_12=0, DF403_13=0, DF403_14=0, DF403_15=0, DF403_16=0, DF403_17=0, DF403_18=0, DF403_19=0, DF403_20=0, DF403_21=0, DF403_22=0, DF403_23=0, DF403_24=0, DF403_25=0, DF403_26=0, DF403_27=0)><RTCM(1094, DF002=1094, DF003=2219, GNSSEpoch=287172000, DF393=0, DF409=0, DF001_7=0, DF411=1, DF412=0, DF417=0, DF418=1, DF394=1202461102655406080, NSat=5, DF395=1073873408, NSig=3, DF396=32767, DF400_01=0.00060529, DF400_02=0.00030249, DF400_03=-0.00080651, DF400_04=-0.00058746, DF400_05=0.00073498, DF400_06=0.00028425, DF400_07=0.00015336, DF400_08=0.00015378, DF400_09=0.00016427, DF400_10=0.00017118, DF400_11=0.00018638, DF400_12=0.00020021, DF400_13=0.00043881, DF400_14=0.0004341, DF400_15=0.00044364, DF401_01=-0.00148158, DF401_02=-0.00388142, DF401_03=0.00314543, DF401_04=0.00333901, DF401_05=0.00200444, DF401_06=-0.00189145, DF401_07=-0.00188926, DF401_08=0.00200433, DF401_09=-0.00384308, DF401_10=-0.0038398, DF401_11=-0.00378734, DF401_12=0.00012413, DF401_13=0.00208074, DF401_14=0.0038182, DF401_15=-0.00204088, DF402_01=7, DF402_02=13, DF402_03=3, DF402_04=1, DF402_05=15, DF402_06=12, DF402_07=15, DF402_08=0, DF402_09=5, DF402_10=12, DF402_11=1, DF402_12=11, DF402_13=11, DF402_14=10, DF402_15=4, DF420_01=1, DF420_02=0, DF420_03=1, DF420_04=0, DF420_05=1, DF420_06=1, DF420_07=0, DF420_08=1, DF420_09=1, DF420_10=1, DF420_11=1, DF420_12=0, DF420_13=1, DF420_14=1, DF420_15=1, DF403_01=25, DF403_02=26, DF403_03=47, DF403_04=63, DF403_05=63, DF403_06=63, DF403_07=63, DF403_08=63, DF403_09=63, DF403_10=63, DF403_11=63, DF403_12=63, DF403_13=56, DF403_14=0, DF403_15=0)>

可以看出

  • 1084电文, 格洛纳斯, NSat=3
  • 1124电文, 北斗, 拆成了2条(为什么?), NSat=12, NSat=6, 共计18颗星
  • 1074, GPS, NSat=9
  • 1094, 伽利略, NSat=5
  • 合计 35 颗星

更多RTCM的电文信息可以参考:

  • AN018_RTCM3.2格式说明_北云科技.pdf (bynav.com)
  • RTCM 3 Message List - SNIP Support (use-snip.com)
  • RTCM | RTCM格式说明-Java架构师必看 (javajgs.com), 里面有RTCM2.x, 3.2, 3.3的区别
  • Tech Chat - What is RTCM format in RTK correction data transmission?_Blog_SingularXYZ
  • PPT - RTCM Data Format ( R adio T echnical C ommission for M aritime Services) PowerPoint Presentation - ID:1205572 (slideserve.com)

RTCM各版本演进

  • RTCM 2.0: Code Correction -> DGPS
  • RTCM 2.1: Code+Phase Correction -> RTK, 引入了相位
  • RTCM 2.2: …+GLONASS, 引入了格洛纳斯
  • RTCM 2.3: …+GPS Antenna Definition
  • RTCM 2.X总结:2.0需要0.5kbit/sec支持DGPS, 2.1~2.3需要5kbit/sec支持DGPS+RTK. 只支持部分系统,进行单一功能的扩展,目前该格式使用的已经不多
  • RTCM 3.0: …+Network RTK & GNSS
  • RTCM3.2: 使用的较多,为标准格式;
  • RTCM3.3: 格式与 RTCM3.2 基本一致,在RTCM3.2基础上增加了北斗星历、GA1-7星历、SBAS系统等;

RTCM Packet 包格式(帧结构)

  • 3字节Header, 共24bit, 包含 8bit 前导码(Preamble, D3), 6bit 保留位(Reserved bits, 全0), 10bit 数据长度(Data Length, 0~1023, 字节数)
  • 数据 Data, 前12bit会给出信息类型, 也就是我们常说的 1005电文(0x3ED), 1033电文(0x409), 1084电文(0x43C), 1124电文(0x464), 1074电文(0x432), 1094电文(0x446)等. 再接着12bit是基站ID, 剩下的不同电文有不同的定义
  • 3字节校验(Parity), CRC24

查表法算CRC24

这里用查表法给出一个CRC24的例子, 参考自 rtcm/crc.ts at master · Node-NTRIP/rtcm (github.com)

#include <stdio.h>
#include <stdint.h>const uint32_t CRC24Q_TABLE[] = {0x00000000, 0x01864CFB, 0x028AD50D, 0x030C99F6,0x0493E6E1, 0x0515AA1A, 0x061933EC, 0x079F7F17,0x08A18139, 0x0927CDC2, 0x0A2B5434, 0x0BAD18CF,0x0C3267D8, 0x0DB42B23, 0x0EB8B2D5, 0x0F3EFE2E,0x10C54E89, 0x11430272, 0x124F9B84, 0x13C9D77F,0x1456A868, 0x15D0E493, 0x16DC7D65, 0x175A319E,0x1864CFB0, 0x19E2834B, 0x1AEE1ABD, 0x1B685646,0x1CF72951, 0x1D7165AA, 0x1E7DFC5C, 0x1FFBB0A7,0x200CD1E9, 0x218A9D12, 0x228604E4, 0x2300481F,0x249F3708, 0x25197BF3, 0x2615E205, 0x2793AEFE,0x28AD50D0, 0x292B1C2B, 0x2A2785DD, 0x2BA1C926,0x2C3EB631, 0x2DB8FACA, 0x2EB4633C, 0x2F322FC7,0x30C99F60, 0x314FD39B, 0x32434A6D, 0x33C50696,0x345A7981, 0x35DC357A, 0x36D0AC8C, 0x3756E077,0x38681E59, 0x39EE52A2, 0x3AE2CB54, 0x3B6487AF,0x3CFBF8B8, 0x3D7DB443, 0x3E712DB5, 0x3FF7614E,0x4019A3D2, 0x419FEF29, 0x429376DF, 0x43153A24,0x448A4533, 0x450C09C8, 0x4600903E, 0x4786DCC5,0x48B822EB, 0x493E6E10, 0x4A32F7E6, 0x4BB4BB1D,0x4C2BC40A, 0x4DAD88F1, 0x4EA11107, 0x4F275DFC,0x50DCED5B, 0x515AA1A0, 0x52563856, 0x53D074AD,0x544F0BBA, 0x55C94741, 0x56C5DEB7, 0x5743924C,0x587D6C62, 0x59FB2099, 0x5AF7B96F, 0x5B71F594,0x5CEE8A83, 0x5D68C678, 0x5E645F8E, 0x5FE21375,0x6015723B, 0x61933EC0, 0x629FA736, 0x6319EBCD,0x648694DA, 0x6500D821, 0x660C41D7, 0x678A0D2C,0x68B4F302, 0x6932BFF9, 0x6A3E260F, 0x6BB86AF4,0x6C2715E3, 0x6DA15918, 0x6EADC0EE, 0x6F2B8C15,0x70D03CB2, 0x71567049, 0x725AE9BF, 0x73DCA544,0x7443DA53, 0x75C596A8, 0x76C90F5E, 0x774F43A5,0x7871BD8B, 0x79F7F170, 0x7AFB6886, 0x7B7D247D,0x7CE25B6A, 0x7D641791, 0x7E688E67, 0x7FEEC29C,0x803347A4, 0x81B50B5F, 0x82B992A9, 0x833FDE52,0x84A0A145, 0x8526EDBE, 0x862A7448, 0x87AC38B3,0x8892C69D, 0x89148A66, 0x8A181390, 0x8B9E5F6B,0x8C01207C, 0x8D876C87, 0x8E8BF571, 0x8F0DB98A,0x90F6092D, 0x917045D6, 0x927CDC20, 0x93FA90DB,0x9465EFCC, 0x95E3A337, 0x96EF3AC1, 0x9769763A,0x98578814, 0x99D1C4EF, 0x9ADD5D19, 0x9B5B11E2,0x9CC46EF5, 0x9D42220E, 0x9E4EBBF8, 0x9FC8F703,0xA03F964D, 0xA1B9DAB6, 0xA2B54340, 0xA3330FBB,0xA4AC70AC, 0xA52A3C57, 0xA626A5A1, 0xA7A0E95A,0xA89E1774, 0xA9185B8F, 0xAA14C279, 0xAB928E82,0xAC0DF195, 0xAD8BBD6E, 0xAE872498, 0xAF016863,0xB0FAD8C4, 0xB17C943F, 0xB2700DC9, 0xB3F64132,0xB4693E25, 0xB5EF72DE, 0xB6E3EB28, 0xB765A7D3,0xB85B59FD, 0xB9DD1506, 0xBAD18CF0, 0xBB57C00B,0xBCC8BF1C, 0xBD4EF3E7, 0xBE426A11, 0xBFC426EA,0xC02AE476, 0xC1ACA88D, 0xC2A0317B, 0xC3267D80,0xC4B90297, 0xC53F4E6C, 0xC633D79A, 0xC7B59B61,0xC88B654F, 0xC90D29B4, 0xCA01B042, 0xCB87FCB9,0xCC1883AE, 0xCD9ECF55, 0xCE9256A3, 0xCF141A58,0xD0EFAAFF, 0xD169E604, 0xD2657FF2, 0xD3E33309,0xD47C4C1E, 0xD5FA00E5, 0xD6F69913, 0xD770D5E8,0xD84E2BC6, 0xD9C8673D, 0xDAC4FECB, 0xDB42B230,0xDCDDCD27, 0xDD5B81DC, 0xDE57182A, 0xDFD154D1,0xE026359F, 0xE1A07964, 0xE2ACE092, 0xE32AAC69,0xE4B5D37E, 0xE5339F85, 0xE63F0673, 0xE7B94A88,0xE887B4A6, 0xE901F85D, 0xEA0D61AB, 0xEB8B2D50,0xEC145247, 0xED921EBC, 0xEE9E874A, 0xEF18CBB1,0xF0E37B16, 0xF16537ED, 0xF269AE1B, 0xF3EFE2E0,0xF4709DF7, 0xF5F6D10C, 0xF6FA48FA, 0xF77C0401,0xF842FA2F, 0xF9C4B6D4, 0xFAC82F22, 0xFB4E63D9,0xFCD11CCE, 0xFD575035, 0xFE5BC9C3, 0xFFDD8538,
};uint32_t crc24q(uint8_t *data, uint32_t len) {uint32_t crc = 0;for (int i = 0; i < len; i++) {crc = (crc << 8) ^ CRC24Q_TABLE[(data[i] ^ (crc >> 16)) & 0xff];}return crc & 0xffffff;
}int main()
{// D3 00 13 3E D8 AB 03 FA 6E 82 93 49 0C 89 E2 22 0E 05 AA 3E 6C 41 47 1D 57 uint8_t data[] = {0xD3,0x00,0x13,0x3E,0xD8,0xAB,0x03,0xFA,0x6E,0x82,0x93,0x49,0x0C,0x89,0xE2,0x22,0x0E,0x05,0xAA,0x3E,0x6C,0x41};uint32_t crc = crc24q(data, sizeof(data));printf("%x\n", crc);    //471d57return 0;
}

RTKLIB中也有decode_rtcm3等, RTCM报文的decode或者parser就不赘述了.

欢迎扫描二维码关注微信公众号, 及时获取最新文章:

GPGGA NTRIP RTCM 笔记相关推荐

  1. ntrip获取源列表_Ntrip通讯协议怎么样?

    1 什么是Ntrip? CORS(Continuously Operating Reference Stations)就是网络基准站,通过网络收发GPS差分数据.用户访问CORS后,不用单独架设GPS ...

  2. ntrip获取源列表_Ntrip协议简介(转)

    1 什么是Ntrip? CORS(Continuously Operating Reference Stations)就是网络基准站,通过网络收发GPS差分数据.用户访问CORS后,不用单独架设GPS ...

  3. Apollo GPS调试笔记

    前言:在Apollo美研团队的支持下,最近完成了Apollo推荐的Novatel PP7与我们的基站调试,在这里对Apollo的笔记做一个补充,希望以后的开发者不用在踩我们踩过的坑. 在自己调导航(h ...

  4. Ntrip通讯协议1.0

    Ntrip通讯协议1.0 1 什么是Ntrip? CORS(Continuously Operating Reference Stations)就是网络基准站,通过网络收发GPS差分数据.用户访问CO ...

  5. NTRIP Caster---SNIP服务器

    一.关于SNIP snip主要是用snip NTRIP Caster做定位差分数据的转发服务器. 二.什么是SNIP? https://www.use-snip.com/ ,美国SubCarrier ...

  6. GPS nmealib学习笔记

    GPS nmealib学习笔记 标签: GPSnmealibCSTACKHEAP 2013-10-17 11:12 4274人阅读 评论(7) 收藏 举报  分类: 嵌入式ARM(24)  版权声明: ...

  7. NTRIP/ SUPL

    1. NTRIP - Network transport of RTCM via Internet NTRIP version 1.0:  http://igs.bkg.bund.de/index_n ...

  8. GPS使用记录NMEA数据解析、RTK定位以及ntrip协议

    目录 1. 概述 2. 泰斗GPS定位模组 3. RTK GPS定位 4. ntrip协议 5. 千寻 1. 概述 本文主要是记录下GPS相关的内容.最开始叫做<泰斗GPS使用记录>,那时 ...

  9. 笔记:中国大学MOOC课程《程序设计入门——C语言》编程练习

    笔记:中国大学MOOC课程<程序设计入门--C语言>编程练习 第7周 数组运算 1 多项式加法 第8周 指针与字符串 2 GPS数据处理 第7周 数组运算 1 多项式加法 题目内容: 一个 ...

  10. 什么是Ntrip?Ntrip协议简介

    文章目录 Ntrip通讯协议1.0 Ntrip是什么? Ntrip系统组成 NtripServer NtripClient 4.1 获取源列表 4.2 获取差分数据 其他资料 Ntrip通讯协议1.0 ...

最新文章

  1. CAAI白皮书丨中国人工智能创新应用白皮书(附下载)
  2. 多进程的一些注意事项
  3. 深入探讨struts的ActionMessages消息机制(转)
  4. kibana操作elasticsearch:修改数据
  5. 采用存储复制方式同步数据,实现数据库安全升级
  6. Java List接口概述
  7. 快查电脑:开关机记录等(电脑使用痕迹)
  8. 更新Svn客户端后,右键菜单中没有TortoiseSVN
  9. HTM皮质学习算法资料
  10. unix操作系统图标大全
  11. 【Window】英文系统显示中文乱码
  12. C语言学习-翁凯(第二章笔记)
  13. 4r照片尺寸是多大_4R照片是什么尺寸,跟普通照片有什么区别? – 手机爱问
  14. Centos7安装Docker,阿里源,网易镜像
  15. 《重构 改善既有代码的设计 1》重构原则
  16. LeetCode 0883「三维形体投影面积」
  17. 关于vertical-align:middle的理解
  18. 快速获取容器VIPs,解决集群自动化测试难题
  19. JavaWeb三层架构的理解/三层架构的优缺点/三层架构与MVC的区别
  20. Ubuntu 11.04 联想 Lenovo Ideapad V470 无线网络不可用解决方法

热门文章

  1. 信号检测与估计理论_永磁同步电机无传感器控制的新策略,提升转子位置检测精度...
  2. python连接服务器informix_连接到Informix数据库 - Python方式
  3. sqlserver 2012 MSSQLSERVER服务显示正在挂起更改且无法启动
  4. 张孝祥JavaScript视频教程flash版
  5. 【Windows】操作系统原理
  6. python科学计算之anaconda
  7. NoSQL数据库的安装和使用
  8. 创业公司研发团队面临的项目管理难题探讨
  9. 调试过程中需要使用的工具
  10. 嵌入式软件工程师所需技能