MRXT: The Multi-Robot eXploration Tool
Multi-Robot autonomous exploration and mapping simulator.
|
00001 00002 #include "FSAPlanner.h" 00003 #include "gridMapInterface.h" 00004 #include <fstream> 00005 #include <math.h> 00006 #include <stdio.h> 00007 #include <list> 00008 #include <vector> 00009 #include <algorithm> 00010 #include <opencv2/opencv.hpp> 00011 #include "pathPlanning.h" 00012 #include "StringTokenizer.h" 00013 00014 // Para registrar la clase en la factoria 00015 namespace planners{ 00016 planner* CreateFSAPlanner(const ConfigFile& conf){ 00017 return new FSAPlanner(conf); 00018 }; 00019 const int FSAPLANNER = 1 ; 00020 const bool registered = plannerFactory::Instance().Register(FSAPLANNER, plannerCreator(CreateFSAPlanner)); 00021 } 00022 00023 00024 using namespace std; 00025 00026 // constructor 00027 FSAPlanner::FSAPlanner(const ConfigFile& config): 00028 planner(), 00029 inflate_obstacles(config.read<int>("INFLATE_OBSTACLES")), 00030 integrate_slam(config.read<bool>("INTEGRATE_SLAM")), 00031 escape_allowed(config.read<bool>("ESCAPE_FROM_LOCAL_MINIMA")), 00032 endPlanner(true) 00033 {} 00034 00035 // destructor 00036 FSAPlanner::~FSAPlanner(){stop();} 00037 00038 // thread setup 00039 int FSAPlanner::setup(){ 00040 // printf("arranco planificador\n"); 00041 prio = 50; 00042 completedPath = true; 00043 return 0; 00044 } 00045 00046 // thread on stop 00047 void FSAPlanner::onStop(){ 00048 if (!endPlanner){ 00049 endPlanner = true; 00050 closing.lock(); 00051 closing.unlock(); 00052 } 00053 printf("[BEHAVIOUR_BASED_PLANNER] [robot %d] Stopped\n", rbase->getNumber()); 00054 } 00055 00056 // thread main code 00057 void FSAPlanner::execute(){ 00058 printf("[BEHAVIOUR_BASED_PLANNER] \t\t\t\t BEHAVIOUR_BASED_PLANNER (%d) running\n", rbase->getNumber()); 00059 closing.lock(); 00060 endPlanner = false; 00061 point goal; 00062 int nextStep=number; 00063 00064 // initial state 00065 exploring = true; 00066 returning = false; 00067 escapingFromLocalMinimum = false; 00068 returningEscape = false; 00069 00070 // init logs 00071 FILE* plannerlog=0; 00072 if (logstr){ 00073 char myfilestr[100]; 00074 sprintf(myfilestr,"%splanR%d.log",logstr,number); 00075 plannerlog = fopen(myfilestr,"w"); 00076 } 00077 00078 // char mystr[250]; 00079 // if (showPlanner){ 00080 // sprintf(mystr,"plan%d.jpg",number); 00081 // cvNamedWindow(mystr,0); 00082 // } 00083 00084 bool endExploration = false; 00085 while(!endPlanner && !endExploration){ 00086 00087 nextStep += 1; 00088 // printf("[robot %d planner] waiting for step %d\n", number, nextStep); 00089 mySlam->waitForStep(nextStep); 00090 00091 if (nextStep > 20000) endExploration= true; 00092 00093 gridMapInterface* omap = mySlam->getOMap(); 00094 binMap* ppmap = mySlam->getPreMap(); 00095 //int numrobots = mySlam->getNumRobots(); 00096 point poscell = mySlam->getCell(number); 00097 00098 // printf("[robot %d] Dispersion: %f\n", number, mySlam->getDisp(number)); 00099 00100 00101 // leer mensajes 00102 string msg; 00103 int msglen; 00104 while((msglen=getMessage(msg))){ 00105 //cout << "Message: >> " << msg << endl; 00106 StringTokenizer st(&msg[0]); 00107 string messagetype(st.nextToken()); 00108 if (messagetype == "END"){ 00109 endExploration = true; 00110 completedPath = true; 00111 } 00112 } 00113 if (completedPath){ 00114 exploring = true; 00115 returning = false; 00116 escapingFromLocalMinimum = false; 00117 returningEscape = false; 00118 completedPath = false; 00119 } 00120 if (integrate_slam){ 00121 if ((exploring || escapingFromLocalMinimum) && mySlam->getLoc(number)){ 00122 exploring = false; 00123 returning = true; 00124 escapingFromLocalMinimum = false; 00125 returningEscape = false; 00126 path.clear(); 00127 } 00128 if ((returning || returningEscape) && !mySlam->getLoc(number)){ 00129 exploring = true; 00130 returning = false; 00131 escapingFromLocalMinimum = false; 00132 returningEscape = false; 00133 path.clear(); 00134 } 00135 } 00136 00137 // si hay minimo planificamos 00138 if (escape_allowed){ 00139 if( (exploring || returning) && reac->localMinimum()){ 00140 // printf("[FSAPlanner] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Planificando >>>> robot %d\n",number); 00141 00142 int lenpath; 00143 if(exploring){ 00144 binMap objectives; 00145 vector<clusterCell> clusterList; 00146 omap->frontiers(objectives); 00147 objectives.cluster(clusterList,4); 00148 objectives.set(clusterList); 00149 lenpath = DijkstraGrid(poscell, objectives, *omap, path, inflate_obstacles); // path to frontier 00150 } 00151 else{ // returning 00152 lenpath = DijkstraGrid(poscell, *ppmap, *omap, path, inflate_obstacles); // path to precise pose 00153 } 00154 00155 if (lenpath == 0){ 00156 // printf("No path found, stopping exploration\n"); 00157 endExploration = true; 00158 completedPath = true; 00159 char sms[100]; 00160 sprintf(sms,"END %d", getDir()); 00161 sendMessage(string(sms),-1); 00162 } 00163 else{ 00164 if(exploring){ 00165 escapingFromLocalMinimum = true; 00166 returningEscape = false; 00167 } 00168 else{ 00169 escapingFromLocalMinimum = false; 00170 returningEscape = true; 00171 } 00172 exploring = false; 00173 returning = false; 00174 } 00175 // printf("[FSAPlanner] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Planning end. len = %d >>>> robot %d\n",path.size(), number); 00176 } 00177 } 00178 // if (showPlanner){ // Visualizacion del path 00179 // IplImage* im = omap->getMapAsImage(); 00180 // for (unsigned int i = 0;i < path.size(); i++) 00181 // cvCircle(im,cvPoint(path[i].x, omap->getHeight()-1-path[i].y),0,CV_RGB(255,0,0),-1); 00182 // cvShowImage(mystr,im); 00183 // cvWaitKey(5); 00184 // cvReleaseImage(&im); 00185 // } 00186 00187 00188 // si estamos en planificado quitamos los puntos que hayamos recorrido 00189 if (escapingFromLocalMinimum || returningEscape){ 00190 00191 // verificamos que el path sea transitable 00192 bool obstructedPath = false; 00193 vector<point>::reverse_iterator riter; 00194 if(path.size()>1) { 00195 for ( riter = path.rbegin(); riter != path.rend(); riter++ ) 00196 if (omap->isoccupied(riter->x,riter->y)) { 00197 // printf("[FSAPlanner] [robot %d] obstructed\n",rbase->getNumber()); 00198 obstructedPath = true; 00199 break; 00200 } 00201 } 00202 00203 // verificar distancia al destino || obstruccion para path completado 00204 if((sqrt(pow((float)(path.front().x-poscell.x),2) + pow((float)(path.front().y-poscell.y),2)) <= 3.0) || obstructedPath){ 00205 // printf("[FSAPlanner] [robot %d] completed\n",rbase->getNumber()); 00206 completedPath = true; 00207 } 00208 else { // No hemos llegado al final seguimos avanzando 00209 bool found=false; 00210 00211 //IplImage* im = (showPlanner)? omap->getMapAsImage() : 0; 00212 //if (showPlanner){ 00213 // cvCircle(im,cvPoint(poscell.x, omap->getHeight()-1-poscell.y),0,CV_RGB(255,0,0),-1); //posicion rojo 00214 // for (unsigned int i = 0;i < path.size(); i++) 00215 // cvCircle(im,cvPoint(path[i].x, omap->getHeight()-1-path[i].y),0,CV_RGB(255,0,255),-1); // path magenta 00216 // cvShowImage(mywindowstr,im); 00217 //} 00218 00219 if(path.size()>=1) { 00220 for ( riter = path.rbegin(); riter != path.rend(); riter++ ){ 00221 bool visible = true; 00222 int size; 00223 point* line = omap->getLine(poscell.x,poscell.y,riter->x,riter->y,size); 00224 00225 for (int p = 0; p < size; p++){ 00226 if (p > 1 && omap->isoccupied(line[p].x,line[p].y,1)){ 00227 visible = false; 00228 break; 00229 } 00230 // else 00231 // cvCircle(im,cvPoint(line[p].x, omap->getHeight()-1-line[p].y),0,CV_RGB(0,255,0),-1); // visual green 00232 } 00233 //cvShowImage(mywindowstr,im); 00234 //cvWaitKey(2); 00235 delete [] line; 00236 if (visible) { // is visible 00237 goal.x = riter->x; 00238 goal.y = riter->y; 00239 if (found) path.pop_back(); 00240 else found = true; 00241 //path.pop_back(); 00242 double dist = sqrt(pow(poscell.x-goal.x,2) + pow(poscell.y-goal.y,2)); 00243 if ( dist > 1.5/omap->getResolution()) break; 00244 } 00245 else break; 00246 } 00247 } 00248 if(!found){ 00249 completedPath = true; // algo falla ninguna celda de la ruta es visible 00250 // printf("[FSAPlanner] [robot %d] no visible cells\n",rbase->getNumber()); 00251 } 00252 //if (showPlanner) cvReleaseImage(&im); 00253 00254 } 00255 // printf("[FSAPlanner] [robot %d] next goal: (%d,%d) - current pos (%d,%d)\n",rbase->getNumber(),goal.x, goal.y, poscell.x,poscell.y); 00256 } 00257 00258 delete omap; 00259 delete ppmap; 00260 00261 // modificar los enables/goal de la parte reactiva 00262 if (exploring){ 00263 // printf("[FSAPlanner] ************************************** [robot %d] Reactive\n",number); 00264 00265 reac->enableAvoidObstacles(); 00266 reac->enableAvoidOtherRobots(); 00267 reac->enableGoToFrontier(); 00268 00269 reac->disableGoToUnexploredZones(); 00270 reac->disableGoToGoal(); 00271 reac->disableGoToPrecisePoses(); 00272 } 00273 else if (returning){ 00274 // printf("[FSAPlanner] ************************************** [robot %d] Returning\n",number); 00275 00276 reac->enableAvoidObstacles(); 00277 reac->enableGoToPrecisePoses(); 00278 00279 reac->disableAvoidOtherRobots(); 00280 reac->disableGoToFrontier(); 00281 reac->disableGoToUnexploredZones(); 00282 reac->disableGoToGoal(); 00283 } 00284 else if (escapingFromLocalMinimum || returningEscape){ 00285 // printf("[FSAPlanner] ************************************** [robot %d] Escaping from local minimum\n",number); 00286 00287 reac->setGoal(goal); 00288 00289 reac->enableAvoidObstacles(); 00290 reac->enableGoToGoal(); 00291 00292 reac->disableAvoidOtherRobots(); 00293 reac->disableGoToFrontier(); 00294 reac->disableGoToUnexploredZones(); 00295 reac->disableGoToPrecisePoses(); 00296 } 00297 00298 // write logs 00299 if (logstr){ 00300 fprintf(plannerlog,"%d, %d, %d, %d, %d, %d, %d\n",nextStep, exploring, returning, escapingFromLocalMinimum, returningEscape, poscell.x, poscell.y); 00301 } 00302 } 00303 00304 // if (showPlanner) cvDestroyWindow(mystr); 00305 00306 //closing logs 00307 if (logstr){ 00308 fclose(plannerlog); 00309 } 00310 00311 // printf("[robot %d] stoping robot", number); 00312 reac->disableAll(); 00313 reac->stop(); 00314 00315 closing.unlock(); 00316 explorationFinished.step(); 00317 00318 }