- v1(2026-10-17 20:06,
40af3b4):模型一次生成整条 32 点路径,失败回落到原规划器("有老师部署")。- v1.1(20:25,
c51f8f9):加入后训练挖错循环。- v2(本稿):按用户决定改为 无老师部署 + 每个控制周期重算(闭环),删除全部"回落原规划器"设计; 加入具身智能领域主流做法的调研与对比(§1–§2),并据此调整模型输出、后训练方法和验收标准。
- 基于
main@3c7c814(贴立柱修复后的规划器)。本文只是方案,代码尚未编写。- 审查重点:§0 定位、§2 差异与优化、§5 输出表示、§7 后训练(APG)、§8 闭环部署与安全层、§9 验收。
| 项目 | 决定 |
|---|---|
| 部署形态 | 无老师:运行时只有「神经策略 + 碰撞安全层」,不加载
IK 大表、PRM 路网、A*/RRT,也不调用 solveDyn /
routeRT |
| 运行方式 | 闭环滚动重算(MPC 式):每个控制周期(默认 50 Hz,20 ms)读当前关节角和目标,重新推理一段短动作块,只执行最前面一小段,下一周期再算。某一周期算错,下一周期有机会纠正 |
| 碰撞安全层 | 保留。它不是老师:不做搜索,只对模型给出的下一小段做胶囊碰撞检查(已有
collideFree + 包围球预筛),不安全就换候选或刹停 |
| 老师的角色 | 只在离线训练时出现:生成预训练数据。后训练阶段用可微碰撞代价(§7),基本不再需要老师 |
| 不做的事 | 不学动力学(速度/加速度上限由插补器保证);不用相机/点云(环境固定:台架 + P01 立柱,几何已知) |
| 收益目标 | 冷启动(新目标到第一个动作)< 10 ms;每周期推理 + 安全检查 < 10 ms;拖拽重规划 P99(现状约 321 ms)不再存在 |
| 底线 | 实时拖拽碰撞帧 = 0(安全层保证);到达率、行程在 §9 的指标上不低于现有规划器 |
为什么安全层必须保留:调研里最好的神经运动策略在静态场景里仍有约 10% 的轨迹发生碰撞(§1 DRP 附录表 6、ELMP 表 I)。 我们的环境几何完全已知、检查只要几毫秒,保留它代价极小,却把"偶尔撞一下"变成"偶尔停一下"。
以下数据均来自论文原文(链接见 §13)。
| 工作 | 年份 / 会议 | 输入 | 输出 | 老师与数据量 | 关键做法 | 运行方式 |
|---|---|---|---|---|---|---|
| MπNets(NVIDIA) | 2022 CoRL | 点云 + 当前关节角 + 目标位姿 | 下一步关节位置 | 规划器生成 300 万+ 问题、50 万+ 环境;8×V100 训练一周 | 端到端行为克隆 | 闭环 9 Hz,每次执行约 70% 推出的路径,1 kHz PD 跟踪 |
| Neural MP(CMU) | 2024 / IROS 2025 | 点云 + 关节角 + 目标 | GMM(LSTM) | AIT* 等,100 万–300 万条 | 测试时优化(TTO):采样多条,选与场景穿透最少的 | 开环为主;冷启动约 2970 ms |
| MπFormer / Avoid Everything(NVIDIA) | 2024 CoRL WS | 点云 | 关节动作 | 规划器数据 | 师生微调 + 困难负样本挖掘 | 闭环 |
| DRP / IMPACT(CMU) | 2025 CoRL | 点云 + 当前关节角 + 目标关节角 | 动作块:10 步关节增量,MSE 回归 | cuRobo 生成 1000 万条;4090 训练 3 天 | ① 大规模预训练 ② 迭代师生微调(局部控制器 Geometric Fabrics 当老师,不用全局规划器,因为每步都规划太贵)③ 局部反应层 DCP-RMP 改写目标 ④ 加入"目标被挡→停在最近安全处"的数据 | 闭环;4.67 M 参数,300 Hz(4090),冷启动 3.48 ms |
| ELMP(ETH) | 2026 arXiv | 点云 + 关节角 + 目标位姿(12 维) | 关节增量 | AIT* 约 60 万条 | 行为克隆后做 APG 微调:可微运动学展开,碰撞/到达/平滑三项损失直接反传,不再需要老师数据 | MPC 式闭环 30 Hz;冷启动 7.8 ms |
| Diffusion Policy / ACT 一类 | 2023– | 视觉 + 本体 | 动作块(扩散 / CVAE) | 人类示教 | 动作块 + 滚动执行(receding horizon)+ 时间集成 | 闭环 |
几个关键数字:
行业共识:
| 条件 | 主流(DRP/ELMP 等) | 本项目 | 意味着 |
|---|---|---|---|
| 环境 | 未知、多变,靠点云感知 | 固定且精确已知(台架 + 立柱,1936 个胶囊) | 不需要点云编码器;模型可以小很多;碰撞检查是精确的 |
| 机器人 | Franka 7 轴 | 自研 6 轴,J1/J3/J6 连续转 | 需处理连续轴展开 |
| 碰撞模型 | SDF / 球近似,有感知噪声 | 胶囊解析距离,可微 | 可以直接做 APG;安全层可信 |
| 运行平台 | 台式 GPU | 浏览器(后续真机) | 模型要小,ONNX + WebGPU/wasm |
结论:我们的问题比主流窄得多也"干净"得多,主流用来对付感知噪声和环境泛化的大部分复杂度(点云、千万级数据、多环境)都可以省掉,资源应投在闭环稳定性、多解选择和安全层上。
| # | v1 做法 | 主流做法 | v2 调整 | 理由 |
|---|---|---|---|---|
| 1 | 一次生成整条 32 点路径,开环执行 | 闭环 + 短动作块滚动执行 | 改为动作块策略:每周期输出未来 16 步(320 ms),只执行前 2–4 步 | 用户要求每周期重算;可纠错、可应对拖拽目标变化 |
| 2 | 失败回落原规划器 | 无回落;靠后训练提升 + 局部反应/检查 | 删除回落,改为安全层:换候选 → 刹停保持 → 下周期重算 | 用户决定无老师部署 |
| 3 | 512 桶离散化 + 自回归 186 token | DRP 用 MSE 回归动作块;Neural MP 用 GMM | K 个模式的动作块头(K=4)+ 模式分类,非自回归一次前向 | 闭环下多峰主要出现在"刚出发选左绕还是右绕",K 模式足够;一次前向比 186 步自回归快一个数量级 |
| 4 | 以目标位姿为条件 | DRP 用目标关节角(IK 另算);ELMP 用目标位姿 | 用目标位姿(位置 + 6D 旋转 + 模式标志),末段可选局部牛顿精修 | 无老师就没有全量 IK;位姿条件让模型连 IK 一起学。局部牛顿精修只是梯度下降几步,不属于搜索 |
| 5 | 后训练:挖错 + 老师重标(每轮 1–2 小时老师计算) | DRP:便宜局部老师;ELMP:APG 无老师 | 主力换成 APG(可微胶囊碰撞),挖错循环保留但不再需要老师重标 | 我们的胶囊模型可微且精确,正好适合 APG;省掉绝大部分老师计算 |
| 6 | 拒判头(REJECT) | DRP:目标被挡时学会"停在最近安全处" | 改为"停靠"行为:目标不可达时,数据里老师路径停在离目标最近的安全位形 | 闭环下"停在最近处"比"拒绝"更有用(目标常在拖拽中短暂进入立柱区) |
| 7 | 20 万条老师数据 | 主流百万–千万条,但它们要泛化到任意环境 | 降到 5 万条(+ 切片增广),其余靠 APG | ELMP 显示 APG 下 1 万条已胜过 60 万条纯克隆;我们的环境固定,需求更小 |
| 8 | 无 | DRP 的 DCP-RMP 局部反应层 | 暂不做;安全层已覆盖静态环境。未来真机有人/动态障碍时再加 | 当前环境静态 |
segSegDist
的可微版本),训练和部署检查同一套几何,消除"训练用球、检查用网格"的口径差(ELMP
的做法有这个差)。| 阶段 | 在哪里跑 | 说明 |
|---|---|---|
| 预训练数据生成 | Hark 沙箱(2 vCPU / 7 GB,Node)或用户机器 | 纯 JS,无需 GPU |
| 预训练 + APG 微调 | 用户的 GPU 机器 | 沙箱无 GPU、无 PyTorch。建议 ≥ 8 GB 显存(RTX 3060 级别) |
| 部署推理 | 浏览器(onnxruntime-web,WebGPU 优先,wasm 兜底);后续真机控制器 | 与现有查看器同页 |
conda create -n armtf python=3.11 -y && conda activate armtf
pip install torch --index-url https://download.pytorch.org/whl/cu121 # 按本机 CUDA 版本选
pip install numpy pyarrow tqdm tensorboard onnx onnxruntime| 文件 | 作用 |
|---|---|
ml/gen/gen_dataset.cjs |
采样任务 → 调老师 → 校验 → 时间参数化 → 写分片 |
ml/gen/sampler.cjs |
起点/目标采样(4.3) |
ml/gen/run_parallel.sh |
多进程,不同种子 |
ml/data/shard_XXXX.jsonl |
原始样本(不入库) |
复用 tests/route_bench_setup.cjs
装配求解器(关节表、docs/travel.json、docs/collide.json)。
{
"id": "s0003_000127", "mode": "pos" | "pose",
"q0": [6], "T": [x,y,z], "R": [[3x3]] | null, "tool": 0,
"path": [[6], ...], // 老师折线 q0 → via... → q_end
"reached": true, // false = 目标不可达,q_end 为离目标最近的安全位形("停靠")
"travel_deg": 123.4, "plan_ms": 812.0,
"fp": "collide.json 指纹"
}关节限位(docs/travel.json):J1/J3/J6 连续 ±180°;J2
[−92, 9],J4 [−111, 16],J5 [−93, 34]。
| 类别 | 占比 | 采样方式 |
|---|---|---|
| A 均匀 | 45% | q0、目标位形 b 均匀采样且无干涉;目标 = fk(b)(pose
模式加 orient(b)) |
| B 直线被挡 | 30% | q0→b 关节直线 1° 细验有干涉(route_bench 口径) |
| C 贴立柱 | 15% | b 满足 nearColumn,q0 在立柱另一侧(near_column_bench
口径) |
| D 目标不可达 | 10% | 目标在立柱内/所有分支都撞/工作空间外;老师标签 = 停在离目标最近的安全位形 |
solveDyn(松手口径)。poseRelaxed 样本只当 pos 模式用。routeRT 1.5
倍的视为绕远(先统计,再定是否丢弃)。闭环策略学的是"在某个状态下,接下来 16 步怎么走",所以要把整条路径切成很多个"状态 → 动作块"样本:
animTo 的轴速比
VREL = [0.6, 0.6, 0.9, 0.9, 1.2, 1.8]
做时间参数化(与查看器动画同口径),控制周期 dt = 20
ms。solveDyn 约 0.7 s/条:5 万条在沙箱 2 进程约 5
小时;用户 8 核机器约 1.5 小时。文件 ml/prep/build_dataset.py →
train/val/test.parquet、norm.json。
| 量 | 维度 | 编码 |
|---|---|---|
| 当前 q_t | 6 | 每轴 (sin, cos) → 12;限位轴另加归一化值 → +3 |
| 当前 TCP 位置与姿态 | 3 + 6 | fk(q_t)、orient(q_t) 的 6D
表示(给模型笛卡尔线索) |
| 目标位置 T | 3 | /600 mm |
| 目标姿态 R | 6 | 6D 表示;pos 模式填 0 |
| 目标 − 当前 TCP | 3 | 位置差,/600 mm |
| 模式 | 2 | one-hot [pos, pose] |
| 上一周期选的模式 k_prev | K+1 | one-hot(含"无"),用于模式粘滞 |
| 关键胶囊对最小距离 | 8 | 当前位形下臂各段到立柱的胶囊距离(cheap,现成函数),给模型"离柱子多近"的直接信号 |
J1/J3/J6 统一用 unwrapTo
口径展开后再做增量;预处理和部署共用一份实现,§6.4 对拍时一并验证。
条件特征(约 60 维)──MLP──▶ 8 个条件 token (d=192)
│
4 层 Transformer encoder
│ (memory)
K×16 个可学习动作 token ──▶ 4 层 Transformer decoder(非自回归,一次前向)
│
├─ 动作头:每 token 输出 6 维 Δq
├─ 模式分类头:K=4
└─ 剩余时间头:1
| 超参 | 值 |
|---|---|
| d_model / 头数 / FFN | 192 / 8 / 768 |
| encoder / decoder 层数 | 4 / 4 |
| 参数量 | 约 3–4 M(DRP 为 4.67 M,含点云编码) |
| 推理 | 一次前向得到 4 条候选动作块 |
L = WTA-L1(动作块, 最近模式) 权重 1.0
+ CE(模式分类) 权重 0.5
+ FK 损失:预测与标签位形下各连杆胶囊端点的位置差 权重 0.5 ← 借鉴 ELMP
+ 平滑:二阶差分 权重 0.05
+ L1(剩余时间) 权重 0.1
| 项 | 值 |
|---|---|
| 优化器 | AdamW,β=(0.9, 0.95),wd 0.01 |
| 学习率 | 1e-3,预热 1000 步,余弦退火(同 DRP 量级) |
| batch | 512 |
| 精度 | bf16 混合精度 |
| 步数 | 约 20 万步(300 万样本约 30 epoch),验证集闭环成功率不再上升即停 |
| 预计耗时 | RTX 3060 约 3–5 小时(估算,跑完首轮校正) |
ml/eval/collide_torch.py:胶囊距离的 PyTorch
批量版(可微,§7 要用),先与 JS
collideFree 对拍 10 万个位形,判定 0 误差。不再请老师标注,直接让模型在可微仿真里闭环展开,用代价反传:
for 每个 batch(随机采样 q0 和目标,82 ms 级别的便宜采样,不需要老师):
q = q0
for t in 0..H-1 (H = 60 个周期 ≈ 1.2 s,长任务分段展开):
chunk, logits = π(obs(q, 目标))
Δq = chunk[选中模式][0:3] # 执行前 3 步,与部署一致
q = clamp(q + Δq) # 限位
累计 L_col(q), L_smooth(Δq)
L = w_tgt·L_target(q_H) + w_col·ΣL_col + w_smooth·ΣL_smooth (+ w_len·行程)
反传(BPTT),梯度裁剪 ≤ 1.0
collide.json 的 margin_mm
基础上再加 5 mm 训练余量;包含臂×立柱、臂×台架、臂×臂(非相邻段)。每轮:
对每个任务采样多条闭环轨迹(不同模式、不同温度),只保留验算通过且最短的一条做行为克隆标签——模型自己当老师。适合 APG 收敛后进一步缩短行程。
每 20 ms:
1. 读当前 q(真机读编码器;查看器读当前插补位形)和最新目标(拖拽时每周期都在变)
2. 推理一次:得到 K=4 条 16 步动作块 + 模式概率 ≈ 2–5 ms(估算)
3. 按"模式概率 − 切换代价"排序(§8.2)
4. 安全层依次检查候选的前 n=3 步(60 ms 的运动)+ 刹停段(§8.3)
第一个通过的 → 送插补器执行这 3 步;记下 k_prev
5. 全部不通过 → 进入刹停:按已验证的刹停轨迹减速停下,保持;下一周期继续推理
6. 到达判据:TCP 误差 < 1 mm(pose 另需 < 0.5°)且速度≈0 → 结束;
接近目标(< 5 mm)时可选做 1–3 次局部牛顿精修(solveTo 单步,不是全量 IK)
插补器在两个周期之间做平滑过渡(下一块与正在执行的块做时间集成/交叉淡入,ACT 的 temporal ensembling 思路),避免每 20 ms 一顿。
pathFine 同口径),外加关节限位。ik-glue.js
的"每帧碰撞守卫"保留,作为第二道保险。| 有 | 没有 |
|---|---|
traj_v2.onnx(fp16,约 7 MB)+
norm.json |
PRM 路网(collide.json.roadmap)、IK 候选大表 |
胶囊碰撞检查(现有
collideFree、包围球预筛、pair2d 表) |
solveDyn / routeRT / RRT / A* |
正运动学 fk / orient、局部牛顿精修
solveTo 单步 |
全量 IK 枚举 |
collide.json
指纹写进模型;不一致时前端拒绝运行并提示重训(不再回落旧规划器)。
| 集合 | 来源 |
|---|---|
| route_bench | tests/route_bench.cjs,60 例 |
| near_column_bench | tests/near_column_bench.cjs,30 例(pos / pose /
rt) |
| rt_drag_bench | tests/rt_drag_bench.cjs,12
例(改为模型在环逐周期运行) |
| held-out | §4.3 留出 2000 条 |
新增 tests/policy_bench.cjs:①现有规划器
②策略(关安全层)③策略 + 安全层(部署形态),输出对比表。
| 指标 | 要求 | 现状参考 |
|---|---|---|
| 实际执行的碰撞帧 | = 0 | rt_drag_bench 0 |
| 到达率(6 s 内) | route ≥ 60/60,near pos ≥ 29/30,near rt ≥ 29/30,held-out ≥ 97% | 60/60、30/30、30/30 |
| 关节行程 | ≤ 现有规划器 × 1.10 | route 平均 467° |
| 冷启动(新目标→第一个动作) | < 10 ms | 首次全量 IK 最差约 2 s |
| 每周期耗时(推理+安全层)P99 | < 15 ms | 拖拽重规划 P99 约 321 ms |
| 刹停发生率 | < 2% 的周期 | — |
| 模式摇摆(≥3 次切换) | < 1% 的任务 | — |
| 策略单独(关安全层)碰撞率 | < 3%(参考:ELMP-APG 8.9%,DRP 10.16%) | — |
说明:允许 near_column 少 1 例,因为无老师时最难的贴柱案例可能要靠多次刹停-重算才能到达,6 s 超时内可能失败;这一条请审查时确认能否接受。
ci27
姿态根枚举漏分支(姿态偏差约 97.5°)会进入预训练数据;APG
的姿态到达项可以部分纠正,必要时先修老师。ml/
gen/ gen_dataset.cjs sampler.cjs run_parallel.sh
data/ (不入库)shard_*.jsonl stats.json *.parquet norm.json
prep/ build_dataset.py
model/ policy_transformer.py
sim/ closed_loop.py # 闭环仿真(训练验证、挖错、APG 展开共用)
eval/ collide_torch.py # 可微胶囊距离,与 JS 对拍
apg/ apg_finetune.py
mining/ mine_round.py gate.py loop.sh
configs/ base.yaml apg.yaml
train.py export_onnx.py README.md
webapp/js/ik-policy.js # 闭环推理 + 模式粘滞 + 安全层 + 刹停
webapp/models/traj_v2.onnx traj_v2.norm.json
tests/policy_bench.cjs
| # | 内容 | 产出 | 在哪跑 |
|---|---|---|---|
| M1 | 数据生成器 + 时间参数化 + 1000 条试跑 | ml/gen/*、stats.json |
沙箱 |
| M2 | 可微胶囊距离(PyTorch)与 JS 对拍 | collide_torch.py,10 万位形 0 误差 |
沙箱(CPU 即可) |
| M3 | 5 万条老师数据 → 约 300 万闭环样本 | Parquet | 沙箱约 5 h 或用户机器 |
| M4 | 模型 + 训练工程 + 闭环仿真;小数据过拟合测试 | train.py、closed_loop.py |
沙箱 CPU 验证可跑 |
| M5 | 预训练(行为克隆) | checkpoint | 用户 GPU |
| M6 | APG 微调 + 挖错循环 3–6 轮 | 每轮 report.md | 用户 GPU |
| M7 | 导出 ONNX + ik-policy.js 闭环部署 + 安全层实测 +
policy_bench |
对比表 | 沙箱 + 浏览器 |
| M8 | 移除查看器里对
solveDyn/routeRT/路网的运行时依赖(保留在
ml/gen 离线使用) |
部署包瘦身 | 沙箱 |