MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/NavigationAndControl/MOOSTaskLib/MOOSBehaviour.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 #ifdef _WIN32
00032     #pragma warning(disable : 4786)
00033 #endif
00034 
00035 
00036 // MOOSBehaviour.cpp: implementation of the CMOOSBehaviour class.
00037 //
00039 #include "math.h"
00040 #include <MOOSGenLib/MOOSGenLib.h>
00041 #include "MOOSBehaviour.h"
00042 
00043 #include <sstream>
00044 #include <iostream>
00045 using namespace std;
00046 
00047 
00048 CMOOSBehaviour::CControllerGains::CControllerGains()
00049 {
00050     
00051     m_dfPitchKp    =PITCH_PID_KP;
00052     m_dfPitchKd    =PITCH_PID_KD;
00053     m_dfPitchKi    =PITCH_PID_KI;
00054     m_dfPitchKiMax =PITCH_PID_INTEGRAL_LIMIT;
00055 
00056 
00057     m_dfYawKp = YAW_PID_KP;
00058     m_dfYawKd = YAW_PID_KD;
00059     m_dfYawKi = YAW_PID_KI;
00060     m_dfYawKiMax = YAW_PID_INTEGRAL_LIMIT;
00061 
00062     m_dfZToPitchKp = Z_TO_PITCH_PID_KP;
00063     m_dfZToPitchKd = Z_TO_PITCH_PID_KD;
00064     m_dfZToPitchKi = Z_TO_PITCH_PID_KI;
00065     m_dfZToPitchKiMax = Z_TO_PITCH_PID_INTEGRAL_LIMIT;
00066 
00067     m_dfMaxPitch = PITCH_MAX;
00068     m_dfMaxRudder = RUDDER_MAX;
00069     m_dfMaxElevator = ELEVATOR_MAX;
00070     m_dfMaxThrust = THRUST_MAX;
00071 
00072 
00073 }
00074 
00075 
00077 // Construction/Destruction
00079 
00080 CMOOSBehaviour::CMOOSBehaviour()
00081 {
00082     m_bComplete = false;
00083     m_bActive = false;
00084 
00085     m_sName="NotSet";
00086 
00087     m_pMissionFileReader = NULL;
00088 
00089     m_bNewRegistrations = true;
00090 
00091     m_dfTimeOut=MOOS_DEFUALT_TIMEOUT;
00092     m_dfStartTime=-1;
00093 
00094     m_dfCreationTime = MOOSTime();
00095 
00096     m_dfIterateTime = m_dfCreationTime;
00097 
00098     m_nPriority = 3;
00099 
00100 }
00101 
00102 CMOOSBehaviour::~CMOOSBehaviour()
00103 {
00104 
00105 }
00106 
00107 bool CMOOSBehaviour::Run(CPathAction &DesiredAction)
00108 {
00109     return false;
00110 }
00111 
00112 bool CMOOSBehaviour::OnNewMail(MOOSMSG_LIST &NewMail)
00113 {
00114     CMOOSMsg Msg;
00115     STRING_LIST::iterator p;
00116     
00117 
00118 
00119     for(p=m_StartFlags.begin();p!=m_StartFlags.end();p++)
00120     {
00121 
00122         if(PeekMail(NewMail,*p,Msg))
00123         {
00124             if(Msg.IsType(MOOS_NOTIFY))
00125             {
00126                 if(!Msg.IsSkewed(GetTimeNow()))
00127                 {
00128                     if(!m_bActive)
00129                     {
00130                         Start();
00131                     }
00132                     break;
00133                 }
00134                 else
00135                 {
00136                     MOOSTrace("stale start flag..too old ignoring. DB still running from previous mission?\n");
00137                 }
00138             }
00139         }
00140     }
00141     return true;
00142 }
00143 
00144 bool CMOOSBehaviour::GetRegistrations(STRING_LIST &List)
00145 {
00146     //MOOSTrace("Before %s insertion, List is %d big\n ", m_sName.c_str(), List.size());
00147 
00148     List.insert(List.begin(),m_StartFlags.begin(),m_StartFlags.end());
00149     
00150     //MOOSTrace("After %s insertion, List is %d big\n ", m_sName.c_str(), List.size());
00151 
00152     m_bNewRegistrations = false;
00153     
00154     return true;
00155 }
00156 
00157 bool CMOOSBehaviour::PeekMail(MOOSMSG_LIST &Mail, const string &sKey, CMOOSMsg &Msg)
00158 {
00159     //note we adopt the policy of always taking the youngest message...
00160     MOOSMSG_LIST::iterator p,q;
00161     
00162     q = Mail.end();
00163 
00164     double dfT = -1.0;
00165 
00166     for(p = Mail.begin();p!=Mail.end();p++)
00167     {
00168         if(MOOSStrCmp(p->m_sKey,sKey))
00169         {
00170             if(dfT<p->GetTime())
00171             {
00172                 dfT = p->GetTime();
00173                 q = p;
00174             }
00175         }
00176     }
00177 
00178     //did we find one?
00179     if(    q!=    Mail.end())
00180     {
00181         Msg=*q;
00182         return true;
00183     }
00184     else
00185     {
00186         return false;
00187     }
00188 }
00189 
00190 
00191 
00192 CMOOSBehaviour::ControlledDOF::ControlledDOF()
00193 {
00194     m_dfCurrent = 0;
00195     m_dfCurrentTime = -1;
00196     m_dfDesired = 0;
00197     m_dfTolerance = 0;
00198 }
00199 
00200 void CMOOSBehaviour::ControlledDOF::SetCurrent(double dfCurrent, double dfTime)
00201 {
00202     m_dfCurrent     = dfCurrent;
00203     m_dfCurrentTime = dfTime;
00204 }
00205 
00206 
00207 void CMOOSBehaviour::ControlledDOF::SetDesired(double dfDesired)
00208 {
00209     m_dfDesired  = dfDesired;
00210 }
00211 
00212 void CMOOSBehaviour::ControlledDOF::SetTolerance(double dfTol)
00213 {
00214     m_dfTolerance = dfTol;
00215 }
00216 
00217 double CMOOSBehaviour::ControlledDOF::GetError()
00218 {
00219     double dfErr = m_dfDesired-m_dfCurrent;
00220     if(fabs(dfErr)<=m_dfTolerance)
00221     {
00222         return 0.0;
00223     }
00224     else
00225     {
00226         return dfErr;
00227     }
00228 
00229 }
00230 
00231 
00232 
00233 double CMOOSBehaviour::ControlledDOF::GetErrorTime()
00234 {
00235     return m_dfCurrentTime;
00236 }
00237 
00238 double CMOOSBehaviour::ControlledDOF::GetDesired()
00239 {
00240     return m_dfDesired;
00241 }
00242 
00243 double CMOOSBehaviour::ControlledDOF::GetCurrent()
00244 {
00245     return m_dfCurrent;
00246 }
00247 
00248 
00249 
00250 bool CMOOSBehaviour::ControlledDOF::IsValid()
00251 {
00252     return m_dfCurrentTime!=-1.0;
00253 }
00254 
00255 bool CMOOSBehaviour::GetNotifications(MOOSMSG_LIST &List)
00256 {
00257     List.splice(List.begin(),m_Notifications);
00258 
00259     return true;
00260 }
00261 
00262 bool CMOOSBehaviour::OnComplete()
00263 {
00264     //we are completed!
00265     //default param is "DONE"
00266     Stop();
00267     return true;
00268 }
00269 
00270 bool CMOOSBehaviour::ShouldRun()
00271 {
00272     if(m_bComplete)
00273         return false; //we have already run once and completed
00274 
00275     if(!m_bActive)
00276     {
00277           return false;
00278     }
00279      
00280 
00281     if(m_dfStartTime==-1)
00282     {
00283         //yep we should go but haven't started as yet
00284         Start();
00285     }
00286 
00287     double dfTimeNow = MOOSTime();
00288     //look for timeouts!!!
00289     if(m_dfTimeOut!=-1 && ((dfTimeNow -m_dfStartTime)>m_dfTimeOut))
00290     {
00291         //hell no! we should have achieved our goal by now..
00292         OnTimeOut();
00293         return false;
00294     }
00295      
00296     //look for active task that is not receiving any updates
00297     //on its watched variables?
00298     if(!RegularMailDelivery(dfTimeNow))
00299     {
00300         ostringstream os;
00301         os<<"task "<< m_sName.c_str()<<" stops for lack of input"<<endl<<ends;
00302         string sStr = os.str();
00303         //os.rdbuf()->freeze(0);
00304 
00305         DebugNotify(sStr);
00306 
00307         //publish error string...
00308         OnError(sStr);
00309 
00310         Stop(sStr);
00311 
00312         //now figure our what could have gone wrong...
00313         STRING_LIST Expected;
00314 
00315         GetRegistrations(Expected);
00316 
00317         ostringstream os2;
00318         os2<<"Not receiving one of:";
00319 
00320 
00321         STRING_LIST::iterator p;
00322         for(p = Expected.begin();p!=Expected.end();p++)
00323         {
00324             os2<<p->c_str()<<" ";
00325         }
00326 
00327         os2<<ends;
00328         
00329         sStr = os2.str();
00330 
00331         //os2.rdbuf()->freeze(0);
00332 
00333         //tell the world...
00334         DebugNotify(sStr);
00335 
00336         return false;
00337     }
00338 
00339     return true;
00340 }
00341 
00342 
00343 
00344 bool CMOOSBehaviour::Start()
00345 {
00346     m_bActive = true;
00347     
00348     m_dfStartTime = MOOSTime();
00349 
00350     ostringstream os;
00351 
00352     os<<"Task "<<m_sName.c_str()<<" goes active"<<endl<<ends;
00353 
00354     MOOSTrace(os.str());
00355     
00356     DebugNotify(os.str());
00357     
00358 //    os.rdbuf()->freeze(0);
00359     
00360     //let derived classes do soething
00361     return OnStart();
00362 
00363 }
00364 
00365 void CMOOSBehaviour::Stop(const string & sReason)
00366 {
00367     m_bComplete = true;
00368     m_bActive = false;
00369 
00370     STRING_LIST::iterator p;
00371 
00372 
00373     for(p=m_CompleteFlags.begin();p!=m_CompleteFlags.end();p++)
00374     {
00375         CMOOSMsg DoneMsg(MOOS_NOTIFY,p->c_str(),sReason.c_str());
00376         m_Notifications.push_front(DoneMsg);
00377 
00378         DebugNotify(sReason);
00379 
00380     }
00381 
00382 }
00383 
00384 bool CMOOSBehaviour::SetParam(string sParam, string sVal)
00385 {
00386     MOOSToUpper(sParam);
00387     MOOSToUpper(sVal);
00388 
00389     if(sParam=="NAME")
00390     {
00391         m_sName = sVal;
00392     }
00393 
00394     else if(sParam=="INITIALSTATE")
00395     {
00396         if(sVal =="ON")
00397         {
00398             m_bActive = true;
00399         }
00400         else
00401         {
00402             m_bActive = false;
00403         }
00404     }
00405     else if(sParam=="PRIORITY")
00406     {
00407         m_nPriority = atoi(sVal.c_str());
00408     }
00409     else if(sParam=="STARTFLAG")
00410     {
00411         while(!sVal.empty())
00412         {
00413             string sFlag = MOOSChomp(sVal,",");
00414             m_StartFlags.push_front(sFlag);
00415         }
00416     }
00417     else if(sParam =="FINISHFLAG")
00418     {
00419         while(!sVal.empty())
00420         {
00421             string sFlag = MOOSChomp(sVal,",");
00422             m_CompleteFlags.push_front(sFlag);
00423         }
00424 
00425     }
00426     else if(sParam=="EVENTFLAG")
00427     {
00428         while(!sVal.empty())
00429         {
00430             string sFlag = MOOSChomp(sVal,",");
00431             m_EventFlags.push_front(sFlag);
00432         }
00433     }
00434     else if(sParam == "TIMEOUT")
00435     {
00436         if(sVal=="NEVER")
00437         {
00438             m_dfTimeOut = -1;
00439         }
00440         else
00441         {
00442             m_dfTimeOut = atof(sVal.c_str());
00443             if(m_dfTimeOut==0.0)
00444             {
00445                 MOOSTrace("warning task set for zero timeout..is this intended?\n");
00446             }
00447         }
00448     }
00449     else if(sParam=="LOGPID")
00450     {
00451         bool bLog = MOOSStrCmp(sVal,"TRUE");
00452         m_ZPID.SetLog(bLog);
00453         m_YawPID.SetLog(bLog);
00454     }
00455     else
00456     {
00457         return false;
00458     }
00459 
00460     return true;
00461 
00462 }
00463 
00464 string CMOOSBehaviour::GetName()
00465 {
00466     return m_sName;
00467 }
00468 
00469 bool CMOOSBehaviour::OnEvent(const string & sReason,bool bVerbalNotify)
00470 {
00471 
00472     STRING_LIST::iterator p;
00473 
00474     if(bVerbalNotify)
00475     {
00476         DebugNotify(sReason);
00477     }
00478 
00479     for(p=m_EventFlags.begin();p!=m_EventFlags.end();p++)
00480     {
00481         CMOOSMsg EventMsg(MOOS_NOTIFY,p->c_str(),sReason.c_str());
00482         m_Notifications.push_front(EventMsg);
00483 
00484     }
00485 
00486     
00487 
00488 
00489     return true;
00490 }
00491 
00492 void CMOOSBehaviour::SetMissionFileReader(CProcessConfigReader* pMissionFileReader)
00493 {
00494     m_pMissionFileReader = pMissionFileReader;
00495 }
00496 
00497 //defualt behaviour....
00498 bool CMOOSBehaviour::OnTimeOut()
00499 {
00500     ostringstream os;
00501 
00502     os<<"Task "<<m_sName.c_str()<<" timed out after "<<m_dfTimeOut<<" seconds"<<endl<<ends;
00503 
00504     MOOSTrace(os.str());
00505         
00506     Stop(os.str());
00507     
00508     //os.rdbuf()->freeze(0);
00509 
00510     return true;
00511 }
00512 
00513 bool CMOOSBehaviour::HasNewRegistration()
00514 {
00515     return m_bNewRegistrations;
00516 }
00517 
00518 bool CMOOSBehaviour::ControlledDOF::IsStale(double dfTimeNow, double dfTaskStartTime,double dfTimeOut)
00519 {
00520     //case 1: No mail at all...
00521     if(!IsValid()&& (dfTimeNow-dfTaskStartTime>dfTimeOut))
00522         return true;
00523 
00524     //case 2: Had mail but it has stopped..
00525     if(IsValid() && dfTimeNow-m_dfCurrentTime>dfTimeOut)
00526         return true;
00527 
00528     //then we are OK...
00529     return false;
00530 }
00531 
00532 double CMOOSBehaviour::GetStartTime()
00533 {
00534     return m_dfStartTime;
00535 }
00536 
00537 double CMOOSBehaviour::GetCreationTime()
00538 {
00539     return m_dfCreationTime;
00540 }
00541 
00542 bool CMOOSBehaviour::DebugNotify(const string &sStr)
00543 {
00544     CMOOSMsg DebugMsg(MOOS_NOTIFY,"MOOS_DEBUG",sStr.c_str());
00545     m_Notifications.push_front(DebugMsg);    
00546 
00547     MOOSTrace(sStr);
00548 
00549     return true;
00550 }
00551 
00552 bool CMOOSBehaviour::OnError(string sReason)
00553 {
00554     string sKey = m_sName+"_ERROR";
00555 
00556     CMOOSMsg ErrorMsg(MOOS_NOTIFY,sKey.c_str(),sReason.c_str());
00557 
00558     m_Notifications.push_front(ErrorMsg);
00559 
00560     return true;
00561 }
00562 
00563 //set up controller gains...given to each new task...
00564 bool CMOOSBehaviour::SetGains(CMOOSBehaviour::CControllerGains NewGains)
00565 {
00566     //copy...
00567     m_Gains = NewGains;
00568 
00569     //set up names
00570     string sZ = MOOSFormat("ZControl%s",m_sName.c_str());
00571     string sYaw = MOOSFormat("YawControl%s",m_sName.c_str());
00572 
00573     m_ZPID.SetName(sZ);
00574     m_YawPID.SetName(sYaw);
00575 
00576     if(m_pMissionFileReader!=NULL)
00577     {
00578         //do we have a path global name?
00579         if(!m_pMissionFileReader->GetValue("GLOBALLOGPATH",m_sLogPath))
00580         {
00581             //no do we have a local name?
00582             m_pMissionFileReader->GetConfigurationParam("PIDLOGPATH",m_sLogPath);
00583         }
00584         m_ZPID.SetLogPath(m_sLogPath);
00585         m_YawPID.SetLogPath(m_sLogPath);
00586     }
00587 
00588 
00589 
00590     //configure...
00591     m_ZPID.SetGains(m_Gains.m_dfZToPitchKp,
00592                     m_Gains.m_dfZToPitchKd,
00593                     m_Gains.m_dfZToPitchKi,
00594                     m_Gains.m_dfPitchKp,
00595                     m_Gains.m_dfPitchKd,
00596                     m_Gains.m_dfPitchKi);
00597 
00598     m_ZPID.SetLimits(m_Gains.m_dfMaxPitch,  //maximum outerloop on pitch
00599                     m_Gains.m_dfMaxElevator,//maximum inner loop on elevator
00600                     m_Gains.m_dfZToPitchKiMax,
00601                     m_Gains.m_dfPitchKiMax);
00602 
00603 
00604     m_YawPID.SetGains(    m_Gains.m_dfYawKp,
00605                         m_Gains.m_dfYawKd,
00606                         m_Gains.m_dfYawKi);
00607 
00608     m_YawPID.SetLimits(m_Gains.m_dfYawKiMax,m_Gains.m_dfMaxRudder);
00609 
00610 
00611 
00612     return true;
00613 }
00614 
00615 
00616 CMOOSBehaviour::CXYPoint::CXYPoint()
00617 {
00618     m_dfX = 0.0;
00619     m_dfY = 0.0;
00620 }
00621 
00622 void CMOOSBehaviour::CXYPoint::SetX(double dfX)
00623 {
00624     m_dfX = dfX;
00625 }
00626 
00627 void CMOOSBehaviour::CXYPoint::SetY(double dfY)
00628 {
00629     m_dfY = dfY;
00630 }
00631 
00632 double CMOOSBehaviour::CXYPoint::GetX()
00633 {
00634     return m_dfX;
00635 }
00636 
00637 double CMOOSBehaviour::CXYPoint::GetY()
00638 {
00639     return m_dfY;
00640 }
00641 
00642 void CMOOSBehaviour::SetName(string sName)
00643 {
00644     m_sName = sName;
00645 }
00646 
00647 int CMOOSBehaviour::GetPriority()
00648 {
00649     return m_nPriority;
00650 }
00651 
00652 void CMOOSBehaviour::SetPriority(int nPriority)
00653 {
00654     m_nPriority = nPriority;
00655 }
00656 
00657 bool CMOOSBehaviour::ReInitialise()
00658 {
00659 
00660     m_bComplete = false;
00661     m_bActive = false;
00662 
00663     m_sName="NotSet";
00664 
00665     m_pMissionFileReader = NULL;
00666 
00667     m_bNewRegistrations = true;
00668 
00669     m_dfTimeOut=MOOS_DEFUALT_TIMEOUT;
00670     
00671     m_dfStartTime=-1;
00672 
00673     m_dfCreationTime = MOOSTime();
00674 
00675     m_dfIterateTime = m_dfCreationTime;
00676 
00677     m_nPriority = 3;
00678 
00679     return true;
00680 }
00681 
00682 void CMOOSBehaviour::SetTime(double dfTimeNow)
00683 {
00684     m_dfIterateTime = dfTimeNow;
00685 }
00686 
00687 
00688 //overload this to do something as task is starting
00689 bool CMOOSBehaviour::OnStart()
00690 {
00691     return true;
00692 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines