给定一个单位向量,找到使该向量与轴对齐的两个旋转角度

Given a unit vector find the two angles of rotation that aligns that vector with an axis

所以我不太精通线性代数,所以我正在努力解决这个问题。

我有一个单位向量v。我想找到两个角度(角度 1,绕 x 轴旋转,角度 2,绕 z 轴旋转),这样当我按它们旋转 v 时,它会将向量 v 与 y 对齐-轴。从 问题我有一个函数可以找到任意向量和 returns 旋转之间的角度。但是这个函数returns3个角度。本质上有无限数量的 3d 旋转 v 与 y 轴对齐,所以我想要两个独特的角度。

这是我现在的代码,它需要 numpy 和 scipy:

import numpy as np
import random
from scipy.spatial.transform import Rotation as R

def rotation_from_unit_vectors(a, b):
    v = np.cross(a, b)
    c = np.dot(a, b)
    s = np.linalg.norm(v)
    kmat = np.array([[0, -v[2], v[1]], [v[2], 0, -v[0]], [-v[1], v[0], 0]])
    rotation_matrix = np.eye(3) + kmat + kmat.dot(kmat) * ((1 - c) / (s ** 2))
    return  R.from_matrix(rotation_matrix)


y_axis = np.asarray([0.0, 1.0, 0.0])

alpha = random.uniform(0, 10)
beta = random.uniform(0, 10)
gamma = random.uniform(0, 10)

v = np.asarray([alpha, beta, gamma])
v = v / np.linalg.norm(v)

r = rotation_from_unit_vectors(v, y_axis)
print(r.as_euler('xyz', degrees = True))
print(r.apply(v))

嗯,不标准的问题,需要思考一下

给定 v1v2 您希望 rotate_z(rotate_x(v1, alpha), beta)v2.

方向相同

我们知道对齐向量可以通过简单的scaling缩放得到v2,这样就得到x1,y3,z3 = v3 = v2 * |v1| / |v2|。由于绕 z 轴旋转不影响 z 坐标,我们可以确定 alpha,使得 rotate_x(v1, alpha) 的 z 坐标等于 z3。之后我们确定角度 beta 以正确对齐放置 X 和 Y 坐标

import numpy as np
def alignment_angles(v1, v2):
    x1,y1,z1 = v1 # initial vector
    x2,y2,z2 = v2 # reference vector

    # magnitude of the two vectors
    r1 = np.sqrt(x1**2 + y1**2 + z1**2)
    r2 = np.sqrt(x2**2 + y2**2 + z2**2)
    # this will be the result when aligning v1 to v2
    # it has the magnitude of v1 and the direction of v2
    x3,y3,z3 = x2*r1/r2, y2*r1/r2, z2*r1/r2
    # the rotation in x must set the z coordinate to the
    # final value, since the rotation over the z axis will
    # not affect the z coordinate (this have two solutions)
    rho1 = np.sqrt(z1**2 + y1**2)
    if(abs(z3 / rho1) > 1):
        raise ValueError('Cannot align these vectors')
    alpha = np.arcsin(z3 / rho1) - np.arctan2(z1, y1);

    # apply the rotation to make easier to calcualte the next stage
    y1, z1 = (y1 * np.cos(alpha) - z1 * np.sin(alpha), 
              y1 * np.sin(alpha) + z1 * np.cos(alpha))
    np.allclose(rho1, np.sqrt(z1**2 + y1**2))
    #assert(np.allclose(z1, z3))
    # now it is just a matter of aligning (x1, y1) to (x3, y3)
    beta = np.arctan2(y3, x3) - np.arctan2(y1, x1)
    x1, y1 = (x1 * np.cos(beta) - y1 * np.sin(beta), 
              x1 * np.sin(beta) + y1 * np.cos(beta))
    
    # ensure the fotated v1 was correctly aligned
    assert(np.allclose([x1, y1, z1], [x3, y3, z3]))
    
    return alpha, beta

那你就打电话

alignment_angles((1,2,3), (3,4,5))

或者您也可以使用 3 行的 numpy 数组。

一开始我以为是球坐标系的应用,如果第二次旋转的轴是根据第一次旋转相应旋转的z轴就是这种情况。

编辑

有些向量无法与 x 轴上的旋转和 y 轴上的旋转对齐。 假设你想对齐向量 v1 = (1, 0, 0) 到向量 v2 = (0, 0, 1) x 的旋转不会影响 v1,它总是指向 x 方向,那么当你绕 z 轴旋转时它总是在 XY 计划上。

你给出的例子确实给出了错误的答案,因为 asin 不是单射的。

我更改了函数以在无法对齐给定向量时引发值错误。

利用固定目标对齐方式,这可以通过三角函数以简单的方式完成:

import math

def to_y(x,y,z):
  rx=-math.atan2(z,y)              # or +math.atan2(z,-y)
  y2=y*math.cos(rx)-z*math.sin(rx) # -> (x,y2,0)
  return rx,math.atan2(x,y2)

当从 +x 或+z[=20 看原点时,旋转被定义为逆时针方向 =](右手法则);旋转方向始终是幅度较小的方向,但有可能找到物理上 更小 的旋转,如评论中所示。请注意,输入不需要归一化,并且永远不会产生 NaN(除非它出现在输入中)。