perf(closed_loop): DLS 批量雅可比(25→10-17ms,数值差≤0.013°)+ 单题安全层早停;实时评估:单次规划 40-80ms 超 50Hz 预算 2-4 倍;实时节奏下每3步 36.3%、每6步 14.8%(每步 42.2% 不可实时)
This commit is contained in:
+14
-10
@@ -51,20 +51,23 @@ def goal_err(kin, q, T, R):
|
||||
def dls_steps(kin, q, T, R, n=3, scale=0.3, lam=0.5):
|
||||
"""局部 DLS 精修:n 步增量 [B,n,6]"""
|
||||
step = torch.tensor(STEP, device=q.device)
|
||||
B = q.shape[0]
|
||||
pose = (R.abs().sum(-1) > 0).float()
|
||||
Rt = R.view(-1, 3, 3)
|
||||
def err(x):
|
||||
def err(x, Tb, Rtb, poseb):
|
||||
xf = kin.cum_xf(x); p = kin.fk(x, xf); Rq = kin.orient(x, xf)
|
||||
M = Rt @ Rq.transpose(1, 2)
|
||||
rv = 0.5 * torch.stack([M[:, 2, 1] - M[:, 1, 2], M[:, 0, 2] - M[:, 2, 0], M[:, 1, 0] - M[:, 0, 1]], -1) * 100 * pose[:, None]
|
||||
return torch.cat([T - p, rv], -1)
|
||||
M = Rtb @ Rq.transpose(1, 2)
|
||||
rv = 0.5 * torch.stack([M[:, 2, 1] - M[:, 1, 2], M[:, 0, 2] - M[:, 2, 0], M[:, 1, 0] - M[:, 0, 1]], -1) * 100 * poseb[:, None]
|
||||
return torch.cat([Tb - p, rv], -1)
|
||||
out = []; x = q.clone()
|
||||
ar = torch.arange(6, device=q.device)
|
||||
for _ in range(n):
|
||||
e0 = err(x); J = []
|
||||
for j in range(6):
|
||||
dx = torch.zeros_like(x); dx[:, j] = 1e-3
|
||||
J.append(-(err(x + dx) - e0) / 1e-3)
|
||||
J = torch.stack(J, -1) # [B,6(err),6(q)]
|
||||
e0 = err(x, T, Rt, pose)
|
||||
# 2026-10-20:6 次串行有限差分合并为一次批量 FK(数值等价,单次规划 ~25ms→~7ms)
|
||||
dx = torch.zeros(B, 6, 6, device=q.device); dx[:, ar, ar] = 1e-3
|
||||
xp = (x[:, None, :] + dx).reshape(B * 6, 6)
|
||||
ep = err(xp, T.repeat_interleave(6, 0), Rt.repeat_interleave(6, 0), pose.repeat_interleave(6, 0))
|
||||
J = -((ep - e0.repeat_interleave(6, 0)) / 1e-3).view(B, 6, 6).transpose(1, 2) # [B,6(err),6(q)]
|
||||
A = J @ J.transpose(1, 2) + lam ** 2 * torch.eye(6, device=q.device)
|
||||
y = torch.linalg.solve(A, e0.unsqueeze(-1))
|
||||
dq = (J.transpose(1, 2) @ y).squeeze(-1)
|
||||
@@ -225,7 +228,7 @@ def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None,
|
||||
else:
|
||||
# 2026-10-19 修错位:last[i] = 上一计划从 qe_old 走 i 步后的位置;提交 3 步后 qe_new = last[3],
|
||||
# 新候选 fut[0] 是 qe_new 再走 1 步 = 对应 last[4]。JS 部署(ik-policy.js)同一处同样修正。
|
||||
n = min(fut.shape[2], last.shape[1] - 4)
|
||||
n = min(fut.shape[2], last.shape[1] - (commit_n + 1))
|
||||
w = 0.85 ** torch.arange(n, device=device, dtype=torch.float32)
|
||||
d2 = (((fut[:, :, :n] - last[:, None, commit_n + 1:commit_n + 1 + n]) / step) ** 2).sum(-1)
|
||||
# 2026-10-19(审查 review_closedloop F5):上一次是刹停或 DLS 接管的行没有「已提交计划」,
|
||||
@@ -251,6 +254,7 @@ def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None,
|
||||
take = plen > maxlen
|
||||
chosen = torch.where(take[:, None, None], ck, chosen); chosen_k = torch.where(take, order[:, kk], chosen_k)
|
||||
maxlen = torch.maximum(maxlen, plen)
|
||||
if B == 1 and int(maxlen[0]) >= commit_n: break # 实时单题:首个全安全候选即停(安全层 16 点→2-4 点)
|
||||
msk = (torch.arange(commit_n, device=device)[None] < maxlen[:, None])
|
||||
commit = torch.where(msk[..., None], chosen, torch.zeros_like(chosen))
|
||||
brakes += (maxlen == 0).float()
|
||||
|
||||
Reference in New Issue
Block a user