Работа с ошибками с плавающей запятой во время вращения вектора - PullRequest
0 голосов
/ 05 мая 2020

В настоящее время я создаю код, который имеет дело с трехмерными векторами и вычисляет угол между ними после их поворота в соответствии с набором углов Эйлера. Частично это нормализация векторов по оси 0,0,1. В основном это просто для того, чтобы я мог легко построить графики распределения и векторные диаграммы и т. Д. c. Чтобы вычислить смещение и вектор, вокруг которого нужно повернуть, я просто использую точечные и перекрестные произведения, как показано ниже:

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))


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

axis = (0,0,1)
Vector1 = (0,1,0)
#ensure things are unit vectors
Vector1 = Vector1 / np.linalg.norm(Vector1)
#calculate the offset and axis of rotation to take vector to the z axis
angle1 = CalculateAngleBetweenVector(axis, Vector1)
cross1 = np.cross(axis, Vector1)
RM1 = RotationMatrix(cross1, angle1)
Vector1rot = ApplyRotationMatrix(Vector1, RM1)
print(Vector1rot)

Кажется, все работает нормально, однако, если вы просто скопируете и вставите приведенный выше код, вы получите скорее всего обнаружит, что повернутый вектор равен 1x10 ^ -9, 0, 1, а не 0,0,1.

Есть ли простой способ решить эту проблему с операциями с плавающей запятой?

Ответы [ 2 ]

1 голос
/ 05 мая 2020

может использоваться для округления числа с плавающей запятой

print(np.around(Vector1rot,decimals=1))
1 голос
/ 05 мая 2020

Вам действительно нужна точность лучше, чем эта? Я думаю, вы сначала хотите ответить, какая точность с плавающей запятой вам нужна и почему. В частности, на ваш вопрос об уменьшении ошибок с плавающей запятой вы можете увеличить квантование с плавающей запятой с помощью numpy long double.

Кроме того, я также должен указать, что вам может быть лучше с помощью кватернионов, в зависимости от в вашем заявлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...