FastDEM Elevation Mapping Engine

repository·main·Indexed 41 days ago

https://github.com/ikhyeon-cho/fastdem

A high-performance, lightweight elevation mapping engine for embedded robots. FastDEM provides real-time terrain mapping (100+ Hz) by fusing LiDAR or RGB-D data into local or global maps. It includes nanoPCL, a header-only point cloud library featuring a Structure-of-Arrays (SoA) design for efficient filtering, ICP registration (Point-to-Point, Point-to-Plane, GICP), segmentation, and I/O support for PCD and KITTI formats.

Tokens
14.4K
Snippets
42
Records
57
Agent score
52%

What's inside FastDEM

  1. Overview of FastDEM

    main

    FastDEM is a lightweight, ultra-fast elevation mapping engine designed for mobile robots. It incrementally fuses LiDAR or RGB-D point clouds into local or global elevation maps.

    Key characteristics:

    • Performance: Achieves 100+ Hz (approx. 10ms per scan) on embedded hardware like Jetson Orin.
    • Lightweight: Runs entirely on CPU and does not require PCL, OpenCV, or CUDA; it relies primarily on Eigen.
    • Versatile: Supports multiple estimators (Kalman Filter and P² Quantile), sensor-aware physics models, and various post-processing tasks like raycasting, uncertainty fusion, and inpainting.
    • Deployment: Can be used as a standalone C++ library or via ROS1/ROS2 adapters.
  2. Overview of nanoPCL features and capabilities

    main

    nanoPCL is a lightweight, high-performance alternative to PCL (Point Cloud Library) designed for robotics and vision. It focuses on minimal dependencies (Eigen only) and fast compilation.

    Key Capabilities:

    • Core Layout: SIMD-friendly Structure-of-Arrays (SoA) for reduced memory footprint (approx. 16 bytes/pt for XYZ+I).
    • Filters: VoxelGrid, CropBox, and Outlier Removal (Radius/Statistical).
    • Registration: ICP, Point-to-Plane, GICP, and VGICP (OpenMP accelerated).
    • Search: VoxelHash (O(1) complexity) and KdTree (via nanoflann wrapper).
    • Integrations: Built-in adapters for ROS 1, ROS 2, PCL, and Rerun for visualization.
  3. Understand nanoPCL's Structure-of-Arrays (SoA) design

    main

    nanoPCL uses a Structure-of-Arrays (SoA) design for memory efficiency and cache friendliness. Channels (like Intensity or Ring) are lazily allocated, meaning they are only created when used. You can pre-declare channels for better performance with large datasets.

    Available Channels:

    ChannelTypeUsage
    IntensityfloatIntensity(0.5f)
    Ringuint16Ring(5)
    TimefloatTime(0.001f)
    ColorRGBColor(255, 0, 0)
    Labeluint32Label(42)

    Usage Patterns:

    • Automatic Allocation: Channels are created automatically when you call .add() with specific types.
    • Pre-declaration: Use methods like .useIntensity() or .useRing() to prepare memory.
    • Bulk Operations: Access channels via methods like .intensities() to perform cache-friendly bulk updates.
    // Channels are created automatically when used
    cloud.add(x, y, z, Intensity(0.5f), Ring(3));
    
    // Pre-declare for performance with large data
    cloud.useIntensity();
    cloud.useRing();
    cloud.reserve(100000);
    
    // Bulk access (cache-friendly)
    for (float& val : cloud.intensities()) {
        val *= 2.0f;
    }
  4. Overview of FastDEM example programs

    main

    The FastDEM repository includes several example programs categorized by difficulty and functionality:

    • 01_hello_mapping (Basic): Demonstrates map setup, integration with explicit-transform, and accessing elevation data.
    • 02_config_loading (Basic): Demonstrates how to load YAML configurations using LOCAL or GLOBAL presets.
    • 03_estimator_comparison (Intermediate): Compares the performance/behavior of Kalman and P2 Quantile estimators.
    • 04_transform_provider (Intermediate): Shows integration with Calibration and Odometry interfaces.
  5. Use FastDEM as a C++ Library

    main

    You can integrate FastDEM directly into your C++ projects without ROS.

    1. Install Dependencies:

      sudo apt install libeigen3-dev libyaml-cpp-dev libspdlog-dev
    2. Build and Install:

      git clone https://github.com/Ikhyeon-Cho/FastDEM.git
      cd FastDEM/fastdem
      mkdir build && cd build
      cmake ..
      make -j$(nproc)
      sudo make install
    3. C++ Integration Example: Include <fastdem/fastdem.hpp>, initialize an ElevationMap with geometry, load a configuration, and use the FastDEM mapper to integrate point clouds using explicit transforms.

      Note: integrate requires the point cloud, the transform from base to sensor (T_base_sensor), and the transform from world to base (T_world_base).

    #include <fastdem/fastdem.hpp>
    
    fastdem::ElevationMap map;
    map.setGeometry(15.0, 15.0, 0.1);  // width, height, resolution [m]
    
    auto cfg = fastdem::loadConfig("config/default.yaml");
    fastdem::FastDEM mapper(map, cfg);
    
    // With explicit transforms
    mapper.integrate(cloud, T_base_sensor, T_world_base);
  6. Build FastDEM examples

    main

    To build the FastDEM example programs, you must enable the FASTDEM_BUILD_EXAMPLES flag during the CMake configuration step. It is recommended to use Release build type for performance testing.

    Follow these steps:

    1. Navigate to the fastdem directory.
    2. Create and enter a build directory.
    3. Run cmake with the example flag enabled.
    4. Compile using make with parallel jobs.
    cd FastDEM/fastdem
    mkdir -p build && cd build
    cmake .. -DFASTDEM_BUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Release
    make -j$(nproc)
  7. Run FastDEM example executables

    main

    Once the build process is complete, the executables are located within the build/examples/ subdirectory. You can run them directly from the build directory.

    ./build/examples/01_hello_mapping/01_hello_mapping
    ./build/examples/02_config_loading/02_config_loading
    ./build/examples/03_estimator_comparison/03_estimator_comparison
    ./build/examples/04_transform_provider/04_transform_provider
  8. Add a new benchmark to nanoPCL

    main

    To add a new performance test to the suite, follow these steps:

    1. Include benchmark_common.hpp in your source file.
    2. Use benchmark::run() to perform the actual measurement.
    3. Use benchmark::printResult() to output the results to the console.
    4. Follow the naming convention: benchmark_<operation>.cpp.
    5. Add an entry for your new benchmark to the benchmarks/README.md file.
  9. Build and run nanoPCL benchmarks

    main

    To build the nanoPCL benchmarks, you must enable the NANOPCL_BUILD_BENCHMARKS flag during the CMake configuration step. If you wish to run the PCL comparison benchmarks, you must also have libpcl-dev installed on your system.

    Requirements

    • Core benchmarks: No external dependencies required (only CMake).
    • PCL comparison benchmarks: Requires libpcl-dev (sudo apt install libpcl-dev).

    Build Instructions

    mkdir build && cd build
    cmake .. -DNANOPCL_BUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release
    make -j$(nproc)
  10. Run individual or batch benchmarks

    main

    After building, you can execute benchmarks directly from their build directory locations.

    • Run a single benchmark: Execute the specific binary (e.g., ./profiling/benchmark_voxel_grid).
    • Run all profiling benchmarks: Use a shell loop to iterate through the profiling/ directory.
    • Run PCL comparisons: Execute binaries in the vs_pcl/ directory (requires PCL installed).
    # Run individual benchmark
    ./profiling/benchmark_voxel_grid
    
    # Run all profiling benchmarks
    for f in profiling/benchmark_*; do ./$f; done
    
    # Run PCL comparisons (requires PCL)
    ./vs_pcl/benchmark_icp
  11. Install and Run FastDEM with ROS1

    main

    To use FastDEM in a ROS1 environment (Ubuntu 20.04 with ROS Noetic), follow these steps:

    1. Install System Dependencies:

      sudo apt install libeigen3-dev libyaml-cpp-dev libspdlog-dev
      sudo apt install ros-noetic-tf2-eigen ros-noetic-grid-map-msgs
    2. Clone and Build:

      cd ~/catkin_ws/src
      git clone https://github.com/Ikhyeon-Cho/FastDEM.git
      catkin build fastdem_ros
    3. Run: Use roslaunch to start the node. To enable map-centric (global) mode, add the global_mapping:=true argument.

      roslaunch fastdem_ros run.launch rviz:=true

    Configuration Files:

    • Local mapping: ros1/config/local_mapping.yaml
    • Global mapping: ros1/config/global_mapping.yaml
    # Dependencies
    sudo apt install libeigen3-dev libyaml-cpp-dev libspdlog-dev
    sudo apt install ros-noetic-tf2-eigen ros-noetic-grid-map-msgs
    
    # Clone and build
    cd ~/catkin_ws/src
    git clone https://github.com/Ikhyeon-Cho/FastDEM.git
    catkin build fastdem_ros
    
    # Run (add global_mapping:=true for map-centric mode)
    roslaunch fastdem_ros run.launch rviz:=true
  12. Use the nanoPCL benchmark framework

    main

    The nanoPCL benchmark framework provides a consistent methodology for performance analysis using benchmark_common.hpp. It includes features like unified iteration policies (FAST, MEDIUM, SLOW), automatic outlier removal using the IQR method, and statistical analysis (mean, stddev, median, 95% CI).

    To implement a new benchmark, include benchmark_common.hpp, use benchmark::run() to wrap the code under test, and use the provided print functions for formatted output.

    #include "benchmark_common.hpp"
    
    int main() {
        benchmark::printHeader("My Benchmark");
        benchmark::PlatformInfo::capture().print();
    
        auto stats = benchmark::run([&]() {
            return myFunction();
        });
    
        benchmark::printResult("myFunction", stats);
        benchmark::printFooter("Conclusion here");
        return 0;
    }