Files
Robot_Arm/ml/gen/timelaw.cjs
T

34 lines
1.9 KiB
JavaScript
Raw Normal View History

/* 局部可观测时间律(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)状态序列,末点精确落在终点。 */
'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 待真机参数)
const DT = 0.02;
function timeParam(P, opt) {
opt = opt || {};
const vmax = opt.vmax || VMAX, a = opt.acc || A, dt = opt.dt || DT;
const segT = [];
for (let i = 1; i < P.length; i++) { let m = 0; for (let j = 0; j < 6; j++) m = Math.max(m, Math.abs(P[i][j] - P[i - 1][j]) / vmax[j]); segT.push(m); }
const cum = [0]; for (const s of segT) cum.push(cum[cum.length - 1] + s);
const total = cum[cum.length - 1];
const at = tau => {
if (tau >= total) return P[P.length - 1].slice();
let i = 0; while (i < segT.length - 1 && cum[i + 1] < tau) i++;
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;
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);
let step = 0.5 * (v + v1) * dt;
if (step <= 1e-9) step = Math.min(rem, a * dt * dt); // 防止末端速度掉到 0 卡住
tau = Math.min(total, tau + step); v = v1;
out.push(at(tau)); taus.push(tau);
}
return { traj: out, taus, cum, total, steps: out.length - 1 };
}
module.exports = { timeParam, VMAX, A, DT };