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