Case Study: Getting Started with LeRobot

conda activate lerobot

Grant permission

sudo nano /etc/udev/rules.d/50-lerobot.rules
50-lerobot.rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d3", GROUP="users", MODE="0666"
sudo udevadm control --reload-rules
sudo udevadm trigger

Teleoperation demo

python lerobot/scripts/control_robot.py teleoperate \
  --robot-path lerobot/configs/robot/koch.yaml

Login to hugging face

huggingface-cli login --token ${HUGGINGFACE_TOKEN} --add-to-git-credential
HF_USER=$(huggingface-cli whoami | head -n 1)
echo $HF_USER

record dataset

python lerobot/scripts/control_robot.py record \
  --robot-path lerobot/configs/robot/koch.yaml \
  --fps 30 \
  --root data \
  --repo-id ${HF_USER}/koch_test \
  --tags tutorial \
  --num-episodes 2 \
  --warmup-time-s 5 \
  --episode-time-s 30 \
  --reset-time-s 30

full 50 episodes!

python lerobot/scripts/control_robot.py record \
  --robot-path lerobot/configs/robot/koch.yaml \
  --fps 30 \
  --root data \
  --repo-id ${HF_USER}/koch_place_block \
  --tags tutorial \
  --num-episodes 50 \
  --warmup-time-s 2 \
  --episode-time-s 30 \
  --reset-time-s 10

Visualize

python lerobot/scripts/visualize_dataset_html.py \
  --root data \
  --repo-id ${HF_USER}/koch_place_block

Replay

python lerobot/scripts/control_robot.py replay \
  --robot-path lerobot/configs/robot/koch.yaml \
  --fps 30 \
  --root data \
  --repo-id ${HF_USER}/koch_place_block \
  --episode 0

Training!!

DATA_DIR=data python lerobot/scripts/train.py \
  dataset_repo_id=${HF_USER}/koch_place_block \
  policy=act_koch_real \
  env=koch_real \
  hydra.run.dir=outputs/train/act_koch_place_block \
  hydra.job.name=act_koch_place_block \
  device=cuda \
  wandb.enable=true

upload trained model

huggingface-cli upload ${HF_USER}/act_koch_place_block   outputs/train/act_koch_place_block/checkpoints/last/pretrained_model

eval

python lerobot/scripts/control_robot.py record \
  --robot-path lerobot/configs/robot/koch.yaml \
  --fps 30 \
  --root data \
  --repo-id ${HF_USER}/eval_koch_place_block \
  --tags tutorial eval \
  --warmup-time-s 5 \
  --episode-time-s 30 \
  --reset-time-s 30 \
  --num-episodes 10 \
  -p outputs/train/act_koch_place_block/checkpoints/last/pretrained_model

Teleop Script

import tqdm
from lerobot.common.robot_devices.motors.dynamixel import DynamixelMotorsBus
from lerobot.common.robot_devices.motors.dynamixel import TorqueMode
from lerobot.common.robot_devices.robots.manipulator import ManipulatorRobot
from lerobot.common.robot_devices.cameras.opencv import OpenCVCamera


leader_port = "/dev/ttyACM0"
follower_port = "/dev/ttyACM1"

leader_arm = DynamixelMotorsBus(
    port=leader_port,
    motors={
        # name: (index, model)
        "shoulder_pan": (1, "xl330-m077"),
        "shoulder_lift": (2, "xl330-m077"),
        "elbow_flex": (3, "xl330-m077"),
        "wrist_flex": (4, "xl330-m077"),
        "wrist_roll": (5, "xl330-m077"),
        "gripper": (6, "xl330-m077"),
    },
)

follower_arm = DynamixelMotorsBus(
    port=follower_port,
    motors={
        # name: (index, model)
        "shoulder_pan": (1, "xl430-w250"),
        "shoulder_lift": (2, "xl430-w250"),
        "elbow_flex": (3, "xl330-m288"),
        "wrist_flex": (4, "xl330-m288"),
        "wrist_roll": (5, "xl330-m288"),
        "gripper": (6, "xl330-m288"),
    },
)

robot = ManipulatorRobot(
    robot_type="koch",
    leader_arms={"main": leader_arm},
    follower_arms={"main": follower_arm},
    calibration_dir=".cache/calibration/koch",
    cameras={
        "laptop": OpenCVCamera(0),
    },
)

robot.connect()

follower_arm.write("Torque_Enable", TorqueMode.ENABLED.value)

# # leader_pos = robot.leader_arms["main"].read("Present_Position")
# # follower_pos = robot.follower_arms["main"].read("Present_Position")

# # print(leader_pos)
# # print(follower_pos)

seconds = 120
frequency = 200

for _ in tqdm.tqdm(range(seconds*frequency)):
    leader_pos = robot.leader_arms["main"].read("Present_Position")
    robot.follower_arms["main"].write("Goal_Position", leader_pos)

    # observation, action = robot.teleop_step(record_data=True)
    # print(observation["observation.images.laptop"].shape)
    # print(observation["observation.images.phone"].shape)
    # print(observation["observation.images.laptop"].min().item())
    # print(observation["observation.images.laptop"].max().item())


follower_arm.write("Torque_Enable", TorqueMode.DISABLED.value)

robot.disconnect()

Last updated

Was this helpful?