LeRobot documentation
المعالجات للروبوتات والمشغّلين عن بُعد
المعالجات للروبوتات والمشغّلين عن بُعد
يُبيّن هذا الدليل كيفية بناء خطوط معالجة وتعديلها لربط المشغّلين عن بُعد (مثل الهاتف) بالروبوتات ومجموعات البيانات. تُوحّد خطوط المعالجة التحويلات بين فضاءات الإجراءات والملاحظات المختلفة، مما يتيح لك تبديل أنظمة التشغيل عن بُعد والروبوتات دون الحاجة إلى إعادة كتابة أكواد الربط.
نستخدم أمثلة المتبوع Phone إلى SO‑100 للتوضيح، لكن الأنماط نفسها تنطبق على الروبوتات الأخرى.
ما ستتعلمه
- التحكم المطلق مقابل التحكم النسبي في EE: ما يعنيه كل منهما، والمقايضات، وكيفية الاختيار لمهمتك.
- نمط ثلاث مراحل: كيفية تحويل إجراءات التشغيل عن بُعد إلى إجراءات مجموعة البيانات ثم إلى أوامر الروبوت، وكيفية تحويل ملاحظات الروبوت إلى ملاحظات مجموعة البيانات.
- المُكيِّفات (
to_transition/to_output): كيف تُحوِّل هذه القواميس الخام إلىEnvTransitionثم تُعيدها إلى شكلها الأصلي لتقليل الكود المتكرر. - عقود ميزات مجموعة البيانات: كيف تُعلن الخطوات عن الميزات عبر
transform_features(...)، وكيفية تجميعها/دمجها للتسجيل. - اختيار تمثيل: متى نخزّن المفاصل، أو أوضاع الطرف النهائي المطلقة، أو دلتا الطرف النهائي النسبية — وكيف يؤثر ذلك على التدريب.
- إرشادات تخصيص خط الأنابيب: كيفية تبديل الروبوتات/ملفات URDF بأمان وضبط الحدود وحجم الخطوات وخيارات مثل تهيئة IK.
التحكم المطلق مقابل التحكم النسبي في EE
تستخدم الأمثلة في هذا الدليل أوضاعًا مطلقة لمفصل الطرف النهائي (EE) لأنها يسهل الاستدلال عليها. في الممارسة العملية، يُفضَّل غالبًا استخدام دلتا مفصل الطرف النهائي النسبية أو موضع المفاصل كميزات للتعلم.
باستخدام المعالجات، تختار ميزات التعلم التي تريد استخدامها لسياستك. وقد تكون هذه الميزات مواضع/سرعات المفاصل، أو موضع الطرف النهائي المطلق، أو مواضع الطرف النهائي النسبية. كما يمكنك اختيار تخزين ميزات أخرى، مثل عزم المفاصل، والتيارات المحركية، وما إلى ذلك.
ثلاث خطوط أنابيب
غالبًا ما نُركّب ثلاثة خطوط أنابيب. اعتمادًا على إعدادك، قد يكون بعضها فارغًا إذا كانت فضاءات الإجراءات والملاحظات متطابقة بالفعل. يتولى كلٌّ من هذه الخطوط الأنابيب تحويلات مختلفة بين فضاءات الإجراءات والملاحظات المختلفة. أدناه شرح موجز لكل خط أنابيب.
- خط أنابيب 1: مساحة أفعال التشغيل عن بُعد → مساحة أفعال مجموعة البيانات (وضعية الهاتف → أهداف الطرف النهائي)
- خط أنابيب 2: مساحة إجراءات مجموعة البيانات → مساحة أوامر الروبوت (أهداف الطرف النهائي → المفاصل)
- خط أنابيب 3: مساحة ملاحظة الروبوت → مساحة ملاحظة مجموعة البيانات (المفاصل → وضعية الطرف النهائي)
فيما يلي مثال على خطوط الأنابيب الثلاثة التي نستخدمها في أمثلة المتبوع من الهاتف إلى SO-100:
phone_to_robot_ee_pose_processor = RobotProcessorPipeline[tuple[RobotAction, RobotObservation], RobotAction]( # teleop -> dataset action
steps=[
MapPhoneActionToRobotAction(platform=teleop_config.phone_os),
EEReferenceAndDelta(
kinematics=kinematics_solver, end_effector_step_sizes={"x": 0.5, "y": 0.5, "z": 0.5}, motor_names=list(robot.bus.motors.keys()),
),
EEBoundsAndSafety(
end_effector_bounds={"min": [-1.0, -1.0, -1.0], "max": [1.0, 1.0, 1.0]}, max_ee_step_m=0.20,
),
GripperVelocityToJoint(),
],
to_transition=robot_action_observation_to_transition,
to_output=transition_to_robot_action,
)
robot_ee_to_joints_processor = RobotProcessorPipeline[tuple[RobotAction, RobotObservation], RobotAction]( # dataset action -> robot
steps=[
InverseKinematicsEEToJoints(
kinematics=kinematics_solver, motor_names=list(robot.bus.motors.keys()), initial_guess_current_joints=True,
),
],
to_transition=robot_action_observation_to_transition,
to_output=transition_to_robot_action,
)
robot_joints_to_ee_pose = RobotProcessorPipeline[RobotObservation, RobotObservation]( # robot obs -> dataset obs
steps=[
ForwardKinematicsJointsToEE(kinematics=kinematics_solver, motor_names=list(robot.bus.motors.keys()))
],
to_transition=observation_to_transition,
to_output=transition_to_observation,
)لماذا to_transition / to_output
لتحويل البيانات من الروبوت/المشغّل عن بُعد إلى خط المعالجة والعكس، نستخدم مُكيّفات خط المعالجة to_transition وto_output.
تُوحّد هذه المُكيّفات عمليات التحويل لتقليل الأكواد المتكررة، وتشكّل الجسر بين القواميس الخام للروبوت والمشغّل عن بُعد وصيغة EnvTransition الخاصة بخط المعالجة.
في أمثلة المتابعة من الهاتف إلى SO-100، نستخدم المُكيّفات التالية:
robot_action_observation_to_transition: يحوّل زوج(action, robot observation)إلى انتقال في خط الأنابيب (تحتاج خطوتا EE وIK إلى مواضع مفاصل الروبوت الحالية).transition_to_robot_action: يحوّل انتقال خط الأنابيب إلى قاموس إجراء للروبوت.observation_to_transition: يحوّل قاموس ملاحظة الروبوت إلى انتقال في خط الأنابيب.transition_to_observation: يحوّل انتقال خط الأنابيب إلى قاموس ملاحظة.
اطّلع على src/lerobot/processor/converters.py لمزيد من التفاصيل.
عقود ميزات مجموعة البيانات
تُحدَّد ميزات مجموعة البيانات بالمفاتيح المحفوظة فيها. يمكن لكل خطوة أن تُعلن عن الميزات التي تعدّلها في عقد يُسمّى transform_features(...). بعد بناء المعالج، يمكن للمعالج تجميع جميع هذه الميزات باستخدام aggregate_pipeline_dataset_features() ودمج قواميس الميزات المتعددة باستخدام combine_feature_dicts(...).
فيما يلي مثال على كيفية إعلان الميزات باستخدام طريقة transform_features في أمثلة المتبوع من الهاتف إلى SO-100:
def transform_features(
self, features: dict[PipelineFeatureType, dict[str, PolicyFeature]]
) -> dict[PipelineFeatureType, dict[str, PolicyFeature]]:
# We only use the ee pose in the dataset, so we don't need the joint positions
for n in self.motor_names:
features[PipelineFeatureType.ACTION].pop(f"{n}.pos", None)
# We specify the dataset features of this step that we want to be stored in the dataset
for k in ["x", "y", "z", "wx", "wy", "wz", "gripper_pos"]:
features[PipelineFeatureType.ACTION][f"ee.{k}"] = PolicyFeature(
type=FeatureType.STATE, shape=(1,)
)
return featuresهنا نحدد ما هي PolicyFeatures التي نعدّلها في هذه الخطوة، حتى نعرف ما هي الميزات التي يمكننا توقعها عند تشغيل المعالج. يمكن بعد ذلك تجميع هذه الميزات واستخدامها لإنشاء ميزات مجموعة البيانات.
فيما يلي مثال على كيفية تجميعنا ودمجنا للميزات في مثال تسجيل الهاتف إلى SO-100:
features=combine_feature_dicts(
# Run the feature contract of the pipelines
# This tells you how the features would look like after the pipeline steps
aggregate_pipeline_dataset_features(
pipeline=phone_to_robot_ee_pose_processor,
initial_features=create_initial_features(action=phone.action_features), # <- Action features we can expect, these come from our teleop device (phone) and action processor
use_videos=True,
),
aggregate_pipeline_dataset_features(
pipeline=robot_joints_to_ee_pose,
initial_features=create_initial_features(observation=robot.observation_features), # <- Observation features we can expect, these come from our robot and observation processor
use_videos=True,
patterns=["observation.state.ee"], # <- Here you could optionally filter the features we want to store in the dataset, with a specific pattern
),
),كيف يعمل:
aggregate_pipeline_dataset_features(...): يطبّقtransform_featuresعبر خط الأنابيب ويصفّي حسب الأنماط (تُضمَّن الصور عندما يكونuse_videos=True، وتُضمَّن ميزات الحالة عندما يُحدَّدpatterns).combine_feature_dicts(...): دمج عدة قواميس ميزات.- يستخدم التسجيل عبر
record_loop(...)الدالةbuild_dataset_frame(...)لبناء إطارات متوافقة معdataset.featuresقبل استدعاءadd_frame(...)لإضافة الإطار إلى مجموعة البيانات.
إرشادات عند تخصيص خطوط أنابيب الروبوت
يمكنك تخزين أي من الميزات التالية كمساحة إجراء/ملاحظة:
- مواضع المفاصل
- وضعيات EE المطلقة
- الفروقات النسبية في EE
- مزايا أخرى: السرعة المشتركة، العزوم، وما إلى ذلك.
اختر ما تريد استخدامه لفضاء إجراء السياسة وملاحظة السياسة، ثم اضبط/عدّل خطوط الأنابيب والخطوات وفقاً لذلك.
روبوتات مختلفة
- يمكنك إعادة استخدام خطوط الأنابيب بسهولة، على سبيل المثال لاستخدام روبوت آخر مع التحكم عن بُعد عبر الهاتف، وذلك بتعديل الأمثلة واستبدال
RobotKinematics(URDF) وmotor_namesلاستخدام روبوتك الخاص مع التحكم عن بُعد عبر الهاتف. بالإضافة إلى ذلك، يجب عليك التأكد من أنtarget_frame_nameيشير إلى قابض/معصم روبوتك.
الأمان أولاً
- عند تغيير خطوط الأنابيب، ابدأ بحدود صارمة، ونفّذ خطوات السلامة عند العمل مع روبوتات حقيقية.
- يُنصح بالبدء بالمحاكاة أولاً ثم الانتقال إلى الروبوتات الحقيقية.
هذا كل شيء! نأمل أن يساعدك هذا الدليل في البدء بتخصيص خطوط أنابيب روبوتاتك. إذا واجهت أي مشكلات في أي نقطة، فانتقل إلى مجتمع Discord لدينا للحصول على الدعم.
Update on GitHub