40 #include "nav2_navfn_planner/navfn.hpp"
43 #include "nav2_core/planner_exceptions.hpp"
44 #include "rclcpp/logger.hpp"
45 #include "rclcpp/logging.hpp"
47 namespace nav2_navfn_planner
119 pb1 =
new int[PRIORITYBUFSIZE];
120 pb2 =
new int[PRIORITYBUFSIZE];
121 pb3 =
new int[PRIORITYBUFSIZE];
125 priInc = 2 * COST_NEUTRAL;
128 goal[0] = goal[1] = 0;
129 start[0] = start[1] = 0;
137 pathx =
pathy = NULL;
186 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"[NavFn] Setting goal to %d,%d\n", goal[0], goal[1]);
195 rclcpp::get_logger(
"rclcpp"),
"[NavFn] Setting start to %d,%d\n", start[0],
206 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"[NavFn] Array is %d x %d\n", xs, ys);
230 memset(
costarr, 0,
ns *
sizeof(COSTTYPE));
248 for (
int i = 0; i < ny; i++) {
250 for (
int j = 0; j < nx; j++, k++, cmap++, cm++) {
257 if (v < COST_OBS_ROS) {
258 v = COST_NEUTRAL + COST_FACTOR * v;
263 }
else if (v == COST_UNKNOWN_ROS && allow_unknown) {
270 for (
int i = 0; i < ny; i++) {
272 for (
int j = 0; j < nx; j++, k++, cmap++, cm++) {
274 if (i < 7 || i > ny - 8 || j < 7 || j > nx - 8) {
278 if (v < COST_OBS_ROS) {
279 v = COST_NEUTRAL + COST_FACTOR * v;
284 }
else if (v == COST_UNKNOWN_ROS) {
299 return propNavFnDijkstra(std::max(nx * ny / 20, nx + ny), cancelChecker, atStart);
313 return propNavFnAstar(std::max(nx * ny / 20, nx + ny), cancelChecker);
325 #define push_cur(n) {if (n >= 0 && n < ns && !pending[n] && \
326 costarr[n] < COST_OBS && curPe < PRIORITYBUFSIZE) \
327 {curP[curPe++] = n; pending[n] = true;}}
328 #define push_next(n) {if (n >= 0 && n < ns && !pending[n] && \
329 costarr[n] < COST_OBS && nextPe < PRIORITYBUFSIZE) \
330 {nextP[nextPe++] = n; pending[n] = true;}}
331 #define push_over(n) {if (n >= 0 && n < ns && !pending[n] && \
332 costarr[n] < COST_OBS && overPe < PRIORITYBUFSIZE) \
333 {overP[overPe++] = n; pending[n] = true;}}
342 for (
int i = 0; i <
ns; i++) {
353 for (
int i = 0; i < nx; i++) {
357 for (
int i = 0; i < nx; i++) {
361 for (
int i = 0; i < ny; i++, pc += nx) {
365 for (
int i = 0; i < ny; i++, pc += nx) {
380 int k = goal[0] + goal[1] * nx;
386 for (
int i = 0; i <
ns; i++, pc++) {
387 if (*pc >= COST_OBS) {
416 #define INVSQRT2 0.707106781
422 const float l =
potarr[n - 1];
423 const float r =
potarr[n + 1];
424 const float u =
potarr[n - nx];
425 const float d =
potarr[n + nx];
432 if (l < r) {tc = l;}
else {tc = r;}
433 if (u < d) {ta = u;}
else {ta = d;}
437 float hf =
static_cast<float>(
costarr[n]);
452 const float div = dc / hf;
453 const float v = -0.2301 * div * div + 0.5307 * div + 0.7040;
461 float le = INVSQRT2 *
static_cast<float>(
costarr[n - 1]);
462 float re = INVSQRT2 *
static_cast<float>(
costarr[n + 1]);
463 float ue = INVSQRT2 *
static_cast<float>(
costarr[n - nx]);
464 float de = INVSQRT2 *
static_cast<float>(
costarr[n + nx]);
467 if (l > pot + le) {push_next(n - 1);}
468 if (r > pot + re) {push_next(n + 1);}
469 if (u > pot + ue) {push_next(n - nx);}
470 if (d > pot + de) {push_next(n + nx);}
472 if (l > pot + le) {push_over(n - 1);}
473 if (r > pot + re) {push_over(n + 1);}
474 if (u > pot + ue) {push_over(n - nx);}
475 if (d > pot + de) {push_over(n + nx);}
490 #define INVSQRT2 0.707106781
506 if (l < r) {tc = l;}
else {tc = r;}
507 if (u < d) {ta = u;}
else {ta = d;}
511 float hf =
static_cast<float>(
costarr[n]);
526 const float div = dc / hf;
527 const float v = -0.2301 * div * div + 0.5307 * div + 0.7040;
535 float le = INVSQRT2 *
static_cast<float>(
costarr[n - 1]);
536 float re = INVSQRT2 *
static_cast<float>(
costarr[n + 1]);
537 float ue = INVSQRT2 *
static_cast<float>(
costarr[n - nx]);
538 float de = INVSQRT2 *
static_cast<float>(
costarr[n + nx]);
543 float dist = hypot(x - start[0], y - start[1]) *
static_cast<float>(COST_NEUTRAL);
548 if (l > pot + le) {push_next(n - 1);}
549 if (r > pot + re) {push_next(n + 1);}
550 if (u > pot + ue) {push_next(n - nx);}
551 if (d > pot + de) {push_next(n + nx);}
553 if (l > pot + le) {push_over(n - 1);}
554 if (r > pot + re) {push_over(n + 1);}
555 if (u > pot + ue) {push_over(n - nx);}
556 if (d > pot + de) {push_over(n + nx);}
579 int startCell = start[1] * nx + start[0];
581 for (; cycle < cycles; cycle++) {
582 if (cycle % terminal_checking_interval == 0 && cancelChecker()) {
586 if (curPe == 0 && nextPe == 0) {
633 if (
potarr[startCell] < POT_HIGH) {
640 rclcpp::get_logger(
"rclcpp"),
641 "[NavFn] Used %d cycles, %d cells visited (%d%%), priority buf max %d\n",
642 cycle, nc, (
int)((nc * 100.0) / (
ns -
nobs)), nwv);
644 return (cycle < cycles) ? true :
false;
664 float dist = hypot(goal[0] - start[0], goal[1] - start[1]) *
static_cast<float>(COST_NEUTRAL);
668 int startCell = start[1] * nx + start[0];
671 for (; cycle < cycles; cycle++) {
672 if (cycle % terminal_checking_interval == 0 && cancelChecker()) {
676 if (curPe == 0 && nextPe == 0) {
722 if (
potarr[startCell] < POT_HIGH) {
730 rclcpp::get_logger(
"rclcpp"),
731 "[NavFn] Used %d cycles, %d cells visited (%d%%), priority buf max %d\n",
732 cycle, nc, (
int)((nc * 100.0) / (
ns -
nobs)), nwv);
734 if (
potarr[startCell] < POT_HIGH) {
767 if (pathx) {
delete[] pathx;}
769 pathx =
new float[n];
770 pathy =
new float[n];
776 if (st == NULL) {st = start;}
777 int stc = st[1] * nx + st[0];
785 for (
int i = 0; i < n; i++) {
787 int nearest_point = std::max(
790 nx * ny - 1, stc +
static_cast<int>(round(dx)) +
791 static_cast<int>(nx * round(dy))));
792 if (
potarr[nearest_point] < COST_NEUTRAL) {
793 pathx[
npath] =
static_cast<float>(goal[0]);
798 if (stc < nx || stc >
ns - nx) {
799 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"[PathCalc] Out of bounds");
804 pathx[
npath] = stc % nx + dx;
808 bool oscillation_detected =
false;
814 rclcpp::get_logger(
"rclcpp"),
815 "[PathCalc] oscillation detected, attempting fix.");
816 oscillation_detected =
true;
819 int stcnx = stc + nx;
820 int stcpx = stc - nx;
823 if (
potarr[stc] >= POT_HIGH ||
824 potarr[stc + 1] >= POT_HIGH ||
825 potarr[stc - 1] >= POT_HIGH ||
826 potarr[stcnx] >= POT_HIGH ||
827 potarr[stcnx + 1] >= POT_HIGH ||
828 potarr[stcnx - 1] >= POT_HIGH ||
829 potarr[stcpx] >= POT_HIGH ||
830 potarr[stcpx + 1] >= POT_HIGH ||
831 potarr[stcpx - 1] >= POT_HIGH ||
832 oscillation_detected)
835 rclcpp::get_logger(
"rclcpp"),
836 "[Path] Pot fn boundary, following grid (%0.1f/%d)",
potarr[stc],
npath);
842 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
844 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
846 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
848 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
850 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
852 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
854 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
856 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
862 rclcpp::get_logger(
"rclcpp"),
"[Path] Pot: %0.1f pos: %0.1f,%0.1f",
865 if (
potarr[stc] >= POT_HIGH) {
866 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"[PathCalc] No path found, high potential");
879 float x1 = (1.0 - dx) *
gradx[stc] + dx *
gradx[stc + 1];
880 float x2 = (1.0 - dx) *
gradx[stcnx] + dx *
gradx[stcnx + 1];
881 float x = (1.0 - dy) * x1 + dy * x2;
882 float y1 = (1.0 - dx) *
grady[stc] + dx *
grady[stc + 1];
883 float y2 = (1.0 - dx) *
grady[stcnx] + dx *
grady[stcnx + 1];
884 float y = (1.0 - dy) * y1 + dy * y2;
889 rclcpp::get_logger(
"rclcpp"),
890 "[Path] %0.2f,%0.2f %0.2f,%0.2f %0.2f,%0.2f %0.2f,%0.2f; final x=%.3f, y=%.3f\n",
897 if (x == 0.0 && y == 0.0) {
898 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"[PathCalc] Zero gradient");
908 if (dx > 1.0) {stc++; dx -= 1.0;}
909 if (dx < -1.0) {stc--; dx += 1.0;}
910 if (dy > 1.0) {stc += nx; dy -= 1.0;}
911 if (dy < -1.0) {stc -= nx; dy += 1.0;}
920 rclcpp::get_logger(
"rclcpp"),
921 "[PathCalc] Path extraction exhausted: npath = %d, max_cycles = %d",
941 if (n < nx || n >
ns - nx) {
950 if (cv >= POT_HIGH) {
951 if (
potarr[n - 1] < POT_HIGH) {
953 }
else if (
potarr[n + 1] < POT_HIGH) {
956 if (
potarr[n - nx] < POT_HIGH) {
958 }
else if (
potarr[n + nx] < POT_HIGH) {
963 if (
potarr[n - 1] < POT_HIGH) {
966 if (
potarr[n + 1] < POT_HIGH) {
971 if (
potarr[n - nx] < POT_HIGH) {
972 dy +=
potarr[n - nx] - cv;
974 if (
potarr[n + nx] < POT_HIGH) {
975 dy += cv -
potarr[n + nx];
980 float norm = hypot(dx, dy);
983 gradx[n] = norm * dx;
984 grady[n] = norm * dy;
int getPathLen()
Accessor for the length of a path.
float * getPathX()
Accessor for the x-coordinates of a path.
bool calcNavFnAstar(std::function< bool()> cancelChecker)
Calculates a plan using the A* heuristic, returns true if one is found.
float gradCell(int n)
Calculate gradient at a cell.
void updateCell(int n)
Updates the cell at index n.
bool propNavFnDijkstra(int cycles, std::function< bool()> cancelChecker, bool atStart=false)
Run propagation for <cycles> iterations, or until start is reached using breadth-first Dijkstra metho...
int calcPath(int n, int *st=NULL)
Calculates the path for at most <n> cycles.
float getLastPathCost()
Gets the cost of the path found the last time a navigation function was computed.
bool calcNavFnDijkstra(std::function< bool()> cancelChecker, bool atStart=false)
Calculates the full navigation function using Dijkstra.
bool propNavFnAstar(int cycles, std::function< bool()> cancelChecker)
Run propagation for <cycles> iterations, or until start is reached using the best-first A* method wit...
void updateCellAstar(int n)
Updates the cell at index n using the A* heuristic.
void initCost(int k, float v)
Initialize cell k with cost v for propagation.
void setNavArr(int nx, int ny)
Sets or resets the size of the map.
NavFn(int nx, int ny)
Constructs the planner.
void setCostmap(const COSTTYPE *cmap, bool isROS=true, bool allow_unknown=true)
Set up the cost array for the planner, usually from ROS.
void setupNavFn(bool keepit=false)
Set up navigation potential arrays for new propagation.
void setGoal(int *goal)
Sets the goal position for the planner. Note: the navigation cost field computed gives the cost to ge...
float * getPathY()
Accessor for the y-coordinates of a path.
void setStart(int *start)
Sets the start position for the planner. Note: the navigation cost field computed gives the cost to g...