La page de guide AY-Robots pour l'entraînement de GR00T N1.7 sur un bras SO-100, montrant le niveau de GPU requis, le format du jeu de données et les paramètres par défaut de l'entraîneur
GR00T N1.7SO-100AffinementLeRobotVLA

Comment entraîner GR00T N1.7 sur votre propre jeu de données SO-100

AY-Robots ResearchAugust 23, 202628 min de lecture

Un guide testé pour l'affinement de NVIDIA GR00T N1.7 sur un jeu de données LeRobot SO-100 : les vrais drapeaux, modality.json, l'exigence v2.1, le coût d'une exécution et les pièges.

NVIDIA fournit un exemple de réglage fin pour exactement le bras que vous possédez probablement. Dans le dépôt Isaac-GR00T, il y a un dossier appelé demo_data/cube_to_bowl_5 : cinq épisodes, 4 148 images à 30 ips, déjà écrits au format LeRobot v2.1, avec une configuration de modalité correspondante sous examples/SO100/. Son meta/info.json rapporte robot_type: so101_follower, qui dans LeRobot est la même classe de configuration que so100_follower. C'est vraiment utile, car cela signifie que le chemin de référence pour GR00T N1.7 sur un bras de loisir à six degrés de liberté est maintenu par les personnes qui ont écrit le modèle. Ce n'est pas une démo humanoïde réduite, c'est le même bras.

La mauvaise nouvelle est la distance entre I recorded 60 episodes et the arm does the task. Il y a environ six endroits où ce pipeline échoue silencieusement plutôt que bruyamment, et quatre d'entre eux se trouvent dans des fichiers que la plupart des gens n'ouvrent jamais : meta/modality.json, la configuration des données Python, meta/relative_stats.json, et la chaîne de version propre au jeu de données. Ce guide parcourt la voie manuelle de bout en bout avec les commandes réelles, puis montre le même travail sous forme de formulaire sur AY-Robots. Tout ce qui suit a été vérifié par rapport à la branche principale d'Isaac-GR00T au 20 août 2026 (la ligne de version n1.7-release) et à lerobot 0.6.1, publié sur PyPI le 3 août 2026. L'amont évolue rapidement, et si un drapeau a été renommé, cet article le mentionne.

Ce qu'il faut savoir avant de commencer

  • Le réglage fin de GR00T N1.7 nécessite 40 Go ou plus de VRAM. NVIDIA recommande des nœuds H100 ou L40. Une RTX 4090 de 24 Go ne fera pas ce travail, bien qu'elle puisse entraîner SmolVLA et ACT.
  • Le jeu de données doit être LeRobot v2 (v2.0 ou v2.1) plus un meta/modality.json spécifique à GR00T. Un jeu de données LeRobot v3.0 ne se charge pas et doit être converti à une version antérieure.
  • Le point d'entrée est gr00t/experiment/launch_finetune.py, une interface CLI tyro. Il n'a pas de drapeau --seed, donc les exécutions ne sont pas reproductibles bit par bit.
  • Pour un bras personnalisé, le tag d'embodiment est NEW_EMBODIMENT, et ce tag rend --modality-config-path obligatoire.
  • La recette SO-100 fournie prédit les articulations du bras comme des deltas RELATIFS et le préhenseur comme une cible ABSOLUE. Inverser cet appariement est un échec silencieux, pas une erreur.
  • Sur AY-Robots, le même travail est un formulaire : 20000 étapes, batch 32, taux d'apprentissage 1e-4, environ 4 à 12 USD sur le niveau A100 80 Go ou H100.

Ce qu'est réellement GR00T N1.7

GR00T N1.7 est un modèle vision-langage-action avec l'architecture à double système décrite dans le document original GR00T N1 : un module vision-langage qui lit les caméras et l'instruction, et un transformeur de diffusion qui transforme cela en un bloc de commandes motrices continues. N1.7 a remplacé la première moitié. Le backbone Eagle de N1.6 a disparu, remplacé par nvidia/Cosmos-Reason2-2B sur une architecture Qwen3-VL, et le modèle a été pré-entraîné sur environ 20 000 heures de vidéo humaine égocentrique en plus des données du robot. Le propre rapport de NVIDIA indique le chiffre de 20 854 heures et rapporte que passer de 1k à 20k heures fait plus que doubler le taux moyen d'achèvement des tâches.

La seconde moitié a également changé, d'une manière qui compte pour votre exécution. La tête d'action est passée de 32 couches de diffusion à 16, le bloc d'action est passé de 16 à 40 étapes, et la largeur maximale d'état et d'action est passée de 29 à 132. Ces trois chiffres proviennent du journal des modifications dans le README du dépôt ; le propre article de lancement de NVIDIA décrit toujours le Système 1 comme un DiT à 32 couches, donc là où les deux sont en désaccord, faites confiance au dépôt que vous êtes sur le point de cloner. Les actions sont exprimées par défaut dans un espace effecteur final relatif, des deltas par rapport à la pose actuelle plutôt que des cibles absolues, ce qui permet aux priors de manipulation appris à partir de vidéos humaines de se transférer dans le contrôle du robot. La tête elle-même est un transformeur de diffusion flow-matching, de la même famille que Pi0.5 mais avec un backbone différent devant. Si vous êtes toujours sur la génération précédente, N1.7 comparé à N1.5 explique si la mise à niveau justifie de refaire votre pipeline.

PropriétéValeurSource
Paramètres3,000,000,000Fiche modèle Hugging Face
Backbone vision-langagenvidia/Cosmos-Reason2-2B (Qwen3-VL), gated on Hugging FaceREADME du dépôt
Tête d'actionTransformeur de diffusion flow-matching, 16 couches (N1.6 en avait 32)README du dépôt
Horizon d'action prédit40 steps for the base checkpoint (N1.6 en avait 16)getting_started/policy.md et README du dépôt
Largeur max. état et action132 (N1.6 en avait 29)README du dépôt
Licence du codeApache 2.0Dépôt Isaac-GR00T
Licence des poidsNVIDIA Open Model License AgreementFiche modèle
Latence, H100 80 GB, PyTorch eager, 4 étapes de débruitage, 1 caméra85.8 ms de bout en bout, 11.7 HzTableau de temps de la fiche modèle
Même matériel, pipeline complet TensorRT27.9 ms de bout en bout, 35.9 HzTableau de temps de la fiche modèle
Latence citée par AY-Robots pour son GR00T N1.7 servi152 ms par étape d'actionCatalogue de politiques AY-Robots

Ces trois dernières lignes expliquent la majeure partie de la déception rapportée par les utilisateurs. Le chiffre principal de 27.9 ms correspond à un moteur TensorRT sur un H100 avec une caméra et quatre étapes de débruitage. PyTorch pur sur la même carte est de 85.8 ms, et la fiche modèle indique un écart de 3.08x. Aucun de ces chiffres n'inclut une couche de service, une deuxième caméra ou un saut de réseau. Les 152 ms par étape d'action citées par AY-Robots pour son GR00T N1.7 servi sont le chiffre avec le service en boucle, et un aller-retour sur internet public s'ajoute à cela. Plus de détails à ce sujet à la fin. Pour les chiffres comparés à d'autres modèles, GR00T N1.7 comparé à Pi0.5 et GR00T N1.7 comparé à SmolVLA les présentent côte à côte.

La page du modèle AY-Robots pour GR00T N1.7 montrant le nombre de paramètres, le niveau de GPU, la latence d'inférence et les forces et limites déclarées du modèle
La page /policies/groot-n1-7 contient la même bande de spécifications que vous assemblereriez autrement à la main à partir de la carte du modèle et du README du dépôt.

Ce dont l'exécution a besoin avant de taper quoi que ce soit

ExigenceFine-tuningInférence
VRAM, recommandations NVIDIA40 Go ou plus, H100 ou L40 recommandé16 Go ou plus, une RTX 4090 fonctionne
Python et CUDA sur dGPU3.12 et CUDA 12.83.12 et CUDA 12.8
Backend vidéotorchcodec 0.8.0, FFmpeg 4 à 7 seulementidem
Format du jeu de donnéesLeRobot v2 plus meta/modality.jsonnon applicable
Accès Hugging Faceapprouvé pour nvidia/Cosmos-Reason2-2Bidem
Autres outilsgit-lfs et uvuv
Niveau de GPU AY-Robots pour l'entraîneur groot1.7A100 80 Go ou H100 80 Gopod provisionné automatiquement
Le backbone à accès restreint vous arrêtera dès la première exécution

Chaque checkpoint GR00T, y compris la base nvidia/GR00T-N1.7-3B, charge nvidia/Cosmos-Reason2-2B lors de la première utilisation, et ce dépôt est à accès restreint. Le README indique l'échec exact : le chargement du modèle échoue avec une GatedRepoError / 401 Client Error. Ce qu'il ne mentionne pas, c'est quand cela se produit, c'est-à-dire après que vous ayez loué la carte et que l'exécution ait commencé. Demandez l'accès sur la page du modèle, puis exécutez uv run huggingface-cli login ou exportez HF_TOKEN avant de louer quoi que ce soit.

Étape 0 : les épisodes eux-mêmes

Tout ce qui suit suppose que vous avez déjà enregistré des épisodes. Si ce n'est pas le cas, c'est la véritable première étape et c'est celle qui détermine la qualité du résultat, car l'apprentissage par imitation ne peut pas récupérer les informations qui ne sont pas dans les données. Calibrez d'abord les deux bras, puis pilotez le bras suiveur avec un bras leader pendant que lerobot-record écrit les fichiers parquet et les flux de caméra. Si le calibrage est incorrect, les valeurs articulaires de votre ensemble de données décrivent un robot légèrement différent de celui qui exécutera la politique plus tard, et aucune quantité d'entraînement ne peut corriger cela.

bash
lerobot-record \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --robot.id=my_follower_arm \
    --robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, wrist: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30}}" \
    --teleop.type=so100_leader \
    --teleop.port=/dev/ttyACM1 \
    --teleop.id=my_leader_arm \
    --dataset.repo_id=${HF_USER}/cube-into-bowl \
    --dataset.num_episodes=60 \
    --dataset.single_task="put the cube in the yellow bowl" \
    --display_data=true
lerobot-record sur un LeRobot actuel. La durée par défaut d'un épisode est de 60 s et le temps de réinitialisation de 60 s. so100_follower et so101_follower sont tous deux enregistrés avec la même classe de configuration LeRobot, c'est pourquoi l'exemple Isaac-GR00T SO100 utilise les noms so101 ; les deux fonctionnent sur un SO-100. Les noms de caméra que vous choisissez ici (front, wrist) sont les noms qui doivent réapparaître dans modality.json.

Le conseil de LeRobot est d'enregistrer au moins 50 épisodes avec environ 10 par emplacement d'objet, de garder les caméras fixes et de maintenir un comportement de préhension cohérent. Ajoutez de la variation plus tard, pas au début. La règle d'or à retenir : si vous ne pouviez pas accomplir la tâche vous-même à partir des seules images de la caméra, la politique ne le pourra pas non plus. Pour la configuration spécifique au bras, le guide de démarrage du SO-100 et la page LeRobot du SO-100 couvrent les ports, le calibrage et les indices de caméra. Sur AY-Robots, vous pouvez également le faire via Internet depuis le navigateur en utilisant la téléopération et enregistrer directement depuis la session.

Étape 1 : le jeu de données doit être LeRobot v2.1

C'est l'obstacle le plus courant. La CODEBASE_VERSION actuelle de LeRobot sur main est la v3.0, donc tout ce que vous enregistrez aujourd'hui avec une chaîne d'outils actuelle sort en v3.0. Le chargeur de GR00T s'attend à la v2. Le dépôt est explicite sur la raison : de nombreux jeux de données en amont tels que DROID, LIBERO et Bridge sont publiés en v2, et le support natif pour les deux est prévu mais pas encore livré. La conversion vous incombe donc, et elle s'exécute dans son propre virtualenv pour une raison concrète : scripts/lerobot_conversion contient son propre pyproject qui demande Python 3.10 ou 3.11 et épingle lerobot à un commit git, tandis qu'Isaac-GR00T lui-même nécessite Python 3.12. Installez le convertisseur depuis la racine du dépôt et vous obtiendrez le package gr00t à la place, ce qui est l'erreur contre laquelle son README met en garde. Si vous débutez avec le format, l'entrée de glossaire Jeu de données LeRobot explique ce qu'il contient réellement.

bash
# from the Isaac-GR00T repo root
cd scripts/lerobot_conversion
uv venv
source .venv/bin/activate
uv pip install -e . --verbose

# pulls the dataset from the Hub and writes a v2.1 copy into the default cache
python convert_v3_to_v2.py --repo-id <your-hf-user>/<your-dataset>

# or, back in the repo root, keep it next to the SO-100 example
uv run --project scripts/lerobot_conversion \
  python scripts/lerobot_conversion/convert_v3_to_v2.py \
  --repo-id <your-hf-user>/<your-dataset> \
  --root examples/SO100/my_dataset_lerobot
Le convertisseur prend --repo-id, un --root optionnel, et --force-conversion, qui supprime tout instantané local existant et le télécharge à nouveau. Il écrit codebase_version: v2.1 dans meta/info.json.
La conversion écrase sur place

Si le jeu de données v3.0 existe déjà localement, le script construit la structure v2.1 à côté, puis échange : l'original est déplacé vers un dossier frère avec la version ajoutée, <name>_v3.0, et la copie convertie prend le chemin d'origine. (Le docstring du script appelle ce dossier _v30 ; le code ajoute la chaîne de version, donc ce que vous obtenez réellement est _v3.0.) Deuxième surprise : la sortie atterrit toujours sous <root>/<repo-id>, donc --root examples/SO100/my_dataset_lerobot vous donne examples/SO100/my_dataset_lerobot/<your-hf-user>/<your-dataset>, et ce chemin plus long est celui que --dataset-path voudra plus tard. Lorsqu'une tâche d'entraînement rejette votre jeu de données pour des raisons de version, la page du jeu de données rejeté comme v3 liste les symptômes exacts.

La structure que GR00T attend après conversion est la disposition classique v2 : meta/info.json, meta/episodes.jsonl, meta/tasks.jsonl, des fichiers parquet sous data/chunk-000/, des fichiers MP4 sous videos/chunk-000/observation.images./, et un fichier supplémentaire que LeRobot standard n'a pas. C'est dans ce fichier supplémentaire que se trouvent la plupart des échecs restants.

Étape 2 : modality.json, les six nombres qui décident de tout

Dans un jeu de données LeRobot, l'état du robot et l'action sont stockés sous forme de tableaux float32 plats. Pour un SO-100, les deux ont la forme [6] : cinq articulations de bras et un préhenseur. Le jeu de données de démonstration les nomme shoulder_pan.pos, shoulder_lift.pos, elbow_flex.pos, wrist_flex.pos, wrist_roll.pos, gripper.pos, mais ces noms se trouvent dans info.json et rien dans le fichier parquet n'indique quel index correspond à quoi. meta/modality.json fournit ce mappage, et GR00T ne s'entraînera pas sans lui. Voici celui que le dépôt fournit pour le SO-100, tel quel.

json
{
  "state": {
    "single_arm": {
      "start": 0,
      "end": 5
    },
    "gripper": {
      "start": 5,
      "end": 6
    }
  },
  "action": {
    "single_arm": {
      "start": 0,
      "end": 5
    },
    "gripper": {
      "start": 5,
      "end": 6
    }
  },
  "video": {
    "front": {
      "original_key": "observation.images.front"
    },
    "wrist": {
      "original_key": "observation.images.wrist"
    }
  },
  "annotation": {
    "human.task_description": {
      "original_key": "task_index"
    }
  }
}
examples/SO100/modality.json. Les indices sont basés sur zéro et suivent le découpage Python, donc single_arm est [0:5] et gripper est [5:6].

Copiez-le dans votre jeu de données converti à l'emplacement meta/modality.json et renommez les clés vidéo pour qu'elles correspondent aux noms réels de vos caméras. Si vous avez enregistré avec une seule caméra zénithale nommée top, alors original_key est observation.images.top et le nom convivial est celui que votre configuration de données référencera. Les deux doivent concorder, et aucun d'eux ne vérifie l'autre pour vous. L'annotation linguistique est pire, car la même clé doit apparaître à trois endroits.

CoucheFichierForme SO-100 utilisée dans le dépôt
Colonne Parquetdata/chunk-*/episode_*.parquetannotation.human.task_description
Clé modality.jsonmeta/modality.json, sous "annotation", sans le préfixe annotation.human.task_description
clés modality dans la configuration des donnéesvotre so100_config.pyannotation.human.task_description
Pourquoi la clé linguistique pose problème

Les segments après annotation. sont choisis par l'auteur du jeu de données. Les données de démonstration SO-100 utilisent annotation.human.task_description ; LIBERO et SimplerEnv utilisent annotation.human.action.task_description. Les deux sont valides. Si vous avez copié une configuration d'un exemple LIBERO et l'avez pointée vers votre propre enregistrement SO-100, le canal linguistique ne résout rien et le modèle s'entraîne sur une instruction vide. La perte diminue toujours. La politique fait toujours quelque chose. Elle ignore simplement ce que vous lui avez dit de faire.

Étape 3 : la configuration des données, le bras relatif et le préhenseur absolu

La configuration de modalité est un fichier Python plutôt que JSON, car elle décide également de la manière dont chaque groupe d'actions est représenté. C'est la partie du flux de travail N1.7 qui n'existait pas sous la même forme dans N1.5, et la partie qui mérite d'être lue deux fois. La configuration SO-100 fournie prédit les cinq articulations du bras comme des RELATIFS deltas par rapport à l'état actuel et la pince comme une position cible ABSOLUE, car un signal binaire ouvert-ou-fermé se comporte mieux comme une cible que comme un delta.

python
from gr00t.configs.data.embodiment_configs import register_modality_config
from gr00t.data.embodiment_tags import EmbodimentTag
from gr00t.data.types import (
    ActionConfig, ActionFormat, ActionRepresentation, ActionType, ModalityConfig,
)

so100_config = {
    "video": ModalityConfig(
        delta_indices=[0],                       # current frame only
        modality_keys=["front", "wrist"],        # must match modality.json
    ),
    "state": ModalityConfig(
        delta_indices=[0],
        modality_keys=["single_arm", "gripper"],
    ),
    "action": ModalityConfig(
        delta_indices=list(range(0, 16)),        # predict 16 future steps
        modality_keys=["single_arm", "gripper"],
        action_configs=[
            ActionConfig(rep=ActionRepresentation.RELATIVE,   # arm joints
                         type=ActionType.NON_EEF,
                         format=ActionFormat.DEFAULT),
            ActionConfig(rep=ActionRepresentation.ABSOLUTE,   # gripper
                         type=ActionType.NON_EEF,
                         format=ActionFormat.DEFAULT),
        ],
    ),
    "language": ModalityConfig(
        delta_indices=[0],
        modality_keys=["annotation.human.task_description"],
    ),
}

register_modality_config(so100_config, embodiment_tag=EmbodimentTag.NEW_EMBODIMENT)
examples/SO100/so100_config.py, réduit à l'essentiel. NON_EEF signifie espace articulaire ; EEF s'attendrait à un vecteur à neuf dimensions de x, y, z plus une rotation 6D.

Deux détails ici vous coûteront une journée si vous ne les connaissez pas. Premièrement, action_configs est positionnel : la documentation exige la même longueur et le même ordre que modality_keys, et elle est très claire sur la conséquence d'une erreur, à savoir que la mauvaise représentation est appliquée silencieusement. Votre pince est entraînée comme un delta et votre bras comme une cible absolue, et il n'y a pas de message d'erreur. Deuxièmement, register_modality_config affirme que le tag n'est pas déjà enregistré, donc une deuxième configuration NEW_EMBODIMENT dans le même processus Python échoue avec Embodiment tag ... already registered. Vous ne pouvez pas en importer deux dans un même script. Une troisième règle est appliquée plus tard, lors du déploiement : les delta_indices de l'action doivent être une plage contiguë commençant à zéro. Une fenêtre éparse telle que [0, 4, 8] est rejetée, car tout ce qui est en aval indexe le bloc prédit linéairement et exécuterait autrement les mauvaises lignes.

Modifiez delta_indices et vous devez régénérer les statistiques

Les statistiques de normalisation, en particulier meta/relative_stats.json, sont calculées pour la longueur d'horizon que vous aviez lors de leur génération. Raccourcissez l'horizon d'action de 16 à 8 sans régénérer et l'entraînement échoue avec IndexError: boolean index did not match indexed array ... dimension is 8 but corresponding boolean dimension is 16. La solution est une seule commande : python gr00t/data/stats.py --dataset-path <path> --embodiment-tag NEW_EMBODIMENT --modality-config-path examples/SO100/so100_config.py. Exécutez-la après toute modification de delta_indices.

Étape 4 : l'environnement

N1.7 a déplacé le dépôt vers et Python 3.12. L'ancien chemin conda plus pip install -e . existe toujours dans une section repliée du README, mais il avertit que les dépendances GPU, y compris flash-attn et TensorRT, peuvent nécessiter une installation manuelle. Utilisez uv à moins d'avoir une raison spécifique de ne pas le faire. Concernant flash-attn, un détail évite la confusion : vous verrez Installing flash-attn affiché à chaque uv run. Il ne s'agit pas d'une reconstruction. uv revalide une roue épinglée par URL qui est déjà mise en cache, et cela prend deux ou trois secondes.

  1. 1
    Installer git-lfs, puis cloner avec les sous-modules

    git-lfs est requis, non optionnel. Sans lui, les fichiers parquet dans demo_data/ sont téléchargés comme des stubs de pointeur, et l'exécution de la démo échoue sur un jeu de données qui semble présent dans la liste des fichiers.

    bash
    sudo apt install git-lfs && git lfs install
    git clone --recurse-submodules https://github.com/NVIDIA/Isaac-GR00T
    cd Isaac-GR00T
  2. 2
    Installer uv et synchroniser l'environnement

    L'installation par défaut télécharge les dépendances GPU, y compris flash-attn et TensorRT. Sur une image A100 ou H100 fraîche, c'est l'étape la plus longue, alors faites-le avant de vous concentrer sur autre chose.

    bash
    curl -LsSf https://astral.sh/uv/install.sh | sh
    sudo apt-get update && sudo apt-get install -y ffmpeg
    uv sync --python 3.12
    uv run python -c "import gr00t; print('GR00T installed successfully')"
  3. 3
    S'authentifier auprès de Hugging Face

    Faites cela avant le premier lancement de l'entraînement, pas après qu'il ait échoué après huit minutes.

    bash
    uv run huggingface-cli login   # or: export HF_TOKEN=<your_token>
  4. 4
    Vérification de bon fonctionnement sur les données de démonstration SO-100 fournies

    Avant de toucher à votre propre enregistrement, exécutez 2000 étapes sur demo_data/cube_to_bowl_5. Il s'agit de cinq épisodes, cela se termine rapidement et cela prouve l'environnement plutôt que vos données. Si cette exécution échoue, rien de ce que vous ferez à votre jeu de données n'aidera.

    bash
    CUDA_VISIBLE_DEVICES=0 uv run python \
        gr00t/experiment/launch_finetune.py \
        --base-model-path nvidia/GR00T-N1.7-3B \
        --dataset-path demo_data/cube_to_bowl_5 \
        --embodiment-tag NEW_EMBODIMENT \
        --modality-config-path examples/SO100/so100_config.py \
        --num-gpus 1 \
        --output-dir /tmp/test_finetune \
        --max-steps 2000 \
        --global-batch-size 32 \
        --dataloader-num-workers 4
Deux pièges d'environnement qui ressemblent à des bugs de modèle

FFmpeg 8. torchcodec 0.8.0 ne prend en charge que FFmpeg 4 à 7, et Ubuntu 25.10 et les versions ultérieures livrent la version 8. L'erreur est Could not load libtorchcodec, ce qui ressemble à une installation corrompue plutôt qu'à un conflit de version. Installez un runtime plus ancien, par exemple conda install -c conda-forge 'ffmpeg<8', et placez ses bibliothèques sur LD_LIBRARY_PATH. CUDA_HOME n'est pas défini. Le fine-tuning échoue complètement. Exécutez bash scripts/deployment/dgpu/install_deps.sh une fois, ou simplement export CUDA_HOME=/usr/local/cuda.

Étape 5 : la commande de fine-tuning et les valeurs par défaut de ses options

Remplacez le jeu de données de démonstration par le vôtre et ajoutez les paramètres que vous souhaitez réellement. Vous trouverez ci-dessous la forme complète que le dépôt utilise dans son propre tutoriel de nouvelle incarnation, y compris les options d'augmentation et de checkpointing que le court exemple du README omet. Il s'agit de au sens strict : le backbone linguistique et l'encodeur visuel restent figés, et ce qui est entraîné est le projecteur et la tête d'action de diffusion.

bash
export NUM_GPUS=1
CUDA_VISIBLE_DEVICES=0 uv run python \
    gr00t/experiment/launch_finetune.py \
    --base-model-path nvidia/GR00T-N1.7-3B \
    --dataset-path ./my_dataset_lerobot \
    --embodiment-tag NEW_EMBODIMENT \
    --modality-config-path examples/SO100/so100_config.py \
    --num-gpus $NUM_GPUS \
    --output-dir /tmp/so100 \
    --save-total-limit 5 \
    --save-steps 2000 \
    --max-steps 20000 \
    --use-wandb \
    --global-batch-size 32 \
    --color-jitter-params brightness 0.3 contrast 0.4 saturation 0.5 hue 0.08 \
    --dataloader-num-workers 4
GPU unique. Pour huit cartes, remplacez le lanceur par uv run torchrun --nproc_per_node=8 --master_port=29500 et définissez --num-gpus 8. Utilisez uv run torchrun, et non torchrun seul, sinon vous obtiendrez un environnement incorrect.
OptionValeur par défaut dans FinetuneConfigDescription
--global-batch-size64Taille totale du lot sur tous les GPU avant l'accumulation de gradient. Les exemples fournis utilisent 32.
--learning-rate1e-4La même valeur qu'AY-Robots envoie pour son entraîneur groot1.7.
--max-steps10000Nombre total d'étapes de l'optimiseur. L'enveloppe examples/finetune.sh utilise également 10000 par défaut.
--gradient-accumulation-steps1Multiplie le lot effectif. Les valeurs supérieures à 1 émettent un avertissement indiquant la taille accumulée.
--save-steps and --save-total-limit1000 and 5Fréquence des checkpoints et nombre de ceux qui sont conservés. Les plus anciens sont supprimés.
--weight-decay and --warmup-ratio1e-5 and 0.05Également défini explicitement par examples/finetune.sh.
--state-dropout-prob0.2 in the CLI, 0.8 in the model configSupprime aléatoirement l'état proprioceptif pendant l'entraînement. Diminuez-le si votre tâche dépend de l'état.
--tune-llm and --tune-visualFalse and FalseLe backbone reste figé par défaut.
--tune-projector and --tune-diffusion-modelTrue and TrueLe projecteur et la tête d'action de diffusion sont ce qui est réellement entraîné.
--use-percentilesTrueNormalise avec q01 et q99 au lieu des valeurs min et max brutes.
--dataloader-num-workers2Le chargeur est basé sur le CPU par conception. Les exemples l'augmentent à 4.
--seeddoes not existIl n'y a pas d'option de seed sur cette CLI.

Cette dernière ligne n'est pas une faute de frappe. launch_finetune.py est une interface CLI tyro générée à partir d'une dataclass, et cette dataclass n'a pas de champ de graine (seed). Le README mentionne séparément une variance de 5 à 6 pour cent entre les exécutions, causée par une augmentation d'image non déterministe. Deux exécutions avec des drapeaux identiques ne produiront pas de checkpoints identiques, ce qui est très important lorsque vous essayez de décider si un changement d'hyperparamètre a été utile ou si vous avez eu de la chance. À titre de comparaison, l'entraîneur de lerobot utilise par défaut la graine 1000, et la recette LeRobot GR00T passe --seed=42 explicitement.

La validation est désactivée par défaut, et le drapeau documenté n'est pas sur cette CLI

Le fine-tuning s'exécute avec eval_strategy="no", il n'y a donc aucune courbe de perte de validation. Vous obtenez la perte d'entraînement et rien d'autre. Le guide de la nouvelle incarnation vous indique de l'activer avec --eval-strategy steps --eval-steps 500, mais ce drapeau n'existe pas sur launch_finetune.py : la CLI est générée par tyro à partir de la dataclass FinetuneConfig, et eval_strategy, eval_steps et eval_batch_size sont des champs de TrainingConfig à la place. Leurs valeurs par défaut sont "no", 500 et 2. Pour les atteindre, utilisez le point d'entrée plus complet gr00t/experiment/launch_train.py, où le drapeau imbriqué est --training.eval-strategy. Dans tous les cas, une perte d'entraînement en baisse ne vous dit que très peu de choses sur la généralisation, ce qui est exactement la situation décrite sur la perte diminue mais la politique ne fait rien.

Ce que coûte une exécution de 20000 étapes

GR00T N1.7 nécessite une carte de 80 Go, la question du coût a donc une réponse limitée. Sur AY-Robots, l'entraîneur groot1.7 s'exécute sur le niveau A100 80 Go ou H100 80 Go, où une exécution prend 3 à 6 heures à 1.20 à 2.00 USD par heure sur le marché spot. Cela représente environ 4 à 12 USD pour la tâche par défaut de 20000 étapes. La même tâche sur SmolVLA ou ACT s'exécute sur une carte de 24 Go à 0.30 à 0.60 USD par heure et 1 à 3 USD par exécution. C'est le véritable compromis : GR00T coûte environ quatre fois plus cher par tentative, et vous ne pouvez pas l'exécuter sur la 4090 sous votre bureau.

ModèleNiveau de GPUDurée typiqueCoût typiqueÉpisodes minimum
GR00T N1.7A100 80 GB or H100 80 GB3 to 6 hours4 to 12 USD50
GR00T N1.5A100 80 GB or H100 80 GB3 to 6 hours4 to 12 USD50
Pi0.5A100 80 GB or H100 80 GB3 to 6 hours4 to 12 USD50
SmolVLARTX 4090 or toute carte de 24 Go2 to 5 hours1 to 3 USD30
ACTRTX 4090 or toute carte de 24 Go2 to 5 hours1 to 3 USD50

Le minimum de 50 épisodes est un plancher, pas un objectif. La FAQ de NVIDIA est plus exigeante : environ 100 trajectoires pour un simple ramassage et placement à emplacement fixe, 500 ou plus pour des scènes complexes ou multi-étapes, et 100 à 500 pour une manipulation fine. Si vous êtes à 20 épisodes, passez l'après-midi à enregistrer plutôt que la soirée à ajuster. Le guide de collecte de données couvre ce qui sépare un épisode utile d'un épisode gaspillé, enregistrez votre premier jeu de données est la version courte, et collecte de données SO-100 est celle spécifique au bras.

Étape 6 : évaluation en boucle ouverte avant de toucher le bras

Ne mettez pas un nouveau point de contrôle sur un bras physique pour savoir si l'entraînement a fonctionné. Exécutez d'abord l'évaluation en boucle ouverte. Elle rejoue un épisode enregistré, demande au modèle des actions à chaque étape, et trace la prédiction par rapport à la vérité terrain avec le MSE et le MAE. Elle ne coûte rien et elle détecte les erreurs de mappage des étapes 2 et 3.

bash
uv run python gr00t/eval/open_loop_eval.py \
    --dataset-path ./my_dataset_lerobot \
    --embodiment-tag NEW_EMBODIMENT \
    --model-path /tmp/so100/checkpoint-20000 \
    --traj-ids 0 \
    --execution-horizon 16 \
    --steps 400 \
    --modality-keys single_arm gripper
Les tracés sont enregistrés dans /tmp/open_loop_eval/traj_<id>.jpeg à moins que vous ne passiez --save-plot-path. Valeurs par défaut : --execution-horizon 16, --steps 200, --denoising-steps 4, --traj-ids 0.

Le dépôt refuse délibérément de publier un MSE cible pour les données personnalisées, et c'est la bonne approche : le nombre dépend de vos unités d'action, de votre tâche et de la taille de votre jeu de données, donc un seuil copié du bras de quelqu'un d'autre ne signifie rien. Ce qui est significatif, c'est la tendance. Voici l'exécution de référence documentée par le dépôt sur un seul H100 avec le jeu de données de démonstration de cinq épisodes et 2000 étapes.

Point de contrôleMSE moyen sur traj 0MAE moyen sur traj 0
50087.55.63
100025.43.30
150013.22.18
200010.01.76

La forme est le signal, pas les valeurs absolues. L'erreur devrait diminuer régulièrement à mesure que les s'accumulent. En moyenne sur les cinq épisodes d'entraînement plutôt que sur la seule trajectoire 0, le point de contrôle final du dépôt a obtenu environ 7.5 MSE et 1.5 MAE, de sorte que même l'exécution de référence se lit différemment selon les épisodes que vous moyennez. Enregistrez votre propre ligne de base sur la commande de démonstration non modifiée avant de modifier quoi que ce soit concernant vos propres données : si vous ne pouvez pas reproduire une exécution connue comme bonne, vous ne pouvez pas distinguer une erreur de configuration d'un problème de données. Le dépôt associe également les symptômes courants aux causes, et chacun d'eux est opérationnel plutôt qu'un bug du modèle.

SymptômeCause probable
MSE stable ou en hausse sur les points de contrôleTaux d'apprentissage trop faible, ou les données ne se chargent pas du tout. Vérifiez --dataset-path et les workers du dataloader.
La courbe de prédiction est plate ou constanteLes clés modality.json ou --modality-config-path ne correspondent pas. Les clés d'action ne sont pas mappées.
MSE énorme, ou perte NaN pendant l'entraînementNormalisation de l'action et de l'état. Vérifiez meta/stats et que les plages d'action sont physiquement plausibles.
Bon sur la traj 0, médiocre sur les épisodes non vusRareté des données, pas un bug. Cinq épisodes de démonstration ne peuvent pas généraliser.

L'autre voie : lerobot-train au lieu d'Isaac-GR00T

La version actuelle de LeRobot, 0.6.1 sur PyPI depuis le 3 août 2026, offre une deuxième manière, très différente, d'affiner les mêmes poids de base. LeRobot expose GR00T N1.7 comme type de politique et l'entraîne via son propre point d'entrée lerobot-train. Deux choses sont importantes ici. L'interface de ligne de commande de LeRobot est un ensemble de scripts console, donc tout ce que vous lisez qui dit python lerobot/scripts/train.py est obsolète et ne fonctionnera pas. Et LeRobot a entièrement supprimé le support de GR00T N1.5, rejetant les points de contrôle et les configurations N1.5 avec une note de migration, donc si vous avez besoin de N1.5 via LeRobot, vous devez épingler lerobot==0.5.1, la dernière version qui le prend en charge, publiée le 7 avril 2026.

bash
pip install "lerobot[groot]" "lerobot[training]"
hf auth login

lerobot-train \
  --dataset.repo_id=$HF_USER/$DATASET_NAME \
  --dataset.image_transforms.enable=true \
  --policy.type=groot \
  --policy.device=cuda \
  --policy.base_model_path=nvidia/GR00T-N1.7-3B \
  --policy.embodiment_tag=new_embodiment \
  --policy.chunk_size=16 \
  --policy.n_action_steps=16 \
  --policy.use_relative_actions=true \
  --policy.relative_exclude_joints='["gripper"]' \
  --policy.use_bf16=true \
  --seed=42 \
  --batch_size=64 \
  --steps=20000 \
  --save_freq=5000 \
  --output_dir=$OUTPUT_DIR
La recette GR00T N1.7 native de LeRobot. Notez relative_exclude_joints : la pince est exclue des actions relatives, ce qui est la même décision que so100_config.py prend avec ActionRepresentation.ABSOLUTE.
AspectIsaac-GR00T launch_finetune.pylerobot-train --policy.type=groot
Version du jeu de donnéesLeRobot v2 uniquement, conversion requiseJeu de données LeRobot natif, pas de rétrogradation
Mappage des modalitésmeta/modality.json plus une configuration de données Pythonpas de modality.json ; comportement défini par les drapeaux --policy.* sur la ligne de commande
Graineaucun drapeau de graine--seed, LeRobot par défaut 1000
Actions relativesActionConfig par clé dans la configuration des données--policy.use_relative_actions plus --policy.relative_exclude_joints
Résultats de référence publiésTendance MSE en boucle ouverte SO-100 sur les données de démonstrationSuites LIBERO, 96,5 pour cent de moyenne sur quatre suites
Chemin de déploiementrun_gr00t_server.py plus eval_so100.py via ZMQlerobot-rollout, avec découpage en temps réel (queue_threshold doit rester à 5 ou moins)
Exécuter le fine-tuning vous-même
Avantages
  • Chaque drapeau est visible et modifiable. Vous pouvez débloquer l'encodeur visuel, déplacer state_dropout_prob ou raccourcir l'horizon d'action.
  • Les tracés en boucle ouverte sont des fichiers locaux. Comparer checkpoint-5000 à checkpoint-20000 est une commande shell.
  • Vous ne dépendez d'aucune plateforme restant en ligne, et le point de contrôle se trouve sur votre disque dans un format standard.
  • Les exemples de benchmark du dépôt pour LIBERO, SimplerEnv et DROID vous donnent des exécutions validées à reproduire avant de faire confiance à vos propres données.
Compromis
  • L'environnement représente la majeure partie du travail. Version FFmpeg, CUDA_HOME, git-lfs, le backbone à accès restreint, torchcodec : aucun de ces éléments n'est un problème de modèle et chacun d'eux arrête l'exécution.
  • La conversion de v3.0 à v2.1 nécessite un virtualenv séparé avec sa propre étape d'installation, et elle réécrit votre répertoire de jeu de données sur place.
  • La facturation de la location de GPU commence lorsque vous débutez le débogage, pas lorsque l'entraînement commence, et rien n'arrête l'instance lorsque l'exécution se termine.
  • L'absence de graine signifie l'absence de reproductibilité bit à bit, en plus d'une variance de 5 à 6 pour cent d'une exécution à l'autre due à l'augmentation seule.

Deux façons d'obtenir le même point de contrôle

Vous louez le GPU et maîtrisez chaque étape. En réalité, cela prend un après-midi la première fois et vingt minutes les fois suivantes.

  1. Enregistrez des épisodes avec lerobot-record sur le SO-100. Vous obtenez un jeu de données LeRobot v3.0.
  2. Convertissez-le en v2.1 avec scripts/lerobot_conversion/convert_v3_to_v2.py dans son propre environnement virtuel.
  3. Écrivez meta/modality.json et une configuration de modalité Python, enregistrée sous EmbodimentTag.NEW_EMBODIMENT.
  4. Louez une carte de 80 Go, clonez avec les sous-modules, synchronisez uv, authentifiez-vous auprès de Hugging Face.
  5. Exécutez launch_finetune.py, puis open_loop_eval.py sur plusieurs checkpoints, et comparez la tendance MSE avant de toucher au matériel.
  6. Récupérez le checkpoint de la machine avant de détruire l'instance, puis construisez le chemin de service vers le bras.
L'étape que tout le monde oublie

Copiez le checkpoint de l'instance louée avant de l'arrêter. --save-total-limit 5 signifie également que les checkpoints plus anciens sont supprimés au fur et à mesure de l'entraînement, de sorte que le checkpoint que vous vouliez à l'étape 5000 pourrait ne plus exister à l'étape 20000.

La matrice d'entraînement AY-Robots avec cinq modèles de politique en lignes et quatre bras robotiques en colonnes, chaque cellule renvoyant à un guide d'entraînement spécifique
La matrice /train : cinq modèles contre quatre bras. La ligne GR00T N1.7 couvre également le SO-101, Koch v1.1 et LeKiwi.

Remettre le checkpoint sur le bras

Isaac-GR00T utilise une architecture client-serveur via ZMQ. La politique s'exécute sur le GPU, et un client léger sur la machine robot envoie les observations et reçoit les morceaux d'action. L'exemple SO-100 est suffisamment complet pour être copié : démarrez run_gr00t_server.py avec votre checkpoint et --embodiment-tag NEW_EMBODIMENT, puis exécutez eval_so100.py côté robot avec le port série, l'ID du robot, les indices de caméra et l'instruction linguistique. Les noms de caméra dans cette commande doivent correspondre aux noms conviviaux de votre modality.json, et non aux numéros de périphérique du système d'exploitation.

bash
# GPU side
uv run python gr00t/eval/run_gr00t_server.py \
  --model-path /tmp/so100/checkpoint-20000 \
  --embodiment-tag NEW_EMBODIMENT \
  --device cuda:0 \
  --host 0.0.0.0 --port 5555

# robot side, from gr00t/eval/real_robot/SO100
uv run --no-sync python eval_so100.py \
  --robot.type=so101_follower \
  --robot.port=/dev/ttyACM2 \
  --robot.id=orange_follower \
  --robot.cameras="{ front: {type: opencv, index_or_path: 6, width: 640, height: 480, fps: 30}, wrist: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30}}" \
  --policy_host=localhost --policy_port=5555 \
  --lang_instruction="put the cube in the yellow bowl"
--execution-horizon contrôle le nombre d'étapes prédites exécutées avant la replanification. Il doit être au maximum l'action_horizon de la politique, et ce nombre est la longueur des delta_indices d'action dans votre configuration de modalité, pas celle du modèle de base. La configuration SO-100 fournie prédit 16, donc 16 est votre plafond ; le checkpoint de base nvidia/GR00T-N1.7-3B est configuré pour 40, et policy.md indique clairement que les checkpoints affinés peuvent différer. Dépassez-le et vous obtiendrez une ValueError nommant les deux nombres. 8 est la valeur suggérée par la documentation pour un déploiement en temps réel. L'ancien nom de flag --action-horizon fonctionne toujours mais émet un avertissement.
7,4 V, pas 12 V

Pendant que vous rebranchez le bras : le SO-100 utilise des servomoteurs de bus Feetech STS3215 sur un rail de 7,4 V. Les alimenter en 12 V les détruit, et c'est une erreur facile si vous possédez également un LeKiwi, dont la base fonctionne en 12 V alors que son bras non. Vérifiez l'alimentation avant la première mise sous tension, pas après la fumée. Voir la page matérielle du SO-100 et SO-100 contre LeKiwi. Si le bras s'allume mais que rien ne bouge, servo ne répond pas est le point de départ.

Maintenant, la partie honnête sur l'endroit où la politique s'exécute, car l'entraînement et le service ont des histoires matérielles différentes. Le réglage fin nécessite 40 Go ou plus. L'inférence non : le README l'estime à 16 Go ou plus et nomme explicitement la RTX 4090, donc une carte que vous possédez déjà peut servir un checkpoint qu'elle n'aurait jamais pu produire. Ce qui décide si la politique semble réactive n'est pas la VRAM, c'est l'emplacement du serveur. Sur AY-Robots, GR00T N1.7 est uniquement dans le cloud, donc la boucle de contrôle paie un aller-retour sur Internet public en plus des 152 ms par étape d'action, et seulement SmolVLA et ACT s'exécutent également localement. Pour un ramassage et placement lent, un pod distant est supportable. Pour tout ce qui est réactif, ce n'est pas le cas : la politique devient hésitante d'une manière qui ressemble exactement à un échec d'entraînement et n'en est pas un. ACT à 20 ms par étape d'action est le modèle qui tolère la boucle la plus serrée, SmolVLA est à 245 ms, et aucune quantité de réglage de la latence ne rachète un aller-retour déjà effectué. Exécuter votre première politique explique le côté service de bout en bout.

Ce qui ne va pas réellement

  • GatedRepoError lors de la première exécution. L'accès à nvidia/Cosmos-Reason2-2B ne vous a pas été accordé, ou vous ne vous êtes pas authentifié. Cela se produit après que l'horloge du GPU a déjà démarré.
  • Jeu de données rejeté au chargement. Presque toujours un jeu de données v3.0. Convertissez-le vers une version antérieure. Voir jeu de données rejeté en tant que v3.
  • IndexError concernant des dimensions booléennes incompatibles. Vous avez modifié delta_indices et n'avez pas régénéré les statistiques.
  • Manque de mémoire au lot 32. Réduisez --global-batch-size et augmentez --gradient-accumulation-steps, ou réduisez --num-shards-per-epoch, ce que la configuration suggère explicitement lorsque la VRAM est limitée. Voir manque de mémoire pendant l'entraînement.
  • La perte diminue, la politique ne fait rien. Il n'y a pas de division de validation par défaut, donc une courbe d'entraînement propre prouve très peu de choses. Cette page couvre le diagnostic.
  • Fonctionne dans votre configuration et nulle part ailleurs. Attendu avec un petit jeu de données filmé sous une seule condition d'éclairage. NVIDIA recommande une augmentation de la gigue de couleur (colour jitter augmentation) plus 20 à 50 épisodes sous différents éclairages. Plus d'informations ici.
  • La pince ne se ferme jamais correctement. Vérifiez que l'action de la pince est ABSOLUE et les articulations du bras RELATIVES, dans cet ordre dans action_configs. La pince ne se ferme pas liste les autres causes.
  • Une caméra se déconnecte silencieusement en cours d'enregistrement. L'épisode est toujours sauvegardé et la clé vidéo existe toujours, c'est pourquoi c'est un problème délicat. Caméra non détectée couvre ce cas.

L'index complet des modes de défaillance se trouve à . Si vous choisissez entre des modèles plutôt que d'en déboguer un, et ont des chiffres de référence avec des sources jointes, et est la comparaison dont la plupart des gens ont réellement besoin, car c'est le choix entre un modèle que vous pouvez entraîner sur la carte sous votre bureau et un autre pour lequel vous devez louer un nœud de 80 Go pour le fine-tuning. Pour comprendre pourquoi ces modèles se comportent de cette manière, la et le méritent d'être lus en premier. Et si vous ne possédez pas encore de bras, diffuse un SO-100 physique sans inscription.

Combien d'épisodes me faut-il avant que le fine-tuning de GR00T N1.7 en vaille la peine ?

AY-Robots fixe un seuil minimum de 50 épisodes pour l'entraîneur groot1.7. La FAQ de NVIDIA est plus exigeante : environ 100 trajectoires pour un simple pick and place à un emplacement fixe, 500 ou plus pour des scènes complexes ou multi-étapes, et 100 à 500 pour la manipulation fine. En dessous de 50, il est presque toujours préférable d'enregistrer plus de données que d'ajuster les hyperparamètres. Si le succès stagne après cela, NVIDIA recommande HG-DAgger : exécutez la politique, intervenez lorsqu'elle échoue et ajoutez ces corrections au jeu de données.

Pourquoi mon jeu de données ne se charge-t-il pas, et comment savoir de quelle version il s'agit ?

Ouvrez meta/info.json et lisez codebase_version. La CODEBASE_VERSION actuelle de LeRobot sur main est v3.0, donc tout ce qui est enregistré avec une chaîne d'outils récente est v3.0, et le chargeur GR00T s'attend à v2. Convertissez avec scripts/lerobot_conversion/convert_v3_to_v2.py du dépôt Isaac-GR00T, qui écrit codebase_version: v2.1 dans le jeu de données converti. Le script s'exécute dans son propre virtualenv car il nécessite une version de lerobot différente de celle épinglée par GR00T.

Puis-je faire du fine-tuning de GR00T N1.7 sur une RTX 4090 ?

Non. NVIDIA recommande 40 Go ou plus de VRAM pour le fine-tuning et cite les nœuds H100 ou L40 ; d'autres cartes fonctionnent mais prennent beaucoup plus de temps. Une 4090 a 24 Go. AY-Robots ne propose GR00T N1.7 que sur les niveaux A100 80 Go et H100 80 Go pour la même raison. L'inférence est une autre histoire : 16 Go suffisent pour servir le modèle, donc une 4090 peut exécuter une politique qu'elle ne peut pas entraîner. Si vous voulez un VLA que vous pouvez entraîner sur 24 Go, il s'agit de SmolVLA avec environ 450 M de paramètres ou d'ACT avec environ 80 M.

Pourquoi deux exécutions avec des drapeaux identiques donnent-elles des checkpoints différents ?

Parce que launch_finetune.py n'a pas de seed. C'est une CLI tyro générée à partir d'une dataclass qui ne contient pas de champ seed, donc rien ne fixe le générateur de nombres aléatoires (RNG). Le dépôt note séparément une variance de 5 à 6 pour cent entre les exécutions causée par une augmentation d'image non déterministe. Si la reproductibilité est importante, utilisez plutôt la voie LeRobot : lerobot-train prend --seed et la recette GR00T publiée passe --seed=42.

Dois-je utiliser Isaac-GR00T ou lerobot-train ?

Utilisez Isaac-GR00T si vous voulez l'implémentation de référence, un contrôle par clé sur la représentation des actions, l'exportation TensorRT, ou les exemples de benchmark à reproduire avant de faire confiance à vos propres données. Utilisez lerobot-train si votre jeu de données est déjà LeRobot v3.0 et que vous préférez ne pas le convertir, si vous voulez une seed, ou si le reste de votre pile est déjà LeRobot. Les deux effectuent le fine-tuning des mêmes poids nvidia/GR00T-N1.7-3B. Notez que LeRobot a entièrement abandonné le support de GR00T N1.5 : les checkpoints N1.5 sont rejetés avec une note de migration, et vous devez épingler lerobot==0.5.1 pour continuer à les utiliser.

Ai-je vraiment besoin d'une caméra de poignet en plus d'une caméra frontale ?

La configuration SO-100 livrée utilise les deux, et modality.json mappe l'avant et le poignet comme des clés vidéo distinctes. Vous pouvez entraîner avec une seule caméra, et le tableau de latence de la carte modèle est mesuré avec une seule caméra, mais la vue du poignet est ce qui donne à la politique des informations utilisables sur la pince au moment du contact. Si la pince se ferme au mauvais moment dans vos rollouts, une caméra de poignet manquante ou mal orientée est l'une des premières choses à vérifier.

Fine-tunez GR00T N1.7 sur votre SO-100 sans construire l'environnement au préalable

Choisissez le modèle, le jeu de données et les hyperparamètres dans un formulaire. Le backend loue un A100 80 Go ou un H100 sur le marché spot, exécute l'entraîneur avec un lot de 32, un taux d'apprentissage de 1e-4 et 20000 étapes, et écrit les checkpoints dans le stockage d'objets. Environ 4 à 12 USD par exécution.

Ouvrir le guide d'entraînement GR00T N1.7

Ready for high-quality robotics data?

AY-Robots connects your robots to skilled operators worldwide.

Get Started