Homepage Demos Overview Downloads Tutorials Reference
Credits

MapBuilder.cc

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #include "Events/EventRouter.h"
00003 #include "Events/LookoutEvents.h"
00004 #include "Events/TextMsgEvent.h"
00005 #include "Motion/HeadPointerMC.h"
00006 #include "Shared/mathutils.h"
00007 #include "Shared/newmat/newmat.h"
00008 
00009 #include "Measures.h"
00010 #include "EllipseData.h"    // for extractEllipses
00011 #include "SphereData.h"     // for extractSpheres
00012 #include "BlobData.h"       // for extractSpheres
00013 #include "PolygonData.h"   // for extractPolygons
00014 #include "ShapeRoot.h"
00015 #include "ShapeLine.h"
00016 #include "ShapeEllipse.h"
00017 #include "ShapeBlob.h"
00018 #include "ShapePolygon.h"
00019 #include "Sketch.h"    // for NEW_SKETCH
00020 #include "visops.h"
00021 #include "VRmixin.h"
00022 
00023 #include "MapBuilder.h"
00024 #include "Lookout.h"
00025 
00026 namespace DualCoding {
00027 
00028 typedef map<ShapeType_t,set<int> > colorMap;
00029 
00030 inline float distSq(const NEWMAT::ColumnVector& vec) {
00031   return vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3);
00032 }
00033 
00034 MapBuilder::MapBuilder() : 
00035   BehaviorBase("MapBuilder"),
00036   camSkS(VRmixin::getCamSkS()),
00037   camShS(VRmixin::getCamSkS().getDualSpace()),
00038   groundShS(VRmixin::groundShS), 
00039   local(maps::local,VRmixin::getLocalSkS()), world(maps::world,VRmixin::getWorldSkS()), 
00040   cur(&local), xres(camSkS.getWidth()), yres(camSkS.getHeight()), 
00041   ground_plane(4), theAgent(VRmixin::theAgent),
00042   localToWorldMatrix(NEWMAT::IdentityMatrix(4)),
00043   worldToLocalTranslateMatrix(NEWMAT::IdentityMatrix(4)), 
00044   worldToLocalRotateMatrix(NEWMAT::IdentityMatrix(4)),
00045   badGazePoints(), 
00046   agentAtOrigin(true), requests(), curReq(NULL), idCounter(0), maxDistSq(0), 
00047   pointAtID(Lookout::Invalid_LO_ID), scanID(Lookout::Invalid_LO_ID),
00048   nextGazePoint() {}
00049 
00050 void MapBuilder::DoStart() {
00051   cout << "MapBuilder::DoStart()\n";
00052   BehaviorBase::DoStart();
00053   erouter->addListener(this,EventBase::textmsgEGID);
00054 }
00055 
00056 /*
00057   since MapBuilder is constructed as static from VRmixin, 
00058   destructor doesn't get called until dog shuts down.
00059   And we have to do everything assumed to be done in destructor in DoStop, 
00060   such as clearing request queue and setting parameters to the initial values as set in constructor
00061 */
00062 void MapBuilder::DoStop() {
00063   cout << "MapBuilder::DoStop()\n";
00064   while(!requests.empty()) {
00065     delete requests.front();
00066     requests.pop();
00067   }
00068   curReq = NULL;
00069   camSkS.clear(); camShS.clear();
00070   groundShS.clear();
00071   local.SkS.clear(); local.ShS.clear();
00072   world.SkS.clear(); world.ShS.clear();
00073 
00074   badGazePoints.clear();
00075   local.gazePts.clear();
00076   world.gazePts.clear();
00077   setAgent(Point(0,0,0),0);
00078 
00079   BehaviorBase::DoStop();
00080 }
00081 
00082 unsigned int MapBuilder::executeRequest(const MapBuilderRequest& req) {
00083   switch (req.getRequestType()) {
00084   case MapBuilderRequest::takeSnap:
00085     if (const TakeSnapAtRequest* snapAtReq = dynamic_cast<const TakeSnapAtRequest*>(&req))
00086       requests.push(new TakeSnapAtRequest(*snapAtReq)); 
00087     else
00088       requests.push(new TakeSnapRequest(*dynamic_cast<const TakeSnapRequest*>(&req))); 
00089     break;
00090   case MapBuilderRequest::localMap:
00091     if (const LocalMapTestRequest* testReq = dynamic_cast<const LocalMapTestRequest*>(&req))
00092       requests.push(new LocalMapTestRequest(*testReq)); 
00093     else
00094       requests.push(new LocalMapRequest(*dynamic_cast<const LocalMapRequest*>(&req))); 
00095     break;
00096   case MapBuilderRequest::worldMap:
00097     if (const WorldMapTestRequest* testReq = dynamic_cast<const WorldMapTestRequest*>(&req))
00098       requests.push(new WorldMapTestRequest(*testReq)); 
00099     else
00100       requests.push(new WorldMapRequest(*dynamic_cast<const WorldMapRequest*>(&req))); 
00101     break;
00102   default: return -1U;
00103   };
00104   requests.back()->requestID = idCounter++;
00105   //  cout << "MapBuilder::executeRequest: new request " << requests.back()->requestID
00106   //       << " added to the queue\n";
00107   if (requests.size() == 1) {
00108     erouter->addListener(this,EventBase::lookoutEGID);
00109     executeRequest();
00110   }
00111   return requests.back()->requestID;
00112 }
00113 
00114 void MapBuilder::executeRequest() {
00115   if ( requests.empty() || curReq != NULL ) return;
00116   curReq = requests.front();
00117   cout << "MapBuilder::executeRequest: execute " << curReq->requestID << endl;
00118   erouter->postEvent(EventBase::mapbuilderEGID, requests.front()->requestID, EventBase::activateETID,0);  
00119   if (curReq->groundPlaneAssumption == MapBuilderRequest::onStand)
00120     calculateGroundPlane(MapBuilderRequest::onStand);
00121 
00122   if (curReq->getRequestType() == MapBuilderRequest::takeSnap)
00123     if (const TakeSnapAtRequest* snapAtReq = dynamic_cast<const TakeSnapAtRequest*>(curReq))
00124       storeImageAt(snapAtReq->gazePt);
00125     else
00126       storeImage();
00127   else {
00128     const LocalMapRequest& curMapReq = *dynamic_cast<const LocalMapRequest*> (&(*curReq));
00129     maxDistSq = curMapReq.maxDist*curMapReq.maxDist;
00130     cur = (&curMapReq.shs==&local.ShS) ?  &local : &world;
00131     if (curMapReq.clearShapes) { // erase shapes and gaze points, start from scratch
00132       cur->ShS.clear();
00133       cur->SkS.clear();
00134       cur->gazePts.clear();
00135       cur->baseToCamMats.clear();
00136     }
00137     defineGazePts(cur->gazePts, curMapReq.area, curMapReq.doScan);
00138     if ( determineNextGazePoint() )
00139       moveToNextGazePoint();
00140     else
00141       requestComplete();
00142   }
00143 }
00144   
00145 void MapBuilder::processEvent(const EventBase &e) {
00146   cout << "MapBuilder::processEvent got " << e.getDescription() << endl;
00147   switch ( e.getGeneratorID() ) {
00148   case EventBase::textmsgEGID: {
00149     const TextMsgEvent &txtev = dynamic_cast<const TextMsgEvent&>(e);
00150     if ( strcmp(txtev.getText().c_str(),"MoveHead") == 0 )
00151       moveToNextGazePoint(true);
00152     break; }
00153   case EventBase::lookoutEGID:
00154     // image stored, extract shapes and extend local/world shape space
00155     cout << "MapBuilder got event " << e.getName() << "   pointAtID=" << pointAtID << endl;
00156     if (e.getSourceID() == pointAtID && e.getTypeID() == EventBase::deactivateETID) { 
00157       const Sketch<uchar>& camImg = dynamic_cast<const LookoutSketchEvent*>(&e)->getSketch();
00158       NEW_SKETCH(camFrame, uchar, camImg);
00159       const NEWMAT::Matrix& camToBase = dynamic_cast<const LookoutSketchEvent*>(&e)->toBaseMatrix;
00160       const NEWMAT::Matrix baseToCam = camToBase.i();
00161       processImage(camFrame, camToBase, baseToCam);
00162       if (curReq->getRequestType() == MapBuilderRequest::takeSnap) {
00163   requestComplete();
00164   return;
00165       }
00166       if (cur->space == maps::local)
00167   extendLocal(baseToCam);
00168       else
00169   extendWorld(baseToCam);
00170     }
00171     // gaze points defined by scan, start constructing map
00172     else if (e.getSourceID() == scanID && e.getTypeID() != EventBase::activateETID) {
00173       const vector<Point>& pts = dynamic_cast<const LookoutScanEvent*>(&e)->getTasks().front()->data;
00174       cur->gazePts.insert(cur->gazePts.end(),pts.begin(), pts.end());
00175     }
00176     else
00177       cout << "MapBuilder::processEvent(): unknown event " << e.getDescription()
00178      << "   pointAtID=" << pointAtID << endl;
00179     
00180     if ( requestExitTest() || !determineNextGazePoint() )
00181       requestComplete();
00182     else
00183       moveToNextGazePoint();
00184     break;
00185   default:
00186     cout << "Unexpected event " << e.getDescription() << endl;
00187   }
00188 }
00189 
00190 void MapBuilder::processImage(const Sketch<uchar>& camFrame, 
00191             const NEWMAT::Matrix& camToBase,
00192             const NEWMAT::Matrix& baseToCam) {
00193   if (curReq->groundPlaneAssumption == MapBuilderRequest::onLegs)
00194     calculateGroundPlane(MapBuilderRequest::onLegs);
00195   getCameraShapes(camFrame);
00196   projectToGround(camToBase);
00197   filterGroundShapes(baseToCam);
00198 }
00199 
00200 bool MapBuilder::determineNextGazePoint() {
00201   if (&cur->ShS == &world.ShS && !agentAtOrigin) {
00202     cur->ShS.applyTransform(worldToLocalTranslateMatrix);
00203     cur->ShS.applyTransform(worldToLocalRotateMatrix);
00204     bool b = determineNextGazePoint(cur->ShS.allShapes()) || determineNextGazePoint(cur->gazePts);
00205     cur->ShS.applyTransform(localToWorldMatrix); // transform back
00206     return b;
00207   }
00208   else
00209     return determineNextGazePoint(cur->ShS.allShapes()) || determineNextGazePoint(cur->gazePts);
00210 }
00211   
00212 bool MapBuilder::determineNextGazePoint(const vector<ShapeRoot>& shapes) {
00213   const LocalMapRequest *locReq = dynamic_cast<const LocalMapRequest*>(curReq);
00214   if ( locReq == NULL || ! locReq->pursueShapes )
00215     return false;
00216   HeadPointerMC headpointer_mc;
00217   for (vector<ShapeRoot>::const_iterator it = shapes.begin();
00218        it != shapes.end(); it++) {
00219     // look for invalid endpoints of lines / polygons
00220     if ((*it)->isType(lineDataType) || (*it)->isType(polygonDataType)) {
00221       const Shape<LineData>& ld = ShapeRootTypeConst(*it,LineData);
00222       const Shape<PolygonData>& pd = ShapeRootTypeConst(*it,PolygonData);
00223       bool isLine = (*it)->isType(lineDataType);
00224       EndPoint p[2] = { isLine ? ld->end1Pt(): pd->end1Pt(), isLine ? ld->end2Pt() : pd->end2Pt()};
00225       for (int i = 0; i < 2; i++) {
00226   if (!p[i].isValid() && !isBadGazePoint(p[i]) 
00227       && badGazePoints.end() == find(badGazePoints.begin(), badGazePoints.end(), (Point) p[i])) {
00228     cout << "take snap at endpoint" << (i+1) << " of shape id " 
00229          << (*it)->getId() << " at " << p[i] << endl;
00230     if (!headpointer_mc.lookAtPoint(p[i].coordX(),p[i].coordY(),p[i].coordZ()))
00231       badGazePoints.push_back((Point)p[i]);
00232     nextGazePoint = p[i];
00233     return true;
00234   }
00235       }
00236     }
00237     // look for shapes w/ <2 confidence
00238     if ((!(*it)->isType(agentDataType)) &&
00239   (*it)->getConfidence() <= 1 &&
00240   ! isBadGazePoint((*it)->getCentroid()) &&
00241   badGazePoints.end() == find(badGazePoints.begin(), badGazePoints.end(), (*it)->getCentroid()))  {
00242       const Point pt = (*it)->getCentroid();
00243       cout << "take snap at shape " << (*it)->getId()  
00244      << " (confidence level: " << (*it)->getConfidence() << ")" << endl;      
00245       cout << " at " << pt << endl;  
00246       if (! headpointer_mc.lookAtPoint(pt.coordX(),pt.coordY(),pt.coordZ()))
00247   badGazePoints.push_back(pt);
00248       nextGazePoint = pt;
00249       return true;
00250     }
00251     cout << "Skipping shape " << (*it)->getId()
00252    << " (confidence level: " << (*it)->getConfidence() << ")" << endl;      
00253   }
00254   return false;
00255 }
00256 
00257 
00258 bool MapBuilder::determineNextGazePoint(vector<Point>& gazePts) {
00259   HeadPointerMC headpointer_mc;
00260   for (vector<Point>::iterator it = gazePts.begin();
00261        it != gazePts.end(); it++) {
00262     cout << "look at pre-defined gazePt: " << *it << endl;
00263     nextGazePoint = *it;
00264     gazePts.erase(it);
00265     return true;
00266   }
00267   /*
00268   cout << "Gaze points exhausted; " << badGazePoints.size() << " bad gaze points were eliminated: " << endl;
00269   for (vector<Point>::const_iterator bad_it = badGazePoints.begin();
00270        bad_it != badGazePoints.end(); bad_it++)
00271     cout << *bad_it << " ";
00272   cout << endl;
00273   */
00274   return false;
00275 }
00276 
00277 void MapBuilder::moveToNextGazePoint(const bool manualOverride) {
00278   if ( curReq == NULL ) {
00279     cout << "curReq == NULL in moveToNextGazePoint!" << endl;
00280     return;
00281   }
00282   cout << "curReq == " << (unsigned int)curReq << endl;
00283   const LocalMapRequest* locReq = dynamic_cast<LocalMapRequest*>(curReq);
00284   if ( locReq != NULL && locReq->manualHeadMotion && manualOverride==false ) {
00285     cout << "To proceed to this gaze point:  !msg MoveHead" << endl;
00286     return;
00287   }
00288   storeImageAt(nextGazePoint);
00289 }
00290 
00291 
00292 bool MapBuilder::isBadGazePoint(const Point& Pt) const {
00293   const coordinate_t x = Pt.coordX();
00294   const coordinate_t y = Pt.coordY();
00295   return ( x*x + y*y > maxDistSq ||
00296      x < -30.0);
00297 }
00298 
00299 void MapBuilder::storeImageAt(const Point& pt) { 
00300   pointAtID = VRmixin::lookout.executeRequest(StoreImageAtRequest(pt));
00301   cout << "MapBuilder sent new storeImageAt request; pointAtID=" << pointAtID << endl;
00302 }
00303 
00304 void MapBuilder::storeImage() { 
00305   pointAtID = VRmixin::lookout.executeRequest(StoreImageRequest());
00306   cout << "MapBuilder sent new storeImage request; pointAtID=" << pointAtID << endl;
00307 }
00308 
00309 void MapBuilder::scan(ScanRequest& req) {
00310   set<int> colors;
00311   for (colorMap::const_iterator it1 = curReq->objectColors.begin();
00312        it1 != curReq->objectColors.end(); it1++)
00313     for (set<int>::const_iterator it2 = it1->second.begin();
00314    it2 != it1->second.end(); it2++)
00315       colors.insert(*it2);
00316   req.addTask(ScanRequest::VisionRegionTask(colors,M_PI/18));
00317   scanID = VRmixin::lookout.executeRequest(req);
00318 }
00319 
00320 void MapBuilder::extendLocal(const NEWMAT::Matrix& baseToCam) {
00321   vector<ShapeRoot> all = local.ShS.allShapes();
00322   removeNoise(local.ShS, baseToCam);
00323   matchSrcToDst(groundShS,local.ShS,curReq->objectColors[polygonDataType]);
00324   removeGazePts(local.gazePts, baseToCam);
00325   local.baseToCamMats.push_back(baseToCam);
00326 }
00327 
00328 void MapBuilder::extendWorld(const NEWMAT::Matrix& baseToCam) {
00329   if (!agentAtOrigin) {
00330     world.ShS.applyTransform(worldToLocalTranslateMatrix);
00331     world.ShS.applyTransform(worldToLocalRotateMatrix);
00332   }
00333   removeNoise(world.ShS, baseToCam);
00334   matchSrcToDst(groundShS,world.ShS,curReq->objectColors[polygonDataType]);
00335   if (!agentAtOrigin)
00336     world.ShS.applyTransform(localToWorldMatrix);
00337   removeGazePts(world.gazePts,baseToCam);
00338   world.baseToCamMats.push_back(baseToCam);
00339 }
00340 
00341 bool MapBuilder::requestExitTest() {
00342   if (const LocalMapTestRequest* localTestReq = dynamic_cast<const LocalMapTestRequest*>(curReq))
00343     return ((*localTestReq->exitTest)());
00344   else if (const WorldMapTestRequest* worldTestReq = dynamic_cast<const WorldMapTestRequest*>(curReq))
00345     return ((*worldTestReq->exitTest)());
00346   else
00347     return false;
00348 }
00349 
00350 void MapBuilder::requestComplete() {
00351   const unsigned int reqID = curReq->requestID;
00352   cout << "MapBuilderRequest " << reqID << " complete\n";
00353   delete curReq;
00354   curReq = NULL;
00355   requests.pop();
00356   if ( requests.empty() )
00357     erouter->removeListener(this,EventBase::lookoutEGID); // don't need to listen to Lookout events when there is no request pending
00358   erouter->postEvent(EventBase::mapbuilderEGID, reqID, EventBase::statusETID,0);
00359   executeRequest(); // execute next request AFTER status event has finished processing
00360 }
00361 
00362 void MapBuilder::setAgent(const Point &location, const AngTwoPi heading) {
00363   theAgent->setCentroidPt(location);
00364   theAgent->setOrientation(heading);
00365   const coordinate_t dx = location.coordX();
00366   const coordinate_t dy = location.coordY();
00367   const coordinate_t dz = location.coordZ();
00368   float localToWorld[] = {cos(heading), -sin(heading), 0, dx,
00369         sin(heading),cos(heading), 0, dy, 
00370         0, 0, 1, dz,
00371         0 ,0, 0, 1};
00372   float worldToLocalTrans[] = {1, 0, 0, -dx,
00373              0, 1, 0, -dy, 
00374              0, 0, 1, -dz,
00375              0 ,0, 0, 1};
00376   float worldToLocalRotate[] = {cos(heading), sin(heading), 0, 0,
00377         -sin(heading),cos(heading), 0, 0, 
00378         0, 0, 1, 0,
00379         0 ,0, 0, 1};
00380   localToWorldMatrix << localToWorld;
00381   worldToLocalTranslateMatrix << worldToLocalTrans;
00382   worldToLocalRotateMatrix << worldToLocalRotate;
00383   agentAtOrigin = (heading == 0 || heading == 2*M_PI) && dx == 0 && dy == 0;
00384 }
00385 
00386 void MapBuilder::moveAgent(coordinate_t const local_dx, coordinate_t const local_dy, AngTwoPi dtheta) {
00387   AngTwoPi const heading = theAgent->getOrientation();
00388   float const c = cos(heading);
00389   float const s = sin(heading);
00390   float const dx = local_dx*c + local_dy*-s;
00391   float const dy = local_dx*s + local_dy*c;
00392   setAgent(Point(dx+theAgent->getCentroid().coordX(),
00393      dy+theAgent->getCentroid().coordY(),
00394      theAgent->getCentroid().coordZ()),
00395      dtheta+heading);
00396 }
00397 
00398 void MapBuilder::importLocalToWorld() {
00399   if (!agentAtOrigin) {
00400     world.ShS.applyTransform(worldToLocalTranslateMatrix);
00401     world.ShS.applyTransform(worldToLocalRotateMatrix);
00402   }
00403   matchSrcToDst(local.ShS, world.ShS);
00404   if (!agentAtOrigin)
00405     world.ShS.applyTransform(localToWorldMatrix);
00406 }
00407 
00408 
00409 void MapBuilder::importWorldToLocal(const ShapeRoot &worldShape) {
00410   ShapeRoot localShape(local.ShS.importShape(worldShape));
00411   localShape->applyTransform(worldToLocalTranslateMatrix);
00412   localShape->applyTransform(worldToLocalRotateMatrix);
00413 }
00414 
00415 bool MapBuilder::isPointVisible(const Point &pt, const NEWMAT::Matrix& baseToCam, float maxDistanceSq) {
00416   NEWMAT::ColumnVector camCoords = baseToCam*pt.coords;
00417   if (camCoords(3) <=0 || distSq(camCoords) >= maxDistanceSq) return false;
00418   float normX,normY; // normalized coordinates in cam frame
00419   config->vision.computePixel(camCoords(1),camCoords(2),camCoords(3),normX,normY);
00420   return (fabs(normX) < 0.9 && fabs(normY) < 0.9); //normX and normY range from -1 to 1. Giving 10% offset here
00421 }
00422 
00423 bool MapBuilder::isLineVisible(const LineData& ln, const NEWMAT::Matrix& baseToCam) {
00424   float normX1,normX2,normY1,normY2;
00425   NEWMAT::ColumnVector camCoords(4);
00426   camCoords = baseToCam*ln.end1Pt().coords;
00427   config->vision.computePixel(camCoords(1),camCoords(2),camCoords(3),normX1,normY1);
00428   camCoords = baseToCam*ln.end2Pt().coords;
00429   config->vision.computePixel(camCoords(1),camCoords(2),camCoords(3),normX2,normY2);
00430   const bool end1Pt_visible = fabs(normX1) < 0.9 && fabs(normY1) < 0.9;
00431   const bool end2Pt_visible = fabs(normX2) < 0.9 && fabs(normY2) < 0.9;
00432   if (end1Pt_visible && end2Pt_visible)
00433     return true;
00434   LineData lnCam(VRmixin::groundShS, Point(normX1,normY1), Point(normX2,normY2));
00435   // define bounding box of camera frame in terms of normalized coordinates with 10% offset
00436   LineData camBounds[] = {LineData(VRmixin::groundShS, Point(0.9,0.9),Point(0.9,-0.9)),
00437         LineData(VRmixin::groundShS, Point(0.9,-0.9),Point(-0.9,-0.9)),
00438         LineData(VRmixin::groundShS, Point(-0.9,-0.9),Point(-0.9,0.9)),
00439         LineData(VRmixin::groundShS, Point(-0.9,0.9),Point(0.9,0.9))};
00440   unsigned int ptCount = 0;
00441   Point p[2];
00442   // find if a portion of the line shows up in cam
00443   if (end1Pt_visible) p[ptCount++].setCoords(normX1,normY1,0); // end1Pt in frame
00444   else if (end2Pt_visible) p[ptCount++].setCoords(normX2,normY2,0); // end2Pt in frame
00445   for (int i = 0; i < 4; i++)
00446     if (camBounds[i].intersectsLine(lnCam)) {
00447       p[ptCount++].setCoords(lnCam.intersectionWithLine(camBounds[i]));
00448       // Let's say portion of line seen in cam should be longer than .1 normalized
00449       if (ptCount > 1)
00450   return p[0].distanceFrom(p[1]) > 0.1; 
00451     }
00452   return false;
00453 }
00454 
00455 bool MapBuilder::isShapeVisible(const ShapeRoot &ground_shape, const NEWMAT::Matrix& baseToCam,
00456            float maxDistanceSq) {
00457   if (ground_shape->isType(lineDataType))
00458     return isLineVisible(ShapeRootTypeConst(ground_shape,LineData).getData(), baseToCam);
00459   else if (ground_shape->isType(polygonDataType)) {
00460     const Shape<PolygonData>& polygon = ShapeRootTypeConst(ground_shape,PolygonData);
00461     for (vector<LineData>::const_iterator edge_it = polygon->getEdges().begin();
00462    edge_it != polygon->getEdges().end(); edge_it++)
00463       if (isLineVisible(*edge_it,baseToCam))
00464   return true;
00465     return false;
00466   }
00467   else 
00468     return isPointVisible(ground_shape->getCentroid(), baseToCam, maxDistanceSq);
00469 }
00470 
00471 
00472 // filter "bad" ground shapes before importing to dst shape space.
00473 // 1. ignore shapes too far from dog or projected to the other side of cam plane
00474 // 2. chop off line at max distance if it is extending beyond the distance and leave the endpoint invalid
00475 void MapBuilder::filterGroundShapes(const NEWMAT::Matrix& baseToCam) {
00476   //  cout << "MapBuilder::filterGroundShapes()" << endl;
00477   vector<ShapeRoot> ground_shapes = groundShS.allShapes();
00478 
00479   for (vector<ShapeRoot>::iterator ground_it = ground_shapes.begin();
00480        ground_it != ground_shapes.end(); ground_it++ ) {
00481     const coordinate_t cenX = (*ground_it)->getCentroid().coordX();
00482     const coordinate_t cenY = (*ground_it)->getCentroid().coordY();
00483     if (cenX*cenX + cenY*cenY > maxDistSq) { // too far
00484       cout << "ground shape " << (*ground_it)->getId() << "(lastMatch " 
00485      << (*ground_it)->getLastMatchId() << ") too far, delete\n";
00486       ground_it->deleteShape();
00487     }
00488     NEWMAT::ColumnVector coords = Kinematics::pack(cenX,cenY,(*ground_it)->getCentroid().coordZ());
00489     coords = baseToCam*coords;
00490     if (coords(3) < 0) { // negative z-coordinate in camera frame indicates projection failed
00491       cout << "Projection failed for ground shape " << (*ground_it)->getId() 
00492            << "(lastMatch " << (*ground_it)->getLastMatchId() << "), delete\n";
00493       ground_it->deleteShape();
00494     }
00495     // if a line is extending to maxDistance, chop it off at maxdistance and mark the endpoint invalid
00496     else if ((*ground_it)->isType(lineDataType)) {
00497       const Shape<LineData>& line = ShapeRootTypeConst(*ground_it,LineData);
00498       const coordinate_t e1x = line->end1Pt().coordX();
00499       const coordinate_t e1y = line->end1Pt().coordY();
00500       const coordinate_t e2x = line->end2Pt().coordX();
00501       const coordinate_t e2y = line->end2Pt().coordY();
00502       if (e1x*e1x + e1y*e1y > maxDistSq && e2x*e2x + e2y*e2y > maxDistSq)
00503   ground_it->deleteShape();
00504       else if (e1x*e1x + e1y*e1y > maxDistSq || e2x*e2x + e2y*e2y > maxDistSq) {
00505   //  cout << (*ground_it)->getId() << "(lastMatch " << (*ground_it)->getLastMatchId() 
00506   //       << ")  extends beyond maximum distance we want. Chop off the line" << endl;
00507   vector<float> line_abc = line->lineEquation_abc();
00508   Point pt;
00509   const EndPoint* far_ept = (e1x*e1x + e1y*e1y > maxDistSq) ? &line->end1Pt() : &line->end2Pt(); 
00510         if (line_abc[1] == 0.0) {
00511     const coordinate_t y_abs = sqrt(maxDistSq - line_abc[2]*line_abc[2]);
00512     if (fabs(far_ept->coordY()-y_abs) < fabs(far_ept->coordY()+y_abs))
00513       pt.setCoords(e1x, y_abs, far_ept->coordZ());
00514     else
00515       pt.setCoords(e1x, -y_abs, far_ept->coordZ());
00516   }
00517   else {
00518     const float a = - line_abc[0]/line_abc[1];
00519     const float b = line_abc[2]/line_abc[1];
00520     const coordinate_t x1 = (sqrt((a*a+1.0)*maxDistSq-b*b)-a*b)/(a*a+1.0);
00521     const coordinate_t x2 = (-sqrt((a*a+1.0)*maxDistSq-b*b)-a*b)/(a*a+1.0);
00522     if (fabs(far_ept->coordX()-x1) < fabs(far_ept->coordX()-x2))
00523       pt.setCoords(x1, a*x1+b, far_ept->coordZ());
00524     else
00525       pt.setCoords(x2, a*x2+b, far_ept->coordZ());
00526   }
00527   EndPoint temp_endPt(pt);
00528   temp_endPt.setValid(false);
00529   //  cout << " (" << far_ept->coordX() << "," << far_ept->coordY() << ") => ("
00530   //       << pt.coordX() << "," << pt.coordY() << ")" << endl;
00531   if (e1x*e1x + e1y*e1y > maxDistSq)
00532     line->setEndPts(temp_endPt, line->end2Pt());
00533   else
00534     line->setEndPts(line->end1Pt(), temp_endPt);
00535   badGazePoints.push_back(pt);
00536       }
00537     }
00538   }
00539 }
00540 
00541 void MapBuilder::calculateGroundPlane(const MapBuilderRequest::GroundPlaneAssumption_t& gpa) {
00542   switch(gpa) {
00543   case MapBuilderRequest::onLegs:
00544     ground_plane << kine->calculateGroundPlane(); 
00545     cout << "Neck pan = " << state->outputs[HeadOffset+PanOffset] << endl;
00546     cout << "Calculated ground plane: " << NEWMAT::printmat(ground_plane) << endl;
00547     break;
00548   case MapBuilderRequest::onStand:
00549 #ifdef TGT_ERS210
00550     ground_plane << 0 << 0 << (float)(-1/200.0) << 1;
00551 #else
00552     ground_plane << 0 << 0 << (float)(-1/170.0) << 1; //for the order-made stands for ERS7 in the lab
00553 #endif
00554     // cout << "Hard-coded ground plane: " << NEWMAT::printmat(ground_plane) << endl;
00555     break;
00556   };
00557 }
00558 
00559 void MapBuilder::projectToGround(const NEWMAT::Matrix& camToBase) {
00560   VRmixin::projectToGround(camToBase, ground_plane);
00561 }
00562     
00563 
00564 void MapBuilder::matchSrcToDst(ShapeSpace &srcShS, ShapeSpace &dstShS,
00565           set<int> polCols, bool mergeSrc, bool mergeDst) {
00566   vector<ShapeRoot> src_shapes = srcShS.allShapes();
00567   vector<ShapeRoot> dst_shapes = dstShS.allShapes();
00568   vector<LineData> polygon_edges;
00569   
00570   // clean up src_shapes before messing with dst space
00571   for (vector<ShapeRoot>::iterator src_it = src_shapes.begin();
00572        src_it != src_shapes.end(); src_it++ ) {
00573     if (!(*src_it)->isAdmissible()) {
00574       cout << "shape " << (*src_it)->getId() << "(lastMatch " 
00575            << (*src_it)->getLastMatchId() << ") is not admissible:" << endl;
00576       (*src_it)->printParams();
00577       src_shapes.erase(src_it--);
00578     }
00579     else if ((*src_it)->isType(polygonDataType)) { 
00580       const vector<LineData>& lines = ShapeRootTypeConst(*src_it, PolygonData)->getEdges();
00581       polygon_edges.insert(polygon_edges.end(), lines.begin(), lines.end());
00582       src_shapes.erase(src_it--);
00583     }
00584     else if ((*src_it)->isType(lineDataType)) {
00585       const int colorIndex = ProjectInterface::getColorIndex((*src_it)->getColor());
00586       if ( polCols.end() != find(polCols.begin(), polCols.end(), colorIndex)) {
00587   polygon_edges.push_back(ShapeRootTypeConst(*src_it, LineData).getData());
00588   src_shapes.erase(src_it--);
00589       }
00590     }
00591   }
00592 
00593   // merge shapes inside srcShS
00594   if (mergeSrc)
00595     for ( vector<ShapeRoot>::iterator it = src_shapes.begin();
00596     it != src_shapes.end(); it++ )
00597       for ( vector<ShapeRoot>::iterator it2 = it+1;
00598     it2 != src_shapes.end(); it2++)
00599   if ((*it2)->isMatchFor(*it) && (*it)->updateParams(*it2)) {
00600     cout << "merging shape " << (*it)->getId() << " and shape " << (*it2)->getId() << endl;
00601     src_shapes.erase(it2--);
00602   }
00603 
00604   vector<Shape<PolygonData> > existingPolygons;
00605   // update dst shapes from src shapes
00606   for (vector<ShapeRoot>::iterator dst_it = dst_shapes.begin();
00607        dst_it != dst_shapes.end(); dst_it++ )
00608     if ((*dst_it)->isType(polygonDataType))
00609       existingPolygons.push_back(ShapeRootType(*dst_it,PolygonData));
00610     else {
00611       for (vector<ShapeRoot>::iterator src_it = src_shapes.begin();
00612      src_it != src_shapes.end(); src_it++)
00613   if ((*dst_it)->isMatchFor(*src_it) && (*dst_it)->updateParams((*src_it))) {
00614     (*dst_it)->increaseConfidence(*src_it);
00615     //    cout << "Matched src shape " << (*src_it)->getId() << " (lastMatch " << (*src_it)->getLastMatchId()
00616     //         << ") to dst shape " << (*dst_it)->getId() << endl;
00617     src_shapes.erase(src_it--);
00618   }
00619     }
00620   
00621   // form polygons from lines and import unmatched src shapes into dstShS
00622   vector<ShapeRoot> deletedPolygons;
00623   //  cout << existingPolygons.size() << " polygons\n";
00624   vector<ShapeRoot> newPolygons = PolygonData::formPolygons(polygon_edges,existingPolygons,deletedPolygons);
00625   //  cout << existingPolygons.size()+deletedPolygons.size() << " polygons\n";
00626   for (vector<ShapeRoot>::iterator delete_it = deletedPolygons.begin();
00627        delete_it != deletedPolygons.end(); delete_it++)
00628     delete_it->deleteShape();
00629   dstShS.importShapes(newPolygons);
00630   dstShS.importShapes(src_shapes);
00631   cout << "Imported " << (src_shapes.size()+newPolygons.size()) << " new shape(s) from "
00632        << srcShS.name << "ShS to " << dstShS.name << "ShS\n";
00633   
00634   // match shapes inside dstShS
00635   if (mergeDst) {
00636     dst_shapes = dstShS.allShapes();
00637     for ( vector<ShapeRoot>::iterator it = dst_shapes.begin();
00638     it < dst_shapes.end(); it++ )
00639       for ( vector<ShapeRoot>::iterator it2 = it+1;
00640       it2 < dst_shapes.end(); it2++)
00641   if ((*it2)->isMatchFor(*it) && (*it)->updateParams(*it2,true)) {
00642     // cout << "Matched src shape " << (*it)->getId() << " (lastMatch " 
00643     //  << (*it)->getLastMatchId()<< ") is a match for " 
00644     //   << (*it2)->getId() << " (lastMatch " 
00645     //   << (*it2)->getLastMatchId() << "), delete\n";
00646     it2->deleteShape();
00647     dst_shapes.erase(it2--);
00648   }
00649   }
00650 }
00651 
00652 // decrease confidence of those shapes should have been seen in the last snap,
00653 // remove shapes from shapespace if confidence becomes <0
00654 void MapBuilder::removeNoise(ShapeSpace& ShS, const NEWMAT::Matrix& baseToCam) {
00655   //  cout << "MapBuilder::removeNoise()\n";
00656   vector<ShapeRoot> shapes = ShS.allShapes();
00657   for (vector<ShapeRoot>::iterator it = shapes.begin();
00658        it != shapes.end(); it++ ) {
00659     // was not looking for this object in the last snap, 
00660     // and it's not fair to decrease this guy's confidence
00661     if (curReq->objectColors[(*it)->getType()].find(ProjectInterface::getColorIndex((*it)->getColor())) ==
00662   curReq->objectColors[(*it)->getType()].end())
00663       continue; 
00664     if ((*it)->isType(polygonDataType)) {
00665       Shape<PolygonData>& polygon = ShapeRootType(*it,PolygonData);
00666       vector<LineData>& edges = polygon->getEdgesRW();
00667       unsigned int edge_index = 0;
00668       for (vector<LineData>::iterator edge_it = edges.begin();
00669      edge_it != edges.end(); edge_it++, edge_index++) {
00670   if (isLineVisible(*edge_it, baseToCam)) {
00671     cout << "edge " << edge_index << " of polygon " << (*it)->getId() << "(confidence: " 
00672          << edge_it->getConfidence() << ") should be visible in this frame" << endl;
00673     edge_it->decreaseConfidence();
00674   }
00675       }
00676       vector<ShapeRoot> brokenPolygons = polygon->updateState();
00677       ShS.importShapes(brokenPolygons);
00678       if (!polygon->isAdmissible()) {
00679   cout << "delete polygon " << (*it)->getId() << " from map" << endl;
00680   it->deleteShape();
00681       }
00682     }
00683     else if ((!(*it)->isType(agentDataType)) && isShapeVisible(*it, baseToCam, maxDistSq)){
00684       (*it)->decreaseConfidence(); // decrease confidence by 1 for every visible shape
00685       cout << "shape " << (*it)->getId() << "(confidence: " << (*it)->getConfidence() 
00686      << ") should be visible in this frame" << endl;
00687       if ((*it)->getConfidence() < 0 ) {
00688   cout << "confidence < 0, shape " << (*it)->getId() << " deleted from map" << endl;
00689   // it->deleteShape();
00690       }
00691     }
00692   }
00693 }
00694 
00695 //================ Gaze points ================
00696 
00697 void MapBuilder::defineGazePts(vector<Point> &gazePts, const ShapeRoot& area, bool doScan) {
00698   cout << "MapBuilder::defineGazePts\n";
00699   static const float meshSize=50;
00700   switch (area->getType()) {
00701   case lineDataType: {
00702     const Shape<LineData>& line = ShapeRootTypeConst(area,LineData);
00703     if (doScan) {
00704       ScanAlongLineRequest req(line->end1Pt(),line->end2Pt());
00705       scan(req);
00706     }
00707     else {
00708       int numIntervals = (int) (line->getLength()/meshSize);
00709       const EndPoint& ep1 = line->end1Pt();
00710       const EndPoint& ep2 = line->end2Pt();
00711       gazePts.push_back(ep1);
00712       for (int i = 1; i < numIntervals; i++)
00713   gazePts.push_back((ep1*i + ep2*(numIntervals-i))/numIntervals);
00714       gazePts.push_back(ep2);
00715     }
00716   }
00717     break;
00718   case blobDataType: {
00719     const Shape<BlobData>& blob = ShapeRootTypeConst(area,BlobData);
00720     if (doScan) {
00721       ScanAreaRequest req(blob->topLeft.coordY(),blob->bottomRight.coordY(),
00722         blob->topLeft.coordX(),blob->bottomRight.coordX());
00723       scan(req);
00724     }
00725     else {
00726       vector<Point> corners;
00727       corners.push_back(blob->topLeft);
00728       corners.push_back(blob->topRight);
00729       corners.push_back(blob->bottomRight);
00730       corners.push_back(blob->bottomLeft);
00731       defineGazePts(gazePts, corners, meshSize);
00732     }
00733   }
00734     break;
00735   case pointDataType:
00736     gazePts.push_back(area->getCentroid());
00737     break;
00738   case polygonDataType: {
00739     const Shape<PolygonData> &poly = ShapeRootTypeConst(area,PolygonData);
00740     const vector<Point> &verts = poly->getVertices();
00741     gazePts.insert(gazePts.end(),verts.begin(),verts.end());
00742   }
00743     break;
00744   default:
00745     cerr << "ERRORR MapBuilder::defineGazePts: Only types of area supported are Blob, Line, Point, and Polygon\n";
00746     requestComplete();
00747     break;
00748   };
00749 }
00750 
00751 void MapBuilder::defineGazePts(vector<Point>& gazePts, const vector<Point>& corners, float meshSize) {
00752   if (corners.size() != 4) {
00753     cout << "Region of interest has to have four corners" << endl;
00754     return;
00755   }
00756   for (vector<Point>::const_iterator it = corners.begin();
00757        it != corners.end()-1; it++) {
00758     if (find(it+1, corners.end(), *it) != corners.end()) {
00759       cout << "At least two corners are identical" << endl;
00760       return;
00761     }
00762   }
00763   LineData ln1(groundShS, corners.at(0),corners.at(1));
00764   LineData ln2(groundShS, corners.at(0),corners.at(2));
00765   const bool edge0_next_to_edge1 = !ln1.intersectsLine(LineData(groundShS, corners.at(2),corners.at(3)));
00766   const bool edge0_next_to_edge2 = !ln2.intersectsLine(LineData(groundShS, corners.at(1),corners.at(3)));
00767   vector<LineData> horizontal, vertical;
00768   
00769   // passed corners may not be in the right order, sort them in clockwise or counterclockwise direction
00770   const Point p0(corners.at(0));
00771   const Point p1(edge0_next_to_edge1 ? corners.at(1) : corners.at(3));
00772   const Point p2(edge0_next_to_edge1 ? (edge0_next_to_edge2 ? corners.at(3) : corners.at(2)) : corners.at(1));
00773   const Point p3(edge0_next_to_edge2 ? corners.at(2) : corners.at(3));
00774 
00775   // define horizontal lines
00776   Point p1_minus_p0 = p1-p0;
00777   Point p2_minus_p3 = p2-p3;
00778   const int num_steps_x = 
00779     (int) (sqrt(max(p1_minus_p0.coordX()*p1_minus_p0.coordX() + p1_minus_p0.coordY()*p1_minus_p0.coordY(),
00780         p2_minus_p3.coordX()*p2_minus_p3.coordX() + p2_minus_p3.coordY()*p2_minus_p3.coordY()))
00781      / meshSize) + 1;
00782   p1_minus_p0 /= (float) num_steps_x;
00783   p2_minus_p3 /= (float) num_steps_x;
00784   
00785   for (int i = 0; i <= num_steps_x; i++)
00786     horizontal.push_back(LineData(groundShS, p0+p1_minus_p0*i, p3+p2_minus_p3*i));
00787 
00788   // define vertical lines
00789   Point p3_minus_p0 = p3-p0;
00790   Point p2_minus_p1 = p2-p1;
00791   const int num_steps_y = 
00792     (int) (sqrt(max(p3_minus_p0.coordX()*p3_minus_p0.coordX() + p3_minus_p0.coordY()*p3_minus_p0.coordY(),
00793         p2_minus_p1.coordX()*p2_minus_p1.coordX() + p2_minus_p1.coordY()*p2_minus_p1.coordY()))
00794      / meshSize) + 1;
00795   p3_minus_p0 /= (float) num_steps_y;
00796   p2_minus_p1 /= (float) num_steps_y;
00797 
00798   for (int i = 0; i <= num_steps_y; i++)
00799     vertical.push_back(LineData(groundShS, p0+p3_minus_p0*i, p1+p2_minus_p1*i));
00800   
00801   // define check points = intersection of horizontal and vertical lines
00802   //  cout << "checkList: " << endl;
00803   for (vector<LineData>::const_iterator H_it = horizontal.begin();
00804        H_it != horizontal.end(); H_it++)
00805     for (vector<LineData>::const_iterator V_it = vertical.begin();
00806    V_it != vertical.end(); V_it++)
00807       gazePts.push_back(H_it->intersectionWithLine(*V_it));
00808 }
00809 
00810 void MapBuilder::removeGazePts(vector<Point> &gazePts, const NEWMAT::Matrix& baseToCam) {
00811   if ( ! dynamic_cast<const LocalMapRequest*>(curReq)->removePts )
00812     return;
00813   int num_points_seen = 0;
00814   for ( vector<Point>::iterator it = gazePts.begin();
00815   it != gazePts.end(); it++ ) {
00816     if (isPointVisible(*it, baseToCam, maxDistSq)) {
00817       num_points_seen++;
00818       gazePts.erase(it--);
00819     }
00820   }
00821   // cout << num_points_seen << " pre-defined gaze points seen in last snap, "
00822   //      << gazePts.size() << " left\n";
00823 }
00824 
00825 
00826 //================================================================
00827 
00828 //Prints shapespace in the format to be used for particle filter on simulator
00829 void MapBuilder::printShS(ShapeSpace &ShS) const {
00830   cout << "MapBuilder::printShS()" << endl;
00831   unsigned int line_count = 0;
00832   vector<ShapeRoot> shapes = ShS.allShapes();
00833   for (vector<ShapeRoot>::const_iterator it = shapes.begin();
00834        it != shapes.end(); it++) {
00835     if ((*it)->isType(lineDataType)) {
00836       const Shape<LineData>& ld = ShapeRootTypeConst(*it,LineData);
00837       cout << (*it)->getId() << " " << lineDataType << " " 
00838      << ProjectInterface::getColorIndex((*it)->getColor()) 
00839      << " " << ld->end1Pt().coordX()  << " " << ld->end1Pt().coordY()
00840      << " " << ++line_count << " " << ld->getLength() << " " << ld->end1Pt().isValid() << endl; 
00841       cout << (*it)->getId() << " " << lineDataType << " " 
00842      << ProjectInterface::getColorIndex((*it)->getColor()) 
00843      << " " << ld->end2Pt().coordX()  << " " << ld->end2Pt().coordY()
00844      << " " << line_count << " " << ld->getLength() << " " << ld->end2Pt().isValid() << endl;
00845     }
00846     else {
00847       cout << (*it)->getId() << " " << (*it)->getType() << " " 
00848      << ProjectInterface::getColorIndex((*it)->getColor()) 
00849      << " " << (*it)->getCentroid().coordX()  << " " << (*it)->getCentroid().coordY() << endl;
00850     }
00851   }
00852 }
00853 
00854 
00855 //================ Shape extraction ================
00856 
00857 
00858 void MapBuilder::getCameraShapes(const Sketch<uchar>& camFrame) { 
00859   camShS.clear();
00860   getCamLines(camFrame, curReq->objectColors[lineDataType], curReq->occluderColors[lineDataType]);
00861   getCamEllipses(camFrame, curReq->objectColors[ellipseDataType], curReq->occluderColors[ellipseDataType]);
00862   getCamPolygons(camFrame, curReq->objectColors[polygonDataType], curReq->occluderColors[polygonDataType]);
00863   getCamSpheres(camFrame, curReq->objectColors[sphereDataType], curReq->occluderColors[sphereDataType]);
00864   getCamWalls(camFrame, curReq->floorColor);
00865   BlobData::extractBlobs(camFrame, curReq->objectColors[blobDataType]);
00866 }
00867 
00868 vector<Shape<LineData> > MapBuilder::getCamLines(const Sketch<uchar> &camFrame, const set<int>& objectColors, 
00869                 const set<int>& occluderColors) const {
00870   vector<Shape<LineData> > lines;
00871   if (objectColors.empty() ) 
00872     return lines;
00873   cout << "*** Find the lines ***" << endl;
00874   NEW_SKETCH_N(occluders,bool,visops::zeros(camFrame));
00875   for ( set<int>::const_iterator it = occluderColors.begin();
00876   it != occluderColors.end(); it++ )
00877     occluders |= visops::minArea(visops::colormask(camFrame,*it));
00878 
00879   for (set<int>::const_iterator it = objectColors.begin();
00880        it != objectColors.end(); it++) {
00881     NEW_SKETCH_N(colormask,bool,visops::colormask(camFrame,*it));
00882     NEW_SKETCH_N(cleancolor,bool,visops::minArea(colormask));
00883     NEW_SKETCH_N(fatmask,bool,visops::fillin(cleancolor,1,2,8));
00884     NEW_SKETCH_N(skel,bool,visops::skel(fatmask));
00885     vector<Shape<LineData> > line_shapes = LineData::extractLines(skel,cleancolor|occluders);
00886     lines.insert(lines.end(), line_shapes.begin(), line_shapes.end());
00887     cout << "Found " << line_shapes.size() << " lines." << endl;
00888   }
00889   return lines;
00890 }
00891 
00892 vector<Shape<EllipseData> > 
00893 MapBuilder::getCamEllipses(const Sketch<uchar> &camFrame,
00894             const set<int>& objectColors, const set<int>& ) const {
00895   vector<Shape<EllipseData> > ellipses;
00896   if (objectColors.empty())
00897     return ellipses;
00898   cout << "*** Find the ellipses ***" << endl;
00899   for (set<int>::const_iterator it = objectColors.begin();
00900        it !=objectColors.end(); it++) {
00901     NEW_SKETCH_N(colormask,bool,visops::colormask(camFrame,*it));
00902     vector<Shape<EllipseData> > ellipse_shapes = EllipseData::extractEllipses(colormask);
00903     ellipses.insert(ellipses.end(), ellipse_shapes.begin(),ellipse_shapes.begin());
00904     cout << "Found " << ellipse_shapes.size() << " ellipses." << endl;
00905   }
00906   return ellipses;
00907 }
00908 
00909 vector<Shape<PolygonData> > 
00910 MapBuilder::getCamPolygons(const Sketch<uchar> &camFrame,
00911             const set<int>& objectColors, const set<int>& occluderColors) const {
00912   vector<Shape<PolygonData> > polygons;
00913   if ( objectColors.empty() ) 
00914     return polygons;
00915   cout << "*** Find the polygons ***" << endl;
00916   NEW_SKETCH_N(occluders,bool,visops::zeros(camFrame));
00917   for ( set<int>::const_iterator it = occluderColors.begin();
00918   it !=occluderColors.end(); it++ )
00919     occluders |= visops::colormask(camFrame,*it);
00920   
00921   for (set<int>::const_iterator it = objectColors.begin();
00922        it !=objectColors.end(); it++) {
00923     NEW_SKETCH_N(colormask,bool,visops::colormask(camFrame,*it));
00924     NEW_SKETCH_N(fatmask,bool,visops::fillin(colormask,1,2,8));
00925     NEW_SKETCH_N(skel,bool,visops::skel(fatmask));
00926     NEW_SKETCH_N(fatskel,bool,visops::fillin(skel,1,2,8));
00927     
00928     vector<Shape<LineData> > polygon_lines = PolygonData::extractPolygonEdges(fatskel,fatmask|occluders);
00929     polygons.insert(polygons.end(), polygon_lines.begin(), polygon_lines.end());
00930     cout << "Found " << polygon_lines.size() << " lines." << endl;
00931   }
00932   return polygons;
00933 }
00934 
00935 vector<Shape<SphereData> > 
00936 MapBuilder::getCamSpheres(const Sketch<uchar> &camFrame,
00937            const set<int>& objectColors, const set<int>& ) const {
00938   vector<Shape<SphereData> > spheres;
00939   if ( objectColors.empty() )
00940     return spheres;
00941   cout << "*** Find the spheres ***" << endl;
00942   for (set<int>::const_iterator it = objectColors.begin();
00943        it !=objectColors.end(); it++) {
00944     NEW_SKETCH_N(colormask,bool,visops::colormask(camFrame,*it));
00945     vector<ShapeRoot> sphere_shapes = SphereData::extractSpheres(colormask);
00946     spheres.insert(spheres.end(), spheres.begin(), spheres.end());
00947     cout << "Found " << sphere_shapes.size() << " spheres." << endl;
00948   }
00949   return spheres;
00950 }
00951 
00952 vector<Shape<LineData> > 
00953 MapBuilder::getCamWalls(const Sketch<uchar> &camFrame, unsigned int floorColor) const {
00954   if (floorColor == 0)
00955     return vector<Shape<LineData> >();
00956   cout << "*** Find the walls ***" << endl;
00957   const int camFrame_offset = 8;
00958 
00959   NEW_SKETCH_N(colormask,bool,visops::colormask(camFrame,floorColor));
00960   NEW_SKETCH_N(fillinmask ,bool,visops::fillin(colormask, 1, 6, 8)); //remove pixels w/ connectivity<6 (noise)
00961   NEW_SKETCH_N(fillinmask2 ,bool,visops::fillin(fillinmask, 2, 3, 8)); //remove pixels w/ connectivity<3 and fill in the others
00962   NEW_SKETCH_N(edgemask ,bool,visops::fillin(fillinmask2, 1, 5, 7)); //remove pixels w/ connectivity=8 (non-edge pixels)
00963   NEW_SKETCH_N(edgemask2 ,bool,visops::non_bounds(edgemask, camFrame_offset)); //remove pixels close to cam_bound
00964 
00965   NEW_SKETCH_N(occluders_floor, bool, camFrame != uchar(0) & camFrame != uchar(floorColor));
00966   NEW_SKETCH_N(occ_mask ,bool,visops::fillin(occluders_floor, 1, 8, 8)); //remove pixels w/ connectivity<7 (noises)
00967   usint const clear_dist = 15;
00968   Sketch<bool> not_too_close = (visops::edist(occ_mask) >= clear_dist); 
00969   edgemask2 &= not_too_close; //remove pixels around occuluders
00970   
00971   NEW_SKETCH_N(fatmask ,bool,visops::fillin(edgemask2,2,2,8)); //make the remaining pixels fat
00972   NEW_SKETCH_N(skel,bool,visops::skel(fatmask));
00973   NEW_SKETCH_N(fatskel,bool,visops::fillin(skel,1,2,8));
00974   
00975   vector<Shape<LineData> > wall_bounds = PolygonData::extractPolygonEdges(fatskel,fatmask|occluders_floor);
00976 
00977   // larger offset from the cam frame should be applied to these lines
00978   // since all pixels near cam frame bounds are removed before extracting these lines.
00979   for (vector<Shape<LineData> >::iterator it = wall_bounds.begin();
00980        it != wall_bounds.end(); it++) {
00981     if (((*it)->end1Pt().coordX() < camFrame_offset*2.0 || (*it)->end1Pt().coordX() > xres - camFrame_offset*2.0
00982    || (*it)->end1Pt().coordY() < camFrame_offset*2.0 || (*it)->end1Pt().coordY() > yres - camFrame_offset*2.0)
00983   && (*it)->end1Pt().isValid())
00984       (*it)->end1Pt().setValid(false);
00985     if (((*it)->end2Pt().coordX() < camFrame_offset*2.0 || (*it)->end2Pt().coordX() > xres - camFrame_offset*2.0
00986    || (*it)->end2Pt().coordY() < camFrame_offset*2.0 || (*it)->end2Pt().coordY() > yres - camFrame_offset*2.0)
00987   && (*it)->end2Pt().isValid())
00988       (*it)->end2Pt().setValid(false);
00989   }
00990   
00991   cout << "Found " << wall_bounds.size() << " wall boundary lines" << endl;
00992   return wall_bounds;
00993 }
00994 
00995 void MapBuilder::getCamBlobs() {
00996   if (  curReq->objectColors[blobDataType].empty() )
00997     return;
00998   cout << "*** Find the blobs ***" << endl;
00999   int minarea;
01000   BlobData::BlobOrientation_t orient;
01001   set<int>& blobColors = curReq->objectColors[blobDataType];
01002   //  unsigned int const numBlobColors = blobColors.size();
01003   //  for ( unsigned int i = 0; i<numBlobColors; i++ ) {
01004   for (set<int>::const_iterator it = blobColors.begin();
01005        it != blobColors.end(); it++) {
01006     //    minarea =  ( i < (curReq->minBlobAreas).size() ) ?  (curReq->minBlobAreas)[i] : 0;
01007     //    minarea =  ( i < (curReq->minBlobAreas).size() ) ?  1 : 0;
01008     //    orient =  ( i < curReq->blobOrientations.size() ) ? curReq->blobOrientations[i] : BlobData::groundplane;
01009     //    vector<Shape<BlobData> > blob_shapes(VRmixin::getBlobsFromRegionGenerator(blobColors[i],minarea,orient));
01010     minarea = (curReq->minBlobAreas.find(*it)==curReq->minBlobAreas.end()) ? 
01011       0 : curReq->minBlobAreas[*it];
01012     orient = (curReq->blobOrientations.find(*it)==curReq->blobOrientations.end()) ? 
01013       BlobData::groundplane : curReq->blobOrientations[*it];
01014     vector<Shape<BlobData> > blob_shapes(VRmixin::getBlobsFromRegionGenerator(*it,minarea,orient));
01015     cout << "Found " << blob_shapes.size() << " blobs." << endl;
01016   }
01017 }
01018 
01019 } // namespace

DualCoding 3.0beta
Generated Wed Oct 4 00:01:53 2006 by Doxygen 1.4.7