本文主要记录对RTKLIB源码中postpos、execses_b、execses_r 函数的源码解读,不涉及其中的天线、星历等文件读取的内容,且为个人理解,如果有误,欢迎交流讨论。
一、postpos 函数部分
/rxn2rtkp 函数 → postpos函数传递参数:
postpos 函数接收参数:
各参数含义:
cpp
• gtime_t ts: 处理开始时间。ts.time == 0 表示没有时间限制。
• gtime_t te: 处理结束时间。te.time == 0 表示没有时间限制。
• double ti: 处理时间间隔(秒)。ti == 0 表示处理整个时间段。
• double tu: 处理段时间(秒)。tu == 0 表示处理所有时间。
• const prcopt_t *popt: 处理选项,包含数据处理的各种参数配置。
• const solopt_t *sopt: 解算选项,定义输出格式等参数。
• const filopt_t *fopt: 文件选项,包含输入输出文件的路径等。
• char **infile: 输入文件列表,包含观测文件、导航文件等。
• int n: 输入文件数量。
• char *outfile: 输出文件路径(可为空字符串,表示输出到标准输出)。
• const char *rov: 移动站(rover)的ID列表。(用空格分隔)
• const char *base: 基准站(base station)的ID列表。(用空格分隔)
• 备注: 输入文件应包含观测数据、导航数据、精密星历/钟差数据(可选)、SBAS 日志文件(可选)、SSR
• 消息日志文件(可选)和 TEC 网格文件(可选)。只有第一个输入文件中的观测数据被视为流动站数据。
• 输入文件的类型通过文件扩展名识别,如下:
• .sp3,.SP3,.eph*,.EPH*: 精密星历 (sp3c)
• .sbs,.SBS,.ems,.EMS : SBAS 消息日志文件 (rtklib 或 ems)
• .rtcm3,.RTCM3 : SSR 消息日志文件 (rtcm3)
• .*i,.*I : TEC 网格文件 (ionex)
• 其他 : RINEX 观测、导航、GNAV、HNAV、QNAV 或钟差文件
• 输入文件可以包含通配符(*):如果文件包含通配符,将会使用展开后的多个文件。
• 输入文件可以包含关键词:如果文件包含关键词,关键词将会被日期、时间、流动站 ID 和基准站 ID 替换,进
• 行多次会话分析。请参阅 reppath() 了解关键词。
• 输出文件同样可以包含关键词:如果输出文件不包含关键词,所有多次会话分析的结果将输出到一个单一的输
• 出文件中。
• SSR 改正仅对前向估计有效。
- 第一个 if 语句:如果开始时间、结束时间 ≠0,处理单元时间 > 0:
cpp
reppath函数:将文件路径中的关键字替换为 - 日期、时间、基准站流动站ID
* args : char *path I 文件路径
* char *rpath O 存储替换关键字后的文件路径
* gtime_t time I time (gpst) (time.time==0: not replaced)
* char *rov I 流动站ID ("": not replaced)
* char *base I 基准站ID ("": not replaced)
1. extern int reppath(const char *path, char *rpath, gtime_t time, const char *rov,
2. const char *base)
3. { //初始化参数
4. double ep[6],ep0[6]={2000,1,1,0,0,0}; //用于存储时间的各部分(年、月、日、小时、分钟、秒)
5. int week,dow,doy,stat=0; //GPS周、周内天(0-6)、年积日(一年中的第几天)、记录替换状态
6. char rep[64];
7.
8. strcpy(rpath,path); //将path(主函数传参过来的infile或outfile)中的路径复制到rpath(postpos函数内部定义的用于后续传参的ifile或ofile)
9. if (!strstr(rpath,"%")) return 0; //检查路径中是否有%关键字,没有直接返回0
10. if (*rov ) stat|=repstr(rpath,"%r",rov ); //检查rov、base是否非空,替换路径中%r、%b关键字
11. if (*base) stat|=repstr(rpath,"%b",base); //rov、base为流动站和基准站的ID列表
12. // |= 位或操作符,其实就是判断返回值是否为非0,就成功
13.
14. if (time.time!=0) { //如果传入时间不为0,执行后续所有代码
15. time2epoch(time,ep); //将传入gps时间转换为历元时间(年月日时分秒),并存储在 ep 数组中
16. ep0[0]=ep[0]; //更新初始参数时间为当前时间的年份
17. dow=(int)floor(time2gpst(time,&week)/86400.0); //计算 GPS 周内天数
(0表示星期天,1 表示星期一,以此类推)
18. doy=(int)floor(timediff(time,epoch2time(ep0))/86400.0)+1; //计算当年第几天
//根据路径中不同关键字对应格式进行替换(这里要注意传入的时间代表什么)
19. sprintf(rep,"%02d", ((int)ep[3]/3)*3); stat|=repstr(rpath,"%ha",rep);
20. sprintf(rep,"%02d", ((int)ep[3]/6)*6); stat|=repstr(rpath,"%hb",rep);
21. sprintf(rep,"%02d", ((int)ep[3]/12)*12); stat|=repstr(rpath,"%hc",rep);
22. sprintf(rep,"%04.0f",ep[0]); stat|=repstr(rpath,"%Y",rep);
23. sprintf(rep,"%02.0f",fmod(ep[0],100.0)); stat|=repstr(rpath,"%y",rep);
24. sprintf(rep,"%02.0f",ep[1]); stat|=repstr(rpath,"%m",rep);
25. sprintf(rep,"%02.0f",ep[2]); stat|=repstr(rpath,"%d",rep);
26. sprintf(rep,"%02.0f",ep[3]); stat|=repstr(rpath,"%h",rep);
27. sprintf(rep,"%02.0f",ep[4]); stat|=repstr(rpath,"%M",rep);
28. sprintf(rep,"%02.0f",floor(ep[5])); stat|=repstr(rpath,"%S",rep);
29. sprintf(rep,"%03d", doy); stat|=repstr(rpath,"%n",rep);
30. sprintf(rep,"%04d", week); stat|=repstr(rpath,"%W",rep);
31. sprintf(rep,"%d", dow); stat|=repstr(rpath,"%D",rep);
32. sprintf(rep,"%c", 'a'+(int)ep[3]); stat|=repstr(rpath,"%H",rep);
33. sprintf(rep,"%02d", ((int)ep[4]/15)*15); stat|=repstr(rpath,"%t",rep);
34. }
35. //如果路径中存在以下时间关键字,但没有给出有效时间,则返回-1 2
36. else if (strstr(rpath,"%ha")||strstr(rpath,"%hb")||strstr(rpath,"%hc")||
37. strstr(rpath,"%Y" )||strstr(rpath,"%y" )||strstr(rpath,"%m" )||
38. strstr(rpath,"%d" )||strstr(rpath,"%h" )||strstr(rpath,"%M" )||
39. strstr(rpath,"%S" )||strstr(rpath,"%n" )||strstr(rpath,"%W" )||
40. strstr(rpath,"%D" )||strstr(rpath,"%H" )||strstr(rpath,"%t" )) {
41. return -1; /* no valid time */
42. }
43. return stat; //这个返回状态是只要有路径中关键字被替换就会返回非0值
44. }
* notes : 路径中的以下关键字将被日期、时间和名称替换
* %Y -> yyyy : year (4 digits) (1900-2099)
* %y -> yy : year (2 digits) (00-99)
* %m -> mm : month (01-12)
* %d -> dd : day of month (01-31)
* %h -> hh : hours (00-23)
* %M -> mm : minutes (00-59)
* %S -> ss : seconds (00-59)
* %n -> ddd : day of year (001-366)
* %W -> wwww : gps week (0001-9999)
* %D -> d : day of gps week (0-6)
* %H -> h : hour code (a=0,b=1,c=2,...,x=23)
* %ha-> hh : 3 hours (00,03,06,...,21)
* %hb-> hh : 6 hours (00,06,12,18)
* %hc-> hh : 12 hours (00,12)
* %t -> mm : 15 minutes (00,15,30,45)
* %r -> rrrr : rover id
* %b -> bbbb : base station id
二、execses_b 函数
/postpos 函数 → execses_b 函数传递参数:
在postpos函数中根据是否输入了开始时间、结束时间和段时间对输入文件进行处理,但是不管如何处理,将输入文件分成多少个,传递到exceses_b函数都是对某段时间进行处理,只需要知道开始时间、结束时间和采样频率就可以。
该函数其实就是
- if (ts.time!=0&&te.time!=0&&tu>=0.0)
- else if (ts.time!=0)
- else
execses_b 函数接收参数:
三、execses_r 函数
四、总体分析