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::GeoPlanner Class Reference

This class implements a geospatial path planner that uses a discrete 2.5D Costmap and a fast Weighted A* algorithm with Kinematic Constraints to find the optimal path through complex terrain between two coordinates. All tunable heuristics and parameters are accessible via constructor initialization. More...

#include <GeoPlanner.h>

Collaboration diagram for pathplanners::GeoPlanner:

Classes

struct  GridCell
 Represents a single cell in our 2.5D discretized Costmap grid. This is used to aggregate sparse point cloud data into a unified, easy-to-search surface for the A* algorithm. More...
 
struct  PlannerState
 This struct represents the state of a node in the A* algorithm. Optimized to work with a flat 1D vector instead of a hash map to prevent heavy heap allocations and memory fragmentation. More...
 
struct  PlannerStateCompare
 This struct is used to compare two PlannerState objects based on their cost to properly sort the priority queue. More...
 
struct  TileKey
 This struct represents a tile key in the implicit graph representation. We divide the plan into a regular grid of tiles of size dTileSize*dTileSize meters. More...
 
struct  TileKeyEqual
 This struct is used to compare two TileKey objects for equality after a hash collision is triggered. More...
 
struct  TileKeyHash
 This struct is used to hash TileKey objects for use in unordered maps. More...
 

Public Member Functions

 GeoPlanner (double dTileSize=50.0, double dGridResolution=0.5, double dHeuristicWeight=1.5, double dBetaBias=1.0, double dMinTravScore=0.0, int nDilationPasses=2, double dSafeTravScoreThreshold=0.5, int nMaxSpiralSearchRadius=20, size_t siMaxPlotPointsPerTile=10, double dPenaltyScalingFactor=10.0, double dPenaltyPower=2.0, double dPathWaypointTolerance=0.5)
 Construct a new Geo Planner:: Geo Planner object. Initializes all complex algorithms and mathematical hyperparameters to avoid explicitly hardcoded magic numbers logic.
 
 ~GeoPlanner ()
 Destroy the Geo Planner:: Geo Planner object.
 
std::vector< geoops::WaypointPlanPath (LiDARHandler *pLiDARHandler, const geoops::UTMCoordinate &stStart, const geoops::UTMCoordinate &stEnd, double dSearchRadius=3.0, double dMaxSearchTimeSeconds=120.0, double dCorridorPadding=100.0)
 Plan an optimal trajectory path from the start UTM to the end UTM coordinate utilizing a 2.5D hierarchical Costmap grid representation.
 
void ClearGeoCache ()
 Explicitly zeroes and reclaims internal spatial database mapping arrays.
 
void UnloadLiDARTiles (double minX, double maxX, double minY, double maxY)
 Unload tile LiDAR data.
 
void SetTileSize (double dTileSize)
 Sets the dimensional size of database tiles mapped during planning.
 
void SetMinTravScore (double dMinTravScore)
 Sets the absolute minimum travel score required for a valid cell.
 
void SetBetaBias (double dBetaBias)
 Sets the algorithm's penalty sensitivity bias multiplier.
 
double GetTileSize () const
 Retrieves the currently configured database tile size constraint.
 
double GetMinTravScore () const
 Retrieves the actively configured minimum travel score parameter limit.
 
double GetBetaBias () const
 Retrieves the beta heuristic bias factor configured dynamically.
 

Private Member Functions

bool PreloadCorridorAndBuildGrid (const geoops::UTMCoordinate &stStart, const geoops::UTMCoordinate &stEnd)
 Calculates a bounding box based on Start and End coordinates, preloads LiDAR chunks, and structures them down into a contiguous 1D Costmap vector.
 
void SearchAStar ()
 Actively runs a highly optimized Weighted A* pathfinding search upon the 1D Costmap grid utilizing kinematic 3D spatial awareness.
 
std::vector< geoops::WaypointReconstructPath () const
 Transforms the abstract 1D computational grid configurations logically backward to rebuild a continuous stream of actionable UTM Geographic sequences.
 
void CheckAndLoadTile (int nTileX, int nTileY)
 Checks if a specific tile is loaded in the cache, and if not, fetches the relevant LiDAR point cloud data into memory.
 
void FillGridHoles ()
 Performs morphological dilation on the costmap to fill in structural voids or gaps caused by sparse LiDAR data collections.
 
int FindNearestValidCell (int nStartIndex) const
 Expands outward concentrically from a target grid cell to locate the nearest neighboring cell that contains valid and safe traversal structures.
 
double EuclideanDistance (double dEasting1, double dNorthing1, double dEasting2, double dNorthing2) const
 Calculates the standard 2D Euclidean distance between two geographic coordinates. This establishes mathematically admissible baseline heuristic bounds for A*.
 
int GetGridIndex (int nX, int nY) const
 Inline helper to convert 2D grid coordinates to a 1D vector index.
 
void GetGridCoords (int nIndex, int &nX, int &nY) const
 Inline helper to convert a 1D vector index back into 2D grid coordinates.
 

Private Attributes

const std::function< void(const rovecomm::RoveCommPacket< float > &, const sockaddr_in &)> fnMinTravScoreCallback
 Callback function used to set the minimum travel score for path planning.
 
const std::function< void(const rovecomm::RoveCommPacket< float > &, const sockaddr_in &)> fnBetaBiasCallback
 Callback function used to set the beta bias for travel scores in path planning.
 
double m_dTileSize
 
double m_dGridResolution
 
double m_dHeuristicWeight
 
double m_dBeta
 
double m_dMinTravScore
 
int m_nDilationPasses
 
double m_dSafeTravScoreThreshold
 
int m_nMaxSpiralSearchRadius
 
size_t m_siMaxPlotPointsPerTile
 
double m_dPenaltyScalingFactor
 
double m_dPenaltyPower
 
double m_dPathWaypointTolerance
 
double m_dSearchRadius
 
double m_dMaxSearchTimeSeconds
 
double m_dCorridorPadding
 
LiDARHandlerm_pLiDARHandler
 
std::mutex m_muPathGenMutex
 
double m_dGridOriginEasting
 
double m_dGridOriginNorthing
 
int m_nGridWidth
 
int m_nGridHeight
 
int m_nStartIndex
 
int m_nEndIndex
 
std::vector< GridCellm_vCostmap
 
std::priority_queue< PlannerState, std::vector< PlannerState >, PlannerStateComparem_pqOpenSetNextBest
 
std::vector< int > m_vPredecessors
 
std::vector< bool > m_vbClosedSet
 
std::vector< double > m_vdGCosts
 
std::unordered_map< TileKey, std::vector< LiDARHandler::PointRow >, TileKeyHash, TileKeyEqualm_umTileMapCache
 

Detailed Description

This class implements a geospatial path planner that uses a discrete 2.5D Costmap and a fast Weighted A* algorithm with Kinematic Constraints to find the optimal path through complex terrain between two coordinates. All tunable heuristics and parameters are accessible via constructor initialization.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14

Constructor & Destructor Documentation

◆ GeoPlanner()

pathplanners::GeoPlanner::GeoPlanner ( double  dTileSize = 50.0,
double  dGridResolution = 0.5,
double  dHeuristicWeight = 1.5,
double  dBetaBias = 1.0,
double  dMinTravScore = 0.0,
int  nDilationPasses = 2,
double  dSafeTravScoreThreshold = 0.5,
int  nMaxSpiralSearchRadius = 20,
size_t  siMaxPlotPointsPerTile = 10,
double  dPenaltyScalingFactor = 10.0,
double  dPenaltyPower = 2.0,
double  dPathWaypointTolerance = 0.5 
)

Construct a new Geo Planner:: Geo Planner object. Initializes all complex algorithms and mathematical hyperparameters to avoid explicitly hardcoded magic numbers logic.

Parameters
dTileSize- The size of each database tile block loaded in meters.
dGridResolution- Metric scale of an individual discrete costmap cell.
dHeuristicWeight- The A* bias weight to accelerate goal seeking behaviors.
dBetaBias- Baseline beta algorithmic multiplier for penalizing bad terrain.
dMinTravScore- Absolute required lower bound on traversal values to be considered usable pathing terrain.
nDilationPasses- Number of morphological loop passes executed to fill void structures in sparse point clouds.
dSafeTravScoreThreshold- Baseline score requirement applied when attempting to snap stray origin coordinates.
nMaxSpiralSearchRadius- Max concentric rings expanded when searching for safe origin snapping structures.
siMaxPlotPointsPerTile- Rendering density constraint to prevent visualizer overload.
dPenaltyScalingFactor- Multiplier intensifying standard penalty math strictly during node score resolution.
dPenaltyPower- Exponential scaler applied universally to mathematically discourage steep or dangerous zones.
dPathWaypointTolerance- Native radius value embedded into actively returned planned telemetry sequence nodes.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-09-24
59 {
60 // Initialize member variables from constructor arguments.
61 m_dTileSize = dTileSize;
62 m_dGridResolution = dGridResolution;
63 m_dHeuristicWeight = dHeuristicWeight;
64 m_dBeta = dBetaBias;
65 m_dMinTravScore = dMinTravScore;
66 m_nDilationPasses = nDilationPasses;
67 m_dSafeTravScoreThreshold = dSafeTravScoreThreshold;
68 m_nMaxSpiralSearchRadius = nMaxSpiralSearchRadius;
69 m_siMaxPlotPointsPerTile = siMaxPlotPointsPerTile;
70 m_dPenaltyScalingFactor = dPenaltyScalingFactor;
71 m_dPenaltyPower = dPenaltyPower;
72 m_dPathWaypointTolerance = dPathWaypointTolerance;
73
74 // Initialize resource pointers and request-specific variables.
75 m_pLiDARHandler = nullptr;
76 m_dSearchRadius = 0.0;
77 m_dMaxSearchTimeSeconds = 0.0;
78 m_dCorridorPadding = 0.0;
79
80 // Bind RoveComm UDP Node network callbacks if available.
81 if (network::g_pRoveCommUDPNode != nullptr)
82 {
83 network::g_pRoveCommUDPNode->AddUDPCallback<float>(fnMinTravScoreCallback, manifest::Autonomy::COMMANDS.find("SETMINTRAVSCORE")->second.DATA_ID);
84 network::g_pRoveCommUDPNode->AddUDPCallback<float>(fnBetaBiasCallback, manifest::Autonomy::COMMANDS.find("SETBETABIAS")->second.DATA_ID);
85 }
86
87 LOG_INFO(logging::g_qSharedLogger, "GeoPlanner initialized successfully with a defined tile fetch size of {} meters.", std::to_string(m_dTileSize));
88 }
const std::function< void(const rovecomm::RoveCommPacket< float > &, const sockaddr_in &)> fnMinTravScoreCallback
Callback function used to set the minimum travel score for path planning.
Definition GeoPlanner.h:256
const std::function< void(const rovecomm::RoveCommPacket< float > &, const sockaddr_in &)> fnBetaBiasCallback
Callback function used to set the beta bias for travel scores in path planning.
Definition GeoPlanner.h:279

◆ ~GeoPlanner()

pathplanners::GeoPlanner::~GeoPlanner ( )

Destroy the Geo Planner:: Geo Planner object.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-09-27
97 {
98 // Smart pointers and standard containers clean themselves up automatically.
99 }

Member Function Documentation

◆ PlanPath()

std::vector< geoops::Waypoint > pathplanners::GeoPlanner::PlanPath ( LiDARHandler pLiDARHandler,
const geoops::UTMCoordinate stStart,
const geoops::UTMCoordinate stEnd,
double  dSearchRadius = 3.0,
double  dMaxSearchTimeSeconds = 120.0,
double  dCorridorPadding = 100.0 
)

Plan an optimal trajectory path from the start UTM to the end UTM coordinate utilizing a 2.5D hierarchical Costmap grid representation.

Parameters
pLiDARHandler- Pointer to the LiDARHandler database instance for fetching geospatial data.
stStart- The desired starting UTM geographic coordinate representation.
stEnd- The ultimate destination UTM geographic coordinate representation.
dSearchRadius- Padding base radius used to compute bounds.
dMaxSearchTimeSeconds- The absolute maximum CPU time in seconds allocated to search attempts.
dCorridorPadding- The extended corridor buffer dimension appended dynamically outside raw bounds.
Returns
std::vector<geoops::Waypoint> - The sequentially planned traversal path configurations.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-09-28
122 {
123 // Acquire a thread mutex lock to prevent concurrent path planning operations from corrupting internal state.
124 std::lock_guard<std::mutex> lkPathLock(m_muPathGenMutex);
125
126 // Secure external variables into local class state for this search pass.
127 m_pLiDARHandler = pLiDARHandler;
128 m_dSearchRadius = dSearchRadius;
129 m_dMaxSearchTimeSeconds = dMaxSearchTimeSeconds;
130 m_dCorridorPadding = dCorridorPadding;
131
132 LOG_NOTICE(logging::g_qSharedLogger,
133 "Starting GeoPlanner path planning from ({:.2f}, {:.2f}) to ({:.2f}, {:.2f}) with algorithmic beta: {}, minimum score threshold: {}.",
134 stStart.dEasting,
135 stStart.dNorthing,
136 stEnd.dEasting,
137 stEnd.dNorthing,
138 m_dBeta,
139 m_dMinTravScore);
140
141 // Sanity check the beta multiplier to avoid dividing by zero or disabling penalty tracking.
142 if (m_dBeta <= 0.0)
143 {
144 m_dBeta = 0.001;
145 LOG_WARNING(logging::g_qSharedLogger, "GeoPlanner: supplied dBeta bias {} is mathematically invalid; utilizing fallback logic 0.001.", m_dBeta);
146 }
147
148 // Store execution start time to profile algorithmic bottlenecks.
149 std::chrono::time_point<std::chrono::high_resolution_clock> tmStartTime = std::chrono::high_resolution_clock::now();
150
151 // Step 1: Preload the bounding box tiles and construct the dense high-res abstract costmap grid matrices.
152 if (!this->PreloadCorridorAndBuildGrid(stStart, stEnd))
153 {
154 LOG_ERROR(logging::g_qSharedLogger, "Failed to initialize the search grid. Aborting pathfinding routine.");
155 return {};
156 }
157
158 std::chrono::time_point<std::chrono::high_resolution_clock> tmAfterInit = std::chrono::high_resolution_clock::now();
159 std::chrono::duration<double> dInitDurationSeconds = tmAfterInit - tmStartTime;
160 LOG_INFO(logging::g_qSharedLogger, "GeoPlanner Grid Generation phase mapped within {:.6f} seconds.", dInitDurationSeconds.count());
161
162 // Step 2: Formally run the highly optimized Weighted A* search logic.
163 this->SearchAStar();
164
165 std::chrono::time_point<std::chrono::high_resolution_clock> tmAfterSearch = std::chrono::high_resolution_clock::now();
166 std::chrono::duration<double> dSearchDurationSeconds = tmAfterSearch - tmAfterInit;
167 LOG_INFO(logging::g_qSharedLogger, "GeoPlanner A* Grid Node Expansion executed within {:.6f} seconds.", dSearchDurationSeconds.count());
168
169 // Step 3: Integrate and rebuild exact geographic sequences tracking backwards from the goal.
170 std::vector<geoops::Waypoint> vPath = this->ReconstructPath();
171
172 std::chrono::time_point<std::chrono::high_resolution_clock> tmEndTime = std::chrono::high_resolution_clock::now();
173 std::chrono::duration<double> dOverallDurationSeconds = tmEndTime - tmStartTime;
174 LOG_NOTICE(logging::g_qSharedLogger,
175 "GeoPlanner total end-to-end path routing executed within {:.6f} seconds rendering {} waypoints.",
176 dOverallDurationSeconds.count(),
177 vPath.size());
178
179 return vPath;
180 }
std::vector< geoops::Waypoint > ReconstructPath() const
Transforms the abstract 1D computational grid configurations logically backward to rebuild a continuo...
Definition GeoPlanner.cpp:589
bool PreloadCorridorAndBuildGrid(const geoops::UTMCoordinate &stStart, const geoops::UTMCoordinate &stEnd)
Calculates a bounding box based on Start and End coordinates, preloads LiDAR chunks,...
Definition GeoPlanner.cpp:285
void SearchAStar()
Actively runs a highly optimized Weighted A* pathfinding search upon the 1D Costmap grid utilizing ki...
Definition GeoPlanner.cpp:454
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ClearGeoCache()

void pathplanners::GeoPlanner::ClearGeoCache ( )

Explicitly zeroes and reclaims internal spatial database mapping arrays.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-09-27
189 {
190 // Acquire a thread mutex lock to guarantee safety during cache wipes.
191 std::lock_guard<std::mutex> lkResourceLock(m_muPathGenMutex);
192 m_umTileMapCache.clear();
193 }

◆ UnloadLiDARTiles()

void pathplanners::GeoPlanner::UnloadLiDARTiles ( double  minX,
double  maxX,
double  minY,
double  maxY 
)

Unload tile LiDAR data.

Parameters
minX- Minimum x coordinate of tile range.
maxX- Maximum x coordinate of tile range.
minY- Minimum y coordinate of tile range.
maxY- Maximum y coordinate of tile range.
Author
Sam Nolte (samno.nosp@m.lte0.nosp@m.302@g.nosp@m.mail.nosp@m..com)
Date
2025-03-01
743 {
744 int nMinTileX = static_cast<int>(std::floor(minX / m_dTileSize));
745 int nMinTileY = static_cast<int>(std::floor(minY / m_dTileSize));
746 int nMaxTileX = static_cast<int>(std::floor(maxX / m_dTileSize));
747 int nMaxTileY = static_cast<int>(std::floor(maxY / m_dTileSize));
748
749 std::list<TileKey> tileKeys;
750 for (int i = 0; i < nMaxTileX - nMinTileX + 1; ++i)
751 for (int j = 0; j < nMaxTileY - nMinTileY + 1; ++j)
752 tileKeys.push_back(TileKey{nMinTileX + i, nMinTileY + j});
753
754 for (std::list<TileKey>::iterator it = tileKeys.begin(); it != tileKeys.end(); ++it)
755 {
756 // Make sure tile is actually loaded
757 if (m_umTileMapCache.find(*it) == m_umTileMapCache.end())
758 {
759 continue;
760 }
761
762 m_umTileMapCache.erase(*it);
763 }
764 }

◆ SetTileSize()

void pathplanners::GeoPlanner::SetTileSize ( double  dTileSize)

Sets the dimensional size of database tiles mapped during planning.

Parameters
dTileSize- The block size in meters.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
204 {
205 m_dTileSize = dTileSize;
206 }

◆ SetMinTravScore()

void pathplanners::GeoPlanner::SetMinTravScore ( double  dMinTravScore)

Sets the absolute minimum travel score required for a valid cell.

Parameters
dMinTravScore- Minimum permissible score limit.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
217 {
218 m_dMinTravScore = dMinTravScore;
219 }

◆ SetBetaBias()

void pathplanners::GeoPlanner::SetBetaBias ( double  dBetaBias)

Sets the algorithm's penalty sensitivity bias multiplier.

Parameters
dBetaBias- Baseline beta algorithmic multiplier.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
230 {
231 m_dBeta = dBetaBias;
232 }

◆ GetTileSize()

double pathplanners::GeoPlanner::GetTileSize ( ) const

Retrieves the currently configured database tile size constraint.

Returns
double - Tile size mapped dimension in meters.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
243 {
244 return m_dTileSize;
245 }

◆ GetMinTravScore()

double pathplanners::GeoPlanner::GetMinTravScore ( ) const

Retrieves the actively configured minimum travel score parameter limit.

Returns
double - The active lowest traversal score permissible.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
256 {
257 return m_dMinTravScore;
258 }

◆ GetBetaBias()

double pathplanners::GeoPlanner::GetBetaBias ( ) const

Retrieves the beta heuristic bias factor configured dynamically.

Returns
double - Scaler factor penalizing bad terrain paths mathematically.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
269 {
270 return m_dBeta;
271 }

◆ PreloadCorridorAndBuildGrid()

bool pathplanners::GeoPlanner::PreloadCorridorAndBuildGrid ( const geoops::UTMCoordinate stStart,
const geoops::UTMCoordinate stEnd 
)
private

Calculates a bounding box based on Start and End coordinates, preloads LiDAR chunks, and structures them down into a contiguous 1D Costmap vector.

Parameters
stStart- The designated starting UTM geographic coordinate.
stEnd- The designated end UTM geographic coordinate.
Returns
true - Grid initialization succeeded.
false - Total structural invalidation or no usable terrain available.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
286 {
287 // Buffer the search bounds to allow the algorithm lateral space to circumvent large topographic obstructions.
288 double dPaddingMeters = m_dSearchRadius + m_dCorridorPadding;
289
290 // Establish spatial bounding box limits outlining the entire search corridor.
291 double dMinEasting = std::min(stStart.dEasting, stEnd.dEasting) - dPaddingMeters;
292 double dMaxEasting = std::max(stStart.dEasting, stEnd.dEasting) + dPaddingMeters;
293 double dMinNorthing = std::min(stStart.dNorthing, stEnd.dNorthing) - dPaddingMeters;
294 double dMaxNorthing = std::max(stStart.dNorthing, stEnd.dNorthing) + dPaddingMeters;
295
296 // Compute the tile keys needed to cover the bounding box.
297 int nMinTileX = static_cast<int>(std::floor(dMinEasting / m_dTileSize));
298 int nMaxTileX = static_cast<int>(std::floor(dMaxEasting / m_dTileSize));
299 int nMinTileY = static_cast<int>(std::floor(dMinNorthing / m_dTileSize));
300 int nMaxTileY = static_cast<int>(std::floor(dMaxNorthing / m_dTileSize));
301
302 // Preload all valid database tiles within this geographic block.
303 for (int nX = nMinTileX; nX <= nMaxTileX; ++nX)
304 {
305 for (int nY = nMinTileY; nY <= nMaxTileY; ++nY)
306 {
307 this->CheckAndLoadTile(nX, nY);
308 }
309 }
310
311 // Establish the matrix dimensions required for the granular abstract grid.
312 m_dGridOriginEasting = dMinEasting;
313 m_dGridOriginNorthing = dMinNorthing;
314 m_nGridWidth = static_cast<int>(std::ceil((dMaxEasting - dMinEasting) / m_dGridResolution));
315 m_nGridHeight = static_cast<int>(std::ceil((dMaxNorthing - dMinNorthing) / m_dGridResolution));
316
317 // Pre-allocate the master costmap vector memory capacity and initialize to empty state (-1.0).
318 int nTotalCells = m_nGridWidth * m_nGridHeight;
319 m_vCostmap.assign(nTotalCells, GridCell());
320
321 // Overlay raw sparse LiDAR matrices onto the structured grid mapping.
322 for (int nX = nMinTileX; nX <= nMaxTileX; ++nX)
323 {
324 for (int nY = nMinTileY; nY <= nMaxTileY; ++nY)
325 {
326 TileKey stKey{nX, nY};
327
328 if (m_umTileMapCache.find(stKey) != m_umTileMapCache.end())
329 {
330 for (const LiDARHandler::PointRow& stPoint : m_umTileMapCache[stKey])
331 {
332 int nGridX = static_cast<int>((stPoint.dEasting - m_dGridOriginEasting) / m_dGridResolution);
333 int nGridY = static_cast<int>((stPoint.dNorthing - m_dGridOriginNorthing) / m_dGridResolution);
334
335 // Ensure index bounds are safe before memory injection.
336 if (nGridX >= 0 && nGridX < m_nGridWidth && nGridY >= 0 && nGridY < m_nGridHeight)
337 {
338 int nIdx = GetGridIndex(nGridX, nGridY);
339
340 // Pessimistic Data Aggregation: We specifically want to take the worst (lowest) traversal score
341 // to ensure obstacles like trees are not masked by overlapping ground returns.
342 if (m_vCostmap[nIdx].dTravScore < 0.0 || stPoint.dTraversalScore < m_vCostmap[nIdx].dTravScore)
343 {
344 m_vCostmap[nIdx].dTravScore = stPoint.dTraversalScore;
345 m_vCostmap[nIdx].dAltitude = stPoint.dAltitude;
346 m_vCostmap[nIdx].nClosestPointID = stPoint.nID;
347 m_vCostmap[nIdx].nZone = std::stoi(stPoint.szZone.substr(0, 2));
348 m_vCostmap[nIdx].bInNorthernHemisphere = (stPoint.dNorthing >= 0);
349 }
350 }
351 }
352 }
353 }
354 }
355
356 // Dilate the existing valid cells to bridge structural void gaps in sparse clouds.
357 this->FillGridHoles();
358
359 // Overlay dynamic obstacles from the WaypointHandler to ensure stuck state and object detection block paths dynamically in memory.
360 std::vector<geoops::Waypoint> vObstacles = globals::g_pWaypointHandler->GetAllObstacles();
361
362 // Loop through the obstacles.
363 for (const geoops::Waypoint& stObstacle : vObstacles)
364 {
365 // Get obstacle UTM coordinate and radius.
366 geoops::UTMCoordinate stObsUTM = stObstacle.GetUTMCoordinate();
367 double dRadius = stObstacle.dRadius;
368
369 // Convert the obstacle's UTM center to grid array coordinates.
370 int nObsGridX = static_cast<int>((stObsUTM.dEasting - m_dGridOriginEasting) / m_dGridResolution);
371 int nObsGridY = static_cast<int>((stObsUTM.dNorthing - m_dGridOriginNorthing) / m_dGridResolution);
372
373 // Determine the bounding box of the obstacle in grid cells.
374 int nRadiusCells = static_cast<int>(std::ceil(dRadius / m_dGridResolution));
375
376 // Looping through the grid cells of the radius.
377 for (int nDx = -nRadiusCells; nDx <= nRadiusCells; ++nDx)
378 {
379 for (int nDy = -nRadiusCells; nDy <= nRadiusCells; ++nDy)
380 {
381 // Increase the X and Y values.
382 int nX = nObsGridX + nDx;
383 int nY = nObsGridY + nDy;
384
385 // Ensure the target indices are within valid 2D grid bounds.
386 if (nX >= 0 && nX < m_nGridWidth && nY >= 0 && nY < m_nGridHeight)
387 {
388 // Make sure that we're checking within the radius with distance formula.
389 double dDistSq = (nDx * m_dGridResolution) * (nDx * m_dGridResolution) + (nDy * m_dGridResolution) * (nDy * m_dGridResolution);
390
391 // Check if the distance is less than radius squared.
392 if (dDistSq <= (dRadius * dRadius))
393 {
394 // If so, set the grid index to a low trav score.
395 int nIdx = GetGridIndex(nX, nY);
396 m_vCostmap[nIdx].dTravScore = 0.01;
397 }
398 }
399 }
400 }
401 }
402
403 // Calculate starting array indices based on geographic coordinate locations.
404 int nStartX = static_cast<int>((stStart.dEasting - m_dGridOriginEasting) / m_dGridResolution);
405 int nStartY = static_cast<int>((stStart.dNorthing - m_dGridOriginNorthing) / m_dGridResolution);
406 int nEndX = static_cast<int>((stEnd.dEasting - m_dGridOriginEasting) / m_dGridResolution);
407 int nEndY = static_cast<int>((stEnd.dNorthing - m_dGridOriginNorthing) / m_dGridResolution);
408
409 // Enforce strict clamping to prevent edge-case out of bounds index evaluation.
410 nStartX = std::clamp(nStartX, 0, m_nGridWidth - 1);
411 nStartY = std::clamp(nStartY, 0, m_nGridHeight - 1);
412 nEndX = std::clamp(nEndX, 0, m_nGridWidth - 1);
413 nEndY = std::clamp(nEndY, 0, m_nGridHeight - 1);
414
415 // Perform a safe-snap search to ensure origin/destination points don't land exactly in a red zone or void.
416 m_nStartIndex = this->FindNearestValidCell(GetGridIndex(nStartX, nStartY));
417 m_nEndIndex = this->FindNearestValidCell(GetGridIndex(nEndX, nEndY));
418
419 // Abort if no viable terrain whatsoever exists near the required start/end points.
420 if (m_nStartIndex == -1 || m_nEndIndex == -1)
421 {
422 LOG_ERROR(logging::g_qSharedLogger, "GeoPlanner explicit termination: Geographic endpoints have no safe nearby terrain data.");
423 return false;
424 }
425
426 // Reset fast A* memory trackers to prepare for the active search loop.
427 m_vPredecessors.assign(nTotalCells, -1);
428 m_vbClosedSet.assign(nTotalCells, false);
429 m_vdGCosts.assign(nTotalCells, std::numeric_limits<double>::infinity());
430
431 // Empty the priority queue cleanly.
432 while (!m_pqOpenSetNextBest.empty())
433 {
434 m_pqOpenSetNextBest.pop();
435 }
436
437 LOG_INFO(logging::g_qSharedLogger,
438 "Abstract Search Grid Built. Width {} x Height {} (Total: {} cells). Start Index: {}, End Index: {}",
439 m_nGridWidth,
440 m_nGridHeight,
441 nTotalCells,
442 m_nStartIndex,
443 m_nEndIndex);
444 return true;
445 }
const std::vector< geoops::Waypoint > GetAllObstacles()
Accessor for the full list of current obstacle stored in the WaypointHandler.
Definition WaypointHandler.cpp:673
int FindNearestValidCell(int nStartIndex) const
Expands outward concentrically from a target grid cell to locate the nearest neighboring cell that co...
Definition GeoPlanner.cpp:776
int GetGridIndex(int nX, int nY) const
Inline helper to convert 2D grid coordinates to a 1D vector index.
Definition GeoPlanner.h:232
void CheckAndLoadTile(int nTileX, int nTileY)
Checks if a specific tile is loaded in the cache, and if not, fetches the relevant LiDAR point cloud ...
Definition GeoPlanner.cpp:645
void FillGridHoles()
Performs morphological dilation on the costmap to fill in structural voids or gaps caused by sparse L...
Definition GeoPlanner.cpp:679
Struct representing a single LiDAR point row from the database.
Definition LiDARHandler.h:54
This struct stores/contains information about a UTM coordinate.
Definition GeospatialOperations.hpp:211
This struct is used by the WaypointHandler class to store location, size, and type information about ...
Definition GeospatialOperations.hpp:423
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SearchAStar()

void pathplanners::GeoPlanner::SearchAStar ( )
private

Actively runs a highly optimized Weighted A* pathfinding search upon the 1D Costmap grid utilizing kinematic 3D spatial awareness.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
455 {
456 std::chrono::high_resolution_clock::time_point tmStartTime = std::chrono::high_resolution_clock::now();
457
458 // Initialize the origin node states.
459 PlannerState stStartState;
460 stStartState.nGridIndex = m_nStartIndex;
461 stStartState.dGCost = 0.0;
462
463 int nEndX, nEndY;
464 GetGridCoords(m_nEndIndex, nEndX, nEndY);
465
466 // Compute baseline Euclidean heuristic scaled up by heuristic weight.
467 int nStartX, nStartY;
468 GetGridCoords(m_nStartIndex, nStartX, nStartY);
469 stStartState.dHCost =
470 m_dHeuristicWeight * EuclideanDistance(nStartX * m_dGridResolution, nStartY * m_dGridResolution, nEndX * m_dGridResolution, nEndY * m_dGridResolution);
471
472 m_vdGCosts[m_nStartIndex] = 0.0;
473 m_pqOpenSetNextBest.push(stStartState);
474
475 // Pre-computed lookup tables for rapid 8-way directional neighbor evaluation.
476 constexpr int anDx[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
477 constexpr int anDy[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
478 constexpr double adMoveDist[8] = {1.414, 1.0, 1.414, 1.0, 1.0, 1.414, 1.0, 1.414};
479
480 // Main algorithm frontier expansion loop.
481 while (!m_pqOpenSetNextBest.empty())
482 {
483 // Acquire the lowest cost node currently located in the Min-Heap.
484 PlannerState stCurrentState = m_pqOpenSetNextBest.top();
485 m_pqOpenSetNextBest.pop();
486
487 // Ignore stale states that were updated with a better path later in the queue.
488 if (stCurrentState.dGCost > m_vdGCosts[stCurrentState.nGridIndex])
489 {
490 continue;
491 }
492
493 // Immediately exit standard operations if the target goal coordinate was successfully reached.
494 if (stCurrentState.nGridIndex == m_nEndIndex)
495 {
496 LOG_INFO(logging::g_qSharedLogger, "Successfully reached valid goal configuration parameter during A* expansions.");
497 return;
498 }
499
500 // Mark this specific node index as fully evaluated.
501 m_vbClosedSet[stCurrentState.nGridIndex] = true;
502
503 int nCurrentX, nCurrentY;
504 GetGridCoords(stCurrentState.nGridIndex, nCurrentX, nCurrentY);
505
506 // Explore all 8 adjacent neighbor grid cells.
507 for (int nI = 0; nI < 8; ++nI)
508 {
509 int nNeighborX = nCurrentX + anDx[nI];
510 int nNeighborY = nCurrentY + anDy[nI];
511
512 // Block bounds queries outside of the physical map.
513 if (nNeighborX < 0 || nNeighborX >= m_nGridWidth || nNeighborY < 0 || nNeighborY >= m_nGridHeight)
514 {
515 continue;
516 }
517
518 int nNeighborIdx = GetGridIndex(nNeighborX, nNeighborY);
519
520 // Skip indices that have already been cleanly solved.
521 if (m_vbClosedSet[nNeighborIdx])
522 {
523 continue;
524 }
525
526 // Reference cell parameters.
527 const GridCell& stCell = m_vCostmap[nNeighborIdx];
528 const GridCell& stCurrentCell = m_vCostmap[stCurrentState.nGridIndex];
529
530 // Ensure neighbor inherently contains registered geographic parameters and meets minimum score limits.
531 if (stCell.dTravScore < 0.0 || stCell.dTravScore < m_dMinTravScore)
532 {
533 continue;
534 }
535
536 // --- KINEMATIC AWARENESS LOGIC ---
537 // Calculate actual true 3D spatial distance incorporating the vertical ascent parameters.
538 double dAltDiff = std::abs(stCell.dAltitude - stCurrentCell.dAltitude);
539 double dPlanarDist = adMoveDist[nI] * m_dGridResolution;
540 double dTrueDist = std::sqrt((dPlanarDist * dPlanarDist) + (dAltDiff * dAltDiff));
541
542 // Constrain traversal metrics rigidly to [0,1] bounds simply for mathematical safety.
543 double dScore = std::clamp(stCell.dTravScore, 0.0, 1.0);
544
545 // Generate an exponential scaling multiplier. Low traversal scores (e.g., rigid trees or sharp canyons) are
546 // inflated heavily. Empowering the multiplier ensures aggressive physical avoidance of high penalties.
547 double dPenaltyWeight = std::pow(1.0 - dScore, m_dPenaltyPower);
548 double dMultiplier = 1.0 + (m_dBeta * m_dPenaltyScalingFactor * dPenaltyWeight);
549
550 // Compute exact, penalized aggregate traversal path cost.
551 double dTentativeGCost = stCurrentState.dGCost + (dTrueDist * dMultiplier);
552
553 // Adopt spatial progression only if it presents a mathematically optimal routing arrangement.
554 if (dTentativeGCost < m_vdGCosts[nNeighborIdx])
555 {
556 m_vdGCosts[nNeighborIdx] = dTentativeGCost;
557 m_vPredecessors[nNeighborIdx] = stCurrentState.nGridIndex;
558
559 // Package mathematical layout elements for injection to the heap bounds queue.
560 PlannerState stNeighborState;
561 stNeighborState.nGridIndex = nNeighborIdx;
562 stNeighborState.dGCost = dTentativeGCost;
563 stNeighborState.dHCost =
564 m_dHeuristicWeight *
565 EuclideanDistance(nNeighborX * m_dGridResolution, nNeighborY * m_dGridResolution, nEndX * m_dGridResolution, nEndY * m_dGridResolution);
566
567 m_pqOpenSetNextBest.push(stNeighborState);
568 }
569 }
570
571 // Consistently measure real-world time elapsed to terminate algorithms forcibly if CPU limits are breached.
572 if (std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - tmStartTime).count() >= m_dMaxSearchTimeSeconds)
573 {
574 LOG_WARNING(logging::g_qSharedLogger, "Grid search forcibly terminated due to exceeding the max search boundary of {} seconds.", m_dMaxSearchTimeSeconds);
575 return;
576 }
577 }
578 }
double EuclideanDistance(double dEasting1, double dNorthing1, double dEasting2, double dNorthing2) const
Calculates the standard 2D Euclidean distance between two geographic coordinates. This establishes ma...
Definition GeoPlanner.cpp:861
void GetGridCoords(int nIndex, int &nX, int &nY) const
Inline helper to convert a 1D vector index back into 2D grid coordinates.
Definition GeoPlanner.h:244
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReconstructPath()

std::vector< geoops::Waypoint > pathplanners::GeoPlanner::ReconstructPath ( ) const
private

Transforms the abstract 1D computational grid configurations logically backward to rebuild a continuous stream of actionable UTM Geographic sequences.

Returns
std::vector<geoops::Waypoint> - Sequentially ordered map of waypoints establishing optimal path structures.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
590 {
591 std::vector<geoops::Waypoint> vPath;
592
593 // Verify that the final path integration chain was actually established to the end node.
594 if (m_vPredecessors[m_nEndIndex] == -1)
595 {
596 LOG_WARNING(logging::g_qSharedLogger, "Algorithmic resolution fault: Final path integration chain was never properly established.");
597 return {};
598 }
599
600 int nCurrentIdx = m_nEndIndex;
601
602 // Traverse the hierarchical sequence strictly backwards.
603 while (nCurrentIdx != -1)
604 {
605 int nX, nY;
606 GetGridCoords(nCurrentIdx, nX, nY);
607
608 const GridCell& stCell = m_vCostmap[nCurrentIdx];
609
610 // Reapply coordinate origins to map grid positions back to real-world UTM coordinates.
611 double dEasting = m_dGridOriginEasting + (nX * m_dGridResolution);
612 double dNorthing = m_dGridOriginNorthing + (nY * m_dGridResolution);
613
614 // Construct waypoint and append to vector.
615 vPath.emplace_back(geoops::UTMCoordinate(dEasting, dNorthing, stCell.nZone, stCell.bInNorthernHemisphere, stCell.dAltitude),
616 geoops::WaypointType::eNavigationWaypoint,
617 m_dPathWaypointTolerance,
618 stCell.nClosestPointID);
619
620 // Halt backtracing immediately upon intersecting initial origin index.
621 if (nCurrentIdx == m_nStartIndex)
622 {
623 break;
624 }
625
626 nCurrentIdx = m_vPredecessors[nCurrentIdx];
627 }
628
629 // Reverse sequence to represent chronology from Start to Goal.
630 std::reverse(vPath.begin(), vPath.end());
631
632 return vPath;
633 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CheckAndLoadTile()

void pathplanners::GeoPlanner::CheckAndLoadTile ( int  nTileX,
int  nTileY 
)
private

Checks if a specific tile is loaded in the cache, and if not, fetches the relevant LiDAR point cloud data into memory.

Parameters
nTileX- The exact coordinate identifier X block reference naturally mapping structurally.
nTileY- The exact coordinate identifier Y block reference naturally mapping structurally.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
646 {
647 TileKey stTileKey{nTileX, nTileY};
648
649 // Check if the tile is already present in the active cache map.
650 if (m_umTileMapCache.find(stTileKey) == m_umTileMapCache.end())
651 {
652 // Set up point filter parameters logically outlining requested search area blocks.
654 stFilter.dEasting = (nTileX + 0.5) * m_dTileSize;
655 stFilter.dNorthing = (nTileY + 0.5) * m_dTileSize;
656 stFilter.dRadius = std::sqrt(2) * (m_dTileSize / 2.0);
657
658 // Retrieve the point cloud data for the tile from the LiDAR handler.
659 std::vector<LiDARHandler::PointRow> vTilePoints = m_pLiDARHandler->GetLiDARData(stFilter);
660
661 // Return if no points were found for the requested tile mapping boundaries.
662 if (vTilePoints.empty())
663 {
664 return;
665 }
666
667 // Store the retrieved points natively into the unordered tile cache matrix.
668 m_umTileMapCache[stTileKey] = std::move(vTilePoints);
669 }
670 }
std::vector< PointRow > GetLiDARData(const PointFilter &stPointFilter)
Retrieves LiDAR data points from DuckDB based on the specified filter.
Definition LiDARHandler.cpp:136
Struct for filtering LiDAR points during queries.
Definition LiDARHandler.h:79
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FillGridHoles()

void pathplanners::GeoPlanner::FillGridHoles ( )
private

Performs morphological dilation on the costmap to fill in structural voids or gaps caused by sparse LiDAR data collections.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
680 {
681 std::vector<GridCell> vNewCostmap = m_vCostmap;
682 constexpr int anDx[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
683 constexpr int anDy[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
684
685 // Perform processing passes to iteratively stretch valid geographic bounds incrementally.
686 for (int nPass = 0; nPass < m_nDilationPasses; ++nPass)
687 {
688 for (int nY = 0; nY < m_nGridHeight; ++nY)
689 {
690 for (int nX = 0; nX < m_nGridWidth; ++nX)
691 {
692 int nIdx = GetGridIndex(nX, nY);
693
694 // Check if the target grid cell is currently an empty void.
695 if (m_vCostmap[nIdx].dTravScore < 0.0)
696 {
697 double dBestScore = -1.0;
698 GridCell stBestCell;
699
700 // Look at neighboring cells to find a valid traversal score to inherit.
701 for (int nI = 0; nI < 8; ++nI)
702 {
703 int nNeighborX = nX + anDx[nI];
704 int nNeighborY = nY + anDy[nI];
705
706 // Ensure neighbor indices are within valid 2D grid bounds.
707 if (nNeighborX >= 0 && nNeighborX < m_nGridWidth && nNeighborY >= 0 && nNeighborY < m_nGridHeight)
708 {
709 int nNeighborIdx = GetGridIndex(nNeighborX, nNeighborY);
710 if (m_vCostmap[nNeighborIdx].dTravScore > dBestScore)
711 {
712 dBestScore = m_vCostmap[nNeighborIdx].dTravScore;
713 stBestCell = m_vCostmap[nNeighborIdx];
714 }
715 }
716 }
717
718 // Inherit the best adjacent traversal score if a valid neighbor was discovered.
719 if (dBestScore >= 0.0)
720 {
721 vNewCostmap[nIdx] = stBestCell;
722 }
723 }
724 }
725 }
726 // Update the core system array structures with the applied morphological filter outcomes.
727 m_vCostmap = vNewCostmap;
728 }
729 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FindNearestValidCell()

int pathplanners::GeoPlanner::FindNearestValidCell ( int  nStartIndex) const
private

Expands outward concentrically from a target grid cell to locate the nearest neighboring cell that contains valid and safe traversal structures.

Parameters
nStartIndex- Origin array structural identifier originally derived from GPS.
Returns
int - Corrected viable mapping ID index, or -1 representing complete absence of viable data.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
777 {
778 // Define an explicit threshold to prevent snapping the origin to extremely hazardous geometry.
779 double dSafeThreshold = std::max(m_dMinTravScore, m_dSafeTravScoreThreshold);
780
781 // Verify quickly if the requested starting index is already a valid and thoroughly safe cell.
782 if (nStartIndex >= 0 && nStartIndex < static_cast<int>(m_vCostmap.size()) && m_vCostmap[nStartIndex].dTravScore >= 0.0 &&
783 m_vCostmap[nStartIndex].dTravScore >= dSafeThreshold)
784 {
785 return nStartIndex;
786 }
787
788 int nStartX, nStartY;
789 GetGridCoords(nStartIndex, nStartX, nStartY);
790
791 int nMaxRadius = m_nMaxSpiralSearchRadius;
792 int nBestFallbackIdx = -1;
793 double dBestFallbackScore = -1.0;
794
795 // Spiral search radially outward tracking concentric boundary edges locally.
796 for (int nRadius = 1; nRadius <= nMaxRadius; ++nRadius)
797 {
798 int nBestIdxInRing = -1;
799 double dBestScoreInRing = -1.0;
800
801 for (int nI = -nRadius; nI <= nRadius; ++nI)
802 {
803 for (int nJ = -nRadius; nJ <= nRadius; ++nJ)
804 {
805 // Restrict processing exclusively to parameters located directly at the current radius boundary.
806 if (std::abs(nI) == nRadius || std::abs(nJ) == nRadius)
807 {
808 int nNeighborX = nStartX + nI;
809 int nNeighborY = nStartY + nJ;
810
811 if (nNeighborX >= 0 && nNeighborX < m_nGridWidth && nNeighborY >= 0 && nNeighborY < m_nGridHeight)
812 {
813 int nIdx = GetGridIndex(nNeighborX, nNeighborY);
814 double dScore = m_vCostmap[nIdx].dTravScore;
815
816 if (dScore >= 0.0 && dScore >= m_dMinTravScore)
817 {
818 // Track the absolute best viable layout encountered overall.
819 if (dScore > dBestFallbackScore)
820 {
821 dBestFallbackScore = dScore;
822 nBestFallbackIdx = nIdx;
823 }
824
825 // Prioritize and track specific indices exceeding the optimal safe threshold.
826 if (dScore >= dSafeThreshold && dScore > dBestScoreInRing)
827 {
828 dBestScoreInRing = dScore;
829 nBestIdxInRing = nIdx;
830 }
831 }
832 }
833 }
834 }
835 }
836
837 // Immediately yield the optimal safe coordinate natively if one was discovered in this ring.
838 if (nBestIdxInRing != -1)
839 {
840 return nBestIdxInRing;
841 }
842 }
843
844 // Return the highest scoring viable cell found within the search limits, or -1 if no usable data exists.
845 return nBestFallbackIdx;
846 }
Here is the caller graph for this function:

◆ EuclideanDistance()

double pathplanners::GeoPlanner::EuclideanDistance ( double  dEasting1,
double  dNorthing1,
double  dEasting2,
double  dNorthing2 
) const
private

Calculates the standard 2D Euclidean distance between two geographic coordinates. This establishes mathematically admissible baseline heuristic bounds for A*.

Parameters
dEasting1- The numeric coordinate east bounds establishing start reference.
dNorthing1- The numeric coordinate north bounds establishing start reference.
dEasting2- The numeric coordinate east bounds establishing end reference.
dNorthing2- The numeric coordinate north bounds establishing end reference.
Returns
double - The calculated spatial euclidean distance dimension.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
862 {
863 // Evaluate numerical differentials mapping bounds simply and efficiently.
864 double dDiffX = dEasting1 - dEasting2;
865 double dDiffY = dNorthing1 - dNorthing2;
866
867 return std::sqrt(dDiffX * dDiffX + dDiffY * dDiffY);
868 }
Here is the caller graph for this function:

◆ GetGridIndex()

int pathplanners::GeoPlanner::GetGridIndex ( int  nX,
int  nY 
) const
inlineprivate

Inline helper to convert 2D grid coordinates to a 1D vector index.

Parameters
nX- The X grid coordinate.
nY- The Y grid coordinate.
Returns
int - The corresponding flat 1D vector index.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
232{ return nY * m_nGridWidth + nX; }
Here is the caller graph for this function:

◆ GetGridCoords()

void pathplanners::GeoPlanner::GetGridCoords ( int  nIndex,
int &  nX,
int &  nY 
) const
inlineprivate

Inline helper to convert a 1D vector index back into 2D grid coordinates.

Parameters
nIndex- The 1D vector index to decode.
nX- Reference to store the resultant X coordinate.
nY- Reference to store the resultant Y coordinate.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-07-14
245 {
246 nY = nIndex / m_nGridWidth;
247 nX = nIndex % m_nGridWidth;
248 }
Here is the caller graph for this function:

Member Data Documentation

◆ fnMinTravScoreCallback

const std::function<void(const rovecomm::RoveCommPacket<float>&, const sockaddr_in&)> pathplanners::GeoPlanner::fnMinTravScoreCallback
private
Initial value:
=
[this](const rovecomm::RoveCommPacket<float>& stPacket, const sockaddr_in& stdAddr)
{
(void) stdAddr;
if (stPacket.vData.size() > 0)
{
m_dMinTravScore = static_cast<double>(stPacket.vData[0]);
this->ClearGeoCache();
LOG_NOTICE(logging::g_qSharedLogger,
"Incoming Packet: Setting GeoPlanner minimum travel score to {}. The tile cache has also been cleared.",
this->m_dMinTravScore);
}
}
void ClearGeoCache()
Explicitly zeroes and reclaims internal spatial database mapping arrays.
Definition GeoPlanner.cpp:188

Callback function used to set the minimum travel score for path planning.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-04-04
258 {
259 (void) stdAddr;
260
261 // Extract minimum travel score from incoming packet.
262 if (stPacket.vData.size() > 0)
263 {
264 m_dMinTravScore = static_cast<double>(stPacket.vData[0]);
265 this->ClearGeoCache();
266
267 LOG_NOTICE(logging::g_qSharedLogger,
268 "Incoming Packet: Setting GeoPlanner minimum travel score to {}. The tile cache has also been cleared.",
269 this->m_dMinTravScore);
270 }
271 };

◆ fnBetaBiasCallback

const std::function<void(const rovecomm::RoveCommPacket<float>&, const sockaddr_in&)> pathplanners::GeoPlanner::fnBetaBiasCallback
private
Initial value:
=
[this](const rovecomm::RoveCommPacket<float>& stPacket, const sockaddr_in& stdAddr)
{
(void) stdAddr;
if (stPacket.vData.size() > 0)
{
m_dBeta = static_cast<double>(stPacket.vData[0]);
LOG_NOTICE(logging::g_qSharedLogger, "Incoming Packet: Setting GeoPlanner beta bias to {}", this->m_dBeta);
}
}

Callback function used to set the beta bias for travel scores in path planning.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-04-04
281 {
282 (void) stdAddr;
283
284 // Extract beta bias from incoming packet.
285 if (stPacket.vData.size() > 0)
286 {
287 m_dBeta = static_cast<double>(stPacket.vData[0]);
288
289 LOG_NOTICE(logging::g_qSharedLogger, "Incoming Packet: Setting GeoPlanner beta bias to {}", this->m_dBeta);
290 }
291 };

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