## rotation format in bullet physics

pwouik
Posts: 3
Joined: Tue Feb 23, 2021 2:43 pm

### rotation format in bullet physics

Hello, searching in src/BulletDynamics/Dynamics/btRigidBody.cpp, it seems that bullet use a 3D vector for rotation, representing the axis of rotation and the angle with the norm.It seems very practical because it's directly given by a cross product when applying an impulse ,and we can add them to combine them.
What is the name of this,and how can we make a rotation matrix from it?
drleviathan
Posts: 699
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

### Re: rotation format in bullet physics

Bullet stores both position and rotation in a btTransform which is a 4x4 matrix under the hood. You can extract just the rotation part into a normalized btQuaternion which is a 4D "vector". The components of a Quaternion are NOT the normalized_axis + angle, however with some practice you can "eyeball" a Quaternion to get an idea of what the axis and rotation are.

Quaternions are useful because it is relatively easy to do rotation math with them to obtain other rotations. Once you're done with rotation math you would take the finalQuaternion and do something like this:

Code: Select all

``````transform.setRotation(finalQuaternion);
body->setTransform(transform);``````
There are many tutorials about Quaternions online, however I will offer a crash course on them here:

(1) Quaternions in general span all of 4D space, however when it comes to rotations we are only concerned with those Quaternions which live on the surface of the unit hypersphere: centered at the origin with radius = 1.

(2) The subset of Quaternions on the unit hypersphere form a "Group" (research "Group Theory" for more about what this means) under some operator we will call "multiplication". In other words, when you "multiply" two elements in the Group the result is another element of the Group.

(3) There is an isomorphism (sorta) between the Group of unit Quaternions and the Group of Rotations in 3D. In other words, the two Groups behave in the same way under the multiplication operator. This is why unitary Quaternions are so useful in 3D math.

(4) The "sorta" qualifier is there because really there is a 2-to-1 mapping from Quaternion space to Rotations. For each valid Rotation there are two Quaternions that represent it, and these Quaternions are at opposite ends of the hypersphere: Q and -Q. This fact matters sometimes when you're doing interpolation from one Quaternion to another, but usually you can forget about it.

(5) Internally the Quaternion has four elements: <x,y,z,w>. In code: some Quaternion implementations might order them <w,x,y,z> but the btQuaternion ctor which takes four floats orders them <x,y,z,w>. The <x,y,z> components are called the "imaginary" part, similar to the "imaginary number 'i' you learned in high school) but in this case there are three distinct imaginary axes and they are often referred to as <i,j,k>. The <w> component is known as the "real part".

(6) The identity btQuaternion (zero rotation) has the form: <0,0,0,1>

(7) For a rotation of A radians about a normalized axis <X,Y,Z> the corresponding btQuaternion has components: <sX, sY, sZ, c> (and its negative as per item (4)) where: s = sin(A/2) and c=cos(A/2). Knowing this, with some practice you can "eyeball" the components of a btQuaternion to get an idea as to what sort of rotation it represents. For example:

<1,0,0,0> = pi radians about X-axis
<0,1,0,0> = pi radians about Y-axis
<sqrt(2)/2, 0, 0, sqrt(2)/2> = pi/2 radians about X-axis

There are some common "gotchas" when working with btQuaternions in code. Here are some:

(8) Due to floating point error a btQuaternion probably doesn't lie on the unit hypersphere, but it is close. Consequently the product of two btQuaternions: Q1*Q2 can drift even further from the sphere. Normally this isn't a problem, but if you ever find yourself recycling a btQuaternion to compute its next value then it will eventually explode off the sphere... unless you constantly normalize. In other words:

Code: Select all

``````Q = Q * deltaQ;   // BAD!
Q = (Q * deltaQ).normalize(); // GOOD!``````
If you're going to use the result then discard it, don't normalize, but if you're going to save the btQuaternion for the next loop then normalize it every loop. Note, this is not a problem if you're "storing" the btQuaternion in a btTrasnform because normalization automatically happens when storing the rotation into the 4x4 matrix.

(9) Bullet does not provide a convenient operator between btQuaternion and btVector3. It is implemented but probably doesn't do what you think: it doesn't just rotate the vector. To rotate a btVector3 in Bullet first store the rotation into a btTransform and use that.

(10) Rotations do not commute, so order matters. When doing rotation math you need to figure out if it is Q1*Q2 or Q2*Q1. My advice for this is to always imagine the rotations operating from the LEFT on a hypothetical vector on the RIGHT. So: consider it like so: Q1 * Q2 * v
The question becomes: Which rotation should operate first? That one always goes RIGHT-most, and subsequent rotations operate from RIGHT to LEFT order.
pwouik
Posts: 3
Joined: Tue Feb 23, 2021 2:43 pm

### Re: rotation format in bullet physics

in btRigidBody.h,angles seem to be stored in a btVector3:

Code: Select all

``````btVector3 m_linearVelocity;
btVector3 m_angularVelocity;``````
also in this function:

Code: Select all

``````void applyTorqueImpulse(const btVector3& torque)
{
m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
#if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
clampVelocity(m_angularVelocity);
#endif
``````
computation are made on a btVector3
how is stored for example m_angularVelocity?
drleviathan
Posts: 699
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

### Re: rotation format in bullet physics

AngularVelocity is indeed a btVector3, however its units are radians/second. It represents the rate of change of the rotation... not the rotation. Perhaps you had a question about AngularVelocity?
pwouik
Posts: 3
Joined: Tue Feb 23, 2021 2:43 pm

### Re: rotation format in bullet physics

so if I understand well,"adding" angular velocities is commutative,in contrary to rotations,and we can use for that a vector collinear to the axis of the rotation,with the norm the velocity in radians(as i understand in the code)
ok,I just found that:https://en.wikipedia.org/wiki/Angular_v ... ty_vectors so it seems to be that
is there a way to efficiently integrate the rotation(with a rotation matrix because it's a school project and i want to stay on the program) with this vector?
drleviathan
Posts: 699
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

### Re: rotation format in bullet physics

is there a way to efficiently integrate the rotation with this vector?
Do you mean: "Given some initial rotation Q0 and a non-zero angular velocity W... is it possible to compute the rotation Q(t) as time progresses forward?"

If so then: yes. In fact, that is what Bullet does: RigidBody dynamics. It has an integration step which computes future rotations. The details there are a bit more complicated than my paraphrased and hypothetical question since you also need to know the body's InertiaTensor (angular mass distribution). Depending on the symmetry of the Body the AngularVelocity might not be uniform over time for a freely tumbling object but the AngularMomentum would be conserved (e.g. would be invariant).

Perhaps you should describe what you really want to do and then then your questions might become more clear.