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 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 }