Skip to main content

Machine Learning LeRobot avec SO-ARM101

Installation et prérequis

Prérequis pour l'entraînement et l'exécution d'un modèle d'IA :

  • Une carte graphique NVidia et une installation de Cuda
  • L'exécution semble OK sur une Quadro P620
  • L'entrainement avec 100 épisodes et 100 000 steps a mis 12H sur une RTX 2080 Super de 2019
    • batch_size=8 alors qu'il faut un minimum de 16, et dans l'idéal 64
    • Il n'aboutit pas au bout de plus de 24H sur une Quadro P620 (via WSL2 et Docker)
  • Config minimum pour ACT batch_size=1516 :
       
    • Tesla T4 (gratuit 5H / mois sur Google Colab) on a 15G de RAM qui permet donc un batch_size=15
    • Config recommandée pour ACT batch_size=64 :

      Installation sous Linux

      wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
      # Vérifier que la clé SHA256 de Miniconda3-latest-Linux-x86_64.sh ici : https://repo.anaconda.com/miniconda/ correspond à :
      sha256sum ~/Miniconda3-latest-Linux-x86_64.sh
      bash ~/Miniconda3-latest-Linux-x86_64.sh
      source ~/.bashrc
      • Créer et activer l'environnement Conda
      conda create -y -n lerobot python=3.10
      conda activate lerobot
      git clone https://github.com/huggingface/lerobot.git ~/lerobot
      conda install ffmpeg=7.1.1 -c conda-forge
      cd ~/lerobot && pip install -e ".[feetech]"
      • A chaque ouverture de Terminal l'environnement python conda est activé, voir au bas du ~/.bashrc 
      • Pour éviter les conflits, on propose d'avoir un fichier ~/.bashrc_conda pour conda et un ~/.bashrc_ros pour ros

      Astuces pour activer/désactiver l'environnement conda sans passer par la modification du ~/.bashrc :

      • Ne pas activer conda au démarrage : conda config --set auto_activate_base false
      • Ne pas configurer le shell pour initialiser conda au démarrage : conda init --reverse $SHELL

      Installation Windows

      • Le compte utilisateur doit avoir les droits pour créer des raccourcis (liens symboliques) dans les sous-dossiers de C:\Users\$USER\lerobot\outputs\train\
      • Ils seront utilisés lors de l'entraînement pour créer un lien entre le dossier last et le dossier du dernier Checkpoint par ex. 100000
        • Le plus sûr est de travailler avec un compte administrateur
        • Il faut peut-être aussi les droits dans le dossier C:\Users\$USER\.cache\huggingface\lerobot\$HUGGINGFACE_USER
      • Installer Miniconda pour Windows : l'environnement de développement Python
      • Ouvrir Anaconda PowerShell Prompt
      • Créer et activer l'environnement Conda
      conda create -y -n lerobot python=3.10
      conda activate lerobot
      git clone https://github.com/huggingface/lerobot.git ~/lerobot
      • Installer Pytorch pour la version de Cuda installée sur votre système (testé avec une version Cuda 127 installée et la version cu128 de Pytorch) et autres dépendances nécessaires
      cd ~/lerobot
      # pip install av poetry-core
      conda install ffmpeg=7.1.1 -c conda-forge
      pip3 install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
      pip install -e ".[feetech]"

      Récupérer les infos système pour débuguer l'installation si les scripts basculent sur le cpu :

      • python lerobot/scripts/display_sys_info.py
      • python -m torch.utils.collect_env 
      • python -c "import torch; print(torch.cuda.is_available())" && nvcc -V
      • cf.  https://github.com/huggingface/lerobot/issues/928 > Here for additional information of my full installation.

      Creer un compte HuggingFace et se login via un token

      • Se créer un compte sur https://huggingface.co/settings/tokens 
      • Aller dans le menu > Access Tokens
      • Récupérer un TOKEN avec des droits en écriture
      • Ouvrir un Anaconda PowerShell lerobot
        (lerobot) PS C:\Users\gauthier.hentz\github\lerobot>
      • Login avec le Token
        huggingface-cli.exe login --token TOKEN

      Vous pouvez maintenant uploader et downloaded des DataSets et Modèles vers le Hub HuggingFace pour collaborer avec des experts du Machine Learning.

      Essai de déploiement sur Windows via WSL2, Docker, et Dev Container

      Pour l'instant pas de test satisfaisant pour l'exécution d'un modèle sur le vrai robot. Passer au WSL2 les ports USB où sont connectés les robots et caméras fait crasher le conteneur. Probablement que la communication série n'est pas supporté.

      • Cloner https://github.com/huggingface/lerobot dans un conteneur WSL2, par exemple Ubuntu
      • Depuis le conteneur Ubuntu, ouvrir un Terminal, se placer dans le répertoire cloné cd ~/lerobot_devcontainer , et lancer Visual Studio Code en tapant code .
      • Ajouter un répertoire ~/lerobot_devcontainer/.devcontainer et un fichier dedans ~/lerobot_devcontainer/.devcontainer/devcontainer.json contenant : 
        {
        "build": {
        // Path is relative to the devcontainer.json file.
        "dockerfile": "../docker/lerobot-gpu-dev/Dockerfile"
        }}
      • Lancer la commande VSCode : Reopen in container

      Tentatives pour faire passer le port série à WSL2 : 

      wsl --shutdown
      winget install --interactive --exact dorssel.usbipd-win
      usbipd list
      wmic diskdrive list brief
      wsl --mount \\.\PHYSICALDRIVE1
      wsl.exe --version
      wsl --mount \\.\PHYSICALDRIVE1 --bare
      wsl --mount \\.\PHYSICALDRIVE1 --partition 2 --type ext4
      wsl --shutdown
      ipconfig
      net localgroup docker-users "gauthier.hentz" /ADD
      wsl --set-default ubuntu
      exit
      wsl --shutdown
      usbipd list
      usbipd bind --busid 1-1
      usbipd list
      usbipd attach --wsl --busid 1-1
      usbipd attach --wsl --busid 2-1
      usbipd attach --wsl --busid 2-2
      usbipd attach --wsl --busid 2-3
      usbipd list
      usbipd attach --wsl --busid 1-1
      usbipd list
      usbipd attach --wsl --busid 1-1
      usbipd attach --wsl --busid 3-3
      usbipd attach --wsl --busid 2-3
      usbipd attach --wsl --busid 2-2
      usbipd attach --wsl --busid 3-2
      usbipd attach --wsl --busid 3-1
      exit

      Banc de Machine Learning LeRobot

      Configurer les servomoteurs

      La carte FE-URT-1 fournie par Feetech n'est pas détectée sous Ubuntu à cause d'un conflit avec un paquet de brail. On le désinstalle : 

      sudo apt-get autoremove brltty

      https://askubuntu.com/questions/1321442/how-to-look-for-ch340-usb-drivers/1472246#1472246 

      https://github.com/huggingface/lerobot/blob/main/examples/10_use_so100.md#c-configure-the-motors 

      • Brancher la carte
      • Trouver l'interface USB sur laquelle est branchée la carte
      python lerobot/scripts/find_motors_bus_port.py
        • Sous Linux, par ex. /dev/ttyACM0 ou /dev/ttyUSB0 
        • Sous Windows, par ex. COM13 ou COM14
      • Sous Linux, Changer les droits sur les interfaces USB
      sudo chmod 666 /dev/ttyACM0
      sudo chmod 666 /dev/ttyACM1
      • Ouvrir Codium > File > Open Folder > admin_ros/lerobot
      • Modifier le fichier de config

      gedit ~/lerobot/lerobot/common/robot_devices/robots/configs.py

      • Chercher la config du So100 en ligne 436 class So100RobotConfig(ManipulatorRobotConfig):
      • Remplacer port="/dev/tty.usbmodem58760431091", pour le leader_arms (L446) et le follower_arms (L463) par le port découvert
      • Brancher les servos un à un à la carte puis lancer le script d'initialisation, en incrémentant l'ID à chaque fois :
      python lerobot/scripts/configure_motor.py \
        --port /dev/tty.usbmodem58760432961 \
        --brand feetech \
        --model sts3215 \
        --baudrate 1000000 \
        --ID 1
      • Au fur et à mesure les brancher en série et/ou noter l'ID sur le moteur
      • Les servos sont bougés à leur position centrale et l'offset mis à 0

      Ne plus bouger les servos jusqu'à l'assemblage

      Construction et assemblage mécanique

      Une version 101 est sortie en 05/2025. Le Leader est plus simple à assembler, et plus besoin de démonter les servos pour enlever un engrenage et les rendre passifs. Il suffit d'acheter le kit de 6 servos avec 3 rapports de transmission différents :

      Astuces pour l'assemblage

      • Mettre une vis sur l'arbre moteur et l'axe passif (à l'opposée de l'arbre moteur) quand il y a la place d'en mettre une (vérifier qu'il y aura la place après assemblage des éléments autour du moteur)
      • Ne plus bouger les servos après leur initialisation qui les met à l'angle 0. Dans l'idéal, assembler les éléments de manière à ce que le robot soit en configuration initiale avec tous les moteurs à 0
      • En pratique, on monte le robot dans la configuration ci-dessous. C'est l'étape de calibration qui permettra de définir un offset pour que le zéro des moteurs corresponde au modèle cinématique du SO-ARM10X

      image.png

      • Il est possible d'ajouter un offset dans la configuration des servomoteurs, par exemple via les scripts du projet LeRobot
      • Attention si vous démarrez le robot sous ROS avant d'avoir lancer la calibration LeRobot qui fixe l'Offset dans les servomoteurs, vous risquez de casser le robot

      Agencement des caméras et robots

      Le nombre, le positionnement et la qualité des caméras sont importants pour la qualité du DataSet :

      Au FabLab de IUT Haguenau

      PXL_20250613_142740983_crop.jpg

      Calibration des caméras

      https://huggingface.co/docs/lerobot/cameras 

      Google Colab

      Pour avoir accès à un GPU avec suffisamment de mémoire (16G recommandé et 64G dans l'idéal) on peut utiliser Google Colab

      • Avec Tesla T4 (gratuit 5H / mois) on a 15G de RAM qui permet donc un batch_size=15
      • Avec A100 (12€ les 70 crédits) on a 80G de RAM qui permet donc un batch_size=64

      Notebook : https://colab.research.google.com/github/huggingface/notebooks/blob/main/lerobot/training-act.ipynb#scrollTo=NQUk3Y0WwYZ4 

      !cd lerobot && python src/lerobot/scripts/lerobot_train.py \
        --dataset.repo_id=gautz/so101_pick_red_18650_drop_black_box_test2_100ep \
        --policy.type=act \
        --output_dir=outputs/train/so101_pick_red_18650_drop_black_box_test2_100ep_15batch \
        --job_name=so101_pick_red_18650_drop_black_box_test2_100ep_15batch \
        --policy.device=cuda \
        --policy.push_to_hub=False \
        --batch_size=15 \
        --wandb.enable=true

      Erreurs :

         18  cd /content/
         20  cd lerobot/
         24  python
         25              from huggingface_hub import HfApi
         26              hub_api = HfApi()
         27              hub_api.create_tag("gautz/so101_pick_red_18650_drop_black_box_test2_100ep", tag="v2.1", repo_type="dataset"
         30  cd src/
         32  cd lerobot
         34  python -m lerobot.datasets.v30.convert_dataset_v21_to_v30 --repo-id=gautz/so101_pick_red_18650_drop_black_box_test2_100ep

      Utilisation de LeRobot avec le bash Linux

      • Activer l'environnement conda lerobot
        cd ~/lerobot
        conda activate lerobot

      python lerobot/scripts/find_motors_bus_port.py

      nano lerobot/common/robot_devices/robots/configs.py

      python lerobot/scripts/control_robot.py   --robot.type=so101   --robot.cameras='{}'   --control.type=teleoperate

      Calibration robot et configuration caméras

      python -m lerobot.calibrate     --teleop.type=so101_leader  --teleop.port=/dev/ttyACM0 --teleop.id=leader_arm_fan1

      python -m lerobot.calibrate     --robot.type=so101_follower     --robot.port=/dev/ttyUSB0 --robot.id=follower_arm_fan1

      Téléopération

      python -m lerobot.teleoperate \
          --robot.type=so101_follower \
          --robot.port=/dev/ttyUSB0 \
          --robot.id=follower_arm_fan1 \
          --robot.cameras="{ top: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30},follower: {type: opencv, index_or_path: 4, width: 640, height: 480, fps: 30}}" \
          --teleop.type=so101_leader \
          --teleop.port=/dev/ttyACM0 \
          --teleop.id=leader_arm_fan1 \
          --display_data=true

      Rejouer dataset en local :

      python -m lerobot.replay \
          --robot.type=so101_follower \
          --robot.port=/dev/ttyUSB0 \
          --robot.id=follower_arm_fan1 \
          --dataset.repo_id=gautz/18650-test1-10ep \
          --dataset.episode=0 # choose the episode you want to replay

      Machine Learning

      Enregistrer dataset en local :

      python -m lerobot.record \
          --robot.type=so101_follower \
          --robot.port=/dev/ttyUSB0 \
          --robot.id=follower_arm_fan1 \
          --robot.cameras="{ top: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30},follower: {type: opencv, index_or_path: 4, width: 640, height: 480, fps: 30}}" \
          --teleop.type=so101_leader \
          --teleop.port=/dev/ttyACM0 \
          --teleop.id=leader_arm_fan1 \
          --display_data=true \
          --dataset.repo_id=gautz/18650-test1-10ep \
          --dataset.episode_time_s=10 \
          --dataset.reset_time_s=10 \
          --dataset.num_episodes=10 \
          --dataset.single_task="Pick red 18650 battery place black box" \
          --dataset.push_to_hub=False

      Entrainer en local avec le CPU

      python lerobot/scripts/train.py \
        --dataset.repo_id=gautz/18650-test1-10ep \
        --policy.type=act \
        --output_dir=outputs/train/act_so101_18650-test1-10ep \
        --job_name=act_so101_18650-test1-10ep \
        --policy.device=cpu # \
        --wandb.enable=false # true

      Entrainer en local avec le GPU NVidia

      python lerobot/scripts/train.py \
        --dataset.repo_id=gautz/18650-test1-10ep \
        --policy.type=act \
        --output_dir=outputs/train/act_so101_18650-test1-10ep \
        --job_name=act_so101_18650-test1-10ep \
        --policy.device=cuda \
        --wandb.enable=false

      Enregistrer un dataset d'évaluation d'un modèle à un checkpoint donné :

      python -m lerobot.record  \
      --robot.type=so101_follower \
      --robot.port=/dev/ttyUSB0 \
      --robot.cameras="{ top: {type: opencv, index_or_path: 2, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 4, width: 800, height: 600, fps: 30}}" \
      --robot.id=follower_arm_fan1 \
      --display_data=false \
      --dataset.repo_id=gautz/eval_act_18650-test2-100ep \
      --dataset.single_task="Pick red 18650 battery place black box" \
      --policy.path=outputs/train/act_so101_18650-test2-100ep/checkpoints/last/pretrained_model \
      --dataset.push_to_hub=False

      Utilisation de LeRobot avec Anaconda Powershell Prompt

      Calibration des robots

      python -m lerobot.setup_motors --robot.type=so101_follower --robot.port=COM13
      python -m lerobot.setup_motors --robot.type=so101_leader --robot.port=COM14

      Machine Learning

      Collecte de données :

      Uploader les données vers le Hub HuggingFace :

      https://huggingface.co/docs/lerobot/en/il_robots#dataset-upload 

      huggingface-cli.exe upload gautz/so101_pick_red_18650_drop_black_box_test2_100ep ..\.cache\huggingface\lerobot\gautz\18650-test2-100ep\ --repo-type dataset

      Entrainer un modèle sur un Dataset (sur IHA-QLIOVR-1, compte admin) :

      cd ..\gauthier.hentz\lerobot\
      conda activate lerobot
      cd .\lerobot\
      conda create -y -n lerobot python=3.10
      conda activate lerobot
      conda install ffmpeg -c conda-forge
      ffmpeg -encoders
      conda install ffmpeg=7.1.1 -c conda-forge
      pip install av poetry-core 
      pip3 install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
      pip install -e .
      python lerobot/scripts/train.py --dataset.repo_id=gautz/18650-test2-100ep --policy.type=act --output_dir=outputs/train/act_so101_18650-test2-100ep --job_name=act_so101_18650-test2-100ep --policy.device=cuda --wandb.enable=false
      

      Enregistrer un dataset d'évaluation d'un modèle à un checkpoint donné :

      python -m lerobot.record  --robot.type=so101_follower --robot.port=/dev/ttyUSB0 --robot.cameras="{ top: {type: opencv, index_or_path: 2, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 4, width: 800, height: 600, fps: 30}}" --robot.id=follower_arm_fan1 --display_data=false --dataset.repo_id=gautz/eval_act_18650-test2-100ep --dataset.single_task="Pick red 18650 battery place black box" --policy.path=outputs/train/act_so101_18650-test2-100ep/checkpoints/last/pretrained_model --dataset.push_to_hub=False

      Uploader un modèle vers HuggingFace

      https://github.com/huggingface/lerobot/?tab=readme-ov-file#add-a-pretrained-policy 

      • Rechercher le dossier du Checkpoint voulu, par ex.
        C:\Users\User\github\lerobot\outputs\train\act_so101_18650-test2-100ep\checkpoints\100000
      • Définir le User HuggingFace (qui doit être Login via un Token) gautz et le Repo act_so101_pick_red_18650_drop_black_box_test2_100ep_100000 , puis uploader le Checkpoint :
        huggingface-cli.exe upload gautz/act_so101_pick_red_18650_drop_black_box_test2_100ep_100000 .\outputs\train\act_so101_18650-test2-100ep\checkpoints\100000

      Historique du Terminal complet

      wget "https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe" -outfile ".\Downloads\Miniconda3-latest-Windows-x86_64.exe"
      cd .\github\lerobot\
      conda create -y -n lerobot python=3.10
      conda activate lerobot
      conda install ffmpeg -c conda-forge
      conda install ffmpeg=7.1.1 -c conda-forge
      wsl --shutdown
      pip install -e .
      pip install -e ".[feetech]" # or "[dynamixel]" for example
      python lerobot/find_port.py
      python lerobot/find_cameras.py opencv 
      python -m lerobot.setup_motors --robot.type=so101_follower --robot.port=COM13`
      python -m lerobot.record  --robot.type=so101_follower --robot.port=COM13 --robot.cameras="{ top: {type: opencv, index_or_path: 2, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 4, width: 800, height: 600, fps: 30}}" --robot.id=follower_arm_fan1 --display_data=false --dataset.repo_id=gautz/eval_act_18650-test2-100ep --dataset.single_task="Pick red 18650 battery place black box" --policy.path=outputs/train/act_so101_18650-test2-100ep/checkpoints/last/pretrained_model --dataset.push_to_hub=False
      python -m lerobot.calibrate     --teleop.type=so101_leader  --teleop.port=COM14 --teleop.id=leader_arm_fan1`
      python -m lerobot.calibrate     --robot.type=so101_follower  --robot.port=COM13 --robot.id=follower_arm_fan1
      python -m lerobot.teleoperate   --robot.type=so101_follower   --robot.port=COM13   --robot.id=follower_arm_fan1   --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30},follower: {type: opencv, index_or_path: 2, width: 640, height: 480, fps: 30}}"   --teleop.type=so101_leader   --teleop.port=COM14   --teleop.id=leader_arm_fan1   --display_data=true
      python lerobot/find_cameras.py opencv 
      python -m lerobot.teleoperate   --robot.type=so101_follower   --robot.port=COM13   --robot.id=follower_arm_fan1   --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 2, width: 800, height: 600, fps: 30}}"   --teleop.type=so101_leader   --teleop.port=COM14   --teleop.id=leader_arm_fan1   --display_data=true
      pip install -e .
      python lerobot/find_cameras.py opencv 
      python -m lerobot.teleoperate   --robot.type=so101_follower   --robot.port=COM13   --robot.id=follower_arm_fan1   --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30}}"   --teleop.type=so101_leader   --teleop.port=COM14   --teleop.id=leader_arm_fan1   --display_data=true
      python -m lerobot.record  --robot.type=so101_follower --robot.port=COM13 --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30}}" --robot.id=follower_arm_fan1 --display_data=false --dataset.repo_id=gautz/eval_act_18650-test2-100ep --dataset.single_task="Pick red 18650 battery place black box" --policy.path=outputs/train/act_so101_18650-test2-100ep/checkpoints/last/pretrained_model --dataset.push_to_hub=False
      python lerobot/scripts/display_sys_info.py
      python -m torch.utils.collect_env
      python -c "import torch; print(torch.cuda.is_available())" && nvcc -V
      python -c "import torch; print(torch.cuda.is_available())"
      pip3 install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
      python -m lerobot.record  --robot.type=so101_follower --robot.port=COM13 --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30}}" --robot.id=follower_arm_fan1 --display_data=false --dataset.repo_id=gautz/eval_act_18650-test2-100ep --dataset.single_task="Pick red 18650 battery place black box" --policy.path=outputs/train/act_so101_18650-test2-100ep/checkpoints/last/pretrained_model --dataset.push_to_hub=False --wandb.enable=false
      python -m lerobot.record  --robot.type=so101_follower --robot.port=COM13 --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30}}" --robot.id=follower_arm_fan1 --display_data=false --dataset.repo_id=gautz/eval_act_18650-test2-100ep --dataset.single_task="Pick red 18650 battery place black box" --policy.path=outputs/train/act_so101_18650-test2-100ep/checkpoints/last/pretrained_model --dataset.push_to_hub=False     --dataset.episode_time_s=10  --dataset.reset_time_s=10    --dataset.num_episodes=10
      exit
      cd .\github\lerobot\
      conda activate lerobot
      python -m lerobot.record  --robot.type=so101_follower --robot.port=COM13 --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30}}" --robot.id=follower_arm_fan1 --display_data=false --dataset.repo_id=gautz/eval_act_18650-test2-100ep --dataset.single_task="Pick red 18650 battery place black box" --policy.path=outputs/train/act_so101_18650-test2-100ep/checkpoints/last/pretrained_model --dataset.push_to_hub=False     --dataset.episode_time_s=15  --dataset.reset_time_s=10    --dataset.num_episodes=10
      python -m lerobot.teleoperate   --robot.type=so101_follower   --robot.port=COM13   --robot.id=follower_arm_fan1   --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30}}"   --teleop.type=so101_leader   --teleop.port=COM14   --teleop.id=leader_arm_fan1   --display_data=true
      exit
      cd .\github\lerobot\
      conda activate lerobot
      python -m lerobot.teleoperate   --robot.type=so101_follower   --robot.port=COM13   --robot.id=follower_arm_fan1   --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30}}"   --teleop.type=so101_leader   --teleop.port=COM14   --teleop.id=leader_arm_fan1   --display_data=true
      python lerobot/find_port.py
      python -m lerobot.teleoperate   --robot.type=so101_follower   --robot.port=COM15   --robot.id=follower_arm_fan1   --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30}}"   --teleop.type=so101_leader   --teleop.port=COM14   --teleop.id=leader_arm_fan1   --display_data=true
      python lerobot/find_cameras.py opencv 
      python -m lerobot.teleoperate   --robot.type=so101_follower   --robot.port=COM15   --robot.id=follower_arm_fan1   --robot.cameras="{ top: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 2, width: 800, height: 600, fps: 30}}"   --teleop.type=so101_leader   --teleop.port=COM14   --teleop.id=leader_arm_fan1   --display_data=true
      python -m lerobot.record  --robot.type=so101_follower --robot.port=COM15 --robot.cameras="{ top: {type: opencv, index_or_path: 1, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30}}" --robot.id=follower_arm_fan1 --display_data=false --dataset.repo_id=gautz/eval_act_18650-test2-100ep --dataset.single_task="Pick red 18650 battery place black box" --policy.path=outputs/train/act_so101_18650-test2-100ep/checkpoints/last/pretrained_model --dataset.push_to_hub=False     --dataset.episode_time_s=15  --dataset.reset_time_s=10    --dataset.num_episodes=10
      python -m lerobot.record  --robot.type=so101_follower --robot.port=COM15 --robot.cameras="{ top: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 2, width: 800, height: 600, fps: 30}}" --robot.id=follower_arm_fan1 --display_data=false --dataset.repo_id=gautz/eval_act_18650-test2-100ep --dataset.single_task="Pick red 18650 battery place black box" --policy.path=outputs/train/act_so101_18650-test2-100ep/checkpoints/last/pretrained_model --dataset.push_to_hub=False     --dataset.episode_time_s=15  --dataset.reset_time_s=10    --dataset.num_episodes=10
      python -m lerobot.teleoperate   --robot.type=so101_follower   --robot.port=COM15   --robot.id=follower_arm_fan1   --robot.cameras="{ top: {type: opencv, index_or_path: 0, width: 800, height: 600, fps: 30},follower: {type: opencv, index_or_path: 2, width: 800, height: 600, fps: 30}}"   --teleop.type=so101_leader   --teleop.port=COM14   --teleop.id=leader_arm_fan1   --display_data=true
      cd .\github\lerobot\
      cd ..
      cd .\.cache\
      cd .\huggingface\ls
      cd .\huggingface\lerobot\calibration\cd ..
      cd .\huggingface\lerobot\
      cd .\gautz\
      cd ..
      cd .\github\lerobot\
      cd .\outputs\train\
      cd .\act_so101_18650-test2-100ep\
      cd .\checkpoints\

      Migration dataset  v2.1 to v3

      https://github.com/huggingface/lerobot/blob/main/docs/source/lerobot-dataset-v3.mdx#migrate-v21--v30 

      Visualiser et rejouer des DataSets (avant hardware refactor)

      • Visualiser un DataSet

      python lerobot/scripts/visualize_dataset.py     --repo-id lerobot/pusht     --root ./my_local_data_dir     --local-files-only 1     --episode-index 0

      python lerobot/scripts/visualize_dataset_html.py \
        --repo-id cadene/act_so100_5_lego_test_080000 \
        --local-files-only 1
      • Rejouer un DataSet (ou une évaluation de modèle) sur le robot
      python lerobot/scripts/control_robot.py \
        --robot.type=so101 \
        --control.type=replay \
        --control.fps=30 \
        --control.repo_id=cadene/act_so100_5_lego_test_080000 \
        --control.episode=0
      • Rejouer la Policy cadene/act_so100_5_lego_test_080000 du modèle ACT pour le SO-ARM101
        • En sauvegardant l'évaluation dans outputs/eval/act_so100_5_lego_test_080000_haguenau
      python lerobot/scripts/control_robot.py \
        --robot.type=so101 \
        --control.type=record \
        --control.fps=30 \
        --control.single_task="Grasp a lego block and put it in the bin." \
        --control.repo_id=outputs/eval/act_so100_5_lego_test_080000_haguenau \
        --control.tags='["tutorial"]' \
        --control.warmup_time_s=5 \
        --control.episode_time_s=30 \
        --control.reset_time_s=30 \
        --control.num_episodes=10 \
        --control.push_to_hub=false \
        --control.policy.path=cadene/act_so100_5_lego_test_080000

      Sources

      https://wiki.seeedstudio.com/lerobot_so100m/ 

      https://huggingface.co/spaces/lerobot/visualize_dataset?path=%2Fsebastiandavidlee%2Fbimanual-so101-handover-plushie%2Fepisode_40 

      https://huggingface.co/blog/sherryxychen/train-act-on-so-101 

      https://github.com/sherrychen1120/so101_bench 

      https://www.linkedin.com/posts/sherryxychen_robotics-machinelearning-ai-ugcPost-7378831270207954944-WsI5?utm_source=share&utm_medium=member_desktop&rcm=ACoAAA1icaQBkYXRoM1Oslzrh8psuL0MmHpaT_4