Compare commits

...

5 Commits

Author SHA1 Message Date
Nikodem Bartnik 6dc9391013 update record API example for consistency 2026-05-18 10:37:29 +02:00
Nikodem Bartnik dca76c07a9 update record example 2026-05-18 09:39:16 +02:00
Nikodem Bartnik 4a6d7f44f1 update teleoperate with cameras 2026-05-18 09:37:16 +02:00
Nikodem Bartnik da1402e4b9 update teleoperation example 2026-05-18 09:36:43 +02:00
Nikodem Bartnik 2cc66766a0 fix api recording example 2026-05-14 13:29:31 +02:00
+124 -100
View File
@@ -68,13 +68,13 @@ from lerobot.teleoperators.so_leader import SO101Leader, SO101LeaderConfig
from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
robot_config = SO101FollowerConfig( robot_config = SO101FollowerConfig(
port="/dev/tty.usbmodem58760431541", port="/dev/tty.usbmodem5AB90687491",
id="my_red_robot_arm", id="my_follower_arm",
) )
teleop_config = SO101LeaderConfig( teleop_config = SO101LeaderConfig(
port="/dev/tty.usbmodem58760431551", port="/dev/tty.usbmodem5AB90689011",
id="my_blue_leader_arm", id="my_leader_arm",
) )
robot = SO101Follower(robot_config) robot = SO101Follower(robot_config)
@@ -122,34 +122,48 @@ lerobot-teleoperate \
<!-- prettier-ignore-start --> <!-- prettier-ignore-start -->
```python ```python
import time
from lerobot.teleoperators.so_leader import SO101Leader, SO101LeaderConfig
from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
from lerobot.cameras.opencv import OpenCVCameraConfig from lerobot.cameras.opencv import OpenCVCameraConfig
from lerobot.teleoperators.koch_leader import KochLeader, KochLeaderConfig from lerobot.utils.visualization_utils import init_rerun, log_rerun_data, shutdown_rerun
from lerobot.robots.koch_follower import KochFollower, KochFollowerConfig
camera_config = { robot_config = SO101FollowerConfig(
"front": OpenCVCameraConfig(index_or_path=0, width=1920, height=1080, fps=30) port="/dev/tty.usbmodem5AB90687491",
} id="my_follower_arm",
cameras={
robot_config = KochFollowerConfig( "wrist": OpenCVCameraConfig(index_or_path=0, width=640, height=480, fps=30),
port="/dev/tty.usbmodem585A0076841", "top": OpenCVCameraConfig(index_or_path=1, width=640, height=480, fps=30)
id="my_red_robot_arm", }
cameras=camera_config
) )
teleop_config = KochLeaderConfig( teleop_config = SO101LeaderConfig(
port="/dev/tty.usbmodem58760431551", port="/dev/tty.usbmodem5AB90689011",
id="my_blue_leader_arm", id="my_leader_arm",
) )
robot = KochFollower(robot_config) init_rerun(session_name="teleoperation")
teleop_device = KochLeader(teleop_config)
robot = SO101Follower(robot_config)
teleop_device = SO101Leader(teleop_config)
robot.connect() robot.connect()
teleop_device.connect() teleop_device.connect()
TARGET_HZ = 30
TIME_PER_FRAME = 1.0 / TARGET_HZ
while True: while True:
start_time = time.perf_counter()
observation = robot.get_observation() observation = robot.get_observation()
action = teleop_device.get_action() action = teleop_device.get_action()
robot.send_action(action) robot.send_action(action)
log_rerun_data(observation=observation, action=action)
elapsed_time = time.perf_counter() - start_time
sleep_time = TIME_PER_FRAME - elapsed_time
if sleep_time > 0:
time.sleep(sleep_time)
``` ```
<!-- prettier-ignore-end --> <!-- prettier-ignore-end -->
@@ -202,10 +216,11 @@ lerobot-record \
<!-- prettier-ignore-start --> <!-- prettier-ignore-start -->
```python ```python
from lerobot.cameras.opencv import OpenCVCameraConfig from lerobot.cameras.opencv import OpenCVCameraConfig
from lerobot.datasets import LeRobotDataset from lerobot.datasets.lerobot_dataset import LeRobotDataset
from lerobot.utils.feature_utils import hw_to_dataset_features from lerobot.utils.feature_utils import hw_to_dataset_features
from lerobot.robots.so_follower import SO100Follower, SO100FollowerConfig from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
from lerobot.teleoperators.so_leader import SO100Leader, SO100LeaderConfig from lerobot.teleoperators.so_leader.config_so_leader import SO101LeaderConfig
from lerobot.teleoperators.so_leader.so_leader import SO101Leader
from lerobot.common.control_utils import init_keyboard_listener from lerobot.common.control_utils import init_keyboard_listener
from lerobot.utils.utils import log_say from lerobot.utils.utils import log_say
from lerobot.utils.visualization_utils import init_rerun from lerobot.utils.visualization_utils import init_rerun
@@ -218,71 +233,56 @@ EPISODE_TIME_SEC = 60
RESET_TIME_SEC = 10 RESET_TIME_SEC = 10
TASK_DESCRIPTION = "My task description" TASK_DESCRIPTION = "My task description"
# Create robot configuration def main():
robot_config = SO100FollowerConfig( # Create robot configuration
id="my_awesome_follower_arm", robot_config = SO101FollowerConfig(
cameras={ port="/dev/tty.usbmodem5AB90687491",
"front": OpenCVCameraConfig(index_or_path=0, width=640, height=480, fps=FPS) # Optional: fourcc="MJPG" for troubleshooting OpenCV async error. id="my_follower_arm",
}, cameras={
port="/dev/tty.usbmodem58760434471", "wrist": OpenCVCameraConfig(index_or_path=0, width=640, height=480, fps=30),
) "top": OpenCVCameraConfig(index_or_path=1, width=640, height=480, fps=30)
}
teleop_config = SO100LeaderConfig(
id="my_awesome_leader_arm",
port="/dev/tty.usbmodem585A0077581",
)
# Initialize the robot and teleoperator
robot = SO100Follower(robot_config)
teleop = SO100Leader(teleop_config)
# Configure the dataset features
action_features = hw_to_dataset_features(robot.action_features, "action")
obs_features = hw_to_dataset_features(robot.observation_features, "observation")
dataset_features = {**action_features, **obs_features}
# Create the dataset
dataset = LeRobotDataset.create(
repo_id="<hf_username>/<dataset_repo_id>",
fps=FPS,
features=dataset_features,
robot_type=robot.name,
use_videos=True,
image_writer_threads=4,
)
# Initialize the keyboard listener and rerun visualization
_, events = init_keyboard_listener()
init_rerun(session_name="recording")
# Connect the robot and teleoperator
robot.connect()
teleop.connect()
# Create the required processors
teleop_action_processor, robot_action_processor, robot_observation_processor = make_default_processors()
episode_idx = 0
while episode_idx < NUM_EPISODES and not events["stop_recording"]:
log_say(f"Recording episode {episode_idx + 1} of {NUM_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,
teleop=teleop,
dataset=dataset,
control_time_s=EPISODE_TIME_SEC,
single_task=TASK_DESCRIPTION,
display_data=True,
) )
# Reset the environment if not stopping or re-recording teleop_config = SO101LeaderConfig(
if not events["stop_recording"] and (episode_idx < NUM_EPISODES - 1 or events["rerecord_episode"]): port="/dev/tty.usbmodem5AB90689011",
log_say("Reset the environment") id="my_leader_arm",
)
# Initialize the robot and teleoperator
robot = SO101Follower(robot_config)
teleop = SO101Leader(teleop_config)
# Configure the dataset features
action_features = hw_to_dataset_features(robot.action_features, "action")
obs_features = hw_to_dataset_features(robot.observation_features, "observation")
dataset_features = {**action_features, **obs_features}
# Create the dataset
dataset = LeRobotDataset.create(
repo_id="<hf_username>/<dataset_repo_id>",
fps=FPS,
features=dataset_features,
robot_type=robot.name,
use_videos=True,
image_writer_threads=4,
)
# Initialize the keyboard listener and rerun visualization
_, events = init_keyboard_listener()
init_rerun(session_name="recording")
# Connect the robot and teleoperator
robot.connect()
teleop.connect()
# Create the required processors
teleop_action_processor, robot_action_processor, robot_observation_processor = make_default_processors()
episode_idx = 0
while episode_idx < NUM_EPISODES and not events["stop_recording"]:
log_say(f"Recording episode {episode_idx + 1} of {NUM_EPISODES}")
record_loop( record_loop(
robot=robot, robot=robot,
events=events, events=events,
@@ -291,26 +291,50 @@ while episode_idx < NUM_EPISODES and not events["stop_recording"]:
robot_action_processor=robot_action_processor, robot_action_processor=robot_action_processor,
robot_observation_processor=robot_observation_processor, robot_observation_processor=robot_observation_processor,
teleop=teleop, teleop=teleop,
control_time_s=RESET_TIME_SEC, dataset=dataset,
control_time_s=EPISODE_TIME_SEC,
single_task=TASK_DESCRIPTION, single_task=TASK_DESCRIPTION,
display_data=True, display_data=True,
) )
if events["rerecord_episode"]: # Reset the environment if not stopping or re-recording
log_say("Re-recording episode") if not events["stop_recording"] and (episode_idx < NUM_EPISODES - 1 or events["rerecord_episode"]):
events["rerecord_episode"] = False log_say("Reset the environment")
events["exit_early"] = False record_loop(
dataset.clear_episode_buffer() robot=robot,
continue events=events,
fps=FPS,
teleop_action_processor=teleop_action_processor,
robot_action_processor=robot_action_processor,
robot_observation_processor=robot_observation_processor,
teleop=teleop,
control_time_s=RESET_TIME_SEC,
single_task=TASK_DESCRIPTION,
display_data=True,
)
dataset.save_episode() if events["rerecord_episode"]:
episode_idx += 1 log_say("Re-recording episode")
events["rerecord_episode"] = False
events["exit_early"] = False
dataset.clear_episode_buffer()
continue
# Clean up dataset.save_episode()
log_say("Stop recording") episode_idx += 1
robot.disconnect()
teleop.disconnect() # finalize dataset
dataset.push_to_hub() log_say("Finalizing dataset...")
dataset.finalize()
# Clean up
log_say("Stop recording")
robot.disconnect()
teleop.disconnect()
dataset.push_to_hub()
if __name__ == "__main__":
main()
``` ```
<!-- prettier-ignore-end --> <!-- prettier-ignore-end -->
@@ -422,7 +446,7 @@ from lerobot.utils.utils import log_say
episode_idx = 0 episode_idx = 0
robot_config = SO100FollowerConfig(port="/dev/tty.usbmodem58760434471", id="my_awesome_follower_arm") robot_config = SO100FollowerConfig(port="/dev/tty.usbmodem5AB90687491", id="my_follower_arm")
robot = SO100Follower(robot_config) robot = SO100Follower(robot_config)
robot.connect() robot.connect()