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 <time.h>
00029 #include "ArRobot.h"
00030 #include "ArResolver.h"
00031 #include "ArActionStallRecover.h"
00032
00041 AREXPORT
00042 ArActionStallRecover::ArActionStallRecover(const char * name,
00043 double obstacleDistance,
00044 int cyclesToMove,
00045 double speed,
00046 double degreesToTurn) :
00047 ArAction(name, "Recovers the robot from a stall.")
00048 {
00049 setNextArgument(ArArg("obstacle distance", &myObstacleDistance,
00050 "Distance at which not to move because of obstacle. (mm)"));
00051 myObstacleDistance = obstacleDistance;
00052 setNextArgument(ArArg("cycles to move", &myCyclesToMove,
00053 "Number of cycles to move (# of cycles)"));
00054 myCyclesToMove = cyclesToMove;
00055 setNextArgument(ArArg("speed", &mySpeed,
00056 "Speed at which to back up or go forward (mm/sec)"));
00057 mySpeed = speed;
00058 setNextArgument(ArArg("degrees to turn", &myDegreesToTurn,
00059 "Number of Degrees to turn (deg)"));
00060 myDegreesToTurn = degreesToTurn;
00061 myState = STATE_NOTHING;
00062
00063 myResolver = NULL;
00064 mySequenceNum = 0;
00065 addSequence(BACK | TURN);
00066 addSequence(FORWARD | TURN);
00067 addSequence(BACK);
00068 addSequence(FORWARD);
00069 addSequence(TURN_LEFT);
00070 addSequence(TURN_RIGHT);
00071 addSequence(BACK | TURN_LEFT);
00072 addSequence(BACK | TURN_RIGHT);
00073 addSequence(FORWARD | TURN_LEFT);
00074 addSequence(FORWARD | TURN_RIGHT);
00075 mySequencePos = 0;
00076 myLastFired = 0;
00077 }
00078
00079 AREXPORT
00080 ArActionStallRecover::~ArActionStallRecover()
00081 {
00082
00083
00084 }
00085
00086 void ArActionStallRecover::addSequence(int sequence)
00087 {
00088 mySequence[mySequenceNum] = sequence;
00089 ++mySequenceNum;
00090 }
00091
00092 AREXPORT
00093 ArActionDesired *ArActionStallRecover::fire(ArActionDesired currentDesired)
00094 {
00095 std::string doingString;
00096
00097 if (myRobot->isLeftMotorStalled())
00098 ArLog::log(ArLog::Verbose, "########## Left stall");
00099 if (myRobot->isRightMotorStalled())
00100 ArLog::log(ArLog::Verbose, "########## Right stall");
00101
00102 if ((currentDesired.getVelStrength() >= 1.0 ||
00103 currentDesired.getDeltaHeadingStrength() >= 1.0 ||
00104 currentDesired.getHeadingStrength() >= 1.0 ||
00105 currentDesired.getRotVelStrength() >= 1.0))
00106 {
00107 if (myState != STATE_NOTHING)
00108 {
00109 myState = STATE_NOTHING;
00110 myCount = -1;
00111 ArLog::log(ArLog::Normal, "StallRecover: done (interrupted)");
00112 }
00113 return NULL;
00114 }
00115
00116 myActionDesired.reset();
00117 switch (myState)
00118 {
00119 case STATE_NOTHING:
00120 if (!myRobot->isLeftMotorStalled() && !myRobot->isRightMotorStalled())
00121 return NULL;
00122 if (myRobot->isLeftMotorStalled() && myRobot->isRightMotorStalled())
00123 doingString = "StallRecover: Both motors stalled";
00124 else if (myRobot->isLeftMotorStalled())
00125 doingString = "StallRecover: Left motor stalled";
00126 else if (myRobot->isRightMotorStalled())
00127 doingString = "StallRecover: Right motor stalled";
00128 if (time(NULL) - myLastFired <= 5)
00129 {
00130
00131 ++mySequencePos;
00132 }
00133 else
00134 {
00135
00136 mySequencePos = 0;
00137 }
00138 if (mySequencePos >= mySequenceNum)
00139 mySequencePos = 0;
00140 myDoing = mySequence[mySequencePos];
00141 if (myDoing & FORWARD)
00142 doingString += " driving_forward";
00143 if (myDoing & BACK)
00144 doingString += " driving_backward";
00145 if (myDoing & TURN)
00146 doingString += " turning";
00147 if (myDoing & TURN_LEFT)
00148 doingString += " turning_left";
00149 if (myDoing & TURN_RIGHT)
00150 doingString += " turning_right";
00151 if (myDoing == 0)
00152 doingString += " messed";
00153 ArLog::log(ArLog::Normal, doingString.c_str());
00154 myActionDesired.setVel(0);
00155 myActionDesired.setDeltaHeading(0);
00156 case STATE_GOING:
00157 myLastFired = time(NULL);
00158 doit();
00159 break;
00160 default:
00161 ArLog::log(ArLog::Normal, "StallRecover: Bad state");
00162 break;
00163 }
00164 return &myActionDesired;
00165 }
00166
00167 void ArActionStallRecover::doit(void)
00168 {
00169 double leftDist, rightDist;
00170 double dist;
00171 int turnDirection;
00172 bool transFired, rotFired;
00173
00174 if (myCount == -1 || myState != STATE_GOING)
00175 {
00176 myCount = myCyclesToMove;
00177 myState = STATE_GOING;
00178 mySideStalled = 0;
00179 if (myRobot->isLeftMotorStalled())
00180 mySideStalled += 1;
00181 if (myRobot->isRightMotorStalled())
00182 mySideStalled += 2;
00183 if (myDoing & TURN)
00184 {
00185 rightDist = myRobot->checkRangeDevicesCurrentPolar(-120, -60);
00186 leftDist = myRobot->checkRangeDevicesCurrentPolar(60, 120);
00187 if (mySideStalled == 1 || rightDist < 0)
00188 turnDirection = -1;
00189 else if (mySideStalled == 2 || leftDist < 0)
00190 turnDirection = 1;
00191 else if (rightDist < leftDist)
00192 turnDirection = 1;
00193 else
00194 turnDirection = -1;
00195 myDesiredHeading = myRobot->getTh() + turnDirection * myDegreesToTurn;
00196 }
00197 else if (myDoing & TURN_LEFT)
00198 myDesiredHeading = myRobot->getTh() + myDegreesToTurn;
00199 else if (myDoing & TURN_RIGHT)
00200 myDesiredHeading = myRobot->getTh() + -1 * myDegreesToTurn;
00201 }
00202 else
00203 --myCount;
00204
00205 if (myDoing & MOVEMASK)
00206 {
00207
00208 if (!(myDoing & TURNMASK))
00209 myActionDesired.setRotVel(0);
00210
00211 if (myDoing & FORWARD)
00212 dist = (myRobot->checkRangeDevicesCurrentPolar(-120, 120) -
00213 myRobot->getRobotRadius());
00214 else if (myDoing & BACK)
00215 dist = (myRobot->checkRangeDevicesCurrentPolar(120, -120) -
00216 myRobot->getRobotRadius());
00217 if ((myCount <= 0 ||
00218 (dist > 0 && dist < myObstacleDistance &&
00219 myCount <= myCyclesToMove / 2)))
00220 {
00221
00222 myActionDesired.setVel(0);
00223 transFired = false;
00224 }
00225 else
00226 {
00227
00228 if (myDoing & BACK)
00229 myActionDesired.setVel(mySpeed * -1);
00230 if (myDoing & FORWARD)
00231 myActionDesired.setVel(mySpeed);
00232 transFired = true;
00233 }
00234 }
00235 else
00236 {
00237 transFired = false;
00238 }
00239
00240 if ((myDoing & TURNMASK))
00241 {
00242
00243 if (!(myDoing & MOVEMASK))
00244 myActionDesired.setVel(0);
00245
00246 if ((myCount <= 0 || myDegreesToTurn == 0 ||
00247 ArMath::fabs(ArMath::subAngle(myRobot->getTh(),myDesiredHeading)) < 3))
00248 {
00249
00250 myActionDesired.setRotVel(0);
00251 rotFired = false;
00252 }
00253 else
00254 {
00255
00256 myActionDesired.setHeading(myDesiredHeading);
00257 rotFired = true;
00258 }
00259 }
00260 else
00261 {
00262 rotFired = false;
00263 }
00264
00265
00266 if (myCount <= 0 || (!transFired && !rotFired))
00267 {
00268 myState = STATE_NOTHING;
00269 ArLog::log(ArLog::Normal, "StallRecover: done");
00270 myActionDesired.reset();
00271 return;
00272 }
00273 }
00274
00275 void ArActionStallRecover::addToConfig(ArConfig* config, const char* sectionName, int priority)
00276 {
00277 if (config == NULL || sectionName == NULL)
00278 {
00279 ArLog::log(ArLog::Terse, "Could not add ArActionStallRecoverToConfig because config (%p) or section (%p) are null", config, sectionName);
00280 return;
00281 }
00282 config->addParam(ArConfigArg(ArConfigArg::SEPARATOR), sectionName, ArPriority::DETAILED);
00283 config->addParam(ArConfigArg("StallRecoverSpeed", &mySpeed, "Speed at which to back away when stalled.", priority), sectionName, ArPriority::DETAILED);
00284 config->addParam(ArConfigArg("StallRecoverDuration", &myCyclesToMove, "Cycles of operation to move when recovering from stall.", priority), sectionName, ArPriority::DETAILED);
00285 config->addParam(ArConfigArg("StallRecoverRotation", &myDegreesToTurn, "Amount of rotation when recovering (degrees).", priority), sectionName, ArPriority::DETAILED);
00286 config->addParam(ArConfigArg(ArConfigArg::SEPARATOR), sectionName, ArPriority::DETAILED);
00287 }
00288