OneFreqCSDetector.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: OneFreqCSDetector.cpp 1325 2008-07-29 14:33:43Z architest $"
00002 
00009 //============================================================================
00010 //
00011 //  This file is part of GPSTk, the GPS Toolkit.
00012 //
00013 //  The GPSTk is free software; you can redistribute it and/or modify
00014 //  it under the terms of the GNU Lesser General Public License as published
00015 //  by the Free Software Foundation; either version 2.1 of the License, or
00016 //  any later version.
00017 //
00018 //  The GPSTk is distributed in the hope that it will be useful,
00019 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021 //  GNU Lesser General Public License for more details.
00022 //
00023 //  You should have received a copy of the GNU Lesser General Public
00024 //  License along with GPSTk; if not, write to the Free Software Foundation,
00025 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026 //
00027 //  Dagoberto Salazar - gAGE ( http://www.gage.es ). 2007, 2008
00028 //
00029 //============================================================================
00030 
00031 
00032 #include "OneFreqCSDetector.hpp"
00033 
00034 
00035 namespace gpstk
00036 {
00037 
00038       // Index initially assigned to this class
00039    int OneFreqCSDetector::classIndex = 3000000;
00040 
00041 
00042       // Returns an index identifying this object.
00043    int OneFreqCSDetector::getIndex() const
00044    { return index; }
00045 
00046 
00047       // Returns a string identifying this object.
00048    std::string OneFreqCSDetector::getClassName() const
00049    { return "OneFreqCSDetector"; }
00050 
00051 
00052       /* Common constructor
00053        *
00054        * @param codeT         Type of code to be used.
00055        * @param dtMax         Maximum interval of time allowed between two
00056        *                      successive epochs.
00057        * @param mwSize        Maximum  size of filter window, in samples.
00058        * @param mnSigmas      Maximum deviation allowed before declaring
00059        *                      cycle slip (in number of sigmas).
00060        * @param dbSigma       Default value assigned to sigma when filter
00061        *                      starts.
00062        */
00063    OneFreqCSDetector::OneFreqCSDetector( const TypeID& codeT,
00064                                          const double& dtMax,
00065                                          const int& mwSize,
00066                                          const double& mnSigmas,
00067                                          const double& dbSigma )
00068       : codeType(codeT), deltaTMax(dtMax), maxNumSigmas(mnSigmas),
00069         defaultBiasSigma(dbSigma)
00070    {
00071 
00072          // Don't allow window sizes less than 1
00073       if (mwSize >= 1)
00074       {
00075          maxWindowSize = mwSize;
00076       }
00077       else
00078       {
00079          maxWindowSize = 60;
00080       }
00081 
00082       switch ( codeT.type )
00083       {
00084          case TypeID::C1:
00085             phaseType   = TypeID::L1;
00086             lliType     = TypeID::LLI1;
00087             resultType  = TypeID::CSL1;
00088             break;
00089          case TypeID::C2:
00090             phaseType   = TypeID::L2;
00091             lliType     = TypeID::LLI2;
00092             resultType  = TypeID::CSL2;
00093             break;
00094          case TypeID::C5:
00095             phaseType   = TypeID::L5;
00096             lliType     = TypeID::LLI5;
00097             resultType  = TypeID::CSL5;
00098             break;
00099          case TypeID::C6:
00100             phaseType   = TypeID::L6;
00101             lliType     = TypeID::LLI6;
00102             resultType  = TypeID::CSL6;
00103             break;
00104          case TypeID::C7:
00105             phaseType   = TypeID::L7;
00106             lliType     = TypeID::LLI7;
00107             resultType  = TypeID::CSL7;
00108             break;
00109          case TypeID::C8:
00110             phaseType   = TypeID::L8;
00111             lliType     = TypeID::LLI8;
00112             resultType  = TypeID::CSL8;
00113             break;
00114          default:
00115             phaseType   = TypeID::L1;
00116             lliType     = TypeID::LLI1;
00117             resultType  = TypeID::CSL1;
00118       };
00119 
00120       setIndex();
00121 
00122    }  // End of constructor 'OneFreqCSDetector::OneFreqCSDetector()'
00123 
00124 
00125 
00126       /* Returns a satTypeValueMap object, adding the new data generated
00127        *  when calling this object.
00128        *
00129        * @param epoch     Time of observations.
00130        * @param gData     Data object holding the data.
00131        * @param epochflag Epoch flag.
00132        */
00133    satTypeValueMap& OneFreqCSDetector::Process( const DayTime& epoch,
00134                                                 satTypeValueMap& gData,
00135                                                 const short& epochflag )
00136       throw(ProcessingException)
00137    {
00138 
00139       try
00140       {
00141 
00142          double value1(0.0);
00143          double value2(0.0);
00144 
00145          SatIDSet satRejectedSet;
00146 
00147             // Loop through all the satellites
00148          satTypeValueMap::iterator it;
00149          for (it = gData.begin(); it != gData.end(); ++it) 
00150          {
00151             try
00152             {
00153                   // Try to extract the values
00154                value1 = (*it).second(codeType);
00155                value2 = (*it).second(phaseType);
00156             }
00157             catch(...)
00158             {
00159                   // If some value is missing, then schedule this satellite
00160                   // for removal
00161                satRejectedSet.insert( (*it).first );
00162                continue;
00163             }
00164 
00165                // If everything is OK, then get the new value inside
00166                // the structure.
00167                // This way of doing it allows concatenation of several
00168                // different cycle slip detectors
00169             (*it).second[resultType] += getDetection( epoch,
00170                                                       (*it).first,
00171                                                       (*it).second,
00172                                                       epochflag,
00173                                                       value1,
00174                                                       value2 );
00175 
00176             if ( (*it).second[resultType] > 1.0 )
00177             {
00178                (*it).second[resultType] = 1.0;
00179             }
00180 
00181          }
00182 
00183             // Remove satellites with missing data
00184          gData.removeSatID(satRejectedSet);
00185 
00186          return gData;
00187 
00188       }
00189       catch(Exception& u)
00190       {
00191             // Throw an exception if something unexpected happens
00192          ProcessingException e( getClassName() + ":"
00193                                 + StringUtils::asString( getIndex() ) + ":"
00194                                 + u.what() );
00195 
00196          GPSTK_THROW(e);
00197 
00198       }
00199 
00200    }  // End of method 'OneFreqCSDetector::Process()'
00201 
00202 
00203 
00204       /* Method to set the maximum size of filter window, in samples.
00205        *
00206        * @param maxSize       Maximum size of filter window, in samples.
00207        */
00208    OneFreqCSDetector& OneFreqCSDetector::setMaxWindowSize(const int& maxSize)
00209    {
00210 
00211          // Don't allow window sizes less than 1
00212       if (maxSize >= 1)
00213       {
00214          maxWindowSize = maxSize;
00215       }
00216       else
00217       {
00218          maxWindowSize = 60;
00219       }
00220 
00221       return (*this);
00222 
00223    }  // End of method 'OneFreqCSDetector::setMaxWindowSize()'
00224 
00225 
00226       /* Returns a gnnsRinex object, adding the new data generated when
00227        *  calling this object.
00228        *
00229        * @param gData    Data object holding the data.
00230        */
00231    gnssRinex& OneFreqCSDetector::Process(gnssRinex& gData)
00232       throw(ProcessingException)
00233    {
00234 
00235       try
00236       {
00237 
00238          Process(gData.header.epoch, gData.body, gData.header.epochFlag);
00239 
00240          return gData;
00241 
00242       }
00243       catch(Exception& u)
00244       {
00245             // Throw an exception if something unexpected happens
00246          ProcessingException e( getClassName() + ":"
00247                                 + StringUtils::asString( getIndex() ) + ":"
00248                                 + u.what() );
00249 
00250          GPSTK_THROW(e);
00251 
00252       }
00253 
00254    }
00255 
00256 
00257       /* Returns a satTypeValueMap object, adding the new data generated
00258        *  when calling this object.
00259        *
00260        * @param epoch     Time of observations.
00261        * @param sat       SatID.
00262        * @param tvMap     Data structure of TypeID and values.
00263        * @param epochflag Epoch flag.
00264        * @param code      Current code observation value.
00265        * @param phase     Current phase observation value.
00266        */
00267    double OneFreqCSDetector::getDetection( const DayTime& epoch,
00268                                            const SatID& sat,
00269                                            typeValueMap& tvMap,
00270                                            const short& epochflag,
00271                                            const double& code,
00272                                            const double& phase )
00273    {
00274 
00275       bool reportCS(false);
00276       double deltaT(0.0);        // Difference between current and former
00277                                  // epochs, in seconds
00278       double bias(0.0);          // Code-phase bias
00279       double dif2(0.0);          // Difference between biases, squared.
00280       double thr2(0.0);          // Threshold in sigmas, squared.
00281       double deltaBias(0.0);     // Difference between biases
00282       double tempLLI(0.0);
00283 
00284          // Get the difference between current epoch and former epoch,
00285          // in seconds
00286       deltaT = ( epoch.MJDdate() - OneFreqData[sat].previousEpoch.MJDdate() )
00287                * DayTime::SEC_DAY;
00288 
00289          // Store current epoch as former epoch
00290       OneFreqData[sat].previousEpoch = epoch;
00291 
00292       bias = code - phase;       // Current value of code-phase bias
00293 
00294          // Increment window size
00295       ++OneFreqData[sat].windowSize;
00296 
00297          // Check if receiver already declared cycle slip or too much time
00298          // has elapsed
00299          // Note: If tvMap(lliType) doesn't exist, then 0 will be returned
00300          // and that test will pass
00301       if ( (tvMap(lliType)==1.0) ||
00302            (tvMap(lliType)==3.0) ||
00303            (tvMap(lliType)==5.0) ||
00304            (tvMap(lliType)==7.0) )
00305       {
00306          tempLLI = 1.0;
00307       }
00308 
00309       if ( (epochflag==1)        ||
00310            (epochflag==6)        ||
00311            (tempLLI==1.0)        ||
00312            (deltaT > deltaTMax) )
00313       {
00314          OneFreqData[sat].windowSize = 1;
00315       }
00316 
00317       if (OneFreqData[sat].windowSize > 1)
00318       {
00319 
00320          deltaBias = (bias - OneFreqData[sat].meanBias);
00321 
00322             // Square difference between biases
00323          dif2 = deltaBias*deltaBias;
00324 
00325             // Compute threshold^2
00326          thr2 = OneFreqData[sat].variance * maxNumSigmas * maxNumSigmas;
00327 
00328             // If difference in biases is bigger or equal to threshold,
00329             // then declare cycle slip
00330          if (dif2 >= thr2)
00331          {
00332             OneFreqData[sat].windowSize = 1;
00333          }
00334          else
00335          {
00336                // Update mean bias
00337             OneFreqData[sat].meanBias = OneFreqData[sat].meanBias +
00338                   deltaBias/(static_cast<double>(OneFreqData[sat].windowSize));
00339 
00340                // Update variance of bias
00341             OneFreqData[sat].variance = OneFreqData[sat].variance +
00342                            ( (dif2-OneFreqData[sat].variance) ) /
00343                            (static_cast<double>(OneFreqData[sat].windowSize));
00344 
00345                // Update buffers storing values at the end of deques
00346             OneFreqData[sat].biasBuffer.push_back(bias);
00347             OneFreqData[sat].dif2Buffer.push_back(dif2);
00348 
00349                // Check limit of window size
00350             if (OneFreqData[sat].windowSize > maxWindowSize)
00351             {
00352 
00353                   // Correct window size
00354                OneFreqData[sat].windowSize = maxWindowSize;
00355 
00356                   // Correct values of meanBias and variance, because they
00357                   // were computed with (maxWindowSize + 1)
00358 
00359                   // First, let's do a cast of 'maxWindowSize'
00360                double N((static_cast<double>(maxWindowSize)));
00361 
00362                   // We need to remove the first element
00363                OneFreqData[sat].meanBias = ( (N + 1.0)/N ) *
00364                   ( OneFreqData[sat].meanBias
00365                   - ( OneFreqData[sat].biasBuffer.front()/(N + 1.0) ) );
00366 
00367                OneFreqData[sat].variance = ( (N + 1.0)/N ) *
00368                   ( OneFreqData[sat].variance
00369                   - ( OneFreqData[sat].dif2Buffer.front()/(N + 1.0) ) );
00370 
00371                   // Finally, remove first elements from buffers (oldest data)
00372                OneFreqData[sat].biasBuffer.pop_front();
00373                OneFreqData[sat].dif2Buffer.pop_front();
00374 
00375             }
00376 
00377          }
00378       }
00379 
00380       if (OneFreqData[sat].windowSize <= 1)   // If a cycle-slip happened
00381       {
00382 
00383             // If a cycle slip happened, we must clear buffers
00384          OneFreqData[sat].biasBuffer.clear();
00385          OneFreqData[sat].dif2Buffer.clear();
00386 
00387             // Set mean bias to current code-phase bias
00388          OneFreqData[sat].meanBias = bias;
00389          OneFreqData[sat].biasBuffer.push_back(bias);
00390 
00391             // Set mean variance to default variance
00392          OneFreqData[sat].variance = defaultBiasSigma * defaultBiasSigma;
00393          OneFreqData[sat].dif2Buffer.push_back(0.0);
00394 
00395             // Report cycle slip
00396          reportCS = true;
00397 
00398       }
00399 
00400       if (reportCS)
00401       {
00402          return 1.0;
00403       }
00404       else
00405       {
00406          return 0.0;
00407       }
00408 
00409    }  // End of method 'OneFreqCSDetector::getDetection()'
00410 
00411 
00412 }  // End of namespace gpstk

Generated on Wed Feb 8 03:31:01 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1