SatPass.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: SatPass.cpp 3140 2012-06-18 15:03:02Z susancummins $"
00002 
00003 //============================================================================
00004 //
00005 //  This file is part of GPSTk, the GPS Toolkit.
00006 //
00007 //  The GPSTk is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU Lesser General Public License as published
00009 //  by the Free Software Foundation; either version 2.1 of the License, or
00010 //  any later version.
00011 //
00012 //  The GPSTk is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU Lesser General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU Lesser General Public
00018 //  License along with GPSTk; if not, write to the Free Software Foundation,
00019 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
00020 //
00021 //  Copyright 2004, The University of Texas at Austin
00022 //
00023 //============================================================================
00024 
00030 //------------------------------------------------------------------------------------
00031 // system
00032 #include <ostream>
00033 #include <string>
00034 #include <vector>
00035 #include <algorithm>
00036 // gpstk
00037 #include "SatPass.hpp"
00038 #include "GNSSconstants.hpp"    // OSC_FREQ,L1_MULT,L2_MULT
00039 #include "Stats.hpp"
00040 #include "StringUtils.hpp"
00041 #include "RinexObsHeader.hpp"
00042 #include "RinexObsData.hpp"
00043 #include "RinexObsStream.hpp"
00044 #include "RinexUtilities.hpp"
00045 #include "logstream.hpp"
00046 
00047 using namespace std;
00048 using namespace gpstk::StringUtils;
00049 
00050 //------------------------------------------------------------------------------------
00051 namespace gpstk {
00052 
00053 // ------------------ configuration --------------------------------
00054 // note that flag & LL1 = true for all L1 discontinuities
00055 //           flag & LL2 = true for all L2 discontinuities
00056 const unsigned short SatPass::OK  = 1; // good data, no discontinuity
00057 const unsigned short SatPass::BAD = 0; // used by caller to mark bad data
00058 const unsigned short SatPass::LL1 = 2; // discontinuity on L1 only
00059 const unsigned short SatPass::LL2 = 4; // discontinuity on L2 only
00060 const unsigned short SatPass::LL3 = 6; // discontinuity on L1 and L2
00061 double SatPass::maxGap = 1800;         // maximum gap (seconds) allowed within pass
00062 string SatPass::outFormat = string("%4F %10.3g");  // GPS week, seconds of week
00063 
00064 // constructors
00065 SatPass::SatPass(GSatID insat, double indt) throw()
00066 {
00067    vector<string> defaultObsTypes;
00068    defaultObsTypes.push_back("L1");
00069    defaultObsTypes.push_back("L2");
00070    defaultObsTypes.push_back("P1");
00071    defaultObsTypes.push_back("P2");
00072 
00073    init(insat, indt, defaultObsTypes);
00074 }
00075 
00076 SatPass::SatPass(GSatID insat, double indt, vector<string> obstypes) throw()
00077 {
00078    init(insat, indt, obstypes);
00079 }
00080 
00081 void SatPass::init(GSatID insat, double indt, vector<string> obstypes) throw()
00082 {
00083    sat = insat;
00084    dt = indt;
00085    //firstTime = CommonTime::BEGINNING_OF_TIME;
00086    //lastTime = CommonTime::END_OF_TIME;
00087    ngood = 0;
00088    Status = 0;
00089 
00090    for(int i=0; i<obstypes.size(); i++) {
00091       indexForLabel[obstypes[i]] = i;
00092       labelForIndex[i] = obstypes[i];
00093    }
00094 }
00095 
00096 SatPass& SatPass::operator=(const SatPass& right) throw()
00097 {
00098    if(&right != this) {
00099       Status = right.Status;
00100       dt = right.dt;
00101       sat = right.sat;
00102       indexForLabel = right.indexForLabel;
00103       labelForIndex = right.labelForIndex;
00104       firstTime = right.firstTime;
00105       lastTime = right.lastTime;
00106       ngood = right.ngood;
00107       spdvector.resize(right.spdvector.size());
00108       for(int i=0; i<right.spdvector.size(); i++)
00109          spdvector[i] = right.spdvector[i];
00110    }
00111 
00112    return *this;
00113 }
00114 
00115 int SatPass::addData(const CommonTime tt, vector<string>& ots, vector<double>& data)
00116    throw(Exception)
00117 {
00118    vector<unsigned short> lli(data.size(),0),ssi(data.size(),0);
00119    try { return addData(tt, ots, data, lli, ssi); }
00120    catch(Exception& e) { GPSTK_RETHROW(e); }
00121 }
00122 
00123 // return -2 time tag out of order, data not added
00124 //        -1 gap is larger than MaxGap, data not added
00125 //       >=0 (success) index of the added data
00126 int SatPass::addData(const CommonTime tt,
00127                          vector<string>& obstypes,
00128                          vector<double>& data,
00129                          vector<unsigned short>& lli,
00130                          vector<unsigned short>& ssi,
00131                          unsigned short flag) throw(Exception)
00132 {
00133    // check that data, lli and ssi have the same length - throw
00134    if(data.size() != lli.size() || data.size() != ssi.size()) {
00135       Exception e("Dimensions do not match in addData()"
00136                   + StringUtils::asString(data.size()) + ","
00137                   + StringUtils::asString(lli.size()) + ","
00138                   + StringUtils::asString(ssi.size()));
00139       GPSTK_THROW(e);
00140    }
00141    if(spdvector.size() > 0 && spdvector[0].data.size() != data.size()) {
00142       Exception e("Error - addData passed different dimension that earlier!"
00143                    + StringUtils::asString(data.size()) + " != "
00144                    + StringUtils::asString(spdvector[0].data.size()));
00145       GPSTK_THROW(e);
00146    }
00147 
00148    // create a new SatPassData
00149    SatPassData spd(data.size());
00150    spd.flag = flag;
00151    for(int k=0; k<data.size(); k++) {
00152       int i = indexForLabel[obstypes[k]];
00153       spd.data[i] = data[k];
00154       spd.lli[i] = lli[k];
00155       spd.ssi[i] = ssi[k];
00156    }
00157 
00158    // push_back defines count and
00159    // returns : >=0 index of added data (ok), -1 gap, -2 tt out of order
00160    return push_back(tt, spd);
00161 }
00162 
00163 // return -3 sat not found, data not added
00164 //        -2 time tag out of order, data not added
00165 //        -1 gap is larger than MaxGap, data not added
00166 //       >=0 (success) index of the added data
00167 int SatPass::addData(const RinexObsData& robs) throw()
00168 {
00169    if(robs.epochFlag != 0 && robs.epochFlag != 1) return false;
00170    RinexObsData::RinexSatMap::const_iterator it;
00171    RinexObsData::RinexObsTypeMap::const_iterator jt;
00172    map<string,unsigned int>::const_iterator kt;
00173    SatPassData spd(indexForLabel.size());
00174 
00175    // loop over satellites
00176    for(it=robs.obs.begin(); it != robs.obs.end(); it++) {
00177       if(it->first == sat) {
00178          // loop over obs
00179          for(kt=indexForLabel.begin(); kt != indexForLabel.end(); kt++) {
00180             if((jt=it->second.find(RinexObsHeader::convertObsType(kt->first)))
00181                   == it->second.end()) {
00182                spd.data[kt->second] = 0.0;
00183                spd.lli[kt->second] = 0;
00184                spd.ssi[kt->second] = 0;
00185             }
00186             else {
00187                spd.data[kt->second] = jt->second.data;
00188                spd.lli[kt->second] = jt->second.lli;
00189                spd.ssi[kt->second] = jt->second.ssi;
00190             }
00191          }  // end loop over obs
00192 
00193          spd.flag = OK;             // default
00194 
00195          return push_back(robs.time,spd);
00196       }
00197    }
00198    return -3;
00199 }
00200 
00201 // smooth pseudorange and debias phase; replace the data only if the
00202 // corresponding input flag is 'true'.
00203 // call this ONLY after cycleslips have been removed.
00204 void SatPass::smooth(bool smoothPR, bool debiasPH, string& msg) throw(Exception)
00205 {
00206    // test for L1, L2, C1/P1, P2
00207    bool useC1=false;
00208    map<string, unsigned int>::const_iterator it;
00209    if(indexForLabel.find("L1") == indexForLabel.end() ||
00210       indexForLabel.find("L2") == indexForLabel.end() ||
00211       (indexForLabel.find("C1") == indexForLabel.end() &&
00212        indexForLabel.find("P1") == indexForLabel.end()) ||
00213       indexForLabel.find("P2") == indexForLabel.end()) {
00214       Exception e("Obs types L1 L2 C1/P1 P2 required for smooth()");
00215       GPSTK_THROW(e);
00216    }
00217    if(indexForLabel.find("P1") == indexForLabel.end()) useC1=true;
00218 
00219    //static const double CFF=C_MPS/OSC_FREQ;
00220    static const double F1=L1_MULT_GPS;   // 154.0;
00221    static const double F2=L2_MULT_GPS;   // 120.0;
00222    // wavelengths
00223    static const double wl1=L1_WAVELENGTH_GPS; //CFF/F1;                        // 19.0cm
00224    static const double wl2=L2_WAVELENGTH_GPS; //CFF/F2;                        // 24.4cm
00225    // ionospheric constant
00226    static const double alpha = ((F1/F2)*(F1/F2) - 1.0);
00227 
00228    // transformation matrix
00229    // PB = D * L - P   pure biases = constants for continuous phase
00230    // RB = D * PB      real biases = wavelength * N
00231    // but DD=1 so **( RB = DDL-DP = L-DP )**
00232    // dbL = L - RB     debiased phase
00233    // smR = D * dbL    smoothed range
00234    //      1 [ a+2     -2  ]
00235    // D = -- [             ]
00236    //      a [ 2a+2 -(a+2) ]
00237    static const double D11 = (alpha+2.)/alpha;
00238    static const double D12 = -2./alpha;
00239    static const double D21 = (2*alpha+2.)/alpha;
00240    static const double D22 = -D11;
00241 
00242    bool first;
00243    int i;
00244    double RB1,RB2,dbL1,dbL2;
00245    Stats<double> PB1,PB2;
00246 
00247    // get the biases B = L - DP
00248    for(first=true,i=0; i<spdvector.size(); i++) {
00249       if(!(spdvector[i].flag & OK)) continue;        // skip bad data
00250       double P1 = spdvector[i].data[indexForLabel[(useC1 ? "C1" : "P1")]];
00251       double P2 = spdvector[i].data[indexForLabel["P2"]];
00252       RB1 = wl1*spdvector[i].data[indexForLabel["L1"]] - D11*P1 - D12*P2;
00253       RB2 = wl2*spdvector[i].data[indexForLabel["L2"]] - D21*P1 - D22*P2;
00254       if(first) { dbL1 = RB1; dbL2 = RB2; first = false; }
00255       PB1.Add(RB1-dbL1);
00256       PB2.Add(RB2-dbL2);
00257    }
00258    // real biases in cycles
00259    RB1 = (dbL1 + PB1.Average())/wl1;
00260    RB2 = (dbL2 + PB2.Average())/wl2;
00261 
00262    ostringstream oss;
00263    oss << "SMT" << fixed << setprecision(2)
00264        << " " << sat
00265        << " " << printTime(getFirstGoodTime(),outFormat)
00266        << " " << printTime(getLastGoodTime(),outFormat)
00267        << " " << setw(5)  << PB1.N()
00268        << " " << setw(12) << PB1.Average()+dbL1
00269        << " " << setw(5)  << PB1.StdDev()
00270        << " " << setw(12) << PB1.Minimum()+dbL1
00271        << " " << setw(12) << PB1.Maximum()+dbL1
00272        << " " << setw(5)  << PB2.N()
00273        << " " << setw(12) << PB2.Average()+dbL2
00274        << " " << setw(5)  << PB2.StdDev()
00275        << " " << setw(12) << PB2.Minimum()+dbL2
00276        << " " << setw(12) << PB2.Maximum()+dbL2
00277        << " " << setw(13) << RB1
00278        << " " << setw(13) << RB2;
00279    msg = oss.str();
00280 
00281    if(!debiasPH && !smoothPR) return;
00282 
00283    for(i=0; i<spdvector.size(); i++) {
00284       if(!(spdvector[i].flag & OK)) continue;        // skip bad data
00285 
00286       // compute the debiased phase
00287       dbL1 = spdvector[i].data[indexForLabel["L1"]] - RB1;
00288       dbL2 = spdvector[i].data[indexForLabel["L2"]] - RB2;
00289 
00290       // replace the phase with the debiased phase
00291       if(debiasPH) {
00292          spdvector[i].data[indexForLabel["L1"]] = dbL1;
00293          spdvector[i].data[indexForLabel["L2"]] = dbL2;
00294       }
00295       // smooth the range - replace the pseudorange with the smoothed pseudorange
00296       if(smoothPR) {
00297          spdvector[i].data[indexForLabel[(useC1 ? "C1" : "P1")]]
00298                                                 = D11*wl1*dbL1 + D12*wl2*dbL2;
00299          spdvector[i].data[indexForLabel["P2"]] = D21*wl1*dbL1 + D22*wl2*dbL2;
00300       }
00301    }
00302 }
00303 
00304 // -------------------------- get and set routines ----------------------------
00305 double& SatPass::data(unsigned int i, std::string type) throw(Exception)
00306 {
00307    if(i >= spdvector.size()) {
00308       Exception e("Invalid index in data() " + asString(i));
00309       GPSTK_THROW(e);
00310    }
00311    map<string, unsigned int>::const_iterator it;
00312    if((it = indexForLabel.find(type)) == indexForLabel.end()) {
00313       Exception e("Invalid obs type in data() " + type);
00314       GPSTK_THROW(e);
00315    }
00316    return spdvector[i].data[it->second];
00317 }
00318 
00319 double& SatPass::timeoffset(unsigned int i) throw(Exception)
00320 {
00321    if(i >= spdvector.size()) {
00322       Exception e("Invalid index in timeoffset() " + asString(i));
00323       GPSTK_THROW(e);
00324    }
00325    return spdvector[i].toffset;
00326 }
00327 
00328 unsigned short& SatPass::LLI(unsigned int i, std::string type) throw(Exception)
00329 {
00330    if(i >= spdvector.size()) {
00331       Exception e("Invalid index in LLI() " + asString(i));
00332       GPSTK_THROW(e);
00333    }
00334    map<string, unsigned int>::const_iterator it;
00335    if((it = indexForLabel.find(type)) == indexForLabel.end()) {
00336       Exception e("Invalid obs type in LLI() " + type);
00337       GPSTK_THROW(e);
00338    }
00339    return spdvector[i].lli[it->second];
00340 }
00341 
00342 unsigned short& SatPass::SSI(unsigned int i, std::string type) throw(Exception)
00343 {
00344    if(i >= spdvector.size()) {
00345       Exception e("Invalid index in SSI() " + asString(i));
00346       GPSTK_THROW(e);
00347    }
00348    map<string, unsigned int>::const_iterator it;
00349    if((it = indexForLabel.find(type)) == indexForLabel.end()) {
00350       Exception e("Invalid obs type in SSI() " + type);
00351       GPSTK_THROW(e);
00352    }
00353    return spdvector[i].ssi[it->second];
00354 }
00355 
00356 // ---------------------------------- set routines ----------------------------
00357 void SatPass::setFlag(unsigned int i, unsigned short f) throw(Exception)
00358 {
00359    if(i >= spdvector.size()) {
00360       Exception e("Invalid index in setFlag() " + asString(i));
00361       GPSTK_THROW(e);
00362    }
00363 
00364    if(spdvector[i].flag != BAD && f == BAD) ngood--;
00365    if(spdvector[i].flag == BAD && f != BAD) ngood++;
00366    spdvector[i].flag = f;
00367 }
00368 
00369 // ---------------------------------- get routines ----------------------------
00370 // get value of flag at one index
00371 unsigned short SatPass::getFlag(unsigned int i) throw(Exception)
00372 {
00373    if(i >= spdvector.size()) {
00374       Exception e("Invalid index in getFlag() " + asString(i));
00375       GPSTK_THROW(e);
00376    }
00377    return spdvector[i].flag;
00378 }
00379 
00380 // get one element of the count array of this SatPass
00381 unsigned int SatPass::getCount(unsigned int i) const throw(Exception)
00382 {
00383    if(i >= spdvector.size()) {
00384       Exception e("invalid in getCount() " + asString(i));
00385       GPSTK_THROW(e);
00386    }
00387    return spdvector[i].ndt;
00388 }
00389 
00390 // ---------------------------------- utils -----------------------------------
00391 // return the time corresponding to the given index in the data array
00392 CommonTime SatPass::time(unsigned int i) const throw(Exception)
00393 {
00394    if(i > spdvector.size()) {
00395       Exception e("invalid in time() " + asString(i));
00396       GPSTK_THROW(e);
00397    }
00398    // computing toff first is necessary to avoid a rare bug in CommonTime..
00399    double toff = spdvector[i].ndt * dt + spdvector[i].toffset;
00400    return (firstTime + toff);
00401 }
00402 
00403 // return true if the input time could lie within the pass
00404 bool SatPass::includesTime(const CommonTime& tt) const throw()
00405 {
00406    if(tt < firstTime) {
00407       if((firstTime-tt) > maxGap) return false;
00408    }
00409    else if(tt > lastTime) {
00410       if((tt-lastTime) > maxGap) return false;
00411    }
00412    return true;
00413 }
00414 
00415 // create a new SatPass from the given one, starting at count N.
00416 // modify this SatPass to end just before N.
00417 // return true if successful.
00418 bool SatPass::split(int N, SatPass &newSP) {
00419 try {
00420    int i,j,n,oldgood,ilast;
00421    CommonTime tt;
00422 
00423    newSP = SatPass(sat, dt);                       // create new SatPass
00424    newSP.Status = Status;
00425    newSP.indexForLabel = indexForLabel;
00426    newSP.labelForIndex = labelForIndex;
00427 
00428    oldgood = ngood;
00429    ngood = ilast = 0;
00430    for(i=0; i<spdvector.size(); i++) {             // loop over all data
00431       n = spdvector[i].ndt;
00432       tt = time(i);
00433       if(n < N) {                                     // keep in this SatPass
00434          if(spdvector[i].flag != BAD) ngood++;
00435          ilast = i;
00436       }
00437       else {                                          // copy out data into new SP
00438          if(n == N) {
00439             newSP.ngood = oldgood-ngood;
00440             newSP.firstTime = newSP.lastTime = tt;
00441          }
00442          j = newSP.countForTime(tt);
00443          spdvector[i].ndt = j;
00444          spdvector[i].toffset = tt - newSP.firstTime - j*dt;
00445          newSP.spdvector.push_back(spdvector[i]);
00446       }
00447    }
00448 
00449    // now trim this SatPass
00450    spdvector.resize(ilast+1);
00451    lastTime = time(ilast);
00452 
00453    return true;
00454 }
00455 catch(Exception& e) { GPSTK_RETHROW(e); }
00456 }
00457 
00458 void SatPass::decimate(const int N, CommonTime refTime) throw(Exception)
00459 {
00460 try {
00461    if(N <= 1) return;
00462    if(spdvector.size() < N) { dt = N*dt; return; }
00463    if(refTime == CommonTime::BEGINNING_OF_TIME) refTime = firstTime;
00464 
00465    // find new firstTime = time(nstart)
00466    int i,j,nstart=int(0.5+(firstTime-refTime)/dt);
00467    nstart = nstart % N;
00468    while(nstart < 0) nstart += N;
00469    if(nstart > 0) nstart = N-nstart;
00470 
00471    // decimate
00472    ngood = 0;
00473    CommonTime newfirstTime, tt;
00474    for(j=0,i=0; i<spdvector.size(); i++) {
00475       if(spdvector[i].ndt % N != nstart) continue;
00476       lastTime = time(i);
00477       if(j==0) {
00478          newfirstTime = time(i);
00479          spdvector[i].toffset = 0.0;
00480          spdvector[i].ndt = 0;
00481       }
00482       else {
00483          tt = time(i);
00484          spdvector[i].ndt = int(0.5+(tt-newfirstTime)/(N*dt));
00485          spdvector[i].toffset = tt - newfirstTime - spdvector[i].ndt * N * dt;
00486       }
00487       spdvector[j] = spdvector[i];
00488       if(spdvector[j].flag != BAD) ngood++;
00489       j++;
00490    }
00491 
00492    dt = N*dt;
00493    firstTime = newfirstTime;
00494    spdvector.resize(j); // trim
00495 }
00496 catch(Exception& e) { GPSTK_RETHROW(e); }
00497 }
00498 
00499 // dump all the data in the pass, one line per timetag;
00500 // put message msg at beginning of each line.
00501 void SatPass::dump(ostream& os, string msg1, string msg2) throw()
00502 {
00503    int i,j,last;
00504    CommonTime tt;
00505    os << '#' << msg1 << " " << *this << " " << msg2 << endl;
00506    os << '#' << msg1 << "  n Sat cnt flg     time      ";
00507    for(j=0; j<indexForLabel.size(); j++)
00508       os << "            " << labelForIndex[j] << " L S";
00509    os << " gap(pts)";
00510    os << endl;
00511 
00512    for(i=0; i<spdvector.size(); i++) {
00513       tt = time(i);
00514       os << msg1
00515          << " " << setw(3) << i
00516          << " " << sat
00517          << " " << setw(3) << spdvector[i].ndt
00518          << " " << setw(2) << spdvector[i].flag
00519          << " " << printTime(tt,SatPass::outFormat)
00520          << fixed << setprecision(6)
00521          << " " << setw(9) << spdvector[i].toffset
00522          << setprecision(3);
00523       for(j=0; j<indexForLabel.size(); j++)
00524          os << " " << setw(13) << spdvector[i].data[j]
00525             << " " << spdvector[i].lli[j]
00526             << " " << spdvector[i].ssi[j];
00527       if(i==0) last = spdvector[i].ndt;
00528       if(spdvector[i].ndt - last > 1) os << " " << spdvector[i].ndt-last;
00529       last = spdvector[i].ndt;
00530       os << endl;
00531    }
00532 }
00533 
00534 // output SatPass to ostream
00535 ostream& operator<<(ostream& os, SatPass& sp )
00536 {
00537    os << setw(4) << sp.spdvector.size()
00538       << " " << sp.sat
00539       << " " << setw(4) << sp.ngood
00540       << " " << setw(2) << sp.Status
00541       << " " << printTime(sp.firstTime,SatPass::outFormat)
00542       << " " << printTime(sp.lastTime,SatPass::outFormat)
00543       << " " << fixed << setprecision(1) << sp.dt;
00544    for(int i=0; i<sp.labelForIndex.size(); i++) os << " " << sp.labelForIndex[i];
00545 
00546    return os;
00547 }
00548 
00549 // ---------------------------- private SatPassData functions --------------------
00550 // add data to the arrays at timetag tt (private)
00551 // return >=0 ok (index of added data), -1 gap, -2 timetag out of order
00552 int SatPass::push_back(const CommonTime tt, SatPassData& spd) throw()
00553 {
00554    unsigned int n;
00555       // if this is the first point, save first time
00556    if(spdvector.size() == 0) {
00557       firstTime = lastTime = tt;
00558       n = 0;
00559    }
00560    else {
00561       if(tt - lastTime < 1.e-8) return -2;
00562          // compute count for this point - prev line means n is >= 0
00563       n = countForTime(tt);
00564          // test size of gap
00565       if( (n - spdvector[spdvector.size()-1].ndt) * dt > maxGap)
00566          return -1;
00567       lastTime = tt;
00568    }
00569 
00570       // add it
00571    //spd.flag = 1;
00572    ngood++;  // ngood is useless unless it's changed whenever any flag is...
00573    spd.ndt = n;
00574    spd.toffset = tt - firstTime - n*dt;
00575    spdvector.push_back(spd);
00576    return (spdvector.size()-1);
00577 }
00578 
00579 // get one element of the data array of this SatPass (private)
00580 struct SatPass::SatPassData SatPass::getData(unsigned int i) const
00581    throw(Exception)
00582 {
00583    if(i >= spdvector.size()) {         // TD ?? keep this - its private
00584       Exception e("invalid in getData() " + asString(i));
00585       GPSTK_THROW(e);
00586    }
00587    return spdvector[i];
00588 }
00589 
00590 // -------------------------------------------------------------------------------
00591 // ---------------------------- iterate over a SatPass list ----------------------
00592 // only constructor
00593 SatPassIterator::SatPassIterator(vector<SatPass>& splist)
00594    throw(Exception) : SPList(splist)
00595 {
00596    if(SPList.size() == 0) {
00597       Exception e("Empty list");
00598       GPSTK_THROW(e);
00599    }
00600 
00601    // ensure time order
00602    sort(SPList);
00603 
00604    int i,j;
00605    vector<string> otlist;
00606 
00607    // copy the data from the first SatPass in the list, for comparison with the rest
00608    DT = SPList[0].dt;
00609    FirstTime = SPList[0].firstTime;
00610    LastTime = SPList[0].lastTime;
00611    // copy the list of obs types, and check that each is registered
00612    for(i=0; i<SPList[0].labelForIndex.size(); i++) {
00613       otlist.push_back(SPList[0].labelForIndex[i]);
00614       if(RinexObsHeader::convertObsType(SPList[0].labelForIndex[i])
00615             == RinexObsHeader::UN) {
00616          Exception e("Unregistered observation type : " + SPList[0].labelForIndex[i]);
00617          GPSTK_THROW(e);
00618       }
00619    }
00620 
00621    // loop over the list
00622    for(i=0; i<SPList.size(); i++) {
00623       // check for consistency of dt
00624       if(SPList[i].dt != DT) {
00625          Exception e("Inconsistent time intervals: " + asString(SPList[i].dt)
00626             + " != " + asString(DT));
00627          GPSTK_THROW(e);
00628       }
00629       // check for consistency of obs types
00630       for(j=0; j<otlist.size(); j++) {
00631          if(SPList[i].indexForLabel.find(otlist[j]) ==
00632             SPList[i].indexForLabel.end()) {
00633                Exception e("Inconsistent observation types");
00634                GPSTK_THROW(e);
00635          }
00636       }
00637       // TD check for increasing time order?
00638 
00639       // find the earliest and latest time
00640       if(SPList[i].firstTime < FirstTime) FirstTime = SPList[i].firstTime;
00641       if(SPList[i].lastTime > LastTime) LastTime = SPList[i].lastTime;
00642 
00643    }  // end loop over the list
00644 
00645    reset();
00646 }
00647 
00648 // return 1 for success, 0 at end of data
00649 // Access (all of) the data for the next epoch. As long as this function
00650 // returns zero, there is more data to be accessed. Ignore passes with
00651 // Status less than zero.
00652 // @param indexMap  map<unsigned int, unsigned int> defined so that all the
00653 //                  data in the current iteration is found at
00654 //                  SatPassList[i].data(j) where indexMap[i] = j.
00655 // @throw if time tags are out of order.
00656 int SatPassIterator::next(map<unsigned int, unsigned int>& indexMap) throw(Exception)
00657 {
00658    int i,j,k,numsvs;
00659    GSatID sat;
00660 
00661    numsvs = 0;
00662    indexMap.clear();
00663    nextIndexMap.clear();
00664 
00665    while(numsvs == 0) {
00666       if(listIndex.size() == 0) return 0;
00667 
00668       // loop over active SatPass's
00669       map<GSatID,int>::iterator kt = listIndex.begin();
00670 
00671       kt = listIndex.begin();
00672       while(kt != listIndex.end()) {
00673          sat = kt->first;
00674          i = kt->second;
00675          j = dataIndex[sat];
00676 
00677          if(SPList[i].Status < 0) continue;     // should never happen
00678 
00679          if(countOffset[sat] + SPList[i].spdvector[j].ndt == currentN) {
00680             // found active sat at this count - add to map
00681             nextIndexMap[i] = j;
00682             numsvs++;
00683 
00684             // increment data index
00685             j++;
00686             if(j == SPList[i].spdvector.size()) {     // this pass is done
00687                indexStatus[i] = 1;
00688 
00689                // find the next pass for this sat
00690                for(k=i+1; k<SPList.size(); k++) {
00691                   if(SPList[k].Status < 0)      // bad pass
00692                      continue;
00693                   if(SPList[k].sat != sat)      // wrong sat
00694                      continue;
00695                   if(indexStatus[k] > 0)        // already done
00696                      continue;
00697 
00698                   // take this one
00699                   indexStatus[k] = 0;
00700                   i = listIndex[sat] = k;
00701                   dataIndex[sat] = 0;
00702                   countOffset[sat]
00703                      = int((SPList[i].firstTime - FirstTime)/DT + 0.5);
00704                   break;
00705                }
00706             }
00707             else {
00708                dataIndex[sat] = j;
00709             }
00710 
00711          }  // end if found active sat at this count
00712 
00713          // increment the iterator
00714          if(indexStatus[i] > 0) {                // a new one was not found
00715             listIndex.erase(kt++);  // erasing a map - do exactly this and no more
00716          }
00717          else kt++;
00718 
00719       }  // end while loop over active SatPass's
00720 
00721       currentN++;
00722 
00723    }  // end while robs.numSvs==0
00724 
00725    indexMap = nextIndexMap;
00726 
00727    return 1;
00728 }
00729 
00730 // return 1 for success, 0 at end of data
00731 int SatPassIterator::next(RinexObsData& robs) throw(Exception)
00732 {
00733    if(listIndex.size() == 0) return 0;
00734 
00735    map<unsigned int, unsigned int> indexMap;
00736    int iret = next(indexMap);
00737    if(iret == 0) return iret;
00738 
00739    robs.obs.clear();
00740    robs.epochFlag = 0;
00741    robs.time = FirstTime + (currentN-1) * DT;      // careful
00742    robs.clockOffset = 0.0;
00743    robs.numSvs = 0;
00744 
00745    // loop over the map
00746    map<unsigned int, unsigned int>::const_iterator kt;
00747    for(kt = indexMap.begin(); kt != indexMap.end(); kt++) {
00748       int i = kt->first;
00749       int j = kt->second;
00750       GSatID sat = SPList[i].getSat();
00751 
00752       bool found = false;
00753       bool flag = (SPList[i].spdvector[j].flag != SatPass::BAD);
00754       for(int k=0; k<SPList[i].labelForIndex.size(); k++) {
00755          RinexObsHeader::RinexObsType ot;
00756          ot = RinexObsHeader::convertObsType(SPList[i].labelForIndex[k]);
00757          if(ot == RinexObsHeader::UN) {
00758          }
00759          else {
00760             found = true;
00761             robs.obs[sat][ot].data = flag ? SPList[i].spdvector[j].data[k] : 0.;
00762             robs.obs[sat][ot].lli  = flag ? SPList[i].spdvector[j].lli[k] : 0;
00763             robs.obs[sat][ot].ssi  = flag ? SPList[i].spdvector[j].ssi[k] : 0;
00764          }
00765       }
00766       if(found) robs.numSvs++;
00767    }
00768 
00769    return 1;
00770 }
00771 
00772 // restart the iteration
00773 void SatPassIterator::reset(void) throw()
00774 {
00775    // clear out the old
00776    currentN = 0;
00777    listIndex.clear();
00778    dataIndex.clear();
00779    countOffset.clear();
00780    indexStatus = vector<int>(SPList.size(),-1);
00781 
00782    // loop over the list
00783    for(int i=0; i<SPList.size(); i++) {
00784       // ignore passes with negative Status
00785       if(SPList[i].Status < 0) continue;
00786 
00787       // (re)build the maps
00788       if(listIndex.find(SPList[i].sat) == listIndex.end()) {
00789          indexStatus[i] = 0;
00790          listIndex[SPList[i].sat] = i;
00791          dataIndex[SPList[i].sat] = 0;
00792          countOffset[SPList[i].sat]
00793             = int((SPList[i].firstTime - FirstTime)/DT + 0.5);
00794       }
00795       else {
00796          indexStatus[i] = -1;
00797       }
00798    }  // end loop over the list
00799 }
00800 
00801 // -------------------------------------------------------------------------------
00802 // ---------------------------- sort, read and write SatPass lists ------------
00803 // NB uses SatPass::operator<()
00804 void sort(vector<SatPass>& SPList) throw()
00805 {
00806    std::sort(SPList.begin(), SPList.end());
00807 }
00808 
00809 int SatPassFromRinexFiles(vector<string>& filenames,
00810                           vector<string>& obstypes,
00811                           double dt,
00812                           vector<SatPass>& SPList,
00813                           CommonTime beginTime,
00814                           CommonTime endTime)
00815    throw(Exception)
00816 {
00817    if(filenames.size() == 0) return -1;
00818 
00819    // sort the file names on the begin time in the header
00820    if(filenames.size() > 1) sortRinexObsFiles(filenames);
00821 
00822    int i,j,nfiles = 0;
00823    vector<double> data(obstypes.size(),0.0);
00824    vector<unsigned short> ssi(obstypes.size(),0);
00825    vector<unsigned short> lli(obstypes.size(),0);
00826    map<GSatID,int> indexForSat;
00827    map<GSatID,int>::const_iterator satit;
00828    RinexObsHeader header;
00829    RinexObsData obsdata;
00830 
00831    // sort existing list on begin time
00832    sort(SPList);
00833 
00834    // fill the index array using SatPass's already there
00835    // assumes SPList is in time order - later ones overwrite earlier
00836    for(i=0; i<SPList.size(); i++)
00837       indexForSat[SPList[i].sat] = i;
00838 
00839    for(int nfile=0; nfile<filenames.size(); nfile++) {
00840       string filename = filenames[nfile];
00841 
00842       // does the file exist?
00843       RinexObsStream RinFile(filename.c_str());
00844       if(filename.empty() || !RinFile) {
00845          //cerr << "Error: input file " << filename << " does not exist.\n";
00846          continue;
00847       }
00848       RinFile.exceptions(fstream::failbit);
00849 
00850       // is it a Rinex Obs file? ... read the header
00851       try { RinFile >> header; }
00852       catch(Exception& e) {
00853          //cerr << "Error: input file " << filename << " is not a Rinex obs file\n";
00854          continue;
00855       }
00856 
00857       // to return the number of files read
00858       nfiles++;
00859 
00860       // check that obs types are in header - first file only
00861       if(obstypes.size() == 0) {
00862          for(j=0; j<header.obsTypeList.size(); j++) {
00863             obstypes.push_back(RinexObsHeader::convertObsType(header.obsTypeList[j]));
00864          }
00865          data = vector<double>(obstypes.size(),0.0);
00866          ssi = vector<unsigned short>(obstypes.size(),0);
00867          lli = vector<unsigned short>(obstypes.size(),0);
00868       }
00869 
00870       // loop over epochs in the file
00871       while(RinFile >> obsdata) {
00872          RinexObsData::RinexSatMap::const_iterator it;
00873          RinexObsData::RinexObsTypeMap::const_iterator jt;
00874 
00875          // test time limits
00876          if(obsdata.time < beginTime) continue;
00877          if(obsdata.time > endTime) break;
00878 
00879          // skip auxiliary header, etc
00880          if(obsdata.epochFlag != 0 && obsdata.epochFlag != 1) continue;
00881 
00882          // loop over satellites
00883          for(it=obsdata.obs.begin(); it != obsdata.obs.end(); ++it) {
00884             GSatID sat = it->first;
00885 
00886             // loop over obs
00887             for(j=0; j<obstypes.size(); j++) {
00888                if((jt=it->second.find(RinexObsHeader::convertObsType(obstypes[j])))
00889                      == it->second.end()) {
00890                   data[j] = 0.0;
00891                   lli[j] = ssi[j] = 0;
00892                }
00893                else {
00894                   data[j] = jt->second.data;
00895                   lli[j] = jt->second.lli;
00896                   ssi[j] = jt->second.ssi;
00897                }
00898             }  // end loop over obs
00899 
00900             // find the current SatPass for this sat
00901             satit = indexForSat.find(sat);
00902 
00903             // if there is not one, create one
00904             if(satit == indexForSat.end()) {
00905                SatPass newSP(sat,dt,obstypes);
00906                SPList.push_back(newSP);
00907                indexForSat[sat] = SPList.size()-1;
00908                satit = indexForSat.find(sat);
00909             }
00910 
00911             // add the data to the SatPass
00912             do {
00913                i = SPList[satit->second].addData(obsdata.time,obstypes,data,lli,ssi);
00914                if(i < 0) {             // failure
00915                   if(i == -1) {        // gap
00916                      SatPass newSP(sat,dt,obstypes);
00917                      SPList.push_back(newSP);
00918                      indexForSat[sat] = SPList.size()-1;
00919                      satit = indexForSat.find(sat);
00920                   }
00921                   else if(i == -2) {   // time tag out of order
00922                      Exception e("Time tags out of order in the RINEX file "
00923                            + filename);
00924                          //+ " at time " + obsdata.time.printf("%4F %10.3g"));
00925                      GPSTK_THROW(e);
00926                   }
00927                   //else if(i == -3) {   // sat not found (RinexObsData form only)
00928                   //}
00929                }
00930             } while(i < 0);
00931 
00932          } // end loop over satellites
00933 
00934       } // end loop over obs data in file
00935 
00936       RinFile.close();
00937    }
00938 
00939    return nfiles;
00940 }
00941 
00942 int SatPassToRinexFile(string filename,
00943                        RinexObsHeader& header,
00944                        vector<SatPass>& SPList) throw(Exception)
00945 {
00946    try {
00947       // create iterator
00948       SatPassIterator spit(SPList);
00949 
00950       // open file
00951       RinexObsStream rstrm(filename.c_str(), ios::out);
00952       if(!rstrm) return -1;
00953       rstrm.exceptions(fstream::failbit);
00954 
00955       // put obs types, first time and interval in header
00956       header.obsTypeList.clear();
00957       for(int i=0; i<SPList[0].labelForIndex.size(); i++)
00958          header.obsTypeList.push_back(
00959             RinexObsHeader::convertObsType(SPList[0].labelForIndex[i]));
00960       header.firstObs = spit.getFirstTime();
00961       header.lastObs = spit.getLastTime();
00962       header.interval = spit.getDT();
00963       header.valid |= RinexObsHeader::firstTimeValid;
00964       header.valid |= RinexObsHeader::lastTimeValid;
00965       header.valid |= RinexObsHeader::intervalValid;
00966 
00967       rstrm << header;
00968 
00969       RinexObsData robs;
00970       RinexObsData::RinexSatMap::const_iterator it;
00971       RinexObsData::RinexObsTypeMap::const_iterator jt;
00972 
00973       while(spit.next(robs)) {
00974          if(robs.epochFlag != 0 || robs.obs.size() == 0) {
00975             continue;
00976          }
00977 
00978          rstrm << robs;
00979       }
00980 
00981       rstrm.close();
00982    }
00983    catch(Exception& e) { GPSTK_RETHROW(e); }
00984 
00985    return 0;
00986 }
00987 
00988 }  // end namespace gpstk

Generated on Tue May 21 03:31:14 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1