MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Instruments/Ocean/iActuation/MOOSActuation.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 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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines