Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

LookAtMarkers.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef _LookAtMarkers_h_
00003 #define _LookAtMarkers_h_
00004 
00005 #include "DualCoding/DualCoding.h"
00006 #include "Events/DataEvent.h"
00007 #include "Motion/MotionPtr.h"
00008 #include "Behaviors/StateMachine.h"
00009 
00010 #define LOOK_AT_MARKERS_EVENT 1010
00011 
00012 // should have provided a map already in the world space
00013 class LookAtMarkers : public StateNode {
00014 public:
00015 
00016   class SelectMarker : public VisualRoutinesStateNode {
00017   private:
00018     MotionPtr<HeadPointerMC> pointer;
00019     
00020   public:
00021     SelectMarker(const std::string& name, MotionPtr<HeadPointerMC> _pointer)
00022       : VisualRoutinesStateNode(name), pointer(_pointer) {}
00023 
00024     virtual void doStart() {
00025       //cout << "Selecting the nearest marker!" << endl;
00026 
00027       Shape<MarkerData> best;
00028       float bestDistance = std::numeric_limits<float>::infinity();
00029       
00030       NEW_SHAPEVEC(markers, MarkerData, select_type<MarkerData>(worldShS));
00031 
00032       DualCoding::Point pR = theAgent->getCentroid();
00033       AngTwoPi oR = theAgent->getOrientation();
00034       //cout << "We think the agent is at: " << pR << ", " << oR << endl;
00035       
00036       GET_SHAPE(worldBounds, PolygonData, worldShS);
00037       SHAPEVEC_ITERATE(markers, MarkerData, m) {
00038   DualCoding::Point pM = m->getCentroid();
00039   //cout << "Checking marker at: " << pM << endl;
00040   
00041   // find angle between two
00042   fmat::Column<2> heading = fmat::SubVector<2>(pM.coords) - fmat::SubVector<2>(pR.coords);
00043   AngSignPi angle = (std::atan2(heading[1], heading[0]) - oR);
00044   
00045   // is the camera within our possible field of view (in front of us)?
00046   if (fabs(angle) > Pi/2.0)
00047     continue;
00048   
00049   //cout << "In front of us!" << endl;
00050   
00051   // are we further away than the closest one so far?
00052   if (pR.xyDistanceFrom(pM) >= bestDistance)
00053     continue;
00054   
00055   //cout << "It's closer!" << endl;
00056   
00057   // do we intersect with the world bounds when looking at marker?
00058   LineData lineOfSight(worldShS, pR, pM);
00059   if (worldBounds.isValid() && worldBounds->intersectsLine(lineOfSight))
00060     continue;
00061   
00062   //cout << "We can see it!" << endl;
00063   
00064   // this marker is viewable and the closest so far!
00065   best = m;
00066   bestDistance = pR.xyDistanceFrom(pM);
00067         
00068       } END_ITERATE;
00069       
00070       //cout << "Best marker is: " << best << endl;
00071 
00072       // there's a marker in sight!
00073       if (best.isValid()) {
00074   // get the point in local space
00075   Shape<MarkerData> localCopy = mapBuilder->importWorldToLocal(best);
00076   Point p = localCopy->getCentroid();
00077   pointer->lookAtPoint(p.coordX(), p.coordY(), p.coordZ());
00078   localShS.deleteShape(localCopy);
00079   
00080   postStateSignal<Shape<MarkerData> >(best);
00081       }
00082       else
00083   postStateCompletion();
00084     }
00085 
00086   private:
00087     SelectMarker(const SelectMarker&); //!< don't call (copy constructor)
00088     SelectMarker& operator=(const SelectMarker&); //!< don't call (assignment operator)
00089   };
00090   
00091   class TrackMarker : public VisualRoutinesStateNode {
00092   private:
00093     MotionPtr<HeadPointerMC> pointer;
00094     Shape<MarkerData> target;
00095 
00096     // number of frames we've missed the marker for
00097     int misses;
00098     // did we see it at all?
00099     bool seenIt;
00100     
00101   public:
00102     TrackMarker(const std::string& name, MotionPtr<HeadPointerMC> _pointer)
00103       : VisualRoutinesStateNode(name), pointer(_pointer), target(),
00104   misses(), seenIt() {}
00105     
00106     virtual void doStart() {
00107       const DataEvent<Shape<MarkerData> > *de = dynamic_cast<const DataEvent<Shape<MarkerData> >*>(event);
00108     if(de==NULL) {
00109       std::cout << "ERROR: TrackMarker needs signal trans to provide Shape<MarkerData> to specify target" << std::endl;
00110       return;
00111     }
00112       target = (de->getData());
00113       //cout << "Tracking." << endl;
00114 
00115       // reset detection misses
00116       misses = 0;
00117       seenIt = false;
00118 
00119       // currently, update the head pointer based on timer events
00120       erouter->addTimer(this, 0, 1000, false);
00121     }
00122 
00123     virtual void doEvent() {
00124       switch (event->getGeneratorID()) {
00125       case EventBase::timerEGID: {
00126   if (event->getSourceID() == 0)
00127     erouter->addTimer(this, 0, 200);
00128   
00129   if (!target.isValid())
00130     return;
00131   
00132   //cout << "*";
00133   MapBuilderRequest mapreq(MapBuilderRequest::cameraMap);
00134   mapreq.markerTypes = MarkerData::allMarkerTypes();
00135   mapreq.immediateRequest = true;
00136   mapBuilder->executeRequest(mapreq);
00137   NEW_SHAPEVEC(markers, MarkerData, select_type<MarkerData>(camShS));
00138   
00139   SHAPEVEC_ITERATE(markers, MarkerData, m) {
00140     if (m->isMatchingMarker(target)) {
00141       // we found a matching marker for the target in the image
00142       // TODO: if markers are non-unique, find closest matching marker?
00143       seenIt = true;
00144       misses = 0;
00145       
00146       // get local coordinates
00147       const PlaneEquation groundplane = kine->calculateGroundPlane();
00148       const fmat::Transform camToBase = kine->linkToBase(CameraFrameOffset);
00149       
00150       Shape<MarkerData> localCopy = m->copy();
00151       localCopy->projectToGround(camToBase, groundplane);
00152       Point p = localCopy->getCentroid();
00153       
00154       // how far back are we looking?
00155       if (p.coordX() > 0)
00156         pointer->lookAtPoint(p.coordX(), p.coordY(), p.coordZ());
00157       else
00158         postStateCompletion();
00159       
00160       // localCopy gets deleted because it was never imported (i think)
00161       camShS.clear();
00162       return;
00163     }
00164   } END_ITERATE;
00165   
00166   // if we make it here, no match found
00167   camShS.clear();
00168   
00169   //cout << "We lost it." << endl;
00170   if (misses++ > 5) {
00171     if (seenIt) { // were tracking it and lost it
00172       postStateCompletion();
00173     } else { // never saw it in the first place (initial estimate of location was wrong)
00174       postStateSignal<Shape<MarkerData> >(target);
00175     }
00176   }
00177   
00178   break;
00179       }
00180       default:
00181   break;
00182       }
00183     }
00184   };
00185 
00186   class Search : public VisualRoutinesStateNode {
00187   private:
00188     MotionPtr<HeadPointerMC> pointer;
00189     Shape<MarkerData> target;
00190 
00191     std::vector<float> panPoints;
00192     
00193   public:
00194     Search(const std::string& name, MotionPtr<HeadPointerMC> _pointer)
00195       : VisualRoutinesStateNode(name), pointer(_pointer), target(), panPoints() {}
00196     
00197     virtual void doStart() {
00198       const DataEvent<Shape<MarkerData> > *de = dynamic_cast<const DataEvent<Shape<MarkerData> >*>(event);
00199     if(de==NULL) {
00200       std::cout << "ERROR: Search node needs signal trans to provide Shape<MarkerData> to specify target" << std::endl;
00201       return;
00202     }
00203     target = (de->getData());
00204       //cout << "Searching for a marker." << endl;
00205       
00206       // setup points to pan to while searching
00207       panPoints = std::vector<float>(5);
00208       panPoints.push_back(-((float)Pi));
00209       panPoints.push_back(-((float)Pi*0.75));
00210       panPoints.push_back(-((float)Pi*0.375));
00211       panPoints.push_back(0.0);
00212       panPoints.push_back(Pi*0.375);
00213       panPoints.push_back(Pi*0.75);
00214       panPoints.push_back(Pi);
00215       panPoints.push_back(Pi*0.5);
00216       panPoints.push_back(Pi*0.25);
00217       panPoints.push_back(0.0);
00218       panPoints.push_back(-((float)Pi*0.25));
00219       panPoints.push_back(-((float)Pi*0.5));
00220 
00221       erouter->addTimer(this, 0, 500, false);
00222     }
00223 
00224     virtual void doEvent()
00225     {
00226       switch (event->getGeneratorID()) {
00227       case EventBase::timerEGID: {
00228   if (event->getSourceID() == 0) {
00229     MapBuilderRequest mapreq(MapBuilderRequest::cameraMap);
00230     mapreq.markerTypes = MarkerData::allMarkerTypes();
00231     mapreq.immediateRequest = true;
00232     mapBuilder->executeRequest(mapreq);
00233     NEW_SHAPEVEC(markers, MarkerData, select_type<MarkerData>(camShS));
00234     Shape<MarkerData> fallback;
00235     SHAPEVEC_ITERATE(markers, MarkerData, m) {
00236       if (m->isMatchingMarker(target)) {
00237         // we found a matching marker for the target in the image
00238         // TODO: if markers are non-unique, find closest matching marker?
00239         
00240         // get local coordinates
00241         const PlaneEquation groundplane = kine->calculateGroundPlane();
00242         const fmat::Transform camToBase = kine->linkToBase(CameraFrameOffset);
00243         
00244         Shape<MarkerData> localCopy = m->copy();
00245         localCopy->projectToGround(camToBase, groundplane);
00246         Point p = localCopy->getCentroid();
00247         pointer->lookAtPoint(p.coordX(), p.coordY(), p.coordZ());
00248         
00249         // localCopy gets deleted because it was never imported (i think)
00250         camShS.clear();
00251         postStateSignal<Shape<MarkerData> >(target);
00252         return;
00253       }
00254       else {
00255         fallback = m;
00256       }
00257     } END_ITERATE;
00258     
00259     // if we make it here, no match found
00260     if (fallback.isValid()) {
00261       // get local coordinates
00262       const PlaneEquation groundplane = kine->calculateGroundPlane();
00263       const fmat::Transform camToBase = kine->linkToBase(CameraFrameOffset);
00264       
00265       Shape<MarkerData> localCopy = fallback->copy();
00266       localCopy->projectToGround(camToBase, groundplane);
00267       Point p = localCopy->getCentroid();
00268       pointer->lookAtPoint(p.coordX(), p.coordY(), p.coordZ());
00269       
00270       // localCopy gets deleted because it was never imported (i think)
00271       camShS.clear();
00272       postStateSignal<Shape<MarkerData> >(fallback);
00273       return;
00274     }
00275     
00276     camShS.clear();
00277     
00278     // focus on next point
00279     if (panPoints.size() > 0) {
00280       //cout << "Panning to: " << panPoints.back() << endl;
00281       //cout << "Current pan is: " << pointer->getJointValue(RobotInfo::PanOffset) << endl;
00282       pointer->setJointValue(RobotInfo::PanOffset, panPoints.back());
00283       panPoints.pop_back();
00284       erouter->addTimer(this, 0, 1000, false);
00285     }
00286     
00287     postStateCompletion();
00288   }
00289   
00290   break;
00291       }
00292       default: {
00293   break;
00294       }
00295       }
00296     }
00297   };
00298 
00299   class DummyFinish : public StateNode {
00300   public:
00301     DummyFinish(const std::string &nodename): StateNode(nodename) {}
00302     virtual void doStart(){
00303       getParent()->stop();
00304     }
00305   };
00306 
00307 public:
00308   LookAtMarkers(const std::string &name) : StateNode(name) {}
00309 
00310   virtual void setup() {
00311     MotionPtr<HeadPointerMC> pointer;
00312     /*MotionManager::MC_ID pointID = */addMotion(pointer);
00313     
00314     pointer->defaultMaxSpeed(0.5f);
00315  startnode = new SpeechNode("startnode", "Looking for markers.");
00316  addNode(startnode);
00317 
00318  SelectMarker *select = new SelectMarker("select", pointer);
00319  addNode(select);
00320 
00321  TrackMarker *track = new TrackMarker("track", pointer);
00322  addNode(track);
00323 
00324  DummyFinish *finish = new DummyFinish("finish");
00325  addNode(finish);
00326 
00327  Search *search = new Search("search", pointer);
00328  addNode(search);
00329 
00330  OutputNode *pause = new OutputNode("pause","Pausing marker tracker...",std::cout);
00331  addNode(pause);
00332 
00333  startnode->addTransition(new TimeOutTrans("timeouttrans1",select,3000));
00334  select->addTransition(new SignalTrans<Shape<MarkerData> >("signaltrans1",track));
00335  track->addTransition(new CompletionTrans("completiontrans1",select));
00336  select->addTransition(new CompletionTrans("completiontrans2",finish));
00337  track->addTransition(new SignalTrans<Shape<MarkerData> >("signaltrans2",search));
00338  search->addTransition(new SignalTrans<Shape<MarkerData> >("signaltrans3",track));
00339 
00340  EventTrans *eventtrans1 = new EventTrans("eventtrans1",pause,EventBase::unknownEGID, LOOK_AT_MARKERS_EVENT, EventBase::deactivateETID);
00341  track->addTransition(eventtrans1);
00342  select->addTransition(eventtrans1);
00343  search->addTransition(eventtrans1);
00344 
00345  pause->addTransition(new EventTrans("eventtrans2",select,EventBase::unknownEGID, LOOK_AT_MARKERS_EVENT, EventBase::activateETID));
00346   }
00347 
00348   static std::string getClassDescription() {
00349     return "Search for and track markers";
00350   }
00351 
00352 private:
00353   LookAtMarkers(const LookAtMarkers&); //!< don't call (copy constructor)
00354   LookAtMarkers& operator=(const LookAtMarkers&); //!< don't call (assignment operator)
00355 };
00356 
00357 #endif //included

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:44 2016 by Doxygen 1.6.3