分享

RTKlib PPP代码解析

 时钟转动 2022-03-28

我所基于的代码版本是RTKlib 2.4.3的一个拓展版本RTKexplore Demo5,这个版本主要针对低成本的GNSS进行了一些改进完善。

pppos

extern void pppos(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav)
  • 所在文件:ppp.c
  • 功能说明:PPP处理
  • 参数说明
 args: 		 IO    rtk_t *rtk			rtk solution structure
			 I     const obsd_t *obs	当前历元观测值
			 I     int n 				当前移动站观测值数目
			 I     const nav_t *nav     星历 
  • 调用关系
  • 处理过程
  1. 调用udstate_ppp函数进行卡尔曼滤波的一步预测;
  2. 调用satposs函数计算卫星位置;
  3. 如果在配置中选择排除block IIA卫星,调用testeclipse函数,将这些卫星的位置、速度置0;
  4. 如果在配置中选择潮汐修正,调用tidedisp函数进行潮汐修正;
  5. 调用ppp_res函数计算预测值与量测值之间的残差;
  6. 待用filter函数进行卡尔曼滤波的量测更新;
  7. 调用ppp_res函数计算量测更新后的残差;
  8. 调用ppp_ar进行整周模糊度结算,并调用ppp_res进行残差计算;
  9. 调用update_stat更新输入、输出参数rtk solution的状态
  • 注意事项
  1. 需要注意的是,步骤8中ppp_ar是个空函数,返回值为0,因此实际后面的ppp_res函数也不会被调用。如此来看,实际PPP的解为通过卡尔曼滤波得到的浮点解。
  2. satposs和相对定位中的函数一致,不再进行解析,可参考RTKLIB源码解析——单点定位

udstate_ppp

static void udstate_ppp(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav)
  • 所在文件:ppp.c
  • 功能说明:进行卡尔曼滤波的一步预测,更新rtk->x状态量值
  • 参数说明
 args: 		 IO    rtk_t *rtk			rtk solution structure
			 I     const obsd_t *obs	当前历元观测值
			 I     int n 				当前移动站观测值数目
			 I     const nav_t *nav     星历 
  • 调用关系
  • 处理过程
  1. 调用udpos_ppp函数位置、速度、加速度状态量 rtk->x以及相应协方差阵 rtk->P的更新;
  2. 调用udclk_ppp函数,更新钟差状态量(以gpst为基准);
  3. 如果在配置中选择的对流层模型为ZTD estimation或者ZTD+grad estimation,调用udtrop_ppp进行对流层参数状态量的更新;
  4. 如果在配置中选择电离层模型为estimation,调用udiono_ppp函数,更新电离层误差参数状态量;
  5. 如果选择的频率数>=3,则进行L5 dcb状态量的更新;
  6. 调用udbias_ppp函数进行相位bias状态量的更新。
  • 注意事项
  1. 参考RTklib manual 来看,PPP算法中使用的量测量为“无电离层组合的伪距、载波相位”,所以配置中可以将电离层模型选择为“Iono free LC”。通过参考RTKexplorer博客Exploring kinematic single-receiver solutions with RTKLIB and the u-blox F9P. 中的配置,对流层模型应该至少配置为ZTD estimation。我在之后的博客中会测试一下不同的PPP配置对精度有多大的影响。
  2. 参考 RTKLIB Manual 可知状态量包括位置、速度、接收机钟差、对流层参数、卫星相位偏差;
  3. udpos_ppp、udtrop_ppp、udiono_ppp函数与之前相对定位中udpos、udtrop、udion函数流程基本一致,就不再详细解释,具体可参考RTKlib相对定位源码解析: udstate函数。由于udbias_ppp和相对定位中不同,因此在下文中进行解析。

udbias_ppp

static void udbias_ppp(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav)
  • 所在文件:ppp.c
  • 功能说明:进行相位偏差状态量和协方差阵的一步预测
  • 参数说明
 args: 		 IO    rtk_t *rtk			rtk solution structure
			 I     const obsd_t *obs	当前历元观测值
			 I     int n 				当前移动站观测值数目
			 I     const nav_t *nav     星历 
  • 处理过程
  1. 首先是对所有共视星进行周跳检测:调用了detslp_ll函数,根据LLI来判断基站和移动站周跳;然后调用detslp_gf利用几何无关组合进行周跳检测;最后调用了detslp_gf_mw函数进行周跳检测。对RTKlib的周跳检测函数,我专门写了一篇博客解析RTKlib源码解析:ppp和rtkpost中的周跳检测函数
  2. 对所有卫星进行循环,判断是否需要重置单差相位偏移状态量。如果所配置的AR的模式为instantaneous(实际由于当前PPP中使用的是浮点解,通常将PPP的AR配置为OFF),或者卫星载波相位的中断次数大于配置中所设置的最大次数,则将单差相位偏移状态量重置为0;
  3. 对每一组观测数据,调用 corr_meas函数对伪距、载波相位进行修正,并计算无电离层组合的伪距、载波相位量测量Pc和Lc;
  4. 将每颗卫星的载波相位偏差bias初始化为0,如果电离层模型为电离层无关模型,则直接计算bias[i]=Lc-Pc;否则的话,通过伪距计算电离层延迟ion=(obs[i].P[0]-obs[i].P[l])/(1.0-SQR(lam[l]/lam[0]));由于L1和L2伪距相减后,只剩下L1和L2的电离层误差之差,以及伪距噪声项,因此由此计算出来的电离层误差实际包含了伪距噪声,误差相对较大。利用修正电离层误差后的伪距和载波相位之差计算bias: bias[i]=L[f]-P[f]+2.0ionSQR(lam[f]/lam[0]);
  5. 计算每颗卫星的bias与载波相位偏差状态量rtk->x之间的偏差offset之和;
  6. 在原有的载波相位偏差状态量上加上offset的平均值,以此来作为载波相位偏差一步预测值:rtk->x[j]+=offset/k;
    7.对每颗卫星循环,更新一步预测协方差阵,对有周跳的卫星、或者没有初始化载波相位偏差状态量的卫星,用之前计算的bias值重新初始化载波相位偏差状态量。

corr_meas

static void corr_meas(const obsd_t *obs, const nav_t *nav, const double *azel,
                      const prcopt_t *opt, const double *dantr,
                      const double *dants, double phw, double *L, double *P,
                      double *Lc, double *Pc)
  • 所在文件:ppp.c
  • 功能说明:计算经过接收机天线修正、相位缠绕校正、SSR修正或者dcb 修正后的伪距、载波相位量测量,并计算无电离层组合的伪距、载波相位值Lc,Pc
  • 参数说明
 args: 		 I     const obsd_t *obs	当前历元观测值
			 I     const nav_t *nav 	星历
			 I     const double *azel 	方位角和俯仰角 (rad)
			 I	   const prcopt_t *opt  处理选项
			 I     const double *dantr  接收机天线校正值
			 I     const double *dants  卫星天线校正值
			 I     double   phw        相位缠绕校正值
			 O     double *L           修正后的载波相位
			 O     double *P           修正后的伪距值
			 O	   double *Lc          无电离层组合的载波相位值
			 O     double *Pc          无电离层组合的伪距值 
  • 处理过程
  1. 调用 testsnr函数检查观测值的信噪比是否大于mask;
  2. 对伪距天线修正、相位缠绕校正,对载波相位进行天线修正;
  3. 如果星历类型是broadcast + SSR_APC或者broadcast + SSR_COM,对伪距值进行ssr 修正;如果是其他星历类型,进行 DCB 校正;
  4. 计算无电离层组合的伪距、载波相位值Lc,Pc

ppp_res

static int ppp_res(int post, const obsd_t *obs, int n, const double *rs,
                   const double *dts, const double *var_rs, const int *svh,
                   const double *dr, int *exc, const nav_t *nav,
                   const double *x, rtk_t *rtk, double *v, double *H, double *R,
                   double *azel)
  • 所在文件:ppp.c
  • 功能说明:计算载波相位和伪距残差
  • 参数说明
 args: 		 I     int post             是否是修正后残差计算标志
 			 I     const obsd_t *obs	当前历元观测值
 			 I     int n                当前移动站观测值数目
             I     const double *dts    卫星钟差
             I     const double *var_rs 星位置和钟差的协方差
             I     const int *svh       卫星健康标志
             I     const double *dr     地球潮汐位移
             IO    int *exc             卫星排除标志
			 I     const nav_t *nav 	星历
			 IO    const double *x      状态量
			 IO    rtk_t *rtk			rtk solution structure
			 IO    double *v            载波相位和伪距残差
			 IO    double *H            卡尔曼滤波中的观测矩阵
			 IO    double *R            测量误差的协方差矩阵
			 I     const double *azel 	方位角和俯仰角 (rad) 
  • 处理过程
  1. 把卫星的有效标志位均置0,rtk->ssat[i].vsat[j]=0;
  2. 在一步预测值x[i]基础上加上潮汐修正,作为移动站位置:rr[i]=x[i]+dr[i];
  3. 对每颗星进行循环,根据移动站位置,计算卫星仰角,如果小于设定阈值,排除该卫星,并且检查该卫星系统、单点定位卫星有效标志、是否在设置中排除,重置排除标志:exc[i]=1;
  4. 调用model_trop函数计算对流层误差dtrp,调用model_iono函数计算电离层误差dion;
  5. 调用satantpcv函数计算卫星天线校正参数dants;调用antmodel函数计算根据接收机天线的相位中心参数计算天线偏移量dantr,该函数在此博客曾进行解析;
  6. 调用model_phw函数计算相位缠绕校正值rtk->ssat[sat-1].phw;
  7. 调用corr_meas函数对伪距和载波相位进行修正,得到量测量;
  8. 计算量测矩阵H和残差v,相位残差存放在 rtk->ssat[sat-1].resc中,伪距残差在rtk->ssat[sat-1].resp中;
  9. 综合考虑伪距(载波相位)噪声、对流层噪声、电离层噪声、卫星位置钟差噪声后,作为量测噪声;如果是GLONASS卫星,在伪距量测噪声上,还要加上IFB噪声(频间差噪声);
  10. 如果是 pre-fit,即!post的情况,如果某颗残差值大于阈值,将这颗星排除;
  11. 如果post为1,某颗残差值大于阈值,将这颗星记录下来;整个循环结束;
  12. 如果post为1,找到11步中残差值最大的那颗星,将其排除。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多