MRXT: The Multi-Robot eXploration Tool
Multi-Robot autonomous exploration and mapping simulator.
src/architecture/planner/IntegratedIGPlanner.cpp
00001 
00002 #include "IntegratedIGPlanner.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 #include "matFuns.h"
00012 #include "robotTypes.h"
00013 
00014 // Para registrar la clase en la factoria
00015 namespace planners{
00016         planner* CreateIntegratedIGPlanner(const ConfigFile& conf){
00017                 return new IntegratedIGPlanner(conf);
00018         };
00019         const int INTEGRATEDIGPLANNER = 6 ;
00020         const bool registered = plannerFactory::Instance().Register(INTEGRATEDIGPLANNER, plannerCreator(CreateIntegratedIGPlanner));
00021 }
00022 
00023 using namespace std;
00024 
00025 // Constructor
00026 IntegratedIGPlanner::IntegratedIGPlanner(const ConfigFile& config):
00027         planner(),
00028         //policy(0),
00029         endPlanner(true),
00030         replanning_period(config.read<float>("REPLANNING_PERIOD")),
00031         inflate_obstacles(config.read<int>("INFLATE_OBSTACLES")),
00032         utility_radius(config.read<float>("UTILITY_RADIUS")),
00033         utility_weight(config.read<float>("UTILITY_WEIGHT")),
00034         cost_weight(config.read<float>("COST_WEIGHT")),
00035         localization_weight(config.read<float>("LOCALIZATION_WEIGHT")),
00036         camrange(config.read<float>("CAMERA_RANGE"))
00037 {}
00038 
00039 // Destructor
00040 IntegratedIGPlanner::~IntegratedIGPlanner(){stop();}
00041 
00042 // thread Setup
00043 int IntegratedIGPlanner::setup(){
00044 
00045 //      printf("arranco planificador\n");
00046         completedPath = true;
00047         prio = 50;
00048         return 0;
00049 }
00050 
00051 // thread on stop
00052 void IntegratedIGPlanner::onStop(){
00053         if (!endPlanner){
00054                 endPlanner = true;
00055                 closing.lock();
00056                 closing.unlock();
00057         }
00058         printf("[INTEGRATED_PLANNER] [robot %d] Stopped\n", rbase->getNumber());
00059 }
00060 
00061 // thread main execution
00062 void IntegratedIGPlanner::execute(){
00063         printf("[INTEGRATED_PLANNER] \t\t\t\t\t INTEGRATED_PLANNER (%d) running\n", rbase->getNumber());
00064         closing.lock();
00065         endPlanner = false;
00066         point goal;     
00067         int nextStep=number;
00068 
00069         FILE* plannerlog=0;
00070         if (logstr){
00071                 char myfilestr[100];
00072                 sprintf(myfilestr,"%splanR%d.log",logstr,number);       
00073                 plannerlog = fopen(myfilestr,"w");
00074         }
00075 
00076 //      char mywindowstr[250];
00077 //      if (showPlanner){
00078 //              sprintf(mywindowstr,"plan%d.jpg",number);
00079 //              cvNamedWindow(mywindowstr,0);
00080 //      }
00081 
00082         bool endExploration = false;
00083         int nextPlanning=0;
00084         while(!endPlanner && !endExploration){
00085 
00086                 // esperamos a SLAM
00087                 nextStep=mySlam->getStep()+1;
00088 //              printf("[INTEGRATEDIGPLANNER] [robot %d planner] waiting for step %d\n", number, nextStep);
00089                 mySlam->waitForStep(nextStep);
00090 
00091                 if (nextStep > 20000) endExploration = true;
00092 
00093                 // tomamos los datos
00094                 gridMapInterface* omap          = mySlam->getOMap();
00095                 binMap* ppmap                   = mySlam->getPreMap();
00096                 //int numrobots                 = mySlam->getNumRobots();
00097                 point poscell                   = mySlam->getCell(number);
00098                 pose robotpos                   = mySlam->getPos(number);
00099                 visualMap* vmap                 = mySlam->getVMap();
00100 
00101                 // celda con orientacion
00102 //              ocell ori;
00103 //              ori.x = poscell.x;
00104 //              ori.y = poscell.y;
00105 //              float ang = robotpos.th;
00106 //              ori.th = int(floor(ang/(PI/4)+0.5));
00107 //              if (ori.th > 7) ori.th -=8;
00108 //              if (ori.th < 0) ori.th +=8;
00109 
00110                 IplImage* im = (showPlanner && rbase->getNumber()==0)? omap->getMapAsImage():0;
00111 
00112                 // leer mensajes
00113                 string msg;
00114                 int msglen;
00115                 while((msglen=getMessage(msg))){
00116                         //cout << "Message: >> " << msg << endl;
00117                         StringTokenizer st(&msg[0]);
00118                         string messagetype(st.nextToken());
00119                         if (messagetype == "END"){
00120                                 endExploration = true;
00121                                 completedPath = true;
00122                         }
00123                 }
00124 
00125                 // si hemos llegado al ultimo destino planificamos
00126                 if(completedPath == true  || nextStep == nextPlanning){
00127                         nextPlanning = nextStep + (int)floor(replanning_period/mySlam->getSampleTime()+0.5);
00128 
00129                         completedPath = false;
00130 //                      printf("[INTEGRATEDIGPLANNER] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PLANNING >>>> robot %d\n",number);
00131                         // mapa de fronteras
00132                         binMap objectives;
00133                         vector<clusterCell> clusterList;
00134                         omap->frontiers(objectives);
00135                         objectives.cluster(clusterList,2*inflate_obstacles);
00136                         objectives.set(clusterList);                    //objectives.showMap("FRONTERAS");
00137                         
00138                         // mapa de costes
00139                         vector<point> targets;
00140                         vector<point>::iterator targetIter;
00141                         costMapSimple* cm = createCostMap(poscell,objectives,*omap,targets,inflate_obstacles);
00142                         
00143 //                      printf("[INTEGRATEDIGPLANNER] Numero de objetivos: %d\n",(int)targets.size());
00144                         
00145                         // elegir destino
00146                         point dest = poscell;
00147                         float maxVal =  -9999999999999.9f;
00148                         int util_cells = ((int)floor(utility_radius/omap->getResolution()+0.5));
00149                         float maxutility =  util_cells*util_cells*PI;
00150                         float maxcost = cm->getMaxCost();
00151                         float det = mySlam->getCovariance(number).det();
00152                         float maxlocutil = -10000.0f;
00153                         if (det > 0) maxlocutil= -0.5*log( pow(PIx2*exp(1.0f),3) *  det);
00154 
00155 //                      printf("[INTEGRATEDIGPLANNER] decidiendo el destino....\n");
00156                         for (targetIter = targets.begin(); targetIter!= targets.end(); targetIter++){
00157 //                              if (fabs(targetIter->x-ori.x) + fabs(targetIter->y - ori.y) > 15){
00158 
00159                                         binMap esz;
00160                                         omap->esz(targetIter->x,targetIter->y,esz,0,util_cells);
00161                                         float utilvalue = IGutility(*omap,esz);
00162                                         float cost = cm->getCost(targetIter->x,targetIter->y);
00163                                         esz.dilate(2);
00164                                         float locvalue = LOCutility(*targetIter,esz,*vmap,mySlam->getGlobalCovariance());
00165 //                                      printf("loc= %f(%f), cost= %f(%f), util= %f(%f)\n",locvalue,maxlocutil,cost,maxcost,utilvalue,maxutility);
00166                                         float value = utility_weight*utilvalue/maxutility - cost_weight*cost/maxcost + localization_weight*locvalue/maxlocutil;
00167                                         //printf("(%d,%d) IGutility = %f, localizability = %f, cost= %f \n",targetIter->x,targetIter->y,utilvalue,locvalue, cost);
00168                                         if (value > maxVal){
00169                                                 maxVal = value;
00170                                                 dest = *targetIter;
00171                                         }
00172 //                              }
00173                         }
00174 //                      printf("[INTEGRATEDIGPLANNER] decidido\n");
00175 
00176                         cm->getPath(dest,path); 
00177 
00178 //                      printf("[INTEGRATEDIGPLANNER] length of the path = %d\n",path.size());
00179                         delete cm;
00180                         
00181                         if (targets.size()==0){
00182 //                              printf("[INTEGRATEDIGPLANNER] No path to frontiers, stopping exploration\n");
00183                                 endPlanner = true;
00184                                 completedPath = true;
00185                                 char sms[100];
00186                                 sprintf(sms,"END %d", getDir()); 
00187                                 sendMessage(string(sms),-1);
00188                         }
00189 //                      printf("[INTEGRATEDIGPLANNER] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PLANNING END >>>> robot %d\n",number);
00190                 }
00191 
00192                 // Seguimos con la ruta
00193                 else {
00194         
00195                         // verificamos que el path sea transitable
00196                         bool obstructedPath = false;
00197                         vector<point>::reverse_iterator riter;
00198                         if(path.size()>1) { 
00199                                 for ( riter = path.rbegin(); riter != path.rend(); riter++ )
00200                                         if (omap->isoccupied(riter->x,riter->y)) { 
00201 //                                              printf("[INTEGRATEDIGPLANNER] [robot %d] obstructed\n",rbase->getNumber()); 
00202                                                 obstructedPath = true;
00203                                                 break;
00204                                         }
00205                         }
00206                         // verificar distancia al destino || obstruccion para path completado
00207                         if((sqrt(pow((float)(path.front().x-poscell.x),2) + pow((float)(path.front().y-poscell.y),2)) <= 3.0)  || obstructedPath){
00208 //                              printf("[INTEGRATEDIGPLANNER] [robot %d] completed\n",rbase->getNumber()); 
00209                                 completedPath = true;
00210                         }
00211                         else { // No hemos llegado al final seguimos avanzando
00212                                 bool found=false;                               
00213 
00214                                 //IplImage* im = (showPlanner)? omap->getMapAsImage() : 0;
00215                                 //if (showPlanner){
00216                                 //      cvCircle(im,cvPoint(poscell.x, omap->getHeight()-1-poscell.y),0,CV_RGB(255,0,0),-1); //posicion rojo    
00217                                 //      for (unsigned int i = 0;i < path.size(); i++)
00218                                 //              cvCircle(im,cvPoint(path[i].x, omap->getHeight()-1-path[i].y),0,CV_RGB(255,0,255),-1); // path magenta
00219                                 //      cvShowImage(mywindowstr,im);
00220                                 //}
00221                                 
00222                                 if(path.size()>=1) {
00223                                         for ( riter = path.rbegin(); riter != path.rend(); riter++ ){
00224                                                 bool visible = true;
00225                                                 int size;
00226                                                 point* line = omap->getLine(poscell.x,poscell.y,riter->x,riter->y,size);
00227                                                 
00228                                                 for (int p = 0; p < size; p++){
00229                                                         if (p > 1 && omap->isoccupied(line[p].x,line[p].y,1)){ 
00230                                                                 visible = false; 
00231                                                                 break;
00232                                                         }
00233                                                 //      else
00234                                                 //              cvCircle(im,cvPoint(line[p].x, omap->getHeight()-1-line[p].y),0,CV_RGB(0,255,0),-1); // visual green
00235                                                 }
00236                                                 //cvShowImage(mywindowstr,im);
00237                                                 //cvWaitKey(2);
00238                                                 delete [] line;
00239                                                 if (visible) { // is visible
00240                                                         goal.x = riter->x;
00241                                                         goal.y = riter->y;
00242                                                         if (found) path.pop_back();
00243                                                         else found = true;
00244                                                         //path.pop_back();
00245                                                         double dist = sqrt(pow(poscell.x-goal.x,2) + pow(poscell.y-goal.y,2));
00246                                                         if ( dist > 1.5/omap->getResolution()) break;
00247                                                 }
00248                                                 else break;
00249                                         }
00250                                 }
00251                                 if(!found){
00252                                         completedPath = true;  // algo falla ninguna celda de la ruta es visible
00253 //                                      printf("[INTEGRATEDIGPLANNER] [robot %d] no visible cells\n",rbase->getNumber()); 
00254                                 }
00255                                 //if (showPlanner) cvReleaseImage(&im);
00256 
00257                         }
00258 //                      printf("[INTEGRATEDIGPLANNER] [robot %d] next goal: (%d,%d) - current pos (%d,%d)\n",rbase->getNumber(),goal.x, goal.y, ori.x,ori.y);                                           
00259                 }
00260 
00261                 // visualizacion
00262 //              if (showPlanner){
00263 //                      cvCircle(im,cvPoint(poscell.x, omap->getHeight()-1-poscell.y),0,CV_RGB(255,0,0),-1); //posicion rojo
00264 //                      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
00265 //                      for (unsigned int i = 0;i < path.size(); i++)
00266 //                              cvCircle(im,cvPoint(path[i].x, omap->getHeight()-1-path[i].y),0,CV_RGB(255,0,255),-1); // path magenta
00267 //                      cvShowImage(mywindowstr,im);
00268 //                      cvWaitKey(5);
00269 //                      cvReleaseImage(&im);
00270 //              }
00271 
00272 
00273                 delete omap;
00274                 delete ppmap;
00275                 delete vmap;
00276 
00277                 //      modificar los enables/goal de la parte reactiva
00278                 if (completedPath)      reac->disableAll();                             // paramos el robot hasta planificar de nuevo
00279                 else{
00280 //                      printf("************************************** [robot %d] Following Path\n",number);
00281 
00282 
00283                         reac->setGoal(goal);
00284                         reac->enableGoToGoal();
00285                         reac->enableAvoidObstacles();                                   
00286                         reac->disableAvoidOtherRobots();
00287                         reac->disableGoToFrontier();
00288                         reac->disableGoToUnexploredZones();
00289                         reac->disableGoToPrecisePoses();        
00290                 }
00291 
00292                 // write logs
00293                 if (logstr)     fprintf(plannerlog,"%d, %d, %d, %d\n", nextStep, completedPath, poscell.x, poscell.y);
00294         }
00295 
00296 //      if (showPlanner) cvDestroyWindow(mywindowstr);
00297 
00298         //closing logs
00299         if (logstr)     fclose(plannerlog);
00300 
00301 //      printf("[robot %d] stoping robot", number);
00302         reac->disableAll();
00303         reac->stop();
00304 
00305         closing.unlock();
00306         explorationFinished.step();
00307 }
00308 
00309 
00310 
00311 float IntegratedIGPlanner::IGutility(const gridMapInterface& omap, const binMap& esz){
00312         float entropy=0;
00313         for (int i = esz.getRoi().x ; i < esz.getRoi().x + esz.getRoi().width ; i++){
00314                 for (int j = esz.getRoi().y ; j < esz.getRoi().y + esz.getRoi().height ; j++){   // for each cell
00315                         if (esz.get(i,j)){
00316                                 float pocc = omap.getValue(i,j)/100.0f;
00317                                 float pemp = 1-pocc;
00318                                 if (pocc > 0 && pemp > 0)
00319                                         entropy += pocc*log(pocc)+pemp*log(pemp);
00320                         }
00321                 }
00322         }
00323         return -entropy;
00324 }
00325 
00326 float IntegratedIGPlanner::LOCutility(const point& oc, const binMap esz, visualMap& vmap, const Ematrix& P){
00327         float camrange2 = camrange*camrange;
00328         int nbots = mySlam->getNumRobots();
00329 
00330         pose pos;
00331         pos.x = mySlam->getXOrigin() + (oc.x+0.5)*mySlam->getResolution();
00332         pos.y = mySlam->getYOrigin() + (oc.y+0.5)*mySlam->getResolution();
00333         pos.th = 0;  //oc.th*PI/4.0f;
00334 
00335         Ematrix Hm(0,0,3*vmap.getNLandmarks(),3*vmap.getNLandmarks());
00336         Ematrix Hv(0,3,3*vmap.getNLandmarks(),3);
00337 
00338         int visiblemarks=0;
00339         int* marksnumbers = new int[vmap.getNLandmarks()];
00340 
00341         Ematrix Hmi             = jacobianHm(pos);
00342 
00343         for (int l = 0; l < vmap.getNLandmarks(); l++){
00344                 landmark* mark = vmap.getLandmarkById(l);
00345                 float dist2 = pow(mark->pos.getX()-pos.x,2)+pow(mark->pos.getY()-pos.y,2);
00346                 if(dist2 < camrange2){
00347                         Hm.extend(3,3);
00348                         Hm.set(3*visiblemarks,3*visiblemarks,Hmi);
00349                         Hv.extend(3,0);
00350                         Hv.set(3*visiblemarks,0,jacobianHv(pos,mark->pos));
00351                         marksnumbers[visiblemarks] = l;
00352                         visiblemarks++;
00353                 }
00354                 delete mark;
00355         }       
00356         
00357         Ematrix Hmtrans = Hm.transpose();
00358         Ematrix Hvtrans = Hv.transpose();
00359         
00360         Ematrix Pom(3*visiblemarks,3*visiblemarks);
00361         for (int l1 = 0; l1 < visiblemarks; l1++){
00362                 for (int l2 = 0; l2 < visiblemarks; l2++){
00363                         Pom.set(l1*3,l2*3,P.subMat(3*nbots+3*marksnumbers[l1],3*nbots+3*marksnumbers[l1]+3,
00364                                                                            3*nbots+3*marksnumbers[l2],3*nbots+3*marksnumbers[l2]+3));
00365                 }
00366         }
00367 
00368         delete[] marksnumbers;
00369         //printf("visiblemarks=%d\n",visiblemarks);
00370         if (visiblemarks > 0){
00371                 Ematrix Pvvinf = (Hvtrans*((Hm*(Pom*Hmtrans)).inverse()*Hv)).inverse();
00372                 //P.print("P=");
00373                 //Pom.print("Pom=");
00374                 //Hm.print("Hm=");
00375                 //Hv.print("Hv=");
00376                 //Pvvinf.print("Pvvinf=");
00377                 float det = Pvvinf.det();
00378                 float locutil = -10000.0f;
00379                 if (det > 0) locutil= -0.5*log( pow(PIx2*exp(1.0f),3) *  det);
00380                 //printf("det= %e, locutil = %f\n",det,locutil);
00381                 return locutil;
00382         }
00383         else return 0.0f;
00384 }
00385 
00386 // jacobian H
00387 matrix IntegratedIGPlanner::jacobianHv(const pose& pos, const pos3d& mark){
00388         matrix H(3,3);
00389         float costh = (float)cos(pos.th);
00390         float sinth = (float)sin(pos.th);
00391         float auxx = mark.getX() - pos.x;
00392         float auxy = mark.getY() - pos.y;
00393         H.set(0,0,-costh);
00394         H.set(0,1,-sinth);
00395         H.set(0,2,-auxx*sinth + auxy*costh );
00396         H.set(1,0, sinth);
00397         H.set(1,1,-costh);
00398         H.set(1,2,-auxx*costh - auxy*sinth );
00399         return H;
00400 }
00401 
00402 matrix IntegratedIGPlanner::jacobianHm(const pose& pos){
00403         matrix H(3,3);
00404         float costh = (float)cos(pos.th);
00405         float sinth = (float)sin(pos.th);
00406         H.set(0,0,costh);
00407         H.set(0,1,sinth);
00408         H.set(1,0,-sinth);
00409         H.set(1,1,costh);
00410         H.set(2,2,1.0f);
00411         return H;
00412 }
 All Classes Functions Variables Typedefs