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

ArActionTriangleDriveTo.cpp

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

Generated on Wed Oct 19 12:56:34 2005 for Aria by  doxygen 1.4.0