diff --git a/docs/Transformer轨迹拟合训练方案.html b/docs/Transformer轨迹拟合训练方案.html
new file mode 100644
index 0000000..35122a3
--- /dev/null
+++ b/docs/Transformer轨迹拟合训练方案.html
@@ -0,0 +1,1253 @@
+
+
+
+
+
+
+ Transformer 避障运动策略:无老师闭环部署方案(v2)
+
+
+
+
+
+
+
+
+
+
+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 验收。
+
+
+
+0. 定位与边界
+
+
+
+
+
+
+部署形态
+无老师 :运行时只有「神经策略 + 碰撞安全层」,不加载
+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)。
+我们的环境几何完全已知、检查只要几毫秒,保留它代价极小,却把"偶尔撞一下"变成"偶尔停一下"。
+
+1.
+业界调研:具身智能里的神经运动规划
+以下数据均来自论文原文(链接见 §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:迭代师生微调使成功率比纯预训练提高
+45% ;纯预训练的 IMPACT "经常有轻微碰撞"。
+ELMP:只用 1 万条老师轨迹 + APG(成功率 72.0%、碰撞 19.4%)就超过 60
+万条纯行为克隆(57.9%、31.9%),老师数据少 60 倍 ;APG
+把环境碰撞率降到原来的 1/3 以下。新环境下,采样 20 万个 APG 问题约 4.5
+CPU 小时,而生成同样数量的老师轨迹要 1194 CPU 小时以上。
+即便最好的方法,静态场景碰撞率也约 9–10%(ELMP-APG 8.9%,DRP
+10.16%)——所以实际部署都配有某种检查或反应层。
+
+行业共识 :
+
+都是闭环 策略,每个周期根据当前状态重新出动作,而不是一次性出整条路径。
+输出短动作块 (10
+步左右)并滚动执行,兼顾平滑和反应速度。
+老师只用于离线造数据;微调阶段倾向于便宜的老师 (局部控制器)或不要老师 (可微代价)。
+纯模仿有"分布偏移、误差累积"问题,必须做后训练(DAgger / 师生微调 /
+APG)。
+
+
+2.
+我们的方案和主流的差异,以及据此做的优化
+2.1 我们的独特条件
+
+
+
+
+
+
+环境
+未知、多变,靠点云感知
+固定且精确已知 (台架 + 立柱,1936 个胶囊)
+不需要点云编码器;模型可以小很多;碰撞检查是精确 的
+
+
+机器人
+Franka 7 轴
+自研 6 轴,J1/J3/J6 连续转
+需处理连续轴展开
+
+
+碰撞模型
+SDF / 球近似,有感知噪声
+胶囊解析距离,可微
+可以直接做 APG;安全层可信
+
+
+运行平台
+台式 GPU
+浏览器(后续真机)
+模型要小,ONNX + WebGPU/wasm
+
+
+
+结论:我们的问题比主流窄得多也"干净"得多 ,主流用来对付感知噪声和环境泛化的大部分复杂度(点云、千万级数据、多环境)都可以省掉,资源应投在闭环稳定性、多解选择和安全层 上。
+2.2 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 局部反应层
+暂不做;安全层已覆盖静态环境。未来真机有人/动态障碍时再加
+当前环境静态
+
+
+
+2.3 v2 相对主流的额外优化点
+
+精确安全层 :主流因感知噪声做不到精确检查,我们可以。每周期对即将执行的动作段做
+1° 细验 + 半格复验,保证只执行检查过的动作 。
+可刹停不变式 :只有当"执行这一段之后,仍存在一条已检查过的刹停轨迹"时才执行(见
+§8.3),保证任何周期推理失败都能安全停住。
+模式粘滞 :闭环每周期重算最怕左右摇摆(这一帧选左绕、下一帧选右绕)。部署时对"切换模式"加代价,除非当前模式不安全(§8.2)。
+APG
+损失直接用我们的胶囊距离 (segSegDist
+的可微版本),训练和部署检查同一套几何,消除"训练用球、检查用网格"的口径差(ELMP
+的做法有这个差)。
+数据便宜 :环境固定,老师离线 5 万条在沙箱约 5
+小时即可,不需要集群。
+
+
+3. 训练环境
+
+
+
+
+
+
+预训练数据生成
+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
+
+4.
+第一步:离线造预训练数据(老师只在这里出现)
+4.1 新增文件
+
+
+
+
+
+
+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)。
+4.2 一条原始样本
+{
+ "id" : "s0003_000127" , "mode" : "pos" | "pose" ,
+ "q0" : [ 6 ] , "T" : [ x , y , z ] , "R" : [[ 3 x3 ]] | 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 指纹"
+}
+4.3 采样分布(5 万条任务)
+关节限位(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%
+目标在立柱内/所有分支都撞/工作空间外;老师标签 =
+停在离目标最近的安全位形
+
+
+
+
+pos / pose 各半;老师用 solveDyn(松手口径)。
+测试集隔离 :固定种子另造 2000
+条留出;三个基准案例不进训练集。
+
+4.4 过滤
+
+整条路径 1° 细验 + 半格复验,任一段干涉即丢弃。
+poseRelaxed 样本只当 pos 模式用。
+行程 > 同任务 routeRT 1.5
+倍的视为绕远(先统计,再定是否丢弃)。
+
+4.5 时间参数化 →
+闭环训练样本(v2 新增,关键)
+闭环策略学的是"在某个状态下,接下来 16
+步怎么走",所以要把整条路径切成很多个"状态 → 动作块"样本:
+
+按现有 animTo 的轴速比
+VREL = [0.6, 0.6, 0.9, 0.9, 1.2, 1.8]
+做时间参数化(与查看器动画同口径),控制周期 dt = 20
+ms 。
+得到状态序列 q_0, q_1, …, q_N。对每个 t(每隔 3 步取 1
+个,减少冗余)生成样本:
+
+输入:当前 q_t、目标 (T, R, mode)
+标签:未来 S = 16 步的增量 Δq_{t+1..t+16} = q_{t+k} −
+q_t(到终点后补零,即"停住")
+
+每条路径平均约 50–150 个样本 → 5 万条任务约 300 万个训练样本。
+路径后缀天然覆盖"从半路出发" ,等于免费的 DAgger
+种子数据。
+
+4.6 耗时与存储
+
+solveDyn 约 0.7 s/条:5 万条在沙箱 2 进程约 5
+小时;用户 8 核机器约 1.5 小时。
+300 万样本 × 约 0.5 KB ≈ 1.5 GB 原始;Parquet 约 300 MB。
+
+4.7 检查点
+
+
+5. 第二步:表示与预处理
+文件 ml/prep/build_dataset.py →
+train/val/test.parquet、norm.json。
+5.1 输入(条件)
+
+
+
+
+
+
+当前 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,现成函数),给模型"离柱子多近"的直接信号
+
+
+
+5.2 输出(动作块)
+
+K = 4 个模式 ,每个模式一整块 16 步 × 6 轴的关节增量
+Δq(连续值,按每轴最大步长归一化)。
+一个模式分类头:4 类 logits。
+训练时
+winner-takes-all :只对与标签最接近的那个模式回归,分类头学"选哪个"(MTR
+/
+多模态轨迹预测的常用做法)。这样左绕、右绕会落到不同模式里,不会被平均到穿过立柱。
+附加头:到达剩余时间估计(帮助排序和早停)。
+
+5.3 连续轴
+J1/J3/J6 统一用 unwrapTo
+口径展开后再做增量;预处理和部署共用一份实现,§6.4 对拍时一并验证。
+
+6.
+第三步:模型与预训练(行为克隆)
+6.1 结构(参考
+IMPACT,去掉点云部分)
+条件特征(约 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 条候选动作块
+
+
+
+6.2 预训练损失
+L = WTA-L1(动作块, 最近模式) 权重 1.0
+ + CE(模式分类) 权重 0.5
+ + FK 损失:预测与标签位形下各连杆胶囊端点的位置差 权重 0.5 ← 借鉴 ELMP
+ + 平滑:二阶差分 权重 0.05
+ + L1(剩余时间) 权重 0.1
+6.3 训练配置
+
+
+
+
+
+
+优化器
+AdamW,β=(0.9, 0.95),wd 0.01
+
+
+学习率
+1e-3,预热 1000 步,余弦退火(同 DRP 量级)
+
+
+batch
+512
+
+
+精度
+bf16 混合精度
+
+
+步数
+约 20 万步(300 万样本约 30
+epoch),验证集闭环成功率不再上升即停
+
+
+预计耗时
+RTX 3060 约 3–5 小时(估算,跑完首轮校正)
+
+
+
+6.4 对拍与验证(每 epoch)
+
+ml/eval/collide_torch.py:胶囊距离的 PyTorch
+批量版(可微 ,§7 要用),先与 JS
+collideFree 对拍 10 万个位形,判定 0 误差。
+验证用闭环仿真 而不是单步误差:从 1000 个验证任务的
+q0 出发,每 20 ms 推理一次、执行前 3 步、直到到达或 6 s
+超时,统计到达率、碰撞步数(安全层关闭时)、行程比。
+
+
+7. 第四步:后训练(无老师为主)
+7.1 主力:APG 可微微调(借鉴
+ELMP)
+不再请老师标注,直接让模型在可微仿真里闭环展开,用代价反传:
+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
+
+碰撞项 L_col = Σ_胶囊对 ReLU(margin −
+胶囊距离),margin 取 collide.json 的 margin_mm
+基础上再加 5 mm 训练余量;包含臂×立柱、臂×台架、臂×臂(非相邻段)。
+到达项 :位置误差² + λ_rot·‖R − R*‖_F²(弦距离,ELMP
+同款,避免四元数梯度消失)。
+平滑项 :速度² + 加速度²。
+可加 行程项 ,直接把"关节行程短"写进目标(ELMP
+用笛卡尔路径长度项做过同类事情)。
+模式选择不可导:用 Gumbel-Softmax,或对 K 个模式都展开 1
+步再取最小代价(K=4,代价可接受)。
+采样任务分布同 §4.3,但 B/C/D 类提到 60%。
+预期:参照 ELMP,APG
+主要降低碰撞率、提高末端精度;不需要任何老师计算 。
+
+7.2 辅助:闭环挖错 +
+门禁(v1.1 循环的无老师版)
+每轮:
+
+出题 :新种子 5 万任务 + 2000
+段模型在环拖拽仿真(目标沿随机曲线移动)。
+闭环作答 :完全按部署方式运行(含模式粘滞,关闭安全层 以暴露真实错误)。
+验算 :GPU
+批量胶囊检查;记录到达、碰撞、行程、摇摆次数。
+错题分类 :E1 撞了 / E2 没到(超时或卡在局部极小)/
+E3 绕远(> 1.2× 参考)/ E4 末端精度差 / E5 模式来回切换 ≥ 3 次 / E6
+拖拽失稳。
+针对性训练 :错题的起点和目标(以及 ±5 mm / ±3° 的
+10 个邻居)加入 APG 的采样池,按类别加权(E1、E6 ×2)。
+
+只有
+E2(卡在局部极小——可微代价本身解决不了的"需要绕远路"问题)才可选地请老师离线给一条路径做行为克隆补充。这是唯一残留的老师用途,量很小,可以在沙箱慢慢跑。
+
+门禁 :留出集闭环到达率上升、三个基准不退化、上一轮修好的错题
+95% 仍对;否则回滚。
+停止 :连续 2 轮提升 < 0.5 个百分点,或满 6
+轮,或达到 §9 全部标准。
+
+7.3 可选:拒绝采样自蒸馏
+对每个任务采样多条闭环轨迹(不同模式、不同温度),只保留验算通过且最短的一条做行为克隆标签——模型自己当老师。适合
+APG 收敛后进一步缩短行程。
+
+8. 第五步:无老师闭环部署
+8.1 每个控制周期做什么(默认 50
+Hz)
+每 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 一顿。
+8.2 模式粘滞(防左右摇摆)
+
+排序分数 = log p(k) − c·[k ≠ k_prev],c 初值 2.0(在 §7.2 的 E5
+统计上调)。
+训练时 k_prev
+作为输入(§5.1),模型自己也学会"保持当前绕行方向"。
+
+8.3 安全层(唯一的硬保证)
+
+检查内容:候选前 3 步的连续运动做 1° 细验 + 半格复验(与现有
+pathFine 同口径),外加关节限位。
+可刹停不变式 :执行前还要检查"从第 3
+步末状态按最大减速度停下"的刹停段也无干涉。于是任何时候系统都处在"有一条已验证的停车路线"的状态,下一周期就算模型完全失效,也只会停下、不会撞。
+耗时:3 步 × 4 候选,最坏约 4 × 10 个采样位形 × 约 1.8 ms ≈ 70
+ms(太慢)→ 实际做法:
+
+先用现有包围球预筛(大多数位形直接判安全,见 2026-10-15 记录
+collideFree 2.9→1.8 ms);
+按排序逐个 检查,第一个通过就停(多数周期只检查 1
+条);
+目标:每周期安全检查 < 5 ms(需在 M6 实测;不达标则把检查放到 Web
+Worker 与推理流水线并行)。
+
+现有 ik-glue.js
+的"每帧碰撞守卫"保留,作为第二道保险。
+
+8.4 部署包里有什么、没有什么
+
+
+
+
+
+
+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
+指纹写进模型;不一致时前端拒绝运行并提示重训 (不再回落旧规划器)。
+
+9. 第六步:评估与验收
+9.1 测试集合
+
+
+
+
+
+
+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:①现有规划器
+②策略(关安全层)③策略 + 安全层(部署形态),输出对比表。
+9.2 验收标准(部署形态 = 策略
++ 安全层)
+
+
+
+
+
+
+实际执行的碰撞帧
+= 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
+超时内可能失败;这一条请审查时确认能否接受。
+
+10. 风险与维护
+
+局部极小 :可微代价和闭环策略都可能卡在立柱前"想直穿过去又被安全层挡住"。对策:B/C
+类数据加权、模式头学左右绕、E2
+错题少量老师补数据(§7.2)。这是无老师方案最大的风险。
+碰撞模型/立柱变动 =
+重训 :指纹不一致即拒绝运行。重训流程:§4(约 5 h)→ §6(约 4
+h)→ §7(约 2–4 h)。
+安全层耗时 :最坏周期可能超 5 ms,见 §8.3
+的流水线方案。
+老师缺陷 :ci27
+姿态根枚举漏分支(姿态偏差约 97.5°)会进入预训练数据;APG
+的姿态到达项可以部分纠正,必要时先修老师。
+真机迁移 :浏览器的"执行"是理想插补;真机需加速度/力矩限制(TOPP
+类时间参数化)和跟踪误差余量(把 margin 再加大)。
+
+
+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
+ 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
+12. 里程碑
+
+
+
+
+
+
+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 离线使用)
+部署包瘦身
+沙箱
+
+
+
+13. 参考文献
+
+Fishman et al., Motion Policy Networks , CoRL 2022. https://arxiv.org/abs/2210.12209
+;闭环细节见补充材料 https://proceedings.mlr.press/v205/fishman23a/fishman23a-supp.pdf
+Dalal et al., Neural MP: A Generalist Neural Motion
+Planner , 2024 / IROS 2025. https://arxiv.org/abs/2409.05864
+Yang, Liu et al., Deep Reactive Policy: Learning Reactive
+Manipulator Motion Planning for Dynamic Environments , CoRL 2025. https://arxiv.org/abs/2509.06953
+Fishman et al., Avoid Everything: Model-Free Collision Avoidance
+with Expert-Guided Fine-Tuning , CoRL 2024 Workshop(DRP 文中引用为
+MπFormer)
+Li et al., ELMP: Efficient Learning for Motion Planning via
+Analytical Policy Gradients , arXiv 2607.00215, 2026. https://arxiv.org/abs/2607.00215
+Ross, Gordon, Bagnell, A Reduction of Imitation Learning and
+Structured Prediction to No-Regret Online
+Learning (DAgger),AISTATS 2011
+
+14. 需要用户确认
+
+训练机显卡型号与显存。
+§9.2 中 near_column 允许
+29/30(无老师下最难案例可能超时)是否接受。
+控制周期 50 Hz、每周期执行 3 步(60
+ms)作为默认值是否合适(真机控制器频率如有要求请告知)。
+
+
+
diff --git a/docs/Transformer轨迹拟合训练方案.md b/docs/Transformer轨迹拟合训练方案.md
index 99f7c8d..ca269f1 100644
--- a/docs/Transformer轨迹拟合训练方案.md
+++ b/docs/Transformer轨迹拟合训练方案.md
@@ -1,7 +1,11 @@
-# Transformer 拟合避障轨迹规划:训练方案(审查稿)
+# Transformer 避障运动策略:无老师闭环部署方案(审查稿 v2)
-> 2026-10-17 起草,基于 `main@3c7c814`(贴立柱修复后的规划器)。本文只是方案,代码尚未编写。
-> 审查时重点看:§0 定位、§2 数据分布、§3 表示方式、§5 训练配置、§5A 后训练循环、§7 验收标准。
+> - 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 验收。
---
@@ -9,25 +13,88 @@
| 项目 | 决定 |
|---|---|
-| 模型角色 | **提议器**:给出若干条候选关节轨迹,由现有 `collideFree` + 半格复验把关,全部不合法时回落 `routeRT` / `solveDyn` |
-| 不做的事 | 不让模型直接驱动电机;不替代碰撞检测;不学习动力学(速度/加速度仍由 `animTo` 时间参数化) |
-| 老师 | 当前 JS 规划器(`webapp/js/ik-solver.js`):松手口径用 `S.solveDyn(T, opt)`,拖拽口径用 `S.solveRoute(T, {quick:true,...})` |
-| 收益目标 | 实时拖拽重规划 P99 ≈ 321 ms → **< 50 ms**;首次全量 IK 尖峰(最差约 2 s)→ < 100 ms |
-| 底线 | 「模型+验证+回落」整体的到达率、路径合法率**不得低于**现有规划器(任何基准上都不允许退化) |
+| 部署形态 | **无老师**:运行时只有「神经策略 + 碰撞安全层」,不加载 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)。
+我们的环境几何完全已知、检查只要几毫秒,保留它代价极小,却把"偶尔撞一下"变成"偶尔停一下"。
---
-## 1. 训练环境
+## 1. 业界调研:具身智能里的神经运动规划
+
+以下数据均来自论文原文(链接见 §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:迭代师生微调使成功率比纯预训练**提高 45%**;纯预训练的 IMPACT "经常有轻微碰撞"。
+- ELMP:只用 1 万条老师轨迹 + APG(成功率 72.0%、碰撞 19.4%)就超过 60 万条纯行为克隆(57.9%、31.9%),**老师数据少 60 倍**;APG 把环境碰撞率降到原来的 1/3 以下。新环境下,采样 20 万个 APG 问题约 4.5 CPU 小时,而生成同样数量的老师轨迹要 1194 CPU 小时以上。
+- 即便最好的方法,静态场景碰撞率也约 9–10%(ELMP-APG 8.9%,DRP 10.16%)——所以实际部署都配有某种检查或反应层。
+
+**行业共识**:
+1. 都是**闭环**策略,每个周期根据当前状态重新出动作,而不是一次性出整条路径。
+2. 输出**短动作块**(10 步左右)并滚动执行,兼顾平滑和反应速度。
+3. 老师只用于离线造数据;微调阶段倾向于**便宜的老师**(局部控制器)或**不要老师**(可微代价)。
+4. 纯模仿有"分布偏移、误差累积"问题,必须做后训练(DAgger / 师生微调 / APG)。
+
+---
+
+## 2. 我们的方案和主流的差异,以及据此做的优化
+
+### 2.1 我们的独特条件
+
+| 条件 | 主流(DRP/ELMP 等) | 本项目 | 意味着 |
+|---|---|---|---|
+| 环境 | 未知、多变,靠点云感知 | **固定且精确已知**(台架 + 立柱,1936 个胶囊) | 不需要点云编码器;模型可以小很多;碰撞检查是**精确**的 |
+| 机器人 | Franka 7 轴 | 自研 6 轴,J1/J3/J6 连续转 | 需处理连续轴展开 |
+| 碰撞模型 | SDF / 球近似,有感知噪声 | 胶囊解析距离,可微 | 可以直接做 APG;安全层可信 |
+| 运行平台 | 台式 GPU | 浏览器(后续真机) | 模型要小,ONNX + WebGPU/wasm |
+
+结论:我们的问题比主流**窄得多也"干净"得多**,主流用来对付感知噪声和环境泛化的大部分复杂度(点云、千万级数据、多环境)都可以省掉,资源应投在**闭环稳定性、多解选择和安全层**上。
+
+### 2.2 v1 方案与主流的差异 → v2 的调整
+
+| # | 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 局部反应层 | 暂不做;安全层已覆盖静态环境。未来真机有人/动态障碍时再加 | 当前环境静态 |
+
+### 2.3 v2 相对主流的额外优化点
+
+1. **精确安全层**:主流因感知噪声做不到精确检查,我们可以。每周期对即将执行的动作段做 1° 细验 + 半格复验,保证**只执行检查过的动作**。
+2. **可刹停不变式**:只有当"执行这一段之后,仍存在一条已检查过的刹停轨迹"时才执行(见 §8.3),保证任何周期推理失败都能安全停住。
+3. **模式粘滞**:闭环每周期重算最怕左右摇摆(这一帧选左绕、下一帧选右绕)。部署时对"切换模式"加代价,除非当前模式不安全(§8.2)。
+4. **APG 损失直接用我们的胶囊距离**(`segSegDist` 的可微版本),训练和部署检查同一套几何,消除"训练用球、检查用网格"的口径差(ELMP 的做法有这个差)。
+5. **数据便宜**:环境固定,老师离线 5 万条在沙箱约 5 小时即可,不需要集群。
+
+---
+
+## 3. 训练环境
| 阶段 | 在哪里跑 | 说明 |
|---|---|---|
-| 数据生成 | Hark 沙箱(2 vCPU / 7 GB,Node) 或 用户机器 | 纯 JS,无需 GPU;可多进程并行 |
-| 训练 | **用户的 GPU 机器** | 沙箱无 GPU、无 PyTorch。最低建议 8 GB 显存(RTX 3060 级别) |
-| 部署推理 | 浏览器(onnxruntime-web,WebGPU 优先,wasm 兜底) | 与现有查看器同页运行 |
-
-Python 环境(训练机):
+| 预训练数据生成 | Hark 沙箱(2 vCPU / 7 GB,Node)或用户机器 | 纯 JS,无需 GPU |
+| 预训练 + APG 微调 | **用户的 GPU 机器** | 沙箱无 GPU、无 PyTorch。建议 ≥ 8 GB 显存(RTX 3060 级别) |
+| 部署推理 | 浏览器(onnxruntime-web,WebGPU 优先,wasm 兜底);后续真机控制器 | 与现有查看器同页 |
```bash
conda create -n armtf python=3.11 -y && conda activate armtf
@@ -37,385 +104,329 @@ pip install numpy pyarrow tqdm tensorboard onnx onnxruntime
---
-## 2. 第一步:生成数据(规划器当老师)
+## 4. 第一步:离线造预训练数据(老师只在这里出现)
-### 2.1 新增文件
+### 4.1 新增文件
| 文件 | 作用 |
|---|---|
-| `ml/gen/gen_dataset.cjs` | 采样任务 → 调用规划器 → 校验 → 写分片 |
-| `ml/gen/sampler.cjs` | 起点/目标采样器(三类分布,见 2.3) |
-| `ml/gen/run_parallel.sh` | 按 CPU 核数起 N 个进程,每个进程不同随机种子 |
-| `ml/data/shard_XXXX.jsonl` | 原始样本分片(每片 5000 条) |
+| `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`,无需网格)。
+复用 `tests/route_bench_setup.cjs` 装配求解器(关节表、`docs/travel.json`、`docs/collide.json`)。
-### 2.2 单条样本的字段
+### 4.2 一条原始样本
```json
{
- "id": "s0003_000127",
- "mode": "pos" | "pose",
- "teacher": "dyn" | "rt",
- "q0": [6 个关节角, 度],
- "T": [x, y, z], // 目标 TCP 位置, mm
- "R": [[3x3]] | null, // 目标姿态(pose 模式)
- "tool": 0,
- "path": [[6], [6], ...], // 老师给出的折线: q0 → via... → q
- "q_goal": [6],
- "ok": true, // 到达 (误差<1mm, pose 另需<0.5°) 且 1° 细验无干涉
- "poseRelaxed": false,
- "travel_deg": 123.4,
- "plan_ms": 812.0,
- "fp": "collide.json 指纹" // modelFingerprint(),碰撞模型变了旧数据作废
+ "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 指纹"
}
```
-### 2.3 采样分布(目标 20 万条原始任务)
+### 4.3 采样分布(5 万条任务)
-关节限位(`docs/travel.json`):J1/J3/J6 连续 ±180°;J2 [-92, 9],J4 [-111, 16],J5 [-93, 34]。
+关节限位(`docs/travel.json`):J1/J3/J6 连续 ±180°;J2 [−92, 9],J4 [−111, 16],J5 [−93, 34]。
| 类别 | 占比 | 采样方式 |
|---|---:|---|
-| A 均匀 | 50% | 起点 q0、目标位形 b 均在限位内均匀采样且本身无干涉;目标取 `fk(b)`(pose 模式加 `orient(b)`) |
-| B 直线被挡 | 30% | 同 A,但要求 q0→b 关节直线 1° 细验有干涉(route_bench 的生成口径) |
-| C 贴立柱 | 15% | b 满足 `nearColumn`(J1/J2/J3 任一 ±4° 即撞立柱),q0 在立柱另一侧(near_column_bench 口径) |
-| D 不可达/无安全解 | 5% | 目标在工作空间外或所有 IK 分支都撞;标签为"拒绝",教模型说"到不了" |
+| 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% | 目标在立柱内/所有分支都撞/工作空间外;老师标签 = 停在离目标最近的安全位形 |
-- `mode`:pos 与 pose 各 50%。
-- 老师:每条任务用 `solveDyn` 求一次(松手口径,质量更高);其中 30% 额外用 `routeRT` 拖拽口径求一次,作为"快速路径"风格的辅助样本(`teacher:"rt"`),训练时可按需过滤。
-- **测试集隔离**:用固定种子另生成 2000 条留作测试集,且排除与训练目标距离 < 5 mm 的样本;`route_bench` / `near_column_bench` / `rt_drag_bench` 的案例**不进入训练集**。
+- pos / pose 各半;老师用 `solveDyn`(松手口径)。
+- **测试集隔离**:固定种子另造 2000 条留出;三个基准案例不进训练集。
-### 2.4 质量过滤
+### 4.4 过滤
-1. `ok == false` 的样本:A/B/C 类丢弃;D 类保留为"拒绝"标签。
-2. 整条路径 1° 细验(`segOK`)+ 半格复验,任一段干涉即丢弃。
-3. `poseRelaxed == true` 的样本单独打标签,训练时只当作 pos 模式样本用(避免模型学到"姿态随便放")。
-4. 关节行程超过同任务 `routeRT` 结果 1.5 倍的视为老师绕远,丢弃(可选,先统计比例再决定)。
+1. 整条路径 1° 细验 + 半格复验,任一段干涉即丢弃。
+2. `poseRelaxed` 样本只当 pos 模式用。
+3. 行程 > 同任务 `routeRT` 1.5 倍的视为绕远(先统计,再定是否丢弃)。
-### 2.5 数据增广(不需要重新规划)
+### 4.5 时间参数化 → 闭环训练样本(v2 新增,关键)
-- **后缀切片**:合法路径的任意后半段也是合法路径。从每条路径中按弧长取 2–4 个中间点作为新 q0,得到新样本(目标不变)。约 ×3。
-- **连续轴平移**:J1 绕立柱对称性**不成立**(立柱在固定位置),不做 J1 旋转增广;J6 若与碰撞无关可加 ±360° 等价表示,归一化时统一处理。
-- 增广后预计约 60 万条训练样本。
+闭环策略学的是"在某个状态下,接下来 16 步怎么走",所以要把整条路径切成很多个"状态 → 动作块"样本:
-### 2.6 耗时与存储估算
+1. 按现有 `animTo` 的轴速比 `VREL = [0.6, 0.6, 0.9, 0.9, 1.2, 1.8]` 做时间参数化(与查看器动画同口径),控制周期 **dt = 20 ms**。
+2. 得到状态序列 q_0, q_1, …, q_N。对每个 t(每隔 3 步取 1 个,减少冗余)生成样本:
+ - 输入:当前 q_t、目标 (T, R, mode)
+ - 标签:未来 S = 16 步的增量 Δq_{t+1..t+16} = q_{t+k} − q_t(到终点后补零,即"停住")
+3. 每条路径平均约 50–150 个样本 → 5 万条任务约 300 万个训练样本。
+4. **路径后缀天然覆盖"从半路出发"**,等于免费的 DAgger 种子数据。
-- `solveDyn` 约 0.7 s/条,沙箱 2 进程约 1 万条/小时 → 20 万条约 20 小时;用户机器 8 核约 5 小时。
-- 每条约 1–2 KB,全部原始数据约 300 MB;转 Parquet 后约 80 MB。
+### 4.6 耗时与存储
-### 2.7 本步检查点(审查时可看)
+- `solveDyn` 约 0.7 s/条:5 万条在沙箱 2 进程约 5 小时;用户 8 核机器约 1.5 小时。
+- 300 万样本 × 约 0.5 KB ≈ 1.5 GB 原始;Parquet 约 300 MB。
-- [ ] `ml/data/stats.json`:各类别数量、ok 率、平均行程、路径点数分布、规划耗时分布
-- [ ] 随机抽 20 条在查看器里回放(新增 `?replay=shard_0000.jsonl#127` URL 参数)
-- [ ] 测试集与 3 个基准案例和训练集无重叠
+### 4.7 检查点
+
+- [ ] `ml/data/stats.json`:类别、到达率、行程、样本数分布
+- [ ] 抽 20 条在查看器回放(新增 `?replay=` URL 参数)
+- [ ] 测试集与训练集、基准案例无重叠
---
-## 3. 第二步:预处理(Python)
+## 5. 第二步:表示与预处理
-文件:`ml/prep/build_dataset.py` → 输出 `ml/data/train.parquet`、`val.parquet`(95/5 划分)、`test.parquet`、`norm.json`。
+文件 `ml/prep/build_dataset.py` → `train/val/test.parquet`、`norm.json`。
-### 3.1 路径重采样
-
-1. 连续轴(J1/J3/J6)先做展开(`unwrapTo` 同口径),保证相邻点差 < 180°。
-2. 按**加权关节空间弧长**重采样为固定 **K = 32** 个点,第 0 点 = q0,第 31 点 = q_goal。权重默认各轴 1(可改成按连杆长度加权)。
-3. 记录原始弧长 `L`(模型额外回归它,用于早停与排序)。
-
-### 3.2 条件输入(编码器一侧)
+### 5.1 输入(条件)
| 量 | 维度 | 编码 |
|---|---:|---|
-| q0 | 6 | 每轴 (sin, cos) → 12;限位轴再加归一化值 (q−lo)/(hi−lo) → +3 |
-| 目标位置 T | 3 | 除以 600 mm 归一化 |
-| 目标姿态 R | 6 | 旋转矩阵前两列(6D 表示);pos 模式填 0 |
+| 当前 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] |
-| 工具号 | 1 | 目前恒 0,留位 |
-| 起点 TCP | 3 | `fk(q0)` 归一化(给模型一个笛卡尔线索) |
+| 上一周期选的模式 k_prev | K+1 | one-hot(含"无"),用于模式粘滞 |
+| 关键胶囊对最小距离 | 8 | 当前位形下臂各段到立柱的胶囊距离(cheap,现成函数),给模型"离柱子多近"的直接信号 |
-### 3.3 输出表示(解码器一侧)——离散化
+### 5.2 输出(动作块)
-- 每个关节值相对 q0 的**增量** Δq = q_k − q0 离散化:连续轴范围 [−360, 360],限位轴范围 [lo−hi, hi−lo],均分 **512 个桶**(约 1.4°/桶)。
-- 每个桶再回归一个桶内偏移 ∈ [−0.5, 0.5](细化到亚度级)。
-- 序列:K−1 = 31 个路径点 × 6 轴 = **186 个 token**(第 0 点即 q0,不需要预测)。
-- 额外 1 个 `[REJECT]/[OK]` 分类 token 放在序列最前:D 类样本只训练这个 token。
+- **K = 4 个模式**,每个模式一整块 16 步 × 6 轴的关节增量 Δq(连续值,按每轴最大步长归一化)。
+- 一个模式分类头:4 类 logits。
+- 训练时 **winner-takes-all**:只对与标签最接近的那个模式回归,分类头学"选哪个"(MTR / 多模态轨迹预测的常用做法)。这样左绕、右绕会落到不同模式里,不会被平均到穿过立柱。
+- 附加头:到达剩余时间估计(帮助排序和早停)。
-**为什么不用直接回归(MSE)**:立柱两侧绕行(左绕/右绕、J3 翻转/不翻转)是多峰分布,MSE 会输出两条路径的平均——恰好穿过立柱。离散化 + 自回归采样能保留多峰。
+### 5.3 连续轴
-### 3.4 归一化文件 `norm.json`
-
-记录桶边界、K、权重、碰撞模型指纹 `fp`;部署端必须校验 `fp` 一致,否则拒绝加载模型。
+J1/J3/J6 统一用 `unwrapTo` 口径展开后再做增量;预处理和部署共用一份实现,§6.4 对拍时一并验证。
---
-## 4. 第三步:模型结构
+## 6. 第三步:模型与预训练(行为克隆)
-文件:`ml/model/traj_transformer.py`
+### 6.1 结构(参考 IMPACT,去掉点云部分)
```
-条件向量 (≈37 维)
- └─ MLP → 8 个条件 token (d=256) ← 编码器:4 层 Transformer encoder
-目标序列: [BOS][OK] (j1,j2,...,j6)×31
- └─ 嵌入 = 桶嵌入 + 轴嵌入(6) + 路径点位置嵌入(32)
- └─ 6 层 Transformer decoder(因果自注意力 + 对条件 token 的交叉注意力)
-输出头:
- ├─ 桶分类头 (512 类 / token)
- ├─ 桶内偏移回归头 (1 / token)
- ├─ OK/REJECT 头 (2 类)
- └─ 路径弧长回归头 (1)
+条件特征(约 60 维)──MLP──▶ 8 个条件 token (d=192)
+ │
+ 4 层 Transformer encoder
+ │ (memory)
+K×16 个可学习动作 token ──▶ 4 层 Transformer decoder(非自回归,一次前向)
+ │
+ ├─ 动作头:每 token 输出 6 维 Δq
+ ├─ 模式分类头:K=4
+ └─ 剩余时间头:1
```
| 超参 | 值 |
|---|---|
-| d_model | 256 |
-| 头数 | 8 |
-| FFN | 1024,GELU |
-| 编码器/解码器层数 | 4 / 6 |
-| Dropout | 0.1 |
-| 参数量 | 约 7 M(fp32 约 28 MB,fp16 约 14 MB) |
+| d_model / 头数 / FFN | 192 / 8 / 768 |
+| encoder / decoder 层数 | 4 / 4 |
+| 参数量 | 约 3–4 M(DRP 为 4.67 M,含点云编码) |
+| 推理 | 一次前向得到 4 条候选动作块 |
-备选(第一版不做):同一骨干改为 flow matching,直接输出 31×6 连续值,推理 8–16 步;在自回归版精度不够时再试。
-
----
-
-## 5. 第四步:训练
-
-文件:`ml/train.py`,配置 `ml/configs/base.yaml`。
-
-### 5.1 损失
+### 6.2 预训练损失
```
-L = CE(桶) 权重 1.0(label smoothing 0.05)
- + L1(桶内偏移) 权重 0.5
- + CE(OK/REJECT) 权重 0.5
- + L1(弧长 L) 权重 0.1
- + 平滑项 ‖q_{k+1} − 2q_k + q_{k−1}‖²(用期望桶值计算) 权重 0.05
- + 终点项 ‖q_31 − q_goal‖(期望值) 权重 0.5
+L = WTA-L1(动作块, 最近模式) 权重 1.0
+ + CE(模式分类) 权重 0.5
+ + FK 损失:预测与标签位形下各连杆胶囊端点的位置差 权重 0.5 ← 借鉴 ELMP
+ + 平滑:二阶差分 权重 0.05
+ + L1(剩余时间) 权重 0.1
```
-### 5.2 训练配置
+### 6.3 训练配置
| 项 | 值 |
|---|---|
-| 优化器 | AdamW,β=(0.9, 0.95),weight decay 0.05 |
-| 学习率 | 3e-4,前 2000 步线性预热,余弦退火到 3e-6 |
-| batch | 256(显存不够用梯度累积) |
-| 精度 | bf16/fp16 混合精度 |
-| 轮数 | 最多 40 epoch,验证集"合法率"连续 5 次不升即早停 |
-| 教师强制 | 全程 teacher forcing;第 20 epoch 后 10% 概率用模型自己的预测(scheduled sampling),减轻曝光偏差 |
-| 预计耗时 | RTX 3060:约 1.5–3 小时(估算,跑完第一轮后校正) |
+| 优化器 | AdamW,β=(0.9, 0.95),wd 0.01 |
+| 学习率 | 1e-3,预热 1000 步,余弦退火(同 DRP 量级) |
+| batch | 512 |
+| 精度 | bf16 混合精度 |
+| 步数 | 约 20 万步(300 万样本约 30 epoch),验证集闭环成功率不再上升即停 |
+| 预计耗时 | RTX 3060 约 3–5 小时(估算,跑完首轮校正) |
-### 5.3 训练中验证(每个 epoch)
+### 6.4 对拍与验证(每 epoch)
-在 `val` 抽 1000 条,**自回归采样**生成路径后用 Python 版碰撞检查器评估:
-- 用 `ml/eval/collide_py.py`(从 `collide.json` 读胶囊,与 JS 同口径;先用 JS 结果对拍 1 万个位形,误差必须为 0)。
-- 指标:合法率(1° 细验无干涉)、终点误差、行程比(模型/老师)、REJECT 准确率。
-- 保存最优 checkpoint 依据 = **合法率**,其次终点误差。
-
-### 5.4 一条命令运行
-
-```bash
-python ml/prep/build_dataset.py --in ml/data --out ml/data
-python ml/train.py --config ml/configs/base.yaml --run runs/v1
-tensorboard --logdir runs
-```
+- `ml/eval/collide_torch.py`:胶囊距离的 PyTorch 批量版(**可微**,§7 要用),先与 JS `collideFree` 对拍 10 万个位形,判定 0 误差。
+- 验证用**闭环仿真**而不是单步误差:从 1000 个验证任务的 q0 出发,每 20 ms 推理一次、执行前 3 步、直到到达或 6 s 超时,统计到达率、碰撞步数(安全层关闭时)、行程比。
---
-## 5A. 第四步半:后训练——验算、挑错、针对性再训练(循环)
+## 7. 第四步:后训练(无老师为主)
-> 2026-10-17 用户补充:一轮监督训练不够,要"模型结果逐条验算 → 挑出错的 → 针对性训练 → 周而复始"。
-> 下面把它做成固定流程,每一轮都可复现、可回滚。
+### 7.1 主力:APG 可微微调(借鉴 ELMP)
-### 5A.1 为什么光和老师数据对比不够
-
-监督训练只在**老师走过的状态**上学习。模型上线后会走到老师没走过的状态(自己的路径稍微偏一点,下一帧的起点就偏了),
-误差会累积——这是模仿学习的"分布偏移"。所以后训练要同时做两件事:
-
-1. **困难样本挖掘**:在新任务上让模型出结果,逐条验算,错的交给老师重新标注。
-2. **DAgger(数据聚合)**:在**模型自己走到的状态**上请老师给答案,再加回训练集。拖拽场景尤其需要这一条。
-
-### 5A.2 一轮的完整流程(第 r 轮)
+不再请老师标注,直接让模型在可微仿真里闭环展开,用代价反传:
```
- ┌──────────────────────────────────────────────┐
- 模型 M_r ──▶ ①出题 ──▶ ②模型作答 ──▶ ③逐条验算 ──▶ ④错题分类
- │
- M_{r+1} ◀── ⑦门禁 ◀── ⑥针对性微调 ◀── ⑤老师重标 + 邻域扩增 ◀┘
+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
```
-**① 出题(挖掘池,每轮新抽)**
-- 每轮用新种子生成 5 万条任务,分布同 §2.3,但把 B/C 类(直线被挡、贴立柱)提到 60%。
-- 另跑 2000 段"模型在环"拖拽仿真(同 rt_drag_bench 口径,但每帧由模型规划、走模型给的路径),记录模型实际经过的状态,作为 DAgger 状态池。
-- **挖掘池与测试集严格分开**:§2.3 的留出测试集和三个基准永远不进挖掘池,否则门禁失效。
+- **碰撞项** L_col = Σ_胶囊对 ReLU(margin − 胶囊距离),margin 取 `collide.json` 的 `margin_mm` 基础上再加 5 mm 训练余量;包含臂×立柱、臂×台架、臂×臂(非相邻段)。
+- **到达项**:位置误差² + λ_rot·‖R − R*‖_F²(弦距离,ELMP 同款,避免四元数梯度消失)。
+- **平滑项**:速度² + 加速度²。
+- 可加 **行程项**,直接把"关节行程短"写进目标(ELMP 用笛卡尔路径长度项做过同类事情)。
+- 模式选择不可导:用 Gumbel-Softmax,或对 K 个模式都展开 1 步再取最小代价(K=4,代价可接受)。
+- 采样任务分布同 §4.3,但 B/C/D 类提到 60%。
+- 预期:参照 ELMP,APG 主要降低碰撞率、提高末端精度;**不需要任何老师计算**。
-**② 模型作答**
-- 每个任务采样 B = 8 条(与部署一致:贪心 + 不同温度)。GPU 批量推理,5 万任务约几分钟。
+### 7.2 辅助:闭环挖错 + 门禁(v1.1 循环的无老师版)
-**③ 逐条验算**(新增 `ml/eval/verify_batch.py`,GPU 批量版碰撞检查器)
-- 每条候选:1° 细验 + 半格复验无干涉;终点 TCP 误差 < 1 mm(pose 另需姿态 < 0.5°);关节不越限位。
-- 同一任务调用老师(已有标签或现算)得到老师行程 `L*`。
-- 验算口径必须与 JS 完全一致:`verify_batch.py` 先与 JS `collideFree` 对拍 10 万个位形,0 误差才允许用于挖掘。
-- 为什么要 GPU 版:5 万任务 × 8 条 × 约 100 个采样位形 = 4000 万次位形检查,JS 单核约 20 小时,GPU 批量约几分钟。
+每轮:
+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. **门禁**:留出集闭环到达率上升、三个基准不退化、上一轮修好的错题 95% 仍对;否则回滚。
+7. **停止**:连续 2 轮提升 < 0.5 个百分点,或满 6 轮,或达到 §9 全部标准。
-**④ 错题分类**(写入 `ml/mining/round_r/errors.parquet`)
+### 7.3 可选:拒绝采样自蒸馏
-| 类别 | 判定 | 典型原因 |
-|---|---|---|
-| E1 全错 | 8 条全部不合法 | 没学会这一类绕行 |
-| E2 部分错 | 有合法的,但贪心那条不合法 | 置信度校准差 |
-| E3 绕远 | 最优合法候选行程 > 1.2 × `L*` | 选错同伦类(该左绕却右绕) |
-| E4 终点偏 | 路径合法但终点误差超限 | 离散化/精修不足 |
-| E5 拒判错 | 可达却判 REJECT,或不可达却给路径 | OK 头没学好 |
-| E6 拖拽失稳 | 模型在环仿真中出现碰撞帧或 3 s 内未到达 | 分布偏移 |
-| G 比老师好 | 合法且行程 < 0.9 × `L*` | 老师没找到更短的路 |
+对每个任务采样多条闭环轨迹(不同模式、不同温度),只保留验算通过且最短的一条做行为克隆标签——模型自己当老师。适合 APG 收敛后进一步缩短行程。
-同时记录每个错题撞的是哪对部件(`collideDetail`),便于看是不是集中在立柱上段等特定区域。
+---
-**⑤ 老师重标 + 邻域扩增**
-- E1–E5:用 `solveDyn` 重新求解(已有标签直接复用),得到正确标签。
-- E6(DAgger):取模型路径**撞前最后一个安全状态**、以及拖拽中途的若干状态作为新起点 q0,请老师从这里规划到目标。
-- 邻域扩增:每个错题再造 10 个邻居(目标 ±5 mm、q0 各轴 ±3°),老师标注,过滤后加入——一个错题往往代表一片区域没学会。
-- G 类:模型的更短路径通过验算后**直接作为新标签**(替换老师标签),模型可以反过来超过老师。
-- 老师耗时:每轮错题约 2000–5000 条 × 11(含邻居)× 0.7 s,8 核机器约 1–2 小时。
+## 8. 第五步:无老师闭环部署
-**⑥ 针对性微调**
-- 从 M_r 的权重继续训练,**不从头训**。
-- 训练集 = 新错题样本 50% + 历史数据回放 50%(防止学了新的忘了旧的)。
-- 错题按类别加权:E1、E6 权重 2.0,E3 权重 1.5,其余 1.0。
-- 学习率 1e-4,预热 500 步,余弦退火,3–5 epoch。
+### 8.1 每个控制周期做什么(默认 50 Hz)
-**⑦ 门禁(不通过就回滚)**
+```
+每 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 一顿。
+
+### 8.2 模式粘滞(防左右摇摆)
+
+- 排序分数 = log p(k) − c·[k ≠ k_prev],c 初值 2.0(在 §7.2 的 E5 统计上调)。
+- 训练时 k_prev 作为输入(§5.1),模型自己也学会"保持当前绕行方向"。
+
+### 8.3 安全层(唯一的硬保证)
+
+- 检查内容:候选前 3 步的连续运动做 1° 细验 + 半格复验(与现有 `pathFine` 同口径),外加关节限位。
+- **可刹停不变式**:执行前还要检查"从第 3 步末状态按最大减速度停下"的刹停段也无干涉。于是任何时候系统都处在"有一条已验证的停车路线"的状态,下一周期就算模型完全失效,也只会停下、不会撞。
+- 耗时:3 步 × 4 候选,最坏约 4 × 10 个采样位形 × 约 1.8 ms ≈ 70 ms(太慢)→ 实际做法:
+ - 先用现有包围球预筛(大多数位形直接判安全,见 2026-10-15 记录 collideFree 2.9→1.8 ms);
+ - 按排序**逐个**检查,第一个通过就停(多数周期只检查 1 条);
+ - 目标:每周期安全检查 < 5 ms(需在 M6 实测;不达标则把检查放到 Web Worker 与推理流水线并行)。
+- 现有 `ik-glue.js` 的"每帧碰撞守卫"保留,作为第二道保险。
+
+### 8.4 部署包里有什么、没有什么
+
+| 有 | 没有 |
|---|---|
-| 留出测试集模型命中率 | 比 M_r 高(≥ +0.3 个百分点) |
-| 留出测试集合法率、行程比 | 不得比 M_r 差 |
-| route_bench / near_column_bench / rt_drag_bench | 「模型+验证+回落」任何一项不得退化 |
-| 上一轮已修好的错题(回归集) | 至少 95% 仍然正确 |
+| `traj_v2.onnx`(fp16,约 7 MB)+ `norm.json` | PRM 路网(`collide.json.roadmap`)、IK 候选大表 |
+| 胶囊碰撞检查(现有 `collideFree`、包围球预筛、`pair2d` 表) | `solveDyn` / `routeRT` / RRT / A* |
+| 正运动学 `fk` / `orient`、局部牛顿精修 `solveTo` 单步 | 全量 IK 枚举 |
-不通过:丢弃 M_{r+1},检查错题标签质量后调整权重/回放比例重做本轮。
-
-### 5A.3 停止条件
-
-- 连续 2 轮命中率提升 < 0.5 个百分点,或
-- 达到 6 轮,或
-- 达到 §7.2 全部验收标准。
-
-### 5A.4 进阶选项(循环稳定后再考虑)
-
-1. **验算过的自我采样微调**(expert iteration / 拒绝采样):对每个任务采样 32 条,只保留验算通过且最短的一条作为标签,不需要老师参与,适合 G 类多的时候。
-2. **偏好训练**(DPO 类):同一任务的"合法路径"和"撞了的路径"组成一对,让模型提高前者概率、降低后者,直接针对"别撞"优化。
-3. **碰撞惩罚项**:在损失里加可微的胶囊最小距离惩罚(从 `collide.json` 的胶囊参数计算),距离 < 安全余量时罚。
-
-### 5A.5 新增文件
-
-```
-ml/mining/
- mine_round.py ①–④ 出题、作答、验算、分类
- relabel.cjs ⑤ 调老师重标 + 邻域扩增(Node)
- finetune.py ⑥ 回放混合 + 加权微调
- gate.py ⑦ 门禁与回滚
- loop.sh 一条命令跑 N 轮:bash ml/mining/loop.sh --rounds 6
- round_r/ 每轮的错题、新标签、指标、checkpoint(不入库)
-ml/eval/verify_batch.py GPU 批量碰撞验算(与 JS 对拍)
-```
-
-每轮输出 `round_r/report.md`:错题分布、门禁结果、命中率曲线,方便逐轮审查。
+`collide.json` 指纹写进模型;不一致时前端**拒绝运行并提示重训**(不再回落旧规划器)。
---
-## 6. 第五步:推理与集成
+## 9. 第六步:评估与验收
-### 6.1 导出
-
-`ml/export_onnx.py`:导出带 KV cache 的解码器(opset 17),fp16 量化;输出 `webapp/models/traj_v1.onnx` + `traj_v1.norm.json`。
-
-### 6.2 推理流程(新增 `webapp/js/ik-learned.js`,在 `routeRT` 之前调用)
-
-1. 编码条件 → 一次 batch 采样 **B = 8** 条(温度 {0, 0.5, 0.8, 1.0} 各 2 条,0 为贪心)。
-2. 若 OK 头判 REJECT 概率 > 0.9 → 直接走原规划器(不信任模型的"到不了",只用来省时间排序)。
-3. 每条候选:终点用 `solveTo` 做 1–3 次牛顿精修 → 整条 `collideFree` 1° 细验 + 半格复验。
-4. 选合法且行程最短的一条;**全部不合法 → 原 `routeRT` / `solveDyn` 回落**。
-5. 拖拽中热启动:把上一帧路径剩余部分作为解码前缀,只重新生成后半段。
-
-### 6.3 延迟预算(目标)
-
-| 环节 | 目标 |
-|---|---:|
-| 模型推理(8 条 × 186 token,WebGPU) | < 15 ms |
-| 碰撞验证(8 条) | < 15 ms(已有包围球预筛) |
-| 合计(命中时) | < 30 ms |
-
----
-
-## 7. 第六步:评估与验收
-
-### 7.1 测试集合
+### 9.1 测试集合
| 集合 | 来源 |
|---|---|
| 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 | §2.3 的 2000 条留出测试集 |
+| rt_drag_bench | `tests/rt_drag_bench.cjs`,12 例(改为模型在环逐周期运行) |
+| held-out | §4.3 留出 2000 条 |
-新增 `tests/learned_bench.cjs`:对同一批案例分别跑 ①原规划器 ②仅模型 ③模型+验证+回落,输出对比表。
+新增 `tests/policy_bench.cjs`:①现有规划器 ②策略(关安全层)③策略 + 安全层(部署形态),输出对比表。
-### 7.2 验收标准
+### 9.2 验收标准(部署形态 = 策略 + 安全层)
-| 指标 | 仅模型(参考) | 模型+验证+回落(必须) |
+| 指标 | 要求 | 现状参考 |
|---|---|---|
-| 路径合法率 | ≥ 90% | = 100%(与现状一致) |
-| 到达率 | ≥ 95% | ≥ 现状(route 60/60,near pos 30/30,rt 30/30) |
-| 关节行程 | ≤ 老师 × 1.1 | ≤ 现状 × 1.05 |
-| 拖拽重规划 P99 | — | < 50 ms(现状约 321 ms) |
-| 拖拽碰撞帧 | — | 0 |
-| 模型命中率(不需回落) | — | ≥ 85% |
+| 实际执行的碰撞帧 | **= 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%) | — |
-不达标的处理:命中率低 → 加数据(重点补失败类别)/ 加大模型;行程差 → 加大行程 loss 或过滤老师绕远样本;延迟不降 → 减少 B 或改 flow matching。
+说明:允许 near_column 少 1 例,因为无老师时最难的贴柱案例可能要靠多次刹停-重算才能到达,6 s 超时内可能失败;这一条请审查时确认能否接受。
---
-## 8. 风险与维护
+## 10. 风险与维护
-1. **碰撞模型/立柱变动 = 重训**:`collide.json` 指纹写进数据和模型,不一致时前端自动禁用模型,回落原规划器,不会出错只会变慢。重训流程 = §2 → §5,约半天。
-2. **老师的缺陷会被学走**:例如 `ci27` 姿态根枚举漏分支(姿态偏差约 97.5°)。数据里 `poseRelaxed` 样本已隔离;老师修好后再重造数据。
-3. **分布外目标**:模型在工作空间边缘可能乱给;有验证+回落兜底,只影响速度。
-4. **J3/J6 连续轴展开**:预处理与部署必须同一套 `unwrapTo` 口径,§3 对拍时一并验证。
+1. **局部极小**:可微代价和闭环策略都可能卡在立柱前"想直穿过去又被安全层挡住"。对策:B/C 类数据加权、模式头学左右绕、E2 错题少量老师补数据(§7.2)。这是无老师方案最大的风险。
+2. **碰撞模型/立柱变动 = 重训**:指纹不一致即拒绝运行。重训流程:§4(约 5 h)→ §6(约 4 h)→ §7(约 2–4 h)。
+3. **安全层耗时**:最坏周期可能超 5 ms,见 §8.3 的流水线方案。
+4. **老师缺陷**:`ci27` 姿态根枚举漏分支(姿态偏差约 97.5°)会进入预训练数据;APG 的姿态到达项可以部分纠正,必要时先修老师。
+5. **真机迁移**:浏览器的"执行"是理想插补;真机需加速度/力矩限制(TOPP 类时间参数化)和跟踪误差余量(把 margin 再加大)。
---
-## 9. 目录规划
+## 11. 目录规划
```
ml/
gen/ gen_dataset.cjs sampler.cjs run_parallel.sh
- data/ shard_*.jsonl stats.json train/val/test.parquet norm.json (不入库,.gitignore)
+ data/ (不入库)shard_*.jsonl stats.json *.parquet norm.json
prep/ build_dataset.py
- model/ traj_transformer.py
- eval/ collide_py.py eval_paths.py
- configs/ base.yaml
+ 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-learned.js
-webapp/models/traj_v1.onnx traj_v1.norm.json
-tests/learned_bench.cjs
+webapp/js/ik-policy.js # 闭环推理 + 模式粘滞 + 安全层 + 刹停
+webapp/models/traj_v2.onnx traj_v2.norm.json
+tests/policy_bench.cjs
```
-## 10. 里程碑
+## 12. 里程碑
| # | 内容 | 产出 | 在哪跑 |
|---|---|---|---|
-| M1 | 数据生成器 + 1000 条试跑 + stats | `ml/gen/*`、stats.json | 沙箱 |
-| M2 | Python 碰撞检查器对拍 | `collide_py.py`,1 万位形 0 误差 | 沙箱 |
-| M3 | 全量 20 万条数据 | Parquet | 沙箱(约 20 h)或用户机器 |
-| M4 | 训练工程 + 小数据过拟合测试(1000 条能背下来) | `train.py` 等 | 沙箱 CPU 验证代码可跑 |
-| M5 | 正式训练 | checkpoint、TensorBoard | **用户 GPU** |
-| M5A | 后训练循环:GPU 批量验算器 + 挖掘/重标/微调/门禁,跑 3–6 轮 | 每轮 report.md | 用户 GPU(老师重标可分到沙箱) |
-| M6 | 导出 ONNX + 前端集成 + learned_bench | 对比表 | 沙箱 + 浏览器 |
+| 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` 离线使用) | 部署包瘦身 | 沙箱 |
-## 11. 需要用户确认
+## 13. 参考文献
+
+- Fishman et al., *Motion Policy Networks*, CoRL 2022. https://arxiv.org/abs/2210.12209 ;闭环细节见补充材料 https://proceedings.mlr.press/v205/fishman23a/fishman23a-supp.pdf
+- Dalal et al., *Neural MP: A Generalist Neural Motion Planner*, 2024 / IROS 2025. https://arxiv.org/abs/2409.05864
+- Yang, Liu et al., *Deep Reactive Policy: Learning Reactive Manipulator Motion Planning for Dynamic Environments*, CoRL 2025. https://arxiv.org/abs/2509.06953
+- Fishman et al., *Avoid Everything: Model-Free Collision Avoidance with Expert-Guided Fine-Tuning*, CoRL 2024 Workshop(DRP 文中引用为 MπFormer)
+- Li et al., *ELMP: Efficient Learning for Motion Planning via Analytical Policy Gradients*, arXiv 2607.00215, 2026. https://arxiv.org/abs/2607.00215
+- Ross, Gordon, Bagnell, *A Reduction of Imitation Learning and Structured Prediction to No-Regret Online Learning*(DAgger),AISTATS 2011
+
+## 14. 需要用户确认
1. 训练机显卡型号与显存。
-2. 定位:只做加速器(本文默认),还是希望最终能脱离规划器。
-3. 数据生成在沙箱跑(约 20 h),还是你的机器跑更快。
+2. §9.2 中 near_column 允许 29/30(无老师下最难案例可能超时)是否接受。
+3. 控制周期 50 Hz、每周期执行 3 步(60 ms)作为默认值是否合适(真机控制器频率如有要求请告知)。