18 #include "geometry_msgs/msg/pose_stamped.hpp"
20 #include "nav2_core/planner_exceptions.hpp"
21 #include "nav2_theta_star_planner/theta_star.hpp"
23 namespace nav2_theta_star_planner
26 ThetaStar::ThetaStar(Parameters * params)
35 void ThetaStar::setStartAndGoal(
36 const geometry_msgs::msg::PoseStamped & start,
37 const geometry_msgs::msg::PoseStamped & goal)
39 unsigned int s[2], d[2];
40 costmap_->worldToMap(start.pose.position.x, start.pose.position.y, s[0], s[1]);
41 costmap_->worldToMap(goal.pose.position.x, goal.pose.position.y, d[0], d[1]);
43 src_ = {
static_cast<int>(s[0]),
static_cast<int>(s[1])};
44 dst_ = {
static_cast<int>(d[0]),
static_cast<int>(d[1])};
47 bool ThetaStar::generatePath(std::vector<coordsW> & raw_path, std::function<
bool()> cancel_checker)
50 addToNodesData(index_generated_);
51 double src_g_cost = getTraversalCost(src_.x, src_.y), src_h_cost = getHCost(src_.x, src_.y);
52 nodes_data_[index_generated_] =
53 {src_.x, src_.y, src_g_cost, src_h_cost, &nodes_data_[index_generated_],
true,
54 src_g_cost + src_h_cost};
55 queue_.push({&nodes_data_[index_generated_]});
56 addIndex(src_.x, src_.y, &nodes_data_[index_generated_]);
60 while (!queue_.empty()) {
65 if (nodes_opened % params_->terminal_checking_interval == 0 && cancel_checker()) {
70 if (isGoal(*curr_data)) {
71 backtrace(raw_path, curr_data);
76 resetParent(curr_data);
77 setNeighbors(curr_data);
86 double g_cost, los_cost = 0;
87 curr_data->is_in_queue =
false;
88 const tree_node * curr_par = curr_data->parent_id;
89 const tree_node * maybe_par = curr_par->parent_id;
91 if (losCheck(curr_data->x, curr_data->y, maybe_par->x, maybe_par->y, los_cost)) {
92 g_cost = maybe_par->g +
93 getEuclideanCost(curr_data->x, curr_data->y, maybe_par->x, maybe_par->y) + los_cost;
95 if (g_cost < curr_data->g) {
96 curr_data->parent_id = maybe_par;
97 curr_data->g = g_cost;
98 curr_data->f = g_cost + curr_data->h;
103 void ThetaStar::setNeighbors(
const tree_node * curr_data)
107 double g_cost, h_cost, cal_cost;
109 for (
int i = 0; i < params_->how_many_corners; i++) {
110 mx = curr_data->x + moves[i].x;
111 my = curr_data->y + moves[i].y;
113 if (withinLimits(mx, my)) {
114 if (!isSafe(mx, my)) {
121 g_cost = curr_data->g + getEuclideanCost(curr_data->x, curr_data->y, mx, my) +
122 getTraversalCost(mx, my);
124 m_id = getIndex(mx, my);
126 if (m_id ==
nullptr) {
127 addToNodesData(index_generated_);
128 m_id = &nodes_data_[index_generated_];
129 addIndex(mx, my, m_id);
135 h_cost = getHCost(mx, my);
136 cal_cost = g_cost + h_cost;
137 if (exp_node->f > cal_cost) {
138 exp_node->g = g_cost;
139 exp_node->h = h_cost;
140 exp_node->f = cal_cost;
141 exp_node->parent_id = curr_data;
142 if (!exp_node->is_in_queue) {
145 exp_node->is_in_queue =
true;
152 void ThetaStar::backtrace(std::vector<coordsW> & raw_points,
const tree_node * curr_n)
const
154 std::vector<coordsW> path_rev;
157 costmap_->mapToWorld(curr_n->x, curr_n->y, world.x, world.y);
158 path_rev.push_back(world);
159 if (path_rev.size() > 1) {
160 curr_n = curr_n->parent_id;
162 }
while (curr_n->parent_id != curr_n);
163 costmap_->mapToWorld(curr_n->x, curr_n->y, world.x, world.y);
164 path_rev.push_back(world);
166 raw_points.reserve(path_rev.size());
167 for (
int i =
static_cast<int>(path_rev.size()) - 1; i >= 0; i--) {
168 raw_points.push_back(path_rev[i]);
172 bool ThetaStar::losCheck(
173 const int & x0,
const int & y0,
const int & x1,
const int & y1,
174 double & sl_cost)
const
178 int dx = abs(x1 - x0), sx = (x0 < x1) ? 1 : -1;
179 int dy = abs(y1 - y0), sy = (y0 < y1) ? 1 : -1;
180 int cx = x0, cy = y0, e = dx - dy;
182 while (cx != x1 || cy != y1) {
183 if (!isSafe(cx, cy, sl_cost)) {
187 if (e2 > -dy && e2 <= dx) {
188 if (!isSafe(cx + sx, cy) || !isSafe(cx, cy + sy)) {
194 }
else if (e2 > -dy) {
206 void ThetaStar::resetContainers()
208 index_generated_ = 0;
209 int last_size_x = size_x_;
210 int last_size_y = size_y_;
211 int curr_size_x =
static_cast<int>(costmap_->getSizeInCellsX());
212 int curr_size_y =
static_cast<int>(costmap_->getSizeInCellsY());
213 if (((last_size_x != curr_size_x) || (last_size_y != curr_size_y)) &&
214 static_cast<int>(node_position_.size()) < (curr_size_x * curr_size_y))
216 initializePosn(curr_size_y * curr_size_x - last_size_y * last_size_x);
217 nodes_data_.reserve(curr_size_x * curr_size_y);
221 size_x_ = curr_size_x;
222 size_y_ = curr_size_y;
225 void ThetaStar::initializePosn(
int size_inc)
227 if (!node_position_.empty()) {
228 for (
int i = 0; i < size_x_ * size_y_; i++) {
229 node_position_[i] =
nullptr;
233 for (
int i = 0; i < size_inc; i++) {
234 node_position_.push_back(
nullptr);
238 void ThetaStar::clearStart()
240 unsigned int mx_start =
static_cast<unsigned int>(src_.x);
241 unsigned int my_start =
static_cast<unsigned int>(src_.y);
242 costmap_->setCost(mx_start, my_start, nav2_costmap_2d::FREE_SPACE);