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  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  if (costmap_->getCost(cx, cy) == UNKNOWN_COST) {
194  curr_cost = OCCUPIED_COST - 1;
195  }
196  cost += params_->w_traversal_cost * curr_cost * curr_cost / MAX_NON_OBSTACLE_COST /
197  MAX_NON_OBSTACLE_COST;
198  return true;
199  } else {
200  return false;
201  }
202  }
203 
204  /*
205  * @brief this function scales the costmap cost by shifting the origin to 25 and then multiply
206  * the actual costmap cost by 0.9 to keep the output in the range of [25, 255)
207  */
208  inline double getCost(const int & cx, const int & cy) const
209  {
210  return 26 + 0.9 * costmap_->getCost(cx, cy);
211  }
212 
218  inline double getTraversalCost(const int & cx, const int & cy)
219  {
220  double curr_cost = getCost(cx, cy);
221  return params_->w_traversal_cost * curr_cost * curr_cost / MAX_NON_OBSTACLE_COST /
222  MAX_NON_OBSTACLE_COST;
223  }
224 
230  inline double getEuclideanCost(const int & ax, const int & ay, const int & bx, const int & by)
231  {
232  return params_->w_euc_cost * std::hypot(ax - bx, ay - by);
233  }
234 
240  inline double getHCost(const int & cx, const int & cy)
241  {
242  return params_->w_heuristic_cost * std::hypot(cx - dst_.x, cy - dst_.y);
243  }
244 
249  inline bool withinLimits(const int & cx, const int & cy) const
250  {
251  return cx >= 0 && cx < size_x_ && cy >= 0 && cy < size_y_;
252  }
253 
258  inline bool isGoal(const tree_node & this_node) const
259  {
260  return this_node.x == dst_.x && this_node.y == dst_.y;
261  }
262 
267  void initializePosn(int size_inc = 0);
268 
273  inline void addIndex(const int & cx, const int & cy, tree_node * node_this)
274  {
275  node_position_[size_x_ * cy + cx] = node_this;
276  }
277 
282  inline tree_node * getIndex(const int & cx, const int & cy)
283  {
284  return node_position_[size_x_ * cy + cx];
285  }
286 
291  void addToNodesData(const int & id_this)
292  {
293  if (static_cast<int>(nodes_data_.size()) <= id_this) {
294  nodes_data_.push_back({});
295  } else {
296  nodes_data_[id_this] = {};
297  }
298  }
299 
303  void resetContainers();
304 
308  void clearQueue()
309  {
310  queue_ = std::priority_queue<tree_node *, std::vector<tree_node *>, comp>();
311  }
312 };
313 } // namespace nav2_theta_star_planner
314 
315 #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:232
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:240
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:249
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:218
bool isGoal(const tree_node &this_node) const
checks if the coordinates of a node is the goal or not
Definition: theta_star.hpp:258
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:159
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:282
void setNeighbors(const tree_node *curr_data)
this function expands the current node
Definition: theta_star.cpp:110
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
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:213
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:273
void clearQueue()
clears the priority queue after each execution of the generatePath function
Definition: theta_star.hpp:308
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:230
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:91
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:291
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:179
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