LeRobot documentation
التعلّم بالتقليد على روبوتات حقيقية
التعلّم بالتقليد على روبوتات حقيقية
ستشرح هذه الشرحية كيفية تدريب شبكة عصبية للتحكم في روبوت حقيقي بشكل مستقل.
ستتعلم:
- كيفية تسجيل مجموعة بياناتك وتصورها.
- كيفية تدريب سياسة باستخدام بياناتك وتجهيزها للتقييم.
- كيفية تقييم سياستك وتصور النتائج.
باتباع هذه الخطوات، ستتمكن من تكرار المهام، مثل التقاط مكعب لего ووضعه في حاوية، بمعدل نجاح مرتفع، كما هو موضح في الفيديو أدناه.
Video: pickup lego block task
لا يرتبط هذا الشرح التعليمي بروبوت محدد: سنرشدك خلال الأوامر ومقاطع واجهة برمجة التطبيقات (API) التي يمكنك تكييفها لأي منصة مدعومة.
أثناء جمع البيانات، ستستخدم جهاز «تشغيل عن بُعد» (teleoperation)، مثل ذراع قائد أو لوحة مفاتيح، لتشغيل الروبوت عن بُعد وتسجيل مسارات حركته.
بمجرد جمعك لعدد كافٍ من المسارات، ستقوم بتدريب شبكة عصبية لمحاكاة هذه المسارات ونشر النموذج المُدرَّب بحيث يتمكن روبوتك من أداء المهمة بشكل مستقل.
إذا واجهت أي مشكلات في أي مرحلة، فانتقل إلى مجتمع Discord لدينا للحصول على الدعم.
هل تريد الحصول بسرعة على الأوامر الصحيحة لإعدادك؟ يتيح لك دفتر البدء السريع
تكوين روبوتك مرة واحدة وتوليد جميع الأوامر أدناه جاهزة للصق.
الإعداد والمعايرة
إذا لم تقم بعد بإعداد روبوتك وجهاز التحكم عن بُعد الخاص بك ومعايرتهما، فيرجى القيام بذلك باتباع الدليل التعليمي الخاص بروبوتك، على سبيل المثال SO-101 أو OpenArm أو Koch أو LeKiwi. جميع الروبوتات المدعومة مدرجة تحت Robots في الشريط الجانبي.
التشغيل عن بُعد
في هذا المثال، سنُبيّن كيفية التشغيل عن بُعد للروبوت SO101. ولكل أمر، نوفر أيضًا مثالًا مطابقًا لواجهة برمجة التطبيقات (API).
لاحظ أن id المرتبط بالروبوت يُستخدم لتخزين ملف المعايرة. من المهم استخدام نفس id عند التشغيل عن بُعد والتسجيل والتقييم عند استخدام نفس الإعداد.
lerobot-teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem58760431541 \
--robot.id=my_awesome_follower_arm \
--teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \
--teleop.id=my_awesome_leader_armfrom lerobot.teleoperators.so_leader import SO101Leader, SO101LeaderConfig
from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
robot_config = SO101FollowerConfig(
port="/dev/tty.usbmodem5AB90687491",
id="my_follower_arm",
)
teleop_config = SO101LeaderConfig(
port="/dev/tty.usbmodem5AB90689011",
id="my_leader_arm",
)
robot = SO101Follower(robot_config)
teleop_device = SO101Leader(teleop_config)
robot.connect()
teleop_device.connect()
while True:
action = teleop_device.get_action()
robot.send_action(action)ستقوم أمر teleoperate تلقائياً بما يلي:
- حدد أي معايرات مفقودة وابدأ إجراء المعايرة.
- قم بتوصيل الروبوت وجهاز التشغيل عن بُعد ثم ابدأ التشغيل عن بُعد.
الكاميرات
لإضافة كاميرات إلى إعدادك، اتبع هذا الدليل.
التحكم عن بُعد بالكاميرات
باستخدام rerun، يمكنك إعادة التشغيل عن بُعد مع عرض تدفقات الكاميرا ومواضع المفاصل في الوقت نفسه. يستخدم هذا المثال كاميرتين، wrist وtop؛ وسنحتفظ بنفس إعداد الكاميرا لبقية الشرح التعليمي.
lerobot-teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem5AB90687491 \
--robot.id=my_follower_arm \
--robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \
--teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodem5AB90689011 \
--teleop.id=my_leader_arm \
--display_data=trueimport 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.utils.visualization_utils import init_visualization, log_visualization_data, shutdown_visualization
robot_config = SO101FollowerConfig(
port="/dev/tty.usbmodem5AB90687491",
id="my_follower_arm",
cameras={
"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 = SO101LeaderConfig(
port="/dev/tty.usbmodem5AB90689011",
id="my_leader_arm",
)
init_visualization("rerun", session_name="teleoperation") # pass "foxglove" to stream to Foxglove instead
robot = SO101Follower(robot_config)
teleop_device = SO101Leader(teleop_config)
robot.connect()
teleop_device.connect()
TARGET_HZ = 30
TIME_PER_FRAME = 1.0 / TARGET_HZ
while True:
start_time = time.perf_counter()
observation = robot.get_observation()
action = teleop_device.get_action()
robot.send_action(action)
log_visualization_data("rerun", 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)تسجيل مجموعة بيانات
بمجرد أن تتعود على التشغيل عن بُعد، يمكنك تسجيل أول مجموعة بيانات لك.
نستخدم ميزات Hugging Face hub لرفع مجموعة البيانات الخاصة بك. إذا لم تكن قد استخدمت Hub من قبل، فتأكد من قدرتك على تسجيل الدخول عبر سطر الأوامر باستخدام رمز وصول للكتابة، ويمكن توليد هذا الرمز من إعدادات Hugging Face.
أضف رمزك إلى سطر الأوامر من خلال تنفيذ هذا الأمر:
hf auth login --token ${HUGGINGFACE_TOKEN} --add-to-git-credentialثم احفظ اسم مستودع Hugging Face الخاص بك في متغير:
HF_USER=$(NO_COLOR=1 hf auth whoami | awk -F': *' 'NR==1 {print $2}')
echo $HF_USERالآن يمكنك تسجيل مجموعة بيانات. لتسجيل 5 حلقات ورفع مجموعة بياناتك إلى hub، عدّل الكود أدناه ليتناسب مع روبوتك ثم نفّذ الأمر أو مثال الواجهة البرمجية (API).
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem585A0076841 \
--robot.id=my_awesome_follower_arm \
--robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 1920, height: 1080, fps: 30}}" \
--robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \
--teleop.type=so101_leader \
--teleop.port=/dev/tty.usbmodem58760431551 \
--teleop.id=my_awesome_leader_arm \
--display_data=true \
--dataset.repo_id=${HF_USER}/record-test \
--dataset.num_episodes=5 \
--dataset.single_task="Grab the black cube" \
--dataset.streaming_encoding=true \
--dataset.encoder_threads=2
# Optional: --dataset.rgb_encoder.vcodec=autofrom lerobot.cameras.opencv import OpenCVCameraConfig
from lerobot.datasets.lerobot_dataset import LeRobotDataset
from lerobot.utils.feature_utils import hw_to_dataset_features
from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
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.utils.utils import log_say
from lerobot.utils.visualization_utils import init_visualization
from lerobot.scripts.lerobot_record import record_loop
from lerobot.processor import make_default_processors
NUM_EPISODES = 5
FPS = 30
EPISODE_TIME_SEC = 60
RESET_TIME_SEC = 10
TASK_DESCRIPTION = "My task description"
def main():
# Create robot configuration
robot_config = SO101FollowerConfig(
port="/dev/tty.usbmodem5AB90687491",
id="my_follower_arm",
cameras={
"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 = SO101LeaderConfig(
port="/dev/tty.usbmodem5AB90689011",
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_visualization("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
if not events["stop_recording"] and (episode_idx < NUM_EPISODES - 1 or events["rerecord_episode"]):
log_say("Reset the environment")
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,
control_time_s=RESET_TIME_SEC,
single_task=TASK_DESCRIPTION,
display_data=True,
)
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
# finalize dataset
log_say("Finalizing dataset...")
dataset.finalize()
# Clean up
log_say("Stop recording")
robot.disconnect()
teleop.disconnect()
dataset.push_to_hub()
if __name__ == "__main__":
main()تصبح أسماء الكاميرات التي تختارها (وهي هنا wrist وtop) مفاتيح مجموعة البيانات observation.images.wrist وobservation.images.top. يتوقع نموذج السياسة المُدرَّب على هذه المجموعة استخدام نفس أسماء الكاميرات ودقة الصورة عند نشره، لذا أعد استخدام نفس قيمة --robot.cameras في كل خطوة من خطوات هذا الشرح. إذا كان لا بد من اختلاف الأسماء، راجع Rename Map.
lerobot-recordيضيف تاريخ ووقت الجلسة إلى نهاية--dataset.repo_id، بحيث يحصل كل تسجيل على اسم فريد: يُحفظ${HF_USER}/record-testباسم${HF_USER}/record-test_YYYYMMDD_HHMMSS(على سبيل المثالrecord-test_20260929_143012). يمكنك العثور على الاسم الكامل في ملفك الشخصي على Hugging Face أو باستخدامls ~/.cache/huggingface/lerobot/${HF_USER}، واستخدمه في أي مكان تشير فيه الأوامر أدناه إلىrecord-test_YYYYMMDD_HHMMSS. للحفاظ على الاسم الدقيق الذي مررته، أضف--dataset.no_stamp=true.
رفع مجموعة البيانات
محليًا، يُخزَّن مجموعة بياناتك في هذا المجلد: ~/.cache/huggingface/lerobot/{repo-id}. عند انتهاء تسجيل البيانات، سيتم رفع مجموعة بياناتك إلى صفحتك على Hugging Face (مثل https://huggingface.co/datasets/${HF_USER}/record-test_YYYYMMDD_HHMMSS) والتي يمكنك الحصول عليها عبر تشغيل الأمر التالي:
echo https://huggingface.co/datasets/${HF_USER}/record-test_YYYYMMDD_HHMMSSسيتم وسم مجموعة بياناتك تلقائيًا بـLeRobot ليسهل على المجتمع العثور عليها، كما يمكنك إضافة وسوم مخصصة، على سبيل المثال --dataset.tags='["tutorial"]'.
يمكنك البحث عن مجموعات بيانات LeRobot أخرى على المنصة عن طريق البحث عن وسوم LeRobot.
يمكنك أيضًا دفع مجموعة البيانات المحلية الخاصة بك إلى Hub يدويًا، من خلال تشغيل:
hf upload ${HF_USER}/record-test_YYYYMMDD_HHMMSS ~/.cache/huggingface/lerobot/${HF_USER}/record-test_YYYYMMDD_HHMMSS --repo-type datasetدالة التسجيل
lerobot-record يوفر مجموعة من الأدوات لالتقاط البيانات وإدارتها أثناء تشغيل الروبوت:
1. تخزين البيانات
- يتم تخزين البيانات باستخدام صيغة
LeRobotDatasetوتُحفظ على القرص أثناء التسجيل. - بشكل افتراضي، يتم دفع مجموعة البيانات إلى صفحتك على Hugging Face بعد التسجيل.
- لإلغاء الرفع، استخدم
--dataset.push_to_hub=False.
- لإلغاء الرفع، استخدم
2. إنشاء نقاط التفتيش والاستئناف
- تُنشأ نقاط التفتيش تلقائيًا أثناء التسجيل.
- إذا حدثت مشكلة أو أردت تسجيل حلقات إضافية في نفس مجموعة البيانات، يمكنك استئناف العملية بإعادة تشغيل نفس الأمر مع
--resume=true. مرر اسم مجموعة البيانات كاملاً، بما في ذلك طابعه الزمني (--dataset.repo_id=${HF_USER}/record-test_YYYYMMDD_HHMMSS). عند استئناف التسجيل، يجب تعيين--dataset.num_episodesإلى عدد الحلقات الإضافية المراد تسجيلها، وليس إلى العدد الإجمالي المستهدف للحلقات في مجموعة البيانات! تأكد أيضاً من تعيين--dataset.root="local_path"، فهو مسار محلي لحفظ الجزء الجديد من مجموعة البيانات وهو مطلوب للاستئناف. - إعادة تشغيل الأمر دون
--resume=trueتبدأ مجموعة بيانات جديدة بختم زمني جديد. إذا استخدمت--dataset.no_stamp=true، احذف أولاً مجلد مجموعة البيانات الموجودة.
3. تسجيل المعلمات
اضبط تدوين تدفق البيانات باستخدام حُجج سطر الأوامر:
--dataset.episode_time_s=60مدة كل حلقة لتسجيل البيانات (الافتراضي: 60 ثانية).--dataset.reset_time_s=60المدة الزمنية لإعادة تعيين البيئة بعد كل حلقة (الافتراضي: 60 ثانية).--dataset.num_episodes=50العدد الإجمالي للحلقات التي سيتم تسجيلها (الافتراضي: 50).
4. التحكم بلوحة المفاتيح أثناء التسجيل
تحكم في تدفق تسجيل البيانات باستخدام اختصارات لوحة المفاتيح:
- اضغط على السهم الأيمن (
→) أوnلإيقاف الحلقة الحالية مبكراً أو إعادة ضبط الوقت والانتقال إلى التالية. - اضغط على السهم الأيسر (
←) أوr: لإلغاء الحلقة الحالية وإعادة تسجيلها. - اضغط Escape (
ESC) أوq: لإيقاف الجلسة فوراً، وتشفير مقاطع الفيديو، ورفع مجموعة البيانات.
تعمل اختصارات تدفق التحكم هذه على جلسات X11 وWayland والجلسات بدون واجهة رسومية/عبر SSH. عندما لا يكون متحكم لوحة المفاتيح العام متاحًا (Wayland، أو جهاز بدون واجهة رسومية، أو macOS بدون إذن إمكانية الوصول)، يقرأ
lerobot-recordتلقائيًا نفس المفاتيح من الطرفية — شغّله من طرفية تفاعلية وأبقِ التركيز عليه. يمكنك أيضًا استخدام الحروف المكافئةn(التالي، نفس→)،r(إعادة التسجيل، نفس←) وq(الخروج، نفسESC). لا يلزم إعداد$DISPLAY.ينطبق هذا على تدفق التحكم في التسجيل فقط. لا يزال التشغيل عن بُعد عبر لوحة المفاتيح (قيادة الروبوت باستخدام لوحة المفاتيح) بحاجة إلى واجهة خلفية مفاتيح عامة، لذا يعمل فقط في جلسة X11، أو سطح مكتب Windows، أو macOS مع منح أذونات إمكانية الوصول/مراقبة الإدخال — وليس في Wayland أو الجلسات بدون واجهة رسومية.
نصائح لجمع البيانات
بمجرد أن تصبح مرتاحًا مع تسجيل البيانات، يمكنك إنشاء مجموعة بيانات أكبر للتدريب. مهمة بداية جيدة هي الإمساك بكائن في مواقع مختلفة ووضعه في حاوية. نقترح تسجيل ما لا يقل عن 50 حلقة، بمعدل 10 حلقات لكل موقع. حافظ على ثبات الكاميرات وحافظ على سلوك إمساك متسق طوال التسجيلات. تأكد أيضًا من أن الكائن الذي تتعامل معه مرئي على الكاميرات. قاعدة إبهام جيدة هي أن تكون قادرًا على أداء المهمة بنفسك بالنظر فقط إلى صور الكاميرا.
في الأقسام التالية، ستقوم بتدريب شبكة العصبية الخاصة بك. بعد تحقيق أداء موثوق في الإمساك، يمكنك البدء في إدخال المزيد من التغيرات أثناء جمع البيانات، مثل مواقع إمساك إضافية، وتقنيات إمساك مختلفة، وتغيير مواضع الكاميرات.
تجنّب إضافة الكثير من التباين بسرعة كبيرة، فقد يعيق ذلك نتائجك.
إذا كنت ترغب في الغوص بعمق أكبر في هذا الموضوع المهم، يمكنك الاطلاع على المقال الذي كتبناه حول ما يجعل مجموعة البيانات جيدة.
تقارير الإيقاع
يقوم lerobot-record بتنظيم وتيرة الحلقة عند --dataset.fps ويبلّغ بما تحقق فعليًا: ملخص من سطر واحد لكل حلقة تحفظها، وقسم للجلسة بأكملها عند انتهاء التسجيل — بما في ذلك عند استخدام Ctrl-C.
Cadence (episode 0): 29.88 Hz vs 30 Hz target · 600 ticks, 20.0 s measured · 8/599 ticks over the 33.3 ms budget (work mean 18.4 ms, worst 45.1 ms)
Cadence (episode 1): 29.88 Hz vs 30 Hz target · 600 ticks, 20.0 s measured · 8/599 ticks over the 33.3 ms budget (work mean 18.4 ms, worst 45.1 ms)
Cadence summary — whole run, 2 episodes · target 30 Hz (33.3 ms budget per tick): 1200 ticks, 1198 judged
effective cadence: 29.88 Hz over 40.1 s measured
ticks over the 33.3 ms work budget: 16/1198 (1.3%) — work mean 18.4 ms, worst 45.1 ms
loop-body steps (share of measured work):
observe mean 13.65 ms · worst 40.20 ms · 74.4% of work · 1200 calls
process_obs mean 0.30 ms · worst 0.30 ms · 1.6% of work · 1200 calls
teleop mean 1.80 ms · worst 1.80 ms · 9.8% of work · 1200 calls
send mean 0.90 ms · worst 0.90 ms · 4.9% of work · 1200 calls
record mean 1.70 ms · worst 1.90 ms · 9.3% of work · 1200 calls
pacing headroom: 15.1 ms slept per tick on average (max 16.7 ms) — near zero means the loop is saturatedيستحق هذا النص القراءة قبل تدريبك على مجموعة البيانات. يُشتق طابع زمني للإطار من فهرسه، لذا فإن جلسة أُجريت بتردد 25 هرتز تنتج مجموعة بيانات تُدّعي تردد 30 — الحركة المسجلة أسرع من الواقع ببساطة. في الأعلى، يمثل observe نسبة 74% من عمل الحلقة، وأقصى قيمة لـ worst هي 40 مللي ثانية ضمن ميزانية قدرها 33.3 مللي ثانية: الكاميرات هي ما دفع تلك الـ 16 نبضة لتتجاوز الحد. تعني هامش التوقيت شبه الصفرية أنه لا يوجد ما يمتص النبضة البطيئة.
تُضبط وتيرة مراحل إعادة الضبط بين الحلقات بنفس الطريقة، لكنها لا تُدرج عمداً ضمن هذه الأرقام، لأنها لا تسجّل أي شيء. تُبلّغ lerobot-teleoperate وlerobot-replay بنفس الطريقة، بينما تضيف lerobot-rollout الأسطر الخاصة بالاستيفاء الموصوفة في تقرير الإيقاع.
استكشاف الأخطاء وإصلاحها:
- على نظام Linux، تعمل مفاتيح تدفق التحكم في التسجيل (مفاتيح الأسهم، Escape) على X11 وWayland وجلسات headless/SSH ما دام أن
lerobot-recordيعمل في طرفية تفاعلية — ولا حاجة إلى إعداد$DISPLAY. إذا لم يكن للمفاتيح أي تأثير، فتأكد من أنك في طرفية تفاعلية (TTY) وليس جلسة piped/non-TTY، وأن الطرفية هي النشطة؛ كما تعمل الحروف المكافئةn/r/q. لا يزال التشغيل عن بُعد عبر لوحة المفاتيح teleoperation (على عكس تدفق التحكم في التسجيل) يتطلب خلفية مفاتيح عامة — جلسة X11، أو سطح مكتب Windows، أو macOS مع منح صلاحيات Accessibility/Input Monitoring — وهو غير متاح على Wayland أو الأجهزة headless. راجع pynput limitations.
تصوير مجموعة بيانات
يتم رفع مجموعة بياناتك إلى Hub افتراضيًا (إلا إذا مررت --dataset.push_to_hub=False)، لذا يمكنك فتحها في LeRobot Dataset Visualizer فورًا: أدخل معرف المستودع الخاص بك في الصفحة الرئيسية، أو انتقل مباشرةً إلى الحلقة الأولى عبر الرابط الذي يطبعه هذا الأمر:
echo "https://huggingface.co/spaces/lerobot/visualize_dataset?path=/${HF_USER}/record-test_YYYYMMDD_HHMMSS/episode_0"سجّل الدخول في أداة العرض لفتح مجموعة بيانات خاصة. راجع استكشاف مجموعة بيانات في المتصفح للحصول على شرح تفصيلي.
إعادة تشغيل حلقة
ميزة مفيدة هي دالة replay، التي تتيح لك إعادة تشغيل أي حلقة سجلتها أو حلقات من أي مجموعة بيانات متاحة. تساعدك هذه الدالة على اختبار قابلية تكرار إجراءات روبوتك وتقييم قابلية النقل بين روبوتات من نفس النموذج.
يمكنك إعادة تشغيل الحلقة الأولى على روبوتك إما باستخدام الأمر أدناه أو مع مثال واجهة برمجة التطبيقات:
lerobot-replay \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem58760431541 \
--robot.id=my_awesome_follower_arm \
--dataset.repo_id=${HF_USER}/record-test_YYYYMMDD_HHMMSS \
--dataset.episode=0 # choose the episode you want to replayimport time
from lerobot.datasets import LeRobotDataset
from lerobot.robots.so_follower import SO101Follower, SO101FollowerConfig
from lerobot.utils.robot_utils import precise_sleep
from lerobot.utils.utils import log_say
episode_idx = 0
robot_config = SO101FollowerConfig(port="/dev/tty.usbmodem5AB90687491", id="my_follower_arm")
robot = SO101Follower(robot_config)
robot.connect()
dataset = LeRobotDataset("<hf_username>/<dataset_repo_id>", episodes=[episode_idx])
actions = dataset.select_columns("action")
log_say(f"Replaying episode {episode_idx}")
for idx in range(dataset.num_frames):
t0 = time.perf_counter()
action = {
name: float(actions[idx]["action"][i]) for i, name in enumerate(dataset.features["action"]["names"])
}
robot.send_action(action)
precise_sleep(max(1.0 / dataset.fps - (time.perf_counter() - t0), 0.0))
robot.disconnect()يجب أن يُعيد روبوتك تحريك حركات مشابهة لتلك التي سجّلتها. على سبيل المثال، راجع هذا الفيديو حيث نستخدم replay على روبوت ALOHA من Trossen Robotics.
تدريب سياسة
لتدريب سياسة للتحكم في روبوتك، استخدم سكربت lerobot-train. هناك بعض الحُجج المطلوبة. إليك مثالاً على الأمر:
lerobot-train \
--dataset.repo_id=${HF_USER}/record-test_YYYYMMDD_HHMMSS \
--policy.type=act \
--output_dir=outputs/train/act_so101_test \
--job_name=act_so101_test \
--policy.device=cuda \
--trackio.enable=true \
--policy.repo_id=${HF_USER}/my_policyلنشرح الأمر:
- قدّمنا مجموعة البيانات المسجّلة سابقًا كحجة باستخدام
--dataset.repo_id=${HF_USER}/record-test_YYYYMMDD_HHMMSS(استخدم الاسم الكامل لمجموعتك، بما في ذلك الطابع الزمني). - قدّمنا السياسة مع
policy.type=act. هذا يُحمّل الإعدادات منconfiguration_act.py. ومن المهم أن هذه السياسة ستتكيف تلقائيًا مع عدد حالات المحركات وإجراءات المحركات والكاميرات في روبوتك (مثلwristوtop) التي تم حفظها في مجموعة بياناتك. - قدّمنا
policy.device=cudaلأننا نتدرّب على معالج رسومي من Nvidia، لكن يمكنك استخدامpolicy.device=mpsللتدريب على شرائح Apple. - قدّمنا
trackio.enable=trueلاستخدام Trackio في عرض رسوم التدريب. هذا الخيار اختياري. نفّذtrackio show --project lerobotلفتح لوحة التحكم، أو مرّر--trackio.space_id=<user>/<space>لمزامنة التشغيل مع مساحة Hugging Face. - لم نضبط
--steps، لذا تُنفَّذ عملية التدريب لعدد الخطوات الافتراضي البالغ 100,000 خطوة. وغالبًا ما يكون هذا العدد أكبر مما تحتاجه مجموعة بيانات صغيرة: فالتعلم بالتقليد يتقارب عادةً خلال 5–10 دورات على البيانات. راجع دليل الحساب والأجهزة لتحويل عدد الدورات إلى قيمة--stepsتناسب حجم مجموعة بياناتك وحجم الدفعة.
ستستغرق عملية التدريب عدة ساعات. ستجد نقاط التفتيش في outputs/train/act_so101_test/checkpoints.
للاستئناف من نقطة تحقق، يُظهر الأمر أدناه مثالاً على كيفية الاستئناف من نقطة التحقق last الخاصة بسياسة act_so101_test:
lerobot-train \
--config_path=outputs/train/act_so101_test/checkpoints/last/pretrained_model/train_config.json \
--resume=trueيقبل --config_path أيضًا معرّف مستودع Hub: إذا قام تشغيل ما بدفع نقاط الفحص الخاصة به إلى Hub (باستخدام --save_checkpoint_to_hub=true)، يمكنك استئناف التدريب مباشرةً من المستودع — حيث يتم تنزيل أحدث نقطة فحص ويستمر التدريب، مع استعادة المُحسِّن، والمُجدوِل، وعداد الخطوات وترتيب البيانات:
lerobot-train --config_path=${HF_USER}/my_policy --resume=trueإذا كنت لا تريد دفع نموذجك إلى المستودع بعد التدريب، استخدم --policy.push_to_hub=false.
بالإضافة إلى ذلك، يمكنك تقديم وسوم tags إضافية أو تحديد license لنموذجك أو جعل مستودع النموذج private عن طريق إضافة ما يلي: --policy.private=true --policy.tags=\[so101,tutorial\] --policy.license=mit
التدريب باستخدام Google Colab
إذا لم يكن جهازك المحلي مجهزة بوحدة معالجة رسومية قوية، يمكنك استخدام Google Colab لتدريب نموذجك من خلال اتباع دفتر تدريب ACT.
التدريب باستخدام Hugging Face Jobs
يتيح لك Hugging Face Jobs اختيار العتاد بسهولة وتشغيل التدريب في السحابة. لذا، إذا لم تكن تملك وحدة معالجة رسومية قوية، أو كنت بحاجة إلى ذاكرة VRAM إضافية، أو كنت ترغب ببساطة في تدريب نموذج بشكل أسرع بكثير، فاستخدم HF Jobs! فهو يعمل بنظام الدفع حسب الاستخدام، حيث تدفع ببساطة عن كل ثانية من الاستخدام، ويمكنك الاطلاع على التسعير والمعلومات الإضافية هنا.
يعمل lerobot-train محليًا بشكل افتراضي. لتشغيله على وحدة معالجة رسومية من HuggingFace، مرّر --job.target مع اسم نوع العتاد:
lerobot-train \
--dataset.repo_id=${HF_USER}/record-test_YYYYMMDD_HHMMSS \
--policy.type=act \
--policy.repo_id=${HF_USER}/my_policy \
--job.target=a10g-smallاستعرض النكهات المتاحة والأسعار باستخدام hf jobs hardware. يقوم الأمر بتشغيل العملية وبث سجلاتها إلى طرفية جهازك؛ اضغط على Ctrl-C لفصل الاتصال (ستستمر العملية في التشغيل على السحابة). أعد الاتصال أو ألغِ العملية باستخدام:
hf jobs logs <job-id>
hf jobs cancel <job-id>إذا كان مجموعة بياناتك موجودة محليًا فقط (ولم تُرفع بعد إلى Hub)، فسيتم دفعها تلقائيًا إلى مستودع Hub خاص حتى يتمكن المهمة من تنزيلها عبر repo_id (لا يتم نشر أي شيء للعموم). يتم دفع النموذج المدرَّب إلى مستودع النموذج في نهاية التشغيل. ولإضافة دفع كل نقطة تحقق وسيطة إلى Hub أثناء حفظها (حتى تتمكن من مراقبة التقدم أثناء التشغيل)، أضف --save_checkpoint_to_hub=true — وهذا يتطلب صورة وقت تشغيل تتضمن هذه الميزة.
يتم وسم كل مهمة (وأي مجموعة بيانات تُدفع بواسطة التشغيل) بوسم lerobot ليسهل العثور عليها على Hub. أضف وسومك الخاصة باستخدام --job.tags '["my-tag"]'.
بشكل افتراضي، يُحدَّد وقت التشغيل الفعلي للمهمة بحد أقصى قدره 2d (48 ساعة). يمكنك تجاوز هذا الحد باستخدام سلسلة مدة HF Jobs، مثل --job.timeout=4h للفشل بشكل أسرع أو --job.timeout=7d لتشغيل أطول.
ملاحظة: يتم إنشاء مستودع النموذج مسبقًا (حيث يحتوي على إعدادات التدريب المُعدّة مسبقًا التي يعمل منها المهمة). إذا فشلت عملية التشغيل قبل دفع النموذج، يُترك ذلك المستودع على Hub لتتمكن من فحصه — فهو لا يُحذف تلقائيًا، لذا قد تترك الفشل المتكرر مستودعات فارغة. احذف مستودعًا باستخدام
hf repos delete <repo-id>.
المتطلبات المسبقة: نفّذ hf auth login قبل الإرسال. فيما يتعلق بـ Trackio، مرّر --trackio.space_id=<user>/<space> — حيث يتم إنشاء المساحة إذا لم تكن موجودة، ويتم تمرير HF_TOKEN الخاص بالمهمة تلقائيًا.
الاستئناف على مهمة. إضافة --job.target إلى أمر الاستئناف يؤدي إلى تنفيذ الاستئناف في السحابة — نفس الأمر يعمل محليًا أو عن بُعد. مستودع نقطة التفتيش هو مصدر الحقيقة، وتواصل نقاط التفتيش الجديدة السلالة في نفس المستودع:
# resume a Hub run on a job (its checkpoints are already on the Hub)
lerobot-train --config_path=${HF_USER}/my_policy --resume=true --job.target=a10g-small
# resume a LOCAL run on a job — the checkpoint is uploaded to a private Hub repo first,
# then the job resumes from it (a local-only dataset is uploaded the same way)
lerobot-train \
--config_path=outputs/train/act_so101_test/checkpoints/last/pretrained_model/train_config.json \
--resume=true \
--job.target=a10g-smallتأتي إعدادات المهمة من الأمر الحالي، لذا تجاوز --job.target و--job.timeout وما إلى ذلك حسب الحاجة؛ ولكي تكون الجولة المستأنفة قابلةً للاستئناف لاحقًا، احتفظ بـ--save_checkpoint_to_hub=true.
رفع نقاط التفتيش للسياسات
بمجرد اكتمال التدريب، ارفع أحدث نقطة تفتيش باستخدام:
hf upload ${HF_USER}/act_so101_test \
outputs/train/act_so101_test/checkpoints/last/pretrained_modelيمكنك أيضًا رفع نقاط التفتيش الوسيطة باستخدام:
CKPT=010000
hf upload ${HF_USER}/act_so101_test${CKPT} \
outputs/train/act_so101_test/checkpoints/${CKPT}/pretrained_modelشغّل الاستدلال وقيّم سياستك
استخدم lerobot-rollout لنشر سياسة مُدرَّبة على روبوتك. يمكنك اختيار استراتيجيات مختلفة حسب احتياجاتك.
استخدم نفس --robot.id (حتى يتم العثور على المعايرة) ونفس --robot.cameras ونفس وصف المهمة كما في مجموعة البيانات المسجلة. يجب أن تبدأ أسماء مجموعات البيانات المسجلة بواسطة lerobot-rollout بـ rollout_، وكما هو الحال مع lerobot-record، فإنه يضيف طابعًا زمنيًا إلى ذلك الاسم.
تحمّل الأمثلة أدناه النموذج من --policy.path. لتثبيت إصدار محدد تم دفعه — وهو أمر مفيد بعد أن يكون --save_checkpoint_to_hub=true قد التزم بعدة نقاط تحقق — أضف --policy.pretrained_revision مع تجزئة التزام أو فرع أو وسم. يتم وسم كل نقطة تحقق تم دفعها بخطوتها (مثل --policy.pretrained_revision=010000)، لذا يمكنك استعادة نقطة تحقق حسب خطوتها دون الحاجة إلى البحث عن تجزئة التزامها.
lerobot-rollout \
--strategy.type=base \
--policy.path=${HF_USER}/my_policy \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem5AB90687491 \
--robot.id=my_follower_arm \
--robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \
--task="Grab the black cube" \
--duration=60lerobot-rollout \
--strategy.type=sentry \
--strategy.upload_every_n_episodes=5 \
--policy.path=${HF_USER}/my_policy \
--robot.type=so101_follower \
--robot.port=/dev/tty.usbmodem5AB90687491 \
--robot.id=my_follower_arm \
--robot.cameras="{ wrist: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}, top: {type: opencv, index_or_path: 1, width: 640, height: 480, fps: 30}}" \
--dataset.repo_id=${HF_USER}/rollout_so101_test \
--dataset.single_task="Grab the black cube" \
--duration=600يحدد علم --strategy.type وضع التنفيذ:
base: نشر ذاتي دون تسجيل بيانات (مفيد للتقييم السريع)sentry: تسجيل مستمر مع رفع تلقائي (مفيد للتقييم على نطاق واسع)highlight: تسجيل عبر مخزن حلقي مع حفظ عند الضغط على المفاتيح (مفيد لالتقاط الأحداث المثيرة للاهتمام)dagger: جمع البيانات بمشاركة الإنسان (انظر جمع بيانات HIL)episodic: تسجيل سياسة موجهة نحو الحلقات مع وجود مراحل إعادة تعيين بين الحلقات
تدعم جميع الاستراتيجيات --inference.type=rtc لتنفيذ سلس مع نماذج VLA البطيئة (Pi0, Pi0.5, SmolVLA). راجع نشر السياسة لكل استراتيجية وأعلامها.