【问题标题】:Matrix to quaternion and back does not give same result矩阵到四元数并返回不给出相同的结果
【发布时间】:2017-10-16 04:21:44
【问题描述】:

我正在将矩阵 (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]]

【问题讨论】:

    标签: python quaternions


    【解决方案1】:

    对于给定的四元数,有多种矩阵表示是正确的。当您将矩阵转换为四元数时,有关您最初使用的这些表示形式的信息会丢失。

    参见例如https://en.wikipedia.org/wiki/Quaternion中的矩阵表示

    【讨论】:

      【解决方案2】:

      我也遇到了同样的问题,分析了一下。

      https://en.wikipedia.org/wiki/Quaternion 的描述描述了四元数的 48 种可能的矩阵表示。我试图从中构造旋转矩阵,并存储要使用的信息,但它不起作用。原因是四元数矩阵表示与旋转变换矩阵无关。我花了一天时间才发现这一点。

      这个问题的相关部分在章节中

      三维和四维旋转组

      所有单位四元数(versors)的集合形成一个 3 球体 S3 和一个 乘法下的群(李群),双覆盖群 行列式 1 的实正交 3×3 矩阵的 SO(3,ℝ),因为两个 单位四元数对应于上述下的每一次旋转 一致。看盘子戏法。

      所以仅仅有一个归一化的变换矩阵是不够的,行列式必须为 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]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多