MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/NavigationAndControl/MOOSNavLib/MOOSObservation.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 // 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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines