本博文以单GPS系统为例,对相对定位进行一个概括描述
所用数据来自Curtin GNSS Research Centre;取基站CUT00的两台接收机的数据,进行零基线分析。
1、调用主函数:rnx2rtkp.c
2、调用后处理函数:postpos.c
3、处理基站信息:execses_b 位于 postpos.c
4、处理移动站信息:execses_r 位于 postpos.c
5、执行处理操作:execses 位于 postpos.c
从execses正式开始执行处理操作,这其中包括文件函数readobsnav,数据的处理函数antpos、procpos等
1、生成调试/trace文件,调取调试等级;
2、读取移动站、基准站观测文件、导航文件;
注:此时观测数据包含在obs_t结构体中,且已经按照rcv=1、2;卫星prn大小排序;
3、根据移动站的坐标固定方式、定位模式;分别确定移动站、基准站的坐标;
4、生成记录/stat文件,调取记录等级;
5、将相关的设置信息输出到.pos中,生成文件头;
6、根据设置:前向处理、后向处理、前后向处理;进入procpos中;
7、释放观测数据、导航数据结构体空间;
1、初始化 rtk 控制结构体
typedef struct { /* RTK control/result type */
sol_t sol; /* RTK solution */
double rb[6]; /* base position/velocity (ecef) (m|m/s) */
int nx,na; /* number of float states/fixed states */
double tt; /* time difference between current and previous (s) */
double *x, *P; /* float states and their covariance */
double *xa,*Pa; /* fixed states and their covariance */
int nfix; /* number of continuous fixes of ambiguity */
ambc_t ambc[MAXSAT]; /* ambibuity control */
ssat_t ssat[MAXSAT]; /* satellite status */
int neb; /* bytes in error message buffer */
char errbuf[MAXERRMSG]; /* error message buffer */
prcopt_t opt; /* processing options */
} rtk_t;
其中rtk_t结构体中,包含:
- sol_t:solution type
- ambc_t:ambiguity control type
- ssat_t:satellite status type
- prcopt_t:processing options type
2、执行inputobs函数,得到当前历元移动站、基准站分别的卫星数、
3、corr_phase_bias_fcb 载波偏差改正;
4、执行rtkpos 函数;
5、执行outsol函数,保存定位结果到.pos文件中
1、确定基站坐标
2、确定移动站坐标——单点定位方式求解!
3、执行relpos 函数;
4、输出 记录/stat文件;
1、计算当前历元移动站、基准站卫星位置、速度、钟差、钟漂/频差、方差(根据ura)、svh(根据星历中svh得出)
2、基准站非差残差;
以单频点L1为例:残差保存在y中;两行分别为:载波残差/m、伪距残差/m
4 y=
77528.250 77509.064 77511.620 77525.375 77530.118 77520.580 77520.092 77519.807 0.000 0.000 77522.390
77525.994 77526.380 77526.041 77526.977 77521.119 77522.576 77520.987 77528.206 0.000 0.000 77524.705
3、得到共视卫星;
注:将基准站卫星,将通过“高度角阈值”的卫星,作为共视卫星;
4、kalman 时间/状态更新 udstate
- udpos :kalman中状态更新方程、状态协方差方程更新;
- udion : 电离层状态、协方差更新;
- udtrop : 对流层状态、协方差更新;
- udrcvbias:
- udbias :更新单差模糊度状态、协方差;
5、移动站非差残差:
注:移动站位置为xp, matcpy(xp,rtk->x,rtk->nx,1);
6、双差
- 残差/v=【参考星(移动站非差残差 - 基准站非差残差)- 非参考星(移动站非差残差 - 基准站非差残差)】-【双差模糊度】
- H = -参考星站星单位矢量 + 非参考星站星单位矢量;移动站下
- H 参考星对应的列为1 ,非参考星对应的列为-1
- 保存伪距、载波残差;对新息阈值检测,卫星相关情况、相关值保存到
ssat_t中 resc、resp、rejc、vsat
typedef struct { /* satellite status type */ unsigned char sys; /* navigation system */ unsigned char vs; /* valid satellite flag single */ double azel[2]; /* azimuth/elevation angles {az,el} (rad) */ double resp[NFREQ]; /* residuals of pseudorange (m) */ double resc[NFREQ]; /* residuals of carrier-phase (m) */ unsigned char vsat[NFREQ]; /* valid satellite flag */ unsigned char snr [NFREQ]; /* signal strength (0.25 dBHz) */ unsigned char fix [NFREQ]; /* ambiguity fix flag (1:fix,2:float,3:hold) */ unsigned char slip[NFREQ]; /* cycle-slip flag */ unsigned char half[NFREQ]; /* half-cycle valid flag */ int lock [NFREQ]; /* lock counter of phase */ unsigned int outc [NFREQ]; /* obs outage counter of phase */ unsigned int slipc[NFREQ]; /* cycle-slip counter */ unsigned int rejc [NFREQ]; /* reject counter */ double gf; /* geometry-free phase L1-L2 (m) */ double gf2; /* geometry-free phase L1-L5 (m) */ double mw; /* MW-LC (m) */ double phw; /* phase windup (cycle) */ gtime_t pt[2][NFREQ]; /* previous carrier-phase time */ double ph[2][NFREQ]; /* previous carrier-phase observable (cycle) *///怎么保存的? } ssat_t;
- 计算站间单差方差
7、kalman 状态更新
Q=H'*P*H+R
K=P*H*Q^-
xp=x+K*v
Pp=(I-K*H')*P
得到实数解/浮点解
8、移动站非差残差
利用状态的实数解进行验后残差;
9、双差残差
利用状态的实数解进行验后残差;
10、浮点解有效性判断
通过判断,则将浮点解赋值到rtk结构体中;并更新ssat_t结构体中模糊度部分
/* update state and covariance matrix */
matcpy(rtk->x,xp,rtk->nx,1);
matcpy(rtk->P,Pp,rtk->nx,rtk->nx);
/* update ambiguity control struct */
rtk->sol.ns=0;
for (i=0;issat[sat[i]-1].vsat[f]) continue;
rtk->ssat[sat[i]-1].lock[f]++;
rtk->ssat[sat[i]-1].outc[f]=0;
if (f==0) rtk->sol.ns++; /* valid satellite count by L1 */
}
11、模糊度固定:宽巷-窄巷、三频、Lambda
以Lambda为例:
单差转双差:
y=D'*x,
Qy=D'*P*D
12、移动站非差残差
利用状态的固定解进行验后残差;
13、双差残差
利用状态的固定解进行验后残差;
14、固定解的有效性判断;
15、保存相关数据;
最后发现,这样写出来的效果远不如画一个流程图来得简单、明了!后期,记录博文,争取换一种思路!