GPS单点定位原理与C++程序实现(一)

作为一名大二导航工程专业的学生,假期留校和老师做科研。众所周知,导航的目标是一下三个:P(positioning)V(velocity)T(timing)。其中,定位和测速有着不可分割的关系。下面就先来看看GPS定位的基本原理和程序实现。

一、单点定位原理

1.原始数据

目前,绝大多数的导航原始文件都来源于IERS(国际地球自转服务)所提供的数据。大家可以随便找一个能够下载卫星星历的网站,下载卫星星历供调试程序使用。卫星星历下载下来之后是一个压缩包,解压后的文件夹里面有好多文件。我在写单点定位的程序的时候只用了GPS卫星进行单点定位,那么就只用到其中的o文件(观测值文件)和n文件(GPS广播星历文件)。当然了,如果想要北斗,GALILEO或者是GLONASS卫星进行定位,可以采用其他的文件。目前的文件记录格式都是采用RINEX进行记录的。我采用的数据是RINEX3.01格式的,其实2.11版本的也可以,只是文件格式略有不同而已,大家在读文件的时候注意一下就好。RINEX3.01的数据记录格式说明(英文版)我已经传到资源区了。

2.基本原理

单点定位分为标准单点定位和精密单点定位。在本篇博客中,我想介绍标准单点定位的相关内容。
标准单点定位就是利用广播星历给出的卫星轨道和卫星钟差以及伪距观测值来进行的,定位精度不是很好,一般为10米级左右。观测方程如下
观测方程的一般形式

其中的参数学测绘的应该都能看懂,要是看不懂,建议参考武汉大学出版社出版的李征航老师和黄劲松老师编写的GPS测量与数据处理这本书,比较详细。
有了观测方程之后就需要线性化,然后根据最小二乘的原理进行最优估计,详细理论过程大家可以参考吴云老师的最优估计及其在GNSS中的应用这本书。由于这篇博客想要重点介绍程序是如何实现,因此在理论部分不多说了。

二、程序设计流程及部分代码

1.读取广播星历文件

在读取卫星的广播星历的文件时,首先要跳过文件头,然后读取相应的卫星星历数据。我在读取GPS卫星数据的时候,采用的是单链表的形式。其实用C++库中的vector类就可以,但是我认为这样不自由,因此我采用了数据结构中的单链表的形式。在头文件中定义了用于存储广播星历参数的数据结构。

//定义用于存储GPS星历参数的结点
typedef struct GPSeph{
 int PRN;
 int year,month,day,hour,minute;
 float second;
 long double a0,a1,a2;
 long double IODE,Crs,deltan,M0;
 long double Cuc,e,Cus,sqrtA;
 long double TOW,Cic,OMEGA,Cis;
 long double i0,Crc,omega,OMEGAdot;
 long double IDOT,L2,WN,L2P;
 long double accurancy,health,TGD,IODC;
 long double sendtime;
 struct GPSeph * nextdata;
 long double deltat;//求卫星钟差的时候要用到
}GPSeph;

有了用来存储卫星星历的数据结构,下面就是读取广播星历了。
大家通过观察广播星历的数据记录格式可以发现,数据是下面这种记录形式
广播星历
也就是说中间是用D隔开,以科学计数法的形式记录的。在读取的时候可以像下面这样读取

GPS_nexteph->a0=a*pow(10,b);
fo>>a>>g>>b;

其中g是char类型的变量,a,b都是long double 类型的变量。利用ifstream读取至文件末尾。整个的读文件的程序我在这里就不附上代码了,因为代码太长了,而且大体上都是这样。在跳过文件头的时候,有两种方法:一种是偷懒型的,就是直接getline,跳过指定的行数(哈哈哈,我就是用的这种方法);还有一种就是利用String类中的字符串匹配方法查找是否含有“End Of Header”。最后读取到文件末尾,留下头指针,广播星历文件读取完毕。

2.读取观测值文件

我下载的观测值文件是间隔为半分钟的观测值,里面虽然数据看上去很多,但是我们只需要伪距观测值就够了,其它的以后再说。
观测值文件的文件头中的一部分上面的图片是我从观测值文件头中截取的一小部分,这里面记录了各种卫星有哪些类型的观测值,里面的字母代表的意义大家可以去我上传的RINEX3.01的说明文档的附录中查看。总之,我们利用每个卫星的PRN号后面的第一个观测值就够了。观测值文件的特点是一个时间点下面有好多颗卫星,因此我也为观测值文件的读取定义了一个单链表。

typedef struct OBSERVATIONdata{
 int year,month,day,hour,minute;
 long double second;
 int flag,satellite_number;
 vector<char> satellite_system;//存储卫星所属的系统
 vector<long double> pseudorange;//存储卫星的伪距观测值
 vector<int> PRN;
 OBSERVATIONdata * nextdata;
}OBSERVATIONdata;

其实用vector类直接就可以完成数据的存储,但是我想让数据的存储格式变得灵活一些,同时便于后期想要向代码中添加新的元素,我采用了比较复杂的自己定义单链表的形式。
o文件的读取不像n文件那样复杂,没有什么想要特殊说明的。

至此,第一部分总算完成了。当时请教老师的时候,老师就说文件的读取会占用代码的很大一部分,果不其然。另外,还要特别的感谢老师,在暑假期间还为我当面为我解答一些问题。下一篇博客打算写读取文件后的计算过程,代码等我完成测速后,一起打包传到资源区。不得不说,看上去过程简单,实际上想要运行出来真正正确的结果对于初学者来说真的不容易。希望大家代码的bug少少,今年新年我的愿望一定是希望我在以后写程序的时候代码少一点啊~
另外,大家如果想要找我交流什么,可以给我留言,不足之处请大家多多指教~

  • 36
    点赞
  • 175
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
GPS应用程序设计》源代码。本软件是专为《GPS应用程序设计》一书配套发行的。包括: 1、 data_log.c 数据采集程序 2、 rinexout.c RINEX数据格式写入子程序 3、 to_rinex.c 数据格式转换 4、 sav_pos.c 卫星位置计算程序 5、 sky_sav.c 卫星天空显示程序 6、 dop_calc.c 卫星星座DOP计算程序 7、 view_sav.c 历书预报卫星出现程序 8、 absl_pos.c 单点绝对定位程序 9、 ssgsoft.c -- 相对静态定位主程序 10、 controlf.c ? 读取输入文件子程序 11、 orbit.c -- 选择参考卫星子程序 12、 broad.c -- 读广播星历计算子程序 13、 igs.c -- 读 IGS 精密星历子程序 14、 singlep.c -- 近似位置计算子程序 15、 rinex.c -- 读 Rinex 数据、探测跳周、组成单差子程序 16、 eqdd_s.c -- 组成双差方程子程序 17、 normdd_s.c ? 组成法方差子程序 18、 ad_core.c -- 平差子程序19、 ambifix.c -- 模糊度固定子程序 20、 tranf.c -- 坐标变换子程序 21、 dgps_ppr. 相位平滑伪距改正数计算程序 22、 dgps_phr 准载波相位改正数计算程序 23 rtcmencd.c RTCM 电文编码程序 24 rtcmencd.c RTCM 电文译码程序 25、 net_dgn.c 测量格网设计程序 26 sur_ctr.c 动态测量控制程序 27、 replay.c 动态测量数据回放程序 28、 kin_tran.c 动态定位坐标转换程序 29、 rms.c 定位精度估计程序 30、 tide.c 潮位改正程序 31、 xybl_54.c 54坐标变换程序 32、 xyxy_loc.c 任意坐标系转换程序 33、 gga+gsv.c GGA和GSV数据模拟程序 34、 depth.c 水深数据模拟程序 35、 gg_pos.c GPS+GLONASS导航程序 36、 menu1.c DOS环境换页式菜单程序 37、 menu2.c DOS环境下拉式菜单程序 38、 menu3.c windows95环境下拉式多层界面菜单程序 39、 makedata.c 利用RINEX格式文件data.98n和data.98o形成的data.out文件,供计算单点定位
rtklib的单点定位是通过procpos()函数实现的,该函数包括数据输入inputobs()、数据处理rtkpos()和数据输出outsol()三个部分。其中,rtkpos()是核心处理单元,包括单点定位pntpos、精密单点定位pppos和相对定位relpos三个部分。单点定位公式需要通过求解卫星的位置、速度和钟差,并考虑电离层和对流层等修正来获取接收机的位置和钟差。卫星部分参数的计算可以通过satposs()函数实现。当增量矩阵满足一定条件时,输出结果包括接收机的位置、钟差以及误差协方差矩阵等信息。具体的计算过程和函数定义可以参考rtklib的源代码。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [RTKLIB学习(二)——单点定位-卫星位置、速度、钟差的计算](https://blog.csdn.net/qq_45598117/article/details/121945476)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [RTKLIB专题学习(五)---单点定位实现进阶(一)](https://blog.csdn.net/absll/article/details/124005570)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值