跳转至

HumanoidPF, LessMimic, APEX Notes

日期:2026-05-28

0. 本地 clone 状态

已 clone:

submodules/Click-and-Traverse
  official repo: https://github.com/GalaxyGeneralRobotics/Click-and-Traverse
  paper/project: HumanoidPF / CAT

submodules/LessMimic
  official repo: https://github.com/Yutang-Lin/LessMimic

APEX 官方项目页目前写的是 Code (Coming Soon),没有官方代码可 clone。项目页:

https://apex-humanoid.github.io/

LessMimic 的 GitHub 仓库目前也只有 README 和 resources/teaser.png,README 明确写着 Code will be released. Stay tuned.,所以 LessMimic 不能做代码级实现分析,只能基于 paper/README/project page。

1. HumanoidPF 到底是不是启发式

结论:

HumanoidPF 的 field 是从 obstacle occupancy + goal 算出来的几何场。
它不是 learned field,也不是 object affordance rule。
但它仍然包含手工设计的公式和超参。

所以它介于两者之间:

不是:手写 chair/socket/pick/place 这种 affordance 规则
也不是:从数据学习出来的 neural affordance field
而是:algorithmic geometric potential/guidance field

1.1 field 构造

核心文件:

submodules/Click-and-Traverse/procedural_obstacle_generation/pf_modular.py
submodules/Click-and-Traverse/procedural_obstacle_generation/main.py

make_sdf(...)

phi_obs = np.ones(obs_mask.shape, dtype=float)
phi_obs[obs_mask] = -1.0
sdf = skfmm.distance(phi_obs, dx=voxel).astype(np.float32)

也就是从 3D obstacle occupancy mask 算 signed distance field。

grad3(sdf, voxel)

dfx, dfy, dfz = np.gradient(scalar_field, voxel, voxel, voxel, edge_order=2)
return np.stack([dfx, dfy, dfz], axis=-1).astype(np.float32)

这得到 obstacle boundary normal field,代码里叫 bf.npy

make_guidance_field_progressive(...) 是 HumanoidPF 核心:

  1. 用 goal seed 和 obstacle mask 跑 Fast Marching,得到到 goal 的 geodesic distance T
  2. -grad(T) 得到朝 goal 的 guidance direction。
  3. 用 SDF normal field bf 把靠近障碍物时的方向投影到 obstacle tangent plane:
g_perp = g - proj * bunit
  1. 根据到 obstacle 的距离 d_out 做 smooth blending:
w = 1.0 - smooth(d_out / r_proj)
g_mix = (1.0 - w) * g + w * g_perp
  1. inside obstacle 时直接用 normal 推出去:
g_mix[obs_mask] = bunit[obs_mask]
  1. normalize 后乘 goal-distance-based speed,保存为 gf.npy

生成脚本 main.py 会为每个 obstacle scene 保存:

sdf.npy  # signed distance
bf.npy   # SDF gradient / obstacle normal field
gf.npy   # goal-conditioned guidance field
obs.npy  # occupancy
obs.obj  # visualization/collision mesh

1.2 field 如何进入 policy observation

核心文件:

submodules/Click-and-Traverse/cat_ppo/envs/g1/env_cat.py

环境初始化时加载:

self.sdf = jp.array(np.load(f"{pf_path}/sdf.npy"))[...,None]
self.bf  = jp.array(np.load(f"{pf_path}/bf.npy"))
self.gf  = jp.array(np.load(f"{pf_path}/gf.npy"))

每个 step 在 humanoid 多个 body site 上采样:

all_poses = concat([
  head_pos,
  pelvis_pos,
  torso_pos,
  feet_pos,
  hands_pos,
  knees_pos,
  shoulders_pos,
])
all_gf = self.sample_field(self.gf, all_poses)
all_bf = self.sample_field(self.bf, all_poses)
all_df = self.sample_field(self.sdf, all_poses)

采样函数是 trilinear interpolation:

idx = (pos - pf_origin) / dx
vals = field[corners]
out = weighted_sum(vals)

policy observation 里放的是:

head/pelvis/torso/feet/hands/knees/shoulders:
  gf  # guidance direction
  bf  # obstacle boundary normal
  df  # signed distance

并且这些向量先被转到 navigation/body frame,df 会 clip 到 [-1.0, 0.5]bf 只在距离 obstacle 小于 0.5m 时保留。

1.3 field 如何进入 reward / termination

termination:

contact_termination |= any(headdf < -term_collision_threshold)
contact_termination |= any(pelvdf < -term_collision_threshold)
contact_termination |= any(torsdf < -term_collision_threshold)
contact_termination |= any(feetdf < -term_collision_threshold)
contact_termination |= any(handsdf < -term_collision_threshold)
contact_termination |= any(kneesdf < -term_collision_threshold)
contact_termination |= any(shldsdf < -term_collision_threshold)

reward 有两类:

  1. gf alignment reward:body part 速度要和 guidance field 方向一致,且只在靠近障碍物时强启用。
cos_align = dot(normalize(gf_vel), normalize(body_vel))
window = sigmoid(k * (tau - sdf))
reward_near = window * alpha_align * cos_align
  1. df collision penalty:SDF 小于 safety margin 时 softplus penalty。
pen_inside = softplus((sdf_safe - sdf) / beta_inside)
reward = -pen_inside_scale * pen_inside

训练入口 train_ppo.py 把不同 body-level obstacle reward 分成:

ground:   feetgf / feetdf
lateral:  handsgf / handsdf / kneesdf / shldsdf
overhead: headgf / headdf

这解释了为什么 HumanoidPF 不是简单 root potential field。它是 body-part sampled 的 3D geometry field。

1.4 field 如何生成 command

compute_cmd_from_rtf(...) 还会把 pelvis guidance 和其他 contact-body guidance/normal 投影成 velocity command:

v = rtf[:2] * 0.7
delta = projection correction from contact-body gf/bf
v_new = v + mean(delta)
command = [move_flag, vx, vy, yaw]

代码注释说这是:

reuse command in velocity control for our HumanoidPF,
can be seen as a single iteration of field projection

所以 HumanoidPF 的 field 同时用于:

policy observation
velocity command generation
collision-aware reward
termination

2. LessMimic 到底是什么 field

本地代码状态:

submodules/LessMimic/README.md
submodules/LessMimic/resources/teaser.png

没有 release 训练代码,所以不能像 HumanoidPF 那样确认函数级实现。

根据 README、arXiv abstract、项目页,LessMimic 的 DF 也是几何距离场,不是简单 object socket 规则。它强调:

surface distances
gradients
velocity decompositions
interaction latents encoded via VAE
AIP-derived RL
DAgger-style distillation to egocentric depth

核心区别:

方法 field 来源 field 作用 是否 learned
HumanoidPF occupancy + goal 的 SDF/geodesic/guidance traversal observation/reward/command field 本身不是 learned,policy 是 learned
LessMimic object distance field / geometry cues interaction observation/reward representation DF 几何是 computed;interaction latent/AIP 是 learned

LessMimic 最关键的不是“DF 是神经网络算的”,而是:

它把不同物体几何 quotient 到统一 DF 空间,
再用 VAE/AIP/RL 学 interaction dynamics。

也就是说,DF 本身仍然可以是 analytic/computed;novelty 在于:

policy 在 DF-derived geometric cue 上学交互,
而不是 track fixed reference motion 或手写每个任务 reward。

3. APEX 可借鉴点

APEX 官方 code 当前未发布。只能根据 paper/project page 确认:

  1. 它不是 field/potential paper。
  2. 核心是 high-platform traversal 的 contact-rich maneuver learning。
  3. 最关键可借鉴的是 generalized ratchet progress reward:
track best-so-far task progress
reward only genuine improvement
penalize non-improving steps
avoid velocity-tracking-induced jumping/impact

对 PhysHSI 的意义:

long-horizon HSI 里可以用 ratchet progress 处理 sparse subgoal:
  approach target
  establish contact
  lift object
  carry through clutter
  place stable
  sit stable

它不直接回答 affordance field,但回答“怎么让 contact-rich RL 不靠速度 reward 硬冲”。

4. 对我们方案的修正

之前把 Kimodo constraint generator 也叫 affordance field,这不够严谨。应改为两层:

Layer A: Affordance-aware constraint generation
  输入: SAGE scene_context / object_sockets / task_validation
  输出: Kimodo constraints
  本质: 约束生成,不必叫 field

Layer B: Body-part field-conditioned RL policy
  输入: geometry field sampled at body parts + task/action phase
  输出: state policy action
  本质: 类 HumanoidPF/LessMimic 的 policy representation

真正有论文价值的是 Layer B。

4.1 我们不能只做启发式 field

如果我们只做:

SAGE object heuristic -> keyframes -> Kimodo

reviewer 会合理地说:

这是 constraint engineering。

更强版本应该是:

computed geometry field + learned interaction field/residual

建议定义:

F_geo:
  SDF / ESDF
  SDF gradient / obstacle normal
  geodesic guidance to subgoal
  height/support map
  held-object inflated collision volume

F_inter:
  contact likelihood for body part and phase
  desired body/object relative velocity decomposition
  attach/release probability
  support/grasp/place stability latent

F_geo 从 SAGE geometry 算,类似 HumanoidPF。 F_inter 从成功/失败 rollout 学,类似 LessMimic 的 interaction latent/AIP 方向。

4.2 对 Kimodo 的正确定位

Kimodo 不需要 field。Kimodo 需要 constraints。

在我们的系统里 Kimodo 应该是:

bootstrap reference generator

不是:

field method 的核心

可行流程:

SAGE scene/task
  -> current object_sockets/keyframe_targets
  -> Kimodo reference
  -> tracking teacher with F_geo/F_inter rewards
  -> successful/failed rollouts
  -> train field-conditioned state policy

4.3 和 HumanoidPF/LessMimic 的差异空间

HumanoidPF 只处理 obstacle traversal:

goal-conditioned guidance field + body-part collision avoidance

LessMimic 处理 object interaction:

object DF + interaction latent/AIP

我们的空间应该是:

SAGE crowded HSI:
  obstacle traversal
  object interaction
  held-object navigation
  sit/pick/place/carry composition

用同一个 body-part field observation/reward interface 统一。

具体差异要落在实验:

  1. TokenHSI/UniHSI 能交互但 crowded collision 多。
  2. HumanoidPF/CAT 能避障但没有 sit/carry/place。
  3. LessMimic 有 interaction DF,但官方目前不强调 crowded indoor obstacle traversal / held-object clearance through clutter。
  4. 我们要证明:
body-part geometry guidance + learned interaction latent
优于
PF traversal -> HSI interaction 的 hard switch

5. 推荐下一步实现

第一步不要重写 Kimodo constraint generator。

更合理的 MVP:

1. 在 SAGE 上实现 HumanoidPF-style F_geo:
   occupancy/ESDF
   geodesic-to-subgoal guidance
   obstacle normal
   body-part sampling API

2. 把 F_geo 接到 tracking/RL env:
   observation: head/pelvis/torso/feet/hands/knees/shoulders sampled field
   reward: gf alignment + df safety penalty
   termination: body-part df threshold

3. 对 HSI 增加 interaction channels:
   hand-object DF
   pelvis-seat DF
   object-support DF
   held-object inflated collision DF

4. 用 Kimodo/reference rollout bootstrap F_inter:
   VAE or small latent encoder over body-part DF sequences
   discriminator/AIP over interaction field trajectories

这样方案才不是“把已有 affordance hints 换个名字”。