| # Training Code Structure |
|
|
| This page describes the Python training codebase under `gear_sonic/`, covering directory layout, the training pipeline, configuration system, key modules, and evaluation scripts. |
|
|
| --- |
|
|
| ## Directory Layout |
|
|
| ``` |
| gear_sonic/ |
| ├── train_agent_trl.py # Main training entry point |
| ├── eval_agent_trl.py # Single-checkpoint evaluation |
| ├── eval_exp.py # Checkpoint monitor (continuous eval) |
| ├── config/ # Hydra configuration hierarchy |
| │ ├── base.yaml # Global defaults (seed, num_envs, paths) |
| │ ├── base_eval.yaml # Eval-specific global defaults |
| │ ├── eval_exp.yaml # Checkpoint monitor config |
| │ ├── base/ # Hydra plumbing (output dirs, resolvers) |
| │ ├── algo/ # PPO hyperparameters |
| │ ├── actor_critic/ # Actor-critic architecture configs |
| │ │ ├── encoders/ # Per-encoder MLP configs (g1, smpl, teleop) |
| │ │ ├── decoders/ # Decoder MLP configs (g1_kin, g1_dyn) |
| │ │ ├── critics/ # Critic backbone configs |
| │ │ ├── quantizers/ # FSQ quantizer config |
| │ │ └── universal_token/ # Assembled encoder+decoder+quantizer presets |
| │ ├── aux_losses/ # Auxiliary loss definitions |
| │ ├── callbacks/ # Training callback configs |
| │ ├── exp/ # Experiment presets (compose all pieces) |
| │ ├── manager_env/ # Environment MDP component configs |
| │ ├── opt/ # Logging options (wandb) |
| │ └── trainer/ # Trainer class selection |
| ├── envs/ # IsaacLab environment wrappers |
| │ ├── manager_env/ |
| │ │ ├── modular_tracking_env_cfg.py # Scene, sensors, robot articulation |
| │ │ ├── robots/ # Per-robot configs (g1.py, h2.py) |
| │ │ └── mdp/ # MDP components (see below) |
| │ ├── wrapper/ |
| │ │ └── manager_env_wrapper.py # RL-facing env wrapper |
| │ └── env_utils/ # Joint ordering utilities |
| ├── trl/ # Training modules (PPO, actor-critic, losses) |
| │ ├── trainer/ |
| │ │ ├── ppo_trainer.py # Base PPO trainer |
| │ │ └── ppo_trainer_aux_loss.py # PPO + auxiliary losses (SONIC) |
| │ ├── modules/ |
| │ │ ├── actor_critic_modules.py # Actor, Critic classes |
| │ │ ├── universal_token_modules.py # UniversalTokenModule (SONIC ATM) |
| │ │ ├── base_module.py # Shared MLP building blocks |
| │ │ └── data_utils.py # Batch/data helpers |
| │ ├── losses/ |
| │ │ └── token_losses.py # Reconstruction & latent auxiliary losses |
| │ ├── callbacks/ # Runtime callbacks |
| │ │ ├── im_eval_callback.py # Imitation evaluation metrics |
| │ │ ├── im_resample_callback.py # Adaptive motion resampling |
| │ │ ├── model_save_callback.py # Checkpoint saving |
| │ │ ├── wandb_callback.py # W&B logging |
| │ │ └── read_eval_callback.py # Read eval results from disk |
| │ └── utils/ # Math, rotation, scheduling utilities |
| ├── utils/ # Shared utilities |
| │ ├── motion_lib/ # Motion library loading (PKL format) |
| │ ├── mujoco_sim/ # MuJoCo sim-to-sim bridge |
| │ └── teleop/ # VR teleoperation helpers |
| ├── data/ # Robot models, URDF/USD assets |
| ├── data_process/ # Motion data conversion scripts |
| └── scripts/ # MuJoCo sim loop, misc tools |
| ``` |
|
|
| --- |
|
|
| ## Training Pipeline |
|
|
| Running `python gear_sonic/train_agent_trl.py +exp=manager/universal_token/all_modes/sonic_release` executes the following steps: |
|
|
| ### 1. Configuration Loading |
|
|
| The entry point uses `@hydra.main(config_path="config", config_name="base")`. The `+exp=...` argument selects an experiment preset that composes all sub-configs: |
|
|
| ``` |
| base.yaml # Global defaults |
| └── +exp=manager/universal_token/all_modes/sonic_release |
| ├── /algo: ppo_im_phc # PPO hyperparameters |
| ├── /actor_critic: universal_token/all_mlp_v1 |
| │ ├── encoders/g1_mf_mlp, smpl_mlp, teleop_mlp |
| │ ├── decoders/g1_kin_mf_mlp, g1_dyn_mlp |
| │ ├── quantizers/fsq |
| │ └── critics/mlp |
| ├── /manager_env: base_env # Environment config |
| │ ├── observations/{tokenizer, policy, critic} |
| │ ├── rewards/tracking/base_5point_local_feet_acc |
| │ ├── terminations/tracking/base_adaptive_strict_ori_foot_xyz |
| │ └── events/tracking/level0_4 |
| ├── /aux_losses: universal_token/g1_recon_and_all_latent |
| ├── /trainer: trl_ppo_aux |
| └── /callbacks: model_save, wandb, read_eval, im_resample |
| ``` |
|
|
| ### 2. Simulator and Accelerator Init |
|
|
| After config resolution, the script: |
| 1. Parses TRL `PPOConfig` / `ScriptArguments` / `ModelConfig` from the config dict. |
| 2. Creates a HuggingFace `Accelerator` for multi-GPU support (DDP). |
| 3. Launches the IsaacLab `AppLauncher` to start the Isaac Sim runtime. |
| 4. Saves `config.yaml` and `meta.yaml` to the experiment directory. |
|
|
| ### 3. Environment Creation |
|
|
| `create_manager_env()` instantiates the IsaacLab `ManagerBasedRLEnv` from the composed environment config, then wraps it with `ManagerEnvWrapper`: |
|
|
| ``` |
| ManagerBasedRLEnv (IsaacLab) |
| └── ManagerEnvWrapper |
| ├── Observation spaces (policy, critic, tokenizer groups) |
| ├── Motion command manager (motion_lib) |
| ├── Action transform module (optional, for pretrained ATM) |
| └── Keyboard / visualization hooks |
| ``` |
|
|
| ### 4. Policy and Value Model Creation |
|
|
| The actor and critic are instantiated from the algo config. For SONIC training, the actor backbone is `UniversalTokenModule`: |
|
|
| ```python |
| # Simplified from train_agent_trl.py |
| policy = custom_instantiate(config.algo.config.actor, env_config=env.config, ...) |
| value_model = custom_instantiate(config.algo.config.critic, env_config=env.config, ...) |
| ``` |
|
|
| The `Actor` wraps `UniversalTokenModule` as its backbone and adds a diagonal Gaussian distribution for exploration. The `Critic` wraps a separate MLP backbone. |
|
|
| ### 5. PPO Training Loop |
|
|
| The `TRLAuxLossPPOTrainer.train()` method runs the main loop: |
|
|
| ``` |
| for iteration in range(num_learning_iterations): |
| # 1. Rollout: collect num_steps_per_env transitions |
| for step in range(num_steps_per_env): |
| actions = policy.rollout(obs_dict) |
| obs_dict, rewards, dones, infos = env.step(actions) |
| store(obs, actions, rewards, values, log_probs) |
| |
| # 2. GAE: compute advantages and returns |
| advantages = generalized_advantage_estimation(rewards, values, dones) |
| |
| # 3. PPO update: num_ppo_epochs over mini-batches |
| for epoch in range(num_ppo_epochs): |
| for mini_batch in shuffle_and_split(rollout_data): |
| policy_loss = clipped_surrogate_objective(...) |
| value_loss = clipped_value_loss(...) |
| aux_loss = sum(coef_i * aux_loss_i) # encoder reconstruction, etc. |
| total_loss = policy_loss + value_loss_coef * value_loss |
| + aux_loss_scale * aux_loss |
| optimizer.step(total_loss) |
| |
| # 4. Post-update: sync running stats, adaptive sampling, callbacks |
| update_scheduled_params(...) # learning rate, domain randomization |
| callbacks.on_step_end(...) # checkpointing, evaluation, logging |
| ``` |
|
|
| --- |
|
|
| ## Configuration System |
|
|
| The configuration system uses [Hydra](https://hydra.cc/) with config groups and composition. |
|
|
| ### Hierarchy |
|
|
| | Level | Path | Purpose | |
| |---|---|---| |
| | **Global** | `config/base.yaml` | Seed, num_envs, paths, wandb toggle | |
| | **Algorithm** | `config/algo/ppo_im_phc.yaml` | PPO hyperparameters, learning rates, epochs | |
| | **Actor-Critic** | `config/actor_critic/` | Network architecture (encoders, decoders, critic) | |
| | **Environment** | `config/manager_env/` | Observations, rewards, terminations, events | |
| | **Auxiliary Losses** | `config/aux_losses/` | Reconstruction and latent alignment losses | |
| | **Trainer** | `config/trainer/` | Trainer class selection (PPO or PPO+AuxLoss) | |
| | **Callbacks** | `config/callbacks/` | Checkpointing, evaluation, W&B logging | |
| | **Experiment** | `config/exp/` | Preset that composes all the above | |
|
|
| ### Experiment Presets |
|
|
| Experiment configs live under `config/exp/` and use the `@package _global_` directive to set values at the root level. They compose all component configs via `defaults`: |
|
|
| ```yaml |
| # config/exp/manager/universal_token/all_modes/sonic_release.yaml |
| defaults: |
| - /algo: ppo_im_phc |
| - /manager_env: base_env |
| - override /actor_critic: universal_token/all_mlp_v1 |
| - override /manager_env/observations/tokenizer: unitoken_all_noz |
| - override /manager_env/observations/policy: local_dir_hist |
| - override /manager_env/rewards: tracking/base_5point_local_feet_acc |
| - override /manager_env/terminations: tracking/base_adaptive_strict_ori_foot_xyz |
| - override /manager_env/events: tracking/level0_4 |
| # ... |
| ``` |
|
|
| ### Key Config Parameters |
|
|
| | Parameter | Default | Description | |
| |---|---|---| |
| | `num_envs` | 4096 | Number of parallel simulation environments | |
| | `algo.config.num_learning_iterations` | 100000 | Total training iterations | |
| | `algo.config.num_steps_per_env` | 32 | Rollout horizon per iteration | |
| | `algo.config.num_learning_epochs` | 5 | PPO epochs per iteration | |
| | `algo.config.num_mini_batches` | 4 | Mini-batches per PPO epoch | |
| | `algo.config.actor_learning_rate` | 2e-5 | Actor learning rate | |
| | `algo.config.critic_learning_rate` | 1e-3 | Critic learning rate | |
| | `algo.config.clip_param` | 0.2 | PPO clipping parameter | |
| | `algo.config.init_noise_std` | 0.05 | Initial exploration noise std | |
| | `algo.config.save_interval` | 500 | Checkpoint save frequency (iterations) | |
|
|
| --- |
|
|
| ## Universal Token Module |
|
|
| The `UniversalTokenModule` implements SONIC's action transform module (ATM) -- the core architecture that maps diverse motion inputs into a shared token space. |
|
|
| ### Architecture |
|
|
| ``` |
| ┌─────────────┐ |
| G1 obs ───► │ G1 Encoder │──┐ |
| └─────────────┘ │ |
| ┌─────────────┐ │ ┌─────────┐ ┌─────────────┐ |
| Teleop obs───► │Teleop Encdr │──┼──► │ FSQ │──► │ G1 Dynamic │──► joint actions |
| └─────────────┘ │ │Quantizer│ │ Decoder │ |
| ┌─────────────┐ │ └─────────┘ └─────────────┘ |
| SMPL obs ───► │ SMPL Encoder│──┘ │ |
| └─────────────┘ │ ┌─────────────┐ |
| └───────► │G1 Kinematic │──► (aux loss only) |
| │ Decoder │ |
| └─────────────┘ |
| ``` |
|
|
| **Encoders** map different observation modalities into a shared latent space. Each encoder is an MLP that takes modality-specific tokenizer observations and outputs a fixed-size latent vector. During training, one encoder is sampled per environment according to `encoder_sample_probs`. |
|
|
| **FSQ Quantizer** discretizes the continuous latent into a finite set of tokens using Finite Scalar Quantization. Each latent dimension is independently quantized to one of `fsq_level_list` discrete levels. This produces a compact, discrete token representation. |
|
|
| **Decoders** reconstruct outputs from the quantized tokens plus proprioception: |
| - **G1 Dynamic Decoder** (`g1_dyn`): Produces joint-space actions fed to the actuators. This is the only decoder used at deployment time. |
| - **G1 Kinematic Decoder** (`g1_kin`): Reconstructs future motion frames from tokens. Used only during training to compute reconstruction auxiliary losses. |
|
|
| ### Latent Residual Mode |
|
|
| For downstream tasks (e.g., object manipulation), an external policy can inject corrections into the token space without retraining the base ATM: |
|
|
| | Mode | Behavior | |
| |---|---| |
| | `post_quantization` (default) | Residual added after FSQ quantization | |
| | `pre_quantization` | Residual added before FSQ; the sum gets quantized | |
| | `pre_quantization_replace` | Latent is replaced entirely by the residual | |
|
|
| ### Encoder Sampling |
|
|
| During training, each environment is randomly assigned an encoder per episode according to `encoder_sample_probs`. The `encoder_index` observation tells the module which encoder produced the current token. At deployment, only one encoder is active (selected by the observation configuration). |
|
|
| --- |
|
|
| ## Environment Structure |
|
|
| The training environment is built on IsaacLab's `ManagerBasedRLEnv` and uses a modular MDP design where each component is configured independently via YAML. |
|
|
| ### MDP Components |
|
|
| All MDP components live in `gear_sonic/envs/manager_env/mdp/`: |
|
|
| | Module | Config path | Description | |
| |---|---|---| |
| | `observations.py` | `config/manager_env/observations/` | Observation terms for policy, critic, and tokenizer groups | |
| | `actions.py` | `config/manager_env/actions/` | Joint position action space | |
| | `rewards.py` | `config/manager_env/rewards/` | Reward terms (tracking, regularization) | |
| | `terminations.py` | `config/manager_env/terminations/` | Episode termination conditions | |
| | `events.py` | `config/manager_env/events/` | Domain randomization events | |
| | `commands.py` | `config/manager_env/commands/` | Motion command generation (motion library) | |
| | `curriculum.py` | `config/manager_env/curriculum/` | Curriculum schedules | |
| | `terrain.py` | (inline) | Terrain generation | |
| | `recorders.py` | `config/manager_env/recorders/` | Video recording | |
|
|
| ### Observation Groups |
|
|
| Observations are split into groups, each with its own config file: |
|
|
| | Group | Purpose | Example terms | |
| |---|---|---| |
| | **policy** | Direct input to the policy MLP | joint_pos, joint_vel, base_ang_vel, gravity_dir, last_actions | |
| | **critic** | Privileged observations for the value function | All policy obs + base_lin_vel, body_pos, body_ori | |
| | **tokenizer** | Input to the UniversalTokenModule encoders | Multi-future joint commands, SMPL joints, VR targets, anchor orientations | |
|
|
| ### Reward Terms |
|
|
| Reward configs compose individual terms from `config/manager_env/rewards/terms/`. Key tracking rewards: |
|
|
| | Term | Description | |
| |---|---| |
| | `tracking_relative_body_pos` | Track reference body positions (5-point: root, wrists, feet) | |
| | `tracking_relative_body_ori` | Track reference body orientations | |
| | `tracking_anchor_pos` | Track root anchor position | |
| | `tracking_anchor_ori` | Track root anchor orientation | |
| | `tracking_body_linvel` | Track reference body linear velocities | |
| | `tracking_body_angvel` | Track reference body angular velocities | |
| | `action_rate_l2` | Penalize action jerk | |
| | `feet_acc` | Penalize foot acceleration (smoothness) | |
|
|
| ### ManagerEnvWrapper |
|
|
| `ManagerEnvWrapper` bridges the IsaacLab environment with the RL training loop. It handles: |
| - Flattening observation dicts for the policy |
| - Applying the optional pretrained action transform module |
| - Motion replay mode |
| - Debug visualization and keyboard controls |
|
|
| --- |
|
|
| ## Evaluation Scripts |
|
|
| ### eval_agent_trl.py -- Single Checkpoint |
|
|
| Loads a single checkpoint and runs evaluation in Isaac Sim. Automatically reads the training `config.yaml` from the checkpoint directory to reconstruct the full configuration. |
|
|
| ```bash |
| # Interactive visualization |
| python gear_sonic/eval_agent_trl.py +checkpoint=path/to/model.pt +headless=False ++num_envs=1 |
| |
| # Headless with video rendering |
| python gear_sonic/eval_agent_trl.py +checkpoint=path/to/model.pt +headless=True \ |
| ++num_envs=16 +run_once=True \ |
| ++manager_env.config.save_rendering_dir=path/to/output \ |
| ++manager_env.config.render_results=True \ |
| +manager_env/recorders=render |
| ``` |
|
|
| Key features: |
| - Merges training config with eval overrides (`eval_overrides` in config) |
| - Removes train-only events and terminations automatically |
| - Supports `+run_once=True` to exit after all environments complete one episode |
| - Handles `+metrics_file` to render worst-performing motions from a prior eval |
|
|
| ### eval_exp.py -- Checkpoint Monitor |
| |
| `CheckpointEvaluator` continuously monitors an experiment directory for new checkpoints and evaluates them sequentially. It runs as a companion process alongside training. |
| |
| ```bash |
| python gear_sonic/eval_exp.py ++experiment_dir=path/to/experiment |
| ``` |
| |
| For each new checkpoint, it: |
| 1. Runs metrics evaluation (launches `eval_agent_trl.py` via subprocess) |
| 2. Runs video rendering for the hardest motions |
| 3. Logs results and videos to W&B (resuming the training run) |
| 4. Marks each checkpoint as evaluated to avoid redundant work |
| |
| Configuration (`config/eval_exp.yaml`): |
| |
| | Parameter | Description | |
| |---|---| |
| | `experiment_dir` | Path to the training experiment directory | |
| | `scan_interval` | Seconds between checkpoint scans (default: 60) | |
| | `num_eval_envs` | Number of environments for metric evaluation | |
| | `num_render_videos` | Number of videos to render per checkpoint | |
| | `eval_frequency` | Only evaluate every N-th checkpoint (default: all) | |
| | `single_pass` | Evaluate pending checkpoints once and exit | |
| |
| --- |
| |
| ## Key Classes Reference |
| |
| | Class | Module | Description | |
| |---|---|---| |
| | `Actor` | `trl/modules/actor_critic_modules.py` | Policy network: backbone + diagonal Gaussian. Maintains observation buffer for temporal models. | |
| | `Critic` | `trl/modules/actor_critic_modules.py` | Value function network: backbone + scalar output. Supports running mean/std normalization. | |
| | `UniversalTokenModule` | `trl/modules/universal_token_modules.py` | SONIC ATM: multi-encoder, FSQ quantizer, multi-decoder. Computes auxiliary reconstruction losses. | |
| | `TRLPPOTrainer` | `trl/trainer/ppo_trainer.py` | Base PPO trainer adapted from HuggingFace TRL. Handles rollout collection, GAE, and gradient updates. | |
| | `TRLAuxLossPPOTrainer` | `trl/trainer/ppo_trainer_aux_loss.py` | Extends `TRLPPOTrainer` with auxiliary loss support (reconstruction, latent alignment). | |
| | `PolicyAndValueWrapper` | `trl/trainer/ppo_trainer.py` | Wraps policy + value model into a single `nn.Module` for DDP-safe forward passes. | |
| | `ManagerEnvWrapper` | `envs/wrapper/manager_env_wrapper.py` | Bridges IsaacLab `ManagerBasedRLEnv` with the training loop. Handles obs flattening, action transforms, replay. | |
| | `CheckpointEvaluator` | `eval_exp.py` | Monitors experiment directory, evaluates new checkpoints, logs to W&B. | |
| |