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

ArActionTriangleDriveTo.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 "ArActionTriangleDriveTo.h"
00029 #include "ArRobot.h"
00030 
00031 AREXPORT ArActionTriangleDriveTo::ArActionTriangleDriveTo(
00032     const char *name, double finalDistFromVertex,  
00033     double approachDistFromVertex, double speed,
00034     double closeDist, double acquireTurnSpeed) :
00035   ArAction(name, "Finds a triangle and drives in front of it")
00036 {
00037   setNextArgument(ArArg("final dist from vertex", &myFinalDistFromVertex, 
00038             "Distance from vertex we want to be at (mm)"));
00039   myFinalDistFromVertex = finalDistFromVertex;
00040 
00041   setNextArgument(ArArg("approach dist from vertex", &myApproachDistFromVertex,
00042             "Distance from vertex we'll go to before going to final (0 goes straight to final) (mm)"));
00043   myApproachDistFromVertex = approachDistFromVertex;
00044 
00045   setNextArgument(ArArg("speed", &mySpeed, "speed to drive at (mm/sec)"));
00046   mySpeed = speed;
00047 
00048   setNextArgument(ArArg("close dist", &myCloseDist, 
00049             "how close we have to get to our final point (mm)"));
00050   myCloseDist = closeDist;
00051 
00052   setNextArgument(ArArg("acquire turn speed", &myAcquireTurnSpeed,
00053         "if we are aqcquiring the rot vel to turn at (deg/sec)"));
00054   myAcquireTurnSpeed = acquireTurnSpeed;
00055 
00056   myLaser = NULL;
00057   myLineFinder = NULL;
00058   myOwnLineFinder = false;
00059   myState = STATE_INACTIVE;
00060   mySaveData = false;
00061   myData = NULL;
00062   myVertexSeen = false;
00063   // set all our defaults
00064   setTriangleParams();
00065   setVertexUnseenStopMSecs();
00066   setAcquire();
00067   setIgnoreTriangleDist();
00068   setMaxDistBetweenLinePoints();
00069   setMaxLateralDist();
00070   myPrinting = false;
00071   myAdjustVertex = false;
00072   myGotoVertex = false;
00073   myLocalXOffset = 0;
00074   myLocalYOffset = 0;
00075 }
00076 
00077 AREXPORT void ArActionTriangleDriveTo::setParameters(
00078     double finalDistFromVertex,  
00079     double approachDistFromVertex, double speed,
00080     double closeDist, double acquireTurnSpeed)
00081 {
00082   myFinalDistFromVertex = finalDistFromVertex;
00083   myApproachDistFromVertex = approachDistFromVertex;
00084   mySpeed = speed;
00085   myCloseDist = closeDist;
00086   myAcquireTurnSpeed = acquireTurnSpeed;
00087 }
00088 
00089 AREXPORT ArActionTriangleDriveTo::~ArActionTriangleDriveTo()
00090 {
00091   if (myOwnLineFinder)
00092     delete myLineFinder;
00093 }
00094 
00095 AREXPORT void ArActionTriangleDriveTo::activate(void)
00096 {
00097   if (myPrinting)
00098     ArLog::log(ArLog::Normal, "ArActionTriangleDriveTo: Activating");
00099   ArAction::activate();
00100   myVertexSeen = false;
00101   myVertexSeenLast.setToNow();
00102   if (myLineFinder != NULL)
00103     myState = STATE_ACQUIRE;
00104   else
00105     myState = STATE_FAILED;
00106 }
00107 
00108 AREXPORT void ArActionTriangleDriveTo::deactivate(void)
00109 {
00110   ArAction::deactivate();
00111   myState = STATE_INACTIVE;
00112 }
00113 
00114 AREXPORT void ArActionTriangleDriveTo::setRobot(ArRobot *robot)
00115 {
00116   ArAction::setRobot(robot);
00117   if (myLineFinder == NULL && myRobot != NULL)
00118   {
00119     if ((myLaser = myRobot->findRangeDevice("laser")) != NULL)
00120     {
00121       myLineFinder = new ArLineFinder(myLaser);
00122       myOwnLineFinder = true;
00123     }
00124   }
00125 }
00126 
00127 AREXPORT void ArActionTriangleDriveTo::setLineFinder(ArLineFinder *lineFinder)
00128 {
00129   if (myLineFinder != NULL && myOwnLineFinder)
00130     delete myLineFinder;
00131 
00132   myLineFinder = lineFinder;
00133   myOwnLineFinder = false;
00134 }
00135 
00136 AREXPORT ArPose ArActionTriangleDriveTo::findPoseFromVertex(
00137     double distFromVertex)
00138 {
00139   ArPose ret;
00140   ArPose vertex;
00141   vertex = myRobot->getEncoderTransform().doTransform(myVertex);
00142 
00143   ret.setX((vertex.getX() + ArMath::cos(vertex.getTh()) * distFromVertex));
00144   ret.setY((vertex.getY() + ArMath::sin(vertex.getTh()) * distFromVertex));
00145   return ret;
00146 }
00147 
00156 AREXPORT void ArActionTriangleDriveTo::findTriangle(bool initial, 
00157                             bool goStraight)
00158 {
00159   if (myGotLinesCounter != myRobot->getCounter())
00160   {
00161     ArTime now;
00162     now.setToNow();
00163     myLineFinder->setMaxDistBetweenPoints(myMaxDistBetweenLinePoints);
00164     myLines = myLineFinder->getLines();
00165     //printf("took %d\n", now.mSecSince());
00166   }
00167   myGotLinesCounter = myRobot->getCounter();
00168   //  myLineFinder->saveLast();
00169   
00170   int start;
00171   int len = myLines->size();
00172   FILE *corners = NULL;
00173   /*if ((corners = fopen("corners", "w+")) == NULL)
00174   {
00175     printf("Couldn't open corners file\n");
00176   }
00177   */
00178   // length of line 1
00179   double line1Dist;
00180   // length of line 2
00181   double line2Dist;
00182   // distance from the end of line1 to the beginning of line2
00183   double distLine1ToLine2;
00184   // difference in angle between line1 and line2
00185   double angleBetween;
00186   // difference between the angleBetween and the angleBetween we want
00187   double angleDelta;
00189   double line1Delta;
00191   double line2Delta;
00192   // the score for the line evaluated
00193   double lineScore;
00194   // our position of this vertex
00195   ArPose vertex;
00196   // the score for our good line
00197   double goodLineScore = 0.0;
00198   // my pose for the good vertex
00199   ArPose goodVertex;
00200   ArLineSegment vertexLine;
00201   ArPose adjustedVertex;
00202 
00203   ArPose lastVertex;
00204   
00205   lastVertex = myRobot->getEncoderTransform().doTransform(myVertex);
00206 
00207   for (start = 0; start < len; start++)
00208   {
00209     if (start + 1 < len)
00210     {
00211       line1Dist = (*myLines)[start]->getEndPoint1().findDistanceTo(
00212           (*myLines)[start]->getEndPoint2());
00213       line2Dist = (*myLines)[start+1]->getEndPoint1().findDistanceTo(
00214           (*myLines)[start+1]->getEndPoint2());
00215       distLine1ToLine2 = (*myLines)[start]->getEndPoint2().findDistanceTo(
00216           (*myLines)[start+1]->getEndPoint1());
00217       angleBetween = ArMath::subAngle(180, 
00218                ArMath::subAngle((*myLines)[start]->getLineAngle(),
00219                        (*myLines)[start+1]->getLineAngle()));
00220       angleDelta = ArMath::fabs(ArMath::subAngle(angleBetween, myAngleBetween));
00221       line1Delta = ArMath::fabs(line1Dist - myLine1Length);
00222       line2Delta = ArMath::fabs(line2Dist - myLine2Length);
00223       if (0)
00224     ArLog::log(ArLog::Normal, "dl1l2 %5.0f l1d %5.0f l2d %5.0f thdt %5.0f l1dt %5.0f l2dt %5.0f", 
00225            distLine1ToLine2,
00226            line1Dist,
00227            line2Dist,
00228            angleDelta,
00229            line1Delta, line2Delta);
00230       // if any of these is true the line is just too bad and we should bail
00231       if (line1Delta > 125 || line2Delta > 125 ||
00232       angleDelta > 15 || distLine1ToLine2 > 100)
00233     continue;
00234 
00235 
00236       ArPose intersection;
00237 
00238 
00239       ArLine *line1Line = new ArLine(*(*myLines)[start]->getLine());
00240       ArLine *line2Line = new ArLine(*(*myLines)[start+1]->getLine());
00241       if (!line1Line->intersects(line2Line, &intersection))
00242       {
00243     ArLog::log(ArLog::Terse, "ArActionTriangeDriveTo: couldn't find intersection of lines (shouldn't happen)");
00244     return;
00245       }
00246       delete line1Line;
00247       delete line2Line;
00248 
00249 
00250       
00251       /*
00252     printf("corner at polar %5.0f %5.0f pose (%.0f %.0f) angleDelta %.0f %.0f\n", 
00253     myFinder->getLinesTakenPose().findAngleTo(intersection),
00254     myFinder->getLinesTakenPose().findDistanceTo(intersection),
00255     intersection.getX(), intersection.getY(),
00256     angleDelta,
00257     ArMath::fabs((line1Delta + line2Delta) / 2));
00258       */
00259       if (corners != NULL)
00260     fprintf(corners, "%.0f %.0f\n", intersection.getX(), 
00261         intersection.getY());
00262       
00263       vertex.setPose(intersection);
00264       /*
00265       vertex.setTh(ArMath::subAngle(ArMath::atan2((*myLines)[start]->getY1() - 
00266                           (*myLines)[start+1]->getY2(),
00267                           (*myLines)[start]->getX1() - 
00268                       (*myLines)[start+1]->getX2()),
00269                     90));;
00270       */
00271       vertex.setTh(ArMath::addAngle((*myLines)[start]->getLineAngle(),
00272                     angleBetween / 2));
00273 
00274       vertexLine.newEndPoints(vertex.getX(), vertex.getY(),
00275               vertex.getX() + ArMath::cos(vertex.getTh()) * 20000,
00276                vertex.getY() + ArMath::sin(vertex.getTh()) * 20000);
00277 
00278       if (myMaxLateralDist > 0)
00279       {
00280     ArLineSegment robotLine;
00281     
00282     robotLine.newEndPoints(
00283         myRobot->getX(), myRobot->getY(),
00284         myRobot->getX() + ArMath::cos(myRobot->getTh()) * 20000,
00285         myRobot->getY() + ArMath::sin(myRobot->getTh()) * 20000);
00286 
00287     if (robotLine.getDistToLine(vertex) > myMaxLateralDist)
00288     {
00289       if (0)
00290         ArLog::log(ArLog::Normal, 
00291            "Robot off possible vertex line by %.0f, ignoring it\n", 
00292                robotLine.getDistToLine(vertex));
00293       continue;
00294     }
00295       }
00296 
00297       if (myAdjustVertex) 
00298       {
00299     ArPose end1 = (*myLines)[start]->getEndPoint1();
00300     ArPose end2 = (*myLines)[start+1]->getEndPoint2();
00301     ArPose vertexLocal = vertex;
00302     end1 = myRobot->getToLocalTransform().doTransform(end1);
00303     end2 = myRobot->getToLocalTransform().doTransform(end2);
00304     vertexLocal = myRobot->getToLocalTransform().doTransform(vertexLocal);
00305 
00306     ArPose closest;
00307     /* old way that checked too large an area
00308     myLaser->currentReadingBox(0, end1.getY(),
00309                    ArUtil::findMax(end1.getX(), end2.getX()),
00310                    end2.getY(),
00311                    &closest);
00312     */
00313 
00314     // new way that looks 100 mm closer to the robot than the
00315     // vertex this may not be quite right because there's a chance
00316     // the vertex won't be closest to the robot but that will be
00317     // at an angle deep enough we probably won't see the other
00318     // side the of the triangle so we should be okay
00319     myLaser->currentReadingBox(vertexLocal.getX() - 100, end1.getY(),
00320                    ArUtil::findMax(end1.getX(), end2.getX()),
00321                    end2.getY(),
00322                    &closest);
00323     closest = myRobot->getToGlobalTransform().doTransform(closest);
00324     //printf("%g %g %g %g close %g %g\n", end1.getX(), end1.getY(), 
00325     //end2.getX(), end2.getY(), closest.getX(), closest.getY());
00326     
00327     adjustedVertex.setPose(
00328         closest.getX(), closest.getY(),
00329         ArMath::addAngle((*myLines)[start]->getLineAngle(),
00330                  angleBetween / 2));
00331 
00332       } 
00333 
00334 
00335       //printf("One that may be good enough\n");
00336       // if we got here we should calculate the score for the line
00337       // first we calculate the score based on it matching
00338       lineScore = 0;
00339       lineScore += 10 - 1 * (line1Delta / 25);
00340       //printf("1 %.0f\n", lineScore);
00341       lineScore += 10 - 1 * (line2Delta / 25);
00342       //printf("2 %.0f\n", lineScore);
00343       lineScore += 10 - 1 * (angleDelta / 2);
00344       //printf("3 %.0f\n", lineScore);
00345       // now we calculate based on its position 
00346       
00347       // if we're in our initial one we mostly want to make sure its
00348       // in front of us
00349       if (initial)
00350       {
00351     if (0)
00352       printf("%.0f (%.3f) %.0f\n", 
00353          ArMath::subAngle(myRobot->getTh(),
00354                   myRobot->getPose().findAngleTo(vertex)),
00355          90 - ArMath::fabs(myRobot->findDeltaHeadingTo(vertex)) / 90,
00356          vertexLine.getDistToLine(myRobot->getPose()));
00357     
00358     //ArMath::subAngle(myRobot->getTh(),
00359     //myRobot->getPose().findAngleTo(vertex)))) / 90,
00360 
00361     // weight it more heavily for the lines in front of us
00362     lineScore *= .5 + .5 * (30 - 
00363                 ArMath::fabs(
00364                     ArMath::subAngle(myRobot->getTh(),
00365                    myRobot->getPose().findAngleTo(vertex)))) / 30;
00366     //printf("angle %.0f\n", lineScore);
00367     lineScore *= .5 + .5 * (1500 - 
00368                 vertexLine.getDistToLine(myRobot->getPose())) / 1500;
00369     //printf("disttoline %.0f\n", lineScore);
00370 
00371     // weight it more heavily if the vertex points towards along
00372     // the same line as the line from the robot to the vertex
00373     lineScore *= .5 + .5 * (30 - fabs(ArMath::subAngle(
00374         vertex.getTh(), vertex.findAngleTo(myRobot->getPose()))));
00375     //printf("anglefrompointing %.0f\n", lineScore);
00376     
00377 
00378       }
00379       // for not the initial one weight them more heavily if they're
00380       // close to us
00381       else
00382       {
00383     double dist = lastVertex.findDistanceTo(vertex);
00384     if (dist < 100)
00385       lineScore *= 1;
00386     if (dist < 200)
00387       lineScore *= .8;
00388     else if (dist < 400)
00389       lineScore *= .5;
00390     else if (dist < 600)
00391       lineScore *= .2;
00392     else if (dist < 800)
00393       lineScore *= .1;
00394     else
00395       lineScore *= 0;
00396 
00397     double angleFromLast = fabs(ArMath::subAngle(lastVertex.getTh(), 
00398                         vertex.getTh()));
00399     //printf("AngleFromLast %.0f %.0f %.0f\n", angleFromLast, lastVertex.getTh(), vertex.getTh());
00400     if (angleFromLast < 5)
00401       lineScore *= 1;
00402     else if (angleFromLast < 10)
00403       lineScore *= .75;
00404     else if (angleFromLast < 20)
00405       lineScore *= .5;
00406     else if (angleFromLast < 30)
00407       lineScore *= .25;
00408     else 
00409       lineScore *= 0;
00410 
00411     if (goStraight)
00412     {
00413       double angle = fabs(myRobot->findDeltaHeadingTo(vertex));
00414       if (angle < 2)
00415         lineScore *= 1;
00416       else if (angle < 5)
00417         lineScore *= .5;
00418       else if (angle < 10)
00419         lineScore *= .1;
00420       else
00421         lineScore *= 0;
00422     }
00423       }
00424       //printf("4 %.0f\n", lineScore);
00425       // if the match is too bad just bail
00426       if (lineScore < 5)
00427       {
00428     continue;
00429       }
00430       // otherwise see if its better then our previous one, if so set
00431       // our actual vertex to it
00432       if (goodLineScore < 1 || lineScore > goodLineScore)
00433       {
00434     if (0)
00435       printf("#### %.0f %.0f %.0f at %.0f %.0f\n", 
00436          vertex.getX(), vertex.getY(), vertex.getTh(),
00437          myRobot->getPose().findAngleTo(vertex),
00438          myRobot->getPose().findDistanceTo(vertex));
00439     goodLineScore = lineScore;
00440     ArPose usedVertex;
00441     if (myAdjustVertex)
00442       usedVertex = adjustedVertex;
00443     else
00444       usedVertex = vertex;
00445     
00446     if (myLocalXOffset != 0 || myLocalYOffset != 0 || 
00447         fabs(myThOffset) > .00001)
00448     {
00449       usedVertex.setX(usedVertex.getX() + 
00450               myLocalXOffset * ArMath::cos(usedVertex.getTh()) + 
00451               myLocalYOffset * ArMath::sin(usedVertex.getTh()));
00452       usedVertex.setY(usedVertex.getY() - 
00453               myLocalXOffset * ArMath::sin(usedVertex.getTh()) -
00454               myLocalYOffset * ArMath::cos(usedVertex.getTh()));
00455       usedVertex.setTh(ArMath::addAngle(vertex.getTh(), myThOffset));
00456     }
00457               
00458     myVertex = myRobot->getEncoderTransform().doInvTransform(usedVertex);
00459 
00460     myVertexSeen = true;
00461     myVertexSeenLast.setToNow();
00462       }
00463       continue;
00464 
00465     }
00466   }
00467 
00468   if (corners != NULL)
00469     fclose(corners);
00470   myDataMutex.lock();
00471   if (mySaveData)
00472   {
00473     if (myData != NULL)
00474       myData->setLinesAndVertex(
00475           myLines, myRobot->getEncoderTransform().doTransform(myVertex));
00476   }
00477   myDataMutex.unlock();
00478 }
00479 
00480 AREXPORT ArActionDesired *ArActionTriangleDriveTo::fire(
00481     ArActionDesired currentDesired)
00482 {
00483   myDesired.reset();
00484   double dist;
00485   double angle;
00486   double vel;
00487   ArPose approach;
00488   ArPose final;
00489   ArPose vertex;
00490   
00491   myDataMutex.lock();
00492   if (myData != NULL)
00493   {
00494     delete myData;
00495     myData = NULL;
00496   }
00497   if (mySaveData)
00498     myData = new Data;
00499   myDataMutex.unlock();
00500 
00501   vertex = myRobot->getEncoderTransform().doTransform(myVertex);
00502 
00503   switch (myState)
00504   {
00505   case STATE_INACTIVE:
00506     return NULL;
00507   case STATE_SUCCEEDED:
00508   case STATE_FAILED:
00509     myDesired.setVel(0);
00510     myDesired.setRotVel(0);
00511     return &myDesired;
00512   case STATE_ACQUIRE:
00513     if (myPrinting)
00514       ArLog::log(ArLog::Normal, "Acquire");
00515     findTriangle(true);
00516     if (!myVertexSeen && 
00517     myVertexSeenLast.mSecSince() > myVertexUnseenStopMSecs)
00518     {
00519       if (myAcquire)
00520       {
00521     myState = STATE_SEARCHING;
00522     return fire(currentDesired);
00523       }
00524       else
00525       {
00526     if (myPrinting)
00527       ArLog::log(ArLog::Normal, "Failed");
00528     myState = STATE_FAILED;
00529     return fire(currentDesired);
00530       }
00531     } 
00532     if (myVertexSeen)
00533     {
00534       approach = findPoseFromVertex(myApproachDistFromVertex);
00535       final = findPoseFromVertex(myFinalDistFromVertex);
00536       if (mySaveData)
00537       {
00538     myDataMutex.lock();
00539     if (myData != NULL)
00540     {
00541       myData->setApproach(approach);
00542       myData->setFinal(final);
00543     }
00544     myDataMutex.unlock();
00545       }
00546       // if we aren't approaching or if its behind us go straight to
00547       // final
00548       if (myPrinting)
00549     ArLog::log(ArLog::Normal, "%.0f", ArMath::fabs(myRobot->findDeltaHeadingTo(approach)));
00550       if (myApproachDistFromVertex <= 0 || 
00551       ArMath::fabs(myRobot->findDeltaHeadingTo(approach)) > 90 ||
00552       (ArMath::fabs(myRobot->findDeltaHeadingTo(approach)) > 45 &&  
00553        myRobot->findDistanceTo(final) < myRobot->findDistanceTo(approach)))
00554 
00555       {
00556     if (myGotoVertex)
00557     {
00558       if (myPrinting)
00559         ArLog::log(ArLog::Normal, "Going to vertex");
00560       myState = STATE_GOTO_VERTEX;
00561     }
00562     else
00563     {
00564       if (myPrinting)
00565         ArLog::log(ArLog::Normal, "Going to final");
00566       myState = STATE_GOTO_FINAL;
00567     }
00568     return fire(currentDesired);
00569       }
00570       // otherwise we go to our approach
00571       else
00572       {
00573     myState = STATE_GOTO_APPROACH;
00574     return fire(currentDesired);
00575       }
00576     }
00577     myDesired.setVel(0);
00578     myDesired.setRotVel(0);
00579     return &myDesired;
00580   case STATE_SEARCHING:
00581     if (myPrinting)
00582       ArLog::log(ArLog::Normal, "Searching");
00583     myVertexSeen = false;
00584     findTriangle(true);
00585     if (myVertexSeen)
00586     {
00587       myState = STATE_ACQUIRE;
00588       return fire(currentDesired);
00589     }
00590     myDesired.setVel(0);
00591     myDesired.setRotVel(myAcquireTurnSpeed);
00592     return &myDesired;
00593     break;
00594   case STATE_GOTO_APPROACH:
00595     findTriangle(false);
00596     if (!myVertexSeen && 
00597     myVertexSeenLast.mSecSince() > myVertexUnseenStopMSecs)
00598     {
00599       if (myAcquire)
00600       {
00601     myState = STATE_SEARCHING;
00602     return fire(currentDesired);
00603       }
00604       else
00605       {
00606     ArLog::log(ArLog::Normal, "ArActionTriangleDriveTo: Failed");
00607     myState = STATE_FAILED;
00608     return fire(currentDesired);
00609       }
00610     } 
00611     approach = findPoseFromVertex(myApproachDistFromVertex);
00612     if (mySaveData)
00613     {
00614       myDataMutex.lock();
00615       if (myData != NULL)
00616     myData->setApproach(approach);
00617       myDataMutex.unlock();
00618     }
00619     dist = myRobot->getPose().findDistanceTo(approach);
00620     angle = myRobot->getPose().findAngleTo(approach);
00621     if (dist < myCloseDist || 
00622     (dist < myCloseDist * 2 && 
00623      ArMath::fabs(myRobot->findDeltaHeadingTo(approach)) > 30))
00624     {
00625       if (myPrinting)
00626     ArLog::log(ArLog::Normal, "Goto approach there");
00627       myState = STATE_ALIGN_APPROACH;
00628       return fire(currentDesired);
00629     }
00630     myDesired.setHeading(angle);
00631     vel = sqrt(dist * 400 * 2);
00632     vel *= (180 - ArMath::fabs(myRobot->findDeltaHeadingTo(approach))) / 180;
00633     if (vel < 0)
00634       vel = 0;
00635     if (vel > mySpeed)
00636       vel = mySpeed;
00637     myDesired.setVel(vel);
00638     if (myPrinting)
00639       ArLog::log(ArLog::Normal, "Goto approach speed %.0f dist %.0f angle %.0f", vel, dist, angle);
00640     return &myDesired;
00641   case STATE_ALIGN_APPROACH:
00642     angle = myRobot->getPose().findAngleTo(vertex);
00643     if (myPrinting)
00644       ArLog::log(ArLog::Normal, "Align approach %.0f %.0f", myRobot->getTh(),
00645          angle);
00646     if (ArMath::fabs(ArMath::subAngle(myRobot->getTh(), angle)) < 2 &&
00647     ArMath::fabs(myRobot->getVel()) < 5)
00648     {
00649       //ArLog::log(ArLog::Normal, "finaldist %.0f", ArMath::fabs(myFinalDistFromVertex));
00650       if (myGotoVertex)
00651       {
00652     if (myPrinting)
00653       ArLog::log(ArLog::Normal, "Going to vertex");
00654     myState = STATE_GOTO_VERTEX;
00655       }
00656       else
00657       {
00658     if (myPrinting)
00659       ArLog::log(ArLog::Normal, "Going to final");
00660     myState = STATE_GOTO_FINAL;
00661       }
00662       return fire(currentDesired);
00663     }
00664     myDesired.setHeading(angle);
00665     myDesired.setVel(0);
00666     return &myDesired;
00667   case STATE_GOTO_VERTEX:
00668     final = findPoseFromVertex(0);
00669     if (myUseIgnoreInGoto && 
00670     (myRobot->findDistanceTo(final) > 
00671      myFinalDistFromVertex + myIgnoreTriangleDist))
00672       findTriangle(false, true);
00673 
00674     if (!myVertexSeen && 
00675     myVertexSeenLast.mSecSince() > myVertexUnseenStopMSecs)
00676     {
00677       ArLog::log(ArLog::Normal, "ActionTriangle: Failed");
00678       myState = STATE_FAILED;
00679       return fire(currentDesired);
00680     } 
00681     final = findPoseFromVertex(0);
00682     if (mySaveData)
00683     {
00684       myDataMutex.lock();
00685       if (myData != NULL)
00686     myData->setFinal(final);
00687       myDataMutex.unlock();
00688     }
00689     dist = myRobot->findDistanceTo(final);
00690     dist -= myFinalDistFromVertex;
00691     angle = myRobot->findDeltaHeadingTo(final);
00692     if (ArMath::fabs(angle) > 10)
00693       {
00694     ArLog::log(ArLog::Normal, "ActionTriangle: FAILING because trying to turn %.0f degrees to something %.0f away that we saw %ld ms ago ", angle, dist, myVertexSeenLast.mSecSince());
00695     myState = STATE_FAILED;
00696     return fire(currentDesired);
00697       }
00698     else
00699       {
00700     myDesired.setDeltaHeading(angle);
00701       }
00702     if (dist > 0)
00703       vel = sqrt(dist * 100 * 2);
00704     else
00705       vel = 0;
00706     if (vel < 0)
00707       vel = 0;
00708     if (vel > mySpeed)
00709       vel = mySpeed;
00710     myDesired.setVel(vel);
00711     if (dist <= 0 && fabs(myRobot->getVel()) < 5)
00712     {
00713       ArLog::log(ArLog::Normal, "ArActionTriangleDriveTo: Succeeded (vertex) %g", dist);
00714       myState = STATE_SUCCEEDED;
00715       return fire(currentDesired);
00716     }
00717     if (myPrinting)
00718       ArLog::log(ArLog::Normal, "Goto vertex speed %.0f dist %.0f angle %.0f %ld ago",
00719          vel, dist, myRobot->findDeltaHeadingTo(final),
00720          myVertexSeenLast.mSecSince());
00721     return &myDesired;
00722 
00723   case STATE_GOTO_FINAL:
00724     // see if we are close enough we just keep the same reading,
00725     // otherwise we get the new reading
00726 
00727     final = findPoseFromVertex(myFinalDistFromVertex);
00728 
00729     //if (myRobot->findDistanceTo(final) > 250)
00730     if (myRobot->findDistanceTo(final) > myIgnoreTriangleDist)
00731       findTriangle(false);
00732 
00733     if (!myVertexSeen && 
00734     myVertexSeenLast.mSecSince() > myVertexUnseenStopMSecs)
00735     {
00736       if (myAcquire)
00737       {
00738     myState = STATE_SEARCHING;
00739     return fire(currentDesired);
00740       }
00741       else
00742       {
00743     ArLog::log(ArLog::Normal, "ArActionTriangleDriveTo: Failed");
00744     myState = STATE_FAILED;
00745     return fire(currentDesired);
00746       }
00747     } 
00748     final = findPoseFromVertex(myFinalDistFromVertex);
00749     if (mySaveData)
00750     {
00751       myDataMutex.lock();
00752       if (myData != NULL)
00753     myData->setFinal(final);
00754       myDataMutex.unlock();
00755     }
00756     dist = myRobot->getPose().findDistanceTo(final);
00757     angle = myRobot->getPose().findAngleTo(final);
00758     if (myPrinting)
00759       ArLog::log(ArLog::Normal, 
00760          "final %.0f away at %.0f vertex %.0f away %ld ago", 
00761          dist, myRobot->findDeltaHeadingTo(final),
00762          myRobot->findDistanceTo(vertex), 
00763          myVertexSeenLast.mSecSince());
00764 
00765     if ((dist < 5) || 
00766     (myRobot->getVel() > 0 && dist < myCloseDist && 
00767      ArMath::fabs(myRobot->findDeltaHeadingTo(final)) > 20) ||
00768     (myRobot->getVel() < 0 && dist < myCloseDist && 
00769      ArMath::fabs(myRobot->findDeltaHeadingTo(final)) < 160) ||
00770     (ArMath::fabs(myRobot->getVel()) < 5 && dist < myCloseDist))
00771     {
00772       if (myPrinting)
00773     ArLog::log(ArLog::Normal, "Goto final there");
00774       myState = STATE_ALIGN_FINAL;
00775       return fire(currentDesired);
00776     }
00777 
00778     if (ArMath::fabs(ArMath::subAngle(myRobot->getTh(),
00779                       angle)) < 90)
00780     {
00781       myDesired.setHeading(angle);
00782       vel = sqrt(dist * 100 * 2);
00783       vel *= (45 - ArMath::fabs(myRobot->findDeltaHeadingTo(final))) / 45;
00784       if (vel < 0)
00785     vel = 0;
00786       if (vel > mySpeed)
00787     vel = mySpeed;
00788       myDesired.setVel(vel);
00789       if (myPrinting)
00790     ArLog::log(ArLog::Normal, "Goto final speed %.0f dist %.0f angle %.0f", vel, dist, myRobot->findDeltaHeadingTo(final));
00791 
00792       return &myDesired;
00793     }
00794     else
00795     {
00796       myDesired.setHeading(
00797           ArMath::subAngle(myRobot->getPose().findAngleTo(final), 180));
00798       vel = -1 * sqrt(dist * 100 * 2);
00799       vel *= (45 - ArMath::fabs(ArMath::subAngle(180,
00800                  myRobot->findDeltaHeadingTo(final)))) / 45;
00801       if (vel > 0)
00802     vel = 0;
00803       if (vel < -mySpeed)
00804     vel = -mySpeed;
00805       myDesired.setVel(vel);
00806       if (myPrinting)
00807     ArLog::log(ArLog::Normal, "Goto final (backing) speed %.0f dist %.0f angle %.0f (turning to %.0f)", vel, dist, angle, 
00808            ArMath::subAngle(180, myRobot->findDeltaHeadingTo(final)));
00809       return &myDesired;
00810     }
00811   case STATE_ALIGN_FINAL:
00812     angle = myRobot->getPose().findAngleTo(vertex);
00813     if (ArMath::fabs(ArMath::subAngle(myRobot->getTh(), angle)) < 2 &&
00814     ArMath::fabs(myRobot->getVel()) < 5)
00815     {
00816       ArLog::log(ArLog::Normal, "ArActionTriangleDriveTo: Succeeded");
00817       myState = STATE_SUCCEEDED;
00818       return fire(currentDesired);
00819     }
00820     if (myPrinting)
00821       ArLog::log(ArLog::Normal, "Align final");
00822     myDesired.setHeading(angle);
00823     myDesired.setVel(0);
00824     return &myDesired;
00825   }
00826 
00827   findTriangle(true);
00828   return NULL;
00829 
00830 }
00831 
00832 ArActionTriangleDriveTo::Data *ArActionTriangleDriveTo::getData(void)
00833 {
00834   Data *data = NULL;
00835   myDataMutex.lock();
00836   data = myData;
00837   myData = NULL;
00838   myDataMutex.unlock();
00839   return data;
00840 }
00841 
00842 

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