RTKLIB专题学习(四)—单点定位实现初识(二)
今天我们来继续学习RTKLIB中单点定位的调用情况,上一篇在这里:RTKLIB专题学习(四)—单点定位实现初识(一)
1.上篇说到了调用procpos
的函数是execses
;execses
中调用的函数有readtec
读取电离层数据文件函数;readerp
读取erp数据文件函数;readobsnav
读取观测值和导航文件函数;readdcb
读取DCB文件函数;setpcv
设置天线参数函数;readotl
读取海洋潮汐数据文件函数
2.然后呢,调用execses
函数的是execses_r
函数,该函数是为每一个接收机执行处理的部分
/* execute processing session for each rover ---------------------------------*/
static int execses_r(gtime_t ts, gtime_t te, double ti, const prcopt_t *popt,
const solopt_t *sopt, const filopt_t *fopt, int flag,
char **infile, const int *index, int n, char *outfile,
const char *rov)
{
gtime_t t0={0};
int i,stat=0;
char *ifile[MAXINFILE],ofile[1024],*rov_,*p,*q,s[64]="";
trace(3,"execses_r: n=%d outfile=%s\n",n,outfile);
for (i=0;i<n;i++) if (strstr(infile[i],"%r")) break;
if (i<n) { /* include rover keywords */
if (!(rov_=(char *)malloc(strlen(rov)+1))) return 0;
strcpy(rov_,rov);
for (i=0;i<n;i++) {
if (!(ifile[i]=(char *)malloc(1024))) {
free(rov_); for (;i>=0;i--) free(ifile[i]);
return 0;
}
}
for (p=rov_;;p=q+1) { /* for each rover */
if ((q=strchr(p,' '))) *q='\0';
if (*p) {
strcpy(proc_rov,p);
if (ts.time) time2str(ts,s,0); else *s='\0';
if (checkbrk("reading : %s",s)) {
stat=1;
break;
}
for (i=0;i<n;i++) reppath(infile[i],ifile[i],t0,p,"");
reppath(outfile,ofile,t0,p,"");
/* execute processing session */
stat=execses(ts,te,ti,popt,sopt,fopt,flag,ifile,index,n,ofile);
}
if (stat==1||!q) break;
}
free(rov_); for (i=0;i<n;i++) free(ifile[i]);
}
else {
/* execute processing session */
stat=execses(ts,te,ti,popt,sopt,fopt,flag,infile,index,n,outfile);
}
return stat;
}
3.然后呢,调用execses_r
的是execses_b
,该部分是执行基站的处理,没有基站就直接处理接收机的文件
/* post-processing positioning -------------------------------------------------
* post-processing positioning
* args : gtime_t ts I processing start time (ts.time==0: no limit)
* : gtime_t te I processing end time (te.time==0: no limit)
* double ti I processing interval (s) (0:all)
* double tu I processing unit time (s) (0:all)
* prcopt_t *popt I processing options
* solopt_t *sopt I solution options
* filopt_t *fopt I file options
* char **infile I input files (see below)
* int n I number of input files
* char *outfile I output file ("":stdout, see below)
* char *rov I rover id list (separated by " ")
* char *base I base station id list (separated by " ")
* return : status (0:ok,0>:error,1:aborted)
* notes : input files should contain observation data, navigation data, precise
* ephemeris/clock (optional), sbas log file (optional), ssr message
* log file (optional) and tec grid file (optional). only the first
* observation data file in the input files is recognized as the rover
* data.
*
* the type of an input file is recognized by the file extention as ]
* follows:
* .sp3,.SP3,.eph*,.EPH*: precise ephemeris (sp3c)
* .sbs,.SBS,.ems,.EMS : sbas message log files (rtklib or ems)
* .rtcm3,.RTCM3 : ssr message log files (rtcm3)
* .*i,.*I : tec grid files (ionex)
* others : rinex obs, nav, gnav, hnav, qnav or clock
*
* inputs files can include wild-cards (*). if an file includes
* wild-cards, the wild-card expanded multiple files are used.
*
* inputs files can include keywords. if an file includes keywords,
* the keywords are replaced by date, time, rover id and base station
* id and multiple session analyses run. refer reppath() for the
* keywords.
*
* the output file can also include keywords. if the output file does
* not include keywords. the results of all multiple session analyses
* are output to a single output file.
*
* ssr corrections are valid only for forward estimation.
*-----------------------------------------------------------------------------*/
extern int postpos(gtime_t ts, gtime_t te, double ti, double tu,
const prcopt_t *popt, const solopt_t *sopt,
const filopt_t *fopt, char **infile, int n, char *outfile,
const char *rov, const char *base)
{
gtime_t tts,tte,ttte;
double tunit,tss;
int i,j,k,nf,stat=0,week,flag=1,index[MAXINFILE]={0};
char *ifile[MAXINFILE],ofile[1024],*ext;
trace(3,"postpos : ti=%.0f tu=%.0f n=%d outfile=%s\n",ti,tu,n,outfile);
/* open processing session */
if (!openses(popt,sopt,fopt,&navs,&pcvss,&pcvsr)) return -1;
if (ts.time!=0&&te.time!=0&&tu>=0.0) {
if (timediff(te,ts)<0.0) {
showmsg("error : no period");
closeses(&navs,&pcvss,&pcvsr);
return 0;
}
for (i=0;i<MAXINFILE;i++) {
if (!(ifile[i]=(char *)malloc(1024))) {
for (;i>=0;i--) free(ifile[i]);
closeses(&navs,&pcvss,&pcvsr);
return -1;
}
}
if (tu==0.0||tu>86400.0*MAXPRCDAYS) tu=86400.0*MAXPRCDAYS;
settspan(ts,te);
tunit=tu<86400.0?tu:86400.0;
tss=tunit*(int)floor(time2gpst(ts,&week)/tunit);
for (i=0;;i++) { /* for each periods */
tts=gpst2time(week,tss+i*tu);
tte=timeadd(tts,tu-DTTOL);
if (timediff(tts,te)>0.0) break;
if (timediff(tts,ts)<0.0) tts=ts;
if (timediff(tte,te)>0.0) tte=te;
strcpy(proc_rov ,"");
strcpy(proc_base,"");
if (checkbrk("reading : %s",time_str(tts,0))) {
stat=1;
break;
}
for (j=k=nf=0;j<n;j++) {
ext=strrchr(infile[j],'.');
if (ext&&(!strcmp(ext,".rtcm3")||!strcmp(ext,".RTCM3"))) {
strcpy(ifile[nf++],infile[j]);
}
else {
/* include next day precise ephemeris or rinex brdc nav */
ttte=tte;
if (ext&&(!strcmp(ext,".sp3")||!strcmp(ext,".SP3")||
!strcmp(ext,".eph")||!strcmp(ext,".EPH"))) {
ttte=timeadd(ttte,3600.0);
}
else if (strstr(infile[j],"brdc")) {
ttte=timeadd(ttte,7200.0);
}
nf+=reppaths(infile[j],ifile+nf,MAXINFILE-nf,tts,ttte,"","");
}
while (k<nf) index[k++]=j;
if (nf>=MAXINFILE) {
trace(2,"too many input files. trancated\n");
break;
}
}
if (!reppath(outfile,ofile,tts,"","")&&i>0) flag=0;
/* execute processing session */
stat=execses_b(tts,tte,ti,popt,sopt,fopt,flag,ifile,index,nf,ofile,
rov,base);
if (stat==1) break;
}
for (i=0;i<MAXINFILE;i++) free(ifile[i]);
}
else if (ts.time!=0) {
for (i=0;i<n&&i<MAXINFILE;i++) {
if (!(ifile[i]=(char *)malloc(1024))) {
for (;i>=0;i--) free(ifile[i]);
return -1;
}
reppath(infile[i],ifile[i],ts,"","");
index[i]=i;
}
reppath(outfile,ofile,ts,"","");
/* execute processing session */
stat=execses_b(ts,te,ti,popt,sopt,fopt,1,ifile,index,n,ofile,rov,
base);
for (i=0;i<n&&i<MAXINFILE;i++) free(ifile[i]);
}
else {
for (i=0;i<n;i++) index[i]=i;
/* execute processing session */
stat=execses_b(ts,te,ti,popt,sopt,fopt,1,infile,index,n,outfile,rov,
base);
}
/* close processing session */
closeses(&navs,&pcvss,&pcvsr);
return stat;
}
4.最后呢,就是主函数调用postpos啦,主函数需要自己写出来,网络上有很多,这里面我把我的给大家发出来:
/* show message --------------------------------------------------------------*/
extern int showmsg(const char* format, ...)
{
va_list arg;
va_start(arg, format); vfprintf(stderr, format, arg); va_end(arg);
fprintf(stderr, "\r");
return 0;
}
extern void settspan(gtime_t ts, gtime_t te) {}
extern void settime(gtime_t time) {}
/* print help ----------------------------------------------------------------*/
static void printhelp(void)
{
int i;
for (i = 0; i < (int)(sizeof(help) / sizeof(*help)); i++) fprintf(stderr, "%s\n", help[i]);
exit(0);
}
/* rnx2rtkp main -------------------------------------------------------------*/
int main(int argc, char** argv)
{
int i, n, ret,x;
double tint = 0; /* 求解时间间隔(0:默认) */
gtime_t ts = { 0 }, te = { 0 }; /* 历元时段始末控制变量 */
char* infile[MAXFILE], outfile[MAXSTRPATH] = { '\0' };
char resultpath[MAXSTRPATH] = "E:\\rtklib\\rtklib-test1\\202202\\"; /* 结果输出路径 */
char sep = (char)FILEPATHSEP;
prcopt_t prcopt = prcopt_default; /* 默认处理选项设置 */
solopt_t solopt = solopt_default; /* 默认求解格式设置 */
sol_t solt;
filopt_t filopt = { /* 参数文件路径设置 */
"E:\\rtklib\\rtklib-test1\\data\\igs14.atx", /* 卫星天线参数文件 */
"", /* 接收机天线参数文件 */
"", /* 测站位置文件 */
"", /* 扩展大地水准面数据文件 */
"", /* 电离层数据文件 */
"", /* DCB数据文件 */
"", /* 地球自转参数文件 */
"", /* 海洋潮汐负荷文件 */
};
char infile_[MAXFILE][MAXSTRPATH] = {
"E:\\rtklib\\rtklib-test1\\202202\\AJAC00FRA_R_20220020000_01D_30S_MO.21o",
"E:\\rtklib\\rtklib-test1\\202202\\BRDC00IGS_R_20220020000_01D_MN.rnx ",
"",
"",
"",
"",
"",
""
};
long t1, t2;
double eps[] = { 2022,1,2,0,0,0 }, epe[] = { 2022,1,3,0,0,0 }; /* 设置计算的历元时段 */
ts = epoch2time(eps); te = epoch2time(epe);
for (i = 0, n = 0; i < MAXFILE; i++)
if (strcmp(infile_[i], "")) infile[n++] = &infile_[i][0];
sprintf(outfile, "%s%c", resultpath, sep);//设置输出路径
/* 自定义求解格式 --------------------------------------------------------*/
solopt.posf = SOLF_XYZ; /* 选择输出的坐标格式,经纬度或是XYZ坐标等 */
solopt.times = TIMES_GPST; /* 控制输出解的时间系统类型 */
solopt.degf = 0; /* 输出经纬度格式(0:°, 1:°′″) */
solopt.outhead = 1; /* 是否输出头文件(0:否,1:是) */
solopt.outopt = 1; /* 是否输出prcopt变量(0:否,1:是) */
solopt.height = 1; /* 高程(0:椭球高,1:大地高) */
solopt.sstat = 2;
/* 自定义处理选项设置-PPP ----------------------------------------------------*/
//prcopt.mode = PMODE_PPP_STATIC; /* PPP静态处理 */
//prcopt.modear = 4; /* 求解模糊度类型 */
//prcopt.sateph = EPHOPT_PREC; /* 使用精密星历 */
//prcopt.ionoopt = IONOOPT_IFLC; /* 使用双频消电离层组合模型 */
/* 自定义处理选项设置-SPP ----------------------------------------------------*/
prcopt.mode = PMODE_SINGLE; /* SPP动态处理 */
prcopt.modear = 0; /* 求解模糊度类型 */
prcopt.sateph = EPHOPT_BRDC; /* 使用广播星历 */
prcopt.ionoopt = IONOOPT_BRDC; /* 使用广播电离层参数 */
prcopt.tropopt = TROPOPT_EST; /* 使用对流层天顶延迟估计模型 */
prcopt.tidecorr = 0; /* 地球潮汐改正选项(0:关闭,1:固体潮,2:固体潮+?+极移) */
prcopt.posopt[0] = 0; /* 卫星天线模型 */
prcopt.posopt[1] = 0; /* 接收机天线模型 */
prcopt.posopt[2] = 0; /* 相位缠绕改正 */
prcopt.posopt[3] = 0; /* 排除掩星 */
prcopt.posopt[4] = 0; /* 求解接收机坐标出错后的检查选项 */
prcopt.navsys = SYS_GPS|SYS_CMP; /* 处理的导航系统 */
sprintf(outfile, "%s%cAJAC-spp-kf1.pos", resultpath, sep); /* 输出结果名称 */
//prcopt.nf = 2; /* 参与计算的载波频率个数 */
prcopt.elmin = 10.0 * D2R;/* 卫星截止高度角 */
prcopt.soltype = 0; /* 求解类型(0:向前滤波,1:向后滤波,2:混合滤波) */
/*rtk*/
solt.stat = SOLQ_SINGLE;
t1 = clock();
ret = postpos(ts, te, tint, 0.0, &prcopt, &solopt, &filopt, infile, n, outfile, "", "");
t2 = clock();
if (!ret) fprintf(stderr, "%40s\r", "");
printf("\n * The total time for running the program: %6.3f seconds\n%c", (double)(t2 - t1) / CLOCKS_PER_SEC, '\0');
printf("Press any key to exit!\n");
getchar();
return ret;
}
单点定位实现的初始部分结束啦,接下来就进入单点定位的进阶部分!