查表法计算CRC-24Q,并校验RTCM数据是否正确

利用RTK进行辅助的定位设备,有时需要分析定位设备接收到的RTCM数据是否正确,初步的校验方法是通过对接收到的数据进行CRC校验,以确定RTCM数据在传输过程中是否产生了错误。

RTCM3.2每条电文的结构如下:

因此,可对接收到的每帧RTCM电文计算其CRC校验码,并将计算得到的校验码与接收到的RTCM原始数据尾部带的24位校验码进行比对。若两者吻合,则说明数据传输无误;若两者不吻合,则说明RTCM数据传输过程中产生的错误。

本例通过查表法计算RTCM数据的校验码,并将计算的校验码与原校验码比对,python脚本如下:

#!/usr/bin/python
# -*- coding:gbk -*-

import os
import os.path as op

#-----------------------------------------------------------------------
#查表法,进行CRC校验码计算
def CalculateCRC2(rtcm_data):
	CRC_Tabel_file = 'C:\\Users\\Desktop\\RTK\CRC-24Q.txt'
	with open(CRC_Tabel_file,'r') as f:
		tbl_CRC24Q = f.readlines()
	tbl_CRC24Q = tbl_CRC24Q[0].split(',')	
	CRC = 0
	for k in range(len(rtcm_data)-3):
		rtcm_dec = int(rtcm_data[k],16)
		p1 = (CRC<<8)&int('FFFFFF',16)
		p2 = int(tbl_CRC24Q[(CRC>>16)^(rtcm_dec&int('FF',16))],16)
		CRC = p1^p2	
	CRC_hex = hex(CRC)[2:]
	return CRC_hex

#-----------------------------------------------------------------------
#比对校验码,验证计算的校验码与原校验码是否吻合
def CheckCRC(rtcm_data,CRC_hex):
	crc_pass = 1
	if len(CRC_hex) < 6:
		crc_pass = 0
		print('错误!计算的CRC长度小于24位!\n')
	else:
		for i in range(3):
			if int(CRC_hex[2*i:2*(i+1)],16) != int(rtcm_data[-3+i],16):
				crc_pass = 0
						
	if crc_pass == 1:
		print('CRC比对通过!\n')
	else:
		print('CRC比对失败!\n')	
	return crc_pass

#-----------------------------------------------------------------------
if (__name__== "__main__"):
	rtcm_file = 'C:\\Users\\Desktop\\RTK\RtcmData.txt'
	with open(rtcm_file,'r') as f:
		contents = f.readlines()
	k = 0
	for rtcm_data in contents:
		k = k + 1
		print('序号:',k)
		rtcm_data = rtcm_data.replace('\n','')
		CRC_hex = CalculateCRC2(rtcm_data)
		crc_pass = CheckCRC(rtcm_data,CRC_hex)

上面脚本中采用的CRC-24Q码表存于一个文本文件CRC-24Q.txt中,计算时读取该文件。码表具体如下:

000000,864CFB,8AD50D,0C99F6,93E6E1,15AA1A,1933EC,9F7F17,A18139,27CDC2,2B5434,AD18CF,3267D8,B42B23,B8B2D5,3EFE2E,C54E89,430272,4F9B84,C9D77F,56A868,D0E493,DC7D65,5A319E,64CFB0,E2834B,EE1ABD,685646,F72951,7165AA,7DFC5C,FBB0A7,0CD1E9,8A9D12,8604E4,00481F,9F3708,197BF3,15E205,93AEFE,AD50D0,2B1C2B,2785DD,A1C926,3EB631,B8FACA,B4633C,322FC7,C99F60,4FD39B,434A6D,C50696,5A7981,DC357A,D0AC8C,56E077,681E59,EE52A2,E2CB54,6487AF,FBF8B8,7DB443,712DB5,F7614E,19A3D2,9FEF29,9376DF,153A24,8A4533,0C09C8,00903E,86DCC5,B822EB,3E6E10,32F7E6,B4BB1D,2BC40A,AD88F1,A11107,275DFC,DCED5B,5AA1A0,563856,D074AD,4F0BBA,C94741,C5DEB7,43924C,7D6C62,FB2099,F7B96F,71F594,EE8A83,68C678,645F8E,E21375,15723B,933EC0,9FA736,19EBCD,8694DA,00D821,0C41D7,8A0D2C,B4F302,32BFF9,3E260F,B86AF4,2715E3,A15918,ADC0EE,2B8C15,D03CB2,567049,5AE9BF,DCA544,43DA53,C596A8,C90F5E,4F43A5,71BD8B,F7F170,FB6886,7D247D,E25B6A,641791,688E67,EEC29C,3347A4,B50B5F,B992A9,3FDE52,A0A145,26EDBE,2A7448,AC38B3,92C69D,148A66,181390,9E5F6B,01207C,876C87,8BF571,0DB98A,F6092D,7045D6,7CDC20,FA90DB,65EFCC,E3A337,EF3AC1,69763A,578814,D1C4EF,DD5D19,5B11E2,C46EF5,42220E,4EBBF8,C8F703,3F964D,B9DAB6,B54340,330FBB,AC70AC,2A3C57,26A5A1,A0E95A,9E1774,185B8F,14C279,928E82,0DF195,8BBD6E,872498,016863,FAD8C4,7C943F,700DC9,F64132,693E25,EF72DE,E3EB28,65A7D3,5B59FD,DD1506,D18CF0,57C00B,C8BF1C,4EF3E7,426A11,C426EA,2AE476,ACA88D,A0317B,267D80,B90297,3F4E6C,33D79A,B59B61,8B654F,0D29B4,01B042,87FCB9,1883AE,9ECF55,9256A3,141A58,EFAAFF,69E604,657FF2,E33309,7C4C1E,FA00E5,F69913,70D5E8,4E2BC6,C8673D,C4FECB,42B230,DDCD27,5B81DC,57182A,D154D1,26359F,A07964,ACE092,2AAC69,B5D37E,339F85,3F0673,B94A88,87B4A6,01F85D,0D61AB,8B2D50,145247,921EBC,9E874A,18CBB1,E37B16,6537ED,69AE1B,EFE2E0,709DF7,F6D10C,FA48FA,7C0401,42FA2F,C4B6D4,C82F22,4E63D9,D11CCE,575035,5BC9C3,DD8538

提供一帧示例的RTCM数据如下:

d300984320023e714a6200580a5a580000000000202000007fffea08a9a949c9c8c869808de24656bdf654031f20b8d501e0b9ea74d815312e1405881606d37dd85c9439f96b29d8d86928d910d001cd00d26583e0fdee6727a342215ee98603a401ec980d20fec09dfbcea1ebe34fca6e9ea987fb121018e4386a8380adfd03b365fffffffffffffffffe00004ade1bd0fdb2d33d2f63b61752e876ad0e

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是用 C 语言解析包含 1124、1074 和 1084 类型数据计算经纬度信息的示例代码: ```c // 定义 RTCM3.2 数据头结构体 typedef struct { unsigned int length : 10; unsigned int messageType : 12; unsigned int stationID : 6; unsigned int epochTime : 30; } RTCM3_Head_t; // 定义 1124 类型观测值结构体 typedef struct { unsigned int P1 : 24; unsigned int L1 : 20; unsigned int D1 : 7; unsigned int S1 : 5; unsigned int P2 : 24; unsigned int L2 : 20; unsigned int D2 : 7; unsigned int S2 : 5; } RTCM3_1124_Obs_t; // 定义 1074 类型 GPS 卫星星历结构体 typedef struct { unsigned int satID : 6; unsigned int IODE : 8; signed int deltaN : 16; signed int M0 : 32; signed int e : 32; signed int rootA : 32; signed int omega0 : 32; signed int i0 : 32; signed int w : 32; signed int OMEGA : 32; unsigned int week : 10; unsigned int L2CodeFlag : 2; unsigned int L2PFlag : 1; signed int accuracy : 4; unsigned int health : 6; unsigned int L1CodeFlag : 1; unsigned int L1PFlag : 1; unsigned int URA : 6; unsigned int fitInterval : 1; } RTCM3_1074_Eph_t; // 定义 1084 类型 GLONASS 卫星星历结构体 typedef struct { unsigned int satID : 6; unsigned int freqNo : 5; unsigned int health : 1; unsigned int P1 : 24; signed int tauN : 22; signed int gammaN : 11; signed int tk : 17; signed int P2 : 24; signed int P3 : 20; unsigned int corrFlag : 1; unsigned int reserved : 1; } RTCM3_1084_Eph_t; int main() { char buffer[1024]; // 假设 buffer 中存储了 RTCM3.2 数据 int len = 1024; // 假设数据长度为 1024 // 解析 RTCM3.2 数据 int pos = 0; while (pos < len) { RTCM3_Head_t* head = (RTCM3_Head_t*)(buffer + pos); pos += 3; switch (head->messageType) { case 1124: // 解析 1124 类型数据 // 解析数据RTCM3_1124_Obs_t* obs = (RTCM3_1124_Obs_t*)(buffer + pos); pos += 64; // 计算经纬度信息 // TODO: 根据卫星编号和观测值计算经纬度信息 break; case 1074: // 解析 1074 类型数据 // 解析数据RTCM3_1074_Eph_t* eph = (RTCM3_1074_Eph_t*)(buffer + pos); pos += 96; // 计算经纬度信息 // TODO: 根据星历数据计算经纬度信息 break; case 1084: // 解析 1084 类型数据 // 解析数据RTCM3_1084_Eph_t* eph = (RTCM3_1084_Eph_t*)(buffer + pos); pos += 96; // 计算经纬度信息 // TODO: 根据星历数据计算经纬度信息 break; default: // 其他类型数据,跳过 pos += head->length; break; } } return 0; } ``` 需要注意的是,计算经纬度信息需要根据卫星编号、观测值和星历等数据进行计算,这需要一定的专业知识和技能。同时,还需要处理数据精度和精度损失等问题,确保计算结果的准确性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hui_farmer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值