BeobotControl.C

Go to the documentation of this file.
00001 /*!@file Beobot/BeobotControl.C control the movement of the Beobot
00002   (via BeoChip)                                                         */
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // 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: Christian Siagian <siagian@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Beobot/BeobotControl.C $
00035 // $Id: BeobotControl.C 7063 2006-08-29 18:26:55Z rjpeters $
00036 
00037 #include "Beobot/BeobotControl.H"
00038 #include "Component/OptionManager.H"
00039 #include "Util/Types.H"
00040 #include "Util/log.H"
00041 #include <math.h>
00042 
00043 #define MAX_SERVO_MOVE .10
00044 
00045 // ######################################################################
00046 void *speedRampFunc( void *ptr )
00047 {
00048   // number of times we set speed each second
00049   const int signalsPerSecond = 50;
00050   const uint64 delayPerSignal = 1000000 / signalsPerSecond;
00051 
00052   float startSpeed;
00053   float desiredSpeed;
00054   int desiredTime;
00055   int currentTime;
00056   SpeedRampType type;
00057 
00058   bool threadOK;
00059   Timer tmr( 1000000 );
00060 
00061   // cast our void pointer back to CarControl
00062   BeobotControl *bc = reinterpret_cast<BeobotControl *>(ptr);
00063 
00064   // loop while thread is supposed to be active and ramping is not yet done
00065   do
00066     {
00067       // start timing
00068       tmr.reset();
00069 
00070       // lock our speed ramping related variables
00071       pthread_mutex_lock( &(bc->speedRampMutex) );
00072 
00073       startSpeed = bc->startSpeed;
00074       desiredSpeed = bc->desiredSpeed;
00075       desiredTime = bc->desiredTime;
00076       currentTime = bc->speedRampTimer.get();
00077       type = bc->speedRampType;
00078       threadOK = bc->speedRampThreadCreated;
00079 
00080       // done reading shared variables
00081       pthread_mutex_unlock( &(bc->speedRampMutex) );
00082 
00083       if( threadOK )
00084         {
00085           // if time is up, set and return
00086           if( currentTime >= desiredTime )
00087             {
00088               LDEBUG( "Time's up!  Will exit speed ramping thread..." );
00089               break;
00090             }
00091 
00092           // otherwise, do ramping
00093           else
00094             {
00095               switch( type )
00096                 {
00097                 case SPEED_RAMP_LINEAR:
00098                   bc->setSpeed( startSpeed + ( desiredSpeed - startSpeed ) /
00099                                 desiredTime * currentTime );
00100                   break;
00101                 case SPEED_RAMP_SIGMOID:
00102                   bc->setSpeed( startSpeed + ( desiredSpeed - startSpeed ) *
00103                                 ( 1.0f / ( 1.0f +
00104                                            exp( -10.0f / desiredTime *
00105                                                 currentTime + 5.0f ) ) ) );
00106                   break;
00107                 default:
00108                   // user did not specify a valid ramping type
00109                   LERROR( "Invalid speed ramping type: %d", type );
00110                   break;
00111                 }
00112             }
00113         }
00114 
00115       // wait until time is up before next signal
00116       while( tmr.get() < delayPerSignal )
00117         {
00118           // do nothing
00119         }
00120     }
00121   while( threadOK );
00122 
00123   LDEBUG( "Speed ramping thread finished" );
00124   pthread_mutex_lock( &(bc->speedRampMutex ) );
00125   bc->speedRampThreadCreated = false;
00126   pthread_mutex_unlock( &(bc->speedRampMutex ) );
00127 
00128   return 0;
00129 }
00130 
00131 // ######################################################################
00132 BeobotControl::BeobotControl(nub::soft_ref<BeoChip> beoChip,
00133                              OptionManager& mgr, const std::string& descrName,
00134                              const std::string& tagName) :
00135   ModelComponent(mgr, descrName, tagName),
00136   itsBeoChip(beoChip),
00137   speedRampTimer( 1000 )
00138 {
00139   // BeoChip is calibrated in the constructor
00140 
00141   // use the raw value to initialize the servo values
00142   // keep the gear at the lowest speed/highest torque
00143   itsBeoChip->setServoRaw(itsBeobotConfig.speedServoNum,
00144                           itsBeobotConfig.speedNeutralVal);
00145   itsBeoChip->setServoRaw(itsBeobotConfig.steerServoNum,
00146                           itsBeobotConfig.steerNeutralVal);
00147   itsBeoChip->setServoRaw(itsBeobotConfig.gearServoNum,
00148                           itsBeobotConfig.gearMinVal);
00149 
00150   // not using speed ramping thread yet
00151   speedRampThreadCreated = false;
00152 }
00153 
00154 // ######################################################################
00155 BeobotControl::~BeobotControl(){ }
00156 
00157 // ######################################################################
00158 float BeobotControl::getSpeed() const
00159 { return itsBeoChip->getServo(itsBeobotConfig.speedServoNum); }
00160 
00161 // ######################################################################
00162 float BeobotControl::getSteer() const
00163 { return itsBeoChip->getServo(itsBeobotConfig.steerServoNum); }
00164 
00165 // ######################################################################
00166 float BeobotControl::getGear() const
00167 { return itsBeoChip->getServo(itsBeobotConfig.gearServoNum ); }
00168 
00169 // ######################################################################
00170 bool BeobotControl::setSpeed(const float newspeed)
00171 {
00172   // check if newspeed is within limit
00173   float procspeed = newspeed;
00174   if(newspeed > 1.0f) procspeed = 1.0f;
00175   else if(newspeed < -1.0f) procspeed = -1.0f;
00176 
00177   pthread_mutex_lock( &setSpeedMutex );
00178 
00179   // make sure the speed assignment does not go beyond the jump limit
00180   float currspeed = getSpeed();
00181   if(procspeed > currspeed + MAX_SERVO_MOVE)
00182     procspeed = currspeed + MAX_SERVO_MOVE;
00183   else if(procspeed < currspeed - MAX_SERVO_MOVE)
00184     procspeed = currspeed - MAX_SERVO_MOVE;
00185 
00186   bool setOK =
00187     itsBeoChip->setServo(itsBeobotConfig.speedServoNum, procspeed);
00188   pthread_mutex_unlock( &setSpeedMutex );
00189   return setOK;
00190 }
00191 
00192 // ######################################################################
00193 bool BeobotControl::setSteer(const float newsteer)
00194 {
00195   // check if newsteer is within limit
00196   float procsteer = newsteer;
00197   if(newsteer > 1.0f) procsteer = 1.0f;
00198   else if(newsteer < -1.0f) procsteer = -1.0f;
00199 
00200   // make sure the steer assignment does not go beyond the jump limit
00201   float currsteer = getSteer();
00202   if(procsteer > currsteer + MAX_SERVO_MOVE)
00203     procsteer = currsteer + MAX_SERVO_MOVE;
00204   else if(procsteer < currsteer - MAX_SERVO_MOVE)
00205     procsteer = currsteer - MAX_SERVO_MOVE;
00206 
00207   return itsBeoChip->setServo(itsBeobotConfig.steerServoNum, procsteer);
00208 }
00209 
00210 // ######################################################################
00211 bool BeobotControl::setGear(const float newgear)
00212 {
00213   // check if newgear is within limit
00214   float procgear = newgear;
00215   if(newgear > 1.0f) procgear = 1.0f;
00216   else if(newgear < -1.0f) procgear = -1.0f;
00217 
00218   // make sure the gear assignment does not go beyond the jump limit
00219   float currgear = getGear();
00220   if(procgear > currgear + MAX_SERVO_MOVE)
00221     procgear = currgear + MAX_SERVO_MOVE;
00222   else if(procgear < currgear - MAX_SERVO_MOVE)
00223     procgear = currgear - MAX_SERVO_MOVE;
00224 
00225   return itsBeoChip->setServo(itsBeobotConfig.gearServoNum, procgear);
00226 }
00227 
00228 // ######################################################################
00229 void BeobotControl::stop1()
00230 {
00231   // end ramping process:
00232   pthread_cancel( speedRampThread );
00233 
00234   // let's stop the car:
00235   setSpeed(0.0F);
00236   setSteer(0.0F);
00237   setGear (0.0F);
00238 }
00239 
00240 // ######################################################################
00241 bool BeobotControl::toSpeedLinear( const float newspeed, const int t )
00242 {
00243   float current = getSpeed();
00244 
00245   // calculate how many times setSpeed() can be called in t milliseconds
00246   int calls = (int)( t / 1000.0 * 30 + 0.5 ); // 30 calls per second
00247   if( calls <= 1 )
00248   {
00249     return setSpeed( newspeed );
00250   }
00251   // calculate appropriate delta values
00252   else
00253   {
00254     bool speedChangeOk = true;
00255     float delta = ( newspeed - current ) / calls;
00256     for( int i = 0; i < calls; i++ )
00257     {
00258       speedChangeOk = speedChangeOk && setSpeed( current + delta * i );
00259       Timer tim( 1000000 );
00260       while( tim.get() < 33333 )
00261         {
00262           // couldn't get usleep() to work, this seems to do the job
00263         }
00264     }
00265     return speedChangeOk;
00266   }
00267 }
00268 
00269 // ######################################################################
00270 bool BeobotControl::toSpeedSigmoid( const float newspeed, const int t )
00271 {
00272   float current = getSpeed();
00273 
00274   // calculate how many times setSpeed() can be called in t milliseconds
00275   int calls = (int)( t / 1000.0 * 30 + 0.5 ); // 30 calls per second
00276   if( calls <= 1 )
00277   {
00278     return setSpeed( newspeed );
00279   }
00280   // calculate appropriate delta values
00281   else
00282   {
00283     bool speedChangeOk = true;
00284     for( int i = 0; i < calls; i++ )
00285     {
00286       speedChangeOk = speedChangeOk &&
00287         setSpeed( current + ( newspeed - current ) /
00288                   ( 1 + exp( -11.0825 / calls * ( i - calls/2 ) ) ) );
00289       Timer tim( 1000000 );
00290       while( tim.get() < 33333 )
00291         {
00292           // couldn't get usleep() to work, this seems to do the job
00293         }
00294     }
00295     return speedChangeOk;
00296   }
00297 
00298   return true;
00299 }
00300 
00301 // ######################################################################
00302 void BeobotControl::rampSpeed( const float newspeed, const int t,
00303                             SpeedRampType behavior )
00304 {
00305   // lock our speed ramping related variables
00306   pthread_mutex_lock( &speedRampMutex );
00307 
00308   startSpeed = getSpeed();
00309   desiredSpeed = newspeed;
00310   desiredTime = t;
00311   speedRampType = behavior;
00312   speedRampTimer.reset();
00313 
00314   // modification is now complete
00315   pthread_mutex_unlock( &speedRampMutex );
00316 
00317   // create thread if not already existing
00318   if( !speedRampThreadCreated )
00319     {
00320       speedRampThreadCreated = true;
00321       pthread_create( &speedRampThread, NULL, speedRampFunc,
00322                       reinterpret_cast<void *>(this) );
00323     }
00324 }
00325 
00326 // ######################################################################
00327 void BeobotControl::abortRamp( void )
00328 {
00329   if( speedRampThreadCreated )
00330     {
00331       speedRampThreadCreated = false;
00332       pthread_cancel( speedRampThread );
00333     }
00334 }
00335 
00336 // ######################################################################
00337 // BeobotAction BeobotControl::move(float vel, float angle)
00338 // {
00339 //   // use neural network to get the appropriate values
00340 //   return BeobotAction(0.0,0.0,0);
00341 // }
00342 
00343 // ######################################################################
00344 /* So things look consistent in everyone's emacs... */
00345 /* Local Variables: */
00346 /* indent-tabs-mode: nil */
00347 /* End: */
Generated on Sun May 8 08:40:12 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3