AWS公式のVLAシミュレータがREADME通り動かなかったので、原因を突き止めて直したらGR00TとOpenVLAが完走した

AWS公式のVLAシミュレータがREADME通り動かなかったので、原因を突き止めて直したらGR00TとOpenVLAが完走した

AWS公式のVLA評価サンプルをGR00Tで動かしてみたところ、依存パッケージのバージョン不整合でセットアップが失敗しました。原因を突き止めてmujocoを固定することで、GR00TとOpenVLA-OFTの両方を完走させ、成功率1.0でロボットアームのタスク実行を確認できました。
2026.07.27

はじめに

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)どおりの順序です。

https://youtu.be/S5uImHSOCpo

https://youtu.be/kzzxu_kkWwY?si=xZ-F23XvaZ7CP-73

なお、動画に付随するメタデータのテキストには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を立てました。

https://github.com/aws-samples/sample-vla-simulator-on-aws/issues/4

コストと後片付け

  • 原因究明の過程で何度も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です。本記事はその範囲での技術検証です。

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事