Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Elastic collisions between round objects

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Elastic collisions between round objects
Ulf Magnusson
Member #2,908
November 2002

Two round objects collide in space. You know the speed along the x and y axises (vx and vy) for both objects and their position when they collide (from this you could i.e. calculate the angle of an imaginary line that connects the centerpoints of the objects). If you want to be somewhat physically correct, how would you calculate new vx and vy'ses for the two objects?

I know how to do it if the collision is "straight on" (as in, the speed vectors of both objects pass through the centerpoint of the other object), but it may not be in this case.

I'm not going to take spin, friction into account. Assume both objects have the same mass. It's just a simple, hopefully somewhat believable, system for my space shoot-em-up :)

When I think about it, it's just a billiards problem, only this time the playing field has no friction..

Any help appriciated

Ulfenstein

vpenquerch
Member #233
April 2000

If they are spheres, then you can simply mirror the velocities around the plane at the collision tengeant.

Otherwise, you get into Rigid Body Dynamics.
Lookup Chris Hecker's articles on google, they're really good.

Ulf Magnusson
Member #2,908
November 2002

Hmm.. but if I understand you right, won't that mean that if the second object was originally standing still, then the first (hitting) object will always stand still after the collision, regardless of how it hits the second object? (zero force rotated either way is still is a zero force)

This is obviously not always the case in billiards..

Ulfalizer

vpenquerch
Member #233
April 2000

D'oh, you're right of course, what I said applies if the other object has an infinite mass :)

Find out Hecker's papers. I couldn't tell you the
formulas here off the top of my head, but it does exactly what you need.
I've needed a whole week to completely understand the whole thing though.

Approx:
get the collision normal
apply an impulse(instant force) to each body
that's proportional to the dot product between collision velocity and collision normal and object's mass wrt. sum of the masses
this impulse modifies the quantity of movement (french term, can't remember how Hecker calls it)
you then deduce the new velocity

works a peach when once of the bodies has infinite mass (eg you can't modify its course) so it can be used for billiards table too.

Ulf Magnusson
Member #2,908
November 2002

I've got a model which works perfectly as long as one of the objects is initially still. I thought it'd be a piece of cake to just "pretend" one object is always standing still by subtracting it's velocity...

relVX = vX1 - vX2;
relVY = vY1 - vY2;

edit: "rel" is for "relative"

...and then add back the speed lost due to the "relativity adjustment" at the point of setting the final resulting speeds for the objects...

(*firstObjectIter)  -> setVX(newRelVX1 + vX2);
(*firstObjectIter)  -> setVY(newRelVY1 + vY2);
(*secondObjectIter) -> setVX(newRelVX2 + vX2);
(*secondObjectIter) -> setVY(newRelVY2 + vY2);

This is problematic. For one thing, the total speed of both objects will be less after the collision than it was before it (if both objects are moving, if one is standing still everything's fine..). In an elastic collision it should be constant

How am I thinking wrong?

Ulfalizer

Rash
Member #2,374
May 2002
avatar

Make sure the equality newRelV?1+newRelV?2==relV? always holds.
[EDIT]
I'm assuming now that no speed is "exchanged" between the X and Y components. This generalization is left as an exercise to the reader.
[/EDIT]

Ulf Magnusson
Member #2,908
November 2002

The problem is that my "relativity" approach is obviously faulty. If i could find some way to extend my one-object-still algorithm to two moving objects, i'd be all done

Ulfalizer

orz
Member #565
August 2000

This is the algorithm I use. It seems correct for elastic collisions between circles with no spin, but I've never checked it against a physics book or anything like that.

1 float dx = a1->x - a2->x;
2 float dy = a1->y - a2->y;
3 float dvx = a1->vx - a2->vx;
4 float dvy = a1->vy - a2->vy;
5 float distance = sqrt(dx * dx + dy * dy);
6 float impact = -2 / distance * (dx * dvx + dy * dvy);
7 if (distance == 0) return;//we can't handle this...
8 dx /= distance;
9 dy /= distance;
10 if (impact < 0) return;//weird collision (should only happen in unusual circumstances)
11 //adjust velocities for newtonian physics
12 impact = impact / (a1->mass + a2->mass);
13 a1->vx += impact * a2->mass * dx;
14 a1->vy += impact * a2->mass * dy;
15 a2->vx -= impact * a1->mass * dx;
16 a2->vy -= impact * a1->mass * dy;

Ulf Magnusson
Member #2,908
November 2002

Thanks, I'm not at a place where I can test the code now, but I will tommorow :)

I can't grasp how it works though. For example, in what way does the distance between the centerpoints matter? After you have determined that the objects actually Have collided that is. And what does that -2 come from? Hmz..

Ulfalizer

EDIT:

With that algorithm, is the sum of the speed of the first object (sqrt(a1->vx * a1->vx + a1->vy * a1->vy)) and the second object the same before and after the collision? What I have now looks right at a glance but leads to all balls eventually moving very slow due to losses in the collisions

orz
Member #565
August 2000

The code I posted, assuming I didn't mess it up when I editted it for posting, produces results that appear correct in my games and simulations.

Thd distance doesn't matter - it was used by a non-newtonian bit of physics that I editted out. However, the distance is used in the newtonian calculations there in the process of figuring out the direction in which the collision occured (i.e. the difference between their positions divided by the distance between their positions equals the unit vector in the direction from object 1 pointing at object 2, which, since they're circular, is equal to the unit vector in the direction normal to the collision). Anyway, then I take the dot product of that vector with the vector of their relative velocities and multiply by 2 (I think if you multiply by a smaller number you'll end up with in-ellastic collisions... but don't quote me on that... or any of this shit...) to get the force of impact. Then I give each object a portion of that force based upon its mass.

The check for negative impact force is there to protect against weird cases. I have weird cases sometimes for a few different reasons. The most common is due to objects teleporting into each other, in games that include teleportation. Another reason it happens is because of the flawed discrete time simulations an object involved in many collisions per game tick can end up at physically impossible combinations of position and velocity. And when doing pixel-perfect collisions I use the simplifying assumption that the sprites are aproximately circular and apply this formula, but if the sprites collide on a particularly non-circular portion, they can end up being weird also.

Andrew Ellem
Member #2,835
October 2002

My physics is a bit rusty, but since you're dealing with elastic collisions, you only have to worry about conservation of momentum and kinteic energy.

Given objects (m1, v1) and (m2, v2), where m is mass and v is velocity before collision and v' is velocity after,

By conservation of momentum you have:
m1 * v1 + m2 * v2 = m1 * v1' + m2 * v2'

You also have conservation of kinetic energy, which give you this formula:
1/2 m1 * v1^2 + 1/2 m2 * v2^2
= 1/2 m1 * v1'^2 + 1/2 m2 * v2'^2

So how do you calculate the new velocities?
Using the above formulas, you get:
v1' = ((m1 - m2) / (v1 + m2)) * v1
v2' = ((2 * m2) / (v1 + m2)) * v1

However, this may be a little simplistic for you, since it assumes that both objects are a single point. This would not be the case for real objects, such as billiard balls, where not all collisions are direct, but also involve glancing blows, etc.. My knowldege is physics is not so great as to explain that case ;)

But the above may suffice for you.

Evert
Member #794
November 2000
avatar

Conservation of momentum and internal energy holds in all (elastic) collisions. If collisions are not head-on (ie, the colliders are not simple points), you also need to consider conservation of the total angular momentum (L = r x p). If you're not considering rotating spheres, then this is not so hard (in the equation, r is the position vector of one object and p is its momentum. x denotes the vector product. In two dimensions, you only need the magnitude of L, since no collision should produce a `bump' out of the plane).

I don't have time to work out the equations myself now. I might have time to do it this evening when I get home (though I should probably work on something else). It shouldn't be too hard to work out, though.

orz
Member #565
August 2000

Andrew Ellem:
While your reasoning sounds right, and the conservation formulas you start with are correct as well, your resulting formula is wrong. For instance, if you switch object 1 and object 2 you should still get the same result, but you won't with that formula. Also, in your formula you add v1 and m2; but v1 is a vector of velocity, m2 is a scalar of mass, so the two don't add like that.

Ulf Magnusson
Member #2,908
November 2002

Orz:

I tried your code, and found the same problems I had with mine. Performing some random collisions between asteroids and the player spaceship, the total speed of both objects was often different after the collision (by a magnitude I don't think can be explained solely by rounding errors). Here's some trace data I cought:

!Before collision!

First object:

x = 171.406
y = 279.15
vX = -1.58721
vY = 0.735375

Second object:

x = 152.439
y = 319.148
vX = -0.0129988
vY = 0.199577

Total speed:

hypot(vX1, vY1) + hypot(vX2, vY2) = 1.94929

!After collision!

First object:

vX = -1.09078
vY = -0.311503

Second object:

vX = -0.509424
vY = 1.24646

Total speed:

hypot(vX1, vY1) + hypot(vX2, vY2) = 2.48093

For simple tests, like the tangeant at at the point of impact having a 45 angle and both objects moving towards eatch other at equal speed, the code worked perfectly.

Ulfalizer

vpenquerch
Member #233
April 2000

orz
Member #565
August 2000

The sum of speeds is not supposed to match. Instead, the sum of momentums is supposed to match, and the sum of energies. And the sum of momentums does match.

Hmm... uh-oh... the sum of energies isn't matching in my calculations... maybe I made a mistake...

(30 minutes later....)

Okay, the sum of energies matched. I should have written a program to theck the numbers, with all the stupid mistakes I've been making typing this in to a calculator...

Anyway, before collision the sum of energies is 1.5500 energy units, afterwards it's 1.5500 energy units. Before collision the sum of momentums is (1.600, 0.935), afterwards it's (1.600, 0.935). This is assuming they both have a mass of 1 mass unit.

edit:

So, in summary, that means that those numbers correspond to a 100% correct newtonian physics calculation, discounting rounding errors.

Vincent Penquerc'h:
Your link is broken for me.

gomez
Member #2,800
October 2002

Firstly we're talking floating point world, where if you add a set of numbers and then subtract that very same set of numbers you won't get zero...so over time things like Total KE will devolve slowly. But this probably doesn't matter.

Secondly, I recommend writing a 2D vector class/struct with a set of basic functions such as addition, subtraction, scaling, magnitude, dot product, cross product. If you haven't already done so, that is. It makes life much easier when dealing with these problems.

Thirdly, you don't need to worry about KE, rather total momentum (m * v). KE is only for elastic collisions, which are collisions where KE is preserved. These are only a subset of all collisions - and if you have any half-complicated physics preservation of KE will no longer hold.

Here is some code off the top of my head which will preserve momentum (p1, p2 position vectors, v1, v2 velocity vectors):

2Dvector d = p1 - p2;

d = d.normalise() * force_constant;

v1 += d;
v2 -= d;

What this means is that this always keeps momentum constant because it always creates opposing and equal force vectors. It's Newton's third law.

Ulf Magnusson
Member #2,908
November 2002

Ops.. I forgot to mention that (currently) all objects in the game have the same mass. Thus the total speed should be the same before and after the collision

edit:

If the total speed need not be the same before and after the collision (providing the mass is the same for all objects), couldn't that i.e. mean that objects could slowly "gain" more and more speed until the speeds of the objects reaches a unplayable level?

I have yet to take whatever math course dot product is introduced in, I don't know what it is and for :-/

Ulfalizer

orz
Member #565
August 2000

The total speed should NOT be the same before & after. See my previous post. There is no conservation of speed law.

Ulf Magnusson
Member #2,908
November 2002

Heh, if so, maybe my old code is correct after all :)

I guess i could test it with some sample data with a known correct answer..

Ulfalizer

Evert
Member #794
November 2000
avatar

Quote:

The total speed should NOT be the same before & after. See my previous post. There is no conservation of speed law.

There is if all objects have equal mass, and that is the case he was refering to, if I read his post correctly.

orz
Member #565
August 2000

Evert: No, there isn't. There is if all objects have equal mass and all collisions are head on. There is not for glancing collisions.

edit: to clarify, for glancing collisions, there is, but it's for each dimension independantly. i.e. the X component of velocity is conserved, and the Y component of velocity is conserved, but total speed is not. Total speed is only preserved in the special case of head-on collisions. Needless to say, this only applies when masses are equal.
edit2: minor terminology correction

gillius
Member #119
April 2000

orz: this worked for me:

[url http://www.d6.com/users/checker/pdfs/]

It seems [1-4] means there's 4 URLs where you replace [1-4] with a number 1 to 4 inclusive.

Gillius
Gillius's Programming -- https://gillius.org/

Ulf Magnusson
Member #2,908
November 2002

Hmm.. but there are obviously collisions in which the total x momentum and y momentum will be different after the collision, aren't there? (if that's what "conservation" is about)

Like in the following collision:

<code>

  /\   ->
  /   ->   <-   /\
            <-   /

<code>

Assuming the normal in the impact point gets a 45 angle, the leftmost object will continue straight up and the rightmost straight down

hmm..

Ulfalizer

Evert
Member #794
November 2000
avatar

Quote:

Evert: No, there isn't. There is if all objects have equal mass and all collisions are head on. There is not for glancing collisions.

Conservation of momentum says that:

sum_i p_i = sum_i q_i

(note: p and q are vectors, as are v and u below).
where i labels the particles in the collision, p_i is the momentum of particle i prior to collision and q_i is the momentum of particle i after collission. The sum runs over all particles.
Now let p_i = m_i v_i and q_i = m_i u_i, where v_i and u_i are the velocities before and after collision respectively.
If all particles have equal mass (say m), then m_i = m for all i and the sum reduces to

m sum_i v_i = m sum_i u_i

and the mass drops out. So yes, if all particles have the same mass, then conservation of momentum is equivalent to the statement that the total (CM) velocity is conserved in the collision.

Actually, that may be a general result (non-relativistically) - I'll need to read back on my newtonian mechanics.

Quote:

edit: to clarify, for glancing collisions, there is, but it's for each dimension independantly. i.e. the X component of velocity is conserved, and the Y component of velocity is conserved, but total speed is not. Total speed is only preserved in the special case of head-on collisions. Needless to say, this only applies when masses are equal.

I'm not sure what you're saying here, but if the x and y components are conserved, then naturally the total velocity is also conserved: if all components of a vector are conserved, then the vector as a whole is conserved.

EDIT:

Quote:

Hmm.. but there are obviously collisions in which the total x momentum and y momentum will be different after the collision, aren't there? (if that's what "conservation" is about)

Yes - in describing collisions that are not head-on, you need to consider conservation of angular momentum as well (see my original post).

 1   2 


Go to: