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 "Shared/mathutils.h"
00010
00011 namespace DualCoding {
00012
00013 void Pilot::doStart() {
00014 if (verbosity & PVstart)
00015 cout << "Pilot starting up: walk_id= " << walk_id <<" waypointwalk_id= " << waypointwalk_id << endl;
00016 setAgent(Point(0,0,0,allocentric),0,false,false);
00017 VRmixin::particleFilter->displayParticles(50);
00018 addNode(new RunMotionModel)->start();
00019 addNode(new CollisionChecker)->start();
00020 }
00021
00022 void Pilot::doStop() {
00023 pilotAbort();
00024 if (verbosity & PVstart)
00025 cout << "Pilot is shutting down." << endl;
00026 motman->removeMotion(walk_id);
00027 motman->removeMotion(waypointwalk_id);
00028 waypointwalk_id = MotionManager::invalid_MC_ID;
00029 walk_id = MotionManager::invalid_MC_ID;
00030 delete defaultLandmarkExtractor;
00031 defaultLandmarkExtractor = NULL;
00032
00033
00034
00035
00036
00037
00038
00039 teardown();
00040 }
00041
00042 void Pilot::doEvent() {
00043 if (event->getGeneratorID() == EventBase::timerEGID && event->getSourceID() == 9999)
00044 executeRequest();
00045 else
00046 cout << "Pilot got unexpected event: " << event->getDescription() << endl;
00047 }
00048
00049 void Pilot::unwindForNextRequest() {
00050 erouter->addTimer(this,9999,1,false);
00051 }
00052
00053 void Pilot::setAgent(const Point &loc, AngTwoPi heading, bool quiet, bool updateWaypoint) {
00054 if (updateWaypoint) {
00055 cout << "Updating waypoint walk to " << loc << " hdg=" << heading << endl;
00056 MMAccessor<WaypointWalkMC> wp_acc(waypointwalk_id);
00057 wp_acc->setCurPos(loc.coordX(), loc.coordY(), heading);
00058 }
00059 VRmixin::mapBuilder->setAgent(loc, heading, quiet);
00060
00061
00062
00063 VRmixin::particleFilter->setPosition(loc.coordX(), loc.coordY(), heading);
00064 VRmixin::particleFilter->synchEstimateToAgent();
00065 }
00066
00067 unsigned int Pilot::executeRequest(BehaviorBase* requestingBehavior, const PilotRequest& req) {
00068 requests.push(new PilotRequest(req));
00069 const unsigned int reqID = ++idCounter;
00070 requests.back()->requestID = reqID;
00071 requests.back()->requestingBehavior = requestingBehavior;
00072 if (curReq == NULL)
00073 unwindForNextRequest();
00074 else if (verbosity & PVqueued)
00075 cout << "Pilot request " << requests.back()->requestID << " queued." << endl;
00076 return reqID;
00077 }
00078
00079
00080 void Pilot::executeRequest() {
00081 if (curReq == NULL && !requests.empty()) {
00082 curReq = requests.front();
00083 if (verbosity & PVexecute)
00084 cout << "Pilot executing request " << curReq->requestID
00085 << ": " << PilotTypes::RequestTypeNames[curReq->requestType] << endl;
00086 VRmixin::particleFilter->synchEstimateToAgent();
00087 if ( ! curReq->walkParameters.empty() ) {
00088 MMAccessor<WaypointWalkMC>(VRmixin::pilot->getWaypointwalk_id())->WalkMC::loadFile(curReq->walkParameters.c_str());
00089 MMAccessor<WalkMC>(VRmixin::pilot->getWalk_id())->loadFile(curReq->walkParameters.c_str());
00090 }
00091 dispatch_->start();
00092 }
00093 }
00094
00095 void Pilot::requestComplete(PilotTypes::ErrorType_t errorType) {
00096 if (curReq == NULL) {
00097 cout << "Pilot::requestComplete had NULL curReq !!!!!!!!!!!!!!!!" << endl;
00098 return;
00099 }
00100 const BehaviorBase* requester = curReq->requestingBehavior;
00101 PilotEvent e(EventBase::pilotEGID,
00102 (requester==NULL) ? curReq->requestID : (size_t)requester,
00103 EventBase::statusETID);
00104 e.requestType = curReq->requestType;
00105 e.errorType = errorType;
00106 if (verbosity & PVcomplete)
00107 cout << "Pilot request " << curReq->requestID << " complete: "
00108 << PilotTypes::ErrorTypeNames[errorType] << endl;
00109 requestComplete(e);
00110 }
00111
00112 void Pilot::requestComplete(const PilotEvent &e) {
00113
00114
00115 dispatch_->finish();
00116
00117 delete curReq->landmarkExtractor;
00118 delete curReq->searchObjectExtractor;
00119 delete curReq;
00120 curReq = NULL;
00121 requests.pop();
00122
00123 erouter->postEvent(e);
00124 unwindForNextRequest();
00125 }
00126
00127 void Pilot::setWorldBounds(const Shape<PolygonData> &bounds) {
00128 VRmixin::particleFilter->setWorldBounds(bounds);
00129 }
00130
00131 void Pilot::setDefaultLandmarks(const std::vector<ShapeRoot> &landmarks) {
00132 defaultLandmarks = landmarks;
00133 }
00134
00135 void Pilot::setDefaultLandmarkExtractor(const MapBuilderRequest &mapreq) {
00136 defaultLandmarkExtractor = new MapBuilderRequest(mapreq);
00137 defaultLandmarkExtractor->clearLocal = false;
00138 }
00139
00140 void Pilot::pilotPop() {
00141 if ( curReq != NULL ) {
00142 if ( verbosity & PVpop )
00143 cout << "Pilot popping current request." << endl;
00144 dispatch_->stop();
00145 VRmixin::pilot->requestComplete(PilotTypes::abort);
00146 }
00147 }
00148
00149 void Pilot::pilotAbort() {
00150 if ( curReq != NULL && (verbosity & PVabort) )
00151 cout << "Pilot aborting." << endl;
00152 dispatch_->stop();
00153 curReq = NULL;
00154 while (!requests.empty()) {
00155 delete requests.front();
00156 requests.pop();
00157 }
00158 }
00159
00160 void Pilot::setupLandmarkExtractor() {
00161
00162 if ( curReq->landmarkExitTest == NULL )
00163 curReq->landmarkExitTest = &Pilot::defaultLandmarkExitTest;
00164 if ( curReq->landmarkExtractor != NULL )
00165 return;
00166 else if ( defaultLandmarkExtractor != NULL ) {
00167 curReq->landmarkExtractor = new MapBuilderRequest(*defaultLandmarkExtractor);
00168 return;
00169 }
00170 vector<ShapeRoot> landmarkTemp;
00171 if ( ! curReq->landmarks.empty() )
00172 landmarkTemp = curReq->landmarks;
00173 else if ( ! defaultLandmarks.empty() )
00174 landmarkTemp = defaultLandmarks;
00175 else {
00176
00177 NEW_SHAPEVEC(markers, MarkerData, select_type<MarkerData>(VRmixin::worldShS));
00178 landmarkTemp.insert(landmarkTemp.begin(), markers.begin(), markers.end());
00179 NEW_SHAPEVEC(apriltags, AprilTagData, select_type<AprilTagData>(VRmixin::worldShS));
00180 landmarkTemp.insert(landmarkTemp.begin(), apriltags.begin(), apriltags.end());
00181 curReq->landmarks = landmarkTemp;
00182 }
00183 if ( !landmarkTemp.empty() ) {
00184 curReq->landmarkExtractor = new MapBuilderRequest(MapBuilderRequest::localMap);
00185 curReq->landmarkExtractor->clearVerbosity = -1U;
00186 curReq->landmarkExtractor->setVerbosity = MapBuilder::MBVimportShapes;
00187 if ( ! select_type<AprilTagData>(landmarkTemp).empty() )
00188 curReq->landmarkExtractor->setAprilTagFamily();
00189
00190 for ( vector<ShapeRoot>::const_iterator it = landmarkTemp.begin();
00191 it != landmarkTemp.end(); it++ ) {
00192 if ( (*it)->getType() == markerDataType ) {
00193 const Shape<MarkerData> &m = ShapeRootTypeConst(*it, MarkerData);
00194 curReq->landmarkExtractor->addMarkerType(m->getMarkerType());
00195 curReq->landmarkExtractor->objectColors[markerDataType].insert(ProjectInterface::getColorIndex(m->getColor()));
00196 }
00197 }
00198 }
00199 }
00200
00201 bool Pilot::defaultLandmarkExitTest() {
00202 return ( VRmixin::localShS.allShapes().size() >= 2 );
00203 }
00204
00205 std::vector<ShapeRoot>
00206 Pilot::calculateVisibleLandmarks(const DualCoding::Point ¤tLocation,
00207 AngTwoPi currentOrientation, AngTwoPi maxTurn,
00208 const std::vector<DualCoding::ShapeRoot> &possibleLandmarks) {
00209 std::vector<ShapeRoot> result;
00210 for(unsigned int i = 0; i<possibleLandmarks.size(); i++)
00211 if ( isLandmarkViewable(possibleLandmarks[i], currentLocation, currentOrientation, maxTurn) )
00212 result.push_back(possibleLandmarks[i]);
00213 return result;
00214 }
00215
00216 bool Pilot::isLandmarkViewable(const DualCoding::ShapeRoot &selectedLandmark,
00217 const DualCoding::Point ¤tLocation,
00218 AngTwoPi currentOrientation, AngTwoPi maxTurn) {
00219 AngSignPi bearing = (selectedLandmark->getCentroid() - currentLocation).atanYX();
00220
00221
00222 if ( fabs(bearing) > (CameraHorizFOV/2.0+maxTurn) )
00223 return false;
00224
00225
00226
00227
00228 Shape<PolygonData> boundary;
00229 GET_SHAPE(worldBounds, PolygonData, VRmixin::worldShS);
00230 if ( worldBounds.isValid() )
00231 boundary = worldBounds;
00232 else {
00233 GET_SHAPE(wall, PolygonData, VRmixin::worldShS);
00234 boundary = wall;
00235 }
00236 if ( ! boundary.isValid() )
00237 return true;
00238
00239 LineData lineOfSight(VRmixin::worldShS, currentLocation, selectedLandmark->getCentroid());
00240 if ( boundary->intersectsLine(lineOfSight) )
00241 return false;
00242
00243
00244 return true;
00245 }
00246
00247 void Pilot::CollisionDispatch::doStart() {
00248 switch ( VRmixin::pilot->curReq->collisionAction ) {
00249 case collisionStop:
00250 case collisionReplan:
00251 erouter->addListener(this, EventBase::pilotEGID, (size_t)VRmixin::pilot, EventBase::statusETID);
00252 break;
00253 default:
00254 break;
00255 }
00256 }
00257
00258 void Pilot::CollisionDispatch::doEvent() {
00259
00260
00261 PilotEvent e(*event);
00262 e.setSourceID((size_t)this);
00263 erouter->postEvent(e);
00264 }
00265
00266 void Pilot::TerminateDueToCollision::doStart() {
00267 PilotEvent e(*event);
00268 e.setSourceID((size_t)VRmixin::pilot->curReq->requestingBehavior);
00269 VRmixin::pilot->requestComplete(e);
00270 }
00271
00272
00273
00274 void Pilot::RunMotionModel::doStart() {
00275 erouter->addTimer(this, 1, 250, true);
00276 }
00277
00278 void Pilot::RunMotionModel::doEvent() {
00279 if (event->getGeneratorID() == EventBase::timerEGID) {
00280 VRmixin::particleFilter->updateMotion();
00281 LocalizationParticle estimate = VRmixin::particleFilter->getEstimate();
00282 VRmixin::mapBuilder->setAgent(Point(estimate.x, estimate.y, 0, allocentric), estimate.theta, true);
00283 }
00284 }
00285
00286 void Pilot::CollisionChecker::doStart() {
00287 enableDetection();
00288 }
00289
00290 void Pilot::CollisionChecker::enableDetection() {
00291 #ifdef TGT_IS_CREATE
00292
00293 erouter->addListener(this, EventBase::buttonEGID, BumpLeftButOffset, EventBase::activateETID);
00294 erouter->addListener(this, EventBase::buttonEGID, BumpRightButOffset, EventBase::activateETID);
00295 erouter->addListener(this, EventBase::buttonEGID, OvercurrentLeftWheelOffset, EventBase::activateETID);
00296 erouter->addListener(this, EventBase::buttonEGID, OvercurrentRightWheelOffset, EventBase::activateETID);
00297 erouter->addTimer(this, overcurrentResetTimer, 1500, true);
00298 #else
00299 std::cout << "Warning: Pilot has no collision check method defined for this robot type" << std::endl;
00300 #endif
00301 }
00302
00303 void Pilot::CollisionChecker::disableDetection(unsigned int howlong=-1U) {
00304 #ifdef TGT_IS_CREATE
00305
00306 erouter->removeListener(this, EventBase::buttonEGID);
00307 #endif
00308 erouter->addTimer(this, 1, howlong, false);
00309 }
00310
00311 void Pilot::CollisionChecker::doEvent() {
00312 if ( event->getGeneratorID() == EventBase::timerEGID ) {
00313 if ( event->getSourceID() == collisionEnableTimer )
00314 enableDetection();
00315 #ifdef TGT_IS_CREATE
00316 else if ( event->getSourceID() == overcurrentResetTimer )
00317 overcurrentCounter = 0;
00318 return;
00319 #endif
00320 }
00321
00322 if ( VRmixin::pilot->curReq == NULL ||
00323 VRmixin::pilot->curReq->collisionAction == collisionIgnore )
00324 return;
00325 #ifdef TGT_IS_CREATE
00326 if ( event->getSourceID() == BumpLeftButOffset ||
00327 event->getSourceID() == BumpRightButOffset )
00328 reportCollision();
00329 else
00330 if ( ++overcurrentCounter >= 12 ) {
00331 overcurrentCounter = 0;
00332 reportCollision();
00333 }
00334 #endif
00335 }
00336
00337 void Pilot::CollisionChecker::reportCollision() {
00338 if ( VRmixin::pilot->verbosity & PVcollision )
00339 cout << "Pilot: collision detected!" << endl;
00340 disableDetection(1000);
00341 PilotEvent e(EventBase::pilotEGID, (size_t)VRmixin::pilot, EventBase::statusETID);
00342 e.errorType = collisionDetected;
00343
00344
00345 erouter->postEvent(e);
00346 }
00347
00348
00349
00350
00351 std::string Pilot::NavigationPlan::toString() const {
00352 ostringstream os;
00353 os << "Navigation plan (" << steps.size() << " steps):" << std::endl;
00354 for ( size_t i=0; i<steps.size(); i++ )
00355 os << " " << steps[i].toString() << endl;
00356 return os.str();
00357 }
00358
00359 void Pilot::NavigationPlan::addNavigationStep(NavigationStepType_t type, const DualCoding::Point &waypoint, AngTwoPi orientation) {
00360 NavigationStep step(type, waypoint);
00361 if ( type == localizeStep )
00362 step.visibleLandmarks = calculateVisibleLandmarks(waypoint, orientation, M_PI/2, VRmixin::pilot->curReq->landmarks);
00363 if ( type != localizeStep || !step.visibleLandmarks.empty() )
00364 steps.push_back(step);
00365 }
00366
00367 std::string Pilot::NavigationStep::toString() const {
00368 ostringstream os;
00369 os << "NavigationStep[";
00370 switch (type) {
00371 case localizeStep: os << "localizeStep"; break;
00372 case turnStep: os << "turnStep"; break;
00373 case travelStep: os << "travelStep"; break;
00374 case turnObjStep: os << "turnObjStep"; break;
00375 case acquireObjStep: os << "acquireObjStep"; break;
00376 default:
00377 os << "unknown step type";
00378 }
00379 if ( type == localizeStep ) {
00380 os << ", visible=(";
00381 for (size_t i = 0; i < visibleLandmarks.size(); i++)
00382 os << ( (i>0) ? "," : "") << visibleLandmarks[i]->getName();
00383 os << ")";
00384 } else
00385 os << ", waypoint=" << waypoint;
00386 os << "]";
00387 return os.str();
00388 }
00389
00390 std::ostream& operator<<(std::ostream& os, const Pilot::NavigationStep &step) { return os << step.toString(); }
00391 std::ostream& operator<<(std::ostream& os, const Pilot::NavigationPlan &plan) { return os << plan.toString(); }
00392
00393
00394 void Pilot::PlanPath::doPlan(NavigationPlan &plan, Point initPos, AngTwoPi initHead, PilotRequest req) {
00395 plan.path.clear();
00396 {
00397 GET_SHAPE(plannedPath, GraphicsData, worldShS);
00398 plannedPath.deleteShape();
00399 GET_SHAPE(plannerTrees, GraphicsData, worldShS);
00400 plannerTrees.deleteShape();
00401 }
00402 GET_SHAPE(worldBounds, PolygonData, worldShS);
00403
00404 const ShapeRoot &target = req.targetShape;
00405 Point targetLoc = target->getCentroid();
00406 if ( targetLoc.getRefFrameType() == egocentric ) {
00407 targetLoc.applyTransform(VRmixin::mapBuilder->localToWorldMatrix);
00408 targetLoc.setRefFrameType(allocentric);
00409 }
00410
00411 const bool planForHeading = ! std::isnan((float)req.targetHeading);
00412 GenericRRTBase::PlannerResult<2> result;
00413 void *pathResult;
00414 size_t pathResultSize;
00415 if ( !planForHeading ) {
00416 std::cout << "Planning path from " << initPos << " to point: " << targetLoc << std::endl;
00417 float const robotRadius = 6 * 25.4f * 1.25;
00418 ShapeSpacePlannerXY planner(worldShS, worldBounds, req.obstacleInflation, robotRadius);
00419 if ( req.displayObstacles )
00420 planner.addObstaclesToShapeSpace(worldShS);
00421 pathResult = new std::vector<ShapeSpacePlannerXY::NodeValue_t>;
00422 std::vector<ShapeSpacePlannerXY::NodeType_t> *treeStartResult =
00423 req.displayTree ? new std::vector<ShapeSpacePlannerXY::NodeType_t> : NULL;
00424 std::vector<ShapeSpacePlannerXY::NodeType_t> *treeEndResult =
00425 req.displayTree ? new std::vector<ShapeSpacePlannerXY::NodeType_t> : NULL;
00426 result = planner.planPath(initPos, targetLoc, req.maxRRTIterations,
00427 (std::vector<ShapeSpacePlannerXY::NodeValue_t>*)pathResult, treeStartResult, treeEndResult);
00428 pathResultSize = ((std::vector<ShapeSpacePlannerXY::NodeValue_t>*)pathResult)->size();
00429 if ( req.displayTree ) {
00430 NEW_SHAPE(plannerTrees, GraphicsData, new GraphicsData(worldShS));
00431 planner.plotTree(*treeStartResult, plannerTrees, rgb(0,0,0));
00432 planner.plotTree(*treeEndResult, plannerTrees, rgb(0,192,0));
00433 delete treeStartResult;
00434 delete treeEndResult;
00435 }
00436 } else {
00437
00438
00439 std::cout << "Planning path from " << initPos << " to point " << targetLoc
00440 << " heading " << float(req.targetHeading)/M_PI*180 << " deg." << std::endl;
00441 float gateDistance = 6 * 25.4;
00442 Point gateLoc = targetLoc - Point(cos(req.targetHeading),sin(req.targetHeading),0,allocentric) * gateDistance;
00443 ShapeSpacePlannerXYTheta planner(worldShS, worldBounds, req.obstacleInflation);
00444 if ( req.displayObstacles )
00445 planner.addObstaclesToShapeSpace(worldShS);
00446 pathResult = new std::vector<ShapeSpacePlannerXYTheta::NodeValue_t>;
00447 std::vector<ShapeSpacePlannerXYTheta::NodeType_t> *treeStartResult = req.displayTree ? new std::vector<ShapeSpacePlannerXYTheta::NodeType_t> : NULL;
00448 std::vector<ShapeSpacePlannerXYTheta::NodeType_t> *treeEndResult = req.displayTree ? new std::vector<ShapeSpacePlannerXYTheta::NodeType_t> : NULL;
00449 result = planner.planPath(initPos, gateLoc, initHead, req.targetHeading, req.maxRRTIterations,
00450 (std::vector<ShapeSpacePlannerXYTheta::NodeValue_t>*)pathResult,
00451 treeStartResult, treeEndResult);
00452 ((std::vector<ShapeSpacePlannerXYTheta::NodeValue_t>*)pathResult)->
00453 push_back(ShapeSpacePlannerXYTheta::NodeValue_t(std::pair<float,float>(targetLoc.coordX(),targetLoc.coordY()),req.targetHeading));
00454 pathResultSize = ((std::vector<ShapeSpacePlannerXYTheta::NodeValue_t>*)pathResult)->size();
00455 if ( req.displayTree ) {
00456 NEW_SHAPE(plannerTrees, GraphicsData, new GraphicsData(worldShS));
00457 planner.plotTree(*treeStartResult, plannerTrees, rgb(0,0,0));
00458 planner.plotTree(*treeEndResult, plannerTrees, rgb(0,192,0));
00459 delete treeStartResult;
00460 delete treeEndResult;
00461 }
00462 }
00463
00464 if ( result.code != GenericRRTBase::SUCCESS ) {
00465 switch ( result.code ) {
00466 case GenericRRTBase::START_COLLIDES:
00467 std::cout << "Navigation path planning failed: start state " << result.movingObstacle->toString()
00468 << " is in collision with " << result.collidingObstacle->toString() << ".\n";
00469 break;
00470 case GenericRRTBase::END_COLLIDES:
00471 std::cout << "Navigation path planning failed: end state " << result.movingObstacle->toString()
00472 << " is in collision with " << result.collidingObstacle->toString() << ".\n";
00473 break;
00474 case GenericRRTBase::MAX_ITER:
00475 std::cout << "Navigation path planning failed: max iterations " << req.maxRRTIterations << " exceeded.\n";
00476 break;
00477 default: break;
00478 }
00479 postStateSignal<GenericRRTBase::PlanPathResultCode>(result.code);
00480 return;
00481 }
00482
00483
00484 for ( size_t i = 0; i < pathResultSize; i++ ) {
00485 const std::pair<float,float> &pt = ( !planForHeading )
00486 ? (*(std::vector<ShapeSpacePlannerXY::NodeValue_t>*)pathResult)[i]
00487 : (*(std::vector<ShapeSpacePlannerXYTheta::NodeValue_t>*)pathResult)[i].first;
00488 plan.path.push_back(Point(pt.first, pt.second, 0, allocentric));
00489 if ( verbosity & PVshowPath ) {
00490 cout << "path[" << i << "] = " << plan.path[i];
00491 if ( planForHeading )
00492 cout << " hdg " << float(AngSignPi((*(std::vector<ShapeSpacePlannerXYTheta::NodeValue_t>*)pathResult)[i].second)) * 180/M_PI
00493 << " deg.";
00494 cout << endl;
00495 }
00496 }
00497
00498
00499 if ( req.displayPath ) {
00500 NEW_SHAPE(plannedPath, GraphicsData, new GraphicsData(worldShS));
00501 if ( !planForHeading )
00502 ShapeSpacePlannerXY::plotPath((*(std::vector<ShapeSpacePlannerXY::NodeValue_t>*)pathResult),
00503 plannedPath, rgb(0,0,255));
00504 else
00505 ShapeSpacePlannerXYTheta::plotPath((*(std::vector<ShapeSpacePlannerXYTheta::NodeValue_t>*)pathResult),
00506 plannedPath, rgb(0,0,255));
00507 }
00508
00509
00510 if ( req.executePath )
00511 postStateCompletion();
00512 else
00513 postStateFailure();
00514 }
00515
00516 void Pilot::ConstructNavPlan::doAnalysis(NavigationPlan &plan, Point initPos, AngTwoPi initHead, PilotRequest req) {
00517
00518 AngTwoPi orientation = initHead;
00519 Point currentPosition = initPos;
00520 plan.steps.clear();
00521
00522 for (unsigned int i = 1; i<(plan.path.size()); i++) {
00523
00524
00525 const Point delta = (plan.path[i] - plan.path[i-1]);
00526 const float distanceBetween = delta.xyNorm();
00527 const AngSignPi headingChange = AngSignPi(delta.atanYX() - orientation);
00528 orientation += headingChange;
00529
00530
00531 if( fabs(headingChange) > M_PI/18 )
00532 plan.addNavigationStep(turnStep, plan.path[i], orientation);
00533
00534 #ifdef TGT_HAS_HEAD
00535 if ( fabs(headingChange) > M_PI / 6 )
00536 if ( req.landmarks.size() > 0)
00537 plan.addNavigationStep(localizeStep, plan.path[i], orientation);
00538 #endif
00539
00540
00541
00542 float maxDistanceBetween = 500;
00543 if ( req.landmarks.empty() ) {
00544 maxDistanceBetween = 1e10f;
00545 }
00546 int numberOfLocalizations = (int)floor(distanceBetween / maxDistanceBetween);
00547
00548 Point deltaStep = delta.unitVector() * maxDistanceBetween;
00549 Point currentPoint = plan.path[i-1];
00550 for ( int j=0; j < numberOfLocalizations; j++ ) {
00551 currentPoint += deltaStep;
00552 plan.addNavigationStep(travelStep, currentPoint, orientation);
00553 plan.addNavigationStep(localizeStep, currentPoint, orientation);
00554 }
00555 plan.addNavigationStep(travelStep, plan.path[i], orientation);
00556 }
00557 plan.currentStep = plan.steps.begin();
00558 postStateCompletion();
00559 }
00560
00561 void Pilot::ExecutePlan::ExecuteStep::doExecute(NavigationPlan &plan,
00562 DisplacementInstruction &nextDisplacementInstruction,
00563 const bool pushType) {
00564
00565 DualCoding::Point position = theAgent->getCentroid();
00566
00567 if (plan.steps.size() == 0) {
00568 std::cout << "Warning: empty path in Pilot::ExecutePlan::doStart" << std::endl;
00569 postStateCompletion();
00570 return;
00571 }
00572
00573 switch (plan.currentStep->type) {
00574
00575 case localizeStep:
00576 if (!pushType)
00577 postStateSignal<NavigationStepType_t>(localizeStep);
00578 else
00579 postStateSuccess();
00580 break;
00581
00582 case travelStep: {
00583 position = theAgent->getCentroid();
00584 fmat::Column<3> pos = position.getCoords();
00585 fmat::Column<3> next = plan.currentStep->waypoint.getCoords();
00586 if ( verbosity & PVnavStep )
00587 cout << ">>> Travel: at " << pos << " hdg " << float(AngSignPi(theAgent->getOrientation()))*180/M_PI
00588 << " deg., next pos. is " << next;
00589 if (position.xyDistanceFrom(plan.currentStep->waypoint) < allowableDistanceError) {
00590 if ( verbosity & PVnavStep )
00591 cout << ". Close enough!" << endl;
00592 postStateSuccess();
00593 }
00594 else {
00595 fmat::Column<2> disp = fmat::SubVector<2>(next) - fmat::SubVector<2>(pos);
00596 nextDisplacementInstruction.nextPoint = disp;
00597 if ( verbosity & PVnavStep )
00598 cout << ", disp=" << disp << endl;
00599
00600 std::vector<NavigationStep>::const_iterator m, n;
00601 m = plan.steps.begin();
00602 n = m;
00603 n++;
00604 if (((m == plan.currentStep) || (n == plan.currentStep)) && pushType)
00605 postStateSignal<NavigationStepType_t>(acquireObjStep);
00606 else
00607 postStateSignal<NavigationStepType_t>(travelStep);
00608 }
00609 break;
00610 }
00611
00612 case turnStep: {
00613 position = theAgent->getCentroid();
00614 fmat::Column<3> pos = position.getCoords();
00615 fmat::Column<3> next = plan.currentStep->waypoint.getCoords();
00616 fmat::Column<2> disp = fmat::SubVector<2>(next) - fmat::SubVector<2>(pos);
00617 AngSignPi angle = (atan2(disp[1], disp[0]) - theAgent->getOrientation());
00618 if (fabs(angle) < allowableAngularError) {
00619 if ( verbosity & PVnavStep )
00620 cout << ">>> Turn: " << float(angle)*180/M_PI << " deg is smaller than minimum "
00621 << float(allowableAngularError)*180/M_PI << " deg (skipped)" << endl;
00622 postStateSuccess();
00623 } else {
00624 if ( verbosity & PVnavStep )
00625 cout << ">>> Turn: " << float(angle)*180/M_PI << " deg" << endl;
00626 nextDisplacementInstruction.angleToTurn = angle;
00627 if (pushType && (plan.currentStep != plan.steps.begin()))
00628 postStateSignal<NavigationStepType_t>(turnObjStep);
00629 else
00630 postStateSignal<NavigationStepType_t>(turnStep);
00631 }
00632 break;
00633 }
00634
00635 default:
00636 cout << "Incorrect step type " << plan.currentStep->type << "in ExecuteStep" << endl;
00637 }
00638 }
00639
00640
00641
00642 const float Pilot::LocalizationUtility::Localize::minConfidentWeight = -30;
00643
00644 #ifdef TGT_HAS_HEAD
00645 void Pilot::LocalizationUtility::ChooseGazePoints::setupGazePoints(std::deque<Point> &gazePoints) {
00646 std::vector<ShapeRoot> visibleLandmarks =
00647 calculateVisibleLandmarks(theAgent->getCentroid(), theAgent->getOrientation(),
00648 M_PI/2,
00649 VRmixin::pilot->curReq->landmarks);
00650 gazePoints = std::deque<Point>();
00651 for ( unsigned int i = 0; i < visibleLandmarks.size(); i++ ) {
00652
00653 Point allovec = visibleLandmarks[i]->getCentroid() - theAgent->getCentroid();
00654 Point egovec = Point(fmat::rotationZ(- theAgent->getOrientation()) * allovec.getCoords());
00655 egovec.setRefFrameType(egocentric);
00656 gazePoints.push_back(egovec);
00657 }
00658 }
00659
00660 #else // robot has no head, so plan on turning the body
00661 void Pilot::LocalizationUtility::ChooseGazePoints::setupGazeHeadings
00662 (const AngTwoPi initialHeading, std::deque<AngTwoPi> &gazeHeadings, const AngTwoPi maxTurn) {
00663 const AngTwoPi robotHeading = theAgent->getOrientation();
00664 std::vector<ShapeRoot> visibleLandmarks =
00665 calculateVisibleLandmarks(theAgent->getCentroid(), robotHeading,
00666 maxTurn,
00667 VRmixin::pilot->curReq->landmarks);
00668 gazeHeadings = std::deque<AngTwoPi>();
00669 for ( unsigned int i = 0; i < visibleLandmarks.size(); i++ ) {
00670 Point allovec = visibleLandmarks[i]->getCentroid() - theAgent->getCentroid();
00671 gazeHeadings.push_back(AngTwoPi(allovec.atanYX()));
00672 }
00673
00674
00675 std::sort(gazeHeadings.begin(), gazeHeadings.end(), BearingLessThan(robotHeading));
00676
00677 if ( gazeHeadings.size() > 1 &&
00678 abs(AngSignPi(gazeHeadings.front()-robotHeading)) > abs(AngSignPi(gazeHeadings.back()-robotHeading)) )
00679 reverse(gazeHeadings.begin(), gazeHeadings.end());
00680 }
00681
00682 void Pilot::LocalizationUtility::PrepareForNextGazePoint::prepareForNext(std::deque<AngTwoPi> &gazeHeadings, const AngTwoPi maxTurn) {
00683 if ( gazeHeadings.empty() ) {
00684 postStateFailure();
00685 return;
00686 }
00687 const AngTwoPi curHeading = VRmixin::theAgent->getOrientation();
00688 const AngTwoPi newHeading = gazeHeadings.front();
00689 gazeHeadings.pop_front();
00690 const AngSignPi turnAmount = AngSignPi(newHeading - curHeading);
00691
00692
00693 if (fabs(turnAmount) > maxTurn) {
00694 postStateSuccess();
00695 return;
00696 }
00697 MMAccessor<WaypointWalkMC> wp_acc(getMC());
00698 wp_acc->getWaypointList().clear();
00699 #ifdef TGT_IS_CREATE
00700 float const va = 1.0f;
00701 wp_acc->addEgocentricWaypoint(0, 0, turnAmount, true, 0, va);
00702 #else
00703
00704 float const va = 1.0f;
00705 wp_acc->addEgocentricWaypoint(0, 0, turnAmount, true, 0, va);
00706 #endif // TGT_IS_CREATE
00707 motman->setPriority(VRmixin::pilot->getWaypointwalk_id(),MotionManager::kStdPriority);
00708 }
00709
00710 #endif // TGT_HAS_HEAD
00711
00712 void Pilot::LocalizationUtility::Localize::doStart() {
00713 VRmixin::particleFilter->updateSensors(particleFilter->getSensorModel(),false,true);
00714 const ShapeBasedParticleFilter::particle_type &estimate = VRmixin::particleFilter->getEstimate();
00715 if ( estimate.weight < minConfidentWeight ) {
00716 std::cout << " Particle filter bestWeight=" << estimate.weight
00717 << " < minConfidentWeight=" << minConfidentWeight << ": resample." << std::endl;
00718 VRmixin::particleFilter->updateSensors(particleFilter->getSensorModel(),false,true);
00719 }
00720 if ( estimate.weight < minConfidentWeight ) {
00721 std::cout << " Particle filter bestWeight=" << estimate.weight
00722 << " < minConfidentWeight=" << minConfidentWeight << ": resample once more." << std::endl;
00723 VRmixin::particleFilter->updateSensors(particleFilter->getSensorModel(),false,true);
00724 }
00725 AngTwoPi heading = theAgent->getOrientation();
00726 cout << "Agent now at " << theAgent->getCentroid() << " hdg " << heading
00727 << " (= " << float(heading)*180/M_PI << " deg.)"
00728 << " std. dev. " << sqrt(((ShapeBasedParticleFilter*)particleFilter)->getVariance().x) << " mm, "
00729 << ((ShapeBasedParticleFilter*)particleFilter)->getVariance().y * 180 / M_PI << " deg."
00730 << " bestWeight=" << estimate.weight
00731 << endl;
00732 VRmixin::mapBuilder->setAgent(Point(estimate.x,estimate.y,0,allocentric), estimate.theta, true);
00733 if ( VRmixin::pilot->curReq->displayIndividualParticles > 0 )
00734 VRmixin::particleFilter->displayIndividualParticles(VRmixin::pilot->curReq->displayIndividualParticles);
00735 else if ( VRmixin::pilot->curReq->displayParticles > 0 )
00736 VRmixin::particleFilter->displayParticles(VRmixin::pilot->curReq->displayParticles);
00737 else {
00738 GET_SHAPE(particles, GraphicsData, worldShS);
00739 if ( particles.isValid() )
00740 VRmixin::particleFilter->displayParticles(50);
00741 }
00742 }
00743
00744
00745
00746 void Pilot::WalkMachine::WalkMachine_WaypointWalker::doStart() {
00747 PilotRequest &req = *VRmixin::pilot->curReq;
00748 MMAccessor<WaypointWalkMC> wp_acc(getMC());
00749 wp_acc->getWaypointList().clear();
00750 #ifdef TGT_IS_CREATE
00751 float vx = (req.forwardSpeed > 0) ? req.forwardSpeed : 50.f;
00752 float va = (req.turnSpeed > 0) ? req.turnSpeed : 1.0f;
00753 if (req.da != 0)
00754 wp_acc->addEgocentricWaypoint(0, 0, req.da, true, vx, va);
00755 if (req.dx != 0)
00756 wp_acc->addEgocentricWaypoint(req.dx, 0, (req.dx >= 0) ? 0 : -(float)M_PI, true, vx, va);
00757 #else
00758
00759 float vx = (req.forwardSpeed > 0) ? req.forwardSpeed : 15.f;
00760 float va = (req.turnSpeed > 0) ? req.turnSpeed : 0.1f;
00761 float daCorrected = req.da + ((req.dx >= 0) ? 0 : -(float)M_PI);
00762 wp_acc->addEgocentricWaypoint(req.dx, req.dy, daCorrected, true, vx, va);
00763 #endif
00764 motman->setPriority(VRmixin::pilot->getWaypointwalk_id(),MotionManager::kStdPriority);
00765 }
00766
00767
00768
00769
00770 void Pilot::WaypointWalkMachine::WaypointWalkMachine_WaypointWalker::doStart() {
00771 PilotRequest &req = *VRmixin::pilot->curReq;
00772 MMAccessor<WaypointWalkMC> wp_acc(getMC());
00773 if(req.clearWaypoints)
00774 wp_acc->clearWaypointList();
00775 wp_acc->appendWaypoints(*req.waypointList);
00776 motman->setPriority(VRmixin::VRmixin::pilot->getWaypointwalk_id(),MotionManager::kStdPriority);
00777 }
00778
00779
00780
00781 void Pilot::SetVelocityMachine::SetVelocityMachine_Walker::doStart() {
00782 PilotRequest &preq = *VRmixin::pilot->curReq;
00783 MotionManager::MC_ID wid = VRmixin::pilot->getWalk_id();
00784 MMAccessor<WalkMC>(wid)->setTargetVelocity(preq.forwardSpeed, preq.strafeSpeed, preq.turnSpeed);
00785 motman->setPriority(wid,MotionManager::kStdPriority);
00786 }
00787
00788 void Pilot::cancelVelocity() {
00789 if ( VRmixin::pilot->curReq != NULL && VRmixin::pilot->curReq->requestType == PilotTypes::setVelocity ) {
00790 MotionManager::MC_ID wid = VRmixin::pilot->getWalk_id();
00791 erouter->postEvent(EventBase(EventBase::motmanEGID, wid, EventBase::statusETID, 0));
00792 }
00793 else
00794 std::cout << "Warning: call to Pilot::cancelVelocity() when not executing a setVelocity request: ignored." << std::endl;
00795 }
00796
00797
00798
00799 const float Pilot::ExecutePlan::allowableDistanceError = 50;
00800 const float Pilot::ExecutePlan::allowableAngularError = 0.15;
00801
00802 void Pilot::GoToShapeMachine::CheckParameters::doStart() {
00803
00804 PilotRequest &req = *VRmixin::pilot->curReq;
00805 if ( ! req.targetShape.isValid() ) {
00806 cout << "Pilot request goToShape fails: no valid targetShape specified" << endl;
00807 postStateFailure();
00808 return;
00809 }
00810 if ( req.targetShape->isObstacle() ) {
00811 cout << "Warning: Pilot marking targetShape '" << req.targetShape->getName()
00812 << "' (" << req.targetShape->getId() << ") as non-obstacle to permit path planning." << endl;
00813 req.targetShape->setObstacle(false);
00814 }
00815
00816 postStateSuccess();
00817 }
00818
00819
00820 void Pilot::PushObjectMachine::CheckParameters::doStart() {
00821
00822 PilotRequest &req = *VRmixin::pilot->curReq;
00823 if ( ! req.objectShape.isValid() ) {
00824 cout << "Pilot request pushObject fails: no valid objectShape specified" << endl;
00825 postStateFailure();
00826 return;
00827 if ( ! req.targetShape.isValid() ) {
00828 cout << "Pilot request pushObject fails: no valid targetShape specified" << endl;
00829 postStateFailure();
00830 return;
00831 }
00832 if ( req.targetShape->isObstacle() ) {
00833 cout << "Warning: Pilot marking targetShape '" << req.targetShape->getName()
00834 << "' (" << req.targetShape->getId() << ") as non-obstacle to permit path planning." << endl;
00835 req.targetShape->setObstacle(false);
00836 }
00837 }
00838
00839 postStateSuccess();
00840 }
00841
00842
00843
00844 unsigned int Pilot::verbosity = -1U & ~Pilot::PVnavStep;
00845
00846 }
00847
00848 #endif