OpenVSLAMのビルドと360度カメラサンプル実行まで

#はじめに
「ここはどこ？あたすは誰？」「迷える子羊よ、vSLAMを使いなさい」という話が聖書にあったかどうかは定かではありませんが、本日は画像による自己位置推定のvisual SLAMを使えるようになろう、というお話です。しかも、360度カメラを使ったお話です。イメージはこちら：
![openvslam_slam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/753103/09927be4-c48b-f56a-9880-edf50cbe4c2a.png)

OpenVSLAMは日本の産業技術総合研究所（AIST）が開発した、単眼、ステレオ、RGBDカメラ、360度カメラで動く、オープンソースのvisual SLAMソフトです。
特徴はなんといっても、360度カメラでも動くことではないでしょうか。
さて、そのOpenVSLAMですが、[オリジナル](https://github.com/xdspacelab/openvslam)は公開が中止になっていました。
ややや、なんてこった、と思って探すと、コミュニティがforkしているものは引き続き公開されています。 
私は今回２種類のPCに入れて試したのですが、手間取った部分があったので、スクリプトを作って、これを実行すれば、ひとまず自分のPCで、サンプルの360度カメラ画像でVSLAMが動くようにしたので、共有いたします。

(2021.7.2追記)以下の内容は、mainにpull requestが取り込まれたので、openvslamをcloneしたあと、scripts/ubuntuにすでにスクリプトが入っています。


#動作確認した環境
OS： Linux
Distribution: Ubuntu 20.04
GPU: GTX1060, RTX3070
ビルド環境： Docker 20.10.7

注意: 
WSLを利用する場合は、Xwindowを使うため、[こちら](https://www.atmarkit.co.jp/ait/articles/1812/06/news040.html)を参考にVcXsrvをインストールすると良いと思います。


#install docker
今回、OpenVSLAMはDocker上で実行します。
もしまだdockerを入れていなければ、下記で入れておきましょう。
下記はスクリプトになっていますので、コピペして、install_docker.shなどと名前をつけて実行($sh ./install_docker.sh)すれば、１コマンドでインストールできます。

```
#!/bin/sh

# Uninstall old versions
sudo apt-get remove docker docker-engine docker.io containerd runc

# Set up the repository
sudo apt-get update
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

# Manage Docker as a non-root user
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker

# Verify that Docker Engine is installed correctly by running the hello-world image.
docker run hello-world
```
reference [official docker document](https://docs.docker.com/engine/install/ubuntu/), [official post process](https://docs.docker.com/engine/install/linux-postinstall/)


# install nvidia GPU supported docker
NVIDIAのGPU搭載マシンであれば、こちらも入れましょう。なければスキップしていただいてもいいかと思いますが、検証はしていません。
以下を、install_nvidia_docker.shなどと命名して実行するだけで大丈夫です。

```
#!/bin/sh

# update repository
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \
  sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \
  sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update

# install nvidia GPU support docker
sudo apt install -y nvidia-container-toolkit
```
reference [nvidia-docker official page](https://nvidia.github.io/nvidia-docker/), [nvidia-docker github page](https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(Native-GPU-Support))

### trouble shoot
- dockerコマンド発行時に、「Got permission denied while trying to connect to the Docker daemon socket」というエラーに遭遇した場合の対処法。
    - 私の場合はlogout, loginだけではうまく行かず、rebootが必要でした。


# get source code
次に、Githubからサブモジュールを含めて、ソースコードをクローンします。
OpenVSLAMを配置したい、お好きなディレクトリに移って下記を実行して下さい。

```   ​
git clone https://github.com/OpenVSLAM-Community/openvslam.git
cd openvslam
git submodule update -i --recursive
```
reference: [openvslam community official document](https://openvslam-community.readthedocs.io/en/latest/installation.html#chapter-installation)


# download sample data to run tests
次に、Dockerを起動する前に、サンプル動作で必要なファイルをダウンロードしておきましょう。
以下をdownload_sampledata.shなどと名前をつけ、 先程クローンしたopenvslam ディレクトリの下に、　scripts/ubuntu　というディレクトリを作り、そこに置いて実行してください。（現在これら一連のscriptを入れたPull requestが取り込まれています）

```
#!/bin/sh

TOPDIR=$PWD/../../ #openvslam directory

# create data directory to store downloaded data
mkdir $TOPDIR/dataset
mkdir $TOPDIR/vocab

# download an ORB vocabulary from GitHub
(
    cd ${TOPDIR}/vocab
    curl -sL "https://github.com/OpenVSLAM-Community/FBoW_orb_vocab/raw/main/orb_vocab.fbow" -o orb_vocab.fbow
)

# download a sample dataset from Google Drive
(
    cd $TOPDIR/dataset
    FILE_ID="1d8kADKWBptEqTF7jEVhKatBEdN7g0ikY"
    curl -sc /tmp/cookie "https://drive.google.com/uc?export=download&id=${FILE_ID}" > /dev/null
    CODE="$(awk '/_warning_/ {print $NF}' /tmp/cookie)"
    curl -sLb /tmp/cookie "https://drive.google.com/uc?export=download&confirm=${CODE}&id=${FILE_ID}" -o aist_living_lab_1.zip
    unzip aist_living_lab_1.zip
    
# download a sample dataset from Google Drive
    FILE_ID="1TVf2D2QvMZPHsFoTb7HNxbXclPoFMGLX"
    curl -sc /tmp/cookie "https://drive.google.com/uc?export=download&id=${FILE_ID}" > /dev/null
    CODE="$(awk '/_warning_/ {print $NF}' /tmp/cookie)"
    curl -sLb /tmp/cookie "https://drive.google.com/uc?export=download&confirm=${CODE}&id=${FILE_ID}" -o aist_living_lab_2.zip
    unzip aist_living_lab_2.zip
)
```
reference [official openvslam doc](https://openvslam-community.readthedocs.io/en/latest/simple_tutorial.html#chapter-simple-tutorial)


# build OpenVSLAM
いよいよOpenVSLAMをビルドします。今回は設定が楽なのでDockerを使います。
以下を、build_openvslam.sh などと名前をつけ、openvslam/scripts/ubuntu　の下に置いて実行してください。

```
#!/bin/sh

TOPDIR=$PWD/../../ #openvslam directory

( 
    cd $TOPDIR

    # Building Docker Image
    docker build -t openvslam-desktop -f Dockerfile.desktop . --build-arg NUM_THREADS=7

    # Starting Docker Container
    # before launching the container, allow display access from local users
    xhost +local:
    # launch the container
    docker run -it --rm --gpus all -e DISPLAY=$DISPLAY -v /tmp/.X11-unix/:/tmp/.X11-unix:ro --volume ${TOPDIR}/dataset:/dataset:ro --volume ${TOPDIR}/vocab:/vocab:ro openvslam-desktop
)
```
注意: 

1. 一番最後の「docker run -it --rm --gpus all ...」のところは、GPUがなければ、「--gpu all」を消して実行すれば行けるかもしれません（公式ページには、--gpuはデフォルトでは付いていませんでした。しかし、ちらっと試しましたところできなかったので、何とも言えません）
1. 2回目以降、Dockerを立ち上げる際は、最後の行の「docker run -it ...」だけ実行すれば良いですが、その際、データが何故かトップディレクトリではなく、一つ上のディレクトリにマウントされているので、次節のサンプルを実行する際は、下記コマンドで実行して下さい。

```
./run_video_slam -v ../vocab/orb_vocab.fbow -m ../dataset/aist_living_lab_1/video.mp4 -c ../example/aist/equirectangular.yaml --frame-skip 3 --no-sleep --map-db map.msg
```

# run sample
ここまでを実行すると、Dockerの中に入っている状態で、"root@*****:/openvslam/build#"のようなターミナル画面が出ているはずです。
その表示されているターミナルに以下を打てば、ウィンドウが２つ立ち上がり、冒頭でもお見せした、以下の写真のようなサンプルデータのデモが実行され始めるはずです。

```
# run tracking and mapping
./run_video_slam -v /vocab/orb_vocab.fbow -m /dataset/aist_living_lab_1/video.mp4 -c ../example/aist/equirectangular.yaml --frame-skip 3 --no-sleep --map-db map.msg
```
![openvslam_slam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/753103/09927be4-c48b-f56a-9880-edf50cbe4c2a.png)

補足:
real time性はなくても、できるだけ精度よく実行したい場合は、" --frame-skip 3 --no-sleep"を消して実行すれば良いです。

ウィンドウの動きが止まったら、ウィンドウの左側にある、Terminateボタンを押します。 すると、"map.msg"が、現在のディレクトリに保存されます。これを用いて次はTrackingのデモが実行できます。以下のコマンドをDockerのターミナルに打つと、下の写真のような、Trackingのデモが開始されます。

```
# run localization
./run_video_localization -v /vocab/orb_vocab.fbow -m /dataset/aist_living_lab_2/video.mp4 -c ../example/aist/equirectangular.yaml --frame-skip 3 --no-sleep --map-db map.msg
```
![openvslam_track.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/753103/55add722-6ade-98eb-4938-3ea11339a6e0.png)


# run OpenVSLAM on your own video
ご自分の360 mp4動画で試す場合は、dataset/の下に、パノラマ画像に変換された360動画を入れ、exampleの下のaist/equirectangular.yamlをコピーして、画像サイズをご自分のmp4ファイルのものに変えて、 scripts/ubuntu/build_openvslam_docker.shを実行後、上記run sampleのmp4動画とyamlファイルを書き換えればOK。
Richo theta Z1で試した結果のキャプチャがこちら。（画像が荒くてすみません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/753103/783fa905-625d-5945-3b39-560600cd11bc.png)


# 終わりに
やっぱりvslamは、結果が3次元なので見栄えがして面白いですよね。萌えー。
次回は、vslamの真価である、リアルタイムにvslamを実行することを、公開されているROS版で実施してご報告したいと思います。チャオ！