MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Essentials/pScheduler/MOOSScheduler.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 at MIT 2001-2002 and Oxford 
00010 //   University 2003-2005. email: pnewman@robots.ox.ac.uk. 
00011 //      
00012 //   This file is part of a  MOOS Core Component. 
00013 //        
00014 //   This program is free software; you can redistribute it and/or 
00015 //   modify it under the terms of the GNU General Public License as 
00016 //   published by the Free Software Foundation; either version 2 of the 
00017 //   License, or (at your option) any later version. 
00018 //          
00019 //   This program is distributed in the hope that it will be useful, 
00020 //   but WITHOUT ANY WARRANTY; without even the implied warranty of 
00021 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
00022 //   General Public License for more details. 
00023 //            
00024 //   You should have received a copy of the GNU General Public License 
00025 //   along with this program; if not, write to the Free Software 
00026 //   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
00027 //   02111-1307, USA. 
00028 //
00030 // MOOSScheduler.cpp: implementation of the CMOOSScheduler class.
00031 //
00033 #include <MOOSLIB/MOOSLib.h>
00034 #include "MOOSScheduler.h"
00035 
00037 // Construction/Destruction
00039 
00040 using namespace std;
00041 
00042 #ifdef _WIN32
00043 
00044 DWORD WINAPI ScheduleLoopProc( LPVOID lpParameter)
00045 {
00046     MOOSTrace("starting Scheduler Thread....\n");
00047     
00048     CMOOSScheduler* pMe =     (CMOOSScheduler*)lpParameter;
00049     
00050     return pMe->Schedule();    
00051 }
00052 
00053 #else
00054 
00055 void * ScheduleLoopProc( void * lpParameter)
00056 {
00057     
00058     MOOSTrace("starting Scheduler Thread....\n");
00059     CMOOSScheduler* pMe =     (CMOOSScheduler*)lpParameter;
00060     
00061     pMe->Schedule();    
00062     
00063     return NULL;
00064 }
00065 
00066 #endif
00067 
00068 
00069 bool CMOOSScheduler::StopThreads()
00070 {
00071     m_bQuit = true;
00072     
00073 #ifdef _WIN32
00074     WaitForSingleObject(m_hScheduleThread,INFINITE);
00075 #else
00076     void * Result;
00077     pthread_join( (pthread_t)m_nScheduleThreadID,&Result);
00078 #endif
00079     
00080     return true;
00081 }
00082 
00083 bool CMOOSScheduler::StartThreads()
00084 {
00085     m_bQuit = false;
00086     
00087 #ifdef _WIN32
00088     //this is the main schedule thread
00089     m_hScheduleThread = ::CreateThread(    NULL,
00090         0,
00091         ScheduleLoopProc,
00092         this,
00093         CREATE_SUSPENDED,
00094         &m_nScheduleThreadID);
00095     ResumeThread(m_hScheduleThread);
00096         
00097 #else
00098         
00099     int Status = pthread_create( (pthread_t*)& m_nScheduleThreadID,NULL,ScheduleLoopProc,this);
00100     
00101     if(Status!=0)
00102     {
00103         return false;
00104     }    
00105     
00106 #endif
00107     
00108     return true;
00109 }
00110 
00111 
00112 
00113 CMOOSScheduler::CMOOSScheduler()
00114 {
00115     m_bQuit = false;
00116     m_bActive = true;
00117 }
00118 
00119 CMOOSScheduler::~CMOOSScheduler()
00120 {
00121 
00122 }
00123 
00124 
00125 bool CMOOSScheduler::Iterate()
00126 {
00127     
00128     return true;
00129 }
00130 
00131 bool CMOOSScheduler::OnConnectToServer()
00132 {
00133     m_Comms.Register("RESTART_SCHEDULER",0);
00134     m_Comms.Register("SCHEDULER_CONTROL",0);
00135 
00136     AddResponses();
00137 
00138     return true;
00139 }
00140 
00141 bool CMOOSScheduler::OnStartUp()
00142 {
00143     Initialise();
00144     return true;
00145 }
00146 
00147 bool CMOOSScheduler::OnNewMail(MOOSMSG_LIST &NewMail)
00148 {
00149     CMOOSMsg Msg;
00150     if(m_Comms.PeekMail(NewMail,"RESTART_SCHEDULER",Msg,true))
00151     {
00152         if(!Msg.IsSkewed(MOOSTime()))
00153         {
00154             OnRestart();
00155         }
00156     }
00157 
00158     if(m_Comms.PeekMail(NewMail,"SCHEDULER_CONTROL",Msg,true))
00159     {
00160         if(!Msg.IsSkewed(MOOSTime()))
00161         {
00162             OnControl(Msg.m_sVal);
00163         }
00164     }
00165 
00166     //give Events start and stop signals
00167     EVENT_LIST::iterator q;
00168     for(q=m_Events.begin();q!=m_Events.end();q++)
00169     {
00170         q->OnNewMail(NewMail);
00171     }
00172 
00173 
00174     HandleResponses(NewMail);
00175 
00176     
00177     
00178     return true;
00179 }
00180 
00181 bool CMOOSScheduler::AddSequences()
00182 {
00183     // SEQUENCE = SEQ_START      : TRUE @ 3.0
00184     // SEQUENCE = SAS_INHIBIT : FALSE @ 0.0
00185     // SEQUENCE = SAS_INHIBIT : TRUE @ 1.9
00186     // SEQUENCE = DVL_INHIBIT : FALSE @ 1.9
00187     // SEQUENCE = DVL_INHIBIT : TRUE @ 2.3
00188     // SEQUENCE = SEQ_END      : TRUE @ 3.0
00189 
00190     STRING_LIST sParams;
00191     m_MissionReader.GetConfiguration(GetAppName(),sParams);
00192     STRING_LIST::iterator p;
00193 
00194     EVENT_LIST LocalList;
00195 
00196     double dfTimeMax = -1;
00197     for(p = sParams.begin();p!=sParams.end();p++)
00198     {
00199         string sTok,sVal;
00200         if(m_MissionReader.GetTokenValPair(*p,sTok,sVal))
00201         {
00202             if(!MOOSStrCmp(sTok,"SEQUENCE"))
00203                 continue;
00204 
00205             //get the names
00206             string sName = MOOSChomp(sVal,":");
00207             string sNameVal = MOOSChomp(sVal,"@");
00208             if(sVal.empty())
00209             {
00210                 MOOSTrace("Missing time in sequence setting!");
00211                 continue;
00212             }
00213             double dfOffset = atof(sVal.c_str());
00214 
00215             dfTimeMax = dfOffset>dfTimeMax?dfOffset:dfTimeMax;
00216                     
00217             CEvent NewEvent;
00218             NewEvent.Initialise(sName,sNameVal,-1,dfOffset);
00219 
00220             LocalList.push_front(NewEvent);
00221 
00222         }
00223     }
00224 
00225     EVENT_LIST::iterator q;
00226     for(q = LocalList.begin();q!=LocalList.end();q++)
00227     {
00228         q->SetPeriod(dfTimeMax);
00229     }
00230 
00231     m_Events.splice(m_Events.begin(),LocalList);
00232 
00233     return true;
00234 }
00235 
00236 bool CMOOSScheduler::AddTimers()
00237 {
00238 
00239     //TIMER = VARNAME @ 0.4, STARTFLAG,STOPFLAG,[VARIABLE_VAL_NAME] -> VALUE
00240 
00241     STRING_LIST sParams;
00242     m_MissionReader.GetConfiguration(GetAppName(),sParams);
00243     STRING_LIST::iterator p;
00244 
00245     for(p = sParams.begin();p!=sParams.end();p++)
00246     {
00247         string sTok,sVal;
00248         if(m_MissionReader.GetTokenValPair(*p,sTok,sVal))
00249         {
00250             if(!MOOSStrCmp(sTok,"TIMER"))
00251                 continue;
00252 
00253             //get the names
00254             string sName = MOOSChomp(sVal,"@");
00255             string sTime = MOOSChomp(sVal,",");
00256             string sFlags = MOOSChomp(sVal,"->");
00257             string sNameVal = sVal;           
00258             string sStartFlag = MOOSChomp(sFlags,",");
00259             string sEndFlag = MOOSChomp(sFlags,",");
00260             string sVarVal = MOOSChomp(sFlags,",");
00261 
00262             CEvent NewEvent;
00263 
00264             double dfPeriod = atof(sTime.c_str());
00265 
00266             NewEvent.Initialise(sName,sNameVal,dfPeriod);
00267             NewEvent.SetEnableFlags(sStartFlag,sEndFlag);
00268 
00269             //waht value do we subscribve to?
00270             NewEvent.SetNameVal(sVarVal);
00271 
00272             if(!sStartFlag.empty())
00273                 m_Comms.Register(sStartFlag,0);
00274 
00275             if(!sEndFlag.empty())
00276                 m_Comms.Register(sEndFlag,0);
00277 
00278             if(!sVarVal.empty())
00279                 m_Comms.Register(sVarVal,0);
00280 
00281             m_Events.push_front(NewEvent);
00282 
00283         }
00284     }
00285     return true;
00286 }
00287 
00288 bool CMOOSScheduler::AddResponses()
00289 {
00290     m_Responses.clear();
00291 
00292     //RESPONSE = ON_COMPLETE[=val] : FLAG_1 @ val1, FLAG_2@ val 2 etc
00293 
00294     STRING_LIST sParams;
00295     m_MissionReader.GetConfiguration(GetAppName(),sParams);
00296     STRING_LIST::iterator p;
00297 
00298     for(p = sParams.begin();p!=sParams.end();p++)
00299     {
00300         string sTok,sVal;
00301         if(m_MissionReader.GetTokenValPair(*p,sTok,sVal))
00302         {
00303             if(!MOOSStrCmp(sTok,"RESPONSE"))
00304                 continue;
00305 
00306             string sName = MOOSChomp(sVal,":");
00307             MOOSToUpper(sName);
00308 
00309             RESPONSE_LIST NewList;
00310 
00311             while(!sVal.empty())
00312             {
00313                 string sChunk = MOOSChomp(sVal,",");
00314                 
00315                 string sFlag =  MOOSChomp(sChunk,"@");
00316                 string sVal = sChunk;
00317 
00318                 CResponseMsg NewElement;
00319                 NewElement.m_sName = sFlag;
00320                 NewElement.m_sVal = sVal;
00321 
00322                 NewList.push_front(NewElement);
00323             }
00324 
00325             m_Responses[sName] = NewList;
00326         }
00327     }
00328 
00329     //now check for circular source and sinks..
00330     RESPONSE_LIST_MAP::iterator q,t;
00331 
00332     for(q = m_Responses.begin();q!=m_Responses.end();q++)
00333     {
00334         RESPONSE_LIST & rList = q->second;
00335 
00336         RESPONSE_LIST::iterator w;
00337 
00338         for(w = rList.begin();w!= rList.end();w++)
00339         {
00340             RESPONSE_LIST_MAP::iterator v = m_Responses.find(w->m_sName);
00341             if(v!=m_Responses.end())
00342             {
00343                 MOOSTrace("Response setup error: cannot sink and source %s\n",w->m_sName.c_str());
00344                 t = q++;
00345                 m_Responses.erase(t);
00346             }
00347         }
00348     }
00349 
00350 
00351     RegisterResponses();
00352     
00353     
00354     return true;
00355 }
00356 
00357 
00358 
00359 CMOOSScheduler::CEvent::CEvent()
00360 {
00361     m_bEnabled = true;
00362     m_dfFireTime = 0 ;
00363     m_dfPeriod = 1.0;
00364     m_dfOffset = 0;
00365 }
00366 
00367 bool CMOOSScheduler::CEvent::GetOutput(double dfTimeNow, MOOSMSG_LIST &Out)
00368 {
00369     if(dfTimeNow>m_dfFireTime && m_bEnabled)
00370     {
00371         //set up next fire time
00372         m_dfFireTime+=m_dfPeriod;
00373 
00374         CMOOSMsg Msg(    MOOS_NOTIFY,
00375                         m_sName.c_str(),
00376                         m_sVal.c_str(),
00377                         dfTimeNow);
00378 
00379         Out.push_front(Msg);
00380 
00381         return true;
00382     }
00383     else
00384     {
00385         return false;
00386     }
00387 }
00388 
00389 bool CMOOSScheduler::CEvent::Enable(bool bEnable,double dfTimeNow)
00390 {
00391     m_bEnabled = bEnable;
00392     return true;
00393 }
00394 
00395 bool CMOOSScheduler::CEvent::Initialise(string sName, string sVal, double dfPeriod,double dfOffset)
00396 {
00397     m_sName = sName;
00398     m_sVal = sVal;
00399     m_dfPeriod = dfPeriod;
00400     m_dfOffset = dfOffset;
00401 
00402     return true;
00403 }
00404 
00405 bool CMOOSScheduler::CEvent::SetPeriod(double dfPeriod)
00406 {
00407     m_dfPeriod = dfPeriod;
00408     return true;
00409 }
00410 
00411 bool CMOOSScheduler::CEvent::SetOffset(double dfOffset)
00412 {
00413     m_dfOffset = dfOffset;
00414     return true;
00415 }
00416 
00417 bool CMOOSScheduler::Schedule()
00418 {
00419     while(!m_bQuit)
00420     {
00421         double dfTimeNow = MOOSTime();
00422 
00423         EVENT_LIST::iterator p;
00424         MOOSMSG_LIST MailOut;
00425         for(p = m_Events.begin();p!=m_Events.end();p++)
00426         {
00427             CEvent & rEvent = *p;
00428             if(m_nTicks==0)
00429                 rEvent.SetStartingTime(dfTimeNow);
00430 
00431             rEvent.GetOutput(dfTimeNow,MailOut);
00432             while(!MailOut.empty())
00433             {
00434                 if(m_bActive)
00435                 {
00436                     m_Comms.Post(MailOut.front());
00437                 }
00438                 MailOut.pop_front();
00439             }
00440         }
00441 
00442         m_nTicks++;
00443 
00444         //reschedule this thread
00445         MOOSPause(1);
00446     }
00447 
00448     MOOSTrace("Scheduler Thread Quits\n");
00449     return true;
00450 }
00451 
00452 bool CMOOSScheduler::OnRestart()
00453 {
00454     MOOSDebugWrite("Scheduler Restarting....");
00455     Clean();
00456     return Initialise();
00457 }
00458 
00459 bool CMOOSScheduler::Clean()
00460 {
00461     StopThreads();
00462     m_Events.clear();
00463     m_Responses.clear();
00464     return true;
00465 }
00466 
00467 bool CMOOSScheduler::Initialise()
00468 {
00469     if(!AddSequences())
00470         return false;
00471 
00472     if(!AddTimers())
00473         return false;
00474 
00475     if(!AddResponses())
00476         return true;
00477 
00478     SetCommsFreq(50);
00479     SetAppFreq(50);
00480 
00481     m_nTicks = 0;
00482 
00483     if(!StartThreads())
00484         return false;
00485 
00486     m_bActive = true;
00487 
00488     return true;
00489 
00490 }
00491 
00492 bool CMOOSScheduler::OnControl(string sControl)
00493 {
00494     if(sControl.find("ON")!=string::npos)
00495     {
00496         m_bActive = true;
00497         MOOSDebugWrite("Activating scheduler");
00498     }
00499     if(sControl.find("OFF")!=string::npos)
00500     {
00501         m_bActive = false;
00502         MOOSDebugWrite("De-activating scheduler");
00503     }
00504 
00505     return true;
00506 }
00507 
00508 bool CMOOSScheduler::HandleResponses(MOOSMSG_LIST &NewMail)
00509 {
00510     MOOSMSG_LIST::iterator p;
00511 
00512     for(p = NewMail.begin();p!=NewMail.end();p++)
00513     {
00514         string sResponseKey1 = p->GetKey();
00515         string sResponseKey2 = p->GetKey() + "=" + p->GetString();
00516         MOOSToUpper(sResponseKey2);
00517 
00518         STRING_LIST lsKeys;
00519         lsKeys.push_back(sResponseKey1);
00520         lsKeys.push_back(sResponseKey2);
00521     
00522         STRING_LIST::iterator l;
00523         for (l = lsKeys.begin(); l != lsKeys.end(); ++l)
00524         {
00525         
00526             string sKey = *l;
00527             RESPONSE_LIST_MAP::iterator q = m_Responses.find(sKey);
00528 
00529 
00530             if(q!=m_Responses.end())
00531             {
00532                 RESPONSE_LIST & rList = q->second;
00533                 
00534                 RESPONSE_LIST::iterator w;
00535                 
00536                 for(w = rList.begin();w!= rList.end();w++)
00537                 {            
00538                     if(m_bActive)
00539                     {
00540                         m_Comms.Notify(w->m_sName,w->m_sVal);
00541                     }                
00542                 }
00543             }
00544         }
00545     }
00546 
00547     return true;
00548 }
00549 
00550 bool CMOOSScheduler::RegisterResponses()
00551 {
00552     RESPONSE_LIST_MAP::iterator q;
00553     for(q = m_Responses.begin();q!=m_Responses.end();q++)
00554     {
00555         string sResponseKey = q->first;
00556         string sResponseVar = MOOSChomp(sResponseKey, "=");
00557         m_Comms.Register(sResponseVar,0);
00558     }
00559     return true;
00560 }
00561 
00562 bool CMOOSScheduler::CEvent::SetEnableFlags(string sStart, string sStop)
00563 {
00564     m_sStartFlag = sStart;
00565     m_sStopFlag = sStop;
00566     
00567     if(!m_sStartFlag.empty())
00568         m_bEnabled = false;
00569 
00570 
00571     
00572     return true;
00573 }
00574 
00575 bool CMOOSScheduler::CEvent::OnNewMail(MOOSMSG_LIST  &NewMail)
00576 {
00577     CMOOSMsg Msg;
00578     if(!m_sStartFlag.empty() && CMOOSCommClient::PeekMail(NewMail,m_sStartFlag,Msg))
00579     {
00580         if(!Msg.IsSkewed(MOOSTime()))
00581         {
00582             Enable(true,MOOSTime());
00583         }
00584     }
00585     if(!m_sStopFlag.empty() && CMOOSCommClient::PeekMail(NewMail,m_sStopFlag,Msg))
00586     {
00587         if(!Msg.IsSkewed(MOOSTime()))
00588         {
00589             Enable(false,MOOSTime());
00590         }
00591     }
00592 
00593     if(!m_sVarName.empty() && CMOOSCommClient::PeekMail(NewMail,m_sVarName,Msg))
00594     {
00595         if(!Msg.IsSkewed(MOOSTime()))
00596         {
00597             if(Msg.IsDataType(MOOS_STRING))
00598             {
00599                 m_sVal = Msg.GetString();
00600             }
00601             else
00602             {
00603                 m_sVal = Msg.GetAsString();
00604             }
00605         }
00606     }
00607 
00608 
00609 
00610 
00611     
00612     return true;
00613 }
00614 
00615 bool CMOOSScheduler::CEvent::SetStartingTime(double dfTime)
00616 {
00617     m_dfFireTime = dfTime+m_dfOffset;
00618     return true;
00619 }
00620 
00621 bool CMOOSScheduler::CEvent::SetNameVal(string sValName)
00622 {
00623     m_sVarName   = sValName;
00624     return true;
00625 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines