Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Dark GDK / need help with 2d circle collision physics :(

Author
Message
Neuro Fuzzy
17
Years of Service
User Offline
Joined: 11th Jun 2007
Location:
Posted: 6th Aug 2010 08:38
I've been struggling with this for a while. I dunno if any of you have noticed my n-body sim code anywhere, but I've discovered the collision method I was using is more bullcrap than I thought it was (I knew it was innacurate but not that innacurate), so I've been struggling to find a decent collision algorithm that will preserve momentum and rotational momentum over many steps. I have the physics pretty good, so that the total momentum of the system only changes in the range of 10^-5 or 10^-6 per step... but the rotational velocity of bodies keeps increasing
Meaning, if you have, say, 20 bodies colliding, at first they behave like you would expect, and form an approximate circle... but then - seemingly out of nowhere - the 20 bodies start spinning in one direction, faster and faster until the centripetal force rips the bodies apart, all from nowhere.
Here's the source code:


If you run it (d3d_circle is used, but you could replace that with whatever command you want to draw a dot, circle, or box; the effect is the same), you can see that the total momentum (x and y values are the second to last and last values printed on the top left of the screen) stays close to zero. If you have two bodies collide (click to create one), you can see them behave as expected, even with preserving momentum when they collide. But... as you add more and more, you can see that it all spins out of control!!!
What am i doing wrong? First I find the force on every point, then I update collision on every point, then I update velocity and move every point. I've tried switching the order of those to no avail, and the problem doesn't just occur with objects of differing radius/mass/density, though it happens faster with smaller/denser objects.

I could imagine that when two objects aren't moving/accelerating towards each other in exactly opposite directions, they would slide and this would add to rotational velocity... but i've no clue how to solve this.


Is't life, I ask, is't even prudence, to bore thyself and bore thy students?
Neuro Fuzzy
17
Years of Service
User Offline
Joined: 11th Jun 2007
Location:
Posted: 7th Aug 2010 02:49
I figure I should post some more info on what I have for the physics so far. The following function

adds gravity based on a vector and mass fed in. Explaining the math of it, this is basically newtons law of universal gravitation:
F=G*m1*m2/d^2
in this case, F=G*m1*m2/|d1|^2 x| being the length of vector x)
however, this is two dimensional, so we want a vector with length F in the direction of d (the difference between the two positions)
direction of d = d/|d|
so F in the direction of d=G*m1*m2/|d1|^2 * d/|d|=d*G*m1*m2/|d1|^3
to find the acceleration of body 1, divide by the mass of m1. This cancels out, so...
acc=d*G*m2/|d1|^3
since this is applied to every object, the law every object has an equal and opposite reaction is obeyed (unless you want it not to be).

this function:

handles the velocity changes in a collision between two bodies. Basically, you have an inelastic collision that conserves momentum. An inelastic collision is one that leaves both bodies with the same velocity after the collision, and we also say momentum (velocity times mass) is conserved (momentum before collision=momentum after collision), that means:
v1*m1+v2*m2=(m1+m2)*vf (vf is the final velocity)
or
vf=(v1*m1+v2*m2)/(m1+m2)
That's the case in one dimension. Soo... to expand this to two dimensions, we first zero the velocity in the direction of x (again, x is the direction of object 2 to object 1). So
v1=v1-(v1*x)x
(v1*x is the dot product, but the other x is scalar multiplication)
The collision can be seen in one dimension, if we just apply it in the direction of x. However, v1 and v2 are also vectors. We want their magnitude in direction x, so we just take their dot product.
1d delta v1 = (m1*v1*x+m2*v2*x)/(m1+m2)
2d delta v1 = (m1*v1*x+m2*v2*x)/(m1+m2)x
so
v1=v1-(v1*x)x+(m1*v1*x+m2*v2*x)/(m1+m2)x
or
v1=v1-(v1*x-(m1*v1*x+m2*v2*x)/(m1+m2))x
which is all whats going on in this function.

Now... I'm pretty sure this is where I run into trouble. This:
center.pos+=(r1-d)/2*x;
colObj->center.pos-=(r1-d)/2*x;
makes sure the two objects aren't colliding. The sum of the radii is r1, and d is the distance between the two, so if they are colliding (and if this code is being run, they are), then r1-d is the amount they intersect eachother by. Moving each body half the colliding distance apart makes sure they don't intersect (again, multiplying by x ensures its in the direction of x).
If I take out this code, three bodies colliding works fine, but everything intersects everything!

I'm not really sure what I need to do... Is my momentum preserving velocity collision thingymajig going too far? Do I need to do something with normal forces or changing acceleration? I need to have code that makes sure the bodies don't intersect, because otherwise errors could build up, and you could have bodies in almost the exact same spot... which would be bad.


Is't life, I ask, is't even prudence, to bore thyself and bore thy students?
Dr Tank
15
Years of Service
User Offline
Joined: 1st Apr 2009
Location: Southampton, UK
Posted: 9th Aug 2010 01:51 Edited at: 9th Aug 2010 01:52
I think your problem may be quite simple.

In the stage where you separate overlapping objects, just changing their positions will affect the angular momentum of the system, unless the particles are colliding along a common axis, like the simple 1D problem.

Imagine an ice skater spinning around. She draws her arms in, (like gravity pulling your circles together), and spins around faster. Then your collision system say's "bam your arms are back out again", but she's still spinning around faster. Then her arms come in again and she spins faster and this keeps repeating.

I imagine to fix this, using a centre of mass frame (like
you use for collisions anyway), you could try preserving the angular momentum of this two body system. Maybe the rotational energy. My mechanics is a bit rusty. Basically when you move two circles apart, the component of their velocities about the centre of mass should decrease.
Neuro Fuzzy
17
Years of Service
User Offline
Joined: 11th Jun 2007
Location:
Posted: 9th Aug 2010 09:41 Edited at: 9th Aug 2010 21:17
Just looked into that, and I don't think that's the problem. If I change the order things update in, I can make sure that the gravity pulling the circles together isn't calculated when they are intersecting each other. When that happens, the rotation problem doesn't seem to occur, but another problem is noticeable [edit] (when I also disable collision :X) [/edit]: the objects keep moving towards each other. For two bodies colliding, this happens (each picture is another five seconds or so).

So... they keep moving towards each other when they're colliding, just very slowly. A similar thing happens with three bodies colliding.
The interesting case is with four bodies colliding like this:

the two bodies that aren't colliding move towards each other faster than the ones that are. This means there's a net force acting on the circles... when in reality it should be at a stable equilibrium.

... I think I need to update the normal force of the objects? The thing is I'm not sure of how to do that with objects accelerating and colliding like this.


Is't life, I ask, is't even prudence, to bore thyself and bore thy students?
Diggsey
18
Years of Service
User Offline
Joined: 24th Apr 2006
Location: On this web page.
Posted: 9th Aug 2010 15:09 Edited at: 9th Aug 2010 15:12
If you can calculate the time that two circle will collide at, you can find the first collision, step all of the movements up to that point, calculate the collision, and then find the next soonest collision, etc. until you have exhausted the time-step.

Unless you can perform the collision calculation at the exact point in time when it happens you will not get an accurate result.

There is also the problem that acceleration isn't constant across the time-step, making the simulation inaccurate to start with.

[b]
Neuro Fuzzy
17
Years of Service
User Offline
Joined: 11th Jun 2007
Location:
Posted: 9th Aug 2010 21:35 Edited at: 9th Aug 2010 22:54
Quote: "There is also the problem that acceleration isn't constant across the time-step, making the simulation inaccurate to start with.
"

yeah... my dad started asking me numerical analysis questions about this >.>

Quote: "If you can calculate the time that two circle will collide at, you can find the first collision, step all of the movements up to that point, calculate the collision, and then find the next soonest collision, etc. until you have exhausted the time-step."

That sounds... scary... and I don't think I can afford for collision to be that computationally expensive.

I'm pretty sure that my problem is that forces don't cancel out... so bodies are trying to accelerate towards each other, and the velocities are partially canceling out, and the position check is handling the rest (which is bad). After a lot of thought, I think my problems can be solved with the statement: "If two objects will be colliding next time step, their acceleration in direction x will be the same" where x is the vector from one object to another.

But... I think I'll have to write a collision solver for this...

[edit]
yeah, I'm pretty sure I do need to write a collision solver for this. I changed the collision routine so that for each two particles colliding, the acceleration would be the same in the direction they were colliding (with no prediction of whether they would be colliding next time step). This works fine for a couple bodies colliding, but it only ensures the acceleration is the same for the last two bodies checked. The more you iterate this check before updating it, the more accurate your result will be, but that's a lot slower than using a collision solver.


Is't life, I ask, is't even prudence, to bore thyself and bore thy students?

Login to post a reply

Server time is: 2024-07-02 09:32:35
Your offset time is: 2024-07-02 09:32:35