
AWS公式のVLAシミュレータがREADME通り動かなかったので、原因を突き止めて直したらGR00TとOpenVLAが完走した
はじめに
VLAを評価するAWSサンプルを見つけたので試してみました。学習済みのVLAモデルを、シミュレータの中で実際に動かして「指示どおりのタスクをこなせるか」を採点する、aws-samples/sample-vla-simulator-on-awsです。1コマンドでGPUインスタンスに評価環境が立ち上がり、成功率と動画がS3に届く、という内容でした。
先に結論を書くと、
- READMEどおりに動かしたら、動きませんでした。NVIDIAのGR00Tを選んだのですが、セットアップの途中でエラーになります。もう一つ試したOpenVLA-OFTも、別のエラーで落ちました。
- 原因は依存パッケージのバージョン不整合でした。サンプルが検証された数か月前から上流のライブラリが更新され、噛み合わなくなっていました。GR00TとOpenVLA-OFTのそれぞれで、ログを掘って原因を突き止め、最終的には両方とも直して完走させました。
- mujocoのバージョンを固定する1行のパッチ(+gatedモデル用のトークン登録)で、GR00Tが完走しました。どちらのタスクも成功率1.0(5/5、3/3)で、ロボットが動く動画も取れました。
- (直した内容はissueとして報告しました。)
これは何をするサンプルか
- リポジトリ: aws-samples/sample-vla-simulator-on-aws(MIT-0)
- 学習済みのVLAモデル(GR00T、π0.5、OpenVLA-OFTなど)を、ロボットシミュレータの中で走らせて、タスクの成功率を測るCDKサンプルです。
VLAモデルというのは、カメラ画像・ロボットの自己状態(関節角度など)・「黒いボウルを引き出しに入れて」といった言語指示を受け取り、次の数ステップ分の動作指令を出力するモデルです。それがちゃんとタスクをこなせるかを、シミュレータの中で採点します。
今回動かしたNVIDIA GR00Tは、ロボット向けの基盤モデルです。評価にはLIBERO(Lifelong Robot Learning benchmark)という、7軸のFrankaアーム(Panda)が物を掴む・引き出しを開けるといった課題を集めた標準テストを使います。
環境
| 項目 | 内容 |
|---|---|
| インスタンス | g6.12xlarge(NVIDIA L4×4、48vCPU) |
| リージョン | us-east-1 |
| クライアント | macOS(AWS CLI + CDK) |
| 対象 | --vla gr00t(LIBERO kitchen 2タスク) |
セットアップ(READMEどおり)
手順はREADMEのQuick Startどおりです。
git clone https://github.com/aws-samples/sample-vla-simulator-on-aws.git
cd sample-vla-simulator-on-aws
python vlasim.py init --email you@example.com --bootstrap
python vlasim.py doctor --vla gr00t # 事前チェック(メール設定とbootstrapを済ませれば全項目OK)
python vlasim.py deploy --vla gr00t --email you@example.com
詰まりどころ①: bootstrapに-c vlaが要る
init --bootstrapが内部で呼ぶcdk bootstrapが、このエラーで止まります。
Error: CDK context "vla" is required. Pass -c vla=gr00t, ...
このCDKアプリは起動時に必ずモデル指定(-c vla=)を要求する作りで、bootstrapのときもそれが要ります。bootstrap自体はモデルと無関係なので、ダミーで付けて単体実行すれば通ります。
cd cdk && npx cdk bootstrap aws://<ACCOUNT>/us-east-1 -c vla=gr00t && cd ..
詰まりどころ②(本編): mj_fullM でセットアップが落ちる
deployすると、GPUインスタンスは立ち上がるものの、セットアップの途中でこのエラーになり、CloudFormationがロールバックしてインスタンスごと消えます。
mujoco.mj_fullM(self.sim.model._model, mass_matrix, self.sim.data.qM)
TypeError: mj_fullM(): incompatible function arguments.
mj_fullMはMuJoCo(LIBEROの物理エンジン)の関数です。「引数の型が合わない」と言われています。
原因の探し方
厄介だったのが、肝心のエラーが巨大な数値配列のダンプに埋もれていたことです。CloudWatchのログをそのまま見ると、numpyの配列が延々と表示されてエラー行が押し出されています。配列の行を除外して、例外の先頭だけ拾います。
aws logs tail /gr00t/userdata --region us-east-1 --since 20m --format short \
| grep -iE "error|traceback|mujoco" \
| grep -viE "e-0|e\+0|0\.0000"
これで原因が見えました。決め手はこの1行です。
+ mujoco==3.10.0
原因: robosuiteの呼び出しが新しいMuJoCoと合っていない
順に裏を取ると、こういうことでした。
- LIBEROの依存で入るrobosuite 1.4.0は、
mj_fullM(model, dst, qM)という古い引数の並びで関数を呼びます。 - ところがMuJoCoの公式Changelogによると、3.10.0(2026年6月)で
mj_fullMの引数の並びが変わりました(mj_fullM(model, data, dst)へ)。3.1〜3.9では古い形が有効です。 - そして実際に入っていたのが、その3.10.0でした。robosuiteの古い呼び出しが弾かれていたわけです。
要するに、mujocoのバージョンを固定していないので、最新の3.10.0が入って、robosuiteの古い呼び出しと噛み合わなくなった、という話です。READMEに書かれたGR00Tの検証日(2026-04-27)より後に3.10.0が出ているので、検証当時は3.9以前が入って噛み合っていたと推測できます(そこは私が直接確認したわけではありません)。
ログが消える問題と、その回避策
原因の切り分けのため、別のモデル(OpenVLA-OFT)でも試しました。すると今度は、エラーの詳細が/tmpのログファイルにしか残らないという別の壁にぶつかりました。CloudWatchに流れるのは「importに失敗した」という結果だけで、肝心の理由は/tmpのファイルの中。そしてロールバックでインスタンスが即削除されるので、そのログごと消えてしまうのです。
そこで、失敗時に必ず通るdie()関数(スクリプトの共通の出口)に、ログをS3へ退避する処理を1行足しました。S3の結果バケットはロールバックでも残るので、インスタンスが消えてもログが手元に残ります。
die() {
log "ERROR: $*"
# 失敗時、cfn_signalを送る前に/tmpのログをS3へ退避
aws s3 cp /tmp/ "s3://${S3_BUCKET}/${RUN_ID}/debug-logs/" \
--recursive --exclude "*" --include "*.log" --region "${REGION}" || true
cfn_signal 1
exit 1
}
これで救出したログから、OpenVLA-OFTの真因も特定できました。
ImportError: cannot import name 'runtime_version' from 'google.protobuf'
こちらは面白い不整合でした。入っていたのはprotobuf 4.25.9。tensorflow_metadata 1.21.0は宣言上は「protobuf 4.21.6以上」で動くことになっているので、pipは矛盾を検出せずインストールを通します。ところがコードの方は4.25には存在しないruntime_versionをimportしていて、実行時に初めて落ちる——宣言している依存範囲と、コードが実際に必要とする範囲がズレているわけです。しかもTensorFlow 2.15系がprotobufを5未満に抑えるため、新しいprotobufへ逃げることもできない組み合わせでした。mujocoのように「変更が入った日付」まで突き止めてはいませんが、バージョンの組み合わせが噛み合っていないという点は同じです。GR00TとOpenVLA-OFTの2つとも、別々のパッケージで依存が噛み合わなくなっていたわけです。
なおOpenVLA-OFTはこの後、tensorflow-metadataを--no-depsで1.15.0に下げる修正で先へ進めたのですが、今度は評価の実行中にGR00Tと同じmj_fullMで落ちました。こちらのLIBERO環境でもmujocoが固定されておらず3.10.0が入っていたためです。つまりmujocoの問題は2モデル共通の根本原因でした。同じmujoco固定を足したところ、OpenVLA-OFTもLIBERO-10のフル評価を完走し、50エピソード中50成功(eval.logの集計でOverall success rate: 1.0000)でした。ただしこのcheckpointはLIBERO-10向けにファインチューニング済みのモデルで、試行数も1タスク5回と少なめなので、100%という数字は、特化モデルでの小規模評価の結果として見てください。
修正: mujocoを固定してGR00Tを通す
原因がmujoco 3.10.0の混入だと分かれば、対策は「3.10より前に固定する」だけです。問題のセットアップスクリプト(NVIDIA側のもので、実行時にダウンロードされる)は、numpyは固定するのにmujocoは野放しでした。そこで、そのスクリプトが実行される前に、mujocoを3.3.1に固定する1行を差し込みます。
# setup_libero.sh実行前に、mujocoの固定を注入
sed -i 's|^\(uv pip install numpy==1.26.4\)$|\1\nuv pip install "mujoco==3.3.1"|' \
gr00t/eval/sim/LIBERO/setup_libero.sh
このsedは、サンプルがEC2起動時に実行するUserDataテンプレート(templates/gr00t-userdata.sh.j2)の、setup_libero.shを呼ぶ直前に追記しました。python generate.py --vla gr00tで再生成すると実際のスクリプトに反映されます。
もう一つ、GR00TのバックボーンであるCosmos-Reason2-2Bがgatedモデルなので、HuggingFaceトークンをSSMパラメータストアに登録しておきます(このサンプルはそこからトークンを読む設計です)。
read -rs HF_TOKEN
aws ssm put-parameter --name "/vla-simulator/hf-token" --type SecureString \
--value "$HF_TOKEN" --region us-east-1 --overwrite
unset HF_TOKEN
このパッチを当てて再deployすると、ログに修正が効いた瞬間が出ます。
- mujoco==3.10.0
+ mujoco==3.3.1
...
Env OK: <class 'gymnasium.wrappers.order_enforcing.OrderEnforcing'>
[3/6] setup_libero.sh complete
mj_fullMの壁を突破して、LIBERO環境が正常に作成されました。あとはモデルのダウンロード、推論サーバの起動と進んで、ロールアウトが始まります。
結果: GR00Tが両タスクを完走、成功率1.0
Task 1/2: KITCHEN_SCENE3_turn_on_the_stove_and_put_the_moka_pot_on_it
success_rate=1.0 (5/5)
Task 2/2: KITCHEN_SCENE4_put_the_black_bowl_in_the_bottom_drawer_of_the_cabinet_and_close_it
success_rate=1.0 (3/3)
| タスク | 内容 | 成功率 |
|---|---|---|
| KITCHEN_SCENE3 | コンロを点けてモカポットを載せる | 1.0(5/5) |
| KITCHEN_SCENE4 | 黒いボウルを引き出しに入れて閉める | 1.0(3/3) |
(試行回数の5回・3回は、サンプルのタスク定義どおりです)
READMEにも同じ2タスクを成功率1.0で検証したと記載があり、依存を自分で直した上で同じ成功率を得られました。
生成された動画を実際に見てみると、Pandaアームがまずコンロを操作し、それからモカポットを載せる動きをしていました。指示(turn_on_the_stove_and_put_the_moka_pot)どおりの順序です。
なお、動画に付随するメタデータのテキストにはRobot: NVIDIA Fourier GR1という記載がありましたが、これはサンプル側のメタデータ生成の誤りのようです。実際に走ったのはログのとおりPandaアーム(Embodiment: LIBERO_PANDA)でした。
なぜ動かなくなっていたのか
依存が原因だった2つの詰まり(mujocoとprotobuf)は、どちらもサンプルのコードが間違っているわけではなく、バージョンを固定していない箇所に新しいパッケージが入って噛み合わなくなったものです。バージョンをきっちり固定していないと、時間が経つほど「動いていたはずのもの」が動かなくなります。
READMEには各モデルの検証日が書いてあり、今回落ちたGR00Tは2026-04-27、OpenVLA-OFTは2026-05-04でした。一方で、他のモデル(RLDX系など)は6月の検証日で、READMEの脚注に依存バージョンを細かく調整した記録が書かれています。私が実際に試したのはGR00TとOpenVLA-OFTの2つだけなので6月組が動くかは確認していませんが、検証日が新しくて依存調整の入っているものほど、こういう不整合に強いはずです。
Issueの起票
再現手順と特定した原因、テスト済みの修正を添えて、リポジトリにissueを立てました。
コストと後片付け
- 原因究明の過程で何度もdeployをやり直しましたが、失敗はどれもセットアップ途中の数分で終わるので、失敗ぶんの課金は合計で$10ほどでした。これに、最後まで走った成功ラン(フルセットアップ+モデル2本ダウンロード+評価で1時間強)が$5〜8乗って、トータルで$15〜18程度です。
- 成功したランは、評価が終わると自動でインスタンスがterminateされます(
auto_terminate: true)。 - スタックとS3バケットは残るので、完全に片付けるなら以下です。
python vlasim.py destroy --vla gr00t
# S3バケットは結果保持のため残る。不要なら:
# aws s3 rb s3://vla-sim-results-gr00t-demo-<region>-<account> --force
おわりに
- AWS公式のVLA評価サンプルは、READMEどおりでは(少なくとも私が試した時点では)動きませんでした。ただ、原因は依存パッケージのバージョン不整合なので、mujocoの固定を軸にした修正でGR00TとOpenVLA-OFTの両方を完走させられました(GR00Tは2タスクとも成功率1.0、OpenVLA-OFTはLIBERO-10で50/50)。
- 直した内容はIssueとして起票しました。GR00Tのmujoco起因の詰まりは、これが取り込まれれば解消されるはずです(OpenVLA-OFTのprotobufは別問題として残りますし、HFトークンの登録などの手順は引き続き必要です)。
NVIDIA GR00T (Isaac-GR00T) のモデル重みはNVIDIA Open Model License、LIBEROはMIT License、aws-samplesのサンプルコードはMIT-0です。本記事はその範囲での技術検証です。









