# Strange quaternion behaviour [solved]

``````from direct.directbase import DirectStart
from pandac.PandaModules import *
base.disableMouse()
base.cam.setPos(0,-30,0)
base.cam.lookAt(0,0,0)
normaly = [loader.loadModel("smiley") for i in xrange(5)]
for m in normaly:
m.reparentTo(render)
strange.reparentTo(render)
normaly.setPos(-3,0,3)
strange.setPos(-3,0,0)
normaly.setPos(-3,0,-3)
normaly.setPos(3,0,3)
normaly.setPos(3,0,0)
normaly.setPos(3,0,-3)
q = Quat()
q.setHpr(normaly.getHpr()+Vec3(1,0,0))
normaly.setQuat(q)

q = Quat()
q.setHpr(strange.getHpr()+Vec3(0,1,0)) #<< HERE
strange.setQuat(q)

q = Quat()
q.setHpr(normaly.getHpr()+Vec3(0,0,1))
normaly.setQuat(q)

normaly.setHpr(normaly.getHpr()+Vec3(1,0,0))
normaly.setHpr(normaly.getHpr()+Vec3(0,1,0))
normaly.setHpr(normaly.getHpr()+Vec3(0,0,1))

run()``````

why it does not rotate?
Panda 1.7.0, Win 7 x64

Interesting.

I suspect it has to do with pitches beyond +/- 90 degrees being kinda strange. If you go past pointing straight down, the same rotation can be expressed as -90 pitch, 180 H and 180 roll (I think). Which representation panda chooses is arbitrary, but choosing the one with a abs§ less than 90 makes sense. Thus, adding to pitch moves it back toward straight down! Nothing is wrong, and the quats do everything properly. Hpr is simply not 1:1. There are infinite HPR that produce the same orientation, and if you go through a quat and back, you can end up having sudden changes in the HPR values from this.

Anyway, this does work: strange.setP(strange.getP()+1)

I’d just stay away from Hpr if you are going to have high pitch values.

Well, ok, I wrote two procedures to obtain the custom quaternion from H and from P, and… see…

``````from direct.directbase import DirectStart
from pandac.PandaModules import *
import math
base.disableMouse()
base.cam.setPos(0,-30,0)
base.cam.lookAt(0,0,0)
normaly.reparentTo(render)
normaly2.reparentTo(render)
strange.reparentTo(render)
normaly.setPos(0,0,2)
strange.setPos(0,0,0)
normaly2.setPos(0,0,-2)

def customQuatFromH(h):
h = h*0.5
h = (math.pi/180)*h
sin_h = math.sin(h)
q = Quat()
q.setR(math.cos(h))
q.setI(0*sin_h) #=0
q.setJ(0*sin_h) #=0
q.setK(1*sin_h)
return q

def customQuatFromP(p):
p = p*0.5
p = (math.pi/180)*p
sin_p = math.sin(p)
q = Quat()
q.setR(math.cos(p))
q.setI(1*sin_p)
q.setJ(0*sin_p) #=0
q.setK(0*sin_p) #=0
return q

normaly.setQuat(customQuatFromH(normaly.getH()+1)) #<< here it work
strange.setQuat(customQuatFromP(strange.getP()+1)) #<< and here not work
normaly2.setQuat(normaly2,customQuatFromP(1)) #<< here work again

run()``````

If you really must use quats and Hpr together, do it like this:

q = strange.getQuat()
q2 = Quat()
q2.setHpr(Vec3(0,1,0))
strange.setQuat(q.multiply(q2))

This way the orientation on your object stats a quat the whole time.

Note that the above does happen to have the same effect as this:
strange.setHpr(strange,0,1,0)

Yes, it’s work! Thanks!
I use quaternions to interpolate the data obtained from the network. And I can get the angular velocity only as the Vec3