🍣

自動運転開発におけるシミュレータ活用

2023/12/15に公開

Turingの機械学習モデル開発チームの@hidetatzです。Turingアドベントカレンダー14日目の記事です。
TuringはAIによる完全自動運転車を開発するスタートアップです。

この記事では、自動運転車というプロダクトを開発するために重要なシミュレータについて、Turingがどう活用しているかを書きます。

シミュレータとは?

自動運転の文脈において、シミュレータは車を運転する実際の道路環境をPC上で再現するためのソフトウェアのことを指します。

シミュレータは、複雑な交通状況や天候の変化、さまざまな道路のレイアウトなど、現実世界の多様な条件を精密に模倣することができます。私達自動運転車の開発者は、これらのシミュレーションを利用して、実際の車両を道路に出す前に、様々なシナリオでの車の振る舞いをテストし、評価することができます。

特に、自動運転技術においては、現実世界で発生しうる無数のシナリオを全て実車でテストすることは非現実的です。シミュレータはこのギャップを埋める重要なツールであり、安全性、効率性、およびシステムの堅牢性の向上に貢献します。例えば、極端な天候条件下での運転や、予期せぬ道路上の障害物への反応など、実際の運転ではまれにしか遭遇しないシナリオも、シミュレータ上で繰り返しテストすることが可能です。

これはrFproという商用エミュレータのYouTube動画からスクリーンショットしたものです。シミュレータとはいえ非常にリアリティがあることが解ると思います。このように、精巧なマップ・車両・歩行者・標識・信号機などをPC上でひとつの世界として動作させ、様々な目的で活用できます。

rFproの他にも、商用ではMathWorksの製品、オープンソースではCARLAMetaDriveなどがあります。

Turingにおけるシミュレータ

Turingでは前述のCARLAというオープンソースのシミュレータを使っています。
Turingの自動運転のアーキテクチャをおおまかに説明すると、こんな感じになっています。

カメラの映像を機械学習モデルに入力し、モデルが出力した経路通りに車が走れるよう、制御ソフトウェアが車を制御します。
さて当然ですが、シミュレータの環境は実際の車両環境に近ければ近いほど、精巧なシミュレーションができます。つまり、シミュレータで動かす車は、可能な限り実際にTuringが開発する車両と近いものが望ましいです。これは車の大きさ等の諸元だけでなく、カメラの位置や角度、内部パラメータやレンズの歪みといったセンサについても同じです。多くのシミュレータ製品では、この辺は自由に調整できるようになっています。

CARLAについて

CARLAはオープンソースの自動運転シミュレータです。スペインにあるCVC (Computer Vision Center)にて開発されています。
CARLAはクライアント・サーバ型のソフトウェアです。CARLAを起動すると、サーバとともにGUIのシミュレータのウインドウが開きます。

クライアントは carla ライブラリを使ってPythonで実装することができます。例えばこんな感じです。

CARLAは内部ではUnreal Engine4を使っており、見た目もなかなかきれいです。そのぶん強めのGPUマシンを必要とします。TuringではNVIDIAのRTX4090を使ったマシンをシミュレータ用に組んでいます。

CARLAではマップ、天候、時間帯などを自由に選択できる他、車両歩行者その他のオブジェクトなどをマップに配置することができます。

CARLAの活用

Turingでは自動運転モデルの検証にCARLAを活用しています。

これはPC上で自動運転システムとCARLAを同時に動かすことで実現しています。CARLA上でカメラを車に取り付け、そのカメラで撮影した画像を自動運転システムに入力します。自動運転システムは車両に対する指示を出力するのですが、この出力をCARLAへの指示に変換する層を介してCARLAに入力することで自動運転のシミュレーションをしています。

Turingでは、実際に自動運転モデル開発のパイプラインにCARLAを組み込んでいます。具体的には、学習を1エポック回すごとに自動でCARLA上で学習したモデルが運転し、学習の正しさを検証できるようになっています。このあたりは自動運転AI開発:学習からシミュレーション、実車テストまでという記事に詳しく書いてあるのでぜひ読んでみてください。

具体例: nuScenesのカメラをCARLAで再現する

Turingでは、実際にTuringが開発する車両となるべく近い車両をCARLAで再現しています。Turingが今開発している車のカメラやセンサの情報はまだ公開できないため、ここではnuScenesのカメラをCARLAで再現することを試みます。

nuScenesとは?

nuScenesは自動運転界隈では非常に有名な、公開データセットです。LiDAR、レーダー、カメラ、IMU、GPSの情報が含まれており、カメラの画像は140万枚ほど含まれています。データ収集車両にはルノーのゾエという車を使っており、ボストンとシンガポールでデータを収集しています。

これはnuScenesのデータ収集車両のセットアップの図です。カメラに着目すると、前方・右前・左前・右後・左後・後方の合計6機のカメラがついています。座標系はZ軸が前後方向、X軸が左右方向、Y軸が上下方向です。

さて、このカメラをCARLAで再現するためにはカメラの取り付け位置・角度、画像のサイズ、画角、レンズの歪みなどの情報が必要です。nuScenesデータセットにキャリブレーション済みのカメラの内部パラメータなどが含まれているため、それらの情報からCARLAで必要な情報を計算してみます。

nuScenesからデータを取り出す

nuScenesのデータセットはアカウントを作ることでこちらのURLからダウンロードできます。今回は「Full dataset (v1.0)」のminiを使用しました。ローカルにダウンロードして展開すると、センサ等のメタデータは v1.0-mini/ ディレクトリにあります。

上記はnuScenesのデータスキーマです。実際に、データの v1.0-mini/ ディレクトリにこれらのスキーマと合うようなメタデータのjsonファイルが格納されています。カメラのメタデータは calibrated_sensor.json にあり、これを sensor.json と突き合わせることで各カメラの位置 ( translation )、角度 ( rotation )、内部パラメータ ( camera_intrinsic )を取得することができます。

位置が示しているのは、nuScenesのデータ収集車における基準点からの距離で、単位はメートルです。例えば、 CAM_BACK_LEFT のカメラ位置は [1.03569100218, 0.484795032713, 1.59097014818] となっています。前から(x, y, z)です。
基準点は、後輪のシャフトにおける左右方向の真ん中になっています。

角度は(w, x, y, z)で、クォータニオンで示された回転です。クォータニオンのことをあまり知らなかったので (ChatGPTに聞いて) 調べてみましたが、次のようなコードでオイラー角への変換ができることがわかりました。

import math

def quaternion_to_euler(w, x, y, z):
    t0 = +2.0 * (w * x + y * z)
    t1 = +1.0 - 2.0 * (x * x + y * y)
    roll_x = math.atan2(t0, t1)

    t2 = +2.0 * (w * y - z * x)
    t2 = +1.0 if t2 > +1.0 else t2
    t2 = -1.0 if t2 < -1.0 else t2
    pitch_y = math.asin(t2)

    t3 = +2.0 * (w * z + x * y)
    t4 = +1.0 - 2.0 * (y * y + z * z)
    yaw_z = math.atan2(t3, t4)

    deg = math.degrees
    return deg(roll_x), deg(pitch_y), deg(yaw_z)

これで実際に計算してみると、例えば CAM_BACK_LEFT のカメラはロール: -90.917度、ピッチ: -0.215度、ヨー: 18.600度となっていることがわかりました。これは、ロール・ピッチはほぼ地面と水平にカメラが設置されていることを意味し、ヨーは車の前・後ろ・斜めなどどの方向を向いているかを示しています。他のカメラも角度を計算した上で図にして考えた結果、角度は車の進行方向から左に90度の角度を0度とし、そこから半時計回りに角度が増えていくようでした。

最後に内部パラメータについてです。内部パラメータは3x3の行列で、例えば CAM_BACK_LEFT のカメラでは以下のような値になっていました。

[
  [1256.7414812095406, 0.0, 792.1125740759628],
  [0.0, 1256.7414812095406, 492.7757465151356],
  [0.0, 0.0, 1.0]
]

内部パラメータの詳細については省略しますが、今回は内部パラメータからカメラのFOVと画像サイズを求めました。内部パラメータに含まれる焦点距離と画像中心を使うことで、 (ChatGPTに教えてもらいながら) 求めることができました。

CARLAでの再現

ここまでわかればCARLAで再現することは簡単です。CARLA及びクライアント自体のインストールはできているものとして、クライアント側のミニマムな実装を紹介します。

# クライアントを初期化
client = carla.Client("localhost", 2000)

# マップを設定
world = client.load_world("Town01")

# ブループリントライブラリ (配置したいオブジェクトのカタログのようなもの) を取得
bl = world.get_blueprint_library()

# AudiのA2を例として使用
audi_bp = bl.find("vehicle.audi.a2")

# 前方カメラとして、FOV70のカメラを作る
cam_70_bp = bl.find('sensor.camera.rgb')
cam_70_bp.set_attribute('image_size_x', "1600")
cam_70_bp.set_attribute('image_size_y', "900")
cam_70_bp.set_attribute('fov', "70")
    
# 適当な位置にまずaudiを配置
audi = world.spawn_actor(audi_bp, world.get_map().get_spawn_points()[0])

# カメラをaudiに設置。nuScenesの原点は後輪のシャフト上なので、まずはその位置を計算
physics = actor.get_physics_control()
time.sleep(0.1) # wait for Unreal Engine retrieve actor's transform
rear_left_wheel_pos = physics.wheels[2].position / 100 # cm -> m
rear_right_wheel_pos = physics.wheels[3].position / 100 # cm -> m
nuscens_origin = carla.Location(x=(rear_left_wheel_pos.x + rear_right_wheel_pos.x) / 2, y=(rear_left_wheel_pos.y + rear_right_wheel_pos.y) / 2)

# CARLA世界におけるAudiの原点とnuScenesにおける原点の距離を計算
dist = nuscenes_origin.distance(audi.get_transform().location)

# 距離を考慮に入れた位置を計算。
# 1.700などはnuScenesのメタデータから求めた原点からの距離 (translation)
camera_trans = carla.Transform(carla.Location(x=1.700 - dist, y=0.0015, z=z), carla.Rotation(yaw=yaw))
# attach_toを指定することで、設置箇所はaudiからの相対位置・角度になる
cam_f = world.spawn_actor(cam_70_bp, camera_trans, attach_to=audi)
cam_f.listen(lambda image: image.save_to_disk(f"CAM_FRONT_{image.frame}.png"))
# 他のカメラも同様に取り付ける

# 3秒間データを取り続ける
time.sleep(3)

# メモリを開けるために消す
cam_f.destroy()
audi.destroy()

実際に試してみたのがこの画像です。実際には車を60台、歩行者を40人配置してそれぞれをオートパイロット機能で動かしつつカメラで映像も録画しています。

今後の発展と課題

シミュレータで重要なのは、テストしたいケースをシナリオとして定義し、シナリオごとにテストすることです。例えば、強烈な悪天候や事故になるかもしれない場面など、現実ではテストが難しいケースを簡単にテストできることはシミュレータの大きなメリットです。
自動運転におけるシナリオ定義はOpenSCENARIOとして標準化されています。CARLAもこれに対応しており、OpenSCENARIOのファイルを入力することでその通りトラフィックを再現することが可能です。こういった機能を使って、より賢く安全な自動運転モデルを開発していきます。
CARLAの課題はマップや標識などの環境の見た目が、日本の道路っぽくないことです。特に標識の違いなどは重要です。ここはカスタムのアセットをCARLAにインポートすることもできるので、今後解決していきたいです。
また、私達はシミュレータだけで自動運転のテストが完結するとは考えていません。シミュレータでうまく運転できることと、現実世界でうまく運転できることがどの程度相関するかは私達にとってもまだ未知であり、感覚的には必ずしも相関しないと考えています (そういった論文もあります) 。
シミュレータで評価できる範囲を広げつつ、実車でもテストを行うことで、開発スピードを最大化できると考えており、このあたりの評価についてはもっと社内で知見を獲得する必要があります。

終わりに

Turingでどうシミュレータを活用しているかを書きました。自動運転開発で重要なことは、モデルを作りその評価のループをたくさん高速に回すことだと考えています。シミュレータは開発速度を上げるために効果的なツールであり、実車テストとのバランスを今後も追求していきたいと思います。
Turingではエンジニアを募集しているので、興味のある方は応募してください!

採用情報
Turing カジュアル面談の部屋

Tech Blog - Turing

Discussion