00001 #include "Motion/WalkMC.h"
00002 #ifdef TGT_HAS_WALK
00003
00004 #include <vector>
00005
00006 #include "Crew/Pilot.h"
00007 #include "DualCoding/VRmixin.h"
00008 #include "Events/PilotEvent.h"
00009 # include "Planners/Navigation/ShapeSpacePlannerXYTheta.h"
00010 #include "Shared/mathutils.h"
00011 #include "Vision/VisualOdometry/VisualOdometry.h"
00012
00013 namespace DualCoding {
00014
00015 void Pilot::doStart() {
00016 if (verbosity & PVstart)
00017 cout << "Pilot starting up: walk_id= " << walk_id <<" waypointwalk_id= " << waypointwalk_id << endl;
00018 setAgent(Point(0,0,0,allocentric),0,false,false);
00019 VRmixin::particleFilter->displayParticles(50);
00020 addNode(new RunMotionModel)->start();
00021 addNode(new CollisionChecker)->start();
00022 addNode(new RunOpticalFlow)->start();
00023 }
00024
00025 void Pilot::doStop() {
00026 pilotAbort();
00027 if (verbosity & PVstart)
00028 cout << "Pilot is shutting down." << endl;
00029 motman->removeMotion(walk_id);
00030 motman->removeMotion(waypointwalk_id);
00031 waypointwalk_id = MotionManager::invalid_MC_ID;
00032 walk_id = MotionManager::invalid_MC_ID;
00033 delete defaultLandmarkExtractor;
00034 defaultLandmarkExtractor = NULL;
00035
00036
00037
00038
00039
00040
00041
00042 teardown();
00043 }
00044
00045 void Pilot::doEvent() {
00046 if (event->getGeneratorID() == EventBase::timerEGID && event->getSourceID() == 9999)
00047 executeRequest();
00048 else
00049 cout << "Pilot got unexpected event: " << event->getDescription() << endl;
00050 }
00051
00052 void Pilot::unwindForNextRequest() {
00053 erouter->addTimer(this,9999,1,false);
00054 }
00055
00056 void Pilot::setAgent(const Point &loc, AngTwoPi heading, bool quiet, bool updateWaypoint) {
00057 if (updateWaypoint) {
00058 cout << "Updating waypoint walk to " << loc << " hdg=" << heading << endl;
00059 MMAccessor<WaypointWalkMC> wp_acc(waypointwalk_id);
00060 wp_acc->setCurPos(loc.coordX(), loc.coordY(), heading);
00061 }
00062 VRmixin::mapBuilder->setAgent(loc, heading, quiet);
00063
00064
00065
00066 VRmixin::particleFilter->setPosition(loc.coordX(), loc.coordY(), heading);
00067 VRmixin::particleFilter->synchEstimateToAgent();
00068 }
00069
00070 unsigned int Pilot::executeRequest(BehaviorBase* requestingBehavior, const PilotRequest& req) {
00071 VRmixin::requireCrew("Pilot");
00072 requests.push(new PilotRequest(req));
00073 const unsigned int reqID = ++idCounter;
00074 requests.back()->requestID = reqID;
00075 requests.back()->requestingBehavior = requestingBehavior;
00076 if (curReq == NULL)
00077 unwindForNextRequest();
00078 else if (verbosity & PVqueued)
00079 cout << "Pilot request " << requests.back()->requestID << " queued." << endl;
00080 return reqID;
00081 }
00082
00083 void Pilot::executeRequest() {
00084 if (curReq == NULL && !requests.empty()) {
00085 curReq = requests.front();
00086 if (verbosity & PVexecute)
00087 cout << "Pilot executing request " << curReq->requestID
00088 << ": " << PilotTypes::RequestTypeNames[curReq->requestType] << endl;
00089 VRmixin::particleFilter->synchEstimateToAgent();
00090 if ( ! curReq->walkParameters.empty() ) {
00091 MMAccessor<WaypointWalkMC>(VRmixin::pilot->getWaypointwalk_id())->WalkMC::loadFile(curReq->walkParameters.c_str());
00092 MMAccessor<WalkMC>(VRmixin::pilot->getWalk_id())->loadFile(curReq->walkParameters.c_str());
00093 }
00094 dispatch_->start();
00095 }
00096 }
00097
00098 void Pilot::requestComplete(PilotTypes::ErrorType_t errorType) {
00099 if (curReq == NULL) {
00100 cout << "Pilot::requestComplete had NULL curReq !!!!!!!!!!!!!!!!" << endl;
00101 return;
00102 }
00103 const BehaviorBase* requester = curReq->requestingBehavior;
00104 PilotEvent e(EventBase::pilotEGID,
00105 (requester==NULL) ? curReq->requestID : (size_t)requester,
00106 EventBase::statusETID);
00107 e.requestType = curReq->requestType;
00108 e.errorType = errorType;
00109 if (verbosity & PVcomplete)
00110 cout << "Pilot request " << curReq->requestID << " complete: "
00111 << PilotTypes::ErrorTypeNames[errorType] << endl;
00112 requestComplete(e);
00113 }
00114
00115 void Pilot::requestComplete(const PilotEvent &e) {
00116
00117
00118 dispatch_->finish();
00119
00120 delete curReq->landmarkExtractor;
00121 delete curReq->searchObjectExtractor;
00122 delete curReq;
00123 curReq = NULL;
00124 requests.pop();
00125
00126 erouter->postEvent(e);
00127 VRmixin::autoRefreshSketchWorld();
00128 unwindForNextRequest();
00129 }
00130
00131 void Pilot::setWorldBounds(float minX, float width, float minY, float height) {
00132 VRmixin::particleFilter->setWorldBounds(minX, width, minY, height);
00133 }
00134
00135 void Pilot::setWorldBounds(const Shape<PolygonData> &bounds) {
00136 VRmixin::particleFilter->setWorldBounds(bounds);
00137 }
00138
00139 void Pilot::randomizeParticles(float widthIncr, float heightIncr) {
00140 computeParticleBounds(widthIncr, heightIncr);
00141 VRmixin::particleFilter->resetFilter();
00142 }
00143
00144 void Pilot::computeParticleBounds(float widthIncr, float heightIncr) {
00145 GET_SHAPE(worldBounds, PolygonData, VRmixin::worldShS);
00146 if ( worldBounds.isValid() )
00147 setWorldBounds(worldBounds);
00148 else {
00149 float minX=1e20, maxX=-minX, minY=1e20, maxY=-minY;
00150 SHAPEROOTVEC_ITERATE(VRmixin::worldShS, s) {
00151 BoundingBox2D b(s->getBoundingBox());
00152 minX = min(minX, b.min[0]);
00153 minY = min(minY, b.min[1]);
00154 maxX = max(maxX, b.max[0]);
00155 maxY = max(maxY, b.max[1]);
00156 } END_ITERATE;
00157 setWorldBounds(minX-widthIncr/2, maxX-minX+widthIncr,
00158 minY-heightIncr/2, maxY-minY+heightIncr);
00159 }
00160 }
00161
00162 void Pilot::setDefaultLandmarks(const std::vector<ShapeRoot> &landmarks) {
00163 defaultLandmarks = landmarks;
00164 }
00165
00166 void Pilot::setDefaultLandmarkExtractor(const MapBuilderRequest &mapreq) {
00167 defaultLandmarkExtractor = new MapBuilderRequest(mapreq);
00168 defaultLandmarkExtractor->clearLocal = false;
00169 }
00170
00171 void Pilot::pilotPop() {
00172 if ( curReq != NULL ) {
00173 if ( verbosity & PVpop )
00174 cout << "Pilot popping current request." << endl;
00175 dispatch_->stop();
00176 VRmixin::pilot->requestComplete(PilotTypes::abort);
00177 }
00178 }
00179
00180 void Pilot::pilotAbort() {
00181 if ( verbosity & PVabort ) {
00182 if ( curReq == NULL )
00183 cout << "Pilot aborting but there is no current request." << endl;
00184 else
00185 cout << "Pilot aborting." << endl;
00186 }
00187 dispatch_->stop();
00188 VRmixin::isWalkingFlag = false;
00189 if ( curReq != NULL )
00190 VRmixin::pilot->requestComplete(abort);
00191 while (!requests.empty()) {
00192 delete requests.front();
00193 requests.pop();
00194 }
00195 }
00196
00197 void Pilot::setupLandmarkExtractor() {
00198 if ( curReq->landmarkExitTest == NULL )
00199 curReq->landmarkExitTest = &Pilot::defaultLandmarkExitTest;
00200 if ( curReq->landmarkExtractor != NULL )
00201 return;
00202 else if ( defaultLandmarkExtractor != NULL ) {
00203 curReq->landmarkExtractor = new MapBuilderRequest(*defaultLandmarkExtractor);
00204 return;
00205 }
00206 vector<ShapeRoot> landmarkTemp;
00207 if ( ! curReq->landmarks.empty() )
00208 landmarkTemp = curReq->landmarks;
00209 else if ( ! defaultLandmarks.empty() )
00210 landmarkTemp = defaultLandmarks;
00211 else {
00212 const vector<ShapeRoot> &wshapes = VRmixin::worldShS.allShapes();
00213 for ( vector<ShapeRoot>::const_iterator it = wshapes.begin();
00214 it != wshapes.end(); it++ )
00215 if ( (*it)->isLandmark() )
00216 landmarkTemp.push_back(*it);
00217 }
00218 if ( landmarkTemp.empty() ) {
00219
00220
00221 NEW_SHAPEVEC(markers, MarkerData, select_type<MarkerData>(VRmixin::worldShS));
00222 landmarkTemp.insert(landmarkTemp.begin(), markers.begin(), markers.end());
00223 NEW_SHAPEVEC(apriltags, AprilTagData, select_type<AprilTagData>(VRmixin::worldShS));
00224 landmarkTemp.insert(landmarkTemp.begin(), apriltags.begin(), apriltags.end());
00225 }
00226 if ( !landmarkTemp.empty() ) {
00227 curReq->landmarks = landmarkTemp;
00228 curReq->landmarkExtractor = new MapBuilderRequest(MapBuilderRequest::localMap);
00229 curReq->landmarkExtractor->clearVerbosity = -1U;
00230 curReq->landmarkExtractor->setVerbosity = MapBuilder::MBVimportShapes;
00231 for ( vector<ShapeRoot>::const_iterator it = landmarkTemp.begin();
00232 it != landmarkTemp.end(); it++ )
00233 curReq->landmarkExtractor->addAttributes(*it);
00234 }
00235 }
00236
00237 bool Pilot::defaultLandmarkExitTest() {
00238
00239
00240
00241
00242
00243 std::vector<ShapeRoot> &locs = VRmixin::localShS.allShapes();
00244 int n = locs.size();
00245 SHAPEROOTVEC_ITERATE(locs, s) {
00246 if ( s->isType(pointDataType) )
00247 --n;
00248 else if ( s->isType(aprilTagDataType) ) {
00249 n--;
00250 SHAPEROOTVEC_ITERATE(VRmixin::pilot->curReq->landmarks, lm) {
00251 if ( lm->isType(aprilTagDataType) &&
00252 ShapeRootTypeConst(lm,AprilTagData)->getTagID() ==
00253 ShapeRootTypeConst(s,AprilTagData)->getTagID() ) {
00254 n++;
00255 break;
00256 } END_ITERATE;
00257 }
00258 }
00259 } END_ITERATE;
00260
00261
00262 return ( n >= 2 );
00263 }
00264
00265 std::vector<ShapeRoot>
00266 Pilot::calculateVisibleLandmarks(const DualCoding::Point ¤tLocation,
00267 AngTwoPi currentOrientation, AngTwoPi maxTurn,
00268 const std::vector<DualCoding::ShapeRoot> &possibleLandmarks) {
00269 std::vector<ShapeRoot> result;
00270 for(unsigned int i = 0; i<possibleLandmarks.size(); i++)
00271 if ( isLandmarkViewable(possibleLandmarks[i], currentLocation, currentOrientation, maxTurn) )
00272 result.push_back(possibleLandmarks[i]);
00273 return result;
00274 }
00275
00276 bool Pilot::isLandmarkViewable(const DualCoding::ShapeRoot &selectedLandmark,
00277 const DualCoding::Point ¤tLocation,
00278 AngTwoPi currentOrientation, AngTwoPi maxTurn) {
00279 AngSignPi bearing = (selectedLandmark->getCentroid() - currentLocation).atanYX();
00280
00281
00282 if ( fabs(bearing) > (CameraHorizFOV/2.0+maxTurn) )
00283 return false;
00284
00285
00286
00287
00288 Shape<PolygonData> boundary;
00289 GET_SHAPE(worldBounds, PolygonData, VRmixin::worldShS);
00290 if ( worldBounds.isValid() )
00291 boundary = worldBounds;
00292 else {
00293 GET_SHAPE(wall, PolygonData, VRmixin::worldShS);
00294 boundary = wall;
00295 }
00296 if ( ! boundary.isValid() )
00297 return true;
00298
00299 LineData lineOfSight(VRmixin::worldShS, currentLocation, selectedLandmark->getCentroid());
00300 if ( boundary->intersectsLine(lineOfSight) )
00301 return false;
00302
00303
00304 return true;
00305 }
00306
00307 void Pilot::CollisionDispatch::doStart() {
00308 switch ( VRmixin::pilot->curReq->collisionAction ) {
00309 case collisionStop:
00310 case collisionReplan:
00311 erouter->addListener(this, EventBase::pilotEGID, (size_t)VRmixin::pilot, EventBase::statusETID);
00312 break;
00313 default:
00314 break;
00315 }
00316 }
00317
00318 void Pilot::CollisionDispatch::doEvent() {
00319
00320
00321 PilotEvent e(*event);
00322 e.setSourceID((size_t)this);
00323 erouter->postEvent(e);
00324 }
00325
00326 void Pilot::TerminateDueToCollision::doStart() {
00327 PilotEvent e(*event);
00328 e.setSourceID((size_t)VRmixin::pilot->curReq->requestingBehavior);
00329 VRmixin::isWalkingFlag = false;
00330 VRmixin::pilot->requestComplete(e);
00331 }
00332
00333
00334
00335 void Pilot::RunMotionModel::doStart() {
00336 erouter->addTimer(this, 1, 250, true);
00337 }
00338
00339 void Pilot::RunMotionModel::doEvent() {
00340 if (event->getGeneratorID() == EventBase::timerEGID) {
00341 VRmixin::particleFilter->updateMotion();
00342 LocalizationParticle estimate = VRmixin::particleFilter->getEstimate();
00343 VRmixin::mapBuilder->setAgent(Point(estimate.x, estimate.y, 0, allocentric), estimate.theta, true);
00344 }
00345 }
00346
00347 void Pilot::RunOpticalFlow::doStart() {
00348 if ( VRmixin::imageOdometry != NULL )
00349 erouter->addTimer(this, 1, VRmixin::imageOdometry->suggestedFrameRate(), true);
00350 }
00351
00352 void Pilot::RunOpticalFlow::doEvent() {
00353 if (event->getGeneratorID() == EventBase::timerEGID)
00354 VRmixin::imageOdometry->update();
00355 }
00356
00357 void Pilot::CollisionChecker::doStart() {
00358 enableDetection();
00359 }
00360
00361 void Pilot::CollisionChecker::enableDetection() {
00362 #if defined(TGT_IS_CREATE) || defined(TGT_IS_CREATE2)
00363
00364 erouter->addListener(this, EventBase::buttonEGID, BumpLeftButOffset, EventBase::activateETID);
00365 erouter->addListener(this, EventBase::buttonEGID, BumpRightButOffset, EventBase::activateETID);
00366 erouter->addListener(this, EventBase::buttonEGID, OvercurrentLeftWheelOffset, EventBase::activateETID);
00367 erouter->addListener(this, EventBase::buttonEGID, OvercurrentRightWheelOffset, EventBase::activateETID);
00368 erouter->addTimer(this, overcurrentResetTimer, 1500, true);
00369 #else
00370 std::cout << "Warning: Pilot has no collision check method defined for this robot type" << std::endl;
00371 #endif
00372 }
00373
00374 void Pilot::CollisionChecker::disableDetection(unsigned int howlong=-1U) {
00375 #if defined(TGT_IS_CREATE) || defined(TGT_IS_CREATE2)
00376
00377 erouter->removeListener(this, EventBase::buttonEGID);
00378 #endif
00379 erouter->addTimer(this, 1, howlong, false);
00380 }
00381
00382 void Pilot::CollisionChecker::doEvent() {
00383 if ( event->getGeneratorID() == EventBase::timerEGID ) {
00384 if ( event->getSourceID() == collisionEnableTimer )
00385 enableDetection();
00386 #if defined(TGT_IS_CREATE) || defined(TGT_IS_CREATE2)
00387 else if ( event->getSourceID() == overcurrentResetTimer )
00388 overcurrentCounter = 0;
00389 return;
00390 #endif
00391 }
00392
00393 if ( VRmixin::pilot->curReq == NULL ||
00394 VRmixin::pilot->curReq->collisionAction == collisionIgnore )
00395 return;
00396 #if defined(TGT_IS_CREATE) || defined(TGT_IS_CREATE2)
00397 if ( event->getSourceID() == BumpLeftButOffset ||
00398 event->getSourceID() == BumpRightButOffset )
00399 reportCollision();
00400 else
00401 if ( ++overcurrentCounter >= 12 ) {
00402 overcurrentCounter = 0;
00403 reportCollision();
00404 }
00405 #endif
00406 }
00407
00408 void Pilot::CollisionChecker::reportCollision() {
00409 if ( VRmixin::pilot->verbosity & PVcollision )
00410 cout << "Pilot: collision detected!" << endl;
00411 disableDetection(1000);
00412 PilotEvent e(EventBase::pilotEGID, (size_t)VRmixin::pilot, EventBase::statusETID);
00413 e.errorType = collisionDetected;
00414
00415
00416 erouter->postEvent(e);
00417 }
00418
00419 void Pilot::PlanPath::clearGraphics() {
00420 GET_SHAPE(plannedPath, GraphicsData, VRmixin::worldShS);
00421 plannedPath.deleteShape();
00422 GET_SHAPE(plannerTrees, GraphicsData, VRmixin::worldShS);
00423 plannerTrees.deleteShape();
00424 }
00425
00426 void Pilot::PlanPath::doPlan(NavigationPlan &plan, Point initPoint, AngTwoPi initHead, PilotRequest &req) {
00427 plan.clear();
00428 clearGraphics();
00429 Point targetPoint = req.targetShape->getCentroid();
00430 if ( targetPoint.getRefFrameType() == egocentric ) {
00431 targetPoint.applyTransform(VRmixin::mapBuilder->localToWorldMatrix);
00432 targetPoint.setRefFrameType(allocentric);
00433 }
00434 AngTwoPi targetHeading = req.targetHeading;
00435 fmat::Column<3> baseOffset = req.baseOffset;
00436
00437 const bool planForHeading = ! std::isnan((float)targetHeading);
00438 std::cout << "Planning path from " << initPoint << " to point: " << targetPoint;
00439 if ( baseOffset != fmat::ZERO3 )
00440 cout << " target offset " << baseOffset;
00441 if ( planForHeading )
00442 cout << " heading " << float(targetHeading)/M_PI*180 << " deg.";
00443 cout << std::endl;
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 Point baseTemp = Point(fmat::rotationZ(targetHeading)*baseOffset, allocentric);
00459 Point straightVec = (targetPoint - baseTemp) - initPoint;
00460 float straightDist = straightVec.xyNorm();
00461 AngTwoPi straightAng = float(straightVec.atanYX());
00462 AngSignPi straightAngDiff = float(straightAng - initHead);
00463 if ( req.allowBackwardMotion && planForHeading &&
00464 straightDist <= req.maxBackwardDistance &&
00465 abs(straightAngDiff) > M_PI/1.8 &&
00466 abs(AngSignPi(targetHeading - initHead)) < M_PI/1.8 ) {
00467 plan.walkBackward = true;
00468 std:: cout << "Walking backward..." << std::endl;
00469 }
00470
00471 Point gatePoint = targetPoint;
00472 if ( plan.walkBackward ) {
00473 gatePoint = targetPoint - baseTemp;
00474 baseOffset = fmat::ZERO3;
00475 swap(initPoint, gatePoint);
00476 swap(initHead, targetHeading);
00477 }
00478
00479
00480 GET_SHAPE(worldBounds, PolygonData, VRmixin::worldShS);
00481 ShapeSpacePlannerXYTheta planner(VRmixin::worldShS, worldBounds, req.obstacleInflation);
00482 std::vector<NodeValue_t> *pathResult = new std::vector<NodeValue_t>;
00483 std::vector<NodeType_t> *treeStartResult = req.displayTree ? new std::vector<NodeType_t> : NULL;
00484 std::vector<NodeType_t> *treeEndResult = req.displayTree ? new std::vector<NodeType_t> : NULL;
00485 GenericRRTBase::PlannerResult2D result =
00486 planner.planPath(initPoint, baseOffset, req.gateLength,
00487 gatePoint, initHead, targetHeading, req.maxRRTIterations,
00488 pathResult, treeStartResult, treeEndResult);
00489 if ( plan.walkBackward ) {
00490 if ( result.code == GenericRRTBase::SUCCESS ) {
00491 swap(initPoint, gatePoint);
00492 swap(initHead, targetHeading);
00493
00494
00495
00496 NodeValue_t &final = (*pathResult)[pathResult->size()-1];
00497 NodeValue_t &preFinal = (*pathResult)[pathResult->size()-2];
00498 std::vector<NodeValue_t> *revPath = new std::vector<NodeValue_t>;
00499 revPath->reserve(pathResult->size()+1);
00500 revPath->push_back(NodeValue_t(final.x, final.y, final.theta, 0));
00501 revPath->push_back(NodeValue_t(preFinal.x, preFinal.y, final.theta, 0));
00502 for ( int i = pathResult->size()-3; i >= 0; i-- )
00503 revPath->push_back(NodeValue_t((*pathResult)[i].x, (*pathResult)[i].y,
00504 (*pathResult)[i+1].theta, -(*pathResult)[i+2].turn));
00505 revPath->push_back(NodeValue_t((*pathResult)[0].x, (*pathResult)[0].y,
00506 (*pathResult)[0].theta, -(*pathResult)[1].turn));
00507 delete pathResult;
00508 pathResult = revPath;
00509 } else if ( result.code == GenericRRTBase::START_COLLIDES )
00510 result.code = GenericRRTBase::END_COLLIDES;
00511 else if ( result.code == GenericRRTBase::END_COLLIDES )
00512 result.code = GenericRRTBase::START_COLLIDES;
00513 } else
00514 if ( result.code == GenericRRTBase::SUCCESS && planForHeading ) {
00515
00516 AngSignPi headingChange = AngSignPi(targetHeading - pathResult->back().theta);
00517 AngSignTwoPi turn;
00518 if ( RRTNodeXYTheta::safeTurn(pathResult->back(), headingChange, turn, planner.getCC()) ) {
00519 fmat::Column<3> offsetTarget = targetPoint.getCoords() - fmat::rotationZ(targetHeading) * baseOffset;
00520 NodeValue_t final(offsetTarget[0],offsetTarget[1],targetHeading, turn);
00521 pathResult->push_back(final);
00522 }
00523 else
00524 result.code = GenericRRTBase::END_COLLIDES;
00525 }
00526
00527 if ( req.displayTree ) {
00528 NEW_SHAPE(plannerTrees, GraphicsData, new GraphicsData(VRmixin::worldShS));
00529 planner.plotTree(*treeStartResult, plannerTrees, rgb(0,0,0));
00530 planner.plotTree(*treeEndResult, plannerTrees, rgb(0,192,0));
00531 delete treeStartResult;
00532 delete treeEndResult;
00533 }
00534 if ( req.displayObstacles || req.autoDisplayObstacles ) {
00535 if ( result.code == GenericRRTBase::END_COLLIDES ) {
00536 VRmixin::robotObstaclesPt = targetPoint;
00537 VRmixin::robotObstaclesOri = planForHeading ? targetHeading : AngTwoPi(0);
00538 planner.addObstaclesToShapeSpace(VRmixin::worldShS);
00539 } else if ( req.displayObstacles || result.code != GenericRRTBase::SUCCESS ) {
00540
00541 VRmixin::robotObstaclesPt = VRmixin::theAgent->getCentroid();
00542 VRmixin::robotObstaclesOri = VRmixin::theAgent->getOrientation();
00543 planner.addObstaclesToShapeSpace(VRmixin::worldShS);
00544 }
00545 }
00546
00547 if ( result.code != GenericRRTBase::SUCCESS ) {
00548 switch ( result.code ) {
00549 case GenericRRTBase::START_COLLIDES:
00550 std::cout << "Navigation path planning failed: start state " << result.movingObstacle->toString()
00551 << " is in collision with " << result.collidingObstacle->toString() << ".\n";
00552 break;
00553 case GenericRRTBase::END_COLLIDES:
00554 std::cout << "Navigation path planning failed: end state " << result.movingObstacle->toString()
00555 << " is in collision with " << result.collidingObstacle->toString() << ".\n";
00556 break;
00557 case GenericRRTBase::MAX_ITER:
00558 std::cout << "Navigation path planning failed: max iterations " << req.maxRRTIterations << " exceeded.\n";
00559 break;
00560 default: break;
00561 }
00562 postStateSignal<GenericRRTBase::PlanPathResultCode>(result.code);
00563 return;
00564 }
00565
00566
00567 if ( req.pathEditor )
00568 (*req.pathEditor)(pathResult, req);
00569 plan.path = *pathResult;
00570 delete pathResult;
00571
00572
00573 if ( verbosity & PVshowPath )
00574 showPath(plan.path);
00575
00576 if ( req.displayPath ) {
00577 NEW_SHAPE(plannedPath, GraphicsData, new GraphicsData(VRmixin::worldShS));
00578 ShapeSpacePlannerXYTheta::plotPath(plan.path, plannedPath, rgb(0,0,255));
00579 }
00580
00581
00582 if ( req.executePath )
00583 postStateCompletion();
00584 else
00585 postStateFailure();
00586 }
00587
00588 void Pilot::PlanPath::showPath (const vector<RRTNodeXYTheta::NodeValue_t> &path) {
00589 if ( path.empty() )
00590 std::cout << "[Empty navigation path]" << std::endl;
00591 else
00592 for ( size_t i = 0; i < path.size(); i++ ) {
00593 Point pt(path[i].x, path[i].y, 0, allocentric);
00594 cout << "path[" << i << "] = ";
00595 if ( i == 0 )
00596 std::cout << "start at ";
00597 else
00598 std::cout << "turn " << float(path[i].turn)*180/M_PI << " deg., then ";
00599 std::cout << pt << " hdg " << float(AngTwoPi(path[i].theta)) * 180/M_PI << " deg." << std::endl;
00600 }
00601 }
00602
00603 void Pilot::ConstructNavPlan::doAnalysis(NavigationPlan &plan, Point initPoint,
00604 AngTwoPi initHead, PilotRequest &req) {
00605 Point currentPosition = initPoint;
00606 plan.steps.clear();
00607
00608 for (unsigned int i = 1; i<(plan.path.size()); i++) {
00609
00610
00611 Point delta = Point(plan.path[i].x - plan.path[i-1].x,
00612 plan.path[i].y - plan.path[i-1].y,
00613 0, allocentric);
00614 const float distanceBetween = delta.xyNorm();
00615 const AngSignTwoPi turn = plan.path[i].turn;
00616
00617
00618
00619
00620
00621
00622
00623 #ifdef TGT_HAS_HEAD
00624 if ( fabs(turn) > M_PI / 6 )
00625 if ( req.landmarks.size() > 0)
00626 plan.addNavigationStep(localizeStep, plan.path[i], req.landmarks);
00627 #endif
00628
00629
00630
00631 float maxDistanceBetween = 500;
00632
00633
00634
00635 int numberOfLocalizations = (int)floor(distanceBetween / maxDistanceBetween);
00636 Point deltaStep = delta.unitVector() * maxDistanceBetween;
00637 Point currentPoint = Point(plan.path[i-1].x, plan.path[i-1].y, 0, allocentric);
00638 for ( int j=0; j < numberOfLocalizations; j++ ) {
00639 currentPoint += deltaStep;
00640 plan.addNavigationStep(travelStep, currentPoint, plan.path[i].theta, 0, req.landmarks);
00641 if ( req.landmarks.size() > 0)
00642 plan.addNavigationStep(localizeStep, currentPoint, plan.path[i].theta, 0, req.landmarks);
00643 }
00644 plan.addNavigationStep(travelStep, plan.path[i], req.landmarks);
00645 }
00646 AngTwoPi finalHeading = std::isnan((float)req.targetHeading) ? plan.path.back().theta : req.targetHeading;
00647 plan.addNavigationStep(headingStep, Point(), finalHeading, 0, req.landmarks);
00648 plan.currentStep = plan.steps.begin();
00649
00650 if ( req.planEditor )
00651 (*req.planEditor)(plan, req);
00652 postStateCompletion();
00653 }
00654
00655 void Pilot::ExecutePlan::ExecuteStep::doExecute(NavigationPlan &plan,
00656 DisplacementInstruction &nextDisplacementInstruction,
00657 const bool pushType) {
00658
00659
00660 DualCoding::Point position = VRmixin::theAgent->getCentroid();
00661
00662 if (plan.steps.size() == 0) {
00663 std::cout << "Warning: empty path in Pilot::ExecutePlan::doStart" << std::endl;
00664 postStateCompletion();
00665 return;
00666 }
00667
00668 nextDisplacementInstruction.walkBackward = plan.walkBackward;
00669 switch (plan.currentStep->type) {
00670
00671 case localizeStep:
00672 if (!pushType)
00673 postStateSignal<NavigationStepType_t>(localizeStep);
00674 else
00675 #ifdef TGT_HAS_HEAD
00676 postStateSignal<NavigationStepType_t>(localizeStep);
00677 #else
00678 postStateSuccess();
00679 #endif
00680 break;
00681
00682 case travelStep: {
00683 position = VRmixin::theAgent->getCentroid();
00684 fmat::Column<3> pos = position.getCoords();
00685 fmat::Column<3> next = plan.currentStep->waypoint.getCoords();
00686 fmat::Column<2> disp = fmat::SubVector<2>(next) - fmat::SubVector<2>(pos);
00687 AngSignPi course = atan2(disp[1], disp[0]);
00688 if ( verbosity & PVnavStep )
00689 cout << ">>> Travel: from " << pos
00690 << " hdg " << float(AngSignPi(VRmixin::theAgent->getOrientation()))*180/M_PI
00691 << " deg., course " << float(course)*180/M_PI <<" to " << next;
00692 if (position.xyDistanceFrom(plan.currentStep->waypoint) < allowableDistanceError) {
00693 if ( verbosity & PVnavStep )
00694 cout << ". Close enough!" << endl;
00695 postStateSuccess();
00696 } else {
00697 AngSignPi angle = course - VRmixin::theAgent->getOrientation();
00698 if ( nextDisplacementInstruction.walkBackward ) {
00699 angle += M_PI;
00700 cout << "nextDisplacementInstruction.walkBackward is true" << endl;
00701 }
00702 if (fabs(angle) < allowableAngularError) {
00703 nextDisplacementInstruction.nextPoint = disp;
00704 if ( verbosity & PVnavStep )
00705 cout << ", disp=" << disp << endl;
00706 postStateSignal<NavigationStepType_t>(travelStep);
00707 }
00708 else {
00709 if ( verbosity & PVnavStep )
00710 cout << "... deferred" << endl << ">>> Turn before travel: "
00711 << float(angle)*180/M_PI << " deg" << endl;
00712 nextDisplacementInstruction.angleToTurn = angle;
00713 postStateSignal<NavigationStepType_t>(preTravelStep);
00714 }
00715 }
00716 break;
00717 }
00718
00719 case turnStep: {
00720 position = VRmixin::theAgent->getCentroid();
00721 fmat::Column<3> pos = position.getCoords();
00722 fmat::Column<3> next = plan.currentStep->waypoint.getCoords();
00723 fmat::Column<2> disp = fmat::SubVector<2>(next) - fmat::SubVector<2>(pos);
00724 AngSignPi directTurn = AngSignPi(atan2(disp[1], disp[0]) - VRmixin::theAgent->getOrientation());
00725 if ( fabs(AngSignPi(directTurn - plan.currentStep->turn)) > M_PI/1.8 )
00726 directTurn += M_PI;
00727 AngSignTwoPi actualTurn = float(directTurn);
00728
00729
00730
00731
00732
00733
00734
00735
00736 if ( fabs(plan.currentStep->turn) > M_PI/2 ) {
00737 if ( directTurn > 0 && plan.currentStep->turn < 0 )
00738 actualTurn -= 2*M_PI;
00739 else if ( directTurn < 0 && plan.currentStep->turn > 0 )
00740 actualTurn += 2*M_PI;
00741 }
00742
00743 if (fabs(actualTurn) < allowableAngularError) {
00744 if ( verbosity & PVnavStep )
00745 cout << ">>> Turn: " << float(actualTurn)*180/M_PI << " deg is smaller than minimum "
00746 << float(allowableAngularError)*180/M_PI << " deg (skipped)" << endl;
00747 postStateSuccess();
00748 } else {
00749 if ( verbosity & PVnavStep )
00750 cout << ">>> Turn: " << float(actualTurn)*180/M_PI << " deg" << endl;
00751 nextDisplacementInstruction.angleToTurn = actualTurn;
00752 postStateSignal<NavigationStepType_t>(turnStep);
00753 }
00754 break;
00755 }
00756
00757 case headingStep: {
00758 AngSignPi angle = float(plan.currentStep->orientation - VRmixin::theAgent->getOrientation());
00759 if (fabs(angle) < allowableAngularError) {
00760 if ( verbosity & PVnavStep )
00761 cout << ">>> Turn: " << float(angle)*180/M_PI << " deg is smaller than minimum "
00762 << float(allowableAngularError)*180/M_PI << " deg (skipped)" << endl;
00763 postStateSuccess();
00764 } else {
00765 if ( verbosity & PVnavStep )
00766 cout << ">>> Turn: " << float(angle)*180/M_PI
00767 << " deg to heading " << float(plan.currentStep->orientation)*(180/M_PI) << endl;
00768 nextDisplacementInstruction.angleToTurn = angle;
00769 postStateSignal<NavigationStepType_t>(headingStep);
00770 }
00771 break;
00772 }
00773
00774 default:
00775 cout << "Incorrect step type " << plan.currentStep->type << "in ExecuteStep" << endl;
00776 }
00777 }
00778
00779 void Pilot::ExecutePlan::AdjustHeading::doAdjust(NavigationPlan &plan) {
00780 cout << "AdjustHeading: navplan = " << plan.toString() << endl;
00781 DualCoding::Point position = VRmixin::theAgent->getCentroid();
00782 fmat::Column<3> pos = position.getCoords();
00783
00784 fmat::Column<3> cur, next;
00785 cur = plan.currentStep->waypoint.getCoords();
00786 if (adjustmentType == collisionAdjust) {
00787 next = plan.currentStep->waypoint.getCoords();
00788 cout << "*************** ADJUST TURN COLLISION ***********************************" << endl;
00789 } else {
00790 plan.currentStep++;
00791 next = plan.currentStep->waypoint.getCoords();
00792 plan.currentStep--;
00793 }
00794
00795
00796
00797 fmat::Column<2> disp = fmat::SubVector<2>(next) - fmat::SubVector<2>(pos);
00798 AngTwoPi newHeading = atan2(disp[1], disp[0]);
00799 AngSignPi turnAngle = float(newHeading - VRmixin::theAgent->getOrientation());
00800
00801 std::cout << "AdjustHeading: pos = " << pos << " curWP = " << cur << " nextWP = " << next << std::endl;
00802 std::cout << "AdjustHeading: disp=" << disp << " new heading " << newHeading
00803 << " (" << float(newHeading)*180/M_PI << " deg.); turn by "
00804 << float(turnAngle)*180/M_PI << " deg." << std::endl;
00805 if ( plan.currentStep != plan.steps.begin() && abs(turnAngle) > 45.0*(M_PI/180.0) ) {
00806 std::cout << "AdjustHeading: overshot target; won't try to correct heading now." << std::endl;
00807 postStateCompletion();
00808 return;
00809 }
00810 if ( (disp.norm() < 50.0 && abs(turnAngle) > 5.0*(M_PI/180.)) ||
00811 abs(turnAngle) < 5.0*(M_PI/180.) ) {
00812 std::cout << "AdjustHeading: punting insignificant turn." << std::endl;
00813 postStateCompletion();
00814 return;
00815 }
00816 PilotRequest &curReq = *VRmixin::pilot->curReq;
00817 #if defined(TGT_IS_CREATE) || defined(TGT_IS_CREATE2)
00818 float va = (curReq.turnSpeed > 0) ? curReq.turnSpeed : 0.25f;
00819 #else
00820
00821 float va = (curReq.turnSpeed > 0) ? curReq.turnSpeed : 0.1f;
00822 #endif
00823 getMC()->setTargetDisplacement(0,0,turnAngle,0,0,va);
00824 motman->setPriority(VRmixin::pilot->getWalk_id(),MotionManager::kStdPriority);
00825 }
00826
00827
00828
00829
00830
00831 const float Pilot::LocalizationUtility::Localize::minConfidentWeight = -30;
00832
00833 #ifdef TGT_HAS_HEAD
00834 void Pilot::LocalizationUtility::ChooseGazePoints::setupGazePoints(std::deque<Point> &gazePoints) {
00835 std::vector<ShapeRoot> visibleLandmarks =
00836 calculateVisibleLandmarks(VRmixin::theAgent->getCentroid(), VRmixin::theAgent->getOrientation(),
00837 M_PI*(2.0/3.0),
00838 VRmixin::pilot->curReq->landmarks);
00839 gazePoints = std::deque<Point>();
00840 for ( unsigned int i = 0; i < visibleLandmarks.size(); i++ ) {
00841
00842 Point allovec = visibleLandmarks[i]->getCentroid() - VRmixin::theAgent->getCentroid();
00843 Point egovec = Point(fmat::rotationZ(- VRmixin::theAgent->getOrientation()) * allovec.getCoords());
00844 egovec.setRefFrameType(egocentric);
00845 gazePoints.push_back(egovec);
00846 }
00847 std::cout << "Pilot wants to localize: " << gazePoints.size() << " gaze points." << std::endl;
00848 }
00849
00850 #else // robot has no head, so plan on turning the body
00851 void Pilot::LocalizationUtility::ChooseGazePoints::setupGazeHeadings
00852 (const AngTwoPi initialHeading, std::deque<AngTwoPi> &gazeHeadings, const AngTwoPi maxTurn) {
00853 const AngTwoPi robotHeading = VRmixin::theAgent->getOrientation();
00854 std::vector<ShapeRoot> visibleLandmarks =
00855 calculateVisibleLandmarks(VRmixin::theAgent->getCentroid(), robotHeading,
00856 maxTurn,
00857 VRmixin::pilot->curReq->landmarks);
00858 gazeHeadings = std::deque<AngTwoPi>();
00859 for ( unsigned int i = 0; i < visibleLandmarks.size(); i++ ) {
00860 Point allovec = visibleLandmarks[i]->getCentroid() - VRmixin::theAgent->getCentroid();
00861 gazeHeadings.push_back(AngTwoPi(allovec.atanYX()));
00862 }
00863
00864
00865 std::sort(gazeHeadings.begin(), gazeHeadings.end(), BearingLessThan(robotHeading));
00866
00867 if ( gazeHeadings.size() > 1 &&
00868 abs(AngSignPi(gazeHeadings.front()-robotHeading)) > abs(AngSignPi(gazeHeadings.back()-robotHeading)) )
00869 reverse(gazeHeadings.begin(), gazeHeadings.end());
00870 }
00871
00872 void Pilot::LocalizationUtility::PrepareForNextGazePoint::prepareForNext(std::deque<AngTwoPi> &gazeHeadings, const AngTwoPi maxTurn) {
00873 if ( gazeHeadings.empty() ) {
00874 postStateFailure();
00875 return;
00876 }
00877 const AngTwoPi curHeading = VRmixin::theAgent->getOrientation();
00878 const AngTwoPi newHeading = gazeHeadings.front();
00879 gazeHeadings.pop_front();
00880 const AngSignPi turnAmount = AngSignPi(newHeading - curHeading);
00881
00882
00883 if (fabs(turnAmount) > maxTurn) {
00884 postStateSuccess();
00885 return;
00886 }
00887 MMAccessor<WalkMC> walk_acc(getMC());
00888 float va = VRmixin::pilot->curReq->turnSpeed;
00889 if ( va == 0 )
00890 va = 1.0f;
00891 walk_acc->setTargetDisplacement(0, 0, turnAmount, 0, 0, va);
00892 motman->setPriority(VRmixin::pilot->getWalk_id(),MotionManager::kStdPriority);
00893 }
00894
00895 #endif // TGT_HAS_HEAD
00896
00897 void Pilot::LocalizationUtility::Localize::doStart() {
00898 VRmixin::particleFilter->updateSensors(VRmixin::particleFilter->getSensorModel(),false,true);
00899 const ShapeBasedParticleFilter::particle_type &estimate = VRmixin::particleFilter->getEstimate();
00900 if ( estimate.weight < minConfidentWeight ) {
00901 std::cout << " Particle filter bestWeight=" << estimate.weight
00902 << " < minConfidentWeight=" << minConfidentWeight << ": resample." << std::endl;
00903 VRmixin::particleFilter->updateSensors(VRmixin::particleFilter->getSensorModel(),false,true);
00904 }
00905 if ( estimate.weight < minConfidentWeight ) {
00906 std::cout << " Particle filter bestWeight=" << estimate.weight
00907 << " < minConfidentWeight=" << minConfidentWeight << ": resample once more." << std::endl;
00908 VRmixin::particleFilter->updateSensors(VRmixin::particleFilter->getSensorModel(),false,true);
00909 }
00910 VRmixin::mapBuilder->setAgent(Point(estimate.x,estimate.y,0,allocentric), estimate.theta, true);
00911 AngTwoPi heading = VRmixin::theAgent->getOrientation();
00912 cout << "Agent now at " << VRmixin::theAgent->getCentroid() << " hdg " << heading
00913 << " (= " << float(heading)*180/M_PI << " deg.)"
00914 << " std. dev. " << sqrt(((ShapeBasedParticleFilter*)VRmixin::particleFilter)->getVariance().x) << " mm, "
00915 << float(((ShapeBasedParticleFilter*)VRmixin::particleFilter)->getVariance().theta) * 180 / M_PI << " deg."
00916 << " wtvar " << ((ShapeBasedParticleFilter*)VRmixin::particleFilter)->getVariance().y
00917 << " bestWeight=" << estimate.weight
00918 << endl;
00919 #if defined(TGT_IS_CREATE) || defined(TGT_IS_CREATE2)
00920
00921 #endif
00922 if ( VRmixin::pilot->curReq->displayIndividualParticles > 0 )
00923 VRmixin::particleFilter->displayIndividualParticles(VRmixin::pilot->curReq->displayIndividualParticles);
00924 else if ( VRmixin::pilot->curReq->displayParticles > 0 )
00925 VRmixin::particleFilter->displayParticles(VRmixin::pilot->curReq->displayParticles);
00926 else {
00927 GET_SHAPE(particles, GraphicsData, VRmixin::worldShS);
00928 if ( particles.isValid() )
00929 VRmixin::particleFilter->displayParticles(50);
00930 }
00931 VRmixin::autoRefreshSketchWorld();
00932 }
00933
00934
00935
00936 void Pilot::WalkMachine::WalkMachine_Walker::doStart() {
00937 PilotRequest &preq = *VRmixin::pilot->curReq;
00938 MMAccessor<WalkMC> walk_acc(getMC());
00939 #ifdef TGT_HAS_WHEELS
00940 float vx = (preq.forwardSpeed > 0) ? preq.forwardSpeed : 50.f;
00941 float vy = 0;
00942 float va = (preq.turnSpeed > 0) ? preq.turnSpeed : 0.25f;
00943 #else
00944
00945 float vx = (preq.forwardSpeed > 0) ? preq.forwardSpeed : 15.f;
00946 float vy = preq.strafeSpeed;
00947 float va = (preq.turnSpeed > 0) ? preq.turnSpeed : 0.1f;
00948 #endif
00949 std::cout << "Pilot walking:";
00950 if ( preq.dx != 0 )
00951 std::cout << " dx = " << preq.dx;
00952 if ( preq.dy != 0 )
00953 std::cout << " dy = " << preq.dy;
00954 if ( preq.da != 0 )
00955 std::cout << " da = " << preq.da << " (" << preq.da*180/M_PI << " deg.)";
00956 std::cout << endl;
00957 walk_acc->setTargetDisplacement(preq.dx, preq.dy, preq.da, vx, vy, va);
00958 motman->setPriority(VRmixin::pilot->getWalk_id(),MotionManager::kStdPriority);
00959 }
00960
00961
00962
00963
00964 void Pilot::WaypointWalkMachine::WaypointWalkMachine_WaypointWalker::doStart() {
00965 PilotRequest &req = *VRmixin::pilot->curReq;
00966 MMAccessor<WaypointWalkMC> wp_acc(getMC());
00967 if (req.clearWaypoints)
00968 wp_acc->clearWaypointList();
00969 if ( req.waypointList.size() > 0 )
00970 wp_acc->appendWaypoints(req.waypointList);
00971 else
00972 std::cout << "Warning: Pilot request to waypointWalk with empty waypoint list." << std::endl;
00973 motman->setPriority(VRmixin::VRmixin::pilot->getWaypointwalk_id(),MotionManager::kStdPriority);
00974 }
00975
00976
00977
00978 void Pilot::SetVelocityMachine::SetVelocityMachine_Walker::doStart() {
00979 PilotRequest &preq = *VRmixin::pilot->curReq;
00980 MotionManager::MC_ID wid = VRmixin::pilot->getWalk_id();
00981 MMAccessor<WalkMC>(wid)->setTargetVelocity(preq.forwardSpeed, preq.strafeSpeed, preq.turnSpeed);
00982 motman->setPriority(wid,MotionManager::kStdPriority);
00983 }
00984
00985 void Pilot:: changeVelocity(float vx, float vy, float va) {
00986 if ( VRmixin::pilot->curReq == NULL ) {
00987 std::cout << "Warning: call to Pilot::changeVelocity() when no Pilot request is active: ignored." << std::endl;
00988 return;
00989 }
00990 PilotRequest &preq = *VRmixin::pilot->curReq;
00991 switch ( preq.requestType ) {
00992 case PilotTypes::walk:
00993 case PilotTypes::setVelocity:
00994 {
00995 MotionManager::MC_ID wid = VRmixin::pilot->getWalk_id();
00996 if ( wid == MotionManager::invalid_MC_ID )
00997 cout << "Error: Pilot::changeVelocity() tried to use an invalid MC_ID" << endl;
00998 else
00999 MMAccessor<WalkMC>(wid)->setTargetVelocity(vx, vy, va);
01000 break;
01001 }
01002 default:
01003 {
01004 std::cout << "Warning: Pilot::changeVelocity() called, but the active Pilot request is not 'walk' or 'setVelocity': ignored."
01005 << std::endl;
01006 }
01007 }
01008 }
01009
01010 void Pilot::cancelVelocity() {
01011 if ( VRmixin::pilot->curReq != NULL && VRmixin::pilot->curReq->requestType == PilotTypes::setVelocity ) {
01012 MotionManager::MC_ID wid = VRmixin::pilot->getWalk_id();
01013 erouter->postEvent(EventBase(EventBase::motmanEGID, wid, EventBase::statusETID, 0));
01014 }
01015 else
01016 std::cout << "Warning: call to Pilot::cancelVelocity() when not executing a setVelocity request: ignored." << std::endl;
01017 }
01018
01019
01020
01021 const float Pilot::ExecutePlan::allowableDistanceError = 100.f;
01022 const float Pilot::ExecutePlan::allowableAngularError = 0.2f;
01023
01024 void Pilot::GoToShapeMachine::CheckParameters::doStart() {
01025
01026 PilotRequest &req = *VRmixin::pilot->curReq;
01027 if ( ! req.targetShape.isValid() ) {
01028 cout << "Pilot request goToShape fails: no valid targetShape specified" << endl;
01029 postStateFailure();
01030 return;
01031 }
01032 if ( req.targetShape->isObstacle() ) {
01033 cout << "Warning: Pilot marking targetShape '" << req.targetShape->getName()
01034 << "' (" << req.targetShape->getId() << ") as non-obstacle to permit path planning." << endl;
01035 req.targetShape->setObstacle(false);
01036 }
01037
01038 postStateSuccess();
01039 }
01040
01041
01042 void Pilot::PushObjectMachine::CheckParameters::doStart() {
01043
01044 PilotRequest &req = *VRmixin::pilot->curReq;
01045 if ( ! req.objectShape.isValid() ) {
01046 cout << "Pilot request pushObject fails: no valid objectShape specified" << endl;
01047 postStateFailure();
01048 return;
01049 if ( ! req.targetShape.isValid() ) {
01050 cout << "Pilot request pushObject fails: no valid targetShape specified" << endl;
01051 postStateFailure();
01052 return;
01053 }
01054 if ( req.targetShape->isObstacle() ) {
01055 cout << "Warning: Pilot marking targetShape '" << req.targetShape->getName()
01056 << "' (" << req.targetShape->getId() << ") as non-obstacle to permit path planning." << endl;
01057 req.targetShape->setObstacle(false);
01058 }
01059 }
01060
01061 postStateSuccess();
01062 }
01063
01064
01065
01066 unsigned int Pilot::verbosity = -1U & ~Pilot::PVnavStep;
01067
01068
01069 int Pilot::PushObjectMachine::backupDist = 600;
01070 int Pilot::PushObjectMachine::obstDist = 150;
01071 int Pilot::PushObjectMachine::robotDiam = 150;
01072 int Pilot::PushObjectMachine::objSize = 50;
01073 float Pilot::PushObjectMachine::prePushTurnSpeed = 0.25f;
01074 float Pilot::PushObjectMachine::prePushForwardSpeed = 100.f;
01075 float Pilot::PushObjectMachine::pushTurnSpeed = 0.25f;
01076 float Pilot::PushObjectMachine::pushForwardSpeed = 100.f;
01077 }
01078
01079 #endif