Called in the obstacle avoidance state to plan a path around obstacles blocking our path.
83 {
84
85 m_vPathCoordinates.clear();
86
87 m_bPathGenerationCancelled = false;
88
89
90 LOG_NOTICE(logging::g_qSharedLogger,
91 "ASTAR has started planning a path up to {} meters long with a node spacing of {} meters. Please wait...",
92 constants::ASTAR_MAX_SEARCH_GRID,
93 constants::ASTAR_NODE_SIZE);
94
95 m_tmStartTime = std::chrono::steady_clock::now();
96
97
99
100 m_stStartNode = nodes::AStarNode(nullptr, stRoundedStart.GetUTMCoordinate());
101
103
104 m_stGoalNode = nodes::AStarNode(nullptr, stRoundedGoal.GetUTMCoordinate());
105
106
107
108
109
110
111
112
113
114 std::vector<nodes::AStarNode> vOpenList;
115 std::make_heap(vOpenList.begin(), vOpenList.end(), std::greater<nodes::AStarNode>());
116
117 std::unordered_map<std::string, double> umOpenListLookup;
118
119
120
121 std::vector<std::shared_ptr<nodes::AStarNode>> vClosedList;
122
123
124 std::unordered_map<std::string, double> umClosedList;
125
126
127 vOpenList.push_back(m_stStartNode);
128
130 umOpenListLookup.emplace(std::make_pair(szLocationString, 0.0));
131
132
133 while (!vOpenList.empty())
134 {
135
136 if (m_bPathGenerationCancelled)
137 {
138
139 LOG_WARNING(logging::g_qSharedLogger, "ASTAR path generation has been cancelled.");
140
141 m_vPathCoordinates.clear();
142
143 return m_vPathCoordinates;
144 }
145
146
147 std::chrono::steady_clock::time_point tmCurrentTime = std::chrono::steady_clock::now();
148 std::chrono::duration<double> dElapsedTime = std::chrono::duration_cast<std::chrono::duration<double>>(tmCurrentTime - m_tmStartTime);
149 if (dElapsedTime.count() > constants::ASTAR_MAX_SEARCH_TIME)
150 {
151
152 LOG_WARNING(logging::g_qSharedLogger,
153 "ASTAR has exceeded the maximum search time of {} seconds. Path planning has been aborted.",
154 constants::ASTAR_MAX_SEARCH_TIME);
155
156 return m_vPathCoordinates;
157 }
158
159
160 std::pop_heap(vOpenList.begin(), vOpenList.end(), std::greater<nodes::AStarNode>());
161 nodes::AStarNode stNextParent = vOpenList.back();
162
163 vOpenList.pop_back();
164
165
166 vClosedList.push_back(std::make_shared<nodes::AStarNode>(stNextParent));
167
168
169 std::vector<nodes::AStarNode> vSuccessors;
170
171
172 for (int nEastingDirection = -1; nEastingDirection <= 1; nEastingDirection += 1)
173 {
174 for (int nNorthingDirection = -1; nNorthingDirection <= 1; nNorthingDirection += 1)
175 {
176
177 if (nEastingDirection == 0 && nNorthingDirection == 0)
178 {
179 continue;
180 }
181
182
183 double dSuccessorEasting = stNextParent.stNodeLocation.dEasting + (nEastingDirection * constants::ASTAR_NODE_SIZE);
184 double dSuccessorNorthing = stNextParent.stNodeLocation.dNorthing + (nNorthingDirection * constants::ASTAR_NODE_SIZE);
185
187 {
188 continue;
189 }
190
191
193
194
195 stSuccessorCoordinate.dEasting = dSuccessorEasting;
196 stSuccessorCoordinate.dNorthing = dSuccessorNorthing;
198
199 nodes::AStarNode stNextSuccessor(vClosedList.back(), stSuccessorCoordinate);
200
201 vSuccessors.emplace_back(stNextSuccessor);
202 }
203 }
204
205
206 for (size_t i = 0; i < vSuccessors.size(); i++)
207 {
208
209 bool bAtGoal = false;
210
211
212 double dDeltaGoalEasting = std::abs(vSuccessors[i].stNodeLocation.dEasting - m_stGoalNode.stNodeLocation.dEasting);
213 double dDeltaGoalNorthing = std::abs(vSuccessors[i].stNodeLocation.dNorthing - m_stGoalNode.stNodeLocation.dNorthing);
214 bAtGoal = dDeltaGoalEasting <= 0.1 && dDeltaGoalNorthing <= 0.1;
215
216
217 if (bAtGoal)
218 {
219
221
222 std::chrono::steady_clock::time_point tmEndTime = std::chrono::steady_clock::now();
223 std::chrono::duration<double> dElapsedTime = std::chrono::duration_cast<std::chrono::duration<double>>(tmEndTime - m_tmStartTime);
224
225 LOG_NOTICE(logging::g_qSharedLogger,
226 "ASTAR has successfully planned a path from UTM point ({}, {}) to UTM point ({}, {}) in {} seconds.",
227 m_stStartNode.stNodeLocation.dEasting,
228 m_stStartNode.stNodeLocation.dNorthing,
229 m_stGoalNode.stNodeLocation.dEasting,
230 m_stGoalNode.stNodeLocation.dNorthing,
231 dElapsedTime.count());
232
233 return m_vPathCoordinates;
234 }
235
236
238
240
242
243
244 double dDeltaParentEasting = vSuccessors[i].stNodeLocation.dEasting - stNextParent.stNodeLocation.dEasting;
245 double dDeltaParentNorthing = vSuccessors[i].stNodeLocation.dNorthing - stNextParent.stNodeLocation.dNorthing;
246 vSuccessors[i].dKg = stNextParent.dKg + std::sqrt(std::pow(dDeltaParentEasting, 2) + std::pow(dDeltaParentNorthing, 2));
247
248
249 vSuccessors[i].dKh = std::sqrt(std::pow(dDeltaGoalEasting, 2) + std::pow(dDeltaGoalNorthing, 2));
250
251
252 vSuccessors[i].dKf = vSuccessors[i].dKg + vSuccessors[i].dKh;
253
254
255 if (umClosedList.count(szSuccessorLookup))
256 {
257
258 continue;
259 }
260
261
262 if (umOpenListLookup.count(szSuccessorLookup))
263 {
264
265 if (vSuccessors[i].dKf < umOpenListLookup[szSuccessorLookup])
266 {
267
268 umOpenListLookup[szSuccessorLookup] = vSuccessors[i].dKf;
269
270
271
272 }
273
274
275 continue;
276 }
277
278
279 umOpenListLookup.emplace(std::make_pair(szSuccessorLookup, vSuccessors[i].dKf));
280 vOpenList.push_back(vSuccessors[i]);
281 std::push_heap(vOpenList.begin(), vOpenList.end(), std::greater<nodes::AStarNode>());
282 }
283
284
286
287 umClosedList.emplace(std::make_pair(szParentLookup, stNextParent.dKf));
288 }
289
290
291 std::chrono::steady_clock::time_point tmEndTime = std::chrono::steady_clock::now();
292 std::chrono::duration<double> dElapsedTime = std::chrono::duration_cast<std::chrono::duration<double>>(tmEndTime - m_tmStartTime);
293
294
295 LOG_ERROR(logging::g_qSharedLogger,
296 "After {} seconds, ASTAR Failed to find a path from UTM point ({}, {}) to UTM point ({}, {})",
297 dElapsedTime.count(),
298 m_stStartNode.stNodeLocation.dEasting,
299 m_stStartNode.stNodeLocation.dNorthing,
300 m_stGoalNode.stNodeLocation.dEasting,
301 m_stGoalNode.stNodeLocation.dNorthing);
302
303 return m_vPathCoordinates;
304 }
geoops::Waypoint FindNearestStartPoint(const geoops::UTMCoordinate &stStartCoordinate)
Helper function to round a UTMCoordinate to align with the grid.
Definition AStar.cpp:626
std::string UTMCoordinateToString(const geoops::UTMCoordinate &stToTranslate)
Helper function used to translate a UTMCoordinate's dEasting and dNorthing values into a string that ...
Definition AStar.cpp:717
geoops::Waypoint FindNearestGoalPoint(const geoops::UTMCoordinate &stGoalCoordinate)
Helper function for the PlanAvoidancePath method. This method takes in a UTMCoordinate reference and ...
Definition AStar.cpp:508
void ConstructPath(const nodes::AStarNode &stFinalNode)
Called when a goal node has been reached. Recursively builds a vector of UTMCoordinates by tracing th...
Definition AStar.cpp:794
bool ValidCoordinate(const double dEasting, const double dNorthing)
Helper function used to determine if a potential UTMCoordinate is valid. Returns False if there is an...
Definition AStar.cpp:737
void RoundUTMCoordinate(geoops::UTMCoordinate &stCoordinateToRound)
Helper function used to round UTMCoordinates to the nearest constants::ASTAR_NODE_SIZE to avoid round...
Definition AStar.cpp:779
This struct stores/contains information about a UTM coordinate.
Definition GeospatialOperations.hpp:195
This struct is used by the WaypointHandler class to store location, size, and type information about ...
Definition GeospatialOperations.hpp:392