00001
00002 #include "Events/EventRouter.h"
00003 #include "Events/TextMsgEvent.h"
00004 #include "Events/LookoutEvents.h"
00005 #include "Motion/HeadPointerMC.h"
00006 #include "Shared/mathutils.h"
00007 #include "Shared/newmat/newmat.h"
00008
00009 #include "Shared/Measures.h"
00010 #include "EllipseData.h"
00011 #include "SphereData.h"
00012 #include "BlobData.h"
00013 #include "PolygonData.h"
00014 #include "SphereData.h"
00015 #include "TargetData.h"
00016 #include "ShapeRoot.h"
00017 #include "ShapeLine.h"
00018 #include "ShapeEllipse.h"
00019 #include "ShapeBlob.h"
00020 #include "ShapePolygon.h"
00021 #include "ShapeSphere.h"
00022 #include "ShapeTarget.h"
00023 #include "Sketch.h"
00024 #include "visops.h"
00025 #include "VRmixin.h"
00026
00027 #include "LookoutRequests.h"
00028 #include "Lookout.h"
00029 #include "MapBuilder.h"
00030
00031 using namespace std;
00032
00033 namespace DualCoding {
00034
00035 inline float distSq(const NEWMAT::ColumnVector& vec) {
00036 return vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3);
00037 }
00038
00039 MapBuilder::MapBuilder() :
00040 BehaviorBase("MapBuilder"),
00041 camSkS(VRmixin::getCamSkS()), camShS(camSkS.getDualSpace()),
00042 groundShS(VRmixin::getGroundShS()),
00043 localSkS(VRmixin::getLocalSkS()), localShS(localSkS.getDualSpace()),
00044 worldSkS(VRmixin::getWorldSkS()), worldShS(worldSkS.getDualSpace()),
00045 xres(camSkS.getWidth()), yres(camSkS.getHeight()),
00046 ground_plane(4),
00047 theAgent(VRmixin::theAgent),
00048 localToWorldMatrix(NEWMAT::IdentityMatrix(4)),
00049 worldToLocalTranslateMatrix(NEWMAT::IdentityMatrix(4)),
00050 worldToLocalRotateMatrix(NEWMAT::IdentityMatrix(4)),
00051 badGazePoints(),
00052 requests(), curReq(NULL), idCounter(0), maxDistSq(0),
00053 pointAtID(Lookout::invalid_LO_ID), scanID(Lookout::invalid_LO_ID),
00054 nextGazePoint() {}
00055
00056 void MapBuilder::DoStart() {
00057 if ( verbosity & MBVstart )
00058 cout << "MapBuilder::DoStart()\n";
00059 BehaviorBase::DoStart();
00060
00061 camSkS.clear(); camShS.clear();
00062 groundShS.clear();
00063 localSkS.clear(); localShS.clear();
00064 worldSkS.clear(); worldShS.clear();
00065 badGazePoints.clear();
00066 setAgent(Point(0,0,0),0);
00067
00068 erouter->addListener(this,EventBase::textmsgEGID);
00069 erouter->addListener(this,EventBase::lookoutEGID);
00070 }
00071
00072 bool MapBuilder::retain = true;
00073 MapBuilder::MapBuilderVerbosity_t MapBuilder::verbosity = -1U;
00074
00075
00076
00077
00078
00079
00080
00081
00082 void MapBuilder::DoStop() {
00083 cout << "MapBuilder::DoStop()\n";
00084 while(!requests.empty()) {
00085 delete requests.front();
00086 requests.pop();
00087 }
00088 curReq = NULL;
00089 BehaviorBase::DoStop();
00090 }
00091
00092 unsigned int MapBuilder::executeRequest(const MapBuilderRequest& req, unsigned int *req_id) {
00093 MapBuilderRequest *newreq = new MapBuilderRequest(req);
00094 const unsigned int this_request = ++idCounter;
00095 newreq->requestID = this_request;
00096 if ( req_id != NULL ) *req_id = this_request;
00097 requests.push(newreq);
00098 executeRequest();
00099 return this_request;
00100 }
00101
00102 void MapBuilder::executeRequest() {
00103 if ( curReq != NULL || requests.empty() ) return;
00104 curReq = requests.front();
00105 if ( verbosity & MBVexecute )
00106 cout << "MapBuilder::executeRequest: execute " << curReq->requestID << endl;
00107 erouter->postEvent(EventBase::mapbuilderEGID, curReq->requestID, EventBase::activateETID,0);
00108 if ( (curReq->pursueShapes || curReq->doScan || curReq->worldTargets.size()>0) &&
00109 curReq->getRequestType() == MapBuilderRequest::cameraMap ) {
00110 cout << "Warning: switching MapBuilderRequest type from cameraMap to localMap because request parameters require head movement." << endl;
00111 curReq->requestType = MapBuilderRequest::localMap;
00112 }
00113
00114 calculateGroundPlane();
00115 maxDistSq = curReq->maxDist*curReq->maxDist;
00116
00117 if ( curReq->clearShapes ) {
00118 curReq->gazePts.clear();
00119 curReq->baseToCamMats.clear();
00120 switch ( curReq->getRequestType() ) {
00121 case MapBuilderRequest::localMap:
00122 localShS.clear();
00123 localSkS.clear();
00124 break;
00125 case MapBuilderRequest::worldMap:
00126 worldShS.clear();
00127 worldSkS.clear();
00128 break;
00129 default:
00130 break;
00131 }
00132 }
00133
00134 if ( curReq->immediateRequest() )
00135 grabCameraImageAndGo();
00136 else if ( !curReq->searchArea.isValid() & curReq->worldTargets.size() == 0 )
00137 storeImage();
00138 else {
00139 defineGazePts();
00140 if ( curReq->doScan == true )
00141 return;
00142 else if ( curReq->worldTargets.size() > 0 )
00143 doNextSearch();
00144 else if ( determineNextGazePoint() )
00145 moveToNextGazePoint();
00146 else
00147 requestComplete();
00148 }
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 void MapBuilder::processEvent(const EventBase &e) {
00167 if ( curReq == NULL) return;
00168 if ( verbosity & MBVevents )
00169 cout << "MapBuilder got event " << e.getName() << "; current pointAtID=" << pointAtID
00170 << " scanID=" << scanID << endl;
00171
00172 switch ( e.getGeneratorID() ) {
00173 case EventBase::textmsgEGID:
00174 if ( strcmp(dynamic_cast<const TextMsgEvent&>(e).getText().c_str(),"MoveHead") == 0 )
00175 moveToNextGazePoint(true);
00176 break;
00177
00178 case EventBase::lookoutEGID:
00179 if ( e.getSourceID() == pointAtID )
00180 processImage(dynamic_cast<const LookoutSketchEvent&>(e));
00181 else if ( e.getSourceID() == scanID ) {
00182 const vector<Point>& pts = dynamic_cast<const LookoutScanEvent*>(&e)->getTasks().front()->data;
00183 cout << " doScan found " << pts.size() << " interest points." << endl;
00184 curReq->gazePts.insert(curReq->gazePts.end(),pts.begin(), pts.end());
00185 }
00186 else {
00187 cout << "MapBuilder: unexpected Lookout event " << e.getDescription()
00188 << ", current pointAtID=" << pointAtID << ", scanID=" << scanID << endl;
00189 return;
00190 }
00191
00192 if ( requestExitTest() )
00193 requestComplete();
00194 else if ( curReq->worldTargets.size() > 0 )
00195 doNextSearch();
00196 else if ( determineNextGazePoint() )
00197 moveToNextGazePoint();
00198 else
00199 requestComplete();
00200 break;
00201
00202 default:
00203 cout << "MapBuilder received unexpected event: " << e.getDescription() << endl;
00204 }
00205 }
00206
00207 void MapBuilder::processImage(const LookoutSketchEvent &e) {
00208 camSkS.clear();
00209 if ( curReq->rawY ) {
00210 NEW_SKETCH(rawY, uchar, VRmixin::sketchFromRawY());
00211 }
00212 NEW_SKETCH(camFrame, uchar, e.getSketch());
00213 const NEWMAT::Matrix& camToBase = e.toBaseMatrix;
00214 const NEWMAT::Matrix baseToCam = camToBase.i();
00215 getCameraShapes(camFrame);
00216 if (curReq->userCamProcessing != NULL) (*curReq->userCamProcessing)();
00217 if (curReq->getRequestType() > MapBuilderRequest::cameraMap) {
00218 projectToGround(camToBase);
00219 if (curReq->userGroundProcessing != NULL) (*curReq->userGroundProcessing)();
00220 filterGroundShapes(baseToCam);
00221 }
00222 switch ( curReq->getRequestType() ) {
00223 case MapBuilderRequest::cameraMap:
00224 case MapBuilderRequest::groundMap:
00225 break;
00226 case MapBuilderRequest::localMap:
00227 extendLocal(baseToCam);
00228 if (curReq->userLocalProcessing != NULL) (*curReq->userLocalProcessing)();
00229 break;
00230 case MapBuilderRequest::worldMap:
00231 extendWorld(baseToCam);
00232 if (curReq->userWorldProcessing != NULL) (*curReq->userWorldProcessing)();
00233 }
00234 }
00235
00236 bool MapBuilder::determineNextGazePoint() {
00237 if (curReq->getRequestType() == MapBuilderRequest::worldMap) {
00238 worldShS.applyTransform(worldToLocalTranslateMatrix,egocentric);
00239 worldShS.applyTransform(worldToLocalRotateMatrix,egocentric);
00240 bool b = determineNextGazePoint(worldShS.allShapes()) || determineNextGazePoint(curReq->gazePts);
00241 worldShS.applyTransform(localToWorldMatrix,allocentric);
00242 return b;
00243 }
00244 else
00245 return determineNextGazePoint(localShS.allShapes()) || determineNextGazePoint(curReq->gazePts);
00246 }
00247
00248
00249 bool MapBuilder::determineNextGazePoint(const vector<ShapeRoot>& shapes) {
00250 if ( ! curReq->pursueShapes ) return false;
00251 HeadPointerMC headpointer_mc;
00252 for (vector<ShapeRoot>::const_iterator it = shapes.begin();
00253 it != shapes.end(); it++) {
00254
00255 if ((*it)->isType(lineDataType) || (*it)->isType(polygonDataType)) {
00256 const Shape<LineData>& ld = ShapeRootTypeConst(*it,LineData);
00257 const Shape<PolygonData>& pd = ShapeRootTypeConst(*it,PolygonData);
00258 bool isLine = (*it)->isType(lineDataType);
00259 EndPoint p[2] = { isLine ? ld->end1Pt(): pd->end1Pt(), isLine ? ld->end2Pt() : pd->end2Pt()};
00260 for (int i = 0; i < 2; i++) {
00261 if ( !p[i].isValid() && !isBadGazePoint(p[i] )
00262 && badGazePoints.end() == find(badGazePoints.begin(), badGazePoints.end(), (Point) p[i])) {
00263 cout << "Take image at endpoint" << (i+1) << " of shape id "
00264 << (*it)->getId() << " at " << p[i] << endl;
00265 if ( !headpointer_mc.lookAtPoint(p[i].coordX(),p[i].coordY(),p[i].coordZ()) ) {
00266 if ( verbosity & MBVbadGazePoint )
00267 cout << "MapBuilder noting unreachable gaze point " << (Point)p[i] << endl;
00268 badGazePoints.push_back((Point)p[i]);
00269 }
00270 nextGazePoint = p[i];
00271 return true;
00272 }
00273 }
00274 }
00275
00276 if ((!(*it)->isType(agentDataType)) &&
00277 (*it)->getLastMatchId() != 0 &&
00278 (*it)->getConfidence() <= 1 &&
00279 ! isBadGazePoint((*it)->getCentroid()) &&
00280 badGazePoints.end() == find(badGazePoints.begin(), badGazePoints.end(), (*it)->getCentroid())) {
00281 const Point pt = (*it)->getCentroid();
00282 cout << "take image at shape " << (*it)
00283 << " (confidence level: " << (*it)->getConfidence() << ")" << endl;
00284 cout << " at " << pt << endl;
00285 if (! headpointer_mc.lookAtPoint(pt.coordX(),pt.coordY(),pt.coordZ()))
00286 badGazePoints.push_back(pt);
00287 nextGazePoint = pt;
00288 return true;
00289 }
00290
00291
00292 }
00293 return false;
00294 }
00295
00296
00297 bool MapBuilder::determineNextGazePoint(vector<Point>& gazePts) {
00298 for (vector<Point>::iterator it = gazePts.begin();
00299 it != gazePts.end(); it++) {
00300 nextGazePoint = *it;
00301 gazePts.erase(it);
00302 if ( ! isBadGazePoint(nextGazePoint) )
00303 return true;
00304 }
00305 return false;
00306 }
00307
00308 void MapBuilder::moveToNextGazePoint(const bool manualOverride) {
00309 if ( curReq == NULL ) {
00310 cout << "curReq == NULL in moveToNextGazePoint!" << endl;
00311 return;
00312 }
00313 if ( (verbosity & MBVnextGazePoint) || (curReq->manualHeadMotion && manualOverride==false) )
00314 cout << "moveToNextGazePoint " << nextGazePoint << endl;
00315 if ( curReq->manualHeadMotion && manualOverride==false ) {
00316 cout << "To proceed to this gaze point: !msg MoveHead" << endl;
00317 return;
00318 }
00319 else
00320 storeImage(nextGazePoint,true);
00321 }
00322
00323
00324 void MapBuilder::doNextSearch() {
00325 LookoutSearchRequest *curLSR = curReq->worldTargets.front();
00326 curReq->worldTargets.pop();
00327 pointAtID = VRmixin::lookout.executeRequest(*curLSR);
00328 }
00329
00330 bool MapBuilder::isBadGazePoint(const Point& Pt) const {
00331 const coordinate_t x = Pt.coordX();
00332 const coordinate_t y = Pt.coordY();
00333 return ( x*x + y*y > maxDistSq || x < -30.0);
00334 }
00335
00336 void MapBuilder::storeImage(const Point& pt, bool havepoint) {
00337 LookoutPointRequest lreq;
00338 if ( havepoint )
00339 lreq.setTarget(pt);
00340 else
00341 lreq.setHeadMotionType(LookoutRequest::noMotion);
00342 lreq.motionSettleTime = curReq->motionSettleTime;
00343 lreq.numSamples = curReq->numSamples;
00344 lreq.sampleInterval = curReq->sampleInterval;
00345 pointAtID = VRmixin::lookout.executeRequest(lreq);
00346 }
00347
00348 void MapBuilder::grabCameraImageAndGo() {
00349
00350
00351
00352
00353 pointAtID = 0;
00354 Sketch<uchar> camFrame(VRmixin::sketchFromSeg());
00355 #ifdef TGT_HAS_CAMERA
00356 const NEWMAT::Matrix camToBase = kine->jointToBase(CameraFrameOffset);
00357 #else
00358 NEWMAT::Matrix camToBase(4,4);
00359 camToBase << ROBOOP::fourbyfourident;
00360 #endif
00361 LookoutSketchEvent dummy(true, camFrame, camToBase,
00362 EventBase::lookoutEGID, pointAtID, EventBase::deactivateETID);
00363 processImage(dummy);
00364 requestComplete();
00365 }
00366
00367 void MapBuilder::scanForGazePts() {
00368 LookoutScanRequest lreq;
00369 lreq.searchArea = curReq->searchArea;
00370 lreq.motionSettleTime = curReq->motionSettleTime;
00371 set<color_index> colors;
00372 for (map<ShapeType_t,set<color_index> >::const_iterator it1 = curReq->objectColors.begin();
00373 it1 != curReq->objectColors.end(); it1++)
00374 for (set<color_index>::const_iterator it2 = it1->second.begin();
00375 it2 != it1->second.end(); it2++)
00376 colors.insert(*it2);
00377 lreq.addTask(LookoutScanRequest::VisionRegionTask(colors,curReq->dTheta));
00378 scanID = VRmixin::lookout.executeRequest(lreq);
00379 }
00380
00381 void MapBuilder::extendLocal(const NEWMAT::Matrix& baseToCam) {
00382 vector<ShapeRoot> all = localShS.allShapes();
00383 removeNoise(localShS, baseToCam);
00384 matchSrcToDst(groundShS,localShS,curReq->objectColors[polygonDataType]);
00385 removeGazePts(curReq->gazePts, baseToCam);
00386 curReq->baseToCamMats.push_back(baseToCam);
00387 }
00388
00389 void MapBuilder::extendWorld(const NEWMAT::Matrix& baseToCam) {
00390 worldShS.applyTransform(worldToLocalTranslateMatrix,egocentric);
00391 worldShS.applyTransform(worldToLocalRotateMatrix,egocentric);
00392 removeNoise(worldShS, baseToCam);
00393 matchSrcToDst(groundShS,worldShS,curReq->objectColors[polygonDataType]);
00394 worldShS.applyTransform(localToWorldMatrix,allocentric);
00395 removeGazePts(curReq->gazePts,baseToCam);
00396 curReq->baseToCamMats.push_back(baseToCam);
00397 }
00398
00399 bool MapBuilder::requestExitTest() {
00400 if ( curReq->exitTest == NULL )
00401 return false;
00402 else
00403 return (*curReq->exitTest)();
00404 }
00405
00406 void MapBuilder::requestComplete() {
00407 const unsigned int reqID = curReq->requestID;
00408 if ( verbosity & MBVcomplete )
00409 cout << "MapBuilderRequest " << reqID << " complete\n";
00410 delete curReq;
00411 curReq = NULL;
00412 requests.pop();
00413 erouter->postEvent(EventBase::mapbuilderEGID, reqID, EventBase::deactivateETID,0);
00414 if ( requests.empty() )
00415 VRmixin::lookout.relax();
00416 else
00417 executeRequest();
00418 }
00419
00420 void MapBuilder::setAgent(const Point &worldLocation, const AngTwoPi worldHeading) {
00421 if ( verbosity & MBVsetAgent )
00422 cout << "Agent now at " << worldLocation << " hdg " << worldHeading
00423 << " (= " << float(worldHeading)*180/M_PI << " deg.)" << endl;
00424 theAgent->setCentroidPt(worldLocation);
00425 theAgent->setOrientation(worldHeading);
00426 const coordinate_t dx = worldLocation.coordX();
00427 const coordinate_t dy = worldLocation.coordY();
00428 const coordinate_t dz = worldLocation.coordZ();
00429 float const c = cos(worldHeading);
00430 float const s = sin(worldHeading);
00431 float localToWorld[] = {c, -s, 0, dx,
00432 s, c, 0, dy,
00433 0, 0, 1, dz,
00434 0 , 0, 0, 1};
00435 float worldToLocalTrans[] = {1, 0, 0, -dx,
00436 0, 1, 0, -dy,
00437 0, 0, 1, -dz,
00438 0 ,0, 0, 1};
00439 float worldToLocalRotate[] = { c, s, 0, 0,
00440 -s, c, 0, 0,
00441 0, 0, 1, 0,
00442 0, 0, 0, 1};
00443 localToWorldMatrix << localToWorld;
00444 worldToLocalTranslateMatrix << worldToLocalTrans;
00445 worldToLocalRotateMatrix << worldToLocalRotate;
00446 }
00447
00448 void MapBuilder::moveAgent(coordinate_t const local_dx, coordinate_t const local_dy, AngTwoPi dtheta) {
00449 Point const agentLoc = theAgent->getCentroid();
00450 AngTwoPi const heading = theAgent->getOrientation();
00451 float const c = cos(heading);
00452 float const s = sin(heading);
00453 float const dx = local_dx*c + local_dy*-s;
00454 float const dy = local_dx*s + local_dy*c;
00455 setAgent(agentLoc + Point(dx,dy,agentLoc.coordZ(),allocentric),
00456 heading+dtheta);
00457 }
00458
00459 void MapBuilder::importLocalToWorld() {
00460 worldShS.applyTransform(worldToLocalTranslateMatrix,egocentric);
00461 worldShS.applyTransform(worldToLocalRotateMatrix,egocentric);
00462 matchSrcToDst(localShS,worldShS);
00463 worldShS.applyTransform(localToWorldMatrix,allocentric);
00464 }
00465
00466
00467 ShapeRoot MapBuilder::importWorldToLocal(const ShapeRoot &worldShape) {
00468 ShapeRoot localShape(localShS.importShape(worldShape));
00469 localShape->applyTransform(worldToLocalTranslateMatrix,egocentric);
00470 localShape->applyTransform(worldToLocalRotateMatrix,egocentric);
00471 return localShape;
00472 }
00473
00474 bool MapBuilder::isPointVisible(const Point &pt, const NEWMAT::Matrix& baseToCam, float maxDistanceSq) {
00475 NEWMAT::ColumnVector camCoords = baseToCam*pt.coords;
00476
00477 if ( camCoords(1)*camCoords(1)+camCoords(2)*camCoords(2) >= maxDistanceSq )
00478 return false;
00479 float normX,normY;
00480 config->vision.computePixel(camCoords(1),camCoords(2),camCoords(3),normX,normY);
00481 return (fabs(normX) < 0.9 && fabs(normY) < 0.9);
00482 }
00483
00484 bool MapBuilder::isLineVisible(const LineData& ln, const NEWMAT::Matrix& baseToCam) {
00485 float normX1,normX2,normY1,normY2;
00486 NEWMAT::ColumnVector camCoords(4);
00487 camCoords = baseToCam*ln.end1Pt().coords;
00488 config->vision.computePixel(camCoords(1),camCoords(2),camCoords(3),normX1,normY1);
00489 camCoords = baseToCam*ln.end2Pt().coords;
00490 config->vision.computePixel(camCoords(1),camCoords(2),camCoords(3),normX2,normY2);
00491 const bool end1Pt_visible = fabs(normX1) < 0.9 && fabs(normY1) < 0.9;
00492 const bool end2Pt_visible = fabs(normX2) < 0.9 && fabs(normY2) < 0.9;
00493 if (end1Pt_visible && end2Pt_visible)
00494 return true;
00495 LineData lnCam(VRmixin::groundShS, Point(normX1,normY1), Point(normX2,normY2));
00496
00497 LineData camBounds[] = {LineData(VRmixin::groundShS, Point(0.9,0.9),Point(0.9,-0.9)),
00498 LineData(VRmixin::groundShS, Point(0.9,-0.9),Point(-0.9,-0.9)),
00499 LineData(VRmixin::groundShS, Point(-0.9,-0.9),Point(-0.9,0.9)),
00500 LineData(VRmixin::groundShS, Point(-0.9,0.9),Point(0.9,0.9))};
00501 unsigned int ptCount = 0;
00502 Point p[2];
00503
00504 if (end1Pt_visible) p[ptCount++].setCoords(normX1,normY1,0);
00505 else if (end2Pt_visible) p[ptCount++].setCoords(normX2,normY2,0);
00506 for (int i = 0; i < 4; i++)
00507 if (camBounds[i].intersectsLine(lnCam)) {
00508 p[ptCount++].setCoords(lnCam.intersectionWithLine(camBounds[i]));
00509
00510 if (ptCount > 1)
00511 return p[0].distanceFrom(p[1]) > 0.1;
00512 }
00513 return false;
00514 }
00515
00516 bool MapBuilder::isShapeVisible(const ShapeRoot &ground_shape, const NEWMAT::Matrix& baseToCam,
00517 float maxDistanceSq) {
00518 if (ground_shape->isType(lineDataType))
00519 return isLineVisible(ShapeRootTypeConst(ground_shape,LineData).getData(), baseToCam);
00520 else if (ground_shape->isType(polygonDataType)) {
00521 const Shape<PolygonData>& polygon = ShapeRootTypeConst(ground_shape,PolygonData);
00522 for (vector<LineData>::const_iterator edge_it = polygon->getEdges().begin();
00523 edge_it != polygon->getEdges().end(); edge_it++)
00524 if (isLineVisible(*edge_it,baseToCam))
00525 return true;
00526 return false;
00527 }
00528 else
00529 return isPointVisible(ground_shape->getCentroid(), baseToCam, maxDistanceSq);
00530 }
00531
00532
00533
00534
00535
00536 void MapBuilder::filterGroundShapes(const NEWMAT::Matrix& baseToCam) {
00537
00538 vector<ShapeRoot> ground_shapes = groundShS.allShapes();
00539
00540 for (vector<ShapeRoot>::iterator ground_it = ground_shapes.begin();
00541 ground_it != ground_shapes.end(); ground_it++ ) {
00542 const coordinate_t cenX = (*ground_it)->getCentroid().coordX();
00543 const coordinate_t cenY = (*ground_it)->getCentroid().coordY();
00544 if (cenX*cenX + cenY*cenY > maxDistSq) {
00545 if ( verbosity & MBVnotAdmissible )
00546 cout << "ground shape " << (*ground_it)->getId() << " (lastMatch "
00547 << (*ground_it)->getLastMatchId() << ") too far, delete\n";
00548 ground_it->deleteShape();
00549 }
00550 NEWMAT::ColumnVector coords = Kinematics::pack(cenX,cenY,(*ground_it)->getCentroid().coordZ());
00551 coords = baseToCam*coords;
00552 if (coords(3) < 0) {
00553 if ( verbosity & MBVprojectionFailed )
00554 cout << "Projection failed for ground shape " << (*ground_it)->getId()
00555 << " (lastMatch " << (*ground_it)->getLastMatchId() << "): deleting\n";
00556 ground_it->deleteShape();
00557 }
00558
00559 else if ((*ground_it)->isType(lineDataType)) {
00560 const Shape<LineData>& line = ShapeRootTypeConst(*ground_it,LineData);
00561 const coordinate_t e1x = line->end1Pt().coordX();
00562 const coordinate_t e1y = line->end1Pt().coordY();
00563 const coordinate_t e2x = line->end2Pt().coordX();
00564 const coordinate_t e2y = line->end2Pt().coordY();
00565 if (e1x*e1x + e1y*e1y > maxDistSq && e2x*e2x + e2y*e2y > maxDistSq)
00566 ground_it->deleteShape();
00567 else if (e1x*e1x + e1y*e1y > maxDistSq || e2x*e2x + e2y*e2y > maxDistSq) {
00568
00569
00570 vector<float> line_abc = line->lineEquation_abc();
00571 Point pt;
00572 const EndPoint* far_ept = (e1x*e1x + e1y*e1y > maxDistSq) ? &line->end1Pt() : &line->end2Pt();
00573 if (line_abc[1] == 0.0) {
00574 const coordinate_t y_abs = sqrt(maxDistSq - line_abc[2]*line_abc[2]);
00575 if (fabs(far_ept->coordY()-y_abs) < fabs(far_ept->coordY()+y_abs))
00576 pt.setCoords(e1x, y_abs, far_ept->coordZ());
00577 else
00578 pt.setCoords(e1x, -y_abs, far_ept->coordZ());
00579 }
00580 else {
00581 const float a = - line_abc[0]/line_abc[1];
00582 const float b = line_abc[2]/line_abc[1];
00583 const coordinate_t x1 = (sqrt((a*a+1.0)*maxDistSq-b*b)-a*b)/(a*a+1.0);
00584 const coordinate_t x2 = (-sqrt((a*a+1.0)*maxDistSq-b*b)-a*b)/(a*a+1.0);
00585 if (fabs(far_ept->coordX()-x1) < fabs(far_ept->coordX()-x2))
00586 pt.setCoords(x1, a*x1+b, far_ept->coordZ());
00587 else
00588 pt.setCoords(x2, a*x2+b, far_ept->coordZ());
00589 }
00590 EndPoint temp_endPt(pt);
00591 temp_endPt.setValid(false);
00592
00593
00594 if (e1x*e1x + e1y*e1y > maxDistSq)
00595 line->setEndPts(temp_endPt, line->end2Pt());
00596 else
00597 line->setEndPts(line->end1Pt(), temp_endPt);
00598 badGazePoints.push_back(pt);
00599 }
00600 }
00601 }
00602 }
00603
00604 void MapBuilder::calculateGroundPlane() {
00605 switch(curReq->groundPlaneAssumption) {
00606 case MapBuilderRequest::onLegs:
00607 ground_plane << kine->calculateGroundPlane();
00608 if ( verbosity & MBVgroundPlane )
00609 cout << "Calculated ground plane: " << NEWMAT::printmat(ground_plane) << endl;
00610 break;
00611 case MapBuilderRequest::onStand:
00612 #ifdef TGT_ERS210
00613 ground_plane << 0 << 0 << (float)(-1/200.0) << 1;
00614 #else
00615 ground_plane << 0 << 0 << (float)(-1/170.0) << 1;
00616 #endif
00617
00618 break;
00619 case MapBuilderRequest::custom:
00620 ground_plane = curReq->customGroundPlane;
00621 }
00622 }
00623
00624 void MapBuilder::projectToGround(const NEWMAT::Matrix& camToBase) {
00625 VRmixin::projectToGround(camToBase, ground_plane);
00626 }
00627
00628
00629 void MapBuilder::matchSrcToDst(ShapeSpace &srcShS, ShapeSpace &dstShS,
00630 set<color_index> polCols, bool mergeSrc, bool mergeDst) {
00631 vector<ShapeRoot> src_shapes = srcShS.allShapes();
00632 vector<ShapeRoot> dst_shapes = dstShS.allShapes();
00633 vector<LineData> polygon_edges;
00634
00635
00636 for (vector<ShapeRoot>::iterator src_it = src_shapes.begin();
00637 src_it != src_shapes.end(); src_it++ ) {
00638 if (!(*src_it)->isAdmissible()) {
00639 if ( verbosity & MBVnotAdmissible )
00640 cout << "shape " << (*src_it)->getId() << "(lastMatch "
00641 << (*src_it)->getLastMatchId() << ") is not admissible:" << endl;
00642 (*src_it)->printParams();
00643 src_shapes.erase(src_it--);
00644 }
00645 else if ((*src_it)->isType(polygonDataType)) {
00646 const vector<LineData>& lines = ShapeRootTypeConst(*src_it, PolygonData)->getEdges();
00647 polygon_edges.insert(polygon_edges.end(), lines.begin(), lines.end());
00648 src_shapes.erase(src_it--);
00649 }
00650 else if ((*src_it)->isType(lineDataType)) {
00651 const color_index colorIndex = ProjectInterface::getColorIndex((*src_it)->getColor());
00652 if ( polCols.end() != find(polCols.begin(), polCols.end(), colorIndex)) {
00653 polygon_edges.push_back(ShapeRootTypeConst(*src_it, LineData).getData());
00654 src_shapes.erase(src_it--);
00655 }
00656 }
00657 }
00658
00659
00660 if (mergeSrc)
00661 for ( vector<ShapeRoot>::iterator it = src_shapes.begin();
00662 it != src_shapes.end(); it++ )
00663 for ( vector<ShapeRoot>::iterator it2 = it+1;
00664 it2 != src_shapes.end(); it2++)
00665 if ((*it2)->isMatchFor(*it) && (*it)->updateParams(*it2)) {
00666 if ( verbosity & MBVshapesMerge )
00667 cout << "merging shape " << (*it)->getId() << " and shape " << (*it2)->getId() << endl;
00668 src_shapes.erase(it2--);
00669 }
00670
00671 vector<Shape<PolygonData> > existingPolygons;
00672
00673 for (vector<ShapeRoot>::iterator dst_it = dst_shapes.begin();
00674 dst_it != dst_shapes.end(); dst_it++ )
00675 if ((*dst_it)->isType(polygonDataType))
00676 existingPolygons.push_back(ShapeRootType(*dst_it,PolygonData));
00677