BeoSubOneBal.C

Go to the documentation of this file.
00001 /*!@file BeoSub/BeoSubOneBal.C An autonomous submarine with one ballast*/
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/BeoSubOneBal.C $
00035 // $Id: BeoSubOneBal.C 7880 2007-02-09 02:34:07Z itti $
00036 //
00037 
00038 #include "BeoSub/BeoSubOneBal.H"
00039 #include "Devices/HMR3300.H"
00040 #include "BeoSub/BeoSubBallast.H"
00041 #include "BeoSub/BeoSubIMU.H"
00042 #include "Util/MathFunctions.H"
00043 #include "Devices/FrameGrabberFactory.H"
00044 
00045 // ######################################################################
00046 //! Class definition for BeoSubListener
00047 /*! This is the listener class that is attached to each BeoChip in the
00048   ballast tube of the submarine. This class is just a
00049   pass-through to the function dispatchBeoChipEvent() of class
00050   BeoSubOneBal. */
00051 class BeoSubListener : public BeoChipListener
00052 {
00053 public:
00054   //! Constructor
00055   BeoSubListener(BeoSubOneBal *sub) : itsBeoSub(sub)  { }
00056 
00057   //! destructor
00058   virtual ~BeoSubListener()  { }
00059 
00060   //! get an event
00061   virtual void event(const BeoChipEventType t, const int valint,
00062                      const float valfloat)
00063   {
00064     //LDEBUG("Event: %d val = %d, fval = %f", int(t), valint, valfloat);
00065     itsBeoSub->dispatchBeoChipEvent(t, valint, valfloat);
00066   }
00067 
00068 private:
00069   BeoSubOneBal *itsBeoSub;        //!< pointer to our master
00070 };
00071 
00072 // ######################################################################
00073 // here a listener for the compass:
00074 class HMRlistener : public HMR3300Listener {
00075 public:
00076   //! Constructor
00077   HMRlistener(BeoSubOneBal *sub) : itsBeoSub(sub) { }
00078 
00079   //! Destructor
00080   virtual ~HMRlistener() {};
00081 
00082   //! New data was received
00083   virtual void newData(const Angle heading, const Angle pitch,
00084                        const Angle roll)
00085   {
00086     //LDEBUG("<Heading=%f Pitch=%f Roll=%f>", heading.getVal(),
00087     //       pitch.getVal(), roll.getVal());
00088     itsBeoSub->updateCompass(heading, pitch, roll);
00089   }
00090 
00091 private:
00092   BeoSubOneBal *itsBeoSub;
00093 };
00094 
00095 // here a listener for the compass:
00096 class IMUListener : public BeoSubIMUListener {
00097 public:
00098   //! Constructor
00099   IMUListener(BeoSubOneBal *sub) : itsBeoSub(sub) { }
00100   //! Destructor
00101   virtual ~IMUListener() {};
00102 
00103   //! New data was received
00104   virtual void newData(const float xa, const float ya, const float za,
00105                        const Angle xv, const Angle yv, const Angle zv)
00106   {
00107           itsBeoSub->updateIMU(xa, ya, za, xv, yv, zv);
00108   }
00109 private:
00110   BeoSubOneBal *itsBeoSub;
00111 };
00112 
00113 
00114 /*
00115 // ######################################################################
00116 // here a listener for the compass:
00117 class IMUlistener : public BeoSubIMUListener {
00118 public:
00119   //! Destructor
00120   virtual ~HMRlistener() {};
00121 
00122   //! New data was received
00123   virtual void newData(const float xa, const float ya, const float za,
00124                        const Angle xv, const Angle yv, const Angle zv)
00125   {
00126   }
00127 
00128 private:
00129   BeoSubOneBal *itsBeoSub;
00130 };
00131 */
00132 
00133 
00134 
00135 // ######################################################################
00136 BeoSubOneBal::BeoSubOneBal(OptionManager& mgr) :
00137   BeoSub(mgr),
00138   itsIMU(new BeoSubIMU(mgr)),
00139   itsLeftThrusterServoNum("BeoSubLeftThrusterServoNum", this, 3),
00140   itsRightThrusterServoNum("BeoSubRightThrusterServoNum", this, 2),
00141   itsHMR3300(new HMR3300(mgr)),
00142   itsBeo(new BeoChip(mgr, "BeoChip", "BeoChip")),
00143   itsFballast(new BeoSubBallast(mgr, "Front Ballast", "FrontBallast")),
00144   itsRballast(new BeoSubBallast(mgr, "Rear Ballast", "RearBallast")),
00145   itsCameraFront(makeIEEE1394grabber(mgr, "Front Camera", "FrontCamera")),
00146   itsCameraDown(makeIEEE1394grabber(mgr, "Down Camera", "DownCamera")),
00147   itsCameraUp(makeIEEE1394grabber(mgr, "Up Camera", "UpCamera")),
00148   itsDepthSensor(30, 0.99999F),
00149   itsHeadingSensor(3, 0.99999F),
00150   itsPitchSensor(3, 0.99999F),
00151   itsDepthPID(0.001F, 0.0F, 0.1F, 3.0F, 3.0F),
00152   itsHeadingPID(0.002F, 0.0F, 0.03F, Angle(170.0), Angle(170.0)),
00153   itsPitchPID(0.001F, 0.0F, 0.1F, Angle(170.0), Angle(170.0)),
00154   itsRotVelPID(0.3, 0.0001, 0, -500, 500),
00155   itsDepthPIDon(false),
00156   itsHeadingPIDon(false),
00157   itsPitchPIDon(false),
00158   itsRotVelPIDon(false),
00159   itsKillSwitchUsed(false),
00160   itsDiveSetting(0.0F),
00161   itsPitchSetting(0.0F),
00162   itsLastHeadingTime(0.0),
00163   itsLastPitchTime(0.0),
00164   itsLastDepthTime(0.0),
00165 #ifdef HAVE_LINUX_PARPORT_H
00166   lp0(new ParPort(mgr)),
00167   markerdropper(lp0),
00168 #endif
00169   killSwitchDebounceCounter(0)
00170 
00171 {
00172   // register our babies as subcomponents:
00173   addSubComponent(itsHMR3300);
00174   addSubComponent(itsIMU);
00175   addSubComponent(itsBeo);
00176   addSubComponent(itsCameraDown);
00177   addSubComponent(itsCameraFront);
00178   addSubComponent(itsCameraUp);
00179   addSubComponent(itsFballast);
00180   addSubComponent(itsRballast);
00181 #ifdef HAVE_LINUX_PARPORT_H
00182   addSubComponent(lp0);
00183 #endif
00184 
00185   // reset the BeoChip:
00186   LINFO("Resetting the BeoChip...");
00187   itsBeo->reset(MC_RECURSE);
00188   usleep(200000);
00189 
00190   // connect our listener to our beochip:
00191   rutz::shared_ptr<BeoChipListener> b(new BeoSubListener(this));
00192   itsBeo->setListener(b);
00193 
00194   // connect our listener to our compass:
00195   rutz::shared_ptr<HMR3300Listener> bl(new HMRlistener(this));
00196   itsHMR3300->setListener(bl);
00197 
00198   rutz::shared_ptr<BeoSubIMUListener> imu(new IMUListener(this));
00199   itsIMU->setListener(imu);
00200 
00201   // hook up BeoChips to Ballasts:
00202   itsFballast->setBeoChip(itsBeo);
00203   itsRballast->setBeoChip(itsBeo);
00204 
00205   // disable RTS/CTS flow control on our BeoChips:
00206   itsBeo->setModelParamVal("BeoChipUseRTSCTS", false);
00207 
00208   // select default serial ports for everybody:
00209   itsHMR3300->setModelParamString("HMR3300SerialPortDevName",
00210                                   "/dev/ttyS0", MC_RECURSE);
00211   itsBeo->setModelParamString("BeoChipDeviceName", "/dev/ttyS2");
00212   itsIMU->setModelParamString("IMUSerialPortDevName", "/dev/ttyS3",
00213                               MC_RECURSE);
00214 
00215   // set the I/O for our ballasts:
00216   itsRballast->setModelParamVal("RearBallastOutRed", 1);
00217   itsRballast->setModelParamVal("RearBallastOutWhite", 0);
00218   itsRballast->setModelParamVal("RearBallastInYellow", 1);
00219   itsRballast->setModelParamVal("RearBallastInWhite", 0);
00220 
00221   itsFballast->setModelParamVal("FrontBallastOutRed", 3);
00222   itsFballast->setModelParamVal("FrontBallastOutWhite", 2);
00223   itsFballast->setModelParamVal("FrontBallastInYellow", 3);
00224   itsFballast->setModelParamVal("FrontBallastInWhite", 2);
00225   //mgr.loadConfig("camconfig.pmap");
00226 }
00227 
00228 // ######################################################################
00229 BeoSubOneBal::~BeoSubOneBal()
00230 {  }
00231 
00232 // ######################################################################
00233 void BeoSubOneBal::start1()
00234 {
00235   // select firewire subchannels for our cameras:
00236   itsCameraDown->setModelParamVal("FrameGrabberSubChan", int(BEOSUBCAMDOWN));
00237   itsCameraFront->setModelParamVal("FrameGrabberSubChan", int(BEOSUBCAMFRONT));
00238   itsCameraUp->setModelParamVal("FrameGrabberSubChan", int(BEOSUBCAMUP));
00239 
00240   //NOTE that the stuff below is certainly necessary, but DOES NOT WORK in current form. FIX!
00241   /*
00242   itsCameraFront->setModelParamVal("FrameGrabberExposure", 511);
00243   itsCameraFront->setModelParamVal("FramGrabberGain", 87);
00244   itsCameraFront->setModelParamVal("FrameGrabberNbuf", 10);
00245   itsCameraFront->setModelParamVal("FrameGrabberSaturation", 90);
00246   itsCameraFront->setModelParamVal("FrameGrabberWhiteBalSU", 95);
00247   itsCameraFront->setModelParamVal("FrameGrabberWhiteBalRV", 87);
00248 
00249   itsCameraDown->setModelParamVal("FrameGrabberExposure", 511);
00250   itsCameraDown->setModelParamVal("FramGrabberGain", 87);
00251   itsCameraDown->setModelParamVal("FrameGrabberNbuf", 10);
00252   itsCameraDown->setModelParamVal("FrameGrabberSaturation", 90);
00253   itsCameraDown->setModelParamVal("FrameGrabberWhiteBalSU", 95);
00254   itsCameraDown->setModelParamVal("FrameGrabberWhiteBalRV", 87);
00255 
00256   itsCameraUp->setModelParamVal("FrameGrabberExposure", 511);
00257   itsCameraUp->setModelParamVal("FramGrabberGain", 87);
00258   itsCameraUp->setModelParamVal("FrameGrabberNbuf", 10);
00259   itsCameraUp->setModelParamVal("FrameGrabberSaturation", 90);
00260   itsCameraUp->setModelParamVal("FrameGrabberWhiteBalSU", 95);
00261   itsCameraUp->setModelParamVal("FrameGrabberWhiteBalRV", 87);
00262   */
00263   // don't forget to call start1() on our base class!
00264   BeoSub::start1();
00265 }
00266 
00267 // ######################################################################
00268 void BeoSubOneBal::start2()
00269 {
00270   // turn on the analog port capture for the pressure sensor, do not
00271   // capture pulses:
00272   itsBeo->captureAnalog(0, true);
00273   itsBeo->captureAnalog(1, false);
00274   itsBeo->capturePulse(0, false);
00275   itsBeo->capturePulse(1, false);
00276 
00277   // set all servos to neutral:
00278   for (int i = 0; i < 8; i ++) itsBeo->setServo(i, 0.0F);
00279 
00280   // turn on KBD capture for our ballasts:
00281   itsBeo->captureKeyboard(true);
00282   itsBeo->debounceKeyboard(false);
00283 
00284   // initialize all ballasts at once:
00285   CLINFO("filling ballasts...");
00286   setBallasts(1.0F, 1.0F, false); sleep(4);
00287   CLINFO("emptying ballasts...");
00288   setBallasts(0.0F, 0.0F, true);
00289 
00290   // turn the PIDs on: NOTE: first we should dive some...
00291   //itsHeadingPIDon = true;
00292   //setBallasts(0.5F, 0.5F, true);
00293   //itsPitchPIDon = true;
00294   itsDiveSetting = 0.5F;
00295 
00296   // display sign of life:
00297   itsBeo->lcdClear();
00298   itsBeo->lcdPrintf(3, 0, " iLab and USC rock! ");
00299 
00300   // we currently don't have a start2() in our base class, but if we
00301   // add one we should call it here.
00302 }
00303 
00304 void BeoSubOneBal::stop1() {
00305         //Turn off all PID's
00306         useDepthPID(false);
00307         useHeadingPID(false);
00308         usePitchPID(false);
00309         useRotVelPID(false);
00310         setRotVel(0.0);
00311         setTransVel(0.0);
00312 
00313         //empty both balasts and  surface!
00314         setBallasts(0.0F, 0.0F, true);
00315 
00316 }
00317 
00318 // ######################################################################
00319 void BeoSubOneBal::advanceRel(const float relDist, const bool stop)
00320 {
00321   float d = relDist * 2.0F;
00322   // turn our heading PID off as it may interfere with our commands of
00323   // the thrusters:
00324   bool hpid = itsHeadingPIDon;
00325   useHeadingPID(false);
00326 
00327   // just pulse the thrusters:
00328   if (fabsf(d) < 1.0F)
00329     {
00330         setTransVel(d);
00331       sleep(1);
00332       if (stop)
00333         {
00334         setTransVel(-d);
00335           usleep(350000);
00336         }
00337     }
00338   else
00339     {
00340       float forward = 1.0F, reverse = -1.0F;
00341       if (d < 0.0F) { forward = -forward; reverse = -reverse; }
00342 
00343       // thrust at full forward:
00344       setTransVel(forward);
00345 
00346       // for a time that is proportional to distance. Note: we will
00347       // reach steady-state speed after about 1sec:
00348       usleep(int(fabsf(d) * 1000000));
00349 
00350       if (stop)
00351         {
00352           // now, to stop, thrust full reverse:
00353           setTransVel(reverse);
00354 
00355           // for one second:
00356           sleep(1);
00357         }
00358     }
00359 
00360   // stop
00361   setTransVel(0);
00362 
00363   itsGlobalPosition.x += relDist * cos(itsGlobalHeading.getRadians());
00364   itsGlobalPosition.y += relDist * sin(itsGlobalHeading.getRadians());
00365 
00366   useHeadingPID(hpid);
00367 }
00368 
00369 // ######################################################################
00370 void BeoSubOneBal::turnOpen(const Angle openHeading, const bool stop){
00371   bool hpid = itsHeadingPIDon;
00372   useHeadingPID(false);
00373 
00374   /* for now, we'll always turn at 15 degrees/sec */
00375   float value = openHeading.getVal();
00376   float turnrate;
00377   if(value > 0) {
00378     turnrate = 15;
00379   } else {
00380     turnrate = -15;
00381   }
00382 
00383   setRotVel(turnrate);
00384   usleep((long)((value/turnrate)*1e6));
00385   setRotVel(0.0);
00386   itsGlobalHeading += openHeading;
00387   useHeadingPID(hpid);
00388 }
00389 
00390 // ######################################################################
00391 void BeoSubOneBal::strafeRel(const float relDist)
00392 {/*
00393   bool hpid = itsHeadingPIDon;
00394   useHeadingPID(false);
00395   BeoSub::strafeRel(relDist);
00396   useHeadingPID(hpid);*/
00397   turnRel(90);
00398   advanceRel(relDist);
00399   turnRel(-90);
00400 }
00401 
00402 void BeoSubOneBal::updateThrusters() {
00403         float left = TransVelCommand + RotVelCommand;
00404         float right = TransVelCommand - RotVelCommand;
00405 
00406         if (left > 1) left = 1;
00407         else if (left < -1) left = -1;
00408 
00409         if (right > 1) right = 1;
00410         else if (right < -1) right = -1;
00411 
00412         thrust(left, right);
00413 }
00414 
00415 void BeoSubOneBal::updateRotVelPID(const Angle current) {
00416         if(itsRotVelPIDon) {
00417                 //LINFO("%5.2f %5.2f", (PIDRotVel-current).getVal(), RotVelCommand);
00418                 RotVelCommand = itsRotVelPID.update(PIDRotVel, current).getVal();
00419                 updateThrusters();
00420         }
00421 }
00422 
00423 void BeoSubOneBal::setRotVel(const Angle desired) {
00424         if(itsRotVelPIDon) {
00425                 PIDRotVel = desired;
00426         } else {
00427                 RotVelCommand = desired.getVal();
00428                 updateThrusters();
00429         }
00430 }
00431 
00432 void BeoSubOneBal::setTransVel(const float desired) {
00433         //desiredTransVel = desired;
00434         TransVelCommand = desired; /* open loop for now */
00435         updateThrusters();
00436 }
00437 
00438 void BeoSubOneBal::updateIMU(const float xa, const float ya, const float za,
00439                              const Angle xv, const Angle yv, const Angle zv)
00440 {
00441         //LINFO("%5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f", xa, ya, za, xv.getVal(), yv.getVal(), zv.getVal(), itsCurrentAttitude.heading.getVal(), itsCurrentAttitude.pitch.getVal(), itsCurrentAttitude.roll.getVal());
00442         updateRotVelPID(zv); /* ignore roll/pitch interaction for now */
00443 }
00444 
00445 // ######################################################################
00446 void BeoSubOneBal::updateCompass(const Angle heading, const Angle pitch,
00447                                  const Angle roll)
00448 {
00449   // note the time at which the data was received:
00450   double t = itsMasterClock.getSecs();
00451 
00452   pthread_mutex_lock(&itsLock);
00453 
00454   // update our heading and pitch sensors:
00455   itsHeadingSensor.newMeasurement(heading);
00456   itsPitchSensor.newMeasurement(pitch);
00457 
00458   // inject these values into our current attitude:
00459   itsCurrentAttitude.heading = itsHeadingSensor.getValue();
00460   itsCurrentAttitude.pitch = itsPitchSensor.getValue();
00461   itsCurrentAttitude.roll = roll;
00462   itsCurrentAttitude.compassTime = t;
00463 
00464 
00465   // also update our heading PID and thrust accordingly:
00466   // only update every once in a while (in seconds):
00467   if (itsHeadingPIDon && t >= itsLastHeadingTime + 0.5)
00468     {
00469       // feed the PID controller:
00470       const float hcmd =
00471         itsHeadingPID.update(itsTargetAttitude.heading,
00472                          itsHeadingSensor.getValue()).getVal();
00473       setRotVel(hcmd);
00474 
00475       // remember when we did all this:
00476       itsLastHeadingTime = t;
00477 
00478       LINFO("hcmd = %f at t = %f", hcmd, t);
00479     }
00480 
00481   // also update our pitch PID and adjust ballasts accordingly:
00482   if (itsPitchPIDon && t >= itsLastPitchTime + 0.5)
00483     {
00484       // feed the PID controller:
00485       const float pcmd =
00486         itsPitchPID.update(itsTargetAttitude.pitch,
00487                            itsPitchSensor.getValue()).getVal();
00488 
00489       // update and limit our pitch setting: This setting should be
00490       // subtracted from the front ballast and added to the rear
00491       // ballast, relative to level:
00492       itsPitchSetting += pcmd;
00493       if (itsPitchSetting > 0.25F) itsPitchSetting = 0.25F;
00494       if (itsPitchSetting < -0.25F) itsPitchSetting = -0.25F;
00495 
00496       // adjust the ballasts: itsDiveSetting provides the mean, while
00497       // itsPitchSetting provides the deviation:
00498       float f = itsDiveSetting - itsPitchSetting;
00499       float r = itsDiveSetting + itsPitchSetting;
00500       if (f < 0.0F) f = 0.0F; else if (f > 1.0F) f = 1.0F;
00501       if (r < 0.0F) r = 0.0F; else if (r > 1.0F) r = 1.0F;
00502       setBallasts(f, r);
00503 
00504       // remember when we did all this:
00505       itsLastPitchTime = t;
00506 
00507       LINFO("pcmd = %f at t = %f", pcmd, t);
00508     }
00509 
00510   pthread_mutex_unlock(&itsLock);
00511 }
00512 
00513 // ######################################################################
00514 void BeoSubOneBal::updateDepth(const float depth)
00515 {
00516   // note the time at which the data was received:
00517   double t = itsMasterClock.getSecs();
00518 
00519   pthread_mutex_lock(&itsLock);
00520 
00521   // update our depth sensor:
00522   itsDepthSensor.newMeasurement(depth);
00523 
00524   // inject these values into our current attitude:
00525   itsCurrentAttitude.depth = itsDepthSensor.getValue();
00526   itsCurrentAttitude.pressureTime = t;
00527   const float tdepth = itsTargetAttitude.depth;
00528 
00529   // also update our depth PID and adjust ballasts:
00530   if (itsDepthPIDon && t >= itsLastDepthTime + 0.5)
00531     {
00532       // feed the PID controller:
00533       const float dcmd = itsDepthPID.update(tdepth, itsDepthSensor.getValue());
00534 
00535       // update and limit our dive setting:
00536       itsDiveSetting += dcmd;
00537       if (itsDiveSetting < 0.0F) itsDiveSetting = 0.0F;
00538       else if (itsDiveSetting > 1.0F) itsDiveSetting = 1.0F;
00539 
00540       // adjust the ballasts: itsDiveSetting provides the mean, while
00541       // itsPitchSetting provides the deviation:
00542       float f = itsDiveSetting - itsPitchSetting;
00543       float r = itsDiveSetting + itsPitchSetting;
00544       if (f < 0.0F) f = 0.0F; else if (f > 1.0F) f = 1.0F;
00545       if (r < 0.0F) r = 0.0F; else if (r > 1.0F) r = 1.0F;
00546       setBallasts(f, r);
00547 
00548       // remember when we did all this:
00549       itsLastDepthTime = t;
00550 
00551       LINFO("dcmd = %f at t=%f", dcmd, t);
00552     }
00553 
00554   pthread_mutex_unlock(&itsLock);
00555 }
00556 
00557 // ######################################################################
00558 void BeoSubOneBal::thrust(const float leftval, const float rightval)
00559 {
00560         // note: if the value is out of range, the BeoChip will clamp it.
00561         // That's why we read it back from the BeoChip before displaying it:
00562         itsBeo->setServo(itsLeftThrusterServoNum.getVal(), leftval);
00563         itsThrustLeft = itsBeo->getServo(itsLeftThrusterServoNum.getVal());
00564 
00565         itsBeo->setServo(itsRightThrusterServoNum.getVal(), rightval);
00566         itsThrustRight = itsBeo->getServo(itsRightThrusterServoNum.getVal());
00567 
00568         //LINFO("Th=%-1.2f/%-1.2f", itsThrustLeft, itsThrustRight);
00569 }
00570 
00571 // ######################################################################
00572 void BeoSubOneBal::getThrusters(float& leftval, float& rightval) const
00573 { leftval = itsThrustLeft; rightval = itsThrustRight; }
00574 
00575 // ######################################################################
00576 void BeoSubOneBal::setFrontBallast(const float val, const bool blocking)
00577 { itsFballast->set(val, blocking); }
00578 
00579 // ######################################################################
00580 void BeoSubOneBal::setRearBallast(const float val, const bool blocking)
00581 { itsRballast->set(val, blocking); }
00582 
00583 // ######################################################################
00584 void BeoSubOneBal::setBallasts(const float f, const float r,
00585                                const bool blocking)
00586 {
00587   // move all ballasts simultaneously rather than sequentially:
00588   itsFballast->set(f, false);
00589   itsRballast->set(r, false);
00590 
00591   if (blocking)
00592     {
00593       const double timeout = itsMasterClock.getSecs() + 20.0;
00594       while(itsMasterClock.getSecs() < timeout)
00595         {
00596           if (itsFballast->moving() == false &&
00597               itsRballast->moving() == false) break;
00598           usleep(100000);
00599         }
00600       if (itsMasterClock.getSecs() >= timeout)
00601         LERROR("Timeout on blocking setBallasts -- IGNORED");
00602     }
00603 }
00604 
00605 // ######################################################################
00606 float BeoSubOneBal::getFrontBallast() const
00607 { return itsFballast->get(); }
00608 
00609 // ######################################################################
00610 float BeoSubOneBal::getRearBallast() const
00611 { return itsRballast->get(); }
00612 
00613 // ######################################################################
00614 void BeoSubOneBal::getBallasts(float& f, float& r) const
00615 { f = itsFballast->get(); r = itsRballast->get(); }
00616 
00617 // ######################################################################
00618 void BeoSubOneBal::dropMarker(const bool blocking)
00619 {
00620 #ifndef HAVE_LINUX_PARPORT_H
00621   LFATAL("<linux/parport.h> must be installed to use this function");
00622 #else
00623   markerdropper.Step(150, 65000);
00624 #endif
00625 }
00626 
00627 // ######################################################################
00628 void BeoSubOneBal::killSwitch()
00629 {
00630   //Turn off all PID's
00631   useDepthPID(false);
00632   useHeadingPID(false);
00633   usePitchPID(false);
00634   useRotVelPID(false);
00635   setRotVel(0.0);
00636   setTransVel(0.0);
00637 
00638   //empty both balasts and  surface!
00639   setBallasts(0.0F, 0.0F, true);
00640 
00641   LFATAL("Kill switch pulled!");
00642 }
00643 
00644 // ######################################################################
00645 void BeoSubOneBal::dispatchBeoChipEvent(const BeoChipEventType t,
00646                                   const int valint,
00647                                   const float valfloat)
00648 {
00649   // what is this event about and whom is it for?
00650   switch(t)
00651     {
00652     case NONE: // ##############################
00653       LERROR("Unexpected BeoChip NONE event!");
00654       break;
00655 
00656     case PWM0: // ##############################
00657       LERROR("Unexpected BeoChip PWM0 event!");
00658       break;
00659 
00660     case PWM1: // ##############################
00661       LERROR("Unexpected BeoChip PWM1 event!");
00662       break;
00663 
00664     case KBD: // ##############################
00665       LDEBUG("Keyboard: new value %d", valint);
00666       // current diagram is:
00667       // #0 = front full/empty switch
00668       // #1 = front gear encoder
00669       // #2 = rear full/empty switch
00670       // #3 = rear gear encoder
00671       // #4 = kill switch
00672 
00673       // let both ballast units know:
00674       itsFballast->input(valint);
00675       itsRballast->input(valint);
00676 
00677       //check if kill switch is activated
00678       //disabled due to kill-switch/start-switch multi-use - khooyp
00679       //if (valint & 0x10 != 0 && itsKillSwitchUsed) killSwitch();
00680       break;
00681 
00682     case ADC0: // ##############################
00683       {
00684         //LINFO("ADC0 new value = %d", valint);
00685         // the ADC0 is connected to the pressure sensor. Convert to
00686         // meters, with positive going down (so the deeper we are, the
00687         // larger the positive reading). Then update the depth reading:
00688 
00689         // A reading of 255 corresponds to 2.5V, given our 2.5V
00690         // reference voltage on the BeoChip's ADC lines:
00691         float depth = (float(valint) * 2.5F) / 255.0F;  // in volts
00692 
00693         // I here assume that the sensor is an ASDX100A24R: NOTE: a
00694         // 220nF cap is required on the supply line.
00695 
00696         // the sensor has a 0.5V offset (i.e., outputs 0.5V when
00697         // pressure is 0):
00698         depth -= 0.5F;
00699 
00700         // An ASDX100A24R has a resolution of 0.040V/psi:
00701         depth /= 0.040F; // now in psi
00702 
00703         // convert from PSI to meters: at the surface, we have 14.7
00704         // psi (= 1 atmosphere); then it's about 0.44 psi/foot, i.e.,
00705         // 1.443 psi/m:
00706         depth = (depth - 14.275F) / 1.443F;
00707 
00708         // NOTE: convention in the rest of the code is positive depth
00709         // the more we go down:
00710         updateDepth(depth);
00711       }
00712       break;
00713 
00714     case ADC1: // ##############################
00715       LERROR("Unexpected BeoChip ADC1 event!");
00716       break;
00717 
00718     case RESET: // ##############################
00719       LERROR("BeoChip RESET!");
00720       break;
00721 
00722     case ECHOREP: // ##############################
00723       LINFO("BeoChip Echo reply.");
00724       break;
00725 
00726     case INOVERFLOW: // ##############################
00727       LERROR("BeoChip input overflow!");
00728       break;
00729 
00730     case SERIALERROR: // ##############################
00731       LERROR("BeoChip serial error!");
00732       break;
00733 
00734     case OUTOVERFLOW: // ##############################
00735       LERROR("BeoChip output overflow!");
00736       break;
00737 
00738     default: // ##############################
00739       LERROR("BeoChip unknown event %d!", int(t));
00740       break;
00741     }
00742 
00743     /* in addition, we also poll the kill switch on the parallel port */
00744     if(isKilled()) {
00745       killSwitchDebounceCounter++;
00746       if(killSwitchDebounceCounter > 50) {
00747         killSwitch();
00748       }
00749       //LINFO("killSwitchDebounce at %i\n", killSwitchDebounceCounter);
00750     } else {
00751       if(killSwitchDebounceCounter > 0) {
00752         LINFO("killSwitchDebounce reset\n");
00753       }
00754       killSwitchDebounceCounter = 0;
00755     }
00756 }
00757 
00758 // ######################################################################
00759 Image< PixRGB<byte> >
00760 BeoSubOneBal::grabImage(const enum BeoSubCamera cam) const
00761 {
00762   if (cam == BEOSUBCAMFRONT) return itsCameraFront->readRGB();
00763   if (cam == BEOSUBCAMDOWN) return itsCameraDown->readRGB();
00764   if (cam == BEOSUBCAMUP) return itsCameraUp->readRGB();
00765   LERROR("Wrong camera %d -- RETURNING EMPTY IMAGE", int(cam));
00766   return Image< PixRGB<byte> >();
00767 }
00768 
00769 // ######################################################################
00770 void BeoSubOneBal::useDepthPID(const bool useit)
00771 { itsDepthPIDon = useit; }
00772 
00773 // ######################################################################
00774 void BeoSubOneBal::useHeadingPID(const bool useit)
00775 { itsHeadingPIDon = useit; }
00776 
00777 // ######################################################################
00778 void BeoSubOneBal::usePitchPID(const bool useit)
00779 { itsPitchPIDon = useit; }
00780 
00781 void BeoSubOneBal::useRotVelPID(const bool useit)
00782 { itsRotVelPIDon = useit; }
00783 
00784 // ######################################################################
00785 void BeoSubOneBal::useKillSwitch(const bool useit)
00786 { itsKillSwitchUsed = useit; }
00787 
00788 // ######################################################################
00789 bool BeoSubOneBal::isKilled()
00790 {
00791 #ifndef HAVE_LINUX_PARPORT_H
00792   LFATAL("<linux/parport.h> must be installed to use this function");
00793   return true; // can't happen, but placate compiler
00794 #else
00795         unsigned char status;
00796         status = lp0->ReadStatus();
00797         return (status & PARPORT_STATUS_BUSY) || !(status & PARPORT_STATUS_ACK);
00798 #endif
00799 }
00800 
00801 // ######################################################################
00802 void BeoSubOneBal::setDepthPgain(float p)
00803 { itsDepthPID.setPIDPgain(p); }
00804 
00805 // ######################################################################
00806 void BeoSubOneBal::setDepthIgain(float i)
00807 { itsDepthPID.setPIDIgain(i); }
00808 
00809 // ######################################################################
00810 void BeoSubOneBal::setDepthDgain(float d)
00811 { itsDepthPID.setPIDDgain(d); }
00812 
00813 // ######################################################################
00814 void BeoSubOneBal::setHeadingPgain(float p)
00815 { itsHeadingPID.setPIDPgain(p); }
00816 
00817 // ######################################################################
00818 void BeoSubOneBal::setHeadingIgain(float i)
00819 { itsHeadingPID.setPIDIgain(i); }
00820 
00821 // ######################################################################
00822 void BeoSubOneBal::setHeadingDgain(float d)
00823 { itsHeadingPID.setPIDDgain(d); }
00824 
00825 // ######################################################################
00826 void BeoSubOneBal::setPitchPgain(float p)
00827 { itsPitchPID.setPIDPgain(p); }
00828 
00829 // ######################################################################
00830 void BeoSubOneBal::setPitchIgain(float i)
00831 { itsPitchPID.setPIDIgain(i); }
00832 
00833 // ######################################################################
00834 void BeoSubOneBal::setPitchDgain(float d)
00835 { itsPitchPID.setPIDDgain(d); }
00836 
00837 // ######################################################################
00838 void BeoSubOneBal::setRotVelPgain(float p)
00839 { itsRotVelPID.setPIDPgain(p); }
00840 
00841 // ######################################################################
00842 void BeoSubOneBal::setRotVelIgain(float i)
00843 { itsRotVelPID.setPIDIgain(i); }
00844 
00845 // ######################################################################
00846 void BeoSubOneBal::setRotVelDgain(float d)
00847 { itsRotVelPID.setPIDDgain(d); }
00848 // ######################################################################
00849 /* So things look consistent in everyone's emacs... */
00850 /* Local Variables: */
00851 /* indent-tabs-mode: nil */
00852 /* End: */
Generated on Sun May 8 08:40:19 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3