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
00047
00048
00049
00050
00051
00052
00053
00054 #include <iri_bspline_navfn/navfn.h>
00055 #include <ros/console.h>
00056 #include <costmap_2d/costmap_2d_ros.h>
00057
00058
00059 namespace iri_bspline_navfn {
00060
00061
00062
00063
00064
00065
00066
00067 int
00068 create_nav_plan_astar(COSTTYPE *costmap, int nx, int ny,
00069 int* goal, int* start,
00070 float *plan, int nplan)
00071 {
00072 static NavFn *nav = NULL;
00073
00074 if (nav == NULL)
00075 nav = new NavFn(nx,ny);
00076
00077 if (nav->nx != nx || nav->ny != ny)
00078 {
00079 delete nav;
00080 nav = new NavFn(nx,ny);
00081 }
00082
00083 nav->setGoal(goal);
00084 nav->setStart(start);
00085
00086 nav->costarr = costmap;
00087 nav->setupNavFn(true);
00088
00089
00090 nav->priInc = 2*COST_NEUTRAL;
00091 nav->propNavFnAstar(std::max(nx*ny/20,nx+ny));
00092
00093
00094 int len = nav->calcPath(nplan);
00095
00096 if (len > 0)
00097 ROS_DEBUG("[NavFn] Path found, %d steps\n", len);
00098 else
00099 ROS_DEBUG("[NavFn] No path found\n");
00100
00101 if (len > 0)
00102 {
00103 for (int i=0; i<len; i++)
00104 {
00105 plan[i*2] = nav->pathx[i];
00106 plan[i*2+1] = nav->pathy[i];
00107 }
00108 }
00109
00110 return len;
00111 }
00112
00113
00114
00115
00116
00117
00118
00119
00120 NavFn::NavFn(int xs, int ys)
00121 {
00122
00123 obsarr = costarr = NULL;
00124 potarr = NULL;
00125 pending = NULL;
00126 gradx = grady = NULL;
00127 setNavArr(xs,ys);
00128
00129
00130 pb1 = new int[PRIORITYBUFSIZE];
00131 pb2 = new int[PRIORITYBUFSIZE];
00132 pb3 = new int[PRIORITYBUFSIZE];
00133
00134
00135
00136 priInc = 2*COST_NEUTRAL;
00137
00138
00139 goal[0] = goal[1] = 0;
00140 start[0] = start[1] = 0;
00141
00142
00143 displayFn = NULL;
00144 displayInt = 0;
00145
00146
00147 npathbuf = npath = 0;
00148 pathx = pathy = NULL;
00149 pathStep = 0.5;
00150 }
00151
00152
00153 NavFn::~NavFn()
00154 {
00155 if(obsarr)
00156 delete[] obsarr;
00157 if(costarr)
00158 delete[] costarr;
00159 if(potarr)
00160 delete[] potarr;
00161 if(pending)
00162 delete[] pending;
00163 if(gradx)
00164 delete[] gradx;
00165 if(grady)
00166 delete[] grady;
00167 if(pathx)
00168 delete[] pathx;
00169 if(pathy)
00170 delete[] pathy;
00171 if(pb1)
00172 delete[] pb1;
00173 if(pb2)
00174 delete[] pb2;
00175 if(pb3)
00176 delete[] pb3;
00177 }
00178
00179
00180
00181
00182
00183
00184 void
00185 NavFn::setGoal(int *g)
00186 {
00187 goal[0] = g[0];
00188 goal[1] = g[1];
00189 ROS_DEBUG("[NavFn] Setting goal to %d,%d\n", goal[0], goal[1]);
00190 }
00191
00192 void
00193 NavFn::setStart(int *g)
00194 {
00195 start[0] = g[0];
00196 start[1] = g[1];
00197 ROS_DEBUG("[NavFn] Setting start to %d,%d\n", start[0], start[1]);
00198 }
00199
00200
00201
00202
00203
00204 void
00205 NavFn::setNavArr(int xs, int ys)
00206 {
00207 ROS_DEBUG("[NavFn] Array is %d x %d\n", xs, ys);
00208
00209 nx = xs;
00210 ny = ys;
00211 ns = nx*ny;
00212
00213 if(obsarr)
00214 delete[] obsarr;
00215 if(costarr)
00216 delete[] costarr;
00217 if(potarr)
00218 delete[] potarr;
00219 if(pending)
00220 delete[] pending;
00221
00222 if(gradx)
00223 delete[] gradx;
00224 if(grady)
00225 delete[] grady;
00226
00227 obsarr = new COSTTYPE[ns];
00228 memset(obsarr, 0, ns*sizeof(COSTTYPE));
00229 costarr = new COSTTYPE[ns];
00230 memset(costarr, 0, ns*sizeof(COSTTYPE));
00231 potarr = new float[ns];
00232 pending = new bool[ns];
00233 memset(pending, 0, ns*sizeof(bool));
00234 gradx = new float[ns];
00235 grady = new float[ns];
00236 }
00237
00238
00239
00240
00241
00242
00243 void
00244 NavFn::setCostmap(const COSTTYPE *cmap, bool isROS, bool allow_unknown)
00245 {
00246 COSTTYPE *cm = costarr;
00247 if (isROS)
00248 {
00249 for (int i=0; i<ny; i++)
00250 {
00251 int k=i*nx;
00252 for (int j=0; j<nx; j++, k++, cmap++, cm++)
00253 {
00254 *cm = COST_OBS;
00255 int v = *cmap;
00256 if (v < COST_OBS_ROS)
00257 {
00258 v = COST_NEUTRAL+COST_FACTOR*v;
00259 if (v >= COST_OBS)
00260 v = COST_OBS-1;
00261 *cm = v;
00262 }
00263 else if(v == COST_UNKNOWN_ROS && allow_unknown)
00264 {
00265 v = COST_OBS-1;
00266 *cm = v;
00267 }
00268 }
00269 }
00270 }
00271
00272 else
00273 {
00274 for (int i=0; i<ny; i++)
00275 {
00276 int k=i*nx;
00277 for (int j=0; j<nx; j++, k++, cmap++, cm++)
00278 {
00279 *cm = COST_OBS;
00280 if (i<7 || i > ny-8 || j<7 || j > nx-8)
00281 continue;
00282 int v = *cmap;
00283 if (v < COST_OBS_ROS)
00284 {
00285 v = COST_NEUTRAL+COST_FACTOR*v;
00286 if (v >= COST_OBS)
00287 v = COST_OBS-1;
00288 *cm = v;
00289 }
00290 else if(v == COST_UNKNOWN_ROS)
00291 {
00292 v = COST_OBS-1;
00293 *cm = v;
00294 }
00295 }
00296 }
00297
00298 }
00299 }
00300
00301 void NavFn::setNavPoses(const geometry_msgs::PoseStamped& goal_, const geometry_msgs::PoseStamped& start_, const double resolution_, const double costmap_ox_, const double costmap_oy_)
00302 {
00303 w_goal = goal_;
00304 w_start = start_;
00305 resolution = resolution_;
00306 costmap_ox=costmap_ox_;
00307 costmap_oy=costmap_oy_;
00308 }
00309
00310 bool NavFn::calcNavFnDijkstra(bool atStart)
00311 {
00312 setupNavFn(true);
00313
00314
00315
00316 propNavFnDijkstra(std::max(nx*ny/20,nx+ny),atStart);
00317
00318
00319 int len = calcPath(nx*4);
00320
00321 if (len > 0)
00322 {
00323 ROS_DEBUG("[NavFn] Path found, %d steps\n", len);
00324 return true;
00325 }
00326 else
00327 {
00328 ROS_DEBUG("[NavFn] No path found\n");
00329 return false;
00330 }
00331
00332 }
00333
00334
00335
00336
00337
00338
00339 bool
00340 NavFn::calcNavFnAstar()
00341 {
00342 setupNavFn(true);
00343
00344
00345 propNavFnAstar(std::max(nx*ny/20,nx+ny));
00346
00347
00348 int len = calcPath(nx*4);
00349
00350 if (len > 0)
00351 {
00352 ROS_DEBUG("[NavFn] Path found, %d steps\n", len);
00353 return true;
00354 }
00355 else
00356 {
00357 ROS_DEBUG("[NavFn] No path found\n");
00358 return false;
00359 }
00360 }
00361
00362
00363
00364
00365
00366
00367 float *NavFn::getPathX() { return pathx; }
00368 float *NavFn::getPathY() { return pathy; }
00369 int NavFn::getPathLen() { return npath; }
00370
00371
00372
00373
00374
00375
00376 void
00377 NavFn::setObs()
00378 {
00379 #if 0
00380
00381 ROS_INFO("[NavFn] Setting simple obstacle\n");
00382 int xx = nx/3;
00383 for (int i=ny/3; i<ny; i++)
00384 costarr[i*nx + xx] = COST_OBS;
00385 xx = 2*nx/3;
00386 for (int i=ny/3; i<ny; i++)
00387 costarr[i*nx + xx] = COST_OBS;
00388
00389 xx = nx/4;
00390 for (int i=20; i<ny-ny/3; i++)
00391 costarr[i*nx + xx] = COST_OBS;
00392 xx = nx/2;
00393 for (int i=20; i<ny-ny/3; i++)
00394 costarr[i*nx + xx] = COST_OBS;
00395 xx = 3*nx/4;
00396 for (int i=20; i<ny-ny/3; i++)
00397 costarr[i*nx + xx] = COST_OBS;
00398 #endif
00399 }
00400
00401
00402
00403 #define push_cur(n) { if (n>=0 && n<ns && !pending[n] && \
00404 costarr[n]<COST_OBS && curPe<PRIORITYBUFSIZE) \
00405 { curP[curPe++]=n; pending[n]=true; }}
00406 #define push_next(n) { if (n>=0 && n<ns && !pending[n] && \
00407 costarr[n]<COST_OBS && nextPe<PRIORITYBUFSIZE) \
00408 { nextP[nextPe++]=n; pending[n]=true; }}
00409 #define push_over(n) { if (n>=0 && n<ns && !pending[n] && \
00410 costarr[n]<COST_OBS && overPe<PRIORITYBUFSIZE) \
00411 { overP[overPe++]=n; pending[n]=true; }}
00412
00413
00414
00415
00416 void
00417 NavFn::setupNavFn(bool keepit)
00418 {
00419
00420 for (int i=0; i<ns; i++)
00421 {
00422 potarr[i] = POT_HIGH;
00423
00424 if (!keepit) costarr[i] = COST_NEUTRAL;
00425 gradx[i] = grady[i] = 0.0;
00426 }
00427
00428
00429 COSTTYPE *pc;
00430 pc = costarr;
00431 for (int i=0; i<nx; i++)
00432 *pc++ = COST_OBS;
00433 pc = costarr + (ny-1)*nx;
00434 for (int i=0; i<nx; i++)
00435 *pc++ = COST_OBS;
00436 pc = costarr;
00437 for (int i=0; i<ny; i++, pc+=nx)
00438 *pc = COST_OBS;
00439 pc = costarr + nx - 1;
00440 for (int i=0; i<ny; i++, pc+=nx)
00441 *pc = COST_OBS;
00442
00443
00444 curT = COST_OBS;
00445 curP = pb1;
00446 curPe = 0;
00447 nextP = pb2;
00448 nextPe = 0;
00449 overP = pb3;
00450 overPe = 0;
00451 memset(pending, 0, ns*sizeof(bool));
00452
00453
00454 int k = goal[0] + goal[1]*nx;
00455 initCost(k,0);
00456
00457
00458 pc = costarr;
00459 int ntot = 0;
00460 for (int i=0; i<ns; i++, pc++)
00461 {
00462 if (*pc >= COST_OBS)
00463 ntot++;
00464 }
00465 nobs = ntot;
00466 }
00467
00468
00469
00470
00471 void
00472 NavFn::initCost(int k, float v)
00473 {
00474 potarr[k] = v;
00475 push_cur(k+1);
00476 push_cur(k-1);
00477 push_cur(k-nx);
00478 push_cur(k+nx);
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 #define INVSQRT2 0.707106781
00491
00494 inline void
00495 NavFn::updateCell(int n)
00496 {
00497
00498 float u,d,l,r;
00499 l = potarr[n-1];
00500 r = potarr[n+1];
00501 u = potarr[n-nx];
00502 d = potarr[n+nx];
00503
00504
00505
00506
00507
00508 float ta, tc, hf;
00509 if (l<r) tc=l; else tc=r;
00510 if (u<d) ta=u; else ta=d;
00511
00512
00513
00514 if (costarr[n] < COST_OBS)
00515 {
00516 hf = (float)costarr[n];
00517
00518 float dc = tc-ta;
00519 if (dc < 0)
00520 {
00521 dc = -dc;
00522 ta = tc;
00523 }
00524
00525
00526 float pot;
00527 if (dc >= hf)
00528 pot = ta+hf;
00529 else
00530 {
00531
00532
00533
00534 float d = dc/hf;
00535 float v = -0.2301*d*d + 0.5307*d + 0.7040;
00536 pot = ta + hf*v;
00537 }
00538
00539 bool inspline;
00540
00541 for (int i=0;i<3*world_s;i++)
00542 {
00543 if (n==S_map[i][0]+nx*S_map[i][1])
00544 {
00545 inspline=true;
00546 break;
00547 }
00548 else {
00549 inspline=false;
00550 }
00551 }
00552
00553 if (inspline==false)
00554 {
00555 pot=pot+100.0;
00556 }
00557
00558
00559
00560
00561 if (pot < potarr[n])
00562 {
00563 float le = INVSQRT2*(float)costarr[n-1];
00564 float re = INVSQRT2*(float)costarr[n+1];
00565 float ue = INVSQRT2*(float)costarr[n-nx];
00566 float de = INVSQRT2*(float)costarr[n+nx];
00567 potarr[n] = pot;
00568
00569
00570 if (pot < curT)
00571 {
00572 if (l > pot+le) push_next(n-1);
00573 if (r > pot+re) push_next(n+1);
00574 if (u > pot+ue) push_next(n-nx);
00575 if (d > pot+de) push_next(n+nx);
00576 }
00577 else
00578 {
00579 if (l > pot+le) push_over(n-1);
00580 if (r > pot+re) push_over(n+1);
00581 if (u > pot+ue) push_over(n-nx);
00582 if (d > pot+de) push_over(n+nx);
00583 }
00584 }
00585
00586 }
00587
00588 }
00589
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 #define INVSQRT2 0.707106781
00605
00606 inline void
00607 NavFn::updateCellAstar(int n)
00608 {
00609
00610
00611 float u,d,l,r;
00612 l = potarr[n-1];
00613 r = potarr[n+1];
00614 u = potarr[n-nx];
00615 d = potarr[n+nx];
00616
00617
00618
00619
00620 float ta, tc;
00621 if (l<r) tc=l; else tc=r;
00622 if (u<d) ta=u; else ta=d;
00623
00624
00625 if (costarr[n] < COST_OBS)
00626 {
00627 float hf = (float)costarr[n];
00628 float dc = tc-ta;
00629 if (dc < 0)
00630 {
00631 dc = -dc;
00632 ta = tc;
00633 }
00634
00635
00636 float pot;
00637 if (dc >= hf)
00638 pot = ta+hf;
00639 else
00640 {
00641
00642
00643
00644 float d = dc/hf;
00645 float v = -0.2301*d*d + 0.5307*d + 0.7040;
00646 pot = ta + hf*v;
00647 }
00648
00649
00650
00651
00652 if (pot < potarr[n])
00653 {
00654 float le = INVSQRT2*(float)costarr[n-1];
00655 float re = INVSQRT2*(float)costarr[n+1];
00656 float ue = INVSQRT2*(float)costarr[n-nx];
00657 float de = INVSQRT2*(float)costarr[n+nx];
00658
00659
00660 int x = n%nx;
00661 int y = n/nx;
00662 float dist = (x-start[0])*(x-start[0]) + (y-start[1])*(y-start[1]);
00663 dist = sqrtf(dist)*(float)COST_NEUTRAL;
00664
00665 potarr[n] = pot;
00666 pot += dist;
00667 if (pot < curT)
00668 {
00669 if (l > pot+le) push_next(n-1);
00670 if (r > pot+re) push_next(n+1);
00671 if (u > pot+ue) push_next(n-nx);
00672 if (d > pot+de) push_next(n+nx);
00673 }
00674 else
00675 {
00676
00677 if (l > pot+le) push_over(n-1);
00678 if (r > pot+re) push_over(n+1);
00679 if (u > pot+ue) push_over(n-nx);
00680 if (d > pot+de) push_over(n+nx);
00681 }
00682 }
00683
00684 }
00685
00686 }
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698 bool
00699 NavFn::propNavFnDijkstra(int cycles, bool atStart)
00700 {
00701 int nwv = 0;
00702 int nc = 0;
00703 int cycle = 0;
00704
00705
00706 int startCell = start[1]*nx + start[0];
00707
00708 spline();
00709
00710
00711
00712
00713
00714 for (; cycle < cycles; cycle++)
00715 {
00716
00717
00718 if (curPe == 0 && nextPe == 0)
00719 break;
00720
00721
00722 nc += curPe;
00723 if (curPe > nwv)
00724 nwv = curPe;
00725
00726
00727 int *pb = curP;
00728 int i = curPe;
00729 while (i-- > 0)
00730 pending[*(pb++)] = false;
00731
00732
00733 pb = curP;
00734 i = curPe;
00735 while (i-- > 0)
00736 {
00737 updateCell(*pb++);
00738 }
00739 if (displayInt > 0 && (cycle % displayInt) == 0)
00740 displayFn(this);
00741
00742
00743 curPe = nextPe;
00744 nextPe = 0;
00745 pb = curP;
00746 curP = nextP;
00747 nextP = pb;
00748
00749
00750
00751 if (curPe == 0)
00752 {
00753 curT += priInc;
00754 curPe = overPe;
00755 overPe = 0;
00756 pb = curP;
00757 curP = overP;
00758 overP = pb;
00759 }
00760
00761
00762 if (atStart)
00763 if (potarr[startCell] < POT_HIGH)
00764 break;
00765 }
00766
00767 ROS_DEBUG("[NavFn] Used %d cycles, %d cells visited (%d%%), priority buf max %d\n",
00768 cycle,nc,(int)((nc*100.0)/(ns-nobs)),nwv);
00769
00770 if (cycle < cycles) return true;
00771 else return false;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784 bool
00785 NavFn::propNavFnAstar(int cycles)
00786 {
00787 int nwv = 0;
00788 int nc = 0;
00789 int cycle = 0;
00790
00791
00792 float dist = (goal[0]-start[0])*(goal[0]-start[0]) + (goal[1]-start[1])*(goal[1]-start[1]);
00793 dist = sqrtf(dist)*(float)COST_NEUTRAL;
00794 curT = dist + curT;
00795
00796
00797 int startCell = start[1]*nx + start[0];
00798
00799
00800 for (; cycle < cycles; cycle++)
00801 {
00802
00803 if (curPe == 0 && nextPe == 0)
00804 break;
00805
00806
00807 nc += curPe;
00808 if (curPe > nwv)
00809 nwv = curPe;
00810
00811
00812 int *pb = curP;
00813 int i = curPe;
00814 while (i-- > 0)
00815 pending[*(pb++)] = false;
00816
00817
00818 pb = curP;
00819 i = curPe;
00820 while (i-- > 0)
00821 updateCellAstar(*pb++);
00822
00823 if (displayInt > 0 && (cycle % displayInt) == 0)
00824 displayFn(this);
00825
00826
00827 curPe = nextPe;
00828 nextPe = 0;
00829 pb = curP;
00830 curP = nextP;
00831 nextP = pb;
00832
00833
00834 if (curPe == 0)
00835 {
00836 curT += priInc;
00837 curPe = overPe;
00838 overPe = 0;
00839 pb = curP;
00840 curP = overP;
00841 overP = pb;
00842 }
00843
00844
00845 if (potarr[startCell] < POT_HIGH)
00846 break;
00847
00848 }
00849
00850 last_path_cost_ = potarr[startCell];
00851
00852 ROS_DEBUG("[NavFn] Used %d cycles, %d cells visited (%d%%), priority buf max %d\n",
00853 cycle,nc,(int)((nc*100.0)/(ns-nobs)),nwv);
00854
00855
00856 if (potarr[startCell] < POT_HIGH) return true;
00857 else return false;
00858 }
00859
00861 void NavFn::spline()
00862 {
00863
00864
00865
00866
00867
00868
00869
00870 theta1 = tf::getYaw(w_start.pose.orientation);
00871 theta4 = tf::getYaw(w_goal.pose.orientation);
00872 p1[0] = w_start.pose.position.x;
00873 p1[1] = w_start.pose.position.y;
00874 p4[0] = w_goal.pose.position.x;
00875 p4[1] = w_goal.pose.position.y;
00876
00877 float v=1.0;
00878 float w=0.0;
00879 float dt=0.5;
00880
00881 float world_x = nx*resolution;
00882 float world_y = ny*resolution;
00883
00884 world_s = 101;
00885
00886
00888 p2[0] = p1[0] + v*dt*cos(theta1);
00889 p2[1] = p1[1] + v*dt*sin(theta1);
00890 theta2 = theta1 + w*dt;
00891
00892 p3[0] = p4[0] - v*dt*cos(theta4);
00893 p3[1] = p4[1] - v*dt*sin(theta4);
00894 theta3 = theta4 - w*dt;
00895
00896
00897
00898 Eigen::Matrix4f M;
00899 M(0,0)=-1;
00900 M(0,1)=3;
00901 M(0,2)=-3;
00902 M(0,3)=1;
00903 M(1,0)=3;
00904 M(1,1)=-6;
00905 M(1,2)=3;
00906 M(1,3)=0;
00907 M(2,0)=-3;
00908 M(2,1)=0;
00909 M(2,2)=3;
00910 M(2,3)=0;
00911 M(3,0)=1;
00912 M(3,1)=4;
00913 M(3,2)=1;
00914 M(3,3)=0;
00915
00916 Eigen::MatrixXf P1(4,2);
00917 P1(0,0)= p1[0];
00918 P1(0,1)= p1[1];
00919 P1(1,0)= p1[0];
00920 P1(1,1)= p1[1];
00921 P1(2,0)= p2[0];
00922 P1(2,1)= p2[1];
00923 P1(3,0)= p3[0];
00924 P1(3,1)= p3[1];
00925
00926
00927 Eigen::MatrixXf P2(4,2);
00928 P2(0,0)= p1[0];
00929 P2(0,1)= p1[1];
00930 P2(1,0)= p2[0];
00931 P2(1,1)= p2[1];
00932 P2(2,0)= p3[0];
00933 P2(2,1)= p3[1];
00934 P2(3,0)= p4[0];
00935 P2(3,1)= p4[1];
00936
00937
00938 Eigen::MatrixXf P3(4,2);
00939 P3(0,0)= p2[0];
00940 P3(0,1)= p2[1];
00941 P3(1,0)= p3[0];
00942 P3(1,1)= p3[1];
00943 P3(2,0)= p4[0];
00944 P3(2,1)= p4[1];
00945 P3(3,0)= p4[0];
00946 P3(3,1)= p4[1];
00947
00948 float res = 1.0 / (world_s-1);
00949
00950
00951 Eigen::MatrixXf t(world_s,1);
00952
00953 t(0,0)=0;
00954 for (int i=1;i<world_s;i++)
00955 {
00956 t(i,0)=t(i-1,0)+res;
00957 }
00958
00959
00960
00961 Eigen::MatrixXf tt(world_s,4);
00962
00963 tt.col(0) = t.array().pow(3);
00964 tt.col(1) = t.array().pow(2);
00965 tt.col(2) = t;
00966 tt.col(3) = Eigen::MatrixXf::Ones(world_s,1);
00967
00968
00969
00970 Eigen::MatrixXf S1(world_s,2);
00971 Eigen::MatrixXf S2(world_s,2);
00972 Eigen::MatrixXf S3(world_s,2);
00973
00974
00975 S1 = tt * (1.0 / 6.0) * M * P1;
00976 S2 = tt * (1.0 / 6.0) * M * P2;
00977 S3 = tt * (1.0 / 6.0) * M * P3;
00978
00979
00980
00981 Eigen::MatrixXf S(3*world_s,2);
00982
00983 S << S1, S2, S3;
00984
00985
00986 for (int i=0;i<3*world_s;i++)
00987 {
00988 S_map[i][0] = (int)((ceil)((S(i,0) - costmap_ox) / resolution));
00989 S_map[i][1] = (int)((ceil)((S(i,1) - costmap_oy) / resolution));
00990 }
00991
00992 m_goal[0] = (int)((ceil)((w_goal.pose.position.x - costmap_ox) / resolution));
00993 m_goal[1] = (int)((ceil)((w_goal.pose.position.y - costmap_oy) / resolution));
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005 }
01006
01011 float NavFn::getLastPathCost()
01012 {
01013 return last_path_cost_;
01014 }
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028 int
01029 NavFn::calcPath(int n, int *st)
01030 {
01031
01032
01033
01034
01035 if (npathbuf < n)
01036 {
01037 if (pathx) delete [] pathx;
01038 if (pathy) delete [] pathy;
01039 pathx = new float[n];
01040 pathy = new float[n];
01041 npathbuf = n;
01042 }
01043
01044
01045
01046 if (st == NULL) st = start;
01047 int stc = st[1]*nx + st[0];
01048
01049
01050 float dx=0;
01051 float dy=0;
01052 npath = 0;
01053
01054
01055 for (int i=0; i<n; i++)
01056 {
01057
01058 int nearest_point=std::max(0,std::min(nx*ny-1,stc+(int)round(dx)+(int)(nx*round(dy))));
01059 if (potarr[nearest_point] < COST_NEUTRAL)
01060 {
01061 pathx[npath] = (float)goal[0];
01062 pathy[npath] = (float)goal[1];
01063 return ++npath;
01064 }
01065
01066 if (stc < nx || stc > ns-nx)
01067 {
01068 ROS_DEBUG("[PathCalc] Out of bounds");
01069 return 0;
01070 }
01071
01072
01073 pathx[npath] = stc%nx + dx;
01074 pathy[npath] = stc/nx + dy;
01075 npath++;
01076
01077 int stcnx = stc+nx;
01078 int stcpx = stc-nx;
01079
01080
01081 if (potarr[stc] >= POT_HIGH ||
01082 potarr[stc+1] >= POT_HIGH ||
01083 potarr[stc-1] >= POT_HIGH ||
01084 potarr[stcnx] >= POT_HIGH ||
01085 potarr[stcnx+1] >= POT_HIGH ||
01086 potarr[stcnx-1] >= POT_HIGH ||
01087 potarr[stcpx] >= POT_HIGH ||
01088 potarr[stcpx+1] >= POT_HIGH ||
01089 potarr[stcpx-1] >= POT_HIGH)
01090
01091 {
01092 ROS_DEBUG("[Path] Pot fn boundary, following grid (%0.1f/%d)", potarr[stc], npath);
01093
01094 int minc = stc;
01095 int minp = potarr[stc];
01096 int st = stcpx - 1;
01097 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
01098 st++;
01099 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
01100 st++;
01101 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
01102 st = stc-1;
01103 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
01104 st = stc+1;
01105 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
01106 st = stcnx-1;
01107 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
01108 st++;
01109 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
01110 st++;
01111 if (potarr[st] < minp) {minp = potarr[st]; minc = st; }
01112 stc = minc;
01113 dx = 0;
01114 dy = 0;
01115
01116 ROS_DEBUG("[Path] Pot: %0.1f pos: %0.1f,%0.1f",
01117 potarr[stc], pathx[npath-1], pathy[npath-1]);
01118
01119 if (potarr[stc] >= POT_HIGH)
01120 {
01121 ROS_DEBUG("[PathCalc] No path found, high potential");
01122
01123 return 0;
01124 }
01125 }
01126
01127
01128 else
01129 {
01130
01131
01132 gradCell(stc);
01133 gradCell(stc+1);
01134 gradCell(stcnx);
01135 gradCell(stcnx+1);
01136
01137
01138
01139 ROS_DEBUG("[Path] %0.2f,%0.2f %0.2f,%0.2f %0.2f,%0.2f %0.2f,%0.2f\n",
01140 gradx[stc], grady[stc], gradx[stc+1], grady[stc+1],
01141 gradx[stcnx], grady[stcnx], gradx[stcnx+1], grady[stcnx+1]);
01142
01143
01144 float x1 = (1.0-dx)*gradx[stc] + dx*gradx[stc+1];
01145 float x2 = (1.0-dx)*gradx[stcnx] + dx*gradx[stcnx+1];
01146 float x = (1.0-dy)*x1 + dy*x2;
01147 float y1 = (1.0-dx)*grady[stc] + dx*grady[stc+1];
01148 float y2 = (1.0-dx)*grady[stcnx] + dx*grady[stcnx+1];
01149 float y = (1.0-dy)*y1 + dy*y2;
01150
01151
01152 if (x == 0.0 && y == 0.0)
01153 {
01154 ROS_DEBUG("[PathCalc] Zero gradient");
01155 return 0;
01156 }
01157
01158
01159 float ss = pathStep/sqrt(x*x+y*y);
01160 dx += x*ss;
01161 dy += y*ss;
01162
01163
01164 if (dx > 1.0) { stc++; dx -= 1.0; }
01165 if (dx < -1.0) { stc--; dx += 1.0; }
01166 if (dy > 1.0) { stc+=nx; dy -= 1.0; }
01167 if (dy < -1.0) { stc-=nx; dy += 1.0; }
01168
01169 }
01170
01171
01172
01173 }
01174
01175
01176 ROS_DEBUG("[PathCalc] No path found, path too long");
01177
01178 return 0;
01179 }
01180
01181
01182
01183
01184
01185
01186
01187
01188 float
01189 NavFn::gradCell(int n)
01190 {
01191 if (gradx[n]+grady[n] > 0.0)
01192 return 1.0;
01193
01194 if (n < nx || n > ns-nx)
01195 return 0.0;
01196
01197 float cv = potarr[n];
01198 float dx = 0.0;
01199 float dy = 0.0;
01200
01201
01202 if (cv >= POT_HIGH)
01203 {
01204 if (potarr[n-1] < POT_HIGH)
01205 dx = -COST_OBS;
01206 else if (potarr[n+1] < POT_HIGH)
01207 dx = COST_OBS;
01208
01209 if (potarr[n-nx] < POT_HIGH)
01210 dy = -COST_OBS;
01211 else if (potarr[nx+1] < POT_HIGH)
01212 dy = COST_OBS;
01213 }
01214
01215 else
01216 {
01217
01218 if (potarr[n-1] < POT_HIGH)
01219 dx += potarr[n-1]- cv;
01220 if (potarr[n+1] < POT_HIGH)
01221 dx += cv - potarr[n+1];
01222
01223
01224 if (potarr[n-nx] < POT_HIGH)
01225 dy += potarr[n-nx]- cv;
01226 if (potarr[n+nx] < POT_HIGH)
01227 dy += cv - potarr[n+nx];
01228 }
01229
01230
01231 float norm = sqrtf(dx*dx+dy*dy);
01232 if (norm > 0)
01233 {
01234 norm = 1.0/norm;
01235 gradx[n] = norm*dx;
01236 grady[n] = norm*dy;
01237 }
01238 return norm;
01239 }
01240
01241
01242
01243
01244
01245
01246
01247 void
01248 NavFn::display(void fn(NavFn *nav), int n)
01249 {
01250 displayFn = fn;
01251 displayInt = n;
01252 }
01253
01254
01255
01256
01257
01258
01259
01260 void
01261 NavFn::savemap(const char *fname)
01262 {
01263 char fn[4096];
01264
01265 ROS_DEBUG("[NavFn] Saving costmap and start/goal points");
01266
01267 sprintf(fn,"%s.txt",fname);
01268 FILE *fp = fopen(fn,"w");
01269 if (!fp)
01270 {
01271 ROS_WARN("Can't open file %s", fn);
01272 return;
01273 }
01274 fprintf(fp,"Goal: %d %d\nStart: %d %d\n",goal[0],goal[1],start[0],start[1]);
01275 fclose(fp);
01276
01277
01278 if (!costarr) return;
01279 sprintf(fn,"%s.pgm",fname);
01280 fp = fopen(fn,"wb");
01281 if (!fp)
01282 {
01283 ROS_WARN("Can't open file %s", fn);
01284 return;
01285 }
01286 fprintf(fp,"P5\n%d\n%d\n%d\n", nx, ny, 0xff);
01287 fwrite(costarr,1,nx*ny,fp);
01288 fclose(fp);
01289 }
01290 };