Autonomy Software C++ 24.5.1
Welcome to the Autonomy Software repository of the Mars Rover Design Team (MRDT) at Missouri University of Science and Technology (Missouri S&T)! API reference contains the source code and other resources for the development of the autonomy software for our Mars rover. The Autonomy Software project aims to compete in the University Rover Challenge (URC) by demonstrating advanced autonomous capabilities and robust navigation algorithms.
Loading...
Searching...
No Matches
pathplanners::AStar Class Reference

Implements the A* (ASTAR) algorithm with the ability to plan paths around obstacles and provide path bias points that the algorithm will try to adhere to. More...

#include <AStar.h>

Collaboration diagram for pathplanners::AStar:

Classes

struct  Obstacle
 Struct to represent the obstacles that need to be avoided by the PlanAvoidanceRoute method. dRadius is meant to represent the estimated size of the obstacle in meters. More...
 

Public Member Functions

 AStar ()
 Construct a new AStar::AStar object.
 
 ~AStar ()
 Destroy the AStar::AStar object.
 
std::vector< geoops::UTMCoordinatePlanAvoidancePath (const geoops::UTMCoordinate &stStartCoordinate, const geoops::UTMCoordinate &stGoalCoordinate, const std::vector< sl::ObjectData > &vObstacles=std::vector< sl::ObjectData >())
 Called in the obstacle avoidance state to plan a path around obstacles blocking our path.
 
geoops::UTMCoordinate FindNearestBoundaryPoint (const geoops::UTMCoordinate &stGoalCoordinate)
 Helper function for the PlanAvoidancePath method. This method takes in a UTMCoordinate reference and uses class member variables to mutate the m_stGoalNode object's coordinates to represent the nearest boundary point.
 
geoops::UTMCoordinate RoundUTMCoordinate (const geoops::UTMCoordinate &stCoordinateToRound)
 Helper function used to round UTMCoordinates to the nearest constants::ASTAR_NODE_SIZE to avoid rounding errors when trying to determine if two nodes have the same location.
 
void ConstructPath (const nodes::AStarNode &stFinalNode)
 Called when a goal node has been reached. Recursively builds a vector of UTMCoordinates by tracing the parent pointers of AStarNodes. This function then saves that vector to m_vPathNodes.
 
void AddObstacle (const sl::ObjectData &slObstacle)
 This method is intended to be called when a new obstacle is detected from the ZedCam to add a new obstacle to be considered in path finding.
 
void AddObstacle (const Obstacle &stObstacle)
 This method is intended to be called when a new obstacle is detected to add a new obstacle to be considered in path finding.
 
void UpdateObstacleData (const std::vector< sl::ObjectData > &vObstacles, const bool &bClearObstacles=true)
 This method clears any saved obstacles in AStar, takes in a vector of sl::ObjectData objects and translates them to a UTMCoordinate and estimated size that is stored in the m_vObstacles vector.
 
void UpdateObstacleData (const std::vector< Obstacle > &vObstacles, const bool &bClearObstacles=true)
 This method clears any saved obstacles in AStar, takes in a vector of AStar::Obstacle and saves a copy to the m_vObstacles vector.
 
void ClearObstacleData ()
 Helper function to destroy objects from m_vObstacles.
 
const std::vector< ObstacleGetObstacleData ()
 
void SetStartCoordinate (const geoops::UTMCoordinate &stStart)
 
const std::vector< geoops::UTMCoordinateGetPath ()
 

Private Member Functions

std::string UTMCoordinateToString (const geoops::UTMCoordinate &stToTranslate)
 Helper function used to translate a UTMCoordinate's dEasting and dNorthing values into a string that can be hashed for the unordered_map data structure for O(1) lookup of nodes at a particular location.
 
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 obstacle is blocking the node or the node is outside the max boundary. Returns True otherwise, representing the node is a valid path to consider. To save memory and compute time, we only evaluate the doubles representing the coordinate.
 

Private Attributes

nodes::AStarNode m_stStartNode
 
nodes::AStarNode m_stGoalNode
 
std::vector< geoops::UTMCoordinatem_vPathCoordinates
 
std::vector< Obstaclem_vObstacles
 

Detailed Description

Implements the A* (ASTAR) algorithm with the ability to plan paths around obstacles and provide path bias points that the algorithm will try to adhere to.

Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-01

Constructor & Destructor Documentation

◆ AStar()

pathplanners::AStar::AStar ( )

Construct a new AStar::AStar object.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-02-01
39 {
40 // Nothing to do yet.
41 }

◆ ~AStar()

pathplanners::AStar::~AStar ( )

Destroy the AStar::AStar object.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-02-01
51 {
52 // Nothing to destroy yet.
53 }

Member Function Documentation

◆ PlanAvoidancePath()

std::vector< geoops::UTMCoordinate > pathplanners::AStar::PlanAvoidancePath ( const geoops::UTMCoordinate stStartCoordinate,
const geoops::UTMCoordinate stGoalCoordinate,
const std::vector< sl::ObjectData > &  vObstacles = std::vector<sl::ObjectData>() 
)

Called in the obstacle avoidance state to plan a path around obstacles blocking our path.

Parameters
stStartCoordinate- A UTMCoordinate reference that represents the start location.
stGoalCoordinate- A UTMCoordinate reference that represents the goal location.
vObstacles- A vector reference containing ObjectData objects from the ZEDCam class, defaults to an empty vector.
Returns
- A vector of UTMCoordinates representing the path calculated by ASTAR.
Todo:
Build a visualizer for testing.
Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-02
414 {
415 // Clear previous path data.
416 m_vPathCoordinates.clear();
417
418 // Translate Object data from camera and construct obstacle nodes.
419 // Stores Data in m_vObstacles.
420 UpdateObstacleData(vObstacles);
421
422 // Create start node.
423 m_stStartNode = nodes::AStarNode(nullptr, stStartCoordinate);
424 // Map the goalLocation to an edge node based on maximum search size.
425 geoops::UTMCoordinate stRoundedGoal(FindNearestBoundaryPoint(stGoalCoordinate));
426 // Create goal node.
427 m_stGoalNode = nodes::AStarNode(nullptr, stRoundedGoal);
428
429 // -------------------A* algorithm-------------------
430 // Create Open and Closed Lists.
431 // Using an additional unordered map is memory inefficient but allows for O(1)
432 // lookup of nodes based on their position rather than iterating over the heap.
433 // Carefully manage nodes between 'lists' to ensure data is consistent.
434
435 // Open list implemented as a min-heap queue for O(1) retrieval of the node with min dKf value.
436 // C++ utilizes the '*_heap' family of functions which operate on vectors.
437 std::vector<nodes::AStarNode> vOpenList;
438 std::make_heap(vOpenList.begin(), vOpenList.end(), std::greater<nodes::AStarNode>());
439 // Unordered map of coordinates for open list for O(1) lookup.
440 std::unordered_map<std::string, double> umOpenListLookup;
441
442 // Vector containing pointers to nodes on the closed list.
443 // This vector also contains the nodes that will be copied to m_vPathCoordinates.
444 std::vector<std::shared_ptr<nodes::AStarNode>> vClosedList;
445
446 // Unordered map of coordinates for closed list for O(1) lookup.
447 std::unordered_map<std::string, double> umClosedList;
448
449 // Place Starting node on open list.
450 vOpenList.push_back(m_stStartNode);
451 // Translate start node to string and add location on open list lookup map.
452 std::string szLocationString = UTMCoordinateToString(m_stStartNode.stNodeLocation);
453 umOpenListLookup.emplace(std::make_pair(szLocationString, 0.0));
454
455 // While open list is not empty:
456 while (!vOpenList.empty())
457 {
458 // Retrieve node with the minimum dKf on open list (Q).
459 std::pop_heap(vOpenList.begin(), vOpenList.end(), std::greater<nodes::AStarNode>());
460 nodes::AStarNode stNextParent = vOpenList.back();
461 // Pop Q off open list.
462 vOpenList.pop_back();
463 // Put Q on closed list to allocate parent pointers of successors.
464 // Note: make_shared creates a copy of stNextParent on the heap, and points to that copy.
465 vClosedList.push_back(std::make_shared<nodes::AStarNode>(stNextParent));
466
467 // Generate Q's 8 successors (neighbors), setting parent to Q.
468 std::vector<nodes::AStarNode> vSuccessors;
469
470 // Counter for avoiding parent duplication.
471 ushort usSuccessorTracker = 0;
472 for (int nEastingDirection = -1; nEastingDirection <= 1; nEastingDirection += 1)
473 {
474 for (int nNorthingDirection = -1; nNorthingDirection <= 1; nNorthingDirection += 1)
475 {
476 double dSuccessorEasting = stNextParent.stNodeLocation.dEasting + (nEastingDirection * constants::ASTAR_NODE_SIZE);
477 double dSuccessorNorthing = stNextParent.stNodeLocation.dNorthing + (nNorthingDirection * constants::ASTAR_NODE_SIZE);
478 // Skip duplicating the parent node.
479 // Implemented with a counter to avoid evaluating coordinates.
480 usSuccessorTracker++;
481 if (usSuccessorTracker == 5)
482 {
483 continue;
484 }
485
486 // Check for valid coordinate (check for boundary and obstacles).
487 if (!ValidCoordinate(dSuccessorEasting, dSuccessorNorthing))
488 {
489 continue;
490 }
491
492 // Otherwise create the successor.
493 // Copy data from parent coordinate.
494 geoops::UTMCoordinate stSuccessorCoordinate = stNextParent.stNodeLocation;
495
496 // Adjust Easting and Northing offsets to create new coordinate.
497 stSuccessorCoordinate.dEasting = dSuccessorEasting;
498 stSuccessorCoordinate.dNorthing = dSuccessorNorthing;
499 RoundUTMCoordinate(stSuccessorCoordinate);
500 // Create successor node, initialize values to 0 (done by constructor).
501 nodes::AStarNode stNextSuccessor(vClosedList.back(), stSuccessorCoordinate);
502 // Copy successor node to vector.
503 vSuccessors.emplace_back(stNextSuccessor);
504 }
505 }
506
507 // For each successor:
508 for (size_t i = 0; i < vSuccessors.size(); i++)
509 {
510 // Vars for distance evaluation.
511 bool bAtGoal = false;
512 double dDeltaEasting;
513 double dDeltaNorthing;
514
515 // If successor distance to goal is less than the node size, stop search.
516 // Try to calculate GeoMeasurement:
517 geoops::GeoMeasurement stDistanceToGoal = geoops::CalculateGeoMeasurement(vSuccessors[i].stNodeLocation, m_stGoalNode.stNodeLocation);
518 bool bGeoSuccess = stDistanceToGoal.dDistanceMeters > 0.01;
519
520 // If this succeeds, use the GeoMeasurement distance.
521 if (bGeoSuccess)
522 {
523 bAtGoal = stDistanceToGoal.dDistanceMeters < constants::ASTAR_NODE_SIZE;
524 }
525 // Otherwise manually check for goal boundaries:
526 else
527 {
528 dDeltaEasting = std::abs(vSuccessors[i].stNodeLocation.dEasting - m_stGoalNode.stNodeLocation.dEasting);
529 dDeltaNorthing = std::abs(vSuccessors[i].stNodeLocation.dNorthing - m_stGoalNode.stNodeLocation.dNorthing);
530 bAtGoal = dDeltaEasting < constants::ASTAR_NODE_SIZE && dDeltaNorthing < constants::ASTAR_NODE_SIZE;
531 }
532
533 // Construct and return path if we have reached the goal.
534 if (bAtGoal)
535 {
536 ConstructPath(vSuccessors[i]);
537 return m_vPathCoordinates;
538 }
539
540 // Create and format lookup string.
541 std::string szSuccessorLookup = UTMCoordinateToString(vSuccessors[i].stNodeLocation);
542
543 // Compute dKg, dKh, and dKf for successor.
544 // Calculate successor previous path cost.
545 vSuccessors[i].dKg = stNextParent.dKg + constants::ASTAR_NODE_SIZE;
546
547 // Calculate successor future path cost through geo measurement if successful:
548 if (bGeoSuccess)
549 {
550 vSuccessors[i].dKh = stDistanceToGoal.dDistanceMeters;
551 }
552 // Otherwise calculate euclidian distance manually.
553 else
554 {
555 vSuccessors[i].dKh = std::sqrt(std::pow(dDeltaEasting, 2) + std::pow(dDeltaNorthing, 2));
556 }
557
558 // f = g + h
559 vSuccessors[i].dKf = vSuccessors[i].dKg + vSuccessors[i].dKh;
560
561 // If a node with the same position as successor is in the open list and has a lower dKf, skip this successor.
562 if (umOpenListLookup.count(szSuccessorLookup))
563 {
564 if (umOpenListLookup[szSuccessorLookup] <= vSuccessors[i].dKf)
565 {
566 continue;
567 }
568 }
569
570 // If a node with the same position as successor is in the closed list and has a lower dKf, skip this successor.
571 if (umClosedList.count(szSuccessorLookup))
572 {
573 if (umClosedList[szSuccessorLookup] <= vSuccessors[i].dKf)
574 {
575 continue;
576 }
577 }
578
579 // Otherwise add successor node to open list.
580 // Add lookup string and dKf value to lookup map.
581 umOpenListLookup.emplace(std::make_pair(szSuccessorLookup, vSuccessors[i].dKf));
582 // Push to heap.
583 vOpenList.push_back(vSuccessors[i]);
584 std::push_heap(vOpenList.begin(), vOpenList.end(), std::greater<nodes::AStarNode>());
585 } // End For (each successor).
586
587 // Create and format lookup string.
588 std::string szParentLookup = UTMCoordinateToString(stNextParent.stNodeLocation);
589 // Push lookup string and dKf value to lookup map.
590 umClosedList.emplace(std::make_pair(szParentLookup, stNextParent.dKf));
591 } // End While(!vOpenList.empty).
592
593 // Function has failed to find a valid path.
594 LOG_ERROR(logging::g_qSharedLogger,
595 "ASTAR Failed to find a path from UTM point ({}, {}) to UTM point ({}, {})",
596 m_stStartNode.stNodeLocation.dEasting,
597 m_stStartNode.stNodeLocation.dNorthing,
598 m_stGoalNode.stNodeLocation.dEasting,
599 m_stGoalNode.stNodeLocation.dNorthing);
600 // Return empty vector and handle outside of class.
601 return m_vPathCoordinates;
602 }
geoops::UTMCoordinate RoundUTMCoordinate(const geoops::UTMCoordinate &stCoordinateToRound)
Helper function used to round UTMCoordinates to the nearest constants::ASTAR_NODE_SIZE to avoid round...
Definition AStar.cpp:362
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:300
void UpdateObstacleData(const std::vector< sl::ObjectData > &vObstacles, const bool &bClearObstacles=true)
This method clears any saved obstacles in AStar, takes in a vector of sl::ObjectData objects and tran...
Definition AStar.cpp:79
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:379
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:320
geoops::UTMCoordinate FindNearestBoundaryPoint(const geoops::UTMCoordinate &stGoalCoordinate)
Helper function for the PlanAvoidancePath method. This method takes in a UTMCoordinate reference and ...
Definition AStar.cpp:180
unsigned short ushort
GeoMeasurement CalculateGeoMeasurement(const GPSCoordinate &stCoord1, const GPSCoordinate &stCoord2)
The shortest path between two points on an ellipsoid at (lat1, lon1) and (lat2, lon2) is called the g...
Definition GeospatialOperations.hpp:445
This struct is used to store the distance, arc length, and relative bearing for a calculated geodesic...
Definition GeospatialOperations.hpp:82
This struct stores/contains information about a UTM coordinate.
Definition GeospatialOperations.hpp:244
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FindNearestBoundaryPoint()

geoops::UTMCoordinate pathplanners::AStar::FindNearestBoundaryPoint ( const geoops::UTMCoordinate stGoalCoordinate)

Helper function for the PlanAvoidancePath method. This method takes in a UTMCoordinate reference and uses class member variables to mutate the m_stGoalNode object's coordinates to represent the nearest boundary point.

Precondition
- m_stStartNode has been initialized with a UTMCoordinate representing the rover's current location.
Parameters
stGoalCoordinate- UTMCoordinate reference representing the current rover destination.
Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-15
181 {
182 // Create return value.
183 geoops::UTMCoordinate stBoundaryCoordinate = stGoalCoordinate;
184 // Determine components of the distance vector formed by the current location and goal.
185 const double dDeltaX = stGoalCoordinate.dEasting - m_stStartNode.stNodeLocation.dEasting;
186 const double dDeltaY = stGoalCoordinate.dNorthing - m_stStartNode.stNodeLocation.dNorthing;
187 const double dAbsoluteDeltaX = std::abs(dDeltaX);
188 const double dAbsoluteDeltaY = std::abs(dDeltaY);
189 short sDirection;
190
191 // Only calculate the boundary point if the goal is not within the search grid.
192 if (dAbsoluteDeltaX > constants::ASTAR_MAXIMUM_SEARCH_GRID || dAbsoluteDeltaY > constants::ASTAR_MAXIMUM_SEARCH_GRID)
193 {
194 // Determine which component is major.
195 // If |X| is longer than |Y|.
196 if (dAbsoluteDeltaX > dAbsoluteDeltaY)
197 {
198 // Calculate scale ratio of distance vectors (big / small).
199 const double dVectorRatio = dAbsoluteDeltaX / constants::ASTAR_MAXIMUM_SEARCH_GRID;
200 // Determine +/- value of major component for boundary distance vector.
201 sDirection = dDeltaX / dAbsoluteDeltaX;
202 // Calculate goal node X component to be the boundary value.
203 stBoundaryCoordinate.dEasting = m_stStartNode.stNodeLocation.dEasting + sDirection * constants::ASTAR_MAXIMUM_SEARCH_GRID;
204 // Determine +/- value of minor component for boundary distance vector.
205 // Edge case of dDeltaY = 0, set sDirection to 0.
206 (dDeltaY != 0) ? sDirection = dDeltaY / dAbsoluteDeltaY : sDirection = 0;
207 // Calculate goal node Y axis with scale ratio.
208 stBoundaryCoordinate.dNorthing = m_stStartNode.stNodeLocation.dNorthing + sDirection * dVectorRatio * dDeltaY;
209 }
210 // Else if |Y| is longer than |X|.
211 else if (dAbsoluteDeltaX < dAbsoluteDeltaY)
212 {
213 // Calculate scale ratio of distance vectors (big / small).
214 const double dVectorRatio = dAbsoluteDeltaY / constants::ASTAR_MAXIMUM_SEARCH_GRID;
215 // Determine +/- value of major component for boundary distance vector.
216 sDirection = dDeltaY / dAbsoluteDeltaY;
217 // Calculate goal node Y component to be the boundary value.
218 stBoundaryCoordinate.dNorthing = m_stStartNode.stNodeLocation.dNorthing + sDirection * constants::ASTAR_MAXIMUM_SEARCH_GRID;
219 // Determine +/- value of minor component for boundary distance vector.
220 // Edge case of dDeltaX = 0, set sDirection to 0.
221 (dDeltaX != 0) ? sDirection = dDeltaX / dAbsoluteDeltaX : sDirection = 0;
222 // Calculate goal node X axis with scale ratio.
223 stBoundaryCoordinate.dEasting = m_stStartNode.stNodeLocation.dEasting + sDirection * dVectorRatio * dDeltaX;
224 }
225 // Else |X| = |Y|, so pick a corner.
226 else
227 {
228 // Determine +/- value of X component.
229 sDirection = dDeltaX / dAbsoluteDeltaX;
230 // Calculate goal node X component to be the boundary value.
231 stBoundaryCoordinate.dEasting = m_stStartNode.stNodeLocation.dEasting + sDirection * constants::ASTAR_MAXIMUM_SEARCH_GRID;
232 // Determine +/- value of Y component.
233 sDirection = dDeltaY / dAbsoluteDeltaY;
234 // Calculate goal node Y component to be the boundary value.
235 stBoundaryCoordinate.dNorthing = m_stStartNode.stNodeLocation.dNorthing + sDirection * constants::ASTAR_MAXIMUM_SEARCH_GRID;
236 }
237 }
238
239 // In all cases, round the goal node's UTMCoordinate to align with grid for equality comparisons.
240 stBoundaryCoordinate = RoundUTMCoordinate(stBoundaryCoordinate);
241
242 // Handle edge case of an obstacle blocking the goal coordinate.
243 // For each obstacle:
244 for (size_t i = 0; i < m_vObstacles.size(); i++)
245 {
246 // Multiplier for avoidance radius.
247 double dAvoidanceRadius = constants::ASTAR_AVOIDANCE_MULTIPLIER * m_vObstacles[i].dRadius;
248 // Create obstacle borders.
249 double dEastObstacleBorder = m_vObstacles[i].stCenterPoint.dEasting + dAvoidanceRadius;
250 double dWestObstacleBorder = m_vObstacles[i].stCenterPoint.dEasting - dAvoidanceRadius;
251 double dNorthObstacleBorder = m_vObstacles[i].stCenterPoint.dNorthing + dAvoidanceRadius;
252 double dSouthObstacleBorder = m_vObstacles[i].stCenterPoint.dNorthing - dAvoidanceRadius;
253
254 // If goal node coordinate is within X axis obstacle borders.
255 if (dWestObstacleBorder < stBoundaryCoordinate.dEasting && stBoundaryCoordinate.dEasting < dEastObstacleBorder)
256 {
257 // Shift goal coordinate along X axis to avoid obstacle.
258 if (stBoundaryCoordinate.dEasting > m_vObstacles[i].stCenterPoint.dEasting)
259 {
260 stBoundaryCoordinate.dEasting = dEastObstacleBorder + constants::ASTAR_NODE_SIZE;
261 }
262 else
263 {
264 stBoundaryCoordinate.dEasting = dWestObstacleBorder - constants::ASTAR_NODE_SIZE;
265 }
266 stBoundaryCoordinate = RoundUTMCoordinate(stBoundaryCoordinate);
267 }
268
269 // If goal node coordinate is within Y axis obstacle borders.
270 if (dNorthObstacleBorder < m_stGoalNode.stNodeLocation.dNorthing && m_stGoalNode.stNodeLocation.dNorthing > dSouthObstacleBorder)
271 {
272 // Shift goal coordinate along Y axis to avoid obstacle.
273 if (stBoundaryCoordinate.dNorthing > m_vObstacles[i].stCenterPoint.dNorthing)
274 {
275 stBoundaryCoordinate.dNorthing = dNorthObstacleBorder + constants::ASTAR_NODE_SIZE;
276 }
277 else
278 {
279 stBoundaryCoordinate.dNorthing = dSouthObstacleBorder - constants::ASTAR_NODE_SIZE;
280 }
281 stBoundaryCoordinate = RoundUTMCoordinate(stBoundaryCoordinate);
282 }
283 }
284 // Return rounded coordinate.
285 return stBoundaryCoordinate;
286 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ RoundUTMCoordinate()

geoops::UTMCoordinate pathplanners::AStar::RoundUTMCoordinate ( const geoops::UTMCoordinate stCoordinateToRound)

Helper function used to round UTMCoordinates to the nearest constants::ASTAR_NODE_SIZE to avoid rounding errors when trying to determine if two nodes have the same location.

Parameters
stCoordinateToRound- A UTMCoordinate reference that will have its dNorthing and dEasting values mutated to round them to the nearest constants::ASTAR_NODE_SIZE.
Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-12
363 {
364 geoops::UTMCoordinate stRounded = geoops::UTMCoordinate(stCoordinateToRound);
365 stRounded.dEasting = std::round(stCoordinateToRound.dEasting / constants::ASTAR_NODE_SIZE) * constants::ASTAR_NODE_SIZE;
366 stRounded.dNorthing = std::round(stCoordinateToRound.dNorthing / constants::ASTAR_NODE_SIZE) * constants::ASTAR_NODE_SIZE;
367 return stRounded;
368 }
Here is the caller graph for this function:

◆ ConstructPath()

void pathplanners::AStar::ConstructPath ( const nodes::AStarNode stEndNode)

Called when a goal node has been reached. Recursively builds a vector of UTMCoordinates by tracing the parent pointers of AStarNodes. This function then saves that vector to m_vPathNodes.

Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-13
380 {
381 // Base case: Check for origin node.
382 if (stEndNode.pParentNode == nullptr)
383 {
384 // Start copying
385 m_vPathCoordinates.emplace_back(stEndNode.stNodeLocation);
386 return;
387 }
388 // Recursive case: call ConstructPath on parent pointer.
389 ConstructPath(*stEndNode.pParentNode);
390 // Copy node UTMCoordinate data to m_vPathNodes.
391 m_vPathCoordinates.emplace_back(stEndNode.stNodeLocation);
392 return;
393 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ AddObstacle() [1/2]

void pathplanners::AStar::AddObstacle ( const sl::ObjectData &  stObstacle)

This method is intended to be called when a new obstacle is detected from the ZedCam to add a new obstacle to be considered in path finding.

Parameters
stObstacle- A reference to an ObjectData struct representing the obstacle to add.
Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-15
139 {
140 // Create Obstacle struct.
141 Obstacle stObstacleToAdd;
142 // Extract coordinate data from ObjectData struct.
143 stObstacleToAdd.stCenterPoint.dEasting = stObstacle.position.x;
144 stObstacleToAdd.stCenterPoint.dNorthing = stObstacle.position.y;
145 // Extract size data from ObjectData and calculate size of obstacle.
146 // Assuming worst case scenario and calculating the maximum diagonal as object radius, optimize later?
147 stObstacleToAdd.dRadius = std::sqrt(std::pow(stObstacle.dimensions.x, 2) + std::pow(stObstacle.dimensions.y, 2));
148 // Copy Obstacle data to m_vObstacles for use in PlanAvoidancePath().
149 m_vObstacles.emplace_back(stObstacleToAdd);
150 }
Here is the caller graph for this function:

◆ AddObstacle() [2/2]

void pathplanners::AStar::AddObstacle ( const Obstacle stObstacle)

This method is intended to be called when a new obstacle is detected to add a new obstacle to be considered in path finding.

Parameters
stObstacle- A reference to an ObjectData struct representing the obstacle to add.
Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-15
163 {
164 m_vObstacles.emplace_back(stObstacle);
165 }

◆ UpdateObstacleData() [1/2]

void pathplanners::AStar::UpdateObstacleData ( const std::vector< sl::ObjectData > &  vObstacles,
const bool &  bClearObstacles = true 
)

This method clears any saved obstacles in AStar, takes in a vector of sl::ObjectData objects and translates them to a UTMCoordinate and estimated size that is stored in the m_vObstacles vector.

Parameters
vObstacles- A vector reference containing ObjectData objects from the ZEDCam class.
bClearObstacles- T/F indicating whether or not internal obstacle data should be cleared.
Todo:
Validate data being pulled from ObjectData structs.
Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-15
80 {
81 // Remove stale obstacle data.
82 if (bClearObstacles)
83 {
85 }
86 // For each object in vObstacles:
87 for (size_t i = 0; i < vObstacles.size(); i++)
88 {
89 // Create Obstacle struct.
90 Obstacle stObstacleToAdd;
91 // Extract coordinate data from ObjectData struct.
92 stObstacleToAdd.stCenterPoint.dEasting = vObstacles[i].position.x;
93 stObstacleToAdd.stCenterPoint.dNorthing = vObstacles[i].position.y;
94 // Extract size data from ObjectData and calculate size of obstacle.
95 // Assuming worst case scenario and calculating the maximum diagonal as object radius, optimize later?
96 stObstacleToAdd.dRadius = std::sqrt(std::pow(vObstacles[i].dimensions.x, 2) + std::pow(vObstacles[i].dimensions.y, 2));
97 // Copy Obstacle data to m_vObstacles for use in PlanAvoidancePath().
98 m_vObstacles.emplace_back(stObstacleToAdd);
99 }
100 }
void ClearObstacleData()
Helper function to destroy objects from m_vObstacles.
Definition AStar.cpp:61
Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateObstacleData() [2/2]

void pathplanners::AStar::UpdateObstacleData ( const std::vector< Obstacle > &  vObstacles,
const bool &  bClearObstacles = true 
)

This method clears any saved obstacles in AStar, takes in a vector of AStar::Obstacle and saves a copy to the m_vObstacles vector.

Parameters
vObstacles- A vector reference containing ObjectData objects from the ZEDCam class.
bClearObstacles- T/F indicating whether or not internal obstacle data should be cleared.
Todo:
Validate data being pulled from ObjectData structs.
Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-15
115 {
116 // Remove stale obstacle data.
117 if (bClearObstacles)
118 {
120 }
121 // For each object in vObstacles:
122 for (size_t i = 0; i < vObstacles.size(); i++)
123 {
124 m_vObstacles.emplace_back(vObstacles[i]);
125 }
126 }
Here is the call graph for this function:

◆ ClearObstacleData()

void pathplanners::AStar::ClearObstacleData ( )

Helper function to destroy objects from m_vObstacles.

Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-02
62 {
63 m_vObstacles.clear();
64 }
Here is the caller graph for this function:

◆ GetObstacleData()

const std::vector< Obstacle > pathplanners::AStar::GetObstacleData ( )
inline
73{ return m_vObstacles; };

◆ SetStartCoordinate()

void pathplanners::AStar::SetStartCoordinate ( const geoops::UTMCoordinate stStart)
inline
75{ m_stStartNode = nodes::AStarNode(nullptr, stStart); }

◆ GetPath()

const std::vector< geoops::UTMCoordinate > pathplanners::AStar::GetPath ( )
inline
80{ return m_vPathCoordinates; }

◆ UTMCoordinateToString()

std::string pathplanners::AStar::UTMCoordinateToString ( const geoops::UTMCoordinate stToTranslate)
private

Helper function used to translate a UTMCoordinate's dEasting and dNorthing values into a string that can be hashed for the unordered_map data structure for O(1) lookup of nodes at a particular location.

Parameters
stToTranslate- A UTMCoordinate struct reference containing the data to translate.
Returns
- A string containing the translated coordinate.
Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-05
301 {
302 std::string szTranslation = std::to_string(stToTranslate.dEasting);
303 szTranslation.append(std::to_string(stToTranslate.dNorthing));
304 return szTranslation;
305 }
Here is the caller graph for this function:

◆ ValidCoordinate()

bool pathplanners::AStar::ValidCoordinate ( const double &  dEasting,
const double &  dNorthing 
)
private

Helper function used to determine if a potential UTMCoordinate is valid. Returns False if there is an obstacle is blocking the node or the node is outside the max boundary. Returns True otherwise, representing the node is a valid path to consider. To save memory and compute time, we only evaluate the doubles representing the coordinate.

Parameters
dEasting- A const double reference representing a dEasting to evaluate.
dNorthing- A const double reference representing a dNorthing to evaluate.
Author
Kai Shafe (kasq5.nosp@m.m@um.nosp@m.syste.nosp@m.m.ed.nosp@m.u)
Date
2024-02-06
321 {
322 // For each obstacle.
323 for (size_t i = 0; i < m_vObstacles.size(); i++)
324 {
325 // Multiplier for avoidance radius.
326 double dAvoidanceRadius = constants::ASTAR_AVOIDANCE_MULTIPLIER * m_vObstacles[i].dRadius;
327 // Create obstacle borders.
328 double dEastObstacleBorder = m_vObstacles[i].stCenterPoint.dEasting + dAvoidanceRadius;
329 double dWestObstacleBorder = m_vObstacles[i].stCenterPoint.dEasting - dAvoidanceRadius;
330 double dNorthObstacleBorder = m_vObstacles[i].stCenterPoint.dNorthing + dAvoidanceRadius;
331 double dSouthObstacleBorder = m_vObstacles[i].stCenterPoint.dNorthing - dAvoidanceRadius;
332
333 // Return false if node is within obstacle borders.
334 if (dWestObstacleBorder < dEasting && dEasting < dEastObstacleBorder && dNorthObstacleBorder < dNorthing && dNorthing > dSouthObstacleBorder)
335 {
336 return false;
337 }
338 }
339
340 // Boundary check (Returns true if params indicate a coordinate inside of the search grid).
341 if (dEasting >= (m_stStartNode.stNodeLocation.dEasting - constants::ASTAR_MAXIMUM_SEARCH_GRID - constants::ASTAR_NODE_SIZE) &&
342 dEasting <= (m_stStartNode.stNodeLocation.dEasting + constants::ASTAR_MAXIMUM_SEARCH_GRID + constants::ASTAR_NODE_SIZE) &&
343 dNorthing >= (m_stStartNode.stNodeLocation.dNorthing - constants::ASTAR_MAXIMUM_SEARCH_GRID - constants::ASTAR_NODE_SIZE) &&
344 dNorthing <= (m_stStartNode.stNodeLocation.dNorthing + constants::ASTAR_MAXIMUM_SEARCH_GRID + constants::ASTAR_NODE_SIZE))
345 {
346 return true;
347 }
348 // Return false if boundary check failed.
349 return false;
350 }
Here is the caller graph for this function:

The documentation for this class was generated from the following files: