MRXT: The Multi-Robot eXploration Tool
Multi-Robot autonomous exploration and mapping simulator.
|
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