【问题标题】:Physics-bodies bouncing of each other at high velocities物理物体以高速相互弹跳
【发布时间】:2020-11-15 18:31:40
【问题描述】:

我正在用 Python 开发一个物理引擎(我知道,它主要用于“学习”),并且运行良好。我一直在关注很多关于这个问题的在线文档,这一系列文章特别有帮助:How to Create a Custom Physics Engine

我的材料正在工作,它们充当一个包含 restitutiondensity 的类。接下来发生的是具有低密度和高复原力(例如分别为 0.3 和 0.8)的物体,它们以如此高的速度相互反弹,以至于它们很快就会射入“虚空”。

我有一个测试场景,有 4 面墙包围着身体(球)。当它们以如此高的速度行驶时,永远不会记录碰撞,因为下一次物理模拟发生在它们已经通过“墙壁”之后。

我真正感兴趣的是为什么它们在相互反弹时会获得如此高的速度,而我认为它们不应该如此。在我的示例录制中,我有一个小球(红色),由玩家(我)控制。它的密度为 0.3,复原率为 0.8,体积为 100(r * r 或 10 * 10),质量为 30 KGs(100 * 0.3)。另一个较大的球(绿色)不是玩家的控制者,但可以通过用红色球击中它来反弹。它具有相同的材料,因此具有相同的密度和复原力。但是,由于半径较大 (30),它的质量较高。绿球的实际质量是 270 (900 * 0.8)。

在录音中,可以看到球以不自然的方式相互反弹。小球不应该比大球受到更大的冲击吗?我试图通过交换计算脉冲时使用的质量值来解决这个问题。所以小球的冲量是用大球的质量来计算的,反之亦然。你会认为这是因为更大的球质量更高,但对我来说,它们彼此反弹得相当快?

这是我在这两个球上的密度和恢复力的正常行为吗?如果需要,我将共享代码,但由于本文已经有点长,如果不需要,我不会浪费空间。我的代码几乎完全遵循文章中的内容,只是“转换”为 Python 代码。

计算冲动的代码

# Relative velocity
rv = b.velocity - a.velocity

# Velocity along the normal direction
vel_along_normal = rv.dot(contact_normal)

# EPSILON (use lowest restitution value)
e = min(a.restitution, b.restitution)

# Calculate j, which will be used to get the impulse
j = -(1 + e) * vel_along_normal
j /= a_inv_mass + b_inv_mass

impulse = contact_normal * j

# Using ratio to have lighter bodies bounce with a higher impulse than heavier bodies
mass_sum = a_mass + b_mass
ratio = (b_mass / mass_sum)
a.rigid_body.velocity -= (impulse * ratio) * dt

ratio = (a_mass / mass_sum)
b.rigid_body.velocity += (impulse * ratio) * dt

【问题讨论】:

  • Restitution e 是一个 0 到 1 之间的值。假设 e 在 e = min(a.restitution, b.restitution) 之后是一个正值,那么下一行 j = -(1 + e) * vel_along_normal 是不正确的,因为它使 (1 + e) > 1 增加了能量碰撞(在现实世界中不应该发生)。由于不清楚您如何定义 e 我会假设标准定义并说计算 j 的行应该是 j = -e * vel_along_normal
  • 当像这样更改代码时,球只是撞到对撞机上,什么也不做。正如您所说,恢复值是 0 到 1。球的e 为 0.8,因此它的弹跳应该很高。但事实并非如此。
  • 我设法让它工作,我没有乘以 dt。不过,他们仍然表现得很奇怪。对于静止的物体,它似乎可以正常工作,但是一旦两者都移动,它们就会突然开始超快。
  • 似乎身体越重,它跑得越快,但只针对静止的物体。我相信这是因为静止物体的质量为 0(无限质量)。所以j 没有正确计算,因为 0 inverse_mass。如果其中一个物体的质量是无限的,我应该使用什么值?
  • 现在我想起来了,当一堵墙有无限的质量时,它不应该像我们看到的那样发回一个高脉冲吗?所以,我猜运动学的原因是为了解决这个问题。所以你仍然可以有质量,但要防止身体受到力的影响。

标签: python game-physics physics physics-engine


【解决方案1】:

看来碰撞后的速度差存在符号问题。与其让红球减速,不如让它加速。

【讨论】:

  • 知道这可能是什么吗?我可以分享计算脉冲的代码。我还添加了另一个视频,您可以在其中看到大小和质量相同的球的这种“奇怪”行为。起初它们的行为“正确”,但很快它们就开始以如此高的速度前进。
  • 检查在碰撞后正确更新速度的部分代码中的数学。
  • 我添加了一些几乎直接代表我的实际代码的示例代码。您会注意到我交换了添加到正文中的值。物体a从b获得质量,反之亦然,这应该是这样的吗?
【解决方案2】:

整个功能对我来说看起来不正确,并且由于它没有按预期工作,所以有问题。与其尝试解决问题所在(代码中有太多未知数,dta_inv_massb_inv_masscontact_normal),不如使用以下 sn-p 为您计算碰撞数学

// A and B are balls at time of collision
mA = A.mass
mB = B.mass
mm = mA + mB

// vector between balls
x = A.x - B.x
y = A.y - B.y  

// restitution
e1 = A.restitution
e2 = B.restitution

// distance sqr between balls
d = x * x + y * y;

// v velocities
uAB = (A.v.x * x + A.v.y * y) / d  // normal component force A into B
u2  = (A.v.y * x - A.v.x * y) / d  // tangent component force A

uBA = (B.v.x * x + B.v.y * y) / d  // normal component force B into A
u4  = (B.v.y * x - B.v.x * y) / d  // tangent component force B

// Force from B into A along normal, scaled for mass ratio and restitution
uA = ((mA - mB) / mm * uAB + (2 * mB) / mm * uBA) * e1

// Force from A into B along normal, scaled for mass ratio and restitution
uB = ((mB - mA) / mm * uBA + (2 * mA) / mm * uAB) * e2

// new velocities 
A.v.x = x * uA - y * u2
A.v.y = y * uA + x * u2

B.v.x = x * uB - y * u4
B.v.y = y * uB + x * u4

注意dt 被忽略(假设dt 是增量时间)

注意两个物体都必须有一定的质量。如果一个或两个的质量为 0,这将不起作用。

【讨论】:

  • 必须忽略吗?我认为速度的变化需要应用 dt 值。如文章中所述,inv_mass 变量是质量 (1 / mass) 的倒数。因为乘法比除法便宜得多。通过存储反质量,使用它会更便宜。
  • @Qlii256 dt 仅适用于该位置,例如A.x += A.v.x * dt 上面的代码有很多优化空间但是我不知道1/mass 将如何节省时间,因为它是比率质量很重要,每次碰撞都会有不同的比例。你可以先mm = 1 / (mA +mB) 然后uA = ((mA - mB) * uAB + 2 * mB * uBA) * mm * e1uB 一样
  • 好的,那么无限质量(值为 0)呢。如果其中一个物体的质量是无限的,会发生什么?
  • @Qlii256 你不是说没有质量(值为 0)。如果一个球的质量为 0,则碰撞的结果是不确定的(无意义的)。如果一个球具有无限质量,那么另一个球将获得无限速度(因为它是弹性碰撞),除非e == 0
  • @Qlii256 我回答中的代码来源于wiki en.wikipedia.org/wiki/Elastic_collision#Two-dimensional
猜你喜欢
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 2013-12-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多