|
1 | | -# Cpp_3D_Occupancy_Grid_Course_Project |
2 | | -C++ Uni Bonn course project for SoSe 25. Uses Eigen and Open3D library as external dependencies to visualise a 3D occupancy grid given the laser scans. |
| 1 | +# 3D Occupancy Grid Mapping from LiDAR Scans |
| 2 | + |
| 3 | +This is a C++ Uni Bonn course project for SoSe 25, which demonstrates the creation of a 3D occupancy grid map from a series of LiDAR scans and vehicle poses. It leverages modern C++17 features, the Eigen library for efficient linear algebra, and the Open3D library for visualization. |
| 4 | + |
| 5 | +The application processes a dataset of point clouds, determines the optimal grid size and resolution, and then integrates each scan to build a map of the environment, distinguishing between free and occupied space. |
| 6 | + |
| 7 | +## Project Overview |
| 8 | + |
| 9 | +The core of the project is to build a probabilistic 3D map of an environment. This is achieved by: |
| 10 | + |
| 11 | +1. **Analyzing the entire dataset** to calculate the necessary bounds for the world, ensuring the grid is large enough to contain the entire trajectory. |
| 12 | +2. **Creating an optimal 3D grid** with a specified resolution. The implementation includes safeguards and auto-adjustments for memory-intensive configurations. |
| 13 | +3. **Processing each LiDAR scan**: For each point in a scan, a ray is cast from the sensor origin to the point. |
| 14 | +4. **Updating Voxel Occupancy**: Voxels along the ray are marked as "free," and the voxel at the ray's endpoint is marked as "occupied" using a log-odds probability model. |
| 15 | +5. **Visualizing the Result**: The final set of occupied voxels is extracted and rendered as a 3D point cloud. |
| 16 | + |
| 17 | +## Code Structure |
| 18 | + |
| 19 | +The project is organized into several components to separate concerns: |
| 20 | + |
| 21 | +- `src/main.cpp`: The main entry point of the application. It orchestrates the entire workflow, from data loading and analysis to mapping and visualization. |
| 22 | +- `src/dataloader/`: A static library responsible for loading LiDAR point cloud data (`.ply` files) and the corresponding ground truth poses. |
| 23 | +- `src/data_analyser.cpp/.hpp`: Contains the logic to perform an initial pass over the entire dataset to determine the environment's boundaries, which is used to configure the optimal grid size and resolution. |
| 24 | +- `src/scan_processor.cpp/.hpp`: Handles the processing of individual LiDAR scans, transforming points to the world frame and integrating them into the occupancy grid. |
| 25 | +- `src/occupancy_grid.cpp/.hpp`: Implements the core 3D occupancy grid data structure, including voxel management, coordinate transformations, the log-odds update model, and the 3D Bresenham's algorithm for ray tracing. |
| 26 | +- `src/visualizer/`: An interface library that provides a simple wrapper around Open3D for visualizing the final grid of occupied voxels. |
| 27 | + |
| 28 | +## Features |
| 29 | + |
| 30 | +- **Dynamic Grid Sizing**: Automatically analyzes the dataset to determine optimal grid dimensions and origin. |
| 31 | +- **Memory Management**: Includes warnings and automatic resolution adjustments for potentially large grid sizes. |
| 32 | +- **Efficient Ray Tracing**: Implements a 3D Bresenham's line algorithm for ray casting. |
| 33 | +- **Probabilistic Mapping**: Uses log-odds values to update voxel states, making the map robust to sensor noise. |
| 34 | +- **Performance Optimized**: Written with modern C++ and performance in mind, leveraging stl algos, efficient stl containers, and release build optimizations. |
| 35 | +- **3D Visualization**: Uses Open3D to render the final occupancy grid. |
| 36 | + |
| 37 | +## Dependencies |
| 38 | + |
| 39 | +- **Eigen3**: For matrix and vector operations. |
| 40 | +- **Open3D**: For point cloud processing and visualization. |
| 41 | + |
| 42 | +You can install the dependencies on a Debian-based system using: |
| 43 | + |
| 44 | +```bash |
| 45 | +sudo apt-get install libeigen3-dev libopen3d-dev |
| 46 | +``` |
| 47 | + |
| 48 | +## Compilation |
| 49 | + |
| 50 | +The project uses CMake. To compile, run the following commands from the project's root directory: |
| 51 | + |
| 52 | +```bash |
| 53 | +# Configure the project for a Release build |
| 54 | +cmake -DCMAKE_BUILD_TYPE=Release -Bbuild -S. |
| 55 | + |
| 56 | +# Build the project using 24 parallel jobs |
| 57 | +cmake --build build -j 24 |
| 58 | +``` |
| 59 | + |
| 60 | +The executable will be located at `build/occupancy_grid_main`. |
| 61 | + |
| 62 | +### Compiler Optimizations |
| 63 | + |
| 64 | +For `Release` builds, the following compiler flags are enabled in `CMakeLists.txt` to maximize performance: |
| 65 | +- `-O3`: Enables the highest level of compiler optimization. |
| 66 | +- `-DNDEBUG`: Disables `assert()` calls to avoid runtime checks. |
| 67 | +- `-march=native`: Instructs the compiler to generate code specifically optimized for the CPU architecture of the machine it's being compiled on. |
| 68 | +- `-ffast-math`: Allows for more aggressive floating-point optimizations that may not be strictly IEEE-compliant but are faster. |
| 69 | +- `-funroll-loops`: Unrolls loops to reduce branch overhead, which can improve performance for tight loops. |
| 70 | + |
| 71 | +## Execution |
| 72 | + |
| 73 | +To run the application, provide the path to the data directory from the `build` directory: |
| 74 | + |
| 75 | +```bash |
| 76 | +./occupancy_grid_main ../src/Data |
| 77 | +``` |
| 78 | + |
| 79 | +## Results |
| 80 | + |
| 81 | +The following images show the final 3D occupancy grid generated from the full dataset, viewed from different angles. |
| 82 | + |
| 83 | +**Top-Down View:** |
| 84 | + |
| 85 | + |
| 86 | +**Side View:** |
| 87 | + |
| 88 | + |
| 89 | +**Inside View:** |
| 90 | + |
| 91 | + |
| 92 | +### Performance Statistics |
| 93 | + |
| 94 | +The following statistics were recorded after processing the entire dataset of 6770 scans. The grid was configured with the following parameters: |
| 95 | + |
| 96 | +- **Dataset Range (X, Y, Z)**: 276.9m, 343.8m, 47.8m |
| 97 | +- **Grid Coverage**: From [-138.2, -223.1, -7.6] to [144.3, 127.9, 41.4] |
| 98 | +- **Grid Origin**: -138.2, -223.1, -7.6 |
| 99 | +- **Grid Resolution**: 0.5m (50cm per voxel) |
| 100 | +- **Grid Dimensions**: 565 x 702 x 98 |
| 101 | +- **Total Voxels**: 38,869,740 |
| 102 | + |
| 103 | +Performance results with the hash collision optimization enabled: |
| 104 | + |
| 105 | +- **Total Scans Processed**: 6770 |
| 106 | +- **Total Execution Time**: 277.43 seconds |
| 107 | +- **Average Time per Scan**: 40.83 ms |
| 108 | +- **Scan Rate**: 24.4 scans/second |
| 109 | +- **Final Occupied Voxels**: 245,669 |
| 110 | +- **Voxel Extraction Time**: 0.02 seconds |
| 111 | + |
| 112 | +## Project Assignment |
| 113 | + |
| 114 | +The detailed requirements and goals for this project are outlined in the official course assignment document. |
| 115 | + |
| 116 | +[View Project Assignment](./project_assignment.pdf) |
| 117 | + |
| 118 | +## References |
| 119 | + |
| 120 | +This project was developed with the help of the following educational resources: |
| 121 | + |
| 122 | +- **Bresenham's Line Algorithm Visualization**: A clear visual explanation of the 2D Bresenham's algorithm, which forms the basis for the 3D implementation in this project. [Watch on YouTube](https://youtu.be/8gIhNSAXYcQ). |
| 123 | +- **Bresenham's Line Algorithm Coding Tutorial**: A coding tutorial for a 2D implementation of Bresenham's algorithm that was adapted to 3D for this project. [Watch on YouTube](https://youtu.be/CceepU1vIKo). |
| 124 | +- **SLAM Lecture on Occupancy Grid Mapping**: A comprehensive lecture covering the theory behind occupancy grid maps, including the log-odds representation, inverse sensor models, and the static binary Bayes filter, all of which are fundamental concepts for this project. [Watch on YouTube](https://youtu.be/v-Rm9TUG9LA). |
3 | 125 |
|
4 | | -### Note: Project work will be started by the end of July 25'. |
|
0 commit comments