MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/NavigationAndControl/MOOSTaskLib/TrackLineTask.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 // TrackLineTask.cpp: implementation of the CTrackLineTask class.
00032 //
00034 #ifdef _WIN32
00035     #pragma warning(disable : 4786)
00036 #endif
00037 #include <math.h>
00038 #include "TrackLineTask.h"
00039 
00041 // Construction/Destruction
00043 #define MINIMUM_LEAD_DISTANCE 1.0
00044 CTrackLineTask::CTrackLineTask()
00045 {
00046     m_dfLead = MINIMUM_LEAD_DISTANCE ;
00047     m_dfX1 = 0;
00048     m_dfY1 = 0;
00049     m_dfX2 = 0;
00050     m_dfY2 = 0;
00051 
00052     m_eMode = NOTSET;
00053 
00054 }
00055 
00056 CTrackLineTask::~CTrackLineTask()
00057 {
00058 
00059 }
00060 
00061 
00062 //returns false if we haven't received data in a while..bad news!
00063 bool CTrackLineTask::RegularMailDelivery(double dfTimeNow)
00064 {
00065     
00066     return CGoToWayPoint::RegularMailDelivery(dfTimeNow);
00067     
00068 }
00069 
00070 
00071 bool CTrackLineTask::Run(CPathAction &DesiredAction)
00072 {
00073     if(CalculateLocalGoal())
00074     {
00075         return CGoToWayPoint::Run(DesiredAction);
00076     }
00077     return false;
00078 }
00079 
00080 bool CTrackLineTask::OnNewMail(MOOSMSG_LIST &NewMail)
00081 {
00082     return CGoToWayPoint::OnNewMail(NewMail);
00083 }
00084 
00085 bool CTrackLineTask::GetRegistrations(STRING_LIST &List)
00086 {
00087 
00088     //always call base class version
00089     return CGoToWayPoint::GetRegistrations(List);
00090 }
00091 
00092 bool CTrackLineTask::SetParam(string sParam, string sVal)
00093 {
00094 
00095     MOOSToUpper(sParam);
00096     MOOSToUpper(sVal);
00097 
00098 
00099 
00100     //this is for us...
00101     if(MOOSStrCmp(sParam,"P1"))
00102     {
00103         string sTmpX = MOOSChomp(sVal,",");
00104         string sTmpY = MOOSChomp(sVal,",");
00105         string sTmpZ = MOOSChomp(sVal,",");
00106 
00107         m_dfX1 =   atof(sTmpX.c_str());
00108         m_dfY1 =   atof(sTmpY.c_str());
00109     }
00110     else if(MOOSStrCmp(sParam,"P2"))
00111     {
00112 
00113         string sTmpX = MOOSChomp(sVal,",");
00114         string sTmpY = MOOSChomp(sVal,",");
00115         string sTmpZ = MOOSChomp(sVal,",");
00116 
00117         m_dfX2 =   atof(sTmpX.c_str());
00118         m_XDOF.SetDesired(m_dfX2);
00119 
00120         m_dfY2 =   atof(sTmpY.c_str());
00121         m_YDOF.SetDesired(m_dfY2);
00122 
00123     }
00124     else if(MOOSStrCmp(sParam,"LEAD"))
00125     {
00126         //useful for later...
00127         m_dfLead = atof(sVal.c_str());
00128         if(m_dfLead<MINIMUM_LEAD_DISTANCE)
00129             m_dfLead = MINIMUM_LEAD_DISTANCE;
00130 
00131     }
00132     else  if(!CGoToWayPoint::SetParam(sParam,sVal))
00133     {
00134         //hmmm - it wasn't for us at all: base class didn't understand either
00135         MOOSTrace("Param \"%s\" not understood!\n",sParam.c_str());
00136         return false;
00137     }
00138 
00139 
00140     return true;
00141 
00142 }
00143 
00144 bool CTrackLineTask::CalculateLocalGoal()
00145 {
00146 
00147     return CalculateLocalGoalV2();
00148 
00149     double dfx1 = m_dfX1;
00150     double dfx2 = m_dfX2;
00151     double dfy1 = m_dfY1;
00152     double dfy2 = m_dfY2;
00153     double dfx12 = m_dfX2-m_dfX1;
00154     double dfy12 = m_dfY2-m_dfY1;
00155     double dfS12 = sqrt((dfx12*dfx12+dfy12*dfy12));
00156 
00157     double dfxv = m_XDOF.GetCurrent();
00158     double dfyv = m_YDOF.GetCurrent();
00159 
00160     //we now solv to find the coordinates of the point
00161     //on or tack line that is closest to nour current position
00162     //solving for xn,yn, lambda where 0<lambda<1 where lamda is
00163     //a scalar realting Xn and P1 Xn = X1+Lambda(X2-X1)
00164     Matrix A(3,3);
00165     A   <<dfx12 <<dfy12 <<  0.0
00166         <<1.0   <<0.0   << -dfx12
00167         <<0.0   <<1.0   << -dfy12;
00168 
00169     Matrix d(3,1);
00170 
00171     d<< dfxv*dfx12 + dfy12*dfyv<< dfx1<< dfy1;
00172     Matrix Sol;
00173     try
00174     {
00175         Sol = A.i()*d;
00176     }
00177     catch(...)
00178     {
00179         Sol.Release();
00180         MOOSTrace("failed inversion in TrackLinetask!");
00181         Stop("Failed Matrix Inversion");
00182         return false;
00183     }
00184 
00185     double dfLambda = Sol(3,1);
00186 
00187     double dfLead = m_dfLead;
00188 
00189     //are we outside the line?
00190     if(dfLambda<0) 
00191     {
00192         //head for first ppint
00193         Sol(1,1) = dfx1;
00194         Sol(2,1) = dfy1;
00195         Sol(3,1) = 0; 
00196         dfLead = 0;
00197     }
00198 
00199     if(dfLambda>=1)
00200     {
00201         //head for second point..
00202         Sol(1,1) = dfx2;
00203         Sol(2,1) = dfy2;
00204         Sol(3,1) = 0; 
00205         dfLead = 0;
00206     }
00207 
00208     if(dfS12*(1.0-dfLambda)<dfLead)
00209     {
00210         //don;t lead past end of line!
00211         Sol(1,1) = dfx2;
00212         Sol(2,1) = dfy2;
00213         Sol(3,1) = 0; 
00214         dfLead = 0;
00215     }
00216 
00217 
00218     //now lead us along the line... 
00219     double dfTargetX = Sol(1,1)+dfLead*dfx12/dfS12;
00220     double dfTargetY = Sol(2,1)+dfLead*dfy12/dfS12;
00221 
00222     m_XDOF.SetDesired(dfTargetX);
00223     m_YDOF.SetDesired(dfTargetY);
00224 
00225 
00226     return true;
00227 }
00228 
00229 double CTrackLineTask::GetDistanceToGo()
00230 {
00231     return sqrt(pow(m_dfX2-m_XDOF.GetCurrent(),2)+pow(m_dfY2-m_YDOF.GetCurrent(),2));
00232 }
00233 
00234 
00235 bool CTrackLineTask::CalculateLocalGoalV2()
00236 {
00237     double dfx1 = m_dfX1;
00238     double dfx2 = m_dfX2;
00239     double dfy1 = m_dfY1;
00240     double dfy2 = m_dfY2;
00241     double dfx12 = m_dfX2-m_dfX1;
00242     double dfy12 = m_dfY2-m_dfY1;
00243     double dfS12 = sqrt((dfx12*dfx12+dfy12*dfy12));
00244 
00245     double dfxv = m_XDOF.GetCurrent();
00246     double dfyv = m_YDOF.GetCurrent();
00247 
00248 
00249     double dfTheta = atan2(dfy2-dfyv,dfx2-dfxv);
00250 
00251     double dfLineTheta = atan2(dfy12,dfx12);    
00252 
00253     double dfRangeToGoal = sqrt(pow(dfy2-dfyv,2)+pow(dfx2-dfxv,2));
00254 
00255     double dfxe = dfRangeToGoal*cos(dfTheta-dfLineTheta);
00256 
00257     double dfTheHenrikRatio  = 0.5;
00258 
00259 
00260     
00261     double dfxp = dfx2-dfxe*cos(dfLineTheta);
00262     double dfyp = dfy2-dfxe*sin(dfLineTheta);
00263 
00264 
00265     double dfXGoal = dfx2;
00266     double dfYGoal = dfy2;
00267 
00268 
00269     if(dfTheHenrikRatio*dfxe>m_dfLead)
00270     {   
00271         //PMN MODE n(v clever)
00272 
00273         SetMode(CTrackLineTask::TRANSIT);
00274 
00275         dfxe = m_dfLead;
00276         dfXGoal = dfxp+m_dfLead*cos(dfLineTheta);
00277         dfYGoal = dfyp+m_dfLead*sin(dfLineTheta);
00278 
00279     }
00280     else
00281     {
00282         //HS Method (moderately clever ;-) )
00283         SetMode(CTrackLineTask::APPROACH);
00284         dfXGoal = (1-dfTheHenrikRatio)*dfxp+dfTheHenrikRatio*dfx2;
00285         dfYGoal = (1-dfTheHenrikRatio)*dfyp+dfTheHenrikRatio*dfy2;
00286     }
00287         
00288 
00289     m_XDOF.SetDesired(dfXGoal);
00290     m_YDOF.SetDesired(dfYGoal);
00291 
00292 
00293     return true;
00294 
00295 }
00296 
00297 bool CTrackLineTask::SetMode(CTrackLineTask::Mode eMode)
00298 {
00299     if(m_eMode!=eMode)
00300     {
00301         //state change
00302         switch(eMode)
00303         {
00304         case APPROACH: MOOSTrace("switching to APPROACH mode\n"); break;
00305         case TRANSIT: MOOSTrace("switching to TRANSIT mode\n"); break;
00306         default:
00307             break;
00308         }
00309     }
00310 
00311     m_eMode = eMode;
00312 
00313     return true;
00314 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines