LeRobot documentation
المحاكاة: محلية أو مُقدَّمة
المحاكاة: محلية أو مُقدَّمة
يمكن تشغيل بيئة محاكاة بطريقتين:
- كـ بيئة مُجمَّعة (
--env.*): بيئات متعددة لمهمة واحدة، تُتقدَّم معًا مع كل استدعاء لـstep(). يستخدمهاlerobot-evalوالتقييم أثناء التدريب. - كروبوت محاكاة (sim robot) (
--robot.type=sim): بيئة واحدة خلف واجهةRobot، قابلة للاستبدال بالأجهزة الفعلية. يستخدمهاlerobot-rolloutوlerobot-recordوlerobot-teleoperateوlerobot-replay.
تعمل إما محليًا، عبر واجهة برمجة التطبيقات الخاصة بالبيئة، أو مُقدَّمة بواسطة lerobot-env-server، وعادةً في صورة Docker خاصة بها، بحيث لا تتقاطع تبعيات المحاكي مع تبعيات السياسة. يؤدي تعيين endpoint إلى اختيار التنفيذ المُقدَّم؛ وكلا المسارين يكشفان عن الملاحظات القياسية نفسها (صور HWC من نوع uint8، وحالة مسطحة من نوع float32)، ونهايات الحلقات، واتفاقيات التحكم.
يحافظ الكود على فصل ثلاث طبقات:
- يُعدّ env (
lerobot.envs،--env.type) هو ما تنفذه أوامر LeRobot، ويُهيّأ بواسطةEnvConfig. وليس كل بيئة محاكاة:gym_manipulatorيتحكم في روبوت حقيقي. - يُعدّ محاكي (
lerobot.sim) هو المحاكاة التي تقف خلف بيئة محاكاة: وهوSimConfigيحدد تكامله، ويُدار عبر خطوات بواسطةLocalVectorEnv، دون استخدام torch. - يقدّم خادم البيئة (
lerobot.env_server) محاكاة؛ بينما يتحكمRemoteVectorEnvفيه باستخدام نفس واجهة برمجة التطبيقات الخاصة بـLocalVectorEnv.
تقييم نقطة تفتيش
محليًا، مع تثبيت المحاكي بجانب LeRobot (انظر إلى LIBERO):
lerobot-eval \
--policy.path=lerobot/smolvla_libero \
--policy.pretrained_revision=a24f1f380461b665158d52acd140152c79e8b36d \
--policy.device=cuda \
--env.type=libero --env.task=libero_spatial --env.task_ids='[0]' \
--rename_map='{"observation.images.image": "observation.images.camera1", "observation.images.image2": "observation.images.camera2"}' \
--eval.n_episodes=1 --eval.batch_size=1 \
--output_dir=outputs/eval_liberoالخدمة: ابدأ الخادم بنفس البيئة (انظر إلى تقديم بيئة)، وأضف نقطة النهاية الخاصة به:
lerobot-env-server --config_path=docker/sim/configs/libero.yaml --docker=true
lerobot-eval ... --env.server.endpoint=tcp/127.0.0.1:7448تقع جميع خيارات الخادم تحت --env.server.*، ولا ينطبق أي منها على التشغيل المحلي. يطلب العميل النشر المُسمّى باسم --env.type، كما تُسمّيه إعدادات الخادم؛ مرّر --env.server.deployment لاختيار نشر آخر. يفشل الاتصال بنقطة نهاية أو نشر خاطئ خلال --env.server.handshake_timeout_s (10 ثوانٍ) ويحدد ما تخدمه نقطة النهاية. عند التعامل مع خادم محمي بتشفير TLS، مرّر ملف Zenoh JSON5 الخاص به باستخدام --env.server.zenoh_config_path، كما هو الحال في الاستدلال عن بُعد. يجب أن يشغّل الخادم البيئة التي يصفها الأمر: نفس النوع والمهمة واتفاقيات التحكم والجسم المُحاكى (robot_type)، وإلا رفض التقييم البدء وقام بسرد الفروقات. تُسجَّل الخيارات الأخرى المختلفة (مثل الدقة وطول الحلقة) كتحذيرات.
تأتي أسماء الملاحظات من البيئة (observation.images.<camera>، observation.state). إذا تم تدريب نقطة التفتيش بأسماء كاميرات أخرى، فقم بتعيينها باستخدام --rename_map، كما هو الحال مع أي روبوت، مع الحفاظ على هوية كل كاميرا حتى عندما تتشارك عدة كاميرات نفس الشكل. الكاميرات الوهمية (empty_cameras) هي إعداد سياسة يُحفظ مع نقطة التفتيش؛ تجاوز هذا الإعداد باستخدام --policy.empty_cameras فقط عند الحاجة.
قبل الخطوة الأولى، يجب أن يكون كل مدخل نقطة تحقق موجودًا في البيئة بعد إعادة التسمية، مع أبعاد متطابقة للحالة والإجراء وعدد قنوات RGB. قد يختلف ارتفاع الصورة وعرضها: فمعالجة ما قبل السياسة هي المسؤولة عن تغيير الحجم. لا يتم فحص اتفاقيات المتحكم (الإجراءات التفاضلية مقابل المطلقة، صيغة الدوران)؛ استخدم نقطة تحقق تم تدريبها على اتفاقية البيئة.
تُقدّم كل استدعاء لـ step() كل بيئة غير منتهية في الدفعة خطوة واحدة. البيئة التي تنتهي تحتفظ بملاحظتها النهائية حتى إعادة الضبط التالية؛ ولا يؤدي تقدّم البيئات الأخرى إلى إعادة تشغيلها. عند استخدام --eval.use_async_envs=true (الافتراضي)، تعمل كل بيئة في عملية عامل مستقلة، محليًا أو على الخادم، وتُنفَّذ خطوات الدفعة بالتوازي. يقبل الخادم حتى max_envs بيئة لكل دفعة (32 افتراضيًا). يُرسل --env.server.encoding=jpeg (أو --robot.env.server.encoding=jpeg، مع --env.server.jpeg_quality، 90 افتراضيًا) إطارات الكاميرا المُقدَّمة بصيغة JPEG: ردود أصغر لخادم بعيد ودفعات أكبر، مقابل تكلفة زمن الترميز وإطارات خاسرة. على localhost، تكون الإطارات الخام أسرع. يحمل الرد إطارات كل البيئات في الدفعة، ويجب أن يتسع max_payload_bytes (32 ميغابايت افتراضيًا) في الطرفين، وإلا رفض الخادم الدفعة عند فتحها. للدفعات الكبيرة أو كاميرات عالية الدقة، ارفع القيمة على الخادم (max_payload_bytes في قسم zenoh من ملف YAML، بجوار listen_endpoints) وعلى العميل (--env.server.max_payload_bytes، أو --robot.env.server.max_payload_bytes).
تشغيل روبوت محاكاة
نفس البيئة كبيئة مُجمَّعة وكروبوت محاكاة:
lerobot-eval --env.type=libero --env.task=libero_spatial --env.task_ids='[0]' ...
lerobot-rollout --robot.type=sim --robot.env.type=libero --robot.env.task=libero_spatial --robot.task_id=0 ...على سبيل المثال:
lerobot-rollout \
--robot.type=sim --robot.env.type=libero --robot.env.task=libero_spatial --robot.task_id=0 \
--task="pick up the black bowl between the plate and the ramekin and place it on the plate" \
--policy.path=lerobot/smolvla_libero \
--policy.pretrained_revision=a24f1f380461b665158d52acd140152c79e8b36d \
--rename_map='{"observation.images.image": "observation.images.camera1", "observation.images.image2": "observation.images.camera2"}' \
--device=cuda --fps=20 --inference.type=sync \
--display_data=true --display_mode=rerun \
--return_to_initial_position=false --play_sounds=false--robot.env.*يتقبل نفس الخيارات التي يتقبلها--env.*في التقييم. يختار--robot.task_idالمهمة الواحدة التي ينفذها الروبوت، بينما ينفذ التقييم كل مهام المجموعة أو تلك الموجودة في--env.task_ids. بيئات EnvHub هي--robot.env.type=envhub --robot.env.hub_path=<user/repo> --robot.env.trust_remote_code=true.- تتطلب بعض السياسات معالجات البيئة (XVLA وCosmos3 على LIBERO، وIsaac Lab Arena). يطبّق
lerobot-evalهذه السياسات، وكذلك يفعل روبوت المحاكاة عند استخدام--inference.type=sync. أما الاستدلال عن بُعد فلا يطبّقها، لذا يرفض مثل هذا نقطة التفتيش عند بدء التشغيل. --robot.env.server.endpoint=tcp/...يشغّل البيئة على خادم بيئات بدلاً من ذلك، كما يفعل--env.server.endpointلبيئة مُجمَّعة. يتحقق الروبوت من أن الخادم يشغّل تلك البيئة.- تُقدّم كل استدعاء لـ
send_action()البيئة خطوة واحدة بالضبط. أما قراءة الملاحظات، والاستدلال على السياسة، والانتظار، فلا تُقدّم المحاكاة؛ إذ يملك حلقة التحكم الحالية إيقاع الساعة الحقيقية. - يجب أن يساوي
--fpsمعدل التحكم في البيئة، مقسومًا على--interpolation_multiplierعند الاستيفاء، لأن كل أمر يُقدّم البيئة خطوة واحدة. عند التسجيل، يجب أن يساوي--dataset.fpsقيمة--fps. وإلا فإن Rollout يرفض البدء.
روبوت المحاكاة هو روبوت: استبدل --robot.type=sim --robot.env.* بـ --robot.* الخاص بالمتابع الحقيقي، ويبقى كل شيء آخر كما هو. يقود المشغّل عن بُعد هذا الروبوت بنفس الطريقة التي يقود بها المتابع الحقيقي (--teleop.type=so101_leader لتوأم SO-101)، عندما يعلن البيئة عن أسماء وحدات الإجراء ووحداتها؛ ويُبلَّغ عن أي عدم تطابق عند أول إجراء. يخزّن lerobot-record الجسم الذي تعلن عنه البيئة كـ robot_type للمجموعة البيانات (panda لـ LIBERO)، أو sim_robot إذا لم تعلن عن أي شيء.
تتبع الحلقات المسجّلة حلقات البيئة. يعيد lerobot-record واستراتيجية النشر الحلقي إعادة تشغيل البيئة المحاكاة في بداية كل حلقة، وينهيها عند انتهاء حلقة البيئة (نجاح، إنهاء أو بلوغ حدّ الخطوات) أو عند انتهاء مدّتها، أيهما يأتي أولاً. لذا فإن كل حلقة مسجّلة هي حلقة محاكاة واحدة، من حالتها الابتدائية. لا حاجة إلى إعادة الضبط يدوياً، لذا تخطَّ مرحلة إعادة الضبط بين الحلقات باستخدام --dataset.reset_time_s=0، ومع استراتيجية النشر الحلقي مرّر أيضاً --strategy.reset_to_initial_position=false. عند انتهاء الحلقة، يتوقف الروبوت: يتجاهل الإجراءات ويحافظ على حالته النهائية، ويحتفظ latest بالمكافأة النهائية والحالة النهائية والنجاح. ثم تبدأ التشغيل عن بُعد واستراتيجية النشر الأساسية حلقة جديدة (وتعيد الاستراتيجية أيضاً ضبط السياسة)، ويتوقف الإعادة. لا تدعم استراتيجيات الحارس والإبراز وDAgger روبوتات المحاكاة بعد، لأنها تسجّل بالوقت أو عند الطلب بدلاً من كل حلقة؛ استخدم الاستراتيجية الحلقيّة للتسجيل. لا تتأثر الروبوتات الحقيقية: حلقاتها مقيّدة بالوقت، ويُعاد ضبط مشهدتها يدوياً. لمعدّلات النجاح، قيّم باستخدام lerobot-eval وبيئة مجمّعة.
تستخدم ميزات كاميرا الروبوت نفس أسماء observation.images.<camera> المستخدمة في التسجيل على الأجهزة الحقيقية. الكاميرا الواحدة غير المسماة هي observation.images.image. يحافظ التقييم المجمّع على مفاتيح البيئة الخاصة بها، مثل observation.image لكاميرا واحدة؛ عند نشر نقطة تحقق بهذا الاسم عبر SimRobot، استخدم --rename_map='{"observation.images.image": "observation.image"}'.
للاستدلال عن بُعد، احتفظ بنفس خيارات --robot.* واستبدل خيارات السياسة والاستدلال المحليين بما يلي:
--inference.type=remote \ --inference.endpoint=tcp/127.0.0.1:7447 \ --inference.deployment=libero \ --inference.semantics=libero-delta-v1
ابدأ خادم السياسة بشكل منفصل باستخدام إعداد الاستدلال عن بُعد. يجب أن يتطابق مخططه مع ملاحظات الروبوت بعد --rename_map. احذف --policy.path من أمر التمرير لأن خادم السياسة يقوم بتحميل نقطة التفتيش. للاستخدام المحلي لـ RTC، استخدم --inference.type=rtc مع إعدادات RTC الخاصة بالسياسة.
عند تأخر السياسة، فإن الاحتفاظ بروبوت محاكاة لا يُقدّم الفيزياء إلى الأمام. تنتقل أعطال المحاكي إلى إيقاف التمرير.
تقديم بيئة
من نسخة المصدر الخاصة بـ LeRobot (يتم بناء الصورة منها)، نفّذ الأمر التالي من جذر المستودع:
lerobot-env-server --config_path=docker/sim/configs/libero.yaml --docker=true--docker=true يستخدم docker/sim/compose.server.yaml، ويختار الصورة من sim.type، ويربط ملف YAML الفعّال، ويشغّل الحاوية على شبكة المضيف، بحيث يستمع الخادم إلى localhost:7448 ما لم يحدد --zenoh.listen_endpoints غير ذلك. استبدل ملف YAML لاختيار محاكي آخر. تأتي نسبة التحكم، واتفاقية الإجراء، وأسماء المكونات، ونوع الروبوت لكل محاكي من conventions() الخاص بتكامله، لذا يكتفي ملف YAML بتسمية المهمة وخيارات المحاكاة.
أما lerobot-policy-server، فتقبل كل حقل في ملف YAML تجاوزًا مدمجًا عبر سطر الأوامر، ويبقى الملف دون تغيير. يتم دمج قيمة القاموس مثل sim.kwargs في ملف YAML:
lerobot-env-server --config_path=docker/sim/configs/libero.yaml --docker=true \
--sim.task=libero_goal \
--sim.kwargs='{gym_kwargs: {observation_height: 256, observation_width: 256}}'يُحفظ التكوين الفعّال تحت $HF_LEROBOT_HOME/sim، بحيث يجده الحاوية عند إعادة تشغيلها. يؤدي تبديل التكوين إلى إعادة إنشاء الخادم وإنهاء الجلسات النشطة. يتم بناء الصورة عند غيابها؛ أضف --build=true لإعادة بنائها بعد تغيير المحاكي أو مصدر LeRobot، أو --stop=true لإيقاف الخادم. تتطلب الحاوية وصول Docker إلى GPU لعرض EGL. تُقدَّم مستودعات EnvHub باستخدام --envhub=<user/repo>؛ راجع EnvHub وخادم المحاكي.
إذا فشل محاكي يعرض باستخدام Vulkan (مثل Isaac Sim، أو ManiSkill/SAPIEN كما في RoboMME، حيث يتضمن ملف الصورة الخاص به ملف Vulkan خاصًا به) داخل الحاوية مع
vkCreateInstance failedأوERROR_INCOMPATIBLE_DRIVERبينما يعمل خارج Docker، فإن الحاوية تحتوي على مكتبات برنامج تشغيل NVIDIA ولكن ليس ملفات المحمّل التي تشير إليها (/usr/share/vulkan/icd.d/nvidia_icd.json،/usr/share/glvnd/egl_vendor.d/10_nvidia.json). قد لا يقوم الوضع الافتراضي لأداة NVIDIA Container Toolkit، المستخدم بواسطةgpus: all، بتركيب هذه الملفات؛ بينما يقوم وضع CDI بذلك. اطلب وحدة المعالجة الرسومية عبر CDI (--device nvidia.com/gpu=allلـdocker run،devices: [nvidia.com/gpu=all]بدلًا منgpus: allفيdocker/sim/compose.server.yaml)، أو أضف الملفين إلى الصورة.
بدون --docker=true، يعمل الأمر نفسه الخادم في البيئة الحالية: تثبيت التبعيات الأصلية لمحاكي الحركة في بيئة معزولة، وتثبيت LeRobot باستخدام --no-deps، وتثبيت docker/sim/requirements.txt. في كلتا الحالتين يستمع على localhost؛ لقبول أجهزة أخرى، مرر عنوان واجهة الشبكة التي تصل إليها، كما في --zenoh.listen_endpoints='[tcp/192.168.1.20:7448]'، وأضف TLS والتحكم في الوصول باستخدام zenoh.config_file في ملف YAML.
تستخدم صور وقت التشغيل الخاصة بـ LIBERO ملفات الحالة الأولية المحوّلة من NumPy. يقوم بناء الصورة بتحويل الأصول الموثوقة من المصدر باستخدام scripts/ci/convert_libero_init_states.py؛ ويرفض الخادم الملفات المحوّلة الناقصة. تتطلب RoboTwin و RoboMME نسخها الخاصة من torch للتخطيط الأصلي و ManiSkill على التوالي؛ وتكون عمليات تثبيت torch الخاصة بها معزولة عن بيئة السياسة.
لا يتم إعادة إرسال طلبات الخادم أبدًا. بعد انتهاء المهلة الزمنيّة الغامض، يفشل العميل؛ أغلقه وافتح جلسة جديدة.
إضافة معيار
راجع إضافة معيار للحصول على وحدات المحاكي، والاتفاقيات، والصور، وتكامل CI.
Update on GitHub