RTKLIB专题学习(七)---精密单点定位实现初识(二)
RTKLIB专题学习(七)—精密单点定位实现初识(二)
上一节我们讲完了pppos
中状态的时间更新函数的内容了,接下来我们往下进行:
1.satposs
是pppps
调用的另一个函数,主要用于计算卫星位置rs
和卫星钟差dts
/* satellite positions and clocks ----------------------------------------------
* compute satellite positions, velocities and clocks
* args : gtime_t teph I time to select ephemeris (gpst)
* obsd_t *obs I observation data
* int n I number of observation data
* nav_t *nav I navigation data
* int ephopt I ephemeris option (EPHOPT_???)
* double *rs O satellite positions and velocities (ecef)
* double *dts O satellite clocks
* double *var O sat position and clock error variances (m^2)
* int *svh O sat health flag (-1:correction not available)
* return : none
* notes : rs [(0:2)+i*6]= obs[i] sat position {x,y,z} (m)
* rs [(3:5)+i*6]= obs[i] sat velocity {vx,vy,vz} (m/s)
* dts[(0:1)+i*2]= obs[i] sat clock {bias,drift} (s|s/s)
* var[i] = obs[i] sat position and clock error variance (m^2)
* svh[i] = obs[i] sat health flag
* if no navigation data, set 0 to rs[], dts[], var[] and svh[]
* satellite position and clock are values at signal transmission time
* satellite position is referenced to antenna phase center
* satellite clock does not include code bias correction (tgd or bgd)
* any pseudorange and broadcast ephemeris are always needed to get
* signal transmission time
*-----------------------------------------------------------------------------*/
extern void satposs(gtime_t teph, const obsd_t *obs, int n, const nav_t *nav,
int ephopt, double *rs, double *dts, double *var, int *svh)
{
gtime_t time[2*MAXOBS]={{0}};
double dt,pr;
int i,j;
trace(3,"satposs : teph=%s n=%d ephopt=%d\n",time_str(teph,3),n,ephopt);
for (i=0;i<n&&i<2*MAXOBS;i++) {
for (j=0;j<6;j++) rs [j+i*6]=0.0;
for (j=0;j<2;j++) dts[j+i*2]=0.0;
var[i]=0.0; svh[i]=0;
/* search any pseudorange */
for (j=0,pr=0.0;j<NFREQ;j++) if ((pr=obs[i].P[j])!=0.0) break;
if (j>=NFREQ) {
trace(3,"no pseudorange %s sat=%2d\n",time_str(obs[i].time,3),obs[i].sat);
continue;
}
/* transmission time by satellite clock */
time[i]=timeadd(obs[i].time,-pr/CLIGHT);
/* satellite clock bias by broadcast ephemeris */
if (!ephclk(time[i],teph,obs[i].sat,nav,&dt)) {
trace(3,"no broadcast clock %s sat=%2d\n",time_str(time[i],3),obs[i].sat);
continue;
}
time[i]=timeadd(time[i],-dt);
/* satellite position and clock at transmission time */
if (!satpos(time[i],teph,obs[i].sat,ephopt,nav,rs+i*6,dts+i*2,var+i,
svh+i)) {
trace(3,"no ephemeris %s sat=%2d\n",time_str(time[i],3),obs[i].sat);
continue;
}
/* if no precise clock available, use broadcast clock instead */
if (dts[i*2]==0.0) {
if (!ephclk(time[i],teph,obs[i].sat,nav,dts+i*2)) continue;
dts[1+i*2]=0.0;
*var=SQR(STD_BRDCCLK);
}
}
for (i=0;i<n&&i<2*MAXOBS;i++) {
trace(4,"%s sat=%2d rs=%13.3f %13.3f %13.3f dts=%12.3f var=%7.3f svh=%02X\n",
time_str(time[i],6),obs[i].sat,rs[i*6],rs[1+i*6],rs[2+i*6],
dts[i*2]*1E9,var[i],svh[i]);
}
}
2.tidedisp
是pppos
调用的又一个函数,用于计算固体潮
海洋潮汐以及极潮对接收机位置产生的影响
/* tidal displacement ----------------------------------------------------------
* displacements by earth tides
* args : gtime_t tutc I time in utc
* double *rr I site position (ecef) (m)
* int opt I options (or of the followings)
* 1: solid earth tide
* 2: ocean tide loading
* 4: pole tide
* 8: elimate permanent deformation
* double *erp I earth rotation parameters (NULL: not used)
* double *odisp I ocean loading parameters (NULL: not used)
* odisp[0+i*6]: consituent i amplitude radial(m)
* odisp[1+i*6]: consituent i amplitude west (m)
* odisp[2+i*6]: consituent i amplitude south (m)
* odisp[3+i*6]: consituent i phase radial (deg)
* odisp[4+i*6]: consituent i phase west (deg)
* odisp[5+i*6]: consituent i phase south (deg)
* (i=0:M2,1:S2,2:N2,3:K2,4:K1,5:O1,6:P1,7:Q1,
* 8:Mf,9:Mm,10:Ssa)
* double *dr O displacement by earth tides (ecef) (m)
* return : none
* notes : see ref [1], [2] chap 7
* see ref [4] 5.2.1, 5.2.2, 5.2.3
* ver.2.4.0 does not use ocean loading and pole tide corrections
*-----------------------------------------------------------------------------*/
extern void tidedisp(gtime_t tutc, const double *rr, int opt, const erp_t *erp,
const double *odisp, double *dr)
{
gtime_t tut;
double pos[2],E[9],drt[3],denu[3],rs[3],rm[3],gmst,erpv[5]={0};
int i;
#ifdef IERS_MODEL
double ep[6],fhr;
int year,mon,day;
#endif
trace(3,"tidedisp: tutc=%s\n",time_str(tutc,0));
if (erp) {
geterp(erp,utc2gpst(tutc),erpv);
}
tut=timeadd(tutc,erpv[2]);
dr[0]=dr[1]=dr[2]=0.0;
if (norm(rr,3)<=0.0) return;
pos[0]=asin(rr[2]/norm(rr,3));
pos[1]=atan2(rr[1],rr[0]);
xyz2enu(pos,E);
if (opt&1) { /* solid earth tides */
/* sun and moon position in ecef */
sunmoonpos(tutc,erpv,rs,rm,&gmst);
#ifdef IERS_MODEL
time2epoch(tutc,ep);
year=(int)ep[0];
mon =(int)ep[1];
day =(int)ep[2];
fhr =ep[3]+ep[4]/60.0+ep[5]/3600.0;
/* call DEHANTTIDEINEL */
dehanttideinel_((double *)rr,&year,&mon,&day,&fhr,rs,rm,drt);
#else
tide_solid(rs,rm,pos,E,gmst,opt,drt);
#endif
for (i=0;i<3;i++) dr[i]+=drt[i];
}
if ((opt&2)&&odisp) { /* ocean tide loading */
tide_oload(tut,odisp,denu);
matmul("TN",3,1,3,1.0,E,denu,0.0,drt);
for (i=0;i<3;i++) dr[i]+=drt[i];
}
if ((opt&4)&&erp) { /* pole tide */
tide_pole(tut,pos,erpv,denu);
matmul("TN",3,1,3,1.0,E,denu,0.0,drt);
for (i=0;i<3;i++) dr[i]+=drt[i];
}
trace(5,"tidedisp: dr=%.3f %.3f %.3f\n",dr[0],dr[1],dr[2]);
}
3.ppp_res
是pppps
调用的下一个函数,该函数主要用于计算残差的:
/* phase and code residuals --------------------------------------------------*/
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)
{
prcopt_t *opt=&rtk->opt;
double y,r,cdtr,bias,C=0.0,rr[3],pos[3],e[3],dtdx[3],L[NFREQ],P[NFREQ],Lc,Pc;
double var[MAXOBS*2],dtrp=0.0,dion=0.0,vart=0.0,vari=0.0,dcb,freq;
double dantr[NFREQ]={0},dants[NFREQ]={0};
double ve[MAXOBS*2*NFREQ]={0},vmax=0;
char str[32];
int ne=0,obsi[MAXOBS*2*NFREQ]={0},frqi[MAXOBS*2*NFREQ],maxobs,maxfrq,rej;
int i,j,k,sat,sys,nv=0,nx=rtk->nx,stat=1;
time2str(obs[0].time,str,2);
for (i=0;i<MAXSAT;i++) for (j=0;j<opt->nf;j++) rtk->ssat[i].vsat[j]=0;
for (i=0;i<3;i++) rr[i]=x[i]+dr[i];
ecef2pos(rr,pos);
for (i=0;i<n&&i<MAXOBS;i++) {
sat=obs[i].sat;
if ((r=geodist(rs+i*6,rr,e))<=0.0||
satazel(pos,e,azel+i*2)<opt->elmin) {
exc[i]=1;
continue;
}
if (!(sys=satsys(sat,NULL))||!rtk->ssat[sat-1].vs||
satexclude(obs[i].sat,var_rs[i],svh[i],opt)||exc[i]) {
exc[i]=1;
continue;
}
/* tropospheric and ionospheric model */
if (!model_trop(obs[i].time,pos,azel+i*2,opt,x,dtdx,nav,&dtrp,&vart)||
!model_iono(obs[i].time,pos,azel+i*2,opt,sat,x,nav,&dion,&vari)) {
continue;
}
/* satellite and receiver antenna model */
if (opt->posopt[0]) satantpcv(rs+i*6,rr,nav->pcvs+sat-1,dants);
antmodel(opt->pcvr,opt->antdel[0],azel+i*2,opt->posopt[1],dantr);
/* phase windup model */
if (!model_phw(rtk->sol.time,sat,nav->pcvs[sat-1].type,
opt->posopt[2]?2:0,rs+i*6,rr,&rtk->ssat[sat-1].phw)) {
continue;
}
/* corrected phase and code measurements */
corr_meas(obs+i,nav,azel+i*2,&rtk->opt,dantr,dants,
rtk->ssat[sat-1].phw,L,P,&Lc,&Pc);
/* stack phase and code residuals {L1,P1,L2,P2,...} */
for (j=0;j<2*NF(opt);j++) {
dcb=bias=0.0;
if (opt->ionoopt==IONOOPT_IFLC) {
if ((y=j%2==0?Lc:Pc)==0.0) continue;
}
else {
if ((y=j%2==0?L[j/2]:P[j/2])==0.0) continue;
if ((freq=sat2freq(sat,obs[i].code[j/2],nav))==0.0) continue;
C=SQR(FREQ1/freq)*ionmapf(pos,azel+i*2)*(j%2==0?-1.0:1.0);
}
for (k=0;k<nx;k++) H[k+nx*nv]=k<3?-e[k]:0.0;
/* receiver clock */
switch (sys) {
case SYS_GLO: k=1; break;
case SYS_GAL: k=2; break;
case SYS_CMP: k=3; break;
case SYS_IRN: k=4; break;
default: k=0; break;
}
cdtr=x[IC(k,opt)];
H[IC(k,opt)+nx*nv]=1.0;
if (opt->tropopt==TROPOPT_EST||opt->tropopt==TROPOPT_ESTG) {
for (k=0;k<(opt->tropopt>=TROPOPT_ESTG?3:1);k++) {
H[IT(opt)+k+nx*nv]=dtdx[k];
}
}
if (opt->ionoopt==IONOOPT_EST) {
if (rtk->x[II(sat,opt)]==0.0) continue;
H[II(sat,opt)+nx*nv]=C;
}
if (j/2==2&&j%2==1) { /* L5-receiver-dcb */
dcb+=rtk->x[ID(opt)];
H[ID(opt)+nx*nv]=1.0;
}
if (j%2==0) { /* phase bias */
if ((bias=x[IB(sat,j/2,opt)])==0.0) continue;
H[IB(sat,j/2,opt)+nx*nv]=1.0;
}
/* residual */
v[nv]=y-(r+cdtr-CLIGHT*dts[i*2]+dtrp+C*dion+dcb+bias);
if (j%2==0) rtk->ssat[sat-1].resc[j/2]=v[nv];
else rtk->ssat[sat-1].resp[j/2]=v[nv];
/* variance */
var[nv]=varerr(obs[i].sat,sys,azel[1+i*2],j/2,j%2,opt)+
vart+SQR(C)*vari+var_rs[i];
if (sys==SYS_GLO&&j%2==1) var[nv]+=VAR_GLO_IFB;
trace(4,"%s sat=%2d %s%d res=%9.4f sig=%9.4f el=%4.1f\n",str,sat,
j%2?"P":"L",j/2+1,v[nv],sqrt(var[nv]),azel[1+i*2]*R2D);
/* reject satellite by pre-fit residuals */
if (!post&&opt->maxinno>0.0&&fabs(v[nv])>opt->maxinno) {
trace(2,"outlier (%d) rejected %s sat=%2d %s%d res=%9.4f el=%4.1f\n",
post,str,sat,j%2?"P":"L",j/2+1,v[nv],azel[1+i*2]*R2D);
exc[i]=1; rtk->ssat[sat-1].rejc[j%2]++;
continue;
}
/* record large post-fit residuals */
if (post&&fabs(v[nv])>sqrt(var[nv])*THRES_REJECT) {
obsi[ne]=i; frqi[ne]=j; ve[ne]=v[nv]; ne++;
}
if (j%2==0) rtk->ssat[sat-1].vsat[j/2]=1;
nv++;
}
}
/* reject satellite with large and max post-fit residual */
if (post&&ne>0) {
vmax=ve[0]; maxobs=obsi[0]; maxfrq=frqi[0]; rej=0;
for (j=1;j<ne;j++) {
if (fabs(vmax)>=fabs(ve[j])) continue;
vmax=ve[j]; maxobs=obsi[j]; maxfrq=frqi[j]; rej=j;
}
sat=obs[maxobs].sat;
trace(2,"outlier (%d) rejected %s sat=%2d %s%d res=%9.4f el=%4.1f\n",
post,str,sat,maxfrq%2?"P":"L",maxfrq/2+1,vmax,azel[1+maxobs*2]*R2D);
exc[maxobs]=1; rtk->ssat[sat-1].rejc[maxfrq%2]++; stat=0;
ve[rej]=0;
}
for (i=0;i<nv;i++) for (j=0;j<nv;j++) {
R[i+j*nv]=i==j?var[i]:0.0;
}
return post?stat:nv;
}
ppp_res
也调用了很多函数,比如geodist
函数,用于计算接收机与卫星之间的几何距离向量;satazel
函数用于计算卫星的天顶距与方位角;satantpcv
函数用于计算卫星天线的相位中心变化;antmodel
用于计算接收机天线相位中心的变化;model_phw
函数用于计算相位缠绕改正;corr_meas
函数用于对码和相位观测值进行校正
4.filter
是pppps
调用的核心函数,该函数主要用于扩展卡尔曼滤波状态的量测更新:
extern int filter(double *x, double *P, const double *H, const double *v,
const double *R, int n, int m)
{
double *x_,*xp_,*P_,*Pp_,*H_;
int i,j,k,info,*ix;
ix=imat(n,1); for (i=k=0;i<n;i++) if (x[i]!=0.0&&P[i+i*n]>0.0) ix[k++]=i;
x_=mat(k,1); xp_=mat(k,1); P_=mat(k,k); Pp_=mat(k,k); H_=mat(k,m);
for (i=0;i<k;i++) {
x_[i]=x[ix[i]];
for (j=0;j<k;j++) P_[i+j*k]=P[ix[i]+ix[j]*n];
for (j=0;j<m;j++) H_[i+j*k]=H[ix[i]+j*n];
}
info= filter_(x_,P_,H_,v,R,k,m,xp_,Pp_);
for (i=0;i<k;i++) {
x[ix[i]]=xp_[i];
for (j=0;j<k;j++) P[ix[i]+ix[j]*n]=Pp_[i+j*k];
}
free(ix); free(x_); free(xp_); free(P_); free(Pp_); free(H_);
return info;
}
该函数主要进行先验状态和后验状态信息的更新,其调用的filter_
函数为精髓:
/* kalman filter ---------------------------------------------------------------
* kalman filter state update as follows:
*
* K=P*H*(H'*P*H+R)^-1, xp=x+K*v, Pp=(I-K*H')*P
*
* args : double *x I states vector (n x 1)
* double *P I covariance matrix of states (n x n)
* double *H I transpose of design matrix (n x m)
* double *v I innovation (measurement - model) (m x 1)
* double *R I covariance matrix of measurement error (m x m)
double *Q - covariance matrix of v (m x m)
* int n,m I number of states and measurements
* double *xp O states vector after update (n x 1)
* double *Pp O covariance matrix of states after update (n x n)
*
* return : status (0:ok,<0:error)
* notes : matirix stored by column-major order (fortran convention)
* if state x[i]==0.0, not updates state x[i]/P[i+i*n]
*-----------------------------------------------------------------------------*/
extern int filter_(const double *x, const double *P, const double *H,
const double *v, const double *R, int n, int m,
double *xp, double *Pp)
{
double *F=mat(n,m),*Q=mat(m,m),*K=mat(n,m),*I=eye(n);
int info;
matcpy(Q,R,m,m);
matcpy(xp,x,n,1);
matmul("NN",n,m,n,1.0,P,H,0.0,F); /* Q=H'*P*H+R */
matmul("TN",m,m,n,1.0,H,F,1.0,Q);
if (!(info=matinv(Q,m))) {
matmul("NN",n,m,m,1.0,F,Q,0.0,K); /* K=P*H*Q^-1 */
matmul("NN",n,1,m,1.0,K,v,1.0,xp); /* xp=x+K*v */
matmul("NT",n,n,m,-1.0,K,H,1.0,I); /* Pp=(I-K*H')*P */
matmul("NN",n,n,n,1.0,I,P,0.0,Pp);
}
free(F); free(Q); free(K); free(I);
return info;
}
该函数主要是进行扩展卡尔曼滤波,进行量测更新部分解算
在解算后,进行后验残差分析,符合限制则输出为精密单点定位状态,结束该迭代部分
/* postfit residuals */
if (ppp_res(i+1,obs,n,rs,dts,var,svh,dr,exc,nav,xp,rtk,v,H,R,azel)) {
matcpy(rtk->x,xp,rtk->nx,1);
matcpy(rtk->P,Pp,rtk->nx,rtk->nx);
stat=SOLQ_PPP;
break;
}
需要注意,若要得到固定解,则接收机位置的标准差要小于固定解的最大标准差,即0.15
5.然后呢,调用pppos
的函数为rtkpos
/* precise positioning ---------------------------------------------------------
* input observation data and navigation message, compute rover position by
* precise positioning
* args : rtk_t *rtk IO RTK control/result struct
* rtk->sol IO solution
* .time O solution time
* .rr[] IO rover position/velocity
* (I:fixed mode,O:single mode)
* .dtr[0] O receiver clock bias (s)
* .dtr[1-5] O receiver GLO/GAL/BDS/IRN/QZS-GPS time offset (s)
* .Qr[] O rover position covarinace
* .stat O solution status (SOLQ_???)
* .ns O number of valid satellites
* .age O age of differential (s)
* .ratio O ratio factor for ambiguity validation
* rtk->rb[] IO base station position/velocity
* (I:relative mode,O:moving-base mode)
* rtk->nx I number of all states
* rtk->na I number of integer states
* rtk->ns O number of valid satellites in use
* rtk->tt O time difference between current and previous (s)
* rtk->x[] IO float states pre-filter and post-filter
* rtk->P[] IO float covariance pre-filter and post-filter
* rtk->xa[] O fixed states after AR
* rtk->Pa[] O fixed covariance after AR
* rtk->ssat[s] IO satellite {s+1} status
* .sys O system (SYS_???)
* .az [r] O azimuth angle (rad) (r=0:rover,1:base)
* .el [r] O elevation angle (rad) (r=0:rover,1:base)
* .vs [r] O data valid single (r=0:rover,1:base)
* .resp [f] O freq(f+1) pseudorange residual (m)
* .resc [f] O freq(f+1) carrier-phase residual (m)
* .vsat [f] O freq(f+1) data vaild (0:invalid,1:valid)
* .fix [f] O freq(f+1) ambiguity flag
* (0:nodata,1:float,2:fix,3:hold)
* .slip [f] O freq(f+1) cycle slip flag
* (bit8-7:rcv1 LLI, bit6-5:rcv2 LLI,
* bit2:parity unknown, bit1:slip)
* .lock [f] IO freq(f+1) carrier lock count
* .outc [f] IO freq(f+1) carrier outage count
* .slipc[f] IO freq(f+1) cycle slip count
* .rejc [f] IO freq(f+1) data reject count
* .gf IO geometry-free phase (L1-L2) (m)
* .gf2 IO geometry-free phase (L1-L5) (m)
* rtk->nfix IO number of continuous fixes of ambiguity
* rtk->neb IO bytes of error message buffer
* rtk->errbuf IO error message buffer
* rtk->tstr O time string for debug
* rtk->opt I processing options
* obsd_t *obs I observation data for an epoch
* obs[i].rcv=1:rover,2:reference
* sorted by receiver and satellte
* int n I number of observation data
* nav_t *nav I navigation messages
* return : status (0:no solution,1:valid solution)
* notes : before calling function, base station position rtk->sol.rb[] should
* be properly set for relative mode except for moving-baseline
*-----------------------------------------------------------------------------*/
extern int rtkpos(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav)
{
prcopt_t *opt=&rtk->opt;
sol_t solb={{0}};
gtime_t time;
int i,nu,nr;
char msg[128]="";
trace(3,"rtkpos : time=%s n=%d\n",time_str(obs[0].time,3),n);
trace(4,"obs=\n"); traceobs(4,obs,n);
/* set base staion position */
if (opt->refpos<=POSOPT_RINEX&&opt->mode!=PMODE_SINGLE&&
opt->mode!=PMODE_MOVEB) {
for (i=0;i<6;i++) rtk->rb[i]=i<3?opt->rb[i]:0.0;
}
/* count rover/base station observations */
for (nu=0;nu <n&&obs[nu ].rcv==1;nu++) ;
for (nr=0;nu+nr<n&&obs[nu+nr].rcv==2;nr++) ;
time=rtk->sol.time; /* previous epoch */
/* rover position by single point positioning */
if (!pntpos(obs,nu,nav,&rtk->opt,&rtk->sol,NULL,rtk->ssat,msg)) {
errmsg(rtk,"point pos error (%s)\n",msg);
if (!rtk->opt.dynamics) {
outsolstat(rtk);
return 0;
}
}
if (time.time != 0) rtk->tt = timediff(rtk->sol.time, time); opt->tt = rtk->tt;
/* single point positioning */
if (opt->mode==PMODE_SINGLE) {
outsolstat(rtk);
return 1;
}
/* suppress output of single solution */
if (!opt->outsingle) {
rtk->sol.stat=SOLQ_NONE;
}
/* precise point positioning */
if (opt->mode>=PMODE_PPP_KINEMA) {
pppos(rtk,obs,nu,nav);
outsolstat(rtk);
return 1;
}
/* check number of data of base station and age of differential */
if (nr==0) {
errmsg(rtk,"no base station observation data for rtk\n");
outsolstat(rtk);
return 1;
}
if (opt->mode==PMODE_MOVEB) { /* moving baseline */
/* estimate position/velocity of base station */
if (!pntpos(obs+nu,nr,nav,&rtk->opt,&solb,NULL,NULL,msg)) {
errmsg(rtk,"base station position error (%s)\n",msg);
return 0;
}
rtk->sol.age=(float)timediff(rtk->sol.time,solb.time);
if (fabs(rtk->sol.age)>TTOL_MOVEB) {
errmsg(rtk,"time sync error for moving-base (age=%.1f)\n",rtk->sol.age);
return 0;
}
for (i=0;i<6;i++) rtk->rb[i]=solb.rr[i];
/* time-synchronized position of base station */
for (i=0;i<3;i++) rtk->rb[i]+=rtk->rb[i+3]*rtk->sol.age;
}
else {
rtk->sol.age=(float)timediff(obs[0].time,obs[nu].time);
if (fabs(rtk->sol.age)>opt->maxtdiff) {
errmsg(rtk,"age of differential error (age=%.1f)\n",rtk->sol.age);
outsolstat(rtk);
return 1;
}
}
/* relative potitioning */
relpos(rtk,obs,nu,nr,nav);
outsolstat(rtk);
return 1;
}
从如上代码中可以看出,若是单点定位,则进行pntpos
函数之后,就直接输出结果:
/* rover position by single point positioning */
if (!pntpos(obs,nu,nav,&rtk->opt,&rtk->sol,NULL,rtk->ssat,msg)) {
errmsg(rtk,"point pos error (%s)\n",msg);
if (!rtk->opt.dynamics) {
outsolstat(rtk);
return 0;
}
}
if (time.time != 0) rtk->tt = timediff(rtk->sol.time, time); opt->tt = rtk->tt;
/* single point positioning */
if (opt->mode==PMODE_SINGLE) {
outsolstat(rtk);
return 1;
}
若是精密单点定位,则进行下面代码,即调用pppos
并输出结果。因此,rtkpos
在调用完pppos
后,就直接返回1
/* precise point positioning */
if (opt->mode>=PMODE_PPP_KINEMA) {
pppos(rtk,obs,nu,nav);
outsolstat(rtk);
return 1;
}
6.然后呢,调用rtkpos
的是procpos
函数;执行该部分代码,首先判断定位模式是否为静态;再利用rtkinit
函数,初始化PPP的各矩阵;接着在成功调用rtkpos
进行精密单点定位之后,就是输出结果了
/* process positioning -------------------------------------------------------*/
static void procpos(FILE *fp, const prcopt_t *popt, const solopt_t *sopt,
int mode)
{
gtime_t time={0};
sol_t sol={{0}};
rtk_t rtk;
obsd_t obs[MAXOBS*2]; /* for rover and base */
double rb[3]={0};
int i,nobs,n,solstatic,pri[]={6,1,2,3,4,5,1,6};
trace(3,"procpos : mode=%d\n",mode);
solstatic=sopt->solstatic&&
(popt->mode==PMODE_STATIC||popt->mode==PMODE_PPP_STATIC);
rtkinit(&rtk,popt);
rtcm_path[0]='\0';
while ((nobs=inputobs(obs,rtk.sol.stat,popt))>=0) {
/* exclude satellites */
for (i=n=0;i<nobs;i++) {
if ((satsys(obs[i].sat,NULL)&popt->navsys)&&
popt->exsats[obs[i].sat-1]!=1) obs[n++]=obs[i];
}
if (n<=0) continue;
/* carrier-phase bias correction */
if (!strstr(popt->pppopt,"-ENA_FCB")) {
corr_phase_bias_ssr(obs,n,&navs);
}
if (!rtkpos(&rtk,obs,n,&navs)) continue;
if (mode==0) { /* forward/backward */
if (!solstatic) {
outsol(fp,&rtk.sol,rtk.rb,sopt);
}
else if (time.time==0||pri[rtk.sol.stat]<=pri[sol.stat]) {
sol=rtk.sol;
for (i=0;i<3;i++) rb[i]=rtk.rb[i];
if (time.time==0||timediff(rtk.sol.time,time)<0.0) {
time=rtk.sol.time;
}
}
}
else if (!revs) { /* combined-forward */
if (isolf>=nepoch) return;
solf[isolf]=rtk.sol;
for (i=0;i<3;i++) rbf[i+isolf*3]=rtk.rb[i];
isolf++;
}
else { /* combined-backward */
if (isolb>=nepoch) return;
solb[isolb]=rtk.sol;
for (i=0;i<3;i++) rbb[i+isolb*3]=rtk.rb[i];
isolb++;
}
}
if (mode==0&&solstatic&&time.time!=0.0) {
sol.time=time;
outsol(fp,&sol,rb,sopt);
}
rtkfree(&rtk);
}
7.然后呢,调用procpos
的函数是execses
,主要部分代码为:
if (popt_.mode==PMODE_SINGLE||popt_.soltype==0) {
if ((fp=openfile(outfile))) {
procpos(fp,&popt_,sopt,0); /* forward */
fclose(fp);
}
}
else if (popt_.soltype==1) {
if ((fp=openfile(outfile))) {
revs=1; iobsu=iobsr=obss.n-1; isbs=sbss.n-1;
procpos(fp,&popt_,sopt,0); /* backward */
fclose(fp);
}
}
else { /* combined */
solf=(sol_t *)malloc(sizeof(sol_t)*nepoch);
solb=(sol_t *)malloc(sizeof(sol_t)*nepoch);
rbf=(double *)malloc(sizeof(double)*nepoch*3);
rbb=(double *)malloc(sizeof(double)*nepoch*3);
if (solf&&solb) {
isolf=isolb=0;
procpos(NULL,&popt_,sopt,1); /* forward */
revs=1; iobsu=iobsr=obss.n-1; isbs=sbss.n-1;
procpos(NULL,&popt_,sopt,1); /* backward */
/* combine forward/backward solutions */
if (!aborts&&(fp=openfile(outfile))) {
combres(fp,&popt_,sopt);
fclose(fp);
}
}
可以看出,该函数直接调用procpos
进行定位解算
8.然后呢,调用execses
函数的是execses_r
,而execses_r
会被execses_b
调用,最后调用的是postpos
函数,由于在前面几篇博文中给出了调用情况,这里不再赘述
9.最后,解算成功时,postpos
的返回值为0
RTKLIB精密单点定位部分的源码就大致介绍到这里啦,下一篇我们主要介绍RTKLIB用到的精密单点定位中的改正
相关文章
- 两列布局之左边固定宽度,右边自适应(绝对定位实现方法)
- 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
- 三点定位算法优化
- 手机卫士10-手机被盗后定位实现
- 记录一次现网问题定位-5月12号
- 大叔问题定位分享(45)hive任务udf函数偶尔报错
- 微信小程序----wx.getLocation(OBJECT) API在iOS关闭本机定位时,获取定位失败
- 快速定位Product assignment block里对应的修改逻辑使用的function module
- 基于遗传算法的配电网故障定位(Matlab代码实现)
- 分布式电源对配电网故障定位的影响(Python代码实现)
- 基于广义互相关的声源定位研究(Matlab代码实现)
- 面对锁等待难题,数仓如何实现问题的秒级定位和分析
- DevOps组织中应用架构师的新定位与实践
- css定位实现星级展示没有交互
- 【HTML+CSS】浅谈:相对定位与绝对定位
- 使用Windbg定位Windows C++程序中的内存泄露
- 使用Clumsy和Process Explorer定位软件高CPU占用问题
- Selenium自动化测试——Xpath定位
- 【2023全网最全最火教程】一文彻底学会Selenium元素定位
- 下班前1小时,整理了1000字selenium 定位总结
- vi/vim 编辑、搜索、查找、定位
- 【ASP.NET 进阶】根据IP地址进行百度地图定位
- 007:Mapbox GL实现地图地点搜索定位功能