利⽤rtklib处理GPS以及北⽃数据详解
利⽤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}
//};
//      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},
{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:\\";
printf怎么加endl
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;