00001
00002
00003 #include "Events/EventRouter.h"
00004 #include "Events/LocomotionEvent.h"
00005 #include "Events/LookoutEvents.h"
00006 #include "Events/VisionObjectEvent.h"
00007 #include "IPC/SharedObject.h"
00008 #include "Motion/MMAccessor.h"
00009 #include "Motion/MotionSequenceMC.h"
00010 #include "Motion/PostureMC.h"
00011 #include "Shared/Config.h"
00012 #include "Shared/ProjectInterface.h"
00013 #include "Shared/mathutils.h"
00014 #include "Shared/WorldState.h"
00015 #include "Vision/RegionGenerator.h"
00016 #include "Vision/SegmentedColorGenerator.h"
00017
00018 #include "DualCoding/VRmixin.h"
00019 #include "Crew/LookoutRequests.h"
00020 #include "Crew/Lookout.h"
00021 #include "Crew/MapBuilder.h"
00022 #include "DualCoding/ShapeBlob.h"
00023 #include "DualCoding/ShapeLine.h"
00024 #include "DualCoding/ShapePolygon.h"
00025
00026 using namespace mathutils;
00027 using namespace std;
00028
00029 namespace DualCoding {
00030
00031 Lookout::Lookout()
00032 : BehaviorBase("Lookout"),
00033 idCounter(0),
00034 pixelHistograms(VRmixin::camSkS.getNumPixels()), distanceSamples(),
00035 pointer_id(MotionManager::invalid_MC_ID),
00036 posture_id(MotionManager::invalid_MC_ID),
00037 sequence_id(MotionManager::invalid_MC_ID),
00038 requests(), curReq(NULL), curPAR(NULL), successSave(false),
00039 trackerState(inactive)
00040 {}
00041
00042 void Lookout::doStart() {
00043 BehaviorBase::doStart();
00044 SharedObject<HeadPointerMC> head_mc;
00045 SharedObject<PostureMC> posture_mc;
00046 SharedObject<MediumMotionSequenceMC> mseq_mc;
00047 pointer_id = motman->addPersistentMotion(head_mc,MotionManager::kIgnoredPriority);
00048 posture_id = motman->addPersistentMotion(posture_mc,MotionManager::kIgnoredPriority);
00049 sequence_id = motman->addPersistentMotion(mseq_mc,MotionManager::kIgnoredPriority);
00050 cout << "Lookout starting up: pointer_id=" << pointer_id
00051 << " posture_id=" << posture_id
00052 << " sequence_id=" << sequence_id << endl;
00053 erouter->addListener(this,EventBase::motmanEGID,pointer_id,EventBase::statusETID);
00054 erouter->addListener(this,EventBase::motmanEGID,posture_id,EventBase::statusETID);
00055 erouter->addListener(this,EventBase::motmanEGID,sequence_id,EventBase::statusETID);
00056 }
00057
00058 void Lookout::doStop() {
00059 motman->removeMotion(pointer_id);
00060 pointer_id = MotionManager::invalid_MC_ID;
00061 motman->removeMotion(posture_id);
00062 posture_id = MotionManager::invalid_MC_ID;
00063 motman->removeMotion(sequence_id);
00064 sequence_id = MotionManager::invalid_MC_ID;
00065 curReq = NULL;
00066 curPAR = NULL;
00067 while (!requests.empty()) {
00068 delete requests.front();
00069 requests.pop();
00070 }
00071 BehaviorBase::doStop();
00072 }
00073
00074 vector<DualCoding::Point> Lookout::groundSearchPoints() {
00075 vector<Point> gazePts;
00076 #ifdef TGT_HAS_WHEELS
00077 int ground_frame_offset = 0;
00078 #else
00079 int ground_frame_offset = -100;
00080 #endif
00081 gazePts.push_back(Point( 200, -250, ground_frame_offset, egocentric));
00082 gazePts.push_back(Point( 800,-1000, ground_frame_offset, egocentric));
00083 gazePts.push_back(Point(1200, 0, ground_frame_offset, egocentric));
00084 gazePts.push_back(Point( 800, 1000, ground_frame_offset, egocentric));
00085 gazePts.push_back(Point( 200, 250, ground_frame_offset, egocentric));
00086 #ifdef TGT_QBOTPLUS //QBotPlus has a higher camera so it see much closer to its body
00087 gazePts.push_back(Point( 100, 0, ground_frame_offset, egocentric));
00088 #endif
00089 gazePts.push_back(Point( 200, 0, ground_frame_offset, egocentric));
00090 gazePts.push_back(Point( 400, 0, ground_frame_offset, egocentric));
00091 gazePts.push_back(Point( 800, 0, ground_frame_offset, egocentric));
00092 return gazePts;
00093 }
00094
00095 unsigned int Lookout::executeRequest(BehaviorBase* requestingBehavior, const LookoutRequestBase& req) {
00096 const unsigned int reqID = ++idCounter;
00097 executeRequest(req);
00098 return reqID;
00099 }
00100
00101
00102 unsigned int Lookout::executeRequest(const LookoutRequestBase &req) {
00103 switch (req.getHeadMotionType()) {
00104 case LookoutRequestBase::noMotion:
00105 case LookoutRequestBase::pointAt:
00106 pushRequest<LookoutPointRequest>(req);
00107 break;
00108 case LookoutRequestBase::scan:
00109 pushRequest<LookoutScanRequest>(req);
00110 break;
00111 case LookoutRequestBase::track:
00112 pushRequest<LookoutTrackRequest>(req);
00113 break;
00114 case LookoutRequestBase::search:
00115 pushRequest<LookoutSearchRequest>(req);
00116 break;
00117 default:
00118 cout << "Lookout::executeRequest: unknown request type " << req.getHeadMotionType() << endl;
00119 };
00120 const unsigned int reqid = requests.back()->requestID = ++idCounter;
00121 executeRequest();
00122 return reqid;
00123 }
00124
00125 void Lookout::executeRequest() {
00126 if ( curReq != NULL || requests.empty() )
00127 return;
00128 curReq = requests.front();
00129
00130
00131 curPAR = dynamic_cast<LookoutPointRequest*>(curReq);
00132
00133
00134 if ( curPAR != NULL && curPAR->numSamples > 1 )
00135 switch ( curPAR->getResultType() ) {
00136 case LookoutRequestBase::imageResult:
00137 for ( unsigned int i=0; i<pixelHistograms.size(); i++ )
00138 pixelHistograms[i].clear();
00139 break;
00140 #ifdef TGT_HAS_IR_DISTANCE
00141 case LookoutRequestBase::distanceResult:
00142 while ( distanceSamples.size() > 0) distanceSamples.pop();
00143 break;
00144 #endif
00145 default:
00146 break;
00147 }
00148
00149
00150 trackerState = inactive;
00151 switch (curReq->getHeadMotionType()) {
00152 case LookoutRequestBase::noMotion:
00153 erouter->addTimer(this, settle_timer, curPAR->motionSettleTime, false);
00154 break;
00155 case LookoutRequestBase::pointAt:
00156 moveHeadToPoint();
00157 break;
00158 case LookoutRequestBase::scan:
00159 setupScan();
00160 break;
00161 case LookoutRequestBase::track:
00162 setupTrack();
00163 break;
00164 case LookoutRequestBase::search:
00165 setupSearch();
00166 break;
00167 default:
00168 cout << "Lookout::executeRequest(): unknown request " << curReq->getHeadMotionType() << endl;
00169 break;
00170 };
00171 }
00172
00173 void Lookout::relax() {
00174 motman->setPriority(pointer_id,MotionManager::kIgnoredPriority);
00175 motman->setPriority(posture_id,MotionManager::kIgnoredPriority);
00176 motman->setPriority(sequence_id,MotionManager::kIgnoredPriority);
00177 }
00178
00179 void Lookout::moveHeadToPoint() {
00180 Point pt = curPAR->gazePt;
00181 switch ( pt.getRefFrameType() ) {
00182 case unspecified:
00183 case camcentric:
00184 cout << "Warning: Lookout gaze point " << curPAR->gazePt << " reference frame must be egocentric or allocentric" << endl;
00185 pt.setRefFrameType(egocentric);
00186 case egocentric:
00187 break;
00188 case allocentric:
00189 pt.applyTransform(VRmixin::mapBuilder->worldToLocalMatrix, egocentric);
00190 }
00191
00192 switch ( curPAR->getResultType() ) {
00193 case LookoutRequestBase::noResult:
00194 case LookoutRequestBase::imageResult: {
00195 successSave = MMAccessor<HeadPointerMC>(pointer_id)->lookAtPoint(pt.coordX(),pt.coordY(),pt.coordZ());
00196 motman->setPriority(pointer_id,MotionManager::kStdPriority);
00197 motman->setPriority(posture_id,MotionManager::kIgnoredPriority);
00198 motman->setPriority(sequence_id,MotionManager::kIgnoredPriority);
00199 }
00200 break;
00201 case LookoutRequestBase::distanceResult: {
00202 #ifdef TGT_HAS_IR_DISTANCE
00203 successSave = MMAccessor<PostureMC>(posture_id)->solveLinkVector(pt.coords,IRFrameOffset,Kinematics::pack(0,0,1));
00204 motman->setPriority(posture_id,MotionManager::kStdPriority);
00205 motman->setPriority(pointer_id,MotionManager::kIgnoredPriority);
00206 motman->setPriority(sequence_id,MotionManager::kIgnoredPriority);
00207 #endif
00208 }
00209 break;
00210 case LookoutRequestBase::interestPoints:
00211 cout << "Lookout error: this scan type cannot return interest points." << endl;
00212 return;
00213 }
00214 }
00215
00216 void Lookout::doEvent() {
00217 if ( curReq == NULL ) {
00218 if ( event->getGeneratorID() == EventBase::motmanEGID &&
00219 event->getTypeID() == EventBase::statusETID )
00220 return;
00221 else {
00222 cout << "Error: Lookout received an event when not executing a request:\n";
00223 cout << " " << event->getDescription(true,3) << endl;
00224 return;
00225 }
00226 }
00227
00228 switch (curReq->getHeadMotionType()) {
00229 case LookoutRequestBase::noMotion:
00230 case LookoutRequestBase::pointAt:
00231 processPointAtEvent(*event);
00232 break;
00233 case LookoutRequestBase::scan:
00234 processScanEvent(*event);
00235 break;
00236 case LookoutRequestBase::track:
00237 processTrackEvent(*event);
00238 break;
00239 case LookoutRequestBase::search:
00240 processSearchEvent(*event);
00241 break;
00242 default:
00243 cout << "Lookout::doEvent: unknown head motion request type: "
00244 << curReq->getHeadMotionType() << ", event: " << event->getDescription() << endl;
00245 break;
00246 };
00247 }
00248
00249 void Lookout::processPointAtEvent(const EventBase& ev) {
00250 switch (ev.getGeneratorID()) {
00251 case EventBase::motmanEGID:
00252 if ( ev.getSourceID() == pointer_id || ev.getSourceID() == posture_id ) {
00253
00254 motman->setPriority(ev.getSourceID(), MotionManager::kBackgroundPriority);
00255 erouter->addTimer(this, settle_timer, curPAR->motionSettleTime, false);
00256 }
00257 break;
00258
00259 case EventBase::timerEGID:
00260 if (ev.getSourceID() == settle_timer || ev.getSourceID() == sample_timer) {
00261 switch (curReq->getResultType()) {
00262 case LookoutRequestBase::imageResult:
00263 erouter->addListener(this, EventBase::visRegionEGID,
00264 ProjectInterface::visRegionSID,EventBase::statusETID);
00265 break;
00266 #ifdef TGT_HAS_IR_DISTANCE
00267 case LookoutRequestBase::distanceResult:
00268 erouter->addListener(this, EventBase::sensorEGID, SensorSrcID::UpdatedSID);
00269 break;
00270 #endif
00271 case LookoutRequestBase::noResult:
00272 default:
00273 requestComplete(successSave);
00274 break;
00275 };
00276 }
00277 break;
00278
00279 case EventBase::visRegionEGID:
00280 erouter->removeListener(this, EventBase::visRegionEGID);
00281 curPAR->image.bind((curPAR->sketchFunc)());
00282 ++curPAR->sampleCounter;
00283 if ( curPAR->numSamples == 1 || findPixelModes() == true ) {
00284 curPAR->toBaseMatrix = kine->linkToBase(curPAR->joint);
00285 requestComplete(successSave);
00286 }
00287 else
00288 erouter->addTimer(this, sample_timer, curPAR->sampleInterval, false);
00289 break;
00290
00291 case EventBase::sensorEGID:
00292 erouter->removeListener(this, EventBase::sensorEGID);
00293 #ifdef TGT_HAS_IR_DISTANCE
00294 if ( findDistanceMode() == true ) {
00295 curPAR->toBaseMatrix = kine->linkToBase(curPAR->joint);
00296 requestComplete(successSave);
00297 } else
00298 #endif
00299 erouter->addTimer(this, sample_timer, curPAR->sampleInterval, false);
00300 break;
00301
00302 default:
00303 cout << "Lookout::processPointAtEvent: unknown event " << ev.getDescription() << endl;
00304 break;
00305 };
00306 }
00307
00308 bool Lookout::findPixelModes() {
00309
00310 for (size_t i = 0; i<pixelHistograms.size(); i++)
00311 pixelHistograms[i][curPAR->image[i]]++;
00312 if ( curPAR->sampleCounter < curPAR->numSamples )
00313 return false;
00314
00315 for (size_t i = 0; i<pixelHistograms.size(); i++) {
00316 unsigned int maxCount = 0;
00317 uchar maxChar = 0;
00318 for (map<uchar, unsigned int>::const_iterator it = pixelHistograms[i].begin();
00319 it != pixelHistograms[i].end(); it++)
00320 if (it->second > maxCount) {
00321 maxCount = it->second;
00322 maxChar = it->first;
00323 }
00324 curPAR->image[i] = maxChar;
00325 }
00326 return true;
00327 }
00328
00329 #ifdef TGT_HAS_IR_DISTANCE
00330 float Lookout::getDistanceModeValue() {
00331 int const npops = distanceSamples.size() / 2;
00332 for ( int i=0; i<npops; i++ ) distanceSamples.pop();
00333 return distanceSamples.top();
00334 }
00335
00336 inline float getIR() {
00337 #ifdef TGT_ERS7
00338 if ( state->sensors[FarIRDistOffset] > 400 )
00339 return state->sensors[FarIRDistOffset];
00340 else
00341 return state->sensors[NearIRDistOffset];
00342 #else
00343 return state->sensors[IRDistOffset];
00344 #endif
00345 }
00346
00347 bool Lookout::findDistanceMode() {
00348 distanceSamples.push(getIR());
00349 return (int)distanceSamples.size() < curPAR->numSamples;
00350 }
00351 #endif // TGT_HAS_IR_DISTANCE
00352
00353 void Lookout::requestComplete(bool success) {
00354
00355 erouter->removeTimer(this);
00356 erouter->removeListener(this,EventBase::sensorEGID);
00357 erouter->removeListener(this,EventBase::visSegmentEGID);
00358 erouter->removeListener(this,EventBase::visRegionEGID);
00359 erouter->removeListener(this,EventBase::visObjEGID);
00360 LookoutRequestBase *saveReq = curReq;
00361 Sketch<uchar> image;
00362 fmat::Transform toBaseMatrix;
00363 switch ( saveReq->getHeadMotionType() ) {
00364 case LookoutRequestBase::noMotion:
00365 case LookoutRequestBase::pointAt:
00366 image = curPAR->image;
00367 toBaseMatrix = curPAR->toBaseMatrix;
00368 break;
00369 case LookoutRequestBase::search: {
00370 LookoutSearchRequest *curSR = static_cast<LookoutSearchRequest*>(curReq);
00371 image = curSR->image;
00372 toBaseMatrix = curSR->toBaseMatrix;
00373 break;
00374 }
00375 default:
00376 break;
00377 }
00378 curReq = NULL;
00379 curPAR = NULL;
00380 requests.pop();
00381 switch ( saveReq->getHeadMotionType() ) {
00382 case LookoutRequestBase::noMotion:
00383 case LookoutRequestBase::pointAt:
00384 switch ( saveReq->getResultType() ) {
00385 case LookoutRequestBase::noResult:
00386 erouter->postEvent(LookoutPointAtEvent(success,static_cast<LookoutPointRequest*>(saveReq)->toBaseMatrix,
00387 EventBase::lookoutEGID, saveReq->requestID, EventBase::deactivateETID));
00388 break;
00389 case LookoutRequestBase::imageResult:
00390 erouter->postEvent(LookoutSketchEvent(success,static_cast<LookoutPointRequest*>(saveReq)->image,
00391 static_cast<LookoutPointRequest*>(saveReq)->toBaseMatrix,
00392 EventBase::lookoutEGID, saveReq->requestID, EventBase::deactivateETID));
00393 break;
00394 #ifdef TGT_HAS_IR_DISTANCE
00395 case LookoutRequestBase::distanceResult:
00396 erouter->postEvent(LookoutIREvent(success,getDistanceModeValue(), static_cast<LookoutPointRequest*>(saveReq)->toBaseMatrix,
00397 EventBase::lookoutEGID, saveReq->requestID, EventBase::deactivateETID));
00398 break;
00399 #endif
00400 default:
00401 cout << "Lookout::requestComplete(): Unknown type returned by getResultType()\n";
00402 }
00403 break;
00404
00405 case LookoutRequestBase::scan:
00406 erouter->postEvent(LookoutScanEvent(static_cast<LookoutScanRequest*>(saveReq)->tasks,
00407 EventBase::lookoutEGID,saveReq->requestID, EventBase::deactivateETID));
00408 break;
00409
00410 case LookoutRequestBase::track:
00411 erouter->postEvent(EventBase(EventBase::lookoutEGID,saveReq->requestID, EventBase::deactivateETID));
00412 break;
00413
00414 case LookoutRequestBase::search: {
00415
00416
00417
00418
00419
00420
00421 erouter->postEvent(LookoutSketchEvent(success, image, toBaseMatrix,
00422 EventBase::lookoutEGID, saveReq->requestID, EventBase::deactivateETID));
00423 break;
00424 }
00425
00426 default:
00427 cout << "Lookout::requestComplete(): Unknown head motion type\n";
00428 }
00429
00430
00431
00432
00433
00434 delete saveReq;
00435 if ( curReq == NULL && !requests.empty() )
00436 executeRequest();
00437 }
00438
00439 Point Lookout::findLocationFor(const CMVision::region* reg) {
00440 return findLocationFor( float(2*reg->cen_x - VRmixin::camSkS.getWidth())/VRmixin::camSkS.getWidth(),
00441 float(2*reg->cen_y - VRmixin::camSkS.getHeight())/VRmixin::camSkS.getWidth());
00442 }
00443
00444 typedef SegmentedColorGenerator::color_class_state color_class_state;
00445
00446 void Lookout::storeVisionRegionDataTo(vector<Point>& data, const set<color_index>& colors, int minArea) {
00447 const unsigned char *img =
00448 ProjectInterface::defRegionGenerator->getImage(ProjectInterface::fullLayer,0);
00449 const color_class_state *regions = reinterpret_cast<const color_class_state*> (img);
00450 for (set<color_index>::const_iterator it = colors.begin();
00451 it != colors.end(); it++)
00452 for (int i = 0; i < regions[*it].num; i++)
00453 if ((regions[*it].list+i)->area > minArea) {
00454 data.push_back(findLocationFor(regions[*it].list));
00455 cout << regions[*it].name << " at " << data.back() << endl;
00456 }
00457 else break;
00458 }
00459
00460 #ifdef TGT_HAS_IR_DISTANCE
00461 void Lookout::storeIRDataTo(vector<Point>& data) {
00462 fmat::Column<3> ray = Kinematics::pack(0,0,getIR());
00463 cout << "dist= " << ray[2] << ", in base frame= ";
00464 fmat::Column<3> baseCoords = kine->linkToBase(IRFrameOffset)*ray;
00465 data.push_back(Point(baseCoords[0],baseCoords[1],baseCoords[2]));
00466 cout << data.back() << endl;
00467 }
00468 #endif
00469
00470
00471
00472
00473 void Lookout::processScanEvent(const EventBase& ev) {
00474
00475 static bool listeningObjEGID = false;
00476 const LookoutScanRequest* curScanReq = dynamic_cast<LookoutScanRequest*>(curReq);
00477
00478 switch (ev.getGeneratorID()) {
00479 case EventBase::motmanEGID:
00480
00481 if (ev.getSourceID() == pointer_id) {
00482 erouter->addTimer(this,settle_timer,curScanReq->motionSettleTime,false);
00483 }
00484 else if (ev.getSourceID() == sequence_id) {
00485 motman->setPriority(sequence_id,MotionManager::kBackgroundPriority);
00486 requestComplete(successSave);
00487 }
00488 break;
00489
00490 case EventBase::timerEGID:
00491 if ( ev.getSourceID() == settle_timer )
00492 triggerScanMotionSequence();
00493 else if ( ev.getSourceID() >= scan_timer && ev.getSourceID()-scan_timer < curScanReq->tasks.size() ) {
00494 LookoutRequestBase::Task* task = curScanReq->tasks[ev.getSourceID()-scan_timer];
00495 if (task->getTaskType() == LookoutRequestBase::Task::visRegTask) {
00496 LookoutRequestBase::VisionRegionTask* vrt = dynamic_cast<LookoutRequestBase::VisionRegionTask*>(task);
00497 storeVisionRegionDataTo(vrt->data,vrt->index,vrt->minArea);
00498 }
00499 else if (task->getTaskType() == LookoutRequestBase::Task::visObjTask) {
00500 erouter->addListener(this, EventBase::visSegmentEGID,
00501 ProjectInterface::visSegmentSID,EventBase::statusETID);
00502 listeningObjEGID = true;
00503 }
00504 #ifdef TGT_HAS_IR_DISTANCE
00505 else if (task->getTaskType() == LookoutRequestBase::Task::irTask)
00506 storeIRDataTo(task->data);
00507 #endif
00508 }
00509 break;
00510
00511 case EventBase::visSegmentEGID:
00512 if (listeningObjEGID)
00513 listeningObjEGID = false;
00514 else
00515 erouter->removeListener(this, EventBase::visSegmentEGID);
00516 break;
00517
00518 case EventBase::visObjEGID:
00519 if (listeningObjEGID) {
00520 const VisionObjectEvent &voe = static_cast<const VisionObjectEvent&>(ev);
00521 for (vector<LookoutRequestBase::Task*>::const_iterator it = curScanReq->tasks.begin();
00522 it != curScanReq->tasks.end(); it++)
00523 if ((*it)->getTaskType() == LookoutRequestBase::Task::visObjTask) {
00524 LookoutRequestBase::VisionTask& vTask = *dynamic_cast<LookoutRequestBase::VisionTask*>(*it);
00525 if (vTask.index.find(ev.getSourceID()) != vTask.index.end()) {
00526 vTask.data.push_back(findLocationFor(voe));
00527 cout << "VisionObject at " << vTask.data.back() << endl;
00528 break;
00529 }
00530 }
00531 }
00532 break;
00533 default:
00534 cout << "Lookout::processScan: unknown event " << ev.getName() << endl;
00535 break;
00536 };
00537 }
00538
00539 void Lookout::setupScan() {
00540 const LookoutScanRequest *curScan = dynamic_cast<const LookoutScanRequest*>(curReq);
00541 cout << "scan speed: " << curScan->scanSpeed
00542 << " (rad / millisec)\n";
00543 if ( !curScan->searchArea.isValid() ) {
00544 cout << "Invalid search area in LookoutScanRequest" << endl;
00545 return;
00546 }
00547 switch ( curScan->searchArea->getType() ) {
00548 case lineDataType: {
00549 const Shape<LineData> &line = ShapeRootTypeConst(curScan->searchArea,LineData);
00550 scanAlongLine(line->firstPt(), line->secondPt());
00551 break;
00552 }
00553 case polygonDataType:{
00554 const Shape<PolygonData> &poly = ShapeRootTypeConst(curScan->searchArea,PolygonData);
00555 scanAlongPolygon(poly->getVertices());
00556 break;
00557 }
00558 default:
00559 cout << "Invalid shape type for LookoutRequestBase searchArea: must be line or polygon" << endl;
00560 }
00561 }
00562
00563 void Lookout::triggerScanMotionSequence() {
00564 const LookoutScanRequest* curScanReq = dynamic_cast<LookoutScanRequest*>(curReq);
00565 for (unsigned int i = 0; i < curScanReq->tasks.size(); i++) {
00566 const LookoutRequestBase::Task* task = curScanReq->tasks[i];
00567 if (task->getTaskType() == LookoutRequestBase::Task::visObjTask) {
00568 const LookoutRequestBase::VisionTask& vTask = *dynamic_cast<const LookoutRequestBase::VisionTask*>(task);
00569 for(set<color_index>::const_iterator color_it = vTask.index.begin();
00570 color_it != vTask.index.end(); color_it++)
00571 erouter->addListener(this,EventBase::visObjEGID, *color_it);
00572 }
00573 erouter->addTimer(this,scan_timer+i,0,false);
00574 int snap_interval = (int)((float)task->dTheta / (float)curScanReq->scanSpeed);
00575 cout << "Lookout scan snap_interval = " << snap_interval << endl;
00576 erouter->addTimer(this, scan_timer+i, snap_interval, true);
00577 }
00578 motman->setPriority(pointer_id,MotionManager::kIgnoredPriority);
00579 motman->setPriority(posture_id,MotionManager::kIgnoredPriority);
00580 motman->setPriority(sequence_id,MotionManager::kStdPriority);
00581 MMAccessor<MediumMotionSequenceMC>(sequence_id)->play();
00582 }
00583
00584 void Lookout::scanAlongLine(const Point& startPt, const Point& endPt) {
00585 motman->setPriority(pointer_id,MotionManager::kIgnoredPriority);
00586 MMAccessor<HeadPointerMC> pointer_acc(pointer_id);
00587
00588
00589 pointer_acc->lookAtPoint(endPt.coordX(),endPt.coordY(),endPt.coordZ());
00590 std::vector<float> anglesA(NumHeadJoints);
00591 for(unsigned int i=0; i<NumHeadJoints; ++i)
00592 anglesA[i]=pointer_acc->getJointValue(i);
00593
00594
00595 pointer_acc->lookAtPoint(startPt.coordX(),startPt.coordY(),startPt.coordZ());
00596 std::vector<float> anglesB(NumHeadJoints);
00597 for(unsigned int i=0; i<NumHeadJoints; ++i)
00598 anglesB[i]=pointer_acc->getJointValue(i);
00599
00600 float total_joint_distance=0;
00601 for(unsigned int i=0; i<NumHeadJoints; ++i) {
00602 float diff = anglesA[i] - anglesB[i];
00603 total_joint_distance += diff*diff;
00604 }
00605 const unsigned int movement_time = (unsigned int)(sqrt(total_joint_distance) / dynamic_cast<const LookoutScanRequest*>(curReq)->scanSpeed);
00606
00607
00608 motman->setPriority(sequence_id,MotionManager::kIgnoredPriority);
00609 MMAccessor<MediumMotionSequenceMC> mseq_acc(sequence_id);
00610 mseq_acc->clear();
00611 mseq_acc->pause();
00612 #ifdef TGT_HAS_HEAD
00613 for(unsigned int i=0; i<NumHeadJoints; ++i)
00614 mseq_acc->setOutputCmd(HeadOffset+i,anglesA[i]);
00615 #endif
00616 mseq_acc->advanceTime(movement_time);
00617 #ifdef TGT_HAS_HEAD
00618 for(unsigned int i=0; i<NumHeadJoints; ++i)
00619 mseq_acc->setOutputCmd(HeadOffset+i,anglesB[i]);
00620 #endif
00621 motman->setPriority(posture_id,MotionManager::kIgnoredPriority);
00622 motman->setPriority(pointer_id,MotionManager::kStdPriority);
00623 }
00624
00625 void Lookout::scanAlongPolygon(vector<Point> const &vertices, const bool closed) {
00626 if ( vertices.size() == 0 )
00627 requestComplete();
00628 vector<Point> vertices_copy(vertices);
00629 const Point startPt = vertices_copy[0];
00630 if ( closed )
00631 vertices_copy.push_back(startPt);
00632 motman->setPriority(pointer_id,MotionManager::kBackgroundPriority);
00633 motman->setPriority(sequence_id,MotionManager::kBackgroundPriority);
00634 MMAccessor<HeadPointerMC> pointer_acc(pointer_id);
00635 MMAccessor<MediumMotionSequenceMC> mseq_acc(sequence_id);
00636 mseq_acc->pause();
00637 mseq_acc->clear();
00638 float const speed = dynamic_cast<const LookoutScanRequest*>(curReq)->scanSpeed;
00639 std::vector<float> anglesA(NumHeadJoints,0), anglesB(NumHeadJoints,0);
00640 for ( vector<Point>::const_iterator it = vertices_copy.begin(); it != vertices_copy.end(); ++it ) {
00641 pointer_acc->lookAtPoint((*it).coordX(),(*it).coordY(),(*it).coordZ());
00642 for(unsigned int i=0; i<NumHeadJoints; ++i)
00643 anglesB[i]=pointer_acc->getJointValue(i);
00644 if ( it != vertices_copy.begin() ) {
00645 float total_joint_distance=0;
00646 for(unsigned int i=0; i<NumHeadJoints; ++i) {
00647 float diff = anglesA[i] - anglesB[i];
00648 total_joint_distance += diff*diff;
00649 }
00650 const unsigned int movement_time = (unsigned int)(sqrt(total_joint_distance) /speed + 200);
00651
00652 mseq_acc->advanceTime(movement_time);
00653 }
00654 #ifdef TGT_HAS_HEAD
00655 for(unsigned int i=0; i<NumHeadJoints; ++i)
00656 mseq_acc->setOutputCmd(HeadOffset+i,anglesB[i]);
00657 mseq_acc->advanceTime(200);
00658 for(unsigned int i=0; i<NumHeadJoints; ++i)
00659 mseq_acc->setOutputCmd(HeadOffset+i,anglesB[i]);
00660 #endif
00661 anglesA.swap(anglesB);
00662 }
00663
00664 cout << "Lookout:scanAlongPolygon lookAtPoint " << startPt.coordX() << " "
00665 << startPt.coordY() << " " << startPt.coordZ() << endl;
00666 pointer_acc->lookAtPoint(startPt.coordX(),startPt.coordY(),startPt.coordZ());
00667 motman->setPriority(pointer_id,MotionManager::kStdPriority);
00668 }
00669
00670
00671
00672 void Lookout::setupTrack() {
00673
00674 LookoutTrackRequest *curTR = static_cast<LookoutTrackRequest*>(curReq);
00675 const ShapeRoot &target = curTR->targetShape;
00676 curTR->cindex = ProjectInterface::getColorIndex(target->getColor());
00677 Point egoLoc = target->getCentroid();
00678 if ( target->getRefFrameType() == camcentric ) {
00679 #ifndef TGT_HAS_CAMERA
00680 std::cerr << "Lookout::setupTrack target has camcentric reference frame, but target model doesn't have a camera" << std::endl;
00681 #else
00682 const fmat::Transform camToBase = kine->linkToBase(CameraFrameOffset);
00683 egoLoc.projectToGround(camToBase,kine->calculateGroundPlane());
00684 #endif
00685 }
00686 trackerState = moveToAcquire;
00687 erouter->addListener(this, EventBase::visRegionEGID, ProjectInterface::visRegionSID, EventBase::deactivateETID);
00688 motman->setPriority(posture_id,MotionManager::kIgnoredPriority);
00689 motman->setPriority(sequence_id,MotionManager::kIgnoredPriority);
00690 motman->setPriority(pointer_id,MotionManager::kStdPriority);
00691 successSave = MMAccessor<HeadPointerMC>(pointer_id)->lookAtPoint(egoLoc.coordX(), egoLoc.coordY(), egoLoc.coordZ());
00692 }
00693
00694 void Lookout::processTrackEvent(const EventBase &ev) {
00695 const LookoutTrackRequest *curTR = static_cast<const LookoutTrackRequest*>(curReq);
00696 switch ( ev.getGeneratorID() ) {
00697
00698 case EventBase::visRegionEGID: {
00699 if ( trackerState == moveToAcquire ) return;
00700 const color_class_state *ccs = reinterpret_cast<const CMVision::color_class_state*>
00701 (ProjectInterface::defRegionGenerator->getImage(ProjectInterface::fullLayer,0));
00702 const color_class_state &col = ccs[curTR->cindex];
00703 if ( col.list == NULL || col.list->area <= curTR->minBlobArea ) {
00704 if ( trackerState != lost ) {
00705 trackerState = lost;
00706 erouter->addTimer(this,lost_timer,2000,false);
00707 }
00708 return;
00709 }
00710
00711 erouter->removeTimer(this,lost_timer);
00712 trackerState = tracking;
00713 Point target = findLocationFor(col.list);
00714 MMAccessor<HeadPointerMC>(pointer_id)->lookAtPoint(target.coordX(),target.coordY(),target.coordZ());
00715 }
00716 break;
00717
00718
00719 case EventBase::motmanEGID:
00720 switch ( trackerState ) {
00721 case inactive:
00722 break;
00723 case moveToAcquire:
00724 trackerState = tracking;
00725 break;
00726 case tracking:
00727 case searching:
00728 case centering:
00729 case lost:
00730 break;
00731 }
00732 break;
00733
00734 case EventBase::timerEGID:
00735 if ( ev.getSourceID() == lost_timer )
00736 stopTrack();
00737 break;
00738
00739 default:
00740 break;
00741 }
00742 }
00743
00744 void Lookout::stopTrack() {
00745 if ( curReq != NULL && curReq->getHeadMotionType() == LookoutRequestBase::track )
00746 requestComplete(false);
00747 }
00748
00749 Point Lookout::findLocationFor(const float normX, const float normY) {
00750 fmat::Column<3> cameraPt;
00751 config->vision.computeRay(normX, normY, cameraPt[0],cameraPt[1],cameraPt[2]);
00752 #ifdef TGT_HAS_IR_DISTANCE
00753 cameraPt *= getIR();
00754 #else
00755 cameraPt *= 400;
00756 #endif
00757
00758
00759 #ifndef TGT_HAS_CAMERA
00760 const fmat::Column<3> groundPt = cameraPt;
00761 #else
00762 const fmat::Transform camToBase(kine->linkToBase(CameraFrameOffset));
00763 const fmat::Column<3> groundPt = camToBase * cameraPt;
00764 #endif
00765 return Point(groundPt,egocentric);
00766 }
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 void Lookout::setupSearch() {
00876
00877 LookoutSearchRequest *curSR = static_cast<LookoutSearchRequest*>(curReq);
00878 const ShapeRoot &target = curSR->targetShape;
00879 curSR->cindex = ProjectInterface::getColorIndex(target->getColor());
00880 Point egoLoc = target->getCentroid();
00881 if ( target->getRefFrameType() == allocentric ) {
00882 egoLoc.applyTransform(VRmixin::mapBuilder->worldToLocalMatrix, egocentric);
00883 }
00884 cout << "Lookout: search target estimated at " << egoLoc << ", color=" << curSR->cindex << endl;
00885 erouter->addListener(this, EventBase::visRegionEGID,ProjectInterface::visRegionSID,EventBase::deactivateETID);
00886 successSave = MMAccessor<HeadPointerMC>(pointer_id)->lookAtPoint(egoLoc.coordX(), egoLoc.coordY(), egoLoc.coordZ());
00887 motman->setPriority(pointer_id,MotionManager::kStdPriority);
00888 trackerState = moveToAcquire;
00889 }
00890
00891 void Lookout::processSearchEvent(const EventBase &ev) {
00892
00893 LookoutSearchRequest *curSR = static_cast<LookoutSearchRequest*>(curReq);
00894 switch ( ev.getGeneratorID() ) {
00895
00896 case EventBase::motmanEGID:
00897 if ( ev.getSourceID() == pointer_id || ev.getSourceID() == sequence_id )
00898 erouter->addTimer(this, settle_timer, 500, false);
00899 else
00900 return;
00901 break;
00902
00903 case EventBase::visRegionEGID: {
00904 if ( trackerState == centering ) {
00905 curSR->image.bind(VRmixin::sketchFromSeg());
00906 curSR->toBaseMatrix = kine->linkToBase(curSR->joint);
00907 requestComplete(successSave);
00908 return;
00909 }
00910 const color_class_state *ccs = reinterpret_cast<const CMVision::color_class_state*>
00911 (ProjectInterface::defRegionGenerator->getImage(ProjectInterface::fullLayer,0));
00912 const color_class_state &col = ccs[curSR->cindex];
00913
00914 if ( col.list != NULL && col.list->area >= curSR->minBlobArea )
00915 erouter->removeListener(this,EventBase::visRegionEGID);
00916 else
00917 return;
00918
00919 const Point center = findLocationFor(col.list);
00920 cout << "Lookout: search result groundpoint = " << center
00921 << " area = " << col.list->area << " color = " << curSR->cindex << endl;
00922 MMAccessor<HeadPointerMC>(pointer_id)->lookAtPoint(center.coordX(),center.coordY(),center.coordZ());
00923 motman->setPriority(pointer_id,MotionManager::kStdPriority);
00924
00925 motman->setPriority(posture_id,MotionManager::kIgnoredPriority);
00926 motman->setPriority(sequence_id,MotionManager::kIgnoredPriority);
00927 trackerState = centering;
00928 erouter->removeListener(this, EventBase::visRegionEGID);
00929 erouter->addTimer(this, settle_timer, 500, false);
00930 break;
00931 }
00932
00933 case EventBase::timerEGID:
00934 switch ( trackerState ) {
00935 case moveToAcquire:
00936 triggerSearchMotionSequence();
00937 break;
00938 case searching:
00939 case centering:
00940 erouter->addListener(this, EventBase::visRegionEGID,
00941 ProjectInterface::visRegionSID,EventBase::statusETID);
00942 break;
00943 default:
00944 break;
00945 }
00946
00947 default:
00948 break;
00949 }
00950 }
00951
00952 void Lookout::triggerSearchMotionSequence() {
00953 cout << "Lookout: beginning search motion sequence" << endl;
00954 const LookoutSearchRequest *curSR = static_cast<const LookoutSearchRequest*>(curReq);
00955 const ShapeRoot &target = curSR->targetShape;
00956 Point egoLoc = target->getCentroid();
00957 if ( target->getRefFrameType() == allocentric ) {
00958 egoLoc.applyTransform(VRmixin::mapBuilder->worldToLocalMatrix, egocentric);
00959 }
00960 int const nspirals = 5;
00961 float const xstep=50, ystep=100;
00962 HeadPointerMC hpmc_temp;
00963 std::vector<float> jointvals(0);
00964 jointvals.reserve(nspirals*4*NumHeadJoints);
00965 for (int i=1; i<=nspirals; i++) {
00966 searchAt(hpmc_temp,jointvals,egoLoc+Point(-i*xstep, 0));
00967 searchAt(hpmc_temp,jointvals,egoLoc+Point( 0, i*ystep));
00968 searchAt(hpmc_temp,jointvals,egoLoc+Point( i*xstep, 0));
00969 searchAt(hpmc_temp,jointvals,egoLoc+Point( 0, -i*ystep));
00970 }
00971
00972
00973 MMAccessor<MediumMotionSequenceMC> mseq_acc(sequence_id);
00974 mseq_acc->clear();
00975 #ifdef TGT_HAS_HEAD
00976 for ( std::vector<float>::const_iterator it = jointvals.begin(); it != jointvals.end(); ) {
00977 mseq_acc->advanceTime(800);
00978 for(unsigned int i=0; i<NumHeadJoints; ++i)
00979 mseq_acc->setOutputCmd(HeadOffset+i,*(it++));
00980 }
00981 mseq_acc->advanceTime(800);
00982 #endif
00983 mseq_acc->play();
00984 motman->setPriority(sequence_id,MotionManager::kStdPriority);
00985 trackerState = searching;
00986 }
00987
00988 void Lookout::searchAt(HeadPointerMC &hpmc_temp,
00989 std::vector<float> &jointvals,
00990 const Point &target) {
00991 hpmc_temp.lookAtPoint(target.coordX() ,target.coordY() ,target.coordZ());
00992 for(unsigned int i=0; i<NumHeadJoints; ++i)
00993 jointvals.push_back(hpmc_temp.getJointValue(i));
00994 }
00995
00996 }