关于pymunk精度的几个问题

A few questions about pymunk's accuracy

我对模拟一种杆摆系统很感兴趣:

from intro import pymunk, space, App
import pygame
from pymunk.vec2d import Vec2d

pygame.init()


b0 = space.static_body                      #declare a universe

b1 = pymunk.Body(mass=1000, moment=10)
b1.position = (240, 200)
c1 = pymunk.Segment(b1, (0, -40), (0, 40), 6)
c1.elasticity = 0.1
space.add(b1, c1)

b2 = pymunk.Body(mass=.1, moment=1)
b2.position = (240, 100)
c2 = pymunk.Segment(b2, (0, 0), (0, -40), 6)
c2.elasticity = 0.1
space.add(b2, c2)

j1 = pymunk.constraints.PinJoint(b0, b1, (240, 200), (0,0))
j2 = pymunk.constraints.PinJoint(b2, b1, (0, 0),(0,-40))

space.add(j1, j2)
b1.torque = 4000
space.gravity = 0,0                 #gx , gy
print(b1.position, b1.velocity)
App().run()
print(b1.position, b1.velocity)

但它并没有像我预期的那样运行。

  1. 我在主杆上设置了扭矩。我会假设单独留下的系统应该随着时间的推移慢慢加速。我没看到。
  2. 副杆似乎没有感觉到向心加速度。我认为当它四处摆动时,它会想指向外面。我认为这与模拟质量的分布方式有关。我是否需要将次级杆变成一系列质量,或者是否有更简单的方法来移动质心?
  3. 我可以改变主杆和副杆的质量比。我假设当 M1>>M2 时,系统只会原地旋转,就好像没有辅助杆一样。但我没有看到,相反,主杆振荡,就好像它正在将大量 angular 动量传递到副杆。我错过了什么吗?
  4. pymunk 甚至应该是一个可靠的物理模拟器吗?或者它只是近似于物理,足以成为游戏的一部分?
  5. 是否有一个基于 python 的物理模拟器可以推荐给像这样的系统。最终我希望能够通过可变扭矩和阻力模拟振荡,同时记录系统上的力。
  1. 扭矩每一步都会重置,如此处所写:http://www.pymunk.org/en/latest/pymunk.html#pymunk.Body.torque鉴于此,我认为期望它应该随着时间的推移而减速。我还应该补充一点,手动设置这些类型的值通常有点棘手,最好使用 SimpleMotor 约束。

  2. 是的,就像你写的一样,重心似乎是这里的问题。重心将位于线段的 0,0(如果您创建多边形形状,重心将位于 0,0)。所以 c1 的重心在中间,而 c2 的重心在一端。 您可以将 c2 的定义更改为 (b2, (0,-20), (0,20)...) 并修改 body 的位置以进行补偿,或者使用 body center_of_gravity 属性 来调整其位置。 http://www.pymunk.org/en/latest/pymunk.html#pymunk.Body.center_of_gravity

  3. 我认为问题是你使用的两个段体的时刻非常极端。可以使用内置方法moment_for_segment计算力矩,例如:pymunk.moment_for_segment(1000, (0, -40), (0, 40), 6) 计算出的力矩为717000,这与您的代码中的值有很大不同。您还可以让 Pymunk 从附加的形状计算物体的质量和力矩,http://www.pymunk.org/en/latest/pymunk.html#pymunk.Body.__init__

  4. Pymunk 使用 C 库 Chipmunk 进行实际模拟。这个库的重点主要是游戏或其他实时用途,Pymunk 也是如此。但是,我知道 Pymunk 已用于许多不同的目的,如此处的使用列表所示:http://www.pymunk.org/en/latest/showcase.html 页面。我不知道 Pymunk 中的算法对于您的用例是否足够准确和全面。

  5. 不确定。

最后要注意的是,在 space.step 函数中使用尽可能小的 dt 可能是个好主意,因为这会产生更好的模拟。