跳转到内容

正在加载搜索…

episode 运行时

三层加一个安全层(shield):模型编写程序(高层),程序调用有界 skill(低层),guard 和 控制器在每个控制 tick 运行(反应层),一个固定的安全层在每条命令到达机器人之前对其进行检查。

托管的模型Driverharness run / program模型循环、trace、预算Kernel · 每个 episode 一个模型写的程序session = skills隔离运行cellsWorker · 一个任务安全层环境tick, observe,fk, ik, plan服务SAM 3, Molmo2, VLAs, OpenWAM, VLMreset、结果
一个 episode 的进程。只有 driver 和模型对话;程序发出的每条命令都经过安全层才到达环境。
进程 由谁启动 做什么
Worker harness run(或 harness serve) benchmark 的一个任务:reset、tick(经过安全层的一个控制步)、state、observe、fk / ik / plan、结果
服务 harness up,或首次使用时由 broker 启动 skill 调用的模型(服务与 deploy 文件)
Driver harness run / harness program 模型循环、trace、预算
Kernel driver,每个 episode 一个 在 skill 的命名空间中运行模型的程序

src/harness_policy/runtime/driver.py。每次模型调用都是一个决策点,在 summary.json 中按原因统计(decisions):

原因 何时
start 第一次调用:指令、任务描述(如果配置使用它们)、机器人状态、相机图像
escalation 程序因一个其中没有任何部分处理的事件而停止
error 程序抛出了异常
program_end 程序未调用 finish() 就结束了
verify 模型向成功验证器发出询问(<verify>)
format 上一条回复没有有效的块
action 直接模式(R0/R1):每个动作之后

一条回复在可选的思考之后恰好包含一个块:<python>(一个程序)、<verify>(交给验证器的 一个断言)或 <finish>(完成);在直接模式下为 <action>{JSON}</action> 或 <finish>。 没有有效块的回复会消耗一次调用,并得到 “Format error … Nothing ran” 的答复;一旦收到 有效回复,这些错误的往来就会从历史中移除。

一个程序 cell 结束后,模型得到:cell 的状态和输出、使其停止的事件、最近的执行、已启用 skill 的每轮报告(按物体 id 调用的工具:重新测量的场景,为下一个程序打上标签,附上每只持物 手臂的抓握状态)、机器人状态和已用的环境步数、程序用 show() 附上的图像以及最新的相机视图 (在每轮报告描出轮廓的地方描出轮廓),以及剩余的调用次数。使用学习型策略时, start(strategy, kind) 是第一个动作:在它被调用之前,每个移动手臂的执行都以 SKILL_ERROR 结束(runtime.strategy_first),summary.json 把这一选择记录为 strategy (分工)。

策略运行之后。 用 start("A" or "C") 交出的任务运行完之后,模型还有 post_policy_calls 次调用(agent 中为 4 次;每一轮都会说明还剩多少次)。用完之后,driver 运行 kernel 的 __policy_to_end__() 钩子(事件 policy_to_end):策略从当前状态继续运行 到 episode 结束,不会因静止而停止。如果此后 episode 仍在运行,driver 会结束它(finish, source: "driver")并执行收尾。

预算与状态。 每个 episode:max_model_calls(agent 的预算:30)、 max_wall_seconds(在每次模型调用之前检查;正在运行的 cell 受 cell_timeout_seconds 限制),以及可选的 max_cost_usd。一个 episode 的结束状态为 finished(<finish> 或 finish())、episode_ended(benchmark 结束了它:成功或达到步数上限)、 budget_exhausted、wall_time_exhausted、cost_exhausted、interrupted 或 error。

历史。 文本历史全部保留;图像只保留最近 keep_images 轮(更早的变为 “[earlier image omitted]”);max_history_turns 保留第一条消息加最近 N 次往来,用于 上下文较小的模型。

验证器。 当 runtime.verifier 开启时(默认),<verify> 和程序中的 verify() 会 带着一次新的观测,询问验证器角色(除非另行指定,否则为主模型)该断言是否成立:YES/NO 加 一句话。

收尾与结果。 finish 之后,若 embodiment 要求(RoboDojo 要求),driver 执行收尾: 每个没有持物的夹爪张开,然后两只手臂回到起始姿态。RoboDojo 的 42 个任务中有 23 个只有在 每个夹爪至少张开 0.8 时才计分,而且大多数只有在手臂回到原位时才算成功;持物的夹爪保持闭合, 因为抬举类任务要求物体仍在空中才计分。结果通过 driver 在 reset 时领取的一个 token 读取; 程序和模型都看不到它。

src/harness_policy/runtime/kernel.py。每个 episode 一个 Python 进程;变量从一个程序 (cell)保留到下一个。一个 cell 的结束状态为 ok、escalated(附带该事件的 trace)、 episode_ended、finished 或 error(traceback 只保留程序自己的帧)。输出截断为 8000 个字符。每个 cell 之后,kernel 会恢复被程序重新绑定的任何 API 名称(def pick(...)), 并在输出中说明。

程序在隔离中运行:它们只能看到 Python 安装和 harness 源码(只读)以及一个全新的工作区, 只能访问其选项中的服务,并且不能启动进程。参见隔离程序。

session 类是针对某一种 embodiment 类型特化的 episode 核心 (src/harness_policy/runtime/episode.py),再加上该类型所有 skill 的 mixin (skills/<name>/);已启用的 skill 决定程序能看到哪些名称。episode 核心持有与 embodiment 无关的部分:worker 连接、模型客户端和学习型策略、handler、反应层以及有界执行。一种 embodiment 类型的 session 规定:一步的命令是什么以及它如何到达 worker,保持一切不变的命令, guard 观察什么,命令何时离开执行的范围,以及它自己执行哪些 guard 动作。机器人的 session 是 RobotSession(runtime/session.py):一条命令是两只手臂的关节向量,范围是某只手臂的 link6 必须停留的区域,guard 还可以张开夹爪。benchmark 决定类型(RoboDojo 和 RoboTwin 驱动 机器人),worker 在其 profile 中报告类型(kind,默认为 robot),如果一次运行的 worker 驱动的是另一种类型,运行会报错停止。每个动作都是一个有界执行:它逐 tick 运行,直到完成、 某个谓词或 guard 触发、离开其范围或超过 max_seconds,并以一个事件和一条执行 trace 结束。

事件 含义
COMPLETED、PREDICATE_SATISFIED 正常:执行完成了要求的事(until 成立)
TIMEOUT 超过了 max_seconds
BLOCKED 手臂在到达目标前停下(稳定后偏差超过 1 cm 或 0.05 rad)
GUARD_TRIGGERED(或 guard 自己的事件名) 反应层的一个 guard 触发了
REGION_EXIT 执行离开了其范围(机器人手臂离开了其区域)
SHIELD_REJECTED 安全层拒绝了一条命令(附带原因)
REACTIVE_FAULT guard 或控制器失败,或超出了其时间预算
SKILL_ERROR skill 无法完成要求的事
EPISODE_ENDED benchmark 结束了 episode

非正常事件会交给程序用 on(event, handler) 为它注册的 handler。如果没有 handler,或 handler 返回 False,事件就会上报:cell 停止,模型带着 trace 被调用(escalation)。 finish(summary) 在程序内部结束 episode。

guard 和控制器在每个控制 tick(RoboDojo 上为 25 Hz)运行,无需询问模型:

  • when(predicate, action) — guard:当谓词成立时,执行 stop、hold、 open_gripper,或抛出以该名称命名的事件。
  • watch(signal, low, high) — 针对数值信号离开某个区间的 guard。
  • clear_guards(names=None)。
  • run_controller(fn, until, max_seconds, region, hz, cameras, camera_hz) — fn 以 hz 的频率把观测映射为关节、末端执行器(left_eef / right_eef,由 IK 求解)或夹爪目标; 使用 cameras 时,可获得用于视觉伺服的最新图像和标定。

反应代码每次调用都有一个时间预算(runtime.reactive_budget_ms;agent 中为 20 ms),且不得 进行 I/O、休眠或调用模型;违反即为 REACTIVE_FAULT。

src/harness_policy/runtime/shield.py 在 worker 中运行,程序无法触及,它检查每个 tick 的 每条命令。它拒绝属于 bug 的命令,此外不做任何改动:它从不对命令进行截断、缩短或减速。

检查 拒绝
形状、有限值 格式错误的命令
关节限位 目标超出限位的程度大于关节当前已超出的程度(外加 1e-3 rad 容差)
关节跳变 手臂关节相对于上一条被接受的命令和测量状态都跳变超过 max_joint_jump_rad
工作空间 末端执行器在工作空间盒之外的程度大于其当前已在外的程度
笛卡尔跳变 末端执行器相对于上一条命令和测量位姿都跳变超过 max_cartesian_jump_m

被拒绝的命令不会执行;执行以 SHIELD_REJECTED 和原因结束,于是程序得知它的命令是错的。 RoboDojo 的限值在 embodiment 中(embodiments/arx_x5):0.3 rad、0.25 m 以及工作空间盒。