MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/NavigationAndControl/MOOSNavLib/MOOSNavLSQEngine.cpp
Go to the documentation of this file.
00001 
00002 //
00003 //   MOOS - Mission Oriented Operating Suite 
00004 //  
00005 //   A suit of Applications and Libraries for Mobile Robotics Research 
00006 //   Copyright (C) 2001-2005 Massachusetts Institute of Technology and 
00007 //   Oxford University. 
00008 //    
00009 //   This software was written by Paul Newman and others
00010 //   at MIT 2001-2002 and Oxford University 2003-2005.
00011 //   email: pnewman@robots.ox.ac.uk. 
00012 //      
00013 //   This file is part of a  MOOS Basic (Common) Application. 
00014 //        
00015 //   This program is free software; you can redistribute it and/or 
00016 //   modify it under the terms of the GNU General Public License as 
00017 //   published by the Free Software Foundation; either version 2 of the 
00018 //   License, or (at your option) any later version. 
00019 //          
00020 //   This program is distributed in the hope that it will be useful, 
00021 //   but WITHOUT ANY WARRANTY; without even the implied warranty of 
00022 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
00023 //   General Public License for more details. 
00024 //            
00025 //   You should have received a copy of the GNU General Public License 
00026 //   along with this program; if not, write to the Free Software 
00027 //   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
00028 //   02111-1307, USA. 
00029 //
00031 // MOOSNavLSQEngine.cpp: implementation of the CMOOSNavLSQEngine class.
00032 //
00034 #ifdef _WIN32
00035 #pragma warning(disable : 4786)
00036 #endif
00037 
00038 #include "MOOSNavLibGlobalHelper.h"
00039 #include "MOOSNavObsStore.h"
00040 #include "MOOSNavVehicle.h"
00041 #include "MOOSNavLSQEngine.h"
00042 #include "MOOSNavLibDefs.h"
00043 #define UKOA_W_REJECTION 2.576
00044 #define MINIMUM_TIME_BETWEEN_SOLUTIONS 0.5
00045 
00046 
00048 // Construction/Destruction
00050 
00051 CMOOSNavLSQEngine::CMOOSNavLSQEngine()
00052 {
00053     m_dfLSQWindow = 4.0;
00054     m_nLSQIterations = 5;
00055     m_bTryToSolve = false;
00056     m_dfLastSolveAttempt = 0;
00057     
00058     //don't  bother updateing more often than once
00059     //ever second..
00060     m_dfUpdatePeriod = 1.0;
00061     
00062     m_sName = "LSQ";
00063     
00064     
00065     m_bGuessed = false;
00066     
00067     m_bInitialOnline = true;
00068 }
00069 
00070 CMOOSNavLSQEngine::~CMOOSNavLSQEngine()
00071 {
00072     
00073 }
00074 
00075 bool CMOOSNavLSQEngine::AddData(const CMOOSMsg &Msg)
00076 {
00077     bool bBaseSuccess = CMOOSNavEngine::AddData(Msg);
00078     
00079     if(bBaseSuccess)
00080     {
00081         m_bTryToSolve = true;
00082     }
00083     
00084     return bBaseSuccess;
00085 }
00086 
00087 bool CMOOSNavLSQEngine::Iterate(double dfTimeNow)
00088 {
00089     //house keeping
00090     if(!IterateRequired(dfTimeNow))
00091     {
00092         return false;
00093     }
00094     
00095     //keep a count of how many times this has been called
00096     if(!m_bGuessed)
00097     {
00098         GuessVehicleLocation();
00099         m_bGuessed = true;;
00100     }
00101     
00102     
00103     
00104     m_dfTimeNow = dfTimeNow;        
00105     
00106     //take a copy of m_Xhat
00107     m_XhatTmp = m_Xhat;
00108     m_PhatTmp = m_Phat;
00109     
00110     
00111     
00112     
00113     double m_dfCutOffTime = dfTimeNow-m_dfLSQWindow;
00114     
00115     m_Observations.clear();
00116     if(m_pStore->GetObservationsBetween(m_Observations,m_dfCutOffTime,dfTimeNow))
00117     {
00118         
00119         if(m_Observations.empty())
00120             return false;
00121         
00122         m_dfLastSolveAttempt = dfTimeNow;
00123         
00124         
00125         //here we add in the fixed observations....
00126         m_Observations.insert(    m_Observations.begin(),
00127             m_FixedObservations.begin(),
00128             m_FixedObservations.end());
00129         
00130 
00131         //limit the number of certain kinds of observations
00132         LimitObservations(CMOOSObservation::DEPTH,1);
00133         LimitObservations(CMOOSObservation::YAW,1);
00134         LimitObservations(CMOOSObservation::X,1);
00135         LimitObservations(CMOOSObservation::Y,1);
00136         
00137         //here is out chance to look at consistency of data..
00138         //PreFilterData();                
00139 
00140         //TraceObservationSet();
00141 
00142         m_Logger.Comment("LSQ Iterate Attempted",dfTimeNow);
00143 
00144         for(int nIteration = 0;nIteration<m_nLSQIterations;nIteration++)
00145         {
00146             if(MakeObsMatrices())
00147             {
00148                 //we've just figured out innovations
00149                 //but don't have innov std - we record
00150                 //this data in each observation
00151                 RecordObsStatistics(&m_Innov,NULL);
00152 
00153                 switch(Solve())
00154                 {
00155                 case LSQ_NO_SOLUTION:
00156                     //failed update...
00157                     //                    MOOSTrace("No Solution!\n");                    
00158                     //TraceObservationSet();
00159                     m_Xhat = m_XhatTmp;
00160                     m_Phat = m_PhatTmp;
00161                     m_bTryToSolve = false;
00162                     m_Logger.Comment("No Solution",dfTimeNow);
00163                     return false;
00164                     
00165                 case LSQ_BIG_CHANGE:
00166                     m_bTryToSolve = false;
00167                     m_Logger.Comment("Big Change In Solution - solution abandoned",dfTimeNow);
00168                     return false;
00169 
00170                 case LSQ_IN_PROGRESS:
00171                     if(nIteration==m_nLSQIterations)
00172                     {
00173                         m_Xhat = m_XhatTmp;
00174                         m_Phat = m_PhatTmp;
00175                         m_bTryToSolve = false;
00176                         m_Logger.Comment("No Convergence",dfTimeNow);
00177                         return false;
00178                     }
00179                     break;
00180                     
00181                     
00182                 case LSQ_SOLVED:
00183                     if(!DoWStatistic())
00184                     {
00185                         //we will have removed the observation
00186                         //that is not fitting...try to iterate again..
00187                         nIteration = 0;
00188                         break;
00189                     }
00190                     else
00191                     {
00192                         return OnSolved();
00193                     }                
00194                 }
00195             }
00196         }                              
00197     }
00198     
00199     
00200     return false;
00201 }
00202 
00203 
00204 
00205 CMOOSNavLSQEngine::LSQStatus CMOOSNavLSQEngine::Solve()
00206 {
00207     
00208     
00209     try
00210     {
00211         
00212         if(m_jH.Nrows()<m_Xhat.Nrows())
00213         {
00214       //      MOOSMatrixTrace(m_jH,"jH");
00215       //      TraceObservationSet();
00216             return LSQ_NO_SOLUTION;
00217         }
00218         
00219         Matrix L = m_jH.t()*m_R.i();
00220         m_Ihat = (L*m_jH);
00221 
00222         //TraceObservationSet();
00223         //MOOSMatrixTrace(m_Ihat,"I");
00224         m_Phat = m_Ihat.i();
00225         
00226         //does the covariance look reasonable?
00227         if(!IsReasonableMerit())
00228         {
00229 
00230             //un comment to see failure cases..
00231             //MOOSMatrixTrace(m_Phat,"Unreasonable P");
00232             //TraceObservationSet();
00233             //MOOSMatrixTrace(m_Ihat,"I");
00234             //MOOSMatrixTrace(m_jH,"jH");
00235             
00236             //interesting we could be in a bad spot...
00237             //better move..
00238             AddToOutput("Ill conditioned LSQ - relocating vehicle to field mean\n");
00239             GuessVehicleLocation();
00240             return LSQ_NO_SOLUTION;
00241         }
00242         
00243         //ok shuffle state a little bit
00244         Matrix dX = m_Phat*L*m_Innov;
00245         m_Xhat += dX;
00246         
00247         //is the state change small?
00248         if(MOOSChiSquaredTest(dX,m_Ihat,true))          
00249         {            
00250             //Matrix DState = m_Xhat-m_XhatTmp;
00251             //if(DState.MaximumAbsoluteValue()>5.0)
00252             //{
00253             //    return LSQ_BIG_CHANGE;
00254             //}
00255 
00256             m_nIterations++;
00257             
00258             return LSQ_SOLVED;
00259         }
00260         else
00261         {
00262             return LSQ_IN_PROGRESS;
00263         }
00264         
00265     }
00266     catch(...)
00267     {
00268         m_Phat.Release();
00269         m_Phat.CleanUp();
00270         return LSQ_NO_SOLUTION;
00271     }
00272     
00273 }
00274 
00275 bool CMOOSNavLSQEngine::IterateRequired(double dfTimeNow)
00276 {
00277     //if we know we could never solve don;t bother
00278     //for exmple if last iteratiodn failed and no new
00279     //data has arrived since then..
00280     if(!m_bTryToSolve)
00281         return false;
00282     
00283     //this ets the fastest possible update rate
00284     //at 2HZ = reasonarble
00285     if(dfTimeNow-m_dfLastSolveAttempt<MINIMUM_TIME_BETWEEN_SOLUTIONS)
00286     {
00287         return false;
00288     }
00289     
00290     if(dfTimeNow-m_dfLastUpdate<m_dfUpdatePeriod)
00291     {
00292         return false;
00293     }
00294     
00295     return true;
00296 }
00297 
00298 void CMOOSNavLSQEngine::DoDebug()
00299 {
00300 /*    DBF<<m_dfTimeNow<<" "<<m_Xhat(1,1)<<" "<<m_Xhat(2,1)<<" "<<m_Xhat(3,1)<<" "<<m_Xhat(4,1)<<" ";
00301     
00302     OBSLIST::iterator p;
00303     
00304     for(p = m_Observations.begin();p!=m_Observations.end();p++)
00305     {
00306         CMOOSObservation  & rObs = *p;
00307         DBF<<rObs.m_dfData<<" ";
00308     }
00309     DBF<<endl;
00310     
00311 */    
00312 }
00313 
00314 // here we look for a reasonable PSD covariance matrix
00315 //this is an extra check to look for results of illconditioned
00316 //inversions
00317 bool CMOOSNavLSQEngine::IsReasonableMerit()
00318 {
00319     int nRows = m_Xhat.Nrows();
00320     
00321     for(int n = 1; n<=nRows;n++)
00322     {
00323         double dfDiag = m_Phat(n,n);
00324         if(dfDiag<0)
00325             return false;
00326         
00327         if(dfDiag>1e4)
00328             return false;
00329     }
00330     return true;
00331 }
00332 
00333 bool CMOOSNavLSQEngine::OnSolved()
00334 {
00335     
00336     //MOOSTrace("\n\n++++ IterateLSQ @%f ++++\n",m_dfTimeNow);
00337     //MOOSMatrixTrace(m_Xhat,"XSolved:");
00338     
00339     //so we used these obs...
00340     m_pStore->MarkAsUsed(m_Observations);
00341     
00342     //our last good time was right now! :-)
00343     m_dfLastUpdate = m_dfTimeNow;
00344     
00345     //don't try and solve until mode data is in..
00346     m_bTryToSolve = false;
00347     
00348     //look after wrapped angle states..
00349     WrapAngleStates();
00350     
00351     if(m_pTracked->RefreshState())
00352     {
00353         PublishData();               
00354         LogObservationSet(m_dfTimeNow,m_nIterations);
00355         m_Logger.LogState(m_dfTimeNow,m_Xhat,m_Phat);
00356     }
00357     
00358     
00359     return true;
00360     
00361 }
00362 
00363 bool CMOOSNavLSQEngine::Initialise(STRING_LIST  sParams)
00364 {
00365     m_bGuessed = false;
00366     
00367     if(!CMOOSNavEngine::Initialise(sParams))
00368         return false;
00369    
00370     //we never use heading bias state in LSQ
00371     m_bEstimateHeadingBias = false;
00372 
00373     //here we set up sensor trajectory based rejection for the LSQ filter
00374     //alwasy on for least square filter
00375     if(!SetUpSensorChannels(sParams,"REJECTION"))
00376         return false;
00377 
00378     
00379     return true;
00380 }
00381 
00382 
00383 
00384 bool CMOOSNavLSQEngine::DoWStatistic()
00385 {
00386     return true;
00387 
00388     //now recalculate the innovation based on our present
00389     //estimate;
00390     if(!MakeObsMatrices())
00391         return false;
00392     
00393     //calculate innovation covariance
00394     Matrix S = m_R-(m_jH*m_Phat*m_jH.t());
00395     
00396     //    MOOSMatrixTrace(S,"S");
00397     //   MOOSMatrixTrace(m_jH,"H");
00398     //    MOOSMatrixTrace(m_R,"m_R");
00399     
00400     int nRows = m_Innov.Nrows();
00401     
00402     OBSLIST::iterator p,q;    
00403     
00404     q= m_Observations.end();
00405     
00406     //calculate w statistics
00407     double dfMaxW = 0;
00408     
00409     
00410     for(p= m_Observations.begin();p!=m_Observations.end();p++)
00411     {
00412         CMOOSObservation & rObs = *p;
00413         
00414         if(!rObs.IsFixed() && !rObs.m_bIgnore)
00415         {         
00416             int iRow = rObs.m_nRow;
00417             
00418             double dfSigma = sqrt(S(iRow,iRow));
00419             
00420             if(dfSigma>1e-10)
00421             {
00422                 double dfResidual = m_Innov(iRow,1);
00423                 
00424                 double dfW = fabs(dfResidual)/dfSigma;
00425                 
00426                 if(dfW>dfMaxW)
00427                 {
00428                     //store largest absolute value
00429                     q=p;
00430                     dfMaxW = dfW;
00431                 }
00432             }
00433         }
00434     }
00435     
00436     //if we have found an observation that doesn't fit
00437     if(dfMaxW>UKOA_W_REJECTION)
00438     {
00439         if(q!=m_Observations.end())
00440         {
00441             CMOOSObservation & rObs = *q;
00442             //ignore it
00443             rObs.m_bIgnore = true;
00444             rObs.m_bGoodDA = false;
00445             
00446             MOOSTrace("Failed W test:\n");
00447             rObs.Trace();
00448             
00449             
00450             return false;
00451         }
00452     }
00453     
00454     return true;
00455 }
00456 
00457 
00458 bool CMOOSNavLSQEngine::PublishData()
00459 {
00460     if(m_nIterations%20==0)
00461     {
00462         AddToOutput("LSQ Completes iteration %d",m_nIterations);
00463     }
00464     
00465     //Ok so lets make some results..
00466     CMOOSMsg MsgX(MOOS_NOTIFY,"LSQ_X", m_pTracked->m_State.m_dfX,m_dfTimeNow);
00467     m_ResultsList.push_front(MsgX);
00468     
00469     CMOOSMsg MsgY(MOOS_NOTIFY,"LSQ_Y", m_pTracked->m_State.m_dfY,m_dfTimeNow);
00470     m_ResultsList.push_front(MsgY);
00471     
00472     CMOOSMsg MsgZ(MOOS_NOTIFY,"LSQ_Z", m_pTracked->m_State.m_dfZ,m_dfTimeNow);
00473     m_ResultsList.push_front(MsgZ);
00474     
00475     CMOOSMsg MsgYaw(MOOS_NOTIFY,"LSQ_YAW", m_pTracked->m_State.m_dfH,m_dfTimeNow);
00476     m_ResultsList.push_front(MsgYaw);
00477     
00478     CMOOSMsg MsgDepth(MOOS_NOTIFY,"LSQ_DEPTH", m_pTracked->m_State.m_dfDepth,m_dfTimeNow);
00479     m_ResultsList.push_front(MsgDepth);
00480     
00481     CMOOSMsg MsgTide(MOOS_NOTIFY,"LSQ_TIDE", m_Xhat(TIDE_STATE_INDEX,1),m_dfTimeNow);
00482     m_ResultsList.push_front(MsgTide);
00483     
00484     return true;
00485 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines