MRXT: The Multi-Robot eXploration Tool
Multi-Robot autonomous exploration and mapping simulator.
src/architecture/slam/mapdata/occupancyGridMap.cpp
00001 #include "occupancyGridMap.h"
00002 #include <math.h> 
00003 #include <stdio.h>
00004 #include <string.h>
00005 #include <opencv2/opencv.hpp>
00006 #include "binMap.h"
00007 #include "ClThread.h"
00008 
00009 // Constructors
00010 occupancyGridMap::occupancyGridMap():
00011         width(0),
00012         height(0),
00013         realWidth(0),
00014         realHeight(0),
00015         xorigin(0),
00016         yorigin(0),
00017         resolution(0)
00018 {
00019 
00020 }
00021 
00022 occupancyGridMap::occupancyGridMap(float w, float h, float res, float x, float y):
00023         width((int)floor(w/res+0.5)),
00024         height((int)floor(h/res+0.5)),
00025         realWidth(w),
00026         realHeight(h),
00027         xorigin(x),
00028         yorigin(y),
00029         resolution(res)
00030 {
00031         
00032 }
00033 
00034 gridMapInterface& occupancyGridMap::operator=(const gridMapInterface& gmap){
00035     assert(typeid(gmap) == typeid(*this));
00036     const occupancyGridMap& map = dynamic_cast<const occupancyGridMap&>(gmap);
00037         width = map.width;
00038         height = map.height;
00039         realWidth = map.realWidth;
00040         realHeight = map.realHeight;
00041         xorigin = map.xorigin;
00042         yorigin = map.yorigin;
00043         resolution = map.resolution;
00044         return *this;
00045 }
00046 
00047 occupancyGridMap::~occupancyGridMap(){};
00048 
00049 
00050 // Search
00051 int occupancyGridMap::frontiers(binMap& newfrontiers) const{
00052         int i,j;
00053         int nfront=0;
00054 
00055         newfrontiers.initialize(width,height,resolution, xorigin, yorigin);
00056 
00057         for (i =0 ; i < width ; i++){
00058                 for (j = 0 ; j < height ; j++){                                 // for each cell
00059                         if (isfrontier(i,j)) {                                          // celda en la zona segura
00060                                 newfrontiers.set(i,j,true);
00061                                 nfront++;                       
00062                         }
00063                 }
00064         }
00065         return nfront;
00066 }
00067 
00068 int occupancyGridMap::frontiersIn(const binMap& vz,  binMap& newfrontiers) const{
00069         int i,j;
00070         int nfront=0;
00071 
00072         newfrontiers.initialize(vz.getWidth(),vz.getHeight(),vz.getResolution(), vz.getXOrigin(), vz.getYOrigin());
00073         RoI roi = vz.getRoi();
00074         newfrontiers.setRoi(roi);
00075 
00076         for (i = roi.x ; i < roi.x + roi.width ; i++){
00077                 for (j = roi.y ; j < roi.y + roi.height ; j++){                                 // for each cell
00078                         if (vz.get(i,j) && isfrontier(i,j)) {                                           // celda en la zona segura
00079                                 newfrontiers.set(i,j,true);
00080                                 nfront++;                       
00081                         }
00082                 }
00083         }
00084         return nfront;
00085 }
00086 
00087 void occupancyGridMap::esz(int x, int y, binMap& map, int dilaterad, int max) const{
00088         float max2 = (float)(max*max);
00089 //      printf("[ESZ] map initialize...\n");
00090         map.initialize(width, height, resolution, xorigin, yorigin);
00091 //      printf("[ESZ] map initialize OK\n");
00092         RoI roi;
00093         roi.x = x;
00094         roi.y = y;
00095         roi.width = 1;
00096         roi.height = 1;
00097         map.set(x,y,true);
00098 
00099         // trazamos rayos desde el centro hasta los bordes de un cuadrado de area 2max x 2max
00100         int i,j,ii,jj;
00101         bool visible;
00102         // linea superior
00103         j = y-max;
00104 //      printf("[ESZ] 0'\n");
00105         //printf("new safe zone\n");
00106         for (i = x-max; i <= x+max; i++){
00107                 visible = true;
00108                 int size;
00109 //              printf("[ESZ] get line...\n");
00110                 point* line = getLine(x,y,i,j,size);
00111 //              printf("[ESZ] get line OK\n");
00112                 //printf("new line\n");
00113                 for (int k = 1; k < size; k++){
00114                         ii = line[k].x; jj = line[k].y;
00115                         if (ii>=0 && jj>=0 && ii<width && jj< height){
00116                                 if(visible == true && (isoccupied(ii,jj,dilaterad) || (x-ii)*(x-ii)+(y-jj)*(y-jj)>max2)){ visible = false; break;}
00117                                 //printf("[%d,%d] visible = %d\n",ii,jj,visible);
00118                                 map.set(ii,jj,visible);
00119                                 if (visible){
00120                                         if(ii > roi.x+roi.width-1)              roi.width = ii-roi.x+1;
00121                                         else if(ii < roi.x)                     {roi.width  += roi.x-ii; roi.x    = ii;}
00122                                         if(jj > roi.y+roi.height-1)             roi.height = jj-roi.y+1;
00123                                         else if(jj < roi.y)                     {roi.height += roi.y-jj; roi.y    = jj;}
00124                                 }
00125                         }
00126                 }
00127                 delete[] line;
00128         }
00129 
00130         // linea inferior
00131         j = y+max;
00132 //      printf("[ESZ] 1\n");
00133         for (i = x-max; i <= x+max; i++){
00134                 visible = true;
00135                 int size;
00136 //              printf("[ESZ] get line...\n");
00137                 point* line = getLine(x,y,i,j,size);
00138 //              printf("[ESZ] get line OK\n");
00139                 for (int k = 1; k < size; k++){
00140                         ii = line[k].x; jj = line[k].y;
00141                         if (ii>=0 && jj>=0 && ii<width && jj< height){
00142                                 if(visible == true && (isoccupied(ii,jj,dilaterad) || (x-ii)*(x-ii)+(y-jj)*(y-jj)>max2)) visible = false;
00143                                 map.set(ii,jj,visible);
00144                                 if (visible){
00145                                         if(ii > roi.x+roi.width-1)              roi.width = ii-roi.x+1;
00146                                         else if(ii < roi.x)                     {roi.width  += roi.x-ii; roi.x    = ii;}
00147                                         if(jj > roi.y+roi.height-1)             roi.height = jj-roi.y+1;
00148                                         else if(jj < roi.y)                     {roi.height += roi.y-jj; roi.y    = jj;}
00149                                 }
00150                         }
00151                 }
00152                 delete[] line;
00153         }
00154 
00155         // linea derecha
00156         i = x-max;
00157 //      printf("[ESZ] 2\n");
00158         for (j = y-max+1; j <= y+max-1; j++){
00159                 visible = true;
00160                 int size;
00161 //              printf("[ESZ] get line...\n");
00162                 point* line = getLine(x,y,i,j,size);
00163 //              printf("[ESZ] get line OK\n");
00164                 for (int k = 1; k < size; k++){
00165                         ii = line[k].x; jj = line[k].y;
00166                         if (ii>=0 && jj>=0 && ii<width && jj< height){
00167                                 if(visible == true && (isoccupied(ii,jj,dilaterad) || (x-ii)*(x-ii)+(y-jj)*(y-jj)>max2)) visible = false;
00168                                 map.set(ii,jj,visible);
00169                                 if (visible){
00170                                         if(ii > roi.x+roi.width-1)              roi.width = ii-roi.x+1;
00171                                         else if(ii < roi.x)                     {roi.width  += roi.x-ii; roi.x    = ii;}
00172                                         if(jj > roi.y+roi.height-1)             roi.height = jj-roi.y+1;
00173                                         else if(jj < roi.y)                     {roi.height += roi.y-jj; roi.y    = jj;}
00174                                 }
00175                         }
00176                 }
00177                 delete[] line;
00178         }
00179 
00180         // linea izquierda
00181         i = x+max;
00182 //      printf("[ESZ] 3\n");
00183         for (j = y-max+1; j <= y+max-1; j++){
00184                 visible = true;
00185                 int size;
00186 //              printf("[ESZ] get line...\n");
00187                 point* line = getLine(x,y,i,j,size);
00188 //              printf("[ESZ] get line OK\n");
00189                 for (int k = 1; k < size; k++){
00190                         ii = line[k].x; jj = line[k].y;
00191                         if (ii>=0 && jj>=0 && ii<width && jj< height){
00192                                 if(visible == true && (isoccupied(ii,jj,dilaterad) || (x-ii)*(x-ii)+(y-jj)*(y-jj)>max2)) visible = false;
00193                                 map.set(ii,jj,visible);
00194                                 if (visible){
00195                                         if(ii > roi.x+roi.width-1)              roi.width = ii-roi.x+1;
00196                                         else if(ii < roi.x)                     {roi.width  += roi.x-ii; roi.x    = ii;}
00197                                         if(jj > roi.y+roi.height-1)             roi.height = jj-roi.y+1;
00198                                         else if(jj < roi.y)                     {roi.height += roi.y-jj; roi.y    = jj;}
00199                                 }
00200                         }
00201                 }
00202                 delete[] line;
00203         }
00204 //      printf("[ESZ] 4\n");
00205 
00206         map.setRoi(roi);
00207         map.set(x,y,true);
00208 //      printf("[ESZ] dilate...\n");
00209         map.dilate(dilaterad);
00210 //      printf("[ESZ] dilate OK\n");
00211 }
00212 
00213 point* occupancyGridMap::getLine(int x1, int y1, int x2, int y2, int& points) const{
00214         int i,j,k;
00215 
00216         float incx, incy, auxx, auxy;
00217         auxx = fabs((float)(x1-x2))+0.0001;
00218         auxy = fabs((float)(y1-y2))+0.0001;
00219         incx = auxx/auxy;
00220         incy = auxy/auxx;
00221 
00222         int count = 0;
00223         point* pointbuf;
00224 
00225         if (incx > incy){
00226                 j = y1;
00227 
00228                 points = (int)(auxx+1);
00229                 pointbuf = new point[points]();
00230                 count=1;
00231                 if (x1 < x2){
00232                         for(i = x1,k=0; i <= x2; i++,k++){
00233                                 if (fabs((float)(i-x1))>=count*incx) {
00234                                         count++;
00235                                         (y1<y2)? j++ : j--;
00236                                 }
00237                                 pointbuf[k].x = i;
00238                                 pointbuf[k].y = j;
00239                         }
00240                 }
00241                 else{
00242                         for(i = x1,k=0; i >= x2; i--,k++){
00243                                 if (fabs((float)(x1-i))>=count*incx) {
00244                                         count++;
00245                                         (y1<y2)? j++ : j--;
00246                                 }
00247                                 pointbuf[k].x = i;
00248                                 pointbuf[k].y = j;
00249                         }
00250                 }
00251         }
00252         
00253         else{
00254                 j = x1;
00255                 points = (int)(auxy+1);
00256                 pointbuf = new point[points]();
00257 
00258                 count=1;
00259                 if (y1 < y2){
00260                         for(i = y1,k=0; i <= y2; i++,k++){
00261                                 if (fabs((float)(i-y1))>=count*incy) {
00262                                         count++;
00263                                         (x1<x2)? j++ : j--;
00264                                 }
00265                                 pointbuf[k].x = j;
00266                                 pointbuf[k].y = i;
00267                         }
00268                 }
00269                 else{
00270                         for(i = y1,k=0; i >= y2; i--,k++){
00271                                 if (fabs((float)(y1-i))>=count*incy) {
00272                                         count++;
00273                                         (x1<x2)? j++ : j--;
00274                                 }
00275                                 pointbuf[k].x = j;
00276                                 pointbuf[k].y = i;
00277                         }
00278                 }
00279         }
00280         if (points != k) printf("error!!!\n");
00281         return pointbuf;
00282 }
00283 
00284 void occupancyGridMap::gateways(const binMap& vz, binMap& newgateways) const {
00285         int i,j;
00286         newgateways.initialize(vz.getWidth(),vz.getHeight(),vz.getResolution(), vz.getXOrigin(), vz.getYOrigin());
00287         RoI roi = vz.getRoi();
00288         newgateways.setRoi(roi);
00289         
00290         for (i = roi.x ; i < roi.x + roi.width ; i++){
00291                 for (j = roi.y ; j < roi.y + roi.height ; j++){                         // for each cell
00292                         if (vz.get(i,j) && (!vz.isInsideD(i,j)) && isfreeD(i,j)) {      // celda en la zona segura
00293                                 newgateways.set(i,j,true);
00294                         }
00295                 }
00296         }
00297 }
00298 
00299 void occupancyGridMap::clearUnconnect(binMap& vz,int x, int y) const{
00300         RoI roi = vz.getRoi();
00301         for (int i = roi.x ; i < roi.x + roi.width ; i++)
00302                 for (int j = roi.y ; j < roi.y + roi.height ; j++)                      // for each cell
00303                         if (!isfree(i,j)) vz.set(i,j,false);
00304         vz.removeUnconnected(x,y);
00305 }
00306 
00307 void occupancyGridMap::occupiedCells(binMap& occupied, int dilateRad) const {
00308         int i,j;
00309 
00310         occupied.initialize(width,height,resolution, xorigin, yorigin);
00311         
00312         for (i = 0 ; i < width ; i++){
00313                 for (j =0 ; j < height ; j++){                   // for each cell
00314                         if (isoccupied(i,j,dilateRad)){ // celda ocupada
00315                                 occupied.set(i,j,true);
00316                         }
00317                 }
00318         }
00319 }
00320 
00321 inline bool occupancyGridMap::isfree(int x, int y, int size) const {
00322         for (int i = x-size; i<= x+size; i++)
00323                 for (int j = y-size; j<= y+size; j++)
00324                         if (!isfree(i,j))
00325                                 return false;
00326         return true;
00327 }
00328 
00329 bool occupancyGridMap::isfreeD(int x, int y) const {
00330         int i,j;
00331 
00332         i = x; j = y;
00333         if (!isfree(i,j))       return false;
00334 
00335         i = x+1; j = y;
00336         if (!isfree(i,j))       return false;
00337 
00338         i = x-1; j = y;
00339         if (!isfree(i,j))       return false;
00340 
00341         i = x; j = y+1;
00342         if (!isfree(i,j))       return false;
00343 
00344         i = x; j = y-1;
00345         if (!isfree(i,j))       return false;
00346 
00347         return true;
00348 }
00349 
00350 bool occupancyGridMap::isoccupied(int x, int y, int size) const {
00351         for (int i = x-size; i<= x+size; i++){
00352                 for (int j = y-size; j<= y+size; j++){
00353                         if (isoccupied(i,j)) return true;
00354                 }
00355         }
00356         return false;
00357 }
00358 
00359 float occupancyGridMap::getValue(int x, int y, int range) const {
00360         float val=0.0f;
00361         int count=0;    
00362         for (int i = x-range; i<= x+range; i++){
00363                 for (int j = y-range; j<= y+range; j++){
00364                         val+=getValue(i,j);
00365                         count++;
00366                 }
00367         }
00368         return val/count;
00369 }
00370 
00371 bool occupancyGridMap::isunknown(int x, int y, int size) const {
00372         for (int i = x-size; i<= x+size; i++)
00373                 for (int j = y-size; j<= y+size; j++)
00374                         if (isunknown(i,j))
00375                                 return true;
00376         return false;
00377 }
00378 
00379 void occupancyGridMap::saveMapAsImage(const char* file) const {
00380         IplImage* img = getMapAsImage();
00381         cvSaveImage(file, img);
00382         cvReleaseImage(&img);
00383 }
00384 
00385 IplImage* occupancyGridMap::getMapAsImage() const {
00386         IplImage* img = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U, 3); 
00387 
00388         for (int i = 0; i< width; i++)
00389                 for(int j = 0; j< height; j++){
00390                         uchar greyvalue = (uchar) (255-2.55f*getValue(i,j));
00391                         ((uchar*)(img->imageData + img->widthStep*(height-1-j)))[3*i] = greyvalue;              
00392                         ((uchar*)(img->imageData + img->widthStep*(height-1-j)))[3*i+1] = greyvalue;            
00393                         ((uchar*)(img->imageData + img->widthStep*(height-1-j)))[3*i+2] = greyvalue;            
00394                 }
00395         return img;
00396 }
00397 
00398 void occupancyGridMap::showMap(const char* windowname)const{
00399         IplImage* img = getMapAsImage();
00400         cvNamedWindow(windowname, 0);
00401         cvShowImage(windowname,img);
00402         cvReleaseImage(&img);
00403 }
00404 
00405 int occupancyGridMap::countAccessible(const point* p, int numpoints, binMap& accessible) const{
00406         // N = some floodfill algorithm counting
00407         //printf("[omap] [countAccessible] npoints :%d, map size (%d, %d)\n", numpoints, getWidth(), getHeight());
00408         accessible.initialize(getWidth(), getHeight());
00409         int N=0;
00410         for (int i=0; i< numpoints; i++){
00411         //      printf("[omap] [countAccessible] %d\n",i);
00412                 accessible.set(p[i].x,p[i].y,true);
00413                 N++;
00414                 N+= floodfill(p[i].x,p[i].y,accessible);
00415         }
00416         //printf("[omap] [countAccessible] result %d\n",N);
00417         return N;
00418 }
00419 
00420 int occupancyGridMap::floodfill(const int& nx, const int& ny, binMap& processed) const{
00421         int N=0;
00422         //printf("[TARGETPROBMAPPER]  para el punto (%d, %d), acumulado: %d\n", nx,ny,N);
00423         //printf("[TARGETPROBMAPPER]  size (%d x %d)\n", processed.getWidth(), processed.getHeight());
00424         for (int x = nx-1; x <= nx+1; x++){
00425 //              printf("[TARGETPROBMAPPER]  x=%d\n",x);
00426                 if(x < 0 ||  x>= getWidth()-1) continue;
00427                 for (int y = ny-1; y <= ny+1; y++){
00428 //                      printf("[TARGETPROBMAPPER]  y=%d\n",y);
00429                         if(y < 0 || y >= getHeight()-1) continue;
00430 //                      printf("[TARGETPROBMAPPER]  considering point (%d, %d) processed= %d, is occupied= %d\n", x,y, processed.get(x,y), omap.isoccupied(x,y));
00431                         if(!processed.get(x,y)){
00432                                 processed.set(x,y,true);
00433                                 if(!isoccupied(x,y)){
00434 //                                      omap.showMap("proc");
00435 //                                      printf("[TARGETPROBMAPPER]  iteration ... point (%d, %d) => (%d, %d)\n", nx, ny, x, y); 
00436 //                                      cvWaitKey(2);
00437                                         N += floodfill(x, y, processed)+1;
00438 //                                      printf("[TARGETPROBMAPPER]  N=%d\n",N);
00439                                 }
00440                         }
00441                 }
00442         }
00443         return N;
00444 }
00445 
 All Classes Functions Variables Typedefs