$search
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 //------------------------------------------------------------------------------