この記事について
この記事はBeaver's Hive アドベントカレンダー2025の記事の一環です
ビーバーズ・ハイブは、関西を中心に活動するモノづくりサークルです。
普段は色々なものを作ったり展示会に参加しています!
ビーバーものづくりチャンネルというYouTubeチャンネルもやっているので、もし良かったら観ていってください~
(すべりこみでアドベントカレンダーを更新しています)
本題
まずはまとめた今回やったことをまとめた動画がこちら
そして今回使用しているコードはここにまとめています
最近話題の物理シミュレーションエンジン 「Genesis」。 「生成AIのための物理世界」を謳うこの新しいエンジンを使って、自作ロボットを強化学習(Reinforcement Learning)で歩かせてみました。
あえて高機能なCAD(Fusion 360等)は使わずテキストにGeminiと格闘しながらテキストエディタだけで簡易的なロボットを作り、強化学習を回した記録です。
(つまりは、二軸しかないロボットを前に進ませて、タイトル通り某監督に怒られそうな歩き方をさせたかっただけです。)
1. Genesis とは?
Genesis は、物理的に正確なシミュレーションを、GPUを使って超高速に行うプラットフォームです。
Geminiによると、従来のシミュレータ(PyBullet, MuJoCo, Isaac Gymなど)と比べて、以下の特徴があるらしいです。
-
Pythonネイティブ: 非常に直感的にコードが書ける
-
微分可能: 物理演算の過程を微分できる(勾配降下法で物理パラメータを最適化できる)
-
生成AIとの親和性: 画像生成や3D生成AIと組み合わせて使うことを想定されている
今回はこのGenesis上で、「地面を這う尺取虫のようなロボット」 を作り、前に進むように学習させます。
2. ロボットを作る
「ロボットのモデルを作る」というとCADが必要に思えますが、単純な検証ならテキストエディタで十分です。とGeminiが言ってました。(あとわざわざCADで作るほどの複雑さもないので)
URDF(Unified Robot Description Format)はXML形式なので、コピペで書けます。ということらしいです。
今回作成した 2joint_robot.urdf は、「青い箱(土台)」に「赤と緑の棒(腕)」が生えただけのシンプルな構造です。
<robot name="simple_2joint_robot">
<link name="base_link">
<visual><geometry><box size="0.2 0.2 0.2"/></geometry>...</visual>
</link>
<joint name="joint_1" type="revolute">
<parent link="base_link"/>
<child link="link_1"/>
<axis xyz="0 1 0"/> <limit lower="-1.57" upper="1.57" effort="10.0" velocity="5.0"/>
</joint>
</robot>
これをGenesisで読み込むと、こんな感じで表示されます。
3. 学習環境の構築 (simple_env.py)
強化学習には**「環境(Environment)」**が必要です。Genesisではクラスベースでスッキリ書けます。 ポイントとなる部分を解説します。
① 観測データ(Observation)
AIに何を教えるか?です。今回は 12個のデータ を渡しました。
-
土台の速度 (3)
-
重力の方向 (3) ※姿勢を知るため
-
関節の角度 (2)
-
関節の速度 (2)
-
前回のアクション (2)
Python
def _get_obs(self):
# ロボットから情報を取得して結合
self.obs_buf = torch.cat([
base_vel, # 速度
projected_gravity, # 姿勢
dof_pos, # 関節角度
dof_vel, # 関節速度
self.actions # アクション
], dim=-1)
② 報酬設計(Reward)
AIをどう褒めるか?で、この報酬を元に学習を進めます。
シンプルに「前に早く進んだらプラス」「エネルギーを使いすぎたらマイナス」としています。
Python
def _get_rewards(self):
# 前進速度(X軸)を報酬に
velocity_reward = self.robot.get_vel()[:, 0]
# 動きすぎ(無駄な振動)は罰則
action_penalty = torch.sum(self.actions ** 2, dim=1) * 0.01
self.rew_buf = velocity_reward * 2.0 - action_penalty
4. 学習の実行と「爆発」
学習アルゴリズムには rsl_rl(PPO)を使用しました。 スクリプトを実行すると、4096体のロボットが同時にシミュレーションされ、凄まじい速度で学習が進みます……はずでした。
以下Geminiと格闘した記録です。
-
データの数(Shape)が合わない
- RuntimeError: mat1 and mat2 shapes cannot be multiplied → 設定ファイルで定義した num_obs と、実際に渡しているデータの数が1つズレていました。数え間違いには注意しましょう。
-
リセット処理のバグ
- 倒れたロボットだけ元の位置に戻す処理で、全員分のデータを渡してしまいエラーに。 → self.init_qpos[env_ids] のように、リセット対象のインデックスでスライスして渡す必要がありました。
-
物理演算の爆発(NaNエラー)
- GenesisException: Invalid constraint forces causing 'nan' 学習が進んでロボットが激しく動き出すと、シミュレーションが破綻してエラー落ちしました。
この辺を解決して学習してみたのですが、めっちゃプルプルしていました。
5. 解決策:PD制御(Kp/Kv)のチューニング
物理演算が爆発したり、ロボットがプルプル震えて進まない原因は、PD制御(Proportional-Derivative Control) の設定にありました。Geminiが見つけました。以下Geminiによる解説です。
強化学習において、AIは「関節をこの角度にしたい」と念じますが、実際にモーターを動かすのはPD制御です。
Kp (Pゲイン): バネの強さ。高いと目標位置に素早く動くが、高すぎると**発振(プルプル)**する。
Kv (Dゲイン): ブレーキの強さ(粘り)。低いと振動が収まらず、高いと動きが鈍くなる。
修正前の設定(デフォルト)
Kp=未設定, Kv=未設定 → ロボットはフニャフニャか、あるいはデフォルト値が合わずに振動。
修正後の設定
Python
# 少し柔らかめ(Kp=10)にしつつ、ブレーキ(Kv=1.0)をしっかり効かせる
self.robot.set_dofs_kp(
torch.tensor([10.0, 10.0], device=self.device),
dofs_idx_local=self.motor_dofs
)
self.robot.set_dofs_kv(
torch.tensor([1.0, 1.0], device=self.device),
dofs_idx_local=self.motor_dofs
)
さらに、物理演算の精度を上げるために、シミュレーションの時間刻み(dt)を 0.02秒から 0.01秒 に細かくしました。
6. 結果 : 這い進むロボットの誕生
上記の通りの
パラメータ調整後、再度学習を2000回(イテレーション)回しました。 再生用スクリプト(simple_play.py)で確認すると……
こんな感じで、ちゃんと人類に対して侮辱を感じさせる気がする歩き方をしたので満足です。
(Qiitaって大きいサイズのGIF貼れなかったので、上の動画で確認してください🥺)
まとめ:Genesisで強化学習を始めるコツ
今回、Genesisを触ってみて得られた知見は以下の通りです。
-
リセット処理は envs_idx が肝: 全環境ではなく「リセットが必要な環境」だけを操作する作法を覚える
-
Kp/Kvの調整が:結構大事: 学習が進まない、またはエラーで落ちる時は、ニューラルネットの構造よりも「物理パラメータ(硬さと粘り)」と「シミュレーション精度(dt)」を見直すべき
なんにせよ、いい感じに歩かせられてよかったです。
参考リンク

