LeRobot documentation
策略部署(lerobot-rollout)
策略部署(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 以覆盖检查点设备。
解析后的设备会在加载策略并构建其处理器之前,应用于策略配置。
例如,如果策略支持 CPU 执行,可以在上述命令中添加 --device=cpu,以便在仅配备 CPU 的主机上运行使用 CUDA 训练的检查点。
在部署到机器人之前,请确认 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_data | 将观察/操作流式传输到 Rerun 以进行可视化 | false |
Sentry ( --strategy.type=sentry )
持续自主录制,并定期上传至 Hugging Face Hub。剧集边界会根据相机分辨率和 FPS 自动计算,确保每个保存的剧集都能生成完整的视频文件,从而保持上传的高效性。
策略状态(隐藏状态、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_episodes | 每 N 个回合推送到 Hub | 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)
Human-in-the-loop 数据收集。在自主策略执行与通过遥操作器进行的人工干预之间交替进行。干预帧会被标记为 intervention=True。需要配置遥操作器(--teleop.type)。
有关详细操作指南,请参阅人机协同数据收集。
仅修正模式(默认):仅记录人工修正窗口。每次修正构成一个 episode。
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):自主帧和校正帧均会进行录制,并采用基于时间的 episode 轮换(与 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"键盘控制(默认输入设备):
| 密钥 | 操作 |
|---|---|
Space | 暂停 / 恢复策略执行 |
Tab | 开始 / 停止人工校正 |
Enter | 将数据集推送到 Hub(仅更正模式) |
ESC | 停止会话 |
也支持通过 --strategy.input_device=pedal 使用脚踏板输入。使用 --strategy.pedal.* 标志配置踏板代码。
当机器人支持 rollout 位置保持时,暂停操作会刷新驱动程序实际应用的最后一个位置目标,包括其裁剪和夹爪目标。在第一条命令之前,经过验证的测量位姿将作为目标提供。这保留了命令位置误差,而不是将目标更改为测量位姿;在策略轨迹推进停止期间,机器人可以继续向该目标收敛。请在实际机器人上验证负载臂和夹爪的行为;此软件保持功能不保证保持抓握或物理静止。
| 标志 | 描述 |
|---|---|
--strategy.num_episodes | 要记录的纠正回合数(默认值:--dataset.num_episodes) |
--strategy.record_autonomous | 同时记录自主帧(默认:false) |
--strategy.upload_every_n_episodes | 每 N 个回合推送到 Hub(默认值:5) |
--strategy.input_device | 输入设备:keyboard 或 pedal(默认:keyboard) |
--strategy.smooth_handover | 在暂停/校正开始时平滑地移交控制权(默认值:true)。对于在接合时以当前机器人位姿重新参考的离合器式遥操作,请禁用此功能 |
--teleop.type | 必填。 遥操作类型 |
情景式(--strategy.type=episodic)
采用以回合(episode)为导向的录制方式,其行为与 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 后缀命名的 RolloutStrategy 子类——与 自定义硬件 相同的 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 中记录的可重启契约 |
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> 加载。策略的数据类字段会成为 --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(不录制)是可供参考的实现;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() 会绕过权限和保持握手:计划中的文本查询可能会无限期等待,且终端故障可能永远不会发出关闭信号。
第三方策略可以调用 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) 中,包括环形缓冲区排空和回合结束处理。这会在录制停顿前使异步运动失效,并且仅在运行仍然健康且处于活动状态时才恢复。具有操作员控制阶段的策略必须将其当前的运动权限作为 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 时,预测内容每个 chunk 刷新一次。请参阅 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.mode | guided(默认)或兼容 Pi05 检查点的训练前缀 trained |
--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 参数的详细信息,请参阅 Real-Time Chunking 指南。
本地 RTC 在 rollout 进程的后台线程中运行,无需传输层。同一台计算机上的服务器和客户端应改用 --inference.type=remote。有关块对齐/混合以及异步后端共有的等待行为,请参阅远程指南。
等待功能需要受支持的机器人。普通的本地 RTC 在没有该功能的情况下仍然可用,但计划中的文本/指令变更暂停以及可恢复的饥饿状态需要它。位置控制的 SO、OMX、Koch、HopeJr 和 Rebot 跟随器支持此功能;OpenArm、Reachy2 和双手包装器存在配置限制,详见机器人支持表。在受支持的情况下,空缓冲区可以保留最后应用的目标,持续时间为 action_starvation_grace_s(默认 1 秒),包括排空旧推理并从新捕获中进行预测所需的时间。在运动开始后,如果宽限期为零或机器人不受支持,耗尽时会立即发生故障;启动有其自身的截止时间。与以前的本地 RTC 路径不同,耗尽不再是一个无限期跳过的 tick。宽限期永远不会延长已过期的请求或新鲜度限制。
Local RTC 通过 --inference. 公开了这些额外的预算:
| 参数 | 默认 | 含义 |
|---|---|---|
max_observation_age_s | 5 s | 通过操作执行实现的最大源年龄 |
action_timeout_s | 10 s | 待处理的操作请求 |
startup_timeout_s | 120 s | 初始准备和新鲜操作启动 |
language_timeout_s | 120 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 以从终端驱动 rollout,而不是立即开始。硬件连接和策略加载照常进行,但 在您输入 /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 仍会按常规方式关闭,而关闭标准输入(Ctrl-D,或管道脚本的末尾)会结束会话——因此,管道脚本必须保持标准输入在预期时长内处于打开状态:
(printf '/start\n'; sleep 60; printf '/stop\n') | lerobot-rollout ... --interactive=true/subtask 用于更新后续推理的任务。在使用 --inference.type=sync 时,预计算的块动作会被丢弃。在本地 RTC 或远程推理中,如果在动作请求期间发生更改,过时的结果将被丢弃。对于支持本地保持(local hold)的机器人,引擎会使队列中/插值中的运动失效,等待控制循环确认保持状态,然后在新任务下请求新的运动。在此过渡期间预计会出现停止;这不保证是连续的混合。请求之间的更改可以保留已接受的动作以保持连续性。在不支持保持的机器人上使用本地 RTC 时,仍然会丢弃过时的结果,但可能会耗尽剩余的动作并终止。如果该机器人无法适当保持,请在运行之间更改指令。
在本地使用 --use_torch_compile=true 时,改变处理后张量形状的指令可能会触发重新编译。填充(Padding)可能使某些任务变更保持相同的形状,但后续的编译并不保证能适配剩余的播放或指令变更截止时间:这可能导致终端故障。除非已验证这些转换,否则在探索指令时应保持编译关闭。在初始编译预热期间的变更不会请求运动保持,因为策略运动尚未开始。
/vqa 和 /autosteer 需要一个声明了文本生成支持并实现了 PreTrainedPolicy.generate_text() 的策略,例如经过适当训练的 EO1 检查点,或一个 外部规划器。在接受查询之前会检查该能力;特定于检查点的行为仍需验证。
/vqa 会基于下一帧观测进行回答,并在就绪时打印结果,因此您可以在此期间继续输入;同一时间只有一个问题在处理中(autosteer 自身的查询也共享该槽位)。若使用外部规划器,问题将在工作线程上回答,而机器人继续执行动作,以下描述均不适用。异步后端首先进入已确认的本地保持状态,并使队列中/插值后的运动失效,然后将新的观测提交给文本路径。健康的活跃运行会在回答后从新的动作块恢复;暂停或停止的运行保持非活动状态。同步文本生成在控制线程上内联执行,并丢弃策略预计算的动作,因此下一个 tick 将从新的推理恢复。查询时间会计入 --duration。仅在运行进行中时才会接受问题——空闲引擎没有当前视图。如果指令或执行上下文使异步回答失效,问题将收到一条取消通知,而不是过时的回答。片段结束时也会报告未回答的问题,包括仍在生成中的问题;报告取消不会中断正在运行的模型调用,也不会提前释放其查询槽位。
/autosteer 向策略(policy)提供一个目标,并每隔 --autosteer_interval_s 秒(默认 10 秒)请求下一个子任务,通过与 /subtask 相同的路径应用每个子任务,并在聊天中宣布。每次查询都是一次完整的文本生成,因此该间隔是一个成本调节旋钮:更低的值会更快重新规划,但会花费更多循环时间用于生成文本而非执行动作。计划进度保存在策略中,而非 rollout 中,因此计划会随 segment 结束而终止;sequencer 也会在 /reset、/subtask、/autosteer off 以及首次规划失败时停止。
会话运行期间,低于 ERROR 级别的日志会被静音,以避免常规输出与您正在输入的内容交错显示;错误和致命的推理失败仍会显示,会话结束后恢复正常日志记录。节奏摘要 会打印在聊天中,而不使用 --interactive 运行则会恢复实时日志。
会话通过 SSH 运行,也适用于无头机器——无需显示服务器。
交互过程中录制。 --strategy.type=sentry 还支持 --interactive=true,在您操控时持续录制:每个 /start…/reset 片段会保存完整的 episode 以及一个最终的 partial episode,并且数据集在关闭前保持打开状态。帧携带实际发送动作的任务来源信息,因此已在旧任务下排队或插值的动作仍保留旧标签。
运行中途的阻塞式 episode 保存会暂停异步推理,使已排队或插值的动作失效,并请求受支持的本地保持。仅当运行仍处于活跃且健康状态时,才会从新的捕获中恢复。相同的保护机制也适用于 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 附加组件)运行,而不是通过策略的文本头。调用在机器人持续行动期间于工作线程上执行,并且不会为它们请求语言保持,但有一个刻意的例外:当 /autosteer 启动时,推理后端会暂停,直到规划器给出第一个回复,因为目标是规划器的上下文,而不是策略的指令。异步后端(rtc、remote)会丢弃已排队或正在为上一条指令计算的动作;同步后端则会保持机器人。一旦第一个子任务被应用,后端将从新的观测中恢复。 /subtask 仍然直接应用您的指令并取消自动规划;规划器晚到的回复无法覆盖它。
规划器适用于所有推理后端。在本地推理中,如果已加载的处理器存在子任务配方,则复用该配方;否则,请求一条简短的指令;但这并不能证明检查点能够遵循该指令。--planner.instructions='["pick up the cup","open the drawer"]' 会限制规划器的输出:VLM 被要求从这些字符串中选择一个,而返回不在列表中的下一个子任务将被视为错误。大小写、多余的空格和末尾的句号会被忽略,而列表本身的措辞会发送给策略。如果不使用此标志,列表将从检查点训练数据集的任务标签中读取(通过其 train_config.json)。由于每个标签都会进入提示词,因此对于包含许多任务的数据集,请通过该标志传入更短的列表。如果无法读取数据集,则会记录一条警告,并且规划器的输出将保持自由格式。远程推理拥有策略,因此本地无法访问配方或训练词汇表:请显式传入 --planner.instructions,否则回答将保持自由格式。规划器仅在配备本地推理的硬件上经过测试。
外部规划器会接收最近 --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://huggingface.co/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 暴露了与库 API 相同的操作——线程安全的 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 callerRolloutController 要求上下文的关闭事件是一个 LinkedEvent,构建方式如上所述:控制器通过其本地标志结束运行段,而您的 parent 事件仍会强制完全关闭。除非您希望听到语音播报,否则请设置 play_sounds=False。
常用标志
| 标志 | 描述 | 默认 |
|---|---|---|
--policy.path | 必填。HF Hub 模型 ID 或本地检查点路径 | — |
--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 | 将遥测数据流式传输到 Rerun 可视化 | false |
--display_ip / --display_port | 远程 Rerun 服务器地址 | — |
--interpolation_multiplier | 每个策略动作对应的机器人指令(以 fps × N Hz 的频率进行控制) | 1 |
--interactive | 在 stdin 上进行聊天会话;机器人在收到 /start 之前保持空闲(base, sentry) | false |
--use_torch_compile | 为推理启用 torch.compile | false |
--resume | 恢复之前的录制会话 | false |
--play_sounds | 活动语音合成 | true |
Cadence 报告
非交互式 rollout 会每五秒记录一次其状态。使用 --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
延迟为区间内的中位数/最差值(RTC/远程为turnaround)。不可用的字段将被省略;GPU 内存为设备级,远程内存为本地。当循环阻塞时,报告将暂停。
每种策略都会报告其控制循环实际达成的结果,lerobot-record、lerobot-teleoperate 和 lerobot-replay 也是如此——它们都按照同一个计时器推进。每个保存的 episode 都会生成一行摘要,当循环结束时——包括在按下 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。
此处的cycle指一个策略动作所对应的 tick 数量(即 --interpolation_multiplier 个)。只有当完整的 cycle 超出 1/fps 的预算时,才会导致掉帧;单个 tick 超出其时间槽只会使插值后的运动不够平滑,因此这两者被分开统计。在没有插值的情况下,一个 cycle 就是一个 tick,因此报告会取消这种区分,并始终按 tick 进行统计。
在 交互式会话中,每个 /start 片段都拥有自己的计时器,因此报告会在每个片段(/reset、/stop 或 --duration)结束时发送到聊天中,而不是在每个进程结束时发送。
编程式用法
对于扩展功能,lerobot.inference 是用于后端配置、本地引擎和共享调度契约的公共包。lerobot.remote_inference 负责远程引擎、协议、部署和会话的实现;lerobot.rollout 负责机器人循环、策略、插值和记录。请从各自的包中导入公共符号,而不是从实现文件中导入。仅在使用远程后端或服务器时,才需要可选的远程依赖项。
对于自定义部署(例如使用运动学处理器),请直接使用 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 以获取包含运动学处理器的完整示例。