Fine-tuned Cosmos3-Nano world model for Unitree G1 humanoid robot manipulation. Given an initial observation image and a task description, the model jointly generates: (1) a video of the robot executing the task, and (2) a 26-dimensional joint-angle trajectory at 15 Hz.
Training: Policy SFT on the G1 BrainCo apple-picking dataset — 10,000 iterations on 7× A100 80 GB GPUs using FSDP. Base model:nvidia/Cosmos3-Nano (8B params, Qwen3-VL-8B backbone)
What This Model Does
Input: image (initial robot observation) + text prompt (task description)
Output: video frames (480p, 15 fps) + 26D joint-angle trajectory at 15 Hz
This is a policy model: give it a photo of what the robot currently sees and a description of what it should do — it predicts both how the robot moves (video) and what joint angles it should command (actions).
[your_image.jpg] + "Pick up the apple from the table"
│
▼
Cosmos3-Nano Policy SFT
│
├── rollout.mp4 ← robot video (what it will see)
└── actions_raw.npy ← joint angles [T × 26] in radians @ 15 Hz
Actions are at 15 Hz and can be sent directly to the G1 robot controller. The model runs autoregressively in 16-frame chunks — the last frame of each chunk feeds into the next, so you can generate arbitrarily long rollouts.
This is a policy model: it predicts both how the robot moves (video) and what joint angles it should command (actions). Actions are at 15 Hz, matching the video frame rate.
Supported tasks (pre-trained):
pickapple — Pick up an apple from the table
grasporeo — Grasp an Oreo cookie from the table
grasprubikscube — Grasp a Rubik's cube from the table
pickcharger — Pick up a phone charger from the table
pickdoll — Pick up a doll from the table
pickdrink — Pick up a drink bottle from the table
picktissues — Pick up a tissue box from the table
picktoothpaste — Pick up a toothpaste tube from the table
Checkpoint Format
This model uses PyTorch DCP (Distributed Checkpoint) format — the same format used during FSDP training. The model/ directory contains 7 .distcp shards.
The fine-tuned checkpoint only stores the 4 trained adapter modules:
moe_gen — MoE generation router
time_embedder — Timestep embedder
vae2llm — VAE latent → LLM token bridge
llm2vae — LLM output → VAE latent bridge
The visual encoder and VLM backbone (Qwen3-VL-8B) are frozen during training and must be loaded from the base nvidia/Cosmos3-Nano checkpoint first. See Two-Stage Loading below.
Installation
Requires the Cosmos3 framework (NVIDIA internal):
bash
1# Clone and install2cd cosmos/packages/cosmos3
3uv sync4source .venv/bin/activate
Policy Inference (Image + Prompt → Video + Actions)
The core capability of this model: give it any image of what the robot sees + a text description of the task, and it outputs a robot video and the joint-angle commands to execute it.
Quick Start — Built-in Tasks
bash
1# Run chunked autoregressive rollout for a built-in task2torchrun --nproc_per_node=1 examples/policy_rollout.py \3 --checkpoint-dir /path/to/iter_000010000 \4 --base-checkpoint-dir examples/checkpoints/Cosmos3-Nano \5 --output-dir /tmp/rollout_output \6 --n-chunks 5\7 --tasks pickapple
The base Cosmos3-Nano supports V2V transfer: style-transfer from a reference video (e.g. human arm picking apple → G1 robot).
Two-Stage Loading for V2V with Fine-Tuned Weights
python
1from cosmos_framework.inference.args import(2 OmniSampleOverrides, OmniSetupOverrides,3 EdgeTransferOverrides, PresetEdgeThreshold,4 BlurTransferOverrides, PresetBlurStrength,5)6from cosmos_framework.inference.inference import OmniInference, get_sample_data
78BASE_CKPT ="examples/checkpoints/Cosmos3-Nano"9FINETUNED_CKPT ="/path/to/iter_000010000"10CONFIG_YAML ="cosmos_framework/inference/configs/model/Cosmos3-Nano.yaml"1112# Stage 1: load base model (gets visual encoder + all base weights)13setup = OmniSetupOverrides(14 checkpoint_path=BASE_CKPT,15 config_file=CONFIG_YAML,16 output_dir="/tmp/v2v_out",17 guardrails=False,18).build_setup()19pipe = OmniInference.create(setup)2021# Stage 2: overlay fine-tuned weights22import torch.distributed.checkpoint as dcp
23from torch.distributed.checkpoint.filesystem import FileSystemReader
24from torch.distributed.checkpoint.default_planner import DefaultLoadPlanner
25from torch.distributed.checkpoint.state_dict import get_model_state_dict
2627state_dict = get_model_state_dict(pipe.model)28dcp.load(29 state_dict=state_dict,30 storage_reader=FileSystemReader(f"{FINETUNED_CKPT}/model"),31 planner=DefaultLoadPlanner(allow_partial_load=True),32)3334# Run V2V with blur+edge dual conditioning (recommended for human→robot)35sample = OmniSampleOverrides(36 name="g1_output",37 output_dir="/tmp/v2v_out/g1_output",38 prompt="A Unitree G1 humanoid robot with five articulated fingers picking up a red apple...",39 vision_path="path/to/input_video.mp4",40 blur=BlurTransferOverrides(preset_blur_strength=PresetBlurStrength.MEDIUM),41 edge=EdgeTransferOverrides(preset_edge_threshold=PresetEdgeThreshold.MEDIUM),42 num_frames=121,43 fps=15,44 resolution="256",45).build_sample(model_config=pipe.model_config)4647pipe.generate_batch([sample], get_sample_data(sample, model=pipe.model))48# Output: /tmp/v2v_out/g1_output/vision.mp4
Conditioning Strategies
Conditioning
When to use
Notes
Blur only
Scene re-styling, preserve motion loosely
Soft background color signal
Canny Edge only
Lock precise arm trajectory
No color context → flat background
Blur + Edge ⭐
Human → robot transfer
Best combo: background + motion
Blur + Edge + Depth
Maximum spatial control
Depth needs pre-computed control_path
For depth/segmentation conditioning, pre-compute the control video first:
python
1# Pre-compute depth (Intel DPT-Large)2from transformers import pipeline as hf_pipeline
3depth_estimator = hf_pipeline("depth-estimation", model="Intel/dpt-large")4# ... process frame by frame, save as depth.mp456# Then use with TransferDataOverrides7from cosmos_framework.inference.args import TransferDataOverrides
8depth=TransferDataOverrides(control_path="/path/to/depth.mp4")
Two-Stage Loading
Why is this needed?
The fine-tuned DCP only saves weights for the 4 trained modules (moe_gen, time_embedder, vae2llm, llm2vae). The 356 visual encoder keys are absent from the DCP because they were frozen during training.
Direct loading fails:
RuntimeError: Missing key in checkpoint state_dict: net.language_model.visual.blocks.0.attn.proj.bias.
Solution: Load the base model first (which includes the visual encoder), then overlay only the fine-tuned weights:
python
1# ✅ Correct: 2-stage load2# Stage 1: base model loads visual encoder + all base weights3model = load_base_cosmos3_nano()45# Stage 2: overlay adapter weights, skip missing visual encoder keys6dcp.load(7 state_dict=get_model_state_dict(model),8 storage_reader=FileSystemReader("/path/to/iter_000010000/model"),9 planner=DefaultLoadPlanner(allow_partial_load=True),# ← key flag10)
python
1# ❌ Wrong: direct DCP load2dcp.load(state_dict=..., storage_reader=FileSystemReader(sft_ckpt))3# → RuntimeError: Missing key in checkpoint state_dict: net.language_model.visual...
Model Configuration
See Cosmos3-Nano-inference.yaml in this repo for the full inference config. Key parameters:
Parameter
Value
Architecture
Cosmos3-Nano (8B)
VLM Backbone
Qwen3-VL-8B
Action dimension
26 (G1 BrainCo joints)
Action frequency
15 Hz
Action chunk size
16 frames
Resolution
480p (policy), 256p (V2V)
Trained modules
moe_gen, time_embedder, vae2llm, llm2vae
Frozen modules
Qwen3-VL visual encoder + text backbone
Training iterations
10,000
Final loss
~3.8 (avg across ranks)
Training Details
Parameter
Value
Dataset
G1 BrainCo (apple-picking manipulation)
Training mode
Policy SFT (image + text → video + actions)
Optimizer
AdamW, lr=5e-6, wd=0, β=[0.9, 0.95]
Scheduler
LambdaCosine, 100-step warmup
Batch
1/GPU, grad_accum=2, effective=14
Hardware
7× A100 80GB (FSDP), ~22s/iter
Epochs
10,000 iterations (~61 hours total)
Checkpointing
Every 500 iters, DCP format
Files
model/
├── __0_0.distcp ─┐
├── __1_0.distcp │
├── __2_0.distcp │ 7× FSDP shards (~13 GB each = ~91 GB total)
├── __3_0.distcp │ contains net.* and net_ema.* for 4 adapter modules
├── __4_0.distcp │
├── __5_0.distcp │
└── __6_0.distcp ─┘
action_stats.json — G1 BrainCo action normalization stats (q01, q99 per joint)
Cosmos3-Nano-inference.yaml — Full model config YAML for inference
Citation
If you use this model, please cite the original Cosmos work:
bibtex
1@misc{cosmos3nano,
2 title={Cosmos3-Nano: An 8B Omni World Model},
3 author={NVIDIA},
4 year={2026},
5 url={https://huggingface.co/nvidia/Cosmos3-Nano}
6}
License
This model is released under the OpenMDW-1.1 license, inherited from the base Cosmos3-Nano model.