Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
theta_star.hpp
1 // Copyright 2020 Anshumaan Singh
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef NAV2_THETA_STAR_PLANNER__THETA_STAR_HPP_
16 #define NAV2_THETA_STAR_PLANNER__THETA_STAR_HPP_
17 
18 #include <cmath>
19 #include <chrono>
20 #include <vector>
21 #include <queue>
22 #include <algorithm>
23 #include "rclcpp/rclcpp.hpp"
24 #include "nav2_costmap_2d/costmap_2d_ros.hpp"
25 #include "nav2_theta_star_planner/parameter_handler.hpp"
26 
27 const double INF_COST = DBL_MAX;
28 const int UNKNOWN_COST = 255;
29 const int OCCUPIED_COST = 254;
30 const int MAX_NON_OBSTACLE_COST = 252;
31 
32 struct coordsM
33 {
34  int x, y;
35 };
36 
37 struct coordsW
38 {
39  double x, y;
40 };
41 
42 struct tree_node
43 {
44  int x, y;
45  double g = INF_COST;
46  double h = INF_COST;
47  const tree_node * parent_id = nullptr;
48  bool is_in_queue = false;
49  double f = INF_COST;
50 };
51 
52 struct comp
53 {
54  bool operator()(const tree_node * p1, const tree_node * p2)
55  {
56  return (p1->f) > (p2->f);
57  }
58 };
59 
60 namespace nav2_theta_star_planner
61 {
62 class ThetaStar
63 {
64 public:
65  coordsM src_{}, dst_{};
66  nav2_costmap_2d::Costmap2D * costmap_{};
68  int size_x_, size_y_;
69 
70  explicit ThetaStar(Parameters * params);
71 
72  ~ThetaStar() = default;
73 
80  bool generatePath(std::vector<coordsW> & raw_path, std::function<bool()> cancel_checker);
81 
86  inline bool isSafe(const int & cx, const int & cy) const
87  {
88  return (costmap_->getCost(cx, cy) == UNKNOWN_COST && params_->allow_unknown) ||
89  costmap_->getCost(cx, cy) <= MAX_NON_OBSTACLE_COST;
90  }
91 
95  void setStartAndGoal(
96  const geometry_msgs::msg::PoseStamped & start,
97  const geometry_msgs::msg::PoseStamped & goal);
98 
103  bool isUnsafeToPlan() const
104  {
105  return !(isSafe(src_.x, src_.y)) || !(isSafe(dst_.x, dst_.y));
106  }
107 
111  void clearStart();
112 
113  int nodes_opened = 0;
114 
115 protected:
120  std::vector<tree_node *> node_position_;
121 
126  std::vector<tree_node> nodes_data_;
127 
129  std::priority_queue<tree_node *, std::vector<tree_node *>, comp> queue_;
130 
135 
136  Parameters * params_;
137 
138  const coordsM moves[8] = {{0, 1},
139  {0, -1},
140  {1, 0},
141  {-1, 0},
142  {1, -1},
143  {-1, 1},
144  {1, 1},
145  {-1, -1}};
146 
147  tree_node * exp_node;
148 
149 
155  void resetParent(tree_node * curr_data);
156 
162  void setNeighbors(const tree_node * curr_data);
163 
171  bool losCheck(
172  const int & x0, const int & y0, const int & x1, const int & y1,
173  double & sl_cost) const;
174 
180  void backtrace(std::vector<coordsW> & raw_points, const tree_node * curr_n) const;
181 
187  bool isSafe(const int & cx, const int & cy, double & cost) const
188  {
189  const double curr_cost = getCost(cx, cy);
190  if ((costmap_->getCost(cx, cy) == UNKNOWN_COST && params_->allow_unknown) ||
191  curr_cost <= MAX_NON_OBSTACLE_COST)
192  {
193  cost += params_->w_traversal_cost * curr_cost * curr_cost / MAX_NON_OBSTACLE_COST /
194  MAX_NON_OBSTACLE_COST;
195  return true;
196  } else {
197  return false;
198  }
199  }
200 
208  inline double getCost(const int & cx, const int & cy) const
209  {
210  const unsigned char cost = costmap_->getCost(cx, cy);
211  return 26 + 0.9 * (cost == UNKNOWN_COST ? OCCUPIED_COST - 1 : cost);
212  }
213 
219  inline double getTraversalCost(const int & cx, const int & cy)
220  {
221  double curr_cost = getCost(cx, cy);
222  return params_->w_traversal_cost * curr_cost * curr_cost / MAX_NON_OBSTACLE_COST /
223  MAX_NON_OBSTACLE_COST;
224  }
225 
231  inline double getEuclideanCost(const int & ax, const int & ay, const int & bx, const int & by)
232  {
233  return params_->w_euc_cost * std::hypot(ax - bx, ay - by);
234  }
235 
241  inline double getHCost(const int & cx, const int & cy)
242  {
243  return params_->w_heuristic_cost * std::hypot(cx - dst_.x, cy - dst_.y);
244  }
245 
250  inline bool withinLimits(const int & cx, const int & cy) const
251  {
252  return cx >= 0 && cx < size_x_ && cy >= 0 && cy < size_y_;
253  }
254 
259  inline bool isGoal(const tree_node & this_node) const
260  {
261  return this_node.x == dst_.x && this_node.y == dst_.y;
262  }
263 
268  void initializePosn(int size_inc = 0);
269 
274  inline void addIndex(const int & cx, const int & cy, tree_node * node_this)
275  {
276  node_position_[size_x_ * cy + cx] = node_this;
277  }
278 
283  inline tree_node * getIndex(const int & cx, const int & cy)
284  {
285  return node_position_[size_x_ * cy + cx];
286  }
287 
292  void addToNodesData(const int & id_this)
293  {
294  if (static_cast<int>(nodes_data_.size()) <= id_this) {
295  nodes_data_.push_back({});
296  } else {
297  nodes_data_[id_this] = {};
298  }
299  }
300 
304  void resetContainers();
305 
309  void clearQueue()
310  {
311  queue_ = std::priority_queue<tree_node *, std::vector<tree_node *>, comp>();
312  }
313 };
314 } // namespace nav2_theta_star_planner
315 
316 #endif // NAV2_THETA_STAR_PLANNER__THETA_STAR_HPP_
A 2D costmap provides a mapping between points in the world and their associated "costs".
Definition: costmap_2d.hpp:69
unsigned char getCost(unsigned int mx, unsigned int my) const
Get the cost of a cell in the costmap.
Definition: costmap_2d.cpp:265
std::priority_queue< tree_node *, std::vector< tree_node * >, comp > queue_
this is the priority queue (open_list) to select the next node to be expanded
Definition: theta_star.hpp:129
void initializePosn(int size_inc=0)
initialises the node_position_ vector by storing -1 as index for all points(x, y) within the limits o...
Definition: theta_star.cpp:225
double getHCost(const int &cx, const int &cy)
for the point(cx, cy), its heuristic cost is calculated by <heuristic_cost_parameter>*<euclidean dist...
Definition: theta_star.hpp:241
bool isUnsafeToPlan() const
checks whether the start and goal points have costmap costs greater than MAX_NON_OBSTACLE_COST
Definition: theta_star.hpp:103
bool withinLimits(const int &cx, const int &cy) const
checks if the given coordinates(cx, cy) lies within the map
Definition: theta_star.hpp:250
double getTraversalCost(const int &cx, const int &cy)
for the point(cx, cy), its traversal cost is calculated by <parameter>*(<actual_traversal_cost_from_c...
Definition: theta_star.hpp:219
bool isGoal(const tree_node &this_node) const
checks if the coordinates of a node is the goal or not
Definition: theta_star.hpp:259
void setStartAndGoal(const geometry_msgs::msg::PoseStamped &start, const geometry_msgs::msg::PoseStamped &goal)
initialises the values of the start and goal points
Definition: theta_star.cpp:35
std::vector< tree_node * > node_position_
Definition: theta_star.hpp:120
int size_x_
the x-directional and y-directional lengths of the map respectively
Definition: theta_star.hpp:68
void backtrace(std::vector< coordsW > &raw_points, const tree_node *curr_n) const
it returns the path by backtracking from the goal to the start, by using their parent nodes
Definition: theta_star.cpp:152
tree_node * getIndex(const int &cx, const int &cy)
retrieves the pointer of the location at which the data of the point(cx, cy) is stored in nodes_data
Definition: theta_star.hpp:283
void setNeighbors(const tree_node *curr_data)
this function expands the current node
Definition: theta_star.cpp:103
bool generatePath(std::vector< coordsW > &raw_path, std::function< bool()> cancel_checker)
it iteratively searches upon the nodes in the queue (open list) until the current node is the goal po...
Definition: theta_star.cpp:47
double getCost(const int &cx, const int &cy) const
this function scales the costmap cost by shifting the origin to 25 and then multiply the actual costm...
Definition: theta_star.hpp:208
bool isSafe(const int &cx, const int &cy) const
this function checks whether the cost of a point(cx, cy) on the costmap is less than or equal to the ...
Definition: theta_star.hpp:86
std::vector< tree_node > nodes_data_
Definition: theta_star.hpp:126
bool isSafe(const int &cx, const int &cy, double &cost) const
it is an overloaded function to ease the cost calculations while performing the LOS check
Definition: theta_star.hpp:187
void resetContainers()
initialises the values of global variables at beginning of the execution of the generatePath function
Definition: theta_star.cpp:206
void addIndex(const int &cx, const int &cy, tree_node *node_this)
it stores id_this in node_position_ at the index [ size_x_*cy + cx ]
Definition: theta_star.hpp:274
void clearQueue()
clears the priority queue after each execution of the generatePath function
Definition: theta_star.hpp:309
double getEuclideanCost(const int &ax, const int &ay, const int &bx, const int &by)
calculates the piecewise straight line euclidean distances by <euc_cost_parameter>*<euclidean distanc...
Definition: theta_star.hpp:231
void resetParent(tree_node *curr_data)
it performs a line of sight (los) check between the current node and the parent node of its parent no...
Definition: theta_star.cpp:84
void addToNodesData(const int &id_this)
this function depending on the size of the nodes_data_ vector allots space to store the data for a no...
Definition: theta_star.hpp:292
bool losCheck(const int &x0, const int &y0, const int &x1, const int &y1, double &sl_cost) const
performs the line of sight check using Bresenham's Algorithm, and has been modified to calculate the ...
Definition: theta_star.cpp:172
double w_traversal_cost
weight on the costmap traversal cost
double w_euc_cost
weight on the euclidean distance cost (used for calculations of g_cost)
double w_heuristic_cost
weight on the heuristic cost (used for h_cost calculations)
bool allow_unknown
parameter to set weather the planner can plan through unknown space