MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/NavigationAndControl/MOOSNavLib/MOOSNavEKFEngine.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 // MOOSNavEKFEngine.cpp: implementation of the CMOOSNavEKFEngine class.
00032 //
00034 #include "MOOSNavLibGlobalHelper.h"
00035 #include "MOOSNavLibDefs.h"
00036 #include "MOOSNavObsStore.h"
00037 #include "MOOSNavVehicle.h"
00038 #include "MOOSNavEKFEngine.h"
00039 
00040 #define MAX_ALLOWED_LIN_VELOCITY 3.0
00041 #define MAX_ALLOWED_ANG_VELOCITY MOOSDeg2Rad(15)
00042 #define EKF_ITERATE_PERIOD 0.3
00043 #define TIME_SLICE (EKF_ITERATE_PERIOD/2.0)
00044 
00046 // Construction/Destruction
00048 
00049 CMOOSNavEKFEngine::CMOOSNavEKFEngine()
00050 {
00051     m_dfXYDynamics=5;
00052     m_dfZDynamics=5;
00053     m_dfYawDynamics=5;    
00054     
00055     m_dfPxx0    = pow(30.0,2.0);
00056     m_dfPyy0    = pow(30.0,2.0);
00057     m_dfPzz0    = pow(10.0,2.0);
00058     m_dfPhh0    = pow(MOOSDeg2Rad(90),2.0);
00059     
00060     m_dfX0 = 0;
00061     m_dfY0 = 0;
00062     m_dfZ0 = 50;
00063     m_dfH0 = 0;
00064     m_dfTide0 = 50;
00065     
00066     m_dfLastIterated = 0;
00067     
00068     m_dfLag = 2.0;
00069     
00070     m_sName = "EKF";
00071     
00072     m_bBooted = 0;
00073 
00074     m_dfYawBiasStd = 0;
00075     
00076     m_dfMaxZVel = MAX_ALLOWED_LIN_VELOCITY;
00077 
00078     m_bInitialOnline = false;
00079 }
00080 
00081 CMOOSNavEKFEngine::~CMOOSNavEKFEngine()
00082 {
00083     
00084 }
00085 
00086 
00087 bool CMOOSNavEKFEngine::Initialise(STRING_LIST  sParams)
00088 {
00089     
00090     //before calling base class member peek to see if we
00091     //are being told to modify the defaul kind of vehcile that
00092     //will be built
00093     string sVal;
00094     if(MOOSGetValueFromToken(sParams,"EKF_VEHICLE_TYPE",sVal))
00095     {
00096         if(MOOSStrCmp(sVal,"MOBILE"))
00097         {
00098             m_eVehicleType =  CMOOSNavEntity::POSE_AND_RATE;
00099         }
00100     }
00101 
00102     //do we want to estimate heading bias?
00103     if(MOOSGetValueFromToken(sParams,"EKF_ESTIMATE_YAW_BIAS",sVal))
00104     {
00105         if(MOOSStrCmp(sVal,"TRUE"))
00106         {
00107             m_bEstimateHeadingBias = true;
00108         }
00109     }
00110 
00111 
00112 
00113     //now call base class version
00114     if(!CMOOSNavEngine::Initialise(sParams))
00115     {
00116         return false;
00117     }
00118     
00119 
00120        if(MOOSGetValueFromToken(sParams,"EKF_YAW_BIAS_NOISE",sVal))
00121     {
00122         m_dfYawBiasStd = atof(sVal.c_str());
00123         if(m_dfYawBiasStd<0) 
00124             m_dfYawBiasStd=0;
00125     }
00126 
00127     
00128     if(MOOSGetValueFromToken(sParams,"EKF_LAG",sVal))
00129     {
00130         double dfVal = atof(sVal.c_str());
00131         if(dfVal<0) dfVal=0;
00132         if(dfVal>4) dfVal = 4;
00133         m_dfLag = dfVal;
00134     }
00135     
00136 
00137 
00138     
00139 
00140     //now we may have other things to set up....
00141     if(MOOSGetValueFromToken(sParams,"EKF_XY_DYNAMICS",sVal))
00142     {
00143         double dfVal = atof(sVal.c_str());
00144         if(dfVal<0) dfVal=0;
00145         if(dfVal>10) dfVal = 10;
00146         m_dfXYDynamics = dfVal;
00147     }
00148     
00149     if(MOOSGetValueFromToken(sParams,"EKF_Z_DYNAMICS",sVal))
00150     {
00151         double dfVal = atof(sVal.c_str());
00152         if(dfVal<0) dfVal=0;
00153         if(dfVal>10) dfVal = 10;
00154         m_dfZDynamics = dfVal;
00155     }
00156     
00157     if(MOOSGetValueFromToken(sParams,"EKF_YAW_DYNAMICS",sVal))
00158     {
00159         double dfVal = atof(sVal.c_str());
00160         if(dfVal<0) dfVal=0;
00161         if(dfVal>10) dfVal = 10;
00162         m_dfYawDynamics = dfVal;
00163     }
00164     
00165     
00166     //rad in intial uncertainties
00167     if(MOOSGetValueFromToken(sParams,"EKF_SIGMA_XX",sVal))
00168     {
00169         double dfVal = atof(sVal.c_str());
00170         if(dfVal>0)
00171         {
00172             m_dfPxx0 = pow(dfVal,2);
00173         }
00174     }
00175     
00176     if(MOOSGetValueFromToken(sParams,"EKF_SIGMA_YY",sVal))
00177     {
00178         double dfVal = atof(sVal.c_str());
00179         if(dfVal>0)
00180         {
00181             m_dfPyy0 = pow(dfVal,2);
00182         }
00183     }
00184     
00185     if(MOOSGetValueFromToken(sParams,"EKF_SIGMA_ZZ",sVal))
00186     {
00187         double dfVal = atof(sVal.c_str());
00188         if(dfVal>0)
00189         {
00190             m_dfPzz0 = pow(dfVal,2);
00191         }
00192     }
00193     
00194     if(MOOSGetValueFromToken(sParams,"EKF_SIGMA_HH",sVal))
00195     {
00196         double dfVal = atof(sVal.c_str());
00197         if(dfVal>0)
00198         {
00199             m_dfPhh0 = pow(MOOSDeg2Rad(dfVal),2);
00200         }
00201     }
00202     
00203     if(MOOSGetValueFromToken(sParams,"EKF_SIGMA_TIDE",sVal))
00204     {
00205         double dfVal = atof(sVal.c_str());
00206         if(dfVal>0)
00207         {
00208             m_dfPTide0 = pow((dfVal),2);
00209         }
00210     }
00211     
00212     
00213     //where shall we start from?
00214     if(MOOSGetValueFromToken(sParams,"EKF_X",sVal))
00215     {
00216         double dfVal = atof(sVal.c_str());
00217         m_dfX0 = dfVal;
00218     }
00219     if(MOOSGetValueFromToken(sParams,"EKF_Y",sVal))
00220     {
00221         double dfVal = atof(sVal.c_str());
00222         m_dfY0 = dfVal;
00223     }
00224     if(MOOSGetValueFromToken(sParams,"EKF_Z",sVal))
00225     {
00226         double dfVal = atof(sVal.c_str());
00227         m_dfZ0 = dfVal;
00228     }
00229     if(MOOSGetValueFromToken(sParams,"EKF_H",sVal))
00230     {
00231         double dfVal = atof(sVal.c_str());
00232         //convert to yaw in degrees
00233         m_dfH0 = MOOSDeg2Rad(-dfVal);
00234     }
00235     if(MOOSGetValueFromToken(sParams,"EKF_TIDE",sVal))
00236     {
00237         double dfVal = atof(sVal.c_str());
00238         m_dfTide0 = dfVal;
00239     }
00240     if(MOOSGetValueFromToken(sParams,"EKF_MAX_Z_VEL",sVal))
00241     {
00242         double dfVal = atof(sVal.c_str());
00243         m_dfMaxZVel = dfVal;
00244     }
00245 
00246 
00247 
00248     m_pTracked->m_State.m_dfX = m_dfX0;
00249     m_pTracked->m_State.m_dfY = m_dfY0;
00250     m_pTracked->m_State.m_dfZ = m_dfZ0;
00251     m_pTracked->m_State.m_dfH = m_dfH0;
00252     
00253     m_pTracked->m_State.m_dfPX = m_dfPxx0;
00254     m_pTracked->m_State.m_dfPY = m_dfPyy0;
00255     m_pTracked->m_State.m_dfPZ = m_dfPzz0;
00256     m_pTracked->m_State.m_dfPH = m_dfPhh0;
00257     
00258     m_pTracked->m_State.m_dfPXdot = 0.0;
00259     m_pTracked->m_State.m_dfPYdot = 0.0;
00260     m_pTracked->m_State.m_dfPZdot = 0.0;
00261     m_pTracked->m_State.m_dfPHdot = 0.0;
00262 
00263 
00264 
00265     m_pStore->m_sOwnerName="EKF";
00266     
00267     m_nUpdates = 0;
00268     
00269     return true;
00270 }
00271 
00272 
00273 bool CMOOSNavEKFEngine::AddData(const CMOOSMsg &Msg)
00274 {
00275     
00276     //    if(Msg.m_sKey=="LBL_TOF")
00277     //    {
00278     //        MOOSTrace("EKF gets LBL\n");
00279     //    }
00280     return CMOOSNavEngine::AddData(Msg);
00281 }
00282 
00283 
00284 bool CMOOSNavEKFEngine::Iterate(double dfTimeNow)
00285 {
00286     
00287     //not allowed to run if not Online!
00288     if(!IsOnline())
00289         return true;
00290     
00291     if(dfTimeNow-m_dfLastIterated<EKF_ITERATE_PERIOD)
00292         return true;
00293     
00294     m_dfLastIterated = dfTimeNow;
00295     
00296     //keep a copy of the time..
00297     m_dfTimeNow = dfTimeNow;
00298     
00299     if(!IsBooted())
00300     {
00301         return Boot();
00302     }
00303     else
00304     {
00305         
00306         //what time should we stop at?
00307         double dfTStop = m_dfTimeNow-m_dfLag;
00308         
00309         double dfNewestObsTime = m_pStore->GetNewestObsTime();
00310         
00311         if(dfNewestObsTime<=m_dfLastUpdate)
00312         {
00313             //predict only ..no new observations have come in...
00314             double dfDeltaT = dfTStop-m_dfLastUpdate;
00315             if(!DoPredict(dfDeltaT))
00316                 return false;    
00317         }
00318         else
00319         {
00320             //get observations in small batches that are close to
00321             //each other...
00322             
00323             double dfDT = dfTStop-m_dfLastUpdate;
00324             
00325             int nIterations = 0;
00326             while(dfDT>TIME_SLICE)
00327             {
00328                 //split up the whole period into even sized chunks
00329                 dfDT=(dfTStop-m_dfLastUpdate)/(++nIterations);
00330             }
00331             
00332             //for each of these chuncks predict then look to update...
00333             for(int nIteration = 0;nIteration<nIterations;nIteration++)
00334             {
00335                 if(!DoPredict(dfDT))
00336                     return false;
00337                 
00338                 m_Observations.clear();
00339                 
00340                 double dfT1 = m_dfLastUpdate+nIteration*dfDT;
00341                 double dfT2 = dfT1+dfDT;
00342                 
00343                 //get the observations (close to each other in time)
00344                 //MOOSTrace("EKF @ %.3f true time = %.3f\n",dfTimeNow,MOOSTime());
00345                 if(m_pStore->GetObservationsBetween(m_Observations,dfT1,dfT2))
00346                 {
00347                     if(!m_Observations.empty())
00348                     {
00349                         
00350                         //TraceObservationSet();
00351                         
00352                         if(nIteration==0)
00353                         {
00354                             //here we add in the fixed observations....
00355                             m_Observations.insert(    m_Observations.begin(),
00356                                 m_FixedObservations.begin(),
00357                                 m_FixedObservations.end());
00358                         }
00359                         
00360                         //limit the number of certain kinds of observations
00361                         LimitObservations(CMOOSObservation::DEPTH,1);
00362                         LimitObservations(CMOOSObservation::YAW,1);
00363                         
00364                         bool bDone = false;
00365 
00366                         //safety - we should always be removeing at least one observation
00367                         //per DA loop so limit the number of times we can do this!
00368                         int nDACycles = m_Observations.size();
00369                         while(!bDone && (nDACycles--)>0)
00370                         {
00371                             if(MakeObsMatrices())
00372                             {
00373                                 
00374                                 //calcuate innovation covariance
00375                                 try
00376                                 {
00377                                     if(m_Innov.Nrows()<0)
00378                                     {
00379                                         //exit condition for DA
00380                                         bDone = true;
00381                                         continue;
00382                                     }
00383 
00384                                     //Kalman equation for innovation covariance
00385                                     m_S = m_jH*m_Phat*m_jH.t() + m_R;
00386 
00387                                     RecordObsStatistics(&m_Innov,&m_S);
00388                                     
00389                                     //do data rejection...
00390                                     bool bAccepted = true;
00391                                     if(MOOSChiSquaredTest(m_Innov,m_S,false))
00392                                     {
00393                                         Matrix W = m_Phat*m_jH.t()*m_S.i();
00394                                         m_Phat-=W*m_S*W.t();
00395                                         m_Xhat+=W*m_Innov;
00396 
00397                                         //complete....
00398                                         bDone = true;   
00399                                     }
00400                                     else
00401                                     {
00402                                         if(m_Innov.Nrows()>1)
00403                                         {
00404                                             //lets figure out which observation was hurting us...
00405                                             Matrix Si = m_S.i();
00406                                             int iReject = HyperDimSelect(m_Innov,m_S,Si);
00407                                             
00408                                             //now we need to figure out what observation that was
00409                                             //and set its bGoodDA to false!
00410                                             OBSLIST::iterator t;
00411                                             for(t = m_Observations.begin();t!=m_Observations.end();t++)
00412                                             {
00413                                                 if(t->m_bIgnore==false && t->m_nRow==iReject)
00414                                                 {
00415                                                     t->SetGoodDA(false);
00416                                                     MOOSTrace("Hyperdim Select removes obs %d \n",
00417                                                                 t->GetID());
00418                                                     t->Trace();
00419                                                     break;
00420                                                 }
00421                                             }
00422                                         }
00423                                     }                                    
00424                                 }
00425                                 catch(...)
00426                                 {
00427                                     AddToOutput("Trouble:EKF inversion failed!\n");
00428                                     MOOSMatrixTrace(m_jH,"H");
00429                                 }
00430                             }
00431                         }
00432                         m_nUpdates++;
00433                                                     
00434                         LogObservationSet((dfT1+dfT2)/2,
00435                             m_nUpdates);
00436 
00437                     }
00438                 }
00439             }
00440         }        
00441         
00442         OnIterateDone(dfTStop);
00443     }
00444     return true;
00445 }
00446 
00447 bool CMOOSNavEKFEngine::DoPredict(double dfDeltaT)
00448 {
00449     
00450     if(!PreparePredictionMatrices())
00451         return false;
00452     
00453     if(!m_pTracked->FillModelMatrices(m_jF,m_jQ,m_Xhat,dfDeltaT))
00454         return false;
00455     
00456     if(!FillGlobalParamModelMatrices(dfDeltaT))
00457         return false;
00458     
00460     //  KALMAN PREDICTION 
00461     //
00462     // note that in this simple case we have 
00463     // a linear model change this later
00464     //
00466     
00467     //    MOOSMatrixTrace(m_jF,"F");
00468     //    MOOSMatrixTrace(m_jQ,"Q");
00469     
00470     
00471     m_Xhat = m_jF*m_Xhat;
00472     m_Phat = m_jF*m_Phat*(m_jF.t()) + m_jQ;
00473     
00474     
00475     return true;
00476 }
00477 
00478 bool CMOOSNavEKFEngine::FillGlobalParamModelMatrices(double dfDeltaT)
00479 {
00480     //firstly do tide
00481     m_jF(TIDE_STATE_INDEX,TIDE_STATE_INDEX) = 1;
00482     m_jQ(TIDE_STATE_INDEX,TIDE_STATE_INDEX) = pow(2e-4,2); //noise on tide...~ 9m in 12 hours
00483     
00484     if(m_bEstimateHeadingBias)
00485     {
00486         //optionally do heading bias
00487         m_jF(HEADING_BIAS_STATE_INDEX,HEADING_BIAS_STATE_INDEX) = 1;
00488         m_jQ(HEADING_BIAS_STATE_INDEX,HEADING_BIAS_STATE_INDEX) = pow(m_dfYawBiasStd,2); 
00489     }
00490 
00491     return true;
00492 }
00493 
00494 
00495 bool CMOOSNavEKFEngine::Boot()
00496 {
00497     CMOOSNavVehicle * pVeh = dynamic_cast< CMOOSNavVehicle* > (m_pTracked);
00498     
00499     if(pVeh==NULL)
00500         return false;
00501     
00502     //set up vehcile mobility/dynamics..
00503     pVeh->SetDynamics(m_dfXYDynamics,m_dfZDynamics,m_dfYawDynamics);
00504     
00505     //set up initial conditions
00506     InitialiseEstimates();
00507     
00508     //start the clock
00509     m_dfLastUpdate = m_dfTimeNow;
00510     
00511     m_bBooted = true;
00512     
00513     return m_bBooted;
00514 }
00515 
00516 
00517 bool CMOOSNavEKFEngine::InitialiseEstimates()
00518 {
00519     
00520     m_Phat = 0;
00521     m_Xhat = 0;
00522     
00523     //do tide first
00524     m_Phat(TIDE_STATE_INDEX,TIDE_STATE_INDEX) = m_dfPTide0;
00525     m_Xhat(TIDE_STATE_INDEX,1) = m_dfTide0;
00526     
00527     
00528     
00529     
00530     m_pTracked->RefreshStateVector();
00531     
00532     m_pTracked->RefreshStateCovariance();
00533        
00534     
00535     return true;
00536 }
00537 
00538 bool CMOOSNavEKFEngine::IsBooted()
00539 {
00540     return m_bBooted;
00541 }
00542 
00543 bool CMOOSNavEKFEngine::PreparePredictionMatrices()
00544 {
00545     if(m_jF.Nrows()!=m_Xhat.Nrows() || m_jF.Ncols()!=m_Xhat.Nrows())
00546     {
00547         m_jF.ReSize(m_Xhat.Nrows(),m_Xhat.Nrows());
00548     }
00549     
00550     if(m_jQ.Nrows()!=m_Xhat.Nrows() || m_jQ.Ncols()!=m_Xhat.Nrows())
00551     {
00552         m_jQ.ReSize(m_Xhat.Nrows(),m_Xhat.Nrows());
00553     }
00554     
00555     //zero all matrices before we start
00556     m_jQ = 0;
00557     m_jF = 0;
00558     
00559     return true;
00560 }
00561 
00562 bool CMOOSNavEKFEngine::OnIterateDone(double dfUpdateTime)
00563 {
00564     //remeber our success!
00565     m_dfLastUpdate = dfUpdateTime;
00566     
00567     //limit velocities
00568     LimitVelocityStates();
00569     
00570     //look after PI
00571     WrapAngleStates();
00572     
00573     MakeSymmetric();
00574     
00575     //copy estimates 
00576     m_XTmp = m_Xhat;
00577     m_PTmp = m_Phat;
00578     
00579     
00580     //predict forwards
00581     PredictForward(dfUpdateTime,m_dfTimeNow);
00582     
00583     //we won;t predict the covariance forwads for siplay purposes
00584     m_Phat = m_PTmp;
00585     
00586     //look after PI
00587     WrapAngleStates();
00588     
00589     if(m_pTracked->RefreshState())
00590     {
00591         m_nIterations++;
00592         PublishResults();
00593         
00594         m_Logger.LogState(m_dfTimeNow,m_Xhat,m_Phat);
00595     }
00596     
00597     //copy estimate back (things went really well we want to
00598     //keep our results...
00599     m_Xhat = m_XTmp;
00600 
00601 
00602     //now we keep statistics on observations
00603     
00604     
00605     
00606     return true;
00607 }
00608 
00609 bool CMOOSNavEKFEngine::PublishResults()
00610 {
00611     //MOOSMatrixTrace(m_Phat,"PHat");
00612 
00613 //    TraceDiagPhat();
00614 
00615     //Ok so lets make some results..
00616     CMOOSMsg MsgX(MOOS_NOTIFY,"EKF_X", m_pTracked->m_State.m_dfX,m_dfTimeNow);
00617     m_ResultsList.push_front(MsgX);
00618     
00619     CMOOSMsg MsgY(MOOS_NOTIFY,"EKF_Y", m_pTracked->m_State.m_dfY,m_dfTimeNow);
00620     m_ResultsList.push_front(MsgY);
00621     
00622     CMOOSMsg MsgZ(MOOS_NOTIFY,"EKF_Z", m_pTracked->m_State.m_dfZ,m_dfTimeNow);
00623     m_ResultsList.push_front(MsgZ);
00624     
00625     CMOOSMsg MsgYaw(MOOS_NOTIFY,"EKF_YAW", m_pTracked->m_State.m_dfH,m_dfTimeNow);
00626     m_ResultsList.push_front(MsgYaw);
00627     
00628     CMOOSMsg MsgDepth(MOOS_NOTIFY,"EKF_DEPTH", m_pTracked->m_State.m_dfDepth,m_dfTimeNow);
00629     m_ResultsList.push_front(MsgDepth);
00630     
00631     CMOOSMsg MsgTide(MOOS_NOTIFY,"EKF_TIDE", m_Xhat(TIDE_STATE_INDEX,1),m_dfTimeNow);
00632     m_ResultsList.push_front(MsgTide);
00633     
00634     if(m_pTracked->GetEntityType()==CMOOSNavEntity::POSE_AND_RATE)
00635     {
00636         CMOOSMsg MsgX(MOOS_NOTIFY,"EKF_X_VEL", m_pTracked->m_State.m_dfXdot,m_dfTimeNow);
00637         m_ResultsList.push_front(MsgX);
00638         
00639         CMOOSMsg MsgY(MOOS_NOTIFY,"EKF_Y_VEL", m_pTracked->m_State.m_dfYdot,m_dfTimeNow);
00640         m_ResultsList.push_front(MsgY);
00641         
00642         CMOOSMsg MsgZ(MOOS_NOTIFY,"EKF_Z_VEL", m_pTracked->m_State.m_dfZdot,m_dfTimeNow);
00643         m_ResultsList.push_front(MsgZ);
00644         
00645         CMOOSMsg MsgYaw(MOOS_NOTIFY,"EKF_YAW_VEL", m_pTracked->m_State.m_dfHdot,m_dfTimeNow);
00646         m_ResultsList.push_front(MsgYaw);
00647         
00648         CMOOSMsg MsgSpeed(MOOS_NOTIFY,"EKF_SPEED", m_pTracked->m_State.m_dfSpeed,m_dfTimeNow);
00649         m_ResultsList.push_front(MsgSpeed);
00650         
00651     }
00652 
00653     //have we been estiamting bias on heading?
00654     if(this->m_bEstimateHeadingBias)
00655     {
00656         CMOOSMsg MsgBias(MOOS_NOTIFY,"EKF_YAW_BIAS", m_Xhat(HEADING_BIAS_STATE_INDEX,1),m_dfTimeNow);
00657         m_ResultsList.push_front(MsgBias);
00658         
00659     }
00660     
00661     
00662     string sCov = MOOSFormat("SigmaX = %f SigmaY = %f",
00663         sqrt(m_pTracked->m_State.m_dfPX),
00664         sqrt(m_pTracked->m_State.m_dfPY));
00665     
00666     CMOOSMsg MsgCov(MOOS_NOTIFY,"EKF_SIGMA",sCov.c_str(),m_dfTimeNow);
00667     m_ResultsList.push_front(MsgCov);
00668 
00669     DoObservationStatistics();
00670     
00671     if(m_nIterations%100==0)
00672     {
00673         string sResult = MOOSFormat("EKF Completes iteration %d",m_nIterations);
00674         AddToOutput(sResult);
00675 
00676         DoObservationSummary();
00677     }
00678     
00679 
00680 
00681     return true;
00682 }
00683 
00684 bool CMOOSNavEKFEngine::PredictForward(double dfStop, double dfTimeNow)
00685 {
00686     //so have stopped at time dfStop but want a result at time dfTimeNow
00687     //->Forward Predict
00688     double dfDT = dfTimeNow-dfStop;
00689     
00690     //MOOSTrace("Forward Predicting by %7.2f seconds:\n",dfDT); 
00691     
00692     return DoPredict(dfDT);
00693     
00694 }
00695 
00696 bool CMOOSNavEKFEngine::MakeSymmetric()
00697 {
00698     for(int i = 1;i<m_Phat.Nrows();i++)
00699     {
00700         for(int j = i;j<m_Phat.Nrows();j++)
00701         {
00702             m_Phat(i,j) = m_Phat(j,i);
00703         }
00704     }
00705     
00706     return true;
00707 }
00708 
00709 bool CMOOSNavEKFEngine::Reset()
00710 {
00711     
00712     m_bBooted = false;
00713     
00714     //try to reboot....
00715     Boot();
00716     
00717     if(m_bBooted)
00718     {
00719         AddToOutput("EKF Reset: OK");
00720     }
00721     else
00722     {
00723         AddToOutput("EKF Reset: FAILED");
00724     }
00725     
00726     return m_bBooted;
00727 }
00728 
00729 bool CMOOSNavEKFEngine::LimitVelocityStates()
00730 {
00731     
00732     
00733     if(m_pTracked->GetEntityType()==CMOOSNavEntity::POSE_AND_RATE)
00734     {
00735         double dfXdot = (*m_pTracked->m_pXhat)(m_pTracked->m_nStart+iiXdot,1);
00736         if(fabs(dfXdot)>MAX_ALLOWED_LIN_VELOCITY)
00737         {
00738             AddToOutput("EKF X Vel is too large (divergence?)-> resetting");
00739             (*m_pTracked->m_pXhat)(m_pTracked->m_nStart+iiXdot,1)=0;
00740         }
00741         
00742         double dfYdot = (*m_pTracked->m_pXhat)(m_pTracked->m_nStart+iiYdot,1);
00743         if(fabs(dfYdot)>MAX_ALLOWED_LIN_VELOCITY)
00744         {
00745             AddToOutput("EKF Y Vel is too large (divergence?)-> resetting");
00746             (*m_pTracked->m_pXhat)(m_pTracked->m_nStart+iiYdot,1)=0;
00747         }
00748         
00749         double dfZdot = (*m_pTracked->m_pXhat)(m_pTracked->m_nStart+iiZdot,1);
00750         if(fabs(dfZdot)>m_dfMaxZVel)
00751         {
00752             if(m_dfMaxZVel>0)
00753             {
00754                 AddToOutput("EKF Z Vel is too large (divergence?)-> resetting");
00755             }
00756             (*m_pTracked->m_pXhat)(m_pTracked->m_nStart+iiZdot,1)=0;
00757         }
00758         
00759         double dfHdot = (*m_pTracked->m_pXhat)(m_pTracked->m_nStart+iiHdot,1);
00760         if(fabs(dfHdot)>MAX_ALLOWED_ANG_VELOCITY)
00761         {
00762             AddToOutput("EKF YAW Vel is too large (divergence?)-> resetting");
00763             (*m_pTracked->m_pXhat)(m_pTracked->m_nStart+iiHdot,1)=0;
00764         }
00765         
00766     }
00767     
00768     return true;
00769 }
00770 
00771 
00778 int  CMOOSNavEKFEngine::HyperDimSelect(Matrix & Innov,Matrix & Cov,Matrix & InvCov)
00779 {
00780     int nDimension = Innov.Nrows();
00781     
00782     Matrix    ZUpper    = Innov;
00783     Matrix    ZLower    = Innov;
00784     ZLower    = 0.0;
00785     Matrix    ZTmp    = ZLower;
00786     
00787     //make sure Zupper is outside
00788     if(IsInside(ZUpper,InvCov))
00789     {
00790         return -1;
00791     }
00792     
00793     
00794     
00795     Matrix  Tmp        = (ZUpper-ZLower);
00796     Matrix    Tmp2    = Tmp.t()*Tmp;
00797     double Dist = sqrt(Tmp2(1,1));
00798     
00799     int nIt = 0;
00800     while(Dist>0.04)
00801     {
00802         ZTmp = (ZUpper+ ZLower)/2;
00803         
00804         if(IsInside(ZTmp,InvCov))
00805         {
00806             ZLower = ZTmp;
00807         }
00808         else
00809         {
00810             ZUpper = ZTmp;
00811         }
00812         
00813         //vector between bracing solutions
00814         Tmp = (ZUpper-ZLower);
00815         Tmp2 = Tmp.t()*Tmp;
00816         
00817         //length of vector
00818         Dist = sqrt(Tmp2(1,1));
00819         
00820         if(++nIt>1000)
00821         {
00822             return -1;
00823         }
00824         
00825     }
00826     
00828     //
00829     //    OK so ZTmp is now the intersection of
00830     //    the hyper ellpsoid with the innovation vector
00831     //    find the maximum component ratios
00832     //
00833     
00834     
00835     double MaxRatio =0.0;
00836     int        iReject = -1;
00837     for(int i = 1; i<=nDimension;i++)
00838     {
00839         double dfTmp =fabs((Innov(i,1)-ZTmp(i,1))/Cov(i,i));
00840         
00841         if(dfTmp>=MaxRatio)
00842         {
00843             MaxRatio = dfTmp;
00844             //this obs to be rejected..
00845             iReject = i;
00846         }
00847     }
00848     
00849     
00850     return iReject;
00851     
00852 }
00854 bool CMOOSNavEKFEngine::IsInside(Matrix &v, Matrix &Ellipse)
00855 {
00856     Matrix Tmp = v.t()*Ellipse*v;
00857     if(Tmp(1,1) <1.0)
00858         return true;
00859     else
00860         return false;
00861 }
00862 
00863 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines