Datasets
May 27, 2026 · View on GitHub
The repo ships configs for three dataset families: DINO-WM (5 simulated environments), RT-1 fractal (real-robot LeRobot), and CSGO (Counter-Strike deathmatch). All datasets feed through a common WorldModelDataset interface — see src/wm_datasets/.

Setup paths
export DATASET_DIR=/path/to/dino_wm_data # DINO-WM root
export CSGO_DATA_DIR=/path/to/csgo # CSGO root (HDF5 files)
export RT1_DATA_ROOT=/path/to/rt1_fractal # RT-1 (LeRobot mirror)
Or use the gitignored src/configs/local/paths.yaml (template at paths.yaml.example). See config_system.md.
At a glance
| Dataset | Episodes | Frames/ep | Resolution | Action dim | Train sampling | Notes |
|---|---|---|---|---|---|---|
| DINO-WM Point Maze | ~500 | ~100–200 | 256² | 2 | exhaustive | frame_interval=5 |
| DINO-WM PushT | ~1000 | ~100–200 | 256² | 2 | exhaustive | relative actions, action_scale=100 |
| DINO-WM Wall | ~500 | ~100–200 | 256² | 2 | exhaustive | |
| DINO-WM Rope | ~500 | ~100–200 | 256² | 2 | exhaustive | deformable |
| DINO-WM Granular | ~500 | ~100–200 | 256² | 2 | exhaustive | deformable |
| RT-1 (fractal) | 87k | ~40–60 | 256² | 7 | random | LeRobot v2.0, frame_interval=1 |
| CSGO | 5500 | 1000 | 320×512 | 51 | random | fixed val start indices, frame_interval=1 |
DINO-WM datasets
5 simulated environments (point_maze, pusht, wall, rope, granular). Originally from the DINO-WM repo. Pure vision (no state); 2D action.
Download
From OSF. Unzip the relevant subfolders following the DINO-WM README. Layout we expect:
${DATASET_DIR}/
├── point_maze/
├── pusht_noise/
│ ├── train/
│ └── val/
├── wall_single/
└── deformable/ # rope + granular share this directory
Configs
src/configs/dataset/dino_wm/:
base.yaml— sets exhaustive train/val sampling, validation_size=32, action normalization on- per-env:
point_maze.yaml,pusht.yaml,wall.yaml,rope.yaml,granular.yaml
PushT is the most distinctive: it uses relative actions (delta moves), action_scale=100, and with_velocity=True.
Train command
python src/main.py experiment=dino_wm_pusht dataset=dino_wm/pusht model=nanowm_b2
Swap the experiment + dataset names for the other four envs.
RT-1 (fractal)
Real-robot manipulation, 87k episodes from the IPEC-COMMUNITY/fractal20220817_data_lerobot mirror of RT-1 fractal on HuggingFace. LeRobot v2.0 format. 7-D end-effector action.
Download
huggingface-cli download IPEC-COMMUNITY/fractal20220817_data_lerobot \
--repo-type dataset --local-dir $RT1_DATA_ROOT
(Run huggingface-cli login first if you haven't.) Without RT1_DATA_ROOT set, LeRobot will pull on first use into ~/.cache/huggingface/lerobot.
Config
src/configs/dataset/rt1/rt1.yaml:
data_path: "IPEC-COMMUNITY/fractal20220817_data_lerobot"(HF repo id)root: "${oc.env:RT1_DATA_ROOT,./data/rt1_fractal}"(local mirror)image_key: "observation.images.image"(RT-1's frame field)train_slice_mode: "random"(87k episodes is too many for exhaustive sampling)action_dim: 7
Train command
# Main run: NanoWM-B/2, 300k steps
python src/main.py experiment=rt1 dataset=rt1/rt1 model=nanowm_b2
# Ablation arms (50k steps)
python src/main.py experiment=ablation_rt1 dataset=rt1/rt1 model=nanowm_b2 \
experiment.diffusion.pred_name=v # or pred_name=x / epsilon
See training.md for the full ablation table.
CSGO
Counter-Strike: Global Offensive deathmatch gameplay. Source: teapearce/CounterStrike_Deathmatch. 5500 episodes (5000 train / 500 val), 1000 frames each at 3 FPS — ~675 GB total.
Download
huggingface-cli download teapearce/CounterStrike_Deathmatch \
--repo-type dataset --local-dir $CSGO_DATA_DIR
We use only the standard deathmatch files: hdf5_dm_july2021_*.hdf5. The 75 expert files (aim training, inferno/mirage/nuke expert) are excluded for consistency with the Vid2World evaluation protocol.
Train / val split
The split is fixed (matches Vid2World):
src/wm_datasets/data_source/game/csgo_splits/train_split.txt— 5000 filessrc/wm_datasets/data_source/game/csgo_splits/test_split.txt— 500 filessrc/wm_datasets/data_source/game/csgo_splits/csgo_validation_start_indices.npy— 500 fixed start frames (one per val episode)
The fixed start indices ensure identical eval positions across runs.
Data format
Each .hdf5 file is one episode:
frame_0_x: [150, 280, 3] uint8 # frame at timestep 0
frame_0_y: [51] float32 # action vector at timestep 0
...
frame_999_x: [150, 280, 3] uint8
frame_999_y: [51] float32
``$
\text{Frames}: 150 \times 280 \text{native}, \text{resized} \text{to} 320 \times 512 \text{during} \text{loading} ($resize_mode: stretch`). After loading: `[0, 255] uint8 → [-1, 1] float32`. **Native aspect ratio is 1.87:1** — when running long rollout decoded back to native res, restore aspect with `--native_res 150 280` (see [applications/long_rollout.md](../applications/long_rollout.md)).
**Action space (51-D)**:
<div align="center">
| Dims | Description |
|:-----|:------------|
| 0–10 (11) | Keyboard keys (W/A/S/D, Space, Ctrl, Shift, …) — binary |
| 11–12 (2) | Mouse clicks (LMB, RMB) — binary |
| 13–35 (23) | Mouse X movement — one-hot bins |
| 36–50 (15) | Mouse Y movement — one-hot bins |
</div>
State dim: 0 (pure vision; no health/ammo/inventory).
### Why CSGO uses random sampling
5000 episodes × 1000 frames ≈ 5M slices. Exhaustive enumeration is impractical, so:
- `train_slice_mode: random` — sample a random `[start, start+T]` window per episode each iteration
- `val_slice_mode: exhaustive` — but only at the 500 fixed `val_start_indices`
### Config
`src/configs/dataset/game/csgo.yaml`:
```yaml
name: "csgo"
frame_interval: 1
loader:
data_path: "${csgo_data_dir}"
normalize_action: False # actions are already [0, 1]
resize_mode: "stretch"
train_file_list: "src/wm_datasets/data_source/game/csgo_splits/train_split.txt"
val_file_list: "src/wm_datasets/data_source/game/csgo_splits/test_split.txt"
val_start_indices: "src/wm_datasets/data_source/game/csgo_splits/csgo_validation_start_indices.npy"
train_slice_mode: "random"
val_slice_mode: "exhaustive"
spec:
action_dim: 51
Train command
python src/main.py experiment=csgo dataset=game/csgo model=nanowm_l2_csgo
The shipped checkpoints are NanoWM-L/2 trained for 50k or 100k steps. See training.md for HF links.
Memory
- Actions: ~10 MB/episode (cached in memory)
- Frames: ~123 MB/episode (loaded on demand — never cached)
- Total: ~675 GB on disk; RAM stays bounded by the per-batch decode
Adding a new dataset
-
DataSource in
src/wm_datasets/data_source/:class MyDataSource(DataSource): def load_trajectory(self, index): ... def load_visual_frames(self, index, start, end, step=1): ... def get_num_trajectories(self): ... def get_seq_length(self, index): ... @property def action_dim(self): ... -
Register in
src/wm_datasets/data_source/factory.py(add a branch ondataset_name). -
Config under
src/configs/dataset/<family>/<name>.yamlinheriting from abase.yaml:defaults: - <family>/base name: "my_dataset" loader: data_path: "${dataset_dir}/my_dataset" train_slice_mode: "exhaustive" # or "random" spec: action_dim: <int> -
Experiment config (optional) under
src/configs/experiment/<name>.yamlif you want non-default training knobs.
Run with dataset=<family>/<name>.
See also
- config_system.md — full Hydra reference
- training.md — training workflow + design choices
- evaluation.md — eval workflow + result tables