ObsID.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: ObsID.cpp 2010 2009-07-03 13:19:29Z ocibu $"
00002 
00008 //============================================================================
00009 //
00010 //  This file is part of GPSTk, the GPS Toolkit.
00011 //
00012 //  The GPSTk is free software; you can redistribute it and/or modify
00013 //  it under the terms of the GNU Lesser General Public License as published
00014 //  by the Free Software Foundation; either version 2.1 of the License, or
00015 //  any later version.
00016 //
00017 //  The GPSTk is distributed in the hope that it will be useful,
00018 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //  GNU Lesser General Public License for more details.
00021 //
00022 //  You should have received a copy of the GNU Lesser General Public
00023 //  License along with GPSTk; if not, write to the Free Software Foundation,
00024 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 //
00026 //  Copyright 2004, The University of Texas at Austin
00027 //
00028 //============================================================================
00029 
00030 //============================================================================
00031 //
00032 //This software developed by Applied Research Laboratories at the University of
00033 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00034 //Department of Defense. The U.S. Government retains all rights to use,
00035 //duplicate, distribute, disclose, or release this software. 
00036 //
00037 //Pursuant to DoD Directive 523024 
00038 //
00039 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00040 //                           release, distribution is unlimited.
00041 //
00042 //=============================================================================
00043 
00044 
00045 
00046 #include "ObsID.hpp"
00047 
00048 
00049 namespace gpstk
00050 {
00051    std::map< ObsID::TrackingCode,    std::string > ObsID::tcDesc;
00052    std::map< ObsID::CarrierBand,     std::string > ObsID::cbDesc;
00053    std::map< ObsID::ObservationType, std::string > ObsID::otDesc;
00054    std::map< char, ObsID::ObservationType> ObsID::rinex2ot;
00055    std::map< char, ObsID::CarrierBand> ObsID::rinex2cb;
00056    std::map< char, ObsID::TrackingCode> ObsID::rinex2tc;
00057    std::map< ObsID::ObservationType, char > ObsID::ot2Rinex;
00058    std::map< ObsID::CarrierBand, char > ObsID::cb2Rinex;
00059    std::map< ObsID::TrackingCode, char> ObsID::tc2Rinex;
00060 
00061 
00062    ObsID::Initializer singleton;
00063 
00064    ObsID::Initializer::Initializer()
00065    {
00066       otDesc[otUnknown]   = "UnknownType";
00067       otDesc[otAny]       = "AnyType";
00068       otDesc[otRange]     = "range";
00069       otDesc[otPhase]     = "phase";
00070       otDesc[otDoppler]   = "doppler";
00071       otDesc[otSNR]       = "snr";
00072       otDesc[otChannel]   = "channel";
00073       otDesc[otIono]      = "iono";
00074       otDesc[otSSI]       = "ssi";
00075       otDesc[otLLI]       = "lli";
00076       otDesc[otTrackLen]  = "tlen";
00077       otDesc[otUndefined] = "undefined";
00078 
00079       cbDesc[cbUnknown]   = "UnknownBand";
00080       cbDesc[cbAny]       = "AnyBand";
00081       cbDesc[cbZero]      = "";
00082       cbDesc[cbL1]        = "L1";
00083       cbDesc[cbL2]        = "L2";
00084       cbDesc[cbL5]        = "L5";
00085       cbDesc[cbL1L2]      = "L1+L2";
00086       cbDesc[cbG1]        = "G1";
00087       cbDesc[cbG2]        = "G2";
00088       cbDesc[cbE5b]       = "E5b";
00089       cbDesc[cbE5ab]      = "L5a+b";
00090       cbDesc[cbE6]        = "E6";
00091       cbDesc[cbUndefined] = "undefined";
00092 
00093       tcDesc[tcUnknown] = "UnknownCode";
00094       tcDesc[tcAny]     = "AnyCode";
00095       tcDesc[tcCA]      = "C/A";
00096       tcDesc[tcP]       = "P";
00097       tcDesc[tcY]       = "Y";
00098       tcDesc[tcW]       = "W";
00099       tcDesc[tcN]       = "N";
00100       tcDesc[tcD]       = "D";
00101       tcDesc[tcM]       = "M";
00102       tcDesc[tcC2M]     = "C2M";
00103       tcDesc[tcC2L]     = "C2L";
00104       tcDesc[tcC2LM]    = "C2L+M";
00105       tcDesc[tcI5]      = "I5";
00106       tcDesc[tcQ5]      = "Q5";
00107       tcDesc[tcIQ5]     = "I+Q5";
00108       tcDesc[tcGCA]     = "C/A";
00109       tcDesc[tcGP]      = "P";
00110       tcDesc[tcA]       = "A";
00111       tcDesc[tcB]       = "B";
00112       tcDesc[tcC]       = "C";
00113       tcDesc[tcBC]      = "B+C";
00114       tcDesc[tcABC]     = "A+B+C";
00115       tcDesc[tcIE5]     = "IE5";
00116       tcDesc[tcQE5]     = "QE5";
00117       tcDesc[tcIQE5]    = "I+QE5";
00118       tcDesc[tcUndefined] = "undefined";
00119 
00120       if (otDesc.size() != (int)otLast)
00121          std::cerr << "Error in otDesc" << std::endl;
00122       if (cbDesc.size() != (int)cbLast)
00123          std::cerr << "Error in cbDesc" << std::endl;
00124       if (tcDesc.size() != (int)tcLast)
00125          std::cerr << "Error in tcDesc" << std::endl;
00126 
00127       // The following definitions really should only describe the items that are
00128       // in the Rinex 3 specification. If an application needs additional ObsID
00129       // types to be able to be translated to/from Rinex3, the additional types
00130       // must be added by the application.
00131       rinex2ot[' '] = otUnknown;
00132       rinex2ot['*'] = otAny;
00133       rinex2ot['C'] = otRange;
00134       rinex2ot['L'] = otPhase;
00135       rinex2ot['D'] = otDoppler;
00136       rinex2ot['S'] = otSNR;
00137       rinex2ot['-'] = otUndefined;
00138 
00139       rinex2cb[' '] = cbUnknown;
00140       rinex2cb['*'] = cbAny;
00141       rinex2cb['1'] = cbL1;
00142       rinex2cb['2'] = cbL2;
00143       rinex2cb['5'] = cbL5;
00144       rinex2cb['6'] = cbE6;
00145       rinex2cb['7'] = cbE5b;
00146       rinex2cb['8'] = cbE5ab;
00147       rinex2cb['-'] = cbUndefined;
00148 
00149       rinex2tc[' '] = tcUnknown;
00150       rinex2tc['*'] = tcAny;
00151       rinex2tc['C'] = tcCA;
00152       rinex2tc['P'] = tcP;  
00153       rinex2tc['W'] = tcW;
00154       rinex2tc['Y'] = tcY;
00155       rinex2tc['M'] = tcM;
00156       rinex2tc['N'] = tcN;
00157       rinex2tc['D'] = tcD;
00158       rinex2tc['S'] = tcC2M;
00159       rinex2tc['L'] = tcC2L;
00160       rinex2tc['X'] = tcC2LM;
00161       rinex2tc['I'] = tcI5;
00162       rinex2tc['Q'] = tcQ5;
00163       rinex2tc['A'] = tcA;
00164       rinex2tc['B'] = tcB;
00165       rinex2tc['Z'] = tcABC;
00166       rinex2tc['-'] = tcUndefined;
00167 
00168       // Since some of the items in the enums don't have corresponding rinex
00169       // definitions, make sure there is an entry for all values
00170       for (int i=otUnknown; i<otLast; i++) ot2Rinex[(ObservationType)i] = ' ';
00171       for (int i=cbUnknown; i<cbLast; i++) cb2Rinex[(CarrierBand)i] = ' ';
00172       for (int i=tcUnknown; i<tcLast; i++) tc2Rinex[(TrackingCode)i] = ' ';
00173 
00174       // Here the above three maps are reversed to speed up the runtime
00175       for (std::map< char, ObservationType>::const_iterator i=rinex2ot.begin();
00176            i != rinex2ot.end(); i++)
00177          ot2Rinex[i->second] = i->first;
00178 
00179       for (std::map< char, CarrierBand>::const_iterator i=rinex2cb.begin();
00180            i != rinex2cb.end(); i++)
00181          cb2Rinex[i->second] = i->first;
00182 
00183       for (std::map< char, TrackingCode>::const_iterator i=rinex2tc.begin();
00184            i != rinex2tc.end(); i++)
00185          tc2Rinex[i->second] = i->first;
00186 
00187       // And add the couple 'special' cases
00188       tc2Rinex[tcC] = 'C';
00189       tc2Rinex[tcIE5] = 'I';
00190       tc2Rinex[tcQE5] = 'Q';
00191       tc2Rinex[tcIQE5] = 'X';
00192       tc2Rinex[tcIQ5] = 'X';
00193       tc2Rinex[tcBC] = 'X';
00194    }
00195 
00196 
00197    // Construct this object from the rinex3 specifier
00198    ObsID::ObsID(const std::string& rinexID) throw(InvalidParameter)
00199    {
00200       int i = rinexID.length() - 3;
00201       if ( i < 0 || i > 1)
00202       {
00203          InvalidParameter e("identifier must be 3 or 4 characters long");
00204          GPSTK_THROW(e);
00205       }
00206 
00207       char sys = i ? rinexID[0] : 'G';
00208       char ot = rinexID[i];
00209       char cb = rinexID[i+1];
00210       char tc = rinexID[i+2];
00211       
00212       if (!rinex2ot.count(ot) || !rinex2cb.count(cb) || !rinex2tc.count(tc))
00213          idCreator(rinexID.substr(i,3));
00214 
00215       type = rinex2ot[ ot ];
00216       band = rinex2cb[ cb ];
00217       code = rinex2tc[ tc ];
00218 
00221       if (sys == 'G') // GPS
00222       {
00223          if (tc=='X' && band==cbL5)
00224             code = tcIQ5;
00225       }
00226       if (sys == 'E') // Galileo
00227       {
00228          switch (code)
00229          {
00230             case tcCA: code = tcC; break;
00231             case tcI5: code = tcIE5; break;
00232             case tcQ5: code = tcQE5; break;
00233          }
00234          if (tc == 'X')
00235          {
00236             if (band == cbL1 || band == cbE6)
00237                code = tcBC;
00238             else if (band == cbL5 || band == cbE5b || band == cbE5ab)
00239                code = tcIQE5;
00240          }
00241       }
00242       else if (sys == 'R') // Glonass
00243       {
00244          switch (code)
00245          {
00246             case tcCA: code = tcGCA; break;
00247             case tcP: code = tcGP; break;
00248          }
00249       } // end of checking which GNSS system this obs is for
00250    }
00251 
00252 
00253    // Convenience output method
00254    std::ostream& ObsID::dump(std::ostream& s) const
00255    {
00256       s << ObsID::cbDesc[band] << " "
00257         << ObsID::tcDesc[code] << " "
00258         << ObsID::otDesc[type];
00259       return s;
00260    } // ObsID::dump()
00261 
00262 
00263 
00264    // Represent this object using the Rinex3 notation
00265    std::string ObsID::asRinex3ID() const
00266    {
00267       char buff[4];
00268 
00269       buff[0] = ot2Rinex[type];
00270       buff[1] = cb2Rinex[band];
00271       buff[2] = tc2Rinex[code];
00272       buff[3] = 0;
00273       return std::string(buff);
00274    }
00275 
00276 
00277    // This is used to register a new ObsID & Rinex 3 identifier.  The syntax for the
00278    // Rinex 3 identifier is the same as for the ObsID constructor. 
00279    // If there are spaces in the provided identifier, they are ignored
00280    ObsID ObsID::newID(const std::string& rinexID, const std::string& desc)
00281       throw(InvalidParameter)
00282    {
00283       if (rinex2ot.count(rinexID[0]) && 
00284           rinex2cb.count(rinexID[1]) && 
00285           rinex2tc.count(rinexID[2]))
00286           GPSTK_THROW(InvalidParameter("Identifier " + rinexID + " already defined."));
00287 
00288       return idCreator(rinexID, desc);
00289    }
00290 
00291 
00292    ObsID ObsID::idCreator(const std::string& rinexID, const std::string& desc)
00293    {
00294       char ot = rinexID[0];
00295       ObservationType type;
00296       if (!rinex2ot.count(ot))
00297       {
00298          type = (ObservationType)otDesc.size();
00299          otDesc[type] = desc;
00300          rinex2ot[ot] = type;
00301          ot2Rinex[type] = ot;
00302       }
00303       else
00304          type = rinex2ot[ot];
00305 
00306       char cb = rinexID[1];
00307       CarrierBand band;
00308       if (!rinex2cb.count(cb))
00309       {
00310          band = (CarrierBand)cbDesc.size();
00311          cbDesc[band] = desc;
00312          rinex2cb[cb] = band;
00313          cb2Rinex[band] = cb;
00314       }
00315       else
00316          band = rinex2cb[cb];
00317 
00318       char tc = rinexID[2];
00319       TrackingCode code;
00320       if (!rinex2tc.count(tc))
00321       {
00322          code = (TrackingCode) tcDesc.size();
00323          tcDesc[code] = desc;
00324          rinex2tc[tc] = code;
00325          tc2Rinex[code] = tc;
00326       }
00327       else
00328          code = rinex2tc[tc];
00329       
00330       return ObsID(type, band, code);
00331    }
00332 
00333 
00334    // Equality requires all fields to be the same unless the field is unknown
00335    bool ObsID::operator==(const ObsID& right) const
00336    {
00337       bool ot = type == otAny || right.type == otAny || type == right.type;
00338       bool cb = band == cbAny || right.band == cbAny || band == right.band;
00339       bool tc = code == tcAny || right.code == tcAny || code == right.code;
00340       return ot && cb && tc;
00341    }
00342 
00343 
00344    // This ordering is somewhat arbitrary but is required to be able
00345    // to use an ObsID as an index to a std::map. If an application needs
00346    // some other ordering, inherit and override this function.
00347    bool ObsID::operator<(const ObsID& right) const
00348    {
00349       if (band == right.band)
00350          if (code == right.code)
00351             return type < right.type;
00352          else
00353             return code < right.code;
00354       else
00355          return band < right.band;
00356 
00357       // This should never be reached...
00358       return false;
00359    }
00360 
00361 
00362    namespace StringUtils
00363    {
00364       // convert this object to a string representation
00365       std::string asString(const ObsID& p)
00366       {
00367          std::ostringstream oss;
00368          p.dump(oss);
00369          return oss.str();
00370       }
00371 
00372       // convert this object to a string representation
00373       std::string asRinex3ID(const ObsID& p)
00374       {
00375          return p.asRinex3ID();
00376       }
00377    }
00378 
00379 
00380    // stream output for ObsID
00381    std::ostream& operator<<(std::ostream& s, const ObsID& p)
00382    {
00383       p.dump(s);
00384       return s;
00385    }
00386 
00387 }

Generated on Tue May 22 03:31:00 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1