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

ArActionStallRecover.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 <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       //printf("Didn't reset... %ld time diff\n", time(NULL) - myLastFired);
00131       ++mySequencePos;
00132     }
00133     else 
00134     {
00135       //printf("Reset\n");
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     // if we're moving but not turning then don't turn
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       //printf("Not backing ");
00222       myActionDesired.setVel(0);
00223       transFired = false;
00224     } 
00225     else
00226     {
00227       //printf("backing ");
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     // if we're turning but not moving then don't move
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       //printf("Not turning \n");
00250       myActionDesired.setRotVel(0);
00251       rotFired = false;
00252     }
00253     else 
00254     {
00255       //printf("turning \n");
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 

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