From 5c74c152e97daa10d4a82d00607b7d427f86e1b1 Mon Sep 17 00:00:00 2001 From: Hark Date: Sat, 17 Oct 2026 15:48:19 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20Transformer=20=E6=8B=9F=E5=90=88?= =?UTF-8?q?=E9=81=BF=E9=9A=9C=E8=BD=A8=E8=BF=B9=E8=A7=84=E5=88=92=E8=AE=AD?= =?UTF-8?q?=E7=BB=83=E6=96=B9=E6=A1=88=EF=BC=88=E6=9C=80=E7=BB=88=E7=89=88?= =?UTF-8?q?=EF=BC=89=EF=BC=9A=E6=97=A0=E8=80=81=E5=B8=88=E9=97=AD=E7=8E=AF?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E3=80=81MeanFlow=20=E5=8A=A8=E4=BD=9C?= =?UTF-8?q?=E5=A4=B4=EF=BC=88WTA=20K=3D8=20=E5=9B=9E=E9=80=80=EF=BC=89?= =?UTF-8?q?=E3=80=81=E8=B7=9D=E7=A6=BB=E4=B8=8B=E7=95=8C=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E8=AE=A4=E8=AF=81=E3=80=81APG=20=E5=90=8E=E8=AE=AD=E7=BB=83?= =?UTF-8?q?=E4=B8=8E=E6=8C=96=E9=94=99=E5=BE=AA=E7=8E=AF=E3=80=81=E9=87=8C?= =?UTF-8?q?=E7=A8=8B=E7=A2=91=20M1=E2=80=93M8=EF=BC=9B=E9=99=84=20HTML=20?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/Transformer轨迹拟合训练方案.html | 1706 +++++++++++++++++++++++++ docs/Transformer轨迹拟合训练方案.md | 521 ++++++++ ml/toy/toy_bimodal.py | 123 ++ 3 files changed, 2350 insertions(+) create mode 100644 docs/Transformer轨迹拟合训练方案.html create mode 100644 docs/Transformer轨迹拟合训练方案.md create mode 100644 ml/toy/toy_bimodal.py 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 避障运动策略:最终方案 + + + + +
+

Transformer 避障运动策略:最终方案

+
+ +

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 大模型AIMPACT 4.67M、300 Hz;π0 3B 单次预填充 46 ms(4090)
数据规划器离线造 5 万条任务 → 约 200 万"状态→动作块"样本BMπNets、DRP、ELMP 均用规划器老师
时间律匀速巡航 + 梯形加减速,只依赖"当前速度 + +剩余路程";当前速度作输入BMπNets 将老师路径重定时为匀速
动作表示16 步 × 6 轴关节增量 ΔqADRP;Diffusion Policy(位置式优于速度式)
动作头MeanFlow 一步生成头,每次并行采 8 个噪声 → 8 +条候选B沙箱双模态实验(§2.4);MP1 约 6.8 ms
块间连续训练时前缀条件化:输入已提交未执行的步B2512.05964:推理零开销,d≥2 时优于推理时 RTC
碰撞修正输出后 1 步解析胶囊距离梯度投影(每轴 ≤ 0.5°,仅 d < +余量时)BDiffusionSeeder:少步生成下在环引导收益很小;投影在已知环境下够用
候选排序与已提交块重叠步的一致性打分 + 价值头BBID:一致性打分 + 多样本相对提升 32%
预训练行为克隆 + FK 胶囊端点损失BELMP 式 FK 损失
后训练(主)APG:可微运动学展开 + 胶囊距离代价反传AELMP:碰撞率 31.3%→8.9%;1 万示范 + APG 胜 60 万纯 BC
后训练(辅)无老师挖错循环 + 门禁BDRP 迭代微调 +45%
安全层距离下界认证 + 可刹停不变式ASchwarzer 2005 连续认证;Thumm & Althoff 2022 failsafe
30/30 手段子目标头、价值头、冷启动/卡死时短前瞻、卡死换向B / CAWE、SHAC、BID
老师PRM 路网 A* + 捷径平滑(确定性);A* 失败才用 +solveDynBMπNets:老师不一致碰撞率 13.78%,一致老师 0.94%
推理后端onnxruntime-web wasm-SIMD 多线程C小模型下 WebGPU 调度开销占主导
+

1.1 +取舍决定(每项只有一个答案)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
选项利弊决定
动作头:MeanFlow 一步头 vs WTA K=4MeanFlow:连续多模态,能同时表达左/右绕行与位姿目标的多个 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 solveDynA*:确定性,同类任务左右选择一致,且是路网上的最短;solveDyn +覆盖更全A*:受路网分辨率限制,个别任务失败A 为主老师*,失败的任务用 +solveDyn(固定种子)补
推理后端:WebGPU vs wasmWebGPU 大模型快本模型约 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
+ +

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% / 00.13 ms
WTA K=4100% / 0%100% / 0% / 00.19 ms
流匹配 10 步100% / 4.0%99.3% / 0% / 3.72.13 ms
朴素流匹配 1 步87.3% / 23.3%81.3% / 0% / 14.00.25 ms
MeanFlow 1 步100% / 2.7%100% / 0% / 0.30.25 ms
+ +
+

3. 训练环境

+ + + + + + + + + + + + + + + + + + + + + + + + + +
阶段在哪里跑说明
数据生成Hark 沙箱(2 vCPU / 7 GB,Node)或用户机器纯 JS,无需 GPU
预训练 + 后训练用户 RTX 3090 24 GBbatch 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%目标在立柱内/所有分支都撞/工作空间外;标签为停靠
+ +

4.4 过滤

+
    +
  1. 整条路径用距离下界认证(与 §8.3 同口径)复核,任一段不过即丢弃。仓库 +tests/route_bench.cjs 上现有规划器有 1/40 +例路径细验不过,这类样本必须丢掉。
  2. +
  3. poseRelaxed 样本只当 pos 模式用。
  4. +
  5. 行程 > 同任务 routeRT 1.5 +倍的先统计,再定是否丢弃;按类别统计丢弃率(C 类 > 20% +说明老师在贴柱场景不可靠)。
  6. +
+

4.5 时间参数化 → 闭环训练样本

+
    +
  1. 时间律:按轴速比 VREL = [0.6, 0.6, 0.9, 0.9, 1.2, 1.8] +匀速巡航,梯形加减速,速度只取决于"当前速度 + 剩余路程"(每轴加速度上限 +a_max 为待定参数,真机型号确定后设定),dt = 20 ms。
  2. +
  3. 得到状态序列 q_0 … q_N,每隔 3 步取一个样本: +
      +
    • 输入:§5.1 全部字段(含当前速度、已提交前缀)
    • +
    • 标签:未来 16 步 Δq_{t+k} = q_{t+k} − q_t(到终点后补零)
    • +
  4. +
  5. 每条路径约 40–50 个样本 → 约 200 万样本(以 stats.json +为准)。
  6. +
  7. 协变量偏移对策:关节噪声增广(σ = +1°,噪声状态由老师离线重标);偏离状态的进一步覆盖靠 §7。
  8. +
+

4.6 耗时与存储

+ +

4.7 检查点

+ +
+

5. 表示与预处理

+

文件 ml/prep/build_dataset.py → +train/val/test.parquet、norm.json。

+

5.1 输入

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
量维度编码
当前 q_t6每轴 (sin, cos) → 12;限位轴另加归一化值 → +3
当前关节速度 q_t − q_{t−1}6按每轴速度上限归一化
当前 TCP 位置与姿态3 + 6fk(q_t)、orient(q_t) 的 6D 表示
目标位置 T3/600 mm
目标姿态 R66D 表示;pos 模式填 0
目标 − 当前 TCP3/600 mm
模式2one-hot [pos, pose]
已提交未执行前缀3×6 + 3前缀 Δq + 有效长度掩码;训练时随机遮盖 0–3 步
当前子目标6子目标头输出的关节途经点(归一化);无子目标时填当前 q
关键胶囊对最小距离8臂各段到立柱的胶囊距离
+

5.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 / 头数 / FFN192 / 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 步,余弦退火
batch1024
精度bf16 混合精度
步数先跑 2000 步测吞吐再定;参考 200 万样本 × 30 epoch ÷ 1024 ≈ 6 +万步;验证集闭环到达率不再上升即停
预计耗时RTX 3090 约 1.5–5.6 小时(按 2000 步吞吐实测重算)
+

6.5 对拍与验证

+ +
+

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
+ +

7.2 辅助:无老师挖错循环

+

每轮:

+
    +
  1. 出题:新种子 5 万任务 + 2000 段模型在环拖拽仿真。
  2. +
  3. 闭环作答:完全按部署方式运行,关闭安全层以暴露真实错误。
  4. +
  5. 验算:GPU 批量胶囊检查。
  6. +
  7. 错题分类:E1 撞 / E2 没到(卡在局部极小)/ E3 绕远(> 1.2× +参考)/ E4 末端精度差 / E5 摇摆(≥ 3 次切换)/ E6 拖拽失稳。
  8. +
  9. 错题及其 ±5 mm / ±3° 的 10 个邻居加入 APG 采样池(E1、E6 ×2);仅 E2 +可离线请老师补少量路径。
  10. +
  11. 门禁(用门禁集,不用验收集):到达率上升、A 类每轮降幅 ≤ 0.5 +个百分点、上一轮修好的错题 95% 仍对;否则回滚。
  12. +
  13. 停止:连续 2 轮提升 < 0.5 个百分点,或满 6 轮。
  14. +
+
+

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 安全层(唯一的硬保证)

+ +

8.4 部署包

+ + + + + + + + + + + + + + + + + + + + + +
有没有
traj_policy.onnx(fp16,约 8.3 MB)+ +norm.jsonPRM 路网、IK 候选大表
胶囊距离与认证(collideFree、包围球预筛、pair2d)solveDyn / routeRT / RRT / A*
fk / orient、局部牛顿精修 +solveTo 单步全量 IK 枚举
+

collide.json +指纹写进模型;不一致时前端拒绝运行并提示重训。

+

8.5 near_column 30/30 +的保障手段

+

"超时"指机械臂在规定时间内没走到目标,是决策问题而非计算速度问题。典型失效:局部极小/活锁(每次都想直穿、每次被安全层挡住)、左右摇摆、绕远。对策(运行时均不需要老师):

+
    +
  1. 子目标头:给出 1–2 +个关节途经点作为绕柱方向锚点,标签取老师路径拐点(离线)。
  2. +
  3. 价值头:预测剩余时间/代价,用于候选打分与进展判断;APG +中用 TD 自举监督。
  4. +
  5. 短前瞻(仅冷启动和卡死换向时):对每条候选再推一块,用胶囊认证 ++ 价值头给 32 步后终态打分。
  6. +
  7. 卡死检测 + 强制换向:0.3 s 内价值不降或连续 2 +次刹停 → 切到另一绕行方向并锁定 1 s。
  8. +
  9. 训练侧加强:贴柱类占 APG 采样 +40%;展开覆盖整段绕行。
  10. +
+

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_benchtests/route_bench.cjs(40 例)+ 60 例随机基准验收
near_column_benchtests/near_column_bench.cjs,30 例(pos / pose / +rt)验收
near_column 扩展§4.3 新造 ≥1000 例一次性验收
rt_drag_benchtests/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 mmroute_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/30near_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(最大不确定项)
R5MeanFlow 头在 6 轴、位姿目标下穿柱或训练不稳near_column 穿柱率(关安全层)≤ 2%;损失不发散同骨干换 WTA K=8 头M5
R6位姿目标的多 IK 分支带来额外多峰不同肘/腕分支子集到达率 ≥ 主集 − 2 个百分点加目标分支标志M5
R7APG 压缩多模态或拉长路径(ELMP 中路径 +23%)每轮左右比例与行程门禁加大 BC 锚定权重;行程项M6
R8卡死换向活锁50 个"两侧都要绕远"对抗用例 3 s 内恢复 ≥ 95%,活锁 = 0子目标改为离散绕行锚点分类M6 / M7
R9安全层贴柱时耗时超标near_column 全程 P99 < 5 msWeb Worker 流水线;提交步数降到 2M7
R10训练耗时估计偏差2000 步吞吐 ≥ 2 万样本/s降 epoch 或增大 batchM5
+

10.2 已知缺陷

+
    +
  1. 现有规划器(老师)在 tests/route_bench.cjs 上有 1/40 +例到达但路径细验不过;§4.4 的认证过滤会丢弃这类样本。
  2. +
  3. ci27 姿态根枚举漏分支(姿态偏差约 97.5°)会影响 pose +数据;APG 姿态项可部分纠正,必要时先修老师。
  4. +
  5. 胶囊模型或立柱变动即需重训:数据约 5 h + 预训练 1.5–5.6 h + 后训练 +2–4 h。
  6. +
+

10.3 需要用户确认

+
    +
  1. 真机电机/驱动型号与通信方式:决定每轴加速度上限 +a_max、插补频率与提交步数。
  2. +
  3. 运行时多候选打分是否算"运行时老师":本方案的理解是不算(只对模型自己的候选做距离认证和打分,不做搜索)。
  4. +
+
+

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、认证模块沙箱
M35 万条老师数据 → 约 200 万样本Parquet沙箱约 5 h 或用户机器
M4模型 + 训练工程 + 闭环仿真;小数据过拟合;导出 ONNX +测浏览器延迟train.py、closed_loop.py、延迟报告沙箱 + 浏览器
M5预训练 + MeanFlow 头门禁checkpoint、门禁报告用户 GPU
M6APG 微调 + 挖错循环 3–6 轮每轮 report.md用户 GPU
M7ik-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)