MRXT: The Multi-Robot eXploration Tool
Multi-Robot autonomous exploration and mapping simulator.
src/architecture/planner/CoordinatedPlanner.cpp
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 }
 All Classes Functions Variables Typedefs