mirror of
https://github.com/huggingface/lerobot.git
synced 2026-06-04 04:41:24 +00:00
* Start adding Reachy 2 (no camera) * Fix joint shape * Remove print * Modify observation_features * Fix observation state * Try adding a fake Reachy teleoperator * Saving test scripts * Add reachy2camera to cameras * Add teleop_left camera to observation * Create test_reachy2_camera.py * Update utils.py * Add all rgb cameras * Future depth work * Try adding mobile_base velocity * Update tests * Update data_acquisition_server.py * Update with use_external_commands * Replay * Usable with or without mobile base * No need for new isntance * Use same ip for cameras * Remove useless imports * Add resume * Divide joints in multiple dicts * Divide joinits into several dicts in teleoperator * Fix forgotten method call * Create test_robot_client.py * Open gripper on start * Add arguments for cameras * Modify get_frame() requested size * Call generate_joints_dict on _init_ * black + isort * Add reachy2 in imports * Add reachy2 dependencies * Add documentation * Update reachy2.mdx * Update reachy2.mdx * Clean files and add types * Fix type in send_action * Remove print * Delete test files * Clean code * Update cameras * Disconnect from camera * Run pre-commit hooks * Update pyproject.toml * Create test_reachy2.py * Fix generate_joints * Update test_reachy2.py * Update send_action test * Update reachy2_cameras depth + CameraManager * Update reachy2_camera tests * Remove useless import and args * Rename reachy2_teleoperator * Create test_reachy2_teleoperator.py * Fix remainging fake_teleoperator * Remove useless elements * Mock cameras in test_reachy2 * Delete commented lines * Add use_present_position to teleoperator * Add cameras tests * Add check no part + test * Use disable_torque_on_disconnect * Use odometry for vel with present_position * Update documentation * Fix vel value type * Use ensure_safe_goal_position * Import joints dict from classes * Update reachy2.mdx * Update reachy2.mdx * Update minimal version * Update minimal version * fix(tests) fixes for reachy2 tests; removing reachy2 references from the script * Add reachy2_sdk fake as plugins --------- Co-authored-by: Michel Aractingi <michel.aractingi@huggingface.co>
112 lines
3.6 KiB
Python
112 lines
3.6 KiB
Python
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import logging
|
|
from pprint import pformat
|
|
|
|
from lerobot.robots import RobotConfig
|
|
|
|
from .robot import Robot
|
|
|
|
|
|
def make_robot_from_config(config: RobotConfig) -> Robot:
|
|
if config.type == "koch_follower":
|
|
from .koch_follower import KochFollower
|
|
|
|
return KochFollower(config)
|
|
elif config.type == "so100_follower":
|
|
from .so100_follower import SO100Follower
|
|
|
|
return SO100Follower(config)
|
|
elif config.type == "so100_follower_end_effector":
|
|
from .so100_follower import SO100FollowerEndEffector
|
|
|
|
return SO100FollowerEndEffector(config)
|
|
elif config.type == "so101_follower":
|
|
from .so101_follower import SO101Follower
|
|
|
|
return SO101Follower(config)
|
|
elif config.type == "lekiwi":
|
|
from .lekiwi import LeKiwi
|
|
|
|
return LeKiwi(config)
|
|
elif config.type == "stretch3":
|
|
from .stretch3 import Stretch3Robot
|
|
|
|
return Stretch3Robot(config)
|
|
elif config.type == "viperx":
|
|
from .viperx import ViperX
|
|
|
|
return ViperX(config)
|
|
elif config.type == "hope_jr_hand":
|
|
from .hope_jr import HopeJrHand
|
|
|
|
return HopeJrHand(config)
|
|
elif config.type == "hope_jr_arm":
|
|
from .hope_jr import HopeJrArm
|
|
|
|
return HopeJrArm(config)
|
|
elif config.type == "bi_so100_follower":
|
|
from .bi_so100_follower import BiSO100Follower
|
|
|
|
return BiSO100Follower(config)
|
|
elif config.type == "reachy2":
|
|
from .reachy2 import Reachy2Robot
|
|
|
|
return Reachy2Robot(config)
|
|
elif config.type == "mock_robot":
|
|
from tests.mocks.mock_robot import MockRobot
|
|
|
|
return MockRobot(config)
|
|
else:
|
|
raise ValueError(config.type)
|
|
|
|
|
|
def ensure_safe_goal_position(
|
|
goal_present_pos: dict[str, tuple[float, float]], max_relative_target: float | dict[str, float]
|
|
) -> dict[str, float]:
|
|
"""Caps relative action target magnitude for safety."""
|
|
|
|
if isinstance(max_relative_target, float):
|
|
diff_cap = dict.fromkeys(goal_present_pos, max_relative_target)
|
|
elif isinstance(max_relative_target, dict):
|
|
if not set(goal_present_pos) == set(max_relative_target):
|
|
raise ValueError("max_relative_target keys must match those of goal_present_pos.")
|
|
diff_cap = max_relative_target
|
|
else:
|
|
raise TypeError(max_relative_target)
|
|
|
|
warnings_dict = {}
|
|
safe_goal_positions = {}
|
|
for key, (goal_pos, present_pos) in goal_present_pos.items():
|
|
diff = goal_pos - present_pos
|
|
max_diff = diff_cap[key]
|
|
safe_diff = min(diff, max_diff)
|
|
safe_diff = max(safe_diff, -max_diff)
|
|
safe_goal_pos = present_pos + safe_diff
|
|
safe_goal_positions[key] = safe_goal_pos
|
|
if abs(safe_goal_pos - goal_pos) > 1e-4:
|
|
warnings_dict[key] = {
|
|
"original goal_pos": goal_pos,
|
|
"safe goal_pos": safe_goal_pos,
|
|
}
|
|
|
|
if warnings_dict:
|
|
logging.warning(
|
|
"Relative goal position magnitude had to be clamped to be safe.\n"
|
|
f"{pformat(warnings_dict, indent=4)}"
|
|
)
|
|
|
|
return safe_goal_positions
|