A complete Visual-Inertial Odometry (VIO) implementation and evaluation using the Basalt framework on EuRoC MAV datasets. This project demonstrates state-of-the-art VIO performance with comprehensive quantitative analysis.
| Dataset | ATE RMSE | RPE RMSE | Duration | Performance |
|---|---|---|---|---|
| MH_01_easy | 0.069 m | 0.023 m | 181.9 s | β Excellent |
| V1_03_difficult | 0.054 m | 0.035 m | 104.7 s | β Excellent |
Performance Highlights:
- π― State-of-the-art accuracy (7cm ATE, 2-4cm RPE)
- π Significantly better than VINS-Mono baseline on tested sequences
- πͺ Robust under aggressive motion (V1_03)
- βοΈ Reproducible and robust with proper ADIS16448 IMU calibration
Figure: Snapshot of the VIO system running on MH_01_easy dataset. Left: Camera input with tracking status. Right: Real-time trajectory estimation (Blue) vs Start point (Green).
Basalt VIO Framework:
- Repository: VladyslavUsenko/basalt
- Commit:
9656344(tracked as git submodule inexternal/basalt/) - Build Type: Release with Debug Info (RelWithDebInfo)
- Note: The exact Basalt version is pinned via git submodule. To ensure reproducibility, the Docker build and local setup both use this specific commit.
To verify your Basalt version:
cd external/basalt
git log --oneline -1
# Should show: 9656344 Merge branch 'remove_rs2_pangolin_headers' into 'master'- Docker and Docker Compose
- ~2GB disk space for datasets
- ~4GB disk space for Docker images
git clone https://github.com/bigalex95/VIO-SLAM-Assignment
cd VIO-SLAM-AssignmentDownload EuRoC MAV datasets to the data/ folder:
# Run the download script
./scripts/download_euroc.sh
# Or manually download from:
# https://www.research-collection.ethz.ch/entities/researchdata/bcaf173e-5dac-484b-bc37-faf97a594f1f
# or
# https://www.kaggle.com/datasets/bhavaniprasadm3/euroc-mav/Expected structure:
data/
βββ MH_01_easy/
β βββ mav0/
β βββ cam0/
β βββ cam1/
β βββ imu0/
β βββ state_groundtruth_estimate0/
βββ V1_03_difficult/
βββ mav0/
βββ [same structure]
Run the complete pipeline automatically:
cd docker
docker-compose up runThis will:
- Build Basalt VIO
- Run VIO on both datasets
- Generate trajectory outputs
- Evaluate with evo
- Create plots and statistics
Results will be saved to results/ directory.
For development, debugging, and GUI visualization:
cd docker
docker-compose up -d dev
docker-compose exec dev bash
# Inside container:
cd /workspace/external/basalt
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
# Run VIO with GUI
./build/basalt_vio \
--dataset-path /workspace/data/MH_01_easy \
--cam-calib /workspace/configs/my_euroc_calib.json \
--dataset-type euroc \
--config-path /workspace/external/basalt/data/euroc_config.json \
--show-gui 1 --use-imu 1- Open project in VS Code
- Install "Dev Containers" extension
- Press
F1β "Dev Containers: Reopen in Container" - Terminal opens inside container automatically
.
βββ configs/ # Calibration configurations
β βββ my_euroc_calib.json # Custom EuRoC calibration
βββ data/ # EuRoC datasets (download here)
β βββ MH_01_easy/
β βββ V1_03_difficult/
βββ docker/ # Docker configurations
β βββ Dockerfile # Production pipeline
β βββ Dockerfile.dev # Development environment
β βββ docker-compose.yml # Orchestration
βββ docs/ # Detailed documentation
β βββ phase_a_literature_review.md
β βββ phase_b_implementation.md
β βββ phase_c_evaluation.md
β βββ phase_d_improvement_proposal.md
βββ external/ # Third-party dependencies
β βββ basalt/ # Basalt VIO framework
βββ results/ # Generated outputs
β βββ evaluation/ # Plots and metrics
β βββ groundtruth/ # Processed ground truth
β βββ stats/ # JSON statistics
β βββ trajectories/ # Estimated trajectories
βββ scripts/ # Automation scripts
βββ download_euroc.sh # Dataset download
βββ run_vio_tests.sh # Run VIO pipeline
βββ evaluate_trajectories.py # Evaluation script
| Metric | Value | Assessment |
|---|---|---|
| ATE RMSE | 0.069 m | β Excellent |
| ATE Mean | 0.064 m | State-of-the-art |
| RPE RMSE | 0.023 m | β Excellent (2.3% drift) |
| Duration | 181.9 s | Long sequence |
| Poses | 3,638 | High density |
| Metric | Value | Assessment |
|---|---|---|
| ATE RMSE | 0.054 m | β Excellent |
| ATE Mean | 0.050 m | Robust tracking |
| RPE RMSE | 0.035 m | β Good (3.5% drift) |
| Duration | 104.7 s | Aggressive motion |
| Poses | 2,094 | Fast movements |
All evaluation plots are in results/evaluation/:
| 3D Trajectory | ATE over Time |
|---|---|
![]() |
![]() |
| 3D Trajectory | ATE over Time |
|---|---|
![]() |
![]() |
| Method | MH_01 ATE | V1_03 ATE | Notes |
|---|---|---|---|
| VINS-Mono | 0.16 m | 0.30 m | VIO baseline |
| ORB-SLAM2 | 0.06 m | 0.14 m | With loop closure |
| Our Basalt | 0.069 m | 0.054 m | VIO-only β |
Performance vs VINS-Mono:
- 2.3x better on MH_01_easy (0.16 / 0.069 β 2.3)
- 5.6x better on V1_03_difficult (0.30 / 0.054 β 5.6)
Properly configured for EuRoC datasets:
{
"imu_update_rate": 200.0,
"accel_noise_std": [0.016, 0.016, 0.016],
"gyro_noise_std": [0.0001454441, 0.0001454441, 0.0001454441],
"accel_bias_std": [0.0003, 0.0003, 0.0003],
"gyro_bias_std": [0.000019394, 0.000019394, 0.000019394]
}Source: ADIS16448 datasheet + EuRoC specifications
Comprehensive documentation in docs/:
- Document: phase_a_literature_review.md
- Topics: VIO fundamentals, frameworks, sensor fusion, optimization
- Document: phase_b_implementation.md
- Content: Basalt setup, Docker containerization, dataset preparation
- Document: phase_c_evaluation.md
- Quick Reference: results/evaluation/README.md
- Content: ATE/RPE metrics, visualizations, root cause analysis
- Document: phase_d_improvement_proposal.md
- Topic: Bag-of-Words loop closure integration
# Run on both datasets
./scripts/run_vio_tests.sh
# Run on single dataset
cd external/basalt/build
./basalt_vio \
--dataset-path /workspace/data/MH_01_easy \
--cam-calib /workspace/configs/my_euroc_calib.json \
--dataset-type euroc \
--config-path /workspace/external/basalt/data/euroc_config.json \
--marg-data /workspace/results/marg_data/mh_01_easy \
--save-trajectory /workspace/results/trajectories/traj_mh_01_easy.csv \
--show-gui 0 --use-imu 1# Run complete evaluation
./scripts/evaluate_results.sh
# Or use Python script directly
python scripts/evaluate_trajectories.py --dataset all
# Evaluate single dataset
python scripts/evaluate_trajectories.py --dataset MH_01_easy# Quick summary
cat results/evaluation/README.md
# Detailed JSON metrics
python -m json.tool results/evaluation/all_results.json
# View specific plots
xdg-open results/evaluation/mh_01_easy/trajectory_3d.pngBest for interactive development and debugging:
# Build
docker build -f docker/Dockerfile.dev -t vio-slam-dev .
# Run with GUI support (X11)
docker run -it \
-v $(pwd)/data:/workspace/data \
-v $(pwd)/results:/workspace/results \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e DISPLAY=$DISPLAY \
vio-slam-dev
# Or use docker-compose
docker-compose up -d dev
docker-compose exec dev bashFeatures:
- Interactive bash shell
- GUI visualization support (Pangolin)
- All development tools included
- Manual control over build and execution
Best for automated pipeline execution:
# Build
docker build -f docker/Dockerfile -t vio-slam-run .
# Run complete pipeline
docker run \
-v $(pwd)/data:/workspace/data \
-v $(pwd)/results:/workspace/results \
vio-slam-run
# Or use docker-compose
docker-compose up runAutomatic Execution:
- Builds Basalt (if needed)
- Runs VIO on all datasets
- Generates trajectories
- Evaluates results
- Creates plots and statistics
- Exits with results in
results/
Both containers use these mounts:
volumes:
- ./data:/workspace/data # Input datasets
- ./results:/workspace/results # Output results
- ./configs:/workspace/configs # Calibration files (optional)- What: Global position accuracy after optimal alignment
- Units: meters (m)
- Calculation: RMSE of position differences after SE(3) alignment
- Our Results: 5-7 cm (excellent)
- Interpretation: Overall system accuracy and calibration quality
- What: Local frame-to-frame accuracy
- Units: meters (m) or meters per meter (m/m)
- Calculation: RMSE of relative pose differences
- Our Results: 2-4 cm/m (excellent)
- Interpretation: Drift rate and short-term tracking quality
| ATE RMSE | Assessment | Use Case |
|---|---|---|
| < 0.10 m | β Excellent | Research and robotics |
| 0.10-0.20 m | Acceptable for many applications | |
| 0.20-0.50 m | Needs improvement | |
| > 0.50 m | β Poor | Not suitable |
| RPE RMSE | Assessment | Drift Rate |
|---|---|---|
| < 0.03 m/m | β Excellent | < 3% per meter |
| 0.03-0.05 m/m | 3-5% per meter | |
| 0.05-0.10 m/m | 5-10% per meter | |
| > 0.10 m/m | β Poor | > 10% per meter |
-
Continuous-Time Representation
- B-spline-based trajectory representation
- Smooth interpolation between poses
- Proper IMU integration
-
Square-Root Keyframe BA
- Numerically stable optimization
- Efficient marginalization
- Robust outlier rejection
-
Visual-Inertial Fusion
- Tightly-coupled optimization
- Pre-integration theory
- Proper uncertainty propagation
-
Optical Flow Tracking
- Multi-scale KLT tracking
- Grid-based feature distribution
- Photometric calibration support
From configs/my_euroc_calib.json and euroc_config.json:
{
"optical_flow_type": "frame_to_frame",
"optical_flow_detection_grid_size": 50,
"optical_flow_max_level": 3,
"vio_max_states": 3,
"vio_max_kfs": 7,
"vio_filter_iteration": 4,
"vio_outlier_threshold": 3.0
}See results/stats/ for:
stats_vio_*.ubjson- VIO tracking statisticsstats_sums_*.ubjson- Summary statisticsstats_all_*.ubjson- Complete statisticsresult_*.json- Formatted results
results/
βββ evaluation/
β βββ all_results.json # Combined metrics
β βββ mh_01_easy/
β β βββ evaluation_results.json # Detailed metrics
β β βββ trajectory_3d.png # 3D comparison
β β βββ trajectory_2d.png # Top-down view
β β βββ ate_over_time.png # Error evolution
β β βββ rpe_over_time.png # Drift analysis
β β βββ xyz_errors.png # Component errors
β βββ v1_03_difficult/
β βββ [same structure]
βββ groundtruth/
β βββ gt_mh_01_easy.csv # Processed GT
β βββ gt_v1_03_difficult.csv # Processed GT
βββ marg_data/
β βββ [marginalization data]
βββ stats/
β βββ [JSON and UBJSON statistics]
βββ trajectories/
βββ traj_mh_01_easy.csv # Estimated trajectory
βββ traj_v1_03_difficult.csv # Estimated trajectory
All plots generated at 300 DPI for publication quality.
# Clean rebuild
rm -rf external/basalt/build
cd external/basalt
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y \
libeigen3-dev libtbb-dev libopencv-dev libfmt-dev \
libglew-dev cmake ninja-build python3-pip
# Python packages
pip3 install evo matplotlib pandas numpy# Enable X11 forwarding (SSH)
ssh -X user@host
# Or run without GUI
./basalt_vio --show-gui 0 ...
# Docker with X11
xhost +local:docker
docker run -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix ...# Verify structure
ls -la data/MH_01_easy/mav0/
# Should contain: cam0/, cam1/, imu0/, state_groundtruth_estimate0/
# Check ground truth format
head data/MH_01_easy/mav0/state_groundtruth_estimate0/data.csv# Fix permissions
chmod +x scripts/*.sh
sudo chown -R $USER:$USER data/ results/Tested Datasets:
- β EuRoC MAV (MH_01_easy, V1_03_difficult)
- β Not yet tested on TUM-VI, UZH-FPV, or custom datasets
System Configuration:
- β Stereo VIO with IMU (ADIS16448-grade sensor)
- β VIO-only (no loop closure, relocalization, or global optimization)
- β Monocular configurations not validated
Environment:
- β Indoor environments with good lighting and texture
β οΈ Outdoor performance not validated- β Not tested in low-light, featureless, or highly dynamic scenes
-
Long-term Drift: VIO-only system accumulates drift over extended missions (>10 minutes)
- Mitigation: Add loop closure or global optimization for longer sequences
-
Feature Tracking: Performance degrades in challenging visual conditions
- Motion blur during fast movements
- Featureless environments (walls, uniform textures)
- Lighting changes or overexposure
-
IMU Requirements: Requires IMU-grade sensor (MEMS acceptable, consumer-grade may struggle)
- Proper calibration essential (noise parameters, biases)
- Time synchronization with camera critical (<2ms jitter)
-
Computational Cost: Real-time performance depends on hardware
- Development tested on desktop CPU
- Embedded deployment may require optimization or GPU acceleration
-
Scale Observability: Stereo provides metric scale naturally
- Monocular VIO would require scale initialization or external reference
Suitable:
- Short to medium duration missions (<10 minutes)
- Indoor and structured environments
- Robotics research and benchmarking
- Visual-inertial odometry frontend for SLAM systems
- Augmented reality tracking in controlled settings
Not Recommended Without Modifications:
- GPS-denied long-term autonomous navigation
- Safety-critical applications without redundancy
- Production deployment without additional validation
- Environments with frequent tracking loss
@inproceedings{usenko2020basalt,
title={The Basalt Framework for Visual-Inertial Odometry},
author={Usenko, Vladyslav and Demmel, Nikolaus and
Schubert, David and others},
booktitle={IEEE/CVF CVPR},
year={2020}
}@article{burri2016euroc,
title={The EuRoC micro aerial vehicle datasets},
author={Burri, Michael and Nikolic, Janosch and
Gohl, Pascal and others},
journal={Int. J. Robotics Research},
year={2016}
}This project follows the license terms in LICENSE.
Basalt framework: BSD-3-Clause (see external/basalt/LICENSE)
- Basalt Team - Outstanding VIO framework
- EuRoC Team - High-quality benchmark datasets
- evo Author (Michael Grupp) - Professional evaluation toolkit
π§ Questions? See detailed documentation in docs/ or check docker/README.md for Docker-specific issues.




