perf+exp: gm_groups 只算特征 8 组(数值一致,features 10.4→7.1ms);混合节奏负结论(执行反馈无提升);浏览器部署 dag2 ONNX + fbGain/commit 参数(bench 刹车 47% 待调);实时口径改为异步规划+tick
This commit is contained in:
@@ -52,8 +52,10 @@ def features(kin, q, q_prev, T, R, prefix, prefix_len, sub, sub_flag, gm=None, x
|
||||
out.append(sd)
|
||||
out.append(sub_flag[:, None].to(dt))
|
||||
if gm is None:
|
||||
gm = kin.gaps(q, GAP_CAP, xf)['gm']
|
||||
out.append(torch.stack([gm[:, a * 7 + b].clamp(max=GAP_CAP) / GAP_CAP for a, b in GP], -1))
|
||||
out.append(kin.gm_groups(q, GP, GAP_CAP) / GAP_CAP) # 2026-10-20:只算特征用到的 8 组
|
||||
gm = None
|
||||
if gm is not None:
|
||||
out.append(torch.stack([gm[:, a * 7 + b].clamp(max=GAP_CAP) / GAP_CAP for a, b in GP], -1))
|
||||
f = torch.cat(out, -1)
|
||||
assert f.shape[1] == F_DIM, f.shape
|
||||
return f
|
||||
|
||||
@@ -202,6 +202,41 @@ class Kin:
|
||||
if not pairs: return {'gm': gm.view(B, 49)}
|
||||
return {'gm': gm.view(B, 49), 'b': rep_b, 'i': pi, 'j': pj, 'gap': gap}
|
||||
|
||||
def gm_groups(self, q, gp, cap=40.0):
|
||||
"""只算指定组对 gp=[(a,b),...] 的最小间隙 [B,len(gp)](特征用,避免 49 组全量)。
|
||||
数值与 gaps(q,cap)['gm'][:, a*7+b] 一致;组对在碰撞粗对里不存在时返回 cap。"""
|
||||
key = tuple(gp)
|
||||
if getattr(self, '_gp_key', None) != key:
|
||||
m = torch.full((49,), -1, dtype=torch.long, device=q.device)
|
||||
for i, (a_, b_) in enumerate(gp): m[min(a_, b_) * 7 + max(a_, b_)] = i
|
||||
ga, gb = self.cl_g[self.cp_a], self.cl_g[self.cp_b]
|
||||
cg = torch.minimum(ga, gb) * 7 + torch.maximum(ga, gb) # 簇对 → 7 连杆组对
|
||||
sel = torch.isin(cg, torch.tensor([min(a, b) * 7 + max(a, b) for a, b in gp], device=q.device))
|
||||
self._gp = (m, sel, sel.nonzero(as_tuple=True)[0]); self._gp_key = key
|
||||
self._gp49, sel, idx = self._gp
|
||||
xf = self.cum_xf(q); Rs, Ts = xf; B = q.shape[0]
|
||||
with torch.no_grad():
|
||||
cc = torch.einsum('bkij,kj->bki', Rs[:, self.cl_g], self.cl_c.to(q.dtype)) + Ts[:, self.cl_g]
|
||||
d2 = (cc[:, self.cp_a[idx]] - cc[:, self.cp_b[idx]]).pow(2).sum(-1)
|
||||
keep = d2 <= (self.cp_lim[idx] + cap).pow(2)
|
||||
bb, mm = keep.nonzero(as_tuple=True)
|
||||
del keep, d2, cc
|
||||
cnt = self.cp_cnt[idx][mm]
|
||||
rep_b = torch.repeat_interleave(bb, cnt)
|
||||
off = torch.repeat_interleave(self.cp_start[idx][mm] - torch.cumsum(cnt, 0) + cnt, cnt) + torch.arange(int(cnt.sum()), device=q.device)
|
||||
pidx = off
|
||||
a, b = self.caps_world(q, xf)
|
||||
with torch.no_grad():
|
||||
pi, pj = self.pi[pidx], self.pj[pidx]
|
||||
mid = 0.5 * (a[rep_b, pi] + b[rep_b, pi] - a[rep_b, pj] - b[rep_b, pj])
|
||||
k2 = mid.pow(2).sum(-1) <= (self.pair_bl[pidx] + cap).pow(2)
|
||||
rep_b, pidx, pi, pj = rep_b[k2], pidx[k2], pi[k2], pj[k2]
|
||||
d = seg_seg_dist(a[rep_b, pi], b[rep_b, pi], a[rep_b, pj], b[rep_b, pj])
|
||||
gap = d - self.pair_need[pidx].to(q.dtype)
|
||||
gm = torch.full((B * len(gp),), float(cap), dtype=q.dtype, device=q.device)
|
||||
gm = gm.scatter_reduce(0, rep_b * len(gp) + self._gp49[self.pair_gp[pidx]], gap.clamp(max=cap), reduce='amin', include_self=True)
|
||||
return gm.view(B, len(gp))
|
||||
|
||||
def min_gap(self, q, cap=40.0):
|
||||
return self.gaps(q, cap)['gm'].min(-1).values
|
||||
|
||||
|
||||
@@ -145,7 +145,8 @@ class TeacherOracle:
|
||||
@torch.no_grad()
|
||||
def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None, return_traj=False, use_sub=True, sub_override=None,
|
||||
qp0=None, steps=1, z_scale=1.0, select='consist', oracle=None, replan='r3', sub_rule='cross',
|
||||
fb_gain=0.0, fb_scale=0.0, fb_near=0.2, fb_fallback=0.0, safety_partial=0, commit_n=3, collect=None):
|
||||
fb_gain=0.0, fb_scale=0.0, fb_near=0.2, fb_fallback=0.0, safety_partial=0, commit_n=3, collect=None,
|
||||
fb_exec=0.0, exec_safety=0):
|
||||
"""use_sub=False:不用子目标(sf=0);sub_override=(subs [B,M,6] 绝对关节角, n [B] 个数 或 need [B] bool):冷启动时用给定途经点代替子目标头;
|
||||
qp0 [B,6]:起点的上一帧(默认 = q0,即静止起步)。steps:MeanFlow 采样段数;z_scale:噪声缩放;
|
||||
select:consist(部署口径:冷启动价值前瞻、之后与上一条已提交计划的一致性)/ value(每次都价值前瞻)/ first(不选,取第 0 条)。
|
||||
|
||||
Reference in New Issue
Block a user