Robot's source code

Dependencies:   mbed

Revision:
109:53918ba98306
Parent:
12:235b5545ff41
Child:
117:f8c147141a0c
--- a/Map/Map.cpp	Mon May 04 13:00:28 2015 +0000
+++ b/Map/Map.cpp	Tue May 05 16:35:53 2015 +0000
@@ -0,0 +1,335 @@
+#include "Map.h"
+
+#include "mbed.h"
+#include "Obs_circle.h"
+#include "Obs_rect.h"
+
+extern Serial logger;
+
+Map::Map()
+{
+    
+}
+
+Map::~Map()
+{
+    for(unsigned int i=0;i<obstacles.size();i++)
+        delete obstacles[i];
+}
+
+void Map::build()
+{
+    //obstacles.push_back(new Obs_circle(ROBOTRADIUS,2,2,1));
+    obstacles.push_back(new Obs_rect(ROBOTRADIUS,-100,-100,2100,0)); // MG
+    
+    
+    obstacles.push_back(new Obs_rect(ROBOTRADIUS,778,0,800,400)); // M1
+    obstacles.push_back(new Obs_rect(ROBOTRADIUS,1200,0,1222,400)); // M2
+    obstacles.push_back(new Obs_rect(ROBOTRADIUS,800,0,1200,70)); // M3
+    
+}
+
+int Map::getHeight(float x, float y)
+{
+    int height = 0;
+    for(unsigned int i=0;i<obstacles.size();i++)
+        height += obstacles[i]->height(x,y);
+    return height;
+}
+
+float dist(Point *p1,Point *p2)
+{
+    int dx = p1->getx()-p2->getx();
+    if(dx<0) dx=-dx;
+    int dy = p1->gety()-p2->gety();
+    if(dy<0) dy=-dy;
+    return sqrt((float)dx*dx+dy*dy);
+}
+
+char Map::AStar(float x, float y, float goal_x, float goal_y, float mpc)
+{
+    /*! http://www.gamedev.net/page/resources/_/technical/artificial-intelligence/a-pathfinding-for-beginners-r2003 !*/
+    //float dx,dy; // Permet de diminuer l'erreur par rapport au centre des cases
+    //dx = ((((int)(x/mpc))*mpc-mpc/2)+(((int)(goal_x/mpc))*mpc-mpc/2))/2;
+    
+    Point goal(goal_x/mpc,goal_y/mpc);
+    if(getHeight(goal_x,goal_y) >= 32000)
+    {
+        #if LOG_LEVEL >= 2
+            logger.printf("[warning - pathfinder] Unreachable point (%.3f,%.3f)\r\n",goal_x,goal_y);
+        #endif
+        return 4;
+    }
+    
+    if(getHeight(x,y) >= 32000)
+    {
+        #if LOG_LEVEL >= 2
+            logger.printf("[warning - pathfinder] Unstartable point (%.3f,%.3f)\r\n",x,y);
+        #endif
+        return 5;
+    }
+    
+    
+    unsigned int i=0;
+    
+    std::vector<Point*> openList;
+    openList.push_back(new Point(x/mpc,y/mpc));
+    openList[0]->setG(0);
+    openList[0]->setH(dist(openList[0],&goal));
+    openList[0]->setParent();
+    
+    std::vector<Point*> closeList;
+    
+    Point* current;
+    do
+    {
+        
+        // On cherche le plus petit F dans la liste ouverte
+        current = openList[0];
+        
+        unsigned int pos = 0;
+        for(i=0;i<openList.size();i++)
+            if(openList[i]->getF() < current->getF())
+            {
+                current = openList[i];
+                pos = i;
+            }
+        
+        // On le place dans la liste fermé
+        closeList.push_back(current);
+        openList.erase(openList.begin()+pos);
+        
+        #if LOG_LEVEL >= 4 && LOG_ASTAR
+            logger.printf("[info - pathfinder] Adding (%d,%d) in the closed list\r\n",current->getx(),current->gety());
+            logger.printf("[info - pathfinder] Closed list : %d elements\r\n[info - pathfinder] Opened list : %d elements\r\n",openList.size(),closeList.size());
+        #endif
+        
+        // On ajoute tous ses voisins viable das la liste ouverte
+        for(int dx=-1;dx<=1;dx++)
+        {
+            for(int dy=-1;dy<=1;dy++)
+            {
+                if(dx==0 && dy==0) continue;
+                
+                Point *p = new Point(current->getx()+dx,current->gety()+dy);
+                if(p == 0) // Overload !!!
+                {
+                    for(unsigned int i=0;i<openList.size();i++)
+                        delete openList[i];
+                    for(unsigned int i=0;i<closeList.size();i++)
+                        delete closeList[i];
+                    
+                    path.clear();
+                        
+                    #if LOG_LEVEL >= 1
+                        logger.printf("[error - pathfinder] Overload (%d,%d)\r\n",openList.size(),closeList.size());
+                    #endif
+                    
+                    return 3;
+                }
+                
+                if(p->in(closeList)) // On ignore le point si il est déjà dans la liste fermé
+                {
+                    delete p;
+                    continue; 
+                }
+                
+                int height = getHeight((current->getx()+dx)*mpc,(current->gety()+dy)*mpc);
+                if(height>=32000)  // On ignore le point, il n'est pas accessible
+                {
+                    delete p;
+                    continue; // On ignore le point si il est déjà dans la liste fermé
+                }
+                
+                if(p->in(openList,pos))
+                {
+                    if(dx == 0 || dy == 0) // Mouvement non diagonnal
+                    {
+                        if(current->getG() + NDIAG_COST < openList[pos]->getG())
+                        {
+                            openList[pos]->setG(current->getG() + NDIAG_COST);
+                            openList[pos]->setParent(current);
+                        }
+                    }
+                    else
+                    {
+                        if(current->getG() + DIAG_COST < openList[pos]->getG())
+                        {
+                            openList[pos]->setG(current->getG() + DIAG_COST);
+                            openList[pos]->setParent(current);
+                        }
+                    }
+                    
+                    delete p;
+                }
+                else
+                {
+                    openList.push_back(p);
+                    if(dx == 0 || dy == 0) // Mouvement non diagonnal
+                        p->setG(current->getG() + NDIAG_COST);
+                    else
+                        p->setG(current->getG() + DIAG_COST);
+                    p->setH(height + dist(p,&goal));
+                    p->setParent(current);
+                }
+            }
+        }
+    }
+    while(dist(closeList.back(),&goal) && !openList.empty()); // Tant qu'on a pas atteint la case et qu'on a des choix
+    
+    
+    #if LOG_LEVEL >= 3
+        logger.printf("[info - pathfinder] Closed list : %d elements\r\n[info - pathfinder] Opened list : %d elements\r\n",openList.size(),closeList.size());
+    #endif
+    
+    if(!openList.empty())
+    {
+        for(i=0;i<openList.size();i++)
+            delete openList[i];
+        
+        // On reconstruit le chemin
+        #if LOG_LEVEL >= 3
+            logger.printf("[info - pathfinder] Recontruction du chemin ... ");
+        #endif
+        path.clear();
+        Point* c = closeList.back();
+        while(c != 0)
+        {
+            path.insert(path.begin(),SimplePoint(c->getx()*mpc,c->gety()*mpc));
+            c = c->getParent();
+        }
+        
+        for(i=0;i<closeList.size();i++)
+            delete closeList[i];
+        
+        #if LOG_LEVEL >= 3
+            logger.printf("[done] %d elements\r\n",path.size());
+            logger.printf("[info - pathfinder] Tendage du chemin ... ");
+        #endif
+        
+        
+        // Algo de 'tendage' du chemin
+        bool continuer = true;
+        std::vector<SimplePoint> tempPath;
+        while(continuer)
+        {
+            for(i=1;i<path.size();i+=2)
+            {
+                tempPath.push_back(path[i-1]);
+                int height = (getHeight(path[i-1].x*mpc,path[i-1].y*mpc)+getHeight(path[i+1].x*mpc,path[i+1].y*mpc))/2;
+                
+                #if LOG_LEVEL >= 4 & LOG_TENDEUR
+                    logger.printf("[info - tendeur] Testing (%.3f,%.3f) %d\r\n",path[i].x,path[i].y,height);
+                #endif
+                
+                if(path[i-1].x!=path[i+1].x)
+                {
+                    // y=a*x+b
+                    float a = (path[i-1].y-path[i+1].y)/(path[i-1].x-path[i+1].x);
+                    float b = path[i-1].y - a*path[i-1].x;
+                    
+                    float step = (mpc*0.1f)*cos(atan(a));
+                    
+                    #if LOG_LEVEL >= 4 & LOG_TENDEUR
+                        logger.printf("[info - tendeur] X: a=%.2f b=%.2f\r\n",a,b);
+                        logger.printf("[info - tendeur] x [%.3f,%.3f] step=%.6f\r\n",path[i-1].x,path[i+1].x,step);
+                    #endif
+                    float x;
+                    for(x=min(path[i-1].x,path[i+1].x);x<max(path[i-1].x,path[i+1].x);x+=step)
+                    {
+                        #if LOG_LEVEL >= 4 & LOG_TENDEUR
+                            logger.printf("%.3f\t%.3f\t%.3f\r\n",getHeight(x,(a*x+b)),x,(a*x+b));
+                        #endif
+                        if(getHeight(x,(a*x+b)) > height) // Ca ne passe pas sans ce point
+                        {
+                            tempPath.push_back(path[i]);
+                            
+                            #if LOG_LEVEL >= 4 & LOG_TENDEUR
+                                logger.printf("[info - tendeur] Adding (%.3f,%.3f) to the path\r\n",path[i].x,path[i].y);
+                            #endif
+                            break;
+                        }
+                    }
+                    #if LOG_LEVEL >= 4 & LOG_TENDEUR
+                        if(x >= max(path[i-1].x,path[i+1].x))
+                        {
+                            logger.printf("[info - tendeur] Skipping (%.3f,%.3f) to the path\r\n",path[i].x,path[i].y);
+                        }
+                    #endif
+                }
+                else if(path[i-1].y!=path[i+1].y)
+                {
+                    // x=a*y+b
+                    float a = (path[i-1].x-path[i+1].x)/(path[i-1].y-path[i+1].y);
+                    float b = path[i-1].x - a*path[i-1].y;
+                    
+                    float step = (mpc*0.1f)*cos(atan(a));
+                    
+                    #if LOG_LEVEL >= 4 & LOG_TENDEUR
+                        logger.printf("[info - tendeur] Y: a=%.2f b=%.2f\r\n",a,b);
+                        logger.printf("[info - tendeur] y [%.3f,%.3f] step=%.6f\r\n",path[i-1].y,path[i+1].y,step);
+                    #endif
+                    float y;
+                    for(y=min(path[i-1].y,path[i+1].y);y<max(path[i-1].y,path[i+1].y);y+=step)
+                    {
+                        #if LOG_LEVEL >= 4 & LOG_TENDEUR
+                            logger.printf("%.3f\t%.3f\t%.3f\t%.3f\r\n",getHeight((a*y+b),y),height,(a*y+b),y);
+                        #endif
+                        if(getHeight((a*y+b),y) > height) // Ca ne passe pas sans ce point
+                        {
+                            tempPath.push_back(path[i]);
+                            
+                            #if LOG_LEVEL >= 4 & LOG_TENDEUR
+                                logger.printf("[info - tendeur] Adding (%.3f,%.3f) to the path\r\n",path[i].x,path[i].y);
+                            #endif
+                            break;
+                        }
+                    }
+                    #if LOG_LEVEL >= 4 & LOG_TENDEUR
+                        if(y >= max(path[i-1].y,path[i+1].y))
+                        {
+                            logger.printf("[info - tendeur] Skipping (%.3f,%.3f) to the path\r\n",path[i].x,path[i].y);
+                        }
+                    #endif
+                }
+            }
+            if(path.back() != tempPath.back())
+                tempPath.push_back(path.back());
+            
+            if(tempPath.size() < path.size()) // On a réussit a enlever un point
+            {
+                path.clear();
+                for(i=0;i<tempPath.size();i++)
+                    path.push_back(tempPath[i]);
+                continuer = true;
+            }
+            else
+                continuer = false;
+            
+            tempPath.clear();
+        }
+        
+        #if LOG_LEVEL >= 3
+            logger.printf("[done] %d elements\r\n",path.size());
+        #endif
+        
+        return 1;
+    }
+    else
+    {
+        for(i=0;i<openList.size();i++)
+            delete openList[i];
+        for(i=0;i<closeList.size();i++)
+            delete closeList[i];
+        
+        path.clear();
+        
+        return 2;
+    }
+}
+
+
+
+
+
+