LICSDetector2.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: LICSDetector2.cpp 1424 2008-10-29 18:04:41Z coandrei $"
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 ). 2008
00028 //
00029 //============================================================================
00030 
00031 
00032 #include "LICSDetector2.hpp"
00033 
00034 
00035 namespace gpstk
00036 {
00037 
00038       // Index initially assigned to this class
00039    int LICSDetector2::classIndex = 3200000;
00040 
00041 
00042       // Returns an index identifying this object.
00043    int LICSDetector2::getIndex() const
00044    { return index; }
00045 
00046 
00047       // Returns a string identifying this object.
00048    std::string LICSDetector2::getClassName() const
00049    { return "LICSDetector2"; }
00050 
00051 
00052       // Minimum buffer size . It is always set to 5
00053    const int LICSDetector2::minBufferSize = 5;
00054 
00055 
00056       /* Common constructor
00057        *
00058        * @param satThr  Saturation threshold to declare cycle slip, in meters.
00059        * @param tc      Threshold time constant, in seconds.
00060        * @param dtMax   Maximum interval of time allowed between two
00061        *                successive epochs, in seconds.
00062        */
00063    LICSDetector2::LICSDetector2( const double& satThr,
00064                                  const double& tc,
00065                                  const double& dtMax,
00066                                  const bool& use )
00067       : obsType(TypeID::LI), lliType1(TypeID::LLI1), lliType2(TypeID::LLI2),
00068         resultType1(TypeID::CSL1), resultType2(TypeID::CSL2), useLLI(use)
00069    {
00070       setDeltaTMax(dtMax);
00071       setSatThreshold(satThr);
00072       setTimeConst(tc);
00073       setIndex();
00074    }
00075 
00076 
00077 
00078       /* Returns a satTypeValueMap object, adding the new data generated
00079        *  when calling this object.
00080        *
00081        * @param epoch     Time of observations.
00082        * @param gData     Data object holding the data.
00083        * @param epochflag Epoch flag.
00084        */
00085    satTypeValueMap& LICSDetector2::Process( const DayTime& epoch,
00086                                             satTypeValueMap& gData,
00087                                             const short& epochflag )
00088       throw(ProcessingException)
00089    {
00090 
00091       try
00092       {
00093 
00094          double value1(0.0);
00095          double lli1(0.0);
00096          double lli2(0.0);
00097 
00098          SatIDSet satRejectedSet;
00099 
00100             // Loop through all the satellites
00101          satTypeValueMap::iterator it;
00102          for (it = gData.begin(); it != gData.end(); ++it)
00103          {
00104             try
00105             {
00106                   // Try to extract the values
00107                value1 = (*it).second(obsType);
00108             }
00109             catch(...)
00110             {
00111                   // If some value is missing, then schedule this satellite
00112                   // for removal
00113                satRejectedSet.insert( (*it).first );
00114                continue;
00115             }
00116 
00117             if (useLLI)
00118             {
00119                try
00120                {
00121                      // Try to get the LLI1 index
00122                   lli1  = (*it).second(lliType1);
00123                }
00124                catch(...)
00125                {
00126                      // If LLI #1 is not found, set it to zero
00127                      // You REALLY want to have BOTH LLI indexes properly set
00128                   lli1 = 0.0;
00129                }
00130 
00131                try
00132                {
00133                      // Try to get the LLI2 index
00134                   lli2  = (*it).second(lliType2);
00135                }
00136                catch(...)
00137                {
00138                      // If LLI #2 is not found, set it to zero
00139                      // You REALLY want to have BOTH LLI indexes properly set
00140                   lli2 = 0.0;
00141                }
00142             }
00143 
00144                // If everything is OK, then get the new values inside the
00145                // structure. This way of computing it allows concatenation of
00146                // several different cycle slip detectors
00147             (*it).second[resultType1] += getDetection( epoch,
00148                                                        (*it).first,
00149                                                        (*it).second,
00150                                                        epochflag,
00151                                                        value1,
00152                                                        lli1,
00153                                                        lli2 );
00154 
00155             if ( (*it).second[resultType1] > 1.0 )
00156             {
00157                (*it).second[resultType1] = 1.0;
00158             }
00159 
00160                // We will mark both cycle slip flags
00161             (*it).second[resultType2] = (*it).second[resultType1];
00162 
00163          }
00164 
00165             // Remove satellites with missing data
00166          gData.removeSatID(satRejectedSet);
00167 
00168          return gData;
00169 
00170       }
00171       catch(Exception& u)
00172       {
00173             // Throw an exception if something unexpected happens
00174          ProcessingException e( getClassName() + ":"
00175                                 + StringUtils::asString( getIndex() ) + ":"
00176                                 + u.what() );
00177 
00178          GPSTK_THROW(e);
00179 
00180       }
00181 
00182    }  // End of method 'LICSDetector2::Process()'
00183 
00184 
00185 
00186       /* Method to set the maximum interval of time allowed between two
00187        *  successive epochs.
00188        *
00189        * @param maxDelta      Maximum interval of time, in seconds
00190        */
00191    LICSDetector2& LICSDetector2::setDeltaTMax(const double& maxDelta)
00192    {
00193          // Don't allow delta times less than or equal to 0
00194       if (maxDelta > 0.0)
00195       {
00196          deltaTMax = maxDelta;
00197       }
00198       else
00199       {
00200          deltaTMax = 61.0;
00201       }
00202 
00203       return (*this);
00204 
00205    }  // End of method 'LICSDetector2::setDeltaTMax()'
00206 
00207 
00208 
00209       /* Method to set the saturation threshold for cycle slip detection, in
00210        * meters.
00211        *
00212        * @param satThr  Saturation threshold for cycle slip detection, in
00213        *                meters.
00214        */
00215    LICSDetector2& LICSDetector2::setSatThreshold(const double& satThr)
00216    {
00217          // Don't allow saturation thresholds less than or equal to 0
00218       if (satThr > 0.0)
00219       {
00220          satThreshold = satThr;
00221       }
00222       else
00223       {
00224          satThreshold = 0.08;
00225       }
00226 
00227       return (*this);
00228 
00229    }  // End of method 'LICSDetector2::setSatThreshold()'
00230 
00231 
00232 
00233       /* Method to set threshold time constant, in seconds
00234        *
00235        * @param tc      Threshold time constant, in seconds.
00236        *
00237        * \warning Be sure you have a very good reason to change this value.
00238        */
00239    LICSDetector2& LICSDetector2::setTimeConst(const double& tc)
00240    {
00241          // Don't allow a time constant less than or equal to 0
00242       if (tc > 0.0)
00243       {
00244          timeConst = tc;
00245       }
00246       else
00247       {
00248          timeConst = 60.0;
00249       }
00250 
00251       return (*this);
00252 
00253    }  // End of method 'LICSDetector2::setTimeConst()'
00254 
00255 
00256 
00257       /* Method to set the maximum buffer size for data, in samples.
00258        *
00259        * @param maxBufSize      Maximum buffer size for data, in samples.
00260        *
00261        * \warning You must not set a value under minBufferSize, which
00262        * usually is 5.
00263        */
00264    LICSDetector2& LICSDetector2::setMaxBufferSize(const int& maxBufSize)
00265    {
00266          // Don't allow buffer sizes less than minBufferSize
00267       if (maxBufSize >= minBufferSize)
00268       {
00269          maxBufferSize = maxBufSize;
00270       }
00271       else
00272       {
00273          maxBufferSize = minBufferSize;
00274       }
00275 
00276       return (*this);
00277 
00278    }  // End of method 'LICSDetector2::setMaxBufferSize()'
00279 
00280 
00281 
00282       /* Returns a gnnsRinex object, adding the new data generated when
00283        * calling this object.
00284        *
00285        * @param gData    Data object holding the data.
00286        */
00287    gnssRinex& LICSDetector2::Process(gnssRinex& gData)
00288       throw(ProcessingException)
00289    {
00290 
00291       try
00292       {
00293 
00294          Process(gData.header.epoch, gData.body, gData.header.epochFlag);
00295 
00296          return gData;
00297 
00298       }
00299       catch(Exception& u)
00300       {
00301             // Throw an exception if something unexpected happens
00302          ProcessingException e( getClassName() + ":"
00303                                 + StringUtils::asString( getIndex() ) + ":"
00304                                 + u.what() );
00305 
00306          GPSTK_THROW(e);
00307 
00308       }
00309 
00310    }  // End of method 'LICSDetector2::Process()'
00311 
00312 
00313       /* Method that implements the LI cycle slip detection algorithm
00314        *
00315        * @param epoch     Time of observations.
00316        * @param sat       SatID.
00317        * @param tvMap     Data structure of TypeID and values.
00318        * @param epochflag Epoch flag.
00319        * @param li        Current LI observation value.
00320        * @param lli1      LLI1 index.
00321        * @param lli2      LLI2 index.
00322        */
00323    double LICSDetector2::getDetection( const DayTime& epoch,
00324                                        const SatID& sat,
00325                                        typeValueMap& tvMap,
00326                                        const short& epochflag,
00327                                        const double& li,
00328                                        const double& lli1,
00329                                        const double& lli2 )
00330    {
00331 
00332       bool reportCS(false);
00333 
00334          // Difference between current and former epochs, in sec
00335       double currentDeltaT(0.0);
00336 
00337       double tempLLI1(0.0);
00338       double tempLLI2(0.0);
00339 
00340 
00341          // Get current buffer size
00342       size_t s( LIData[sat].LIEpoch.size() );
00343 
00344          // Get the difference between current epoch and LAST epoch,
00345          // in seconds, but first test if we have epoch data inside LIData
00346       if(s > 0)
00347       {
00348          currentDeltaT = ( epoch - LIData[sat].LIEpoch.back() );
00349       }
00350       else
00351       {
00352             // This will yield a very big value
00353          currentDeltaT = ( epoch - DayTime::BEGINNING_OF_TIME );
00354       }
00355 
00356 
00357          // Check if receiver already declared cycle slip or too much time
00358          // has elapsed
00359          // Note: If tvMap(lliType1) or tvMap(lliType2) don't exist, then 0
00360          // will be returned and those tests will pass
00361       if ( (tvMap(lliType1)==1.0) ||
00362            (tvMap(lliType1)==3.0) ||
00363            (tvMap(lliType1)==5.0) ||
00364            (tvMap(lliType1)==7.0) )
00365       {
00366          tempLLI1 = 1.0;
00367       }
00368 
00369       if ( (tvMap(lliType2)==1.0) ||
00370            (tvMap(lliType2)==3.0) ||
00371            (tvMap(lliType2)==5.0) ||
00372            (tvMap(lliType2)==7.0) )
00373       {
00374          tempLLI2 = 1.0;
00375       }
00376 
00377       if ( (epochflag==1)  ||
00378            (epochflag==6)  ||
00379            (tempLLI1==1.0) ||
00380            (tempLLI2==1.0) ||
00381            (currentDeltaT > deltaTMax) )
00382       {
00383 
00384             // We reset buffer with the following lines
00385          LIData[sat].LIEpoch.clear();
00386          LIData[sat].LIBuffer.clear();
00387 
00388             // current buffer size should be updated
00389          s = LIData[sat].LIEpoch.size();
00390 
00391             // Report cycle slip
00392          reportCS = true;
00393       }
00394 
00395          // Check if we have enough data to start processing.
00396       if (s >= minBufferSize)
00397       {
00398             // Declare a Vector for LI measurements
00399          Vector<double> y(s, 0.0);
00400 
00401             // Declare a Matrix for epoch information
00402          Matrix<double> M(s, 3, 0.0);
00403 
00404             // We store here the OLDEST (or FIRST) epoch in buffer for future
00405             // reference. This is important because adjustment will be made
00406             // with respect to that first epoch
00407          DayTime firstEpoch(LIData[sat].LIEpoch.front());
00408 
00409             // Feed 'y' with data
00410          for(size_t i=0; i<s; i++)
00411          {
00412                // The newest goes first in 'y' vector
00413             y(i) = LIData[sat].LIBuffer[s-1-i];
00414          }
00415 
00416             // Feed 'M' with data
00417          for(size_t i=0; i<s; i++)
00418          {
00419                // Compute epoch difference with respect to FIRST epoch
00420             double dT( LIData[sat].LIEpoch[s-1-i] - firstEpoch );
00421 
00422             M(i,0) = 1.0;
00423             M(i,1) = dT;
00424             M(i,2) = dT*dT;
00425          }
00426 
00427             // Now, proceed to find a 2nd order fiting curve using a least
00428             // mean squares (LMS) adjustment
00429          Matrix<double> MT(transpose(M));
00430          Matrix<double> covMatrix( MT * M );
00431 
00432          // Let's try to invert MT*M   matrix
00433          try
00434          {
00435             covMatrix = inverseChol( covMatrix );
00436          }
00437          catch(...)
00438          {
00439                // If covMatrix can't be inverted we have a serious problem
00440                // with data, so reset buffer and declare cycle slip
00441             LIData[sat].LIEpoch.clear();
00442             LIData[sat].LIBuffer.clear();
00443 
00444             reportCS = true;
00445          }
00446 
00447 
00448             // Now, compute the Vector holding the results of adjustment to
00449             // second order curve
00450          Vector<double> a(covMatrix * MT * y);
00451 
00452             // The next step is to compute the maximum deviation from
00453             // adjustment, in order to assess if our adjustment is too noisy
00454          double maxDeltaLI(0.0);
00455 
00456          for(size_t i=0; i<s; i++)
00457          {
00458                // Compute epoch difference with respect to FIRST epoch
00459             double dT( LIData[sat].LIEpoch[s-1-i] - firstEpoch );
00460 
00461                // Compute adjusted LI value
00462             double LIa( a(0) + a(1)*dT + a(2)*dT*dT );
00463 
00464                // Find maximum deviation in current data buffer
00465             double deltaLI( std::abs(LIa - LIData[sat].LIBuffer[s-1-i]) );
00466             if( deltaLI > maxDeltaLI )
00467             {
00468                 maxDeltaLI = deltaLI;
00469             }
00470          }
00471 
00472             // Compute epoch difference with respect to FIRST epoch
00473          double deltaT( epoch - firstEpoch );
00474 
00475             // Compute current adjusted LI value
00476          double currentLIa( a(0) + a(1)*deltaT + a(2)*deltaT*deltaT );
00477 
00478             // Difference between current and adjusted LI values
00479          double currentBias( std::abs( currentLIa - li ) );
00480 
00481             // We will continue processing only if we trust our current
00482             // adjustment, i.e: it is NOT too noisy
00483          if( (2.0*maxDeltaLI) < currentBias )
00484          {
00485                // Compute limit to declare cycle slip
00486             double deltaLimit( satThreshold /
00487                                ( 1.0 + ( 1.0 /
00488                                          std::exp(currentDeltaT/timeConst) )));
00489 
00490                // Check if current LI deviation is above deltaLimit threshold
00491             if( currentBias > deltaLimit )
00492             {
00493                   // Reset buffer and declare cycle slip
00494                LIData[sat].LIEpoch.clear();
00495                LIData[sat].LIBuffer.clear();
00496 
00497                reportCS = true;
00498 
00499             }
00500 
00501          }
00502 
00503       }
00504       else
00505       {
00506             // If we don't have enough data, we report cycle slips
00507          reportCS = true;
00508       }
00509 
00510          // Let's prepare for the next epoch
00511 
00512          // Store current epoch at the end of deque
00513       LIData[sat].LIEpoch.push_back(epoch);
00514 
00515          // Store current value of LI at the end of deque
00516       LIData[sat].LIBuffer.push_back(li);
00517 
00518          // Update current buffer size
00519       s = LIData[sat].LIEpoch.size();
00520 
00521          // Check if we have exceeded maximum window size
00522       if(s > maxBufferSize)
00523       {
00524             // Get rid of oldest data, which is at the beginning of deque
00525          LIData[sat].LIEpoch.pop_front();
00526          LIData[sat].LIBuffer.pop_front();
00527 
00528       }
00529 
00530 
00531       if (reportCS)
00532       {
00533          return 1.0;
00534       }
00535       else
00536       {
00537          return 0.0;
00538       }
00539 
00540    }  // End of method 'LICSDetector2::getDetection()'
00541 
00542 
00543 
00544 }  // End of namespace gpstk

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