diff --git a/.clang-format b/.clang-format index b6e30e865..b73b83d49 100644 --- a/.clang-format +++ b/.clang-format @@ -4,3 +4,4 @@ BasedOnStyle: Google Language: Cpp ColumnLimit: 100 UseTab: Never +PointerAlignment: Right diff --git a/CMakeLists.txt b/CMakeLists.txt index df144105f..2aa958ff7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ message("RTKLIB version: ${VERSION}-${PATCH_LEVEL}") project(rtklib LANGUAGES C CXX VERSION 2.4.3) +include(GNUInstallDirs) include(CTest) option(IERS_MODEL "Use Earth models from IERS" OFF) diff --git a/app/consapp/convbin/bcc/_convbin.cbproj b/app/consapp/convbin/bcc/_convbin.cbproj index 23be7b23f..b6391586d 100644 --- a/app/consapp/convbin/bcc/_convbin.cbproj +++ b/app/consapp/convbin/bcc/_convbin.cbproj @@ -478,7 +478,6 @@ - diff --git a/app/consapp/convbin/convbin.c b/app/consapp/convbin/convbin.c index 44aa24234..8d3da4022 100644 --- a/app/consapp/convbin/convbin.c +++ b/app/consapp/convbin/convbin.c @@ -403,7 +403,11 @@ static int get_filetime(const char *file, gtime_t *time) struct stat st; if (!stat(path, &st)) { struct tm tm; +#ifdef _MSC_VER + if (gmtime_s(&tm, &st.st_mtime) != 0) { +#else if (gmtime_r(&st.st_mtime, &tm)) { +#endif double ep[6]; ep[0] = tm.tm_year + 1900; ep[1] = tm.tm_mon + 1; @@ -518,7 +522,7 @@ static int cmdopts(int argc, char **argv, rnxopt_t *opt, char **ifile, } } else if (!strcmp(argv[i],"-v" )&&i+1rnxver=(int)(atof(argv[++i])*100.0); + opt->rnxver=(int)round(atof(argv[++i])*100.0); } else if (!strcmp(argv[i],"-od")) { opt->obstype|=OBSTYPE_DOP; diff --git a/app/consapp/convbin/gcc/makefile b/app/consapp/convbin/gcc/makefile index 809ed5201..b6399ceac 100644 --- a/app/consapp/convbin/gcc/makefile +++ b/app/consapp/convbin/gcc/makefile @@ -52,8 +52,6 @@ ephemeris.o: $(SRC)/ephemeris.c $(CC) -c $(CFLAGS) $(SRC)/ephemeris.c novatel.o : $(SRC)/rcv/novatel.c $(CC) -c $(CFLAGS) $(SRC)/rcv/novatel.c -ss2.o : $(SRC)/rcv/ss2.c - $(CC) -c $(CFLAGS) $(SRC)/rcv/ss2.c ublox.o : $(SRC)/rcv/ublox.c $(CC) -c $(CFLAGS) $(SRC)/rcv/ublox.c crescent.o : $(SRC)/rcv/crescent.c @@ -93,7 +91,6 @@ pntpos.o : $(SRC)/rtklib.h ephemeris.o: $(SRC)/rtklib.h ionex.o : $(SRC)/rtklib.h novatel.o : $(SRC)/rtklib.h -ss2.o : $(SRC)/rtklib.h ublox.o : $(SRC)/rtklib.h crescent.o : $(SRC)/rtklib.h skytraq.o : $(SRC)/rtklib.h diff --git a/app/consapp/convbin/msc/msc.sln b/app/consapp/convbin/msc/msc.sln index 13ce11219..7407f7e8f 100644 --- a/app/consapp/convbin/msc/msc.sln +++ b/app/consapp/convbin/msc/msc.sln @@ -1,20 +1,31 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 18 +VisualStudioVersion = 18.6.11822.322 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msc", "msc.vcxproj", "{A9A9B274-2448-4FA0-AC05-857D411DCA48}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {A9A9B274-2448-4FA0-AC05-857D411DCA48}.Debug|Win32.ActiveCfg = Debug|Win32 {A9A9B274-2448-4FA0-AC05-857D411DCA48}.Debug|Win32.Build.0 = Debug|Win32 + {A9A9B274-2448-4FA0-AC05-857D411DCA48}.Debug|x64.ActiveCfg = Debug|x64 + {A9A9B274-2448-4FA0-AC05-857D411DCA48}.Debug|x64.Build.0 = Debug|x64 {A9A9B274-2448-4FA0-AC05-857D411DCA48}.Release|Win32.ActiveCfg = Release|Win32 {A9A9B274-2448-4FA0-AC05-857D411DCA48}.Release|Win32.Build.0 = Release|Win32 + {A9A9B274-2448-4FA0-AC05-857D411DCA48}.Release|x64.ActiveCfg = Release|x64 + {A9A9B274-2448-4FA0-AC05-857D411DCA48}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3E1704BE-3ED0-4969-81B9-0AD591AF4943} + EndGlobalSection EndGlobal diff --git a/app/consapp/convbin/msc/msc.vcxproj b/app/consapp/convbin/msc/msc.vcxproj index c71333b49..7186a99e8 100644 --- a/app/consapp/convbin/msc/msc.vcxproj +++ b/app/consapp/convbin/msc/msc.vcxproj @@ -5,28 +5,47 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + {A9A9B274-2448-4FA0-AC05-857D411DCA48} msc Win32Proj - 10.0.10586.0 + 10.0 Application NotSet true - v141 + v145 + + + Application + NotSet + true + v145 Application - Unicode - v141 + NotSet + v145 + + + Application + NotSet + v145 @@ -34,27 +53,36 @@ + + + + + + <_ProjectFileVersion>10.0.40219.1 $(SolutionDir)$(Configuration)\ $(Configuration)\ true + true $(SolutionDir)$(Configuration)\ $(Configuration)\ false + false convbin + convbin convbin + convbin Disabled - ..\..\..\src;%(AdditionalIncludeDirectories) - WIN32;TRACE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=3;NEXOBS=3;%(PreprocessorDefinitions) - true + ..\..\..\..\src;%(AdditionalIncludeDirectories) + WIN32;WIN_STATIC;TRACE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=4;NEXOBS=3;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -73,10 +101,32 @@ MachineX86 + + + Disabled + ..\..\..\..\src;%(AdditionalIncludeDirectories) + WIN32;WIN_STATIC;TRACE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=4;NEXOBS=3;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + winmm.lib;%(AdditionalDependencies) + $(OutDir)convbin.exe + true + Console + false + + + + - ..\..\..\src;%(AdditionalIncludeDirectories) - WIN32;TRACE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=3;NEXOBS=3;%(PreprocessorDefinitions) + ..\..\..\..\src;%(AdditionalIncludeDirectories) + WIN32;WIN_STATIC;TRACE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=4;NEXOBS=3;%(PreprocessorDefinitions) MultiThreadedDLL @@ -97,38 +147,58 @@ MachineX86 + + + ..\..\..\..\src;%(AdditionalIncludeDirectories) + WIN32;WIN_STATIC;TRACE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=4;NEXOBS=3;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + winmm.lib;%(AdditionalDependencies) + $(OutDir)convbin.exe + %(AdditionalLibraryDirectories) + true + Console + true + true + false + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - diff --git a/app/consapp/rnx2rtkp/msc/msc.sln b/app/consapp/rnx2rtkp/msc/msc.sln index 00228f3ef..6076ececf 100644 --- a/app/consapp/rnx2rtkp/msc/msc.sln +++ b/app/consapp/rnx2rtkp/msc/msc.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.14 +# Visual Studio Version 18 +VisualStudioVersion = 18.6.11822.322 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msc", "msc.vcxproj", "{830901EE-9359-489F-BA7E-04289F28D5E0}" EndProject @@ -15,12 +15,17 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {830901EE-9359-489F-BA7E-04289F28D5E0}.Debug|Win32.ActiveCfg = Debug|Win32 {830901EE-9359-489F-BA7E-04289F28D5E0}.Debug|Win32.Build.0 = Debug|Win32 - {830901EE-9359-489F-BA7E-04289F28D5E0}.Debug|x64.ActiveCfg = Debug|Win32 + {830901EE-9359-489F-BA7E-04289F28D5E0}.Debug|x64.ActiveCfg = Debug|x64 + {830901EE-9359-489F-BA7E-04289F28D5E0}.Debug|x64.Build.0 = Debug|x64 {830901EE-9359-489F-BA7E-04289F28D5E0}.Release|Win32.ActiveCfg = Release|Win32 {830901EE-9359-489F-BA7E-04289F28D5E0}.Release|Win32.Build.0 = Release|Win32 - {830901EE-9359-489F-BA7E-04289F28D5E0}.Release|x64.ActiveCfg = Release|Win32 + {830901EE-9359-489F-BA7E-04289F28D5E0}.Release|x64.ActiveCfg = Release|x64 + {830901EE-9359-489F-BA7E-04289F28D5E0}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5E8C4733-2D0A-4323-A580-F50E9C46CA7F} + EndGlobalSection EndGlobal diff --git a/app/consapp/rnx2rtkp/msc/msc.vcxproj b/app/consapp/rnx2rtkp/msc/msc.vcxproj index 7ae86f740..f5871f51f 100644 --- a/app/consapp/rnx2rtkp/msc/msc.vcxproj +++ b/app/consapp/rnx2rtkp/msc/msc.vcxproj @@ -5,10 +5,18 @@ Debug Win32 + + Debug + x64 + Release Win32 + + Release + x64 + {830901EE-9359-489F-BA7E-04289F28D5E0} @@ -21,12 +29,23 @@ Application NotSet true - v142 + v145 + + + Application + NotSet + true + v145 Application NotSet - v142 + v145 + + + Application + NotSet + v145 @@ -34,27 +53,36 @@ + + + + + + <_ProjectFileVersion>10.0.30319.1 $(SolutionDir)$(Configuration)\ $(Configuration)\ true + true $(SolutionDir)$(Configuration)\ $(Configuration)\ false + false rnx2rtkp + rnx2rtkp rnx2rtkp + rnx2rtkp Disabled ..\..\..\..\src;%(AdditionalIncludeDirectories);..\ - WIN32;TRACE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=3;NEXOBS=3;%(PreprocessorDefinitions) - false + WIN32;WIN_STATIC;TRACE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=4;NEXOBS=3;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -77,10 +105,36 @@ false + + + Disabled + ..\..\..\..\src;%(AdditionalIncludeDirectories);..\ + WIN32;WIN_STATIC;TRACE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=4;NEXOBS=3;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + $(OutDir)rnx2rtkp.exe + true + Console + false + + + winmm.lib;%(AdditionalDependencies) + false + + + false + + ..\..\..\..\src;%(AdditionalIncludeDirectories);..\ - WIN32;TRACE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=3;NEXOBS=3;%(PreprocessorDefinitions) + WIN32;WIN_STATIC;TRACE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=4;NEXOBS=3;%(PreprocessorDefinitions) MultiThreadedDLL @@ -101,13 +155,34 @@ false + + + ..\..\..\..\src;%(AdditionalIncludeDirectories);..\ + WIN32;WIN_STATIC;TRACE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=4;NEXOBS=3;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + winmm.lib;%(AdditionalDependencies) + $(OutDir)rnx2rtkp.exe + true + Console + true + true + false + + + false + + - - WIN32;TRACE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;ENAGLO;ENAQZS;ENAGAL;ENACMP;ENAIRN;NFREQ=3;NEXOBS=3;%(PreprocessorDefinitions) - + @@ -116,6 +191,7 @@ + diff --git a/app/consapp/rnx2rtkp/rnx2rtkp.c b/app/consapp/rnx2rtkp/rnx2rtkp.c index 95d2e49be..8e237dc1e 100644 --- a/app/consapp/rnx2rtkp/rnx2rtkp.c +++ b/app/consapp/rnx2rtkp/rnx2rtkp.c @@ -75,7 +75,7 @@ static const char *help[]={ " -x level debug trace level (0:off) [0]", " --rover list rover names for processing, separated by a space", " --base list base names for processing, separated by a space", -" --version display release version", +" --version display release version" }; /* show message --------------------------------------------------------------*/ extern int showmsg(const char *format, ...) @@ -193,7 +193,7 @@ int main(int argc, char **argv) else if (n sizeof(satlst) - 1) continue; + if (len + 1 + strlen(id) + 1 > sizeof(satlst)) continue; p += sprintf(p, " %s", id); } } @@ -680,9 +680,8 @@ static void prstatus(vt_t *vt) }; gtime_t eventime={0}; const char *freq[]={"-","L1","L1+L2","L1+L2+E5b","L1+L2+E5b+L5","5","6","7"}; - rtcm_t rtcm[3]; pthread_t thread; - int i,j,n,cycle,state,rtkstat,nsat0,nsat1,prcout,rcvcount,tmcount,timevalid,nave; + int j,cycle,state,rtkstat,nsat0,nsat1,prcout,rcvcount,tmcount,timevalid,nave; int cputime,nb[3]={0},nmsg[3][10]={{0}}; char tstr[40],tmstr[40],s[1024],*p; double runtime,rt[3]={0},dop[4]={0},rr[3],bl1=0.0,bl2=0.0; @@ -693,6 +692,12 @@ static void prstatus(vt_t *vt) rtk_t *rtk = (rtk_t *)malloc(sizeof(rtk_t)); if (rtk == NULL) return; + rtcm_t *rtcm[3] = { NULL, NULL, NULL }; + for (int i = 0; i < 3; i++) { + rtcm[i] = (rtcm_t *)malloc(sizeof(rtcm_t)); + if (rtcm[i] == NULL) goto done; + } + rtksvrlock(&svr); *rtk=svr.rtk; thread=svr.thread; @@ -706,8 +711,8 @@ static void prstatus(vt_t *vt) cputime=svr.cputime; prcout=svr.prcout; nave=svr.nave; - for (i=0;i<3;i++) nb[i]=svr.nb[i]; - for (i=0;i<3;i++) for (j=0;j<10;j++) { + for (int i=0;i<3;i++) nb[i]=svr.nb[i]; + for (int i=0;i<3;i++) for (j=0;j<10;j++) { nmsg[i][j]=svr.nmsg[i][j]; } if (svr.state) { @@ -715,17 +720,24 @@ static void prstatus(vt_t *vt) rt[0]=floor(runtime/3600.0); runtime-=rt[0]*3600.0; rt[1]=floor(runtime/60.0); rt[2]=runtime-rt[1]*60.0; } - for (i=0;i<3;i++) rtcm[i]=svr.rtcm[i]; + for (int i=0;i<3;i++) *rtcm[i]=svr.rtcm[i]; if (svr.raw[0].obs.data != NULL) { timevalid = svr.raw[0].obs.data[0].timevalid; eventime = svr.raw[0].obs.data[0].eventime; } time2str(eventime,tmstr,9); rtksvrunlock(&svr); - - for (i=n=0;iopt.mode==PMODE_SINGLE&&!rtk->ssat[i].vs) continue; - if (rtk->opt.mode!=PMODE_SINGLE&&!rtk->ssat[i].vsat[0]) continue; + + int n = 0; + for (int i=0;iopt.mode == PMODE_SINGLE) { + if (!rtk->ssat[i].vs) continue; + } else { + int any = 0; + for (int fi = 0; fi < NFREQ; fi++) + if (rtk->ssat[i].vsat[fi]) { any = 1; break; } + if (!any) continue; + } azel[ n*2]=rtk->ssat[i].azel[0]; azel[1+n*2]=rtk->ssat[i].azel[1]; n++; @@ -743,27 +755,31 @@ static void prstatus(vt_t *vt) vt_printf(vt,"%-28s: %d\n","cpu time for a cycle (ms)",cputime); vt_printf(vt,"%-28s: %d\n","missing obs data count",prcout); vt_printf(vt,"%-28s: %d,%d\n","bytes in input buffer",nb[0],nb[1]); - for (i=0;i<3;i++) { + for (int i=0;i<3;i++) { sprintf(s,"# of input data %s",type[i]); vt_printf(vt,"%-28s: obs(%d),nav(%d),gnav(%d),ion(%d),sbs(%d),pos(%d),dgps(%d),ssr(%d),err(%d)\n", s,nmsg[i][0],nmsg[i][1],nmsg[i][6],nmsg[i][2],nmsg[i][3], nmsg[i][4],nmsg[i][5],nmsg[i][7],nmsg[i][9]); } - for (i=0;i<3;i++) { + for (int i=0;i<3;i++) { p=s; *p='\0'; for (j=1;j<100;j++) { - if (rtcm[i].nmsg2[j]==0) continue; - p+=sprintf(p,"%s%d(%d)",p>s?",":"",j,rtcm[i].nmsg2[j]); + if (rtcm[i]->nmsg2[j]==0) continue; + p+=sprintf(p,"%s%d(%d)",p>s?",":"",j,rtcm[i]->nmsg2[j]); } - if (rtcm[i].nmsg2[0]>0) { - sprintf(p,"%sother2(%d)",p>s?",":"",rtcm[i].nmsg2[0]); + if (rtcm[i]->nmsg2[0]>0) { + sprintf(p,"%sother2(%d)",p>s?",":"",rtcm[i]->nmsg2[0]); } for (j=1;j<300;j++) { - if (rtcm[i].nmsg3[j]==0) continue; - p+=sprintf(p,"%s%d(%d)",p>s?",":"",j+1000,rtcm[i].nmsg3[j]); + if (rtcm[i]->nmsg3[j]==0) continue; + p+=sprintf(p,"%s%d(%d)",p>s?",":"",j+1000,rtcm[i]->nmsg3[j]); } - if (rtcm[i].nmsg3[0]>0) { - sprintf(p,"%sother3(%d)",p>s?",":"",rtcm[i].nmsg3[0]); + for (j=300;j<399;j++) { + if (rtcm[i]->nmsg3[j]==0) continue; + p+=sprintf(p,"%s%d(%d)",p>s?",":"",j+3770,rtcm[i]->nmsg3[j]); + } + if (rtcm[i]->nmsg3[0]>0) { + sprintf(p,"%sother3(%d)",p>s?",":"",rtcm[i]->nmsg3[0]); } vt_printf(vt,"%-15s %-9s: %s\n","# of rtcm messages",type[i],s); } @@ -812,11 +828,11 @@ static void prstatus(vt_t *vt) vt_printf(vt,"%-28s: %.3f,%.3f,%.3f\n","vel enu (m/s) base", vel[0],vel[1],vel[2]); if (rtk->opt.mode>0&&rtk->x&&norm(rtk->x,3)>0.0) { - for (i=0;i<3;i++) rr[i]=rtk->x[i]-rtk->rb[i]; + for (int i=0;i<3;i++) rr[i]=rtk->x[i]-rtk->rb[i]; bl1=norm(rr,3); } if (rtk->opt.mode>0&&rtk->xa&&norm(rtk->xa,3)>0.0) { - for (i=0;i<3;i++) rr[i]=rtk->xa[i]-rtk->rb[i]; + for (int i=0;i<3;i++) rr[i]=rtk->xa[i]-rtk->rb[i]; bl2=norm(rr,3); } vt_printf(vt,"%-28s: %.3f\n","baseline length float (m)",bl1); @@ -824,7 +840,10 @@ static void prstatus(vt_t *vt) vt_printf(vt,"%-28s: %s\n","last time mark",tmcount ? tmstr : "-"); vt_printf(vt,"%-28s: %d\n","receiver time mark count",rcvcount); vt_printf(vt,"%-28s: %d\n","rtklib time mark count",tmcount); + +done: free(rtk); + for (int i = 0; i < 3; i++) free(rtcm[i]); } /* print satellite -----------------------------------------------------------*/ static void prsatellite(vt_t *vt, int nf) @@ -842,7 +861,7 @@ static void prsatellite(vt_t *vt, int nf) *rtk=svr.rtk; rtksvrunlock(&svr); if (nf<=0||nf>NFREQ) nf=NFREQ; - vt_printf(vt,"\n%s%3s %2s %5s %4s",ESC_BOLD,"SAT","C1","Az","El"); + vt_printf(vt,"\n%s%3s %2s %5s %4s",ESC_BOLD,"SAT","V","Az","El"); for (j=0;jssat[i].azel[1]<=0.0) continue; satno2id(i+1,id); - vt_printf(vt,"%3s %2s",id,rtk->ssat[i].vs?"OK":"-"); + int vsat = 0; + if (rtk->opt.mode == PMODE_SINGLE) { + vsat = rtk->ssat[i].vs; + } else { + for (int fi = 0; fi < NFREQ; fi++) + if (rtk->ssat[i].vsat[fi]) { vsat = 1; break; } + } + vt_printf(vt,"%3s %2s",id,vsat?"OK":"-"); az=rtk->ssat[i].azel[0]*R2D; if (az<0.0) az+=360.0; el=rtk->ssat[i].azel[1]*R2D; vt_printf(vt," %5.1f %4.1f",az,el); @@ -917,34 +943,39 @@ static void probserv(vt_t *vt, int nf) free(obs); } /* print navigation data -----------------------------------------------------*/ -static void prnavidata(vt_t *vt) +static void prnavidata(vt_t *vt, int prev, int set) { eph_t eph[MAXSAT]; geph_t geph[MAXPRNGLO]; double ion[8],utc[8]; gtime_t time; char id[8],s1[64],s2[64],s3[64]; - int i,valid,prn; trace(4,"prnavidata:\n"); - + rtksvrlock(&svr); time=svr.rtk.sol.time; - for (i=0;i= 0 && set <= 1 && prev >= 0 && prev <= 1) + for (int i = 0; i < MAXSAT; i++) eph[i] = svr.nav.eph[i + (prev * 2 + set) * MAXSAT]; + else + memset(&eph, 0, sizeof(eph)); + if (set >= 0 && set <= 0 && prev >= 0 && prev <= 1) + for (int i = 0; i < MAXPRNGLO; i++) geph[i] = svr.nav.geph[i + (prev * 1 + set) * MAXPRNGLO]; + else + memset(&geph, 0, sizeof(geph)); + for (int i=0;i<8;i++) ion[i]=svr.nav.ion_gps[i]; + for (int i=0;i<8;i++) utc[i]=svr.nav.utc_gps[i]; rtksvrunlock(&svr); vt_printf(vt,"\n%s%3s %3s %3s %3s %3s %3s %3s %19s %19s %19s %3s %3s%s\n", ESC_BOLD,"SAT","S","IOD","IOC","FRQ","A/A","SVH","Toe","Toc", "Ttr/Tof","L2C","L2P",ESC_RESET); - for (i=0;i 3) + ssr[i] = svr.nav.ssr[i]; + else + ssr[i] = svr.rtcm[ri - 1].ssr[i]; } rtksvrunlock(&svr); + char *buff = (char *)malloc(128 * MAXSAT); + if (buff == NULL) return; + char *p = buff; + p+=sprintf(p,"\n%s%3s %3s %3s %3s %3s %19s %6s %6s %6s %6s %6s %6s %8s " - "%6s %6s %6s%s\n", + "%6s %6s %6s%s%s%s\n", ESC_BOLD,"SAT","S","UDI","IOD","URA","T0","D0-A","D0-C","D0-R", - "D1-A","D1-C","D1-R","C0","C1","C2","C-HR",ESC_RESET); + "D1-A","D1-C","D1-R","C0","C1","C2","C-HR", + cbias ? " CBIAS" : "", pbias ? " PBIAS" : "", ESC_RESET); for (i=0;i1) cycle=(int)(atof(args[1])*1000.0); + for (int i = 1; i < narg; i++) { + if (strcmp(args[i], "-p") == 0) { + prev = 1; + continue; + } + if (sscanf(args[i], "-%d", &set) == 1) continue; + cycle = (int)(atof(args[i]) * 1000.0); + } while (!vt_chkbrk(vt)) { if (cycle>0) vt_printf(vt,ESC_CLEAR); - prnavidata(vt); + prnavidata(vt, prev, set); if (cycle>0) sleepms(cycle); else return; } vt_printf(vt,"\n"); @@ -1202,15 +1267,26 @@ static void cmd_stream(char **args, int narg, vt_t *vt) /* ssr command ---------------------------------------------------------------*/ static void cmd_ssr(char **args, int narg, vt_t *vt) { - int cycle=0; - trace(3,"cmd_ssr:\n"); - if (narg>1) cycle=(int)(atof(args[1])*1000.0); - + int cycle = 0; + int ri = 0, cbias = 0, pbias = 0; + for (int i = 1; i < narg; i++) { + if (sscanf(args[i], "-%d", &ri) == 1) continue; + if (strcmp(args[i], "-c") == 0) { + cbias = 1; + continue; + } + if (strcmp(args[i], "-p") == 0) { + pbias = 1; + continue; + } + cycle = (int)(atof(args[i]) * 1000.0); + } + while (!vt_chkbrk(vt)) { if (cycle>0) vt_printf(vt,ESC_CLEAR); - prssr(vt); + prssr(vt, ri, cbias, pbias); if (cycle>0) sleepms(cycle); else return; } vt_printf(vt,"\n"); @@ -1646,7 +1722,7 @@ static void accept_sock(int ssock, con_t **con) inet_ntoa(addr.sin_addr)); } -static void deamonise(void) +static void daemonise(void) { #ifndef WIN32 /* In case we were not started in the background, fork and let the parent @@ -1694,7 +1770,7 @@ static void deamonise(void) * set, load or save command on the console. To shutdown the program, use * shutdown command on the console or send USR2 signal to the process. * -* The --deamon option implies no console. When used with -s or -nc the RTK +* The --daemon option implies no console. When used with -s or -nc the RTK * server is started on program startup. A telnet console can be used with * this option to start and control the RTK server. * @@ -1709,7 +1785,7 @@ static void deamonise(void) * -r level output solution status file (0:off,1:states,2:residuals) * -t level debug trace level (0:off,1-5:on) * -sta sta station name for receiver dcb -* --deamon detach from the console +* --daemon detach from the console * --version prints the version and exits * * command @@ -1740,12 +1816,19 @@ static void deamonise(void) * Show observation data. Use option cycle for cyclic display. Option -n * specify number of frequencies. * -* navidata [cycle] -* Show navigation data. Use option cycle for cyclic display. +* navidata [-p] [-n] [cycle] +* Show navigation data. Option -p shows the previous set. Option -n +* specifies the set, 0 to 1. Use option cycle for cyclic display. * * stream [cycle] * Show stream status. Use option cycle for cyclic display. * +* ssr [-[1,2,3]] [-c] [-p] [cycle] +* Show the RTCM SSR state. Option -1 -2 or -3 selects the respective +* input, output, or correction RTCM stream index otherwise the combined +* ssr state is used. Option -c includes code biases and option -p +* includes phase biases. Use option cycle for cyclic display. +* * error * Show error/warning messages. To stop messages, send break (ctr-C). * @@ -1800,9 +1883,9 @@ static void deamonise(void) int main(int argc, char **argv) { con_t *con[MAXCON]={0}; - int i,port=0,outstat=0,trace=0,sock=0; + int i,port=0,outstat=0,outstatp=0,trace=0,sock=0; char *dev="",file[MAXSTR]=""; - int deamon=0; + int daemon=0; for (i=1;i0) { traceopen(TRACEFILE); tracelevel(trace); @@ -1846,8 +1933,9 @@ int main(int argc, char **argv) if (!readnav(NAVIFILE,&svr.nav)) { fprintf(stderr,"no navigation data: %s\n",NAVIFILE); } - if (outstat>0) { - rtkopenstat(STATFILE,outstat); + if (!outstatp) outstat = solopt->sstat; + if (outstat > 0) { + rtkopenstat(filopt.solstat[0] != '\0' ? filopt.solstat : STATFILE, outstat); } /* open monitor port */ if (moniport>0&&!openmoni(moniport)) { @@ -1865,7 +1953,7 @@ int main(int argc, char **argv) } if (start&2) { /* Start without console */ startsvr(NULL); - } else if (!deamon) { + } else if (!daemon) { /* open device for local console */ if (!(con[0]=con_open(0,dev))) { fprintf(stderr,"console open error dev=%s\n",dev); diff --git a/app/consapp/str2str/gcc/makefile b/app/consapp/str2str/gcc/makefile index 3d3ab7ea6..0c6bd9c24 100644 --- a/app/consapp/str2str/gcc/makefile +++ b/app/consapp/str2str/gcc/makefile @@ -40,8 +40,6 @@ novatel.o : $(SRC)/rcv/novatel.c $(CC) -c $(CFLAGS) $(SRC)/rcv/novatel.c ublox.o : $(SRC)/rcv/ublox.c $(CC) -c $(CFLAGS) $(SRC)/rcv/ublox.c -ss2.o : $(SRC)/rcv/ss2.c - $(CC) -c $(CFLAGS) $(SRC)/rcv/ss2.c crescent.o : $(SRC)/rcv/crescent.c $(CC) -c $(CFLAGS) $(SRC)/rcv/crescent.c skytraq.o : $(SRC)/rcv/skytraq.c @@ -84,7 +82,6 @@ geoid.o : $(SRC)/rtklib.h rcvraw.o : $(SRC)/rtklib.h novatel.o : $(SRC)/rtklib.h ublox.o : $(SRC)/rtklib.h -ss2.o : $(SRC)/rtklib.h crescent.o : $(SRC)/rtklib.h skytraq.o : $(SRC)/rtklib.h javad.o : $(SRC)/rtklib.h diff --git a/app/consapp/str2str/str2str.c b/app/consapp/str2str/str2str.c index 63be61ebc..7c1708a44 100644 --- a/app/consapp/str2str/str2str.c +++ b/app/consapp/str2str/str2str.c @@ -38,7 +38,7 @@ #define PRGNAME "str2str" /* program name */ #define MAXSTR 5 /* max number of streams */ #define TRACEFILE "str2str_%Y%m%d%h%M.trace" /* Debug trace file */ -#define LOGFILE "str2str_%Y%m%d%h%M.log" /* Deamon log file */ +#define LOGFILE "str2str_%Y%m%d%h%M.log" /* Daemon log file */ /* global variables ----------------------------------------------------------*/ static strsvr_t strsvr; /* stream server */ @@ -116,7 +116,7 @@ static const char *help[]={ " -b str_no relay back messages from output str to input str [no]", " -t level trace level [0]", " -fl file log file [str2str.trace]", -" --deamon detach from the console", +" --daemon detach from the console", " --version print version", " -h print help", "", @@ -246,7 +246,7 @@ static void readcmd(const char *file, char *cmd, size_t size, int type) fclose(fp); } -static void deamonise(void) +static void daemonise(void) { #ifndef WIN32 /* In case we were not started in the background, fork and let the parent @@ -295,7 +295,7 @@ int main(int argc, char **argv) int i,j,n=0,dispint=5000,trlevel=0,opts[]={10000,10000,2000,32768,10,0,30,0}; int types[MAXSTR]={STR_FILE,STR_FILE},stat[MAXSTR]={0},log_stat[MAXSTR]={0}; int byte[MAXSTR]={0},bps[MAXSTR]={0},fmts[MAXSTR]={0},sta=0; - int deamon=0; + int daemon=0; const char *msg = "1004,1019"; // Current messages. const char *msgs[MAXSTR]; // Messages per output stream. const char *log = ""; // Log for the next input or output stream. @@ -364,7 +364,8 @@ int main(int argc, char **argv) else if (!strcmp(argv[i],"-b" )&&i+1out.sta.pos,stapos,3,1); matcpy(conv[i]->out.sta.del,stadel,3,1); } - if (deamon) deamonise(); + if (daemon) daemonise(); signal(SIGTERM,sigfunc); signal(SIGINT ,sigfunc); signal(SIGHUP ,SIG_IGN); diff --git a/app/qtapp/appcmn_qt/fileoptdlg.cpp b/app/qtapp/appcmn_qt/fileoptdlg.cpp index d8594b70b..666e5e4f9 100644 --- a/app/qtapp/appcmn_qt/fileoptdlg.cpp +++ b/app/qtapp/appcmn_qt/fileoptdlg.cpp @@ -153,10 +153,12 @@ QString FileOptDialog::getPath() //--------------------------------------------------------------------------- void FileOptDialog::filePathSelect() { + QString filename; if (!options) - ui->lEFilePath->setText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, QString(), ui->lEFilePath->text()))); + filename = QFileDialog::getOpenFileName(this, QString(), ui->lEFilePath->text()); else - ui->lEFilePath->setText(QDir::toNativeSeparators(QFileDialog::getSaveFileName(this, QString(), ui->lEFilePath->text()))); + filename = QFileDialog::getSaveFileName(this, QString(), ui->lEFilePath->text()); + if (!filename.isEmpty()) ui->lEFilePath->setText(QDir::toNativeSeparators(filename)); } //--------------------------------------------------------------------------- void FileOptDialog::keyDialogShow() diff --git a/app/qtapp/appcmn_qt/glofcndlg.cpp b/app/qtapp/appcmn_qt/glofcndlg.cpp index aa7225f83..2da7eb4cd 100644 --- a/app/qtapp/appcmn_qt/glofcndlg.cpp +++ b/app/qtapp/appcmn_qt/glofcndlg.cpp @@ -39,10 +39,6 @@ void GloFcnDialog::readRinex() return; } - filename = QFileDialog::getOpenFileName(this, tr("Open RINEX file"), "", tr("Rinex (*.obs *.*O);;All (*.*)")); - - if (filename.isEmpty()) return; - if (!readrnx(qPrintable(filename), 0, "", NULL, nav, NULL)) { free(nav); return; diff --git a/app/qtapp/appcmn_qt/navi_post_opt.cpp b/app/qtapp/appcmn_qt/navi_post_opt.cpp index ca9c89be6..cf76fbd1a 100644 --- a/app/qtapp/appcmn_qt/navi_post_opt.cpp +++ b/app/qtapp/appcmn_qt/navi_post_opt.cpp @@ -67,7 +67,12 @@ OptDialog::OptDialog(QWidget *parent, int opts) ui->cBTideCorrection->setItemData(0, tr("Not apply earth tides correction"), Qt::ToolTipRole); ui->cBTideCorrection->setItemData(1, tr("Apply solid earth tides correction"), Qt::ToolTipRole); - ui->cBTideCorrection->setItemData(2, tr("Apply solid earth tides, OTL (ocean tide loading) and pole tide corrections"), Qt::ToolTipRole); + ui->cBTideCorrection->setItemData(2, tr("Apply OTL (ocean tide loading)"), Qt::ToolTipRole); + ui->cBTideCorrection->setItemData(3, tr("Apply solid earth tides and OTL (ocean tide loading)"), Qt::ToolTipRole); + ui->cBTideCorrection->setItemData(4, tr("Apply pole tide corrections"), Qt::ToolTipRole); + ui->cBTideCorrection->setItemData(5, tr("Apply solid earth tides and pole tide corrections"), Qt::ToolTipRole); + ui->cBTideCorrection->setItemData(6, tr("Apply OTL (ocean tide loading) and pole tide corrections"), Qt::ToolTipRole); + ui->cBTideCorrection->setItemData(7, tr("Apply solid earth tides, OTL (ocean tide loading) and pole tide corrections"), Qt::ToolTipRole); ui->cBIonosphereOption->setItemData(IONOOPT_OFF, tr("Not apply ionospheric correction"), Qt::ToolTipRole); ui->cBIonosphereOption->setItemData(IONOOPT_BRDC, tr("Apply broadcast ionospheric model"), Qt::ToolTipRole); @@ -134,9 +139,9 @@ OptDialog::OptDialog(QWidget *parent, int opts) QString decSep = QRegularExpression::escape(QLocale().decimalPoint()); regExDMSLat = QRegularExpression(QString("^\\s*(?:(?[%0%1]?90)[°\\s]\\s*(?0{1,2})['\\s]\\s*(?0{1,2}(?:[%2]0*)?)\"?\\s*)|" - "(?:(?[%0%1]?(?:[1-8][0-9]|[0-9]))[°\\s]\\s*(?(?:[0-5][0-9]|[0-9]))['\\s]\\s*(?(?:[0-5][0-9]|[0-9])(?:[%2][0-9]*)?)\"?)\\s*$").arg(posSign, negSign, decSep)); + "(?:(?[%0%1]?(?:[1-8][0-9]|[0-9]))[°\\s]\\s*(?(?:[0-5][0-9]|[0-9]))['\\s]\\s*(?(?:[0-6][0-9]|[0-9])(?:[%2][0-9]*)?)\"?)\\s*$").arg(posSign, negSign, decSep)); regExDMSLon = QRegularExpression(QString("^\\s*(?:(?[%0%1]?180)[°\\s]\\s*(?0{1,2})['\\s]\\s*(?0{1,2}(?:[%2]0*)?)\"?\\s*)|" - "(?:(?[%0%1]?(?:1[0-7][0-9]|[0-9][0-9]|[0-9]))[°\\s]\\s*(?(?:[0-5][0-9]|[0-9]))['\\s]\\s*(?(?:[0-5][0-9]|[0-9])(?:[%2][0-9]*)?)\"?)\\s*$").arg(posSign, negSign, decSep)); + "(?:(?[%0%1]?(?:1[0-7][0-9]|[0-9][0-9]|[0-9]))[°\\s]\\s*(?(?:[0-5][0-9]|[0-9]))['\\s]\\s*(?(?:[0-6][0-9]|[0-9])(?:[%2][0-9]*)?)\"?)\\s*$").arg(posSign, negSign, decSep)); processingOptions = prcopt_default; @@ -169,6 +174,9 @@ OptDialog::OptDialog(QWidget *parent, int opts) navSelect = 0; /* navigation mesaage select */ proxyaddr[0] = '\0'; /* proxy address */ + current_roverPositionType = -1; + current_referencePositionType = -1; + static opt_t _naviopt[] = { { "misc-svrcycle", 0, (void *)&serverCycle, "ms" }, { "misc-timeout", 0, (void *)&timeoutTime, "ms" }, @@ -429,10 +437,15 @@ void OptDialog::showSnrMaskDialog() //--------------------------------------------------------------------------- void OptDialog::roverPositionTypeChanged(int) { - QLineEdit *edit[] = {ui->lERoverPosition1, ui->lERoverPosition2, ui->lERoverPosition3}; - double pos[3]; + // Startup guard. + if (current_roverPositionType < 0 ) { + current_roverPositionType = ui->cBRoverPositionType->currentIndex(); + return; + } // update position value in accordance to type + QLineEdit *edit[] = {ui->lERoverPosition1, ui->lERoverPosition2, ui->lERoverPosition3}; + double pos[3]; int error = getPosition(current_roverPositionType, edit, pos); if (error) { ui->cBRoverPositionType->setCurrentIndex(current_roverPositionType); // don't allow to change the type @@ -445,6 +458,12 @@ void OptDialog::roverPositionTypeChanged(int) //--------------------------------------------------------------------------- void OptDialog::referencePositionTypeChanged(int) { + // Startup guard. + if (current_referencePositionType < 0 ) { + current_referencePositionType = ui->cBReferencePositionType->currentIndex(); + return; + } + QLineEdit *edit[] = {ui->lEReferencePosition1, ui->lEReferencePosition2, ui->lEReferencePosition3}; double pos[3]; @@ -651,7 +670,6 @@ void OptDialog::selectSolutionFont() //--------------------------------------------------------------------------- void OptDialog::updateOptions() { - double rovPos[3], refPos[3]; QLineEdit *editu[] = {ui->lERoverPosition1, ui->lERoverPosition2, ui->lERoverPosition3 }; QLineEdit *editr[] = {ui->lEReferencePosition1, ui->lEReferencePosition2, ui->lEReferencePosition3 }; pcvs_t pcvr; @@ -705,8 +723,7 @@ void OptDialog::updateOptions() processingOptions.ionoopt = ui->cBIonosphereOption->currentIndex(); processingOptions.tropopt = ui->cBTroposphereOption->currentIndex(); processingOptions.dynamics = ui->cBDynamicModel->currentIndex(); - processingOptions.tidecorr = ui->cBTideCorrection->currentIndex(); - if (processingOptions.tidecorr > 1) processingOptions.tidecorr = 7; + processingOptions.tidecorr = ui->cBTideCorrection->currentIndex() & 7; processingOptions.niter = ui->sBNumIteration->value(); // codesmooth processingOptions.intpref = ui->cBIntputReferenceObservation->currentIndex(); @@ -756,6 +773,7 @@ void OptDialog::updateOptions() processingOptions.baseline[1] = 0.0; } + double rovPos[3], refPos[3]; getPosition(ui->cBRoverPositionType->currentIndex(), editu, rovPos); getPosition(ui->cBReferencePositionType->currentIndex(), editr, refPos); @@ -933,7 +951,7 @@ void OptDialog::updateUi(const prcopt_t &prcopt, const solopt_t &solopt, const f ui->cBIonosphereOption->setCurrentIndex(prcopt.ionoopt); ui->cBTroposphereOption->setCurrentIndex(prcopt.tropopt); ui->cBDynamicModel->setCurrentIndex(prcopt.dynamics); - ui->cBTideCorrection->setCurrentIndex(prcopt.tidecorr > 1 ? 2 : prcopt.tidecorr); + ui->cBTideCorrection->setCurrentIndex(prcopt.tidecorr & 7); ui->sBNumIteration->setValue(prcopt.niter); //prcopt.codesmooth if (options == PostOptions) { @@ -1132,8 +1150,7 @@ void OptDialog::save(const QString &file) procOpts.ionoopt = ui->cBIonosphereOption->currentIndex(); procOpts.tropopt = ui->cBTroposphereOption->currentIndex(); procOpts.dynamics = ui->cBDynamicModel->currentIndex(); - procOpts.tidecorr = ui->cBTideCorrection->currentIndex(); - if (procOpts.tidecorr > 1) procOpts.tidecorr = 7; + procOpts.tidecorr = ui->cBTideCorrection->currentIndex() & 7; procOpts.niter = ui->sBNumIteration->value(); // procOpts.codesmooth procOpts.intpref = ui->cBIntputReferenceObservation->currentIndex(); @@ -1274,7 +1291,6 @@ void OptDialog::save(const QString &file) //--------------------------------------------------------------------------- void OptDialog::saveOptions(QSettings &settings) { - double rovPos[3], refPos[3]; QLineEdit *editu[] = {ui->lERoverPosition1, ui->lERoverPosition2, ui->lERoverPosition3}; QLineEdit *editr[] = {ui->lEReferencePosition1, ui->lEReferencePosition2, ui->lEReferencePosition3}; @@ -1312,7 +1328,7 @@ void OptDialog::saveOptions(QSettings &settings) settings.setValue("prcopt/ionoopt", ui->cBIonosphereOption->currentIndex()); settings.setValue("prcopt/tropopt", ui->cBTroposphereOption->currentIndex()); settings.setValue("prcopt/dynamics", ui->cBDynamicModel->currentIndex()); - settings.setValue("prcopt/tidecorr", ui->cBTideCorrection->currentIndex()); + settings.setValue("prcopt/tidecorr", ui->cBTideCorrection->currentIndex() & 7); settings.setValue("prcopt/niter", ui->sBNumIteration->value()); // settings.setValue("prcopt/codesmooth", processingOptions.codesmooth); settings.setValue("prcopt/intpref", ui->cBIntputReferenceObservation->currentIndex()); @@ -1323,6 +1339,7 @@ void OptDialog::saveOptions(QSettings &settings) settings.setValue("setting/rovpostype", ui->cBRoverPositionType->currentIndex()); settings.setValue("setting/refpostype", ui->cBReferencePositionType->currentIndex()); + double rovPos[3] = {0}, refPos[3] = {0}; if (ui->cBRoverPositionType->currentIndex() < 3) getPosition(ui->cBRoverPositionType->currentIndex(), editu, rovPos); if (ui->cBReferencePositionType->currentIndex() < 3) getPosition(ui->cBReferencePositionType->currentIndex(), editr, refPos); @@ -1473,7 +1490,6 @@ void OptDialog::saveOptions(QSettings &settings) //--------------------------------------------------------------------------- void OptDialog::loadOptions(QSettings &settings) { - double rovPos[3], refPos[3]; QLineEdit *editu[] = {ui->lERoverPosition1, ui->lERoverPosition2, ui->lERoverPosition3}; QLineEdit *editr[] = {ui->lEReferencePosition1, ui->lEReferencePosition2, ui->lEReferencePosition3}; @@ -1481,7 +1497,7 @@ void OptDialog::loadOptions(QSettings &settings) ui->cBPositionMode->setCurrentIndex(settings.value("prcopt/mode", 0).toInt()); ui->cBSolution->setCurrentIndex(settings.value("prcopt/soltype", 0).toInt()); ui->cBFrequencies->setCurrentIndex(settings.value("prcopt/nf", 2).toInt() > NFREQ - 1 ? NFREQ - 1 : settings.value("prcopt/nf", 2).toInt() - 1); - int navsys = settings.value("prcopt/navsys", SYS_GPS).toInt(); + int navsys = settings.value("prcopt/navsys", SYS_GPS | SYS_GLO | SYS_GAL | SYS_CMP).toInt(); ui->cBNavSys1->setChecked(navsys & SYS_GPS); ui->cBNavSys2->setChecked(navsys & SYS_GLO); ui->cBNavSys3->setChecked(navsys & SYS_GAL); @@ -1511,7 +1527,7 @@ void OptDialog::loadOptions(QSettings &settings) ui->cBIonosphereOption->setCurrentIndex(settings.value("prcopt/ionoopt", IONOOPT_BRDC).toInt()); ui->cBTroposphereOption->setCurrentIndex(settings.value("prcopt/tropopt", TROPOPT_SAAS).toInt()); ui->cBDynamicModel->setCurrentIndex(settings.value("prcopt/dynamics", 0).toInt()); - ui->cBTideCorrection->setCurrentIndex(settings.value("prcopt/tidecorr", 0).toInt()); + ui->cBTideCorrection->setCurrentIndex(settings.value("prcopt/tidecorr", 0).toInt() & 7); ui->sBNumIteration->setValue(settings.value("prcopt/niter", 1).toInt()); // processingOptions.codesmooth = settings.value("prcopt/codesmooth", 0).toInt(); if (options == PostOptions) { @@ -1533,9 +1549,9 @@ void OptDialog::loadOptions(QSettings &settings) ui->sBMeasurementError3->setValue(settings.value("prcopt/err2", 0.003).toDouble()); ui->sBMeasurementError4->setValue(settings.value("prcopt/err3", 0.0).toDouble()); ui->sBMeasurementError5->setValue(settings.value("prcopt/err4", 1.0).toDouble()); - ui->sBMeasurementErrorSNR_Max->setValue(settings.value("prcopt/err5", 1.0).toDouble()); - ui->sBMeasurementErrorSNR->setValue(settings.value("prcopt/err6", 1.0).toDouble()); - ui->sBMeasurementErrorReceiver->setValue(settings.value("prcopt/err7", 1.0).toDouble()); + ui->sBMeasurementErrorSNR_Max->setValue(settings.value("prcopt/err5", 52.0).toDouble()); + ui->sBMeasurementErrorSNR->setValue(settings.value("prcopt/err6", 0.000).toDouble()); + ui->sBMeasurementErrorReceiver->setValue(settings.value("prcopt/err7", 0.000).toDouble()); // std ui->sBProcessNoise1->setValue(settings.value("prcopt/prn0", 1E-4).toDouble()); ui->sBProcessNoise2->setValue(settings.value("prcopt/prn1", 1E-3).toDouble()); @@ -1543,15 +1559,15 @@ void OptDialog::loadOptions(QSettings &settings) ui->sBProcessNoise4->setValue(settings.value("prcopt/prn3", 10.0).toDouble()); ui->sBProcessNoise5->setValue(settings.value("prcopt/prn4", 10.0).toDouble()); ui->sBSatelliteClockStability->setValue(settings.value("prcopt/sclkstab", 5E-12).toDouble()); - ui->sBValidThresAR->setValue(settings.value("prcopt/thresar0", 100.0).toDouble()); - ui->sBMaxPositionVarAR->setValue(settings.value("prcopt/thresar1", 100.0).toDouble()); - ui->sBGlonassHwBias->setValue(settings.value("prcopt/thresar2", 100.0).toDouble()); - ui->sBValidThresARMin->setValue(settings.value("prcopt/thresar5", 100.0).toDouble()); - ui->sBValidThresARMax->setValue(settings.value("prcopt/thresar6", 100.0).toDouble()); + ui->sBValidThresAR->setValue(settings.value("prcopt/thresar0", 3.0).toDouble()); + ui->sBMaxPositionVarAR->setValue(settings.value("prcopt/thresar1", 0.25).toDouble()); + ui->sBGlonassHwBias->setValue(settings.value("prcopt/thresar2", 0.0).toDouble()); + ui->sBValidThresARMin->setValue(settings.value("prcopt/thresar5", 3.0).toDouble()); + ui->sBValidThresARMax->setValue(settings.value("prcopt/thresar6", 3.0).toDouble()); ui->sBElevationMaskAR->setValue(settings.value("prcopt/elmaskar", 0.0).toDouble()); ui->sBElevationMaskHold->setValue(settings.value("prcopt/elmaskhold", 0.0).toDouble()); ui->sBSlipThreshold->setValue(settings.value("prcopt/thresslip", 0.05).toDouble()); - ui->sBDopplerThreshold->setValue(settings.value("prcopt/thresdop", 0.05).toDouble()); + ui->sBDopplerThreshold->setValue(settings.value("prcopt/thresdop", 0.00).toDouble()); ui->sBVarHoldAmb->setValue(settings.value("prcopt/varholdamb", 0.1).toDouble()); ui->sBGainHoldAmb->setValue(settings.value("prcopt/gainholdamb", 0.01).toDouble()); ui->sBMaxAgeDifferences->setValue(settings.value("prcopt/maxtdiff", 30.0).toDouble()); @@ -1569,6 +1585,7 @@ void OptDialog::loadOptions(QSettings &settings) ui->cBRoverAntenna->setCurrentIndex(ui->cBRoverAntenna->findText(settings.value("prcopt/anttype1", "").toString())); ui->cBReferenceAntenna->setCurrentIndex(ui->cBReferenceAntenna->findText(settings.value("prcopt/anttype2", "").toString())); + double rovPos[3], refPos[3]; for (int i = 0; i < 3; i++) { rovPos[i] = settings.value(QStringLiteral("setting/rovpos_%1").arg(i), 0.0).toDouble(); refPos[i] = settings.value(QStringLiteral("setting/refpos_%1").arg(i), 0.0).toDouble(); @@ -1913,8 +1930,8 @@ void OptDialog::setPosition(int type, QLineEdit **edit, const double *pos) ecef2pos(pos, p); s1 = p[0] < 0 ? -1 : 1; s2 = p[1] < 0 ? -1 : 1; - p[0] = fabs(p[0]) * R2D + 1E-12; - p[1] = fabs(p[1]) * R2D + 1E-12; + p[0] = fabs(p[0]) * R2D; + p[1] = fabs(p[1]) * R2D; dms1[0] = floor(p[0]); p[0] = (p[0] - dms1[0]) * 60.0; dms1[1] = floor(p[0]); dms1[2] = (p[0] - dms1[1]) * 60.0; dms2[0] = floor(p[1]); p[1] = (p[1] - dms2[0]) * 60.0; diff --git a/app/qtapp/appcmn_qt/navi_post_opt.ui b/app/qtapp/appcmn_qt/navi_post_opt.ui index a69e2df57..626b21d55 100644 --- a/app/qtapp/appcmn_qt/navi_post_opt.ui +++ b/app/qtapp/appcmn_qt/navi_post_opt.ui @@ -190,11 +190,36 @@ Solid + + + OTL + + Solid/OTL + + + S.Pole + + + + + Solid/S.Pole + + + + + OTL/S.Pole + + + + + Solid/OTL/S.Pole + + @@ -931,7 +956,7 @@ - <html><head/><body><p>Set the cycle-slip threshold (Hz) of difference between doppler and carrier phase difference between epochs, 0 = disabled (option: <span style=" font-style:italic;">pos2-dopthres).</span></p></body></html> + <html><head/><body><p>Set the cycle-slip threshold (m/s) of difference between doppler and carrier phase difference between epochs, 0 = disabled (option: <span style=" font-style:italic;">pos2-dopthres).</span></p></body></html> Hz @@ -1118,7 +1143,7 @@ - <html><head/><body><p>Set the reject threshold of the kalman filter innovations (option: <span style=" font-style:italic;">pos2-rejionn</span>). </p><p>If the carrier phase innovation is over the value, the observable is excluded for the estimation process as an outlier. The innovation threshold is multiplied by the carrier phase/pseudorange error ratio to generate the threshold for pseudorange innovations.</p></body></html> + <html><head/><body><p>Set the reject threshold (m) of the kalman filter innovations (option: <span style=" font-style:italic;">pos2-rejphase</span>). </p><p>If the carrier phase innovation is over the value, the observable is excluded for the estimation process as an outlier. The innovation threshold is multiplied by the carrier phase/pseudorange error ratio to generate the threshold for pseudorange innovations.</p></body></html> m @@ -1976,6 +2001,9 @@ 3 + + 0.001 + @@ -2080,6 +2108,12 @@ <html><head/><body><p>Set the SNR dependent terms of carrier-phase error standard deviation (option: <span style=" font-style:italic;">stats-errsnr</span>)</p><p>e * 10^(0.1*(SNR_MAX - snr))</p></body></html> + + 3 + + + 0.001 + @@ -2798,7 +2832,7 @@ - <html><head/><body><p>Set the re-connect interval for TCP client and NTRIP client connections (option <span style=" font-style:italic;">misc-reconnect</span>). </p><p>If the timeout time expired without sever response, RTKNAVI retries to connect to server after waiting for the re-connect interval.</p></body></html> + <html><head/><body><p>Set the re-connect interval for TCP client and NTRIP client connections (option <span style=" font-style:italic;">misc-reconnect</span>). </p><p>If the timeout time expired without server response, RTKNAVI retries to connect to server after waiting for the re-connect interval.</p></body></html> ms @@ -2924,7 +2958,7 @@ - <html><head/><body><p>Set the timeout interval for TCP client and NTRIP client connections (option <span style=" font-style:italic;">misc-timeout</span>).</p><p>If the timeout time expired without sever response, RTKNAVI retries to connect to server after waiting for the reconnect interval.</p></body></html> + <html><head/><body><p>Set the timeout interval for TCP client and NTRIP client connections (option <span style=" font-style:italic;">misc-timeout</span>).</p><p>If the timeout time expired without server response, RTKNAVI retries to connect to server after waiting for the reconnect interval.</p></body></html> ms diff --git a/app/qtapp/appcmn_qt/refdlg.cpp b/app/qtapp/appcmn_qt/refdlg.cpp index 2b29893d1..6a4d45866 100644 --- a/app/qtapp/appcmn_qt/refdlg.cpp +++ b/app/qtapp/appcmn_qt/refdlg.cpp @@ -73,8 +73,9 @@ void RefDialog::accept() //--------------------------------------------------------------------------- void RefDialog::loadStations() { - stationPositionFile = QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Load Station List..."), stationPositionFile, tr("Position File (*.pos *.snx);;All (*.*)"))); - + QString filename = QFileDialog::getOpenFileName(this, tr("Load Station List..."), stationPositionFile, tr("Position File (*.pos *.snx);;All (*.*)")); + if (filename.isEmpty()) return; + stationPositionFile = QDir::toNativeSeparators(filename); loadList(stationPositionFile); } //--------------------------------------------------------------------------- @@ -123,8 +124,8 @@ void RefDialog::loadList(QString filename) for (int i = 0; i < 3; i++) pos[i] = tokens.at(i).toDouble(); - addReference(n, pos, tokens.size() > 3 ? tokens.at(3) : "", - tokens.size() > 4 ? tokens.at(4) : ""); + addReference(n, pos, tokens.size() > 3 ? tokens.at(3) : QString(""), + tokens.size() > 4 ? tokens.at(4) : QString("")); } if (n == 0) ui->tWStationList->setRowCount(0); diff --git a/app/qtapp/appcmn_qt/tcpoptdlg.cpp b/app/qtapp/appcmn_qt/tcpoptdlg.cpp index b280ce51a..f90cf8b97 100644 --- a/app/qtapp/appcmn_qt/tcpoptdlg.cpp +++ b/app/qtapp/appcmn_qt/tcpoptdlg.cpp @@ -219,7 +219,8 @@ void TcpOptDialog::btnNtripClicked() ui->cBMountPoint->clear(); for (p = buff; (p = strstr(p, "STR;")); p+=4) { if (sscanf(p, "STR;%255[^;]", mntpnt) == 1) { - ui->cBMountPoint->addItem(mntpnt, QString(p).split('\n', Qt::SkipEmptyParts).first()); + QString str = QString(p).split('\n', Qt::SkipEmptyParts).first().trimmed(); + ui->cBMountPoint->addItem(mntpnt, str); } } btn->setEnabled(true); diff --git a/app/qtapp/appcmn_qt/viewer.cpp b/app/qtapp/appcmn_qt/viewer.cpp index 6085b441b..6c9988ffa 100644 --- a/app/qtapp/appcmn_qt/viewer.cpp +++ b/app/qtapp/appcmn_qt/viewer.cpp @@ -57,10 +57,13 @@ void TextViewer::reloadText() //--------------------------------------------------------------------------- void TextViewer::readSaveFile() { - if (ui->btnReadSave->text() == tr("&Save...")) - save(QDir::toNativeSeparators(QFileDialog::getSaveFileName(this, QString(), file))); - else - read(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, QString(), file))); + if (ui->btnReadSave->text() == tr("&Save...")) { + QString filename = QFileDialog::getSaveFileName(this, QString(), file); + if (!filename.isEmpty()) save(QDir::toNativeSeparators(filename)); + } else { + QString filename = QFileDialog::getOpenFileName(this, QString(), file); + if (!filename.isEmpty()) read(QDir::toNativeSeparators(filename)); + } } //--------------------------------------------------------------------------- void TextViewer::showOptions() diff --git a/app/qtapp/rtkconv_qt/convmain.cpp b/app/qtapp/rtkconv_qt/convmain.cpp index 68c666ebd..183cc6d93 100644 --- a/app/qtapp/rtkconv_qt/convmain.cpp +++ b/app/qtapp/rtkconv_qt/convmain.cpp @@ -448,7 +448,7 @@ void MainWindow::showStopTimeDialog() void MainWindow::selectInputFile() { QString filename = QFileDialog::getOpenFileName(this, tr("Input RTCM, RCV RAW or RINEX File"), ui->cBInputFile->currentText(), - tr("All (*.*);;RTCM 2 (*.rtcm2);;RTCM 3 (*.rtcm3);;NovtAtel (*.gps);;ublox (*.ubx);;SuperStart II (*.log);;" + tr("All (*.*);;RTCM 2 (*.rtcm2);;RTCM 3 (*.rtcm3);;NovtAtel (*.gps);;ublox (*.ubx);;" "Hemisphere (*.bin);;Javad (*.jps);;RINEX OBS (*.obs *.*O);;Septentrio (*.sbf)")); if (!filename.isEmpty()) { diff --git a/app/qtapp/rtkconv_qt/rtklib_de.ts b/app/qtapp/rtkconv_qt/rtklib_de.ts index 5a1ad38b2..14f4a80c3 100644 --- a/app/qtapp/rtkconv_qt/rtklib_de.ts +++ b/app/qtapp/rtkconv_qt/rtklib_de.ts @@ -2364,7 +2364,7 @@ Copyright (C) 2016-2024 Jens Reimann - All (*.*);;RTCM 2 (*.rtcm2);;RTCM 3 (*.rtcm3);;NovtAtel (*.gps);;ublox (*.ubx);;SuperStart II (*.log);;Hemisphere (*.bin);;Javad (*.jps);;RINEX OBS (*.obs *.*O);Septentrio (*.sbf) + All (*.*);;RTCM 2 (*.rtcm2);;RTCM 3 (*.rtcm3);;NovtAtel (*.gps);;ublox (*.ubx);;Hemisphere (*.bin);;Javad (*.jps);;RINEX OBS (*.obs *.*O);Septentrio (*.sbf) diff --git a/app/qtapp/rtkconv_qt/rtklib_zh_CN.ts b/app/qtapp/rtkconv_qt/rtklib_zh_CN.ts index 575f960c1..1388fc508 100644 --- a/app/qtapp/rtkconv_qt/rtklib_zh_CN.ts +++ b/app/qtapp/rtkconv_qt/rtklib_zh_CN.ts @@ -2262,8 +2262,8 @@ Copyright (C) 2016-2025 Jens Reimann - All (*.*);;RTCM 2 (*.rtcm2);;RTCM 3 (*.rtcm3);;NovtAtel (*.gps);;ublox (*.ubx);;SuperStart II (*.log);;Hemisphere (*.bin);;Javad (*.jps);;RINEX OBS (*.obs *.*O);;Septentrio (*.sbf) - 所有文件 (*.*);;RTCM 2 (*.rtcm2);;RTCM 3 (*.rtcm3);;NovtAtel (*.gps);;ublox (*.ubx);;SuperStart II (*.log);;Hemisphere (*.bin);;Javad (*.jps);;RINEX OBS (*.obs *.*O);;Septentrio (*.sbf) + All (*.*);;RTCM 2 (*.rtcm2);;RTCM 3 (*.rtcm3);;NovtAtel (*.gps);;ublox (*.ubx);;Hemisphere (*.bin);;Javad (*.jps);;RINEX OBS (*.obs *.*O);;Septentrio (*.sbf) + 所有文件 (*.*);;RTCM 2 (*.rtcm2);;RTCM 3 (*.rtcm3);;NovtAtel (*.gps);;ublox (*.ubx);;Hemisphere (*.bin);;Javad (*.jps);;RINEX OBS (*.obs *.*O);;Septentrio (*.sbf) diff --git a/app/qtapp/rtklaunch_qt/CMakeLists.txt b/app/qtapp/rtklaunch_qt/CMakeLists.txt index 6013ead83..96c2e0cb8 100644 --- a/app/qtapp/rtklaunch_qt/CMakeLists.txt +++ b/app/qtapp/rtklaunch_qt/CMakeLists.txt @@ -26,7 +26,7 @@ set_target_properties(rtklaunch_qt PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON ) -install(TARGETS rtkget_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) +install(TARGETS rtklaunch_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) if (UNIX) install(FILES rtklaunch_qt.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) install(FILES ../icon/rtklaunch.png DESTINATION ${XDG_APPS_PIXMAPS_DIR}) diff --git a/app/qtapp/rtknavi_qt/CMakeLists.txt b/app/qtapp/rtknavi_qt/CMakeLists.txt index 3e176f7e9..dd8564e0e 100644 --- a/app/qtapp/rtknavi_qt/CMakeLists.txt +++ b/app/qtapp/rtknavi_qt/CMakeLists.txt @@ -81,7 +81,7 @@ set_target_properties(rtknavi_qt PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON ) -install(TARGETS rtkget_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) +install(TARGETS rtknavi_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) if (UNIX) install(FILES rtknavi_qt.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) install(FILES ../icon/rtknavi.png DESTINATION ${XDG_APPS_PIXMAPS_DIR}) diff --git a/app/qtapp/rtknavi_qt/logstrdlg.cpp b/app/qtapp/rtknavi_qt/logstrdlg.cpp index 387ea77ed..71a1b95ec 100644 --- a/app/qtapp/rtknavi_qt/logstrdlg.cpp +++ b/app/qtapp/rtknavi_qt/logstrdlg.cpp @@ -62,17 +62,20 @@ LogStrDialog::LogStrDialog(QWidget *parent) //--------------------------------------------------------------------------- void LogStrDialog::selectFile1() { - ui->lEFilePath1->setText(QDir::toNativeSeparators(QFileDialog::getSaveFileName(this, tr("Open..."), ui->lEFilePath1->text()))); + QString filename = QFileDialog::getSaveFileName(this, tr("Open..."), ui->lEFilePath1->text()); + if (!filename.isEmpty()) ui->lEFilePath1->setText(QDir::toNativeSeparators(filename)); } //--------------------------------------------------------------------------- void LogStrDialog::selectFile2() { - ui->lEFilePath2->setText(QDir::toNativeSeparators(QFileDialog::getSaveFileName(this, tr("Open..."), ui->lEFilePath2->text()))); + QString filename = QFileDialog::getSaveFileName(this, tr("Open..."), ui->lEFilePath2->text()); + if (!filename.isEmpty()) ui->lEFilePath2->setText(QDir::toNativeSeparators(filename)); } //--------------------------------------------------------------------------- void LogStrDialog::selectFile3() { - ui->lEFilePath3->setText(QDir::toNativeSeparators(QFileDialog::getSaveFileName(this, tr("Open..."), ui->lEFilePath3->text()))); + QString filename = QFileDialog::getSaveFileName(this, tr("Open..."), ui->lEFilePath3->text()); + if (!filename.isEmpty()) ui->lEFilePath3->setText(QDir::toNativeSeparators(filename)); } //--------------------------------------------------------------------------- void LogStrDialog::showKeyDialog() diff --git a/app/qtapp/rtknavi_qt/mondlg.cpp b/app/qtapp/rtknavi_qt/mondlg.cpp index 174c69477..8b13ae9fc 100644 --- a/app/qtapp/rtknavi_qt/mondlg.cpp +++ b/app/qtapp/rtknavi_qt/mondlg.cpp @@ -222,7 +222,7 @@ void MonitorDialog::clearTable() ui->cBSelectObservation->setVisible(displayType == 1); ui->cBSelectNavigationSystems->setVisible(displayType == 1 || displayType == 5); ui->cBSelectSingleNavigationSystem->setVisible(displayType == 2 || displayType == 14); - ui->cBSelectSatellites->setVisible(displayType == 2 || displayType == 5); + ui->cBSelectSatellites->setVisible(displayType == 2 || displayType == 5 || displayType == 6 || displayType == 7 || displayType == 14); ui->cBSelectInputStream->setVisible(displayType == 12 || displayType == 14 || displayType == 15 || displayType == 16); ui->cBSelectSolutionStream->setVisible(displayType == 17); ui->cBSelectFormat->setVisible(displayType == 16); @@ -393,7 +393,7 @@ void MonitorDialog::setRtk() int width[] = {500, 500}; ui->tWConsole->setColumnCount(2); - ui->tWConsole->setRowCount(52 + NFREQ*2); + ui->tWConsole->setRowCount(53 + NFREQ*2); ui->tWConsole->setHorizontalHeaderLabels(header); for (int i = 0; (i < ui->tWConsole->columnCount()) && (i < 2); i++) @@ -464,8 +464,14 @@ void MonitorDialog::showRtk() rtksvrunlock(rtksvr); // unlock for (j = k = 0; j < MAXSAT; j++) { - if (rtk->opt.mode == PMODE_SINGLE && !rtk->ssat[j].vs) continue; - if (rtk->opt.mode != PMODE_SINGLE && !rtk->ssat[j].vsat[0]) continue; + if (rtk->opt.mode == PMODE_SINGLE) { + if (!rtk->ssat[j].vs) continue; + } else { + int any = 0; + for (int fi = 0; fi < NFREQ; fi++) + if (rtk->ssat[j].vsat[fi]) { any = 1; break; } + if (!any) continue; + } azel[k * 2] = rtk->ssat[j].azel[0]; azel[k * 2 + 1] = rtk->ssat[j].azel[1]; k++; @@ -480,7 +486,7 @@ void MonitorDialog::showRtk() if (rtk->opt.navsys & SYS_IRN) navsys = navsys + tr("NavIC "); if (rtk->opt.navsys & SYS_SBS) navsys = navsys + tr("SBAS "); - if (ui->tWConsole->rowCount() < 55) { + if (ui->tWConsole->rowCount() < 53 + NFREQ * 2) { free(rtk); return; } @@ -526,8 +532,14 @@ void MonitorDialog::showRtk() .arg(rtk->opt.snrmask.mask[2][3], 0).arg(rtk->opt.snrmask.mask[2][4], 0).arg(rtk->opt.snrmask.mask[2][5], 0) .arg(rtk->opt.snrmask.mask[2][6], 0).arg(rtk->opt.snrmask.mask[2][7], 0).arg(rtk->opt.snrmask.mask[2][8], 0)); - ui->tWConsole->item(row, 0)->setText(tr("Rec Dynamic/Earth Tides Correction")); - ui->tWConsole->item(row++, 1)->setText(QStringLiteral("%1, %2").arg(rtk->opt.dynamics ? tr("ON") : tr("OFF"), rtk->opt.tidecorr ? tr("ON") : tr("OFF"))); + ui->tWConsole->item(row, 0)->setText(tr("Rec Dynamics")); + ui->tWConsole->item(row++, 1)->setText(QStringLiteral("%1").arg(rtk->opt.dynamics ? tr("ON") : tr("OFF"))); + + ui->tWConsole->item(row, 0)->setText(tr("Earth Tides Correction")); + const char *tideopts[]={"OFF","Solid Earth","Ocean Loading","Solid Earth + Ocean Loading", + "Solid Pole","Solid Earth + Solid Pole","Ocean Loading + Sold Pole", + "Solid Earth + Ocean Loading + Solid Pole"}; + ui->tWConsole->item(row++, 1)->setText(QStringLiteral("%1").arg(tideopts[rtk->opt.tidecorr & 7])); ui->tWConsole->item(row, 0)->setText(tr("Ionosphere/Troposphere Model")); ui->tWConsole->item(row++, 1)->setText(QStringLiteral("%1, %2").arg(ionoopt[rtk->opt.ionoopt < 0 || rtk->opt.ionoopt > 6 ? 0 : rtk->opt.ionoopt], @@ -792,8 +804,13 @@ void MonitorDialog::showSat() rtksvrunlock(rtksvr); for (i = 0; i < MAXSAT; i++) { - ssat = rtk->ssat + i; - vsat[i] = ssat->vs; + if (rtk->opt.mode == PMODE_SINGLE) { + vsat[i] = rtk->ssat[i].vs; + } else { + vsat[i] = 0; + for (int fi = 0; fi < NFREQ; fi++) + if (rtk->ssat[i].vsat[fi]) { vsat[i] = 1; break; } + } } for (i = 0, nsat = 0; i < MAXSAT; i++) { @@ -821,7 +838,7 @@ void MonitorDialog::showSat() if (ui->cBSelectSatellites->currentIndex() == 1 && !vsat[i]) continue; satno2id(i + 1, id); ui->tWConsole->item(n, j++)->setText(id); - ui->tWConsole->item(n, j++)->setText(ssat->vs ? tr("OK") : tr("-")); + ui->tWConsole->item(n, j++)->setText(vsat[i] ? tr("OK") : tr("-")); az = ssat->azel[0] * R2D; if (az < 0.0) az += 360.0; el = ssat->azel[1] * R2D; ui->tWConsole->item(n, j++)->setText(QString::number(az, 'f', 1)); @@ -1065,7 +1082,7 @@ void MonitorDialog::setObservations() //--------------------------------------------------------------------------- void MonitorDialog::showObservations() { - char tstr[40], id[8], *code; + char tstr[40], id[8]; int i, k, n = 0, nex = ui->cBSelectObservation->currentIndex() ? NEXOBS : 0; int sys = sys_tbl[ui->cBSelectNavigationSystems->currentIndex()]; int std = ui->cBSelectObservation->currentIndex(); @@ -1107,7 +1124,7 @@ void MonitorDialog::showObservations() ui->tWConsole->item(i, j++)->setText(id); ui->tWConsole->item(i, j++)->setText(QString("(%1)").arg(obs[i].rcv)); for (k = 0; k < NFREQ + nex; k++) { - code = code2obs(obs[i].code[k]); + const char *code = code2obs(obs[i].code[k]); if (*code) ui->tWConsole->item(i, j++)->setText(code); else ui->tWConsole->item(i, j++)->setText("-"); } @@ -1931,37 +1948,39 @@ void MonitorDialog::setRtcm() //--------------------------------------------------------------------------- void MonitorDialog::showRtcm() { - static rtcm_t rtcm; int i = 0, j, format; QString mstr1, mstr2; char tstr[40] = "-"; int effectiveStream = (inputStream < 0 || inputStream > 2) ? 0 : inputStream; + rtcm_t *rtcm = (rtcm_t *)malloc(sizeof(rtcm_t)); + if (rtcm == NULL) return; + rtksvrlock(rtksvr); format = rtksvr->format[effectiveStream]; - rtcm = rtksvr->rtcm[effectiveStream]; + *rtcm = rtksvr->rtcm[effectiveStream]; rtksvrunlock(rtksvr); - if (rtcm.time.time) time2str(rtcm.time, tstr, 3); + if (rtcm->time.time) time2str(rtcm->time, tstr, 3); for (j = 1; j < 100; j++) { - if (rtcm.nmsg2[j] == 0) continue; - mstr1 += QString("%1%2 (%3)").arg(mstr1.isEmpty() ? "" : ",").arg(j).arg(rtcm.nmsg2[j]); + if (rtcm->nmsg2[j] == 0) continue; + mstr1 += QString("%1%2 (%3)").arg(mstr1.isEmpty() ? "" : ",").arg(j).arg(rtcm->nmsg2[j]); } - if (rtcm.nmsg2[0] > 0) { - mstr1 += QString("%1other (%2)").arg(mstr1.isEmpty() ? "" : ",").arg(rtcm.nmsg2[0]); + if (rtcm->nmsg2[0] > 0) { + mstr1 += QString("%1other (%2)").arg(mstr1.isEmpty() ? "" : ",").arg(rtcm->nmsg2[0]); } for (j = 1; j < 300; j++) { - if (rtcm.nmsg3[j] == 0) continue; - mstr2 += QString("%1%2(%3)").arg(mstr2.isEmpty() ? "" : ",").arg(j + 1000).arg(rtcm.nmsg3[j]); + if (rtcm->nmsg3[j] == 0) continue; + mstr2 += QString("%1%2(%3)").arg(mstr2.isEmpty() ? "" : ",").arg(j + 1000).arg(rtcm->nmsg3[j]); } for (j = 300; j < 399; j++) { - if (rtcm.nmsg3[j] == 0) continue; - mstr2+=QString("%1%2(%3)").arg(mstr2.isEmpty()?"":",").arg(j+3770).arg(rtcm.nmsg3[j]); + if (rtcm->nmsg3[j] == 0) continue; + mstr2+=QString("%1%2(%3)").arg(mstr2.isEmpty()?"":",").arg(j+3770).arg(rtcm->nmsg3[j]); } - if (rtcm.nmsg3[0] > 0) - mstr2 += QString("%1other(%2)").arg(mstr2.isEmpty() ? "" : ",").arg(rtcm.nmsg3[0]); + if (rtcm->nmsg3[0] > 0) + mstr2 += QString("%1other(%2)").arg(mstr2.isEmpty() ? "" : ",").arg(rtcm->nmsg3[0]); ui->tWConsole->item(i, 0)->setText(tr("Format")); ui->tWConsole->item(i++, 1)->setText(format == STRFMT_RTCM2 ? tr("RTCM 2") : tr("RTCM 3")); @@ -1970,43 +1989,45 @@ void MonitorDialog::showRtcm() ui->tWConsole->item(i++, 1)->setText(tstr); ui->tWConsole->item(i, 0)->setText(tr("Station ID")); - ui->tWConsole->item(i++, 1)->setText(QString::number(rtcm.staid)); + ui->tWConsole->item(i++, 1)->setText(QString::number(rtcm->staid)); ui->tWConsole->item(i, 0)->setText(tr("Station Health")); - ui->tWConsole->item(i++, 1)->setText(QString::number(rtcm.stah)); + ui->tWConsole->item(i++, 1)->setText(QString::number(rtcm->stah)); ui->tWConsole->item(i, 0)->setText(tr("Sequence No")); - ui->tWConsole->item(i++, 1)->setText(QString::number(rtcm.seqno)); + ui->tWConsole->item(i++, 1)->setText(QString::number(rtcm->seqno)); ui->tWConsole->item(i, 0)->setText(tr("RTCM Special Message")); - ui->tWConsole->item(i++, 1)->setText(rtcm.msg); + ui->tWConsole->item(i++, 1)->setText(rtcm->msg); ui->tWConsole->item(i, 0)->setText(tr("Last Message")); - ui->tWConsole->item(i++, 1)->setText(rtcm.msgtype); + ui->tWConsole->item(i++, 1)->setText(rtcm->msgtype); ui->tWConsole->item(i, 0)->setText(tr("# of RTCM Messages")); ui->tWConsole->item(i++, 1)->setText(format == STRFMT_RTCM2 ? mstr1 : mstr2); ui->tWConsole->item(i, 0)->setText(tr("MSM Signals for GPS")); - ui->tWConsole->item(i++, 1)->setText(rtcm.msmtype[0]); + ui->tWConsole->item(i++, 1)->setText(rtcm->msmtype[0]); ui->tWConsole->item(i, 0)->setText(tr("MSM Signals for GLONASS")); - ui->tWConsole->item(i++, 1)->setText(rtcm.msmtype[1]); + ui->tWConsole->item(i++, 1)->setText(rtcm->msmtype[1]); ui->tWConsole->item(i, 0)->setText(tr("MSM Signals for Galileo")); - ui->tWConsole->item(i++, 1)->setText(rtcm.msmtype[2]); + ui->tWConsole->item(i++, 1)->setText(rtcm->msmtype[2]); ui->tWConsole->item(i, 0)->setText(tr("MSM Signals for QZSS")); - ui->tWConsole->item(i++, 1)->setText(rtcm.msmtype[3]); + ui->tWConsole->item(i++, 1)->setText(rtcm->msmtype[3]); ui->tWConsole->item(i, 0)->setText(tr("MSM Signals for SBAS")); - ui->tWConsole->item(i++, 1)->setText(rtcm.msmtype[4]); + ui->tWConsole->item(i++, 1)->setText(rtcm->msmtype[4]); ui->tWConsole->item(i, 0)->setText(tr("MSM Signals for BDS")); - ui->tWConsole->item(i++, 1)->setText(rtcm.msmtype[5]); + ui->tWConsole->item(i++, 1)->setText(rtcm->msmtype[5]); ui->tWConsole->item(i, 0)->setText(tr("MSM Signals for NavIC")); - ui->tWConsole->item(i++, 1)->setText(rtcm.msmtype[6]); + ui->tWConsole->item(i++, 1)->setText(rtcm->msmtype[6]); + + free(rtcm); } //--------------------------------------------------------------------------- void MonitorDialog::setRtcmDgps() @@ -2063,7 +2084,7 @@ void MonitorDialog::setRtcmSsr() header << tr("SAT") << tr("Status") << tr("UDI (s)") << tr("UDHR (s)") << tr("IOD") << tr("URA") << tr("Datum") << tr("T0") << tr("D0-A (m)") << tr("D0-C (m)") << tr("D0-R (m)") << tr("D1-A (mm/s)") << tr("D1-C (mm/s)") << tr("D1-R (mm/s)") << tr("C0 (m)") << tr("C1 (mm/s)") << tr("C2 (mm/s²)") << tr("C-HR (m)") << tr("Code Bias (m)") << tr("Phase Bias (m)"); - int i, width[] = { 46, 60, 70, 90, 30, 25, 70, 115, 90, 90, 90, 120, 120, 120, 90, 120, 120, 120, 200, 200 }; + int i, width[] = { 46, 60, 70, 90, 30, 25, 70, 115, 90, 90, 90, 120, 120, 120, 90, 120, 120, 120, 400, 400 }; ui->tWConsole->setColumnCount(20); ui->tWConsole->setRowCount(0); @@ -2089,7 +2110,12 @@ void MonitorDialog::showRtcmSsr() time = rtksvr->rtk.sol.time; for (i = n = 0; i < MAXSAT; i++) { if (!(satsys(i + 1, NULL) & sys)) continue; - ssr[n] = rtksvr->rtcm[effectiveStream].ssr[i]; + if (inputStream == 3) + ssr[n] = rtksvr->nav.ssr[i]; + else + ssr[n] = rtksvr->rtcm[effectiveStream].ssr[i]; + bool valid = ssr[n].t0[0].time && fabs(timediff(time, ssr[n].t0[0])) <= 1800.0 && ssr[n].iode >= 0; + if (ui->cBSelectSatellites->currentIndex() && !valid) continue; sat[n++] = i + 1; } rtksvrunlock(rtksvr); @@ -2109,7 +2135,9 @@ void MonitorDialog::showRtcmSsr() ui->tWConsole->item(i, j++)->setText(valid ? tr("OK") : tr("-")); ui->tWConsole->item(i, j++)->setText(QString::number(ssr[i].udi[0], 'f', 0)); ui->tWConsole->item(i, j++)->setText(QString::number(ssr[i].udi[2], 'f', 0)); - ui->tWConsole->item(i, j++)->setText(QString::number(ssr[i].iode)); + if (ssr[i].iode < 0) s = "-"; + else s = QString::number(ssr[i].iode); + ui->tWConsole->item(i, j++)->setText(s); ui->tWConsole->item(i, j++)->setText(QString::number(ssr[i].ura)); ui->tWConsole->item(i, j++)->setText(QString::number(ssr[i].refd)); if (ssr[i].t0[0].time) time2str(ssr[i].t0[0], tstr, 0); else strcpy(tstr, "-"); diff --git a/app/qtapp/rtknavi_qt/navimain.cpp b/app/qtapp/rtknavi_qt/navimain.cpp index 38237ca8c..1f3f4db6b 100644 --- a/app/qtapp/rtknavi_qt/navimain.cpp +++ b/app/qtapp/rtknavi_qt/navimain.cpp @@ -75,7 +75,7 @@ MainWindow *mainForm; #define KACYCLE 5000 // keep alive cycle (ms) #define TIMEOUT 10000 // inactive timeout time (ms) #define MAX_PORT_OFFSET 9 // max port number offset -#define MAXTRKSCALE 23 // track scale +#define MAXTRKSCALE 26 // track scale #define MAXPANELMODE 7 // max panel mode #define SQRT(x) ((x)<0.0||(x)!=(x)?0.0:sqrt(x)) @@ -126,7 +126,7 @@ MainWindow::MainWindow(QWidget *parent) timeSystem = solutionType = 0; for (int i = 0; i < 4; i++) { plotType[i] = frequencyType[i] = baselineMode[i] = trackType[i] = 0; - trackScale[i] = 5; + trackScale[i] = 8; }; solutionsCurrent = solutionsStart = solutionsEnd = numSatellites[0] = numSatellites[1] = 0; nMapPoint = 0; @@ -138,10 +138,12 @@ MainWindow::MainWindow(QWidget *parent) for (int i = 0; i < 2; i++) for (int j = 0; j < MAXSAT; j++) { - satellites[i][j] = validSatellites[i][j] = 0; + satellites[i][j] = 0; satellitesAzimuth[i][j] = satellitesElevation[i][j] = 0.0; - for (int k = 0; k < NFREQ; k++) + for (int k = 0; k < NFREQ; k++) { + validSatellites[i][j][k] = 0; satellitesSNR[i][j][k] = 0; + } } static opt_t rcvopts[] = { @@ -1662,8 +1664,8 @@ void MainWindow::drawSolutionPlot(QLabel *plot, int type, int freq) int w = buffer.size().width() - 2; int h = buffer.height() - 2; - int i, j, x, sat[2][MAXSAT], ns[2], snr[2][MAXSAT][NFREQ], vsat[2][MAXSAT]; - int *snr0[MAXSAT], *snr1[MAXSAT], topMargin = QFontMetrics(optDialog->panelFont).height()*3/2; + int i, j, x, sat[2][MAXSAT], ns[2], snr[2][MAXSAT][NFREQ], vsat[2][MAXSAT][NFREQ]; + int topMargin = QFontMetrics(optDialog->panelFont).height()*3/2; double az[2][MAXSAT], el[2][MAXSAT], rr[3], pos[3]; trace(4, "drawSolutionPlot\n"); @@ -1672,12 +1674,8 @@ void MainWindow::drawSolutionPlot(QLabel *plot, int type, int freq) fstr[i + 1] = QStringLiteral("L%1").arg(i + 1); fstr[i + 1] = " SYS"; - for (i = 0; i < MAXSAT; i++) { - snr0[i] = snr[0][i]; - snr1[i] = snr[1][i]; - } - ns[0] = rtksvrostat(rtksvr, 0, &time, sat[0], az[0], el[0], snr0, vsat[0]); - ns[1] = rtksvrostat(rtksvr, 1, &time, sat[1], az[1], el[1], snr1, vsat[1]); + ns[0] = rtksvrostat(rtksvr, 0, &time, sat[0], az[0], el[0], snr[0], vsat[0]); + ns[1] = rtksvrostat(rtksvr, 1, &time, sat[1], az[1], el[1], snr[1], vsat[1]); rtksvrlock(rtksvr); matcpy(rr, rtksvr->rtk.sol.rr, 3, 1); @@ -1691,15 +1689,17 @@ void MainWindow::drawSolutionPlot(QLabel *plot, int type, int freq) satellites[i][j] = sat[i][j]; satellitesAzimuth[i][j] = az[i][j]; satellitesElevation[i][j] = el[i][j]; - for (int k = 0; k < NFREQ; k++) + for (int k = 0; k < NFREQ; k++) { + validSatellites[i][j][k] = vsat[i][j][k]; satellitesSNR[i][j][k] = snr[i][j][k]; - validSatellites[i][j] = vsat[i][j]; + } } } else { for (j = 0; j < numSatellites[i]; j++) { - validSatellites[i][j] = 0; - for (int k = 0; k < NFREQ; k++) + for (int k = 0; k < NFREQ; k++) { + validSatellites[i][j][k] = 0; satellitesSNR[i][j][k] = 0; + } } } } @@ -1720,12 +1720,12 @@ void MainWindow::drawSolutionPlot(QLabel *plot, int type, int freq) drawText(c, w / 2 + x, 1, s2, Qt::darkGray, 1, 2); } } else if (type == 1) { // snr plot rover - drawSnr(c, w, h - topMargin, 0, topMargin, 0, type); + drawSnr(c, w, h - topMargin, 0, topMargin, 0, freq); s1 = tr("Rover %L1 SNR (dBHz)").arg(fstr[freq]); drawText(c, x, 1, s1, Qt::darkGray, 1, 2); } else if (type == 2) { // skyplot rover - drawSatellites(c, w, h, 0, 0, 0, type); - s1 = tr("Rover %L1").arg(fstr[type]); + drawSatellites(c, w, h, 0, 0, 0, freq); + s1 = tr("Rover %L1").arg(fstr[freq]); drawText(c, x, 1, s1, Qt::darkGray, 1, 2); } else if (type == 3) { // skyplot+snr plot rover s1 = tr("Rover %L1").arg(fstr[freq]); @@ -1861,7 +1861,10 @@ void MainWindow::drawSnr(QPainter &c, int w, int h, int x0, int y0, QRect r1(x1, y1, barWidth, -height); if (j == 0) { // filled bar c.setBrush(QBrush(freq < NFREQ + 1 ? snrColor(snr[snrIdx]) : color_sys[sysIdx], Qt::SolidPattern)); - if (!validSatellites[index][i]) + int any = 0; + for (int fi = 0; fi < NFREQ; fi++) + if (validSatellites[index][i][fi]) { any = 1; break; } + if (!any) c.setBrush(QBrush(QColor(QColorConstants::LightGray), Qt::SolidPattern)); } else { // outline only c.setPen(j < NFREQ + 1 ? QColor(QColorConstants::LightGray) : Qt::darkGray); @@ -1909,7 +1912,10 @@ void MainWindow::drawSatellites(QPainter &c, int w, int h, int x0, int y0, snr[0] = snr[j + 1]; // max snr } } - if (validSatellites[index][k] && (freq > NFREQ || snr[freq] > 0)) { + int anyValidSatFreq = 0; + for (int fi = 0; fi < NFREQ; fi++) + if (validSatellites[index][k][fi]) { anyValidSatFreq = 1; break; } + if (anyValidSatFreq && (freq > NFREQ || snr[freq] > 0)) { azel[nsats * 2] = satellitesAzimuth[index][k]; azel[nsats * 2 + 1] = satellitesElevation[index][k]; nsats++; @@ -1920,8 +1926,8 @@ void MainWindow::drawSatellites(QPainter &c, int w, int h, int x0, int y0, y[i] = static_cast(p.y() - r * (90 - satellitesElevation[index][k] * R2D) / 90 * cos(satellitesAzimuth[index][k])) + y0; radius = QFontMetrics(optDialog->panelFont).height(); - c.setBrush(!validSatellites[index][k] ? Color::Silver : - (freq < NFREQ ? snrColor(snr[freq]) : color_sys[sysIdx])); + c.setBrush(!anyValidSatFreq ? Color::Silver : + (freq < NFREQ + 1 ? snrColor(snr[freq]) : color_sys[sysIdx])); c.setPen(Qt::darkGray); color_text = Qt::white; if (freq < NFREQ + 1 && snr[freq] <= 0) { @@ -2041,17 +2047,18 @@ void MainWindow::drawTrack(QPainter &c, int id, QPaintDevice *plot) QPoint p1, p2; QString label; static const double scale[] = { - 0.00021, 0.00047, 0.001, 0.0021, 0.0047, 0.01, 0.021, 0.047, 0.1, 0.21, 0.47, - 1.0, 2.1, 4.7, 10.0, 21.0, 47.0, 100.0, 210.0, 470.0, 1000.0, 2100.0,4700.0, + 0.000021, 0.000047, 0.0001, 0.00021, 0.00047, 0.001, 0.0021, 0.0047, + 0.01, 0.021, 0.047, 0.1, 0.21, 0.47, + 1.0, 2.1, 4.7, 10.0, 21.0, 47.0, 100.0, 210.0, 470.0, 1000.0, 2100.0, 4700.0, 10000.0 }; double *x, *y, xt, yt, sx, sy, ref[3], pos[3], dr[3], enu[3]; - int i, j, currentPointNo, numPoints = 0, type, scl; + int i, j, currentPointNo, numPoints = 0; trace(3, "drawTrack\n"); - type = id == 0 ? trackType[0] : trackType[1]; - scl = id == 0 ? trackScale[0] : trackScale[1]; + int type = trackType[id]; + int scl = trackScale[id]; x = new double[optDialog->solutionBufferSize]; y = new double[optDialog->solutionBufferSize]; @@ -2350,7 +2357,7 @@ void MainWindow::loadNavigation(nav_t *nav) QString str; eph_t eph0; char buff[2049], *p; - long toe_time,toc_time,ttr_time; + long unsigned toe_time,toc_time,ttr_time; int i; trace(3, "loadNavigation\n"); @@ -2358,13 +2365,13 @@ void MainWindow::loadNavigation(nav_t *nav) memset(&eph0, 0, sizeof(eph_t)); for (i = 0; i < 2 * MAXSAT; i++) { - if ((str = settings.value(QString("navi/eph_%1").arg(i, 2)).toString()).isEmpty()) continue; + if ((str = settings.value(QString("navi/eph_%1").arg(i, 3, 10, QChar('0'))).toString()).isEmpty()) continue; nav->eph[i] = eph0; strncpy(buff, qPrintable(str), 2047); if (!(p = strchr(buff, ','))) continue; *p = '\0'; if (!(nav->eph[i].sat = satid2no(buff))) continue; - sscanf(p + 1, "%d,%d,%d,%d,%ld,%ld,%ld,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%d,%d,%lf", + sscanf(p + 1, "%d,%d,%d,%d,%lu,%lu,%lu,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%d,%d,%lf", &nav->eph[i].iode, &nav->eph[i].iodc, &nav->eph[i].sva, @@ -2433,9 +2440,9 @@ void MainWindow::saveNavigation(nav_t *nav) str = str + QString("%1,").arg(nav->eph[i].iodc); str = str + QString("%1,").arg(nav->eph[i].sva); str = str + QString("%1,").arg(nav->eph[i].svh); - str = str + QString("%1,").arg(static_cast(nav->eph[i].toe.time)); - str = str + QString("%1,").arg(static_cast(nav->eph[i].toc.time)); - str = str + QString("%1,").arg(static_cast(nav->eph[i].ttr.time)); + str = str + QString("%1,").arg(static_cast(nav->eph[i].toe.time)); + str = str + QString("%1,").arg(static_cast(nav->eph[i].toc.time)); + str = str + QString("%1,").arg(static_cast(nav->eph[i].ttr.time)); str = str + QString("%1,").arg(nav->eph[i].A, 0, 'E', 14); str = str + QString("%1,").arg(nav->eph[i].e, 0, 'E', 14); str = str + QString("%1,").arg(nav->eph[i].i0, 0, 'E', 14); @@ -2460,7 +2467,7 @@ void MainWindow::saveNavigation(nav_t *nav) str = str + QString("%1,").arg(nav->eph[i].code); str = str + QString("%1,").arg(nav->eph[i].flag); str = str + QString("%1,").arg(nav->eph[i].tgd[1],0,'E',14); - settings.setValue(QString("navi/eph_%1").arg(i, 2), str); + settings.setValue(QString("navi/eph_%1").arg(i, 3, 10, QChar('0')), str); } str = ""; for (i = 0; i < 8; i++) str = str + QString("%1,").arg(nav->ion_gps[i], 0, 'E', 14); @@ -2535,14 +2542,15 @@ void MainWindow::loadOptions() trackType[1] = settings.value("setting/trktype2", 0).toInt(); trackType[2] = settings.value("setting/trktype3", 0).toInt(); trackType[3] = settings.value("setting/trktype4", 0).toInt(); - trackScale[0] = settings.value("setting/trkscale1", 5).toInt(); - trackScale[1] = settings.value("setting/trkscale2", 5).toInt(); - trackScale[2] = settings.value("setting/trkscale3", 5).toInt(); - trackScale[3] = settings.value("setting/trkscale4", 5).toInt(); + trackScale[0] = settings.value("setting/trkscale1", 8).toInt(); + trackScale[1] = settings.value("setting/trkscale2", 8).toInt(); + trackScale[2] = settings.value("setting/trkscale3", 8).toInt(); + trackScale[3] = settings.value("setting/trkscale4", 8).toInt(); frequencyType[0] = settings.value("setting/freqtype1", 0).toInt(); frequencyType[1] = settings.value("setting/freqtype2", 0).toInt(); frequencyType[2] = settings.value("setting/freqtype3", 0).toInt(); frequencyType[3] = settings.value("setting/freqtype4", 0).toInt(); + for (int i = 0; i < 4; i++) if (frequencyType[i] > NFREQ + 1) frequencyType[i] = 0; baselineMode[0] = settings.value("setting/blmode1", 0).toInt(); baselineMode[1] = settings.value("setting/blmode2", 0).toInt(); baselineMode[2] = settings.value("setting/blmode3", 0).toInt(); diff --git a/app/qtapp/rtknavi_qt/navimain.h b/app/qtapp/rtknavi_qt/navimain.h index ad9d499c5..3876e2a1c 100644 --- a/app/qtapp/rtknavi_qt/navimain.h +++ b/app/qtapp/rtknavi_qt/navimain.h @@ -160,7 +160,7 @@ public slots: int monitorPortOpen; int solutionsCurrent, solutionsStart, solutionsEnd, numSatellites[2], solutionCurrentStatus; - int satellites[2][MAXSAT], satellitesSNR[2][MAXSAT][NFREQ], validSatellites[2][MAXSAT]; + int satellites[2][MAXSAT], satellitesSNR[2][MAXSAT][NFREQ], validSatellites[2][MAXSAT][NFREQ]; double satellitesAzimuth[2][MAXSAT], satellitesElevation[2][MAXSAT]; gtime_t *timeStamps; int *solutionStatus, *numValidSatellites; diff --git a/app/qtapp/rtkplot_qt/CMakeLists.txt b/app/qtapp/rtkplot_qt/CMakeLists.txt index ac52c1396..436a0c9e2 100644 --- a/app/qtapp/rtkplot_qt/CMakeLists.txt +++ b/app/qtapp/rtkplot_qt/CMakeLists.txt @@ -90,7 +90,7 @@ set_target_properties(rtkplot_qt PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON ) -install(TARGETS rtkget_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) +install(TARGETS rtkplot_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) if (UNIX) install(FILES rtkplot_qt.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) install(FILES ../icon/rtkplot.png DESTINATION ${XDG_APPS_PIXMAPS_DIR}) diff --git a/app/qtapp/rtkplot_qt/plotdata.cpp b/app/qtapp/rtkplot_qt/plotdata.cpp index cf8065940..1d4d4d0df 100644 --- a/app/qtapp/rtkplot_qt/plotdata.cpp +++ b/app/qtapp/rtkplot_qt/plotdata.cpp @@ -182,7 +182,7 @@ void Plot::readObservation(const QStringList &files) clearObservation(); observation = obs; - navigation = *nav; + *navigation = *nav; free(nav); station = sta; simulatedObservation = 0; @@ -321,7 +321,7 @@ void Plot::readNavigation(const QStringList &files) timeSpan(&ts, &te, &tint); - freenav(&navigation, 0xFF); + freenav(navigation, 0xFF); showMessage(tr("Reading navigation data...")); @@ -329,11 +329,11 @@ void Plot::readNavigation(const QStringList &files) for (i = 0; i < files.size(); i++) { readrnxt(qPrintable(QDir::toNativeSeparators(files.at(i))), 1, ts, te, tint, - qPrintable(plotOptDialog->getRinexOptions()), NULL, &navigation, NULL); + qPrintable(plotOptDialog->getRinexOptions()), NULL, navigation, NULL); } - uniqnav(&navigation); + uniqnav(navigation); - if (navigation.n <= 0 && navigation.ng <= 0 && navigation.ns <= 0) { + if (navigation->n <= 0 && navigation->ng <= 0 && navigation->ns <= 0) { showMessage(tr("No navigation message: %1...").arg(QDir::toNativeSeparators(files.at(i)))); readWaitEnd(); return; @@ -1093,10 +1093,11 @@ void Plot::connectStream() } if (rtStream[i] == STR_SERIAL) mode |= STR_MODE_W; - if ((p = path.indexOf("::"))) path = path.left(p); - if ((p = path.indexOf("/:"))) path = path.left(p); - if ((p = path.indexOf("@"))) name[i] = path.mid(p+1); - else name[i] = path; + QString buff = path; + if ((p = buff.indexOf("::"))) buff = buff.left(p); + if ((p = buff.indexOf("/:"))) buff = buff.left(p); + if ((p = buff.indexOf("@"))) name[i] = buff.mid(p+1); + else name[i] = buff; if (!stropen(stream + i, rtStream[i], mode, qPrintable(path))) { showMessage(tr("Connect error: %1").arg(name[0])); @@ -1225,7 +1226,7 @@ void Plot::updateObservation(int nobs) if (plotOptDialog->getReceiverPosition() == 0) { // single point position opt.err[0] = 900.0; - pntpos(observation.data + i, j - i, &navigation, &opt, &sol, azel, NULL, msg); + pntpos(observation.data + i, j - i, navigation, &opt, &sol, azel, NULL, msg); matcpy(rr, sol.rr, 3, 1); ecef2pos(rr, pos); } else if (plotOptDialog->getReceiverPosition() == 1) { // lat/lon/height @@ -1245,7 +1246,7 @@ void Plot::updateObservation(int nobs) continue; } } else { - if (!satpos(time, time, sat, EPHOPT_BRDC, &navigation, rs, dts, &var, &svh)) { + if (!satpos(time, time, sat, EPHOPT_BRDC, navigation, rs, dts, &var, &svh)) { continue; } } @@ -1294,10 +1295,10 @@ void Plot::updateMp() // Choose two frequencies to calculate reference I. double freq1 = 0.0, freq2 = 0.0, I = 0.0; for (int j = 0; j < NFREQ + NEXOBS; j++) { - freq1 = sat2freq(data->sat, data->code[j], &navigation); + freq1 = sat2freq(data->sat, data->code[j], navigation); if (data->L[j] == 0.0 || freq1 == 0.0 ) continue; for (int k = j + 1; k < NFREQ + NEXOBS; k++) { - freq2 = sat2freq(data->sat, data->code[k], &navigation); + freq2 = sat2freq(data->sat, data->code[k], navigation); if (data->L[k] == 0.0 || freq2 == 0.0 || freq1 == freq2) continue; I = -CLIGHT * (data->L[j] / freq1-data->L[k] / freq2) / (1.0 - SQR(freq1 / freq2)); break; @@ -1307,7 +1308,7 @@ void Plot::updateMp() if (freq1 == 0.0 || freq2 == 0.0) continue; for (int j = 0; j < NFREQ + NEXOBS; j++) { - double freq = sat2freq(data->sat, data->code[j], &navigation); + double freq = sat2freq(data->sat, data->code[j], navigation); if (data->P[j] == 0.0 || data->L[j] == 0.0 || freq == 0.0) continue; multipath[j][i] = data->P[j] - CLIGHT * data->L[j] / freq - 2.0 * SQR(freq1 / freq) * I; } @@ -1370,8 +1371,8 @@ void Plot::updateIono() for (i = 0; i < observation.n; i++) { data = observation.data + i; - freq1 = sat2freq(data->sat, data->code[0], &navigation); - freq2 = sat2freq(data->sat, data->code[1], &navigation); + freq1 = sat2freq(data->sat, data->code[0], navigation); + freq2 = sat2freq(data->sat, data->code[1], navigation); if (data->P[0] == 0.0 || data->P[1] == 0.0 || freq1 == 0.0 || freq2 == 0.0 || freq1 == freq2) continue; I = 1/ 40.308 * SQR(freq1)*SQR(freq2)/(SQR(freq1)-SQR(freq2))*1e-16; @@ -1423,7 +1424,7 @@ void Plot::clearObservation() sta_t sta0 = {}; freeobs(&observation); - freenav(&navigation, 0xFF); + freenav(navigation, 0xFF); delete [] indexObservation; indexObservation = NULL; delete [] azimuth; azimuth = NULL; diff --git a/app/qtapp/rtkplot_qt/plotdraw.cpp b/app/qtapp/rtkplot_qt/plotdraw.cpp index 520548994..9f849d929 100644 --- a/app/qtapp/rtkplot_qt/plotdraw.cpp +++ b/app/qtapp/rtkplot_qt/plotdraw.cpp @@ -1138,13 +1138,13 @@ void Plot::generateObservationSlips(int *LLI) if (plotOptDialog->getShowSlip() == 1) { // LG jump if (obstype.isNull()) { // "ALL" selected - if ((freq1 = sat2freq(obs->sat, obs->code[0], &navigation)) == 0.0) continue; + if ((freq1 = sat2freq(obs->sat, obs->code[0], navigation)) == 0.0) continue; LLI[i] = obs->LLI[0] & 2; for (j = 1; j < NFREQ + NEXOBS; j++) { LLI[i] |= obs->LLI[j] & 2; - if ((freq2 = sat2freq(obs->sat, obs->code[j], &navigation)) == 0.0) continue; + if ((freq2 = sat2freq(obs->sat, obs->code[j], navigation)) == 0.0) continue; gf = CLIGHT * (obs->L[0] / freq1-obs->L[j] / freq2); // geometry-free if (fabs(prev_gf[obs->sat-1][j] - gf) > THRESLIP) LLI[i] |= 1; @@ -1165,8 +1165,8 @@ void Plot::generateObservationSlips(int *LLI) LLI[i] = obs->LLI[j] & 2; k = (j == 0) ? 1 : 0; // selected reference for geometry-free solution - if ((freq1 = sat2freq(obs->sat, obs->code[k], &navigation)) == 0.0) continue; - if ((freq2 = sat2freq(obs->sat, obs->code[j], &navigation)) == 0.0) continue; + if ((freq1 = sat2freq(obs->sat, obs->code[k], navigation)) == 0.0) continue; + if ((freq2 = sat2freq(obs->sat, obs->code[j], navigation)) == 0.0) continue; gf = CLIGHT * (obs->L[k] / freq1-obs->L[j] / freq2); if (fabs(prev_gf[obs->sat-1][j] - gf) > THRESLIP) LLI[i] |= 1; @@ -1238,20 +1238,20 @@ void Plot::drawObservationEphemeris(QPainter &c, double *yp) if (!satelliteSelection[sat]) continue; // GPS/Galileo/... ephemeris - for (i = 0; i < navigation.n; i++) { - if (navigation.eph[i].sat != sat + 1) continue; + for (i = 0; i < navigation->n; i++) { + if (navigation->eph[i].sat != sat + 1) continue; - graphSingle->toPoint(timePosition(navigation.eph[i].ttr), yp[sat], ps[0]); // start position + graphSingle->toPoint(timePosition(navigation->eph[i].ttr), yp[sat], ps[0]); // start position ps[1] = ps[0]; - in = graphSingle->toPoint(timePosition(navigation.eph[i].toe), yp[sat], ps[2]); // end position + in = graphSingle->toPoint(timePosition(navigation->eph[i].toe), yp[sat], ps[2]); // end position - offset[navigation.eph[i].sat - 1] = offset[navigation.eph[i].sat - 1] ? 0 : 3; + offset[navigation->eph[i].sat - 1] = offset[navigation->eph[i].sat - 1] ? 0 : 3; for (k = 0; k < 3; k++) - ps[k].ry() += plotOptDialog->getMarkSize() + 2 + offset[navigation.eph[i].sat - 1]; + ps[k].ry() += plotOptDialog->getMarkSize() + 2 + offset[navigation->eph[i].sat - 1]; ps[0].ry() -= 2; - svh = navigation.eph[i].svh; + svh = navigation->eph[i].svh; // Mask QZS LEX health. int health = satsys(sat + 1, NULL) == SYS_QZS ? (svh & 0xfe) != 0 : svh != 0; graphSingle->drawPoly(c, ps, 3, health ? plotOptDialog->getMarkerColor(0, 5) : plotOptDialog->getCColor(1), 0); @@ -1259,40 +1259,40 @@ void Plot::drawObservationEphemeris(QPainter &c, double *yp) if (in) graphSingle->drawMark(c, ps[2], Graph::MarkerTypes::Dot, health ? plotOptDialog->getMarkerColor(0, 5) : plotOptDialog->getCColor(1), health ? 4 : 3, 0); } // Glonass ephemeris - for (i = 0; i < navigation.ng; i++) { - if (navigation.geph[i].sat != sat + 1) continue; + for (i = 0; i < navigation->ng; i++) { + if (navigation->geph[i].sat != sat + 1) continue; - graphSingle->toPoint(timePosition(navigation.geph[i].tof), yp[sat], ps[0]); + graphSingle->toPoint(timePosition(navigation->geph[i].tof), yp[sat], ps[0]); ps[1] = ps[0]; - in = graphSingle->toPoint(timePosition(navigation.geph[i].toe), yp[sat], ps[2]); + in = graphSingle->toPoint(timePosition(navigation->geph[i].toe), yp[sat], ps[2]); - offset[navigation.geph[i].sat - 1] = offset[navigation.geph[i].sat - 1] ? 0 : 3; + offset[navigation->geph[i].sat - 1] = offset[navigation->geph[i].sat - 1] ? 0 : 3; for (k = 0; k < 3; k++) - ps[k].ry() += plotOptDialog->getMarkSize() + 2 + offset[navigation.geph[i].sat - 1]; + ps[k].ry() += plotOptDialog->getMarkSize() + 2 + offset[navigation->geph[i].sat - 1]; ps[0].ry() -= 2; - svh = navigation.geph[i].svh; + svh = navigation->geph[i].svh; int health = (svh & 9) != 0 || (svh & 6) == 4; graphSingle->drawPoly(c, ps, 3, health ? plotOptDialog->getMarkerColor(0, 5) : plotOptDialog->getCColor(1), 0); if (in) graphSingle->drawMark(c, ps[2], Graph::MarkerTypes::Dot, health ? plotOptDialog->getMarkerColor(0, 5) : plotOptDialog->getCColor(1), health ? 4 : 3, 0); } // SBAS ephemeris - for (i = 0; i < navigation.ns; i++) { - if (navigation.seph[i].sat != sat + 1) continue; + for (i = 0; i < navigation->ns; i++) { + if (navigation->seph[i].sat != sat + 1) continue; - graphSingle->toPoint(timePosition(navigation.seph[i].tof), yp[sat], ps[0]); + graphSingle->toPoint(timePosition(navigation->seph[i].tof), yp[sat], ps[0]); ps[1] = ps[0]; - in = graphSingle->toPoint(timePosition(navigation.seph[i].t0), yp[sat], ps[2]); + in = graphSingle->toPoint(timePosition(navigation->seph[i].t0), yp[sat], ps[2]); - offset[navigation.seph[i].sat - 1] = offset[navigation.seph[i].sat - 1] ? 0 : 3; + offset[navigation->seph[i].sat - 1] = offset[navigation->seph[i].sat - 1] ? 0 : 3; for (k = 0; k < 3; k++) - ps[k].ry() += plotOptDialog->getMarkSize() + 2 + offset[navigation.seph[i].sat - 1]; + ps[k].ry() += plotOptDialog->getMarkSize() + 2 + offset[navigation->seph[i].sat - 1]; ps[0].ry() -= 2; - svh = navigation.seph[i].svh; + svh = navigation->seph[i].svh; graphSingle->drawPoly(c, ps, 3, svh ? plotOptDialog->getMarkerColor(0, 5) : plotOptDialog->getCColor(1), 0); if (in) graphSingle->drawMark(c, ps[2], Graph::MarkerTypes::Dot, svh ? plotOptDialog->getMarkerColor(0, 5) : plotOptDialog->getCColor(1), svh ? 4 : 3, 0); @@ -1450,7 +1450,7 @@ void Plot::drawSky(QPainter &c, int level) } } - if (navigation.n <= 0 && navigation.ng <= 0 && !simulatedObservation) { // indicate if no navigation data is available + if (navigation->n <= 0 && navigation->ng <= 0 && !simulatedObservation) { // indicate if no navigation data is available graphSky->getExtent(p1, p2); p2.rx() -= 10; p2.ry() -= 3; @@ -1691,7 +1691,7 @@ void Plot::drawSky(QPainter &c, int level) } } - if (navigation.n <= 0 && navigation.ng <= 0 && !simulatedObservation) { // indicate if no navigation data is available + if (navigation->n <= 0 && navigation->ng <= 0 && !simulatedObservation) { // indicate if no navigation data is available graphSky->getExtent(p1, p2); p2.rx() -= 10; p2.ry() -= 3; @@ -2004,7 +2004,7 @@ void Plot::drawDop(QPainter &c, int level) drawDopStat(c, dop, ns, n); } - if (navigation.n <= 0 && navigation.ng <= 0 && (doptype == 0 || doptype >= 2) && !simulatedObservation) { // indicate if no navigation data is available + if (navigation->n <= 0 && navigation->ng <= 0 && (doptype == 0 || doptype >= 2) && !simulatedObservation) { // indicate if no navigation data is available graphSingle->getExtent(p1, p2); p2.rx() -= 10; p2.ry() -= 3; @@ -2861,7 +2861,7 @@ void Plot::drawIonoSky(QPainter &c, int level) } } - if (navigation.n <= 0 && navigation.ng <= 0 && !simulatedObservation) { // indicate if no navigation data is available + if (navigation->n <= 0 && navigation->ng <= 0 && !simulatedObservation) { // indicate if no navigation data is available graphSky->getExtent(p1, p2); p2.rx() -= 10; p2.ry() -= 3; diff --git a/app/qtapp/rtkplot_qt/plotinfo.cpp b/app/qtapp/rtkplot_qt/plotinfo.cpp index 52071029b..8c3acd8bf 100644 --- a/app/qtapp/rtkplot_qt/plotinfo.cpp +++ b/app/qtapp/rtkplot_qt/plotinfo.cpp @@ -382,7 +382,6 @@ static int _strcmp(const void *str1, const void *str2) // update observation type pull-down menu -------------------------------------- void Plot::updateObservationType() { - char *codes[MAXCODE + 1], *obs; int i, j, n = 0, codeMask[MAXCODE + 1] = { 0 }; trace(3, "updateObservationType\n"); @@ -393,9 +392,11 @@ void Plot::updateObservationType() codeMask[observation.data[i].code[j]] = 1; // count codes + const char *codes[MAXCODE + 1]; for (uint8_t c = 1; c <= MAXCODE; c++) { if (!codeMask[c]) continue; - if (!*(obs = code2obs(c))) continue; + const char *obs = code2obs(c); + if (!*obs) continue; codes[n++] = obs; } qsort(codes, n, sizeof(char *), _strcmp); diff --git a/app/qtapp/rtkplot_qt/plotmain.cpp b/app/qtapp/rtkplot_qt/plotmain.cpp index e349cf201..f16ee25be 100644 --- a/app/qtapp/rtkplot_qt/plotmain.cpp +++ b/app/qtapp/rtkplot_qt/plotmain.cpp @@ -136,7 +136,7 @@ Plot::Plot(QWidget *parent) : QMainWindow(parent), ui(new Ui::Plot) observationIndex = 0; observation = obs0; - memset(&navigation, 0, sizeof(navigation)); + navigation = new nav_t{}; station = sta0; gis = gis0; simulatedObservation = 0; @@ -395,6 +395,8 @@ Plot::~Plot() delete lWRangeList; delete tVdirectorySelector; + + delete navigation; } // callback on all events ---------------------------------------------------- bool Plot::eventFilter(QObject *obj, QEvent *event) @@ -668,29 +670,29 @@ void Plot::dropEvent(QDropEvent *event) void Plot::openSolution1() { trace(3, "openSolution1\n"); - - readSolution(QStringList(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open Solution 1"), solutionFiles[0].value(0), tr("Solution File (*.pos *.stat *.nmea *.nma *.txt *.ubx);;All (*.*)")))), 0); + QString filename = QFileDialog::getOpenFileName(this, tr("Open Solution 1"), solutionFiles[0].value(0), tr("Solution File (*.pos *.stat *.nmea *.nma *.txt *.ubx);;All (*.*)")); + if (!filename.isEmpty()) readSolution(QStringList(QDir::toNativeSeparators(filename)), 0); } // callback on menu-open-solution-2 ----------------------------------------- void Plot::openSolution2() { trace(3, "openSolution2\n"); - - readSolution(QStringList(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open Solution 2"), solutionFiles[1].value(0), tr("Solution File (*.pos *.stat *.nmea *.nma *.txt *.ubx);;All (*.*)")))), 1); + QString filename = QFileDialog::getOpenFileName(this, tr("Open Solution 2"), solutionFiles[1].value(0), tr("Solution File (*.pos *.stat *.nmea *.nma *.txt *.ubx);;All (*.*)")); + if (!filename.isEmpty()) readSolution(QStringList(QDir::toNativeSeparators(filename)), 1); } // callback on menu-open-map-image ------------------------------------------ void Plot::openMapImage() { trace(3, "openMapImage\n"); - - readMapData(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open Map Image"), mapImageFile, tr("JPEG File (*.jpg *.jpeg);;All (*.*)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("Open Map Image"), mapImageFile, tr("JPEG File (*.jpg *.jpeg);;All (*.*)")); + if (!filename.isEmpty()) readMapData(QDir::toNativeSeparators(filename)); } // callback on menu-open-track-points --------------------------------------- void Plot::openShapeFile() { trace(3, "openShapeFile\n"); - QStringList files = QFileDialog::getOpenFileNames(this, tr("Open Shape File"), QString(), tr("Shape File (*.shp);;All (*.*)")); + if (files.isEmpty()) return; for (int i = 0; i < files.size(); i++) files[i] = QDir::toNativeSeparators(files.at(i)); @@ -700,35 +702,37 @@ void Plot::openShapeFile() void Plot::openSkyImage() { trace(3, "openSkyImage\n"); - - readSkyData(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open Sky Image"), skyImageFile, tr("JPEG File (*.jpg *.jpeg);;All (*.*)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("Open Sky Image"), skyImageFile, tr("JPEG File (*.jpg *.jpeg);;All (*.*)")); + if (!filename.isEmpty()) readSkyData(QDir::toNativeSeparators(filename)); } // callback on menu-oepn-waypoint ------------------------------------------- void Plot::openWaypointsFile() { trace(3, "openWaypointFile\n"); - - readWaypoints(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open Waypoints"), QString(), tr("Waypoints File (*.gpx *.pos);;All (*.*)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("Open Waypoints"), QString(), tr("Waypoints File (*.gpx *.pos);;All (*.*)")); + if (!filename.isEmpty()) readWaypoints(QDir::toNativeSeparators(filename)); } // callback on menu-open-obs-data ------------------------------------------- void Plot::openObservationFile() { trace(3, "openObservationFile\n"); - readObservation(QFileDialog::getOpenFileNames(this, tr("Open Obs/Nav Data"), observationFiles.value(0), tr("RINEX OBS (*.obs *.*o *.*O *.*d *.O.rnx *O.rnx *O.rnx.gz *O.crx *O.crx.gz *.*o.gz *.*o.Z *.d.gz *.d.Z);;All (*.*)"))); + QStringList files = QFileDialog::getOpenFileNames(this, tr("Open Obs/Nav Data"), observationFiles.value(0), tr("RINEX OBS (*.obs *.*o *.*O *.*d *.O.rnx *O.rnx *O.rnx.gz *O.crx *O.crx.gz *.*o.gz *.*o.Z *.d.gz *.d.Z);;All (*.*)")); + if (!files.isEmpty()) readObservation(files); } // callback on menu-open-nav-data ------------------------------------------- void Plot::openNavigationFile() { trace(3, "openNavigationFile\n"); - - readNavigation(QFileDialog::getOpenFileNames(this, tr("Open Raw Obs/Nav Messages"), navigationFiles.value(0), tr("RINEX NAV (*.nav *.gnav *.hnav *.qnav *.*n *.*g *.*h *.*q *.*p *N.rnx *N.rnx.gz);;All (*.*)"))); + QStringList files = QFileDialog::getOpenFileNames(this, tr("Open Raw Obs/Nav Messages"), navigationFiles.value(0), tr("RINEX NAV (*.nav *.gnav *.hnav *.qnav *.*n *.*g *.*h *.*q *.*p *N.rnx *N.rnx.gz);;All (*.*)")); + if (!files.isEmpty()) readNavigation(files); } // callback on menu-open-elev-mask ------------------------------------------ void Plot::openElevationMaskFile() { trace(3, "openElevationMaskFile\n"); - readElevationMaskData(QDir::toNativeSeparators(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open Elevation Mask"), QString(), tr("Text File (*.txt);;All (*.*)"))))); + QString filename = QFileDialog::getOpenFileName(this, tr("Open Elevation Mask"), QString(), tr("Text File (*.txt);;All (*.*)")); + if (!filename.isEmpty()) readElevationMaskData(QDir::toNativeSeparators(filename)); } // callback on menu-vis-analysis -------------------------------------------- void Plot::visibilityAnalysis() @@ -774,35 +778,36 @@ void Plot::visibilityAnalysis() void Plot::savePlotImage() { trace(3, "savePlotImage\n"); - buffer.save(QDir::toNativeSeparators(QFileDialog::getSaveFileName(this, tr("Save Image"), QString(), tr("JPEG (*.jpg);;Windows Bitmap (*.bmp)")))); + QString filename = QFileDialog::getSaveFileName(this, tr("Save Image"), QString(), tr("JPEG (*.jpg);;Windows Bitmap (*.bmp)")); + if (!filename.isEmpty()) buffer.save(QDir::toNativeSeparators(filename)); } // callback on menu-save-waypoint ------------------------------------------- void Plot::saveWaypointsFile() { trace(3, "saveWaypointsFile\n"); - - saveWaypoints(QDir::toNativeSeparators(QFileDialog::getSaveFileName(this, tr("Save Waypoints"), QString(), tr("GPX File (*.gpx *.pos);;All (*.*)")))); + QString filename = QFileDialog::getSaveFileName(this, tr("Save Waypoints"), QString(), tr("GPX File (*.gpx *.pos);;All (*.*)")); + if (!filename.isEmpty()) saveWaypoints(QDir::toNativeSeparators(filename)); } // callback on menu-save-# of sats/dop -------------------------------------- void Plot::saveDopFile() { trace(3, "saveDopFile\n"); - - saveDop(QDir::toNativeSeparators(QFileDialog::getSaveFileName(this, tr("Save Data"), QString(), tr("All (*.*);;Text File (*.txt)")))); + QString filename = QFileDialog::getSaveFileName(this, tr("Save Data"), QString(), tr("All (*.*);;Text File (*.txt)")); + if (!filename.isEmpty()) saveDop(QDir::toNativeSeparators(filename)); } // callback on menu-save-snr,azel ------------------------------------------- void Plot::saveSnrMpFile() { trace(3, "saveSnrMpFile\n"); - - saveSnrMp(QDir::toNativeSeparators(QFileDialog::getSaveFileName(this, tr("Save Data"), QString(), tr("All (*.*);;Text File (*.txt)")))); + QString filename = QFileDialog::getSaveFileName(this, tr("Save Data"), QString(), tr("All (*.*);;Text File (*.txt)")); + if (!filename.isEmpty()) saveSnrMp(QDir::toNativeSeparators(filename)); } // callback on menu-save-elmask --------------------------------------------- void Plot::saveElevationMaskFile() { trace(3, "saveElevationMaskFile\n"); - - saveElevationMask(QDir::toNativeSeparators(QFileDialog::getSaveFileName(this, tr("Save Data"), QString(), tr("All (*.*);;Text File (*.txt)")))); + QString filename = QFileDialog::getSaveFileName(this, tr("Save Data"), QString(), tr("All (*.*);;Text File (*.txt)")); + if (!filename.isEmpty()) saveElevationMask(QDir::toNativeSeparators(filename)); } // callback on menu-connection-settings ------------------------------------- void Plot::showConnectionSettingsDialog() @@ -1532,12 +1537,11 @@ void Plot::mouseDownSolution(int x, int y) graphTriple[0]->getLimits(xl, yl); graphTriple[0]->toPoint(x_pos, yl[1], pnt); - if ((x - pnt.x()) * (x - pnt.x()) + (y - pnt.y()) * (y - pnt.y()) < 5*5) { + double dx = x - pnt.x(), dy = y - pnt.y(); + if (dx * dx + dy * dy < 5 * 5) { setCursor(Qt::SizeHorCursor); - dragState = 20; refresh(); - return; } } @@ -1582,7 +1586,8 @@ void Plot::mouseDownObservation(int x, int y) graphSingle->getLimits(xl, yl); graphSingle->toPoint(x_pos, yl[1], pnt); - if ((x - pnt.x()) * (x - pnt.x()) + (y - pnt.y()) * (y - pnt.y()) < 5*5) { + double dx = x - pnt.x(), dy = y - pnt.y(); + if (dx * dx + dy * dy < 5 * 5) { setCursor(Qt::SizeHorCursor); dragState = 20; refresh(); diff --git a/app/qtapp/rtkplot_qt/plotmain.h b/app/qtapp/rtkplot_qt/plotmain.h index f7064b763..1d00f40cb 100644 --- a/app/qtapp/rtkplot_qt/plotmain.h +++ b/app/qtapp/rtkplot_qt/plotmain.h @@ -250,7 +250,7 @@ protected slots: solstatbuf_t solutionStat[2]; int solutionIndex[2]; obs_t observation; - nav_t navigation; + nav_t *navigation; sta_t station; double *azimuth, *elevation, *multipath[NFREQ+NEXOBS], *ionosphere; char streamBuffer[1024]; diff --git a/app/qtapp/rtkplot_qt/plotopt.cpp b/app/qtapp/rtkplot_qt/plotopt.cpp index 13a7aa12f..71340af56 100644 --- a/app/qtapp/rtkplot_qt/plotopt.cpp +++ b/app/qtapp/rtkplot_qt/plotopt.cpp @@ -200,17 +200,20 @@ void PlotOptDialog::fontSelect() //--------------------------------------------------------------------------- void PlotOptDialog::shapeFileOpen() { - ui->lEShapeFile->setText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open"), ui->lEShapeFile->text()))); + QString filename = QFileDialog::getOpenFileName(this, tr("Open"), ui->lEShapeFile->text()); + if (!filename.isEmpty()) ui->lEShapeFile->setText(QDir::toNativeSeparators(filename)); } //--------------------------------------------------------------------------- void PlotOptDialog::tleFileOpen() { - ui->lETLEFile->setText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open"), ui->lETLEFile->text(), tr("Text Files (*.txt);;Position Files (*.pos *.snx);;All (*.*)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("Open"), ui->lETLEFile->text(), tr("Text Files (*.txt);;Position Files (*.pos *.snx);;All (*.*)")); + if (!filename.isEmpty()) ui->lETLEFile->setText(QDir::toNativeSeparators(filename)); } //--------------------------------------------------------------------------- void PlotOptDialog::tleSatelliteFileOpen() { - ui->lETLESatelliteFile->setText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open"), ui->lETLESatelliteFile->text(), tr("Text Files (*.txt);;Position Files (*.pos *.snx);;All (*.*)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("Open"), ui->lETLESatelliteFile->text(), tr("Text Files (*.txt);;Position Files (*.pos *.snx);;All (*.*)")); + if (!filename.isEmpty()) ui->lETLESatelliteFile->setText(QDir::toNativeSeparators(filename)); } //--------------------------------------------------------------------------- void PlotOptDialog::referencePositionSelect() diff --git a/app/qtapp/rtkplot_qt/skydlg.cpp b/app/qtapp/rtkplot_qt/skydlg.cpp index 4332b2596..2c3e76845 100644 --- a/app/qtapp/rtkplot_qt/skydlg.cpp +++ b/app/qtapp/rtkplot_qt/skydlg.cpp @@ -116,8 +116,9 @@ void SkyImgDialog::updateSkyEnabled() //--------------------------------------------------------------------------- void SkyImgDialog::loadSkyImageTag() { - readSkyTag(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open Tag"), plot->getSkyImageFileName(), tr("Tag File (*.tag);;All (*.*)")))); - + QString filename = QFileDialog::getOpenFileName(this, tr("Open Tag"), plot->getSkyImageFileName(), tr("Tag File (*.tag);;All (*.*)")); + if (filename.isEmpty()) return; + readSkyTag(QDir::toNativeSeparators(filename)); updateSky(); } //--------------------------------------------------------------------------- diff --git a/app/qtapp/rtkpost_qt/CMakeLists.txt b/app/qtapp/rtkpost_qt/CMakeLists.txt index 2cd56ddb2..0ce1be10a 100644 --- a/app/qtapp/rtkpost_qt/CMakeLists.txt +++ b/app/qtapp/rtkpost_qt/CMakeLists.txt @@ -51,7 +51,7 @@ set_target_properties(rtkpost_qt PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON ) -install(TARGETS rtkget_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) +install(TARGETS rtkpost_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) if (UNIX) install(FILES rtkpost_qt.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) install(FILES ../icon/rtkpost.png DESTINATION ${XDG_APPS_PIXMAPS_DIR}) diff --git a/app/qtapp/rtkpost_qt/kmzconv.cpp b/app/qtapp/rtkpost_qt/kmzconv.cpp index b68b5cfb2..910b6cd4f 100644 --- a/app/qtapp/rtkpost_qt/kmzconv.cpp +++ b/app/qtapp/rtkpost_qt/kmzconv.cpp @@ -80,7 +80,9 @@ void ConvDialog::setInput(const QString &filename) //--------------------------------------------------------------------------- void ConvDialog::selectInputFile() { - ui->lEInputFile->setText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Open..."), ui->lEInputFile->text(), tr("All (*.*)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("Open..."), ui->lEInputFile->text(), tr("All (*.*)")); + if (filename.isEmpty()) return; + ui->lEInputFile->setText(QDir::toNativeSeparators(filename)); updateOutputFile(); } //--------------------------------------------------------------------------- @@ -232,7 +234,8 @@ void ConvDialog::updateOutputFile() //--------------------------------------------------------------------------- void ConvDialog::selectGoogleEarthFile() { - ui->lEGoogleEarthFile->setText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Google Earth Exe File"), ui->lEGoogleEarthFile->text()))); + QString filename = QFileDialog::getOpenFileName(this, tr("Google Earth Exe File"), ui->lEGoogleEarthFile->text()); + if (!filename.isEmpty()) ui->lEGoogleEarthFile->setText(QDir::toNativeSeparators(filename)); } //--------------------------------------------------------------------------- void ConvDialog::callGoogleEarth() diff --git a/app/qtapp/rtkpost_qt/postmain.cpp b/app/qtapp/rtkpost_qt/postmain.cpp index 4b37fd951..de8ffd71d 100644 --- a/app/qtapp/rtkpost_qt/postmain.cpp +++ b/app/qtapp/rtkpost_qt/postmain.cpp @@ -560,45 +560,53 @@ void MainForm::showStopTimeDialog() // callback on button-inputfile-1 ------------------------------------------- void MainForm::selectInputFile1() { - ui->cBInputFile1->setCurrentText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("RINEX OBS (Rover) File"), ui->cBInputFile1->currentText(), - tr("All (*.*);;RINEX OBS (*.rnx *.obs *.*O *.*D)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("RINEX OBS (Rover) File"), ui->cBInputFile1->currentText(), + tr("All (*.*);;RINEX OBS (*.rnx *.obs *.*O *.*D)")); + if (filename.isEmpty()) return; + ui->cBInputFile1->setCurrentText(QDir::toNativeSeparators(filename)); setOutputFile(); } // callback on button-inputfile-2 ------------------------------------------ void MainForm::selectInputFile2() { - ui->cBInputFile2->setCurrentText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("RINEX OBS (Base Station) File"), ui->cBInputFile2->currentText(), - tr("All (*.*);;RINEX OBS (*.rnx *.obs *.*O *.*D)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("RINEX OBS (Base Station) File"), ui->cBInputFile2->currentText(), + tr("All (*.*);;RINEX OBS (*.rnx *.obs *.*O *.*D)")); + if (!filename.isEmpty()) ui->cBInputFile2->setCurrentText(QDir::toNativeSeparators(filename)); } // callback on button-inputfile-3 ------------------------------------------- void MainForm::selectInputFile3() { - ui->cBInputFile3->setCurrentText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("RINEX NAV/CLK,SP3,Bias-SINEX,IONEX or SBAS/EMS File"), ui->cBInputFile3->currentText(), - tr("All (*.*);;RINEX NAV (*.rnx *.*nav *.*N *.*P *.*G *.*H *.*Q)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("RINEX NAV/CLK,SP3,Bias-SINEX,IONEX or SBAS/EMS File"), ui->cBInputFile3->currentText(), + tr("All (*.*);;RINEX NAV (*.rnx *.*nav *.*N *.*P *.*G *.*H *.*Q)")); + if (!filename.isEmpty()) ui->cBInputFile3->setCurrentText(QDir::toNativeSeparators(filename)); } // callback on button-inputfile-4 ------------------------------------------- void MainForm::selectInputFile4() { - ui->cBInputFile4->setCurrentText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("RINEX NAV/CLK,SP3,Bias-SINEX,IONEX or SBAS/EMS File"), ui->cBInputFile4->currentText(), - tr("All (*.*);;Precise Ephemeris/Clock/Biases (*.SP3 *.sp3 *.eph* *.CLK *.clk* *.BIA)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("RINEX NAV/CLK,SP3,Bias-SINEX,IONEX or SBAS/EMS File"), ui->cBInputFile4->currentText(), + tr("All (*.*);;Precise Ephemeris/Clock/Biases (*.SP3 *.sp3 *.eph* *.CLK *.clk* *.BIA)")); + if (!filename.isEmpty()) ui->cBInputFile4->setCurrentText(QDir::toNativeSeparators(filename)); } // callback on button-inputfile-5 ------------------------------------------- void MainForm::selectInputFile5() { - ui->cBInputFile5->setCurrentText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("RINEX NAV/CLK,SP3,Bias-SINEX,IONEX or SBAS/EMS File"), ui->cBInputFile5->currentText(), - tr("All (*.*);;Precise Ephemeris/Clock/Biases (*.SP3 *.sp3 *.eph* *.CLK *.clk* *.BIA)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("RINEX NAV/CLK,SP3,Bias-SINEX,IONEX or SBAS/EMS File"), ui->cBInputFile5->currentText(), + tr("All (*.*);;Precise Ephemeris/Clock/Biases (*.SP3 *.sp3 *.eph* *.CLK *.clk* *.BIA)")); + if (!filename.isEmpty()) ui->cBInputFile5->setCurrentText(QDir::toNativeSeparators(filename)); } // callback on button-inputfile-6 ------------------------------------------- void MainForm::selectInputFile6() { - ui->cBInputFile6->setCurrentText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("RINEX NAV/CLK,SP3,Bias-SINEX,IONEX or SBAS/EMS File"), ui->cBInputFile6->currentText(), - tr("All (*.*);;Bias-SINEX (*.BIA *.BSX),IONEX (*.*i *.ionex, *.inx),SBAS (*.sbs *.ems)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("RINEX NAV/CLK,SP3,Bias-SINEX,IONEX or SBAS/EMS File"), ui->cBInputFile6->currentText(), + tr("All (*.*);;Bias-SINEX (*.BIA *.BSX),IONEX (*.*i *.ionex, *.inx),SBAS (*.sbs *.ems)")); + if (!filename.isEmpty()) ui->cBInputFile6->setCurrentText(QDir::toNativeSeparators(filename)); } // callback on button-outputfile -------------------------------------------- void MainForm::selectOutputFile() { - ui->cBOutputFile->setCurrentText(QDir::toNativeSeparators(QFileDialog::getSaveFileName(this, tr("Output File"), ui->cBOutputFile->currentText(), - tr("All (*.*);;Position Files (*.pos)")))); + QString filename = QFileDialog::getSaveFileName(this, tr("Output File"), ui->cBOutputFile->currentText(), + tr("All (*.*);;Position Files (*.pos)")); + if (!filename.isEmpty()) ui->cBOutputFile->setCurrentText(QDir::toNativeSeparators(filename)); } // callback on button-inputview-1 ------------------------------------------- void MainForm::viewInputFile1() @@ -711,7 +719,8 @@ void MainForm::plotInputFile2() // callback on button-output-directory -------------------------------------- void MainForm::selectOutputDirectory() { - ui->lEOutputDirectory->setText(QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("Output Directory"), ui->lEOutputDirectory->text()))); + QString dir = QFileDialog::getExistingDirectory(this, tr("Output Directory"), ui->lEOutputDirectory->text()); + if (!dir.isEmpty()) ui->lEOutputDirectory->setText(QDir::toNativeSeparators(dir)); } // callback on button keyword ----------------------------------------------- void MainForm::showKeyDialog() diff --git a/app/qtapp/srctblbrows_qt/CMakeLists.txt b/app/qtapp/srctblbrows_qt/CMakeLists.txt index 0db977e86..05eba4e95 100644 --- a/app/qtapp/srctblbrows_qt/CMakeLists.txt +++ b/app/qtapp/srctblbrows_qt/CMakeLists.txt @@ -51,7 +51,7 @@ set_target_properties(srctblbrows_qt PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON ) -install(TARGETS rtkget_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) +install(TARGETS srctblbrows_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) if (UNIX) install(FILES srctblbrows_qt.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) install(FILES ../icon/srctblbrows.png DESTINATION ${XDG_APPS_PIXMAPS_DIR}) diff --git a/app/qtapp/srctblbrows_qt/browsmain.cpp b/app/qtapp/srctblbrows_qt/browsmain.cpp index 190dd2cf6..1ab6a4e6d 100644 --- a/app/qtapp/srctblbrows_qt/browsmain.cpp +++ b/app/qtapp/srctblbrows_qt/browsmain.cpp @@ -406,7 +406,7 @@ void MainForm::casterTableSelectItem(int row, int col) { Q_UNUSED(col); - if (ui->tWTableStr->columnCount() < 3) return; + if (ui->tWTableCas->columnCount() < 3) return; if (0 <= row && row < ui->tWTableCas->rowCount()) { @@ -564,17 +564,21 @@ void MainForm::showTable() table[type]->setRowCount(numStations); j = 0; foreach(QString line, lines) { - switch (type) { - case 0: if (line.startsWith("STR")) break; else continue; - case 1: if (line.startsWith("CAS")) break; else continue; - case 2: if (line.startsWith("NET")) break; else continue; - } - table[type]->setItem(j, 0, new QTableWidgetItem(QString::number(j))); - QStringList tokens = line.split(";"); - for (int i = 0; i < table[type]->columnCount() && i < tokens.size(); i++) - table[type]->setItem(j, i, new QTableWidgetItem(tokens.at(i))); - j++; - } + switch (type) { + case 0: if (line.startsWith("STR")) break; else continue; + case 1: if (line.startsWith("CAS")) break; else continue; + case 2: if (line.startsWith("NET")) break; else continue; + } + table[type]->setItem(j, 0, new QTableWidgetItem(QString::number(j))); + QStringList tokens = line.split(";"); + for (int i = 0; i < table[type]->columnCount(); i++) { + if (i < tokens.size()) + table[type]->setItem(j, i, new QTableWidgetItem(tokens.at(i))); + else + table[type]->setItem(j, i, new QTableWidgetItem()); + } + j++; + } updateMap(); } //--------------------------------------------------------------------------- diff --git a/app/qtapp/strsvr_qt/CMakeLists.txt b/app/qtapp/strsvr_qt/CMakeLists.txt index c3e2aeaa9..6aeb360f1 100644 --- a/app/qtapp/strsvr_qt/CMakeLists.txt +++ b/app/qtapp/strsvr_qt/CMakeLists.txt @@ -53,7 +53,7 @@ set_target_properties(strsvr_qt PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON ) -install(TARGETS rtkget_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) +install(TARGETS strsvr_qt RUNTIME DESTINATION bin BUNDLE DESTINATION bin) if (UNIX) install(FILES strsvr_qt.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) install(FILES ../icon/strsvr.png DESTINATION ${XDG_APPS_PIXMAPS_DIR}) diff --git a/app/qtapp/strsvr_qt/svrmain.cpp b/app/qtapp/strsvr_qt/svrmain.cpp index 3a1420e9b..92dce0baf 100644 --- a/app/qtapp/strsvr_qt/svrmain.cpp +++ b/app/qtapp/strsvr_qt/svrmain.cpp @@ -822,7 +822,7 @@ void MainForm::loadOptions() svrOptDialog->traceLevel = settings.value("set/tracelevel", 0).toInt(); svrOptDialog->nmeaRequest = settings.value("set/nmeareq", 0).toInt(); svrOptDialog->fileSwapMargin = settings.value("set/fswapmargin", 30).toInt(); - svrOptDialog->relayBack = settings.value("set/relayback", 30).toInt(); + svrOptDialog->relayBack = settings.value("set/relayback", 0).toInt(); svrOptDialog->progressBarRange = settings.value("set/progbarrange", 30).toInt(); svrOptDialog->stationId = settings.value("set/staid", 0).toInt(); svrOptDialog->stationSelect = settings.value("set/stasel", 0).toInt(); diff --git a/app/qtapp/strsvr_qt/svroptdlg.cpp b/app/qtapp/strsvr_qt/svroptdlg.cpp index c075307e6..0f1db5f81 100644 --- a/app/qtapp/strsvr_qt/svroptdlg.cpp +++ b/app/qtapp/strsvr_qt/svroptdlg.cpp @@ -178,6 +178,7 @@ void SvrOptDialog::updateEnable() //--------------------------------------------------------------------------- void SvrOptDialog::logFileSelect() { - ui->lELogFile->setText(QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Log File"), ui->lELogFile->text(), tr("All (*.*)")))); + QString filename = QFileDialog::getOpenFileName(this, tr("Log File"), ui->lELogFile->text(), tr("All (*.*)")); + if (!filename.isEmpty()) ui->lELogFile->setText(QDir::toNativeSeparators(filename)); } //--------------------------------------------------------------------------- diff --git a/app/qtapp/strsvr_qt/svroptdlg.ui b/app/qtapp/strsvr_qt/svroptdlg.ui index dbd7ba044..dc322a662 100644 --- a/app/qtapp/strsvr_qt/svroptdlg.ui +++ b/app/qtapp/strsvr_qt/svroptdlg.ui @@ -620,6 +620,21 @@ (3) -> (0) + + + (4) -> (0) + + + + + (5) -> (0) + + + + + (6) -> (0) + + diff --git a/app/winapp/rtkconv/convmain.dfm b/app/winapp/rtkconv/convmain.dfm index 11a53e04b..2fd620a70 100644 --- a/app/winapp/rtkconv/convmain.dfm +++ b/app/winapp/rtkconv/convmain.dfm @@ -1149,9 +1149,10 @@ object MainWindow: TMainWindow object OpenDialog: TOpenDialog Filter = 'All (*.*)|*.*|RTCM 2 (*.rtcm2)|*.rtcm2|RTCM 3 (*.rtcm3)|*.rtcm3|' + - 'NovtAtel (*.gps)|*.gps|ublox (*.ubx)|*.ubx|SuperStart II (*.log)' + - '|*.log|Hemisphere (*.bin)|*.bin|Javad (*.jps)|*.jps|RINEX OBS (*' + - '.obs,*.*O)|*.obs;*.*O' + 'NovtAtel (*.gps)|*.gps|ublox (*.ubx)|*.ubx' + + '|Hemisphere (*.bin)|*.bin|Javad (*.jps)|*.jps|' + + 'Septentrio (*.sbf)|*.sbf|' + + 'RINEX OBS (*.obs,*.*O)|*.obs;*.*O' Options = [ofHideReadOnly, ofNoChangeDir, ofEnableSizing] Left = 260 Top = 221 diff --git a/app/winapp/rtkconv/rtkconv.cbproj b/app/winapp/rtkconv/rtkconv.cbproj index 848faff65..dfd5d201c 100644 --- a/app/winapp/rtkconv/rtkconv.cbproj +++ b/app/winapp/rtkconv/rtkconv.cbproj @@ -593,7 +593,6 @@ - @@ -633,7 +632,6 @@ - diff --git a/app/winapp/rtknavi/mondlg.cpp b/app/winapp/rtknavi/mondlg.cpp index b9e71bfbe..673d993c8 100644 --- a/app/winapp/rtknavi/mondlg.cpp +++ b/app/winapp/rtknavi/mondlg.cpp @@ -173,12 +173,12 @@ void __fastcall TMonitorDialog::ClearTable(void) SelObs ->Visible=TypeF==1; SelSys ->Visible=TypeF==1||TypeF==5; SelSys2 ->Visible=TypeF==2||TypeF==14; - SelSat ->Visible=TypeF==2||TypeF==5; + SelSat ->Visible=TypeF==2||TypeF==5||TypeF==6||TypeF==7||TypeF==14; SelStr ->Visible=TypeF==12||TypeF==14||TypeF==15||TypeF==16; SelStr2 ->Visible=TypeF==17; SelFmt ->Visible=TypeF==16; SelEph ->Visible=TypeF==2; - SelStr ->Left=(TypeF==14)?SelSys->Left+SelSys->Width+1:Type->Left+Type->Width+1; + SelStr ->Left=(TypeF==14)?SelSat->Left+SelSat->Width+1:Type->Left+Type->Width+1; } //--------------------------------------------------------------------------- void __fastcall TMonitorDialog::Timer2Timer(TObject *Sender) @@ -410,8 +410,14 @@ void __fastcall TMonitorDialog::ShowRtk(void) rtksvrunlock(&rtksvr); // unlock for (j=k=0;jopt.mode==PMODE_SINGLE&&!rtk->ssat[j].vs) continue; - if (rtk->opt.mode!=PMODE_SINGLE&&!rtk->ssat[j].vsat[0]) continue; + if (rtk->opt.mode == PMODE_SINGLE) { + if (!rtk->ssat[j].vs) continue; + } else { + int any = 0; + for (int fi = 0; fi < NFREQ; fi++) + if (rtk->ssat[j].vsat[fi]) { any = 1; break; } + if (!any) continue; + } azel[ k*2]=rtk->ssat[j].azel[0]; azel[1+k*2]=rtk->ssat[j].azel[1]; k++; @@ -478,8 +484,14 @@ void __fastcall TMonitorDialog::ShowRtk(void) rtk->opt.snrmask.mask[3][0],rtk->opt.snrmask.mask[3][1],rtk->opt.snrmask.mask[3][2], rtk->opt.snrmask.mask[3][3],rtk->opt.snrmask.mask[3][4],rtk->opt.snrmask.mask[3][5], rtk->opt.snrmask.mask[3][6],rtk->opt.snrmask.mask[3][7],rtk->opt.snrmask.mask[3][8]); - Tbl->Cells[0][i ]="Rec Dynamic/Earth Tides Correction"; - Tbl->Cells[1][i++]=s.sprintf("%s, %s",rtk->opt.dynamics?"ON":"OFF",rtk->opt.tidecorr?"ON":"OFF"); + + Tbl->Cells[0][i ]="Rec Dynamics"; + Tbl->Cells[1][i++]=s.sprintf("%s",rtk->opt.dynamics?"ON":"OFF"); + + Tbl->Cells[0][i ]="Earth Tides Correction"; + const char *tideopts[]={"OFF","Solid Earth","Ocean Loading","Solid Earth + Ocean Loading","Solid Pole", + "Solid Earth + Solid Pole","Ocean Loading + Sold Pole","Solid Earth + Ocean Loading + Solid Pole"}; + Tbl->Cells[1][i++]=s.sprintf("%s", tideopts[rtk->opt.tidecorr & 7]); Tbl->Cells[0][i ]="Ionosphere/Troposphere Model"; Tbl->Cells[1][i++]=s.sprintf("%s, %s",ionoopt[rtk->opt.ionoopt],tropopt[rtk->opt.tropopt]); @@ -740,8 +752,13 @@ void __fastcall TMonitorDialog::ShowSat(void) Label->Caption=""; for (i=0;issat+i; - vsat[i]=ssat->vs; + if (rtk->opt.mode == PMODE_SINGLE) { + vsat[i] = rtk->ssat[i].vs; + } else { + vsat[i] = 0; + for (int fi = 0; fi < NFREQ; fi++) + if (rtk->ssat[i].vsat[fi]) { vsat[i] = 1; break; } + } } for (i=0,n=1;iItemIndex==1&&!vsat[i]) continue; satno2id(i+1,id); Tbl->Cells[j++][n]=id; - Tbl->Cells[j++][n]=ssat->vs?"OK":"-"; + Tbl->Cells[j++][n]=vsat[i]?"OK":"-"; az=ssat->azel[0]*R2D; if (az<0.0) az+=360.0; el=ssat->azel[1]*R2D; Tbl->Cells[j++][n]=s.sprintf("%.1f",az); @@ -991,7 +1008,7 @@ void __fastcall TMonitorDialog::SetObs(void) void __fastcall TMonitorDialog::ShowObs(void) { AnsiString s; - char tstr[40],id[8],*code; + char tstr[40],id[8]; int i,j,k,n=0,nex=ObsMode?NEXOBS:0,sys=sys_tbl[SelSys->ItemIndex]; obsd_t *obs = static_cast(calloc(MAXOBS * 2, sizeof(obsd_t))); @@ -1023,7 +1040,7 @@ void __fastcall TMonitorDialog::ShowObs(void) Tbl->Cells[j++][i+1]=id; Tbl->Cells[j++][i+1]=s.sprintf("(%d)",obs[i].rcv); for (k=0;kCells[j++][i+1]=s.sprintf("%s",code); else Tbl->Cells[j++][i+1]="-"; } @@ -1782,35 +1799,37 @@ void __fastcall TMonitorDialog::SetRtcm(void) void __fastcall TMonitorDialog::ShowRtcm(void) { AnsiString s; - static rtcm_t rtcm; double pos[3]={0}; int i=1,j,format; char tstr[40]="-",mstr1[1024]="",mstr2[1024]="",*p1=mstr1,*p2=mstr2; + rtcm_t *rtcm = (rtcm_t *)malloc(sizeof(rtcm_t)); + if (rtcm == NULL) return; + rtksvrlock(&rtksvr); format=rtksvr.format[Str1]; - rtcm=rtksvr.rtcm[Str1]; + *rtcm=rtksvr.rtcm[Str1]; rtksvrunlock(&rtksvr); - if (rtcm.time.time) time2str(rtcm.time,tstr,3); + if (rtcm->time.time) time2str(rtcm->time,tstr,3); for (j=1;j<100;j++) { - if (rtcm.nmsg2[j]==0) continue; - p1+=sprintf(p1,"%s%d (%d)",p1>mstr1?",":"",j,rtcm.nmsg2[j]); + if (rtcm->nmsg2[j]==0) continue; + p1+=sprintf(p1,"%s%d (%d)",p1>mstr1?",":"",j,rtcm->nmsg2[j]); } - if (rtcm.nmsg2[0]>0) { - sprintf(p1,"%sother (%d)",p1>mstr1?",":"",rtcm.nmsg2[0]); + if (rtcm->nmsg2[0]>0) { + sprintf(p1,"%sother (%d)",p1>mstr1?",":"",rtcm->nmsg2[0]); } for (j=1;j<300;j++) { - if (rtcm.nmsg3[j]==0) continue; - p2+=sprintf(p2,"%s%d(%d)",p2>mstr2?",":"",j+1000,rtcm.nmsg3[j]); + if (rtcm->nmsg3[j]==0) continue; + p2+=sprintf(p2,"%s%d(%d)",p2>mstr2?",":"",j+1000,rtcm->nmsg3[j]); } for (j=300;j<399;j++) { - if (rtcm.nmsg3[j]==0) continue; - p2+=sprintf(p2,"%s%d(%d)",p2>mstr2?",":"",j+3770,rtcm.nmsg3[j]); + if (rtcm->nmsg3[j]==0) continue; + p2+=sprintf(p2,"%s%d(%d)",p2>mstr2?",":"",j+3770,rtcm->nmsg3[j]); } - if (rtcm.nmsg3[0]>0) { - sprintf(p2,"%sother(%d)",p2>mstr2?",":"",rtcm.nmsg3[0]); + if (rtcm->nmsg3[0]>0) { + sprintf(p2,"%sother(%d)",p2>mstr2?",":"",rtcm->nmsg3[0]); } Label->Caption=""; @@ -1823,43 +1842,45 @@ void __fastcall TMonitorDialog::ShowRtcm(void) Tbl->Cells[1][i++]=tstr; Tbl->Cells[0][i ]="Station ID"; - Tbl->Cells[1][i++]=s.sprintf("%d",rtcm.staid); + Tbl->Cells[1][i++]=s.sprintf("%d",rtcm->staid); Tbl->Cells[0][i ]="Station Health"; - Tbl->Cells[1][i++]=s.sprintf("%d",rtcm.stah); + Tbl->Cells[1][i++]=s.sprintf("%d",rtcm->stah); Tbl->Cells[0][i ]="Sequence No"; - Tbl->Cells[1][i++]=s.sprintf("%d",rtcm.seqno); + Tbl->Cells[1][i++]=s.sprintf("%d",rtcm->seqno); Tbl->Cells[0][i ]="RTCM Special Message"; - Tbl->Cells[1][i++]=rtcm.msg; + Tbl->Cells[1][i++]=rtcm->msg; Tbl->Cells[0][i ]="Last Message"; - Tbl->Cells[1][i++]=rtcm.msgtype; + Tbl->Cells[1][i++]=rtcm->msgtype; Tbl->Cells[0][i ]="# of RTCM Messages"; Tbl->Cells[1][i++]=format==STRFMT_RTCM2?mstr1:mstr2; Tbl->Cells[0][i ]="MSM Signals for GPS"; - Tbl->Cells[1][i++]=rtcm.msmtype[0]; + Tbl->Cells[1][i++]=rtcm->msmtype[0]; Tbl->Cells[0][i ]="MSM Signals for GLONASS"; - Tbl->Cells[1][i++]=rtcm.msmtype[1]; + Tbl->Cells[1][i++]=rtcm->msmtype[1]; Tbl->Cells[0][i ]="MSM Signals for Galileo"; - Tbl->Cells[1][i++]=rtcm.msmtype[2]; + Tbl->Cells[1][i++]=rtcm->msmtype[2]; Tbl->Cells[0][i ]="MSM Signals for QZSS"; - Tbl->Cells[1][i++]=rtcm.msmtype[3]; + Tbl->Cells[1][i++]=rtcm->msmtype[3]; Tbl->Cells[0][i ]="MSM Signals for SBAS"; - Tbl->Cells[1][i++]=rtcm.msmtype[4]; + Tbl->Cells[1][i++]=rtcm->msmtype[4]; Tbl->Cells[0][i ]="MSM Signals for BDS"; - Tbl->Cells[1][i++]=rtcm.msmtype[5]; + Tbl->Cells[1][i++]=rtcm->msmtype[5]; Tbl->Cells[0][i ]="MSM Signals for NavIC"; - Tbl->Cells[1][i++]=rtcm.msmtype[6]; + Tbl->Cells[1][i++]=rtcm->msmtype[6]; + + free(rtcm); } //--------------------------------------------------------------------------- void __fastcall TMonitorDialog::SetRtcmDgps(void) @@ -1918,7 +1939,7 @@ void __fastcall TMonitorDialog::SetRtcmSsr(void) "Phase Bias(m)" }; int i,width[]={ - 25,30,30,30,30,25,15,115,50,50,50,50,50,50,50,50,50,50,180,180 + 25,30,30,30,30,25,15,115,50,50,50,50,50,50,50,50,50,50,250,250 }; char *code; @@ -1944,6 +1965,8 @@ void __fastcall TMonitorDialog::ShowRtcmSsr(void) for (i=n=0;i= 0; + if (SelSat->ItemIndex == 1 && !valid) continue; sat[n++]=i+1; } rtksvrunlock(&rtksvr); @@ -1959,7 +1982,7 @@ void __fastcall TMonitorDialog::ShowRtcmSsr(void) Tbl->Cells[j++][i+1]=valid?"OK":"-"; Tbl->Cells[j++][i+1]=s.sprintf("%.0f",ssr[i].udi[0]); Tbl->Cells[j++][i+1]=s.sprintf("%.0f",ssr[i].udi[2]); - Tbl->Cells[j++][i+1]=s.sprintf("%d",ssr[i].iode); + Tbl->Cells[j++][i+1] = ssr[i].iode < 0 ? "-" : s.sprintf("%d", ssr[i].iode); Tbl->Cells[j++][i+1]=s.sprintf("%d",ssr[i].ura); Tbl->Cells[j++][i+1]=s.sprintf("%d",ssr[i].refd); if (ssr[i].t0[0].time) time2str(ssr[i].t0[0],tstr,0); else strcpy(tstr,"-"); diff --git a/app/winapp/rtknavi/navimain.cpp b/app/winapp/rtknavi/navimain.cpp index a0ce89240..a98548b52 100644 --- a/app/winapp/rtknavi/navimain.cpp +++ b/app/winapp/rtknavi/navimain.cpp @@ -127,8 +127,8 @@ __fastcall TMainForm::TMainForm(TComponent* Owner) CmdEna[i][0]=CmdEna[i][1]=CmdEna[i][2]=0; } TimeSys=SolType=PlotType1=PlotType2=FreqType1=FreqType2=0; - TrkType1=TrkType2=0; - TrkScale1=TrkScale2=5; + TrkType1=TrkType2=TrkType3=TrkType4=0; + TrkScale1=TrkScale2=TrkScale3=TrkScale4=8; BLMode1=BLMode2=BLMode3=BLMode4=0; PSol=PSolS=PSolE=Nsat[0]=Nsat[1]=0; NMapPnt=0; @@ -138,9 +138,12 @@ __fastcall TMainForm::TMainForm(TComponent* Owner) SolCurrentStat=0; SolRov=SolRef=Qr=VelRov=Age=Ratio=NULL; for (int i=0;i<2;i++) for (int j=0;j=MAXTRKSCALE) return; + TrkScale3++; + UpdatePlot(); +} +// callback on button expand-4 ---------------------------------------------- +void __fastcall TMainForm::BtnExpand4Click(TObject *Sender) +{ + if (TrkScale4<=0) return; + TrkScale4--; + UpdatePlot(); +} +// callback on button shrink-4 ---------------------------------------------- +void __fastcall TMainForm::BtnShrink4Click(TObject *Sender) +{ + if (TrkScale4>=MAXTRKSCALE) return; + TrkScale4++; + UpdatePlot(); +} // callback on button-rtk-monitor ------------------------------------------- void __fastcall TMainForm::BtnMonitorClick(TObject *Sender) { @@ -1292,6 +1323,7 @@ void __fastcall TMainForm::SvrStart(void) strsetopt(stropt); strcpy(rtksvr.cmd_reset,ResetCmd.c_str()); rtksvr.bl_reset=MaxBL; + //rtksvrinit(&rtksvr); // uncomment this to make RTKNAVI repeatable from run to run (useful for debug) // start rtk server if (!rtksvrstart(&rtksvr,SvrCycle,SvrBuffSize,strs,(const char **)paths,Format, @@ -1637,8 +1669,8 @@ void __fastcall TMainForm::DrawPlot(TImage *plot, int type, int freq) TCanvas *c=plot->Canvas; TLabel *label[]={Plabel1,Plabel2,Plabel3,Pos1,Pos2,Pos3}; int w=plot->Parent->Width-2,h=plot->Parent->Height-2; - int i,j,x,sat[2][MAXSAT],ns[2],snr[2][MAXSAT][NFREQ],vsat[2][MAXSAT]; - int *snr0[MAXSAT],*snr1[MAXSAT],tm=PanelFont->Size*3/2; + int i,j,x,sat[2][MAXSAT],ns[2],snr[2][MAXSAT][NFREQ],vsat[2][MAXSAT][NFREQ]; + int tm=PanelFont->Size*3/2; char name[16]; double az[2][MAXSAT],el[2][MAXSAT],rr[3],rs[6],e[3],pos[3],azel[2]; @@ -1649,12 +1681,8 @@ void __fastcall TMainForm::DrawPlot(TImage *plot, int type, int freq) } fstr[i+1]=" SYS"; - for (i=0;iBrush->Style=bsSolid; c->Brush->Color=freqBrush->Color=clSilver; + int any = 0; + for (int fi = 0; fi < NFREQ; fi++) + if (Vsat[index][i][fi]) { any = 1; break; } + if (!any) c->Brush->Color=clSilver; c->Rectangle(r1); } else { @@ -1900,7 +1931,10 @@ void __fastcall TMainForm::DrawSat(TCanvas *c, int w, int h, int x0, int y0, snr[0]=snr[j+1]; // max snr } } - if (Vsat[index][k]&&(freq>NFREQ||snr[freq]>0)) { + int anyvsatf = 0; + for (int fi = 0; fi < NFREQ; fi++) + if (Vsat[index][k][fi]) { anyvsatf = 1; break; } + if (anyvsatf && (freq > NFREQ || snr[freq] > 0)) { azel[ns*2]=Az[index][k]; azel[1+ns*2]=El[index][k]; ns++; } @@ -1909,7 +1943,7 @@ void __fastcall TMainForm::DrawSat(TCanvas *c, int w, int h, int x0, int y0, x[i]=(int)(p.x+r*(90-El[index][k]*R2D)/90*sin(Az[index][k]))+x0; y[i]=(int)(p.y-r*(90-El[index][k]*R2D)/90*cos(Az[index][k]))+y0; d=PanelFont->Size*3/2; - c->Brush->Color=!Vsat[index][k]?clSilver: + c->Brush->Color=!anyvsatf?clSilver: (freqBrush->Style=bsSolid; c->Pen->Color=clGray; @@ -2037,12 +2071,12 @@ void __fastcall TMainForm::DrawTrk(TImage *plot) 10000.0 }; double *x,*y,xt,yt,sx,sy,ref[3],pos[3],dr[3],enu[3]; - int i,j,k,n=0,type,scl; + int i,j,k,n=0; trace(3,"DrawTrk\n"); - type=plot->Name=="Plot1"?TrkType1 :TrkType2 ; - scl =plot->Name=="Plot1"?TrkScale1:TrkScale2; + int type=plot->Name=="Plot1"?TrkType1:plot->Name=="Plot2"?TrkType2:plot->Name=="Plot3"?TrkType3:TrkType4; + int scl =plot->Name=="Plot1"?TrkScale1:plot->Name=="Plot2"?TrkScale2:plot->Name=="Plot3"?TrkScale3:TrkScale4; x=new double[SolBuffSize]; y=new double[SolBuffSize]; @@ -2294,19 +2328,19 @@ void __fastcall TMainForm::LoadNav(nav_t *nav) AnsiString str,s; eph_t eph0={0}; char buff[2049],id[32],*p; - long toe_time,toc_time,ttr_time; + long unsigned toe_time,toc_time,ttr_time; int i; trace(3,"LoadNav\n"); for (i=0;iReadString("navi",s.sprintf("eph_%02d",i),""))=="") continue; + if ((str=ini->ReadString("navi",s.sprintf("eph_%03d",i),""))=="") continue; nav->eph[i]=eph0; strcpy(buff,str.c_str()); if (!(p=strchr(buff,','))) continue; *p='\0'; if (!(nav->eph[i].sat=satid2no(buff))) continue; - sscanf(p+1,"%d,%d,%d,%d,%ld,%ld,%ld,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%d,%d,%lf", + sscanf(p+1,"%d,%d,%d,%d,%lu,%lu,%lu,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%d,%d,%lf", &nav->eph[i].iode, &nav->eph[i].iodc, &nav->eph[i].sva , @@ -2375,9 +2409,9 @@ void __fastcall TMainForm::SaveNav(nav_t *nav) str=str+s.sprintf("%d,",nav->eph[i].iodc); str=str+s.sprintf("%d,",nav->eph[i].sva); str=str+s.sprintf("%d,",nav->eph[i].svh); - str=str+s.sprintf("%d,",(int)nav->eph[i].toe.time); - str=str+s.sprintf("%d,",(int)nav->eph[i].toc.time); - str=str+s.sprintf("%d,",(int)nav->eph[i].ttr.time); + str=str+s.sprintf("%lu,",(long unsigned)nav->eph[i].toe.time); + str=str+s.sprintf("%lu,",(long unsigned)nav->eph[i].toc.time); + str=str+s.sprintf("%lu,",(long unsigned)nav->eph[i].ttr.time); str=str+s.sprintf("%.14E,",nav->eph[i].A); str=str+s.sprintf("%.14E,",nav->eph[i].e); str=str+s.sprintf("%.14E,",nav->eph[i].i0); @@ -2402,7 +2436,7 @@ void __fastcall TMainForm::SaveNav(nav_t *nav) str=str+s.sprintf("%d,",nav->eph[i].code); str=str+s.sprintf("%d,",nav->eph[i].flag); str=str+s.sprintf("%.14E,",nav->eph[i].tgd[1]); - ini->WriteString("navi",s.sprintf("eph_%02d",i),str); + ini->WriteString("navi",s.sprintf("eph_%03d",i),str); } str=""; for (i=0;i<8;i++) str=str+s.sprintf("%.14E,",nav->ion_gps[i]); @@ -2460,6 +2494,7 @@ void __fastcall TMainForm::LoadOpt(void) } PrcOpt.mode =ini->ReadInteger("prcopt", "mode", 2); PrcOpt.nf =ini->ReadInteger("prcopt", "nf", NFREQ); + if (PrcOpt.nf > NFREQ) PrcOpt.nf = NFREQ; PrcOpt.elmin =ini->ReadFloat ("prcopt", "elmin", 15.0*D2R); PrcOpt.snrmask.ena[0]=ini->ReadInteger("prcopt","snrmask_ena1",0); PrcOpt.snrmask.ena[1]=ini->ReadInteger("prcopt","snrmask_ena2",0); @@ -2509,7 +2544,7 @@ void __fastcall TMainForm::LoadOpt(void) PrcOpt.thresar[4]=ini->ReadFloat ("prcopt", "thresar4", 1E-5); PrcOpt.elmaskar =ini->ReadFloat ("prcopt", "elmaskar", 15.0*D2R); PrcOpt.elmaskhold=ini->ReadFloat ("prcopt", "elmaskhold",15.0*D2R); - PrcOpt.thresdop=ini->ReadFloat ("prcopt", "thresdop", 0.00); + PrcOpt.thresdop=ini->ReadFloat ("prcopt", "thresdop", 0.00); PrcOpt.thresslip=ini->ReadFloat ("prcopt", "thresslip", 0.05); PrcOpt.maxtdiff =ini->ReadFloat ("prcopt", "maxtdiff", 30.0); PrcOpt.maxinno[0]=ini->ReadFloat ("prcopt", "maxphase", 5.0); @@ -2611,14 +2646,18 @@ void __fastcall TMainForm::LoadOpt(void) TrkType2 =ini->ReadInteger("setting","trktype2", 0); TrkType3 =ini->ReadInteger("setting","trktype3", 0); TrkType4 =ini->ReadInteger("setting","trktype4", 0); - TrkScale1 =ini->ReadInteger("setting","trkscale1", 5); - TrkScale2 =ini->ReadInteger("setting","trkscale2", 5); - TrkScale3 =ini->ReadInteger("setting","trkscale3", 5); - TrkScale4 =ini->ReadInteger("setting","trkscale4", 5); + TrkScale1 =ini->ReadInteger("setting","trkscale1", 8); + TrkScale2 =ini->ReadInteger("setting","trkscale2", 8); + TrkScale3 =ini->ReadInteger("setting","trkscale3", 8); + TrkScale4 =ini->ReadInteger("setting","trkscale4", 8); FreqType1 =ini->ReadInteger("setting","freqtype1", 0); FreqType2 =ini->ReadInteger("setting","freqtype2", 0); FreqType3 =ini->ReadInteger("setting","freqtype3", 0); FreqType4 =ini->ReadInteger("setting","freqtype4", 0); + if (FreqType1 > NFREQ + 1) FreqType1 = 0; + if (FreqType2 > NFREQ + 1) FreqType2 = 0; + if (FreqType3 > NFREQ + 1) FreqType3 = 0; + if (FreqType4 > NFREQ + 1) FreqType4 = 0; BLMode1 =ini->ReadInteger("setting","blmode1", 0); BLMode2 =ini->ReadInteger("setting","blmode2", 0); BLMode3 =ini->ReadInteger("setting","blmode3", 0); @@ -2757,6 +2796,9 @@ void __fastcall TMainForm::SaveOpt(void) ini->WriteFloat ("prcopt", "err2", PrcOpt.err[2] ); ini->WriteFloat ("prcopt", "err3", PrcOpt.err[3] ); ini->WriteFloat ("prcopt", "err4", PrcOpt.err[4] ); + ini->WriteFloat ("prcopt", "err5", PrcOpt.err[5] ); + ini->WriteFloat ("prcopt", "err6", PrcOpt.err[6] ); + ini->WriteFloat ("prcopt", "err7", PrcOpt.err[7] ); ini->WriteFloat ("prcopt", "prn0", PrcOpt.prn[0] ); ini->WriteFloat ("prcopt", "prn1", PrcOpt.prn[1] ); ini->WriteFloat ("prcopt", "prn2", PrcOpt.prn[2] ); diff --git a/app/winapp/rtknavi/navimain.dfm b/app/winapp/rtknavi/navimain.dfm index 9911304e4..bf001e3d4 100644 --- a/app/winapp/rtknavi/navimain.dfm +++ b/app/winapp/rtknavi/navimain.dfm @@ -707,7 +707,7 @@ object MainForm: TMainForm B4000000000000000000B4B4B4FFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FF00} - OnClick = BtnExpand2Click + OnClick = BtnExpand3Click end object BtnShrink3: TSpeedButton Left = 1 @@ -735,7 +735,7 @@ object MainForm: TMainForm B4000000000000000000B4B4B4FFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FF00} - OnClick = BtnShrink2Click + OnClick = BtnShrink3Click end end object Panel25: TPanel @@ -833,7 +833,7 @@ object MainForm: TMainForm B4000000000000000000B4B4B4FFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FF00} - OnClick = BtnExpand2Click + OnClick = BtnExpand4Click end object BtnShrink4: TSpeedButton Left = 1 @@ -861,7 +861,7 @@ object MainForm: TMainForm B4000000000000000000B4B4B4FFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FF00} - OnClick = BtnShrink2Click + OnClick = BtnShrink4Click end end end diff --git a/app/winapp/rtknavi/navimain.h b/app/winapp/rtknavi/navimain.h index 4135aa8d2..6e433b124 100644 --- a/app/winapp/rtknavi/navimain.h +++ b/app/winapp/rtknavi/navimain.h @@ -186,6 +186,10 @@ class TMainForm : public TForm void __fastcall BtnShrink1Click(TObject *Sender); void __fastcall BtnExpand2Click(TObject *Sender); void __fastcall BtnShrink2Click(TObject *Sender); + void __fastcall BtnExpand3Click(TObject *Sender); + void __fastcall BtnShrink3Click(TObject *Sender); + void __fastcall BtnExpand4Click(TObject *Sender); + void __fastcall BtnShrink4Click(TObject *Sender); void __fastcall BtnMarkClick(TObject *Sender); void __fastcall Panel24Resize(TObject *Sender); void __fastcall Panel25Resize(TObject *Sender); @@ -250,7 +254,7 @@ class TMainForm : public TForm int MoniPort,OpenPort,AutoRun; int PSol,PSolS,PSolE,Nsat[2],SolCurrentStat; - int Sat[2][MAXSAT],Snr[2][MAXSAT][NFREQ],Vsat[2][MAXSAT]; + int Sat[2][MAXSAT],Snr[2][MAXSAT][NFREQ],Vsat[2][MAXSAT][NFREQ]; double Az[2][MAXSAT],El[2][MAXSAT]; gtime_t *Time; int *SolStat,*Nvsat; diff --git a/app/winapp/rtknavi/naviopt.cpp b/app/winapp/rtknavi/naviopt.cpp index 78fa19289..6522ff358 100644 --- a/app/winapp/rtknavi/naviopt.cpp +++ b/app/winapp/rtknavi/naviopt.cpp @@ -421,7 +421,7 @@ void __fastcall TOptDialog::GetOpt(void) Freq ->ItemIndex=PrcOpt.nf-1>NFREQ-1?NFREQ-1:PrcOpt.nf-1; ElMask ->Text =s.sprintf("%.0f",PrcOpt.elmin*R2D); DynamicModel ->ItemIndex=PrcOpt.dynamics; - TideCorr ->ItemIndex=PrcOpt.tidecorr > 1 ? 2 : PrcOpt.tidecorr; + TideCorr ->ItemIndex=PrcOpt.tidecorr & 7; IonoOpt ->ItemIndex=PrcOpt.ionoopt; TropOpt ->ItemIndex=PrcOpt.tropopt; SatEphem ->ItemIndex=PrcOpt.sateph; @@ -465,6 +465,7 @@ void __fastcall TOptDialog::GetOpt(void) PosOpt3 ->Checked =PrcOpt.posopt[2]; PosOpt4 ->Checked =PrcOpt.posopt[3]; PosOpt5 ->Checked =PrcOpt.posopt[4]; + PosOpt6 ->Checked =PrcOpt.posopt[5]; SolFormat ->ItemIndex=SolOpt.posf; TimeFormat ->ItemIndex=SolOpt.timef==0?0:SolOpt.times+1; @@ -565,8 +566,7 @@ void __fastcall TOptDialog::SetOpt(void) PrcOpt.nf =Freq ->ItemIndex+1; PrcOpt.elmin =str2dbl(ElMask ->Text)*D2R; PrcOpt.dynamics =DynamicModel->ItemIndex; - PrcOpt.tidecorr =TideCorr ->ItemIndex; - if (PrcOpt.tidecorr > 1) PrcOpt.tidecorr = 7; + PrcOpt.tidecorr =TideCorr ->ItemIndex & 7; PrcOpt.ionoopt =IonoOpt ->ItemIndex; PrcOpt.tropopt =TropOpt ->ItemIndex; PrcOpt.sateph =SatEphem ->ItemIndex; @@ -752,7 +752,7 @@ void __fastcall TOptDialog::LoadOpt(AnsiString file) ElMask ->Text =s.sprintf("%.0f",prcopt.elmin*R2D); PrcOpt.snrmask =prcopt.snrmask; DynamicModel ->ItemIndex =prcopt.dynamics; - TideCorr ->ItemIndex =prcopt.tidecorr > 1 ? 2 : prcopt.tidecorr; + TideCorr ->ItemIndex =prcopt.tidecorr & 7; IonoOpt ->ItemIndex =prcopt.ionoopt; TropOpt ->ItemIndex =prcopt.tropopt; SatEphem ->ItemIndex =prcopt.sateph; @@ -994,8 +994,7 @@ void __fastcall TOptDialog::SaveOpt(AnsiString file) prcopt.elmin =str2dbl(ElMask ->Text)*D2R; prcopt.snrmask =PrcOpt.snrmask; prcopt.dynamics =DynamicModel->ItemIndex; - prcopt.tidecorr =TideCorr ->ItemIndex; - if (prcopt.tidecorr > 1) prcopt.tidecorr = 7; + prcopt.tidecorr =TideCorr ->ItemIndex & 7; prcopt.ionoopt =IonoOpt ->ItemIndex; prcopt.tropopt =TropOpt ->ItemIndex; prcopt.sateph =SatEphem ->ItemIndex; diff --git a/app/winapp/rtknavi/naviopt.dfm b/app/winapp/rtknavi/naviopt.dfm index 0be0683e1..68d4c09d4 100644 --- a/app/winapp/rtknavi/naviopt.dfm +++ b/app/winapp/rtknavi/naviopt.dfm @@ -199,7 +199,7 @@ object OptDialog: TOptDialog object DynamicModel: TComboBox Left = 248 Top = 136 - Width = 75 + Width = 45 Height = 21 Style = csDropDownList ItemIndex = 0 @@ -210,9 +210,9 @@ object OptDialog: TOptDialog 'ON') end object TideCorr: TComboBox - Left = 325 + Left = 295 Top = 136 - Width = 75 + Width = 105 Height = 21 Style = csDropDownList ItemIndex = 0 @@ -220,7 +220,13 @@ object OptDialog: TOptDialog Text = 'OFF' Items.Strings = ( 'OFF' - 'Solid') + 'Solid Earth Tide' + 'Ocean Tide Loading' + 'Solid Earth + OTL' + 'Solid Pole' + 'Solid Earth + Pole' + 'OTL + Solid Pole' + 'Solid + OTL + Pole') end object IonoOpt: TComboBox Left = 248 @@ -433,7 +439,7 @@ object OptDialog: TOptDialog Top = 117 Width = 206 Height = 13 - Caption = 'Slip Threshs: Doppler (Hz) / Geom-Free (m)' + Caption = 'Slip Threshs: Doppler (m/s) / Geom-Free (m)' end object Label14: TLabel Left = 24 @@ -602,7 +608,7 @@ object OptDialog: TOptDialog Width = 75 Height = 21 TabOrder = 11 - Text = '0.0' + Text = '0.00' end object SlipThres: TEdit Left = 325 diff --git a/app/winapp/rtknavi/rtknavi.cbproj b/app/winapp/rtknavi/rtknavi.cbproj index c2e876b67..62857f6a5 100644 --- a/app/winapp/rtknavi/rtknavi.cbproj +++ b/app/winapp/rtknavi/rtknavi.cbproj @@ -759,8 +759,6 @@ - - diff --git a/app/winapp/rtkplot/plotdata.cpp b/app/winapp/rtkplot/plotdata.cpp index 3a52ee869..4ce75d864 100644 --- a/app/winapp/rtkplot/plotdata.cpp +++ b/app/winapp/rtkplot/plotdata.cpp @@ -171,7 +171,7 @@ void __fastcall TPlot::ReadObs(TStrings *files) } ClearObs(); Obs=obs; - Nav=*nav; + *Nav=*nav; free(nav); Sta=sta; SimObs=0; @@ -309,18 +309,18 @@ void __fastcall TPlot::ReadNav(TStrings *files) TimeSpan(&ts,&te,&tint); - freenav(&Nav,0xFF); + freenav(Nav,0xFF); ShowMsg("reading nav data..."); Application->ProcessMessages(); for (i=0;iCount;i++) { strcpy(navfile,U2A(files->Strings[i]).c_str()); - readrnxt(navfile,1,ts,te,tint,opt,NULL,&Nav,NULL); + readrnxt(navfile,1,ts,te,tint,opt,NULL,Nav,NULL); } - uniqnav(&Nav); + uniqnav(Nav); - if (Nav.n<=0&&Nav.ng<=0&&Nav.ns<=0) { + if (Nav->n<=0&&Nav->ng<=0&&Nav->ns<=0) { ShowMsg(s.sprintf("no nav message: %s...",files->Strings[0].c_str())); ReadWaitEnd(); return; @@ -1231,7 +1231,7 @@ void __fastcall TPlot::UpdateObs(int nobs) char msg[128]; opt.err[0]=900.0; - pntpos(Obs.data+i,j-i,&Nav,&opt,&sol,azel,NULL,msg); + pntpos(Obs.data+i,j-i,Nav,&opt,&sol,azel,NULL,msg); matcpy(rr,sol.rr,3,1); ecef2pos(rr,pos); } @@ -1253,7 +1253,7 @@ void __fastcall TPlot::UpdateObs(int nobs) if (!tle_pos(time,name,"","",&TLEData,NULL,rs)) continue; } else { - if (!satpos(time,time,sat,EPHOPT_BRDC,&Nav,rs,dts,&var,&svh)) { + if (!satpos(time,time,sat,EPHOPT_BRDC,Nav,rs,dts,&var,&svh)) { continue; } } @@ -1304,10 +1304,10 @@ void __fastcall TPlot::UpdateMp(void) // Choose two frequencies to calculate reference I. double freq1 = 0.0, freq2 = 0.0, I = 0.0; for (int j = 0; j < NFREQ + NEXOBS; j++) { - freq1 = sat2freq(data->sat, data->code[j], &Nav); + freq1 = sat2freq(data->sat, data->code[j], Nav); if (data->L[j] == 0.0 || freq1 == 0.0 ) continue; for (int k = j + 1; k < NFREQ + NEXOBS; k++) { - freq2 = sat2freq(data->sat, data->code[k], &Nav); + freq2 = sat2freq(data->sat, data->code[k], Nav); if (data->L[k] == 0.0 || freq2 == 0.0 || freq1 == freq2) continue; I = -CLIGHT * (data->L[j] / freq1-data->L[k] / freq2) / (1.0 - SQR(freq1 / freq2)); break; @@ -1317,7 +1317,7 @@ void __fastcall TPlot::UpdateMp(void) if (freq1 == 0.0 || freq2 == 0.0) continue; for (int j=0;jsat,data->code[j],&Nav); + double freq=sat2freq(data->sat,data->code[j],Nav); if (data->P[j]==0.0||data->L[j]==0.0||freq==0.0) continue; Mp[j][i]=data->P[j]-CLIGHT*data->L[j]/freq-2.0*SQR(freq1/freq)*I; } @@ -1388,7 +1388,7 @@ void __fastcall TPlot::ClearObs(void) int i; freeobs(&Obs); - freenav(&Nav,0xFF); + freenav(Nav,0xFF); delete [] IndexObs; IndexObs=NULL; delete [] Az; Az=NULL; delete [] El; El=NULL; diff --git a/app/winapp/rtkplot/plotdraw.cpp b/app/winapp/rtkplot/plotdraw.cpp index 30d393b96..57cb4ed1b 100644 --- a/app/winapp/rtkplot/plotdraw.cpp +++ b/app/winapp/rtkplot/plotdraw.cpp @@ -1015,11 +1015,11 @@ void __fastcall TPlot::GenObsSlip(int *LLI) double freq1,freq2,gf; if (!strcmp(obstype,"ALL")) { - if ((freq1=sat2freq(obs->sat,obs->code[0],&Nav))==0.0) continue; + if ((freq1=sat2freq(obs->sat,obs->code[0],Nav))==0.0) continue; LLI[i]=obs->LLI[0]&2; for (j=1;jLLI[j]&2; - if ((freq2=sat2freq(obs->sat,obs->code[j],&Nav))==0.0) continue; + if ((freq2=sat2freq(obs->sat,obs->code[j],Nav))==0.0) continue; gf=CLIGHT*(obs->L[0]/freq1-obs->L[j]/freq2); if (fabs(gfp[obs->sat-1][j]-gf)>THRESLIP) LLI[i]|=1; gfp[obs->sat-1][j]=gf; @@ -1037,8 +1037,8 @@ void __fastcall TPlot::GenObsSlip(int *LLI) } LLI[i]=obs->LLI[j]&2; k=(j==0)?1:0; - if ((freq1=sat2freq(obs->sat,obs->code[k],&Nav))==0.0) continue; - if ((freq2=sat2freq(obs->sat,obs->code[j],&Nav))==0.0) continue; + if ((freq1=sat2freq(obs->sat,obs->code[k],Nav))==0.0) continue; + if ((freq2=sat2freq(obs->sat,obs->code[j],Nav))==0.0) continue; gf=CLIGHT*(obs->L[k]/freq1-obs->L[j]/freq2); if (fabs(gfp[obs->sat-1][j]-gf)>THRESLIP) LLI[i]|=1; gfp[obs->sat-1][j]=gf; @@ -1102,53 +1102,53 @@ void __fastcall TPlot::DrawObsEphem(double *yp) for (i=0;iToPoint(TimePos(Nav.eph[j].ttr),yp[i],ps[0]); - in=GraphR->ToPoint(TimePos(Nav.eph[j].toe),yp[i],ps[2]); + for (j=0;jn;j++) { + if (Nav->eph[j].sat!=i+1) continue; + GraphR->ToPoint(TimePos(Nav->eph[j].ttr),yp[i],ps[0]); + in=GraphR->ToPoint(TimePos(Nav->eph[j].toe),yp[i],ps[2]); ps[1]=ps[0]; - off[Nav.eph[j].sat-1]=off[Nav.eph[j].sat-1]?0:3; + off[Nav->eph[j].sat-1]=off[Nav->eph[j].sat-1]?0:3; - for (k=0;k<3;k++) ps[k].y+=MarkSize+2+off[Nav.eph[j].sat-1]; + for (k=0;k<3;k++) ps[k].y+=MarkSize+2+off[Nav->eph[j].sat-1]; ps[0].y-=2; - svh=Nav.eph[j].svh; + svh=Nav->eph[j].svh; // Mask QZS LEX health. int health = satsys(i + 1, NULL) == SYS_QZS ? (svh & 0xfe) != 0 : svh != 0; GraphR->DrawPoly(ps,3,health?MColor[0][5]:CColor[1],0); if (in) GraphR->DrawMark(ps[2],0,health?MColor[0][5]:CColor[1],health?4:3,0); } - for (j=0;jToPoint(TimePos(Nav.geph[j].tof),yp[i],ps[0]); - in=GraphR->ToPoint(TimePos(Nav.geph[j].toe),yp[i],ps[2]); + for (j=0;jng;j++) { + if (Nav->geph[j].sat!=i+1) continue; + GraphR->ToPoint(TimePos(Nav->geph[j].tof),yp[i],ps[0]); + in=GraphR->ToPoint(TimePos(Nav->geph[j].toe),yp[i],ps[2]); ps[1]=ps[0]; - off[Nav.geph[j].sat-1]=off[Nav.geph[j].sat-1]?0:3; - for (k=0;k<3;k++) ps[k].y+=MarkSize+2+off[Nav.geph[j].sat-1]; + off[Nav->geph[j].sat-1]=off[Nav->geph[j].sat-1]?0:3; + for (k=0;k<3;k++) ps[k].y+=MarkSize+2+off[Nav->geph[j].sat-1]; ps[0].y-=2; - svh=Nav.geph[j].svh; + svh=Nav->geph[j].svh; int health = (svh & 9) != 0 || (svh & 6) == 4; GraphR->DrawPoly(ps,3,health?MColor[0][5]:CColor[1],0); - if (in) GraphR->DrawMark(ps[2],0,Nav.geph[j].svh?MColor[0][5]:CColor[1], - Nav.geph[j].svh?4:3,0); + if (in) GraphR->DrawMark(ps[2],0,Nav->geph[j].svh?MColor[0][5]:CColor[1], + Nav->geph[j].svh?4:3,0); } - for (j=0;jToPoint(TimePos(Nav.seph[j].tof),yp[i],ps[0]); - in=GraphR->ToPoint(TimePos(Nav.seph[j].t0),yp[i],ps[2]); + for (j=0;jns;j++) { + if (Nav->seph[j].sat!=i+1) continue; + GraphR->ToPoint(TimePos(Nav->seph[j].tof),yp[i],ps[0]); + in=GraphR->ToPoint(TimePos(Nav->seph[j].t0),yp[i],ps[2]); ps[1]=ps[0]; - off[Nav.seph[j].sat-1]=off[Nav.seph[j].sat-1]?0:3; - for (k=0;k<3;k++) ps[k].y+=MarkSize+2+off[Nav.seph[j].sat-1]; + off[Nav->seph[j].sat-1]=off[Nav->seph[j].sat-1]?0:3; + for (k=0;k<3;k++) ps[k].y+=MarkSize+2+off[Nav->seph[j].sat-1]; ps[0].y-=2; - svh=Nav.seph[j].svh; + svh=Nav->seph[j].svh; GraphR->DrawPoly(ps,3,svh?MColor[0][5]:CColor[1],0); - if (in) GraphR->DrawMark(ps[2],0,Nav.seph[j].svh?MColor[0][5]:CColor[1], - Nav.seph[j].svh?4:3,0); + if (in) GraphR->DrawMark(ps[2],0,Nav->seph[j].svh?MColor[0][5]:CColor[1], + Nav->seph[j].svh?4:3,0); } } } @@ -1387,7 +1387,7 @@ void __fastcall TPlot::DrawSky(int level) GraphS->DrawText(p2,ustr,col==clBlack?MColor[0][0]:col,2,2,0,MS_FONT); } } - if (Nav.n<=0&&Nav.ng<=0&&!SimObs) { + if (Nav->n<=0&&Nav->ng<=0&&!SimObs) { GraphS->GetPos(p1,p2); p2.x-=10; p2.y-=3; @@ -1667,7 +1667,7 @@ void __fastcall TPlot::DrawDop(int level) else { DrawDopStat(dop,ns,n); } - if (Nav.n<=0&&Nav.ng<=0&&(doptype==0||doptype>=2)&&!SimObs) { + if (Nav->n<=0&&Nav->ng<=0&&(doptype==0||doptype>=2)&&!SimObs) { GraphR->GetPos(p1,p2); p2.x-=10; p2.y-=3; diff --git a/app/winapp/rtkplot/plotinfo.cpp b/app/winapp/rtkplot/plotinfo.cpp index 54255fde0..28be1e407 100644 --- a/app/winapp/rtkplot/plotinfo.cpp +++ b/app/winapp/rtkplot/plotinfo.cpp @@ -333,7 +333,6 @@ static int _strcmp(const void *str1, const void *str2) void __fastcall TPlot::UpdateObsType(void) { UTF8String s; - char *obs,*codes[MAXCODE+1]; int i,j,n=0,cmask[MAXCODE+1]={0},fmask[10]={0}; const char *obstypes[] = {"L1/LC","L2/E5b","L5/E5a","L6","L7","L8"}; @@ -342,9 +341,11 @@ void __fastcall TPlot::UpdateObsType(void) for (i=0;iGetLim(xl,yl); GraphG[0]->ToPoint(x,yl[1],pnt); - - if ((X-pnt.x)*(X-pnt.x)+(Y-pnt.y)*(Y-pnt.y)<25) { + + double dx = X - pnt.x, dy = Y - pnt.y; + if (dx * dx + dy * dy < 5 * 5) { Screen->Cursor=crSizeWE; Drag=20; Refresh(); @@ -1568,7 +1569,8 @@ void __fastcall TPlot::MouseDownObs(int X, int Y) GraphR->GetLim(xl,yl); GraphR->ToPoint(x,yl[1],pnt); - if ((X-pnt.x)*(X-pnt.x)+(Y-pnt.y)*(Y-pnt.y)<25) { + double dx = X - pnt.x, dy = Y - pnt.y; + if (dx * dx + dy * dy < 5 * 5) { Screen->Cursor=crSizeWE; Drag=20; Refresh(); diff --git a/app/winapp/rtkplot/plotmain.h b/app/winapp/rtkplot/plotmain.h index c63f4f2a1..9ab487cf9 100644 --- a/app/winapp/rtkplot/plotmain.h +++ b/app/winapp/rtkplot/plotmain.h @@ -410,7 +410,7 @@ class TPlot : public TForm solstatbuf_t SolStat[2]; int SolIndex[2]; obs_t Obs; - nav_t Nav; + nav_t *Nav; sta_t Sta; double *Az,*El,*Mp[NFREQ+NEXOBS]; char StrBuff[1024]; diff --git a/app/winapp/rtkplot/rtkplot.cbproj b/app/winapp/rtkplot/rtkplot.cbproj index b5b35bb69..d00b039b8 100644 --- a/app/winapp/rtkplot/rtkplot.cbproj +++ b/app/winapp/rtkplot/rtkplot.cbproj @@ -728,7 +728,6 @@ - diff --git a/app/winapp/rtkpost/postmain.cpp b/app/winapp/rtkpost/postmain.cpp index 1feccb1d3..c547818c9 100644 --- a/app/winapp/rtkpost/postmain.cpp +++ b/app/winapp/rtkpost/postmain.cpp @@ -1000,8 +1000,7 @@ int __fastcall TMainForm::GetOption(prcopt_t &prcopt, solopt_t &solopt, prcopt.posopt[4]=PosOpt[4]; prcopt.posopt[5]=PosOpt[5]; prcopt.dynamics =DynamicModel; - prcopt.tidecorr =TideCorr; - if (prcopt.tidecorr > 1) prcopt.tidecorr = 7; + prcopt.tidecorr =TideCorr & 7; prcopt.armaxiter=ARIter; prcopt.niter =NumIter; prcopt.minfixsats=MinFixSats; @@ -1356,6 +1355,7 @@ void __fastcall TMainForm::LoadOpt(void) PosMode =ini->ReadInteger("opt","posmode", 2); Freq =ini->ReadInteger("opt","freq", NFREQ-1); + if (Freq > NFREQ - 1) Freq = NFREQ - 1; Solution =ini->ReadInteger("opt","solution", 0); ElMask =ini->ReadFloat ("opt","elmask", 15.0); SnrMask.ena[0] =ini->ReadInteger("opt","snrmask_ena1", 0); @@ -1396,7 +1396,7 @@ void __fastcall TMainForm::LoadOpt(void) ElMaskHold =ini->ReadFloat ("opt","elmaskhold", 15.0); OutCntResetAmb =ini->ReadInteger("opt","outcntresetbias",20); SlipThres =ini->ReadFloat ("opt","slipthres", 0.05); - DopThres =ini->ReadFloat ("opt","dopthres", 0.0); + DopThres =ini->ReadFloat ("opt","dopthres", 0.00); MaxAgeDiff =ini->ReadFloat ("opt","maxagediff", 30.0); RejectPhase =ini->ReadFloat ("opt","rejectphase", 5.0); VarHoldAmb =ini->ReadFloat ("opt","varholdamb", 0.1); diff --git a/app/winapp/rtkpost/postopt.cpp b/app/winapp/rtkpost/postopt.cpp index eec8cfaa6..2e31c813d 100644 --- a/app/winapp/rtkpost/postopt.cpp +++ b/app/winapp/rtkpost/postopt.cpp @@ -636,7 +636,7 @@ void __fastcall TOptDialog::LoadOpt(AnsiString file) ElMask ->Text =s.sprintf("%.0f",prcopt.elmin*R2D); SnrMask =prcopt.snrmask; DynamicModel ->ItemIndex =prcopt.dynamics; - TideCorr ->ItemIndex =prcopt.tidecorr > 1 ? 2 : prcopt.tidecorr; + TideCorr ->ItemIndex =prcopt.tidecorr & 7; IonoOpt ->ItemIndex =prcopt.ionoopt; TropOpt ->ItemIndex =prcopt.tropopt; SatEphem ->ItemIndex =prcopt.sateph; @@ -797,8 +797,7 @@ int ppp=PosMode->ItemIndex>=PMODE_PPP_KINEMA; prcopt.elmin =str2dbl(ElMask ->Text)*D2R; prcopt.snrmask =SnrMask; prcopt.dynamics =DynamicModel->ItemIndex; - prcopt.tidecorr =TideCorr ->ItemIndex; - if (prcopt.tidecorr > 1) prcopt.tidecorr = 7; + prcopt.tidecorr =TideCorr ->ItemIndex & 7; prcopt.ionoopt =IonoOpt ->ItemIndex; prcopt.tropopt =TropOpt ->ItemIndex; prcopt.sateph =SatEphem ->ItemIndex; diff --git a/app/winapp/rtkpost/postopt.dfm b/app/winapp/rtkpost/postopt.dfm index 14ba9f8aa..4e836dde0 100644 --- a/app/winapp/rtkpost/postopt.dfm +++ b/app/winapp/rtkpost/postopt.dfm @@ -216,7 +216,7 @@ object OptDialog: TOptDialog object DynamicModel: TComboBox Left = 248 Top = 92 - Width = 75 + Width = 45 Height = 21 Style = csDropDownList ItemIndex = 0 @@ -228,9 +228,9 @@ object OptDialog: TOptDialog 'ON') end object TideCorr: TComboBox - Left = 325 + Left = 295 Top = 92 - Width = 75 + Width = 105 Height = 21 Style = csDropDownList ItemIndex = 0 @@ -238,8 +238,13 @@ object OptDialog: TOptDialog Text = 'OFF' Items.Strings = ( 'OFF' - 'Solid' - 'Solid/OTL') + 'Solid Earth Tide' + 'Ocean Tide Loading' + 'Solid Earth + OTL' + 'Solid Pole' + 'Solid Earth + Pole' + 'OTL + Solid Pole' + 'Solid + OTL + Pole') end object IonoOpt: TComboBox Left = 248 @@ -455,7 +460,7 @@ object OptDialog: TOptDialog Top = 117 Width = 206 Height = 13 - Caption = 'Slip Threshs: Doppler (Hz) / Geom-Free (m)' + Caption = 'Slip Threshs: Doppler (m/s) / Geom-Free (m)' end object Label14: TLabel Left = 24 @@ -622,7 +627,7 @@ object OptDialog: TOptDialog Width = 75 Height = 21 TabOrder = 11 - Text = '0.100' + Text = '0.00' end object SlipThres: TEdit Left = 325 diff --git a/app/winapp/srctblbrows/srctblbrows.cbproj b/app/winapp/srctblbrows/srctblbrows.cbproj index 03e56850a..9e57cee70 100644 --- a/app/winapp/srctblbrows/srctblbrows.cbproj +++ b/app/winapp/srctblbrows/srctblbrows.cbproj @@ -503,7 +503,6 @@ - diff --git a/app/winapp/strsvr/strsvr.cbproj b/app/winapp/strsvr/strsvr.cbproj index a871587f8..26f509edc 100644 --- a/app/winapp/strsvr/strsvr.cbproj +++ b/app/winapp/strsvr/strsvr.cbproj @@ -616,7 +616,6 @@ - diff --git a/data/config/f9p_ppk.conf b/data/config/f9p_ppk.conf index 464ad142c..fad29431b 100644 --- a/data/config/f9p_ppk.conf +++ b/data/config/f9p_ppk.conf @@ -1,4 +1,6 @@ -# rtkpost options (2023/07/29 20:37:05, v.demo5 b34h) +# rtkpost options (RTKLIB-EX 7/27/26 and later) +# Optimized for post-processing u-blox F9P receiver in typical conditions for unmatched receivers +# ( for matched receivers set gloarmode=on) pos1-posmode =kinematic # (0:single,1:dgps,2:kinematic,3:static,4:static-start,5:movingbase,6:fixed,7:ppp-kine,8:ppp-static,9:ppp-fixed) pos1-frequency =l1+l2 # (1:l1,2:l1+l2,3:l1+l2+l5,4:l1+l2+l5+l6) @@ -9,8 +11,9 @@ pos1-snrmask_b =off # (0:off,1:on) pos1-snrmask_L1 =35,35,35,35,35,35,35,35,35 pos1-snrmask_L2 =35,35,35,35,35,35,35,35,35 pos1-snrmask_L5 =35,35,35,35,35,35,35,35,35 +pos1-snrmask_L6 =35,35,35,35,35,35,35,35,35 pos1-dynamics =on # (0:off,1:on) -pos1-tidecorr =off # (0:off,1:on,2:otl) +pos1-tidecorr =0 # (1:solid+2:otl+4:spole) pos1-ionoopt =brdc # (0:off,1:brdc,2:sbas,3:dual-freq,4:est-stec,5:ionex-tec,6:qzs-brdc) pos1-tropopt =saas # (0:off,1:saas,2:sbas,3:est-ztd,4:est-ztdgrad) pos1-sateph =brdc # (0:brdc,1:precise,2:brdc+sbas,3:brdc+ssrapc,4:brdc+ssrcom) @@ -38,17 +41,18 @@ pos2-gainholdamb =0.01 pos2-arlockcnt =5 pos2-minfixsats =4 pos2-minholdsats =5 -pos2-mindropsats =10 -pos2-arelmask =25 # (deg) -pos2-arminfix =20 +pos2-mindropsats =5 +pos2-arelmask =20 # (deg) +pos2-arminfix =10 pos2-armaxiter =1 -pos2-elmaskhold =15 # (deg) +pos2-elmaskhold =25 # (deg) pos2-aroutcnt =20 pos2-maxage =30 # (s) pos2-syncsol =off # (0:off,1:on) pos2-slipthres =0.05 # (m) pos2-dopthres =0 # (m) -pos2-rejionno =2 # (m) +pos2-rejionno =2 # (m (DEPRECATED)) +pos2-rejphase =2 # (m) pos2-rejcode =10 # (m) pos2-niter =1 pos2-baselen =0 # (m) @@ -73,6 +77,7 @@ out-outstat =residual # (0:off,1:state,2:residual) stats-eratio1 =300 stats-eratio2 =300 stats-eratio5 =300 +stats-eratio6 =300 stats-errphase =0.005 # (m) stats-errphaseel =0.005 # (m) stats-errphasebl =0 # (m/10km) diff --git a/data/config/f9p_urban.conf b/data/config/f9p_urban.conf new file mode 100644 index 000000000..a58a3f85f --- /dev/null +++ b/data/config/f9p_urban.conf @@ -0,0 +1,131 @@ +# rtkpost options (RTKLIB-EX 7/27/26 and later) +# Optimized for u-blox F9P receiver in real-time urban canyon conditions and validated with UrbanNav Tokyo benchmark + +pos1-posmode =kinematic # (0:single,1:dgps,2:kinematic,3:static,4:static-start,5:movingbase,6:fixed,7:ppp-kine,8:ppp-static,9:ppp-fixed) +pos1-frequency =l1+l2 # (1:l1,2:l1+l2,3:l1+l2+l5,4:l1+l2+l5+l6) +pos1-soltype =forward # (0:forward,1:backward,2:combined,3:combined-nophasereset) +pos1-elmask =15 # (deg) +pos1-snrmask_r =on # (0:off,1:on) +pos1-snrmask_b =off # (0:off,1:on) +pos1-snrmask_L1 =35,35,35,35,35,35,35,35,35 +pos1-snrmask_L2 =35,35,35,35,35,35,35,35,35 +pos1-snrmask_L5 =35,35,35,35,35,35,35,35,35 +pos1-snrmask_L6 =35,35,35,35,35,35,35,35,35 +pos1-dynamics =on # (0:off,1:on) +pos1-tidecorr =0 # (1:solid+2:otl+4:spole) +pos1-ionoopt =brdc # (0:off,1:brdc,2:sbas,3:dual-freq,4:est-stec,5:ionex-tec,6:qzs-brdc) +pos1-tropopt =saas # (0:off,1:saas,2:sbas,3:est-ztd,4:est-ztdgrad) +pos1-sateph =brdc # (0:brdc,1:precise,2:brdc+sbas,3:brdc+ssrapc,4:brdc+ssrcom) +pos1-posopt1 =off # (0:off,1:on) +pos1-posopt2 =off # (0:off,1:on) +pos1-posopt3 =off # (0:off,1:on,2:precise) +pos1-posopt4 =off # (0:off,1:on) +pos1-posopt5 =off # (0:off,1:on) +pos1-posopt6 =off # (0:off,1:on) +pos1-exclsats = # (prn ...) +pos1-navsys =61 # (1:gps+2:sbas+4:glo+8:gal+16:qzs+32:bds+64:navic) +pos2-armode =fix-and-hold # (0:off,1:continuous,2:instantaneous,3:fix-and-hold) +pos2-gloarmode =on # (0:off,1:on,2:autocal,3:fix-and-hold) +pos2-bdsarmode =on # (0:off,1:on) +pos2-arfilter =on # (0:off,1:on) +pos2-arthres =3 +pos2-arthresmin =1.8 +pos2-arthresmax =5 +pos2-arthres1 =0.5 +pos2-arthres2 =0 +pos2-arthres3 =1e-09 +pos2-arthres4 =1e-05 +pos2-varholdamb =0.5 # (cyc^2) +pos2-gainholdamb =0.01 +pos2-arlockcnt =1 +pos2-minfixsats =4 +pos2-minholdsats =5 +pos2-mindropsats =5 +pos2-arelmask =20 # (deg) +pos2-arminfix =10 +pos2-armaxiter =1 +pos2-elmaskhold =30 # (deg) +pos2-aroutcnt =20 +pos2-maxage =30 # (s) +pos2-syncsol =off # (0:off,1:on) +pos2-slipthres =0.05 # (m) +pos2-dopthres =0.4 # (m/s) +pos2-rejionno =1 # (m (DEPRECATED)) +pos2-rejphase =1 # (m) +pos2-rejcode =5 # (m) +pos2-niter =1 +pos2-baselen =0 # (m) +pos2-basesig =0 # (m) +out-solformat =llh # (0:llh,1:xyz,2:enu,3:nmea) +out-outhead =on # (0:off,1:on) +out-outopt =on # (0:off,1:on) +out-outvel =on # (0:off,1:on) +out-timesys =gpst # (0:gpst,1:utc,2:jst) +out-timeform =tow # (0:tow,1:hms) +out-timendec =3 +out-degform =deg # (0:deg,1:dms) +out-fieldsep = +out-outsingle =on # (0:off,1:on) +out-maxsolstd =0 # (m) +out-height =ellipsoidal # (0:ellipsoidal,1:geodetic) +out-geoid =internal # (0:internal,1:egm96,2:egm08_2.5,3:egm08_1,4:gsi2000) +out-solstatic =all # (0:all,1:single) +out-nmeaintv1 =0 # (s) +out-nmeaintv2 =0 # (s) +out-outstat =residual # (0:off,1:state,2:residual) +stats-eratio1 =300 +stats-eratio2 =300 +stats-eratio5 =300 +stats-eratio6 =300 +stats-errphase =0.005 # (m) +stats-errphaseel =0.005 # (m) +stats-errphasebl =0 # (m/10km) +stats-errdoppler =1 # (Hz) +stats-snrmax =52 # (dB.Hz) +stats-errsnr =0.005 # (m) +stats-errrcv =0 # ( ) +stats-stdbias =30 # (m) +stats-stdiono =0.03 # (m) +stats-stdtrop =0.3 # (m) +stats-prnaccelh =0.1 # (m/s^2) +stats-prnaccelv =0.05 # (m/s^2) +stats-prnbias =0.0001 # (m) +stats-prniono =0.001 # (m) +stats-prntrop =0.0001 # (m) +stats-prnpos =0 # (m) +stats-clkstab =5e-12 # (s/s) +ant1-postype =llh # (0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm) +ant1-pos1 =90 # (deg|m) +ant1-pos2 =0 # (deg|m) +ant1-pos3 =-6335367.6285 # (m|m) +ant1-anttype = +ant1-antdele =0 # (m) +ant1-antdeln =0 # (m) +ant1-antdelu =0 # (m) +ant2-postype =rinexhead # (0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm) +ant2-pos1 =0 # (deg|m) +ant2-pos2 =0 # (deg|m) +ant2-pos3 =0 # (m|m) +ant2-anttype =* +ant2-antdele =0 # (m) +ant2-antdeln =0 # (m) +ant2-antdelu =0 # (m) +ant2-maxaveep =1 +ant2-initrst =on # (0:off,1:on) +misc-timeinterp =off # (0:off,1:on) +misc-sbasatsel =0 # (0:all) +misc-rnxopt1 = +misc-rnxopt2 = +misc-pppopt = +file-satantfile = +file-rcvantfile =C:\gps\rtklib_test\benchmarks\UrbanNav_Tokyo\igs20.atx +file-staposfile = +file-geoidfile = +file-ionofile = +file-dcbfile = +file-eopfile = +file-blqfile = +file-tempdir = +file-geexefile = +file-solstatfile = +file-tracefile = diff --git a/data/config/septentrio_urban.conf b/data/config/septentrio_urban.conf new file mode 100644 index 000000000..39e7a85ad --- /dev/null +++ b/data/config/septentrio_urban.conf @@ -0,0 +1,131 @@ +# rtkpost options (RTKLIB-EX 7/27/26 and later) +# Optimized for real-time Septentrio Mosaic receiver in urban canyon conditions and validated with PPC-Dataset benchmark + +pos1-posmode =kinematic # (0:single,1:dgps,2:kinematic,3:static,4:static-start,5:movingbase,6:fixed,7:ppp-kine,8:ppp-static,9:ppp-fixed) +pos1-frequency =l1+l2+l5+l6 # (1:l1,2:l1+l2,3:l1+l2+l5,4:l1+l2+l5+l6) +pos1-soltype =forward # (0:forward,1:backward,2:combined,3:combined-nophasereset) +pos1-elmask =15 # (deg) +pos1-snrmask_r =on # (0:off,1:on) +pos1-snrmask_b =off # (0:off,1:on) +pos1-snrmask_L1 =30,30,30,30,30,30,30,30,30 +pos1-snrmask_L2 =35,35,35,35,35,35,35,35,35 +pos1-snrmask_L5 =35,35,35,35,35,35,35,35,35 +pos1-snrmask_L6 =40,40,40,40,40,40,40,40,40 +pos1-dynamics =on # (0:off,1:on) +pos1-tidecorr =0 # (1:solid+2:otl+4:spole) +pos1-ionoopt =brdc # (0:off,1:brdc,2:sbas,3:dual-freq,4:est-stec,5:ionex-tec,6:qzs-brdc) +pos1-tropopt =saas # (0:off,1:saas,2:sbas,3:est-ztd,4:est-ztdgrad) +pos1-sateph =brdc # (0:brdc,1:precise,2:brdc+sbas,3:brdc+ssrapc,4:brdc+ssrcom) +pos1-posopt1 =off # (0:off,1:on) +pos1-posopt2 =off # (0:off,1:on) +pos1-posopt3 =off # (0:off,1:on,2:precise) +pos1-posopt4 =off # (0:off,1:on) +pos1-posopt5 =off # (0:off,1:on) +pos1-posopt6 =off # (0:off,1:on) +pos1-exclsats = # (prn ...) +pos1-navsys =61 # (1:gps+2:sbas+4:glo+8:gal+16:qzs+32:bds+64:navic) +pos2-armode =fix-and-hold # (0:off,1:continuous,2:instantaneous,3:fix-and-hold) +pos2-gloarmode =off # (0:off,1:on,2:autocal,3:fix-and-hold) +pos2-bdsarmode =on # (0:off,1:on) +pos2-arfilter =on # (0:off,1:on) +pos2-arthres =3 +pos2-arthresmin =1.8 +pos2-arthresmax =5 +pos2-arthres1 =0.5 +pos2-arthres2 =0 +pos2-arthres3 =1e-09 +pos2-arthres4 =1e-05 +pos2-varholdamb =0.5 # (cyc^2) +pos2-gainholdamb =0.01 +pos2-arlockcnt =5 +pos2-minfixsats =4 +pos2-minholdsats =5 +pos2-mindropsats =5 +pos2-arelmask =20 # (deg) +pos2-arminfix =10 +pos2-armaxiter =1 +pos2-elmaskhold =30 # (deg) +pos2-aroutcnt =20 +pos2-maxage =30 # (s) +pos2-syncsol =off # (0:off,1:on) +pos2-slipthres =0.05 # (m) +pos2-dopthres =0.2 # (m/s) +pos2-rejionno =1 # (m (DEPRECATED)) +pos2-rejphase =1 # (m) +pos2-rejcode =10 # (m) +pos2-niter =1 +pos2-baselen =0 # (m) +pos2-basesig =0 # (m) +out-solformat =llh # (0:llh,1:xyz,2:enu,3:nmea) +out-outhead =on # (0:off,1:on) +out-outopt =on # (0:off,1:on) +out-outvel =on # (0:off,1:on) +out-timesys =gpst # (0:gpst,1:utc,2:jst) +out-timeform =tow # (0:tow,1:hms) +out-timendec =3 +out-degform =deg # (0:deg,1:dms) +out-fieldsep = +out-outsingle =on # (0:off,1:on) +out-maxsolstd =0 # (m) +out-height =ellipsoidal # (0:ellipsoidal,1:geodetic) +out-geoid =internal # (0:internal,1:egm96,2:egm08_2.5,3:egm08_1,4:gsi2000) +out-solstatic =all # (0:all,1:single) +out-nmeaintv1 =0 # (s) +out-nmeaintv2 =0 # (s) +out-outstat =residual # (0:off,1:state,2:residual) +stats-eratio1 =300 +stats-eratio2 =300 +stats-eratio5 =300 +stats-eratio6 =300 +stats-errphase =0.005 # (m) +stats-errphaseel =0.005 # (m) +stats-errphasebl =0 # (m/10km) +stats-errdoppler =1 # (Hz) +stats-snrmax =52 # (dB.Hz) +stats-errsnr =0.005 # (m) +stats-errrcv =0 # ( ) +stats-stdbias =30 # (m) +stats-stdiono =0.03 # (m) +stats-stdtrop =0.3 # (m) +stats-prnaccelh =0.1 # (m/s^2) +stats-prnaccelv =0.05 # (m/s^2) +stats-prnbias =0.0001 # (m) +stats-prniono =0.001 # (m) +stats-prntrop =0.0001 # (m) +stats-prnpos =0 # (m) +stats-clkstab =5e-12 # (s/s) +ant1-postype =llh # (0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm) +ant1-pos1 =90 # (deg|m) +ant1-pos2 =0 # (deg|m) +ant1-pos3 =-6335367.6285 # (m|m) +ant1-anttype = +ant1-antdele =0 # (m) +ant1-antdeln =0 # (m) +ant1-antdelu =0 # (m) +ant2-postype =rinexhead # (0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm) +ant2-pos1 =0 # (deg|m) +ant2-pos2 =0 # (deg|m) +ant2-pos3 =0 # (m|m) +ant2-anttype =* +ant2-antdele =0 # (m) +ant2-antdeln =0 # (m) +ant2-antdelu =0 # (m) +ant2-maxaveep =1 +ant2-initrst =on # (0:off,1:on) +misc-timeinterp =off # (0:off,1:on) +misc-sbasatsel =0 # (0:all) +misc-rnxopt1 = +misc-rnxopt2 = +misc-pppopt = +file-satantfile = +file-rcvantfile =C:\gps\data\benchmarks\UrbanNav_Tokyo\igs20.atx +file-staposfile = +file-geoidfile = +file-ionofile = +file-dcbfile = +file-eopfile = +file-blqfile = +file-tempdir = +file-geexefile = +file-solstatfile = +file-tracefile = diff --git a/data/config/trimble_urban.conf b/data/config/trimble_urban.conf new file mode 100644 index 000000000..4cce9cc03 --- /dev/null +++ b/data/config/trimble_urban.conf @@ -0,0 +1,131 @@ +# rtkpost options (RTKLIB-EX 7/27/26 and later) +# Optimized for real-time Trimble NetR9 receiver in urban canyon conditions and validated with UrbanNav Tokyo benchmark data + +pos1-posmode =kinematic # (0:single,1:dgps,2:kinematic,3:static,4:static-start,5:movingbase,6:fixed,7:ppp-kine,8:ppp-static,9:ppp-fixed) +pos1-frequency =l1+l2+l5 # (1:l1,2:l1+l2,3:l1+l2+l5,4:l1+l2+l5+l6) +pos1-soltype =forward # (0:forward,1:backward,2:combined,3:combined-nophasereset) +pos1-elmask =15 # (deg) +pos1-snrmask_r =on # (0:off,1:on) +pos1-snrmask_b =off # (0:off,1:on) +pos1-snrmask_L1 =30,30,30,30,30,30,30,30,30 +pos1-snrmask_L2 =30,30,30,30,30,30,30,30,30 +pos1-snrmask_L5 =35,35,35,35,35,35,35,35,35 +pos1-snrmask_L6 =35,35,35,35,35,35,35,35,35 +pos1-dynamics =on # (0:off,1:on) +pos1-tidecorr =0 # (1:solid+2:otl+4:spole) +pos1-ionoopt =brdc # (0:off,1:brdc,2:sbas,3:dual-freq,4:est-stec,5:ionex-tec,6:qzs-brdc) +pos1-tropopt =saas # (0:off,1:saas,2:sbas,3:est-ztd,4:est-ztdgrad) +pos1-sateph =brdc # (0:brdc,1:precise,2:brdc+sbas,3:brdc+ssrapc,4:brdc+ssrcom) +pos1-posopt1 =off # (0:off,1:on) +pos1-posopt2 =off # (0:off,1:on) +pos1-posopt3 =off # (0:off,1:on,2:precise) +pos1-posopt4 =off # (0:off,1:on) +pos1-posopt5 =off # (0:off,1:on) +pos1-posopt6 =off # (0:off,1:on) +pos1-exclsats = # (prn ...) +pos1-navsys =61 # (1:gps+2:sbas+4:glo+8:gal+16:qzs+32:bds+64:navic) +pos2-armode =fix-and-hold # (0:off,1:continuous,2:instantaneous,3:fix-and-hold) +pos2-gloarmode =on # (0:off,1:on,2:autocal,3:fix-and-hold) +pos2-bdsarmode =on # (0:off,1:on) +pos2-arfilter =on # (0:off,1:on) +pos2-arthres =3 +pos2-arthresmin =1.8 +pos2-arthresmax =5 +pos2-arthres1 =0.5 +pos2-arthres2 =0 +pos2-arthres3 =1e-09 +pos2-arthres4 =1e-05 +pos2-varholdamb =0.5 # (cyc^2) +pos2-gainholdamb =0.01 +pos2-arlockcnt =2 +pos2-minfixsats =4 +pos2-minholdsats =5 +pos2-mindropsats =5 +pos2-arelmask =20 # (deg) +pos2-arminfix =10 +pos2-armaxiter =1 +pos2-elmaskhold =30 # (deg) +pos2-aroutcnt =20 +pos2-maxage =30 # (s) +pos2-syncsol =off # (0:off,1:on) +pos2-slipthres =0.05 # (m) +pos2-dopthres =0.4 # (m/s) +pos2-rejionno =0.5 # (m (DEPRECATED)) +pos2-rejphase =0.5 # (m) +pos2-rejcode =5 # (m) +pos2-niter =1 +pos2-baselen =0 # (m) +pos2-basesig =0 # (m) +out-solformat =llh # (0:llh,1:xyz,2:enu,3:nmea) +out-outhead =on # (0:off,1:on) +out-outopt =on # (0:off,1:on) +out-outvel =on # (0:off,1:on) +out-timesys =gpst # (0:gpst,1:utc,2:jst) +out-timeform =tow # (0:tow,1:hms) +out-timendec =3 +out-degform =deg # (0:deg,1:dms) +out-fieldsep = +out-outsingle =on # (0:off,1:on) +out-maxsolstd =0 # (m) +out-height =ellipsoidal # (0:ellipsoidal,1:geodetic) +out-geoid =internal # (0:internal,1:egm96,2:egm08_2.5,3:egm08_1,4:gsi2000) +out-solstatic =all # (0:all,1:single) +out-nmeaintv1 =0 # (s) +out-nmeaintv2 =0 # (s) +out-outstat =residual # (0:off,1:state,2:residual) +stats-eratio1 =300 +stats-eratio2 =300 +stats-eratio5 =300 +stats-eratio6 =300 +stats-errphase =0.005 # (m) +stats-errphaseel =0.005 # (m) +stats-errphasebl =0 # (m/10km) +stats-errdoppler =1 # (Hz) +stats-snrmax =52 # (dB.Hz) +stats-errsnr =0.005 # (m) +stats-errrcv =0 # ( ) +stats-stdbias =30 # (m) +stats-stdiono =0.03 # (m) +stats-stdtrop =0.3 # (m) +stats-prnaccelh =0.1 # (m/s^2) +stats-prnaccelv =0.05 # (m/s^2) +stats-prnbias =0.0001 # (m) +stats-prniono =0.001 # (m) +stats-prntrop =0.0001 # (m) +stats-prnpos =0 # (m) +stats-clkstab =5e-12 # (s/s) +ant1-postype =llh # (0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm) +ant1-pos1 =90 # (deg|m) +ant1-pos2 =0 # (deg|m) +ant1-pos3 =-6335367.6285 # (m|m) +ant1-anttype = +ant1-antdele =0 # (m) +ant1-antdeln =0 # (m) +ant1-antdelu =0 # (m) +ant2-postype =rinexhead # (0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm) +ant2-pos1 =0 # (deg|m) +ant2-pos2 =0 # (deg|m) +ant2-pos3 =0 # (m|m) +ant2-anttype =* +ant2-antdele =0 # (m) +ant2-antdeln =0 # (m) +ant2-antdelu =0 # (m) +ant2-maxaveep =1 +ant2-initrst =on # (0:off,1:on) +misc-timeinterp =off # (0:off,1:on) +misc-sbasatsel =0 # (0:all) +misc-rnxopt1 = +misc-rnxopt2 = +misc-pppopt = +file-satantfile = +file-rcvantfile =C:\gps\rtklib_test\benchmarks\UrbanNav_Tokyo\igs20.atx +file-staposfile = +file-geoidfile = +file-ionofile = +file-dcbfile = +file-eopfile = +file-blqfile = +file-tempdir = +file-geexefile = +file-solstatfile = +file-tracefile = diff --git a/readme.txt b/readme.txt index 6785bdd2b..497533fcd 100644 --- a/readme.txt +++ b/readme.txt @@ -59,5 +59,26 @@ Pre-complied linux packages are available at https://build.opensuse.org/package/ The last step will copy the compiled executables into a new directory RTKLIB_bin next to the rtklib source directory. +BENCHMARKS: +For evaluation and comparison purposes, config files (septentrio_urban.conf, f9p_urban.conf, trimble_urban.conf) are included in the data/config folder for real-time compatible solutions for the PPC-Dataset and UrbanNav Tokyo benchmarks. Both benchmark datasets are available on Github. Results with the latest code as of 8/24/26 using the PPC_Dataset offficial scoring for both benchmarks are: + +Results: PPC-Dataset + nagoya run1: 82.2% + nagoya run2: 68.3% + nagoya run3: 93.6% + tokyo run1: 84.8% + tokyo run2: 94.4% + tokyo run3: 93.3% + Overall score: 88.0% + +Results: UrbanNav Tokyo + F9P Odaiba: 83.6% + F9P Shinjuku: 67.5% + Trimble Odaiba: 81.8% + Trimble Shinjuku: 72.1% + Overall score: 75.7% + +For more information on running the benchmarks, see https://rtklibexplorer.wordpress.com/2026/07/09/benchmarking-rtk-solutions-with-the-ppc-dataset/ +For more typical, post-processed, less severe RTK conditions, the f9p_ppk.conf config file in the same folder is recommended. The CRX2RNX utility needs to be available in the search path for the decompression of CRX compressed RINEX files. For Linux the 'CRX2RNX' command needs to be renamed to 'crx2rnx'. This utility is available at https://terras.gsi.go.jp/ja/crx2rnx.html. diff --git a/src/convrnx.c b/src/convrnx.c index 958821a7c..696666e69 100644 --- a/src/convrnx.c +++ b/src/convrnx.c @@ -395,7 +395,8 @@ static void setopt_obstype(const uint8_t *codes, const uint8_t *types, int sys, rnxopt_t *opt) { const char type_str[]="CLDS"; - char type[16],*id,ver; + const char *id; + char type[16],ver; int i,j,k,idx; trace(3,"setopt_obstype: sys=%d\n",sys); diff --git a/src/ephemeris.c b/src/ephemeris.c index 56c8e6ea4..391f45c75 100644 --- a/src/ephemeris.c +++ b/src/ephemeris.c @@ -453,10 +453,6 @@ static eph_t *seleph(gtime_t time, int sat, int iode, const nav_t *nav) if (iode>=0&&nav->eph[i].iode!=iode) continue; if (sys==SYS_GAL) { sel=getseleph(SYS_GAL); - /* this code is from 2.4.3 b34 but does not seem to be fully supported, - so for now I have dropped back to the b33 code */ - /* if (sel==0&&!(nav->eph[i].code&(1<<9))) continue; */ /* I/NAV */ - /*if (sel==1&&!(nav->eph[i].code&(1<<8))) continue; */ /* F/NAV */ if (sel==1&&!(nav->eph[i].code&(1<<9))) continue; /* I/NAV */ if (sel==2&&!(nav->eph[i].code&(1<<8))) continue; /* F/NAV */ if (timediff(nav->eph[i].toe,time)>=0.0) continue; /* AOD<=0 */ @@ -470,7 +466,7 @@ static eph_t *seleph(gtime_t time, int sat, int iode, const nav_t *nav) sat,iode); return NULL; } - trace(4,"seleph: sat=%d dt=%.0f\n",sat,tmin); + trace(4,"seleph: sat=%d dt=%.0f j=%d iode=%d, sel=%d\n",sat,tmin,j,nav->eph[j].iode, sel); return nav->eph+j; } /* select glonass ephemeris --------------------------------------------------*/ @@ -808,8 +804,13 @@ extern void satposs(gtime_t teph, const obsd_t *obs, int n, const nav_t *nav, time[i]=timeadd(obs[i].time,-pr/CLIGHT); /* satellite clock offset from precise products or broadcast ephemeris */ - if (ephopt==EPHOPT_PREC&&nav->nc>0) { - if(!pephclk(time[i],obs[i].sat,nav,&dt,NULL)) { + + // Note: this uses as input the estimated satellite clock time without + // correction but the precise clock corrections are wrt GPST. The + // satellite clock drift over this small period is considered + // negligible to the clock offset lookup here. + if (ephopt == EPHOPT_PREC) { + if (!pephclk(time[i], obs[i].sat, nav, &dt, NULL)) { trace(3,"no precise clock %s sat=%2d\n",time2str(time[i],tstr,3),obs[i].sat); continue; } diff --git a/src/ionex.c b/src/ionex.c index d4cd62385..c5555e139 100644 --- a/src/ionex.c +++ b/src/ionex.c @@ -19,7 +19,9 @@ #include "rtklib.h" #define SQR(x) ((x)*(x)) +#define MIN(x,y) ((x)<=(y)?(x):(y)) #define VAR_NOTEC SQR(30.0) /* variance of no tec */ +#define VAR_SSR_VTEC SQR(10.0); /* variance of SSR VTEC */ #define MIN_EL 0.0 /* min elevation angle (rad) */ #define MIN_HGT -1000.0 /* min user height (m) */ @@ -479,6 +481,87 @@ extern int iontec(gtime_t time, const nav_t *nav, const double *pos, *delay=dels[1]; *var =vars[1]; } - trace(3,"iontec : delay=%5.2f std=%5.2f\n",*delay,sqrt(*var)); + trace(4,"iontec : delay=%5.2f std=%5.2f\n",*delay,sqrt(*var)); + return 1; +} +/* ionosphere model (VTEC spherical harmonics) --------------------------------- +* compute ionospheric delay by VTEC spherical harmonics (RTCM SSR MT1264) +* args : gtime_t time I time (GPST) +* nav_t *nav I navigation data (vtec coefficients) +* double *pos I receiver position {lat,lon,h} (rad,rad,m) +* double *azel I azimuth/elevation {az,el} (rad) +* double freq I signal frequency (Hz) +* double *delay O ionospheric delay (m) +* double *var O ionospheric delay variance (m^2) +* return : status (1:ok, 0:error) +* notes : delay is positive for code (L1 scale), i.e. corrected = meas - delay +*-----------------------------------------------------------------------------*/ +extern int ionvtec(gtime_t time, const nav_t *nav, const double *pos, + const double *azel, double freq, double *delay, double *var) +{ + const double re=6371.0; /* fallback single-layer height (km) */ + double pppos[2],fs,vtec,P[17][17],cosl[17],sinl[17]; + double sinp,cosp,x; + int i,j,k,nmax,mmax; + char tstr[40]; + + trace(4,"ionvtec: time=%s pos=%.3f %.3f azel=%.3f %.3f\n", + time2str(time,tstr,0),pos[0]*R2D,pos[1]*R2D,azel[0]*R2D,azel[1]*R2D); + + *delay=*var=0.0; + + if (nav->vtec.nlay<=0) { + trace(2,"ionvtec: no vtec data\n"); + return 0; + } + if (pos[2]vtec.nlay;i++) { + /* ionospheric pierce point position */ + ionppp(pos,azel,re,nav->vtec.hgt[i],pppos); + + nmax=nav->vtec.nmax[i]; + mmax=nav->vtec.mmax[i]; + sinp=sin(pppos[0]); + cosp=cos(pppos[0]); + + /* fully normalized associated Legendre polynomials */ + P[0][0]=1.0; + for (j=1;j<=nmax;j++) { + /* diagonal term */ + P[j][j]=sqrt((2*j+1)/(2.0*j))*cosp*P[j-1][j-1]; + /* one above diagonal */ + P[j][j-1]=sqrt(2*j+1)*sinp*P[j-1][j-1]; + } + for (j=2;j<=nmax;j++) { + for (k=0;k<=j-2;k++) { + P[j][k]=sqrt((2*j+1)*(2*j-1)/((double)(j-k)*(j+k)))*sinp*P[j-1][k] + -sqrt((2*j+1)*(j+k-1)*(j-k-1)/((double)(j-k)*(j+k)*(2*j-3)))*P[j-2][k]; + } + } + /* cosine and sine of longitude multiples */ + cosl[0]=1.0; sinl[0]=0.0; + for (j=1;j<=mmax;j++) { + cosl[j]=cos(j*pppos[1]); + sinl[j]=sin(j*pppos[1]); + } + /* evaluate spherical harmonic expansion (TECU) */ + x=0.0; + for (j=0;j<=nmax;j++) { + x+=nav->vtec.cosC[i][j][0]*P[j][0]; + for (k=1;k<=MIN(j,mmax);k++) { + x+=nav->vtec.cosC[i][j][k]*P[j][k]*cosl[k]+ + nav->vtec.sinC[i][j][k]*P[j][k]*sinl[k]; + } + } + vtec+=x; + } + /* convert TECU to metres on L1, then scale to signal frequency */ + fs=ionmapf(pos,azel); /* mapping function */ + *delay=40.3E16/SQR(FREQL1)*vtec*SQR(FREQL1/freq)*fs; + *var=VAR_SSR_VTEC; /* use fixed variance for now */ + trace(4,"ionvtec: pppos=%.3f %.3f vtec=%.1f delay=%.3f var=%.2f, freq=%.1f\n", + pppos[0]*R2D,pppos[1]*R2D,vtec,*delay,*var,freq); return 1; } diff --git a/src/options.c b/src/options.c index 2204e07f3..2da409536 100644 --- a/src/options.c +++ b/src/options.c @@ -114,7 +114,7 @@ EXPORT opt_t sysopts[]={ {"pos2-maxage", 1, (void *)&prcopt_.maxtdiff, "s" }, {"pos2-syncsol", 3, (void *)&prcopt_.syncsol, SWTOPT }, {"pos2-slipthres", 1, (void *)&prcopt_.thresslip, "m" }, - {"pos2-dopthres", 1, (void *)&prcopt_.thresdop, "m" }, + {"pos2-dopthres", 1, (void *)&prcopt_.thresdop, "m/s" }, {"pos2-rejionno", 1, (void *)&prcopt_.maxinno[0], "m (DEPRECATED)"}, {"pos2-rejphase", 1, (void *)&prcopt_.maxinno[0], "m" }, {"pos2-rejcode", 1, (void *)&prcopt_.maxinno[1], "m" }, diff --git a/src/postpos.c b/src/postpos.c index df10c05b5..41e210ebd 100644 --- a/src/postpos.c +++ b/src/postpos.c @@ -1077,7 +1077,7 @@ static int execses(gtime_t ts, gtime_t te, double ti, const prcopt_t *popt, if (*fopt->eop) { free(navs.erp.data); navs.erp.data=NULL; navs.erp.n=navs.erp.nmax=0; reppath(fopt->eop,path,ts,"",""); - if (!readerp(path,&navs.erp)) { + if (readerp(path,&navs.erp) == 0) { showmsg("error : no erp data %s",path); trace(2,"no erp data %s\n",path); } diff --git a/src/ppp.c b/src/ppp.c index 81d813db0..b04cd1825 100644 --- a/src/ppp.c +++ b/src/ppp.c @@ -124,7 +124,7 @@ static double STD(rtk_t *rtk, int i) return SQRT(rtk->P[i+i*rtk->nx]); } /* write solution status for PPP ---------------------------------------------*/ -extern int pppoutstat(rtk_t *rtk, char *buff) +extern int pppoutstat(rtk_t *rtk, char *buff, int level) { ssat_t *ssat; double tow,pos[3],vel[3],acc[3],*x; @@ -184,17 +184,23 @@ extern int pppoutstat(rtk_t *rtk, char *buff) rtk->ssat[i].azel[1]*R2D,x[j],STD(rtk,j)); } } -#ifdef OUTSTAT_AMB - /* ambiguity parameters */ - int k; - for (i=0;iopt);j++) { - k=IB(i+1,j,&rtk->opt); - if (rtk->x[k]==0.0) continue; + if (level <= 1) return (int)(p-buff); + + /* Write residuals and status */ + for (int i=0;issat+i; + if (!ssat->vs) continue; satno2id(i+1,id); - p+=sprintf(p,"$AMB,%d,%.3f,%d,%s,%d,%.4f,%.4f\n",week,tow, - rtk->sol.stat,id,j+1,x[k],STD(rtk,k)); + for (int j=0;jopt);j++) { + int k=IB(i+1,j,&rtk->opt); + p+=sprintf(p,"$SAT,%d,%.3f,%s,%d,%.1f,%.1f,%.4f,%.4f,%d,%.0f,%d,%d,%d,%u,%u,%u,%.2f,%.6f,%.5f\n", + week,tow,id,j+1,ssat->azel[0]*R2D,ssat->azel[1]*R2D, + ssat->resp[j],ssat->resc[j],ssat->vsat[j],ssat->snr_rover[j], + ssat->fix[j],ssat->slip[j]&(LLI_SLIP|LLI_HALFC),ssat->lock[j],ssat->outc[j], + ssat->slipc[j],ssat->rejc[j],knx?rtk->x[k]:0, + knx?rtk->P[k+k*rtk->nx]:0,ssat->icbias[j]); + } } -#endif return (int)(p-buff); } /* exclude meas of eclipsing satellite (block IIA) ---------------------------*/ @@ -382,28 +388,27 @@ static inline void initx(rtk_t *rtk, double xi, double var, int i) rtk->P[i+i*rtk->nx]=var; } /* geometry-free phase measurement -------------------------------------------*/ -static double gfmeas(const obsd_t *obs, const nav_t *nav) +static double gfmeas(const obsd_t *obs, const nav_t *nav, int f2) { double freq1,freq2; freq1=sat2freq(obs->sat,obs->code[0],nav); - freq2=sat2freq(obs->sat,obs->code[1],nav); - if (freq1==0.0||freq2==0.0||obs->L[0]==0.0||obs->L[1]==0.0) return 0.0; - return (obs->L[0]/freq1-obs->L[1]/freq2)*CLIGHT; + freq2=sat2freq(obs->sat,obs->code[f2],nav); + if (freq1==0.0||freq2==0.0||obs->L[0]==0.0||obs->L[f2]==0.0) return 0.0; + return (obs->L[0]/freq1-obs->L[f2]/freq2)*CLIGHT; } /* Melbourne-Wubbena linear combination --------------------------------------*/ -static double mwmeas(const obsd_t *obs, const nav_t *nav) +static double mwmeas(const obsd_t *obs, const nav_t *nav, int f2) { double freq1,freq2; freq1=sat2freq(obs->sat,obs->code[0],nav); - freq2=sat2freq(obs->sat,obs->code[1],nav); + freq2=sat2freq(obs->sat,obs->code[f2],nav); - if (freq1==0.0||freq2==0.0||obs->L[0]==0.0||obs->L[1]==0.0|| - obs->P[0]==0.0||obs->P[1]==0.0) return 0.0; - trace(3,"mwmeas: %12.1f %12.1f %15.3f %15.3f %15.3f %15.3f %d %d\n",freq1,freq2,obs->L[0],obs->L[1],obs->P[0],obs->P[1],obs->code[0],obs->code[1]); - return (obs->L[0]-obs->L[1])*CLIGHT/(freq1-freq2)- - (freq1*obs->P[0]+freq2*obs->P[1])/(freq1+freq2); + if (freq1==0.0||freq2==0.0||obs->L[0]==0.0||obs->L[f2]==0.0|| + obs->P[0]==0.0||obs->P[f2]==0.0) return 0.0; + return (obs->L[0]-obs->L[f2])*CLIGHT/(freq1-freq2)- + (freq1*obs->P[0]+freq2*obs->P[f2])/(freq1+freq2); } /* antenna corrected measurements --------------------------------------------*/ static void corr_meas(const obsd_t *obs, const nav_t *nav, const double *azel, @@ -426,18 +431,11 @@ static void corr_meas(const obsd_t *obs, const nav_t *nav, const double *azel, P[i]=obs->P[i] -dants[i]-dantr[i]; double P_nobias = P[i]; if (opt->sateph==EPHOPT_SSRAPC||opt->sateph==EPHOPT_SSRCOM) { - /* select SSR code correction based on code */ - if (sys==SYS_GPS) - ix=(i==0?CODE_L1W-1:CODE_L2W-1); - else if (sys==SYS_GLO) - ix=(i==0?CODE_L1P-1:CODE_L2P-1); - else if (sys==SYS_GAL) - ix=(i==0?CODE_L1X-1:CODE_L7X-1); /* apply SSR correction */ - P[i]+=(nav->ssr[obs->sat-1].cbias[obs->code[i]-1]-nav->ssr[obs->sat-1].cbias[ix]); + P[i]-=nav->ssr[obs->sat-1].cbias[obs->code[i]-1]; } else { /* apply code bias corrections from file */ - P[i]-=code2bias(nav,sys,obs->sat,obs->code[i],0); /* differential bias*/ + P[i]-=code2bias(nav,sys,obs->sat,obs->code[i],1); /* absolute bias*/ } trace(4,"sys=%d sat=%d frq=%d, P: %.3f->%.3f, dt=%.3f\n",sys,obs->sat,i,P_nobias,P[i],(P[i]-P_nobias)/(1E-9*CLIGHT)); } @@ -450,6 +448,7 @@ static void corr_meas(const obsd_t *obs, const nav_t *nav, const double *azel, if (L[0]!=0.0&&L[frq2]!=0.0) *Lc=C1*L[0]+C2*L[frq2]; if (P[0]!=0.0&&P[frq2]!=0.0) *Pc=C1*P[0]+C2*P[frq2]; + trace(4,"corr_meas: sat=%d f2=%d, Lc=%.3f Pc=%.3f\n",obs->sat,frq2,*Lc,*Pc); } /* detect cycle slip by LLI --------------------------------------------------*/ static void detslp_ll(rtk_t *rtk, const obsd_t *obs, int n) @@ -470,49 +469,57 @@ static void detslp_ll(rtk_t *rtk, const obsd_t *obs, int n) /* detect cycle slip by geometry free phase jump -----------------------------*/ static void detslp_gf(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav) { - double g0,g1; - int i,j; + double gf0,gf1; + int i,k,sat; trace(4,"detslp_gf: n=%d\n",n); + if (rtk->opt.thresslip==0) return; /* return if check disabled */ for (i=0;issat[obs[i].sat-1].gf[0]; - rtk->ssat[obs[i].sat-1].gf[0]=g1; - - trace(4,"detslip_gf: sat=%2d gf0=%8.3f gf1=%8.3f\n",obs[i].sat,g0,g1); - - if (g0!=0.0&&fabs(g1-g0)>rtk->opt.thresslip) { - trace(3,"detslip_gf: slip detected sat=%2d gf=%8.3f->%8.3f\n", - obs[i].sat,g0,g1); - - for (j=0;jopt.nf;j++) rtk->ssat[obs[i].sat-1].slip[j]|=LLI_SLIP; + sat=obs[i].sat; + for (k=1;kopt.nf;k++) { + /* skip check if slip already detected */ + if (rtk->ssat[sat-1].slip[k]&LLI_SLIP) continue; + /* calc SD geomotry free LC of phase between freq0 and freqk */ + if ((gf1=gfmeas(obs+i,nav,k))==0.0) continue; + + gf0=rtk->ssat[sat-1].gf[k-1]; /* retrieve previous gf */ + rtk->ssat[sat-1].gf[k-1]=gf1; /* save current gf for next epoch */ + + if (gf0!=0.0&&fabs(gf1-gf0)>rtk->opt.thresslip) { + rtk->ssat[sat-1].slip[0]|=LLI_SLIP; + rtk->ssat[sat-1].slip[k]|=LLI_SLIP; + trace(3,"slip detected GF jump (sat=%2d L1-L%d dGF=%.3f)\n", + sat,k+1,gf0-gf1); + } } } } /* detect slip by Melbourne-Wubbena linear combination jump ------------------*/ static void detslp_mw(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav) { - double w0,w1; - int i,j; + double mw0,mw1; + int i,j,k,sat; trace(4,"detslp_mw: n=%d\n",n); for (i=0;issat[obs[i].sat-1].mw[0]; - rtk->ssat[obs[i].sat-1].mw[0]=w1; - - trace(4,"detslip_mw: sat=%2d mw0=%8.3f mw1=%8.3f\n",obs[i].sat,w0,w1); - - if (w0!=0.0&&fabs(w1-w0)>THRES_MW_JUMP) { - trace(3,"detslip_mw: slip detected sat=%2d mw=%8.3f->%8.3f\n", - obs[i].sat,w0,w1); - - for (j=0;jopt.nf;j++) rtk->ssat[obs[i].sat-1].slip[j]|=LLI_SLIP; + sat=obs[i].sat; + for (k=1;kopt.nf;k++) { + /* skip check if slip already detected */ + if (rtk->ssat[sat-1].slip[k]&LLI_SLIP) continue; + /* calc MW LC of phase between freq0 and freqk */ + if ((mw1=mwmeas(obs+i,nav,k))==0.0) continue; + + mw0=rtk->ssat[sat-1].mw[k-1]; /* retrieve previous mw */ + rtk->ssat[sat-1].mw[k-1]=mw1; /* save current mw for next epoch */ + + if (mw0!=0.0&&fabs(mw1-mw0)>THRES_MW_JUMP) { + rtk->ssat[sat-1].slip[0]|=LLI_SLIP; + rtk->ssat[sat-1].slip[k]|=LLI_SLIP; + trace(3,"slip detected MW jump (sat=%2d L1-L%d dMW=%.3f)\n", + sat,k+1,mw0-mw1); + } } } } @@ -659,7 +666,7 @@ static void udtrop_ppp(rtk_t *rtk) /* temporal update of ionospheric parameters ---------------------------------*/ static void udiono_ppp(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav) { - double freq1,freq2,ion,sinel,pos[3],*azel; + double freq1,freq2,ion,sinel,pos[3],*azel,var=VAR_IONO; char *p; int i,j,f2,gap_resion=GAP_RESION,sat; @@ -675,27 +682,56 @@ static void udiono_ppp(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav) rtk->x[j]=0.0; } } + /* reset ionosphere states if VTEC corrections just became available */ + if (rtk->vtec_used==0&&nav->vtec.nlay>0) { + for (i=0;ix[II(i+1,&rtk->opt)]=0.0; + } + rtk->vtec_used=1; // indicate that vtec coeffs have been used + } for (i=0;iopt); - if (rtk->x[j]==0.0) { + if (rtk->x[j]==0.0&&(int)rtk->ssat[i].outc[0]<=gap_resion) { /* initialize ionosphere delay estimates if zero */ + ecef2pos(rtk->sol.rr,pos); + azel=rtk->ssat[sat-1].azel; f2=seliflc(rtk->opt.nf,satsys(sat,NULL)); + if (testsnr(0,0,azel[1],obs[i].SNR[0],&rtk->opt.snrmask)) continue; freq1=sat2freq(sat,obs[i].code[0],nav); freq2=sat2freq(sat,obs[i].code[f2],nav); - if (obs[i].P[0]==0.0||obs[i].P[f2]==0.0||freq1==0.0||freq2==0.0) { - continue; + if (freq1==0.0) continue; + if (nav->vtec.nlay>0) { /* use VTEC if corrections available */ + ionvtec(obs[i].time,nav,pos,azel,freq1,&ion,&var); + if (var==0.0) continue; + } else { + if (obs[i].P[0]==0.0||obs[i].P[f2]==0.0||freq2==0.0|| + testsnr(0,f2,azel[1],obs[i].SNR[f2],&rtk->opt.snrmask)) { + continue; + } + /* use pseudorange difference adjusted by freq for initial estimate */ + int sys=satsys(sat,NULL); + double P0_corr=obs[i].P[0]; + double Pf_corr=obs[i].P[f2]; + if (rtk->opt.sateph==EPHOPT_SSRAPC||rtk->opt.sateph==EPHOPT_SSRCOM) { + /* apply SSR correction */ + P0_corr-=nav->ssr[obs->sat-1].cbias[obs[i].code[0]-1]; + Pf_corr-=nav->ssr[obs->sat-1].cbias[obs[i].code[f2]-1]; + } + else { /* apply code bias corrections from file */ + P0_corr-=code2bias(nav,sys,sat,obs[i].code[0],1); + Pf_corr-=code2bias(nav,sys,sat,obs[i].code[f2],1); + } + ion=(P0_corr-Pf_corr)/(SQR(FREQL1/freq1)-SQR(FREQL1/freq2)); + trace(3,"P1=%.3f P2=%.3f frq1=%.1f frq2=%.1f\n",obs[i].P[0],obs[i].P[f2],freq1,freq2); + var=VAR_IONO; } - /* use pseudorange difference adjusted by freq for initial estimate */ - ion=(obs[i].P[0]-obs[i].P[f2])/(SQR(FREQL1/freq1)-SQR(FREQL1/freq2)); - ecef2pos(rtk->sol.rr,pos); - azel=rtk->ssat[sat-1].azel; /* adjust delay estimate by path length */ ion/=ionmapf(pos,azel); - initx(rtk,ion,VAR_IONO,j); - trace(4,"ion init: sat=%d ion=%.4f\n",sat,ion); + initx(rtk,ion,var,j); + trace(3,"ion init: sat=%d ion=%.4f var=%.1f\n",sat,ion,var); } - else { + else { /* temporal update */ sinel=sin(MAX(rtk->ssat[sat-1].azel[1],5.0*D2R)); /* update variance of delay state */ rtk->P[j+j*rtk->nx]+=SQR(rtk->opt.prn[1]/sinel)*fabs(rtk->tt); @@ -739,7 +775,7 @@ static void udbias_ppp(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav) detslp_mw(rtk,obs,n,nav); for (f=0;fopt);f++) { - + offset=0; /* reset phase-bias if expire obs outage counter */ for (i=0;issat[i].outc[f]>(uint32_t)rtk->opt.maxout|| @@ -757,7 +793,8 @@ static void udbias_ppp(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav) if (rtk->opt.ionoopt==IONOOPT_IFLC) { bias[i]=Lc-Pc; - slip[i]=rtk->ssat[sat-1].slip[0]||rtk->ssat[sat-1].slip[1]; + int f2=seliflc(rtk->opt.nf,rtk->ssat[sat-1].sys); + slip[i]=rtk->ssat[sat-1].slip[0]||rtk->ssat[sat-1].slip[f2]; } else if (L[f]!=0.0&&P[f]!=0.0) { freq1=sat2freq(sat,obs[i].code[0],nav); @@ -794,6 +831,7 @@ static void udbias_ppp(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav) /* reinitialize phase-bias if detecting cycle slip */ initx(rtk,bias[i],VAR_BIAS,IB(sat,f,&rtk->opt)); + trace(3,"init bias: sat=%d frq=%d\n", sat,f); /* reset fix flags */ for (k=0;kambc[sat-1].flags[k]=0; diff --git a/src/preceph.c b/src/preceph.c index b3e3928c2..0777c9d29 100644 --- a/src/preceph.c +++ b/src/preceph.c @@ -55,11 +55,12 @@ #define NMAX 10 /* order of polynomial interpolation */ #define MAXDTE 900.0 /* max time difference to ephem time (s) */ -#define EXTERR_CLK 1E-3 /* extrapolation error for clock (m/s) */ +#define EXTERR_CLK 0.4E-3 /* extrapolation error for clock (m/s) */ #define EXTERR_EPH 5E-7 /* extrapolation error for ephem (m/s^2) */ +#define MAX_BIAS_SYS 6 /* # of constellations supported */ /* table to translate code to code bias table index */ -static int8_t code_bias_ix[NSYS][MAXCODE]; +static int8_t code_bias_ix[MAX_BIAS_SYS][MAXCODE]; /* initialize code bias lookup table ------------------------------------------- * -1 = code not supported * 0 = reference code (0 bias) @@ -68,7 +69,7 @@ static int8_t code_bias_ix[NSYS][MAXCODE]; static void init_bias_ix(void) { int i,j; - for (i=0;ine>=nav->nemax) { - nav->nemax+=256; + nav->nemax += nav->nemax < 4 ? 1 : nav->nemax / 4; if (!(nav_peph=(peph_t *)realloc(nav->peph,sizeof(peph_t)*nav->nemax))) { trace(1,"readsp3b malloc error n=%d\n",nav->nemax); free(nav->peph); nav->peph=NULL; nav->ne=nav->nemax=0; @@ -186,6 +187,8 @@ static void readsp3b(FILE *fp, char type, int *sats, int ns, double *bfact, if (!strncmp(buff,"EOF",3)) break; + if (buff[0] == '/' && buff[1] == '*') continue; // Comment. + if (buff[0]!='*'||str2time(buff,3,28,&time)) { trace(2,"sp3 invalid epoch %31.31s\n",buff); continue; @@ -402,14 +405,16 @@ static int readdcbf(const char *file, nav_t *nav, const sta_t *sta) if ((cbias=str2num(buff,26,9))==0.0) continue; if (sta&&(!strcmp(str1,"G")||!strcmp(str1,"R"))) { /* receiver DCB */ -/* receiver DCBs never used in RTKLIB so remove support */ -// for (i=0;irbias[i][j][type-1]=cbias*1E-9*CLIGHT; /* ns -> m */ -// } +#ifdef RTK_DISABLED + /* Receiver DCBs never used in RTKLIB so remove support */ + for (i=0;irbias[i][j][type-1]=cbias*1E-9*CLIGHT; /* ns -> m */ + } +#endif } else if ((sat=satid2no(str1))) { /* satellite dcb */ nav->cbias[sat-1][type-1][0]=-cbias*1E-9*CLIGHT; /* ns -> m */ @@ -431,7 +436,7 @@ static int sys2ix(int sys) case SYS_QZS: return 4; case SYS_IRN: return 5; } - return 0; + return -1; } /* lookup code bias from table ---------------- * return 0 if not found @@ -442,10 +447,12 @@ extern double code2bias(const nav_t *nav, int sys, int sat, int code, int mode) int sys_ix,frq_ix,code_ix; double bias=0; + if (code <= CODE_NONE) return 0; sys_ix=sys2ix(sys); frq_ix=code2idx(sys,code); - if (frq_ix>=0&&sat<=MAXSAT) { + if (sys_ix >= 0 && sys_ix < MAX_BIAS_SYS && frq_ix >= 0 && sat <= MAXSAT) { code_ix = code_bias_ix[sys_ix][code]; + if (code_ix < 0) return 0; bias=nav->cbias[sat-1][frq_ix][code_ix]; // absolute bias if (mode==0) bias-=nav->cbias[sat-1][frq_ix][0]; // difference with reference @@ -459,7 +466,7 @@ static int readbiaf(const char *file, nav_t *nav) { FILE *fp; double cbias; - char buff[256],bias[6]="",svn[6]="",prn[6]="",obs1[6]="",obs2[6]; + char buff[256],bias[4]="",svn[4]="",prn[4]="",obs1[4]="",obs2[4]; int sat,sys_ix,frq_ix,code1,code2,bias_ix1,bias_ix2,sys; trace(3,"readbiaf: file=%s\n",file); @@ -469,12 +476,17 @@ static int readbiaf(const char *file, nav_t *nav) return 0; } while (fgets(buff,sizeof(buff),fp)) { - if (sscanf(buff,"%4s %5s %4s %4s %4s",bias,svn,prn,obs1,obs2)<5) continue; + if ((int)strlen(buff)<91) continue; + strncpy(bias, buff+1, 3); bias[3] ='\0'; + strncpy(prn, buff+11, 3); prn[3] ='\0'; + strncpy(obs1, buff+25, 3); obs1[3] ='\0'; + strncpy(obs2, buff+29, 3); obs2[3] ='\0'; if (obs1[0]!='C') continue; /* skip phase biases for now */ if ((cbias=str2num(buff,70,21))==0.0) continue; sat=satid2no(prn); sys=satsys(sat,NULL); sys_ix=sys2ix(sys); + if (sys_ix < 0 || sys_ix >= MAX_BIAS_SYS) continue; if (!(code1=obs2code(&obs1[1]))) continue; /* skip if code not valid */ if ((frq_ix=code2idx(sys,code1))<0) continue; if ((bias_ix1=code_bias_ix[sys_ix][code1])<0) continue; @@ -627,7 +639,7 @@ static int pephpos(gtime_t time, int sat, const nav_t *nav, double *rs, else if (c[0]!=0.0&&c[1]!=0.0) { dts[0]=(c[1]*t[0]-c[0]*t[1])/(t[0]-t[1]); i=t[0]<-t[1]?0:1; - std=nav->peph[index+i].std[sat-1][3]+EXTERR_CLK*fabs(t[i]); + std = nav->peph[index+i].std[sat-1][3] * CLIGHT + EXTERR_CLK * fabs(t[i]); } else { dts[0]=0.0; @@ -635,9 +647,10 @@ static int pephpos(gtime_t time, int sat, const nav_t *nav, double *rs, if (varc) *varc=SQR(std); return 1; } + /* satellite clock by precise clock ------------------------------------------*/ -extern int pephclk(gtime_t time, int sat, const nav_t *nav, double *dts, - double *varc) +static int pephclk1(gtime_t time, int sat, const nav_t *nav, double *dts, + double *varc) { double t[2],c[2],std; int i,j,k,index; @@ -649,7 +662,7 @@ extern int pephclk(gtime_t time, int sat, const nav_t *nav, double *dts, timediff(time,nav->pclk[0].time)<-MAXDTE|| timediff(time,nav->pclk[nav->nc-1].time)>MAXDTE) { trace(3,"no prec clock %s sat=%2d\n",time2str(time,tstr,0),sat); - return 1; + return 0; } /* binary search */ for (i=0,j=nav->nc-1;inbyte==0) { - if (!sync_ubx(raw->buff,data)) return 0; - raw->nbyte=2; + if (sync_ubx(raw->buff,data)) raw->nbyte=2; return 0; } raw->buff[raw->nbyte++]=data; diff --git a/src/rcv/unicore.c b/src/rcv/unicore.c index 1249dccc7..68c1b837a 100644 --- a/src/rcv/unicore.c +++ b/src/rcv/unicore.c @@ -103,11 +103,12 @@ static int checkpri(const char* opt, int sys, int code, int idx) if (sys == SYS_GPS) { if (strstr(opt, "-GL1L") && idx == 0) return (code == CODE_L1L) ? 0 : -1; - if (strstr(opt, "-GL2S") && idx == 1) return (code == CODE_L2X) ? 1 : -1; - if (strstr(opt, "-GL2P") && idx == 1) return (code == CODE_L2P) ? 1 : -1; + if (strstr(opt, "-GL2S") && idx == 1) return (code == CODE_L2S) ? 1 : -1; + if (strstr(opt, "-GL2L") && idx == 1) return (code == CODE_L2L) ? 1 : -1; + if (strstr(opt, "-GL2P") && idx == 1) return (code == CODE_L2W) ? 1 : -1; if (code == CODE_L1L) return (nex < 1) ? -1 : NFREQ; if (code == CODE_L2S) return (nex < 2) ? -1 : NFREQ + 1; - if (code == CODE_L2P) return (nex < 3) ? -1 : NFREQ + 2; + if (code == CODE_L2L) return (nex < 3) ? -1 : NFREQ + 2; } else if (sys == SYS_GLO) { if (strstr(opt, "-RL2C") && idx == 1) return (code == CODE_L2C) ? 1 : -1; @@ -497,14 +498,12 @@ static int decode_bdsephb(raw_t* raw) { eph_t eph = { 0 }; uint8_t* p = raw->buff + HLEN; - double ura; - int prn, sat, toc; if (raw->len < HLEN + 232) { trace(2, "unicore bdsephb length error: len=%d\n", raw->len); return -1; } - prn = U4(p); p += 4; + int prn = U4(p); p += 4; double tow = R8(p); p += 8; (void)tow; eph.svh = U4(p); p += 4; @@ -532,7 +531,7 @@ static int decode_bdsephb(raw_t* raw) eph.OMGd = R8(p); p += 8; eph.iodc = U4(p); p += 4; - toc = R8(p); p += 8; + double toc = R8(p); p += 8; eph.tgd[0] = R8(p); p += 8; /* TGD1 for B1 (s) */ eph.tgd[1] = R8(p); p += 8; /* TGD2 for B2 (s) */ @@ -545,10 +544,10 @@ static int decode_bdsephb(raw_t* raw) (void)as; double N = R8(p); p += 8; (void)N; - ura = R8(p); p += 8; - + double ura = R8(p); p += 8; - if (!(sat = satno(SYS_CMP, prn))) { + int sat = satno(SYS_CMP, prn); + if (!sat) { trace(2, "unicore bdsephb satellite error: prn=%d\n", prn); return -1; } diff --git a/src/rcvraw.c b/src/rcvraw.c index 99ce3ad92..512040e3f 100644 --- a/src/rcvraw.c +++ b/src/rcvraw.c @@ -568,7 +568,6 @@ static int decode_bds_d1_eph(const uint8_t *buff, eph_t *eph) eph_bds.f2 =getbits (buff,i+214,11)*P2_66; eph_bds.f0 =getbits2(buff,i+225, 7,i+240,17)*P2_33; eph_bds.f1 =getbits2(buff,i+257, 5,i+270,17)*P2_50; - eph_bds.iode =getbitu (buff,i+287, 5); /* AODE */ i=8*38*1; /* subframe 2 */ frn2 =getbitu (buff,i+ 15, 3); @@ -611,6 +610,7 @@ static int decode_bds_d1_eph(const uint8_t *buff, eph_t *eph) toc_bds); return 0; } + eph_bds.iode =((int)(toc_bds/720.0))%240; /* per BeiDou ICD */ eph_bds.ttr=bdt2gpst(bdt2time(eph_bds.week,sow1)); /* bdt -> gpst */ if (eph_bds.toes>sow1+302400.0) eph_bds.week++; else if (eph_bds.toeshalfc[i][j]=0; raw->lockflag[i][j]=0; } - raw->icpp[i]=raw->off[i]=raw->prCA[i]=raw->dpCA[i]=0.0; + raw->prCA[i]=raw->dpCA[i]=0.0; } for (i=0;ifreqn[i]=0; - raw->icpc=0.0; raw->nbyte=raw->len=0; raw->iod=raw->flag=raw->tbase=raw->outtype=0; raw->tod=-1; diff --git a/src/rinex.c b/src/rinex.c index 1bcd288b0..edbbc0bb0 100644 --- a/src/rinex.c +++ b/src/rinex.c @@ -671,11 +671,31 @@ static int readrnxh(FILE *fp, double *ver, char *type, int *sys, int *tsys, } else if (strstr(label,"RINEX VERSION / TYPE")) { *ver=str2num(buff,0,9); - // Format change for clock files >=3.04 - *type=(*ver<3.04||flag==0)?*(buff+20):*(buff+21); + char sc; + if (*ver >= 3.04) { + // The format changed for clock files >=3.04. + if (flag == 1) { // Expecting a clock file. + *type = buff[21]; + sc = buff[42]; + if (*type != 'C') { + *type = buff[20]; + sc = buff[40]; + } + } else { // Not expecting a clock file. + *type = buff[20]; + sc = buff[40]; + if (*type == ' ' && buff[21] == 'C') { + *type = buff[21]; + sc = buff[42]; + } + } + } else { + *type = buff[20]; + sc = buff[40]; + } // Satellite system - switch ((*ver<3.04||flag==0)?*(buff+40):*(buff+42)) { + switch (sc) { case ' ': case 'G': *sys=SYS_GPS; *tsys=TSYS_GPS; break; case 'R': *sys=SYS_GLO; *tsys=TSYS_UTC; break; @@ -686,7 +706,7 @@ static int readrnxh(FILE *fp, double *ver, char *type, int *sys, int *tsys, case 'I': *sys=SYS_IRN; *tsys=TSYS_IRN; break; /* v.3.03 */ case 'M': *sys=SYS_NONE; *tsys=TSYS_GPS; break; /* mixed */ default : - trace(2,"not supported satellite system: %c\n",*(buff+40)); + trace(2,"not supported satellite system: %c\n", sc); break; } continue; @@ -914,17 +934,15 @@ static int decode_obsdata(FILE *fp, char *buff, double ver, int mask, /* save cycle slips ----------------------------------------------------------*/ static void saveslips(uint8_t slips[][NFREQ+NEXOBS], obsd_t *data) { - int i; - for (i=0;iLLI[i]&1) slips[data->sat-1][i]|=LLI_SLIP; + for (int i=0;iLLI[i]&LLI_SLIP) slips[data->sat-1][i]=1; } } /* restore cycle slips -------------------------------------------------------*/ static void restslips(uint8_t slips[][NFREQ+NEXOBS], obsd_t *data) { - int i; - for (i=0;isat-1][i]&1) data->LLI[i]|=LLI_SLIP; + for (int i=0;isat-1][i]!=0) data->LLI[i]|=LLI_SLIP; slips[data->sat-1][i]=0; } } @@ -1121,7 +1139,7 @@ static int readrnxobs(FILE *fp, gtime_t ts, gtime_t te, double tint, if (!obs||rcv>MAXRCV) return 0; - if (!(data=(obsd_t *)malloc(sizeof(obsd_t)*MAXOBS))) return 0; + if (!(data=(obsd_t *)malloc(sizeof(obsd_t)*MAXOBS))) return -1; /* read RINEX observation data body */ while ((n=readrnxobsb(fp,opt,ver,tsys,tobs,&flag,data,sta))>=0&&stat>=0) { @@ -1538,34 +1556,33 @@ static int readrnxnav(FILE *fp, const char *opt, double ver, int sys, /* read RINEX clock ----------------------------------------------------------*/ static int readrnxclk(FILE *fp, const char *opt, double ver, int index, nav_t *nav) { - pclk_t *nav_pclk; - gtime_t time; - double data[2]; - int i,j,sat,mask,off; - char buff[MAXRNXLEN],satid[8]=""; - trace(3,"readrnxclk: index=%d\n", index); if (!nav) return 0; + pclk_t *nav_pclk; + char buff[MAXRNXLEN]; /* set system mask */ - mask=set_sysmask(opt); - off=ver>=3.04?5:0; /* format change for ver>=3.04 */ + int mask=set_sysmask(opt); + int off=ver>=3.04?5:0; /* format change for ver>=3.04 */ while (fgets(buff,sizeof(buff),fp)) { - + gtime_t time; if (str2time(buff,8+off,26,&time)) { trace(2,"rinex clk invalid epoch: %34.34s\n",buff); continue; } + char satid[8]=""; memcpy(satid,buff+3,4); /* only read AS (satellite clock) record */ + int sat; if (strncmp(buff,"AS",2)||!(sat=satid2no(satid))) continue; if (!(satsys(sat,NULL)&mask)) continue; - for (i=0,j=40+off;i<2;i++,j+=20) data[i]=str2num(buff,j,19); + double data[2]; + for (int i=0,j=40+off;i<2;i++,j+=20) data[i]=str2num(buff,j,19); if (nav->nc>=nav->ncmax) { nav->ncmax+=1024; @@ -1580,7 +1597,7 @@ static int readrnxclk(FILE *fp, const char *opt, double ver, int index, nav_t *n nav->nc++; nav->pclk[nav->nc-1].time =time; nav->pclk[nav->nc-1].index=index; - for (i=0;ipclk[nav->nc-1].clk[i][0]=0.0; nav->pclk[nav->nc-1].std[i][0]=0.0f; } @@ -1588,6 +1605,40 @@ static int readrnxclk(FILE *fp, const char *opt, double ver, int index, nav_t *n nav->pclk[nav->nc-1].clk[sat-1][0]=data[0]; nav->pclk[nav->nc-1].std[sat-1][0]=(float)data[1]; } + + // Interpolate the standard deviations. The standard deviations can be + // supplied at a lower rate than the clock biases, e.g. 30 sec biases with + // 5 minute standard deviations. + for (int k = 0; k < MAXSAT; k++) { + int last_std_idx = -1; + for (int i = 0; i < nav->nc; i++) { + double std = nav->pclk[i].std[k][0]; + if (std > 0) { + if (last_std_idx < 0) { + for (int j = 0; j < i; j++) + if (nav->pclk[j].clk[k][0] != 0) nav->pclk[j].std[k][0] = std; + } else { + // Linear interpolation of the variance. + for (int j = last_std_idx + 1; j < i; j++) { + if (nav->pclk[j].clk[k][0] != 0) { + double last_std = nav->pclk[last_std_idx].std[k][0]; + double t0 = timediff(nav->pclk[j].time, nav->pclk[last_std_idx].time); + double t1 = timediff(nav->pclk[j].time, nav->pclk[i].time); + double var = (SQR(std) * t0 - SQR(last_std) * t1) / (t0 - t1); + nav->pclk[j].std[k][0] = (float)sqrt(var); + } + } + } + last_std_idx = i; + } + } + if (last_std_idx >= 0) { + double last_std = nav->pclk[last_std_idx].std[k][0]; + for (int j = last_std_idx + 1; j < nav->nc; j++) + if (nav->pclk[j].clk[k][0] != 0) nav->pclk[j].std[k][0] = last_std; + } + } + return nav->nc>0; } /* read RINEX file -----------------------------------------------------------*/ @@ -2321,7 +2372,7 @@ static void outrnxobsf(FILE *fp, double obs, int lli, int std) static int obsindex(int rnxver, int sys, const uint8_t *code, const char *tobs, const char *mask) { - char *id; + const char *id; int i; for (i=0;idgps=NULL; for (i=0;issr[i]=ssr0; + rtcm->ssr[i].iode= -1; } rtcm->msg[0]=rtcm->msgtype[0]=rtcm->opt[0]='\0'; for (i=0;i<6;i++) rtcm->msmtype[i][0]='\0'; @@ -128,6 +129,7 @@ extern int init_rtcm(rtcm_t *rtcm) for (int i = 0; i < MAXPRNGLO; i++) rtcm->nav.geph[i] = geph0; } rtcm->nav.ng = rtcm->nav.ngmax = MAXPRNGLO; + for (int i = 0; i < 32; i++) rtcm->nav.glo_fcn[i] = 0; return 1; } diff --git a/src/rtcm3.c b/src/rtcm3.c index d3baa2e0b..584e90d9d 100644 --- a/src/rtcm3.c +++ b/src/rtcm3.c @@ -101,8 +101,9 @@ const char *msm_sig_gal[32] = { "", "", "", "", "", "", "", ""}; // 25-32 const char *msm_sig_qzs[32] = { // QZSS: ref [17] table 3.5-105. - // 1E, 1Z, 1B, 6E, 6Z, 5D, 5P, 5Z are tentative from the PocketSDR extensions - "", "1C", "", "", "1E", "1Z", "1B", "", "6S", "6L", "6X", "6E", // 1-12 + // 1Z, 1B, 6E, 6Z, 5D, 5P, 5Z are tentative from the PocketSDR extensions + // 1E tentative, noted from Trimble Alloy and Septentrio PolaRx5 receivers. + "", "1C", "1E", "", "", "1Z", "1B", "", "6S", "6L", "6X", "6E", // 1-12 "6Z", "", "2S", "2L", "2X", "", "", "", "", "5I", "5Q", "5X", // 13-24 "5D", "5P", "5Z", "", "", "1S", "1L", "1X"}; // 25-32 const char *msm_sig_sbs[32] = { @@ -110,7 +111,7 @@ const char *msm_sig_sbs[32] = { "", "1C", "", "", "", "", "", "", "", "", "", "", // 1-12 "", "", "", "", "", "", "", "", "", "5I", "5Q", "5X", // 13-24 "", "", "", "", "", "", "", ""}; // 25-32 -const char *msm_sig_cmp[32] = { +const char *msm_sig_bds[32] = { // BeiDou: ref [17] table 3.5-108. // 1S, 1L, 1Z, 6D, 6P, 6Z, 7P, 7Z, 8D, 8P, 8X are tentative from the PocketSDR extensions "", "2I", "2Q", "2X", "1S", "1L", "1Z", "6I", "6Q", "6X", "6D", "6P", // 1-12 @@ -124,33 +125,65 @@ const char *msm_sig_irn[32] = { "", "", "", "", "", "", "", "", "", "5A", "5B", "5C", // 13-24 "5X", "", "", "", "", "", "", ""}; // 25-32 -/* SSR signal and tracking mode IDs ------------------------------------------*/ +/* RTCM SSR signal and tracking mode IDs --------------------------------------*/ +// Signals L1S and L1L have intentional redundant entries, as producers +// currently vary in usage. const uint8_t ssr_sig_gps[32]={ CODE_L1C,CODE_L1P,CODE_L1W,CODE_L1S,CODE_L1L,CODE_L2C,CODE_L2D,CODE_L2S, - CODE_L2L,CODE_L2X,CODE_L2P,CODE_L2W, 0, 0,CODE_L5I,CODE_L5Q + CODE_L2L,CODE_L2X,CODE_L2P,CODE_L2W,CODE_L2Y,CODE_L2M,CODE_L5I,CODE_L5Q, + CODE_L5X,CODE_L1S,CODE_L1L,CODE_L1X }; const uint8_t ssr_sig_glo[32]={ + CODE_L1C,CODE_L1P,CODE_L2C,CODE_L2P,CODE_L4A,CODE_L4B,CODE_L4X,CODE_L6A, + CODE_L6B,CODE_L6X,CODE_L3I,CODE_L3Q,CODE_L3X +}; +const uint8_t ssr_sig_gal[32]={ + CODE_L1A,CODE_L1B,CODE_L1C,CODE_L1X,CODE_L1Z,CODE_L5I,CODE_L5Q,CODE_L5X, + CODE_L7I,CODE_L7Q,CODE_L7X,CODE_L8I,CODE_L8Q,CODE_L8X,CODE_L6A,CODE_L6B, + CODE_L6C,CODE_L6X,CODE_L6Z +}; +const uint8_t ssr_sig_qzs[32]={ + CODE_L1C,CODE_L1S,CODE_L1L,CODE_L2S,CODE_L2L,CODE_L2X,CODE_L5I,CODE_L5Q, + CODE_L5X,CODE_L6S,CODE_L6L,CODE_L6X,CODE_L1X,CODE_L1Z,CODE_L5D,CODE_L5P, + CODE_L5Z,CODE_L6E,CODE_L6Z +}; +const uint8_t ssr_sig_bds[32]={ + CODE_L2I,CODE_L2Q,CODE_L2X,CODE_L6I,CODE_L6Q,CODE_L6X,CODE_L7I,CODE_L7Q, + CODE_L7X,CODE_L1D,CODE_L1P,CODE_L1X,CODE_L5D,CODE_L5P,CODE_L5X,CODE_L1A, + 0, 0,CODE_L6A +}; +const uint8_t ssr_sig_sbs[32]={ + CODE_L1C,CODE_L5I,CODE_L5Q +}; + +/* IGS SSR signal and tracking mode IDs ---------------------------------------*/ +const uint8_t ssr_igs_sig_gps[32]={ + CODE_L1C,CODE_L1P,CODE_L1W,CODE_L1S,CODE_L1L,CODE_L2C,CODE_L2D,CODE_L2S, + CODE_L2L, 0,CODE_L2P,CODE_L2W, 0, 0,CODE_L5I,CODE_L5Q +}; +const uint8_t ssr_igs_sig_glo[32]={ CODE_L1C,CODE_L1P,CODE_L2C,CODE_L2P,CODE_L4A,CODE_L4B,CODE_L6A,CODE_L6B, CODE_L3I,CODE_L3Q }; -const uint8_t ssr_sig_gal[32]={ +const uint8_t ssr_igs_sig_gal[32]={ CODE_L1A,CODE_L1B,CODE_L1C, 0, 0,CODE_L5I,CODE_L5Q, 0, - CODE_L7I,CODE_L7Q, 0,CODE_L8I,CODE_L8Q, 0,CODE_L6A,CODE_L6B, + CODE_L7I,CODE_L7Q, 0, 0, 0, 0,CODE_L6A,CODE_L6B, CODE_L6C }; -const uint8_t ssr_sig_qzs[32]={ +const uint8_t ssr_igs_sig_qzs[32]={ CODE_L1C,CODE_L1S,CODE_L1L,CODE_L2S,CODE_L2L, 0,CODE_L5I,CODE_L5Q, 0,CODE_L6S,CODE_L6L, 0, 0, 0, 0, 0, 0,CODE_L6E }; -const uint8_t ssr_sig_cmp[32]={ +const uint8_t ssr_igs_sig_bds[32]={ CODE_L2I,CODE_L2Q, 0,CODE_L6I,CODE_L6Q, 0,CODE_L7I,CODE_L7Q, 0,CODE_L1D,CODE_L1P, 0,CODE_L5D,CODE_L5P, 0,CODE_L1A, 0, 0,CODE_L6A }; -const uint8_t ssr_sig_sbs[32]={ +const uint8_t ssr_igs_sig_sbs[32]={ CODE_L1C,CODE_L5I,CODE_L5Q }; + /* SSR update intervals ------------------------------------------------------*/ static const double ssrudint[16]={ 1,2,5,10,15,30,60,120,240,300,600,900,1800,3600,7200,10800 @@ -452,7 +485,7 @@ static int decode_type1005(rtcm_t *rtcm) if (!test_staid(rtcm,staid)) return -1; sprintf(rtcm->sta.name,"%04d",staid); - rtcm->sta.deltype=0; /* xyz */ + rtcm->sta.deltype=0; // ENU for (j=0;j<3;j++) { rtcm->sta.pos[j]=rr[j]*0.0001; rtcm->sta.del[j]=0.0; @@ -491,7 +524,7 @@ static int decode_type1006(rtcm_t *rtcm) if (!test_staid(rtcm,staid)) return -1; sprintf(rtcm->sta.name,"%04d",staid); - rtcm->sta.deltype=1; /* xyz */ + rtcm->sta.deltype=0; // ENU for (j=0;j<3;j++) { rtcm->sta.pos[j]=rr[j]*0.0001; rtcm->sta.del[j]=0.0; @@ -1437,7 +1470,7 @@ static int decode_type1042(rtcm_t *rtcm) week =getbitu(rtcm->buff,i,13); i+=13; eph.sva =getbitu(rtcm->buff,i, 4); i+= 4; eph.idot =getbits(rtcm->buff,i,14)*P2_43*SC2RAD; i+=14; - eph.iode =getbitu(rtcm->buff,i, 5); i+= 5; /* AODE */ + i+= 5; /* AODE */ toc =getbitu(rtcm->buff,i,17)*8.0; i+=17; eph.f2 =getbits(rtcm->buff,i,11)*P2_66; i+=11; eph.f1 =getbits(rtcm->buff,i,22)*P2_50; i+=22; @@ -1479,6 +1512,7 @@ static int decode_type1042(rtcm_t *rtcm) } eph.sat=sat; eph.week=adjbdtweek(week); + eph.iode =((int)(toc/720.0))%240; /* per BeiDou ICD */ if (rtcm->time.time==0) rtcm->time=utc2gpst(timeget()); tt=timediff(bdt2gpst(bdt2time(eph.week,eph.toes)),rtcm->time); if (tt<-302400.0) eph.week++; @@ -1608,7 +1642,7 @@ static int decode_ssr1(rtcm_t *rtcm, int sys, int subtype) type=getbitu(rtcm->buff,24,12); if ((nsat=decode_ssr1_head(rtcm,sys,subtype,&sync,&iod,&udint,&refd,&i))<0) { - trace(2,"rtcm3 %d length error: len=%d\n",type,rtcm->len); + trace(2,"rtcm3 %d/%d length error: len=%d\n",type,subtype,rtcm->len); return -1; } switch (sys) { @@ -1616,14 +1650,13 @@ static int decode_ssr1(rtcm_t *rtcm, int sys, int subtype) case SYS_GLO: np=5; ni= 8; nj= 0; offp= 0; break; case SYS_GAL: np=6; ni=10; nj= 0; offp= 0; break; case SYS_QZS: np=4; ni= 8; nj= 0; offp=192; break; - case SYS_CMP: np=6; ni=10; nj=24; offp= 1; break; + case SYS_CMP: np=6; ni=10; nj=8; offp= 0; break; case SYS_SBS: np=6; ni= 9; nj=24; offp=120; break; default: return sync?0:10; } if (subtype>0) { /* IGS SSR */ np=6; ni=8; nj=0; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + if (sys==SYS_SBS) offp=119; } for (j=0;jlen*8;j++) { prn =getbitu(rtcm->buff,i,np)+offp; i+=np; @@ -1637,12 +1670,15 @@ static int decode_ssr1(rtcm_t *rtcm, int sys, int subtype) ddeph[2]=getbits(rtcm->buff,i,19)*4E-6; i+=19; if (!(sat=satno(sys,prn))) { - trace(2,"rtcm3 %d satellite number error: prn=%d\n",type,prn); + trace(2,"rtcm3 %d/%d satellite number error: prn=%d\n",type,subtype,prn); continue; } rtcm->ssr[sat-1].t0 [0]=rtcm->time; rtcm->ssr[sat-1].udi[0]=udint; rtcm->ssr[sat-1].iod[0]=iod; + if (sys==SYS_CMP && subtype==0) { + iode=iodcrc; /* BDS per-satellite SSR IOD */ + } rtcm->ssr[sat-1].iode=iode; /* SBAS/BDS: toe/t0 modulo */ rtcm->ssr[sat-1].iodcrc=iodcrc; /* SBAS/BDS: IOD CRC */ rtcm->ssr[sat-1].refd=refd; @@ -1664,7 +1700,7 @@ static int decode_ssr2(rtcm_t *rtcm, int sys, int subtype) type=getbitu(rtcm->buff,24,12); if ((nsat=decode_ssr2_head(rtcm,sys,subtype,&sync,&iod,&udint,&i))<0) { - trace(2,"rtcm3 %d length error: len=%d\n",type,rtcm->len); + trace(2,"rtcm3 %d/%d length error: len=%d\n",type,subtype,rtcm->len); return -1; } switch (sys) { @@ -1672,14 +1708,13 @@ static int decode_ssr2(rtcm_t *rtcm, int sys, int subtype) case SYS_GLO: np=5; offp= 0; break; case SYS_GAL: np=6; offp= 0; break; case SYS_QZS: np=4; offp=192; break; - case SYS_CMP: np=6; offp= 1; break; + case SYS_CMP: np=6; offp= 0; break; case SYS_SBS: np=6; offp=120; break; default: return sync?0:10; } if (subtype>0) { /* IGS SSR */ np=6; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + if (sys==SYS_SBS) offp=119; } for (j=0;jlen*8;j++) { prn =getbitu(rtcm->buff,i,np)+offp; i+=np; @@ -1688,7 +1723,7 @@ static int decode_ssr2(rtcm_t *rtcm, int sys, int subtype) dclk[2]=getbits(rtcm->buff,i,27)*2E-8; i+=27; if (!(sat=satno(sys,prn))) { - trace(2,"rtcm3 %d satellite number error: prn=%d\n",type,prn); + trace(2,"rtcm3 %d/%d satellite number error: prn=%d\n",type,subtype,prn); continue; } rtcm->ssr[sat-1].t0 [1]=rtcm->time; @@ -1712,22 +1747,29 @@ static int decode_ssr3(rtcm_t *rtcm, int sys, int subtype) type=getbitu(rtcm->buff,24,12); if ((nsat=decode_ssr2_head(rtcm,sys,subtype,&sync,&iod,&udint,&i))<0) { - trace(2,"rtcm3 %d length error: len=%d\n",type,rtcm->len); + trace(2,"rtcm3 %d/%d length error: len=%d\n",type,subtype,rtcm->len); return -1; } - switch (sys) { + if (subtype>0) { /* IGS SSR */ + switch (sys) { + case SYS_GPS: np=6; offp= 0; sigs=ssr_igs_sig_gps; break; + case SYS_GLO: np=6; offp= 0; sigs=ssr_igs_sig_glo; break; + case SYS_GAL: np=6; offp= 0; sigs=ssr_igs_sig_gal; break; + case SYS_QZS: np=6; offp=192; sigs=ssr_igs_sig_qzs; break; + case SYS_CMP: np=6; offp= 0; sigs=ssr_igs_sig_bds; break; + case SYS_SBS: np=6; offp=119; sigs=ssr_igs_sig_sbs; break; + default: return sync?0:10; + } + } else { + switch (sys) { case SYS_GPS: np=6; offp= 0; sigs=ssr_sig_gps; break; case SYS_GLO: np=5; offp= 0; sigs=ssr_sig_glo; break; case SYS_GAL: np=6; offp= 0; sigs=ssr_sig_gal; break; case SYS_QZS: np=4; offp=192; sigs=ssr_sig_qzs; break; - case SYS_CMP: np=6; offp= 1; sigs=ssr_sig_cmp; break; + case SYS_CMP: np=6; offp= 0; sigs=ssr_sig_bds; break; case SYS_SBS: np=6; offp=120; sigs=ssr_sig_sbs; break; default: return sync?0:10; - } - if (subtype>0) { /* IGS SSR */ - np=6; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + } } for (j=0;jlen*8;j++) { prn =getbitu(rtcm->buff,i,np)+offp; i+=np; @@ -1741,11 +1783,11 @@ static int decode_ssr3(rtcm_t *rtcm, int sys, int subtype) cbias[sigs[mode]-1]=bias; } else { - trace(2,"rtcm3 %d not supported mode: mode=%d\n",type,mode); + trace(2,"rtcm3 %d/%d not supported mode: mode=%d\n",type,subtype,mode); } } if (!(sat=satno(sys,prn))) { - trace(2,"rtcm3 %d satellite number error: prn=%d\n",type,prn); + trace(2,"rtcm3 %d/%d satellite number error: prn=%d\n",type,subtype,prn); continue; } rtcm->ssr[sat-1].t0 [4]=rtcm->time; @@ -1768,7 +1810,7 @@ static int decode_ssr4(rtcm_t *rtcm, int sys, int subtype) type=getbitu(rtcm->buff,24,12); if ((nsat=decode_ssr1_head(rtcm,sys,subtype,&sync,&iod,&udint,&refd,&i))<0) { - trace(2,"rtcm3 %d length error: len=%d\n",type,rtcm->len); + trace(2,"rtcm3 %d/%d length error: len=%d\n",type,subtype,rtcm->len); return -1; } switch (sys) { @@ -1776,14 +1818,13 @@ static int decode_ssr4(rtcm_t *rtcm, int sys, int subtype) case SYS_GLO: np=5; ni= 8; nj= 0; offp= 0; break; case SYS_GAL: np=6; ni=10; nj= 0; offp= 0; break; case SYS_QZS: np=4; ni= 8; nj= 0; offp=192; break; - case SYS_CMP: np=6; ni=10; nj=24; offp= 1; break; + case SYS_CMP: np=6; ni=10; nj= 8; offp= 0; break; case SYS_SBS: np=6; ni= 9; nj=24; offp=120; break; default: return sync?0:10; } if (subtype>0) { /* IGS SSR */ np=6; ni=8; nj=0; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + if (sys==SYS_SBS) offp=119; } for (j=0;jlen*8;j++) { prn =getbitu(rtcm->buff,i,np)+offp; i+=np; @@ -1801,12 +1842,15 @@ static int decode_ssr4(rtcm_t *rtcm, int sys, int subtype) dclk [2]=getbits(rtcm->buff,i,27)*2E-8; i+=27; if (!(sat=satno(sys,prn))) { - trace(2,"rtcm3 %d satellite number error: prn=%d\n",type,prn); + trace(2,"rtcm3 %d/%d satellite number error: prn=%d\n",type,subtype,prn); continue; } rtcm->ssr[sat-1].t0 [0]=rtcm->ssr[sat-1].t0 [1]=rtcm->time; rtcm->ssr[sat-1].udi[0]=rtcm->ssr[sat-1].udi[1]=udint; rtcm->ssr[sat-1].iod[0]=rtcm->ssr[sat-1].iod[1]=iod; + if (sys==SYS_CMP && subtype==0) { + iode=iodcrc; /* BDS per-satellite SSR IOD */ + } rtcm->ssr[sat-1].iode=iode; rtcm->ssr[sat-1].iodcrc=iodcrc; rtcm->ssr[sat-1].refd=refd; @@ -1829,7 +1873,7 @@ static int decode_ssr5(rtcm_t *rtcm, int sys, int subtype) type=getbitu(rtcm->buff,24,12); if ((nsat=decode_ssr2_head(rtcm,sys,subtype,&sync,&iod,&udint,&i))<0) { - trace(2,"rtcm3 %d length error: len=%d\n",type,rtcm->len); + trace(2,"rtcm3 %d/%d length error: len=%d\n",type,subtype,rtcm->len); return -1; } switch (sys) { @@ -1837,21 +1881,20 @@ static int decode_ssr5(rtcm_t *rtcm, int sys, int subtype) case SYS_GLO: np=5; offp= 0; break; case SYS_GAL: np=6; offp= 0; break; case SYS_QZS: np=4; offp=192; break; - case SYS_CMP: np=6; offp= 1; break; + case SYS_CMP: np=6; offp= 0; break; case SYS_SBS: np=6; offp=120; break; default: return sync?0:10; } if (subtype>0) { /* IGS SSR */ np=6; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + if (sys==SYS_SBS) offp=119; } for (j=0;jlen*8;j++) { prn=getbitu(rtcm->buff,i,np)+offp; i+=np; ura=getbitu(rtcm->buff,i, 6); i+= 6; if (!(sat=satno(sys,prn))) { - trace(2,"rtcm3 %d satellite number error: prn=%d\n",type,prn); + trace(2,"rtcm3 %d/%d satellite number error: prn=%d\n",type,subtype,prn); continue; } rtcm->ssr[sat-1].t0 [3]=rtcm->time; @@ -1871,7 +1914,7 @@ static int decode_ssr6(rtcm_t *rtcm, int sys, int subtype) type=getbitu(rtcm->buff,24,12); if ((nsat=decode_ssr2_head(rtcm,sys,subtype,&sync,&iod,&udint,&i))<0) { - trace(2,"rtcm3 %d length error: len=%d\n",type,rtcm->len); + trace(2,"rtcm3 %d/%d length error: len=%d\n",type,subtype,rtcm->len); return -1; } switch (sys) { @@ -1879,21 +1922,20 @@ static int decode_ssr6(rtcm_t *rtcm, int sys, int subtype) case SYS_GLO: np=5; offp= 0; break; case SYS_GAL: np=6; offp= 0; break; case SYS_QZS: np=4; offp=192; break; - case SYS_CMP: np=6; offp= 1; break; + case SYS_CMP: np=6; offp= 0; break; case SYS_SBS: np=6; offp=120; break; default: return sync?0:10; } if (subtype>0) { /* IGS SSR */ np=6; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + if (sys==SYS_SBS) offp=119; } for (j=0;jlen*8;j++) { prn =getbitu(rtcm->buff,i,np)+offp; i+=np; hrclk=getbits(rtcm->buff,i,22)*1E-4; i+=22; if (!(sat=satno(sys,prn))) { - trace(2,"rtcm3 %d satellite number error: prn=%d\n",type,prn); + trace(2,"rtcm3 %d/%d satellite number error: prn=%d\n",type,subtype,prn); continue; } rtcm->ssr[sat-1].t0 [2]=rtcm->time; @@ -1947,7 +1989,7 @@ static int decode_ssr7_head(rtcm_t *rtcm, int sys, int subtype, int *sync, static int decode_ssr7(rtcm_t *rtcm, int sys, int subtype) { const uint8_t *sigs; - double udint,bias,std=0.0,pbias[MAXCODE],stdpb[MAXCODE]; + double udint,bias,pbias[MAXCODE]; int i,j,k,type,mode,sync,iod,nsat,prn,sat,nbias,np,mw,offp,sii,swl; int dispe,sdc,yaw_ang,yaw_rate; @@ -1955,21 +1997,29 @@ static int decode_ssr7(rtcm_t *rtcm, int sys, int subtype) if ((nsat=decode_ssr7_head(rtcm,sys,subtype,&sync,&iod,&udint,&dispe,&mw, &i))<0) { - trace(2,"rtcm3 %d length error: len=%d\n",type,rtcm->len); + trace(2,"rtcm3 %d/%d length error: len=%d\n",type,subtype,rtcm->len); return -1; } - switch (sys) { + if (subtype>0) { /* IGS SSR */ + switch (sys) { + case SYS_GPS: np=6; offp= 0; sigs=ssr_igs_sig_gps; break; + case SYS_GLO: np=6; offp= 0; sigs=ssr_igs_sig_glo; break; + case SYS_GAL: np=6; offp= 0; sigs=ssr_igs_sig_gal; break; + case SYS_QZS: np=6; offp=192; sigs=ssr_igs_sig_qzs; break; + case SYS_CMP: np=6; offp= 0; sigs=ssr_igs_sig_bds; break; + case SYS_SBS: np=6; offp=119; sigs=ssr_igs_sig_sbs; break; + default: return sync?0:10; + } + } else { + switch (sys) { case SYS_GPS: np=6; offp= 0; sigs=ssr_sig_gps; break; case SYS_GLO: np=5; offp= 0; sigs=ssr_sig_glo; break; case SYS_GAL: np=6; offp= 0; sigs=ssr_sig_gal; break; case SYS_QZS: np=4; offp=192; sigs=ssr_sig_qzs; break; - case SYS_CMP: np=6; offp= 1; sigs=ssr_sig_cmp; break; + case SYS_CMP: np=6; offp= 0; sigs=ssr_sig_bds; break; + case SYS_SBS: np=6; offp=120; sigs=ssr_sig_sbs; break; default: return sync?0:10; - } - if (subtype>0) { /* IGS SSR */ - np=6; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + } } for (j=0;jlen*8;j++) { prn =getbitu(rtcm->buff,i,np)+offp; i+=np; @@ -1977,26 +2027,22 @@ static int decode_ssr7(rtcm_t *rtcm, int sys, int subtype) yaw_ang =getbitu(rtcm->buff,i, 9); i+= 9; yaw_rate=getbits(rtcm->buff,i, 8); i+= 8; - for (k=0;klen*8;k++) { mode=getbitu(rtcm->buff,i, 5); i+= 5; sii =getbitu(rtcm->buff,i, 1); i+= 1; /* integer-indicator */ swl =getbitu(rtcm->buff,i, 2); i+= 2; /* WL integer-indicator */ sdc =getbitu(rtcm->buff,i, 4); i+= 4; /* discontinuity counter */ bias=getbits(rtcm->buff,i,20); i+=20; /* phase bias (m) */ - if (subtype==0) { - std =getbitu(rtcm->buff,i,17); i+=17; /* phase bias std-dev (m) */ - } if (sigs[mode]) { pbias[sigs[mode]-1]=bias*0.0001; /* (m) */ - stdpb[sigs[mode]-1]=std *0.0001; /* (m) */ } else { - trace(2,"rtcm3 %d not supported mode: mode=%d\n",type,mode); + trace(2,"rtcm3 %d/%d not supported mode: mode=%d\n",type,subtype,mode); } } if (!(sat=satno(sys,prn))) { - trace(2,"rtcm3 %d satellite number error: prn=%d\n",type,prn); + trace(2,"rtcm3 %d/%d satellite number error: prn=%d\n",type,subtype,prn); continue; } rtcm->ssr[sat-1].t0 [5]=rtcm->time; @@ -2007,11 +2053,75 @@ static int decode_ssr7(rtcm_t *rtcm, int sys, int subtype) for (k=0;kssr[sat-1].pbias[k]=pbias[k]; - rtcm->ssr[sat-1].stdpb[k]=(float)stdpb[k]; } } return 20; } +/* decode SSR 8: VTEC ionosphere --------------------------------------------- */ +static int decode_ssr8(rtcm_t *rtcm, int subtype) +{ + double udint,hgt,cosC,sinC,tow; + int i=0,j,k,l,type,sync,iod,udi,nlay,nmax,mmax,np,offp,qi; + char *msg,tstr[40]; + + type=getbitu(rtcm->buff,24,12); + + i+=decode_ssr_epoch(rtcm,SYS_GPS,subtype); + udi =getbitu(rtcm->buff,i, 4); i+= 4; + udint=ssrudint[udi]; + sync =getbitu(rtcm->buff,i,1); i+= 1; + iod =getbitu(rtcm->buff,i,4); i+= 4; + getbitu(rtcm->buff,i,16); i+=16; /* provider ID */ + getbitu(rtcm->buff,i, 4); i+= 4; /* solution ID */ + qi =getbitu(rtcm->buff,i,9); i+= 9; /* quality indicator */ + nlay =getbitu(rtcm->buff,i,2)+1; i+= 2; /* number of layers (1-4) */ + + if (rtcm->outtype) { + time2str(rtcm->time,tstr,2); + msg=rtcm->msgtype+strlen(rtcm->msgtype); + sprintf(msg," %s nsat= iod=%2d udi=%2d sync=%d",tstr,iod,udi,sync); + } + + if (nlay>4) { + trace(2,"rtcm3 %d too many layers: nlay=%d\n",type,nlay); + return -1; + } + + for (j=0;jlen*8;j++) { + hgt =getbitu(rtcm->buff,i,8)*10; i+=8; /* height (km) DF472 */ + nmax =getbitu(rtcm->buff,i, 4)+1; i+= 4; /* degree DF473 */ + mmax =getbitu(rtcm->buff,i, 4)+1; i+= 4; /* order DF474 */ + + rtcm->nav.vtec.hgt[j]=hgt; + rtcm->nav.vtec.nmax[j]=nmax; + rtcm->nav.vtec.mmax[j]=mmax; + + /* clear previous coefficients */ + memset(rtcm->nav.vtec.cosC, 0, sizeof(rtcm->nav.vtec.cosC)); + memset(rtcm->nav.vtec.sinC, 0, sizeof(rtcm->nav.vtec.sinC)); + /* cosine coefficients: for order o=0..mmax, degree n=o..nmax */ + for (k=0;k<=mmax;k++) { + for (l=k;l<=nmax;l++) { + cosC=getbits(rtcm->buff,i,16); i+=16; + rtcm->nav.vtec.cosC[j][l][k]=cosC/200.0; + } + } + /* sine coefficients: for order o=1..mmax, degree n=o..nmax */ + for (k=1;k<=mmax;k++) { + for (l=k;l<=nmax;l++) { + sinC=getbits(rtcm->buff,i,16); i+=16; + rtcm->nav.vtec.sinC[j][l][k]=sinC/200.0; + } + } + } + rtcm->nav.vtec.udint=udint; + rtcm->nav.vtec.iod=iod; + rtcm->nav.vtec.nlay=nlay; + rtcm->nav.vtec.qi=qi*0.05; /* TECU */ + + trace(3,"ssr8 vtec: nlay=%d\n",nlay); + return 10; +} /* get signal index ----------------------------------------------------------*/ static void sigindex(int sys, const uint8_t *code, int n, const char *opt, int *idx) @@ -2081,7 +2191,7 @@ static void save_msm_obs(rtcm_t *rtcm, int sys, msm_h_t *h, const double *r, case SYS_GAL: sig[i]=msm_sig_gal[h->sigs[i]-1]; break; case SYS_QZS: sig[i]=msm_sig_qzs[h->sigs[i]-1]; break; case SYS_SBS: sig[i]=msm_sig_sbs[h->sigs[i]-1]; break; - case SYS_CMP: sig[i]=msm_sig_cmp[h->sigs[i]-1]; break; + case SYS_CMP: sig[i]=msm_sig_bds[h->sigs[i]-1]; break; case SYS_IRN: sig[i]=msm_sig_irn[h->sigs[i]-1]; break; default: sig[i]=""; break; } @@ -2753,10 +2863,13 @@ extern int decode_rtcm3(rtcm_t *rtcm) case 1261: ret=decode_ssr4(rtcm,SYS_CMP,0); break; /* draft */ case 1262: ret=decode_ssr5(rtcm,SYS_CMP,0); break; /* draft */ case 1263: ret=decode_ssr6(rtcm,SYS_CMP,0); break; /* draft */ - case 11: ret=decode_ssr7(rtcm,SYS_GPS,0); break; /* tentative */ - case 12: ret=decode_ssr7(rtcm,SYS_GAL,0); break; /* tentative */ - case 13: ret=decode_ssr7(rtcm,SYS_QZS,0); break; /* tentative */ - case 14: ret=decode_ssr7(rtcm,SYS_CMP,0); break; /* tentative */ + case 1264: ret=decode_ssr8(rtcm,0); break; /* draft */ + case 1265: ret=decode_ssr7(rtcm,SYS_GPS,0); break; /* draft */ + case 1266: ret=decode_ssr7(rtcm,SYS_GLO,0); break; /* draft */ + case 1267: ret=decode_ssr7(rtcm,SYS_GAL,0); break; /* draft */ + case 1268: ret=decode_ssr7(rtcm,SYS_QZS,0); break; /* draft */ + case 1269: ret=decode_ssr7(rtcm,SYS_SBS,0); break; /* draft */ + case 1270: ret=decode_ssr7(rtcm,SYS_CMP,0); break; /* draft */ case 4073: ret=decode_type4073(rtcm); break; case 4076: ret=decode_type4076(rtcm); break; } diff --git a/src/rtcm3e.c b/src/rtcm3e.c index 6f68a4410..d5beb3a4b 100644 --- a/src/rtcm3e.c +++ b/src/rtcm3e.c @@ -71,7 +71,7 @@ extern const char *msm_sig_glo[32]; extern const char *msm_sig_gal[32]; extern const char *msm_sig_qzs[32]; extern const char *msm_sig_sbs[32]; -extern const char *msm_sig_cmp[32]; +extern const char *msm_sig_bds[32]; extern const char *msm_sig_irn[32]; /* SSR signal and tracking mode IDs ------------------------------------------*/ @@ -79,7 +79,7 @@ extern const uint8_t ssr_sig_gps[32]; extern const uint8_t ssr_sig_glo[32]; extern const uint8_t ssr_sig_gal[32]; extern const uint8_t ssr_sig_qzs[32]; -extern const uint8_t ssr_sig_cmp[32]; +extern const uint8_t ssr_sig_bds[32]; extern const uint8_t ssr_sig_sbs[32]; /* SSR update intervals ------------------------------------------------------*/ @@ -1447,29 +1447,26 @@ static int encode_ssr_head(int type, rtcm_t *rtcm, int sys, int subtype, if (subtype==0) { /* RTCM SSR */ ns=(sys==SYS_QZS)?4:6; - switch (sys) { - case SYS_GPS: msgno=(type==7)?11:1056+type; break; - case SYS_GLO: msgno=(type==7)? 0:1062+type; break; - case SYS_GAL: msgno=(type==7)?12:1239+type; break; /* draft */ - case SYS_QZS: msgno=(type==7)?13:1245+type; break; /* draft */ - case SYS_CMP: msgno=(type==7)?14:1257+type; break; /* draft */ - case SYS_SBS: msgno=(type==7)? 0:1251+type; break; /* draft */ - default: return 0; - } - if (msgno==0) { - return 0; - } + switch (sys) { + case SYS_GPS: msgno=(type==7)?1265:1056+type; break; + case SYS_GLO: msgno=(type==7)?1266:1062+type; break; + case SYS_GAL: msgno=(type==7)?1267:1239+type; break; /* draft */ + case SYS_QZS: msgno=(type==7)?1268:1245+type; break; /* draft */ + case SYS_CMP: msgno=(type==7)?1269:1257+type; break; /* draft */ + case SYS_SBS: msgno=(type==7)?1270:1251+type; break; /* draft */ + default: return 0; + } setbitu(rtcm->buff,i,12,msgno); i+=12; /* message type */ - if (sys==SYS_GLO) { - tow=time2gpst(timeadd(gpst2utc(rtcm->time),10800.0),&week); - epoch=ROUND(tow)%86400; - setbitu(rtcm->buff,i,17,epoch); i+=17; /* GLONASS epoch time */ - } - else { - tow=time2gpst(rtcm->time,&week); - epoch=ROUND(tow)%604800; - setbitu(rtcm->buff,i,20,epoch); i+=20; /* GPS epoch time */ + if (sys==SYS_GLO) { + tow=time2gpst(timeadd(gpst2utc(rtcm->time),10800.0),&week); + epoch=ROUND(tow)%86400; + setbitu(rtcm->buff,i,17,epoch); i+=17; /* GLONASS epoch time */ + } + else { + tow=time2gpst(rtcm->time,&week); + epoch=ROUND(tow)%604800; + setbitu(rtcm->buff,i,20,epoch); i+=20; /* GPS epoch time */ } } else { /* IGS SSR */ @@ -1502,31 +1499,59 @@ static int encode_ssr_head(int type, rtcm_t *rtcm, int sys, int subtype, setbitu(rtcm->buff,i,ns,nsat ); i+=ns; /* no of satellites */ return i; } -/* SSR signal and tracking mode IDs ------------------------------------------*/ +/* RTCM SSR signal and tracking mode IDs --------------------------------------*/ static const int codes_gps[32]={ - CODE_L1C,CODE_L1P,CODE_L1W,CODE_L1S,CODE_L1L,CODE_L2C,CODE_L2D,CODE_L2S, - CODE_L2L,CODE_L2X,CODE_L2P,CODE_L2W, 0, 0,CODE_L5I,CODE_L5Q + CODE_L1C,CODE_L1P,CODE_L1W, 0, 0,CODE_L2C,CODE_L2D,CODE_L2S, + CODE_L2L,CODE_L2X,CODE_L2P,CODE_L2W,CODE_L2Y,CODE_L2M,CODE_L5I,CODE_L5Q, + CODE_L5X,CODE_L1S,CODE_L1L,CODE_L1X }; static const int codes_glo[32]={ + CODE_L1C,CODE_L1P,CODE_L2C,CODE_L2P,CODE_L4A,CODE_L4B,CODE_L4X,CODE_L6A, + CODE_L6B,CODE_L6X,CODE_L3I,CODE_L3Q,CODE_L3X +}; +static const int codes_gal[32]={ + CODE_L1A,CODE_L1B,CODE_L1C,CODE_L1X,CODE_L1Z,CODE_L5I,CODE_L5Q,CODE_L5X, + CODE_L7I,CODE_L7Q,CODE_L7X,CODE_L8I,CODE_L8Q,CODE_L8X,CODE_L6A,CODE_L6B, + CODE_L6C,CODE_L6X,CODE_L6Z +}; +static const int codes_qzs[32]={ + CODE_L1C,CODE_L1S,CODE_L1L,CODE_L2S,CODE_L2L,CODE_L2X,CODE_L5I,CODE_L5Q, + CODE_L5X,CODE_L6S,CODE_L6L,CODE_L6X,CODE_L1X,CODE_L1Z,CODE_L5D,CODE_L5P, + CODE_L5Z,CODE_L6E,CODE_L6Z +}; +static const int codes_bds[32]={ + CODE_L2I,CODE_L2Q,CODE_L2X,CODE_L6I,CODE_L6Q,CODE_L6X,CODE_L7I,CODE_L7Q, + CODE_L7X,CODE_L1D,CODE_L1P,CODE_L1X,CODE_L5D,CODE_L5P,CODE_L5X,CODE_L1A, + 0, 0,CODE_L6A +}; +static const int codes_sbs[32]={ + CODE_L1C,CODE_L5I,CODE_L5Q +}; +/* IGS SSR signal and tracking mode IDs ---------------------------------------*/ +static const int codes_igs_gps[32]={ + CODE_L1C,CODE_L1P,CODE_L1W,CODE_L1S,CODE_L1L,CODE_L2C,CODE_L2D,CODE_L2S, + CODE_L2L, 0,CODE_L2P,CODE_L2W, 0, 0,CODE_L5I,CODE_L5Q +}; +static const int codes_igs_glo[32]={ CODE_L1C,CODE_L1P,CODE_L2C,CODE_L2P,CODE_L4A,CODE_L4B,CODE_L6A,CODE_L6B, CODE_L3I,CODE_L3Q }; -static const int codes_gal[32]={ +static const int codes_igs_gal[32]={ CODE_L1A,CODE_L1B,CODE_L1C, 0, 0,CODE_L5I,CODE_L5Q, 0, - CODE_L7I,CODE_L7Q, 0,CODE_L8I,CODE_L8Q, 0,CODE_L6A,CODE_L6B, + CODE_L7I,CODE_L7Q, 0, 0, 0, 0,CODE_L6A,CODE_L6B, CODE_L6C }; -static const int codes_qzs[32]={ +static const int codes_igs_qzs[32]={ CODE_L1C,CODE_L1S,CODE_L1L,CODE_L2S,CODE_L2L, 0,CODE_L5I,CODE_L5Q, 0,CODE_L6S,CODE_L6L, 0, 0, 0, 0, 0, 0,CODE_L6E }; -static const int codes_bds[32]={ +static const int codes_igs_bds[32]={ CODE_L2I,CODE_L2Q, 0,CODE_L6I,CODE_L6Q, 0,CODE_L7I,CODE_L7Q, 0,CODE_L1D,CODE_L1P, 0,CODE_L5D,CODE_L5P, 0,CODE_L1A, 0, 0,CODE_L6A }; -static const int codes_sbs[32]={ +static const int codes_igs_sbs[32]={ CODE_L1C,CODE_L5I,CODE_L5Q }; /* encode SSR 1: orbit corrections -------------------------------------------*/ @@ -1542,14 +1567,13 @@ static int encode_ssr1(rtcm_t *rtcm, int sys, int subtype, int sync) case SYS_GLO: np=5; ni= 8; nj= 0; offp= 0; break; case SYS_GAL: np=6; ni=10; nj= 0; offp= 0; break; case SYS_QZS: np=4; ni= 8; nj= 0; offp=192; break; - case SYS_CMP: np=6; ni=10; nj=24; offp= 1; break; + case SYS_CMP: np=6; ni=10; nj=24; offp= 0; break; case SYS_SBS: np=6; ni= 9; nj=24; offp=120; break; default: return 0; } if (subtype>0) { /* IGS SSR */ np=6; ni=8; nj=0; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + if (sys==SYS_SBS) offp=119; } /* number of satellites */ for (j=nsat=0;j0) { /* IGS SSR */ np=6; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + if (sys==SYS_SBS) offp=119; } /* number of satellites */ for (j=nsat=0;j0) { /* IGS SSR */ + switch (sys) { + case SYS_GPS: np=6; offp= 0; codes=codes_igs_gps; break; + case SYS_GLO: np=6; offp= 0; codes=codes_igs_glo; break; + case SYS_GAL: np=6; offp= 0; codes=codes_igs_gal; break; + case SYS_QZS: np=6; offp=192; codes=codes_igs_qzs; break; + case SYS_CMP: np=6; offp= 0; codes=codes_igs_bds; break; + case SYS_SBS: np=6; offp=119; codes=codes_igs_sbs; break; + default: return 0; + } + } else { + switch (sys) { case SYS_GPS: np=6; offp= 0; codes=codes_gps; break; case SYS_GLO: np=5; offp= 0; codes=codes_glo; break; case SYS_GAL: np=6; offp= 0; codes=codes_gal; break; case SYS_QZS: np=4; offp=192; codes=codes_qzs; break; - case SYS_CMP: np=6; offp= 1; codes=codes_bds; break; + case SYS_CMP: np=6; offp= 0; codes=codes_bds; break; case SYS_SBS: np=6; offp=120; codes=codes_sbs; break; default: return 0; - } - if (subtype>0) { /* IGS SSR */ - np=6; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + } } /* number of satellites */ for (j=nsat=0;j0) { /* IGS SSR */ np=6; ni=8; nj=0; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + if (sys==SYS_SBS) offp=119; } /* number of satellites */ for (j=nsat=0;j0) { /* IGS SSR */ np=6; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + if (sys==SYS_SBS) offp=119; } /* number of satellites */ for (j=nsat=0;j0) { /* IGS SSR */ np=6; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + if (sys==SYS_SBS) offp=119; } /* number of satellites */ for (j=nsat=0;j0) { /* IGS SSR */ + switch (sys) { + case SYS_GPS: np=6; offp= 0; codes=codes_igs_gps; break; + case SYS_GLO: np=6; offp= 0; codes=codes_igs_glo; break; + case SYS_GAL: np=6; offp= 0; codes=codes_igs_gal; break; + case SYS_QZS: np=6; offp=192; codes=codes_igs_qzs; break; + case SYS_CMP: np=6; offp= 0; codes=codes_igs_bds; break; + case SYS_SBS: np=6; offp=119; codes=codes_igs_sbs; break; + default: return 0; + } + } else { + switch (sys) { case SYS_GPS: np=6; offp= 0; codes=codes_gps; break; case SYS_GLO: np=5; offp= 0; codes=codes_glo; break; case SYS_GAL: np=6; offp= 0; codes=codes_gal; break; case SYS_QZS: np=4; offp=192; codes=codes_qzs; break; - case SYS_CMP: np=6; offp= 1; codes=codes_bds; break; + case SYS_CMP: np=6; offp= 0; codes=codes_bds; break; case SYS_SBS: np=6; offp=120; codes=codes_sbs; break; default: return 0; - } - if (subtype>0) { /* IGS SSR */ - np=6; - if (sys==SYS_CMP) offp=0; - else if (sys==SYS_SBS) offp=119; + } } /* number of satellites */ for (j=nsat=0;jssr[j].pbias[codes[k]-1]==0.0) continue; code[nbias]=k; - pbias[nbias ]=ROUND(rtcm->ssr[j].pbias[codes[k]-1]/0.0001); - stdpb[nbias++]=ROUND(rtcm->ssr[j].stdpb[codes[k]-1]/0.0001); + pbias[nbias++]=ROUND(rtcm->ssr[j].pbias[codes[k]-1]/0.0001); } yaw_ang =ROUND(rtcm->ssr[j].yaw_ang /180.0* 256.0); yaw_rate=ROUND(rtcm->ssr[j].yaw_rate/180.0*8192.0); @@ -1901,9 +1934,6 @@ static int encode_ssr7(rtcm_t *rtcm, int sys, int subtype, int sync) setbitu(rtcm->buff,i, 2,0 ); i+= 2; /* WL integer-indicator */ setbitu(rtcm->buff,i, 4,0 ); i+= 4; /* discont counter */ setbits(rtcm->buff,i,20,pbias[k]); i+=20; /* phase bias */ - if (subtype==0) { - setbits(rtcm->buff,i,17,stdpb[k]); i+=17; /* std-dev ph-bias */ - } } } rtcm->nbit=i; @@ -1925,7 +1955,7 @@ static int to_satid(int sys, int sat) static int to_sigid(int sys, uint8_t code) { const char **msm_sig; - char *sig; + const char *sig; int i; /* signal conversion for undefined signal by rtcm */ @@ -1946,7 +1976,7 @@ static int to_sigid(int sys, uint8_t code) case SYS_GAL: msm_sig=msm_sig_gal; break; case SYS_QZS: msm_sig=msm_sig_qzs; break; case SYS_SBS: msm_sig=msm_sig_sbs; break; - case SYS_CMP: msm_sig=msm_sig_cmp; break; + case SYS_CMP: msm_sig=msm_sig_bds; break; case SYS_IRN: msm_sig=msm_sig_irn; break; default: return 0; } @@ -2786,10 +2816,12 @@ extern int encode_rtcm3(rtcm_t *rtcm, int type, int subtype, int sync) case 1261: ret=encode_ssr4(rtcm,SYS_CMP,0,sync); break; /* draft */ case 1262: ret=encode_ssr5(rtcm,SYS_CMP,0,sync); break; /* draft */ case 1263: ret=encode_ssr6(rtcm,SYS_CMP,0,sync); break; /* draft */ - case 11: ret=encode_ssr7(rtcm,SYS_GPS,0,sync); break; /* tentative */ - case 12: ret=encode_ssr7(rtcm,SYS_GAL,0,sync); break; /* tentative */ - case 13: ret=encode_ssr7(rtcm,SYS_QZS,0,sync); break; /* tentative */ - case 14: ret=encode_ssr7(rtcm,SYS_CMP,0,sync); break; /* tentative */ + case 1265: ret=encode_ssr7(rtcm,SYS_GPS,0,sync); break; /* draft */ + case 1266: ret=encode_ssr7(rtcm,SYS_GLO,0,sync); break; /* draft */ + case 1267: ret=encode_ssr7(rtcm,SYS_GAL,0,sync); break; /* draft */ + case 1268: ret=encode_ssr7(rtcm,SYS_QZS,0,sync); break; /* draft */ + case 1269: ret=encode_ssr7(rtcm,SYS_SBS,0,sync); break; /* draft */ + case 1270: ret=encode_ssr7(rtcm,SYS_CMP,0,sync); break; /* draft */ case 4073: ret=encode_type4073(rtcm,subtype,sync); break; case 4076: ret=encode_type4076(rtcm,subtype,sync); break; } diff --git a/src/rtkcmn.c b/src/rtkcmn.c index a4c078da3..bb4ac760c 100644 --- a/src/rtkcmn.c +++ b/src/rtkcmn.c @@ -203,7 +203,7 @@ const double chisqr[100]={ /* chi-sqr(n) (alpha=0.001) */ }; const prcopt_t prcopt_default={ /* defaults processing options */ PMODE_KINEMA,SOLTYPE_FORWARD, /* mode,soltype */ - 2,SYS_GPS|SYS_GLO|SYS_GAL, /* nf, navsys */ + 2,SYS_GPS|SYS_GLO|SYS_GAL|SYS_CMP, /* nf, navsys */ 15.0*D2R,{{0,0}}, /* elmin,snrmask */ 0,3,3,1,0,1, /* sateph,modear,glomodear,gpsmodear,bdsmodear,arfilter */ 20,0,4,5,10,20, /* maxout,minlock,minfixsats,minholdsats,mindropsats,minfix */ @@ -255,8 +255,8 @@ const char *formatstrs[32]={ /* stream format strings */ NULL }; -static char *obscodes[MAXCODE + 1]={ /* observation code strings */ - +// Observation code strings. +static const char *obscodes[MAXCODE + 1]={ "" ,"1C","1P","1W","1Y", "1M","1N","1S","1L","1E", /* 0- 9 */ "1A","1B","1X","1Z","2C", "2D","2S","2L","2X","2P", /* 10-19 */ "2W","2Y","2M","2N","5I", "5Q","5X","7I","7Q","7X", /* 20-29 */ @@ -602,7 +602,7 @@ extern uint8_t obs2code(const char *obs) * return : obs code string ("1C","1P","1P",...) * notes : obs codes are based on RINEX 3.04 *-----------------------------------------------------------------------------*/ -extern char *code2obs(uint8_t code) +extern const char *code2obs(uint8_t code) { if (code<=CODE_NONE||MAXCODE= 0; i--) free(efiles[i]); + return 0; + } } - char buff[256]; - int state = 0; - int utcp = 0, taip = 0; - while (fgets(buff, sizeof(buff), fp)) { - // Detect the IGS format, and support concatenated files. - if (strstr(buff, "version 2") || strstr(buff, "VERSION 2")) { - state = 1; - continue; - } - if (state == 0) { - // Ignore content without firstly seeing the IGS format version. - continue; - } - if (state == 1) { - // IGS format content header search. Data is not read without firstly - // reading the content header line. A version line is detected above, - // and other lines are ignored. Allow some variation in case. - if (strstr(buff, "MJD") || strstr(buff, "mjd") || strstr(buff, "Xpole") || - strstr(buff, "xpole") || strstr(buff, "Ypole") || strstr(buff, "ypole") || - strstr(buff, "UT1") || strstr(buff, "ut1") || strstr(buff, "UTC") || - strstr(buff, "utc") || strstr(buff, "TAI") || strstr(buff, "tai") || - strstr(buff, "LOD") || strstr(buff, "lod")) { - // Note UTC vs TAI. - utcp = !!(strstr(buff, "UTC") || strstr(buff, "utc")); - taip = !!(strstr(buff, "TAI") || strstr(buff, "tai")); - state = 2; - } - continue; - } - if (state == 2) { - // IGS format data search. Detect data lines as containing only - // numeric data. A version line is detected above, and other lines are - // ignored. - int data = 0; - for (size_t i = 0; i < strlen(buff); i++) { - char ch = buff[i]; - if (ch == '\0' || ch == '\r' || ch == '\n') break; - if (ch == '.' || ch == '-' || ch == '+' || ch == ' ' || ch == '\t') continue; - if (ch < '0' || ch > '9') { - data = 0; - break; - } - data = 1; + // Expand wild card in file path. + int n = expath(file, efiles, MAXEXFILE), nr = 0; + + for (int i = 0; i < n; i++) { + char *ext = strrchr(efiles[i], '.'); + if (!ext) continue; + + if (!strstr(ext,".erp") && !strstr(ext,".ERP")) continue; + + FILE *fp = fopen(efiles[i], "r"); + if (!fp) { + trace(2, "erp file open error: file=%s\n", efiles[i]); + for (int j = 0; j < MAXEXFILE; j++) free(efiles[j]); + return 0; + } + char buff[256]; + int state = 0; + int utcp = 0, taip = 0, nerp = 0; + while (fgets(buff, sizeof(buff), fp)) { + // Detect the IGS format, and support concatenated files. + if (strstr(buff, "version 2") || strstr(buff, "VERSION 2")) { + state = 1; + continue; } - if (!data) continue; - double v[14] = {0}; - if (sscanf(buff, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", v, v + 1, v + 2, - v + 3, v + 4, v + 5, v + 6, v + 7, v + 8, v + 9, v + 10, v + 11, v + 12, - v + 13) < 5) { + if (state == 0) { + // Ignore content without firstly seeing the IGS format version. continue; } - if (erp->n >= erp->nmax) { - erp->nmax = erp->nmax <= 0 ? 128 : erp->nmax * 2; - erpd_t *erp_data = (erpd_t *)realloc(erp->data, sizeof(erpd_t) * erp->nmax); - if (erp_data == NULL) { - free(erp->data); - erp->data = NULL; - erp->n = erp->nmax = 0; - fclose(fp); - return 0; + if (state == 1) { + // IGS format content header search. Data is not read without firstly + // reading the content header line. A version line is detected above, + // and other lines are ignored. Allow some variation in case. + if (strstr(buff, "MJD") || strstr(buff, "mjd") || strstr(buff, "Xpole") || + strstr(buff, "xpole") || strstr(buff, "Ypole") || strstr(buff, "ypole") || + strstr(buff, "UT1") || strstr(buff, "ut1") || strstr(buff, "UTC") || + strstr(buff, "utc") || strstr(buff, "TAI") || strstr(buff, "tai") || + strstr(buff, "LOD") || strstr(buff, "lod")) { + // Note UTC vs TAI. + utcp = !!(strstr(buff, "UTC") || strstr(buff, "utc")); + taip = !!(strstr(buff, "TAI") || strstr(buff, "tai")); + state = 2; } - erp->data = erp_data; + continue; } - erp->data[erp->n].mjd = v[0]; - erp->data[erp->n].xp = v[1] * 1E-6 * AS2R; - erp->data[erp->n].yp = v[2] * 1E-6 * AS2R; - erp->data[erp->n].ut1_utc = v[3] * 1E-7; - (void)utcp; - if (taip) { - // Convert UT1-TAI to UT1-UTC. - const double ep[] = {2000, 1, 1, 12, 0, 0}; - gtime_t tutc = timeadd(epoch2time(ep), (v[0] - 51544.5) * 86400.0); - erp->data[erp->n].ut1_utc += timediff(utc2gpst(tutc), tutc) + 19; + if (state == 2) { + // IGS format data search. Detect data lines as containing only + // numeric data. A version line is detected above, and other lines are + // ignored. + int data = 0; + for (size_t i = 0; i < strlen(buff); i++) { + char ch = buff[i]; + if (ch == '\0' || ch == '\r' || ch == '\n') break; + if (ch == '.' || ch == '-' || ch == '+' || ch == ' ' || ch == '\t') continue; + if (ch < '0' || ch > '9') { + data = 0; + break; + } + data = 1; + } + if (!data) continue; + double v[14] = {0}; + if (sscanf(buff, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", v, v + 1, v + 2, + v + 3, v + 4, v + 5, v + 6, v + 7, v + 8, v + 9, v + 10, v + 11, v + 12, + v + 13) < 5) { + continue; + } + if (erp->n >= erp->nmax) { + erp->nmax = erp->nmax <= 0 ? 128 : erp->nmax * 2; + erpd_t *erp_data = (erpd_t *)realloc(erp->data, sizeof(erpd_t) * erp->nmax); + if (erp_data == NULL) { + free(erp->data); + erp->data = NULL; + erp->n = erp->nmax = 0; + fclose(fp); + for (int j = 0; j < MAXEXFILE; j++) free(efiles[j]); + return 0; + } + erp->data = erp_data; + } + erp->data[erp->n].mjd = v[0]; + erp->data[erp->n].xp = v[1] * 1E-6 * AS2R; + erp->data[erp->n].yp = v[2] * 1E-6 * AS2R; + erp->data[erp->n].ut1_utc = v[3] * 1E-7; + (void)utcp; + if (taip) { + // Convert UT1-TAI to UT1-UTC. + const double ep[] = {2000, 1, 1, 12, 0, 0}; + gtime_t tutc = timeadd(epoch2time(ep), (v[0] - 51544.5) * 86400.0); + erp->data[erp->n].ut1_utc += timediff(utc2gpst(tutc), tutc) + 19; + } + erp->data[erp->n].lod = v[4] * 1E-7; + erp->data[erp->n].xpr = v[12] * 1E-6 * AS2R; + erp->data[erp->n++].ypr = v[13] * 1E-6 * AS2R; + nerp++; } - erp->data[erp->n].lod = v[4] * 1E-7; - erp->data[erp->n].xpr = v[12] * 1E-6 * AS2R; - erp->data[erp->n++].ypr = v[13] * 1E-6 * AS2R; } + if (nerp > 0) nr++; + fclose(fp); } - fclose(fp); - return 1; + for (int j = 0; j < MAXEXFILE; j++) free(efiles[j]); + return nr; } /* get earth rotation parameter values ----------------------------------------- * get earth rotation parameter values @@ -3136,7 +3160,7 @@ extern int readnav(const char *file, nav_t *nav) eph_t eph0={0}; geph_t geph0={0}; char buff[4096],*p; - long toe_time,tof_time,toc_time,ttr_time; + long unsigned toe_time,tof_time,toc_time,ttr_time; int i,sat,prn; trace(3,"loadnav: file=%s\n",file); @@ -3160,7 +3184,7 @@ extern int readnav(const char *file, nav_t *nav) nav->geph[prn-1]=geph0; nav->geph[prn-1].sat=sat; toe_time=tof_time=0; - (void)sscanf(p+1,"%d,%d,%d,%d,%d,%d,%ld,%ld,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf," + (void)sscanf(p+1,"%d,%d,%d,%d,%d,%d,%lu,%lu,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf," "%lf,%lf,%lf,%lf", &nav->geph[prn-1].iode,&nav->geph[prn-1].frq,&nav->geph[prn-1].svh, &nav->geph[prn-1].flags,&nav->geph[prn-1].sva,&nav->geph[prn-1].age, @@ -3176,7 +3200,7 @@ extern int readnav(const char *file, nav_t *nav) nav->eph[sat-1]=eph0; nav->eph[sat-1].sat=sat; toe_time=toc_time=ttr_time=0; - (void)sscanf(p+1,"%d,%d,%d,%d,%ld,%ld,%ld,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf," + (void)sscanf(p+1,"%d,%d,%d,%d,%lu,%lu,%lu,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf," "%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%d,%d", &nav->eph[sat-1].iode,&nav->eph[sat-1].iodc,&nav->eph[sat-1].sva , &nav->eph[sat-1].svh , @@ -3210,12 +3234,12 @@ extern int savenav(const char *file, const nav_t *nav) for (i=0;ieph[i].ttr.time==0) continue; satno2id(nav->eph[i].sat,id); - fprintf(fp,"%s,%d,%d,%d,%d,%d,%d,%d,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E," + fprintf(fp,"%s,%d,%d,%d,%d,%lu,%lu,%lu,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E," "%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E," "%.14E,%.14E,%.14E,%.14E,%.14E,%d,%d\n", id,nav->eph[i].iode,nav->eph[i].iodc,nav->eph[i].sva , - nav->eph[i].svh ,(int)nav->eph[i].toe.time, - (int)nav->eph[i].toc.time,(int)nav->eph[i].ttr.time, + nav->eph[i].svh ,(long unsigned)nav->eph[i].toe.time, + (long unsigned)nav->eph[i].toc.time,(long unsigned)nav->eph[i].ttr.time, nav->eph[i].A ,nav->eph[i].e ,nav->eph[i].i0 ,nav->eph[i].OMG0, nav->eph[i].omg ,nav->eph[i].M0 ,nav->eph[i].deln,nav->eph[i].OMGd, nav->eph[i].idot,nav->eph[i].crc,nav->eph[i].crs ,nav->eph[i].cuc , @@ -3226,12 +3250,12 @@ extern int savenav(const char *file, const nav_t *nav) for (i=0;igeph[i].tof.time==0) continue; satno2id(nav->geph[i].sat,id); - fprintf(fp,"%s,%d,%d,%d,%d,%d,%d,%d,%d,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E," + fprintf(fp,"%s,%d,%d,%d,%d,%d,%d,%lu,%lu,%.14E,%.14E,%.14E,%.14E,%.14E,%.14E," "%.14E,%.14E,%.14E,%.14E,%.14E,%.14E\n", id,nav->geph[i].iode,nav->geph[i].frq,nav->geph[i].svh, nav->geph[i].flags, - nav->geph[i].sva,nav->geph[i].age,(int)nav->geph[i].toe.time, - (int)nav->geph[i].tof.time, + nav->geph[i].sva,nav->geph[i].age,(long unsigned)nav->geph[i].toe.time, + (long unsigned)nav->geph[i].tof.time, nav->geph[i].pos[0],nav->geph[i].pos[1],nav->geph[i].pos[2], nav->geph[i].vel[0],nav->geph[i].vel[1],nav->geph[i].vel[2], nav->geph[i].acc[0],nav->geph[i].acc[1],nav->geph[i].acc[2], @@ -3740,8 +3764,8 @@ extern double ionppp(const double *pos, const double *azel, double re, /* select iono-free linear combination (L1/L2 or L1/L5) ----------------------*/ extern int seliflc(int optnf,int sys) { - /* use L1/L5 for Galileo if L5 is enabled */ - return((optnf==2||sys!=SYS_GAL)?1:2); + /* use L1/L5 for GPS,GAL,BDS if L5 is enabled */ + return((optnf==2||sys==SYS_GLO)?1:2); } /* troposphere model ----------------------------------------------------------- * compute tropospheric delay by standard atmosphere and saastamoinen model diff --git a/src/rtklib.h b/src/rtklib.h index 55149be8e..276e659cd 100644 --- a/src/rtklib.h +++ b/src/rtklib.h @@ -55,8 +55,10 @@ extern "C" { #ifdef _MSC_VER #ifdef WIN_DLL /* for Windows DLL */ #define EXPORT __declspec(dllexport) -#else +#elif !defined(WIN_STATIC) #define EXPORT __declspec(dllimport) +#else +#define EXPORT // For files bundled into an app. #endif #else #define EXPORT @@ -67,7 +69,7 @@ extern "C" { #elif defined(__GNUC__) #define THREADLOCAL __thread #elif defined(_MSC_VER) -#define THREADLOCAL __declspec(__thread) +#define THREADLOCAL __declspec(thread) #else #define THREADLOCAL #endif @@ -76,7 +78,7 @@ extern "C" { #define VER_RTKLIB "EX" /* library version */ -#define PATCH_LEVEL "2.5.0" /* patch level */ +#define PATCH_LEVEL "2.5.1" /* patch level */ #define COPYRIGHT_RTKLIB \ "Copyright (C) 2007-2020 T.Takasu\nAll rights reserved." @@ -562,7 +564,11 @@ extern "C" { #define rtklib_unlock(f) LeaveCriticalSection(f) #define RTKLIB_FILEPATHSEP '\\' /* strtok_r not supported in Windows */ +#ifdef _MSC_VER +#define strtok_r(str,delim,ptr) strtok_s(str,delim,ptr) +#else #define strtok_r(str,delim,ptr) strtok(str,delim) +#endif #else #define rtklib_thread_t pthread_t #define rtklib_lock_t pthread_mutex_t @@ -753,6 +759,18 @@ typedef struct { /* TEC grid type */ float *rms; /* RMS values (tecu) */ } tec_t; +typedef struct { + double udint; + double qi; + int iod; + int nlay; + int nmax[4]; + int mmax[4]; + double hgt[4]; + double cosC[4][16][16]; + double sinC[4][16][16]; +} vtec_t; + typedef struct { /* SBAS message type */ int week,tow; /* reception time */ uint8_t prn,rcv; /* SBAS satellite PRN,receiver number */ @@ -837,7 +855,6 @@ typedef struct { /* SSR correction type */ double hrclk; /* high-rate clock correction (m) */ float cbias[MAXCODE]; /* code biases (m) */ double pbias[MAXCODE]; /* phase biases (m) */ - float stdpb[MAXCODE]; /* std-dev of phase biases (m) */ double yaw_ang,yaw_rate; /* yaw angle and yaw rate (deg,deg/s) */ uint8_t update; /* update flag (0:no update,1:update) */ } ssr_t; @@ -872,6 +889,7 @@ typedef struct { /* navigation data type */ double ion_irn[8]; /* IRNSS iono model parameters {a0,a1,a2,a3,b0,b1,b2,b3} */ int glo_fcn[32]; /* GLONASS FCN + 8 */ double cbias[MAXSAT][NFREQ][MAX_CODE_BIASES]; /* satellite code biases] (m) */ + vtec_t vtec; /* ionosphere VTEC coefficients */ pcv_t pcvs[MAXSAT]; /* satellite antenna pcv */ sbssat_t sbssat; /* SBAS satellite corrections */ sbsion_t sbsion[MAXBAND+1]; /* SBAS ionosphere corrections */ @@ -1222,8 +1240,9 @@ typedef struct { /* RTK control/result type */ prcopt_t opt; /* processing options */ int initial_mode; /* initial positioning mode */ int epoch; /* epoch number */ - int intpres_nb; // Time interpolation of residuals, number of previous base observations. - obsd_t intpres_obsb[MAXOBS]; // Time interpolation of residuals, previous base observations. + int intpres_nb; /* Time interpolation of residuals, number of previous base observations */ + int vtec_used; /* indicates VTEC coeffs have been used to init ion states */ + obsd_t intpres_obsb[MAXOBS]; /* Time interpolation of residuals, previous base observations */ } rtk_t; typedef struct { /* receiver raw data control type */ @@ -1240,7 +1259,6 @@ typedef struct { /* receiver raw data control type */ uint8_t subfrm[MAXSAT][380]; /* subframe buffer */ double lockt[MAXSAT][NFREQ+NEXOBS]; /* lock time (s) */ unsigned char lockflag[MAXSAT][NFREQ+NEXOBS]; /* used for carrying forward cycle slip */ - double icpp[MAXSAT],off[MAXSAT],icpc; /* carrier params for ss2 */ double prCA[MAXSAT],dpCA[MAXSAT]; /* L1/CA pseudorange/doppler for javad */ uint8_t halfc[MAXSAT][NFREQ+NEXOBS]; /* half-cycle resolved */ char freqn[MAXOBS]; /* frequency number for javad */ @@ -1393,7 +1411,7 @@ EXPORT int satsys (int sat, int *prn); EXPORT int satid2no(const char *id); EXPORT void satno2id(int sat, char id[8]); EXPORT uint8_t obs2code(const char *obs); -EXPORT char *code2obs(uint8_t code); +EXPORT const char *code2obs(uint8_t code); EXPORT double code2freq(int sys, uint8_t code, int fcn); EXPORT double sat2freq(int sat, uint8_t code, const nav_t *nav); EXPORT int code2idx(int sys, uint8_t code); @@ -1571,6 +1589,8 @@ EXPORT int iontec(gtime_t time, const nav_t *nav, const double *pos, EXPORT void readtec(const char *file, nav_t *nav, int opt); EXPORT int ionocorr(gtime_t time, const nav_t *nav, int sat, const double *pos, const double *azel, int ionoopt, double *ion, double *var); +EXPORT int ionvtec(gtime_t time, const nav_t *nav, const double *pos, + const double *azel, double freq, double *delay, double *var); EXPORT int tropcorr(gtime_t time, const nav_t *nav, const double *pos, const double *azel, int tropopt, double *trp, double *var); EXPORT int seliflc(int optnf, int sys); @@ -1859,7 +1879,7 @@ EXPORT int rtkoutstat(rtk_t *rtk, int level, char *buff); /* precise point positioning -------------------------------------------------*/ EXPORT void pppos(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav); EXPORT int pppnx(const prcopt_t *opt); -EXPORT int pppoutstat(rtk_t *rtk, char *buff); +EXPORT int pppoutstat(rtk_t *rtk, char *buff, int level); EXPORT int ppp_ar(rtk_t *rtk, const obsd_t *obs, int n, int *exc, const nav_t *nav, const double *azel, double *x, double *P); @@ -1897,8 +1917,8 @@ EXPORT int rtksvropenstr(rtksvr_t *svr, int index, int str, const char *path, EXPORT void rtksvrclosestr(rtksvr_t *svr, int index); EXPORT void rtksvrlock (rtksvr_t *svr); EXPORT void rtksvrunlock(rtksvr_t *svr); -EXPORT int rtksvrostat (rtksvr_t *svr, int type, gtime_t *time, int *sat, - double *az, double *el, int **snr, int *vsat); +EXPORT int rtksvrostat (rtksvr_t *svr, int type, gtime_t *time, int sat[MAXSAT], + double *az, double *el, int snr[MAXSAT][NFREQ], int vsat[MAXSAT][NFREQ]); EXPORT void rtksvrsstat (rtksvr_t *svr, int *sstat, char *msg); EXPORT int rtksvrmark(rtksvr_t *svr, const char *name, const char *comment); diff --git a/src/rtkpos.c b/src/rtkpos.c index 8ebc15939..3e86fe0d4 100644 --- a/src/rtkpos.c +++ b/src/rtkpos.c @@ -231,7 +231,7 @@ extern int rtkoutstat(rtk_t *rtk, int level, char *buff) if (rtk->opt.mode>=PMODE_PPP_KINEMA) { /* Write ppp solution status to buffer */ - p+=pppoutstat(rtk,buff); + p+=pppoutstat(rtk,buff,level); } else { /* Receiver position */ if (est) { @@ -300,23 +300,22 @@ extern int rtkoutstat(rtk_t *rtk, int level, char *buff) rtk->sol.stat,i+1,rtk->x[j],xa[0]); } } - } - - if (level <= 1) return (int)(p-buff); - - /* Write residuals and status */ - for (int i=0;issat+i; - if (!ssat->vs) continue; - satno2id(i+1,id); - for (int j=0;jopt); - p+=sprintf(p,"$SAT,%d,%.3f,%s,%d,%.1f,%.1f,%.4f,%.4f,%d,%.0f,%d,%d,%d,%u,%u,%u,%.2f,%.6f,%.5f\n", - week,tow,id,j+1,ssat->azel[0]*R2D,ssat->azel[1]*R2D, - ssat->resp[j],ssat->resc[j],ssat->vsat[j],ssat->snr_rover[j], - ssat->fix[j],ssat->slip[j]&(LLI_SLIP|LLI_HALFC),ssat->lock[j],ssat->outc[j], - ssat->slipc[j],ssat->rejc[j],knx?rtk->x[k]:0, - knx?rtk->P[k+k*rtk->nx]:0,ssat->icbias[j]); + if (level <= 1) return (int)(p-buff); + + /* Write residuals and status */ + for (int i=0;issat+i; + if (!ssat->vs) continue; + satno2id(i+1,id); + for (int j=0;jopt); + p+=sprintf(p,"$SAT,%d,%.3f,%s,%d,%.1f,%.1f,%.4f,%.4f,%d,%.0f,%d,%d,%d,%u,%u,%u,%.2f,%.6f,%.5f\n", + week,tow,id,j+1,ssat->azel[0]*R2D,ssat->azel[1]*R2D, + ssat->resp[j],ssat->resc[j],ssat->vsat[j],ssat->snr_rover[j], + ssat->fix[j],ssat->slip[j]&(LLI_SLIP|LLI_HALFC),ssat->lock[j],ssat->outc[j], + ssat->slipc[j],ssat->rejc[j],knx?rtk->x[k]:0, + knx?rtk->P[k+k*rtk->nx]:0,ssat->icbias[j]); + } } } @@ -750,54 +749,74 @@ static void detslp_gf(rtk_t *rtk, const obsd_t *obs, int i, int j, } } } +static int cmpdop(const void *dop1, const void *dop2) { + double d1 = *(const double *)dop1; + double d2 = *(const double *)dop2; + return (d1 > d2) - (d1 < d2); +} /* detect cycle slip by doppler and phase difference -------------------------*/ static void detslp_dop(rtk_t *rtk, const obsd_t *obs, const int *ix, int ns, int rcv, const nav_t *nav) { - (void)nav; int i,ii,f,sat,ndop=0,nf=rtk->opt.nf; - double dph,dpt,mean_dop=0; + double dph,dpt,lam,med_dop; double dopdif[MAXSAT][NFREQ], tt[MAXSAT][NFREQ]; + double doplist[MAXSAT*NFREQ]; trace(4,"detslp_dop: rcv=%d\n", rcv); + if (rtk->opt.thresdop<=0) return; /* skip test if doppler thresh <= 0 */ - /* calculate doppler differences for all sats and freqs */ - for (i=0;issat[sat-1].ph[rcv-1][f]==0.0) continue; - if (fabs(tt[i][f]=timediff(obs[ii].time,rtk->ssat[sat-1].pt[rcv-1][f]))ssat[sat-1].ph[rcv-1][f]==0.0) continue; - /* calc phase difference and doppler x time (cycle) */ - dph=(obs[ii].L[f]-rtk->ssat[sat-1].ph[rcv-1][f])/tt[i][f]; + tt[i][f]=timediff(obs[ii].time, + rtk->ssat[sat-1].pt[rcv-1][f]); + + if (fabs(tt[i][f])ssat[sat-1].ph[rcv-1][f])/tt[i][f]; dpt=-obs[ii].D[f]; - dopdif[i][f]=dph-dpt; - /* if not outlier, use this to calculate mean */ - if (fabs(dopdif[i][f])<3*rtk->opt.thresdop) { - mean_dop+=dopdif[i][f]; - ndop++; + /* convert to m/s for consistent scaling across frequencies */ + dopdif[i][f]=(dph-dpt)*lam; + doplist[ndop++]=dopdif[i][f]; } } - } - /* calc mean doppler diff, most likely due to clock error */ - if (ndop==0) return; /* unable to calc mean doppler, usually very large clock err */ - mean_dop=mean_dop/ndop; + if (ndop==0) return; - /* set slip if doppler difference with mean removed exceeds threshold */ + /* median common range-rate error */ + qsort(doplist, ndop, sizeof(double), cmpdop); + /* calc median doppler diff, most likely due to clock error */ + med_dop=ndop%2?doplist[ndop/2]: + (doplist[ndop/2-1]+doplist[ndop/2])/2.0; + + /* set slip if corrected phase-doppler rate exceeds threshold */ for (i=0;irtk->opt.thresdop) { + if (tt[i][f]==0.0) continue; + if (fabs(dopdif[i][f]-med_dop)>rtk->opt.thresdop) { rtk->ssat[sat-1].slip[f]|=LLI_SLIP; + errmsg(rtk,"slip detected doppler (sat=%2d rcv=%d dL%d=%.3f off=%.3f tt=%.2f)\n", - sat,rcv,f+1,dopdif[i][f]-mean_dop,mean_dop,tt[i][f]); + sat,rcv,f+1,dopdif[i][f]-med_dop,med_dop,tt[i][f]); } } } @@ -817,8 +836,9 @@ static void udbias(rtk_t *rtk, double tt, const obsd_t *obs, const int *sat, } /* detect cycle slip by doppler and phase difference */ - detslp_dop(rtk,obs,iu,ns,1,nav); - detslp_dop(rtk,obs,ir,ns,2,nav); + detslp_dop(rtk,obs,iu,ns,1,nav); // rover + if (rtk->opt.mode==PMODE_MOVEB) // only check base if moving baseline + detslp_dop(rtk,obs,ir,ns,2,nav); for (i=0;iopt; double bl,dr[3],posu[3],posr[3],didxi=0.0,didxj=0.0,*im; double *tropr,*tropu,*dtdxr,*dtdxu,*Ri,*Rj,freqi,freqj,*Hi=NULL,df; + double refvar,minvar; int i,j,k,m,f,nv=0,nb[NFREQ*NSYS*2+2]={0},b=0,sysi,sysj,nf=NF(opt); int frq,code; @@ -1255,14 +1276,44 @@ static int ddres(rtk_t *rtk, const obsd_t *obs, double dt, const double *x, for (f=opt->mode>PMODE_DGPS?0:nf;fssat[sat[j]-1].sys; - if (!test_sys(sysi,m) || sysi==SYS_SBS) continue; + sysj=rtk->ssat[sat[j]-1].sys; + + if (!test_sys(sysj,m) || sysj==SYS_SBS) continue; if (!validobs(iu[j],ir[j],f,nf,y)) continue; - /* skip sat with slip unless no other valid sat */ - if (i>=0&&rtk->ssat[sat[j]-1].slip[frq]&LLI_SLIP) continue; - if (i<0||azel[1+iu[j]*2]>=azel[1+iu[i]*2]) i=j; + if (rtk->ssat[sat[j]-1].slip[frq]&LLI_SLIP) continue; + if (rtk->ssat[sat[j]-1].lock[frq]<0) continue; + + refvar=varerr(sat[j],sysj,azel[1+iu[j]*2], + rtk->ssat[sat[j]-1].snr_rover[frq], + rtk->ssat[sat[j]-1].snr_base[frq], + bl,dt,f,opt,&obs[iu[j]]); + if (i<0||refvarssat[sat[j]-1].sys; + + if (!test_sys(sysj,m)||sysj==SYS_SBS) continue; + if (!validobs(iu[j],ir[j],f,nf,y)) continue; + + refvar=varerr(sat[j],sysj,azel[1+iu[j]*2], + rtk->ssat[sat[j]-1].snr_rover[frq], + rtk->ssat[sat[j]-1].snr_base[frq], + bl,dt,f,opt,&obs[iu[j]]); + if (i<0||refvarnx-rtk->na,nv=0,nf=NF(&rtk->opt); + int i,j,n,m,f,info,index[MAXSAT]; + int sat[MAXSAT],nb=rtk->nx-rtk->na,nv=0,ns=0,nf=NF(&rtk->opt); + int used[MAXSAT]={0}; double dd; trace(3,"holdamb :\n"); @@ -1618,8 +1671,17 @@ static void holdamb(rtk_t *rtk, const double *xa) rtk->ssat[i].azel[1]opt.elmaskhold) { continue; } - index[n++]=IB(i+1,f,&rtk->opt); - rtk->ssat[i].fix[f]=3; /* hold */ + index[n]=IB(i+1,f,&rtk->opt); + sat[n++]=i; + } + if (n<2) continue; /* need at least two sats to form a double difference */ + /* mark and count unique sats actually used for hold */ + for (i=0;issat[sat[i]].fix[f]=3; /* hold */ + if (!used[sat[i]]) { + used[sat[i]]=1; + ns++; + } } /* use ambiguity resolution results to generate a set of pseudo-innovations to feed to kalman filter based on error between fixed and float solutions */ @@ -1634,8 +1696,9 @@ static void holdamb(rtk_t *rtk, const double *xa) } } /* return if less than min sats for hold (skip if fix&hold for GLONASS only) */ - if (rtk->opt.modear==ARMODE_FIXHOLD&&nvopt.minholdsats) { - trace(3,"holdamb: not enough sats to hold ambiguity\n"); + if (rtk->opt.modear==ARMODE_FIXHOLD&&nsopt.minholdsats) { + trace(3,"holdamb: not enough sats to hold ambiguity (ns=%d min=%d nv=%d)\n", + ns,rtk->opt.minholdsats,nv); free(v); free(H); return; } @@ -1713,8 +1776,21 @@ static int resamb_LAMBDA(rtk_t *rtk, double *bias, double *xa,int gps,int glo,in /* Create index of single to double-difference transformation matrix (D') used to translate phase biases to double difference */ ix=imat(nx,2); - if ((nb=ddidx(rtk,ix,gps,glo,sbs))<(rtk->opt.minfixsats-1)) { /* nb is sat pairs */ - errmsg(rtk,"not enough valid double-differences\n"); + nb=ddidx(rtk,ix,gps,glo,sbs); + + /* count unique sats used for AR on at least one frequency */ + int ns=0,f; + for (i=0;issat[i].fix[f]==2) { + ns++; + break; + } + } + } + if (nb<=0||nsminfixsats) { + errmsg(rtk,"not enough valid sats for AR: ns=%d min=%d\n", + ns,opt->minfixsats); free(ix); return -1; /* flag abort */ } @@ -1847,8 +1923,16 @@ static int manage_amb_LAMBDA(rtk_t *rtk, double *bias, double *xa, const int *sa return 0; } // If no fix on previous sample and enough sats, exclude next sat in list. - int lockc[NFREQ], excsat = 0; - if (rtk->sol.prev_ratio2 < rtk->sol.thres && rtk->nb_ar >= rtk->opt.mindropsats) { + int lockc[NFREQ],excsat=0,nbsat=0; + for (int i=0;issat[sat[i]-1].fix[f]==2) { + nbsat++; + break; + } + } + } + if (rtk->sol.prev_ratio2sol.thres&&nbsat>=rtk->opt.mindropsats) { // Find the position of the last excluded sat. int i = 0; if (rtk->excsat != 0) { @@ -1885,7 +1969,10 @@ static int manage_amb_LAMBDA(rtk_t *rtk, double *bias, double *xa, const int *sa /* for inital ambiguity resolution attempt, include all enabled sats */ gps1=1; /* always enable gps for initial pass */ - glo1=(rtk->opt.navsys&SYS_GLO)?(((rtk->opt.glomodear==GLO_ARMODE_FIXHOLD)&&!rtk->holdamb)?0:1):0; + /* enable GLO AR if configured and FIXHOLD has acquired hold */ + glo1 = (rtk->opt.navsys & SYS_GLO) && + rtk->opt.glomodear != GLO_ARMODE_OFF && + (rtk->opt.glomodear != GLO_ARMODE_FIXHOLD || rtk->holdamb); sbas1=(rtk->opt.navsys&SYS_GLO)?glo1:((rtk->opt.navsys&SYS_SBS)?1:0); /* first attempt to resolve ambiguities */ nb=resamb_LAMBDA(rtk,bias,xa,gps1,glo1,sbas1); @@ -2100,13 +2187,13 @@ static int relpos(rtk_t *rtk, const obsd_t *obs, int nu, int nr, K=P*H*(H'*P*H+R)^-1 xp=x+K*v Pp=(I-K*H')*P */ - trace(3,"before filter x=");tracemat(3,rtk->x,1,9,13,6); + trace(3,"before filter x=");tracemat(3,rtk->x,1,NP(opt),13,6); if ((info=filter(xp,Pp,H,v,R,rtk->nx,nv))) { errmsg(rtk,"filter error (info=%d)\n",info); stat=SOLQ_NONE; break; } - trace(3,"after filter x=");tracemat(3,xp,1,9,13,6); + trace(3,"after filter x=");tracemat(3,xp,1,NP(opt),13,6); trace(4,"x(%d)=",i+1); tracemat(4,xp,1,NR(opt),13,4); } /* calc zero diff residuals again after kalman filter update */ @@ -2359,6 +2446,7 @@ extern int rtkpos(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav) opt->mode!=PMODE_MOVEB) { for (i=0;i<6;i++) rtk->rb[i]=i<3?opt->rb[i]:0.0; } + /* count rover/base station observations */ for (nu=0;nu toc,eph2->toc)!=0.0)) { *eph3=*eph2; /* current ->previous */ *eph2=*eph1; /* received->current */ + trace(4,"update_eph: sat=%d iode %d->%d\n",ephsat,eph3->iode,eph2->iode); } } svr->nmsg[index][1]++; @@ -211,7 +212,8 @@ static void update_eph(rtksvr_t *svr, nav_t *nav, int ephsat, int ephset, (geph1->iode!=geph3->iode&&geph1->iode!=geph2->iode)) { *geph3=*geph2; *geph2=*geph1; - update_glofcn(svr); + update_glofcn(svr); + trace(4,"update_eph: sat=%d iode %d->%d\n",ephsat,geph3->iode,geph2->iode); } } svr->nmsg[index][6]++; @@ -262,16 +264,15 @@ static void update_antpos(rtksvr_t *svr, int index) { } else { sta = &svr->raw[index].sta; } - if (index == 1 && svr->rtk.opt.refpos == POSOPT_RTCM) { + if (index == 1 && svr->rtk.opt.refpos == POSOPT_RTCM && norm(sta->pos, 3) > RE_WGS84 / 2) { // Update base station position. for (int i = 0; i < 3; i++) svr->rtk.rb[i] = sta->pos[i]; tracet(2, "updated antenna index=%d position to %.4f %.4f %.4f\n", index, svr->rtk.rb[0], svr->rtk.rb[1], svr->rtk.rb[2]); } - if (index == 0 && svr->rtk.opt.rovpos == POSOPT_RTCM && - (svr->rtk.opt.mode == PMODE_FIXED || svr->rtk.opt.mode == PMODE_PPP_FIXED)) { + if (index == 0 && svr->rtk.opt.rovpos == POSOPT_RTCM && norm(sta->pos, 3) > RE_WGS84 / 2) { // Update rover fixed position. for (int i = 0; i < 3; i++) svr->rtk.opt.ru[i] = sta->pos[i]; - tracet(2, "updated antenna index=%d position to %.4f %.4f %.4f\n", index, svr->rtk.rb[0], svr->rtk.rb[1], svr->rtk.rb[2]); + tracet(2, "updated antenna index=%d default position to %.4f %.4f %.4f\n", index, svr->rtk.opt.ru[0], svr->rtk.opt.ru[1], svr->rtk.opt.ru[2]); } // Antenna type and delta. These are updated independently of the antenna @@ -312,37 +313,50 @@ static void update_antpos(rtksvr_t *svr, int index) { /* update ssr corrections ----------------------------------------------------*/ static void update_ssr(rtksvr_t *svr, int index) { - int i,sys,prn,iode; + for (int i=0;irtcm[index].ssr[i].update) continue; + svr->rtcm[index].ssr[i].update=0; // just check once per update - for (i=0;irtcm[index].ssr[i].update) continue; - - /* check consistency between iods of orbit and clock */ - if (svr->rtcm[index].ssr[i].iod[0]!=svr->rtcm[index].ssr[i].iod[1]) { + // Check consistency between iods of orbit and clock. + if (svr->rtcm[index].ssr[i].iod[0]!=svr->rtcm[index].ssr[i].iod[1]) continue; - } - svr->rtcm[index].ssr[i].update=0; - - iode=svr->rtcm[index].ssr[i].iode; - sys=satsys(i+1,&prn); - - /* check corresponding ephemeris exists */ - if (sys==SYS_GPS||sys==SYS_GAL||sys==SYS_QZS) { - if (svr->nav.eph[i ].iode!=iode&& - svr->nav.eph[i+MAXSAT].iode!=iode) { - continue; - } + + // Check consistency of iode between ssr and broadcast. + int ssr_iode=svr->rtcm[index].ssr[i].iode, iode=-1; + if (ssr_iode<0) continue; + int prn; + if (satsys(sat, &prn)!=SYS_GLO) { + eph_t *eph=svr->nav.eph+i; + if (eph->sat==sat&&ssr_iode==eph->iode) // check current ephemeris + iode=eph->iode; + else { // check previous ephemeris + eph=svr->nav.eph+i+2*MAXSAT; + if (eph->sat==sat&&ssr_iode==eph->iode) + iode=eph->iode; } - else if (sys==SYS_GLO) { - if (svr->nav.geph[prn-1 ].iode!=iode&& - svr->nav.geph[prn-1+MAXPRNGLO].iode!=iode) { - continue; - } + } else { // SYS_GLO + geph_t *geph=svr->nav.geph+prn-1; + if (geph->sat==sat&&ssr_iode==geph->iode) + iode=geph->iode; + else { // check previous ephemeris + geph=svr->nav.geph+prn-1+MAXPRNGLO; + if (geph->sat==sat&&ssr_iode==geph->iode) + iode=geph->iode; } - svr->nav.ssr[i]=svr->rtcm[index].ssr[i]; } - svr->nmsg[index][7]++; + if (iode!=-1) { + if (svr->nav.ssr[i].iode!=ssr_iode) { + trace(4,"update_ssr_iode: sat=%d %d->%d\n",sat,svr->nav.ssr[i].iode,ssr_iode); + } + svr->nav.ssr[i]=svr->rtcm[index].ssr[i]; + } } + svr->nmsg[index][7]++; + + /* update vtec */ + svr->nav.vtec=svr->rtcm[index].nav.vtec; +} /* update rtk server struct --------------------------------------------------*/ static void update_svr(rtksvr_t *svr, int ret, obs_t *obs, nav_t *nav, int ephsat, int ephset, sbsmsg_t *sbsmsg, int index, @@ -556,7 +570,7 @@ static double baseline_len(const rtk_t *rtk) double dr[3]; int i; - if (norm(rtk->sol.rr,3)<=0.0||norm(rtk->rb,3)<=0.0) return 0.0; + if (norm(rtk->sol.rr,3) <= RE_WGS84 / 2 || norm(rtk->rb,3) <= RE_WGS84 / 2) return 0.0; for (i=0;i<3;i++) { dr[i]=rtk->sol.rr[i]-rtk->rb[i]; @@ -567,30 +581,28 @@ static double baseline_len(const rtk_t *rtk) static void send_nmea(rtksvr_t *svr, uint32_t *tickreset) { sol_t sol_nmea={{0}}; - double vel,bl; - uint32_t tick=tickget(); - int i; if (svr->stream[1].state!=1) return; - sol_nmea.ns=10; /* Some servers don't like when ns = 0 */ if (svr->nmeareq==1) { /* lat-lon-hgt mode */ sol_nmea.stat=SOLQ_SINGLE; sol_nmea.time=utc2gpst(timeget()); + sol_nmea.ns = 10; // Some servers don't like when ns = 0. matcpy(sol_nmea.rr,svr->nmeapos,3,1); - strsendnmea(svr->stream+1,&sol_nmea); } else if (svr->nmeareq==2) { /* single-solution mode */ - if (norm(svr->rtk.sol.rr,3)<=0.0) return; - sol_nmea.stat=SOLQ_SINGLE; - sol_nmea.time=utc2gpst(timeget()); + if (norm(svr->rtk.sol.rr, 3) <= RE_WGS84 / 2) return; + sol_nmea.stat = svr->rtk.sol.stat; + sol_nmea.time = utc2gpst(timeget()); + sol_nmea.ns = svr->rtk.sol.ns; + sol_nmea.age = svr->rtk.sol.age; + sol_nmea.refstationid = svr->rtk.sol.refstationid; matcpy(sol_nmea.rr,svr->rtk.sol.rr,3,1); - strsendnmea(svr->stream+1,&sol_nmea); } else if (svr->nmeareq==3) { /* reset-and-single-sol mode */ - /* send reset command if baseline over threshold */ - bl=baseline_len(&svr->rtk); + double bl = baseline_len(&svr->rtk); + uint32_t tick = tickget(); if (bl>=svr->bl_reset&&(int)(tick-*tickreset)>MIN_INT_RESET) { strsendcmd(svr->stream+1,svr->cmd_reset); @@ -599,22 +611,28 @@ static void send_nmea(rtksvr_t *svr, uint32_t *tickreset) svr->rtk.rb[0],svr->rtk.rb[1],svr->rtk.rb[2]); *tickreset=tick; } - if (norm(svr->rtk.sol.rr,3)<=0.0) return; - sol_nmea.stat=SOLQ_SINGLE; + if (norm(svr->rtk.sol.rr, 3) <= RE_WGS84 / 2) return; + sol_nmea.stat = svr->rtk.sol.stat; sol_nmea.time=utc2gpst(timeget()); + sol_nmea.ns = svr->rtk.sol.ns; + sol_nmea.age = svr->rtk.sol.age; + sol_nmea.refstationid = svr->rtk.sol.refstationid; matcpy(sol_nmea.rr,svr->rtk.sol.rr,3,1); /* set predicted position if velocity > 36km/h */ - if ((vel=norm(svr->rtk.sol.rr+3,3))>10.0) { - for (i=0;i<3;i++) { + double vel = norm(svr->rtk.sol.rr + 3, 3); + if (vel > 10.0) { + for (int i = 0; i < 3; i++) { sol_nmea.rr[i]+=svr->rtk.sol.rr[i+3]/vel*svr->bl_reset*0.8; } } - strsendnmea(svr->stream+1,&sol_nmea); - - tracet(3,"send nmea: rr=%.3f %.3f %.3f\n",sol_nmea.rr[0],sol_nmea.rr[1], - sol_nmea.rr[2]); } + else return; + + strsendnmea(svr->stream + 1, &sol_nmea); + trace(3, "send nmea: stat=%d ns=%d age=%.3f ref=%d rr=%.3f %.3f %.3f\n", + sol_nmea.stat, sol_nmea.ns, sol_nmea.age, sol_nmea.refstationid, + sol_nmea.rr[0], sol_nmea.rr[1], sol_nmea.rr[2]); } /* rtk server thread ---------------------------------------------------------*/ #ifdef WIN32 @@ -832,10 +850,19 @@ extern int rtksvrinit(rtksvr_t *svr) memset(svr->rtcm+i,0,sizeof(rtcm_t)); } for (i=0;istream+i); + + for (i=0;inav.ssr[i].iode=-1; + for (j=0;j<6;j++) { + svr->nav.ssr[i].t0[j]=time0; + } + } for (i=0;i<3;i++) *svr->cmds_periodic[i]='\0'; *svr->cmd_reset='\0'; svr->bl_reset=10.0; + svr->pcvsr.pcv = NULL; + svr->pcvsr.n = svr->pcvsr.nmax = 0; rtklib_initlock(&svr->lock); return 1; @@ -916,7 +943,7 @@ extern int rtksvrstart(rtksvr_t *svr, int cycle, int buffsize, int *strs, int nmeareq, const double *nmeapos, prcopt_t *prcopt, solopt_t *solopt, stream_t *moni, char *errmsg) { - gtime_t time,time0={0}; + gtime_t time; int i,j,rw; tracet(3,"rtksvrstart: cycle=%d buffsize=%d navsel=%d nmeacycle=%d nmeareq=%d\n", @@ -984,10 +1011,13 @@ extern int rtksvrstart(rtksvr_t *svr, int cycle, int buffsize, int *strs, svr->rtk.rb[i]=i<3?prcopt->rb[i]:0.0; } } +#ifdef RTKLIB_DISABLED /* update navigation data */ + gtime_t time0 = {0}; for (i=0;inav.eph [i].ttr=time0; for (i=0;inav.geph[i].tof=time0; for (i=0;inav.seph[i].tof=time0; +#endif /* set monitor stream */ svr->moni=moni; @@ -1008,6 +1038,12 @@ extern int rtksvrstart(rtksvr_t *svr, int cycle, int buffsize, int *strs, svr->rtcm[i].time=strs[i]==STR_FILE?strgettime(svr->stream+i):time; } } + svr->rtk.vtec_used=0; + if (svr->rtk.opt.sateph==EPHOPT_SSRAPC||svr->rtk.opt.sateph==EPHOPT_SSRCOM) + setseleph(SYS_GAL,1); // SSR mode not compatible with mixed I/NAV F/NAV ephemeris + else + setseleph(SYS_GAL,0); // restore to default + /* sync input streams */ strsync(svr->stream,svr->stream+1); strsync(svr->stream,svr->stream+2); @@ -1139,31 +1175,27 @@ extern void rtksvrclosestr(rtksvr_t *svr, int index) * int *vsat O valid satellite flag * return : number of satellites *-----------------------------------------------------------------------------*/ -extern int rtksvrostat(rtksvr_t *svr, int rcv, gtime_t *time, int *sat, - double *az, double *el, int **snr, int *vsat) +extern int rtksvrostat(rtksvr_t *svr, int rcv, gtime_t *time, int sat[MAXSAT], + double *az, double *el, int snr[MAXSAT][NFREQ], int vsat[MAXSAT][NFREQ]) { - int i,j,ns; - tracet(4,"rtksvrostat: rcv=%d\n",rcv); if (!svr->state) return 0; rtksvrlock(svr); - ns=svr->obs[rcv][0].n; + int ns=svr->obs[rcv][0].n; if (ns>0) { *time=svr->obs[rcv][0].data[0].time; } - for (i=0;iobs[rcv][0].data[i].sat; az [i]=svr->rtk.ssat[sat[i]-1].azel[0]; el [i]=svr->rtk.ssat[sat[i]-1].azel[1]; - for (j=0;jobs[rcv][0].data[i].SNR[j]); - } - if (svr->rtk.sol.stat==SOLQ_NONE||svr->rtk.sol.stat==SOLQ_SINGLE) { - vsat[i]=svr->rtk.ssat[sat[i]-1].vs; - } - else { - vsat[i]=svr->rtk.ssat[sat[i]-1].vsat[0]; + for (int j=0;jobs[rcv][0].data[i].SNR[j] + 0.5); + if (svr->rtk.sol.stat == SOLQ_NONE || svr->rtk.sol.stat == SOLQ_SINGLE) + vsat[i][j] = svr->rtk.ssat[sat[i] - 1].vs; + else + vsat[i][j] = svr->rtk.ssat[sat[i] - 1].vsat[j]; } } rtksvrunlock(svr); diff --git a/test/data/rcvraw/ss2_20080517.log b/test/data/rcvraw/ss2_20080517.log deleted file mode 100644 index 1a6ba89f5..000000000 Binary files a/test/data/rcvraw/ss2_20080517.log and /dev/null differ diff --git a/test/utest/t_tle.c b/test/utest/t_tle.c index 63dbd07b5..6f167882a 100644 --- a/test/utest/t_tle.c +++ b/test/utest/t_tle.c @@ -112,7 +112,7 @@ static void utest3(void) assert(nav.n>0); stat=readerp(file3,&erp); - assert(stat); + assert(stat > 0); stat=tle_read(file2,&tle); assert(stat); diff --git a/util/ppc-dataset/batch_rnx2rtkp.py b/util/ppc-dataset/batch_rnx2rtkp.py new file mode 100644 index 000000000..e4379f4c3 --- /dev/null +++ b/util/ppc-dataset/batch_rnx2rtkp.py @@ -0,0 +1,60 @@ +''' + batch_rnx2rtkp - template to run multiple simultaneous solutions of rnx2rtkp in Windows. + This example is configured to run the PPC_dataset benchmark files at https://github.com/taroz/PPC-Dataset + ''' + +import os +import subprocess +import psutil +import time + +# set location of data and rnx2rtkp executable +datapaths = [r'C:\gps\data\PPC\PPC-Dataset\nagoya\run1', + r'C:\gps\data\PPC\PPC-Dataset\nagoya\run2', + r'C:\gps\data\PPC\PPC-Dataset\nagoya\run3', + r'C:\gps\data\PPC\PPC-Dataset\tokyo\run1', + r'C:\gps\data\PPC\PPC-Dataset\tokyo\run2', + r'C:\gps\data\PPC\PPC-Dataset\tokyo\run3', + ] +binpath = r'C:\gps\rtklib\bins\RTKLIB_EX_2.5.1' + +# set input files +cfgs = [r'C:\gps\data\PPC\PPC-Dataset\tokyo\ppc_benchmark'] # list of config files to run (files should have .conf ext) +rovFile = 'rover.obs' # rover files with wild cards +baseFile = 'base.obs' # base files with wild cards +navFile = 'base.nav' # navigation files with wild cards +outFile = '' + +# set maximum number of simultaneous occurences of rnx2rtkp to run +max_windows = 10 + +# get list of current threads running in Windows +current_process = psutil.Process() +num_start = len(current_process.children()) + +# loop through data folders +for datapath in datapaths: + #datepath = datapath + '/' + date + print(datapath) + os.chdir(datapath) + + # Run a solution for each config file in list + for cfg in cfgs: + out = cfg.split('\\')[-1] + '_' + outFile + # create command to run solution + rtkcmd=r'%s\rnx2rtkp -x 0 -y 2 -k %s.conf -o %s.pos %s %s %s' % \ + (binpath, cfg, out, rovFile, baseFile, navFile) + + # run command + subprocess.Popen(rtkcmd) + + + # if max windows open, wait for one to close + while len(current_process.children())-num_start >= max_windows: + time.sleep(1) #wait here for existing window to close + +# Wait for all solutions to finish +print('Waiting for solutions to complete ...') +while len(current_process.children())-num_start > 0: + pass #wait here if max windows open +print('Done') \ No newline at end of file diff --git a/util/ppc-dataset/gnssplusplus2pos.py b/util/ppc-dataset/gnssplusplus2pos.py new file mode 100644 index 000000000..eabf46971 --- /dev/null +++ b/util/ppc-dataset/gnssplusplus2pos.py @@ -0,0 +1,32 @@ +# Files +REF_FILE = r"C:\gps\data\PPC\PPC-Dataset\gnssplusplusresults\ppc_nagoya_run3_rtk.pos" +OUT_FILE = r"C:\gps\data\PPC\PPC-Dataset\gnssplusplusresults\ppc_nagoya_run3_rtklib.pos" + +with open(OUT_FILE, "w", newline="") as fo: + fo.write("% GPST latitude(deg) longitude(deg) height(m) Q ns " + "sdn(m) sde(m) sdu(m) sdne(m) sdeu(m) sdun(m) age(s) ratio\n") + + with open(REF_FILE, newline="") as fi: + for line in fi: + if not line.strip() or line.startswith("%"): + continue + + f = line.split() + + week = int(f[0]) + tow = float(f[1]) + lat = float(f[5]) + lon = float(f[6]) + height = float(f[7]) + q = int(f[8]) # Status + ns = int(f[9]) # NumSat + ratio = float(f[11]) # Ratio + + fo.write(f"{week:4d} {tow:10.3f} " + f"{lat:15.9f} " + f"{lon:15.9f} " + f"{height:10.4f} " + f"{q:3d} {ns:3d} " + f"{0.0000:8.4f} {0.0000:8.4f} {0.0000:8.4f} " + f"{0.0000:8.4f} {0.0000:8.4f} {0.0000:8.4f} " + f"{0.00:6.2f} {ratio:6.1f}\n") \ No newline at end of file diff --git a/util/ppc-dataset/mrtklib2pos.py b/util/ppc-dataset/mrtklib2pos.py new file mode 100644 index 000000000..7a842fc77 --- /dev/null +++ b/util/ppc-dataset/mrtklib2pos.py @@ -0,0 +1,26 @@ +from compare_ppc import parse_nmea_full_ts + +# Files +NMEA_FILE = r"C:\gps\data\PPC\PPC-Dataset\mrtklib_results\nagoya_run3_rtk.nmea" +OUT_FILE = r"C:\gps\data\PPC\PPC-Dataset\mrtklib_results\mrtk_nagoya_run3_rtklib.pos" + +# Set these for the PPC run date +GPS_WEEK = 2324 +UTC_TO_GPST_OFFSET = 18.0 # seconds, valid for recent PPC data + + +with open(OUT_FILE, "w", newline="") as fo: + fo.write("% GPST latitude(deg) longitude(deg) height(m) Q ns " + "sdn(m) sde(m) sdu(m) sdne(m) sdeu(m) sdun(m) age(s) ratio\n") + + for week, tow, utc_sod, lat, lon, height, q, ns in parse_nmea_full_ts(NMEA_FILE): + ratio = 0.0 + + fo.write(f"{week:4d} {tow:10.3f} " + f"{lat:15.9f} " + f"{lon:15.9f} " + f"{height:10.4f} " + f"{q:3d} {ns:3d} " + f"{0.0000:8.4f} {0.0000:8.4f} {0.0000:8.4f} " + f"{0.0000:8.4f} {0.0000:8.4f} {0.0000:8.4f} " + f"{0.00:6.2f} {ratio:6.1f}\n") \ No newline at end of file diff --git a/util/ppc-dataset/ppc_ref2pos.py b/util/ppc-dataset/ppc_ref2pos.py new file mode 100644 index 000000000..dd858ef4d --- /dev/null +++ b/util/ppc-dataset/ppc_ref2pos.py @@ -0,0 +1,22 @@ +# Files +REF_FILE = r"C:\gps\data\PPC\PPC-Dataset\nagoya\run3\reference.csv" +OUT_FILE = r"C:\gps\data\PPC\PPC-Dataset\nagoya\run3\reference.pos" +#REF_FILE = r"C:\gps\data\PPC\PPC-Dataset\gnssplusplusresults\ppc_tokyo_run3_rtk.pos" +#OUT_FILE = r"C:\gps\data\PPC\PPC-Dataset\gnssplusplusresults\ppc_tokyo_run3_rtklib.pos" + +import csv + +with open(OUT_FILE, "w", newline="") as fo: + fo.write("% GPST latitude(deg) longitude(deg) height(m) Q ns " + "sdn(m) sde(m) sdu(m) sdne(m) sdeu(m) sdun(m) age(s) ratio\n") + + with open(REF_FILE, newline="") as fi: + for r in csv.DictReader(fi): + fo.write(f"{int(r['GPS Week']):4d} {float(r['GPS TOW (s)']):10.3f} " + f"{float(r['Latitude (deg)']):15.9f} " + f"{float(r['Longitude (deg)']):15.9f} " + f"{float(r['Ellipsoid Height (m)']):10.4f} " + f"{1:3d} {0:3d} " + f"{0.0000:8.4f} {0.0000:8.4f} {0.0000:8.4f} " + f"{0.0000:8.4f} {0.0000:8.4f} {0.0000:8.4f} " + f"{0.00:6.2f} {999.9:6.1f}\n") \ No newline at end of file diff --git a/util/ppc-dataset/score_ppc_sol.py b/util/ppc-dataset/score_ppc_sol.py new file mode 100644 index 000000000..c32fbdee6 --- /dev/null +++ b/util/ppc-dataset/score_ppc_sol.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python3 +# Score an RTKLIB .pos solution using PPC GNSS competition rules. + +dataDir = r"C:\gps\data\PPC\PPC-Dataset" +REF_FILE = [ + r"\nagoya\run1\reference.csv", + r"\nagoya\run2\reference.csv", + r"\nagoya\run3\reference.csv", + r"\tokyo\run1\reference.csv", + r"\tokyo\run2\reference.csv", + r"\tokyo\run3\reference.csv"] + +# GNSSplusplus +# SOL_FILE = [ +# r"\gnssplusplusresults\ppc_nagoya_run1_rtklib.pos", +# r"\gnssplusplusresults\ppc_nagoya_run2_rtklib.pos", +# r"\gnssplusplusresults\ppc_nagoya_run3_rtklib.pos", +# r"\gnssplusplusresults\ppc_tokyo_run1_rtklib.pos", +# r"\gnssplusplusresults\ppc_tokyo_run2_rtklib.pos", +# r"\gnssplusplusresults\ppc_tokyo_run3_rtklib.pos"] + +# MRTKLIB +# SOL_FILE = [ +# r"\mrtklib_results\mrtk_nagoya_run1_rtklib.pos", +# r"\mrtklib_results\mrtk_nagoya_run2_rtklib.pos", +# r"\mrtklib_results\mrtk_nagoya_run3_rtklib.pos", +# r"\mrtklib_results\mrtk_tokyo_run1_rtklib.pos", +# r"\mrtklib_results\mrtk_tokyo_run2_rtklib.pos", +# r"\mrtklib_results\mrtk_tokyo_run3_rtklib.pos"] + +# RTKLIB_EX 2.5.1 +file = r'\ppc_benchmark_0622_.pos' +#file = r'\f9p_ppk_.pos' +#file = r'\b243_b.pos' +SOL_FILE = [ + r"\nagoya\run1"+ file, + r"\nagoya\run2" + file, + r"\nagoya\run3" + file, + r"\tokyo\run1" + file, + r"\tokyo\run2" + file, + r"\tokyo\run3" + file] + + +MAX_ERR_M = 0.50 # PPC threshold: 3D error <= 50 cm +USE_DISTANCE_WEIGHTING = True # True = PPC distance score, False = epoch percentage + +import csv +import math +import matplotlib.pyplot as plt +from datetime import datetime + +def llh_to_ecef(lat_deg, lon_deg, h): + a = 6378137.0 + f = 1.0 / 298.257223563 + e2 = f * (2.0 - f) + lat = math.radians(lat_deg) + lon = math.radians(lon_deg) + s = math.sin(lat) + n = a / math.sqrt(1.0 - e2 * s * s) + x = (n + h) * math.cos(lat) * math.cos(lon) + y = (n + h) * math.cos(lat) * math.sin(lon) + z = (n * (1.0 - e2) + h) * math.sin(lat) + return (x, y, z) + + +def norm3(a, b): + return math.sqrt(sum((a[i] - b[i]) ** 2 for i in range(3))) + +def datetime_to_gps(date, time): + gps_epoch = datetime(1980, 1, 6) + dt = datetime.strptime(f"{date} {time}", "%Y/%m/%d %H:%M:%S.%f") + + gps_seconds = (dt - gps_epoch).total_seconds() + week = int(gps_seconds // 604800) + tow = gps_seconds % 604800 + + return week, tow + +def read_rtklib_pos(path): + sol = [] + with open(path, "r", encoding="utf-8", errors="ignore") as f: + for line in f: + if not line.strip() or line[0] == "%": + continue + + p = line.split() + if len(p) < 5: + continue + + try: + try: + t = float(p[1]) + except: + w, t = datetime_to_gps(p[0], p[1]) + lat = float(p[2]) + lon = float(p[3]) + h = float(p[4]) + sol.append((t, llh_to_ecef(lat, lon, h))) + except ValueError: + pass + return sorted(sol) + + +def read_reference_csv(path): + ref = [] + with open(path, newline="", encoding="utf-8-sig") as f: + for row in csv.DictReader(f): + #t = float(row["GPS Week"]) * 604800.0 + float(row["GPS TOW (s)"]) + t = float(row["GPS TOW (s)"]) + lat = float(row["Latitude (deg)"]) + lon = float(row["Longitude (deg)"]) + h = float(row["Ellipsoid Height (m)"]) + ref.append((t, llh_to_ecef(lat, lon, h))) + return sorted(ref) + +def calc_score(ref, sol, distance_weighted=False): + j = 0 + last_sol = None + + good = 0.0 + total = 0.0 + good_epochs = 0 + total_epochs = 0 + + t0 = ref[0][0] + times = [] + errors = [] + + for i in range(len(ref)): + t, ref_xyz = ref[i] + + while j < len(sol) and sol[j][0] <= t: + last_sol = sol[j] + j += 1 + + err = float("inf") if last_sol is None else norm3(last_sol[1], ref_xyz) + + times.append((t - t0) / 60.0) # minutes + errors.append(err) + + if distance_weighted: + if i == 0: + continue + weight = norm3(ref[i][1], ref[i - 1][1]) + else: + weight = 1.0 + + total += weight + total_epochs += 1 + + if err <= MAX_ERR_M: + good += weight + good_epochs += 1 + + score = 100.0 * good / total if total > 0 else 0.0 + + return score, good, total, good_epochs, total_epochs, times, errors + +# main code +#print('Results: %s' % file) +total_good = 0.0 +total_weight = 0.0 +total_good_ep = 0 +total_ep = 0 +route_scores = [] +nfiles = len(REF_FILE) +for i in range(nfiles): + ref = read_reference_csv(dataDir + REF_FILE[i]) + sol = read_rtklib_pos(dataDir + SOL_FILE[i]) + score, good, total, good_ep, total_ep_i, times, errors = calc_score( + ref, sol, distance_weighted=USE_DISTANCE_WEIGHTING) + + route_scores.append(score) + total_good += good + total_weight += total + total_good_ep += good_ep + total_ep += total_ep_i + + ref_file = REF_FILE[i].split('\\') + print('%14s: %5.2f%% (%d/%d, missing=%d)' % + (ref_file[-3] + ' ' + ref_file[-2], + score, good_ep, total_ep_i, len(ref) - len(sol))) + + plt.figure(figsize=(12,4)) + plt.plot(times, errors, '.', markersize=1) + plt.axhline(0.5, color='r', linestyle='--') + plt.xlabel('Time (minutes)') + plt.ylabel('3D Error (m)') + plt.title(ref_file[-3] + ' ' + ref_file[-2]) + plt.grid(True) + plt.yscale('log') # optional but usually helpful + plt.show() + + +print() + +if USE_DISTANCE_WEIGHTING: + overall = 100.0 * total_good / total_weight if total_weight else 0.0 + print("Overall PPC score: %6.2f%% (%.1f/%.1f m)" % + (overall, total_good, total_weight)) + +else: + overall = 100.0 * total_good_ep / total_ep if total_ep else 0.0 + print("Overall epoch score: %6.2f%% (%d/%d epochs)" % + (overall, total_good_ep, total_ep)) \ No newline at end of file diff --git a/util/simobs/simobs.c b/util/simobs/simobs.c index 2045d3af2..68c0595fa 100644 --- a/util/simobs/simobs.c +++ b/util/simobs/simobs.c @@ -561,7 +561,7 @@ int main(int argc, char **argv) { if (nErp>0) { fprintf(stdout,"Reading %s\n",erpFileName); - if (!readerp(erpFileName,&nav.erp)) { + if (readerp(erpFileName,&nav.erp) == 0) { fprintf(stdout,"ERROR: cannot read ERP file %s\n",erpFileName); return -1; };