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 // SurveyTask.cpp: implementation of the CSurveyTask class. 00032 // 00034 #ifdef _WIN32 00035 #pragma warning(disable : 4786) 00036 #endif 00037 #include <math.h> 00038 #include <sstream> 00039 #include <iostream> 00040 using namespace std; 00041 00042 #include "SurveyTask.h" 00043 #include "XYPatternTask.h" 00044 00046 // Construction/Destruction 00048 00049 CSurveyTask::CSurveyTask() 00050 { 00051 m_nNoLegs = 0; 00052 m_nNoArms = 0; 00053 m_nTotalSurveyLines = 0; 00054 m_nCurrentSurveyLine = 0; 00055 m_nSpacing = 0; 00056 m_nTheta = 0; 00057 00058 m_nA = 0; 00059 m_nB = 0; 00060 00061 m_CenterOfSurvey.SetX(0.0); 00062 m_CenterOfSurvey.SetY(0.0); 00063 00064 m_nPriority = 3; 00065 m_bInitialised = false; 00066 m_dfVicinityRadius = 5; 00067 m_dfThrust = 0; 00068 m_dfLead = 1; 00069 m_dfLegTimeOut = 100.0; 00070 00071 } 00072 00073 CSurveyTask::~CSurveyTask() 00074 { 00075 00076 } 00077 00078 00079 bool CSurveyTask::Initialise() 00080 { 00081 //Define the survey area 00082 m_nNoArms = m_nB / m_nSpacing; 00083 m_nNoLegs = m_nNoArms + 1; 00084 m_nTotalSurveyLines = m_nNoArms + m_nNoLegs; 00085 00086 double dfRad = m_nTheta * PI/180; 00087 00088 00089 //XXX: using the center of the survey is not advised for trackline creation, 00090 //XXX: as rotation does not occur properly if translation is done first 00091 //XXX: different strategy: 00092 //XXX: 1. Make Survey around origin 00093 //XXX: 2. Rotate Coordinates of Survey points 00094 //XXX: 3. Translate Coordinates to the Survey's center 00095 00096 //start in the lower left corner of the box 00097 //XXX:11/19/02 - fixed survey problem of not being able to use 00098 //XXX:A and B values of different magnitudes 00099 double dfXStart = -(m_nB / 2); 00100 double dfYStart = -(m_nA / 2); 00101 00102 CXYPoint StartPoint; 00103 StartPoint.SetX(dfXStart); 00104 StartPoint.SetY(dfYStart); 00105 00106 //make sure we have enough room 00107 m_XYPoints.resize(m_nTotalSurveyLines + 2); 00108 m_XYPoints[0] = StartPoint; 00109 00110 int nM = -1; 00111 int kCnt = 1; 00112 00113 while(kCnt <= m_nTotalSurveyLines) 00114 { 00115 for(int j = 0; j < 2; j++) 00116 { 00117 if(j == 0) 00118 { 00119 //make the Point for the Leg 00120 CXYPoint NextPoint; 00121 nM *= -1; 00122 double dfY = m_XYPoints[kCnt - 1].GetY() + nM * m_nA; 00123 NextPoint.SetY(dfY); 00124 NextPoint.SetX(m_XYPoints[kCnt - 1].GetX()); 00125 00126 m_XYPoints[kCnt++] = NextPoint; 00127 } 00128 else 00129 { 00130 //make the Point for the Arm 00131 CXYPoint NextPoint; 00132 double dfX = m_XYPoints[kCnt - 1].GetX() + m_nSpacing; 00133 NextPoint.SetX(dfX); 00134 NextPoint.SetY(m_XYPoints[kCnt - 1].GetY()); 00135 00136 m_XYPoints[kCnt++] = NextPoint; 00137 } 00138 } 00139 } 00140 00141 //Turn the Survey points into a matrix, 00142 //this allows for easy rotation 00143 Matrix GridPoints(2, m_nTotalSurveyLines + 2); 00144 00145 for(int i = 0;i < GridPoints.Ncols();i++) 00146 { 00147 GridPoints(XROW,i + 1) = m_XYPoints[i].GetX(); 00148 GridPoints(YROW,i + 1) = m_XYPoints[i].GetY(); 00149 } 00150 00151 //now rotate the points if need be 00152 if(dfRad != 0) 00153 { 00154 //This matrix will rotate a box CW, i.e. in negative yaw (positive heading) 00155 Matrix Rotator(2,2); 00156 Rotator << cos(dfRad) << sin(dfRad) 00157 << -sin(dfRad) << cos(dfRad); 00158 00159 //Rotate the Survey 00160 GridPoints = Rotator * GridPoints; 00161 } 00162 00163 //XXX: Translate the Grid to the actual Survey's center 00164 // 00165 //now go thru the GridPoints and make that the actual 00166 //points that we will survey with 00167 string sPoints; 00168 string sTrackline; 00169 int tCnt = 0; 00170 for(int j = 0; j < GridPoints.Ncols(); j++) 00171 { 00172 //point creation 00173 m_XYPoints[j].SetX(GridPoints(XROW, j + 1) + m_CenterOfSurvey.GetX()); 00174 m_XYPoints[j].SetY(GridPoints(YROW, j + 1) + m_CenterOfSurvey.GetY()); 00175 00176 //debug information 00177 sTrackline += MOOSFormat("%f", m_XYPoints[j].GetX()); 00178 sTrackline += ","; 00179 sTrackline += MOOSFormat("%f", m_XYPoints[j].GetY()); 00180 00181 //announcement to SURVEY_POINTS 00182 sPoints += MOOSFormat("%f", m_XYPoints[j].GetX()); 00183 sPoints += ","; 00184 sPoints += MOOSFormat("%f", m_XYPoints[j].GetY()); 00185 00186 if((j % 2) == 0) 00187 { 00188 sPoints += "->"; 00189 sTrackline += "->"; 00190 } 00191 else 00192 { 00193 DebugNotify(MOOSFormat("Trackline %d: %s\n", ++tCnt, sTrackline.c_str())); 00194 sPoints += "|"; 00195 00196 //reset the debug information 00197 sTrackline = ""; 00198 } 00199 } 00200 00201 //announce what we have done by adding a list of points to our notifications 00202 CMOOSMsg Msg(MOOS_NOTIFY, "SURVEY_POINTS", sPoints.c_str()); 00203 m_Notifications.push_back(Msg); 00204 00205 //create the first trackline 00206 SetNextLineInSurvey(); 00207 00208 m_bInitialised = true; 00209 00210 return m_bInitialised; 00211 } 00212 00213 //returns false if we haven't received data in a while..bad news! 00214 bool CSurveyTask::RegularMailDelivery(double dfTimeNow) 00215 { 00216 00217 return m_ActiveTrackLine.RegularMailDelivery(dfTimeNow); 00218 00219 } 00220 00221 00222 bool CSurveyTask::Run(CPathAction &DesiredAction) 00223 { 00224 00225 if(!m_bInitialised) 00226 { 00227 Initialise(); 00228 } 00229 00230 if(ShouldRun()) 00231 { 00232 00233 if(m_nCurrentSurveyLine < m_nTotalSurveyLines) 00234 { 00235 if(ActiveTracklineShouldRun()) 00236 return m_ActiveTrackLine.Run(DesiredAction); 00237 else 00238 return SetNextLineInSurvey(); 00239 } 00240 else 00241 { 00242 OnComplete(); 00243 } 00244 00245 } 00246 return true; 00247 } 00248 00249 bool CSurveyTask::OnNewMail(MOOSMSG_LIST &NewMail) 00250 { 00251 00252 CMOOSBehaviour::OnNewMail(NewMail); 00253 //make sure we pass this information on to the active trackline 00254 //MOOSTrace("Survey - new mail %f\n", MOOSTime()); 00255 if(ActiveTracklineShouldRun()) 00256 { 00257 // MOOSTrace("Survey - new mail - passing %f\n", MOOSTime()); 00258 m_ActiveTrackLine.OnNewMail(NewMail); 00259 } 00260 return true; 00261 } 00262 00263 bool CSurveyTask::GetRegistrations(STRING_LIST &List) 00264 { 00265 CMOOSBehaviour::GetRegistrations(List); 00266 return m_ActiveTrackLine.GetRegistrations(List); 00267 } 00268 00269 bool CSurveyTask::SetParam(string sParam, string sVal) 00270 { 00271 00272 MOOSToUpper(sParam); 00273 MOOSToUpper(sVal); 00274 00275 00276 //this is for us... 00277 if(MOOSStrCmp(sParam,"CENTER")) 00278 { 00279 string sTmpX = MOOSChomp(sVal,","); 00280 string sTmpY = MOOSChomp(sVal,","); 00281 00282 m_CenterOfSurvey.SetX(atof(sTmpX.c_str())); 00283 m_CenterOfSurvey.SetY(atof(sTmpY.c_str())); 00284 } 00285 else if(MOOSStrCmp(sParam,"A")) 00286 { 00287 m_nA = atoi(sVal.c_str()); 00288 } 00289 else if(MOOSStrCmp(sParam,"B")) 00290 { 00291 m_nB = atoi(sVal.c_str()); 00292 } 00293 else if(MOOSStrCmp(sParam,"LEGTIMEOUT")) 00294 { 00295 m_dfLegTimeOut = atof(sVal.c_str()); 00296 } 00297 else if(MOOSStrCmp(sParam,"SPACING")) 00298 { 00299 m_nSpacing = atoi(sVal.c_str()); 00300 } 00301 else if(MOOSStrCmp(sParam,"ROTATION")) 00302 { 00303 m_nTheta = atoi(sVal.c_str()); 00304 } 00305 else if(MOOSStrCmp(sParam,"LEAD")) 00306 { 00307 m_dfLead = atof(sVal.c_str()); 00308 } 00309 else if(!CXYPatternTask::SetParam(sParam,sVal)) 00310 { 00311 //hmmm - it wasn't for us at all: base class didn't understand either 00312 MOOSTrace("Param \"%s\" not understood!\n",sParam.c_str()); 00313 return false; 00314 } 00315 00316 00317 return true; 00318 00319 } 00320 00321 00322 00323 bool CSurveyTask::SetNextLineInSurvey() 00324 { 00325 00326 string sP1, sP2, sRadius, sThrust, sLead,sLegTimeOut; 00327 string sTracklineName = m_sName; 00328 00329 if(!m_bInitialised) 00330 { 00331 00332 //always start by heading to the first position around the center 00333 m_nCurrentSurveyLine = 0; 00334 sTracklineName += MOOSFormat("_TRACKLINE_%d",(m_nCurrentSurveyLine + 1)); 00335 m_ActiveTrackLine.SetName(sTracklineName); 00336 m_ActiveTrackLine.SetGains(m_Gains); 00337 00338 } 00339 else 00340 { 00341 string sStatus = MOOSFormat("Survey Trackline %d Complete", (m_nCurrentSurveyLine + 1)); 00342 //do notification of completion here for other tasks to fire off of 00343 string sFlag = MOOSFormat("SURVEY_TRACKLINE_%d_DONE", (m_nCurrentSurveyLine + 1)); 00344 CMOOSMsg DoneMsg(MOOS_NOTIFY, sFlag.c_str(), ""); 00345 00346 //augment our current point we are heading to 00347 m_nCurrentSurveyLine++; 00348 sTracklineName += MOOSFormat("_TRACKLINE_%d",(m_nCurrentSurveyLine + 1)); 00349 00350 //also provide some intelligible info 00351 CMOOSMsg Msg(MOOS_NOTIFY, "SURVEY_STATUS", sStatus.c_str()); 00352 m_Notifications.push_back(Msg); 00353 m_Notifications.push_back(DoneMsg); 00354 00355 //reinitializing a trackline does not affect the Gains 00356 m_ActiveTrackLine.ReInitialise(); 00357 m_ActiveTrackLine.SetName(sTracklineName); 00358 } 00359 00360 //format the variables 00361 sP1 = MOOSFormat("%f,%f", 00362 m_XYPoints[m_nCurrentSurveyLine].GetX(), 00363 m_XYPoints[m_nCurrentSurveyLine].GetY()); 00364 00365 sP2 = MOOSFormat("%f,%f", 00366 m_XYPoints[m_nCurrentSurveyLine + 1].GetX(), 00367 m_XYPoints[m_nCurrentSurveyLine + 1].GetY()); 00368 00369 sRadius = MOOSFormat("%f", m_dfVicinityRadius); 00370 sLead = MOOSFormat("%f", m_dfLead); 00371 sThrust = MOOSFormat("%f", m_dfThrust); 00372 sLegTimeOut = MOOSFormat("%f", m_dfLegTimeOut); 00373 00374 m_ActiveTrackLine.SetParam("P1", sP1); 00375 m_ActiveTrackLine.SetParam("P2", sP2); 00376 m_ActiveTrackLine.SetParam("LEAD", sLead); 00377 m_ActiveTrackLine.SetParam("RADIUS", sRadius); 00378 m_ActiveTrackLine.SetParam("THRUST", sThrust); 00379 m_ActiveTrackLine.SetParam("TimeOut", sLegTimeOut); 00380 //always make the initialstate ON 00381 m_ActiveTrackLine.SetParam("INITIALSTATE", "ON"); 00382 00383 //announce where we are going to 00384 //XXX: need to add an end flag that we are DONE on the SURVEYNAME_TRACKLINE_NO 00385 ostringstream os; 00386 00387 os<<"SURVEY - transiting to: pos["<<(m_nCurrentSurveyLine + 1)<<"]"<< 00388 " -> "<<m_XYPoints[m_nCurrentSurveyLine + 1].GetX()<<","<< 00389 m_XYPoints[m_nCurrentSurveyLine + 1].GetY()<<endl<<ends; 00390 00391 string sInfo = os.str(); 00392 //os.rdbuf()->freeze(0); 00393 DebugNotify(sInfo); 00394 CMOOSMsg Msg(MOOS_NOTIFY,"SURVEY_INFO",sInfo.c_str()); 00395 m_Notifications.push_back(Msg); 00396 00397 m_ActiveTrackLine.Start(); 00398 00399 return true; 00400 } 00401 00402 bool CSurveyTask::ActiveTracklineShouldRun() 00403 { 00404 return m_ActiveTrackLine.ShouldRun(); 00405 } 00406 00407 void CSurveyTask::SetTime(double dfTimeNow) 00408 { 00409 m_dfIterateTime = dfTimeNow; 00410 //and pass this time along to our trackline 00411 // if(ActiveTracklineShouldRun()) 00412 m_ActiveTrackLine.SetTime(dfTimeNow); 00413 } 00414 00415 bool CSurveyTask::OnStart() 00416 { 00417 //dummy call starts owned class.. 00418 m_ActiveTrackLine.Start(); 00419 return true; 00420 } 00421 00422 bool CSurveyTask::GetNotifications(MOOSMSG_LIST &List) 00423 { 00424 //for our child... 00425 m_ActiveTrackLine.GetNotifications(List); 00426 00427 //for ourselves 00428 List.splice(List.begin(),m_Notifications); 00429 00430 return true; 00431 } 00432 00433 00434