自動運転の認識スタックを1から — カメラとLiDARは何を分担しているのか
自動運転車が「周りに何があるか」を知る仕組みを、センサの物理特性から解説。カメラとLiDARの得意・不得意、全センサを1枚の地図にまとめるBEV表現、ベイズ更新で育てる占有格子、そして安全要件と計算資源のせめぎ合いまで、前提知識ゼロで追う。
車は世界をどう「見て」いるのか
夜道を歩くとき、人間は目だけに頼っていません。足裏で路面の凹凸を感じ、耳で背後の自転車に気づき、それらを頭の中で1つの「周囲の地図」に統合しています。自動運転車がやっていることも本質的には同じです。性質の違う複数のセンサで世界を測り、矛盾をならして1枚の地図にまとめ、その上で「何がどこにいて、次にどう動くか」を推定する——この一連の処理を認識スタック(perception stack)と呼びます。
スタックは大まかに、センサ入力 → 物体検出・セグメンテーション → 追跡(トラッキング) → 動き予測、と流れ、その出力を受けて経路計画が「どう走るか」を決めます。この記事は前半の「見る」部分、つまりセンサと表現の設計を扱います。なお、この工程の分業そのものをやめ、センサ入力から操作までを1つのネットワークで学習させる路線もあります。そちらはEnd-to-End運転を1からで扱っています。
カメラとLiDAR: 物理が決める得意・不得意
まずセンサの素性を押さえます。ここを飛ばすと、後段の設計がすべて恣意的に見えてしまいます。
カメラは太陽や街灯の光が物体に反射したものを受け取る受動センサです。画素は密で、色とテクスチャが分かるので「これは停止標識だ」「あれは白線だ」という意味の判別が得意です。安価で複数台積みやすいのも強みです。弱点は、1枚の画像から奥行きが直接は分からないこと。3次元の世界を2次元に潰す射影で距離情報が失われるからです。逆光や暗闇、レンズに付いた水滴にも弱い。
LiDARは自分でレーザーパルスを打ち、反射が返るまでの時間から距離を測る能動センサです。距離の測定が直接的で正確、真っ暗闇でも動きます。代わりに得られるのは疎な点群(point cloud)で、色はなく、遠くの物体ほど当たる点が減ります。また雨粒や霧、雪はレーザーを散乱させるので悪天候では性能が落ち、機械としても高価な部類です。
つまり両者は弱点が重ならない。カメラは「何であるか」に強く距離に弱い。LiDARは「どこにあるか」に強く意味の判別に弱い。この相補性こそが、自動運転が複数センサを積む理由です。多くの車両はさらにレーダー(電波なので雨霧に強く、ドップラー効果で相対速度が直接測れる)を加え、故障モードの異なる三重の目を持たせます。
カメラの根本問題を式で見る
「カメラは奥行きが分からない」を1本の式にします。ピンホールカメラモデルでは、画素座標から3次元の点を復元する逆射影はこう書けます。
は画素の位置(同次座標)、 はカメラ内部パラメータ行列(焦点距離や画像中心をまとめたもの)、 がその画素の奥行き、 が復元される3次元の点です。言い換えると——画素の位置は「その物体がこの直線上のどこかにある」ことしか教えてくれず、直線上のどこかを決めるには奥行き が別途必要、ということです。LiDARはこの を物理的に測ってくれる。カメラだけで走るなら、 をニューラルネットで推定するしかない。認識スタックの設計論争の多くは、突き詰めればこの を誰が払うかの話です。
BEV: 全センサを「上から見た1枚の地図」に集める
センサごとにバラバラの座標系——カメラは画像平面、LiDARは3次元点群——のままでは、後段の追跡や計画が扱えません。そこで現代のスタックは、すべてをBEV(Bird's Eye View、鳥瞰図)という地面に平行な格子に変換して合流させます。車を真上から見た方眼紙を想像してください。
BEVが合流点として優れている理由は3つあります。第一に、物体どうしが重ならない。画像では手前の車が奥の車を隠しますが、上から見れば全員が自分のマスに立っています。第二に、スケールが一様。画像では遠くの車ほど小さく写りますが、BEVでは5m先の車も50m先の車も同じ大きさで描かれ、距離の推論がそのまま格子上の距離になります。第三に、経路計画が欲しいのはまさにこの俯瞰地図なので、出力がそのまま次工程の入力になる。
LiDAR点群は3次元座標を持つので、高さ方向を潰せばほぼそのままBEVに落ちます。難しいのはカメラで、式(1)の通り奥行きを推定しながら画素を3次元へ「持ち上げる」必要があります。この持ち上げ方の設計(深度分布で押し出す方式、BEV側から問い合わせるTransformer方式)は一大トピックなので、BEV表現を1からで独立に扱っています。
占有格子: 「何か分からなくても、そこに何かある」
BEVの上で走る最も古典的で頑健な表現が占有格子(occupancy grid)です。方眼紙の各マスに「そこが物体で埋まっている確率」を持たせ、センサ観測が届くたびにベイズ更新で育てます。実装では確率そのものではなく、対数オッズ(log-odds)で持つのが定石です。
は時刻 でのそのマスの対数オッズ(占有の確からしさ)、 は今届いた観測、 は「この観測を見たとき、そのマスが埋まっている確率」を表すセンサモデル、 は観測前の事前値です。言い換えると——新しい観測が来るたびに、そのマスの「埋まってる度」に足し算(占有を示す観測)か引き算(素通りしたので空きを示す観測)をするだけ。掛け算だらけのベイズ則が、対数を取ることでただの足し算になるのがミソです。
占有格子の価値は、「何であるか」を当てられなくても安全に止まれることにあります。物体検出器は学習した種類(車・歩行者・自転車…)しか箱にできません。道路に落ちたソファ、倒れた木、横転したトラック——学習データにない物体を検出器は見逃しえますが、占有格子は「レーザーがそこで返ってきた。だから何かある」という物理的事実だけで埋まります。分類に基づく検出と、分類によらない占有。この二段構えが安全設計の背骨で、近年はこの占有格子自体をニューラルネットで予測する「占有ネットワーク」路線も盛んです。
コードにすると、更新の核心は10行で書けます。
import numpy as np
L_OCC, L_FREE = 0.85, -0.4 # センサモデル由来の対数オッズ増分
def update_grid(logodds, hits, passes):
"""hits: レーザーが返ったマス, passes: 素通りしたマス (bool格子)"""
logodds[hits] += L_OCC # 「何かある」方向へ足す
logodds[passes] += L_FREE # 「空いている」方向へ引く
return np.clip(logodds, -10, 10) # 飽和して復帰不能になるのを防ぐ
prob = 1 / (1 + np.exp(-logodds)) # 確率に戻すのはシグモイド1発
融合のタイミング: 早いか、遅いか
カメラとLiDARをどこで合流させるかにも設計の幅があります。後期融合(late fusion)は、各センサが独立に検出まで済ませ、検出結果(箱のリスト)どうしを突き合わせる方式。片方が死んでも他方が生き残る分離の良さがあり、検証もしやすい。早期融合(early fusion)は、生に近い特徴量の段階で混ぜる方式。「カメラではぼんやり見え、LiDARでは数点だけ返っている」ような弱い証拠どうしを足し合わせて初めて見つかる物体を拾えますが、センサ間の時刻同期と位置合わせ(キャリブレーション)のズレにそのまま脆くなります。BEVはこの早期融合の合流点としても機能します。
安全要件と計算資源: 締切のある知能
認識スタックには他のAIにない制約が2つあります。締切と故障の想定です。
時速60kmの車は1秒で約17m進みます。LiDARが一周する周期やカメラのフレーム間隔のうちに、検出から予測までを毎回必ず完走させなければならない。クラウドのGPUではなく、車載の限られた電力・発熱枠で、です。だから表現の計算量が死活問題になります。3次元空間をそのままボクセル(立方体のマス)で持つと、一辺の解像度を上げるたびにマス数は3乗で爆発します。BEVが高さ方向を潰して2次元格子にするのは、精度と引き換えに次数を1つ落として締切に間に合わせる判断でもあるのです。
もう1つが確信度の扱いです。ニューラルネットの分類出力はsoftmaxで確率の形をしていますが、確率の形をしているだけで、当たる頻度と一致している保証はありません。「歩行者 99%」と言いながら実際は9割しか当たらない検出器は、後段の計画が「99%なら回避不要」と判断したとき事故に直結します。出力の確信度を実際の的中率に合わせる作業をキャリブレーションと呼び、softmaxの温度を1つ調整するだけの温度スケーリングが定番の第一手です。
現場ではこう使う
自動運転や物流ロボットの知覚(perception)エンジニアが日常的に触るのは、モデル本体よりむしろその周辺です。
- データと評価: 公開データセットのnuScenesやKITTIで手法を比較し、社内データで再評価する。BEV検出の評価では、IoU閾値ごとの平均適合率に加え、距離帯別(0-30m / 30-50m…)の再現率を必ず見る。遠距離の見逃しは平均値に埋もれるため。
- 触るパラメータ: 点群前処理のボクセルサイズ(
voxel_size、粗いほど速いが小物体が消える)、検出の確信度閾値と重複除去のnms_iou_threshold、占有格子のマス解像度とセンサモデルのl_occ/l_free。ツールはROS 2のbag再生でセンサ時系列を再現し、可視化にRViz系を使うのが定番。車載へはONNX経由でTensorRTに載せ、FP16/INT8量子化で締切に収める。 - 事故になる落とし穴①: 外部キャリブレーションのドリフト。カメラとLiDARの相対位置・姿勢(extrinsics)は出荷時に校正しても、走行の振動や軽い接触で数度ズレる。早期融合はこのズレに脆く、「LiDARの点がカメラ上の隣の車に色付けされる」形で静かに壊れる。定期的な再校正か、走行中の自動校正の仕組みが要る。
- 落とし穴②: 時刻同期。カメラとLiDARのタイムスタンプが数十ミリ秒ズレるだけで、高速走行中の物体は1m近く別の場所に描かれる。ハードウェアトリガやPTPでの同期を最初に確認する。「融合の精度が悪い」の原因調査は、モデルより先に時計を疑うのが鉄則。
- 落とし穴③: 評価と実走のギャップ。晴天の昼に集めたデータで測った精度は、雨夜のトンネル出口では成立しない。天候・時間帯・地域で層別した評価をせずに閾値を決めると、平均では良いのに特定条件で系統的に見逃す検出器ができあがる。
まとめ
- カメラは「何であるか」、LiDARは「どこにあるか」。弱点が重ならないから両方積む
- 全センサはBEVという俯瞰の格子で合流する。重なりなし・スケール一様・計画への直結が理由
- 占有格子は「分類できなくても止まれる」ための、分類によらない安全網
- 締切(実時間性)と故障想定が設計を支配する。次数を1つ削るBEVも、確信度のキャリブレーションも、その帰結
検出器そのものの中身は物体検出を1からで、カメラ画像をBEVへ持ち上げる各方式はBEV表現を1からで、それぞれ深掘りしています。あわせてどうぞ。
コメント
コメントにはログインが必要です