bullet : Mad Quaternion[Solved]


I have little trouble with rotation made by bullet.
I apply torque to rotate my bullet body, and all is fine.

By now, I send the quaternion of my body through network, and on client side, I try to do a linear interpolation, to do smooth move (I don’t use panda lerp, for different topic).
But it seems that my quaternion are just mad. When I do a rotation of near 180, because I want to go behind me, what happens?
My last quaternion sent by my server is

-0.481109 + 0i + 0j + 0.876661k

and next received msg, I discover

0.522228 + 0i + 0j + -0.852806k

My first number becomes positive. I think the interpretation of the quaternion is right, and means the same thing… but why it became positive.
So in my linear interpolation, I am doing difference between last send, and the before, and my value between is > 1. :frowning:

Is there a way, to have quaternion always with same type, and not changing suddenly?

Thank you

Well, your two quaternions represent almost the same rotation, and thus are effectively (almost) the same. The axis is inverted, but also the angle of rotation around this axis.

>>> q1 = LQuaternion(-0.481109, 0, 0, 8.876661)
>>> q2 = LQuaternion(0.52228, 0, 0, -8.852806)
>>> q1.get_hpr()
LVecBase3f(-173.795, 0, 0)
>>> q2.get_hpr()
LVecBase3f(-173.247, 0, 0)

I’m not aware of a way to influence the quaterions computed by Bullet - I just convert and pass them on. You should try to improve your linear interpolation to handle such discontinuity in single values. What matters is the effective value given by the combination of all four components.

I’ve solved my problem with this:

lastQuatServer = self.pointerToGo.getQuat()
		oldQuatServer = self.pointerToGoOld.getQuat()
		diffQuat=Quat(lastQuatServer - oldQuatServer) 
		if diffQuat.getR()>0.8 or diffQuat.getR()<-0.8:

Just inverting all coordinates of my quaternion.

I was dealing with a similar problem. (See: [url]simDrift issues in 3d])
I’m very grateful I found this post as I was getting no end of headaches.

This may be obvious, but in any case, here is a slightly more generic solution to the same problem. (See the link I posted for the context.)

    #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:
    #Update previous quat
    self.previous_quat = quat_cycle