It seems that blender's Matrix decompose() function can exhibit some numerical "instability". What I mean is that orientation matrices that are relatively close can have significantly different elements in their quaternion matrix that makes interpolated keyframing unusable.
The following simple python script will calculate a sequence of matrices representing rotations around the Z axis in a smooth manner. It then decomposes the matrix into a quaternion, and inserts that as a keyframe. When you view the resulting fcurves in blender you can see that the Z value jumps from -1 to 1 about halfway through the animation.
import bpy from math import * from mathutils import * def matrix_for_time(t): theta = 2 * pi * t mat = Matrix([[cos(theta), sin(theta), 0], [-sin(theta), cos(theta), 0], [0, 0, 1]]).to_4x4() # for illustration we use rotation about Z axis, # but in the arbitrary case, the orientation could be for a pine cone bouncing down a hill. return mat def mission(obj): res = 36 qs = QuaternionStabilizer() for z in range(res): mat = matrix_for_time(z/res) (loc,quat,scale) = mat.decompose() obj.rotation_quaternion = qs.stabilize(quat) for ai in range(len(quat)): obj.keyframe_insert(frame=z*5, data_path="rotation_quaternion", index=ai) mission(bpy.context.active_object)
" How to make a true linear quaternion rotation? " has some screenshots that imply quaternions aren't necessarily discontinuous.
Is there a technique for blender's python API to get a sequence of quaternions that can be keyframed and interpolated without discontinuity? For bonus points: link to an article that explains this mathematical oddity and why decomposition works this way.
This technique should be usable with arbitrary orientation matrices, because they are calculated from something a little more complex than this simple Z rotation (in my specific case I'm flying along a bezier curve).