40 #include "nav2_navfn_planner/navfn.hpp"
43 #include "nav2_core/planner_exceptions.hpp"
44 #include "rclcpp/rclcpp.hpp"
46 namespace nav2_navfn_planner
118 pb1 =
new int[PRIORITYBUFSIZE];
119 pb2 =
new int[PRIORITYBUFSIZE];
120 pb3 =
new int[PRIORITYBUFSIZE];
124 priInc = 2 * COST_NEUTRAL;
127 goal[0] = goal[1] = 0;
128 start[0] = start[1] = 0;
136 pathx =
pathy = NULL;
185 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"[NavFn] Setting goal to %d,%d\n", goal[0], goal[1]);
194 rclcpp::get_logger(
"rclcpp"),
"[NavFn] Setting start to %d,%d\n", start[0],
205 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"[NavFn] Array is %d x %d\n", xs, ys);
229 memset(
costarr, 0,
ns *
sizeof(COSTTYPE));
247 for (
int i = 0; i < ny; i++) {
249 for (
int j = 0; j < nx; j++, k++, cmap++, cm++) {
256 if (v < COST_OBS_ROS) {
257 v = COST_NEUTRAL + COST_FACTOR * v;
262 }
else if (v == COST_UNKNOWN_ROS && allow_unknown) {
269 for (
int i = 0; i < ny; i++) {
271 for (
int j = 0; j < nx; j++, k++, cmap++, cm++) {
273 if (i < 7 || i > ny - 8 || j < 7 || j > nx - 8) {
277 if (v < COST_OBS_ROS) {
278 v = COST_NEUTRAL + COST_FACTOR * v;
283 }
else if (v == COST_UNKNOWN_ROS) {
298 return propNavFnDijkstra(std::max(nx * ny / 20, nx + ny), cancelChecker, atStart);
312 return propNavFnAstar(std::max(nx * ny / 20, nx + ny), cancelChecker);
324 #define push_cur(n) {if (n >= 0 && n < ns && !pending[n] && \
325 costarr[n] < COST_OBS && curPe < PRIORITYBUFSIZE) \
326 {curP[curPe++] = n; pending[n] = true;}}
327 #define push_next(n) {if (n >= 0 && n < ns && !pending[n] && \
328 costarr[n] < COST_OBS && nextPe < PRIORITYBUFSIZE) \
329 {nextP[nextPe++] = n; pending[n] = true;}}
330 #define push_over(n) {if (n >= 0 && n < ns && !pending[n] && \
331 costarr[n] < COST_OBS && overPe < PRIORITYBUFSIZE) \
332 {overP[overPe++] = n; pending[n] = true;}}
341 for (
int i = 0; i <
ns; i++) {
352 for (
int i = 0; i < nx; i++) {
356 for (
int i = 0; i < nx; i++) {
360 for (
int i = 0; i < ny; i++, pc += nx) {
364 for (
int i = 0; i < ny; i++, pc += nx) {
379 int k = goal[0] + goal[1] * nx;
385 for (
int i = 0; i <
ns; i++, pc++) {
386 if (*pc >= COST_OBS) {
415 #define INVSQRT2 0.707106781
421 const float l =
potarr[n - 1];
422 const float r =
potarr[n + 1];
423 const float u =
potarr[n - nx];
424 const float d =
potarr[n + nx];
431 if (l < r) {tc = l;}
else {tc = r;}
432 if (u < d) {ta = u;}
else {ta = d;}
436 float hf =
static_cast<float>(
costarr[n]);
451 const float div = dc / hf;
452 const float v = -0.2301 * div * div + 0.5307 * div + 0.7040;
460 float le = INVSQRT2 *
static_cast<float>(
costarr[n - 1]);
461 float re = INVSQRT2 *
static_cast<float>(
costarr[n + 1]);
462 float ue = INVSQRT2 *
static_cast<float>(
costarr[n - nx]);
463 float de = INVSQRT2 *
static_cast<float>(
costarr[n + nx]);
466 if (l > pot + le) {push_next(n - 1);}
467 if (r > pot + re) {push_next(n + 1);}
468 if (u > pot + ue) {push_next(n - nx);}
469 if (d > pot + de) {push_next(n + nx);}
471 if (l > pot + le) {push_over(n - 1);}
472 if (r > pot + re) {push_over(n + 1);}
473 if (u > pot + ue) {push_over(n - nx);}
474 if (d > pot + de) {push_over(n + nx);}
489 #define INVSQRT2 0.707106781
505 if (l < r) {tc = l;}
else {tc = r;}
506 if (u < d) {ta = u;}
else {ta = d;}
510 float hf =
static_cast<float>(
costarr[n]);
525 const float div = dc / hf;
526 const float v = -0.2301 * div * div + 0.5307 * div + 0.7040;
534 float le = INVSQRT2 *
static_cast<float>(
costarr[n - 1]);
535 float re = INVSQRT2 *
static_cast<float>(
costarr[n + 1]);
536 float ue = INVSQRT2 *
static_cast<float>(
costarr[n - nx]);
537 float de = INVSQRT2 *
static_cast<float>(
costarr[n + nx]);
542 float dist = hypot(x - start[0], y - start[1]) *
static_cast<float>(COST_NEUTRAL);
547 if (l > pot + le) {push_next(n - 1);}
548 if (r > pot + re) {push_next(n + 1);}
549 if (u > pot + ue) {push_next(n - nx);}
550 if (d > pot + de) {push_next(n + nx);}
552 if (l > pot + le) {push_over(n - 1);}
553 if (r > pot + re) {push_over(n + 1);}
554 if (u > pot + ue) {push_over(n - nx);}
555 if (d > pot + de) {push_over(n + nx);}
578 int startCell = start[1] * nx + start[0];
580 for (; cycle < cycles; cycle++) {
581 if (cycle % terminal_checking_interval == 0 && cancelChecker()) {
585 if (curPe == 0 && nextPe == 0) {
632 if (
potarr[startCell] < POT_HIGH) {
639 rclcpp::get_logger(
"rclcpp"),
640 "[NavFn] Used %d cycles, %d cells visited (%d%%), priority buf max %d\n",
641 cycle, nc, (
int)((nc * 100.0) / (
ns -
nobs)), nwv);
643 return (cycle < cycles) ? true :
false;
663 float dist = hypot(goal[0] - start[0], goal[1] - start[1]) *
static_cast<float>(COST_NEUTRAL);
667 int startCell = start[1] * nx + start[0];
670 for (; cycle < cycles; cycle++) {
671 if (cycle % terminal_checking_interval == 0 && cancelChecker()) {
675 if (curPe == 0 && nextPe == 0) {
721 if (
potarr[startCell] < POT_HIGH) {
729 rclcpp::get_logger(
"rclcpp"),
730 "[NavFn] Used %d cycles, %d cells visited (%d%%), priority buf max %d\n",
731 cycle, nc, (
int)((nc * 100.0) / (
ns -
nobs)), nwv);
733 if (
potarr[startCell] < POT_HIGH) {
766 if (pathx) {
delete[] pathx;}
768 pathx =
new float[n];
769 pathy =
new float[n];
775 if (st == NULL) {st = start;}
776 int stc = st[1] * nx + st[0];
784 for (
int i = 0; i < n; i++) {
786 int nearest_point = std::max(
789 nx * ny - 1, stc +
static_cast<int>(round(dx)) +
790 static_cast<int>(nx * round(dy))));
791 if (
potarr[nearest_point] < COST_NEUTRAL) {
792 pathx[
npath] =
static_cast<float>(goal[0]);
797 if (stc < nx || stc >
ns - nx) {
798 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"[PathCalc] Out of bounds");
803 pathx[
npath] = stc % nx + dx;
807 bool oscillation_detected =
false;
813 rclcpp::get_logger(
"rclcpp"),
814 "[PathCalc] oscillation detected, attempting fix.");
815 oscillation_detected =
true;
818 int stcnx = stc + nx;
819 int stcpx = stc - nx;
822 if (
potarr[stc] >= POT_HIGH ||
823 potarr[stc + 1] >= POT_HIGH ||
824 potarr[stc - 1] >= POT_HIGH ||
825 potarr[stcnx] >= POT_HIGH ||
826 potarr[stcnx + 1] >= POT_HIGH ||
827 potarr[stcnx - 1] >= POT_HIGH ||
828 potarr[stcpx] >= POT_HIGH ||
829 potarr[stcpx + 1] >= POT_HIGH ||
830 potarr[stcpx - 1] >= POT_HIGH ||
831 oscillation_detected)
834 rclcpp::get_logger(
"rclcpp"),
835 "[Path] Pot fn boundary, following grid (%0.1f/%d)",
potarr[stc],
npath);
841 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
843 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
845 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
847 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
849 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
851 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
853 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
855 if (
potarr[sti] < minp) {minp =
potarr[sti]; minc = sti;}
861 rclcpp::get_logger(
"rclcpp"),
"[Path] Pot: %0.1f pos: %0.1f,%0.1f",
864 if (
potarr[stc] >= POT_HIGH) {
865 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"[PathCalc] No path found, high potential");
878 float x1 = (1.0 - dx) *
gradx[stc] + dx *
gradx[stc + 1];
879 float x2 = (1.0 - dx) *
gradx[stcnx] + dx *
gradx[stcnx + 1];
880 float x = (1.0 - dy) * x1 + dy * x2;
881 float y1 = (1.0 - dx) *
grady[stc] + dx *
grady[stc + 1];
882 float y2 = (1.0 - dx) *
grady[stcnx] + dx *
grady[stcnx + 1];
883 float y = (1.0 - dy) * y1 + dy * y2;
888 rclcpp::get_logger(
"rclcpp"),
889 "[Path] %0.2f,%0.2f %0.2f,%0.2f %0.2f,%0.2f %0.2f,%0.2f; final x=%.3f, y=%.3f\n",
896 if (x == 0.0 && y == 0.0) {
897 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"[PathCalc] Zero gradient");
907 if (dx > 1.0) {stc++; dx -= 1.0;}
908 if (dx < -1.0) {stc--; dx += 1.0;}
909 if (dy > 1.0) {stc += nx; dy -= 1.0;}
910 if (dy < -1.0) {stc -= nx; dy += 1.0;}
918 RCLCPP_DEBUG(rclcpp::get_logger(
"rclcpp"),
"[PathCalc] No path found, path too long");
937 if (n < nx || n >
ns - nx) {
946 if (cv >= POT_HIGH) {
947 if (
potarr[n - 1] < POT_HIGH) {
949 }
else if (
potarr[n + 1] < POT_HIGH) {
952 if (
potarr[n - nx] < POT_HIGH) {
954 }
else if (
potarr[n + nx] < POT_HIGH) {
959 if (
potarr[n - 1] < POT_HIGH) {
962 if (
potarr[n + 1] < POT_HIGH) {
967 if (
potarr[n - nx] < POT_HIGH) {
968 dy +=
potarr[n - nx] - cv;
970 if (
potarr[n + nx] < POT_HIGH) {
971 dy += cv -
potarr[n + nx];
976 float norm = hypot(dx, dy);
979 gradx[n] = norm * dx;
980 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...