00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 #ifndef WIN32
00022 #define _POSIX_C_SOURCE 2
00023 #endif
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <stdarg.h>
00028 #include <ctype.h>
00029 #ifdef WIN32
00030 #else
00031 #include <unistd.h>
00032 #include <errno.h>
00033 #include <pthread.h>
00034 #endif
00035 #include <rtklib/rtklib.h>
00036 
00037 #define MAXSTR      1024                
00038 #define MAXBUFF     1024                
00039 #define MAXRCVCMD   4096                
00040 #define NAVIFILE    "rtkrcv.nav"        
00041 #define STATFILE    "rtkrcv.stat"       
00042 #define TRACEFILE   "rtkrcv.trace"      
00043 #define INTKEEPALIVE 1000               
00044 
00045 #define MIN(x,y)    ((x)<(y)?(x):(y))
00046 #define MAX(x,y)    ((x)>(y)?(x):(y))
00047 #define SQRT(x)     ((x)<=0.0?0.0:sqrt(x))
00048 
00049 
00050 typedef struct {                        
00051     int type;                           
00052     int state;                          
00053     int in,out;                         
00054     int nbuff;                          
00055     char buff[MAXBUFF];                 
00056     pthread_t svr;                      
00057     pthread_t parent;                   
00058     pthread_mutex_t lock;               
00059     pthread_cond_t event;               
00060 } vt_t;
00061 
00062 
00063 static rtksvr_t svr;                    
00064 static stream_t moni;                   
00065 
00066 static FILE *logfp      =NULL;          
00067 
00068 static char passwd[MAXSTR]="admin";     
00069 static int timetype     =0;             
00070 static int soltype      =0;             
00071 static int solflag      =2;             
00072 static int strtype[]={                  
00073     STR_SERIAL,STR_NONE,STR_NONE,STR_NONE,STR_NONE,STR_NONE,STR_NONE,STR_NONE
00074 };
00075 static char strpath[8][MAXSTR]={""};    
00076 static int strfmt[]={                   
00077     STRFMT_UBX,STRFMT_RTCM3,STRFMT_SP3,SOLF_LLH,SOLF_NMEA
00078 };
00079 static int svrcycle     =10;            
00080 static int timeout      =10000;         
00081 static int reconnect    =10000;         
00082 static int nmeacycle    =5000;          
00083 static int buffsize     =32768;         
00084 static int navmsgsel    =0;             
00085 static char proxyaddr[256]="";          
00086 static int nmeareq      =0;             
00087 static double nmeapos[] ={0,0};         
00088 static char rcvcmds[3][MAXSTR]={""};    
00089 static char startcmd[MAXSTR]="";        
00090 static char stopcmd [MAXSTR]="";        
00091 static int modflgr[256] ={0};           
00092 static int modflgs[256] ={0};           
00093 static int moniport     =0;             
00094 static int keepalive    =0;             
00095 static int fswapmargin  =30;            
00096 
00097 static prcopt_t prcopt;                 
00098 static solopt_t solopt[2]={{0}};        
00099 static filopt_t filopt  ={""};          
00100 
00101 
00102 #define TIMOPT  "0:gpst,1:utc,2:jst,3:tow"
00103 #define CONOPT  "0:dms,1:deg,2:xyz,3:enu,4:pyl"
00104 #define FLGOPT  "0:off,1:std+2:age/ratio/ns"
00105 #define ISTOPT  "0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,7:ntripcli,8:ftp,9:http"
00106 #define OSTOPT  "0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripsvr"
00107 #define FMTOPT  "0:rtcm2,1:rtcm3,2:oem4,3:oem3,4:ubx,5:ss2,6:hemis,7:skytraq,8:gw10,9:javad,10:nvs,15:sp3"
00108 #define NMEOPT  "0:off,1:latlon,2:single"
00109 #define SOLOPT  "0:llh,1:xyz,2:enu,3:nmea"
00110 #define MSGOPT  "0:all,1:rover,2:base,3:corr"
00111 
00112 static opt_t rcvopts[]={
00113     {"console-passwd",  2,  (void *)passwd,              ""     },
00114     {"console-timetype",3,  (void *)&timetype,           TIMOPT },
00115     {"console-soltype", 3,  (void *)&soltype,            CONOPT },
00116     {"console-solflag", 0,  (void *)&solflag,            FLGOPT },
00117     
00118     {"inpstr1-type",    3,  (void *)&strtype[0],         ISTOPT },
00119     {"inpstr2-type",    3,  (void *)&strtype[1],         ISTOPT },
00120     {"inpstr3-type",    3,  (void *)&strtype[2],         ISTOPT },
00121     {"inpstr1-path",    2,  (void *)strpath [0],         ""     },
00122     {"inpstr2-path",    2,  (void *)strpath [1],         ""     },
00123     {"inpstr3-path",    2,  (void *)strpath [2],         ""     },
00124     {"inpstr1-format",  3,  (void *)&strfmt [0],         FMTOPT },
00125     {"inpstr2-format",  3,  (void *)&strfmt [1],         FMTOPT },
00126     {"inpstr3-format",  3,  (void *)&strfmt [2],         FMTOPT },
00127     {"inpstr2-nmeareq", 3,  (void *)&nmeareq,            NMEOPT },
00128     {"inpstr2-nmealat", 1,  (void *)&nmeapos[0],         "deg"  },
00129     {"inpstr2-nmealon", 1,  (void *)&nmeapos[1],         "deg"  },
00130     {"outstr1-type",    3,  (void *)&strtype[3],         OSTOPT },
00131     {"outstr2-type",    3,  (void *)&strtype[4],         OSTOPT },
00132     {"outstr1-path",    2,  (void *)strpath [3],         ""     },
00133     {"outstr2-path",    2,  (void *)strpath [4],         ""     },
00134     {"outstr1-format",  3,  (void *)&strfmt [3],         SOLOPT },
00135     {"outstr2-format",  3,  (void *)&strfmt [4],         SOLOPT },
00136     {"logstr1-type",    3,  (void *)&strtype[5],         OSTOPT },
00137     {"logstr2-type",    3,  (void *)&strtype[6],         OSTOPT },
00138     {"logstr3-type",    3,  (void *)&strtype[7],         OSTOPT },
00139     {"logstr1-path",    2,  (void *)strpath [5],         ""     },
00140     {"logstr2-path",    2,  (void *)strpath [6],         ""     },
00141     {"logstr3-path",    2,  (void *)strpath [7],         ""     },
00142     
00143     {"misc-svrcycle",   0,  (void *)&svrcycle,           "ms"   },
00144     {"misc-timeout",    0,  (void *)&timeout,            "ms"   },
00145     {"misc-reconnect",  0,  (void *)&reconnect,          "ms"   },
00146     {"misc-nmeacycle",  0,  (void *)&nmeacycle,          "ms"   },
00147     {"misc-buffsize",   0,  (void *)&buffsize,           "bytes"},
00148     {"misc-navmsgsel",  3,  (void *)&navmsgsel,          MSGOPT },
00149     {"misc-proxyaddr",  2,  (void *)proxyaddr,           ""     },
00150     {"misc-fswapmargin",0,  (void *)&fswapmargin,        "s"    },
00151     
00152     {"misc-startcmd",   2,  (void *)startcmd,            ""     },
00153     {"misc-stopcmd",    2,  (void *)stopcmd,             ""     },
00154     
00155     {"file-cmdfile1",   2,  (void *)rcvcmds[0],          ""     },
00156     {"file-cmdfile2",   2,  (void *)rcvcmds[1],          ""     },
00157     {"file-cmdfile3",   2,  (void *)rcvcmds[2],          ""     },
00158     
00159     {"",0,NULL,""}
00160 };
00161 
00162 
00163 static void chop(char *str)
00164 {
00165     char *p;
00166     for (p=str+strlen(str)-1;p>=str&&!isgraph((int)*p);p--) *p='\0';
00167 }
00168 
00169 static void *sendkeepalive(void *arg)
00170 {
00171     trace(3,"sendkeepalive: start\n");
00172     
00173     while (keepalive) {
00174         strwrite(&moni,(unsigned char *)"\r",1);
00175         sleepms(INTKEEPALIVE);
00176     }
00177     trace(3,"sendkeepalive: stop\n");
00178     return NULL;
00179 }
00180 
00181 static int openmoni(int port)
00182 {
00183     pthread_t thread;
00184     char path[64];
00185     
00186     trace(3,"openmomi: port=%d\n",port);
00187     
00188     sprintf(path,":%d",port);
00189     if (!stropen(&moni,STR_TCPSVR,STR_MODE_RW,path)) return 0;
00190     strsettimeout(&moni,timeout,reconnect);
00191     keepalive=1;
00192     pthread_create(&thread,NULL,sendkeepalive,NULL);
00193     return 1;
00194 }
00195 
00196 static void closemoni(void)
00197 {
00198     trace(3,"closemoni:\n");
00199     keepalive=0;
00200     
00201     
00202     strwrite(&moni,(unsigned char *)MSG_DISCONN,strlen(MSG_DISCONN));
00203     
00204     
00205     sleepms(1000);
00206     
00207     strclose(&moni);
00208 }
00209 
00210 static int readremote(vt_t *vt, char *buff, int nmax)
00211 {
00212     int n=0;
00213     
00214     trace(4,"readremote:\n");
00215     
00216     if (!vt->state) return 0;
00217     pthread_cond_wait(&vt->event,&vt->lock);
00218     if (vt->state) {
00219         n=MIN(nmax,vt->nbuff);
00220         memcpy(buff,vt->buff,n);
00221         vt->nbuff=0;
00222     }
00223     pthread_mutex_unlock(&vt->lock);
00224     return n;
00225 }
00226 
00227 static int writeremote(vt_t *vt, char *buff, int n)
00228 {
00229     char *p,*q,crlf[]="\r\n";;
00230     
00231     trace(4,"writeremote: n=%d\n",n);
00232     
00233     if (!vt->state) return 0;
00234     
00235     for (p=buff;p<buff+n;p=q+1) {
00236         if (!(q=strchr(p,'\n'))) {
00237             if (write(vt->out,p,buff+n-p)<buff+n-p) return 0;
00238             break;
00239         }
00240         if (write(vt->out,p,q-p)<q-p) return 0;
00241         if (write(vt->out,crlf,2)<2) return 0;
00242     }
00243     return 1;
00244 }
00245 
00246 static int outvt(vt_t *vt, char *buff, int n)
00247 {
00248     trace(4,"outvt: n=%d\n",n);
00249     
00250     if (logfp) fwrite(buff,n,1,logfp);
00251     if (vt->type==1) return writeremote(vt,buff,n);
00252     return write(vt->out,buff,n)==n;
00253 }
00254 
00255 static int inpvt(vt_t *vt, char *buff, int nmax)
00256 {
00257     int n;
00258     
00259     trace(4,"inpvt:\n");
00260     
00261     if (vt->type==1) n=readremote(vt,buff,nmax-1);
00262     else n=read(vt->in,buff,nmax-1);
00263     if (n<=0) {
00264         outvt(vt,"\n",1);
00265         return 0;
00266     }
00267     buff[n]='\0';
00268     if (logfp) fprintf(logfp,"%s",buff);
00269     chop(buff);
00270     return 1;
00271 }
00272 
00273 static int printvt(vt_t *vt, const char *format, ...)
00274 {
00275     va_list ap;
00276     int n;
00277     char buff[MAXSTR];
00278     
00279     trace(4,"prvt:\n");
00280     
00281     if (!vt->state) {
00282         va_start(ap,format);
00283         vfprintf(stderr,format,ap);
00284         va_end(ap);
00285         return 1;
00286     }
00287     va_start(ap,format);
00288     n=vsprintf(buff,format,ap);
00289     va_end(ap);
00290     return outvt(vt,buff,n);
00291 }
00292 
00293 static int confwrite(vt_t *vt, const char *file)
00294 {
00295     FILE *fp;
00296     char buff[MAXSTR],*p;
00297     
00298     strcpy(buff,file);
00299     if ((p=strstr(buff,"::"))) *p='\0'; 
00300     if (!vt->state||!(fp=fopen(buff,"r"))) return 1; 
00301     fclose(fp);
00302     printvt(vt,"overwrite %-16s ? (y/n): ",buff);
00303     if (!inpvt(vt,buff,sizeof(buff))) return 0;
00304     return toupper((int)buff[0])=='Y';   
00305 }
00306 
00307 static int readcmd(const char *file, char *cmd, int type)
00308 {
00309     FILE *fp;
00310     char buff[MAXSTR],*p=cmd;
00311     int i=0;
00312     
00313     trace(3,"readcmd: file=%s\n",file);
00314     
00315     if (!(fp=fopen(file,"r"))) return 0;
00316     
00317     while (fgets(buff,sizeof(buff),fp)) {
00318         if (*buff=='@') i=1;
00319         else if (i==type&&p+strlen(buff)+1<cmd+MAXRCVCMD) {
00320             p+=sprintf(p,"%s",buff);
00321         }
00322     }
00323     fclose(fp);
00324     return 1;
00325 }
00326 
00327 static void readant(vt_t *vt, prcopt_t *opt, nav_t *nav)
00328 {
00329     const pcv_t pcv0={0};
00330     pcvs_t pcvr={0},pcvs={0};
00331     pcv_t *pcv;
00332     gtime_t time=timeget();
00333     int i;
00334     
00335     trace(3,"readant:\n");
00336     
00337     opt->pcvr[0]=opt->pcvr[1]=pcv0;
00338     if (!*filopt.rcvantp) return;
00339     
00340     if (readpcv(filopt.rcvantp,&pcvr)) {
00341         for (i=0;i<2;i++) {
00342             if (!*opt->anttype[i]) continue;
00343             if (!(pcv=searchpcv(0,opt->anttype[i],time,&pcvr))) {
00344                 printvt(vt,"no antenna %s in %s",opt->anttype[i],filopt.rcvantp);
00345                 continue;
00346             }
00347             opt->pcvr[i]=*pcv;
00348         }
00349     }
00350     else printvt(vt,"antenna file open error %s",filopt.rcvantp);
00351     
00352     if (readpcv(filopt.satantp,&pcvs)) {
00353         for (i=0;i<MAXSAT;i++) {
00354             if (!(pcv=searchpcv(i+1,"",time,&pcvs))) continue;
00355             nav->pcvs[i]=*pcv;
00356         }
00357     }
00358     else printvt(vt,"antenna file open error %s",filopt.satantp);
00359     
00360     free(pcvr.pcv); free(pcvs.pcv);
00361 }
00362 
00363 static int startsvr(vt_t *vt)
00364 {
00365     double pos[3],npos[3];
00366     char s[3][MAXRCVCMD]={"","",""},*cmds[]={NULL,NULL,NULL};
00367     char *ropts[]={"","",""};
00368     char *paths[]={
00369         strpath[0],strpath[1],strpath[2],strpath[3],strpath[4],strpath[5],
00370         strpath[6],strpath[7]
00371     };
00372     int i,ret,stropt[8]={0};
00373     
00374     trace(3,"startsvr:\n");
00375     
00376     
00377     for (i=0;i<3;i++) {
00378         if (!*rcvcmds[i]) continue;
00379         if (!readcmd(rcvcmds[i],s[i],0)) {
00380             printvt(vt,"no command file: %s\n",rcvcmds[i]);
00381         }
00382         else cmds[i]=s[i];
00383     }
00384     
00385     for (i=3;i<8;i++) {
00386         if (strtype[i]==STR_FILE&&!confwrite(vt,strpath[i])) return 0;
00387     }
00388     if (prcopt.refpos==4) { 
00389         for (i=0;i<3;i++) prcopt.rb[i]=0.0;
00390     }
00391     pos[0]=nmeapos[0]*D2R;
00392     pos[1]=nmeapos[1]*D2R;
00393     pos[2]=0.0;
00394     pos2ecef(pos,npos);
00395     
00396     
00397     readant(vt,&prcopt,&svr.nav);
00398     
00399     
00400     if (solopt[0].geoid>0&&!opengeoid(solopt[0].geoid,filopt.geoid)) {
00401         trace(2,"geoid data open error: %s\n",filopt.geoid);
00402         printvt(vt,"geoid data open error: %s\n",filopt.geoid);
00403     }
00404     for (i=0;*rcvopts[i].name;i++) modflgr[i]=0;
00405     for (i=0;*sysopts[i].name;i++) modflgs[i]=0;
00406     
00407     
00408     stropt[0]=timeout;
00409     stropt[1]=reconnect;
00410     stropt[2]=1000;
00411     stropt[3]=buffsize;
00412     stropt[4]=fswapmargin;
00413     strsetopt(stropt);
00414     
00415     if (strfmt[2]==8) strfmt[2]=STRFMT_SP3;
00416     
00417     
00418     strsetdir(filopt.tempdir);
00419     strsetproxy(proxyaddr);
00420     
00421     
00422     if (*startcmd&&(ret=system(startcmd))) {
00423         trace(2,"command exec error: %s (%d)\n",startcmd,ret);
00424         printvt(vt,"command exec error: %s (%d)\n",startcmd,ret);
00425     }
00426     solopt[0].posf=strfmt[3];
00427     solopt[1].posf=strfmt[4];
00428     
00429     
00430     if (!rtksvrstart(&svr,svrcycle,buffsize,strtype,paths,strfmt,navmsgsel,
00431                      cmds,ropts,nmeacycle,nmeareq,npos,&prcopt,solopt,&moni)) {
00432         trace(2,"rtk server start error\n");
00433         printvt(vt,"rtk server start error\n");
00434         return 0;
00435     }
00436     return 1;
00437 }
00438 
00439 static void stopsvr(vt_t *vt)
00440 {
00441     char s[3][MAXRCVCMD]={"","",""},*cmds[]={NULL,NULL,NULL};
00442     int i,ret;
00443     
00444     trace(3,"stopsvr:\n");
00445     
00446     if (!svr.state) return;
00447     
00448     
00449     for (i=0;i<3;i++) {
00450         if (!*rcvcmds[i]) continue;
00451         if (!readcmd(rcvcmds[i],s[i],1)) {
00452             printvt(vt,"no command file: %s\n",rcvcmds[i]);
00453         }
00454         else cmds[i]=s[i];
00455     }
00456     
00457     rtksvrstop(&svr,cmds);
00458     
00459     
00460     if (*stopcmd&&(ret=system(stopcmd))) {
00461         trace(2,"command exec error: %s (%d)\n",stopcmd,ret);
00462         printvt(vt,"command exec error: %s (%d)\n",stopcmd,ret);
00463     }
00464     if (solopt[0].geoid>0) closegeoid();
00465 }
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 static vt_t svr_vt={0};
00489 static int outstat=0,rcv_trace=0;
00490 
00491 int loadrosopts(opt_t *opts);
00492 
00493 int start_rtkrcv(int argc, char **argv)
00494 {
00495     int i;
00496 
00497     for (i=1;i<argc;i++) {
00498         if (!strcmp(argv[i],"-m")&&i+1<argc) moniport=atoi(argv[++i]);
00499         else if (!strcmp(argv[i],"-r")&&i+1<argc) outstat=atoi(argv[++i]);
00500         else if (!strcmp(argv[i],"-t")&&i+1<argc) rcv_trace=atoi(argv[++i]);
00501         else fprintf(stderr,"Unknown option: %s\n",argv[i]);
00502     }
00503     if (rcv_trace>0) {
00504         traceopen(TRACEFILE);
00505         tracelevel(rcv_trace);
00506     }
00507     
00508     rtksvrinit(&svr);
00509     strinit(&moni);
00510 
00511     
00512     resetsysopts();
00513     loadrosopts(rcvopts);
00514     loadrosopts(sysopts);
00515     getsysopts(&prcopt,solopt,&filopt);
00516 
00517     
00518     if (!readnav(NAVIFILE,&svr.nav)) {
00519         fprintf(stderr,"no navigation data: %s\n",NAVIFILE);
00520     }
00521     if (outstat>0) {
00522         rtkopenstat(STATFILE,outstat);
00523     }
00524     
00525     if (moniport>0&&!openmoni(moniport)) {
00526         fprintf(stderr,"monitor port open error: %d\n",moniport);
00527         return 0;
00528     }
00529     
00530     if (!startsvr(&svr_vt)) return 0;
00531     return 1;
00532 }
00533 
00534 void stop_rtkrcv() {
00535     
00536     stopsvr(&svr_vt);
00537 
00538     if (moniport>0) closemoni();
00539 
00540     if (outstat>0) rtkclosestat();
00541 
00542     if (rcv_trace>0) traceclose();
00543 
00544     
00545     if (!savenav(NAVIFILE,&svr.nav)) {
00546         fprintf(stderr,"navigation data save error: %s\n",NAVIFILE);
00547     }
00548 }
00549 
00550 char get_solution(double &lat, double &lon, double &height)
00551 {
00552     rtksvrlock(&svr);
00553     const sol_t *sol = &svr.solbuf[svr.nsol-1];
00554     const double *rb = svr.rtk.rb;
00555     double pos[3]={0},Qr[9],Qe[9]={0},dms1[3]={0},dms2[3]={0},bl[3]={0};
00556     double enu[3]={0},pitch=0.0,yaw=0.0,len;
00557     int i;
00558     int status;
00559 
00560     if (sol->time.time == 0 || !sol->stat) {
00561         rtksvrunlock(&svr);
00562         return -1; 
00563     }
00564     if (1 <= sol->stat && sol->stat <= 2) status = 0; 
00565     if (sol->stat == 3)                   status = 1; 
00566     else                                  status = 2; 
00567 
00568     if (norm(sol->rr,3) > 0.0 && norm(rb,3) > 0.0) {
00569         for (i=0;i<3;i++) bl[i]=sol->rr[i]-rb[i];
00570     }
00571     len=norm(bl,3);
00572     Qr[0]=sol->qr[0];
00573     Qr[4]=sol->qr[1];
00574     Qr[8]=sol->qr[2];
00575     Qr[1]=Qr[3]=sol->qr[3];
00576     Qr[5]=Qr[7]=sol->qr[4];
00577     Qr[2]=Qr[6]=sol->qr[5];
00578 
00579     if (norm(sol->rr,3) > 0.0) {
00580         ecef2pos(sol->rr,pos);
00581         covenu(pos,Qr,Qe);
00582         lat = pos[0]*R2D;
00583         lon = pos[1]*R2D;
00584         if (solopt[0].height == 1) pos[2]-=geoidh(pos); 
00585         height = pos[2];
00586     }
00587     svr.nsol=0;
00588     rtksvrunlock(&svr);
00589     return status;
00590 }