simDrift issues in 3d

Thanks again for your response. I did some browsing through the forums regarding quaternions and found two helpful posts, both of which you will be familiar with:

passing quaternions to objects over time [url]passing quaternions to objects over time]

Quat.angleDeg and Quat.setHpr with roll [url]Quat.angleDeg and Quat.setHpr with roll]

The trouble is that I’m still getting a “twitch” when pitch passes across -90 degrees even without any change to roll or yaw. I believe I have a nice simple method using quaternions correctly (see below). Am I missing something?

The “twitch” occurs here. The hpr for the cycle is on the left. The hpr for the chase cam is on the right:
LVecBase3f(0, -88.0852, 0) — LVecBase3f(0, -85.3164, 0)
LVecBase3f(0, -89.692, 0) — LVecBase3f(0, -85.7539, 0)
LVecBase3f(-180, -89.9268, -180) — LVecBase3f(0, -86.1859, 0)
LVecBase3f(180, -89.3085, -180) — LVecBase3f(0, -85.6227, 0)
LVecBase3f(-180, -87.6016, 180) — LVecBase3f(0, -84.5305, 0)
LVecBase3f(180, -86.6258, -180) — LVecBase3f(0, -82.6031, 0)
LVecBase3f(-180, -84.9346, 180) — LVecBase3f(0, -78.6328, 0)
LVecBase3f(-180, -84.9346, 180) — LVecBase3f(0, -69.7036, 0)
LVecBase3f(-180, -84.9346, 180) — LVecBase3f(0, -33.7563, 0)

Here is my simulated drift code. dirNP is the node path that “chases” the cycle. The cycle is the node path of a hoverbike model. The camera is parented to dirNP:

  def simDrift(self, dt):
    #Gets the quaternions representing this NodePaths' orientations.
    quat_cycle = self.cycle.getQuat()
    quat_dirNP = self.dirNP.getQuat()
    #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:
        new_quat = quat_cycle
    else:
        #Otherwise perform a linear interpolation
        t = 0.1 #Close 10% of the difference in orientation
        new_quat = quat_dirNP + (quat_cycle - quat_dirNP) * t
    self.dirNP.setQuat(new_quat)

The only other relevant code I can think of is the code that changes pitch:

  def changePitch(self, dir, dt):
    '''dir = up/down'''
    turnRate = self.handling * (2 - (self.speed / self.maxSpeed))
    if(dir == "down"):
      turnRate = -turnRate
    self.cycle.setP(self.cycle, turnRate * dt)