I found a solution in another post:
bullet : Mad Quaternion [url]bullet : Mad Quaternion[Solved]]
I think my code improves on that solution. Code follows.
In English, the solution is a hack that checks for a too-large difference between subsequent quaternions and reverses the quaternion to an equivalent, but not-so-different quaternion. I hope that makes sense.
def simDrift(self, dt):
#Gets the quaternions representing this NodePaths' orientations.
quat_cycle = self.cycle.getQuat()
quat_dirNP = self.dirNP.getQuat()
#Get the difference between quat_cycle and the previous value of quat_cycle
diff_quat=Quat(quat_cycle - self.previous_quat)
#If the difference is abnormally large, reverse the quat to an equivalent quat.
if abs(diff_quat.getR())>1.0 or abs(diff_quat.getI())>1.0 or \
abs(diff_quat.getJ())>1.0 or abs(diff_quat.getK())>1.0:
quat_cycle.setR(-quat_cycle.getR())
quat_cycle.setI(-quat_cycle.getI())
quat_cycle.setJ(-quat_cycle.getJ())
quat_cycle.setK(-quat_cycle.getK())
#Update previous quat
self.previous_quat = quat_cycle
#Difference between actual and desired orientations in degrees
diff_deg = quat_dirNP.angleDeg(quat_cycle)
#If the difference is small enough, then just snap to the Cycle's orientation.
if diff_deg < 0.1:
self.dirNP.setQuat(quat_cycle)
else:
#Otherwise perform a linear interpolation
t = 10.0 * dt #Close 10% of the difference in orientation per second.
self.dirNP.setQuat(quat_dirNP + (quat_cycle - quat_dirNP) * t)