This repo provides a single flag-based Stereo VO + iSAM2 pipeline for KITTI odometry.
Use run_isam2_kitti.py (single sequence) or run_all_gt_sequences.py (batch) with flags:
base: odometry-only iSAM2 (default)loop-closure: add geometric loop-closure factors (--enable-loop-closure)confidence-v1: confidence-weighted odometry (--enable-confidence-weighting)confidence-v2: stronger confidence weighting + robust kernels (--enable-confidence-v2)info-weighted: information-weighted odometry using inlier count, match count, and reprojection error (--enable-info-weighting)degeneracy-aware+loop: observability-aware odometry noise scaling with loop closure (--degeneracy-aware --enable-loop-closure)
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtExpected --dataset-root structure:
<KITTI_DATASET_ROOT>/
poses/
00.txt
01.txt
...
sequences/
00/
image_0/
image_1/
calib.txt
times.txt
01/
...
Use --seq 00 (or any sequence id) and choose one method configuration.
python3 run_isam2_kitti.py \
--dataset-root <KITTI_DATASET_ROOT> \
--seq 00 \
--fallback-no-motion \
--output output/experiments/base/seq00_allframes/poses_est_00.txt \
--metrics-out output/experiments/base/seq00_allframes/metrics_00.jsonpython3 run_isam2_kitti.py \
--dataset-root <KITTI_DATASET_ROOT> \
--seq 00 \
--fallback-no-motion \
--enable-loop-closure \
--output output/experiments/loop_closure/seq00_allframes/poses_est_00.txt \
--metrics-out output/experiments/loop_closure/seq00_allframes/metrics_00.jsonpython3 run_isam2_kitti.py \
--dataset-root <KITTI_DATASET_ROOT> \
--seq 00 \
--fallback-no-motion \
--enable-confidence-weighting \
--confidence-floor 0.08 \
--confidence-min-scale 0.85 \
--confidence-max-scale 4.0 \
--output output/experiments/confidence_v1/seq00_allframes/poses_est_00.txt \
--metrics-out output/experiments/confidence_v1/seq00_allframes/metrics_00.jsonpython3 run_isam2_kitti.py \
--dataset-root <KITTI_DATASET_ROOT> \
--seq 00 \
--fallback-no-motion \
--enable-confidence-v2 \
--enable-loop-closure \
--confidence-v2-robust-kernel huber \
--confidence-v2-robust-k 1.5 \
--output output/experiments/loop_closure_confidence_v2/seq00_allframes/poses_est_00.txt \
--metrics-out output/experiments/loop_closure_confidence_v2/seq00_allframes/metrics_00.jsonpython3 run_isam2_kitti.py \
--dataset-root <KITTI_DATASET_ROOT> \
--seq 00 \
--fallback-no-motion \
--enable-loop-closure \
--enable-info-weighting \
--info-min-confidence 0.1 \
--info-max-confidence 1.0 \
--output output/experiments/info_weighted_loop/seq00_allframes/poses_est_00.txt \
--metrics-out output/experiments/info_weighted_loop/seq00_allframes/metrics_00.jsonpython3 run_isam2_kitti.py \
--dataset-root <KITTI_DATASET_ROOT> \
--seq 00 \
--fallback-no-motion \
--enable-loop-closure \
--degeneracy-aware \
--degeneracy-cond-ref 800 \
--degeneracy-noise-max-mult 25 \
--output output/experiments/degeneracy_loop/seq00_allframes/poses_est_00.txt \
--metrics-out output/experiments/degeneracy_loop/seq00_allframes/metrics_00.jsonBase:
python3 run_all_gt_sequences.py \
--dataset-root <KITTI_DATASET_ROOT> \
--fallback-no-motion \
--output-dir output/experiments/base/batch_gtLoop closure:
python3 run_all_gt_sequences.py \
--dataset-root <KITTI_DATASET_ROOT> \
--fallback-no-motion \
--enable-loop-closure \
--output-dir output/experiments/loop_closure/batch_gtConfidence v2 + loop:
python3 run_all_gt_sequences.py \
--dataset-root <KITTI_DATASET_ROOT> \
--fallback-no-motion \
--enable-loop-closure \
--enable-confidence-v2 \
--output-dir output/experiments/loop_closure_confidence_v2/batch_gtInfo-weighted + loop:
python3 run_all_gt_sequences.py \
--dataset-root <KITTI_DATASET_ROOT> \
--fallback-no-motion \
--enable-loop-closure \
--enable-info-weighting \
--output-dir output/experiments/info_weighted_loop/batch_gtDegeneracy-aware + loop:
python3 run_all_gt_sequences.py \
--dataset-root <KITTI_DATASET_ROOT> \
--fallback-no-motion \
--enable-loop-closure \
--degeneracy-aware \
--output-dir output/experiments/degeneracy_loop/batch_gt--enable-confidence-v2overrides--enable-confidence-weightingbehavior.--enable-info-weightingcannot be combined with confidence-v1 or confidence-v2.--degeneracy-awarecurrently:- can be used with or without loop closure
- cannot be combined with confidence-v1, confidence-v2, or info-weighting
This repo currently has two output organizations:
- Legacy per-method folders (existing historical outputs under
output/) - Consolidated folders:
output/experiments/output/comparisons/output/manifests/
The consolidation copy manifest is saved at:
output/manifests/output_migration_manifest.json
- Batch metric plots:
plot_batch_metrics.py - Estimate-vs-GT comparisons:
plot_estimate_vs_gt.py - Base-vs-loop comparison:
plot_base_vs_loop.py - Metric utilities:
eval/compute_kitti_metrics.py,eval/loop_closure_gain.py
Use --help on each script for full options.
If the unified main branch does not reproduce expected outputs, run the original method groups on their source branches separately:
loop_vs_loopconf: methods M1-M6degeneracy2.0: methods M7-M8mohammad/information-based-weighting: method M9
Suggested workflow:
git fetch origin
# M1-M6
git checkout loop_vs_loopconf
# M7-M8
git checkout degeneracy2.0
# M9
git checkout mohammad/information-based-weighting
# return to unified implementation
git checkout mainRun each branch's method scripts/configs independently so the nine implementations are executed in their original branch context.