- Home /
How do I programmatically Combine Inertia Tensors?
Hello!
I'm making a complex compound "ship" that I'm trying to simulate with a certain level of accuracy. The ship maneuvers in an atmospheric zero-G environment and is maneuvered through thrusters and aerodynamic control surfaces.
Ultimately I want the ship to handle as if it were the sum of its parts. In other words, the overall center of gravity and moment of inertia should be relative to the placement, size, and mass of each of the individual parts of the ship. Generator, engine, cockpit, fuel tanks, frame parts, etc.
Now, in Unity, I realize you can have multiple colliders as children of a rigidbody and Unity automatically calculates the COG and InertiaTensor for the rigidbody based on all the colliders, but with one major drawback. It assumes that all the colliders have exactly the same density. It spreads all the mass of the rigidbody out evenly across the combined volumes of all the colliders. As a result, something like an empty carbon fiber cockpit would way as much as an engine of the same size, made entirely of metal.
One solution that I'm using right now is to have a bunch of rigidbodies connected by fixed joints, but this is less than optimal in many ways (especially when you figure networking into the mix)
The only solution I can think of is to manually figure the inertia tensor myself, but I'm having one major problem:
All of the textbooks and documents and, well, everything that I can find online everywhere speaks of inertia tensors as a 3x3 array, but Unity describes them as a combination of a vector and a Quaternion rotation! Waugh!
Anyone have a clue on this? Either on how to translate the vector+rotation format into a matrix and then back again, or how to do the math using the existing structure?
Answer by iwaldrop · Feb 13, 2013 at 04:51 AM
As a matter of fact, one of the values in a tensor matrix is it's rotation, as demonstrated here. In Unity, what you'll probably want to do is grab the rotation as a Vector3 using eulerAngles. This way you can use the traditional math, but convert the rotation back and forth for Unity.
Hope that helps.
Also of use may be this page, but it sounds like you've probably already done your homework!
Partially helpful, but is that the link you meant to post? I can't really see where rotation comes in to any of those examples, as they're all symmetrical objects aligned with the their principal axis, and thus there's no rotation involved anywhere (all the $$anonymous$$atrix values are zero except the diagonals)
Sorry if I sound like I only have half-a-clue. I've done my homework but much of it is going over my head, admittedly. It's been awhile since I've done much of this heavier math, and until now Unity has sheltered me from needing to get back into it!
I'm in pretty well exactly the same position as you described, right down to the space ship scenario lol. Unfortunately, I don't have the answer to the main question, but I may be able to provide an answer to how inertia tensors work in unity.
As I understand it, the inertial tensor in a rigidbody is represented by a cube which is transformed to best describe the objects mass distribution. The variables centerOf$$anonymous$$ass controls the cubes translation, inertiaTensorRotation it's rotation, and inertiaTensor it's scale.
For people in this scenario, you should probably just try computing this cube yourself. Even if it's not perfect, it will still be much less derpy looking than using joints connecting multiple rigidbodies.
If profNoobland is correct then you should be able to create the matrix for the inertia tensor with:
$$anonymous$$atrix4x4 m = $$anonymous$$atrix4x4.TRS(rigidbody.com, rigidbody.inertiaTensorRotation,rigidbody.inertiaTensor);
This is a 4x4 matrix in homogeneous coordinates, not a 3x3 matrix in cartesian coordinates. But it the center of mass is at 0,0,0 then the 3x3 matrix should just be the top left 3x3 part of the 4x4 matrix. I have not tested this myself, but you could try this on some shapes where you know what the inertia matrix should be to see if it generates the correct matrix.
I'm finally revisiting this problem and have a closer understanding to it, but am still missing a piece or two. Here's my understanding so far: a) Unity provides a diagonal inertia tensor matrix relative to its principal axis of rotation b) Unity provides said principal axis c) I need them all relative to the same axis (i.e. world space) in order to use the parallel axis theorem to scale them and combine them d) once combined, I need to extrapolate the new principal axes and re-diagonalize the new tensor matrix.
so something like 1) find the tensors relative to world space (rotate them by the principal axis or something?) 2) scale them relative to their distance from the new center of mass with parallel axis theorem 3) add them all together 4) find the new principal axis and its associated diagonalized tensor
It's steps 1 and 4 that I'm trying to work out right now. All the math papers I'm reading are pretty vague on it, or they make assumptions like "it's easier if you can just observe the object and find one of the axes" which... obviously can't be assumed, here. I feel like if I could grok #4, I could work it backwards for #1? I'm getting the feeling it's going to be a bit more complex than just a simple rotation
Your answer
Follow this Question
Related Questions
Wierd Internal Physics problem 1 Answer
How can I detect Actors which will cause the "Compute mesh inertia tensor failed!" error? 1 Answer
Excluding a collider from tensor calculations? 0 Answers
Disable inertia tensor calculations on rigidbody? 0 Answers
Compute the torque needed to rotate an object at a constant rate 3 Answers