LeRobot documentation

نشر السياسة (lerobot-rollout)

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

نشر السياسة (lerobot-rollout)

lerobot-rollout هو واجهة سطر الأوامر الوحيدة لنشر السياسات المدرَّبة على الروبوتات الحقيقية. يدعم عدة استراتيجيات تنفيذ وخوادم استدلال، بدءًا من التقييم السريع وصولًا إلى التسجيل المستمر وجمع البيانات بمشاركة الإنسان في الحلقة.

البدء السريع

لا حاجة إلى أي تبعيات إضافية بخلاف الإضافات الخاصة بروبوتك وسياساتك.

lerobot-rollout \
    --strategy.type=base \
    --policy.path=lerobot/act_koch_real \
    --robot.type=koch_follower \
    --robot.port=/dev/ttyACM0 \
    --task="pick up cube" \
    --duration=30

يُشغّل هذا الأمر السياسة لمدة 30 ثانية دون تسجيل.

اختيار جهاز

مرّر --device=cpu أو --device=cuda لتجاوز جهاز نقطة التفتيش على مضيف يتوفر فيه ذلك الجهاز. يُطبَّق الجهاز المُحدَّد على تكوين السياسة قبل تحميل السياسة وبناء مُعالِجاتها. على سبيل المثال، أضف --device=cpu إلى الأمر أعلاه لتشغيل نقطة تفتيش مُدرَّبة على CUDA على مضيف يعمل بالمعالج المركزي فقط، إذا كانت السياسة تدعم التنفيذ على المعالج المركزي. تحقق من أن الاستدلال على المعالج المركزي يمكنه تلبية معدل التحكم المطلوب قبل النشر على روبوت.

عند إغفال --device، يستخدم rollout جهاز إعدادات السياسة إذا كان مُعيَّنًا، وإلا فإنه يختار جهازًا متاحًا تلقائيًا. ينطبق السلوك نفسه على RolloutConfig(device=...) مع build_rollout_context.


استراتيجيات

اختر استراتيجية باستخدام --strategy.type=<name>. تُعرّف كل استراتيجية حلقة تحكم مختلفة لها دلالاتها الخاصة للتسجيل والتفاعل.

الأساسية ( --strategy.type=base )

تنفيذ سياسة ذاتية دون تسجيل بيانات. استخدم هذا للتحليل السريع أو العروض التوضيحية أو عندما تحتاج فقط إلى مراقبة الروبوت.

lerobot-rollout \
    --strategy.type=base \
    --policy.path=${HF_USER}/my_policy \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
    --task="Put lego brick into the box" \
    --duration=60
علمالوصفافتراضي
--durationزمن التشغيل بالثواني (0 = لا نهائي)0
--taskوصف المهمة المُمرَّر إلى السياسة—
--display_dataبث الملاحظات/الإجراءات إلى Rerun للعرضfalse

Sentry ( --strategy.type=sentry )

تسجيل ذاتي مستمر مع رفع دوري إلى Hugging Face Hub. تُحسب حدود الحلقات تلقائيًا من دقة الكاميرا ومعدل الإطارات (FPS) بحيث تنتج كل حلقة محفوظة ملف فيديو كاملًا، مما يحافظ على كفاءة عمليات الرفع.

تستمر حالة السياسة (الحالة المخفية، طابور RTC) عبر حدود الحلقات: لا يُعاد ضبط الروبوت بين الحلقات.

lerobot-rollout \
    --strategy.type=sentry \
    --strategy.upload_every_n_episodes=5 \
    --policy.path=${HF_USER}/my_policy \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
    --dataset.repo_id=${HF_USER}/rollout_eval_data \
    --dataset.single_task="Put lego brick into the box" \
    --duration=3600
علمالوصفافتراضي
--strategy.upload_every_n_episodesدفع إلى Hub كل N حلقات5
--strategy.target_video_file_size_mbحجم ملف الفيديو المستهدف لتدوير الحلقاتauto
--dataset.repo_idمطلوب. مستودع Hub الخاص بالبيانات المسجلة—
--dataset.push_to_hubما إذا كان سيتم الدفع إلى Hub عند التفكيكtrue

تمييز ( --strategy.type=highlight )

التشغيل الذاتي مع تسجيل عند الطلب عبر مخزن حلقي محدود الذاكرة. يلتقط المخزن آخر N ثانية من بيانات القياس. اضغط على مفتاح الحفظ لتفريغ المخزن وبدء التسجيل المباشر؛ اضغط عليه مرة أخرى لحفظ الحلقة. مع وجود خادم غير متزامن، يوقف كل تبديل الاستدلال، ويبطل الحركة المجدولة/المقوّلة، ويطالب بالحفاظ المحلي المدعوم قبل التفريغ الحاسم أو الحفظ. تستأنف الدورة الصحية من التقاط جديد بعد ذلك.

lerobot-rollout \
    --strategy.type=highlight \
    --strategy.ring_buffer_seconds=30 \
    --strategy.save_key=s \
    --strategy.push_key=h \
    --policy.path=${HF_USER}/my_policy \
    --robot.type=koch_follower \
    --robot.port=/dev/ttyACM0 \
    --dataset.repo_id=${HF_USER}/rollout_highlight_data \
    --dataset.single_task="Pick up the red cube"

التحكم بلوحة المفاتيح:

المفتاحإجراء
s (قابل للتهيئة)بدء التسجيل (يفرّغ المخزن المؤقت) / إيقاف وحفظ الحلقة
h (قابل للتهيئة)دفع مجموعة البيانات إلى Hub
ESCإيقاف الجلسة
علمالوصف
--strategy.ring_buffer_secondsمدة التلقيمات المخزنة مؤقتًا (الافتراضي: 10)
--strategy.ring_buffer_max_memory_mbالحد الأقصى للذاكرة لمتخزين الحلقة (الافتراضي: 1024)
--strategy.save_keyالمفتاح لتبديل التسجيل (الافتراضي: s)
--strategy.push_keyالمفتاح للضغط على Hub (الافتراضي: h)

DAgger ( --strategy.type=dagger )

جمع البيانات بمشاركة الإنسان. يتناوب بين تنفيذ السياسة المستقلة والتدخل البشري عبر مشغّل عن بُعد. تُوسم إطارات التدخل بـintervention=True. يتطلب الأمر وجود مشغّل عن بُعد (--teleop.type).

راجع دليل جمع البيانات بمشاركة الإنسان للحصول على شرح مفصل خطوة بخطوة.

وضع التصحيحات فقط (الافتراضي): يتم تسجيل نوافذ التصحيح البشرية فقط. يصبح كل تصحيح حلقة واحدة.

lerobot-rollout \
    --strategy.type=dagger \
    --strategy.num_episodes=20 \
    --policy.path=outputs/pretrain/checkpoints/last/pretrained_model \
    --robot.type=bi_openarm_follower \
    --teleop.type=bi_openarm_mini \
    --dataset.repo_id=${HF_USER}/rollout_hil_data \
    --dataset.single_task="Fold the T-shirt"

وضع التسجيل المستمر (--strategy.record_autonomous=true): يتم تسجيل إطارات الاستقلالية والتصحيح مع تدوير الحلقات الزمني (نفس ما في Sentry).

lerobot-rollout \
    --strategy.type=dagger \
    --strategy.record_autonomous=true \
    --strategy.num_episodes=50 \
    --policy.path=${HF_USER}/my_policy \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --teleop.type=so101_leader \
    --teleop.port=/dev/ttyACM1 \
    --dataset.repo_id=${HF_USER}/rollout_dagger_data \
    --dataset.single_task="Grasp the block"

التحكم بلوحة المفاتيح Keyboard controls (جهاز الإدخال الافتراضي):

المفتاحإجراء
Spaceإيقاف مؤقت / استئناف تنفيذ السياسة
Tabبدء / إيقاف التصحيح البشري
Enterدفع مجموعة البيانات إلى Hub (وضع التصحيحات فقط)
ESCإيقاف الجلسة

يُؤمَّن أيضًا إدخال عبر دواسة القدم من خلال --strategy.input_device=pedal. اضبط أكواد الدواسة باستخدام أعلام --strategy.pedal.*.

عندما يدعم الروبوت وضع تثبيت موضع التمرير، يقوم الإيقاف المؤقت بتحديث آخر هدف موضع تم تطبيقه فعليًا بواسطة السائق، بما في ذلك قصّه (clipping) وهدف الماسك. قبل الأمر الأول، يوفر وضع مقاس ومُتحقق منه الهدف. يحافظ هذا على خطأ الموضع المُمرَّر بدلًا من تغيير الهدف إلى الوضع المقاس؛ حيث يمكن للروبوت أن يكمل استقراره نحو ذلك الهدف بينما يتوقف تقدم مسار السياسة. تحقق من سلوك الذراع المحمّلة والماسك على الروبوت الفعلي؛ فهذا التثبيت البرمجي لا يضمن الاحتفاظ بالقبضة أو عدم الحركة الفيزيائية.

علمالوصف
--strategy.num_episodesعدد حلقات التصحيح التي سيتم تسجيلها (الافتراضي: --dataset.num_episodes)
--strategy.record_autonomousسجّل الإطارات المستقلة أيضاً (الافتراضي: false)
--strategy.upload_every_n_episodesدفع إلى Hub كل N حلقات (الافتراضي: 5)
--strategy.input_deviceجهاز الإدخال: keyboard أو pedal (الافتراضي: keyboard)
--strategy.smooth_handoverتسليم السيطرة بسلاسة عند بدء الإيقاف/التصحيح (الافتراضي: true). عطّل هذا الخيار لتحكم يدوي بنمط القابض (clutch-style) يعيد المرجعية عند وضعية الروبوت الحالية عند التفعيل
--teleop.typeمطلوب. نوع المشغّل عن بُعد

الحلقات ( --strategy.type=episodic )

تسجيل موجه نحو الحلقات يعكس سلوك lerobot-record. يقوم النموذج (Policy) بتشغيل الروبوت في كل حلقة؛ ويمكن لمُشغِّل عن بُعد اختياري تشغيل الروبوت خلال مرحلة إعادة الضبط بين الحلقات.

lerobot-rollout \
    --strategy.type=episodic \
    --policy.path=${HF_USER}/my_policy \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --teleop.type=so100_leader \
    --teleop.port=/dev/ttyACM1 \
    --dataset.repo_id=${HF_USER}/rollout_eval_data \
    --dataset.num_episodes=20 \
    --dataset.episode_time_s=30 \
    --dataset.reset_time_s=10 \
    --dataset.single_task="Pick up the red cube"

تُعدّ Teleop اختيارية — إذا تمّ حذفها، فإنّ الروبوت يحافظ على موقعه خلال مرحلة إعادة الضبط.

التحكم بلوحة المفاتيح:

المفتاحإجراء
→ (يمين)إنهاء الحلقة الحالية مبكراً
← (يسار)تجاهل الحلقة وتسجيلها مرة أخرى
ESCإيقاف جلسة التسجيل
علمالوصف
--dataset.num_episodesعدد الحلقات التي سيتم تسجيلها
--dataset.episode_time_sمدة كل حلقة تسجيل بالثواني. الافتراضي هو --duration عندما يتم تعيين ذلك ولا يتم تعيين هذا
--dataset.reset_time_sمدة مرحلة إعادة الضبط بين الحلقات بالثواني
--teleop.typeاختياري. مشغّل عن بُعد لتوجيه الروبوت أثناء إعادة الضبط
--strategy.reset_to_initial_positionما إذا كان يجب إعادة ضبط الروبوت إلى موقعه الأولي بين الحلقات
--strategy.smooth_leader_to_follower_handoverما إذا كان سيتم تفعيل أو تعطيل سلوك التسليم السلس من القائد إلى التابع.
--strategy.smooth_handoverتسليم التحكم بسلاسة إلى التحكم عن بُعد عند بدء إعادة الضبط (الافتراضي: true). عطّل هذا الخيار لأنماط التحكم عن بُعد من نوع القابض التي تعيد المراجعة عند وضعية الروبوت الحالية عند التفعيل

استراتيجية خاصة بك

يقبل --strategy.type أي استراتيجية مسجلة في البيئة، وليس فقط المدمجة أعلاه. تتكون الاستراتيجية من صفحتين في حزمة قابلة للتثبيت عبر pip: إعداد مسجل على RolloutStrategyConfig، وفئة فرعية من RolloutStrategy تحمل الاسم نفسه دون لاحقة Config — وفق نفس اتفاقية SomethingConfig/Something الخاصة بـ الأجهزة المخصصة، وتُحل من وحدة الإعداد أو الحزمة.

from dataclasses import dataclass
from typing import ClassVar

from lerobot.rollout import RolloutContext, RolloutStrategy, RolloutStrategyConfig


@RolloutStrategyConfig.register_subclass("patrol")
@dataclass
class PatrolStrategyConfig(RolloutStrategyConfig):
    dataset_mode: ClassVar[str] = "required"  # the engine creates the dataset for you
    legs: int = 2  # becomes --strategy.legs


class PatrolStrategy(RolloutStrategy):
    def run(self, ctx: RolloutContext) -> None:
        ...  # the paced control loop: see the contract on RolloutStrategy.run

    def teardown(self, ctx: RolloutContext) -> None:
        ctx.data.dataset.finalize()
        self._teardown_hardware(ctx.hardware, ctx.runtime.cfg.return_to_initial_position)

يُعلن الإعداد ما يرتّبه المحرك نيابةً عن الاستراتيجية، لذا لا حاجة لأيّ شيء في LeRobot لمعرفة نوعه:

الإعلانالتأثير
dataset_mode"none" (الافتراضي) يرفض أعلام --dataset.*، بينما "optional" يسجّلها عند تقديمها، و"required" يجعل --dataset.repo_id إلزامياً
requires_teleopيجعل --teleop.type إلزاميًا
supports_interactiveيسمح بـ --interactive=true؛ ويجب على run() بعد ذلك الالتزام بعقد إعادة التشغيل الموثق في RolloutStrategy
supports_sim_robotيسمح بـ --robot.type=sim؛ ويجب أن يبدأ run() حلقة جديدة كلما انتهت حلقة (انظر lerobot.robots.sim_robot)
requires_streaming_encoding()أعد True عند كتابة الإطارات من داخل حلقة التحكم: يُفعَّل --dataset.streaming_encoding إجبارياً
extra_dataset_features()أعمدة مجموعة البيانات التي تملكها الاستراتيجية (مثل intervention في DAgger)؛ يجب أن تحمل كل إطار مسجّل هذه الأعمدة

سمِّ التوزيع lerobot_strategy_<name> وسيقوم lerobot-rollout باستيراد الحزمة قبل تحليل سطر الأوامر — حيث يُنفَّذ __init__.py فقط، لذا استورد الإعداد هناك. أما أي حزمة تحمل اسمًا آخر فتُحمَّل، بما في ذلك وحداتها الفرعية، عبر --strategy.discover_packages_path=<package>. وتتحول حقول dataclass الخاصّة بالاستراتيجية إلى أعلام --strategy.*:

lerobot-rollout \
    --strategy.type=patrol \
    --strategy.legs=3 \
    --policy.path=${HF_USER}/my_policy \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --dataset.repo_id=${HF_USER}/rollout_patrol \
    --dataset.single_task="patrol the aisle"

SentryStrategy (تسجيل، آمن تفاعليًا) وBaseStrategy (بدون تسجيل) هما التنفيذان المرجعيان للنسخ منهما؛ وsend_next_action وsafe_push_to_hub وestimate_max_episode_seconds من lerobot.rollout.strategies هي الأدوات المساعدة التي تُبنى عليها.

في حالة الخوادم غير المتزامنة، يكون عقد الإرسال إلزاميًا. انشر كل ملاحظة تم التقاطها باستخدام engine.notify_observation(obs_processed)، ثم استدعِ send_next_action(...) في كل نبضة محرك ذاتية، بما في ذلك نبضات الاستيفاء والنبضات الممسوكة، ثم استدعِ engine.pump_query(obs_processed). الاستدعاء الوحيد لـ engine.get_action() يتجاوز مصافحة الإذن والاحتفاظ: فقد تنتظر استعلام نصي مخطط له إلى ما لا نهاية، وقد لا يُصدر عطل نهائي إشارة الإيقاف أبدًا.

يمكن لاستراتيجيات الأطراف الثالثة استدعاء self._tick(timer, new_cycle=interpolator.needs_new_action()) بدلاً من timer.tick(...) لتضمين تقارير الصحة الدورية بعد _init_engine(ctx).

send_next_action مبني على lerobot.inference.dispatch_tick ومكوناته (next_interpolated_action، commit_action، dispatch_permitted)، والتي ترمّز ذلك الترتيب مرة واحدة: dispatch_allowed() قبل وبعد سحب الإجراء، ثم مرة أخرى قبل الإرسال، وإبطال الاستيفاء مع دعم الاحتفاظ المحلي وacknowledge_hold() عند الرفض، وrecord_dispatch() بعد الإرسال. لا يتم أبدًا تأكيد الاحتفاظ الذي يفشل. استخدم تلك الأدوات المساعدة بدلاً من إعادة تنفيذ التسلسل؛ send_next_action يضيف فقط إطار مجموعة البيانات ومعالج الإجراء على جانب الروبوت وحساب الإيقاع. في السياقات عن بُعد، تكون ctx.policy.policy وpreprocessor وpostprocessor مضبوطة على None؛ استخدم ctx.policy.inference وخطوط الأنابيب على جانب الروبوت في ctx.processors.

قم بتغليف أعمال التسجيل المعروفة بأنها محظورة أثناء التشغيل داخل self._pause_for_recording(ctx)، بما في ذلك تفريغ مخزن الحلقة (ring-buffer) وإتمام الحلقات (episodes). يؤدي هذا إلى إبطال الحركة غير المتزامنة قبل توقف التسجيل، ولا يُستأنف إلا إذا كان التشغيل لا يزال سليمًا ونشطًا. يجب على الاستراتيجيات ذات المراحل التي يتحكم فيها المشغّل تمرير إذن الحركة الحالي الخاص بها كـ resume_allowed. يجب أن يأتي الإجراء التالي من ملاحظة جديدة؛ فلا يجوز أن تُحيي الأعمال المحفوظة تشغيلًا متوقفًا مؤقتًا أو متوقفًا أو معطوبًا.


تصوّر تنبؤات السياسة

مع --display_data، يعرض العارض أيضاً ما تتنبأ به السياسة إلى جانب الإجراءات: إطارات الكاميرا المتخيَّلة لنموذج العالم، مهمة فرعية متنبأ بها، وصناديق تحديد مرسومة فوق كاميرا. تقرر كل سياسة ما تتنبأ به وتفعّله عبر إعداداتها الخاصة، على سبيل المثال --policy.return_predicted_video=true لـ LingBot-VA. يُسمّى التنبؤ باسم ما يتنبأ به: يعرض Rerun تنبؤاً بـ observation.images.top على أنه prediction.images.top، ومهمة فرعية متنبأ بها على أنها prediction.subtask، والصناديق تحت كاميرتها (<camera>/prediction)؛ بينما ينشر Foxglove هذه التنبؤات على مواضيع /prediction/... وتعليقات الصور <camera topic>/prediction. مع RTC، يتم تحديث التنبؤ مرة واحدة لكل شريحة. راجع Bring your own policy لإرجاع تنبؤ من سياسة.

واجهات الاستدلال

اختر وحدة الخلفية باستخدام --inference.type=<name>. يستخدم الاستدلال المحلي المتزامن والاستدلال عبر RTC السياسة المُهيأة أدناه. تحصل وحدة الخلفية عن بُعد على عقد سياستها من الخادم ولا تُحمّل الأوزان على حاسوب الروبوت.

المزامنة (افتراضي)

استدعاء واحد للسياسة لكل نبضة تحكم. يحجب الحلقة الرئيسية حتى يتم حساب الإجراء.

يعمل مع جميع السياسات. لا حاجة إلى أي أعلام إضافية.

التقطيع في الوقت الفعلي ( --inference.type=rtc )

ينتج خيط في الخلفية مقاطع من الإجراءات بشكل غير متزامن. يستطلع حلقة التحكم الرئيسية الإجراء التالي الجاهز بينما يحسب النموذج المقطع التالي بالتوازي.

استخدم RTC مع نماذج VLA المتوافقة (Pi0, Pi0.5, SmolVLA) لتداخل الاستدلال والحركة. لا يزال التنفيذ المستمر يتطلب كمية كافية من تشغيل الإجراءات القابلة للاستخدام لتغطية زمن تأخير الاستدلال وتباينه.

lerobot-rollout \
    --strategy.type=base \
    --inference.type=rtc \
    --inference.rtc.execution_horizon=10 \
    --inference.rtc.max_guidance_weight=10.0 \
    --policy.path=${HF_USER}/pi0_policy \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
    --task="Pick up the cube" \
    --duration=60 \
    --device=cuda
علمالوصف
--inference.rtc.execution_horizonالخطوات للدمج مع الجزء السابق (الافتراضي: يختلف حسب السياسة)
--inference.rtc.modeguided (افتراضي) أو بادئة مدرّبة trained لنقاط التفتيش Pi05 المتوافقة
--inference.rtc.max_guidance_weightقوة فرض الاتساق (الافتراضي: يختلف حسب السياسة)
--inference.rtc.prefix_attention_scheduleجدول المزج: LINEAR، EXP، ONES، ZEROS
--inference.queue_thresholdحدّ ضغط الرجوع؛ يتطلب تدريب RTC على الأقل تأخيره الأقصى
--inference.action_starvation_grace_sانتظر حركة جديدة بعد الجوع على روبوت مدعوم (الافتراضي 1.0؛ 0 يعطي خطأ فورياً)

راجع دليل التقطيع في الوقت الفعلي لمعرفة التفاصيل حول ضبط معاملات RTC.

يعمل RTC المحلي في خيط خلفية ضمن عملية النشر، دون استخدام النقل. أما الخادم والعميل على نفس الحاسوب فيستخدمان --inference.type=remote بدلاً من ذلك. راجع دليل البُعد لمحاذاة/مزج المقاطع، وسلوك الانتظار المشترك بين الخوادم الخلفية غير المتزامنة.

يتطلب الانتظار روبوتًا مدعومًا. تظل تقنية RTC المحلية العادية متاحة دون هذه الإمكانية، لكن فترات التوقف المخططة لتغيير النص/التعليمات ونقص التغذية القابل للاسترداد تتطلبها. تدعم متابعات SO وOMX وKoch وHopeJr وRebot التي تتحكم في الموضع هذه الإمكانية؛ بينما تفرض OpenArm وReachy2 وغلافات التحكم الثنائي قيودًا على التهيئة مدرجة في جدول دعم الروبوتات. عند توفر الدعم، يمكن لخزان فارغ أن يحتفظ بالهدف المطبق الأخير لمدة action_starvation_grace_s (الافتراضي 1 ثانية)، بما في ذلك الوقت اللازم لتصريف الاستدلال القديم والتنبؤ من التقاط جديد. بعد بدء الحركة، يؤدي انعدام المهلة أو استخدام روبوت غير مدعوم إلى حدوث عطل فوري عند الاستنفاد؛ ولبدء التشغيل مهلة خاصة به. على عكس مسار RTC المحلي السابق، لم يعد الاستنفاد يعني تخطي دورة بشكل غير محدود. لا تمدد المهلة أبدًا حدود الطلبات المنتهية أو حدود حداثة البيانات.

تُعرّض RTC المحلية هذه الميزانيات الإضافية من خلال --inference.:

معاملافتراضيالمعنى
max_observation_age_s5 sأقصى عمر للمصدر عبر تنفيذ الإجراء
action_timeout_s10 sطلب إجراء معلق
startup_timeout_s120 sالتحضير الأولي وبدء التشغيل الجديد
language_timeout_s120 sعملية لغة مخطط لها

هذه قيم ابتدائية وليست ضمانات مقيسة للأجهزة. يجب أن يحتفظ RTC بما يكفي من تشغيل ما بعد الضبط لاستدلال آخر وهامش زمني. لا يمكن لرفع queue_threshold أن يساعد إذا كان الاستدلال يستهلك بشكل روتيني أفق التنبؤ القابل للاستخدام؛ قلّل زمن الاستجابة أو تحقق من أفق أطول/تكرار إجراء مختلف.

لا تستأنف عطل الطرفية حركة السياسة تلقائيًا أبدًا. مع الحصول على ملاحظات قابلة للاستخدام والتحكم في المشغلات، يحترم الإيقاف --return_to_initial_position (الافتراضي: true) ويقوم بفصل الاتصال. تتضمن عملية العودة قراءة ملاحظة كاملة، لذا يمكن لفشل الكاميرا المستمر أن يمنعها. يؤدي فشل تطبيق الأمر إلى كبح حركة الإيقاف اللاحقة لجميع الخلفيات، بما في ذلك المتزامنة. لا يغيّر هذا التنبؤ المتزامن أو يُدخل استردادًا محددًا للكاميرا.

Compilation and instruction changes

يُسخّن تجميع RTC كلًا من الاستدعاءات الأولية والمُسبقة، بما في ذلك تأخير غير صفري تمثيلي، قبل الحركة. على الرغم من أن --compile_warmup_inferences يُساوي افتراضيًا 2، فإن تفعيل RTC يتطلب 3 على الأقل؛ وتُبلّغ سجلات الإقلاع عن العدد الفعّال. يجب أن يتناسب الإحماء مع startup_timeout_s. قد تُحفّز التعليمات اللاحقة التي تُغيّر أشكال المصفوفات إعادة التجميع وتتجاوز مهلة التشغيل أو مهلة العملية.

تؤدي تغيير المهمة أثناء الاستدلال إلى التخلص من النتيجة القديمة. تتوقف الروبوتات المدعومة وتطلب إجراءات جديدة؛ وبدون تلك القدرة على الانتظار، قد تنفد الإجراءات المتبقية. يُفضَّل تغيير المهام بين الجولات على تلك الروبوتات.


جلسات تفاعلية

أضف --interactive=true للتحكم في التنفيذ من الطرفية بدلاً من البدء فوراً. يتم توصيل العتاد وتحميل السياسة كما هو معتاد، لكن يبقى الروبوت ساكناً حتى تكتب /start — وهو مفيد عندما تريد تموضع المشهد أولاً، أو إعادة تعليمات السياسة بين المحاولات، أو تنفيذ عدة جولات دون دفع تكلفة التحميل مرة أخرى.

lerobot-rollout \
    --strategy.type=base \
    --policy.path=${HF_USER}/my_smolvla_policy \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --robot.cameras="{ front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
    --task="pick up the cube" \
    --interactive=true
أمرإجراء
/startابدأ (أو أعد تشغيل) حلقة التحكم في السياسة
/subtask <text>غيّر التعليمات ضمن التشغيل الحالي؛ قد يدخل الاستدلال غير المتزامن في فترة توقف مخطط لها. لا يُطبع أي حجة المهمة الحالية. يؤثر فقط على السياسات التي تشترط على اللغة (SmolVLA، π0/π0.5، وما شابه). عند استخدام مخطط خارجي، يُعيد /subtask أيضًا التحكم من القيادة الذاتية
/vqa <text>اطرح سؤالاً حول ما يراه الروبوت حاليًا. فقط أثناء تقدم تشغيل، وفقط مع رأس نصي للسياسة أو مخطط خارجي
/autosteer <goal>قدّم هدفًا عالي المستوى ودع رأس النص في السياسة أو المخطط الخارجي يختار المهام الفرعية. الأمر /autosteer off يعيد التحكم؛ ولا يُبلَّغ عن الهدف الحالي عند عدم تقديم أي حجة
/resetتوقف الحركة، أعد الروبوت إلى موضعه عند بدء التشغيل، واستعد تعليمات --task
/stopأنهِ الجلسة وشغّل روتينات الإيقاف الاعتيادية
/helpThe input is a single short phrase without any markup tags. I will translate it directly into natural Modern Standard Arabic. قائمة بالأوامر
> /start
Rollout running — task 'pick up the cube'. /subtask <text> to change it, ...
> /subtask put the cube in the box
Task: 'pick up the cube' → 'put the cube in the box' (applies from the next policy inference)
> /vqa is the cube inside the box?
Asked: 'is the cube inside the box?' — answering from the next observation...
Q: is the cube inside the box?
A: No — the cube is on the table to the left of the box.
> /reset
Task restored to 'pick up the cube'
Resetting — returning the robot to its initial position...
Robot reset — holding at initial position. /start to run.
> /stop

الأسطر التي تبدأ بـ> هي ما تكتبه؛ لا يعرض البرنامج أي موجه خاص به.

Ctrl-C لا يزال يُنهي التشغيل كما هو معتاد، وإغلاق مدخل البيانات القياسي (Ctrl-D، أو نهاية سكربت مُوجَّه عبر أنبوب) يُنهي الجلسة — لذا يجب على سكربت مُوجَّه عبر أنبوب إبقاء مدخل البيانات القياسي مفتوحاً طوال المدة المقصودة:

(printf '/start\n'; sleep 60; printf '/stop\n') | lerobot-rollout ... --interactive=true

/subtask يحدّث المهمة للاستدلال اللاحق. عند استخدام --inference.type=sync، تُهمل إجراءات الأجزاء المحسوبة مسبقًا. مع RTC المحلي أو الاستدلال عن بُعد، يؤدي التغيير أثناء طلب إجراء إلى التخلص من النتيجة القديمة. على روبوت يدعم الاحتفاظ المحلي، يلغي المحرك الحركة المجدولة/المقوّلة، وينتظر حتى يعترف حلقة التحكم بالاحتفاظ، ثم يطلب حركة جديدة تحت المهمة الجديدة. توقّف توقّف أثناء هذا الانتقال؛ فهو ليس مزجًا مستمرًا مضمونًا. يمكن للتغيير بين الطلبات أن يحتفظ بالإجراءات المقبولة بالفعل من أجل الاستمرارية. ما زال RTC المحلي على روبوت لا يدعم الاحتفاظ يتخلص من النتيجة القديمة، لكنه قد يستنفد إجراءاته المتبقية وينتهي. غيّر التعليمات بين التشغيلات إذا كان ذلك الروبوت غير قادر على الاحتفاظ بشكل مناسب.

عند استخدام --use_torch_compile=true محليًا، يمكن لتعليمات تغيير أشكال المصفوفات المعالجة أن تُطلق إعادة تجميع. قد يحافظ الحشو على بعض تغييرات المهام بنفس الشكل، لكن لا يُضمن أن تتوافق عمليات التجميع اللاحقة مع البث المتبقي أو مع مهلة تغيير التعليمات: فقد تسبب عطلًا نهائيًا. اترك التجميع معطلاً أثناء استكشاف التعليمات ما لم تكن تلك الانتقالات قد تم التحقق منها. التغييرات التي تحدث أثناء فترة الإحماء للتجميع الأولي لا تطلب إيقاف الحركة، لأن حركة السياسة لم تبدأ بعد.

يتطلب /vqa و/autosteer سياسة تُعلن عن دعم توليد النص وتنفذ PreTrainedPolicy.generate_text()، مثل نقطة تحقق EO1 مدربة بشكل مناسب، أو مخطط خارجي. يتم التحقق من القدرة قبل قبول الاستعلام؛ ولا يزال سلوك نقطة التحقق المحدد بحاجة إلى التحقق منه.

يجيب /vqa عن الأسئلة بناءً على الملاحظة التالية ويُظهر النتيجة عند جاهزيتها، مما يتيح لك مواصلة الكتابة في الأثناء؛ حيث لا يكون هناك سؤال واحد قيد التنفيذ في أي وقت (تشارك استعلامات autosteer الخاصة بها ذلك الخانة). عند استخدام مخطط خارجي، يُجاب عن السؤال في خيط عامل بينما يستمر الروبوت في اتخاذ الإجراءات، ولا ينطبق أي مما يلي. تدخل الخلفيات غير المتزامنة أولاً في حالة انتظار محلية معترف بها وتُبطل الحركة المصفوفة/المقترنة، ثم تُرسل ملاحظة جديدة إلى مسار النص. تستأنف عملية نشطة سليمة من مقطع إجراء جديد بعد الإجابة؛ بينما تبقى العمليات الموقوفة أو المتوقفة غير نشطة. يعمل توليد النص المتزامن بشكل مباشر على خيط التحكم ويتخلص من الإجراءات المحسوبة مسبقًا للسياسة، لذا يستأنف التيك التالي من استدلال جديد. يُحتسب وقت الاستعلام ضمن --duration. تُقبل الأسئلة فقط أثناء تقدم عملية — فالمحرك الخامل لا يملك عرضًا حاليًا. إذا ألغى التعليم أو سياق التنفيذ إجابة غير متزامنة، يتلقى السؤال إشعار إلغاء واحد بدلاً من الإجابة القديمة. يبلغ نهاية المقطع أيضًا عن الأسئلة غير المُجابة، بما في ذلك التوليد الذي لا يزال قيد التنفيذ؛ ولا يُسبب الإبلاغ عن إلغاء مقاطعة استدعاء نموذج قيد التشغيل أو تحرير خانة الاستعلام الخاصة به مبكرًا.

يُسلّم /autosteer السياسة هدفًا ويطلب منها المهام الفرعية التالية كل --autosteer_interval_s ثانية (الافتراضي 10)، مطبّقًا كل مهمة عبر المسار نفسه الخاص بـ/subtask ومُعلِنًا عنها في الدردشة. كل استعلام هو توليد نص كامل، لذا فإن الفاصل الزمني هو مِفتاح تكلفة: القيم الأدنى تعيد التخطيط مبكرًا لكنها تُنفق المزيد من حلقة العمل على توليد النص بدلًا من التنفيذ. تقدم الخطة موجود في السياسة وليس في التنفيذ، لذا فإن الخطة تموت مع المقطع؛ كما يتوقف المُسلسل أيضًا عند /reset، و/subtask، و/autosteer off، وأول فشل في التخطيط.

تُكتم السجلات الأدنى من مستوى ERROR أثناء تشغيل الجلسة حتى لا تتداخل المخرجات الروتينية مع ما تكتبه؛ لا تزال الأخطاء وأعطال الاستدلال القاتلة تظهر، وتعود السجلات العادية عند انتهاء الجلسة. تُطبع ملخصات الإيقاع في الدردشة بدلاً من ذلك، وتشغيل الأمر دون --interactive يعيد إليك السجل المباشر.

تعمل الجلسات عبر SSH وعلى الأجهزة التي لا تحتوي على واجهة رسومية — لا حاجة إلى خادم عرض.

التسجيل أثناء التفاعل. يقبل --strategy.type=sentry أيضًا --interactive=true ويسجّل بشكل مستمر أثناء توجيهك: يحفظ كل مقطع /start…/reset حلقات كاملة بالإضافة إلى حلقة جزئية نهائية واحدة، وتبقى مجموعة البيانات مفتوحة حتى الإيقاف. تحمل الإطارات أصل المهمة للإجراء المُرسَل فعليًا، لذا يحتفظ الإجراءات المُجمّعة مسبقًا أو المُستوفَلة تحت المهمة القديمة بالتسمية القديمة.

توقف حفظ الحلقات أثناء التشغيل يوقف الاستدلال غير المتزامن، ويُبطِل الإجراءات المُجمَّعة/المُستوفَلة، ويطالب بحالة إيقاف محلية مدعومة. تستأنف هذه العمليات من التقاط جديد فقط إذا بقي التشغيل نشطًا وسليمًا. تنطبق الحماية نفسها على عمليات حفظ DAgger وتصريف/حفظ مخزن الحلقة الدائرية (ring-buffer) الخاص بـ Highlight. يتشارك إيقاف التسجيل والجوع العادي سلوك الانتظار الفيزيائي، لكن آجالهما النهائية وأسباب استئنافهما تبقى منفصلة.

lerobot-rollout \
    --strategy.type=sentry \
    --policy.path=${HF_USER}/my_smolvla_policy \
    --robot.type=so100_follower \
    --robot.port=/dev/ttyACM0 \
    --dataset.repo_id=${HF_USER}/rollout_cube_sessions \
    --task="pick up the cube" \
    --interactive=true

لا تُدعم استراتيجيات التسجيل الأخرى (الحلقي، DAgger، أبرز اللحظات): فهي تربط أزرار لوحة المفاتيح الخاصة بها وتُنهِي مجموعة البيانات عند خروج run()، لذا لا يمكن إعادة تشغيلها مقطعاً بمقطع.

مخطط خارجي

يوجّه --planner.model_id=<name> الطلبات إلى /vqa و/autosteer عبر عميل VLM الخاص بخط أنابيب التسمية (إضافة annotations) بدلاً من رأس النص الخاص بسياسة اتخاذ القرار. تُنفَّذ الاستدعاءات في خيط عامل بينما يستمر الروبوت في اتخاذ الإجراءات، ولا يُطلب أي احتجاز لغوي لها، مع استثناء مقصود واحد: عند بدء /autosteer، يُوقف الخلفية الاستدلالية حتى أول رد من المخطط، لأن الهدف هو سياق للمخطط وليس تعليمات للسياسة. تتخلّى الخلفيات غير المتزامنة (rtc، remote) عن الإجراءات المُجمَّعة مسبقاً أو قيد الحساب للتعليمات السابقة؛ بينما تحتجز الخلفية المتزامنة الروبوت. بمجرد تطبيق أول مهمة فرعية، تستأنف الخلفية العمل من ملاحظة جديدة. لا يزال /subtask يطبّق تعليماتك مباشرةً ويلغي التخطيط التلقائي؛ ولا يمكن للردود المتأخرة من المخطط تجاوز ذلك.

يعمل المخطط مع كل واجهة خلفية للاستدلال. عند الاستدلال المحلي، يعيد استخدام وصف مهمة فرعية للمعالج المحمّل إذا كان موجودًا، وإلا يطلب تعليمات قصيرة؛ وهذا لا يثبت أن نقطة التفتيش قادرة على اتباعها. يقيّد --planner.instructions='["pick up the cup","open the drawer"]' إخراج المخطط: يُطلب من نموذج اللغة البصرية اختيار أحد هذه النصوص، ويُعدّ ردّ مهمة فرعية تالية خارج القائمة خطأً. يتم تجاهل حالة الأحرف والمسافات الإضافية والنقطة في نهاية الجملة، ويُرسَل صياغة القائمة نفسها إلى السياسة. بدون هذا العلم، تُقرأ القائمة من تسميات المهام في مجموعة بيانات التدريب الخاصة بنقطة التفتيش (عبر train_config.json). تدخل كل تسمية في الموجه، لذا مرّر العلم بقائمة أقصر لمجموعات البيانات التي تحتوي على مهام كثيرة. إذا تعذّرت قراءة مجموعة البيانات، يُسجَّل تحذير ويبقى إخراج المخطط حرّ الصياغة. الاستدلال عن بُعد يملك السياسة، لذا لا يتوفر وصف المهمة الفرعية ولا مفردات التدريب محليًا: مرّر --planner.instructions صراحةً وإلا بقيت الإجابات حرّة الصياغة. تم اختبار المخطط على أجهزة مع الاستدلال المحلي فقط.

يستقبل المخطط الخارجي آخر أزواج الملاحظة/الأمر --planner.history (الافتراضي 4)، تليها الصور الحالية. يحتوي كل زوج على الملاحظة المستخدمة لطلب تعليمات والأمر الذي قبله المحرك لاحقًا؛ ولا يعني القبول نجاح التنفيذ. تبقى التعليمات المتكررة في السجل حتى يتمكن نموذج اللغة البصرية (VLM) من تقييم غياب التقدم. يتم مسح السجل عند الاستيلاء اليدوي، أو إعادة الضبط، أو التوقف، أو نهاية المقطع، أو هدف جديد للتوجيه الذاتي. اضبط --planner.history=0 لتعطيله. يمكن لأمر /vqa فحص هذا السجل لكنه لا يضيف إدخالات. لطلب مهمة فرعية تالية، يجب على نموذج اللغة البصرية أولاً وصف المشهد وتحديد ما إذا كان الأمر السابق مكتملًا أو قيد التنفيذ أو فاشلًا، ثم فقط تسمية التعليمات التالية. تعني الإجابة done اكتمال الهدف: يتوقف التوجيه الذاتي، وينتهي التشغيل، ويبقى الروبوت في وضعه حتى /reset أو /start. يتم تجاهل أي done متأخر من قبل /subtask أو /reset أو هدف جديد. يتم طباعة كل مهمة فرعية مطبقة مع تقييم المشهد من النموذج وزمن استجابة الطلب.

ابدأ خادم VLM متوافقًا مع OpenAI بشكل منفصل، ثم اربط به:

transformers serve Qwen/Qwen3-VL-8B-Instruct --port 8000
# Alternatively: vllm serve Qwen/Qwen3-VL-8B-Instruct --port 8000
lerobot-rollout ... --task="pick up the cup" --interactive=true \
    --planner.model_id=Qwen/Qwen3-VL-8B-Instruct \
    --planner.api_base=http://localhost:8000/v1
> /start
> /vqa What is the next short instruction to clear the table?
> /subtask put the cup in the sink
> /autosteer clear the table

يعمل النموذج المستضاف بالطريقة نفسها. يستخدم هذا المثال مزوّدي الاستدلال من Hugging Face، مع رمز وصول يحمل صلاحية “إجراء مكالمات إلى مزوّدي الاستدلال”:

export HF_TOKEN=hf_...
lerobot-rollout ... --task="put all colored cubes in the green bin" --interactive=true \
    --planner.model_id=Qwen/Qwen3.8-27B:novita \
    --planner.api_base=https://huggingface.co/static-proxy/router.huggingface.co/v1 \
    --planner.api_key_env=HF_TOKEN

/vqa يُبلّغ بإجابة فقط؛ بينما /autosteer يطبّق التعليمات. اضبط نقطة النهاية باستخدام --planner.api_base، والمفتاح باستخدام --planner.api_key_env=<variable> (المفضّل، إذ يبقى المفتاح خارج الأوامر والسجلات) أو --planner.api_key. تحدّد --planner.request_timeout_s (الافتراضي 600) و--planner.request_max_retries (الافتراضي 2) حدود كل طلب؛ ويختار --planner.camera_key كاميرا واحدة؛ ويضيف --planner.log_path كل تبادل كسطر JSON واحد. تنتمي تبعيات تقديم النموذج إلى بيئة الخادم. يقيس --autosteer_interval_s زمن حركة الروبوت بعد تطبيق الرد، بالإضافة إلى زمن استجابة الطلب. يقع التوجيه متعدد المستويات وجرد المشهد التلقائي خارج نطاق هذا المكيّف.

التحكم البرمجي

يكشف RolloutController عن نفس العمليات التي يوفرها واجهة برمجة التطبيقات المكتبة — عمليات start() / reset() / stop() / set_task() آمنة من حيث الخيوط بالإضافة إلى استدعاء RolloutEvent، دون أي إدخال قياسي أو طباعة أو كتم للسجلات:

from threading import Event, Thread

from lerobot.rollout import (
    LinkedEvent,
    RolloutController,
    RolloutEvent,
    build_rollout_context,
    create_strategy,
)

parent = Event()  # your application's shutdown signal
ctx = build_rollout_context(cfg, LinkedEvent(parent))  # loads policy, connects robot
strategy = create_strategy(cfg.strategy)
strategy.setup(ctx)

controller = RolloutController(strategy, ctx, on_event=print)  # or your own observer
serve_thread = Thread(target=controller.serve)  # serve() blocks; run it where you like
serve_thread.start()

controller.start()                        # robot starts executing the policy
controller.set_task("grab the red cube")  # re-instruct mid-run
controller.reset()                        # stop movement, return home, stay warm
controller.stop()                         # end serve()

serve_thread.join()
strategy.teardown(ctx)  # teardown stays with the caller

يتطلب RolloutController أن يكون حدث الإيقاف في السياق من نوع LinkedEvent، كما تم بناؤه أعلاه: حيث ينهي المتحكم مقاطع التشغيل عبر علامته المحلية، بينما لا يزال حدث parent الخاص بك يفرض إيقافًا كاملًا. اضبط play_sounds=False ما لم ترغب في الإعلانات الصوتية.


أعلام شائعة

علمالوصفافتراضي
--policy.pathمطلوب. معرف نموذج HF Hub أو مسار نقطة التفتيش المحلية—
--robot.typeمطلوب. نوع الروبوت (مثل so100_follower، koch_follower)—
--robot.portالمنفذ التسلسلي للروبوت—
--robot.camerasإعدادات الكاميرا (قائمة JSON)—
--fpsتكرير الاستدلال على السياسة وتسجيل مجموعة البيانات30
--status_interval_sالثواني بين سجلات الحالة (0 لتعطيلها؛ غير تفاعلي فقط)5
--durationزمن التشغيل بالثواني (0 = لا نهائي؛ لكل مقطع إذا كان تفاعليًا)0
--deviceجهاز Torch (cpu، cuda، mps)auto
--taskوصف المهمة (يُستخدم عند عدم توفير مجموعة بيانات)—
--display_dataبث بيانات التلميتري إلى عرض Rerunfalse
--display_ip / --display_portعنوان خادم إعادة التشغيل عن بُعد—
--interpolation_multiplierأوامر الروبوت لكل إجراء في السياسة (التحكم عند fps × N هرتز)1
--interactiveجلسة دردشة عبر stdin؛ يبقى الروبوت في وضع الخمول حتى /start (base, sentry)false
--use_torch_compileتفعيل torch.compile للاستدلالfalse
--resumeاستئناف جلسة تسجيل سابقةfalse
--play_soundsتوليد الصوت للأحداثtrue

تقارير Cadence

يسجّل التمرين غير التفاعلي حالته كل خمس ثوانٍ. غيّر الفترة باستخدام --status_interval_s=10، أو عطّلها باستخدام --status_interval_s=0.

Rollout: loop 29.7/30 Hz · over budget 2/149 · starved 0 · infer 18.7 ms (worst 40.1) · process 2.41 GiB · GPU 5.12/79.6 GiB

تُمثّل زمن الاستجابة القيمة الوسطى/الأسوأ خلال الفترة (turnaround لـ RTC/البعيد). تُستبعد الحقول غير المتوفرة، وذاكرة وحدة المعالجة الرسومية تشمل الجهاز بالكامل، بينما الذاكرة البعيدة محلية. يتوقف الإبلاغ عندما يحجب الحلقة.

تُبلّغ كل استراتيجية عما حقّقته حلقة التحكم الفعلية، وكذلك تفعل lerobot-record وlerobot-teleoperate وlerobot-replay — إذ تتقدّم جميعها وفق المؤقّت نفسه. يحصل كل حلقة محفوظة على ملخّص من سطر واحد، وعند انتهاء الحلقة — بما في ذلك عند Ctrl-C — يظهر كتلة تغطي كامل التشغيل:

Cadence (episode 1): 29.84 Hz policy vs 30 Hz target · 1200 ticks, 20.1 s measured · 6/598 cycles over the 33.3 ms budget (work mean 18.7 ms, worst 48.1 ms)
Cadence (episode 2): 29.84 Hz policy vs 30 Hz target · 1200 ticks, 20.1 s measured · 6/599 cycles over the 33.3 ms budget (work mean 18.7 ms, worst 48.1 ms)
Cadence summary — whole run, 2 episodes · target 30 Hz × 2 (16.7 ms tick slot, 33.3 ms cycle budget): 2400 ticks, 1197 cycles judged
  effective cadence: 29.84 Hz policy / 59.67 Hz commands over 40.2 s measured
  cycles over the 33.3 ms work budget: 12/1197 (1.0%) — work mean 18.7 ms, worst 48.1 ms
  ticks over their 16.7 ms slot: 40/2400 (costs interpolation smoothness only)
  loop-body steps (share of measured work):
    observe      mean   3.13 ms · worst   9.00 ms ·  31.7% of work · 2400 calls
    process_obs  mean   0.50 ms · worst   1.00 ms ·   5.1% of work · 2400 calls
    infer        mean   5.18 ms · worst  40.00 ms ·  52.4% of work · 2400 calls
    send         mean   0.40 ms · worst   0.40 ms ·   4.1% of work · 2400 calls
    record       mean   0.67 ms · worst 620.00 ms ·   6.8% of work · 2402 calls
  pacing headroom: 7.4 ms slept per tick on average (max 13.0 ms) — near zero means the loop is saturated

اقرأها من الأعلى إلى الأسفل: الإيقاع الفعّال هو ما حصلت عليه مقابل --fps، والدورات التي تجاوزت الميزانية هو مدى تكرار تعذّر حلقة التشغيل على الحفاظ عليه، وتفصيل الخطوة يوضح أين ذهبت المدة الزمنية، وهامش التوقيت القريب من الصفر يعني أنه لا يوجد ما يمتص التأخير الطفيف. نسبة عالية من infer تشير إلى السياسة أو الجهاز؛ ونسبة عالية من observe تشير إلى الكاميرات. أن تكون worst لخطوة ما أعلى بكثير من mean الخاص بها تعني أنها حالة استثنائية — أعلاه، record هو 0.67 مللي ثانية لكل إطار، والقيمة الشاذة البالغة 620 مللي ثانية هي save_episode الحاصلة على الحجب التي أغلقت الحلقة.

يُعدّ دورة هنا ما يعادل إجراء سياسة واحد من الإطارات (--interpolation_multiplier منها). لا يمكن أن تُكلّفك إطارات إلا الدورات الكاملة ضمن ميزانية 1/fps؛ فإطار واحد يتجاوز حصته يجعل الحركة المُستوفاة أقل سلاسة، ولهذا السبب يُحتسب كلاهما بشكل منفصل. في غياب الاستيفاء، تكون الدورة إطارًا واحدًا، لذا يتخلّى التقرير عن هذا التمييز ويحتسب الإطارات على مدار التقرير.

في الجلسات التفاعلية، يملك كل مقطع /start مؤقتًا خاصًا به، لذا يصل التقرير إلى المحادثة مرة واحدة لكل مقطع (/reset، /stop، أو --duration) بدلاً من مرة واحدة لكل عملية.


الاستخدام البرمجي

بالنسبة إلى الامتدادات، lerobot.inference هو الحزمة العامة لإعدادات الخلفية والمحركات المحلية وعقود الجدولة المشتركة. تمتلك lerobot.remote_inference المحرك البعيد والبروتوكول والنشر وتنفيذ الجلسة؛ تمتلك lerobot.rollout حلقة الروبوت والاستراتيجيات والاستيفاء والتسجيل. استورد الرموز العامة من حزمها بدلاً من ملفات التنفيذ. لا تكون التبعيات البعيدة الاختيارية مطلوبة إلا عند استخدام الخلفية البعيدة أو الخادم.

للتنسيقات المخصصة (مثل المعالجات الحركية)، استخدم واجهة برمجة تطبيقات وحدة التمرين مباشرةً:

from lerobot.rollout import BaseStrategyConfig, RolloutConfig, build_rollout_context
from lerobot.inference import SyncInferenceConfig
from lerobot.rollout.strategies import BaseStrategy
from lerobot.utils.process import ProcessSignalHandler

cfg = RolloutConfig(
    robot=my_robot_config,
    policy=my_policy_config,
    strategy=BaseStrategyConfig(),
    inference=SyncInferenceConfig(),
    fps=30,
    duration=60,
    task="my task",
)

signal_handler = ProcessSignalHandler(use_threads=True)
ctx = build_rollout_context(
    cfg,
    signal_handler.shutdown_event,
    robot_action_processor=my_custom_action_processor,       # optional
    robot_observation_processor=my_custom_obs_processor,     # optional
)

strategy = BaseStrategy(cfg.strategy)
try:
    strategy.setup(ctx)
    strategy.run(ctx)
finally:
    strategy.teardown(ctx)

راجع examples/so100_to_so100_EE/rollout.py وexamples/phone_to_so100/rollout.py للحصول على أمثلة كاملة تتضمن معالجات الحركة.

Update on GitHub