Changeset 709 in ntrip
- Timestamp:
- Mar 7, 2008, 5:56:07 PM (17 years ago)
- Location:
- trunk/BNC
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/RTCM/RTCM2.cpp
r708 r709 45 45 // 2008/03/04 AHA Fixed problems with PRN 32 46 46 // 2008/03/05 AHA Implemeted fix for Trimble 4000SSI receivers 47 // 2008/03/07 AHA Major revision of input buffer handling 48 // 2008/03/07 AHA Removed unnecessary failure flag 47 49 // 48 50 // (c) DLR/GSOC … … 63 65 // undersized packets in get(Unsigned)Bits 64 66 65 #define DEBUG 0 67 #define DEBUG 0 66 68 67 69 // Activate (1) or deactivate (0) rounding of measurement epochs to 100ms … … 136 138 void ThirtyBitWord::clear() { 137 139 W = 0; 138 };139 140 // Failure indicator for input operations141 142 bool ThirtyBitWord::fail() const {143 return failure;144 140 }; 145 141 … … 259 255 260 256 261 262 257 // Append a byte with six data bits 263 258 … … 275 270 // Bits 7 and 6 (of 0..7) must be "01" for valid data bytes 276 271 if ( (b & 0x40) != 0x40 ) { 277 failure = true;272 // We simply skip the invalid input byte and leave the word unchanged 278 273 return; 279 274 }; … … 290 285 // Get next 30bit word from string 291 286 292 void ThirtyBitWord::get( string& buf) {287 void ThirtyBitWord::get(const string& buf) { 293 288 294 289 // Check if string is long enough 295 290 296 291 if (buf.size()<5) { 297 failure = true;292 // Ignore; users should avoid this case prior to calling get() 298 293 return; 299 294 }; … … 302 297 303 298 for (int i=0; i<5; i++) append(buf[i]); 304 buf.erase(0,5);305 299 306 300 #if (DEBUG>0) 307 301 if (!validParity()) { 308 cerr << "Parity error "302 cerr << "Parity error in get()" 309 303 << bitset<32>(all()) << endl; 310 304 }; 311 305 #endif 312 failure = false;313 306 314 307 }; … … 328 321 #if (DEBUG>0) 329 322 if (!validParity()) { 330 cerr << "Parity error "323 cerr << "Parity error in get()" 331 324 << bitset<32>(all()) << endl; 332 325 }; 333 326 #endif 334 failure = false;335 327 336 328 }; … … 340 332 void ThirtyBitWord::getHeader(string& buf) { 341 333 342 unsigned int W_old = W; 334 const int wordLen = 5; // Number of bytes representing a 30-bit word 335 const int spare = 1; // Number of spare words for resync of parity 336 // (same value as inRTCM2packet::getPacket()) 343 337 unsigned int i; 344 338 345 339 i=0; 346 while (!isHeader() || i<5 ) { 347 // Check if string is long enough; if not restore old word and exit 348 if (buf.size()<i+1) { 349 W = W_old; 350 failure = true; 351 return; 352 }; 340 while (!isHeader() && i<buf.size() ) { 353 341 // Process byte 354 append(buf[i]); i++; 355 }; 356 357 // Remove processed bytes from buffer 358 359 buf.erase(0,i); 342 append(buf[i]); 343 // Increment count 344 i++; 345 }; 346 347 // Remove processed bytes from buffer. Retain also the previous word to 348 // allow a resync if getHeader() is called repeatedly on the same buffer. 349 if (i>=(1+spare)*wordLen) buf.erase(0,i-(1+spare)*wordLen); 360 350 361 351 #if (DEBUG>0) 362 352 if (!validParity()) { 363 cerr << "Parity error "353 cerr << "Parity error in getHeader()" 364 354 << bitset<32>(all()) << endl; 365 355 }; 366 356 #endif 367 failure = false; 368 357 369 358 }; 370 359 … … 385 374 #if (DEBUG>0) 386 375 if (!validParity()) { 387 cerr << "Parity error "376 cerr << "Parity error in getHeader()" 388 377 << bitset<32>(all()) << endl; 389 378 }; 390 379 #endif 391 failure = false;392 380 393 381 }; … … 443 431 void RTCM2packet::getPacket(std::string& buf) { 444 432 445 int n; 446 ThirtyBitWord W_old = W; 447 string buf_old = buf; 448 449 // Try to read a full packet. If the input buffer is too short 450 // clear all data and restore the latest 30-bit word prior to 451 // the getPacket call. The empty header word will indicate 452 // an invalid message, which signals an unsuccessful getPacket() 453 // call. 454 455 W.getHeader(buf); 456 H1 = W.value(); 457 if (W.fail()) { clear(); W=W_old; buf=buf_old; return; }; 458 if (!W.validParity()) { clear(); return; }; 459 460 W.get(buf); 461 H2 = W.value(); 462 if (W.fail()) { clear(); W=W_old; buf=buf_old; return; }; 463 if (!W.validParity()) { clear(); return; }; 433 const int wordLen = 5; // Number of bytes representing a 30-bit word 434 const int spare = 1; // Number of spare words for resync of parity 435 // (same value as used in ThirtyBitWord::getHeader) 436 unsigned int n; 437 438 // Try to read a full packet. Processed bytes are removed from the input 439 // buffer except for the latest spare*wordLen bytes to restore the parity 440 // bytes upon subseqeunt calls of getPAcket(). 441 442 // Locate and read the first header word 443 W.getHeader(buf); 444 if (!W.isHeader()) { 445 // No header found; try again next time. buf retains only the spare 446 // words. The packet contents is cleared to indicate an unsuccessful 447 // termination of getPacket(). 448 clear(); 449 return; 450 }; 451 H1 = W.value(); 452 453 // Do we have enough bytes to read the next word? If not, the packet 454 // contents is cleared to indicate an unsuccessful termination. The 455 // previously read spare and header bytes are retained in the buffer 456 // for use in the next call of getPacket(). 457 if (buf.size()<(spare+2)*wordLen) { clear(); return; }; 458 459 // Read the second header word 460 W.get(buf.substr((spare+1)*wordLen,buf.size()-1-(spare+1)*wordLen)); 461 H2 = W.value(); 462 if (!W.validParity()) { 463 // Invalid H2 word; delete first buffer byte and try to resynch next time. 464 // The packet contents is cleared to indicate an unsuccessful termination. 465 clear(); 466 buf.erase(0,1); 467 return; 468 }; 464 469 465 470 n = nDataWords(); 471 472 // Do we have enough bytes to read the next word? If not, the packet 473 // contents is cleared to indicate an unsuccessful termination. The 474 // previously read spare and header bytes are retained in the buffer 475 // for use in the next call of getPacket(). 476 if (buf.size()<(spare+2+n)*wordLen) { clear(); return; }; 477 466 478 DW.resize(n); 467 for (int i=0; i<n; i++) { 468 W.get(buf); 469 DW[i] = W.value(); 470 if (W.fail()) { clear(); W=W_old; buf=buf_old; return; }; 471 if (!W.validParity()) { clear(); return; }; 472 }; 473 479 for (unsigned int i=0; i<n; i++) { 480 W.get(buf.substr((spare+2+i)*wordLen,buf.size()-1-(spare+2+i)*wordLen)); 481 DW[i] = W.value(); 482 if (!W.validParity()) { 483 // Invalid data word; delete first byte and try to resynch next time. 484 // The packet contents is cleared to indicate an unsuccessful termination. 485 clear(); 486 buf.erase(0,1); 487 return; 488 }; 489 }; 490 491 // Successful packet extraction; delete total number of message bytes 492 // from buffer. 493 // Note: a total of "spare" words remain in the buffer to enable a 494 // parity resynchronization when searching the next header. 495 496 buf.erase(0,(n+2)*wordLen); 497 474 498 return; 475 499 … … 487 511 W.getHeader(inp); 488 512 H1 = W.value(); 489 if ( W.fail() || !W.validParity()) { clear(); return; }513 if (inp.fail() || !W.isHeader()) { clear(); return; } 490 514 491 515 W.get(inp); 492 516 H2 = W.value(); 493 if ( W.fail() || !W.validParity()) { clear(); return; }517 if (inp.fail() || !W.validParity()) { clear(); return; } 494 518 495 519 n = nDataWords(); … … 498 522 W.get(inp); 499 523 DW[i] = W.value(); 500 if ( W.fail() || !W.validParity()) { clear(); return; }524 if (inp.fail() || !W.validParity()) { clear(); return; } 501 525 }; 502 526 -
trunk/BNC/RTCM/RTCM2.h
r332 r709 28 28 // 2006/10/17 OMO Removed obsolete check of multiple message indicator 29 29 // 2006/11/25 OMO Revised check for presence of GLONASS data 30 // 2008/03/07 AHA Removed unnecessary failure flag 30 31 // 31 32 // (c) DLR/GSOC … … 81 82 // Input 82 83 83 void get( std::string& buf);84 void get(const std::string& buf); 84 85 void get(std::istream& inp); 85 86 void getHeader(std::string& buf); … … 94 95 private: 95 96 96 bool failure;97 // bool failure; 97 98 98 99 // -
trunk/BNC/bncgetthread.cpp
r704 r709 117 117 _adviseScript = settings.value("adviseScript").toString(); 118 118 expandEnvVar(_adviseScript); 119 120 // Latency interval/average 121 // ------------------------ 122 _latIntr = 86400; 123 if ( settings.value("latIntr").toString().isEmpty() ) { _latIntr = 0; } 124 if ( settings.value("latIntr").toString().indexOf("1 min") != -1 ) { _latIntr = 60; } 125 if ( settings.value("latIntr").toString().indexOf("5 min") != -1 ) { _latIntr = 300; } 126 if ( settings.value("latIntr").toString().indexOf("15 min") != -1 ) { _latIntr = 900; } 127 if ( settings.value("latIntr").toString().indexOf("1 hour") != -1 ) { _latIntr = 3600; } 128 if ( settings.value("latIntr").toString().indexOf("6 hours") != -1 ) { _latIntr = 21600; } 129 if ( settings.value("latIntr").toString().indexOf("1 day") != -1 ) { _latIntr = 86400; } 119 130 120 131 // RINEX writer … … 377 388 void bncGetThread::run() { 378 389 390 const double maxDt = 600.0; // Check observation epoch 379 391 bool wrongEpoch = false; 380 392 bool decode = true; … … 382 394 int secSucc = 0; 383 395 int secFail = 0; 384 int initPause = 30; 396 int initPause = 30; // Initial pause for corrupted streams 385 397 int currPause = 0; 386 398 bool begCorrupt = false; 387 399 bool endCorrupt = false; 400 int oldSec= 0; 401 int newSec = 0; 402 int numLat = 0; 403 double sumLat = 0.; 404 double minLat = maxDt; 405 double maxLat = -maxDt; 406 double curLat = 0.; 407 double leapsec = 14.; // Leap second for latency estimation 388 408 389 409 _decodeTime = QDateTime::currentDateTime(); … … 539 559 540 560 const double secPerWeek = 7.0 * 24.0 * 3600.0; 541 const double maxDt = 600.0;542 561 543 562 if (week < obs->_o.GPSWeek) { … … 560 579 else { 561 580 wrongEpoch = false; 581 582 // Latency 583 // ------- 584 if (_latIntr>0) { 585 newSec = static_cast<int>(sec); 586 if (newSec != oldSec) { 587 if (newSec % _latIntr < oldSec % _latIntr) { 588 if (numLat>0) { 589 emit( newMessage(QString("%1: %2 sec mean latency, min %3, max %4") 590 .arg(_staID.data()) 591 .arg(int(sumLat/numLat*100)/100.) 592 .arg(int(minLat*100)/100.) 593 .arg(int(maxLat*100)/100.) 594 .toAscii()) ); 595 } 596 sumLat = 0.; 597 numLat = 0; 598 minLat = maxDt; 599 maxLat = -maxDt; 600 } 601 curLat = sec - obs->_o.GPSWeeks + leapsec; 602 sumLat += curLat; 603 if (curLat < minLat) minLat = curLat; 604 if (curLat >= maxLat) maxLat = curLat; 605 numLat += 1; 606 oldSec = newSec; 607 } 608 } 562 609 } 563 610 -
trunk/BNC/bncgetthread.h
r699 r709 88 88 int _adviseFail; 89 89 int _adviseReco; 90 int _latIntr; 90 91 int _timeOut; 91 92 int _nextSleep; -
trunk/BNC/bnchelp.html
r705 r709 85 85 3.8.3. <a href=#advreco>Recovery Threshold</a><br> 86 86 3.8.4. <a href=#advscript>Advisory Script</a><br> 87 3.8.5. <a href=#meanlate>Mean Latency</a><br> 87 88 3.9. <a href=#mountpoints>Mountpoints</a><br> 88 89 3.9.1. <a href=#mountadd>Add Mountpoints</a><br> … … 438 439 </p> 439 440 441 <p><a name="meanlate"><h4>3.8.5 Mean Latency - optional </h4></p> 442 <p> 443 Latency is defined here through the following equation: 444 </p> 445 <p> 446 (a) UTC time provided by BNC's host, minus<br> 447 (b) GPS time of currently processed epoch, plus<br> 448 (c) Number of leap seconds between UTC and GPS time (hard-coded to 14). 449 </p> 450 <p>BNC can average all latencies per stream over a certain period. The resulting mean latencies are recorded in the Log file/section at the end of each 'Mean latency' interval. Select a 'Mean latency' interval or select the empty option field if you do not want BNC to log latency information. 451 </p> 452 440 453 <p><a name="mountpoints"><h4>3.9. Mountpoints</h4></p> 441 454 <p> -
trunk/BNC/bncmain.cpp
r686 r709 84 84 settings.setValue("adviseFail", "15"); 85 85 settings.setValue("adviseReco", "5"); 86 settings.setValue("latIntr", ""); 86 87 } 87 88 -
trunk/BNC/bncwindow.cpp
r705 r709 177 177 _logFileLineEdit = new QLineEdit(settings.value("logFile").toString()); 178 178 _adviseScriptLineEdit = new QLineEdit(settings.value("adviseScript").toString()); 179 180 _latIntrComboBox = new QComboBox(); 181 _latIntrComboBox->setMaximumWidth(9*ww); 182 _latIntrComboBox->setEditable(false); 183 _latIntrComboBox->addItems(QString(",1 min,5 min,15 min,1 hour,6 hours,1 day").split(",")); 184 int ll = _latIntrComboBox->findText(settings.value("latIntr").toString()); 185 if (ll != -1) { 186 _latIntrComboBox->setCurrentIndex(ll); 187 } 188 179 189 _mountPointsTable = new QTableWidget(0,7); 180 190 … … 273 283 _logFileLineEdit->setWhatsThis(tr("Records of BNC's activities are shown in the Log section on the bottom of this window. They can be saved into a file when a valid path is specified in the 'Logfile (full path)' field.")); 274 284 _adviseScriptLineEdit->setWhatsThis(tr("<p>Specify the full path to a script or batch file to handle advisory notes generated in the event of corrupted streams or stream outages. The affected mountpoint and one of the comments 'Begin_Outage', 'End_Outage', 'Begin_Corrupted', or 'End_Corrupted' are passed on to the script as command line parameters.</p><p>The script can be configured to send an email to BNC's operator and/or to the affected stream provider. An empty option field (default) or invalid path means that you don't want to use this option.</p>")); 285 _latIntrComboBox->setWhatsThis(tr("<p>BNC can average all latencies per stream over a certain period. The resulting mean latencies are recorded in the Log file/section at the end of each 'Mean latency' interval.</p><p>Select a 'Mean latency' interval or select the empty option field if you do not want BNC to log latency information.</p>")); 275 286 _mountPointsTable->setWhatsThis(tr("<p>Streams selected for retrieval are listed in the 'Mountpoints' section. Clicking on 'Add Mountpoints' button will open a window that allows the user to select data streams from an NTRIP broadcaster according to their mountpoints. To remove a stream from the 'Mountpoints' list, highlight it by clicking on it and hit the 'Delete Mountpoints' button. You can also remove multiple mountpoints by highlighting them using +Shift and +Ctrl.</p><p>BNC automatically allocates one of its internal decoders to a stream based on the stream's 'format' and 'format-details' as given in the sourcetable. However, there might be cases where you need to override the automatic selection due to incorrect sourcetable for example. BNC allows users to manually select the required decoder by editing the decoder string. Double click on the 'decoder' field, enter your preferred decoder and then hit Enter. The accepted decoder strings are 'RTCM_2.x', 'RTCM_3.x', and 'RTIGS'.</p><p>In case you need to log the raw data as is, BNC allows users to by-pass its decoders and and directly save the input in daily log files. To do this specify the decoder string as 'ZERO'.</p><p>BNC can also retrieve streams from virtual reference stations (VRS). To initiate these streams, an approximate rover position needs to be sent in NMEA GGA message to the NTRIP broadcaster. In return, a user-specific data stream is generated, typically by a Network-RTK software. This stream is customized to the exact latitude and longitude as shown in the 'lat' and 'long' columns under 'Mountpoints'. These VRS streams are indicated by a 'yes' in the 'nmea' column under 'Mountpoints' as well as in the sourcetable. The default 'lat' and 'long' values are taken from the sourcetable. However, in most cases you would probably want to change this according to your requirement. Double click on 'lat' and 'long' fields, enter the values you wish to send and then hit Enter. The format is in positive north latitude degrees (e.g. for northern hemisphere: 52.436, for southern hemisphere: -24.567) and eastern longitude degrees (e.g.: 358.872 or -1.128). Only mountpoints with a 'yes' in its 'nmea' column can be edited. The position should preferably be a point within the coverage of the network.</p>")); 276 287 _log->setWhatsThis(tr("Records of BNC's activities are shown in the Log section. The message log covers the communication status between BNC and the NTRIP broadcaster as well as any problems that occur in the communication link, stream availability, stream delay, stream conversion etc.")); … … 358 369 aLayout->addWidget(new QLabel("Script (full path)"), 3, 0); 359 370 aLayout->addWidget(_adviseScriptLineEdit, 3, 1); 360 aLayout->addWidget(new QLabel("Network monitoring, handling of corrupted streams."),4,0,1,2,Qt::AlignLeft); 361 aLayout->addWidget(new QLabel(" "),5,0); 371 aLayout->addWidget(new QLabel("Mean latency"), 4, 0); 372 aLayout->addWidget(_latIntrComboBox, 4, 1); 373 aLayout->addWidget(new QLabel("Network monitoring, handling of corrupted streams, latency logging."),5,0,1,2,Qt::AlignLeft); 362 374 agroup->setLayout(aLayout); 363 375 … … 518 530 settings.setValue("adviseReco", _adviseRecoSpinBox->value()); 519 531 settings.setValue("outFile", _outFileLineEdit->text()); 532 settings.setValue("latIntr", _latIntrComboBox->currentText()); 520 533 settings.setValue("outPort", _outPortLineEdit->text()); 521 534 settings.setValue("outEphPort", _outEphPortLineEdit->text()); -
trunk/BNC/bncwindow.h
r686 r709 106 106 QSpinBox* _adviseRecoSpinBox; 107 107 QLineEdit* _adviseScriptLineEdit; 108 QComboBox* _latIntrComboBox; 108 109 QTableWidget* _mountPointsTable; 109 110
Note:
See TracChangeset
for help on using the changeset viewer.