MRXT: The Multi-Robot eXploration Tool
Multi-Robot autonomous exploration and mapping simulator.
src/architecture/slam/mapdata/binMap.cpp
00001 /*
00002 *
00003 * Author: Miguel Julia <mjulia@umh.es> 
00004 * 
00005 * Date:   2008
00006 * 
00007 * Class binMap
00008 *
00009 * Implements a binary gridmap
00010 *
00011 */
00012 #include "binMap.h"
00013 
00014 using namespace std;
00015 
00016 // Constructors
00017 
00018 // Default constructor
00019 binMap::binMap():
00020 width(0),
00021 height(0),
00022 totalsize(0),
00023 xorigin(0),
00024 yorigin(0),
00025 resolution(1),
00026 roi(0,0,0,0),
00027 cells(0)
00028 {
00029 
00030 }
00031 // Builds a binary grid map of size w x h
00032 binMap::binMap(int w, int h):
00033 width(w),
00034 height(h),
00035 totalsize((width*height)/32 + 1),
00036 xorigin(0),
00037 yorigin(0),
00038 resolution(1),
00039 roi(0,0,w,h)
00040 {
00041         cells.resize(totalsize);
00042         clear();
00043 };
00044 // Builds a binary grid map of size w x h with origin in real coordinates (x,y) and resolution res
00045 binMap::binMap(int w, int h, float res, float x, float y):
00046 width(w),
00047 height(h),
00048 totalsize((width*height)/32 + 1),
00049 xorigin(x),
00050 yorigin(y),
00051 resolution(res),
00052 roi(RoI(0,0,w,h))
00053 {
00054         cells.resize(totalsize);
00055         clear();
00056 };
00057 // Builds a binary grid map of size w x h (in meters) with origin in real coordinates (x,y) and resolution res
00058 binMap::binMap(float w, float h, float res, float x, float y):
00059 width((int)floor(w/res+0.5)),
00060 height((int)floor(h/res+0.5)),
00061 totalsize((width*height)/32 + 1),
00062 xorigin(x),
00063 yorigin(y),
00064 resolution(res),
00065 roi(RoI(0,0,width,height))
00066 {
00067         cells.resize(totalsize);
00068         clear();
00069 };
00070 // Copy contructor
00071 binMap::binMap(const binMap &map):
00072 width(map.width),
00073 height(map.height),
00074 totalsize(map.totalsize),
00075 xorigin(map.xorigin),
00076 yorigin(map.yorigin),
00077 resolution(map.resolution),
00078 roi(map.roi),
00079 cells(map.cells)
00080 {
00081 
00082 };
00083 // Destructor
00084 binMap::~binMap(){
00085 
00086 }
00087 // Initializers
00088 void binMap::initialize(int w, int h){
00089         initialize(w,h,0,0,0);
00090 };
00091 void binMap::initialize(int w, int h, float res, float x, float y){
00092         width  = w;
00093         height = h;
00094         totalsize = (width*height)/32 + 1;
00095         xorigin = x;
00096         yorigin = y;
00097         resolution = res;
00098         cells.resize(totalsize);
00099         roi.x = 0;
00100         roi.y = 0;
00101         roi.width = width;
00102         roi.height = height;
00103         clear();
00104 };
00105 void binMap::initialize(float w, float h, float res, float x, float y){
00106         int wd  = (int)floor(w/res+0.5);
00107         int ht = (int)floor(h/res+0.5);
00108         initialize(wd, ht, res, x, y);
00109 };
00110 binMap& binMap::operator=(const binMap& map){
00111         width = map.width;
00112         height = map.height;
00113         totalsize = map.totalsize;
00114         xorigin = map.xorigin;
00115         yorigin = map.yorigin;
00116         resolution = map.resolution;
00117         roi = map.roi;
00118         cells = map.cells;
00119         return *this;
00120 }
00121 
00122 
00123 // Data operations
00124 
00125 bool binMap::isInside(int x, int y, int size) const{
00126         for (int i = x-size; i<= x+size; i++)
00127                 for (int j = y-size; j<= y+size; j++)
00128                         if (!get(i,j))
00129                                 return false;
00130         return true;
00131 }
00132 
00133 bool binMap::isInsideD(int x, int y) const {
00134         int i,j;
00135         i = x; j = y;
00136         if (!get(i,j))
00137                 return false;
00138         i = x+1; j = y;
00139         if (!get(i,j))
00140                 return false;
00141         i = x-1; j = y;
00142         if (!get(i,j))
00143                 return false;
00144         i = x; j = y+1;
00145         if (!get(i,j))
00146                 return false;
00147         i = x; j = y-1;
00148         if (!get(i,j))
00149                 return false;
00150         return true;
00151 }
00152 
00153 bool binMap::isOver(int x, int y, int size) const {
00154         for (int i = x-size; i<= x+size; i++)
00155                 for (int j = y-size; j<= y+size; j++)
00156                         if (get(i,j)){
00157                                 return true;
00158                         }
00159         return false;
00160 }
00161 
00162 // Full map operations
00163 void binMap::sub(const binMap& map){
00164         for (int i = 0; i< (int)cells.size(); i++){
00165                 cells[i] &= (~map.cells[i]);
00166         }
00167 }
00168 void binMap::times(const binMap& map){
00169         for (int i = 0; i< (int)cells.size(); i++){
00170                 cells[i] &= map.cells[i];
00171         }
00172 }
00173 void binMap::invert(){
00174         for (int i = 0; i< (int)cells.size(); i++){
00175                 cells[i].flip();
00176         }
00177 }
00178 
00179 void binMap::add(const binMap& map){
00180         for (int i = 0; i< (int)cells.size(); i++){
00181                 cells[i] |= map.cells[i];
00182         }
00183         if (roi.x > map.roi.x){
00184                 roi.width += roi.x-map.roi.x; 
00185                 roi.x = map.roi.x;
00186         }
00187         if (roi.y > map.roi.y){
00188                 roi.height += roi.y-map.roi.y; 
00189                 roi.y = map.roi.y;      
00190         }
00191         if (roi.x + roi.width <= map.roi.x + map.roi.width){
00192                 roi.width += (map.roi.x + map.roi.width) - (roi.x + roi.width);
00193         }
00194         if (roi.y + roi.height <= map.roi.y + map.roi.height){
00195                 roi.height += (map.roi.y + map.roi.height) - (roi.y + roi.height);
00196         }
00197 }
00198 void binMap::clear(){
00199         for (int i = 0; i< (int)cells.size(); i++){
00200                 cells[i].reset();
00201         }
00202 }
00203 void binMap::closing(int rad){
00204         dilate(rad);
00205         erode(rad);
00206 }
00207 void binMap::opening(int rad){
00208         erode(rad);
00209         dilate(rad);
00210 }
00211 void binMap::dilate(int rad){
00212         int i,j;
00213         binMap prevData(*this);
00214         roi.x -= rad;
00215         roi.y -= rad;
00216         roi.width += 2*rad;
00217         roi.height += 2*rad;
00218         if (roi.x < 0){ roi.width  += roi.x; roi.x = 0; }
00219         if (roi.y < 0){ roi.height += roi.y; roi.y = 0; }
00220         if (roi.x + roi.width  > width)  {roi.width  = width  - roi.x;} 
00221         if (roi.y + roi.height > height) {roi.height = height - roi.y;} 
00222         for (i = roi.x ; i < roi.x + roi.width ; i++){
00223                 for (j = roi.y ; j < roi.y + roi.height ; j++){   // for each cell                              
00224                         if(prevData.isOver(i,j,rad)){
00225                                 set(i,j,true);
00226                         }
00227                         else{
00228                                 set(i,j,false);
00229                         }
00230                 }
00231         }
00232 }
00233 void binMap::erode(int rad){
00234         int i,j;
00235         binMap prevData(*this);
00236         roi.x += rad;
00237         roi.y += rad;
00238         roi.width -= 2*rad;
00239         roi.height -= 2*rad;
00240         for (i = roi.x ; i < roi.x + roi.width ; i++){
00241                 for (j = roi.y ; j < roi.y + roi.height ; j++){   // for each cell                              
00242                         if(prevData.isInside(i,j,rad)){
00243                                 set(i,j,true);
00244                         }
00245                         else{
00246                                 set(i,j,false);
00247                         }
00248                 }
00249         }
00250 }
00251 
00252 void binMap::remUnconnectRec(int x, int y, const binMap& prevData){
00253         for (int i = x-1 ; i <= x+1; i++){
00254                 for (int j = y-1 ; j <= y+1 ; j++){   // for each cell                          
00255                         if(prevData.get(i,j) && !get(i,j)) {
00256                                 set(i,j,true);
00257                                 remUnconnectRec(i,j,prevData);
00258                         }
00259                 }
00260         }
00261 }
00262 
00263 void binMap::removeUnconnected(int x, int y){
00264         binMap prevData(*this);
00265         clear();
00266         set(x,y,true);
00267         remUnconnectRec(x,y,prevData);
00268 }
00269 
00270 
00271 // Drawing Functions
00272 void binMap::line(int x1, int y1, int x2, int y2){
00273         int i,j ;
00274         float incx, incy, auxx, auxy;
00275         auxx = fabs((float)(x1-x2));
00276         auxy = fabs((float)(y1-y2));
00277         incx = auxx/auxy;
00278         incy = auxy/auxx;
00279 
00280         int count = 0;
00281 
00282         if (incx > incy){
00283                 j = y1;
00284 
00285                 count=1;
00286                 if (x1 < x2){
00287                         for(i = x1; i <= x2; i++){
00288                                 if (fabs((float)(i-x1))>=count*incx) {
00289                                         count++;
00290                                         if (y1<y2)
00291                                                 j++;
00292                                         else
00293                                                 j--;
00294                                 }
00295                                 set(i,j,true);
00296                         }
00297                 }
00298                 else{
00299                         for(i = x1; i >= x2; i--){
00300                                 if (fabs((float)(x1-i))>=count*incx) {
00301                                         count++;
00302                                         if (y1<y2)
00303                                                 j++;
00304                                         else
00305                                                 j--;
00306                                 }
00307                                 set(i,j,true);
00308                         }
00309                 }
00310         }
00311 
00312         else{
00313                 j = x1;
00314 
00315                 count=1;
00316                 if (y1 < y2){
00317                         for(i = y1; i <= y2; i++){
00318                                 if (fabs((float)(i-y1))>=count*incy) {
00319                                         count++;
00320                                         if (x1<x2)
00321                                                 j++;
00322                                         else
00323                                                 j--;
00324                                 }
00325                                 set(j,i,true);
00326                         }
00327                 }
00328                 else{
00329                         for(i = y1; i >= y2; i--){
00330                                 if (fabs((float)(y1-i))>=count*incy) {
00331                                         count++;
00332                                         if (x1<x2)
00333                                                 j++;
00334                                         else
00335                                                 j--;
00336                                 }
00337                                 set(j,i,true);
00338                         }
00339                 }
00340         }
00341 }
00342 
00343 void binMap::saveMapAsImage(const char* file) const{
00344 
00345         IplImage* img = getMapAsImage();
00346         cvSaveImage(file, img);
00347         cvReleaseImage(&img);
00348 }
00349 
00350 void binMap::showMap(const char* windowname)const{
00351         IplImage* img = getMapAsImage();
00352         cvNamedWindow(windowname, 0);
00353         cvShowImage(windowname,img);
00354         cvReleaseImage(&img);
00355 
00356 }
00357 
00358 IplImage* binMap::getMapAsImage() const {
00359         IplImage* img = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 3); 
00360 
00361         for (int i = 0; i< width; i++)
00362                 for(int j = 0; j< height; j++){
00363                         uchar greyvalue = (uchar) (255.0f*get(i,j));
00364                         ((uchar*)(img->imageData + img->widthStep*(height-1-j)))[3*i] = greyvalue;              
00365                         ((uchar*)(img->imageData + img->widthStep*(height-1-j)))[3*i+1] = greyvalue;            
00366                         ((uchar*)(img->imageData + img->widthStep*(height-1-j)))[3*i+2] = greyvalue;            
00367                 }
00368         return img;
00369 }
00370 
00371 int binMap::getPositives(vector<point>& positives) const{
00372         int idx = 0;
00373         int count=0;
00374         positives.reserve(width*height);
00375         for (int j = 0; j< height; j++){
00376                 for (int i = 0; i< width; i++){
00377                         if (cells[idx/32][idx%32]){
00378                                 positives.push_back(point(i,j));
00379                                 count++;
00380                         }
00381                         idx++;
00382                 }
00383         }
00384         return count;
00385 }
00386 
00387 int binMap::cluster(vector<clusterCell>& clusterList, int minSize) const{
00388 
00389         //mapa en blanco de celdas analizadas
00390         binMap aux(getWidth(), getHeight(), getResolution(), getXOrigin(), getYOrigin());
00391 
00392         clusterCell cl;
00393         int count = 0;  // numero de clusters encontrado
00394 
00395         for (int i = getRoi().x ; i < getRoi().x + getRoi().width ; i++){
00396                 for (int j = getRoi().y ; j < getRoi().y + getRoi().height ; j++){   // for each cell
00397                         
00398                         std::list<point> seq;
00399                         clustering(i,j,aux,cl,seq,true);
00400                         
00401                         if (cl.scale >= minSize){ // cluster de al menos 3 celdas
00402 
00403                                 // nos quedamos con la celda central del cluster
00404                                 std::list<point>::iterator it;
00405                                 int k;
00406                                 for( k = 0, it = seq.begin(); it != seq.end() && k <= cl.scale/2; it++ , k++);
00407                                 it--;
00408                                 k--;
00409                                 cl.x = it->x;
00410                                 cl.y = it->y;
00411 
00412                                 count++;
00413         
00414                                 clusterList.push_back(cl);
00415                         }
00416                         cl.x=0;
00417                         cl.y=0;
00418                         cl.scale=0;
00419                 }
00420         }
00421 
00422         return count;
00423 }
00424 
00425 bool binMap::clustering(const int &i, const int &j, binMap& aux, clusterCell& cl, std::list<point> &seq, bool backfront) const{
00426 
00427         if(!aux.get(i,j) && get(i,j) ){  // if ipoint or door
00428                 point p(i,j);
00429                 if (backfront)  seq.push_back(p);
00430                 else    seq.push_front(p);
00431 
00432                 cl.x += i;
00433                 cl.y += j;
00434                 cl.scale++;
00435                 aux.set(i,j,true);
00436 
00437                 int x, y;
00438                 for (x = i-1; x<=i+1; x++){
00439                         for (y = j-1; y<=j+1; y++){                             
00440                                 if (clustering(x,y,aux,cl,seq,backfront)){
00441                                         backfront = !backfront;
00442                                 }
00443                         }
00444                 }
00445                 return true; 
00446         }
00447         else{
00448                 aux.set(i,j,true);
00449                 return false; 
00450         }
00451 }
00452 
00453 void binMap::set(const vector<clusterCell>& cl){
00454         clear();
00455         vector<clusterCell>::const_iterator clit;
00456         for(clit = cl.begin(); clit != cl.end(); clit++)
00457                 set(clit->x, clit->y, true);
00458 }
00459 
00460 int binMap::count() const{
00461         int count=0;
00462         for (int i = getRoi().x ; i < getRoi().x + getRoi().width ; i++)
00463                 for (int j = getRoi().y ; j < getRoi().y + getRoi().height ; j++)   // for each cell
00464                         if (get(i,j)) count++;
00465         return count;
00466 }
00467 
 All Classes Functions Variables Typedefs