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 "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
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
00166 }
00167 myGotLinesCounter = myRobot->getCounter();
00168
00169
00170 int start;
00171 int len = myLines->size();
00172 FILE *corners = NULL;
00173
00174
00175
00176
00177
00178
00179 double line1Dist;
00180
00181 double line2Dist;
00182
00183 double distLine1ToLine2;
00184
00185 double angleBetween;
00186
00187 double angleDelta;
00189 double line1Delta;
00191 double line2Delta;
00192
00193 double lineScore;
00194
00195 ArPose vertex;
00196
00197 double goodLineScore = 0.0;
00198
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
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
00253
00254
00255
00256
00257
00258
00259 if (corners != NULL)
00260 fprintf(corners, "%.0f %.0f\n", intersection.getX(),
00261 intersection.getY());
00262
00263 vertex.setPose(intersection);
00264
00265
00266
00267
00268
00269
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
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
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
00325
00326
00327 adjustedVertex.setPose(
00328 closest.getX(), closest.getY(),
00329 ArMath::addAngle((*myLines)[start]->getLineAngle(),
00330 angleBetween / 2));
00331
00332 }
00333
00334
00335
00336
00337
00338 lineScore = 0;
00339 lineScore += 10 - 1 * (line1Delta / 25);
00340
00341 lineScore += 10 - 1 * (line2Delta / 25);
00342
00343 lineScore += 10 - 1 * (angleDelta / 2);
00344
00345
00346
00347
00348
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
00359
00360
00361
00362 lineScore *= .5 + .5 * (30 -
00363 ArMath::fabs(
00364 ArMath::subAngle(myRobot->getTh(),
00365 myRobot->getPose().findAngleTo(vertex)))) / 30;
00366
00367 lineScore *= .5 + .5 * (1500 -
00368 vertexLine.getDistToLine(myRobot->getPose())) / 1500;
00369
00370
00371
00372
00373 lineScore *= .5 + .5 * (30 - fabs(ArMath::subAngle(
00374 vertex.getTh(), vertex.findAngleTo(myRobot->getPose()))));
00375
00376
00377
00378 }
00379
00380
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
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
00425
00426 if (lineScore < 5)
00427 {
00428 continue;
00429 }
00430
00431
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
00547
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
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
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
00725
00726
00727 final = findPoseFromVertex(myFinalDistFromVertex);
00728
00729
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