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: */