00001
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
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
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
00035
00036 GET_SHAPE(worldBounds, PolygonData, worldShS);
00037 SHAPEVEC_ITERATE(markers, MarkerData, m) {
00038 DualCoding::Point pM = m->getCentroid();
00039
00040
00041
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
00046 if (fabs(angle) > Pi/2.0)
00047 continue;
00048
00049
00050
00051
00052 if (pR.xyDistanceFrom(pM) >= bestDistance)
00053 continue;
00054
00055
00056
00057
00058 LineData lineOfSight(worldShS, pR, pM);
00059 if (worldBounds.isValid() && worldBounds->intersectsLine(lineOfSight))
00060 continue;
00061
00062
00063
00064
00065 best = m;
00066 bestDistance = pR.xyDistanceFrom(pM);
00067
00068 } END_ITERATE;
00069
00070
00071
00072
00073 if (best.isValid()) {
00074
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&);
00088 SelectMarker& operator=(const SelectMarker&);
00089 };
00090
00091 class TrackMarker : public VisualRoutinesStateNode {
00092 private:
00093 MotionPtr<HeadPointerMC> pointer;
00094 Shape<MarkerData> target;
00095
00096
00097 int misses;
00098
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
00114
00115
00116 misses = 0;
00117 seenIt = false;
00118
00119
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
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
00142
00143 seenIt = true;
00144 misses = 0;
00145
00146
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
00155 if (p.coordX() > 0)
00156 pointer->lookAtPoint(p.coordX(), p.coordY(), p.coordZ());
00157 else
00158 postStateCompletion();
00159
00160
00161 camShS.clear();
00162 return;
00163 }
00164 } END_ITERATE;
00165
00166
00167 camShS.clear();
00168
00169
00170 if (misses++ > 5) {
00171 if (seenIt) {
00172 postStateCompletion();
00173 } else {
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
00205
00206
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
00238
00239
00240
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
00250 camShS.clear();
00251 postStateSignal<Shape<MarkerData> >(target);
00252 return;
00253 }
00254 else {
00255 fallback = m;
00256 }
00257 } END_ITERATE;
00258
00259
00260 if (fallback.isValid()) {
00261
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
00271 camShS.clear();
00272 postStateSignal<Shape<MarkerData> >(fallback);
00273 return;
00274 }
00275
00276 camShS.clear();
00277
00278
00279 if (panPoints.size() > 0) {
00280
00281
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 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&);
00354 LookAtMarkers& operator=(const LookAtMarkers&);
00355 };
00356
00357 #endif //included