按你的四步框架,把修正和两个问题的答案都揉进去: #


1. 法向规则 #

我们定义了一套法向力的规则,法向力跟穿透和靠近速度有关(Kelvin–Voigt:弹簧加阻尼,隐式地用步末的穿透),本质上是一根弹簧。整理之后是:

\[\gamma_n = \frac{\hat v_n - v_n}{R_n}\]

$\hat v_n = -\phi_0/(h+\tau)$ 是法向力为 0 时的零点,它是一个门槛,不是一个状态:

  • 已经穿透时,$\hat v_n > 0$:物体必须以这个速度往外退,力才为 0;
  • 还有间隙时,$\hat v_n < 0$:物体只要靠近得不比这个速度快,就没有力。

$v_n < \hat v_n$ 时有推力;$v_n \ge \hat v_n$ 时没有力。SAP 里的”分离”指的是后者,也就是”这一步没有法向力”,不一定是物体在远离。

2. 理想的切向规则 #

理想情况下,摩擦力有三种情况:

  • 分离:没有法向力,也就没有摩擦力;
  • 滑动:摩擦力 $= \mu F_n$,方向与滑移相反;
  • 粘滞:$v_t = 0$,摩擦力 $\le \mu F_n$。

所以理想情况下,摩擦力本身就像一个 projection 操作:$F_n$ 决定上界,摩擦力被限制在这个上界以内。

难点在于粘滞:这时摩擦力是一个约束力,”需要多少就给多少”,由整个系统决定,不是速度的函数。一个速度($v_t = 0$)对应无数个可能的力,没法写成规则,也就没法优化。

3. SAP 的切向规则:用一点点滑动换来静摩擦 #

SAP 的做法是:$\gamma_t = -v_t/R_t$,$v_t$ 是相对滑动速度。通过允许一点点相对滑动,让静摩擦力”需要多少就给多少”变成由速度唯一确定。这和法向用一点点穿透换来弹簧规则是同一个套路。$R_t = \sigma w$,滑动量大约是”没有摩擦时会滑的速度”的 $\sigma$ 倍。

这样做还有一个好处:切向规则的形式和法向一样(切向取 $\hat v_t = 0$),可以统一写成

\[y = R^{-1}(\hat v - v_c)\]

$y$ 就是投影前的冲量。然后用 $R$ 范数把 $y$ 投影到摩擦锥上,得到真正的冲量 $\gamma$。在锥里就是粘滞,被截到锥面上就是滑动,被截到锥尖就是分离。

4. 为了能优化:要对称,所以联合投影 #

如果法向和切向分开投影(先算 $F_n$,再把摩擦截到 $\mu F_n$),会发现 Jacobian $\partial\gamma/\partial v$ 不对称:滑动时摩擦上限依赖 $v_n$,但法向不依赖 $v_t$。不对称就写不成”某个凸势能的梯度”,也就没法优化。

所以 SAP 把 $y$ 整个一起在 $R$ 范数下投影到三维锥上。这样一来,法向自动获得了对切向速度的耦合:滑动时,法向冲量相当于把 $v_n$ 换成了 $v_n - \muv_t$,而且强度正好和正向耦合相等。用 $R$ 范数,就是为了让两边配平。

这种耦合只在滑动时出现,因为只有滑动时摩擦被上界卡住,才依赖法向。粘滞时摩擦没达到上界,和法向无关,正向耦合为 0,反向耦合也必须为 0。分离时两者都是 0。所以耦合不是三种情况都要加,而是哪里有正向耦合,哪里才需要反向耦合。

代价是 gliding 伪影:滑动时物体会被多推出约 $\muv_t(h+\tau)$,悬在表面上方滑行。

5. 补一句:ICF / Lagged #

“能优化”的精确条件是:冲量场 $\gamma(v_c)$ 无旋(Jacobian 对称)并且单调(势能是凸的)。SAP 是通过”两边都耦合“来满足对称性。Lagged 则是”两边都不耦合“:把摩擦上界冻结成步初算好的 $\mu n_0$,法向和切向完全分开,因此不需要联合投影,也没有 gliding 伪影。代价是摩擦上界滞后一步。

gliding artifacts,到底是允许一点点相对滑动引入的,还是这个耦合引入的 #

是耦合引入的,和”允许一点点相对滑动”无关。有三个证据。

证据 1:伪影的大小和 $R_t$ 无关 #

gliding 那一项是:

\[\hat\mu\,y_r = \mu\frac{R_t}{R_n}\cdot\frac{\|v_t\|}{R_t} = \frac{\mu\|v_t\|}{R_n}\]

$R_t$(也就是 $\sigma$)被约掉了。把 $\sigma$ 调大或调小,蠕滑会变,但 gliding 不变。即使让 $\sigma \to 0$(完全不允许滑动),它仍然存在。没有正则化的刚体 Anitescu 凸近似,同样有这个伪影。

证据 2:它只在滑动时出现,而滑动时正则化根本不起作用 #

滑动时 $\gamma_t = -\mu\gamma_n\hat v_t$,和 $R_t$ 无关,正则化在这里已经”失效”了。”允许一点点滑动”只在粘滞时起作用,而粘滞时 $\gamma = y$,没有任何耦合,也就没有 gliding。

证据 3:Lagged 有同样的正则化,却没有 gliding #

Lagged 的摩擦在原点处的刚度也是 $1/(\sigma w)$,”允许一点点滑动”的程度和 SAP 完全相同。但它把摩擦上界冻结成了 $\mu n_0$,没有联合投影,也就没有反向耦合,因此没有 gliding。

两个伪影各管各的 #

 来源什么时候出现大小SAPLagged  
蠕滑切向正则化(允许一点点滑动)粘滞时约为”没有摩擦时会滑的速度”的 $\sigma$ 倍有有  
gliding联合投影带来的反向耦合滑动时多推出约 $\muv_t(h+\tau)$有无

需要澄清的一点是:之前说”正则化让切向和法向形式统一,所以可以用 $R$ 范数联合投影”。这说的是正则化让联合投影写得出来,但 gliding 不是正则化造成的。真正造成 gliding 的,是”为了对称而让法向依赖 $v_t$”这个选择本身。

最核心最核心的一定要让摩擦力和切向速度联系在一起的原因是啥 #

最核心的原因只有一个:SAP 选择了只把速度当作未知量。

一句话 #

SAP 把一个时间步写成:

\[\min_v\ \tfrac12\|v - v^*\|_M^2 + \sum_i \ell_i(J_i v)\]

未知量只有 $v$。力不是未知量,而是 $v$ 的函数 $\gamma(v_c)$。既然力必须由速度算出来,摩擦力也就必须是切向速度的函数。

为什么理想的静摩擦做不到这一点 #

理想静摩擦是:$v_t = 0$,摩擦力可以是 $[-\mu F_n, \mu F_n]$ 中的任意值。

在 $v_t = 0$ 这一点上,一个速度对应无数个力。它不是函数,所以:

  • 给定速度 $v$,算不出唯一的 $\gamma$,Newton 法的每一步都没法计算;
  • 也写不出光滑的势能 $\ell$,因为 $\ell$ 在那里有尖角,没有 Hessian。

用 $\gamma_t = -v_t/R_t$ 代替它,把”一个点对应一整段力”换成”一条很陡的直线”,就变成了函数。

不这样做的话,替代方案是什么 #

替代方案是把力也当成未知量,把静摩擦写成约束:$v_t = 0$,并且 $\gamma_t\le \mu\gamma_n$。传统的 LCP、NCP、PGS,以及各种锥规划方法都是这么做的。

代价是:

  • 变成带约束的问题,要么不光滑,要么需要 active set、内点法这类更复杂的方法;
  • 刚性静摩擦的解可能不唯一(比如四条腿的桌子,每条腿分担多少摩擦是不确定的)。

SAP 的取舍是:接受一点点蠕滑,换来一个只关于速度的、无约束、光滑、严格凸的问题,可以直接用 Newton 法求解,而且解唯一。

所以”摩擦力必须和切向速度联系起来”不是物理上的要求,而是”只解速度“这个求解方式上的要求。法向也是一样:用弹簧代替刚性的”不穿透”约束,同样是为了让法向力成为速度的函数。

primal和dual优化指的是什么? #

这两个词说的是选哪个量作为未知量:

  • Primal(原问题):未知量是速度 $v$;
  • Dual(对偶问题):未知量是冲量 $\gamma$。

两者描述的是同一个物理问题,最优解对应同一个状态,只是从两个方向去解。

Primal:解速度(SAP 的做法) #

\[\min_v\ \tfrac12(v - v^*)^\top M(v - v^*) + \sum_i \ell_i(J_i v)\]
  • 未知量的个数 = 自由度数;
  • 没有约束。摩擦锥藏在 $\gamma(v_c)$ 这个函数里,通过投影来处理;
  • 冲量是速度的函数,所以静摩擦必须正则化成速度的函数(上一个问题的答案);
  • Newton 法的矩阵是 $M + \sum_i J_i^\top G_i J_i$。它的稀疏结构和 $M$ 一样,沿运动学树分布。

Dual:解冲量 #

从动量方程把速度消掉:$v = v^* + M^{-1}J^\top\gamma$,所以接触速度是:

\[v_c = \underbrace{Jv^*}_{v_c^*} + \underbrace{JM^{-1}J^\top}_{W}\,\gamma\]

Delassus 算子 $W$ 在这里登场了。代入后,问题变成:

\[\min_{\gamma\in\mathcal F}\ \tfrac12\gamma^\top(W + R)\,\gamma + \gamma^\top(v_c^* - \hat v)\]
  • 未知量的个数 = 3 × 接触数;
  • 有约束:$\gamma$ 必须在摩擦锥里;
  • 冲量本身就是未知量,静摩擦可以直接当约束处理,原则上不需要正则化。但加上 $R$ 可以保证 $W + R$ 正定,从而解唯一。否则接触有冗余时(比如四条腿的桌子),$W$ 是奇异的,冲量不唯一;
  • 矩阵 $W + R$ 需要 $M^{-1}$,而且只要两个接触在同一个物体或同一条链上,它们之间就有耦合,所以通常比较稠密。

可以验证:对这个 dual 问题写出最优性条件,得到的正是”$\gamma$ 是 $y = R^{-1}(\hat v - v_c)$ 在 $R$ 范数下到 $\mathcal F$ 的投影”,也就是 SAP 的投影规则。两个问题互为 Fenchel 对偶,正则化 $R$ 在两边是同一个东西。

对比 #

 Primal(SAP)Dual
未知量速度 $v$冲量 $\gamma$
规模自由度数3 × 接触数
约束无$\gamma \in \mathcal F$
矩阵$M + J^\top GJ$,稀疏,跟树结构一致$W + R = JM^{-1}J^\top + R$,往往稠密
典型解法Newton + line search,收敛快PGS(逐个接触投影)、锥规划、内点法
优点无约束,收敛快,有全局收敛保证接触少、自由度多时规模小;PGS 实现简单
缺点规模随自由度增长;需要正则化静摩擦有约束;PGS 在质量比大时收敛很慢

和你在对齐的 MuJoCo 的关系 #

MuJoCo 两种都有:Newton 和 CG 求解器在 primal 空间(加速度)里工作,PGS 在 dual 空间(约束力)里工作。它也有正则化 $R$,作用和 SAP 的 $R$ 一样。SAP 和 MuJoCo 默认的 Newton 求解器都是 primal 的,所以它们的结构很像。这也是我们能把刚体场景对齐到 MuJoCo Warp 的原因之一。

法向力模型 #

法向力用线性 Kelvin–Voigt 模型,并且取步末的穿透量:

\[\phi(v_n) \approx \phi_0 + h\,v_n,\qquad f_n = -k\,(\phi + \tau v_n) = -k\big(\phi_0 + (h+\tau)v_n\big)\]

我现在有点迷糊,我们一点点来,线性 Kelvin–Voigt 模型是啥

Kelvin–Voigt 模型是什么 #

它就是一根弹簧和一个阻尼器并联:

      ┌──/\/\/\/──┐   弹簧 k
  ────┤           ├────
      └───[ | ]───┘   阻尼 c

两个元件的伸缩量相同,所以力直接相加:

\[f = k\,\delta + c\,\dot\delta\]

其中 $\delta$ 是压缩量。弹簧项和压缩量成正比,阻尼项和压缩速度成正比。”线性”指的是两项都是一次的。Drake 里还有非线性的 Hunt–Crossley 模型,那是另一回事。

习惯上会把阻尼写成 $c = k\tau$:

\[f = k\,(\delta + \tau\,\dot\delta)\]

$\tau = c/k$ 的单位是秒,就是图里的 dissipation time scale。它表示阻尼和弹簧的相对强弱:$\tau = 0$ 是纯弹簧,碰撞后会完全弹回;$\tau$ 越大,能量耗散越多。

法向冲量形式 #

好,接着做下一步:把力变成冲量,再整理成 $R_n^{-1}(\hat v_n - v_n)$ 的形式。

第一步:力乘以 $h$,得到冲量 #

求解器解的是速度,动量方程里用的是冲量(力 × 时间),所以:

\[\gamma_n = h\,f_n = -h k\big(\phi_0 + (h+\tau)\,v_n\big)\]

第二步:把 $(h+\tau)$ 提出来 #

\[\gamma_n = -h k (h+\tau)\Big(\frac{\phi_0}{h+\tau} + v_n\Big) = \underbrace{h k (h+\tau)}_{R_n^{-1}}\Big(\underbrace{-\frac{\phi_0}{h+\tau}}_{\hat v_n} - v_n\Big)\]

这就是:

\[\gamma_n = R_n^{-1}\,(\hat v_n - v_n),\qquad R_n = \frac{1}{h k (h+\tau)},\qquad \hat v_n = -\frac{\phi_0}{h+\tau}\]

为什么是除h+tau,tau这个不是当时法向力里面和速度耦合的吗 #

回到这个式子:

\[f_n = -k\big(\phi_0 + h\,v_n + \tau\,v_n\big)\]

括号里有两项都乘着 $v_n$:

  • $h\,v_n$ 来自隐式离散化:这一步走完,位置变了 $h v_n$;
  • $\tau\,v_n$ 来自阻尼器:速度本身产生的阻尼力。

合起来,$v_n$ 的系数就是 $(h+\tau)$。$\hat v_n$ 的定义是”力为零时的速度”,也就是解方程:

\[\phi_0 + (h+\tau)\,v_n = 0 \;\Rightarrow\; v_n = -\frac{\phi_0}{h+\tau}\]

所以除以 $(h+\tau)$ 并没有引入新的物理,只是求这个线性函数的零点。系数是什么就除以什么。$\tau$ 之所以在分母里,恰恰是因为它和 $v_n$ 耦合。

推出法向力和法向冲量之后,怎么体现摩擦问题优化的? #

第一步:只有法向的一维例子 #

一个质量为 $m$ 的方块落向地面。没有接触力时,它这一步的速度会是 $v^*$。

动量方程:

\[m(v - v^*) = \gamma_n(v)\]

Kelvin–Voigt 推出来的法向冲量(只推不拉,所以有个 $\max$):

\[\gamma_n(v) = \max\big(0,\ R_n^{-1}(\hat v_n - v)\big)\]

这两条联立,就能解出 $v$。现在换个角度,定义一个势能:

\[\ell(v) = \tfrac12 R_n^{-1}\big(\max(0,\ \hat v_n - v)\big)^2 = \tfrac12 R_n\gamma_n^2\]

对它求导,正好是 $\ell’(v) = -\gamma_n(v)$。于是考虑这个优化问题:

\[\min_v\ \underbrace{\tfrac12 m(v - v^*)^2}_{\text{动能项}} + \underbrace{\ell(v)}_{\text{接触势能}}\]

令导数为零:

\[m(v - v^*) - \gamma_n(v) = 0\]

这就是动量方程。 所以”解动量方程”和”求这个函数的最小值”是同一件事。而且这个函数是凸的(两项都是凸的),所以最小值唯一,可以用 Newton 法求。

第二步:加上摩擦,$\max$ 变成了锥投影 #

一维时,”只推不拉”就是一个 $\max(0,\cdot)$。它其实就是把 $y_n$ 投影到集合 ${\gamma_n \ge 0}$ 上。

加上摩擦后,冲量变成三维的,允许的集合从半直线 ${\gamma_n \ge 0}$ 变成了摩擦锥 ${\gamma_t\le \mu\gamma_n}$。
 一维(只有法向)三维(法向 + 摩擦)
试探冲量$y_n = R_n^{-1}(\hat v_n - v_n)$$y = R^{-1}(\hat v - v_c)$
限制$\gamma_n \ge 0$$\gamma \in \mathcal F$(摩擦锥)
怎么得到冲量$\max(0, y_n)$在 $R$ 范数下投影到 $\mathcal F$
势能$\tfrac12 R_n\gamma_n^2$$\tfrac12\gamma^\top R\gamma$
关键性质$\ell’ = -\gamma_n$$\nabla_{v_c}\ell = -\gamma$

锥投影就是 $\max(0,\cdot)$ 的三维版本。 摩擦就是通过这一步进入问题的:它决定了 $\gamma_t$ 怎样被截断,同时也决定了 $\ell$ 的形状。而选 $R$ 范数,就是为了让最后一行的梯度关系在三维时依然成立。

第三步:整个系统 #

多个接触、多个自由度时,接触速度是 $v_{c,i} = J_i v$,问题变成:

\[\min_v\ \tfrac12(v - v^*)^\top M(v - v^*) + \sum_i \ell_i(J_i v)\]

用链式法则求梯度,令其为零:

\[M(v - v^*) - \sum_i J_i^\top\gamma_i = 0\]

这还是动量方程:广义动量的变化等于所有接触冲量(通过 $J^\top$ 搬回广义坐标)之和。

所以有两层”优化” #

  1. 内层(每个接触各自做,有闭式解):给定 $v_c$,在 $R$ 范数下把 $y$ 投影到锥上,得到 $\gamma$。这一步编码了摩擦的物理:粘滞、滑动、分离三种情况。
  2. 外层(全局,用 Newton 法):对整体速度 $v$ 最小化上面的总代价。每次 Newton 迭代都要调用内层来得到 $\gamma_i$ 和它的导数 $G_i = -\partial\gamma_i/\partial v_c$,然后解:
\[\Big(M + \sum_i J_i^\top G_i J_i\Big)\Delta v = -\text{梯度}\]

所以,Kelvin–Voigt 给出的是法向的物理,正则化给出的是切向的物理,锥投影把两者拼在一起并加上 Coulomb 限制。最后,”$\nabla\ell = -\gamma$”这个性质把它们变成了一个可以用 Newton 法求解的凸优化问题。

到底什么是“在 $R$ 范数下投影到 $\mathcal F$” #

我们一个词一个词来,最后用一组具体数字算一遍。

1. “投影”:在集合里找离某个点最近的点 #

给定一个点 $y$ 和一个集合 $\mathcal F$:

  • 如果 $y$ 在 $\mathcal F$ 里,投影就是 $y$ 自己;
  • 如果不在,就在 $\mathcal F$ 里找一个离 $y$ 最近的点。

最简单的例子是投影到半直线 ${\gamma_n \ge 0}$ 上:$y_n = 3$ 就还是 3,$y_n = -2$ 最近的点是 0。结果就是 $\max(0, y_n)$。

2. “$\mathcal F$”:摩擦锥 #

$\mathcal F = {\gamma : |\gamma_t| \le \mu\gamma_n}$,就是所有物理上允许的冲量:法向只能推,摩擦不能超过 $\mu$ 倍法向。为了画图,只看一个切向方向,它就是一个 V 字形区域:

       γ_n
        ↑
   ╲    │    ╱
    ╲ 𝓕 │   ╱      边界:|γ_t| = μ γ_n
     ╲  │  ╱
      ╲ │ ╱
───────╲│╱────────→ γ_t

3. “在 $R$ 范数下”:用什么尺子量”最近” #

“最近”取决于怎么量距离。

欧氏距离:$d^2 = \Delta\gamma_t^2 + \Delta\gamma_n^2$。到 $y$ 等距离的点组成圆。

$R$ 范数:$d^2 = R_t\,\Delta\gamma_t^2 + R_n\,\Delta\gamma_n^2$。到 $y$ 等距离的点组成椭圆。$R_t$ 很小,所以椭圆沿 $\gamma_t$ 方向拉得很长:在切向走很远,距离才增加一点点;在法向稍微动一下,距离就增加很多。

投影的几何做法:以 y 为中心画等距离曲线,慢慢放大,第一次碰到锥的那个点就是投影结果 γ。

  欧氏:圆                        R 范数:扁椭圆
       γ_n                             γ_n
        ↑     ╱                         ↑     ╱
        │    ╱  ●γ                      │    ╱
        │   ╱ ╱  ╲                      │   ╱
        │  ╱ (  ×y )                  ──│●─(─────×y─────)
        │ ╱                             │╱γ
────────┼──────────→ γ_t       ─────────┼──────────→ γ_t
   圆往斜上方碰到锥边                 椭圆横着拉长,几乎水平地碰到锥边
   → γ_n 被抬高很多                    → γ_n 几乎不变,只砍了 γ_t

4. 算一组数字 #

取 $\mu = 0.5$,$R_t = 0.01$,$R_n = 1$,试探冲量 $y = (y_t, y_n) = (4,\ 1)$。检查:$\lvert y_t\rvert = 4 > \mu y_n = 0.5$,在锥外面,需要投影。

欧氏投影:

\[\gamma_n = \frac{y_n + \mu|y_t|}{1+\mu^2} = \frac{1 + 2}{1.25} = 2.4,\qquad \gamma_t = 1.2\]

法向冲量从 1 变成了 2.4。只因为物体在滑,法向力就翻了一倍多,物理上说不通。

$R$ 范数投影($\tilde\mu = \mu R_t/R_n = 0.005$):

\[\gamma_n = \frac{y_n + \tilde\mu|y_t|}{1+\mu\tilde\mu} = \frac{1 + 0.02}{1.0025} \approx 1.017,\qquad \gamma_t = \mu\gamma_n \approx 0.509\]

法向几乎没变,摩擦从 4 被截到了 0.509,正好落在锥边上,就是 Coulomb 滑动摩擦。

5. 为什么 $R$ 范数这把尺子是对的 #

$y_t = 4$ 之所以这么大,是因为 $y_t = -v_t/R_t$,而 $R_t$ 被人为地设得很小(极硬的粘性摩擦)。所以这个大数字只是正则化”放大”出来的,并不是一个真实的物理需求。

$R$ 把冲量换算回速度:切向改动 $\Delta\gamma_t$,对应的速度只变 $R_t\Delta\gamma_t$,很小;法向改动 $\Delta\gamma_n$,对应的速度变 $R_n\Delta\gamma_n$,很大。$R$ 范数 $\Delta\gamma^\top R\,\Delta\gamma$ 的单位是”冲量 × 速度”,也就是能量。所以:

在 $R$ 范数下投影 = 找一个物理上允许的冲量,使它和试探冲量之间的”能量差”最小。

这个能量差会按每个方向各自的刚度来衡量,而不是把不同刚度放大出来的数字直接放在一起比较。

写成公式就是图里 (26) 式的左半边:

\[\gamma = \arg\min_{\gamma\in\mathcal F}\ (\gamma - y)^\top R\,(\gamma - y)\]

此外还有上一节说的数学上的好处:用这把尺子,才能保证 $\nabla_{v_c}\ell = -\gamma$,从而把整个时间步变成一个凸优化问题。

y是不是就是投影前的gamma #

对,可以这么理解。$y$ 就是投影前的冲量:

\[y = R^{-1}(\hat v - v_c)\]

它是在不管摩擦锥限制的情况下,只按弹簧阻尼(法向)和粘性摩擦(切向)算出来的冲量。投影之后才是真正用的冲量:

\[\gamma = P_{\mathcal F}(y)\]
  • 粘滞时,$y$ 本来就在锥里,$\gamma = y$,两者相同;
  • 滑动时,$\gamma$ 是 $y$ 被截到锥面上的结果;
  • 分离时,$\gamma = 0$。

有一点要注意:$y$ 和 $\gamma$ 都依赖于当前的接触速度 $v_c$,不是固定不变的数。Newton 法每迭代一次,$v$ 就会变,$v_c = Jv$ 跟着变,$y$ 要重新算,然后再投影得到新的 $\gamma$。代码里也是这样:_eval_contact_point 每次调用都先由 vc 算出 y,再投影得到 gamma。

所以准确地说,$y$ 是”在当前速度猜测下,投影前的冲量“。

还是没懂 #

还是没懂,首先我在优化一个系统,一个包含frictional contact考量的系统,会有个未知的速度变量让我求解。然后我定义了法向冲量的规则,我能通过这个速度变量得到法向冲量。同时,我是不是也应该有一套规则,直接从速度变量算出切向冲量。但这个时候,我需要去检查,法向冲量和切向冲量耦合在一起是不是在摩擦锥里。

对,你的理解完全正确。我按你的思路把它整理成一个流程,再补上最后一块。

你说的流程 #

给定速度变量的当前值 $v$,先算接触速度 $v_c = Jv$,然后:

1. 法向规则(Kelvin–Voigt):从速度直接算出法向冲量

\[y_n = R_n^{-1}(\hat v_n - v_n)\]

2. 切向规则(粘性摩擦):从速度直接算出切向冲量

\[y_t = -v_t / R_t\]

3. 检查:两者合在一起,$(y_t, y_n)$ 在不在摩擦锥里?

这三步就是你说的。$y$ 就是这两条规则直接算出来的结果,还没经过检查。

你缺的是第 4 步:检查不通过怎么办 #

4. 修正:

  • 检查通过($y_t\le \mu y_n$):两条规则的结果都合法,直接用,$\gamma = y$。这时切向冲量确实就是粘性规则给出的,而这个粘性规则极硬,所以物体几乎不滑。这种情况起了个名字叫”粘滞”。
  • 检查不通过:要把它修正成锥里的某个点。投影就是”怎么修正”的规则:找锥里离 $y$ 最近($R$ 范数)的点。结果是摩擦被截到 $\mu\gamma_n$(滑动),或者全部为零(分离)。法向也可能被顺带微调一点。

所以,1 到 4 合起来,就是一个完整的函数:

\[v \;\to\; v_c = Jv \;\to\; y \;\to\; \gamma = P_{\mathcal F}(y)\]

输入速度,输出一个保证在锥里的冲量。

容易混淆的一点:检查不是优化问题的约束 #

你可能会以为”摩擦锥”是加在优化问题上的一个约束,即优化器要在满足锥约束的前提下去找 $v$。不是这样的。

检查和修正都发生在冲量函数的内部。不管优化器试的是什么 $v$,这个函数吐出来的 $\gamma$ 永远在锥里,因为它已经被投影过了。所以优化器本身没有任何约束:

\[\min_v\ \tfrac12\|v - v^*\|_M^2 + \sum_i \ell_i(J_i v)\]

它只管找一个 $v$,使得动量方程 $M(v - v^*) = \sum_i J_i^\top\gamma_i(J_i v)$ 成立。这就是 SAP 名字里 “Unconstrained” 的意思:锥的限制被藏进了 $\gamma(v_c)$ 这个函数,而不是作为优化问题的约束出现。

切向规则是怎么定义出来的 #

切向规则不是从物理推出来的,而是人为选的。法向规则有物理来源(弹簧阻尼),切向没有。下面说明它是怎么被”选”出来的。

1. 想要的东西写不成函数 #

我们需要一条”从速度算出切向冲量”的规则,也就是一个函数 $\gamma_t = g(v_t)$。

真实的静摩擦是:$v_t = 0$,冲量可以是 $[-\mu\gamma_n, \mu\gamma_n]$ 里的任意值。在 $v_t = 0$ 这一点上,一个速度对应无数个冲量,它不是函数。所以没法直接用。

2. 那就选一个最简单的、近似它的函数 #

最简单的选择是一条过原点、很陡的直线:

\[\gamma_t = -\frac{v_t}{R_t}\]

这相当于在切向加了一个阻尼器,阻尼系数 $c_t$ 很大:$f_t = -c_t v_t$,乘以 $h$ 得到冲量,于是 $R_t = 1/(h c_t)$。只要 $R_t$ 足够小,不滑就需要很大的冲量,所以 $v_t$ 会非常接近 0,这样就近似了 $v_t = 0$。

3. 为什么正好是这个形式 #

关键是要和法向规则长得一样。法向是:

\[\gamma_n = R_n^{-1}(\hat v_n - v_n)\]

切向写成同样的形式,取 $\hat v_t = 0$(切向没有弹簧,没有”想回去的位置”,目标就是不滑):

\[\gamma_t = R_t^{-1}(\hat v_t - v_t) = R_t^{-1}(0 - v_t)\]

于是三个方向可以统一写成:

\[y = R^{-1}(\hat v - v_c),\qquad R = \text{diag}(R_t, R_t, R_n)\]

这样统一的好处是:后面的投影(在 $R$ 范数下)、代价 $\ell = \tfrac12\gamma^\top R\gamma$,以及 $\nabla\ell = -\gamma$ 这个性质,都可以对三个方向一起成立。如果切向选了别的形状(比如 Lagged 那种光滑曲线),就要换一套构造方法。

4. 最后定 $R_t$ 的大小 #

这是唯一需要权衡的地方:

  • 太大:蠕滑明显,抓不住东西;
  • 太小:条件数差,Newton 和 PCG 难收敛。

选 $R_t = \sigma w$,让蠕滑比例固定为约 $\sigma$,条件数固定为 $1/\sigma$,与物体轻重无关。这就是前面讲过的内容。


总结:切向规则 = “用一个极硬的线性阻尼器近似静摩擦”。选线性,是为了和法向统一成 $R^{-1}(\hat v - v_c)$;选 $\hat v_t = 0$,是因为目标就是不滑;选 $R_t = \sigma w$,是为了在蠕滑和条件数之间取得一个与尺度无关的折中。

MuJoCo 其实也是同样的思路:它在每个约束方向(包括摩擦方向)上都加了一个正则化项 $R$。SAP 的这套构造和它是一脉相承的。

这两个速度是怎么回到摩擦锥的 #

先澄清一点:摩擦锥在冲量空间里,不在速度空间里。速度本身不需要”回到锥里”,需要在锥里的是冲量。

速度是怎么变成锥里的冲量的 #

分两步:

第一步:两条规则把速度换成冲量(这一步还不管锥)

\[v_c = (v_t, v_n) \;\longrightarrow\; y = \Big(-\frac{v_t}{R_t},\ \frac{\hat v_n - v_n}{R_n}\Big)\]

第二步:在冲量空间里检查、投影

\[y \;\longrightarrow\; \gamma = P_{\mathcal F}(y) \in \mathcal F\]

所以,”回到锥里”的是 $y$(投影前的冲量),而不是速度。速度只是输入。

反过来看:三种情况在速度空间里长什么样 #

把 $y$ 的定义代进三个区域的判断条件,就能直接用速度来写。

粘滞:$\lvert y_t \rvert \le \mu y_n$ \(\frac{\lvert v_t\rvert}{R_t} \le \mu\frac{\hat v_n - v_n}{R_n} \quad\Longrightarrow\quad \|v_t\| \le \hat\mu\,(\hat v_n - v_n),\qquad \hat\mu = \mu\frac{R_t}{R_n}\) $\hat\mu$ 很小,所以粘滞时滑移速度必须非常小,和法向压得多紧成正比。

分离:$y_n + \hat\mu,\lvert y_t\rvert \le 0$ \(\frac{\hat v_n - v_n}{R_n} + \mu\frac{R_t}{R_n}\cdot\frac{\|v_t\|}{R_t} \le 0 \quad\Longrightarrow\quad v_n - \hat v_n \ge \mu\,\|v_t\|\) 也就是法向速度超过平衡点足够多,物体在分开。

滑动:介于两者之间。

画在速度空间里(横轴是 $\lvert v_t\rvert$,纵轴是 $v_n - \hat v_n$):

  v_n − v̂_n
     ↑        ╱
     │ 分离  ╱   斜率 1/μ:v_n − v̂_n = μ‖v_t‖
     │     ╱
     │   ╱
     │ ╱       滑动
─────┼────────────────→ ‖v_t‖
     │╲
     │ 粘滞(一条极窄的楔形,斜率 1/μ̂,几乎贴着纵轴)
     ↓

两个空间对照:

 冲量空间($y$)速度空间($v_c$)
粘滞摩擦锥内部 $\lvert y_t\rvert \le \mu y_n$贴着纵轴的极窄楔形 $\lvert v_t\rvert \le \hat\mu(\hat v_n - v_n)$
分离锥尖下方的区域锥 $v_n - \hat v_n \ge \mu\lvert v_t\rvert$
滑动其他其他

这两个图是对偶的:冲量空间里的摩擦锥,对应速度空间里的”分离锥”。

分离条件 $v_n - \hat v_n \ge \mu\lvert v_t\rvert$ 还再次暴露了前面说的 gliding 伪影:滑得越快,物体需要更大的法向速度才算”分离”。这正是法向和切向在投影里耦合的结果。