C++

C++はSLAMの作業言語である。後のレベルで学ぶほぼすべてのシステム——ORB-SLAM、DSO、VINS-Mono、KinectFusion——はC++で書かれている。なぜなら、SLAMはカメラフレーム、IMUパケット、最適化問題を、制約のあるハードウェア上でリアルタイムに処理しなければならないからだ。このレベルにおいて「C++を知っている」とは、単に文法を知っているということではなく、SLAMのコードベースが使う特有のイディオムとツールチェインで生産的に働けるということを意味する。

モダンC++(C++11/14/17/20)。 SLAMのコードはモダンなイディオムに生死を懸けている。範囲for文、auto、ラムダ関数、std::thread、スマートポインタ、ムーブセマンティクスなどである。特にムーブセマンティクスが重要なのは、SLAMが大きなオブジェクト(画像、点群、記述子行列)を持ち歩くため、ホットループ内での不意の深いコピーを許容できないからである。

OOPとデザインパターン。 SLAMシステムは、トラッカー、ローカルマッパー、ループクローザー、マップデータベースといった、スレッド間で状態を共有する相互作用するモジュールとして構成されている。継承と合成の違い、センサー抽象化のためのインターフェース、そして一般的なパターン(マップデータベースのためのシングルトン、センサードライバのためのファクトリー、pub/sub風のコールバックのためのオブザーバー)を理解していれば、ORB-SLAMのような大規模なコードベースが読みやすくなる。

データ構造とアルゴリズム。 複雑度について常に考える必要がある。最近傍探索のためのkd-treeやハッシュグリッド、キーフレーム削減のための優先度付きキュー、共視性やポーズグラフ構造のためのグラフなどである。適切なコンテナ(std::vectorstd::unordered_map)を選ぶことは、フレームレートに目に見える影響を与える。

コンパイラとビルドシステム。 実際のプロジェクトは、MakeやNinjaを駆動するCMakeでビルドされる。Eigen/OpenCVを見つけ、最適化フラグ(-O3-march=native)を設定し、サードパーティのサブモジュールを管理するCMakeLists.txtを読み書きできるようになっておくこと。SLAM風の最小限のCMakeLists.txtは以下のようになる。

cmake_minimum_required(VERSION 3.16)
project(my_vo)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_BUILD_TYPE Release)          # forget this and everything is "slow"

find_package(OpenCV REQUIRED)
find_package(Eigen3 REQUIRED)

add_executable(vo main.cpp)
target_link_libraries(vo ${OpenCV_LIBS} Eigen3::Eigen)

コンパイラが何をしているのか(インライン化、ベクトル化、デバッグビルドとリリースビルドの違い)をおおまかに知っていれば、なぜ「遅い」SLAMシステムが実は単にデバッグビルドだったというだけの話であることが多いのかが理解できる。

C++でのOpenCV。 OpenCVは画像処理層のデフォルトである。画像の読み込みとディストーション補正、特徴点検出(cv::ORBcv::SIFT)、マッチング(cv::BFMatchercv::FlannBasedMatcher)、姿勢推定(cv::solvePnP)、そしてキャリブレーション(cv::calibrateCamera)がある。最小限の特徴点パイプラインは以下のようになる。

cv::Ptr<cv::ORB> orb = cv::ORB::create(2000);
std::vector<cv::KeyPoint> kps;
cv::Mat desc;
orb->detectAndCompute(img, cv::noArray(), kps, desc);

cv::BFMatcher matcher(cv::NORM_HAMMING);
std::vector<cv::DMatch> matches;
matcher.match(desc_prev, desc, matches);

実際のSLAMシステムにおける並行処理

リアルタイムSLAMシステムは、複数の粒度で並列性を積極的に利用する。

よくある落とし穴

SLAMにおける意義

このレベル以上のすべては、あなたが中規模のC++コードベースを読み、ビルドし、修正できることを前提としている。論文を再現するとは、通常、C++リポジトリをクローンし、そのCMakeビルドをあなたのローカルのEigen/OpenCVバージョンに対して修正し、時間がどこに使われているかをプロファイルすることを意味する。C++の流暢さは、SLAMシステムを使うことから変えることへ——特徴点検出器を交換したり、センサーを追加したり、スレッド化やSIMDでボトルネックを最適化したりすることへ——移行するために必要なものでもある。

ハンズオン

関連ノート