이 저장소가 대체 무엇인가.
게임 캐릭터가 자연스럽게 걷고 뛰고 구르는 애니메이션을 만들려면 전통적으로는 사람이 모션 캡처를 찍고 애니메이터가 일일이 다듬어야 했다. 로봇이 걷는 법을 배우게 하려면 로봇공학자가 제어 이론으로 보행 패턴을 손수 설계해야 했다. ProtoMotions3는 이 두 문제를 하나의 틀로 묶는다 — "물리 법칙이 작동하는 가상 세계(시뮬레이터)에 사람 동작 데이터를 놓고, 강화학습 에이전트가 그 동작을 흉내 내는 과정에서 스스로 균형·보행·제어를 익히게" 하는 것이다.
비유하면: AMASS 동작 데이터셋 = 무술 교본 영상 수만 개, 물리 시뮬레이터(IsaacGym 등) = 안전하게 반복 연습할 수 있는 가상 도장, 강화학습 에이전트 = 영상을 보고 실제로 몸을 움직여 따라 하는 연습생이다. 수천 개의 가상 도장(병렬 환경)에서 동시에 연습시키면, GPU 한 대로 하루 만에 40시간 분량의 동작을 익힐 정도로 빨라진다. 그리고 이 연습생(정책)을 실제 로봇(Unitree G1)에 그대로 옮겨 심으면, 진짜 로봇이 사람처럼 움직인다.
README는 이렇게 소개한다: "A GPU-accelerated simulation and learning framework for training physically simulated digital humans and humanoid robots." 모듈성(Modularity), 확장성(Extensibility), 확장 가능성(Scalability) 세 가지를 핵심 가치로 내세우며, 애니메이션·로보틱스·강화학습이라는 서로 다른 커뮤니티를 잇는 다리 역할을 표방한다. NVIDIA Research의 SIL(Simulation, Imitation, Learning) 팀이 만들었고, 이전 버전들(ProtoMotions, ASE, MaskedMimic 등 여러 논문 코드베이스)의 후속작인 3세대(v3.1)다.
NVIDIA Research의 다목적 통합 플랫폼 포지셔닝 · sim2real 실증 · 경쟁 프로젝트 대비 장점.
ProtoMotions3가 TrendShift 상위권에 오른 이유는 크게 세 가지로 요약된다. 첫째, 휴머노이드 로봇(Unitree G1·H1_2 등) 상용화가 급물살을 타면서 "물리 시뮬레이션으로 로봇 제어를 학습시키는" 접근 자체의 수요가 폭증했다. 둘째, README가 보여주는 데모 목록이 이례적으로 광범위하다 — 대규모 모션 학습, 멀티 GPU 확장, 원커맨드 리타겟팅, 임의 로봇 학습, sim2sim, sim2real, 고품질 렌더링, 텍스트-투-모션, 절차적 씬 생성, 생성형 정책까지 한 저장소 안에서 전부 다룬다. 셋째, NVIDIA Research 브랜드와 Apache-2.0 완전 오픈소스 라이선스가 결합되어 학계·산업계 양쪽에서 채택 장벽이 낮다.
| 비교 축 | IsaacLab / legged_gym | ASE / AMP (원조 논문 코드) | ProtoMotions3의 접근 |
|---|---|---|---|
| 범위 | 범용 로봇 학습 프레임워크(과제 특화 X) | 단일 논문 재현용 코드(범위 좁음) | 모션 모방 + 로보틱스 + 생성형 정책을 한 저장소에 |
| 시뮬레이터 | 보통 1~2종 고정 | IsaacGym 단일 종속 | 5종 지원(IsaacGym/IsaacLab/Newton/MuJoCo/Genesis) — 실행 인자 한 줄만 교체 |
| 모션 데이터 | 제공 안 함(직접 설계) | AMASS 일부 | AMASS 전체(40+시간) + BONES-SEED(14만+ 모션) + Kimodo 텍스트-투-모션 |
| 로봇 확장 | 로봇별 재구현 필요 | SMPL 휴머노이드 고정 | 설정 파일 등록만으로 신규 로봇 추가(robot_configs/factory.py) |
| sim2real 실증 | 제한적 | 없음(순수 시뮬레이션 연구) | Unitree G1 실기 배포 + ONNX 파이프라인 문서화 |
| 자매 프로젝트 | - | - | MimicKit(경량 버전) 병행 제공 |
README는 "One-click test of robot control policies... in different physics engines"라고 주장하는데, 실제로 protomotions/simulator/ 아래에 base_simulator/(추상 인터페이스)와 isaacgym/·isaaclab/·newton/·mujoco/·genesis/ 5개의 구체 구현이 나란히 존재한다. base_simulator/simulator.py(1,679줄)에 정의된 추상 메서드가 20개 이상(_physics_step·_apply_simulator_pd_targets·_get_simulator_bodies_state 등)이며, 각 시뮬레이터는 이 계약을 구현하기만 하면 나머지 학습·평가·리타겟팅 코드를 그대로 재사용한다. "말로만 5종 지원"이 아니라 실제 추상 클래스 설계로 뒷받침된 통합이다.
README는 이렇게 설명한다: "Our deployment pipeline exports a single ONNX model (with observation computation baked in), so deployment frameworks only need to provide raw sensor signals." 실제로 deployment/export_bm_tracker_onnx.py(740줄)는 체크포인트에서 관측(observation) 함수까지 통째로 ONNX 그래프에 굽는다 — 로봇 배포 팀이 별도로 "학습 때와 똑같은 관측 계산 로직"을 재구현할 필요가 없다는 뜻이다. 이런 실무 디테일까지 오픈소스로 공개된 점이 로보틱스 실무자들에게 특히 매력적이다.
이름 그대로 "프로토타이핑 플랫폼"이다. README의 대표 데모(AMASS 전체 학습)는 A100 4장으로 12시간, 대규모 확장 실험은 A100 24장을 사용했다고 명시되어 있다 — 개인이 노트북에서 대표 결과를 그대로 재현하기는 어렵다. 다만 MuJoCo 백엔드는 CPU 전용(num_envs=1)으로 동작해, 학습된 체크포인트를 GPU 없이 눈으로 확인하는 용도로는 쓸 수 있다(7·8절 참고).
시뮬레이터 백엔드 5종 · 강화학습 프레임워크(PyTorch Lightning Fabric) · 리타겟팅/변환 파이프라인.
setup.py는 아주 단순하다 — 패키지 이름 protomotions, 버전 3.1, find_namespace_packages로 하위 패키지를 전부 포함한다. 진짜 복잡함은 의존성 쪽에 있다 — 시뮬레이터별로 requirements_isaacgym.txt·requirements_isaaclab.txt·requirements_newton.txt·requirements_mujoco.txt·requirements_genesis.txt 5개의 별도 requirements 파일이 존재한다. 이는 "하나의 코드베이스, 여러 개의 설치 프로파일"이라는 설계 철학을 그대로 드러낸다.
| 시뮬레이터 | 실행 방식 | 핵심 의존성 | 특징 |
|---|---|---|---|
| IsaacGym | Preview 4, GPU 전용 | torch>=2.2, python 3.8 | 가장 오래된 대규모 병렬 GPU 물리 엔진. 레거시지만 여전히 널리 쓰임 |
| IsaacLab | v2.3.0, GPU 전용 | Omniverse 기반, USD 씬 | IsaacGym 후속. Gaussian splatting 렌더링(IsaacSim 5.0+) 지원 |
| Newton | 1.0.0(PyPI), GPU 전용 | warp-lang, mujoco 3.5.0, uv 패키지 매니저 | NVIDIA·Google DeepMind·Disney Research 공동 개발 차세대 오픈 물리 엔진 |
| MuJoCo | 3.0+, CPU 전용 | onnxruntime, dm_control | 단일 환경(num_envs=1)만 지원 — 빠른 디버깅·재현용 |
| Genesis | 커뮤니티 기여, 미검증(untested) | genesis-world, torch==2.5.0 | 공식 지원은 아니나 "커스텀 시뮬레이터 추가" 예시로 저장소에 포함 |
| 레이어 | 기술 | 역할 |
|---|---|---|
| 분산학습 오케스트레이션 | PyTorch Lightning Fabric | 멀티 GPU/노드 학습 루프 관리(fabric.launch()·fabric.call() 훅 시스템) |
| 실험 추적 | Weights & Biases(wandb) + TensorBoard | 학습 곡선·하이퍼파라미터 로깅. wandb 비활성 시 자동 폴백 |
| 텐서 배치 관리 | tensordict | 관측/보상/종료 신호를 named-tensor 딕셔너리로 일괄 처리 |
| SLURM 통합 | train_slurm.py + callbacks/slurm_autoresume_srun.py | 클러스터 큐 시스템에서 자동 재시작(auto-resume) 지원 |
| 물리 자세 라이브러리 | pose_lib(protomotions/components) | SMPL/SMPL-X/MJCF 골격 파싱, 순기구학(FK) 계산 |
| 리타겟팅 엔진 | PyRoki(chungmin99/pyroki) | 사람 동작 → 로봇 관절각으로 최적화 기반 변환(구 버전은 Mink 사용) |
| 모델 로딩 | transformers(>=4.20) | MaskedMimic 등 트랜스포머 기반 정책의 백본 |
| 구성 관리 | 자체 config_builder(Hydra 유사, 순정 dataclass) | 실험 파일이 함수로 config를 조립 — YAML 대신 Python 코드로 설정 |
| ONNX 배포 | onnxruntime | 학습된 정책 + 관측 계산을 통째로 그래프로 굽는 배포 표준 포맷 |
| USD 변환 | usd_convert/ 스크립트 모음 | MJCF(MuJoCo XML) ↔ USD(Universal Scene Description) 상호 변환 |
| 테스트 | pytest | 100개 이상의 테스트 파일 — 회귀 방지용 유닛 테스트가 매우 촘촘함 |
멀티 시뮬레이터 추상화 · MdpComponent 모듈 조립 · obs/reward/control 분리 · 학습 루프 전체 흐름.
ProtoMotions3의 아키텍처를 이해하는 가장 빠른 길은 "이 저장소가 어떤 문제를 풀려고 이렇게 설계됐는가"를 먼저 보는 것이다. 목표는 ① 물리 엔진이 바뀌어도 학습 코드는 그대로, ② 새로운 과제(steering·mimic·masked_mimic 등)를 만들 때 거대한 환경 클래스를 통째로 새로 짜지 않아도 되게, ③ 학습된 정책을 ONNX로 내보낼 때 "이 관측값이 어디서 왔는지"를 자동으로 추적할 수 있게 하는 것이다. 이 세 목표가 각각 Simulator 추상 클래스, MdpComponent 컴포넌트 시스템, FieldPath 컨텍스트 경로라는 세 가지 설계로 구현되어 있다.
protomotions/simulator/base_simulator/simulator.py(1,679줄)는 Simulator(RecordingMixin, ABC)라는 추상 클래스를 정의한다. _physics_step·_apply_simulator_pd_targets·_apply_simulator_torques·_get_simulator_bodies_state·_get_sim_body_ordering 등 @abstractmethod로 표시된 메서드가 20개 이상이며, 각 물리 엔진 구현체(isaacgym/simulator.py·newton/simulator.py 등)는 이 메서드들만 자신의 API에 맞게 구현하면 된다. 그 위의 공개 API(reset()·step()·get_bodies_state())는 전부 부모 클래스에 한 번만 구현되어 있어, 학습 루프·리타겟팅·평가 코드는 어떤 시뮬레이터를 쓰든 완전히 동일하다.
자동차 회사가 엔진 제조사(현대·도요타·테슬라)를 자유롭게 바꿔 끼울 수 있게 하려면, "가속 페달을 밟으면 바퀴가 굴러간다"는 겉모습(운전자 인터페이스)은 그대로 두고, 내부에서 "페달 신호를 받아 실제로 엔진을 돌리는" 부분만 각 제조사가 자기 방식대로 구현하게 한다. Simulator 추상 클래스가 정확히 이 역할이다 — _physics_step() 하나가 "엔진을 실제로 돌리는" 부분이고, IsaacGym·Newton·MuJoCo가 각자 다른 방식으로 이 페달을 밟는다.
실제 소스(protomotions/envs/mdp_component.py)를 열어 보면, MdpComponent 클래스는 세 부분으로 나뉜다: compute_func(순수 텐서 함수 — 부작용 없이 입력을 받아 출력을 계산), dynamic_vars(compute_func의 파라미터 이름을 FieldPath 객체에 매핑 — "이 값은 매 스텝 바뀐다"는 뜻), static_params(가중치·상수처럼 실행 중 안 바뀌는 값). 이 구조가 왜 중요한가는 get_bindings_dict() 메서드를 보면 드러난다 — dynamic_vars의 FieldPath들이 그대로 ONNX 입력 이름 문자열로 변환된다. 즉 "이 관측값이 컨텍스트의 어느 경로에서 왔는지"를 설정 단계에서부터 명시적으로 선언해 두면, 나중에 배포 파이프라인이 자동으로 "로봇이 실제로 어떤 센서 데이터를 넣어줘야 하는지"를 추출할 수 있다.
# mdp_component.py 실제 docstring 예제 (경로 표기 + 정적 파라미터 분리)
observation_components = {
"max_coords_obs": MdpComponent(
compute_func=compute_humanoid_max_coords_observations,
dynamic_vars={
"body_pos": EnvContext.current.rigid_body_pos, # FieldPath
"body_rot": EnvContext.current.rigid_body_rot,
},
static_params={"local_obs": True}, # ONNX 그래프에 상수로 굽힘
),
}
context_views.py의 EnvContext는 클래스 레벨로 접근하면(EnvContext.current.dof_pos) 설정용 FieldPath 객체를 반환하고, 인스턴스 레벨로 접근하면(ctx.current.dof_pos) 실제 텐서 값을 반환하는 이중 접근(dual access) 디스크립터 패턴을 쓴다. 이 트릭 덕분에 실험 config 파일 안에서 IDE 자동완성을 받으면서도, 런타임에는 진짜 텐서가 흘러 들어온다.
README가 자랑하는 "몬리식 env 클래스 없이 모듈로 과제를 조립한다"는 주장은 실제로 steering(방향 조종) 과제의 4개 파일에서 그대로 확인된다.
| 레이어 | 실제 파일 | 역할 |
|---|---|---|
| Control | envs/control/steering_control.py | 과제 상태(목표 방향·속도·바라보는 방향) 관리. 주기적으로 새 목표를 샘플링 |
| Observation | envs/obs/steering.py | 순수 텐서 커널 — 목표를 로봇 로컬 좌표계로 변환해 5차원 특징 벡터로 |
| Reward | envs/rewards/task.py | compute_heading_velocity_rew — 방향 일치(0.7) + 자세 일치(0.3) 보상 혼합 |
| Experiment | examples/experiments/steering/mlp.py | 위 세 조각을 MdpComponent 인스턴스로 엮어 하나의 학습 설정으로 완성 |
실제 steering_control.py(약 220줄)를 열어 보면, SteeringControl 클래스는 reset()(새 목표 방향·속도 샘플링, 10%는 완전 랜덤 방향, 나머지는 이전 방향에서 점진적 변화), step()(목표 갱신 시점 확인), populate_context()(계산된 상태를 EnvContext.steering에 채워 넣기)라는 세 메서드만으로 과제 상태 관리를 전부 해결한다. 이 클래스는 관측·보상 계산 로직을 전혀 모른다 — 오직 "지금 목표가 무엇인지"만 컨텍스트에 올려 두고, 그걸 누가 어떻게 쓰는지는 mlp.py가 MdpComponent로 배선한다. 이게 바로 "몬리식 env 클래스가 필요 없다"는 주장의 실체다.
train_agent.py(1,020줄)의 main()은 체크포인트 유무로 resume/warm_start/fresh 세 모드를 판별한 뒤, build_all_components()로 terrain·scene_lib·motion_lib·simulator를 만들고, BaseEnv와 BaseAgent(PPO/AMP/ASE 등)를 초기화해 agent.fit()을 호출한다. 흥미로운 점은 설정 저장 방식이다 — dataclass 기반 config 객체는 JSON/YAML로 안전하게 직렬화하기 어려운 타입(Union, 중첩 dataclass, torch.Tensor)을 담고 있어서, resolved_configs.pt(pickle, 완전 재현 보장)와 resolved_configs.yaml(사람이 읽기용, best-effort)을 동시에 저장한다. "학습 중 CLI로 오버라이드한 값은 영구적으로 저장되어 재시작 시에도 그대로 적용된다"는 점도 코드 주석에 명시적으로 경고되어 있다 — 실무에서 재현성 버그를 막기 위한 설계다.
protomotions/·examples/·pyroki/·deployment/·usd_convert/ 실제 내용 기반.
envs/base_env/env.py(1,619줄)가 "모든 조각을 지휘하는 오케스트라 지휘자"라면, simulator/base_simulator/simulator.py(1,679줄)는 "어떤 연주자(물리 엔진)를 세워도 같은 악보를 읽게 만드는 규칙집"이다. envs/control·obs·rewards 세 폴더는 각각 "무대 위 배우가 뭘 하는지(control) · 관객이 뭘 보는지(obs) · 배우가 잘했을 때 박수를 얼마나 치는지(reward)"에 해당하며, 이 셋을 절대 한 파일에 섞지 않는 게 이 저장소의 핵심 규율이다. 처음 읽는다면 examples/experiments/steering/mlp.py(가장 간단한 실험 설정) → envs/control/steering_control.py → envs/obs/steering.py → envs/rewards/task.py 순서로 "하나의 과제가 어떻게 4개 파일에 걸쳐 조립되는지" 따라가 보는 게 가장 빠르다.
이 저장소에서 실제로 무엇을 배울 수 있는가 + 각 주제 실습 아이디어.
agents/ppo/agent.py(863줄)와 agents/amp/agent.py(34줄, AMP가 사실 PPO를 상속해 판별기 보상만 추가하는 매우 얇은 확장)를 나란히 읽으면, "순수 과제 보상만으로 학습하면 로봇이 어색하게 움직이는 문제"를 AMP가 어떻게 해결하는지 코드 레벨에서 확인할 수 있다. 판별기(discriminator)가 "이 동작이 진짜 사람 동작 데이터와 비슷한지"를 점수 매겨 추가 보상으로 준다.
실습: examples/experiments/steering/mlp.py의 agent_config()에서 task_reward_w(과제 보상 vs 스타일 보상 비율) 값을 0.9와 0.1로 각각 바꿔 두 설정 파일을 만들어 보고, "왜 이 값이 학습된 동작의 자연스러움에 영향을 주는지" 코드 주석과 논문을 근거로 설명해 보기.
simulator/base_simulator/simulator.py의 추상 메서드 목록과, 그중 하나(예: _physics_step)가 isaacgym/simulator.py·newton/simulator.py에서 각각 어떻게 다르게 구현됐는지 나란히 비교해 보자. "인터페이스와 구현을 분리한다"는 객체지향 원칙이 실전 대규모 코드베이스에서 어떻게 쓰이는지 배우는 좋은 사례다.
실습: 직접 만든 미니 물리 시뮬레이션(예: 단순 진자 운동)에 대해 PendulumSimulator 추상 클래스를 정의하고, "느린 파이썬 버전"과 "numpy 벡터화 버전" 두 구현체를 같은 인터페이스로 만들어 속도 차이를 비교.
robot_configs/g1.py를 열어 보면 STIFFNESS_5020·DAMPING_5020 같은 상수가 ARMATURE(관절 관성)·NATURAL_FREQ(고유 진동수, 10Hz)·DAMPING_RATIO(감쇠비, 2.0)로부터 공식으로 유도되는 걸 볼 수 있다 — 이는 BeyondMimic 프로젝트에서 가져온 실전 검증된 PD 게인 설계법이다. "강성(stiffness)이 너무 높으면 로봇이 뻣뻣해지고, 너무 낮으면 목표를 못 따라간다"는 제어이론의 기초를 실제 로봇 설정값으로 체감할 수 있다.
실습: NATURAL_FREQ를 5Hz·10Hz·20Hz로 바꿔가며 각각의 STIFFNESS·DAMPING 값을 손으로 계산해 보고, 이 값이 실제로 관절 반응 속도에 어떤 영향을 줄지 제어이론 관점에서 설명.
pyroki/batch_retarget_to_g1_from_keypoints.py(1,257줄)는 사람 골격의 3D 키포인트(관절 위치)를 입력받아, 로봇의 관절각(joint angle)이 그 키포인트에 최대한 가깝게 맞도록 최적화 문제를 푼다. 사람은 팔이 길고 로봇은 짧을 수 있으므로, 이건 "완벽한 복사"가 아니라 "최선의 근사"를 찾는 작업이다.
실습: docs의 리타겟팅 튜토리얼을 참고해, AMASS 샘플 동작 하나를 G1과 H1_2 두 로봇에 각각 리타겟팅해 보고 두 결과의 차이(로봇 팔 길이·관절 범위 차이가 최적화 결과에 미치는 영향)를 비교.
envs/mdp_component.py의 MdpComponent와 envs/context_views.py의 FieldPath 이중 접근 디스크립터는, "설정 파일에서는 타입 안전한 자동완성을 받고, 런타임에서는 실제 값이 흐르고, 배포 시점에는 자동으로 ONNX 입력 이름을 추출"하는 3중 목적을 하나의 작은 클래스로 달성한다. 파이썬 디스크립터 프로토콜(__get__)을 실전에서 어떻게 쓰는지 배우는 좋은 예제다.
실습: MdpComponent를 참고하지 않고, "함수 + 파라미터 매핑 딕셔너리"를 저장하는 나만의 미니 클래스를 만들어, to_dict()로 사람이 읽을 수 있는 형태로 직렬화하는 기능까지 구현.
deployment/export_bm_tracker_onnx.py는 체크포인트에서 관측 함수 목록을 자동 감지하고, observation 계산 로직까지 ONNX 그래프에 통째로 구워 unified_pipeline.onnx 하나만 넘겨주면 되게 만든다. deployment/test_tracker_mujoco.py(864줄)로 실제 로봇에 넣기 전에 MuJoCo에서 sim2sim 검증까지 거치는 실무 파이프라인 전체를 볼 수 있다.
실습: ONNX 모델 구조를 onnx.helper나 Netron 같은 도구로 열어, 입력 노드 이름들이 실제로 get_bindings_dict()가 만드는 "current.dof_pos" 같은 경로 문자열과 일치하는지 직접 확인.
agents/common/discrete_latent.py·fsq.py(Finite Scalar Quantization)는 "정책이 매 순간 어떤 스킬(잠재 코드)을 쓸지 스스로 고르는" 생성형 모델의 핵심 부품이다. agents/supervised/masked_mimic_model.py가 이를 지도학습(Supervised)으로 프리트레이닝하는 과정을 보여준다. GPC(Generalist Policy with Composable skills)와 PEFT(어댑터 기반 파인튜닝) 조합을 통해 "재사용 가능한 이산 잠재 프라이어"라는 최근 생성 모델 연구 트렌드를 실전 코드로 접할 수 있다.
실습: examples/experiments/gpc/ 아래 4개 실험 파일(prior.py·sft_target_prior_peft.py 등)을 읽는 순서를 스스로 정해 보고, "프라이어를 먼저 학습한 뒤 PEFT 어댑터를 붙인다"는 2단계 학습 전략을 도식으로 그려 설명.
GPU/CUDA 요구사항 · 시뮬레이터별 규모 · 현실적인 개인 대안.
| 항목 | 공식 언급 값 |
|---|---|
| GPU (대표 데모) | NVIDIA A100 4장 — AMASS 전체(40+시간) 학습에 약 12시간 |
| GPU (대규모 확장) | NVIDIA A100 24장 — BONES 데이터셋 13,000개 모션/GPU 규모 |
| Python (IsaacGym) | 3.8 — setup.py의 python_requires=">=3.8" 및 Dockerfile.isaacgym 기준 |
| Python (Newton) | 3.10 — Dockerfile.newton 기준, uv 가상환경 사용 |
| CUDA (IsaacGym) | 12.1.0 (nvidia/cuda:12.1.0-devel-ubuntu20.04 베이스 이미지) |
| CUDA (Newton) | 12.4.0 (nvidia/cuda:12.4.0-devel-ubuntu22.04 베이스 이미지) |
| torch | >=2.2(공통) ~ 2.5.0(Genesis 전용 고정) |
| MuJoCo 전용 제약 | CPU 전용, num_envs=1 — GPU 없이 빠른 디버깅/재현 용도 |
| 디스플레이 | 헤드리스 렌더링용 Xvfb 가상 디스플레이(Dockerfile.newton에 내장) |
| 라이선스 | Apache-2.0 — 상업적 사용 가능(단, 번들 자산은 legal/의 서드파티 고지 확인 필요) |
README 대표 데모(AMASS 전체 학습, A100 4장·12시간)조차 가정용 GPU 1~2장으로는 같은 시간 안에 재현하기 어렵다. IsaacGym·IsaacLab·Newton·Genesis 4종 모두 GPU 필수이며, 대량 병렬 환경(num_envs 수천~수만)을 굴려야 학습 속도의 이점을 체감할 수 있다. "많은 병렬 환경 = 빠른 데이터 수집"이라는 강화학습의 근본 트레이드오프가 이 프로젝트에서는 그대로 GPU 메모리 요구량으로 직결된다.
① MuJoCo(CPU 전용) 활용 — requirements_mujoco.txt 안내대로 CPU 전용 torch를 설치하면 GPU 없이도 inference_agent.py --simulator mujoco --num-envs 1로 이미 학습된 체크포인트를 재생·시각화할 수 있다(학습은 불가, 추론/디버깅만). ② 소규모 num_envs로 학습 흉내 — GPU 1장(예: RTX 4090)에서도 num_envs를 수백 개로 낮추면 학습 자체는 돌아간다. 속도는 느리지만 "코드가 실제로 어떻게 도는지" 확인하는 목적은 달성된다. ③ 사전학습 모델 활용 — 저장소의 data/pretrained_models·문서의 사전학습 체크포인트를 내려받아, 학습 없이 추론 파이프라인(inference_agent.py→ONNX export→MuJoCo sim2sim)만 먼저 실습.
num_envs=4096이면 "동시에 4096개의 가상 로봇이 각자 다른 상황에서 연습 중"이라는 뜻이다. 이 숫자가 클수록 학습은 빨라지지만 GPU 메모리를 그만큼 더 요구한다.난이도별 5단계 — GPU 없이 코드를 읽는 것부터, GPU 보유자를 위한 전체 학습 파이프라인까지.
GPU도, 설치도 필요 없는 첫 실습이다. examples/experiments/steering/mlp.py 파일 하나만 읽고, "이 실험이 실행될 때 어떤 순서로 어떤 파일이 호출되는지"를 손으로 화살표 도식을 그려 본다. terrain_config()·env_config()·agent_config() 세 함수가 무엇을 반환하고 train_agent.py의 어느 부분이 그것을 소비하는지 추적하는 것이 목표다.
# 코드를 실행하지 않고 읽기만 해도 되는 실습 — 저장소 클론만
git clone https://github.com/NVlabs/ProtoMotions.git
cd ProtoMotions
cat examples/experiments/steering/mlp.py
# env_config() 함수가 반환하는 EnvConfig의 필드들을 나열해 보기
grep -n "def \|_control\|_obs\|_reward" examples/experiments/steering/mlp.py
protomotions/envs/mdp_component.py를 참고하되 그대로 베끼지 않고, "함수 + 파라미터 매핑"을 저장하는 나만의 MiniComponent 클래스를 파이썬으로 새로 작성한다. compute() 메서드가 딕셔너리에서 실제 값을 찾아와 함수에 넣어 호출하도록 구현하고, 원본의 to_dict() 직렬화 메서드까지 흉내 내 본다.
// 직접 구현해 볼 시그니처 (GPU/torch 불필요, 순수 파이썬으로 연습 가능)
class MiniComponent:
def __init__(self, compute_func, dynamic_vars: dict, static_params: dict = None):
self.compute_func = compute_func
self.dynamic_vars = dynamic_vars # {param_name: context_key}
self.static_params = static_params or {}
def compute(self, ctx: dict):
# TODO: dynamic_vars의 각 경로를 ctx에서 찾아 실제 값으로 치환한 뒤
# compute_func(**resolved, **static_params) 호출
...
# 테스트 예시
def add(a, b, scale=1.0):
return (a + b) * scale
comp = MiniComponent(add, {"a": "x", "b": "y"}, {"scale": 2.0})
assert comp.compute({"x": 3, "y": 4}) == 14
GPU가 없어도 시도할 수 있는 첫 "진짜 실행" 실습이다. requirements_mujoco.txt 안내를 그대로 따라 CPU 전용 conda 환경을 만들고, 공식 문서(Quick Start)가 제공하는 사전학습 체크포인트를 내려받아 재생해 본다. 물리 시뮬레이션이 실제로 로봇의 관절을 움직이는 것을 화면으로 확인하는 것이 이 실습의 핵심이다.
# MuJoCo CPU 백엔드 설치 (requirements_mujoco.txt 안내 그대로)
conda create -n protomotions_mujoco python=3.10
conda activate protomotions_mujoco
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
pip install -e .
pip install -r requirements_mujoco.txt
# 사전학습 체크포인트로 추론 (num_envs=1 필수)
python protomotions/inference_agent.py \
--checkpoint results/pretrained/last.ckpt \
--simulator mujoco \
--num-envs 1
GPU 1장(중급 이상)이 있다면, examples/experiments/steering/mlp.py의 compute_heading_velocity_rew 호출부에서 방향 일치 가중치(0.7)와 자세 일치 가중치(0.3)를 각각 0.5/0.5, 0.9/0.1로 바꿔가며 세 번 학습시켜 본다. num_envs는 작게(예: 512) 설정해 학습 시간을 단축하고, TensorBoard로 세 실험의 보상 곡선을 겹쳐 비교한다.
# 예시 학습 명령 (GPU 1장, 축소된 num_envs)
python protomotions/train_agent.py \
--robot-name g1 \
--simulator isaacgym \
--experiment-path examples/experiments/steering/mlp.py \
--experiment-name steering_test_v1 \
--motion-file data/motions/amass_train.pt \
--num-envs 512 \
--batch-size 4096
README의 "Add Your Own Robot" 가이드(MJCF 자산 추가 → robot_configs 설정 채우기 → factory.py에 등록)를 그대로 따라, 간단한 로봇(예: 2족 보행 장난감 수준의 MJCF)을 하나 등록해 본다. 이후 --simulator isaacgym으로 학습한 정책을 --simulator newton·--simulator mujoco로 각각 sim2sim 테스트하며, 3개 물리 엔진에서 행동이 얼마나 일관되는지 직접 관찰하는 것이 최종 목표다.
강화학습 기초 → 물리 시뮬레이션 → 휴머노이드 제어 → sim2real — 8주 계획.
| 주차 | 주제 | 할 일 |
|---|---|---|
| 1주차 | 강화학습 기초 & PPO | 정책·보상·가치함수 개념. OpenAI Spinning Up의 PPO 자료 정독 + agents/ppo/agent.py 코드와 대조하며 읽기 |
| 2주차 | 물리 시뮬레이터 개념 | 강체 역학·접촉(contact)·PD 제어 기초. simulator/base_simulator/simulator.py의 추상 메서드 20여 개를 표로 정리(과제 1 확장) |
| 3주차 | 모션 모방 학습(AMP/ASE) | Adversarial Motion Priors 원 논문 요약 + agents/amp/agent.py·component.py 정독. 판별기가 왜 "자연스러움"을 학습시키는지 이해 |
| 4주차 | MdpComponent 아키텍처 | 파이썬 디스크립터 프로토콜(__get__/__set_name__) 공식 문서 + context_paths.py·context_views.py 재독. 과제 2(미니 구현) 완주 |
| 5주차 | 휴머노이드 제어(PD 게인) | 제어이론의 2차 시스템(고유진동수·감쇠비) 기초 + robot_configs/g1.py의 게인 계산식 재해석 |
| 6주차 | 모션 리타겟팅 | 역기구학(IK) 최적화 기초 + PyRoki 공식 문서. pyroki/batch_retarget_to_g1_from_keypoints.py 정독, 과제 3 완주 |
| 7주차 | 생성형 정책(MaskedMimic/GPC) | 이산 잠재변수(VQ-VAE류) 개념 + FSQ(Finite Scalar Quantization) 논문 요약. agents/common/fsq.py 재독 |
| 8주차 | Sim2Real 배포 | ONNX 그래프 구조, 배포 시 관측 일치의 중요성. deployment/export_bm_tracker_onnx.py+test_tracker_mujoco.py 완독, 과제 5(GPU 있으면) 도전 |
이 저장소는 강화학습 이론 · 물리 시뮬레이션 시스템 · 로보틱스 제어라는 세 개의 서로 다른 전문 분야가 겹쳐 있다. 한 번에 다 이해하려 하면 좌절하기 쉽다. 먼저 "가장 간단한 과제 하나"(steering)를 처음부터 끝까지 따라가 보고 → 그 다음 시뮬레이터 추상화 계층을 이해하고 → 마지막에 로보틱스 응용(리타겟팅·sim2real)으로 확장하는 순서를 추천한다. 강화학습 기초가 약하다면 1주차를 건너뛰지 말 것 — AMP/GRPO류 알고리즘 코드를 읽어도 "왜 이렇게 계산하는지"가 안 잡히면 암기가 되어버린다.
이 문서와 저장소에 나온 주요 용어 정리.
agents/ppo/가 이 알고리즘의 기본 구현체이며, 다른 에이전트(AMP·ASE 등)들이 이를 상속해 확장한다.agents/supervised/masked_mimic_model.py가 이를 구현한다.robot_configs/g1.py의 강성(stiffness)·감쇠(damping) 값이 이 제어기의 핵심 파라미터다.EnvContext 클래스에 선언된, "이 값이 컨텍스트의 어느 경로에 있는지"를 나타내는 디스크립터 객체. 클래스로 접근하면 경로 정보를, 인스턴스로 접근하면 실제 텐서 값을 반환하는 이중 역할을 한다..xml 파일을 작성하는 것이다.공식 저장소 · 공식 문서 · 관련 프로젝트 · 데이터셋.
| 구분 | 링크 |
|---|---|
| GitHub 저장소 | github.com/NVlabs/ProtoMotions |
| 공식 문서 | protomotions.github.io |
| Quick Start | protomotions.github.io/getting_started/quickstart.html |
| 설치 가이드 | protomotions.github.io/getting_started/installation.html |
| G1 실기 배포 튜토리얼 | protomotions.github.io/tutorials/workflows/g1_deployment.html |
| GPC & PEFT 가이드 | protomotions.github.io/user_guide/gpc.html |
| API 레퍼런스 | protomotions.github.io/api_reference |
| 자매 프로젝트 MimicKit | github.com/xbpeng/MimicKit — 경량 모션 모방 학습 프레임워크 |
| PyRoki (리타겟팅) | github.com/chungmin99/pyroki |
| Newton 물리 엔진 | github.com/newton-physics/newton |
| AMASS 데이터셋 | amass.is.tue.mpg.de |
| BONES-SEED 데이터셋 | huggingface.co/datasets/bones-studio/seed |
| Kimodo (텍스트-투-모션) | research.nvidia.com/labs/sil/projects/kimodo |
| MaskedMimic 연구 페이지 | research.nvidia.com/labs/par/maskedmimic |
| RoboJuDo (실기 배포 프레임워크) | github.com/HansZ8/RoboJuDo |
| IsaacLab (비교 대상) | github.com/isaac-sim/IsaacLab |
| DeepWiki 비공식 문서(AI 생성) | deepwiki.com/NVlabs/ProtoMotions |
| 라이선스 | Apache-2.0 (상업적 이용 가능, 서드파티 자산 고지는 legal/ 참고) |