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