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 }