Skip to content

Commit 2fee5fb

Browse files
committed
加README、ROS导航包
1 parent 31b50f6 commit 2fee5fb

File tree

32 files changed

+2587
-289
lines changed

32 files changed

+2587
-289
lines changed

01-RTKLIB源码阅读/01-RTKLIB源码阅读(一)程序介绍、编译调试、界面程序、后处理解算、核心代码库.md

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,18 @@ RTKLIB 可以初步实现以下功能,相对于商业软件,可靠性没那
7272
* [RTKLIB-demo5](https://github.com/rtklibexplorer/RTKLIB):针对低成本接收机做了算法增强,下面的部分程序是基于 demo5 开发的。
7373
* [rtklib-py](https://github.com/rtklibexplorer/rtklib-py)
7474
* [GPSTK](https://github.com/SGL-UT/GPSTk)
75-
* GAMP:山科大周峰写的非差非组合PPP,在 RTKLIB 基础上做精简和算法的增强,比原版 RTKLIB 简单,适合作为学 PPP 的入门。曾经老师给我一套他师弟在GAMP基础上改的三频PPP 让我看。
76-
* [Ginan](https://github.com/GeoscienceAustralia/ginan):澳大利亚,包括精密定位程序 PEA、定轨程序 POD,文档很详细,老师让我看,但我没看下去,受不了它的代码风格
75+
* GAMP:山科大周峰写的双频非差非组合浮点解 PPP,在 RTKLIB 基础上做精简和算法的增强,比原版 RTKLIB 简单,是入门学习 PPP 不错的选择。曾经老师给我一套他师弟在 GAMP 基础上改的三频 PPP 让我看。
76+
* [Ginan](https://github.com/GeoscienceAustralia/ginan):澳大利亚,包括精密定位程序 PEA、定轨程序 POD,文档很详细,老师让我看,但我没看下去,代码比较难懂,而且它的代码风格很奇怪
7777
* [GraphGNSSLib](https://github.com/weisongwen/GraphGNSSLib):港理工,支持图优化 SPP、RTK。作者在知乎很活跃,时常发一些科普文章。
7878
* PPPLIB:我老师在矿大读研的时候写的,我看的第一个 C++ 程序,
7979
* [TGINS](https://github.com/heiwa0519/TGINS):我老师去年刚来安理的时候写的,文档和注释很少,紧组合看着比较费劲
80+
* GINAV:MATLAB 紧组合,文件名起的和 RTKLIB 函数名一模一样
8081
* [GICI-LIB](https://github.com/chichengcn/gici-open):上海交大,
8182
* [PPP-AR](https://github.com/PrideLab/PRIDE-PPPAR):武大GNSS中心,使用了 rnx2rtkp 可执行程序计算测站初值坐标,网址
8283
* [IGNAV](https://github.com/Erensu/ignav):武大GNSS中心,
8384
* [pppwizard](http://www.ppp-wizard.net/)
8485
* [GNSS-SDR](https://github.com/gnss-sdr/gnss-sdr):GNSS 软件接收机,与上面列举的数据处理软件不同,GNSS-SDR 实现基带算法直接对接收机输出的数字中频信号处理,PVT 部分用了 RTKLIB。
85-
* [APOLLO](https://github.com/ApolloAuto/apollo):百度的开源无人驾驶系统,暑假的时候心血来潮准备看看的,被代码量吓到了,没那么多时间看,遂放弃。
86+
* [APOLLO](https://github.com/ApolloAuto/apollo):百度的开源无人驾驶系统,
8687

8788
#### 5. 我用 RTKLIB 做的事
8889

@@ -92,7 +93,7 @@ RTKLIB 自带的程序除了 rtkplot 之外我都没咋用过,我主要是用
9293
* **坐标转换**:我程序的坐标都用 Eigen 库的 Vector3d 向量表示;为方便调用,我对 ENU、ECEF、BLH 坐标之间的转换函数做了一层封装,接口为 Eigen 形式。
9394
* **结果输出**:为了能输出姿态,扩展了 sol_t 结构体,加上三个欧拉角,输出结果的语句上加上欧拉角;然后拓展 rtkplot,把姿态角结果也画出来。
9495
* **GNSS相关的类型定义**:卫星系统、卫星、观测值定义
95-
* **配置选项**
96+
* **配置选项**GNSS 相关的
9697
* **数据读取**:RINEX、RTCM、NMEA
9798
* **数据流**
9899
*
@@ -151,7 +152,7 @@ RTKLIB 自带的程序除了 rtkplot 之外我都没咋用过,我主要是用
151152

152153
### 5、源码学习建议
153154

154-
#### 1. 编程基础差怎么办
155+
#### 1. 编程基础
155156

156157
* 有一点点 C 语言基础就可以了,之前上课学过那一点点 C 语言就足够了,不需要再特意的学语法,直接看代码,没见过的语法查一下,以后就会了;学编程光看书看网课是远远不够的,得多练,先看别人写的代码,然后才能自己写。
157158
* 如果语法基础不好,一开始看的可能会比较艰难;可以先不想那么多,就从最基础的矩阵计算开始看,这几个小函数总能看下去吧;看完矩阵运算就继续看时间系统、坐标系统,RINEX文件读取......,一点点看,拼命的看,坚持下去;刚开始看的慢没关系,过了最初的坎,熟悉起来之后,后面就会慢慢顺起来,之后无论是再继续看别的程序还是自己写都能得心应手。
@@ -162,8 +163,8 @@ RTKLIB 自带的程序除了 rtkplot 之外我都没咋用过,我主要是用
162163

163164
* 现在人工智能越来越强,把 RTKLIB 的代码段扔给 AI,基本都能给你解释解释。
164165
* 网上 RTKLIB 的资料很丰富,基本上能把每一行代码的意思都给你讲明白了;可以先照着博客,把代码快速的过一遍,把博客上的注释、讲解复制到你手头的代码里,自己再看能顺很多。当然,博客大多写的很随意,不严谨,但有个参考总比没有好。
165-
* 学 RTK 可以看我的老师杨旭、陈健的硕士论文,短基线看杨旭、长基线看陈健,他们论文写的算法和 RTKLIB 几乎一模一样。上知网搜一搜,或者去我的仓库下载
166-
* 学 PPP 可以先结合着周峰老师的博士论文看 GAMP,然后再看 RTKLIB
166+
* 学 RTK 可以看我的老师杨旭的硕士论文,算法和 RTKLIB 几乎一模一样,学短基线算法、模糊度固定
167+
* 学 PPP 算法推荐看吉林大学周昌杰的硕士论文:《基于RTKLIB的GNSS精密单点定位研究》
167168
* RTKLIB 算法除了模糊度固定,理解起来都没啥难度,不懂的算法找论文看看就会了。
168169
* 代码量很大,直接看可能会一头雾水,很难一下记住那么复杂的代码逻辑;可以通过流程图、函数调用关系图、思维导图,来辅助理解;通过画图来理清思路,画出的图也可以用来复习。
169170

@@ -180,15 +181,14 @@ RTKLIB 自带的程序除了 rtkplot 之外我都没咋用过,我主要是用
180181

181182
* 学的时候先从后处理开始,先看 [postpos 的用法](https://www.bilibili.com/video/BV1m5411Y7xV),然后顺着 rnx2rtkp 的源码,把从读取 RINEX 文件到算出定位结果整个过程看明白。
182183

183-
184184

185185
#### 5. 算法学习顺序
186186

187187
* **矩阵运算**:矩阵都是用一维 double 数组表示、列优先,要熟练掌握矩阵的加减乘除转置求逆,还要会 `matprint()` 输出矩阵用于 debug。
188188
* **参数估计**:最小二乘、卡尔曼滤波、前向滤波、后向滤波、正反向结合。
189189
* **时间系统**:知道基本概念(GPS 时、UTC、周内秒、跳秒、儒略日),理解 `gtime_t` 类型,会用操作 `gtime_t` 的函数,比如算时间差、比较时间先后、输出时间字符串、输出当前北京时间字符串、转周内秒。
190190
* **坐标系统**:矩阵用三维向量表示,要掌握 ECEF(XYZ)、LLH(经纬高)、ENU(东北天)的用途、转换函数。
191-
* **卫星系统定义**两套:表示卫星系统的字母:GRECJIS;或者 7 位二进制码,对应位写 1 表示有对应的系统,做与运算可加系统。
191+
* **卫星系统定义**有两套表示方法:表示卫星系统的字母:GRECJIS;或者 7 位二进制码,对应位写 1 表示有对应的系统,做与运算可加系统。
192192
* **卫星定义**:可以表示为各系统的卫星 ID(系统缩写+PRN):B02、C21;也可表示为连续的整型数字 satellite number。
193193
* **观测量定义****C**:伪距、**D**:多普勒、**L**:载波相位、**S**:载噪比;`CODE_XXX`:观测值类型定义,用一串连续的数字表示。
194194
* **配置选项**:主要是三个结构体:`prcopt_t` 存处理选项、`filopt_t` 存文件路径、`solopt_t` 存结果输出格式;默认处理选项、结果选项要理解,常用的处理选项要记住。
@@ -199,25 +199,25 @@ RTKLIB 自带的程序除了 rtkplot 之外我都没咋用过,我主要是用
199199
* **卫星位置**:就是读文件套公式计算,没啥难度,过一遍文件格式和公式,有点点印象,知道 BDS、GLONASS 和其它系统计算的区别就可以。
200200
* **卫星钟差计算**:用 ,迭代三次,要做群波延迟校正、相对论效应改正
201201
* **克罗布歇模型电离层改正**
202-
* **对流层改正**
203-
* **卫星天线相位改正**:GNSS 观测量是卫星和接收机天线相位之间的,而不是几何中心,
204-
* **接收机天线相位改正**
202+
* **对流层改正**:GPT 模型的气压温度算的准一点
203+
* **天线相位改正**:包括卫星端和接收机端、PCO 和 PCV,GNSS 观测量是卫星和接收机天线相位之间的,而不是几何中心,需要转到几何中心,常通过 igs14.atx 文件来改正。
205204
* **天线相位缠绕**
206205
* **地球自转改正**:也称 Sagnac 效应改正,卫星信号到达地球时 ECEF 坐标系会绕地球时 转动 $\omega r$,计算卫星与接收机间的几何距离时需要套公式改正。
207-
* **潮汐改正**:地球并非刚体,会在日月引力、地球负荷作用下产生周期性形变,分为固体潮、极潮、海洋潮,改正的时候先算 ECI 下日月坐标,然后套公式计算。
206+
* **潮汐改正**:地球并非刚体,会在日月引力、地球负荷作用下产生周期性形变,分为固体潮、极潮、海洋潮,改正的时候先算日月坐标,然后套公式计算。
208207
* **观测值排除**:星历缺失、高度角、信噪比、人为排除卫星、URA。
208+
* **差分码偏差 DCB**:GPS 广播星历是相对 P 码而言,而我们普通用户定位解算的时候用 C/A 码,需要通过 DCB 文件中的参数或者广播星历中的 TGD 来把测量的伪距归化到 P 码。
209209
* **单频单系统伪距单点定位**:高度角方位角、卫地视线向量、近似距离计算,设计矩阵 H、新息向量 V 的构建,量测协方差阵 var
210+
* **多系统**:多系统涉及到系统间偏差 ISB,以系统间时间偏差为主,还包括硬件延迟,每多一个系统,就要多估计一个相对于 GPS 的 ISB,增广状态向量和。
210211
* **DOP 值计算**
211-
* **RAIM-FDE**
212-
* **多系统**:多系统涉及到系统间偏差 ISB,以系统间时间偏差为主。
212+
* **RAIM-FDE**:定位解算迭代若干次之后,残差仍然过大,认为定位解算发射,剔除残差最大的卫星观测值再进行解算,不断重复这个过程,知道解算成功,或者卫星数量过少不足以解算。
213213
* **多频**:多频涉及到频间偏差 IFB;由于 GLONASS 信号频分多址调制,同频还存在频间偏差。
214214
* **周跳检测**:RTKLIB 实现了两套周跳检测 LLI 和 GF,检测到周跳要重置模糊度估计参数,没做周跳修复。
215215
* **模糊度固定**
216-
* **差分定位**非差、单差、双差
216+
* **差分定位**
217217
* **电离层 INOEX 文件**
218218
* **估计电离层 STEC**
219219
* **估计对流层 ZTD**
220-
* **精密单点定位**:理清楚改正了哪些误差,用了哪些文件,估计了哪些参数,参数的排列顺序,每种参数建立什么随机模型,初始噪声过程噪声怎么设置,出现什么情况要重置参数。
220+
* **浮点解 PPP**:理清楚改正了哪些误差,用了哪些文件,估计了哪些参数,参数的排列顺序,每种参数建立什么随机模型,初始噪声过程噪声怎么设置,出现什么情况要重置参数。
221221
* **实时解算流程**:从 rtkrcv
222222
* **数据流**
223223
* **RTCM、RAW 读取**:要简单了解数据格式,知道每种语句都有什么数据,用什么函数能读取到什么类型的哪个变量中。
@@ -764,7 +764,7 @@ rtklib 后处理主函数需要做的主要就是:读取配置文件(可省
764764
765765
766766
767-
读取结果文件流程
767+
读取配置文件流程
768768
769769
* 先调用 `resetsysopts()` 重置所有配置为默认。
770770
* 调用 `loadopts()` 读取配置文件内容,存入 `opt_t` 的 `sysopt` 中。
@@ -1070,7 +1070,6 @@ RTKLIB 提供许多代码库和 API,包括:卫星和导航系统函数、矩
10701070
* 先调用 `resetsysopts()` 重置所有配置为默认。
10711071
* 调用 `loadopts()` 读取配置文件内容,存入 `opt_t``sysopt` 中。
10721072
* 最后调用 `getsysopts()``opt_t` 转到 `porcopt_t`/`solopt_t`/`filopt_t`
1073-
*
10741073

10751074
![image-20231025205106288](https://pic-bed-1316053657.cos.ap-nanjing.myqcloud.com/img/image-20231025205106288.png)
10761075

01-RTKLIB源码阅读/08-RTKLIB源码阅读(八)伪距单点定位 SPP.md

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,11 +1117,11 @@ extern double ionmodel(gtime_t t, const double *ion, const double *pos,
11171117
11181118
![](https://pic-bed-1316053657.cos.ap-nanjing.myqcloud.com/img/894f3255c10846b994d589fcc1746100.png)
11191119
1120-
11211120
#### 1、IONEX文件概述
11221121
11231122
##### 1.文件结构
1124-
分四大部分:**文件头**结束于`END OF HEADER`。**多组总电子含量**,每组以`START OF TEC MAP` ,结束于`END OF TEC MAP` 。**多组电子含量均方根误差** ,与总电子含量对应,开始于`START OF RMS MAP`,结束于`END OF RMS MAP`,**DCB数据块**开始于`START OF AUS DATA`,结束于`END OF AUS DATA`,也称**辅助数据块**(Auxiliary Data Blocks)。
1123+
1124+
IONEX 文件分四大部分:**文件头**结束于`END OF HEADER`。**多组总电子含量**,每组以`START OF TEC MAP` ,结束于`END OF TEC MAP` 。**多组电子含量均方根误差** ,与总电子含量对应,开始于`START OF RMS MAP`,结束于`END OF RMS MAP`,**DCB数据块**开始于`START OF AUS DATA`,结束于`END OF AUS DATA`,也称**辅助数据块**(Auxiliary Data Blocks)。
11251125
11261126
##### 2.文件头
11271127
@@ -1241,6 +1241,7 @@ extern void readtec(const char *file, nav_t *nav, int opt)
12411241
格网改正模型电离层格网模型文件 IONEX,通过内插获得穿刺点位置,并结合当天电离层格网数据求出穿刺点的垂直电子含量,获得电离层延迟误差 。
12421242
12431243
##### 2.iontec():TEC格网改正主入口函数
1244+
12441245
由所属时间段两端端点的TEC网格数据**时间插值**计算出电离层延时 (L1) (m)
12451246
12461247
@@ -1307,7 +1308,7 @@ extern void readtec(const char *file, nav_t *nav, int opt)
13071308

13081309

13091310

1310-
##### 3.iondelay():计算指定时间电离层延时 (L1) (m)
1311+
##### 3.iondelay():计算指定时间电离层延时 (L1) (m)
13111312

13121313
* while大循环`tec->ndata[2]`次:
13131314
* 调用`ionppp()`函数,计算当前电离层高度,穿刺点的位置 {lat,lon,h} (rad,m)和倾斜率
@@ -1399,6 +1400,7 @@ extern void readtec(const char *file, nav_t *nav, int opt)
13991400

14001401

14011402
##### 5.dataindex():获取TEC格网数据下标
1403+
14021404
先判断点位是否在格网中,之后获取网格点的tec数据在 tec.data中的下标
14031405

14041406
```c
@@ -1412,6 +1414,7 @@ extern void readtec(const char *file, nav_t *nav, int opt)
14121414
14131415
14141416
##### 6.interptec():插值计算穿刺点处TEC
1417+
14151418
通过在经纬度网格点上进行双线性插值,计算第k个高度层时穿刺点处的电子数总量TEC
14161419
14171420
![](https://pic-bed-1316053657.cos.ap-nanjing.myqcloud.com/img/8c24cde54f6e4005b7858f2fef0c1dce.png)
@@ -1432,12 +1435,12 @@ extern void readtec(const char *file, nav_t *nav, int opt)
14321435
int i,j,n,index;
14331436
14341437
trace(3,"interptec: k=%d posp=%.2f %.2f\n",k,posp[0]*R2D,posp[1]*R2D);
1435-
*value=*rms=0.0; //将 value和 rms所指向的值置为 0
1438+
*value=*rms=0.0; // 将 value和 rms所指向的值置为 0
14361439
14371440
if (tec->lats[2]==0.0||tec->lons[2]==0.0) return 0; //检验 tec的纬度和经度间隔是否为 0。是,则直接返回 0
14381441
1439-
//将穿刺点的经纬度分别减去网格点的起始经纬度,再除以网格点间距,对结果进行取整,
1440-
//得到穿刺点所在网格的序号和穿刺点所在网格的位置(比例) i,j
1442+
// 将穿刺点的经纬度分别减去网格点的起始经纬度,再除以网格点间距,对结果进行取整,
1443+
// 得到穿刺点所在网格的序号和穿刺点所在网格的位置(比例) i,j
14411444
dlat=posp[0]*R2D-tec->lats[0];
14421445
dlon=posp[1]*R2D-tec->lons[0];
14431446
if (tec->lons[2]>0.0) dlon-=floor( dlon/360)*360.0; /* 0<=dlon<360 */
@@ -1447,28 +1450,28 @@ extern void readtec(const char *file, nav_t *nav, int opt)
14471450
i=(int)floor(a); a-=i;
14481451
j=(int)floor(b); b-=j;
14491452
1450-
//调用 dataindex函数分别计算这些网格点的 tec数据在 tec.data中的下标,
1451-
//按从左下到右上的顺序
1452-
//从而得到这些网格点处的 TEC值和相应误差的标准差
1453+
// 调用 dataindex() 函数分别计算这些网格点的 tec 数据在 tec.data中的下标,
1454+
// 按从左下到右上的顺序
1455+
// 从而得到这些网格点处的 TEC 值和相应误差的标准差
14531456
/* get gridded tec data */
14541457
for (n=0;n<4;n++) {
14551458
if ((index=dataindex(i+(n%2),j+(n<2?0:1),k,tec->ndata))<0) continue;
14561459
d[n]=tec->data[index];
14571460
r[n]=tec->rms [index];
14581461
}
14591462
if (d[0]>0.0&&d[1]>0.0&&d[2]>0.0&&d[3]>0.0) {
1460-
//穿刺点位于网格内,使用双线性插值计算出穿刺点的 TEC值
1463+
// 穿刺点位于网格内,使用双线性插值计算出穿刺点的 TEC 值
14611464
/* bilinear interpolation (inside of grid) */
14621465
*value=(1.0-a)*(1.0-b)*d[0]+a*(1.0-b)*d[1]+(1.0-a)*b*d[2]+a*b*d[3];
14631466
*rms =(1.0-a)*(1.0-b)*r[0]+a*(1.0-b)*r[1]+(1.0-a)*b*r[2]+a*b*r[3];
14641467
}
1465-
//穿刺点不位于网格内,使用最邻近的网格点值作为穿刺点的 TEC值,不过前提是网格点的 TEC>0
1468+
// 穿刺点不位于网格内,使用最邻近的网格点值作为穿刺点的 TEC值,不过前提是网格点的 TEC>0
14661469
/* nearest-neighbour extrapolation (outside of grid) */
14671470
else if (a<=0.5&&b<=0.5&&d[0]>0.0) {*value=d[0]; *rms=r[0];}
14681471
else if (a> 0.5&&b<=0.5&&d[1]>0.0) {*value=d[1]; *rms=r[1];}
14691472
else if (a<=0.5&&b> 0.5&&d[2]>0.0) {*value=d[2]; *rms=r[2];}
14701473
else if (a> 0.5&&b> 0.5&&d[3]>0.0) {*value=d[3]; *rms=r[3];}
1471-
//否则,选用四个网格点中 >0的值的平均值作为穿刺点的 TEC值
1474+
// 否则,选用四个网格点中 >0的值的平均值作为穿刺点的 TEC值
14721475
else {
14731476
i=0;
14741477
for (n=0;n<4;n++) if (d[n]>0.0) {i++; *value+=d[n]; *rms+=r[n];}

0 commit comments

Comments
 (0)