【问题标题】:Rotating a point to be parallel to a direction vector delivers wrong vector. Why?将一个点旋转为平行于方向向量会产生错误的向量。为什么?
【发布时间】:2019-06-20 09:56:28
【问题描述】:

我需要旋转一个由其从 (0,0,0) 开始并在给定点结束定义的向量,以便与给定方向向量平行。出于这个原因,我的代码基于以下答案:

我猜“平行”是指“指向同一方向”。

我们不妨旋转 (d,e,f) 在由 v=(d,e,f) 和 w=(a,b,c) 跨越的平面上。旋转轴 > 将围绕垂直于该平面的矢量,例如 a=v×w,> 您将标准化为单位长度矢量 u。最后,我们需要 >rotation θ 的角度,它可以通过求解 θ 从 v⋅w=∥v∥∥w∥cos(θ) 中得到。

然后按照使用四元数进行旋转的方案,您要寻找的>四元数是q=cos(θ/2)+usin(θ/2)。变换 >x→qxq−1 使 v 指向与 w 相同的方向。

https://math.stackexchange.com/questions/734707/how-to-rotate-a-3d-vector-to-be-parallel-to-another-3d-vector-using-quaternions/735136#735136

我已经设法实现了这一点,尽管通过可视化结果,很明显它们不是平行的。

## Example code

def get_unit_vector(vector):
    return vector / np.linalg.norm(vector)

def get_angle_between_vectors(vector1, vector2):
    unit_vector_1 = get_unit_vector(vector1)
    unit_vector_2 = get_unit_vector(vector2)
    angle = np.arccos(np.dot(unit_vector_2, unit_vector_1))
    return min(angle, np.pi-angle)

def rotate_point(point, direction):
    # get the axis and normalize it
    axis = np.cross(point, direction)
    norm_axis = get_unit_vector(axis)
    angle = get_angle_between_vectors(point, direction)
    q = np.cos((angle/2))+norm_axis*np.sin(angle/2)
    q = get_unit_vector(q)
    new_point = (q*point)*np.conj(q)
    new_angle = get_angle_between_vectors(new_point, direction)
    if new_angle != 0:
        q = np.cos((np.pi-angle / 2)) + norm_axis * np.sin(np.pi-angle / 2)
        new_point = (q * point) * (np.conj(q))
    return new_point

结果如下:

如前所述,我希望橙色和绿色向量都是平行的,但事实并非如此。有没有我遗漏的步骤?

【问题讨论】:

  • 一个点怎么能与任何东西“平行”呢?它可以在一条线上,但仅此而已......你在旋转什么?你想把这个点放在橙色线上吗?如果是,那又如何?您是否需要对用于将点放置在正确线上的旋转做其他事情?
  • q = np.cos((angle/2))+norm_axis*np.sin(angle/2) 行听起来很可疑:它在 3 坐标向量上添加一个数字,这是一个有效的 numpy 操作,但在这里没有数学意义。不知道修复会是什么。
  • @PatrickArtner 定义不够明确。我的意思是从 (0,0,0) 到给定点的向量。轴是平面的垂直向量,如引用的答案中所述。换句话说,我试图对齐两个向量,使绿色与橙色的方向相同。
  • 链接答案下的 cmets 阐明 u 是一个单位 四元数,它代表旋转轴 A,即 u = [w=0, xyz=A]cos(θ/2) also 表示实部等于cos(θ/2) 的四元数。因此四元数q[w=cos(θ/2), xyz=A*sin(θ/2)] 的组成部分,这与网络上的其他教程一致。结论:总是引用不止一个来源。
  • @MWP 如果您尝试进行四元数运算,那么new_point = (q*point)*np.conj(q) 不会按照您的想法执行。 Per the doc,np.conj 以元素方式返回复共轭(因此这里没有任何改变,因为你有一个实值向量)。

标签: python numpy vector rotation


【解决方案1】:

所以经过一些修改后,我设法获得了所需的输出。我从here得到了乘法函数。

def get_unit_vector(vector):
    return vector / np.linalg.norm(vector)


def get_angle_between_vectors(vector1, vector2):
    unit_vector_1 = get_unit_vector(vector1)
    unit_vector_2 = get_unit_vector(vector2)
    angle = np.arccos(np.dot(unit_vector_2, unit_vector_1))
    return min(angle, np.pi-angle)

def quaternion_conjugate(q):
    first = q[0]
    q_prime = -1*q
    q_prime[0] = first
    return q_prime

def quaternion_multiply(quaternion1, quaternion0):
    w0, x0, y0, z0 = quaternion0
    w1, x1, y1, z1 = quaternion1
    return np.array([-x1 * x0 - y1 * y0 - z1 * z0 + w1 * w0,
                     x1 * w0 + y1 * z0 - z1 * y0 + w1 * x0,
                     -x1 * z0 + y1 * w0 + z1 * x0 + w1 * y0,
                     x1 * y0 - y1 * x0 + z1 * w0 + w1 * z0], dtype=np.float64)


def rotate_point(point, direction):
    axis = np.cross(point, direction)
    norm_axis = get_unit_vector(axis)
    angle = -get_angle_between_vectors(point, direction)
    q = np.array([np.cos((angle/2)),*(norm_axis*np.sin(angle/2))])
    point_as_q = np.array([0,*point])
    q3 = quaternion_multiply(q, point_as_q)
    q3 = quaternion_multiply(q3, quaternion_conjugate(q))
    new_point = q3[1:]
    return new_point

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-30
    • 2021-02-11
    • 2021-06-02
    • 2015-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多