MOOS 0.2375
|
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