Delete test files

This commit is contained in:
glannuzel
2025-08-21 15:00:53 +02:00
parent 130a6a969b
commit 67acccf778
6 changed files with 0 additions and 830 deletions
@@ -1,439 +0,0 @@
from pathlib import Path
import json
import os
import shutil
from concurrent import futures
from typing import Dict
import threading
import grpc
from logging import getLogger
import torch.multiprocessing as mp
from lerobot.datasets.lerobot_dataset import LeRobotDataset
from lerobot.datasets.utils import hw_to_dataset_features
from lerobot.robots.reachy2 import Reachy2Robot, Reachy2RobotConfig
from lerobot.teleoperators.reachy2_fake_teleoperator import Reachy2FakeTeleoperator, Reachy2FakeTeleoperatorConfig
from lerobot.utils.utils import log_say
from lerobot.record import record_loop
from data_acquisition_api.data_acquisition_pb2 import (
ActionAck,
EpisodeRating,
SessionParams,
Dataset,
DatasetList,
DatasetPushState,
)
from data_acquisition_api.data_acquisition_pb2_grpc import add_DataAcquisitionServiceServicer_to_server
from google.protobuf.empty_pb2 import Empty
class DataAcquisitionServicer():
def __init__(
self,
):
self._logger = getLogger(__name__)
self.play_sound = True
self.thread: threading.Thread = None
self.events: Dict = {}
self.events["exit_early"] = False
self.setup_over = False
self.dataset_list_path = Path("datasets.json")
self.robot: Reachy2Robot = None
self.task: str = None
self.dataset: LeRobotDataset = None
self.fps: int
self.episode_duration: int
self.break_time_duration: int
self.episode_recording_in_progress: bool = False
self.episode_saved: bool = False
self.episode_recorded_in_session: bool = False
self.run_compute_stats: bool = True
def register_to_server(self, server):
add_DataAcquisitionServiceServicer_to_server(self, server)
def GetDatasetList(self, request: Empty, context: grpc.ServicerContext) -> DatasetList:
dataset_list = self.read_datasets_from_json(self.dataset_list_path)
return dataset_list
def RemoveDataset(self, request: Dataset, context: grpc.ServicerContext) -> ActionAck:
self.remove_dataset_by_name(request.dataset_name, self.dataset_list_path)
return ActionAck(success_ack=True)
def AddDataset(self, request: Dataset, context: grpc.ServicerContext) -> ActionAck:
# Create a new dataset
dataset = self.create_dataset(request.dataset_name, DatasetPushState.PUSHED, 0)
# Add it to the JSON file
self.add_dataset_to_json_file(dataset, self.dataset_list_path)
return ActionAck(success_ack=True)
def UpdateDataset(self, request: Dataset, context: grpc.ServicerContext) -> ActionAck:
self.update_dataset(request, self.dataset_list_path)
return ActionAck(success_ack=True)
def ClearAllDatasets(self, request: Empty, context: grpc.ServicerContext) -> ActionAck:
# Clear all datasets from the JSON file
self.clear_all_datasets(self.dataset_list_path)
return ActionAck(success_ack=True)
def RemoveSession(self, request: SessionParams, context: grpc.ServicerContext) -> ActionAck:
self.delete_folder(request.session_name)
return ActionAck(success_ack=True)
def ClearAllSessions(self, request: Empty, context: grpc.ServicerContext) -> ActionAck:
pass
# Session and Episode Management with LeRobot
def StartSession(self, request: SessionParams, context: grpc.ServicerContext) -> ActionAck:
self._logger.error(f"Starting session with params: {request}")
try:
self.setup_recording_session(request, context)
self.setup_over = True
ack = ActionAck(success_ack=True)
except Exception as e:
self._logger.error(f"Error starting session: {e}")
ack = ActionAck(success_ack=False)
return ack
def StopSession(self, request: Empty, context: grpc.ServicerContext) -> ActionAck:
self._logger.error("Stopping session")
try:
if self.thread and self.thread.is_alive():
self.thread.join() # Wait for the thread to finish
log_say("Stop recording", play_sounds=self.play_sound, blocking=True)
self.robot.disconnect()
ack = ActionAck(success_ack=True)
self._logger.error("Session stopped")
except Exception as e:
self._logger.error(f"Error stopping session: {e}")
ack = ActionAck(success_ack=False)
return ack
def StartEpisode(self, request: Empty, context: grpc.ServicerContext) -> ActionAck:
self._logger.error("Starting episode")
try:
if self.episode_recorded_in_session and not self.episode_saved:
self._logger.error("Episode not saved. Clearing episode buffer.")
self.dataset.clear_episode_buffer()
if not self.setup_over:
raise RuntimeError("Setup not completed. Please call StartSession first.")
if self.episode_recording_in_progress:
raise RuntimeError("Episode recording already in progress. Please stop it before starting a new one.")
self.episode_saved = False
self.thread = threading.Thread(target=self.record_episode)
self.thread.daemon = True
self.thread.start()
self.episode_recorded_in_session = True
ack = ActionAck(success_ack=True)
self._logger.error("Episode started")
except Exception as e:
self._logger.error(f"Error starting episode: {e}")
ack = ActionAck(success_ack=False)
return ack
def StopEpisode(self, request: Empty, context: grpc.ServicerContext) -> ActionAck:
self._logger.error("Stopping episode")
try:
self.events["exit_early"] = True
if self.thread and self.thread.is_alive():
self.thread.join() # Wait for the thread to finish
self.events["exit_early"] = False
ack = ActionAck(success_ack=True)
self._logger.error("Episode stopped")
except Exception as e:
self._logger.error(f"Error stopping session: {e}")
ack = ActionAck(success_ack=False)
return ack
def SaveEpisode(self, request: EpisodeRating, context: grpc.ServicerContext) -> ActionAck:
self._logger.error("Saving episode")
try:
if self.episode_recording_in_progress:
raise RuntimeError("Episode recording in progress. Please stop it before saving.")
self.dataset.save_episode()
self.episode_saved = True
ack = ActionAck(success_ack=True)
self._logger.error("Episode saved")
except Exception as e:
self._logger.error(f"Error saving episode: {e}")
ack = ActionAck(success_ack=False)
return ack
def UploadSession(self, request: Empty, context: grpc.ServicerContext) -> ActionAck:
try:
if self.episode_recording_in_progress:
raise RuntimeError("Episode recording in progress. Please stop it before uploading.")
self.dataset.push_to_hub()
ack = ActionAck(success_ack=True)
self._logger.error("Session uploaded")
except Exception as e:
self._logger.error(f"Error uploading session: {e}")
ack = ActionAck(success_ack=False)
return ack
def setup_recording_session(
self,
request: SessionParams,
context: grpc.ServicerContext,
):
# Create the robot and teleoperator configurations
self.robot_config = Reachy2RobotConfig(
ip_address=request.robot.ip_address,
id=request.robot.robot_id,
use_external_commands=True,
)
self.teleop_config = Reachy2FakeTeleoperatorConfig(
ip_address=request.robot.ip_address,
)
# Initialize the robot and teleoperator
self.robot = Reachy2Robot(self.robot_config)
self.teleop = Reachy2FakeTeleoperator(self.teleop_config)
self.fps = request.fps if request.HasField("fps") else 30
self.task = request.task_description
self.episode_duration = request.episode_duration
self.break_time_duration = request.break_time_duration
# Configure the dataset features
action_features = hw_to_dataset_features(self.robot.action_features, "action")
obs_features = hw_to_dataset_features(self.robot.observation_features, "observation")
dataset_features = {**action_features, **obs_features}
print(f"Dataset name: {request.dataset_name}")
if request.resume:
self.dataset = LeRobotDataset(
request.dataset_name,
root="/home/demo/.cache/huggingface/lerobot/" + request.dataset_name,
)
if hasattr(self.robot, "cameras") and len(self.robot.cameras) > 0:
self.dataset.start_image_writer()
else:
# Create the dataset
self.dataset = LeRobotDataset.create(
repo_id=request.dataset_name,
fps=self.fps,
features=dataset_features,
robot_type=self.robot.name,
use_videos=True,
image_writer_threads=4,
)
current_dataset = self.create_dataset(request.dataset_name, DatasetPushState.LOCAL_ONLY, 0)
self.add_dataset_to_json_file(current_dataset, self.dataset_list_path)
# Connect the robot and teleoperator
if not self.robot.is_connected:
self.robot.connect()
if not self.teleop.is_connected:
self.teleop.connect()
def record_episode(
self,
display_cameras: bool = False,
play_sounds: bool = True,
):
self.episode_recording_in_progress = True
record_loop(
robot=self.robot,
events=self.events,
fps=self.fps,
teleop=self.teleop,
dataset=self.dataset,
control_time_s=self.episode_duration,
single_task=self.task,
display_data=True,
)
self.episode_recording_in_progress = False
def create_dataset(self, dataset_name: str, pushed: DatasetPushState, nb_episodes: int) -> Dataset:
dataset = Dataset()
dataset.dataset_name = dataset_name
dataset.pushed = pushed
dataset.nb_episodes = nb_episodes
return dataset
def dataset_to_dict(self, dataset: Dataset) -> dict:
"""Convert Dataset proto to a dict manually."""
return {
"dataset_name": dataset.dataset_name,
"pushed": DatasetPushState.Name(dataset.pushed),
"nb_episodes": dataset.nb_episodes
}
def add_dataset_to_json_file(self, dataset: Dataset, json_filename: str):
if os.path.exists(json_filename):
with open(json_filename, "r") as f:
try:
data = json.load(f)
if not isinstance(data, list):
print("Warning: JSON root is not a list, resetting.")
data = []
except json.JSONDecodeError:
print("Warning: Invalid JSON file, resetting.")
data = []
else:
data = []
# Add the new dataset
data.append(self.dataset_to_dict(dataset))
# Save back to file
with open(json_filename, "w") as f:
json.dump(data, f, indent=2)
def update_dataset(self, dataset: Dataset, json_filename: str):
"""Update the 'pushed' field of a dataset in the JSON file."""
if not os.path.exists(json_filename):
print(f"File '{json_filename}' does not exist.")
return
with open(json_filename, "r") as f:
try:
data = json.load(f)
if not isinstance(data, list):
print("Warning: JSON root is not a list. No update performed.")
return
except json.JSONDecodeError:
print("Warning: JSON file is invalid. No update performed.")
return
dataset_found = False
for d in data:
if d.get("dataset_name") == dataset.dataset_name:
d["pushed"] = DatasetPushState.Name(dataset.pushed) # Convert enum to string
dataset_found = True
break
if not dataset_found:
print(f"No dataset with name '{dataset.dataset_name}' found.")
return
with open(json_filename, "w") as f:
json.dump(data, f, indent=2)
print(f"Dataset '{dataset.dataset_name}' updated successfully.")
def dict_to_dataset(self, d: Dict) -> Dataset:
"""Convert a dictionary to a Dataset proto."""
dataset = Dataset()
dataset.dataset_name = d.get("dataset_name", "")
pushed_str = d.get("pushed", "UNKNOWN")
if isinstance(pushed_str, str):
# Convert string to enum value
dataset.pushed = DatasetPushState.Value(pushed_str)
elif isinstance(pushed_str, int):
# Already an integer value
dataset.pushed = pushed_str
else:
dataset.pushed = DatasetPushState.UNKNOWN
dataset.nb_episodes = d.get("nb_episodes", 0)
return dataset
def read_datasets_from_json(self, json_filename: str) -> DatasetList:
dataset_list = DatasetList()
if not os.path.exists(json_filename):
print(f"File {json_filename} does not exist.")
return dataset_list # Empty list
with open(json_filename, "r") as f:
try:
data = json.load(f)
if not isinstance(data, list):
print("Warning: JSON root is not a list. Ignored.")
return dataset_list
except json.JSONDecodeError:
print("Warning: Invalid JSON file. Ignored.")
return dataset_list
for d in data:
dataset = self.dict_to_dataset(d)
dataset_list.datasets.append(dataset)
return dataset_list
def remove_dataset_by_name(self, dataset_name: str, json_filename: str):
"""Remove a dataset with a given name from the JSON file."""
if not os.path.exists(json_filename):
print(f"File {json_filename} does not exist.")
return
with open(json_filename, "r") as f:
try:
data = json.load(f)
if not isinstance(data, list):
print("Warning: JSON root is not a list. No action taken.")
return
except json.JSONDecodeError:
print("Warning: Invalid JSON file. No action taken.")
return
original_length = len(data)
# Filter out datasets with the matching name
data = [d for d in data if d.get("dataset_name") != dataset_name]
if len(data) == original_length:
print(f"No dataset found with name '{dataset_name}'. No action taken.")
return
# Save the modified list back to the file
with open(json_filename, "w") as f:
json.dump(data, f, indent=2)
print(f"Dataset '{dataset_name}' removed successfully.")
def clear_all_datasets(self, json_filename: str):
"""Clear all datasets from the JSON file."""
if not os.path.exists(json_filename):
print(f"File {json_filename} does not exist. Nothing to clear.")
return
# Overwrite the file with an empty list
with open(json_filename, "w") as f:
json.dump([], f, indent=2)
print(f"All datasets have been cleared from '{json_filename}'.")
def delete_folder(self, folder_path: str):
"""Delete an entire folder and its content."""
if not os.path.exists(folder_path):
print(f"Folder '{folder_path}' does not exist.")
return
if not os.path.isdir(folder_path):
print(f"Path '{folder_path}' is not a folder.")
return
try:
shutil.rmtree(folder_path)
print(f"Folder '{folder_path}' and all its contents have been deleted.")
except Exception as e:
print(f"Error while deleting folder '{folder_path}': {e}")
def main():
mp.set_start_method('spawn', force=True)
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
data_acquisition_servicer = DataAcquisitionServicer()
data_acquisition_servicer.register_to_server(server)
server.add_insecure_port('[::]:50062')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
main()
-116
View File
@@ -1,116 +0,0 @@
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.act.modeling_act import ACTPolicy
from lerobot.robots.reachy2 import Reachy2Robot, Reachy2RobotConfig
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.record import record_loop
from reachy2_sdk import ReachySDK
import numpy as np
import time
NUM_EPISODES = 2
FPS = 15
EPISODE_TIME_SEC = 4
TASK_DESCRIPTION = "Grab a cube with Reachy 2"
# Create the robot configuration
robot_config = Reachy2RobotConfig(
ip_address="192.168.0.199",
id="reachy2-pvt02",
with_mobile_base=False,
)
# Initialize the robot
robot = Reachy2Robot(robot_config)
# Instantiate a client for starting and intermediate positions
# reachy = ReachySDK(robot_config.ip_address)
# Initialize the policy
policy = ACTPolicy.from_pretrained("pepijn223/grab_cube_2")
# Get initial dataset first episode
initial_dataset = LeRobotDataset(repo_id="glannuzel/grab_cube_2", episodes=[0])
actions = initial_dataset.hf_dataset.select_columns("action")
# 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="glannuzel/eval_grab_cube_2.1",
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
robot.connect()
# Go to the initial pose
action_array = actions[0]["action"]
action = {}
for i, name in enumerate(dataset.features["action"]["names"]):
action[name] = action_array[i].item()
neck_goal = [action["neck_roll.pos"], action["neck_pitch.pos"], action["neck_yaw.pos"]]
r_arm_goal = [action["r_shoulder_pitch.pos"],
action["r_shoulder_roll.pos"],
action["r_elbow_yaw.pos"],
action["r_elbow_pitch.pos"],
action["r_wrist_roll.pos"],
action["r_wrist_pitch.pos"],
action["r_wrist_yaw.pos"]]
l_arm_goal = [action["l_shoulder_pitch.pos"],
action["l_shoulder_roll.pos"],
action["l_elbow_yaw.pos"],
action["l_elbow_pitch.pos"],
action["l_wrist_roll.pos"],
action["l_wrist_pitch.pos"],
action["l_wrist_yaw.pos"]]
robot.reachy.head.goto(neck_goal)
robot.reachy.r_arm.goto(r_arm_goal)
robot.reachy.r_arm.gripper.goto(100.0)
robot.reachy.l_arm.goto(l_arm_goal, wait=True)
time.sleep(1.0)
for episode_idx in range(NUM_EPISODES):
log_say(f"Running inference, recording eval episode {episode_idx + 1} of {NUM_EPISODES}")
# Run the policy inference loop
record_loop(
robot=robot,
events=events,
fps=FPS,
policy=policy,
dataset=dataset,
control_time_s=EPISODE_TIME_SEC,
single_task=TASK_DESCRIPTION,
display_data=False,
)
# Set the robot back to the initial pose
robot.reachy.head.goto(neck_goal)
robot.reachy.r_arm.goto(r_arm_goal)
robot.reachy.r_arm.gripper.goto(100.0)
robot.reachy.l_arm.goto(l_arm_goal, wait=True)
time.sleep(1.0)
dataset.save_episode()
# Clean up
robot.disconnect()
dataset.push_to_hub()
@@ -1,60 +0,0 @@
import time
from lerobot.robots.reachy2 import Reachy2Robot, Reachy2RobotConfig
# {lerobot_keys: reachy2_sdk_keys}
REACHY2_JOINTS = {
"neck_yaw.pos": "head.neck.yaw",
"neck_pitch.pos": "head.neck.pitch",
"neck_roll.pos": "head.neck.roll",
"r_shoulder_pitch.pos": "r_arm.shoulder.pitch",
"r_shoulder_roll.pos": "r_arm.shoulder.roll",
"r_elbow_yaw.pos": "r_arm.elbow.yaw",
"r_elbow_pitch.pos": "r_arm.elbow.pitch",
"r_wrist_roll.pos": "r_arm.wrist.roll",
"r_wrist_pitch.pos": "r_arm.wrist.pitch",
"r_wrist_yaw.pos": "r_arm.wrist.yaw",
"r_gripper.pos": "r_arm.gripper",
"l_shoulder_pitch.pos": "l_arm.shoulder.pitch",
"l_shoulder_roll.pos": "l_arm.shoulder.roll",
"l_elbow_yaw.pos": "l_arm.elbow.yaw",
"l_elbow_pitch.pos": "l_arm.elbow.pitch",
"l_wrist_roll.pos": "l_arm.wrist.roll",
"l_wrist_pitch.pos": "l_arm.wrist.pitch",
"l_wrist_yaw.pos": "l_arm.wrist.yaw",
"l_gripper.pos": "l_arm.gripper",
"l_antenna.pos": "head.l_antenna",
"r_antenna.pos": "head.r_antenna",
}
REACHY2_VEL = {
"mobile_base.vx": "vx",
"mobile_base.vy": "vy",
"mobile_base.vtheta": "vtheta",
}
robot_config = Reachy2RobotConfig(ip_address="localhost")
robot = Reachy2Robot(robot_config)
robot.connect()
print(f"is_connected(): {robot.is_connected}\n")
print(f"_get_state(): {robot._get_state()}\n")
obs = robot.get_observation()
print(f"get_observation(): {obs}\n")
print(f"observation_features: {robot.observation_features}\n")
print(f"action_features: {robot.action_features}\n")
def get_action(robot):
pos_dict = {k: robot.reachy.joints[v].present_position for k, v in REACHY2_JOINTS.items()}
vel_dict = {k: robot.reachy.mobile_base.odometry[v] for k, v in REACHY2_VEL.items()}
return {**pos_dict, **vel_dict}
action = get_action(robot)
time.sleep(5)
robot.send_action(action)
@@ -1,104 +0,0 @@
from lerobot.datasets.lerobot_dataset import LeRobotDataset
from lerobot.datasets.utils import hw_to_dataset_features
from lerobot.robots.reachy2 import Reachy2Robot, Reachy2RobotConfig
from lerobot.teleoperators.reachy2_fake_teleoperator import Reachy2FakeTeleoperator, Reachy2FakeTeleoperatorConfig
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.record import record_loop
import time
NUM_EPISODES = 35
FPS = 20
EPISODE_TIME_SEC = 10
RESET_TIME_SEC = 5
TASK_DESCRIPTION = "Grab a cube in Mujoco simulation"
# Create the robot and teleoperator configurations
robot_config = Reachy2RobotConfig(
ip_address="192.168.0.199",
id="test_reachy",
with_mobile_base=False,
)
teleop_config = Reachy2FakeTeleoperatorConfig(
ip_address="192.168.0.199",
with_mobile_base=False,
)
# Initialize the robot and teleoperator
robot = Reachy2Robot(robot_config)
teleop = Reachy2FakeTeleoperator(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="glannuzel/grab_cube",
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()
episode_idx = 0
while episode_idx < NUM_EPISODES and not events["stop_recording"]:
start_time = time.time()
log_say(f"Recording episode {episode_idx + 1} of {NUM_EPISODES}")
print("########### RECORDING ###########")
record_loop(
robot=robot,
events=events,
fps=FPS,
teleop=teleop,
dataset=dataset,
control_time_s=EPISODE_TIME_SEC,
single_task=TASK_DESCRIPTION,
display_data=False,
)
# Reset the environment if not stopping or re-recording
if not events["stop_recording"] and (episode_idx < NUM_EPISODES - 1 or events["rerecord_episode"]):
log_say("Reset the environment")
print("------------- RESETTING -------------")
record_loop(
robot=robot,
events=events,
fps=FPS,
teleop=teleop,
control_time_s=RESET_TIME_SEC,
single_task=TASK_DESCRIPTION,
display_data=False,
)
if events["rerecord_episode"]:
log_say("Re-recording episode")
events["rerecord_episode"] = False
events["exit_early"] = False
dataset.clear_episode_buffer()
continue
# episode_idx = NUM_EPISODES
dataset.save_episode()
episode_idx += 1
print(time.time()-start_time)
# Clean up
log_say("Stop recording")
robot.disconnect()
dataset.push_to_hub()
-65
View File
@@ -1,65 +0,0 @@
from lerobot.datasets.lerobot_dataset import LeRobotDataset
from lerobot.robots.reachy2 import Reachy2Robot, Reachy2RobotConfig
from lerobot.utils.robot_utils import busy_wait
import time
# Create the robot configuration
robot_config = Reachy2RobotConfig(
ip_address="192.168.0.199",
id="reachy2-pvt02",
)
# Initialize the robot
robot = Reachy2Robot(robot_config)
# Create the dataset
dataset = LeRobotDataset(repo_id="glannuzel/store-rubiks-cube", episodes=[0])
actions = dataset.hf_dataset.select_columns("action")
# Connect the robot
robot.connect()
# Go smoothly to the first action
action_array = actions[0]["action"]
action = {}
for i, name in enumerate(dataset.features["action"]["names"]):
action[name] = action_array[i].item()
neck_goal = [action["neck_roll.pos"], action["neck_pitch.pos"], action["neck_yaw.pos"]]
r_arm_goal = [action["r_shoulder_pitch.pos"],
action["r_shoulder_roll.pos"],
action["r_elbow_yaw.pos"],
action["r_elbow_pitch.pos"],
action["r_wrist_roll.pos"],
action["r_wrist_pitch.pos"],
action["r_wrist_yaw.pos"]]
l_arm_goal = [action["l_shoulder_pitch.pos"],
action["l_shoulder_roll.pos"],
action["l_elbow_yaw.pos"],
action["l_elbow_pitch.pos"],
action["l_wrist_roll.pos"],
action["l_wrist_pitch.pos"],
action["l_wrist_yaw.pos"]]
robot.reachy.head.goto(neck_goal)
robot.reachy.r_arm.goto(r_arm_goal)
robot.reachy.r_arm.gripper.goto(100.0, percentage=True)
robot.reachy.l_arm.gripper.goto(100.0, percentage=True)
robot.reachy.l_arm.goto(l_arm_goal, wait=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"]):
action[name] = action_array[i].item()
robot.send_action(action)
dt_s = time.perf_counter() - start_episode_t
busy_wait(1 / dataset.fps - dt_s)
# Clean up
robot.disconnect()
@@ -1,46 +0,0 @@
import threading
from lerobot.robots.reachy2 import Reachy2Robot, Reachy2RobotConfig
from lerobot.scripts.server.configs import RobotClientConfig
from lerobot.scripts.server.helpers import visualize_action_queue_size
from lerobot.scripts.server.robot_client import RobotClient
robot_config = Reachy2RobotConfig(
ip_address="192.168.0.199",
id="reachy2-pvt02",
with_mobile_base=False,
with_l_arm=False,
with_neck=False,
with_antennas=False,
)
# 3. Create client configuration
client_cfg = RobotClientConfig(
robot=robot_config,
server_address="localhost:8080",
policy_device="cuda",
policy_type="act",
pretrained_name_or_path="CarolinePascal/pick_and_place_bottle",
chunk_size_threshold=0.5,
actions_per_chunk=20, # make sure this is less than the max actions of the policy
)
# 4. Create and start client
client = RobotClient(client_cfg)
# 5. Specify the task
task = "Don't do anything, stay still"
if client.start():
# Start action receiver thread
action_receiver_thread = threading.Thread(target=client.receive_actions, daemon=True)
action_receiver_thread.start()
try:
# Run the control loop
client.control_loop(task)
except KeyboardInterrupt:
client.stop()
action_receiver_thread.join()
# (Optionally) plot the action queue size
visualize_action_queue_size(client.action_queue_size)