Accessing/Calculating inertia tensors

Post Reply
KodoCoder
Posts: 10
Joined: Sat Aug 16, 2014 12:40 am

Accessing/Calculating inertia tensors

Post by KodoCoder »

Hey all,

Sorry if this is a really basic question, but I've been trying to figure this out for a bit now, and I thought I could save myself some time by asking y'all. The best info I've found from searching this site came from this issue topic (https://code.google.com/p/bullet/issues/detail?id=413), but it only gives an outline on how to do what I want to.

There are two problems that I'm coming across, although I realize I might be coming at this problem from the wrong way.

1):
I'm trying to get the inertia tensor for a btRigidBody/btCollisionShape in a hinge joint. I'm using hinge_pointer->getRigidBodyA().getCollisionShape() to get at the btCollisionShape, and that compiles fine; but when I try to call calculateLocalInertia() from that btCollisionShape my code doesn't compile. Do I need to call calculateLocalInertia() from a specific shape (i.e. btSpereShape)? If so, how do I do that?

2):
Even if I could get the above working, I don't know what I do once I use calculateLocalInertia(), because from the documentation it looks like it doesn't output anything--it only sets the internal 'inertia' variable.

Code: Select all

65 void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
66 {
67  btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin();
68  inertia.setValue(elem,elem,elem);
69 
70 }


How would I access this variable? I want to use it to help modulate the force used by the hinge's motor.

To be clear, all I'm trying to do is calculate or access a btCollisionShape's inertia tensor at a given time-step; so if the above attempt makes no sense to you, please disregard that and point me in the direction of the proper way to get at the inertia.

Thank you for your time,
Josh
dern23
Posts: 26
Joined: Thu Oct 04, 2012 1:58 pm

Re: Accessing/Calculating inertia tensors

Post by dern23 »

1. If your code doesn't compile, you should be able to figure out why from the error message if you are proficient in C++, but that leads to number 2...

2. There's no output variable in that function yes, but the second argument in the method signature is passed by reference so when the variable inertia is set, the actual object in memory that is operated on is whatever the method caller passed to it, see http://en.wikipedia.org/wiki/Reference_%28C%2B%2B%29. This is a fairly common idiom in C++ (and in C with pointers instead); the fact that you weren't aware of them suggests that it might be wise to invest a little bit of time refreshing yourself on the finer points of C++ before delving into a project like Bullet. Don't worry too much about templates, they are thankfully used sparingly in Bullet, mainly for container classes where it actually make sense to use them. I recommend http://www.cplusplus.com/doc/tutorial/ to get started and http://www.parashift.com/c++-faq/ is good for clearing up any confusion you might have.

About the inertia tensor, that is only calculated for the derived class, btRigidBody. You can get a constant reference to it's inverse from the public method btRigidBody::getInvInertiaTensorWorld(); to get the tensor itself simply chain in a call to btMatrix3x3::inverse(), as in:

Code: Select all

btRigidBody* body;
// Initialize body somehow
btMatrix3x3 inertiaTensor = body->getInvInertiaTensorWorld().inverse();
KodoCoder
Posts: 10
Joined: Sat Aug 16, 2014 12:40 am

Re: Accessing/Calculating inertia tensors

Post by KodoCoder »

Hey dern23,

Thanks for your help, especially the C++ references. I know it's not the normal ideal, but I am working on a project in Bullet without having a firm grasp on the fundementals of C++. I find trial-by-fire is a good way for me to learn, as there are too many nuances for me to deal with in many new languages (especially C++), and by having a definite project I am forced to deal with specific ones--and this makes that knowledge stick more readily in my mind. This does create the problem that there are some gaps in my basic understanding of the language (such as this use of references), but luckily there are many people who are able to point me in the right direction when I get stuck, such as yourself.

I found a difference between values of the inertia tensor from joint->getRigidBodyA.getInvInertiaTensorWorld().inverse() and from a btVector3 I set using joint->getRigidBodyA().getCollisionShape()->calculateLocalInertia(1, inertia).

Some of the print-out I got. The single rows are the inertia vectors from calculateLocalInertia() and the triple rows are the matrices from getInvInertiaTensorWorld().inverse():
One TimeStep
(0.343333, 0.343333, 0.000000)

((0.341537, -0.008606, 0.022439)
(-0.008606, 0.302105, 0.107502)
(0.022439, 0.107502, 0.063025))

Another TimeStep
(0.346667, 0.666667, 0.000000)

((0.349021, 0.025059, -0.010957)
(0.025059, 0.613333, -0.116595)
(-0.010957, -0.116595, 0.397646))
Is this difference due to the bodies not being aligned with the "principal basis about which the tensor is diagonal" (as duscussed in the first comment here [https://code.google.com/p/bullet/issues/detail?id=413])? Both inertia variables are calculated within the same timestep, so I know that shouldn't be a confounding factor.

Thanks again,
Josh
dern23
Posts: 26
Joined: Thu Oct 04, 2012 1:58 pm

Re: Accessing/Calculating inertia tensors

Post by dern23 »

No worries, I did the same thing actually (Bullet was one of the first C++ project I delved into as well, learned it on the way). As you're quickly finding out there's a lot of little nuances with the language that can trip up a newcomer; the problem is compounded when looking at other people's code, because while even veterans will typically only use a subset of the language's features, everyone's particular subset is slightly different. That's why Bullet code doesn't look like OGRE code for instance, or heaven forbid Boost (not withstanding style differences, like white-space count, bracket placement, etc.), even though all are perfectly valid C++.

The difference in values in the matrices stem from the fact that the method I gave you returns the world-space inertia tensor, and the one you used returns the diagonal of the local-space tensor in a btVector3. If you have any experience in graphics then those terms should be familiar to you. If not check this out for an explanation http://answers.unity3d.com/questions/31 ... space.html. Basically it doesn't matter too much what frame of reference you do your calculations in, as long as it's consistent (don't mix local and world space values in the same equation). To transform a world space vector into a bodies local space, simply multiply by it's inverse world transform, i.e.

Code: Select all

btVector3 worldPoint(5, 5, 5);
btVector3 localpoint = body->getWorldTransform().inverse() * worldPoint;
And the other way

Code: Select all

btVector3 localpoint (5, 5, 5);
btVector3 worldPoint= body->getWorldTransform() * localpoint ;
Hope this helps!
dern23
Posts: 26
Joined: Thu Oct 04, 2012 1:58 pm

Re: Accessing/Calculating inertia tensors

Post by dern23 »

How would I access this variable? I want to use it to help modulate the force used by the hinge's motor.
Just a quick word of caution, be very careful when trying to manually modify motor forces. If you add them in directly via btRigidBody::addForce/addTorque, you may end up with instability due to the fact that Bullet uses a semi-implicit integrator, meaning external forces are not necessarily stable. However, constraint forces are always stable (see https://code.google.com/p/box2d/downloa ... f&can=2&q=), so make sure to use the hinge's existing motor interface for any experimentation.
Post Reply