LeRobot documentation
تمثيلات الإجراءات
تمثيلات الإجراءات
يشرح هذا الدليل الطرق المختلفة التي يمكن من خلالها تمثيل أفعال الروبوت في LeRobot، وكيف ترتبط هذه الطرق ببعضها البعض، ومتى ينبغي استخدام كل منها.
مساحة المفصل مقابل مساحة الطرف النهائي
قبل مناقشة تمثيلات الإجراءات، من المفيد فهم المساحتين الإحداثيتين اللتين يمكن أن توجد فيهما الإجراءات.
فضاء مشترك
تحدد إجراءات فضاء المفاصل (Joint-space) الموضع المستهدف لكل محرك مباشرةً. ففي ذراع روبوتية بست درجات حرية (6-DOF) مزودة بمقبض، قد تبدو إجراءات فضاء المفاصل على النحو التالي:
action = [shoulder_pan: 45.0, shoulder_lift: -20.0, elbow: -30.0, wrist_pitch: 10.0, wrist_roll: 0.0, wrist_yaw: 5.0, gripper: 0.8]يمثل الفضاء المشترك الافتراضي في LeRobot. فهو بسيط، ولا يتطلب نموذج حركيات، ويترجم مباشرةً إلى أوامر المحركات. وتعتمد معظم الإعدادات الموجهة للمبتدئين (SO-100، Koch) على الإجراءات في الفضاء المشترك.
مساحة الطرف النهائي (EE)
تحدد إجراءات فضاء الطرف النهائي الموضع والاتجاه المطلوبين لنهاية أداة الروبوت (الماسك) في الإحداثيات الديكارتية:
action = [x: 0.25, y: -0.10, z: 0.15, wx: 0.0, wy: 0.0, wz: 0.1, gripper: 0.8]تُعدّ فضاء الطرف النهائي (EE) أكثر بديهيةً للمهام مثل الالتقاط والوضع، لأنها تصف مباشرةً المكان الذي يجب أن يتوجه إليه الماسك، لكنها تتطلب نموذج حركيات (URDF) لتحويل بين أوضاع الطرف النهائي وزوايا المفاصل.
التحويل بين المساحات
توفر LeRobot خطوات معالج لتحويل المساحات بين فضاء المفاصل وفضاء الطرف النهائي باستخدام الحركية الأمامية والعكسية. وتُبنى هذه الخطوات على أساس RobotKinematics، الذي يقوم بتحميل نموذج URDF لروبوتك.
from lerobot.model.kinematics import RobotKinematics
from lerobot.robots.so_follower.robot_kinematic_processor import (
ForwardKinematicsJointsToEE,
InverseKinematicsEEToJoints,
)
kinematics = RobotKinematics(
urdf_path="./SO101/so101_new_calib.urdf",
target_frame_name="gripper_frame_link",
joint_names=["shoulder", "elbow", "wrist_pitch", "wrist_roll", "wrist_yaw"],
)
# Joints → EE (for observations: "where is my gripper?")
fk_step = ForwardKinematicsJointsToEE(kinematics=kinematics, motor_names=[...])
# EE → Joints (for actions: "move my gripper here")
ik_step = InverseKinematicsEEToJoints(kinematics=kinematics, motor_names=[...])راجع examples/so100_to_so100_EE/ للحصول على مثال عملي كامل لتسجيل وإعادة تشغيل وتقييم الأفعال في فضاء EE على ذراع SO-100.
الإجراءات المطلقة والنسبية والدلتا
سواء كنت تعمل في فضاء المفاصل أو فضاء الطرف النهائي، يمكن التعبير عن قيم الإجراء بثلاث طرق مختلفة. تتبع المصطلحات UMI (Chi et al., 2024).
الإجراءات المطلقة (الافتراضي في LeRobot)
تحدد كل إجراء الموضع المستهدف مباشرةً.
مثال (مساحة مشتركة، كتلة من 4):
current_state = [45.0, -30.0, 10.0]
action_chunk = [
[46.0, -29.0, 11.0], # go to 46, -29, 11
[47.5, -27.0, 12.0], # go to 47.5, -27, 12
[49.0, -25.0, 13.5], # go to 49, -25, 13.5
[50.0, -24.0, 15.0], # go to 50, -24, 15
]كل قيمة تمثل موضعًا مستهدفًا في إطار إحداثيات الروبوت. الأمر بسيط ومباشر، لكنه يتطلب إطار إحداثيات عالميًا متسقًا. هذا هو الافتراضي في LeRobot.
الإجراءات النسبية (تُستخدم بواسطة OpenPI / pi0)
كل إجراء في الدفعة هو إزاحة عن الحالة الحالية في لحظة التنبؤ. جميع الإجراءات في الدفعة تشترك في نفس نقطة المرجع:
current_state = [45.0, -30.0, 10.0]
relative_chunk = [
[1.0, 1.0, 1.0], # +1 from current → target 46, -29, 11
[2.5, 3.0, 2.0], # +2.5 from current → target 47.5, -27, 12
[4.0, 5.0, 3.5], # +4 from current → target 49, -25, 13.5
[5.0, 6.0, 5.0], # +5 from current → target 50, -24, 15
]التحويل مباشر: relative = absolute - current_state. لاستعادة القيمة المطلقة: absolute = relative + current_state.
لماذا نستخدم الإجراءات النسبية؟ يتعلم النموذج التنبؤ بإزاحات متمركزة حول الصفر، وهو أمر أسهل في التطبيع ويؤدي إلى تدريب أكثر استقرارًا. وبما أن كل مقطع يشير إلى نفس الحالة الحالية، فلا يوجد تراكم للأخطاء عبر المقاطع.
إجراءات دلتا (الفرق المتسلسلة)
كل إجراء هو إزاحة عن الإجراء السابق (أو عن الحالة الحالية في الخطوة الأولى):
current_state = [45.0, -30.0, 10.0]
delta_chunk = [
[1.0, 1.0, 1.0], # current → 46, -29, 11
[1.5, 2.0, 1.0], # previous action → 47.5, -27, 12
[1.5, 2.0, 1.5], # previous action → 49, -25, 13.5
[1.0, 1.0, 1.5], # previous action → 50, -24, 15
]هنا كل خطوة نسبية للتي تسبقها. لاستعادة الموضعيات المطلقة يجب عليك جمع جميع الدلتا السابقة، مما يعني أن الأخطاء تتراكم مع مرور الوقت. يجادل UMI صراحةً ضد هذا التمثيل لهذا السبب.
مقارنة بصرية
يوضح الشكل أدناه (المستند إلى شكل من UMI, Chi et al., 2024) الفرق الجوهري. مع relative trajectory، تشير كل حركة في الدفعة إلى نفس نقطة الأصل (الحالة الحالية)، لذا فإن خطوة الاستدلال الجديدة تعيد ضبط المرجع بشكل نظيف. أما مع delta، فتعتمد كل حركة على الحركة السابقة، مما يؤدي إلى تراكم الأخطاء. وتتطلب الحركات Absolute إطار إحداثيات عالمي متسق.
استخدام الإجراءات النسبية في LeRobot
يوفر LeRobot RelativeActionsProcessorStep للتحويل بين الإجراءات المطلقة والإجراءات النسبية داخل خط المعالجة. وهذا هو الأسلوب الذي تدعم به pi0 وpi0.5 وpi0_fast الإجراءات النسبية.
ملاحظة: جميع نماذج pi (pi0، pi0.5، pi0fast) تطبّق التحويل النسبي _قبل التطبيع (
relative → normalize)، لذا يرى المُطبِّع دائمًا قيم الدلتا (النسبية). وهذا يعني أن إحصاءات الإجراءات النسبية مطلوبة لجميعها عند التدريب باستخدامuse_relative_actions=true. في pi0_fast، يعدّلRelativeActionsProcessorStepالإجراء فقط — بينما تبقى ملاحظة الحالة دون تغيير — لذا لا يزالNormalizerProcessorStepيعمل قبل مُرمِّز الحالة، ويستمر المُرمِّز في استلام الحالة المُطبَّعة كما هو متوقع.
كيف يعمل
أثناء التدريب (المعالجة المسبقة)، يتم تحويل الإجراءات من المطلقة إلى النسبية قبل أن تراها النموذج:
raw absolute action → RelativeActionsProcessorStep → normalize → modelأثناء الاستدلال (المعالجة اللاحقة)، تُعاد تنبؤات النموذج إلى قيم مطلقة قبل إرسالها إلى الروبوت:
model output → unnormalize → AbsoluteActionsProcessorStep → robotتقرأ AbsoluteActionsProcessorStep الحالة الحالية المخزنة مؤقتًا من RelativeActionsProcessorStep المقترن بها، لذا يجب ربط الاثنين معًا (يتم التعامل مع ذلك تلقائيًا بواسطة مصنع السياسة).
تفعيل الإجراءات النسبية لعائلة pi (pi0، pi0.5، pi0_fast)
الخطوة 1: احسب مسبقًا إحصاءات الإجراءات النسبية لمجموعتك البيانات:
lerobot-edit-dataset \
--repo_id your_dataset \
--new_repo_id your_dataset \
--operation.type recompute_stats \
--operation.overwrite true \
--operation.relative_action true \
--operation.chunk_size 50 \
--operation.relative_exclude_joints "['gripper']"الخطوة 2: تدريب مع تمكين الإجراءات النسبية:
lerobot-train \
--dataset.repo_id=your_dataset \
--policy.type=pi0 \
--policy.use_relative_actions=true \
--policy.relative_exclude_joints='["gripper"]'يحدد المعامل relative_exclude_joints المفاصل التي يجب أن تبقى في الفضاء المطلق. على سبيل المثال، تكون أوامر الماسك ثنائية (فتح/إغلاق) عادةً ولا تستفيد من الترميز النسبي.
في حالات تكوينات السياسة التي تُعرّف action_feature_names، تُملأ هذه القائمة بواسطة make_policy من بيانات الوصف names الخاصة بخاصية الإجراء في مجموعة البيانات.
قد تكون الأسماء تسلسلاً مسطّحاً أو قاموساً تكون قيمه جميعها قوائم أو مجموعات.
على سبيل المثال، يتحول {"arm": ["shoulder", "elbow"], "hand": ["gripper"]} إلى ["shoulder", "elbow", "gripper"]، وليس مفاتيح المجموعات.
يتم الحفاظ على ترتيب إدراج المجموعات والترتيب داخل كل مجموعة، لذا يُنصح بإعلان الأسماء بنفس ترتيب متجه الإجراء.
تحتفظ خرائط الأسماء إلى الفهارس القديمة بسلوك ترتيب المفاتيح الخاص بها.
دمج الإجراءات النسبية مع RTC
يعمل RTC على استنتاج السياسة بتردد عالٍ ويرسل الإجراءات إلى الروبوت فور توقعها بدلاً من الانتظار حتى اكتمال الكتلة كاملة. الإجراءات النسبية و RTC متوافقة تماماً: لأن كل كتلة في الوضع النسبي تشير إلى الحالة الحالية نفسها (الملتقطة عند بدء الاستنتاج)، تظل كل إجراء متوقع داخل الكتلة إزاحة صالحة حتى لو كان الروبوت قد تحرك بالفعل. لا حاجة إلى معالجة خاصة — حيث يخزّن RelativeActionsProcessorStep الحالة مرة واحدة لكل استدعاء استنتاج، ويطبّق AbsoluteActionsProcessorStep هذه الحالة على كل إجراء في المخرجات المُرسلة عبر البث.
دمج الإجراءات النسبية مع فضاء EE
تعمل الإجراءات النسبية في كل من فضاء المفصل وفضاء الطرف النهائي. على سبيل المثال، إذا كانت مجموعة بياناتك تخزن إجراءات الطرف النهائي، فإن الترميز النسبي يحوّلها إلى إزاحات عن وضعية الطرف النهائي الحالية:
current_ee_state = [x: 0.25, y: -0.10, z: 0.15, gripper: 0.8]
absolute_ee_chunk = [
[0.26, -0.09, 0.16, 0.8],
[0.28, -0.07, 0.18, 0.8],
]
relative_ee_chunk = [
[0.01, 0.01, 0.01, 0.0], # offset from current EE pose
[0.03, 0.03, 0.03, 0.0], # offset from current EE pose
]ملخص خط المعالجة
إليك كيفية تركيب المعالجات المختلفة. كل سهم يمثل خطوة معالجة، ويمكن ربطها في RobotProcessorPipeline أو PolicyProcessorPipeline:
┌─────────────────────────────────────────┐
Action Space │ Joint Space ←──IK──→ EE Space │
│ ForwardKinematicsJointsToEE │
│ InverseKinematicsEEToJoints │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
Representation │ Absolute ←────→ Relative │
│ RelativeActionsProcessorStep (pre) │
│ AbsoluteActionsProcessorStep (post) │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
Normalization │ Raw ←────→ Normalized │
│ NormalizerProcessorStep (pre) │
│ UnnormalizerProcessorStep (post) │
└─────────────────────────────────────────┘قد يربط مُعالج ما قبل التدريب النموذجي بين: raw absolute joint actions → relative → normalize. أما مُعالج ما بعد الاستدلال النموذجي فيربط بين: unnormalize → absolute → (optionally IK to joints).
المراجع
- واجهة التلاعب الشاملة (UMI) - تشي وآخرون، 2024. يحدد تمثيل مسار الإجراء النسبي ويقارنه بالإجراءات المطلقة والدلتا.
- مقدمة إلى المعالجات - كيف تعمل خطوط معالجة المعالجات في LeRobot.
examples/so100_to_so100_EE/- مثال كامل لتسجيل وتقييم الإجراءات في فضاء EE.