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 // XYPatternTask.cpp: implementation of the CXYPatternTask class. 00032 // 00034 #ifdef _WIN32 00035 #pragma warning(disable : 4786) 00036 #endif 00037 00038 #include "MOOSTaskDefaults.h" 00039 #include "XYPatternTask.h" 00040 #include "math.h" 00041 #include <sstream> 00042 #include <iostream> 00043 using namespace std; 00044 00045 00047 // Construction/Destruction 00049 00050 CXYPatternTask::CXYPatternTask() 00051 { 00052 m_nPriority = 2; 00053 00054 00055 m_bInitialised = false; 00056 00057 m_dfVicinityRadius = 0; 00058 00059 m_bPositionSet = true; 00060 00061 m_bThrustSet = false; 00062 00063 m_dfThrust = 0; 00064 00065 m_nTotalPositions = 0; 00066 00067 m_nTotalRepetitions = 0; 00068 00069 m_nCurrentPosition = 0; 00070 00071 m_nRepCounter = 0; 00072 00073 } 00074 00075 CXYPatternTask::~CXYPatternTask() 00076 { 00077 m_XYPoints.clear(); 00078 } 00079 00080 bool CXYPatternTask::OnNewMail(MOOSMSG_LIST &NewMail) 00081 { 00082 00083 CMOOSMsg Msg; 00084 00085 if(PeekMail(NewMail,"NAV_POSE",Msg)) 00086 { 00087 if(!Msg.IsSkewed(GetTimeNow())) 00088 { 00089 std::vector<double> Pose; 00090 int nRows,nCols; 00091 if(MOOSValFromString(Pose,nRows,nCols,Msg.GetString(),"Pose",true)) 00092 { 00093 if(Pose.size() == 3) 00094 { 00095 m_XDOF.SetCurrent(Pose[0],Msg.GetTime()); 00096 m_YDOF.SetCurrent(Pose[1],Msg.GetTime()); 00097 m_YawDOF.SetCurrent(Pose[2],Msg.GetTime()); 00098 00099 // MOOSTrace("we are at %f %f %f\n",Pose[0],Pose[1],Pose[2]); 00100 } 00101 } 00102 00103 } 00104 } 00105 00106 if(PeekMail(NewMail,"NAV_X",Msg)) 00107 { 00108 if(!Msg.IsSkewed(GetTimeNow())) 00109 { 00110 m_XDOF.SetCurrent(Msg.m_dfVal,Msg.m_dfTime); 00111 } 00112 } 00113 if(PeekMail(NewMail,"NAV_Y",Msg)) 00114 { 00115 if(!Msg.IsSkewed(GetTimeNow())) 00116 { 00117 m_YDOF.SetCurrent(Msg.m_dfVal,Msg.m_dfTime); 00118 } 00119 } 00120 00121 if(PeekMail(NewMail,"NAV_YAW",Msg)) 00122 { 00123 if(!Msg.IsSkewed(GetTimeNow())) 00124 { 00125 00126 double dfVal = Msg.m_dfVal; 00127 00128 if(dfVal>PI) 00129 { 00130 dfVal-=2*PI; 00131 } 00132 m_YawDOF.SetCurrent(dfVal,Msg.m_dfTime); 00133 00134 // MOOSTrace("%s gets yaw = %f @ %f\n",m_sName.c_str(),dfVal,Msg.m_dfTime); 00135 } 00136 00137 } 00138 00139 //always call base class version 00140 CMOOSBehaviour::OnNewMail(NewMail); 00141 00142 return true; 00143 } 00144 00145 bool CXYPatternTask::GetRegistrations(STRING_LIST &List) 00146 { 00147 List.push_front("NAV_X"); 00148 List.push_front("NAV_Y"); 00149 List.push_front("NAV_YAW"); 00150 List.push_front("NAV_POSE"); 00151 00152 //always call base class version 00153 CMOOSBehaviour::GetRegistrations(List); 00154 00155 return true; 00156 } 00157 00158 00159 00160 //returns false if we haven't received data in a while..bad news! 00161 bool CXYPatternTask::RegularMailDelivery(double dfTimeNow) 00162 { 00163 if(m_YawDOF.IsStale(dfTimeNow,GetStartTime())) 00164 return false; 00165 00166 if(m_XDOF.IsStale(dfTimeNow,GetStartTime())) 00167 return false; 00168 00169 if(m_YDOF.IsStale(dfTimeNow,GetStartTime())) 00170 return false; 00171 00172 return true; 00173 } 00174 00175 00176 00177 bool CXYPatternTask::Run(CPathAction &DesiredAction) 00178 { 00179 if(!m_bPositionSet) 00180 { 00181 MOOSTrace("position not set\n");; 00182 return false; 00183 } 00184 00185 if(!m_bInitialised) 00186 { 00187 Initialise(); 00188 } 00189 00190 if(ShouldRun()) 00191 { 00192 00193 if(ValidData() && m_nTotalPositions!=0) 00194 { 00195 00196 double dfDistanceToGo = sqrt(pow(m_YDOF.GetError(),2)+pow(m_XDOF.GetError(),2)); 00197 00198 00199 if(dfDistanceToGo<m_dfVicinityRadius) 00200 { 00201 00202 if(m_nRepCounter < m_nTotalRepetitions) 00203 { 00204 SetNextPoint(); 00205 } 00206 else 00207 { 00208 OnComplete(); 00209 } 00210 } 00211 else 00212 { 00213 //calculate vector heading angle to goal 00214 00215 00216 double dfDesiredYaw = -atan2(m_XDOF.GetError(),m_YDOF.GetError()); 00217 00218 m_YawDOF.SetDesired(dfDesiredYaw); 00219 00220 double dfError = m_YawDOF.GetError(); 00221 00222 // MOOSTrace("x_err = %f y_err = %f current_yaw = %f desired_yaw = %f\n", 00223 // m_XDOF.GetError(),m_YDOF.GetError(),m_YawDOF.GetCurrent(),dfDesiredYaw); 00224 00225 00226 dfError = MOOS_ANGLE_WRAP(dfError); 00227 00228 double dfCmd = 0; 00229 00230 //this is for loggin purposes only 00231 m_YawPID.SetGoal(m_YawDOF.GetDesired()); 00232 if(m_YawPID.Run(dfError,m_YawDOF.GetErrorTime(),dfCmd)) 00233 { 00234 //OK we need to change something 00235 SetControl(DesiredAction,-dfCmd,m_dfThrust); 00236 } 00237 } 00238 } 00239 } 00240 return true; 00241 } 00242 00243 00244 bool CXYPatternTask::SetControl(CPathAction &DesiredAction,double dfRudder,double dfThrust) 00245 { 00246 DesiredAction.Set( ACTUATOR_RUDDER, 00247 dfRudder, 00248 m_nPriority, 00249 GetName().c_str()); 00250 00251 //set the thrust 00252 if(m_bThrustSet) 00253 { 00254 DesiredAction.Set( ACTUATOR_THRUST, 00255 dfThrust, 00256 m_nPriority, 00257 GetName().c_str()); 00258 } 00259 00260 return true; 00261 } 00262 00263 00264 00265 bool CXYPatternTask::Initialise() 00266 { 00267 00268 m_YawDOF.SetDesired(0); 00269 m_YawDOF.SetTolerance(0.00); 00270 00271 //begin the loop-d-loop of points 00272 SetNextPoint(); 00273 00274 m_bInitialised = true; 00275 00276 return m_bInitialised; 00277 } 00278 00279 bool CXYPatternTask::ValidData() 00280 { 00281 return m_XDOF.IsValid() && 00282 m_YDOF.IsValid() && 00283 m_YawDOF.IsValid(); 00284 } 00285 00286 00287 00288 bool CXYPatternTask::SetParam(string sParam, string sVal) 00289 { 00290 MOOSToUpper(sParam); 00291 MOOSToUpper(sVal); 00292 00293 00294 if(!CMOOSBehaviour::SetParam(sParam,sVal)) 00295 { 00296 //this is for us... 00297 if(sParam=="RADIUS") 00298 { 00299 m_dfVicinityRadius=atof(sVal.c_str()); 00300 } 00301 else if(sParam=="THRUST") 00302 { 00303 m_dfThrust=atof(sVal.c_str()); 00304 m_bThrustSet = true; 00305 } 00306 else if(sParam=="LOCATION") 00307 { 00308 //useful for later... 00309 m_sLocation = sVal; 00310 string sCopyOfLocation = sVal; 00311 00312 string sTmpX = MOOSChomp(sVal,","); 00313 string sTmpY = MOOSChomp(sVal,","); 00314 string sTmpZ = MOOSChomp(sVal,","); 00315 00316 if(sTmpX.empty()||sTmpY.empty()||sTmpZ.empty()) 00317 { 00318 MOOSTrace("error in reading location from file\n"); 00319 return false; 00320 } 00321 00322 //instead of setting this as the X,Y point to go to, 00323 //store the points in a list that will be parsed later 00324 m_Positions.push_back(sCopyOfLocation); 00325 m_nTotalPositions++; 00326 00327 } 00328 else if((sParam == "REPEAT")) 00329 { 00330 int nTotal = atoi(sVal.c_str()); 00331 //only accept positive values 00332 if((nTotal > 0) && (nTotal < XYPATTERN_MAX_TOTAL_REPETITION)) 00333 { 00334 m_nTotalRepetitions = nTotal; 00335 } 00336 else if((nTotal > 0) && (nTotal > XYPATTERN_MAX_TOTAL_REPETITION)) 00337 { 00338 m_nTotalRepetitions = XYPATTERN_MAX_TOTAL_REPETITION; 00339 } 00340 else 00341 { 00342 //default 00343 m_nTotalRepetitions = XYPATTERN_DEFAULT_TOTAL_REPETITION; 00344 } 00345 00346 } 00347 else 00348 { 00349 //hmmm - it wasn't for us at all: base class didn't understand either 00350 MOOSTrace("Param \"%s\" not understood by %s!\n",sParam.c_str(),m_sName.c_str()); 00351 return false; 00352 } 00353 } 00354 00355 return true; 00356 } 00357 00358 00359 void CXYPatternTask::SetNextPoint() 00360 { 00361 //first time through, we need to make some calculations 00362 if(!m_bInitialised) 00363 { 00364 //always start by heading to the first position around the center 00365 m_nCurrentPosition = 0; 00366 00367 //guarantee enough space 00368 m_XYPoints.clear(); 00369 m_XYPoints.resize(m_nTotalPositions + 1); 00370 00371 for(int i = 0; i < m_nTotalPositions; i++) 00372 { 00373 string sVal = m_Positions.front(); 00374 m_Positions.pop_front(); 00375 double dfX = atof(MOOSChomp(sVal,",").c_str()); 00376 double dfY = atof(MOOSChomp(sVal,",").c_str()); 00377 00378 CXYPoint Position; 00379 00380 Position.SetX(dfX); 00381 Position.SetY(dfY); 00382 00383 m_XYPoints[i] = Position; 00384 00385 } 00386 } 00387 else 00388 { 00389 //otherwise just augment our current point we are heading to 00390 //and have the new Desired location input for the controller 00391 m_nCurrentPosition++; 00392 //make sure we go in a circle 00393 m_nCurrentPosition %= m_nTotalPositions; 00394 //augment our repetitions 00395 if(m_nCurrentPosition==0) 00396 { 00397 m_nRepCounter++; 00398 } 00399 } 00400 00401 //announce where we are going to 00402 ostringstream os; 00403 00404 os<<"XYPATTERN - transiting to: pos["<<m_nCurrentPosition<<"]"<< 00405 " -> "<<m_XYPoints[m_nCurrentPosition].GetX()<<","<< 00406 m_XYPoints[m_nCurrentPosition].GetY()<<" - [REP : "<< 00407 m_nRepCounter<<"]"<<endl<<ends; 00408 00409 DebugNotify(os.str()); 00410 00411 //now set the point we are heading to 00412 m_XDOF.SetDesired(m_XYPoints[m_nCurrentPosition].GetX()); 00413 m_YDOF.SetDesired(m_XYPoints[m_nCurrentPosition].GetY()); 00414 00415 return; 00416 }