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 // MOOSObservation.cpp: implementation of the CMOOSObservation class. 00032 // 00034 #include <math.h> 00035 #include "MOOSNavEntity.h" 00036 #include "MOOSNavBeacon.h" 00037 #include "MOOSNavVehicle.h" 00038 00039 #include "MOOSNavSensor.h" 00040 #include "MOOSObservation.h" 00041 #include "MOOSNavLibGlobalHelper.h" 00042 #include "MOOSNavLibDefs.h" 00043 00044 #include <sstream> 00045 #include <iomanip> 00047 // Construction/Destruction 00049 00050 00051 00052 00053 bool CMOOSObservation::JacCallBack( Matrix & XOut, 00054 Matrix & XIn, 00055 void * pParam) 00056 { 00057 00058 CMOOSObservation* pMe = (CMOOSObservation*)pParam; 00059 00060 return pMe->JacEvaluate(XIn,XOut); 00061 00062 } 00063 00064 00065 00066 CMOOSObservation::CMOOSObservation() 00067 { 00068 //good guess 00069 m_dfSV = 1500.0; 00070 00071 //default of one element deep 00072 m_nDim = 1; 00073 00074 m_nRow = -1; 00075 00076 //default lbl channel is -1 00077 m_nChan = -1; 00078 00079 //this observaiton has not been used yet 00080 m_bUsed = false; 00081 00082 //by default do thing explicitly 00083 m_bNumericalJacobians = false; 00084 00085 //by defualt don't ignore observations 00086 m_bIgnore = false; 00087 00088 //assume good data association 00089 m_bGoodDA = true; 00090 00091 //we by default don't expect to be a fixed observation! 00092 m_bFixed = false; 00093 00094 m_dfInnov = 0; 00095 00096 //negative->not set 00097 m_dfInnovStd = -1; 00098 00099 //by default don't look for heading bias state! 00100 m_bUseHeadingBias = false; 00101 00102 00103 } 00104 00105 CMOOSObservation::~CMOOSObservation() 00106 { 00107 00108 } 00109 00110 00111 bool CMOOSObservation::MakeMatrices(Matrix &Innov, 00112 Matrix &jH, 00113 Matrix &jR, 00114 Matrix &Xhat) 00115 { 00116 00117 00118 00119 switch(m_eType) 00120 { 00121 case X: 00122 case Y: 00123 return MakeXYMatrices(Innov, 00124 jH, 00125 jR); 00126 case LBL_BEACON_2WR: 00127 return MakeBeacon2WRMatrices(Innov, 00128 jH, 00129 jR); 00130 break; 00131 case YAW: 00132 return MakeYawMatrices(Innov, 00133 jH, 00134 jR); 00135 break; 00136 00137 case DEPTH: 00138 return MakeDepthMatrices(Innov, 00139 jH, 00140 jR); 00141 break; 00142 00143 case TIDE: 00144 return MakeTideMatrices(Innov, 00145 jH, 00146 jR); 00147 break; 00148 00149 case HEADING_BIAS: 00150 return MakeHeadingBiasMatrices(Innov, 00151 jH, 00152 jR); 00153 break; 00154 00155 case BODY_VEL_Y: 00156 case BODY_VEL_X: 00157 return MakeBodyVelMatrices(Innov, 00158 jH, 00159 jR); 00160 break; 00161 00162 default: 00163 break; 00164 } 00165 00166 00167 return false; 00168 } 00169 00170 00171 bool CMOOSObservation::MakeBeacon2WRMatrices(Matrix &Innov, 00172 Matrix &jH, 00173 Matrix &jR) 00174 00175 { 00176 00177 double dfTOF=0; 00178 00180 //note this is somewhat confusing if you aren't careful 00181 //times are calculated using the current estimates of 00182 //position and velocity. eg a V1 at origin moving 1m/s in 00183 //x direction towards a beacon at 1500 on x axis will have 00184 //and estimated travel time of GREATER than 2 seconds! 00185 //this is because if the vehcile is at the origin now 00186 //it would have been more than 1500 m away when it transmitted 00187 //the interrogation.... cunning! 00188 00189 m_pXEvaluate = m_pInterrogateSensor->GetParent()->m_pXhat; 00190 00191 bool bSolved = false; 00192 00193 bSolved = m_LBLMaths.CalculateTwoWayTOF( m_pInterrogateSensor, 00194 m_pRespondingSensor, 00195 m_pXEvaluate, 00196 m_dfSV, 00197 dfTOF); 00198 00199 if(!bSolved) 00200 { 00201 return false; 00202 } 00203 00204 //fill in innovation 00205 Innov(m_nRow,1) = m_dfData-dfTOF; 00206 00207 // MOOSTrace("Predicted travel time = %f seconds\n",dfTOF); 00208 00209 //now look after jacobian 00210 Matrix JNumeric,JExplicit; 00211 00212 //make jacobian maths use the state predicted... 00213 Matrix* pXPred=m_pInterrogateSensor->GetParent()->m_pXhat; 00214 00215 00216 if(m_bNumericalJacobians) 00217 { 00218 MOOSGetJacobian(JNumeric, 00219 *pXPred, 00220 1, 00221 pXPred->Nrows(), 00222 JacCallBack, 00223 this); 00224 } 00225 else 00226 { 00227 m_LBLMaths.CalculateTwoWayTOFJacobians(m_pInterrogateSensor, 00228 m_pRespondingSensor, 00229 pXPred, 00230 m_dfSV, 00231 JExplicit); 00232 } 00233 00234 // MOOSMatrixTrace(JNumeric,"Numeric"); 00235 // MOOSMatrixTrace(JExplicit,"Explicit"); 00236 00237 00238 //fill in relevant sub matrix in jH 00239 jH.SubMatrix(m_nRow,m_nRow+m_nDim-1,1,jH.Ncols())=JExplicit; 00240 00241 00242 //and now fill in the observation noise 00243 jR(m_nRow,m_nRow) = pow(m_dfDataStd,2); 00244 00245 00246 00247 return bSolved; 00248 } 00249 00250 00251 00252 00253 00254 bool CMOOSObservation::JacEvaluate(Matrix & XIn,Matrix & XOut) 00255 { 00256 //store old XEvaluate pointer 00257 Matrix * pOldXEvaluate = m_pXEvaluate; 00258 00259 //make XEvaluate pointer point to our new input vector... 00260 m_pXEvaluate = &XIn; 00261 00262 00263 //now do the calculation.... 00264 double dfTOF=0; 00265 bool bSolved = m_LBLMaths.CalculateTwoWayTOF( m_pInterrogateSensor, 00266 m_pRespondingSensor, 00267 m_pXEvaluate, 00268 m_dfSV, 00269 dfTOF); 00270 00271 if(bSolved) 00272 { 00273 XOut(1,1) = dfTOF; 00274 } 00275 00276 00277 //restore XEvaluate pointer 00278 m_pXEvaluate = pOldXEvaluate; 00279 00280 return true; 00281 } 00282 00283 int CMOOSObservation::GetDimension() 00284 { 00285 return m_nDim; 00286 } 00287 00288 00289 bool CMOOSObservation::MakeHeadingBiasMatrices( Matrix &Innov, 00290 Matrix &jH, 00291 Matrix &jR) 00292 { 00293 //z = Bias; 00294 m_pXEvaluate = m_pInterrogateSensor->GetParent()->m_pXhat; 00295 00296 int nStateNdx = HEADING_BIAS_STATE_INDEX; 00297 00298 double dfZPred = (*m_pXEvaluate)(nStateNdx,1); 00299 00300 Innov(m_nRow,1) = m_dfData-dfZPred; 00301 00302 jR(m_nRow,m_nRow) = pow(m_dfDataStd,2); 00303 00304 jH(m_nRow,nStateNdx) = 1.0; 00305 00306 return true; 00307 } 00308 00309 00310 bool CMOOSObservation::MakeTideMatrices( Matrix &Innov, 00311 Matrix &jH, 00312 Matrix &jR) 00313 { 00314 00315 m_pXEvaluate = m_pInterrogateSensor->GetParent()->m_pXhat; 00316 00317 int nStateNdx = TIDE_STATE_INDEX; 00318 00319 double dfZPred = (*m_pXEvaluate)(nStateNdx,1); 00320 00321 Innov(m_nRow,1) = m_dfData-dfZPred; 00322 00323 jR(m_nRow,m_nRow) = pow(m_dfDataStd,2); 00324 00325 jH(m_nRow,nStateNdx) = 1.0; 00326 00327 return true; 00328 } 00329 00330 00331 bool CMOOSObservation::MakeDepthMatrices(Matrix &Innov, 00332 Matrix &jH, 00333 Matrix &jR) 00334 { 00335 00336 CMOOSNavEntity * pEntity = m_pInterrogateSensor->GetParent(); 00337 m_pXEvaluate = pEntity->m_pXhat; 00338 00339 00340 //z component of entity measuring depth... 00341 int nStateNdx =pEntity->m_nStart+iiZ; 00342 00343 double dfZv = 0.0; 00344 00345 if(pEntity->GetEntityType() == CMOOSNavEntity::FIXED) 00346 { 00347 //at thios point we could worry about roll and pitch corrections 00348 //but we don't expect this to be big or important in non USBL applications 00349 00350 //FIXED vehicle Z + sensor Z 00351 dfZv = pEntity->m_State.m_dfZ+m_pInterrogateSensor->m_Offset.m_dfZ; 00352 00353 } 00354 else 00355 { 00356 //moving vehicle Z + sensor Z 00357 dfZv = (*m_pXEvaluate)(nStateNdx,1)+m_pInterrogateSensor->m_Offset.m_dfZ; 00358 } 00359 00360 00361 //depth is a function of Tide 00362 //depth = Tide-Zv 00363 double S = (*m_pXEvaluate)(TIDE_STATE_INDEX,1); 00364 00365 double dfZPred = (S-dfZv); 00366 00367 //always have this component 00368 jH(m_nRow,TIDE_STATE_INDEX) = 1.0; 00369 00370 if(pEntity->GetEntityType() !=CMOOSNavEntity::FIXED) 00371 { 00372 //add mobile state derivative 00373 jH(m_nRow,nStateNdx) = -1.0; 00374 } 00375 00376 Innov(m_nRow,1) = m_dfData-dfZPred; 00377 00378 00379 00380 jR(m_nRow,m_nRow) = pow(m_dfDataStd,2); 00381 00382 return true; 00383 00384 } 00385 00386 bool CMOOSObservation::MakeXYMatrices(Matrix &Innov, 00387 Matrix &jH, 00388 Matrix &jR) 00389 { 00390 00391 CMOOSNavVehicle* pVeh = dynamic_cast< CMOOSNavVehicle * >(m_pInterrogateSensor->GetParent()); 00392 00393 if(pVeh == NULL) 00394 return false; 00395 00396 m_pXEvaluate = pVeh->m_pXhat; 00397 00398 00399 00400 00402 // global and body stablised coordinates 00403 00404 m_pXEvaluate = m_pInterrogateSensor->GetParent()->m_pXhat; 00405 00406 double dfX = (*m_pXEvaluate)(pVeh->m_nStart+iiX,1); 00407 double dfY = (*m_pXEvaluate)(pVeh->m_nStart+iiY,1); 00408 double dfH = (*m_pXEvaluate)(pVeh->m_nStart+iiH,1); 00409 00410 double dfx,dfy,dfz; 00411 m_pInterrogateSensor->GetAlignedOffsets(dfH,dfx,dfy,dfz); 00412 00413 00414 00415 00416 double dfHdot = 0; 00417 if(pVeh->GetEntityType()==CMOOSNavVehicle::POSE_AND_RATE) 00418 { 00419 dfHdot = (*m_pXEvaluate)(pVeh->m_nStart+iiHdot,1); 00420 } 00421 00422 00423 double dT = 0.0; 00424 00426 // prediction part.... note rotation matrix is 00427 // 00428 // | c -s | 00429 // | s c | 00430 // 00431 // ie the transpose (inverse) of what we might expect 00432 // as we are taking rotated pojnts back to the base frame 00433 00434 double dfPX = dfX + dfx* cos(dfH) - dfy*sin(dfH); 00435 double dfPY = dfY + dfx* sin(dfH) + dfy*cos(dfH); 00436 00437 00439 // jacobian part.... 00440 00441 //differential of X w.r.t heading 00442 double dXdH = -(dfx* sin(dfH)+dfy*cos(dfH)- ( (dfx*cos(dfH)-dfy*sin(dfH) )*dfHdot*dT)); 00443 00444 //differential of Y w.r.t heading 00445 double dYdH = dfx*cos(dfH) - dfy*sin(dfH) + (( dfx* sin(dfH) + dfy*cos(dfH))*dfHdot*dT); 00446 00447 double dXdX = 1.0; 00448 00449 double dYdY = 1.0; 00450 00451 //all other differntials dX/dY are clearly zero 00452 //remain slightly concerned about dZ/dw though... 00453 00455 // Now fill in the matrices! 00456 00457 double dfZPred; 00458 switch(m_eType) 00459 { 00460 case X: 00461 dfZPred = dfPX; 00462 jH(m_nRow,pVeh->m_nStart+iiX) = dXdX; 00463 jH(m_nRow,pVeh->m_nStart+iiH) = dXdH; 00464 break; 00465 case Y: 00466 dfZPred = dfPY; 00467 jH(m_nRow,pVeh->m_nStart+iiY) = dYdY; 00468 jH(m_nRow,pVeh->m_nStart+iiH) = dYdH; 00469 break; 00470 default: 00471 return false; 00472 } 00473 00474 00475 Innov(m_nRow,1) = (m_dfData-dfZPred); 00476 jR(m_nRow,m_nRow) = pow(m_dfDataStd,2); 00477 00478 00479 return true; 00480 00481 } 00482 00483 00484 00485 bool CMOOSObservation::MakeYawMatrices(Matrix &Innov, 00486 Matrix &jH, 00487 Matrix &jR) 00488 00489 { 00490 00491 m_pXEvaluate = m_pInterrogateSensor->GetParent()->m_pXhat; 00492 00493 int nStateNdx = m_pInterrogateSensor->GetParent()->m_nStart+iiH; 00494 00495 00496 double dfZPred = (*m_pXEvaluate)(nStateNdx,1); 00497 00498 if(m_bUseHeadingBias) 00499 { 00500 dfZPred+=(*m_pXEvaluate)(HEADING_BIAS_STATE_INDEX,1); 00501 } 00502 00503 00504 Innov(m_nRow,1) = MOOS_WRAP_ANGLE(m_dfData-dfZPred); 00505 00506 jR(m_nRow,m_nRow) = pow(m_dfDataStd,2); 00507 00508 jH(m_nRow,nStateNdx) = 1.0; 00509 00510 if(m_bUseHeadingBias) 00511 { 00512 //z = Yaw+Bias 00513 jH(m_nRow,HEADING_BIAS_STATE_INDEX) = 1.0; 00514 } 00515 00516 00517 return true; 00518 } 00519 00520 bool CMOOSObservation::MakeBodyVelMatrices(Matrix &Innov, 00521 Matrix &jH, 00522 Matrix &jR) 00523 00524 { 00525 00526 if(m_eType!=BODY_VEL_Y && m_eType!=BODY_VEL_X) 00527 { 00528 jH.SubMatrix(m_nRow,m_nRow,1,jH.Ncols())=0; 00529 MOOSTrace("Only Body Vel X and Y supprted so far\n"); 00530 return false; 00531 } 00532 if(m_pInterrogateSensor->GetParent()->GetEntityType()!=CMOOSNavEntity::POSE_AND_RATE) 00533 { 00534 MOOSTrace("cannot use body vel obs on static vehcile\n"); 00535 return false; 00536 } 00537 00538 //ok begin.... 00539 m_pXEvaluate = m_pInterrogateSensor->GetParent()->m_pXhat; 00540 00541 int nStart = m_pInterrogateSensor->GetParent()->m_nStart; 00542 double dfYaw = (*m_pXEvaluate)(nStart+iiH,1); 00543 00544 if(m_eType==BODY_VEL_Y) 00545 { 00546 //resolve onto axis 90 deg further around.. 00547 dfYaw+=PI/2; 00548 } 00549 00550 double dfXdot = (*m_pXEvaluate)(nStart+iiXdot,1); 00551 double dfYdot = (*m_pXEvaluate)(nStart+iiYdot,1); 00552 00553 double dfZPred = dfXdot*cos(dfYaw)+dfYdot*sin(dfYaw); 00554 00555 Innov(m_nRow,1) = m_dfData-dfZPred; 00556 00557 jR(m_nRow,m_nRow) = pow(m_dfDataStd,2); 00558 00559 jH(m_nRow,nStart+iiXdot) = cos(dfYaw); 00560 jH(m_nRow,nStart+iiYdot) = sin(dfYaw); 00561 jH(m_nRow,nStart+iiH) = -dfXdot*sin(dfYaw)+dfYdot*cos(dfYaw); 00562 00563 00564 return true; 00565 } 00566 00567 00568 00569 00570 void CMOOSObservation::Trace() 00571 { 00572 string sType; 00573 switch(m_eType) 00574 { 00575 case UNKNOWN_TYPE: sType = "Unknown"; break; 00576 case X: sType = "X"; break; 00577 case Y: sType = "Y"; break; 00578 case YAW: sType = "Yaw"; break; 00579 case LBL_BEACON_2WR: sType = "Beacon 2WR"; break; 00580 case DEPTH: sType = "Depth"; break; 00581 case SPEED: sType = "Speed"; break; 00582 case THRUST: sType = "Thrust"; break; 00583 case RUDDER: sType = "Rudder"; break; 00584 case ELEVATOR: sType = "Elevator"; break; 00585 case TIDE: sType = "Tide";break; 00586 case BODY_VEL_X:sType = "BodyVelX";break; 00587 case BODY_VEL_Y:sType = "BodyVelY";break; 00588 case BODY_VEL_Z:sType = "BodyVelZ";break; 00589 } 00590 00591 MOOSTrace("ID %d Type=%s,Time = %f,Data=%f\n", 00592 GetID(),sType.c_str(),m_dfTime,m_dfData); 00593 00594 if(m_eType ==LBL_BEACON_2WR) 00595 { 00596 MOOSTrace("\t%s -> %s\n", 00597 m_pInterrogateSensor->GetParent()->GetName().c_str(), 00598 m_pRespondingSensor->GetParent()->GetName().c_str()); 00599 } 00600 00601 00602 } 00603 00604 00605 void CMOOSObservation::DoDebug() 00606 { 00607 00608 } 00609 00610 //returns a unique string describing the type obs 00611 //I use source sensor and if acoustic the channel 00612 string CMOOSObservation::GetName() 00613 { 00614 ostringstream os; 00615 00616 os<<m_pInterrogateSensor->GetName(); 00617 00618 if(m_eType ==LBL_BEACON_2WR) 00619 { 00620 os<<"["<<m_nChan<<"]"; 00621 } 00622 if(m_eType==X) 00623 { 00624 os<<"[X]"; 00625 } 00626 if(m_eType==Y) 00627 { 00628 os<<"[Y]"; 00629 } 00630 00631 00632 os<<ends; 00633 00634 string sAnswer = os.str(); 00635 // os.rdbuf()->freeze(0); 00636 00637 return sAnswer; 00638 } 00639 00640 bool CMOOSObservation::IsFixed() 00641 { 00642 return m_bFixed; 00643 } 00644 00645 bool CMOOSObservation::SetFixed(bool bFixed) 00646 { 00647 m_bFixed = bFixed; 00648 00649 return true; 00650 } 00651 00652 bool CMOOSObservation::IsType(CMOOSObservation::Type eType) 00653 { 00654 return m_eType == eType; 00655 } 00656 00657 bool CMOOSObservation::Ignore(bool bIgnore) 00658 { 00659 m_bIgnore = bIgnore; 00660 00661 return true; 00662 } 00663 00664 bool CMOOSObservation::SetGoodDA(bool bGoodDA) 00665 { 00666 m_bGoodDA = bGoodDA; 00667 return true; 00668 } 00669 00670 void CMOOSObservation::UsingHeadingBias(bool bUsing) 00671 { 00672 m_bUseHeadingBias = bUsing; 00673 }