# how to rotate scaled-vector (orientation) by scaled-vector (rotation)

Recently I got the physics-engine portion of my 3D simulation / game engine working correctly. The most convenient way to store and compute position and orientation are in 3-element vectors (though my code actually holds both in the x,y,z elements of a 4-element vector).

The orientation is kept in what seems to be commonly called "scaled-vector" form, where the axis is defined by the vector direction, and the rotation angle is the length of the vector in radians.

After streamlining the code for a long time, the code is quite short and sweet (simple)... except where the code computes the new orientation (where torque forces and previous angular velocity applied to the previous orientation generate a new angular velocity and orientation). Whether this computation is done with matrices or quaternions, this section of code is relatively messy, extensive and slower to execute.

I'm not good at math (barely good enough to get the physics working after reading about ten million articles and books). But I have a very strong intuitive feeling there must be a way to rotate an orientation in scaled-vector form by a rotation also in scaled-vector form. This seems "obvious" to math-moron-me because a quaternion is equivalent to a scaled-vector, and because a quaternion is equivalent to a 4-element axis-angle vector which is itself equivalent to a scaled-vector.

Furthermore, I have found that all other computations in the physics engine with scaled-vectors are [somewhat to much] simpler and faster than any alternative, which makes me think there is something inherently good about these scaled-vectors. For one thing they don't get messed up when objects get rotating very fast (more than pi or 2pi per physics interval), while other approaches do.

Perhaps I've given more background than I should, but I do so to justify my desire to find the math to "rotate an orientation" AKA "rotate a rotation" with in scaled-vector form without converting them to quaternions or rotation matrices and back again, which is what I do now.

I've searched far and wide, but can't find the equations. I've found about ten million versions with quaternions and rotation matrices, but that's not what I'm looking for. Is my weakness in math hiding some obscure reason that this operation inherently can't be formulated with scaled-vectors?

Or can some math genius out there somewhere just whip these equations out, and receive my sincere admiration and appreciation?

PS: If someone provides a practical answer, I have a feeling many physics-engine and game-engine developers will find them as extremely helpful as me.

• Sorry, I'm not familiar with any other method that doesn't basically reduce to converting a quaternion back to axis-angle. To me, the "obvious" approach would be to use quaternions to keep the attitude of each object and to write the physics equations in terms of time derivatives of those quaternions. What issues did you have with that approach (I recognize you described this briefly, but I'm curious for a more detailed explanation)? What issues do you have with converting quats back and forth to axis-angle? I'm curious because such code may be slow due to trig, but shouldn't be messy. – Muphrid May 19 '15 at 5:25
• @Murphrid: Oh boy, now I'm in trouble. I can't possibly remember all the reasons, but I'll mention one. The angular acceleration and angular velocity can be more than 2*pi during the "physics interval" (the time step). From what I recall, the nature of a quaternion and a rotation matrix are such that angles greater than pi (or perhaps 2*pi) cannot be represented. This is a huge problem! And this is not uncommon either. A typical medium-speed motor rotates much faster than pi radians per second, and much more than pi radians in 1/30 or 1/60 second (typical frame and physics intervals). – honestann May 19 '15 at 5:38
• @Murphrid: And so, for example, if an object rotated 718 degrees during a physics interval, it would be truncated to the range the quaternion or matrix could represent, which would make the orientation -2.000 !!!! While this may leave the object in the correct orientation, the object is moving the wrong direction and 359 times slower than the facts of the matter. This totally screws up physics, and some other computations (that escape my mind at the moment). But "scaled-vector" representation works perfectly for all representations of all quantities. – honestann May 19 '15 at 5:41
• I see, so the issue isn't the rotation produced over the interval, it's that trying to convert back to recover your time derivatives is getting you fudged. Is that a fair assessment? – Muphrid May 19 '15 at 5:43
• That being because a rotation of, say, a quaternion representing a rotation of 45 degrees is mathematically indistinguishable from one representing a rotation of 765 degrees. – Muphrid May 19 '15 at 5:45

Though I cannot offer a solution for the question exactly as asked (a means to perform rotations directly with angular orientation vectors), I can offer as scheme that should be somewhat efficient and painless.

Suppose a position on an object is described by $x(t)$ such that

$$x(t) = qx(0) q^{-1}$$

where $q = q(t)$ is some unit quaternion.

Note that the time derivative of $x$ then has the form

$$x'(t) = (2 q' q^{-1}) \times x = \Omega(t) \times x$$

$\Omega$ here is the angular velocity, rendered as a pure imaginary quaternion (a vector), and the cross product here could be computed in quaternion parlance by merely considering only the imaginary parts of $\Omega x$. This quaternion need not (and almost certainly will not) be unit.

The angular velocity is intimately related to the quaternion describing orientation, and indeed, we can recover $q' = \Omega q/2$.

Given a torque $\tau$ and a moment of inertia tensor $I$, conservation of angular momentum $L$ tells us that

$$L' = [I(\Omega)]' = \tau$$

The case in which $I$ is constant is simpler, but in any case, this yields an ODE for the angular velocity $\Omega$, which I'm sure you're already quite familiar with.

So I suggest to you a scheme in which you carry two pieces of information: both the orientation ($q$) and the angular velocity ($\Omega$) at each time step. You use the evolution equations that dictate $q'$ and $\Omega'$ to update $q$ and $\Omega$, and once you do so, you can compute the new positions of every location on the rigid rotating body. You can combine these equations with those for linear momentum, of course.

From a numerical perspective, I suspect normalization of $q$ will not be precisely maintained under this scheme, and I'm uncertain what the effects will be of imposing normalization at an arbitrary point in the computation. The equation $2q'q^{-1} = \Omega$ already presumes that the quaternions stay fixed and normalized. I suspect one could check the quantity $q'q^* + q (q')^*$ to ensure this is zero (for unit quats, $q^* = q^{-1}$, but if you lose normalization, this should no longer be true).

From how you've described the problems you were having, it sounds like you may have been trying to avoid storing angular velocity separately, or that you might've tried to store angular velocity as a unit quaternion (which is indeed not useful or correct), rather than an unnormalized quaternion.

The approach I've described here should be rather straightforward from the perspective of an undergraduate-level course on ODEs (I say this merely to point you in the direction of appropriate texts if this is not part of your background). In particular, treating $q$ and $\Omega$ as "independent" variables and coupling them only through $q' = \Omega q/2$ is standard technique for taking a second-order system and reducing it to first-order.

Edit: I should add that this general approach could be used with rotation matrices or axis-angle, but the main obstacle for axis-angle would be the evolution equation for the orientation. For quats and rotatio matrices, the evolution equation is a simple function of the angular velocity. I'm not aware of any such simple law for axis-angle (or other closely related representations for the orientation).