00001
00002
00003 #include "Events/EventRouter.h"
00004 #include "Events/LocomotionEvent.h"
00005 #include "Events/LookoutEvents.h"
00006 #include "Events/VisionObjectEvent.h"
00007 #include "Motion/HeadPointerMC.h"
00008 #include "Motion/PostureMC.h"
00009 #include "Motion/MMAccessor.h"
00010 #include "Motion/MotionSequenceMC.h"
00011 #include "Motion/MotionManager.h"
00012 #include "Shared/ProjectInterface.h"
00013 #include "Shared/WorldState.h"
00014 #include "Vision/RegionGenerator.h"
00015
00016 #include "VRmixin.h"
00017 #include "LookoutRequests.h"
00018 #include "Lookout.h"
00019
00020 namespace DualCoding {
00021
00022
00023 typedef SegmentedColorGenerator::color_class_state color_class_state;
00024
00025 inline float getIR() {
00026 #ifdef TGT_ERS7
00027 return state->sensors[NearIRDistOffset];
00028 #else
00029 return state->sensors[IRDistOffset];
00030 #endif
00031 }
00032
00033
00034 Lookout::Lookout()
00035 : BehaviorBase("Lookout"),
00036 pointer_id(MotionManager::invalid_MC_ID),
00037 sequence_id(MotionManager::invalid_MC_ID),
00038 requests(), curReq(NULL), landmarkInView(true),
00039 idCounter(0)
00040 {}
00041
00042 void Lookout::DoStart() {
00043 BehaviorBase::DoStart();
00044 }
00045
00046 void Lookout::DoStop() {
00047 curReq = NULL;
00048 while (!requests.empty()) {
00049 if (requests.front() != NULL)
00050 delete requests.front();
00051 requests.pop();
00052 }
00053 motman->removeMotion(pointer_id);
00054 pointer_id = MotionManager::invalid_MC_ID;
00055 motman->removeMotion(sequence_id);
00056 sequence_id = MotionManager::invalid_MC_ID;
00057 BehaviorBase::DoStop();
00058 }
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 void Lookout::processScan(const EventBase& event) {
00071
00072 static bool listeningObjEGID = false;
00073 static ScanRequest* curScanReq = dynamic_cast<ScanRequest*>(curReq);
00074 if (curScanReq != curReq) curScanReq = dynamic_cast<ScanRequest*>(curReq);
00075 switch (event.getGeneratorID()) {
00076 case EventBase::motmanEGID:
00077 if (event.getTypeID() != EventBase::deactivateETID) return;
00078
00079 if (event.getSourceID() == pointer_id) {
00080 pointer_id = MotionManager::invalid_MC_ID;
00081 motman->setPriority(sequence_id,MotionManager::kStdPriority);
00082 MMAccessor<SmallMotionSequenceMC>(sequence_id)->play();
00083 for (unsigned int i = 0; i < curScanReq->tasks.size(); i++) {
00084 const ScanRequest::Task* task = curScanReq->tasks[i];
00085 if (task->getTaskType() == ScanRequest::Task::visObj) {
00086 const ScanRequest::VisionTask& vTask = *dynamic_cast<const ScanRequest::VisionTask*>(task);
00087 for(set<int>::const_iterator color_it = vTask.index.begin();
00088 color_it != vTask.index.end(); color_it++)
00089 erouter->addListener(this,EventBase::visObjEGID, *color_it);
00090 }
00091 erouter->addTimer(this,scan_timer+i,0,false);
00092 erouter->addTimer(this,scan_timer+i,
00093 (int) ((float) task->interval/(float)curScanReq->scanSpeed),true);
00094 }
00095 }
00096 else if (event.getSourceID() == sequence_id) {
00097 sequence_id = MotionManager::invalid_MC_ID;
00098 requestComplete();
00099 }
00100 break;
00101 case EventBase::timerEGID:
00102 if (event.getSourceID()-scan_timer < curScanReq->tasks.size()) {
00103 ScanRequest::Task* task = curScanReq->tasks[event.getSourceID()-scan_timer];
00104 if (task->getTaskType() == ScanRequest::Task::visReg) {
00105 ScanRequest::VisionRegionTask* vrt = dynamic_cast<ScanRequest::VisionRegionTask*>(task);
00106 storeVisionRegionDataTo(vrt->data,vrt->index,vrt->minArea);
00107 }
00108 else if (task->getTaskType() == ScanRequest::Task::visObj) {
00109 erouter->addListener(this, EventBase::visSegmentEGID,
00110 ProjectInterface::visSegmentSID,EventBase::statusETID);
00111 listeningObjEGID = true;
00112 }
00113 else if (task->getTaskType() == ScanRequest::Task::ir)
00114 storeIRDataTo(task->data);
00115 }
00116 break;
00117 case EventBase::visSegmentEGID:
00118 if (listeningObjEGID)
00119 listeningObjEGID = false;
00120 else
00121 erouter->removeListener(this, EventBase::visSegmentEGID);
00122 break;
00123 case EventBase::visObjEGID:
00124 if (listeningObjEGID) {
00125 const VisionObjectEvent voe = *static_cast<const VisionObjectEvent*>(&event);
00126 for (vector<ScanRequest::Task*>::iterator it = curScanReq->tasks.begin();
00127 it != curScanReq->tasks.end(); it++)
00128 if ((*it)->getTaskType() == ScanRequest::Task::visObj) {
00129 ScanRequest::VisionTask& vTask = *dynamic_cast<ScanRequest::VisionTask*>(*it);
00130 if (vTask.index.find(event.getSourceID()) != vTask.index.end()) {
00131 vTask.data.push_back(findLocationFor(&voe));
00132 cout << "VisionObject at " << vTask.data.back() << endl;
00133 break;
00134 }
00135 }
00136 }
00137 break;
00138 default:
00139 cout << "Lookout::processScan: unknown event " << event.getName() << endl;
00140 break;
00141 };
00142 }
00143
00144 void Lookout::storeVisionRegionDataTo(vector<Point>& data, const set<int>& colors, int minArea) {
00145 const unsigned char *img =
00146 ProjectInterface::defRegionGenerator->getImage(ProjectInterface::fullLayer,0);
00147 const color_class_state *regions = reinterpret_cast<const color_class_state*> (img);
00148 for (set<int>::const_iterator it = colors.begin();
00149 it != colors.end(); it++)
00150 for (int i = 0; i < regions[*it].num; i++)
00151 if ((regions[*it].list+i)->area > minArea) {
00152 data.push_back(findLocationFor(regions[*it].list));
00153 cout << regions[*it].name << " at " << data.back() << endl;
00154 }
00155 else break;
00156 }
00157
00158 void Lookout::storeIRDataTo(vector<Point>& data) {
00159 NEWMAT::ColumnVector ray = Kinematics::pack(0,0,getIR());
00160 cout << "dist= " << ray(3) << ", in base frame= ";
00161 #ifdef TGT_ERS7
00162 NEWMAT::ColumnVector baseCoords = kine->jointToBase(NearIRFrameOffset)*ray;
00163 #else //not ERS7
00164 NEWMAT::ColumnVector baseCoords = kine->jointToBase(IRFrameOffset)*ray;
00165 #endif
00166 data.push_back(Point(baseCoords(1),baseCoords(2),baseCoords(3)));
00167 cout << data.back() << endl;
00168 }
00169
00170 bool Lookout::findPixelModes(StoreModeImageRequest& modeRequest) {
00171 static size_t npixels = modeRequest.image->getNumPixels();
00172 static vector<map<uchar, unsigned int> > colorCount(npixels);
00173 if (modeRequest.numImages-- == 0) {
00174 for (size_t i = 0; i<npixels; i++) {
00175 unsigned int maxCount = 0; uchar maxChar = 0;
00176 for (map<uchar, unsigned int>::const_iterator it = colorCount[i].begin();
00177 it != colorCount[i].end(); it++)
00178 if (it->second > maxCount) {
00179 maxCount = it->second;
00180 maxChar = it->first;
00181 }
00182 modeRequest.image[i] = maxChar;
00183 colorCount[i].clear();
00184 }
00185 return true;
00186 }
00187 else {
00188 for (size_t i = 0; i<npixels; i++)
00189 colorCount[i][modeRequest.image[i]]++;
00190 return false;
00191 }
00192 }
00193
00194 void Lookout::processPointAt(const EventBase& event) {
00195
00196 switch (event.getGeneratorID()) {
00197 case EventBase::motmanEGID:
00198 if (event.getSourceID() == pointer_id && event.getTypeID() == EventBase::deactivateETID) {
00199 pointer_id = MotionManager::invalid_MC_ID;
00200 erouter->addTimer(this, dur_timer, dynamic_cast<const PointAtBase*>(curReq)->duration, false);
00201 }
00202 break;
00203 case EventBase::timerEGID:
00204 if (event.getSourceID() == dur_timer) {
00205 PointAtBase* baseReq = dynamic_cast<PointAtBase*>(curReq);
00206 switch (baseReq->getPointAtType()) {
00207 case PointAtBase::storeImage:
00208 erouter->addListener(this, EventBase::visSegmentEGID,
00209 ProjectInterface::visSegmentSID,EventBase::statusETID);
00210 break;
00211 case PointAtBase::measureDist:
00212 erouter->addListener(this, EventBase::sensorEGID, SensorSourceID::UpdatedSID);
00213 break;
00214 default:
00215 requestComplete();
00216 break;
00217 };
00218 break;
00219 }
00220 case EventBase::visSegmentEGID: {
00221 erouter->removeListener(this, EventBase::visSegmentEGID);
00222 PointAtBase* baseReq = dynamic_cast<PointAtBase*>(curReq);
00223 baseReq->toBaseMatrix = kine->jointToBase(baseReq->joint);
00224 VRmixin::camSkS.clear();
00225 StoreImageRequest& storeImageReq = *dynamic_cast<StoreImageRequest*>(curReq);
00226 storeImageReq.image = (*storeImageReq.sketchFunc)();
00227 if (StoreModeImageRequest* modeReq = dynamic_cast<StoreModeImageRequest*>(curReq))
00228 if ( ! findPixelModes(*modeReq) ) {
00229 erouter->addTimer(this, dur_timer, modeReq->interval, false);
00230 return;
00231 }
00232 requestComplete();
00233 }
00234 break;
00235 case EventBase::sensorEGID: {
00236 MeasureDistanceRequest* measureDistReq = dynamic_cast<MeasureDistanceRequest*>(curReq);
00237 measureDistReq->toBaseMatrix = kine->jointToBase(measureDistReq->joint);
00238 measureDistReq->val = getIR();
00239 requestComplete();
00240 }
00241 break;
00242 default:
00243 cout << "Lookout::processPointAt: unknown event " << event.getName() << endl;
00244 break;
00245 };
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 unsigned int Lookout::executeRequest(const LookoutRequest& req) {
00313 switch (req.getHeadMotionType()) {
00314 case LookoutRequest::none:
00315 switch (dynamic_cast<const PointAtBase*>(&req)->getPointAtType()) {
00316 case PointAtBase::storeImage:
00317 if (dynamic_cast<const StoreModeImageRequest*>(&req))
00318 pushRequest<StoreModeImageRequest>(req);
00319 else
00320 pushRequest<StoreImageRequest>(req);
00321 break;
00322 case PointAtBase::measureDist:
00323 pushRequest<MeasureDistanceRequest>(req); break;
00324 default:
00325 cout << "Lookout::executeRequest: unknown PointAtRequest type\n";
00326 break;
00327 };
00328 break;
00329 case LookoutRequest::pointAt:
00330 switch (dynamic_cast<const PointAtRequest*>(&req)->getPointAtType()) {
00331 case PointAtBase::none:
00332 pushRequest<PointAtRequest>(req); break;
00333 case PointAtBase::storeImage:
00334 if (dynamic_cast<const StoreModeImageAtRequest*>(&req))
00335 pushRequest<StoreModeImageAtRequest>(req);
00336 else
00337 pushRequest<StoreImageAtRequest>(req);
00338 break;
00339 case PointAtBase::measureDist:
00340 pushRequest<MeasureDistanceAtRequest>(req); break;
00341 default: cout << "Lookout::executeRequest: unknown PointAtRequest type\n"; break;
00342 };
00343 break;
00344 case LookoutRequest::scan:
00345 if (dynamic_cast<const ScanRequest*>(&req)->getScanType() == ScanRequest::line)
00346 pushRequest<ScanAlongLineRequest>(req);
00347 else
00348 pushRequest<ScanAreaRequest>(req);
00349 break;
00350 case LookoutRequest::track:
00351 pushRequest<TrackRequest>(req); break;
00352 default:
00353 cout << "Lookout::executeRequest: unknown request type " << req.getHeadMotionType() << endl;
00354 };
00355 requests.back()->requestID = idCounter++;
00356
00357 if (requests.size() == 1)
00358 executeRequest();
00359 return requests.back()->requestID;
00360 }
00361
00362
00363 void Lookout::executeRequest() {
00364 curReq = requests.front();
00365
00366 switch (curReq->getHeadMotionType()) {
00367 case LookoutRequest::none:
00368 erouter->addTimer(this,dur_timer,dynamic_cast<const PointAtBase*>(curReq)->duration,false);
00369 break;
00370 case LookoutRequest::pointAt: {
00371 const Point& pt = dynamic_cast<const PointAtRequest*>(curReq)->gazePt;
00372 if (dynamic_cast<const PointAtBase*>(curReq)->getPointAtType() == PointAtBase::measureDist) {
00373 SharedObject<PostureMC> pstmc;
00374 #ifdef TGT_ERS7
00375 pstmc->solveLinkVector(pt.coords,NearIRFrameOffset,Kinematics::pack(0,0,1));
00376 #else
00377 pstmc->solveLinkVector(pt.coords,IRFrameOffset,Kinematics::pack(0,0,1));
00378 #endif
00379 pointer_id = motman->addPrunableMotion(pstmc);
00380 }
00381 else {
00382 SharedObject<HeadPointerMC> hpmc;
00383 hpmc->lookAtPoint(pt.coordX(),pt.coordY(),pt.coordZ());
00384 pointer_id = motman->addPrunableMotion(hpmc);
00385 }
00386 erouter->addListener(this,EventBase::motmanEGID,pointer_id);
00387 }
00388 break;
00389 case LookoutRequest::scan:
00390 erouter->addListener(this,EventBase::motmanEGID);
00391 scan();
00392 break;
00393 default:
00394 cout << "Lookout::executeRequest(): unknown request " << curReq->getHeadMotionType() << endl;
00395 break;
00396 };
00397 }
00398
00399 void Lookout::requestComplete() {
00400
00401 erouter->removeListener(this);
00402 erouter->removeTimer(this);
00403 if (curReq->getHeadMotionType() == LookoutRequest::scan) {
00404 erouter->postEvent(LookoutScanEvent
00405 (dynamic_cast<ScanRequest*>(curReq)->tasks,
00406 EventBase::lookoutEGID,curReq->requestID, EventBase::deactivateETID));
00407 }
00408 else if (curReq->getHeadMotionType() == LookoutRequest::pointAt
00409 || curReq->getHeadMotionType() == LookoutRequest::none) {
00410 const NEWMAT::Matrix& toBase = dynamic_cast<const PointAtBase*>(curReq)->toBaseMatrix;
00411 switch (dynamic_cast<const PointAtBase*>(curReq)->getPointAtType()) {
00412 case PointAtRequest::none:
00413 erouter->postEvent(LookoutPointAtEvent(toBase,EventBase::lookoutEGID,
00414 curReq->requestID, EventBase::deactivateETID));
00415 break;
00416 case PointAtRequest::storeImage:
00417 erouter->postEvent(LookoutSketchEvent
00418 (dynamic_cast<StoreImageRequest*>(curReq)->image,
00419 toBase,EventBase::lookoutEGID,
00420 curReq->requestID, EventBase::deactivateETID));
00421 break;
00422 case PointAtRequest::measureDist:
00423 erouter->postEvent(LookoutIREvent
00424 (dynamic_cast<const MeasureDistanceRequest*>(curReq)->val,
00425 toBase,EventBase::lookoutEGID,
00426 curReq->requestID, EventBase::deactivateETID));
00427 break;
00428 default:
00429 cout << "Lookout::requestComplete(): Unknown type returned by getPointAtType()\n";
00430 };
00431 }
00432 requests.pop();
00433
00434 curReq = NULL;
00435 if (!requests.empty())
00436 executeRequest();
00437 }
00438
00439
00440 void Lookout::processEvent(const EventBase& event) {
00441 cout << "Lookout::processEvent got " << event.getDescription() << endl;
00442 if (NULL==curReq) {
00443 cout << "Should not get any event when executing no request\n";
00444 return;
00445 }
00446
00447 switch (curReq->getHeadMotionType()) {
00448 case LookoutRequest::scan:
00449 processScan(event);
00450 break;
00451
00452
00453
00454
00455
00456
00457
00458
00459 case LookoutRequest::pointAt:
00460 case LookoutRequest::none:
00461 processPointAt(event); break;
00462 default:
00463 cout << "Lookout::processEvent: unknown request type: " << event.getName() << endl;
00464 break;
00465 };
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 Point Lookout::findLocationFor(float normX, float normY) {
00499 NEWMAT::ColumnVector ground_plane = kine->calculateGroundPlane();
00500 NEWMAT::ColumnVector cameraPt(4), groundPt(4);
00501 config->vision.computeRay(normX, normY, cameraPt(1),cameraPt(2),cameraPt(3));
00502 cameraPt(4) = 1;
00503 groundPt = kine->projectToPlane(CameraFrameOffset, cameraPt,
00504 BaseFrameOffset, ground_plane, BaseFrameOffset);
00505 return Point(groundPt(1),groundPt(2),groundPt(3),egocentric);
00506 }
00507
00508 void Lookout::scan() {
00509 cout << "scan speed: " << dynamic_cast<const ScanRequest*>(curReq)->scanSpeed
00510 << " (rad / millisec)\n";
00511 if (dynamic_cast<const ScanRequest*>(curReq)->getScanType()==ScanRequest::line) {
00512 const ScanAlongLineRequest& scanLineReq = *dynamic_cast<const ScanAlongLineRequest*>(curReq);
00513 scanAlongLine(scanLineReq.beginPt, scanLineReq.endPt);
00514 }
00515 else {
00516 const ScanAreaRequest& scanLineReq = *dynamic_cast<const ScanAreaRequest*>(curReq);
00517 scanArea(scanLineReq.left, scanLineReq.right, scanLineReq.far, scanLineReq.near);
00518 }
00519 }
00520
00521 void Lookout::scanAlongLine(const Point& startPt, const Point& endPt) {
00522 SharedObject<HeadPointerMC> hpmc;
00523
00524 hpmc->lookAtPoint(endPt.coordX(),endPt.coordY(),endPt.coordZ());
00525 const float pan1 = hpmc->getJointValue(PanOffset);
00526 const float tilt1 = hpmc->getJointValue(TiltOffset);
00527 const float roll1 = hpmc->getJointValue(RollOffset);
00528
00529 hpmc->lookAtPoint(startPt.coordX(),startPt.coordY(),startPt.coordZ());
00530 const float pan0 = hpmc->getJointValue(PanOffset);
00531 const float tilt0 = hpmc->getJointValue(TiltOffset);
00532 const float roll0 = hpmc->getJointValue(RollOffset);
00533
00534 const unsigned int time = (unsigned int)
00535 (sqrt((pan1-pan0)*(pan1-pan0)+(tilt1-tilt0)*(tilt1-tilt0)+(roll1-roll0)*(roll1-roll0))
00536 / dynamic_cast<const ScanRequest*>(curReq)->scanSpeed);
00537
00538 SharedObject<SmallMotionSequenceMC> scanmc;
00539 scanmc->pause();
00540 scanmc->setOutputCmd(HeadOffset+TiltOffset,tilt0);
00541 scanmc->setOutputCmd(HeadOffset+RollOffset,roll0);
00542 scanmc->setOutputCmd(HeadOffset+PanOffset,pan0);
00543 scanmc->advanceTime(time);
00544 scanmc->setOutputCmd(HeadOffset+TiltOffset,tilt1);
00545 scanmc->setOutputCmd(HeadOffset+RollOffset,roll1);
00546 scanmc->setOutputCmd(HeadOffset+PanOffset,pan1);
00547
00548 pointer_id = motman->addPrunableMotion(hpmc);
00549
00550 sequence_id = motman->addPrunableMotion(scanmc,MotionManager::kIgnoredPriority);
00551 }
00552
00553 void Lookout::scanArea(coordinate_t left, coordinate_t right,
00554 coordinate_t far, coordinate_t near) {
00555 const float& scanSpeed = dynamic_cast<const ScanRequest*>(curReq)->scanSpeed;
00556 static const float tiltJointValDelta = mathutils::deg2rad(15.0);
00557 const int tiltTime = (int) (tiltJointValDelta / scanSpeed);
00558 const float z_coord = -150;
00559 unsigned short counter = 1;
00560
00561 SharedObject<HeadPointerMC> hpmc;
00562 near = (near > 100) ? near : 100;
00563 const Point firstPt(near, (counter < 2) ? right : left, z_coord);
00564 hpmc->lookAtPoint(firstPt.coordX(),firstPt.coordY(),firstPt.coordZ());
00565 float tiltJointVal = hpmc->getJointValue(TiltOffset);
00566
00567
00568
00569
00570
00571 hpmc->lookAtPoint(far,left,z_coord);
00572 const float tiltJointValFar = hpmc->getJointValue(TiltOffset);
00573 const float panJointValLeftFar = hpmc->getJointValue(PanOffset);
00574 hpmc->lookAtPoint(far,right,z_coord);
00575 const float panJointValRiteFar = hpmc->getJointValue(PanOffset);
00576 hpmc->lookAtPoint(near,left,z_coord);
00577 float panJointValLeft = hpmc->getJointValue(PanOffset);
00578 hpmc->lookAtPoint(near,right,z_coord);
00579 float panJointValRite = hpmc->getJointValue(PanOffset);
00580 const int panTime = (int) (fabs(panJointValLeft-panJointValRite)/scanSpeed);
00581
00582 const float panJointLeftDelta = (tiltJointValFar-tiltJointVal < 0.01) ? 0 :
00583 (panJointValLeftFar-panJointValLeft)/(tiltJointValFar-tiltJointVal)*tiltJointValDelta;
00584 const float panJointRiteDelta = (tiltJointValFar-tiltJointVal < 0.01) ? 0 :
00585 (panJointValRiteFar-panJointValRite)/(tiltJointValFar-tiltJointVal)*tiltJointValDelta;
00586
00587 SharedObject<SmallMotionSequenceMC> scanmc;
00588 scanmc->pause();
00589 while (true) {
00590 counter++;
00591 counter = counter % 4;
00592 if (counter%2 == 1) {
00593 tiltJointVal += tiltJointValDelta;
00594 if (tiltJointVal > tiltJointValFar) break;
00595 if (counter == 1) panJointValRite += panJointRiteDelta;
00596 else panJointValLeft += panJointLeftDelta;
00597 }
00598 scanmc->advanceTime((counter%2==1) ? tiltTime : panTime);
00599 scanmc->setOutputCmd(HeadOffset+TiltOffset, tiltJointVal);
00600 scanmc->setOutputCmd(HeadOffset+RollOffset,0);
00601 scanmc->setOutputCmd(HeadOffset+PanOffset, (counter < 2) ? panJointValRite : panJointValLeft);
00602 }
00603 hpmc->lookAtPoint(firstPt.coordX(),firstPt.coordY(),firstPt.coordZ());
00604 pointer_id = motman->addPrunableMotion(hpmc);
00605
00606 sequence_id = motman->addPrunableMotion(scanmc,MotionManager::kIgnoredPriority);
00607 }
00608
00609 }