aalgorithm.c

Go to the documentation of this file.
00001 
00011 #include "aalgorithm.h"
00012 #include "pathqueue.h"
00013 #include "map.h"
00014 #include <math.h>
00015 #include <stdlib.h>
00016 
00017 #define SQRT2 1.41421356        
00018 #define WALL_COST       1000    
00020 GraphMapCell graph[MAP_HEIGHT][MAP_WIDTH];      
00022 void pushNodeInOrder(NodeQueue * q, int x, int y);      
00023 float cFunction(int x1, int y1, int x2, int y2);
00024 
00045 int aAlgorithm(double xstart_real,double ystart_real, double xgoal_real, double ygoal_real, double ** original_path){
00052         NodeQueue * prioritySet = newQueue();
00056         Node nbest;
00057         int i, j;
00058         int xcontig, ycontig;
00059         int xstart, ystart, xgoal, ygoal;
00060         // Transform real data in cell data
00061         xstart = ShmapPoint2Cell_X(xstart_real); ystart = ShmapPoint2Cell_Y(ystart_real); 
00062         xgoal = ShmapPoint2Cell_X(xgoal_real); ygoal = ShmapPoint2Cell_Y(ygoal_real); 
00063         
00065 
00066 
00067         initGraphStructure();
00069         calculateMapHeuristic(xgoal, ygoal);
00070 
00072         pushNodeInOrder(prioritySet,xstart,ystart);
00073         graph[ystart][xstart].g = 0;
00074         graph[ystart][xstart].f = graph[ystart][xstart].g + graph[ystart][xstart].h ;
00075         graph[ystart][xstart].bx = xstart;
00076         graph[ystart][xstart].by = ystart;
00077 
00079 
00080         do {
00083                 popNode(prioritySet, &nbest);
00084 
00086                 graph[nbest.y][nbest.x].processed = 1;
00087 
00089                 if((nbest.x==xgoal) && (nbest.y==ygoal)){
00090                         NodeQueue * list = newQueue();          // Auxiliary list
00091                         int nbpoints, count;
00092                         
00093                         // clear prioritySet list
00094                         drainQueue(prioritySet);
00095                         delQueue(prioritySet);
00096                         
00097                         /* Returns a pointer to the path in real coordonates*/
00098                         
00099                         /* Memory allocation for the original path */
00100                         nbpoints = getPathLength(xstart, ystart, xgoal, ygoal);
00101                         (*original_path) = (double *) malloc(2 * sizeof(double) * (nbpoints));
00102                 
00103                         /*
00104                          * Put the path in a LIFO list. The A* algorithm "returns" the path from goal to start.
00105                          * The robot needs the path from start to goal.
00106                          */
00107                         i = xgoal;j = ygoal; 
00108                         pushNodeLast( list, xgoal, ygoal);
00109                         while ( ! ((i== xstart) && (j == ystart)) ) {
00110                                 xcontig = graph[j][i].bx;
00111                                 ycontig = graph[j][i].by;
00112                                 pushNodeLast( list, xcontig, ycontig);
00113                                 i=xcontig;j=ycontig;
00114                         }
00115                 
00116                         // Convert from grid coordonates to real coordonates
00117                         // the first point of the path is the real point
00118                         *((*original_path))     = xstart_real;
00119                         *((*original_path) + 1) = ystart_real;
00120                         popNode( list, &nbest);
00121                         count = 0;
00122                         while(!queueIsEmpty( list)){
00123                                 count++;
00124                                 popNode( list, &nbest);
00125                                 *((*original_path) + count*2)   = ShmapCell2Point_X(nbest.x);
00126                                 *((*original_path) + count*2+1) = ShmapCell2Point_Y(nbest.y);
00127                         }
00128                         // The last point is the real goal
00129                         *((*original_path) + count*2)   = xgoal_real;
00130                         *((*original_path) + count*2+1) = ygoal_real;
00131                         drainQueue(list);
00132                         delQueue(list);
00133                         return nbpoints;
00134                 }
00135 
00137                 for (i=-1;i<=1;i++){
00138                         for (j=-1;j<=1;j++){
00139                                 if (!((i== 0) && (j==0))){ // If we are not in the center cell
00140                                         xcontig=nbest.x+i;ycontig=nbest.y+j;
00141                                         if(ShmapIsCellInMap(xcontig, ycontig) && (graph[ycontig][xcontig].processed == 0)){
00143                                                 if (!isInQueue(prioritySet,xcontig,ycontig)){
00144                                                         //  add to prioritySet.
00145                                                         graph[ycontig][xcontig].g=graph[nbest.y][nbest.x].g + cFunction(nbest.x, nbest.y, xcontig, ycontig);
00146                                                         graph[ycontig][xcontig].f = graph[ycontig][xcontig].g + graph[ycontig][xcontig].h;
00147                                                         graph[ycontig][xcontig].bx=nbest.x;
00148                                                         graph[ycontig][xcontig].by=nbest.y;
00149                                                         if(ShmapIsFreeCell(xcontig, ycontig)) pushNodeInOrder(prioritySet,xcontig,ycontig);
00150                                                 } else if ((graph[nbest.y][nbest.x].g + cFunction(nbest.x, nbest.y, xcontig, ycontig)) < graph[ycontig][xcontig].g){
00152                                                         graph[ycontig][xcontig].bx=nbest.x;
00153                                                         graph[ycontig][xcontig].by=nbest.y;
00154                                                         graph[ycontig][xcontig].g = (graph[nbest.y][nbest.x].g + cFunction(nbest.x, nbest.y, xcontig, ycontig));
00155                                                 }
00156                                         }
00157                                 }
00158                         }
00159                 }
00161         } while(!queueIsEmpty(prioritySet));
00163         delQueue(prioritySet);
00165 
00167         return -1;
00168 
00169 }
00170 
00171 
00172 
00182 float cFunction(int x1, int y1, int x2, int y2)
00183 {
00184         float c;
00185         //if(GETMAPPOS(x2, y2)== MAP_WALL) c = WALL_COST;
00186         if(!ShmapIsFreeCell(x2,y2)) c = WALL_COST;
00187         else if( (x1==x2) || (y1 == y2) ) c=1.0;
00188         else c=SQRT2;
00189         
00190         return c;
00191 
00192 }
00193 
00201 void calculateMapHeuristic(int xgoal, int ygoal){
00210         int i, j;
00211         for(i=0;i<MAP_HEIGHT;i++){
00212                 for (j=0;j<MAP_WIDTH;j++){
00213                         graph[i][j].h=sqrt(abs(xgoal-j)*abs(xgoal-j)+abs(ygoal-i)*abs(ygoal-i));
00214                 }
00215         }
00216 #if 0
00217 /*      This is another way to compute heuristic without SQRT but it don't work properly */
00218 
00219         Node n;
00220         NodeQueue * toProcess = malloc(sizeof(NodeQueue));
00221         int xcontig, ycontig;
00222         float h; // Heuristic distance of cell
00223         float newh;                             // New Heuristic distance of cell
00224         newQueue(toProcess);
00225         graph[ygoal][xgoal].h=0;
00226         graph[ygoal][xgoal].processed=1;
00227         
00228         pushNode(toProcess, xgoal, ygoal);
00229         while(!queueIsEmpty(toProcess)){
00230         //printPrioritySet(toProcess);
00231                 // Pop the first node in the queue
00232         popNode(toProcess,&n);
00233         graph[n.y][n.x].processed=1;
00234                 // Take node's heuristic distance
00235         h = graph[n.y][n.x].h;
00236                 
00237                 // Cross contiguous cells
00238         for (xcontig = n.x-1 ; xcontig <= n.x + 1 ; xcontig++){
00239         for (ycontig = n.y - 1 ; ycontig <= n.y + 1 ; ycontig++){
00240         if(ShmapIsCellInMap(xcontig, ycontig) && (graph[ycontig][xcontig].processed==0)) {
00241                                                 //Add node to priority queue
00242         if ((!isInQueue(toProcess,xcontig,ycontig))) pushNode(toProcess,xcontig,ycontig);
00243                                         // Update heuristic if  [ (Heuristic not set) OR [oldHeuristic is higher than newer)]
00244         newh= h + calculateCost(n.x, n.y, xcontig, ycontig);
00245         if( ( (graph[ycontig][xcontig].h < 0) || (graph[ycontig][xcontig].h > newh )) ) 
00246         graph[ycontig][xcontig].h=newh ;
00247 }
00248                                 
00249 }
00250 }
00251 }
00252 
00253         // Clear proccessed flag        
00254         for(i=0;i<MAP_HEIGHT;i++){
00255         for (j=0;j<MAP_WIDTH;j++){
00256         graph[i][j].processed=0;
00257 }
00258 }
00259 #endif
00260 
00261 }
00262 
00272 float calculateCost(int x1, int y1, int x2, int y2){
00273 
00274         if( (x1==x2) || (y1 == y2) ) return 1.0;
00275         else return SQRT2;
00276 
00277 }
00278 
00291 void initGraphStructure(void){
00292         int i,j;
00293 
00294         //Initialisation of graph structure
00295         for(i=0;i<MAP_HEIGHT;i++){
00296                 for (j=0;j<MAP_WIDTH;j++){
00297                         graph[i][j].h=-1;
00298                         graph[i][j].f=-1;
00299                         graph[i][j].g=0xFFFF;
00300                         graph[i][j].bx=-1;
00301                         graph[i][j].by=-1;
00302                         graph[i][j].processed=0;
00303                 }
00304         }
00305 }
00314 void pushNodeInOrder(NodeQueue * q, int x, int y){
00315         Node *current;
00316         Node *last;
00317         Node *n= malloc(sizeof(Node));
00318 
00319         if (n == NULL) {
00320                 // Memory could not be allocated, so print an error and exit. 
00321                 fprintf(stderr, "Couldn't allocate memory\n");
00322                 exit(EXIT_FAILURE);
00323         }
00324 
00325         n->x=x;
00326         n->y=y;
00327         n->next=NULL;
00328 
00329         if (queueIsEmpty(q)) {
00330                 q->first=n;
00331                 q->last=n;
00332         } else {
00333                 // Put the node in right position
00334                 current=q->first;
00335                 last=NULL;
00336                 while (current!=NULL){
00337                         if ( graph[y][x].f < graph[current->y][current->x].f ){
00338                                 if(last==NULL) q->first = n;
00339                                 else last->next = n;
00340                                 n->next=current;
00341                                 current=NULL;
00342                         } else {
00343                                 if (current->next==NULL){
00344                                         // the node goes in the last position
00345                                         (q->last)->next=n;
00346                                         q->last=n;
00347                                         current = NULL;
00348                                 } else {
00349                                         last=current;
00350                                         current=current->next;
00351                                 }
00352                         }
00353                 }
00354         }
00355 }
00370 int getPathLength(int xstart, int ystart, int xgoal, int ygoal){
00371         int i,j,tmpx, tmpy, nbpoints;
00372         // Count original path length 
00373         i = xgoal;j = ygoal; nbpoints =1;
00374         while ( ! ((i== xstart) && (j == ystart)) ) {
00375                 tmpx = graph[j][i].bx;
00376                 tmpy = graph[j][i].by;
00377                 nbpoints++;
00378                 i=tmpx;j=tmpy;
00379                 ShmapSetCellValue(i,j, MAP_PATH);
00380         }
00381         ShmapSetCellValue(xgoal,ygoal, MAP_GOAL);
00382         ShmapSetCellValue(xstart,ystart, MAP_START);
00383         return nbpoints;
00384 }
00385 

Generated on Thu Sep 13 11:28:28 2007 for DCE-Eurobot by  doxygen 1.5.3