Changeset 10657 in ntrip for trunk/BNC/src/upload


Ignore:
Timestamp:
Jun 2, 2025, 9:22:52 AM (6 months ago)
Author:
stuerze
Message:

upload to caster revised

Location:
trunk/BNC/src/upload
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/src/upload/bncrtnetuploadcaster.cpp

    r10616 r10657  
    3737    bncUploadCaster(mountpoint, outHost, outPort, ntripVersion, userName, password, iRow, 0) {
    3838
    39   if (!mountpoint.isEmpty()) {
    40     _casterID += mountpoint;
    41   }
    42   if (!outHost.isEmpty()) {
    43     _casterID +=  " " + outHost;
    44     if (outPort) {
    45       _casterID += ":" +  QString("%1").arg(outPort, 10);
    46     }
    47   }
    48   if (!crdTrafo.isEmpty()) {
    49     _casterID += " " + crdTrafo;
    50   }
    51   if (!sp3FileName.isEmpty()) {
    52     _casterID += " " + sp3FileName;
    53   }
    54   if (!rnxFileName.isEmpty()) {
    55     _casterID += " " + rnxFileName;
    56   }
    57 
    58   if (!bsxFileName.isEmpty()) {
    59     _casterID += " " + bsxFileName;
    60   }
    61 
    62   _crdTrafoStr = crdTrafo;
    63 
    64   _ssrFormat = ssrFormat;
    65 
    66   _ssrCorr = 0;
    67   if      (_ssrFormat == "IGS-SSR") {
    68     _ssrCorr = new SsrCorrIgs();
    69   }
    70   else if (_ssrFormat == "RTCM-SSR") {
    71     _ssrCorr = new SsrCorrRtcm();
    72   }
    73 
    74   _CoM = CoM;
    75   _PID = PID;
    76   _SID = SID;
    77   _IOD = IOD;
    78   _phaseBiasInformationDecoded = false;
    79 
    80   // Member that receives the ephemeris
    81   // ----------------------------------
    82   _ephUser = new bncEphUser(true);
    83 
    84   bncSettings settings;
    85   QString intr = settings.value("uploadIntr").toString();
    86   QStringList hlp = settings.value("cmbStreams").toStringList();
    87   _samplRtcmEphCorr = settings.value("uploadSamplRtcmEphCorr").toDouble();
    88   if (hlp.size() > 1) { // combination stream upload
    89     _samplRtcmClkCorr = settings.value("cmbSampl").toInt();
    90   }
    91   else { // single stream upload or sp3 file generation
    92     _samplRtcmClkCorr = 5; // default
    93   }
    94   _samplRtcmVtec = 60.0;
    95   _samplRtcmCrs  = 60.0;
    96   int samplClkRnx = settings.value("uploadSamplClkRnx").toInt();
    97   int samplSp3    = settings.value("uploadSamplSp3").toString().split("sec").first().toInt();
    98   int samplBiaSnx = settings.value("uploadSamplBiaSnx").toInt();
    99 
    100   if (_samplRtcmEphCorr == 0.0) {
    101     _usedEph = 0;
    102   }
    103   else {
    104     _usedEph = new QMap<QString, const t_eph*>;
    105   }
    106 
    107   // RINEX writer
    108   // ------------
    109   if (!rnxFileName.isEmpty()) {
    110     _rnx = new bncClockRinex(rnxFileName, intr, samplClkRnx);
    111   }
    112   else {
    113     _rnx = 0;
    114   }
    115 
    116   // SP3 writer
    117   // ----------
    118   if (!sp3FileName.isEmpty()) {
    119     _sp3 = new bncSP3(sp3FileName, intr, samplSp3);
    120   }
    121   else {
    122     _sp3 = 0;
    123   }
    124 
    125   // SINEX writer
    126   // ------------
    127   if (!bsxFileName.isEmpty()) {
    128     _bsx = new bncBiasSinex(bsxFileName, intr, samplBiaSnx);
    129   }
    130   else {
    131     _bsx = 0;
    132   }
    133 
    134 
    135   // Set Transformation Parameters
    136   // -----------------------------
    137   // Transformation Parameters from ITRF2014 to ETRF2000
    138   // http://etrs89.ign.fr/pub/EUREF-TN-1-Mar-04-2024.pdf
    139   if (_crdTrafoStr == "ETRF2000") {
    140     _dx  =  0.0552;
    141     _dy  =  0.0527;
    142     _dz  = -0.0836;
    143 
    144     _dxr =  0.0001;
    145     _dyr =  0.0001;
    146     _dzr = -0.0019;
    147 
    148     _ox  =  0.002106;
    149     _oy  =  0.012740;
    150     _oz  = -0.020592;
    151 
    152     _oxr =  0.000081;
    153     _oyr =  0.000490;
    154     _ozr = -0.000792;
    155 
    156     _sc  =  2.67;
    157     _scr =  0.11;
    158 
    159     _t0  =  2015.0;
    160   }
    161   // Transformation Parameters from ITRF2014 to GDA2020 (Ryan Ruddick, GA)
    162   else if (_crdTrafoStr == "GDA2020") {
    163     _dx  = 0.0;
    164     _dy  = 0.0;
    165     _dz  = 0.0;
    166 
    167     _dxr = 0.0;
    168     _dyr = 0.0;
    169     _dzr = 0.0;
    170 
    171     _ox  = 0.0;
    172     _oy  = 0.0;
    173     _oz  = 0.0;
    174 
    175     _oxr = 0.00150379;
    176     _oyr = 0.00118346;
    177     _ozr = 0.00120716;
    178 
    179     _sc  = 0.0;
    180     _scr = 0.0;
    181 
    182     _t0  = 2020.0;
    183   }
    184   // Transformation Parameters from IGb14 to SIRGAS2000 (Thanks to Sonia Costa, BRA)
    185   // June 29 2020: TX:-0.0027 m  TY:-0.0025 m  TZ:-0.0042 m  SCL:1.20 (ppb) no rotations and no rates.*/
    186   else if (_crdTrafoStr == "SIRGAS2000") {
    187     _dx  = -0.0027;
    188     _dy  = -0.0025;
    189     _dz  = -0.0042;
    190 
    191     _dxr =  0.0;
    192     _dyr =  0.0;
    193     _dzr =  0.0;
    194 
    195     _ox  =  0.0;
    196     _oy  =  0.0;
    197     _oz  =  0.0;
    198 
    199     _oxr =  0.0;
    200     _oyr =  0.0;
    201     _ozr =  0.0;
    202 
    203     _sc  =  1.2;
    204     _scr =  0.0;
    205     _t0  =  2000.0;
    206   }
    207   // Transformation Parameters from ITRF2014 to DREF91
    208   else if (_crdTrafoStr == "DREF91") {
    209     _dx  =  0.0547;
    210     _dy  =  0.0522;
    211     _dz  = -0.0741;
    212 
    213     _dxr =  0.0001;
    214     _dyr =  0.0001;
    215     _dzr = -0.0019;
    216     // ERTF200  + rotation parameters (ETRF2000 => DREF91)
    217     _ox  =  0.001701 + 0.000658;
    218     _oy  =  0.010290 - 0.000208;
    219     _oz  = -0.016632 + 0.000755;
    220 
    221     _oxr =  0.000081;
    222     _oyr =  0.000490;
    223     _ozr = -0.000729;
    224 
    225     _sc  =  2.12;
    226     _scr =  0.11;
    227 
    228     _t0  =  2010.0;
    229   }
    230   else if (_crdTrafoStr == "Custom") {
    231     _dx = settings.value("trafo_dx").toDouble();
    232     _dy = settings.value("trafo_dy").toDouble();
    233     _dz = settings.value("trafo_dz").toDouble();
    234     _dxr = settings.value("trafo_dxr").toDouble();
    235     _dyr = settings.value("trafo_dyr").toDouble();
    236     _dzr = settings.value("trafo_dzr").toDouble();
    237     _ox = settings.value("trafo_ox").toDouble();
    238     _oy = settings.value("trafo_oy").toDouble();
    239     _oz = settings.value("trafo_oz").toDouble();
    240     _oxr = settings.value("trafo_oxr").toDouble();
    241     _oyr = settings.value("trafo_oyr").toDouble();
    242     _ozr = settings.value("trafo_ozr").toDouble();
    243     _sc = settings.value("trafo_sc").toDouble();
    244     _scr = settings.value("trafo_scr").toDouble();
    245     _t0 = settings.value("trafo_t0").toDouble();
    246   }
     39    if (!mountpoint.isEmpty()) {
     40        _casterID += mountpoint;
     41    }
     42    if (!outHost.isEmpty()) {
     43        _casterID += " " + outHost;
     44        if (outPort) {
     45            _casterID += ":" + QString("%1").arg(outPort, 10);
     46        }
     47    }
     48    if (!crdTrafo.isEmpty()) {
     49        _casterID += " " + crdTrafo;
     50    }
     51    if (!sp3FileName.isEmpty()) {
     52        _casterID += " " + sp3FileName;
     53    }
     54    if (!rnxFileName.isEmpty()) {
     55        _casterID += " " + rnxFileName;
     56    }
     57
     58    if (!bsxFileName.isEmpty()) {
     59        _casterID += " " + bsxFileName;
     60    }
     61
     62    _crdTrafoStr = crdTrafo;
     63
     64    _ssrFormat = ssrFormat;
     65
     66    _ssrCorr = 0;
     67    if (_ssrFormat == "IGS-SSR") {
     68        _ssrCorr = new SsrCorrIgs();
     69    }
     70    else if (_ssrFormat == "RTCM-SSR") {
     71        _ssrCorr = new SsrCorrRtcm();
     72    }
     73
     74    _CoM = CoM;
     75    _PID = PID;
     76    _SID = SID;
     77    _IOD = IOD;
     78    _phaseBiasInformationDecoded = false;
     79
     80    // Member that receives the ephemeris
     81    // ----------------------------------
     82    _ephUser = new bncEphUser(true);
     83
     84    bncSettings settings;
     85    QString intr      = settings.value("uploadIntr").toString();
     86    QStringList hlp   = settings.value("cmbStreams").toStringList();
     87    _samplRtcmEphCorr = settings.value("uploadSamplRtcmEphCorr").toString().split("sec").first().toDouble();
     88
     89    if (hlp.size() > 1) { // combination stream upload
     90        _samplRtcmClkCorr = settings.value("cmbSampl").toString().split("sec").first().toDouble();
     91    }
     92    else { // single stream upload or sp3 file generation
     93        _samplRtcmClkCorr = 5.0; // default
     94    }
     95    _samplRtcmVtec = 60.0;
     96    _samplRtcmCrs = 60.0;
     97    int samplClkRnx = settings.value("uploadSamplClkRnx").toString().split("sec").first().toInt();
     98    int samplSp3    = settings.value("uploadSamplSp3").toString().split("sec").first().toInt();
     99    int samplBiaSnx = settings.value("uploadSamplBiaSnx").toString().split("sec").first().toInt();
     100
     101    if (_samplRtcmEphCorr == 0.0) {
     102        _usedEph = 0;
     103    }
     104    else {
     105        _usedEph = new QMap<QString, const t_eph*>;
     106    }
     107
     108    // RINEX writer
     109    // ------------
     110    if (!rnxFileName.isEmpty()) {
     111        _rnx = new bncClockRinex(rnxFileName, intr, samplClkRnx);
     112    }
     113    else {
     114        _rnx = 0;
     115    }
     116
     117    // SP3 writer
     118    // ----------
     119    if (!sp3FileName.isEmpty()) {
     120        _sp3 = new bncSP3(sp3FileName, intr, samplSp3);
     121    }
     122    else {
     123        _sp3 = 0;
     124    }
     125
     126    // SINEX writer
     127    // ------------
     128    if (!bsxFileName.isEmpty()) {
     129        _bsx = new bncBiasSinex(bsxFileName, intr, samplBiaSnx);
     130    }
     131    else {
     132        _bsx = 0;
     133    }
     134
     135
     136    // Set Transformation Parameters
     137    // -----------------------------
     138    // Transformation Parameters from ITRF2014 to ETRF2000
     139    // http://etrs89.ign.fr/pub/EUREF-TN-1-Mar-04-2024.pdf
     140    if (_crdTrafoStr == "ETRF2000") {
     141        _dx = 0.0552;
     142        _dy = 0.0527;
     143        _dz = -0.0836;
     144
     145        _dxr = 0.0001;
     146        _dyr = 0.0001;
     147        _dzr = -0.0019;
     148
     149        _ox = 0.002106;
     150        _oy = 0.012740;
     151        _oz = -0.020592;
     152
     153        _oxr = 0.000081;
     154        _oyr = 0.000490;
     155        _ozr = -0.000792;
     156
     157        _sc = 2.67;
     158        _scr = 0.11;
     159
     160        _t0 = 2015.0;
     161    }
     162    // Transformation Parameters from ITRF2014 to GDA2020 (Ryan Ruddick, GA)
     163    else if (_crdTrafoStr == "GDA2020") {
     164        _dx = 0.0;
     165        _dy = 0.0;
     166        _dz = 0.0;
     167
     168        _dxr = 0.0;
     169        _dyr = 0.0;
     170        _dzr = 0.0;
     171
     172        _ox = 0.0;
     173        _oy = 0.0;
     174        _oz = 0.0;
     175
     176        _oxr = 0.00150379;
     177        _oyr = 0.00118346;
     178        _ozr = 0.00120716;
     179
     180        _sc = 0.0;
     181        _scr = 0.0;
     182
     183        _t0 = 2020.0;
     184    }
     185    // Transformation Parameters from IGb14 to SIRGAS2000 (Thanks to Sonia Costa, BRA)
     186    // June 29 2020: TX:-0.0027 m  TY:-0.0025 m  TZ:-0.0042 m  SCL:1.20 (ppb) no rotations and no rates.*/
     187    else if (_crdTrafoStr == "SIRGAS2000") {
     188        _dx = -0.0027;
     189        _dy = -0.0025;
     190        _dz = -0.0042;
     191
     192        _dxr = 0.0;
     193        _dyr = 0.0;
     194        _dzr = 0.0;
     195
     196        _ox = 0.0;
     197        _oy = 0.0;
     198        _oz = 0.0;
     199
     200        _oxr = 0.0;
     201        _oyr = 0.0;
     202        _ozr = 0.0;
     203
     204        _sc = 1.2;
     205        _scr = 0.0;
     206        _t0 = 2000.0;
     207    }
     208    // Transformation Parameters from ITRF2014 to DREF91
     209    else if (_crdTrafoStr == "DREF91") {
     210        _dx = 0.0547;
     211        _dy = 0.0522;
     212        _dz = -0.0741;
     213
     214        _dxr = 0.0001;
     215        _dyr = 0.0001;
     216        _dzr = -0.0019;
     217        // ERTF200  + rotation parameters (ETRF2000 => DREF91)
     218        _ox = 0.001701 + 0.000658;
     219        _oy = 0.010290 - 0.000208;
     220        _oz = -0.016632 + 0.000755;
     221
     222        _oxr = 0.000081;
     223        _oyr = 0.000490;
     224        _ozr = -0.000729;
     225
     226        _sc = 2.12;
     227        _scr = 0.11;
     228
     229        _t0 = 2010.0;
     230    }
     231    else if (_crdTrafoStr == "Custom") {
     232        _dx = settings.value("trafo_dx").toDouble();
     233        _dy = settings.value("trafo_dy").toDouble();
     234        _dz = settings.value("trafo_dz").toDouble();
     235        _dxr = settings.value("trafo_dxr").toDouble();
     236        _dyr = settings.value("trafo_dyr").toDouble();
     237        _dzr = settings.value("trafo_dzr").toDouble();
     238        _ox = settings.value("trafo_ox").toDouble();
     239        _oy = settings.value("trafo_oy").toDouble();
     240        _oz = settings.value("trafo_oz").toDouble();
     241        _oxr = settings.value("trafo_oxr").toDouble();
     242        _oyr = settings.value("trafo_oyr").toDouble();
     243        _ozr = settings.value("trafo_ozr").toDouble();
     244        _sc = settings.value("trafo_sc").toDouble();
     245        _scr = settings.value("trafo_scr").toDouble();
     246        _t0 = settings.value("trafo_t0").toDouble();
     247    }
    247248    // TODO: the following lines can be deleted if all parameters are updated regarding ITRF2020
    248   if (_crdTrafoStr == "ETRF2000" ||
    249       _crdTrafoStr == "GDA2020"  ||
    250       _crdTrafoStr == "DREF91"  ||
    251       _crdTrafoStr == "SIRGAS2000") {
    252        // Transformation Parameters from ITRF2020 to ITRF2014
    253        // from ITRF web site: https://itrf.ign.fr/en/solutions/transformations
    254    _dx14 = -0.0014;
    255    _dy14 = -0.0009;
    256    _dz14  = 0.0014;
    257    _dxr14 =  0.0;
    258    _dyr14 = -0.0001;
    259    _dzr14 = -0.0002;
    260    _ox14  = 0.0;
    261    _oy14  = 0.0;
    262    _oz14  = 0.0;
    263    _oxr14 =  0.0;
    264    _oyr14 =  0.0;
    265    _ozr14 =  0.0;
    266    _sc14 = -0.42;
    267    _scr14 =  0.0;
    268    _t014  = 2015.0;
    269  }
     249    if (_crdTrafoStr == "ETRF2000" ||
     250        _crdTrafoStr == "GDA2020" ||
     251        _crdTrafoStr == "DREF91" ||
     252        _crdTrafoStr == "SIRGAS2000") {
     253        // Transformation Parameters from ITRF2020 to ITRF2014
     254        // from ITRF web site: https://itrf.ign.fr/en/solutions/transformations
     255        _dx14 = -0.0014;
     256        _dy14 = -0.0009;
     257        _dz14 = 0.0014;
     258        _dxr14 = 0.0;
     259        _dyr14 = -0.0001;
     260        _dzr14 = -0.0002;
     261        _ox14 = 0.0;
     262        _oy14 = 0.0;
     263        _oz14 = 0.0;
     264        _oxr14 = 0.0;
     265        _oyr14 = 0.0;
     266        _ozr14 = 0.0;
     267        _sc14 = -0.42;
     268        _scr14 = 0.0;
     269        _t014 = 2015.0;
     270    }
    270271}
    271272
     
    273274////////////////////////////////////////////////////////////////////////////
    274275bncRtnetUploadCaster::~bncRtnetUploadCaster() {
    275   if (isRunning()) {
    276     wait();
    277   }
    278   delete _rnx;
    279   delete _sp3;
    280   delete _ephUser;
    281   delete _usedEph;
    282   delete _ssrCorr;
     276    if (isRunning()) {
     277        wait();
     278    }
     279    delete _rnx;
     280    delete _sp3;
     281    delete _bsx;
     282    delete _ephUser;
     283    delete _usedEph;
     284    delete _ssrCorr;
    283285}
    284286
     
    287289void bncRtnetUploadCaster::decodeRtnetStream(char* buffer, int bufLen) {
    288290
    289   QMutexLocker locker(&_mutex);
    290 
    291   // Append to internal buffer
    292   // -------------------------
    293   _rtnetStreamBuffer.append(QByteArray(buffer, bufLen));
    294 
    295   // Select buffer part that contains last epoch
    296   // -------------------------------------------
    297   QStringList lines;
    298   int iEpoBeg = _rtnetStreamBuffer.lastIndexOf('*');   // begin of last epoch
    299   if (iEpoBeg == -1) {
    300     _rtnetStreamBuffer.clear();
    301     return;
    302   }
    303   _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoBeg);
    304 
    305   int iEpoEnd = _rtnetStreamBuffer.lastIndexOf("EOE"); // end   of last epoch
    306   if (iEpoEnd == -1) {
    307     return;
    308   }
    309   else {
    310     lines = _rtnetStreamBuffer.left(iEpoEnd).split('\n', Qt::SkipEmptyParts);
    311     _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoEnd+3);
    312   }
    313 
    314   if (lines.size() < 2) {
    315       emit(newMessage(
     291    QMutexLocker locker(&_mutex);
     292
     293    // Append to internal buffer
     294    // -------------------------
     295    _rtnetStreamBuffer.append(QByteArray(buffer, bufLen));
     296
     297    // Select buffer part that contains last epoch
     298    // -------------------------------------------
     299    QStringList lines;
     300    int iEpoBeg = _rtnetStreamBuffer.lastIndexOf('*');   // begin of last epoch
     301    if (iEpoBeg == -1) {
     302        _rtnetStreamBuffer.clear();
     303        return;
     304    }
     305    _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoBeg);
     306
     307    int iEpoEnd = _rtnetStreamBuffer.lastIndexOf("EOE"); // end   of last epoch
     308    if (iEpoEnd == -1) {
     309        return;
     310    }
     311    else {
     312        lines = _rtnetStreamBuffer.left(iEpoEnd).split('\n', Qt::SkipEmptyParts);
     313        _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iEpoEnd + 3);
     314    }
     315
     316    if (lines.size() < 2) {
     317        emit(newMessage(
    316318            "bncRtnetUploadCaster: less than 2 lines to decode " + _casterID.toLatin1(), false));
    317     return;
    318   }
    319 
    320   // Keep the last unfinished line in buffer
    321   // ---------------------------------------
    322   int iLastEOL = _rtnetStreamBuffer.lastIndexOf('\n');
    323   if (iLastEOL != -1) {
    324     _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iLastEOL+1);
    325   }
    326 
    327   decodeRtnetEpoch(lines);
    328 }
    329 
    330 //
    331 ////////////////////////////////////////////////////////////////////////////
    332 void bncRtnetUploadCaster::decodeRtnetEpoch(QStringList epochLines) {
    333 
    334   // Read first line (with epoch time)
    335   // ---------------------------------
    336   QTextStream in(epochLines[0].toLatin1());
    337   QString hlp;
    338   int year, month, day, hour, min;
    339   double sec;
    340   in >> hlp >> year >> month >> day >> hour >> min >> sec;
    341   bncTime epoTime;
    342   epoTime.set(year, month, day, hour, min, sec);//cout <<  epoTime.timestr().c_str() << endl;
    343 
    344   emit(newMessage(
    345       "bncRtnetUploadCaster: decode " + QByteArray(epoTime.datestr().c_str())
    346           + " " + QByteArray(epoTime.timestr().c_str()) + " "
    347           + _casterID.toLatin1(), false));
    348 
    349   struct SsrCorr::ClockOrbit co;
    350   memset(&co, 0, sizeof(co));
    351   co.EpochTime[CLOCKORBIT_SATGPS] = static_cast<int>(epoTime.gpssec());
    352   double gt = epoTime.gpssec() - gnumleap(year, month, day);
    353   if      (_ssrFormat == "RTCM-SSR") {
    354     gt += 3 * 3600;
    355   }
    356   co.EpochTime[CLOCKORBIT_SATGLONASS] = static_cast<int>(fmod(gt, 86400.0));
    357   co.EpochTime[CLOCKORBIT_SATGALILEO] = static_cast<int>(epoTime.gpssec());
    358   co.EpochTime[CLOCKORBIT_SATQZSS]    = static_cast<int>(epoTime.gpssec());
    359   co.EpochTime[CLOCKORBIT_SATSBAS]    = static_cast<int>(epoTime.gpssec());
    360   co.EpochTime[CLOCKORBIT_SATBDS]     = static_cast<int>(epoTime.bdssec());
    361   co.Supplied[_ssrCorr->COBOFS_CLOCK] = 1;
    362   co.Supplied[_ssrCorr->COBOFS_ORBIT] = 1;
    363   (_crdTrafoStr == "IGS20") ?
    364       co.SatRefDatum = _ssrCorr->DATUM_ITRF :
    365       co.SatRefDatum = _ssrCorr->DATUM_LOCAL;
    366   co.SSRIOD        = _IOD;
    367   co.SSRProviderID = _PID; // 256 .. BKG,  257 ... EUREF
    368   co.SSRSolutionID = _SID;
    369   if      (_ssrFormat == "RTCM-SSR") {
     319        return;
     320    }
     321
     322    // Keep the last unfinished line in buffer
     323    // ---------------------------------------
     324    int iLastEOL = _rtnetStreamBuffer.lastIndexOf('\n');
     325    if (iLastEOL != -1) {
     326        _rtnetStreamBuffer = _rtnetStreamBuffer.mid(iLastEOL + 1);
     327    }
     328
     329
     330    // Read first line (with epoch time)
     331    // ---------------------------------
     332    //QTextStream in(lines[0].toLatin1());
     333    QTextStream in(&lines[0], QIODevice::ReadOnly);
     334    QString hlp;
     335    int year, month, day, hour, min;
     336    double sec;
     337    in >> hlp >> year >> month >> day >> hour >> min >> sec;
     338    bncTime epoTime;
     339    epoTime.set(year, month, day, hour, min, sec);
     340
     341    emit(newMessage(
     342        "bncRtnetUploadCaster: decode " + QByteArray(epoTime.datestr().c_str())
     343        + " " + QByteArray(epoTime.timestr().c_str()) + " "
     344        + _casterID.toLatin1(), false));
     345
     346    struct SsrCorr::ClockOrbit co;
     347    memset(&co, 0, sizeof(co));
     348    co.EpochTime[CLOCKORBIT_SATGPS] = static_cast<int>(epoTime.gpssec());
     349    double gt = epoTime.gpssec() - gnumleap(year, month, day);
     350    if (_ssrFormat == "RTCM-SSR") {
     351        gt += 3 * 3600;
     352    }
     353    co.EpochTime[CLOCKORBIT_SATGLONASS] = static_cast<int>(fmod(gt, 86400.0));
     354    co.EpochTime[CLOCKORBIT_SATGALILEO] = static_cast<int>(epoTime.gpssec());
     355    co.EpochTime[CLOCKORBIT_SATQZSS] = static_cast<int>(epoTime.gpssec());
     356    co.EpochTime[CLOCKORBIT_SATSBAS] = static_cast<int>(epoTime.gpssec());
    370357    co.EpochTime[CLOCKORBIT_SATBDS] = static_cast<int>(epoTime.bdssec());
    371   }
    372   else if (_ssrFormat == "IGS-SSR") {
    373     co.EpochTime[CLOCKORBIT_SATBDS] = static_cast<int>(epoTime.gpssec());
    374   }
    375   co.Supplied[_ssrCorr->COBOFS_CLOCK] = 1;
    376   co.Supplied[_ssrCorr->COBOFS_ORBIT] = 1;
    377 
    378 
    379   t_serviceCrs serviceCrs;
    380   t_rtcmCrs    rtcmCrs;
    381   if (_crdTrafoStr == "IGS20") {
    382     serviceCrs._CE = serviceCrs._coordinateEpoch  = 0;
    383     int nc = _crdTrafoStr.length();
    384     if (nc > 31) {nc = 31;}
    385     for (int i = 0; i < nc; i++) {
    386       serviceCrs._name[i] =
    387          rtcmCrs._name[i] = _crdTrafoStr.toStdString()[i];
    388     }
    389     serviceCrs._name[nc] = 0;
    390     rtcmCrs._name[nc] = 0;
    391     rtcmCrs._anchor      = 0; // global CRS
    392     rtcmCrs._plateNumber = 0; // unknown
    393     rtcmCrs._databaseLinks << "ISO.DATUM.979" << "ISO.CRS:980";
    394   }
    395   else {
    396     if (_crdTrafoStr != "Custom") {
    397       serviceCrs._coordinateEpoch = _t0;
    398       serviceCrs.setCEFromCoordinateEpoch();
    399       int nc = _crdTrafoStr.length();
    400       if (nc > 31) {nc = 31;}
    401       for (int i = 0; i < nc; i++) {
    402         serviceCrs._name[i] = _crdTrafoStr.toStdString()[i];
    403       }
    404       serviceCrs._name[nc] = 0;
    405       QString rtcmcrsname = _crdTrafoStr + QString("(%1)").arg(_t0,4,'d',0);
    406       nc = rtcmcrsname.length();
    407       if (nc > 31) {nc = 31;}
    408       for (int i = 0; i < nc; i++) {
    409         rtcmCrs._name[i] = rtcmcrsname.toStdString()[i];
    410       }
    411       rtcmCrs._name[nc] = 0;
    412       if (_crdTrafoStr == "ETRF2000") {
    413         rtcmCrs._anchor      = 1; // plate-fixed CRS
    414         rtcmCrs._plateNumber = 7; // Eurasia
    415         rtcmCrs._databaseLinks << "ISO.DATUM.187"    << "ISO.CRS:260"   << "ISO.CRS:457"
    416                                << "EPSG.DATUM:1186"  << "EPSG.CRS:7930" << "EPSG.CRS:7931";
    417       }
    418       else if (_crdTrafoStr == "DREF91") {
    419         rtcmCrs._anchor      = 1; // plate-fixed CRS
    420         rtcmCrs._plateNumber = 7; // Eurasia
    421       }
    422       else if (_crdTrafoStr == "GDA2020") {
    423         rtcmCrs._anchor      = 1; // plate-fixed CRS
    424         rtcmCrs._plateNumber = 4; // Australia
    425         rtcmCrs._databaseLinks << "ISO.DATUM.186"   << "ISO.CRS:404"   << "ISO.CRS:329"
    426                                << "EPSG.DATUM:1168" << "EPSG.CRS:7842" << "EPSG.CRS:7843";
    427       }
    428       else if (_crdTrafoStr == "SIRGAS2000") {
    429         rtcmCrs._anchor      =  1; // plate-fixed CRS
    430         rtcmCrs._plateNumber = 12; // S.America
    431         rtcmCrs._databaseLinks << "ISO.DATUM:169"   << "ISO.CRS:384"   << "ISO.CRS:313"
    432                                << "EPSG.DATUM:6674" << "EPSG.CRS:4988" << "EPSG.CRS:4989";
    433       }
    434     }
    435   }
    436 
    437   struct SsrCorr::CodeBias bias;
    438   memset(&bias, 0, sizeof(bias));
    439   bias.EpochTime[CLOCKORBIT_SATGPS]     = co.EpochTime[CLOCKORBIT_SATGPS];
    440   bias.EpochTime[CLOCKORBIT_SATGLONASS] = co.EpochTime[CLOCKORBIT_SATGLONASS];
    441   bias.EpochTime[CLOCKORBIT_SATGALILEO] = co.EpochTime[CLOCKORBIT_SATGALILEO];
    442   bias.EpochTime[CLOCKORBIT_SATQZSS]    = co.EpochTime[CLOCKORBIT_SATQZSS];
    443   bias.EpochTime[CLOCKORBIT_SATSBAS]    = co.EpochTime[CLOCKORBIT_SATSBAS];
    444   bias.EpochTime[CLOCKORBIT_SATBDS]     = co.EpochTime[CLOCKORBIT_SATBDS];
    445   bias.SSRIOD        = _IOD;
    446   bias.SSRProviderID = _PID;
    447   bias.SSRSolutionID = _SID;
    448 
    449   struct SsrCorr::PhaseBias phasebias;
    450   memset(&phasebias, 0, sizeof(phasebias));
    451   unsigned int dispersiveBiasConsistenyIndicator = 0;
    452   unsigned int mwConsistencyIndicator = 0;
    453   phasebias.EpochTime[CLOCKORBIT_SATGPS]     = co.EpochTime[CLOCKORBIT_SATGPS];
    454   phasebias.EpochTime[CLOCKORBIT_SATGLONASS] = co.EpochTime[CLOCKORBIT_SATGLONASS];
    455   phasebias.EpochTime[CLOCKORBIT_SATGALILEO] = co.EpochTime[CLOCKORBIT_SATGALILEO];
    456   phasebias.EpochTime[CLOCKORBIT_SATQZSS]    = co.EpochTime[CLOCKORBIT_SATQZSS];
    457   phasebias.EpochTime[CLOCKORBIT_SATSBAS]    = co.EpochTime[CLOCKORBIT_SATSBAS];
    458   phasebias.EpochTime[CLOCKORBIT_SATBDS]     = co.EpochTime[CLOCKORBIT_SATBDS];
    459   phasebias.SSRIOD        = _IOD;
    460   phasebias.SSRProviderID = _PID;
    461   phasebias.SSRSolutionID = _SID;
    462 
    463   struct SsrCorr::VTEC vtec;
    464   memset(&vtec, 0, sizeof(vtec));
    465   vtec.EpochTime = static_cast<int>(epoTime.gpssec());
    466   vtec.SSRIOD        = _IOD;
    467   vtec.SSRProviderID = _PID;
    468   vtec.SSRSolutionID = _SID;
    469 
    470   // Default Update Interval
    471   // -----------------------
    472   int clkUpdInd = 2;         // 5 sec
    473   int ephUpdInd = clkUpdInd; // default
    474 
    475   if (!_samplRtcmEphCorr) {
    476     _samplRtcmEphCorr = 5.0;
    477   }
    478 
    479   if (_samplRtcmClkCorr > 5.0 && _samplRtcmEphCorr <= 5.0) { // combined orb and clock
    480     ephUpdInd = determineUpdateInd(_samplRtcmClkCorr);
    481   }
    482   if (_samplRtcmClkCorr > 5.0) {
    483     clkUpdInd = determineUpdateInd(_samplRtcmClkCorr);
    484   }
    485   if (_samplRtcmEphCorr > 5.0) {
    486     ephUpdInd = determineUpdateInd(_samplRtcmEphCorr);
    487   }
    488 
    489   co.UpdateInterval = clkUpdInd;
    490   bias.UpdateInterval = ephUpdInd;
    491   phasebias.UpdateInterval = ephUpdInd;
    492 
    493   for (int ii = 1; ii < epochLines.size(); ii++) {
    494     QString key;  // prn or key VTEC, IND (phase bias indicators)
    495     double rtnUra = 0.0; // [m]
    496     ColumnVector rtnAPC; rtnAPC.ReSize(3); rtnAPC = 0.0;          // [m, m, m]
    497     ColumnVector rtnVel; rtnVel.ReSize(3); rtnVel = 0.0;          // [m/s, m/s, m/s]
    498     ColumnVector rtnCoM; rtnCoM.ReSize(3); rtnCoM = 0.0;          // [m, m, m]
    499     ColumnVector rtnClk; rtnClk.ReSize(3); rtnClk = 0.0;          // [m, m/s, m/s²]
    500     ColumnVector rtnClkSig; rtnClkSig.ReSize(3); rtnClkSig = 0.0; // [m, m/s, m/s²]
    501 
    502     QTextStream in(epochLines[ii].toLatin1());
    503 
    504     in >> key;
    505 
    506     // non-satellite specific parameters
    507     if (key.contains("IND", Qt::CaseSensitive)) {
    508       in >> dispersiveBiasConsistenyIndicator >> mwConsistencyIndicator;
    509       continue;
    510     }
    511     // non-satellite specific parameters
    512     if (key.contains("VTEC", Qt::CaseSensitive)) {
    513       double ui;
    514       in >> ui >> vtec.NumLayers;
    515       vtec.UpdateInterval = (unsigned int) determineUpdateInd(ui);
    516       for (unsigned ll = 0; ll < vtec.NumLayers; ll++) {
    517         int dummy;
    518         in >> dummy >> vtec.Layers[ll].Degree >> vtec.Layers[ll].Order
    519             >> vtec.Layers[ll].Height;
    520         for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
    521           for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
    522             in >> vtec.Layers[ll].Cosinus[iDeg][iOrd];
    523           }
    524         }
    525         for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
    526           for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
    527             in >> vtec.Layers[ll].Sinus[iDeg][iOrd];
    528           }
    529         }
    530       }
    531       continue;
    532     }
    533     // satellite specific parameters
    534     t_prn prn;
    535     char sys = key.mid(0, 1).at(0).toLatin1();
    536     int  num = key.mid(1, 2).toInt();
    537     int flag = t_corrSSR::getSsrNavTypeFlag(sys, num);
    538     if (!num) {
    539       continue;
    540     }
    541     prn.set(sys, num, flag);
    542     QString prnInternalStr = QString::fromStdString(prn.toInternalString());
    543     QString prnStr         = QString::fromStdString(prn.toString());
    544 
    545     const t_eph* ephLast = _ephUser->ephLast(prnInternalStr);
    546     const t_eph* ephPrev = _ephUser->ephPrev(prnInternalStr);
    547     const t_eph* eph = ephLast;
    548     if (eph) {
    549 
    550       // Use previous ephemeris if the last one is too recent
    551       // ----------------------------------------------------
    552       const int MINAGE = 60; // seconds
    553       if (ephPrev && eph->receptDateTime().isValid() &&
    554           eph->receptDateTime().secsTo(currentDateAndTimeGPS()) < MINAGE) {
    555         eph = ephPrev;
    556       }
    557 
    558       // Make sure the clock messages refer to same IOD as orbit messages
    559       // ----------------------------------------------------------------
    560       if (_usedEph) {
     358    co.Supplied[_ssrCorr->COBOFS_CLOCK] = 1;
     359    co.Supplied[_ssrCorr->COBOFS_ORBIT] = 1;
     360    (_crdTrafoStr == "IGS20") ?
     361        co.SatRefDatum = _ssrCorr->DATUM_ITRF :
     362        co.SatRefDatum = _ssrCorr->DATUM_LOCAL;
     363    co.SSRIOD = _IOD;
     364    co.SSRProviderID = _PID; // 256 .. BKG,  257 ... EUREF
     365    co.SSRSolutionID = _SID;
     366    if (_ssrFormat == "RTCM-SSR") {
     367        co.EpochTime[CLOCKORBIT_SATBDS] = static_cast<int>(epoTime.bdssec());
     368    }
     369    else if (_ssrFormat == "IGS-SSR") {
     370        co.EpochTime[CLOCKORBIT_SATBDS] = static_cast<int>(epoTime.gpssec());
     371    }
     372    co.Supplied[_ssrCorr->COBOFS_CLOCK] = 1;
     373    co.Supplied[_ssrCorr->COBOFS_ORBIT] = 1;
     374
     375
     376    t_serviceCrs serviceCrs;
     377    t_rtcmCrs    rtcmCrs;
     378    if (_crdTrafoStr == "IGS20") {
     379        serviceCrs._CE = serviceCrs._coordinateEpoch = 0;
     380        int nc = _crdTrafoStr.length();
     381        if (nc > 31) { nc = 31; }
     382        for (int i = 0; i < nc; i++) {
     383            serviceCrs._name[i] =
     384                rtcmCrs._name[i] = _crdTrafoStr.toStdString()[i];
     385        }
     386        serviceCrs._name[nc] = 0;
     387        rtcmCrs._name[nc] = 0;
     388        rtcmCrs._anchor = 0; // global CRS
     389        rtcmCrs._plateNumber = 0; // unknown
     390        rtcmCrs._databaseLinks << "ISO.DATUM.979" << "ISO.CRS:980";
     391    }
     392    else {
     393        if (_crdTrafoStr != "Custom") {
     394            serviceCrs._coordinateEpoch = _t0;
     395            serviceCrs.setCEFromCoordinateEpoch();
     396            int nc = _crdTrafoStr.length();
     397            if (nc > 31) { nc = 31; }
     398            for (int i = 0; i < nc; i++) {
     399                serviceCrs._name[i] = _crdTrafoStr.toStdString()[i];
     400            }
     401            serviceCrs._name[nc] = 0;
     402            QString rtcmcrsname = _crdTrafoStr + QString("(%1)").arg(_t0, 4, 'd', 0);
     403            nc = rtcmcrsname.length();
     404            if (nc > 31) { nc = 31; }
     405            for (int i = 0; i < nc; i++) {
     406                rtcmCrs._name[i] = rtcmcrsname.toStdString()[i];
     407            }
     408            rtcmCrs._name[nc] = 0;
     409            if (_crdTrafoStr == "ETRF2000") {
     410                rtcmCrs._anchor = 1; // plate-fixed CRS
     411                rtcmCrs._plateNumber = 7; // Eurasia
     412                rtcmCrs._databaseLinks << "ISO.DATUM.187" << "ISO.CRS:260" << "ISO.CRS:457"
     413                    << "EPSG.DATUM:1186" << "EPSG.CRS:7930" << "EPSG.CRS:7931";
     414            }
     415            else if (_crdTrafoStr == "DREF91") {
     416                rtcmCrs._anchor = 1; // plate-fixed CRS
     417                rtcmCrs._plateNumber = 7; // Eurasia
     418            }
     419            else if (_crdTrafoStr == "GDA2020") {
     420                rtcmCrs._anchor = 1; // plate-fixed CRS
     421                rtcmCrs._plateNumber = 4; // Australia
     422                rtcmCrs._databaseLinks << "ISO.DATUM.186" << "ISO.CRS:404" << "ISO.CRS:329"
     423                    << "EPSG.DATUM:1168" << "EPSG.CRS:7842" << "EPSG.CRS:7843";
     424            }
     425            else if (_crdTrafoStr == "SIRGAS2000") {
     426                rtcmCrs._anchor = 1; // plate-fixed CRS
     427                rtcmCrs._plateNumber = 12; // S.America
     428                rtcmCrs._databaseLinks << "ISO.DATUM:169" << "ISO.CRS:384" << "ISO.CRS:313"
     429                    << "EPSG.DATUM:6674" << "EPSG.CRS:4988" << "EPSG.CRS:4989";
     430            }
     431        }
     432    }
     433
     434    struct SsrCorr::CodeBias bias;
     435    memset(&bias, 0, sizeof(bias));
     436    bias.EpochTime[CLOCKORBIT_SATGPS] = co.EpochTime[CLOCKORBIT_SATGPS];
     437    bias.EpochTime[CLOCKORBIT_SATGLONASS] = co.EpochTime[CLOCKORBIT_SATGLONASS];
     438    bias.EpochTime[CLOCKORBIT_SATGALILEO] = co.EpochTime[CLOCKORBIT_SATGALILEO];
     439    bias.EpochTime[CLOCKORBIT_SATQZSS] = co.EpochTime[CLOCKORBIT_SATQZSS];
     440    bias.EpochTime[CLOCKORBIT_SATSBAS] = co.EpochTime[CLOCKORBIT_SATSBAS];
     441    bias.EpochTime[CLOCKORBIT_SATBDS] = co.EpochTime[CLOCKORBIT_SATBDS];
     442    bias.SSRIOD = _IOD;
     443    bias.SSRProviderID = _PID;
     444    bias.SSRSolutionID = _SID;
     445
     446    struct SsrCorr::PhaseBias phasebias;
     447    memset(&phasebias, 0, sizeof(phasebias));
     448    unsigned int dispersiveBiasConsistenyIndicator = 0;
     449    unsigned int mwConsistencyIndicator = 0;
     450    phasebias.EpochTime[CLOCKORBIT_SATGPS] = co.EpochTime[CLOCKORBIT_SATGPS];
     451    phasebias.EpochTime[CLOCKORBIT_SATGLONASS] = co.EpochTime[CLOCKORBIT_SATGLONASS];
     452    phasebias.EpochTime[CLOCKORBIT_SATGALILEO] = co.EpochTime[CLOCKORBIT_SATGALILEO];
     453    phasebias.EpochTime[CLOCKORBIT_SATQZSS] = co.EpochTime[CLOCKORBIT_SATQZSS];
     454    phasebias.EpochTime[CLOCKORBIT_SATSBAS] = co.EpochTime[CLOCKORBIT_SATSBAS];
     455    phasebias.EpochTime[CLOCKORBIT_SATBDS] = co.EpochTime[CLOCKORBIT_SATBDS];
     456    phasebias.SSRIOD = _IOD;
     457    phasebias.SSRProviderID = _PID;
     458    phasebias.SSRSolutionID = _SID;
     459
     460    struct SsrCorr::VTEC vtec;
     461    memset(&vtec, 0, sizeof(vtec));
     462    vtec.EpochTime = static_cast<int>(epoTime.gpssec());
     463    vtec.SSRIOD = _IOD;
     464    vtec.SSRProviderID = _PID;
     465    vtec.SSRSolutionID = _SID;
     466
     467    // Update Interval
     468    // ---------------
     469
     470    if (_samplRtcmEphCorr == 0.0) {// combined orb and clock
     471        _samplRtcmEphCorr = _samplRtcmClkCorr = 5.0;
     472    }
     473    int clkUpdInd = determineUpdateInd(_samplRtcmClkCorr);
     474    int ephUpdInd = determineUpdateInd(_samplRtcmEphCorr);
     475
     476    co.UpdateInterval = clkUpdInd;
     477    bias.UpdateInterval = ephUpdInd;
     478    phasebias.UpdateInterval = ephUpdInd;
     479
     480    for (int ii = 1; ii < lines.size(); ii++) {
     481        QString key;  // prn or key VTEC, IND (phase bias indicators)
     482        double rtnUra = 0.0; // [m]
     483        ColumnVector rtnAPC; rtnAPC.ReSize(3); rtnAPC = 0.0;          // [m, m, m]
     484        ColumnVector rtnVel; rtnVel.ReSize(3); rtnVel = 0.0;          // [m/s, m/s, m/s]
     485        ColumnVector rtnCoM; rtnCoM.ReSize(3); rtnCoM = 0.0;          // [m, m, m]
     486        ColumnVector rtnClk; rtnClk.ReSize(3); rtnClk = 0.0;          // [m, m/s, m/s²]
     487        ColumnVector rtnClkSig; rtnClkSig.ReSize(3); rtnClkSig = 0.0; // [m, m/s, m/s²]
     488
     489        //QTextStream in(lines[ii].toLatin1());
     490        QTextStream in(&lines[ii], QIODevice::ReadOnly);
     491        in >> key;
     492
     493        // non-satellite specific parameters
     494        if (key.contains("IND", Qt::CaseSensitive)) {
     495            in >> dispersiveBiasConsistenyIndicator >> mwConsistencyIndicator;
     496            continue;
     497        }
     498        // non-satellite specific parameters
     499        if (key.contains("VTEC", Qt::CaseSensitive)) {
     500            double ui;
     501            in >> ui >> vtec.NumLayers;
     502            vtec.UpdateInterval = (unsigned int)determineUpdateInd(ui);
     503            for (unsigned ll = 0; ll < vtec.NumLayers; ll++) {
     504                int dummy;
     505                in >> dummy >> vtec.Layers[ll].Degree >> vtec.Layers[ll].Order
     506                    >> vtec.Layers[ll].Height;
     507                for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
     508                    for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
     509                        in >> vtec.Layers[ll].Cosinus[iDeg][iOrd];
     510                    }
     511                }
     512                for (unsigned iDeg = 0; iDeg <= vtec.Layers[ll].Degree; iDeg++) {
     513                    for (unsigned iOrd = 0; iOrd <= vtec.Layers[ll].Order; iOrd++) {
     514                        in >> vtec.Layers[ll].Sinus[iDeg][iOrd];
     515                    }
     516                }
     517            }
     518            continue;
     519        }
     520        // satellite specific parameters
     521        t_prn prn;
     522        char sys = key.mid(0, 1).at(0).toLatin1();
     523        int  num = key.mid(1, 2).toInt();
     524        int flag = t_corrSSR::getSsrNavTypeFlag(sys, num);
     525        if (!num) {
     526            continue;
     527        }
     528        prn.set(sys, num, flag);
     529        QString prnInternalStr = QString::fromStdString(prn.toInternalString());
     530        QString prnStr = QString::fromStdString(prn.toString());
     531
     532        const t_eph* ephLast = _ephUser->ephLast(prnInternalStr);
     533        const t_eph* ephPrev = _ephUser->ephPrev(prnInternalStr);
     534        const t_eph* eph = ephLast;
     535        if (eph) {
     536
     537            // Use previous ephemeris if the last one is too recent
     538            // ----------------------------------------------------
     539            const int MINAGE = 60; // seconds
     540            if (ephPrev && eph->receptDateTime().isValid() &&
     541                eph->receptDateTime().secsTo(currentDateAndTimeGPS()) < MINAGE) {
     542                eph = ephPrev;
     543            }
     544
     545            // Make sure the clock messages refer to same IOD as orbit messages
     546            // ----------------------------------------------------------------
     547            if (_usedEph) {
     548                if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     549                    (*_usedEph)[prnInternalStr] = eph;
     550                }
     551                else {
     552                    eph = 0;
     553                    if (_usedEph->contains(prnInternalStr)) {
     554                        const t_eph* usedEph = _usedEph->value(prnInternalStr);
     555                        if (usedEph == ephLast) {
     556                            eph = ephLast;
     557                        }
     558                        else if (usedEph == ephPrev) {
     559                            eph = ephPrev;
     560                        }
     561                    }
     562                }
     563            }
     564        }
     565
     566        QDateTime now = currentDateAndTimeGPS();
     567        bncTime   currentTime(now.toString(Qt::ISODate).toStdString());
     568        if (eph &&
     569            !outDatedBcep(eph, currentTime) &&  // detected from storage because of no update
     570            eph->checkState() != t_eph::bad &&
     571            eph->checkState() != t_eph::unhealthy &&
     572            eph->checkState() != t_eph::outdated) {   // detected during reception (bncephuser)
     573            QMap<QString, double> codeBiases;
     574            QList<phaseBiasSignal> phaseBiasList;
     575            phaseBiasesSat pbSat;
     576            _phaseBiasInformationDecoded = false;
     577
     578            while (true) {
     579                QString key;
     580                int numVal = 0;
     581                in >> key;
     582                if (in.status() != QTextStream::Ok) {
     583                    break;
     584                }
     585                if (key == "APC") {
     586                    in >> numVal;
     587                    rtnAPC.ReSize(3); rtnAPC = 0.0;
     588                    for (int ii = 0; ii < numVal; ii++) {
     589                        in >> rtnAPC[ii];
     590                    }
     591                }
     592                else if (key == "Ura") {
     593                    in >> numVal;
     594                    if (numVal == 1)
     595                        in >> rtnUra;
     596                }
     597                else if (key == "Clk") {
     598                    in >> numVal;
     599                    rtnClk.ReSize(3); rtnClk = 0.0;
     600                    for (int ii = 0; ii < numVal; ii++) {
     601                        in >> rtnClk[ii];
     602                    }
     603                }
     604                else if (key == "ClkSig") {
     605                    in >> numVal;
     606                    rtnClkSig.ReSize(3); rtnClkSig = 0.0;
     607                    for (int ii = 0; ii < numVal; ii++) {
     608                        in >> rtnClkSig[ii];
     609                    }
     610                }
     611                else if (key == "Vel") {
     612                    in >> numVal;
     613                    rtnVel.ReSize(3); rtnVel = 0.0;
     614                    for (int ii = 0; ii < numVal; ii++) {
     615                        in >> rtnVel[ii];
     616                    }
     617                }
     618                else if (key == "CoM") {
     619                    in >> numVal;
     620                    rtnCoM.ReSize(3); rtnCoM = 0.0;
     621                    for (int ii = 0; ii < numVal; ii++) {
     622                        in >> rtnCoM[ii];
     623                    }
     624                }
     625                else if (key == "CodeBias") {
     626                    in >> numVal;
     627                    for (int ii = 0; ii < numVal; ii++) {
     628                        QString type;
     629                        double value;
     630                        in >> type >> value;
     631                        codeBiases[type] = value;
     632                    }
     633                }
     634                else if (key == "YawAngle") {
     635                    _phaseBiasInformationDecoded = true;
     636                    in >> numVal >> pbSat.yawAngle;
     637                    if (pbSat.yawAngle < 0.0) {
     638                        pbSat.yawAngle += (2 * M_PI);
     639                    }
     640                    else if (pbSat.yawAngle > 2 * M_PI) {
     641                        pbSat.yawAngle -= (2 * M_PI);
     642                    }
     643                }
     644                else if (key == "YawRate") {
     645                    _phaseBiasInformationDecoded = true;
     646                    in >> numVal >> pbSat.yawRate;
     647                }
     648                else if (key == "PhaseBias") {
     649                    _phaseBiasInformationDecoded = true;
     650                    in >> numVal;
     651                    for (int ii = 0; ii < numVal; ii++) {
     652                        phaseBiasSignal pb;
     653                        in >> pb.type >> pb.bias >> pb.integerIndicator
     654                            >> pb.wlIndicator >> pb.discontinuityCounter;
     655                        phaseBiasList.append(pb);
     656                    }
     657                }
     658                else {
     659                    in >> numVal;
     660                    for (int ii = 0; ii < numVal; ii++) {
     661                        double dummy;
     662                        in >> dummy;
     663                    }
     664                    emit(newMessage("                      RTNET format error: "
     665                        + lines[ii].toLatin1(), false));
     666                    break;
     667                }
     668            }
     669
     670            struct SsrCorr::ClockOrbit::SatData* sd = 0;
     671            if (prn.system() == 'G') {
     672                sd = co.Sat + co.NumberOfSat[CLOCKORBIT_SATGPS];
     673                ++co.NumberOfSat[CLOCKORBIT_SATGPS];
     674            }
     675            else if (prn.system() == 'R') {
     676                sd = co.Sat + CLOCKORBIT_NUMGPS + co.NumberOfSat[CLOCKORBIT_SATGLONASS];
     677                ++co.NumberOfSat[CLOCKORBIT_SATGLONASS];
     678            }
     679            else if (prn.system() == 'E') {
     680                sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     681                    + co.NumberOfSat[CLOCKORBIT_SATGALILEO];
     682                ++co.NumberOfSat[CLOCKORBIT_SATGALILEO];
     683            }
     684            else if (prn.system() == 'J') {
     685                sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     686                    + CLOCKORBIT_NUMGALILEO
     687                    + co.NumberOfSat[CLOCKORBIT_SATQZSS];
     688                ++co.NumberOfSat[CLOCKORBIT_SATQZSS];
     689            }
     690            else if (prn.system() == 'S') {
     691                sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     692                    + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     693                    + co.NumberOfSat[CLOCKORBIT_SATSBAS];
     694                ++co.NumberOfSat[CLOCKORBIT_SATSBAS];
     695            }
     696            else if (prn.system() == 'C') {
     697                sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     698                    + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     699                    + CLOCKORBIT_NUMSBAS
     700                    + co.NumberOfSat[CLOCKORBIT_SATBDS];
     701                ++co.NumberOfSat[CLOCKORBIT_SATBDS];
     702            }
     703            if (sd) {
     704                QString outLine;
     705                t_irc irc = processSatellite(eph, epoTime.gpsw(), epoTime.gpssec(), prnStr, rtnAPC,
     706                    rtnUra, rtnClk, rtnVel, rtnCoM, rtnClkSig, sd, outLine);
     707                if (irc != success) {
     708                    continue;
     709                }
     710            }
     711
     712            // Code Biases
     713            // -----------
     714            struct SsrCorr::CodeBias::BiasSat* biasSat = 0;
     715            if (!codeBiases.isEmpty()) {
     716                if (prn.system() == 'G') {
     717                    biasSat = bias.Sat + bias.NumberOfSat[CLOCKORBIT_SATGPS];
     718                    ++bias.NumberOfSat[CLOCKORBIT_SATGPS];
     719                }
     720                else if (prn.system() == 'R') {
     721                    biasSat = bias.Sat + CLOCKORBIT_NUMGPS
     722                        + bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
     723                    ++bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
     724                }
     725                else if (prn.system() == 'E') {
     726                    biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     727                        + bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
     728                    ++bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
     729                }
     730                else if (prn.system() == 'J') {
     731                    biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     732                        + CLOCKORBIT_NUMGALILEO
     733                        + bias.NumberOfSat[CLOCKORBIT_SATQZSS];
     734                    ++bias.NumberOfSat[CLOCKORBIT_SATQZSS];
     735                }
     736                else if (prn.system() == 'S') {
     737                    biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     738                        + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     739                        + bias.NumberOfSat[CLOCKORBIT_SATSBAS];
     740                    ++bias.NumberOfSat[CLOCKORBIT_SATSBAS];
     741                }
     742                else if (prn.system() == 'C') {
     743                    biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     744                        + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     745                        + CLOCKORBIT_NUMSBAS
     746                        + bias.NumberOfSat[CLOCKORBIT_SATBDS];
     747                    ++bias.NumberOfSat[CLOCKORBIT_SATBDS];
     748                }
     749            }
     750
     751            if (biasSat) {
     752                biasSat->ID = prn.number();
     753                biasSat->NumberOfCodeBiases = 0;
     754                QMapIterator<QString, double> it(codeBiases);
     755                while (it.hasNext()) {
     756                    it.next();
     757                    int ii = biasSat->NumberOfCodeBiases;
     758                    if (ii >= CLOCKORBIT_NUMBIAS)
     759                        break;
     760                    SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), it.key().toStdString());
     761                    if (type != _ssrCorr->RESERVED) {
     762                        biasSat->NumberOfCodeBiases += 1;
     763                        biasSat->Biases[ii].Type = type;
     764                        biasSat->Biases[ii].Bias = it.value();
     765                        if (_bsx) {
     766                            QString obsCode = 'C' + it.key();
     767                            _bsx->write(epoTime.gpsw(), epoTime.gpssec(), prnStr, obsCode, it.value());
     768                        }
     769                    }
     770                }
     771            }
     772
     773            // Phase Biases
     774            // ------------
     775            struct SsrCorr::PhaseBias::PhaseBiasSat* phasebiasSat = 0;
     776            if (prn.system() == 'G') {
     777                phasebiasSat = phasebias.Sat
     778                    + phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
     779                ++phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
     780            }
     781            else if (prn.system() == 'R') {
     782                phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS
     783                    + phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
     784                ++phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
     785            }
     786            else if (prn.system() == 'E') {
     787                phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     788                    + phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
     789                ++phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
     790            }
     791            else if (prn.system() == 'J') {
     792                phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     793                    + CLOCKORBIT_NUMGALILEO
     794                    + phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
     795                ++phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
     796            }
     797            else if (prn.system() == 'S') {
     798                phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     799                    + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     800                    + phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
     801                ++phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
     802            }
     803            else if (prn.system() == 'C') {
     804                phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
     805                    + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
     806                    + CLOCKORBIT_NUMSBAS
     807                    + phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
     808                ++phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
     809            }
     810
     811            if (phasebiasSat && _phaseBiasInformationDecoded) {
     812                phasebias.DispersiveBiasConsistencyIndicator = dispersiveBiasConsistenyIndicator;
     813                phasebias.MWConsistencyIndicator = mwConsistencyIndicator;
     814                phasebiasSat->ID = prn.number();
     815                phasebiasSat->NumberOfPhaseBiases = 0;
     816                phasebiasSat->YawAngle = pbSat.yawAngle;
     817                phasebiasSat->YawRate = pbSat.yawRate;
     818                QListIterator<phaseBiasSignal> it(phaseBiasList);
     819                while (it.hasNext()) {
     820                    const phaseBiasSignal& pbSig = it.next();
     821                    int ii = phasebiasSat->NumberOfPhaseBiases;
     822                    if (ii >= CLOCKORBIT_NUMBIAS)
     823                        break;
     824                    SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), pbSig.type.toStdString());
     825                    if (type != _ssrCorr->RESERVED) {
     826                        phasebiasSat->NumberOfPhaseBiases += 1;
     827                        phasebiasSat->Biases[ii].Type = type;
     828                        phasebiasSat->Biases[ii].Bias = pbSig.bias;
     829                        phasebiasSat->Biases[ii].SignalIntegerIndicator = pbSig.integerIndicator;
     830                        phasebiasSat->Biases[ii].SignalsWideLaneIntegerIndicator = pbSig.wlIndicator;
     831                        phasebiasSat->Biases[ii].SignalDiscontinuityCounter = pbSig.discontinuityCounter;
     832                        if (_bsx) {
     833                            QString obsCode = 'L' + pbSig.type;
     834                            _bsx->write(epoTime.gpsw(), epoTime.gpssec(), prnStr, obsCode, pbSig.bias);
     835                        }
     836                    }
     837                }
     838            }
     839        }
     840    }
     841
     842    QByteArray hlpBufferCo;
     843    char obuffer[CLOCKORBIT_BUFFERSIZE];
     844    size_t len = 0;
     845
     846    // Orbit and Clock Corrections together
     847    // ------------------------------------
     848    if (_samplRtcmEphCorr == _samplRtcmClkCorr) {
     849        if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0
     850            || co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
     851            || co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
     852            || co.NumberOfSat[CLOCKORBIT_SATBDS] > 0
     853            || co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
     854            || co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
     855            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     856                memset(obuffer, 0, sizeof(obuffer));
     857                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_AUTO, 0, obuffer, sizeof(obuffer));
     858                if (len > 0) {
     859                    hlpBufferCo = QByteArray(obuffer, int(len));
     860                }
     861            }
     862        }
     863    }
     864
     865    // Orbit and Clock Corrections separately
     866    // --------------------------------------
     867    else {
     868        if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
     869            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     870                co.UpdateInterval = ephUpdInd;
     871                memset(obuffer, 0, sizeof(obuffer));
     872                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSORBIT, 1, obuffer, sizeof(obuffer));
     873                if (len > 0) {
     874                    hlpBufferCo += QByteArray(obuffer, int(len));
     875                }
     876            }
     877            int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0 ||
     878                co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
     879                co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ||
     880                co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
     881                co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) ? 1 : 0;
     882            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     883                co.UpdateInterval = clkUpdInd;
     884                memset(obuffer, 0, sizeof(obuffer));
     885                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSCLOCK, mmsg, obuffer, sizeof(obuffer));
     886                if (len > 0) {
     887                    hlpBufferCo += QByteArray(obuffer, int(len));
     888                }
     889            }
     890        }
     891        if (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
     892            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     893                co.UpdateInterval = ephUpdInd;
     894                memset(obuffer, 0, sizeof(obuffer));
     895                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSORBIT, 1, obuffer, sizeof(obuffer));
     896                if (len > 0) {
     897                    hlpBufferCo += QByteArray(obuffer, int(len));
     898                }
     899            }
     900            int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
     901                co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ||
     902                co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
     903                co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) ? 1 : 0;
     904            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     905                co.UpdateInterval = clkUpdInd;
     906                memset(obuffer, 0, sizeof(obuffer));
     907                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSCLOCK, mmsg, obuffer, sizeof(obuffer));
     908                if (len > 0) {
     909                    hlpBufferCo += QByteArray(obuffer, int(len));
     910                }
     911            }
     912        }
     913        if (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
     914            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     915                co.UpdateInterval = ephUpdInd;
     916                memset(obuffer, 0, sizeof(obuffer));
     917                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOORBIT, 1, obuffer, sizeof(obuffer));
     918                if (len > 0) {
     919                    hlpBufferCo += QByteArray(obuffer, int(len));
     920                }
     921            }
     922            int mmsg = (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0 ||
     923                co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
     924                co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) ? 1 : 0;
     925            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     926                co.UpdateInterval = clkUpdInd;
     927                memset(obuffer, 0, sizeof(obuffer));
     928                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOCLOCK, mmsg, obuffer, sizeof(obuffer));
     929                if (len > 0) {
     930                    hlpBufferCo += QByteArray(obuffer, int(len));
     931                }
     932            }
     933        }
     934        if (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
     935            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     936                co.UpdateInterval = ephUpdInd;
     937                memset(obuffer, 0, sizeof(obuffer));
     938                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSORBIT, 1, obuffer, sizeof(obuffer));
     939                if (len > 0) {
     940                    hlpBufferCo += QByteArray(obuffer, int(len));
     941                }
     942            }
     943            int mmsg = (co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0 ||
     944                co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) ? 1 : 0;
     945            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     946                co.UpdateInterval = clkUpdInd;
     947                memset(obuffer, 0, sizeof(obuffer));
     948                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSCLOCK, mmsg, obuffer, sizeof(obuffer));
     949                if (len > 0) {
     950                    hlpBufferCo += QByteArray(obuffer, int(len));
     951                }
     952            }
     953        }
     954        if (co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
     955            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     956                co.UpdateInterval = ephUpdInd;
     957                memset(obuffer, 0, sizeof(obuffer));
     958                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSORBIT, 1, obuffer, sizeof(obuffer));
     959                if (len > 0) {
     960                    hlpBufferCo += QByteArray(obuffer, int(len));
     961                }
     962            }
     963            int mmsg = (co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) ? 1 : 0;
     964            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     965                co.UpdateInterval = clkUpdInd;
     966                memset(obuffer, 0, sizeof(obuffer));
     967                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSCLOCK, mmsg, obuffer, sizeof(obuffer));
     968                if (len > 0) {
     969                    hlpBufferCo += QByteArray(obuffer, int(len));
     970                }
     971            }
     972        }
     973        if (co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
     974            if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     975                co.UpdateInterval = ephUpdInd;
     976                memset(obuffer, 0, sizeof(obuffer));
     977                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASORBIT, 1, obuffer, sizeof(obuffer));
     978                co.UpdateInterval = clkUpdInd;
     979                if (len > 0) {
     980                    hlpBufferCo += QByteArray(obuffer, int(len));
     981                }
     982            }
     983            int mmsg = 0;
     984            if (fmod(epoTime.gpssec(), _samplRtcmClkCorr) == 0.0) {
     985                co.UpdateInterval = clkUpdInd;
     986                memset(obuffer, 0, sizeof(obuffer));
     987                len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASCLOCK, mmsg, obuffer, sizeof(obuffer));
     988                if (len > 0) {
     989                    hlpBufferCo += QByteArray(obuffer, int(len));
     990                }
     991            }
     992        }
     993    }
     994
     995    // Code Biases
     996    // -----------
     997    QByteArray hlpBufferBias;
     998    if (bias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
     999        || bias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
     1000        || bias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
     1001        || bias.NumberOfSat[CLOCKORBIT_SATBDS] > 0
     1002        || bias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
     1003        || bias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
    5611004        if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    562           (*_usedEph)[prnInternalStr] = eph;
    563         }
    564         else {
    565           eph = 0;
    566           if (_usedEph->contains(prnInternalStr)) {
    567             const t_eph* usedEph = _usedEph->value(prnInternalStr);
    568             if (usedEph == ephLast) {
    569               eph = ephLast;
    570             }
    571             else if (usedEph == ephPrev) {
    572               eph = ephPrev;
    573             }
    574           }
    575         }
    576       }
    577     }
    578 
    579     QDateTime now = currentDateAndTimeGPS();
    580     bncTime   currentTime(now.toString(Qt::ISODate).toStdString());
    581     if (eph &&
    582         !outDatedBcep(eph, currentTime)       &&  // detected from storage because of no update
    583         eph->checkState() != t_eph::bad       &&
    584         eph->checkState() != t_eph::unhealthy &&
    585         eph->checkState() != t_eph::outdated) {   // detected during reception (bncephuser)
    586       QMap<QString, double> codeBiases;
    587       QList<phaseBiasSignal> phaseBiasList;
    588       phaseBiasesSat pbSat;
    589       _phaseBiasInformationDecoded = false;
    590 
    591       while (true) {
    592         QString key;
    593         int numVal = 0;
    594         in >> key;
    595         if (in.status() != QTextStream::Ok) {
    596           break;
    597         }
    598         if (key == "APC") {
    599           in >> numVal;
    600           rtnAPC.ReSize(3); rtnAPC = 0.0;
    601           for (int ii = 0; ii < numVal; ii++) {
    602             in >> rtnAPC[ii];
    603           }
    604         }
    605         else if (key == "Ura") {
    606           in >> numVal;
    607           if (numVal == 1)
    608             in >> rtnUra;
    609         }
    610         else if (key == "Clk") {
    611           in >> numVal;
    612           rtnClk.ReSize(3); rtnClk = 0.0;
    613           for (int ii = 0; ii < numVal; ii++) {
    614             in >> rtnClk[ii];
    615           }
    616         }
    617         else if (key == "ClkSig") {
    618           in >> numVal;
    619           rtnClkSig.ReSize(3); rtnClkSig = 0.0;
    620           for (int ii = 0; ii < numVal; ii++) {
    621             in >> rtnClkSig[ii];
    622           }
    623         }
    624         else if (key == "Vel") {
    625           in >> numVal;
    626           rtnVel.ReSize(3); rtnVel = 0.0;
    627           for (int ii = 0; ii < numVal; ii++) {
    628             in >> rtnVel[ii];
    629           }
    630         }
    631         else if (key == "CoM") {
    632           in >> numVal;
    633           rtnCoM.ReSize(3); rtnCoM = 0.0;
    634           for (int ii = 0; ii < numVal; ii++) {
    635             in >> rtnCoM[ii];
    636           }
    637         }
    638         else if (key == "CodeBias") {
    639           in >> numVal;
    640           for (int ii = 0; ii < numVal; ii++) {
    641             QString type;
    642             double value;
    643             in >> type >> value;
    644             codeBiases[type] = value;
    645           }
    646         }
    647         else if (key == "YawAngle") {
    648           _phaseBiasInformationDecoded = true;
    649           in >> numVal >> pbSat.yawAngle;
    650           if      (pbSat.yawAngle < 0.0) {
    651             pbSat.yawAngle += (2*M_PI);
    652           }
    653           else if (pbSat.yawAngle > 2*M_PI) {
    654             pbSat.yawAngle -= (2*M_PI);
    655           }
    656         }
    657         else if (key == "YawRate") {
    658           _phaseBiasInformationDecoded = true;
    659           in >> numVal >> pbSat.yawRate;
    660         }
    661         else if (key == "PhaseBias") {
    662           _phaseBiasInformationDecoded = true;
    663           in >> numVal;
    664           for (int ii = 0; ii < numVal; ii++) {
    665             phaseBiasSignal pb;
    666             in >> pb.type >> pb.bias >> pb.integerIndicator
    667               >> pb.wlIndicator >> pb.discontinuityCounter;
    668             phaseBiasList.append(pb);
    669           }
    670         }
    671         else {
    672           in >> numVal;
    673           for (int ii = 0; ii < numVal; ii++) {
    674             double dummy;
    675             in >> dummy;
    676           }
    677           emit(newMessage("                      RTNET format error: "
    678                           +  epochLines[ii].toLatin1(), false));
    679           break;
    680         }
    681       }
    682 
    683       struct SsrCorr::ClockOrbit::SatData* sd = 0;
    684       if (prn.system() == 'G') {
    685         sd = co.Sat + co.NumberOfSat[CLOCKORBIT_SATGPS];
    686         ++co.NumberOfSat[CLOCKORBIT_SATGPS];
    687       }
    688       else if (prn.system() == 'R') {
    689         sd = co.Sat + CLOCKORBIT_NUMGPS + co.NumberOfSat[CLOCKORBIT_SATGLONASS];
    690         ++co.NumberOfSat[CLOCKORBIT_SATGLONASS];
    691       }
    692       else if (prn.system() == 'E') {
    693         sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    694            + co.NumberOfSat[CLOCKORBIT_SATGALILEO];
    695         ++co.NumberOfSat[CLOCKORBIT_SATGALILEO];
    696       }
    697       else if (prn.system() == 'J') {
    698         sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    699            + CLOCKORBIT_NUMGALILEO
    700            + co.NumberOfSat[CLOCKORBIT_SATQZSS];
    701         ++co.NumberOfSat[CLOCKORBIT_SATQZSS];
    702       }
    703       else if (prn.system() == 'S') {
    704         sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    705             + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    706             + co.NumberOfSat[CLOCKORBIT_SATSBAS];
    707         ++co.NumberOfSat[CLOCKORBIT_SATSBAS];
    708       }
    709       else if (prn.system() == 'C') {
    710         sd = co.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    711             + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    712             + CLOCKORBIT_NUMSBAS
    713             + co.NumberOfSat[CLOCKORBIT_SATBDS];
    714         ++co.NumberOfSat[CLOCKORBIT_SATBDS];
    715       }
    716       if (sd) {
    717         QString outLine;
    718         t_irc irc = processSatellite(eph, epoTime.gpsw(), epoTime.gpssec(), prnStr, rtnAPC,
    719                                      rtnUra, rtnClk, rtnVel, rtnCoM, rtnClkSig, sd, outLine);
    720         if (irc != success) {
    721           continue;
    722         }
    723       }
    724 
    725       // Code Biases
    726       // -----------
    727       struct SsrCorr::CodeBias::BiasSat* biasSat = 0;
    728       if (!codeBiases.isEmpty()) {
    729         if (prn.system() == 'G') {
    730           biasSat = bias.Sat + bias.NumberOfSat[CLOCKORBIT_SATGPS];
    731           ++bias.NumberOfSat[CLOCKORBIT_SATGPS];
    732         }
    733         else if (prn.system() == 'R') {
    734           biasSat = bias.Sat + CLOCKORBIT_NUMGPS
    735                   + bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
    736           ++bias.NumberOfSat[CLOCKORBIT_SATGLONASS];
    737         }
    738         else if (prn.system() == 'E') {
    739           biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    740                   + bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
    741           ++bias.NumberOfSat[CLOCKORBIT_SATGALILEO];
    742         }
    743         else if (prn.system() == 'J') {
    744           biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    745                   + CLOCKORBIT_NUMGALILEO
    746                   + bias.NumberOfSat[CLOCKORBIT_SATQZSS];
    747           ++bias.NumberOfSat[CLOCKORBIT_SATQZSS];
    748         }
    749         else if (prn.system() == 'S') {
    750           biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    751                   + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    752                   + bias.NumberOfSat[CLOCKORBIT_SATSBAS];
    753           ++bias.NumberOfSat[CLOCKORBIT_SATSBAS];
    754         }
    755         else if (prn.system() == 'C') {
    756           biasSat = bias.Sat + CLOCKORBIT_NUMGPS + CLOCKORBIT_NUMGLONASS
    757                   + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    758                   + CLOCKORBIT_NUMSBAS
    759                   + bias.NumberOfSat[CLOCKORBIT_SATBDS];
    760           ++bias.NumberOfSat[CLOCKORBIT_SATBDS];
    761         }
    762       }
    763 
    764       if (biasSat) {
    765         biasSat->ID = prn.number();
    766         biasSat->NumberOfCodeBiases = 0;
    767         QMapIterator<QString, double> it(codeBiases);
    768         while (it.hasNext()) {
    769           it.next();
    770           int ii = biasSat->NumberOfCodeBiases;
    771           if (ii >= CLOCKORBIT_NUMBIAS)
    772             break;
    773           SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), it.key().toStdString());
    774           if (type != _ssrCorr->RESERVED) {
    775             biasSat->NumberOfCodeBiases += 1;
    776             biasSat->Biases[ii].Type = type;
    777             biasSat->Biases[ii].Bias = it.value();
    778             if (_bsx) {
    779               QString obsCode = 'C' + it.key();
    780               _bsx->write(epoTime.gpsw(), epoTime.gpssec(), prnStr, obsCode, it.value());
    781             }
    782           }
    783         }
    784       }
    785 
    786       // Phase Biases
    787       // ------------
    788       struct SsrCorr::PhaseBias::PhaseBiasSat* phasebiasSat = 0;
    789       if (prn.system()      == 'G') {
    790         phasebiasSat = phasebias.Sat
    791                      + phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
    792         ++phasebias.NumberOfSat[CLOCKORBIT_SATGPS];
    793       }
    794       else if (prn.system() == 'R') {
    795         phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS
    796                      + phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
    797         ++phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS];
    798       }
    799       else if (prn.system() == 'E') {
    800         phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS  + CLOCKORBIT_NUMGLONASS
    801                      + phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
    802         ++phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO];
    803       }
    804       else if (prn.system() == 'J') {
    805         phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS  + CLOCKORBIT_NUMGLONASS
    806                      + CLOCKORBIT_NUMGALILEO
    807                      + phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
    808         ++phasebias.NumberOfSat[CLOCKORBIT_SATQZSS];
    809       }
    810       else if (prn.system() == 'S') {
    811         phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS  + CLOCKORBIT_NUMGLONASS
    812                      + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    813                      + phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
    814         ++phasebias.NumberOfSat[CLOCKORBIT_SATSBAS];
    815       }
    816       else if (prn.system() == 'C') {
    817         phasebiasSat = phasebias.Sat + CLOCKORBIT_NUMGPS  + CLOCKORBIT_NUMGLONASS
    818                      + CLOCKORBIT_NUMGALILEO + CLOCKORBIT_NUMQZSS
    819                      + CLOCKORBIT_NUMSBAS
    820                      + phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
    821         ++phasebias.NumberOfSat[CLOCKORBIT_SATBDS];
    822       }
    823 
    824       if (phasebiasSat && _phaseBiasInformationDecoded) {
    825         phasebias.DispersiveBiasConsistencyIndicator = dispersiveBiasConsistenyIndicator;
    826         phasebias.MWConsistencyIndicator = mwConsistencyIndicator;
    827         phasebiasSat->ID = prn.number();
    828         phasebiasSat->NumberOfPhaseBiases = 0;
    829         phasebiasSat->YawAngle = pbSat.yawAngle;
    830         phasebiasSat->YawRate = pbSat.yawRate;
    831         QListIterator<phaseBiasSignal> it(phaseBiasList);
    832         while (it.hasNext()) {
    833           const phaseBiasSignal &pbSig = it.next();
    834           int ii = phasebiasSat->NumberOfPhaseBiases;
    835           if (ii >= CLOCKORBIT_NUMBIAS)
    836             break;
    837           SsrCorr::CodeType type = _ssrCorr->rnxTypeToCodeType(prn.system(), pbSig.type.toStdString());
    838           if (type != _ssrCorr->RESERVED) {
    839             phasebiasSat->NumberOfPhaseBiases += 1;
    840             phasebiasSat->Biases[ii].Type = type;
    841             phasebiasSat->Biases[ii].Bias = pbSig.bias;
    842             phasebiasSat->Biases[ii].SignalIntegerIndicator = pbSig.integerIndicator;
    843             phasebiasSat->Biases[ii].SignalsWideLaneIntegerIndicator = pbSig.wlIndicator;
    844             phasebiasSat->Biases[ii].SignalDiscontinuityCounter = pbSig.discontinuityCounter;
    845             if (_bsx) {
    846               QString obsCode = 'L' + pbSig.type;
    847               _bsx->write(epoTime.gpsw(), epoTime.gpssec(), prnStr, obsCode, pbSig.bias);
    848             }
    849           }
    850         }
    851       }
    852     }
    853   }
    854 
    855   QByteArray hlpBufferCo;
    856 
    857   // Orbit and Clock Corrections together
    858   // ------------------------------------
    859   if (_samplRtcmEphCorr == _samplRtcmClkCorr) {
    860     if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0
    861         || co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
    862         || co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
    863         || co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
    864         || co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
    865         || co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
    866       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    867       int len = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_AUTO, 0, obuffer, sizeof(obuffer));
    868       if (len > 0) {
    869         hlpBufferCo = QByteArray(obuffer, len);
    870       }
    871     }
    872   }
    873 
    874   // Orbit and Clock Corrections separately
    875   // --------------------------------------
    876   else {
    877     if (co.NumberOfSat[CLOCKORBIT_SATGPS] > 0) {
    878       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    879       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    880         co.UpdateInterval = ephUpdInd;
    881         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSORBIT, 1, obuffer, sizeof(obuffer));
    882         co.UpdateInterval = clkUpdInd;
    883         if (len1 > 0) {
    884           hlpBufferCo += QByteArray(obuffer, len1);
    885         }
    886       }
    887       int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0 ||
    888                   co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
    889                   co.NumberOfSat[CLOCKORBIT_SATQZSS]    > 0 ||
    890                   co.NumberOfSat[CLOCKORBIT_SATSBAS]    > 0 ||
    891                   co.NumberOfSat[CLOCKORBIT_SATBDS]     > 0   ) ? 1 : 0;
    892       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GPSCLOCK, mmsg, obuffer, sizeof(obuffer));
    893       if (len2 > 0) {
    894         hlpBufferCo += QByteArray(obuffer, len2);
    895       }
    896     }
    897     if (co.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0) {
    898       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    899       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    900         co.UpdateInterval = ephUpdInd;
    901         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSORBIT, 1, obuffer, sizeof(obuffer));
    902         co.UpdateInterval = clkUpdInd;
    903         if (len1 > 0) {
    904           hlpBufferCo += QByteArray(obuffer, len1);
    905         }
    906       }
    907       int mmsg = (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0 ||
    908                   co.NumberOfSat[CLOCKORBIT_SATQZSS]    > 0 ||
    909                   co.NumberOfSat[CLOCKORBIT_SATSBAS]    > 0 ||
    910                   co.NumberOfSat[CLOCKORBIT_SATBDS]     > 0   ) ? 1 : 0;
    911       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GLONASSCLOCK, mmsg, obuffer, sizeof(obuffer));
    912       if (len2 > 0) {
    913         hlpBufferCo += QByteArray(obuffer, len2);
    914       }
    915     }
    916     if (co.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0) {
    917       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    918       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    919         co.UpdateInterval = ephUpdInd;
    920         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOORBIT, 1, obuffer, sizeof(obuffer));
    921         co.UpdateInterval = clkUpdInd;
    922         if (len1 > 0) {
    923           hlpBufferCo += QByteArray(obuffer, len1);
    924         }
    925       }
    926       int mmsg = (co.NumberOfSat[CLOCKORBIT_SATQZSS]    > 0 ||
    927                   co.NumberOfSat[CLOCKORBIT_SATSBAS]    > 0 ||
    928                   co.NumberOfSat[CLOCKORBIT_SATBDS]     > 0   ) ? 1 : 0;
    929       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_GALILEOCLOCK, mmsg, obuffer, sizeof(obuffer));
    930       if (len2 > 0) {
    931         hlpBufferCo += QByteArray(obuffer, len2);
    932       }
    933     }
    934     if (co.NumberOfSat[CLOCKORBIT_SATQZSS] > 0) {
    935       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    936       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    937         co.UpdateInterval = ephUpdInd;
    938         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSORBIT, 1, obuffer, sizeof(obuffer));
    939         co.UpdateInterval = clkUpdInd;
    940         if (len1 > 0) {
    941           hlpBufferCo += QByteArray(obuffer, len1);
    942         }
    943       }
    944       int mmsg = (co.NumberOfSat[CLOCKORBIT_SATSBAS]    > 0 ||
    945                   co.NumberOfSat[CLOCKORBIT_SATBDS]     > 0   ) ? 1 : 0;
    946       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_QZSSCLOCK, mmsg, obuffer, sizeof(obuffer));
    947       if (len2 > 0) {
    948         hlpBufferCo += QByteArray(obuffer, len2);
    949       }
    950     }
    951     if (co.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) {
    952       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    953       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    954         co.UpdateInterval = ephUpdInd;
    955         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASORBIT, 1, obuffer, sizeof(obuffer));
    956         co.UpdateInterval = clkUpdInd;
    957         if (len1 > 0) {
    958           hlpBufferCo += QByteArray(obuffer, len1);
    959         }
    960       }
    961       int mmsg = (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) ? 1 : 0;
    962       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_SBASCLOCK, mmsg, obuffer,
    963           sizeof(obuffer));
    964       if (len2 > 0) {
    965         hlpBufferCo += QByteArray(obuffer, len2);
    966       }
    967     }
    968     if (co.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
    969       char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    970       if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    971         co.UpdateInterval = ephUpdInd;
    972         int len1 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSORBIT, 1, obuffer, sizeof(obuffer));
    973         co.UpdateInterval = clkUpdInd;
    974         if (len1 > 0) {
    975           hlpBufferCo += QByteArray(obuffer, len1);
    976         }
    977       }
    978       int mmsg = 0;
    979       int len2 = _ssrCorr->MakeClockOrbit(&co, _ssrCorr->COTYPE_BDSCLOCK, mmsg, obuffer, sizeof(obuffer));
    980       if (len2 > 0) {
    981         hlpBufferCo += QByteArray(obuffer, len2);
    982       }
    983     }
    984   }
    985 
    986   // Code Biases
    987   // -----------
    988   QByteArray hlpBufferBias;
    989   if (bias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
    990       || bias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
    991       || bias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
    992       || bias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
    993       || bias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
    994       || bias.NumberOfSat[CLOCKORBIT_SATBDS] > 0) {
    995     char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    996     if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    997       int len = _ssrCorr->MakeCodeBias(&bias, _ssrCorr->CBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
    998       if (len > 0) {
    999         hlpBufferBias = QByteArray(obuffer, len);
    1000       }
    1001     }
    1002   }
    1003 
    1004   // Phase Biases
    1005   // ------------
    1006   QByteArray hlpBufferPhaseBias;
    1007   if ((phasebias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
    1008       || phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
    1009       || phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
    1010       || phasebias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
    1011       || phasebias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0
    1012       || phasebias.NumberOfSat[CLOCKORBIT_SATBDS] > 0)
    1013       && (_phaseBiasInformationDecoded)) {
    1014     char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    1015     if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
    1016       int len = _ssrCorr->MakePhaseBias(&phasebias, _ssrCorr->PBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
    1017       if (len > 0) {
    1018         hlpBufferPhaseBias = QByteArray(obuffer, len);
    1019       }
    1020     }
    1021   }
    1022 
    1023   // VTEC
    1024   // ----
    1025   QByteArray hlpBufferVtec;
    1026   if (vtec.NumLayers > 0) {
    1027     char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    1028     if (fmod(epoTime.gpssec(), _samplRtcmVtec) == 0.0) {
    1029       int len = _ssrCorr->MakeVTEC(&vtec, 0, obuffer, sizeof(obuffer));
    1030       if (len > 0) {
    1031         hlpBufferVtec = QByteArray(obuffer, len);
    1032       }
    1033     }
    1034   }
    1035 
    1036   // Service CRS
    1037   // -----------
    1038   QByteArray hlpBufferServiceCrs;
    1039   if (sizeof(serviceCrs._name) > 0) {
    1040     char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    1041     if (fmod(epoTime.gpssec(), _samplRtcmCrs) == 0.0) {
    1042       int len = t_crsEncoder::RTCM3(serviceCrs, obuffer, sizeof(obuffer));
    1043       if (len > 0) {
    1044         hlpBufferServiceCrs = QByteArray(obuffer, len);
    1045       }
    1046     }
    1047   }
    1048 
    1049   // RTCM CRS
    1050   // --------
    1051   QByteArray hlpBufferRtcmCrs;
    1052   if (sizeof(rtcmCrs._name) > 0) {
    1053     char obuffer[CLOCKORBIT_BUFFERSIZE] = {'\0'};
    1054     if (fmod(epoTime.gpssec(), _samplRtcmCrs) == 0.0) {
    1055       int len = t_crsEncoder::RTCM3(rtcmCrs, obuffer, sizeof(obuffer));
    1056       if (len > 0) {
    1057         hlpBufferRtcmCrs = QByteArray(obuffer, len);
    1058       }
    1059     }
    1060   }
    1061 
    1062   // Create OutBuffer
    1063   // ----------------
    1064   _outBuffer += hlpBufferCo + hlpBufferBias + hlpBufferPhaseBias + hlpBufferVtec
    1065       + hlpBufferServiceCrs + hlpBufferRtcmCrs + '\0';
     1005            memset(obuffer, 0, sizeof(obuffer));
     1006            len = _ssrCorr->MakeCodeBias(&bias, _ssrCorr->CBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
     1007            if (len > 0) {
     1008                hlpBufferBias = QByteArray(obuffer, int(len));
     1009            }
     1010        }
     1011    }
     1012
     1013    // Phase Biases
     1014    // ------------
     1015    QByteArray hlpBufferPhaseBias;
     1016    if ((phasebias.NumberOfSat[CLOCKORBIT_SATGPS] > 0
     1017        || phasebias.NumberOfSat[CLOCKORBIT_SATGLONASS] > 0
     1018        || phasebias.NumberOfSat[CLOCKORBIT_SATGALILEO] > 0
     1019        || phasebias.NumberOfSat[CLOCKORBIT_SATBDS] > 0
     1020        || phasebias.NumberOfSat[CLOCKORBIT_SATQZSS] > 0
     1021        || phasebias.NumberOfSat[CLOCKORBIT_SATSBAS] > 0) && (_phaseBiasInformationDecoded)) {
     1022        if (fmod(epoTime.gpssec(), _samplRtcmEphCorr) == 0.0) {
     1023            memset(obuffer, 0, sizeof(obuffer));
     1024            len = _ssrCorr->MakePhaseBias(&phasebias, _ssrCorr->PBTYPE_AUTO, 0, obuffer, sizeof(obuffer));
     1025            if (len > 0) {
     1026                hlpBufferPhaseBias = QByteArray(obuffer, int(len));
     1027            }
     1028        }
     1029    }
     1030
     1031    // VTEC
     1032    // ----
     1033    QByteArray hlpBufferVtec;
     1034    if (vtec.NumLayers > 0) {
     1035        if (fmod(epoTime.gpssec(), _samplRtcmVtec) == 0.0) {
     1036            memset(obuffer, 0, sizeof(obuffer));
     1037            len = _ssrCorr->MakeVTEC(&vtec, 0, obuffer, sizeof(obuffer));
     1038            if (len > 0) {
     1039                hlpBufferVtec = QByteArray(obuffer, int(len));
     1040            }
     1041        }
     1042    }
     1043
     1044    // Service CRS
     1045    // -----------
     1046    QByteArray hlpBufferServiceCrs;
     1047    if (sizeof(serviceCrs._name) > 0) {
     1048        if (fmod(epoTime.gpssec(), _samplRtcmCrs) == 0.0) {
     1049            memset(obuffer, 0, sizeof(obuffer));
     1050            len = t_crsEncoder::RTCM3(serviceCrs, obuffer, sizeof(obuffer));
     1051            if (len > 0) {
     1052                hlpBufferServiceCrs = QByteArray(obuffer, int(len));
     1053            }
     1054        }
     1055    }
     1056
     1057    // RTCM CRS
     1058    // --------
     1059    QByteArray hlpBufferRtcmCrs;
     1060    if (sizeof(rtcmCrs._name) > 0) {
     1061        if (fmod(epoTime.gpssec(), _samplRtcmCrs) == 0.0) {
     1062            memset(obuffer, 0, sizeof(obuffer));
     1063            len = t_crsEncoder::RTCM3(rtcmCrs, obuffer, sizeof(obuffer));
     1064            if (len > 0) {
     1065                hlpBufferRtcmCrs = QByteArray(obuffer, int(len));
     1066            }
     1067        }
     1068    }
     1069
     1070    // Create OutBuffer
     1071    // ----------------
     1072    _outBuffer += hlpBufferCo + hlpBufferBias + hlpBufferPhaseBias + hlpBufferVtec
     1073        + hlpBufferServiceCrs + hlpBufferRtcmCrs + '\0';
    10661074}
    10671075//
     
    10731081    struct SsrCorr::ClockOrbit::SatData* sd, QString& outLine) {
    10741082
    1075   // Broadcast Position and Velocity
    1076   // -------------------------------
    1077   ColumnVector xB(6);
    1078   ColumnVector vB(3);
    1079   t_irc irc = eph->getCrd(bncTime(GPSweek, GPSweeks), xB, vB, false);
    1080 
    1081   if (irc != success) {
    1082     return irc;
    1083   }
    1084 
    1085   // Precise Position
    1086   // ----------------
    1087   ColumnVector xP = _CoM ? rtnCoM : rtnAPC;
    1088 
    1089   if (xP.size() == 0) {
    1090     return failure;
    1091   }
    1092 
    1093   double dc = 0.0;
    1094   if (_crdTrafoStr != "IGS20") {
    1095     crdTrafo14(GPSweek, xP, dc); // ITRF2020 => ITRF2014
    1096     crdTrafo(GPSweek, xP, dc);   // ITRF2014 to other reference frames
    1097   }
    1098 
    1099   // Difference in xyz
    1100   // -----------------
    1101   ColumnVector dx = xB.Rows(1, 3) - xP;
    1102   ColumnVector dv = vB - rtnVel;
    1103 
    1104   // Difference in RSW
    1105   // -----------------
    1106   ColumnVector rsw(3);
    1107   XYZ_to_RSW(xB.Rows(1, 3), vB, dx, rsw);
    1108 
    1109   ColumnVector dotRsw(3);
    1110   XYZ_to_RSW(xB.Rows(1, 3), vB, dv, dotRsw);
    1111 
    1112   // Clock Correction
    1113   // ----------------
    1114   double dClkA0 = rtnClk(1) - (xB(4) - dc) * t_CST::c;
    1115   double dClkA1 = 0.0;
    1116   if (rtnClk(2)) {
    1117     dClkA1 = rtnClk(2) - xB(5) * t_CST::c;
    1118   }
    1119   double dClkA2 = 0.0;
    1120   if (rtnClk(3)) {
    1121     dClkA2 = rtnClk(3) - xB(6) * t_CST::c;
    1122   }
    1123 
    1124   if (sd) {
    1125     sd->ID = prn.mid(1).toInt();
    1126     sd->IOD = eph->IOD();
    1127     sd->Clock.DeltaA0 = dClkA0;
    1128     sd->Clock.DeltaA1 = dClkA1;
    1129     sd->Clock.DeltaA2 = dClkA2;
    1130     sd->UserRangeAccuracy = rtnUra;
    1131     sd->Orbit.DeltaRadial    = rsw(1);
    1132     sd->Orbit.DeltaAlongTrack = rsw(2);
    1133     sd->Orbit.DeltaCrossTrack = rsw(3);
    1134     sd->Orbit.DotDeltaRadial    = dotRsw(1);
    1135     sd->Orbit.DotDeltaAlongTrack = dotRsw(2);
    1136     sd->Orbit.DotDeltaCrossTrack = dotRsw(3);
    1137 
    1138     if (corrIsOutOfRange(sd)) {
    1139       emit(newMessage(QString("bncRtnetUploadCaster: SSR parameter is out of its defined range").toLatin1(), false));
    1140       return failure;
    1141     }
    1142   }
    1143 
    1144   outLine = QString().asprintf("%d %.1f %s  %u  %10.3f %8.3f %8.3f  %8.3f %8.3f %8.3f\n", GPSweek,
    1145       GPSweeks, eph->prn().toString().c_str(), eph->IOD(), dClkA0, dClkA1, dClkA2,
    1146       rsw(1), rsw(2), rsw(3));  //fprintf(stderr, "%s\n", outLine.toStdString().c_str());
    1147 
    1148   // RTNET full clock for RINEX and SP3 file
    1149   // ---------------------------------------
    1150   double relativity = -2.0 * DotProduct(xP, rtnVel) / t_CST::c;
    1151   double clkRnx    = (rtnClk[0] - relativity) / t_CST::c;  // [s]
    1152   double clkRnxRate = rtnClk[1] / t_CST::c;                 // [s/s  = -]
    1153   double clkRnxAcc  = rtnClk[2] / t_CST::c;                 // [s/s² = -/s]
    1154 
    1155   if (_rnx) {
    1156     double clkRnxSig, clkRnxRateSig, clkRnxAccSig;
    1157     int s = rtnClkSig.size();
    1158     switch (s) {
    1159       case 1:
    1160         clkRnxSig    = rtnClkSig[0] / t_CST::c;    // [s]
    1161         clkRnxRateSig = 0.0;                        // [s/s = -]
    1162         clkRnxAccSig  = 0.0;                        // [s/s² ) -/s]
    1163         break;
    1164       case 2:
    1165         clkRnxSig    = rtnClkSig[0] / t_CST::c;     // [s]
    1166         clkRnxRateSig = rtnClkSig[1] / t_CST::c;     // [s/s = -]
    1167         clkRnxAccSig  = 0.0;                         // [s/s² ) -/s]
    1168         break;
    1169       case 3:
    1170         clkRnxSig    = rtnClkSig[0] / t_CST::c;     // [s]
    1171         clkRnxRateSig = rtnClkSig[1] / t_CST::c;     // [s/s = -]
    1172         clkRnxAccSig  = rtnClkSig[2] / t_CST::c;     // [s/s² ) -/s]
    1173         break;
    1174     }
    1175     _rnx->write(GPSweek, GPSweeks, prn, clkRnx, clkRnxRate, clkRnxAcc,
    1176                 clkRnxSig, clkRnxRateSig, clkRnxAccSig);
    1177   }
    1178   if (_sp3) {
    1179     _sp3->write(GPSweek, GPSweeks, prn, rtnCoM, clkRnx, rtnVel, clkRnxRate);
    1180   }
    1181   return success;
     1083    // Broadcast Position and Velocity
     1084    // -------------------------------
     1085    ColumnVector xB(6);
     1086    ColumnVector vB(3);
     1087    t_irc irc = eph->getCrd(bncTime(GPSweek, GPSweeks), xB, vB, false);
     1088
     1089    if (irc != success) {
     1090        return irc;
     1091    }
     1092
     1093    // Precise Position
     1094    // ----------------
     1095    ColumnVector xP = _CoM ? rtnCoM : rtnAPC;
     1096
     1097    if (xP.size() == 0) {
     1098        return failure;
     1099    }
     1100
     1101    double dc = 0.0;
     1102    if (_crdTrafoStr != "IGS20") {
     1103        crdTrafo14(GPSweek, xP, dc); // ITRF2020 => ITRF2014
     1104        crdTrafo(GPSweek, xP, dc);   // ITRF2014 to other reference frames
     1105    }
     1106
     1107    // Difference in xyz
     1108    // -----------------
     1109    ColumnVector dx = xB.Rows(1, 3) - xP;
     1110    ColumnVector dv = vB - rtnVel;
     1111
     1112    // Difference in RSW
     1113    // -----------------
     1114    ColumnVector rsw(3);
     1115    XYZ_to_RSW(xB.Rows(1, 3), vB, dx, rsw);
     1116
     1117    ColumnVector dotRsw(3);
     1118    XYZ_to_RSW(xB.Rows(1, 3), vB, dv, dotRsw);
     1119
     1120    // Clock Correction
     1121    // ----------------
     1122    double dClkA0 = rtnClk(1) - (xB(4) - dc) * t_CST::c;
     1123    double dClkA1 = 0.0;
     1124    if (rtnClk(2)) {
     1125        dClkA1 = rtnClk(2) - xB(5) * t_CST::c;
     1126    }
     1127    double dClkA2 = 0.0;
     1128    if (rtnClk(3)) {
     1129        dClkA2 = rtnClk(3) - xB(6) * t_CST::c;
     1130    }
     1131
     1132    if (sd) {
     1133        sd->ID = prn.mid(1).toInt();
     1134        sd->IOD = eph->IOD();
     1135        sd->Clock.DeltaA0 = dClkA0;
     1136        sd->Clock.DeltaA1 = dClkA1;
     1137        sd->Clock.DeltaA2 = dClkA2;
     1138        sd->UserRangeAccuracy = rtnUra;
     1139        sd->Orbit.DeltaRadial = rsw(1);
     1140        sd->Orbit.DeltaAlongTrack = rsw(2);
     1141        sd->Orbit.DeltaCrossTrack = rsw(3);
     1142        sd->Orbit.DotDeltaRadial = dotRsw(1);
     1143        sd->Orbit.DotDeltaAlongTrack = dotRsw(2);
     1144        sd->Orbit.DotDeltaCrossTrack = dotRsw(3);
     1145
     1146        if (corrIsOutOfRange(sd)) {
     1147            emit(newMessage(QString("bncRtnetUploadCaster: SSR parameter is out of its defined range").toLatin1(), false));
     1148            return failure;
     1149        }
     1150    }
     1151
     1152    outLine = QString().asprintf("%d %.1f %s  %u  %10.3f %8.3f %8.3f  %8.3f %8.3f %8.3f\n", GPSweek,
     1153        GPSweeks, eph->prn().toString().c_str(), eph->IOD(), dClkA0, dClkA1, dClkA2,
     1154        rsw(1), rsw(2), rsw(3));  //fprintf(stderr, "%s\n", outLine.toStdString().c_str());
     1155
     1156    // RTNET full clock for RINEX and SP3 file
     1157    // ---------------------------------------
     1158    double relativity = -2.0 * DotProduct(xP, rtnVel) / t_CST::c;
     1159    double clkRnx = (rtnClk[0] - relativity) / t_CST::c;  // [s]
     1160    double clkRnxRate = rtnClk[1] / t_CST::c;                 // [s/s  = -]
     1161    double clkRnxAcc = rtnClk[2] / t_CST::c;                 // [s/s² = -/s]
     1162
     1163    if (_rnx) {
     1164        double clkRnxSig, clkRnxRateSig, clkRnxAccSig;
     1165        int s = rtnClkSig.size();
     1166        switch (s) {
     1167        case 1:
     1168            clkRnxSig = rtnClkSig[0] / t_CST::c;    // [s]
     1169            clkRnxRateSig = 0.0;                        // [s/s = -]
     1170            clkRnxAccSig = 0.0;                        // [s/s² ) -/s]
     1171            break;
     1172        case 2:
     1173            clkRnxSig = rtnClkSig[0] / t_CST::c;     // [s]
     1174            clkRnxRateSig = rtnClkSig[1] / t_CST::c;     // [s/s = -]
     1175            clkRnxAccSig = 0.0;                         // [s/s² ) -/s]
     1176            break;
     1177        case 3:
     1178            clkRnxSig = rtnClkSig[0] / t_CST::c;     // [s]
     1179            clkRnxRateSig = rtnClkSig[1] / t_CST::c;     // [s/s = -]
     1180            clkRnxAccSig = rtnClkSig[2] / t_CST::c;     // [s/s² ) -/s]
     1181            break;
     1182        }
     1183        _rnx->write(GPSweek, GPSweeks, prn, clkRnx, clkRnxRate, clkRnxAcc,
     1184            clkRnxSig, clkRnxRateSig, clkRnxAccSig);
     1185    }
     1186    if (_sp3) {
     1187        _sp3->write(GPSweek, GPSweeks, prn, rtnCoM, clkRnx, rtnVel, clkRnxRate);
     1188    }
     1189    return success;
    11821190}
    11831191
     
    11871195    double& dc) {
    11881196
    1189   // Current epoch minus 2000.0 in years
    1190   // ------------------------------------
    1191   double dt = (GPSWeek - (1042.0 + 6.0 / 7.0)) / 365.2422 * 7.0 + 2000.0 - _t0;
    1192 
    1193   ColumnVector dx(3);
    1194 
    1195   dx(1) = _dx + dt * _dxr;
    1196   dx(2) = _dy + dt * _dyr;
    1197   dx(3) = _dz + dt * _dzr;
    1198 
    1199   static const double arcSec = 180.0 * 3600.0 / M_PI;
    1200 
    1201   double ox = (_ox + dt * _oxr) / arcSec;
    1202   double oy = (_oy + dt * _oyr) / arcSec;
    1203   double oz = (_oz + dt * _ozr) / arcSec;
    1204 
    1205   double sc = 1.0 + _sc * 1e-9 + dt * _scr * 1e-9;
    1206 
    1207   // Specify approximate center of area
    1208   // ----------------------------------
    1209   ColumnVector meanSta(3);
    1210 
    1211   if (_crdTrafoStr == "ETRF2000") {
    1212     meanSta(1) = 3661090.0;
    1213     meanSta(2) = 845230.0;
    1214     meanSta(3) = 5136850.0;
    1215   }
    1216   else if (_crdTrafoStr == "GDA2020") {
    1217     meanSta(1) = -4052050.0;
    1218     meanSta(2) = 4212840.0;
    1219     meanSta(3) = -2545110.0;
    1220   }
    1221   else if (_crdTrafoStr == "SIRGAS2000") {
    1222     meanSta(1) = 3740860.0;
    1223     meanSta(2) = -4964290.0;
    1224     meanSta(3) = -1425420.0;
    1225   }
    1226   else if (_crdTrafoStr == "DREF91") {
    1227     meanSta(1) = 3959579.0;
    1228     meanSta(2) = 721719.0;
    1229     meanSta(3) = 4931539.0;
    1230   }
    1231   else if (_crdTrafoStr == "Custom") {
    1232     meanSta(1) = 0.0;
    1233     meanSta(2) = 0.0;
    1234     meanSta(3) = 0.0;
    1235   }
    1236 
    1237   // Clock correction proportional to topocentric distance to satellites
    1238   // -------------------------------------------------------------------
    1239   double rho = (xyz - meanSta).NormFrobenius();
    1240   dc = rho * (sc - 1.0) / sc / t_CST::c;
    1241 
    1242   Matrix rMat(3, 3);
    1243   rMat(1, 1) = 1.0;
    1244   rMat(1, 2) = -oz;
    1245   rMat(1, 3) = oy;
    1246   rMat(2, 1) = oz;
    1247   rMat(2, 2) = 1.0;
    1248   rMat(2, 3) = -ox;
    1249   rMat(3, 1) = -oy;
    1250   rMat(3, 2) = ox;
    1251   rMat(3, 3) = 1.0;
    1252 
    1253   xyz = sc * rMat * xyz + dx;
     1197    // Current epoch minus 2000.0 in years
     1198    // ------------------------------------
     1199    double dt = (GPSWeek - (1042.0 + 6.0 / 7.0)) / 365.2422 * 7.0 + 2000.0 - _t0;
     1200
     1201    ColumnVector dx(3);
     1202
     1203    dx(1) = _dx + dt * _dxr;
     1204    dx(2) = _dy + dt * _dyr;
     1205    dx(3) = _dz + dt * _dzr;
     1206
     1207    static const double arcSec = 180.0 * 3600.0 / M_PI;
     1208
     1209    double ox = (_ox + dt * _oxr) / arcSec;
     1210    double oy = (_oy + dt * _oyr) / arcSec;
     1211    double oz = (_oz + dt * _ozr) / arcSec;
     1212
     1213    double sc = 1.0 + _sc * 1e-9 + dt * _scr * 1e-9;
     1214
     1215    // Specify approximate center of area
     1216    // ----------------------------------
     1217    ColumnVector meanSta(3);
     1218
     1219    if (_crdTrafoStr == "ETRF2000") {
     1220        meanSta(1) = 3661090.0;
     1221        meanSta(2) = 845230.0;
     1222        meanSta(3) = 5136850.0;
     1223    }
     1224    else if (_crdTrafoStr == "GDA2020") {
     1225        meanSta(1) = -4052050.0;
     1226        meanSta(2) = 4212840.0;
     1227        meanSta(3) = -2545110.0;
     1228    }
     1229    else if (_crdTrafoStr == "SIRGAS2000") {
     1230        meanSta(1) = 3740860.0;
     1231        meanSta(2) = -4964290.0;
     1232        meanSta(3) = -1425420.0;
     1233    }
     1234    else if (_crdTrafoStr == "DREF91") {
     1235        meanSta(1) = 3959579.0;
     1236        meanSta(2) = 721719.0;
     1237        meanSta(3) = 4931539.0;
     1238    }
     1239    else if (_crdTrafoStr == "Custom") {
     1240        meanSta(1) = 0.0;
     1241        meanSta(2) = 0.0;
     1242        meanSta(3) = 0.0;
     1243    }
     1244
     1245    // Clock correction proportional to topocentric distance to satellites
     1246    // -------------------------------------------------------------------
     1247    double rho = (xyz - meanSta).NormFrobenius();
     1248    dc = rho * (sc - 1.0) / sc / t_CST::c;
     1249
     1250    Matrix rMat(3, 3);
     1251    rMat(1, 1) = 1.0;
     1252    rMat(1, 2) = -oz;
     1253    rMat(1, 3) = oy;
     1254    rMat(2, 1) = oz;
     1255    rMat(2, 2) = 1.0;
     1256    rMat(2, 3) = -ox;
     1257    rMat(3, 1) = -oy;
     1258    rMat(3, 2) = ox;
     1259    rMat(3, 3) = 1.0;
     1260
     1261    xyz = sc * rMat * xyz + dx;
    12541262}
    12551263
     
    12591267    double& dc) {
    12601268
    1261   // Current epoch minus 2000.0 in years
    1262   // ------------------------------------
    1263   double dt = (GPSWeek - (1042.0 + 6.0 / 7.0)) / 365.2422 * 7.0 + 2000.0 - _t0;
    1264 
    1265   ColumnVector dx(3);
    1266 
    1267   dx(1) = _dx14 + dt * _dxr14;
    1268   dx(2) = _dy14 + dt * _dyr14;
    1269   dx(3) = _dz14 + dt * _dzr14;
    1270 
    1271   static const double arcSec = 180.0 * 3600.0 / M_PI;
    1272 
    1273   double ox = (_ox14 + dt * _oxr14) / arcSec;
    1274   double oy = (_oy14 + dt * _oyr14) / arcSec;
    1275   double oz = (_oz14 + dt * _ozr14) / arcSec;
    1276 
    1277   double sc = 1.0 + _sc14 * 1e-9 + dt * _scr14 * 1e-9;
    1278 
    1279   // Specify approximate center of area
    1280   // ----------------------------------
    1281   ColumnVector meanSta(3);
    1282   meanSta(1) = 0.0; // TODO
    1283   meanSta(2) = 0.0; // TODO
    1284   meanSta(3) = 0.0; // TODO
    1285 
    1286   // Clock correction proportional to topocentric distance to satellites
    1287   // -------------------------------------------------------------------
    1288   double rho = (xyz - meanSta).NormFrobenius();
    1289   dc = rho * (sc - 1.0) / sc / t_CST::c;
    1290 
    1291   Matrix rMat(3, 3);
    1292   rMat(1, 1) = 1.0;
    1293   rMat(1, 2) = -oz;
    1294   rMat(1, 3) = oy;
    1295   rMat(2, 1) = oz;
    1296   rMat(2, 2) = 1.0;
    1297   rMat(2, 3) = -ox;
    1298   rMat(3, 1) = -oy;
    1299   rMat(3, 2) = ox;
    1300   rMat(3, 3) = 1.0;
    1301 
    1302   xyz = sc * rMat * xyz + dx;
     1269    // Current epoch minus 2000.0 in years
     1270    // ------------------------------------
     1271    double dt = (GPSWeek - (1042.0 + 6.0 / 7.0)) / 365.2422 * 7.0 + 2000.0 - _t0;
     1272
     1273    ColumnVector dx(3);
     1274
     1275    dx(1) = _dx14 + dt * _dxr14;
     1276    dx(2) = _dy14 + dt * _dyr14;
     1277    dx(3) = _dz14 + dt * _dzr14;
     1278
     1279    static const double arcSec = 180.0 * 3600.0 / M_PI;
     1280
     1281    double ox = (_ox14 + dt * _oxr14) / arcSec;
     1282    double oy = (_oy14 + dt * _oyr14) / arcSec;
     1283    double oz = (_oz14 + dt * _ozr14) / arcSec;
     1284
     1285    double sc = 1.0 + _sc14 * 1e-9 + dt * _scr14 * 1e-9;
     1286
     1287    // Specify approximate center of area
     1288    // ----------------------------------
     1289    ColumnVector meanSta(3);
     1290    meanSta(1) = 0.0; // TODO
     1291    meanSta(2) = 0.0; // TODO
     1292    meanSta(3) = 0.0; // TODO
     1293
     1294    // Clock correction proportional to topocentric distance to satellites
     1295    // -------------------------------------------------------------------
     1296    double rho = (xyz - meanSta).NormFrobenius();
     1297    dc = rho * (sc - 1.0) / sc / t_CST::c;
     1298
     1299    Matrix rMat(3, 3);
     1300    rMat(1, 1) = 1.0;
     1301    rMat(1, 2) = -oz;
     1302    rMat(1, 3) = oy;
     1303    rMat(2, 1) = oz;
     1304    rMat(2, 2) = 1.0;
     1305    rMat(2, 3) = -ox;
     1306    rMat(3, 1) = -oy;
     1307    rMat(3, 2) = ox;
     1308    rMat(3, 3) = 1.0;
     1309
     1310    xyz = sc * rMat * xyz + dx;
    13031311}
    13041312
     
    13071315int bncRtnetUploadCaster::determineUpdateInd(double samplingRate) {
    13081316
    1309   if (samplingRate == 10.0) {
    1310     return 3;
    1311   }
    1312   else if (samplingRate == 15.0) {
    1313     return 4;
    1314   }
    1315   else if (samplingRate == 30.0) {
    1316     return 5;
    1317   }
    1318   else if (samplingRate == 60.0) {
    1319     return 6;
    1320   }
    1321   else if (samplingRate == 120.0) {
    1322     return 7;
    1323   }
    1324   else if (samplingRate == 240.0) {
    1325     return 8;
    1326   }
    1327   else if (samplingRate == 300.0) {
    1328     return 9;
    1329   }
    1330   else if (samplingRate == 600.0) {
    1331     return 10;
    1332   }
    1333   else if (samplingRate == 900.0) {
    1334     return 11;
    1335   }
    1336   else if (samplingRate == 1800.0) {
    1337     return 12;
    1338   }
    1339   else if (samplingRate == 3600.0) {
    1340     return 13;
    1341   }
    1342   else if (samplingRate == 7200.0) {
    1343     return 14;
    1344   }
    1345   else if (samplingRate == 10800.0) {
    1346     return 15;
    1347   }
    1348   return 2;  // default
     1317    if (samplingRate == 1.0) {
     1318        return 0;
     1319    }
     1320    else if (samplingRate == 2.0) {
     1321        return 1;
     1322    }
     1323    else if (samplingRate == 5.0) {
     1324        return 2;
     1325    }
     1326    else if (samplingRate == 10.0) {
     1327        return 3;
     1328    }
     1329    else if (samplingRate == 15.0) {
     1330        return 4;
     1331    }
     1332    else if (samplingRate == 30.0) {
     1333        return 5;
     1334    }
     1335    else if (samplingRate == 60.0) {
     1336        return 6;
     1337    }
     1338    else if (samplingRate == 120.0) {
     1339        return 7;
     1340    }
     1341    else if (samplingRate == 240.0) {
     1342        return 8;
     1343    }
     1344    else if (samplingRate == 300.0) {
     1345        return 9;
     1346    }
     1347    else if (samplingRate == 600.0) {
     1348        return 10;
     1349    }
     1350    else if (samplingRate == 900.0) {
     1351        return 11;
     1352    }
     1353    else if (samplingRate == 1800.0) {
     1354        return 12;
     1355    }
     1356    else if (samplingRate == 3600.0) {
     1357        return 13;
     1358    }
     1359    else if (samplingRate == 7200.0) {
     1360        return 14;
     1361    }
     1362    else if (samplingRate == 10800.0) {
     1363        return 15;
     1364    }
     1365    return 2;  // default
    13491366}
    13501367
     
    13531370bool bncRtnetUploadCaster::corrIsOutOfRange(struct SsrCorr::ClockOrbit::SatData* sd) {
    13541371
    1355   if (fabs(sd->Clock.DeltaA0) > 209.7151)   {return true;}
    1356   if (fabs(sd->Clock.DeltaA1) > 1.048575)   {return true;}
    1357   if (fabs(sd->Clock.DeltaA2) > 1.34217726) {return true;}
    1358 
    1359   if (fabs(sd->Orbit.DeltaRadial)     > 209.7151) {return true;}
    1360   if (fabs(sd->Orbit.DeltaAlongTrack) > 209.7148) {return true;}
    1361   if (fabs(sd->Orbit.DeltaCrossTrack) > 209.7148) {return true;}
    1362 
    1363   if (fabs(sd->Orbit.DotDeltaRadial)     > 1.048575) {return true;}
    1364   if (fabs(sd->Orbit.DotDeltaAlongTrack) > 1.048572) {return true;}
    1365   if (fabs(sd->Orbit.DotDeltaCrossTrack) > 1.048572) {return true;}
    1366   return false;
     1372    if (fabs(sd->Clock.DeltaA0) > 209.7151) { return true; }
     1373    if (fabs(sd->Clock.DeltaA1) > 1.048575) { return true; }
     1374    if (fabs(sd->Clock.DeltaA2) > 1.34217726) { return true; }
     1375
     1376    if (fabs(sd->Orbit.DeltaRadial) > 209.7151) { return true; }
     1377    if (fabs(sd->Orbit.DeltaAlongTrack) > 209.7148) { return true; }
     1378    if (fabs(sd->Orbit.DeltaCrossTrack) > 209.7148) { return true; }
     1379
     1380    if (fabs(sd->Orbit.DotDeltaRadial) > 1.048575) { return true; }
     1381    if (fabs(sd->Orbit.DotDeltaAlongTrack) > 1.048572) { return true; }
     1382    if (fabs(sd->Orbit.DotDeltaCrossTrack) > 1.048572) { return true; }
     1383    return false;
    13671384}
  • trunk/BNC/src/upload/bncrtnetuploadcaster.h

    r10543 r10657  
    1919
    2020class bncRtnetUploadCaster : public bncUploadCaster {
    21  Q_OBJECT
    22  public:
    23   bncRtnetUploadCaster(const QString& mountpoint,
    24                   const QString& outHost, int outPort,
    25                   const QString& ntripVersion, const QString& userName,
    26                   const QString& password,
    27                   const QString& crdTrafo, const QString& ssrFormat,
    28                   bool  CoM,
    29                   const QString& sp3FileName,
    30                   const QString& rnxFileName,
    31                   const QString& bsxFileName,
    32                   int PID, int SID, int IOD, int iRow);
    33   void decodeRtnetStream(char* buffer, int bufLen);
    34  protected:
    35   virtual ~bncRtnetUploadCaster();
    36  private:
    37   t_irc processSatellite(const t_eph* eph, int GPSweek,
    38                         double GPSweeks, const QString& prn,
    39                         const ColumnVector& rtnAPC,
    40                         double ura,
    41                         const ColumnVector& rtnClk,
    42                         const ColumnVector& rtnVel,
    43                         const ColumnVector& rtnCoM,
    44                         const ColumnVector& rtnClkSig,
    45                         struct SsrCorr::ClockOrbit::SatData* sd,
    46                         QString& outLine);
    47   void decodeRtnetEpoch(QStringList epochLines);
    48   bool corrIsOutOfRange(struct SsrCorr::ClockOrbit::SatData* sd);
     21    Q_OBJECT
     22public:
     23    bncRtnetUploadCaster(const QString& mountpoint,
     24        const QString& outHost, int outPort,
     25        const QString& ntripVersion, const QString& userName,
     26        const QString& password,
     27        const QString& crdTrafo, const QString& ssrFormat,
     28        bool  CoM,
     29        const QString& sp3FileName,
     30        const QString& rnxFileName,
     31        const QString& bsxFileName,
     32        int PID, int SID, int IOD, int iRow);
     33    void decodeRtnetStream(char* buffer, int bufLen);
     34protected:
     35    virtual ~bncRtnetUploadCaster();
     36private:
     37    t_irc processSatellite(const t_eph* eph, int GPSweek,
     38        double GPSweeks, const QString& prn,
     39        const ColumnVector& rtnAPC,
     40        double ura,
     41        const ColumnVector& rtnClk,
     42        const ColumnVector& rtnVel,
     43        const ColumnVector& rtnCoM,
     44        const ColumnVector& rtnClkSig,
     45        struct SsrCorr::ClockOrbit::SatData* sd,
     46        QString& outLine);
     47    bool corrIsOutOfRange(struct SsrCorr::ClockOrbit::SatData* sd);
    4948
    50   void crdTrafo(int GPSWeek, ColumnVector& xyz, double& dc);
    51   // TODO: the following line can be deleted if all parameters are updated regarding ITRF2020
    52   void crdTrafo14(int GPSWeek, ColumnVector& xyz, double& dc);
     49    void crdTrafo(int GPSWeek, ColumnVector& xyz, double& dc);
     50    // TODO: the following line can be deleted if all parameters are updated regarding ITRF2020
     51    void crdTrafo14(int GPSWeek, ColumnVector& xyz, double& dc);
    5352
    54   int determineUpdateInd(double samplingRate);
     53    int determineUpdateInd(double samplingRate);
    5554
    56   QString        _casterID;
    57   bncEphUser*    _ephUser;
    58   QString        _rtnetStreamBuffer;
    59   QString        _crdTrafoStr;
    60   SsrCorr*      _ssrCorr;
    61   QString        _ssrFormat;
    62   bool           _CoM;
    63   bool           _phaseBiasInformationDecoded;
    64   int            _PID;
    65   int            _SID;
    66   int            _IOD;
    67   int            _samplRtcmClkCorr;
    68   double         _samplRtcmEphCorr;
    69   double         _samplRtcmVtec;
    70   double         _samplRtcmCrs;
    71   double         _dx;
    72   double         _dy;
    73   double         _dz;
    74   double         _dxr;
    75   double         _dyr;
    76   double         _dzr;
    77   double         _ox;
    78   double         _oy;
    79   double         _oz;
    80   double         _oxr;
    81   double         _oyr;
    82   double         _ozr;
    83   double         _sc;
    84   double         _scr;
    85   double         _t0;
    86   /* TODO: the following lines can be deleted if all parameters are updated regarding ITRF2020*/
    87   double         _dx14;
    88   double         _dy14;
    89   double         _dz14;
    90   double         _dxr14;
    91   double         _dyr14;
    92   double         _dzr14;
    93   double         _ox14;
    94   double         _oy14;
    95   double         _oz14;
    96   double         _oxr14;
    97   double         _oyr14;
    98   double         _ozr14;
    99   double         _sc14;
    100   double         _scr14;
    101   double         _t014;
     55    QString        _casterID;
     56    bncEphUser* _ephUser;
     57    QString        _rtnetStreamBuffer;
     58    QString        _crdTrafoStr;
     59    SsrCorr* _ssrCorr;
     60    QString        _ssrFormat;
     61    bool           _CoM;
     62    bool           _phaseBiasInformationDecoded;
     63    int            _PID;
     64    int            _SID;
     65    int            _IOD;
     66    double         _samplRtcmClkCorr;
     67    double         _samplRtcmEphCorr;
     68    double         _samplRtcmVtec;
     69    double         _samplRtcmCrs;
     70    double         _dx;
     71    double         _dy;
     72    double         _dz;
     73    double         _dxr;
     74    double         _dyr;
     75    double         _dzr;
     76    double         _ox;
     77    double         _oy;
     78    double         _oz;
     79    double         _oxr;
     80    double         _oyr;
     81    double         _ozr;
     82    double         _sc;
     83    double         _scr;
     84    double         _t0;
     85    /* TODO: the following lines can be deleted if all parameters are updated regarding ITRF2020*/
     86    double         _dx14;
     87    double         _dy14;
     88    double         _dz14;
     89    double         _dxr14;
     90    double         _dyr14;
     91    double         _dzr14;
     92    double         _ox14;
     93    double         _oy14;
     94    double         _oz14;
     95    double         _oxr14;
     96    double         _oyr14;
     97    double         _ozr14;
     98    double         _sc14;
     99    double         _scr14;
     100    double         _t014;
    102101
    103   bncClockRinex* _rnx;
    104   bncSP3*        _sp3;
    105   bncBiasSinex*  _bsx;
    106   QMap<QString, const t_eph*>* _usedEph;
     102    bncClockRinex* _rnx;
     103    bncSP3* _sp3;
     104    bncBiasSinex* _bsx;
     105    QMap<QString, const t_eph*>* _usedEph;
    107106};
    108107
    109108struct phaseBiasesSat {
    110   phaseBiasesSat() {
    111     yawAngle = 0.0;
    112     yawRate = 0.0;
    113   }
    114   double yawAngle;
    115   double yawRate;
     109    phaseBiasesSat() {
     110        yawAngle = 0.0;
     111        yawRate = 0.0;
     112    }
     113    double yawAngle;
     114    double yawRate;
    116115};
    117116
    118117struct phaseBiasSignal {
    119   phaseBiasSignal() {
    120     bias      = 0.0;
    121     integerIndicator    = 0;
    122     wlIndicator          = 0;
    123     discontinuityCounter = 0;
    124   }
    125   QString type;
    126   double bias;
    127   unsigned int integerIndicator;
    128   unsigned int wlIndicator;
    129   unsigned int discontinuityCounter;
     118    phaseBiasSignal() {
     119        bias = 0.0;
     120        integerIndicator = 0;
     121        wlIndicator = 0;
     122        discontinuityCounter = 0;
     123    }
     124    QString type;
     125    double bias;
     126    unsigned int integerIndicator;
     127    unsigned int wlIndicator;
     128    unsigned int discontinuityCounter;
    130129};
    131130
Note: See TracChangeset for help on using the changeset viewer.