← 全部报告
2026-08-22XLeRobot 双臂 操作指南

实机试跑 · 面板操作

把训练好的 checkpoint 放到真手臂上跑 10 次。 整个循环都在手机面板上按按钮完成,不用终端。 这一页是站在机器人旁边时打开的那一页。

★ 打开哪个地址

面板服务跑在 Jetson 上,监听 0.0.0.0:8770,所以下面几条路都通 —— 按你人在哪、手机连的是什么网来选:

场景地址说明
手机(推荐) http://100.107.145.111:8770 Tailscale 地址。手机装了 Tailscale 就能用,不管在哪个网
手机 / 笔记本在校园 WiFi http://193.167.0.37:8770 校园局域网,最快,不经过任何中继
连 Jetson 自己的热点 http://10.42.0.1:8770 校园网挂了也能用,Jetson 自己发的 WiFi
就在 Jetson 上 http://127.0.0.1:8770 本机浏览器

头盔里那一页是 http://100.107.145.111:8770/vr —— 安全状态在那里是 52px 大字版。但跑试验时你人应该站在机器人旁边, 用手机开主面板,头盔页是录数据时用的。

进去之后找红框的「实机试跑 POLICY TRIALS」卡片,在「实机试验 TRIALS」结果卡的上方。

⚠️ 开始之前:重启面板服务

面板上这些新东西是 8-22 加的。如果服务是更早起的,接口会返回 404、卡片不出现。

kill <pid>
cd ~/Robotic_challenge/03-software/scripts
~/miniconda3/envs/lerobot/bin/python -u robot_server.py --port 8770

确认:curl -s http://127.0.0.1:8770/api/trials 返回 JSON 而不是 404。 重启不会杀掉正在跑的作业 —— 每个作业跑在自己的进程组里、日志写文件,这是设计好的。

为什么做成面板操作 —— 理由是安全,不是方便

SAFETY.md §6 要求操作者在场、手放在急停上。 而守着一台笔记本敲终端,恰恰是最占手的姿势。一只手拿手机、另一只手放急停才是对的。

面板模式不放宽任何前提。那两条脚本查不了的确认(急停在手边、工作区无玻璃和液体), 仍然要按一次「两条都确认了」,和终端里输入 yes 是同一道门。

面板上没有急停,以后也不会有。急停是物理按钮。

三个东西分别管什么

功能什么时候看解决了什么
安全层实时状态手臂在动的那 25 秒 OK / 钳位 / 拒帧和拒帧原因原来只打在终端,戴头盔或站在机器人旁边的人根本看不到
试验看板跑完之后 原来 10 次跑完只能自己 cat json
质量回报伴随录数据时,跟这次试跑无关 「每录 10 集回报一次」原来要自己另开终端,戴头盔时开不了,等于从没生效过。现在跟着录制自动起停

安全状态那四个词

显示含义你该怎么反应
通过 OK这一帧原样发出去了正常
钳位 CLIPPED 有关节被夹回限位、或被步长上限限速,动作还是发出去了 偶发正常;一直黄要看是哪个关节
拒帧 HELD 这一帧没发,手臂重复上一条指令。下面会写具体原因 连续红 = 策略在往包络外顶,准备按急停
无信号超过 3 秒没有新帧脚本停了或崩了

陈旧优先于一切:3 秒没新帧就显示「无信号」,而不是继续挂着最后那个状态 —— 面板上挂一个过时的绿色 OK,比什么都不显示更危险。

一步步做

第 0 步 · 三条自检(约 5 分钟,不碰硬件)

PY=~/miniconda3/envs/train310/bin/python
$PY 03-software/scripts/policy_safety.py     # 必须 RESULT: PASS
$PY 03-software/scripts/run_policy_trials.py --dry
$PY 03-software/scripts/robot_profile.py

三条都过了再碰硬件。第一条会打印六种合成攻击(NaN、inf、5000°、超限位 500°、 单帧跳 60°、腕部沉到桌面下)分别被拦成什么样 —— 跑一次看一眼,那是这一层唯一的存在理由。

第 1 步 · 物理准备

  • 急停放在手边,手放上去
  • 工作区清掉玻璃器皿和液体
  • 杯子摆在 120–175 mm 中段
  • 另开一个终端放 base_watchdog.py,全程开着
  • ⚠️ 换过夹爪的话:先跑完 measure_table.py; 而且这批数据只能当「新爪基线」,不能和旧数据比

第 2 步起 · 全部在面板上

手机打开 http://100.107.145.111:8770, 找红框的「实机试跑 POLICY TRIALS」卡(在试验结果卡上方)。

1
▶ 空跑 1 次(手臂不动)

没有 --send 时脚本连 send_action 都到不了 —— 它连、它推理、它过安全层,什么都不发。这一步就是给你熟悉按钮位置的。

看这次的统计:拒帧比例高 → 策略在往包络外顶,别往下走,先查是杯子位置还是包络; 钳位比例高 → 多半是步长上限在限速,正常。

2
▶ 实跑 10 次(手臂会动)

弹确认框,列出三条前提。

3
两条都确认了,开始

急停在手边、工作区无玻璃和液体。这一步不能跳。

4
摆好杯子 → 点 ▶ 开始这一次
5
手臂跑最多 25 秒 —— 盯着安全状态条

要停就按物理急停,别等脚本自己中止。脚本会在连续 15 帧(半秒)被拒时自动中止, 但半秒也够撞上去了。

6
判定:✅ 成功 ❌ 失败 — 不计

「不计」用于摆放或你自己操作失误。它不进成功率的分母

7
回到第 4 步,直到 10 次跑完

结果自动写进 05-training/trials/trials-<时间戳>.json, 面板下方的 TRIALS 卡会自动出现这一轮,不用刷新

整个过程底下常驻一个 ⏹ 中止全部试验。 按钮是跟着脚本走的 —— 脚本把「现在等什么」写进状态,面板据此只显示该按的那几个, 不会一次摆一排让你猜。

做这个时抓到并修掉的一个 bug

等待期间脚本不发帧,3 秒后面板就判定「无信号」,把按钮全部收起来 —— 而摆一次杯子远不止 3 秒。加了每秒心跳,实测 7 秒等待期间帧龄稳定在 1.0s。

另一个:实时发布第一版写成了 v.reason(真实字段是 v.reasons,列表),属性错误被安全层的静默兜底 except Exception: pass 完全吞掉 —— 自检照样 PASS,文件却一个字节没写。 是冒烟测试抓出来的,不是自检。那层静默兜底是对的(不能因为写日志失败而改变手臂行为), 但代价就是它永远不会告诉你它坏了。