概述
文章目录
- DCB概念
- DCB文件下载
- RTKLIB中的DCB修正
- RTKLIB测试
DCB概念
由于卫星或接收机硬件延迟,导致不同信号的传播时间并不一致,从而产生了DCB(Differential Code Bias 差分码偏差)。DCB包括卫星端差分码偏差和接收机端差分码偏差,一般来说接收机端的DCB可以跟接收机钟差一起解算,被接收机钟差所吸收;而卫星端的DCB在精密定位中必须得到补偿。
DCB根据频率可以分为两种:
- 频内偏差:相同频率不同码之间存在的偏差(如P1-C1、P2-C2等)
- 频间偏差:不同频率之间存在的偏差(如P1-P2)
差分码偏差是影响电离层总电子含量(total electron content, TEC)监测和建模的主要误差源,忽略卫星和接收机DCB会导致TEC计算误差达到数十个纳秒。差分码偏差也直接影响利用伪距进行导航定位与授时的精度,其误差可达数米。因此,在电离层延迟估计、精密定位等应用中需要对DCB进行修正。
DCB文件下载
目前有两个两个机构为IGS(International GNSS Service)提供DCB产品,一是德国宇航中心(DLR),二是位于武汉的中国科学院大地测量与地球物理研究所(IGG)。IGG计算的卫星和站偏差(BSX文件)是每天生成的,延时为2-3天,包括以下信号;
目前, 这些文件被归档在CDDIS:https://cddis.nasa.gov/archive/gnss/products/bias/
RTKLIB中的DCB修正
读取DCB文件
我所使用的是RTKLIB b34版本,从源码可知,目前RTKLIB只支持GPS 和GLONASS部分信号的DCB修正,DCB参数放在 nav->cbias中。
/* read DCB parameters file --------------------------------------------------*/
static int readdcbf(const char *file, nav_t *nav, const sta_t *sta)
{
FILE *fp;
double cbias;
char buff[256],str1[32],str2[32]="";
int i,j,sat,type=0;
trace(3,"readdcbf: file=%sn",file);
if (!(fp=fopen(file,"r"))) {
trace(2,"dcb parameters file open error: %sn",file);
return 0;
}
while (fgets(buff,sizeof(buff),fp)) {
if (strstr(buff,"DIFFERENTIAL (P1-P2) CODE BIASES")) type=1;
else if (strstr(buff,"DIFFERENTIAL (P1-C1) CODE BIASES")) type=2;
else if (strstr(buff,"DIFFERENTIAL (P2-C2) CODE BIASES")) type=3;
if (!type||sscanf(buff,"%s %s",str1,str2)<1) continue;
if ((cbias=str2num(buff,26,9))==0.0) continue;
if (sta&&(!strcmp(str1,"G")||!strcmp(str1,"R"))) { /* receiver DCB */
for (i=0;i<MAXRCV;i++) {
if (!strcmp(sta[i].name,str2)) break;
}
if (i<MAXRCV) {
j=!strcmp(str1,"G")?0:1;
nav->rbias[i][j][type-1]=cbias*1E-9*CLIGHT; /* ns -> m */
}
}
else if ((sat=satid2no(str1))) { /* satellite dcb */
nav->cbias[sat-1][type-1]=cbias*1E-9*CLIGHT; /* ns -> m */
}
}
fclose(fp);
return 1;
}
单点定位中的DCB修正
从源码可知,RTKLIB会将GPS和GLONASS的C1伪距信号通过DCB修正到P1,将C2伪距信号通过DCB修正到P2。由于GPS广播星历的卫星钟差参数以L1P(Y)和L2P(Y)消电离层组合为参考基准,所以不用再及进行P1、P2之间的的DCB修正。
如果没有DCB,可以使用TGD参数修正不同信号的延迟。与IGS提供的DCB产品相比,TGD参数精度不高且更新频次较低(如GPS TGD参数平均每4个月更新一次)。但由于TGD参数能够通过广播星历实时获取,因此可以用来提高实时定位精度。具体如何使用TGD对信号进行修正,可以参考每个卫星系统的ICD,里面写得比较清楚。
/* iono-free or "pseudo iono-free" pseudorange with code bias correction -----*/
static double prange(const obsd_t *obs, const nav_t *nav, const prcopt_t *opt,
double *var)
{
double P1,P2,gamma,b1,b2;
int sat,sys;
sat=obs->sat;
sys=satsys(sat,NULL);
P1=obs->P[0];
P2=obs->P[1];
*var=0.0;
if (P1==0.0||(opt->ionoopt==IONOOPT_IFLC&&P2==0.0)) return 0.0;
/* P1-C1,P2-C2 DCB correction */
if (sys==SYS_GPS||sys==SYS_GLO) {
if (obs->code[0]==CODE_L1C) P1+=nav->cbias[sat-1][1]; /* C1->P1 */
if (obs->code[1]==CODE_L2C) P2+=nav->cbias[sat-1][2]; /* C2->P2 */
}
if (opt->ionoopt==IONOOPT_IFLC) { /* dual-frequency */
if (sys==SYS_GPS||sys==SYS_QZS) { /* L1-L2,G1-G2 */
gamma=SQR(FREQL1/FREQL2);
return (P2-gamma*P1)/(1.0-gamma);
}
else if (sys==SYS_GLO) { /* G1-G2 */
gamma=SQR(FREQ1_GLO/FREQ2_GLO);
return (P2-gamma*P1)/(1.0-gamma);
}
else if (sys==SYS_GAL) { /* E1-E5b */
gamma=SQR(FREQL1/FREQE5b);
if (getseleph(SYS_GAL)) { /* F/NAV */
P2-=gettgd(sat,nav,0)-gettgd(sat,nav,1); /* BGD_E5aE5b */
}
return (P2-gamma*P1)/(1.0-gamma);
}
else if (sys==SYS_CMP) { /* B1-B2 */
gamma=SQR(((obs->code[0]==CODE_L2I)?FREQ1_CMP:FREQL1)/FREQ2_CMP);
if (obs->code[0]==CODE_L2I) b1=gettgd(sat,nav,0); /* TGD_B1I */
else if (obs->code[0]==CODE_L1P) b1=gettgd(sat,nav,2); /* TGD_B1Cp */
else b1=gettgd(sat,nav,2)+gettgd(sat,nav,4); /* TGD_B1Cp+ISC_B1Cd */
b2=gettgd(sat,nav,1); /* TGD_B2I/B2bI (m) */
return ((P2-gamma*P1)-(b2-gamma*b1))/(1.0-gamma);
}
else if (sys==SYS_IRN) { /* L5-S */
gamma=SQR(FREQL5/FREQs);
return (P2-gamma*P1)/(1.0-gamma);
}
}
else { /* single-freq (L1/E1/B1) */
*var=SQR(ERR_CBIAS);
if (sys==SYS_GPS||sys==SYS_QZS) { /* L1 */
b1=gettgd(sat,nav,0); /* TGD (m) */
return P1-b1;
}
else if (sys==SYS_GLO) { /* G1 */
gamma=SQR(FREQ1_GLO/FREQ2_GLO);
b1=gettgd(sat,nav,0); /* -dtaun (m) */
return P1-b1/(gamma-1.0);
}
else if (sys==SYS_GAL) { /* E1 */
if (getseleph(SYS_GAL)) b1=gettgd(sat,nav,0); /* BGD_E1E5a */
else b1=gettgd(sat,nav,1); /* BGD_E1E5b */
return P1-b1;
}
else if (sys==SYS_CMP) { /* B1I/B1Cp/B1Cd */
if (obs->code[0]==CODE_L2I) b1=gettgd(sat,nav,0); /* TGD_B1I */
else if (obs->code[0]==CODE_L1P) b1=gettgd(sat,nav,2); /* TGD_B1Cp */
else b1=gettgd(sat,nav,2)+gettgd(sat,nav,4); /* TGD_B1Cp+ISC_B1Cd */
return P1-b1;
}
else if (sys==SYS_IRN) { /* L5 */
gamma=SQR(FREQs/FREQL5);
b1=gettgd(sat,nav,0); /* TGD (m) */
return P1-gamma*b1;
}
}
return P1;
}
PPP中的DCB修正
在RTKLIB的PPP中,如果有SSR修正,则使用SSR修正中对伪距进行修正;如果没有SSR,则用DCB文件的修正参数进行修正。
/* antenna corrected measurements --------------------------------------------*/
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)
{
double freq[NFREQ]={0},C1,C2;
int i,ix=0,frq2, sys=satsys(obs->sat,NULL);
for (i=0;i<NFREQ;i++) {
L[i]=P[i]=0.0;
/* skip if low SNR or missing observations */
freq[i]=sat2freq(obs->sat,obs->code[i],nav);
if (freq[i]==0.0||obs->L[i]==0.0||obs->P[i]==0.0) continue;
if (testsnr(0,0,azel[1],obs->SNR[i]*SNR_UNIT,&opt->snrmask)) continue;
/* antenna phase center and phase windup correction */
L[i]=obs->L[i]*CLIGHT/freq[i]-dants[i]-dantr[i]-phw*CLIGHT/freq[i];
P[i]=obs->P[i] -dants[i]-dantr[i];
if (opt->sateph==EPHOPT_SSRAPC||opt->sateph==EPHOPT_SSRCOM) {
/* select SSR code correction based on code */
if (sys==SYS_GPS)
ix=(i==0?CODE_L1W-1:CODE_L2W-1);
else if (sys==SYS_GLO)
ix=(i==0?CODE_L1P-1:CODE_L2P-1);
else if (sys==SYS_GAL)
ix=(i==0?CODE_L1X-1:CODE_L7X-1);
/* apply SSR correction */
P[i]+=(nav->ssr[obs->sat-1].cbias[obs->code[i]-1]-nav->ssr[obs->sat-1].cbias[ix]);
}
else { /* use P1-C1,P2-C2 code corrections from DCB file */
/* P1-C1,P2-C2 dcb correction (C1->P1,C2->P2) */
if (sys==SYS_GPS||sys==SYS_GLO) {
if (obs->code[i]==CODE_L1C)
P[i]+=nav->cbias[obs->sat-1][1]; /* C1->P1 */
if (obs->code[i]==CODE_L2C||obs->code[i]==CODE_L2X||
obs->code[i]==CODE_L2L||obs->code[i]==CODE_L2S)
P[i]+=nav->cbias[obs->sat-1][2]; /* C2->P2 */
}
}
}
/* choose freqs for iono-free LC */
*Lc=*Pc=0.0;
frq2=L[1]==0?2:1; /* if L[1]==0, try L[2] */
if (freq[0]==0.0||freq[frq2]==0.0) return;
C1= SQR(freq[0])/(SQR(freq[0])-SQR(freq[frq2]));
C2=-SQR(freq[frq2])/(SQR(freq[0])-SQR(freq[frq2]));
if (L[0]!=0.0&&L[frq2]!=0.0) *Lc=C1*L[0]+C2*L[frq2];
if (P[0]!=0.0&&P[frq2]!=0.0) *Pc=C1*P[0]+C2*P[frq2];
}
RTKLIB测试
测试采用已知精密位置的CORS站数据。数据来源、RTKLIB配置和之前的PPP测试博客“RTKlib 后处理静态PPP性能分析测试”中基本一致。
测试中只用两个小时的GPS的数据,比较使用DCB文件和不使用DCB文件情况下,前向PPP精度。从下图中的定位结果来看,有DCB修正PPP收敛得比较平稳、比较快。
将前向PPP最后一个定位值与CORS站精确位置进行比较,ecef误差分别为:
- 有DCB修正:-0.0230m, 0.1382m 0.0639m
- 无DCB修正: -0.0212m 0.0980m 0.0744m
虽然看起有DCB修正的PPP显得还稍微差一丢丢,不过有无DCB最后PPP收敛的位置只差0.0018m, -0.0402m, 0.0105m,我觉得都在PPP的精度范围内,所以收敛后的定位精度其实是比较一致的。
参考文献:
[1] 吴竞, et al. “BDS-2 导航电文的 TGD 参数精度及其对用户导航定位精度的影响.” 天文学进展 37.03 (2019): 337-346.
[2] 王宁波, et al. “GPS 民用广播星历中 ISC 参数精度分析及其对导航定位的影响.” (2016).
最后
以上就是有魅力导师为你收集整理的DCB差分码偏差概念及应用(附RTKLIB测试对比结果)的全部内容,希望文章能够帮你解决DCB差分码偏差概念及应用(附RTKLIB测试对比结果)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复