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