DEVELOPMENT NOTE / 2026.10.25
2 日で、走る車の「目」ができた。その途中で、箱庭のコアも一段強くなった。
第 1 回では、カメラを「時刻を渡すと絵が返ってくる関数」にした、という話をしました。とはいえ、最初からそう見えていたわけではありません。第 2 回は、作り始めた 2 日間(2026 年 10 月 23 日と 24 日)の記録です。
出発点:カメラの設定は、もうあった
朝起きて、さあ作ろうとしたところで思い出しました。箱庭の MuJoCo ロボットには、カメラの設定ファイルが既にありました。形は SDF に似せてあります。SDF は、ロボットやセンサーの姿を書き表すための形式で、ロボットのシミュレータ Gazebo などで使われています。画角、画像の大きさ、写る距離の範囲、ノイズ、撮る間隔を書けます。
これを、自動運転のシミュレータ CARLA や、シナリオの標準 OpenSCENARIO で扱うくらいまで広げればいい。そう考えて、まずは設定の決まり(スキーマ)から手を付けました。
設定は、カメラの物理で書く
CARLA のカメラの設定と、SDF の最新版(1.12)のカメラを調べ、3 つのことを決めました。
- 「カメラ」と「何を取り出すか」を分ける:ISO 感度、シャッター速度、絞り(F 値)、色温度、レンズといったカメラそのものの性質と、色の絵・距離・写っている物の種類といった取り出したい情報を、別々に書きます。
- 物理の単位で書く:描画ソフトの設定値ではなく、秒、メートル、度のような物理の量で書きます。あとで本物のカメラや別の描画ソフトに合わせるときも、設定を書き直さずに済みます。
- CARLA に合わせた値は、別に持つ:CARLA と同じ設定にすることはできます。ただ、同じ設定にしても、同じ絵になるとは限りません(描画のソフトも、明るさの整え方も違うからです)。そこで、CARLA に合わせた値は「CARLA 互換」の設定として分けて持ちます。
Godot につなぐ
絵を描くのは、ゲームエンジンの Godot です。箱庭は既に Godot と共有メモリでつながっていたので、つなぐ部分は少しの改造で済みました。
ただ、つなぎ方には工夫が要りました。箱庭のサンプルの多くは、箱庭のほうから決まったタイミングで呼び出してもらう作りです。ゲームエンジンは自分で画面を回し続けているので、外から呼び出してもらう形にはできません。そこで、ゲームエンジンのほうから箱庭の様子を見に行き、そのとき使ってよい機能だけを使う作りにしました。
小さなつまずきもありました。Godot を画面を出さずに起動すると、絵を描いてくれないのです。カメラ用の Godot は、画面を出して起動することにしました。
カメラより先に、コアを直した
1 日目の夜、思わぬものが見つかりました。AI と一緒にカメラをつないでいたところ、AI が、これまでの箱庭ではほとんどしなかった使い方を始めたのです。ゲームエンジンを起動したまま、シミュレーションを止めては始め直す。これを繰り返すと、2 回目からは、箱庭の呼び出しの仕組み(サービス)がつながらなくなりました。
その晩のうちに、2 時間ほどで、起きたことを再現する小さなプログラムを作り、原因を突き止めて直しました。始め直しを確かめるテストも、自動テストに加えました。第 1 回で「最初の半日はコアのバグと戦っていた」と書きましたが、記録を見直すと、実際は 2 時間ほどでした。笑
この直しは、同じコアを使う製品(Drone PRO)にも入れて、回帰テストまで確かめました。詳しくは issue にまとめてあります。カメラを作るつもりが、まずは箱庭のコアを一段強くすることになりました。
カメラの作り:撮る時刻を決めるのは、カメラ係だけ
ここが、箱庭のカメラでいちばん伝えたいところです。

- カメラ係:箱庭の時計に合わせて動く、カメラの本体です。撮る時刻 t になると、車の位置と向きを箱庭のデータ(PDU。シミュレーションの部品どうしがやりとりするデータ)から読み、どこから撮るかを決めます。
- 描画の係(Godot と MuJoCo):カメラ係から「時刻 t に、この位置と向きから見た絵を描いてほしい」という依頼を受けて、絵を描いて返すだけです。自分では時刻を持ちません。色の絵は Godot、距離と物の種類は MuJoCo に付いている描画の仕組み(Filament)が描きます。どちらにも、まったく同じ依頼が届きます。
- 時刻のそろった 4 つの PDU:カメラ係は、返ってきた絵を、色の絵・距離・物の種類・撮影情報の 4 つのデータとして書き出します。撮影情報を最後に書くので、それが「1 組そろった」という合図になります。読む側(たとえば E2E AI)は、同じ撮影時刻の 4 つを 1 組として受け取れます。
時刻の流れで見ると、こうなります。

ゲームエンジンと物理エンジンという、まったく別の 2 つの描画を使っても、絵は同じ瞬間のものになります。描画の係が時刻を持たず、カメラ係から渡された時刻と位置だけで描くからです。描画の係は依頼の形さえ守れば差し替えられるので、別のゲームエンジンや描画ソフトに替えられる作りです。
依頼の形は、箱庭のデータの定義集(PDU レジストリ)に、新しいサービス RenderCameraFrame として足しました。依頼にはカメラの名前、時刻、位置と向きが入り、返事として絵が返ってきます。

動いた:走る車の「目」
1 日目は、都庁のまわりの街(PLATEAU の 3D 都市モデル)で、道路に沿ってカメラを動かし、Godot で描きました。日付が変わった夜中には、Urban Mobility の車にカメラを載せ、走る車から見た映像を、箱庭のデータとして取り出せるようになりました。取り出した絵は Python から読めます。ここが、E2E AI の入り口になります。

このとき、はっきりしました。ゲームエンジンが画面を描き換える速さ(フレームレート)を、シミュレーションに合わせる必要はない。時刻を渡して 1 枚頼めば、その時刻の絵が返ってくる。第 1 回に書いた気づきは、ここから来ています。
このシリーズ
- カメラを「関数」にした ― なぜ箱庭にカメラが要ったのか
- 作ってみた ― カメラより先に、コアを直した(この記事)
- 真実はシミュレーションの中に ― カメラは、撮影の瞬間を読んで写すだけ
- CARLA と比べてみた ― 同じ場所、同じ条件で測った
次回は、動いたあとで「これは箱庭の考え方と違う」と気づき、半日かけてカメラの作りを直した話です。
※ 箱庭カメラは開発中です。製品としての提供範囲・時期は未定です。シミュレーションの画像は、実際のカメラの映像や、それを使うソフトウェアの性能・安全性を保証しません。
※ Godot は MIT ライセンスのオープンソースです。SDF(SDFormat)は Open Robotics の記述形式です。CARLA は、その開発元・権利者のものです。3D 都市モデルは PLATEAU を使っています。
関連:箱庭Godot / Urban Mobility
