4

Question

In a closed system where moving 2-dimensional circular bodies (they have mass and velocity attributes) collide with one another with perfect elasticity, is total velocity speed (magnitude of velocity) of all the bodies within the system conserved?

Background

I'm implementing a simple 2-D physics engine in Python based on the collision resolution method outlined in this Stack Overflow question. My expectation is that total speed (the sum of the length of the velocity vectors associated with each body) should remain constant between 2 bodies when they collide and I designed a unit test for my resolution method based on this expectation. But I find my test failing. So I want to make sure first that my assumption is correct.

If it is correct, I invite you to review my code and explain why the test is failing:

Collision Resolution

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

Unit Test

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)

I'm using this pygame vector class: http://www.pygame.org/wiki/2DVectorClass

Community
  • 1
  • 1
klenwell
  • 6,978
  • 4
  • 45
  • 84

3 Answers3

4

Total momentum is conserved, regardless of how elastic the collision is. Total velocity is obviously not. Strictly speaking, velocity is a vector quantity, and it is rather easy to see that it will change, as a vector quantity: for example, a ball that elastically bounces off an immovable perpendicular wall changes its velocity to its opposite.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Completely "immovable" walls are non-physical. Instead, you can say a "massive" wall, and that it gains only a tiny amount of velocity when the ball bounces off (with slightly less velocity than it came in with, since some momentum was transferred to the wall). – Blckknght Nov 30 '12 at 04:53
  • @Blckknght: If the wall's mass is sufficiently high and the available energy in the system sufficiently low by comparison, then it will be impossible to *measurably* move the wall, which is close enough. – Dietrich Epp Nov 30 '12 at 04:54
  • Can you come up with a simple example where the total of the velocity *magnitudes* obviously changes after a collision? (I'm having trouble doing so myself.) – Cameron Nov 30 '12 at 04:57
  • @Cameron: Sure, AndreyT's example works (as long as you interpret "immovable" as "massive"). Imagine a 1 gram ball bouncing off a 1000 Kg wall. The ball's velocity will be almost exactly reversed and the wall will pick up a negligible speed. Total system momentum will be the same, but the total velocities will have changed a lot. – Blckknght Nov 30 '12 at 04:59
  • @Cameron: I have a feeling that at least in 1D cases the sum of magnitudes should remain constant... – AnT stands with Russia Nov 30 '12 at 05:10
  • 2
    @AndreyT: Incorrect. Sum of magnitudes does not remain constant in 1D, even with perfectly elastic collisions. Imagine a 1000 kg brick wall travelling at 10 m/s towards a stationary 100 g rubber ball. Obviously the brick wall will still be going 10 m/s, and the ball will now be going 20 m/s. The sum of the magnitudes of the velocities has tripled. The only way it will stay the same is if the ball *passes through the wall* which is obviously impossible. – Dietrich Epp Nov 30 '12 at 05:18
  • @Dietrich Epp: Your example is invalid. In a system with elastic collisions total mechanical energy is always preserved. We can exclude potential energy from consideration (as constant), so the total *kinetic* energy must be preserved. In your imaginary experiment the total kinetic energy is not preserved, meaning that the example is invalid. – AnT stands with Russia Nov 30 '12 at 05:32
  • @Dietrich Epp: ... although it is only "slightly" invalid :) After the collision the speeds are going to be `9.998` and `19.998`, meaning that the sum is indeed not preserved. You are right. – AnT stands with Russia Nov 30 '12 at 05:37
1

AndreyT's answer straightened me out. Here's the unit test I wanted:

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)

It passes.

Community
  • 1
  • 1
klenwell
  • 6,978
  • 4
  • 45
  • 84
0

It is an excellent Problem. I don't think the right solution exists in the theory of elastic collisions as it is taught in Physics courses/books.

In the center of mass (CM) reference frame the relative velocity is reversed, in a binary elastic collision (Huygens). Since the relative velocity does not depend on the reference frame chosen, it follows that, relative velocity reverses in any arbitrary reference frame. This ensures that the magnitude of relative velocity which is the same as the sum of the speeds in the CM reference frame remains constant.

In essence what is said above means this: if you calculate the sum of the speeds (magnitudes of velocities) in CM frame, your test/code must face no failure.

I may add the following by way of supplementary information.

There is another theory that leads to the result that requires mere restoration of relative speed and does not insist on reversal of relative velocity. According to this theory, it is possible, in an arbitrary reference frame, for transfer of kinetic energy (KE) between the two masses, keeping the sum of KEs unchanged. This theory could lead to failure of results in your code/test.

I don't understand the code you wrote since I am not conversant with computer codes/ programs. As such, I am not in a position to suggest modifications in your program.