当前位置: 首页 > 面试题库 >

通过四元数旋转坐标系

佴波鸿
2023-03-14
问题内容

我们有一个代表3d空间中原子的无数个空间坐标(x,y和z),并且我正在构造一个函数,将这些点转换为新的坐标系。将坐标移动到任意原点很简单,但是我无法绕下下一步:3d点旋转计算。换句话说,我正在尝试将点从(x,y,z)转换为(x’,y’,z’),其中x’,y’和z’分别是i’,j’和k’,我在euclid
python模块
的帮助下创建的新轴矢量。

认为 我只需要一个四元体即可做到这一点,即

>>> q * Vector3(x, y, z)
Vector3(x', y', z')

但是要做到这一点,我相信我需要一个旋转轴矢量和一个旋转角度。但是我不知道如何从i’,j’和k’计算这些。这似乎是一个简单的从头开始编写代码的过程,但是我怀疑这样的事情需要线性代数自行解决。非常感谢您朝着正确的方向前进。


问题答案:

从代数的角度来看,使用四元数来表示旋转并不困难。就个人而言,我发现很难从 视觉上
对四元数进行推理,但是使用四元数进行旋转所涉及的公式非常简单。我将在此处提供一组基本的参考功能。

您可以将四元数(出于我们的目的)视为一个标量加上一个3-d向量-抽象地w + xi + yj + zk表示为此处的一个简单元组(w, x, y, z)。3-d旋转空间完全由四元数的子空间( 单位
四元数的空间)表示,因此您需要确保四元数被标准化。您可以按照将任何4个向量归一化的方式进行操作(即,幅度应接近1;否则,将值按幅度缩减):

def normalize(v, tolerance=0.00001):
    mag2 = sum(n * n for n in v)
    if abs(mag2 - 1.0) > tolerance:
        mag = sqrt(mag2)
        v = tuple(n / mag for n in v)
    return v

请注意,为简单起见,以下函数假定四元数值 已标准化
。在实践中,您将需要不时地对它们进行规范化,但是最好的解决方法将取决于问题域。这些功能仅提供基本信息,仅供参考。

每次旋转都用一个单位四元数表示,旋转的级联对应于单位四元数的 乘法 。公式2如下:

def q_mult(q1, q2):
    w1, x1, y1, z1 = q1
    w2, x2, y2, z2 = q2
    w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2
    x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2
    y = w1 * y2 + y1 * w2 + z1 * x2 - x1 * z2
    z = w1 * z2 + z1 * w2 + x1 * y2 - y1 * x2
    return w, x, y, z

要通过四元数旋转 向量 ,还需要四元数的共轭。这很容易:

def q_conjugate(q):
    w, x, y, z = q
    return (w, -x, -y, -z)

现在四元数-向量乘法很简单,只要矢量变换成四元数(通过设置w = 0和离开xy以及z相同的),然后乘以q * v * q_conjugate(q)

def qv_mult(q1, v1):
    q2 = (0.0,) + v1
    return q_mult(q_mult(q1, q2), q_conjugate(q1))[1:]

最后,您需要知道如何将轴角旋转转换为四元数。还容易!在这里通过调用“清理”输入和输出是有意义的normalize

def axisangle_to_q(v, theta):
    v = normalize(v)
    x, y, z = v
    theta /= 2
    w = cos(theta)
    x = x * sin(theta)
    y = y * sin(theta)
    z = z * sin(theta)
    return w, x, y, z

然后回来:

def q_to_axisangle(q):
    w, v = q[0], q[1:]
    theta = acos(w) * 2.0
    return normalize(v), theta

这是一个快速使用示例。绕x,y和z轴旋转90度的序列会将y轴上的向量返回到其原始位置。此代码执行这些旋转:

x_axis_unit = (1, 0, 0)
y_axis_unit = (0, 1, 0)
z_axis_unit = (0, 0, 1)
r1 = axisangle_to_q(x_axis_unit, numpy.pi / 2)
r2 = axisangle_to_q(y_axis_unit, numpy.pi / 2)
r3 = axisangle_to_q(z_axis_unit, numpy.pi / 2)

v = qv_mult(r1, y_axis_unit)
v = qv_mult(r2, v)
v = qv_mult(r3, v)

print v
# output: (0.0, 1.0, 2.220446049250313e-16)

请记住,这种旋转顺序不会将 所有
矢量返回到相同位置。例如,对于x轴上的矢量,它将对应于围绕y轴旋转90度。(此处请牢记右手法则;围绕y轴的正向旋转会将x轴上的矢量推入z 负向 区域。)

v = qv_mult(r1, x_axis_unit)
v = qv_mult(r2, v)
v = qv_mult(r3, v)

print v
# output: (4.930380657631324e-32, 2.220446049250313e-16, -1.0)

与往常一样,如果您在此处发现任何问题,请告诉我。

1.这些改编自此处存档的OpenGL教程。

2.四元数乘法公式看起来像老鼠的巢,但是推导很简单(如果很乏味)。首先请注意ii = jj = kk = -1; 那么ij = kjk = iki = j; 最后是ji = -kkj = -iik = -j。然后将两个四元数相乘,分配这些项并根据16个乘法中每一个的结果重新排列它们。这也有助于说明 为什么
可以使用四元数来表示旋转。最后六个恒等式遵循右手定则,在 i到的j旋转与 围绕的 旋转之间创建双射k,依此类推。



 类似资料:
  • 本文向大家介绍unity3d 四元数外观旋转,包括了unity3d 四元数外观旋转的使用技巧和注意事项,需要的朋友参考一下 示例 Quaternion.LookRotation(Vector3 forward [, Vector3 up])将创建一个四元数旋转,该旋转向前看“向下”向前的向量,并使Y轴与“向上”向量对齐。如果未指定up向量,Vector3.up则将使用。 旋转此游戏对象以查看目标游

  • 给定的是一个旋转的矩形,该矩形内接到另一个矩形中<两个矩形都有自己的坐标系 在该区域中 我对变换矩阵的尝试(setRotate() 如何计算P点相对于外矩形的位置? 提前感谢!

  • 我正在开发简单的游戏。我有cca。50个矩形排列在10列5行中。以某种方式将它们放入整个屏幕是没有问题的。但是当我旋转画布时,假设大约7°角,旧的坐标不适合坐标的新位置。在构造函数中,我已经创建并定义了那个矩形的位置,在onDraw方法中,我正在绘制这个矩形(当然有aready旋转)bud我需要一些与当前矩形碰撞的方法。我尝试使用这样的东西(我确实围绕屏幕的中心点旋转) 但是它不起作用(因为它给了

  • 问题内容: 我试图了解四元数旋转的工作原理,我发现了这个迷你教程http://www.julapy.com/blog/2008/12/22/quaternion- rotation/, 但是他做出了一些我不能锻炼的假设,就像我如何“ 简单地通过绕轴旋转矢量来计算绕轴的旋转矢量 ” 。 他如何计算angleDegreesX,angleDegreesY和angleDegreesZ? 有人可以提供可行的

  • 问题内容: 我使用Java中的Graphics2D缩放和旋转绘制的图片。现在,我想知道当单击图片中的某个点时的原始坐标是什么。因此,鉴于旋转坐标和缩放坐标,我想计算原始坐标。有没有简单的方法可以做到这一点? 问题答案: 如果保留在绘制图像时使用的副本,则可以使用 AffineTransform.inverseTransform(Point2D ptSrc,Point2D ptDst) 将设备空间坐

  • 我正在尝试使用Surfaceview和canvas drawing在Android中创建自定义组件。这些组件可以通过触摸来调整大小和旋转。考虑创建一个图像视图,它的上、右、下和左边缘可通过触摸和拖动所需的边缘来缩放。我使用< code>RectF来保持组件的边界,对于旋转,我使用< code>canvas.rotate(angle,bounds.centerX()、bounds.centerY()

  • 如何获得旋转矩形的角坐标(以矩形为中心)? 我已经尝试了以下链接中的所有解决方案,但似乎没有任何运气。 将一个点绕另一个点旋转(2D) 找到给定中心点和旋转的旋转矩形的角 https://game dev . stack exchange . com/questions/86755/how-to-calculate-corner-positions-marks-of-a-rotated-tilte

  • 问题内容: 我想在Oracle 11g中旋转一个表。枢纽选项需要汇总。这是我的原始表: 旋转后,表格应如下所示: 现在,如您所见,分组应该在项目列上进行。无需折叠或计算值。只需旋转即可。那么,枢轴选择正确的事情了吗? 问题答案: 是的,我想是这样。使用汇总很容易进行这样的枢轴操作: 否则,您必须在max聚合内执行case语句。像这样: 这几乎和做。但我宁愿做在..