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