16 #include "nav2_theta_star_planner/theta_star.hpp"
21 ThetaStar::ThetaStar()
22 : w_traversal_cost_(1.0),
24 w_heuristic_cost_(1.0),
34 void ThetaStar::setStartAndGoal(
35 const geometry_msgs::msg::PoseStamped & start,
36 const geometry_msgs::msg::PoseStamped & goal)
38 unsigned int s[2], d[2];
39 costmap_->worldToMap(start.pose.position.x, start.pose.position.y, s[0], s[1]);
40 costmap_->worldToMap(goal.pose.position.x, goal.pose.position.y, d[0], d[1]);
42 src_ = {
static_cast<int>(s[0]),
static_cast<int>(s[1])};
43 dst_ = {
static_cast<int>(d[0]),
static_cast<int>(d[1])};
46 bool ThetaStar::generatePath(std::vector<coordsW> & raw_path)
49 addToNodesData(index_generated_);
50 double src_g_cost = getTraversalCost(src_.x, src_.y), src_h_cost = getHCost(src_.x, src_.y);
51 nodes_data_[index_generated_] =
52 {src_.x, src_.y, src_g_cost, src_h_cost, &nodes_data_[index_generated_],
true,
53 src_g_cost + src_h_cost};
54 queue_.push({&nodes_data_[index_generated_]});
55 addIndex(src_.x, src_.y, &nodes_data_[index_generated_]);
56 tree_node * curr_data = &nodes_data_[index_generated_];
60 while (!queue_.empty()) {
63 if (isGoal(*curr_data)) {
67 resetParent(curr_data);
68 setNeighbors(curr_data);
70 curr_data = queue_.top();
79 backtrace(raw_path, curr_data);
87 double g_cost, los_cost = 0;
88 curr_data->is_in_queue =
false;
89 const tree_node * curr_par = curr_data->parent_id;
90 const tree_node * maybe_par = curr_par->parent_id;
92 if (losCheck(curr_data->x, curr_data->y, maybe_par->x, maybe_par->y, los_cost)) {
93 g_cost = maybe_par->g +
94 getEuclideanCost(curr_data->x, curr_data->y, maybe_par->x, maybe_par->y) + los_cost;
96 if (g_cost < curr_data->g) {
97 curr_data->parent_id = maybe_par;
98 curr_data->g = g_cost;
99 curr_data->f = g_cost + curr_data->h;
104 void ThetaStar::setNeighbors(
const tree_node * curr_data)
108 double g_cost, h_cost, cal_cost;
110 for (
int i = 0; i < how_many_corners_; i++) {
111 mx = curr_data->x + moves[i].x;
112 my = curr_data->y + moves[i].y;
114 if (withinLimits(mx, my)) {
115 if (!isSafe(mx, my)) {
122 g_cost = curr_data->g + getEuclideanCost(curr_data->x, curr_data->y, mx, my) +
123 getTraversalCost(mx, my);
125 m_id = getIndex(mx, my);
127 if (m_id ==
nullptr) {
128 addToNodesData(index_generated_);
129 m_id = &nodes_data_[index_generated_];
130 addIndex(mx, my, m_id);
136 h_cost = getHCost(mx, my);
137 cal_cost = g_cost + h_cost;
138 if (exp_node->f > cal_cost) {
139 exp_node->g = g_cost;
140 exp_node->h = h_cost;
141 exp_node->f = cal_cost;
142 exp_node->parent_id = curr_data;
143 if (!exp_node->is_in_queue) {
146 exp_node->is_in_queue =
true;
153 void ThetaStar::backtrace(std::vector<coordsW> & raw_points,
const tree_node * curr_n)
const
155 std::vector<coordsW> path_rev;
158 costmap_->mapToWorld(curr_n->x, curr_n->y, world.x, world.y);
159 path_rev.push_back(world);
160 if (path_rev.size() > 1) {
161 curr_n = curr_n->parent_id;
163 }
while (curr_n->parent_id != curr_n);
164 costmap_->mapToWorld(curr_n->x, curr_n->y, world.x, world.y);
165 path_rev.push_back(world);
167 raw_points.reserve(path_rev.size());
168 for (
int i =
static_cast<int>(path_rev.size()) - 1; i >= 0; i--) {
169 raw_points.push_back(path_rev[i]);
173 bool ThetaStar::losCheck(
174 const int & x0,
const int & y0,
const int & x1,
const int & y1,
175 double & sl_cost)
const
180 int dy = abs(y1 - y0), dx = abs(x1 - x0), f = 0;
182 sx = x1 > x0 ? 1 : -1;
183 sy = y1 > y0 ? 1 : -1;
185 int u_x = (sx - 1) / 2;
186 int u_y = (sy - 1) / 2;
194 if (!isSafe(cx + u_x, cy + u_y, sl_cost)) {
200 if (f != 0 && !isSafe(cx + u_x, cy + u_y, sl_cost)) {
203 if (dy == 0 && !isSafe(cx + u_x, cy, sl_cost) && !isSafe(cx + u_x, cy - 1, sl_cost)) {
212 if (!isSafe(cx + u_x, cy + u_y, sl_cost)) {
218 if (f != 0 && !isSafe(cx + u_x, cy + u_y, sl_cost)) {
221 if (dx == 0 && !isSafe(cx, cy + u_y, sl_cost) && !isSafe(cx - 1, cy + u_y, sl_cost)) {
230 void ThetaStar::resetContainers()
232 index_generated_ = 0;
233 int last_size_x = size_x_;
234 int last_size_y = size_y_;
235 int curr_size_x =
static_cast<int>(costmap_->getSizeInCellsX());
236 int curr_size_y =
static_cast<int>(costmap_->getSizeInCellsY());
237 if (((last_size_x != curr_size_x) || (last_size_y != curr_size_y)) &&
238 static_cast<int>(node_position_.size()) < (curr_size_x * curr_size_y))
240 initializePosn(curr_size_y * curr_size_x - last_size_y * last_size_x);
241 nodes_data_.reserve(curr_size_x * curr_size_y);
245 size_x_ = curr_size_x;
246 size_y_ = curr_size_y;
249 void ThetaStar::initializePosn(
int size_inc)
251 if (!node_position_.empty()) {
252 for (
int i = 0; i < size_x_ * size_y_; i++) {
253 node_position_[i] =
nullptr;
257 for (
int i = 0; i < size_inc; i++) {
258 node_position_.push_back(
nullptr);