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 // 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 }