Changeset 11083 in ntrip
- Timestamp:
- Oct 12, 2026, 3:32:43 PM (9 hours ago)
- Location:
- trunk/BNC
- Files:
-
- 16 edited
-
CHANGELOG.md (modified) (2 diffs)
-
Example_Configs/21_CompareSp3.bnc (modified) (1 diff)
-
scripts/compareSP3Plot.pl (modified) (6 diffs)
-
src/RTCM3/RTCM3coDecoder.cpp (modified) (2 diffs)
-
src/RTCM3/clock_and_orbit/clock_orbit_rtcm.cpp (modified) (7 diffs)
-
src/bnchelp.html (modified) (1 diff)
-
src/combination/bnccomb.cpp (modified) (1 diff)
-
src/orbComp/sp3Comp.cpp (modified) (1 diff)
-
tests/README.md (modified) (2 diffs)
-
tests/cases/combi/expected/BKG0MGXRTS_20262780000_01D_05S_CLK.CLK.gz (modified) ( previous)
-
tests/cases/combi/expected/BKG0MGXRTS_20262780000_01D_05S_OSB.BIA.gz (modified) ( previous)
-
tests/cases/combi/expected/Combi.log.gz (modified) ( previous)
-
tests/cases/combi_ppp/expected/BKG0MGXRTS_20262780000_01D_05S_CLK.CLK.gz (modified) ( previous)
-
tests/cases/combi_ppp/expected/BKG0MGXRTS_20262780000_01D_05S_OSB.BIA.gz (modified) ( previous)
-
tests/cases/combi_ppp/expected/CombiPPP.log.gz (modified) ( previous)
-
tests/cases/combi_ppp/expected/FFMJ00DEU_20262780000_01D_01S.ppp.gz (modified) ( previous)
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/CHANGELOG.md
r11082 r11083 5 5 - ADDED: Stream comparison in the SSR QC: orbits (radial, along, cross), clocks referred to the reference signals and signal-in-space differences (SIS = radial - clock) of each stream compared with the consensus of the other ACs (one vote per AC, own AC left out, combination products not voting) or with a selected stream (e.g. 'INTERNAL'), as RMS and standard deviation per satellite and system 6 6 - ADDED: SIS (radial - clock, satellite-specific clock offset included) per epoch and SISRMS/SISSig per satellite and system in the SP3 comparison 7 - CHANGED: SP3 comparison: the clock offsets are estimated with the epoch offsets eliminated from the normal equations (identical result); a daily file with 30-second sampling is now compared in seconds instead of hours 7 8 - ADDED: Combination: check of the consistency of each AC's code biases with its clocks; an AC whose satellite offsets follow the ionosphere-free combination of its reference signal biases is reported and excluded from the clock datum 8 9 - ADDED: Combination: clocks of AC satellites without code biases of both reference signals are combined, but excluded from the clock datum (hourly message) … … 22 23 - CHANGED: Replays of raw files ('--file') are reproducible, including PPP with ambiguity resolution; corrections pending at the end of a raw file are written 23 24 - CHANGED: Example configurations 17 and 18 (sampling interval 5 s, ACs CNE, CHC, BKG, CAS bias file), ANTEX file igs20.atx updated 25 - CHANGED: Combination: GLONASS corrections are accepted up to 960 s (before 900 s) from the reference time of their broadcast ephemeris, as ACs switch to the next ephemeris shortly before its validity begins 24 26 - CHANGED: Legacy PPP_SSR_I module removed 27 - FIXED: SSR corrections of the old GPS week received after the week change (e.g. Saturday 23:59:55 received at 00:00:03) were assigned an epoch 12 h later (Sunday 11:59:55); affected all streams once per week 25 28 - FIXED: IGS-SSR epoch time (IDF003) of GLONASS and BDS is GPS time; decoded corrections were placed 18 s (GLONASS) and 14 s (BDS) late, and the encoder wrote the wrong convention 26 29 - FIXED: Combination: sign of the ionosphere-free combination of the SSR code biases used to refer the AC clocks to the reference signals (SSR and SINEX sign conventions differ) -
trunk/BNC/Example_Configs/21_CompareSp3.bnc
r10968 r11083 107 107 sslClientCertPath= 108 108 sslIgnoreErrors=0 109 ssrQcIntr=1 hour 110 ssrQcPath= 111 ssrQcRef=CONSENSUS 112 ssrQcStreams=ALL 109 113 startTab=5 110 114 statusTab=0 -
trunk/BNC/scripts/compareSP3Plot.pl
r10126 r11083 15 15 # - at first one offset 'per epoch for all satellites' and 16 16 # - secondly one offset 'per satellite for all epochs'. 17 # The signal-in-space difference SIS (radial minus clock difference, only the 18 # epoch offset removed, i.e. including the satellite offsets) is given in the 19 # last column of BNC's epoch lines. 17 20 # ======================================================================== 18 21 # Uses … … 70 73 my (%COMPARISON); 71 74 my (@array); 72 my ($sys, $sat, $epo, $radial, $along, $out, $drange, $clk, $clkRed); 75 my ($sys, $sat, $epo, $radial, $along, $out, $drange, $clk, $clkRed, $sis); 73 76 # ----------------------------------------------------------------------------- 74 77 # create pdf for plot results … … 95 98 $clk = $array[5];#print "$clk\n"; 96 99 $clkRed = $array[6];#print "$clkRed\n"; 100 $sis = $array[8];# not present if the clock comparison is missing 97 101 if ($out !~ /^\.$/) { 98 102 push @{$COMPARISON{$sys}{$sat}{EPOCH }}, $epo; … … 102 106 push @{$COMPARISON{$sys}{$sat}{CLK }}, $clk; 103 107 push @{$COMPARISON{$sys}{$sat}{CLKRED}}, $clkRed; 108 } 109 if (defined $sis && $sis =~ /^-?\d/) { 110 push @{$COMPARISON{$sys}{$sat}{EPOCH_SIS}}, $epo; 111 push @{$COMPARISON{$sys}{$sat}{SIS }}, $sis; 104 112 } 105 113 } … … 280 288 } 281 289 } 290 ######## SIS ##################### 291 if (("ALL" ~~ @plotTypes ) || ("SIS" ~~ @plotTypes)) { 292 print "Plot SIGNAL-IN-SPACE DIFFERENCES (RADIAL MINUS CLOCK) ...\n"; 293 $page = $pdf->page(); $page->mediabox('A4'); 294 $headline = sprintf("Signal-in-space differences, radial minus clock, incl. satellite offsets (%s)", $inputFilename); 295 $headline_text = $page->text; 296 $headline_text->font($font1, 11/pt); 297 $headline_text->translate(15/mm, 280/mm); 298 $headline_text->text($headline); 299 $y = $y0+$dy; 300 #SYSTEM 301 foreach my $key_sys (sort keys %COMPARISON) { 302 my @sats = grep { exists $COMPARISON{$key_sys}{$_}{SIS} } sort keys %{$COMPARISON{$key_sys}}; 303 next unless @sats; 304 print " for $key_sys\n"; 305 my @datasets_s; # init datasets 306 my $pngName_s = sprintf ("%s_SIS_%s.png", $inputFilename, $key_sys); 307 # SIS contains the satellite offsets: y range from the data 308 my $maxAbs = 0.1; 309 foreach my $key_sat (@sats) { 310 my ( $min, $max ) = minmax @{$COMPARISON{$key_sys}{$key_sat}{SIS}}; 311 $maxAbs = abs($min) if abs($min) > $maxAbs; 312 $maxAbs = abs($max) if abs($max) > $maxAbs; 313 } 314 my $chart_s = Chart::Gnuplot->new( 315 output => $pngName_s, terminal => 'png',title => "SIS (radial minus clock)", 316 ylabel => "SIS Difference [m]", yrange => ["-$maxAbs", "$maxAbs"], 317 xlabel => "Time [h]", timeaxis => 'x', xtics => {labelfmt => '%H:%M', rotate => '-270',}, 318 legend => { position => "outside right",}, 319 grid => 'on',); 320 #SATELLITE 321 foreach my $key_sat (@sats) { 322 my $colour = sprintf("%d", (substr $key_sat, -2)+1); 323 my $dataset_s = Chart::Gnuplot::DataSet->new( 324 xdata => \@{$COMPARISON{$key_sys}{$key_sat}{EPOCH_SIS}}, 325 ydata => \@{$COMPARISON{$key_sys}{$key_sat}{SIS}}, 326 title => "$key_sat", 327 timefmt => '%Y-%m-%d_%H:%M:%S', 328 linetype => $colour, 329 style => " lines ",); 330 push (@datasets_s, $dataset_s); 331 } 332 $chart_s->plot2d(@datasets_s); 333 $y = $y - $dy; 334 if($y < 30/mm) { 335 $page = $pdf->page(); $page->mediabox('A4'); 336 $y = $y0; 337 } 338 $png = $page->gfx(); die("Unable to find image file: $!") unless -e $pngName_s; 339 $png->image($pdf->image_png($pngName_s), $x, $y, $width, $height); 340 } 341 } 282 342 $pdf->save(); 283 343 $pdf->end(); … … 295 355 PARAMETER: 296 356 297 --plotTypes possible: ALL => RAO and CLOCK; CLK => CLOCK and CLOCKRED; RAO => RAO only 298 --logFiles comma separated list of BNC's combination logfiles 357 --plotTypes possible: ALL => RAO, CLOCK and SIS; CLK => CLOCK and CLOCKRED; RAO => RAO only; 358 SIS => signal-in-space differences (radial minus clock) only 359 --logFiles comma separated list of BNC's SP3 comparison logfiles 299 360 --help show help contents 300 361 -
trunk/BNC/src/RTCM3/RTCM3coDecoder.cpp
r11074 r11083 1275 1275 if (bdt) { 1276 1276 epoSecBds += 14.0; 1277 if (epoSecBds > 604800.0) { 1277 if (epoSecBds >= 604800.0) { 1278 1278 epoSecBds -= 7.0*24.0*60.0*60.0; 1279 1279 } … … 1289 1289 } 1290 1290 1291 // The epoch is given as seconds of week (or of day): move it by whole days 1292 // to the one closest to the current time. Folding in 12 h steps (as 1293 // before) stopped at the edge of the +-12 h window, e.g. at the week 1294 // change a correction of Saturday 23:59:55 received after midnight ended 1295 // up at Sunday 11:59:55. 1291 1296 if (_lastTime.valid()) { 1292 double maxDiff = 12 * 3600.0; 1293 while (_lastTime < currentTime - maxDiff) { 1294 _lastTime = _lastTime + maxDiff; 1295 } 1296 while (_lastTime > currentTime + maxDiff) { 1297 _lastTime = _lastTime - maxDiff; 1297 const double halfDay = 12 * 3600.0; 1298 const double day = 24 * 3600.0; 1299 while (_lastTime < currentTime - halfDay) { 1300 _lastTime = _lastTime + day; 1301 } 1302 while (_lastTime > currentTime + halfDay) { 1303 _lastTime = _lastTime - day; 1298 1304 } 1299 1305 } -
trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_rtcm.cpp
r11042 r11083 97 97 break; 98 98 case CLOCKORBIT_SATGLONASS: 99 E_GLONASS_SATELLITE_ID(co->Sat[i].ID) 99 E_GLONASS_SATELLITE_ID_OLD(co->Sat[i].ID) 100 100 E_GLONASS_IOD(co->Sat[i].IOD) 101 101 break; … … 161 161 break; 162 162 case CLOCKORBIT_SATGLONASS: 163 E_GLONASS_SATELLITE_ID(co->Sat[i].ID) 163 E_GLONASS_SATELLITE_ID_OLD(co->Sat[i].ID) 164 164 break; 165 165 } … … 221 221 break; 222 222 case CLOCKORBIT_SATGLONASS: 223 E_GLONASS_SATELLITE_ID(co->Sat[i].ID) 223 E_GLONASS_SATELLITE_ID_OLD(co->Sat[i].ID) 224 224 E_GLONASS_IOD(co->Sat[i].IOD) 225 225 break; … … 294 294 break; 295 295 case CLOCKORBIT_SATGLONASS: 296 E_GLONASS_SATELLITE_ID(co->Sat[i].ID) 296 E_GLONASS_SATELLITE_ID_OLD(co->Sat[i].ID) 297 297 break; 298 298 } … … 334 334 break; 335 335 case CLOCKORBIT_SATGLONASS: 336 E_GLONASS_SATELLITE_ID(co->Sat[i].ID) 336 E_GLONASS_SATELLITE_ID_OLD(co->Sat[i].ID) 337 337 break; 338 338 } … … 385 385 break; 386 386 case CLOCKORBIT_SATGLONASS: 387 E_GLONASS_SATELLITE_ID(cb->Sat[i].ID) 387 E_GLONASS_SATELLITE_ID_OLD(cb->Sat[i].ID) 388 388 break; 389 389 } … … 442 442 break; 443 443 case CLOCKORBIT_SATGLONASS: 444 E_GLONASS_SATELLITE_ID(pb->Sat[i].ID) 444 E_GLONASS_SATELLITE_ID_OLD(pb->Sat[i].ID) 445 445 break; 446 446 } -
trunk/BNC/src/bnchelp.html
r11081 r11083 4337 4337 </p> 4338 4338 <p> 4339 To compare satellite clocks provided by the two files, BNC first converts coordinate differences dX,dY,dZ 4340 into along track, out-of-plane, and radial components. It then corrects the clock differences for the radial 4341 components 4342 of coordinate differences. RMS values of clock differences are finally calculated after introducing at first one 4343 offset 4344 'per epoch for all satellites' and secondly one offset 'per satellite for all epochs'. 4339 To compare the orbits, BNC converts the coordinate differences dX,dY,dZ into radial, along-track and out-of-plane 4340 components, using the satellite velocity derived from neighbouring epochs. 4341 </p> 4342 <p> 4343 The clocks of two products usually differ by an offset common to all satellites of a system, which changes from 4344 epoch to epoch (clock datum), and by a constant offset per satellite (e.g. different realizations of the satellite 4345 code biases). For each system, BNC therefore estimates from all clock differences in a least-squares adjustment 4346 one offset 'per epoch for all satellites' and one offset 'per satellite for all epochs' (column 'Offset'), with 4347 the sum of the satellite offsets constrained to zero. The clock residuals of this adjustment ('clk') are then 4348 corrected for the radial component of the orbit differences ('clkRed'). The signal-in-space difference ('SIS', 4349 radial orbit difference minus clock difference) removes only the epoch offset, i.e. it contains the satellite 4350 offsets. 4351 </p> 4352 <p> 4353 The epoch offsets are eliminated from the normal equations before the satellite offsets are solved for; the 4354 result is identical to that of the complete adjustment. This keeps the comparison fast also for long or densely 4355 sampled files: comparing two daily files with 30-second sampling (2880 epochs) takes a few seconds. 4345 4356 </p> 4346 4357 <p><img src="IMG/Figure15.png" width=800 /></p> -
trunk/BNC/src/combination/bnccomb.cpp
r11079 r11083 1525 1525 // 30 min and are valid for ±900 s around the reference time (TOC). 1526 1526 // t_ephGlo::position() uses Runge-Kutta integration from TOC; beyond 1527 // ±900 s the integration error grows unchecked and propagates into both 1528 // the combined clock estimate and the SP3 position. 1527 // that the integration error grows and propagates into both the 1528 // combined clock estimate and the SP3 position. A margin of 60 s is 1529 // allowed, as ACs switch to the next ephemeris a few seconds before its 1530 // window begins (otherwise satellites drop out at every switch). 1529 1531 if (corr->_eph->prn().system() == 'R') { 1530 1532 double age = epoTime - corr->_eph->TOC(); 1531 if (fabs(age) > 9 00.0) {1533 if (fabs(age) > 960.0) { 1532 1534 emit newMessage(QString().asprintf( 1533 1535 "bncComb: skip %s, GLONASS eph age %.0fs", -
trunk/BNC/src/orbComp/sp3Comp.cpp
r11076 r11083 178 178 } 179 179 180 int nPar = epochs.size() + clkSats.size(); 181 SymmetricMatrix NN(nPar); NN = 0.0; 182 ColumnVector bb(nPar); bb = 0.0; 183 184 // Create Matrix A'A and vector b 185 // ------------------------------ 186 for (unsigned ie = 0; ie < epochs.size(); ie++) { 180 // Least-squares adjustment of an epoch-specific offset (common to all 181 // satellites) and a satellite-specific offset (common to all epochs), the 182 // sum of the satellite offsets constrained to zero (weight 1). The normal 183 // equations of the epoch offsets are diagonal, so these offsets are 184 // eliminated (Schur complement) and only the satellite offsets are solved 185 // for; the epoch offsets follow from them. The solution is identical to 186 // that of the full system, but the effort grows only linearly with the 187 // number of epochs (before: cubic). 188 // ----------------------------------------------------------------------- 189 int nEpo = epochs.size(); 190 int nSat = clkSats.size(); 191 int nPar = nEpo + nSat; 192 193 vector<vector<int> > satIdx(nEpo); // satellites (index) of each epoch 194 ColumnVector nEp(nEpo); nEp = 0.0; // number of satellites per epoch 195 ColumnVector bEp(nEpo); bEp = 0.0; // sum of the differences per epoch 196 SymmetricMatrix NS(nSat); NS = 1.0; // regularization: sum of satellite offsets 197 ColumnVector bS(nSat); bS = 0.0; 198 for (int ie = 0; ie < nEpo; ie++) { 187 199 const map<t_prn, double>& dc = epochs[ie]->_dc; 188 Matrix AA(dc.size(), nPar); AA = 0.0; 189 ColumnVector ll(dc.size()); ll = 0.0; 190 map<t_prn, double>::const_iterator it; 191 int ii = -1; 192 for (it = dc.begin(); it != dc.end(); it++) { 193 const t_prn& prn = it->first; 194 if (satIndex(clkSats, prn) != -1) { 195 ++ii; 196 int index = epochs.size() + satIndex(clkSats, prn); 197 AA[ii][ie] = 1.0; // epoch-specfic offset (common for all satellites) 198 AA[ii][index] = 1.0; // satellite-specific offset (common for all epochs) 199 ll[ii] = it->second; 200 } 201 } 202 SymmetricMatrix dN; dN << AA.t() * AA; 203 NN += dN; 204 bb += AA.t() * ll; 205 } 206 207 // Regularize NN 208 // ------------- 209 RowVector HH(nPar); 210 HH.columns(1, epochs.size()) = 0.0; 211 HH.columns(epochs.size()+1, nPar) = 1.0; 212 SymmetricMatrix dN; dN << HH.t() * HH; 213 NN += dN; 214 215 // Estimate Parameters 216 // ------------------- 217 ColumnVector xx = NN.i() * bb; 200 for (map<t_prn, double>::const_iterator it = dc.begin(); it != dc.end(); it++) { 201 int is = satIndex(clkSats, it->first); 202 if (is != -1) { 203 satIdx[ie].push_back(is); 204 nEp[ie] += 1.0; 205 bEp[ie] += it->second; 206 NS(is+1, is+1) += 1.0; 207 bS[is] += it->second; 208 } 209 } 210 } 211 212 // Eliminate the epoch offsets 213 // --------------------------- 214 for (int ie = 0; ie < nEpo; ie++) { 215 const vector<int>& idx = satIdx[ie]; 216 for (unsigned ia = 0; ia < idx.size(); ia++) { 217 bS[idx[ia]] -= bEp[ie] / nEp[ie]; 218 for (unsigned ib = 0; ib <= ia; ib++) { 219 NS(idx[ia]+1, idx[ib]+1) -= 1.0 / nEp[ie]; 220 } 221 } 222 } 223 224 // Estimate Parameters (epoch offsets first, then satellite offsets) 225 // --------------------------------------------------------------- 226 ColumnVector yy = NS.i() * bS; 227 ColumnVector xx(nPar); 228 for (int ie = 0; ie < nEpo; ie++) { 229 double sum = bEp[ie]; 230 for (unsigned ia = 0; ia < satIdx[ie].size(); ia++) { 231 sum -= yy[satIdx[ie][ia]]; 232 } 233 xx[ie] = sum / nEp[ie]; 234 } 235 for (int is = 0; is < nSat; is++) { 236 xx[nEpo + is] = yy[is]; 237 } 218 238 219 239 // Compute clock residuals -
trunk/BNC/tests/README.md
r11075 r11083 71 71 received stream again: `upload_rtnet` (IGS-SSR encoding, SP3/CLK/BIA files, 72 72 decoded `.ssr`), `upload_eph` (RTCM3 ephemerides to RINEX nav) and 73 `upload_raw` (raw forwarding to RINEX nav). 73 `upload_raw` (raw forwarding to RINEX nav). `upload_rtnet_rtcm` encodes the same input to RTCM-SSR 74 (message numbers 1057-1068, 1240-1270) and decodes it again. 74 75 * SSR decoding (`ssr_*`): 3 min slices of real streams replayed through 75 76 `03_BrdcCorr.bnc`. They compare the `.ssr` files and the `BNC_DEBUG_SSR` … … 79 80 * `ssr_rtcm_SSRA00CNE0`, `ssr_rtcm_WHU1_OSBC`: RTCM 1059-1270; these test 80 81 whichever class `RTCM3Decoder.cpp` selects for non-4076 SSR. 82 * `ssr_weekchange`: 2 min across the GPS week change (SSRA00CNE1, SSRA00CHC1); 83 corrections of Saturday received after midnight must keep their epochs. 81 84 * `ssr_qc`, `ssr_qc_select`: SSR QC (31_SsrQC, one file per stream, 5 min interval; 82 85 all streams resp. `ssrQcStreams SSRA00CNE1,SSRA00GMV0`) of the 7 AC streams of
Note:
See TracChangeset
for help on using the changeset viewer.
