Does friction work with balls on a plane?

First off — fantastic work with nphysics/ncollide/nalgebra. I’m learning so much about physics and geometry from the docs. I am indebted to the rustsim developers, and M. Crozet in particular.

Now to my question: does friction slow down balls? In a minimal test:

  • I place a cube on a plane and impulse it along the X axis. The cube slides to a halt.
  • I place a ball on a plane and impulse it along the X axis. The ball rolls forever along the positive X axis.

It would be understandable to me if the physics engine were not computing any friction, as the contact surface of a sphere and plane is infinitesimal. But my use-case is for simulating billiards, in which such infinite movement is undesirable.

Are there any recommended ways of getting a ball rolling on a plane to slow to a halt? I’m quite open to any ideas here.

Perhaps, for example, I could coerce the engine into treating the ball as being a few millimeters below the surface of the plane, so as to impart some friction? If this idea would work, how would I go about doing it?

Sorry if this is a noob question! It’s my first time using a physics engine like this one.

Hi!

Glad those crates are useful to you!
The reason why the ball will not slow down is because nphysics does not supports rolling friction yet (i.e. the loss of velocity due to the fact that real-life balls are subjected to deformation when they roll). Adding rolling friction to nphysics will be considered (I’ve created an issue), but will probably not be done for some times.

Perhaps, for example, I could coerce the engine into treating the ball as being a few millimeters below the surface of the plane, so as to impart some friction? If this idea would work, how would I go about doing it?

That would not work as only one contact point will be generated, even if there are some penetration.

A workaround that may work is for you to apply a force to the balls that should be affected by the friction. The direction of the force would oppose the ball’s current velocity and its magnitude could be a function of the velocity magnitude (up to some maximum).

That makes sense to me! I came to a similar conclusion shortly after composing this question.

Does this look like a sane way to achieve the workaround you mention?

for ball in &self.balls {
    let body = self.world.rigid_body_mut(*ball).unwrap();
    let angular_velocity = body.velocity().angular;
    let torque = Force::torque_from_vector(
        angular_velocity * self.angular_velocity_drag_coefficient,
    );

    body.apply_force(0, &torque, ForceType::Force, false);
}

Where the angular_velocity_drag_coefficient is a constant like -0.00001?

I’m afraid I must admit that the multiple force methods available to me, as well as the many ways to construct forces/torques, has be a bit baffled. I’m not certain whether the forces should be “local”, or whether they should be applied to a “local point”.

Perhaps related to my issues with properly simulating this dampening, inelastic collisions are not behaving as I would expect them to.

I’ll try to formulate a clear demo tomorrow, but I’m seeing some bizarre (to me) behavior with balls and walls — when a ball comes into contact with a wall (both with restitution = 1), at low enough velocities, the ball stops dead in its tracks.

I’ve disabled sleeping on the ball via .sleep_threshold(None), so my elementary understanding would suggest that it’s impossible for such a perfect inelastic collision to yield such a result, as energy is not being preserved?

Perhaps the collision model has some threshold at which it will make objects “stick”, if their relative velocities are small enough? When I send my ball at an angle against a wall, the ball will slide along the wall rather than bounce off it, not unlike what this user reports:

I suspect I’ve misconfigured one of the constants for this crate. I’ll try to produce a clear test case that you can work with, as I’m sure this stream-of-consciousness is unhelpful. Any case, thanks again for this marvelous set of libraries!

Yes, that sounds like a good way of doing this. There are several way to apply a force or torque, depending on where you apply the force and in which coordinate frame the various parameters are expressed. In your case, you select the right force application method. The local terms mean that the quantity is expressed in the local-space of the body. In your case you are using the angular velocity expressed in world-space, so you should not use the local variants.

Perhaps the collision model has some threshold at which it will make objects “stick”, if their relative velocities are small enough?

There is such a parameter, yes, called restitution_velocity_threshold. This can be changed with: world.integration_parameters_mut().restitution_velocity_threshold = 0.0;.

Disabling sleeping was a good idea by the way.