4

質問

移動する2次元の円形物体(質量と速度の属性を持つ)が完全な弾性で互いに衝突する閉鎖系では、システム内のすべての物体の総速度速度(速度の大きさ)は保存されていますか?

バックグラウンド

このStackOverflowの質問で概説されている衝突解決方法に基づいて、Pythonで単純な2次元物理エンジンを実装しています。私の期待は、合計速度(各物体に関連付けられた速度ベクトルの長さの合計)が衝突したときに2つの物体間で一定のままである必要があることであり、この期待に基づいて解決方法の単体テストを設計しました。しかし、テストが失敗しました。ですから、最初に私の仮定が正しいことを確認したいと思います。

正しければ、コードを確認して、テストが失敗する理由を説明してください。

衝突の解決

class Physics:

    @staticmethod
    def reflect_colliding_circles(
        (c1_x, c1_y, c1_vx, c1_vy, c1_r, c1_m, c1_e),
        (c2_x, c2_y, c2_vx, c2_vy, c2_r, c2_m, c2_e)):
        # inverse masses, mtd, restitution
        im1 = 1.0 / c1_m
        im2 = 1.0 / c2_m
        mtd = Physics.calculate_mtd((c1_x, c1_y, c1_r), (c2_x, c2_y, c2_r))
        normal_mtd = mtd.normalized()
        restitution = c1_e * c2_e

        # impact speed
        v = vec2d(c1_vx, c1_vy) - vec2d(c2_vx, c2_vy)
        vn = v.dot(normal_mtd)

        # circle moving away from each other already -- return
        # original velocities
        if vn > 0.0:
            return vec2d(c1_vx, c1_vy), vec2d(c2_vx, c2_vy)

        # collision impulse
        i = (-1.0 * (1.0 + restitution) * vn) / (im1 + im2)
        impulse = normal_mtd * i

        # change in momentun
        new_c1_v = vec2d(c1_vx, c1_vy) + (impulse * im1)
        new_c2_v = vec2d(c2_vx, c2_vy) - (impulse * im2)

        return new_c1_v, new_c2_v

    @staticmethod
    def calculate_mtd((c1_x, c1_y, c1_r), (c2_x, c2_y, c2_r)):
        """source: https://stackoverflow.com/q/345838/1093087"""
        delta = vec2d(c1_x, c1_y) - vec2d(c2_x, c2_y)
        d = delta.length
        mtd = delta * (c1_r + c2_r - d) / d
        return mtd

単体テスト

def test_conservation_of_velocity_in_elastic_collisions(self):
    for n in range(10):
        r = 2
        m = 10
        e = 1.0

        c1_pos = vec2d(0, 0)
        c1_v = vec2d(random.randint(-100,100), random.randint(-100,100))

        c2_delta = vec2d(random.randint(-100,100), random.randint(-100,100))
        c2_delta.length = random.randint(50, 99) * r / 100.0
        c2_pos = c1_pos + c2_delta
        c2_v = vec2d(random.randint(-100,100), random.randint(-100,100))

        c1_np, c2_np = Physics.translate_colliding_circles(
            (c1_pos.x, c1_pos.y, r, m),
            (c2_pos.x, c2_pos.y, r, m))

        c1_nv, c2_nv = Physics.reflect_colliding_circles(
            (c1_np.x, c1_np.y, c1_v.x, c1_v.y, r, m, e),
            (c2_np.x, c2_np.y, c2_v.x, c2_v.y, r, m, e))

        old_v = c1_v.length + c2_v.length
        new_v = c1_nv.length + c2_nv.length

        self.assertTrue(Physics.circles_overlap(
            (c1_pos.x, c1_pos.y, r), (c2_pos.x, c2_pos.y, r)))
        self.assertTrue(old_v - new_v < old_v * .01)

私はこのpygameベクトルクラスを使用しています:http ://www.pygame.org/wiki/2DVectorClass

4

3 に答える 3

4

衝突の弾力性に関係なく、総運動量は保存されます。全速度は明らかにそうではありません。厳密に言えば、速度はベクトル量であり、ベクトル量として変化することはかなり簡単にわかります。たとえば、動かない垂直な壁で弾性的に跳ね返るボールは、その速度を反対に変化させます。

于 2012-11-30T04:43:18.447 に答える
1

AndreyTの答えは私をまっすぐにしました。これが私が欲しかった単体テストです:

def test_conservation_of_momentum_in_elastic_collisions(self):
    """Some references:
    http://en.wikipedia.org/wiki/Elastic_collision
    http://en.wikipedia.org/wiki/Momentum
    https://stackoverflow.com/a/13639140/1093087"""
    for n in range(10):
        r = 2
        m = 10
        e = 1.0

        c1_pos = vec2d(0, 0)
        c1_v = vec2d(random.randint(-100,100), random.randint(-100,100))

        c2_delta = vec2d(random.randint(-100,100), random.randint(-100,100))
        c2_delta.length = random.randint(50, 99) * r / 100.0
        c2_pos = c1_pos + c2_delta
        c2_v = vec2d(random.randint(-100,100), random.randint(-100,100))

        momentum_before = (c1_v * m) + (c2_v * m)  

        c1_np, c2_np = collision.translate_colliding_circles(
            (c1_pos.x, c1_pos.y, r, m),
            (c2_pos.x, c2_pos.y, r, m))

        c1_nv, c2_nv = collision.reflect_colliding_circles(
            (c1_np.x, c1_np.y, c1_v.x, c1_v.y, r, m, e),
            (c2_np.x, c2_np.y, c2_v.x, c2_v.y, r, m, e))

        momentum_after = (c1_nv * m) + (c2_nv * m)  

        self.assertTrue(collision.circles_overlap(
            (c1_pos.x, c1_pos.y, r), (c2_pos.x, c2_pos.y, r)))
        self.assertEqual(momentum_before, momentum_after)

合格です。

于 2012-11-30T05:15:57.857 に答える
0

それは素晴らしい問題です。物理学のコース/本で教えられているように、弾性衝突の理論には正しい解決策が存在しないと思います。

重心(CM)参照フレームでは、相対速度が逆になり、バイナリ弾性衝突(Huygens)が発生します。相対速度は選択した参照フレームに依存しないため、任意の参照フレームで相対速度が反転します。これにより、CM参照フレームの速度の合計と同じ相対速度の大きさが一定に保たれます。

本質的に、上記の意味はこれを意味します。CMフレームの速度(速度の大きさ)の合計を計算する場合、テスト/コードは失敗に直面してはなりません。

補足情報として以下を追加する場合があります。

相対速度の単なる回復を必要とし、相対速度の逆転を主張しない結果につながる別の理論があります。この理論によれば、任意の参照フレームで、KEの合計を変更せずに2つの質量間で運動エネルギー(KE)を伝達することが可能です。この理論は、コード/テストの結果の失敗につながる可能性があります。

私はコンピューターのコード/プログラムに精通していないので、あなたが書いたコードを理解していません。そのため、私はあなたのプログラムの変更を提案する立場にはありません。

于 2012-12-24T07:16:34.057 に答える