| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| """ |
| Replays the actions of an episode from a dataset on a robot. |
| |
| Example: |
| |
| ```shell |
| lerobot-replay \ |
| --robot.type=so100_follower \ |
| --robot.port=/dev/tty.usbmodem58760431541 \ |
| --robot.id=black \ |
| --dataset.repo_id=<USER>/record-test \ |
| --dataset.episode=2 |
| ``` |
| """ |
|
|
| import logging |
| import time |
| from dataclasses import asdict, dataclass |
| from pathlib import Path |
| from pprint import pformat |
|
|
| import draccus |
|
|
| from lerobot.datasets import LeRobotDataset |
| from lerobot.robots import ( |
| Robot, |
| RobotConfig, |
| koch_follower, |
| make_robot_from_config, |
| so_follower, |
| ) |
| from lerobot.utils.constants import ACTION |
| from lerobot.utils.robot_utils import precise_sleep |
| from lerobot.utils.utils import ( |
| init_logging, |
| log_say, |
| ) |
|
|
|
|
| @dataclass |
| class DatasetReplayConfig: |
| |
| repo_id: str |
| |
| episode: int |
| |
| root: str | Path | None = None |
| |
| fps: int = 30 |
|
|
|
|
| @dataclass |
| class ReplayConfig: |
| robot: RobotConfig |
| dataset: DatasetReplayConfig |
| |
| play_sounds: bool = True |
|
|
|
|
| @draccus.wrap() |
| def replay(cfg: ReplayConfig): |
| init_logging() |
| logging.info(pformat(asdict(cfg))) |
|
|
| robot = make_robot_from_config(cfg.robot) |
| dataset = LeRobotDataset(cfg.dataset.repo_id, root=cfg.dataset.root, episodes=[cfg.dataset.episode]) |
| actions = dataset.select_columns(ACTION) |
| robot.connect() |
|
|
| try: |
| log_say("Replaying episode", cfg.play_sounds, blocking=True) |
| for idx in range(dataset.num_frames): |
| start_episode_t = time.perf_counter() |
|
|
| action_array = actions[idx][ACTION] |
| action = {} |
| for i, name in enumerate(dataset.features[ACTION]["names"]): |
| key = f"{name.removeprefix('main_')}.pos" |
| action[key] = action_array[i].item() |
|
|
| action["shoulder_lift.pos"] = -(action["shoulder_lift.pos"] - 90) |
| action["elbow_flex.pos"] -= 90 |
| robot.send_action(action) |
|
|
| dt_s = time.perf_counter() - start_episode_t |
| precise_sleep(max(1 / dataset.fps - dt_s, 0.0)) |
| finally: |
| robot.disconnect() |
|
|
|
|
| if __name__ == "__main__": |
| replay() |
|
|