# Batch Evaluation of Square Root Optimization and Marginalization In this tutorial we detail how you can use the batch evaluation scripts to reproduce the results of the ICCV'21 paper Demmel et al., "Square Root Marginalization for Sliding-Window Bundle Adjustment". In the paper we discuss how square root estimation techniques can be used in Basalt's optimization-based sliding-window odometry to make optimization faster and marginalization numerially more stable. See the [project page](https://go.vision.in.tum.de/rootvo) for further details. Basalt's VIO/VO now runs with single-precision floating point numbers by default, using the new square root formulation. The conventional squared (Hessian-based) formualtion is still available via config options. For manual testing, you can pass `--use-double true` or `--use-double false` (default) as command line arguments to `basalt_vio`, and change `config.vio_sqrt_marg` in the config file, which controls if the marginalization prior is stored in Hessian or Jacobian form (default: `true`), as well as `config.vio_linearization_type` in the config file, which controls whether to use Schur complement, or nullspace projection and QR-decomposition for optimization and marginalization (`"ABS_SC"` or `"ABS_QR"` (default)). In the following tutorial we systematically compare the different formulations in single and double precision to reproduce the results from the ICCV'21 paper. You can of course adjust the correspondig config files to evaluate other aspects of the system. ## Prerequisites 1. **Source installation of Basalt:** The batch evaluation scripts by default assume that the `build` folder is directly inside the source checkout `basalt`. See [README.md](../README.md#source-installation-for-ubuntu-1804-and-macos-1014-mojave) for instructions. 2. **Downloads of the datasets:** We evaluate EuRoC (all 11 sequneces), TUMVI (euroc format in 512x512 resultion; sequences: corridor1-2, magistrale1-2, room1-2, slides1-2), and Kitti Odometry (sequences 00-10). It's recommended to store the data locally on an SSD to ensure that reading the images is not the bottleneck during evaluation (on a multicore desktop Basalt runs many times faster than real-time). There are instructions for downloading these dataset: [EuRoC](VioMapping.md#euroc-dataset), [TUMVI](VioMapping.md#tum-vi-dataset), [KITTI](Vo.md#kitti-dataset). Calibration for EuRoC and TUMVI is provided in the `data` folder. For KITTI you can use the `basalt_convert_kitti_calib.py` script to convert the provided calibration to a Basalt-compatible format (see [KITTI](Vo.md#kitti-dataset)). 3. **Dependencies of evaluation scripts:** You need pip packages `py_ubjson`, `matplotlib`, `numpy`, `munch`, `scipy`, `pylatex`, `toml`. How to install depends on your Python setup (virtualenv, conda, ...). To just install for the local user with pip you can use the command `python3 -m pip install --user -U py_ubjson matplotlib numpy munch scipy pylatex toml`. For generating result tables and plots you additionally need latexmk and a LaTeX distribution (Ubuntu: `sudo apt install texlive-latex-extra latexmk`; macOS with Homebrew: `brew install --cask mactex`). ## Folder Structure The batch evaluation scripts and config files assume a certain folder structure inside a "parent" folder, since relative paths are used to find the compiled executable and calibration files. So **it's important to follow the folder structure**. ``` parent-folder/ ├─ basalt/ │ ├─ build/ │ │ ├─ basalt_vio │ │ ├─ ... │ ├─ data/ │ │ ├─ euroc_ds_calib.json │ │ ├─ ... │ ├─ ... ├─ experiments/ │ ├─ iccv_tutorial/ │ │ ├─ basalt_batch_config.toml │ │ ├─ experiments-iccv.toml │ │ ├─ 01_iccv_all/ │ │ │ ├─ ... │ │ ├─ 02_iccv_runtime/ │ │ │ ├─ ... ``` As a sibling of the `basalt` source checkout we'll have an `experiments` folder, and inside, a folder `iccv_tutorial` for this tutorial. Into that folder, we copy the provided `basalt_batch_config.toml` file that defines the configurations we want to evaluate and from which we generate individual config files for each VIO / VO run. We also copy the provided `experiments-iccv.toml` config file, which defines the results tables and plots that we generate from the experiments' logs. > *Note:* Commands in this tutorial are assumed to be executed from > within `parent-folder` unless specified otherwise. ```bash mkdir -p experiments/iccv_tutorial cp basalt/data/iccv21/basalt_batch_config.toml experiments/iccv_tutorial/ cp basalt/data/iccv21/experiments-iccv.toml experiments/iccv_tutorial/ ``` ## Generate Experimental Configs First, edit the copied configuration file `experiments/iccv_tutorial/basalt_batch_config.toml` and modify all `"dataset-path"` lines to point to the locations where you downloaded the datasets to. Now, we can generate per-experiment config files: ```bash cd experiments/iccv_tutorial/ ../../basalt/scripts/batch/generate-batch-configs.py . ``` This will create subfolder `01_iccv_all` containing folders `vio_euroc`, `vio_tumvi`, and `vo_kitti`, which in turn contain all generated `basalt_config_...json` files, one for each experiment we will run. ## Run Experiments We can now run all experiments for those generate configs. Each config / sequence combination will automatically be run twice and only the second run is evaluated, which is meant to ensure that file system caches are hot. Since we also evaluate runtimes, we recommend that you don't use the machine running the experiments for anything else and also ensure no expensive background tasks are running during the evaluation. On one of our desktops with 12 (virtual) cores the total evaluation of all sequences takes aroudn 3:30h. Your milage may vary of course depending on the hardware. ```bash cd experiments/iccv_tutorial/ time ../../basalt/scripts/batch/run-all-in.sh 01_iccv_all/ ``` Inside `01_iccv_all`, a new folder with the start-time of the experimental run is created, e.g., `20211006-143137`, and inside that you can again see the same per-dataset subfolders `vio_euroc`, `vio_tumvi`, and `vo_kitti`, inside of which there is a folder for each config / run. Inside these per-run folders you can find log files including the command line output, which you can inspect in case something doesn't work. In a second terminal, you can check the status of evaluation while it is running (adjust the argument to match the actual folder name). ```bash cd experiments/iccv_tutorial/ ../../basalt/scripts/batch/list-jobs.sh 01_iccv_all/20211006-143137 ``` If you see failed experiments for the square root solver in single precision, don't worry, that is expected. ## Generate Results Tables and Plots After all experimental runs have completed, you can generate a PDF file with tabulated results and plots, similar to those in the ICCV'21 paper. ```bash cd experiments/iccv_tutorial/ ../../basalt/scripts/batch/generate-tables.py --config experiments-iccv.toml --open ``` The results are in the generated `tables/experiments-iccv.pdf` file (and with the `--open` argument should automatically open with the default PDF reader). ## Better Runtime Evaluation The experiments above have the extended logging of eigenvalue and nullspace information enabled, which does cost a little extra runtime. To get a better runtime comparison, you can re-run the experiments without this extended logging. The downside is, that you can only generate the results tables, but not the plots. We assume that you have already followed the tutorial above, including the initial folder setup. For these modified experiments, we redo all three steps (generating config files; running experiments; generating results) with slight modifications. First, edit the `experiments/iccv_tutorial/basalt_batch_config.toml` file at the bottom, and uncomment the commented entries in `_batch.combinations` as well as the commented `revision`. At the same time, comment out the initially uncommented lines. It should look something like this after the modifications: ```toml [_batch.combinations] #vio_euroc = ["vio", "savetumgt", "extlog", "runtwice", "all_meth", "all_double", "all_euroc"] #vio_tumvi = ["vio", "tumvivio", "savetumgt", "extlog", "runtwice", "all_meth", "all_double", "more_tumvi"] #vo_kitti = ["vo", "kittivo", "savetumgt", "extlog", "runtwice", "all_meth", "all_double", "all_kitti"] vio_euroc = ["vio", "runtwice", "all_meth", "all_double", "all_euroc"] vio_tumvi = ["vio", "tumvivio", "runtwice", "all_meth", "all_double", "more_tumvi"] vo_kitti = ["vo", "kittivo", "runtwice", "all_meth", "all_double", "all_kitti"] ``` ```toml [_batch] #revision = "01_iccv_all" revision = "02_iccv_runtime" ``` You can see that we removed the `savetumgt` and `extlog` named config elements and that generated config files and results for this second run of experiments will be placed in `02_iccv_runtime`. Now generate config files and start the experimental runs: ``` cd experiments/iccv_tutorial/ ../../basalt/scripts/batch/generate-batch-configs.py . time ../../basalt/scripts/batch/run-all-in.sh 02_iccv_runtime/ ``` Before generating the results PDF you need to now edit the `experiments-iccv.toml` file, point it to the new location for experimental logs and disable the generation of plots. Check the place towards the start of the file where substitutions for `EXP_PATTERN_VIO` and `EXP_PATTERN_VO` are defined, as well as `SHOW_TRAJECTORY_PLOTS`, `SHOW_EIGENVALUE_PLOTS`, and `SHOW_NULLSPACE_PLOTS`. After your modifications, that section should look something like: ```toml ################### ## where to find experimental runs [[substitutions]] #EXP_PATTERN_VIO = "01_iccv_all/*-*/vio_*/" #EXP_PATTERN_VO = "01_iccv_all/*-*/vo_*/" EXP_PATTERN_VIO = "02_iccv_runtime/*-*/vio_*/" EXP_PATTERN_VO = "02_iccv_runtime/*-*/vo_*/" ################### ## which kind of plots to show [[substitutions]] SHOW_TRAJECTORY_PLOTS = false SHOW_EIGENVALUE_PLOTS = false SHOW_NULLSPACE_PLOTS = false ``` Now we can generate the results tables for the new experimental runs with the same command as before: ```bash cd experiments/iccv_tutorial/ ../../basalt/scripts/batch/generate-tables.py --config experiments-iccv.toml --open ```