尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

RTK模组调试

RTK模组调试 最近有项目需要用高精度定位模组原来用的普通北斗定位模组换成了高精度RTK模组也是第一次使用现在把调试过程记录下。一、RTK工作原理RTK工作原理⚫将基站放置通过精确测量的位置且无GNSS信号遮挡以确保能够连续接收所有可见的GNSS卫 星信号。⚫基站通过可靠的数据链路网络、无线电等向移动站发送其坐标和修正数据。⚫移动站接收来自基站的数据并同步观测和收集GNSS卫星的载波相位数据。⚫移动站根据从卫星接收到的载波相位数据和从基站接收到的修正数据计算出精确的位置。RTK通常可分为⚫传统RTK差分改正数据的传输链路通常由无线电台来提供且基站和移动站之间的距离一般在 20~30 km 以内。因为其形成的测量偏差与距离有关超过这个距离则会造成移动站的定位精度 大幅度下降。⚫网络RTK通过联合多基站的数据进行误差计算、改正向用户提供空间位置服务的一种实时定 位技术需要通过网络实现系统中心对多基准站的数据共享。网络 RTK技术克服了传统RTK技 术定位精度与距离相关性强、作业时需频繁架设基准站等缺点。传统RTK技术与网络RTK技术在传统RTK技术服务模型中改正数据的传输链路通常由无线电台来提供且基站和移动站之间的距离一般在 30 km以内。由于移动站与基站距离不同这就导致轨道偏差、电离层偏差和对流层偏差会有所 不同。超过这个距离移动站的定位精度将大幅度下降。为了突破这种单基站的传统 RTK技术的局限性网络RTK技术应运而生。网络RTK技术是联合多基 站的数据进行误差计算、改正向用户提供空间位置服务的一种实时定位技术需要通过网络实现系统中 心对多基站数据共享。网络 RTK技术克服了传统RTK技术作业范围小、定位精度与距离相关性强、作业 时需频繁架设基站等缺点。目前网络RTK最常见的方法是VRS虚拟参考站。在这种情况下移动站以标准的NMEA0183 GGA 消息格式将位置发送给网络数据处理中心网络数据处理中心将在移动站附近创建一个 VRS并计算出一 组对应的改正数据然后发送回移动站移动站再计算出高精度位置。网络RTK的特点通常情况网络RTK有如下特点优点1.精度不再受地域限制。随着CORS网络的建设可以在大部分地区获得高精度的定位坐标。2.无需单独部署基站不仅节省了运营成本也在一定程度上提高了工作效率。3.快速实现高精度定位集成服务商提供的SDK可以快速实现秒级的固定收敛。缺点对无线数据网络的覆盖有强依赖。网络RTK需要通过无线数据网络来传输改正数据无网络覆盖的地 区无法使用网络 RTK。通过以上我们知道要使用RTK需要系统能从RTK服务器获得差分修正数据然后传给RTK模组这样就可以到的高精度坐标。二、RTK与NTRIP为了实现RTK的高精度定位效果需要向GNSS移动站连续注入基站的改正数据通常情况下是通过 因特网传输协议为 NTRIP。NTRIP是一个应用进程级协议它支持通过因特网流式传输全球导航卫星系统GNSS数据。NTRIP 是一个基于超文本传输协议HTTP的通用无状态协议。使用NTRIP协议发送GNSS数据流主要包括RTCM 数据格式的数据流和NMEA格式的GGA数据流以及其他格式的GNSS数据流。NTRIP支持通过以下方式上网⚫移动IP网络如GSM、GPRS、EDGE、UMTS、LTE和5G⚫Wi-Fi网络⚫有线IP网络NTRIP系统的组成NTRIP协议目前有两个版本分别为NTRIP v1.0和NTRIP v2.0。主要区别为数据传输格式上v2.0 版本更加严格地遵循了标准 HTTP协议规范详细具体差异可参考RTCM104系列的规范文档。考虑目前实际应用过程中大部分使用的是 v1.0版本的协议因此以下介绍默认参考NTRIP v1.0版本。⚫NtripSource生成特定位置的改正数据流并把此改正数据提交给NtripServer。⚫NtripServer负责把改正数据提交给NtripCaster。⚫NtripCaster数据分发中心负责接收、转发GNSS数据流。⚫NtripClient登录NtripCaster后NtripCaster把特定位置的改正数据发送给它。NtripSource和NtripServer一般已经集成到一台GNSS基站内基站产生当前特定位置的改正数据然后再通过网络发送给 NtripCaster。NtripCaster 一般就是一台服务器它负责接收、转发GNSS数据数据流。通常NtripCaster有两种工 作形式⚫依据不同的挂载点直接将对应的基站的改正数据发送给移动站。⚫先通过算法将多个实际的基站虚拟成一个最为匹配移动站的虚拟参考站VRS。然后将改正数据 发送给移动站。NtripClient一般就是GNSS移动站。移动站登录NtripCaster后发送自身的坐标给NtripCaster。NtripCaster 选择或产生特定位置的改正数据然后发送给NtripClient。这样在GNSS移动站即可实现RTK 的高精度定位。通过以上我知道了系统必须创建一个TCP链接然后在TCP上面建立HTTP客户端登入并发送坐标数据等待服务器返回差分数据。三、RTCM3协议RTK服务器返回的数据是RTCM3协议数据格式是HEX格式。字段比特说明Preamble 前导码8bit固定 0xD3帧起始标志Reserved 保留位6bit默认填 0Message Length 消息长度10bit载荷 Data 字段字节数最大 1023 字节Data 数据载荷N×8bit变长内部第一个 12bit 是消息类型号CRC24Q 校验24bit3 字节校验范围前导码 保留 长度 Data 载荷不包含自身 CRC3 字节整帧总字节 3 字节头 N 字节载荷 3 字节 CRC总帧最小 6 字节最大310233 1029 字节[0xD3][ResvLen(2B)][Data(N字节)][CRC24Q(3B)]Data 载荷内部开头Data 最开始12bit Message Type 消息号例如 1005、1074、1124 等。⚠️TCP 是字节流会粘包、拆包不能按固定长度读取必须写状态机循环扫描 0xD3 同步头取出完整帧做 CRC24Q 校验校验成功才解析失败丢弃。计算法uint32_t rtcm_crc24q(const uint8_t *data, size_t len) { const uint32_t POLY 0x1864CFB; // CRC-24Q 多项式 uint32_t crc 0; size_t i, j; for (i 0; i len; i) { crc ^ ((uint32_t)data[i]) 16; // 字节与CRC高8位异或 for (j 0; j 8; j) { crc 1; // 左移一位 if (crc 0x01000000) { // 检查最高位(第24位) crc ^ POLY; // 异或多项式 } } } return crc 0x00FFFFFF; // 只保留低24位 }查表法const uint32_t wCrc24qTable[] { 0x00000000,0x00864CFB,0x008AD50D,0x000C99F6, 0x0093E6E1,0x0015AA1A,0x001933EC,0x009F7F17, 0x00A18139,0x0027CDC2,0x002B5434,0x00AD18CF, 0x003267D8,0x00B42B23,0x00B8B2D5,0x003EFE2E, 0x00C54E89,0x00430272,0x004F9B84,0x00C9D77F, 0x0056A868,0x00D0E493,0x00DC7D65,0x005A319E, 0x0064CFB0,0x00E2834B,0x00EE1ABD,0x00685646, 0x00F72951,0x007165AA,0x007DFC5C,0x00FBB0A7, 0x000CD1E9,0x008A9D12,0x008604E4,0x0000481F, 0x009F3708,0x00197BF3,0x0015E205,0x0093AEFE, 0x00AD50D0,0x002B1C2B,0x002785DD,0x00A1C926, 0x003EB631,0x00B8FACA,0x00B4633C,0x00322FC7, 0x00C99F60,0x004FD39B,0x00434A6D,0x00C50696, 0x005A7981,0x00DC357A,0x00D0AC8C,0x0056E077, 0x00681E59,0x00EE52A2,0x00E2CB54,0x006487AF, 0x00FBF8B8,0x007DB443,0x00712DB5,0x00F7614E, 0x0019A3D2,0x009FEF29,0x009376DF,0x00153A24, 0x008A4533,0x000C09C8,0x0000903E,0x0086DCC5, 0x00B822EB,0x003E6E10,0x0032F7E6,0x00B4BB1D, 0x002BC40A,0x00AD88F1,0x00A11107,0x00275DFC, 0x00DCED5B,0x005AA1A0,0x00563856,0x00D074AD, 0x004F0BBA,0x00C94741,0x00C5DEB7,0x0043924C, 0x007D6C62,0x00FB2099,0x00F7B96F,0x0071F594, 0x00EE8A83,0x0068C678,0x00645F8E,0x00E21375, 0x0015723B,0x00933EC0,0x009FA736,0x0019EBCD, 0x008694DA,0x0000D821,0x000C41D7,0x008A0D2C, 0x00B4F302,0x0032BFF9,0x003E260F,0x00B86AF4, 0x002715E3,0x00A15918,0x00ADC0EE,0x002B8C15, 0x00D03CB2,0x00567049,0x005AE9BF,0x00DCA544, 0x0043DA53,0x00C596A8,0x00C90F5E,0x004F43A5, 0x0071BD8B,0x00F7F170,0x00FB6886,0x007D247D, 0x00E25B6A,0x00641791,0x00688E67,0x00EEC29C, 0x003347A4,0x00B50B5F,0x00B992A9,0x003FDE52, 0x00A0A145,0x0026EDBE,0x002A7448,0x00AC38B3, 0x0092C69D,0x00148A66,0x00181390,0x009E5F6B, 0x0001207C,0x00876C87,0x008BF571,0x000DB98A, 0x00F6092D,0x007045D6,0x007CDC20,0x00FA90DB, 0x0065EFCC,0x00E3A337,0x00EF3AC1,0x0069763A, 0x00578814,0x00D1C4EF,0x00DD5D19,0x005B11E2, 0x00C46EF5,0x0042220E,0x004EBBF8,0x00C8F703, 0x003F964D,0x00B9DAB6,0x00B54340,0x00330FBB, 0x00AC70AC,0x002A3C57,0x0026A5A1,0x00A0E95A, 0x009E1774,0x00185B8F,0x0014C279,0x00928E82, 0x000DF195,0x008BBD6E,0x00872498,0x00016863, 0x00FAD8C4,0x007C943F,0x00700DC9,0x00F64132, 0x00693E25,0x00EF72DE,0x00E3EB28,0x0065A7D3, 0x005B59FD,0x00DD1506,0x00D18CF0,0x0057C00B, 0x00C8BF1C,0x004EF3E7,0x00426A11,0x00C426EA, 0x002AE476,0x00ACA88D,0x00A0317B,0x00267D80, 0x00B90297,0x003F4E6C,0x0033D79A,0x00B59B61, 0x008B654F,0x000D29B4,0x0001B042,0x0087FCB9, 0x001883AE,0x009ECF55,0x009256A3,0x00141A58, 0x00EFAAFF,0x0069E604,0x00657FF2,0x00E33309, 0x007C4C1E,0x00FA00E5,0x00F69913,0x0070D5E8, 0x004E2BC6,0x00C8673D,0x00C4FECB,0x0042B230, 0x00DDCD27,0x005B81DC,0x0057182A,0x00D154D1, 0x0026359F,0x00A07964,0x00ACE092,0x002AAC69, 0x00B5D37E,0x00339F85,0x003F0673,0x00B94A88, 0x0087B4A6,0x0001F85D,0x000D61AB,0x008B2D50, 0x00145247,0x00921EBC,0x009E874A,0x0018CBB1, 0x00E37B16,0x006537ED,0x0069AE1B,0x00EFE2E0, 0x00709DF7,0x00F6D10C,0x00FA48FA,0x007C0401, 0x0042FA2F,0x00C4B6D4,0x00C82F22,0x004E63D9, 0x00D11CCE,0x00575035,0x005BC9C3,0x00DD8538, }; /** * 查表法核心实现 * * 算法原理: * crc (crc 8) ^ table[((crc 16) ^ data[i]) 0xFF] * * 其中: * - (crc 16): 取出CRC高8位 * - ^ data[i]: 与当前字节异或 * - 0xFF: 取低8位作为表索引 * - table[index]: 预计算好的CRC增量 * - crc 8: CRC左移8位 * - ^ table[index]: 异或增量 */ uint32_t rtcm_crc24q_table(const uint8_t *data, size_t len) { // 确保表已初始化 // if (!table_initialized) { // rtcm_crc24q_init_table(); // } uint32_t crc 0; for (size_t i 0; i len; i) { uint8_t index (uint8_t)(((crc 16) ^ data[i]) 0xFF); crc (crc 8) ^ wCrc24qTable[index]; crc 0x00FFFFFF; // 保持24位 } return crc; }四、嵌入式开发流程RTK服务器可以选用千寻位置、中移定位、六分科技等需要花钱购买账号。这里以千寻位置为例其他类似。IP网址和端口号rtk.ntrip.qxwz.com:8003这里选择8003挂载点有两个AUTO五星十六频RTCM32_GGB三星八频)这里选择AUTO千寻位置账号使用有两种方式SDK和差分账号。SDK需要提供编译信息向官方申请这里选用差分账号。HTTP链接登入格式GET /{MountPoint} HTTP/1.0User-Agent: NTRIP ClientName/VersionAuthorization: Basic {Base64EncodedCredentials}Ntrip-Version: Ntrip/2.0Connection: closeNtrip-GGA: {GPGGA_Sentence} // 可选用于发送移动端位置字段 说明MountPoint 挂载点名称如RTCM32_GGB标识特定数据流User-Agent 客户端标识需符合NTRIP规范如NTRIP RTKLIB/1.0Authorization Basic认证格式Basic base64(user:password)Ntrip-Version 协议版本声明v2.0必须包含此头Ntrip-GGA 可选的NMEA GGA语句用于向服务器报告客户端位置认证格式为user:password然后用 base64格式化static const char base64_table[] ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/; // **Base64 编码实现** uint16_t base64_encode(unsigned char* pchOutput, uint16_t hwOutputBufferSize,const unsigned char* c_pchInput, uint16_t hwInputLen) { uint16_t output_len 4 * ((hwInputLen 2) / 3); // 计算输出长度 //char* output (char*)malloc(output_len 1); // 为输出分配内存 if(NULL pchOutput || !hwOutputBufferSize || NULL c_pchInput || !hwInputLen){ return 0; } if(output_len1 hwOutputBufferSize){ return 0; } //if (!pchOutput) return 0; // 内存分配失败 uint16_t i, j; for (i 0, j 0; i hwInputLen;) { uint32_t octet_a i hwInputLen ? c_pchInput[i] : 0; uint32_t octet_b i hwInputLen ? c_pchInput[i] : 0; uint32_t octet_c i hwInputLen ? c_pchInput[i] : 0; uint32_t combined (octet_a 16) | (octet_b 8) | octet_c; pchOutput[j] base64_table[(combined 18) 0x3F]; pchOutput[j] base64_table[(combined 12) 0x3F]; pchOutput[j] i hwInputLen 1 ? : base64_table[(combined 6) 0x3F]; pchOutput[j] i hwInputLen ? : base64_table[combined 0x3F]; } pchOutput[output_len] \0; // 添加 NULL 终止符 return output_len; } // **Base64 解码实现** uint16_t base64_decode(unsigned char* pchOutput,uint16_t hwOutputBufferSize,const char* c_pcInput) { uint16_t hwOutputLen 0; uint16_t hwInputLen 0; if(NULL pchOutput || !hwOutputBufferSize || NULL c_pcInput){ return 0; } hwInputLen strlen(c_pcInput); if (hwInputLen % 4 ! 0) return 0; // 输入长度必须是4的倍数 hwOutputLen hwInputLen / 4 * 3; if (c_pcInput[hwInputLen - 1] ) (hwOutputLen)--; if (c_pcInput[hwInputLen - 2] ) (hwOutputLen)--; if(hwOutputLen 1 hwOutputBufferSize){ return 0; } //unsigned char* output (unsigned char*)malloc(*output_len 1); // 分配额外空间以存储 NULL 终止符 //if (!pchOutput) return 0; size_t i, j; for (i 0, j 0; i hwInputLen;) { int sextet_a c_pcInput[i] ? 0 : strchr(base64_table, c_pcInput[i]) - base64_table; int sextet_b c_pcInput[i] ? 0 : strchr(base64_table, c_pcInput[i]) - base64_table; int sextet_c c_pcInput[i] ? 0 : strchr(base64_table, c_pcInput[i]) - base64_table; int sextet_d c_pcInput[i] ? 0 : strchr(base64_table, c_pcInput[i]) - base64_table; uint32_t combined (sextet_a 18) | (sextet_b 12) | (sextet_c 6) | sextet_d; if (j hwOutputLen) pchOutput[j] (combined 16) 0xFF; if (j hwOutputLen) pchOutput[j] (combined 8) 0xFF; if (j hwOutputLen) pchOutput[j] combined 0xFF; } pchOutput[hwOutputLen] \0; // 添加 NULL 终止符 return hwOutputLen; }登入流程如下1、获取RTK模组的GGA信息如$GNGGA,071516.000,3149.301159,N,11706.919870,E,1,16,0.95,70.2,M,-0.3,M,,*592、设备登入RTK服务器1TCP登入rtk.ntrip.qxwz.com:80032发送HTTP登入帧返回ICY 200 OK说明登入成功。注意发送帧后面要跟两个回车换行符3设备直接发送GGA信息给RTK服务器得到差分数据转发给RTK模组即可。$GNGGA,071516.000,3149.301159,N,11706.919870,E,1,16,0.95,70.2,M,-0.3,M,,*59\r\n\r\n注意发送帧后面要跟两个回车换行符4等到二进制RTCM3数据。5RTK模组成功后2026.08.25今天测试RTK模组用官方提供的软件可以成功用自己搭建的测试环境始终不行。分析原因是自己搭建的环境只是把RTK服务器的一帧数据返回给了模组应该是把模组没秒的GGA数据给RTK服务器然后把服务器每秒返回的数据给模组让模组不停地修正这样才能进入RTK模组。
返回列表