diff --git a/app/consapp/rnx2rtkp/rnx2rtkp.c b/app/consapp/rnx2rtkp/rnx2rtkp.c index 54fe48a48..c8e30ef02 100644 --- a/app/consapp/rnx2rtkp/rnx2rtkp.c +++ b/app/consapp/rnx2rtkp/rnx2rtkp.c @@ -28,7 +28,7 @@ static const char *help[]={ "", " usage: rnx2rtkp [option]... file file [...]", "", -" Read RINEX OBS/NAV/GNAV/HNAV/CLK, SP3, SBAS message log files and ccompute ", +" Read RINEX OBS/NAV/GNAV/HNAV/CLK, SP3, SBAS message log files and compute ", " receiver (rover) positions and output position solutions.", " The first RINEX OBS file shall contain receiver (rover) observations. For the", " relative mode, the second RINEX OBS file shall contain reference", @@ -57,16 +57,22 @@ static const char *help[]={ " -c forward/backward combined solutions [off]", " -i instantaneous integer ambiguity resolution [off]", " -h fix and hold for integer ambiguity resolution [off]", +" -w widelane integer ambiguity resolution [off]", " -e output x/y/z-ecef position [latitude/longitude/height]", " -a output e/n/u-baseline [latitude/longitude/height]", " -n output NMEA-0183 GGA sentence [off]", " -g output latitude/longitude in the form of ddd mm ss.ss' [ddd.ddd]", " -t output time in the form of yyyy/mm/dd hh:mm:ss.ss [sssss.ss]", " -u output time in utc [gpst]", +" -z output single point position when unable to compute", +" DGPS/float/fix/PPP position", " -d col number of decimals in time [3]", " -s sep field separator [' ']", " -r x y z reference (base) receiver ecef pos (m) [average of single pos]", " rover receiver ecef pos (m) for fixed or ppp-fixed mode", +" -rb mode reference (base) receiver position mode (1:average of single pos,", +" 2:read from file,3:read from RINEX header,6:read from RINEX header", +" and subsequent site occupancy events) [1]", " -l lat lon hgt reference (base) receiver latitude/longitude/height (deg/m)", " rover latitude/longitude/height for fixed or ppp-fixed mode", " -y level output soltion status (0:off,1:states,2:residuals) [0]", @@ -99,16 +105,18 @@ int main(int argc, char **argv) gtime_t ts={0},te={0}; double tint=0.0,es[]={2000,1,1,0,0,0},ee[]={2000,12,31,23,59,59},pos[3]; int i,j,n,ret; - char *infile[MAXFILE],*outfile="",*p; - - prcopt.mode =PMODE_KINEMA; + char *infile[MAXFILE] = {[0 ... (MAXFILE-1)] = ""}; + char *outfile = ""; + char *p = NULL; + + prcopt.mode = PMODE_KINEMA; prcopt.navsys=0; prcopt.refpos=1; prcopt.glomodear=1; solopt.timef=0; sprintf(solopt.prog ,"%s ver.%s %s",PROGNAME,VER_RTKLIB,PATCH_LEVEL); sprintf(filopt.trace,"%s.trace",PROGNAME); - + /* load options from configuration file */ for (i=1;iReadInteger("prcopt", "dynamics", 0); PrcOpt.tidecorr =ini->ReadInteger("prcopt", "tidecorr", 0); PrcOpt.modear =ini->ReadInteger("prcopt", "modear", 1); + PrcOpt.wlmodear =ini->ReadInteger("prcopt", "wlmodear", 0); PrcOpt.glomodear=ini->ReadInteger("prcopt", "glomodear", 0); PrcOpt.bdsmodear=ini->ReadInteger("prcopt", "bdsmodear", 0); PrcOpt.maxout =ini->ReadInteger("prcopt", "maxout", 5); @@ -2701,6 +2702,7 @@ void __fastcall TMainForm::SaveOpt(void) ini->WriteInteger("prcopt", "dynamics", PrcOpt.dynamics ); ini->WriteInteger("prcopt", "tidecorr", PrcOpt.tidecorr ); ini->WriteInteger("prcopt", "modear", PrcOpt.modear ); + ini->WriteInteger("prcopt", "wlmodear", PrcOpt.wlmodear ); ini->WriteInteger("prcopt", "glomodear", PrcOpt.glomodear ); ini->WriteInteger("prcopt", "bdsmodear", PrcOpt.bdsmodear ); ini->WriteInteger("prcopt", "maxout", PrcOpt.maxout ); diff --git a/app/winapp/rtknavi/naviopt.cpp b/app/winapp/rtknavi/naviopt.cpp index 6151b3fce..839dd1f83 100644 --- a/app/winapp/rtknavi/naviopt.cpp +++ b/app/winapp/rtknavi/naviopt.cpp @@ -405,7 +405,15 @@ void __fastcall TOptDialog::GetOpt(void) IonoOpt ->ItemIndex=PrcOpt.ionoopt; TropOpt ->ItemIndex=PrcOpt.tropopt; SatEphem ->ItemIndex=PrcOpt.sateph; - AmbRes ->ItemIndex=PrcOpt.modear; + if(PrcOpt.modear>ARMODE_FIXHOLD) { + if(PrcOpt.wlmodear==0) { + AmbRes ->ItemIndex =4; + } else { + AmbRes ->ItemIndex =5; + } + } else { + AmbRes ->ItemIndex =PrcOpt.modear; + } GloAmbRes ->ItemIndex=PrcOpt.glomodear; BdsAmbRes ->ItemIndex=PrcOpt.bdsmodear; ValidThresAR ->Text =s.sprintf("%.1f",PrcOpt.thresar[0]); @@ -533,6 +541,11 @@ void __fastcall TOptDialog::SetOpt(void) PrcOpt.tropopt =TropOpt ->ItemIndex; PrcOpt.sateph =SatEphem ->ItemIndex; PrcOpt.modear =AmbRes ->ItemIndex; + PrcOpt.wlmodear=0; + if(AmbRes->ItemIndex>3) { + PrcOpt.modear=ARMODE_WL; + if(AmbRes->ItemIndex==5) PrcOpt.wlmodear=1; + } PrcOpt.glomodear =GloAmbRes ->ItemIndex; PrcOpt.bdsmodear =BdsAmbRes ->ItemIndex; PrcOpt.thresar[0]=str2dbl(ValidThresAR->Text); @@ -720,8 +733,15 @@ void __fastcall TOptDialog::LoadOpt(AnsiString file) PosOpt4 ->Checked =prcopt.posopt[3]; PosOpt5 ->Checked =prcopt.posopt[4]; PosOpt6 ->Checked =prcopt.posopt[5]; - - AmbRes ->ItemIndex =prcopt.modear; + if(prcopt.modear>ARMODE_FIXHOLD) { + if(prcopt.wlmodear==0) { + AmbRes ->ItemIndex =4; + } else { + AmbRes ->ItemIndex =5; + } + } else { + AmbRes ->ItemIndex =prcopt.modear; + } GloAmbRes ->ItemIndex =prcopt.glomodear; BdsAmbRes ->ItemIndex =prcopt.bdsmodear; ValidThresAR ->Text =s.sprintf("%.1f",prcopt.thresar[0]); @@ -937,6 +957,11 @@ void __fastcall TOptDialog::SaveOpt(AnsiString file) prcopt.posopt[5]=PosOpt6->Checked; prcopt.modear =AmbRes ->ItemIndex; + prcopt.wlmodear=0; + if(AmbRes->ItemIndex>3) { + prcopt.modear=ARMODE_WL; + if(AmbRes->ItemIndex==5) prcopt.wlmodear=1; + } prcopt.glomodear=GloAmbRes ->ItemIndex; prcopt.bdsmodear=BdsAmbRes ->ItemIndex; prcopt.thresar[0]=str2dbl(ValidThresAR->Text); diff --git a/app/winapp/rtknavi/naviopt.dfm b/app/winapp/rtknavi/naviopt.dfm index 033f793b5..7f4b469be 100644 --- a/app/winapp/rtknavi/naviopt.dfm +++ b/app/winapp/rtknavi/naviopt.dfm @@ -5,7 +5,7 @@ object OptDialog: TOptDialog BorderStyle = bsDialog Caption = 'Options' ClientHeight = 297 - ClientWidth = 411 + ClientWidth = 491 Color = clWhite Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText @@ -55,7 +55,7 @@ object OptDialog: TOptDialog object Options: TPageControl Left = 0 Top = 0 - Width = 411 + Width = 491 Height = 263 ActivePage = TabSheet1 Align = alTop @@ -481,7 +481,7 @@ object OptDialog: TOptDialog object AmbRes: TComboBox Left = 248 Top = 4 - Width = 61 + Width = 141 Height = 21 Style = csDropDownList ItemIndex = 0 @@ -492,7 +492,9 @@ object OptDialog: TOptDialog 'OFF' 'Continuous' 'Instantaneous' - 'Fix and Hold') + 'Fix and Hold' + 'Wide Lane' + 'Wide Lane with Fix and Hold') end object ValidThresAR: TEdit Left = 248 @@ -559,7 +561,7 @@ object OptDialog: TOptDialog Text = '1' end object GloAmbRes: TComboBox - Left = 311 + Left = 391 Top = 4 Width = 43 Height = 21 @@ -653,7 +655,7 @@ object OptDialog: TOptDialog 'ON') end object BdsAmbRes: TComboBox - Left = 356 + Left = 436 Top = 4 Width = 43 Height = 21 @@ -1832,7 +1834,7 @@ object OptDialog: TOptDialog ExplicitWidth = 0 ExplicitHeight = 0 DesignSize = ( - 403 + 483 235) object Label19: TLabel Left = 32 @@ -1849,7 +1851,7 @@ object OptDialog: TOptDialog Caption = 'Solution Font' end object FontLabel2: TLabel - Left = 265 + Left = 345 Top = 188 Width = 80 Height = 18 @@ -1921,7 +1923,7 @@ object OptDialog: TOptDialog Caption = 'Panel Font' end object FontLabel1: TLabel - Left = 265 + Left = 345 Top = 164 Width = 80 Height = 18 diff --git a/app/winapp/rtknavi/rtknavi.cbproj b/app/winapp/rtknavi/rtknavi.cbproj index 5fc42983c..d8d2fffda 100644 --- a/app/winapp/rtknavi/rtknavi.cbproj +++ b/app/winapp/rtknavi/rtknavi.cbproj @@ -403,6 +403,9 @@ 31 2 + + 59 + 48 15 diff --git a/app/winapp/rtkpost/postmain.cpp b/app/winapp/rtkpost/postmain.cpp index ae3653eaa..2143784b6 100644 --- a/app/winapp/rtkpost/postmain.cpp +++ b/app/winapp/rtkpost/postmain.cpp @@ -894,6 +894,11 @@ int __fastcall TMainForm::GetOption(prcopt_t &prcopt, solopt_t &solopt, prcopt.maxgdop =RejectGdop; prcopt.maxinno =RejectThres; prcopt.outsingle=OutputSingle; + prcopt.wlmodear=0; + if (AmbRes>3) { + prcopt.modear=ARMODE_WL; + if(AmbRes==5) prcopt.wlmodear=1; + } if (BaseLineConst) { prcopt.baseline[0]=BaseLine[0]; prcopt.baseline[1]=BaseLine[1]; @@ -916,7 +921,7 @@ int __fastcall TMainForm::GetOption(prcopt_t &prcopt, solopt_t &solopt, else if (RefPosType<=2) { for (int i=0;i<3;i++) prcopt.rb[i]=RefPos[i]; } - else prcopt.refpos=RefPosType-2; + else prcopt.refpos=RefPosType==6?6:RefPosType-2; if (RovAntPcv) { strcpy(prcopt.anttype[0],RovAnt.c_str()); diff --git a/app/winapp/rtkpost/postopt.cpp b/app/winapp/rtkpost/postopt.cpp index 5be742db4..b82404770 100644 --- a/app/winapp/rtkpost/postopt.cpp +++ b/app/winapp/rtkpost/postopt.cpp @@ -632,8 +632,16 @@ void __fastcall TOptDialog::LoadOpt(AnsiString file) PosOpt4 ->Checked =prcopt.posopt[3]; PosOpt5 ->Checked =prcopt.posopt[4]; PosOpt6 ->Checked =prcopt.posopt[5]; - - AmbRes ->ItemIndex =prcopt.modear; + + if(prcopt.modear>ARMODE_FIXHOLD) { + if(prcopt.wlmodear==0) { + AmbRes ->ItemIndex =4; + } else { + AmbRes ->ItemIndex =5; + } + } else { + AmbRes ->ItemIndex =prcopt.modear; + } GloAmbRes ->ItemIndex =prcopt.glomodear; BdsAmbRes ->ItemIndex =prcopt.bdsmodear; ValidThresAR ->Text =s.sprintf("%.3g",prcopt.thresar[0]); @@ -703,7 +711,7 @@ void __fastcall TOptDialog::LoadOpt(AnsiString file) IntpRefObs ->ItemIndex =prcopt.intpref; SbasSat ->Text =s.sprintf("%d",prcopt.sbassatsel); RovPosType ->ItemIndex =prcopt.rovpos==0?0:prcopt.rovpos+2; - RefPosType ->ItemIndex =prcopt.refpos==0?0:prcopt.refpos+2; + RefPosType ->ItemIndex =prcopt.refpos==0?0:prcopt.refpos==POSOPT_RINEX_DYN?6:prcopt.refpos+2; RovPosTypeP =RovPosType->ItemIndex; RefPosTypeP =RefPosType->ItemIndex; SetPos(RovPosType->ItemIndex,editu,prcopt.ru); @@ -779,6 +787,11 @@ void __fastcall TOptDialog::SaveOpt(AnsiString file) // prcopt.mapfunc =MapFunc ->ItemIndex; prcopt.modear =AmbRes ->ItemIndex; + prcopt.wlmodear=0; + if(AmbRes->ItemIndex>3) { + prcopt.modear=ARMODE_WL; + if(AmbRes->ItemIndex==5) prcopt.wlmodear=1; + } prcopt.glomodear=GloAmbRes ->ItemIndex; prcopt.bdsmodear=BdsAmbRes ->ItemIndex; prcopt.thresar[0]=str2dbl(ValidThresAR->Text); @@ -843,7 +856,7 @@ void __fastcall TOptDialog::SaveOpt(AnsiString file) prcopt.intpref =IntpRefObs->ItemIndex; prcopt.sbassatsel=SbasSat->Text.ToInt(); prcopt.rovpos=RovPosType->ItemIndex<3?0:RovPosType->ItemIndex-2; - prcopt.refpos=RefPosType->ItemIndex<3?0:RefPosType->ItemIndex-2; + prcopt.refpos=RefPosType->ItemIndex<3?0:RefPosType->ItemIndex==6?POSOPT_RINEX_DYN:RefPosType->ItemIndex-2; if (prcopt.rovpos==0) GetPos(RovPosType->ItemIndex,editu,prcopt.ru); if (prcopt.refpos==0) GetPos(RefPosType->ItemIndex,editr,prcopt.rb); diff --git a/app/winapp/rtkpost/postopt.dfm b/app/winapp/rtkpost/postopt.dfm index 31e38bdef..0632e5cb5 100644 --- a/app/winapp/rtkpost/postopt.dfm +++ b/app/winapp/rtkpost/postopt.dfm @@ -535,7 +535,8 @@ object OptDialog: TOptDialog 'Continuous' 'Instantaneous' 'Fix and Hold' - 'PPP-AR') + 'Wide Lane' + 'Wide Lane with Fix and Hold') end object ValidThresAR: TEdit Left = 248 @@ -1260,7 +1261,7 @@ object OptDialog: TOptDialog Caption = 'Delta-E/N/U (m)' end object Label24: TLabel - Left = 149 + Left = 231 Top = 17 Width = 31 Height = 13 @@ -1351,7 +1352,7 @@ object OptDialog: TOptDialog object RefPosType: TComboBox Left = 6 Top = 14 - Width = 137 + Width = 219 Height = 21 Style = csDropDownList ItemIndex = 0 @@ -1364,10 +1365,11 @@ object OptDialog: TOptDialog 'X/Y/Z-ECEF (m)' 'Average of Single Position' 'Get from Position File' - 'RINEX Header Postion') + 'RINEX Header Postion' + 'RINEX Header Position and Site Occupation Events') end object DatumRef: TComboBox - Left = 186 + Left = 268 Top = 14 Width = 76 Height = 21 diff --git a/src/options.c b/src/options.c index a64b12e31..e95507b95 100644 --- a/src/options.c +++ b/src/options.c @@ -58,8 +58,8 @@ static char snrmask_[NFREQ][1024]; #define GEOOPT "0:internal,1:egm96,2:egm08_2.5,3:egm08_1,4:gsi2000" #define STAOPT "0:all,1:single" #define STSOPT "0:off,1:state,2:residual" -#define ARMOPT "0:off,1:continuous,2:instantaneous,3:fix-and-hold" -#define POSOPT "0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm,6:raw" +#define ARMOPT "0:off,1:continuous,2:instantaneous,3:fix-and-hold,4:WLNL,5:TCAR,6:wide-lane" +#define POSOPT "0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm,6:raw,7:rinexdynamic" #define TIDEOPT "0:off,1:on,2:otl" #define PHWOPT "0:off,1:on,2:precise" @@ -86,8 +86,9 @@ EXPORT opt_t sysopts[]={ {"pos1-posopt6", 3, (void *)&prcopt_.posopt[5], SWTOPT }, {"pos1-exclsats", 2, (void *)exsats_, "prn ..."}, {"pos1-navsys", 0, (void *)&prcopt_.navsys, NAVOPT }, - + {"pos2-armode", 3, (void *)&prcopt_.modear, ARMOPT }, + {"pos2-wlarmode", 3, (void *)&prcopt_.wlmodear, SWTOPT }, {"pos2-gloarmode", 3, (void *)&prcopt_.glomodear, GAROPT }, {"pos2-bdsarmode", 3, (void *)&prcopt_.bdsmodear, SWTOPT }, {"pos2-arthres", 1, (void *)&prcopt_.thresar[0], "" }, diff --git a/src/rinex.c b/src/rinex.c index 7b8db6cf7..9cca5af80 100644 --- a/src/rinex.c +++ b/src/rinex.c @@ -647,7 +647,7 @@ static int readrnxh(FILE *fp, double *ver, char *type, int *sys, int *tsys, trace(3,"readrnxh:\n"); - *ver=2.10; *type=' '; *sys=SYS_GPS; + *ver=2.10; *type=' '; *sys=SYS_GPS; *tsys=TSYS_GPS; while (fgets(buff,MAXRNXLEN,fp)) { @@ -1015,7 +1015,14 @@ static int readrnxobsb(FILE *fp, const char *opt, double ver, int *tsys, data[n].sat=(uint8_t)sats[i-1]; /* decode RINEX observation data */ - if (decode_obsdata(fp,buff,ver,mask,index,data+n)) n++; + if (decode_obsdata(fp,buff,ver,mask,index,data+n)) { + if (sta) { + data[n].refpos[0]=sta->pos[0]; + data[n].refpos[1]=sta->pos[1]; + data[n].refpos[2]=sta->pos[2]; + } + n++; + } } else if (*flag==3||*flag==4) { /* new site or header info follows */ @@ -1035,7 +1042,7 @@ static int readrnxobs(FILE *fp, gtime_t ts, gtime_t te, double tint, uint8_t slips[MAXSAT][NFREQ+NEXOBS]={{0}}; int i,n,flag=0,stat=0; - trace(4,"readrnxobs: rcv=%d ver=%.2f tsys=%d\n",rcv,ver,tsys); + trace(4,"readrnxobs: rcv=%d ver=%.2f tsys=%d\n",rcv,ver,*tsys); if (!obs||rcv>MAXRCV) return 0; diff --git a/src/rtcm3.c b/src/rtcm3.c index 1aa92989b..252c9b906 100644 --- a/src/rtcm3.c +++ b/src/rtcm3.c @@ -113,7 +113,7 @@ const char *msm_sig_sbs[32]={ const char *msm_sig_cmp[32]={ /* BeiDou: ref [17] table 3.5-108 */ "" ,"2I","2Q","2X","" ,"" ,"" ,"6I","6Q","6X","" ,"" , - "" ,"7I","7Q","7X","" ,"" ,"" ,"" ,"" ,"" ,"" ,"" , + "" ,"7I","7Q","7X","" ,"" ,"" ,"" ,"" ,"5D","5P","5X", "" ,"" ,"" ,"" ,"" ,"" ,"" ,"" }; const char *msm_sig_irn[32]={ @@ -2088,7 +2088,7 @@ static void save_msm_obs(rtcm_t *rtcm, int sys, msm_h_t *h, const double *r, (float)(-(rr[i]+rrf[j])*freq/CLIGHT); } rtcm->obs.data[index].LLI[idx[k]]= - lossoflock(rtcm,sat,idx[k],lock[j])+(half[j]?3:0); + lossoflock(rtcm,sat,idx[k],lock[j])+(half[j]?2:0); rtcm->obs.data[index].SNR [idx[k]]=(uint16_t)(cnr[j]/SNR_UNIT+0.5); rtcm->obs.data[index].code[idx[k]]=code[k]; } diff --git a/src/rtkcmn.c b/src/rtkcmn.c index 9a0acf58c..6c55b76be 100644 --- a/src/rtkcmn.c +++ b/src/rtkcmn.c @@ -204,7 +204,7 @@ const double chisqr[100]={ /* chi-sqr(n) (alpha=0.001) */ const prcopt_t prcopt_default={ /* defaults processing options */ PMODE_SINGLE,0,2,SYS_GPS, /* mode,soltype,nf,navsys */ 15.0*D2R,{{0,0}}, /* elmin,snrmask */ - 0,1,1,1, /* sateph,modear,glomodear,bdsmodear */ + 0,1,0,1,1, /* sateph,modear,wlmodear,glomodear,bdsmodear */ 5,0,10,1, /* maxout,minlock,minfix,armaxiter */ 0,0,0,0, /* estion,esttrop,dynamics,tidecorr */ 1,0,0,0,0, /* niter,codesmooth,intpref,sbascorr,sbassatsel */ @@ -3114,10 +3114,13 @@ extern void traceobs(int level, const obsd_t *obs, int n) for (i=0;i +#include #include "rtklib.h" /* constants/macros ----------------------------------------------------------*/ @@ -1278,7 +1279,7 @@ static int ddidx(rtk_t *rtk, int *ix) /* restore SD (single-differenced) ambiguity ---------------------------------*/ static void restamb(rtk_t *rtk, const double *bias, int nb, double *xa) { - int i,n,m,f,index[MAXSAT],nv=0,nf=NF(&rtk->opt); + int i,n,m,f,index[MAXSAT]={0},index0[MAXSAT]={0},nv=0,nf=NF(&rtk->opt); trace(3,"restamb :\n"); @@ -1291,23 +1292,41 @@ static void restamb(rtk_t *rtk, const double *bias, int nb, double *xa) if (!test_sys(rtk->ssat[i].sys,m)||rtk->ssat[i].fix[f]!=2) { continue; } + if (f==0) { + index0[n]=IB(i+1,0,&rtk->opt); + } index[n++]=IB(i+1,f,&rtk->opt); } if (n<2) continue; - xa[index[0]]=rtk->x[index[0]]; - - for (i=1;iopt.modear==ARMODE_WL) { + for (i=1;i0&&index0[0]!=0&& + index0[i]!=0&& + index[0] !=0&& + index[i] !=0) { + xa[index[i]]=bias[nv++]-(xa[index0[0]]-xa[index0[i]]-xa[index[0]]); + } + } + } + else { + xa[index[0]]=rtk->x[index[0]]; + + for (i=1;inx-rtk->na,nv=0,nf=NF(&rtk->opt); - + int i,n,m,f,info,index[MAXSAT]={0},index0[MAXSAT]={0},nb=rtk->nx-rtk->na; + int nv=0,nf=NF(&rtk->opt); + trace(3,"holdamb :\n"); v=mat(nb,1); H=zeros(nb,rtk->nx); @@ -1319,16 +1338,43 @@ static void holdamb(rtk_t *rtk, const double *xa) rtk->ssat[i].azel[1]opt.elmaskhold) { continue; } + if (f==0) { + index0[n]=IB(i+1,0,&rtk->opt); + } index[n++]=IB(i+1,f,&rtk->opt); rtk->ssat[i].fix[f]=3; /* hold */ } /* constraint to fixed ambiguity */ - for (i=1;ix[index[0]]-rtk->x[index[i]]); - - H[index[0]+nv*rtk->nx]= 1.0; - H[index[i]+nv*rtk->nx]=-1.0; - nv++; + if (rtk->opt.modear==ARMODE_WL) { + for (i=1;i0&&index0[0]!=0&& + index0[i]!=0&& + index[0] !=0&& + index[i] !=0) { + v[nv]=xa[index0[0]]-xa[index0[i]] + -(xa[index[0]]-xa[index[i]]) + -(rtk->x[index0[0]]-rtk->x[index0[i]] + -(rtk->x[index[0]]-rtk->x[index[i]])); + + trace(3,"hold_amb = %lf \n",xa[index0[0]]-xa[index0[i]] + -(xa[index[0]]-xa[index[i]])); + + H[index[0]+nv*rtk->nx]= -1.0; + H[index[i]+nv*rtk->nx]= 1.0; + H[index0[0]+nv*rtk->nx]= 1.0; + H[index0[i]+nv*rtk->nx]=-1.0; + nv++; + } + } + } else { + for (i=1;ix[index[0]]-rtk->x[index[i]]); + + H[index[0]+nv*rtk->nx]= 1.0; + H[index[i]+nv*rtk->nx]=-1.0; + nv++; + } } } if (nv>0) { @@ -1343,6 +1389,174 @@ static void holdamb(rtk_t *rtk, const double *xa) } free(v); free(H); } + +/* single to double-differenced wide-lane transformation matrix (D') ---------*/ +static int dd_wl_mat(rtk_t *rtk, double *D) +{ + int i,j,k,m,f,nb=0,nx=rtk->nx,na=rtk->na,nf=NF(&rtk->opt),nofix; + + trace(3,"dd_wl_mat :\n"); + + for (i=0;issat[i].fix[j]=0; + } + for (i=0;iopt.glomodear==0)||(m==3&&rtk->opt.bdsmodear==0); + if (nofix) { + continue; + } + + k=na; + f=nf==2?1:2; + for (i=k;ix[i]==0.0|| + rtk->x[i+f*MAXSAT]==0.0|| + !test_sys(rtk->ssat[i-k].sys,m)|| + !rtk->ssat[i-k].vsat[0]|| + !rtk->ssat[i-k].half[0]|| + !rtk->ssat[i-k].vsat[f]|| + !rtk->ssat[i-k].half[f]) { + continue; + } + if (rtk->ssat[i-k].lock[0]>0&& + rtk->ssat[i-k].lock[f]>0&& + !(rtk->ssat[i-k].slip[f]&2)&& + !(rtk->ssat[i-k].slip[0]&2)&& + rtk->ssat[i-k].azel[1]>=rtk->opt.elmaskar) { + rtk->ssat[i-k].fix[0]=2; /* fix */ + rtk->ssat[i-k].fix[f]=2; /* fix */ + break; + } + else { + rtk->ssat[i-k].fix[0]=1; + rtk->ssat[i-k].fix[f]=1; + } + } + + for (j=k;jx[j]==0.0|| + rtk->x[j+f*MAXSAT]==0.0|| + !test_sys(rtk->ssat[j-k].sys,m)|| + !rtk->ssat[j-k].vsat[0]|| + !rtk->ssat[j-k].vsat[f]) { + continue; + } + if (rtk->ssat[j-k].lock[0]>0&& + rtk->ssat[j-k].lock[f]>0&& + !(rtk->ssat[j-k].slip[0]&2)&& + !(rtk->ssat[j-k].slip[f]&2)&& + rtk->ssat[j-k].azel[1]>=rtk->opt.elmaskar) { + D[i+(na+nb)*nx]= 1.0; + D[i+f*MAXSAT+(na+nb)*nx]=-1.0; + D[j+(na+nb)*nx]=-1.0; + D[j+f*MAXSAT+(na+nb)*nx]=1.0; + nb++; + rtk->ssat[j-k].fix[f]=2; /* fix */ + rtk->ssat[j-k].fix[0]=2; /* fix */ + } + else { + rtk->ssat[j-k].fix[0]=1; + rtk->ssat[j-k].fix[f]=1; + } + } + } + + trace(4,"Dw=\n"); tracemat(4,D,nx,na+nb,2,0); + return nb; +} + +/* resolve integer ambiguity by LAMBDA ---------------------------------------*/ +static int resamb_WL(rtk_t *rtk, double *bias, double *xa) +{ + prcopt_t *opt=&rtk->opt; + int i,j,ny,nb,info,nx=rtk->nx,na=rtk->na; + double *D,*DP,*y,*Qy,*b,*db,*Qb,*Qab,*QQ,s[2]; + + trace(3,"resamb_WL : nx=%d\n",nx); + + rtk->sol.ratio=0.0; + + if (rtk->opt.modear!=ARMODE_WL||rtk->opt.thresar[0]<1.0||rtk->opt.nf<2) { + return 0; + } + /* single to double-differenced wide-lane transformation matrix (D') */ + D=zeros(nx,nx); + if ((nb=dd_wl_mat(rtk,D))<=0) { + errmsg(rtk,"no valid double, wide-lane difference\n"); + free(D); + return 0; + }; + trace(2,"na = %d, nb = %d\n", na, nb); + ny=na+nb; y=mat(ny,1); Qy=mat(ny,ny); DP=mat(ny,nx); + b=mat(nb,2); db=mat(nb,1); Qb=mat(nb,nb); Qab=mat(na,nb); QQ=mat(na,nb); + + /* transform single to DD wide-lane phase-bias (y=D'*x, Qy=D'*P*D) */ + matmul("TN",ny, 1,nx,1.0,D ,rtk->x,0.0,y ); + matmul("TN",ny,nx,nx,1.0,D ,rtk->P,0.0,DP); + matmul("NN",ny,ny,nx,1.0,DP,D ,0.0,Qy); + + /* phase-bias covariance (Qb) and real-parameters to bias covariance (Qab) */ + for (i=0;ixa); + + /* covariance of fixed solution (Qa=Qa-Qab*Qb^-1*Qab') */ + matmul("NN",na,nb,nb, 1.0,Qab,Qb ,0.0,QQ); + matmul("NT",na,na,nb,-1.0,QQ ,Qab,1.0,rtk->Pa); + + trace(3,"resamb : validation ok (nb=%d ratio=%.2f s=%.2f/%.2f)\n", + nb,s[0]==0.0?0.0:s[1]/s[0],s[0],s[1]); + + /* restore single-differenced ambiguity */ + trace(2,"nb = %d\n",nb); + restamb(rtk,bias,nb,xa); + } + else nb=0; + } + else { /* validation failed */ + errmsg(rtk,"ambiguity validation failed (nb=%d ratio=%.2f s=%.2f/%.2f)\n", + nb,s[1]/s[0],s[0],s[1]); + nb=0; + } + } + else { + errmsg(rtk,"lambda error (info=%d)\n",info); + nb=0; + } + free(D); free(y); free(Qy); free(DP); + free(b); free(db); free(Qb); free(Qab); free(QQ); + + return nb; /* number of ambiguities */ +} /* resolve integer ambiguity by LAMBDA ---------------------------------------*/ static int resamb_LAMBDA(rtk_t *rtk, double *bias, double *xa) { @@ -1567,8 +1781,15 @@ static int relpos(rtk_t *rtk, const obsd_t *obs, int nu, int nr, } else stat=SOLQ_NONE; } + /* resolve integer ambiguity by WL */ + if (stat!=SOLQ_NONE&&rtk->opt.modear==ARMODE_WL) { + if (resamb_WL(rtk,bias,xa)>1) { + if (rtk->opt.wlmodear==1) holdamb(rtk,xa); + stat=SOLQ_FIX; + } + } /* resolve integer ambiguity by LAMBDA */ - if (stat!=SOLQ_NONE&&resamb_LAMBDA(rtk,bias,xa)>1) { + else if (stat!=SOLQ_NONE&&resamb_LAMBDA(rtk,bias,xa)>1) { if (zdres(0,obs,nu,rs,dts,var,svh,nav,xa,opt,0,y,e,azel,freq)) { @@ -1774,6 +1995,13 @@ extern int rtkpos(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav) for (nu=0;nu refpos==POSOPT_RINEX_DYN&&opt->mode!=PMODE_SINGLE&& + opt->mode!=PMODE_MOVEB) { + if (nr > 0) { + for (i=0;i<6;i++) rtk->rb[i]=i<3?obs[nu].refpos[i]:0.0; + } + } + time=rtk->sol.time; /* previous epoch */ /* rover position by single point positioning */