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_]);
57 tree_node * curr_data = &nodes_data_[index_generated_];
61 while (!queue_.empty()) {
64 if (nodes_opened % params_->terminal_checking_interval == 0 && cancel_checker()) {
69 if (isGoal(*curr_data)) {
73 resetParent(curr_data);
74 setNeighbors(curr_data);
76 curr_data = queue_.top();
85 backtrace(raw_path, curr_data);
93 double g_cost, los_cost = 0;
94 curr_data->is_in_queue =
false;
95 const tree_node * curr_par = curr_data->parent_id;
96 const tree_node * maybe_par = curr_par->parent_id;
98 if (losCheck(curr_data->x, curr_data->y, maybe_par->x, maybe_par->y, los_cost)) {
99 g_cost = maybe_par->g +
100 getEuclideanCost(curr_data->x, curr_data->y, maybe_par->x, maybe_par->y) + los_cost;
102 if (g_cost < curr_data->g) {
103 curr_data->parent_id = maybe_par;
104 curr_data->g = g_cost;
105 curr_data->f = g_cost + curr_data->h;
110 void ThetaStar::setNeighbors(
const tree_node * curr_data)
114 double g_cost, h_cost, cal_cost;
116 for (
int i = 0; i < params_->how_many_corners; i++) {
117 mx = curr_data->x + moves[i].x;
118 my = curr_data->y + moves[i].y;
120 if (withinLimits(mx, my)) {
121 if (!isSafe(mx, my)) {
128 g_cost = curr_data->g + getEuclideanCost(curr_data->x, curr_data->y, mx, my) +
129 getTraversalCost(mx, my);
131 m_id = getIndex(mx, my);
133 if (m_id ==
nullptr) {
134 addToNodesData(index_generated_);
135 m_id = &nodes_data_[index_generated_];
136 addIndex(mx, my, m_id);
142 h_cost = getHCost(mx, my);
143 cal_cost = g_cost + h_cost;
144 if (exp_node->f > cal_cost) {
145 exp_node->g = g_cost;
146 exp_node->h = h_cost;
147 exp_node->f = cal_cost;
148 exp_node->parent_id = curr_data;
149 if (!exp_node->is_in_queue) {
152 exp_node->is_in_queue =
true;
159 void ThetaStar::backtrace(std::vector<coordsW> & raw_points,
const tree_node * curr_n)
const
161 std::vector<coordsW> path_rev;
164 costmap_->mapToWorld(curr_n->x, curr_n->y, world.x, world.y);
165 path_rev.push_back(world);
166 if (path_rev.size() > 1) {
167 curr_n = curr_n->parent_id;
169 }
while (curr_n->parent_id != curr_n);
170 costmap_->mapToWorld(curr_n->x, curr_n->y, world.x, world.y);
171 path_rev.push_back(world);
173 raw_points.reserve(path_rev.size());
174 for (
int i =
static_cast<int>(path_rev.size()) - 1; i >= 0; i--) {
175 raw_points.push_back(path_rev[i]);
179 bool ThetaStar::losCheck(
180 const int & x0,
const int & y0,
const int & x1,
const int & y1,
181 double & sl_cost)
const
185 int dx = abs(x1 - x0), sx = (x0 < x1) ? 1 : -1;
186 int dy = abs(y1 - y0), sy = (y0 < y1) ? 1 : -1;
187 int cx = x0, cy = y0, e = dx - dy;
189 while (cx != x1 || cy != y1) {
190 if (!isSafe(cx, cy, sl_cost)) {
194 if (e2 > -dy && e2 <= dx) {
195 if (!isSafe(cx + sx, cy) || !isSafe(cx, cy + sy)) {
201 }
else if (e2 > -dy) {
213 void ThetaStar::resetContainers()
215 index_generated_ = 0;
216 int last_size_x = size_x_;
217 int last_size_y = size_y_;
218 int curr_size_x =
static_cast<int>(costmap_->getSizeInCellsX());
219 int curr_size_y =
static_cast<int>(costmap_->getSizeInCellsY());
220 if (((last_size_x != curr_size_x) || (last_size_y != curr_size_y)) &&
221 static_cast<int>(node_position_.size()) < (curr_size_x * curr_size_y))
223 initializePosn(curr_size_y * curr_size_x - last_size_y * last_size_x);
224 nodes_data_.reserve(curr_size_x * curr_size_y);
228 size_x_ = curr_size_x;
229 size_y_ = curr_size_y;
232 void ThetaStar::initializePosn(
int size_inc)
234 if (!node_position_.empty()) {
235 for (
int i = 0; i < size_x_ * size_y_; i++) {
236 node_position_[i] =
nullptr;
240 for (
int i = 0; i < size_inc; i++) {
241 node_position_.push_back(
nullptr);
245 void ThetaStar::clearStart()
247 unsigned int mx_start =
static_cast<unsigned int>(src_.x);
248 unsigned int my_start =
static_cast<unsigned int>(src_.y);
249 costmap_->setCost(mx_start, my_start, nav2_costmap_2d::FREE_SPACE);