00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include <navfn/navfn.h>
00047 #include <ros/console.h>
00048
00049 namespace navfn {
00050
00051
00052
00053
00054
00055
00056
00057 int
00058 create_nav_plan_astar(COSTTYPE *costmap, int nx, int ny,
00059 int* goal, int* start,
00060 float *plan, int nplan)
00061 {
00062 static NavFn *nav = NULL;
00063
00064 if (nav == NULL)
00065 nav = new NavFn(nx,ny);
00066
00067 if (nav->nx != nx || nav->ny != ny)
00068 {
00069 delete nav;
00070 nav = new NavFn(nx,ny);
00071 }
00072
00073 nav->setGoal(goal);
00074 nav->setStart(start);
00075
00076 nav->costarr = costmap;
00077 nav->setupNavFn(true);
00078
00079
00080 nav->priInc = 2*COST_NEUTRAL;
00081 nav->propNavFnAstar(std::max(nx*ny/20,nx+ny));
00082
00083
00084 int len = nav->calcPath(nplan);
00085
00086 if (len > 0)
00087 ROS_DEBUG("[NavFn] Path found, %d steps\n", len);
00088 else
00089 ROS_DEBUG("[NavFn] No path found\n");
00090
00091 if (len > 0)
00092 {
00093 for (int i=0; i<len; i++)
00094 {
00095 plan[i*2] = nav->pathx[i];
00096 plan[i*2+1] = nav->pathy[i];
00097 }
00098 }
00099
00100 return len;
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110 NavFn::NavFn(int xs, int ys)
00111 {
00112
00113 costarr = NULL;
00114 potarr = NULL;
00115 pending = NULL;
00116 gradx = grady = NULL;
00117 setNavArr(xs,ys);
00118
00119
00120 pb1 = new int[PRIORITYBUFSIZE];
00121 pb2 = new int[PRIORITYBUFSIZE];
00122 pb3 = new int[PRIORITYBUFSIZE];
00123
00124
00125
00126 priInc = 2*COST_NEUTRAL;
00127
00128
00129 goal[0] = goal[1] = 0;
00130 start[0] = start[1] = 0;
00131
00132
00133 displayFn = NULL;
00134 displayInt = 0;
00135
00136
00137 npathbuf = npath = 0;
00138 pathx = pathy = NULL;
00139 pathStep = 0.5;
00140 }
00141
00142
00143 NavFn::~NavFn()
00144 {
00145 if(costarr)
00146 delete[] costarr;
00147 if(potarr)
00148 delete[] potarr;
00149 if(pending)
00150 delete[] pending;
00151 if(gradx)
00152 delete[] gradx;
00153 if(grady)
00154 delete[] grady;
00155 if(pathx)
00156 delete[] pathx;
00157 if(pathy)
00158 delete[] pathy;
00159 if(pb1)
00160 delete[] pb1;
00161 if(pb2)
00162 delete[] pb2;
00163 if(pb3)
00164 delete[] pb3;
00165 }
00166
00167
00168
00169
00170
00171
00172 void
00173 NavFn::setGoal(int *g)
00174 {
00175 goal[0] = g[0];
00176 goal[1] = g[1];
00177 ROS_DEBUG("[NavFn] Setting goal to %d,%d\n", goal[0], goal[1]);
00178 }
00179
00180 void
00181 NavFn::setStart(int *g)
00182 {
00183 start[0] = g[0];
00184 start[1] = g[1];
00185 ROS_DEBUG("[NavFn] Setting start to %d,%d\n", start[0], start[1]);
00186 }
00187
00188
00189
00190
00191
00192 void
00193 NavFn::setNavArr(int xs, int ys)
00194 {
00195 ROS_DEBUG("[NavFn] Array is %d x %d\n", xs, ys);
00196
00197 nx = xs;
00198 ny = ys;
00199 ns = nx*ny;
00200
00201 if(costarr)
00202 delete[] costarr;
00203 if(potarr)
00204 delete[] potarr;
00205 if(pending)
00206 delete[] pending;
00207
00208 if(gradx)
00209 delete[] gradx;
00210 if(grady)
00211 delete[] grady;
00212
00213 costarr = new COSTTYPE[ns];
00214 memset(costarr, 0, ns*sizeof(COSTTYPE));
00215 potarr = new float[ns];
00216 pending = new bool[ns];
00217 memset(pending, 0, ns*sizeof(bool));
00218 gradx = new float[ns];
00219 grady = new float[ns];
00220 }
00221
00222
00223
00224
00225
00226
00227 void
00228 NavFn::setCostmap(const COSTTYPE *cmap, bool isROS, bool allow_unknown)
00229 {
00230 COSTTYPE *cm = costarr;
00231 if (isROS)
00232 {
00233 for (int i=0; i<ny; i++)
00234 {
00235 int k=i*nx;
00236 for (int j=0; j<nx; j++, k++, cmap++, cm++)
00237 {
00238
00239
00240
00241
00242 *cm = COST_OBS;
00243 int v = *cmap;
00244 if (v < COST_OBS_ROS)
00245 {
00246 v = COST_NEUTRAL+COST_FACTOR*v;
00247 if (v >= COST_OBS)
00248 v = COST_OBS-1;
00249 *cm = v;
00250 }
00251 else if(v == COST_UNKNOWN_ROS && allow_unknown)
00252 {
00253 v = COST_OBS-1;
00254 *cm = v;
00255 }
00256 }
00257 }
00258 }
00259
00260 else
00261 {
00262 for (int i=0; i<ny; i++)
00263 {
00264 int k=i*nx;
00265 for (int j=0; j<nx; j++, k++, cmap++, cm++)
00266 {
00267 *cm = COST_OBS;
00268 if (i<7 || i > ny-8 || j<7 || j > nx-8)
00269 continue;
00270 int v = *cmap;
00271 if (v < COST_OBS_ROS)
00272 {
00273 v = COST_NEUTRAL+COST_FACTOR*v;
00274 if (v >= COST_OBS)
00275 v = COST_OBS-1;
00276 *cm = v;
00277 }
00278 else if(v == COST_UNKNOWN_ROS)
00279 {
00280 v = COST_OBS-1;
00281 *cm = v;
00282 }
00283 }
00284 }
00285
00286 }
00287 }
00288
00289 bool
00290 NavFn::calcNavFnDijkstra(bool atStart)
00291 {
00292 #if 0
00293 static char costmap_filename[1000];
00294 static int file_number = 0;
00295 snprintf( costmap_filename, 1000, "navfn-dijkstra-costmap-%04d", file_number++ );
00296 savemap( costmap_filename );
00297 #endif
00298 setupNavFn(true);
00299
00300
00301 propNavFnDijkstra(std::max(nx*ny/20,nx+ny),atStart);
00302
00303
00304 int len = calcPath(nx*ny/2);
00305
00306 if (len > 0)
00307 {
00308 ROS_DEBUG("[NavFn] Path found, %d steps\n", len);
00309 return true;
00310 }
00311 else
00312 {
00313 ROS_DEBUG("[NavFn] No path found\n");
00314 return false;
00315 }
00316
00317 }
00318
00319
00320
00321
00322
00323
00324 bool
00325 NavFn::calcNavFnAstar()
00326 {
00327 setupNavFn(true);
00328
00329
00330 propNavFnAstar(std::max(nx*ny/20,nx+ny));
00331
00332
00333 int len = calcPath(nx*4);
00334
00335 if (len > 0)
00336 {
00337 ROS_DEBUG("[NavFn] Path found, %d steps\n", len);
00338 return true;
00339 }
00340 else
00341 {
00342 ROS_DEBUG("[NavFn] No path found\n");
00343 return false;
00344 }
00345 }
00346
00347
00348
00349
00350
00351
00352 float *NavFn::getPathX() { return pathx; }
00353 float *NavFn::getPathY() { return pathy; }
00354 int NavFn::getPathLen() { return npath; }
00355
00356
00357
00358
00359
00360
00361 void
00362 NavFn::setObs()
00363 {
00364 #if 0
00365
00366 ROS_INFO("[NavFn] Setting simple obstacle\n");
00367 int xx = nx/3;
00368 for (int i=ny/3; i<ny; i++)
00369 costarr[i*nx + xx] = COST_OBS;
00370 xx = 2*nx/3;
00371 for (int i=ny/3; i<ny; i++)
00372 costarr[i*nx + xx] = COST_OBS;
00373
00374 xx = nx/4;
00375 for (int i=20; i<ny-ny/3; i++)
00376 costarr[i*nx + xx] = COST_OBS;
00377 xx = nx/2;
00378 for (int i=20; i<ny-ny/3; i++)
00379 costarr[i*nx + xx] = COST_OBS;
00380 xx = 3*nx/4;
00381 for (int i=20; i<ny-ny/3; i++)
00382 costarr[i*nx + xx] = COST_OBS;
00383 #endif
00384 }
00385
00386
00387
00388 #define push_cur(n) { if (n>=0 && n<ns && !pending[n] && \
00389 costarr[n]<COST_OBS && curPe<PRIORITYBUFSIZE) \
00390 { curP[curPe++]=n; pending[n]=true; }}
00391 #define push_next(n) { if (n>=0 && n<ns && !pending[n] && \
00392 costarr[n]<COST_OBS && nextPe<PRIORITYBUFSIZE) \
00393 { nextP[nextPe++]=n; pending[n]=true; }}
00394 #define push_over(n) { if (n>=0 && n<ns && !pending[n] && \
00395 costarr[n]<COST_OBS && overPe<PRIORITYBUFSIZE) \
00396 { overP[overPe++]=n; pending[n]=true; }}
00397
00398
00399
00400
00401 void
00402 NavFn::setupNavFn(bool keepit)
00403 {
00404
00405 for (int i=0; i<ns; i++)
00406 {
00407 potarr[i] = POT_HIGH;
00408 if (!keepit) costarr[i] = COST_NEUTRAL;
00409 gradx[i] = grady[i] = 0.0;
00410 }
00411
00412
00413 COSTTYPE *pc;
00414 pc = costarr;
00415 for (int i=0; i<nx; i++)
00416 *pc++ = COST_OBS;
00417 pc = costarr + (ny-1)*nx;
00418 for (int i=0; i<nx; i++)
00419 *pc++ = COST_OBS;
00420 pc = costarr;
00421 for (int i=0; i<ny; i++, pc+=nx)
00422 *pc = COST_OBS;
00423 pc = costarr + nx - 1;
00424 for (int i=0; i<ny; i++, pc+=nx)
00425 *pc = COST_OBS;
00426
00427
00428 curT = COST_OBS;
00429 curP = pb1;
00430 curPe = 0;
00431 nextP = pb2;
00432 nextPe = 0;
00433 overP = pb3;
00434 overPe = 0;
00435 memset(pending, 0, ns*sizeof(bool));
00436
00437
00438 int k = goal[0] + goal[1]*nx;
00439 initCost(k,0);
00440
00441
00442 pc = costarr;
00443 int ntot = 0;
00444 for (int i=0; i<ns; i++, pc++)
00445 {
00446 if (*pc >= COST_OBS)
00447 ntot++;
00448 }
00449 nobs = ntot;
00450 }
00451
00452
00453
00454
00455 void
00456 NavFn::initCost(int k, float v)
00457 {
00458 potarr[k] = v;
00459 push_cur(k+1);
00460 push_cur(k-1);
00461 push_cur(k-nx);
00462 push_cur(k+nx);
00463 }
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 #define INVSQRT2 0.707106781
00475
00476 inline void
00477 NavFn::updateCell(int n)
00478 {
00479
00480 float u,d,l,r;
00481 l = potarr[n-1];
00482 r = potarr[n+1];
00483 u = potarr[n-nx];
00484 d = potarr[n+nx];
00485
00486
00487
00488
00489
00490 float ta, tc;
00491 if (l<r) tc=l; else tc=r;
00492 if (u<d) ta=u; else ta=d;
00493
00494
00495 if (costarr[n] < COST_OBS)
00496 {
00497 float hf = (float)costarr[n];
00498 float dc = tc-ta;
00499 if (dc < 0)
00500 {
00501 dc = -dc;
00502 ta = tc;
00503 }
00504
00505
00506 float pot;
00507 if (dc >= hf)
00508 pot = ta+hf;
00509 else
00510 {
00511
00512
00513
00514 float d = dc/hf;
00515 float v = -0.2301*d*d + 0.5307*d + 0.7040;
00516 pot = ta + hf*v;
00517 }
00518
00519
00520
00521
00522 if (pot < potarr[n])
00523 {
00524 float le = INVSQRT2*(float)costarr[n-1];
00525 float re = INVSQRT2*(float)costarr[n+1];
00526 float ue = INVSQRT2*(float)costarr[n-nx];
00527 float de = INVSQRT2*(float)costarr[n+nx];
00528 potarr[n] = pot;
00529 if (pot < curT)
00530 {
00531 if (l > pot+le) push_next(n-1);
00532 if (r > pot+re) push_next(n+1);
00533 if (u > pot+ue) push_next(n-nx);
00534 if (d > pot+de) push_next(n+nx);
00535 }
00536 else
00537 {
00538 if (l > pot+le) push_over(n-1);
00539 if (r > pot+re) push_over(n+1);
00540 if (u > pot+ue) push_over(n-nx);
00541 if (d > pot+de) push_over(n+nx);
00542 }
00543 }
00544
00545 }
00546
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 #define INVSQRT2 0.707106781
00560
00561 inline void
00562 NavFn::updateCellAstar(int n)
00563 {
00564
00565 float u,d,l,r;
00566 l = potarr[n-1];
00567 r = potarr[n+1];
00568 u = potarr[n-nx];
00569 d = potarr[n+nx];
00570
00571
00572
00573
00574
00575 float ta, tc;
00576 if (l<r) tc=l; else tc=r;
00577 if (u<d) ta=u; else ta=d;
00578
00579
00580 if (costarr[n] < COST_OBS)
00581 {
00582 float hf = (float)costarr[n];
00583 float dc = tc-ta;
00584 if (dc < 0)
00585 {
00586 dc = -dc;
00587 ta = tc;
00588 }
00589
00590
00591 float pot;
00592 if (dc >= hf)
00593 pot = ta+hf;
00594 else
00595 {
00596
00597
00598
00599 float d = dc/hf;
00600 float v = -0.2301*d*d + 0.5307*d + 0.7040;
00601 pot = ta + hf*v;
00602 }
00603
00604
00605
00606
00607 if (pot < potarr[n])
00608 {
00609 float le = INVSQRT2*(float)costarr[n-1];
00610 float re = INVSQRT2*(float)costarr[n+1];
00611 float ue = INVSQRT2*(float)costarr[n-nx];
00612 float de = INVSQRT2*(float)costarr[n+nx];
00613
00614
00615 int x = n%nx;
00616 int y = n/nx;
00617 float dist = hypot(x-start[0], y-start[1])*(float)COST_NEUTRAL;
00618
00619 potarr[n] = pot;
00620 pot += dist;
00621 if (pot < curT)
00622 {
00623 if (l > pot+le) push_next(n-1);
00624 if (r > pot+re) push_next(n+1);
00625 if (u > pot+ue) push_next(n-nx);
00626 if (d > pot+de) push_next(n+nx);
00627 }
00628 else
00629 {
00630 if (l > pot+le) push_over(n-1);
00631 if (r > pot+re) push_over(n+1);
00632 if (u > pot+ue) push_over(n-nx);
00633 if (d > pot+de) push_over(n+nx);
00634 }
00635 }
00636
00637 }
00638
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 bool
00652 NavFn::propNavFnDijkstra(int cycles, bool atStart)
00653 {
00654 int nwv = 0;
00655 int nc = 0;
00656 int cycle = 0;
00657
00658
00659 int startCell = start[1]*nx + start[0];
00660
00661 for (; cycle < cycles; cycle++)
00662 {
00663
00664 if (curPe == 0 && nextPe == 0)
00665 break;
00666
00667
00668 nc += curPe;
00669 if (curPe > nwv)
00670 nwv = curPe;
00671
00672
00673 int *pb = curP;
00674 int i = curPe;
00675 while (i-- > 0)
00676 pending[*(pb++)] = false;
00677
00678
00679 pb = curP;
00680 i = curPe;
00681 while (i-- > 0)
00682 updateCell(*pb++);
00683
00684 if (displayInt > 0 && (cycle % displayInt) == 0)
00685 displayFn(this);
00686
00687
00688 curPe = nextPe;
00689 nextPe = 0;
00690 pb = curP;
00691 curP = nextP;
00692 nextP = pb;
00693
00694
00695 if (curPe == 0)
00696 {
00697 curT += priInc;
00698 curPe = overPe;
00699 overPe = 0;
00700 pb = curP;
00701 curP = overP;
00702 overP = pb;
00703 }
00704
00705
00706 if (atStart)
00707 if (potarr[startCell] < POT_HIGH)
00708 break;
00709 }
00710
00711 ROS_DEBUG("[NavFn] Used %d cycles, %d cells visited (%d%%), priority buf max %d\n",
00712 cycle,nc,(int)((nc*100.0)/(ns-nobs)),nwv);
00713
00714 if (cycle < cycles) return true;
00715 else return false;
00716 }
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 bool
00729 NavFn::propNavFnAstar(int cycles)
00730 {
00731 int nwv = 0;
00732 int nc = 0;
00733 int cycle = 0;
00734
00735
00736 float dist = hypot(goal[0]-start[0], goal[1]-start[1])*(float)COST_NEUTRAL;
00737 curT = dist + curT;
00738
00739
00740 int startCell = start[1]*nx + start[0];
00741
00742
00743 for (; cycle < cycles; cycle++)
00744 {
00745
00746 if (curPe == 0 && nextPe == 0)
00747 break;
00748
00749
00750 nc += curPe;
00751 if (curPe > nwv)
00752 nwv = curPe;
00753
00754
00755 int *pb = curP;
00756 int i = curPe;
00757 while (i-- > 0)
00758 pending[*(pb++)] = false;
00759
00760
00761 pb = curP;
00762 i = curPe;
00763 while (i-- > 0)
00764 updateCellAstar(*pb++);
00765
00766 if (displayInt > 0 && (cycle % displayInt) == 0)
00767 displayFn(this);
00768
00769
00770 curPe = nextPe;
00771 nextPe = 0;
00772 pb = curP;
00773 curP = nextP;
00774 nextP = pb;
00775
00776
00777 if (curPe == 0)
00778 {
00779 curT += priInc;
00780 curPe = overPe;
00781 overPe = 0;
00782 pb = curP;
00783 curP = overP;
00784 overP = pb;
00785 }
00786
00787
00788 if (potarr[startCell] < POT_HIGH)
00789 break;
00790
00791 }
00792
00793 last_path_cost_ = potarr[startCell];
00794
00795 ROS_DEBUG("[NavFn] Used %d cycles, %d cells visited (%d%%), priority buf max %d\n",
00796 cycle,nc,(int)((nc*100.0)/(ns-nobs)),nwv);
00797
00798
00799 if (potarr[startCell] < POT_HIGH) return true;
00800 else return false;
00801 }
00802
00803
00804 float NavFn::getLastPathCost()
00805 {
00806 return last_path_cost_;
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 int
00822 NavFn::calcPath(int n, int *st)
00823 {
00824
00825
00826
00827
00828 if (npathbuf < n)
00829 {
00830 if (pathx) delete [] pathx;
00831 if (pathy) delete [] pathy;
00832 pathx = new float[n];
00833 pathy = new float[n];
00834 npathbuf = n;
00835 }
00836
00837
00838
00839 if (st == NULL) st = start;
00840 int stc = st[1]*nx + st[0];
00841
00842
00843 float dx=0;
00844 float dy=0;
00845 npath = 0;
00846
00847
00848 for (int i=0; i<n; i++)
00849 {
00850
00851 int nearest_point=std::max(0,std::min(nx*ny-1,stc+(int)round(dx)+(int)(nx*round(dy))));
00852 if (potarr[nearest_point] < COST_NEUTRAL)
00853 {
00854 pathx[npath] = (float)goal[0];
00855 pathy[npath] = (float)goal[1];
00856 return ++npath;
00857 }
00858
00859 if (stc < nx || stc > ns-nx)
00860 {
00861 ROS_DEBUG("[PathCalc] Out of bounds");
00862 return 0;
00863 }
00864
00865
00866 pathx[npath] = stc%nx + dx;
00867 pathy[npath] = stc/nx + dy;
00868 npath++;
00869
00870 bool oscillation_detected = false;
00871 if( npath > 2 &&
00872 pathx[npath-1] == pathx[npath-3] &&
00873 pathy[npath-1] == pathy[npath-3] )
00874 {
00875 ROS_DEBUG("[PathCalc] oscillation detected, attempting fix.");
00876 oscillation_detected = true;
00877 }
00878
00879 int stcnx = stc+nx;
00880 int stcpx = stc-nx;
00881
00882
00883 if (potarr[stc] >= POT_HIGH ||
00884 potarr[stc+1] >= POT_HIGH ||
00885 potarr[stc-1] >= POT_HIGH ||
00886 potarr[stcnx] >= POT_HIGH ||
00887 potarr[stcnx+1] >= POT_HIGH ||
00888 potarr[stcnx-1] >= POT_HIGH ||
00889 potarr[stcpx] >= POT_HIGH ||
00890 potarr[stcpx+1] >= POT_HIGH ||
00891 potarr[stcpx-1] >= POT_HIGH ||
00892 oscillation_detected)
00893 {
00894 ROS_DEBUG("[Path] Pot fn boundary, following grid (%0.1f/%d)", potarr[stc], npath);
00895
00896 int minc = stc;
00897 int minp = potarr[stc];
00898 int st = stcpx - 1;
00899 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
00900 st++;
00901 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
00902 st++;
00903 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
00904 st = stc-1;
00905 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
00906 st = stc+1;
00907 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
00908 st = stcnx-1;
00909 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
00910 st++;
00911 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
00912 st++;
00913 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
00914 stc = minc;
00915 dx = 0;
00916 dy = 0;
00917
00918 ROS_DEBUG("[Path] Pot: %0.1f pos: %0.1f,%0.1f",
00919 potarr[stc], pathx[npath-1], pathy[npath-1]);
00920
00921 if (potarr[stc] >= POT_HIGH)
00922 {
00923 ROS_DEBUG("[PathCalc] No path found, high potential");
00924
00925 return 0;
00926 }
00927 }
00928
00929
00930 else
00931 {
00932
00933
00934 gradCell(stc);
00935 gradCell(stc+1);
00936 gradCell(stcnx);
00937 gradCell(stcnx+1);
00938
00939
00940
00941 float x1 = (1.0-dx)*gradx[stc] + dx*gradx[stc+1];
00942 float x2 = (1.0-dx)*gradx[stcnx] + dx*gradx[stcnx+1];
00943 float x = (1.0-dy)*x1 + dy*x2;
00944 float y1 = (1.0-dx)*grady[stc] + dx*grady[stc+1];
00945 float y2 = (1.0-dx)*grady[stcnx] + dx*grady[stcnx+1];
00946 float y = (1.0-dy)*y1 + dy*y2;
00947
00948
00949 ROS_DEBUG("[Path] %0.2f,%0.2f %0.2f,%0.2f %0.2f,%0.2f %0.2f,%0.2f; final x=%.3f, y=%.3f\n",
00950 gradx[stc], grady[stc], gradx[stc+1], grady[stc+1],
00951 gradx[stcnx], grady[stcnx], gradx[stcnx+1], grady[stcnx+1],
00952 x, y);
00953
00954
00955 if (x == 0.0 && y == 0.0)
00956 {
00957 ROS_DEBUG("[PathCalc] Zero gradient");
00958 return 0;
00959 }
00960
00961
00962 float ss = pathStep/hypot(x, y);
00963 dx += x*ss;
00964 dy += y*ss;
00965
00966
00967 if (dx > 1.0) { stc++; dx -= 1.0; }
00968 if (dx < -1.0) { stc--; dx += 1.0; }
00969 if (dy > 1.0) { stc+=nx; dy -= 1.0; }
00970 if (dy < -1.0) { stc-=nx; dy += 1.0; }
00971
00972 }
00973
00974
00975
00976 }
00977
00978
00979 ROS_DEBUG("[PathCalc] No path found, path too long");
00980
00981 return 0;
00982 }
00983
00984
00985
00986
00987
00988
00989
00990
00991 float
00992 NavFn::gradCell(int n)
00993 {
00994 if (gradx[n]+grady[n] > 0.0)
00995 return 1.0;
00996
00997 if (n < nx || n > ns-nx)
00998 return 0.0;
00999
01000 float cv = potarr[n];
01001 float dx = 0.0;
01002 float dy = 0.0;
01003
01004
01005 if (cv >= POT_HIGH)
01006 {
01007 if (potarr[n-1] < POT_HIGH)
01008 dx = -COST_OBS;
01009 else if (potarr[n+1] < POT_HIGH)
01010 dx = COST_OBS;
01011
01012 if (potarr[n-nx] < POT_HIGH)
01013 dy = -COST_OBS;
01014 else if (potarr[nx+1] < POT_HIGH)
01015 dy = COST_OBS;
01016 }
01017
01018 else
01019 {
01020
01021 if (potarr[n-1] < POT_HIGH)
01022 dx += potarr[n-1]- cv;
01023 if (potarr[n+1] < POT_HIGH)
01024 dx += cv - potarr[n+1];
01025
01026
01027 if (potarr[n-nx] < POT_HIGH)
01028 dy += potarr[n-nx]- cv;
01029 if (potarr[n+nx] < POT_HIGH)
01030 dy += cv - potarr[n+nx];
01031 }
01032
01033
01034 float norm = hypot(dx, dy);
01035 if (norm > 0)
01036 {
01037 norm = 1.0/norm;
01038 gradx[n] = norm*dx;
01039 grady[n] = norm*dy;
01040 }
01041 return norm;
01042 }
01043
01044
01045
01046
01047
01048
01049
01050 void
01051 NavFn::display(void fn(NavFn *nav), int n)
01052 {
01053 displayFn = fn;
01054 displayInt = n;
01055 }
01056
01057
01058
01059
01060
01061
01062
01063 void
01064 NavFn::savemap(const char *fname)
01065 {
01066 char fn[4096];
01067
01068 ROS_DEBUG("[NavFn] Saving costmap and start/goal points");
01069
01070 sprintf(fn,"%s.txt",fname);
01071 FILE *fp = fopen(fn,"w");
01072 if (!fp)
01073 {
01074 ROS_WARN("Can't open file %s", fn);
01075 return;
01076 }
01077 fprintf(fp,"Goal: %d %d\nStart: %d %d\n",goal[0],goal[1],start[0],start[1]);
01078 fclose(fp);
01079
01080
01081 if (!costarr) return;
01082 sprintf(fn,"%s.pgm",fname);
01083 fp = fopen(fn,"wb");
01084 if (!fp)
01085 {
01086 ROS_WARN("Can't open file %s", fn);
01087 return;
01088 }
01089 fprintf(fp,"P5\n%d\n%d\n%d\n", nx, ny, 0xff);
01090 fwrite(costarr,1,nx*ny,fp);
01091 fclose(fp);
01092 }
01093 };