MRXT: The Multi-Robot eXploration Tool
Multi-Robot autonomous exploration and mapping simulator.
|
00001 00002 #include "CoordinatedPlanner.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* CreateCoordinatedPlanner(const ConfigFile& conf){ 00015 return new CoordinatedPlanner(conf); 00016 }; 00017 const int COORDINATEDPLANNER = 4 ; 00018 const bool registered = plannerFactory::Instance().Register(COORDINATEDPLANNER, plannerCreator(CreateCoordinatedPlanner)); 00019 } 00020 00021 using namespace std; 00022 00023 // Constructor 00024 CoordinatedPlanner::CoordinatedPlanner(const ConfigFile& config): 00025 planner(), 00026 endPlanner(true), 00027 destinations(new point[10]), 00028 replanning_period(config.read<float>("REPLANNING_PERIOD")), 00029 inflate_obstacles(config.read<int>("INFLATE_OBSTACLES")), 00030 influence_radius(config.read<float>("INFLUENCE_RADIUS")) 00031 { 00032 // printf("coordinated planner constructed\n"); 00033 } 00034 00035 // Destructor 00036 CoordinatedPlanner::~CoordinatedPlanner(){stop();} 00037 00038 // thread Setup 00039 int CoordinatedPlanner::setup(){ 00040 00041 // printf("arranco planificador\n"); 00042 completedPath = true; 00043 prio = 50; 00044 return 0; 00045 } 00046 00047 // thread on stop 00048 void CoordinatedPlanner::onStop(){ 00049 if (!endPlanner){ 00050 endPlanner = true; 00051 closing.lock(); 00052 closing.unlock(); 00053 } 00054 printf("[COORDINATED_PLANNER] [robot %d] Stopped\n", rbase->getNumber()); 00055 } 00056 00057 // thread main execution 00058 void CoordinatedPlanner::execute(){ 00059 printf("[COORDINATED_PLANNER] \t\t\t\t\t COORDINATED_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("[COORDINATEDPLANNER] [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 int robotid = atoi(st.nextToken()); 00115 if (messagetype == "DEST"){ 00116 if (robotid != number){ 00117 int x = atoi(st.nextToken()); 00118 int y = atoi(st.nextToken()); 00119 destinations[robotid] = point(x,y); 00120 } 00121 } 00122 else if (messagetype == "END"){ 00123 endExploration = true; 00124 completedPath = true; 00125 } 00126 } 00127 00128 bool obstructedPath; 00129 00130 // si hemos llegado al ultimo destino planificamos 00131 if(completedPath == true || nextStep == nextPlanning){ 00132 nextPlanning = nextStep + (int)floor(replanning_period/mySlam->getSampleTime()+0.5); 00133 completedPath = false; 00134 // printf("[COORDINATEDPLANNER] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PLANNING >>>> robot %d\n",number); 00135 // mapa de fronteras 00136 binMap objectives; 00137 vector<clusterCell> clusterList; 00138 omap->frontiers(objectives); 00139 objectives.cluster(clusterList,2*inflate_obstacles); 00140 objectives.set(clusterList); 00141 //objectives.showMap("FRONTERAS"); 00142 00143 // mapa de costes 00144 vector<point> targets; 00145 vector<point>::iterator targetIter; 00146 costMapSimple* cm = createCostMap(poscell,objectives,*omap,targets,inflate_obstacles); 00147 00148 // printf("[COORDINATEDPLANNER] Número de objetivos: %d",(int)targets.size()); 00149 00150 // elegir destino 00151 point dest = poscell; 00152 00153 float maxVal = -9999999999999.9f; 00154 int maxutility = mySlam->getNumRobots(); 00155 float maxcost = cm->getMaxCost(); 00156 00157 int affected_cells = ((int)floor(influence_radius/omap->getResolution()+0.5)); 00158 00159 for (targetIter = targets.begin(); targetIter!= targets.end(); targetIter++){ 00160 if (targetIter->x!=poscell.x && targetIter->y != poscell.y){ 00161 float utility = maxutility; 00162 for (int r=0; r< mySlam->getNumRobots(); r++){ 00163 if (r!=number){ 00164 float dist = sqrt(pow((float)(targetIter->x-destinations[r].x),2) + pow((float)(targetIter->y-destinations[r].y),2)); 00165 if (dist<affected_cells) utility -= 1-dist/affected_cells; 00166 //printf("target robot %d = (%d,%d)\n", r, destinations[r].x, destinations[r].y); 00167 } 00168 } 00169 float cost = cm->getCost(targetIter->x,targetIter->y); 00170 float value = utility/maxutility - 0.5*cost/maxcost; 00171 //printf("(%d,%d) value = %f, utility = %f, cost= %f \n",targetIter->x,targetIter->y,value,utility, cost); 00172 if (value > maxVal){ 00173 maxVal = value; 00174 dest = *targetIter; 00175 } 00176 } 00177 } 00178 00179 // enviar el destino elegido a los otros 00180 char sms[100]; 00181 sprintf(sms,"DEST %d %d %d", number, dest.x, dest.y); 00182 sendMessage(string(sms),-1); 00183 00184 // recuperar el path 00185 //printf("origen (%d,%d,%d)\n",ori.x,ori.y,ori.th); 00186 //printf("destino (%d,%d,%d)\n",dest.x,dest.y,dest.th); 00187 cm->getPath(dest,path); 00188 delete cm; 00189 00190 if (targets.size()==0){ 00191 // printf("[COORDINATEDPLANNER] No path to frontiers, stopping exploration\n"); 00192 endExploration = true; 00193 completedPath = true; 00194 char sms[100]; 00195 sprintf(sms,"END %d", number); 00196 sendMessage(string(sms),-1); 00197 } 00198 // printf("[COORDINATEDPLANNER] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PLANNING END >>>> robot %d\n",number); 00199 } 00200 // Seguimos con la ruta 00201 else { 00202 00203 // verificamos que el path sea transitable 00204 bool obstructedPath = false; 00205 vector<point>::reverse_iterator riter; 00206 if(path.size()>1) { 00207 for ( riter = path.rbegin(); riter != path.rend(); riter++ ) 00208 if (omap->isoccupied(riter->x,riter->y)) { 00209 // printf("[COORDINATEDPLANNER] [robot %d] obstructed\n",rbase->getNumber()); 00210 obstructedPath = true; 00211 break; 00212 } 00213 } 00214 // verificar distancia al destino || obstruccion para path completado 00215 if((sqrt(pow((float)(path.front().x-poscell.x),2) + pow((float)(path.front().y-poscell.y),2)) <= 3.0) || obstructedPath){ 00216 // printf("[COORDINATEDPLANNER] [robot %d] completed\n",rbase->getNumber()); 00217 completedPath = true; 00218 } 00219 else { // No hemos llegado al final seguimos avanzando 00220 bool found=false; 00221 00222 //IplImage* im = (showPlanner)? omap->getMapAsImage() : 0; 00223 //if (showPlanner){ 00224 // cvCircle(im,cvPoint(poscell.x, omap->getHeight()-1-poscell.y),0,CV_RGB(255,0,0),-1); //posicion rojo 00225 // for (unsigned int i = 0;i < path.size(); i++) 00226 // cvCircle(im,cvPoint(path[i].x, omap->getHeight()-1-path[i].y),0,CV_RGB(255,0,255),-1); // path magenta 00227 // cvShowImage(mywindowstr,im); 00228 //} 00229 00230 if(path.size()>=1) { 00231 for ( riter = path.rbegin(); riter != path.rend(); riter++ ){ 00232 bool visible = true; 00233 int size; 00234 point* line = omap->getLine(poscell.x,poscell.y,riter->x,riter->y,size); 00235 00236 for (int p = 0; p < size; p++){ 00237 if (p > 1 && omap->isoccupied(line[p].x,line[p].y,1)){ 00238 visible = false; 00239 break; 00240 } 00241 // else 00242 // cvCircle(im,cvPoint(line[p].x, omap->getHeight()-1-line[p].y),0,CV_RGB(0,255,0),-1); // visual green 00243 } 00244 //cvShowImage(mywindowstr,im); 00245 //cvWaitKey(2); 00246 delete [] line; 00247 if (visible) { // is visible 00248 goal.x = riter->x; 00249 goal.y = riter->y; 00250 if (found) path.pop_back(); 00251 else found = true; 00252 //path.pop_back(); 00253 double dist = sqrt(pow(poscell.x-goal.x,2) + pow(poscell.y-goal.y,2)); 00254 if ( dist > 1.5/omap->getResolution()) break; 00255 } 00256 else break; 00257 } 00258 } 00259 if(!found){ 00260 completedPath = true; // algo falla ninguna celda de la ruta es visible 00261 // printf("[COORDINATEDPLANNER] [robot %d] no visible cells\n",rbase->getNumber()); 00262 } 00263 //if (showPlanner) cvReleaseImage(&im); 00264 00265 } 00266 // printf("[COORDINATEDPLANNER] [robot %d] next goal: (%d,%d) - current pos (%d,%d)\n",rbase->getNumber(),goal.x, goal.y, ori.x,ori.y); 00267 } 00268 00269 // visualizacion 00270 // if (showPlanner){ 00271 // cvCircle(im,cvPoint(poscell.x, omap->getHeight()-1-poscell.y),0,CV_RGB(255,0,0),-1); //posicion rojo 00272 // 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 00273 // for (unsigned int i = 0;i < path.size(); i++) 00274 // cvCircle(im,cvPoint(path[i].x, omap->getHeight()-1-path[i].y),0,CV_RGB(255,0,255),-1); // path magenta 00275 // cvShowImage(mywindowstr,im); 00276 // cvWaitKey(5); 00277 // cvReleaseImage(&im); 00278 // } 00279 00280 delete omap; 00281 delete ppmap; 00282 00283 // modificar los enables/goal de la parte reactiva 00284 if (completedPath) reac->disableAll(); // paramos el robot hasta planificar de nuevo 00285 else{ 00286 // printf("************************************** [robot %d] Following Path\n",number); 00287 00288 reac->setGoal(goal); 00289 reac->enableGoToGoal(); 00290 reac->enableAvoidObstacles(); 00291 reac->disableAvoidOtherRobots(); 00292 reac->disableGoToFrontier(); 00293 reac->disableGoToUnexploredZones(); 00294 reac->disableGoToPrecisePoses(); 00295 } 00296 00297 // write logs 00298 if (logstr) fprintf(plannerlog,"%d, %d, %d, %d\n", nextStep, completedPath, poscell.x, poscell.y); 00299 } 00300 00301 // if (showPlanner) cvDestroyWindow(mywindowstr); 00302 00303 //closing logs 00304 if (logstr) fclose(plannerlog); 00305 00306 // printf("[robot %d] stoping robot", number); 00307 reac->disableAll(); 00308 reac->stop(); 00309 00310 closing.unlock(); 00311 explorationFinished.step(); 00312 }