3D JPS Pathfinding (base on JPSAABBEnv)
This document describes how to perform 3D JPS using the JPSAABBEnv class.
JPSAABBEnv provides high‑precision collision detection through CGAL’s AABB tree.
Features
JPSAABBPathFinder Class
/// JPSAABBPathFinder extends the JPSAABBEnv environment for 3D pathfinding
class JPSAABBPathFinder : public JPSAABBEnv
{
public:
JPSAABBPathFinder(
const std::unordered_map<size_t, SCData>& SCMap,
const std::unordered_map<size_t, EFData>& EFMap
);
/**
* Executes JPS graph search between two 3D points
* @param startPoint Starting position;
* @param endPoint Ending position;
* @return A sequence of 3D integer grid coordinates representing the found path
*/
std::vector<Eigen::RowVector3i> JPSGraphSearch(
const Eigen::RowVector3d& startPoint,
const Eigen::RowVector3d& endPoint
);
}
⚠️Critical Constraint:
- Both
startPointandendPointmust lie within the navigable space defined bySCMap. - Neither
startPointnorendPointmust be located inside any obstacle volume defined byEFMap.
Example Usage
1. Data Preparation
This example uses testdata_simple.json from the repository.
Load the navigable‑corridor volumes (SCMap) and obstacle volumes (EFMap) from the JSON file.
// Load navigable‑corridor volumes (SCMap) and obstacle volumes (EFMap)
const auto& [SCMap,EFMap] = loadVolumeMaps("./testData/testdata_simple.json");
// Define start/end points within bounds and outside obstacles
Eigen::RowVector3d startPoint(748876.1520, 2564890.4544, 65.5);
Eigen::RowVector3d endPoint(748678.2699, 2564651.6236, 50.0761);
2. Environment Initialization
Next, initialize the JPSAABBPathFinder class with the loaded spatial data.
During construction, the class builds a CGAL‑based DetectionObjects structure (AABB tree) and stores it as a private member. This structure is later used to test whether a candidate point lies inside the corridor, on its boundary, or within an obstacle.
// Initialize pathfinder with collision detection structures
JPSAABBPathFinder _JPSAABBPathFinder(SCMap, EFMap); // Constructs AABB trees for spatial queries
3. Path Search Execution
With the environment initialized, you can now execute JPS between the start and end points:
// Perform JPS search
const auto& bestPath = _JPSAABBPathFinder.JPSGraphSearch(startPoint, endPoint);
4. Results
The resulting path is a sequence of 3D grid coordinates representing the optimal trajectory. The figure below visualizes the output:
- Obstacles: Represented in red.
- Navigable corridor: Shown in green.
- JPS path: Displayed as a blue polyline.
Complete Implementation
#include "Prepare.h"
#include "JPSAABBEnv.h"
#include <chrono>
int main() {
// Load spatial data
const auto& [SCMap,EFMap] = loadVolumeMaps("./testData/testdata_simple.json");
// Define start / end points
Eigen::RowVector3d startPoint(748876.1520, 2564890.4544, 65.5);
Eigen::RowVector3d endPoint(748678.2699, 2564651.6236, 50.0761);
// Initialise path‑finder (constructs AABB trees)
JPSAABBPathFinder _JPSAABBPathFinder(SCMap, EFMap);
// Perform JPS search and measure execution time
auto t0 = std::chrono::high_resolution_clock::now();
const auto& bestPaths = _JPSAABBPathFinder.JPSGraphSearch(startPoint, endPoint);
auto t1 = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0);
std::cout << "JPSAABBPathFinder execution time: " << duration.count() << " ms" << std::endl;
return 0;
}