• Create Account

Jittering due to gravity and restitution

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

13 replies to this topic

#1Juliean  GDNet+

6202
Like
0Likes
Like

Posted 13 January 2014 - 09:05 AM

Hello,

I've been implementing a 3d physics engine using impulse resolution, following this series of tutorials, porting them to 3d:

http://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-core-engine--2778

Now I'm at a state where I've got the basic collision pair generation and resolution (using friction, mass, restitution), as well as gravity and velocity/position integration, no angular velocity yet. Now I'm experiencing some issues under the following scenario:

I've got a sphere with radius 1 and mass 1 eigther falling straigth on to or lying directly on an AABB with infinte mass. Restitution of both these bodies is 0.75, gravity is 10.0, static and dynamic friction is both 0.1 (but it doesn't have any effect here anyway). Now the issue happens when the sphere has los most of its momentum due to gravity, and should lay quitely on the AABB. Instead, it yitters around quite noticable, obviously due to the gravity pulling it down into the box, which pushes the box out further away then it originally was, causing it to fall down again in the next frame, etc... hope you get the idea. Now, this gets effect gets less noticable the more I turn down the restituation, and completely dissappears once it reaches 0.0f, obivously since the sphere will now loose all its momentum instantly as it hits the AABB. But every other value will cause such a noticable yittering.

Without showing any of my code (I checked a hundred times to ensure that there are no typos and its pretty much equivalent to the one from the tutorial algorithm-wise), is there any solution for this problem? I've already read about the problem of sinking bodies due to gravity and that you should use position correction, but doing so didn't help, and it appears to be a utterly different problem anyways. Any ideas? Or let me know if you'd have to see some code in order to help. Thanks!

#2brucedjones  Members

850
Like
1Likes
Like

Posted 13 January 2014 - 09:49 AM

It sounds like you need to add damping. This is reinforced by your findings with changing the coefficient of restitution. Since both remove energy from the system.

Edited by brucedjones, 13 January 2014 - 09:50 AM.

#3Juliean  GDNet+

6202
Like
0Likes
Like

Posted 13 January 2014 - 10:17 AM

It sounds like you need to add damping. This is reinforced by your findings with changing the coefficient of restitution. Since both remove energy from the system.

Thanks for your suqqestion, however adding damping didn't remove the jittering issue, even when using a huge damping coefficient (like 0.5f) without accounting for the timestep, there is still some jittering (it isn't even anywhere nearly as restricted as the "normal" velocities are. I'm using damping method 2 from this site:

http://www.digitalrune.com/Support/Blog/tabid/719/EntryId/78/Damping-in-Computer-Games.aspx

which in my code basically looks like this:

for(auto pBody : m_vBodies)
{
// c = 0.5f
pBody->m_vVelocity *= (1.0f - c);
}


Is there anything wrong with this form of damping? If not, any other suggestions what I could do?

#4h4tt3n  Members

1917
Like
2Likes
Like

Posted 13 January 2014 - 11:52 AM

The damping you mention seems wrong. It should always apply force along some axis (along the constraint or normal to intersection), not just remove a fraction of all movement per game loop.

The folowing equation will compute the exact force to make your object align with the floor and come to rest in one step:

correction force = - ( object mass / timestep^2 ) * overlap distance along axis * coefficient - ( object mass / timestep ) * velocity along axis * coefficient

If you are dealing with impulses or velocities then the equation should be:

Correction impulse = - ( object mass / timestep ) * overlap distance along axis * coefficient - velocity along axis * coefficient

The coefficient is just a number between 0 and 1 determining how soft / rigid you want it to behave. Setting the coefficients to 1 will do the job in 1 loop, but may also introduce instability if there are several objects interacting at one time. Setting them between 0.5 and 0.05 should work just fine.

Cheers,

Mike

Edited by h4tt3n, 13 January 2014 - 11:56 AM.

#5Juliean  GDNet+

6202
Like
0Likes
Like

Posted 13 January 2014 - 05:17 PM

The damping you mention seems wrong. It should always apply force along some axis (along the constraint or normal to intersection), not just remove a fraction of all movement per game loop.

The folowing equation will compute the exact force to make your object align with the floor and come to rest in one step:

Thanks for that hint, and I tried to implemented your second correction impulse, but for some reason I'm still not getting the results I expect. When I set the coefficient to 0.5f, the sphere immediately stops when hitting the floor once, with something around 0.25f it will only bounce 2-3 times (instead of 7-10 as it was used to), and after that still jitter a little, and if I choose 0.05f, jittering is still visible, though somewhat reduced. I'm not to sure if I implemented it correctly, so I'd be glad if you could help me out some more regarding that:

Am I right to assume that this correction impulse should go where the collison resolution happens, in detail after I applied the impulse to seperate the two objects? If so, am I also right to assume that this correction impulse should simply be added to the objects velocity afterwards? See my code for example:

//... calculate everything need for the seperation impulse

const math::Vector3 vVelocityA = m_pBodyA->GetInvMass() * vImpulse;
m_pBodyA->m_vVelocity -= vVelocityA;

/********************************************
* Damping
*********************************************/

const float coefficient = 0.25f;
math::Vector3 vCorrectionA = -(m_pBodyA->GetInvMass() * (1.0f / 60.0f)) * m_penetration * m_vNormal * coefficient - vVelocityA * coefficient;
m_pBodyA->m_vVelocity += vCorrectionA;


I explicitely left out the impulse for the second body, since it is of no concern for this example. Does that code, as well as my explanation, look right to you, or is there something that should have been done differently?

#6h4tt3n  Members

1917
Like
0Likes
Like

Posted 14 January 2014 - 12:50 AM

Hello Juliean,

Sorry, I wasn't beeing too clear in my explanation. The two coefficients aren't necessarily the same number. The first one is the stiffness coefficient, the secon one the damping coefficient.

correction impulse = - ( object mass / timestep ) * overlap distance along axis * stiffness coefficient - velocity along axis * damping coefficient

or shorthand:

Jc = -(m / dt ) x Ck - v Cd

If you set Ck and Cd to 1.0 the object should stop completely when it hits the floor. If Ck is 1.0 and Cd is 0.0 it should keep bouncing indefinitely.

Cheers,

Mike

#7Juliean  GDNet+

6202
Like
0Likes
Like

Posted 14 January 2014 - 06:58 AM

Sorry, I wasn't beeing too clear in my explanation. The two coefficients aren't necessarily the same number. The first one is the stiffness coefficient, the secon one the damping coefficient.

Ah, I see, since both were named the same I assumed they where the same variable Now it makes more sense.

But I'm still having some trouble getting some acceptable results. If I set stiffness to 1.0f and damping to 0.5f, the sphere already stops almost instantly. All smaller values, like 0.25f, already reduce the bouncing of the sphere to virtually nothing (from e.g. ~10 meters on first bounce without the daming, to ~2 with 0.25). In addition, even a large value like 0.5f will still leave some jittering, which you notice at least if you stick your face up to the spheres. Everything less does reduce the jitter, but by an amount that still leaves it noticable unless you go to a birds-eye perspective. Do you think there is something wrong with my implementation? I mean, I have found a way to remove the jittering, but it is a little hacky:

void World::IntegrateVelocities(double dt)
{
// TODO: fix for gravities that are set in other directions than straigth down/up the y-axis
const float bias = abs(m_vGravity.y * 0.05f);

for(auto pBody : m_vBodies)
{
if(pBody->GetInvMass() == 0.0f)
continue;

// fixes gravity jittering
// TODO: find out better, less hacky and more physical based solution
if(pBody->m_vVelocity.y > 0.0f)
pBody->m_transform.vPosition += math::Vector3(pBody->m_vVelocity.x, max(0.0f, pBody->m_vVelocity.y - bias), pBody->m_vVelocity.z) * dt;
else if(pBody->m_vVelocity.y < 0.0f)
pBody->m_transform.vPosition += math::Vector3(pBody->m_vVelocity.x, min(0.0f, pBody->m_vVelocity.y + bias), pBody->m_vVelocity.z) * dt;
}
}


What this pretty much does is bias or clamp the velocity along the x-axis by 5% of the gravity on integration, which seems to be the approximate value in which range the bodies jitter around, so that the bodies only begin to move due to gravity after it extents this bias. This works without noticably changing the way the bodies move/bounce, though it does naturally slightly change their positions. Don't get me wrong, I'd much rather have a less-hacky solution, but would you consider this something that is viable in a pyhsics engine (given that it works best so far without altering the simulation by a noticable amount), or do you think this can bite me in the a** later in the progress?

Edited by Juliean, 14 January 2014 - 06:58 AM.

#8brucedjones  Members

850
Like
0Likes
Like

Posted 14 January 2014 - 09:07 AM

Are you still applying restitution? and are you modifying the position manually after collision has occured?

Assuming your body is spherical and simply falling downward, then the body colliding with the surface is essentially a 1d mass-spring-damper. It is possible to model such a system, and achieve a steady (rest) state. If I were you, I would begin by implementing such a model to see how it should work. This would give you a minimum working example which you can base your collision model on.

Check out wikipedia for reference material.

#9Juliean  GDNet+

6202
Like
0Likes
Like

Posted 14 January 2014 - 03:31 PM

Are you still applying restitution? and are you modifying the position manually after collision has occured?

Yes, I am applying restitution, in the same amount I used before. I actually found the solution why the article I was reading didn't have the problem, they where calculating a bias much similar than me, and set the restitution to 0.0f if velocity went under a certain amount.

    // Determine if we should perform a resting collision or not
// The idea is if the only thing moving this object is gravity,
// then the collision should be performed without any restitution
if(rv.LenSqr( ) < (dt * gravity).LenSqr( ) + EPSILON)
e = 0.0f;


After going through the even more, I think I've come to the conclusion that damping wouldn't be going to help anyway. From what I understand, dampings main purpose is to reduce the amount of energy of a body over time (very simplified), am I right? Now the problem with the jittering comes from the fact that the small amount of gravity that is applied each frame will push the body a certain amount higher over the body, just by a tiny amount, almost equal to the negative gravity. In the next frame, gravity will drag the body down again, moving it to a slighly different position than it was before. This happens frame by frame, the body pretty much alternates between rising and falling by a very small amount around the contact point of the sphere with the floor. (e.g. in the range of -0.05 to 0.05). Now in my limited understanding of the subject, in order for damping to remove this effect, it would need to be so strong that it would cancel out most of the other forces on the body (pretty much which I am experience with the damping implementation by h4tt3n). Am I right to assume so, or did I miss anything?

Edited by Juliean, 14 January 2014 - 03:32 PM.

#10h4tt3n  Members

1917
Like
0Likes
Like

Posted 15 January 2014 - 04:22 AM

Are you still applying restitution? and are you modifying the position manually after collision has occured?

Assuming your body is spherical and simply falling downward, then the body colliding with the surface is essentially a 1d mass-spring-damper. It is possible to model such a system, and achieve a steady (rest) state. If I were you, I would begin by implementing such a model to see how it should work. This would give you a minimum working example which you can base your collision model on.

Check out wikipedia for reference material.

The method I described is such a mass-spring-damper, and it works very well in my simulations. I am using it on force level, not velocity level, but it should react just the same. I think you might get rid of the jittering if you apply gravity as a downward velocity beofre calculating spring forces, then the damper would cancel it out.

Cheers,

Mike

#11brucedjones  Members

850
Like
0Likes
Like

Posted 15 January 2014 - 08:47 AM

Restitution is a fudge for damping, they both seek to remove energy from the system so that stability is achieved. You should use one or the other, not both.

Your interpretation of how gravity should be applied appears to be flawed. Gravity is a force that acts on the body, your collision should produce another force. You sum these forces to find the acceleration of your body. Assuming you have damping, after a certain number of bounces the force due to gravity and the force due to contact will cancel and the body will be at rest.

#12Juliean  GDNet+

6202
Like
0Likes
Like

Posted 15 January 2014 - 09:07 AM

Your interpretation of how gravity should be applied appears to be flawed. Gravity is a force that acts on the body, your collision should produce another force. You sum these forces to find the acceleration of your body. Assuming you have damping, after a certain number of bounces the force due to gravity and the force due to contact will cancel and the body will be at rest.

Apologies, my explanation may appear flawed, but I do apply gravity just like you say I should. The jittering arises because of these forces. Say the body is in resting state, and gravity will apply a force making it collide with the body. For the sake of clarity, say this force is exactly (0.0f, -0.05f, 0.0f). Now on collision, due to the restitution choosen, another impulse in the reverse direction is applied - I don't have the exact values, but lets say its somewhere around (0.0f, 0.15f, 0.0f). Now combine those, and the final velocity of the object is (0.0f, 0.1f, 0.0f), which means the body will rise. In the next two frames, the body will fall unhindered, until in the third frame gravity drags it into the floor again, resulting in the force that is pushing it up by (0.0, 0.1f, 0.0f) again, and repeats. The issue is a bit different, but I can't test it right now. Do you still get where I'm going at? The jittering is not caused by the accumulated velocity, but by the initial gravtiy that is added every frame, causing the floor to push the sphere out by a noticable amount due to its restitution. Therefore the body will never come to rest, because even if it has a velocity of exaclty 0.0f, the next step gravity will start the process all over again. As I said, in the "impulse engine" from the tutorial I was following, they cancelled this effect out by setting the restitution to 0 if the velocity is smaller than one-step gravtiy. How is a normal damping/restitution-system supposed to cancel this out anyway?

#13brucedjones  Members

850
Like
0Likes
Like

Posted 15 January 2014 - 10:07 PM

From that link, and your explanation. It looks like you've worked out how to cancel the jittering when using this restitution technique.

If you were to use a damping system, you would treat your boundary surface as a compressive spring-damper. As the body overlaps the surface you calculate the magnitude of the overlap, the force you apply to the body is then calculated as though you have compressed a spring-damper. So you work out the overlap, then using the stiffness and damping coefficient of the surface you would calculate a proportionate force to be applied to the body.

When using such a system, the body and surface would overlap slightly while the body is at rest. But the overlap would be negligible. This type of collision handling is commonly used in the Discrete Element Method. I am not sure how common it is in Games, as I haven't dug into any of the physics libraries. Though it is how I would implement it. Collision detection tends to be far more expensive then the actual collision handling so you can afford to use a realistic solution in this case

#14Shannon Barber  Moderators

1657
Like
0Likes
Like

Posted 01 February 2014 - 12:11 PM

Below a certain threshold between the objects, you cease treating them like separate objects.

Instead the colliding object becomes a sub-node on the larger object's tree.

Edited by Shannon Barber, 01 February 2014 - 12:11 PM.

- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.