SLAM is typically used for robot perception and autonomous vehicle navigation as it can be used for building 3D world maps quickly. The algorithm processes sensor data online, determining the pose of the sensor while incrementally building a model of the environment. It is well suited to multithreaded implementation on modern computers.
Visual SLAM refers to a variant of SLAM that uses either monocular images, stereo images or images from an RGB-D camera. SLAM variants may use other sensing modalities such as LIDAR and SONAR. Algorithms that support Inertial Measurement Units (IMU) use the term inertial, e.g. VI-SLAM, Visual Inertial SLAM.
The Difference between Visual SLAM and Structure from Motion
Visual SLAM (VSLAM) processes video frame by frame so tracking is easier as feature points have moved only a small amount. SLAM will only keep keyframes for map building rather than use all the frames. Frequent optimisation is employed to keep the map accurate, but sometimes incorrect matching can result in propagated errors that can be difficult to automatically recover from. Ensuring that the path the sensor travels frequently crosses previous locations can give rise to constraints that limit the amount of drift. When these crossing points occur they are known as Loop Closures (LC). The online nature allows the sensor to be controlled interactively which can be important in unknown environments.
Structure from Motion (SfM) processes all frames offline and the order of images may be random. COLMAP can find it difficult to choose which images to use as a starting point but it does have features such as additional matching and manually choice of initial images for difficult cases. Because SfM is designed as an offline operation, there is an opportunity for human review of the images that are used to build the model.
What makes a good SLAM algorithm?
Pros
Cons
In this section, the key points of two of the current best SLAM algorithms are very briefly described.
ORB-SLAM 3 is a complete SLAM system based on the previous ORB-SLAM algorithms that use ORB features to build a covisibility graph to manage tracking and matching. If the system loses localisation, a bag of words database is used to find the most similar keyframe position on the map.
A feature called Atlas manages multiple maps: if the system takes too long to relocalise, processing can continue by starting a new map and then looking for similarities between maps. If a similarity is found then the maps are merged. Atlas allows for multi session capability; either extending maps created previously or using multiple robots to collaboratively build a single map.
ORB-SLAM 3 is a classical algorithm and often used as a reference comparison when evaluating new techniques.
DROID-SLAM is a deep learning based SLAM. It builds a dense map while estimating camera poses using a feature extraction network and dense bundle adjustment. Recurrent iterative optimisation is used (the same authors also wrote the RAFT paper explored in my optical flow demonstration).
Using dense learned features to keep optical flow based tracking of features and a learned update that maps flow to pose and dense depth updates results in a method that is neither direct or indirect. Similar to ORB-SLAM, a frame graph represents visibility between frames. If the camera revisits a region then edges are added to the graph for Loop Closure.
If all the processes are run on the same GPU then the result is deterministic. ORB-SLAM and many other classical SLAM algorithms cannot produce a deterministic result because they use RANSAC for estimation.
DROID-SLAM is the current state of the art technique, outperforming both classical and deep learning based algorithms.
Outline of the Visual SLAM algorithm:
For my asymmetrical stereo camera system, this is the workflow needed to obtain camera poses and a sparse reconstruction:
Code on github - additional code is linked below
You should either calibrate the camera rig in advance or you can use the calibrations linked below.
In this example we will create a dataset specifically for running SLAM on it. You will need to copy camera calibration and LUT data files to somewhere accessible by the docker and use scripts from the slam and stereocamera sections of my TechDemo repository on github.
Make a directory for the project and copy the video files to it, e.g.
mkdir -p /data/project
cp GX001000.MP4 /data/project
cp GO000001.MP4 /data/projectRun my techdemo docker image,
rundocker.sh techdemo /dataInstall the required python frameworks using the requirements.txt file.
My TechDemo docker image is missing the venv package so install it first if you need it,
sudo apt update
sudo apt install python3.10-venvNow set up the venv and install the packages,
python3 -m venv .venv
source .venv/bin/activate
pip3 install -r requirements.txtRun stsync.py to extract synchronised frames and apply colour correction,
cd /work/project
mkdir rig
stsync.py --left GX001000.MP4 --right GO00001.MP4 --output rig --lut h3.cube
The intrinsic calibration files are from my GoPro Calibrations repository on github and the extrinsics and LUT files are in stereocamera/data at my TechDemo repository.
Make a directory to store the images and related files,
mkdir datasetUsing precomputed calibration and create_dataset.py, create rectified images from the synchronised frames, a config file and timestamps file,
create_dataset.py --input rig --leftcal /work/hero10-1080-wide-f.yaml \
--rightcal /work/hero3-1080-wide-f.yaml --extcal /work/stereo.yaml \
--output datasetRun my modified ORB-SLAM 3 docker image (it will be built on the first run or you can do this in advance),
rundocker.sh orbslam3 /data
I'm using the community version of ORB-SLAM 3 maintained by Jeremy Salwen. The authors original code has known issues with fixes available which have been applied in his repo.
Run the setup.sh script to copy code for stereo_asym into the local ORB-SLAM 3 codebase, patch and build it,
setup.shRun ORB-SLAM 3,
cd ~/ORB_SLAM_COMMUNITY/Examples/Stereo
./stereo_asym ../../Vocabulary/ORBvoc.txt /work/project/dataset/settings.yaml /work/project/dataset /work/project/dataset/timestamps.txtObserve ORB-SLAM 3 running on the data,
ORB-SLAM 3 Reconstruction
This image shows the keyframes and sparse reconstruction for my Beetle dataset.
Copy the sparse reconstruction to the host computer,
cp map.ply /work/project
Open the map.ply file in MeshLab, CloudCompare or a tool of your choice
ORB-SLAM 3 can work with unrectified images but for simplification of processing and to avoid mixing different lens models I chose to rectify images during preprocessing.
DROID-SLAM will be run on the same dataset; note that the documentation suggests that you will need at least 12GB VRAM,
git clone --recursive https://github.com/princeton-vl/DROID-SLAM.git
Run my techdemo docker image, make sure to mount the filesystem so that you can access the code just downloaded,
rundocker.sh techdemo /dataInstall the Python venv package if you need it,
sudo apt update
sudo apt install python3.10-venv
Follow the DROID-SLAM installation instructions as below; my techdemo docker image is running CUDA 11.8 so I had to install a version of torch that was built for it,
cd /work/DROID-SLAM
python3 -m venv .venv
source .venv/bin/activate
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
Now edit requirements.txt to remove the top 3 lines that install torch and continue with the installation. I also had to disable build isolation for pytorch scatter,
pip3 install -r requirements.txt
pip3 install moderngl moderngl-window
pip3 install thirdparty/lietorch
pip3 install thirdparty/pytorch_scatter
pip3 install --no-build-isolation --force-reinstall --no-binary=torch_scatter thirdparty/pytorch_scatter
pip3 install -e .
./tools/download_model.sh
Copy test_asym.py and load_settings.py from the DROID-SLAM section of my code repository to the evaluation_scripts directory,
cp /work/slam/droid_slam/test_asym.py /work/DROID-SLAM/evaluation_scripts
cp /work/slam/droid_slam/load_settings.py /work/DROID-SLAM/evaluation_scripts
Run the script,
cd /work/DROID-SLAM
python3 evaluation_scripts/test_asym.py --datapath /work/project/dataset --stereo --ply map.plyMy setup (Ryzen 5 + RTX 3060Ti) takes about 5 minutes to initialise.
If you use the --reconstruction parameter, you may specify
a file to save the reconstruction to, e.g. --reconstruction map.pth
and view it with python3 view_reconstruction.py map.pth
DROID-SLAM running on my Beetle dataset
This example script loads all of the images into memory before processing so depending on how long your video sequence is, you may run out of memory. DROID-SLAM can accept images input one by one which should allow reduced memory consumption.
Copy the map.ply file to somewhere safe, so you can open it in MeshLab, etc.
cp map.ply /work/reconstructions/project-map.ply
Viewing the Sparse Reconstruction in MeshLab
DROID-SLAM should not be compared to ORB-SLAM 3 by the quality of the visualisation while the algorithm is running, but by the trajectory error, comparisons with known ground truth datasets can be found in the paper. Although DROID-SLAM gives better accuracy it needs more resources than ORB-SLAM, so is less likely to be used when running on an edge device.