Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 #ifndef __GridMapBase_h_
00030 #define __GridMapBase_h_
00031 
00032 #include <Eigen/Geometry>
00033 #include <Eigen/LU>
00034 
00035 #include "MapDimensionProperties.h"
00036 
00037 namespace hectorslam {
00038 
00043 template<typename ConcreteCellType>
00044 class GridMapBase
00045 {
00046 
00047 public:
00048 
00049   EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00050 
00055   bool hasGridValue(int x, int y) const
00056   {
00057     return (x >= 0) && (y >= 0) && (x < this->getSizeX()) && (y < this->getSizeY());
00058   }
00059 
00060   const Eigen::Vector2i& getMapDimensions() const { return mapDimensionProperties.getMapDimensions(); };
00061   int getSizeX() const { return mapDimensionProperties.getSizeX(); };
00062   int getSizeY() const { return mapDimensionProperties.getSizeY(); };
00063 
00064   bool pointOutOfMapBounds(const Eigen::Vector2f& pointMapCoords) const
00065   {
00066     return mapDimensionProperties.pointOutOfMapBounds(pointMapCoords);
00067   }
00068 
00069   virtual void reset()
00070   {
00071     this->clear();
00072   }
00073 
00077   void clear()
00078   {
00079     int size = this->getSizeX() * this->getSizeY();
00080 
00081     for (int i = 0; i < size; ++i) {
00082       this->mapArray[i].resetGridCell();
00083     }
00084 
00085     
00086     
00087   }
00088 
00089 
00090   const MapDimensionProperties& getMapDimProperties() const { return mapDimensionProperties; };
00091 
00095   GridMapBase(float mapResolution, const Eigen::Vector2i& size, const Eigen::Vector2f& offset)
00096     : mapArray(0)
00097     , lastUpdateIndex(-1)
00098   {
00099     Eigen::Vector2i newMapDimensions (size);
00100 
00101     this->setMapGridSize(newMapDimensions);
00102     sizeX = size[0];
00103 
00104     setMapTransformation(offset, mapResolution);
00105 
00106     this->clear();
00107   }
00108 
00112   virtual ~GridMapBase()
00113   {
00114     deleteArray();
00115   }
00116 
00120   void allocateArray(const Eigen::Vector2i& newMapDims)
00121   {
00122     int sizeX = newMapDims.x();
00123     int sizeY = newMapDims.y();
00124 
00125     mapArray = new ConcreteCellType [sizeX*sizeY];
00126 
00127     mapDimensionProperties.setMapCellDims(newMapDims);
00128   }
00129 
00130   void deleteArray()
00131   {
00132     if (mapArray != 0){
00133 
00134       delete[] mapArray;
00135 
00136       mapArray = 0;
00137       mapDimensionProperties.setMapCellDims(Eigen::Vector2i(-1,-1));
00138     }
00139   }
00140 
00141   ConcreteCellType& getCell(int x, int y)
00142   {
00143     return mapArray[y * sizeX + x];
00144   }
00145 
00146   const ConcreteCellType& getCell(int x, int y) const
00147   {
00148     return mapArray[y * sizeX + x];
00149   }
00150 
00151   ConcreteCellType& getCell(int index)
00152   {
00153     return mapArray[index];
00154   }
00155 
00156   const ConcreteCellType& getCell(int index) const
00157   {
00158     return mapArray[index];
00159   }
00160 
00161   void setMapGridSize(const Eigen::Vector2i& newMapDims)
00162   {
00163     if (newMapDims != mapDimensionProperties.getMapDimensions() ){
00164      deleteArray();
00165      allocateArray(newMapDims);
00166      this->reset();
00167     }
00168   }
00169 
00173   GridMapBase(const GridMapBase& other)
00174   {
00175     allocateArray(other.getMapDimensions());
00176     *this = other;
00177   }
00178 
00182   GridMapBase& operator=(const GridMapBase& other)
00183   {
00184     if ( !(this->mapDimensionProperties == other.mapDimensionProperties)){
00185       this->setMapGridSize(other.mapDimensionProperties.getMapDimensions());
00186     }
00187 
00188     this->mapDimensionProperties = other.mapDimensionProperties;
00189 
00190     this->worldTmap = other.worldTmap;
00191     this->mapTworld = other.mapTworld;
00192     this->worldTmap3D = other.worldTmap3D;
00193 
00194     this->scaleToMap = other.scaleToMap;
00195 
00196     
00197     int sizeX = this->getSizeX();
00198     int sizeY = this->getSizeY();
00199 
00200     size_t concreteCellSize = sizeof(ConcreteCellType);
00201 
00202     memcpy(this->mapArray, other.mapArray, sizeX*sizeY*concreteCellSize);
00203 
00204     return *this;
00205   }
00206 
00210   inline Eigen::Vector2f getWorldCoords(const Eigen::Vector2f& mapCoords) const
00211   {
00212     return worldTmap * mapCoords;
00213   }
00214 
00218   inline Eigen::Vector2f getMapCoords(const Eigen::Vector2f& worldCoords) const
00219   {
00220     return mapTworld * worldCoords;
00221   }
00222 
00226   inline Eigen::Vector3f getWorldCoordsPose(const Eigen::Vector3f& mapPose) const
00227   {
00228     Eigen::Vector2f worldCoords (worldTmap * mapPose.head<2>());
00229     return Eigen::Vector3f(worldCoords[0], worldCoords[1], mapPose[2]);
00230   }
00231 
00235   inline Eigen::Vector3f getMapCoordsPose(const Eigen::Vector3f& worldPose) const
00236   {
00237     Eigen::Vector2f mapCoords (mapTworld * worldPose.head<2>());
00238     return Eigen::Vector3f(mapCoords[0], mapCoords[1], worldPose[2]);
00239   }
00240 
00241   void setDimensionProperties(const Eigen::Vector2f& topLeftOffsetIn, const Eigen::Vector2i& mapDimensionsIn, float cellLengthIn)
00242   {
00243     setDimensionProperties(MapDimensionProperties(topLeftOffsetIn,mapDimensionsIn,cellLengthIn));
00244   }
00245 
00246   void setDimensionProperties(const MapDimensionProperties& newMapDimProps)
00247   {
00248     
00249     if (!newMapDimProps.hasEqualDimensionProperties(this->mapDimensionProperties)){
00250       this->setMapGridSize(newMapDimProps.getMapDimensions());
00251     }
00252 
00253     
00254     if(!newMapDimProps.hasEqualTransformationProperties(this->mapDimensionProperties)){
00255       this->setMapTransformation(newMapDimProps.getTopLeftOffset(), newMapDimProps.getCellLength());
00256     }
00257   }
00258 
00265   void setMapTransformation(const Eigen::Vector2f& topLeftOffset, float cellLength)
00266   {
00267     mapDimensionProperties.setCellLength(cellLength);
00268     mapDimensionProperties.setTopLeftOffset(topLeftOffset);
00269 
00270     scaleToMap = 1.0f / cellLength;
00271 
00272     mapTworld = Eigen::AlignedScaling2f(scaleToMap, scaleToMap) * Eigen::Translation2f(topLeftOffset[0], topLeftOffset[1]);
00273 
00274     worldTmap3D = Eigen::AlignedScaling3f(scaleToMap, scaleToMap, 1.0f) * Eigen::Translation3f(topLeftOffset[0], topLeftOffset[1], 0);
00275 
00276     
00277     worldTmap3D = worldTmap3D.inverse();
00278 
00279     worldTmap = mapTworld.inverse();
00280   }
00281 
00282 
00287   float getScaleToMap() const
00288   {
00289     return scaleToMap;
00290   }
00291 
00296   float getCellLength() const
00297   {
00298     return mapDimensionProperties.getCellLength();
00299   }
00300 
00305   const Eigen::Affine2f& getWorldTmap() const
00306   {
00307     return worldTmap;
00308   }
00309 
00314   const Eigen::Affine3f& getWorldTmap3D() const
00315   {
00316     return worldTmap3D;
00317   }
00318 
00323   const Eigen::Affine2f& getMapTworld() const
00324   {
00325     return mapTworld;
00326   }
00327 
00328   void setUpdated() { lastUpdateIndex++; };
00329   int getUpdateIndex() const { return lastUpdateIndex; };
00330 
00334   bool getMapExtends(int& xMax, int& yMax, int& xMin, int& yMin) const
00335   {
00336     int lowerStart = -1;
00337     int upperStart = 10000;
00338 
00339     int xMaxTemp = lowerStart;
00340     int yMaxTemp = lowerStart;
00341     int xMinTemp = upperStart;
00342     int yMinTemp = upperStart;
00343 
00344     int sizeX = this->getSizeX();
00345     int sizeY = this->getSizeY();
00346 
00347     for (int x = 0; x < sizeX; ++x) {
00348       for (int y = 0; y < sizeY; ++y) {
00349         if (this->mapArray[x][y].getValue() != 0.0f) {
00350 
00351           if (x > xMaxTemp) {
00352             xMaxTemp = x;
00353           }
00354 
00355           if (x < xMinTemp) {
00356             xMinTemp = x;
00357           }
00358 
00359           if (y > yMaxTemp) {
00360             yMaxTemp = y;
00361           }
00362 
00363           if (y < yMinTemp) {
00364             yMinTemp = y;
00365           }
00366         }
00367       }
00368     }
00369 
00370     if ((xMaxTemp != lowerStart) &&
00371         (yMaxTemp != lowerStart) &&
00372         (xMinTemp != upperStart) &&
00373         (yMinTemp != upperStart)) {
00374 
00375       xMax = xMaxTemp;
00376       yMax = yMaxTemp;
00377       xMin = xMinTemp;
00378       yMin = yMinTemp;
00379       return true;
00380     } else {
00381       return false;
00382     }
00383   }
00384 
00385 protected:
00386 
00387   ConcreteCellType *mapArray;    
00388 
00389   float scaleToMap;              
00390 
00391   Eigen::Affine2f worldTmap;     
00392   Eigen::Affine3f worldTmap3D;   
00393   Eigen::Affine2f mapTworld;     
00394 
00395   MapDimensionProperties mapDimensionProperties;
00396   int sizeX;
00397 
00398 private:
00399   int lastUpdateIndex;
00400 };
00401 
00402 }
00403 
00404 #endif