| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| from lerobot.datasets import LeRobotDataset |
| from lerobot.processor import make_default_processors |
| from lerobot.robots.lekiwi import LeKiwiClient, LeKiwiClientConfig |
| from lerobot.scripts.lerobot_record import record_loop |
| from lerobot.teleoperators.keyboard import KeyboardTeleop, KeyboardTeleopConfig |
| from lerobot.teleoperators.so_leader import SO100Leader, SO100LeaderConfig |
| from lerobot.utils.constants import ACTION, OBS_STR |
| from lerobot.utils.feature_utils import hw_to_dataset_features |
| from lerobot.utils.keyboard_input import init_keyboard_listener |
| from lerobot.utils.utils import log_say |
| from lerobot.utils.visualization_utils import init_rerun |
|
|
| NUM_EPISODES = 2 |
| FPS = 30 |
| EPISODE_TIME_SEC = 30 |
| RESET_TIME_SEC = 10 |
| TASK_DESCRIPTION = "My task description" |
| HF_REPO_ID = "<hf_username>/<dataset_repo_id>" |
|
|
|
|
| def main(): |
| |
| robot_config = LeKiwiClientConfig(remote_ip="172.18.134.136", id="lekiwi") |
| leader_arm_config = SO100LeaderConfig(port="/dev/tty.usbmodem585A0077581", id="my_awesome_leader_arm") |
| keyboard_config = KeyboardTeleopConfig() |
|
|
| |
| robot = LeKiwiClient(robot_config) |
| leader_arm = SO100Leader(leader_arm_config) |
| keyboard = KeyboardTeleop(keyboard_config) |
|
|
| |
| action_features = hw_to_dataset_features(robot.action_features, ACTION) |
| obs_features = hw_to_dataset_features(robot.observation_features, OBS_STR) |
| dataset_features = {**action_features, **obs_features} |
|
|
| |
| dataset = LeRobotDataset.create( |
| repo_id=HF_REPO_ID, |
| fps=FPS, |
| features=dataset_features, |
| robot_type=robot.name, |
| use_videos=True, |
| image_writer_threads=4, |
| ) |
|
|
| |
| |
| robot.connect() |
| leader_arm.connect() |
| keyboard.connect() |
|
|
| |
| listener, events = init_keyboard_listener() |
| init_rerun(session_name="lekiwi_record") |
|
|
| try: |
| if not robot.is_connected or not leader_arm.is_connected or not keyboard.is_connected: |
| raise ValueError("Robot or teleop is not connected!") |
|
|
| teleop_action_processor, robot_action_processor, robot_observation_processor = ( |
| make_default_processors() |
| ) |
|
|
| print("Starting record loop...") |
| recorded_episodes = 0 |
| while recorded_episodes < NUM_EPISODES and not events["stop_recording"]: |
| log_say(f"Recording episode {recorded_episodes}") |
|
|
| |
| record_loop( |
| robot=robot, |
| events=events, |
| fps=FPS, |
| teleop_action_processor=teleop_action_processor, |
| robot_action_processor=robot_action_processor, |
| robot_observation_processor=robot_observation_processor, |
| dataset=dataset, |
| teleop=[leader_arm, keyboard], |
| control_time_s=EPISODE_TIME_SEC, |
| single_task=TASK_DESCRIPTION, |
| display_data=True, |
| ) |
|
|
| |
| if not events["stop_recording"] and ( |
| (recorded_episodes < NUM_EPISODES - 1) or events["rerecord_episode"] |
| ): |
| log_say("Reset the environment") |
| record_loop( |
| robot=robot, |
| events=events, |
| fps=FPS, |
| teleop_action_processor=teleop_action_processor, |
| robot_action_processor=robot_action_processor, |
| robot_observation_processor=robot_observation_processor, |
| teleop=[leader_arm, keyboard], |
| control_time_s=RESET_TIME_SEC, |
| single_task=TASK_DESCRIPTION, |
| display_data=True, |
| ) |
|
|
| if events["rerecord_episode"]: |
| log_say("Re-record episode") |
| events["rerecord_episode"] = False |
| events["exit_early"] = False |
| dataset.clear_episode_buffer() |
| continue |
|
|
| |
| dataset.save_episode() |
| recorded_episodes += 1 |
| finally: |
| |
| log_say("Stop recording") |
| robot.disconnect() |
| leader_arm.disconnect() |
| keyboard.disconnect() |
| listener.stop() |
|
|
| dataset.finalize() |
| dataset.push_to_hub() |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|