目录
一、main函数流程总结
二、分析识别 -k 后如何配置
三、最后传参的数据文件处理方式
一、main函数流程总结
详解rtklib中main函数如何配置文件(上)-CSDN博客
在这片文章中讲解了rtklib中main函数的整个流程。
(1)通过两种方法给main函数传递参数,并放在 argv 这个指针数组中。
(2)初始化三个主要结构体及其它参数。
prcopt_t prcopt=prcopt_default; //process option 定位配置-默认值
solopt_t solopt=solopt_default; //solotion option 结果配置-默认值
filopt_t filopt={""}; //fileoption 文件配置-默认空
(3) 首先识别给main函数的参数中是否有 -k,如果有则根据 -k 后面的配置文件信息给 prcopt、solopt、filopt 这三个结构体赋值。下面这段代码也是本文第二点详细讲解的内容。
/* load options from configuration file */
for (i=1;i<argc;i++) {
if (!strcmp(argv[i],"-k")&&i+1<argc) {
resetsysopts();
if (!loadopts(argv[++i],sysopts)) return -1; //加载配置文件
getsysopts(&prcopt,&solopt,&filopt);
}
}
(4)随后再依次遍历传递的参数中是否有和代码中的 ‘ -××× ’对应,如果有则直接赋值给结构体中的变量,假如前面读取 -k 里面哪些信息有误,通过后面的代码还可以修改。
(5)通过postpos函数进入下一步。
//开始时间、结束时间、采样频率、process option、solution option、file option、输入文件、输入文件个数、输出文件
ret=postpos(ts,te,tint,0.0,&prcopt,&solopt,&filopt,infile,n,outfile,"","");
要记住最主要的这三个结构体prcopt、solopt、filopt都包含哪些成员。
typedef struct { /* 处理选项类型-配置定义 */
int mode; /* positioning mode (PMODE_???) */
int soltype; /* solution type (0:forward,1:backward,2:combined) */
int nf; /* number of frequencies (1:L1,2:L1+L2,3:L1+L2+L5) */
int navsys; /* navigation system */
double elmin; /* elevation mask angle (rad) */
snrmask_t snrmask; /* SNR mask */
int sateph; /* satellite ephemeris/clock (EPHOPT_???) */
int modear; /* AR mode (0:off,1:continuous,2:instantaneous,3:fix and hold,4:ppp-ar) */
int glomodear; /* GLONASS AR mode (0:off,1:on,2:auto cal,3:ext cal) */
int bdsmodear; /* BeiDou AR mode (0:off,1:on) */
int maxout; /* obs outage count to reset bias */
int minlock; /* min lock count to fix ambiguity */
int minfix; /* min fix count to hold ambiguity */
int armaxiter; /* max iteration to resolve ambiguity */
int ionoopt; /* ionosphere option (IONOOPT_???) */
int tropopt; /* troposphere option (TROPOPT_???) */
int dynamics; /* dynamics model (0:none,1:velociy,2:accel) */
int tidecorr; /* earth tide correction (0:off,1:solid,2:solid+otl+pole) */
int niter; /* number of filter iteration */
int codesmooth; /* code smoothing window size (0:none) */
int intpref; /* interpolate reference obs (for post mission) */
int sbascorr; /* SBAS correction options */
int sbassatsel; /* SBAS satellite selection (0:all) */
int rovpos; /* rover position for fixed mode */
int refpos; /* base position for relative mode */
/* (0:pos in prcopt, 1:average of single pos, */
/* 2:read from file, 3:rinex header, 4:rtcm pos) */
double eratio[NFREQ]; /* code/phase error ratio */
double err[5]; /* measurement error factor */
/* [0]:reserved */
/* [1-3]:error factor a/b/c of phase (m) */
/* [4]:doppler frequency (hz) */
double std[3]; /* initial-state std [0]bias,[1]iono [2]trop */
double prn[6]; /* process-noise std [0]bias,[1]iono [2]trop [3]acch [4]accv [5] pos */
double sclkstab; /* satellite clock stability (sec/sec) */
double thresar[8]; /* AR validation threshold */
double elmaskar; /* elevation mask of AR for rising satellite (deg) */
double elmaskhold; /* elevation mask to hold ambiguity (deg) */
double thresslip; /* slip threshold of geometry-free phase (m) */
double maxtdiff; /* max difference of time (sec) */
double maxinno; /* reject threshold of innovation (m) */
double maxgdop; /* reject threshold of gdop */
double baseline[2]; /* baseline length constraint {const,sigma} (m) */
double ru[3]; /* rover position for fixed mode {x,y,z} (ecef) (m) */
double rb[3]; /* base position for relative mode {x,y,z} (ecef) (m) */
char anttype[2][MAXANT]; /* antenna types {rover,base} */
double antdel[2][3]; /* antenna delta {{rov_e,rov_n,rov_u},{ref_e,ref_n,ref_u}} */
pcv_t pcvr[2]; /* receiver antenna parameters {rov,base} */
uint8_t exsats[MAXSAT]; /* excluded satellites (1:excluded,2:included) */
int maxaveep; /* max averaging epoches */
int initrst; /* initialize by restart */
int outsingle; /* output single by dgps/float/fix/ppp outage */
char rnxopt[2][256]; /* rinex options {rover,base} */
int posopt[6]; /* positioning options */
int syncsol; /* solution sync mode (0:off,1:on) */
double odisp[2][6*11]; /* ocean tide loading parameters {rov,base} */
int freqopt; /* disable L2-AR */
char pppopt[256]; /* ppp option */
} prcopt_t;
typedef struct { /* solution options type */
int posf; /* solution format (SOLF_???) */
int times; /* time system (TIMES_???) */
int timef; /* time format (0:sssss.s,1:yyyy/mm/dd hh:mm:ss.s) */
int timeu; /* time digits under decimal point */
int degf; /* latitude/longitude format (0:ddd.ddd,1:ddd mm ss) */
int outhead; /* output header (0:no,1:yes) */
int outopt; /* output processing options (0:no,1:yes) */
int outvel; /* output velocity options (0:no,1:yes) */
int datum; /* datum (0:WGS84,1:Tokyo) */
int height; /* height (0:ellipsoidal,1:geodetic) */
int geoid; /* geoid model (0:EGM96,1:JGD2000) */
int solstatic; /* solution of static mode (0:all,1:single) */
int sstat; /* solution statistics level (0:off,1:states,2:residuals) */
int trace; /* debug trace level (0:off,1-5:debug) */
double nmeaintv[2]; /* nmea output interval (s) (<0:no,0:all) */
/* nmeaintv[0]:gprmc,gpgga,nmeaintv[1]:gpgsv */
char sep[64]; /* field separator */
char prog[64]; /* program name */
double maxsolstd; /* max std-dev for solution output (m) (0:all) */
} solopt_t;
typedef struct { /* file options type */
char satantp[MAXSTRPATH]; /* satellite antenna parameters file */
char rcvantp[MAXSTRPATH]; /* receiver antenna parameters file */
char stapos [MAXSTRPATH]; /* station positions file */
char geoid [MAXSTRPATH]; /* external geoid data file */
char iono [MAXSTRPATH]; /* ionosphere data file */
char dcb [MAXSTRPATH]; /* dcb data file */
char eop [MAXSTRPATH]; /* eop data file */
char blq [MAXSTRPATH]; /* ocean tide loading blq file */
char tempdir[MAXSTRPATH]; /* ftp/http temporaly directory */
char geexe [MAXSTRPATH]; /* google earth exec file */
char solstat[MAXSTRPATH]; /* solution statistics file */
char trace [MAXSTRPATH]; /* debug trace file */
} filopt_t;
二、分析识别 -k 后如何配置
/* load options from configuration file */
for (i=1;i<argc;i++) {
if (!strcmp(argv[i],"-k")&&i+1<argc) {
resetsysopts();
if (!loadopts(argv[++i],sysopts)) return -1; //加载配置文件
getsysopts(&prcopt,&solopt,&filopt);
}
}
当在main函数参数中找到 -k后首先进入resetsysopts()函数,可以发现仍然是在给结构体初始化。但是要注意这里首先初始化的是prcopt_、solopt_、filopt_,和main函数中最终给postpos传参的prcopt、solopt、filopt不同。在这个for循环内其实都在给prcopt_、solopt_、filopt_这三个全局变量赋值,最后再通过 getsysopts(&prcopt,&solopt,&filopt);函数将prcopt_、solopt_、filopt_的值传给prcopt、solopt、filopt。
extern void resetsysopts(void)
{
int i,j;
trace(3,"resetsysopts:\n");
prcopt_=prcopt_default;
solopt_=solopt_default;
filopt_.satantp[0]='\0';
filopt_.rcvantp[0]='\0';
filopt_.stapos [0]='\0';
filopt_.geoid [0]='\0';
filopt_.dcb [0]='\0';
filopt_.blq [0]='\0';
filopt_.solstat[0]='\0';
filopt_.trace [0]='\0';
for (i=0;i<2;i++) antpostype_[i]=0;
elmask_=15.0;
elmaskar_=0.0;
elmaskhold_=0.0;
for (i=0;i<2;i++) for (j=0;j<3;j++) {
antpos_[i][j]=0.0;
}
exsats_[0] ='\0';
}
随后通过下述代码,来加载配置文件,即将你自定义的配置文件参数全部都传递给prcopt_、solopt_、filopt_这三个全局变量。
if (!loadopts(argv[++i],sysopts)) return -1; //加载配置文件
首先记住loadopts函数传递的两个参数,第一个是argv[++i],即 -k 后配置文件路径即自定义的配置文件,第二个参数是 sysopts ,它是一个结构体数组,声明的结构体以及内容如下:
typedef struct { /* option type */
const char *name; /* option name */
int format; /* option format (0:int,1:double,2:string,3:enum) */
void *var; /* pointer to option variable */
const char *comment; /* 选项注释/enum labels/unit */
} opt_t;
EXPORT opt_t sysopts[]={
{"pos1-posmode", 3, (void *)&prcopt_.mode, MODOPT }, //(void *)&prcopt_.mode,将结构体成员prcopt_.mode地址强制类型转换为void* 指针
{"pos1-frequency", 3, (void *)&prcopt_.nf, FRQOPT },
{"pos1-soltype", 3, (void *)&prcopt_.soltype, TYPOPT },
{"pos1-elmask", 1, (void *)&elmask_, "deg" },
{"pos1-snrmask_r", 3, (void *)&prcopt_.snrmask.ena[0],SWTOPT},
{"pos1-snrmask_b", 3, (void *)&prcopt_.snrmask.ena[1],SWTOPT},
{"pos1-snrmask_L1", 2, (void *)snrmask_[0], "" },
{"pos1-snrmask_L2", 2, (void *)snrmask_[1], "" },
{"pos1-snrmask_L5", 2, (void *)snrmask_[2], "" },
{"pos1-dynamics", 3, (void *)&prcopt_.dynamics, SWTOPT },
{"pos1-tidecorr", 3, (void *)&prcopt_.tidecorr, TIDEOPT},
{"pos1-ionoopt", 3, (void *)&prcopt_.ionoopt, IONOPT },
{"pos1-tropopt", 3, (void *)&prcopt_.tropopt, TRPOPT },
{"pos1-sateph", 3, (void *)&prcopt_.sateph, EPHOPT },
{"pos1-posopt1", 3, (void *)&prcopt_.posopt[0], SWTOPT },
{"pos1-posopt2", 3, (void *)&prcopt_.posopt[1], SWTOPT },
{"pos1-posopt3", 3, (void *)&prcopt_.posopt[2], PHWOPT },
{"pos1-posopt4", 3, (void *)&prcopt_.posopt[3], SWTOPT },
{"pos1-posopt5", 3, (void *)&prcopt_.posopt[4], SWTOPT },
{"pos1-posopt6", 3, (void *)&prcopt_.posopt[5], SWTOPT },
{"pos1-exclsats", 2, (void *)exsats_, "prn ..."},
{"pos1-navsys", 0, (void *)&prcopt_.navsys, NAVOPT },
{"pos2-armode", 3, (void *)&prcopt_.modear, ARMOPT },
{"pos2-gloarmode", 3, (void *)&prcopt_.glomodear, GAROPT },
{"pos2-bdsarmode", 3, (void *)&prcopt_.bdsmodear, SWTOPT },
{"pos2-arthres", 1, (void *)&prcopt_.thresar[0], "" },
{"pos2-arthres1", 1, (void *)&prcopt_.thresar[1], "" },
{"pos2-arthres2", 1, (void *)&prcopt_.thresar[2], "" },
{"pos2-arthres3", 1, (void *)&prcopt_.thresar[3], "" },
{"pos2-arthres4", 1, (void *)&prcopt_.thresar[4], "" },
{"pos2-arlockcnt", 0, (void *)&prcopt_.minlock, "" },
{"pos2-arelmask", 1, (void *)&elmaskar_, "deg" },
{"pos2-arminfix", 0, (void *)&prcopt_.minfix, "" },
{"pos2-armaxiter", 0, (void *)&prcopt_.armaxiter, "" },
{"pos2-elmaskhold", 1, (void *)&elmaskhold_, "deg" },
{"pos2-aroutcnt", 0, (void *)&prcopt_.maxout, "" },
{"pos2-maxage", 1, (void *)&prcopt_.maxtdiff, "s" },
{"pos2-syncsol", 3, (void *)&prcopt_.syncsol, SWTOPT },
{"pos2-slipthres", 1, (void *)&prcopt_.thresslip, "m" },
{"pos2-rejionno", 1, (void *)&prcopt_.maxinno, "m" },
{"pos2-rejgdop", 1, (void *)&prcopt_.maxgdop, "" },
{"pos2-niter", 0, (void *)&prcopt_.niter, "" },
{"pos2-baselen", 1, (void *)&prcopt_.baseline[0],"m" },
{"pos2-basesig", 1, (void *)&prcopt_.baseline[1],"m" },
{"out-solformat", 3, (void *)&solopt_.posf, SOLOPT },
{"out-outhead", 3, (void *)&solopt_.outhead, SWTOPT },
{"out-outopt", 3, (void *)&solopt_.outopt, SWTOPT },
{"out-outvel", 3, (void *)&solopt_.outvel, SWTOPT },
{"out-timesys", 3, (void *)&solopt_.times, TSYOPT },
{"out-timeform", 3, (void *)&solopt_.timef, TFTOPT },
{"out-timendec", 0, (void *)&solopt_.timeu, "" },
{"out-degform", 3, (void *)&solopt_.degf, DFTOPT },
{"out-fieldsep", 2, (void *) solopt_.sep, "" },
{"out-outsingle", 3, (void *)&prcopt_.outsingle, SWTOPT },
{"out-maxsolstd", 1, (void *)&solopt_.maxsolstd, "m" },
{"out-height", 3, (void *)&solopt_.height, HGTOPT },
{"out-geoid", 3, (void *)&solopt_.geoid, GEOOPT },
{"out-solstatic", 3, (void *)&solopt_.solstatic, STAOPT },
{"out-nmeaintv1", 1, (void *)&solopt_.nmeaintv[0],"s" },
{"out-nmeaintv2", 1, (void *)&solopt_.nmeaintv[1],"s" },
{"out-outstat", 3, (void *)&solopt_.sstat, STSOPT },
{"stats-eratio1", 1, (void *)&prcopt_.eratio[0], "" },
{"stats-eratio2", 1, (void *)&prcopt_.eratio[1], "" },
{"stats-errphase", 1, (void *)&prcopt_.err[1], "m" },
{"stats-errphaseel",1, (void *)&prcopt_.err[2], "m" },
{"stats-errphasebl",1, (void *)&prcopt_.err[3], "m/10km"},
{"stats-errdoppler",1, (void *)&prcopt_.err[4], "Hz" },
{"stats-stdbias", 1, (void *)&prcopt_.std[0], "m" },
{"stats-stdiono", 1, (void *)&prcopt_.std[1], "m" },
{"stats-stdtrop", 1, (void *)&prcopt_.std[2], "m" },
{"stats-prnaccelh", 1, (void *)&prcopt_.prn[3], "m/s^2"},
{"stats-prnaccelv", 1, (void *)&prcopt_.prn[4], "m/s^2"},
{"stats-prnbias", 1, (void *)&prcopt_.prn[0], "m" },
{"stats-prniono", 1, (void *)&prcopt_.prn[1], "m" },
{"stats-prntrop", 1, (void *)&prcopt_.prn[2], "m" },
{"stats-prnpos", 1, (void *)&prcopt_.prn[5], "m" },
{"stats-clkstab", 1, (void *)&prcopt_.sclkstab, "s/s" },
{"ant1-postype", 3, (void *)&antpostype_[0], POSOPT },
{"ant1-pos1", 1, (void *)&antpos_[0][0], "deg|m"},
{"ant1-pos2", 1, (void *)&antpos_[0][1], "deg|m"},
{"ant1-pos3", 1, (void *)&antpos_[0][2], "m|m" },
{"ant1-anttype", 2, (void *)prcopt_.anttype[0], "" },
{"ant1-antdele", 1, (void *)&prcopt_.antdel[0][0],"m" },
{"ant1-antdeln", 1, (void *)&prcopt_.antdel[0][1],"m" },
{"ant1-antdelu", 1, (void *)&prcopt_.antdel[0][2],"m" },
{"ant2-postype", 3, (void *)&antpostype_[1], POSOPT },
{"ant2-pos1", 1, (void *)&antpos_[1][0], "deg|m"},
{"ant2-pos2", 1, (void *)&antpos_[1][1], "deg|m"},
{"ant2-pos3", 1, (void *)&antpos_[1][2], "m|m" },
{"ant2-anttype", 2, (void *)prcopt_.anttype[1], "" },
{"ant2-antdele", 1, (void *)&prcopt_.antdel[1][0],"m" },
{"ant2-antdeln", 1, (void *)&prcopt_.antdel[1][1],"m" },
{"ant2-antdelu", 1, (void *)&prcopt_.antdel[1][2],"m" },
{"ant2-maxaveep", 0, (void *)&prcopt_.maxaveep ,"" },
{"ant2-initrst", 3, (void *)&prcopt_.initrst, SWTOPT },
{"misc-timeinterp", 3, (void *)&prcopt_.intpref, SWTOPT },
{"misc-sbasatsel", 0, (void *)&prcopt_.sbassatsel, "0:all"},
{"misc-rnxopt1", 2, (void *)prcopt_.rnxopt[0], "" },
{"misc-rnxopt2", 2, (void *)prcopt_.rnxopt[1], "" },
{"misc-pppopt", 2, (void *)prcopt_.pppopt, "" },
{"file-satantfile", 2, (void *)&filopt_.satantp, "" },
{"file-rcvantfile", 2, (void *)&filopt_.rcvantp, "" },
{"file-staposfile", 2, (void *)&filopt_.stapos, "" },
{"file-geoidfile", 2, (void *)&filopt_.geoid, "" },
{"file-ionofile", 2, (void *)&filopt_.iono, "" },
{"file-dcbfile", 2, (void *)&filopt_.dcb, "" },
{"file-eopfile", 2, (void *)&filopt_.eop, "" },
{"file-blqfile", 2, (void *)&filopt_.blq, "" },
{"file-tempdir", 2, (void *)&filopt_.tempdir, "" },
{"file-geexefile", 2, (void *)&filopt_.geexe, "" },
{"file-solstatfile",2, (void *)&filopt_.solstat, "" },
{"file-tracefile", 2, (void *)&filopt_.trace, "" },
{"",0,NULL,""} /* terminator */
};
随后进入loadopts函数, 我对这个函数内的代码做了详细的注释。其中file即自定义的配置文件,opts即指向 sysopts这个结构体数组的指针。只需要注意在函数的开始定义了一个char类型的字符数组 buff [2048],用来存放自定义配置文件中每一行的信息,所以说不管是名称、还是后面所跟的值都是以字符串的形式进行处理。
可以看到在loadopts这个函数内,使用了while循环,每次循环提取自定义配置文件内的一行信息进行处理,如下:
extern int loadopts(const char *file, opt_t *opts)
{ // file == 配置文件 opts == sysopts
FILE *fp;
opt_t *opt;
char buff[2048],*p;
int n=0;
trace(3,"loadopts: file=%s\n",file);
if (!(fp=fopen(file,"r"))) {
trace(1,"loadopts: options file open error (%s)\n",file);
return 0;
} //从文件中读取一行数据,并将其存储到 buff 缓冲区中
while (fgets(buff,sizeof(buff),fp)) {
n++;
chop(buff); //去除字符串中结尾的空白字符和 # 号后面的内容
if (buff[0]=='\0') continue;
if (!(p=strstr(buff,"="))) {//在字符串中查找指定子字符串的函数,返回该位置地址
fprintf(stderr,"invalid option %s (%s:%d)\n",buff,file,n);//被后续的参数依次填充并输出到标准错误流中
continue;
}
*p++='\0';
chop(buff); //buff == 每一行数据 opts == sysopts
if (!(opt=searchopt(buff,opts))) continue;
//找到这一行的名称和sysopts对应,返回的是sysopts[i]的结构体地址,并赋给结构体指针opt_t * opt
if (!str2opt(opt,p)) {
fprintf(stderr,"invalid option value %s (%s:%d)\n",buff,file,n);
continue;
}
}
fclose(fp);
return 1;
}
loadopts函数中除了打印trace信息总共调用了三个涉及处理配置文件的函数。
第一个函数是chop函数,主要目的是截断将提取的一行信息 # 后面的内容,只保留名称和值,如下图所示:
/* 去除字符串中结尾的空白字符和 # 号后面的内容 ------------------------------------------*/
static void chop(char *str) // str指向首字符地址
{
char *p;
if ((p=strchr(str,'#'))) *p='\0'; /*在字符串str中查找#的位置并将指针p指向#的位置,并将该位置的字符改为字符串结束标记 \0,从而截断字符串 */
for (p=str+strlen(str)-1;p>=str&&!isgraph((int)*p);p--) *p='\0';
} /*从字符串末尾开始向前遍历,找到第一个不是空白字符的位置,然后将该位置之后的字符截断(即将该位置之后的字符改为字符串结束标记 \0)。这里使用了 isgraph 函数来判断字符是否为可打印字符(不是空白字符)。*/
第二个函数是 opt = searchopt( buff,opts ),可以看到 searchopt 函数的第一个参数是提取的自定义配置文件的某一行的去除过注释,只保留名称和对应值的信息,第二个参数仍是sysopts这个包含所有配置信息的结构体数组,最终返回的值赋给同样是 opt_t 的结构体指针。
分析下述代码,不难发现,searchopt 函数其实是比较自定义配置文件的某一行的名称和rtklib中定义的 sysopts 结构体数组中的名称是否对应,即下图所示,如果在 sysopts 结构体数组中找到了这个名称,则返回 sysopts 结构体数组中这行所在位置的地址,然后用同样是 opt_t 类型的结构体指针 opt 指向 sysopts[ i ]。
extern opt_t *searchopt(const char *name, const opt_t *opts) //name==buff == 每一行数据
{ // opts == sysopts
int i;
trace(3,"searchopt: name=%s\n",name);
//strstr --- 从前面的字符串找后面的字符串
for (i=0;*opts[i].name;i++) {
if (strstr(opts[i].name,name)) return (opt_t *)(opts+i);//此时opts是结构体数组,+i 表示opts[i]
}
return NULL;
}
当找到这行的配置信息的名称后进入了下一个函数 str2opt, 这个函数的第一个参数是刚刚找到的sysopts 结构体数组中的对应位置,第二个参数 p 根据下图划线代码可以明显发现是自定义配置文件该行 = 号后面的值。
直接进入str2opt 函数,因为之间说过,提取的每一行信息都是以字符串的形式,所以这个函数的目的就是将=号后面的值进行形式转换,随后赋值给全局变量 prcopt_、solopt_、filopt_等。这样通过while循环将自定义配置文件内的所有信息全部提取好了,但此时还是在全局变量中,而不是main 函数定义的局部变量中。
/* string to option value ------------------------------------------------------
* convert string to option value
* args : opt_t *opt O option
* char *str I option value string
* return : status (1:ok,0:error)
*-----------------------------------------------------------------------------*/
extern int str2opt(opt_t *opt, const char *str) //该行sysopts结构体地址,‘=’后面值的地址
{
switch (opt->format) {
case 0: *(int *)opt->var=atoi(str); break; //字符串转换成整数
case 1: *(double *)opt->var=atof(str); break; //字符串转换成浮点数
case 2: strcpy((char *)opt->var,str); break;
case 3: return str2enum(str,opt->comment,(int *)opt->var);
default: return 0;
}
return 1;
}
所以还要来到 for 循环内最后一个函数,将这三个全局变量 prcopt_、solopt_、filopt_结构体的值传给了main 函数中的局部变量 prcopt、solopt、filopt。
在 getsysopts 函数中还有一个 buff2sysopts 函数,则是对读入自定义配置文件数据后的全局变量prcopt_、solopt_、filopt_等做进一步处理,比如频率,卫星系统prn号、坐标转换等,暂时没有细看。
/* system options buffer to options ------------------------------------------*/
static void buff2sysopts(void)
{
double pos[3],*rr;
char buff[1024],*p,*id;
int i,j,sat,*ps;
//角度转弧度
prcopt_.elmin =elmask_ *D2R;
prcopt_.elmaskar =elmaskar_ *D2R;
prcopt_.elmaskhold=elmaskhold_*D2R;
for (i=0;i<2;i++) {
ps=i==0?&prcopt_.rovpos:&prcopt_.refpos;
rr=i==0?prcopt_.ru:prcopt_.rb;
if (antpostype_[i]==0) { /* lat/lon/hgt */
*ps=0;
pos[0]=antpos_[i][0]*D2R;
pos[1]=antpos_[i][1]*D2R;
pos[2]=antpos_[i][2];
pos2ecef(pos,rr);
}
else if (antpostype_[i]==1) { /* xyz-ecef */
*ps=0;
rr[0]=antpos_[i][0];
rr[1]=antpos_[i][1];
rr[2]=antpos_[i][2];
}
else *ps=antpostype_[i]-1;
}
/* excluded satellites */
for (i=0;i<MAXSAT;i++) prcopt_.exsats[i]=0;
if (exsats_[0]!='\0') {
strcpy(buff,exsats_);
for (p=strtok(buff," ");p;p=strtok(NULL," ")) { //strtok - 将字符串分割,返回子字符串
if (*p=='+') id=p+1; else id=p;
if (!(sat=satid2no(id))) continue;
prcopt_.exsats[sat-1]=*p=='+'?2:1;
}
}
/* snrmask */ //频率
for (i=0;i<NFREQ;i++) {
for (j=0;j<9;j++) prcopt_.snrmask.mask[i][j]=0.0;
strcpy(buff,snrmask_[i]);
for (p=strtok(buff,","),j=0;p&&j<9;p=strtok(NULL,",")) {
prcopt_.snrmask.mask[i][j++]=atof(p);
}
}
/* number of frequency (4:L1+L5) */
if (prcopt_.nf==4) {
prcopt_.nf=3;
prcopt_.freqopt=1;
}
}
三、最后传参的数据文件处理方式
输出 .pos文件路径:在识别 -o 后,直接 char* outfile指向了路径字符串的首地址。
而传参中的观测文件和星历文件是放在了最后,全部放在了infile这个指针数组中。