spikefly's picture
Add files using upload-large-folder tool
530d2e1 verified
|
Raw History Blame Contribute Delete
7.09 kB

π0.5 · ARX Lift2S「place the answers on the whiteboard」部署契约(一页)

训练:LeRobot π0.5,上游 huggingface/lerobot 提交 89236ea0f4f81a81ca566081e20dd1ff5f823cbe(训练时另有两个只管存档的本地开关,与推理无关);底座 lerobot/pi05_base;数据 yaoxianze/arx_cot_math(版本 10aa998)转 LeRobot v3.0(转换与分位数统计脚本见 tools/);全局批 32,先训 3 万步,再从 3 万步档精确续训到 4 万步(优化器 / 调度器 / 随机数状态和数据顺序都接上,余弦衰减终点由 3 万步延到 4 万步);块长 70、每次执行 35 步;绝对关节;分位数归一化。 仓根 = 训练落盘的 pretrained_model/,PI05Policy.from_pretrained(<仓名或本地目录>) 直接可用。前后处理器(policy_preprocessor*、policy_postprocessor*)已经含相机改名和分位数归一化 / 反归一化参数,客户端不要自己归一化。 推理代码:上游 lerobot 提交 89236ea 即可(clone 后 git checkout 89236ea && pip install -e ".[pi,dataset]";[dataset] 是复现检查和数据转换要用的 PyAV、jsonlines 等)。

输入(每次推理一帧)

键 内容 形状 / 类型 注意
observation.images.camera_h 头部相机 640×480,RGB 和采集同一台相机、同样设置
observation.images.camera_l 左腕相机 640×480,RGB
observation.images.camera_r 右腕相机 640×480,RGB
observation.state 当前关节读数 float32 (14,) 顺序 [左 j0…j5, 左夹爪, 右 j0…j5, 右夹爪];关节为弧度,夹爪为原始读数(数据实测:左 −3.328 … −1.545、右 −3.384 … −1.438,两只夹爪在示教里最多都只闭到约 −1.5;按数据集约定 0 为全闭、约 −3.3 全开,请以你们机器人的实际读数为准)
task 提示词 字符串 逐字(含句末句点):Place the answers to the questions on the whiteboard properly.(这份数据只有这一个任务)
  • 图像转换:torch.from_numpy(rgb_uint8_HxWx3).permute(2,0,1).float() / 255,不要自己缩放(预处理器内部 resize-pad 到 224)。
  • 颜色:OpenCV 取图是 BGR,必须先转 RGB。deploy/fit_check_pi05.py 里的客户端路径测试会抓这个错。
  • 这份数据只有这三路相机(没有外部相机)。

输出

  • 一块 70 步 × 14 维绝对关节目标,顺序与 state 相同 [左 6, 左夹爪, 右 6, 右夹爪],单位同 state(已反归一化)。
  • 数据里 action ≡ 当前状态 → 第 0 步 ≈「现在在哪」,部署从第 1 步开始执行。

执行

  • 控制频率 20 Hz(和采集一致)。
  • 同步重规划:推理 → 执行第 1…35 步 → 再推理(执行步数可调,默认 35 = 块长一半,与训练配置的 n_action_steps 一致)。
  • 块起点渐入:默认开,前 5 步(k 可调)从实测关节线性过渡到预测轨迹,缓解每次重推的起点跳变;开 / 关效果在真机上对比。
  • 夹爪:直接下发模型输出值,不做特殊处理。这份数据的动作列记的是实测位置(两只夹爪最多闭到约 −1.5);照这个值下发能不能拿住、放下答案,在回放测试里看。
  • 推理显存约 9 GB(bf16),RTX 5090 够用。

归一化参数(不能和别的模型混用)

  • 仓根的 policy_preprocessor_step_3_normalizer_processor.safetensors(状态 / 动作的 q01、q99)和 policy_postprocessor_step_0_unnormalizer_processor.safetensors(动作的 q01、q99)是用这份数据自己统计的。夹爪区间:左 [−3.327, −1.727]、右 [−3.384, −1.620]。
  • 不要拿叠杯、叠毛巾或挂衣架模型的处理器文件来跑这个模型:四份数据的夹爪区间上界各不相同(叠杯 −1.673 / −1.700,叠毛巾 −0.040 / −0.048,挂衣架 −0.476 / −0.118,本模型 −1.727 / −1.620),混用的话夹爪的归一化和反归一化都会错。用 from_pretrained(本仓) 加载就不会混。

上真机前

  1. 先做回放测试(与模型无关,任何策略之前):python deploy/replay_demo.py export --dataset-root <数据目录> --episode 0 --out replay_ep000_commands.csv(数据目录 = 按 README 第 3 节用 tools/prep_pi05_data.sh 转换出来的目录;本仓不含数据),按第 0 局的场景摆好(参照第 0 局视频),机械臂慢速移到第 0 行,再按 20 Hz 逐行下发,记录实测关节(RolloutLogger.state 或 CSV)和视频;然后 python deploy/replay_demo.py analyze --commands … --measured …。它回答三件事:「拿实测位置当指令」能否复现示教;夹爪按示教的读数下发时拿不拿得住要放的东西(看视频);控制器跟踪滞后几帧(作为真机执行段跟踪的基线)。回放都做不成,先查硬件 / 指令语义。
  2. 在部署机上跑 deploy/fit_check_pi05.py(命令见 deploy/TOLERANCE.md,要带 --task-prompt from-dataset --repo-id local/arx_math_pi05 --execute-horizon 35——这份数据只有一个任务串,from-dataset 和直接传那句话结果相同;--dataset-root 用你自己转换出来的目录,--compare-to deploy/expected/action_fit_summary_bf16.json),对照 deploy/TOLERANCE.md(脚本读 deploy/tolerance.json,末尾打印 TOLERANCE_CHECK PASS/FAIL):期望块最大差(全部 14 维和只看关节两项)、聚合拟合误差相对差都要在容差内;client_path_test.pass 必须为 true(判据:每帧图像差 ≤ 1/255;两条路径的块差只作提示,部分显卡上两次前向不逐位相同)。
  3. 必须用你自己机器人端的「相机取图 → 张量」代码跑一遍客户端路径测试:--client-fn 你的模块:函数 --client-frame-format bgr|rgb(函数收相机原样交出的 uint8 HxWx3 帧,返回进模型的 float (3,H,W) [0,1];客户端 / 服务端分开的话把两段拼起来)。模板见 deploy/example_client_fn.py。BGR、缩放、裁剪这类错只有这样才抓得到。
  4. 第一次上机先悬空或低速,只打印一块 70 步动作,核对关节范围、顺序、夹爪方向都对了再正式执行;确认急停可用。

真机上查训推不一致(上真机后)

  • 客户端用 deploy/rollout_consistency.py 里的 RolloutLogger 记每次推理(当前关节状态 + 预测块 + 执行区间,exec_n=35)和每个控制步的实测关节,一局一个 jsonl。
  • 跑完执行 python deploy/rollout_consistency.py run_*.jsonl --reference deploy/expected/action_fit_summary_bf16.json,得到和离线同口径的两个数:
    • 块起点偏移 |â0 − s_t|(模型估计「手臂现在在哪」与实测关节之差,不需要标注):离线基准见 deploy/TOLERANCE.md;真机上超过离线 3 倍会给出排错提示(只是提示、不是关卡),先查相机机位 / 曝光、光照、取图转换、相机顺序;
    • 执行段跟踪 |â_k − s_{t+k}|:含控制器跟踪滞后,离线没有这部分,应当和回放测试测出的跟踪误差比,而不是和离线拟合误差比。