exp: 端点进度选择——commit2 到达 52.1%/time_ok 35.2%(n=512),ratio2s 0.343→0.285;附带 50Hz 饥饿实测

- select='endpoint'(候选块末态离目标最近)优于 consist:n=512 到达 +1.3pp、time_ok +6.3pp、ratio −0.058
- 负结论:safety_try 1/2(41.4/44.9%)、K=4(47.3%)、DLS 兜底(52.3%/碰撞+1.1pp)、增益调度(47.3%)
- JS Runner:endpoint 选择落地、冷启动跳前瞻;starveTicks 指标;commit2 平均空转 0.8–1.3 tick,commit3 可覆盖
- route40 endpoint:12/20 ok、13/20 到达、刹车 40.4%
This commit is contained in:
cbb
2026-10-20 15:48:31 +08:00
parent d977be321b
commit ce9edd7934
5 changed files with 92 additions and 27 deletions
+20 -3
View File
@@ -153,7 +153,7 @@ class TeacherOracle:
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_exec=0.0, exec_safety=0, fb_ki=0.0, fb_decay=0.9, fb_imax=0.5, fb_every=1):
fb_exec=0.0, exec_safety=0, fb_ki=0.0, fb_decay=0.9, fb_imax=0.5, fb_every=1, safety_try=0, sel_w=0.1):
"""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 条)。
@@ -237,6 +237,10 @@ def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None,
fut = qe[:, None, None] + torch.cumsum(inc[:, :, r:], 2) # [B,K,H-r,6]
if select == 'first':
score = torch.zeros(B, K, device=device); score[:, 0] = 1
elif select == 'endpoint':
qa = fut[:, :, -1].reshape(B * K, 6)
e_end, _ = goal_err(kin, qa, T.repeat_interleave(K, 0), R.repeat_interleave(K, 0))
score = -e_end.view(B, K)
elif cold or select == 'value':
# 短前瞻:候选末态的价值
qa = fut[:, :, -1].reshape(B * K, 6); qb = fut[:, :, -2].reshape(B * K, 6)
@@ -253,6 +257,10 @@ def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None,
# 2026-10-19(审查 review_closedloop F5):上一次是刹停或 DLS 接管的行没有「已提交计划」,
# 与 JS(lastPlan = null → 一致性项缺席、各候选同分 → 取第 0 条)一致:同分,稳定排序取第 0 条
score = torch.where(last_ok[:, None], -(d2 * w).sum(-1), torch.zeros_like(d2[..., 0]))
if select == 'mix': # 一致性 + 端点进度(w=sel_w/mm)
qa = fut[:, :, -1].reshape(B * K, 6)
e_end, _ = goal_err(kin, qa, T.repeat_interleave(K, 0), R.repeat_interleave(K, 0))
score = score - sel_w * e_end.view(B, K)
order = torch.sort(score, dim=-1, descending=True, stable=True).indices
pick = order[:, 0]
if select == 'average': # 2026-10-20:候选平均(平滑误差)——所有候选置为 K 条动作的均值
@@ -267,7 +275,8 @@ def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None,
if safety and safety_partial: # 2026-10-20:允许「部分安全前缀」——执行到第一个不安全步为止,而不是全拒刹停
maxlen = torch.zeros(B, dtype=torch.long, device=device)
chosen = torch.zeros(B, commit_n, 6, device=device); chosen_k = pick.clone()
for kk in range(K_eff):
ntry = min(K_eff, safety_try) if safety_try > 0 else K_eff
for kk in range(ntry):
ck = inc[ar, order[:, kk], r:r + commit_n]
pts = qe[:, None] + torch.cumsum(ck, 1)
mids = torch.cat([qe[:, None], pts[:, :-1]], 1) + 0.5 * ck
@@ -281,12 +290,20 @@ def rollout(model, kin, tasks, device, K=8, safety=False, seed=0, max_sec=None,
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))
if fb_gain > 0 and fb_fallback > 0: # 全拒时兜底:半步朝目标(须通过间隙认证),避免原地停满整个周期
fb1 = dls_steps(kin, qe, T, R, n=1) * fb_fallback
ok1 = kin.gaps(qe + fb1[:, 0], 0.5)['gm'].min(-1).values > 0
fbcom = torch.zeros(B, commit_n, 6, device=device); fbcom[:, 0] = fb1[:, 0] # 只走一步(重复会被第二步未经认证的位移带进碰撞)
mskf = (maxlen == 0) & ok1
commit = torch.where(mskf[:, None, None], fbcom, commit)
msk = msk | mskf[:, None]
brakes += (maxlen == 0).float()
pick = chosen_k; committed = maxlen > 0
elif safety:
ok_any = torch.zeros(B, dtype=torch.bool, device=device)
chosen = torch.zeros(B, commit_n, 6, device=device); chosen_k = pick.clone()
for kk in range(K_eff):
ntry = min(K_eff, safety_try) if safety_try > 0 else K_eff
for kk in range(ntry):
ck = inc[ar, order[:, kk], r:r + commit_n]
pts = qe[:, None] + torch.cumsum(ck, 1)
mids = torch.cat([qe[:, None], pts[:, :-1]], 1) + 0.5 * ck