Homepage Demos Overview Downloads Tutorials Reference
Credits

MapBuilder.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef _MapBuilder_h_
00003 #define _MapBuilder_h_
00004 
00005 #include <queue>
00006 
00007 #include "Behaviors/BehaviorBase.h"
00008 #include "Shared/newmat/newmat.h"
00009 
00010 #include "BlobData.h"
00011 #include "LineData.h"
00012 #include "Point.h"
00013 #include "VRmixin.h"
00014 #include "LookoutRequests.h"
00015 #include "MapBuilderRequests.h"
00016 #include "SketchTypes.h"
00017 #include "ShapeSpace.h"
00018 
00019 namespace DualCoding {
00020 
00021 class SketchSpace;
00022 class ScanRequest;
00023 
00024 class MapBuilder : public BehaviorBase {
00025 protected:
00026   SketchSpace &camSkS;
00027   ShapeSpace &camShS, &groundShS;
00028 
00029   struct maps {
00030     enum Space { local, world } space;
00031     SketchSpace &SkS;
00032     ShapeSpace &ShS;
00033     vector<Point> gazePts;
00034     vector<NEWMAT::Matrix> baseToCamMats;
00035     maps(Space _space, SketchSpace& _SkS) :
00036       space(_space), SkS(_SkS), ShS(_SkS.getDualSpace()), gazePts(), baseToCamMats() {}
00037   } local, world, *cur;
00038 
00039 public:
00040   const int xres, yres; //!< width and height of camera frame
00041   NEWMAT::ColumnVector ground_plane; //!< ground plane to which shapes are projected
00042 
00043 protected:
00044   Shape<AgentData> &theAgent; //!< agent in the world frame
00045    //! trasformation matrices between local and world frames.
00046   NEWMAT::Matrix localToWorldMatrix, worldToLocalTranslateMatrix, worldToLocalRotateMatrix;
00047 
00048   vector<Point> badGazePoints; //!<  gaze points for which HeadPointerMC.lookAtPoint() returned false
00049   bool agentAtOrigin; //!< whether or not agent is at origin and orientation is zero or two pi.
00050 
00051   queue<MapBuilderRequest*> requests;
00052   MapBuilderRequest *curReq;
00053   unsigned int idCounter;
00054   
00055   unsigned int maxDistSq; //!< sqrt of current request's max distance parameter
00056   unsigned int pointAtID, scanID; //!< ID's for lookout requests
00057   Point nextGazePoint;
00058 
00059   //! posts completion event and deletes current request, executes next request if there is one
00060   void requestComplete(); 
00061   //! triggers action to execute the front one in requests queue
00062   void executeRequest();
00063   //! calls exitTest of current request if there is one and returns the result
00064   bool requestExitTest();
00065 
00066 public:
00067   MapBuilder(); //!< Constructor
00068   virtual ~MapBuilder() {}   //!< Destructor
00069   virtual void DoStart();
00070   virtual void DoStop(); 
00071   virtual void processEvent(const EventBase&);
00072   virtual std::string getDescription() const { return "MapBuilder"; }
00073   void printShS(ShapeSpace&) const;
00074   unsigned int executeRequest(const MapBuilderRequest& req);
00075 
00076   void processImage(const Sketch<uchar>&, const NEWMAT::Matrix& camToBase, const NEWMAT::Matrix& baseToCam);
00077 
00078   // returns if a ground shape should be seen in the current camera frame
00079   static bool isPointVisible(const Point &pt, const NEWMAT::Matrix& baseToCam, float maxDistanceSq) ;
00080   static bool isLineVisible(const LineData& ln, const NEWMAT::Matrix& baseToCam);
00081   static bool isShapeVisible(const ShapeRoot &ground_shape, const NEWMAT::Matrix& baseToCam, float maxDistanceSq);
00082   
00083   
00084   //!@ utility functions which may be used by MapBuilderRequests' exit condition and others
00085   const Shape<AgentData>& getAgent() const { return theAgent; }
00086 
00087   // sets the agent location and heading
00088   void setAgent(const Point &location, const AngTwoPi heading);
00089   
00090   // updates the agent location and heading
00091   void moveAgent(coordinate_t const local_dx, coordinate_t const local_dy, AngTwoPi dtheta);
00092   
00093   vector<ShapeRoot> getShapes(const ShapeSpace& ShS, int minConf=2) const {
00094     const vector<ShapeRoot> allShapes = ShS.allShapes();
00095     if (&ShS == &camShS || &ShS == &groundShS || minConf <= 0) 
00096       return allShapes;
00097     vector<ShapeRoot> nonNoiseShapes;
00098     for (vector<ShapeRoot>::const_iterator it = allShapes.begin();
00099    it != allShapes.end(); it++)
00100       if ((*it)->getConfidence() >= minConf)
00101   nonNoiseShapes.push_back(*it);
00102     return nonNoiseShapes;
00103   }
00104 
00105   const vector<Point>& getGazePts() const { return cur->gazePts; }
00106   static bool returnTrue() { return true; }
00107   static bool returnFalse() { return false; }
00108   //}@
00109 
00110   //!@ Shape extraction functions
00111   vector<Shape<LineData> > 
00112   getCamLines(const Sketch<uchar>&, const set<int>& objectColors, 
00113         const set<int>& occluderColors) const ;
00114   vector<Shape<PolygonData> > 
00115   getCamPolygons(const Sketch<uchar>&, const set<int>& objectColors, 
00116      const set<int>& occluderColors) const ;
00117   vector<Shape<EllipseData> > 
00118   getCamEllipses(const Sketch<uchar>&, const set<int>& objectColors, 
00119      const set<int>& occluderColors) const ;
00120   vector<Shape<SphereData> >  
00121   getCamSpheres(const Sketch<uchar>&, const set<int>& objectColors, 
00122     const set<int>& occluderColors) const ;
00123   vector<Shape<LineData> >  
00124   getCamWalls(const Sketch<uchar>&, unsigned int) const ;
00125   vector<Shape<BlobData> >  
00126   getCamBlobs(const Sketch<uchar>& sketch, const set<int>& objectColors) const {
00127     return BlobData::extractBlobs(sketch, objectColors);
00128   }
00129   //}@
00130 
00131   static Shape<BlobData> formBoundingBox(coordinate_t left, coordinate_t right, 
00132            coordinate_t front, coordinate_t rear) {
00133     return Shape<BlobData>
00134       (new BlobData(VRmixin::groundShS, Point(front,left), Point(front,right), 
00135         Point(rear,right), Point(rear,left), fabs((left-right)*(front-rear)), 
00136         vector<BlobData::run>(), BlobData::groundplane, rgb()));
00137   }
00138 
00139   void importLocalToWorld();
00140   void importWorldToLocal(const ShapeRoot &shape);
00141   // matching shapes between two spaces.
00142   static void matchSrcToDst(ShapeSpace &src, ShapeSpace &dst, set<int> polygonEdgeColors=set<int>(),
00143           bool mergeSrc=true, bool mergeDst=true);
00144 
00145 protected:
00146   //! functions to make requests to lookout
00147   void scan(ScanRequest& req);
00148   void storeImageAt(const Point& pt);
00149   void storeImage();
00150 
00151   //! define gazePts either virtually or by scan
00152   void defineGazePts(vector<Point>&, const ShapeRoot& area, bool doScan);// {}
00153   void defineGazePts(vector<Point>& gazePts, const vector<Point>& corners, float meshSize);
00154   
00155   void getCameraShapes(const Sketch<uchar>& camFrame);
00156   void getCamBlobs();
00157 
00158   void extendLocal(const NEWMAT::Matrix& baseToCam);
00159   void extendWorld(const NEWMAT::Matrix& baseToCam);
00160 
00161   //! decrement confidence of shapes which should have been seen according to the baseToCam matrix
00162   void removeNoise(ShapeSpace&, const NEWMAT::Matrix& baseToCam);
00163   //! erase gaze points which should have been seen according to the baseToCam matrix
00164   void removeGazePts(vector<Point>&, const NEWMAT::Matrix& baseToCam);
00165   
00166   //! Returns true if it has set up a valid next gaze point in nextGazePoint
00167   bool determineNextGazePoint();
00168   //! Returns true if there is a shape which needs be looked at again and is reachable; sets it up as nextGazePoint
00169   bool determineNextGazePoint(const vector<ShapeRoot>&);
00170   // Returns true if an element of gazePt can be looked at; sets it up as nextGazePoint
00171   bool determineNextGazePoint(vector<Point> &gazePts);
00172   //! Starts robot moving to the next gaze point
00173   void moveToNextGazePoint(const bool manualOverride=false);
00174 
00175   // operations in ground shape space 
00176   bool isBadGazePoint(const Point&) const ;
00177   void projectToGround(const NEWMAT::Matrix& camToBase);
00178   void filterGroundShapes(const NEWMAT::Matrix& baseToCam);
00179 
00180   // calculates ground place based on ground plane assumption type
00181   void calculateGroundPlane(const MapBuilderRequest::GroundPlaneAssumption_t& gpa);
00182 
00183 private:
00184   MapBuilder(const MapBuilder&); //!< never call this
00185   MapBuilder& operator=(const MapBuilder&);  //!< never call this
00186 };
00187 
00188 /*
00189 
00190 Functions of the MapBuilder subsystem:
00191 
00192 1. Given a series of camera views from the same body position (but
00193 varying head positions), assemble them into a local world view.  This
00194 requires:
00195 
00196  a) Matching functions to establish correspondence between
00197     groundspace objects and local worldspace objects.  This is
00198     tricky when lines have missing endpoints, or ellipses lie
00199     partially offscreen.
00200 
00201  Matching algorithm:
00202     do ellipses first -- they're simpler: just match color, center point
00203 
00204     Line matching:  
00205        pick a starting line (longest first) in groundShS
00206        then find all colinear line segments in groundShS matching its rho/theta
00207        do the same in localworldShS
00208        now a smart algorithm can assemble line segments into a more
00209          complex match than just 1-1
00210        but for starters can code just a 1-1 match
00211 
00212   Find nearby ellipses in ground and world space and cluster them together
00213   before matching.  This will allow us to handle piles of free game pieces.
00214 
00215   Make a list of ambiguous points that we would like to examine further
00216   by taking another image, moving the head and maybe even the body.
00217 
00218   Idea: we have to deal with lots of ambiguity in matching camera frames
00219   to the local world map, and may want to confirm some things with
00220   additional camera frames if we suspect noise.  But the world map should
00221   be considered to be reliable so we shouldn't need the same kind of
00222   expensive tentative matching there.  However, we may want to allow for
00223   "hints" of things to be put in the world map if we're not certain of our
00224   data.  For example, a far off ellipse may be of indeterminate size and
00225   orientation, so put it in the world map as a hint-of-ellipse and let the
00226   robot wander over there and get a close up view if it wants to resolve
00227   whether this is a real ellipse or noise.
00228 
00229   Can use distance from the camera as a parameter to control how we
00230   treat an object; small, far away objects should be treated as less reliable.
00231   Can keep counts on how many frames an object was seen or not seen, and
00232   delete objects as spurious if they were only seen once or twice and
00233   then not seen in a while.
00234 
00235   Unmatched object:  to know that a mobile object has disappeared, we
00236   need to recognize that we should see it but we don't.  How?  For each
00237   camera frame, project the four corners to ground, yielding a trapezoid.
00238   As we build the local world map we have a collection of trapezoids.  For
00239   any object in the global map that isn't matched by something in the local,
00240   we can check its coordinates to see if it falls within one of the 
00241   trapizeoids.  If so, then we looked and didn't see it, so it's gone.
00242 
00243  b) Update functions that update local worldspace object descriptions
00244     once correspondences have been determined.
00245 
00246 2. Given a local worldspace map and a global worldspace map, and
00247 possibly an estimate of current position and orientation on the
00248 latter, determine the robot's true position and orientation in the
00249 world, and update the global worldspace map.  This requires:
00250 
00251   a) A search method to find the best translation and rotation of
00252      the local worldspace map to fit the global worldspace map.
00253      A particle filter looks like a good candidate method.
00254 
00255   b) Update functions that update the global worldspace description
00256      once correspondences have been determined.
00257 
00258   c) A mechanism for recognizing when the world has changed, e.g.,
00259      objects have been added, deleted, or moved.  This requires:
00260 
00261        i) Designation of objects as fixed or mobile
00262 
00263        ii) Declaration of objects as unique, of a fixed number,
00264            or multitudinous.  Unique fixed objects are the best
00265      landmarks.  Multitudinous mobile objects may need to
00266      be monitored more frequently.
00267 
00268 3. Given a request to self-localize, acquire the minimum necessary
00269 number of local views to perform that function.  This requires:
00270 
00271   a) Designation of objects to be used as beacons or key landmarks.
00272 
00273   b) Head motion constraints.
00274 
00275   c) Body motion constraints (possibly "no body motion allowed".)
00276 
00277 Ideally, rather than directly executing motion commands, the system
00278 should pass its requests to look in certain directions to the
00279 affordance generator, which will figure out what is feasible, e.g., if
00280 we're up against a wall and can't turn in that direction, we may have
00281 to take a step sideways first.  Let the affordance system worry abou
00282 that.
00283 
00284 4. Given a prototype global world map description, visually explore
00285 the world and instantiate the prototype as an actual global world map.
00286 For example, we might define a tic-tac-toe environment as containing
00287 two sets of perpendicular lines defining the game board, plus a pool
00288 of free pieces.  We may not know the exact lengths of the lines, or
00289 their orientation, or the location of the pool relative to the board;
00290 these need to be determined by observation.  We may not even know the
00291 color of the lines, in which case we'll have to look for a contrast
00292 difference, but that is too advanced to worry about at present.
00293 
00294 */
00295 
00296 } // namespace
00297 
00298 #endif
00299 

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