BeoSubAction.C

Go to the documentation of this file.
00001 /*!@file BeoSub/BeoSubAction.C Helper class for BeoSub motor actions */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/BeoSub/BeoSubAction.C $
00035 // $Id: BeoSubAction.C 4663 2005-06-23 17:47:28Z rjpeters $
00036 //
00037 
00038 #include "BeoSub/BeoSubAction.H"
00039 #include "BeoSub/BeoSub.H"
00040 #include <cmath>
00041 
00042 // ######################################################################
00043 // ########## BeoSubAction member functions
00044 // ######################################################################
00045 BeoSubAction::BeoSubAction(BeoSub *bs, const bool pulseWidthControl) :
00046   itsBeoSub(bs), itsDeadBand(10.0f), pulseWidthControl(pulseWidthControl)
00047 { }
00048 
00049 // ######################################################################
00050 BeoSubAction::~BeoSubAction()
00051 { }
00052 
00053 // ######################################################################
00054 bool BeoSubAction::execute(const float target, const bool stabil, const int itsMaxIter)
00055 {
00056 
00057   if(pulseWidthControl){
00058     return pulseWidthExecute(target, stabil, itsMaxIter);
00059   }
00060   int iter = 0;
00061   itsErrIndex = 0;
00062   itsErrorHistory[itsErrIndex] = difference(getPosition(), target);
00063 
00064 
00065   while(iter < itsMaxIter)
00066     {
00067             float pos = getPosition();
00068         //difference between current pos and target pos
00069         itsErrorHistory[(itsErrIndex+1)%20] = difference(pos,  target);
00070         //difference between current error and error in the previous iteration
00071         float errDiff = itsErrorHistory[(itsErrIndex+1)%20] - itsErrorHistory[itsErrIndex];
00072 
00073         LDEBUG("pos = %f, target = %f", pos, target);
00074         LDEBUG("Current error = %f, Previous Error = %f, errDiff = %f", itsErrorHistory[(itsErrIndex+1)%20], itsErrorHistory[itsErrIndex], errDiff);
00075 
00076         // have we achieved the target position?
00077         if (fabsf(difference(pos, target)) < itsDeadBand) return true; // done
00078 
00079         //calculate the total error for integral control
00080         float totalErr  = 0; // total error over last 20 iterations
00081         for(int i = 0; i < 20; i ++)
00082           totalErr += itsErrorHistory[i];
00083 
00084         LDEBUG("Total error = %f", totalErr);
00085 
00086         //calculating number of pulses based on PID control
00087         u = itsGainP*itsErrorHistory[(itsErrIndex+1)%20]
00088           + itsGainD*errDiff
00089           + itsGainI*totalErr;
00090         LDEBUG("u = %f", u);
00091         int numOfPulses;
00092         if(fabsf(u) > 8 )
00093           numOfPulses = 8;
00094         else
00095           numOfPulses = int(fabsf(u));
00096         // activate according to difference between current and target pos:
00097         for(float i = 0; i < numOfPulses; i++){
00098            activate(u > 0);
00099            // if desired, stabilize a bit:
00100            if (stabil) stabilize();
00101         }
00102 
00103         iter ++;
00104         itsErrIndex = (itsErrIndex +1)%20;
00105         usleep(50000);
00106     }
00107 
00108   LINFO("Max number (%d) of iterations reached -- GIVING UP", itsMaxIter);
00109   return false;
00110 }
00111 
00112 
00113 // ######################################################################
00114 bool BeoSubAction::pulseWidthExecute(const float target, const bool stabil, const int itsMaxIter)
00115 {
00116   int iter = 0;
00117   itsErrIndex = 0;
00118   itsErrorHistory[itsErrIndex] = difference(getPosition(), target);
00119 
00120 
00121   while(iter < itsMaxIter)
00122     {
00123             float pos = getPosition();
00124         //difference between current pos and target pos
00125         itsErrorHistory[(itsErrIndex+1)%20] = difference(pos,  target);
00126         //difference between current error and error in the previous iteration
00127         float errDiff = itsErrorHistory[(itsErrIndex+1)%20] - itsErrorHistory[itsErrIndex];
00128 
00129         LDEBUG("Pulse Width: pos = %f, target = %f", pos, target);
00130         LDEBUG("Pulse Width: Current error = %f, Previous Error = %f, errDiff = %f", itsErrorHistory[(itsErrIndex+1)%20], itsErrorHistory[itsErrIndex], errDiff);
00131 
00132         // have we achieved the target position?
00133         if (fabsf(difference(pos, target)) < itsDeadBand) return true; // done
00134 
00135         //calculate the total error for integral control
00136         float totalErr  = 0; // total error over last 20 iterations
00137         for(int i = 0; i < 20; i ++)
00138           totalErr += itsErrorHistory[i];
00139 
00140         LDEBUG("Pulse Width: Total error = %f", totalErr);
00141 
00142         //calculating number of pulses based on PID control
00143         u = itsGainP*itsErrorHistory[(itsErrIndex+1)%20]
00144           + itsGainD*errDiff
00145           + itsGainI*totalErr;
00146         LDEBUG("u = %f", u);
00147         if(turnOnTime < 0)
00148           turnOnTime ++;
00149 
00150         if(turnOnTime == 0){
00151           turnOnTime = int(fabsf(u));
00152           turnOnMotor(u > 0);
00153         }
00154 
00155         if(turnOnTime > 0){
00156           turnOnTime --;
00157           if(turnOnTime == 0)
00158             turnOffMotor(u > 0);
00159           turnOnTime = -3;
00160         }
00161 
00162         // if desired, stabilize a bit:
00163         if (stabil) stabilize(pulseWidthControl);
00164         iter ++;
00165         itsErrIndex = (itsErrIndex +1)%20;
00166         usleep(50000);
00167     }
00168 
00169   LINFO("Max number (%d) of iterations reached -- GIVING UP", itsMaxIter);
00170   return false;
00171 }
00172 
00173 
00174 // ######################################################################
00175 // ########## BeoSubActionDive member functions
00176 // ######################################################################
00177 BeoSubActionDive::BeoSubActionDive(BeoSub *bs, const bool pulseWidthControl) :
00178   BeoSubAction(bs, pulseWidthControl)
00179 {
00180   itsDeadBand = 5.0f; //FIXME: what are the units???
00181 
00182   if(pulseWidthControl){
00183     itsGainP = 10.0f/5;
00184     itsGainD = 0;
00185     itsGainI = 0.01f/1;
00186   }else{
00187     itsGainP = 13.0f/5;
00188     itsGainD = 0;
00189     itsGainI = 0.01f/1;
00190   }
00191   // get current heading in case we want to stabilize it:
00192   itsHeading = itsBeoSub->getHeading();
00193 }
00194 
00195 // ######################################################################
00196 BeoSubActionDive::~BeoSubActionDive()
00197 { }
00198 
00199 // ######################################################################
00200 bool BeoSubActionDive::activate(const bool incr)
00201 {
00202   // one pulse on vertical thruster
00203   itsBeoSub->pulseMotor(BSM_UPDOWN, !incr);
00204   return true;
00205 }
00206 
00207 // ######################################################################
00208 bool BeoSubActionDive::turnOnMotor(const bool incr){
00209   itsBeoSub->turnOnMotor(BSM_UPDOWN, !incr);
00210   return true;
00211 }
00212 
00213 // ######################################################################
00214 bool BeoSubActionDive::turnOffMotor(const bool incr){
00215   itsBeoSub->turnOffMotor(BSM_UPDOWN);
00216   return true;
00217 }
00218 
00219 // ######################################################################
00220 float BeoSubActionDive::getPosition() const
00221 { return itsBeoSub->getDepth(); }
00222 
00223 // ######################################################################
00224 bool BeoSubActionDive::stabilize(const bool pulseWidthControl)
00225 {
00226   BeoSubActionTurn t(itsBeoSub, pulseWidthControl);
00227 
00228   return t.execute(itsHeading, false, 1);
00229 }
00230 
00231 // ######################################################################
00232 float BeoSubActionDive::difference(float pos, float target)
00233 {
00234   return pos - target;
00235 }
00236 
00237 
00238 // ######################################################################
00239 // ########## BeoSubActionTurn member functions
00240 // ######################################################################
00241 BeoSubActionTurn::BeoSubActionTurn(BeoSub *bs, const bool pulseWidthControl) :
00242   BeoSubAction(bs, pulseWidthControl)
00243 {
00244   itsDeadBand = 10.0f; //FIXME: what are the units???
00245 
00246   if(pulseWidthControl){
00247     itsGainP = 5.0f/20;
00248     itsGainD = 0;
00249     itsGainI = 0.01f/5;
00250   }
00251   else{
00252     itsGainP = 5.0f/20;
00253     itsGainD = 0;
00254     itsGainI = 0.01f/5;
00255   }
00256   // get current depth in case we want to stabilize it:
00257   itsDepth = itsBeoSub->getDepth();
00258 }
00259 
00260 // ######################################################################
00261 BeoSubActionTurn::~BeoSubActionTurn()
00262 { }
00263 
00264 // ######################################################################
00265 bool BeoSubActionTurn::activate(const bool incr)
00266 {
00267   // one pulse on lateral thrusters
00268   itsBeoSub->pulseMotor(BSM_LEFTRIGHT, incr);
00269   return true;
00270 }
00271 // ######################################################################
00272 bool BeoSubActionTurn::turnOnMotor(const bool incr){
00273   itsBeoSub->turnOnMotor(BSM_UPDOWN, !incr);
00274   return true;
00275 }
00276 
00277 // ######################################################################
00278 bool BeoSubActionTurn::turnOffMotor(const bool incr){
00279   itsBeoSub->turnOffMotor(BSM_UPDOWN);
00280   return true;
00281 }
00282 
00283 // ######################################################################
00284 float BeoSubActionTurn::getPosition() const
00285 { return itsBeoSub->getHeading(); }
00286 
00287 // ######################################################################
00288 bool BeoSubActionTurn::stabilize(const bool pulseWidthControl)
00289 {
00290   BeoSubActionDive d(itsBeoSub, pulseWidthControl);
00291   return d.execute(itsDepth, false, 1);
00292 }
00293 
00294 // ######################################################################
00295 float BeoSubActionTurn::difference(float pos, float target)
00296 {
00297   //assuming turning clockwise is positive
00298   if(fabsf(pos - target) > 180){
00299     if(pos > target)
00300       return target + 360 - pos;
00301     else
00302         return pos + 360 - target;
00303   }
00304   else
00305     return (pos - target);
00306 
00307 }
00308 
00309 // ######################################################################
00310 /* So things look consistent in everyone's emacs... */
00311 /* Local Variables: */
00312 /* indent-tabs-mode: nil */
00313 /* End: */
Generated on Sun May 8 08:04:32 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3