LeRobot documentation

정책 배포 (lerobot-rollout)

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.6.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

정책 배포 (lerobot-rollout)

lerobot-rollout은 학습된 정책을 실제 로봇에 배포하기 위한 단일 CLI입니다. 빠른 평가부터 연속 기록, human-in-the-loop 데이터 수집까지 다양한 실행 전략과 추론 백엔드를 지원합니다.

빠른 시작

로봇 및 정책 추가 항목 외에 추가적인 종속성이 필요하지 않습니다.

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를 전달하여 체크포인트의 디바이스를 재정의할 수 있습니다. 해결된 디바이스는 정책이 로드되고 프로세서가 구성되기 전에 정책 구성에 적용됩니다. 예를 들어, 정책이 CPU 실행을 지원하는 경우 위의 명령에 --device=cpu를 추가하여 CUDA로 학습된 체크포인트를 CPU 전용 호스트에서 실행할 수 있습니다. 로봇에 배포하기 전에 CPU 추론이 필요한 제어율을 충족할 수 있는지 확인하세요.

--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_dataRerun으로 관찰/동작을 스트리밍하여 시각화false

Sentry ( --strategy.type=sentry )

Hugging Face Hub로 주기적으로 업로드되는 연속 자율 녹화. 에피소드 경계는 카메라 해상도와 FPS에서 자동 계산되어 각 저장된 에피소드가 완전한 비디오 파일을 생성하므로 업로드 효율이 유지됩니다.

Policy 상태(숨겨진 상태, RTC 큐)는 episode 경계를 넘어 유지됩니다: 로봇은 episode 사이에 리셋되지 않습니다.

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_episodesN에피소드마다 Hub에 푸시5
--strategy.target_video_file_size_mb에피소드 로테이션을 위한 대상 비디오 파일 크기auto
--dataset.repo_id필수. 기록된 데이터셋의 Hub 저장소—
--dataset.push_to_hubteardown 시 Hub에 push할지 여부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_keyHub에 푸시할 키 (기본값: h)

DAgger ( --strategy.type=dagger )

Human-in-the-loop 데이터 수집. 자율 정책 실행과 텔레오퍼레이터를 통한 인간 개입을 번갈아 수행합니다. 개입 프레임에는 intervention=True 태그가 붙습니다. 텔레오퍼레이터(--teleop.type)가 필요합니다.

상세한 단계별 안내는 Human-In-the-Loop 데이터 수집 가이드를 참고하세요.

수정 전용 모드(기본값): 인간 수정 창만 기록됩니다. 각 수정은 하나의 에피소드가 됩니다.

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): 자율 프레임과 보정 프레임 모두 시간 기반 에피소드 로테이션(센트리와 동일)으로 녹화됩니다.

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"

키보드 컨트롤(기본 입력 장치):

키액션
Space정책 실행 일시 정지/재개
Tab시작 / 중지
EnterHub에 데이터셋 푸시(수정 전용 모드)
ESC세션 중지

--strategy.input_device=pedal을 통해 페달 입력도 지원됩니다. --strategy.pedal.* 플래그로 페달 코드를 구성합니다.

로봇이 rollout position hold를 지원하는 경우, 일시중지 시 드라이버가 실제로 적용한 마지막 위치 목표(클리핑 및 그리퍼 목표를 포함)가 새로고침됩니다. 첫 번째 명령 이전에는 검증된 측정된 포즈가 목표를 제공합니다. 이는 목표를 측정된 포즈로 변경하는 대신 명령된 위치 오차를 유지하며, 정책 궤적의 진행이 중단된 동안에도 로봇이 해당 목표 방향으로 안정화될 수 있습니다. 실제 로봇에서 로드된 팔 및 그리퍼 동작을 검증하십시오. 이 소프트웨어 기반 홀드는 그립 유지나 물리적 정지를 보장하지 않습니다.

플래그설명
--strategy.num_episodes기록할 교정 에피소드 수 (기본값: --dataset.num_episodes)
--strategy.record_autonomous자율 프레임도 기록합니다 (기본값: false)
--strategy.upload_every_n_episodesN 에피소드마다 Hub에 push (기본값: 5)
--strategy.input_device입력 장치: keyboard 또는 pedal (기본값: keyboard)
--strategy.smooth_handover일시정지/수정 시작 시 제어를 부드럽게 인계합니다 (기본값: true). 현재 로봇 자세를 기준으로 다시 참조하는 클러치 스타일 텔레오퍼레이션의 경우 비활성화합니다
--teleop.type필수. 텔레오퍼레이터 유형

에피소딕 ( --strategy.type=episodic )

lerobot-record의 동작을 반영하는 에피소드 중심의 기록입니다. 각 에피소드마다 정책이 로봇을 제어하며, 에피소드 사이의 리셋 단계에서는 선택적으로 텔레오퍼레이터가 로봇을 제어할 수 있습니다.

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이 설정되어 있고 이 값이 설정되지 않은 경우 기본값으로 --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에 등록된 config와, Config 접미사를 제외한 이름으로 명명된 RolloutStrategy 하위 클래스입니다. 이는 custom hardware에서 사용하는 SomethingConfig/Something 규칙과 동일하며, config의 모듈 또는 패키지에서 해석됩니다.

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)

config는 엔진이 전략을 대신하여 어떤 것을 구성하는지 선언하므로, LeRobot 내부에서는 그 타입을 알 필요가 없습니다:

선언효과
dataset_mode"none"(기본값)은 --dataset.* 플래그를 거부하고, "optional"은 지정된 경우 기록하며, "required"는 --dataset.repo_id를 필수로 만듭니다
requires_teleop--teleop.type를 필수로 만듭니다
supports_interactive--interactive=true를 허용합니다. 이 경우 run()은 RolloutStrategy에 문서화된 재시작 가능 계약을 준수해야 합니다.
requires_streaming_encoding()제어 루프 내부에서 프레임이 기록되면 True를 반환합니다: --dataset.streaming_encoding이 강제로 켜집니다
extra_dataset_features()전략이 소유한 데이터셋 열(예: DAgger의 intervention); 기록된 모든 프레임에는 이러한 열이 포함되어야 합니다

배포를 lerobot_strategy_<name>으로 명명하고 lerobot-rollout은 CLI를 파싱하기 전에 해당 패키지를 가져옵니다. 이때 __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(recording, interactive-safe)와 BaseStrategy(no recording)는 복사할 기준 구현체입니다. lerobot.rollout.strategies의 send_next_action, safe_push_to_hub, estimate_max_episode_seconds는 이 구현체들이 기반으로 하는 헬퍼입니다.

비동기 백엔드의 경우 디스패치 계약은 필수입니다. 각 캡처된 관찰을 engine.notify_observation(obs_processed)로 게시하고, 보간 및 홀드 틱을 포함하여 모든 자율 모터 틱에서 send_next_action(...)을 호출한 다음, engine.pump_query(obs_processed)를 호출합니다. engine.get_action()만 호출하면 권한 및 홀드 핸드셰이크가 우회됩니다. 이로 인해 계획된 텍스트 쿼리가 무기한 대기할 수 있으며, 터미널 장애가 종료 시그널을 보내지 못할 수 있습니다.

서드파티 전략은 _init_engine(ctx) 이후 주기적인 상태 보고를 포함하기 위해 timer.tick(...) 대신 self._tick(timer, new_cycle=interpolator.needs_new_action())를 호출할 수 있습니다.

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)로 감싸야 하며, 여기에는 링 버퍼 드레인 및 에피소드 최종화가 포함됩니다. 이를 통해 기록이 멈추기 전에 비동기 모션을 무효화하고, 러닝이 여전히 정상적이고 활성 상태일 때만 재개합니다. 연산자 제어 단계가 있는 전략은 현재 모션 권한을 resume_allowed로 전달해야 합니다. 다음 액션은 새로운 관측에서 나와야 하며, 저장된 작업은 일시 중지, 정지 또는 장애가 발생한 러닝을 되살려서는 안 됩니다.


정책 예측 시각화

--display_data를 사용하면 뷰어는 액션 외에도 정책이 예측하는 내용을 표시합니다. 월드 모델이 상상한 카메라 프레임, 예측된 서브태스크, 카메라 위에 그려진 바운딩 박스 등이 해당됩니다. 각 정책은 자신이 예측할 내용을 결정하고 자체 설정을 통해 이를 활성화합니다. 예를 들어 LingBot-VA의 경우 --policy.return_predicted_video=true를 사용합니다. 예측 항목은 예측 대상의 이름을 따서 명명됩니다. 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 )

배경 스레드가 비동기적으로 액션 청크를 생성합니다. 정책이 다음 청크를 병렬로 계산하는 동안, 메인 제어 루프는 다음에 준비된 액션을 폴링합니다.

호환되는 VLA 모델(Pi0, Pi0.5, SmolVLA)과 함께 RTC를 사용하여 추론과 모션을 겹치게 실행할 수 있습니다. 연속 실행을 위해서는 추론 지연 시간과 그 변동성을 커버할 수 있을 만큼 충분한 사용 가능한 액션 재생이 필요합니다.

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(기본값) 또는 호환되는 Pi05 체크포인트에 대한 학습된 접두사 trained
--inference.rtc.max_guidance_weight일관성 강제 강도 (기본값: 정책에 따라 다름)
--inference.rtc.prefix_attention_schedule블렌드 스케줄: LINEAR, EXP, ONES, ZEROS
--inference.queue_thresholdBackpressure threshold; 학습된 RTC는 최소한 최대 지연 시간만큼 필요합니다
--inference.action_starvation_grace_s지원되는 로봇에서 기아 상태 이후 새로운 모션을 기다립니다 (기본값 1.0; 0이면 즉시 오류가 발생합니다)

RTC 파라미터 조정의 자세한 내용은 실시간 청킹 가이드를 참조하세요.

Local RTC는 rollout 프로세스의 백그라운드 스레드에서 전송 없이 실행됩니다. 같은 컴퓨터의 서버와 클라이언트는 대신 --inference.type=remote를 사용합니다. chunk 정렬/블렌딩 및 비동기 백엔드가 공유하는 대기 동작에 대해서는 remote 가이드를 참조하세요.

Waiting 기능은 지원되는 로봇이 필요합니다. 해당 기능이 없어도 일반적인 로컬 RTC는 계속 사용할 수 있지만, 계획된 텍스트/지시 변경 일시중지 및 복구 가능한 starvation에는 이 기능이 필요합니다. 위치 제어 방식의 SO, OMX, Koch, HopeJr 및 Rebot 팔로워는 이를 지원합니다. OpenArm, Reachy2 및 양손 조작 래퍼는 로봇 지원 표에 나열된 구성 제약 사항이 있습니다. 지원되는 경우, 빈 버퍼는 action_starvation_grace_s(기본값 1초) 동안 마지막으로 적용된 타겟을 유지할 수 있으며, 여기에는 이전 추론을 완전히 처리하고 새로운 캡처에서 예측하는 데 필요한 시간도 포함됩니다. 움직임이 시작된 후, grace가 0이거나 로봇이 지원하지 않으면 소진 시 즉시 오류가 발생합니다. 시작 단계에는 별도의 마감 시간이 있습니다. 이전 로컬 RTC 경로와 달리, 소진은 더 이상 무한정 건너뛰는 틱이 아닙니다. Grace는 만료된 요청 또는 신선도 제한을 연장하지 않습니다.

Local RTC는 --inference.를 통해 이러한 추가 예산을 노출합니다:

매개변수기본값의미
max_observation_age_s5 s액션 실행을 통한 최대 소스 경과 시간
action_timeout_s10 s미처리된 작업 요청
startup_timeout_s120 s초기 준비 및 fresh-action 시작
language_timeout_s120 s계획된 언어 작업

이것들은 시작 값이며, 측정된 하드웨어 보증이 아닙니다. RTC는 다음 추론과 타이밍 마진을 위해 충분한 트림 후 재생을 유지해야 합니다. 추론이 사용 가능한 예측 지평선을 일상적으로 소진하는 경우, queue_threshold를 높여도 도움이 되지 않습니다. 지연 시간을 줄이거나 더 긴 지평선/다른 동작 주기를 검증하십시오.

터미널 장애는 정책 동작을 자동으로 재개하지 않습니다. 사용 가능한 관측 획득 및 액추에이터 제어가 있는 경우, 종료 시 --return_to_initial_position(기본값 true)을 준수하고 연결을 해제합니다. 반환 동작은 전체 관측을 읽으므로, 영구적인 카메라 장애가 이를 방해할 수 있습니다. 명령 적용 실패 시에는 sync를 포함한 모든 백엔드에서 추가적인 종료 움직임이 억제됩니다. 이는 동기식 예측을 변경하지 않으며, 카메라 전용 복구 메커니즘을 도입하지도 않습니다.

Compilation and instruction changes

RTC 컴파일은 움직임 전에 초기 호출과 접두사(prefix)가 포함된 호출을 모두 워밍업하며, 대표적이지 않은(nonzero) 지연 시간도 포함합니다. --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는 autosteer에서 제어권을 되돌려 줍니다
/vqa <text>로봇이 현재 보고 있는 것에 대해 질문을 합니다. 실행이 진행 중일 때만, 그리고 정책 텍스트 헤드 또는 외부 플래너를 사용할 때만 가능합니다.
/autosteer <goal>고수준 목표를 전달하고 정책의 텍스트 헤드 또는 외부 플래너가 하위 작업을 선택하도록 합니다. /autosteer off은 제어권을 되돌려 주고, 인자가 없으면 현재 목표를 보고합니다.
/reset이동을 중지하고 로봇을 시작 위치로 되돌린 다음 --task 지시를 복원합니다
/stop세션을 종료하고 정상적인 종료 루틴을 실행합니다
/help명령어 나열
> /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는 여전히 평소와 같이 종료되며, stdin을 닫으면(Ctrl-D 또는 파이프된 스크립트의 끝) 세션이 종료됩니다. 따라서 파이프된 스크립트는 의도된 시간 동안 stdin을 열려 있도록 유지해야 합니다:

(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는 정책(policy)에 목표를 전달하고, --autosteer_interval_s 초(기본값 10)마다 다음 하위 작업(subtask)을 요청합니다. 각 하위 작업은 /subtask와 동일한 경로를 통해 적용되며 채팅에 공지됩니다. 모든 쿼리는 완전한 텍스트 생성이므로, 이 간격은 비용 조절 수단입니다. 값이 낮을수록 재계획이 더 빨리 일어나지만, 행동 대신 텍스트 생성에 루프의 자원이 더 많이 소모됩니다. 계획 진행 상태는 롤아웃이 아닌 정책에 저장되므로, 세그먼트가 종료되면 계획도 함께 사라집니다. 시퀀서(sequencer)는 /reset, /subtask, /autosteer off, 그리고 첫 번째 계획 실패 시에도 중단됩니다.

ERROR보다 낮은 로그는 세션 실행 중에 억제됩니다. 이는 루틴 출력이 사용자가 입력하는 내용과 섞이지 않도록 하기 위함입니다. 오류와 치명적인 추론 실패는 여전히 표시되며, 세션이 종료되면 정상 로깅이 재개됩니다. cadence summaries는 대신 채팅에 출력되며, --interactive 없이 실행하면 실시간 로그를 다시 받을 수 있습니다.

Sessions는 SSH를 통해 작동하며 헤드리스 머신에서도 사용할 수 있습니다. 디스플레이 서버가 필요하지 않습니다.

인터랙티브 상태에서의 녹화. --strategy.type=sentry는 --interactive=true도 허용하며, 사용자가 조종하는 동안 지속적으로 녹화합니다. 각 /start…/reset 세그먼트는 완전한 에피소드와 최종 부분 에피소드 하나를 저장하며, 데이터셋은 종료 시까지 열려 있는 상태를 유지합니다. 프레임에는 실제로 전송된 액션의 작업 출처가 포함되므로, 이전 작업 아래에서 이미 큐에 추가되었거나 보간된 액션은 이전 라벨을 유지합니다.

Blocking mid-run episode saves는 비동기 추론을 일시 중지하고, 대기 중이거나 보간된 작업을 무효화하며, 지원되는 로컬 홀드를 요청합니다. 실행이 여전히 활성 상태이고 정상적인 경우에만 새로운 캡처에서 재개됩니다. 동일한 보호가 DAgger 저장 및 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

다른 기록 전략(episodic, DAgger, highlight)은 지원되지 않습니다. 이들은 자체 키보드 제어를 바인딩하고 run()이 종료될 때 데이터셋을 최종 처리하므로, 세그먼트별로 재시작할 수 없습니다.

외부 플래너

--planner.model_id=<name>는 /vqa와 /autosteer를 정책의 텍스트 헤드 대신 어노테이션 파이프라인의 VLM 클라이언트(annotations extra)를 통해 라우팅합니다. 호출은 로봇이 계속 동작하는 동안 워커 스레드에서 실행되며, 언어 홀드는 요청되지 않습니다. 다만 의도된 예외가 하나 있습니다. /autosteer가 시작되면 목표는 정책의 지시가 아니라 플래너의 컨텍스트이므로, 플래너의 첫 응답까지 추론 백엔드가 일시 중지됩니다. 비동기 백엔드(rtc, remote)는 이전 지시를 위해 이미 큐에 쌓이거나 계산 중인 동작을 폐기합니다. 동기 백엔드는 로봇을 홀드합니다. 첫 서브태스크가 적용되면 백엔드는 새로운 관측에서 재개됩니다. /subtask는 여전히 사용자의 지시를 직접 적용하고 자동 플래닝을 취소합니다. 늦게 도착하는 플래너 응답은 이를 오버라이드할 수 없습니다.

planner는 모든 추론 백엔드와 함께 작동합니다. 로컬 추론의 경우, 하위 작업 레시피가 있으면 로드된 프로세서의 하위 작업 레시피를 재사용하고, 그렇지 않으면 짧은 지시를 요청합니다. 이는 체크포인트가 해당 지시를 따를 수 있음을 보장하지 않습니다. --planner.instructions='["pick up the cup","open the drawer"]' 플래그는 planner의 출력을 제한합니다. VLM은 이 문자열 중 하나를 선택하도록 요청받으며, 목록에 없는 다음 하위 작업 응답은 오류로 처리됩니다. 대소문자, 추가 공백, 마침표는 무시되며, 목록 자체의 표현이 policy에 전달됩니다. 이 플래그가 없으면 체크포인트 학습 데이터셋의 작업 라벨(해당 train_config.json을 통해)에서 목록을 읽습니다. 모든 라벨이 프롬프트에 포함되므로, 작업이 많은 데이터셋의 경우 더 짧은 목록으로 플래그를 전달하세요. 데이터셋을 읽을 수 없는 경우 경고가 기록되고 planner 출력은 자유 형식으로 유지됩니다. 원격 추론은 policy를 관리하므로 레시피나 학습 어휘를 로컬에서 사용할 수 없습니다. --planner.instructions를 명시적으로 전달하지 않으면 응답은 자유 형식으로 유지됩니다. planner는 로컬 추론이 가능한 하드웨어에서만 테스트되었습니다.

외부 플래너는 마지막 --planner.history개의 관찰/명령 쌍(기본값 4)을 받은 후, 현재 이미지들을 수신합니다. 각 쌍에는 지시사항을 요청하는 데 사용된 관찰과 엔진에 의해 이후 수락된 지시사항이 포함됩니다. 수락은 성공적인 실행을 의미하지 않습니다. 반복된 지시사항은 VLM이 진행 상황의 부재를 평가할 수 있도록 히스토리에 유지됩니다. 히스토리는 수동 인계, 리셋, 정지, 세그먼트 종료 또는 새로운 autosteer 목표 설정 시 초기화됩니다. --planner.history=0을 설정하여 이를 비활성화할 수 있습니다. /vqa는 이 히스토리를 검사할 수 있지만 항목을 추가하지는 않습니다. 다음 하위 작업 요청 시 VLM은 먼저 장면을 설명하고 이전 명령이 완료되었는지, 진행 중인지, 실패했는지 여부를 명시한 후, 다음 지시사항을 지정해야 합니다. done 응답은 목표가 완료되었음을 의미하며, autosteer가 정지되고 실행이 종료되며, 로봇은 /reset 또는 /start가 실행될 때까지 현재 자세를 유지합니다. /subtask, /reset 또는 새로운 목표 설정 이전에 발생한 늦은 done은 폐기됩니다. 각 적용된 하위 작업은 모델의 장면 평가와 요청 지연 시간과 함께 출력됩니다.

OpenAI 호환 VLM 서버를 별도로 시작하고, 연결합니다:

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 Inference Providers를 사용하며, “Make calls to Inference Providers” 권한이 있는 토큰을 사용합니다:

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://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는 라이브러리 API와 동일한 작업을 노출합니다. 스레드 안전의 start() / reset() / stop() / set_task()와 RolloutEvent 콜백을 제공하며, stdin, 출력 또는 로그 음소거가 연결되어 있지 않습니다:

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 모델 ID 또는 로컬 체크포인트 경로—
--robot.type필수. 로봇 유형 (예: so100_follower, koch_follower)—
--robot.port로봇용 시리얼 포트—
--robot.cameras카메라 구성 (JSON dict)—
--fps정책 추론 및 데이터셋 기록 빈도30
--status_interval_s헬스 로그 간격(초) (0은 비활성화; 비대화형 전용)5
--duration실행 시간(초) (0 = 무한; 인터랙티브 모드인 경우 세그먼트별)0
--deviceTorch 장치(cpu, cuda, mps)auto
--task작업 설명(데이터셋이 제공되지 않은 경우 사용)—
--display_dataRerun 시각화로 텔레메트리 스트리밍false
--display_ip / --display_port원격 Rerun 서버 주소—
--interpolation_multiplier정책 동작당 로봇 명령 (주파수 fps × N Hz에서 제어)1
--interactivestdin에서 채팅 세션; 로봇은 /start(base, sentry)까지 대기false
--use_torch_compile추론에 torch.compile 활성화false
--resume이전 녹화 세션 재개false
--play_sounds이벤트를 위한 보컬 합성true

Cadence 보고

Non-interactive rollout은 5초마다 상태를 기록합니다. --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

Latency는 해당 구간의 중앙값/최악의 값입니다(RTC/원격의 경우 turnaround). 사용 불가능한 필드는 생략되며, GPU 메모리는 장치 전체를 나타내고 원격 메모리는 로컬을 나타냅니다. 루프가 차단되면 보고가 일시 중지됩니다.

각 전략은 제어 루프가 실제로 달성한 내용을 보고하며, 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

위에서 아래로 읽으세요: effective cadence는 --fps 대비 실제로 달성한 값이며, cycles over budget는 루프가 해당 속도를 유지하지 못한 횟수, step breakdown는 시간이 어디에 쓰였는지, 그리고 pacing headroom가 0에 가까우면 느린 틱을 흡수할 여유가 전혀 남지 않았다는 뜻입니다. infer 비중이 높으면 정책이나 디바이스를, observe 비중이 높으면 카메라를 의심해 보세요. 특정 스텝의 worst 값이 mean 값보다 훨씬 높다면 일회성 이벤트입니다. 위 예시에서 record는 프레임당 0.67 ms이고, 620 ms의 이상치는 에피소드를 종료하는 블로킹 save_episode입니다.

여기서 cycle은 하나의 정책 액션에 해당하는 틱 수(--interpolation_multiplier개)를 의미합니다. 1/fps 예산을 초과하는 것은 오직 완전한 사이클에 대해서만 프레임 손실을 유발합니다. 단일 틱이 자신의 슬롯을 초과하는 경우 보간된 움직임이 덜 매끄러워질 뿐이므로, 두 항목은 별도로 집계됩니다. 보간이 없는 경우 사이클은 단일 틱이므로, 보고서는 이 구분을 생략하고 틱으로 일관되게 집계합니다.

대화형 세션에서는 각 /start 세그먼트가 자체 타이머를 가지므로, 프로세스당 한 번이 아니라 세그먼트당 한 번(/reset, /stop, 또는 --duration)씩 보고가 채팅에 전송됩니다.


프로그램 방식 사용

확장 기능의 경우, lerobot.inference는 백엔드 구성, 로컬 엔진 및 공유 스케줄링 계약을 위한 공개 패키지입니다. lerobot.remote_inference는 원격 엔진, 프로토콜, 배포 및 세션 구현을 담당하며, lerobot.rollout는 로봇 루프, 전략, 보간 및 기록을 담당합니다. 구현 파일이 아닌 해당 패키지에서 공개 심볼을 가져오세요. 선택적 원격 의존성은 원격 백엔드 또는 서버를 사용할 때만 필요합니다.

커스텀 배포(예: kinematics 프로세서 사용)의 경우, rollout 모듈 API를 직접 사용하세요:

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