diag: H 段(老师 oracle 走 rollout / 前缀消融 / 子目标越过顶点规则 / 分轴与分类别指标);训练:EMA、选模不落在 p_neq 预热、闭环分数选模、24000 步余弦、p_neq 0.5 + p_edge 0.1、子目标头切断抄输入、前缀/dq 增广;仿真:last 记真正提交的候选、碰撞与到达按每题时限、回放门禁读 pass+指纹并走 rollout;数据:动作标签按 1.25·STEP 归一化(act_scale 随 meta/ckpt/ONNX 传递,旧模型 1.0)、收回亏空结转、DAgger 带 qPrev 与起步速度、打包签名变更自动重打;ik-policy.js 同步(actScale、子目标规则、DLS 时清 lastPlan);本机执行清单与 README 更新
This commit is contained in:
@@ -5,7 +5,9 @@
|
||||
* 每行一条任务:采样 → 老师 → 距离下界认证过滤 → 局部时间律(50 Hz)→ 写出。
|
||||
* 认证不过的样本也写出(keep=false + 原因),供 stats 统计丢弃率;训练只用 keep=true。
|
||||
* 2026-10-18 断点续写:第 i 条任务的随机数只由 (seed, i) 决定(sampler.reseed);输出文件已存在时保留其中完整的行、
|
||||
* 截掉写了一半的最后一行,从下一条接着写 —— 生成几小时被中断,重跑只补剩下的,不重来、不重复。 */
|
||||
* 截掉写了一半的最后一行,从下一条接着写 —— 生成几小时被中断,重跑只补剩下的,不重来、不重复。
|
||||
* 2026-10-19:--tasks 的任务带 qPrev(DAgger 采集时策略的上一帧)时,记录 qPrev 与起步速度 v0(timelaw.initSpeed),
|
||||
* 时间律从 v0 起步;build_dataset.cjs 用它们做 t=0 样本的 dq 特征与标签。 */
|
||||
'use strict';
|
||||
const fs = require('fs'), path = require('path');
|
||||
const args = {}; for (let i = 2; i < process.argv.length; i += 2) args[process.argv[i].replace(/^--/, '')] = process.argv[i + 1];
|
||||
@@ -19,7 +21,7 @@ const K_CONS = +args.consensus || 0;
|
||||
const GIVEN = args.tasks ? fs.readFileSync(args.tasks, 'utf8').split('\n').filter(Boolean).map(l => JSON.parse(l)) : null;
|
||||
const NT = GIVEN ? GIVEN.length : N;
|
||||
const cert = require('./cert.cjs')(S, {});
|
||||
const { timeParam } = require('./timelaw.cjs');
|
||||
const { timeParam, initSpeed } = require('./timelaw.cjs');
|
||||
const fp = S.modelFingerprint ? S.modelFingerprint() : null;
|
||||
fs.mkdirSync(path.dirname(OUT), { recursive: true });
|
||||
let done = 0;
|
||||
@@ -63,7 +65,11 @@ for (let i = done; i < NT; i++) {
|
||||
if (valid >= 2 && agree * 2 < valid) { rec.keep = false; rec.why = 'consensus'; }
|
||||
}
|
||||
if (t.poseRelaxed && task.mode === 'pose') { rec.mode = 'pos'; rec.R = null; rec.demoted = true; rec.reached = t.err < 1; }
|
||||
if (rec.keep) { const tp = timeParam(t.pts); rec.traj = tp.traj.map(q => q.map(r3)); rec.exec_s = r3(tp.steps * 0.02); }
|
||||
if (rec.keep && task.qPrev) {
|
||||
rec.qPrev = task.qPrev.map(r3);
|
||||
rec.v0 = r3(initSpeed(t.pts, task.qPrev, S.wrap180, S.ORDER.map(id => !!S.LIM[id].cont)));
|
||||
}
|
||||
if (rec.keep) { const tp = timeParam(t.pts, { v0: rec.v0 || 0 }); rec.traj = tp.traj.map(q => q.map(r3)); rec.exec_s = r3(tp.steps * 0.02); }
|
||||
fs.writeSync(fd, JSON.stringify(rec) + '\n');
|
||||
if ((i + 1) % 25 === 0) process.stderr.write(`[seed ${SEED}] ${i + 1}/${NT} ${((performance.now() - t00) / 1000 / (i + 1 - done)).toFixed(2)} s/条\n`);
|
||||
}
|
||||
|
||||
+20
-3
@@ -1,7 +1,10 @@
|
||||
/* 局部可观测时间律(2026-10-17,方案 §4.5)
|
||||
* 折线按"巡航时间" τ 参数化:每段 τ = max_j |Δq_j| / VMAX_j(各轴同步、主导轴满速)。
|
||||
* 归一化速度 v∈[0,1](1 = 巡航):v ← min(1, v + A·dt, sqrt(2·A·剩余 τ)),只依赖当前速度与剩余路程。
|
||||
* 输出 50 Hz(dt = 20 ms)状态序列,末点精确落在终点。 */
|
||||
* 输出 50 Hz(dt = 20 ms)状态序列,末点精确落在终点。
|
||||
* 2026-10-19(审查 review_closedloop F7 / review_data_actions C10):opt.v0 = 起步归一化速度(默认 0 = 静止起步)。
|
||||
* DAgger 重新标注的起点来自策略闭环、本来就在运动,原来一律从静止加速,标签与策略真正到达的 (q, dq) 状态不符。
|
||||
* initSpeed(P, qPrev) 把当前速度投影到首段方向上得到 v0(gen_dataset.cjs 用)。 */
|
||||
'use strict';
|
||||
const VMAX = [60, 60, 90, 90, 120, 180]; // °/s,与 tests/route_bench.cjs 同(轴速比 0.6/0.6/0.9/0.9/1.2/1.8)
|
||||
const A = 5.0; // 1/s²:0→巡航约 0.2 s(a_max 待真机参数)
|
||||
@@ -19,7 +22,7 @@ function timeParam(P, opt) {
|
||||
const u = segT[i] > 0 ? (tau - cum[i]) / segT[i] : 1;
|
||||
return P[i].map((v, j) => v + (P[i + 1][j] - v) * u);
|
||||
};
|
||||
const out = [P[0].slice()], taus = [0]; let tau = 0, v = 0, guard = 0;
|
||||
const out = [P[0].slice()], taus = [0]; let tau = 0, v = Math.max(0, Math.min(1, opt.v0 || 0)), guard = 0;
|
||||
while (tau < total - 1e-9 && guard++ < 100000) {
|
||||
const rem = total - tau;
|
||||
const v1 = Math.min(1, v + a * dt, Math.sqrt(2 * a * Math.max(0, rem - 0.5 * v * dt)) + 1e-9);
|
||||
@@ -30,4 +33,18 @@ function timeParam(P, opt) {
|
||||
}
|
||||
return { traj: out, taus, cum, total, steps: out.length - 1 };
|
||||
}
|
||||
module.exports = { timeParam, VMAX, A, DT };
|
||||
/* 起步速度:w_j = 当前每步增量 / STEP_j(qPrev → P[0]),u_j = 巡航时首段每步增量 / STEP_j(max|u_j| = 1),
|
||||
v0 = clamp(⟨w,u⟩/⟨u,u⟩, 0, 1)——当前速度在首段方向上的分量;反向或首段为零时 0。wrap:连续轴差值的最短弧函数(可缺省)。 */
|
||||
function initSpeed(P, qPrev, wrap, cont) {
|
||||
if (!qPrev || !P || P.length < 2) return 0;
|
||||
const dd = (a, b, j) => (wrap && cont && cont[j]) ? wrap(a - b) : a - b;
|
||||
let seg = 0; for (let j = 0; j < 6; j++) seg = Math.max(seg, Math.abs(P[1][j] - P[0][j]) / VMAX[j]);
|
||||
if (seg < 1e-9) return 0;
|
||||
let wu = 0, uu = 0;
|
||||
for (let j = 0; j < 6; j++) {
|
||||
const u = (P[1][j] - P[0][j]) / VMAX[j] / seg, w = dd(P[0][j], qPrev[j], j) / (VMAX[j] * DT);
|
||||
wu += w * u; uu += u * u;
|
||||
}
|
||||
return Math.max(0, Math.min(1, wu / uu));
|
||||
}
|
||||
module.exports = { timeParam, initSpeed, VMAX, A, DT };
|
||||
|
||||
Reference in New Issue
Block a user