LeRobot documentation
Dùng phần cứng của riêng bạn
Dùng phần cứng của riêng bạn
Hướng dẫn này sẽ giải thích cách tích hợp thiết kế robot của bạn vào hệ sinh thái LeRobot và cho phép nó truy cập tất cả các công cụ của chúng tôi (thu thập dữ liệu, các pipeline điều khiển, huấn luyện và suy luận chính sách).
Với mục đích đó, chúng tôi cung cấp lớp cơ sở Robot trong LeRobot, xác định một giao diện chuẩn cho việc tích hợp robot vật lý. Hãy cùng xem cách triển khai nó.
Yêu cầu tiên quyết
- Robot của bạn có giao diện giao tiếp (ví dụ: serial, CAN, TCP)
- Một cách để đọc dữ liệu cảm biến và gửi lệnh động cơ theo chương trình, ví dụ như SDK hoặc API của nhà sản xuất, hoặc chính bạn tự triển khai giao thức.
- LeRobot đã được cài đặt trong môi trường của bạn. Hãy làm theo Hướng dẫn cài đặt của chúng tôi.
Chọn động cơ của bạn
Nếu bạn đang sử dụng động cơ Feetech hoặc Dynamixel, LeRobot cung cấp giao diện bus tích hợp sẵn, SerialMotorsBus, có thể điều khiển cả hai dòng động cơ này: model của từng động cơ sẽ xác định dòng tương ứng. Hãy tham khảo tài liệu của nó để tìm hiểu về API. Bạn cần cài đặt gói bổ sung serial-motors, trong đó sẽ cài đặt rustypot: pip install 'lerobot[serial-motors]', hoặc pip install -e ".[serial-motors]" từ bản checkout mã nguồn.
Để có một ví dụ tốt về cách sử dụng, bạn có thể xem cách triển khai SO101 follower của chúng tôi.
Sử dụng các thành phần này nếu tương thích. Nếu không, bạn sẽ cần tìm hoặc viết một giao diện Python (không được đề cập trong hướng dẫn này):
- Tìm một SDK có sẵn trong Python (hoặc sử dụng các bindings cho C/C++)
- Hoặc triển khai một lớp bọc giao tiếp cơ bản (ví dụ: thông qua pyserial, socket hoặc CANopen)
Bạn không đơn độc—nhiều đóng góp từ cộng đồng sử dụng các bo mạch tùy chỉnh hoặc firmware!
Đối với Feetech và Dynamixel, hiện tại chúng tôi hỗ trợ các servo sau:
- Feetech STS & SMS series:
sts3215,sts3250,sm8512bl - Feetech SCS series:
scs0009 - Dòng Dynamixel X (giao thức 2.0):
xl330-m077,xl330-m288,xc330-t181,xc330-t288,xl430-w250,xl430-w250-2,xc430-w150,xm430-w350,xm540-w270,xh540-w150
Các model có thể chia sẻ một bus, các servo STS/SMS và SCS hoặc XL430 và XL330: mỗi motor được đọc và ghi thông qua định nghĩa của chính model của nó, bao gồm cả thứ tự byte và mã hóa dấu. Sự khác biệt giữa các dòng sản phẩm bắt nguồn từ chính các định nghĩa đó: giá trị chế độ hoạt động nào có nghĩa là điều khiển vị trí (bus.set_operating_mode("position")), offset homing được cộng vào vị trí hay bị trừ khỏi vị trí, và những thanh ghi nào tồn tại.
Việc hỗ trợ một model không có nghĩa là mọi công cụ hiệu chỉnh đều hoạt động trên model đó: Feetech SCS0009 không có chế độ hoạt động cũng như không có độ lệch về vị trí gốc, do đó set_operating_mode() và set_half_turn_homings() sẽ từ chối model này. Công thức hiệu chỉnh bên dưới dành cho các servo có cả hai, chẳng hạn như STS; một servo SCS được hiệu chỉnh chỉ bằng phạm vi của nó.
Nếu bạn đang sử dụng servo Feetech hoặc Dynamixel không có trong danh sách này, hãy thêm chúng vào rustypot, nơi lưu trữ các bảng điều khiển mà các bus đọc: một model chia sẻ bảng điều khiển hiện có chỉ cần đăng ký số model, còn một model mới cần định nghĩa servo (xem hướng dẫn đóng góp servo). LeRobot đọc các model từ gói Python rustypot đã cài đặt, vì vậy nó phải bao gồm model mới: một bản phát hành rustypot có chứa model đó, hoặc rustypot được biên dịch từ mã nguồn.
Trong các phần tiếp theo, các ví dụ sử dụng động cơ Feetech. Hãy thay đổi các model và điều chỉnh cho phù hợp với động cơ của bạn nếu cần.
Bước 1: Kế thừa giao diện Robot
Trước tiên, bạn cần chỉ định lớp cấu hình và một chuỗi định danh (name) cho robot của bạn. Nếu robot của bạn có các yêu cầu đặc biệt mà bạn muốn có thể thay đổi dễ dàng, hãy đặt chúng ở đây (ví dụ: cổng/địa chỉ, baudrate).
Ở đây, chúng ta sẽ thêm tên cổng và một camera mặc định cho robot của mình:
from dataclasses import dataclass, field
from lerobot.cameras import CameraConfig
from lerobot.cameras.opencv import OpenCVCameraConfig
from lerobot.robots import RobotConfig
@RobotConfig.register_subclass("my_cool_robot")
@dataclass
class MyCoolRobotConfig(RobotConfig):
port: str
cameras: dict[str, CameraConfig] = field(
default_factory=lambda: {
"cam_1": OpenCVCameraConfig(
index_or_path=2,
fps=30,
width=480,
height=640,
),
}
)Hướng dẫn về camera để hiểu cách phát hiện và thêm camera của bạn.
Tiếp theo, chúng ta sẽ tạo lớp robot thực tế của mình, kế thừa từ Robot. Lớp trừu tượng này định nghĩa một hợp đồng mà bạn phải tuân theo để robot của bạn có thể được sử dụng với các công cụ LeRobot khác.
Ở đây chúng ta sẽ tạo một robot 5-DoF đơn giản với một camera. Nó có thể là một cánh tay đơn giản, nhưng hãy lưu ý rằng lớp trừu tượng Robot không giả định bất kỳ điều gì về hình dạng của robot của bạn. Bạn có thể để trí tưởng tượng bay bổng khi thiết kế các robot mới!
from typing import Any
from lerobot.cameras import make_cameras_from_configs
from lerobot.motors import Motor, MotorCalibration, MotorNormMode, SerialMotorsBus
from lerobot.robots import Robot
class MyCoolRobot(Robot):
config_class = MyCoolRobotConfig
name = "my_cool_robot"
def __init__(self, config: MyCoolRobotConfig):
super().__init__(config)
self.config = config
self.bus = SerialMotorsBus(
port=self.config.port,
motors={
"joint_1": Motor(1, "sts3250", MotorNormMode.RANGE_M100_100),
"joint_2": Motor(2, "sts3215", MotorNormMode.RANGE_M100_100),
"joint_3": Motor(3, "sts3215", MotorNormMode.RANGE_M100_100),
"joint_4": Motor(4, "sts3215", MotorNormMode.RANGE_M100_100),
"joint_5": Motor(5, "sts3215", MotorNormMode.RANGE_M100_100),
},
calibration=self.calibration,
)
self.cameras = make_cameras_from_configs(config.cameras)Bước 2: Định nghĩa các đặc trưng quan sát và hành động
Hai thuộc tính này xác định khế ước giao diện giữa robot của bạn và các công cụ sử dụng nó (chẳng hạn như các pipeline thu thập dữ liệu hoặc học tập).
Lưu ý rằng các thuộc tính này phải có thể gọi được ngay cả khi robot chưa được kết nối, do đó hãy tránh dựa vào trạng thái phần cứng thời gian chạy để định nghĩa chúng.
observation_features
Thuộc tính này nên trả về một từ điển mô tả cấu trúc của các đầu ra cảm biến từ robot của bạn. Các khóa khớp với những gì get_observation() trả về, và các giá trị mô tả hình dạng (cho mảng/ảnh) hoặc kiểu (cho các giá trị đơn giản).
Ví dụ cho cánh tay 5-DoF của chúng ta với một camera:
@property
def _motors_ft(self) -> dict[str, type]:
return {
"joint_1.pos": float,
"joint_2.pos": float,
"joint_3.pos": float,
"joint_4.pos": float,
"joint_5.pos": float,
}
@property
def _cameras_ft(self) -> dict[str, tuple]:
return {
cam: (self.cameras[cam].height, self.cameras[cam].width, 3) for cam in self.cameras
}
@property
def observation_features(self) -> dict:
return {**self._motors_ft, **self._cameras_ft}Trong trường hợp này, các quan sát bao gồm một dict đơn giản lưu trữ vị trí của mỗi động cơ và một hình ảnh từ camera.
action_features
Thuộc tính này mô tả các lệnh mà robot của bạn kỳ vọng nhận được qua send_action(). Một lần nữa, các khóa phải khớp với định dạng đầu vào mong đợi, và các giá trị xác định hình dạng/kiểu của từng lệnh.
Ở đây, chúng ta đơn giản sử dụng các đặc trưng cảm nhận vị trí khớp (self._motors_ft) giống như với observation_features: hành động được gửi đi sẽ đơn giản là vị trí đích cho mỗi động cơ.
@property
def action_features(self) -> dict:
return self._motors_ftBước 3: Xử lý kết nối và ngắt kết nối
Các phương thức này nên xử lý việc mở và đóng kết nối giao tiếp với phần cứng của bạn (ví dụ: cổng serial, giao diện CAN, thiết bị USB, camera).
is_connected
Thuộc tính này đơn giản chỉ nên phản ánh việc kết nối với phần cứng của robot đã được thiết lập. Khi thuộc tính này là True, bạn nên có thể đọc và ghi vào phần cứng bằng cách sử dụng get_observation() và send_action().
@property
def is_connected(self) -> bool:
return self.bus.is_connected and all(cam.is_connected for cam in self.cameras.values())connect()
Phương thức này nên thiết lập kết nối với phần cứng. Hơn nữa, nếu robot của bạn cần hiệu chuẩn và chưa được hiệu chuẩn, nó nên bắt đầu quy trình hiệu chuẩn theo mặc định. Nếu robot của bạn cần một số cấu hình cụ thể, các cấu hình này cũng nên được gọi tại đây.
def connect(self, calibrate: bool = True) -> None:
self.bus.connect()
if not self.is_calibrated and calibrate:
self.calibrate()
for cam in self.cameras.values():
cam.connect()
self.configure()disconnect()
Phương thức này nên kết thúc giao tiếp với phần cứng một cách êm đẹp: giải phóng mọi tài nguyên liên quan (các luồng hoặc tiến trình), đóng các cổng, v.v.
Ở đây, chúng ta đã xử lý điều này trong các lớp SerialMotorsBus và Camera của mình, vì vậy chúng ta chỉ cần gọi phương thức disconnect() của chúng:
def disconnect(self) -> None:
self.bus.disconnect()
for cam in self.cameras.values():
cam.disconnect()Bước 4: Hỗ trợ hiệu chuẩn và cấu hình
LeRobot hỗ trợ tự động lưu và nạp dữ liệu hiệu chuẩn. Điều này hữu ích cho các độ lệch khớp, vị trí zero hoặc căn chỉnh cảm biến.
Lưu ý rằng tùy thuộc vào phần cứng của bạn, điều này có thể không áp dụng. Nếu đúng như vậy, bạn có thể đơn giản để các phương thức này ở dạng no-op:
@property
def is_calibrated(self) -> bool:
return True
def calibrate(self) -> None:
passis_calibrated
Điều này nên phản ánh xem robot của bạn đã được nạp hiệu chuẩn cần thiết hay chưa.
@property
def is_calibrated(self) -> bool:
return self.bus.is_calibratedcalibrate()
Mục tiêu của việc hiệu chuẩn là kép:
- Hiểu được phạm vi chuyển động vật lý của từng động cơ để chỉ gửi các lệnh nằm trong phạm vi này.
- Chuẩn hóa các vị trí động cơ thô thành các giá trị liên tục hợp lý (ví dụ: phần trăm, độ) thay vì các giá trị rời rạc tùy ý phụ thuộc vào động cơ cụ thể được sử dụng, vốn sẽ không thể tái lập ở nơi khác.
Nó nên triển khai logic cho việc hiệu chuẩn (nếu liên quan) và cập nhật từ điển self.calibration. Nếu bạn đang sử dụng động cơ Feetech hoặc Dynamixel, SerialMotorsBus đã thực hiện hiệu chuẩn thủ công:
_keep_calibration_file()cho phép bạn tái sử dụng tệp hiệu chuẩn của id này. Nếu bạn giữ lại, tệp sẽ được ghi vào các động cơ và quá trình hiệu chuẩn kết thúc tại đó.record_calibration()giải phóng các động cơ và đặt chúng vào chế độ hoạt động mà bạn chỉ định.- Nó yêu cầu bạn giữ các khớp ở giữa phạm vi chuyển động: tư thế đó sẽ tương ứng với nửa vòng quay của mỗi động cơ.
- Nó ghi lại phạm vi của từng khớp khi bạn di chuyển chúng, cho đến khi bạn nhấn ENTER. Các khớp xoay liên tục sẽ được đưa vào
full_turn_motorsvà nhận toàn bộ phạm vi encoder thay vào đó; cánh tay 5-DoF của chúng tôi không có khớp nào như vậy. write_calibration()ghi kết quả vào các động cơ, và_save_calibration()lưu nó vào tệp hiệu chuẩn.
def calibrate(self) -> None:
if self._keep_calibration_file(self.bus):
return
self.calibration = self.bus.record_calibration("position", full_turn_motors=[])
self.bus.write_calibration(self.calibration)
self._save_calibration()
print("Calibration saved to", self.calibration_fpath)configure()
Sử dụng điều này để thiết lập bất kỳ cấu hình nào cho phần cứng của bạn (chế độ điều khiển servo, hệ số bộ điều khiển, v.v.). Việc này thường nên được thực hiện khi kết nối và phải có tính chất idempotent.
def configure(self) -> None:
with self.bus.torque_disabled():
self.bus.configure_motors()
for motor in self.bus.motors:
self.bus.set_operating_mode("position", motor)
self.bus.write("P_Coefficient", motor, 16)
self.bus.write("I_Coefficient", motor, 0)
self.bus.write("D_Coefficient", motor, 32)Bước 5: Triển khai đọc cảm biến và gửi hành động
Đây là các hàm thời gian chạy quan trọng nhất: vòng lặp I/O cốt lõi.
get_observation()
Trả về một từ điển chứa các giá trị cảm biến từ robot. Những giá trị này thường bao gồm trạng thái động cơ, khung hình từ camera, các cảm biến khác nhau, v.v. Trong framework LeRobot, các quan sát này sẽ được đưa vào một policy để dự đoán các hành động cần thực hiện. Các khóa và cấu trúc của từ điển phải khớp với observation_features.
def get_observation(self) -> dict[str, Any]:
if not self.is_connected:
raise ConnectionError(f"{self} is not connected.")
# Read arm position
obs_dict = self.bus.sync_read("Present_Position")
obs_dict = {f"{motor}.pos": val for motor, val in obs_dict.items()}
# Capture images from cameras
for cam_key, cam in self.cameras.items():
obs_dict[cam_key] = cam.async_read()
return obs_dictsend_action()
Nhận một từ điển khớp với action_features và gửi nó đến phần cứng của bạn. Bạn có thể thêm các giới hạn an toàn (cắt, làm mượt) và trả về những gì thực sự đã được gửi.
Để đơn giản, chúng ta sẽ không thêm bất kỳ sự thay đổi nào cho các hành động trong ví dụ ở đây.
def send_action(self, action: dict[str, Any]) -> dict[str, Any]:
goal_pos = {key.removesuffix(".pos"): val for key, val in action.items()}
# Send goal position to the arm
self.bus.sync_write("Goal_Position", goal_pos)
return actionChờ giữa các lần dự đoán
Chế độ RTC cục bộ thông thường vẫn có thể sử dụng mà không cần khả năng robot mới. Việc triển khai từ xa, các khoảng dừng ngôn ngữ bất đồng bộ theo kế hoạch và tình trạng thiếu hành động có thể phục hồi đòi hỏi một thỏa thuận chờ giữ mục tiêu. Chỉ bật tùy chọn này bằng supports_position_hold = True khi việc làm mới mọi trường hành động thông qua send_action() là an toàn cho bộ điều khiển. Thông thường, các trường đó là các mục tiêu vị trí thực tế. Một bộ điều khiển có thể chọn tham gia bằng một lệnh giữ đã được xác thực riêng biệt, chẳng hạn như token chuyển động tiềm ẩn của SONIC, khi việc lặp lại nó giúp bộ điều khiển trên thiết bị duy trì thăng bằng. Việc bật mô-men xoắn hoặc chỉ có hậu tố .pos không đủ để thiết lập điều này; các lệnh vận tốc/lực và di chuyển vẫn không phù hợp.
Cài đặt rollout dùng chung làm mới hành động hữu hạn hoàn chỉnh cuối cùng được trả về bởi send_action(), bao gồm cả kẹp và bất kỳ việc cắt (clipping) nào của driver. Hãy trả về đích (target) thực tế đã được áp dụng, chứ không phải yêu cầu gốc, khi driver của bạn sửa đổi nó. Các bản cập nhật quan sát (observation) tiếp theo sẽ không thay thế đích đó. Trước khi bất kỳ lệnh nào được áp dụng, một bản chụp (snapshot) vị trí đo đã được xác thực sẽ khởi tạo nó. Robot có thể ổn định dần về phía đích được giữ lại; hợp đồng này dừng việc tiến triển quỹ đạo (trajectory) chứ không đảm bảo dừng vật lý tức thời. Hãy xác minh hỗ trợ tải, khả năng kẹp và hành vi làm mới lệnh trên phần cứng cho mỗi triển khai.
Khi tính năng giữ (holding) được bật, các bộ xử lý hành động tùy chỉnh và các điều chỉnh điều khiển từ xa phải duy trì lệnh vị trí hoàn chỉnh, bao gồm cả kẹp (gripper). Trình điều khiển phải trả về mọi thành phần hành động với các giá trị áp dụng hữu hạn. Việc trả về không hoàn chỉnh/không hợp lệ là sự vi phạm hợp đồng sau khi lệnh được áp dụng: quá trình rollout sẽ dừng lại và ngăn chặn việc đưa về vị trí gốc (homing) thay vì tái sử dụng một mục tiêu cũ. Các lỗi lệnh cũng ngăn chặn việc đưa về vị trí gốc trong quá trình rollout đồng bộ.
Remote rollout tự động kiểm tra khả năng của driver này; không cần cờ CLI chế độ giữ bổ sung. Các lỗi quan sát chung sử dụng đường dẫn dọn dẹp rollout thông thường. Việc quay lại vị trí ban đầu vẫn cần một quan sát hoàn chỉnh và có thể thất bại nếu một camera vẫn không khả dụng.
| Triển khai robot | Hỗ trợ chờ theo vị trí đích |
|---|---|
| SO followers (SO-100/SO-101), OMX, Koch | Được hỗ trợ. |
| HopeJr cánh tay và bàn tay | Được hỗ trợ. |
| Rebot B601 | Được hỗ trợ trên các chế độ cánh tay/kẹp tuyệt đối hiện có. |
| YAM | Được hỗ trợ. Nếu không có lệnh nào đến trong command_timeout_s, cánh tay sẽ giữ nguyên vị trí hoặc lơ lửng, tùy theo cài đặt của idle_mode. |
| OpenArm | Được hỗ trợ với use_velocity_and_torque=false; các schema hành động hỗn hợp bị loại trừ. |
| BiSO, BiOpenArm, BiRebot B601, BiYAM | Được hỗ trợ khi cả hai nhánh cơ bản đều hỗ trợ; các mục tiêu được áp dụng của chúng giữ nguyên tiền tố trái/phải. |
| Reachy2 | Chỉ được hỗ trợ với with_mobile_base=false, use_external_commands=false và max_relative_target=null. Lệnh mobile-base là vận tốc, chế độ bên ngoài không truyền các mục tiêu, và đường dẫn cắt hiện tại trả về giá trị gốc thay vì giá trị đã áp dụng. |
| LeKiwi (bao gồm client mạng), EarthRover Mini Plus | Không hỗ trợ: các hành động bao gồm vận tốc cơ sở di động, không thể được giữ lại như các mục tiêu vị trí. |
| Unitree G1 | Chỉ được hỗ trợ với SonicWholeBodyController: lệnh chờ sẽ lặp lại token chuyển động 64-D hoàn chỉnh cuối trong khi bộ giải mã trên thiết bị tiếp tục cân bằng. Locomotion của GR00T/Holosoma và điều khiển .q thô vẫn chưa được hỗ trợ. |
Các khai báo này phản ánh hợp đồng lệnh của trình điều khiển, không phải việc xác thực vật lý cho mọi biến thể hoặc cấu hình bộ điều khiển. Mặc định chung của Robot vẫn là false. Các kiểm tra khả năng không xác lập tính tương thích checkpoint, hiệu chỉnh bộ điều khiển, hỗ trợ tải hoặc tình trạng phần cứng.
Thêm một Teleoperator
Để triển khai các thiết bị điều khiển từ xa, chúng tôi cũng cung cấp lớp cơ sở Teleoperator. Lớp này rất giống với lớp cơ sở Robot và cũng không giả định bất kỳ điều gì về hình dạng thiết bị.
Các điểm khác biệt chính nằm ở các hàm I/O: một teleoperator cho phép bạn tạo ra hành động thông qua get_action và có thể nhận các hành động phản hồi thông qua send_feedback. Phản hồi có thể là bất kỳ thứ gì có thể điều khiển được trên thiết bị teleoperation, giúp người điều khiển hiểu được hậu quả của các hành động đã gửi đi. Ví dụ như phản hồi chuyển động/lực trên cánh tay dẫn động, hoặc rung trên tay cầm game. Để triển khai một teleoperator, bạn có thể làm theo hướng dẫn này và điều chỉnh cho phù hợp với hai phương thức trên.
Sử dụng Thiết bị LeRobot Của Bạn 🔌
Bạn có thể dễ dàng mở rộng lerobot với phần cứng tùy chỉnh của riêng mình—dù là camera, robot hay thiết bị teleoperation—bằng cách tạo một gói Python riêng biệt, có thể cài đặt được. Nếu bạn tuân theo một vài quy ước đơn giản, các công cụ dòng lệnh của lerobot (như lerobot-teleoperate và lerobot-record) sẽ tự động phát hiện và tích hợp các sáng tạo của bạn mà không cần bất kỳ thay đổi nào đối với mã nguồn lerobot.
Hướng dẫn này nêu bật các quy ước mà plugin của bạn phải tuân theo.
4 Quy ước cốt lõi
Để đảm bảo thiết bị tùy chỉnh của bạn có thể được phát hiện, bạn phải tuân thủ bốn quy tắc sau.
1 . Tạo một Gói Cài Đặt Có Tiền Tụ Cụ Thể
Dự án của bạn phải là một gói Python chuẩn, có thể cài đặt được. Quan trọng là tên gói của bạn (được định nghĩa trong pyproject.toml hoặc setup.py) phải bắt đầu bằng một trong các tiền tố sau:
lerobot_robot_cho một robot.lerobot_camera_cho một camera.lerobot_teleoperator_cho thiết bị điều khiển từ xa.lerobot_strategy_cho chiến lượclerobot-rollout(xem Mang chiến lược của riêng bạn).
Hệ thống tiền tố này là cách lerobot tự động tìm thấy plugin của bạn trong môi trường Python.
2 . Tuân theo Mẫu Đặt Tên SomethingConfig / Something
Lớp triển khai của thiết bị của bạn phải được đặt tên theo lớp cấu hình của nó, chỉ cần bỏ hậu tố Config.
- Lớp cấu hình:
MyAwesomeTeleopConfig - Lớp thiết bị:
MyAwesomeTeleop
3. Đặt tệp của bạn trong một cấu trúc dễ dự đoán
Lớp thiết bị (MyAwesomeTeleop) phải nằm trong một module có thể dự đoán được so với lớp cấu hình của nó (MyAwesomeTeleopConfig). lerobot sẽ tự động tìm kiếm tại các vị trí sau:
- Trong cùng module với lớp config.
- Trong một submodule được đặt tên theo thiết bị (ví dụ:
my_awesome_teleop.py).
Cấu trúc được khuyến nghị và đơn giản nhất là đặt chúng trong các tệp riêng biệt, có tên rõ ràng, cùng nằm trong một thư mục.
4 . Công khai các lớp trong __init__.py
Tệp __init__.py của gói của bạn nên import và expose cả lớp configuration lẫn lớp device, giúp chúng dễ dàng truy cập.
Kết hợp tất cả: Một ví dụ hoàn chỉnh
Hãy tạo một teleoperator mới có tên là my_awesome_teleop.
Cấu trúc thư mục
Dưới đây là cách thư mục dự án nên trông như thế nào. Tên gói, lerobot_teleoperator_my_awesome_teleop, tuân theo Quy ước #1.
lerobot_teleoperator_my_awesome_teleop/
├── pyproject.toml # (or setup.py) lists lerobot as a dependency
└── lerobot_teleoperator_my_awesome_teleop/
├── __init__.py
├── config_my_awesome_teleop.py
└── my_awesome_teleop.pyNội dung tệp
config_my_awesome_teleop.py: Định nghĩa lớp cấu hình. Lưu ý hậu tốConfig(Quy ước #2).from dataclasses import dataclass from lerobot.teleoperators.config import TeleoperatorConfig @TeleoperatorConfig.register_subclass("my_awesome_teleop") @dataclass class MyAwesomeTeleopConfig(TeleoperatorConfig): # Your configuration fields go here port: str = "192.168.1.1"my_awesome_teleop.py: Triển khai thiết bị. Tên lớpMyAwesomeTeleopkhớp với tên lớp cấu hình của nó (Quy ước #2). Cấu trúc tệp này tuân thủ Quy ước #3.from lerobot.teleoperators.teleoperator import Teleoperator from .config_my_awesome_teleop import MyAwesomeTeleopConfig class MyAwesomeTeleop(Teleoperator): config_class = MyAwesomeTeleopConfig name = "my_awesome_teleop" def __init__(self, config: MyAwesomeTeleopConfig): super().__init__(config) self.config = config # Your device logic (e.g., connect) goes here__init__.py: Công bố các lớp chính (Quy ước #4).from .config_my_awesome_teleop import MyAwesomeTeleopConfig from .my_awesome_teleop import MyAwesomeTeleop
Cài đặt và Sử dụng
Cài đặt plugin mới của bạn trong môi trường Python. Bạn có thể cài đặt gói plugin cục bộ của mình bằng chế độ chỉnh sửa của
piphoặc từ PyPi.# Locally # Navigate to your plugin's root directory and install it cd lerobot_teleoperator_my_awesome_teleop pip install -e . # From PyPi pip install lerobot_teleoperator_my_awesome_teleopSử dụng trực tiếp từ dòng lệnh. Bây giờ, bạn có thể sử dụng thiết bị tùy chỉnh của mình bằng cách tham chiếu đến kiểu của nó.
# Add the other arguments you need (robot type, ports, ids, ...) lerobot-teleoperate --teleop.type=my_awesome_teleop ...
Và như vậy là xong! Thiết bị tùy chỉnh của bạn giờ đã được tích hợp hoàn toàn.
Bạn đang tìm một ví dụ?
Cộng đồng duy trì hàng chục plugin được xây dựng theo cách này. Duyệt qua Third-Party Robots & Teleoperators và Third-Party Cameras & Sensors để tìm một plugin phù hợp với phần cứng của bạn, hoặc bắt đầu từ hai gói nhỏ này:
- https://github.com/SpesRobotics/lerobot-robot-xarm
- https://github.com/SpesRobotics/lerobot-teleoperator-teleop
Tổng kết
Khi lớp robot của bạn đã hoàn tất, bạn có thể tận dụng hệ sinh thái LeRobot:
- Điều khiển robot của bạn bằng các thiết bị teleoperator có sẵn hoặc tích hợp trực tiếp thiết bị teleoperating của bạn
- Ghi lại dữ liệu huấn luyện và trực quan hóa
- Tích hợp nó vào các quy trình học tăng cường hoặc học bắt chước
Sau khi plugin của bạn được phát hành, hãy mở một PR để thêm nó vào Third-Party Robots & Teleoperators hoặc Third-Party Cameras & Sensors để người dùng khác có thể tìm thấy.
Đừng ngần ngại liên hệ với cộng đồng để được hỗ trợ trên Discord của chúng tôi 🤗
Update on GitHub