MRXT: The Multi-Robot eXploration Tool
Multi-Robot autonomous exploration and mapping simulator.
|
00001 00002 #include "IGPlanner.h" 00003 #include "gridMapInterface.h" 00004 #include <fstream> 00005 #include <math.h> 00006 #include <stdio.h> 00007 #include <list> 00008 #include <vector> 00009 #include <opencv2/opencv.hpp> 00010 #include "StringTokenizer.h" 00011 00012 // Para registrar la clase en la factoria 00013 namespace planners{ 00014 planner* CreateInformationGainPlanner(const ConfigFile& conf){ 00015 return new InformationGainPlanner(conf); 00016 }; 00017 const int IGPLANNER = 3 ; 00018 const bool registered = plannerFactory::Instance().Register(IGPLANNER, plannerCreator(CreateInformationGainPlanner)); 00019 } 00020 00021 00022 using namespace std; 00023 00024 // Constructor 00025 InformationGainPlanner::InformationGainPlanner(const ConfigFile& config): 00026 planner(), 00027 endPlanner(true), 00028 replanning_period(config.read<float>("REPLANNING_PERIOD")), 00029 inflate_obstacles(config.read<int>("INFLATE_OBSTACLES")), 00030 utility_radius(config.read<float>("UTILITY_RADIUS")), 00031 utility_weight(config.read<float>("UTILITY_WEIGHT")), 00032 cost_weight(config.read<float>("COST_WEIGHT")) 00033 {} 00034 00035 // Destructor 00036 InformationGainPlanner::~InformationGainPlanner(){stop();} 00037 00038 // thread Setup 00039 int InformationGainPlanner::setup(){ 00040 00041 // printf("arranco planificador\n"); 00042 completedPath = true; 00043 prio = 50; 00044 return 0; 00045 } 00046 00047 // thread on stop 00048 void InformationGainPlanner::onStop(){ 00049 if (!endPlanner){ 00050 endPlanner = true; 00051 closing.lock(); 00052 closing.unlock(); 00053 } 00054 printf("[CU-PLANNER] [robot %d] Stopped\n", rbase->getNumber()); 00055 } 00056 00057 // thread main execution 00058 void InformationGainPlanner::execute(){ 00059 printf("[CU-PLANNER] \t\t\t\t\t\t COST-UTILITY PLANNER (%d) running\n", rbase->getNumber()); 00060 closing.lock(); 00061 endPlanner = false; 00062 point goal; 00063 int nextStep=number; 00064 00065 FILE* plannerlog=0; 00066 if (logstr){ 00067 char myfilestr[100]; 00068 sprintf(myfilestr,"%splanR%d.log",logstr,number); 00069 plannerlog = fopen(myfilestr,"w"); 00070 } 00071 00072 // char mywindowstr[250]; 00073 // if (showPlanner){ 00074 // sprintf(mywindowstr,"plan%d.jpg",number); 00075 // cvNamedWindow(mywindowstr,0); 00076 // } 00077 // 00078 bool endExploration = false; 00079 int nextPlanning=0; 00080 while(!endPlanner && !endExploration){ 00081 00082 // esperamos a SLAM 00083 nextStep=mySlam->getStep()+1; 00084 //printf("[CU-PLANNER] [robot %d planner] waiting for step %d\n", number, nextStep); 00085 mySlam->waitForStep(nextStep); 00086 00087 if (nextStep > 20000) endExploration = true; 00088 00089 // tomamos los datos 00090 gridMapInterface* omap = mySlam->getOMap(); 00091 binMap* ppmap = mySlam->getPreMap(); 00092 //int numrobots = mySlam->getNumRobots(); 00093 point poscell = mySlam->getCell(number); 00094 pose robotpos = mySlam->getPos(number); 00095 00096 // celda con orientacion 00097 // ocell ori; 00098 // ori.x = poscell.x; 00099 // ori.y = poscell.y; 00100 // float ang = robotpos.th; 00101 // ori.th = int(floor(ang/(PI/4)+0.5)); 00102 // if (ori.th > 7) ori.th -=8; 00103 // if (ori.th < 0) ori.th +=8; 00104 00105 IplImage* im = (showPlanner)? omap->getMapAsImage():0; 00106 00107 // leer mensajes 00108 string msg; 00109 int msglen; 00110 while((msglen=getMessage(msg))){ 00111 //cout << "Message: >> " << msg << endl; 00112 StringTokenizer st(&msg[0]); 00113 string messagetype(st.nextToken()); 00114 if (messagetype == "END"){ 00115 endExploration = true; 00116 completedPath = true; 00117 } 00118 } 00119 00120 bool obstructedPath; 00121 00122 // si hemos llegado al ultimo destino planificamos 00123 if(completedPath == true || nextStep == nextPlanning){ 00124 nextPlanning = nextStep + (int)floor(replanning_period/mySlam->getSampleTime()+0.5); 00125 completedPath = false; 00126 // printf("[IGPLANNER] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PLANNING >>>> robot %d\n",number); 00127 // mapa de fronteras 00128 binMap objectives; 00129 vector<clusterCell> clusterList; 00130 omap->frontiers(objectives); 00131 objectives.cluster(clusterList,2*inflate_obstacles); 00132 objectives.set(clusterList); 00133 //objectives.showMap("FRONTERAS"); 00134 00135 // mapa de costes 00136 vector<point> targets; 00137 vector<point>::iterator targetIter; 00138 // printf("[IGPLANNER] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Creating COST MAP !!!!!!!!!!!\n"); 00139 costMapSimple* cm = createCostMap(poscell,objectives,*omap,targets,inflate_obstacles); 00140 // printf("[IGPLANNER] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> COSTMAP Created !!!!!!!!!!!!!\n"); 00141 00142 // printf("[IGPLANNER] Número de objetivos: %d\n",(int)targets.size()); 00143 00144 // elegir destino 00145 point dest = poscell; 00146 float maxVal = -9999999999999.9f; 00147 int util_cells = ((int)floor(utility_radius/omap->getResolution()+0.5)); 00148 float maxutility = util_cells*util_cells*PI; 00149 float maxcost = cm->getMaxCost(); 00150 for (targetIter = targets.begin(); targetIter!= targets.end(); targetIter++){ 00151 if (targetIter->x!=poscell.x && targetIter->y != poscell.y){ 00152 binMap esz; 00153 omap->esz(targetIter->x,targetIter->y,esz,0,util_cells); 00154 float utilvalue = utility(*omap,esz); 00155 float cost = cm->getCost(targetIter->x,targetIter->y); 00156 float value = utility_weight*utilvalue/maxutility - cost_weight*cost/maxcost; 00157 //printf("(%d,%d) value = %f, utility = %f, cost= %f \n",targetIter->x,targetIter->y,value,utilvalue, cost); 00158 if (value > maxVal){ 00159 maxVal = value; 00160 dest = *targetIter; 00161 } 00162 } 00163 } 00164 00165 // recuperar el path 00166 //printf("origen (%d,%d,%d)\n",ori.x,ori.y,ori.th); 00167 //printf("destino (%d,%d,%d)\n",dest.x,dest.y,dest.th); 00168 cm->getPath(dest,path); 00169 delete cm; 00170 00171 if (targets.size()==0){ 00172 // printf("[IGPLANNER] No path to frontiers, stopping exploration\n"); 00173 endExploration = true; 00174 completedPath = true; 00175 char sms[100]; 00176 sprintf(sms,"END %d", getDir()); 00177 sendMessage(string(sms),-1); 00178 } 00179 // printf("[IGPLANNER] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PLANNING END >>>> robot %d\n",number); 00180 } 00181 00182 // Seguimos con la ruta 00183 else { 00184 00185 // verificamos que el path sea transitable 00186 bool obstructedPath = false; 00187 vector<point>::reverse_iterator riter; 00188 if(path.size()>1) { 00189 for ( riter = path.rbegin(); riter != path.rend(); riter++ ) 00190 if (omap->isoccupied(riter->x,riter->y)) { 00191 // printf("[IGPLANNER] [robot %d] obstructed\n",rbase->getNumber()); 00192 obstructedPath = true; 00193 break; 00194 } 00195 } 00196 // verificar distancia al destino || obstruccion para path completado 00197 if((sqrt(pow((float)(path.front().x-poscell.x),2) + pow((float)(path.front().y-poscell.y),2)) <= 3.0) || obstructedPath){ 00198 // printf("[IGPLANNER] [robot %d] completed\n",rbase->getNumber()); 00199 completedPath = true; 00200 } 00201 else { // No hemos llegado al final seguimos avanzando 00202 bool found=false; 00203 00204 //IplImage* im = (showPlanner)? omap->getMapAsImage() : 0; 00205 //if (showPlanner){ 00206 // cvCircle(im,cvPoint(poscell.x, omap->getHeight()-1-poscell.y),0,CV_RGB(255,0,0),-1); //posicion rojo 00207 // for (unsigned int i = 0;i < path.size(); i++) 00208 // cvCircle(im,cvPoint(path[i].x, omap->getHeight()-1-path[i].y),0,CV_RGB(255,0,255),-1); // path magenta 00209 // cvShowImage(mywindowstr,im); 00210 //} 00211 00212 if(path.size()>=1) { 00213 for ( riter = path.rbegin(); riter != path.rend(); riter++ ){ 00214 bool visible = true; 00215 int size; 00216 point* line = omap->getLine(poscell.x,poscell.y,riter->x,riter->y,size); 00217 00218 for (int p = 0; p < size; p++){ 00219 if (p > 1 && omap->isoccupied(line[p].x,line[p].y,1)){ 00220 visible = false; 00221 break; 00222 } 00223 // else 00224 // cvCircle(im,cvPoint(line[p].x, omap->getHeight()-1-line[p].y),0,CV_RGB(0,255,0),-1); // visual green 00225 } 00226 //cvShowImage(mywindowstr,im); 00227 //cvWaitKey(2); 00228 delete [] line; 00229 if (visible) { // is visible 00230 goal.x = riter->x; 00231 goal.y = riter->y; 00232 if (found) path.pop_back(); 00233 else found = true; 00234 //path.pop_back(); 00235 double dist = sqrt(pow(poscell.x-goal.x,2) + pow(poscell.y-goal.y,2)); 00236 if ( dist > 1.5/omap->getResolution()) break; 00237 } 00238 else break; 00239 } 00240 } 00241 if(!found){ 00242 completedPath = true; // algo falla ninguna celda de la ruta es visible 00243 // printf("[IGPLANNER] [robot %d] no visible cells\n",rbase->getNumber()); 00244 } 00245 //if (showPlanner) cvReleaseImage(&im); 00246 00247 } 00248 // printf("[IGPLANNER] [robot %d] next goal: (%d,%d) - current pos (%d,%d)\n",rbase->getNumber(),goal.x, goal.y, ori.x,ori.y); 00249 } 00250 00251 00252 // visualizacion 00253 // if (showPlanner){ 00254 // cvCircle(im,cvPoint(poscell.x, omap->getHeight()-1-poscell.y),0,CV_RGB(255,0,0),-1); //posicion rojo 00255 // cvCircle(im,cvPoint(poscell.x+avancex[ori.th], omap->getHeight()-1-poscell.y-avancey[ori.th]),0,CV_RGB(0,0,255),-1); // orientacion azul 00256 // for (unsigned int i = 0;i < path.size(); i++) 00257 // cvCircle(im,cvPoint(path[i].x, omap->getHeight()-1-path[i].y),0,CV_RGB(255,0,255),-1); // path magenta 00258 // cvShowImage(mywindowstr,im); 00259 // cvWaitKey(5); 00260 // cvReleaseImage(&im); 00261 // } 00262 00263 if (omap) delete omap; 00264 if (ppmap) delete ppmap; 00265 00266 // modificar los enables/goal de la parte reactiva 00267 if (completedPath) reac->disableAll(); // paramos el robot hasta planificar de nuevo 00268 else{ 00269 // printf("************************************** [robot %d] Following Path\n",number); 00270 00271 reac->setGoal(goal); 00272 reac->enableGoToGoal(); 00273 reac->enableAvoidObstacles(); 00274 reac->disableAvoidOtherRobots(); 00275 reac->disableGoToFrontier(); 00276 reac->disableGoToUnexploredZones(); 00277 reac->disableGoToPrecisePoses(); 00278 } 00279 00280 // write logs 00281 if (logstr) fprintf(plannerlog,"%d, %d, %d, %d\n", nextStep, completedPath, poscell.x, poscell.y); 00282 } 00283 00284 // if (showPlanner) cvDestroyWindow(mywindowstr); 00285 00286 //closing logs 00287 if (logstr) fclose(plannerlog); 00288 00289 // printf("[robot %d] stoping robot", number); 00290 reac->disableAll(); 00291 reac->stop(); 00292 00293 closing.unlock(); 00294 explorationFinished.step(); 00295 } 00296 00297 00298 int InformationGainPlanner::utility(const gridMapInterface& omap, const binMap& esz){ 00299 int value=0; 00300 for (int i = esz.getRoi().x ; i < esz.getRoi().x + esz.getRoi().width ; i++){ 00301 for (int j = esz.getRoi().y ; j < esz.getRoi().y + esz.getRoi().height ; j++){ // for each cell 00302 if (esz.get(i,j) && omap.isunknown(i,j)){ 00303 value++; 00304 } 00305 } 00306 } 00307 return value; 00308 }