Quaternion interpolation not working
Opened this issue · 4 comments
GoogleCodeExporter commented
What steps will reproduce the problem?
q1 = Quaternion(.15,0, 0.99,0).normalized()
q2 = Quaternion(.15,0,-0.99,0).normalized()
print Quaternion.new_interpolate(q1,q2,0.0)
print Quaternion.new_interpolate(q1,q2,0.25)
print Quaternion.new_interpolate(q1,q2,0.5)
print Quaternion.new_interpolate(q1,q2,0.75)
print Quaternion.new_interpolate(q1,q2,1.0)
What is the expected output? What do you see instead?
I get the following output which does not appear to interpolate between the two
quaternions:
Quaternion(real=0.15, imag=<0.00, -0.99, 0.00>)
Quaternion(real=0.15, imag=<0.00, -1.00, 0.00>)
Quaternion(real=0.15, imag=<0.00, -1.00, 0.00>)
Quaternion(real=0.15, imag=<0.00, -1.00, 0.00>)
Quaternion(real=0.15, imag=<0.00, -0.99, 0.00>)
This might be occurring when the angle between the two quaternions is obtuse??
I haven't dug into it enough yet to figure out the reason for failure.
What version of the product are you using? On what operating system?
Revision 36 on Ubuntu 10.04
Please provide any additional information below.
Original issue reported on code.google.com by chris.fl...@gmail.com
on 19 Dec 2011 at 9:10
GoogleCodeExporter commented
The error seems to have been introduced in revision 26. Revision 25 works fine
on this example but revision 26 fails.
Original comment by chris.fl...@gmail.com
on 19 Dec 2011 at 9:21
- Added labels: ****
- Removed labels: ****
GoogleCodeExporter commented
Here is the diff between -r25 and -r26:
@@ -1287,6 +1346,12 @@
Q = cls()
costheta = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z
+ if costheta < 0.:
+ costheta = -costheta
+ q1 = q1.conjugated()
+ elif costheta > 1:
+ costheta = 1
+
theta = math.acos(costheta)
if abs(theta) < 0.01:
Q.w = q2.w
It just seems like reverting the new_interpolate function back to -r25 would
fix things. I'm not sure why the following lines are necessary (assuming both
quaternions are normalized):
+ elif costheta > 1:
+ costheta = 1
I guess in case of rounding errors?
Original comment by chris.fl...@gmail.com
on 19 Dec 2011 at 9:32
- Added labels: ****
- Removed labels: ****
GoogleCodeExporter commented
Probably related to bug #16
Original comment by rodrigo....@gmail.com
on 6 Aug 2014 at 9:45
- Added labels: ****
- Removed labels: ****
GoogleCodeExporter commented
I ended up making some other mods to this function, here is currently working
for me. I needed to have very precise interpolation for my application, the
existing code will skip interpolation altogether if the quaternion angle
difference is lower than an arbitrary threshold.
def new_interpolate(cls, q1, q2, t):
assert isinstance(q1, Quaternion) and isinstance(q2, Quaternion)
Q = cls()
costheta = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z
if costheta < 0.:
costheta = -costheta
q1 = q1.conjugated()
elif costheta > 1:
costheta = 1
elif costheta == 1.0:
Q.w = q1.w
Q.x = q1.x
Q.y = q1.y
Q.z = q1.z
return Q
theta = math.acos(costheta)
sintheta = math.sqrt(1.0 - costheta * costheta)
try:
ratio1 = math.sin((1 - t) * theta) / sintheta
except ZeroDivisionError:
Q.w = q1.w
Q.x = q1.x
Q.y = q1.y
Q.z = q1.z
return Q
ratio2 = math.sin(t * theta) / sintheta
Q.w = q1.w * ratio1 + q2.w * ratio2
Q.x = q1.x * ratio1 + q2.x * ratio2
Q.y = q1.y * ratio1 + q2.y * ratio2
Q.z = q1.z * ratio1 + q2.z * ratio2
return Q
new_interpolate = classmethod(new_interpolate)
Original comment by chris.fl...@gmail.com
on 6 Aug 2014 at 10:33
- Added labels: ****
- Removed labels: ****