Program Listing for File jump_point_search.cpp¶
↰ Return to documentation for file (src/jump_point_search.cpp
)
#include <cmath>
#ifdef BUILD_INDIVIDUAL
#include <random>
#endif // BUILD_INDIVIDUAL
#include "path_planning/jump_point_search.hpp"
Node JumpPointSearch::jump(const Node& new_point, const Node& motion,
const int id) {
Node next_point = new_point + motion;
next_point.id_ = n_ * next_point.x_ + next_point.y_;
next_point.pid_ = id;
next_point.h_cost_ =
std::abs(next_point.x_ - goal_.x_) + std::abs(next_point.y_ - goal_.y_);
if (next_point.x_ < 0 || next_point.y_ < 0 || next_point.x_ >= n_ ||
next_point.y_ >= n_ || grid_[next_point.x_][next_point.y_] != 0) {
// return new_point;
return Node(-1, -1, -1, -1, -1, -1);
}
if (pruned.find(next_point.id_) != pruned.end()) {
pruned.insert(next_point.id_);
}
if (CompareCoordinates(next_point, goal_)) {
return next_point;
}
bool fn = false;
fn = HasForcedNeighbours(new_point, next_point, motion);
if (fn) {
// std::cout << "Forced neighbours found"<<'\n';
return next_point;
}
Node jump_node = jump(next_point, motion, id);
// Prevent over shoot
if (jump_node.cost_ != -1 && jump_node.cost_ + jump_node.h_cost_ <=
next_point.cost_ + next_point.h_cost_) {
return jump_node;
}
return next_point;
}
bool JumpPointSearch::HasForcedNeighbours(const Node& new_point,
const Node& next_point,
const Node& motion) const {
int cn1x = new_point.x_ + motion.y_;
int cn1y = new_point.y_ + motion.x_;
int cn2x = new_point.x_ - motion.y_;
int cn2y = new_point.y_ - motion.x_;
int nn1x = next_point.x_ + motion.y_;
int nn1y = next_point.y_ + motion.x_;
int nn2x = next_point.x_ - motion.y_;
int nn2y = next_point.y_ - motion.x_;
bool a = !(cn1x < 0 || cn1y < 0 || cn1x >= n_ || cn1y >= n_ ||
grid_[cn1x][cn1y] == 1);
bool b = !(nn1x < 0 || nn1y < 0 || nn1x >= n_ || nn1y >= n_ ||
grid_[nn1x][nn1y] == 1);
if (a != b) {
return true;
}
a = !(cn2x < 0 || cn2y < 0 || cn2x >= n_ || cn2y >= n_ ||
grid_[cn2x][cn2y] == 1);
b = !(nn2x < 0 || nn2y < 0 || nn2x >= n_ || nn2y >= n_ ||
grid_[nn2x][nn2y] == 1);
return a != b;
}
std::tuple<bool, std::vector<Node>> JumpPointSearch::Plan(const Node& start,
const Node& goal) {
grid_ = original_grid_;
start_ = start;
goal_ = goal;
// Get possible motions
std::vector<Node> motion = GetMotion();
open_list_.push(start_);
// Main loop
while (!open_list_.empty()) {
Node current = open_list_.top();
open_list_.pop();
current.id_ = current.x_ * n_ + current.y_;
if (CompareCoordinates(current, goal_)) {
closed_list_.push_back(current);
grid_[current.x_][current.y_] = 2;
return {true, closed_list_};
}
grid_[current.x_][current.y_] = 2; // Point opened
for (const auto& m :
motion) { // auto it = motion.begin(); it!=motion.end(); ++it){
Node new_point;
new_point = current + m;
new_point.id_ = n_ * new_point.x_ + new_point.y_;
new_point.pid_ = current.id_;
new_point.h_cost_ =
abs(new_point.x_ - goal_.x_) + abs(new_point.y_ - goal_.y_);
if (CompareCoordinates(new_point, goal_)) {
open_list_.push(new_point);
break;
}
if (checkOutsideBoundary(new_point, n_)) {
continue; // Check boundaries
}
if (grid_[new_point.x_][new_point.y_] != 0) {
continue; // obstacle or visited
}
Node jump_point = jump(new_point, m, current.id_);
if (jump_point.id_ != -1) {
open_list_.push(jump_point);
if (CompareCoordinates(jump_point, goal_)) {
closed_list_.push_back(current);
closed_list_.push_back(jump_point);
grid_[jump_point.x_][jump_point.y_] = 2;
return {true, closed_list_};
}
}
open_list_.push(new_point);
}
closed_list_.push_back(current);
}
return {false, {}};
}
#ifdef BUILD_INDIVIDUAL
int main() {
constexpr int n = 11;
std::vector<std::vector<int>> grid(n, std::vector<int>(n, 0));
MakeGrid(grid);
std::random_device rd; // obtain a random number from hardware
std::mt19937 eng(rd()); // seed the generator
std::uniform_int_distribution<int> distr(0, n - 1); // define the range
Node start(distr(eng), distr(eng), 0, 0, 0, 0);
Node goal(distr(eng), distr(eng), 0, 0, 0, 0);
start.id_ = start.x_ * n + start.y_;
start.pid_ = start.x_ * n + start.y_;
goal.id_ = goal.x_ * n + goal.y_;
start.h_cost_ = abs(start.x_ - goal.x_) + abs(start.y_ - goal.y_);
// Make sure start and goal are not obstacles and their ids are correctly
// assigned.
grid[start.x_][start.y_] = 0;
grid[goal.x_][goal.y_] = 0;
start.PrintStatus();
goal.PrintStatus();
PrintGrid(grid);
JumpPointSearch new_jump_point_search(grid);
const auto [path_found, path_vector] =
new_jump_point_search.Plan(start, goal);
PrintPath(path_vector, start, goal, grid);
return 0;
}
#endif // BUILD_INDIVIDUAL