00001
00002 #include "Events/EventRouter.h"
00003 #include "Events/TextMsgEvent.h"
00004 #include "Events/LookoutEvents.h"
00005 #include "Motion/HeadPointerMC.h"
00006 #include "Motion/Kinematics.h"
00007 #include "Shared/mathutils.h"
00008 #include "Shared/Measures.h"
00009 #include "Shared/Config.h"
00010 #include "Shared/MarkScope.h"
00011
00012 #include "DualCoding/ShapeRoot.h"
00013 #include "DualCoding/ShapeLine.h"
00014 #include "DualCoding/ShapeEllipse.h"
00015 #include "DualCoding/ShapeBlob.h"
00016 #include "DualCoding/ShapeCylinder.h"
00017 #include "DualCoding/ShapePolygon.h"
00018 #include "DualCoding/ShapeSphere.h"
00019 #include "DualCoding/ShapeTarget.h"
00020 #include "DualCoding/ShapeMarker.h"
00021 #include "DualCoding/ShapeSift.h"
00022 #include "DualCoding/ShapeAprilTag.h"
00023 #include "DualCoding/Sketch.h"
00024 #include "DualCoding/visops.h"
00025 #include "DualCoding/VRmixin.h"
00026
00027 #include "Crew/LookoutRequests.h"
00028 #include "Crew/Lookout.h"
00029 #include "Crew/MapBuilder.h"
00030
00031 #include "Vision/SIFT/API/SiftTekkotsu.h"
00032 #include "Vision/AprilTags/TagDetector.h"
00033 #include "Vision/AprilTags/TagDetection.h"
00034
00035 using namespace std;
00036
00037 namespace DualCoding {
00038
00039 inline float distSq(const fmat::Column<4>& vec) {
00040 return vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2];
00041 }
00042
00043 MapBuilder::MapBuilder() :
00044 BehaviorBase("MapBuilder"),
00045 camSkS(VRmixin::getCamSkS()), camShS(camSkS.getDualSpace()),
00046 groundShS(VRmixin::getGroundShS()),
00047 localSkS(VRmixin::getLocalSkS()), localShS(localSkS.getDualSpace()),
00048 worldSkS(VRmixin::getWorldSkS()), worldShS(worldSkS.getDualSpace()),
00049 xres(camSkS.getWidth()), yres(camSkS.getHeight()),
00050 ground_plane(),
00051 theAgent(VRmixin::theAgent),
00052 localToWorldMatrix(fmat::Transform::identity()),
00053 worldToLocalMatrix(fmat::Transform::identity()),
00054 badGazePoints(),
00055 requests(), curReq(NULL), idCounter(0), maxDistSq(0), siftMatchers(),
00056 pointAtID(Lookout::invalid_LO_ID), scanID(Lookout::invalid_LO_ID),
00057 nextGazePoint() {}
00058
00059 void MapBuilder::preStart() {
00060 BehaviorBase::preStart();
00061 if ( verbosity & MBVstart )
00062 cout << "MapBuilder::start()\n";
00063
00064 camSkS.clear(); camShS.clear();
00065 groundShS.clear();
00066 localSkS.clear(); localShS.clear();
00067 worldSkS.clear(); worldShS.clear();
00068 badGazePoints.clear();
00069
00070 erouter->addListener(this,EventBase::textmsgEGID);
00071 erouter->addListener(this,EventBase::lookoutEGID);
00072 }
00073
00074 bool MapBuilder::retain = true;
00075
00076 MapBuilder::MapBuilderVerbosity_t MapBuilder::verbosity = (-1U & ~(MBVevents | MBVcomplete | MBVgroundPlane | MBVskipShape));
00077
00078
00079
00080
00081
00082
00083
00084
00085 void MapBuilder::stop() {
00086 cout << "MapBuilder::stop()\n";
00087 while(!requests.empty()) {
00088 delete requests.front();
00089 requests.pop();
00090 }
00091 curReq = NULL;
00092 BehaviorBase::stop();
00093 }
00094
00095 void MapBuilder::executeRequest(BehaviorBase *requestingBehavior, const MapBuilderRequest &req) {
00096 MapBuilderRequest newreq(req);
00097 newreq.requestingBehavior = requestingBehavior;
00098 executeRequest(newreq);
00099 }
00100
00101 unsigned int MapBuilder::executeRequest(const MapBuilderRequest& req, unsigned int *req_id) {
00102 MapBuilderRequest *newreq = new MapBuilderRequest(req);
00103 if ( !newreq->validateRequest() ) {
00104 cout << "*** Request rejected by MapBuilder" << endl;
00105 return 0;
00106 }
00107 const unsigned int this_request = ++idCounter;
00108 newreq->requestID = this_request;
00109 if ( req_id != NULL ) *req_id = this_request;
00110 requests.push(newreq);
00111 executeRequest();
00112 return this_request;
00113 }
00114
00115 void MapBuilder::executeRequest() {
00116 if ( curReq != NULL || requests.empty() ) return;
00117 curReq = requests.front();
00118 curReq->verbosity = (verbosity & ~curReq->clearVerbosity) | curReq->setVerbosity;
00119 if ( curReq->verbosity & MBVexecute )
00120 cout << "MapBuilder::executeRequest: execute " << curReq->requestID << endl;
00121 erouter->postEvent(EventBase::mapbuilderEGID, curReq->requestID, EventBase::activateETID,0);
00122
00123 calculateGroundPlane();
00124 maxDistSq = curReq->maxDist*curReq->maxDist;
00125
00126 if ( curReq->clearCamera ) {
00127 camShS.clear();
00128 camSkS.clear();
00129 curReq->gazePts.clear();
00130 curReq->baseToCamMats.clear();
00131 }
00132 if ( curReq->clearLocal ) {
00133 localShS.clear();
00134 localSkS.clear();
00135 }
00136 if ( curReq->clearWorld ) {
00137 worldShS.clear();
00138 worldSkS.clear();
00139 }
00140
00141 if ( curReq->immediateRequest )
00142 grabCameraImageAndGo();
00143 else if ( !curReq->searchArea.isValid() && curReq->worldTargets.size() == 0 )
00144 storeImage(false);
00145 else {
00146 defineGazePts();
00147 if ( curReq->doScan == true )
00148 return;
00149 else if ( curReq->worldTargets.size() > 0 )
00150 doNextSearch();
00151 else if ( determineNextGazePoint() )
00152 moveToNextGazePoint();
00153 else
00154 requestComplete();
00155 }
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 void MapBuilder::doEvent() {
00175 if ( curReq == NULL) return;
00176 if ( curReq->verbosity & MBVevents )
00177 cout << "MapBuilder got event " << event->getName() << endl;
00178
00179 switch ( event->getGeneratorID() ) {
00180 case EventBase::textmsgEGID:
00181 if ( strcmp(dynamic_cast<const TextMsgEvent&>(*event).getText().c_str(),"MoveHead") == 0 )
00182 moveToNextGazePoint(true);
00183 break;
00184
00185 case EventBase::lookoutEGID:
00186 if ( event->getSourceID() == pointAtID )
00187 processImage(dynamic_cast<const LookoutSketchEvent&>(*event));
00188 else if ( event->getSourceID() == scanID ) {
00189 const vector<Point>& pts = dynamic_cast<const LookoutScanEvent*>(event)->getTasks().front()->data;
00190 cout << " doScan found " << pts.size() << " interest points." << endl;
00191 curReq->gazePts.insert(curReq->gazePts.end(),pts.begin(), pts.end());
00192 }
00193 else {
00194 cout << "MapBuilder: unexpected Lookout event " << event->getDescription()
00195 << ", current pointAtID=" << pointAtID << ", scanID=" << scanID << endl;
00196 return;
00197 }
00198
00199 if ( requestExitTest() )
00200 requestComplete();
00201 else if ( curReq->worldTargets.size() > 0 )
00202 doNextSearch();
00203 else if ( determineNextGazePoint() )
00204 moveToNextGazePoint();
00205 else
00206 requestComplete();
00207 break;
00208
00209 default:
00210 cout << "MapBuilder received unexpected event: " << event->getDescription() << endl;
00211 }
00212 }
00213
00214 void MapBuilder::processImage(const LookoutSketchEvent &e) {
00215 if ( curReq->clearCamera ) {
00216 camSkS.clear(false);
00217 camShS.clear();
00218 }
00219 if ( curReq->rawY ) {
00220 NEW_SKETCH(rawY, uchar, VRmixin::sketchFromRawY());
00221 }
00222 NEW_SKETCH(camFrame, uchar, e.getSketch());
00223 if (curReq->userImageProcessing != NULL) (*curReq->userImageProcessing)();
00224 const fmat::Transform& camToBase = curReq->baseTransform * e.toBaseMatrix;
00225 const fmat::Transform baseToCam = camToBase.rigidInverse();
00226 getCameraShapes(camFrame);
00227 if (curReq->userCamProcessing != NULL) (*curReq->userCamProcessing)();
00228 if (curReq->getRequestType() > MapBuilderRequest::cameraMap) {
00229 projectToGround(camToBase);
00230 if (curReq->userGroundProcessing != NULL) (*curReq->userGroundProcessing)();
00231 filterGroundShapes(baseToCam);
00232 }
00233 switch ( curReq->getRequestType() ) {
00234 case MapBuilderRequest::cameraMap:
00235 case MapBuilderRequest::groundMap:
00236 break;
00237 case MapBuilderRequest::localMap:
00238 extendLocal(baseToCam);
00239 if (curReq->userLocalProcessing != NULL) (*curReq->userLocalProcessing)();
00240 break;
00241 case MapBuilderRequest::worldMap:
00242 extendLocal(baseToCam);
00243 if (curReq->userLocalProcessing != NULL) (*curReq->userLocalProcessing)();
00244 extendWorld(baseToCam);
00245 if (curReq->userWorldProcessing != NULL) (*curReq->userWorldProcessing)();
00246 }
00247 }
00248
00249 bool MapBuilder::determineNextGazePoint() {
00250 if (curReq->getRequestType() == MapBuilderRequest::worldMap) {
00251 worldShS.applyTransform(worldToLocalMatrix,egocentric);
00252 bool b = determineNextGazePoint(worldShS.allShapes()) || determineNextGazePoint(curReq->gazePts);
00253 worldShS.applyTransform(localToWorldMatrix,allocentric);
00254 return b;
00255 }
00256 else
00257 return determineNextGazePoint(localShS.allShapes()) || determineNextGazePoint(curReq->gazePts);
00258 }
00259
00260
00261 bool MapBuilder::determineNextGazePoint(const vector<ShapeRoot>& shapes) {
00262 if ( ! curReq->pursueShapes ) return false;
00263 HeadPointerMC headpointer_mc;
00264 for (vector<ShapeRoot>::const_iterator it = shapes.begin();
00265 it != shapes.end(); it++) {
00266
00267 if ((*it)->isType(lineDataType) || (*it)->isType(polygonDataType)) {
00268 const Shape<LineData>& ld = ShapeRootTypeConst(*it,LineData);
00269 const Shape<PolygonData>& pd = ShapeRootTypeConst(*it,PolygonData);
00270 bool isLine = (*it)->isType(lineDataType);
00271 EndPoint p[2] = { isLine ? ld->end1Pt(): pd->end1Pt(), isLine ? ld->end2Pt() : pd->end2Pt()};
00272 for (int i = 0; i < 2; i++) {
00273 if ( !p[i].isValid() && !isBadGazePoint(p[i] )
00274 && badGazePoints.end() == find(badGazePoints.begin(), badGazePoints.end(), (Point) p[i])) {
00275 cout << "Next gazepoint at endpoint" << (i+1) << " of shape id "
00276 << (*it)->getId() << " at " << p[i] << endl;
00277 if ( !headpointer_mc.lookAtPoint(p[i].coordX(),p[i].coordY(),p[i].coordZ()) ) {
00278 if ( curReq->verbosity & MBVbadGazePoint )
00279 cout << "MapBuilder noting unreachable gaze point " << (Point)p[i] << endl;
00280 badGazePoints.push_back((Point)p[i]);
00281 }
00282 nextGazePoint = p[i];
00283 return true;
00284 }
00285 }
00286 }
00287
00288 if ( (*it)->isType(blobDataType) ) {
00289 const Shape<BlobData>& bd = ShapeRootTypeConst(*it,BlobData);
00290 if ( ! (bd->bottomValid && bd->topValid && bd->leftValid && bd->rightValid) ) {
00291 Point bcentroid = bd->getCentroid();
00292 if ( ! isBadGazePoint(bcentroid) ) {
00293
00294 badGazePoints.push_back(bcentroid);
00295 cout << "Next gazepoint for blob at " << bcentroid << endl;
00296 nextGazePoint = bcentroid;
00297 return true;
00298 }
00299 }
00300 }
00301
00302 if ((!(*it)->isType(agentDataType)) &&
00303 (*it)->getLastMatchId() != 0 &&
00304 (*it)->getConfidence() <= 1 &&
00305 ! isBadGazePoint((*it)->getCentroid()) &&
00306 badGazePoints.end() == find(badGazePoints.begin(), badGazePoints.end(), (*it)->getCentroid())) {
00307 const Point pt = (*it)->getCentroid();
00308 cout << "Next gaze point is shape " << (*it)
00309 << " (confidence level: " << (*it)->getConfidence() << ")" << endl;
00310 cout << " at " << pt << endl;
00311 if (! headpointer_mc.lookAtPoint(pt.coordX(),pt.coordY(),pt.coordZ()))
00312 badGazePoints.push_back(pt);
00313 nextGazePoint = pt;
00314 return true;
00315 }
00316
00317 if ( curReq->verbosity & MBVskipShape )
00318 cout << "Skipping shape " << (*it)
00319 << " (confidence level: " << (*it)->getConfidence() << ")" << endl;
00320 }
00321 return false;
00322 }
00323
00324
00325 bool MapBuilder::determineNextGazePoint(vector<Point>& gazePts) {
00326 for ( vector<Point>::iterator it = gazePts.begin();
00327 it != gazePts.end(); it = gazePts.erase(it) )
00328 if ( ! isBadGazePoint(*it) ) {
00329 nextGazePoint = *it;
00330 return true;
00331 }
00332 return false;
00333 }
00334
00335 void MapBuilder::moveToNextGazePoint(const bool manualOverride) {
00336 if ( curReq == NULL ) {
00337 cout << "curReq == NULL in moveToNextGazePoint!" << endl;
00338 return;
00339 }
00340 if ( (curReq->verbosity & MBVnextGazePoint) || (curReq->manualHeadMotion && manualOverride==false) )
00341 cout << "moveToNextGazePoint " << nextGazePoint << endl;
00342 if ( curReq->manualHeadMotion && manualOverride==false ) {
00343 cout << "To proceed to this gaze point: !msg MoveHead" << endl;
00344 return;
00345 }
00346 else
00347 storeImage(true);
00348 }
00349
00350
00351 void MapBuilder::doNextSearch() {
00352 LookoutSearchRequest *curLSR = curReq->worldTargets.front();
00353 curReq->worldTargets.pop();
00354 pointAtID = VRmixin::lookout->executeRequest(*curLSR);
00355 }
00356
00357 bool MapBuilder::isBadGazePoint(const Point& Pt) const {
00358 const coordinate_t x = Pt.coordX();
00359 const coordinate_t y = Pt.coordY();
00360 return ( x*x + y*y > maxDistSq || x < -30.0);
00361 }
00362
00363 void MapBuilder::storeImage(bool useNextGazePoint) {
00364 LookoutPointRequest lreq;
00365 lreq.motionSettleTime = curReq->motionSettleTime;
00366 lreq.numSamples = curReq->numSamples;
00367 lreq.sampleInterval = curReq->sampleInterval;
00368 if ( useNextGazePoint )
00369 lreq.setTarget(nextGazePoint);
00370 else
00371 lreq.setHeadMotionType(LookoutRequestBase::noMotion);
00372 pointAtID = VRmixin::lookout->executeRequest(lreq);
00373 }
00374
00375 void MapBuilder::grabCameraImageAndGo() {
00376
00377
00378
00379
00380 pointAtID = 0;
00381 Sketch<uchar> camFrame(VRmixin::sketchFromSeg());
00382 #ifdef TGT_HAS_CAMERA
00383 const fmat::Transform camToBase = kine->linkToBase(CameraFrameOffset);
00384 #else
00385 const fmat::Transform &camToBase = fmat::Transform::identity();
00386 #endif
00387 LookoutSketchEvent dummy(true, camFrame, camToBase,
00388 EventBase::lookoutEGID, pointAtID, EventBase::deactivateETID);
00389 processImage(dummy);
00390 requestComplete();
00391 }
00392
00393 void MapBuilder::scanForGazePts() {
00394 LookoutScanRequest lreq;
00395 lreq.searchArea = curReq->searchArea;
00396 lreq.motionSettleTime = curReq->motionSettleTime;
00397 set<color_index> colors;
00398 for (map<ShapeType_t,set<color_index> >::const_iterator it1 = curReq->objectColors.begin();
00399 it1 != curReq->objectColors.end(); it1++)
00400 for (set<color_index>::const_iterator it2 = it1->second.begin();
00401 it2 != it1->second.end(); it2++)
00402 colors.insert(*it2);
00403 lreq.addTask(LookoutScanRequest::VisionRegionTask(colors,curReq->dTheta));
00404 scanID = VRmixin::lookout->executeRequest(lreq);
00405 }
00406
00407 void MapBuilder::extendLocal(const fmat::Transform& baseToCam) {
00408 vector<ShapeRoot> all = localShS.allShapes();
00409 removeNoise(localShS, baseToCam);
00410 matchSrcToDst(groundShS,localShS,curReq->objectColors[polygonDataType]);
00411
00412
00413
00414
00415 if ( curReq->gazePts.size() > 0 )
00416 curReq->gazePts.erase(curReq->gazePts.begin());
00417 curReq->baseToCamMats.push_back(baseToCam);
00418 }
00419
00420 void MapBuilder::extendWorld(const fmat::Transform& baseToCam) {
00421 worldShS.applyTransform(worldToLocalMatrix,egocentric);
00422 removeNoise(worldShS, baseToCam);
00423 matchSrcToDst(localShS,worldShS,curReq->objectColors[polygonDataType]);
00424 worldShS.applyTransform(localToWorldMatrix,allocentric);
00425 removeGazePts(curReq->gazePts,baseToCam);
00426 curReq->baseToCamMats.push_back(baseToCam);
00427 }
00428
00429 bool MapBuilder::requestExitTest() {
00430 if ( curReq->exitTest == NULL )
00431 return false;
00432 else
00433 return (*curReq->exitTest)();
00434 }
00435
00436 void MapBuilder::requestComplete() {
00437 const size_t reqID = curReq->requestID;
00438 if ( curReq->verbosity & MBVcomplete )
00439 cout << "MapBuilderRequest " << reqID << " complete\n";
00440 BehaviorBase* reqbeh = curReq->requestingBehavior;
00441 delete curReq;
00442 curReq = NULL;
00443 requests.pop();
00444 if ( reqbeh )
00445 erouter->postEvent(EventBase::mapbuilderEGID, (size_t)reqbeh, EventBase::statusETID,0);
00446 else {
00447 erouter->postEvent(EventBase::mapbuilderEGID, reqID, EventBase::statusETID,0);
00448 erouter->postEvent(EventBase::mapbuilderEGID, reqID, EventBase::deactivateETID,0);
00449 }
00450 if ( requests.empty() )
00451 VRmixin::lookout->relax();
00452 else
00453 executeRequest();
00454 }
00455
00456 void MapBuilder::setAgent(const Point &worldLocation, const AngTwoPi worldHeading, bool quiet) {
00457 if ( !quiet && ((curReq==NULL ? verbosity : curReq->verbosity) & MBVsetAgent) )
00458 cout << "Agent now at " << worldLocation << " hdg " << worldHeading
00459 << " (= " << float(worldHeading)*180/M_PI << " deg.)" << endl;
00460 theAgent->setCentroidPt(worldLocation);
00461 theAgent->setOrientation(worldHeading);
00462 const coordinate_t dx = worldLocation.coordX();
00463 const coordinate_t dy = worldLocation.coordY();
00464 const coordinate_t dz = worldLocation.coordZ();
00465 float const c = cos(worldHeading);
00466 float const s = sin(worldHeading);
00467 float localToWorld[] =
00468 {c, -s, 0, dx,
00469 s, c, 0, dy,
00470 0, 0, 1, dz};
00471 localToWorldMatrix = fmat::Matrix<4,3>(localToWorld).transpose();;
00472 worldToLocalMatrix = localToWorldMatrix.inverse();
00473 }
00474
00475 void MapBuilder::moveAgent(coordinate_t const local_dx, coordinate_t const local_dy, coordinate_t const local_dz, AngSignPi dtheta) {
00476 Point const agentLoc = theAgent->getCentroid();
00477 AngTwoPi const heading = theAgent->getOrientation();
00478 float const c = cos(heading);
00479 float const s = sin(heading);
00480 float const dx = local_dx*c + local_dy*-s;
00481 float const dy = local_dx*s + local_dy*c;
00482 setAgent(agentLoc + Point(dx,dy,local_dz,allocentric), heading+dtheta);
00483 }
00484
00485 void MapBuilder::importLocalToWorld() {
00486 worldShS.applyTransform(worldToLocalMatrix,egocentric);
00487 matchSrcToDst(localShS,worldShS);
00488 worldShS.applyTransform(localToWorldMatrix,allocentric);
00489 }
00490
00491 ShapeRoot MapBuilder::importLocalShapeToWorld(const ShapeRoot &localShape) {
00492 ShapeRoot worldShape(worldShS.importShape(localShape));
00493 worldShape->applyTransform(localToWorldMatrix, allocentric);
00494 return worldShape;
00495 }
00496
00497 ShapeRoot MapBuilder::importWorldToLocal(const ShapeRoot &worldShape) {
00498 ShapeRoot localShape(localShS.importShape(worldShape));
00499 localShape->applyTransform(worldToLocalMatrix,egocentric);
00500 return localShape;
00501 }
00502
00503 bool MapBuilder::isPointVisible(const Point &pt, const fmat::Transform& baseToCam, float maxDistanceSq) {
00504 fmat::Column<3> camCoords = baseToCam*fmat::pack(pt.coordX(),pt.coordY(),pt.coordZ());
00505
00506 if ( fmat::SubVector<2>(camCoords).sumSq() >= maxDistanceSq )
00507 return false;
00508 float normX,normY;
00509 config->vision.computePixel(camCoords[0],camCoords[1],camCoords[2],normX,normY);
00510 return (fabs(normX) < 0.9f && fabs(normY) < config->vision.aspectRatio*.9f);
00511 }
00512
00513 bool MapBuilder::isLineVisible(const LineData& ln, const fmat::Transform& baseToCam) {
00514 float normX1,normX2,normY1,normY2;
00515 fmat::Column<3> camCoords;
00516 Point pt = ln.end1Pt();
00517 camCoords = baseToCam*fmat::pack(pt.coordX(),pt.coordY(),pt.coordZ());
00518 config->vision.computePixel(camCoords[0],camCoords[1],camCoords[2],normX1,normY1);
00519 pt = ln.end2Pt();
00520 camCoords = baseToCam*fmat::pack(pt.coordX(),pt.coordY(),pt.coordZ());
00521 config->vision.computePixel(camCoords[0],camCoords[1],camCoords[2],normX2,normY2);
00522 const float xRange = 0.9f;
00523 const float yRange = config->vision.aspectRatio*.9f;
00524 const bool end1Pt_visible = fabs(normX1) < xRange && fabs(normY1) < yRange;
00525 const bool end2Pt_visible = fabs(normX2) < xRange && fabs(normY2) < yRange;
00526 if (end1Pt_visible && end2Pt_visible)
00527 return true;
00528 LineData lnCam(VRmixin::groundShS, Point(normX1,normY1), Point(normX2,normY2));
00529
00530 LineData camBounds[] = {LineData(VRmixin::groundShS, Point( xRange, yRange), Point( xRange,-yRange)),
00531 LineData(VRmixin::groundShS, Point( xRange,-yRange), Point(-xRange,-yRange)),
00532 LineData(VRmixin::groundShS, Point(-xRange,-yRange), Point(-xRange, yRange)),
00533 LineData(VRmixin::groundShS, Point(-xRange, yRange), Point( xRange, yRange))};
00534 unsigned int ptCount = 0;
00535 Point p[2];
00536
00537 if (end1Pt_visible) p[ptCount++].setCoords(normX1,normY1,0);
00538 else if (end2Pt_visible) p[ptCount++].setCoords(normX2,normY2,0);
00539 for (int i = 0; i < 4; i++)
00540 if (camBounds[i].intersectsLine(lnCam)) {
00541 p[ptCount++].setCoords(lnCam.intersectionWithLine(camBounds[i]));
00542
00543 if (ptCount > 1)
00544 return p[0].distanceFrom(p[1]) > 0.1;
00545 }
00546 return false;
00547 }
00548
00549 bool MapBuilder::isShapeVisible(const ShapeRoot &ground_shape, const fmat::Transform& baseToCam,
00550 float maxDistanceSq) {
00551 if (ground_shape->isType(lineDataType))
00552 return isLineVisible(ShapeRootTypeConst(ground_shape,LineData).getData(), baseToCam);
00553 else if (ground_shape->isType(polygonDataType)) {
00554 const Shape<PolygonData>& polygon = ShapeRootTypeConst(ground_shape,PolygonData);
00555 for (vector<LineData>::const_iterator edge_it = polygon->getEdges().begin();
00556 edge_it != polygon->getEdges().end(); edge_it++)
00557 if (isLineVisible(*edge_it,baseToCam))
00558 return true;
00559 return false;
00560 }
00561 else
00562 return isPointVisible(ground_shape->getCentroid(), baseToCam, maxDistanceSq);
00563 }
00564
00565
00566
00567
00568
00569 void MapBuilder::filterGroundShapes(const fmat::Transform& baseToCam) {
00570
00571 vector<ShapeRoot> ground_shapes = groundShS.allShapes();
00572
00573 for (vector<ShapeRoot>::iterator ground_it = ground_shapes.begin();
00574 ground_it != ground_shapes.end(); ground_it++ ) {
00575 const coordinate_t cenX = (*ground_it)->getCentroid().coordX();
00576 const coordinate_t cenY = (*ground_it)->getCentroid().coordY();
00577 if (cenX*cenX + cenY*cenY > maxDistSq) {
00578 if ( curReq->verbosity & MBVnotAdmissible )
00579 cout << "ground shape " << (*ground_it)->getId() << " (lastMatch "
00580 << (*ground_it)->getLastMatchId() << ") too far, delete\n";
00581 ground_it->deleteShape();
00582 }
00583 fmat::Column<3> coords = Kinematics::pack(cenX,cenY,(*ground_it)->getCentroid().coordZ());
00584 coords = baseToCam*coords;
00585 if (coords[2] < 0) {
00586 if ( curReq->verbosity & MBVprojectionFailed )
00587 cout << "Projection failed for ground shape " << (*ground_it)->getId()
00588 << ": " << coords
00589 << " (lastMatch " << (*ground_it)->getLastMatchId() << "): deleting\n";
00590 ground_it->deleteShape();
00591 }
00592
00593 else if ((*ground_it)->isType(lineDataType)) {
00594 Shape<LineData>& line = ShapeRootType(*ground_it,LineData);
00595 const coordinate_t e1x = line->end1Pt().coordX();
00596 const coordinate_t e1y = line->end1Pt().coordY();
00597 const coordinate_t e2x = line->end2Pt().coordX();
00598 const coordinate_t e2y = line->end2Pt().coordY();
00599 if (e1x*e1x + e1y*e1y > maxDistSq && e2x*e2x + e2y*e2y > maxDistSq)
00600 ground_it->deleteShape();
00601 else if (e1x*e1x + e1y*e1y > maxDistSq || e2x*e2x + e2y*e2y > maxDistSq) {
00602
00603
00604 vector<float> line_abc = line->lineEquation_abc();
00605 Point pt;
00606 const EndPoint* far_ept = (e1x*e1x + e1y*e1y > maxDistSq) ? &line->end1Pt() : &line->end2Pt();
00607 if (line_abc[1] == 0.0) {
00608 const coordinate_t y_abs = sqrt(maxDistSq - line_abc[2]*line_abc[2]);
00609 if (fabs(far_ept->coordY()-y_abs) < fabs(far_ept->coordY()+y_abs))
00610 pt.setCoords(e1x, y_abs, far_ept->coordZ());
00611 else
00612 pt.setCoords(e1x, -y_abs, far_ept->coordZ());
00613 }
00614 else {
00615 const float a = - line_abc[0]/line_abc[1];
00616 const float b = line_abc[2]/line_abc[1];
00617 const coordinate_t x1 = (std::sqrt((a*a+1)*maxDistSq-b*b)-a*b)/(a*a+1);
00618 const coordinate_t x2 = (-std::sqrt((a*a+1)*maxDistSq-b*b)-a*b)/(a*a+1);
00619 if (std::abs(far_ept->coordX()-x1) < std::abs(far_ept->coordX()-x2))
00620 pt.setCoords(x1, a*x1+b, far_ept->coordZ());
00621 else
00622 pt.setCoords(x2, a*x2+b, far_ept->coordZ());
00623 }
00624 EndPoint temp_endPt(pt);
00625 temp_endPt.setValid(false);
00626
00627
00628 if (e1x*e1x + e1y*e1y > maxDistSq)
00629 line->setEndPts(temp_endPt, line->end2Pt());
00630 else
00631 line->setEndPts(line->end1Pt(), temp_endPt);
00632 badGazePoints.push_back(pt);
00633 }
00634 }
00635 }
00636 }
00637
00638 void MapBuilder::calculateGroundPlane() {
00639 switch(curReq->groundPlaneAssumption) {
00640 case MapBuilderRequest::onLegs:
00641 ground_plane = kine->calculateGroundPlane();
00642 if ( curReq->verbosity & MBVgroundPlane )
00643 cout << "Calculated ground plane: " << ground_plane << endl;
00644 break;
00645 case MapBuilderRequest::onStand:
00646 #if defined(TGT_ERS210) || defined(TGT_ERS220) || defined(TGT_ERS2xx)
00647 ground_plane = PlaneEquation(0,0,-1,200);
00648 #else
00649 ground_plane = PlaneEquation(0,0,-1,170);
00650 #endif
00651
00652 break;
00653 case MapBuilderRequest::onWheel:
00654 #ifdef TGT_REGIS1
00655 std::cout << "Target Regis 1 Mapping";
00656 ground_plane = fmat::pack<float>(0,0,(-1/85.0),1);
00657 #endif
00658 break;
00659 case MapBuilderRequest::custom:
00660 ground_plane = curReq->customGroundPlane;
00661 }
00662 }
00663
00664 void MapBuilder::projectToGround(const fmat::Transform& camToBase) {
00665 VRmixin::projectToGround(camToBase, ground_plane);
00666 }
00667
00668 ShapeRoot MapBuilder::projectToLocal(ShapeRoot &shape) {
00669 #ifdef TGT_HAS_CAMERA
00670 fmat::Transform camToBase = kine->linkToBase(CameraFrameOffset);
00671 #else
00672 fmat::Transform camToBase = fmat::Transform::identity();
00673 #endif
00674 ground_plane = kine->calculateGroundPlane();
00675
00676 groundShS.importShape(shape);
00677 ShapeRoot &newShape = groundShS.allShapes().back();
00678 newShape->projectToGround(camToBase, ground_plane);
00679 localShS.importShape(newShape);
00680 return localShS.allShapes().back();
00681 }
00682
00683 void MapBuilder::matchSrcToDst(ShapeSpace &srcShS, ShapeSpace &dstShS,
00684 set<color_index> polCols, bool mergeSrc, bool mergeDst) {
00685 vector<ShapeRoot> src_shapes = srcShS.allShapes();
00686 vector<ShapeRoot> dst_shapes = dstShS.allShapes();
00687 vector<LineData> polygon_edges;
00688
00689
00690 std::set<int> markedForDeletion;
00691 vector<ShapeRoot> cleaned_src;
00692 for (vector<ShapeRoot>::iterator src_it = src_shapes.begin();
00693 src_it != src_shapes.end(); src_it++ ) {
00694 if (!(*src_it)->isAdmissible()) {
00695 if (curReq && curReq->verbosity & MBVnotAdmissible )
00696 cout << "shape " << (*src_it)->getId() << " (lastMatch "
00697 << (*src_it)->getLastMatchId() << ") is not admissible." << endl;
00698
00699 markedForDeletion.insert((*src_it)->getId());
00700 }
00701 else if ((*src_it)->isType(polygonDataType)) {
00702 const vector<LineData>& lines = ShapeRootTypeConst(*src_it, PolygonData)->getEdges();
00703 polygon_edges.insert(polygon_edges.end(), lines.begin(), lines.end());
00704 markedForDeletion.insert((*src_it)->getId());
00705 }
00706 else if ((*src_it)->isType(lineDataType)) {
00707 const color_index colorIndex = ProjectInterface::getColorIndex((*src_it)->getColor());
00708 if ( polCols.end() != find(polCols.begin(), polCols.end(), colorIndex)) {
00709 polygon_edges.push_back(ShapeRootTypeConst(*src_it, LineData).getData());
00710 markedForDeletion.insert((*src_it)->getId());
00711 }
00712 }
00713 }
00714
00715 for ( vector<ShapeRoot>::iterator it = src_shapes.begin();
00716 it != src_shapes.end(); it++ )
00717 if ( markedForDeletion.find((*it)->getId()) == markedForDeletion.end() )
00718 cleaned_src.push_back(*it);
00719 src_shapes = cleaned_src;
00720
00721
00722 if (mergeSrc) {
00723 markedForDeletion.clear();
00724 cleaned_src.clear();
00725 for ( vector<ShapeRoot>::iterator it = src_shapes.begin();
00726 it != src_shapes.end(); it++ )
00727 for ( vector<ShapeRoot>::iterator it2 = it+1;
00728 it2 != src_shapes.end(); it2++)
00729 if ((*it2)->isMatchFor(*it) && (*it)->updateParams(*it2)) {
00730 if (curReq && curReq->verbosity & MBVshapesMerge )
00731 cout << "merging shape " << (*it)->getId() << " (from " << (*it)->getLastMatchId()
00732 << ") and shape " << (*it2)->getId() << " (from " << (*it2)->getLastMatchId() << ")" << endl;
00733 markedForDeletion.insert((*it2)->getId());
00734 }
00735
00736 for ( vector<ShapeRoot>::iterator it = src_shapes.begin();
00737 it != src_shapes.end(); it++ )
00738 if ( markedForDeletion.find((*it)->getId()) == markedForDeletion.end() )
00739 cleaned_src.push_back(*it);
00740 src_shapes = cleaned_src;
00741 }
00742
00743
00744 markedForDeletion.clear();
00745 cleaned_src.clear();
00746 vector<Shape<PolygonData> > existingPolygons;
00747 for (vector<ShapeRoot>::iterator dst_it = dst_shapes.begin();
00748 dst_it != dst_shapes.end(); dst_it++ ) {
00749 if ((*dst_it)->isType(polygonDataType)) {
00750 existingPolygons.push_back(ShapeRootType(*dst_it,PolygonData));
00751 continue;
00752 }
00753 if ( (*dst_it)->isType(localizationParticleDataType) )
00754 continue;
00755 for (vector<ShapeRoot>::iterator src_it = src_shapes.begin();
00756 src_it != src_shapes.end(); src_it++)
00757 if ((*dst_it)->isMatchFor(*src_it) && (*dst_it)->updateParams((*src_it))) {
00758 (*dst_it)->increaseConfidence(2);
00759 (*dst_it)->setLastMatchId((*src_it)->getId());
00760 if (curReq && curReq->verbosity & MBVshapeMatch )
00761 cout << "Matched src shape " << (*src_it)->getId() << " (lastMatch " << (*src_it)->getLastMatchId()
00762 << ") to dst shape " << (*dst_it)->getId() << endl;
00763 markedForDeletion.insert((*src_it)->getId());
00764 }
00765 }
00766
00767
00768 for ( vector<ShapeRoot>::iterator it = src_shapes.begin();
00769 it != src_shapes.end(); it++ )
00770 if ( markedForDeletion.find((*it)->getId()) == markedForDeletion.end() )
00771 cleaned_src.push_back(*it);
00772 src_shapes = cleaned_src;
00773
00774
00775 vector<ShapeRoot> deletedPolygons;
00776
00777 vector<ShapeRoot> newPolygons = PolygonData::formPolygons(polygon_edges,existingPolygons,deletedPolygons);
00778
00779 for (vector<ShapeRoot>::iterator delete_it = deletedPolygons.begin();
00780 delete_it != deletedPolygons.end(); delete_it++)
00781 delete_it->deleteShape();
00782 dstShS.importShapes(newPolygons);
00783 dstShS.importShapes(src_shapes);
00784 if (curReq && curReq->verbosity & MBVimportShapes )
00785 cout << "Imported " << (src_shapes.size()+newPolygons.size()) << " new shape(s) from "
00786 << srcShS.name << "ShS to " << dstShS.name << "ShS\n";
00787
00788
00789
00790 if (mergeDst) {
00791 dst_shapes = dstShS.allShapes();
00792 for ( vector<ShapeRoot>::iterator it = dst_shapes.begin();
00793 it != dst_shapes.end(); it++ )
00794 if ( ! (*it)->isType(localizationParticleDataType) )
00795 for ( vector<ShapeRoot>::iterator it2 = it+1;
00796 it2 < dst_shapes.end(); it2++)
00797 if ((*it2)->isMatchFor(*it) && (*it)->updateParams(*it2,true)) {
00798 cout << "Matched src shape " << (*it)->getId() << " (lastMatch "
00799 << (*it)->getLastMatchId()<< ") is a match for "
00800 << (*it2)->getId() << " (lastMatch "
00801 << (*it2)->getLastMatchId() << "), delete\n";
00802 it2->deleteShape();
00803 }
00804 }
00805 }
00806
00807
00808
00809 void MapBuilder::removeNoise(ShapeSpace& ShS, const fmat::Transform& baseToCam) {
00810
00811 vector<ShapeRoot> shapes = ShS.allShapes();
00812 for (vector<ShapeRoot>::iterator it = shapes.begin();
00813 it != shapes.end(); it++ ) {
00814
00815
00816 if (curReq->objectColors[(*it)->getType()].find(ProjectInterface::getColorIndex((*it)->getColor())) ==
00817 curReq->objectColors[(*it)->getType()].end())
00818 continue;
00819 if ((*it)->isType(polygonDataType)) {
00820 Shape<PolygonData>& polygon = ShapeRootType(*it,PolygonData);
00821 vector<LineData>& edges = polygon->getEdgesRW();
00822 unsigned int edge_index = 0;
00823 for (vector<LineData>::iterator edge_it = edges.begin();
00824 edge_it != edges.end(); edge_it++, edge_index++) {
00825 if (isLineVisible(*edge_it, baseToCam)) {
00826 if ( curReq->verbosity & MBVshouldSee )
00827 cout << "edge " << edge_index << " of polygon " << (*it)->getId() << "(confidence: "
00828 << edge_it->getConfidence() << ") should be visible in this frame" << endl;
00829 edge_it->decreaseConfidence();
00830 }
00831 }
00832 vector<ShapeRoot> brokenPolygons = polygon->updateState();
00833 ShS.importShapes(brokenPolygons);
00834 if (!polygon->isAdmissible()) {
00835 if ( curReq->verbosity & MBVdeleteShape )
00836 cout << "delete polygon " << (*it)->getId() << " from map" << endl;
00837 it->deleteShape();
00838 }
00839 }
00840 else if ((!(*it)->isType(agentDataType)) && isShapeVisible(*it, baseToCam, maxDistSq)){
00841 (*it)->decreaseConfidence();
00842 if ((*it)->getConfidence() < 0 ) {
00843 if ( curReq->verbosity & MBVshouldSee )
00844 cout << "shape " << (*it)->getId() << "(confidence: " << (*it)->getConfidence()
00845 << ") should be visible in this frame; deleted" << endl;
00846 it->deleteShape();
00847 }
00848 }
00849 }
00850 }
00851
00852
00853
00854 void MapBuilder::defineGazePts() {
00855 const ShapeRoot &sArea = curReq->searchArea;
00856 if ( !sArea.isValid() )
00857 return;
00858 else if ( curReq->doScan == true )
00859 scanForGazePts();
00860 else
00861 switch ( sArea->getType() ) {
00862
00863 case pointDataType:
00864 curReq->gazePts.push_back(sArea->getCentroid());
00865 break;
00866
00867 case lineDataType: {
00868 static const float meshSize=50;
00869 const Shape<LineData>& line = ShapeRootTypeConst(sArea,LineData);
00870 if ( curReq->doScan == true )
00871 scanForGazePts();
00872 else {
00873 int numIntervals = (int) (line->getLength()/meshSize);
00874 const EndPoint& ep1 = line->end1Pt();
00875 const EndPoint& ep2 = line->end2Pt();
00876 curReq->gazePts.push_back(ep1);
00877 for (int i = 1; i < numIntervals; i++)
00878 curReq->gazePts.push_back((ep1*i + ep2*(numIntervals-i))/numIntervals);
00879 curReq->gazePts.push_back(ep2);
00880 }
00881 }
00882 break;
00883
00884 case polygonDataType:
00885 if ( curReq->doScan == true )
00886 scanForGazePts();
00887 else {
00888 const Shape<PolygonData> &poly = ShapeRootTypeConst(sArea,PolygonData);
00889 const vector<Point> &verts = poly->getVertices();
00890 curReq->gazePts.insert(curReq->gazePts.end(),verts.begin(),verts.end());
00891 }
00892 break;
00893
00894 default:
00895 cerr << "ERROR MapBuilder::defineGazePts: Supported searchArea shapes are Point, Line, and Polygon\n";
00896 requestComplete();
00897 break;
00898 }
00899 }
00900
00901 void MapBuilder::removeGazePts(vector<Point> &gazePts, const fmat::Transform& baseToCam) {
00902 if (curReq->removePts) {
00903 int num_points_seen = 0;
00904 for ( vector<Point>::iterator it = gazePts.begin();
00905 it != gazePts.end(); it++ ) {
00906 if ( isPointVisible(*it,baseToCam,maxDistSq) ) {
00907 cout << "Removing already-visible gaze point " << *it << endl;
00908 num_points_seen++;
00909 gazePts.erase(it--);
00910 }
00911 }
00912
00913
00914 }
00915 }
00916
00917
00918
00919
00920
00921 void MapBuilder::printShS(ShapeSpace &ShS) const {
00922 cout << "MapBuilder::printShS()" << endl;
00923 unsigned int line_count = 0;
00924 vector<ShapeRoot> shapes = ShS.allShapes();
00925 for (vector<ShapeRoot>::const_iterator it = shapes.begin();
00926 it != shapes.end(); it++) {
00927 if ((*it)->isType(lineDataType)) {
00928 const Shape<LineData>& ld = ShapeRootTypeConst(*it,LineData);
00929 cout << (*it)->getId() << " " << lineDataType << " "
00930 << ProjectInterface::getColorIndex((*it)->getColor())
00931 << " " << ld->end1Pt().coordX() << " " << ld->end1Pt().coordY()
00932 << " " << ++line_count << " " << ld->getLength() << " " << ld->end1Pt().isValid() << endl;
00933 cout << (*it)->getId() << " " << lineDataType << " "
00934 << ProjectInterface::getColorIndex((*it)->getColor())
00935 << " " << ld->end2Pt().coordX() << " " << ld->end2Pt().coordY()
00936 << " " << line_count << " " << ld->getLength() << " " << ld->end2Pt().isValid() << endl;
00937 }
00938 else {
00939 cout << (*it)->getId() << " " << (*it)->getType() << " "
00940 << ProjectInterface::getColorIndex((*it)->getColor())
00941 << " " << (*it)->getCentroid().coordX() << " " << (*it)->getCentroid().coordY() << endl;
00942 }
00943 }
00944 }
00945
00946
00947
00948
00949 void MapBuilder::getCameraShapes(const Sketch<uchar>& camFrame) {
00950 getCamLines(camFrame, curReq->objectColors[lineDataType], curReq->occluderColors[lineDataType]);
00951 getCamEllipses(camFrame, curReq->objectColors[ellipseDataType], curReq->occluderColors[ellipseDataType]);
00952 getCamPolygons(camFrame, curReq->objectColors[polygonDataType], curReq->occluderColors[polygonDataType]);
00953 getCamSpheres(camFrame, curReq->objectColors[sphereDataType], curReq->occluderColors[sphereDataType]);
00954 getCamCylinders(camFrame, curReq->objectColors[cylinderDataType], curReq->assumedCylinderHeights, curReq->minBlobAreas);
00955 getCamWalls(camFrame, curReq->floorColor);
00956 if ( curReq->numSamples == 1 && !curReq->searchArea.isValid() &&
00957 !curReq->objectColors[blobDataType].empty() && curReq->userImageProcessing == NULL )
00958 getCamBlobs(curReq->objectColors[blobDataType]);
00959 else
00960 getCamBlobs(camFrame, curReq->objectColors[blobDataType], curReq->minBlobAreas, curReq->blobOrientations, curReq->assumedBlobHeights);
00961 getCamTargets(camFrame, curReq->objectColors[targetDataType], curReq->occluderColors[targetDataType]);
00962 getCamMarkers(camFrame, curReq->objectColors[markerDataType], curReq->occluderColors[markerDataType],
00963 curReq->markerTypes);
00964
00965 NEW_SKETCH_N(rawY, uchar, VRmixin::sketchFromRawY());
00966 getCamSiftObjects(rawY, curReq->siftDatabasePath, curReq->siftObjectNames);
00967 getCamAprilTags(rawY);
00968 }
00969
00970 vector<Shape<LineData> > MapBuilder::getCamLines(const Sketch<uchar> &camFrame, const set<color_index>& objectColors,
00971 const set<color_index>& occluderColors) const {
00972 vector<Shape<LineData> > linesReturned;
00973 if ( objectColors.empty() )
00974 return linesReturned;
00975 if ( curReq->verbosity & MBVshapeSearch )
00976 cout << "*** Find the lines ***" << endl;
00977 NEW_SKETCH_N(occluders,bool,visops::zeros(camFrame));
00978 for ( set<color_index>::const_iterator it = occluderColors.begin();
00979 it != occluderColors.end(); it++ )
00980 occluders |= visops::minArea(visops::colormask(camFrame,*it));
00981
00982 for (set<color_index>::const_iterator it = objectColors.begin();
00983 it != objectColors.end(); it++) {
00984 NEW_SKETCH_N(colormask,bool,visops::colormask(camFrame,*it));
00985 NEW_SKETCH_N(cleancolor,bool,visops::minArea(colormask));
00986 NEW_SKETCH_N(fatmask,bool,visops::fillin(cleancolor,1,2,8));
00987 NEW_SKETCH_N(skel,bool,visops::skel(fatmask));
00988 vector<Shape<LineData> > line_shapes(LineData::extractLines(skel,cleancolor|occluders));
00989 linesReturned.insert(linesReturned.end(), line_shapes.begin(), line_shapes.end());
00990 if ( curReq->verbosity & MBVshapesFound )
00991 cout << "Found " << line_shapes.size() << " "
00992 << ProjectInterface::getColorName(*it) << " lines." << endl;
00993 }
00994 return linesReturned;
00995 }
00996
00997 vector<Shape<EllipseData> >
00998 MapBuilder::getCamEllipses(const Sketch<uchar> &camFrame,
00999 const set<color_index>& objectColors, const set<color_index>& ) const {
01000 vector<Shape<EllipseData> > ellipses;
01001 if (objectColors.empty())
01002 return ellipses;
01003 if ( curReq->verbosity & MBVshapeSearch )
01004 cout << "*** Find the ellipses ***" << endl;
01005 for (set<color_index>::const_iterator it = objectColors.begin();
01006 it !=objectColors.end(); it++) {
01007 NEW_SKETCH_N(colormask,bool,visops::colormask(camFrame,*it));
01008 vector<Shape<EllipseData> > ellipse_shapes = EllipseData::extractEllipses(colormask);
01009 ellipses.insert(ellipses.end(), ellipse_shapes.begin(),ellipse_shapes.end());
01010 if ( curReq->verbosity & MBVshapesFound )
01011 cout << "Found " << ellipse_shapes.size() << " "
01012 << ProjectInterface::getColorName(*it) << " ellipses." << endl;
01013 }
01014 return ellipses;
01015 }
01016
01017 void MapBuilder::getCamPolygons(const Sketch<uchar> &camFrame,
01018 const set<color_index>& objectColors, const set<color_index>& occluderColors) const {
01019 vector<Shape<PolygonData> > polygons;
01020 if ( objectColors.empty() )
01021 return;
01022 if ( curReq->verbosity & MBVshapeSearch )
01023 cout << "*** Find the polygons ***" << endl;
01024 NEW_SKETCH_N(occluders,bool,visops::zeros(camFrame));
01025 for ( set<color_index>::const_iterator it = occluderColors.begin();
01026 it !=occluderColors.end(); it++ )
01027 occluders |= visops::colormask(camFrame,*it);
01028
01029 for (set<color_index>::const_iterator it = objectColors.begin();
01030 it !=objectColors.end(); it++) {
01031 NEW_SKETCH_N(colormask,bool,visops::colormask(camFrame,*it));
01032 NEW_SKETCH_N(fatmask,bool,visops::fillin(colormask,1,2,8));
01033 NEW_SKETCH_N(skel,bool,visops::skel(fatmask));
01034 NEW_SKETCH_N(fatskel,bool,visops::fillin(skel,1,2,8));
01035
01036 vector<Shape<LineData> > polygon_lines = PolygonData::extractPolygonEdges(fatskel,fatmask|occluders);
01037 polygons.insert(polygons.end(), polygon_lines.begin(), polygon_lines.end());
01038 if ( curReq->verbosity & MBVshapesFound )
01039 cout << "Found " << polygon_lines.size() << " lines." << endl;
01040 }
01041 }
01042
01043 void MapBuilder::getCamSpheres(const Sketch<uchar> &camFrame,
01044 const set<color_index>& objectColors, const set<color_index>& ) const {
01045 vector<Shape<SphereData> > spheres;
01046 if ( objectColors.empty() )
01047 return;
01048 if ( curReq->verbosity & MBVshapeSearch )
01049 cout << "*** Find the spheres ***" << endl;
01050 for (set<color_index>::const_iterator it = objectColors.begin();
01051 it !=objectColors.end(); it++) {
01052 NEW_SKETCH_N(colormask,bool,visops::colormask(camFrame,*it));
01053 vector<Shape<SphereData> > sphere_shapes = SphereData::extractSpheres(colormask);
01054 spheres.insert(spheres.end(), spheres.begin(), spheres.end());
01055 if ( curReq->verbosity & MBVshapesFound )
01056 cout << "Found " << sphere_shapes.size() << " spheres." << endl;
01057 }
01058 }
01059
01060 void MapBuilder::getCamCylinders(const Sketch<uchar>& camFrame,
01061 const set<color_index>& colors,
01062 const map<color_index,coordinate_t>& assumedHeights,
01063 const map<color_index,int>& minCylinderAreas) {
01064 if ( colors.empty() )
01065 return;
01066 if ( curReq->verbosity & MBVshapeSearch )
01067 cout << "*** Find the cylinders ***" << endl;
01068 int const maxcylinders = 50;
01069 vector<Shape<CylinderData> > result(CylinderData::extractCylinders(camFrame, colors, assumedHeights, minCylinderAreas, maxcylinders));
01070 if ( curReq->verbosity & MBVshapesFound )
01071 if ( !result.empty() )
01072 cout << "Found " << result.size() << " cylinders." << endl;
01073 }
01074
01075 vector<Shape<LineData> >
01076 MapBuilder::getCamWalls(const Sketch<uchar> &camFrame, unsigned int floorColor) const {
01077 if (floorColor == 0)
01078 return vector<Shape<LineData> >();
01079 if ( curReq->verbosity & MBVshapeSearch )
01080 cout << "*** Find the walls ***" << endl;
01081 const int camFrame_offset = 8;
01082
01083 NEW_SKETCH_N(colormask,bool,visops::colormask(camFrame,floorColor));
01084 NEW_SKETCH_N(fillinmask ,bool,visops::fillin(colormask, 1, 6, 8));
01085 NEW_SKETCH_N(fillinmask2 ,bool,visops::fillin(fillinmask, 2, 3, 8));
01086 NEW_SKETCH_N(edgemask ,bool,visops::fillin(fillinmask2, 1, 5, 7));
01087 NEW_SKETCH_N(edgemask2 ,bool,visops::non_bounds(edgemask, camFrame_offset));
01088
01089 NEW_SKETCH_N(occluders_floor, bool, (camFrame != uchar(0)) & (camFrame != uchar(floorColor)));
01090 NEW_SKETCH_N(occ_mask ,bool,visops::fillin(occluders_floor, 1, 8, 8));
01091 usint const clear_dist = 15;
01092 Sketch<bool> not_too_close = (visops::mdist(occ_mask) >= clear_dist);
01093 edgemask2 &= not_too_close;
01094
01095 NEW_SKETCH_N(fatmask ,bool,visops::fillin(edgemask2,2,2,8));
01096 NEW_SKETCH_N(skel,bool,visops::skel(fatmask));
01097 NEW_SKETCH_N(fatskel,bool,visops::fillin(skel,1,2,8));
01098
01099 vector<Shape<LineData> > wall_bounds = PolygonData::extractPolygonEdges(fatskel,fatmask|occluders_floor);
01100
01101
01102
01103 for (vector<Shape<LineData> >::iterator it = wall_bounds.begin();
01104 it != wall_bounds.end(); it++) {
01105 if (((*it)->end1Pt().coordX() < camFrame_offset*2.0 || (*it)->end1Pt().coordX() > xres - camFrame_offset*2.0
01106 || (*it)->end1Pt().coordY() < camFrame_offset*2.0 || (*it)->end1Pt().coordY() > yres - camFrame_offset*2.0)
01107 && (*it)->end1Pt().isValid())
01108 (*it)->end1Pt().setValid(false);
01109 if (((*it)->end2Pt().coordX() < camFrame_offset*2.0 || (*it)->end2Pt().coordX() > xres - camFrame_offset*2.0
01110 || (*it)->end2Pt().coordY() < camFrame_offset*2.0 || (*it)->end2Pt().coordY() > yres - camFrame_offset*2.0)
01111 && (*it)->end2Pt().isValid())
01112 (*it)->end2Pt().setValid(false);
01113 }
01114
01115 if ( curReq->verbosity & MBVshapesFound )
01116 cout << "Found " << wall_bounds.size() << " wall boundary lines" << endl;
01117 return wall_bounds;
01118 }
01119
01120 void MapBuilder::getCamBlobs(const Sketch<uchar>& camFrame,
01121 const set<color_index>& colors,
01122 const map<color_index,int>& minBlobAreas,
01123 const map<color_index, BlobData::BlobOrientation_t>& blobOrientations,
01124 const map<color_index,coordinate_t>& assumedBlobHeights) {
01125 if ( colors.empty() )
01126 return;
01127 int const maxblobs = 50;
01128 vector<Shape<BlobData> > result(BlobData::extractBlobs(camFrame, colors, minBlobAreas, blobOrientations, assumedBlobHeights, maxblobs));
01129 if ( curReq->verbosity & MBVshapesFound )
01130 if ( !result.empty() )
01131 cout << "Found " << result.size() << " blobs." << endl;
01132 }
01133
01134
01135
01136 void MapBuilder::getCamBlobs(const set<color_index>& colors, int defMinBlobArea) {
01137
01138 if ( curReq->verbosity & MBVshapeSearch )
01139 cout << "*** Find the blobs ***" << endl;
01140 for (set<color_index>::const_iterator it = colors.begin();
01141 it != colors.end(); it++) {
01142 int const minarea = (curReq->minBlobAreas.find(*it)==curReq->minBlobAreas.end()) ?
01143 defMinBlobArea : curReq->minBlobAreas[*it];
01144 BlobData::BlobOrientation_t const orient = (curReq->blobOrientations.find(*it)==curReq->blobOrientations.end()) ?
01145 BlobData::groundplane : curReq->blobOrientations[*it];
01146 coordinate_t const height = (curReq->assumedBlobHeights.find(*it)==curReq->assumedBlobHeights.end()) ?
01147 0 : curReq->assumedBlobHeights[*it];
01148 vector<Shape<BlobData> > blob_shapes(VRmixin::getBlobsFromRegionGenerator(*it,minarea,orient,height));
01149 if ( curReq->verbosity & MBVshapesFound )
01150 if ( !blob_shapes.empty() )
01151 cout << "Found " << blob_shapes.size() << " "
01152 << ProjectInterface::getColorName(*it) << " region generator blobs." << endl;
01153 }
01154 }
01155
01156 void MapBuilder::getCamTargets(const Sketch<uchar> &camFrame, const set<color_index>& objectColors, const set<color_index>& occluderColors) const {
01157 vector<Shape<TargetData> > targets;
01158 if (objectColors.empty())
01159 return;
01160 if ( curReq->verbosity & MBVshapeSearch )
01161 cout << "*** Find the targets ***" << endl;
01162
01163 NEW_SKETCH_N(occluders,bool,visops::zeros(camFrame));
01164 for (set<color_index>::const_iterator it = occluderColors.begin();
01165 it != occluderColors.end(); it++)
01166 occluders |= visops::minArea(visops::colormask(camFrame,*it));
01167
01168
01169 for (set<color_index>::const_iterator it = objectColors.begin();
01170 it != objectColors.end(); it++) {
01171 NEW_SKETCH_N(front_colormask, bool, visops::colormask(camFrame,*it));
01172 it++;
01173 if (it == objectColors.end()) {
01174 it--;
01175 }
01176 NEW_SKETCH_N(back_colormask, bool, visops::colormask(camFrame,*it));
01177 it++;
01178 if (it == objectColors.end()) {
01179 it--;
01180 }
01181 NEW_SKETCH_N(right_colormask, bool, visops::colormask(camFrame,*it));
01182 Shape<TargetData> target = TargetData::extractLineTarget(front_colormask, back_colormask, right_colormask, occluders);
01183 if (target.isValid()) {
01184 targets.insert(targets.end(), target);
01185 }
01186 if ( curReq->verbosity & MBVshapesFound )
01187 cout << "Found " << (target.isValid() ? 1 : 0) << " targets." << endl;
01188 }
01189 }
01190
01191 vector<Shape<MarkerData> >
01192 MapBuilder::getCamMarkers(const Sketch<uchar> &camFrame, const set<color_index>& objectColors,
01193 const set<color_index>&, const set<MarkerType_t>& markerTypes) const
01194 {
01195 vector<Shape<MarkerData> > markers;
01196 if (objectColors.empty() || markerTypes.empty())
01197 return markers;
01198
01199 if ( curReq->verbosity & MBVshapeSearch )
01200 cout << "*** Find the markers ***" << endl;
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211 for (set<MarkerType_t>::const_iterator it = markerTypes.begin();
01212 it != markerTypes.end(); it++) {
01213 vector<Shape<MarkerData> > single_type = MarkerData::extractMarkers(camFrame, *it, *curReq);
01214 markers.insert(markers.end(), single_type.begin(), single_type.end());
01215 }
01216
01217 if ( curReq->verbosity & MBVshapesFound )
01218 cout << "Found " << markers.size() << " markers." << endl;
01219
01220 return markers;
01221 }
01222
01223 void MapBuilder::getCamSiftObjects(const Sketch<uchar> &rawY, const std::string &siftDatabasePath,
01224 const std::set<std::string> &siftObjectNames) {
01225 if ( siftDatabasePath.empty() ) return;
01226 SiftTekkotsu *matcher = siftMatchers[siftDatabasePath];
01227 if ( matcher == NULL ) {
01228 matcher = new SiftTekkotsu;
01229 matcher->loadFile(siftDatabasePath);
01230 matcher->setParameter("probOfMatch", 0.8);
01231 siftMatchers[siftDatabasePath] = matcher;
01232 }
01233 ImageBuffer buff = matcher->sketchToBuffer(rawY);
01234 vector<SiftMatch*> results;
01235 if ( siftObjectNames.empty() )
01236 matcher->findAllObjectsInImage(buff, results);
01237 else
01238 for ( std::set<std::string>::const_iterator it = siftObjectNames.begin();
01239 it != siftObjectNames.end(); it++ ) {
01240 int id = matcher->getObjectID(*it);
01241 matcher->findObjectInImage(id, buff, results);
01242 };
01243 if ( curReq->verbosity & MBVshapesFound )
01244 cout << "Found " << results.size() << " sift objects." << endl;
01245 for ( vector<SiftMatch*>::const_iterator it = results.begin();
01246 it != results.end(); it++ ) {
01247 NEW_SHAPE(siftobj, SiftData, new SiftData(VRmixin::camShS, *it));
01248 }
01249 }
01250
01251 void MapBuilder::newSiftMatcher(const std::string &siftDatabasePath) {
01252 if ( siftDatabasePath.empty() ) return;
01253 SiftTekkotsu *matcher = siftMatchers[siftDatabasePath];
01254 if ( matcher == NULL ) {
01255 matcher = new SiftTekkotsu;
01256
01257 matcher->setParameter("probOfMatch", 0.8);
01258 siftMatchers[siftDatabasePath] = matcher;
01259 }
01260 }
01261
01262 void MapBuilder::getCamAprilTags(const Sketch<uchar> &rawY) {
01263 std::map<std::pair<int,int>,AprilTags::TagFamily*>::const_iterator registryEntry =
01264 AprilTags::TagFamily::tagFamilyRegistry.find(curReq->aprilTagFamily);
01265 if ( registryEntry == AprilTags::TagFamily::tagFamilyRegistry.end() )
01266 return;
01267 AprilTags::TagFamily *tagFamily = registryEntry->second;
01268 std::vector<Shape<AprilTagData> > results = AprilTagData::extractAprilTags(rawY, *tagFamily);
01269
01270 coordinate_t markerHeight = MapBuilderRequest::defaultMarkerHeight;
01271 for ( std::vector<Shape<AprilTagData> >::iterator it = results.begin();
01272 it != results.end(); it++ ) {
01273 Point c = (*it)->getCentroid();
01274 MarkerData::calculateCameraDistance(c, markerHeight);
01275 (*it)->setCentroid(c);
01276 }
01277 }
01278
01279 void MapBuilder::saveSiftDatabase(const std::string &siftDatabasePath) {
01280 if ( siftDatabasePath.empty() ) return;
01281 SiftTekkotsu *matcher = siftMatchers[siftDatabasePath];
01282 if ( matcher == NULL )
01283 cout << "Error in saveSiftDatabase: no database named '" << siftDatabasePath << "' has been loaded." << endl;
01284 else {
01285 matcher->saveToFile(siftDatabasePath, false);
01286 cout << "Wrote SIFT database " << siftDatabasePath << endl;
01287 }
01288 }
01289
01290 void MapBuilder::trainSiftObject(const std::string &siftDatabasePath,
01291 const std::string &objectName, const std::string &modelName) {
01292 NEW_SKETCH_N(rawY, uchar, VRmixin::sketchFromRawY());
01293 trainSiftObject(siftDatabasePath, rawY, objectName, modelName);
01294 }
01295
01296 void MapBuilder::trainSiftObject(const std::string &siftDatabasePath, const Sketch<uchar> &sketch,
01297 const std::string &objectName, const std::string &modelName) {
01298 if ( siftDatabasePath.empty() ) return;
01299 SiftTekkotsu *matcher = siftMatchers[siftDatabasePath];
01300 if ( matcher == NULL ) {
01301 cout << "Error in trainSiftObject:: no database named '" << siftDatabasePath << "' has been loaded." << endl;
01302 return;
01303 }
01304 ImageBuffer buffer = SiftTekkotsu::sketchToBuffer(sketch);
01305 int id = matcher->getObjectID(objectName);
01306 if ( id == -1 ) {
01307 int new_id = matcher->train_addNewObject(buffer);
01308 matcher->setObjectName(new_id, objectName);
01309 } else {
01310 matcher->train_addToObject(id, buffer);
01311 }
01312 }
01313
01314 }
01315