# İşleyicilere Giriş

Robotikte, robotların ve insanların ürettiği veriler ile makine öğrenme modellerinin beklediği veriler arasında temel bir uyumsuzluk vardır. Robotlar, modellerin işleyebilmesi için normalizasyon, toplu işleme (batching) ve cihaz yerleşimi gerektiren kamera görüntüleri ve eklem konumları gibi ham sensör verileri üretir. İnsanlardan gelen dil talimatları sayısal temsillere dönüştürülmeli (tokenize edilmeli) ve farklı robotların kullandığı farklı koordinat sistemleri standartlaştırılmalıdır.

Zorluk, model çıktılarında da kendini gösterir. Modeller son ekleme konumlarını üretebilirken robotlar eklem uzayı komutlarına ihtiyaç duyar; teleoperatörler göreli hareketler üretirken robotlar mutlak komutlar bekler. Model tahminleri genellikle normalize edilir ve gerçek dünya ölçeklerine geri dönüştürülmesi gerekir.

Alanlar arası çeviri, ek bir karmaşıklık katmanı ekler. Bir robot kurulumundan gelen eğitim verilerinin farklı donanımlarda dağıtım için uyarlanması, belirli kamera yapılandırmalarıyla eğitilen modellerin yeni düzenlemelerle çalışması ve farklı adlandırma kurallarına sahip veri setlerinin uyumlaştırılması gerekir.

**İşleyiciler tam da burada devreye girer.** Bu boşlukları köprüleyen evrensel çevirmenler olarak görev yaparlar ve sensörlerden modellere, oradan da aktüatörlere kesintisiz bir veri akışı sağlarlar. İşleyiciler, ham ortam verilerini modele hazır girdilere dönüştürmek ve bunun tersini yapmak için gereken tüm ön işleme ve son işleme adımlarını ele alır.

Bu, favori politikanızın şu şekilde kullanılabileceği anlamına gelir:

```python
import torch

from lerobot.datasets import LeRobotDataset
from lerobot.policies import make_pre_post_processors
from lerobot.policies.your_policy import YourPolicy
from lerobot.processor import RobotProcessorPipeline, PolicyProcessorPipeline
dataset = LeRobotDataset("hf_user/dataset", episodes=[0])
sample = dataset[10]

model = YourPolicy.from_pretrained(
    "hf_user/model",
)
model.eval()
model.to("cuda")
preprocessor, postprocessor = make_pre_post_processors(model.config, pretrained_path="hf_user/model", dataset_stats=dataset.meta.stats)

preprocessed_sample = preprocessor(sample)
action = model.select_action(preprocessed_sample)
postprocessed_action = postprocessor(action)
```

## İşleyiciler Nedir?

Robotikte veri birçok formda gelir: kameralardan gelen görüntüler, sensörlerden gelen eklem konumları, kullanıcılardan gelen metin talimatları ve daha fazlası. Verinin her türü, bir modelin onu etkili bir şekilde kullanabilmesi için belirli dönüşümler gerektirir. Modellerin bu verinin şu şekilde olması gerekir:

- **Normalize edilmiş**: Sinir ağı işleme için uygun aralıklara ölçeklenmiş
- **Toplu (Batched)**: Toplu işleme için uygun boyutlarla düzenlenmiştir
- **Tokenize edilmiş**: Sayısal temsillere dönüştürülmüş metin
- **Cihazda konumlandırılmış**: Doğru donanıma (CPU/GPU) taşındı
- **Tür dönüştürülmüş**: Uygun veri türlerine dönüştürülür

İşleyiciler, bu dönüşümleri bir araya getirilerek iş akışlarına dönüştürülebilen, birleştirilebilir ve yeniden kullanılabilir adımlar aracılığıyla gerçekleştirir. Bunları, her istasyonun verileriniz üzerinde belirli bir dönüşüm gerçekleştirdiği modüler bir montaj hattı olarak düşünebilirsiniz.

## Temel Kavramlar

### EnvTransition: Evrensel Veri Kapsayıcısı

`EnvTransition`, tüm işleyicilerden geçen temel veri yapısıdır. Tam bir robot-ortam etkileşimini temsil eden tipli bir sözlüktür:

- **GÖZLEM**: Tüm sensör verileri (görseller, durumlar, propriyosepsiyon)
- **ACTION**: Çalıştırılacak veya çalıştırılmış işlem
- **ÖDÜL**: Pekiştirmeli öğrenme sinyali
- **DONE/TRUNCATED**: Bölüm sınır göstergeleri
- **BİLGİ**: İsteğe bağlı meta veriler
- **COMPLEMENTARY_DATA**: Görev açıklamaları, dizinler, dolgu bayrakları, adım arası veriler

Batch dönüştürücüler, `index`, `episode_index` ve `frame_index` gibi dizinleme meta verilerini `COMPLEMENTARY_DATA` içinde tutar. `batch_to_transition` / `transition_to_batch` gidiş-dönüş işleminde `frame_index`, orijinal skaler veya tensör değerini korur. Girdi `frame_index` alanını içermezse, dönüştürücüler bu alanı eklemez.

### ProcessorStep: Yapı Taşı

`ProcessorStep`, geçişleri işleyen tekil bir dönüştürme birimidir. İki zorunlu yöntemi olan soyut bir temel sınıftır:

```python
from lerobot.processor import ProcessorStep, EnvTransition

class MyProcessorStep(ProcessorStep):
    """Example processor step - inherit and implement abstract methods."""

    def __call__(self, transition: EnvTransition) -> EnvTransition:
        """Transform the transition - REQUIRED abstract method."""
        # Your processing logic here
        return transition

    def transform_features(self, features):
        """Declare how this step transforms feature shapes/types - REQUIRED abstract method."""
        return features  # Most processors return features unchanged
```

`__call__`, işlemcinizin çekirdeğidir. Bir `EnvTransition` alır ve değiştirilmiş bir `EnvTransition` döndürür.

`transform_features`, bu adımın özellik biçimlerinin/tiplerini nasıl dönüştürdüğünü beyan etmek için kullanılır.

### DataProcessorPipeline: Genel Orkestratör

`DataProcessorPipeline[TInput, TOutput]`, birden fazla `ProcessorStep` örneğini bir araya getirir:

```python
from lerobot.processor import RobotProcessorPipeline, PolicyProcessorPipeline

# For robot hardware (unbatched data)
robot_processor = RobotProcessorPipeline[RobotAction, RobotAction](
    steps=[step1, step2, step3],
    name="robot_pipeline"
)

# For model training/inference (batched data)
policy_processor = PolicyProcessorPipeline[dict[str, Any], dict[str, Any]](
    steps=[step1, step2, step3],
    name="policy_pipeline"
)
```

## RobotProcessorPipeline ve PolicyProcessorPipeline

Temel ayrım, ele aldıkları veri yapılarındadır:

| Özellik          | RobotProcessorPipeline                       | PolicyProcessorPipeline                  |
| --------------- | -------------------------------------------- | ---------------------------------------- |
| **Girdi**       | `dict[str, Any]` - Bireysel robot değerleri   | `dict[str, Any]` - Toplu tensörler       |
| **Çıktı**      | `dict[str, Any]` - Bireysel robot komutları | `torch.Tensor` - Politika tahminleri      |
| **Kullanım Senaryosu**    | Gerçek zamanlı robot kontrolü                      | Model eğitimi/çıkarımı                 |
| **Veri Biçimi** | Toplu olmayan, heterojen                     | Toplu, homojen                     |
| **Örnekler**    | `{"joint_1": 0.5}`                           | `{"observation.state": tensor([[0.5]])}` |

Robot donanım arayüzleri için **`RobotProcessorPipeline` kullanın**:

```python
# Robot data structures: dict[str, Any] for observations and actions
robot_obs: dict[str, Any] = {
    "joint_1": 0.5,           # Individual joint values
    "joint_2": -0.3,
    "camera_0": image_array   # Raw camera data
}

robot_action: dict[str, Any] = {
    "joint_1": 0.2,          # Target joint positions
    "joint_2": 0.1,
    "gripper": 0.8
}
```

Model eğitimi ve toplu işleme için **`PolicyProcessorPipeline` kullanın**:

```python
# Policy data structures: batch dicts and tensors
policy_batch: dict[str, Any] = {
    "observation.state": torch.tensor([[0.5, -0.3]]),      # Batched states
    "observation.images.camera0": torch.tensor(...),        # Batched images
    "action": torch.tensor([[0.2, 0.1, 0.8]])              # Batched actions
}

policy_action: torch.Tensor = torch.tensor([[0.2, 0.1, 0.8]])  # Model output tensor
```

## Dönüştürücü İşlevleri

LeRobot, `lerobot.processor.converters` içinde farklı veri biçimleri arasında köprü kuran dönüştürücü işlevler sağlar. Bu işlevler, robot donanımı veri yapıları, politika model biçimleri ve işlemci hatları boyunca akan iç `EnvTransition` temsilcisi arasındaki kritik çevirileri yönetir.

| Kategori                       | Fonksiyon                      | Açıklama                     |
| ------------------------------ | ----------------------------- | ------------------------------- |
| **Robotik Donanım Dönüştürücüler**  | `robot_action_to_transition`  | Robot sözlüğü → EnvTransition      |
|                                | `observation_to_transition`   | Robot gözlemleri → EnvTransition       |
|                                | `transition_to_robot_action`  | EnvTransition → Robot sözlüğü      |
| **Politika/Eğitim Dönüştürücüler** | `batch_to_transition`         | Batch dict → EnvTransition      |
|                                | `transition_to_batch`         | EnvTransition → Batch sözlüğü      |
|                                | `policy_action_to_transition` | Policy tensörü → EnvTransition   |
|                                | `transition_to_policy_action` | EnvTransition → Policy tensörü   |
| **Yardımcılar**                  | `create_transition`           | Varsayılanlarla geçişler oluşturun |
|                                | `identity_transition`         | Geçiş dönüştürücüsü          |

Temel içgörü, **robot donanım dönüştürücülerinin** bireysel değerler ve sözlüklerle çalışırken, **politika/eğitim dönüştürücülerinin** toplu tensörler ve model çıktılarıyla çalışmasıdır. Dönüştürücü işlevleri yapısal farklılıkları otomatik olarak ele alır; böylece işlemciniz, veri biçimi uyumluluğuyla uğraşmadan temel dönüşümlere odaklanabilir.

## İşleyici Örnekleri

Aşağıdaki örnekler, politika eğitimi ve çıkarımı için gerçek dünya işlemci yapılandırmalarını göstermektedir.

İşte politika eğitimi ve çıkarımı için örnek bir işlemci:

```python
# Training data preprocessing (optimized order for GPU performance)
training_preprocessor = PolicyProcessorPipeline[dict[str, Any], dict[str, Any]](
    steps=[
        RenameObservationsProcessorStep(rename_map={}),     # Standardize keys
        AddBatchDimensionProcessorStep(),                   # Add batch dims
        TokenizerProcessorStep(tokenizer_name="...", ...),  # Tokenize language
        DeviceProcessorStep(device="cuda"),                 # Move to GPU first
        NormalizerProcessorStep(features=..., stats=...),   # Normalize on GPU
    ]
)

# Model output postprocessing
training_postprocessor = PolicyProcessorPipeline[torch.Tensor, torch.Tensor](
    steps=[
        DeviceProcessorStep(device="cpu"),                  # Move to CPU
        UnnormalizerProcessorStep(features=..., stats=...), # Denormalize
    ],
    to_transition=policy_action_to_transition,
    to_output=transition_to_policy_action,
)
```

### İşleyicilere sahip bir politika ile bir robot arasındaki etkileşim

En yaygın gerçek dünya senaryosu, her iki pipeline türünü birleştirir: robot donanımı, politika işleme gerektiren gözlemler üretir ve politika çıktıları, robotla uyumlu son işleme gerektirir:

```python
# Real deployment: Robot sensors → Model → Robot commands
with torch.no_grad():
    while not done:
        raw_obs = robot.get_observation()  # dict[str, Any]

        # Add your robot observation to policy observation processor

        policy_input = policy_preprocessor(raw_obs)  # Batched dict

        policy_output = policy.select_action(policy_input)  # Policy tensor

        policy_action = policy_postprocessor(policy_output)

        # Add your robot action to policy action processor

        robot.send_action(policy_action)
```

## Özellik Sözleşmeleri: Şekil ve Tür Dönüşümü

İşleyiciler yalnızca verileri dönüştürmez, aynı zamanda **veri yapısının kendisini de değiştirebilir**. `transform_features()` metodu bu değişiklikleri bildirir; bu, veri seti kaydı ve politika oluşturma için kritiktir.

### Neden Özellik Sözleşmeleri Önemlidir

Veri kümeleri veya politikalar oluşturulurken LeRobot'un bilmesi gerekenler:

- **İşlemden sonra hangi veri alanları var olacak**
- **Her alanın sahip olacağı şekiller ve türler**
- Beklenen veri yapısı için **modellerin nasıl yapılandırılacağı**

```python
# Example: A processor that adds velocity to observations
class VelocityProcessor(ObservationProcessorStep):
    def observation(self, obs):
        new_obs = obs.copy()
        if "observation.state" in obs:
            # concatenate computed velocity field to the state
            new_obs["observation.state"] = self._compute_velocity(obs["observation.state"])
        return new_obs

    def transform_features(self, features):
        """Declare the new velocity field we're adding."""
        state_feature = features[PipelineFeatureType.OBSERVATION].get("observation.state")
        if state_feature:
            double_shape = (state_feature.shape[0] * 2,) if state_feature.shape else (2,)
            features[PipelineFeatureType.OBSERVATION]["observation.state"] = PolicyFeature(
                type=FeatureType.STATE, shape=double_shape
            )
        return features
```

### Özellik Belirtimi Fonksiyonları

`create_initial_features()` ve `aggregate_pipeline_dataset_features()` kritik bir veri seti oluşturma sorununu çözer: herhangi bir veri işlenmeden önce kesin nihai veri yapısının belirlenmesi. İşleyici (processor) hatları yeni özellikler ekleyebilir (hız alanları gibi), tensör şekillerini değiştirebilir (görselleri kırpma gibi) veya anahtarları yeniden adlandırabilir; bu nedenle veri setleri, uygun depolama alanı ayırmak ve şemaları tanımlamak için tam çıktı spesifikasyonunu önceden bilmelidir. Bu işlevler birlikte çalışarak robot donanım spesifikasyonlarından başlar (`create_initial_features()`), ardından tüm hat dönüşümünü simüle eder (`aggregate_pipeline_dataset_features()`) ve `LeRobotDataset.create()`'e iletilen nihai özellik sözlüğünü hesaplar; bu da işleyicilerin ürettiği ile veri setlerinin depolamayı beklediği arasındaki mükemmel uyumu sağlar.

```python
from lerobot.datasets import aggregate_pipeline_dataset_features

# Start with robot's raw features
initial_features = create_initial_features(
    observation=robot.observation_features,  # {"joint_1.pos": float, "camera_0": (480,640,3)}
    action=robot.action_features            # {"joint_1.pos": float, "gripper.pos": float}
)

# Apply processor pipeline to compute final features
final_features = aggregate_pipeline_dataset_features(
    pipeline=my_processor_pipeline,
    initial_features=initial_features,
    use_videos=True
)

# Use for dataset creation
dataset = LeRobotDataset.create(
    repo_id="my_dataset",
    features=final_features,  # Knows exactly what data to expect
    ...
)
```

## Ortak İşleyici Adımları

LeRobot, kayıtlı birçok işlemci adımı sağlar. En sık kullanılan çekirdek işlemciler şunlardır:

### Temel İşlemciler

- **`normalizer_processor`**: Gözlemleri/aksiyonları veri seti istatistikleri (ortalama/std veya min/max) kullanarak normalize et
- **`device_processor`**: Tensörleri isteğe bağlı dtype dönüşümüyle CPU/GPU'ya taşır
- **`to_batch_processor`**: Model uyumluluğu için geçişlere parti boyutları ekler
- **`rename_observations_processor`**: Gözlem anahtarlarını eşleme sözlükleri kullanarak yeniden adlandırma
- **`tokenizer_processor`**: Doğal dil görev açıklamalarını token ve dikkat maskelerine dönüştürür

### Sonraki Adımlar

- **[Kendi İşleyicinizi Uygulayın](./implement_your_own_processor)** - Özel işleyici adımları oluşturun
- **[Pipeline'ınızı Hata Ayıklama](./debug_processor_pipeline)** - Pipeline'ları sorun giderme ve optimize etme
- **[Robotlar ve Teleoperatörler için İşleyiciler](./processors_robots_teleop)** - Gerçek dünya entegrasyon kalıpları

## Özet

İşleyiciler, robotikte veri çeviri sorununu şu şekilde çözerek:

- **Modüler dönüşümler**: Birleştirilebilir, yeniden kullanılabilir işleme adımları
- **Tür güvenliği**: Derleme zamanı denetimi olan genel amaçlı boru hatları
- **Performans optimizasyonu**: GPU hızlandırmalı işlemler
- **Robot/Policy ayrımı**: Farklı veri yapıları için ayrı boru hatları
- **Kapsamlı ekosistem**: Yaygın görevler için 30+ kayıtlı işleyici

Temel içgörü: `RobotProcessorPipeline` toplulaştırılmamış robot donanım verilerini, `PolicyProcessorPipeline` ise toplulaştırılmış model verilerini işler. Veri yapınıza uygun aracı seçin!

