目录
Step1:如何给rtklib中的主函数 rnx2rtkp 传参
Step2:给配置选项结构体赋默认值
Step3:继续配置
Step4:寻找 main 函数参数中的 -k
Step5:依次遍历参数
Step1:如何给rtklib中的主函数 rnx2rtkp 传参
关于C语言中 main 函数如何传参在这篇文章里有详细讲解,如果不懂请先进行学习。
详解main函数参数argc、argv及如何传参-CSDN博客
要想在代码中运行 rtklib 进行定位就必须先进行文件配置,就是通过选项设置决定要进行哪种定位模式、文件的输入输出路径以及中间处理参数等,说白了等价于设置 rtkpost 中的Options 选项,只不过通过代码的形式。
关于如何给 rtklib 主函数传参在 rtklib_manual 的 A.2 RNX2RTKP 部分有详细说明,我把它翻译了出来如下:
以单点定位为例,那么给 main 函数传参时要进行如下格式输入(具体需求参照上面options,假如 -p 后面有模式选项,那么-p 后就要输入对应数字,-u 后没要求输入那么在传参时只输入 -u即可):(考虑到转义字符,假如想表示路径 C:\myfolder\myfile.txt
,在输入时时,需要写成 "C:\\myfolder\\myfile.txt"
)
-p 0 -x 3 -m 10 -o 输出文件路径 o文件路径 n文件路径
这是我的配置路径:
在主函数直接F11进行调试,可以发现总共传入12个参数,且 argv 这个指针数组的第一个指针 argv[0] 始终指向Debug中可执行程序的地址。其他指针依次指向输入的参数,且输入的参数以空格分隔,每个参数代表一个字符串,后续的代码就是识别这些字符串并进行配置处理。
Step2:给配置选项结构体赋默认值
主要给 prcopt_t (process option 定位配置)、solopt_t (solotion option 结果配置)、filopt_t(fileoption 文件配置)、gtime_t (时间)结构体设置初始默认值。
源代码如下:
prcopt_t prcopt=prcopt_default; //process option 定位配置-默认值
solopt_t solopt=solopt_default; //solotion option 结果配置-默认值
filopt_t filopt={""}; //fileoption 文件配置-默认空
gtime_t ts={0},te={0};
double tint=0.0,es[]={2000,1,1,0,0,0},ee[]={2000,12,31,23,59,59},pos[3];
各结构体定义如下:
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;
typedef struct {
time_t time; //标准时间整数的秒数
double sec; //非整数秒数的小数部分
} gtime_t;
上述是几个主要配置结构体的声明,第一行代码 prcopt_t prcopt = prcopt_default; 将提前设置好的默认参数 prcopt_default 赋值给 prcopt_t 类型的结构体 prcopt ,里面包含了各项的基础配置,prcopt_default 的默认参数设置如下:
const prcopt_t prcopt_default={ /* defaults processing options */
PMODE_SINGLE,0,2,SYS_GPS, /* mode,soltype,nf,navsys */
15.0*D2R,{{0,0}}, /* elmin,snrmask */
0,1,1,1, /* sateph,modear,glomodear,bdsmodear */
5,0,10,1, /* maxout,minlock,minfix,armaxiter */
0,0,0,0, /* estion,esttrop,dynamics,tidecorr */
1,0,0,0,0, /* niter,codesmooth,intpref,sbascorr,sbassatsel */
0,0, /* rovpos,refpos */
{100.0,100.0}, /* eratio[] */
{100.0,0.003,0.003,0.0,1.0}, /* err[] */
{30.0,0.03,0.3}, /* std[] */
{1E-4,1E-3,1E-4,1E-1,1E-2,0.0}, /* prn[] */
5E-12, /* sclkstab */
{3.0,0.9999,0.25,0.1,0.05}, /* thresar */
0.0,0.0,0.05, /* elmaskar,almaskhold,thresslip */
30.0,30.0,30.0, /* maxtdif,maxinno,maxgdop */
{0},{0},{0}, /* baseline,ru,rb */
{"",""}, /* anttype */
{{0}},{{0}},{0} /* antdel,pcv,exsats */
};
第二行代码 solopt_t solopt=solopt_default;同理,是对输出文件格式的配置,默认参数如下:
const solopt_t solopt_default={ /* defaults solution output options */
SOLF_LLH,TIMES_GPST,1,3, /* posf,times,timef,timeu */
0,1,0,0,0,0,0, /* degf,outhead,outopt,outvel,datum,height,geoid */
0,0,0, /* solstatic,sstat,trace */
{0.0,0.0}, /* nmeaintv */
" ","" /* separator/program name */
};
第三行第四行代码设置为空,因为需要接下来读取文件路径,进行处理,ts、te 代表观测文件中的起止时间,先设置为0。
filopt_t filopt={""}; //fileoption 文件配置-默认空
gtime_t ts={0},te={0};
第五行代码如下,tint 表示采样频率,es、ee 表示以日历形式的时间,后续会转换成秒的形式赋值给ts,pos是用来存储 xyz 坐标的数组。
double tint=0.0,es[]={2000,1,1,0,0,0},ee[]={2000,12,31,23,59,59},pos[3];
Step3:继续配置
这里 prcopt 和 solopt 结构体是需要重点关注的,因为二者内包含了全部的处理选项以及文件输出格式,后续的定位解算与输出也是根据这两个结构体的内容进行处理。
下面代码定义了几个变量,设置了输入文件个数最大值为16,然后继续对 prcopt结构体内容进行设置。
int i,j,n,ret; //定义变量
char *infile[MAXFILE],*outfile="",*p; //MAXFILE == 16
//设置默认值
prcopt.mode =PMODE_KINEMA;
prcopt.navsys=0;
prcopt.refpos=1;
prcopt.glomodear=1;
solopt.timef=0;
sprintf(solopt.prog ,"%s ver.%s %s",PROGNAME,VER_RTKLIB,PATCH_LEVEL);
sprintf(filopt.trace,"%s.trace",PROGNAME);
Step4:寻找 main 函数参数中的 -k
首先了解一下什么是配置文件,从rtklib manual中可知,-k 对应的就是配置文件,如果输入 -k 作为参数,那么后面应该对应配置文件的路径。
配置文件所在的路径如下:
以文本文件形式打开后可以发现配置文件中详细记录了所有选项参数,所以说假如我们在配置文件中将各个参数设置好后,就不需要在给main函数传递参数时输入别的配置符号了,只需要输入
-k 配置文件路径 -o 输出文件路径 o文件路径 n文件路径
/* 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);
}
}
接下来就是开始对传递的参数进行解读,argc 为参数的个数,用 for 循环依次遍历参数。
分析 if 中的判断语句,首先是通过strcmp函数依次比较 argv[ i ]中的参数是否与 -k 相同,如果相同则返回 0 ,由于0代表假,所以前面加了 !,这样就找到了 -k 所在的位置。同时还要保证 -k后面所跟配置文件路径这个参数的位置是否小于总参数的个数。
(!strcmp(argv[i],"-k")&&i+1<argc)
当找到参数中的 -k 后,进入函数 resetsysopts();中,该函数代码如下,可以看到其作用还是初始值的设定,为后续读取配置文件做准备。
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';
}
然后仍然是一个判断语句,可以看到 loadopts函数中传递了两个参数,第一个参数是 -k 后面的字符串即对应的配置文件的路径,ctrl + 左键 打开第二个参数 sysopts。
if (!loadopts(argv[++i],sysopts)) return -1; //加载配置文件
可以发现它是一个结构体数组,总共有四列,同时其内容与配置文件的内容相同。
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 */
};
找到这个结构体 opt_t 的声明,可以发现上述结构体数组中第一列为选项名称,第二列是参数的格式,决定着参数是数字、字符串还是枚举类型,第三列将每个地址转换成void类型的指针,第四列只是一些说明,并不重要。
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; /* option comment/enum labels/unit */
} opt_t;
通过上述可以发现这行代码中的 loadopts 函数就是用来加载 -k 后面配置文件路径下的配置文件的内容,然后读取。
if (!loadopts(argv[++i],sysopts)) return -1; //加载配置文件
getsysopts(&prcopt,&solopt,&filopt);
Step5:依次遍历参数
for (i=1,n=0;i<argc;i++) {
if (!strcmp(argv[i],"-o")&&i+1<argc) outfile=argv[++i];
else if (!strcmp(argv[i],"-ts")&&i+2<argc) {
sscanf(argv[++i],"%lf/%lf/%lf",es,es+1,es+2);
sscanf(argv[++i],"%lf:%lf:%lf",es+3,es+4,es+5);
ts=epoch2time(es);
}
else if (!strcmp(argv[i],"-te")&&i+2<argc) {
sscanf(argv[++i],"%lf/%lf/%lf",ee,ee+1,ee+2);
sscanf(argv[++i],"%lf:%lf:%lf",ee+3,ee+4,ee+5);
te=epoch2time(ee);
}
else if (!strcmp(argv[i],"-ti")&&i+1<argc) tint=atof(argv[++i]); //atof-字符串转double
else if (!strcmp(argv[i],"-k")&&i+1<argc) {++i; continue;}
else if (!strcmp(argv[i],"-p")&&i+1<argc) prcopt.mode=atoi(argv[++i]);
else if (!strcmp(argv[i],"-f")&&i+1<argc) prcopt.nf=atoi(argv[++i]);
else if (!strcmp(argv[i],"-sys")&&i+1<argc) {
for (p=argv[++i];*p;p++) {
switch (*p) {
case 'G': prcopt.navsys|=SYS_GPS;
case 'R': prcopt.navsys|=SYS_GLO;
case 'E': prcopt.navsys|=SYS_GAL;
case 'J': prcopt.navsys|=SYS_QZS;
case 'C': prcopt.navsys|=SYS_CMP;
case 'I': prcopt.navsys|=SYS_IRN;
}
if (!(p=strchr(p,','))) break;
}
}
else if (!strcmp(argv[i],"-m")&&i+1<argc) prcopt.elmin=atof(argv[++i])*D2R; // -m 后面跟了一个值读取
else if (!strcmp(argv[i],"-v")&&i+1<argc) prcopt.thresar[0]=atof(argv[++i]);
else if (!strcmp(argv[i],"-s")&&i+1<argc) strcpy(solopt.sep,argv[++i]);
else if (!strcmp(argv[i],"-d")&&i+1<argc) solopt.timeu=atoi(argv[++i]);
else if (!strcmp(argv[i],"-b")) prcopt.soltype=1; // -b 后面没有值读取
else if (!strcmp(argv[i],"-c")) prcopt.soltype=2;
else if (!strcmp(argv[i],"-i")) prcopt.modear=2;
else if (!strcmp(argv[i],"-h")) prcopt.modear=3;
else if (!strcmp(argv[i],"-t")) solopt.timef=1;
else if (!strcmp(argv[i],"-u")) solopt.times=TIMES_UTC;
else if (!strcmp(argv[i],"-e")) solopt.posf=SOLF_XYZ;
else if (!strcmp(argv[i],"-a")) solopt.posf=SOLF_ENU;
else if (!strcmp(argv[i],"-n")) solopt.posf=SOLF_NMEA;
else if (!strcmp(argv[i],"-g")) solopt.degf=1;
else if (!strcmp(argv[i],"-r")&&i+3<argc) {
prcopt.refpos=prcopt.rovpos=0;
for (j=0;j<3;j++) prcopt.rb[j]=atof(argv[++i]);
matcpy(prcopt.ru,prcopt.rb,3,1);
}
else if (!strcmp(argv[i],"-l")&&i+3<argc) {
prcopt.refpos=prcopt.rovpos=0;
for (j=0;j<3;j++) pos[j]=atof(argv[++i]);
for (j=0;j<2;j++) pos[j]*=D2R;
pos2ecef(pos,prcopt.rb);
matcpy(prcopt.ru,prcopt.rb,3,1);
}
else if (!strcmp(argv[i],"-y")&&i+1<argc) solopt.sstat=atoi(argv[++i]);
else if (!strcmp(argv[i],"-x")&&i+1<argc) solopt.trace=atoi(argv[++i]);
else if (*argv[i]=='-') printhelp();
else if (n<MAXFILE) infile[n++]=argv[i];
}
if (!prcopt.navsys) {
prcopt.navsys=SYS_GPS|SYS_GLO;
}
if (n<=0) {
showmsg("error : no input file");
return -2;
}
接下来的代码仍然是继续匹配 main 参数,最终读取的所有配置都存在了prcopt 、solopt 结构体中,为后续函数传参做好配置准备。
通过上述代码可以发现,即使通过 -k 读取配置文件后,仍可以通过传参时对指定参数进行更改。
最后调用postpos函数开始处理数据。
//开始时间、结束时间、采样频率、process option、solution option、file option、输入文件、输入文件个数、输出文件
ret=postpos(ts,te,tint,0.0,&prcopt,&solopt,&filopt,infile,n,outfile,"","");
整体的main函数代码如下:
/* rnx2rtkp main -------------------------------------------------------------*/
int main(int argc, char **argv) //参数个数、参数value
{
prcopt_t prcopt=prcopt_default; //process option 定位配置-默认值
solopt_t solopt=solopt_default; //solotion option 结果配置-默认值
filopt_t filopt={""}; //fileoption 文件配置-默认空
gtime_t ts={0},te={0};
double tint=0.0,es[]={2000,1,1,0,0,0},ee[]={2000,12,31,23,59,59},pos[3];
int i,j,n,ret;
char *infile[MAXFILE],*outfile="",*p; //MAXFILE == 16
//设置默认值
prcopt.mode =PMODE_KINEMA;
prcopt.navsys=0;
prcopt.refpos=1;
prcopt.glomodear=1;
solopt.timef=0;
sprintf(solopt.prog ,"%s ver.%s %s",PROGNAME,VER_RTKLIB,PATCH_LEVEL);
sprintf(filopt.trace,"%s.trace",PROGNAME);
/* 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);
}
}
for (i=1,n=0;i<argc;i++) {
if (!strcmp(argv[i],"-o")&&i+1<argc) outfile=argv[++i];
else if (!strcmp(argv[i],"-ts")&&i+2<argc) {
sscanf(argv[++i],"%lf/%lf/%lf",es,es+1,es+2);
sscanf(argv[++i],"%lf:%lf:%lf",es+3,es+4,es+5);
ts=epoch2time(es);
}
else if (!strcmp(argv[i],"-te")&&i+2<argc) {
sscanf(argv[++i],"%lf/%lf/%lf",ee,ee+1,ee+2);
sscanf(argv[++i],"%lf:%lf:%lf",ee+3,ee+4,ee+5);
te=epoch2time(ee);
}
else if (!strcmp(argv[i],"-ti")&&i+1<argc) tint=atof(argv[++i]); //atof-字符串转double
else if (!strcmp(argv[i],"-k")&&i+1<argc) {++i; continue;}
else if (!strcmp(argv[i],"-p")&&i+1<argc) prcopt.mode=atoi(argv[++i]);
else if (!strcmp(argv[i],"-f")&&i+1<argc) prcopt.nf=atoi(argv[++i]);
else if (!strcmp(argv[i],"-sys")&&i+1<argc) {
for (p=argv[++i];*p;p++) {
switch (*p) {
case 'G': prcopt.navsys|=SYS_GPS;
case 'R': prcopt.navsys|=SYS_GLO;
case 'E': prcopt.navsys|=SYS_GAL;
case 'J': prcopt.navsys|=SYS_QZS;
case 'C': prcopt.navsys|=SYS_CMP;
case 'I': prcopt.navsys|=SYS_IRN;
}
if (!(p=strchr(p,','))) break;
}
}
else if (!strcmp(argv[i],"-m")&&i+1<argc) prcopt.elmin=atof(argv[++i])*D2R; // -m 后面跟了一个值读取
else if (!strcmp(argv[i],"-v")&&i+1<argc) prcopt.thresar[0]=atof(argv[++i]);
else if (!strcmp(argv[i],"-s")&&i+1<argc) strcpy(solopt.sep,argv[++i]);
else if (!strcmp(argv[i],"-d")&&i+1<argc) solopt.timeu=atoi(argv[++i]);
else if (!strcmp(argv[i],"-b")) prcopt.soltype=1; // -b 后面没有值读取
else if (!strcmp(argv[i],"-c")) prcopt.soltype=2;
else if (!strcmp(argv[i],"-i")) prcopt.modear=2;
else if (!strcmp(argv[i],"-h")) prcopt.modear=3;
else if (!strcmp(argv[i],"-t")) solopt.timef=1;
else if (!strcmp(argv[i],"-u")) solopt.times=TIMES_UTC;
else if (!strcmp(argv[i],"-e")) solopt.posf=SOLF_XYZ;
else if (!strcmp(argv[i],"-a")) solopt.posf=SOLF_ENU;
else if (!strcmp(argv[i],"-n")) solopt.posf=SOLF_NMEA;
else if (!strcmp(argv[i],"-g")) solopt.degf=1;
else if (!strcmp(argv[i],"-r")&&i+3<argc) {
prcopt.refpos=prcopt.rovpos=0;
for (j=0;j<3;j++) prcopt.rb[j]=atof(argv[++i]);
matcpy(prcopt.ru,prcopt.rb,3,1);
}
else if (!strcmp(argv[i],"-l")&&i+3<argc) {
prcopt.refpos=prcopt.rovpos=0;
for (j=0;j<3;j++) pos[j]=atof(argv[++i]);
for (j=0;j<2;j++) pos[j]*=D2R;
pos2ecef(pos,prcopt.rb);
matcpy(prcopt.ru,prcopt.rb,3,1);
}
else if (!strcmp(argv[i],"-y")&&i+1<argc) solopt.sstat=atoi(argv[++i]);
else if (!strcmp(argv[i],"-x")&&i+1<argc) solopt.trace=atoi(argv[++i]);
else if (*argv[i]=='-') printhelp();
else if (n<MAXFILE) infile[n++]=argv[i];
}
if (!prcopt.navsys) {
prcopt.navsys=SYS_GPS|SYS_GLO;
}
if (n<=0) {
showmsg("error : no input file");
return -2;
}
//开始时间、结束时间、采样频率、process option、solution option、file option、输入文件、输入文件个数、输出文件
ret=postpos(ts,te,tint,0.0,&prcopt,&solopt,&filopt,infile,n,outfile,"","");
if (!ret) fprintf(stderr,"%40s\r","");
return ret;
}