selfdriving
TPS_Astar.h
Go to the documentation of this file.
1 /* -------------------------------------------------------------------------
2  * SelfDriving C++ library based on PTGs and mrpt-nav
3  * Copyright (C) 2019-2022 Jose Luis Blanco, University of Almeria
4  * See LICENSE for license information.
5  * ------------------------------------------------------------------------- */
6 
7 #pragma once
8 
10 #include <mpp/algos/Planner.h>
12 #include <mrpt/core/bits_math.h> // 0.0_deg
13 #include <mrpt/poses/CPose2DGridTemplate.h>
14 #include <mrpt/system/COutputLogger.h>
15 #include <mrpt/system/CTimeLogger.h>
16 
17 #include <limits>
18 #include <unordered_map>
19 
20 namespace mpp
21 {
22 using astar_heuristic_t = std::function<cost_t(
23  const SE2_KinState& /*from*/, const SE2orR2_KinState& /*goal*/)>;
24 
26 {
27  TPS_Astar_Parameters() = default;
28  static TPS_Astar_Parameters FromYAML(const mrpt::containers::yaml& c);
29 
30  double grid_resolution_xy = 0.20;
31  double grid_resolution_yaw = 5.0_deg;
32 
33  double SE2_metricAngleWeight = 1.0;
34 
35  double heuristic_heading_weight = 0.1; //!< [0,1]
36 
38  std::vector<duration_seconds_t> ptg_sample_timestamps = {1.0, 3.0, 5.0};
40 
41  /** Required to smooth interpolation of rendered paths, evaluation of
42  * path cost, etc.
43  * Even if this is 0, the interpolated path container `interpolatedPath`
44  * will contain the start and final pose, along with their times.
45  */
47 
48  /** 0:disabled */
51 
52  /** Maximum time to spend looking for a solution */
54  std::numeric_limits<duration_seconds_t>::max();
55 
56  mrpt::containers::yaml as_yaml();
57  void load_from_yaml(const mrpt::containers::yaml& c);
58 };
59 
60 /**
61  * Uses a SE(2) lattice to run an A* algorithm to find a kinematicaly feasible
62  * path from "A" to "B" using a set of trajectories in the form of PTGs.
63  *
64  */
65 class TPS_Astar : virtual public mrpt::system::COutputLogger, public Planner
66 {
67  DEFINE_MRPT_OBJECT(TPS_Astar, mpp)
68 
69  public:
70  TPS_Astar();
71  virtual ~TPS_Astar() = default;
72 
74 
75  PlannerOutput plan(const PlannerInput& in) override;
76 
77  mrpt::containers::yaml params_as_yaml() override
78  {
79  return params_.as_yaml();
80  }
81 
82  void params_from_yaml(const mrpt::containers::yaml& c) override
83  {
84  params_.load_from_yaml(c);
85  }
86 
87  cost_t default_heuristic(
88  const SE2_KinState& from, const SE2orR2_KinState& goal) const;
89 
90  cost_t default_heuristic_SE2(
91  const SE2_KinState& from, const mrpt::math::TPose2D& goal) const;
92  cost_t default_heuristic_R2(
93  const SE2_KinState& from, const mrpt::math::TPoint2D& goal) const;
94 
96  [this](const SE2_KinState& from, const SE2orR2_KinState& goal) {
97  return this->default_heuristic(from, goal);
98  });
99 
100  private:
101  struct NodeCoords
102  {
103  NodeCoords() = default;
104 
105  NodeCoords(int32_t ix, int32_t iy) : idxX(ix), idxY(iy) {}
106  NodeCoords(int32_t ix, int32_t iy, int32_t iphi)
107  : idxX(ix), idxY(iy), idxYaw(iphi)
108  {
109  }
110 
112  {
113  return {
114  idxX + o.idxX, idxY + o.idxY,
115  idxYaw.value() + o.idxYaw.value()};
116  }
117 
118  std::string asString() const
119  {
120  std::string r = "(";
121  r += std::to_string(idxX);
122  r += ",";
123  r += std::to_string(idxY);
124  if (idxYaw.has_value())
125  {
126  r += ",";
127  r += std::to_string(*idxYaw);
128  }
129  r += ")";
130  return r;
131  }
132 
133  bool operator==(const NodeCoords& o) const
134  {
135  if (idxX != o.idxX || idxY != o.idxY) return false;
136  if (idxYaw.has_value() != o.idxYaw.has_value()) return false;
137  if (idxYaw.has_value() && idxYaw.value() != o.idxYaw.value())
138  return false;
139  return true;
140  }
141  bool operator!=(const NodeCoords& o) const { return !(*this == o); }
142 
143  /** Returns true if:
144  * (1) two cells have heading and all (x,y,phi) are the same; or
145  * (2) at least one cell has no heading defined, and (x,y) are equal.
146  */
147  bool sameLocation(const NodeCoords& o) const
148  {
149  if (idxX != o.idxX || idxY != o.idxY) return false;
150  if (idxYaw.has_value() && o.idxYaw.has_value())
151  return idxYaw.value() == o.idxYaw.value();
152  // same (x,y), indifferent heading:
153  return true;
154  }
155 
156  /** Integer cell indices for (x,y) in `grid_` */
157  int32_t idxX = 0, idxY = 0;
158 
159  /** Phi or Yaw index in `grid_`, or none if undefined/arbitrary */
160  std::optional<int32_t> idxYaw;
161  };
162 
164  {
165  size_t operator()(const NodeCoords& x) const
166  {
167  size_t res = 17;
168  res = res * 31 + std::hash<int32_t>()(x.idxX);
169  res = res * 31 + std::hash<int32_t>()(x.idxY);
170  if (x.idxYaw)
171  res = res * 31 + std::hash<int32_t>()(x.idxYaw.value());
172  return res;
173  }
174  };
175 
176 #if 0
177  using nodes_with_exact_coordinates_t =
178  std::unordered_map<NodeCoords, SE2_KinState, NodeCoordsHash>;
179 #endif
180 
182  std::unordered_map<NodeCoords, normalized_speed_t, NodeCoordsHash>;
183 
184  using absolute_cell_index_t = size_t;
185 
187  {
188  return grid_.getSizeX() * grid_.getSizeY() * n.idxYaw.value() +
189  grid_.getSizeX() * n.idxY + n.idxX;
190  }
191 
192 #if 0
193  mrpt::math::TPose2D nodeCoordsToPose(
194  const NodeCoords& n,
195  const nodes_with_exact_coordinates_t& specialNodes) const
196  {
197  if (const auto it = specialNodes.find(n); it != specialNodes.end())
198  return it->second.pose;
199 
200  return {
201  grid_.idx2x(n.idxX), grid_.idx2y(n.idxY),
202  grid_.idx2phi(n.idxYaw.value())};
203  }
204 #endif
205 
206  /** Each of the nodes in the SE(2) lattice grid */
207  struct Node
208  {
209  Node() = default;
210  ~Node() = default;
211 
212  std::optional<mrpt::graphs::TNodeID> id;
213 
214  //!< exact pose and velocity (no binning here)
216 
217  /// Total cost from initialState to this node (default=Inf)
218  cost_t gScore = std::numeric_limits<cost_t>::max();
219 
220  /// Guess of cost from this node to goal (default=Inf)
221  cost_t fScore = std::numeric_limits<cost_t>::max();
222 
223  /// parent (precedent) of this node in the path.
224  std::optional<const Node*> cameFrom;
225 
226  bool pendingInOpenSet = false;
227  bool visited = false;
228  };
229 
230  mrpt::poses::CPose2DGridTemplate<Node> grid_;
231 
232  /// throws on out of grid limits.
233  /// Returns a ref to the node.
235  const mpp::SE2_KinState& p, mrpt::graphs::TNodeID& nextFreeId)
236  {
237  Node& n = *grid_.getByPos(p.pose.x, p.pose.y, p.pose.phi);
238  if (!n.id.has_value())
239  {
240  n.id = nextFreeId++;
241  n.state = p;
242  }
243 
244  return n;
245  }
246 
247  /// throws on out of grid limits.
248  NodeCoords nodeGridCoords(const mrpt::math::TPose2D& p) const
249  {
250  return NodeCoords(
251  grid_.x2idx(p.x), grid_.y2idx(p.y), grid_.phi2idx(p.phi));
252  }
253  NodeCoords nodeGridCoords(const mrpt::math::TPoint2D& p) const
254  {
255  return NodeCoords(grid_.x2idx(p.x), grid_.y2idx(p.y));
256  }
257 
258  struct NodePtr
259  {
260  NodePtr() = default;
261  ~NodePtr() = default;
262 
263  NodePtr(Node* p) : ptr(p) {}
264 
266  {
267  ASSERT_(ptr);
268  return ptr;
269  }
270  const Node* operator->() const
271  {
272  ASSERT_(ptr);
273  return ptr;
274  }
276  {
277  ASSERT_(ptr);
278  return *ptr;
279  }
280  const Node& operator*() const
281  {
282  ASSERT_(ptr);
283  return *ptr;
284  }
285 
286  Node* ptr = nullptr;
287  };
288 
290  {
291  std::optional<ptg_index_t> ptgIndex;
292  std::optional<trajectory_index_t> ptgTrajIndex;
293  std::optional<uint32_t> relTrgStep; //!< traj step index
294  std::optional<ptg_t::TNavDynamicState> ptgDynState;
295  normalized_speed_t ptgTrimmableSpeed = 1.0;
296  distance_t ptgDist = std::numeric_limits<distance_t>::max();
297  mrpt::math::TPose2D relReconstrPose;
299  };
300 
301  using list_paths_to_neighbors_t = std::vector<path_to_neighbor_t>;
302 
303  /** This generates a list of many potential neighbor cells to visit, subject
304  * to kinematic and dynamic limitations, and obstacle checking.
305  */
306  list_paths_to_neighbors_t find_feasible_paths_to_neighbors(
307  const Node& from, const TrajectoriesAndRobotShape& trs,
308  const SE2orR2_KinState& goalState,
309  const std::vector<mrpt::maps::CPointsMap::Ptr>& globalObstacles,
310  double MAX_XY_OBSTACLES_CLIPPING_DIST,
311  const nodes_with_desired_speed_t& nodesWithSpeed);
312 
313  mrpt::maps::CPointsMap::Ptr cached_local_obstacles(
314  const mrpt::math::TPose2D& queryPose,
315  const std::vector<mrpt::maps::CPointsMap::Ptr>& globalObstacles,
316  double MAX_PTG_XY_DIST);
317 };
318 
319 } // namespace mpp
Definition: TPS_Astar.h:25
mrpt::containers::yaml as_yaml()
std::optional< ptg_index_t > ptgIndex
Definition: TPS_Astar.h:291
Definition: TPS_Astar.h:65
double cost_t
Definition: basic_types.h:25
std::vector< path_to_neighbor_t > list_paths_to_neighbors_t
Definition: TPS_Astar.h:301
std::string asString() const
Definition: TPS_Astar.h:118
mrpt::poses::CPose2DGridTemplate< Node > grid_
Definition: TPS_Astar.h:230
Node & operator*()
Definition: TPS_Astar.h:275
void load_from_yaml(const mrpt::containers::yaml &c)
Definition: bestTrajectory.h:15
NodePtr(Node *p)
Definition: TPS_Astar.h:263
double duration_seconds_t
Definition: basic_types.h:36
NodeCoords nodeGridCoords(const mrpt::math::TPoint2D &p) const
Definition: TPS_Astar.h:253
std::optional< ptg_t::TNavDynamicState > ptgDynState
Definition: TPS_Astar.h:294
Definition: TPS_Astar.h:163
Definition: TPS_Astar.h:207
bool operator==(const NodeCoords &o) const
Definition: TPS_Astar.h:133
Definition: TrajectoriesAndRobotShape.h:25
uint32_t max_ptg_trajectories_to_explore
Definition: TPS_Astar.h:37
Node * operator->()
Definition: TPS_Astar.h:265
Definition: SE2_KinState.h:65
NodeCoords(int32_t ix, int32_t iy, int32_t iphi)
Definition: TPS_Astar.h:106
duration_seconds_t maximumComputationTime
Definition: TPS_Astar.h:53
std::optional< int32_t > idxYaw
Definition: TPS_Astar.h:160
double heuristic_heading_weight
[0,1]
Definition: TPS_Astar.h:35
Definition: PlannerInput.h:18
double distance_t
Definition: basic_types.h:16
bool sameLocation(const NodeCoords &o) const
Definition: TPS_Astar.h:147
mrpt::containers::yaml params_as_yaml() override
Definition: TPS_Astar.h:77
bool debugVisualizationShowEdgeCosts
Definition: TPS_Astar.h:50
static TPS_Astar_Parameters FromYAML(const mrpt::containers::yaml &c)
double SE2_metricAngleWeight
Definition: TPS_Astar.h:33
NodeCoords nodeGridCoords(const mrpt::math::TPose2D &p) const
throws on out of grid limits.
Definition: TPS_Astar.h:248
const Node & operator*() const
Definition: TPS_Astar.h:280
int32_t idxX
Definition: TPS_Astar.h:157
std::unordered_map< NodeCoords, normalized_speed_t, NodeCoordsHash > nodes_with_desired_speed_t
Definition: TPS_Astar.h:182
Definition: PlannerOutput.h:19
Definition: Planner.h:22
mrpt::math::TPose2D pose
global pose (x,y,phi)
Definition: SE2_KinState.h:69
mrpt::math::TPose2D relReconstrPose
Definition: TPS_Astar.h:297
size_t saveDebugVisualizationDecimation
Definition: TPS_Astar.h:49
Definition: TPS_Astar.h:101
double normalized_speed_t
Definition: basic_types.h:33
size_t absolute_cell_index_t
Definition: TPS_Astar.h:184
bool operator!=(const NodeCoords &o) const
Definition: TPS_Astar.h:141
uint32_t max_ptg_speeds_to_explore
Definition: TPS_Astar.h:39
absolute_cell_index_t nodeCoordsToAbsIndex(const NodeCoords &n) const
Definition: TPS_Astar.h:186
double grid_resolution_yaw
Definition: TPS_Astar.h:31
size_t operator()(const NodeCoords &x) const
Definition: TPS_Astar.h:165
std::optional< uint32_t > relTrgStep
traj step index
Definition: TPS_Astar.h:293
NodeCoords operator+(const NodeCoords &o) const
Definition: TPS_Astar.h:111
std::optional< mrpt::graphs::TNodeID > id
exact pose and velocity (no binning here)
Definition: TPS_Astar.h:212
void params_from_yaml(const mrpt::containers::yaml &c) override
Definition: TPS_Astar.h:82
std::vector< duration_seconds_t > ptg_sample_timestamps
Definition: TPS_Astar.h:38
std::optional< trajectory_index_t > ptgTrajIndex
Definition: TPS_Astar.h:292
Node & getOrCreateNodeByPose(const mpp::SE2_KinState &p, mrpt::graphs::TNodeID &nextFreeId)
Definition: TPS_Astar.h:234
SE2_KinState state
Definition: TPS_Astar.h:215
Definition: TPS_Astar.h:289
NodeCoords neighborNodeCoords
Definition: TPS_Astar.h:298
const Node * operator->() const
Definition: TPS_Astar.h:270
int32_t idxY
Definition: TPS_Astar.h:157
TPS_Astar_Parameters params_
Definition: TPS_Astar.h:73
Definition: TPS_Astar.h:258
std::function< cost_t(const SE2_KinState &, const SE2orR2_KinState &)> astar_heuristic_t
Definition: TPS_Astar.h:23
double grid_resolution_xy
Definition: TPS_Astar.h:30
Definition: SE2_KinState.h:75
size_t pathInterpolatedSegments
Definition: TPS_Astar.h:46
NodeCoords(int32_t ix, int32_t iy)
Definition: TPS_Astar.h:105
std::optional< const Node * > cameFrom
parent (precedent) of this node in the path.
Definition: TPS_Astar.h:224