In Silico

Physical AI

LEAPPとは:Isaac Labの方策を前処理ごとONNXに書き出す仕組み

2026/11/3

  • LEAPP
  • ロボット学習
  • 強化学習
  • Isaac Lab
  • ONNX
  • YAML
  • LeRobot
  • Exploy
  • Isaac ROS Deploy
  • ONNX Runtime
  • 方策
  • 観測
  • 前処理
  • 後処理
  • トレース
  • 正規化
  • ROS
  • トークナイザ
  • safetensors
  • 推論
  • RSL-RL
  • RAI Institute
  • Warp
  • Hugging Face
  • smolvla_libero
目次
背景・問い・要点
背景

強化学習(RL、Reinforcement Learning)でロボットの動かし方を学ばせる技術者を考える。技術者は、Python のシミュレータで方策を学習し、その方策を実機の C++ や ROS(Robot Operating System)の制御プログラムで動かしたい。方策は、観測(センサの値)を受け取って行動(関節を動かすモーター、つまりアクチュエータへの指令)を返すニューラルネットワークである。学習済みのネットワークに入力を渡して出力を得る計算を、推論と呼ぶ。

ネットワークが担うのは、センサの値から指令までの計算の中ほどだけである。手前では、センサの値を拡大縮小し、直前の行動や過去の値を並べて、ネットワークへの入力を組み立てる。これを観測の前処理と呼ぶ。後ろでは、ネットワークの出力を拡大縮小し、上限と下限で切り、基準の位置を足して、関節への指令にする。これを行動の後処理と呼ぶ。重みだけを実機へ渡すと、実機側の技術者が前処理と後処理を C++ で書き直す。書き直した処理が学習時と一か所でも食い違うと、ネットワークは学習時と違う入力を受け取り、関節は学習時と違う指令を受け取る。

前処理と後処理を実機へ運ぶ方法は複数ある。実機側の技術者が手で書き直す方法と、Python の学習環境ごと実機へ持ち込む方法がある1。ほかに、前処理と後処理をネットワークと一緒に、ONNX(Open Neural Network Exchange)のような一つのモデルのファイルへ書き出す方法と、処理の設定を重みの横に別のファイルとして保存する方法がある。本稿は、書き出す方法の例として NVIDIA の LEAPP(Lightweight Export Annotations for Policy Pipelines)を主に取り上げ、同じ方法をとる Exploy と、設定を保存する方法をとる LeRobot を比べる相手に選んだ。三つとも、作り手が設計の理由を一次資料に書いている。

問い

LEAPP は、Isaac Lab で学習した方策を、重みのほかに何まで書き出して、Python のない実機側に学習時と同じ計算をさせる仕組みなのか。

要点

LEAPP は、Isaac Lab の方策を、重みだけでなく観測の前処理・行動の後処理・次の制御周期へ持ち越す値まで含めて、ONNX のモデルと YAML の設定ファイルに書き出す。実機側は Python なしで、学習時と同じ計算を再現できる。

LEAPP は、計算を一度実際に走らせ、通った演算を記録して書き出す。この記録をトレースと呼ぶ。記録されるのは一度通った経路だけなので、入力の値によって通る経路が変わる分岐は書き出せない。

モデル・例示

重みだけを渡す場合と LEAPP の出力を渡す場合で、実機の制御プログラムが書く処理

※ この節の例は、説明のために作った架空のものです。

この例は、LEAPP を使うと、前処理と後処理を実行する場所が実機の制御プログラムからモデルの中へ移り、関節への指令の値は変わらないことを示す。重みだけを書き出す形では、前処理と後処理を実機の制御プログラムが実装する。LEAPP の出力を使う形では、書き出されたモデルが前処理と後処理を実行し、制御プログラムは生のセンサの値を渡す。扱う方策は、LEAPP の README が使う小さな方策と同じ構成である2。

6 関節のロボットを考える。方策への入力は、6 個の位置を [−1,1][-1, 1] に切った値と、6 個の速度に 0.10.1 を掛けた値を並べた 12 個とする。ネットワークは 12 個を受け取って 6 個を出し、出力に 0.250.25 を掛けて [−1,1][-1, 1] に切った値を、関節への指令とする。ONNX は、学習済みの計算を Python の外へ運ぶためのモデルのファイル形式であり、ONNX Runtime がそのファイルを実行する。

  1. 実機の制御プログラム1. 位置を -1 から 1 に切り、速度に 0.1 を掛けて 12 個に並べる(C++ で自作)
  2. 実機の制御プログラム重みだけの ONNX2. 12 個を渡す
  3. 重みだけの ONNX実機の制御プログラム3. 6 個の出力を返す
  4. 実機の制御プログラム4. 出力に 0.25 を掛けて -1 から 1 に切り、指令にする(C++ で自作)
  5. 実機の制御プログラムLEAPP が書いた ONNX5. 生の位置 6 個と速度 6 個を渡す
  6. LEAPP が書いた ONNX6. 切る・0.1 を掛ける・並べる・推論・0.25 を掛ける・切る、を全部行う
  7. LEAPP が書いた ONNX実機の制御プログラム7. 関節への指令 6 個を返す

1 個の関節で値を追う。位置 1.21.2 を読むと、前処理で 11 に切られる。速度 2.02.0 を読むと、0.10.1 を掛けて 0.20.2 になる。ネットワークがこの関節に 0.80.8 を出したとすると、後処理で 0.8×0.25=0.20.8 \times 0.25 = 0.2 が指令になる。重みだけの形では、11 と 0.20.2 と指令の 0.20.2 を C++ の制御プログラムが計算する。LEAPP の形では、同じ計算を書き出された ONNX が行い、制御プログラムは 1.21.2 と 2.02.0 を渡して 0.20.2 を受け取る。

  1. 指令の値は、前処理と後処理をどこで実行しても同じ 0.20.2 である。変わるのは、制御プログラムが実装する処理の数である。
  2. 重みだけの形では、処理が一つ抜けると入力が変わる。制御プログラムが 0.10.1 を掛け忘れると、ネットワークは 0.20.2 の代わりに 2.02.0 を受け取り、学習時の 10 倍の入力で推論する。
  3. LEAPP の形では、制御プログラムは前処理と後処理を実装しないので、この書き忘れは起きない。

重みだけの書き出しから、前後の処理を含む書き出しへ

重みだけを書き出す形では、観測の組み立てと行動の変換を配備する側が別の言語で書き直すので、学習時の計算と食い違うおそれがある。Isaac Lab v2.3.0 で、強化学習のライブラリ RSL-RL 用の書き出し機能は、行動を決めるネットワークと観測を正規化する層を書き出し、方策が再帰型なら再帰層も、隠れ状態の入出力とともに書き出す3。観測の項目の組み立てと行動のスケーリングは、このファイルに含まれない3。

LEAPP は、NVIDIA が 2026 年に公開した Apache-2.0 のライブラリである。GitHub のスター数は 34(2026-11-03 時点)で、利用の広さを示す数字はまだ小さい2。NVIDIA は LEAPP を、2022 年から公開しているロボット学習フレームワーク Isaac Lab(スター数 8,554)の 3.0 に書き出し機能として組み込んだ4。書き出したものは、実機向けの Isaac ROS Deploy で動かせる5。

LEAPP の作り手は、この状況を文書で次のように説明する。LEAPP が無いと、チームは処理を別の言語で書き直すか、書き出し用の別の仕組みを保つか、研究用の環境ごと配備先へ持ち込むことが多い1。LEAPP の成果物は、方策と、観測の前処理と、行動の後処理を一つにまとめるので、配備側のフレームワークが同じ処理を再実装しなくてよい5。

同じ動機は、別の組織の Exploy にもある。Exploy は、RAI Institute が 2026 年 3 月に公開したライブラリで、スター数は 199(2026-11-03 時点)である6。Exploy の README は、多くの方策の受け渡し方式がネットワークの構造と重みしか ONNX に入れず、生の観測から生の行動への写像だけを作り、観測の生成と行動の処理に要る複雑な周辺の論理を無視すると書く6。Exploy は、シミュレーション環境の PyTorch の演算をトレースして、単体で動く ONNX を作り、C++ の制御プログラムが ONNX Runtime で実行する。Isaac Lab と MjLab に対応する6。NVIDIA と RAI Institute は、どちらも 2026 年にリポジトリを作り、トレースによって前後の処理を ONNX に入れる道具を公開した26。

LEAPP はトレースした計算と、それをつなぐ YAML の契約を書き出す

LEAPP は二つのものを書き出す。一つは、トレースした計算を収めた ONNX である。もう一つは、どのモデルを読み、どの値をどこへ渡すかを書いた YAML(YAML Ain’t Markup Language)である。実機側のランタイムは ONNX を実行し、YAML に従って値を受け渡す7。

書き出しは次の順に進む5。

  1. 環境を一つだけ作り(並列数 1)、学習済みの重みを保存したチェックポイントを読む。
  2. 書き出しのコマンドが環境に注釈を注入し、方策の前処理から後処理までの入口と出口を LEAPP に示す。学習のコードと環境の設定は変えなくてよい。環境を直接書く Direct 型の方策では、利用者が注釈を足してから書き出す。
  3. 短い試験走行を一度行い、その計算をトレースする。前処理と後処理も走った演算として記録されるので、手で書き直す必要がない。
  4. ONNX を作ってグラフをコンパイルし、書き出したモデルが試験走行の出力を再現するかを検査する。検査の既定は 5 ステップで、0 にすると省く。

実機側のランタイムは、どのモデルを読み、外から何の値を渡し、ある出力を次にどこへ渡すかを知る必要がある。LEAPP の文書は、YAML をこのランタイムの契約と位置づける7。契約の各項目は、実機側が迷う点を一つずつ埋める。

文書は、生成された設定とモデルのファイルは中身をすべて読めるので、必要なら自前のランタイムを実装できると書く7。動かす先には、シミュレーション用の LeappDeploymentEnv、実機用の Isaac ROS Deploy、YAML を読む自作のランタイムがある5。Isaac Lab 3.0 では、カメラ入力、フレーム履歴の扱い、RGB(Red Green Blue)画像の前処理が、視覚を使う方策の書き出しに加わった4。

トレースの制限と、処理を Python のまま保存する LeRobot

LEAPP は一度の試験走行で通った演算だけを記録するので、入力の値によって通る経路が変わる処理は書き出せない。LEAPP の README は、データに依存する Python の分岐は保存されず、未対応の演算やスカラーの取り出しで値が固まることがあると書き、新しい入力での検証を求める2。文書は、テンソルの値に依存する if・for・while、トレースできない外部ライブラリの呼び出し、Warp の演算を、この書き出し経路の非対応に挙げる5。LEAPP の文書は、書き出したグラフは静的な構造なので、テンソルの値に依存する分岐を持てないと説明する2。そのうえで、要素ごとの選択は torch.where() に、値で回るループは固定の回数に書き換えるか、分岐の手前でノードを分けて分岐を呼び出し側に任せるよう勧める2。

統計の差し替えやトークナイザ(文章を数値の列に変える処理)のような処理を Python のまま運びたいなら、処理の設定を重みの横に保存する LeRobot の方式が向く。LeRobot は、Hugging Face が 2024 年から公開しているロボット学習のライブラリで、スター数は 28,645(2026-11-03 時点)である8。LeRobot は、処理を Python のまま保存する。ロボットは生のセンサの値を出し、それには正規化、バッチ化、デバイスへの転送が要る。言語の指示はトークン化が要り、モデルの出力は正規化された値のことがある。LeRobot のドキュメントは、これらの処理を組み替え可能な手順にして、方策の前に置くプリプロセッサと、後に置くポストプロセッサの列にしたと説明する9。実機の制御ループは、生の観測、プリプロセッサ、方策、ポストプロセッサ、ロボットへの送信の順で、すべて Python で動く9。各手順は、JSON(JavaScript Object Notation)で書ける設定と、テンソルの状態を分けて持つ10。公開されている smolvla_libero のリポジトリには、model.safetensors の横に、手順の列を記した JSON と、正規化の統計の safetensors が並ぶ。前処理は、観測の名前の付け替え、バッチ化、改行の整形、トークナイザ、デバイスへの転送、正規化の順である11。

LeRobot の設計の利点は、読み込み時の差し替えである。利用者は、手順の引数を読み込み時に overrides で置き換えられる。ドキュメントは使い方として三つを挙げる。学習時の統計を持たない基盤モデルに自分のデータの統計を入れる。GPU(Graphics Processing Unit)で学習した方策を CPU(Central Processing Unit)だけのロボットで動かす。カメラのキーを付け替える10。LeRobot も、前後の処理を重みと一緒に配る点では LEAPP や Exploy と同じだが、処理の置き場所は逆である。LEAPP と Exploy は処理をモデルのファイルの中へ入れ、LeRobot は重みの中にあった正規化を外へ出して別のファイルにした。この変更は PR(Pull Request)#1452 の破壊的変更で入り、方策の前後でプリプロセッサとポストプロセッサを呼ぶ形になった。PR の説明は、データの変換をモデルの論理から切り離し、ロボットの制御を柔軟にし、プラットフォームをまたぐ互換性を高めるための変更だと書く12。

LeRobot の欠点は、ONNX へ書き出す組み込みの機能が無いことである。ACT(Action Chunking with Transformers)や Diffusion Policy などの学習済みの方策を ONNX や TensorRT に書き出す組み込みの手段を求める Issue #3146 が、2026-03-12 から開いている(2026-11-03 時点)13。

実機側が Python を動かせず、C++ や ROS で制御するなら、トレース方式の LEAPP や Exploy が向く。利点は、Python なしで学習時の計算を再現でき、書き出したモデルが元の計算と同じ出力を返すかを確かめる検証まで、LEAPP と Exploy の両方が備える点である56。欠点は、値に依存する分岐をグラフに持てず、LEAPP の文書が勧めるように書き換えるか、分岐を制御プログラムの側へ出す必要がある点である。方策の前後にトークナイザのようなトレースしにくい処理があるか、読み込み時にロボットごとの統計を差し替えたく、しかも実機で Python が動くなら、LeRobot のように処理を設定として保存する方式が向く。利点は、処理を Python のまま運べて、読み込み時に引数を差し替えられる点である。欠点は、実機の制御ループに Python と LeRobot が要り、ONNX への組み込みの書き出しが要望にとどまる点である。LEAPP で統計を変えるときに書き出し直しが要るかは、本稿が読んだ資料に書かれていない。

出典13件
  1. NVIDIA「Isaac LEAPP」documentation(2026-11-03 取得). https://nvidia-isaac.github.io/leapp/ — 方策の経路全体を書き出す設計と、書き直しや研究環境の持ち込みを避ける作り手の理由。 ↩ ↩2

  2. NVIDIA「nvidia-isaac/leapp」GitHub(2026-11-03 取得). https://github.com/nvidia-isaac/leapp https://nvidia-isaac.github.io/leapp/tensor_libraries/torch_limitations.html — README の制限と小さな例、静的なグラフが値に依存する分岐を持てない理由と書き換え方。Apache-2.0、2026-04-24 作成、スター 34(2026-11-03)。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  3. Isaac Lab v2.3.0「rsl_rl/exporter.py」. https://github.com/isaac-sim/IsaacLab/blob/v2.3.0/source/isaaclab_rl/isaaclab_rl/rsl_rl/exporter.py — 書き出しの対象がアクターのネットワークと観測の正規化層(再帰方策では再帰層と隠れ状態の入出力も)である点。 ↩ ↩2

  4. Isaac Lab「Isaac Lab 3.0」GitHub Discussions #8775, 2026-10-22. https://github.com/isaac-sim/IsaacLab/discussions/8775 — 3.0 の正式版と、LEAPP のカメラ入力・フレーム履歴・RGB 前処理への対応。Isaac Lab はスター 8,554、2022-11-16 作成(2026-11-03 取得)。 ↩ ↩2

  5. Isaac Lab「Export Policies with LEAPP」Isaac Lab 3.0.0 docs(2026-11-03 取得). https://isaac-sim.github.io/IsaacLab/v3.0.0/source/policy_deployment/05_leapp/exporting_policies_with_leapp.html — 方策と前処理・後処理・再帰状態を書き出す手順、出力物、検証、対応範囲と制限。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7

  6. RAI Institute「rai-opensource/exploy」GitHub(2026-11-03 取得). https://github.com/rai-opensource/exploy https://rai-opensource.github.io/exploy/tutorial/exporter/exporter_tutorial.html — 重みだけの受け渡しへの批判、トレースによる単体の ONNX、元の環境と出力を毎ステップ比べる検証。2026-03-13 作成、スター 199。 ↩ ↩2 ↩3 ↩4 ↩5

  7. NVIDIA「Understanding the Generated Configs」LEAPP docs(2026-11-03 取得). https://nvidia-isaac.github.io/leapp/generated_configs.html — YAML のランタイム契約、data_flow と feedback_flow、実行周期、時間軸の項目。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8

  8. Hugging Face「huggingface/lerobot」GitHub(2026-11-03 取得). https://github.com/huggingface/lerobot — 2024-01-26 作成、スター 28,645(2026-11-03)。 ↩

  9. Hugging Face「Introduction to Processors」LeRobot docs(2026-11-03 取得). https://huggingface.co/docs/lerobot/introduction_processors — 前処理と後処理を手順の列にした理由と、Python で動く制御ループ。 ↩ ↩2

  10. Hugging Face「Implement your own Robot Processor」LeRobot docs(2026-11-03 取得). https://huggingface.co/docs/lerobot/implement_your_own_processor — 処理を設定として保存すれば、読み込み時に統計・デバイス・キーを差し替えられる。グラフに固める方式には無い利点。 ↩ ↩2

  11. Hugging Face「HuggingFaceVLA/smolvla_libero」policy_preprocessor.json(2026-11-03 取得). https://huggingface.co/HuggingFaceVLA/smolvla_libero/blob/main/policy_preprocessor.json — 重みの横に置かれた前処理・後処理の JSON と統計の safetensors。 ↩

  12. Hugging Face「Backward compatibility」LeRobot docs(2026-11-03 取得). https://huggingface.co/docs/lerobot/backwardcomp https://github.com/huggingface/lerobot/pull/1452 — PR #1452 で正規化を重みの外へ出した変更と移行手順、PR の説明が書く変更の理由。 ↩

  13. jashshah999「Feature: ONNX / TensorRT export for trained policies」lerobot Issue #3146, 2026-03-12(2026-11-03 open). https://github.com/huggingface/lerobot/issues/3146 — 組み込みの書き出しが無いというコミュニティの要望。メンテナの見解ではない。 ↩

この記事はAIを使用して執筆されました。内容には誤りが含まれる可能性があります。事実や数字の出典は脚注から確かめられます。