Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages | Examples

ArActionDeceleratingLimiter.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 #include "ArExport.h"
00027 #include "ariaOSDef.h"
00028 #include "ArActionDeceleratingLimiter.h"
00029 #include "ArRobot.h"
00030 #include "ArCommands.h"
00031 #include "ariaInternal.h"
00032 #include "ArRobotConfigPacketReader.h"
00033 #include "ArRangeDevice.h"
00034 
00039 AREXPORT ArActionDeceleratingLimiter::ArActionDeceleratingLimiter(
00040     const char *name, 
00041     bool forwards) :
00042   ArAction(name,
00043        "Slows the robot down and cranks up deceleration so as not to hit anything in front of it.")
00044 {
00045   myForwards = forwards;
00046   setParameters();
00047 
00048   myLastStopped = false;
00049   myUseLocationDependentDevices = true;
00050 }
00051 
00052 AREXPORT ArActionDeceleratingLimiter::~ArActionDeceleratingLimiter()
00053 {
00054 
00055 }
00056 
00069 AREXPORT void ArActionDeceleratingLimiter::setParameters(
00070     double clearance,
00071     double sideClearanceAtSlowSpeed,
00072     double paddingAtSlowSpeed,
00073     double slowSpeed,
00074     double sideClearanceAtFastSpeed,
00075     double paddingAtFastSpeed,
00076     double fastSpeed,
00077     double preferredDecel,
00078     bool useEStop,
00079     double maxEmergencyDecel)
00080 {
00081   myClearance = clearance;
00082   mySideClearanceAtSlowSpeed = sideClearanceAtSlowSpeed;
00083   myPaddingAtSlowSpeed = paddingAtSlowSpeed;
00084   mySlowSpeed = slowSpeed;
00085   mySideClearanceAtFastSpeed = sideClearanceAtFastSpeed;
00086   myPaddingAtFastSpeed = paddingAtFastSpeed;
00087   myFastSpeed = fastSpeed;
00088   myPreferredDecel = preferredDecel;
00089   myUseEStop = useEStop;
00090   myMaxEmergencyDecel = maxEmergencyDecel;
00091 }
00092 
00093 AREXPORT void ArActionDeceleratingLimiter::addToConfig(ArConfig *config, 
00094                                const char *section, 
00095                                const char *prefix)
00096 {
00097   std::string strPrefix;
00098   std::string name;
00099   if (prefix == NULL || prefix[0] == '\0')
00100     strPrefix = "";
00101   else
00102     strPrefix = prefix;
00103 
00104   config->addParam(ArConfigArg(ArConfigArg::SEPARATOR), section, ArPriority::NORMAL);  
00105 
00106   name = strPrefix;
00107   name += "Clearance";
00108   config->addParam(
00109       ArConfigArg(name.c_str(), &myClearance, 
00110               "Don't get closer than this to something in front or back. (mm)"), 
00111       section, ArPriority::NORMAL);
00112 
00113   name = strPrefix;
00114   name += "SlowSpeed";
00115   config->addParam(
00116       ArConfigArg(name.c_str(),
00117               &mySlowSpeed,
00118               "Consider this speed slow (mm/sec)"),
00119       section, ArPriority::NORMAL);
00120 
00121   name = strPrefix;
00122   name += "SideClearanceAtSlowSpeed";
00123   config->addParam(
00124       ArConfigArg(name.c_str(),
00125               &mySideClearanceAtSlowSpeed, 
00126               "Don't get closer than this to something on the side if we're going at slow speed or below. (mm)"),
00127       section, ArPriority::NORMAL);
00128 
00129   name = strPrefix;
00130   name += "PaddingAtSlowSpeed";
00131   config->addParam(
00132       ArConfigArg(name.c_str(), &myPaddingAtSlowSpeed, 
00133               "Try to stop this far away from clearance at slow speed or below. (mm)"), 
00134       section, ArPriority::NORMAL);
00135 
00136   name = strPrefix;
00137   name += "FastSpeed";
00138   config->addParam(
00139       ArConfigArg(name.c_str(),
00140               &myFastSpeed,
00141               "Consider this speed fast (mm/sec)"),
00142       section, ArPriority::NORMAL);
00143 
00144   name = strPrefix;
00145   name += "SideClearanceAtFastSpeed";
00146   config->addParam(
00147       ArConfigArg(name.c_str(),
00148               &mySideClearanceAtFastSpeed, 
00149               "Don't get closer than this to something on the side if we're going at fast speed or above. (mm)"),
00150       section, ArPriority::NORMAL);
00151 
00152   name = strPrefix;
00153   name += "PaddingAtFastSpeed";
00154   config->addParam(
00155       ArConfigArg(name.c_str(), &myPaddingAtFastSpeed, 
00156               "Try to stop this far away from clearance at fast speed or below. (mm)"), 
00157       section, ArPriority::NORMAL);
00158 
00159   name = strPrefix;
00160   name += "PreferredDecel";
00161   config->addParam(
00162       ArConfigArg(name.c_str(),
00163               &myPreferredDecel,
00164               "The maximum decel we'll use until something might infringe on clearance and sideClearanceAtSlowSpeed (mm/sec/sec"),
00165       section, ArPriority::NORMAL);
00166 
00167   name = strPrefix;
00168   name += "MaxEmergencyDecel";
00169   config->addParam(
00170       ArConfigArg(name.c_str(),
00171               &myMaxEmergencyDecel,
00172               "The maximum decel we'll ever use, 0 means use the robot's maximum (mm/sec/sec"),
00173       section, ArPriority::NORMAL);
00174 
00175   name = strPrefix;
00176   name += "UseEStop";
00177   config->addParam(
00178       ArConfigArg(name.c_str(),
00179               &myUseEStop,
00180               "Whether to use an EStop to stop if something will intrude on our clearance"),
00181       section, ArPriority::NORMAL);
00182 
00183   config->addParam(ArConfigArg(ArConfigArg::SEPARATOR), section, ArPriority::NORMAL);
00184 }
00185 
00186 AREXPORT ArActionDesired *
00187 ArActionDeceleratingLimiter::fire(ArActionDesired currentDesired)
00188 {
00189   double dist;
00190   const ArRangeDevice *distRangeDevice;
00191   double distInner;
00192   const ArRangeDevice *distInnerRangeDevice;
00193   bool printing = false;
00194   double absVel;
00195   
00196   myDesired.reset();
00197   // see if we're going the right direction for this to work
00198   if (myRobot->getVel() < -100 && myForwards)
00199     return NULL;
00200   else if (myRobot->getVel() > 100 && !myForwards)
00201     return NULL;
00202   absVel = ArMath::fabs(myRobot->getVel());
00203 
00204   double sideClearance;
00205   double padding;
00206   
00207   // see if we're going slow
00208   if (ArMath::fabs(myRobot->getVel()) <= mySlowSpeed)
00209   {
00210     sideClearance = mySideClearanceAtSlowSpeed;
00211     padding = myPaddingAtSlowSpeed;
00212   }
00213   // or if we're going fast
00214   else if (ArMath::fabs(myRobot->getVel()) >= myFastSpeed)
00215   {
00216     sideClearance = mySideClearanceAtFastSpeed;
00217     padding = myPaddingAtFastSpeed;
00218   }
00219   // or if we have to interpolate
00220   else
00221   {
00222     sideClearance = (((mySideClearanceAtFastSpeed - 
00223                mySideClearanceAtSlowSpeed) * 
00224               ((ArMath::fabs(myRobot->getVel()) - mySlowSpeed) / 
00225                (myFastSpeed - mySlowSpeed))) + 
00226              mySideClearanceAtSlowSpeed);
00227     padding = (((myPaddingAtFastSpeed - 
00228          myPaddingAtSlowSpeed) * 
00229         ((ArMath::fabs(myRobot->getVel()) - mySlowSpeed) / 
00230          (myFastSpeed - mySlowSpeed))) + 
00231            myPaddingAtSlowSpeed);
00232   }
00233 
00234 
00235   if (printing)
00236     printf("%d side %.0f padding %.0f\n", myForwards, sideClearance, padding);
00237               
00238   if (myForwards)
00239     dist = myRobot->checkRangeDevicesCurrentBox(
00240         0,
00241         -(myRobot->getRobotWidth()/2.0 + sideClearance),
00242         myRobot->getRobotLength()/2.0 + myClearance + padding + 8000,
00243         (myRobot->getRobotWidth()/2.0 + sideClearance),
00244         NULL,
00245         &distRangeDevice, myUseLocationDependentDevices);
00246   else
00247     dist = myRobot->checkRangeDevicesCurrentBox(
00248         0,
00249         -(myRobot->getRobotWidth()/2.0 + sideClearance),
00250         -(myRobot->getRobotLength()/2.0 + myClearance + padding + 8000),
00251         (myRobot->getRobotWidth()/2.0 + sideClearance),
00252         NULL,
00253         &distRangeDevice, myUseLocationDependentDevices);
00254 
00255   if (myForwards)
00256     distInner = myRobot->checkRangeDevicesCurrentBox(
00257         0,
00258         -(myRobot->getRobotWidth()/2.0 + mySideClearanceAtSlowSpeed),
00259         myRobot->getRobotLength()/2.0 + myClearance + 8000,
00260         (myRobot->getRobotWidth()/2.0 + mySideClearanceAtSlowSpeed),
00261         NULL,
00262         &distInnerRangeDevice, myUseLocationDependentDevices);
00263   else
00264     distInner = myRobot->checkRangeDevicesCurrentBox(
00265         0,
00266         -(myRobot->getRobotWidth()/2.0 + mySideClearanceAtSlowSpeed),
00267         -(myRobot->getRobotLength()/2.0 + myClearance + 8000),
00268         (myRobot->getRobotWidth()/2.0 + mySideClearanceAtSlowSpeed),
00269         NULL,
00270         &distInnerRangeDevice, myUseLocationDependentDevices);
00271     
00272   // subtract off our clearance and padding to see how far we have to stop
00273   dist -= myRobot->getRobotLength() / 2.0;
00274   dist -= myClearance;
00275   dist -= padding;
00276 
00277   // this is what we estop for, so don't subtract our padding from this
00278   distInner -= myRobot->getRobotLength() / 2.0;
00279   distInner -= myClearance;
00280 
00281   if (printing)
00282     printf("%d dist %.0f\n", myForwards, dist);
00283   // see if we need to throw an estop
00284   if (distInner < 1 && ((myRobot->getVel() > 5 && myForwards) ||
00285            (myRobot->getVel() < -5 && !myForwards)))
00286   {
00287     if (printing && !myLastStopped)
00288       printf("%d Stopping\n", myForwards);
00289     if (ArMath::fabs(myRobot->getVel()) > 100)
00290     {
00291       if (myUseEStop)
00292       {
00293     ArLog::log(ArLog::Normal, "ArActionDeceleratingLimiter: estopping because of reading from %s", distInnerRangeDevice->getName());
00294     myRobot->comInt(ArCommands::ESTOP, 1);
00295       }
00296       else
00297       {
00298     ArLog::log(ArLog::Normal, "ArActionDeceleratingLimiter: maximum deceleration because of reading from %s", distInnerRangeDevice->getName());
00299       }
00300       // if we have a maximum emergency decel, use that
00301       if (fabs(myMaxEmergencyDecel) > 1)
00302       {
00303     if (printing)
00304       printf("Max emergency decel %.0f\n", 
00305          myMaxEmergencyDecel);
00306     myDesired.setTransDecel(myMaxEmergencyDecel);
00307       }
00308       //  if we don't use the robot's top decel
00309       else if (myRobot->getOrigRobotConfig() != NULL && 
00310       myRobot->getOrigRobotConfig()->hasPacketArrived())
00311       {
00312     if (printing)
00313       printf("Robots max decel %d\n", 
00314          myRobot->getOrigRobotConfig()->getTransAccelTop());
00315     myDesired.setTransDecel(
00316         myRobot->getOrigRobotConfig()->getTransAccelTop());
00317       }
00318       // if we don't have that either use our preferred decel
00319       else
00320       {
00321     if (printing)
00322       printf("Prefered decel %g\n", myPreferredDecel);
00323     myDesired.setTransDecel(myPreferredDecel);
00324       }
00325     }
00326     myLastStopped = true;
00327     if (myForwards)
00328       myDesired.setMaxVel(0);
00329     else
00330       myDesired.setMaxNegVel(0);
00331     myDesired.setVel(0);
00332     ArLog::log(ArLog::Verbose, "Stopping (inner) because of reading from %s", 
00333            distInnerRangeDevice->getName());
00334     return &myDesired;
00335   }
00336   // if our distance is greater than how far it'd take us to stop
00337   //printf("%.0f %.0f %.0f\n", dist, absVel, absVel * absVel / 2.0 / myRobot->getTransDecel());
00338   if (dist > absVel * absVel / 2.0 / myRobot->getTransDecel())
00339   {
00340     if (printing)
00341       printf("%d Nothing\n", myForwards);
00342     return NULL;
00343   }
00344 
00345   if (printing && myLastStopped)
00346     printf("%d moving\n", myForwards);
00347   myLastStopped = false;
00348   //printf("%f ", dist);
00349   //maxVel = (dist - clearance);
00350   double deceleration = - absVel * absVel / dist / 2.0;
00351   double decelerationInner = - absVel * absVel / distInner / 2.0;
00352   // make sure the robot or other actions aren't already decelerating
00353   // more than we want to
00354 
00355   //printf("%.0f %.0f %.0f %.0f\n", deceleration, myRobot->getTransDecel(),      currentDesired.getTransDecelStrength(), currentDesired.getTransDecel());
00356   if (fabs(deceleration) > fabs(myRobot->getTransDecel()) &&
00357       (currentDesired.getTransDecelStrength() < ArActionDesired::MIN_STRENGTH 
00358        || fabs(deceleration) > fabs(currentDesired.getTransDecel())))
00359   {
00360     // if our deceleration is faster than we want to decel see if we
00361     // actually will have to decel that fast or not
00362     if (fabs(myMaxEmergencyDecel) > 1 && 
00363     fabs(decelerationInner) > myMaxEmergencyDecel)
00364       myDesired.setTransDecel(myMaxEmergencyDecel);
00365     else if (fabs(decelerationInner) > myPreferredDecel)
00366       myDesired.setTransDecel(fabs(decelerationInner));
00367     else if (fabs(myMaxEmergencyDecel) > 1 && 
00368          fabs(deceleration) > myMaxEmergencyDecel)
00369       myDesired.setTransDecel(myMaxEmergencyDecel);
00370     else if (fabs(deceleration) > myPreferredDecel)
00371       myDesired.setTransDecel(myPreferredDecel);
00372     else 
00373       myDesired.setTransDecel(fabs(deceleration));
00374     if (printing)
00375       printf("Set deceleration to %g\n", myDesired.getTransDecel());
00376   }
00377   else
00378     deceleration = myRobot->getTransDecel();
00379 
00380   //double maxVel = absVel - deceleration  / 10.0;
00381 
00382   if (printing)
00383     printf("%d accel %.0f\n", myForwards, deceleration);
00384   //printf("Max vel %f (stopdist %.1f slowdist %.1f slowspeed %.1f\n", maxVel,   myStopDist, mySlowDist, mySlowSpeed);
00385 
00386   ArLog::log(ArLog::Verbose, "Stopping because of reading from %s", 
00387          distInnerRangeDevice->getName());
00388 
00389   if (myForwards)
00390     myDesired.setMaxVel(0);
00391   else
00392     myDesired.setMaxNegVel(0);
00393   return &myDesired;
00394 }
00395 
00396 
00397 

Generated on Tue Feb 20 10:51:38 2007 for Aria by  doxygen 1.4.0