ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RTKLIB中RTK定位原理:从载波相位到整周模糊度固定

RTKLIB中RTK定位原理:从载波相位到整周模糊度固定 做GNSS的人电脑里几乎都有一份RTKLIB源码。不管你是做测绘、无人机、自动驾驶还是刚入门的在校生只要跟高精度定位打交道迟早会撞上这个开源工具。而RTK定位原理又是绕不开的第一道坎。我在实际项目里见过太多这种场面RTKLIB编译好了RTKNAVI也能跑但一看结果——固定率不到百分之三十或者干脆一直浮点解。问起来大家都说是“环境不好”“卫星太少”其实很多时候是在原理层面就没想清楚参数怎么调都是瞎试。所以这个系列我打算把RTKLIB里RTK定位的完整原理拆开讲从观测方程、差分模型、模糊度固定到代码流程一点点对应起来。这一篇先解决最核心的问题RTK在解什么RTKLIB又是怎样把“载波相位”变成“厘米级坐标”的这个系列适合两类人一类是想把RTKLIB真正用明白的工程人员另一类是准备啃源码、做二次开发的研究者。我会尽量用大白话把数学和代码串起来该给的公式给公式该指的源码指源码。1. RTK定位要解决什么问题1.1 从伪距到载波相位的精度跃迁GNSS定位的本质就是测距。卫星一直在广播导航信号接收机通过测量信号从卫星到自己的传播时间乘以光速就得到距离。这个距离叫“伪距”因为里面混了一堆误差卫星钟差、接收机钟差、电离层延迟、对流层延迟、多路径、轨道误差等等。普通单点定位用的就是伪距。GPS L1频段的C/A码码元宽度约293米接收机能把码相位跟踪到1%个码元左右所以单频伪距的噪声通常有零点几米到几米。这就是为什么手机定位精度只能到米级。再努力伪距的天花板就在那里。但载波相位不一样。L1载波的波长只有19.03厘米接收机对相位测定的噪声可以做到0.01周对应大约2毫米的测距精度。这个精度听起来非常诱人问题是接收机只能测到“相位的小数部分”以及从锁定开始的“整周变化量”却不知道信号从卫星出发时到底经历了多少个完整波长这个未知的整数就是整周模糊度。不知道它相位观测值就不能直接当距离用。RTK要解决的就是把这个整周模糊度解出来让载波相位真正变成高精度测距值。这是整个技术的核心矛盾后面所有数学模型、滤波策略、代码逻辑都在围绕这一件事转。1.2 RTK为何必须用差分有人可能会问既然相位测距精度这么高为什么不搞单点的载波相位定位问题出在误差上。卫星钟差可以达到毫秒级对应几百公里的测距误差虽然广播星历里有钟差参数能修正大部分但残差依然有米级。轨道误差同样有米级甚至更大。再加上电离层在L1上白天可以有几十米的延迟对流层也有几米到十几米。这些误差叠加起来单点载波相位的“绝对距离”完全被淹没了模糊度根本无从解起。RTK的思路是“差分”。如果两个接收机距离很近比如几公里以内它们看到同一颗卫星时卫星钟差、轨道误差、电离层延迟、对流层延迟这些量高度相关几乎是相同的。于是一台接收机架在已知坐标的基准站上另一台作为流动站两台同时观测同一组卫星把观测值相减这些共同误差就能被消除或者大幅削弱。基准站把观测数据通过电台、网络或者NTRIP服务实时发给流动站流动站结合自身观测值实时解算这就是“实时动态”Real-Time Kinematic的来源。差分把未知误差变成了已知的公共项剩下的主要未知量就是流动站位置和整周模糊度问题一下子从“在一堆误差里找距离”变成了“在干净的观测值里解整数”这是RTK能够达到厘米级的根本原因。1.3 RTKLIB在整个问题里的定位RTKLIB是日本学者高须知开发的一套开源GNSS处理工具从2006年发布至今已经成为高精度定位领域事实上的参考实现。它支持GPS、GLONASS、Galileo、BDS、QZSS等多个系统能处理单频、双频、三频数据既支持实时RTK也支持后处理PPK还能做PPP。它不是一个黑盒子。源码里从RINEX解析、卫星位置计算、观测方程构建、卡尔曼滤波到模糊度固定每一步都是开放可读的。这意味着你不光可以用它做定位还可以通过它理解整个RTK技术栈。RTKLIB里的核心入口是rtkpos()函数高层界面比如RTKNAVI、RTKPOST最终都会调用它完成逐历元定位解算。对刚接触RTK的人来说把RTKLIB当计算器用是不够的因为同样的配置换了环境可能结果就完全不同。追到原理层面你才能理解为什么卫星高度角阈值要设15度、为什么Ratio阈值设3、为什么动态模式下初始化更慢。接下来的章节我按RTKLIB实际解算的顺序先讲观测方程再讲差分模型然后是模糊度固定最后对照代码流程。2. 打开RTKLIB前先理解观测方程2.1 伪距观测方程与符号约定RTKLIB里所有解算都是围绕观测方程展开的。伪距观测值P可以写成P ρ c·(dt_r - dt^s) I T ε其中ρ是卫星到接收机的几何距离dt_r是接收机钟差dt^s是卫星钟差I是电离层延迟T是对流层延迟ε是测量噪声和其它未模型化误差。这个方程看起来简单但用的时候有几个点容易混。首先是符号伪距上的电离层延迟是“额外多出来的距离”所以是加号载波相位上电离层会改变相速导致信号传播距离看起来变短所以是负号。同一个电离层误差在伪距和相位里符号相反跑RTKLIB的时候看到残差符号异常十有八九是这个没理清。另外RTKLIB内部做各种改正时单位统一为米钟差统一乘以光速c换算成距离。所有频率相关的量都要指定频点比如GPS L1对应C1/P1码和L1相位L2对应P2码和L2相位。不同接收机输出的伪距观测量可能是C1也可能是P1二者存在码偏差RTKLIB里有一套优先级选择逻辑处理RINEX和RTCM时会有体现。为了方便对照常用符号整理如下表符号含义单位P伪距观测值米Φ载波相位观测值含模糊度项米ρ卫星到接收机的几何距离米dt_r接收机钟差秒dt^s卫星钟差秒I电离层延迟米T对流层延迟米λ载波波长米N整周模糊度周ε噪声与未模型化误差米2.2 载波相位观测方程和整周模糊度载波相位观测值可以写成Φ ρ c·(dt_r - dt^s) - I T λ·N ε注意这里Φ、I、T都以米为单位λ·N是整周模糊度对应的距离N是整数。为什么必须是整数因为载波是一个周期性信号接收机锁定后能精确跟踪相位变化但无法知道从卫星发射到接收之间到底过去了多少个整周。这个“过去多少个整周”只能是整数不会出现半周的情况。整周模糊度N一旦确定相位观测值就变成极高精度的距离测量值。RTK所有算法的目标就是把N这个整数求出来。难点在于N和接收机钟差、位置等参数混在一起而且伪距噪声大、相位观测里又有各种残差直接解整数很难。所以工程上一般先把N当作浮点数估计得到“浮点解”再用整数搜索手段把N固定成整数得到“固定解”。实际使用中还有个烦恼叫周跳。接收机锁定卫星后如果信号被遮挡或受到强多路径干扰相位整周计数会突然跳变等效于模糊度N发生了变化。周跳不处理模糊度固定就是空中楼阁。RTKLIB里专门有周跳检测逻辑这个后面讲到滤波会涉及。2.3 RTKLIB中的观测数据组织理解原理之后再回头翻RTKLIB源码会轻松很多。RTKLIB内部用一个观测结构体来存每个历元的所有卫星观测值主要字段是L[]和P[]分别存载波相位和伪距数组下标对应不同频率。比如L1存在L[0]L2存在L[1]L5存在L[2]频率数和系统有关。这个设计有个容易踩的坑不同系统、不同频点的观测值放在同一个数组里代码里必须同时知道卫星系统、PRN和频率索引才能取对数据。RTKLIB用satsys()判断卫星所属系统用satno()解析卫星编号处理多系统数据时这套编号逻辑非常重要。观测值是否有效可以通过L[]和P[]是否为0或者是否超出范围来判断RTKLIB里还有专门的观测值检核函数。调试的时候我建议把原始观测值先画出来看一遍卫星高度角曲线、伪距残差、相位连续性是否正常比直接上滤波调参会少走很多弯路。3. 差分组合双差模型的推导思路3.1 单差先消除卫星端误差RTK的第一步差分是“站间单差”也就是用流动站的观测值减去基准站对同一颗卫星的观测值。以载波相位为例Φ_u^s - Φ_b^s (ρ_u^s - ρ_b^s) c·(dt_u - dt_b) 大气残余 λ·(N_u^s - N_b^s) 噪声单差之后卫星钟差直接消掉了轨道误差也几乎完全消除。短基线情况下电离层和对流层误差在上式中被大幅削弱残余量随基线变长而增大。接收机钟差仍然存在变成了两个接收机钟差之差这是一个未知数。单差模糊度N_u^s - N_b^s虽然还是整数但它受到两台接收机各自的整周模糊度影响。双差的目的就是进一步把接收机钟差消掉让模糊度变成更干净的形式。3.2 双差消除接收机钟差在单差基础上再选一颗参考卫星k用卫星s的单差结果减去卫星k的单差结果得到双差观测值。这个操作叫“星间差分”得到的观测模型为DD Δρ ΔT ΔI λ·ΔN 噪声其中关键之处在于双差模糊度ΔN N_u^s - N_b^s - N_u^k N_b^k 依然是整数而接收机钟差被彻底消除。这个性质是RTK能够可靠固定模糊度的基石。双差模型并非没有代价。站间单差已经把噪声放大了√2倍再星间差分噪声继续放大总体的噪声水平约为原始观测值的2倍。但换来的是模型里只剩位置、残余大气和整数模糊度未知参数大幅减少。以GPS单系统为例如果共视卫星是8颗选一颗作参考星双差模糊度数量就是7个再加3个位置参数状态量非常紧凑。RTKLIB在构建双差观测矩阵时通常选高度角最高的卫星作参考星因为高度角高的卫星大气残余小、多路径弱这样整体解算质量最好。3.3 三差、GF组合和MW组合的用途除了双差还有几种常用组合需要了解。三差就是在双差基础上再做一次历元间差分可以彻底消掉模糊度但观测噪声进一步放大所以三差很少直接用于定位主要用来做周跳探测。RTKLIB检测到相位发生跳变后会把对应卫星的模糊度参数重置避免污染后续滤波。几何无关组合GF用两个频率的相位相减表达式为Φ1 - Φ2它与几何距离无关只与电离层和模糊度有关。由于几何项被消掉GF组合的变化量能非常灵敏地反映周跳是双频接收机周跳检测的标配。MW组合则结合了宽巷相位和窄巷伪距它消掉了几何距离、钟差和大部分电离层影响剩下的主要是宽巷模糊度。RTKLIB常用MW组合来估计宽巷模糊度为后续的模糊度固定提供初值或验证。这三个组合在RTKLIB源码里都有对应的实现函数理解它们之后再去看周跳检测、模糊度固定逻辑会清晰得多。3.4 RTKLIB中的差分实现与参数设置在RTKLIB里做差分解算的核心函数是relpos()它负责从共视卫星中选取参考星、构建双差观测方程、调用卡尔曼滤波、再执行模糊度固定。RTKNAVI或RTKPOST的配置界面上有几个参数直接决定差分质量。基线长度是第一个需要关注的参数。基线越短双差后大气残余越小模糊度固定越容易。RTKLIB默认把基线当作未知向量估计但如果你在配置里把基线设成了“固定”且知道精确值那解算会简化很多不过一般场景不这么用。电离层和对流层改正策略要跟基线配套。短基线双差后大气残余小通常电离层选“关闭”或“广播改正”对流层选“Saastamoinen模型”或“关闭”残余误差交给滤波吸收。长基线或低高度角卫星较多时就需要把对流层天顶延迟作为未知参数估计否则高程方向容易出现系统性偏差。4. 模糊度估计与固定从浮点解到固定解4.1 卡尔曼滤波估计浮点模糊度双差方程建立后RTKLIB使用扩展卡尔曼滤波来估计未知参数。最典型的状态向量包括三维位置、接收机钟差、天顶对流层湿延迟以及所有卫星的双差模糊度。滤波每一历元做两步预测和更新。预测阶段用状态转移模型推算当前历元的先验状态比如静态模式下位置不变、动态模式下按随机游走或常速度模型传递更新阶段则用当前历元的伪距和相位观测值修正状态。滤波的好处是能把历史历元的信息累积起来模糊度参数随着时间收敛得越来越准。浮点模糊度就是滤波在固定之前给出的实数估计。虽然N理论上应该是整数但在噪声和残余误差影响下滤波给出的浮点值可能是7.8周、8.2周这样的数。如果直接把浮点模糊度代回去定位那定位结果就是浮点解精度通常只有分米级到几十厘米。想要厘米级必须把模糊度固定成整数。卡尔曼滤波的参数调起来很微妙。RTKLIB里过程噪声设置得过大离谱的模糊度估计跳来跳去固定率很受影响。设置得过小滤波响应太慢初始化时间会拉长。实际调试时我一般先确认观测数据质量再动滤波参数否则很容易陷入“调参游戏”。4.2 LAMBDA方法与RTKLIB中的实现得到浮点模糊度向量和对应的协方差矩阵后接下来就是整数搜索。RTKLIB里用的是LAMBDA方法全称Least-squares AMBiguity Decorrelation Adjustment最小二乘模糊度降相关平差。LAMBDA的核心思路分两步。第一步是降相关浮点模糊度之间的相关性往往很高直接搜整数效率很低通过一个整数变换Z把模糊度空间旋转、缩放使新的模糊度向量相关性变弱、搜索范围更规则。第二步是在变换后的空间里搜索候选整数组合搜完再变回原始模糊度空间。RTKLIB里对应的函数是lambda()它接收浮点模糊度、协方差阵、搜索候选数等参数返回排序后的整数候选和残差平方和。这个函数短小但非常经典很多人二次开发时都会直接复用。理解LAMBDA不一定非要推导全部矩阵理论但要记住一个关键点搜索质量完全取决于浮点模糊度协方差的准确性伪距噪声大、大气残余多、滤波不收敛都会导致协方差失真搜索出的整数候选自然不可靠。4.3 Ratio检验和固定策略整数搜索会得到一组候选解最优解和次优解之间可能非常接近。如果次优解和最优解的残差平方和之比很小说明两个候选说明不了问题固定很容易出错。这时需要用Ratio检验来判断整组候选的可信度。RTKLIB中的Ratio阈值默认是3.0意思是次优解残差平方和至少是最优解的3倍才认为最优解显著优于次优解可以固定。阈值调高了固定更保守固定率会下降调低了固定率高但错误固定的风险上升。实际基线条件良好时Ratio经常能达到几十甚至上百如果Ratio长期在2以下徘徊通常说明观测数据有问题这时候再去调阈值意义不大。RTKLIB的AR模式里有off、continuous、instantaneous和fix-and-hold四种可选。continuous模式保留已经固定的模糊度信息适合大部分动态场景instantaneous模式每个历元都重新搜索适合频繁遮挡或短时观测的场景但对单频多径严重的情况不友好fix-and-hold在固定成功后把模糊度当作约束锁定能提高后续历元的位置稳定性但一旦锁定错误会导致解偏向错误方向需要慎用。4.4 固定失败时的降级处理模糊度固定不是每次都成功这很正常。固定失败时RTKLIB会退回浮点解输出这时候定位精度降到分米级甚至更低但总比没有输出强。很多RTK应用里把固定率和浮点解的比例作为质量指标固定率低就说明场景或配置不达标。更隐蔽的问题是错误固定。有时候Ratio刚好过阈但模糊度固定值实际上是错的位置解会出现一个固定偏差而且历元之间看起来挺稳定不容易发现。RTKLIB里fix-and-hold模式风险就在这。实际做测量任务时遇到可疑解最好用后处理软件做二次确认或者让流动站重新初始化不要盲目相信固定标志。另外现在多系统GNSS普及后不同系统之间的系统间偏差ISB会破坏双差模糊度的整数性RTKLIB在多系统融合时会单独估计系统间偏差参数新一代Demo5版本在这块的策略更完整这个内容放到后面系列里细讲。5. 把原理对应到RTKLIB代码流程5.1 RTKLIB整体模块划分RTKLIB源码结构并不复杂核心库在src目录下几个关键文件值得重点看。rtkpos.c是RTK解算入口包含rtkpos()、relpos()、udstate()、ddres()等核心函数rtkcmn.c是通用工具函数负责卫星星历计算、坐标转换、时间处理等lambda.c是LAMBDA模糊度固定实现ephemeris.c处理广播星历和精密星历rcvraw.c和rinex.c负责接收机原始数据和RINEX文件解析。如果你只是想用RTKLIB定位不一定需要读懂每一个文件。但rtkpos()和relpos()这两个函数几乎是理解全部原理的关键建议精读。rtkpos()负责逐历元调度relpos()负责相对定位核心处理包括观测值选择、双差方程构建、滤波更新、模糊度固定和结果输出。5.2 rtkpos()与relpos()的主流程RTKLIB的定位主流程可以简化成下面这段伪代码rtkpos(rtk, obs, nav, opt) { // 1. 单点定位获得初始位置和接收机钟差 pntpos(obs, nav, opt, sol); // 2. 如果是RTK模式进入相对定位 if (opt-mode PMODE_KINEMA || PMODE_STATIC) { relpos(rtk, obs, nav, opt, sol); } }relpos()里做的事情更多大致包括relpos(rtk, obs, nav, opt, sol) { // 1. 选取共视卫星确定参考星 selsat(); // 2. 构建双差观测值 ddres(); // 3. 卡尔曼滤波时间更新和观测更新 udstate(); // 4. LAMBDA模糊度固定 raim_fde(); // 5. 输出固定解或浮点解 }读源码的时候我建议先把ddres()函数啃下来因为它把双差观测方程、设计矩阵、观测残差全部集中在一个函数里信息量最大。理解了ddres()里H矩阵和v向量的构造就能直观感受到前面讲的数学模型是如何变成代码的。5.3 关键配置项定位模式、频率、大气改正RTKLIB的配置项多达上百个但真正决定成败的只有一小批。定位模式分为单点、DGPS、静态RTK、动态RTK、PPP等频率选择决定了用几个频段的数据双频一定比单频更容易固定系统选择决定是否启用GLO、Galileo、BDS等多系统融合能显著增加共视卫星数。大气改正设置要根据基线和场景动态调整。短基线RTK通常不需要估计电离层但长基线或单频RTK就需要考虑电离层约束。对流层改正RTKLIB可以在“关”、“Saastamoinen模型”和“估计天顶延迟”之间选择动态测量时如果高程变化剧烈建议把对流层估计打开。我整理了几个高频配置项的影响表格方便大家对照配置项常规推荐说明定位模式动态或静态RTK静置测量用静态RTK移动测量用动态RTK频率L1L2或L1L2L5双频起步三频对固定率提升明显截止高度角10-15度太低引入多路径和大气噪声太高丢卫星电离层改正关或广播模型短基线可关长基线建议模型或估计对流层改正Saastamoinen基线长或高差大时建议加估计参数AR模式continuous遮挡严重可换instantaneousRatio阈值3.0高精度测量可调高动态灵敏度场景可调低5.4 多系统融合与新版差异RTKLIB 2.4.3之后社区维护的Demo5分支增加了大量多系统、多频点支持模糊度固定策略也更丰富比如部分模糊度固定。这部分功能对BDS三频、Galileo多频用户非常友好实际固定率提升明显。但原理层面多系统融合并非简单把卫星加进去就行。不同系统的时间基准、坐标框架、信号频点不同RTKLIB需要在滤波状态里额外引入系统间偏差参数否则模糊度的整数性会被破坏。这也是为什么同一份数据单GPS固定得好好的开启多系统反而可能出现奇怪的浮点解。如果你做工程应用我建议先用单GPS或单BDS把流程跑通确认观测数据和环境没问题再逐步增加系统。别一上来就“全系统全频率”出问题你都分不清是数据问题还是配置问题。6. 实测常见问题与排查技巧6.1 固定率上不去的常见原因固定率低是RTK应用里最常被问的问题我把它常见原因和排查方向整理成了表格现象可能原因排查动作一直浮点解AR模式被设为off检查配置里的AR Mode固定率低且卫星数少截止角太高或多系统没开降低截止角开启BDS/GAL固定率随环境变化大多路径严重、信号遮挡挪天线、提高截止角、换观测环境固定后频繁失锁周跳严重、流动性遮挡检查trace里的周跳标志固定解有明显偏差基准站坐标不准核对基准站已知坐标长时间不固定Ratio阈值过高临时调低阈值观察Ratio走势排查时我习惯按“数据先于参数”的顺序来先看天空可见卫星图再看伪距和相位残差最后才改配置。很多固定率问题其实从卫星星空图就能看出端倪。6.2 初始化时间偏长的排查初始化时间是指从开始解算到第一次固定所用的时间。RTKLIB里初始化偏长的原因主要有四个一是可见卫星数少模糊度解算条件不足二是观测噪声大滤波收敛慢三是Ratio阈值设得太高四是动态模型设置过激进导致位置先验不稳定。解决办法也相应明确。如果卫星少优先开启多系统如果噪声大检查天线位置和基准站数据质量如果滤波收敛慢可以适当调整观测噪声方差如果周围环境遮挡严重考虑用instantaneous模式试一试它不依赖历史模糊度累积。实际项目中我还会关注“首次固定时间”这个指标它比固定率更能反映系统启动阶段的性能。6.3 坐标系和精度评估的那些坑RTK解算结果默认在ECEF坐标系下输出时通常转成经纬度和椭球高。很多人把椭球高直接当海拔用这是不对的。椭球高和正高之间差一个大地水准面差距不同地区可能差几十米实际工程中要加高程转换。基准站坐标不准确是最容易被忽略的系统性误差。基准站坐标偏差会以常差的形式进入所有解算结果RTKLIB虽然能通过滤波估计部分偏差但如果基准站坐标差了几米固定解的平面位置还是会差出不少。架设基准站时一定要用已知控制点或长时间静态单点平差结果不能把单点定位的瞬时值当基准站坐标。评估定位精度也不能光看固定状态。固定解之间依然有厘米级噪声要统计ENU三个方向的标准差才有意义。水平精度和垂直精度差别很大垂直方向一般要差1.5到2倍这取决于卫星几何和大气残余是正常现象。6.4 一个提高排查效率的小技巧我调试RTKLIB时有个习惯正式跑数据前先把trace日志等级打开输出滤波残差和Ratio序列然后结合RTKPLOT看时间序列。很多问题从Ratio曲线的形态能直接判断——如果Ratio间歇性跳到阈值上下说明观测值质量在波动如果Ratio很低但很平稳说明系统误差或模型问题如果Ratio经常突然跳变大概率是周跳或钟跳。RTKPLOT里还有一个容易被忽视的功能就是查看浮点解和固定解的轨迹差异。固定解和浮点解如果偏离明显说明模糊度固定对结果影响很大这时候要关注模糊度是否正确。如果二者几乎重合说明当前场景即使不固定模糊度定位精度也还可以固定失败的影响不会太致命。最后再分享一个我自己的经验调RTK别贪多一次只改一个变量。先固定一个干净的观测环境把单频、单系统的流程跑明白再逐步加频率、加系统、加复杂场景。这样即使出了问题你也知道是哪个环节引入的。RTKLIB这套代码足够透明只要原理清楚任何怪异现象都能顺着观测方程和滤波流程一步步追到根上。这个系列下一篇我准备深入rtkpos()和relpos()的源码把双差矩阵、滤波更新和模糊度固定逐行对应起来。
返回列表