# Bir Benchmark Ekleme

Bir benchmark, LeRobot'ün her kullanım biçiminin aynı davranmasını sağlamak için tek bir yerde sürdüğü bir simülatördür: `lerobot.sim`, `lerobot-eval` (toplu bir env, `--env.type=<benchmark>`), rollout ve kayıt (bir sim robot, `--robot.type=sim --robot.env.type=<benchmark>`), yerel olarak veya kendi Docker görüntüsünden `lerobot-env-server` tarafından sunulur. Kullanımına ilişkin bilgi için [Simulation: local or served](./simulation) bölümüne bakın.

## Eklenecekler

| Bileşen            | Konum                                      | Eklenecekler                                                                                                                                                             |
| -------------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Entegrasyon          | `src/lerobot/sim/integrations/<benchmark>.py` | O simülatör için `gym.Env`, `env_fns()` fabrikaları, `canonical_observation()` adaptörü ve `conventions()`                                                          |
| Yapılandırma               | `src/lerobot/envs/configs.py`                 | Fabrikasının kwargs'larına seçeneklerini eşleyen `sim_settings()` içeren bir `EnvConfig` alt sınıfı                                                                                 |
| Sunucu yapılandırması | `docker/sim/configs/<benchmark>.yaml`         | Sunucu ve CI'nin kullandığı görev ve fabrika kwargs'ları                                                                                                                       |
| Simülatör görseli      | `docker/Dockerfile.sim`                       | A `<benchmark>_native` aşaması: sabitlenmiş yerel bağımlılıklar (temel düz Ubuntu olduğu için CUDA araç seti dahil) ve varlık revizyonları; son aşama sunucuyu ekler |
| CI manifesti          | `benchmarks/benchmarks.yaml`                  | Ad, görevler, checkpoint revizyonu, kamera `rename_map` ve isteğe bağlı `parity`; geri kalanı ad üzerinden varsayılan olarak alınır                                                            |
| Bağımlılıklar         | `pyproject.toml`                              | Yerel kullanım için isteğe bağlı bağımlılık grubu                                                                                                                              |
| Belgeler        | `docs/source/<benchmark>.mdx`, `_toctree.yml` | Kullanıcıya yönelik bir sayfa                                                                                                                                                      |
| Köken           | `docs/source/<benchmark>.mdx`                 | Kaynak depoları, lisansları ile birlikte sabitlenmiş kod ve varlık revizyonları ve çalıştırabileceğiniz bir kontrol noktası için yayımlanmış başarı oranı                                     |

Her iki yol da aynı ortam davranışını sunar:

```text
native simulator → LocalVectorEnv, locally or on an env server → canonical NumPy observations
  → batched env or sim robot → one-time image/tensor preparation → saved policy preprocessing
  → policy → saved action postprocessing → native simulator
```

Görsel yönelimi, kuaterniyon dönüşümünü ve durum sıralamasını o simülatörün `canonical_observation()` adaptörüne, kontrol kurallarını ise `conventions()` fonksiyonuna yerleştirin; böylece değerlendirme ve rollout tutarlı olur. `sim/integrations/utils.py` dosyasını yalnızca entegrasyonlar arasında paylaşılan eşlemeler için yeniden kullanın; paylaşılan ortam kodu simülatör adlarına göre dallanmamalıdır. Yeni bir benchmark için [environment processor](./env_processor) gerekmez: gözlemler, politikanın kendi işlemcilerine zaten kanonik olarak ulaşır.

## Değerlendirmenin nasıl çalıştığı

`lerobot-eval` tüm kıyasları aynı şekilde değerlendirir:

1. `make_env()`, iç içe geçmiş `{suite: {task_id: vector env}}` sözlüğünü oluşturur.
2. `eval_policy_all()`, her görev için `n_episodes` rollout çalıştırır; görevler sırayla (veya `--env.max_parallel_tasks` kadarı eşzamanlı olarak) işlenir.
3. Sonuçlar bölüm başına, görev başına, paket başına ve genel olarak toplanır: `pc_success` (başarı oranı), `avg_sum_reward` ve `avg_max_reward`. Her başarı oranı, sayıları (`n_episodes` içinde `n_success`) ve yüzde cinsinden %95 Wilson aralığı (`pc_success_ci95`) ile birlikte gelir. Aralık yalnızca bölümler üzerindeki örneklem gürültüsünü kapsar; aynı tarife ait eğitim çalışmaları arasındaki değişkenlik hakkında hiçbir şey söylemez.

Başarı, ortamınızın her `step()` çağrısında bildirdiği `info["is_success"]` değerinden gelir. Ortamınız kendi sayılarını da bildirebilir. Bunları, her ortam için her adıma bir float eşleyen `info["metrics"]` haritasına koyar. Bu değerler, bölümün sona erdiği adımda alınarak her bölümün girdisindeki `per_episode[i]["metrics"]` altında yer alır.

## Ortamınızın sağlaması gerekenler

### Ortam yapısı

`env_fns()`, ortamları oluşturmadan her görevin ortam fabrikalarını döndürür:

```python
def env_fns(
    task: str,
    n_envs: int,
    gym_kwargs: dict | None = None,
) -> dict[str, dict[int, list[Callable[[], gym.Env]]]]:
    """{suite: {task_id: [make_single_env] * n_envs}} for MyBenchmark."""
```

Tek görevli bir benchmark `{"<task>": {0: [...]}}` döndürür; çok görevli bir benchmark (LIBERO gibi) ise `{"libero_spatial": {0: [...], 1: [...], ...}, ...}` döndürür. `LocalVectorEnv`, ilk kullanımda her bir `make_single_env` fabrikasını yerel olarak veya sunucuda ve `--eval.use_async_envs=true` ile her ortam için ayrı bir süreçte çağırır.

### The gym.Env

```python
class MyBenchmarkEnv(gym.Env):
    metadata = {"render_modes": ["rgb_array"], "render_fps": <fps>}

    def __init__(self, task_suite, task_id, ...):
        super().__init__()
        self.task = <task_name_string>
        self.task_description = <natural_language_instruction>
        self._max_episode_steps = <max_steps>
        self.observation_space = spaces.Dict({...})
        self.action_space = spaces.Box(low=..., high=..., shape=(...,), dtype=np.float32)
```

| Öznitelik            | Tür  | Neden                                                  |
| -------------------- | ----- | ---------------------------------------------------- |
| `_max_episode_steps` | `int` | Bir bölümü sonlandırır (kısaltır)                          |
| `task_description`   | `str` | VLA politikalarına dil talimatı olarak iletilir     |
| `task`               | `str` | `task_description` ayarlanmadıysa yedek tanımlayıcı |

`step()`, başarıyı `info["is_success"]` içinde raporlar ve ölçtüğü diğer her şeyi `info["metrics"]` içinde tutar. Eylemler, tek boyutlu sürekli bir `Box`'tur.

Gözlemler, entegrasyonun `canonical_observation()` adaptörünün anladığı bir sözlüktür. Yeniden kullanılabilir varsayılan adaptör şunları eşler:

| Ortamınızın çıktıları          | Kanonik anahtar                   | Nedir                          |
| ------------------------- | ------------------------------- | ----------------------------------- |
| `"pixels"` (tek dizi) | `observation.image`             | Tek kamera görüntüsü, HWC uint8      |
| `"pixels"` (sözlük)         | `observation.images.<cam>`      | Birden fazla kamera, her biri HWC uint8    |
| `"agent_pos"`             | `observation.state`             | Proprioseptif durum vektörü         |
| `"environment_state"`     | `observation.environment_state` | Tam ortam durumu (ör. PushT) |

Diğer tüm diziler `observation.<key>` olarak iletilir. Simülatörünüzün çıktılarını `gym.Env` içinde bu anahtarlara yeniden adlandırın veya yerel temsilini ilgili entegrasyonun adaptöründe işleyin.

**GPU tabanlı simülatörler (ör. EGL render kullanan MuJoCo):** simülatörünüz `__init__` sırasında GPU/EGL bağlamları ayırıyorsa, bu ayrımı ilk `reset()`/`step()` çağrısında çalışan bir `_ensure_env()` yardımcı fonksiyonuna erteleyin; böylece bir worker sürecinde oluşturulan ortam, eski GPU tutamaçlarını devralmaz. Bu desen için `LiberoEnv._ensure_env()` örneğine bakın.

### Conventions (entegrasyondaki `conventions()`)

`conventions(kwargs)` işlevinden, simülatörün seçeneklerinin bir işlevi olan (RoboTwin'de olduğu gibi bir eylem moduna bağlı olabilirler) simülatörün kontrol hızını, denetleyicisini ve sıralı bileşen adlarını döndürür. Bir yapılandırmanın atladığı ayarları doldurur ve robotlar, veri kümeleri ve denetim noktaları için durum ve eylem bileşenlerini adlandırır. `semantics` varsayılan olarak `<type>-<control>-v1` değerini alır. `robot_type`, bir sim robotunun kaydettiği simüle edilmiş gövdenin adını belirtir: lerobot'un bir sınıfına sahip olduğu durumda gerçek robotun kaydettiği tür (`so_follower`), aksi halde kısa bir ad (`panda`, `sawyer`); belirtilmezse veri kümeleri `sim_robot` kaydeder.

### Yapılandırma (`src/lerobot/envs/configs.py`)

Kullanıcıların `--env.type=<name>` (ve `--robot.env.type=<name>`) ile benchmark'ınızı seçebilmesi için bir config kaydedin. `sim_settings()` metodu, simülatörü bir sunucu YAML dosyasının `sim` bölümü olarak tanımlar; `LocalVectorEnv` ise gerisini halleder:

```python
@EnvConfig.register_subclass("<benchmark_name>")
@dataclass
class MyBenchmarkEnvConfig(EnvConfig):
    task: str = "<default_task>"
    fps: int = <fps>
    obs_type: str = "pixels_agent_pos"

    @property
    def gym_kwargs(self) -> dict:
        return {"obs_type": self.obs_type}

    def sim_settings(self) -> dict:
        return {"type": "<benchmark_name>", "task": self.task, "kwargs": {"gym_kwargs": self.gym_kwargs}}
```

Varsayılanlarını ve sunucu YAML'lerini tutarlı tutun: sunulan bir değerlendirme, komutun tarif ettiğinden farklı bir ortamda çalışan sunucuyu reddeder. Özellikler, ortam oluşturulduğunda ortamın açıklamasından gelir, bu nedenle yapılandırma hiçbirini beyan etmez.

## Checkpoint kabulü

`--rename_map`, herhangi bir robot için olduğu gibi, ortam kamera anahtarlarını checkpoint'in eğitim görmüş anahtarlarına eşler; CI'da bu değer, `benchmarks/benchmarks.yaml` dosyasındaki girdinin `rename_map` alanından gelir. Yeniden adlandırma sonrasında checkpoint girdileri var olmalı ve durum/aksiyon boyutları eşleşmelidir; yeniden adlandırma, checkpoint meta verilerini onaramaz. RGB kanal sayısı ve düzeni kabul aşamasında kontrol edilir. Edinim yükseklik/genişliği, eğitim meta verilerinden farklı olabilir; yeniden boyutlandırma, politika ön işleme kapsamındadır.

## Doğrulama ve CI

1. Entegrasyonun gözlem adaptörünü, özellikle kamera yönelimi ve durum sırası açısından, simülatörünüzün ham çıktılarıyla karşılaştırın ve ortam sarmalayıcısının uyguladığı eylemleri kontrol edin.
2. Yerel ve sunulan tohumlu sıfırlama/adım dizilerini karşılaştırın (`scripts/ci/check_sim_parity.py`); deterministik bir simülatörün manifest girdisine `parity: true` ayarlayarak CI'nin bunu çalıştırmasını sağlayın. Terminal donmasını, başarıyı, bölüm uzunluğunu, render'ı ve kaynak temizliğini kontrol edin.
3. Sunucu kodu ve yerel modülünüz için torch-devre dışı bırakılmış içe aktarma koruyucularını çalıştırın. RoboTwin ve RoboMME gibi kendi torch çalışma zamanına ihtiyaç duyan simülatörleri belgeleyin.
4. `lerobot-eval --env.type=<name> --env.task=<task> --eval.n_episodes=1 --policy.path=<checkpoint>` komutunu yerel olarak ve `--env.server.endpoint` ile sunucuya karşı çalıştırın. Görev açıklamalarını ve render edilmiş kamera görüntülerini inceleyin.
5. Oluşturulan benchmark işini GPU çalıştırıcısında çalıştırın. Ortak değerlendirme/eğitim entegrasyonunu değiştirirken LIBERO eğitim duman testini koruyun.

`benchmarks/benchmarks.yaml`, `scripts/ci/benchmark_matrix.py` üzerinden matrisi oluşturur; `.github/workflows/benchmark_run.yml` her girdiyi çalıştırır. CI işlerini kopyalamak yerine girdileri manifeste ekleyin. CI, hattı uçtan uca kontrol etmek için bölümleri sınırlar; `metrics.json` dosyası checkpoint revizyonunu, simülatör imaj etiketini, commit ve sınırı kaydeder ve bu çalıştırmaları `smoke` olarak işaretler: başarı oranları politika puanları değildir. Simülatör imajlarının ayrı sabitlemeleri ve içerik etiketleri vardır; BuildKit önbellekleri yalnızca kalıcı çalıştırıcılarda kalıcıdır.

## Bir ölçümün değiştirilmesi

Bir entegrasyonun `canonical_observation()`, `conventions()` ve ortam sarmalayıcısı, politikanın ne gördüğünü ve eylemlerinin nasıl uygulandığını belirler. Yanlış bir görüntü yönelimi, durum sırası veya kontrol hızı çökme yapmaz: politika hafifçe hatalı girdiler görür ve başarı oranı düşer. Bunlardan herhangi birine yapılan değişiklik şunları içerir:

- Kaydedilmiş veya sentetik bir gözlem üzerinde eski ve yeni çıktıları karşılaştıran bir **geri dönüş testi**. `tests/sim/integrations/test_libero.py` içindeki `test_libero_numpy_adapter_parity` bunun modelidir: torch içermeyen LIBERO adaptörünün, önceki LIBERO işleyicisinin ürettiğiyle birebir aynı sonucu ürettiğini gösterir.
- **Pull request'te puanlar üzerindeki beklenen etki**: yok, ya da hangi puanların neden değişmesi gerektiği.

## Dependencies (`pyproject.toml`)

Yerel kullanım için yeni bir isteğe bağlı bağımlılık grubu ekleyin:

```toml
mybenchmark = ["my-benchmark-pkg==1.2.3", "lerobot[scipy-dep]"]
```

Sabitleme kuralları:

- **Her zaman** yeniden üretilebilirlik için benchmark paketlerini kesin sürümlere sabitleyin (ör. `metaworld==3.0.0`).
- Gerekli durumlarda (ör. `; sys_platform == 'linux'`) **platform işaretleyicileri ekleyin**.
- Biliniyorsa **kırılgan dolaylı bağımlılıkları sabitleyin** (ör. Meta-World görüntüsü, MuJoCo 3.17'nin mocap kaynaklı kaynaklarını bozduğu için `mujoco==3.15.0` sürümünü sabitler).
- **Belge kısıtlamaları** benchmark doküman sayfanızda. Bağımlılıklar LeRobot'unkilerle çelişiyorsa, sunulan yol desteklenen olandır.

## Bir benchmark doküman sayfası yazma

`docs/source/_toctree.yml` dosyasındaki "Benchmarks" bölümüne sayfayı ekleyin. Her benchmark sayfası şunları içermelidir:

- **Başlık ve açıklama** — Benchmark'ın neyi test ettiğini ve neden önemli olduğunu anlatan 1-2 paragraf.
- **Bağlantılar** — makale, GitHub deposu, proje web sitesi (mevcutsa).
- **Köken ve lisanslar** — kaynak depoları, sabitlenmiş kod ve varlık revizyonları ve bunların her birinin lisansı. Lisansı kullanımı yasaklayan bir benchmark eklemeyin.
- **Genel bakış görseli veya GIF.**
- **Mevcut görevler** — görev setlerinin sayıları ve kısa açıklamalarıyla tablosu.
- **Yükleme** — `pip install -e ".[<benchmark>]"` veya sunucu komutu.
- **Değerlendirme** — tekrarlanabilir sonuçlar için `n_episodes` ile önerilen `lerobot-eval` komutu.
- **Politika girdileri ve çıktıları** — şekilleriyle birlikte gözlem anahtarları, eylem uzayı açıklaması.
- **Eğitim** — örnek `lerobot-train` komutu.
- **Referans sonuçlar** — çalıştırabileceğiniz en az bir önceden eğitilmiş checkpoint'in yayınlanmış başarı oranı, revizyonu ve bunu yeniden üreten `lerobot-eval` komutu. Bu değere yakın bir sonuç üretmeyen bir entegrasyon tamamlanmamış sayılır.

Tam örnekler için `docs/source/libero.mdx` ve `docs/source/metaworld.mdx` dosyalarına bakın.

