人形机器人与物体交互时,需要协调运动跟踪、接触力和全身平衡。物体几何或接触状态发生变化后,固定运动参考可能产生较大的接触力;允许参考随外力调整,则需要同时约束位移范围和接触稳定性。

本文从阻抗与导纳控制出发,介绍柔顺参考如何随交互力更新,以及全身策略如何执行这些参考。GentleHumanoid 提供方法背景,基于 Omni 的普通物体交互、柔顺交互与 FALCON 扩展提供具体实现。物体交互部分以双手夹持和承载箱体为例,分析法向预紧、接触丢失与参考回弹,文中对应数值均来自这一案例。新增机制属于适配实现,需要与原论文方法区分。

三条实现的区别首先在力从哪里来、参考改到哪一层:Gentle 使用交互弹簧分别驱动虚拟参考与仿真连杆;Omni 交互适配把处理后的接触力送进参考积分器;FALCON 扩展还将笛卡尔退让经 IK 转成关节参考。它们共享虚拟动力学的思路,但受力模型、积分状态和策略输入各不相同,下面分开推导。

1. 先区分关节 PD、阻抗和导纳

关节 PD 的典型形式是:

它在关节空间定义误差与力矩的关系。末端接触刚度还受到姿态、雅可比和机构耦合影响。固定接触、忽略冗余和其他动力学项时,可用局部近似:

所以把所有关节 统一减半,不能保证每个接触方向都得到相同的柔顺变化。接近奇异位形时,这种简化分析尤其需要谨慎。

阻抗控制通常从运动偏差生成力或力矩;导纳控制从外力生成运动参考。例如让位置接口机器人追踪一个虚拟质量的状态:

其中, 是名义目标, 是柔顺参考, 是虚拟质量,并非实际手臂质量。虽然一些实现把模块命名为 impedance reference,从“力输入、位置参考输出”的接口看,它承担导纳参考生成的作用。

2. 刚度、质量和阻尼分别控制什么

对静止目标、恒定外力、未触发限幅的单轴系统,令 :

自然频率与阻尼比为:

质量改变响应速度,刚度改变静态退让距离。增大质量不会降低恒定载荷下的最终退让量。取 kg、 N/m,临界阻尼为 N·s/m,自然频率 Hz。10 N 恒力对应 4 cm 平衡偏移。

对静止目标、常系数且未限幅的单轴参考模型,还可以从能量检查阻尼的作用。取虚拟动能与弹性势能之和:

外力通过运动做功,正阻尼消耗能量;无外力时能量不增加。但这里分析的只是连续时间虚拟参考。离散积分、移动目标、限幅、接触状态机与跟踪策略加入后,还需要重新分析整个闭环,不能把这一个等式当成真机交互安全的证明。

虚拟柔顺参考的解析响应

图 1:静止目标受到 10 N 阶跃力的单轴解析响应,均使用临界阻尼。虚线表示 Omni 配置的 3 cm 总偏移边界;曲线未模拟裁剪、接触状态机或机器人动力学,不是真机测量。

对于移动目标,上述绝对加速度形式变为:

没有参考加速度前馈时,快速变化的名义轨迹本身也会引起偏移。因此不能看到 就全部归因于接触。

3. GentleHumanoid 为什么要改参考

纯粹加入随机推力,再奖励机器人恢复原动作,往往训练出抗扰动能力;它不会自动学会“对人的推拉让开”。GentleHumanoid 将交互力和柔顺参考联系起来,使任务目标允许身体在接触中发生受控偏移。GentleHumanoid 论文

GentleHumanoid 的参考动力学与训练机制

论文原图:GentleHumanoid 作者,Figure 2,CC BY 4.0;未修改。来源:论文/原图。图右的部署演示属于论文结果,不是本文适配的验证结果。

图 a 维护虚拟参考状态,而非直接把外力当作 actor 动作;图 b 同时比较位置、速度和交互力。实现对应到 command 的参考积分、奖励函数的目标替换、以及实际仿真身体状态三个位置。只添加外力 randomization 而保留刚性目标,会改变训练扰动,却没有复制这条机制。

该图也提醒我们检查训练/部署的信息边界:privileged observation 可以帮助训练,但不能假定部署拥有同样的接触力真值。Omni 物体交互适配和 FALCON 扩展的新增链路分别在下文展开。

两个力分别作用在哪里

对肩、肘、手等选定连杆,各维护一个三维虚拟点。记名义动作目标为 ,积分状态为 ,真实机器人状态为 ;前三维位置都在同一个 root 坐标系中表示。这里的虚拟点不是关节转角,虚拟质量也不是 armature。参考模型的基本方程为:

驱动力将虚拟点拉向名义动作:

这里, 的单位是 N/m, 是 N·s/m;下发到电机的关节 PD 则使用 N·m/rad 和 N·m·s/rad。两者都能从二阶系统分析,但作用空间、惯量和控制对象不同,不能直接复制数值。

交互弹簧描述连杆与外界的联系,其基础形式为:

阻性接触从接触开始时的位置建立锚点;机器人继续向接触方向运动时,弹簧产生恢复力。引导接触将锚点移向从人体姿态采样的目标,产生协调的推拉。对肩、肘、手使用同一姿态样本,可以保留运动链的几何关系;若每个点独立抽方向,可能生成同一手臂难以协调完成的受力组合。锚点在代码中保存在 root 系,切换时平滑插值,不能把它当成始终固定的世界坐标障碍物。GentleHumanoid:力模型与锚点定义

同一模型要计算两遍:虚拟参考使用 ,仿真施力使用 。前者决定期望怎样退让,后者改变真实机器人的动力学。驱动力留在参考积分器中;交互力则按真实连杆位置计算后施加到仿真身体。把所有力都理解成“不作用于机器人”,会漏掉训练时的受力环境。

单边接触与向量限幅

基础弹簧在两个方向都会拉回,实现还要定义接触在哪一侧生效。令 从锚点指向名义目标,位移 ,当前实现使用:

当 ,力沿 作用;当虚拟点或真实连杆离开该接触侧,力为零。符号取决于 n 的定义,不能把 clamp_max(0) 随手改成 clamp_min(0)。这是单边接触代理,尚未包含完整的摩擦锥或物体形变模型。

驱动力的安全阈值另作一次范数裁剪:

它保持向量方向,仅缩小幅值。例如原力为 (6,8,0) N、阈值为 5 N,结果是 (3,4,0) N;逐分量裁剪得到的 (5,5,0) N,其范数仍超过 5 N。论文记号 在这里仍是力,单位 N,并非关节力矩。它与交互力上限 是不同参数。GentleHumanoid:驱动力限幅

参考怎样积分,代码又增加了什么

论文主文使用半隐式 Euler:先更新速度,再用新速度更新位置。当前实现额外增加质量链阻尼 N·s/m,并对加速度、速度做范数限幅:

参考更新的主要计算可写成下面的等价步骤;sat_norm 表示上面的范数裁剪,批次与连杆维度省略:

1
2
3
4
5
6
7
8
9
10
for _ in range(4):
drive = kp * (target_pos - ref_pos) + kd * (target_vel - ref_vel)
drive = sat_norm(drive, safe_force)
displacement = anchor - ref_pos
projected = (displacement * direction).sum(-1, keepdim=True).clamp_max(0) * direction
interaction = sat_norm(spring_gain * projected, max_interaction_force)
acceleration = sat_norm((drive + interaction - 2.0 * ref_vel) / 0.1, 1000.0)
ref_vel = sat_norm(ref_vel + physics_dt * acceleration, 4.0)
ref_pos = ref_pos + physics_dt * ref_vel
# 另用 actual_pos 代替 ref_pos 计算真实连杆的施力

这条实现设置 kg、 m/s、 m/s²;子步 h 读取物理步长。若物理步长为 0.005 s,4 次更新才覆盖 0.02 s 的策略周期。复制循环次数时,仍需核对实际 physics_dt 与控制周期;不能每次使用 0.02 s 再循环四次。论文主文与附录对积分名称和步长的描述并不完全一致,这里以代码中的“先速度、后位置”顺序说明运行机制。

驱动刚度还随期望力阈值变化:

当 N 时, N/m,驱动阻尼约为 8.9443 N·s/m。考虑额外阻尼后,无接触、静止目标且未触发限幅时,阻尼比约为 ,已不是恰好临界。驱动力在纯位置误差达到 5 cm 时进入限幅;目标或参考正在运动时,速度误差也会使它提前饱和。

接触弹簧怎样改变平衡点与阻尼比

在单轴接触侧已激活、目标和锚点静止、所有限幅都未触发的局部区间,方程变为:

因此:

取 N/m、 N/m、名义目标为 0、锚点为 −3 cm,平衡参考在 −1 cm:驱动力为 +2 N,交互弹簧力为 −2 N。增大接触刚度改变的不只是退让距离,也会改变闭环自然频率和阻尼比;按驱动弹簧设计的临界阻尼,并不保证接触后仍临界。

这里也能判断“刚性特例”的说法是否成立。令交互弹簧刚度趋于无穷,参考趋向锚点;令安全阈值趋于无穷,只是去掉驱动力裁剪。两者并不等于固定跟踪原动作。普通物体交互与柔顺交互的区别,应检查是否启用受力参考更新,以及更新后的参考是否真正进入奖励和控制接口。

训练信号怎样约束上述模型

论文的柔顺奖励为:

三个原始量如下,系数对应论文 Table I;后面的机器人握手适配另有实际权重表。论文使用误差范数的指数核,不能将下面的范数擅自平方。GentleHumanoid:奖励定义与权重

论文项 权重 模型与策略之间的联系
reference_dynamics_tracking 2 实际位置、速度跟踪虚拟参考
reference_force_tracking 2 实际交互力匹配参考模型交互力
unsafe_force_penalty 6 惩罚超过阈值与容差的接触
reference_dynamics_tracking

论文将位置与速度项相加:

位置误差和速度误差有不同单位,分别由各自的 sigma 缩放。实际适配把二者拆成独立配置项,并按施力点集合聚合;不能把论文的系数 2 直接当作每个适配项的权重。

reference_force_tracking

参考弹簧力与实际施加的弹簧力分别用虚拟状态、真实状态计算,再比较:

只让位置误差小,并不一定让作用力匹配,尤其在弹簧刚度变化时。本项约束两条力计算是否一致;它并不直接要求所有交互力都为零。

unsafe_force_penalty

论文的超力代价形式为:

原始量已经为负,因此论文系数为 +6。当前握手适配还要求实际力超过期望力 +5 N,之后才计入超限接触点比例;它与这条论文指示函数并不完全相同,具体代码见下表的 force_exd_penalty。

论文将交互弹簧刚度在 5–250 N/m 内随机化,锚点与受力集合按时间重采样;当前代码还对锚点、刚度和阈值做平滑过渡。这与“每隔几秒独立抽一个恒力向量”不同,力会随位置变化。本文握手适配只在右手建立有效接触,单点力上限为 6 N,躯干合力/合力矩预算为 7 N/4.5 N·m;不能把论文展示的 0–25 N 力分布、默认单点上限 30 N 和本例上限 6 N 混为同一参数。

学生策略的可部署观测可概括为:

参考状态与交互力真值属于教师的额外信息。论文的压力垫用于接触力测量与评估,不能据此认定学生必须把压力垫读数作为输入;原方法可通过本体感知与历史学习接触响应。若要显式在线力闭环,才需另行定义传感器或估计器接口。当前握手适配仍训练教师,并未因为具备力观测槽位就自动完成学生部署。

最后还要关注坐标系:在运动的 root frame 中积分,位置、速度和力必须使用相容的变换。严格的相对速度包含旋转项,。当前速度变换只旋转世界速度差,未减去旋转项;在躯干快速旋转时,它不等于该相对位置坐标的时间导数。

Gentle 适配:力、位置、速度是不同奖励

下面列出握手柔顺任务的交互奖励与运动跟踪奖励;姿态生存、接地与动作正则属于另外的 loco 组。环境默认在每组奖励汇总后乘 step_dt。这是针对当前握手动作的适配配置,不是论文表格的照抄。applied_force_mean 和 applied_force_max 虽有 weight=1,但 enabled=false,所以不计入回报。

点击名称可跳到对应的公式与实现说明,并自动展开。

名称 配置权重 核参数 作用
force_reward +0.12 σ=[4,2] N 匹配期望交互力
force_exd_penalty +0.60 超过 safe_limit+10 N 且超过期望力+5 N 抑制超阈值交互力
force_target_tracking +0.60 σ=[0.25] m 追踪受力后的虚拟位置
force_target_vel_tracking +0.12 σ=[1,0.5] m/s 追踪柔顺参考速度
keypoint_tracking_imp +3.2 σ=[0.5] m 关键点总体跟踪
lower_keypoint_tracking +1.8 σ=[0.5] m 稳定下肢与支撑
root_pos_tracking +0.65 σ=[0.4] m 保持根位置
root_rot_tracking +1.3 σ=[1,0.5] rad 保持根朝向
root_vel_tracking +0.2 σ=[1,0.5] m/s 跟住根运动速度
root_ang_vel_tracking +0.2 σ=[2.5] rad/s 跟住根角速度
joint_pos_tracking +1 σ=[0.6,0.3] rad 保留关节动作
joint_vel_tracking +0.18 σ=[3,1.5] rad/s 保留关节速度

逐项实现

force_reward

握手任务的力跟踪比较实际施加力与期望力之差,先求各点向量范数再平均。_calc_exp_sigma 使用 exp(−error/σ),对多个 σ 的核求平均,既没有误差平方,也没有 σ²。只要任一点超过当前安全阈值+10 N,就将本项清零。

1
2
3
error = (force_applied - force_expected).norm(dim=-1).mean(-1)
r = 0.5 * (torch.exp(-error / 4) + torch.exp(-error / 2))
r *= ~((force_applied.norm(dim=-1) > safe_limit + 10).any(-1))
force_exd_penalty

注意正号:奖励函数内部返回负的超限接触点比例,再乘 +0.60。若误把权重设成 −0.60,会奖励超力。安全阈值是 command 状态,不是固定写死的物理接触上界。

1
2
3
actual = force_applied.norm(dim=-1)
expected = force_expected.norm(dim=-1)
r = -((actual > safe_limit + 10) & (actual > expected + 5)).float().mean(-1)
force_target_tracking

选 force_apply 对应的身体位置,与 force_keypoint_w 比较。名字含 force,但这是位置跟踪项,不是再次对力做回归。当前握手配置保留三组观测槽位,只有右手是真正施力接触点,不能把三个槽位都描述成施力点。

1
2
error = (force_keypoint_w - actual_body_pos).norm(dim=-1).mean(-1)
r = torch.exp(-error / 0.25)
force_target_vel_tracking

比较实际身体线速度与虚拟关键点速度,平均范数误差后使用两个指数核。仅在位置目标上允许退让但不匹配速度,可能学到高速追赶;这项对该瞬态提供约束。

1
2
error = (force_keypoint_vel_w - body_vel_w).norm(dim=-1).mean(-1)
r = (torch.exp(-error) + torch.exp(-error / 0.5)) / 2
keypoint_tracking_imp

先复制名义关键点,再把柔顺子集替换为 force_keypoint_w。因此一项里同时存在普通目标与柔顺目标,不能把整套参考都改成同一个平移偏移。

1
2
3
4
target = nominal_keypoints.clone()
target[:, compliant_ids] = force_keypoint_w
error = (target - actual).norm(dim=-1).mean(-1)
r = torch.exp(-error / 0.5)
lower_keypoint_tracking

对下肢关键点单独计算位置范数均值,避免上肢大量点稀释支撑结构。它保持名义参考,不沿用上肢柔顺点的偏移。

1
2
error = (lower_target - lower_actual).norm(dim=-1).mean(-1)
r = torch.exp(-error / 0.5)
root_pos_tracking

误差是世界位置差的范数。 表中系数来自当前机器人握手任务,不能作为 GentleHumanoid 原论文全部实验的统一参数。

1
2
error = (root_target - root_actual).norm(dim=-1)
r = torch.exp(-error / 0.4)
root_rot_tracking

使用目标与实际四元数组合后的轴角范数。 表中系数来自当前机器人握手任务,不能作为 GentleHumanoid 原论文全部实验的统一参数。

1
2
error = axis_angle_error.norm(dim=-1)
r = (torch.exp(-error) + torch.exp(-error / 0.5)) / 2
root_vel_tracking

各自用实际/参考 root 四元数转到身体坐标,再比较向量范数。 表中系数来自当前机器人握手任务,不能作为 GentleHumanoid 原论文全部实验的统一参数。

1
2
error = (v_ref_body - v_actual_body).norm(dim=-1)
r = (torch.exp(-error) + torch.exp(-error / 0.5)) / 2
root_ang_vel_tracking

各自转入 root frame 后比较,不直接相减两个不同坐标系的分量。 表中系数来自当前机器人握手任务,不能作为 GentleHumanoid 原论文全部实验的统一参数。

1
2
error = (omega_ref_body - omega_actual_body).norm(dim=-1)
r = torch.exp(-error / 2.5)
joint_pos_tracking

先取关节绝对误差的平均,即 L1 均值,而非平方和。 表中系数来自当前机器人握手任务,不能作为 GentleHumanoid 原论文全部实验的统一参数。

1
2
error = (q_ref - q).abs().mean(-1)
r = (torch.exp(-error / 0.6) + torch.exp(-error / 0.3)) / 2
joint_vel_tracking

当前实现以相邻关节位置差除 step_dt 估计实际速度,再和参考比较,不直接读取仿真器 dof_vel。 表中系数来自当前机器人握手任务,不能作为 GentleHumanoid 原论文全部实验的统一参数。

1
2
3
qd_fd = (q - q_last) / step_dt
error = (qd_ref - qd_fd).abs().mean(-1)
r = (torch.exp(-error / 3) + torch.exp(-error / 1.5)) / 2

loco 组仍负责站稳:当前启用 survival 15、impact force 0.05、feet slip 8.5、joint velocity 0.003、action rate 0.8、二阶动作差 0.005、位置限位 20(soft factor 0.75)、feet on ground 8、下肢/腰默认姿态 5.8、termination 12;这些惩罚的负号在函数内部。joint acceleration、feet air time、feet contact count 在该任务关闭。调整柔顺项时不能把支撑正则当成没有了,也不能跨实现只比较正负号。

对原生思路的具体适配还包括:只在右手施加交互力、上肢动作幅度按左右侧和关节分组降低、保留力观测槽位以兼容已有 checkpoint,并以 student_train=False 训练当前教师。训练中的特权力信息不能不经验证直接放入部署 actor。

4. 基于 Omni 的普通交互与柔顺交互

普通物体交互先用 OmniRetarget 生成机器人、物体与场景之间的几何参考,再由物理跟踪策略执行。本例使用箱体作为交互对象。接触会改变机器人的真实状态,名义目标本身却不会因为手腕受力自动退让:策略仍朝原有参考纠偏。

柔顺交互在 command 层启用 enable_compliance,为手臂接触链维护位置与速度状态。接触力经滤波、法向投影及限幅进入虚拟动力学;积分后的参考再经过方向边界与接触状态机,最后替换身体位置奖励的对应目标。预紧、防滑和接触丢失项共同约束“既能退让,又不松手”。仿真材质的 compliance 参数只影响接触模型,不能代替这条主动参考更新链。

与前面的 Gentle 交互弹簧相比,这个参考积分器接收的是处理后的真实接触力,而不再用虚拟点到锚点的弹簧距离生成外力。子步更新为:

这里的接触力先经过上游的滤波和方向处理;积分器自身再次按向量范数限幅。它没有 Gentle 质量链中额外的 −2v 阻尼项,阻尼由驱动项 D 提供。之后才执行总偏移边界与径向速度修正,不能把两套积分器写成参数不同但其余完全相同的模型。

柔顺参考与全身控制闭环

图 2:重定向提供名义几何参考;力驱动的参考更新处理交互变化;全身策略在平衡与跟踪之间协调。图中的力反馈必须来自传感器、估计器或仿真,不能凭空假定部署端可用。

本文物体交互案例中的柔顺参数为:虚拟质量 0.5 kg,基准刚度 250 N/m,reset 时随机化范围 200–350 N/m,4 个积分子步,驱动力范数上限 25 N,输入交互力裁剪 30 N,总偏移边界 0.03 m。临界阻尼随刚度重算。

随机化区间对应 – rad/s,即约 3.18–4.21 Hz;不能沿用旧注释中的频率估计。10 N 恒力在基准刚度下需要 4 cm 平衡位置,已经超出 3 cm 边界,所以此时系统最终行为由饱和机制决定,不能继续按线性平衡点解释。

注意 25 N 限制的是虚拟驱动力。它不是硬件接触力上限。实际峰值还受到接触刚度、惯性、跟踪误差和控制延迟影响;输入力裁剪也只是避免参考积分被异常尖峰破坏,不会让真实接触力消失。

5. 物体交互中的方向柔顺与接触稳定性

双手夹持依赖法向预紧产生摩擦。一个简化对称模型要求:

例如仅作量纲示例, kg、 时,每侧至少需要约 19.62 N 法向力,尚未计入运动加速度和力矩平衡。若每侧只有 12 N,则简单模型最多支持约 1.22 kg。真实抱箱可能还有前臂、胸部支撑,不能用这个例子推定实际箱重或实际成功与否。

Omni 对手腕采用法向柔顺,限制向外张开,并保留向内建立接触的能力。一般阶段向外上限 5 mm,左右向内上限分别为 5、10 mm;承载阶段向外进一步限制到 1 mm。这样做的动机是防止接触尖峰触发过度松手,但代价是更窄的退让空间。

预紧目标为 12 N,带 ±2 N 死区与 EMA 滤波系数 0.25。若更新周期为 ,该滤波的等效时间常数为:

例如 50 Hz 时约 69.5 ms。滤波改善噪声,却可能掩盖快速滑落,因此实现还使用原始力骤降触发快速向内恢复。滤波时间常数应由实际 command 更新周期确认,不能拿渲染 FPS 代入。

承载时,法向力超过 20 N 要持续 0.20 s 才慢速退让,下降到 15 N 以下解除;超过 25 N 可跳过等待。接触丢失还会锁住向外方向,直到恢复阈值满足一定时长。这是带滞回和时间条件的状态机,不能简化成一个连续弹簧。

配置中的拾取、承载、放置窗口采用参考帧号。更换动作速度或裁剪动作后必须重新映射这些窗口,否则预紧可能在箱子还没接触时开启,或者已经放下之后仍继续夹紧。

6. 为什么只裁剪位置会在松手时反弹

半隐式 Euler 的参考更新为:

如果 超出边界后只把位置裁回去,但保留向外速度,虚拟系统仍保存着将参考推离边界的动量。外力撤掉后会出现不符合预期的延迟回归或回弹。

Omni 的边界处理去除相对目标速度中继续向外的径向分量。设 ,触及边界时执行:

向内速度允许参考脱离边界,切向速度不被粗暴清零。这类 anti-windup 处理比单纯减小质量更直接地解决边界储能问题,但并不构成整个学习闭环的被动性证明。

7. FALCON 扩展多了一层 Cartesian IK

这套扩展在原有控制器前加入柔顺参考与关节修正,再通过 teacher、adaptation、finetune 等配置连接学习过程。其整体延迟和可跟踪带宽与直接把关键点参考交给全身策略的方案不同。

实际实验配置覆盖了类默认值:虚拟质量为 0.3 kg,参考速度上限 0.4 m/s,加速度上限 4 m/s²,偏移上限 0.15 m。不能用类默认的 0.1 kg、4 m/s、1000 m/s² 描述运行行为。

此外,主更新循环再次覆盖刚度,使用 ;力阈值范围 3–15 N 对应实际刚度 60–300 N/m。YAML 中的 driving_stiffness: 50 不是这条运行路径的最终刚度。

取阈值 10 N,得到 N/m、 kg、驱动阻尼 15.4919 N·s/m;再加相对速度阻尼 2,静止、未饱和近似下 Hz、。限速限加速度触发后,响应不再服从这个线性二阶模型。

将笛卡尔误差变成关节修正,采用阻尼最小二乘:

配置中的 缓解奇异位形放大,但引入残差。再加姿态项:

这里 是阻尼伪逆,因此第二项不处于严格零空间,通常 。姿态恢复可能干扰主要末端任务,需要通过残差和关节速度检查,而不是把“nullspace”变量名当成数学保证。

该扩展的额外阻尼作用于 ;若错误地作用于绝对速度,会使匀速移动的名义参考受到持续阻力。另一方面,其参考速度裁剪仍作用于当前实现中的速度向量,名义轨迹很快时也会受限。应分别测试静止目标受推和移动目标受推。

FALCON 扩展:先确认参考改变后奖励跟踪的是谁

下表列出 FALCON 受力控制适配中,与上肢柔顺接口直接相关的十项底层环境奖励。上下肢组权重均为 1;每项再乘控制周期,惩罚课程初始为 0.5,只作用于配置名单内的项。下肢速度、站立、足接触等目标继续承担平衡任务。

名称 配置权重 实际定义 作用
tracking_upper_body_dofs +4 分母 0.1 跟踪上肢关节参考
penalty_upper_body_action_rate −0.1 原始动作平方和 抑制输出跳变
penalty_upper_body_torques −0.00001 力矩平方和 降低驱动负担
penalty_upper_body_dof_vel −0.001 速度平方和 限制高速关节运动
penalty_upper_body_dof_acc −0.00000025 速度差除 dt 后平方 限制实际关节加速度
limits_upper_body_dof_pos −5 仿真器软边界 减少位置越界
limits_upper_body_dof_vel −5 每关节越界最多计 1 减少超速
limits_upper_body_torque −0.1 函数内硬编码 0.9 留出力矩余量
penalty_ee_lin_acc −0.1 相邻速度差,未除 dt 减少手部速度跳变
penalty_ee_ang_acc −0.01 相邻角速度差,未除 dt 减少手部转动跳变

逐项实现

tracking_upper_body_dofs

diff_force 实现对上肢关节位置误差平方求和,再除以 upper_body_tracking_sigma,不是再除 sigma²。当前配置关闭该 sigma 的课程。柔顺扩展若更新 ref_upper_dof_pos,相同奖励就会跟踪 IK 后的柔顺关节参考;必须查清 reference 的写入位置。

1
2
error = (q_upper - q_upper_ref).square().sum(-1)
r = torch.exp(-error / 0.1)
penalty_upper_body_action_rate

对上肢动作索引做相邻平方差,属于惩罚课程名单。其对象不是 Cartesian 参考的变化率,参考滤波和动作正则处理的是不同位置的信号。

1
raw = (action_upper - previous_action_upper).square().sum(-1)
penalty_upper_body_torques

同样只选择 upper dof;权重还会乘惩罚课程与 dt。平方力矩不是机械功率,后者至少还需要速度与方向。

1
raw = torque_upper.square().sum(-1)
penalty_upper_body_dof_vel

与动作率不同,它读取实际仿真关节速度,即使动作不变、身体被外力带动也会产生代价。

1
raw = qd_upper.square().sum(-1)
penalty_upper_body_dof_acc

该项确实除以 dt;下面两个末端 acc 项则没有。不能仅根据变量名把它们写成相同量纲。

1
raw = ((qd_upper - qd_upper_previous) / dt).square().sum(-1)
limits_upper_body_dof_pos

从模拟器加载的上肢上下界计算线性越界量。权重属于惩罚课程;修改 YAML 的 soft limit 时仍需确认模拟器初始化如何生成最终边界。

1
2
raw = ((q_lower_soft - q_upper).clamp_min(0)
+ (q_upper - q_upper_soft).clamp_min(0)).sum(-1)
limits_upper_body_dof_vel

该函数直接比较 simulator.dof_vel_limits,没有在函数内再次乘 YAML 的 0.95。不要重复收缩边界;确认 simulator 提供的是哪一级限制。

1
raw = (qd_upper.abs() - simulator_velocity_limits).clamp(0, 1).sum(-1)
limits_upper_body_torque

源码直接使用 0.9×torque_limits;并没有读取此项对应的 0.95 YAML 值。这是需要保留的实际代码与配置差异,不能只按配置表推算。

1
raw = (torque_upper.abs() - 0.9 * torque_limits_upper).clamp_min(0).sum(-1)
penalty_ee_lin_acc

实际计算两手线速度增量的范数之和。虽然函数名含 acc,它的单位仍是 m/s;换控制周期后不能维持同一权重就声称保持同样的加速度代价。这项不在惩罚课程名单。

1
raw = (hand_v - hand_v_previous).norm(dim=-1).sum(-1)
penalty_ee_ang_acc

与线速度项同理,对两手角速度增量求范数后相加。它也不在当前惩罚课程名单。

1
raw = (hand_omega - hand_omega_previous).norm(dim=-1).sum(-1)

这套基础奖励表没有上述 Omni 物体交互案例中的 12 N 法向预紧项,也没有 Gentle 的 force_target_tracking 同名项。接入柔顺参考的第一步是让上肢关节跟踪目标确实来自导纳+IK,并保持观测与奖励引用一致;是否再训练新的力代价,需要单独指定实验。教师训练、观测适应和微调各自优化不同的对象,应分别报告它们带来的改进。

Reference teacher 实际训练的是重建损失

必须把上面的底层环境奖励与教师训练分开。ComplianceReferenceTeacher 冻结 FALCON,使用特权观测编码 latent,再解码柔顺位移,经过 IK 喂给冻结的控制器。其配置保留 clip/GAE 等字段是为了复用原训练基础设施;实际 _training_step 只反传位移重建和 latent 正则,没有对 FALCON 参数做 PPO 更新。

名称 系数/权重 作用
reference_displacement_mse 1;点权重 active=1、inactive=1 重建六个关键点的柔顺位移
small_signal_weight 近零 4 倍 → 3 cm 时 1 倍 防止小幅柔顺被大动作样本淹没
latent_l2 0.00001 约束教师 latent 尺度

逐项实现

reference_displacement_mse

ComplianceReferenceTeacher._training_step 对 decoded 与 target 的六点三维误差平方做加权平均。没有施力的一侧目标是零位移,仍与激活一侧同权,防止解码噪声泄漏到另一条手臂的 IK。归一化分母是权重总和乘 3;这项用于更新 encoder/decoder,不是给底层机器人 actor 的每步 reward。

1
2
squared = (decoded.reshape(-1, 6, 3) - target.reshape(-1, 6, 3)).square()
loss_reconstruction = (squared * weights).sum() / (weights.sum() * 3).clamp_min(1)
small_signal_weight

按每条手臂目标中腕部位移的范数构造连续权重,再复制到该臂肩、肘、腕三点。它是重建误差的相对权重,不是额外一项可简单相加的环境回报;分母也包含该权重,所以全批统一放大时不会把平均 MSE 放大四倍。

1
2
3
wrist_norm = target.reshape(-1, 2, 3, 3)[:, :, 2].norm(dim=-1)
arm_weight = 1 + 3 * (1 - wrist_norm / 0.03).clamp(0, 1)
weights = arm_weight.repeat_interleave(3, dim=1).unsqueeze(-1)
latent_l2

教师 latent 总维度 64,左右臂各 32;对所有 latent 元素取平方均值。decoder 输出用 0.15×tanh 限制各坐标位移,这与虚拟参考的速度/加速度限制是不同层面的约束。

1
2
loss = loss_reconstruction + 1e-5 * latent.square().mean()
displacement = 0.15 * torch.tanh(decoder_output)

教师优化器学习率 3×10⁻⁴、weight decay 10⁻⁵,梯度裁剪 1;这又是优化器设置,不是环境奖励。端到端评估应执行 encoder → decoder → IK → 冻结控制器。当前 teacher 的评估配置明确关闭普通 actor-only ONNX 导出,因为单独导出 actor 无法包含环境侧 IK。要声称部署等价,必须把参考解码与 IK 的执行契约一并保存。

8. 重定向怎样与柔顺衔接

离线重定向应先确保可达性、足底支撑、手物接触位置与手臂几何关系合理。在线柔顺只能在允许的空间内修改参考,不能负责补救严重穿透、不可能达到的手距或错误脚步。

可采用三个明确层次:名义参考 表达任务意图;接触方向与允许偏移集合 表达交互约束;导纳积分给出候选 ,再投影到允许集合。投影时同步处理速度状态,防止边界储能。

离线把重定向权重调小,并不等于在线柔顺。前者没有实时外力输入;后者需要感知接触并随时间更新。若部署没有力传感器,应明确使用什么估计器或学习隐变量,以及训练是否覆盖它的延迟和误差。

实现补充:普通交互与柔顺交互的奖励差在哪里

下表比较基于 Omni 的普通物体交互与柔顺交互,列出全部奖励及其差异,数值对应本节的箱体夹持与承载案例。“—”表示普通交互没有这一项,不是权重未知。所有数值都是配置权重;Holosoma RewardManager 再乘控制周期 dt,窗口、接触条件和 ramp 则在项内部生效。代码块提炼了真实计算顺序,省略环境访问及批量索引。

名称 普通交互 柔顺交互 参数/门控 作用
motion_global_ref_position_error_exp 0.5 0.5 std = 0.3 m 限制 anchor 全局漂移
motion_global_ref_orientation_error_exp 0.5 0.5 std = 0.4 rad 跟住 anchor 朝向
motion_relative_body_position_error_exp 1 1 std = 0.3 m 保留身体相对几何
motion_relative_body_orientation_error_exp 1 1 std = 0.4 rad 保留各身体姿态
motion_global_body_lin_vel 1 1 std = 1 m/s 匹配平移速度
motion_global_body_ang_vel 1 1 std = 3.14 rad/s 匹配转动速度
action_rate_l2 −0.1 −0.15 原始动作平方和 抑制动作抖动
limits_dof_pos −1 −1 软限位越界量,rad 远离关节限位
undesired_contacts −0.1 −0.1 阈值 1 N 减少不允许的身体碰撞
object_global_ref_position_error_exp 1 3 σ = 0.3 m 跟踪被交互物体的位置目标
object_global_ref_orientation_error_exp 1 2 σ = 0.4 rad 限制箱子倾斜
ankle_pos — 1 σ = 0.12 m 避免脚部被全身均值稀释
ankle_ori — 0.5 σ = 0.25 rad 保持足部落地朝向
base_ori — 0.5 σ = 0.30 rad 减少承载时骨盆倾斜
feet_slip — −0.1 接触 >10 N;速度平方截至 4 抑制支撑脚滑动
arm_leg_clearance — −0.2 最小 0.19 m;参考余量 0.03 m 减少放箱时手臂撞腿
wrist_roll_pos — 1.5 → 稳态承载 0.3 σ = 0.12 m;保留比例 0.2 保留夹持几何锚点
wrist_roll_ori — 1 σ = 0.25 rad 保持手腕朝向
wrist_pickup_height — −0.75 允许下沉 5 mm;尺度 2 cm 避免拾取时手碰地
wrist_ground_contact — −1 向上力阈值 2 N;尺度 20 N 区分触地与水平夹持
compliance_ref_vel — 0.5 σ = 1 m/s 跟踪退让参考的速度
wrist_box_tangential — 1.5 σ = 0.06 m 限制沿箱面滑移
wrist_box_slip_velocity — −0.75 容忍 0.01 m/s;尺度 0.05 m/s 在位置明显滑落前惩罚
wrist_grasp_opening — −1 间距余量 2 mm;张开速度阈值 0.02 m/s 惩罚双手提前松开
wrist_normal_force — 1 目标 12 N;σ = 8 N;平衡占 0.4 建立双侧预紧
wrist_min_force — −0.5 滤波后最弱侧至少 8 N 抑制持续单侧失去接触
wrist_fast_contact_loss — −1.5 原始力 10 N;骤降阈值 100 N/s 捕捉短暂双侧脱离
compliance_force_penalty — −0.02 每链阈值 15 N;峰值截至 30 N 限制柔顺部位过度用力
arm_contact_force_penalty — −0.02 总量阈值 25 N;逐身体截至 150 N 避免把挤压力转移给别的链

逐项实现

motion_global_ref_position_error_exp

motion_global_ref_position_error_exp 对 anchor 三轴位置差取平方和,再做指数核。权重 0.5 控制该项的贡献,0.3 m 控制容忍尺度。误差 0.3 m 时原始值约 0.3679;它不能保证机器人永不漂移。

1
2
err2 = (p_anchor_ref - p_anchor).square().sum(-1)
r = torch.exp(-err2 / 0.3**2)
motion_global_ref_orientation_error_exp

motion_global_ref_orientation_error_exp 使用四元数的最短旋转角误差,先平方,再除以 0.4²。不要将四个四元数分量直接相减:q 和 −q 表示同一旋转。

1
2
angle = quat_error_magnitude(q_ref, q_actual)
r = torch.exp(-angle.square() / 0.4**2)
motion_relative_body_position_error_exp

motion_relative_body_position_error_exp 比较经过 anchor/yaw 对齐的参考身体位置与实际位置:先对 xyz 求平方和,再对身体取均值,最后求一次 exp。它不是逐身体 exp 后求平均。身体列表改变后,每个部位在均值中的占比也会改变。 柔顺开启且参考状态存在时,目标切换为 body_pos_compliance_w;其余身体仍使用原来的相对参考。权重不变,却改变了策略需要追踪的对象。

1
2
err2 = (p_body_aligned - p_body).square().sum(-1)
r = torch.exp(-err2.mean(-1) / 0.3**2)
motion_relative_body_orientation_error_exp

motion_relative_body_orientation_error_exp 对每个身体计算最短旋转角,平方后在身体维度平均,再用 0.4 rad 核。相对目标的构造与位置项共享参考约定,不能把局部和世界四元数混用。

1
2
angle = quat_error_magnitude(q_body_aligned, q_body)
r = torch.exp(-angle.square().mean(-1) / 0.4**2)
motion_global_body_lin_vel

motion_global_body_lin_vel 比较世界系身体线速度,三轴平方和后对身体平均;1 m/s 是误差尺度。位置很接近但身体仍在快速冲过目标时,这项会降低奖励。

1
2
err2 = (v_ref_w - v_w).square().sum(-1)
r = torch.exp(-err2.mean(-1) / 1.0**2)
motion_global_body_ang_vel

motion_global_body_ang_vel 比较世界系身体角速度。3.14 rad/s 是指数核尺度,不是机器人最大允许角速度。它补充姿态项,但不能替代力矩限制。

1
2
err2 = (omega_ref_w - omega_w).square().sum(-1)
r = torch.exp(-err2.mean(-1) / 3.14**2)
action_rate_l2

Holosoma 的 action_rate_l2 返回连续两次动作之差的平方和,配置乘负权重。它没有除以控制周期,因此不是物理意义上的关节加速度。动作幅度和控制频率变化后,同一系数的效果也会变。

1
cost = (action - previous_action).square().sum(-1)
limits_dof_pos

普通交互与柔顺交互都将原 G1 的 −10 改成 −1,软范围比例从 0.9 改成 0.98。该项读取奖励自己的 params,单改 RobotConfig 的同名字段并不能改变这里的边界。实际计算是线性越界量求和,不是平方,也不是硬约束。

1
2
cost = ((lower_soft - q).clamp_min(0)
+ (q - upper_soft).clamp_min(0)).sum(-1)
undesired_contacts

Holosoma 的 undesired_contacts 先在接触历史窗取每个身体的力范数峰值,超过 1 N 的身体记为 1,再求和。脚和允许接触的部位必须从筛选集合排除;阈值判断意味着超过 1 N 与超过 100 N 对同一个身体贡献一样。 该机器人明确允许脚踝 roll、手腕 roll 与 hand_contact 接触。手腕链末端与 G1 不同;继续排除 wrist_yaw 会把正常夹箱误判为不期望接触。

1
2
peak = contact_forces_history.norm(dim=-1).amax(dim=1)
cost = (peak[:, forbidden_body_ids] > 1.0).sum(-1)
object_global_ref_position_error_exp

普通交互物体位置权重 1,柔顺交互增加到 3。核函数仍比较物体世界位置,和机器人身体的 yaw 对齐误差不是同一坐标定义。增加权重提高任务重要性,不改变 0.3 m 的误差容忍尺度。

1
r = torch.exp(-(p_box_ref - p_box).square().sum(-1) / 0.3**2)
object_global_ref_orientation_error_exp

普通交互为 1,柔顺交互为 2。使用箱体四元数最短旋转角,不能仅看箱子中心位置判断搬运完成;同一位置仍可能出现明显倾斜或滚转。

1
r = torch.exp(-quat_error_magnitude(q_box_ref, q_box).square() / 0.4**2)
ankle_pos

MotionBodyPositionTrackingFiltered 只选左右脚踝,三轴平方和后在两脚平均。相较全身位置项,它为脚部建立独立梯度;并不是给全身每个身体增加 1。

1
2
err2 = (p_ankle_target - p_ankle).square().sum(-1)
r = torch.exp(-err2.mean(-1) / 0.12**2)
ankle_ori

MotionBodyOrientationTrackingFiltered 选择左右脚踝,计算旋转角误差的平方均值。位置正确仍可能脚尖着地,独立姿态项就是处理这种误差。

1
2
angle = quat_error_magnitude(q_ankle_ref, q_ankle)
r = torch.exp(-angle.square().mean(-1) / 0.25**2)
base_ori

仅筛选 base_link,补充以腰部为 anchor 的姿态项。腰部姿态接近参考,不保证骨盆也接近,因此两项不等价。

1
r = torch.exp(-quat_error_magnitude(q_base_ref, q_base).square() / 0.30**2)
feet_slip

FeetSlipPenalty 在最新物理样本的竖直力绝对值超过 10 N 时惩罚脚的水平速度平方;摆动脚没有这项惩罚。它不会代替脚部位置跟踪,反而要避免把自然摆腿当成滑脚。

1
2
3
contact_mask = latest_ankle_force_z.abs() > 10.0
speed2 = ankle_velocity[..., :2].square().sum(-1).clamp_max(4.0)
cost = (speed2 * contact_mask).sum(-1)
arm_leg_clearance

ArmKneeClearancePenalty 对每侧手臂与腿部原点组合取最近距离。阈值是 max(参考最近距离−0.03, 0.19),不是完整网格间距;将不足量除 0.05、截至 1 后平方,两侧相加。窗口 505–755 帧、10 帧 smoothstep,不能替代通用自碰撞检测。

1
2
threshold = torch.maximum(reference_distance - 0.03, reference_distance.new_tensor(0.19))
cost = envelope * ((threshold - actual_distance).clamp_min(0) / 0.05).clamp_max(1).square().sum(-1)
wrist_roll_pos

MotionBodyPositionTrackingFiltered 明确使用柔顺目标。134–557 帧内以 10 帧 ramp 将原始 reward 乘到 0.2,因此表中的 0.3=1.5×0.2,不是另外一项。完全取消位置奖励会让部署 actor 缺少几何约束,只能在滑落后反应。

1
2
r_base = torch.exp(-(x_compliant - x_wrist).square().sum(-1).mean(-1) / 0.12**2)
r = r_base * (1.0 - 0.8 * envelope)
wrist_roll_ori

位置可以柔顺退让,手腕朝向仍追踪原有相对姿态。该配置并没有对每个旋转自由度做力矩驱动的柔顺参考,不能把位置导纳说成完整 6D 阻抗。

1
2
angle = quat_error_magnitude(q_wrist_ref, q_wrist)
r = torch.exp(-angle.square().mean(-1) / 0.25**2)
wrist_pickup_height

90–177 帧有效。用名义参考腕高减实际腕高,扣除 5 mm 容忍量;除以 2 cm 并截至 1 后平方,取两腕较大值。比较的是 body 原点高度,不能直接视为手指网格的实际离地距离。

1
2
d = ((z_ref - z_wrist - 0.005).clamp_min(0) / 0.02).clamp_max(1)
cost = active * d.square().amax(-1)
wrist_ground_contact

90–177 帧有效。取近期世界 Z 向力最大值而不是力范数,再归一化并平方,取两腕最大值;这样不会直接惩罚期望的水平夹紧力。但其他接触也可能产生向上分量,所以它是当前任务的触地代理。

1
2
fz = wrist_force_history[..., 2].amax(dim=1)
cost = active * ((fz - 2).clamp_min(0) / 20).clamp_max(1).square().amax(-1)
compliance_ref_vel

ComplianceReferenceVelocityTracking 比较柔顺链的实际身体速度与虚拟参考速度。只跟踪位置会容许高速追赶后刚好经过目标,速度项提供额外瞬态约束;柔顺关闭或状态不存在时返回 0。

1
2
err2 = (v_compliant - v_body).square().sum(-1)
r = torch.exp(-err2.mean(-1) / 1.0**2)
wrist_box_tangential

114–557 帧有效。把腕相对箱体的位置转进各自箱体坐标,移除法向误差,保留切向误差;用参考的水平箱心—腕方向近似表面法向,退化时使用 +Y 备用方向。它不是碰撞网格返回的精确表面法线,适用性依赖当前箱体与抓握几何。

1
2
3
delta = offset_box_actual - offset_box_ref
tangent = delta - (delta * normal_ref).sum(-1, keepdim=True) * normal_ref
r = active * torch.exp(-tangent.square().sum(-1).mean(-1) / 0.06**2)
wrist_box_slip_velocity

155–507 帧有效。物体接触点速度包含 v_box + omega_box × offset,减腕速度后转到箱体系,再去法向。与演示中的切向相对速度比较,而不是要求演示里也完全无滑动;归一化平方后取两腕最大值。

1
2
3
4
v_point = v_box[:, None] + torch.cross(omega_box[:, None].expand_as(offset), offset, dim=-1)
# 转到箱体系并去除法向后,与参考同类量比较
speed_error = (v_tangent_actual - v_tangent_ref).norm(dim=-1)
cost = active * ((speed_error - 0.01).clamp_min(0) / 0.05).clamp_max(1).square().amax(-1)
wrist_grasp_opening

147–507 帧有效。比较双腕水平间距与参考间距;同时惩罚沿间距轴的正向分离速度。位置尺度 0.02 m、速度尺度 0.10 m/s,速度项内部系数 0.5,均截至 1 后平方。向内恢复不受罚。

1
2
3
p = ((gap - gap_ref - 0.002).clamp_min(0) / 0.02).clamp_max(1)
v = ((opening_speed - 0.02).clamp_min(0) / 0.10).clamp_max(1)
cost = active * (p.square() + 0.5 * v.square())
wrist_normal_force

125–557 帧、23 帧 smoothstep;目标随包络上升。WristNormalForceTracking 对各腕先计算高斯核,再减掉零接触时的分数并重新归一化,防止没有接触也拿到可观奖励。60% 来自逐腕独立分数,40% 来自双侧平衡且有接触的分数;不是要求两侧同时接触才有任何奖励。

1
2
3
4
5
6
7
target = 12.0 * envelope
zero = torch.exp(-(target / 8.0).square())
g = torch.exp(-((force - target[:, None]) / 8.0).square())
score = ((g - zero[:, None]) / (1 - zero[:, None]).clamp_min(1e-6)).clamp(0, 1)
balance = torch.exp(-((force[:, 0] - force[:, 1]) / 8.0).square())
contact_gate = (force.amin(-1) / target.clamp_min(1e-6)).clamp(0, 1)
r = envelope * (0.6 * score.mean(-1) + 0.4 * balance * contact_gate)
wrist_min_force

125–557 帧、23 帧 ramp。读取 command 的 EMA 法向力,最弱侧低于随包络变化的目标时,将不足量除以固定 8 N 再平方。它减少单帧尖峰误报,代价是可能漏掉很短的脱离。

1
2
minimum = 8.0 * envelope
cost = ((minimum - filtered_force.amin(-1)).clamp_min(0) / 8.0).square()
wrist_fast_contact_loss

155–507 帧有效。它使用未经过 EMA 的法向力和下降速率:最弱侧不足平方+0.25×超速下降平方+双侧不足乘积的平方。内部每个归一化误差截到 1。两侧完全失联与单侧失联因而不再获得相同惩罚。

1
2
3
4
deficit = ((10.0 - raw_force).clamp_min(0) / 10.0).clamp_max(1)
drop = ((drop_rate.amax(-1) - 100.0).clamp_min(0) / 100.0).clamp_max(1)
cost = active * (deficit.amax(-1).square() + 0.25 * drop.square()
+ (deficit[:, 0] * deficit[:, 1]).square())
compliance_force_penalty

对每个柔顺身体取近期力范数最大值,截到 30 N,超过 15 N 的部分按身体求和。这是逐身体阈值,且先截峰再减阈值;不能说它把真实力限制在 15 N。

1
2
peak = compliance_force_history.norm(dim=-1).amax(dim=1).clamp_max(30)
cost = (peak - 15).clamp_min(0).sum(-1)
arm_contact_force_penalty

选择肩、肘、腕、手与 base_link,每个身体先取近期峰值并截到 150 N,再求和后扣 25 N。它覆盖范围更广,能减少策略绕过少数柔顺身体的力惩罚;不同身体的峰值可能发生在不同物理子步,所以这不是同一时刻净合力。

1
2
peak = selected_force_history.norm(dim=-1).amax(dim=1).clamp_max(150)
cost = (peak.sum(-1) - 25).clamp_min(0)

用一次短暂松手检查奖励是否表达了任务

在承载稳态、两腕原始法向力同时变成 0、下降速率超过 200 N/s 时,fast-contact-loss 原始代价达到 1+0.25+1=2.25;乘 −1.5,再乘 0.02 s,单步贡献为 −0.0675。若只有一腕失联、其余条件相同,双侧乘积项为 0,单步为 −0.0375。这个差值才是新增双侧项实际表达的偏好。

但其他奖励仍可抵消这项惩罚。因此评估应同时画原始力、EMA 力、腕间距、箱体高度及各项加权贡献;只看到总 reward 上升,无法判断它是否学会“拿稳”。窗口帧号依赖这段动作;换片段必须重标,不能直接照抄 155–507。

哪些来自原方法,哪些是交互适配

普通交互保留运动/物体跟踪和正则。机器人适配先修正手腕末端接触名单,并放宽限位奖励的软区间。柔顺交互再增加虚拟参考、法向偏移边界、预紧及失联状态机;奖励侧增加独立手脚项、切向位置/速度、腕间距和两种时间尺度的力反馈。它们是上述物体交互案例的设计,不是 OmniRetarget 论文原图中“最小跟踪奖励”的逐项复现。

GentleHumanoid 提供受力改变目标的思路,但双手夹箱必须额外保证摩擦与支撑。FALCON 扩展则增加 Cartesian IK,把柔顺目标重新映射到关节空间。三者共享“可变参考”的思想,不能据此假定它们的力反馈位置、奖励核、actor 观测或部署条件完全相同。

9. 实验必须同时测“让得开”和“拿得住”

比较刚性跟踪、只加导纳、加入方向约束与预紧的版本时,应固定动作、箱重、摩擦、初始接触和外力时序。至少记录接触力峰值及 95 分位、超阈值持续时间、接触冲量、箱子滑移、掉落率、轨迹误差和外力撤除后的回归时间。

净接触力向量的范数可能因为多接触方向相消而较小;若目标是限制局部压力,不能只记录整条手臂的合力。应同时观察具体接触点或接触区域的法向力。

上述数值用于解释参考模型与交互适配。尚未在统一协议下测得接触力降低幅度或成功率变化,不据此声称性能提升。

当力峰值下降时,还要确认下降是否来自任务真正更柔顺,还是来自手臂不再碰箱子。成功率、接触力和任务误差必须一起报告,才能判断这个柔顺控制器有没有解决原问题。