【问题标题】:Colision Resolution between Circles - Slow Sliding圆之间的碰撞解决 - 慢速滑动
【发布时间】:2013-04-06 02:24:32
【问题描述】:

我在解决圆到圆碰撞时遇到问题。

首先,我检测到碰撞,然后如果球发生碰撞,我用它们的半径之和将它们分开并设置速度。这很容易。

我的问题是当重力作用时,一个球与另一个球从上方相撞。它应该弹开,但它滑得很慢,直到掉到地上

发生的事情是,在解决碰撞后,重力将球向下推并导致另一次碰撞。我试过用它们的半径 + x 之和来分离球,但它只是滑动得快了一点。

您可以通过http://www.youtube.com/watch?v=tk7qQ9KDFp0&feature=youtu.be观看视频。

这是处理大肠杆菌的代码:

for p in world.particle_list:

        if not p == self:

            if self.pos.sub(p.pos).get_length() <= self.radius * ppm + p.radius * ppm:

                p_mass_ratio = float(self.mass) / (self.mass + p.mass)
                self_mass_ratio = float(p.mass) / (self.mass + p.mass)

                rel_pos = p.pos.sub(self.pos)
                shift = rel_pos.set_length(- rel_pos.get_length() + self.radius * ppm + p.radius * ppm)
                p.pos = p.pos.add(shift.scale(0.50))
                self.pos = self.pos.add(shift.scale(-0.50))

                p_speed = p.speed
                self_speed = self.speed

                self.speed = p_speed.add(self.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(-self.friction))).scale(0.50 * self_mass_ratio)
                p.speed = self_speed.add(p.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(self.friction))).scale(0.50 * p_mass_ratio)

我做了一个矢量类来处理这个:

def dcos(x):

    return cos(radians(x))

def dsin(x):

    return sin(radians(x))

def dtan(x):

    return tan(radians(x))

class Vec(object):

    def __init__(self, x, y):

        self.x = float(x)
        self.y = float(y)

        self.length = self.get_length()
        self.angle = self.get_angle()

    def get_length(self):

        return sqrt(self.x ** 2 + self.y ** 2)

    def get_angle(self):

        return atan2(self.y, self.x) * 180 / pi

    def add(self, vec1):

        new_x = self.x + vec1.x
        new_y = self.y + vec1.y

        return Vec(new_x, new_y)

    def sub(self, vec1):

        new_x = self.x - vec1.x
        new_y = self.y - vec1.y

        return Vec(new_x, new_y)

    def scale(self, k):

        return Vec(self.x * k, self.y * k)

    def set_angle(self, a):

        new_x = self.length * dcos(a)
        new_y = self.length * dsin(a)

        if a == -90 or a == 90:

            new_x = 0

        if a == 180 or a == 0 or a == -180:

            new_y = 0

        return Vec(new_x, new_y)

    def set_length(self, l):

        new_x = l * dcos(self.angle)
        new_y = l * dsin(self.angle)

        return Vec(new_x, new_y)

    def inverse(self):

        return Vec(- self.x, - self.y)


    def norm_reflect(self, vec1):

        if self.get_angle == vec1.get_angle():

            return Vec(self.x, self.y)

        if vec1.get_angle() >= 0:

            return self.set_angle(vec1.get_angle() - self.get_angle() + 90)

    else:

        return self.set_angle(vec1.get_angle() - self.get_angle() - 90)

【问题讨论】:

  • 将长度设置为负值是否合法?它会反转向量的方向吗?
  • 是的,如果参数为负,set_length() 方法将反转方向。

标签: python physics collision


【解决方案1】:

(我不知道 python,但我知道物理,你没有得到其他答案,所以我会尝试一下。)

看看

if self.pos.sub(p.pos).get_length() <= self.radius * ppm + p.radius * ppm:
  ...
  rel_pos = p.pos.sub(self.pos)
  shift = rel_pos.set_length(- rel_pos.get_length() + self.radius * ppm + p.radius * ppm)
  p.pos = p.pos.add(shift.scale(0.50))
  self.pos = self.pos.add(shift.scale(-0.50))

您将长度设置为负数,因此您将对象朝向彼此移动。

norm_reflect() 函数没有多大意义,我怀疑它做的不是你想要的(在这种情况下你不是在测试你的代码)。

这两行:

self.speed = p_speed.add(self.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(-self.friction))).scale(0.50 * self_mass_ratio)
p.speed = self_speed.add(p.speed.norm_reflect(rel_pos.set_angle(rel_pos.get_angle() + 90).scale(self.friction))).scale(0.50 * p_mass_ratio)

似乎只用一个参数调用norm_reflect()并且在简单案例起作用之前,您将摩擦和质量比带入图片中,并且您'在多次转换后重用rel_pos并且物理是非牛顿的(即错误到需要从头开始)。

【讨论】:

  • 首先,正如您在 youtube 视频中看到的那样,我没有将球移向彼此,其次,如果您认为 norm_reflect 函数是错误的,请告诉它是怎么错的,第三,我的向量类的每个方法都返回另一个方法,所以我无法使用转换后的向量。
  • 返回另一个向量类而不是方法。
  • 1) 如果您不相信我,请单独尝试 shift 的内容,不要依赖有很多其他内容的视频 . 2) 你打算norm_reflect() 做什么?将一个向量反射到另一个向量?如果两个论点相同,您会期望什么? 3) 你认为rel_pos 不会被self.speed =... 行改变吗?
  • 1) 我单独尝试了 shift 的东西,我知道它没有任何问题。首先,我将球放在相同的位置,然后它们分开(就像在视频中一样)。2) norm_reflect() 应该反映另一个法线的向量(不是问题,因为没有重力就没有问题)。 3)我在计算前后打印了rel_pos,它们是一样的。
  • 唯一有意义的部分表明您已经实现了非标准行为,例如set_angle 方法实际上不会改变调用对象的角度。可能你也设置了A.sub(B)返回B-A,没办法说。也许如果您发布一个最小的完整示例,有人可以帮助您。
猜你喜欢
  • 1970-01-01
  • 2019-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-20
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
相关资源
最近更新 更多