00001 #include <math.h>
00002 #include <vector>
00003 #include <set>
00004 #include "mex.h"
00005 #include "time.h"
00006
00007 using namespace std;
00008
00009 #define max(a,b) (a>=b ? a : b)
00010 #define min(a,b) (a<=b ? a : b)
00011
00012 #define TIME_DEBUG 1
00013
00014 typedef struct{
00015 int x;
00016 int y;
00017 double g;
00018 double h;
00019 bool closed;
00020 } state_t;
00021
00022 vector<state_t> states;
00023
00024 int startX;
00025 int startY;
00026
00027 int transY[8] = {-1,-1,-1,0,0,1,1,1};
00028 int transX[8] = {-1,0,1,-1,1,-1,0,1};
00029 double transC[8] = {sqrt(2),1,sqrt(2),1,1,sqrt(2),1,sqrt(2)};
00030
00031
00032 class stateComparison{
00033 public:
00034
00035 bool operator() (const state_t* s1, const state_t* s2) const{
00036
00037 if(s1==s2)
00038 return false;
00039 double f1 = s1->g+s1->h;
00040 double f2 = s2->g+s2->h;
00041 if(f1==f2)
00042 return s1 < s2;
00043 return f1 < f2;
00044 }
00045 };
00046
00047
00048 double getH(int x, int y){
00049 return 0;
00050 }
00051
00052 void getPreds(state_t* state, vector<state_t*>& preds, vector<double>& costs, double* map, int mapY, int mapX){
00053 int i;
00054
00055
00056
00057 for(i=0; i<8; i++){
00058 int newX = state->x + transX[i];
00059 int newY = state->y + transY[i];
00060
00061
00062 if(newX < 0 || newX >= mapX || newY < 0 || newY >= mapY || map[newY+mapY*newX])
00063 continue;
00064
00065 double c = transC[i];
00066
00067
00068
00069 preds.push_back(&states[newY*mapX + newX]);
00070 costs.push_back(c);
00071 }
00072 }
00073
00074 void runAStar(double* map, int mapY, int mapX, double* start, double* goal, vector<double>& pathX, vector<double>& pathY){
00075 states.resize(mapY*mapX);
00076 startX = ((int)(start[0]+0.5))-1;
00077 startY = ((int)(start[1]+0.5))-1;
00078 int goalX = ((int)(goal[0]+0.5))-1;
00079 int goalY = ((int)(goal[1]+0.5))-1;
00080 mexPrintf("start(%d,%d) goal(%d,%d)\n",startX,startY,goalX,goalY);
00081
00082 mexPrintf("map size (%d %d)\n",mapX,mapY);
00083
00084 #if TIME_DEBUG
00085 clock_t t0 = clock();
00086 #endif
00087
00088 for(int y=0; y<mapY; y++){
00089 for(int x=0; x<mapX; x++){
00090 states[y*mapX+x].x = x;
00091 states[y*mapX+x].y = y;
00092 states[y*mapX+x].g = -1;
00093 states[y*mapX+x].h = getH(x,y);
00094 states[y*mapX+x].closed = false;
00095
00096 }
00097
00098 }
00099 states[goalY*mapX+goalX].g = 0;
00100 mexPrintf("goal state %d %d\n",states[goalY*mapX+goalX].x,states[goalY*mapX+goalX].y);
00101 set<state_t*, stateComparison> queue;
00102 queue.insert(&states[goalY*mapX+goalX]);
00103
00104 #if TIME_DEBUG
00105 clock_t t1 = clock();
00106 mexPrintf("init time = %f\n", ((double)(t1-t0))/CLOCKS_PER_SEC);
00107 t0 = clock();
00108 #endif
00109
00110 while(!queue.empty()){
00111
00112
00113
00114
00115
00116
00117
00118
00119 state_t* s = *(queue.begin());
00120 queue.erase(queue.begin());
00121 vector<state_t*> preds;
00122 vector<double> costs;
00123 getPreds(s,preds,costs,map,mapY,mapX);
00124 if(s->closed){
00125 mexPrintf("Error: we are expanding a state that is already closed\n");
00126 return;
00127 }
00128 s->closed = true;
00129
00130 if(s->x == startX && s->y == startY){
00131 #if TIME_DEBUG
00132 t1 = clock();
00133 mexPrintf("plan time = %f\n", ((double)(t1-t0))/CLOCKS_PER_SEC);
00134 mexPrintf("path cost = %f\n", s->g);
00135 t0 = clock();
00136 #endif
00137
00138 while(true){
00139 vector<state_t*> succs;
00140 vector<double> unused;
00141 getPreds(s,succs,unused,map,mapY,mapX);
00142 pathX.push_back(s->x+1);
00143 pathY.push_back(s->y+1);
00144
00145 state_t* best_state = NULL;
00146 double best_cost = s->g;
00147
00148 for(int i=0; i<succs.size(); i++){
00149 if(succs[i]->x == goalX && succs[i]->y == goalY){
00150 pathX.push_back(succs[i]->x+1);
00151 pathY.push_back(succs[i]->y+1);
00152
00153 #if TIME_DEBUG
00154 t1 = clock();
00155 mexPrintf("path time = %f\n", ((double)(t1-t0))/CLOCKS_PER_SEC);
00156 #endif
00157
00158 return;
00159 }
00160
00161 if(succs[i]->g < best_cost && succs[i]->g >= 0){
00162 best_state = succs[i];
00163 best_cost = succs[i]->g;
00164 }
00165 }
00166 if(!best_state){
00167 mexPrintf("Error: path reconstruction could not find a cheaper successor\n");
00168 pathX.clear();
00169 pathY.clear();
00170 return;
00171 }
00172 s = best_state;
00173 }
00174
00175 }
00176
00177 for(int i=0; i<preds.size(); i++){
00178
00179
00180 if(preds[i]->g < 0 || preds[i]->g > s->g + costs[i]){
00181 set<state_t*>::iterator it = queue.find(preds[i]);
00182 if(it != queue.end()){
00183 if(preds[i] != *it){
00184 mexPrintf("Error: Updating the wrong element in the queue!\n");
00185 return;
00186 }
00187 queue.erase(it);
00188 }
00189 preds[i]->g = s->g + costs[i];
00190 queue.insert(preds[i]);
00191
00192 }
00193 }
00194 }
00195
00196 mexPrintf("Error: Queue is empty and we didn't find the goal\n");
00197 }
00198
00199 void mexFunction( int nlhs, mxArray *plhs[],
00200 int nrhs, const mxArray*prhs[] ){
00201 double *path;
00202 double *map,*robot,*target;
00203 mwSize mapY,mapX;
00204 vector<double> pathX,pathY;
00205
00206 mapY = mxGetM(prhs[0]);
00207 mapX = mxGetN(prhs[0]);
00208
00209 map = mxGetPr(prhs[0]);
00210 robot = mxGetPr(prhs[1]);
00211 target = mxGetPr(prhs[2]);
00212
00213 mexPrintf("robot(%f,%f) target(%f,%f)\n",robot[0],robot[1],target[0],target[1]);
00214
00215 runAStar(map, mapY, mapX, robot,target,pathX,pathY);
00216
00217 plhs[0] = mxCreateDoubleMatrix(pathX.size(), 2, mxREAL);
00218 path = mxGetPr(plhs[0]);
00219
00220 for(int i=0; i<pathX.size(); i++){
00221 path[i] = pathX[i];
00222 path[i+pathX.size()] = pathY[i];
00223 }
00224 mexPrintf("path length = %d\n",pathX.size());
00225 return;
00226 }
00227
00228