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 Instrument. 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 // MOOSActuation.cpp: implementation of the CMOOSActuation class. 00032 // 00034 #ifdef _WIN32 00035 #pragma warning(disable : 4786) 00036 #endif 00037 00038 #include <MOOSLIB/MOOSLib.h> 00039 #include "MOOSActuation.h" 00040 #include "MOOSActuationDriver.h" 00041 #include "MOOSSAILDriver.h" 00042 #include "MOOSJRKerrDriver.h" 00043 #include "MOOSASCDriver.h" 00044 #include "MOOSBluefinDriver.h" 00045 00046 #include <iostream> 00047 #include <math.h> 00048 00049 #define ACTUATION_WATCHDOG_PERIOD 10.0 00050 #define HW_WATCHDOG_PERIOD 4.0 00051 00053 // Construction/Destruction 00055 00056 CMOOSActuation::CMOOSActuation() 00057 { 00058 00059 m_bSimMode=false; 00060 00061 //some sensible defaults (missionfile can overwrite this) 00062 SetAppFreq(5); 00063 SetCommsFreq(8); 00064 00065 m_pDriver = NULL; 00066 00067 m_dfLastRPMTime = MOOSTime(); 00068 00069 } 00070 00071 CMOOSActuation::~CMOOSActuation() 00072 { 00073 00074 } 00075 00076 bool CMOOSActuation::Iterate() 00077 { 00078 00079 for(int i = 0; i<sizeof(m_Motors)/sizeof(m_Motors[0]);i++) 00080 { 00081 if(m_Motors[i].HasExpired()) 00082 { 00083 const char *Names[] = {"RUDDER","ELEVATOR","THRUST"}; 00084 if(m_Port.IsVerbose()) 00085 { 00086 MOOSTrace("watchdog reset %s=0\n",Names[i]); 00087 } 00088 //here we set the desired thriust to zero as 00089 //no one is telling us what to do - we may be 00090 //the only process left in the known universe 00091 MOOSTrace("*---*\n"); 00092 m_Motors[i].SetDesired(0,MOOSTime()); 00093 } 00094 00095 CMOOSActuation::MotorName Name = (CMOOSActuation::MotorName)i; 00096 DoIO(Name); 00097 } 00098 00099 00100 if(!IsSimulateMode()) 00101 { 00102 if(MOOSTime()-m_dfLastRPMTime>4.0) 00103 { 00104 m_Comms.Notify("ACTUATION_RPM",m_pDriver->GetRPM(),MOOSTime()); 00105 m_dfLastRPMTime = MOOSTime(); 00106 } 00107 00108 //here we look after hardware wathcdog - we tell teh 00109 //hardware that the actuation driver process is still here 00110 //so don't shut down on us! 00111 if(!HandleHWWatchDog()) 00112 return false; 00113 } 00114 00115 return true; 00116 } 00117 00118 00119 00120 bool CMOOSActuation::DoIO(CMOOSActuation::MotorName Name) 00121 { 00122 00123 bool bResult = false; 00124 00125 if(m_Motors[Name].IsUpdateRequired()) 00126 { 00127 00128 if(IsSimulateMode()) 00129 { 00130 //here we send commands to the simulator 00131 //to instruct it to change thrust etc.. 00132 string sVarName; 00133 switch(Name) 00134 { 00135 case THRUST: sVarName = "SIM_DESIRED_THRUST"; break; 00136 case RUDDER: sVarName = "SIM_DESIRED_RUDDER"; break; 00137 case ELEVATOR: sVarName = "SIM_DESIRED_ELEVATOR"; break; 00138 } 00139 00140 bResult = m_Comms.Notify(sVarName,m_Motors[Name].GetDesired()); 00141 } 00142 else 00143 { 00144 double dfRudder, dfElevator; 00145 00146 switch(Name) 00147 { 00148 00149 //here the call to the driver itself are made... 00150 case THRUST: 00151 bResult = m_pDriver->SetThrust(m_Motors[Name].GetDesired()); 00152 break; 00153 00154 case RUDDER: 00155 dfRudder = m_Motors[Name].GetDesired(); 00156 dfElevator = m_Motors[ELEVATOR].GetDesired(); 00157 MOOSTrace(MOOSFormat("Rudder in: %.3f <Elev in %.3f>\n", dfRudder, dfElevator)); 00158 00159 if(m_RollTransform.IsTransformRequired()) 00160 { 00161 m_RollTransform.Transform(dfRudder, dfElevator); 00162 00163 //if transforming, must also set elevator 00164 bResult &= m_pDriver->SetRudder(dfRudder); 00165 bResult &= m_pDriver->SetElevator(dfElevator); 00166 } 00167 else 00168 { 00169 bResult = m_pDriver->SetRudder(dfRudder); 00170 } 00171 00172 MOOSTrace(MOOSFormat("Rudder out: %.3f <Elev out %.3f>\n", dfRudder, dfElevator)); 00173 break; 00174 00175 case ELEVATOR: 00176 dfRudder = m_Motors[RUDDER].GetDesired(); 00177 dfElevator = m_Motors[Name].GetDesired(); 00178 MOOSTrace(MOOSFormat("Elev in: %.3f <Rudder in %.3f>\n", dfElevator, dfRudder)); 00179 00180 if(m_RollTransform.IsTransformRequired()) 00181 { 00182 m_RollTransform.Transform(dfRudder, dfElevator); 00183 00184 //if transforming, must also set elevator 00185 bResult &= m_pDriver->SetRudder(dfRudder); 00186 bResult &= m_pDriver->SetElevator(dfElevator); 00187 } 00188 else 00189 { 00190 bResult = m_pDriver->SetElevator(dfElevator); 00191 } 00192 00193 MOOSTrace(MOOSFormat("Elev out: %.3f <Rudder out %.3f>\n", dfElevator, dfRudder)); 00194 break; 00195 } 00196 00197 OnActuationSet(); 00198 00199 00200 } 00201 00202 //and here we remember what the current setting is 00203 if(bResult == true) 00204 { 00205 m_Motors[Name].SetValue(m_Motors[Name].GetDesired(),MOOSTime()); 00206 00207 } 00208 00209 } 00210 else 00211 { 00212 bResult = true; 00213 } 00214 00215 00216 return bResult; 00217 } 00218 00219 00220 00221 00222 00223 bool CMOOSActuation::OnConnectToServer() 00224 { 00225 00226 //want to be told about pretty much every change.. 00227 m_Comms.Register("DESIRED_THRUST",0.01); 00228 m_Comms.Register("DESIRED_ELEVATOR",0.01); 00229 m_Comms.Register("DESIRED_RUDDER",0.01); 00230 m_Comms.Register("ZERO_RUDDER",0.01); 00231 m_Comms.Register("ZERO_ELEVATOR",0.01); 00232 m_Comms.Register("RESET_ACTUATION",1.0); 00233 00234 //to support transformations 00235 m_Comms.Register("INS_ROLL",0.01); 00236 00237 return true; 00238 } 00239 00240 bool CMOOSActuation::OnNewMail(MOOSMSG_LIST &NewMail) 00241 { 00242 CMOOSMsg Msg; 00243 double dfTimeNow = MOOSTime(); 00244 00245 //to support transformations 00246 if(m_Comms.PeekMail(NewMail,"INS_ROLL",Msg)) 00247 { 00248 if(!Msg.IsSkewed(MOOSTime())) 00249 { 00250 m_RollTransform.SetValue(Msg.m_dfVal, dfTimeNow); 00251 } 00252 } 00253 00254 if(m_Comms.PeekMail(NewMail,"DESIRED_THRUST",Msg,false,true)) 00255 { 00256 m_Motors[THRUST].SetDesired(Msg.m_dfVal,dfTimeNow); 00257 } 00258 00259 if(m_Comms.PeekMail(NewMail,"DESIRED_ELEVATOR",Msg,false,true)) 00260 { 00261 m_Motors[ELEVATOR].SetDesired(Msg.m_dfVal,Msg.m_dfTime); 00262 } 00263 00264 if(m_Comms.PeekMail(NewMail,"DESIRED_RUDDER",Msg,false,true)) 00265 { 00266 m_Motors[RUDDER].SetDesired(Msg.m_dfVal,Msg.m_dfTime); 00267 } 00268 00269 if(m_Comms.PeekMail(NewMail,"ZERO_RUDDER",Msg)) 00270 { 00271 if(!Msg.IsSkewed(MOOSTime())) 00272 { 00273 m_pDriver->SetZeroRudder(); 00274 } 00275 } 00276 00277 if(m_Comms.PeekMail(NewMail,"RESET_ACTUATION",Msg)) 00278 { 00279 if(!Msg.IsSkewed(MOOSTime())) 00280 { 00281 Reset(); 00282 } 00283 } 00284 00285 if(m_Comms.PeekMail(NewMail,"ZERO_ELEVATOR",Msg)) 00286 { 00287 if(!Msg.IsSkewed(MOOSTime())) 00288 { 00289 m_pDriver->SetZeroElevator(); 00290 } 00291 } 00292 00293 return true; 00294 } 00295 00296 00297 00298 bool CMOOSActuation::OnStartUp() 00299 { 00300 00301 //call base class version first... 00302 CMOOSInstrument::OnStartUp(); 00303 00304 00305 if(IsSimulateMode()) 00306 { 00307 SetAppFreq(5); 00308 SetCommsFreq(10); 00309 } 00310 else 00311 { 00312 if(!m_MissionReader.GetConfigurationParam("DRIVER",m_sDriverType)) 00313 { 00314 MOOSTrace("Driver type not specified!!\n"); 00315 MOOSPause(2000); 00316 return false; 00317 } 00318 00319 //added to support actuation transforms 11/4/02 00320 string sTfm; 00321 if(!m_MissionReader.GetConfigurationParam("TRANSFORM",sTfm)) 00322 { 00323 MOOSDebugWrite("Tailcone Transformation: NO"); 00324 m_RollTransform.SetTransformRequired(false); 00325 } 00326 else 00327 { 00328 bool bTfm = MOOSStrCmp(sTfm, "TRUE") ? true : false; 00329 m_RollTransform.SetTransformRequired(bTfm); 00330 00331 MOOSDebugWrite(MOOSFormat("Tailcone Transformation: %s", (bTfm ? "YES" : "NO"))); 00332 } 00333 00334 if(MOOSStrCmp(m_sDriverType,"SAIL")) 00335 { 00336 m_pDriver = new CMOOSSAILDriver; 00337 MOOSTrace("Loading SAIL driver\n"); 00338 } 00339 else if(MOOSStrCmp(m_sDriverType,"ASC")) 00340 { 00341 m_pDriver = new CMOOSASCDriver; 00342 MOOSTrace("Loading ASC driver\n"); 00343 } 00344 else if(MOOSStrCmp(m_sDriverType,"BLUEFIN")) 00345 { 00346 m_pDriver = new CMOOSBluefinDriver; 00347 MOOSTrace("Loading BLUEFIN driver\n"); 00348 } 00349 else if(MOOSStrCmp(m_sDriverType,"JRKERR")) 00350 { 00351 m_pDriver = new CMOOSJRKerrDriver; 00352 MOOSTrace("Loading JRKerr driver\n"); 00353 } 00354 else 00355 { 00356 MOOSTrace("Only SAIL,ASC and Bluefin Drivers supported in this release\n"); 00357 return false; 00358 } 00359 00360 //try to open 00361 if(!SetupPort()) 00362 { 00363 return false; 00364 } 00365 00366 m_pDriver->SetPort(&m_Port); 00367 00368 double dfTmp=0; 00369 if(m_MissionReader.GetConfigurationParam("RudderOffset",dfTmp)) 00370 { 00371 m_pDriver->SetRudderOffset(dfTmp); 00372 } 00373 00374 if(m_MissionReader.GetConfigurationParam("ElevatorOffset",dfTmp)) 00375 { 00376 m_pDriver->SetElevatorOffset(dfTmp); 00377 } 00378 00379 00380 if(Reset()==false) 00381 { 00382 return false; 00383 } 00384 00385 00386 00387 } 00388 00389 return true; 00390 } 00391 00395 CMOOSActuation::RollTransform::RollTransform() 00396 { 00397 m_dfVal = 0; 00398 m_dfDesired = 0; 00399 m_dfTimeSet = MOOSTime(); 00400 m_dfTimeRequested = m_dfTimeSet; 00401 m_bTransform = false; 00402 } 00403 00404 bool CMOOSActuation::RollTransform::Transform(double &dfRudder, double &dfElevator) 00405 { 00406 00407 //m_dfVal is the roll which comes from DB as radians 00408 MOOSTrace(MOOSFormat("Roll for Tform: %.3f\n", m_dfVal)); 00409 double roll = m_dfVal; 00410 00411 //input is in degrees, so convert to radians 00412 dfRudder = MOOSDeg2Rad(dfRudder); 00413 dfElevator = MOOSDeg2Rad(dfElevator); 00414 MOOSTrace(MOOSFormat("radian conv: %.3f %.3f\n", dfRudder, dfElevator)); 00415 00416 double dfR = cos(roll)*tan(dfRudder) + sin(roll)*tan(dfElevator); 00417 double dfE = -sin(roll)*tan(dfRudder) + cos(roll)*tan(dfElevator); 00418 00419 MOOSTrace(MOOSFormat("new val: %.3f %.3f\n", dfR, dfE)); 00420 00421 //convert back to degrees! 00422 dfRudder = MOOSRad2Deg(atan(dfR)); 00423 dfElevator = MOOSRad2Deg(atan(dfE)); 00424 00425 return true; 00426 } 00427 00428 bool CMOOSActuation::RollTransform::IsTransformRequired() 00429 { 00430 return m_bTransform; 00431 } 00432 00433 void CMOOSActuation::RollTransform::SetTransformRequired(bool bTForm) 00434 { 00435 m_bTransform = bTForm; 00436 } 00437 00438 CMOOSActuation::ActuatorDOF::ActuatorDOF() 00439 { 00440 m_dfVal = 0; 00441 m_dfDesired = 0; 00442 m_dfTimeSet = MOOSTime(); 00443 m_dfRefreshPeriod = ACTUATION_WATCHDOG_PERIOD; 00444 m_dfTimeRequested = m_dfTimeSet; 00445 } 00446 00447 bool CMOOSActuation::ActuatorDOF::IsUpdateRequired() 00448 { 00449 if(m_dfVal!=m_dfDesired) 00450 return true; 00451 00452 if(MOOSTime()-m_dfTimeSet>m_dfRefreshPeriod) 00453 return true; 00454 00455 00456 00457 return false; 00458 } 00459 00460 bool CMOOSActuation::ActuatorDOF::HasExpired() 00461 { 00462 double dfTimeNow = MOOSTime(); 00463 double dfDT =dfTimeNow-m_dfTimeRequested; 00464 return (dfDT)>m_dfRefreshPeriod; 00465 } 00466 00467 bool CMOOSActuation::ActuatorDOF::SetDesired(double dfVal,double dfTime) 00468 { 00469 if(dfTime>=m_dfTimeRequested) 00470 { 00471 m_dfDesired =dfVal; 00472 m_dfTimeRequested = dfTime; 00473 return true; 00474 } 00475 else 00476 { 00477 return false; 00478 } 00479 } 00480 00481 double CMOOSActuation::ActuatorDOF::GetDesired() 00482 { 00483 return m_dfDesired; 00484 } 00485 00486 00487 bool CMOOSActuation::ActuatorDOF::SetValue(double dfVal,double dfTime) 00488 { 00489 m_dfVal = dfVal; 00490 m_dfTimeSet = dfTime; 00491 return true; 00492 } 00493 /* 00494 bool CMOOSActuation::IsASC() 00495 { 00496 return MOOSStrCmp(m_sDriverType,"ASC"); 00497 } 00498 00499 00500 bool CMOOSActuation::IsBluefin() 00501 { 00502 return MOOSStrCmp(m_sDriverType,"BLUEFIN"); 00503 } 00504 */ 00505 00506 bool CMOOSActuation::HandleHWWatchDog() 00507 { 00508 if(IsSimulateMode()) 00509 return true; 00510 00511 #define MAX(a,b) ((a)>(b)?(a):(b)) 00512 double dfLastSet = MAX(MAX(m_Motors[THRUST].GetTimeSet(),m_Motors[RUDDER].GetTimeSet()), m_Motors[ELEVATOR].GetTimeSet()); 00513 double dfDT = MOOSTime()-dfLastSet; 00514 00515 if(dfDT>HW_WATCHDOG_PERIOD) 00516 { 00517 bool bResult = m_pDriver->SetThrust(m_Motors[THRUST].GetDesired()); 00518 00519 OnActuationSet(); 00520 00521 if(bResult) 00522 { 00523 MOOSTrace("***\n"); 00524 m_Motors[THRUST].SetValue(m_Motors[THRUST].GetDesired(),MOOSTime()); 00525 } 00526 else 00527 { 00528 return false; 00529 } 00530 00531 00532 } 00533 00534 return true; 00535 } 00536 00537 double CMOOSActuation::ActuatorDOF::GetTimeSet() 00538 { 00539 return m_dfTimeSet; 00540 } 00541 00542 bool CMOOSActuation::Reset() 00543 { 00544 //ask for the resource to be turned on... 00545 m_Comms.Notify("JANITOR_SWITCH",m_sResourceName+":ON"); 00546 MOOSTrace("Requesting \"%s\" power switch...",m_sResourceName.c_str()); 00547 MOOSPause(2000); 00548 MOOSTrace("OK\n"); 00549 00550 double dfTimeNow = MOOSTime(); 00551 00552 m_Motors[THRUST].SetDesired(0,dfTimeNow); 00553 m_Motors[RUDDER].SetDesired(0,dfTimeNow); 00554 m_Motors[ELEVATOR].SetDesired(0,dfTimeNow); 00555 00556 if(!IsSimulateMode() && !m_pDriver->Initialise()) 00557 { 00558 MOOSTrace("Driver failed initialisation\n"); 00559 return false; 00560 00561 } 00562 return true; 00563 } 00564 00565 bool CMOOSActuation::OnActuationSet() 00566 { 00567 //we publish a variable to say we are still here... 00568 return m_Comms.Notify("ACTUATION_WD_HIT",MOOSTime()); 00569 00570 } 00571