00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
00208 if (ArMath::fabs(myRobot->getVel()) <= mySlowSpeed)
00209 {
00210 sideClearance = mySideClearanceAtSlowSpeed;
00211 padding = myPaddingAtSlowSpeed;
00212 }
00213
00214 else if (ArMath::fabs(myRobot->getVel()) >= myFastSpeed)
00215 {
00216 sideClearance = mySideClearanceAtFastSpeed;
00217 padding = myPaddingAtFastSpeed;
00218 }
00219
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
00273 dist -= myRobot->getRobotLength() / 2.0;
00274 dist -= myClearance;
00275 dist -= padding;
00276
00277
00278 distInner -= myRobot->getRobotLength() / 2.0;
00279 distInner -= myClearance;
00280
00281 if (printing)
00282 printf("%d dist %.0f\n", myForwards, dist);
00283
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
00301 if (fabs(myMaxEmergencyDecel) > 1)
00302 {
00303 if (printing)
00304 printf("Max emergency decel %.0f\n",
00305 myMaxEmergencyDecel);
00306 myDesired.setTransDecel(myMaxEmergencyDecel);
00307 }
00308
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
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
00337
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
00349
00350 double deceleration = - absVel * absVel / dist / 2.0;
00351 double decelerationInner = - absVel * absVel / distInner / 2.0;
00352
00353
00354
00355
00356 if (fabs(deceleration) > fabs(myRobot->getTransDecel()) &&
00357 (currentDesired.getTransDecelStrength() < ArActionDesired::MIN_STRENGTH
00358 || fabs(deceleration) > fabs(currentDesired.getTransDecel())))
00359 {
00360
00361
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
00381
00382 if (printing)
00383 printf("%d accel %.0f\n", myForwards, deceleration);
00384
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