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