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 // MOOSNavEngine.cpp: implementation of the CMOOSNavEngine class. 00032 // 00034 #ifdef _WIN32 00035 #pragma warning(disable : 4786) 00036 #endif 00037 00038 #include <MOOSGenLib/MOOSGenLib.h> 00039 #include "MOOSNavBeacon.h" 00040 #include "MOOSNavVehicle.h" 00041 #include "MOOSNavSensor.h" 00042 #include "MOOSNavObsStore.h" 00043 #include "MOOSNavEngine.h" 00044 #include "MOOSNavLibDefs.h" 00045 #include <sstream> 00046 #include <iomanip> 00047 #include "math.h" 00048 00050 // Construction/Destruction 00052 00053 //noises 00054 #define LBL_2WR_STD (2*0.0015) 00055 #define BODY_VEL_STD (0.02) 00056 00057 #define YAW_STD 0.001 00058 #define DEPTH_STD 0.1 00059 #define XY_STD 1.0 00060 00061 00062 CMOOSNavEngine::CMOOSNavEngine() 00063 { 00064 m_bInitialOnline = false; 00065 00066 00067 m_dfSV = 1500.0; 00068 00069 m_nNextID = 0; 00070 m_dfLastUpdate = 0; 00071 00072 //by defualt update as often as posisble 00073 m_dfUpdatePeriod = 0; 00074 00075 m_nIterations = 0; 00076 00077 //by default we make static vehciles 00078 m_eVehicleType = CMOOSNavEntity::POSE_ONLY; 00079 00080 m_bOnline = true; 00081 00082 m_bEnabled = true; 00083 00084 //by default we will not map thrust to velocity measurements 00085 m_bThrust2Vel = false; 00086 m_dfThrust2VelGain = 1.0; 00087 00088 //by default no heading bias state! 00089 m_bEstimateHeadingBias = false; 00090 00091 00092 //here we set the base class pointer to results mesage list to be our own 00093 //results list (lets CMOOSNavBase::addToOutput work 00094 00095 CMOOSNavBase::SetOutputList(&m_ResultsList); 00096 } 00097 00098 CMOOSNavEngine::~CMOOSNavEngine() 00099 { 00100 if(m_pStore!=NULL) 00101 delete m_pStore; 00102 } 00103 00104 bool CMOOSNavEngine::AddData(const CMOOSMsg &Msg) 00105 { 00106 //don't add data if not enabled 00107 if(!IsEnabled()) 00108 return true; 00109 00110 00111 // 1) convert to observation 00112 // 2) store it 00113 // 3) look to processes 00114 00115 OBSLIST NewObs; 00116 00117 if(DataToObservations(Msg,NewObs)) 00118 { 00119 return m_pStore->Add(NewObs); 00120 } 00121 return false; 00122 } 00123 00124 bool CMOOSNavEngine::DataToObservations(const CMOOSMsg &Msg, OBSLIST &ObsList) 00125 { 00126 CMOOSNavSensor * pRelevantSensor = GetSensorBySource(Msg.m_sSrc,Msg.m_sKey); 00127 00128 if(pRelevantSensor==NULL) 00129 { 00130 //no idea what to do with it... 00131 return false; 00132 } 00133 00134 bool bSuccess = false; 00135 switch(pRelevantSensor->m_eType) 00136 { 00137 case CMOOSNavSensor::LBL: 00138 bSuccess = MakeLBLObservations(Msg,ObsList); 00139 break; 00140 00141 case CMOOSNavSensor::DEPTH: 00142 bSuccess = MakeDepthObservations(Msg,ObsList); 00143 break; 00144 00145 case CMOOSNavSensor::XY: 00146 bSuccess = MakeXYObservations(Msg,ObsList); 00147 break; 00148 00149 case CMOOSNavSensor::BODY_VEL: 00150 bSuccess = MakeBodyVelObservations(Msg,ObsList); 00151 break; 00152 00153 case CMOOSNavSensor::CONTROL: 00154 bSuccess = MakeControlObservations(Msg,ObsList); 00155 break; 00156 00157 00158 case CMOOSNavSensor::ORIENTATION: 00159 //for now we only deal with yaw 00160 if(Msg.m_sKey.find("YAW")!=string::npos) 00161 { 00162 bSuccess = MakeYawObservations(Msg,ObsList); 00163 } 00164 break; 00165 00166 default: 00167 break; 00168 } 00169 00170 00171 00172 OBSLIST::iterator p; 00173 00174 for(p = ObsList.begin();p!=ObsList.end();p++) 00175 { 00176 //observations may need to know if they are 00177 // using heading bias estimation 00178 p->UsingHeadingBias(m_bEstimateHeadingBias); 00179 } 00180 00181 return bSuccess; 00182 } 00183 00184 00185 CMOOSSensorChannel * CMOOSNavEngine::GetSensorChannel(const string & sKey) 00186 { 00187 SOURCE_SENSORCHANNEL_MAP::iterator q = m_SensorChannelMap.find(sKey); 00188 00189 if(q==m_SensorChannelMap.end() || m_SensorChannelMap.empty()) 00190 { 00191 //must be made from mission file 00192 return NULL; 00193 } 00194 00195 return &(q->second); 00196 } 00197 00198 00199 00200 bool CMOOSNavEngine::MakeDepthObservations(const CMOOSMsg &Msg, OBSLIST &ObsList) 00201 { 00202 CMOOSObservation NewObs; 00203 NewObs.m_dfTime = Msg.m_dfTime; 00204 NewObs.m_dfData = Msg.m_dfVal; 00205 NewObs.m_dfDataStd = DEPTH_STD; 00206 00207 NewObs.m_eType = CMOOSObservation::DEPTH; 00208 NewObs.m_nID = GetNextID(); 00209 00210 //use the message source to figure out the sensor this 00211 //corresponds to 00212 NewObs.m_pInterrogateSensor = GetSensorBySource(Msg.m_sSrc,Msg.m_sKey); 00213 00214 if(NewObs.m_pInterrogateSensor!=NULL) 00215 { 00216 //overload noise 00217 if(NewObs.m_pInterrogateSensor->GetNoise()>=0) 00218 { 00219 NewObs.m_dfDataStd = NewObs.m_pInterrogateSensor->GetNoise(); 00220 } 00221 00222 ObsList.push_front(NewObs); 00223 } 00224 00225 return true; 00226 } 00227 00228 bool CMOOSNavEngine::MakeXYObservations(const CMOOSMsg &Msg, OBSLIST &ObsList) 00229 { 00230 CMOOSObservation NewObs; 00231 NewObs.m_dfTime = Msg.m_dfTime; 00232 NewObs.m_dfData = Msg.m_dfVal; 00233 NewObs.m_dfDataStd = XY_STD; 00234 00235 if(Msg.m_sKey.find("_X")!=string::npos) 00236 { 00237 NewObs.m_eType = CMOOSObservation::X; 00238 } 00239 if(Msg.m_sKey.find("_Y")!=string::npos) 00240 { 00241 NewObs.m_eType = CMOOSObservation::Y; 00242 } 00243 00244 NewObs.m_nID = GetNextID(); 00245 00246 //use the message source to figure out the sensor this 00247 //corresponds to 00248 NewObs.m_pInterrogateSensor = GetSensorBySource(Msg.m_sSrc,Msg.m_sKey); 00249 00250 if(NewObs.m_pInterrogateSensor!=NULL) 00251 { 00252 //overload noise 00253 if(NewObs.m_pInterrogateSensor->GetNoise()>=0) 00254 { 00255 NewObs.m_dfDataStd = NewObs.m_pInterrogateSensor->GetNoise(); 00256 } 00257 00258 ObsList.push_front(NewObs); 00259 } 00260 return true; 00261 00262 } 00263 00264 bool CMOOSNavEngine::MakeControlObservations(const CMOOSMsg &Msg, OBSLIST &ObsList) 00265 { 00266 if(Msg.m_sKey.find("_THRUST")!=string::npos) 00267 { 00268 //do we wnat to use thrust measurements? 00269 if(!m_bThrust2Vel) 00270 return true; 00271 00272 CMOOSMsg MappedMsg = Msg; 00273 00274 //dilute the precision of this.. 00275 double dfObsDilation = 4; 00276 //make a message for the y (forward velocity) 00277 MappedMsg.m_dfVal*= m_dfThrust2VelGain; 00278 MappedMsg.m_sKey="THRUST_DERIVED_BODY_VEL_Y"; 00279 if(!MakeBodyVelObservations(MappedMsg,ObsList,dfObsDilation)) 00280 return false; 00281 00282 //make a message for the x (Lateral velocity) 00283 MappedMsg.m_dfVal= 0; 00284 MappedMsg.m_sKey="THRUST_DERIVED_BODY_VEL_X"; 00285 if(!MakeBodyVelObservations(MappedMsg,ObsList,dfObsDilation)) 00286 return false; 00287 } 00288 00289 return true; 00290 00291 } 00292 00293 00294 bool CMOOSNavEngine::MakeBodyVelObservations(const CMOOSMsg &Msg, OBSLIST &ObsList,double dfSF) 00295 { 00296 CMOOSObservation NewObs; 00297 NewObs.m_dfTime = Msg.m_dfTime; 00298 NewObs.m_dfData = Msg.m_dfVal; 00299 NewObs.m_dfDataStd = BODY_VEL_STD*dfSF; 00300 00301 if(Msg.m_sKey.find("_Y")!=string::npos) 00302 { 00303 NewObs.m_eType = CMOOSObservation::BODY_VEL_Y; 00304 } 00305 else if(Msg.m_sKey.find("_X")!=string::npos) 00306 { 00307 NewObs.m_eType = CMOOSObservation::BODY_VEL_X; 00308 } 00309 00310 NewObs.m_nID = GetNextID(); 00311 00312 //use the message source to figure out the sensor this 00313 //corresponds to 00314 NewObs.m_pInterrogateSensor = GetSensorBySource(Msg.m_sSrc,Msg.m_sKey); 00315 00316 if(NewObs.m_pInterrogateSensor!=NULL) 00317 { 00318 //overload noise 00319 if(NewObs.m_pInterrogateSensor->GetNoise()>=0) 00320 { 00321 NewObs.m_dfDataStd = NewObs.m_pInterrogateSensor->GetNoise(); 00322 } 00323 00324 ObsList.push_front(NewObs); 00325 } 00326 return true; 00327 00328 } 00329 00330 00331 bool CMOOSNavEngine::MakeYawObservations(const CMOOSMsg &Msg, OBSLIST &ObsList) 00332 { 00333 CMOOSObservation NewObs; 00334 NewObs.m_dfTime = Msg.m_dfTime; 00335 NewObs.m_dfData = Msg.m_dfVal; 00336 NewObs.m_dfDataStd = YAW_STD; 00337 NewObs.m_eType = CMOOSObservation::YAW; 00338 NewObs.m_nID = GetNextID(); 00339 00340 00341 00342 //use the message source to figure out the sensor this 00343 //corresponds to 00344 NewObs.m_pInterrogateSensor = GetSensorBySource(Msg.m_sSrc,Msg.m_sKey); 00345 00346 if(NewObs.m_pInterrogateSensor!=NULL) 00347 { 00348 00349 //overload noise 00350 if(NewObs.m_pInterrogateSensor->GetNoise()>=0) 00351 { 00352 NewObs.m_dfDataStd = NewObs.m_pInterrogateSensor->GetNoise(); 00353 } 00354 00355 ObsList.push_front(NewObs); 00356 } 00357 00358 ObsList.push_front(NewObs); 00359 00360 return true; 00361 } 00362 00363 00364 bool CMOOSNavEngine::MakeLBLObservations(const CMOOSMsg &Msg, OBSLIST &ObsList) 00365 { 00366 //this is LBL data 00367 string sData = Msg.m_sVal; 00368 00369 //what time was interrogation sent? 00370 MOOSChomp(sData,"Tx="); 00371 double dfTxTime = atof(MOOSChomp(sData,",").c_str()); 00372 00373 if(dfTxTime<=0) 00374 { 00375 MOOSTrace("Tx time of LBL is not positive\n"); 00376 return false; 00377 } 00378 00379 while(!sData.empty()) 00380 { 00381 //for each reply... 00382 CMOOSObservation NewObs; 00383 string sChunk = MOOSChomp(sData,","); 00384 00385 MOOSChomp(sChunk,"Ch["); 00386 00387 int nChan = atoi(sChunk.c_str()); 00388 00389 if(nChan<=0 || nChan > 14) 00390 { 00391 MOOSTrace("Channel of LBL obs is not valid\n"); 00392 continue; 00393 } 00394 00395 00396 NewObs.m_nChan = nChan; 00397 00398 //figure out the beacon from the channel.... 00399 CMOOSNavBeacon * pBeacon = GetBeaconByChannel(nChan); 00400 00401 if(pBeacon==NULL) 00402 { 00403 MOOSTrace("Warning: No known Beacon with Channel[%d]\n",nChan); 00404 } 00405 00406 00407 00408 //so what was the observation - the TOF? 00409 MOOSChomp(sChunk,"="); 00410 double dfTOF = atof(sChunk.c_str()); 00411 if(dfTOF<=0) 00412 { 00413 MOOSTrace("TOF of LBL obs is not valid\n"); 00414 return false; 00415 } 00416 NewObs.m_dfData = dfTOF; 00417 00418 00419 //set obs time Tx Time plus in water time 00420 NewObs.m_dfTime = dfTxTime+dfTOF; 00421 00422 // MOOSTrace("Making LBL Obs.dfTime = %f and now = %f\n",NewObs.m_dfTime,MOOSTime()); 00423 00424 //set obs type 00425 NewObs.m_eType = CMOOSObservation::LBL_BEACON_2WR; 00426 00427 //give it a unique id 00428 NewObs.m_nID = GetNextID(); 00429 00430 00431 //use the message source to figure out the sensor this 00432 //corresponds to 00433 NewObs.m_pInterrogateSensor = GetSensorBySource(Msg.m_sSrc,Msg.m_sKey); 00434 00435 if(NewObs.m_pInterrogateSensor==NULL) 00436 { 00437 return false; 00438 } 00439 00440 //set observation noise 00441 NewObs.m_dfDataStd = LBL_2WR_STD; 00442 if(NewObs.m_pInterrogateSensor->GetNoise()>=0) 00443 { 00444 NewObs.m_dfDataStd = NewObs.m_pInterrogateSensor->GetNoise(); 00445 } 00446 00447 //what other responding sensor was involved? 00448 if(pBeacon!=NULL) 00449 { 00450 NewObs.m_pRespondingSensor = pBeacon->GetSensorByType(CMOOSNavSensor::LBL); 00451 } 00452 else 00453 { 00454 NewObs.m_pRespondingSensor=NULL; 00455 } 00456 00457 00458 //this is an acoustic obs so set the sound velocity 00459 NewObs.m_dfSV = m_dfSV; 00460 //finally add the obs to the list 00461 if(NewObs.m_pRespondingSensor!=NULL) 00462 { 00463 ObsList.push_back(NewObs); 00464 } 00465 00466 /* MOOSTrace("NewLBL: MOOSTime = %.3f,msgtime= %.3f,datatime = %.3f,TxTime = %.3f, cTOF= %.3f\n", 00467 MOOSTime(), 00468 Msg.m_dfTime, 00469 NewObs.m_dfTime, 00470 dfTxTime, 00471 NewObs.m_dfTime-dfTxTime);*/ 00472 00473 } 00474 00475 return true; 00476 } 00477 00478 CMOOSNavBeacon * CMOOSNavEngine::GetBeaconByName(const string & sName) 00479 { 00480 BEACONLIST::iterator p; 00481 00482 for(p = m_Beacons.begin();p!=m_Beacons.end();p++) 00483 { 00484 00485 CMOOSNavBeacon * pBcn = *p; 00486 00487 if(pBcn->m_sName==sName) 00488 { 00489 return pBcn; 00490 } 00491 } 00492 return NULL; 00493 } 00494 00495 CMOOSNavBeacon * CMOOSNavEngine::GetBeaconByChannel(int nChannel) 00496 { 00497 BEACONLIST::iterator p; 00498 00499 for(p = m_Beacons.begin();p!=m_Beacons.end();p++) 00500 { 00501 00502 CMOOSNavBeacon * pBcn = *p; 00503 00504 if(pBcn->m_nChan==nChannel) 00505 { 00506 return pBcn; 00507 } 00508 } 00509 return NULL; 00510 } 00511 00512 00513 bool CMOOSNavEngine::Iterate(double dfTimeNow) 00514 { 00515 return false; 00516 } 00517 00518 00519 bool CMOOSNavEngine::Initialise(STRING_LIST sParams) 00520 { 00521 00522 //make a store for observations.. 00523 m_pStore = new CMOOSNavObsStore; 00524 00525 //we may be being asked to map thrust to velocity 00526 string sVal; 00527 if(MOOSGetValueFromToken(sParams,"THRUST2VELOCITY",sVal)) 00528 { 00529 if(MOOSStrCmp(sVal,"TRUE")) 00530 { 00531 if(MOOSGetValueFromToken(sParams,"THRUST2VELOCITY_GAIN",sVal)) 00532 { 00533 m_bThrust2Vel = true; 00534 m_dfThrust2VelGain = atof(sVal.c_str()); 00535 } 00536 } 00537 } 00538 00539 00540 00541 if(MOOSGetValueFromToken(sParams,"SV",sVal)) 00542 { 00543 double dfNewSV = atof(sVal.c_str()); 00544 if(dfNewSV !=0) 00545 { 00546 m_dfSV=dfNewSV; 00547 } 00548 } 00549 00550 //set up navigation filter logging.... 00551 bool bLog = false; 00552 if(MOOSGetValueFromToken(sParams,"NAV_LOG",sVal)) 00553 { 00554 bLog = MOOSStrCmp(sVal,"TRUE"); 00555 } 00556 if(bLog) 00557 { 00558 string sPath=""; 00559 00560 //do we have a globally defined path? 00561 CProcessConfigReader Reader; 00562 Reader.SetFile(m_sMissionFileName); 00563 00564 if(!Reader.GetValue("GLOBALLOGPATH",sPath)) 00565 { 00566 //no..get it locally 00567 MOOSGetValueFromToken(sParams,"NAV_LOG_PATH",sPath); 00568 } 00569 bool bTimeStamp=false; 00570 if(MOOSGetValueFromToken(sParams,"NAV_LOG_TIMESTAMP",sVal)) 00571 { 00572 bTimeStamp = MOOSStrCmp(sVal,"TRUE"); 00573 } 00574 00575 00576 m_Logger.Initialise(m_sName,sPath,bTimeStamp); 00577 00578 00579 } 00580 00581 00582 00583 //Allocate Global states.. 00584 SetUpGlobalStates(); 00585 00586 AddTheVehicle(sParams); 00587 00588 //fixed observations are attached to the COG... 00589 AddSensor("FIXED","COG", CMOOSNavSensor::FIXED,0,0,0); 00590 00591 //set our default start up state... 00592 //set in constructor of derived classes 00593 SetOnline(m_bInitialOnline); 00594 return true; 00595 00596 } 00597 00598 00599 bool CMOOSNavEngine::AddEntity(CMOOSNavEntity *pEntity, 00600 Matrix * pCovariance, 00601 Matrix * pCrossCovariance) 00602 { 00603 Matrix XNew; 00604 00605 //we always give entities a pinter to the global estimate 00606 //matrices 00607 00608 pEntity->m_pXhat = & m_Xhat; 00609 pEntity->m_pPhat = & m_Phat; 00610 00611 00612 //get the entity to format a state vector representing 00613 //its state 00614 if(pEntity->GetFullState(XNew,NULL,false)) 00615 { 00616 //XNew will be 8x1 but what are the estimated states? 00617 int nSize = pEntity->GetStateSize(); 00618 00619 if(nSize==0) 00620 { 00621 //its not in the state vector (eg a beaon) 00622 return true; 00623 } 00624 00625 00626 pEntity->m_nStart = m_Xhat.Nrows()+1; 00627 pEntity->m_nEnd = pEntity->m_nStart+nSize-1; 00628 00629 if(m_Xhat.Nrows()==0 || m_Xhat.Ncols() ==0) 00630 { 00631 m_Xhat = XNew.SubMatrix(1,nSize,1,1); 00632 m_Phat.ReSize(nSize,nSize); 00633 m_XhatTmp = m_Xhat; 00634 m_PhatTmp = m_Phat; 00635 00636 } 00637 else 00638 { 00639 m_Xhat = m_Xhat & XNew.SubMatrix(1,nSize,1,1); 00640 00641 //now resize P.. 00642 Matrix OldP = m_Phat; 00643 m_Phat.ReSize(m_Xhat.Nrows(),m_Xhat.Nrows()); 00644 m_Phat=0; 00645 m_Phat.SubMatrix(1,OldP.Nrows(),1,OldP.Ncols()) = OldP; 00646 00647 00648 } 00649 00650 } 00651 00652 00653 return true; 00654 } 00655 00656 bool CMOOSNavEngine::IndexObservations(int &nObsDim) 00657 { 00658 00659 nObsDim = 0; 00660 00661 OBSLIST::iterator p; 00662 00663 for(p = m_Observations.begin();p!=m_Observations.end();p++) 00664 { 00665 CMOOSObservation & rObs = *p; 00666 00667 if(rObs.m_bIgnore || rObs.m_bGoodDA==false) 00668 continue; 00669 00670 rObs.m_nRow = nObsDim+1; 00671 00672 nObsDim+=rObs.GetDimension(); 00673 00674 } 00675 00676 return true; 00677 } 00678 00679 bool CMOOSNavEngine::TraceObservationSet() 00680 { 00681 OBSLIST::iterator p; 00682 int nIgnored=0; 00683 for(p = m_Observations.begin();p!=m_Observations.end();p++) 00684 { 00685 if(p->m_bIgnore) 00686 nIgnored++; 00687 } 00688 00689 00690 MOOSTrace("\n %s Working with %d observations (%d ignored):\n", 00691 m_sName.c_str(), 00692 m_Observations.size()-nIgnored,nIgnored); 00693 00694 00695 int i = 1; 00696 for(p = m_Observations.begin();p!=m_Observations.end();p++) 00697 { 00698 if(p->m_bIgnore) 00699 continue; 00700 00701 MOOSTrace("%d)\t",i++); 00702 p->Trace(); 00703 } 00704 00705 return true; 00706 } 00707 00708 bool CMOOSNavEngine::AddSensor(const string & sSource, 00709 const string &sName, 00710 CMOOSNavSensor::Type eType, 00711 double dfX, 00712 double dfY, 00713 double dfZ, 00714 double dfNoise) 00715 { 00717 // add an new sensor 00718 CMOOSNavSensor * pNewSensor = new CMOOSNavSensor; 00719 pNewSensor->m_nID = GetNextID(); 00720 pNewSensor->m_sName=sName; 00721 pNewSensor->m_eType = eType; 00722 pNewSensor->m_sMOOSSource = sSource; 00723 pNewSensor->SetNoise(dfNoise); 00724 if(m_pTracked!=NULL) 00725 { 00726 m_pTracked->AddSensor(pNewSensor); 00727 00728 string sKey = sSource+":"+sName; 00729 if(m_SourceToSensorMap.find(sName)==m_SourceToSensorMap.end()) 00730 { 00731 m_SourceToSensorMap[sKey] = pNewSensor; 00732 MOOSTrace("Added new sensor:\n\t\"%s\" @ %f %f %f\n",sKey.c_str(),dfX,dfY,dfZ); 00733 00734 } 00735 else 00736 { 00737 MOOSTrace("Error Sensor \"%s\" already exists \n",sKey.c_str()); 00738 return false; 00739 } 00740 } 00741 else 00742 { 00743 return false; 00744 } 00745 00746 return true; 00747 } 00748 00749 bool CMOOSNavEngine::AddAcousticBeacon(const string & sName, 00750 int nChan, 00751 double dfTAT, 00752 double dfX, 00753 double dfY, 00754 double dfZ) 00755 { 00756 00758 // add a beacon 00759 CMOOSNavBeacon* pBeacon = new CMOOSNavBeacon; 00760 00761 pBeacon->m_sName = sName; 00762 pBeacon->m_nID = GetNextID(); 00763 00764 pBeacon->m_State.m_dfX = dfX; 00765 pBeacon->m_State.m_dfY = dfY; 00766 pBeacon->m_State.m_dfZ = dfZ; 00767 00768 pBeacon->m_dfTAT = dfTAT; 00769 pBeacon->m_nChan = nChan; 00770 00771 if(AddEntity(pBeacon)) 00772 { 00773 // MOOSTrace("Added Beacon :\n\t"); 00774 // pBeacon->Trace(); 00775 m_Beacons.push_front(pBeacon); 00776 } 00777 00778 return true; 00779 00780 } 00781 00782 00783 bool CMOOSNavEngine::AddFixedObservation(CMOOSObservation::Type eType, double dfVal, double dfStd) 00784 { 00785 CMOOSObservation NewFixedObs; 00786 00787 NewFixedObs.m_dfData = dfVal; 00788 NewFixedObs.m_dfDataStd = dfStd; 00789 NewFixedObs.m_eType = eType; 00790 NewFixedObs.m_nID = GetNextID(); 00791 NewFixedObs.m_dfTime = -1; 00792 NewFixedObs.SetFixed(true); 00793 NewFixedObs.UsingHeadingBias(m_bEstimateHeadingBias); 00794 00795 NewFixedObs.m_pInterrogateSensor = GetSensorByName("COG"); 00796 00797 if(NewFixedObs.m_pInterrogateSensor==NULL) 00798 { 00799 return false; 00800 } 00801 00802 m_FixedObservations.push_back(NewFixedObs); 00803 00804 return true; 00805 00806 } 00807 00808 CMOOSNavSensor* CMOOSNavEngine::GetSensorByName(const string &sSensorName) 00809 { 00810 SENSOR_MAP::iterator p; 00811 for(p = m_SourceToSensorMap.begin();p!=m_SourceToSensorMap.end();p++) 00812 { 00813 CMOOSNavSensor * pSensor = p->second; 00814 if(pSensor->GetName()==sSensorName) 00815 { 00816 return pSensor; 00817 } 00818 00819 } 00820 return NULL; 00821 00822 } 00823 00824 00825 CMOOSNavSensor* CMOOSNavEngine::GetSensorBySource(const string &sMOOSSource,const string & sDataName) 00826 { 00827 SENSOR_MAP::iterator p; 00828 00829 CMOOSNavSensor::Type eType = SensorTypeFromDataName(sDataName); 00830 00831 if(eType==CMOOSNavSensor::INVALID) 00832 return NULL; 00833 00834 for(p = m_SourceToSensorMap.begin();p!=m_SourceToSensorMap.end();p++) 00835 { 00836 CMOOSNavSensor * pSensor = p->second; 00837 if(pSensor->m_eType==eType && pSensor->m_sMOOSSource==sMOOSSource) 00838 { 00839 return pSensor; 00840 } 00841 } 00842 return NULL; 00843 00844 } 00845 00846 // here we set aside space for global states such 00847 //as tide and heading bias estimation etc.. 00848 bool CMOOSNavEngine::SetUpGlobalStates() 00849 { 00850 int nGlobalStates = 1; //tide... 00851 00852 if(m_bEstimateHeadingBias) 00853 nGlobalStates = 2; //tide and heading bias 00854 00855 m_Xhat.ReSize(nGlobalStates,1); 00856 m_Xhat=0; 00857 m_Phat.ReSize(nGlobalStates,nGlobalStates); 00858 m_Phat = 0; 00859 00860 return true; 00861 } 00862 00863 //client calls this to fetch results... 00864 bool CMOOSNavEngine::GetNextResult(CMOOSMsg &ResultMsg) 00865 { 00866 if(m_ResultsList.empty()) 00867 { 00868 return false; 00869 } 00870 00871 ResultMsg = m_ResultsList.front(); 00872 m_ResultsList.pop_front(); 00873 00874 return true; 00875 } 00876 00877 bool CMOOSNavEngine::LimitObservations(CMOOSObservation::Type eType, int nNumber) 00878 { 00879 OBSLIST::iterator p; 00880 00881 int nFound = 0; 00882 for(p = m_Observations.begin();p!=m_Observations.end();p++) 00883 { 00884 if(p->m_eType==eType) 00885 { 00886 nFound++; 00887 if(nFound>nNumber) 00888 { 00889 p->m_bIgnore = true; 00890 } 00891 else 00892 { 00893 p->m_bIgnore = false; 00894 } 00895 } 00896 } 00897 00898 return true; 00899 } 00900 00901 bool CMOOSNavEngine::WrapAngleStates() 00902 { 00903 //wrap the state itself! 00904 int nStateNdx = m_pTracked->m_nStart+iiH; 00905 m_Xhat(nStateNdx,1) = MOOS_ANGLE_WRAP(m_Xhat(nStateNdx,1)); 00906 00907 if(m_pTracked->GetEntityType()==CMOOSNavEntity::POSE_AND_RATE) 00908 { 00909 nStateNdx = m_pTracked->m_nStart+iiHdot; 00910 m_Xhat(nStateNdx,1) = MOOS_ANGLE_WRAP(m_Xhat(nStateNdx,1)); 00911 } 00912 00913 00914 return true; 00915 } 00916 00917 bool CMOOSNavEngine::GuessVehicleLocation() 00918 { 00919 BEACONLIST::iterator q; 00920 double dfX=0; 00921 double dfY=0; 00922 double dfZ = 0; 00923 for(q=m_Beacons.begin();q!=m_Beacons.end();q++) 00924 { 00925 dfX+=(*q)->m_State.m_dfX; 00926 dfY+=(*q)->m_State.m_dfY; 00927 dfZ+=(*q)->m_State.m_dfZ; 00928 00929 } 00930 00931 dfX/=m_Beacons.size(); 00932 dfY/=m_Beacons.size(); 00933 dfZ/=m_Beacons.size(); 00934 00935 m_pTracked->m_State.m_dfX = dfX; 00936 m_pTracked->m_State.m_dfY = dfY; 00937 m_pTracked->m_State.m_dfZ = dfZ+10; 00938 00939 m_pTracked->RefreshStateVector(); 00940 00941 00942 MOOSTrace("Set Vehicle to [%7.3f %7.3f %7.3f]\n", 00943 m_pTracked->m_State.m_dfX, 00944 m_pTracked->m_State.m_dfY, 00945 m_pTracked->m_State.m_dfZ); 00946 00947 00948 return true; 00949 00950 } 00951 00952 00953 00954 00955 bool CMOOSNavEngine::GetTATByChannel(int nChannel, double &dfTAT) 00956 { 00957 CMOOSNavBeacon * pBcn = GetBeaconByChannel(nChannel); 00958 00959 if(pBcn) 00960 { 00961 dfTAT = pBcn->m_dfTAT; 00962 return true; 00963 } 00964 else 00965 { 00966 return false; 00967 } 00968 } 00969 00970 bool CMOOSNavEngine::AddTheVehicle(STRING_LIST &sParams) 00971 { 00973 // add the vehicle itself! 00974 // overide this function to make more complex vehicles 00975 m_pTracked = new CMOOSNavVehicle; 00976 m_pTracked->m_nID = GetNextID(); 00977 m_pTracked->m_sName="TheAUV"; 00978 m_pTracked->SetEntityType(m_eVehicleType); 00979 m_pTracked->m_State.m_dfZ = 0; 00980 return AddEntity(m_pTracked); 00981 } 00982 00983 00984 bool CMOOSNavEngine::MakeObsMatrices() 00985 { 00986 int nObsSize; 00987 00988 if(!IndexObservations(nObsSize)) 00989 return false; 00990 00991 int nStateSize = m_Xhat.Nrows(); 00992 00993 if(m_jH.Nrows()!=nObsSize || m_jH.Ncols() != nStateSize) 00994 { 00995 m_jH.ReSize(nObsSize,nStateSize); 00996 } 00997 00998 if(m_R.Nrows()!=nObsSize || m_R.Ncols() != nObsSize) 00999 { 01000 m_R.ReSize(nObsSize,nObsSize); 01001 } 01002 01003 if(m_Innov.Nrows()!=nObsSize || m_Innov.Ncols() != 1) 01004 { 01005 m_Innov.ReSize(nObsSize,1); 01006 } 01007 01008 //zero all.. 01009 m_jH=0; 01010 m_R=0; 01011 m_Innov = 0; 01012 01013 01014 OBSLIST::iterator p; 01015 01016 for(p = m_Observations.begin();p!=m_Observations.end();p++) 01017 { 01018 CMOOSObservation & rObs = *p; 01019 01020 if(rObs.m_bIgnore || rObs.m_bGoodDA==false) 01021 continue; 01022 01023 rObs.MakeMatrices(m_Innov,m_jH,m_R,m_Xhat); 01024 01025 } 01026 01027 01028 return true; 01029 } 01030 01031 bool CMOOSNavEngine::GetTrackedPosition(double &dfX, double &dfY, double &dfZ,double & dfH,double & dfLastUpdate) 01032 { 01033 m_pTracked->RefreshState(); 01034 dfX = m_pTracked->m_State.m_dfX; 01035 dfY = m_pTracked->m_State.m_dfY; 01036 dfZ = m_pTracked->m_State.m_dfZ; 01037 dfH = m_pTracked->m_State.m_dfH; 01038 01039 dfLastUpdate = m_dfLastUpdate; 01040 01041 return true; 01042 } 01043 01044 bool CMOOSNavEngine::GetTrackedUncertainty(double &dfPX, 01045 double &dfPY, 01046 double &dfPZ, 01047 double &dfPH) 01048 { 01049 m_pTracked->RefreshState(); 01050 dfPX = m_pTracked->m_State.m_dfPX; 01051 dfPY = m_pTracked->m_State.m_dfPY; 01052 dfPZ = m_pTracked->m_State.m_dfPZ; 01053 dfPH = m_pTracked->m_State.m_dfPH; 01054 01055 return true; 01056 } 01057 01058 01059 bool CMOOSNavEngine::ForceTrackedPosition(double dfX, double dfY, double dfZ, double dfH) 01060 { 01061 m_pTracked->m_State.m_dfX = dfX; 01062 m_pTracked->m_State.m_dfY = dfY; 01063 m_pTracked->m_State.m_dfZ = dfZ; 01064 m_pTracked->m_State.m_dfH = dfH; 01065 01066 m_pTracked->RefreshStateVector(); 01067 01068 AddToOutput("Forcing %s to [%.1f,%.1f,%.1f,%.1f]", 01069 m_sName.c_str(), 01070 dfX, 01071 dfY, 01072 dfZ, 01073 dfH); 01074 01075 01076 01077 01078 return true; 01079 01080 } 01081 01082 bool CMOOSNavEngine::LimitObservationTypes() 01083 { 01084 01085 if(m_pTracked->GetEntityType()==CMOOSNavEntity::POSE_ONLY) 01086 { 01087 set<CMOOSObservation::Type> Allowed; 01088 01089 Allowed.insert(CMOOSObservation::X); 01090 Allowed.insert(CMOOSObservation::Y); 01091 Allowed.insert(CMOOSObservation::YAW); 01092 Allowed.insert(CMOOSObservation::LBL_BEACON_2WR); 01093 Allowed.insert(CMOOSObservation::DEPTH); 01094 Allowed.insert(CMOOSObservation::TIDE); 01095 01096 if(m_bEstimateHeadingBias) 01097 { 01098 Allowed.insert(CMOOSObservation::HEADING_BIAS); 01099 } 01100 01101 01102 OBSLIST::iterator p; 01103 01104 for(p=m_Observations.begin();p!=m_Observations.end();p++) 01105 { 01106 CMOOSObservation & rObs = *p; 01107 if(Allowed.find(rObs.m_eType)==Allowed.end()) 01108 { 01109 rObs.Ignore(true); 01110 } 01111 } 01112 } 01113 01114 return true; 01115 } 01116 01117 bool CMOOSNavEngine::Reset() 01118 { 01119 return true; 01120 } 01121 01122 bool CMOOSNavEngine::IsOnline() 01123 { 01124 return m_bOnline; 01125 } 01126 01127 bool CMOOSNavEngine::SetOnline(bool bOnline) 01128 { 01129 if(m_bOnline==false && bOnline==true) 01130 { 01131 //reset cousnters when starting up 01132 m_nIterations = 0; 01133 } 01134 01135 m_bOnline = bOnline; 01136 01137 AddToOutput("%s is %s!",m_sName.c_str(),m_bOnline?"ONLINE":"OFFLINE"); 01138 01139 return true; 01140 } 01141 01142 int CMOOSNavEngine::GetIterations() 01143 { 01144 return m_nIterations; 01145 } 01146 01147 bool CMOOSNavEngine::Enable(bool bEnable) 01148 { 01149 m_bEnabled = bEnable; 01150 return true; 01151 } 01152 01153 bool CMOOSNavEngine::IsEnabled() 01154 { 01155 return m_bEnabled; 01156 } 01157 01158 double CMOOSNavEngine::GetYoungestDataTime() 01159 { 01160 return m_pStore->GetNewestObsTime(); 01161 } 01162 01163 bool CMOOSNavEngine::SetMissionFileName(const string &sFileName) 01164 { 01165 m_sMissionFileName = sFileName; 01166 return true; 01167 } 01168 01169 bool CMOOSNavEngine::MarkObservationsDA(bool bGoodDA) 01170 { 01171 OBSLIST::iterator p; 01172 for(p = m_Observations.begin();p!=m_Observations.end();p++) 01173 { 01174 CMOOSObservation & rObs = *p; 01175 01176 if(!rObs.m_bIgnore) 01177 { 01178 rObs.SetGoodDA(bGoodDA); 01179 } 01180 } 01181 01182 return true; 01183 } 01184 bool CMOOSNavEngine::LogObservationSet(double dfTimeNow, 01185 int nthUpdate) 01186 { 01187 OBSLIST::iterator p; 01188 for(p=m_Observations.begin();p!=m_Observations.end();p++) 01189 { 01190 CMOOSObservation & rObs = *p; 01191 01192 if(!rObs.m_bIgnore) 01193 { 01194 m_Logger.LogObservation(dfTimeNow,rObs,nthUpdate); 01195 } 01196 } 01197 01198 return true; 01199 } 01200 01201 bool CMOOSNavEngine::RecordObsStatistics(Matrix *pInnov, Matrix *pS) 01202 { 01203 if(pInnov==NULL) 01204 return true; 01205 01206 int nObs = pInnov->Nrows(); 01207 for(int i = 1;i<=nObs;i++) 01208 { 01209 OBSLIST::iterator t; 01210 for(t = m_Observations.begin();t!=m_Observations.end();t++) 01211 { 01212 if(t->m_bIgnore==false && t->m_nRow==i) 01213 { 01214 t->m_dfInnov = (*pInnov)(i,1); 01215 if(pS!=NULL) 01216 { 01217 t->m_dfInnovStd = sqrt((*pS)(i,i)); 01218 } 01219 } 01220 } 01221 } 01222 return true; 01223 } 01224 01225 bool CMOOSNavEngine::SetTimeStarted(double dfTime) 01226 { 01227 m_dfTimeStarted = dfTime; 01228 return true; 01229 } 01230 01231 01232 double CMOOSNavEngine::GetTimeStarted() 01233 { 01234 return m_dfTimeStarted; 01235 } 01236 01237 CMOOSNavSensor::Type CMOOSNavEngine::SensorTypeFromDataName(const string &sDataName) 01238 { 01239 if(sDataName.find("_YAW")!=string ::npos) 01240 return CMOOSNavSensor::ORIENTATION; 01241 01242 if(sDataName.find("_DEPTH")!=string ::npos) 01243 return CMOOSNavSensor::DEPTH; 01244 01245 if(sDataName.find("_BODY_VEL")!=string ::npos ) 01246 return CMOOSNavSensor::BODY_VEL; 01247 01248 if(sDataName.find("_X")!=string ::npos) 01249 return CMOOSNavSensor::XY; 01250 01251 if(sDataName.find("_Y")!=string ::npos) 01252 return CMOOSNavSensor::XY; 01253 01254 if(sDataName.find("_TOF")!=string ::npos) 01255 return CMOOSNavSensor::LBL; 01256 01257 01258 return CMOOSNavSensor::INVALID; 01259 } 01260 01261 bool CMOOSNavEngine::TraceDiagPhat() 01262 { 01263 01264 ostringstream os; 01265 01266 os.setf(ios::left); 01267 01268 os<<endl<<"********* COVARIANCE DUMP *************"<<endl; 01269 01270 os<<setw(15)<<"Tide Std = "<<sqrt(m_Phat(TIDE_STATE_INDEX,TIDE_STATE_INDEX))<<endl; 01271 01272 if(m_bEstimateHeadingBias) 01273 { 01274 os<<"YawBias Std= "<<sqrt(m_Phat(HEADING_BIAS_STATE_INDEX,HEADING_BIAS_STATE_INDEX))<<endl; 01275 } 01276 01277 int nOffset = m_pTracked->m_nStart; 01278 01279 os<<setw(15)<<"X Std= "<<sqrt(m_Phat(nOffset+iiX,nOffset+iiX))<<endl; 01280 os<<setw(15)<<"Y Std= "<<sqrt(m_Phat(nOffset+iiY,nOffset+iiY))<<endl; 01281 os<<setw(15)<<"Z Std= "<<sqrt(m_Phat(nOffset+iiZ,nOffset+iiZ))<<endl; 01282 os<<setw(15)<<"Yaw Std= "<<sqrt(m_Phat(nOffset+iiH,nOffset+iiH))<<endl; 01283 01284 01285 01286 if(m_pTracked->GetEntityType()==CMOOSNavEntity::POSE_AND_RATE) 01287 { 01288 01289 os<<setw(15)<<"XVel Std= "<<sqrt(m_Phat(nOffset+iiXdot,nOffset+iiXdot))<<endl; 01290 os<<setw(15)<<"YVel Std= "<<sqrt(m_Phat(nOffset+iiYdot,nOffset+iiYdot))<<endl; 01291 os<<setw(15)<<"ZVel Std= "<<sqrt(m_Phat(nOffset+iiZdot,nOffset+iiZdot))<<endl; 01292 os<<setw(15)<<"YawVel Std= "<<sqrt(m_Phat(nOffset+iiHdot,nOffset+iiHdot))<<endl; 01293 } 01294 01295 os<<ends; 01296 string sOut = os.str(); 01297 //os.rdbuf()->freeze(0); 01298 01299 MOOSTrace(sOut); 01300 return true; 01301 01302 } 01303 bool CMOOSNavEngine::SetUpSensorChannels(STRING_LIST sParams,string sToken) 01304 { 01305 01306 01307 //ok we need to load up rejection settings 01308 STRING_LIST::iterator p; 01309 01310 for(p = sParams.begin();p!=sParams.end();p++) 01311 { 01312 string sLine = *p; 01313 if(sLine.find(sToken)!=string::npos) 01314 { 01315 MOOSRemoveChars(sLine," \t"); 01316 MOOSChomp(sLine,"="); 01317 //LSQ_REJECTION = TheAvtrak : Reject = 3, History = 5,Fail = 0.001 01318 CMOOSSensorChannel NewChannel; 01319 01320 string sSensor = MOOSChomp(sLine,":"); 01321 string sHistory = MOOSChomp(sLine,","); 01322 string sFail = MOOSChomp(sLine,","); 01323 01324 MOOSChomp(sHistory,"="); 01325 MOOSChomp(sFail,"="); 01326 01327 01328 if(sFail.empty() ||sHistory.empty()) 01329 { 01330 MOOSTrace("error in %s line!\n",sToken.c_str()); 01331 return false; 01332 } 01333 01334 int nDepth = atoi(sHistory.c_str()); 01335 if(nDepth>0) 01336 { 01337 NewChannel.SetHistoryDepth(nDepth); 01338 } 01339 01340 01341 double dfFail = atof(sFail.c_str()); 01342 if(dfFail>0) 01343 { 01344 NewChannel.SetNoiseLimit(dfFail); 01345 } 01346 01347 NewChannel.SetName(sSensor); 01348 01349 m_SensorChannelMap[sSensor]=NewChannel; 01350 01351 } 01352 } 01353 01354 return true; 01355 } 01356 01357 bool CMOOSNavEngine::AddToHistory(CMOOSObservation & rObs) 01358 { 01359 01360 string sKey = rObs.GetName(); 01361 01362 //we now have a list of observations on this channel 01363 //with the most recent at the fromt of the list 01364 CMOOSSensorChannel * pChannel = GetSensorChannel(sKey); 01365 01366 pChannel->Add(rObs); 01367 01368 01369 return true; 01370 } 01371 01372 01373 bool CMOOSNavEngine::AgreesWithHistory(CMOOSObservation &rObs) 01374 { 01375 //figure out what acoustic trajectory we are talking about 01376 string sKey = rObs.GetName(); 01377 01378 CMOOSSensorChannel * pChannel = GetSensorChannel(sKey); 01379 01380 if(pChannel==NULL) 01381 { 01382 //we are not running trajectory filter on this sensor 01383 //so we suppose its OK - definately don't want to reject it 01384 //otherwise we are enforcing use of a sensor channel rejection 01385 //scheme! 01386 return true; 01387 } 01388 else 01389 { 01390 //ask the channel 01391 return pChannel->Agrees(rObs); 01392 } 01393 01394 01395 } 01396 01397 bool CMOOSNavEngine::PreFilterData() 01398 { 01399 OBSLIST::iterator p; 01400 01401 // TraceObservationSet(); 01402 01403 //firstly see if we are accpeting this kind of data 01404 LimitObservationTypes(); 01405 01406 01407 bool bSentProgress = false; 01408 for(p = m_Observations.begin();p!=m_Observations.end();p++) 01409 { 01410 01411 //from most recent to oldest.. 01412 CMOOSObservation & rObs = *p; 01413 01414 //if we have already been told not to use then we had better 01415 //not overide this decision 01416 if(rObs.m_bIgnore==true) 01417 { 01418 continue; 01419 } 01420 01421 //do we have filtering set up for this kind of data? 01422 CMOOSSensorChannel * pChannel =GetSensorChannel(rObs.GetName()); 01423 if(pChannel==NULL) 01424 { 01425 //no then we must use it! 01426 rObs.Ignore(false); 01427 continue; 01428 } 01429 01430 //if the observation is fixed or already marked for ignore 01431 //then don't use it 01432 if(!rObs.IsFixed() && rObs.m_bIgnore==false) 01433 { 01434 //add it to our history 01435 AddToHistory(rObs); 01436 01437 //does this observation line up with its own history 01438 if(!AgreesWithHistory(rObs)) 01439 { 01440 //maybe we are just starting up 01441 if(pChannel->IsOnline()) 01442 { 01443 //no we are online .... 01444 MOOSTrace("SensorChannel rejecting obs[%d] %s data = %f\n", 01445 rObs.m_nID, 01446 rObs.GetName().c_str(), 01447 rObs.m_dfData); 01448 01449 //pChannel->Trace(); 01450 } 01451 else 01452 { 01453 if(!bSentProgress && !pChannel->IsBuilt()) 01454 { 01455 SOURCE_SENSORCHANNEL_MAP::iterator q; 01456 for(q = m_SensorChannelMap.begin();q!=m_SensorChannelMap.end();q++) 01457 { 01458 CMOOSSensorChannel & rLocalChannel = q->second; 01459 01460 if(rLocalChannel.GetPercentFull()>0) 01461 { 01462 #ifdef VERBOSE 01463 AddToOutput("%s building history for %s, %f percent done", 01464 GetName().c_str(), 01465 rLocalChannel.GetName().c_str(), 01466 rLocalChannel.GetPercentFull()); 01467 #endif 01468 } 01469 01470 } 01471 bSentProgress = true; 01472 } 01473 } 01474 //didn't agree with history or history not yet built 01475 //set the ignore flag 01476 01477 rObs.m_bGoodDA = false; 01478 01479 //log our rejection here 01480 m_Logger.LogObservation(m_dfTimeNow, 01481 rObs, 01482 m_nIterations, 01483 !pChannel->IsOnline()); 01484 01485 rObs.m_bIgnore = true; 01486 } 01487 else 01488 { 01489 rObs.m_bIgnore = false; 01490 rObs.m_bGoodDA = true; 01491 } 01492 //pChannel->Trace(); 01493 } 01494 } 01495 01496 01497 return true; 01498 } 01499 01500 CMOOSNavEngine::CObservationStatistic::CObservationStatistic() 01501 { 01502 m_dfRejectionRate = 0; 01503 m_nTotal = 0; 01504 } 01505 bool CMOOSNavEngine::CObservationStatistic::AddPoint(bool bAccepted) 01506 { 01507 double dfAlpha = 0.95; 01508 double dfRejected = bAccepted?0.0:1.0; 01509 m_nTotal++; 01510 m_dfRejectionRate = (100.0)*(dfAlpha*m_dfRejectionRate/100.0 + (1.0-dfAlpha)*dfRejected); 01511 01512 return true; 01513 } 01514 01515 01516 bool CMOOSNavEngine::DoObservationStatistics() 01517 { 01518 01519 OBSLIST::iterator p; 01520 for(p=m_Observations.begin();p!=m_Observations.end();p++) 01521 { 01522 CMOOSObservation & rObs = *p; 01523 01524 OBSSTATISTIC_MAP::iterator q= m_ObsStatisticsMap.find(rObs.GetName()); 01525 01526 if(q==m_ObsStatisticsMap.end()) 01527 { 01528 CObservationStatistic NewStatistic; 01529 NewStatistic.m_sType = rObs.GetName(); 01530 m_ObsStatisticsMap[rObs.GetName()] = NewStatistic; 01531 q= m_ObsStatisticsMap.find(rObs.GetName()); 01532 } 01533 01534 CObservationStatistic & rStat = q->second; 01535 01536 rStat.AddPoint(rObs.m_bGoodDA); 01537 01538 } 01539 01540 01541 return true; 01542 } 01543 01544 bool CMOOSNavEngine::DoObservationSummary() 01545 { 01546 OBSSTATISTIC_MAP::iterator q; 01547 for(q = m_ObsStatisticsMap.begin();q!=m_ObsStatisticsMap.end();q++) 01548 { 01549 CObservationStatistic & rStat = q->second; 01550 string sText = MOOSFormat("%s Rejecting %d percent of %s [%d]", 01551 GetName().c_str(), 01552 (int)rStat.m_dfRejectionRate, 01553 rStat.m_sType.c_str(), 01554 rStat.m_nTotal); 01555 01556 AddToOutput(sText); 01557 } 01558 return true; 01559 }