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:
+35
-11
@@ -178,8 +178,10 @@ class Runner {
|
||||
this.S = S; this.infer = infer;
|
||||
this.o = Object.assign({ K: 8, commit: 3, margin: 5, /* 2026-10-18:运行时投影余量保持 5 mm(真机护栏,不迁就数据分布);数据侧另行过滤认证间隙 < 3 mm 的老师轨迹,APG 训练余量 3 mm */
|
||||
projMax: 0.5, refineMm: 5, arriveMm: 1, arriveDeg: 0.5,
|
||||
stuckPlans: 5, lockSec: 1.0, subReachDeg: 5, subTimeout: 1.5, seed: 12345, lookahead: true,
|
||||
certBudget: 40, safetyMs: 30, firstMs: 45 }, opts || {}); // 每条候选最多 40 次距离查询;安全层总预算 30 ms,第 1 条候选可用到 45 ms(超出按刹停处理)
|
||||
stuckPlans: 5, lockSec: 1.0, subReachDeg: 5, subTimeout: 1.5, subRule: 'cross', subLeadSec: 0.02, seed: 12345, lookahead: true,
|
||||
actScale: 1, certBudget: 40, safetyMs: 30, firstMs: 45 }, opts || {});
|
||||
/* 2026-10-19:actScale = 模型 meta.act_scale(动作标签按 act_scale·STEP 归一化,旧模型 1);增量 = clamp(act, ±1)·actScale·STEP,
|
||||
与 ml/sim/closed_loop.py 同口径。subRule:'cross'(默认,越过顶点即切,与训练标签同口径;见 _subAdvance)/ 'timeout'(旧:< subReachDeg 或 subTimeout 超时)。 */ // 每条候选最多 40 次距离查询;安全层总预算 30 ms,第 1 条候选可用到 45 ms(超出按刹停处理)
|
||||
this.cert = makeCert(S, { leverTable: this.o.leverTable, cap: 20 });
|
||||
this.rng = makeRng(this.o.seed);
|
||||
/* 2026-10-18 第六轮(审查 B-1/B-2):耗时拆开记——inferMs 主推理、lookaheadMs 前瞻(第二次推理 + 8 份特征)、safetyMs 只含认证、
|
||||
@@ -190,7 +192,7 @@ class Runner {
|
||||
reset(q0) {
|
||||
this.q = q0 ? q0.slice() : null; this.qPrev = this.q ? this.q.slice() : null;
|
||||
this.queue = []; this.brakeTail = []; this.lastPlan = null; this.goal = null;
|
||||
this.subs = []; this.subT = 0; this.vals = []; this.brakeRun = 0; this.lock = null; this.t = 0; this.cold = true; this.done = false;
|
||||
this.subs = []; this.subT = 0; this.subPrev = null; this.vals = []; this.brakeRun = 0; this.lock = null; this.t = 0; this.cold = true; this.done = false;
|
||||
}
|
||||
setGoal(T, R) {
|
||||
const jump = !this.goal || Math.hypot(T[0] - this.goal.T[0], T[1] - this.goal.T[1], T[2] - this.goal.T[2]) > 50 || (!!R !== !!this.goal.R);
|
||||
@@ -220,10 +222,34 @@ class Runner {
|
||||
return this.q;
|
||||
}
|
||||
_cand(act, k, r) { // 第 k 条候选:增量(°),丢掉模型的前 r 步(已提交前缀),取接下来的步
|
||||
const inc = [];
|
||||
for (let s = 0; s < H; s++) { const row = []; for (let j = 0; j < 6; j++) row.push(Math.max(-1, Math.min(1, act[(k * H + s) * 6 + j])) * STEP[j]); inc.push(row); }
|
||||
const inc = [], sc = this.o.actScale || 1;
|
||||
for (let s = 0; s < H; s++) { const row = []; for (let j = 0; j < 6; j++) row.push(Math.max(-1, Math.min(1, act[(k * H + s) * 6 + j])) * sc * STEP[j]); inc.push(row); }
|
||||
return inc;
|
||||
}
|
||||
/* 子目标推进(与 ml/sim/closed_loop.py sub_advance 同一规则,三处同步改)。
|
||||
2026-10-19(审查 C5 / P0-1):训练标签里 sub = 老师「下一个尚未经过的顶点」,老师 τ 一过顶点(−0.02 s)就换;
|
||||
旧规则要 < 5° 或 1.5 s 超时,策略在顶点附近进不去时 sub 一直指着身后的点(训练里从未出现的特征序列)。
|
||||
'cross':进入方向 a = 顶点 − 上一点,离开方向 b = 下一顶点 − 顶点(最后一个取 a),各轴 /VMAX 折成秒;
|
||||
法向 n = â + b̂,(qe − 顶点)·n̂ ≥ −subLeadSec 即越过。没有超时(标签也没有)。 */
|
||||
_subAdvance(qe) {
|
||||
if (!this.subs.length) return;
|
||||
const S = this.S, o = this.o, sg = this.subs[0];
|
||||
const df = (a, b, j) => (S.LIM[S.ORDER[j]].cont ? wrap180(a - b) : a - b);
|
||||
let adv = false;
|
||||
if (o.subRule === 'timeout') {
|
||||
let m = 0; for (let j = 0; j < 6; j++) m = Math.max(m, Math.abs(df(sg[j], qe[j], j)));
|
||||
adv = m < o.subReachDeg || this.t - this.subT > o.subTimeout;
|
||||
} else {
|
||||
const unit = v => { const n = Math.hypot.apply(null, v); return n > 1e-9 ? v.map(x => x / n) : v.map(() => 0); };
|
||||
const prev = this.subPrev || this.q;
|
||||
const a = [0, 1, 2, 3, 4, 5].map(j => df(sg[j], prev[j], j) / VMAX[j]);
|
||||
const b = this.subs.length > 1 ? [0, 1, 2, 3, 4, 5].map(j => df(this.subs[1][j], sg[j], j) / VMAX[j]) : a;
|
||||
const ua = unit(a), ub = unit(b), n = unit(ua.map((x, j) => x + ub[j]));
|
||||
let proj = 0; for (let j = 0; j < 6; j++) proj += df(qe[j], sg[j], j) / VMAX[j] * n[j];
|
||||
adv = proj >= -o.subLeadSec;
|
||||
}
|
||||
if (adv) { this.subPrev = this.subs.shift(); this.subT = this.t; }
|
||||
}
|
||||
_certCommit(qe, steps) { // 认证:提交步 + 刹停段(先用离散判定快速剔除,再做距离下界认证)
|
||||
const pts = [qe.slice()]; let q = qe.slice();
|
||||
for (const d of steps) { q = q.map((v, j) => v + d[j]); pts.push(q.slice()); }
|
||||
@@ -257,13 +283,11 @@ class Runner {
|
||||
const steps = []; let q = qe.slice();
|
||||
for (let k = 0; k < o.commit; k++) { const rs = refineStep(S, q, this.goal.T, this.goal.R, 0.3); steps.push(rs.dq); q = q.map((v, j) => v + rs.dq[j]); }
|
||||
const c = this._certCommit(qe, steps);
|
||||
if (c.ok) { this.queue.push(...steps); this.brakeTail = c.tail; this.stats.refine++; return; }
|
||||
/* 2026-10-19(审查 F5):DLS 接管时没有「已提交的模型计划」,lastPlan 置空(原来保留上一条,下次一致性去对齐一条没执行的轨迹;仿真同步) */
|
||||
if (c.ok) { this.queue.push(...steps); this.brakeTail = c.tail; this.stats.refine++; this.lastPlan = null; return; }
|
||||
}
|
||||
/* 子目标推进 */
|
||||
if (this.subs.length) {
|
||||
const sg = this.subs[0]; let m = 0; for (let j = 0; j < 6; j++) m = Math.max(m, Math.abs((S.LIM[S.ORDER[j]].cont ? wrap180(sg[j] - qe[j]) : sg[j] - qe[j])));
|
||||
if (m < o.subReachDeg || this.t - this.subT > o.subTimeout) { this.subs.shift(); this.subT = this.t; }
|
||||
}
|
||||
this._subAdvance(qe);
|
||||
const gm = S.gapMatrix(this.q, GAP_CAP);
|
||||
const st = { q: this.q, qPrev: this.qPrev, T: this.goal.T, R: this.goal.R, prefix, sub: this.subs[0] || null };
|
||||
const f = features(S, st, gm);
|
||||
@@ -279,7 +303,7 @@ class Runner {
|
||||
if (this.needSub) {
|
||||
this.needSub = false; this.subT = this.t;
|
||||
const sb = out.sub.subarray(best * 13, best * 13 + 13);
|
||||
if (sb[12] > 0.5) this.subs = [0, 1].map(v => this.q.map((x, j) => x + sb[v * 6 + j] * 180));
|
||||
if (sb[12] > 0.5) { this.subs = [0, 1].map(v => this.q.map((x, j) => x + sb[v * 6 + j] * 180)); this.subPrev = this.q.slice(); }
|
||||
}
|
||||
/* 候选:去掉前缀后的提交步,投影,打分 */
|
||||
const cands = [], near = S.criticalPairs(qe, o.margin + 10).slice(0, 64);
|
||||
|
||||
Reference in New Issue
Block a user