NVIDIAGameWorks/PhysX

Pushing bodies at specific positions - torque vs velocity (extensions)

RobertMtx opened this issue · 10 comments

While looking at the extensions method to apply forces to a body at a specific position, it looks like the routine doesn't apply velocity the way one would expect. I'm the furthest thing you can imagine from a physics expert, but I believe the point at which you push an object determines how far it moves, right? For example, if I push an object into the air from the very edge, it will spin around, but won't go very high. Whereas if I push it up from its very center point, it won't spin much, and will travel much further up. The point of contact determines how much of the force is converted to torque, and how much remains velocity.

It doesn't look like the dynamic body extension method applies velocity this way:

const PxTransform globalPose = body.getGlobalPose();
const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p);

const PxVec3 torque = (pos - centerOfMass).cross(force);
body.addForce(force, mode, wakeup);
body.addTorque(torque, mode, wakeup);

Unless I'm mistaken, it seems to convert force into torque correctly, but it leaves all of the force in the resulting velocity, which makes objects travel the same distance, regardless of the contact point.

Am I misunderstanding the code? Or is there perhaps a more advanced version of this method? Am I correct in assuming that we can just measure how much torque is being applied, then dot-product-scale that from the force? Or does that have some strange side effect that is difficult to overcome, and it was simplified as a result?

Thanks for any information!

Edit: I've found source code for similar functions for three different projects, and all of them do it this same way. So either everyone is doing it wrong, or I'm missing something obvious, and I would sooner believe the latter. But if anyone can point me to what it is I'm missing, that would be great. Maybe this has something to do with the length of time the force is being applied? IE, if pushing an object from the very edge, the amount of time we push on it decreases as compared to pushing it in the center? I realize this question is turning more into a physics lesson, but I still appreciate any assistance understanding this.

The code in PhysX is actually correct. A force applied to any part of a rigid body causes the same linear acceleration. The location that the force was applied relative to the centre of rotation causes a torque to be applied. The is proportional to the cross product of the force with the offset from the COM.

We can confirm this by an example of you and a friend lifting up a desk with each at a different end of the desk. The forces you each apply at either end of the desk are able to fully lift the desk. The torques you each cause by lifting the desk cancel each other out, and the weight that you are each lifting is roughly half the mass of the desk (assuming you are standing on a horizontal surface - the story changes if there is an incline involved where the weight distribution would not be even between each of you). However, regardless of the distribution, if you were to measure the net forces that you are both applying to stop the desk from falling under gravity, these would all sum up to the same value regardless of your relative configurations along the desk or how it was oriented.

However, as noticed, it's much easier to pick up a heavy object at one end than near the COM. It requires less force, and this is because the effective mass of the body at a given point on the body varies. In a classic rigid body model, we can define this effective mass as 1/(1/m + I^-1*rXn.dot(rXn), where rXn is (pos - centerOfMass).cross(forceDirection) and I^-1 is the inverse inertia tensor of the body. If (pos-centerOfMass).cross(forceDirection) is zero, then the effective mass is m - this happens when the force is applied either at the COM, or the line of action passes through the COM. However, in cases where this is not the case, the effective mass of the body at that point is less than m, and with very long objects, it can be significantly less than m.

I appreciate your attempt to explain this to me, but I feel like I'm still missing something. If you were to place a long rectangular object on a surface, such as a ruler, then briefly tap it on one corner, it will just spin around, but barely move anywhere. But if you were to tap it again near the center of the ruler, it will not spin much at all, but travel across the surface. Is that not true? Maybe I'm missing something obvious here.

Thank you again for your explanation.

The force applied between your finger and the ruler is likely to be far larger near the COM than it will be at one of the ends, even though your finger is moving at the same speed. This is because the effective mass of the ruler will be lower towards the ends of the ruler than near its COM. As the mass is relatively small, you probably don't pick up on this difference, but it's there.

You should feel this difference if you scale up to a larger object like a 100Kg wooden beam resting on the ground. If you attempt to push it near the center of mass, it's really heavy and hard to move. If you push as hard as you can, you may just about be able to move it, but it won't move much. If you go towards one of the ends and try to push, you should be able to move it by pushing at the ends, but it will mostly rotate while its center doesn't move much if it moves at all. Assuming you are putting maximum effort into pushing the beam in both cases, you're likely applying a similar force at different locations. The change in linear velocity is pretty much the same (its barely moving/not moving linearly), but now there's additionally a torque which causes the wooden beam to rotate.

Yes, that's what I was trying (very poorly) to explain. The amount of force applied to the object depends on how much the point of contact lines up with the center of mass, compared to the force direction. So something like..
linear_force = applied_force * Dot3( applied_force , contact_point - COM );

But the function doesn't seem to take this into consideration. It uses the contact point and center of mass to compute the torque, but not the linear velocity, so I'm just not sure why. Would I need to create a custom function to process it at this level of realism, or is there still something I'm missing? If its just a dot product, I don't understand why its not already there.

My code is not far enough along to test anything, so maybe things will make more sense once I can test it out.

Edit: I'm not the only person confused by this concept. See this poor guy's post: https://www.physicsforums.com/threads/applying-forces-to-a-body-outside-its-center-of-mass.617965/
He was trying to find the same answer, but no one supplied one.

Thanks again for your help!

The addForceAtPoint function in PhysX and the other physics engines is doing the correct thing so there isn't anything that you can do that will be more realistic. The linear acceleration of a body from a given force is the same regardless of where the force is applied on the body. The angular acceleration caused by the force changes depending on where the force is applied.

What does change with the location of a contact is the effective mass. The magnitude of the force or impulse for a given contact is proportional to the effective mass and relative velocity at the contact location, so as the effective mass is reduced, the magnitude of the force/impulse also reduces. This means that different contact forces may be applied at different contact sites to enforce the non-penetration condition, but the way the forces affect linear acceleration and angular acceleration is captured correctly by PhysX and the other rigid body engines you've looked at.

Chris Hecker has a pretty good series on rigid body dynamics that includes the full impulse response formula explanation that can be used to compute the impulse required to respond to a singular rigid body contact here:

https://chrishecker.com/Rigid_Body_Dynamics

This series doesn't by any means give you all the information to be able to write your own stable contact solver, but it does do a pretty good job of explaining the basic formulas that govern equations of motion. It's one of the several resources that I started out with when I was learning about this stuff.

Erin Catto also has a pretty good paper that covers the basics of writing your own contact model:

https://box2d.org/files/ErinCatto_IterativeDynamics_GDC2005.pdf

The approach described by Erin is a pretty good introduction to how physics engines can be implemented.

I appreciate the time you put into helping me understand this. Just to confirm, does this mean I can call this method on a ruler-shaped object in PhysX, on its very edge, and then again behind its COM, and it will move different distances for each, just as in real life?

If all linear velocity just gets fed into a generic value pool the way it seems to, then I'm very interested to learn/understand what happens to make impacts in different locations push the object different distances. But that's just something to look forward to.

Thanks again!

If you apply a force explicitly on the body at different locations, the linear acceleration caused by this force will be the same regardless of where the force is applied. The angular accelerations caused by the force vary depending on the location. This is not physically incorrect. When we have a set of contacts that are able to fully counteract gravity, the sum of the contact forces acting on the body will be equal and opposing to gravitational forces. However, the distribution of forces between the individual contact sites will vary. This is why it is possible for several people to lift a large piece of furniture from different ends in cases where the furniture is too large to lift by a single person. It is usually easiest to lift with a person at each extreme end rather than two people trying to lift really close to the COM because it makes no difference to the force required to lift the thing, but it does make a difference to the torques that are caused by lifting - lifting from the ends makes it much easier to make rotational adjustments than trying to rotate it near the COM.

When simulating collisions, PhysX will compute the appropriate forces to apply at all the contacts based on the equations of motion that are discussed in those links I provided. The angular acceleration is proportional to the computed normal forces and offsets, while the linear acceleration is just proportional to the applied forces and is not influenced by the relative position of the contact.

If you would like to provide your own physically accurate impulses or forces using the addForce methods, you will need to compute the appropriate forces to achieve the result you want. The way PhysX responds to the forces is physically correct, so you trying to do something other than this will not produce accurate results.

If you take a look at the impulse response formula in Chris Hecker's web site, it will show you how to compute forces for a single contact. You can use this as a basis to compute the forces required to achieve any arbitrary change in velocity at a given site, as the underlying requirement to compute these forces is to compute the mass at the sites you are interested in. Given that F=ma. If you know what velocity change you want at a specific site and you know the mass at that site, you can easily compute the magnitude of the force required to achieve that velocity change using F=ma.

If you apply a force explicitly on the body at different locations, the linear acceleration caused by this force will be the same regardless of where the force is applied.

Is this the same behavior (in PhysX) as we see when one body collides with another? For example, can I call this function on a specific impact point and see the same reaction as when an object collides there at that same impact point with the equivalent force?

This can be tested in real life by rolling a marble or heavy coin down a slope (a ruler with a groove in the middle), into something like a pencil or long box. It's a very easy test to setup. Just make sure the ramp is taped onto something so its exactly the same height each time.

It makes sense that an impact would push an object the same amount, regardless of where it hits. But that's not what I'm seeing in these tests. If an object is long enough, and its struck on one end, the other end won't move at all. Some objects, like pencils, will literally spin in place when struck at the edge, without moving anywhere.

I think the confusion here is related to friction. I think the distance that an object moves after being struck depends on where, how much, and what type of friction is holding it in place. I would assume the contact point changes the static friction vs dynamic friction along non-square objects. It makes sense - the struck site starts moving (spinning) right away, but the other end isn't moving at first. That means one end is using static friction, while the other end is using dynamic friction. Depending on how long the object is, the other end of the shape may never break its static friction. And we know that an object using dynamic friction will move further than one using static friction.

Anyway, I'm just rambling on here. Regardless of weather it is friction or not, I'm almost positive that both statements are true - the amount of force applied doesn't depend on the impact site, AND the distance an object moves depends on the impact site.

I'm almost positive that both statements are true - the amount of force applied doesn't depend on the impact site, AND the distance an object moves depends on the impact site.

See the below image showing 3 different configurations of a box attached to a rope.

In all 3 images, the box and rope are in different relative configurations but they have the same underlying mass and inertia. Gravity in this case can be assumed to be downwards.

In each of these 3 images, the rope is supporting a varying amount of the total mass of the box, ranging from a small amount in the top image to the full mass of the box in the bottom image. In these 3 cases, different forces will be being applied between the rope and the box to keep the rope and box attached to each other.

This might seem like a different problem to that of a contact, but the calculation for these forces are exactly the same as the calculation for the contact forces. It's not going to be a constant force in all 3 configurations; the force will change depending on the relative configuration because the effective mass of the box acting on the rope is different in all 3 configurations.

You are absolutely right that when we consider contact problems, there are other factors like friction that influence behaviour, but these are all modelled in PhysX. If you set up a PhysX simulation and let a ball roll down a ramp and hit a can at different locations, it would move exactly how you expect it to move based on your real world observations. It would also be applying forces exactly as you see in the source code. The difference between contacts at the various sites is that it would be applying a different amount of contact forces depending on the location of the contact.

I can only attempt to reassure you that the code that's applying forces to rigid bodies that you enquired about is correct.

swinging_box

That's good enough for me. I probably still have a week or more before I can test at that level, but it sounds promising. I was getting a bit mixed up by confusing impact force with the final motions of objects. If secondary effects like friction are the reason for the differences in travel distance, then it totally makes sense. If you consider these objects being struck in space, where there is little gravity or friction, then its easy to picture an impact moving an object the exact same distance, regardless of where an impact is.

Thanks again for your patience and time!