Adding friction to collision impulse

Started by
5 comments, last by Zviri 12 years, 11 months ago
Hi,

I know this topic was discussed here a few times, and I red all of them, I get the idea, but for some reason I cannot implement it correctly. I'm currently working on a physical simulation which is currently aimed on spheres and their collisions with static object, for example a plane. The collision handling is impulse based and everything works ok without the friction involved. I even have the resting forces correctly implemented using Baraffs papers.

Here is how I do it:


/*
... normal impulse calculations ...
The * operator between vectors is cross product.
*/



Vector3D r1 = collision_point - rigid_body->getCenterOfMassLocation();
Vector3D col_point_vel_rel_new = rigid_body->getLinearVelocity() + (rigid_body->getAngularVelocity() * r1);
Vector3D tangent_vel = col_point_vel_rel_new - (collision_normal * col_point_vel_rel_new.dot(collision_normal));
double tangent_speed = tangent_vel.mag();
Vector3D T = -tangent_vel * (1 / tangent_speed);

Vector3D r1_cross_col_tangent = r1 * T;
matrix_tools::transform(rigid_body->getInertiaTensorInverse(), r1_cross_col_tangent, r1_cross_col_tangent);
double denominator = (1.0 / rigid_body->getMass()) + T.dot(r1_cross_col_tangent * r1);

if (denominator > EPSILON)
{
double impulse_to_reverse = tangent_speed / denominator;
double impulse_from_normal_impulse = normal_impulse_size * rigid_body->getCoefficientOfStaticFrictionWith(entity->getType());

double friction_impulse = (impulse_to_reverse < impulse_from_normal_impulse) ? impulse_to_reverse : (normal_impulse_size * rigid_body->getCoefficientOfDynamicFrictionWith(entity->getType()));
T *= friction_impulse;
rigid_body->setLinearVelocity(rigid_body->getLinearVelocity() + T * (1.0 / rigid_body->getMass()));
rigid_body->setAngularMomentum(rigid_body->getAngularMomentum() + r1 * T);

}



The idea behind this is that, if I the tangential impulse is smaller than the normal_impulse*static_friction_coeff, it means that the static friction was not overcamed, hences it equals the tangential impulse which would result in zero tangential velocity. Otherwise the dynamic friction is involved. The inspiration comes from the jiglib project and its creator to which I'm very thankfull.

But with this code, the dynamic friction does not work at all, for example if I drop a ball with no angular momentum to a horizontal plane with some horizontal velocity (after that only gravitation is working), than the impulse_to_reverse is applied to the rigid_body at the first collision, which I think is wrong. And when the second collision occurs the relative tangential velocity is zero hence, no friction is applied anymore.

I use the inertia tensor and its inverse like this:
d13ab810735a04fade8dba1249592fd1.png

I do not transform the inertia tensor to world coors because it's just simple scaling so in my opinion it is not necessary.

Can anyone tell me please what may be the problem? I think I'm missing something basic, and I'm not applying or calculating the impulse correctly, but I'm struggling with this a few day and I'm have no idea what to do.
Thanks.
Advertisement
I *think* your calculation to decide whether or not to apply static friction is missing the coefficient of static friction?

I did something like this:

// check if impulse lies within static friction cone
if tangential velocity > coefficient of static friction * normal impulse mag
{
apply dynamic friction
}
else
{
apply static friction
}

Cheers, Paul.
Hi,

[color="#1C2837"][size="4"]But with this code, the dynamic friction does not work at all, for example if I drop a ball with no angular momentum to a horizontal plane with some horizontal velocity (after that only gravitation is working), than the impulse_to_reverse is applied to the rigid_body at the first collision, which I think is wrong. And when the second collision occurs the relative tangential velocity is zero hence, no friction is applied anymore.
[color="#1C2837"] [/quote]


Well, this makes sense because the same impulse is applied to the linear momentum and the angular momentum as well, so when I take an Euler step (I forget to mention it above), then get the new contact point relative velocity, the tangential part of the linear momentum acts forward, and the tangential part of angular momentum on the point acts backwards so of course it is zero. Am I misinterpreting something here? Or this is the problem of Euler accuracy? Does anybody know how to solve this?

My main goal is to be able to simulate the natural roll of the sphere on a surface, is this the correct approach or should I try something else.

@wildbunny:
Thanks, for the reply, but I think the forces are calculated correctly and the problem is in my simulation engine or using the new impulses.

Thx
@wildbunny:
Thanks, for the reply, but I think the forces are calculated correctly and the problem is in my simulation engine or using the new impulses.

Thx
[/quote]


The forces might be calculated correctly, but if you're applying them at the wrong point it won't help you :)

You need to take the coefficient of static friction into account when deciding between the static and dynamic friction impulse...

Cheers, Paul.


But with this code, the dynamic friction does not work at all, for example if I drop a ball with no angular momentum to a horizontal plane with some horizontal velocity (after that only gravitation is working), than the impulse_to_reverse is applied to the rigid_body at the first collision, which I think is wrong.


It's not necessarily wrong - it all depends on the magnitude of the horizontal velocity, the coefficient of static friction and the speed at which it vertically hits the plane. If the horizontal speed is small enough, then the friction is indeed enough to bring the contact point to a standstill. The fact that the relative velocity is zero on the second bounce strongly suggests your maths implementation is right anyway. Try increasing the velocity (or decreasing the static friction coefficient, and/or lowering the initial drop height) and you should find that at some point it starts to slip on the first bounce.


I'm pretty sure the logic for the static/dynamic friction is correct.

(Thanks for the message btw)


I'm not sure your maths is right (but I haven't checked it very thoroughly)
For example you don't use the intertia tensor in the denominator calculation (which isn't such a big issue as it should be the identity matrix times a scalar)
Also you don't show how you calculated the normal impulse and you don't apply it to the body before/after the tangential impulse.

The general concepts are right though:
Calculate the normal impulse (and apply it, this won't affect the tangential velocity as the two are independent for a sphere)
Apply the coefficient of friction times the normal impulse tangentially (if it would cause the tangential velocity to reverse apply an impulse which causes the velocity to go to zero instead)

It is perfectly reasonable for an impulse to be applied at the first collision (although it is not rotating there is still a relative tangential velocity)
and it is also acceptable that the relative tangential velocity could be zero by the second collision.

If you want to deal with non-spherical shapes things become more complicated, check out for one way to deal with friction:
http://www.euclidean...rianMirtich.pdf
I wrote some source code here:
http://www.euclidean...sWithFriction.c
It can be easily modified to simulate a ball bouncing for comparison to your simulation.

It's not necessarily wrong - it all depends on the magnitude of the horizontal velocity, the coefficient of static friction and the speed at which it vertically hits the plane. If the horizontal speed is small enough, then the friction is indeed enough to bring the contact point to a standstill. The fact that the relative velocity is zero on the second bounce strongly suggests your maths implementation is right anyway. Try increasing the velocity (or decreasing the static friction coefficient, and/or lowering the initial drop height) and you should find that at some point it starts to slip on the first bounce.


Actually, you are right here, it was mostly the problem of setting correctly the values, of the gravity, frictions and the inertia tensor.


I'm not sure your maths is right (but I haven't checked it very thoroughly)
For example you don't use the intertia tensor in the denominator calculation (which isn't such a big issue as it should be the identity matrix times a scalar)
Also you don't show how you calculated the normal impulse and you don't apply it to the body before/after the tangential impulse.
[/quote]

If you look closely I use the inertia tensor to compute the denominator, its the transform method used before, just my implementation of matrices is a bit unhandy.


The rest is as you all said, I finally made it work, so thank you all.


This topic is closed to new replies.

Advertisement