Changeset 709 in ntrip


Ignore:
Timestamp:
Mar 7, 2008, 5:56:07 PM (16 years ago)
Author:
weber
Message:

* empty log message *

Location:
trunk/BNC
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/RTCM/RTCM2.cpp

    r708 r709  
    4545//   2008/03/04  AHA  Fixed problems with PRN 32
    4646//   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
    4749//
    4850// (c) DLR/GSOC
     
    6365// undersized packets in get(Unsigned)Bits
    6466
    65 #define DEBUG 0   
     67#define DEBUG 0
    6668
    6769// Activate (1) or deactivate (0) rounding of measurement epochs to 100ms
     
    136138void ThirtyBitWord::clear() {
    137139  W = 0;
    138 };
    139 
    140 // Failure indicator for input operations
    141 
    142 bool ThirtyBitWord::fail() const {
    143   return failure;
    144140};
    145141
     
    259255
    260256
    261 
    262257// Append a byte with six data bits
    263258
     
    275270  // Bits 7 and 6 (of 0..7) must be "01" for valid data bytes
    276271  if ( (b & 0x40) != 0x40 ) {
    277     failure = true;
     272    // We simply skip the invalid input byte and leave the word unchanged
    278273    return;
    279274  };
     
    290285// Get next 30bit word from string
    291286
    292 void ThirtyBitWord::get(string& buf) {
     287void ThirtyBitWord::get(const string& buf) {
    293288
    294289  // Check if string is long enough
    295290   
    296291  if (buf.size()<5) {
    297     failure = true;
     292    // Ignore; users should avoid this case prior to calling get()
    298293    return;
    299294  };
     
    302297 
    303298  for (int i=0; i<5; i++) append(buf[i]);
    304   buf.erase(0,5);
    305299
    306300#if (DEBUG>0)
    307301  if (!validParity()) {
    308     cerr << "Parity error "
     302    cerr << "Parity error in get()"
    309303         << bitset<32>(all()) << endl;
    310304  };
    311305#endif
    312   failure = false;
    313306
    314307};
     
    328321#if (DEBUG>0)
    329322  if (!validParity()) {
    330     cerr << "Parity error "
     323    cerr << "Parity error in get()"
    331324         << bitset<32>(all()) << endl;
    332325  };
    333326#endif
    334   failure = false;
    335327
    336328};
     
    340332void ThirtyBitWord::getHeader(string& buf) {
    341333
    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())
    343337  unsigned int i;
    344338 
    345339  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() ) {
    353341    // 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);
    360350
    361351#if (DEBUG>0)
    362352  if (!validParity()) {
    363     cerr << "Parity error "
     353    cerr << "Parity error in getHeader()"
    364354         << bitset<32>(all()) << endl;
    365355  };
    366356#endif
    367   failure = false;
    368 
     357 
    369358};
    370359
     
    385374#if (DEBUG>0)
    386375  if (!validParity()) {
    387     cerr << "Parity error "
     376    cerr << "Parity error in getHeader()"
    388377         << bitset<32>(all()) << endl;
    389378  };
    390379#endif
    391   failure = false;
    392380
    393381};
     
    443431void RTCM2packet::getPacket(std::string& buf) {
    444432
    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  };
    464469
    465470  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 
    466478  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 
    474498  return;
    475499 
     
    487511  W.getHeader(inp);
    488512  H1 = W.value();
    489   if (W.fail() || !W.validParity()) { clear(); return; }
     513  if (inp.fail() || !W.isHeader()) { clear(); return; }
    490514 
    491515  W.get(inp);       
    492516  H2 = W.value();
    493   if (W.fail() || !W.validParity()) { clear(); return; }
     517  if (inp.fail() || !W.validParity()) { clear(); return; }
    494518
    495519  n = nDataWords();
     
    498522    W.get(inp);
    499523    DW[i] = W.value();
    500     if (W.fail() || !W.validParity()) { clear(); return; }
     524    if (inp.fail() || !W.validParity()) { clear(); return; }
    501525  };
    502526
  • trunk/BNC/RTCM/RTCM2.h

    r332 r709  
    2828//   2006/10/17  OMO  Removed obsolete check of multiple message indicator
    2929//   2006/11/25  OMO  Revised check for presence of GLONASS data
     30//   2008/03/07  AHA  Removed unnecessary failure flag
    3031//
    3132// (c) DLR/GSOC
     
    8182    // Input
    8283   
    83     void         get(std::string& buf);
     84    void         get(const std::string& buf);
    8485    void         get(std::istream& inp);
    8586    void         getHeader(std::string& buf);
     
    9495  private:
    9596
    96     bool         failure;
     97//    bool         failure;
    9798
    9899    //
  • trunk/BNC/bncgetthread.cpp

    r704 r709  
    117117  _adviseScript = settings.value("adviseScript").toString();
    118118  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; }
    119130
    120131  // RINEX writer
     
    377388void bncGetThread::run() {
    378389
     390  const double maxDt = 600.0;  // Check observation epoch
    379391  bool wrongEpoch = false;
    380392  bool decode = true;
     
    382394  int secSucc = 0;
    383395  int secFail = 0;
    384   int initPause = 30;
     396  int initPause = 30;  // Initial pause for corrupted streams
    385397  int currPause = 0;
    386398  bool begCorrupt = false;
    387399  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
    388408
    389409  _decodeTime = QDateTime::currentDateTime();
     
    539559         
    540560          const double secPerWeek = 7.0 * 24.0 * 3600.0;
    541           const double maxDt      = 600.0;           
    542561
    543562          if (week < obs->_o.GPSWeek) {
     
    560579          else {
    561580            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            }
    562609          }
    563610
  • trunk/BNC/bncgetthread.h

    r699 r709  
    8888   int         _adviseFail;
    8989   int         _adviseReco;
     90   int         _latIntr;
    9091   int         _timeOut;
    9192   int         _nextSleep;
  • trunk/BNC/bnchelp.html

    r705 r709  
    8585&nbsp; &nbsp; &nbsp; 3.8.3. <a href=#advreco>Recovery Threshold</a><br>
    8686&nbsp; &nbsp; &nbsp; 3.8.4. <a href=#advscript>Advisory Script</a><br>
     87&nbsp; &nbsp; &nbsp; 3.8.5. <a href=#meanlate>Mean Latency</a><br>
    87883.9. <a href=#mountpoints>Mountpoints</a><br>
    8889&nbsp; &nbsp; &nbsp; 3.9.1. <a href=#mountadd>Add Mountpoints</a><br>
     
    438439</p>
    439440
     441<p><a name="meanlate"><h4>3.8.5 Mean Latency - optional </h4></p>
     442<p>
     443Latency 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
    440453<p><a name="mountpoints"><h4>3.9. Mountpoints</h4></p>
    441454<p>
  • trunk/BNC/bncmain.cpp

    r686 r709  
    8484    settings.setValue("adviseFail", "15");
    8585    settings.setValue("adviseReco", "5");
     86    settings.setValue("latIntr",    "");
    8687  }
    8788
  • trunk/BNC/bncwindow.cpp

    r705 r709  
    177177  _logFileLineEdit    = new QLineEdit(settings.value("logFile").toString());
    178178  _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
    179189  _mountPointsTable   = new QTableWidget(0,7);
    180190
     
    273283  _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."));
    274284  _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>"));
    275286  _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>"));
    276287  _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."));
     
    358369  aLayout->addWidget(new QLabel("Script (full path)"),            3, 0);
    359370  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);
    362374  agroup->setLayout(aLayout);
    363375
     
    518530  settings.setValue("adviseReco",  _adviseRecoSpinBox->value());
    519531  settings.setValue("outFile",     _outFileLineEdit->text());
     532  settings.setValue("latIntr",     _latIntrComboBox->currentText());
    520533  settings.setValue("outPort",     _outPortLineEdit->text());
    521534  settings.setValue("outEphPort",  _outEphPortLineEdit->text());
  • trunk/BNC/bncwindow.h

    r686 r709  
    106106    QSpinBox*  _adviseRecoSpinBox;
    107107    QLineEdit* _adviseScriptLineEdit;
     108    QComboBox* _latIntrComboBox;
    108109    QTableWidget* _mountPointsTable;
    109110
Note: See TracChangeset for help on using the changeset viewer.