本文解析了RTKlib ppp.c中两个周跳检测函数detslp_mw和detslp_gf,以及rtkpos.c中的detslp_ll和detslp_dop函数。

由于PPP中的detslp_ll直接根据LLI进行周跳判断,比较简单,根据Rinex中对LLI的定义即可明白,因此不进行解析。

rtkpos.c中的周跳检测函数包括detslp_ll、detslp_gf_L1L2、detslp_gf_L1L5、detslp_dop,其中detslp_gf_L1L2、detslp_gf_L1L5与PPP中的detslp_gf相似,只不过这里使用的是双差后的载波相位。由于rtkpost中的detslp_ll比PPP中稍微复杂一些,因此对detslp_ll和detslp_dop进行了解析。

我所基于的代码版本是RTKlib 2.4.3的一个拓展版本RTKexplore Demo5,这个版本主要针对低成本的GNSS定位。该版本整体算法并未做较大更改,只是针对低成本接收机进行了完善。

文章目录

  • detslp_mw
  • detslp_gf
  • detslp_ll
  • detslp_dop

detslp_mw

static void detslp_mw(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav)
  • 所在文件:ppp.c
  • 功能说明:通过MW组合检测周跳
  • 参数说明
* args   : rtk_t  *rtk       IO  gps solution structure
*          obsd_t *obs       I   satellite observations
*          int     n         I   number of the user(rover) observations at current epoch
*          nav_t  *nav       I   satellite navigation data
/* detect slip by Melbourne-Wubbena linear combination jump ------------------*/
static void detslp_mw(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav)
{double w0,w1;int i,j;trace(4,"detslp_mw: n=%d\n",n);for (i=0;i<n&&i<MAXOBS;i++) {if ((w1=mwmeas(obs+i,nav))==0.0) continue;w0=rtk->ssat[obs[i].sat-1].mw;rtk->ssat[obs[i].sat-1].mw=w1;trace(4,"detslip_mw: sat=%2d mw0=%8.3f mw1=%8.3f\n",obs[i].sat,w0,w1);if (w0!=0.0&&fabs(w1-w0)>THRES_MW_JUMP) {trace(3,"detslip_mw: slip detected sat=%2d mw=%8.3f->%8.3f\n",obs[i].sat,w0,w1);for (j=0;j<rtk->opt.nf;j++) rtk->ssat[obs[i].sat-1].slip[j]|=1;}}
}
  • 处理过程
  1. 先调用mwmeas函数计算Melbourne-Wubbena组合值MW=λ1λ2λ2−λ1(ϕ1−ϕ2)−λ2P1+λ1P2λ2+λ1MW = \frac{\lambda_1\lambda_2}{\lambda_2 - \lambda_1} (\phi_1 - \phi_2)-\frac{\lambda_2 P_1+\lambda_1P_2}{\lambda_2 + \lambda_1}MW=λ2​−λ1​λ1​λ2​​(ϕ1​−ϕ2​)−λ2​+λ1​λ2​P1​+λ1​P2​​,其中ϕ1\phi_1ϕ1​、ϕ2\phi_2ϕ2​分别为L1,L2的载波相位测量值(单位:周),P1P_1P1​、P2P_2P2​为伪距测量值(单位:m);
  2. 将当前历元的MW组合值与上一次的组合值进行比较,如果差值的绝对值大于了阈值THRES_MW_JUMP(默认值10.0),则认为有周跳。
  • 注意事项
  1. MWMWMW组合本质上是计算λwNw\lambda_wN_wλw​Nw​,其中λw=cf1−f2\lambda_w=\frac{c}{f1-f2}λw​=f1−f2c​为宽巷组合的波长,Nw=N1−N2N_w = N_1-N_2Nw​=N1​−N2​是宽巷组合的整周模糊度。可想而知,如果没有周跳发生,那么上一历元和当前历元的λwNw\lambda_wN_wλw​Nw​应该是一致的。
  2. MWMWMW组合的推导可以参考《GPS测量与数据处理》书中4.3.3节“不同类型观测值线性组合”一节。从MW组合的推导中可以看出该组合消除了电离层延迟误差、卫星、接收机钟差、卫星至接收机的几何距离。该组合虽有较高的检测精度,但是如果L1,L2同时发生相同大小的周跳,则不能成功检测。
  3. MWMWMW组合的噪声水平可根据其表达式进行推导,结果如下:
    σMW=[(f1f1−f2)2+(f2f1−f2)2]σL2+[(f1f1+f2)2+(f2f1+f2)2]σp2\sigma_{MW} = \sqrt{[(\frac{f_1}{f_1-f_2})^2+(\frac{f_2}{f_1-f_2})^2]\sigma_L^2+[(\frac{f_1}{f_1+f_2})^2+(\frac{f_2}{f_1+f_2})^2]\sigma_p^2}σMW​=[(f1​−f2​f1​​)2+(f1​−f2​f2​​)2]σL2​+[(f1​+f2​f1​​)2+(f1​+f2​f2​​)2]σp2​​
    由于载波相位的噪声水平远低于伪距,因此:
    σMW≈[(f1f1+f2)2+(f2f1+f2)2]σp2\sigma_{MW}\approx\sqrt{[(\frac{f_1}{f_1+f_2})^2+(\frac{f_2}{f_1+f_2})^2]\sigma_p^2} σMW​≈[(f1​+f2​f1​​)2+(f1​+f2​f2​​)2]σp2​​
    上式进一步近似,则:σMW2≈12σp2\sigma_{MW}^2\approx\frac{1}{2}\sigma_p^2σMW2​≈21​σp2​
  4. MWMWMW组合周跳检测的阈值设定,可以根据3中的噪声水平,结合接收机的噪声大小,进行设定;也可采用滑动窗口计算平均值和标准差的方法。RTKlib中使用固定值10,另外开源代码GAMP中也有根据采样间隔、高度角进行阈值设定的方法,感兴趣可以进一步参考其论文和开源代码。

detslp_gf

static void detslp_gf(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav)
  • 所在文件:ppp.c
  • 功能说明:通过GF(几何无关)组合检测周跳
  • 参数说明
* args   : rtk_t  *rtk       IO  gps solution structure
*          obsd_t *obs       I   satellite observations
*          int     n         I   number of the user(rover) observations at current epoch
*          nav_t  *nav       I   satellite navigation data
/* detect cycle slip by geometry free phase jump -----------------------------*/
static void detslp_gf(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav)
{`在这里插入代码片`double g0,g1;int i,j;trace(4,"detslp_gf: n=%d\n",n);for (i=0;i<n&&i<MAXOBS;i++) {if ((g1=gfmeas(obs+i,nav))==0.0) continue;g0=rtk->ssat[obs[i].sat-1].gf;rtk->ssat[obs[i].sat-1].gf=g1;trace(4,"detslip_gf: sat=%2d gf0=%8.3f gf1=%8.3f\n",obs[i].sat,g0,g1);if (g0!=0.0&&fabs(g1-g0)>rtk->opt.thresslip) {trace(3,"detslip_gf: slip detected sat=%2d gf=%8.3f->%8.3f\n",obs[i].sat,g0,g1);for (j=0;j<rtk->opt.nf;j++) rtk->ssat[obs[i].sat-1].slip[j]|=1;}}
}
  • 处理过程
  1. 先调用gfmeas函数计算GF组合值GF=λ1ϕ1−λ2ϕ2GF = \lambda_1\phi_1-\lambda_2\phi_2GF=λ1​ϕ1​−λ2​ϕ2​,其中ϕ1\phi_1ϕ1​、ϕ2\phi_2ϕ2​分别为L1,L2的载波相位测量值(单位:周),λ1\lambda_1λ1​、λ2\lambda_2λ2​为L1、L2的波长;
  2. 将当前历元的GF组合值与上一次的组合值进行比较,如果差值的绝对值大于了阈值(默认值0.05),则认为有周跳。
  • 注意事项
  1. GF组合本质上是计算GF=λ1ϕ1−λ2ϕ2=λ1N1−λ2N2GF = \lambda_1\phi_1-\lambda_2\phi_2 =\lambda_1N_1-\lambda_2N_2GF=λ1​ϕ1​−λ2​ϕ2​=λ1​N1​−λ2​N2​,如果没有周跳发生,那么上一历元和当前历元的GF值应该是一致的。
  2. GF组合根据其表达式可以推导其噪声:σGF=2σL\sigma_{GF}=\sqrt{2}\sigma_LσGF​=2​σL​。该周跳检测的阈值也可以根据噪声水平进行设定,GAMP中同样也根据采样间隔和高度角对阈值进行了调整,感兴趣可以参考其论文和代码。

detslp_ll

static void detslp_ll(rtk_t *rtk, const obsd_t *obs, int i, int rcv)
  • 所在文件:rtkpost.c
  • 功能说明:通过LLI标志进行周跳检测
  • 参数说明
* args   : rtk_t  *rtk       IO  gps solution structure
*          obsd_t *obs       I   satellite observations
*          int     i         I   index of obs
*          int    rcv        I   1: rover receiver; 2: base receiver 
  • 处理过程
  1. 由于前向处理和后向处理,在利用LLI进行周跳判断上有所不同。因此在处理过程中,仅以前向为例;
  2. LLI=getbitu(&rtk->ssat[sat-1].slip[f],0,2); 首先将上一历元该卫星的周跳标志取出存在LLI变量中,该变量之后会用来判断上一历元和当前历元,半周跳标志(LLI&2,即LLI的bit 1位)是否发生变化;
  3. slip=obs[i].LLI[f];将当前历元原始观测量中的LLI赋值给slip变量;
  4. 如果上一历元和当前历元的半周跳标志不同,则认为有周跳,将slip的第0位置1;
  5. 存放当前历元的LLI和周跳。
  • 注意事项
  1. 后向处理和前向处理之间的区别:仔细观察代码,会发现后向处理中,判断周跳利用的是前一历元的LLI,而不是当前历元的LLI,而前向处理,使用的是当前历元的LLI。原因:假设一组连续8个历元的整周模糊度为:1-1-1-1-50-50-50-50,在历元5时,LLI=1。那么在前向处理时,将第5个历元标记为周跳是没问题的,因为在历元5,整周模糊度由1跳变为50。但是在后向处理时,虽然原始数据中历元5的LLI为1,但是实际周跳应该在历元4,因为后向处理时,历元4的整周模糊度由50跳变为1。
  • 我的疑惑
  1. rtkpost.c中detslp_ll比较重要的特点是考虑了半周跳变化的情况,如果半周跳标志(LLI=2)前后两个历元发生变化,则认为有周跳。如果一直维持半周跳情况,并没有将slip的第0位置1,在之后的处理中仍然会使用该数据,这样似乎不太合理?

detslp_dop

static void detslp_dop(rtk_t *rtk, const obsd_t *obs, int i, int rcv, const nav_t *nav)
  • 所在文件:rtkpost.c
  • 功能说明:通过多普勒值进行周跳检测
  • 参数说明
* args   : rtk_t  *rtk       IO  gps solution structure
*          obsd_t *obs       I   satellite observations
*          int     i         I   index of obs
*          int    rcv        I   1: rover receiver; 2: base receiver
*          nav_t  *nav       I   satellite navigation data
  • 处理过程
  1. 因为这个函数在RTKlib2.4.3中已经不再使用,所以有些变量的定义不太清楚具体的含义,但是大致处理方法和流程还是比较清晰的。
  2. 首先计算周跳检测阈值,thres=MAXACC*tt *tt/2.0/lam+rtk->opt.err[4]*fabs(tt)*4.0;
  3. 计算前后两个历元的载波相位差值:dph=obs[i].L[f]-rtk->ph[rcv-1][sat-1][f];计算多普勒的积分值,dpt=-obs[i].D[f]*tt;;
  4. 将上述两个计算值相减,如果差值的绝对值超过阈值,则认为有周跳。
  • 注意事项
  1. RTKlib注释中提到,detslp_dop函数由于clock-jump的问题,所以暂时没有使用。我猜测clock-jump可能是历元间时间的跳变,因为理论上 应该对多普勒进行连续积分,如果历元时间跳变,直接用dpt=-obs[i].D[f]*tt计算积分值,误差是很大的。
  2. 不考虑clock-jump的问题,利用前一历元和当前历元,这两个历元的平均多普勒进行梯形积分,可能会比仅使用当前历元的多普勒值进行矩形积分的效果更好。即多普勒积分值进行如下计算:
    dD(k)=−[D(k)+D(k−1)]∗0.5∗dtd_D(k) = - [D(k) + D(k-1)] *0.5*dtdD​(k)=−[D(k)+D(k−1)]∗0.5∗dt

RTKlib源码解析:ppp和rtkpost中的周跳检测函数相关推荐

  1. RTKLIB源码解析(一)、单点定位(pntpos.c)

      目录 pntpos satposs estpos raim_fde estvel ephclk satpos satsys seleph eph2clk ephpos eph2pos rescod ...

  2. rtklib源码 rtk差分解算,rtkpos和replos函数流程梳理

    rtklib源码 rtk差分解算,rtkpos和replos函数流程梳理 rtkpos函数梳理 总体流程 replos函数梳理 replos总体流程 1. 通过satposs函数计算卫星的位置.速度等 ...

  3. 12、常见Conditional注解源码解析-ConditionalOnBean(写作中...)

    ConditionalOnBean 源码解析 ConditionalOnBean 注解 看看 ConditionalOnBean 注解 @Conditional(OnBeanCondition.cla ...

  4. 【backtrader源码解析7】backtrader中mathsupport中计算平均值、方差和标准差的函数的分析(含金量挺低的)

    前面的几篇文章尝试通过优化backtrader几个时间处理函数来提高效率,使用cython能提高单个函数效率但是在整体中效率降低导致失败之后,我又尝试了使用numba来改进那几个时间处理函数,也失败了 ...

  5. python3 socketserver源码解析_解读python中SocketServer源码

    再看继承 真正的大餐来之前,还是来点儿开胃菜!回顾一下关于类的继承的知识: 我们先看上面的代码,这是一个简单的类继承,我们可以看到父类Base和子类Son,它们中各有一个Testfunc方法,当我们实 ...

  6. RTKLIB源码解析(二)、 RTK定位(rtkpos.c)

    本博客是转载,感谢: rtklib代码详解--rtkpos.c - 博客园-哆啦A梦 - 博客园 主函数:rtkpos 1.  设置基站位置 2. 统计基站和流动站的卫星数量 3. 单点定位解算 4. ...

  7. SpringSession的源码解析(从Cookie中读取Sessionid,根据sessionid查询信息全流程分析)

    前言 上一篇我们介绍了SpringSession中Session的保存过程,今天我们接着来看看Session的读取过程.相对保存过程,读取过程相对比较简单. 本文想从源码的角度,详细介绍一下Sessi ...

  8. RTKlib相对定位源码解析: udstate函数

    最近阅读RTKlib开源代码,非常感谢"塔奇克敲代码"博主的博客(RTKLIB源码解析--单点定位),他将单点定位部分整理成函数小卡片,为我理解RTKlib提供了很大的帮助.我参照 ...

  9. RTKlib相对定位源码解析:zdres函数

    最近阅读RTKlib开源代码,非常感谢"塔奇克敲代码"博主的博客(RTKLIB源码解析--单点定位),他将单点定位部分整理成函数小卡片,为我理解RTKlib提供了很大的帮助.我参照 ...

  10. RTKlib相对定位源码解析: ddres函数

    最近阅读RTKlib开源代码,非常感谢"塔奇克敲代码"博主的博客(RTKLIB源码解析--单点定位),他将单点定位部分整理成函数小卡片,为我理解RTKlib提供了很大的帮助.我参照 ...

最新文章

  1. Cocos2d之Texture2D类详解之将文件加载成Texture2D对象
  2. RDA5807 FM收音机模块
  3. python读取输入流_Python读取实时数据流教程
  4. 第二章(jQuery选择器)
  5. 计算机硬件的组装实践,毕业论文-计算机硬件组装实践.doc
  6. 图文:知乎千万级高性能长连接网关是如何搭建的?
  7. MySQL中自动增长类型要求
  8. while用法_语法||由一句译文聊聊while的用法
  9. python 加锁_python之给文件加锁(fcntl模块)
  10. WordPress病毒杂志主题King V6.5 英文Nulled版
  11. ViewPager异常,对ViewPager源码分析
  12. oracle asm 加盘,ASM添加磁盘最佳实践
  13. 2008年17款远程控制软件大比拼
  14. linux 提取网卡驱动,linux(ubuntu18.04)系统上安装RTL8822CE网卡驱动
  15. 由内而外的云计算之路 英特尔现身说法
  16. 全球及中国冷冻减脂行业需求趋势及投资策略分析报告2022-2028年
  17. jquery fullpage
  18. 【矩阵论】单射、满射与双射
  19. canvas实现涂鸦效果--橡皮檫和历史记录
  20. Java分割字符串(spilt())

热门文章

  1. chrome插件帮助你在12306官网刷票
  2. 信用卡一样大小的(小型电脑):树莓派
  3. 计算机安全模式快捷键,windows7怎么进入安全模式(快捷键进入的方法)
  4. python gdal 基于栅格shp文件裁剪geotif图
  5. 假如某人年薪100万,如何分配月发和年终奖会使其纳税金额最少
  6. 即时聊天软件与开放平台
  7. ThinkPHP6.0学习入门:环境搭建与安装教程
  8. 中国细菌学试验市场趋势报告、技术动态创新及市场预测
  9. 整流-1.输入电压角度计算
  10. idea 提示Expecting newline or semicolon解决办法