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

ArActionDeceleratingLimiter.cpp

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

Generated on Wed Oct 19 12:56:34 2005 for Aria by  doxygen 1.4.0