MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Instruments/Ocean/iActuation/MOOSBluefinDriver.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 // MOOSBluefinDriver.cpp: implementation of the CMOOSBluefinDriver class.
00032 //
00034 #include <MOOSLIB/MOOSLib.h>
00035 #include <iostream>
00036 #include <math.h>
00037 #include <sstream>
00038 #include "MOOSBluefinDriver.h"
00039 
00040 #define BLUEFIN_UNKNOWN -1;
00041 #define BLUEFIN_THRUSTER 1
00042 #define BLUEFIN_RUDDER 2
00043 #define BLUEFIN_ELEVATOR 3
00044 #define BLUEFIN_MAX_ELEVATOR_ANGLE 18.0
00045 #define BLUEFIN_MAX_RUDDER_ANGLE 18.0
00046 
00047 //this is for a 6 Mhz unit
00048 #define BLUEFIN_ZERO_THRUST 92
00049 #define BLUEFIN_FS_THRUST 40
00050 #define VOLTS_2_RPM 1.87
00051 #define BLUEFIN_THRUST_DEADZONE 10
00052 
00053 
00054 #define BLUEFIN_MID_ANALOG_STROKE 144.0
00055 #define ANALOG_2_COUNTS (4000.0/(248.0-67.0))
00056 
00057 //#define BLUEFIN_ACTUATOR_FS 1608.69
00059 // Construction/Destruction
00061 
00062 CMOOSBluefinDriver::CMOOSBluefinDriver()
00063 {
00064     
00065     m_nSelectedActuation = BLUEFIN_UNKNOWN;
00066     
00067     
00068     
00069 }
00070 
00071 CMOOSBluefinDriver::~CMOOSBluefinDriver()
00072 {
00073 
00074     
00075 }
00076 
00077 
00078 
00079 bool CMOOSBluefinDriver::Initialise()
00080 {
00081     
00082     
00083     if(m_pPort != NULL )
00084     {
00085         
00086         STRING_LIST List;
00087         
00088         //Initialization isn't really needed, but it would be nice to
00089         //see the result of this. The TT8 will spit out several lines of
00090         //initialization data, which can be turned off as needed.
00091         
00092         //thruster
00093         List.push_back("BD1\r");
00094         List.push_back("M92\r");
00095         
00096 
00097         
00098         
00099         //rudder
00100         List.push_back("BD2\r");
00101 //        List.push_back("SD400\r");
00102        List.push_back("SD300\r");
00103         List.push_back("SA10\r");
00104 //        List.push_back("SM400\r");
00105 
00106         List.push_back("SM300\r");
00107         List.push_back("SF\r");
00108         List.push_back("SO\r");
00109         
00110         //elevator
00111         List.push_back("BD3\r");
00112         List.push_back("SD400\r");
00113         List.push_back("SA10\r");
00114         List.push_back("SM400\r");
00115         List.push_back("SF\r");
00116         List.push_back("SO\r");
00117         
00118         STRING_LIST::iterator p;
00119         
00120         for(p = List.begin();p!=List.end();p++)
00121         {
00122             string sCmd = *p;
00123             
00124             string sReply;
00125             
00126             if(m_pPort->IsVerbose())
00127             {
00128                 MOOSTrace("iActuation Init() : Sending %s \n",sCmd.c_str());
00129             }
00130             //note bluefin tail cone does not reply to commands...
00131             //hence false
00132             if(!SendAndAck(sCmd,sReply,false))
00133             {
00134                 MOOSTrace("Failed command\n");
00135             }
00136             MOOSPause(100);            
00137         }        
00138     }
00139     
00140     HomeActuators();
00141 
00142     //Bluefin hardware requires passing through a true zero point
00143     //briefly reversing does this....
00144     MOOSTrace("Energizing thruster...");
00145     SetThrust(-2);
00146     MOOSPause(1000);
00147     SetThrust(0);
00148     
00149 
00150     MOOSTrace("OK\n");
00151     
00152    
00153    
00154     return true;
00155 }
00156 
00157 
00158 string CMOOSBluefinDriver::GetBoardSelectString(int nActuator)
00159 {
00160     switch(nActuator)
00161     {
00162     case BLUEFIN_THRUSTER: return "BD1\r";
00163     case BLUEFIN_RUDDER: return "BD2\r";
00164     case BLUEFIN_ELEVATOR: return "BD3\r";
00165     default:
00166         MOOSTrace("Unknown board! Dummy!\n");
00167         return "BD1\r";
00168     }
00169 }
00170 
00171 bool CMOOSBluefinDriver::SelectBoard(int nActuator)
00172 {
00173     if(m_nSelectedActuation==nActuator)
00174         return true;
00175     
00176     string sReply;
00177     
00178     string sBoard = GetBoardSelectString(nActuator);
00179     
00180     //here we're checking to make sure the BD select command worked
00181     if(SendAndAck(sBoard,sReply,false))
00182     {
00183     //read EEPROM location zero - contains board ID #
00184     bool bResult = SendAndAck("RE0\r",sReply,true);
00185     if(bResult)
00186     {
00187         int nBoard = atoi(sReply.c_str());
00188         int nExpected = -1;
00189         switch(nActuator)
00190         {
00191         case BLUEFIN_THRUSTER: nExpected = 1;break;
00192         case BLUEFIN_RUDDER: nExpected = 2;break;
00193         case BLUEFIN_ELEVATOR: nExpected = 3;break;
00194         }
00195         if(nExpected!=nBoard)
00196         {
00197         MOOSTrace("Aw shucks board select didn't work\n\a");
00198         m_nSelectedActuation = BLUEFIN_UNKNOWN;
00199         return false;
00200         }
00201         else MOOSTrace("Switched to board %d\n", nBoard);
00202     }
00203     else
00204     {
00205         MOOSTrace("No reply when reading board ID\n\a");
00206         m_nSelectedActuation = BLUEFIN_UNKNOWN;
00207         return false;
00208     }
00209         m_nSelectedActuation = nActuator;
00210         return true;
00211     }
00212     else
00213     {
00214         m_nSelectedActuation = BLUEFIN_UNKNOWN;
00215         return false;
00216     }
00217 }
00218 
00219 
00220 bool CMOOSBluefinDriver::SetElevator(double dfAng,bool bAnalog)
00221 {    
00222 
00223     //return true;
00224 
00225 
00226     if(fabs(dfAng)>BLUEFIN_MAX_ELEVATOR_ANGLE)
00227     {
00228         dfAng = BLUEFIN_MAX_ELEVATOR_ANGLE*fabs(dfAng)/dfAng;
00229     }
00230 
00231     
00232     return MoveTo(BLUEFIN_ELEVATOR, dfAng+m_dfElevatorOffset,bAnalog);      
00233 }
00234 
00235 bool CMOOSBluefinDriver::SetRudder(double dfAng,bool bAnalog)
00236 {
00237 
00238     if(fabs(dfAng)>BLUEFIN_MAX_RUDDER_ANGLE)
00239     {
00240         dfAng = BLUEFIN_MAX_RUDDER_ANGLE*fabs(dfAng)/dfAng;
00241     }
00242 
00243     return MoveTo(BLUEFIN_RUDDER, dfAng+m_dfRudderOffset,bAnalog);      
00244 }
00245 
00246 bool CMOOSBluefinDriver::SetZeroElevator()
00247 {
00248     
00249         
00250     
00251     return true;
00252 }
00253 
00254 bool CMOOSBluefinDriver::SetZeroRudder()
00255 {
00256     
00257     return true;
00258 }
00259 
00260 bool CMOOSBluefinDriver::SetThrust(double dfPercent)
00261 {
00262     if(!SelectBoard(BLUEFIN_THRUSTER))
00263         return false;
00264     
00265     
00266     int nThrust;
00267     
00268     if(dfPercent>100)
00269     {
00270         dfPercent = 100.0;
00271     }
00272     if(dfPercent<-100)
00273     {
00274         dfPercent = -100.0;
00275     }
00276 
00277     double dfOffset = dfPercent>0 ? 
00278                         BLUEFIN_THRUST_DEADZONE:
00279                         -BLUEFIN_THRUST_DEADZONE;
00280    
00281     if(dfPercent==0)
00282         dfOffset = 0;
00283 
00284     nThrust = (int)((dfPercent/100.0)* BLUEFIN_FS_THRUST + BLUEFIN_ZERO_THRUST+dfOffset );    
00285         
00286     if(nThrust<0)
00287         nThrust = 0;
00288     
00289     //now format motor command
00290     stringstream os;
00291     os<<"M"<<nThrust<<"\r"<<ends;
00292     string sCmd = os.str();
00293     
00294     
00295     string sReply;
00296     
00297     if(!SendAndAck(sCmd,sReply,false))
00298         return false;
00299     
00300     
00301     return true;
00302     
00303 }
00304 
00305 
00306 
00307 bool CMOOSBluefinDriver::HomeActuators()
00308 {
00309     //home rudder
00310     SetElevator(0,true);
00311 
00312     //wait for it to get there....
00313     MOOSTrace("Homing elevator...");
00314     MOOSPause(2000);
00315     
00316     //set this to encoder position zero...
00317     string sReply;
00318     string sCmd = "HM0\r";
00319     SendAndAck(sCmd,sReply,false);
00320     
00321     MOOSTrace("done\n");
00322 
00323 
00324     //now do rudder
00325     SetRudder(0,true);
00326 
00327     //wait for it to get there....
00328     MOOSTrace("Homing rudder ");
00329     MOOSPause(2000);
00330     
00331     //set this to encoder position zero...
00332     sCmd = "HM0\r";
00333     SendAndAck(sCmd,sReply,false);
00334     
00335     MOOSTrace("done\n");
00336    
00337         
00338     return true;
00339     
00340     
00341 }
00342 
00343 //bool CMOOSBluefinDriver::HomeActuator(int nActuator)
00344 //{
00345         
00346 //    return true;
00347 //}
00348 
00349 bool CMOOSBluefinDriver::GetAnalogReading(double & dfPosition)
00350 {
00351     string sReply;
00352     //stop immediately
00353 //    SendAndAck("HI\r",sReply,false);
00354        
00355     //ability to average analog reading..
00356     int nMaxSamples = 4;
00357     int nSamples = 1;
00358     int nGood = 0;
00359     for(int n = 0;n<nMaxSamples && nGood<nSamples;n++)
00360     {
00361         string sCmd = "AD1\r";
00362         if(!SendAndAck(sCmd,sReply,true))
00363         {
00364             MOOSTrace("Failed Analog Read (try %d out of %d)\n\a",n+1,nMaxSamples);
00365         continue;
00366         }
00367 
00368     double dfJustRead = atof(sReply.c_str());
00369 
00370         if(dfJustRead> 0)
00371     {
00372         dfPosition+= dfJustRead;
00373         nGood++;
00374     }
00375     else
00376     {
00377         MOOSTrace("Experience has shown not to trust 0 volts!\n\a");
00378     }
00379 
00380 
00381     if(m_pPort->IsVerbose())
00382         {
00383             MOOSTrace("AD1 reply = %s\n",sReply.c_str());
00384         }
00385     
00386     }
00387 
00388     if(nGood==0)
00389     return false;
00390 
00391     //unwrap..
00392     dfPosition/=nGood;
00393 
00394     return true;
00395 
00396 }
00397 
00398 bool CMOOSBluefinDriver::MoveTo(int nActuation, double dfAngle,bool bAnalog/*=false*/)
00399 {
00400     
00401     if(!SelectBoard(nActuation))
00402         return false;
00403  
00404     double dfStepPosition = 0;
00405 
00406     double dfAnalogRequired = AnalogFromAngle(nActuation,dfAngle,dfStepPosition);
00407     
00408     if(bAnalog)
00409     {    
00410     MOOSTrace("ANALOG!\n");
00411         //figure out where we are...    
00412     double dfAnalogPos =0;
00413     string sReply;
00414     SendAndAck("HI\r",sReply,false);
00415     
00416     if(!GetAnalogReading(dfAnalogPos))
00417         return false;
00418     
00419     double dfAnalogError =dfAnalogRequired -dfAnalogPos;
00420 
00421     if(fabs(dfAnalogError)<2)
00422         return true;
00423 
00424     double dfCountsToMove = dfAnalogError*ANALOG_2_COUNTS;
00425     
00426     //now format an incremental move..
00427     stringstream os;
00428     os<<"II"<<(int)dfCountsToMove<<"\r"<<ends;
00429     string sCmd = os.str();
00430 
00431 
00432     return SendAndAck(sCmd,sReply,false);
00433     }    
00434     else
00435     {
00436         //now format an ABSOLUTE move..
00437     MOOSTrace("NOT ANALOG\n");
00438     string sReply;
00439 //    SendAndAck("HI\r",sReply,false);
00440 //    SendAndAck("RC\r",sReply,true);
00441     
00442     if(fabs(dfStepPosition/ANALOG_2_COUNTS)<2)
00443         return true;
00444 
00445     stringstream os;
00446     os<<"MI"<<(int)dfStepPosition<<"\r"<<ends;
00447     string sCmd = os.str();
00448     return SendAndAck(sCmd,sReply,false);
00449   
00450     }
00451 
00452 /*
00453     static ofstream Hmmm;
00454     if(!Hmmm.is_open())
00455     {
00456     Hmmm.open("HmmTest.txt");
00457     }
00458 
00459     if(nActuation == BLUEFIN_RUDDER)
00460     {
00461     Hmmm<<MOOSFormat("%.3f",MOOSTime()).c_str()<<"  ERROR: "<<dfAnalogError<<" DPOS: "<< dfAngle<<" ANPOS: "<<dfAnalogPos <<endl;    
00462     }
00463 */
00464     
00465    
00466     
00467 }
00468 
00469 double CMOOSBluefinDriver::AnalogFromAngle(int nActuation, double dfAng,double & dfStepPosition)
00470 {
00471     double dfPercentRequired = 0;
00472     
00473     dfAng*=-1;
00474 
00475     double dfL1,dfL2,dfR0,dfTheta0;
00476     
00477     //for now we assume that the offsets applied by being able to
00478     //call anywhere zero do not affect the follwing equations
00479     //as the trim angles are likely to be small.
00480     switch(nActuation)
00481     {
00482     case BLUEFIN_RUDDER:
00483         dfL1     = 0.333;
00484         dfL2     =0.075;
00485         dfR0     = 0.302;
00486         dfTheta0 = 1.045;
00487         //     dfPercentRequired = dfAng/BLUEFIN_MAX_RUDDER_ANGLE*100;
00488         break;
00489     case BLUEFIN_ELEVATOR:
00490         dfL1     = 0.35;
00491         dfL2     =0.077;
00492         dfR0     = 0.311;
00493         dfTheta0 = 0.936;
00494         
00495         //       dfPercentRequired = dfAng/BLUEFIN_MAX_ELEVATOR_ANGLE*100;
00496         break;
00497     default:
00498         MOOSTrace("Only set stroke for rudder and elevator!\n");
00499         return 0;
00500     }
00501     
00502     double dfThetaCmd = MOOSDeg2Rad(dfAng)+dfTheta0;
00503     double dfRDes = sqrt(dfL1*dfL1-2*dfL1*dfL2*cos(dfThetaCmd)+dfL2*dfL2);
00504     dfStepPosition = (94488.189)*(dfRDes-dfR0);
00505     double dfAnalog = dfStepPosition/ANALOG_2_COUNTS+BLUEFIN_MID_ANALOG_STROKE;
00506  
00507     return dfAnalog;
00508 }
00509 
00510 double CMOOSBluefinDriver::GetRPM()
00511 {
00512     return  0;
00513     if(!SelectBoard(BLUEFIN_THRUSTER))
00514         return 0;
00515     
00516     string sReply;
00517     
00518     int nDir = 1;
00519     if(SendAndAck("AD2\r",sReply,true))
00520     {
00521         double dfdir = atof(sReply.c_str());
00522         if(dfdir>0)
00523         {
00524             nDir = -1;
00525         }
00526     }   
00527     
00528     if(SendAndAck("AD1\r",sReply,true))
00529     {
00530         double dfVoltage = atof(sReply.c_str());
00531 
00532         if(m_pPort->IsVerbose())
00533         {
00534             MOOSTrace("RPM Voltage %f\n",dfVoltage);
00535         }
00536         
00537         double dfRPM = Volts2RPM(dfVoltage);
00538         
00539         return nDir*dfRPM;
00540     }
00541     
00542     return 0;
00543 }
00544 
00545 double CMOOSBluefinDriver::Volts2RPM(double dfVoltage)
00546 {
00547     //here we write a polynomial fit to experimental data
00548     //matlab used for fit
00549     
00550     return VOLTS_2_RPM*dfVoltage;
00551 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines