Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
goal_manager.hpp
1 // Copyright (c) 2020, Samsung Research America
2 // Copyright (c) 2020, Applied Electric Vehicles Pty Ltd
3 // Copyright (c) 2024, Stevedan Ogochukwu Omodolor Omodia
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License. Reserved.
16 
17 #ifndef NAV2_SMAC_PLANNER__GOAL_MANAGER_HPP_
18 #define NAV2_SMAC_PLANNER__GOAL_MANAGER_HPP_
19 
20 #include <algorithm>
21 #include <functional>
22 #include <type_traits>
23 #include <unordered_set>
24 #include <vector>
25 
26 #include "nav2_smac_planner/types.hpp"
27 #include "nav2_smac_planner/node_2d.hpp"
28 #include "nav2_smac_planner/node_hybrid.hpp"
29 #include "nav2_smac_planner/node_lattice.hpp"
30 #include "nav2_smac_planner/node_basic.hpp"
31 #include "nav2_smac_planner/collision_checker.hpp"
32 
33 
34 namespace nav2_smac_planner
35 {
36 
41 template<typename NodeT>
43 {
44 public:
45  typedef NodeT * NodePtr;
46  typedef std::vector<NodePtr> NodeVector;
47  typedef std::unordered_set<NodePtr> NodeSet;
48  typedef std::vector<GoalState<NodeT>> GoalStateVector;
49  typedef typename NodeT::Coordinates Coordinates;
50  typedef typename NodeT::CoordinateVector CoordinateVector;
51  using NodeContext = typename NodeT::NodeContext;
52 
57  : _goals_set(NodeSet()),
58  _goals_state(GoalStateVector()),
59  _goals_coordinate(CoordinateVector()),
60  _ref_goal_coord(Coordinates())
61  {
62  }
63 
67  ~GoalManager() = default;
68 
73  void setContext(NodeContext * ctx)
74  {
75  _ctx = ctx;
76  }
77 
82  bool goalsIsEmpty()
83  {
84  return _goals_state.empty();
85  }
86 
91  void addGoal(NodePtr & goal)
92  {
93  _goals_state.push_back({goal, true});
94  }
95 
99  void clear()
100  {
101  _goals_set.clear();
102  _goals_state.clear();
103  _goals_coordinate.clear();
104  }
105 
113  NodeVector & coarse_check_goals, NodeVector & fine_check_goals,
114  int coarse_search_resolution)
115  {
116  for (unsigned int i = 0; i < _goals_state.size(); i++) {
117  if (_goals_state[i].is_valid) {
118  if (i % coarse_search_resolution == 0) {
119  coarse_check_goals.push_back(_goals_state[i].goal);
120  } else {
121  fine_check_goals.push_back(_goals_state[i].goal);
122  }
123  }
124  }
125  }
126 
138  const NodePtr node, const float & radius, GridCollisionChecker * collision_checker,
139  const bool & traverse_unknown) const
140  {
141  if (radius < 1) {
142  return false;
143  }
144 
145  const auto size_x = collision_checker->getCostmap()->getSizeInCellsX();
146  const auto size_y = collision_checker->getCostmap()->getSizeInCellsY();
147 
148  auto getIndexFromPoint = [this, &size_x](const Coordinates & point) {
149  unsigned int index = 0;
150 
151  const auto mx = static_cast<unsigned int>(point.x);
152  const auto my = static_cast<unsigned int>(point.y);
153 
154  if constexpr (!std::is_base_of_v<Node2D, NodeT>) {
155  const auto angle = static_cast<unsigned int>(point.theta);
156  index = NodeT::getIndex(mx, my, angle, _ctx->motion_table.size_x,
157  _ctx->motion_table.num_angle_quantization);
158  } else {
159  index = NodeT::getIndex(mx, my, size_x);
160  }
161 
162  return index;
163  };
164 
165  const Coordinates & center_point = node->pose;
166  const float min_x = std::max(0.0f, std::floor(center_point.x - radius));
167  const float min_y = std::max(0.0f, std::floor(center_point.y - radius));
168  const float max_x =
169  std::min(static_cast<float>(size_x - 1), std::ceil(center_point.x + radius));
170  const float max_y =
171  std::min(static_cast<float>(size_y - 1), std::ceil(center_point.y + radius));
172  const float radius_sq = radius * radius;
173 
174  Coordinates m;
175  for (m.x = min_x; m.x <= max_x; m.x += 1.0f) {
176  for (m.y = min_y; m.y <= max_y; m.y += 1.0f) {
177  const float dx = m.x - center_point.x;
178  const float dy = m.y - center_point.y;
179 
180  if (dx * dx + dy * dy > radius_sq) {
181  continue;
182  }
183 
184  NodeT current_node(getIndexFromPoint(m), _ctx);
185  current_node.setPose(m);
186 
187  if (current_node.isNodeValid(traverse_unknown, collision_checker)) {
188  return true;
189  }
190  }
191  }
192 
193  return false;
194  }
195 
206  const float & tolerance,
207  GridCollisionChecker * collision_checker,
208  const bool & traverse_unknown)
209  {
210  // Make sure that there was a goal clear before this was run
211  if (!_goals_set.empty() || !_goals_coordinate.empty()) {
212  throw std::runtime_error(
213  "Goal set should be cleared before calling "
214  "removeinvalidgoals");
215  }
216  for (unsigned int i = 0; i < _goals_state.size(); i++) {
217  if (_goals_state[i].goal->isNodeValid(traverse_unknown, collision_checker) ||
218  isZoneValid(_goals_state[i].goal, tolerance, collision_checker, traverse_unknown))
219  {
220  _goals_state[i].is_valid = true;
221  _goals_set.insert(_goals_state[i].goal);
222  _goals_coordinate.push_back(_goals_state[i].goal->pose);
223  } else {
224  _goals_state[i].is_valid = false;
225  }
226  }
227  }
228 
234  inline bool isGoal(const NodePtr & node)
235  {
236  return _goals_set.find(node) != _goals_set.end();
237  }
238 
243  inline NodeSet & getGoalsSet()
244  {
245  return _goals_set;
246  }
247 
252  inline GoalStateVector & getGoalsState()
253  {
254  return _goals_state;
255  }
256 
261  inline CoordinateVector & getGoalsCoordinates()
262  {
263  return _goals_coordinate;
264  }
265 
270  inline void setRefGoalCoordinates(const Coordinates & coord)
271  {
272  _ref_goal_coord = coord;
273  }
274 
280  inline bool hasGoalChanged(const Coordinates & coord)
281  {
288  return _ref_goal_coord != coord;
289  }
290 
291 protected:
292  NodeSet _goals_set;
293  GoalStateVector _goals_state;
294  CoordinateVector _goals_coordinate;
295  Coordinates _ref_goal_coord;
296  NodeContext * _ctx = nullptr;
297 };
298 
299 } // namespace nav2_smac_planner
300 
301 #endif // NAV2_SMAC_PLANNER__GOAL_MANAGER_HPP_
unsigned int getSizeInCellsX() const
Accessor for the x size of the costmap in cells.
Definition: costmap_2d.cpp:548
unsigned int getSizeInCellsY() const
Accessor for the y size of the costmap in cells.
Definition: costmap_2d.cpp:553
CostmapT getCostmap()
Get the current costmap object.
Responsible for managing multiple variables storing information on the goal.
GoalManager()
Constructor: Initializes empty goal state. sets and coordinate lists.
void setContext(NodeContext *ctx)
Sets the node context for goal nodes.
~GoalManager()=default
Destructor for the GoalManager.
bool isZoneValid(const NodePtr node, const float &radius, GridCollisionChecker *collision_checker, const bool &traverse_unknown) const
Checks if zone within the radius of a node is feasible. Returns true if there's at least one non-leth...
void removeInvalidGoals(const float &tolerance, GridCollisionChecker *collision_checker, const bool &traverse_unknown)
Filters and marks invalid goals based on collision checking and tolerance thresholds.
NodeSet & getGoalsSet()
Get pointer reference to goals set vector.
bool hasGoalChanged(const Coordinates &coord)
Checks whether the Reference goal coordinate has changed.
void addGoal(NodePtr &goal)
Adds goal to the goal vector.
void prepareGoalsForAnalyticExpansion(NodeVector &coarse_check_goals, NodeVector &fine_check_goals, int coarse_search_resolution)
Populates coarse and fine goal lists for analytic expansion.
GoalStateVector & getGoalsState()
Get pointer reference to goals state.
void setRefGoalCoordinates(const Coordinates &coord)
Set the Reference goal coordinate.
void clear()
Clears all internal goal data, including goals, states, and coordinates.
bool goalsIsEmpty()
Checks if the goals set is empty.
bool isGoal(const NodePtr &node)
Check if a given node is part of the goal set.
CoordinateVector & getGoalsCoordinates()
Get pointer reference to goals coordinates.
A costmap grid collision checker.
Implementation of coordinate2d structure.
Definition: types.hpp:224