From 770e6f462e9e67fdeb06fe6f42f5286bf1c2f345 Mon Sep 17 00:00:00 2001 From: oaq Date: Mon, 20 Apr 2026 16:36:36 +1000 Subject: [PATCH 01/18] rtknavi_qt: correct freq change in SNR and sky plots --- app/qtapp/rtknavi_qt/navimain.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/qtapp/rtknavi_qt/navimain.cpp b/app/qtapp/rtknavi_qt/navimain.cpp index 38237ca8c..a04e2b303 100644 --- a/app/qtapp/rtknavi_qt/navimain.cpp +++ b/app/qtapp/rtknavi_qt/navimain.cpp @@ -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]); @@ -1921,7 +1921,7 @@ void MainWindow::drawSatellites(QPainter &c, int w, int h, int x0, int y0, radius = QFontMetrics(optDialog->panelFont).height(); c.setBrush(!validSatellites[index][k] ? Color::Silver : - (freq < NFREQ ? snrColor(snr[freq]) : color_sys[sysIdx])); + (freq < NFREQ + 1 ? snrColor(snr[freq]) : color_sys[sysIdx])); c.setPen(Qt::darkGray); color_text = Qt::white; if (freq < NFREQ + 1 && snr[freq] <= 0) { From 590403b23ac8578f4f01a6ac9c870746bdd2686d Mon Sep 17 00:00:00 2001 From: oaq Date: Mon, 20 Apr 2026 20:12:52 +1000 Subject: [PATCH 02/18] preceph: fix code_bias_ix system indexing --- src/preceph.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/preceph.c b/src/preceph.c index b3e3928c2..2bb2a90b9 100644 --- a/src/preceph.c +++ b/src/preceph.c @@ -57,9 +57,10 @@ #define MAXDTE 900.0 /* max time difference to ephem time (s) */ #define EXTERR_CLK 1E-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;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 +434,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 @@ -444,7 +447,7 @@ extern double code2bias(const nav_t *nav, int sys, int sat, int code, int mode) 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]; bias=nav->cbias[sat-1][frq_ix][code_ix]; // absolute bias if (mode==0) @@ -475,6 +478,7 @@ static int readbiaf(const char *file, nav_t *nav) 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; From b8198ef11ef9f0d860e5a969dbf68164af011f14 Mon Sep 17 00:00:00 2001 From: pleba Date: Wed, 22 Apr 2026 12:12:46 +0200 Subject: [PATCH 03/18] Fix incorrect install targets for some QT apps (launch, navi, plot, post, srctblbrows and strsvr) --- app/qtapp/rtklaunch_qt/CMakeLists.txt | 2 +- app/qtapp/rtknavi_qt/CMakeLists.txt | 2 +- app/qtapp/rtkplot_qt/CMakeLists.txt | 2 +- app/qtapp/rtkpost_qt/CMakeLists.txt | 2 +- app/qtapp/srctblbrows_qt/CMakeLists.txt | 2 +- app/qtapp/strsvr_qt/CMakeLists.txt | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) 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/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/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/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/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}) From fe5026cb8330c3b9db59a6a2d0d62ebc08ab7b5a Mon Sep 17 00:00:00 2001 From: oaq Date: Wed, 22 Apr 2026 22:44:14 +1000 Subject: [PATCH 04/18] rtknavi: fix the track plot expand and shrink for plots 3 and 4 It was missing implementations for plots 3 and 4. --- app/qtapp/rtknavi_qt/navimain.cpp | 23 ++++++++-------- app/winapp/rtknavi/navimain.cpp | 46 +++++++++++++++++++++++++------ app/winapp/rtknavi/navimain.dfm | 8 +++--- app/winapp/rtknavi/navimain.h | 4 +++ 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/app/qtapp/rtknavi_qt/navimain.cpp b/app/qtapp/rtknavi_qt/navimain.cpp index 38237ca8c..963700167 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; @@ -2041,17 +2041,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]; @@ -2535,10 +2536,10 @@ 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(); diff --git a/app/winapp/rtknavi/navimain.cpp b/app/winapp/rtknavi/navimain.cpp index a0ce89240..ee31a2f11 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; @@ -1011,6 +1011,34 @@ void __fastcall TMainForm::BtnShrink2Click(TObject *Sender) TrkScale2++; UpdatePlot(); } +// callback on button expand-2 ---------------------------------------------- +void __fastcall TMainForm::BtnExpand3Click(TObject *Sender) +{ + if (TrkScale3<=0) return; + TrkScale3--; + UpdatePlot(); +} +// callback on button shrink-3 ---------------------------------------------- +void __fastcall TMainForm::BtnShrink3Click(TObject *Sender) +{ + if (TrkScale3>=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) { @@ -2037,12 +2065,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]; @@ -2611,10 +2639,10 @@ 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); 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..ffa5725a4 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); From 72dca37463ccfc7289265dad1ce23ae726ec248e Mon Sep 17 00:00:00 2001 From: oaq Date: Sat, 25 Apr 2026 19:42:45 +1000 Subject: [PATCH 05/18] Add BDS to the systems in the default process options --- src/rtkcmn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtkcmn.c b/src/rtkcmn.c index a4c078da3..1639a1950 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_BDS, /* 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 */ From ca3befa0432a451a67f34bcd86e5117af530133b Mon Sep 17 00:00:00 2001 From: oaq Date: Sat, 25 Apr 2026 19:39:47 +1000 Subject: [PATCH 06/18] rnx2rtkp: default nav sys to include Galileo and BDS --- app/consapp/rnx2rtkp/rnx2rtkp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/consapp/rnx2rtkp/rnx2rtkp.c b/app/consapp/rnx2rtkp/rnx2rtkp.c index 95d2e49be..de3234bd7 100644 --- a/app/consapp/rnx2rtkp/rnx2rtkp.c +++ b/app/consapp/rnx2rtkp/rnx2rtkp.c @@ -193,7 +193,7 @@ int main(int argc, char **argv) else if (n Date: Tue, 28 Apr 2026 00:25:52 +1000 Subject: [PATCH 07/18] readsp3: handle arbitrary comment lines Common product files are using more that the example 4 lines, so rework the code to handle this without generating error messages. --- src/preceph.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/preceph.c b/src/preceph.c index 2bb2a90b9..3576e1473 100644 --- a/src/preceph.c +++ b/src/preceph.c @@ -146,7 +146,7 @@ static int readsp3h(FILE *fp, gtime_t *time, char *type, int *sats, bfact[0]=str2num(buff, 3,10); bfact[1]=str2num(buff,14,12); } - else if (i==2*nl+11){ + else if (i==2*nl+7){ break; /* at end of header */ } i=i+1; /* line counter */ @@ -187,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; From d3dc227eeb0681ea9cb8dca68f5cffa9c045e5df Mon Sep 17 00:00:00 2001 From: oaq Date: Mon, 27 Apr 2026 10:15:31 +1000 Subject: [PATCH 08/18] rinex header: fix clock file system parsing It uses the 'flag' to indicated that a clock file is expected and to handle the format changes in clock files from version 3.04, but could incorrectly parse the type and system if this expectation was not met. Rework this to use the flag to bias the search but to fallback to the alternative if not met. --- src/rinex.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/rinex.c b/src/rinex.c index 1bcd288b0..2385a0736 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; From 0bba414473086096ec17964a165cf2211855e0ef Mon Sep 17 00:00:00 2001 From: rtklibexplorer Date: Mon, 27 Apr 2026 10:28:11 -0600 Subject: [PATCH 09/18] Fix wrong constant in recent commits: SYS_BDS->SYS_CMP --- app/consapp/rnx2rtkp/rnx2rtkp.c | 2 +- src/rtkcmn.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/consapp/rnx2rtkp/rnx2rtkp.c b/app/consapp/rnx2rtkp/rnx2rtkp.c index de3234bd7..7cabfd3cd 100644 --- a/app/consapp/rnx2rtkp/rnx2rtkp.c +++ b/app/consapp/rnx2rtkp/rnx2rtkp.c @@ -193,7 +193,7 @@ int main(int argc, char **argv) else if (n Date: Tue, 28 Apr 2026 11:25:36 -0600 Subject: [PATCH 10/18] Modify iono-free option to use iono-free combination of freq slots 1 and 2 for all constellations if freqs="L1+L2", else use L1/L2 for GLONASS and freq slots 1 and 3 for all other constellations --- src/rtkcmn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rtkcmn.c b/src/rtkcmn.c index 55958e2df..4443e9b0f 100644 --- a/src/rtkcmn.c +++ b/src/rtkcmn.c @@ -3740,8 +3740,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 From a67d8a8798698558d27e2393c9aef7b70f5dc3c0 Mon Sep 17 00:00:00 2001 From: oaq Date: Mon, 27 Apr 2026 23:57:11 +1000 Subject: [PATCH 11/18] code2bias: guard code being zero, and code_ix not found --- src/preceph.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/preceph.c b/src/preceph.c index 2bb2a90b9..2d839f158 100644 --- a/src/preceph.c +++ b/src/preceph.c @@ -445,10 +445,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 (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 From f542de90425010781d0b52040492e00b9f30684f Mon Sep 17 00:00:00 2001 From: rtklibexplorer Date: Fri, 1 May 2026 15:52:41 -0600 Subject: [PATCH 12/18] Make Beidou SSR clock and orbit correction message parsing functional - Fix field length errors - Derive IODEs per Beidou ICD --- src/rcvraw.c | 4 ++-- src/rtcm3.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/rcvraw.c b/src/rcvraw.c index 99ce3ad92..17c1b2263 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.toesbuff,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 +1479,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++; @@ -1616,7 +1617,7 @@ 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; } @@ -1643,6 +1644,9 @@ static int decode_ssr1(rtcm_t *rtcm, int sys, int subtype) 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; @@ -1776,7 +1780,7 @@ 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; } @@ -1807,6 +1811,9 @@ static int decode_ssr4(rtcm_t *rtcm, int sys, int subtype) 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; From 5b59da32e47bb930d73de9bd5426a0dec9d39eee Mon Sep 17 00:00:00 2001 From: rtklibexplorer Date: Fri, 1 May 2026 15:55:04 -0600 Subject: [PATCH 13/18] Some .BIA bias files leave SVN field blank, modify file parsing to handle this case. --- src/preceph.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/preceph.c b/src/preceph.c index e62e493d0..9269d46dc 100644 --- a/src/preceph.c +++ b/src/preceph.c @@ -466,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); @@ -476,7 +476,11 @@ 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); From 9ada3b7ed49ae4019b5ef047e5805d3745a315a4 Mon Sep 17 00:00:00 2001 From: rtklibexplorer Date: Fri, 1 May 2026 15:56:43 -0600 Subject: [PATCH 14/18] Apply code biases for PPP solutions as absolute instead of differential for SSR and post-processing solutions --- src/ppp.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/ppp.c b/src/ppp.c index 81d813db0..9f2509004 100644 --- a/src/ppp.c +++ b/src/ppp.c @@ -426,18 +426,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 +443,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) From 28ad77c06ffc16b215858d6d5184d85333d44db9 Mon Sep 17 00:00:00 2001 From: rtklibexplorer Date: Fri, 1 May 2026 16:04:01 -0600 Subject: [PATCH 15/18] - Initialize timestamps for SSR corrections in rtksvrinit - Add reset of rtksvr structure when starting RTKNAVI as a commented out line, uncommenting this line makes RTKNAVI solutions repeatable when postprocessing data from files. --- app/winapp/rtknavi/navimain.cpp | 1 + src/rtksvr.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/app/winapp/rtknavi/navimain.cpp b/app/winapp/rtknavi/navimain.cpp index ee31a2f11..41e193c62 100644 --- a/app/winapp/rtknavi/navimain.cpp +++ b/app/winapp/rtknavi/navimain.cpp @@ -1320,6 +1320,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, diff --git a/src/rtksvr.c b/src/rtksvr.c index ac45da1c1..cacbf0996 100644 --- a/src/rtksvr.c +++ b/src/rtksvr.c @@ -832,6 +832,10 @@ 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].t0[j]=time0; + } for (i=0;i<3;i++) *svr->cmds_periodic[i]='\0'; *svr->cmd_reset='\0'; From bfd6491205cc5e7c3a7b613f8c8aa987fd30f120 Mon Sep 17 00:00:00 2001 From: oaq Date: Fri, 8 May 2026 13:29:10 +1000 Subject: [PATCH 16/18] readrnxclk: 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 seen in the CODE precise clock bias products. --- src/rinex.c | 55 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/src/rinex.c b/src/rinex.c index 2385a0736..6dc53ad5b 100644 --- a/src/rinex.c +++ b/src/rinex.c @@ -1558,34 +1558,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; @@ -1600,7 +1599,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; } @@ -1608,6 +1607,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 -----------------------------------------------------------*/ From 5c9cd9de9fdf46b6e1b96e5aae5ae4e1d20a7e75 Mon Sep 17 00:00:00 2001 From: oaq Date: Thu, 7 May 2026 20:07:49 +1000 Subject: [PATCH 17/18] satposs: fix to work with precise clocks from sp3 files satposs() was failing when precise clocks were configured and supplied in only an sp3 file and without broadcast ephemeris. Rework the code to fix this and a few related issues noted. pephclk() - rework to search both the precise clocks and the precise ephemeris data, giving preference to the precise clocks which are typically at a shorter period and more accurate. It was searching only the precise clocks and failing to make use of the satellite clock biases in sp3 files in some paths. Return 0 on all failure return paths, so the caller can test the return value for success or failure, and rework the callers as necessary. satposs() use the updated pephclk() to work with only satellite clock biases in sp3 files, and without broadcast ephemeris to give the satellite clock bias. pephpos() correct the returned clock variance which was not being scaled by CLIGHT to return it in units of m^2. It was effectively only applying the interpolation variance. Lower the precise clock extrapolation error from 1mm/s to 0.4mm/s. This gives a midpoint standard deviation of around 6mm for 30s data and 60mm for 5 minute data which seems more appropriate for current satellite clocks and still conservative. --- src/ephemeris.c | 9 +++++++-- src/preceph.c | 40 +++++++++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/ephemeris.c b/src/ephemeris.c index 56c8e6ea4..da56ad17e 100644 --- a/src/ephemeris.c +++ b/src/ephemeris.c @@ -808,8 +808,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/preceph.c b/src/preceph.c index 9269d46dc..19a4676d3 100644 --- a/src/preceph.c +++ b/src/preceph.c @@ -55,7 +55,7 @@ #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 */ @@ -639,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; @@ -647,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; @@ -661,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;i Date: Fri, 8 May 2026 16:50:17 -0600 Subject: [PATCH 18/18] Move $SAT output code to stat file for PPP solutions from rtkpos.c to ppp.c to avoid using wrong macro define for state indices --- src/ppp.c | 26 ++++++++++++++++---------- src/rtklib.h | 2 +- src/rtkpos.c | 35 +++++++++++++++++------------------ 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/ppp.c b/src/ppp.c index 9f2509004..5c6a5a91c 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) ---------------------------*/ diff --git a/src/rtklib.h b/src/rtklib.h index 55149be8e..9a95e7987 100644 --- a/src/rtklib.h +++ b/src/rtklib.h @@ -1859,7 +1859,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); diff --git a/src/rtkpos.c b/src/rtkpos.c index 8ebc15939..ac9611a4a 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]); + } } }