矩阵到四元数和返回不给出相同的结果
Matrix to quaternion and back does not give same result
我正在将矩阵 (M) 转换为四元数,以便我可以,例如在两个不同的变换矩阵之间进行 lerp 制作平滑的图像动画,我需要自己制作视频帧。
当我从四元数转换回矩阵作为测试时,这个新矩阵与变成四元数的矩阵相去甚远。
import numpy as np
from transforms3d import quaternions
M = np.array([[ 0.757403109, -0.186744161, 145.541734],
[ -0.154492906, 0.626185286, 100.878814],
[ -0.000294826495, -0.000344726091, 1.00000000]])
quat = quaternions.mat2quat(M)
testM = quaternions.quat2mat(quat)
print("TEST: M original")
print(M)
print("TEST: quat back to mat (testM)")
print(testM)
print("Why not the same")
print ("quat")
print(quat)
print("quat of testM")
print(quaternions.mat2quat(testM))
#Scaling gives same result, scale M to be -1. to 1
mmax = np.amax(M)
scaleTestM = M / mmax
print("M Scaled")
print(scaleTestM)
quatOfScaled = quaternions.mat2quat(scaleTestM)
print("Quat of scaled")
print(quaternions.quat2mat(quatOfScaled))
我是否遗漏了四元数实际可以表示的某些内容,或者代码有误?
如果这行不通,欢迎提出其他关于如何在两个变换矩阵之间平滑移动的建议。
Python 3.6
控制台输出是这样的:
TEST: M original
[[ 7.57403109e-01 -1.86744161e-01 1.45541734e+02]
[ -1.54492906e-01 6.26185286e-01 1.00878814e+02]
[ -2.94826495e-04 -3.44726091e-04 1.00000000e+00]]
TEST: quat back to mat (testM)
[[ 0.38627453 -0.42005089 0.8211877 ]
[-0.54462197 0.61466344 0.57059247]
[-0.74443193 -0.6676422 0.00865989]]
Why not the same
quat
[ 0.70880143 -0.43673539 0.55220671 -0.04393723]
quat of testM
[ 0.70880143 -0.43673539 0.55220671 -0.04393723]
M Scaled
[[ 5.20402697e-03 -1.28309699e-03 1.00000000e+00]
[ -1.06150244e-03 4.30244486e-03 6.93126372e-01]
[ -2.02571789e-06 -2.36857210e-06 6.87088145e-03]]
Quat of scaled
[[ 0.38627453 -0.42005089 0.8211877 ]
[-0.54462197 0.61466344 0.57059247]
[-0.74443193 -0.6676422 0.00865989]]
对于给定的四元数,存在多种矩阵表示形式。当您将矩阵转换为四元数时,有关您最初使用这些表示的信息会丢失。
中的矩阵表示
我也遇到了同样的问题,分析的比较深入
https://en.wikipedia.org/wiki/Quaternion 处的描述描述了四元数的 48 种可能的矩阵表示。我试图从中构造旋转矩阵,并存储要使用哪个矩阵的信息,但它没有用。原因是四元数矩阵表示与旋转变换矩阵无关。我花了一天时间才弄明白。
这个问题的相关部分在章节
Three-dimensional and four-dimensional rotation groups
The set of all unit quaternions (versors) forms a 3-sphere S3 and a
group (a Lie group) under multiplication, double covering the group
SO(3,ℝ) of real orthogonal 3×3 matrices of determinant 1 since two
unit quaternions correspond to every rotation under the above
correspondence. See the plate trick.
所以仅仅有一个归一化的变换矩阵是不够的,行列式必须是1。一旦满足这个条件,你就可以创建一个旋转四元数并将它转换回旋转变换矩阵。如果不满足条件,四元数将是未定义的,因此在转换回矩阵时会产生不同的矩阵。
您可以使用矩阵中两个向量的叉积从您的矩阵构建这样的矩阵,然后使用结果的叉积。
M = np.array([[0.757403109, -0.186744161, 145.541734],
[-0.154492906, 0.626185286, 100.878814],
[-0.000294826495, -0.000344726091, 1.00000000]])
quat = quaternions.mat2quat(M)
testM = quaternions.quat2mat(quat)
print("TEST: M original")
det = np.linalg.det(M)
print("M det:"+str(det))
print(M)
print("TEST: quat back to mat (testM)")
print(testM)
print("Why not the same")
print("quat")
print(quat)
print("quat of testM")
print(quaternions.mat2quat(testM))
# Scaling gives same result, scale M to be -1. to 1
mmax = np.amax(M)
scaleTestM = M / mmax
print("M Scaled")
det = np.linalg.det(scaleTestM)
print("M Scaled det:"+str(det))
print(scaleTestM)
quatOfScaled = quaternions.mat2quat(scaleTestM)
print("Quat of scaled")
print(quaternions.quat2mat(quatOfScaled))
v1 = M[0]
v2 = M[1]
v3 = M[2]
v1 = v1 / np.linalg.norm(v1)
v2 = v2 / np.linalg.norm(v2)
v3 = v3 / np.linalg.norm(v3)
print(v1)
print(v2)
print(v3)
v33 = np.cross(v1, v2)
v33 = v33 / np.linalg.norm(v33)
v22 = np.cross(v1, v33)
v22 = v22 / np.linalg.norm(v22)
scaledOrthoM = np.array([v1, v22, v33])
print("M Scaled")
det = np.linalg.det(scaledOrthoM)
print("M Scaled det:"+str(det))
print(scaledOrthoM)
if det == -1:
v33 = v33 * -1
scaledOrthoM = np.array([v1, v22, v33])
det = np.linalg.det(scaledOrthoM)
print("M Scaled det:"+str(det))
quatOfScaledOrtho = quaternions.mat2quat(scaledOrthoM)
print("Quat of scaled")
print(quaternions.quat2mat(quatOfScaledOrtho))
控制台输出是这样的:
TEST: M original
M det:0.5119378064538171
[[ 7.57403109e-01 -1.86744161e-01 1.45541734e+02]
[-1.54492906e-01 6.26185286e-01 1.00878814e+02]
[-2.94826495e-04 -3.44726091e-04 1.00000000e+00]]
TEST: quat back to mat (testM)
[[ 0.38627453 -0.42005089 0.8211877 ]
[-0.54462197 0.61466344 0.57059247]
[-0.74443193 -0.6676422 0.00865989]]
Why not the same
quat
[ 0.70880143 -0.43673539 0.55220671 -0.04393723]
quat of testM
[ 0.70880143 -0.43673539 0.55220671 -0.04393723]
M Scaled
M Scaled det:1.6605599862106246e-07
[[ 5.20402697e-03 -1.28309699e-03 1.00000000e+00]
[-1.06150244e-03 4.30244486e-03 6.93126372e-01]
[-2.02571789e-06 -2.36857210e-06 6.87088145e-03]]
Quat of scaled
[[ 0.38627453 -0.42005089 0.8211877 ]
[-0.54462197 0.61466344 0.57059247]
[-0.74443193 -0.6676422 0.00865989]]
[ 0.00520395 -0.00128308 0.99998564]
[-0.00153144 0.00620718 0.99997956]
[-2.94826465e-04 -3.44726056e-04 9.99999897e-01]
M Scaled
M Scaled det:-1.0
[[ 0.00520395 -0.00128308 0.99998564]
[ 0.66862666 -0.74358506 -0.00443364]
[-0.74358006 -0.66864013 0.00301168]]
M Scaled det:1.0
Quat of scaled
[[ 0.00520395 -0.00128308 0.99998564]
[ 0.66862666 -0.74358506 -0.00443364]
[ 0.74358006 0.66864013 -0.00301168]]
我正在将矩阵 (M) 转换为四元数,以便我可以,例如在两个不同的变换矩阵之间进行 lerp 制作平滑的图像动画,我需要自己制作视频帧。
当我从四元数转换回矩阵作为测试时,这个新矩阵与变成四元数的矩阵相去甚远。
import numpy as np
from transforms3d import quaternions
M = np.array([[ 0.757403109, -0.186744161, 145.541734],
[ -0.154492906, 0.626185286, 100.878814],
[ -0.000294826495, -0.000344726091, 1.00000000]])
quat = quaternions.mat2quat(M)
testM = quaternions.quat2mat(quat)
print("TEST: M original")
print(M)
print("TEST: quat back to mat (testM)")
print(testM)
print("Why not the same")
print ("quat")
print(quat)
print("quat of testM")
print(quaternions.mat2quat(testM))
#Scaling gives same result, scale M to be -1. to 1
mmax = np.amax(M)
scaleTestM = M / mmax
print("M Scaled")
print(scaleTestM)
quatOfScaled = quaternions.mat2quat(scaleTestM)
print("Quat of scaled")
print(quaternions.quat2mat(quatOfScaled))
我是否遗漏了四元数实际可以表示的某些内容,或者代码有误? 如果这行不通,欢迎提出其他关于如何在两个变换矩阵之间平滑移动的建议。
Python 3.6
控制台输出是这样的:
TEST: M original [[ 7.57403109e-01 -1.86744161e-01 1.45541734e+02] [ -1.54492906e-01 6.26185286e-01 1.00878814e+02] [ -2.94826495e-04 -3.44726091e-04 1.00000000e+00]] TEST: quat back to mat (testM) [[ 0.38627453 -0.42005089 0.8211877 ] [-0.54462197 0.61466344 0.57059247] [-0.74443193 -0.6676422 0.00865989]] Why not the same quat [ 0.70880143 -0.43673539 0.55220671 -0.04393723] quat of testM [ 0.70880143 -0.43673539 0.55220671 -0.04393723] M Scaled [[ 5.20402697e-03 -1.28309699e-03 1.00000000e+00] [ -1.06150244e-03 4.30244486e-03 6.93126372e-01] [ -2.02571789e-06 -2.36857210e-06 6.87088145e-03]] Quat of scaled [[ 0.38627453 -0.42005089 0.8211877 ] [-0.54462197 0.61466344 0.57059247] [-0.74443193 -0.6676422 0.00865989]]
对于给定的四元数,存在多种矩阵表示形式。当您将矩阵转换为四元数时,有关您最初使用这些表示的信息会丢失。
中的矩阵表示我也遇到了同样的问题,分析的比较深入
https://en.wikipedia.org/wiki/Quaternion 处的描述描述了四元数的 48 种可能的矩阵表示。我试图从中构造旋转矩阵,并存储要使用哪个矩阵的信息,但它没有用。原因是四元数矩阵表示与旋转变换矩阵无关。我花了一天时间才弄明白。
这个问题的相关部分在章节
Three-dimensional and four-dimensional rotation groups
The set of all unit quaternions (versors) forms a 3-sphere S3 and a group (a Lie group) under multiplication, double covering the group SO(3,ℝ) of real orthogonal 3×3 matrices of determinant 1 since two unit quaternions correspond to every rotation under the above correspondence. See the plate trick.
所以仅仅有一个归一化的变换矩阵是不够的,行列式必须是1。一旦满足这个条件,你就可以创建一个旋转四元数并将它转换回旋转变换矩阵。如果不满足条件,四元数将是未定义的,因此在转换回矩阵时会产生不同的矩阵。
您可以使用矩阵中两个向量的叉积从您的矩阵构建这样的矩阵,然后使用结果的叉积。
M = np.array([[0.757403109, -0.186744161, 145.541734],
[-0.154492906, 0.626185286, 100.878814],
[-0.000294826495, -0.000344726091, 1.00000000]])
quat = quaternions.mat2quat(M)
testM = quaternions.quat2mat(quat)
print("TEST: M original")
det = np.linalg.det(M)
print("M det:"+str(det))
print(M)
print("TEST: quat back to mat (testM)")
print(testM)
print("Why not the same")
print("quat")
print(quat)
print("quat of testM")
print(quaternions.mat2quat(testM))
# Scaling gives same result, scale M to be -1. to 1
mmax = np.amax(M)
scaleTestM = M / mmax
print("M Scaled")
det = np.linalg.det(scaleTestM)
print("M Scaled det:"+str(det))
print(scaleTestM)
quatOfScaled = quaternions.mat2quat(scaleTestM)
print("Quat of scaled")
print(quaternions.quat2mat(quatOfScaled))
v1 = M[0]
v2 = M[1]
v3 = M[2]
v1 = v1 / np.linalg.norm(v1)
v2 = v2 / np.linalg.norm(v2)
v3 = v3 / np.linalg.norm(v3)
print(v1)
print(v2)
print(v3)
v33 = np.cross(v1, v2)
v33 = v33 / np.linalg.norm(v33)
v22 = np.cross(v1, v33)
v22 = v22 / np.linalg.norm(v22)
scaledOrthoM = np.array([v1, v22, v33])
print("M Scaled")
det = np.linalg.det(scaledOrthoM)
print("M Scaled det:"+str(det))
print(scaledOrthoM)
if det == -1:
v33 = v33 * -1
scaledOrthoM = np.array([v1, v22, v33])
det = np.linalg.det(scaledOrthoM)
print("M Scaled det:"+str(det))
quatOfScaledOrtho = quaternions.mat2quat(scaledOrthoM)
print("Quat of scaled")
print(quaternions.quat2mat(quatOfScaledOrtho))
控制台输出是这样的:
TEST: M original
M det:0.5119378064538171
[[ 7.57403109e-01 -1.86744161e-01 1.45541734e+02]
[-1.54492906e-01 6.26185286e-01 1.00878814e+02]
[-2.94826495e-04 -3.44726091e-04 1.00000000e+00]]
TEST: quat back to mat (testM)
[[ 0.38627453 -0.42005089 0.8211877 ]
[-0.54462197 0.61466344 0.57059247]
[-0.74443193 -0.6676422 0.00865989]]
Why not the same
quat
[ 0.70880143 -0.43673539 0.55220671 -0.04393723]
quat of testM
[ 0.70880143 -0.43673539 0.55220671 -0.04393723]
M Scaled
M Scaled det:1.6605599862106246e-07
[[ 5.20402697e-03 -1.28309699e-03 1.00000000e+00]
[-1.06150244e-03 4.30244486e-03 6.93126372e-01]
[-2.02571789e-06 -2.36857210e-06 6.87088145e-03]]
Quat of scaled
[[ 0.38627453 -0.42005089 0.8211877 ]
[-0.54462197 0.61466344 0.57059247]
[-0.74443193 -0.6676422 0.00865989]]
[ 0.00520395 -0.00128308 0.99998564]
[-0.00153144 0.00620718 0.99997956]
[-2.94826465e-04 -3.44726056e-04 9.99999897e-01]
M Scaled
M Scaled det:-1.0
[[ 0.00520395 -0.00128308 0.99998564]
[ 0.66862666 -0.74358506 -0.00443364]
[-0.74358006 -0.66864013 0.00301168]]
M Scaled det:1.0
Quat of scaled
[[ 0.00520395 -0.00128308 0.99998564]
[ 0.66862666 -0.74358506 -0.00443364]
[ 0.74358006 0.66864013 -0.00301168]]