Skip to content

碰撞求解(二):使用冲量 #35

Open
@phenomLi

Description

@phenomLi

上一次讲了基于向量的碰撞求解方法,该方法基本上只适用于无方向的球体间的完全弹性碰撞,灵活性较低。今天介绍一种基于冲量的碰撞求解方法,该方法更加精确,强大,而且能模拟非弹性碰撞。


注意:该文章只涉及一定量数学,要求:

  • 高中向量知识

(虽然看着很多公式,但是大部分都是课本现成的物理公式,我们要做的工作只是把这些公式重新组合整理一下而已)


什么是冲量

冲量(impulse)是一个力学上的矢量,记作符号J用于描述物体动量的变化,冲量是一个过程量,比如一个物体t=0时动量5,t=1时动量10,那么该物体在0到1时的冲量为5。


但是我们毕竟不是搞物理的,不需要对某些概念这么深究。我本人简单地将冲量看作为 “ 一股一瞬间改变速度的力 ”,而且该“力”可以作用在物体的任何点上。这就是冲量最大的优点,如果冲量的作用点不过质心,那么物体便会发生旋转。


另外,使用冲量的另一个优点是,冲量可以很容易和力建立联系:


两个小球间的碰撞

现在,我们先将问题简化,考虑两个小球间的碰撞。假设小球为AB,如图:


其中小球A的质量为massA,碰撞时速度为VA,碰撞后速度为V'A。小球B的质量为massB,碰撞时速度为VB,碰撞后速度为V'B我们要求的就是改变小球速度的冲量J,下面我们一步步来推导出J


先从小球的速度入手,我们引入 相对速度(relative velocity) 这个概念:AB间的相对速度即A的速度减去B的速度,即 公式一

其中VABAB的相对速度(对于相对速度的具体理解,可以看下面的评论)。


在碰撞求解中,我们关注的是碰撞法线方向的相对速度,即公式一应该用碰撞法线n表示,也就是说,我们想知道从AB沿碰撞法向的相对速度,得到公式二


下一步,我们引入恢复系数(coefficient of restitution)。恢复系数是一个控制碰撞弹性程度的量,用符号e表示,取值范围[0, 1],若e = 1,表示完全弹性碰撞,碰撞后两物体不损失能量;若e = 0,表示完全非弹性碰撞,两物体碰撞后粘在一起,能量和为0。e通常取两物体恢复系数的积的平方根:

e = Math.sqrt(A.restitution * B.restitution);

现在,根据牛顿恢复定律,有公式三

该公式表明了碰撞后的速度等于碰撞前的速度乘以恢复系数。


现在我们将公式二公式三组合一下,得到公式四

即:

注意,我们要在右边引入一个负号。因为在在牛顿恢复定律中,碰撞后的速度V',实际上是指向碰撞前速度V的相反方向。


目前,我们还没有出现冲量J,别急,下面重点开始了。我们现在要做的就是将冲量J和速度V联系起来。首先看公式五

该公式描述了碰撞后速度 V' 和碰撞前速度V的关系。又因为冲量J是动量的变化量,有公式六

现在终于出现了J,为了得到 V' 关于J的表达式,我们将公式五和公式六进行组合,得到公式七

因为AB发生碰撞时,A将被推向与B相反的方向,所以:

显然,求 V' 的关键是求出J。将公式四公式七进行组合,整理,推出公式八

我们观察这个式子,只有J是未知的,顺理成章地将式子整理一下,将J移到式子左边,其他量移到等式右边,得到J的表达式:


解决了,虽然有点复杂,但是不难理解。将J代入公式七便可以求出小球的碰撞后速度。但是故事还没结束,我们现在的情况只是两个小球间的碰撞,两个小球间的碰撞用向量方法就可解决,搞这么多公式的推导,目的是将碰撞求解抽象到适用于所有情况


求解复杂的碰撞

有了以上基础,我们来看复杂一点的碰撞求解。例如下面两个矩形的情况:

求解该碰撞的关键在于碰撞点。我们可以视这个碰撞点为两个分别在两个矩形碰撞点位置的小球间的碰撞,那么,对于该碰撞点,便可以转换为两个小球间碰撞的情况。但是问题在于,我们只知道两个矩形的速度,所以要解决问题,需要求出碰撞点分别基于两个矩形的速度:

其中V为线速度,w为角速度,r为碰撞点到矩形质心的距离向量。求出碰撞点速度后再求出J,便可以将J作用在碰撞点上产生摩擦力,加速度和扭矩,使矩形发生位移或旋转。

最后

基于冲量的碰撞求解可以适用于更多情况,而且更加真实,但是并不是完美的。冲量法往往伴随抖动,特别在大量物体堆叠时,抖动会更加明显。碰撞求解不是一个简单的内容,基于冲量的方法仍然不够抽象,接下来有时间我会再介绍一种更高阶的碰撞求解方法。

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions