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