二足歩行型

【Unitree G1】動画から人の動きの再現

弊社インターンの作成記事になります

目次

はじめに

本記事では,GENMO,GMR,ProtoMotionsを用いて,人物動画からUnitree G1向けのモーションを生成する手順を紹介します.

参考記事では,動画から人体モーションを抽出し,Unitree G1向けにリターゲティングした後,事前学習済みの制御ポリシーを用いて,物理シミュレーション上で安定した動作を生成するまでの全体像が説明されています.

本記事では,その流れを参考にしながら,自分の環境で実際に検証した際の実行コマンド,データ変換方法,発生したエラーとその対応を中心にまとめます.参考記事を補足する形で,実際の再現手順と検証時に詰まった点を記録することを目的としています.

この記事で分かること

  • 人物動画からUnitree G1向けのモーションを生成する一連の流れ
  • GENMOの出力をGMRで読み込める形式へ変換する方法
  • GMRで生成したモーションをProtoMotions形式へ変換する方法
  • 公式checkpointを用いてモーショントラッキングを実行する方法
  • 公式checkpointを初期値として,Isaac Gymで追加学習する方法
  • 接地位置,クォータニオンの順序,MotionLibの読み込みエラーへの対応例

この記事の対象者

  • 人物動画を基に,Unitree G1のモーションを生成したい人
  • GENMO,GMR,ProtoMotionsを組み合わせて使用したい人
  • モーションの形式変換やリターゲティングで詰まっている人
  • 公式checkpointを用いた推論と追加学習の流れを確認したい人

使用する動画

入力動画の選び方

GENMOで人物の動きを正しく推定するためには,入力動画の撮影条件や動作の内容が重要です.今回の検証では,主に以下の点を意識して動画を選びました.

  • カメラが固定されていること
    カメラ自体が大きく移動したり揺れたりすると,人物の移動とカメラの移動を区別しにくくなる可能性があります.そのため,定点カメラで撮影された動画が望ましいです.
  • 人物の全身が映っていること
    頭から足先までが画面内に収まり,動作中も身体の一部が画面外へ出ない動画を選びます.特に,足の位置が見えない場合は,接地状態や下半身の動きを正しく推定できない可能性があります.
  • 直立した状態から動作を開始すること
    正座や深い中腰など,ロボットの初期姿勢と大きく異なる状態から始まる動画よりも,直立した状態から動作を開始する動画の方が扱いやすいと考えました.
  • 人物と背景を区別しやすいこと
    人物の服装と背景の色が似ている場合,身体の輪郭を認識しにくくなる可能性があります.そのため,人物と背景の色や明るさに差がある動画が望ましいです.
  • 動作ごとに短く区切ること
    長時間の動画をそのまま使用するのではなく,一つの技や一連の動作ごとに短く切り出します.短く区切ることで,変換結果を確認しやすくなり,追加学習に必要な時間も抑えられます.
  • 身体の重なりや遮蔽が少ないこと
    腕や脚が身体の後ろに隠れ続ける動画や,他の人物や物体によって身体が遮られる動画は避けます.

これらは,今回の検証を通して入力動画を選ぶ際に意識した点です.

今回使用した動画

今回は,Unitree G1に学習させる参照モーションとして,以下の2つの動画を使用しました.

躰道

以下の動画の30秒から45秒までの動きを使用します.

https://youtu.be/XbopRIx3his?si=kRnGPUGaGC2MeW84

テコンドー

以下の動画の0秒から3秒までの動きを使用します.

なぜ躰道を選んだのか

私は学生時代に躰道サークルに所属していました.その経験から,躰道のダイナミックで格好良い動きを,ロボットモーションとして再現してみたいと考えました.また,本記事を通して,躰道という武道やその特徴的な動きを知ってもらいたいという思いもあります.

躰道は,突きや蹴りといった武道の技に,跳躍や回転などの立体的な動きを取り入れていることが特徴です.身体の軸や重心を意識して動くことが重要であるため,その動作をロボットへリターゲティングした際にも,バランスを保ちやすいモーションになるのではないかと考えました.

全体の流れ

本記事では,以下の5つのStepに沿って,人物動画からUnitree G1向けのモーションを生成します.

Step 1:GENMOによる人体モーションの推定
Step 2:GMRによるUnitree G1へのリターゲティング
Step 3:MuJoCoによるキネマティクス再生
Step 4:ProtoMotions形式への変換と公式checkpointによる推論
Step 5:Isaac Gymによる追加学習

動作環境・使用ツール

本記事では,以下の環境で動作確認を行いました.

対象Step実行環境主な使用ツール
Step 1Google Colab(Ubuntu 22.04.5 LTS)GENMO
Step 2〜4Ubuntu 24.04.2 LTSGMR,ProtoMotions,MuJoCo
Step 5Ubuntu 22.04.5 LTS,NVIDIA GeForce RTX 3090ProtoMotions,Isaac Gym

Step 1:GENMOで動画からSMPLパラメータを生成する

Step 1では,Google Colab上でGENMOを実行し,入力動画からSMPLパラメータを生成します.

実行前に,Google Colabのメニューから[ランタイム]→[ランタイムのタイプを変更]を選択し,ハードウェアアクセラレータをGPUに設定しておきます.

1.環境を構築する

GENMOとGVHMRのリポジトリをクローンし,Python 3.10の仮想環境を作成します.

以下のコマンドをGoogle Colabのセルで実行します.環境構築コマンド

%%bash
set -e

mkdir -p /content/intern/g1-motion
cd /content/intern/g1-motion

git clone https://github.com/NVlabs/GENMO.git
git clone https://github.com/zju3dv/GVHMR.git

python -m pip install -q uv

cd GENMO

uv venv .venv --python 3.10 --clear

uv pip install \
  --python .venv/bin/python \
  pip setuptools wheel

uv pip install \
  --python .venv/bin/python \
  -e .

uv pip install \
  --python .venv/bin/python \
  -e ../GVHMR

uv pip install \
  --python .venv/bin/python \
  huggingface_hub

以降のGENMO関連のコマンドでは,作成した仮想環境内のPythonである.venv/bin/pythonを使用します.

2.Google Driveをマウントする

SMPL-Xモデル,入力動画,生成結果をGoogle Driveから読み書きするため,Google DriveをGoogle Colabへマウントします.

from google.colab import drive

drive.mount("/content/drive")

3.SMPL-Xモデルと入力動画を配置する

事前に,以下のファイルをGoogle Driveへ配置しておきます.

  • SMPLX_NEUTRAL.npz
  • モーションを抽出する入力動画

本記事では,入力動画のファイル名をinput.mp4とします.

Google Drive上のファイルを,GENMOの実行ディレクトリへコピーします.Google Colabへのコピーコマンド

%%bash
set -e

cd /content/intern/g1-motion/GENMO

mkdir -p inputs/checkpoints/body_models/smplx

cp \
  /content/drive/MyDrive/intern/g1-motion/checkpoints/SMPLX_NEUTRAL.npz \
  inputs/checkpoints/body_models/smplx/SMPLX_NEUTRAL.npz

cp \
  /content/drive/MyDrive/intern/g1-motion/videos/input.mp4 \
  ./input.mp4

4.GVHMRの補助ファイルを配置する

GENMOの実行に必要な人体モデル関連の補助ファイルを,GVHMRのディレクトリからGENMO側へコピーします.補助ファイルの配置

%%bash
set -e

cd /content/intern/g1-motion/GENMO

mkdir -p gem/utils/body_model

cp \
  ../GVHMR/hmr4d/utils/body_model/smplx2smpl_sparse.pt \
  ../GVHMR/hmr4d/utils/body_model/coco_aug_dict.pth \
  ../GVHMR/hmr4d/utils/body_model/smplx_verts437.pt \
  ../GVHMR/hmr4d/utils/body_model/smpl_coco17_J_regressor.pt \
  gem/utils/body_model/

5.事前学習済みモデルをダウンロードする

姿勢推定に使用するViTPoseとHMR2の事前学習済みモデルを,Hugging Faceからダウンロードします.ダウンロードコマンド

%%bash
set -e

cd /content/intern/g1-motion/GENMO

.venv/bin/python - <<'PY'
from huggingface_hub import hf_hub_download

files = [
    "vitpose/vitpose-h-multi-coco.pth",
    "hmr2/epoch=10-step=25000.ckpt",
]

for filename in files:
    hf_hub_download(
        repo_id="camenduru/GVHMR",
        filename=filename,
        local_dir="inputs/checkpoints",
    )
PY

ダウンロード後のファイル構成は,次のようになります.

inputs/checkpoints/
├── body_models/
│   └── smplx/
│       └── SMPLX_NEUTRAL.npz
├── hmr2/
│   └── epoch=10-step=25000.ckpt
└── vitpose/
    └── vitpose-h-multi-coco.pth

6.入力動画を前処理する

GENMOへ入力する前に,動画から使用する区間を切り出し,フレームレートと解像度を統一します.

今回は,入力動画の先頭3秒を切り出し,30 fps,横幅512ピクセルへ変換しました.

%%bash
set -e

cd /content/intern/g1-motion/GENMO

ffmpeg -y \
  -ss 0 \
  -t 3 \
  -i input.mp4 \
  -vf "fps=30,scale=512:-2" \
  -c:v libx264 \
  -pix_fmt yuv420p \
  -an \
  input_512.mp4

主なオプションの意味は,以下のとおりです.

オプション説明
-ss 0入力動画の0秒地点から切り出します.
-t 3切り出す動画の長さを3秒に指定します.
fps=30フレームレートを30 fpsへ変換します.
scale=512:-2アスペクト比を維持したまま,横幅を512ピクセルへ変更します.
-c:v libx264映像をH.264形式 映像をH.264形式でエンコードします.
-pix_fmt yuv420p出力動画のピクセル形式をyuv420pに指定します.
-an出力動画から音声を削除します.

7.GENMOを実行する

前処理した動画(./input_512.mp4)と,生成したい動きを表すテキスト(”text:a person is performing a traditional dance”)をGENMOへ入力します.

%%bash
set -e

cd /content/intern/g1-motion/GENMO

export XDG_RUNTIME_DIR=/tmp/runtime-root
mkdir -p "${XDG_RUNTIME_DIR}"
chmod 700 "${XDG_RUNTIME_DIR}"

export PYOPENGL_PLATFORM=egl
export MUJOCO_GL=egl

.venv/bin/python scripts/demo/demo_smpl.py \
  --input_list \
    ./input_512.mp4 \
    "text:a person is performing a traditional dance" \
  --no_render

--no_renderを指定することで,この段階では動画のレンダリングを行わず,SMPLパラメータのみを生成します.

実行後,次のファイルが生成されます.

outputs/input_512_mix/smpl_params.pt

このファイルには,入力動画から推定されたモーションと,テキストから生成されたモーションの両方が含まれています.

8.入力動画に対応する区間を抽出する

次のStepでは,入力動画から推定されたモーションのみを使用します.

そこで,smpl_params.ptに含まれるsegment_infoを参照し,typevideoとなっている区間を抽出します.入力動画区間の抽出コード

%%bash
set -e

cd /content/intern/g1-motion/GENMO

.venv/bin/python - <<'PY'
from pathlib import Path

import torch

src = Path("outputs/input_512_mix/smpl_params.pt")
dst = Path("outputs/input_512_mix/smpl_params_video_only.pt")

data = torch.load(
    src,
    map_location="cpu",
    weights_only=False,
)

video_segment = next(
    segment
    for segment in data["segment_info"]
    if segment["type"] == "video"
)

start = video_segment["start"]
end = video_segment["end"]

out = {}

for key in ["body_params_global", "body_params_incam"]:
    out[key] = {
        name: value[start:end].clone()
        for name, value in data[key].items()
    }

if "K_fullimg" in data:
    out["K_fullimg"] = data["K_fullimg"][start:end].clone()

out["segment_info"] = [
    {
        **video_segment,
        "start": 0,
        "end": end - start,
    }
]

torch.save(out, dst)

print(f"saved: {dst}")
print(f"frames: {end - start}")
PY

フレーム数を固定値で指定するのではなく,出力ファイルに記録されたsegment_infoを使用して抽出しています.これにより,入力動画の長さが変わった場合でも,同じコードで動画区間を取得できます.

抽出後,次のファイルが生成されます.

outputs/input_512_mix/smpl_params_video_only.pt

9.生成結果をGoogle Driveへ保存する

Step 2のGMRによるリターゲティングで使用するsmpl_params_video_only.ptを,Google Driveへコピーします.

%%bash
set -e

cd /content/intern/g1-motion/GENMO

OUTPUT_DIR=/content/drive/MyDrive/intern/g1-motion/GENMO_outputs/input_512_mix

mkdir -p "${OUTPUT_DIR}"

cp \
  outputs/input_512_mix/smpl_params_video_only.pt \
  "${OUTPUT_DIR}/"

以上で,Step 2のGMRによるリターゲティングに使用するSMPLパラメータの生成は完了です.

Step 2:GMR用にキーを変換し,Unitree G1へリターゲティングする

Step 2では,GENMOが生成したSMPLパラメータをGMRで読み込める形式へ変換し,Unitree G1向けのモーションにリターゲティングします.

1.GENMOの出力キーをGMR用に変換する

GENMOの出力ファイルでは,SMPLパラメータが以下のキーに保存されていました.

body_params_global
body_params_incam

一方,今回使用したGMRのgvhmr_to_robot.pyでは,以下のキー名を参照します.

smpl_params_global
smpl_params_incam

そこで,GENMOの出力に含まれるデータをコピーし,GMRが参照するキーを追加しました.
変換後のファイルは,以下の名前で保存します.

data/genmo/smpl_params_video_only_gvhmr_format.pt

2.足が床に接地しない問題に対応する

発生した問題

リターゲティング結果をMuJoCoで再生したところ,足裏と地面の間に隙間があり,ロボットが床から少し浮いているように見えました.

offset_to_groundを有効にする

まず,GMRのリターゲティング処理で接地位置を補正するため,gvhmr_to_robot.py内の処理を,次のように変更します.

# 変更前
qpos = retarget.retarget(smplx_data)

# 変更後
qpos = retarget.retarget(
    smplx_data,
    offset_to_ground=True,
)

ground_offsetを調整する

offset_to_ground=Trueを有効にした後も,今回のモーションでは足裏が床からやや浮いているように見えました.

そこで,接地位置の補正量を指定するground_offsetを変更しました.

# 変更前
ground_offset = 0.1

# 変更後
ground_offset = 0.05

今回の入力モーションでは,ground_offset0.05に設定することで,足裏と床の隙間が小さくなりました.

3.Unitree G1へリターゲティングする

キーの変換と接地位置の調整が完了したら,gvhmr_to_robot.pyを実行します.

python scripts/gvhmr_to_robot.py \
  --gvhmr_pred_file data/genmo/smpl_params_video_only_gvhmr_format.pt \
  --robot unitree_g1 \
  --save_path retargeting_data/unitree_g1/smpl_params_video_only.pkl \
  --rate_limit

主な引数の意味は以下のとおりです.

引数説明
--gvhmr_pred_fileGMR形式に変換したSMPLパラメータの入力ファイルを指定します.
--robot unitree_g1リターゲティング先のロボットとしてUnitree G1を指定します.
--save_path変換後のロボットモーションを保存する場所を指定します.
--rate_limit関節角度の急激な変化を抑える処理を有効にします.

実行後,以下のファイルが生成されます.

retargeting_data/unitree_g1/smpl_params_video_only.pkl

Step 3:MuJoCoでリターゲティング結果を再生する

Step 3では,Step 2で生成した.pklファイルをMuJoCo上で再生し,リターゲティング結果を確認します.

まず,録画した動画の保存先を作成します.

mkdir -p ~/intern/g1-motion/step3_outputs

続いて,vis_robot_motion.pyを実行します.

python scripts/vis_robot_motion.py \
  --robot unitree_g1 \
  --robot_motion_path retargeting_data/unitree_g1/smpl_params_video_only.pkl \
  --record_video \
  --video_path ~/intern/g1-motion/step3_outputs/step3_kinematics_replay.mp4

主な引数の意味は以下のとおりです.

引数説明
--robot unitree_g1再生に使用するロボットモデルを指定します.
--robot_motion_pathStep 2で生成したモーションファイルを指定します.
--record_video再生結果を動画として保存します.
--video_path録画した動画の保存先を指定します.

この段階では,強化学習による制御は行いません.リターゲティングによって得られたルート姿勢と関節角度の時系列データを,ロボットモデルへ反映して再生します.

主に以下の点を確認しました.

  • ロボットの姿勢が大きく崩れていないか
  • 足裏と床の間に不自然な隙間がないか
  • 入力動画の動きが大まかに反映されているか
  • 関節の向きや回転が不自然になっていないか
  • フレーム間で関節角度が急激に変化していないか

この段階で姿勢や動作に問題がある場合は,ProtoMotions形式へ変換する前に,入力動画,キー変換,接地補正,クォータニオンなどを確認します.

Step 4:ProtoMotions形式へ変換し,公式checkpointでWBC推論する

Step 4では,GMRで生成した.pklファイルをProtoMotionsで扱える形式へ変換し,公式の事前学習済みcheckpointを用いてモーショントラッキングを実行します.

今回使用した変換経路は,以下のとおりです.

GMRの.pkl
  ↓
.csv
  ↓
.motion
  ↓
モーション一覧を記述したYAML
  ↓
MotionLib用のpackaged .pt

.motionファイルとYAMLは,公式checkpointを用いたMuJoCo上でのモーショントラッキングに使用します.

一方,packaged .ptファイルは,Step 5でIsaac Gymによる追加学習を行う際に使用します.

1..pkl.csvへ変換する

まず,GMRで生成した.pklファイルを.csv形式へ変換します.

クォータニオンの順序が異なる問題

発生した問題

GMRのroot_rotは,クォータニオンがxyzwの順序で格納されていました.一方,今回使用したProtoMotions側の変換処理では,wxyzの順序が必要でした.

そのまま変換すると,ルート姿勢が正しく解釈されず,ロボットの向きや姿勢が不自然になりました.

対応方法

.pklから.csvへ変換する際に,batch_gmr_pkl_to_csv_wxyz.pyのクォータニオンを次のように並べ替えました.

motion[:, 3:7] = motion_data["root_rot"][:, [3, 0, 1, 2]]

この処理により,xyzw → wxyzに順序を変換しています.
修正した変換スクリプトを実行します.

python scripts/batch_gmr_pkl_to_csv_wxyz.py \
  --folder retargeting_data/unitree_g1

変換後の.csvファイルは,以下のディレクトリに生成されます.

retargeting_data/unitree_g1/csv/

2..csv.motionへ変換する

ProtoMotionsの変換スクリプトを使用し,GMRの.csvファイルを.motion形式へ変換します.

mkdir -p data/motion_for_trackers/custom/motions_from_gmr

python data/scripts/convert_pyroki_retargeted_robot_motions_to_proto.py \
  --retargeted-motion-dir \
    ~/intern/g1-motion/GMR/retargeting_data/unitree_g1/csv \
  --output-dir \
    data/motion_for_trackers/custom/motions_from_gmr \
  --robot-type g1 \
  --input-fps 30 \
  --output-fps 30 \
  --force-remake

主な引数の意味は,以下のとおりです.

引数説明
--retargeted-motion-dirGMRから出力された.csvファイルのディレクトリを指定します.
--output-dir変換後の.motionファイルを保存するディレクトリを指定します.
--robot-type g1対象ロボットとしてUnitree G1を指定します.
--input-fps 30入力モーションのフレームレートを指定します.
--output-fps 30出力モーションのフレームレートを指定します.
--force-remake既存の出力がある場合でも,再度変換を実行します.

変換後,以下のファイルが生成されます.

data/motion_for_trackers/custom/motions_from_gmr/
└── smpl_params_video_only.motion

3.モーション一覧を記述したYAMLを作成する

ProtoMotionsへ読み込ませるモーションとその重みを,YAMLファイルに記述します.

cat > data/motion_for_trackers/custom/smpl_params_video_only.yaml <<'YAML'
motions:
  - file: motions_from_gmr/smpl_params_video_only.motion
    weight: 1.0
YAML

weightは,複数のモーションを読み込む場合に,各モーションをどの程度の割合で使用するかを指定する値です.今回は1つのモーションのみを使用するため,1.0に設定しています.

4.MotionLib用の.ptファイルを作成する

Step 5の追加学習で使用するため,YAMLに記載したモーションをMotionLib用の.ptファイルにまとめます.

python protomotions/components/motion_lib.py \
  --motion-path \
    data/motion_for_trackers/custom/smpl_params_video_only.yaml \
  --output-file \
    data/motion_for_trackers/custom/smpl_params_video_only_protomotions.pt \
  --device cpu

実行後,以下のファイルが生成されます.

data/motion_for_trackers/custom/
└── smpl_params_video_only_protomotions.pt

5.公式checkpointによるWBC推論

変換後のモーションと公式checkpointを指定し,MuJoCo上でモーショントラッキングを実行します.

ここで行う処理は,関節角度を直接ロボットモデルへ反映するStep 3のキネマティクス再生とは異なり,事前学習済みの制御ポリシーが参照モーションを追従しながら,物理シミュレーション上でロボットを制御します.

python protomotions/inference_agent.py \
  --checkpoint \
    data/pretrained_models/motion_tracker/g1-bones-deploy/last.ckpt \
  --motion-file \
    data/motion_for_trackers/custom/smpl_params_video_only.yaml \
  --simulator mujoco \
  --num-envs 1

主な引数の意味は,以下のとおりです.

引数説明
--checkpoint推論に使用する事前学習済み制御ポリシーを指定します.
--motion-file追従対象となる参照モーションのYAMLファイルを指定します.
--simulator mujocoシミュレータとしてMuJoCoを使用します.
--num-envs 1実行する並列環境数を1に設定します.

Step 5:Isaac Gymで追加学習し,学習後checkpointを確認する

Step 5では,公式checkpointを初期値として,今回用意したモーションに対する追加学習を行います.

ゼロから新しい制御ポリシーを学習するのではなく,既に汎用的な動作を学習している公式checkpointから学習を再開する,Warm Startを使用します.

今回の処理は,以下の流れで行いました.

  1. Step 4で作成したMotionLib形式の.ptファイルを用意する
  2. モーションデータを学習用GPUマシンへ転送する
  3. 公式checkpointに対応するexperiment configを基に,学習設定を調整する
  4. Isaac Gym上で追加学習を行う
  5. 保存されたcheckpointをMuJoCo上で読み込み,動作を比較する

1.MotionLib読み込み時のエラーに対応する

発生した問題

MotionLib用の.ptファイルを読み込んだ際に,packaged motionにcontacts属性が含まれておらず,self.contactsを参照する処理でエラーが発生しました.

対応方法

contacts属性が存在しない場合に,Noneを設定する処理をmotion_lib.pyへ追加しました.

# Some packaged motion files may not contain optional contacts.
if not hasattr(self, "contacts"):
    self.contacts = None

これは,Noneのフィールドを読み飛ばす処理ではなく,存在しないcontacts属性を補完するための処理です.

注意

本来は,変換処理の段階で必要な属性を適切に生成する方が望ましい可能性があります.
今回の修正は,実験を進めるための暫定的な対応として扱っています.

2.追加学習の設定を調整する

Isaac Gymで追加学習を行う際には,公式checkpointの方策を急激に変化させないことと,学習途中のcheckpointを細かく比較することを目的として,以下の設定値を変更しました.

actor_optimizer = 2e-6
critic_optimizer = 1e-5
discriminator_optimizer = 1e-5
num_mini_epochs = 2
save_epoch_checkpoint_every = 10

各項目の設定値と役割は,以下のとおりです.

項目説明
actor_optimizerロボットの行動を決定するActorの学習率です.値を小さくすることで,事前学習済みの方策を大きく崩さず,対象モーションへ徐々に適応させることを狙いました.
critic_optimizerActorが選択した行動や状態の価値を評価するCriticの学習率です.どの状態や行動が高い報酬につながるかを学習します.
discriminator_optimizer実行した動作が参照モーションらしいかを評価するDiscriminatorの学習率です.
num_mini_epochs収集した1回分の学習データに対して,パラメータ更新を繰り返す回数です.値を増やすと同じデータを多く使用できますが,計算量の増加や過学習につながる可能性があります.
save_epoch_checkpoint_everycheckpointを保存するepoch間隔です.今回は,学習途中の動作を比較できるように,10 epochごとに保存しました.

今回の設定では,Actorの学習率を比較的小さくしました.これにより,事前学習済みの動作能力をできるだけ維持しながら,対象モーションへ段階的に適応させることを狙っています.

3.Isaac Gymで追加学習する

以下のコマンドを実行し,公式checkpointを初期値とした追加学習を開始します.

python protomotions/train_agent.py \
  --robot-name g1 \
  --simulator isaacgym \
  --experiment-path \
    data/pretrained_models/motion_tracker/g1-bones-deploy/experiment_config_lr01_save10.py \
  --experiment-name keri \
  --motion-file \
    ../data/keri/orig_data/smpl_params_video_only_protomotions.pt \
  --checkpoint \
    data/pretrained_models/motion_tracker/g1-bones-deploy/last.ckpt \
  --num-envs 128 \
  --batch-size 4096 \
  --ngpu 1 \
  --training-max-steps 192512000

主な引数の意味は,以下のとおりです.

引数説明
--robot-name g1学習対象のロボットとしてUnitree G1を指定します.
--simulator isaacgym学習用シミュレータとしてIsaac Gymを使用します.
--experiment-path学習率やcheckpointの保存間隔などを記述した設定ファイルを指定します.
--experiment-name keri実験結果を識別する名前を指定します.
--motion-fileStep 4で作成したMotionLib形式の.ptファイルを指定します.
--checkpointWarm Startに使用する公式checkpointを指定します.
--num-envs 128並列実行するシミュレーション環境数を指定します.
--batch-size 40961回のパラメータ更新に使用するサンプル数を指定します.
--ngpu 1学習に使用するGPU数を指定します.
--training-max-steps 192512000学習を行う最大step数を指定します.

num-envsを増やすと,複数のシミュレーション環境から並列に経験を収集できますが,必要なGPUメモリも増加します.また,batch-sizetraining-max-stepsは,使用するGPUや目標とする学習量に応じて調整する必要があります.

結果

追加学習中に保存されたcheckpointを順番にMuJoCo上で再生し,参照モーションの再現度や姿勢の安定性を目視で比較しました.

以下は,checkpointを指定して動作を確認するコマンドの例です.

python protomotions/inference_agent.py \
  --checkpoint ./results/keri/epoch_46850.ckpt \
  --motion-file ../data/keri/orig_data/smpl_params_video_only_protomotions.pt \
  --simulator mujoco \
  --num-envs 1

以下に,Step 5で得られた動作結果を示します.

躰道の法形

sen_houkei.gif

テコンドーの回し蹴り

keri.gif

結果から分かったこと

どちらのモーションでも,入力動画に含まれる大まかな身体の動きをUnitree G1上で再現できました.一方で,入力動画から奥行き方向の動きを把握しにくい場面では,重心移動や足の位置が不安定になる様子も見られました.

特に,回転や蹴りのように奥行き方向へ大きく身体を動かすモーションでは,以下の点が結果に影響すると考えられます.

  • 人物を撮影するカメラの角度
  • 腕や脚の重なり
  • 支持脚や足先の見えやすさ
  • 動作開始時の姿勢
  • 入力動画から推定された奥行き方向の位置

まとめ

本記事では,GENMO,GMR,ProtoMotionsを用いて,人物動画からUnitree G1向けのモーションを生成するまでの手順や,その流れを自分の環境で再現する際に使用したコマンドや,実際に必要となったデータ変換,修正箇所を中心にまとめました.

今回の結果から,人物動画を基に,躰道やテコンドーのような動きの大まかな特徴をUnitree G1上で再現できることを確認しました.一方で,奥行き方向の推定や接地,重心移動には改善の余地があります.今後は,入力動画の撮影条件や学習設定を変更し,より安定した動作を生成できるか検証したいと考えています.

関連記事

TOP