首页 > 解决方案 > 归一化 z 轴上的所有向量

问题描述

我编写了计算两个向量之间角度的代码。然而,这样做的方法是从两个向量开始,根据在单独程序中计算的一些欧拉角旋转每个向量,然后计算向量之间的角度。

到目前为止,我一直在处理一个用例,这意味着两个起始向量都是 (0,0,1),这让生活变得超级简单。我可以只取一组欧拉角,然后计算 0,0,1 和由差值旋转的向量之间的角度。这意味着我可以绘制漂亮的分布图和矢量图,因为一切都归一化为 0,0,1。(我有 1000 个这些向量作为记录)。

不,我正在尝试编写一个函数,以允许两个起始向量不在 0,0,1 上的用例。我认为最简单的方法是计算向量相对于 0,0,1 的方向,然后在计算向量的位置后,只需按预先计算的偏移量旋转即可。(这可能是一种愚蠢的做法,如果是请告诉我)。

我当前的代码适用于向量为 0,1,0 但如果我开始输入随机数就会崩溃的情况。

import numpy as np
import math

def RotationMatrix(axis, rotang):
    """
    This uses Euler-Rodrigues formula.
    """
    #Input taken in degrees, here we change it to radians
    theta = rotang * 0.0174532925
    axis = np.asarray(axis)
    #Ensure axis is a unit vector
    axis = axis/math.sqrt(np.dot(axis, axis))
    #calclating a, b, c and d according to euler-rodrigues forumla requirments
    a = math.cos(theta/2)
    b, c, d = axis*math.sin(theta/2)
    a2, b2, c2, d2 = a*a, b*b, c*c, d*d
    bc, ad, ac, ab, bd, cd = b*c, a*d, a*c, a*b, b*d, c*d
    #Return the rotation matrix
    return np.array([[a2+b2-c2-d2, 2*(bc-ad), 2*(bd+ac)],
                     [2*(bc+ad), a2+c2-b2-d2, 2*(cd-ab)],
                     [2*(bd-ac), 2*(cd+ab), a2+d2-b2-c2]])



def ApplyRotationMatrix(vector, rotationmatrix):
    """
    This function take the output from the RotationMatrix function and
    uses that to apply the rotation to an input vector
    """
    a1 = (vector[0] * rotationmatrix[0, 0]) + (vector[1] * rotationmatrix[0, 1]) + (vector[2] * rotationmatrix[0, 2])
    b1 = (vector[0] * rotationmatrix[1, 0]) + (vector[1] * rotationmatrix[1, 1]) + (vector[2] * rotationmatrix[1, 2])
    c1 = (vector[0] * rotationmatrix[2, 0]) + (vector[1] * rotationmatrix[2, 1]) + (vector[2] * rotationmatrix[2, 2])

    return np.array((a1, b1, c1)


'''
Functions for Calculating the angles of 3D vectors relative to one another
'''

def CalculateAngleBetweenVector(vector, vector2):
    """
    Does what it says on the tin, outputs an angle in degrees between two input vectors.
    """
    dp = np.dot(vector, vector2)

    maga = math.sqrt((vector[0] ** 2) + (vector[1] ** 2) + (vector[2] ** 2))
    magb = math.sqrt((vector2[0] ** 2) + (vector2[1] ** 2) + (vector2[2] ** 2))
    magc = maga * magb

    dpmag = dp / magc

    #These if statements deal with rounding errors of floating point operations
    if dpmag > 1:
        error = dpmag - 1
        print('error = {}, do not worry if this number is very small'.format(error))
        dpmag = 1
    elif dpmag < -1:
        error = 1 + dpmag
        print('error = {}, do not worry if this number is very small'.format(error))
        dpmag = -1


    angleindeg = ((math.acos(dpmag)) * 180) / math.pi

    return angleindeg


def CalculateAngleAroundZ(Vector):
    X,Y,Z = Vector[0], Vector[1], Vector[2]
    AngleAroundZ = math.atan2(Y, X)
    AngleAroundZdeg = (AngleAroundZ*180)/math.pi
    return AngleAroundZdeg

def CalculateAngleAroundX(Vector):
    X,Y,Z = Vector[0], Vector[1], Vector[2]
    AngleAroundZ = math.atan2(Y, Z)
    AngleAroundZdeg = (AngleAroundZ*180)/math.pi
    return AngleAroundZdeg

def CalculateAngleAroundY(Vector):
    X,Y,Z = Vector[0], Vector[1], Vector[2]
    AngleAroundZ = math.atan2(X, Z)
    AngleAroundZdeg = (AngleAroundZ*180)/math.pi
    return AngleAroundZdeg


V1 = (0,0,1)
V2 = (3,5,4)

Xoffset = (CalculateAngleAroundX(V2))
Yoffset = (CalculateAngleAroundY(V2))
Zoffset = (CalculateAngleAroundZ(V2))

XRM = RotationMatrix((1,0,0), (Xoffset * 1))
YRM = RotationMatrix((0,1,0), (Yoffset * 1))
ZRM = RotationMatrix((0,0,1), (Zoffset * 1))

V2 = V2 / np.linalg.norm(V2)
V2X = ApplyRotationMatrix(V2, XRM)
V2XY = ApplyRotationMatrix(V2X, YRM)
V2XYZ = ApplyRotationMatrix(V2XY, ZRM)
print(V2XYZ)
print(CalculateAngleBetweenVector(V1, V2XYZ))

任何解决此问题的建议将不胜感激。

标签: pythonnumpymathvector

解决方案


我不确定完全理解您需要什么,但如果要计算空间中两个向量之间的角度,您可以使用以下公式:

在此处输入图像描述

其中 ab 是标量积,theta 是向量之间的角度。

因此您的功能CalculateAngleBetweenVector变为:

def CalculateAngleBetweenVector(vector, vector2):
    return math.acos(np.dot(vector,vector2)/(np.linalg.norm(vector)* np.linalg.norm(vector2))) * 180 /math.pi

您还可以简化您的ApplyRotationMatrix功能:

def ApplyRotationMatrix(vector, rotationmatrix):
"""
This function take the output from the RotationMatrix function and
uses that to apply the rotation to an input vector
"""
return rotationmatrix @ vector

@ 符号是矩阵乘积

希望这会帮助你。如果这没有帮助,请随时详细说明您的要求。


推荐阅读