LeRobot documentation

Guide du flux de travail d'entraînement sur robot réel HIL-SERL

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Guide du flux de travail d'entraînement sur robot réel HIL-SERL

Dans ce tutoriel, vous parcourez le flux de travail complet d'apprentissage par renforcement économe en échantillons avec humain dans la boucle (Human-in-the-Loop Sample-Efficient Reinforcement Learning, HIL-SERL) à l'aide de LeRobot. Vous maîtriserez l'entraînement d'une politique par RL sur un robot réel en quelques heures seulement.

HIL-SERL est un algorithme d'apprentissage par renforcement efficace en termes d'échantillons, qui combine des démonstrations humaines avec l'apprentissage en ligne et les interventions humaines. L'approche part d'un petit ensemble de démonstrations humaines, les utilise pour entraîner un classifieur de récompense, puis met en œuvre une architecture acteur-apprenant où les humains peuvent intervenir pendant l'exécution de la politique pour guider l'exploration et corriger les comportements non sûrs. Dans ce tutoriel, vous utiliserez une manette pour fournir des interventions et contrôler le robot pendant le processus d'apprentissage.

Il combine trois ingrédients clés :

  1. Démonstrations hors ligne et classifieur de récompense : quelques épisodes de téléopération humaine et un détecteur de succès basé sur la vision offrent à la politique un point de départ structuré.

  2. Boucle acteur/apprenant sur le robot avec interventions humaines : un apprenant Soft Actor Critic (SAC) distribué met à jour la politique pendant qu'un acteur explore sur le robot physique ; l'humain peut intervenir à tout moment pour corriger un comportement dangereux ou non productif.

  3. Outils de sécurité et d’efficacité : les limites des articulations/effets terminaux (EE), le prétraitement de la région d’intérêt (ROI) et la surveillance Trackio garantissent l’utilité des données et la sécurité du matériel.

Ces éléments combinés permettent à HIL-SERL d’atteindre un taux de réussite quasi parfait et des temps de cycle plus rapides que les méthodes de référence basées uniquement sur l’imitation.

HIL-SERL workflow

Flux de travail HIL-SERL, Luo et al. 2024

Ce guide fournit des instructions étape par étape pour entraîner une politique robotique à l’aide de l’implémentation HilSerl de LeRobot, afin de s’entraîner sur un robot réel.

De quoi ai-je besoin ?

  • Une manette de jeu (recommandée) ou un clavier pour contrôler le robot
  • Un GPU Nvidia
  • Un robot réel avec un bras suiveur et un bras leader (facultatif si vous utilisez le clavier ou la manette)
  • Un fichier URDF du robot pour le package de cinématique (voir lerobot/model/kinematics.py)

Quels types de tâches puis-je entraîner ?

On peut utiliser HIL-SERL pour entraîner sur une variété de tâches de manipulation. Quelques recommandations :

  • Commencez par une tâche simple pour comprendre le fonctionnement du système.
    • Pousser le cube vers une zone cible
    • Prendre et soulever le cube avec la pince
  • Évitez les tâches à horizon extrêmement long. Concentrez-vous sur des tâches qui peuvent être réalisées en 5 à 10 secondes.
  • Une fois que vous avez une bonne idée du fonctionnement du système, vous pouvez essayer des tâches plus complexes et des horizons plus longs.
    • Prendre et placer un cube
    • Tâches bimanuelles pour saisir des objets avec deux bras
    • Tâches de transfert pour passer des objets d'un bras à l'autre
    • Déchaînez-vous !

Installer LeRobot avec HIL-SERL

Pour installer LeRobot avec HIL-SERL, vous devez installer l'extra hilserl.

pip install -e ".[hilserl]"

Workflow d'entraînement sur robot réel

Comprendre la configuration

Le processus d’entraînement commence par une configuration appropriée de l’environnement HILSERl. La classe de configuration principale est GymManipulatorConfig dans lerobot/rl/gym_manipulator.py, qui contient les sous-configurations imbriquées HILSerlRobotEnvConfig (définie dans lerobot/envs/configs.py) et DatasetConfig. La configuration est organisée en sous-configurations imbriquées et ciblées :

class GymManipulatorConfig:
    env: HILSerlRobotEnvConfig    # Environment configuration (nested)
    dataset: DatasetConfig    # Dataset recording/replay configuration (nested)
    mode: str | None = None    # "record", "replay", or None (for training)
    device: str = "cpu"    # Compute device

class HILSerlRobotEnvConfig(EnvConfig):
    robot: RobotConfig | None = None    # Main robot agent (defined in `lerobot/robots`)
    teleop: TeleoperatorConfig | None = None    # Teleoperator agent, e.g., gamepad or leader arm
    processor: HILSerlProcessorConfig    # Processing pipeline configuration (nested)
    name: str = "real_robot"    # Environment name
    task: str | None = None    # Task identifier
    fps: int = 30    # Control frequency

# Nested processor configuration
class HILSerlProcessorConfig:
    control_mode: str = "gamepad"    # Control mode
    observation: ObservationConfig | None = None    # Observation processing settings
    image_preprocessing: ImagePreprocessingConfig | None = None    # Image crop/resize settings
    gripper: GripperConfig | None = None    # Gripper control and penalty settings
    reset: ResetConfig | None = None    # Environment reset and timing settings
    inverse_kinematics: InverseKinematicsConfig | None = None    # IK processing settings
    reward_classifier: RewardClassifierConfig | None = None    # Reward classifier settings
    max_gripper_pos: float | None = 100.0    # Maximum gripper position

# Sub-configuration classes
class ObservationConfig:
    add_joint_velocity_to_observation: bool = False    # Add joint velocities to state
    add_current_to_observation: bool = False    # Add motor currents to state
    add_ee_pose_to_observation: bool = False    # Add end-effector pose to state
    display_cameras: bool = False    # Display camera feeds during execution

class ImagePreprocessingConfig:
    crop_params_dict: dict[str, tuple[int, int, int, int]] | None = None    # Image cropping parameters
    resize_size: tuple[int, int] | None = None    # Target image size

class GripperConfig:
    use_gripper: bool = True    # Enable gripper control
    gripper_penalty: float = 0.0    # Penalty for inappropriate gripper usage

class ResetConfig:
    fixed_reset_joint_positions: list[float] | None = None    # Joint positions for reset
    reset_time_s: float = 5.0    # Time to wait during reset
    control_time_s: float = 20.0    # Maximum episode duration
    terminate_on_success: bool = True    # Whether to terminate episodes on success detection

class InverseKinematicsConfig:
    urdf_path: str | None = None    # Path to robot URDF file
    target_frame_name: str | None = None    # End-effector frame name
    end_effector_bounds: dict[str, list[float]] | None = None    # EE workspace bounds
    end_effector_step_sizes: dict[str, float] | None = None    # EE step sizes per axis

class RewardClassifierConfig:
    pretrained_path: str | None = None    # Path to pretrained reward classifier
    success_threshold: float = 0.5    # Success detection threshold
    success_reward: float = 1.0    # Reward value for successful episodes

# Dataset configuration
class DatasetConfig:
    repo_id: str    # LeRobot dataset repository ID
    task: str    # Task identifier
    root: str | None = None    # Local dataset root directory
    num_episodes_to_record: int = 5    # Number of episodes for recording
    replay_episode: int | None = None    # Episode index for replay
    push_to_hub: bool = False    # Whether to push datasets to Hub

Architecture du pipeline de processeur

HIL-SERL utilise une architecture de pipeline de processeur modulaire qui traite les observations et les actions du robot à travers une série d'étapes composables. Le pipeline est divisé en deux composants principaux :

Pipeline de processeur d'environnement

Le processeur d'environnement (env_processor) gère les observations entrantes et l'état de l'environnement :

  1. VanillaObservationProcessorStep : convertit les observations brutes du robot en un format standardisé
  2. JointVelocityProcessorStep (facultatif) : ajoute des informations sur la vitesse des articulations aux observations
  3. MotorCurrentProcessorStep (facultatif) : ajoute les mesures de courant du moteur aux observations
  4. ForwardKinematicsJointsToEE (facultatif) : calcule la pose de l'effecteur final à partir des positions des articulations
  5. ImageCropResizeProcessorStep (facultatif) : recadre et redimensionne les images de la caméra
  6. TimeLimitProcessorStep (facultatif) : impose des limites de temps aux épisodes
  7. GripperPenaltyProcessorStep (facultatif) : applique des pénalités pour une utilisation inappropriée du gripper
  8. RewardClassifierProcessorStep (facultatif) : détection automatique des récompenses à l'aide de modèles de vision
  9. AddBatchDimensionProcessorStep : convertit les données au format de lot pour le traitement par réseau de neurones
  10. DeviceProcessorStep : Déplace les données vers le dispositif de calcul spécifié (CPU/GPU)

Pipeline de processeur d’actions

Le processeur d’actions (action_processor) gère les actions sortantes et les interventions humaines :

  1. AddTeleopActionAsComplimentaryDataStep : capture les actions de l’opérateur télécommandé pour les journaliser
  2. AddTeleopEventsAsInfoStep : enregistre les événements d'intervention et les signaux de contrôle d'épisode
  3. InterventionActionProcessorStep : Gère les interventions humaines et la fin des épisodes
  4. Inverse Kinematics Pipeline (lorsqu'il est activé) :
    • MapDeltaActionToRobotActionStep : convertit les actions delta au format d’action robot
    • EEReferenceAndDelta : Calcule les mouvements de référence et de delta de l'effecteur terminal
    • EEBoundsAndSafety : Applique les limites de sécurité de l’espace de travail
    • InverseKinematicsEEToJoints : Convertit les actions de l'effecteur terminal en cibles articulaires
    • GripperVelocityToJoint : Gère les commandes de contrôle de la pince

Exemples de configuration

Traitement de base des observations :

{
  "env": {
    "processor": {
      "observation": {
        "add_joint_velocity_to_observation": true,
        "add_current_to_observation": false,
        "display_cameras": false
      }
    }
  }
}

Prétraitement des images :

{
  "env": {
    "processor": {
      "image_preprocessing": {
        "crop_params_dict": {
          "observation.images.front": [180, 250, 120, 150],
          "observation.images.side": [180, 207, 180, 200]
        },
        "resize_size": [128, 128]
      }
    }
  }
}

Configuration de la cinématique inverse :

{
  "env": {
    "processor": {
      "inverse_kinematics": {
        "urdf_path": "path/to/robot.urdf",
        "target_frame_name": "end_effector",
        "end_effector_bounds": {
          "min": [0.16, -0.08, 0.03],
          "max": [0.24, 0.2, 0.1]
        },
        "end_effector_step_sizes": {
          "x": 0.02,
          "y": 0.02,
          "z": 0.02
        }
      }
    }
  }
}

Traitement avancé des observations

Le cadre HIL-SERL prend en charge des fonctionnalités supplémentaires de traitement des observations qui peuvent améliorer l'apprentissage de la politique :

Traitement de la vitesse articulaire

Activer l’estimation conjointe de la vitesse pour fournir des informations sur le mouvement à la politique :

{
  "env": {
    "processor": {
      "observation": {
        "add_joint_velocity_to_observation": true
      }
    }
  }
}

Ce processeur :

  • Estime les vitesses articulaires conjointes à l'aide de différences finies entre les lectures consécutives des positions articulaires
  • Ajoute les informations de vitesse au vecteur d'état d'observation
  • Utile pour les politiques qui nécessitent une prise en compte du mouvement pour des tâches dynamiques

Traitement du courant du moteur

Surveiller les courants moteurs pour détecter les forces de contact et les conditions de charge :

{
  "env": {
    "processor": {
      "observation": {
        "add_current_to_observation": true
      }
    }
  }
}

Ce processeur :

  • Lit les valeurs de courant moteur depuis le système de contrôle du robot
  • Ajoute les mesures actuelles au vecteur d'état d'observation
  • Aide à détecter les événements de contact, les poids des objets et la résistance mécanique
  • Utile pour les tâches de manipulation riches en contacts

Traitement combiné des observations

Vous pouvez activer plusieurs fonctionnalités de traitement des observations simultanément :

{
  "env": {
    "processor": {
      "observation": {
        "add_joint_velocity_to_observation": true,
        "add_current_to_observation": true,
        "display_cameras": false
      }
    }
  }
}

Note : L’activation de fonctionnalités d’observation supplémentaires augmente la dimensionnalité de l’espace d’état, ce qui peut nécessiter d’ajuster l’architecture de votre réseau de politique et, potentiellement, de collecter davantage de données d’entraînement.

Déterminer les limites de l'espace de travail du robot

Avant de collecter des démonstrations, vous devez déterminer les limites opérationnelles appropriées pour votre robot.

Cela contribue à simplifier le problème d’apprentissage sur le robot réel de deux manières : 1) en limitant l’espace opérationnel du robot à une région spécifique qui résout la tâche et évite toute exploration inutile ou dangereuse, et 2) en permettant l’entraînement dans l’espace de l’effecteur final plutôt que dans l’espace articulaire. Empiriquement, l’apprentissage dans l’espace articulaire pour le renforcement par apprentissage en manipulation est souvent un problème plus difficile - certaines tâches sont quasi impossibles à apprendre dans l’espace articulaire mais deviennent apprenables lorsque l’espace d’action est transformé en coordonnées de l’effecteur final.

Utilisation de lerobot-find-joint-limits

Ce script vous aide à déterminer les limites opérationnelles sûres de l’effecteur final de votre robot. Étant donné que vous disposez d’un bras suiveur et d’un bras leader, vous pouvez utiliser le script pour trouver les limites du bras suiveur qui seront appliquées pendant l’entraînement. Délimiter l’espace d’actions réduira l’exploration redondante de l’agent et garantit la sécurité.

lerobot-find-joint-limits \
  --robot.type=so100_follower \
  --robot.port=/dev/tty.usbmodem58760431541 \
  --robot.id=black \
  --teleop.type=so100_leader \
  --teleop.port=/dev/tty.usbmodem58760431551 \
  --teleop.id=blue \
  --urdf_path=SO-ARM100/Simulation/SO101/so101_new_calib.urdf \
  --target_frame_name=gripper

--urdf_path est obligatoire : il pointe vers le fichier URDF de votre robot, que le script utilise pour calculer la position de l'effecteur terminal. Pour le SO-100/SO-101, clonez le dépôt SO-ARM100 avec git clone https://github.com/TheRobotStudio/SO-ARM100.git ; l'URDF se trouve alors dans SO-ARM100/Simulation/SO101/so101_new_calib.urdf.

Flux de travail

  1. Exécutez le script et déplacez le robot dans l’espace qui résout la tâche

  2. Le script enregistre les positions minimale et maximale de l'effecteur terminal ainsi que les angles articulaires, et les affiche dans la console, par exemple :

    # End Effector Bounds (x, y, z):
    max_ee = [0.2417, 0.2012, 0.1027]
    min_ee = [0.1663, -0.0823, 0.0336]
    
    # Joint Position Limits (radians):
    max_pos = [...]
    min_pos = [...]
  3. Utilisez ces valeurs dans votre configuration d’environnement sous env.processor.inverse_kinematics.end_effector_bounds (voir InverseKinematicsConfig dans lerobot/envs/configs.py)

Exemple de configuration

{
  "env": {
    "processor": {
      "inverse_kinematics": {
        "end_effector_bounds": {
          "max": [0.24, 0.2, 0.1],
          "min": [0.16, -0.08, 0.03]
        }
      }
    }
  }
}

Collecte de démonstrations

Une fois les bornes définies, vous pouvez collecter en toute sécurité des démonstrations pour l’entraînement. L’entraînement par renforcement avec un algorithme hors politique nous permet d’utiliser des jeux de données hors ligne collectés à cet effet afin d’améliorer l’efficacité du processus d’apprentissage.

Configuration du mode d’enregistrement

Les fichiers de configuration d’exemple pour ce guide se trouvent dans le jeu de données lerobot/config_examples sur le Hub. Téléchargez les configurations d’environnement et d’entraînement dans votre répertoire de travail :

hf download lerobot/config_examples rl/env_config.json rl/train_config.json --repo-type dataset --local-dir .

Cela les enregistre dans rl/env_config.json et rl/train_config.json, les chemins utilisés dans les commandes ci-dessous. Modifiez rl/env_config.json pour enregistrer des démonstrations :

  1. Définissez mode sur "record" au niveau racine
  2. Spécifiez un repo_id unique pour votre jeu de données dans la section dataset (par exemple, « username/task_name »)
  3. Définissez num_episodes_to_record dans la section dataset sur le nombre de démonstrations que vous souhaitez collecter
  4. Définissez env.processor.image_preprocessing.crop_params_dict sur {} au départ (nous déterminerons les recadrages plus tard)
  5. Configurez env.robot, env.teleop et les autres paramètres matériels dans la section env

Exemple de section de configuration :

{
  "env": {
    "type": "gym_manipulator",
    "name": "real_robot",
    "fps": 10,
    "processor": {
      "control_mode": "gamepad",
      "observation": {
        "display_cameras": false
      },
      "image_preprocessing": {
        "crop_params_dict": {},
        "resize_size": [128, 128]
      },
      "gripper": {
        "use_gripper": true,
        "gripper_penalty": 0.0
      },
      "reset": {
        "reset_time_s": 5.0,
        "control_time_s": 20.0
      }
    },
    "robot": {
      // ... robot configuration ...
    },
    "teleop": {
      // ... teleoperator configuration ...
    }
  },
  "dataset": {
    "repo_id": "username/pick_lift_cube",
    "root": null,
    "task": "pick_and_lift",
    "num_episodes_to_record": 15,
    "replay_episode": 0,
    "push_to_hub": true
  },
  "mode": "record",
  "device": "cpu"
}

Utiliser un appareil de téléopération

En plus de votre robot, vous aurez besoin d'un dispositif de téléopération pour le contrôler afin de collecter des jeux de données de votre tâche et d'effectuer des interventions pendant l'entraînement en ligne. Nous prenons en charge l'utilisation d'une manette de jeu, d'un clavier ou du bras leader du robot.

HIL-Serl apprend les actions dans l’espace de l’effecteur terminal du robot. Par conséquent, la téléopération contrôlera les déplacements x, y, z de l’effecteur terminal.

La transformation de l'effecteur terminal est appliquée par le pipeline de processeur (InverseKinematicsRLStep, EEBoundsAndSafety, EEReferenceAndDelta, GripperVelocityToJoint) configuré sous env.processor.inverse_kinematics (InverseKinematicsConfig) et env.processor.gripper / env.processor.max_gripper_pos. Les valeurs par défaut liées à l'espace de l'effecteur terminal sont :

class InverseKinematicsConfig:
    """Configuration for inverse kinematics processing."""

    urdf_path: str | None = None
    target_frame_name: str | None = None
    # bounds for the end-effector in x,y,z direction
    end_effector_bounds: dict[str, list[float]] | None = None
    # maximum step size for the end-effector in x,y,z direction
    end_effector_step_sizes: dict[str, float] | None = None

class HILSerlProcessorConfig:
    ...
    # maximum gripper position that the gripper will be open at
    max_gripper_pos: float | None = 100.0

Le Teleoperator définit l'appareil de téléopération. Vous pouvez consulter la liste des téléopérateurs disponibles dans lerobot/teleoperators.

Configurer la manette de jeu

La manette de jeu offre un moyen très pratique de contrôler le robot et l'état de l'épisode.

Pour configurer la manette de jeu, vous devez définir control_mode sur "gamepad" et définir la section teleop dans le fichier de configuration.

{
  "env": {
    "teleop": {
      "type": "gamepad",
      "use_gripper": true
    },
    "processor": {
      "control_mode": "gamepad",
      "gripper": {
        "use_gripper": true
      }
    }
  }
}

Figure shows the control mappings on a Logitech gamepad.

Cartographie des boutons de la manette pour le contrôle du robot et la gestion des épisodes

Configuration du leader SO101

Le bras leader du SO101 est équipé de réducteurs qui lui permettent de se déplacer et de suivre le bras suiveur pendant l'exploration. Par conséquent, la reprise de contrôle est beaucoup plus fluide que sur le SO100, qui n'en est pas doté.

Pour configurer le leader SO101, vous devez définir control_mode sur "leader" et définir la section teleop dans le fichier de configuration.

{
  "env": {
    "teleop": {
      "type": "so101_leader",
      "port": "/dev/tty.usbmodem585A0077921",
      "use_degrees": true
    },
    "processor": {
      "control_mode": "leader",
      "gripper": {
        "use_gripper": true
      }
    }
  }
}

Pour annoter le succès ou l’échec de l’épisode, vous devrez utiliser un clavier pour appuyer sur s en cas de succès et sur esc en cas d’échec. Pendant l’entraînement en ligne, appuyez sur space pour prendre le contrôle de la politique, puis sur space à nouveau pour rendre le contrôle à la politique.

Video: SO101 leader teleoperation

Exemple de téléopération leader SO101, le leader suit le suiveur, appuyez sur `space` pour intervenir

Enregistrement de démonstrations

Démarrez le processus d'enregistrement avec la configuration de l'environnement que vous avez modifiée ci-dessus :

python -m lerobot.rl.gym_manipulator --config_path rl/env_config.json

Pendant l'enregistrement :

  1. Le robot reviendra à la position initiale définie dans le fichier de configuration env.processor.reset.fixed_reset_joint_positions
  2. Réussir la tâche
  3. L'épisode se termine avec une récompense de 1 lorsque vous appuyez sur le bouton « success »
  4. Si la limite de temps est atteinte ou si le bouton d'échec est appuyé, l'épisode se termine avec une récompense de 0
  5. Vous pouvez réenregistrer un épisode en appuyant sur le bouton « réenregistrer »
  6. Le processus passe automatiquement à l'épisode suivant
  7. Après l'enregistrement de tous les épisodes, le jeu de données est poussé vers le Hugging Face Hub (facultatif) et enregistré localement

Traitement du jeu de données

Après avoir collecté les démonstrations, traitez-les pour déterminer les recadrages de caméra optimaux. L'apprentissage par renforcement est sensible aux distractions en arrière-plan, il est donc important de recadrer les images sur la zone de travail pertinente.

Les algorithmes de RL visuel apprennent directement à partir des entrées en pixels, ce qui les rend vulnérables aux informations visuelles non pertinentes. Des éléments d'arrière-plan tels que des changements d'éclairage, des ombres, des personnes en mouvement ou des objets hors de l'espace de travail peuvent perturber le processus d'apprentissage. Une bonne sélection de ROI doit :

  • N'inclure que l'espace de travail essentiel où la tâche est exécutée
  • Capturer l'effecteur terminal du robot et tous les objets impliqués dans la tâche
  • Exclure les éléments de fond et les distractions inutiles

Note : Si vous connaissez déjà les paramètres de recadrage, vous pouvez passer cette étape et définir directement crop_params_dict dans le fichier de configuration lors de l'enregistrement.

Détermination des paramètres de recadrage

Utilisez le script crop_dataset_roi.py pour sélectionner de manière interactive les régions d'intérêt dans vos images de caméra :

python -m lerobot.rl.crop_dataset_roi --repo-id username/pick_lift_cube
  1. Pour chaque vue de caméra, le script affichera la première image
  2. Dessinez un rectangle autour de la zone de travail concernée
  3. Appuyez sur « c » pour confirmer la sélection
  4. Répétez pour toutes les vues de la caméra
  5. Le script affiche les paramètres de recadrage et crée un nouveau jeu de données recadré

Exemple de sortie :

Selected Rectangular Regions of Interest (top, left, height, width):
observation.images.side: [180, 207, 180, 200]
observation.images.front: [180, 250, 120, 150]

Outil de recadrage interactif pour sélectionner des régions d'intérêt

Mise à jour de la configuration

Ajoutez ces paramètres de recadrage à votre configuration d’entraînement :

{
  "env": {
    "processor": {
      "image_preprocessing": {
        "crop_params_dict": {
          "observation.images.side": [180, 207, 180, 200],
          "observation.images.front": [180, 250, 120, 150]
        },
        "resize_size": [128, 128]
      }
    }
  }
}

Résolution d'image recommandée

La plupart des politiques basées sur la vision ont été validées sur des entrées carrées de 128×128 (par défaut) ou de 64×64 pixels. Nous recommandons donc de définir le paramètre resize_size sur [128, 128] – ou sur [64, 64] si vous devez économiser la mémoire et la bande passante du GPU. D'autres résolutions sont possibles mais n'ont pas été testées de manière exhaustive.

Entraîner un classifieur de récompense

Le classifieur de récompense joue un rôle important dans le flux de travail HIL-SERL en automatisant l’attribution des récompenses et la détection automatique du succès des épisodes. Plutôt que de définir manuellement des fonctions de récompense ou de s’appuyer sur des retours humains à chaque pas de temps, le classifieur de récompense apprend à prédire le succès ou l’échec à partir des observations visuelles. Cela permet à l’algorithme d’apprentissage par renforcement d’apprendre efficacement en fournissant des signaux de récompense cohérents et automatisés, basés sur les entrées de la caméra du robot.

Ce guide explique comment entraîner un classifieur de récompense pour une implémentation du renforcement humain dans la boucle (human-in-the-loop) de LeRobot. Les classifieurs de récompense apprennent à prédire la valeur de la récompense à partir d'un état, ce qui peut être utilisé dans un cadre RL pour entraîner une politique.

Note : L’entraînement d’un classifieur de récompense est facultatif. Vous pouvez lancer la première série d’expériences RL en annotant manuellement le succès à l’aide de votre manette ou de votre clavier.

L'implémentation du classifieur de récompense dans lerobot/rewards/classifier/modeling_classifier.py utilise un modèle de vision préentraîné pour traiter les images. Il peut produire une seule valeur pour les récompenses binaires afin de prédire les cas de succès/échec, ou plusieurs valeurs pour les configurations multi-classes.

Collecter un jeu de données pour le classifieur de récompense

Avant l’entraînement, vous devez collecter un jeu de données avec des exemples étiquetés. Définir mode: "record" dans votre configuration et exécuter gym_manipulator.py permet de lancer le processus de collecte d’un jeu de données d’observations, d’actions et de récompenses.

Pour collecter un jeu de données, vous devez modifier certains paramètres dans la configuration de l'environnement basée sur HILSerlRobotEnvConfig.

python -m lerobot.rl.gym_manipulator --config_path rl/env_config.json

Paramètres clés pour la collecte de données

  • mode : définissez-le sur "record" pour collecter un jeu de données (au niveau racine)
  • dataset.repo_id : "hf_username/dataset_name", nom du jeu de données et du dépôt sur le hub
  • dataset.num_episodes_to_record : Nombre d'épisodes à enregistrer
  • env.processor.reset.terminate_on_success : Indique s'il faut terminer automatiquement les épisodes lorsque le succès est détecté (par défaut : true)
  • env.fps : Nombre d'images par seconde à enregistrer
  • dataset.push_to_hub : Indique s'il faut pousser le jeu de données vers le hub

Le paramètre env.processor.reset.terminate_on_success permet de contrôler le comportement de fin d'épisode. Lorsqu'il est défini sur false, les épisodes se poursuivent même après la détection d'un succès, ce qui permet de collecter davantage d'exemples positifs avec l'étiquette reward=1. C'est essentiel pour l'entraînement des classifieurs de récompense, car cela fournit plus d'exemples d'états de succès dans votre jeu de données. Lorsqu'il est défini sur true (par défaut), les épisodes se terminent immédiatement dès la détection d'un succès.

Important : Pour l’entraînement du classifieur de récompense, définissez terminate_on_success: false afin de collecter un nombre suffisant d’exemples positifs. Pour l’entraînement HIL-SERL standard, conservez la valeur true pour activer la terminaison automatique de l’épisode lorsque la tâche est accomplie avec succès.

Exemple de section de configuration pour la collecte de données :

{
  "env": {
    "type": "gym_manipulator",
    "name": "real_robot",
    "fps": 10,
    "processor": {
      "reset": {
        "reset_time_s": 5.0,
        "control_time_s": 20.0,
        "terminate_on_success": false
      },
      "gripper": {
        "use_gripper": true
      }
    },
    "robot": {
      // ... robot configuration ...
    },
    "teleop": {
      // ... teleoperator configuration ...
    }
  },
  "dataset": {
    "repo_id": "hf_username/dataset_name",
    "root": "data/your_dataset",
    "task": "reward_classifier_task",
    "num_episodes_to_record": 20,
    "replay_episode": null,
    "push_to_hub": true
  },
  "mode": "record",
  "device": "cpu"
}

Configuration du classificateur de récompense

Le classifieur de récompense est configuré à l'aide de lerobot/rewards/classifier/configuration_classifier.py. Voici les principaux paramètres :

  • model_name : Architecture du modèle de base (par exemple, nous utilisons principalement "helper2424/resnet10")
  • model_type : "cnn" ou "transformer"
  • num_cameras : Nombre d'entrées caméra
  • num_classes : Nombre de classes de sortie (généralement 2 pour un succès/échec binaire)
  • hidden_dim : Taille de la représentation cachée
  • dropout_rate : Paramètre de régularisation
  • learning_rate : Taux d'apprentissage de l'optimiseur

Exemple de configuration pour l'entraînement du classifieur de récompense. Enregistrez-le sous le nom reward_classifier_train_config.json :

{
  "dataset": {
    "repo_id": "hf_username/dataset_name",
    "root": null
  },
  "reward_model": {
    "type": "reward_classifier",
    "model_name": "helper2424/resnet10",
    "model_type": "cnn",
    "num_cameras": 2,
    "num_classes": 2,
    "hidden_dim": 256,
    "dropout_rate": 0.1,
    "learning_rate": 1e-4,
    "device": "cuda",
    "input_features": {
      "observation.images.front": {
        "type": "VISUAL",
        "shape": [3, 128, 128]
      },
      "observation.images.side": {
        "type": "VISUAL",
        "shape": [3, 128, 128]
      }
    },
    "push_to_hub": true,
    "repo_id": "hf_username/model_repo"
  },
  "batch_size": 16,
  "num_workers": 4,
  "steps": 5000,
  "log_freq": 10,
  "env_eval_freq": 1000,
  "save_freq": 1000,
  "save_checkpoint": true,
  "seed": 2,
  "resume": false,
  "optimizer": {
    "grad_clip_norm": 10.0
  },
  "trackio": {
    "enable": true,
    "project": "reward-classifier"
  },
  "job_name": "reward-classifier"
}

Entraînement du classifieur

Pour entraîner le classifieur, utilisez le script train.py avec votre configuration :

lerobot-train --config_path reward_classifier_train_config.json

Déploiement et test du modèle

Pour utiliser votre classifieur de récompense entraîné, configurez HILSerlRobotEnvConfig afin d'utiliser votre modèle :

config = GymManipulatorConfig(
    env=HILSerlRobotEnvConfig(
        processor=HILSerlProcessorConfig(
            reward_classifier=RewardClassifierConfig(
                pretrained_path="path_to_your_pretrained_trained_model"
            )
        ),
        # Other environment parameters
    ),
    dataset=DatasetConfig(...),
    mode=None  # For training
)

ou définir l'argument dans le fichier de configuration json.

{
  "env": {
    "processor": {
      "reward_classifier": {
        "pretrained_path": "path_to_your_pretrained_model",
        "success_threshold": 0.7,
        "success_reward": 1.0
      },
      "reset": {
        "terminate_on_success": true
      }
    }
  }
}

Exécutez gym_manipulator.py pour tester le modèle.

python -m lerobot.rl.gym_manipulator --config_path rl/env_config.json

Le classifieur de récompense fournira automatiquement des récompenses en fonction de l'entrée visuelle provenant des caméras du robot.

Exemple de flux de travail pour l’entraînement du classifieur de récompense

  1. Créer les fichiers de configuration : Créez les fichiers de configuration json nécessaires pour le classifieur de récompense et l’environnement : reward_classifier_train_config.json à partir de l’exemple ci-dessus, et le rl/env_config.json téléchargé.

  2. Collecter un jeu de données :

    python -m lerobot.rl.gym_manipulator --config_path rl/env_config.json
  3. Entraîner le classifieur :

    lerobot-train --config_path reward_classifier_train_config.json
  4. Tester le classifieur :

    python -m lerobot.rl.gym_manipulator --config_path rl/env_config.json

Entraînement avec Actor-Learner

Le système LeRobot utilise une architecture distribuée acteur-apprenant pour l'entraînement. Cette architecture découple les interactions du robot du processus d'apprentissage, permettant à ces deux éléments de s'exécuter de manière concurrente sans se bloquer mutuellement. Le serveur acteur gère les observations et les actions du robot, et envoie les données d'interaction au serveur apprenant. Le serveur apprenant effectue la descente de gradient et met à jour périodiquement les poids de la politique de l'acteur. Vous devrez démarrer deux processus : un apprenant et un acteur.

Configuration de la configuration

Modifiez le fichier de configuration d’entraînement téléchargé précédemment, rl/train_config.json (exemple disponible ici). La configuration d’entraînement est basée sur la classe principale TrainRLServerPipelineConfig dans lerobot/rl/train_rl.py.

  1. Configurez les paramètres de la politique (type="gaussian_actor", device, etc.)
  2. Configurez les paramètres de l’algorithme sous le bloc de niveau supérieur algorithm (type="sac", taux d’apprentissage, facteur d’actualisation, etc., définis dans lerobot/rl/algorithms/sac/configuration_sac.py).
  3. Définissez dataset sur votre jeu de données rogné
  4. Configurer les paramètres de l’environnement avec les paramètres de recadrage
  5. Vérifiez les autres paramètres liés à l'acteur gaussien dans configuration_gaussian_actor.py.
  6. Vérifiez que la configuration policy est correcte avec les input_features et output_features appropriés pour votre tâche.

Démarrage du Learner

Premièrement, démarrez le processus du serveur d'apprentissage :

python -m lerobot.rl.learner --config_path rl/train_config.json

L'apprenant :

  • Initialise le réseau de politique
  • Prépare les tampons de lecture
  • Ouvre un serveur gRPC pour communiquer avec les acteurs
  • Traite les transitions et met à jour la politique

Démarrage de l'Actor

Dans un terminal séparé, démarrez le processus acteur avec la même configuration :

python -m lerobot.rl.actor --config_path rl/train_config.json

L'acteur :

  • Se connecte à l'apprenant via gRPC
  • Initialise l'environnement
  • Exécuter des déroulements de la politique pour collecter de l'expérience
  • Envoie les transitions à l'apprenant
  • Reçoit les paramètres de politique mis à jour

Flux d'entraînement

L'entraînement se déroule automatiquement :

  1. L'acteur exécute la politique dans l'environnement
  2. Les transitions sont collectées et envoyées à l'apprenant
  3. L'apprenant met à jour la politique sur la base de ces transitions
  4. Les paramètres de politique mis à jour sont renvoyés à l'acteur
  5. Le processus se poursuit jusqu'à ce que la limite d'étapes spécifiée soit atteinte

Humain dans la boucle

  • La clé pour apprendre efficacement est de disposer d'interventions humaines fournissant un retour correctif et complétant la tâche, afin d'aider l'apprentissage de la politique et l'exploration.
  • Pour effectuer des interventions humaines, vous pouvez appuyer sur le bouton de gâchette supérieur droit de la manette (ou sur la touche space du clavier). Cela mettra les actions de la politique en pause et vous permettra de prendre le contrôle.
  • Une expérience réussie est celle où l’humain doit intervenir au début, puis réduit le nombre d’interventions au fur et à mesure que la politique s’améliore. Vous pouvez suivre le taux d’intervention dans le tableau de bord Trackio (trackio show --project <project>).

Figure shows the control mappings on a Logitech gamepad.

Exemple montrant comment les interventions humaines aident à guider l'apprentissage de la politique au fil du temps

  • La figure montre le tracé de la récompense épisodique en fonction de l'étape d'interaction. La figure montre l'effet des interventions humaines sur l'apprentissage de la politique.
  • La courbe orange correspond à une expérience sans aucune intervention humaine. Les courbes rose et bleue, en revanche, correspondent à des expériences avec des interventions humaines.
  • Nous pouvons observer que le nombre d'étapes à partir desquelles la politique commence à atteindre la récompense maximale est réduit d'un quart lorsque des interventions humaines sont présentes.

Surveillance et débogage

Si vous avez défini trackio.enable sur true dans votre configuration, vous pouvez suivre la progression de l’entraînement en temps réel via le tableau de bord Trackio (trackio show --project <project>).

Guide des interventions humaines

Le processus d'apprentissage est très sensible à la stratégie d'intervention. Il faudra plusieurs exécutions pour comprendre comment intervenir efficacement. Quelques conseils et astuces :

  • Autoriser la politique à explorer pendant quelques épisodes au début de l'entraînement.
  • Évitez d'intervenir pendant de longues périodes. Essayez d'intervenir dans la situation pour corriger le comportement du robot lorsqu'il s'écarte de la trajectoire prévue.
  • Une fois que la politique commence à accomplir la tâche, même si ce n'est pas parfait, vous pouvez limiter vos interventions à de simples actions rapides, comme des commandes de préhension simples.

Le comportement idéal est que votre taux d'intervention diminue progressivement au cours de l'entraînement, comme le montre la figure ci-dessous.

Intervention rate

Représentation du taux d'intervention au cours d'une exécution d'entraînement sur une tâche de prise et d'élévation d'un cube

Hyperparamètres clés à ajuster

Certaines valeurs de configuration ont un impact disproportionné sur la stabilité et la vitesse de l'entraînement :

  • temperature_init (algorithm.temperature_init) – température d'entropie initiale dans SAC. Des valeurs plus élevées encouragent davantage l'exploration ; des valeurs plus basses rendent la politique plus déterministe au début. Un bon point de départ est 1e-2. Nous avons observé que le définir trop haut peut rendre les interventions humaines inefficaces et ralentir l'apprentissage.
  • policy_parameters_push_frequency (policy.actor_learner_config.policy_parameters_push_frequency) – intervalle en secondes entre deux poussées de poids du learner vers l’actor. La valeur par défaut est 4 s. Diminuez à 1-2 s pour fournir des poids plus récents (au prix d’un trafic réseau accru) ; n’augmentez que si votre connexion est lente, car cela réduira l’efficacité des échantillons.
  • storage_device (policy.storage_device) – périphérique sur lequel l’apprenant conserve les paramètres de la politique. Si vous disposez de mémoire GPU supplémentaire, définissez cette valeur sur "cuda" (au lieu de la valeur par défaut "cpu"). Conserver les poids sur le GPU supprime le surcoût de transfert CPU→GPU et peut augmenter considérablement le nombre de mises à jour de l’apprenant par seconde.

Félicitations 🎉, vous avez terminé ce tutoriel !

Si vous avez des questions ou besoin d'aide, n'hésitez pas à nous contacter sur Discord.

Citation de l'article :

@article{luo2024precise,
  title={Precise and Dexterous Robotic Manipulation via Human-in-the-Loop Reinforcement Learning},
  author={Luo, Jianlan and Xu, Charles and Wu, Jeffrey and Levine, Sergey},
  journal={arXiv preprint arXiv:2410.21845},
  year={2024}
}
Update on GitHub