diff --git a/docs/Transformer轨迹拟合训练方案.html b/docs/Transformer轨迹拟合训练方案.html
new file mode 100644
index 0000000..3e794e8
--- /dev/null
+++ b/docs/Transformer轨迹拟合训练方案.html
@@ -0,0 +1,1706 @@
+
+
+
+
+
+
+ Transformer 避障运动策略:最终方案
+
+
+
+
+
+
+
+
+基于
+main@3c7c814(贴立柱修复后的规划器)。本文是方案,代码尚未编写。
+训练机:RTX 3090 24 GB。部署:浏览器(后续真机)。
+
+
+0. 定位与边界
+
+
+
+
+
+
+| 部署形态 |
+无运行时老师:运行时只有「神经策略 +
+碰撞安全层」,不加载 IK 大表、PRM 路网、A*/RRT,也不调用
+solveDyn / routeRT |
+
+
+| 运行方式 |
+闭环滚动执行:执行频率 50 Hz(每步 20 ms);每 60
+ms 读一次当前关节角和目标,推理一段 16 步动作块,安全层认证后提交前 3
+步 |
+
+
+| 碰撞安全层 |
+不做搜索,只对模型给出的候选做距离下界认证(§8.3),不安全就换候选或沿已认证刹停段停下 |
+
+
+| 老师的角色 |
+只在离线出现:生成预训练数据;后训练以可微碰撞代价为主(§7) |
+
+
+| 不做的事 |
+不学动力学(速度/加速度上限由时间律与插补器保证);不用相机/点云(环境固定:台架
++ P01 立柱,几何已知) |
+
+
+| 收益目标 |
+冷启动(新目标到第一个动作)< 10 ms;每次推理 + 安全认证 < 20
+ms;消除现有拖拽重规划 P99 约 321 ms 的长尾 |
+
+
+| 底线 |
+实时拖拽碰撞帧 =
+0(由安全层距离认证保证);到达率、行程在 §9
+指标上不低于现有规划器 |
+
+
+
+关于"风险":
+论文证据只能说明"别人在相近条件下做成过",没有一篇论文的条件(低维状态、单根固定立柱、约
+4M
+参数、浏览器推理、30/30)与本项目完全一致。因此本方案中只有安全层是硬保证;每个设计点都已定为唯一选择(§1.1),只有
+MeanFlow
+头带一个预先写定触发条件的回退(碰撞与否不依赖模型好坏);其余每一项都配有证据等级、本仓库可测的门禁(不过不进下一步)和回退(§10)。
+
+1. 方案总览
+
+
+
+
+
+
+| 模型规模 |
+约 4.1M 参数编码器-解码器 Transformer,不用 VLA 大模型 |
+A |
+IMPACT 4.67M、300 Hz;π0 3B 单次预填充 46 ms(4090) |
+
+
+| 数据 |
+规划器离线造 5 万条任务 → 约 200 万"状态→动作块"样本 |
+B |
+MπNets、DRP、ELMP 均用规划器老师 |
+
+
+| 时间律 |
+匀速巡航 + 梯形加减速,只依赖"当前速度 +
+剩余路程";当前速度作输入 |
+B |
+MπNets 将老师路径重定时为匀速 |
+
+
+| 动作表示 |
+16 步 × 6 轴关节增量 Δq |
+A |
+DRP;Diffusion Policy(位置式优于速度式) |
+
+
+| 动作头 |
+MeanFlow 一步生成头,每次并行采 8 个噪声 → 8
+条候选 |
+B |
+沙箱双模态实验(§2.4);MP1 约 6.8 ms |
+
+
+| 块间连续 |
+训练时前缀条件化:输入已提交未执行的步 |
+B |
+2512.05964:推理零开销,d≥2 时优于推理时 RTC |
+
+
+| 碰撞修正 |
+输出后 1 步解析胶囊距离梯度投影(每轴 ≤ 0.5°,仅 d <
+余量时) |
+B |
+DiffusionSeeder:少步生成下在环引导收益很小;投影在已知环境下够用 |
+
+
+| 候选排序 |
+与已提交块重叠步的一致性打分 + 价值头 |
+B |
+BID:一致性打分 + 多样本相对提升 32% |
+
+
+| 预训练 |
+行为克隆 + FK 胶囊端点损失 |
+B |
+ELMP 式 FK 损失 |
+
+
+| 后训练(主) |
+APG:可微运动学展开 + 胶囊距离代价反传 |
+A |
+ELMP:碰撞率 31.3%→8.9%;1 万示范 + APG 胜 60 万纯 BC |
+
+
+| 后训练(辅) |
+无老师挖错循环 + 门禁 |
+B |
+DRP 迭代微调 +45% |
+
+
+| 安全层 |
+距离下界认证 + 可刹停不变式 |
+A |
+Schwarzer 2005 连续认证;Thumm & Althoff 2022 failsafe |
+
+
+| 30/30 手段 |
+子目标头、价值头、冷启动/卡死时短前瞻、卡死换向 |
+B / C |
+AWE、SHAC、BID |
+
+
+| 老师 |
+PRM 路网 A* + 捷径平滑(确定性);A* 失败才用
+solveDyn |
+B |
+MπNets:老师不一致碰撞率 13.78%,一致老师 0.94% |
+
+
+| 推理后端 |
+onnxruntime-web wasm-SIMD 多线程 |
+C |
+小模型下 WebGPU 调度开销占主导 |
+
+
+
+1.1
+取舍决定(每项只有一个答案)
+
+
+
+
+
+
+| 动作头:MeanFlow 一步头 vs WTA K=4 |
+MeanFlow:连续多模态,能同时表达左/右绕行与位姿目标的多个 IK
+分支;沙箱 1 步达到 10 步流匹配质量。WTA:训练稳、实现简单 |
+MeanFlow:训练需 JVP(训练慢约 1.5–2
+倍)、原生版本在部分任务失败(K-MF 表 1)。WTA:只有 4 个固定模式,左右
+× 肘/腕分支可能超过 4 个;沙箱分不出两者高下 |
+上 MeanFlow。WTA 不实现;只有 M5
+门禁不过(near_column 穿柱率高于 2% 或训练发散)才换成 WTA
+K=8,二者共用骨干,切换约 1 天 |
+
+
+| Shortcut + 条件 OT 配对 |
+无需 JVP |
+本项目无任何实测,组合无论文先例 |
+不上 |
+
+
+| B 样条动作表示 |
+平滑由表示保证;输出维度小 |
+贴柱时拐角被抹圆、局部精度下降;只有间接证据;平滑已由梯形时间律 +
+平滑损失保证 |
+不上,固定 16 步 Δq |
+
+
+| 输出后梯度投影 |
+修掉 1–2 mm 的轻微侵入,成本约 0.1 ms,减少刹停 |
+推离数据分布、改变块间一致性;修不了"绕错侧" |
+上,限 1 步、每轴修正量 ≤ 0.5°,仅 d <
+余量时触发 |
+
+
+| 短前瞻(多推一块打分) |
+避开"走两步就撞墙"的分支 |
+推理次数翻倍,加剧最大不确定项(浏览器延迟) |
+只在冷启动和卡死换向时上,平时不做 |
+
+
+| 拒绝采样自蒸馏 |
+进一步缩短行程 |
+偏向贴柱、余量变小、多样性塌缩;APG 行程项已覆盖同一目标 |
+不上 |
+
+
+| ReinFlow 强化学习微调 |
+能直接优化到达/卡死/刹停等离散目标 |
+RL
+会重塑左右模式比例;奖励调参与训练多出数天;这些离散目标已由卡死换向规则
++ APG 覆盖 |
+不上 |
+
+
+| 挖错循环中 E2 错题请老师补路径 |
+解决可微代价绕不出的局部极小 |
+量小、离线 |
+上 |
+
+
+老师:PRM 路网 A* vs solveDyn |
+A*:确定性,同类任务左右选择一致,且是路网上的最短;solveDyn
+覆盖更全 |
+A*:受路网分辨率限制,个别任务失败 |
+A 为主老师*,失败的任务用
+solveDyn(固定种子)补 |
+
+
+| 推理后端:WebGPU vs wasm |
+WebGPU 大模型快 |
+本模型约 4M 参数,WebGPU 每次调度 33–67 μs × 150–300
+次,调度开销反而大 |
+wasm-SIMD 多线程;M4 实测若 WebGPU P99
+更低再换 |
+
+
+| 训练余量 |
+越大越不易被认证拒绝 |
+越大行程越长、贴柱越难 |
+5 mm |
+
+
+| 关节噪声增广 σ |
+覆盖偏离状态 |
+过大产生无意义状态 |
+1° |
+
+
+| 局部牛顿精修 |
+末端精度到 < 1 mm |
+无 |
+上,同样过安全层 |
+
+
+
+证据等级:A 有直接先例与数字 · B
+有相近先例,需本仓库验证 · C 仅推断。
+
+2. 依据
+2.1 业界神经运动规划
+
+
+
+
+
+
+| MπNets(NVIDIA) |
+2022 CoRL |
+点云 + 关节角 + 目标位姿 |
+下一步关节位置 |
+规划器 300 万+ 问题 |
+端到端行为克隆;老师路径重定时为匀速 |
+闭环 9 Hz,1 kHz PD 跟踪 |
+
+
+| Neural MP(CMU) |
+2024 / IROS 2025 |
+点云 + 关节角 + 目标 |
+GMM(LSTM) |
+100 万–300 万条 |
+测试时采样多条,选穿透最少的(去掉后成功率 81%→31%) |
+开环为主 |
+
+
+| DRP / IMPACT(CMU) |
+2025 CoRL |
+点云 + 关节角 + 目标关节角 |
+10 步关节增量 |
+cuRobo 1000 万条 |
+大规模预训练 + 迭代师生微调 + "目标被挡停在最近安全处" |
+闭环;4.67M 参数,300 Hz |
+
+
+| ELMP(ETH) |
+2026 arXiv |
+点云 + 关节角 + 目标位姿 |
+关节增量 |
+AIT* 约 60 万条 |
+行为克隆后 APG
+微调,碰撞/到达/平滑损失直接反传 |
+闭环 30 Hz |
+
+
+
+
+- ELMP:1 万条老师轨迹 + APG(成功率 72.0%)超过 60
+万条纯行为克隆(57.9%);APG 把碰撞率降到 1/3 以下。
+- 最好的方法在静态场景仍有约 9–10% 碰撞(ELMP-APG 8.9%,DRP
+10.16%),实际部署都配检查或反应层。
+- 共识:闭环、短动作块滚动执行、老师只离线用、必须后训练。
+
+2.2 本项目的条件
+
+
+
+
+
+
+| 环境 |
+未知、多变,靠点云 |
+固定且精确已知(台架 + 立柱,1936 个胶囊) |
+不需要点云编码器;模型可以小;碰撞检查精确 |
+
+
+| 机器人 |
+Franka 7 轴 |
+自研 6 轴,J1/J3/J6 连续转 |
+需处理连续轴展开 |
+
+
+| 碰撞模型 |
+SDF / 球近似 |
+胶囊解析距离,可微 |
+直接做 APG;安全层可认证 |
+
+
+| 平台 |
+台式 GPU |
+浏览器(后续真机) |
+模型小,ONNX + WebGPU/wasm |
+
+
+
+资源应投在闭环稳定性、左右绕行选择和安全层上,而不是感知和泛化。
+2.3 前沿生成式技术取舍
+
+
+
+
+
+
+| VLA 大模型(π0/π0.5、GR00T、OpenVLA) |
+不采用 |
+无图像、无语言指令;3B 参数更慢不更准 |
+
+
+| 一步生成:MeanFlow(MP1) |
+采用 |
+1 次前向;沙箱双模态实验通过 |
+
+
+| Consistency Policy、OneDP、朴素 1 步流匹配 |
+不采用 |
+CP 原文承认偏向一侧;OneDP 有意取单模态;朴素 1 步 FM
+等于条件均值,会穿柱 |
+
+
+| Shortcut / 条件 OT 配对 |
+不采用 |
+见 §1.1 |
+
+
+| OFP 自蒸馏 |
+不采用 |
+未找到公开代码;自引导 λ=0.5 时出现模态塌缩 |
+
+
+| 生成过程中代价引导(MPD/EDMP/GPD) |
+不采用 |
+无论文在 1–2 步下验证;改用输出后投影 |
+
+
+| 推理时 RTC |
+不采用 |
+原文只验证 5 步去噪且需反向传播;改用训练时前缀条件化 |
+
+
+| 时间集成 / 交叉淡入 |
+不采用 |
+执行的是未认证的混合块;左右两块平均可能穿柱;π0 弃用 |
+
+
+| FAST 动作分词 |
+不采用 |
+服务于语言骨干,自回归推理慢 |
+
+
+| B 样条动作表示 |
+不采用 |
+见 §1.1 |
+
+
+| ReinFlow / DPPO |
+不采用 |
+见 §1.1 |
+
+
+
+2.4 沙箱双模态对照实验
+2D 点从柱左侧到右侧,示教一半从上绕一半从下绕,16 步动作块、每 3
+步重推理,与本方案同构。代码 ml/toy/toy_bimodal.py,150
+个"起终点都贴近中轴"的难例:
+
+
+
+
+
+
+| MSE 回归 |
+100% / 0% |
+100% / 0% / 0 |
+0.13 ms |
+
+
+| WTA K=4 |
+100% / 0% |
+100% / 0% / 0 |
+0.19 ms |
+
+
+| 流匹配 10 步 |
+100% / 4.0% |
+99.3% / 0% / 3.7 |
+2.13 ms |
+
+
+| 朴素流匹配 1 步 |
+87.3% / 23.3% |
+81.3% / 0% / 14.0 |
+0.25 ms |
+
+
+| MeanFlow 1 步 |
+100% / 2.7% |
+100% / 0% / 0.3 |
+0.25 ms |
+
+
+
+
+- 朴素 1 步流匹配会把模态平均进柱子;MeanFlow 1 步达到 10
+步流匹配的质量,推理快约 8 倍。
+- 安全层在所有方法上把穿柱降为 0,代价是刹停。
+- 该任务过于简单(闭环中状态一偏离中轴即打破对称),分不出一步头与
+WTA 谁更好;因此 WTA 只作为 M5
+门禁不过时的预定回退(§1.1)。
+- 训练仅 300 步的 MSE 在同一难例上 100% 穿柱、加安全层后 0%
+到达,说明欠拟合时平均模态的风险真实存在。
+
+
+3. 训练环境
+
+
+
+
+
+
+| 数据生成 |
+Hark 沙箱(2 vCPU / 7 GB,Node)或用户机器 |
+纯 JS,无需 GPU |
+
+
+| 预训练 + 后训练 |
+用户 RTX 3090 24 GB |
+batch 1024–2048 |
+
+
+| 部署推理 |
+浏览器 onnxruntime-web wasm-SIMD 多线程;后续真机控制器 |
+与现有查看器同页 |
+
+
+
+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
+
+4. 离线数据(老师只在这里出现)
+4.1 文件
+
+
+
+
+
+
+ml/gen/gen_dataset.cjs |
+采样任务 → 调老师 → 校验 → 时间参数化 → 写分片 |
+
+
+ml/gen/sampler.cjs |
+起点/目标采样 |
+
+
+ml/gen/run_parallel.sh |
+多进程,不同种子 |
+
+
+ml/data/shard_XXXX.jsonl |
+原始样本(不入库) |
+
+
+
+复用 tests/route_bench_setup.cjs
+装配求解器(关节表、docs/travel.json、docs/collide.json)。
+4.2 原始样本
+{
+ "id": "s0003_000127", "mode": "pos" | "pose",
+ "q0": [6], "T": [x,y,z], "R": [[3x3]] | null, "tool": 0,
+ "path": [[6], ...],
+ "reached": true,
+ "travel_deg": 123.4, "plan_ms": 812.0,
+ "fp": "collide.json 指纹"
+}
+reached=false
+表示目标不可达,路径终点为离目标最近的安全位形("停靠")。
+4.3 采样分布(5 万条任务)
+关节限位: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 关节直线有干涉 |
+
+
+| C 贴立柱 |
+15% |
+b 满足 nearColumn,q0 在立柱另一侧 |
+
+
+| D 目标不可达 |
+10% |
+目标在立柱内/所有分支都撞/工作空间外;标签为停靠 |
+
+
+
+
+- pos / pose 各半;老师为 PRM 路网 A* + 捷径平滑(确定性;复用
+
routeRT 的路网图搜索,放宽时间预算);A* 失败的任务用
+solveDyn(固定种子)补。
+- 另造三个互不重叠的集合:门禁集 2000
+条(挖错循环每轮用)、held-out 验收集 2000
+条、near_column 扩展验收集 ≥1000
+条;两个验收集只在最终验收时用一次。现有三个基准不进训练集。
+
+4.4 过滤
+
+- 整条路径用距离下界认证(与 §8.3 同口径)复核,任一段不过即丢弃。仓库
+
tests/route_bench.cjs 上现有规划器有 1/40
+例路径细验不过,这类样本必须丢掉。
+poseRelaxed 样本只当 pos 模式用。
+- 行程 > 同任务
routeRT 1.5
+倍的先统计,再定是否丢弃;按类别统计丢弃率(C 类 > 20%
+说明老师在贴柱场景不可靠)。
+
+4.5 时间参数化 → 闭环训练样本
+
+- 时间律:按轴速比
VREL = [0.6, 0.6, 0.9, 0.9, 1.2, 1.8]
+匀速巡航,梯形加减速,速度只取决于"当前速度 + 剩余路程"(每轴加速度上限
+a_max 为待定参数,真机型号确定后设定),dt = 20 ms。
+- 得到状态序列 q_0 … q_N,每隔 3 步取一个样本:
+
+- 输入:§5.1 全部字段(含当前速度、已提交前缀)
+- 标签:未来 16 步 Δq_{t+k} = q_{t+k} − q_t(到终点后补零)
+
+- 每条路径约 40–50 个样本 → 约 200 万样本(以
stats.json
+为准)。
+- 协变量偏移对策:关节噪声增广(σ =
+1°,噪声状态由老师离线重标);偏离状态的进一步覆盖靠 §7。
+
+4.6 耗时与存储
+
+- 路网 A* 每条数十毫秒,耗时主要在过滤认证;按
solveDyn
+0.7 s/条上限估算,沙箱 2 进程不超过 5 小时。
+- 200 万样本原始约 1 GB;Parquet 约 200 MB。
+
+4.7 检查点
+
+
+5. 表示与预处理
+文件 ml/prep/build_dataset.py →
+train/val/test.parquet、norm.json。
+5.1 输入
+
+
+
+
+
+
+| 当前 q_t |
+6 |
+每轴 (sin, cos) → 12;限位轴另加归一化值 → +3 |
+
+
+| 当前关节速度 q_t − q_{t−1} |
+6 |
+按每轴速度上限归一化 |
+
+
+| 当前 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] |
+
+
+| 已提交未执行前缀 |
+3×6 + 3 |
+前缀 Δq + 有效长度掩码;训练时随机遮盖 0–3 步 |
+
+
+| 当前子目标 |
+6 |
+子目标头输出的关节途经点(归一化);无子目标时填当前 q |
+
+
+| 关键胶囊对最小距离 |
+8 |
+臂各段到立柱的胶囊距离 |
+
+
+
+5.2 输出
+
+- MeanFlow 一步头:每条候选 16 步 × 6 轴
+Δq(按每轴最大步长归一化)。
+- 附加头:价值头(剩余时间/代价)、子目标头(2 个关节途经点 +
+是否需要)。
+
+5.3 连续轴
+J1/J3/J6 统一用 unwrapTo
+展开后再做增量;预处理与部署共用一份实现,对拍时一并验证。
+
+6. 模型与预训练
+6.1 结构
+条件特征(约 90 维)──MLP──▶ 8 个条件 token (d=192)
+ │
+ 4 层 Transformer encoder
+ │ (memory)
+16 个动作 token(注入噪声 z + 时间嵌入 (r, t))
+ ▼
+ 4 层 Transformer decoder(非自回归,一次前向)
+ ├─ 动作输出:每 token 6 维 Δq
+ ├─ 价值头:1
+ └─ 子目标头:2 个关节途经点 + 是否需要
+
+
+
+
+
+
+| d_model / 头数 / FFN |
+192 / 8 / 768 |
+
+
+| encoder / decoder 层数 |
+4 / 4 |
+
+
+| 参数量 |
+约 4.1M |
+
+
+
+子目标触发:新目标或目标跳变 > 50 mm 时输出;到达当前子目标 <
+5° 后切下一个。
+6.2 动作头:MeanFlow 一步生成
+
+
+
+
+
+
+| 多模态 |
+连续分布;每次推理并行采 8 个噪声 → 8 条候选 |
+
+
+| 训练 |
+MeanFlow 平均速度场损失(MP1 配方:25% 样本
+r≠t,自适应损失加权),JVP 用 torch.func.jvp |
+
+
+| 推理 |
+1 次批量前向(r=0, t=1) |
+
+
+| 后处理 |
+1 步解析胶囊距离梯度投影,每轴修正 ≤ 0.5°,仅 d < 余量时(JS
+实现,不走 ONNX) |
+
+
+| APG 兼容 |
+固定噪声后为确定性可微映射 |
+
+
+| 预定回退 |
+M5 门禁不过(near_column 穿柱率 > 2% 或训练发散)→ 同骨干换 WTA
+K=8 头(WTA-L1 + 模式 CE),约 1 天 |
+
+
+
+6.3 损失
+L = MeanFlow 损失 1.0
+ + FK 损失:一步输出(固定噪声)的各连杆胶囊端点位置差 0.5
+ + 平滑:二阶差分 0.05
+ + 价值头 L1 + 子目标头 L1 0.1 / 0.1
+6.4 训练配置
+
+
+
+
+
+
+| 优化器 |
+AdamW,β=(0.9, 0.95),wd 0.01 |
+
+
+| 学习率 |
+1e-3,预热 1000 步,余弦退火 |
+
+
+| batch |
+1024 |
+
+
+| 精度 |
+bf16 混合精度 |
+
+
+| 步数 |
+先跑 2000 步测吞吐再定;参考 200 万样本 × 30 epoch ÷ 1024 ≈ 6
+万步;验证集闭环到达率不再上升即停 |
+
+
+| 预计耗时 |
+RTX 3090 约 1.5–5.6 小时(按 2000 步吞吐实测重算) |
+
+
+
+6.5 对拍与验证
+
+ml/eval/collide_torch.py:可微胶囊距离 PyTorch
+批量版,与 JS collideFree 对拍 10 万位形:布尔判定 0
+差异,距离误差 < 1e-4 mm,梯度与有限差分相对误差 < 1e-3。
+- 每 epoch 闭环验证:从 1000 个验证任务出发,按部署节奏(每 60 ms
+推理、提交 3 步)运行到到达或超时(老师路径时长 × 2,最少 3
+s),统计到达率、用时 ≤ 老师 × 1.3
+的达标率、碰撞步数(关安全层)、行程比、左/右/穿柱三类比例。
+
+
+7. 后训练
+7.1 主力:APG 可微微调
+for 每个 batch(随机采样 q0 和目标,不需要老师):
+ q = q0
+ for t in 0..H-1 (H = 60 次推理 × 3 步 = 180 步 ≈ 3.6 s;长任务分段截断反传):
+ chunk = π(obs(q, 目标, 前缀), z) # 每条展开固定一个噪声 z
+ Δq = chunk[0: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·行程) + w_bc·L_BC
+ 反传,梯度裁剪 ≤ 1.0,lr 1e-4
+
+- 碰撞项 L_col = Σ ReLU(margin − 胶囊距离),margin =
+
margin_mm + 训练余量 5
+mm(覆盖安全层认证的保守量);含臂×立柱、臂×台架、臂×臂(非相邻段)。
+- 到达项:位置误差² + λ_rot·‖R − R*‖_F²。
+- 平滑项:速度² + 加速度²。
+- BC 锚定项:保留预训练损失,防止多模态被压缩;每轮监控左右比例。
+- 采样分布同 §4.3,B/C/D 类提到 60%,其中贴柱类 40%。
+
+7.2 辅助:无老师挖错循环
+每轮:
+
+- 出题:新种子 5 万任务 + 2000 段模型在环拖拽仿真。
+- 闭环作答:完全按部署方式运行,关闭安全层以暴露真实错误。
+- 验算:GPU 批量胶囊检查。
+- 错题分类:E1 撞 / E2 没到(卡在局部极小)/ E3 绕远(> 1.2×
+参考)/ E4 末端精度差 / E5 摇摆(≥ 3 次切换)/ E6 拖拽失稳。
+- 错题及其 ±5 mm / ±3° 的 10 个邻居加入 APG 采样池(E1、E6 ×2);仅 E2
+可离线请老师补少量路径。
+- 门禁(用门禁集,不用验收集):到达率上升、A 类每轮降幅 ≤ 0.5
+个百分点、上一轮修好的错题 95% 仍对;否则回滚。
+- 停止:连续 2 轮提升 < 0.5 个百分点,或满 6 轮。
+
+
+8. 部署
+8.1 执行循环
+执行:50 Hz,每步 20 ms,按已提交步走
+每 60 ms:
+ 1. 读当前 q、当前速度、已提交未执行前缀、最新目标
+ 2. 推理:8 个噪声 → 8 条 16 步动作块(冷启动或卡死换向时,再各推一块做短前瞻)
+ 3. 每条候选做 1 步胶囊距离梯度投影(每轴 ≤ 0.5°,仅 d < 余量时)
+ 4. 排序(§8.2)
+ 5. 安全层依次认证候选前 3 步 + 刹停段(§8.3),第一个通过的提交给执行器
+ 6. 全部不通过 → 沿上一次已认证的刹停段停下,下次继续推理
+ 7. 到达:TCP 误差 < 1 mm(pose 另需 < 0.5°)且速度≈0;
+ 接近目标(< 5 mm)时做 1–3 次局部牛顿精修(solveTo 单步),精修段同样过安全层认证
+执行的始终是安全层认证过的那一块,不做新旧块混合。执行时钟放在 Web
+Worker、按实际 dt 推进,避免 requestAnimationFrame(60
+Hz)与 20 ms 不整除及后台节流造成的抖动。
+8.2 候选排序(防左右摇摆)
+分数 = −Σ w_k‖候选第 k 步 − 已提交块第 k 步‖²(重叠步加权)−
+λ·价值头剩余代价。冷启动时无已提交块,只用价值头 + 短前瞻打分。
+8.3 安全层(唯一的硬保证)
+
+- 距离下界认证:对一段运动 q_a →
+q_b,若两端到障碍的最小距离之和 d(q_a) + d(q_b) > Σ_j r_j·|Δθ_j|(r_j
+为每轴实测杠杆上界,J1 约 9.0 mm/°,六轴合计最大约 24.3
+mm/°),则整段安全;否则二分,直到全部子段通过或判不安全。臂×立柱/台架用胶囊距离;自碰撞对复用
+
pair2d 杠杆界(J3 3.24、J4 2.54 mm/°)。外加关节限位。
+- 离散采样检查(现有
pathFine,1.5° +
+半格)只作快速预筛,不作保证依据。
+- 可刹停不变式:只有当"候选前 3 步 + 从第 3
+步末按每轴 a_max
+减速到停"整段都通过认证时才提交。任何时候系统都持有一条已认证的停车路线,下一次推理即使完全失效也只会停下。
+- 耗时:每段一次距离查询覆盖整段,不通过才二分(通常 2–6
+次);按排序逐个认证,第一个通过即停;包围球预筛先行。目标每次 < 5
+ms,否则放 Web Worker 与推理流水线并行。
+ik-glue.js 的每帧碰撞守卫保留为第二道保险。
+
+8.4 部署包
+
+
+
+
+
+
+traj_policy.onnx(fp16,约 8.3 MB)+
+norm.json |
+PRM 路网、IK 候选大表 |
+
+
+胶囊距离与认证(collideFree、包围球预筛、pair2d) |
+solveDyn / routeRT / RRT / A* |
+
+
+fk / orient、局部牛顿精修
+solveTo 单步 |
+全量 IK 枚举 |
+
+
+
+collide.json
+指纹写进模型;不一致时前端拒绝运行并提示重训。
+8.5 near_column 30/30
+的保障手段
+"超时"指机械臂在规定时间内没走到目标,是决策问题而非计算速度问题。典型失效:局部极小/活锁(每次都想直穿、每次被安全层挡住)、左右摇摆、绕远。对策(运行时均不需要老师):
+
+- 子目标头:给出 1–2
+个关节途经点作为绕柱方向锚点,标签取老师路径拐点(离线)。
+- 价值头:预测剩余时间/代价,用于候选打分与进展判断;APG
+中用 TD 自举监督。
+- 短前瞻(仅冷启动和卡死换向时):对每条候选再推一块,用胶囊认证
++ 价值头给 32 步后终态打分。
+- 卡死检测 + 强制换向:0.3 s 内价值不降或连续 2
+次刹停 → 切到另一绕行方向并锁定 1 s。
+- 训练侧加强:贴柱类占 APG 采样
+40%;展开覆盖整段绕行。
+
+8.6 控制周期
+伺服层(参考):Franka FCI 1 ms;UR e-Series 2 ms、CB3 8 ms;ABB EGM
+4 ms(滞后 10–20 ms);KUKA RSI 4/12 ms;FANUC DPM 约 8 ms;MoveIt Servo
+默认 10 ms;RC 舵机 20 ms。
+策略层(参考):MπNets 9 Hz;Diffusion Policy 10 Hz、预测 16 执行
+8;ELMP 30 Hz;π0 50 Hz、约每 0.5 s 推理一次;DRP 300
+Hz。业界均为"策略层 10–50 Hz + 伺服层 125 Hz–1 kHz"两层结构。
+本方案:执行 50 Hz、每 60 ms 推理一次、提交 3 步。真机上提交步数 n ≥
+⌈(通信滞后 + 一次推理最坏耗时) / 20 ms⌉ + 1,刹停段另行认证;策略输出 50
+Hz
+关节目标,由插补器升采样到电机控制器频率。dt、n、动作块长度均可配置。
+
+9. 评估与验收
+9.1 测试集合
+
+
+
+
+
+
+| route_bench |
+tests/route_bench.cjs(40 例)+ 60 例随机基准 |
+验收 |
+
+
+| near_column_bench |
+tests/near_column_bench.cjs,30 例(pos / pose /
+rt) |
+验收 |
+
+
+| near_column 扩展 |
+§4.3 新造 ≥1000 例 |
+一次性验收 |
+
+
+| rt_drag_bench |
+tests/rt_drag_bench.cjs,12 例(模型在环) |
+验收 |
+
+
+| held-out |
+§4.3 2000 条 |
+一次性验收 |
+
+
+| 门禁集 |
+§4.3 2000 条 |
+训练中门禁,不参与验收 |
+
+
+
+新增 tests/policy_bench.cjs:①现有规划器
+②策略(关安全层)③策略 + 安全层,输出对比表。
+9.2 验收标准(部署形态 = 策略
++ 安全层)
+
+
+
+
+
+
+| 实际执行的碰撞 |
+= 0(距离认证或 0.01° 审计测量) |
+rt_drag_bench 0 |
+
+
+| 到达率 |
+route 全部可达例到达;near pos 30/30、near rt
+30/30;near_column 扩展集 0
+失败;held-out 可达任务 ≥ 98%,D 类停靠距离 ≤ 老师 + 5 mm |
+route_bench 40 例:到达 40/40、细验有效 39/40;60
+例随机基准有效 60/60;near 30/30、30/30 |
+
+
+| 到达用时 |
+≤ 老师路径时长 × 1.3 |
+— |
+
+
+| 关节行程 |
+≤ 现有规划器 × 1.10(按类别分别报告) |
+60 例平均 467° |
+
+
+| 冷启动 |
+< 10 ms |
+首次全量 IK 最差约 2 s |
+
+
+| 每次推理 + 安全认证 P99 |
+< 20 ms |
+拖拽重规划 P99 约 321 ms |
+
+
+| 刹停发生率 |
+< 2% 的推理周期 |
+— |
+
+
+| 模式摇摆(≥3 次切换) |
+< 1% 的任务 |
+— |
+
+
+| 策略单独(关安全层)碰撞率 |
+< 3% |
+— |
+
+
+
+说明:30 例全对时,失败率的 95% 置信上界约 9.5%;扩展集 1000 例 0
+失败时约 0.3%,因此以扩展集作为 30/30 的统计支撑。
+
+10. 当前存在的问题与风险
+10.1
+只能靠实测消除的风险(按里程碑顺序)
+
+
+
+
+
+
+| R1 |
+老师在相邻任务上左右绕行跳变,标签自相矛盾 |
+起终点扰动 ±5 mm 的邻居任务同伦类一致率 ≥ 90% |
+对 A* 边代价加左右偏好项,强制同区域选同侧 |
+M1 |
+
+
+| R2 |
+时间律仍有不可观测成分,闭环起不了步 |
+近邻样本标签方差 < 10% 步长;起步失败率 = 0 |
+进一步把剩余路程估计加入输入 |
+M1 / M5 |
+
+
+| R3 |
+距离认证过于保守,贴柱处拒绝率高,影响 30/30 |
+near_column 上认证拒绝率统计;离线 10⁵ 段 0.01° 审计漏检 = 0 |
+训练余量提高到 3–6 mm,接受行程变长;收紧杠杆界(按位形分区) |
+M2 / M7 |
+
+
+| R4 |
+浏览器推理延迟 |
+M4 后立即导出 ONNX,wasm-SIMD 多线程测 batch=8 P99 < 15 ms |
+减小模型(d=128,约 1.8M 参数);同时测 WebGPU,更快则换 |
+M4(最大不确定项) |
+
+
+| R5 |
+MeanFlow 头在 6 轴、位姿目标下穿柱或训练不稳 |
+near_column 穿柱率(关安全层)≤ 2%;损失不发散 |
+同骨干换 WTA K=8 头 |
+M5 |
+
+
+| R6 |
+位姿目标的多 IK 分支带来额外多峰 |
+不同肘/腕分支子集到达率 ≥ 主集 − 2 个百分点 |
+加目标分支标志 |
+M5 |
+
+
+| R7 |
+APG 压缩多模态或拉长路径(ELMP 中路径 +23%) |
+每轮左右比例与行程门禁 |
+加大 BC 锚定权重;行程项 |
+M6 |
+
+
+| R8 |
+卡死换向活锁 |
+50 个"两侧都要绕远"对抗用例 3 s 内恢复 ≥ 95%,活锁 = 0 |
+子目标改为离散绕行锚点分类 |
+M6 / M7 |
+
+
+| R9 |
+安全层贴柱时耗时超标 |
+near_column 全程 P99 < 5 ms |
+Web Worker 流水线;提交步数降到 2 |
+M7 |
+
+
+| R10 |
+训练耗时估计偏差 |
+2000 步吞吐 ≥ 2 万样本/s |
+降 epoch 或增大 batch |
+M5 |
+
+
+
+10.2 已知缺陷
+
+- 现有规划器(老师)在
tests/route_bench.cjs 上有 1/40
+例到达但路径细验不过;§4.4 的认证过滤会丢弃这类样本。
+ci27 姿态根枚举漏分支(姿态偏差约 97.5°)会影响 pose
+数据;APG 姿态项可部分纠正,必要时先修老师。
+- 胶囊模型或立柱变动即需重训:数据约 5 h + 预训练 1.5–5.6 h + 后训练
+2–4 h。
+
+10.3 需要用户确认
+
+- 真机电机/驱动型号与通信方式:决定每轴加速度上限
+a_max、插补频率与提交步数。
+- 运行时多候选打分是否算"运行时老师":本方案的理解是不算(只对模型自己的候选做距离认证和打分,不做搜索)。
+
+
+11. 目录规划
+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 # MeanFlow 一步头
+ sim/ closed_loop.py # 闭环仿真(验证、挖错、APG 共用)
+ eval/ collide_torch.py # 可微胶囊距离,与 JS 对拍
+ apg/ apg_finetune.py
+ mining/ mine_round.py gate.py loop.sh
+ toy/ toy_bimodal.py # 2D 双模态对照实验
+ configs/ base.yaml apg.yaml
+ train.py export_onnx.py README.md
+webapp/js/ik-policy.js # 闭环推理 + 排序 + 安全认证 + 刹停
+webapp/models/traj_policy.onnx traj_policy.norm.json
+tests/policy_bench.cjs
+12. 里程碑
+
+
+
+
+
+
+| M1 |
+数据生成器 + 时间律 + 1000 条试跑;老师一致性门禁 |
+ml/gen/*、stats.json |
+沙箱 |
+
+
+| M2 |
+可微胶囊距离(PyTorch)与 JS 对拍;距离认证实现与 10⁵ 段审计 |
+collide_torch.py、认证模块 |
+沙箱 |
+
+
+| M3 |
+5 万条老师数据 → 约 200 万样本 |
+Parquet |
+沙箱约 5 h 或用户机器 |
+
+
+| M4 |
+模型 + 训练工程 + 闭环仿真;小数据过拟合;导出 ONNX
+测浏览器延迟 |
+train.py、closed_loop.py、延迟报告 |
+沙箱 + 浏览器 |
+
+
+| M5 |
+预训练 + MeanFlow 头门禁 |
+checkpoint、门禁报告 |
+用户 GPU |
+
+
+| M6 |
+APG 微调 + 挖错循环 3–6 轮 |
+每轮 report.md |
+用户 GPU |
+
+
+| M7 |
+ik-policy.js 闭环部署 + 安全层实测 +
+policy_bench + 一次性验收 |
+对比表 |
+沙箱 + 浏览器 |
+
+
+| M8 |
+移除查看器对
+solveDyn/routeRT/路网的运行时依赖(保留在
+ml/gen 离线使用) |
+部署包瘦身 |
+沙箱 |
+
+
+
+13. 参考文献
+
+
+
diff --git a/docs/Transformer轨迹拟合训练方案.md b/docs/Transformer轨迹拟合训练方案.md
new file mode 100644
index 0000000..15e64c3
--- /dev/null
+++ b/docs/Transformer轨迹拟合训练方案.md
@@ -0,0 +1,521 @@
+# Transformer 避障运动策略:最终方案
+
+> 基于 `main@3c7c814`(贴立柱修复后的规划器)。本文是方案,代码尚未编写。
+> 训练机:RTX 3090 24 GB。部署:浏览器(后续真机)。
+
+---
+
+## 0. 定位与边界
+
+| 项目 | 决定 |
+|---|---|
+| 部署形态 | **无运行时老师**:运行时只有「神经策略 + 碰撞安全层」,不加载 IK 大表、PRM 路网、A*/RRT,也不调用 `solveDyn` / `routeRT` |
+| 运行方式 | **闭环滚动执行**:执行频率 50 Hz(每步 20 ms);每 60 ms 读一次当前关节角和目标,推理一段 16 步动作块,安全层认证后提交前 3 步 |
+| 碰撞安全层 | 不做搜索,只对模型给出的候选做**距离下界认证**(§8.3),不安全就换候选或沿已认证刹停段停下 |
+| 老师的角色 | 只在**离线**出现:生成预训练数据;后训练以可微碰撞代价为主(§7) |
+| 不做的事 | 不学动力学(速度/加速度上限由时间律与插补器保证);不用相机/点云(环境固定:台架 + P01 立柱,几何已知) |
+| 收益目标 | 冷启动(新目标到第一个动作)< 10 ms;每次推理 + 安全认证 < 20 ms;消除现有拖拽重规划 P99 约 321 ms 的长尾 |
+| 底线 | 实时拖拽**碰撞帧 = 0**(由安全层距离认证保证);到达率、行程在 §9 指标上不低于现有规划器 |
+
+**关于"风险":** 论文证据只能说明"别人在相近条件下做成过",没有一篇论文的条件(低维状态、单根固定立柱、约 4M 参数、浏览器推理、30/30)与本项目完全一致。因此本方案中只有安全层是**硬保证**;每个设计点都已定为唯一选择(§1.1),只有 MeanFlow 头带一个预先写定触发条件的回退(碰撞与否不依赖模型好坏);其余每一项都配有证据等级、本仓库可测的**门禁**(不过不进下一步)和**回退**(§10)。
+
+---
+
+## 1. 方案总览
+
+| 模块 | 最终选择 | 证据等级 | 关键依据 |
+|---|---|---|---|
+| 模型规模 | 约 4.1M 参数编码器-解码器 Transformer,不用 VLA 大模型 | A | IMPACT 4.67M、300 Hz;π0 3B 单次预填充 46 ms(4090) |
+| 数据 | 规划器离线造 5 万条任务 → 约 200 万"状态→动作块"样本 | B | MπNets、DRP、ELMP 均用规划器老师 |
+| 时间律 | 匀速巡航 + 梯形加减速,只依赖"当前速度 + 剩余路程";当前速度作输入 | B | MπNets 将老师路径重定时为匀速 |
+| 动作表示 | 16 步 × 6 轴关节增量 Δq | A | DRP;Diffusion Policy(位置式优于速度式) |
+| 动作头 | **MeanFlow 一步生成头**,每次并行采 8 个噪声 → 8 条候选 | B | 沙箱双模态实验(§2.4);MP1 约 6.8 ms |
+| 块间连续 | 训练时前缀条件化:输入已提交未执行的步 | B | 2512.05964:推理零开销,d≥2 时优于推理时 RTC |
+| 碰撞修正 | 输出后 1 步解析胶囊距离梯度投影(每轴 ≤ 0.5°,仅 d < 余量时) | B | DiffusionSeeder:少步生成下在环引导收益很小;投影在已知环境下够用 |
+| 候选排序 | 与已提交块重叠步的一致性打分 + 价值头 | B | BID:一致性打分 + 多样本相对提升 32% |
+| 预训练 | 行为克隆 + FK 胶囊端点损失 | B | ELMP 式 FK 损失 |
+| 后训练(主) | APG:可微运动学展开 + 胶囊距离代价反传 | A | ELMP:碰撞率 31.3%→8.9%;1 万示范 + APG 胜 60 万纯 BC |
+| 后训练(辅) | 无老师挖错循环 + 门禁 | B | DRP 迭代微调 +45% |
+| 安全层 | 距离下界认证 + 可刹停不变式 | A | Schwarzer 2005 连续认证;Thumm & Althoff 2022 failsafe |
+| 30/30 手段 | 子目标头、价值头、冷启动/卡死时短前瞻、卡死换向 | B / C | AWE、SHAC、BID |
+| 老师 | PRM 路网 A* + 捷径平滑(确定性);A* 失败才用 `solveDyn` | B | MπNets:老师不一致碰撞率 13.78%,一致老师 0.94% |
+| 推理后端 | onnxruntime-web wasm-SIMD 多线程 | C | 小模型下 WebGPU 调度开销占主导 |
+
+### 1.1 取舍决定(每项只有一个答案)
+
+| 选项 | 利 | 弊 | 决定 |
+|---|---|---|---|
+| 动作头:MeanFlow 一步头 vs WTA K=4 | MeanFlow:连续多模态,能同时表达左/右绕行与位姿目标的多个 IK 分支;沙箱 1 步达到 10 步流匹配质量。WTA:训练稳、实现简单 | MeanFlow:训练需 JVP(训练慢约 1.5–2 倍)、原生版本在部分任务失败(K-MF 表 1)。WTA:只有 4 个固定模式,左右 × 肘/腕分支可能超过 4 个;沙箱分不出两者高下 | **上 MeanFlow**。WTA 不实现;只有 M5 门禁不过(near_column 穿柱率高于 2% 或训练发散)才换成 WTA K=8,二者共用骨干,切换约 1 天 |
+| Shortcut + 条件 OT 配对 | 无需 JVP | 本项目无任何实测,组合无论文先例 | **不上** |
+| B 样条动作表示 | 平滑由表示保证;输出维度小 | 贴柱时拐角被抹圆、局部精度下降;只有间接证据;平滑已由梯形时间律 + 平滑损失保证 | **不上**,固定 16 步 Δq |
+| 输出后梯度投影 | 修掉 1–2 mm 的轻微侵入,成本约 0.1 ms,减少刹停 | 推离数据分布、改变块间一致性;修不了"绕错侧" | **上**,限 1 步、每轴修正量 ≤ 0.5°,仅 d < 余量时触发 |
+| 短前瞻(多推一块打分) | 避开"走两步就撞墙"的分支 | 推理次数翻倍,加剧最大不确定项(浏览器延迟) | **只在冷启动和卡死换向时上**,平时不做 |
+| 拒绝采样自蒸馏 | 进一步缩短行程 | 偏向贴柱、余量变小、多样性塌缩;APG 行程项已覆盖同一目标 | **不上** |
+| ReinFlow 强化学习微调 | 能直接优化到达/卡死/刹停等离散目标 | RL 会重塑左右模式比例;奖励调参与训练多出数天;这些离散目标已由卡死换向规则 + APG 覆盖 | **不上** |
+| 挖错循环中 E2 错题请老师补路径 | 解决可微代价绕不出的局部极小 | 量小、离线 | **上** |
+| 老师:PRM 路网 A* vs `solveDyn` | A*:确定性,同类任务左右选择一致,且是路网上的最短;`solveDyn` 覆盖更全 | A*:受路网分辨率限制,个别任务失败 | **A* 为主老师**,失败的任务用 `solveDyn`(固定种子)补 |
+| 推理后端:WebGPU vs wasm | WebGPU 大模型快 | 本模型约 4M 参数,WebGPU 每次调度 33–67 μs × 150–300 次,调度开销反而大 | **wasm-SIMD 多线程**;M4 实测若 WebGPU P99 更低再换 |
+| 训练余量 | 越大越不易被认证拒绝 | 越大行程越长、贴柱越难 | **5 mm** |
+| 关节噪声增广 σ | 覆盖偏离状态 | 过大产生无意义状态 | **1°** |
+| 局部牛顿精修 | 末端精度到 < 1 mm | 无 | **上**,同样过安全层 |
+
+证据等级:**A** 有直接先例与数字 · **B** 有相近先例,需本仓库验证 · **C** 仅推断。
+
+---
+
+## 2. 依据
+
+### 2.1 业界神经运动规划
+
+| 工作 | 年份 / 会议 | 输入 | 输出 | 老师与数据量 | 关键做法 | 运行方式 |
+|---|---|---|---|---|---|---|
+| **MπNets**(NVIDIA) | 2022 CoRL | 点云 + 关节角 + 目标位姿 | 下一步关节位置 | 规划器 300 万+ 问题 | 端到端行为克隆;老师路径重定时为匀速 | 闭环 9 Hz,1 kHz PD 跟踪 |
+| **Neural MP**(CMU) | 2024 / IROS 2025 | 点云 + 关节角 + 目标 | GMM(LSTM) | 100 万–300 万条 | 测试时采样多条,选穿透最少的(去掉后成功率 81%→31%) | 开环为主 |
+| **DRP / IMPACT**(CMU) | 2025 CoRL | 点云 + 关节角 + 目标关节角 | 10 步关节增量 | cuRobo 1000 万条 | 大规模预训练 + 迭代师生微调 + "目标被挡停在最近安全处" | 闭环;4.67M 参数,300 Hz |
+| **ELMP**(ETH) | 2026 arXiv | 点云 + 关节角 + 目标位姿 | 关节增量 | AIT* 约 60 万条 | 行为克隆后 **APG 微调**,碰撞/到达/平滑损失直接反传 | 闭环 30 Hz |
+
+- ELMP:1 万条老师轨迹 + APG(成功率 72.0%)超过 60 万条纯行为克隆(57.9%);APG 把碰撞率降到 1/3 以下。
+- 最好的方法在静态场景仍有约 9–10% 碰撞(ELMP-APG 8.9%,DRP 10.16%),实际部署都配检查或反应层。
+- 共识:闭环、短动作块滚动执行、老师只离线用、必须后训练。
+
+### 2.2 本项目的条件
+
+| 条件 | 主流 | 本项目 | 意味着 |
+|---|---|---|---|
+| 环境 | 未知、多变,靠点云 | 固定且精确已知(台架 + 立柱,1936 个胶囊) | 不需要点云编码器;模型可以小;碰撞检查精确 |
+| 机器人 | Franka 7 轴 | 自研 6 轴,J1/J3/J6 连续转 | 需处理连续轴展开 |
+| 碰撞模型 | SDF / 球近似 | 胶囊解析距离,可微 | 直接做 APG;安全层可认证 |
+| 平台 | 台式 GPU | 浏览器(后续真机) | 模型小,ONNX + WebGPU/wasm |
+
+资源应投在**闭环稳定性、左右绕行选择和安全层**上,而不是感知和泛化。
+
+### 2.3 前沿生成式技术取舍
+
+| 技术 | 结论 | 理由 |
+|---|---|---|
+| VLA 大模型(π0/π0.5、GR00T、OpenVLA) | 不采用 | 无图像、无语言指令;3B 参数更慢不更准 |
+| 一步生成:MeanFlow(MP1) | **采用** | 1 次前向;沙箱双模态实验通过 |
+| Consistency Policy、OneDP、朴素 1 步流匹配 | 不采用 | CP 原文承认偏向一侧;OneDP 有意取单模态;朴素 1 步 FM 等于条件均值,会穿柱 |
+| Shortcut / 条件 OT 配对 | 不采用 | 见 §1.1 |
+| OFP 自蒸馏 | 不采用 | 未找到公开代码;自引导 λ=0.5 时出现模态塌缩 |
+| 生成过程中代价引导(MPD/EDMP/GPD) | 不采用 | 无论文在 1–2 步下验证;改用输出后投影 |
+| 推理时 RTC | 不采用 | 原文只验证 5 步去噪且需反向传播;改用训练时前缀条件化 |
+| 时间集成 / 交叉淡入 | 不采用 | 执行的是未认证的混合块;左右两块平均可能穿柱;π0 弃用 |
+| FAST 动作分词 | 不采用 | 服务于语言骨干,自回归推理慢 |
+| B 样条动作表示 | 不采用 | 见 §1.1 |
+| ReinFlow / DPPO | 不采用 | 见 §1.1 |
+
+### 2.4 沙箱双模态对照实验
+
+2D 点从柱左侧到右侧,示教一半从上绕一半从下绕,16 步动作块、每 3 步重推理,与本方案同构。代码 `ml/toy/toy_bimodal.py`,150 个"起终点都贴近中轴"的难例:
+
+| 动作头 | 单样本、无安全层:到达 / 穿柱回合 | 8 候选 + 安全层:到达 / 穿柱 / 平均刹停 | 推理(CPU,8 候选) |
+|---|---|---|---|
+| MSE 回归 | 100% / 0% | 100% / 0% / 0 | 0.13 ms |
+| WTA K=4 | 100% / 0% | 100% / 0% / 0 | 0.19 ms |
+| 流匹配 10 步 | 100% / 4.0% | 99.3% / 0% / 3.7 | 2.13 ms |
+| 朴素流匹配 1 步 | 87.3% / **23.3%** | 81.3% / 0% / 14.0 | 0.25 ms |
+| **MeanFlow 1 步** | 100% / 2.7% | 100% / 0% / 0.3 | 0.25 ms |
+
+- 朴素 1 步流匹配会把模态平均进柱子;MeanFlow 1 步达到 10 步流匹配的质量,推理快约 8 倍。
+- 安全层在所有方法上把穿柱降为 0,代价是刹停。
+- 该任务过于简单(闭环中状态一偏离中轴即打破对称),**分不出一步头与 WTA 谁更好**;因此 WTA 只作为 M5 门禁不过时的预定回退(§1.1)。
+- 训练仅 300 步的 MSE 在同一难例上 100% 穿柱、加安全层后 0% 到达,说明欠拟合时平均模态的风险真实存在。
+
+---
+
+## 3. 训练环境
+
+| 阶段 | 在哪里跑 | 说明 |
+|---|---|---|
+| 数据生成 | Hark 沙箱(2 vCPU / 7 GB,Node)或用户机器 | 纯 JS,无需 GPU |
+| 预训练 + 后训练 | 用户 RTX 3090 24 GB | batch 1024–2048 |
+| 部署推理 | 浏览器 onnxruntime-web wasm-SIMD 多线程;后续真机控制器 | 与现有查看器同页 |
+
+```bash
+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
+```
+
+---
+
+## 4. 离线数据(老师只在这里出现)
+
+### 4.1 文件
+
+| 文件 | 作用 |
+|---|---|
+| `ml/gen/gen_dataset.cjs` | 采样任务 → 调老师 → 校验 → 时间参数化 → 写分片 |
+| `ml/gen/sampler.cjs` | 起点/目标采样 |
+| `ml/gen/run_parallel.sh` | 多进程,不同种子 |
+| `ml/data/shard_XXXX.jsonl` | 原始样本(不入库) |
+
+复用 `tests/route_bench_setup.cjs` 装配求解器(关节表、`docs/travel.json`、`docs/collide.json`)。
+
+### 4.2 原始样本
+
+```json
+{
+ "id": "s0003_000127", "mode": "pos" | "pose",
+ "q0": [6], "T": [x,y,z], "R": [[3x3]] | null, "tool": 0,
+ "path": [[6], ...],
+ "reached": true,
+ "travel_deg": 123.4, "plan_ms": 812.0,
+ "fp": "collide.json 指纹"
+}
+```
+
+`reached=false` 表示目标不可达,路径终点为离目标最近的安全位形("停靠")。
+
+### 4.3 采样分布(5 万条任务)
+
+关节限位: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 关节直线有干涉 |
+| C 贴立柱 | 15% | b 满足 `nearColumn`,q0 在立柱另一侧 |
+| D 目标不可达 | 10% | 目标在立柱内/所有分支都撞/工作空间外;标签为停靠 |
+
+- pos / pose 各半;老师为 PRM 路网 A* + 捷径平滑(确定性;复用 `routeRT` 的路网图搜索,放宽时间预算);A* 失败的任务用 `solveDyn`(固定种子)补。
+- 另造三个互不重叠的集合:**门禁集** 2000 条(挖错循环每轮用)、**held-out 验收集** 2000 条、**near_column 扩展验收集** ≥1000 条;两个验收集只在最终验收时用一次。现有三个基准不进训练集。
+
+### 4.4 过滤
+
+1. 整条路径用距离下界认证(与 §8.3 同口径)复核,任一段不过即丢弃。仓库 `tests/route_bench.cjs` 上现有规划器有 1/40 例路径细验不过,这类样本必须丢掉。
+2. `poseRelaxed` 样本只当 pos 模式用。
+3. 行程 > 同任务 `routeRT` 1.5 倍的先统计,再定是否丢弃;按类别统计丢弃率(C 类 > 20% 说明老师在贴柱场景不可靠)。
+
+### 4.5 时间参数化 → 闭环训练样本
+
+1. 时间律:按轴速比 `VREL = [0.6, 0.6, 0.9, 0.9, 1.2, 1.8]` 匀速巡航,梯形加减速,速度只取决于"当前速度 + 剩余路程"(每轴加速度上限 a_max 为待定参数,真机型号确定后设定),dt = 20 ms。
+2. 得到状态序列 q_0 … q_N,每隔 3 步取一个样本:
+ - 输入:§5.1 全部字段(含当前速度、已提交前缀)
+ - 标签:未来 16 步 Δq_{t+k} = q_{t+k} − q_t(到终点后补零)
+3. 每条路径约 40–50 个样本 → 约 200 万样本(以 `stats.json` 为准)。
+4. 协变量偏移对策:关节噪声增广(σ = 1°,噪声状态由老师离线重标);偏离状态的进一步覆盖靠 §7。
+
+### 4.6 耗时与存储
+
+- 路网 A* 每条数十毫秒,耗时主要在过滤认证;按 `solveDyn` 0.7 s/条上限估算,沙箱 2 进程不超过 5 小时。
+- 200 万样本原始约 1 GB;Parquet 约 200 MB。
+
+### 4.7 检查点
+
+- [ ] `ml/data/stats.json`:类别、到达率、行程、样本数、补零样本占比
+- [ ] 老师一致性:起终点扰动 ±5 mm 的邻居任务同伦类一致率 ≥ 90%
+- [ ] 抽 20 条在查看器回放(新增 `?replay=` 参数)
+- [ ] 各集合与训练集无重叠
+
+---
+
+## 5. 表示与预处理
+
+文件 `ml/prep/build_dataset.py` → `train/val/test.parquet`、`norm.json`。
+
+### 5.1 输入
+
+| 量 | 维度 | 编码 |
+|---|---:|---|
+| 当前 q_t | 6 | 每轴 (sin, cos) → 12;限位轴另加归一化值 → +3 |
+| 当前关节速度 q_t − q_{t−1} | 6 | 按每轴速度上限归一化 |
+| 当前 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] |
+| 已提交未执行前缀 | 3×6 + 3 | 前缀 Δq + 有效长度掩码;训练时随机遮盖 0–3 步 |
+| 当前子目标 | 6 | 子目标头输出的关节途经点(归一化);无子目标时填当前 q |
+| 关键胶囊对最小距离 | 8 | 臂各段到立柱的胶囊距离 |
+
+### 5.2 输出
+
+- MeanFlow 一步头:每条候选 16 步 × 6 轴 Δq(按每轴最大步长归一化)。
+- 附加头:价值头(剩余时间/代价)、子目标头(2 个关节途经点 + 是否需要)。
+
+### 5.3 连续轴
+
+J1/J3/J6 统一用 `unwrapTo` 展开后再做增量;预处理与部署共用一份实现,对拍时一并验证。
+
+---
+
+## 6. 模型与预训练
+
+### 6.1 结构
+
+```
+条件特征(约 90 维)──MLP──▶ 8 个条件 token (d=192)
+ │
+ 4 层 Transformer encoder
+ │ (memory)
+16 个动作 token(注入噪声 z + 时间嵌入 (r, t))
+ ▼
+ 4 层 Transformer decoder(非自回归,一次前向)
+ ├─ 动作输出:每 token 6 维 Δq
+ ├─ 价值头:1
+ └─ 子目标头:2 个关节途经点 + 是否需要
+```
+
+| 超参 | 值 |
+|---|---|
+| d_model / 头数 / FFN | 192 / 8 / 768 |
+| encoder / decoder 层数 | 4 / 4 |
+| 参数量 | 约 4.1M |
+
+子目标触发:新目标或目标跳变 > 50 mm 时输出;到达当前子目标 < 5° 后切下一个。
+
+### 6.2 动作头:MeanFlow 一步生成
+
+| 项 | 做法 |
+|---|---|
+| 多模态 | 连续分布;每次推理并行采 8 个噪声 → 8 条候选 |
+| 训练 | MeanFlow 平均速度场损失(MP1 配方:25% 样本 r≠t,自适应损失加权),JVP 用 `torch.func.jvp` |
+| 推理 | 1 次批量前向(r=0, t=1) |
+| 后处理 | 1 步解析胶囊距离梯度投影,每轴修正 ≤ 0.5°,仅 d < 余量时(JS 实现,不走 ONNX) |
+| APG 兼容 | 固定噪声后为确定性可微映射 |
+| 预定回退 | M5 门禁不过(near_column 穿柱率 > 2% 或训练发散)→ 同骨干换 WTA K=8 头(WTA-L1 + 模式 CE),约 1 天 |
+
+### 6.3 损失
+
+```
+L = MeanFlow 损失 1.0
+ + FK 损失:一步输出(固定噪声)的各连杆胶囊端点位置差 0.5
+ + 平滑:二阶差分 0.05
+ + 价值头 L1 + 子目标头 L1 0.1 / 0.1
+```
+
+### 6.4 训练配置
+
+| 项 | 值 |
+|---|---|
+| 优化器 | AdamW,β=(0.9, 0.95),wd 0.01 |
+| 学习率 | 1e-3,预热 1000 步,余弦退火 |
+| batch | 1024 |
+| 精度 | bf16 混合精度 |
+| 步数 | 先跑 2000 步测吞吐再定;参考 200 万样本 × 30 epoch ÷ 1024 ≈ 6 万步;验证集闭环到达率不再上升即停 |
+| 预计耗时 | RTX 3090 约 1.5–5.6 小时(按 2000 步吞吐实测重算) |
+
+### 6.5 对拍与验证
+
+- `ml/eval/collide_torch.py`:可微胶囊距离 PyTorch 批量版,与 JS `collideFree` 对拍 10 万位形:布尔判定 0 差异,距离误差 < 1e-4 mm,梯度与有限差分相对误差 < 1e-3。
+- 每 epoch 闭环验证:从 1000 个验证任务出发,按部署节奏(每 60 ms 推理、提交 3 步)运行到到达或超时(老师路径时长 × 2,最少 3 s),统计到达率、用时 ≤ 老师 × 1.3 的达标率、碰撞步数(关安全层)、行程比、左/右/穿柱三类比例。
+
+---
+
+## 7. 后训练
+
+### 7.1 主力:APG 可微微调
+
+```
+for 每个 batch(随机采样 q0 和目标,不需要老师):
+ q = q0
+ for t in 0..H-1 (H = 60 次推理 × 3 步 = 180 步 ≈ 3.6 s;长任务分段截断反传):
+ chunk = π(obs(q, 目标, 前缀), z) # 每条展开固定一个噪声 z
+ Δq = chunk[0: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·行程) + w_bc·L_BC
+ 反传,梯度裁剪 ≤ 1.0,lr 1e-4
+```
+
+- 碰撞项 L_col = Σ ReLU(margin − 胶囊距离),margin = `margin_mm` + 训练余量 5 mm(覆盖安全层认证的保守量);含臂×立柱、臂×台架、臂×臂(非相邻段)。
+- 到达项:位置误差² + λ_rot·‖R − R*‖_F²。
+- 平滑项:速度² + 加速度²。
+- BC 锚定项:保留预训练损失,防止多模态被压缩;每轮监控左右比例。
+- 采样分布同 §4.3,B/C/D 类提到 60%,其中贴柱类 40%。
+
+### 7.2 辅助:无老师挖错循环
+
+每轮:
+1. 出题:新种子 5 万任务 + 2000 段模型在环拖拽仿真。
+2. 闭环作答:完全按部署方式运行,**关闭安全层**以暴露真实错误。
+3. 验算:GPU 批量胶囊检查。
+4. 错题分类:E1 撞 / E2 没到(卡在局部极小)/ E3 绕远(> 1.2× 参考)/ E4 末端精度差 / E5 摇摆(≥ 3 次切换)/ E6 拖拽失稳。
+5. 错题及其 ±5 mm / ±3° 的 10 个邻居加入 APG 采样池(E1、E6 ×2);仅 E2 可离线请老师补少量路径。
+6. 门禁(用门禁集,不用验收集):到达率上升、A 类每轮降幅 ≤ 0.5 个百分点、上一轮修好的错题 95% 仍对;否则回滚。
+7. 停止:连续 2 轮提升 < 0.5 个百分点,或满 6 轮。
+
+---
+
+## 8. 部署
+
+### 8.1 执行循环
+
+```
+执行:50 Hz,每步 20 ms,按已提交步走
+每 60 ms:
+ 1. 读当前 q、当前速度、已提交未执行前缀、最新目标
+ 2. 推理:8 个噪声 → 8 条 16 步动作块(冷启动或卡死换向时,再各推一块做短前瞻)
+ 3. 每条候选做 1 步胶囊距离梯度投影(每轴 ≤ 0.5°,仅 d < 余量时)
+ 4. 排序(§8.2)
+ 5. 安全层依次认证候选前 3 步 + 刹停段(§8.3),第一个通过的提交给执行器
+ 6. 全部不通过 → 沿上一次已认证的刹停段停下,下次继续推理
+ 7. 到达:TCP 误差 < 1 mm(pose 另需 < 0.5°)且速度≈0;
+ 接近目标(< 5 mm)时做 1–3 次局部牛顿精修(solveTo 单步),精修段同样过安全层认证
+```
+
+执行的始终是安全层认证过的那一块,不做新旧块混合。执行时钟放在 Web Worker、按实际 dt 推进,避免 `requestAnimationFrame`(60 Hz)与 20 ms 不整除及后台节流造成的抖动。
+
+### 8.2 候选排序(防左右摇摆)
+
+分数 = −Σ w_k‖候选第 k 步 − 已提交块第 k 步‖²(重叠步加权)− λ·价值头剩余代价。冷启动时无已提交块,只用价值头 + 短前瞻打分。
+
+### 8.3 安全层(唯一的硬保证)
+
+- **距离下界认证**:对一段运动 q_a → q_b,若两端到障碍的最小距离之和 d(q_a) + d(q_b) > Σ_j r_j·|Δθ_j|(r_j 为每轴实测杠杆上界,J1 约 9.0 mm/°,六轴合计最大约 24.3 mm/°),则整段安全;否则二分,直到全部子段通过或判不安全。臂×立柱/台架用胶囊距离;自碰撞对复用 `pair2d` 杠杆界(J3 3.24、J4 2.54 mm/°)。外加关节限位。
+- 离散采样检查(现有 `pathFine`,1.5° + 半格)只作快速预筛,不作保证依据。
+- **可刹停不变式**:只有当"候选前 3 步 + 从第 3 步末按每轴 a_max 减速到停"整段都通过认证时才提交。任何时候系统都持有一条已认证的停车路线,下一次推理即使完全失效也只会停下。
+- 耗时:每段一次距离查询覆盖整段,不通过才二分(通常 2–6 次);按排序逐个认证,第一个通过即停;包围球预筛先行。目标每次 < 5 ms,否则放 Web Worker 与推理流水线并行。
+- `ik-glue.js` 的每帧碰撞守卫保留为第二道保险。
+
+### 8.4 部署包
+
+| 有 | 没有 |
+|---|---|
+| `traj_policy.onnx`(fp16,约 8.3 MB)+ `norm.json` | PRM 路网、IK 候选大表 |
+| 胶囊距离与认证(`collideFree`、包围球预筛、`pair2d`) | `solveDyn` / `routeRT` / RRT / A* |
+| `fk` / `orient`、局部牛顿精修 `solveTo` 单步 | 全量 IK 枚举 |
+
+`collide.json` 指纹写进模型;不一致时前端拒绝运行并提示重训。
+
+### 8.5 near_column 30/30 的保障手段
+
+"超时"指机械臂在规定时间内没走到目标,是决策问题而非计算速度问题。典型失效:局部极小/活锁(每次都想直穿、每次被安全层挡住)、左右摇摆、绕远。对策(运行时均不需要老师):
+
+1. **子目标头**:给出 1–2 个关节途经点作为绕柱方向锚点,标签取老师路径拐点(离线)。
+2. **价值头**:预测剩余时间/代价,用于候选打分与进展判断;APG 中用 TD 自举监督。
+3. **短前瞻**(仅冷启动和卡死换向时):对每条候选再推一块,用胶囊认证 + 价值头给 32 步后终态打分。
+4. **卡死检测 + 强制换向**:0.3 s 内价值不降或连续 2 次刹停 → 切到另一绕行方向并锁定 1 s。
+5. **训练侧加强**:贴柱类占 APG 采样 40%;展开覆盖整段绕行。
+
+### 8.6 控制周期
+
+伺服层(参考):Franka FCI 1 ms;UR e-Series 2 ms、CB3 8 ms;ABB EGM 4 ms(滞后 10–20 ms);KUKA RSI 4/12 ms;FANUC DPM 约 8 ms;MoveIt Servo 默认 10 ms;RC 舵机 20 ms。
+
+策略层(参考):MπNets 9 Hz;Diffusion Policy 10 Hz、预测 16 执行 8;ELMP 30 Hz;π0 50 Hz、约每 0.5 s 推理一次;DRP 300 Hz。业界均为"策略层 10–50 Hz + 伺服层 125 Hz–1 kHz"两层结构。
+
+本方案:执行 50 Hz、每 60 ms 推理一次、提交 3 步。真机上提交步数 n ≥ ⌈(通信滞后 + 一次推理最坏耗时) / 20 ms⌉ + 1,刹停段另行认证;策略输出 50 Hz 关节目标,由插补器升采样到电机控制器频率。`dt`、n、动作块长度均可配置。
+
+---
+
+## 9. 评估与验收
+
+### 9.1 测试集合
+
+| 集合 | 来源 | 用途 |
+|---|---|---|
+| route_bench | `tests/route_bench.cjs`(40 例)+ 60 例随机基准 | 验收 |
+| near_column_bench | `tests/near_column_bench.cjs`,30 例(pos / pose / rt) | 验收 |
+| near_column 扩展 | §4.3 新造 ≥1000 例 | 一次性验收 |
+| rt_drag_bench | `tests/rt_drag_bench.cjs`,12 例(模型在环) | 验收 |
+| held-out | §4.3 2000 条 | 一次性验收 |
+| 门禁集 | §4.3 2000 条 | 训练中门禁,不参与验收 |
+
+新增 `tests/policy_bench.cjs`:①现有规划器 ②策略(关安全层)③策略 + 安全层,输出对比表。
+
+### 9.2 验收标准(部署形态 = 策略 + 安全层)
+
+| 指标 | 要求 | 现有规划器 |
+|---|---|---|
+| 实际执行的碰撞 | **= 0**(距离认证或 0.01° 审计测量) | rt_drag_bench 0 |
+| 到达率 | route 全部可达例到达;near pos **30/30**、near rt **30/30**;near_column 扩展集 **0 失败**;held-out 可达任务 ≥ 98%,D 类停靠距离 ≤ 老师 + 5 mm | `route_bench` 40 例:到达 40/40、细验有效 39/40;60 例随机基准有效 60/60;near 30/30、30/30 |
+| 到达用时 | ≤ 老师路径时长 × 1.3 | — |
+| 关节行程 | ≤ 现有规划器 × 1.10(按类别分别报告) | 60 例平均 467° |
+| 冷启动 | < 10 ms | 首次全量 IK 最差约 2 s |
+| 每次推理 + 安全认证 P99 | < 20 ms | 拖拽重规划 P99 约 321 ms |
+| 刹停发生率 | < 2% 的推理周期 | — |
+| 模式摇摆(≥3 次切换) | < 1% 的任务 | — |
+| 策略单独(关安全层)碰撞率 | < 3% | — |
+
+说明:30 例全对时,失败率的 95% 置信上界约 9.5%;扩展集 1000 例 0 失败时约 0.3%,因此以扩展集作为 30/30 的统计支撑。
+
+---
+
+## 10. 当前存在的问题与风险
+
+### 10.1 只能靠实测消除的风险(按里程碑顺序)
+
+| # | 风险 | 门禁(不过不进下一步) | 回退 | 何时测 |
+|---|---|---|---|---|
+| R1 | 老师在相邻任务上左右绕行跳变,标签自相矛盾 | 起终点扰动 ±5 mm 的邻居任务同伦类一致率 ≥ 90% | 对 A* 边代价加左右偏好项,强制同区域选同侧 | M1 |
+| R2 | 时间律仍有不可观测成分,闭环起不了步 | 近邻样本标签方差 < 10% 步长;起步失败率 = 0 | 进一步把剩余路程估计加入输入 | M1 / M5 |
+| R3 | 距离认证过于保守,贴柱处拒绝率高,影响 30/30 | near_column 上认证拒绝率统计;离线 10⁵ 段 0.01° 审计漏检 = 0 | 训练余量提高到 3–6 mm,接受行程变长;收紧杠杆界(按位形分区) | M2 / M7 |
+| R4 | 浏览器推理延迟 | M4 后立即导出 ONNX,wasm-SIMD 多线程测 batch=8 P99 < 15 ms | 减小模型(d=128,约 1.8M 参数);同时测 WebGPU,更快则换 | **M4(最大不确定项)** |
+| R5 | MeanFlow 头在 6 轴、位姿目标下穿柱或训练不稳 | near_column 穿柱率(关安全层)≤ 2%;损失不发散 | 同骨干换 WTA K=8 头 | M5 |
+| R6 | 位姿目标的多 IK 分支带来额外多峰 | 不同肘/腕分支子集到达率 ≥ 主集 − 2 个百分点 | 加目标分支标志 | M5 |
+| R7 | APG 压缩多模态或拉长路径(ELMP 中路径 +23%) | 每轮左右比例与行程门禁 | 加大 BC 锚定权重;行程项 | M6 |
+| R8 | 卡死换向活锁 | 50 个"两侧都要绕远"对抗用例 3 s 内恢复 ≥ 95%,活锁 = 0 | 子目标改为离散绕行锚点分类 | M6 / M7 |
+| R9 | 安全层贴柱时耗时超标 | near_column 全程 P99 < 5 ms | Web Worker 流水线;提交步数降到 2 | M7 |
+| R10 | 训练耗时估计偏差 | 2000 步吞吐 ≥ 2 万样本/s | 降 epoch 或增大 batch | M5 |
+
+### 10.2 已知缺陷
+
+1. 现有规划器(老师)在 `tests/route_bench.cjs` 上有 1/40 例到达但路径细验不过;§4.4 的认证过滤会丢弃这类样本。
+2. `ci27` 姿态根枚举漏分支(姿态偏差约 97.5°)会影响 pose 数据;APG 姿态项可部分纠正,必要时先修老师。
+3. 胶囊模型或立柱变动即需重训:数据约 5 h + 预训练 1.5–5.6 h + 后训练 2–4 h。
+
+### 10.3 需要用户确认
+
+1. **真机电机/驱动型号与通信方式**:决定每轴加速度上限 a_max、插补频率与提交步数。
+2. **运行时多候选打分是否算"运行时老师"**:本方案的理解是不算(只对模型自己的候选做距离认证和打分,不做搜索)。
+
+---
+
+## 11. 目录规划
+
+```
+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 # MeanFlow 一步头
+ sim/ closed_loop.py # 闭环仿真(验证、挖错、APG 共用)
+ eval/ collide_torch.py # 可微胶囊距离,与 JS 对拍
+ apg/ apg_finetune.py
+ mining/ mine_round.py gate.py loop.sh
+ toy/ toy_bimodal.py # 2D 双模态对照实验
+ configs/ base.yaml apg.yaml
+ train.py export_onnx.py README.md
+webapp/js/ik-policy.js # 闭环推理 + 排序 + 安全认证 + 刹停
+webapp/models/traj_policy.onnx traj_policy.norm.json
+tests/policy_bench.cjs
+```
+
+## 12. 里程碑
+
+| # | 内容 | 产出 | 在哪跑 |
+|---|---|---|---|
+| M1 | 数据生成器 + 时间律 + 1000 条试跑;老师一致性门禁 | `ml/gen/*`、stats.json | 沙箱 |
+| M2 | 可微胶囊距离(PyTorch)与 JS 对拍;距离认证实现与 10⁵ 段审计 | `collide_torch.py`、认证模块 | 沙箱 |
+| M3 | 5 万条老师数据 → 约 200 万样本 | Parquet | 沙箱约 5 h 或用户机器 |
+| M4 | 模型 + 训练工程 + 闭环仿真;小数据过拟合;**导出 ONNX 测浏览器延迟** | `train.py`、`closed_loop.py`、延迟报告 | 沙箱 + 浏览器 |
+| M5 | 预训练 + MeanFlow 头门禁 | checkpoint、门禁报告 | 用户 GPU |
+| M6 | APG 微调 + 挖错循环 3–6 轮 | 每轮 report.md | 用户 GPU |
+| M7 | `ik-policy.js` 闭环部署 + 安全层实测 + `policy_bench` + 一次性验收 | 对比表 | 沙箱 + 浏览器 |
+| M8 | 移除查看器对 `solveDyn`/`routeRT`/路网的运行时依赖(保留在 `ml/gen` 离线使用) | 部署包瘦身 | 沙箱 |
+
+## 13. 参考文献
+
+- MπNets:https://arxiv.org/abs/2210.12209
+- Neural MP:https://arxiv.org/abs/2409.05864
+- Deep Reactive Policy / IMPACT:https://arxiv.org/abs/2509.06953
+- ELMP:https://arxiv.org/abs/2607.00215
+- Diffusion Policy:https://arxiv.org/abs/2303.04137
+- π0:https://arxiv.org/abs/2410.24164 ;π0.5:https://arxiv.org/abs/2504.16054
+- FAST:https://arxiv.org/abs/2501.09747
+- MP1 / MeanFlow:https://arxiv.org/abs/2507.10543
+- One-Step Flow Policy:https://arxiv.org/abs/2603.12480
+- 条件 OT 流策略:https://proceedings.mlr.press/v305/sochopoulos25a.html
+- Kinematic MeanFlow:https://arxiv.org/abs/2610.00864
+- Consistency Policy:https://arxiv.org/abs/2405.07503 ;OneDP:https://arxiv.org/abs/2410.21257
+- MPD:https://arxiv.org/abs/2308.01557 ;EDMP:https://arxiv.org/abs/2309.11414 ;GPD:https://arxiv.org/abs/2501.18229 ;DiffusionSeeder:https://arxiv.org/abs/2410.16727
+- Real-Time Chunking:https://arxiv.org/abs/2506.07339 ;训练时动作条件化:https://arxiv.org/abs/2512.05964
+- Bidirectional Decoding(BID):https://arxiv.org/abs/2408.17355
+- DPPO:https://arxiv.org/abs/2409.00588 ;ReinFlow:https://arxiv.org/abs/2505.22094
+- Schwarzer, Saha, Latombe, *Adaptive Dynamic Collision Checking for Single and Multiple Articulated Robots in Complex Environments*, IEEE T-RO 2005
+- Thumm & Althoff, *Provably Safe Deep Reinforcement Learning for Robotic Manipulation in Human Environments*, ICRA 2022
+- Zhou et al., *On the Continuity of Rotation Representations in Neural Networks*, CVPR 2019
+- AWE(航点提取):https://arxiv.org/abs/2307.14326 ;SHAC:https://arxiv.org/abs/2204.07137
+- 控制周期:Franka FCI https://frankarobotics.github.io/docs/overview.html ;UR RTDE https://www.universal-robots.com/articles/ur/interface-communication/remote-control-via-tcpip ;ABB EGM 应用手册 3HAC073318;KUKA RSI https://docs.quanser.com/quarc/documentation/kuka_rsi_block.html
diff --git a/ml/toy/toy_bimodal.py b/ml/toy/toy_bimodal.py
new file mode 100644
index 0000000..8734413
--- /dev/null
+++ b/ml/toy/toy_bimodal.py
@@ -0,0 +1,123 @@
+# 2D 绕柱玩具实验:比较不同动作头在"左右(上下)双模态绕行"下的闭环表现
+import torch, torch.nn as nn, numpy as np, math, time, sys, json
+torch.manual_seed(0); np.random.seed(0); torch.set_num_threads(2)
+R=1.0; H=16; STEP=0.05
+def demo(s,g,mode):
+ via=np.array([0.0, 1.35*mode])
+ pts=[s, np.array([-0.9,0.95*mode]) if s[0]<-0.9 else s, via, np.array([0.9,0.95*mode]), g]
+ P=np.array(pts); L=np.r_[0,np.cumsum(np.linalg.norm(np.diff(P,axis=0),axis=1))]
+ n=int(L[-1]/STEP)+1; u=np.linspace(0,L[-1],n)
+ x=np.interp(u,L,P[:,0]); y=np.interp(u,L,P[:,1]); Q=np.c_[x,y]
+ # 平滑
+ for _ in range(20): Q[1:-1]=0.5*Q[1:-1]+0.25*(Q[:-2]+Q[2:])
+ return Q
+def sample_task(hard=False):
+ sy=np.random.uniform(-0.3,0.3) if hard else np.random.uniform(-1.5,1.5)
+ gy=np.random.uniform(-0.3,0.3) if hard else np.random.uniform(-1.5,1.5)
+ return np.array([np.random.uniform(-2.5,-1.6),sy]), np.array([np.random.uniform(1.6,2.5),gy])
+def collide_path(Q):
+ return np.any(np.linalg.norm(Q,axis=1)0.3 else (1 if np.random.rand()<0.5 else -1)
+ Q=demo(s,g,mode)
+ if collide_path(Q): continue
+ D=np.diff(Q,axis=0); D=np.r_[D,np.zeros((H,2))]
+ for i in range(len(Q)-1):
+ O.append(np.r_[Q[i],g]); A.append(D[i:i+H].reshape(-1)/STEP)
+ return torch.tensor(np.array(O),dtype=torch.float32), torch.tensor(np.array(A),dtype=torch.float32)
+O,A=build(); print('samples',len(O),flush=True)
+AD=2*H
+def mlp(i,o,h=256): return nn.Sequential(nn.Linear(i,h),nn.SiLU(),nn.Linear(h,h),nn.SiLU(),nn.Linear(h,h),nn.SiLU(),nn.Linear(h,o))
+class MSE(nn.Module):
+ def __init__(s): super().__init__(); s.f=mlp(4,AD)
+ def loss(s,o,a): return ((s.f(o)-a)**2).mean()
+ def sample(s,o,k=1): return s.f(o).unsqueeze(1).expand(-1,k,-1)
+class WTA(nn.Module):
+ K=4
+ def __init__(s): super().__init__(); s.f=mlp(4,AD*s.K+s.K)
+ def out(s,o):
+ y=s.f(o); return y[:,:AD*s.K].view(-1,s.K,AD), y[:,AD*s.K:]
+ def loss(s,o,a):
+ p,l=s.out(o); e=(p-a[:,None]).abs().mean(-1); k=e.argmin(1)
+ return e.gather(1,k[:,None]).mean()+0.5*nn.functional.cross_entropy(l,k)
+ def sample(s,o,k=1):
+ p,l=s.out(o)
+ if k==1: return p.gather(1,l.argmax(1)[:,None,None].expand(-1,1,AD))
+ o_=l.argsort(1,descending=True); return p.gather(1,o_[:,:,None].expand(-1,-1,AD)) # 按概率排序
+class FM(nn.Module):
+ def __init__(s,steps): super().__init__(); s.f=mlp(4+AD+1,AD); s.steps=steps
+ def loss(s,o,a):
+ e=torch.randn_like(a); t=torch.rand(len(a),1); z=(1-t)*a+t*e
+ return ((s.f(torch.cat([o,z,t],1))-(e-a))**2).mean()
+ def sample(s,o,k=1):
+ B=len(o); oo=o.repeat_interleave(k,0); z=torch.randn(B*k,AD); dt=1/s.steps
+ for i in range(s.steps):
+ t=torch.full((B*k,1),1-i*dt); z=z-dt*s.f(torch.cat([oo,z,t],1))
+ return z.view(B,k,AD)
+class MF(nn.Module): # MeanFlow (Geng et al. 2025)
+ def __init__(s): super().__init__(); s.f=mlp(4+AD+2,AD)
+ def u(s,o,z,r,t): return s.f(torch.cat([o,z,r,t],1))
+ def loss(s,o,a):
+ B=len(a); e=torch.randn_like(a)
+ t=torch.rand(B,1); r=torch.rand(B,1); t,r=torch.maximum(t,r),torch.minimum(t,r)
+ eq=(torch.rand(B,1)<0.75); r=torch.where(eq,t,r)
+ z=(1-t)*a+t*e; v=e-a
+ fn=lambda z_,r_,t_: s.u(o,z_,r_,t_)
+ u,dudt=torch.func.jvp(fn,(z,r,t),(v,torch.zeros_like(r),torch.ones_like(t)))
+ tgt=(v-(t-r)*dudt).detach()
+ return ((u-tgt)**2).mean()
+ def sample(s,o,k=1):
+ B=len(o); oo=o.repeat_interleave(k,0); e=torch.randn(B*k,AD)
+ x=e-s.u(oo,e,torch.zeros(B*k,1),torch.ones(B*k,1)); return x.view(B,k,AD)
+def train(m,iters=6000,bs=512):
+ opt=torch.optim.AdamW(m.parameters(),1e-3,weight_decay=1e-4)
+ sch=torch.optim.lr_scheduler.CosineAnnealingLR(opt,iters)
+ for it in range(iters):
+ idx=torch.randint(0,len(O),(bs,)); l=m.loss(O[idx],A[idx])
+ opt.zero_grad(); l.backward(); opt.step(); sch.step()
+ return m
+def seg_collide(p,q):
+ for a in np.linspace(0,1,6):
+ if np.linalg.norm(p+(q-p)*a)0 for r in res])
+ br=np.mean([r['brakes'] for r in res]); up=np.mean([r['mode']>0 for r in res if r['ok']]) if ok>0 else float('nan')
+ return dict(reach=round(ok,3),collide_ep=round(col,3),brakes=round(br,1),frac_up=round(up,2))
+methods={'MSE':lambda:MSE(),'WTA4':lambda:WTA(),'FM10':lambda:FM(10),'FM1':lambda:FM(1),'MeanFlow1':lambda:MF()}
+which=sys.argv[1:] or list(methods)
+out={}
+for name in which:
+ torch.manual_seed(0); t0=time.time(); m=train(methods[name]()); tt=time.time()-t0
+ o=torch.tensor(np.r_[[-2,0],[2,0]],dtype=torch.float32)[None]
+ t1=time.time(); [m.sample(o,8) for _ in range(50)]; lat=(time.time()-t1)/50*1000
+ r={'train_s':round(tt),'infer_ms_k8':round(lat,2)}
+ r['hard_raw_k1']=evaluate(m,1,False); r['hard_safe_k8']=evaluate(m,4 if name=='WTA4' else (1 if name=='MSE' else 8),True)
+ r['easy_raw_k1']=evaluate(m,1,False,hard=False)
+ out[name]=r; print(name,json.dumps(r,ensure_ascii=False),flush=True)
+json.dump(out,open(f'/workspace/work/toy/res_{"_".join(which)}.json','w'),indent=1)