environment_navxythetalat.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Maxim Likhachev
00003  * All rights reserved.
00004  * 
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  * 
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the University of Pennsylvania nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  * 
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 #include <iostream>
00030 using namespace std;
00031 
00032 #include "../../sbpl/headers.h"
00033 
00034 
00035 #if TIME_DEBUG
00036 static clock_t time3_addallout = 0;
00037 static clock_t time_gethash = 0;
00038 static clock_t time_createhash = 0;
00039 static clock_t time_getsuccs = 0;
00040 #endif
00041 
00042 static long int checks = 0; 
00043 
00044 #define XYTHETA2INDEX(X,Y,THETA) (THETA + X*NAVXYTHETALAT_THETADIRS + Y*EnvNAVXYTHETALATCfg.EnvWidth_c*NAVXYTHETALAT_THETADIRS)
00045 
00046 //-----------------constructors/destructors-------------------------------
00047 EnvironmentNAVXYTHETALATTICE::EnvironmentNAVXYTHETALATTICE()
00048 {
00049         EnvNAVXYTHETALATCfg.obsthresh = ENVNAVXYTHETALAT_DEFAULTOBSTHRESH;
00050         EnvNAVXYTHETALATCfg.cost_inscribed_thresh = EnvNAVXYTHETALATCfg.obsthresh; //the value that pretty much makes it disabled
00051         EnvNAVXYTHETALATCfg.cost_possibly_circumscribed_thresh = -1; //the value that pretty much makes it disabled
00052 
00053         grid2Dsearchfromstart = NULL;
00054         grid2Dsearchfromgoal = NULL;
00055         bNeedtoRecomputeStartHeuristics = true;
00056         bNeedtoRecomputeGoalHeuristics = true;
00057         iteration = 0;
00058 
00059         EnvNAVXYTHETALAT.bInitialized = false;
00060 
00061         EnvNAVXYTHETALATCfg.actionwidth = NAVXYTHETALAT_DEFAULT_ACTIONWIDTH;
00062 
00063         //no memory allocated in cfg yet
00064         EnvNAVXYTHETALATCfg.Grid2D = NULL;
00065         EnvNAVXYTHETALATCfg.ActionsV = NULL;
00066         EnvNAVXYTHETALATCfg.PredActionsV = NULL;
00067 
00068 
00069 }
00070 
00071 EnvironmentNAVXYTHETALATTICE::~EnvironmentNAVXYTHETALATTICE()
00072 {
00073         SBPL_PRINTF("destroying XYTHETALATTICE\n");
00074         if(grid2Dsearchfromstart != NULL)
00075                 delete grid2Dsearchfromstart;
00076         grid2Dsearchfromstart = NULL;
00077 
00078         if(grid2Dsearchfromgoal != NULL)
00079                 delete grid2Dsearchfromgoal;
00080         grid2Dsearchfromgoal = NULL;
00081 
00082         if(EnvNAVXYTHETALATCfg.Grid2D != NULL)
00083         {       
00084                 for (int x = 0; x < EnvNAVXYTHETALATCfg.EnvWidth_c; x++) 
00085                         delete [] EnvNAVXYTHETALATCfg.Grid2D[x];
00086                 delete [] EnvNAVXYTHETALATCfg.Grid2D;
00087                 EnvNAVXYTHETALATCfg.Grid2D = NULL;
00088         }
00089 
00090         //delete actions
00091         if(EnvNAVXYTHETALATCfg.ActionsV != NULL)
00092         {
00093                 for(int tind = 0; tind < NAVXYTHETALAT_THETADIRS; tind++)
00094                         delete [] EnvNAVXYTHETALATCfg.ActionsV[tind];
00095                 delete [] EnvNAVXYTHETALATCfg.ActionsV;
00096                 EnvNAVXYTHETALATCfg.ActionsV = NULL;
00097         }
00098         if(EnvNAVXYTHETALATCfg.PredActionsV != NULL)
00099         {
00100                 delete [] EnvNAVXYTHETALATCfg.PredActionsV;
00101                 EnvNAVXYTHETALATCfg.PredActionsV = NULL;
00102         }
00103 }
00104 
00105 //---------------------------------------------------------------------
00106 
00107 
00108 //-------------------problem specific and local functions---------------------
00109 
00110 
00111 static unsigned int inthash(unsigned int key)
00112 {
00113   key += (key << 12);
00114   key ^= (key >> 22);
00115   key += (key << 4);
00116   key ^= (key >> 9);
00117   key += (key << 10);
00118   key ^= (key >> 2);
00119   key += (key << 7);
00120   key ^= (key >> 12);
00121   return key;
00122 }
00123 
00124 
00125 
00126 void EnvironmentNAVXYTHETALATTICE::SetConfiguration(int width, int height,
00127                                         const unsigned char* mapdata,
00128                                         int startx, int starty, int starttheta,
00129                                         int goalx, int goaly, int goaltheta,
00130                                         double cellsize_m, double nominalvel_mpersecs, double timetoturn45degsinplace_secs, const vector<sbpl_2Dpt_t> & robot_perimeterV) {
00131   EnvNAVXYTHETALATCfg.EnvWidth_c = width;
00132   EnvNAVXYTHETALATCfg.EnvHeight_c = height;
00133   EnvNAVXYTHETALATCfg.StartX_c = startx;
00134   EnvNAVXYTHETALATCfg.StartY_c = starty;
00135   EnvNAVXYTHETALATCfg.StartTheta = starttheta;
00136  
00137   if(EnvNAVXYTHETALATCfg.StartX_c < 0 || EnvNAVXYTHETALATCfg.StartX_c >= EnvNAVXYTHETALATCfg.EnvWidth_c) {
00138     SBPL_ERROR("ERROR: illegal start coordinates\n");
00139     throw new SBPL_Exception();
00140   }
00141   if(EnvNAVXYTHETALATCfg.StartY_c < 0 || EnvNAVXYTHETALATCfg.StartY_c >= EnvNAVXYTHETALATCfg.EnvHeight_c) {
00142     SBPL_ERROR("ERROR: illegal start coordinates\n");
00143     throw new SBPL_Exception();
00144   }
00145   if(EnvNAVXYTHETALATCfg.StartTheta < 0 || EnvNAVXYTHETALATCfg.StartTheta >= NAVXYTHETALAT_THETADIRS) {
00146     SBPL_ERROR("ERROR: illegal start coordinates for theta\n");
00147     throw new SBPL_Exception();
00148   }
00149   
00150   EnvNAVXYTHETALATCfg.EndX_c = goalx;
00151   EnvNAVXYTHETALATCfg.EndY_c = goaly;
00152   EnvNAVXYTHETALATCfg.EndTheta = goaltheta;
00153 
00154   if(EnvNAVXYTHETALATCfg.EndX_c < 0 || EnvNAVXYTHETALATCfg.EndX_c >= EnvNAVXYTHETALATCfg.EnvWidth_c) {
00155     SBPL_ERROR("ERROR: illegal goal coordinates\n");
00156     throw new SBPL_Exception();
00157   }
00158   if(EnvNAVXYTHETALATCfg.EndY_c < 0 || EnvNAVXYTHETALATCfg.EndY_c >= EnvNAVXYTHETALATCfg.EnvHeight_c) {
00159     SBPL_ERROR("ERROR: illegal goal coordinates\n");
00160     throw new SBPL_Exception();
00161   }
00162   if(EnvNAVXYTHETALATCfg.EndTheta < 0 || EnvNAVXYTHETALATCfg.EndTheta >= NAVXYTHETALAT_THETADIRS) {
00163     SBPL_ERROR("ERROR: illegal goal coordinates for theta\n");
00164     throw new SBPL_Exception();
00165   }
00166 
00167   EnvNAVXYTHETALATCfg.FootprintPolygon = robot_perimeterV;
00168 
00169   EnvNAVXYTHETALATCfg.nominalvel_mpersecs = nominalvel_mpersecs;
00170   EnvNAVXYTHETALATCfg.cellsize_m = cellsize_m;
00171   EnvNAVXYTHETALATCfg.timetoturn45degsinplace_secs = timetoturn45degsinplace_secs;
00172 
00173 
00174   //allocate the 2D environment
00175   EnvNAVXYTHETALATCfg.Grid2D = new unsigned char* [EnvNAVXYTHETALATCfg.EnvWidth_c];
00176   for (int x = 0; x < EnvNAVXYTHETALATCfg.EnvWidth_c; x++) {
00177     EnvNAVXYTHETALATCfg.Grid2D[x] = new unsigned char [EnvNAVXYTHETALATCfg.EnvHeight_c];
00178   }
00179   
00180   //environment:
00181   if (0 == mapdata) {
00182     for (int y = 0; y < EnvNAVXYTHETALATCfg.EnvHeight_c; y++) {
00183       for (int x = 0; x < EnvNAVXYTHETALATCfg.EnvWidth_c; x++) {
00184         EnvNAVXYTHETALATCfg.Grid2D[x][y] = 0;
00185       }
00186     }
00187   }
00188   else {
00189     for (int y = 0; y < EnvNAVXYTHETALATCfg.EnvHeight_c; y++) {
00190       for (int x = 0; x < EnvNAVXYTHETALATCfg.EnvWidth_c; x++) {
00191                         EnvNAVXYTHETALATCfg.Grid2D[x][y] = mapdata[x+y*width];
00192       }
00193     }
00194   }
00195 }
00196 
00197 void EnvironmentNAVXYTHETALATTICE::ReadConfiguration(FILE* fCfg)
00198 {
00199         //read in the configuration of environment and initialize  EnvNAVXYTHETALATCfg structure
00200         char sTemp[1024], sTemp1[1024];
00201         int dTemp;
00202         int x, y;
00203 
00204         //discretization(cells)
00205   if(fscanf(fCfg, "%s", sTemp) != 1){
00206     SBPL_ERROR("ERROR: ran out of env file early\n");
00207     throw new SBPL_Exception();
00208   }
00209         strcpy(sTemp1, "discretization(cells):");
00210         if(strcmp(sTemp1, sTemp) != 0)
00211         {
00212                 SBPL_ERROR("ERROR: configuration file has incorrect format\n");
00213                 SBPL_PRINTF("Expected %s got %s\n", sTemp1, sTemp);
00214                 throw new SBPL_Exception();
00215         }
00216   if(fscanf(fCfg, "%s", sTemp) != 1){
00217     SBPL_ERROR("ERROR: ran out of env file early\n");
00218     throw new SBPL_Exception();
00219   }
00220         EnvNAVXYTHETALATCfg.EnvWidth_c = atoi(sTemp);
00221   if(fscanf(fCfg, "%s", sTemp) != 1){
00222     SBPL_ERROR("ERROR: ran out of env file early\n");
00223     throw new SBPL_Exception();
00224   }
00225         EnvNAVXYTHETALATCfg.EnvHeight_c = atoi(sTemp);
00226 
00227         //obsthresh: 
00228   if(fscanf(fCfg, "%s", sTemp) != 1){
00229     SBPL_ERROR("ERROR: ran out of env file early\n");
00230     throw new SBPL_Exception();
00231   }
00232         strcpy(sTemp1, "obsthresh:");
00233         if(strcmp(sTemp1, sTemp) != 0)
00234         {
00235                 SBPL_ERROR("ERROR: configuration file has incorrect format\n");
00236                 SBPL_PRINTF("Expected %s got %s\n", sTemp1, sTemp);
00237                 SBPL_PRINTF("see existing examples of env files for the right format of heading\n");
00238                 throw new SBPL_Exception();
00239         }
00240   if(fscanf(fCfg, "%s", sTemp) != 1){
00241     SBPL_ERROR("ERROR: ran out of env file early\n");
00242     throw new SBPL_Exception();
00243   }
00244         EnvNAVXYTHETALATCfg.obsthresh = atoi(sTemp);
00245         SBPL_PRINTF("obsthresh = %d\n", EnvNAVXYTHETALATCfg.obsthresh);
00246 
00247         //cost_inscribed_thresh: 
00248   if(fscanf(fCfg, "%s", sTemp) != 1){
00249     SBPL_ERROR("ERROR: ran out of env file early\n");
00250     throw new SBPL_Exception();
00251   }
00252         strcpy(sTemp1, "cost_inscribed_thresh:");
00253         if(strcmp(sTemp1, sTemp) != 0)
00254         {
00255                 SBPL_ERROR("ERROR: configuration file has incorrect format\n");
00256                 SBPL_PRINTF("Expected %s got %s\n", sTemp1, sTemp);
00257                 SBPL_PRINTF("see existing examples of env files for the right format of heading\n");
00258                 throw new SBPL_Exception();
00259         }
00260   if(fscanf(fCfg, "%s", sTemp) != 1){
00261     SBPL_ERROR("ERROR: ran out of env file early\n");
00262     throw new SBPL_Exception();
00263   }
00264         EnvNAVXYTHETALATCfg.cost_inscribed_thresh = atoi(sTemp);
00265         SBPL_PRINTF("cost_inscribed_thresh = %d\n", EnvNAVXYTHETALATCfg.cost_inscribed_thresh);
00266 
00267 
00268         //cost_possibly_circumscribed_thresh: 
00269   if(fscanf(fCfg, "%s", sTemp) != 1){
00270     SBPL_ERROR("ERROR: ran out of env file early\n");
00271     throw new SBPL_Exception();
00272   }
00273         strcpy(sTemp1, "cost_possibly_circumscribed_thresh:");
00274         if(strcmp(sTemp1, sTemp) != 0)
00275         {
00276                 SBPL_ERROR("ERROR: configuration file has incorrect format\n");
00277                 SBPL_PRINTF("Expected %s got %s\n", sTemp1, sTemp);
00278                 SBPL_PRINTF("see existing examples of env files for the right format of heading\n");
00279                 throw new SBPL_Exception();
00280         }
00281   if(fscanf(fCfg, "%s", sTemp) != 1){
00282     SBPL_ERROR("ERROR: ran out of env file early\n");
00283     throw new SBPL_Exception();
00284   }
00285         EnvNAVXYTHETALATCfg.cost_possibly_circumscribed_thresh = atoi(sTemp);
00286         SBPL_PRINTF("cost_possibly_circumscribed_thresh = %d\n", EnvNAVXYTHETALATCfg.cost_possibly_circumscribed_thresh);
00287 
00288         
00289         //cellsize
00290   if(fscanf(fCfg, "%s", sTemp) != 1){
00291     SBPL_ERROR("ERROR: ran out of env file early\n");
00292     throw new SBPL_Exception();
00293   }
00294         strcpy(sTemp1, "cellsize(meters):");
00295         if(strcmp(sTemp1, sTemp) != 0)
00296         {
00297                 SBPL_ERROR("ERROR: configuration file has incorrect format\n");
00298                 SBPL_PRINTF("Expected %s got %s\n", sTemp1, sTemp);
00299                 throw new SBPL_Exception();
00300         }
00301   if(fscanf(fCfg, "%s", sTemp) != 1){
00302     SBPL_ERROR("ERROR: ran out of env file early\n");
00303     throw new SBPL_Exception();
00304   }
00305         EnvNAVXYTHETALATCfg.cellsize_m = atof(sTemp);
00306         
00307         //speeds
00308   if(fscanf(fCfg, "%s", sTemp) != 1){
00309     SBPL_ERROR("ERROR: ran out of env file early\n");
00310     throw new SBPL_Exception();
00311   }
00312         strcpy(sTemp1, "nominalvel(mpersecs):");
00313         if(strcmp(sTemp1, sTemp) != 0)
00314         {
00315                 SBPL_ERROR("ERROR: configuration file has incorrect format\n");
00316                 SBPL_PRINTF("Expected %s got %s\n", sTemp1, sTemp);
00317                 throw new SBPL_Exception();
00318         }
00319   if(fscanf(fCfg, "%s", sTemp) != 1){
00320     SBPL_ERROR("ERROR: ran out of env file early\n");
00321     throw new SBPL_Exception();
00322   }
00323         EnvNAVXYTHETALATCfg.nominalvel_mpersecs = atof(sTemp);
00324   if(fscanf(fCfg, "%s", sTemp) != 1){
00325     SBPL_ERROR("ERROR: ran out of env file early\n");
00326     throw new SBPL_Exception();
00327   }
00328         strcpy(sTemp1, "timetoturn45degsinplace(secs):");
00329         if(strcmp(sTemp1, sTemp) != 0)
00330         {
00331                 SBPL_ERROR("ERROR: configuration file has incorrect format\n");
00332                 SBPL_PRINTF("Expected %s got %s\n", sTemp1, sTemp);
00333                 throw new SBPL_Exception();
00334         }
00335   if(fscanf(fCfg, "%s", sTemp) != 1){
00336     SBPL_ERROR("ERROR: ran out of env file early\n");
00337     throw new SBPL_Exception();
00338   }
00339         EnvNAVXYTHETALATCfg.timetoturn45degsinplace_secs = atof(sTemp);
00340 
00341 
00342         //start(meters,rads): 
00343   if(fscanf(fCfg, "%s", sTemp) != 1){
00344     SBPL_ERROR("ERROR: ran out of env file early\n");
00345     throw new SBPL_Exception();
00346   }
00347   if(fscanf(fCfg, "%s", sTemp) != 1){
00348     SBPL_ERROR("ERROR: ran out of env file early\n");
00349     throw new SBPL_Exception();
00350   }
00351         EnvNAVXYTHETALATCfg.StartX_c = CONTXY2DISC(atof(sTemp),EnvNAVXYTHETALATCfg.cellsize_m);
00352   if(fscanf(fCfg, "%s", sTemp) != 1){
00353     SBPL_ERROR("ERROR: ran out of env file early\n");
00354     throw new SBPL_Exception();
00355   }
00356         EnvNAVXYTHETALATCfg.StartY_c = CONTXY2DISC(atof(sTemp),EnvNAVXYTHETALATCfg.cellsize_m);
00357   if(fscanf(fCfg, "%s", sTemp) != 1){
00358     SBPL_ERROR("ERROR: ran out of env file early\n");
00359     throw new SBPL_Exception();
00360   }
00361         EnvNAVXYTHETALATCfg.StartTheta = ContTheta2Disc(atof(sTemp), NAVXYTHETALAT_THETADIRS);
00362 
00363 
00364         if(EnvNAVXYTHETALATCfg.StartX_c < 0 || EnvNAVXYTHETALATCfg.StartX_c >= EnvNAVXYTHETALATCfg.EnvWidth_c)
00365         {
00366                 SBPL_ERROR("ERROR: illegal start coordinates\n");
00367                 throw new SBPL_Exception();
00368         }
00369         if(EnvNAVXYTHETALATCfg.StartY_c < 0 || EnvNAVXYTHETALATCfg.StartY_c >= EnvNAVXYTHETALATCfg.EnvHeight_c)
00370         {
00371                 SBPL_ERROR("ERROR: illegal start coordinates\n");
00372                 throw new SBPL_Exception();
00373         }
00374         if(EnvNAVXYTHETALATCfg.StartTheta < 0 || EnvNAVXYTHETALATCfg.StartTheta >= NAVXYTHETALAT_THETADIRS) {
00375                 SBPL_ERROR("ERROR: illegal start coordinates for theta\n");
00376                 throw new SBPL_Exception();
00377         }
00378 
00379         //end(meters,rads): 
00380   if(fscanf(fCfg, "%s", sTemp) != 1){
00381     SBPL_ERROR("ERROR: ran out of env file early\n");
00382     throw new SBPL_Exception();
00383   }
00384   if(fscanf(fCfg, "%s", sTemp) != 1){
00385     SBPL_ERROR("ERROR: ran out of env file early\n");
00386     throw new SBPL_Exception();
00387   }
00388         EnvNAVXYTHETALATCfg.EndX_c = CONTXY2DISC(atof(sTemp),EnvNAVXYTHETALATCfg.cellsize_m);
00389   if(fscanf(fCfg, "%s", sTemp) != 1){
00390     SBPL_ERROR("ERROR: ran out of env file early\n");
00391     throw new SBPL_Exception();
00392   }
00393         EnvNAVXYTHETALATCfg.EndY_c = CONTXY2DISC(atof(sTemp),EnvNAVXYTHETALATCfg.cellsize_m);
00394   if(fscanf(fCfg, "%s", sTemp) != 1){
00395     SBPL_ERROR("ERROR: ran out of env file early\n");
00396     throw new SBPL_Exception();
00397   }
00398         EnvNAVXYTHETALATCfg.EndTheta = ContTheta2Disc(atof(sTemp), NAVXYTHETALAT_THETADIRS);;
00399 
00400         if(EnvNAVXYTHETALATCfg.EndX_c < 0 || EnvNAVXYTHETALATCfg.EndX_c >= EnvNAVXYTHETALATCfg.EnvWidth_c)
00401         {
00402                 SBPL_ERROR("ERROR: illegal end coordinates\n");
00403                 throw new SBPL_Exception();
00404         }
00405         if(EnvNAVXYTHETALATCfg.EndY_c < 0 || EnvNAVXYTHETALATCfg.EndY_c >= EnvNAVXYTHETALATCfg.EnvHeight_c)
00406         {
00407                 SBPL_ERROR("ERROR: illegal end coordinates\n");
00408                 throw new SBPL_Exception();
00409         }
00410         if(EnvNAVXYTHETALATCfg.EndTheta < 0 || EnvNAVXYTHETALATCfg.EndTheta >= NAVXYTHETALAT_THETADIRS) {
00411                 SBPL_ERROR("ERROR: illegal goal coordinates for theta\n");
00412                 throw new SBPL_Exception();
00413         }
00414 
00415 
00416         //allocate the 2D environment
00417         EnvNAVXYTHETALATCfg.Grid2D = new unsigned char* [EnvNAVXYTHETALATCfg.EnvWidth_c];
00418         for (x = 0; x < EnvNAVXYTHETALATCfg.EnvWidth_c; x++)
00419         {
00420                 EnvNAVXYTHETALATCfg.Grid2D[x] = new unsigned char [EnvNAVXYTHETALATCfg.EnvHeight_c];
00421         }
00422 
00423         //environment:
00424   if(fscanf(fCfg, "%s", sTemp) != 1){
00425     SBPL_ERROR("ERROR: ran out of env file early\n");
00426     throw new SBPL_Exception();
00427   }
00428         for (y = 0; y < EnvNAVXYTHETALATCfg.EnvHeight_c; y++)
00429                 for (x = 0; x < EnvNAVXYTHETALATCfg.EnvWidth_c; x++)
00430                 {
00431                         if(fscanf(fCfg, "%d", &dTemp) != 1)
00432                         {
00433                                 SBPL_ERROR("ERROR: incorrect format of config file\n");
00434                                 throw new SBPL_Exception();
00435                         }
00436                         EnvNAVXYTHETALATCfg.Grid2D[x][y] = dTemp;
00437                 }
00438 
00439 }
00440 
00441 bool EnvironmentNAVXYTHETALATTICE::ReadinCell(EnvNAVXYTHETALAT3Dcell_t* cell, FILE* fIn)
00442 {
00443    char sTemp[60];
00444 
00445         if(fscanf(fIn, "%s", sTemp) == 0)
00446            return false;
00447         cell->x = atoi(sTemp);
00448         if(fscanf(fIn, "%s", sTemp) == 0)
00449            return false;
00450         cell->y = atoi(sTemp);
00451         if(fscanf(fIn, "%s", sTemp) == 0)
00452            return false;
00453         cell->theta = atoi(sTemp);
00454 
00455     //normalize the angle
00456         cell->theta = NORMALIZEDISCTHETA(cell->theta, NAVXYTHETALAT_THETADIRS);
00457 
00458         return true;
00459 }
00460 
00461 bool EnvironmentNAVXYTHETALATTICE::ReadinPose(EnvNAVXYTHETALAT3Dpt_t* pose, FILE* fIn)
00462 {
00463    char sTemp[60];
00464 
00465         if(fscanf(fIn, "%s", sTemp) == 0)
00466            return false;
00467         pose->x = atof(sTemp);
00468         if(fscanf(fIn, "%s", sTemp) == 0)
00469            return false;
00470         pose->y = atof(sTemp);
00471         if(fscanf(fIn, "%s", sTemp) == 0)
00472            return false;
00473         pose->theta = atof(sTemp);
00474 
00475         pose->theta = normalizeAngle(pose->theta);
00476 
00477         return true;
00478 }
00479 
00480 bool EnvironmentNAVXYTHETALATTICE::ReadinMotionPrimitive(SBPL_xytheta_mprimitive* pMotPrim, FILE* fIn)
00481 {
00482     char sTemp[1024];
00483         int dTemp;
00484     char sExpected[1024];
00485     int numofIntermPoses;
00486 
00487     //read in actionID
00488     strcpy(sExpected, "primID:");
00489     if(fscanf(fIn, "%s", sTemp) == 0)
00490         return false;
00491     if(strcmp(sTemp, sExpected) != 0){
00492         SBPL_ERROR("ERROR: expected %s but got %s\n", sExpected, sTemp);
00493         return false;
00494     }
00495     if(fscanf(fIn, "%d", &pMotPrim->motprimID) != 1)
00496         return false;
00497 
00498     //read in start angle
00499     strcpy(sExpected, "startangle_c:");
00500     if(fscanf(fIn, "%s", sTemp) == 0)
00501         return false;
00502     if(strcmp(sTemp, sExpected) != 0){
00503         SBPL_ERROR("ERROR: expected %s but got %s\n", sExpected, sTemp);
00504         return false;
00505     }
00506    if(fscanf(fIn, "%d", &dTemp) == 0)
00507    {
00508            SBPL_ERROR("ERROR reading startangle\n");
00509        return false;    
00510    }
00511    pMotPrim->starttheta_c = dTemp;
00512  
00513    //read in end pose
00514    strcpy(sExpected, "endpose_c:");
00515    if(fscanf(fIn, "%s", sTemp) == 0)
00516        return false;
00517    if(strcmp(sTemp, sExpected) != 0){
00518        SBPL_ERROR("ERROR: expected %s but got %s\n", sExpected, sTemp);
00519        return false;
00520    }
00521 
00522    if(ReadinCell(&pMotPrim->endcell, fIn) == false){
00523                 SBPL_ERROR("ERROR: failed to read in endsearchpose\n");
00524         return false;
00525    }
00526    
00527     //read in action cost
00528     strcpy(sExpected, "additionalactioncostmult:");
00529     if(fscanf(fIn, "%s", sTemp) == 0)
00530         return false;
00531     if(strcmp(sTemp, sExpected) != 0){
00532         SBPL_ERROR("ERROR: expected %s but got %s\n", sExpected, sTemp);
00533         return false;
00534     }
00535     if(fscanf(fIn, "%d", &dTemp) != 1)
00536         return false;
00537         pMotPrim->additionalactioncostmult = dTemp;
00538     
00539     //read in intermediate poses
00540     strcpy(sExpected, "intermediateposes:");
00541     if(fscanf(fIn, "%s", sTemp) == 0)
00542         return false;
00543     if(strcmp(sTemp, sExpected) != 0){
00544         SBPL_ERROR("ERROR: expected %s but got %s\n", sExpected, sTemp);
00545         return false;
00546     }
00547     if(fscanf(fIn, "%d", &numofIntermPoses) != 1)
00548         return false;
00549         //all intermposes should be with respect to 0,0 as starting pose since it will be added later and should be done 
00550         //after the action is rotated by initial orientation
00551     for(int i = 0; i < numofIntermPoses; i++){
00552         EnvNAVXYTHETALAT3Dpt_t intermpose;
00553         if(ReadinPose(&intermpose, fIn) == false){
00554             SBPL_ERROR("ERROR: failed to read in intermediate poses\n");
00555             return false;
00556         }
00557                 pMotPrim->intermptV.push_back(intermpose);
00558     }
00559 
00560         //check that the last pose corresponds correctly to the last pose
00561         EnvNAVXYTHETALAT3Dpt_t sourcepose;
00562         sourcepose.x = DISCXY2CONT(0, EnvNAVXYTHETALATCfg.cellsize_m);
00563         sourcepose.y = DISCXY2CONT(0, EnvNAVXYTHETALATCfg.cellsize_m);
00564         sourcepose.theta = DiscTheta2Cont(pMotPrim->starttheta_c, NAVXYTHETALAT_THETADIRS);
00565         double mp_endx_m = sourcepose.x + pMotPrim->intermptV[pMotPrim->intermptV.size()-1].x;
00566         double mp_endy_m = sourcepose.y + pMotPrim->intermptV[pMotPrim->intermptV.size()-1].y;
00567         double mp_endtheta_rad = pMotPrim->intermptV[pMotPrim->intermptV.size()-1].theta;                               
00568         int endx_c = CONTXY2DISC(mp_endx_m, EnvNAVXYTHETALATCfg.cellsize_m);
00569         int endy_c = CONTXY2DISC(mp_endy_m, EnvNAVXYTHETALATCfg.cellsize_m);
00570         int endtheta_c = ContTheta2Disc(mp_endtheta_rad, NAVXYTHETALAT_THETADIRS);
00571         if(endx_c != pMotPrim->endcell.x || endy_c != pMotPrim->endcell.y || endtheta_c != pMotPrim->endcell.theta)
00572         {       
00573                 SBPL_ERROR("ERROR: incorrect primitive %d with startangle=%d last interm point %f %f %f does not match end pose %d %d %d\n", 
00574                         pMotPrim->motprimID, pMotPrim->starttheta_c,
00575                         pMotPrim->intermptV[pMotPrim->intermptV.size()-1].x, pMotPrim->intermptV[pMotPrim->intermptV.size()-1].y, pMotPrim->intermptV[pMotPrim->intermptV.size()-1].theta,
00576                         pMotPrim->endcell.x, pMotPrim->endcell.y,pMotPrim->endcell.theta);      
00577                         return false;
00578         }
00579 
00580   
00581     return true;
00582 }
00583 
00584 
00585 
00586 bool EnvironmentNAVXYTHETALATTICE::ReadMotionPrimitives(FILE* fMotPrims)
00587 {
00588     char sTemp[1024], sExpected[1024];
00589     float fTemp;
00590         int dTemp;
00591     int totalNumofActions = 0;
00592 
00593     SBPL_PRINTF("Reading in motion primitives...");
00594     
00595     //read in the resolution
00596     strcpy(sExpected, "resolution_m:");
00597     if(fscanf(fMotPrims, "%s", sTemp) == 0)
00598         return false;
00599     if(strcmp(sTemp, sExpected) != 0){
00600         SBPL_ERROR("ERROR: expected %s but got %s\n", sExpected, sTemp);
00601         return false;
00602     }
00603     if(fscanf(fMotPrims, "%f", &fTemp) == 0)
00604         return false;
00605     if(fabs(fTemp-EnvNAVXYTHETALATCfg.cellsize_m) > ERR_EPS){
00606         SBPL_ERROR("ERROR: invalid resolution %f (instead of %f) in the dynamics file\n", 
00607                fTemp, EnvNAVXYTHETALATCfg.cellsize_m);
00608         return false;
00609     }
00610 
00611     //read in the angular resolution
00612     strcpy(sExpected, "numberofangles:");
00613     if(fscanf(fMotPrims, "%s", sTemp) == 0)
00614         return false;
00615     if(strcmp(sTemp, sExpected) != 0){
00616         SBPL_ERROR("ERROR: expected %s but got %s\n", sExpected, sTemp);
00617         return false;
00618     }
00619     if(fscanf(fMotPrims, "%d", &dTemp) == 0)
00620         return false;
00621     if(dTemp != NAVXYTHETALAT_THETADIRS){
00622         SBPL_ERROR("ERROR: invalid angular resolution %d angles (instead of %d angles) in the motion primitives file\n", 
00623                dTemp, NAVXYTHETALAT_THETADIRS);
00624         return false;
00625     }
00626 
00627 
00628     //read in the total number of actions
00629     strcpy(sExpected, "totalnumberofprimitives:");
00630     if(fscanf(fMotPrims, "%s", sTemp) == 0)
00631         return false;
00632     if(strcmp(sTemp, sExpected) != 0){
00633         SBPL_ERROR("ERROR: expected %s but got %s\n", sExpected, sTemp);
00634         return false;
00635     }
00636     if(fscanf(fMotPrims, "%d", &totalNumofActions) == 0){
00637         return false;
00638     }
00639 
00640     for(int i = 0; i < totalNumofActions; i++){
00641                 SBPL_xytheta_mprimitive motprim;
00642 
00643                 if(EnvironmentNAVXYTHETALATTICE::ReadinMotionPrimitive(&motprim, fMotPrims) == false)
00644                         return false;
00645 
00646                 EnvNAVXYTHETALATCfg.mprimV.push_back(motprim);
00647 
00648         }
00649     SBPL_PRINTF("done ");
00650 
00651     return true;
00652 }
00653 
00654 
00655 void EnvironmentNAVXYTHETALATTICE::ComputeReplanningDataforAction(EnvNAVXYTHETALATAction_t* action)
00656 {
00657         int j;
00658 
00659         //iterate over all the cells involved in the action
00660         EnvNAVXYTHETALAT3Dcell_t startcell3d, endcell3d;
00661         for(int i = 0; i < (int)action->intersectingcellsV.size(); i++)
00662         {
00663 
00664                 //compute the translated affected search Pose - what state has an outgoing action whose intersecting cell is at 0,0
00665                 startcell3d.theta = action->starttheta;
00666                 startcell3d.x = - action->intersectingcellsV.at(i).x;
00667                 startcell3d.y = - action->intersectingcellsV.at(i).y;
00668 
00669                 //compute the translated affected search Pose - what state has an incoming action whose intersecting cell is at 0,0
00670                 endcell3d.theta = NORMALIZEDISCTHETA(action->endtheta, NAVXYTHETALAT_THETADIRS); 
00671                 endcell3d.x = startcell3d.x + action->dX; 
00672                 endcell3d.y = startcell3d.y + action->dY;
00673 
00674                 //store the cells if not already there
00675                 for(j = 0; j < (int)affectedsuccstatesV.size(); j++)
00676                 {
00677                         if(affectedsuccstatesV.at(j) == endcell3d)
00678                                 break;
00679                 }
00680                 if (j == (int)affectedsuccstatesV.size())
00681                         affectedsuccstatesV.push_back(endcell3d);
00682 
00683                 for(j = 0; j < (int)affectedpredstatesV.size(); j++)
00684                 {
00685                         if(affectedpredstatesV.at(j) == startcell3d)
00686                                 break;
00687                 }
00688                 if (j == (int)affectedpredstatesV.size())
00689                         affectedpredstatesV.push_back(startcell3d);
00690 
00691     }//over intersecting cells
00692 
00693         
00694 
00695         //add the centers since with h2d we are using these in cost computations
00696         //---intersecting cell = origin
00697         //compute the translated affected search Pose - what state has an outgoing action whose intersecting cell is at 0,0
00698         startcell3d.theta = action->starttheta;
00699         startcell3d.x = - 0;
00700         startcell3d.y = - 0;
00701 
00702         //compute the translated affected search Pose - what state has an incoming action whose intersecting cell is at 0,0
00703         endcell3d.theta = NORMALIZEDISCTHETA(action->endtheta, NAVXYTHETALAT_THETADIRS); 
00704         endcell3d.x = startcell3d.x + action->dX; 
00705         endcell3d.y = startcell3d.y + action->dY;
00706 
00707         //store the cells if not already there
00708         for(j = 0; j < (int)affectedsuccstatesV.size(); j++)
00709         {
00710                 if(affectedsuccstatesV.at(j) == endcell3d)
00711                         break;
00712         }
00713         if (j == (int)affectedsuccstatesV.size())
00714                 affectedsuccstatesV.push_back(endcell3d);
00715 
00716         for(j = 0; j < (int)affectedpredstatesV.size(); j++)
00717         {
00718                 if(affectedpredstatesV.at(j) == startcell3d)
00719                         break;
00720         }
00721         if (j == (int)affectedpredstatesV.size())
00722                 affectedpredstatesV.push_back(startcell3d);
00723 
00724 
00725         //---intersecting cell = outcome state
00726         //compute the translated affected search Pose - what state has an outgoing action whose intersecting cell is at 0,0
00727         startcell3d.theta = action->starttheta;
00728         startcell3d.x = - action->dX;
00729         startcell3d.y = - action->dY;
00730 
00731         //compute the translated affected search Pose - what state has an incoming action whose intersecting cell is at 0,0
00732         endcell3d.theta = NORMALIZEDISCTHETA(action->endtheta, NAVXYTHETALAT_THETADIRS); 
00733         endcell3d.x = startcell3d.x + action->dX; 
00734         endcell3d.y = startcell3d.y + action->dY;
00735 
00736         for(j = 0; j < (int)affectedsuccstatesV.size(); j++)
00737         {
00738                 if(affectedsuccstatesV.at(j) == endcell3d)
00739                         break;
00740         }
00741         if (j == (int)affectedsuccstatesV.size())
00742                 affectedsuccstatesV.push_back(endcell3d);
00743 
00744         for(j = 0; j < (int)affectedpredstatesV.size(); j++)
00745         {
00746                 if(affectedpredstatesV.at(j) == startcell3d)
00747                         break;
00748         }
00749         if (j == (int)affectedpredstatesV.size())
00750                 affectedpredstatesV.push_back(startcell3d);
00751 
00752 
00753 }
00754 
00755 
00756 //computes all the 3D states whose outgoing actions are potentially affected when cell (0,0) changes its status
00757 //it also does the same for the 3D states whose incoming actions are potentially affected when cell (0,0) changes its status
00758 void EnvironmentNAVXYTHETALATTICE::ComputeReplanningData()
00759 {
00760 
00761     //iterate over all actions
00762         //orientations
00763         for(int tind = 0; tind < NAVXYTHETALAT_THETADIRS; tind++)
00764     {        
00765         //actions
00766                 for(int aind = 0; aind < EnvNAVXYTHETALATCfg.actionwidth; aind++)
00767                 {
00768             //compute replanning data for this action 
00769                         ComputeReplanningDataforAction(&EnvNAVXYTHETALATCfg.ActionsV[tind][aind]);
00770                 }
00771         }
00772 }
00773 
00774 //here motionprimitivevector contains actions only for 0 angle
00775 void EnvironmentNAVXYTHETALATTICE::PrecomputeActionswithBaseMotionPrimitive(vector<SBPL_xytheta_mprimitive>* motionprimitiveV)
00776 {
00777 
00778         SBPL_PRINTF("Pre-computing action data using base motion primitives...\n");
00779         EnvNAVXYTHETALATCfg.ActionsV = new EnvNAVXYTHETALATAction_t* [NAVXYTHETALAT_THETADIRS];
00780         EnvNAVXYTHETALATCfg.PredActionsV = new vector<EnvNAVXYTHETALATAction_t*> [NAVXYTHETALAT_THETADIRS];
00781         vector<sbpl_2Dcell_t> footprint;
00782 
00783         //iterate over source angles
00784         for(int tind = 0; tind < NAVXYTHETALAT_THETADIRS; tind++)
00785         {
00786                 SBPL_PRINTF("pre-computing for angle %d out of %d angles\n", tind, NAVXYTHETALAT_THETADIRS);
00787                 EnvNAVXYTHETALATCfg.ActionsV[tind] = new EnvNAVXYTHETALATAction_t[motionprimitiveV->size()];
00788 
00789                 //compute sourcepose
00790                 EnvNAVXYTHETALAT3Dpt_t sourcepose;
00791                 sourcepose.x = DISCXY2CONT(0, EnvNAVXYTHETALATCfg.cellsize_m);
00792                 sourcepose.y = DISCXY2CONT(0, EnvNAVXYTHETALATCfg.cellsize_m);
00793                 sourcepose.theta = DiscTheta2Cont(tind, NAVXYTHETALAT_THETADIRS);
00794 
00795                 //iterate over motion primitives
00796                 for(size_t aind = 0; aind < motionprimitiveV->size(); aind++)
00797                 {
00798                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].aind = aind;
00799                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].starttheta = tind;
00800                         double mp_endx_m = motionprimitiveV->at(aind).intermptV[motionprimitiveV->at(aind).intermptV.size()-1].x;
00801                         double mp_endy_m = motionprimitiveV->at(aind).intermptV[motionprimitiveV->at(aind).intermptV.size()-1].y;
00802                         double mp_endtheta_rad = motionprimitiveV->at(aind).intermptV[motionprimitiveV->at(aind).intermptV.size()-1].theta;
00803                         
00804                         double endx = sourcepose.x + (mp_endx_m*cos(sourcepose.theta) - mp_endy_m*sin(sourcepose.theta));
00805                         double endy = sourcepose.y + (mp_endx_m*sin(sourcepose.theta) + mp_endy_m*cos(sourcepose.theta));
00806                         
00807                         int endx_c = CONTXY2DISC(endx, EnvNAVXYTHETALATCfg.cellsize_m);
00808                         int endy_c = CONTXY2DISC(endy, EnvNAVXYTHETALATCfg.cellsize_m);
00809 
00810                         
00811                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta = ContTheta2Disc(mp_endtheta_rad+sourcepose.theta, NAVXYTHETALAT_THETADIRS);
00812                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX = endx_c;
00813                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY = endy_c;
00814                         if(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY != 0 || EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX != 0)
00815                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost = (int)(ceil(NAVXYTHETALAT_COSTMULT_MTOMM*EnvNAVXYTHETALATCfg.cellsize_m/EnvNAVXYTHETALATCfg.nominalvel_mpersecs*
00816                                                                 sqrt((double)(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX*EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX + 
00817                                                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY*EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY))));
00818                         else //cost of turn in place
00819                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost = (int)(NAVXYTHETALAT_COSTMULT_MTOMM*
00820                                                 EnvNAVXYTHETALATCfg.timetoturn45degsinplace_secs*fabs(computeMinUnsignedAngleDiff(mp_endtheta_rad,0))/(PI_CONST/4.0));
00821 
00822                         //compute and store interm points as well as intersecting cells
00823                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV.clear();
00824                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV.clear();
00825                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].interm3DcellsV.clear();
00826                         EnvNAVXYTHETALAT3Dcell_t previnterm3Dcell;
00827                         previnterm3Dcell.theta = previnterm3Dcell.x = previnterm3Dcell.y = 0;
00828                         for (int pind = 0; pind < (int)motionprimitiveV->at(aind).intermptV.size(); pind++)
00829                         {
00830                                 EnvNAVXYTHETALAT3Dpt_t intermpt = motionprimitiveV->at(aind).intermptV[pind];
00831                 
00832                                 //rotate it appropriately
00833                                 double rotx = intermpt.x*cos(sourcepose.theta) - intermpt.y*sin(sourcepose.theta);
00834                                 double roty = intermpt.x*sin(sourcepose.theta) + intermpt.y*cos(sourcepose.theta);
00835                                 intermpt.x = rotx;
00836                                 intermpt.y = roty;
00837                                 intermpt.theta = normalizeAngle(sourcepose.theta + intermpt.theta);
00838 
00839                                 //store it (they are with reference to 0,0,stattheta (not sourcepose.x,sourcepose.y,starttheta (that is, half-bin))
00840                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV.push_back(intermpt);
00841 
00842                                 //now compute the intersecting cells (for this pose has to be translated by sourcepose.x,sourcepose.y
00843                                 EnvNAVXYTHETALAT3Dpt_t pose;
00844                                 pose = intermpt;
00845                                 pose.x += sourcepose.x;
00846                                 pose.y += sourcepose.y;
00847                                 CalculateFootprintForPose(pose, &EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV);
00848 
00849                                 //now also store the intermediate discretized cell if not there already
00850                                 EnvNAVXYTHETALAT3Dcell_t interm3Dcell;
00851                                 interm3Dcell.x = CONTXY2DISC(pose.x, EnvNAVXYTHETALATCfg.cellsize_m);
00852                                 interm3Dcell.y = CONTXY2DISC(pose.y, EnvNAVXYTHETALATCfg.cellsize_m);
00853                                 interm3Dcell.theta = ContTheta2Disc(pose.theta, NAVXYTHETALAT_THETADIRS); 
00854                                 if(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].interm3DcellsV.size() == 0 || 
00855                                         previnterm3Dcell.theta != interm3Dcell.theta || previnterm3Dcell.x != interm3Dcell.x || previnterm3Dcell.y != interm3Dcell.y)
00856                                 {
00857                                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].interm3DcellsV.push_back(interm3Dcell);
00858                                 }
00859                                 previnterm3Dcell = interm3Dcell;
00860 
00861                         }
00862 
00863                         //now remove the source footprint
00864                         RemoveSourceFootprint(sourcepose, &EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV);
00865 
00866 #if DEBUG
00867                         SBPL_FPRINTF(fDeb, "action tind=%d aind=%d: dX=%d dY=%d endtheta=%d (%.2f degs -> %.2f degs) cost=%d (mprim: %.2f %.2f %.2f)\n",
00868                                 tind, aind,                     
00869                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX, EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY,
00870                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta, sourcepose.theta*180/PI_CONST, 
00871                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV[EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV.size()-1].theta*180/PI_CONST,     
00872                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost,
00873                                 mp_endx_m, mp_endy_m, mp_endtheta_rad);
00874 #endif
00875 
00876                         //add to the list of backward actions
00877                         int targettheta = EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta;
00878                         if (targettheta < 0)
00879                                 targettheta = targettheta + NAVXYTHETALAT_THETADIRS;
00880                          EnvNAVXYTHETALATCfg.PredActionsV[targettheta].push_back(&(EnvNAVXYTHETALATCfg.ActionsV[tind][aind]));
00881 
00882                 }
00883         }
00884 
00885         //set number of actions
00886         EnvNAVXYTHETALATCfg.actionwidth = motionprimitiveV->size();
00887 
00888 
00889         //now compute replanning data
00890         ComputeReplanningData();
00891 
00892         SBPL_PRINTF("done pre-computing action data based on motion primitives\n");
00893 
00894 
00895 }
00896 
00897 
00898 //here motionprimitivevector contains actions for all angles
00899 void EnvironmentNAVXYTHETALATTICE::PrecomputeActionswithCompleteMotionPrimitive(vector<SBPL_xytheta_mprimitive>* motionprimitiveV)
00900 {
00901 
00902         SBPL_PRINTF("Pre-computing action data using motion primitives for every angle...\n");
00903         EnvNAVXYTHETALATCfg.ActionsV = new EnvNAVXYTHETALATAction_t* [NAVXYTHETALAT_THETADIRS];
00904         EnvNAVXYTHETALATCfg.PredActionsV = new vector<EnvNAVXYTHETALATAction_t*> [NAVXYTHETALAT_THETADIRS];
00905         vector<sbpl_2Dcell_t> footprint;
00906 
00907         if(motionprimitiveV->size()%NAVXYTHETALAT_THETADIRS != 0)
00908         {
00909                 SBPL_ERROR("ERROR: motionprimitives should be uniform across actions\n");
00910                 throw new SBPL_Exception();
00911         }
00912 
00913         EnvNAVXYTHETALATCfg.actionwidth = ((int)motionprimitiveV->size())/NAVXYTHETALAT_THETADIRS;
00914 
00915         //iterate over source angles
00916         int maxnumofactions = 0;
00917         for(int tind = 0; tind < NAVXYTHETALAT_THETADIRS; tind++)
00918         {
00919                 SBPL_PRINTF("pre-computing for angle %d out of %d angles\n", tind, NAVXYTHETALAT_THETADIRS);
00920 
00921                 EnvNAVXYTHETALATCfg.ActionsV[tind] = new EnvNAVXYTHETALATAction_t[EnvNAVXYTHETALATCfg.actionwidth];  
00922 
00923                 //compute sourcepose
00924                 EnvNAVXYTHETALAT3Dpt_t sourcepose;
00925                 sourcepose.x = DISCXY2CONT(0, EnvNAVXYTHETALATCfg.cellsize_m);
00926                 sourcepose.y = DISCXY2CONT(0, EnvNAVXYTHETALATCfg.cellsize_m);
00927                 sourcepose.theta = DiscTheta2Cont(tind, NAVXYTHETALAT_THETADIRS);
00928 
00929 
00930                 //iterate over motion primitives
00931                 int numofactions = 0;
00932                 int aind = -1;
00933                 for(int mind = 0; mind < (int)motionprimitiveV->size(); mind++)
00934                 {
00935                         //find a motion primitive for this angle
00936                         if(motionprimitiveV->at(mind).starttheta_c != tind)
00937                                 continue;
00938                         
00939                         aind++;
00940                         numofactions++;
00941                         
00942                         //action index
00943                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].aind = aind;
00944 
00945                         //start angle
00946                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].starttheta = tind;
00947 
00948                         //compute dislocation
00949                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta = motionprimitiveV->at(mind).endcell.theta;
00950                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX = motionprimitiveV->at(mind).endcell.x;
00951                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY = motionprimitiveV->at(mind).endcell.y;
00952 
00953                         //compute cost
00954                         if(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY != 0 || EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX != 0)
00955                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost = (int)(ceil(NAVXYTHETALAT_COSTMULT_MTOMM*EnvNAVXYTHETALATCfg.cellsize_m/EnvNAVXYTHETALATCfg.nominalvel_mpersecs*
00956                                                                 sqrt((double)(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX*EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX + 
00957                                                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY*EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY))));
00958                         else //cost of turn in place
00959                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost = (int)(NAVXYTHETALAT_COSTMULT_MTOMM*
00960                                                 EnvNAVXYTHETALATCfg.timetoturn45degsinplace_secs*
00961                                                 fabs(computeMinUnsignedAngleDiff(DiscTheta2Cont(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta, NAVXYTHETALAT_THETADIRS),
00962                                                                                                                 DiscTheta2Cont(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].starttheta, NAVXYTHETALAT_THETADIRS)))/(PI_CONST/4.0));
00963                         //use any additional cost multiplier
00964                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost *= motionprimitiveV->at(mind).additionalactioncostmult;
00965 
00966                         //compute and store interm points as well as intersecting cells
00967                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV.clear();
00968                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV.clear();
00969                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].interm3DcellsV.clear();
00970                         EnvNAVXYTHETALAT3Dcell_t previnterm3Dcell;
00971                         previnterm3Dcell.theta = 0; previnterm3Dcell.x = 0; previnterm3Dcell.y = 0;                     
00972                         for (int pind = 0; pind < (int)motionprimitiveV->at(mind).intermptV.size(); pind++)
00973                         {
00974                                 EnvNAVXYTHETALAT3Dpt_t intermpt = motionprimitiveV->at(mind).intermptV[pind];
00975                 
00976                                 //store it (they are with reference to 0,0,stattheta (not sourcepose.x,sourcepose.y,starttheta (that is, half-bin))
00977                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV.push_back(intermpt);
00978 
00979                                 //now compute the intersecting cells (for this pose has to be translated by sourcepose.x,sourcepose.y
00980                                 EnvNAVXYTHETALAT3Dpt_t pose;
00981                                 pose = intermpt;
00982                                 pose.x += sourcepose.x;
00983                                 pose.y += sourcepose.y;
00984                                 CalculateFootprintForPose(pose, &EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV);
00985                         
00986                                 //now also store the intermediate discretized cell if not there already
00987                                 EnvNAVXYTHETALAT3Dcell_t interm3Dcell;
00988                                 interm3Dcell.x = CONTXY2DISC(pose.x, EnvNAVXYTHETALATCfg.cellsize_m);
00989                                 interm3Dcell.y = CONTXY2DISC(pose.y, EnvNAVXYTHETALATCfg.cellsize_m);
00990                                 interm3Dcell.theta = ContTheta2Disc(pose.theta, NAVXYTHETALAT_THETADIRS); 
00991                                 if(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].interm3DcellsV.size() == 0 || 
00992                                         previnterm3Dcell.theta != interm3Dcell.theta || previnterm3Dcell.x != interm3Dcell.x || previnterm3Dcell.y != interm3Dcell.y)
00993                                 {
00994                                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].interm3DcellsV.push_back(interm3Dcell);
00995                                 }
00996                                 previnterm3Dcell = interm3Dcell;
00997                         }
00998 
00999                         //now remove the source footprint
01000                         RemoveSourceFootprint(sourcepose, &EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV);
01001 
01002 #if DEBUG
01003                         SBPL_FPRINTF(fDeb, "action tind=%d aind=%d: dX=%d dY=%d endtheta=%d (%.2f degs -> %.2f degs) cost=%d (mprimID %d: %d %d %d) numofintermcells = %d numofintercells=%d\n",
01004                                 tind, aind,                     
01005                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX, EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY,
01006                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta, 
01007                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV[0].theta*180/PI_CONST, 
01008                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV[EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV.size()-1].theta*180/PI_CONST,     
01009                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost,
01010                                 motionprimitiveV->at(mind).motprimID, 
01011                                 motionprimitiveV->at(mind).endcell.x, motionprimitiveV->at(mind).endcell.y, motionprimitiveV->at(mind).endcell.theta,
01012                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].interm3DcellsV.size(),
01013                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV.size()); 
01014 #endif
01015 
01016                         //add to the list of backward actions
01017                         int targettheta = EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta;
01018                         if (targettheta < 0)
01019                                 targettheta = targettheta + NAVXYTHETALAT_THETADIRS;
01020                          EnvNAVXYTHETALATCfg.PredActionsV[targettheta].push_back(&(EnvNAVXYTHETALATCfg.ActionsV[tind][aind]));
01021 
01022                 }
01023 
01024                 if(maxnumofactions < numofactions)
01025                         maxnumofactions = numofactions;
01026         }
01027 
01028 
01029 
01030         //at this point we don't allow nonuniform number of actions
01031         if(motionprimitiveV->size() != (size_t)(NAVXYTHETALAT_THETADIRS*maxnumofactions))
01032         {
01033                 SBPL_ERROR("ERROR: nonuniform number of actions is not supported (maxnumofactions=%d while motprims=%d thetas=%d\n",
01034                                 maxnumofactions, (unsigned int)motionprimitiveV->size(), NAVXYTHETALAT_THETADIRS);
01035                 throw new SBPL_Exception();
01036         }
01037 
01038         //now compute replanning data
01039         ComputeReplanningData();
01040 
01041         SBPL_PRINTF("done pre-computing action data based on motion primitives\n");
01042 
01043 
01044 }
01045 
01046 void EnvironmentNAVXYTHETALATTICE::PrecomputeActions()
01047 {
01048 
01049         //construct list of actions
01050         SBPL_PRINTF("Pre-computing action data using the motion primitives for a 3D kinematic planning...\n");
01051         EnvNAVXYTHETALATCfg.ActionsV = new EnvNAVXYTHETALATAction_t* [NAVXYTHETALAT_THETADIRS];
01052         EnvNAVXYTHETALATCfg.PredActionsV = new vector<EnvNAVXYTHETALATAction_t*> [NAVXYTHETALAT_THETADIRS];
01053         vector<sbpl_2Dcell_t> footprint;
01054         //iterate over source angles
01055         for(int tind = 0; tind < NAVXYTHETALAT_THETADIRS; tind++)
01056         {
01057                 SBPL_PRINTF("processing angle %d\n", tind);
01058                 EnvNAVXYTHETALATCfg.ActionsV[tind] = new EnvNAVXYTHETALATAction_t[EnvNAVXYTHETALATCfg.actionwidth];
01059 
01060                 //compute sourcepose
01061                 EnvNAVXYTHETALAT3Dpt_t sourcepose;
01062                 sourcepose.x = DISCXY2CONT(0, EnvNAVXYTHETALATCfg.cellsize_m);
01063                 sourcepose.y = DISCXY2CONT(0, EnvNAVXYTHETALATCfg.cellsize_m);
01064                 sourcepose.theta = DiscTheta2Cont(tind, NAVXYTHETALAT_THETADIRS);
01065 
01066                 //the construction assumes that the robot first turns and then goes along this new theta
01067                 int aind = 0;
01068                 for(; aind < 3; aind++)
01069                 {
01070                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].aind = aind;
01071                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].starttheta = tind;
01072                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta = (tind + aind - 1)%NAVXYTHETALAT_THETADIRS; //-1,0,1
01073                         double angle = DiscTheta2Cont(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta, NAVXYTHETALAT_THETADIRS);
01074                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX = (int)(cos(angle) + 0.5*(cos(angle)>0?1:-1));
01075                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY = (int)(sin(angle) + 0.5*(sin(angle)>0?1:-1));
01076                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost = (int)(ceil(NAVXYTHETALAT_COSTMULT_MTOMM*EnvNAVXYTHETALATCfg.cellsize_m/EnvNAVXYTHETALATCfg.nominalvel_mpersecs*sqrt((double)(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX*EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX + 
01077                                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY*EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY))));
01078 
01079                         //compute intersecting cells
01080                         EnvNAVXYTHETALAT3Dpt_t pose;
01081                         pose.x = DISCXY2CONT(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX, EnvNAVXYTHETALATCfg.cellsize_m);
01082                         pose.y = DISCXY2CONT(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY, EnvNAVXYTHETALATCfg.cellsize_m);
01083                         pose.theta = angle;
01084                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV.clear();
01085                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV.clear();
01086                         CalculateFootprintForPose(pose, &EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV);
01087                         RemoveSourceFootprint(sourcepose, &EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV);
01088 
01089 #if DEBUG
01090                         SBPL_PRINTF("action tind=%d aind=%d: endtheta=%d (%f) dX=%d dY=%d cost=%d\n",
01091                                 tind, aind, EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta, angle, 
01092                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX, EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY,
01093                                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost);
01094 #endif
01095 
01096                         //add to the list of backward actions
01097                         int targettheta = EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta;
01098                         if (targettheta < 0)
01099                                 targettheta = targettheta + NAVXYTHETALAT_THETADIRS;
01100                          EnvNAVXYTHETALATCfg.PredActionsV[targettheta].push_back(&(EnvNAVXYTHETALATCfg.ActionsV[tind][aind]));
01101 
01102                 }
01103 
01104                 //decrease and increase angle without movement
01105                 aind = 3;
01106                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].aind = aind;
01107                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].starttheta = tind;
01108                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta = tind-1;
01109                 if(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta < 0) EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta += NAVXYTHETALAT_THETADIRS;
01110                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX = 0;
01111                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY = 0;
01112                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost = (int)(NAVXYTHETALAT_COSTMULT_MTOMM*EnvNAVXYTHETALATCfg.timetoturn45degsinplace_secs);
01113 
01114                 //compute intersecting cells
01115                 EnvNAVXYTHETALAT3Dpt_t pose;
01116                 pose.x = DISCXY2CONT(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX, EnvNAVXYTHETALATCfg.cellsize_m);
01117                 pose.y = DISCXY2CONT(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY, EnvNAVXYTHETALATCfg.cellsize_m);
01118                 pose.theta = DiscTheta2Cont(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta, NAVXYTHETALAT_THETADIRS);
01119                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV.clear();
01120                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV.clear();
01121                 CalculateFootprintForPose(pose, &EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV);
01122                 RemoveSourceFootprint(sourcepose, &EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV);
01123 
01124 #if DEBUG
01125                 SBPL_PRINTF("action tind=%d aind=%d: endtheta=%d (%f) dX=%d dY=%d cost=%d\n",
01126                         tind, aind, EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta, DiscTheta2Cont(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta, NAVXYTHETALAT_THETADIRS),
01127                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX, EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY,
01128                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost);
01129 #endif
01130 
01131                 //add to the list of backward actions
01132                 int targettheta = EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta;
01133                 if (targettheta < 0)
01134                         targettheta = targettheta + NAVXYTHETALAT_THETADIRS;
01135                  EnvNAVXYTHETALATCfg.PredActionsV[targettheta].push_back(&(EnvNAVXYTHETALATCfg.ActionsV[tind][aind]));
01136 
01137 
01138                 aind = 4;
01139                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].aind = aind;
01140                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].starttheta = tind;
01141                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta = (tind + 1)%NAVXYTHETALAT_THETADIRS; 
01142                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX = 0;
01143                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY = 0;
01144                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost = (int)(NAVXYTHETALAT_COSTMULT_MTOMM*EnvNAVXYTHETALATCfg.timetoturn45degsinplace_secs);
01145 
01146                 //compute intersecting cells
01147                 pose.x = DISCXY2CONT(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX, EnvNAVXYTHETALATCfg.cellsize_m);
01148                 pose.y = DISCXY2CONT(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY, EnvNAVXYTHETALATCfg.cellsize_m);
01149                 pose.theta = DiscTheta2Cont(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta, NAVXYTHETALAT_THETADIRS);
01150                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV.clear();
01151                 EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV.clear();
01152                 CalculateFootprintForPose(pose, &EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV);
01153                 RemoveSourceFootprint(sourcepose, &EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intersectingcellsV);
01154 
01155 
01156 #if DEBUG
01157                 SBPL_PRINTF("action tind=%d aind=%d: endtheta=%d (%f) dX=%d dY=%d cost=%d\n",
01158                         tind, aind, EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta, DiscTheta2Cont(EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta, NAVXYTHETALAT_THETADIRS),
01159                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dX, EnvNAVXYTHETALATCfg.ActionsV[tind][aind].dY,
01160                         EnvNAVXYTHETALATCfg.ActionsV[tind][aind].cost);
01161 #endif
01162 
01163                 //add to the list of backward actions
01164                 targettheta = EnvNAVXYTHETALATCfg.ActionsV[tind][aind].endtheta;
01165                 if (targettheta < 0)
01166                         targettheta = targettheta + NAVXYTHETALAT_THETADIRS;
01167                  EnvNAVXYTHETALATCfg.PredActionsV[targettheta].push_back(&(EnvNAVXYTHETALATCfg.ActionsV[tind][aind]));
01168 
01169         }
01170 
01171         //now compute replanning data
01172         ComputeReplanningData();
01173 
01174         SBPL_PRINTF("done pre-computing action data\n");
01175 
01176 
01177 }
01178 
01179 
01180 
01181 void EnvironmentNAVXYTHETALATTICE::InitializeEnvConfig(vector<SBPL_xytheta_mprimitive>* motionprimitiveV)
01182 {
01183         //aditional to configuration file initialization of EnvNAVXYTHETALATCfg if necessary
01184 
01185         //dXY dirs
01186         EnvNAVXYTHETALATCfg.dXY[0][0] = -1;
01187         EnvNAVXYTHETALATCfg.dXY[0][1] = -1;
01188         EnvNAVXYTHETALATCfg.dXY[1][0] = -1;
01189         EnvNAVXYTHETALATCfg.dXY[1][1] = 0;
01190         EnvNAVXYTHETALATCfg.dXY[2][0] = -1;
01191         EnvNAVXYTHETALATCfg.dXY[2][1] = 1;
01192         EnvNAVXYTHETALATCfg.dXY[3][0] = 0;
01193         EnvNAVXYTHETALATCfg.dXY[3][1] = -1;
01194         EnvNAVXYTHETALATCfg.dXY[4][0] = 0;
01195         EnvNAVXYTHETALATCfg.dXY[4][1] = 1;
01196         EnvNAVXYTHETALATCfg.dXY[5][0] = 1;
01197         EnvNAVXYTHETALATCfg.dXY[5][1] = -1;
01198         EnvNAVXYTHETALATCfg.dXY[6][0] = 1;
01199         EnvNAVXYTHETALATCfg.dXY[6][1] = 0;
01200         EnvNAVXYTHETALATCfg.dXY[7][0] = 1;
01201         EnvNAVXYTHETALATCfg.dXY[7][1] = 1;
01202 
01203 
01204         EnvNAVXYTHETALAT3Dpt_t temppose;
01205         temppose.x = 0.0;
01206         temppose.y = 0.0;
01207         temppose.theta = 0.0;
01208         vector<sbpl_2Dcell_t> footprint;
01209         CalculateFootprintForPose(temppose, &footprint);
01210         SBPL_PRINTF("number of cells in footprint of the robot = %d\n", (unsigned int)footprint.size());
01211 
01212 #if DEBUG
01213         SBPL_FPRINTF(fDeb, "footprint cells (size=%d):\n", footprint.size());
01214         for(int i = 0; i < (int) footprint.size(); i++)
01215         {
01216                 SBPL_FPRINTF(fDeb, "%d %d (cont: %.3f %.3f)\n", footprint.at(i).x, footprint.at(i).y, 
01217                         DISCXY2CONT(footprint.at(i).x, EnvNAVXYTHETALATCfg.cellsize_m), 
01218                         DISCXY2CONT(footprint.at(i).y, EnvNAVXYTHETALATCfg.cellsize_m));
01219         }
01220 #endif
01221 
01222 
01223         if(motionprimitiveV == NULL)
01224                 PrecomputeActions();
01225         else
01226                 PrecomputeActionswithCompleteMotionPrimitive(motionprimitiveV);
01227 
01228 
01229 }
01230 
01231 
01232 
01233 bool EnvironmentNAVXYTHETALATTICE::IsValidCell(int X, int Y)
01234 {
01235         return (X >= 0 && X < EnvNAVXYTHETALATCfg.EnvWidth_c && 
01236                 Y >= 0 && Y < EnvNAVXYTHETALATCfg.EnvHeight_c && 
01237                 EnvNAVXYTHETALATCfg.Grid2D[X][Y] < EnvNAVXYTHETALATCfg.obsthresh);
01238 }
01239 
01240 bool EnvironmentNAVXYTHETALATTICE::IsWithinMapCell(int X, int Y)
01241 {
01242         return (X >= 0 && X < EnvNAVXYTHETALATCfg.EnvWidth_c && 
01243                 Y >= 0 && Y < EnvNAVXYTHETALATCfg.EnvHeight_c);
01244 }
01245 
01246 bool EnvironmentNAVXYTHETALATTICE::IsValidConfiguration(int X, int Y, int Theta)
01247 {
01248         vector<sbpl_2Dcell_t> footprint;
01249         EnvNAVXYTHETALAT3Dpt_t pose;
01250 
01251         //compute continuous pose
01252         pose.x = DISCXY2CONT(X, EnvNAVXYTHETALATCfg.cellsize_m);
01253         pose.y = DISCXY2CONT(Y, EnvNAVXYTHETALATCfg.cellsize_m);
01254         pose.theta = DiscTheta2Cont(Theta, NAVXYTHETALAT_THETADIRS);
01255 
01256         //compute footprint cells
01257         CalculateFootprintForPose(pose, &footprint);
01258 
01259         //iterate over all footprint cells
01260         for(int find = 0; find < (int)footprint.size(); find++)
01261         {
01262                 int x = footprint.at(find).x;
01263                 int y = footprint.at(find).y;
01264 
01265                 if (x < 0 || x >= EnvNAVXYTHETALATCfg.EnvWidth_c ||
01266                         y < 0 || y >= EnvNAVXYTHETALATCfg.EnvHeight_c ||                
01267                         EnvNAVXYTHETALATCfg.Grid2D[x][y] >= EnvNAVXYTHETALATCfg.obsthresh)
01268                 {
01269                         return false;
01270                 }
01271         }
01272 
01273         return true;
01274 }
01275 
01276 
01277 int EnvironmentNAVXYTHETALATTICE::GetActionCost(int SourceX, int SourceY, int SourceTheta, EnvNAVXYTHETALATAction_t* action)
01278 {
01279         sbpl_2Dcell_t cell;
01280         EnvNAVXYTHETALAT3Dcell_t interm3Dcell;
01281         int i;
01282 
01283         //TODO - go over bounding box (minpt and maxpt) to test validity and skip testing boundaries below, also order intersect cells so that the four farthest pts go first
01284         
01285         if(!IsValidCell(SourceX, SourceY))
01286                 return INFINITECOST;
01287         if(!IsValidCell(SourceX + action->dX, SourceY + action->dY))
01288                 return INFINITECOST;
01289 
01290         if(EnvNAVXYTHETALATCfg.Grid2D[SourceX + action->dX][SourceY + action->dY] >= EnvNAVXYTHETALATCfg.cost_inscribed_thresh)
01291                 return INFINITECOST;
01292 
01293         //need to iterate over discretized center cells and compute cost based on them
01294         unsigned char maxcellcost = 0;
01295         for(i = 0; i < (int)action->interm3DcellsV.size(); i++)
01296         {
01297                 interm3Dcell = action->interm3DcellsV.at(i);
01298                 interm3Dcell.x = interm3Dcell.x + SourceX;
01299                 interm3Dcell.y = interm3Dcell.y + SourceY;
01300                 
01301                 if(interm3Dcell.x < 0 || interm3Dcell.x >= EnvNAVXYTHETALATCfg.EnvWidth_c ||
01302                         interm3Dcell.y < 0 || interm3Dcell.y >= EnvNAVXYTHETALATCfg.EnvHeight_c)
01303                         return INFINITECOST;
01304 
01305                 maxcellcost = __max(maxcellcost, EnvNAVXYTHETALATCfg.Grid2D[interm3Dcell.x][interm3Dcell.y]);
01306 
01307                 //check that the robot is NOT in the cell at which there is no valid orientation
01308                 if(maxcellcost >= EnvNAVXYTHETALATCfg.cost_inscribed_thresh)
01309                         return INFINITECOST;
01310         }
01311 
01312 
01313         //check collisions that for the particular footprint orientation along the action
01314         if(EnvNAVXYTHETALATCfg.FootprintPolygon.size() > 1 && (int)maxcellcost >= EnvNAVXYTHETALATCfg.cost_possibly_circumscribed_thresh)
01315         {
01316                 checks++;
01317 
01318                 for(i = 0; i < (int)action->intersectingcellsV.size(); i++) 
01319                 {
01320                         //get the cell in the map
01321                         cell = action->intersectingcellsV.at(i);
01322                         cell.x = cell.x + SourceX;
01323                         cell.y = cell.y + SourceY;
01324                         
01325                         //check validity
01326                         if(!IsValidCell(cell.x, cell.y))
01327                                 return INFINITECOST;
01328 
01329                         //if(EnvNAVXYTHETALATCfg.Grid2D[cell.x][cell.y] > currentmaxcost) //cost computation changed: cost = max(cost of centers of the robot along action)
01330                         //      currentmaxcost = EnvNAVXYTHETALATCfg.Grid2D[cell.x][cell.y];    //intersecting cells are only used for collision checking
01331                 }
01332         }
01333 
01334         //to ensure consistency of h2D:
01335         maxcellcost = __max(maxcellcost, EnvNAVXYTHETALATCfg.Grid2D[SourceX][SourceY]);
01336         int currentmaxcost = (int)__max(maxcellcost, EnvNAVXYTHETALATCfg.Grid2D[SourceX + action->dX][SourceY + action->dY]);
01337 
01338 
01339         return action->cost*(currentmaxcost+1); //use cell cost as multiplicative factor
01340  
01341 }
01342 
01343 
01344 
01345 double EnvironmentNAVXYTHETALATTICE::EuclideanDistance_m(int X1, int Y1, int X2, int Y2)
01346 {
01347     int sqdist = ((X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2));
01348     return EnvNAVXYTHETALATCfg.cellsize_m*sqrt((double)sqdist);
01349 
01350 }
01351 
01352 //calculates a set of cells that correspond to the specified footprint
01353 //adds points to it (does not clear it beforehand) 
01354 void EnvironmentNAVXYTHETALATTICE::CalculateFootprintForPose(EnvNAVXYTHETALAT3Dpt_t pose, vector<sbpl_2Dcell_t>* footprint, const vector<sbpl_2Dpt_t>& FootprintPolygon)
01355 {
01356 
01357 int pind;
01358 
01359 #if DEBUG
01360 //  SBPL_PRINTF("---Calculating Footprint for Pose: %f %f %f---\n",
01361 //       pose.x, pose.y, pose.theta);
01362 #endif
01363 
01364   //handle special case where footprint is just a point
01365   if(FootprintPolygon.size() <= 1){
01366     sbpl_2Dcell_t cell;
01367     cell.x = CONTXY2DISC(pose.x, EnvNAVXYTHETALATCfg.cellsize_m);
01368     cell.y = CONTXY2DISC(pose.y, EnvNAVXYTHETALATCfg.cellsize_m);
01369 
01370         for(pind = 0; pind < (int)footprint->size(); pind++)
01371         {
01372                 if(cell.x == footprint->at(pind).x && cell.y == footprint->at(pind).y)
01373                         break;
01374         }
01375         if(pind == (int)footprint->size()) footprint->push_back(cell);
01376     return;
01377   }
01378 
01379   vector<sbpl_2Dpt_t> bounding_polygon;
01380   unsigned int find;
01381   double max_x = -INFINITECOST, min_x = INFINITECOST, max_y = -INFINITECOST, min_y = INFINITECOST;
01382   sbpl_2Dpt_t pt = {0,0};
01383   for(find = 0; find < FootprintPolygon.size(); find++){
01384     
01385     //rotate and translate the corner of the robot
01386     pt = FootprintPolygon[find];
01387     
01388     //rotate and translate the point
01389     sbpl_2Dpt_t corner;
01390     corner.x = cos(pose.theta)*pt.x - sin(pose.theta)*pt.y + pose.x;
01391     corner.y = sin(pose.theta)*pt.x + cos(pose.theta)*pt.y + pose.y;
01392     bounding_polygon.push_back(corner);
01393 #if DEBUG
01394 //    SBPL_PRINTF("Pt: %f %f, Corner: %f %f\n", pt.x, pt.y, corner.x, corner.y);
01395 #endif
01396     if(corner.x < min_x || find==0){
01397       min_x = corner.x;
01398     }
01399     if(corner.x > max_x || find==0){
01400       max_x = corner.x;
01401     }
01402     if(corner.y < min_y || find==0){
01403       min_y = corner.y;
01404     }
01405     if(corner.y > max_y || find==0){
01406       max_y = corner.y;
01407     }
01408     
01409   }
01410 
01411 #if DEBUG
01412 //  SBPL_PRINTF("Footprint bounding box: %f %f %f %f\n", min_x, max_x, min_y, max_y);
01413 #endif
01414   //initialize previous values to something that will fail the if condition during the first iteration in the for loop
01415   int prev_discrete_x = CONTXY2DISC(pt.x, EnvNAVXYTHETALATCfg.cellsize_m) + 1; 
01416   int prev_discrete_y = CONTXY2DISC(pt.y, EnvNAVXYTHETALATCfg.cellsize_m) + 1;
01417   int prev_inside = 0;
01418   int discrete_x;
01419   int discrete_y;
01420 
01421   for(double x=min_x; x<=max_x; x+=EnvNAVXYTHETALATCfg.cellsize_m/3){
01422     for(double y=min_y; y<=max_y; y+=EnvNAVXYTHETALATCfg.cellsize_m/3){
01423       pt.x = x;
01424       pt.y = y;
01425       discrete_x = CONTXY2DISC(pt.x, EnvNAVXYTHETALATCfg.cellsize_m);
01426       discrete_y = CONTXY2DISC(pt.y, EnvNAVXYTHETALATCfg.cellsize_m);
01427       
01428       //see if we just tested this point
01429       if(discrete_x != prev_discrete_x || discrete_y != prev_discrete_y || prev_inside==0){
01430 
01431 #if DEBUG
01432 //              SBPL_PRINTF("Testing point: %f %f Discrete: %d %d\n", pt.x, pt.y, discrete_x, discrete_y);
01433 #endif
01434         
01435                 if(IsInsideFootprint(pt, &bounding_polygon)){ 
01436                 //convert to a grid point
01437 
01438 #if DEBUG
01439 //                      SBPL_PRINTF("Pt Inside %f %f\n", pt.x, pt.y);
01440 #endif
01441 
01442                         sbpl_2Dcell_t cell;
01443                         cell.x = discrete_x;
01444                         cell.y = discrete_y;
01445 
01446                         //insert point if not there already
01447                         int pind = 0;
01448                         for(pind = 0; pind < (int)footprint->size(); pind++)
01449                         {
01450                                 if(cell.x == footprint->at(pind).x && cell.y == footprint->at(pind).y)
01451                                         break;
01452                         }
01453                         if(pind == (int)footprint->size()) footprint->push_back(cell);
01454 
01455                         prev_inside = 1;
01456 
01457 #if DEBUG
01458 //                      SBPL_PRINTF("Added pt to footprint: %f %f\n", pt.x, pt.y);
01459 #endif
01460                 }
01461                 else{
01462                         prev_inside = 0;
01463                 }
01464 
01465       }
01466           else
01467           {
01468 #if DEBUG
01469                 //SBPL_PRINTF("Skipping pt: %f %f\n", pt.x, pt.y);
01470 #endif
01471       }
01472       
01473       prev_discrete_x = discrete_x;
01474       prev_discrete_y = discrete_y;
01475 
01476     }//over x_min...x_max
01477   }
01478 
01479 
01480 
01481 }
01482 
01483 //calculates a set of cells that correspond to the footprint of the base
01484 //adds points to it (does not clear it beforehand) 
01485 void EnvironmentNAVXYTHETALATTICE::CalculateFootprintForPose(EnvNAVXYTHETALAT3Dpt_t pose, vector<sbpl_2Dcell_t>* footprint)
01486 {  
01487         CalculateFootprintForPose(pose, footprint, EnvNAVXYTHETALATCfg.FootprintPolygon);
01488 }
01489 
01490 //removes a set of cells that correspond to the specified footprint at the sourcepose
01491 //adds points to it (does not clear it beforehand) 
01492 void EnvironmentNAVXYTHETALATTICE::RemoveSourceFootprint(EnvNAVXYTHETALAT3Dpt_t sourcepose, vector<sbpl_2Dcell_t>* footprint, const vector<sbpl_2Dpt_t>& FootprintPolygon)
01493 {  
01494         vector<sbpl_2Dcell_t> sourcefootprint;
01495 
01496         //compute source footprint
01497         CalculateFootprintForPose(sourcepose, &sourcefootprint, FootprintPolygon);
01498 
01499         //now remove the source cells from the footprint
01500         for(int sind = 0; sind < (int)sourcefootprint.size(); sind++)
01501         {
01502                 for(int find = 0; find < (int)footprint->size(); find++)
01503                 {
01504                         if(sourcefootprint.at(sind).x == footprint->at(find).x && sourcefootprint.at(sind).y == footprint->at(find).y)
01505                         {
01506                                 footprint->erase(footprint->begin() + find);
01507                                 break;
01508                         }
01509                 }//over footprint
01510         }//over source
01511 
01512 
01513 
01514 }
01515 
01516 //removes a set of cells that correspond to the footprint of the base at the sourcepose
01517 //adds points to it (does not clear it beforehand) 
01518 void EnvironmentNAVXYTHETALATTICE::RemoveSourceFootprint(EnvNAVXYTHETALAT3Dpt_t sourcepose, vector<sbpl_2Dcell_t>* footprint)
01519 {  
01520         RemoveSourceFootprint(sourcepose, footprint, EnvNAVXYTHETALATCfg.FootprintPolygon);
01521 }
01522 
01523 
01524 //------------------------------------------------------------------------------
01525 
01526 //------------------------------Heuristic computation--------------------------
01527 
01528 
01529 void EnvironmentNAVXYTHETALATTICE::EnsureHeuristicsUpdated(bool bGoalHeuristics)
01530 {
01531 
01532         if(bNeedtoRecomputeStartHeuristics && !bGoalHeuristics)
01533         {
01534                 grid2Dsearchfromstart->search(EnvNAVXYTHETALATCfg.Grid2D, EnvNAVXYTHETALATCfg.cost_inscribed_thresh, 
01535                         EnvNAVXYTHETALATCfg.StartX_c, EnvNAVXYTHETALATCfg.StartY_c, EnvNAVXYTHETALATCfg.EndX_c, EnvNAVXYTHETALATCfg.EndY_c, 
01536                         SBPL_2DGRIDSEARCH_TERM_CONDITION_TWOTIMESOPTPATH); 
01537                 bNeedtoRecomputeStartHeuristics = false;
01538                 SBPL_PRINTF("2dsolcost_infullunits=%d\n", (int)(grid2Dsearchfromstart->getlowerboundoncostfromstart_inmm(EnvNAVXYTHETALATCfg.EndX_c, EnvNAVXYTHETALATCfg.EndY_c)
01539                         /EnvNAVXYTHETALATCfg.nominalvel_mpersecs));
01540 
01541         }
01542 
01543 
01544         if(bNeedtoRecomputeGoalHeuristics && bGoalHeuristics)
01545         {
01546                 grid2Dsearchfromgoal->search(EnvNAVXYTHETALATCfg.Grid2D, EnvNAVXYTHETALATCfg.cost_inscribed_thresh, 
01547                         EnvNAVXYTHETALATCfg.EndX_c, EnvNAVXYTHETALATCfg.EndY_c, EnvNAVXYTHETALATCfg.StartX_c, EnvNAVXYTHETALATCfg.StartY_c,  
01548                         SBPL_2DGRIDSEARCH_TERM_CONDITION_TWOTIMESOPTPATH); 
01549                 bNeedtoRecomputeGoalHeuristics = false;
01550                 SBPL_PRINTF("2dsolcost_infullunits=%d\n", (int)(grid2Dsearchfromgoal->getlowerboundoncostfromstart_inmm(EnvNAVXYTHETALATCfg.StartX_c, EnvNAVXYTHETALATCfg.StartY_c)
01551                         /EnvNAVXYTHETALATCfg.nominalvel_mpersecs));
01552 
01553         }
01554 
01555 
01556 }
01557 
01558 
01559 
01560 void EnvironmentNAVXYTHETALATTICE::ComputeHeuristicValues()
01561 {
01562         //whatever necessary pre-computation of heuristic values is done here 
01563         SBPL_PRINTF("Precomputing heuristics...\n");
01564         
01565         //allocated 2D grid searches
01566         grid2Dsearchfromstart = new SBPL2DGridSearch(EnvNAVXYTHETALATCfg.EnvWidth_c, EnvNAVXYTHETALATCfg.EnvHeight_c, (float)EnvNAVXYTHETALATCfg.cellsize_m);
01567         grid2Dsearchfromgoal = new SBPL2DGridSearch(EnvNAVXYTHETALATCfg.EnvWidth_c, EnvNAVXYTHETALATCfg.EnvHeight_c, (float)EnvNAVXYTHETALATCfg.cellsize_m); 
01568 
01569         //set OPEN type to sliding buckets
01570         grid2Dsearchfromstart->setOPENdatastructure(SBPL_2DGRIDSEARCH_OPENTYPE_SLIDINGBUCKETS); 
01571         grid2Dsearchfromgoal->setOPENdatastructure(SBPL_2DGRIDSEARCH_OPENTYPE_SLIDINGBUCKETS);
01572 
01573         SBPL_PRINTF("done\n");
01574 
01575 }
01576 
01577 //------------debugging functions---------------------------------------------
01578 bool EnvironmentNAVXYTHETALATTICE::CheckQuant(FILE* fOut) 
01579 {
01580 
01581   for(double theta  = -10; theta < 10; theta += 2.0*PI_CONST/NAVXYTHETALAT_THETADIRS*0.01)
01582     {
01583                 int nTheta = ContTheta2Disc(theta, NAVXYTHETALAT_THETADIRS);
01584                 double newTheta = DiscTheta2Cont(nTheta, NAVXYTHETALAT_THETADIRS);
01585                 int nnewTheta = ContTheta2Disc(newTheta, NAVXYTHETALAT_THETADIRS);
01586 
01587                 SBPL_FPRINTF(fOut, "theta=%f(%f)->%d->%f->%d\n", theta, theta*180/PI_CONST, nTheta, newTheta, nnewTheta);
01588 
01589         if(nTheta != nnewTheta)
01590         {
01591             SBPL_ERROR("ERROR: invalid quantization\n");                     
01592             return false;
01593         }
01594     }
01595 
01596   return true;
01597 }
01598 
01599 
01600 
01601 //-----------------------------------------------------------------------------
01602 
01603 //-----------interface with outside functions-----------------------------------
01604 bool EnvironmentNAVXYTHETALATTICE::InitializeEnv(const char* sEnvFile, const vector<sbpl_2Dpt_t>& perimeterptsV, const char* sMotPrimFile)
01605 {
01606         EnvNAVXYTHETALATCfg.FootprintPolygon = perimeterptsV;
01607 
01608         FILE* fCfg = fopen(sEnvFile, "r");
01609         if(fCfg == NULL)
01610         {
01611                 SBPL_ERROR("ERROR: unable to open %s\n", sEnvFile);
01612                 throw new SBPL_Exception();
01613         }
01614         ReadConfiguration(fCfg);
01615   fclose(fCfg);
01616 
01617         if(sMotPrimFile != NULL)
01618         {
01619                 FILE* fMotPrim = fopen(sMotPrimFile, "r");
01620                 if(fMotPrim == NULL)
01621                 {
01622                         SBPL_ERROR("ERROR: unable to open %s\n", sMotPrimFile);
01623                         throw new SBPL_Exception();
01624                 }
01625                 if(ReadMotionPrimitives(fMotPrim) == false)
01626                 {
01627                         SBPL_ERROR("ERROR: failed to read in motion primitive file\n");
01628                         throw new SBPL_Exception();
01629                 }
01630                 InitGeneral(&EnvNAVXYTHETALATCfg.mprimV);
01631     fclose(fMotPrim);
01632         }
01633         else
01634                 InitGeneral(NULL);
01635 
01636         SBPL_PRINTF("size of env: %d by %d\n", EnvNAVXYTHETALATCfg.EnvWidth_c, EnvNAVXYTHETALATCfg.EnvHeight_c);
01637 
01638         return true;
01639 }
01640 
01641 
01642 bool EnvironmentNAVXYTHETALATTICE::InitializeEnv(const char* sEnvFile)
01643 {
01644 
01645         FILE* fCfg = fopen(sEnvFile, "r");
01646         if(fCfg == NULL)
01647         {
01648                 SBPL_ERROR("ERROR: unable to open %s\n", sEnvFile);
01649                 throw new SBPL_Exception();
01650         }
01651         ReadConfiguration(fCfg);
01652   fclose(fCfg);
01653 
01654         InitGeneral(NULL);
01655 
01656 
01657         return true;
01658 }
01659 
01660 
01661 
01662 bool EnvironmentNAVXYTHETALATTICE::InitializeEnv(int width, int height,
01663                                         const unsigned char* mapdata,
01664                                         double startx, double starty, double starttheta,
01665                                         double goalx, double goaly, double goaltheta,
01666                                     double goaltol_x, double goaltol_y, double goaltol_theta,
01667                                         const vector<sbpl_2Dpt_t> & perimeterptsV,
01668                                         double cellsize_m, double nominalvel_mpersecs, double timetoturn45degsinplace_secs,
01669                                         unsigned char obsthresh,  const char* sMotPrimFile)
01670 {
01671 
01672         SBPL_PRINTF("env: initialize with width=%d height=%d start=%.3f %.3f %.3f goalx=%.3f %.3f %.3f cellsize=%.3f nomvel=%.3f timetoturn=%.3f, obsthresh=%d\n",
01673                 width, height, startx, starty, starttheta, goalx, goaly, goaltheta, cellsize_m, nominalvel_mpersecs, timetoturn45degsinplace_secs, obsthresh);
01674 
01675         SBPL_PRINTF("perimeter has size=%d\n", (unsigned int)perimeterptsV.size());
01676 
01677         for(int i = 0; i < (int)perimeterptsV.size(); i++)
01678         {
01679                 SBPL_PRINTF("perimeter(%d) = %.4f %.4f\n", i, perimeterptsV.at(i).x, perimeterptsV.at(i).y);
01680         }
01681 
01682 
01683         EnvNAVXYTHETALATCfg.obsthresh = obsthresh;
01684 
01685         //TODO - need to set the tolerance as well
01686 
01687         SetConfiguration(width, height,
01688                                         mapdata,
01689                                         CONTXY2DISC(startx, cellsize_m), CONTXY2DISC(starty, cellsize_m), ContTheta2Disc(starttheta, NAVXYTHETALAT_THETADIRS),
01690                                         CONTXY2DISC(goalx, cellsize_m), CONTXY2DISC(goaly, cellsize_m), ContTheta2Disc(goaltheta, NAVXYTHETALAT_THETADIRS),
01691                                         cellsize_m, nominalvel_mpersecs, timetoturn45degsinplace_secs, perimeterptsV);
01692 
01693         if(sMotPrimFile != NULL)
01694         {
01695                 FILE* fMotPrim = fopen(sMotPrimFile, "r");
01696                 if(fMotPrim == NULL)
01697                 {
01698                         SBPL_ERROR("ERROR: unable to open %s\n", sMotPrimFile);
01699                         throw new SBPL_Exception();
01700                 }
01701 
01702                 if(ReadMotionPrimitives(fMotPrim) == false)
01703                 {
01704                         SBPL_ERROR("ERROR: failed to read in motion primitive file\n");
01705                         throw new SBPL_Exception();
01706                 }
01707     fclose(fMotPrim);
01708         }
01709 
01710         if(EnvNAVXYTHETALATCfg.mprimV.size() != 0)
01711         {
01712                 InitGeneral(&EnvNAVXYTHETALATCfg.mprimV);
01713         }
01714         else
01715                 InitGeneral(NULL);
01716 
01717         return true;
01718 }
01719 
01720 
01721 bool EnvironmentNAVXYTHETALATTICE::InitGeneral(vector<SBPL_xytheta_mprimitive>* motionprimitiveV) {
01722 
01723 
01724   //Initialize other parameters of the environment
01725   InitializeEnvConfig(motionprimitiveV);
01726   
01727   //initialize Environment
01728   InitializeEnvironment();
01729   
01730   //pre-compute heuristics
01731   ComputeHeuristicValues();
01732 
01733   return true;
01734 }
01735 
01736 bool EnvironmentNAVXYTHETALATTICE::InitializeMDPCfg(MDPConfig *MDPCfg)
01737 {
01738         //initialize MDPCfg with the start and goal ids 
01739         MDPCfg->goalstateid = EnvNAVXYTHETALAT.goalstateid;
01740         MDPCfg->startstateid = EnvNAVXYTHETALAT.startstateid;
01741 
01742         return true;
01743 }
01744 
01745 
01746 void EnvironmentNAVXYTHETALATTICE::PrintHeuristicValues()
01747 {
01748 #ifndef ROS
01749   const char* heur = "heur.txt";
01750 #endif
01751         FILE* fHeur = SBPL_FOPEN(heur, "w");
01752   if(fHeur == NULL){
01753     SBPL_ERROR("ERROR: could not open debug file to write heuristic\n");
01754     throw new SBPL_Exception();
01755   }
01756         SBPL2DGridSearch* grid2Dsearch = NULL;
01757         
01758         for(int i = 0; i < 2; i++)
01759         {
01760                 if(i == 0 && grid2Dsearchfromstart != NULL)
01761                 {
01762                         grid2Dsearch = grid2Dsearchfromstart;
01763                         SBPL_FPRINTF(fHeur, "start heuristics:\n");
01764                 }
01765                 else if(i == 1 && grid2Dsearchfromgoal != NULL)
01766                 {
01767                         grid2Dsearch = grid2Dsearchfromgoal;
01768                         SBPL_FPRINTF(fHeur, "goal heuristics:\n");
01769                 }
01770                 else
01771                         continue;
01772 
01773                 for (int y = 0; y < EnvNAVXYTHETALATCfg.EnvHeight_c; y++) {
01774                         for (int x = 0; x < EnvNAVXYTHETALATCfg.EnvWidth_c; x++) {
01775                                 if(grid2Dsearch->getlowerboundoncostfromstart_inmm(x, y) < INFINITECOST)
01776                                         SBPL_FPRINTF(fHeur, "%5d ", grid2Dsearch->getlowerboundoncostfromstart_inmm(x, y));
01777                         else
01778                                 SBPL_FPRINTF(fHeur, "XXXXX ");
01779                         }
01780                         SBPL_FPRINTF(fHeur, "\n");
01781                 }
01782         }
01783         SBPL_FCLOSE(fHeur);
01784 }
01785 
01786 
01787 
01788 
01789 void EnvironmentNAVXYTHETALATTICE::SetAllPreds(CMDPSTATE* state)
01790 {
01791         //implement this if the planner needs access to predecessors
01792         
01793         SBPL_ERROR("ERROR in EnvNAVXYTHETALAT... function: SetAllPreds is undefined\n");
01794         throw new SBPL_Exception();
01795 }
01796 
01797 
01798 void EnvironmentNAVXYTHETALATTICE::GetSuccs(int SourceStateID, vector<int>* SuccIDV, vector<int>* CostV)
01799 {
01800         GetSuccs(SourceStateID, SuccIDV, CostV, NULL);
01801 }
01802 
01803 
01804 
01805 
01806 
01807 const EnvNAVXYTHETALATConfig_t* EnvironmentNAVXYTHETALATTICE::GetEnvNavConfig() {
01808   return &EnvNAVXYTHETALATCfg;
01809 }
01810 
01811 
01812 
01813 bool EnvironmentNAVXYTHETALATTICE::UpdateCost(int x, int y, unsigned char newcost)
01814 {
01815 
01816 #if DEBUG
01817   //SBPL_FPRINTF(fDeb, "Cost updated for cell %d %d from old cost=%d to new cost=%d\n", x,y,EnvNAVXYTHETALATCfg.Grid2D[x][y], newcost);
01818 #endif
01819 
01820     EnvNAVXYTHETALATCfg.Grid2D[x][y] = newcost;
01821 
01822         bNeedtoRecomputeStartHeuristics = true;
01823         bNeedtoRecomputeGoalHeuristics = true;
01824 
01825     return true;
01826 }
01827 
01828 
01829 bool EnvironmentNAVXYTHETALATTICE::SetMap(const unsigned char* mapdata)
01830 {
01831         int xind=-1, yind=-1;
01832 
01833         for (xind = 0; xind < EnvNAVXYTHETALATCfg.EnvWidth_c; xind++) {
01834                 for(yind = 0; yind < EnvNAVXYTHETALATCfg.EnvHeight_c; yind++) {
01835                         EnvNAVXYTHETALATCfg.Grid2D[xind][yind] = mapdata[xind+yind*EnvNAVXYTHETALATCfg.EnvWidth_c];
01836                 }
01837         }
01838 
01839         bNeedtoRecomputeStartHeuristics = true;
01840         bNeedtoRecomputeGoalHeuristics = true;
01841 
01842         return true;
01843 
01844 }
01845 
01846 
01847 
01848 void EnvironmentNAVXYTHETALATTICE::PrintEnv_Config(FILE* fOut)
01849 {
01850 
01851         //implement this if the planner needs to print out EnvNAVXYTHETALAT. configuration
01852         
01853         SBPL_ERROR("ERROR in EnvNAVXYTHETALAT... function: PrintEnv_Config is undefined\n");
01854         throw new SBPL_Exception();
01855 
01856 }
01857 
01858 void EnvironmentNAVXYTHETALATTICE::PrintTimeStat(FILE* fOut)
01859 {
01860 
01861 #if TIME_DEBUG
01862     SBPL_FPRINTF(fOut, "time3_addallout = %f secs, time_gethash = %f secs, time_createhash = %f secs, time_getsuccs = %f\n",
01863             time3_addallout/(double)CLOCKS_PER_SEC, time_gethash/(double)CLOCKS_PER_SEC, 
01864             time_createhash/(double)CLOCKS_PER_SEC, time_getsuccs/(double)CLOCKS_PER_SEC);
01865 #endif
01866 }
01867 
01868 
01869 
01870 bool EnvironmentNAVXYTHETALATTICE::IsObstacle(int x, int y)
01871 {
01872 
01873 #if DEBUG
01874         SBPL_FPRINTF(fDeb, "Status of cell %d %d is queried. Its cost=%d\n", x,y,EnvNAVXYTHETALATCfg.Grid2D[x][y]);
01875 #endif
01876 
01877 
01878         return (EnvNAVXYTHETALATCfg.Grid2D[x][y] >= EnvNAVXYTHETALATCfg.obsthresh); 
01879 
01880 }
01881 
01882 void EnvironmentNAVXYTHETALATTICE::GetEnvParms(int *size_x, int *size_y, double* startx, double* starty, double*starttheta, double* goalx, double* goaly, double* goaltheta,
01883                                                                                 double* cellsize_m, double* nominalvel_mpersecs, double* timetoturn45degsinplace_secs, unsigned char* obsthresh,
01884                                                                                 vector<SBPL_xytheta_mprimitive>* mprimitiveV)
01885 {
01886         *size_x = EnvNAVXYTHETALATCfg.EnvWidth_c;
01887         *size_y = EnvNAVXYTHETALATCfg.EnvHeight_c;
01888 
01889         *startx = DISCXY2CONT(EnvNAVXYTHETALATCfg.StartX_c, EnvNAVXYTHETALATCfg.cellsize_m);
01890         *starty = DISCXY2CONT(EnvNAVXYTHETALATCfg.StartY_c, EnvNAVXYTHETALATCfg.cellsize_m);
01891         *starttheta = DiscTheta2Cont(EnvNAVXYTHETALATCfg.StartTheta, NAVXYTHETALAT_THETADIRS);
01892         *goalx = DISCXY2CONT(EnvNAVXYTHETALATCfg.EndX_c, EnvNAVXYTHETALATCfg.cellsize_m);
01893         *goaly = DISCXY2CONT(EnvNAVXYTHETALATCfg.EndY_c, EnvNAVXYTHETALATCfg.cellsize_m);
01894         *goaltheta = DiscTheta2Cont(EnvNAVXYTHETALATCfg.EndTheta, NAVXYTHETALAT_THETADIRS);;
01895 
01896         *cellsize_m = EnvNAVXYTHETALATCfg.cellsize_m;
01897         *nominalvel_mpersecs = EnvNAVXYTHETALATCfg.nominalvel_mpersecs;
01898         *timetoturn45degsinplace_secs = EnvNAVXYTHETALATCfg.timetoturn45degsinplace_secs;
01899 
01900         *obsthresh = EnvNAVXYTHETALATCfg.obsthresh;
01901 
01902         *mprimitiveV = EnvNAVXYTHETALATCfg.mprimV;
01903 }
01904 
01905 
01906 bool EnvironmentNAVXYTHETALATTICE::PoseContToDisc(double px, double py, double pth,
01907                                          int &ix, int &iy, int &ith) const
01908 {
01909   ix = CONTXY2DISC(px, EnvNAVXYTHETALATCfg.cellsize_m);
01910   iy = CONTXY2DISC(py, EnvNAVXYTHETALATCfg.cellsize_m);
01911   ith = ContTheta2Disc(pth, NAVXYTHETALAT_THETADIRS); // ContTheta2Disc() normalizes the angle
01912   return (pth >= -2*PI_CONST) && (pth <= 2*PI_CONST)
01913     && (ix >= 0) && (ix < EnvNAVXYTHETALATCfg.EnvWidth_c)
01914     && (iy >= 0) && (iy < EnvNAVXYTHETALATCfg.EnvHeight_c);
01915 }
01916 
01917 
01918 bool EnvironmentNAVXYTHETALATTICE::PoseDiscToCont(int ix, int iy, int ith,
01919                                          double &px, double &py, double &pth) const
01920 {
01921   px = DISCXY2CONT(ix, EnvNAVXYTHETALATCfg.cellsize_m);
01922   py = DISCXY2CONT(iy, EnvNAVXYTHETALATCfg.cellsize_m);
01923   pth = normalizeAngle(DiscTheta2Cont(ith, NAVXYTHETALAT_THETADIRS));
01924   return (ith >= 0) && (ith < NAVXYTHETALAT_THETADIRS)
01925     && (ix >= 0) && (ix < EnvNAVXYTHETALATCfg.EnvWidth_c)
01926     && (iy >= 0) && (iy < EnvNAVXYTHETALATCfg.EnvHeight_c);
01927 }
01928 
01929 unsigned char EnvironmentNAVXYTHETALATTICE::GetMapCost(int x, int y)
01930 {
01931         return EnvNAVXYTHETALATCfg.Grid2D[x][y];
01932 }
01933 
01934 
01935 
01936 bool EnvironmentNAVXYTHETALATTICE::SetEnvParameter(const char* parameter, int value)
01937 {
01938 
01939         if(EnvNAVXYTHETALAT.bInitialized == true)
01940         {
01941                 SBPL_ERROR("ERROR: all parameters must be set before initialization of the environment\n");
01942                 return false;
01943         }
01944 
01945         SBPL_PRINTF("setting parameter %s to %d\n", parameter, value);
01946 
01947         if(strcmp(parameter, "cost_inscribed_thresh") == 0)
01948         {
01949                 if(value < 0 || value > 255)
01950                 {
01951                   SBPL_ERROR("ERROR: invalid value %d for parameter %s\n", value, parameter);
01952                         return false;
01953                 }
01954                 EnvNAVXYTHETALATCfg.cost_inscribed_thresh = (unsigned char)value;
01955         }
01956         else if(strcmp(parameter, "cost_possibly_circumscribed_thresh") == 0)
01957         {
01958                 if(value < 0 || value > 255)
01959                 {
01960                   SBPL_ERROR("ERROR: invalid value %d for parameter %s\n", value, parameter);
01961                         return false;
01962                 }
01963                 EnvNAVXYTHETALATCfg.cost_possibly_circumscribed_thresh = value;
01964         }
01965         else if(strcmp(parameter, "cost_obsthresh") == 0)
01966         {
01967                 if(value < 0 || value > 255)
01968                 {
01969                   SBPL_ERROR("ERROR: invalid value %d for parameter %s\n", value, parameter);
01970                         return false;
01971                 }
01972                 EnvNAVXYTHETALATCfg.obsthresh = (unsigned char)value;
01973         }
01974         else
01975         {
01976                 SBPL_ERROR("ERROR: invalid parameter %s\n", parameter);
01977                 return false;
01978         }
01979 
01980         return true;
01981 }
01982 
01983 int EnvironmentNAVXYTHETALATTICE::GetEnvParameter(const char* parameter)
01984 {
01985 
01986         if(strcmp(parameter, "cost_inscribed_thresh") == 0)
01987         {
01988                 return (int) EnvNAVXYTHETALATCfg.cost_inscribed_thresh;
01989         }
01990         else if(strcmp(parameter, "cost_possibly_circumscribed_thresh") == 0)
01991         {
01992                 return (int) EnvNAVXYTHETALATCfg.cost_possibly_circumscribed_thresh;
01993         }
01994         else if(strcmp(parameter, "cost_obsthresh") == 0)
01995         {
01996                 return (int) EnvNAVXYTHETALATCfg.obsthresh;
01997         }
01998         else
01999         {
02000                 SBPL_ERROR("ERROR: invalid parameter %s\n", parameter);
02001                 throw new SBPL_Exception();
02002         }
02003 
02004 }
02005 
02006 //------------------------------------------------------------------------------
02007 
02008 
02009 
02010 //-----------------XYTHETA Enivornment (child) class---------------------------
02011 
02012 EnvironmentNAVXYTHETALAT::~EnvironmentNAVXYTHETALAT()
02013 {
02014         SBPL_PRINTF("destroying XYTHETALAT\n");
02015 
02016         //delete the states themselves first
02017         for (int i = 0; i < (int)StateID2CoordTable.size(); i++)
02018         {
02019                 delete StateID2CoordTable.at(i);
02020                 StateID2CoordTable.at(i) = NULL;
02021         }
02022         StateID2CoordTable.clear();
02023 
02024         //delete hashtable
02025         if(Coord2StateIDHashTable != NULL)
02026         {
02027                 delete [] Coord2StateIDHashTable;
02028                 Coord2StateIDHashTable = NULL;
02029         }       
02030         if(Coord2StateIDHashTable_lookup != NULL)
02031         {
02032                 delete [] Coord2StateIDHashTable_lookup;
02033                 Coord2StateIDHashTable_lookup = NULL;
02034         }
02035 
02036 }
02037 
02038 
02039 void EnvironmentNAVXYTHETALAT::GetCoordFromState(int stateID, int& x, int& y, int& theta) const {
02040   EnvNAVXYTHETALATHashEntry_t* HashEntry = StateID2CoordTable[stateID];
02041   x = HashEntry->X;
02042   y = HashEntry->Y;
02043   theta = HashEntry->Theta;
02044 }
02045 
02046 int EnvironmentNAVXYTHETALAT::GetStateFromCoord(int x, int y, int theta) {
02047 
02048    EnvNAVXYTHETALATHashEntry_t* OutHashEntry;
02049     if((OutHashEntry = (this->*GetHashEntry)(x, y, theta)) == NULL){
02050         //have to create a new entry
02051         OutHashEntry = (this->*CreateNewHashEntry)(x, y, theta);
02052     }
02053     return OutHashEntry->stateID;
02054 }
02055 
02056 void EnvironmentNAVXYTHETALAT::ConvertStateIDPathintoXYThetaPath(vector<int>* stateIDPath, vector<EnvNAVXYTHETALAT3Dpt_t>* xythetaPath)
02057 {
02058         vector<EnvNAVXYTHETALATAction_t*> actionV;
02059         vector<int> CostV;
02060         vector<int> SuccIDV;
02061         int targetx_c, targety_c, targettheta_c;
02062         int sourcex_c, sourcey_c, sourcetheta_c;
02063 
02064         SBPL_PRINTF("checks=%ld\n", checks);
02065 
02066         xythetaPath->clear();
02067 
02068 #if DEBUG
02069         SBPL_FPRINTF(fDeb, "converting stateid path into coordinates:\n");
02070 #endif
02071 
02072         for(int pind = 0; pind < (int)(stateIDPath->size())-1; pind++)
02073         {
02074                 int sourceID = stateIDPath->at(pind);
02075                 int targetID = stateIDPath->at(pind+1);
02076 
02077 #if DEBUG
02078                 GetCoordFromState(sourceID, sourcex_c, sourcey_c, sourcetheta_c);
02079 #endif
02080 
02081 
02082                 //get successors and pick the target via the cheapest action
02083                 SuccIDV.clear();
02084                 CostV.clear();
02085                 actionV.clear();
02086                 GetSuccs(sourceID, &SuccIDV, &CostV, &actionV);
02087                 
02088                 int bestcost = INFINITECOST;
02089                 int bestsind = -1;
02090 
02091 #if DEBUG
02092                 GetCoordFromState(sourceID, sourcex_c, sourcey_c, sourcetheta_c);
02093                 GetCoordFromState(targetID, targetx_c, targety_c, targettheta_c);
02094                 SBPL_FPRINTF(fDeb, "looking for %d %d %d -> %d %d %d (numofsuccs=%d)\n", sourcex_c, sourcey_c, sourcetheta_c,
02095                                         targetx_c, targety_c, targettheta_c, SuccIDV.size()); 
02096 
02097 #endif
02098 
02099                 for(int sind = 0; sind < (int)SuccIDV.size(); sind++)
02100                 {
02101 
02102 #if DEBUG
02103                 int x_c, y_c, theta_c;
02104                 GetCoordFromState(SuccIDV[sind], x_c, y_c, theta_c);
02105                 SBPL_FPRINTF(fDeb, "succ: %d %d %d\n", x_c, y_c, theta_c); 
02106 #endif
02107 
02108                         if(SuccIDV[sind] == targetID && CostV[sind] <= bestcost)
02109                         {
02110                                 bestcost = CostV[sind];
02111                                 bestsind = sind;
02112                         }
02113                 }
02114                 if(bestsind == -1)
02115                 {
02116                         SBPL_ERROR("ERROR: successor not found for transition:\n");
02117                         GetCoordFromState(sourceID, sourcex_c, sourcey_c, sourcetheta_c);
02118                         GetCoordFromState(targetID, targetx_c, targety_c, targettheta_c);
02119                         SBPL_PRINTF("%d %d %d -> %d %d %d\n", sourcex_c, sourcey_c, sourcetheta_c,
02120                                         targetx_c, targety_c, targettheta_c); 
02121                         throw new SBPL_Exception();
02122                 }
02123 
02124                 //now push in the actual path
02125                 int sourcex_c, sourcey_c, sourcetheta_c;
02126                 GetCoordFromState(sourceID, sourcex_c, sourcey_c, sourcetheta_c);
02127                 double sourcex, sourcey;
02128                 sourcex = DISCXY2CONT(sourcex_c, EnvNAVXYTHETALATCfg.cellsize_m);
02129                 sourcey = DISCXY2CONT(sourcey_c, EnvNAVXYTHETALATCfg.cellsize_m);
02130                 //TODO - when there are no motion primitives we should still print source state
02131                 for(int ipind = 0; ipind < ((int)actionV[bestsind]->intermptV.size())-1; ipind++) 
02132                 {
02133                         //translate appropriately
02134                         EnvNAVXYTHETALAT3Dpt_t intermpt = actionV[bestsind]->intermptV[ipind];
02135                         intermpt.x += sourcex;
02136                         intermpt.y += sourcey;
02137 
02138 #if DEBUG
02139                         int nx = CONTXY2DISC(intermpt.x, EnvNAVXYTHETALATCfg.cellsize_m);
02140                         int ny = CONTXY2DISC(intermpt.y, EnvNAVXYTHETALATCfg.cellsize_m);
02141                         SBPL_FPRINTF(fDeb, "%.3f %.3f %.3f (%d %d %d cost=%d) ", 
02142                                 intermpt.x, intermpt.y, intermpt.theta, 
02143                                 nx, ny, 
02144                                 ContTheta2Disc(intermpt.theta, NAVXYTHETALAT_THETADIRS), EnvNAVXYTHETALATCfg.Grid2D[nx][ny]);
02145                         if(ipind == 0) SBPL_FPRINTF(fDeb, "first (heur=%d)\n", GetStartHeuristic(sourceID));
02146                         else SBPL_FPRINTF(fDeb, "\n");
02147 #endif
02148 
02149                         //store
02150                         xythetaPath->push_back(intermpt);
02151                 }
02152         }
02153 }
02154 
02155 
02156 //returns the stateid if success, and -1 otherwise
02157 int EnvironmentNAVXYTHETALAT::SetGoal(double x_m, double y_m, double theta_rad){
02158 
02159         int x = CONTXY2DISC(x_m, EnvNAVXYTHETALATCfg.cellsize_m);
02160         int y = CONTXY2DISC(y_m, EnvNAVXYTHETALATCfg.cellsize_m);
02161         int theta = ContTheta2Disc(theta_rad, NAVXYTHETALAT_THETADIRS);
02162 
02163         SBPL_PRINTF("env: setting goal to %.3f %.3f %.3f (%d %d %d)\n", x_m, y_m, theta_rad, x, y, theta);
02164 
02165         if(!IsWithinMapCell(x,y))
02166         {
02167                 SBPL_ERROR("ERROR: trying to set a goal cell %d %d that is outside of map\n", x,y);
02168                 return -1;
02169         }
02170 
02171     if(!IsValidConfiguration(x,y,theta))
02172         {
02173                 SBPL_PRINTF("WARNING: goal configuration is invalid\n");
02174         }
02175 
02176     EnvNAVXYTHETALATHashEntry_t* OutHashEntry;
02177     if((OutHashEntry = (this->*GetHashEntry)(x, y, theta)) == NULL){
02178         //have to create a new entry
02179         OutHashEntry = (this->*CreateNewHashEntry)(x, y, theta);
02180     }
02181 
02182         //need to recompute start heuristics?
02183         if(EnvNAVXYTHETALAT.goalstateid != OutHashEntry->stateID)
02184         {
02185                 bNeedtoRecomputeStartHeuristics = true; //because termination condition may not plan all the way to the new goal
02186                 bNeedtoRecomputeGoalHeuristics = true; //because goal heuristics change
02187         }
02188 
02189 
02190 
02191     EnvNAVXYTHETALAT.goalstateid = OutHashEntry->stateID;
02192 
02193         EnvNAVXYTHETALATCfg.EndX_c = x;
02194         EnvNAVXYTHETALATCfg.EndY_c = y;
02195         EnvNAVXYTHETALATCfg.EndTheta = theta;
02196 
02197 
02198     return EnvNAVXYTHETALAT.goalstateid;    
02199 
02200 }
02201 
02202 
02203 //returns the stateid if success, and -1 otherwise
02204 int EnvironmentNAVXYTHETALAT::SetStart(double x_m, double y_m, double theta_rad){
02205 
02206         int x = CONTXY2DISC(x_m, EnvNAVXYTHETALATCfg.cellsize_m);
02207         int y = CONTXY2DISC(y_m, EnvNAVXYTHETALATCfg.cellsize_m); 
02208         int theta = ContTheta2Disc(theta_rad, NAVXYTHETALAT_THETADIRS);
02209 
02210         if(!IsWithinMapCell(x,y))
02211         {
02212                 SBPL_ERROR("ERROR: trying to set a start cell %d %d that is outside of map\n", x,y);
02213                 return -1;
02214         }
02215 
02216         SBPL_PRINTF("env: setting start to %.3f %.3f %.3f (%d %d %d)\n", x_m, y_m, theta_rad, x, y, theta);
02217 
02218     if(!IsValidConfiguration(x,y,theta))
02219         {
02220                 SBPL_PRINTF("WARNING: start configuration %d %d %d is invalid\n", x,y,theta);
02221         }
02222 
02223     EnvNAVXYTHETALATHashEntry_t* OutHashEntry;
02224     if((OutHashEntry = (this->*GetHashEntry)(x, y, theta)) == NULL){
02225         //have to create a new entry
02226         OutHashEntry = (this->*CreateNewHashEntry)(x, y, theta);
02227     }
02228 
02229         //need to recompute start heuristics?
02230         if(EnvNAVXYTHETALAT.startstateid != OutHashEntry->stateID)
02231         {
02232                 bNeedtoRecomputeStartHeuristics = true;
02233                 bNeedtoRecomputeGoalHeuristics = true; //because termination condition can be not all states TODO - make it dependent on term. condition
02234         }
02235 
02236         //set start
02237     EnvNAVXYTHETALAT.startstateid = OutHashEntry->stateID;
02238         EnvNAVXYTHETALATCfg.StartX_c = x;
02239         EnvNAVXYTHETALATCfg.StartY_c = y;
02240         EnvNAVXYTHETALATCfg.StartTheta = theta;
02241 
02242     return EnvNAVXYTHETALAT.startstateid;    
02243 
02244 }
02245 
02246 void EnvironmentNAVXYTHETALAT::PrintState(int stateID, bool bVerbose, FILE* fOut /*=NULL*/)
02247 {
02248 #if DEBUG
02249         if(stateID >= (int)StateID2CoordTable.size())
02250         {
02251                 SBPL_ERROR("ERROR in EnvNAVXYTHETALAT... function: stateID illegal (2)\n");
02252                 throw new SBPL_Exception();
02253         }
02254 #endif
02255 
02256         if(fOut == NULL)
02257                 fOut = stdout;
02258 
02259         EnvNAVXYTHETALATHashEntry_t* HashEntry = StateID2CoordTable[stateID];
02260 
02261         if(stateID == EnvNAVXYTHETALAT.goalstateid && bVerbose)
02262         {
02263                 SBPL_FPRINTF(fOut, "the state is a goal state\n");
02264         }
02265 
02266     if(bVerbose)
02267         SBPL_FPRINTF(fOut, "X=%d Y=%d Theta=%d\n", HashEntry->X, HashEntry->Y, HashEntry->Theta);
02268     else
02269         SBPL_FPRINTF(fOut, "%.3f %.3f %.3f\n", DISCXY2CONT(HashEntry->X, EnvNAVXYTHETALATCfg.cellsize_m), DISCXY2CONT(HashEntry->Y,EnvNAVXYTHETALATCfg.cellsize_m), 
02270                 DiscTheta2Cont(HashEntry->Theta, NAVXYTHETALAT_THETADIRS));
02271 
02272 }
02273 
02274 
02275 EnvNAVXYTHETALATHashEntry_t* EnvironmentNAVXYTHETALAT::GetHashEntry_lookup(int X, int Y, int Theta)
02276 {
02277 
02278         int index = XYTHETA2INDEX(X,Y,Theta);   
02279         return Coord2StateIDHashTable_lookup[index];
02280 
02281 }
02282 
02283 
02284 EnvNAVXYTHETALATHashEntry_t* EnvironmentNAVXYTHETALAT::GetHashEntry_hash(int X, int Y, int Theta)
02285 {
02286 
02287 #if TIME_DEBUG
02288         clock_t currenttime = clock();
02289 #endif
02290 
02291         int binid = GETHASHBIN(X, Y, Theta);    
02292 
02293 #if DEBUG
02294         if ((int)Coord2StateIDHashTable[binid].size() > 5)
02295         {
02296                 SBPL_FPRINTF(fDeb, "WARNING: Hash table has a bin %d (X=%d Y=%d) of size %d\n", 
02297                         binid, X, Y, Coord2StateIDHashTable[binid].size());
02298                 
02299                 PrintHashTableHist(fDeb);               
02300         }
02301 #endif
02302 
02303         //iterate over the states in the bin and select the perfect match
02304         vector<EnvNAVXYTHETALATHashEntry_t*>* binV = &Coord2StateIDHashTable[binid];
02305         for(int ind = 0; ind < (int)binV->size(); ind++)
02306         {
02307                 EnvNAVXYTHETALATHashEntry_t* hashentry = binV->at(ind);
02308                 if( hashentry->X == X  && hashentry->Y == Y && hashentry->Theta == Theta)
02309                 {
02310 #if TIME_DEBUG
02311                         time_gethash += clock()-currenttime;
02312 #endif
02313                         return hashentry;
02314                 }
02315         }
02316 
02317 #if TIME_DEBUG  
02318         time_gethash += clock()-currenttime;
02319 #endif
02320 
02321         return NULL;      
02322 }
02323 
02324 EnvNAVXYTHETALATHashEntry_t* EnvironmentNAVXYTHETALAT::CreateNewHashEntry_lookup(int X, int Y, int Theta) 
02325 {
02326         int i;
02327 
02328 #if TIME_DEBUG  
02329         clock_t currenttime = clock();
02330 #endif
02331 
02332         EnvNAVXYTHETALATHashEntry_t* HashEntry = new EnvNAVXYTHETALATHashEntry_t;
02333 
02334         HashEntry->X = X;
02335         HashEntry->Y = Y;
02336         HashEntry->Theta = Theta;
02337         HashEntry->iteration = 0;
02338 
02339         HashEntry->stateID = StateID2CoordTable.size();
02340 
02341         //insert into the tables
02342         StateID2CoordTable.push_back(HashEntry);
02343 
02344         int index = XYTHETA2INDEX(X,Y,Theta);
02345 
02346 #if DEBUG
02347         if(Coord2StateIDHashTable_lookup[index] != NULL)
02348         {
02349                 SBPL_ERROR("ERROR: creating hash entry for non-NULL hashentry\n");
02350                 throw new SBPL_Exception();
02351         }
02352 #endif
02353 
02354         Coord2StateIDHashTable_lookup[index] =  HashEntry;
02355 
02356         //insert into and initialize the mappings
02357         int* entry = new int [NUMOFINDICES_STATEID2IND]; 
02358         StateID2IndexMapping.push_back(entry);
02359         for(i = 0; i < NUMOFINDICES_STATEID2IND; i++)
02360         {
02361                 StateID2IndexMapping[HashEntry->stateID][i] = -1;
02362         }
02363 
02364         if(HashEntry->stateID != (int)StateID2IndexMapping.size()-1)
02365         {
02366                 SBPL_ERROR("ERROR in Env... function: last state has incorrect stateID\n");
02367                 throw new SBPL_Exception();     
02368         }
02369 
02370 #if TIME_DEBUG
02371         time_createhash += clock()-currenttime;
02372 #endif
02373 
02374         return HashEntry;
02375 }
02376 
02377 
02378 
02379 
02380 EnvNAVXYTHETALATHashEntry_t* EnvironmentNAVXYTHETALAT::CreateNewHashEntry_hash(int X, int Y, int Theta) 
02381 {
02382         int i;
02383 
02384 #if TIME_DEBUG  
02385         clock_t currenttime = clock();
02386 #endif
02387 
02388         EnvNAVXYTHETALATHashEntry_t* HashEntry = new EnvNAVXYTHETALATHashEntry_t;
02389 
02390         HashEntry->X = X;
02391         HashEntry->Y = Y;
02392         HashEntry->Theta = Theta;
02393         HashEntry->iteration = 0;
02394 
02395         HashEntry->stateID = StateID2CoordTable.size();
02396 
02397         //insert into the tables
02398         StateID2CoordTable.push_back(HashEntry);
02399 
02400 
02401         //get the hash table bin
02402         i = GETHASHBIN(HashEntry->X, HashEntry->Y, HashEntry->Theta); 
02403 
02404         //insert the entry into the bin
02405     Coord2StateIDHashTable[i].push_back(HashEntry);
02406 
02407         //insert into and initialize the mappings
02408         int* entry = new int [NUMOFINDICES_STATEID2IND]; 
02409         StateID2IndexMapping.push_back(entry);
02410         for(i = 0; i < NUMOFINDICES_STATEID2IND; i++)
02411         {
02412                 StateID2IndexMapping[HashEntry->stateID][i] = -1;
02413         }
02414 
02415         if(HashEntry->stateID != (int)StateID2IndexMapping.size()-1)
02416         {
02417                 SBPL_ERROR("ERROR in Env... function: last state has incorrect stateID\n");
02418                 throw new SBPL_Exception();     
02419         }
02420 
02421 #if TIME_DEBUG
02422         time_createhash += clock()-currenttime;
02423 #endif
02424 
02425         return HashEntry;
02426 }
02427 
02428 
02429 
02430 void EnvironmentNAVXYTHETALAT::GetSuccs(int SourceStateID, vector<int>* SuccIDV, vector<int>* CostV, vector<EnvNAVXYTHETALATAction_t*>* actionV /*=NULL*/)
02431 {
02432     int aind;
02433 
02434 #if TIME_DEBUG
02435                 clock_t currenttime = clock();
02436 #endif
02437 
02438     //clear the successor array
02439     SuccIDV->clear();
02440     CostV->clear();
02441     SuccIDV->reserve(EnvNAVXYTHETALATCfg.actionwidth); 
02442     CostV->reserve(EnvNAVXYTHETALATCfg.actionwidth);
02443         if(actionV != NULL)
02444         {
02445                 actionV->clear();
02446                 actionV->reserve(EnvNAVXYTHETALATCfg.actionwidth);
02447         }
02448 
02449         //goal state should be absorbing
02450         if(SourceStateID == EnvNAVXYTHETALAT.goalstateid)
02451                 return;
02452 
02453         //get X, Y for the state
02454         EnvNAVXYTHETALATHashEntry_t* HashEntry = StateID2CoordTable[SourceStateID];
02455         
02456         //iterate through actions
02457         for (aind = 0; aind < EnvNAVXYTHETALATCfg.actionwidth; aind++)
02458         {
02459                 EnvNAVXYTHETALATAction_t* nav3daction = &EnvNAVXYTHETALATCfg.ActionsV[(unsigned int)HashEntry->Theta][aind];
02460         int newX = HashEntry->X + nav3daction->dX;
02461                 int newY = HashEntry->Y + nav3daction->dY;
02462                 int newTheta = NORMALIZEDISCTHETA(nav3daction->endtheta, NAVXYTHETALAT_THETADIRS);      
02463 
02464         //skip the invalid cells
02465         if(!IsValidCell(newX, newY)) 
02466                         continue;
02467 
02468                 //get cost
02469                 int cost = GetActionCost(HashEntry->X, HashEntry->Y, HashEntry->Theta, nav3daction);
02470         if(cost >= INFINITECOST)
02471             continue;
02472 
02473         EnvNAVXYTHETALATHashEntry_t* OutHashEntry;
02474                 if((OutHashEntry = (this->*GetHashEntry)(newX, newY, newTheta)) == NULL)
02475                 {
02476                         //have to create a new entry
02477                         OutHashEntry = (this->*CreateNewHashEntry)(newX, newY, newTheta);
02478                 }
02479 
02480         SuccIDV->push_back(OutHashEntry->stateID);
02481         CostV->push_back(cost);
02482                 if(actionV != NULL)
02483                         actionV->push_back(nav3daction);
02484         }
02485 
02486 #if TIME_DEBUG
02487                 time_getsuccs += clock()-currenttime;
02488 #endif
02489 
02490 }
02491 
02492 void EnvironmentNAVXYTHETALAT::GetPreds(int TargetStateID, vector<int>* PredIDV, vector<int>* CostV)
02493 {
02494 
02495         //TODO- to support tolerance, need: a) generate preds for goal state based on all possible goal state variable settings,
02496         //b) change goal check condition in gethashentry c) change getpredsofchangedcells and getsuccsofchangedcells functions
02497 
02498     int aind;
02499 
02500 #if TIME_DEBUG
02501         clock_t currenttime = clock();
02502 #endif
02503 
02504         //get X, Y for the state
02505         EnvNAVXYTHETALATHashEntry_t* HashEntry = StateID2CoordTable[TargetStateID];
02506 
02507     //clear the successor array
02508     PredIDV->clear();
02509     CostV->clear();
02510     PredIDV->reserve(EnvNAVXYTHETALATCfg.PredActionsV[(unsigned int)HashEntry->Theta].size()); 
02511     CostV->reserve(EnvNAVXYTHETALATCfg.PredActionsV[(unsigned int)HashEntry->Theta].size());
02512         
02513         //iterate through actions
02514         vector<EnvNAVXYTHETALATAction_t*>* actionsV = &EnvNAVXYTHETALATCfg.PredActionsV[(unsigned int)HashEntry->Theta];
02515         for (aind = 0; aind < (int)EnvNAVXYTHETALATCfg.PredActionsV[(unsigned int)HashEntry->Theta].size(); aind++)
02516         {
02517 
02518                 EnvNAVXYTHETALATAction_t* nav3daction = actionsV->at(aind);
02519 
02520         int predX = HashEntry->X - nav3daction->dX;
02521                 int predY = HashEntry->Y - nav3daction->dY;
02522                 int predTheta = nav3daction->starttheta;        
02523         
02524         
02525                 //skip the invalid cells
02526         if(!IsValidCell(predX, predY))
02527                         continue;
02528 
02529                 //get cost
02530                 int cost = GetActionCost(predX, predY, predTheta, nav3daction);
02531             if(cost >= INFINITECOST)
02532                         continue;
02533         
02534         EnvNAVXYTHETALATHashEntry_t* OutHashEntry;
02535                 if((OutHashEntry = (this->*GetHashEntry)(predX, predY, predTheta)) == NULL)
02536                 {
02537                         //have to create a new entry
02538                         OutHashEntry = (this->*CreateNewHashEntry)(predX, predY, predTheta);
02539                 }
02540 
02541         PredIDV->push_back(OutHashEntry->stateID);
02542         CostV->push_back(cost);
02543         }
02544 
02545 #if TIME_DEBUG
02546                 time_getsuccs += clock()-currenttime;
02547 #endif
02548 
02549 
02550 }
02551 
02552 void EnvironmentNAVXYTHETALAT::SetAllActionsandAllOutcomes(CMDPSTATE* state)
02553 {
02554 
02555         int cost;
02556 
02557 #if DEBUG
02558         if(state->StateID >= (int)StateID2CoordTable.size())
02559         {
02560                 SBPL_ERROR("ERROR in Env... function: stateID illegal\n");
02561                 throw new SBPL_Exception();
02562         }
02563 
02564         if((int)state->Actions.size() != 0)
02565         {
02566                 SBPL_ERROR("ERROR in Env_setAllActionsandAllOutcomes: actions already exist for the state\n");
02567                 throw new SBPL_Exception();
02568         }
02569 #endif
02570         
02571 
02572         //goal state should be absorbing
02573         if(state->StateID == EnvNAVXYTHETALAT.goalstateid)
02574                 return;
02575 
02576         //get X, Y for the state
02577         EnvNAVXYTHETALATHashEntry_t* HashEntry = StateID2CoordTable[state->StateID];
02578         
02579         //iterate through actions
02580         for (int aind = 0; aind < EnvNAVXYTHETALATCfg.actionwidth; aind++)
02581         {
02582                 EnvNAVXYTHETALATAction_t* nav3daction = &EnvNAVXYTHETALATCfg.ActionsV[(unsigned int)HashEntry->Theta][aind];
02583         int newX = HashEntry->X + nav3daction->dX;
02584                 int newY = HashEntry->Y + nav3daction->dY;
02585                 int newTheta = NORMALIZEDISCTHETA(nav3daction->endtheta, NAVXYTHETALAT_THETADIRS);      
02586 
02587         //skip the invalid cells
02588         if(!IsValidCell(newX, newY))
02589                         continue;
02590 
02591                 //get cost
02592                 cost = GetActionCost(HashEntry->X, HashEntry->Y, HashEntry->Theta, nav3daction);
02593         if(cost >= INFINITECOST)
02594             continue;
02595 
02596                 //add the action
02597                 CMDPACTION* action = state->AddAction(aind);
02598 
02599 #if TIME_DEBUG
02600                 clock_t currenttime = clock();
02601 #endif
02602 
02603         EnvNAVXYTHETALATHashEntry_t* OutHashEntry;
02604                 if((OutHashEntry = (this->*GetHashEntry)(newX, newY, newTheta)) == NULL)
02605                 {
02606                         //have to create a new entry
02607                         OutHashEntry = (this->*CreateNewHashEntry)(newX, newY, newTheta);
02608                 }
02609                 action->AddOutcome(OutHashEntry->stateID, cost, 1.0); 
02610 
02611 #if TIME_DEBUG
02612                 time3_addallout += clock()-currenttime;
02613 #endif
02614 
02615         }
02616 }
02617 
02618 
02619 void EnvironmentNAVXYTHETALAT::GetPredsofChangedEdges(vector<nav2dcell_t> const * changedcellsV, vector<int> *preds_of_changededgesIDV)
02620 {
02621         nav2dcell_t cell;
02622         EnvNAVXYTHETALAT3Dcell_t affectedcell;
02623         EnvNAVXYTHETALATHashEntry_t* affectedHashEntry;
02624 
02625         //increment iteration for processing savings
02626         iteration++;
02627 
02628         for(int i = 0; i < (int)changedcellsV->size(); i++) 
02629         {
02630                 cell = changedcellsV->at(i);
02631                         
02632                 //now iterate over all states that could potentially be affected
02633                 for(int sind = 0; sind < (int)affectedpredstatesV.size(); sind++)
02634                 {
02635                         affectedcell = affectedpredstatesV.at(sind);
02636 
02637                         //translate to correct for the offset
02638                         affectedcell.x = affectedcell.x + cell.x;
02639                         affectedcell.y = affectedcell.y + cell.y;
02640 
02641                         //insert only if it was actually generated
02642                     affectedHashEntry = (this->*GetHashEntry)(affectedcell.x, affectedcell.y, affectedcell.theta);
02643                         if(affectedHashEntry != NULL && affectedHashEntry->iteration < iteration)
02644                         {
02645                                 preds_of_changededgesIDV->push_back(affectedHashEntry->stateID);
02646                                 affectedHashEntry->iteration = iteration; //mark as already inserted
02647                         }
02648                 }
02649         }
02650 }
02651 
02652 void EnvironmentNAVXYTHETALAT::GetSuccsofChangedEdges(vector<nav2dcell_t> const * changedcellsV, vector<int> *succs_of_changededgesIDV)
02653 {
02654         nav2dcell_t cell;
02655         EnvNAVXYTHETALAT3Dcell_t affectedcell;
02656         EnvNAVXYTHETALATHashEntry_t* affectedHashEntry;
02657 
02658         SBPL_ERROR("ERROR: getsuccs is not supported currently\n");
02659         throw new SBPL_Exception();
02660 
02661         //increment iteration for processing savings
02662         iteration++;
02663 
02664         //TODO - check
02665         for(int i = 0; i < (int)changedcellsV->size(); i++) 
02666         {
02667                 cell = changedcellsV->at(i);
02668                         
02669                 //now iterate over all states that could potentially be affected
02670                 for(int sind = 0; sind < (int)affectedsuccstatesV.size(); sind++)
02671                 {
02672                         affectedcell = affectedsuccstatesV.at(sind);
02673 
02674                         //translate to correct for the offset
02675                         affectedcell.x = affectedcell.x + cell.x;
02676                         affectedcell.y = affectedcell.y + cell.y;
02677 
02678                         //insert only if it was actually generated
02679                     affectedHashEntry = (this->*GetHashEntry)(affectedcell.x, affectedcell.y, affectedcell.theta);
02680                         if(affectedHashEntry != NULL && affectedHashEntry->iteration < iteration)
02681                         {
02682                                 succs_of_changededgesIDV->push_back(affectedHashEntry->stateID);
02683                                 affectedHashEntry->iteration = iteration; //mark as already inserted
02684                         }
02685                 }
02686         }
02687 }
02688 
02689 void EnvironmentNAVXYTHETALAT::InitializeEnvironment()
02690 {
02691         EnvNAVXYTHETALATHashEntry_t* HashEntry;
02692 
02693         int maxsize = EnvNAVXYTHETALATCfg.EnvWidth_c*EnvNAVXYTHETALATCfg.EnvHeight_c*NAVXYTHETALAT_THETADIRS;
02694 
02695         if(maxsize <= SBPL_XYTHETALAT_MAXSTATESFORLOOKUP)
02696         {
02697                 SBPL_PRINTF("environment stores states in lookup table\n");
02698 
02699                 Coord2StateIDHashTable_lookup = new EnvNAVXYTHETALATHashEntry_t*[maxsize]; 
02700                 for(int i = 0; i < maxsize; i++)
02701                         Coord2StateIDHashTable_lookup[i] = NULL;
02702                 GetHashEntry = &EnvironmentNAVXYTHETALAT::GetHashEntry_lookup;
02703                 CreateNewHashEntry = &EnvironmentNAVXYTHETALAT::CreateNewHashEntry_lookup;
02704                 
02705                 //not using hash table
02706                 HashTableSize = 0;
02707                 Coord2StateIDHashTable = NULL;
02708         }
02709         else
02710         {               
02711                 SBPL_PRINTF("environment stores states in hashtable\n");
02712 
02713                 //initialize the map from Coord to StateID
02714                 HashTableSize = 4*1024*1024; //should be power of two 
02715                 Coord2StateIDHashTable = new vector<EnvNAVXYTHETALATHashEntry_t*>[HashTableSize]; 
02716                 GetHashEntry = &EnvironmentNAVXYTHETALAT::GetHashEntry_hash;
02717                 CreateNewHashEntry = &EnvironmentNAVXYTHETALAT::CreateNewHashEntry_hash;
02718 
02719                 //not using hash
02720                 Coord2StateIDHashTable_lookup = NULL;
02721         }
02722 
02723 
02724         //initialize the map from StateID to Coord
02725         StateID2CoordTable.clear();
02726 
02727         //create start state 
02728         if((HashEntry = (this->*GetHashEntry)(EnvNAVXYTHETALATCfg.StartX_c, EnvNAVXYTHETALATCfg.StartY_c, EnvNAVXYTHETALATCfg.StartTheta)) == NULL){
02729         //have to create a new entry
02730                 HashEntry = (this->*CreateNewHashEntry)(EnvNAVXYTHETALATCfg.StartX_c, EnvNAVXYTHETALATCfg.StartY_c, EnvNAVXYTHETALATCfg.StartTheta);
02731         }
02732         EnvNAVXYTHETALAT.startstateid = HashEntry->stateID;
02733 
02734         //create goal state 
02735         if((HashEntry = (this->*GetHashEntry)(EnvNAVXYTHETALATCfg.EndX_c, EnvNAVXYTHETALATCfg.EndY_c, EnvNAVXYTHETALATCfg.EndTheta)) == NULL){
02736         //have to create a new entry
02737                 HashEntry = (this->*CreateNewHashEntry)(EnvNAVXYTHETALATCfg.EndX_c, EnvNAVXYTHETALATCfg.EndY_c, EnvNAVXYTHETALATCfg.EndTheta);
02738         }
02739         EnvNAVXYTHETALAT.goalstateid = HashEntry->stateID;
02740 
02741         //initialized
02742         EnvNAVXYTHETALAT.bInitialized = true;
02743 
02744 }
02745 
02746 
02747 //examples of hash functions: map state coordinates onto a hash value
02748 //#define GETHASHBIN(X, Y) (Y*WIDTH_Y+X) 
02749 //here we have state coord: <X1, X2, X3, X4>
02750 unsigned int EnvironmentNAVXYTHETALAT::GETHASHBIN(unsigned int X1, unsigned int X2, unsigned int Theta)
02751 {
02752 
02753         return inthash(inthash(X1)+(inthash(X2)<<1)+(inthash(Theta)<<2)) & (HashTableSize-1);
02754 }
02755 
02756 void EnvironmentNAVXYTHETALAT::PrintHashTableHist(FILE* fOut)
02757 {
02758         int s0=0, s1=0, s50=0, s100=0, s200=0, s300=0, slarge=0;
02759 
02760         for(int  j = 0; j < HashTableSize; j++)
02761         {
02762           if((int)Coord2StateIDHashTable[j].size() == 0)
02763                         s0++;
02764                 else if((int)Coord2StateIDHashTable[j].size() < 5)
02765                         s1++;
02766                 else if((int)Coord2StateIDHashTable[j].size() < 25)
02767                         s50++;
02768                 else if((int)Coord2StateIDHashTable[j].size() < 50)
02769                         s100++;
02770                 else if((int)Coord2StateIDHashTable[j].size() < 100)
02771                         s200++;
02772                 else if((int)Coord2StateIDHashTable[j].size() < 400)
02773                         s300++;
02774                 else
02775                         slarge++;
02776         }
02777         SBPL_FPRINTF(fOut, "hash table histogram: 0:%d, <5:%d, <25:%d, <50:%d, <100:%d, <400:%d, >400:%d\n",
02778                 s0,s1, s50, s100, s200,s300,slarge);
02779 }
02780 
02781 int EnvironmentNAVXYTHETALAT::GetFromToHeuristic(int FromStateID, int ToStateID)
02782 {
02783 
02784 #if USE_HEUR==0
02785         return 0;
02786 #endif
02787 
02788 
02789 #if DEBUG
02790         if(FromStateID >= (int)StateID2CoordTable.size() 
02791                 || ToStateID >= (int)StateID2CoordTable.size())
02792         {
02793                 SBPL_ERROR("ERROR in EnvNAVXYTHETALAT... function: stateID illegal\n");
02794                 throw new SBPL_Exception();
02795         }
02796 #endif
02797 
02798         //get X, Y for the state
02799         EnvNAVXYTHETALATHashEntry_t* FromHashEntry = StateID2CoordTable[FromStateID];
02800         EnvNAVXYTHETALATHashEntry_t* ToHashEntry = StateID2CoordTable[ToStateID];
02801         
02802         //TODO - check if one of the gridsearches already computed and then use it.
02803         
02804 
02805         return (int)(NAVXYTHETALAT_COSTMULT_MTOMM*EuclideanDistance_m(FromHashEntry->X, FromHashEntry->Y, ToHashEntry->X, ToHashEntry->Y)/EnvNAVXYTHETALATCfg.nominalvel_mpersecs);     
02806 
02807 }
02808 
02809 
02810 int EnvironmentNAVXYTHETALAT::GetGoalHeuristic(int stateID)
02811 {
02812 #if USE_HEUR==0
02813         return 0;
02814 #endif
02815 
02816 #if DEBUG
02817         if(stateID >= (int)StateID2CoordTable.size())
02818         {
02819                 SBPL_ERROR("ERROR in EnvNAVXYTHETALAT... function: stateID illegal\n");
02820                 throw new SBPL_Exception();
02821         }
02822 #endif
02823 
02824         EnvNAVXYTHETALATHashEntry_t* HashEntry = StateID2CoordTable[stateID];
02825         int h2D = grid2Dsearchfromgoal->getlowerboundoncostfromstart_inmm(HashEntry->X, HashEntry->Y); //computes distances from start state that is grid2D, so it is EndX_c EndY_c 
02826         int hEuclid = (int)(NAVXYTHETALAT_COSTMULT_MTOMM*EuclideanDistance_m(HashEntry->X, HashEntry->Y, EnvNAVXYTHETALATCfg.EndX_c, EnvNAVXYTHETALATCfg.EndY_c));
02827                 
02828         //define this function if it is used in the planner (heuristic backward search would use it)
02829     return (int)(((double)__max(h2D,hEuclid))/EnvNAVXYTHETALATCfg.nominalvel_mpersecs); 
02830 
02831 }
02832 
02833 
02834 int EnvironmentNAVXYTHETALAT::GetStartHeuristic(int stateID)
02835 {
02836 
02837 
02838 #if USE_HEUR==0
02839         return 0;
02840 #endif
02841 
02842 
02843 #if DEBUG
02844         if(stateID >= (int)StateID2CoordTable.size())
02845         {
02846                 SBPL_ERROR("ERROR in EnvNAVXYTHETALAT... function: stateID illegal\n");
02847                 throw new SBPL_Exception();
02848         }
02849 #endif
02850 
02851         EnvNAVXYTHETALATHashEntry_t* HashEntry = StateID2CoordTable[stateID];
02852         int h2D = grid2Dsearchfromstart->getlowerboundoncostfromstart_inmm(HashEntry->X, HashEntry->Y);
02853         int hEuclid = (int)(NAVXYTHETALAT_COSTMULT_MTOMM*EuclideanDistance_m(EnvNAVXYTHETALATCfg.StartX_c, EnvNAVXYTHETALATCfg.StartY_c, HashEntry->X, HashEntry->Y));
02854                 
02855         //define this function if it is used in the planner (heuristic backward search would use it)
02856     return (int)(((double)__max(h2D,hEuclid))/EnvNAVXYTHETALATCfg.nominalvel_mpersecs); 
02857 
02858 }
02859 
02860 int EnvironmentNAVXYTHETALAT::SizeofCreatedEnv()
02861 {
02862         return (int)StateID2CoordTable.size();
02863         
02864 }
02865 //------------------------------------------------------------------------------
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


sbpl
Author(s): Maxim Likhachev/maximl@seas.upenn.edu
autogenerated on Fri Jan 18 2013 13:41:53