利用rtklib开源代码处理GPS以及北斗数据详解

在GNSS领域最基础的工作是这些GNSS系统的定位工作,对于绝大多数研究者,自己着手完成这些工作是一个“鸡肋”:完全独立设计的话费时费力,运用开源代码又很难弄懂。我当初也是如此。但想到毕竟开源代码已经做了很多工作,不用实在可惜,最终毅然决定咬紧牙关弄懂rtklib。尝试用过rtklib的人都知道,其功能固然完全,然而代码却太过复杂,把人搅得一头雾水。想用vs2008使用那些代码,从添加文件到使用函数,简直是步步艰难。我已经从中吃了不少苦头,在用的时候也找不到比较详细的使用方法。不想后来者也像我一样,在rtklib使用中痛苦万分,故以现有的研究程度,对rtklib做个入门介绍。

关于rtklib的基本介绍,网上一堆,在此不再赘言,本文重点介绍如何用vs2008使用其src文件中的开源代码以及修改以完成自己需要的功能。

一、rtklib代码的添加

由于习惯了vs2008,在开发程序时用到这个编译器。添加过程如下:

1、  在vs中新建一个控制台项目(含预编译头);

2、  在建好的项目中添加rtklib.h以及需要用到的source文件(.c文件),然后将.c改为.cpp并在每个文件首句增加一行#include "stdafx.h",当然在stdafx.h文件中添加#include "rtklib.h"; 这样编译基本可以通过了;

3、  一般而言,我们不会需要用到rtklib程序集中的所有文件,只是需要部分。比如我需要用到其中的pntpos这个标准单点定位函数,这个时候就需要添加该函数所在实现文件(pntpos.c)。于是添加了这个文件。但是一般而言,只添加这一个可能不能解决问题,因为rtklib的各个文件之间并不是完全独立,pntpos文件中某些函数可能会调用到其他文件中实现的函数。于是需要再把相关文件添加到工程中。对于这个问题,可以根据自己添加的文件,编译时候的提示,依次添加进来相应文件。这样可以解决fatal error的问题;

4、  在添加完成后,可能会遇到一些其他问题。主要问题有:a.关于某些地方数组越界或为空(主要是glonass),这个时候,查看rtklib.h头文件,可以发现关于系统启用的#define语句,其中除GPS系统外,其他系统数目都是0。解决办法如截图:主要

是注释掉这个判断语句。(当然,这样造成的是所有系统直接启用,这是我的处理办法,不是最佳的办法,读者有更好的办法求赐教哈)b.关于很多地方会出现const char*与char*的不能转化问题,这个很简单,在相应地方进行强制转化就行。c.还存在字符集采用的问题,这个只需要在项目属性中使用多字节字符集即可(见下图)。

d.关于某些函数存在未实现的问题,这个时候,可以网上直接搜索那些没有实现的函数,进行替换,或是直接屏蔽掉。

rtklib中代码的添加工作基本就这些问题,解决后应该就可以使用了。

二、rtklib代码的修改

rtkilib的头疼之处不只在于添加工作一堆问题,还在于即便添加好了,在使用其中函数的时候还是一堆问题。我这次使用主要是用最新版本rtklib_2.4.2进行GPS与北斗的标准单点定位:主要会用到readrnx、pntpos、postpos等函数(函数里面又有一堆子函数),本以为调用成功就可以了,没想到根本不是那么顺利。rtklib虽然声称能处理北斗数据和rinex3.0以上版本,但实际上并没完全实现。要想处理这些问题,还得自己修改代码。我这次主要是修改了文件读取和定位部分。

1、rinex文件读取函数的修改

a.  读取北斗导航文件的问题:rtklib在读取导航文件的时候没法区分GPS n文件与北斗c文件,这会导致后面没法进行北斗的定位。下面详述修改方法:本人的方法是在readrnxfp函数的readrnxh函数里面进行系统的标示。

如上图,在type确认出文件为导航n文件时,区分GPS与北斗。并将系统标示赋在sys里面。增加这些后,区分没问题了。但还不够,如果这样,后面还是无法区分,而且sys一直是GPS。当时这个破问题废了我两个多小时(无语死了)。后来仔细调试,才终于发现,问题出在该函数后面的一个语句有误。如下图,只需要在该处添加一个break!!!(小问题害死人!)

不要以为这样就行了,这还只是解决了系统辨认的问题,革命尚未成功!在导航文件的文件体读取中,还得修改。Readrnxnavb中需要增加处理北斗系统的语句,以与GPS区分。在增加了处理部分后,区分并读取北斗导航文件就没问题了,就不会影响到后面北斗的定位了。

b.  rinex3.0以上版本北斗观测值文件的读取:如果没进行修改就去读取含北斗的rinex3.0以上版本o文件,会发现北斗数据压根就没有读取进去。(虽然声称已解决,但不够完美)这个时候,又需要修改读取函数了。首先需要修改读取观测值文件头的函数decode_obsh中的convcode。由于3.0版本的观测值类型跟低版本的差别较大,而且GNSS系统较多,观测值类型的存储有一定转化规律,然而这个究竟如何,暂时也没有一定之规。该函数中的转化不够合理,没法处理北斗的部分

这个需要自己增加处理北斗的语句,至于具体怎么添加,主要是采用截图所示方法,但具体编码之间的对应,则各人见仁见智了。

在文件体中则需要修改readrnxobsb中用到的set_index。这个是将

改为



方法很笨拙,目前还没仔细思考更好的办法(多交流。。),不过这样就可以了。

2、  GPS以及北斗单点定位的代码修改

a.pntpos的使用:如果直接在读取了rinex文件后进行pntpos的定位操作,会发现定位结果为0。这是直接用pntpos会存在的问题。单步调试会发现其实是因为函数中用到的lam为0,仔细查找,发现其实根本没有地方给这个变量赋值。这时候需要在外部直接赋值。在处理北斗时候,由于14s(得感谢何师兄的点拨才解决)的存在,需要再卫星位置计算函数里面设置判断,当处理北斗时进行14s的处理。然后就行了。

在用此函数定位时,参数输入会很多,代码里面自带一个默认参数配置,如果切换定位系统则需要相应的修改参数。

主要是将navsys相应的切换就行。

c.  postpos的使用:postpos的单点定位实际上是用到了前述的所有函数,而且一般是作为外部调用的最佳接口。前面各个部分都改好了的话,直接使用这个函数是没问题的,如果GPS或是北斗没法定位那绝对是前面没改好。

在处理好上述问题后,用代码单独处理北斗数据或者GPS数据都是没问题的。至于如何同时都利用则是一个更复杂的问题,rtklib提供的可执行程序也没实现这个问题,这需要在以后的工作中继续研究。

三、调用函数时候参数的设置代码

函数怎么用也是一个问题,为了方便使用,贴出我的调用代码作为参考,相信可以减少不少时间。

1、  pntpos模式:

//  const char *file="d:\\rinex\\*.*";//cent1530.12o";

//  int rcv=0;//接收机编号

//  const char *opt="";//选择提取信号类型

//  obs_t *obs=new obs_t();//函数里面会分配内存

//  nav_t *nav=new nav_t();//同上

//  sta_t *sta=new sta_t();//同上

//      for (int ii=0;ii

//      {

//               nav->lam[ii][0]=CLIGHT/FREQ1;

//               nav->lam[ii][1]=CLIGHT/FREQ2;

//               nav->lam[ii][2]=CLIGHT/FREQ5;

//      }

//      for(intii=NSATGPS+NSATGLO+NSATGAL;ii

//      {

//               nav->lam[ii][0]=CLIGHT/FREQ2_CMP;

//               nav->lam[ii][1]=CLIGHT/FREQ7_CMP;

//               nav->lam[ii][2]=CLIGHT/FREQ6_CMP;

//      }

//      readrnx(file, rcv, opt, obs, nav, sta);//全部读取

//

//      char sat[4]="";

//      for (int i=0;i<25;i++)

//      {

//               satno2id(obs->data[i].sat,sat);

//               printf("%d         %s    ",obs->data[i].sat,sat);

//               cout<<setiosflags(ios::fixed)<<setprecision(4)<<obs->data[i].P[0]<<" "

//                         <<obs->data[i].P[1]<<" "

//                         <<obs->data[i].P[2]<<endl; //

//     }

//      for (int i=9;i<18;i++)

//      {

//               satno2id(nav->eph[i].sat,sat);

//               printf("%d         %s    ",nav->eph[i].sat,sat);

//               cout<<setiosflags(ios::fixed)<<setprecision(4)<<nav->eph[i].toes<<" "

//                         <<nav->eph[i].week<<endl;

//      }

//

//      cout<<"read rinex over"<<endl;

//

//      const prcopt_t prcopt_df={

//    PMODE_SINGLE,0,2,SYS_CMP,

//    15.0*D2R,{{0,0}},

//   EPHOPT_BRDC,1,1,5,0,10,

//        IONOOPT_BRDC,TROPOPT_SAAS,0,0,                    //edit by wfb

//    1,0,0,0,0,

//    0,0,

//    {100.0,100.0},

//    {100.0,0.003,0.003,0.0,1.0},

//    {30.0,0.03,0.3},

//    {1E-4,1E-3,1E-4,1E-1,1E-2},

//    5E-12,

//    {3.0,0.9999,0.20},

//    0.0,0.0,0.05,

//    30.0,30.0,30.0,

//    {0},{0},{0},

//    {"",""},

//    {{0}},{{0}},{0}

//};

//      int nn=18-9;

//      const prcopt_t *optn=new prcopt_t(prcopt_df);//前面设置好系统(GPS、北斗等)

//      sol_t *sol=new sol_t();//(sol_t*)malloc(sizeof(sol_t)*1);

//      //ssat_t *ssat=(ssat_t*)malloc(sizeof(ssat_t)*obs->n);

//    double *azel=zeros(2,nn);//

//    char *msg=new char(1024);//同上

//      //ssat_t *ssat=NULL;

//      pntpos(obs->data+9,nn,nav,optn,sol,azel,NULL,msg);//

//      for (int i=0;i

//      {

//               satno2id(obs->data[i].sat,sat);

//               printf("%s         ",sat);

//               cout<<azel[i*2]<<"  "<<azel[i*2+1]<<endl;

//      }

//

//      cout<<"single postioning over\n\npos and vel:\n"<<endl;

//      for (int i=0;i<2;i++)

//      {

//               printf("%.4f      %.4f %.4f\n",sol->rr[i*3],sol->rr[i*3+1],sol- >rr[i*3+2]);

//      }

//      cout<<"all over"<<endl;

//

//      free(azel);free(obs);free(nav);free(sta);free(sol);//free(ssat);

//      return 0;

2、  postpose模式:

const prcopt_t prcopt_df={

PMODE_SINGLE,0,2,SYS_CMP,   //                           15.0*D2R,{{0,0}},

EPHOPT_BRDC,1,1,5,0,10,

IONOOPT_BRDC,TROPOPT_SAAS,0,0,                    //edit by wfb

1,0,0,0,0,

0,0,

{100.0,100.0},

{100.0,0.003,0.003,0.0,1.0},

{30.0,0.03,0.3},

{1E-4,1E-3,1E-4,1E-1,1E-2},

5E-12,

{3.0,0.9999,0.20},

0.0,0.0,0.05,

30.0,30.0,30.0,

{0},{0},{0},

{"",""},

{{0}},{{0}},{0}

};

const solopt_t solopt_df={

SOLF_XYZ,TIMES_GPST,1,3,    //times            0,1,0,0,0,0,

0,0,0,

{0.0,0.0},

" ",""

};

gtime_t ts={0,0};

gtime_t te={0,0};

double ti=0;

double tu=0;

const prcopt_t *popt=new prcopt_t(prcopt_df);

const solopt_t *sopt=new solopt_t(solopt_df);

const filopt_t *fopt=new filopt_t();

char *infile[]={"d:\\rinex\\huashicom3.12O","d:\\rinex\\huashicom3.12C"};

int n=2;

char *outfile="D:\\pos.txt";

const char *rov="";

const char *base="";

cout<<"*********postpos start*********"<<endl;

postpos(ts,te,ti,tu,popt,sopt,fopt,infile,n,outfile,rov,base);

cout<<"*********postpos over*********"<<endl;

利用rtklib处理GPS以及北斗数据详解的更多相关文章

  1. android bundle存放数据详解

    转载自:android bundle存放数据详解 正如大家所知道,Activity之间传递数据,是将数据存放在Intent或者Bundle中 例如: 将数据存放倒Intent中传递: 将数据放到Bun ...

  2. MySQL数据库使用mysqldump导出数据详解

    mysqldump是mysql用于转存储数据库的实用程序.它主要产生一个SQL脚本,其中包含从头重新创建数据库所必需的命令CREATE TABLE INSERT等.接下来通过本文给大家介绍MySQL数 ...

  3. InheritableThreadLocal类原理简介使用 父子线程传递数据详解 多线程中篇(十八)

      上一篇文章中对ThreadLocal进行了详尽的介绍,另外还有一个类: InheritableThreadLocal 他是ThreadLocal的子类,那么这个类又有什么作用呢?   测试代码 p ...

  4. 【笔记】Pandas分类数据详解

    [笔记]Pandas分类数据详解 Pandas  Pandas分类数据详解|轻松玩转Pandas(5) 参考:Pandas分类数据详解|轻松玩转Pandas(5)

  5. Farseer.net轻量级开源框架 入门篇:添加数据详解

    导航 目   录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 入门篇: 分类逻辑层 下一篇:Farseer.net轻量级开源框架 入门篇: 修改数据详解 ...

  6. Farseer.net轻量级开源框架 入门篇:修改数据详解

    导航 目   录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 入门篇: 添加数据详解 下一篇:Farseer.net轻量级开源框架 入门篇: 删除数据详解 ...

  7. Farseer.net轻量级开源框架 入门篇:删除数据详解

    导航 目   录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 入门篇: 修改数据详解 下一篇:Farseer.net轻量级开源框架 入门篇: 查询数据详解 ...

  8. Farseer.net轻量级开源框架 入门篇:查询数据详解

    导航 目   录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 入门篇: 删除数据详解 下一篇:Farseer.net轻量级开源框架 中级篇: Where条 ...

  9. linux驱动由浅入深系列:高通sensor架构实例分析之三(adsp上报数据详解、校准流程详解)【转】

    本文转载自:https://blog.csdn.net/radianceblau/article/details/76180915 本系列导航: linux驱动由浅入深系列:高通sensor架构实例分 ...

随机推荐

  1. 【JDK】Linux安装源码包JDK完整步骤

    [JDK]Linux安装源码包JDK完整步骤 1.检查一下系统中的jdk版本 [root@localhost software]# java -version 显示: openjdk version ...

  2. 关于bat批处理的一些操作,如启动jar 关闭进程等

    先说一下学习这个的前提: 公司要写个生成uid的工具,整完了之后就又整批处理工具,出于此目的,也是为了丰富自己的知识,就学习了一下,下面是相关的批处理脚本 我花了半天的时间找了相关的bat批处理,但是 ...

  3. Mybatis通用Join的实现(最终版)

    你是否还在为mybatis的多表关联查询而写xml烦恼,是否还在为动态组装查询条件烦恼,是否还在为此没有合适的解决方案烦恼? mybatis-extension插件,解决开发过程中需要多表关联时需手写 ...

  4. java初探(1)之登录总结

    登录总结 前几章总结了登录各个步骤中遇到的问题,现在完成的做一个登录的案例,其难点不在于实现功能,而在于抽象各种功能模块,提高复用性,较低耦合度. 前端页面: 对于前端页面来说,不是后端程序员要考虑的 ...

  5. Linux服务器关联Git,通过执行更新脚本实现代码同步

    1.在Linux服务器安装Git yum install git -y   tips: 卸载Git :  yum remove git   2.在Linux生成ssh key   1)创建用户 git ...

  6. 跟着兄弟连系统学习Linux-【day02】

    day02-20200528 p6.vmvare安装与使用         官网下载安装包,个人学习的时候要求不高,所以不用安装最新版本,用不到那么多的功能,保证稳定版本就好了,然后傻瓜式安装.注意安 ...

  7. 判断同名股票是否存在的MyBatis查询函数写法

    在A股中,除非股票退市,六位的股票代号是永不变化的,而名称则可能变化,比如更换主业,更换金主,因经营不善而戴帽等,这时名称都会改变. 因此,从网页上爬取的实时股票信息,需要常常与存在本地数据库里的信息 ...

  8. springBoot 使用webSocket

    本文(2019年6月18日 飞快的蜗牛博客) 有许多人走着走着,就迷失了自己,所以不论发生了什么,有时候抱着自己去静下来想想,要好好的对待自己:"钱塘江上潮信来,今日方知我是我", ...

  9. 跟我一起学.NetCore之文件系统应用及核心浅析

    前言 在开发过程中,肯定避免不了读取文件操作,比如读取配置文件.上传和下载文件.Web中html.js.css.图片等静态资源的访问:在配置文件读取章节中有说到,针对不同配置源数据读取由对应的ICon ...

  10. python2与python3同时安装

    安装步骤: 下载 1.第一步先下载python2和python3的安装包,下载地址:https://www.python.org/downloads/windows/ 下载之后,分别给python2和 ...