Incorrect rotation for 'thin/long' objects.

Started by
11 comments, last by Norbo 16 years, 5 months ago
In my physics engine, objects which are not of approximately the same height/length/width (cubelike) develop inaccurate angular velocities. At first, I had assumed I had made an error in my numerical method for finding the inertia tensor and continued working within the bounds of cubelike objects, planning to fix it at a later stage. Now, as I add support objects whose inertia tensors can be evaluated symbolically (spheres, cones, cylinders), I observe the same behavior despite my confidence in the calculation. For testing purposes, I focused on the cylinder case. I calculate the body inertia tensor in the same manner as listed at http://scienceworld.wolfram.com/physics/MomentofInertiaCylinder.html, with a 'minor' difference. As I am developing specifically for the XNA Framework, I am using their Matrix class which is exclusively 4x4. For my implementation, I simply used the 4x4 identity matrix as a base, setting the M11, M22, and M33 fields to the appropriate values (as shown in the link). The body inertia tensor inverse is then calculated based on that, and each frame's inertia tensor is calculated using: myInertiaTensorInverse = rotationMatrix * myBodyInertiaTensorInverse * Matrix.Transpose(rotationMatrix); Video: http://www.bepu-games.com/downloads/video/InertiaTensorQuestionmark.wmv I filmed a test set up with two cylinders of different sizes and the same mass under two different timescales (1 and .25). In each, the iteration count for the iterative solver is very high (100) so the impulse calculation converges accurately. Additionally, the larger, more cubelike cylinder stabilizes quickly after rolling around a little bit, while the smaller cylinder jitters noticably at timescale = 1 as it bounces and attempts to flip around. In both timescales, significant rotational error can be observed after the cylinder falls off the platform. What is the most likely culprit for this bug? As I am not 100% sure, I would like to verify that my 4x4 inertia tensor matrix interpretation is valid, though I have thought of some other possibilities. My current method of moving the simulation forward is a very simple euler integration implementation; as some of the jitter was removed with a lower timestep (more updates per movement), I thought perhaps that changing to an RK4 or other higher level integration method would help alleviate the issue, though I'm not sure it can fully explain the extreme case of spinning after falling off the platform. Another option would be that I have misused the inertia tensor somewhere else in the implementation, outside of contact impulse application (given that it spins inappropriately even when not in contact with any object). This narrows it down to essentially a couple of statements: -As listed above, the inertia tensor inverse update in the forces/velocities update method: myInertiaTensorInverse = rotationMatrix * myBodyInertiaTensorInverse * Matrix.Transpose(rotationMatrix); -And also in the forces/velocities update method: angularVelocity = Vector3.Transform(myAngularMomentum, myInertiaTensorInverse); Any ideas would be greatly appreciated. [Edited by - Norbo on November 4, 2007 10:28:48 PM]
Advertisement
It might be the inertia tensor, but I would also consider a few other possible culprits:

* impulse application (make sure your impulse radius vector is correct, also make sure your units are correct i.e. not angVel += (r x impulse), you need angVel += inverseWorldInertiaTensor * (r x impulse) or angMomentum += (r x impulse)

* keep in mind that since in that video, the cylinders have the same mass, the smaller one will have a much higher density which will affect how it behaves (think balloon vs. bowling ball). So, try setting the masses of the objects to be proportional to their volumes.

* are you using any sort of bias velocity in your impulse application to correct object penetration? make sure that this is not causing your problems. In the video, on the lower speed, it seems like there is less craziness. lower speed -> less penetration -> less penetration correction.
Thanks for the response.

Quote:Original post by Aressera
* impulse application (make sure your impulse radius vector is correct, also make sure your units are correct i.e. not angVel += (r x impulse), you need angVel += inverseWorldInertiaTensor * (r x impulse) or angMomentum += (r x impulse)


I use the latter, angMomentum += (r x impulse), while calculating the angular velocity afterwards using angVel = inverseWorldInertiaTensor * angMomentum. However, the contact impulses are not applied during freefall, so the strange flipping behavior after leaving the platform isn't explicable by the contact impulses.

Quote:Original post by Aressera
* keep in mind that since in that video, the cylinders have the same mass, the smaller one will have a much higher density which will affect how it behaves (think balloon vs. bowling ball). So, try setting the masses of the objects to be proportional to their volumes.


I just tried this test, with the large cylinder having a mass of 1, and the smaller cylinder having a mass of .006944. The small one jittered about, perhaps even more furiously, before jumping off the platform into an illogically quickly rotating deathspin.

A test with masses of 1 and 144 generated similar results, as well.

Quote:Original post by Aressera
* are you using any sort of bias velocity in your impulse application to correct object penetration? make sure that this is not causing your problems. In the video, on the lower speed, it seems like there is less craziness. lower speed -> less penetration -> less penetration correction


That is true, I do use a bias for shallow penetration. However, in essentially all tests not involving a non-cubelike object, the kind of jitter the small cylinder experienced never manifested. I suspect the bias combined with normal contact impulses are being magnified and misused by these non-cubelike objects, causing even a correct and minor impulse to trigger erratic movements. This would seem to support the idea that the inertia tensor is somehow incorrect, and the objects are acting rotationally as if they were a different shape.

Thanks again.
Quote:Original post by Norbo
That is true, I do use a bias for shallow penetration. However, in essentially all tests not involving a non-cubelike object, the kind of jitter the small cylinder experienced never manifested. I suspect the bias combined with normal contact impulses are being magnified and misused by these non-cubelike objects, causing even a correct and minor impulse to trigger erratic movements. This would seem to support the idea that the inertia tensor is somehow incorrect, and the objects are acting rotationally as if they were a different shape.


I've had problems before with jitter due to bias stuff. Are you keeping track of a separate velocity vector for your bias velocities, or are you just applying the biases directly to the object's velocities? you should be doing the former, otherwise objects will bounce around whenever they penetrate. your final velocity calculation should look like this:

velocity = linear + linearBias
angularVelocity = angular + angularBias

basically, bias velocities will not affect the object's movement for more than one frame, and they are set to zero every frame.


I really doubt it is the inertia tensor. Usually if you can't solve a bug related to something directly, the problem lies elsewhere in an indirectly related system.
You do bring up a good point- it doesn't use a separate bias velocity/impulse. I presume what you're suggesting is similar to the split impulses/psuedo velocities discussed by Erin Catto in the GDC 2007 slides? It also appears that on gphysics.com he's put up a bit about Baumgarte and some other relevant methods. The full NGS method seems interesting.

I do need to implement that at some point, but I'm not convinced that it's the sole source of the behavior in the video. Specifically, when the object leaves the platform, it is no longer affected by contact impulses; it is fairly difficult to see in the video, but the mid-air rotation is wildly inaccurate and swings in impossible manners, clearly accelerating and decelerating as if the extra length didn't exist and didn't resist motion.

[Edited by - Norbo on November 5, 2007 1:06:01 AM]
Another possible culprit: what is your integration method for angular velocities->orientation?
Though I don't have access to the specifics at this time (I'll edit this post when I can), it is very simplistic like I mentioned in the first post (state modified by derivative equals result). Could switching to a higher accuracy integration method alone eliminate the entire effect, or are you referring simply to a possible error in the implementation?

I know that there would certainly be some benefit to a 'better' solver, but I am unsure of its extent. Assuming the current implementation is not in some way bugged, could it still be responsible for such immense variations in the particular case of thin/long objects?
I use plain old Euler in my engine and it is very stable, so I don't think the integration method is to blame, just the implementation.
I've implemented a quaternion system similar to the one detailed in http://www.cs.cmu.edu/~baraff/sigcourse/notesd1.pdf by David Baraff on pages 21 and 22.

In the following, 'wait' is the time since the last frame in seconds.
First, I take into account forces to generate the new velocities.

Angular Momentum:
myAngularMomentum = myAngularMomentum + myTorque * wait;
Tensor:
myInertiaTensorInverse = Matrix.Transpose(rotationMatrix) * myBodyInertiaTensorInverse * rotationMatrix;
Angular Velocity:
angularVelocity = Vector3.Transform(myAngularMomentum, myInertiaTensorInverse);

Second, any constraints/contacts are resolved, and finally the rotation is updated:
rotation += ((new Quaternion(angularVelocity * wait, 0)) * .5f) * rotation;
rotation = Quaternion.Normalize(rotation);
rotationMatrix = Matrix.CreateFromQuaternion(rotation);

Does anything in there jump out to you as incorrect? Though, it seems to me that an error within the integration would likely manifest in all objects, but maybe it is simply unnoticable.

[Edited by - Norbo on November 5, 2007 7:01:19 PM]
I'm not particularly familiar with quaternions, so I can't say for certain, but is there any particular reason you are using them over rotation matrices?

at this point, i'm kind of stumped, the error could come from any number of places, and without taking a look at you whole code, i can't say for certain what it is.

This topic is closed to new replies.

Advertisement