$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 #if MEM_CHECK == 1 00035 void DisableMemCheck() 00036 { 00037 // Get the current state of the flag 00038 // and store it in a temporary variable 00039 int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); 00040 00041 // Turn On (OR) - All freed memory is re-initialized with xDD 00042 tmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF; 00043 00044 // Turn Off (AND) - memory checking is disabled for future allocations 00045 tmpFlag &= ~_CRTDBG_ALLOC_MEM_DF; 00046 00047 // Set the new state for the flag 00048 _CrtSetDbgFlag( tmpFlag ); 00049 00050 } 00051 00052 void EnableMemCheck() 00053 { 00054 // Get the current state of the flag 00055 // and store it in a temporary variable 00056 int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); 00057 00058 // Turn On (OR) - All freed memory is re-initialized with xDD 00059 tmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF; 00060 00061 // Turn On (OR) - memory checking is enabled for future allocations 00062 tmpFlag |= _CRTDBG_ALLOC_MEM_DF; 00063 00064 // Set the new state for the flag 00065 _CrtSetDbgFlag( tmpFlag ); 00066 00067 } 00068 #endif 00069 00070 void checkmdpstate(CMDPSTATE* state) 00071 { 00072 #if DEBUG == 0 00073 SBPL_ERROR("ERROR: checkMDPstate is too expensive for not in DEBUG mode\n"); 00074 throw new SBPL_Exception(); 00075 #endif 00076 00077 for(int aind = 0; aind < (int)state->Actions.size(); aind++) 00078 { 00079 for(int aind1 = 0; aind1 < (int)state->Actions.size(); aind1++) 00080 { 00081 if(state->Actions[aind1]->ActionID == state->Actions[aind]->ActionID && 00082 aind1 != aind) 00083 { 00084 SBPL_ERROR("ERROR in CheckMDP: multiple actions with the same ID exist\n"); 00085 throw new SBPL_Exception(); 00086 } 00087 } 00088 for(int sind = 0; sind < (int)state->Actions[aind]->SuccsID.size(); sind++) 00089 { 00090 for(int sind1 = 0; sind1 < (int)state->Actions[aind]->SuccsID.size(); sind1++) 00091 { 00092 if(state->Actions[aind]->SuccsID[sind] == state->Actions[aind]->SuccsID[sind1] && 00093 sind != sind1) 00094 { 00095 SBPL_ERROR("ERROR in CheckMDP: multiple outcomes with the same ID exist\n"); 00096 throw new SBPL_Exception(); 00097 } 00098 } 00099 } 00100 } 00101 } 00102 00103 00104 void CheckMDP(CMDP* mdp) 00105 { 00106 for(int i = 0; i < (int)mdp->StateArray.size(); i++) 00107 { 00108 checkmdpstate(mdp->StateArray[i]); 00109 } 00110 } 00111 00112 00113 00114 00115 void PrintMatrix(int** matrix, int rows, int cols, FILE* fOut) 00116 { 00117 for(int r = 0; r < rows; r++) 00118 { 00119 for(int c = 0; c < cols; c++) 00120 { 00121 SBPL_FPRINTF(fOut, "%d ", matrix[r][c]); 00122 } 00123 SBPL_FPRINTF(fOut, "\n"); 00124 } 00125 } 00126 00127 00128 //return true if there exists a path from sourcestate to targetstate and false otherwise 00129 bool PathExists(CMDP* pMarkovChain, CMDPSTATE* sourcestate, CMDPSTATE* targetstate) 00130 { 00131 CMDPSTATE* state; 00132 vector<CMDPSTATE*> WorkList; 00133 int i; 00134 bool *bProcessed = new bool [pMarkovChain->StateArray.size()]; 00135 bool bFound = false; 00136 00137 //insert the source state 00138 WorkList.push_back(sourcestate); 00139 while((int)WorkList.size() > 0) 00140 { 00141 //get the state and its info 00142 state = WorkList[WorkList.size()-1]; 00143 WorkList.pop_back(); 00144 00145 //Markov Chain should just contain a single policy 00146 if((int)state->Actions.size() > 1) 00147 { 00148 SBPL_ERROR("ERROR in PathExists: Markov Chain is a general MDP\n"); 00149 throw new SBPL_Exception(); 00150 } 00151 00152 if(state == targetstate) 00153 { 00154 //path found 00155 bFound = true; 00156 break; 00157 } 00158 00159 //otherwise just insert policy successors into the worklist unless it is a goal state 00160 for(int sind = 0; (int)state->Actions.size() != 0 && sind < (int)state->Actions[0]->SuccsID.size(); sind++) 00161 { 00162 //get a successor 00163 for(i = 0; i < (int)pMarkovChain->StateArray.size(); i++) 00164 { 00165 if(pMarkovChain->StateArray[i]->StateID == state->Actions[0]->SuccsID[sind]) 00166 break; 00167 } 00168 if(i == (int)pMarkovChain->StateArray.size()) 00169 { 00170 SBPL_ERROR("ERROR in PathExists: successor is not found\n"); 00171 throw new SBPL_Exception(); 00172 } 00173 CMDPSTATE* SuccState = pMarkovChain->StateArray[i]; 00174 00175 //insert at the end of list if not there or processed already 00176 if(!bProcessed[i]) 00177 { 00178 bProcessed[i] = true; 00179 WorkList.push_back(SuccState); 00180 } 00181 } //for successors 00182 }//while WorkList is non empty 00183 00184 delete [] bProcessed; 00185 00186 return bFound; 00187 } 00188 00189 int ComputeNumofStochasticActions(CMDP* pMDP) 00190 { 00191 int i; 00192 int nNumofStochActions = 0; 00193 SBPL_PRINTF("ComputeNumofStochasticActions...\n"); 00194 00195 for(i = 0; i < (int)pMDP->StateArray.size(); i++) 00196 { 00197 for(int aind = 0; aind < (int)pMDP->StateArray[i]->Actions.size(); aind++) 00198 { 00199 if((int)pMDP->StateArray[i]->Actions[aind]->SuccsID.size() > 1) 00200 nNumofStochActions++; 00201 } 00202 } 00203 SBPL_PRINTF("done\n"); 00204 00205 return nNumofStochActions; 00206 } 00207 00208 00209 void EvaluatePolicy(CMDP* PolicyMDP, int StartStateID, int GoalStateID, 00210 double* PolValue, bool *bFullPolicy, double* Pcgoal, int *nMerges, 00211 bool* bCycles) 00212 { 00213 int i, j, startind=-1; 00214 double delta = INFINITECOST; 00215 double mindelta = 0.1; 00216 00217 *Pcgoal = 0; 00218 *nMerges = 0; 00219 00220 SBPL_PRINTF("Evaluating policy...\n"); 00221 00222 //create and initialize values 00223 double* vals = new double [PolicyMDP->StateArray.size()]; 00224 double* Pcvals = new double [PolicyMDP->StateArray.size()]; 00225 for(i = 0; i < (int)PolicyMDP->StateArray.size(); i++) 00226 { 00227 vals[i] = 0; 00228 Pcvals[i] = 0; 00229 00230 //remember the start index 00231 if(PolicyMDP->StateArray[i]->StateID == StartStateID) 00232 { 00233 startind = i; 00234 Pcvals[i] = 1; 00235 } 00236 } 00237 00238 //initially assume full policy 00239 *bFullPolicy = true; 00240 bool bFirstIter = true; 00241 while(delta > mindelta) 00242 { 00243 delta = 0; 00244 for(i = 0; i < (int)PolicyMDP->StateArray.size(); i++) 00245 { 00246 //get the state 00247 CMDPSTATE* state = PolicyMDP->StateArray[i]; 00248 00249 //do the backup for values 00250 if(state->StateID == GoalStateID) 00251 { 00252 vals[i] = 0; 00253 } 00254 else if((int)state->Actions.size() == 0) 00255 { 00256 *bFullPolicy = false; 00257 vals[i] = UNKNOWN_COST; 00258 *PolValue = vals[startind]; 00259 return; 00260 } 00261 else 00262 { 00263 //normal backup 00264 CMDPACTION* action = state->Actions[0]; 00265 00266 //do backup 00267 double Q = 0; 00268 for(int oind = 0; oind < (int)action->SuccsID.size(); oind++) 00269 { 00270 //get the state 00271 for(j = 0; j < (int)PolicyMDP->StateArray.size(); j++) 00272 { 00273 if(PolicyMDP->StateArray[j]->StateID == action->SuccsID[oind]) 00274 break; 00275 } 00276 if(j == (int)PolicyMDP->StateArray.size()) 00277 { 00278 SBPL_ERROR("ERROR in EvaluatePolicy: incorrect successor %d\n", 00279 action->SuccsID[oind]); 00280 throw new SBPL_Exception(); 00281 } 00282 Q += action->SuccsProb[oind]*(vals[j] + action->Costs[oind]); 00283 } 00284 00285 if(vals[i] > Q) 00286 { 00287 SBPL_ERROR("ERROR in EvaluatePolicy: val is decreasing\n"); 00288 throw new SBPL_Exception(); 00289 } 00290 00291 //update delta 00292 if(delta < Q - vals[i]) 00293 delta = Q-vals[i]; 00294 00295 //set the value 00296 vals[i] = Q; 00297 } 00298 00299 //iterate through all the predecessors and compute Pc 00300 double Pc = 0; 00301 //go over all predecessor states 00302 int nMerge = 0; 00303 for(j = 0; j < (int)PolicyMDP->StateArray.size(); j++) 00304 { 00305 for(int oind = 0; (int)PolicyMDP->StateArray[j]->Actions.size() > 0 && 00306 oind < (int)PolicyMDP->StateArray[j]->Actions[0]->SuccsID.size(); oind++) 00307 { 00308 if(PolicyMDP->StateArray[j]->Actions[0]->SuccsID[oind] == state->StateID) 00309 { 00310 //process the predecessor 00311 double PredPc = Pcvals[j]; 00312 double OutProb = PolicyMDP->StateArray[j]->Actions[0]->SuccsProb[oind]; 00313 00314 //accumulate into Pc 00315 Pc = Pc + OutProb*PredPc; 00316 nMerge++; 00317 00318 //check for cycles 00319 if(bFirstIter && !(*bCycles)) 00320 { 00321 if(PathExists(PolicyMDP, state, PolicyMDP->StateArray[j])) 00322 *bCycles = true; 00323 } 00324 } 00325 } 00326 } 00327 if(bFirstIter && state->StateID != GoalStateID && nMerge > 0) 00328 *nMerges += (nMerge-1); 00329 00330 //assign Pc 00331 if(state->StateID != StartStateID) 00332 Pcvals[i] = Pc; 00333 00334 if(state->StateID == GoalStateID) 00335 *Pcgoal = Pcvals[i]; 00336 } //over states 00337 bFirstIter = false; 00338 } //until delta small 00339 00340 *PolValue = vals[startind]; 00341 00342 SBPL_PRINTF("done\n"); 00343 } 00344 00345 00346 00347 void get_bresenham_parameters(int p1x, int p1y, int p2x, int p2y, bresenham_param_t *params) 00348 { 00349 params->UsingYIndex = 0; 00350 00351 if (fabs((double)(p2y-p1y)/(double)(p2x-p1x)) > 1) 00352 (params->UsingYIndex)++; 00353 00354 if (params->UsingYIndex) 00355 { 00356 params->Y1=p1x; 00357 params->X1=p1y; 00358 params->Y2=p2x; 00359 params->X2=p2y; 00360 } 00361 else 00362 { 00363 params->X1=p1x; 00364 params->Y1=p1y; 00365 params->X2=p2x; 00366 params->Y2=p2y; 00367 } 00368 00369 if ((p2x - p1x) * (p2y - p1y) < 0) 00370 { 00371 params->Flipped = 1; 00372 params->Y1 = -params->Y1; 00373 params->Y2 = -params->Y2; 00374 } 00375 else 00376 params->Flipped = 0; 00377 00378 if (params->X2 > params->X1) 00379 params->Increment = 1; 00380 else 00381 params->Increment = -1; 00382 00383 params->DeltaX=params->X2-params->X1; 00384 params->DeltaY=params->Y2-params->Y1; 00385 00386 params->IncrE=2*params->DeltaY*params->Increment; 00387 params->IncrNE=2*(params->DeltaY-params->DeltaX)*params->Increment; 00388 params->DTerm=(2*params->DeltaY-params->DeltaX)*params->Increment; 00389 00390 params->XIndex = params->X1; 00391 params->YIndex = params->Y1; 00392 } 00393 00394 void get_current_point(bresenham_param_t *params, int *x, int *y) 00395 { 00396 if (params->UsingYIndex) 00397 { 00398 *y = params->XIndex; 00399 *x = params->YIndex; 00400 if (params->Flipped) 00401 *x = -*x; 00402 } 00403 else 00404 { 00405 *x = params->XIndex; 00406 *y = params->YIndex; 00407 if (params->Flipped) 00408 *y = -*y; 00409 } 00410 } 00411 00412 int get_next_point(bresenham_param_t *params) 00413 { 00414 if (params->XIndex == params->X2) 00415 { 00416 return 0; 00417 } 00418 params->XIndex += params->Increment; 00419 if (params->DTerm < 0 || (params->Increment < 0 && params->DTerm <= 0)) 00420 params->DTerm += params->IncrE; 00421 else 00422 { 00423 params->DTerm += params->IncrNE; 00424 params->YIndex += params->Increment; 00425 } 00426 return 1; 00427 } 00428 00429 00430 00431 //converts discretized version of angle into continuous (radians) 00432 //maps 0->0, 1->delta, 2->2*delta, ... 00433 double DiscTheta2Cont(int nTheta, int NUMOFANGLEVALS) 00434 { 00435 double thetaBinSize = 2.0*PI_CONST/NUMOFANGLEVALS; 00436 return nTheta*thetaBinSize; 00437 } 00438 00439 00440 00441 //converts continuous (radians) version of angle into discrete 00442 //maps 0->0, [delta/2, 3/2*delta)->1, [3/2*delta, 5/2*delta)->2,... 00443 int ContTheta2Disc(double fTheta, int NUMOFANGLEVALS) 00444 { 00445 00446 double thetaBinSize = 2.0*PI_CONST/NUMOFANGLEVALS; 00447 return (int)(normalizeAngle(fTheta+thetaBinSize/2.0)/(2.0*PI_CONST)*(NUMOFANGLEVALS)); 00448 00449 } 00450 00451 00452 00453 00454 //input angle should be in radians 00455 //counterclockwise is positive 00456 //output is an angle in the range of from 0 to 2*PI 00457 double normalizeAngle(double angle) 00458 { 00459 double retangle = angle; 00460 00461 //get to the range from -2PI, 2PI 00462 if(fabs(retangle) > 2*PI_CONST) 00463 retangle = retangle - ((int)(retangle/(2*PI_CONST)))*2*PI_CONST; 00464 00465 //get to the range 0, 2PI 00466 if(retangle < 0) 00467 retangle += 2*PI_CONST; 00468 00469 if(retangle < 0 || retangle > 2*PI_CONST) 00470 { 00471 SBPL_ERROR("ERROR: after normalization of angle=%f we get angle=%f\n", angle, retangle); 00472 } 00473 00474 return retangle; 00475 } 00476 00477 00478 00479 /* 00480 * point - the point to test 00481 * 00482 * Function derived from http://ozviz.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/ 00483 */ 00484 bool IsInsideFootprint(sbpl_2Dpt_t pt, vector<sbpl_2Dpt_t>* bounding_polygon){ 00485 00486 int counter = 0; 00487 int i; 00488 double xinters; 00489 sbpl_2Dpt_t p1; 00490 sbpl_2Dpt_t p2; 00491 int N = bounding_polygon->size(); 00492 00493 p1 = bounding_polygon->at(0); 00494 for (i=1;i<=N;i++) { 00495 p2 = bounding_polygon->at(i % N); 00496 if (pt.y > __min(p1.y,p2.y)) { 00497 if (pt.y <= __max(p1.y,p2.y)) { 00498 if (pt.x <= __max(p1.x,p2.x)) { 00499 if (p1.y != p2.y) { 00500 xinters = (pt.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x; 00501 if (p1.x == p2.x || pt.x <= xinters) 00502 counter++; 00503 } 00504 } 00505 } 00506 } 00507 p1 = p2; 00508 } 00509 00510 if (counter % 2 == 0) 00511 return false; 00512 else 00513 return true; 00514 #if DEBUG 00515 //SBPL_PRINTF("Returning from inside footprint: %d\n", c); 00516 #endif 00517 // return c; 00518 00519 } 00520 00521 00522 double computeMinUnsignedAngleDiff(double angle1, double angle2) 00523 { 00524 //get the angles into 0-2*PI range 00525 angle1 = normalizeAngle(angle1); 00526 angle2 = normalizeAngle(angle2); 00527 00528 double anglediff = fabs(angle1-angle2); 00529 00530 //see if we can take a shorter route 00531 if(anglediff > PI_CONST){ 00532 anglediff = fabs(anglediff - 2*PI_CONST); 00533 } 00534 00535 return anglediff; 00536 } 00537 00538 00539 //computes 8-connected distances to obstacles and non-free areas in two linear passes and returns them in disttoObs_incells 00540 //and disttoNonfree_incells arrays. The distances are in terms of the number of cells but are floats. These distances 00541 //can then be converted into the actual distances using the actual discretization values 00542 //areas outside of the map are considered to be obstacles 00543 void computeDistancestoNonfreeAreas(unsigned char** Grid2D, int width_x, int height_y, unsigned char obsthresh, float** disttoObs_incells, 00544 float** disttoNonfree_incells) 00545 { 00546 int x,y,nbrx,nbry; 00547 float mindisttoObs, mindisttoNonfree; 00548 float maxDist = (float)(__min(width_x, height_y)); 00549 float disttoObs, disttoNonfree; 00550 int dir; 00551 const int NUMOF2DQUASIDIRS = 4; 00552 00553 // for quasi-Euclidean distance transform 00554 // going left-to-right, top-to-bottom 00555 int dxdownlefttoright_[NUMOF2DQUASIDIRS]; 00556 int dydownlefttoright_[NUMOF2DQUASIDIRS]; 00557 int dxdownrighttoleft_[NUMOF2DQUASIDIRS]; 00558 int dydownrighttoleft_[NUMOF2DQUASIDIRS]; 00559 00560 // going right-to-left, bottom-to-top 00561 int dxuprighttoleft_[NUMOF2DQUASIDIRS]; 00562 int dyuprighttoleft_[NUMOF2DQUASIDIRS]; 00563 int dxuplefttoright_[NUMOF2DQUASIDIRS]; 00564 int dyuplefttoright_[NUMOF2DQUASIDIRS]; 00565 00566 // distances to the above nbrs 00567 float distdownlefttoright_[NUMOF2DQUASIDIRS]; 00568 float distdownrighttoleft_[NUMOF2DQUASIDIRS]; 00569 float distuprighttoleft_[NUMOF2DQUASIDIRS]; 00570 float distuplefttoright_[NUMOF2DQUASIDIRS]; 00571 00572 // and for distance transform: 00573 // increasing x (outer) 00574 // increasing y (inner) 00575 // [2] 00576 // [1][s] 00577 // [0][3] 00578 dxdownlefttoright_[0] = -1; dydownlefttoright_[0] = -1; 00579 dxdownlefttoright_[1] = -1; dydownlefttoright_[1] = 0; 00580 dxdownlefttoright_[2] = -1; dydownlefttoright_[2] = 1; 00581 dxdownlefttoright_[3] = 0; dydownlefttoright_[3] = -1; 00582 00583 // increasing x (outer) 00584 // decreasing y (inner) 00585 // [2][3] 00586 // [1][s] 00587 // [0] 00588 dxdownrighttoleft_[0] = -1; dydownrighttoleft_[0] = -1; 00589 dxdownrighttoleft_[1] = -1; dydownrighttoleft_[1] = 0; 00590 dxdownrighttoleft_[2] = -1; dydownrighttoleft_[2] = 1; 00591 dxdownrighttoleft_[3] = 0; dydownrighttoleft_[3] = 1; 00592 00593 // decreasing x (outer) 00594 // decreasing y (inner) 00595 // [3][2] 00596 // [s][1] 00597 // [0] 00598 dxuprighttoleft_[0] = 1; dyuprighttoleft_[0] = -1; 00599 dxuprighttoleft_[1] = 1; dyuprighttoleft_[1] = 0; 00600 dxuprighttoleft_[2] = 1; dyuprighttoleft_[2] = 1; 00601 dxuprighttoleft_[3] = 0; dyuprighttoleft_[3] = 1; 00602 00603 // decreasing x (outer) 00604 // increasing y (inner) 00605 // [2] 00606 // [s][1] 00607 // [3][0] 00608 dxuplefttoright_[0] = 1; dyuplefttoright_[0] = -1; 00609 dxuplefttoright_[1] = 1; dyuplefttoright_[1] = 0; 00610 dxuplefttoright_[2] = 1; dyuplefttoright_[2] = 1; 00611 dxuplefttoright_[3] = 0; dyuplefttoright_[3] = -1; 00612 00613 // insert the corresponding distances 00614 distdownlefttoright_[0] = (float)1.414; 00615 distdownlefttoright_[1] = (float)1.0; 00616 distdownlefttoright_[2] = (float)1.414; 00617 distdownlefttoright_[3] = (float)1.0; 00618 00619 distdownrighttoleft_[0] = (float)1.414; 00620 distdownrighttoleft_[1] = (float)1.0; 00621 distdownrighttoleft_[2] = (float)1.414; 00622 distdownrighttoleft_[3] = (float)1.0; 00623 00624 distuprighttoleft_[0] = (float)1.414; 00625 distuprighttoleft_[1] = (float)1.0; 00626 distuprighttoleft_[2] = (float)1.414; 00627 distuprighttoleft_[3] = (float)1.0; 00628 00629 distuplefttoright_[0] = (float)1.414; 00630 distuplefttoright_[1] = (float)1.0; 00631 distuplefttoright_[2] = (float)1.414; 00632 distuplefttoright_[3] = (float)1.0; 00633 00634 00635 // step through the map from top to bottom, 00636 // alternating left-to-right then right-to-left 00637 // This order maintains the invariant that the min distance for each 00638 // cell to all previously-visited obstacles is accurate 00639 for(x = 0; x < width_x; x++) 00640 { 00641 // move from left to right 00642 if (x%2 == 0) { 00643 00644 for(y = 0; y < height_y; y++) 00645 { 00646 00647 mindisttoObs = maxDist; // initialize to max distance 00648 mindisttoNonfree = maxDist; 00649 00650 // if cell is an obstacle, set disttoObs to 0 and continue 00651 if (Grid2D[x][y] >= obsthresh){ 00652 disttoObs_incells[x][y] = 0; 00653 disttoNonfree_incells[x][y] = 0; 00654 continue; 00655 } 00656 00657 if(Grid2D[x][y] > 0){ 00658 mindisttoNonfree = 0; 00659 } 00660 00661 //iterate over predecessors 00662 for(dir = 0; dir < NUMOF2DQUASIDIRS; dir++){ 00663 nbrx = x + dxdownlefttoright_[dir]; 00664 nbry = y + dydownlefttoright_[dir]; 00665 00666 //make sure it is inside the map and has no obstacle 00667 // compute min cost to an obstacle for each cell, using 00668 // *just* the cells already computed this pass for checking distance 00669 if(nbrx < 0 || nbrx >= width_x || nbry < 0 || nbry >= height_y){ 00670 disttoObs = distdownlefttoright_[dir]; 00671 disttoNonfree = disttoObs; 00672 } 00673 else 00674 { 00675 disttoObs = distdownlefttoright_[dir] + disttoObs_incells[nbrx][nbry]; 00676 disttoNonfree = distdownlefttoright_[dir] + disttoNonfree_incells[nbrx][nbry]; 00677 } 00678 00679 if (disttoObs < mindisttoObs) 00680 mindisttoObs = disttoObs; 00681 if (disttoNonfree < mindisttoNonfree) 00682 mindisttoNonfree = disttoNonfree; 00683 }//over preds 00684 00685 disttoObs_incells[x][y] = mindisttoObs; 00686 disttoNonfree_incells[x][y] = mindisttoNonfree; 00687 } 00688 00689 } else { 00690 00691 // move from right to left 00692 for(y = height_y-1; y >= 0; y--) 00693 { 00694 00695 mindisttoObs = maxDist; // initialize to max distance 00696 mindisttoNonfree = maxDist; 00697 00698 // if cell is an obstacle, set disttoObs to 0 and continue 00699 if (Grid2D[x][y] >= obsthresh){ 00700 disttoObs_incells[x][y] = 0; 00701 disttoNonfree_incells[x][y] = 0; 00702 continue; 00703 } 00704 00705 if(Grid2D[x][y] > 0){ 00706 mindisttoNonfree = 0; 00707 } 00708 00709 00710 //iterate over predecessors 00711 for(dir = 0; dir < NUMOF2DQUASIDIRS; dir++) 00712 { 00713 nbrx = x + dxdownrighttoleft_[dir]; 00714 nbry = y + dydownrighttoleft_[dir]; 00715 00716 //make sure it is inside the map and has no obstacle 00717 // compute min cost to an obstacle for each cell, using 00718 // *just* the cells already computed this pass for checking distance 00719 if(nbrx < 0 || nbrx >= width_x || nbry < 0 || nbry >= height_y){ 00720 disttoObs = distdownrighttoleft_[dir]; 00721 disttoNonfree = disttoObs; 00722 } else { 00723 disttoObs = distdownrighttoleft_[dir] + disttoObs_incells[nbrx][nbry]; 00724 disttoNonfree = distdownrighttoleft_[dir] + disttoNonfree_incells[nbrx][nbry]; 00725 } 00726 00727 if (disttoObs < mindisttoObs) 00728 mindisttoObs = disttoObs; 00729 if (disttoNonfree < mindisttoNonfree) 00730 mindisttoNonfree = disttoNonfree; 00731 } 00732 00733 disttoObs_incells[x][y] = mindisttoObs; 00734 disttoNonfree_incells[x][y] = mindisttoNonfree; 00735 } 00736 //SBPL_PRINTF("x=%d\n", x); 00737 } 00738 } 00739 00740 // step through the map from bottom to top 00741 for(x = width_x-1; x >= 0; x--) 00742 { 00743 00744 // move from right to left 00745 if (x%2 == 0) { 00746 00747 for(y = height_y-1; y >= 0; y--) 00748 { 00749 00750 // initialize to current distance 00751 mindisttoObs = disttoObs_incells[x][y]; 00752 mindisttoNonfree = disttoNonfree_incells[x][y]; 00753 00754 //iterate over predecessors 00755 for(dir = 0; dir < NUMOF2DQUASIDIRS; dir++) 00756 { 00757 nbrx = x + dxuprighttoleft_[dir]; 00758 nbry = y + dyuprighttoleft_[dir]; 00759 00760 //make sure it is inside the map and has no obstacle 00761 // compute min cost to an obstacle for each cell, using 00762 // *just* the cells already computed this pass for checking distance 00763 if(nbrx < 0 || nbrx >= width_x || nbry < 0 || nbry >= height_y){ 00764 disttoObs = distuprighttoleft_[dir]; 00765 disttoNonfree = disttoObs; 00766 } else { 00767 disttoObs = distuprighttoleft_[dir] + disttoObs_incells[nbrx][nbry]; 00768 disttoNonfree = distuprighttoleft_[dir] + disttoNonfree_incells[nbrx][nbry]; 00769 } 00770 00771 if (disttoObs < mindisttoObs) 00772 mindisttoObs = disttoObs; 00773 if (disttoNonfree < mindisttoNonfree) 00774 mindisttoNonfree = disttoNonfree; 00775 }//over preds 00776 00777 disttoObs_incells[x][y] = mindisttoObs; 00778 disttoNonfree_incells[x][y] = mindisttoNonfree; 00779 }//for y 00780 } else { 00781 00782 // move from left to right 00783 for(y = 0; y< height_y; y++) 00784 { 00785 // initialize to current distance 00786 mindisttoObs = disttoObs_incells[x][y]; 00787 mindisttoNonfree = disttoNonfree_incells[x][y]; 00788 00789 //iterate over predecessors 00790 for(dir = 0; dir < NUMOF2DQUASIDIRS; dir++) 00791 { 00792 nbrx = x + dxuplefttoright_[dir]; 00793 nbry = y + dyuplefttoright_[dir]; 00794 00795 //make sure it is inside the map and has no obstacle 00796 // compute min cost to an obstacle for each cell, using 00797 // *just* the cells already computed this pass for checking distance 00798 if(nbrx < 0 || nbrx >= width_x || nbry < 0 || nbry >= height_y){ 00799 disttoObs = distuplefttoright_[dir]; 00800 disttoNonfree = disttoObs; 00801 } else { 00802 disttoObs = distuplefttoright_[dir] + disttoObs_incells[nbrx][nbry]; 00803 disttoNonfree = distuplefttoright_[dir] + disttoNonfree_incells[nbrx][nbry]; 00804 } 00805 00806 if (disttoObs < mindisttoObs) 00807 mindisttoObs = disttoObs; 00808 if (disttoNonfree < mindisttoNonfree) 00809 mindisttoNonfree = disttoNonfree; 00810 } 00811 00812 disttoObs_incells[x][y] = mindisttoObs; 00813 disttoNonfree_incells[x][y] = mindisttoNonfree; 00814 }//over y 00815 }//direction 00816 }//over x 00817 }