详解rtklib中main函数如何配置文件

news2024/11/15 1:27:01

目录

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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1537047.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot接口防止重复提交(AOP+Redis)

方法一&#xff1a; 若依框架的实现 【具体靠请求地址URL参数列表来判断请求是否重复】 SpingBoot接口防止重复提交_springboot接口防抖(防重复提交)的一些实现方案-CSDN博客文章浏览阅读518次。3.根据缓存键获取缓存中对象&#xff0c;如果存在&#xff0c;判断当前请求参…

156.乐理基础-和弦固定标记法(五)挂留(sus)和弦省略音(omit)和弦

如果到这五线谱还没记住还不认识的话去看102.五线谱-高音谱号与103.五线谱-低音谱号这两个里&#xff0c;这里面有五线谱对应的音名&#xff0c;对比着看 如果一章没落下&#xff0c;看到这里&#xff0c;但是看不懂什么意思&#xff0c;那就强行下看&#xff0c;看着看着指不…

【Linux操作系统】命令的运行原理

文章目录 shell命令以及运行原理Linux系列学习目录 shell命令以及运行原理 Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。而是通过kernel的“外壳”程序&…

怎么选择陪诊陪护APP开发公司

随着科技的发展&#xff0c;陪诊陪护APP已经成为了人们日常生活中不可或缺的一部分。它为患者提供了便捷的陪诊服务&#xff0c;也为医护人员提供了更多的工作机会。然而&#xff0c;市场上的陪诊陪护APP开发公司众多&#xff0c;如何选择一家专业且有实力的公司成为了消费者的…

DenseNet《Densely Connected Convolutional Networks》

DenseNet学习笔记 摘要引言DenseNetsResNetsDense connectivityResNet 和 DenseNet 的对比DenseBlock 向前传播的过程Composite functionPooling layersGrowth rateBottleneck layersCompression 压缩实现细节 实验训练 代码复现 摘要 最近的研究表明&#xff0c;如果卷积网络…

实现:mysql-5.7.42 到 mysql-8.2.0 的升级(rpm方式)

实现&#xff1a;mysql-5.7.42 到 mysql-8.2.0 的升级&#xff08;rpm方式&#xff09; 1、升级准备1、使用mysql-shell 检查工具检查兼容性 2、操作环境3、备份数据库、my.cnf文件&#xff0c;停止mysql服务&#xff08;重要&#xff09;4、上传、解压安装包5、查看已安装的my…

如何根据业务需求选择合适的电子合同平台?

在数字化转型的浪潮中&#xff0c;电子合同已经成为企业运营中不可或缺的一部分。然而&#xff0c;面对市场上众多的电子合同平台&#xff0c;企业如何根据自身的业务需求做出合适的选择呢&#xff1f;本文将为您一一解答。 在电子合同的签署过程中&#xff0c;数字证书颁发机…

AI论文速读 |(Mamba×时空图预测!) STG-Mamba:通过选择性状态空间模型进行时空图学习

&#xff08;来了来了&#xff0c;虽迟但到&#xff0c;序列建模的新宠儿mamba终于杀入了时空预测&#xff01;&#xff09; 论文标题&#xff1a;STG-Mamba: Spatial-Temporal Graph Learning via Selective State Space Model 作者&#xff1a;Lincan Li, Hanchen Wang&…

WeTrade众汇简单总结保证金和杠杆

通过之前的文章&#xff0c;相信各位投资者都已经明白了保证金和杠杆的含义。今天让WeTrade众汇继续简单总结一下: 财务杠杆是由经纪人提供的无息贷款&#xff0c;允许购买更多的资产或减少保证金&#xff0c;节省经纪人作为抵押品保留的资金。 保证金是交易者由经纪人保留作…

第十节HarmonyOS 常用容器组件3-GridRow

1、描述 栅格容器组件&#xff0c;仅可以和栅格子组件&#xff08;GridCol&#xff09;在栅格布局场景中使用。 2、子组件 可以包含GridCol子组件。 3、接口 GridRow(options:{columns: number | GridRowColumnOption, gutter?: Length | GutterOption, Breakpoints?: B…

企业管理:如何防止私加客户、飞单私单

1、聚合聊天与聚合管理 多个微信号可以在一界面聚合聊天&#xff0c;不用来回切换账号&#xff0c;还可以设置常用的快捷回复提高与客户沟通的效率&#xff0c;右侧可备注客户信息及跟进情况&#xff0c;也可以查看好友朋友圈&#xff0c;素材库可保存图片、视频链接方便随时可…

MATLAB机器学习工具箱——傻瓜式操作

一、使用回归学习期预测北京二手房房价 软件&#xff1a;MATLAB R2023 a 数据&#xff1a; 第一步&#xff1a;导入原始数据和待预测数据 第二步 &#xff1a;打开工具箱中的回归学习器导入学习数据 1.新建会话 2.寻找导入learning data 3.自动锁定前7列为自变量&#xff…

Day17:LeedCode 110.平衡二叉树 257.二叉树的所有路径 404.左叶子之和

110. 平衡二叉树 给定一个二叉树&#xff0c;判断它是否是 平衡二叉树 平衡二叉树:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 思路: 二叉树节点的深度&#xff1a;指从根节点到该节点的最长简单路径边的条数。二叉树节点的高度&#xff1a;指从该节点到叶…

详解Python的函数嵌套

Python语言允许在定义函数的时候&#xff0c;其函数体内又包含另外一个函数的完整定义&#xff0c;这就是我们通常所说的嵌套定义。 实例1&#xff1a; def OutFun(): #定义函数OutFun()&#xff0c;m3 #定义变量m3;def InFun(): #在OutFun内定义函…

Java毕业设计 基于springboot医院挂号系统 医院管理系统

Java毕业设计 基于springboot医院挂号系统 医院管理系统 springboot医院挂号系统 医院管理系统 功能介绍 用户&#xff1a;登录 首页 个人资料 修改密码 门诊管理 用户挂号 医生&#xff1a;登录 首页 个人资料 修改密码 门诊管理: 用户挂号 处方划价 项目划价 项目缴费 项目…

小白必看的python中的Bool运算和真假值

在python中&#xff0c;任何对象都可以判断其真假值&#xff1a;True&#xff0c;False 在if或while条件判断中&#xff0c;下面的情况值为False&#xff1a; 1.None 2.Flase 3.数值为0的情况&#xff0c;如&#xff1a;0,0.0,0j 4.所有空序列&#xff0c;如&#xff1a;,…

基于SpringBoot的网上订餐系统(含源文件)

&#xff08;源码附文章底部&#xff09; 摘 要 随着我国经济的飞速发展&#xff0c;人们的生活速度明显加快&#xff0c;在餐厅吃饭排队的情况到处可见&#xff0c;近年来由于新兴IT行业的空前发展&#xff0c;它与传统餐饮行业也进行了新旧的结合&#xff0c;很多餐饮商户开始…

Linux docker7--私有镜像仓库registry和UI搭建及使用

一、对于开源的镜像&#xff0c;如redis&#xff0c;nginx等&#xff0c;可以通过官方仓库Docker Hub&#xff0c;或者国内的阿里云等共有仓库下载获取到镜像。但是企业内对于自己的研发产品不可能往公共仓库去发布镜像的&#xff0c;一般都会搭建私有的镜像仓库&#xff0c;保…

RHCSA(第一天)

1.部署Linux环境&#xff1a; 安装Vmware之后&#xff0c;在windows会产生两个虚拟网卡&#xff1a;vmnet1&#xff0c; vmnet8 部署Linux&#xff1a;需要有网卡&#xff0c;必须要知道root用户的密码&#xff0c;和你普通的用户的用户名和密码 远程连接配置&#xff1a…

面试笔记——Redis(双写一致、持久化)

双写一致 双写一致性&#xff1a; 当修改了数据库中的数据&#xff0c;也要更新缓存的数据&#xff0c;使缓存和数据库中的数据保持一致。 相关问题&#xff1a;使用Redis作为缓存&#xff0c;mysql的数据如何与Redis进行同步&#xff1f;——双写一致性问题 回答时&#xff0…