Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions cameras.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import cv2
from lerobot.cameras.opencv.configuration_opencv import OpenCVCameraConfig
from lerobot.cameras.opencv.camera_opencv import OpenCVCamera
from lerobot.cameras.configs import ColorMode, Cv2Rotation

# First camera
config1 = OpenCVCameraConfig(
index_or_path=0,
width=1280,
height=720,
color_mode=ColorMode.RGB, # good for ML
rotation=Cv2Rotation.NO_ROTATION
)
camera1 = OpenCVCamera(config1)
camera1.connect()

# Second camera
config2 = OpenCVCameraConfig(
index_or_path=3,
width=1280,
height=720,
color_mode=ColorMode.RGB, # also RGB
rotation=Cv2Rotation.ROTATE_180
)
camera2 = OpenCVCamera(config2)
camera2.connect()

try:
while True:
# Grab latest available frames (non-blocking)
frame1 = camera1.async_read()
frame2 = camera2.async_read()

if frame1 is not None:
# convert for OpenCV display (expects BGR)
cv2.imshow("Camera 0", cv2.cvtColor(frame1, cv2.COLOR_RGB2BGR))

if frame2 is not None:
cv2.imshow("Camera 3", cv2.cvtColor(frame2, cv2.COLOR_RGB2BGR))

# Needed for display refresh + quit on 'q'
if cv2.waitKey(1) & 0xFF == ord("q"):
break

finally:
camera1.disconnect()
camera2.disconnect()
cv2.destroyAllWindows()
134 changes: 134 additions & 0 deletions src/lerobot/robots/meca/collect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
from lerobot.cameras.opencv.configuration_opencv import OpenCVCameraConfig
from lerobot.datasets.lerobot_dataset import LeRobotDataset
from lerobot.datasets.utils import hw_to_dataset_features
from lerobot.utils.control_utils import init_keyboard_listener
from lerobot.utils.utils import log_say
from lerobot.utils.visualization_utils import init_rerun
from lerobot.scripts.lerobot_record import record_loop

# Import your robot + teleop
from lerobot.robots.meca.meca import Meca
from lerobot.robots.meca.mecaconfig import MecaConfig
from lerobot.teleoperators.omni.omni import OmniTeleoperator, OmniConfig
from lerobot.policies.factory import make_policy, make_pre_post_processors

# ------------------------
# Experiment parameters
# ------------------------
NUM_EPISODES = 5
FPS = 30
EPISODE_TIME_SEC = 60
RESET_TIME_SEC = 10
TASK_DESCRIPTION = "Microsurgery teleop task"

# ------------------------
# Configurations
# ------------------------

# Cameras (adapt indices to your setup)
camera_config = {
"top": OpenCVCameraConfig(index_or_path=0, width=640, height=480, fps=FPS),
"bottom": OpenCVCameraConfig(index_or_path=3, width=1280, height=720, fps=260),
}

# Meca robot config
meca_cfg = MecaConfig(
ip="192.168.0.100", # <-- Replace with your robot IP
id="meca500",
cameras=camera_config,
)

# Omni haptic device config
omni_cfg = OmniConfig()

# ------------------------
# Instantiate
# ------------------------
robot = Meca(meca_cfg)
teleop = OmniTeleoperator(omni_cfg)

# 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}



try:
dataset = LeRobotDataset("dylanmcguir3/meca-needle-pick")
print("πŸ“‚ Loaded existing dataset")
except Exception:
# Otherwise, create it fresh
dataset = LeRobotDataset.create(
repo_id="dylanmcguir3/meca-needle-pick",
fps=FPS,
features=dataset_features,
robot_type=robot.name,
use_videos=True,
image_writer_threads=4,
)
print("πŸ“‚ Created new dataset")

# ------------------------
# Setup utils
# ------------------------
_, events = init_keyboard_listener()
init_rerun(session_name="meca_teleop_recording")

# ------------------------
# Main recording loop
# ------------------------
robot.connect()
teleop.connect()

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=teleop,
dataset=dataset,
control_time_s=EPISODE_TIME_SEC,
single_task=TASK_DESCRIPTION,
display_data=True,
teleop_action_processor=robot.teleop_action_processor,
robot_action_processor=robot.robot_action_processor,
robot_observation_processor=robot.robot_observation_processor,
)

# Reset environment if needed
if not events["stop_recording"] and (episode_idx < NUM_EPISODES - 1 or events["rerecord_episode"]):
log_say("Resetting environment...")
record_loop(
robot=robot,
events=events,
fps=FPS,
teleop=teleop,
control_time_s=RESET_TIME_SEC,
single_task=TASK_DESCRIPTION,
display_data=True,
robot_observation_processor=robot.robot_observation_processor,
teleop_action_processor=robot.teleop_action_processor,
robot_action_processor=robot.robot_action_processor,
)

if events["rerecord_episode"]:
log_say("Re-recording episode")
events["rerecord_episode"] = False
events["exit_early"] = False
dataset.clear_episode_buffer()
continue

dataset.save_episode()
episode_idx += 1

# ------------------------
# Cleanup
# ------------------------
log_say("Stopping recording...")
robot.disconnect()
teleop.disconnect()
dataset.push_to_hub()
109 changes: 109 additions & 0 deletions src/lerobot/robots/meca/inference.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
from pathlib import Path
import time

from lerobot.cameras.opencv.configuration_opencv import OpenCVCameraConfig
from lerobot.datasets.lerobot_dataset import LeRobotDataset
from lerobot.datasets.utils import hw_to_dataset_features
from lerobot.policies.diffusion.modeling_diffusion import DiffusionPolicy
from lerobot.robots.meca.mecaconfig import MecaConfig
from lerobot.robots.meca.meca import Meca
from lerobot.utils.control_utils import init_keyboard_listener
from lerobot.utils.utils import log_say
from lerobot.utils.visualization_utils import init_rerun
from lerobot.scripts.lerobot_record import record_loop
from lerobot.policies.factory import make_policy, make_pre_post_processors
import cv2


# -------------------------
# User settings
# -------------------------
NUM_EPISODES = 5
FPS = 30
EPISODE_TIME_SEC = 60
TASK_DESCRIPTION = "Microsurgery teleop task"

# πŸ‘‡ Fill in your actual repos
HF_USER = "dylanmcguir3"
HF_MODEL_ID = f"{HF_USER}/needle-pick" # trained diffusion policy
HF_DATASET_ID = f"{HF_USER}/meca-needle-pick" # dataset to store evaluation rollouts

# -------------------------
# Robot + camera config
# -------------------------
camera_config = {
"top": OpenCVCameraConfig(index_or_path=0, width=640, height=480, fps=FPS),
"bottom": OpenCVCameraConfig(index_or_path=3, width=1280, height=720, fps=260),
}

robot_config = MecaConfig(ip="192.168.0.100", id="meca_eval_robot", cameras=camera_config)
robot = Meca(robot_config)

# -------------------------
# Load trained policy
# -------------------------
policy = DiffusionPolicy.from_pretrained(Path("/home/dylan/LeRobot/lerobot/outputs/train/needle-pick-diffusion-test/checkpoints/100000/pretrained_model"))

# -------------------------
# 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}

dataset = LeRobotDataset.create(
repo_id=HF_DATASET_ID + "-eval",
fps=FPS,
features=dataset_features,
robot_type=robot.name,
use_videos=True,
image_writer_threads=4,
)

# -------------------------
# Keyboard + visualization
# -------------------------
_, events = init_keyboard_listener()
init_rerun(session_name="policy_eval")

# -------------------------
# Connect robot
# -------------------------
robot.connect()

# Pre/post processors for policy I/O
preprocessor, postprocessor = make_pre_post_processors(policy, pretrained_path=Path("/home/dylan/LeRobot/lerobot/outputs/train/needle-pick-diffusion-test/checkpoints/100000/pretrained_model"), dataset_stats=dataset.meta.stats)

# -------------------------
# Evaluation loop
# -------------------------
for episode_idx in range(NUM_EPISODES):
log_say(f"Running inference, recording eval episode {episode_idx + 1}/{NUM_EPISODES}")

record_loop(
robot=robot,
events=events,
fps=FPS,
policy=policy,
preprocessor=preprocessor,
postprocessor=postprocessor,
dataset=dataset,
control_time_s=EPISODE_TIME_SEC,
single_task=TASK_DESCRIPTION,
display_data=True,
teleop_action_processor=robot.teleop_action_processor,
robot_action_processor=robot.robot_action_processor,
robot_observation_processor=robot.robot_observation_processor,
)

if cv2.waitKey(1) & 0xFF == ord("r"):
robot.reset()


dataset.save_episode()

# -------------------------
# Cleanup
# -------------------------
robot.disconnect()
dataset.push_to_hub()
Loading