まとめ:SLAMの要点
- SLAMは「未知の環境に置かれたロボットが、地図を作りながら、その地図の中での自分の位置を同時に求める」問題です。自己位置推定だけを指す言葉ではありません。
- 本体はループ閉じ込み(loop closure)です。同じ場所に戻ってきたと判定できる仕組みが無ければ、どれだけ高度な最適化を回してもSLAMは単なるオドメトリに退化します。本記事ではポーズグラフを自作して、この退化を実測で示します。
- ループ閉じ込みは誤ると逆に地図を壊します。正しい拘束21本に誤った拘束を1本混ぜただけで、軌跡誤差は0.293メートルから19.181メートルへ悪化し、オドメトリだけの2.662メートルより悪くなりました。外れ値を抑えるDCSは効きますが、重みのパラメータΦを外すと正しい拘束まで捨てます。
- アルゴリズムはEKF-SLAM・FastSLAM・Graph SLAMの3系統で、現在の実装の主流はGraph SLAMです。EKF-SLAMは共分散の記憶量がランドマーク数の2乗で増え、実測でもランドマーク800個で共分散だけが約20MiBに達しました。
- センサーの選択(LiDARかカメラか)は精度の優劣ではなく、環境の形状が単調かどうか、明るさが安定しているかで決まります。どちらも苦手な環境があります。
- 2026年11月時点でROS 2上の実装を選ぶなら、更新が続いているのはslam_toolboxとRTAB-Mapです。3次元LiDARで人気のKISS-ICPとFAST-LIOは、READMEでオドメトリと名乗っています。単体ではループを閉じません。Cartographerは公式に「もはや積極的には保守されていない」と表明しています。
SLAMとは:地図作成と自己位置推定を同時に解く問題
SLAMの定義と自己位置推定との違い
SLAMはSimultaneous Localization and Mapping(同時自己位置推定・地図作成)の頭字語です。分野の標準的なチュートリアルであるDurrant-WhyteとBaileyの論文(IEEE Robotics and Automation Magazine、2006年)は、この問題を次のように定義しています。
The Simultaneous Localisation and Mapping (SLAM) problem asks if it is possible for a mobile robot to be placed at an unknown location in an unknown environment and for the robot to incrementally build a consistent map of this environment while simultaneously determining its location within this map.
(未知の環境の未知の場所に置かれた移動ロボットが、その環境の一貫した地図を逐次的に構築しながら、同時にその地図の中での自らの位置を決定できるか、を問うのがSLAM問題である)
要は「同時に」の部分です。地図があれば自己位置推定は比較的容易で、自己位置が正確に分かれば地図作成も容易です。SLAMが難しいのは、どちらも分かっていない状態から両方を同時に求める点にあります。GPSも地図も無い屋内・地下・トンネル・水中で必要になる技術で、既存の地図や外部の測位設備が使えるなら、地図作成を伴わない自己位置推定(ローカライゼーション)だけで移動できます。
SLAMの起源と頭字語の命名時期
同じ論文によると、確率的SLAM問題の出発点は1986年にサンフランシスコで開かれたIEEE Robotics and Automation Conferenceです(逐語「The genesis of the probabilistic SLAM problem occurred at the 1986 IEEE Robotics and Automation Conference held in San Francisco.」)。SLAMという頭字語が最初に提示されたのは、1995年のInternational Symposium on Robotics Researchで発表された移動ロボティクスのサーベイ論文だとしています。
この時期に判明した鍵が、ランドマーク同士の相関でした。論文は「the more these correlations grew, the better the solution」(相関が大きく育つほど解は良くなる)と書いており、地図の要素を1つの結合状態として解く設計がここで確立しました。その後については、Cadenaらの2016年のサーベイ(IEEE Transactions on Robotics)が1986年から2004年をclassical age、2004年から2015年をalgorithmic-analysis age(可観測性・収束性の解析と主要なオープンソース実装の時期)と区切り、その先をrobust-perception ageと位置づけています。
SLAMの仕組み:フロントエンドとバックエンド
SLAMのフロントエンドとバックエンドの役割分担
Cadenaらの2016年のサーベイは、SLAMの処理を低位のフロントエンドと高位のバックエンドに分けて整理しています。
- フロントエンド:センサーの生データを幾何的な拘束に変換する層です。LiDARならスキャンマッチング、カメラなら特徴点の抽出と対応付けを行い、「1つ前の姿勢から見て、今の姿勢はこれだけ動いた」という相対姿勢の観測を作ります。同じ場所に戻ってきたことを検出するループ閉じ込みの判定も、ここの仕事です。
- バックエンド:フロントエンドが作った拘束の集合を、最も矛盾が小さくなるように一括で解く層です。本記事で扱うポーズグラフ方式であれば、姿勢をノード、相対姿勢の拘束をエッジとして非線形最小二乗を解きます。方式によっては、ランドマークも推定変数に含めたり、フィルタで逐次更新したりします。
フロントエンドの中身はセンサーで決まります。LiDARの場合、2つの点群を照合して相対変位を求める処理をスキャンマッチングと呼びます。田崎の解説論文「LiDAR を用いた SLAM 技術の現状と展望」(システム/制御/情報 64巻2号、2020年)は、代表的な手法を次のように整理しています。
- ICP(Iterative Closest Point)(Besl・McKay、IEEE TPAMI 1992年):最も近い点どうしを対応させ、距離を反復的に縮めます。実装は簡単ですが、論文は「反復の収束領域が狭いため、初期偏差が大きい場合や点群がノイズを含む場合に局所最適解に停留してしまう恐れがある」と指摘しています。
- NDT(Normal Distribution Transform)(Biber・Straßer):点群をボクセルに分け、各ボクセルの点の分布を正規分布で近似し、その生起確率が最大になる変位を求めます。一般の3次元点群に使えます。
- LOAM:スキャンからエッジ特徴点と平面特徴点を抽出し、それぞれを対応する直線と平面に照合します(Zhang・Singh、RSS 2014)。
カメラの場合は、ORB-SLAM3のように特徴点を抽出して対応付ける特徴点法と、LSD-SLAMのように画素の輝度を直接そろえる直接法に分かれます。どの手法でも出力は「相対姿勢の観測」で、バックエンドから見た形は同じです。
ループ閉じ込み拘束の有無による軌跡誤差の比較
Cadenaらのサーベイは、SLAMとオドメトリの境界をひとことで示しています。
The keyword here is “loop closure”: if we sacrifice loop closures, SLAM reduces to odometry.
(鍵となるのはループ閉じ込みである。ループ閉じ込みを手放せば、SLAMはオドメトリに退化する)
この主張がどの程度のものかを確かめるため、2次元のポーズグラフSLAMをnumpyだけで実装して測りました。1辺25歩の正方形を1周する軌跡(105ノード・104拘束)に、1歩あたり位置0.02メートル・角度1度の雑音を載せたオドメトリを与え、Gauss-Newton法で最適化します。
import numpy as np
def wrap(a):
return (a + np.pi) % (2 * np.pi) - np.pi
def t2v(T): # 同次変換行列 -> [x, y, theta]
return np.array([T[0, 2], T[1, 2], np.arctan2(T[1, 0], T[0, 0])])
def v2t(v): # [x, y, theta] -> 同次変換行列
c, s = np.cos(v[2]), np.sin(v[2])
return np.array([[c, -s, v[0]], [s, c, v[1]], [0, 0, 1]])
def optimize(poses, edges, iters=30):
"""edges: (i, j, 相対姿勢の観測z, 情報行列omega)"""
x = poses.copy()
n = len(x)
for _ in range(iters):
H = np.zeros((3 * n, 3 * n))
b = np.zeros(3 * n)
for i, j, z, omega in edges:
Zij, Xi, Xj = v2t(z), v2t(x[i]), v2t(x[j])
e = t2v(np.linalg.inv(Zij) @ (np.linalg.inv(Xi) @ Xj))
e[2] = wrap(e[2])
A = np.zeros((3, 3)) # 数値微分でヤコビアンを作る
B = np.zeros((3, 3))
dlt = 1e-6
for k in range(3):
dxk = np.zeros(3)
dxk[k] = dlt
ei = t2v(np.linalg.inv(Zij) @ (np.linalg.inv(v2t(x[i] + dxk)) @ Xj))
ej = t2v(np.linalg.inv(Zij) @ (np.linalg.inv(Xi) @ v2t(x[j] + dxk)))
ei[2], ej[2] = wrap(ei[2]), wrap(ej[2])
A[:, k] = (ei - e) / dlt
B[:, k] = (ej - e) / dlt
I, J = slice(3 * i, 3 * i + 3), slice(3 * j, 3 * j + 3)
H[I, I] += A.T @ omega @ A
H[I, J] += A.T @ omega @ B
H[J, I] += B.T @ omega @ A
H[J, J] += B.T @ omega @ B
b[I] += A.T @ omega @ e
b[J] += B.T @ omega @ e
H[0:3, 0:3] += np.eye(3) * 1e6 # 先頭ノードを固定
dx = np.linalg.solve(H, -b).reshape(n, 3)
x = x + dx
x[:, 2] = wrap(x[:, 2])
return x
# ループ閉じ込み=始点と終点が同一地点だと判定できたときに足す1本の拘束
def loop_closure_edge(n_poses):
return (0, n_poses - 1, np.zeros(3),
np.diag([1 / 0.05 ** 2, 1 / 0.05 ** 2, 1 / np.deg2rad(2) ** 2]))
掲載したのは最適化部分で、軌跡と雑音の生成(乱数シード固定)とATEの計算は省いています。実行結果は次のとおりです(Python 3.9.6・numpy 2.0.2・macOS 26.6.2・x86_64、2026年9月19日実行。2026年11月10日の再実行でも同値)。
| 条件 | 軌跡の位置RMSE(ATE) | 終端の位置ずれ |
|---|---|---|
| デッドレコニング(オドメトリ積分のみ) | 1.939 m | 4.683 m |
| ポーズグラフ最適化(ループ閉じ込みなし) | 1.939 m | 4.683 m |
| ポーズグラフ最適化(ループ閉じ込み拘束を1本追加) | 1.207 m | 0.002 m |
注目すべきは2行目です。今回のように拘束が隣接姿勢間のオドメトリだけの鎖状グラフでは、最適化を回しても誤差が1ミリも減りません。拘束が数珠つなぎのままでは、オドメトリを積分した軌跡がそのまま最小二乗解になるためです(別のセンサーによる拘束やランドマーク観測を持つグラフでは、ループ閉じ込みが無くても最適化は効きます)。逆に、始点と終点が同じ場所だと判定できた拘束をたった1本足すだけで、終端の位置ずれは4.683メートルから0.002メートルへ落ちます。
この実験で改善に寄与したのは、正しいループ閉じ込み拘束の追加であって、最適化器の性能ではありませんでした(始点と終点の対応は正解として与えており、場所認識器の性能は評価していません)。Cadenaらも、視覚と慣性を組み合わせたオドメトリ(VIN)を「ループ閉じ込み(場所認識)モジュールを無効にした、縮退したSLAMシステム」と呼んでいます。また、Forsterらの研究を例に、軌跡長の0.5パーセント未満という小さなドリフトを紹介しています。地図の再利用や大域的な整合を必要とせず、移動区間内のドリフトが要求精度に収まる用途なら、高精度オドメトリを選べます。
誤ったループ閉じ込み1本による地図の崩れとDCSでの抑制
ループ閉じ込みは効きが強いぶん、間違えたときの被害も大きくなります。見た目の似た別の廊下を「同じ場所」と判定してしまう誤り(知覚的エイリアシング)は、場所認識では避けられません。田崎の解説論文は、誤ったループを含んだまま最小化すると「ポーズ補正前よりもさらに歪みを悪化させてしまう結果になり得る」と書いています。どの程度悪化するかを、前節の実装を拡張して測りました。
条件は次のとおりです。正方形を2周する209ノードの軌跡で、2周目の5ノードおきに1周目の同じ地点と結ぶ正しいループ拘束を21本張ります(観測雑音は位置0.05メートル・角度2度)。そこに、実際には25メートル離れた2つの辺の中央を「同じ場所」とする誤った拘束を1本だけ加えます。外れ値対策には、Agarwalらが2013年のICRAで発表したDynamic Covariance Scaling(DCS)を使います。DCSはループ拘束ごとに残差の大きさ χ2 を見て、係数 s = min(1, 2Φ / (Φ + χ2)) を計算し、情報行列を s2 倍して効きを弱めます。前節の最適化ループに足すのは数行です。
# ループ拘束(is_loop=True)にだけ DCS を掛ける
chi2 = float(e @ omega @ e)
s = min(1.0, 2 * dcs_phi / (dcs_phi + chi2))
w = omega * s * s # 残差を s 倍する=情報行列を s^2 倍する
H[I, I] += A.T @ w @ A # 以降は omega の代わりに w を使う
結果は次のとおりです(Python 3.9.6・numpy 2.0.2・macOS 26.6.2・x86_64、2026年11月10日実行。初期値はすべてオドメトリ積分の軌跡、Gauss-Newtonの反復は最大60回)。
| 条件 | ATE | 誤った拘束のDCS係数 |
|---|---|---|
| オドメトリのみ | 2.662 m | - |
| 正しいループ拘束21本 | 0.293 m | - |
| 正しい21本+誤り1本(通常の最小二乗) | 19.181 m | - |
| 正しい21本+誤り1本(DCS、Φ=1) | 2.655 m | 7.78×10-6 |
| 正しい21本+誤り1本(DCS、Φ=10〜1,000) | 0.269〜0.293 m | 7.59×10-5〜7.59×10-3 |
| 正しい21本+誤り1本(DCS、Φ=10,000以上) | 19.181〜22.559 m | 1.00 |
読み取れることは2つです。
第一に、誤った拘束1本が、正しい拘束21本の効果を打ち消すどころか、オドメトリだけの場合の7倍以上まで誤差を広げました(2.662メートルが19.181メートルに悪化)。ループ閉じ込みを「足せば足すほど良い」と考えるのは危険で、フロントエンドの誤検出率とバックエンドの外れ値対策は1組で設計する必要があります。
第二に、DCSは効きますが、Φを決め打ちすると外します。論文は評価の既定値をΦ=1としていますが、この実験でΦ=1にすると、誤った拘束だけでなく正しい21本も係数0.001前後まで落ちて捨てられ、結果はオドメトリのみとほぼ同じでした。初期値のオドメトリ軌跡が6メートル以上ずれているため、正しいループ拘束の χ2 も最初は巨大になるからです。逆にΦを10,000以上にすると誤った拘束を通してしまい、通常の最小二乗と同じ崩れ方をしました。χ2 の大きさは情報行列の設定(観測の分散をいくらと置いたか)で変わるため、Φの適正域は自分のグラフで振って確かめるしかありません(この設定では10〜1,000)。自前で書く必要はなく、g2oにはRobustKernelDCS、GTSAMにはmEstimator::DCSとしてDCSそのものが実装されています(HuberやCauchyなど他のロバスト関数も同梱)。
SLAMアルゴリズム3方式の違い
EKF-SLAM:最初の定式化とその限界
EKF-SLAMは、ロボットの姿勢と全ランドマークの座標を1本の状態ベクトルにまとめ、拡張カルマンフィルタで逐次更新する方式です。相関を捨てずに保持するという原理には忠実ですが、その代償が計算量です。Durrant-WhyteとBaileyは「観測更新のたびに全ランドマークと結合共分散行列を更新する必要がある」と述べ、その帰結を「Naively, this means computation grows quadratically with the number of landmarks.」(素朴に実装すれば、計算量はランドマーク数の2乗で増える)と書いています。
この2乗則が実務でどの程度効くかを、共分散更新だけを取り出して測りました。状態次元は3プラス2×ランドマーク数です。表のメモリ値は共分散配列だけを対象とした値(1,024バイトを1KiBとして表示)で、プロセス全体のピークメモリではありません。なお更新式の書き方でも計算量が変わります。教科書どおりの (I – KH)P はd×d同士の行列積になるためO(d3)ですが、P – K(HP) と括ればHが2×dなのでO(d2)で済みます。両式が数値的に一致することを確認したうえで、両方の時間を並べました。
import time
import numpy as np
rng = np.random.default_rng(1)
def build(n):
d = 3 + 2 * n
P = np.eye(d) * 0.1
P += 1e-3 * (lambda A: A @ A.T)(rng.standard_normal((d, d)))
H = np.zeros((2, d))
H[0, 0] = H[1, 1] = -1.0
H[0, 3] = H[1, 4] = 1.0 # ランドマーク1つを観測
return d, P, H, np.eye(2) * 0.01
def update(P, H, R, efficient):
S = H @ P @ H.T + R
K = P @ H.T @ np.linalg.inv(S)
# efficient: H が 2 x d なので H @ P も K @ (H @ P) も O(d^2)
# 教科書形 (I - K @ H) @ P は d x d 同士の積になり O(d^3)
return P - K @ (H @ P) if efficient else (np.eye(P.shape[0]) - K @ H) @ P
| ランドマーク数 | 状態次元 | 共分散のメモリ | n=50比 | O(d2)形の1更新 | O(d3)形の1更新 |
|---|---|---|---|---|---|
| 50 | 103 | 82.9 KiB | 1.0倍 | 0.118 ms | 0.238 ms |
| 100 | 203 | 321.9 KiB | 3.9倍 | 0.301 ms | 0.707 ms |
| 200 | 403 | 1,268.8 KiB | 15.3倍 | 1.376 ms | 3.504 ms |
| 400 | 803 | 5,037.6 KiB | 60.8倍 | 6.411 ms | 21.986 ms |
| 800 | 1,603 | 20,075.1 KiB | 242.2倍 | 91.565 ms | 208.528 ms |
メモリはランドマーク数が倍になるごとにほぼ4倍(1.0倍・3.9倍・15.3倍・60.8倍・242.2倍)で、2乗則どおりに増えています。これは実装に依存しない、定義そのものの帰結です。時間のほうは、教科書どおりの (I – KH)P と書いた場合、O(d2)形の約2.0〜3.4倍かかりました。またO(d2)形でも、ランドマーク50個から400個(8倍)では54.3倍とおおむね2乗則に沿う一方、800個では775.1倍へ跳ねています。共分散は約20MiBになりますが、処理時間が増えた原因は今回の計時だけでは特定できません。キャッシュ容量やメモリ帯域の影響は追加計測が必要です。表の時間はこの実装・この環境での値であり、EKF-SLAM一般の処理時間ではありません。
それでも目安にはなります。この環境では、ランドマーク800個の共分散更新は計算順序を整えた形で91.565ミリ秒、教科書形で208.528ミリ秒でした。10ヘルツの周期100ミリ秒に対し、前者でも残る時間は約8.4ミリ秒です。EKF-SLAMを採るなら、計算順序を整えた実装で、想定するランドマーク数と観測頻度での処理時間を先に測ってください。なお原典は、効率化した変種なら数千のランドマークをリアルタイムで扱えると述べています。
FastSLAM:粒子による軌跡表現とランドマーク別フィルタ
FastSLAMは、ロボットの軌跡を多数の粒子(パーティクル)で表現し、各粒子ごとにランドマークを独立した小さなフィルタで持つ方式です。軌跡を条件として与えればランドマーク同士が独立になるという性質(Rao-Blackwell化)を使い、EKF-SLAMの巨大な結合共分散を回避します。原典であるMontemerloらの2002年の論文(AAAI 2002)は、この構成によって観測の取り込みが「地図内のランドマーク数に対して対数的にスケールする」と述べ、50,000個のランドマークでの動作を報告しています。同じ抄録はEKF系を「観測1つを取り込むのにランドマーク数の2乗の時間を要する」と対比させています。ただし前節では記憶量と実行時間の両方を測っており、記憶量の2乗則と、実装や実行環境に依存する処理時間は区別する必要があります。非線形性やマルチモーダルな分布に強い一方、粒子数を増やすほど計算量とメモリが増え、長時間走らせると粒子の多様性が失われる(粒子枯渇)という固有の課題があります。2次元の格子地図を作るLiDAR SLAMでは、この系統のgmappingが長く標準的な選択肢でした。
Graph SLAM:現在の実装の主流
Graph SLAMは、前章で実装したとおり姿勢をノード・拘束をエッジとするグラフを組み、全体を非線形最小二乗として解く方式です。時系列に沿って逐次的に絞り込むフィルタ系と違い、過去の姿勢を変数として保持し、後からまとめて修正できる点が決定的な差になります。EKF-SLAMもランドマークの再観測によって現在の姿勢と地図を補正しますが、過去の姿勢まで遡って再最適化することはできません。拘束行列が疎であることを利用すれば大規模でも解けるため、現在のROS 2向け実装はほぼこの系統です。
| 方式 | 状態の持ち方 | 過去の姿勢の修正 | 主な弱点 | 代表的な実装 |
|---|---|---|---|---|
| EKF-SLAM | 姿勢と全ランドマークを1本の状態ベクトルで結合 | できない(直近の状態のみ更新) | 計算量がランドマーク数の2乗で増える/線形化誤差の蓄積 | 教育・小規模の参照実装 |
| FastSLAM | 軌跡を粒子群、地図を粒子ごとの独立フィルタ | 粒子の重み付けを通じて間接的に | 粒子枯渇/粒子数に比例する計算量 | gmapping(2次元格子地図) |
| Graph SLAM | 姿勢のグラフと拘束の集合 | できる(全体を一括で再最適化) | ループ閉じ込みの誤検出が全体を壊す | slam_toolbox、Cartographer、RTAB-Map |
深層学習ベースのSLAM:DROID-SLAMとMASt3R-SLAM
深層学習の利用は、EKF・粒子フィルタ・グラフ最適化という推定方式とは別の分類軸です。特徴抽出や対応付けにニューラルネットワークを使い、幾何最適化と組み合わせる構成があります。代表的な2本は、GitHubのREADMEとLICENSEで条件を確かめられます(2026年11月10日に確認)。
- DROID-SLAM(Teed・Deng、NeurIPS 2021):単眼・ステレオ・RGB-Dカメラに対応します。ライセンスはBSD 3-Clauseです。READMEによると、デモの推論には11GB以上のメモリを持つGPU、学習には24GB以上のGPUが必要です。
- MASt3R-SLAM(Murai・Dexheimer・Davison、CVPR 2025):3次元復元モデルMASt3Rの予測を事前知識に使う密なSLAMです。著者はRTX 4090で実験しています。ライセンスはCC BY-NC-SA 4.0(非営利)です。使う学習済みモデルにも、別の利用条件が付いています。
研究や事前評価にもライセンス条件は適用されます。MASt3R-SLAMはCC BY-NC-SA 4.0の非営利(NonCommercial)条件のもとでしか使えないため、製品化に向けた社内評価がこの範囲に入るかは個別に確認が必要です。DROID-SLAMはBSD 3-Clauseで商用利用もできますが、11GB以上のGPUメモリという要件が組み込み機器の予算に収まらないことが多くあります。製品化を前提にするなら、後述のROS 2向けGraph SLAM実装から選び、深層学習は場所認識などの部品として後から組み込むほうが現実的です。
LiDAR SLAMとVisual SLAMの選び分け
センサーの違いは精度の優劣ではなく、何を手がかりに位置を合わせるかの違いです。LiDAR SLAMは形状を、Visual SLAMは見た目の模様を手がかりにします。したがって苦手な条件も異なります。ただし形状も模様も乏しい環境のように、両方が同時に失敗しやすい条件もあります。
| 観点 | LiDAR SLAM | Visual SLAM |
|---|---|---|
| 手がかり | 点群の形状(スキャンマッチング) | 画像の特徴点・輝度パターン |
| 明るさの影響 | 暗所・夜間でも測距できる(強い外光の影響は機種・条件による) | 大きく受ける(逆光・暗所・急な明暗変化で破綻) |
| 苦手な環境 | 長い直線廊下・トンネル・広場など形状が単調な場所(縦方向の拘束が効かず滑る) | 白い壁・一様な床など模様の乏しい場所 |
| 天候 | 雨・霧・粉塵で点群が乱れる | 雨滴・レンズ汚れの影響を受ける |
| 取得できる情報 | 距離が直接得られるため絶対スケールが決まる | 単眼画像だけでは絶対スケールが不定。実寸が必要なら追加の尺度情報を使う |
| コスト・搭載性 | センサーが高価で重い傾向 | カメラは安価で軽い |
実務では、運動条件や方式に応じてIMU(慣性計測装置)を併用すると効く場面が多くあります。IMUは短時間の姿勢変化を保持できるためです(単調な廊下で進行方向の拘束が失われる問題まで解消するとは限りません)。Cartographerの公式資料でも、2次元でのIMU入力は任意、3次元では必須とされています。距離と画像を同時に得るRGB-Dカメラ(深度カメラ)を使う方式もあり、単眼カメラの弱点である絶対スケールの不定はこれで解消します。RTAB-Map、ORB-SLAM3、DROID-SLAMはいずれもRGB-D入力に対応しています。センサー単体の仕様比較より先に、自分の現場が「形状が単調か」「明るさが変わるか」のどちらに寄るかを決めるのが選定の出発点になります。LiDARセンサーそのものの測距方式や点群処理については LiDARとは?仕組み・ToF方式・点群処理を実装目線で解説する技術ガイド で詳しく扱っています。
2026年にROS 2で使えるSLAM実装の現況
日本語の解説では今もCartographerとORB-SLAM3が代表例ですが、実装を選ぶなら「今も更新されているか」と「ループを閉じるか」が先に効きます。次の表は2026年11月10日時点でGitHub APIとREADMEから取得した情報です(日付はGitHub APIが返すUTC)。更新が続いていても、対象のROS 2ディストリビューションで動くとは限りません(たとえばORB-SLAM3本家が同梱するROS例はROS 1系のものです)。
| 実装 | 入力 | READMEでの位置づけ | ライセンス | 最新版 | 最終push |
|---|---|---|---|---|---|
| slam_toolbox | 2次元LiDAR | SLAM | LGPL-2.1 | 2.10.0(2026-07-21) | 2026-11-02 |
| RTAB-Map | RGB-D・ステレオ・LiDAR | SLAM | BSD 3-Clause形式 | 0.24.2(2026-10-25) | 2026-11-09 |
| GLIM | 3次元LiDAR・RGB-Dなど距離センサー | 3次元マッピング | MIT | v1.2.2(2026-07-11) | 2026-10-08 |
| KISS-ICP | 3次元LiDAR | LiDAR Odometry | MIT | v1.3.0(2026-04-26) | 2026-06-09 |
| FAST-LIO | 3次元LiDAR+IMU | LiDAR-inertial odometry | GPL-2.0 | リリースなし | 2026-10-25 |
| Cartographer | 2次元・3次元LiDAR | SLAM(積極的な保守は停止) | Apache-2.0 | 2.0.0(2021-03-11) | 2024-01-05 |
| ORB-SLAM3 | 単眼・ステレオ・RGB-D+IMU | SLAM | GPL-3.0 | v1.0-release(2021-12-22) | 2024-07-24 |
リポジトリは順に SteveMacenski/slam_toolbox、introlab/rtabmap、koide3/glim、PRBonn/kiss-icp、hku-mars/FAST_LIO、cartographer-project/cartographer、UZ-SLAMLab/ORB_SLAM3 です。読み取れることは4点です。
- 2次元ならslam_toolbox、RGB-Dやカメラを含むならRTAB-Mapが第一候補です。どちらも直近数週間以内に更新されています。slam_toolboxは、ROS 2の移動ロボット向けナビゲーションスタックであるNav2(ros-navigation/navigation2、2026年10月17日に1.5.3をリリース)と組み合わせる構成が標準です。
- KISS-ICPとFAST-LIOは、READMEで自らをオドメトリと名乗っています。KISS-ICPは「a LiDAR Odometry pipeline」、FAST-LIOは「LiDAR-inertial odometry package」です。手軽に精度の良い軌跡が出るので「SLAMライブラリ」と紹介されがちですが、ポーズグラフの実測どおり、ループを閉じなければ周回しても誤差は戻りません。広い現場を周回するなら、ループ検出と大域最適化を別に足す必要があります。GLIMは因子グラフ上で複数スキャンの整合を最適化する3次元マッピングの枠組みです。明示的なループ検出は、拡張パッケージglim_extに実装例として収録されています。
- Cartographerは積極的な保守の停止が公式に明記されています。READMEに「Cartographer is no longer actively maintained.」とあり、重大なプルリクエストをまれにマージする以外、issueへの返答を含めて新規開発は行わないとしています。同じREADMEはROS向けフォーク(ros2/cartographer・ros2/cartographer_ros)についても「only maintained in a limited capacity」(限定的にしか保守されていない)と書いており、フォークの最終pushも2025年5月です。既存システムの保守以外で選ぶ理由は乏しくなっています。
- ライセンスは必ず確認してください。ORB-SLAM3はGPL-3.0、FAST-LIOはGPL-2.0です。GPLのプログラムを製品に組み込んで第三者に頒布すると、対応するソースコードの提供などが必要になります。社内利用だけなら公開義務は生じませんが、研究用の評価から製品化へ移る段階で問題になりやすい箇所です。
ROS 2そのものの構成やディストリビューションの選び方は ROS(Robot Operating System)とは?ノードとDDS通信の構造・ROS 2世代の選び方を実装者目線で解説【2026年8月時点】 と ROS1とROS2の違い|通信・QoS・コードの比較とNoetic EOL後の移行手順【2026年10月】 にまとめています。
実機を走らせる前に、誤検出しやすい似た廊下や周回経路をシミュレーターで作って試すと、DCSのΦのような調整値を安全に詰められます。シミュレーターの導入条件は Isaac Simとは?無料で使えるライセンスの範囲・GPU要件・導入方法【6.2対応・2026年10月】 にまとめています。
SLAMの用途と分野別の利用条件
- 自律移動ロボット(AMR):未知の屋内環境で地図を作る場面でSLAMが使われます。一度作った地図を使い回す運用では、走行時は自己位置推定だけを行う構成もあります。
- ロボット掃除機(ルンバ):iRobotは2015年9月16日発表のRoomba 980で、独自のvSLAM(カメラを使うVisual SLAM)を「for the first time in a consumer product」(消費者向け製品で初めて)搭載しました。一方、2025年4月16日に日本で発表されたRoomba 105 Combo・205 DustCompactor ComboやRoomba Plus 405 Comboは、「ClearView LiDAR」による「素早いマッピングとスムーズなナビゲーション」をうたっています(Plus 505 ComboはClearView Pro LiDAR)。同じルンバでも、世代によって前章のVisual SLAMとLiDAR SLAMの違いがそのまま当てはまります。
- 自動運転:走行中にゼロから地図を作るというより、事前に作成した高精度地図に対して現在位置を合わせる用途が中心です。ただしその高精度地図を作る工程自体がSLAMです。
- ドローン:橋梁の裏側・屋内・地下などGPSが届かない場所での自律飛行に使われます。積載量の制約が厳しいため、軽量なカメラとIMUを組み合わせる構成が選ばれやすい領域です。
- ARグラス・XRデバイス:現実空間に仮想物体を固定して見せるには、デバイス自身の姿勢を常時推定し続ける必要があります。
- 測量・インフラ点検:手持ちや背負い型のスキャナで歩きながら3次元点群を取得する手法が普及しています。据え置き型の地上レーザースキャナと比べる際は、要求精度・対象範囲・歩行経路・位置合わせと後処理を含めた総作業時間を、機種の仕様で確認してください。
いずれの用途でも、処理を機体上で完結させるか外部に投げるかが設計判断になります。機体側で回す場合の計算資源については NVIDIA Jetsonとは?Orin・Thorの違いと選定基準・量産判断を実装視点で解説【2026年版】 が参考になります。
よくある質問
SLAMとローカライゼーション(自己位置推定)の違いは何ですか?
ローカライゼーション(localization)は「既にある地図の中で自分がどこにいるか」を求める処理で、SLAMの出力の片方にあたります。SLAMの定義には「地図を同時に構築すること」が含まれるため、既存の地図に位置を合わせるだけの処理はSLAMとは呼びません。自動運転で高精度地図に位置合わせする処理や、一度SLAMで作った地図を使い回して走るロボットの通常運転は、ローカライゼーションのほうです。
SLAMの読み方は何ですか?
日本語では「スラム」と読まれます。ただし検索結果には市街地の貧困地区を指す「スラム」が混在するため、技術文脈で検索するときは「SLAM 自己位置推定」「SLAM ロボット」のように語を足すほうが確実です。
EKF-SLAMは今でも使われていますか?
教育や参照実装では今も使われます。本記事の実測では、ランドマーク800個のとき共分散更新だけで約92ミリ秒かかり(教科書どおりの書き方では約209ミリ秒)、10ヘルツのセンサーなら、周期100ミリ秒のうち更新以外に使える時間は約8ミリ秒しか残りません。新規に組む場合の主流はGraph SLAMです。カルマンフィルタそのものの仕組みは カルマンフィルタとは?仕組みを1次元の例でわかりやすく解説【Python実装とQ・Rの決め方】 で解説しています。
ループ閉じ込みとは何ですか?なぜ重要なのですか?
一度通った場所に戻ってきたことを検出し、「この2つの姿勢は同じ場所である」という拘束をグラフに追加する処理です。本記事の実測では、この拘束が無いとポーズグラフ最適化を回しても誤差がまったく減らず(ATEは1.939メートルのまま)、1本足しただけで終端の位置ずれが4.683メートルから0.002メートルへ縮みました。反対に、別の場所を同じ場所と誤認した拘束が1本入ると、ATEは0.293メートルから19.181メートルへ悪化します。検出の精度と外れ値対策をセットで考える必要があります。
LiDARとカメラはどちらが高精度ですか?
環境によって逆転するため、一般論としての優劣はつきません。LiDARは暗所に強い一方で長い直線廊下では滑り、カメラは模様のある環境に強い一方で白い壁や逆光に弱いので、自分の現場がどちらの弱点に当たるかで選びます。
SLAMは完成した技術ですか?
Durrant-WhyteとBaileyは2006年の時点で「理論的・概念的なレベルではSLAMは解かれた問題と考えてよい」としつつ、「より一般的なSLAMの実現、とくに知覚的に豊かな地図の構築と利用には実務上の課題が残る」と書いています。Cadenaらの2016年のサーベイも、長期運用での頑健性、動的に変化する環境への追従、意味情報を含む地図といった論点を未解決の課題として挙げています。