具有旋转矩阵的不精确度,可将向量对准轴 [英] Imprecision with rotation matrix to align a vector to an axis

查看:76
本文介绍了具有旋转矩阵的不精确度,可将向量对准轴的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经用这个把我的头撞在墙上好几个小时了,我似乎无法弄清楚我在做什么错.

I've been banging my head against the wall with this for several hours and I can't seem to figure out what I'm doing wrong.

我正在尝试生成将矢量与特定轴对齐的旋转矩阵(我将最终转换更多数据,因此拥有旋转矩阵很重要).

I'm trying to generate a rotation matrix which will align a vector with a particular axis (I'll ultimately be transforming more data, so having the rotation matrix is important).

我觉得我的方法是正确的,并且如果我在各种向量上对其进行测试,那么它效果很好,但是转换后的向量总是有点偏离

I feel like my method is right, and if I test it on a variety of vectors, it works pretty well, but the transformed vectors are always a little off.

这是我用来测试该方法的完整代码示例:

Here's a full code sample I'm using to test the method:

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d
import matplotlib as mpl


def get_rotation_matrix(i_v, unit=None):
    # From http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38
    if unit is None:
        unit = [1.0, 0.0, 0.0]
    # Normalize vector length
    i_v = np.divide(i_v, np.sqrt(np.dot(i_v, i_v)))
    # Get axis
    u, v, w = np.cross(i_v, unit)
    # Get angle
    phi = np.arccos(np.dot(i_v, unit))
    # Precompute trig values
    rcos = np.cos(phi)
    rsin = np.sin(phi)
    # Compute rotation matrix
    matrix = np.zeros((3, 3))
    matrix[0][0] = rcos + u * u * (1.0 - rcos)
    matrix[1][0] = w * rsin + v * u * (1.0 - rcos)
    matrix[2][0] = -v * rsin + w * u * (1.0 - rcos)
    matrix[0][1] = -w * rsin + u * v * (1.0 - rcos)
    matrix[1][1] = rcos + v * v * (1.0 - rcos)
    matrix[2][1] = u * rsin + w * v * (1.0 - rcos)
    matrix[0][2] = v * rsin + u * w * (1.0 - rcos)
    matrix[1][2] = -u * rsin + v * w * (1.0 - rcos)
    matrix[2][2] = rcos + w * w * (1.0 - rcos)
    return matrix

# Example Vector
origv = np.array([0.47404573,  0.78347482,  0.40180573])

# Compute the rotation matrix
R = get_rotation_matrix(origv)

# Apply the rotation matrix to the vector
newv = np.dot(origv.T, R.T)

# Get the 3D figure
fig = plt.figure()
ax = fig.gca(projection='3d')

# Plot the original and rotated vector
ax.plot(*np.transpose([[0, 0, 0], origv]), label="original vector", color="r")
ax.plot(*np.transpose([[0, 0, 0], newv]), label="rotated vector", color="b")

# Plot some axes for reference
ax.plot([0, 1], [0, 0], [0, 0], color='k')
ax.plot([0, 0], [0, 1], [0, 0], color='k')
ax.plot([0, 0], [0, 0], [0, 1], color='k')

# Show the plot and legend
ax.legend()
plt.show()

我已链接找到方法此处.为什么这种转换总是稍微偏离?

I've linked found the method here. Why is the transform this produces always just a little bit off???

推荐答案

您需要规范uvw才能正常工作.因此,替换

You need to norm uvw for that to work. So replace

u,v,w = np.cross(i_v,unit)

u, v, w = np.cross(i_v, unit)

使用

uvw = np.cross(i_v, unit)
uvw /= np.linalg.norm(uvw)

与您已经拥有的i_v = np.divide(i_v, np.sqrt(np.dot(i_v, i_v)))行基本相同.

Which is basically the same as the i_v = np.divide(i_v, np.sqrt(np.dot(i_v, i_v))) line you already had.

您可以做得更好,并完全避免触发:

You can do better though, and avoid trig entirely:

def get_rotation_matrix(i_v, unit=None):
    # From http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38
    if unit is None:
        unit = [1.0, 0.0, 0.0]
    # Normalize vector length
    i_v /= np.linalg.norm(i_v)

    # Get axis
    uvw = np.cross(i_v, unit)

    # compute trig values - no need to go through arccos and back
    rcos = np.dot(i_v, unit)
    rsin = np.linalg.norm(uvw)

    #normalize and unpack axis
    if not np.isclose(rsin, 0):
        uvw /= rsin
    u, v, w = uvw

    # Compute rotation matrix - re-expressed to show structure
    return (
        rcos * np.eye(3) +
        rsin * np.array([
            [ 0, -w,  v],
            [ w,  0, -u],
            [-v,  u,  0]
        ]) +
        (1.0 - rcos) * uvw[:,None] * uvw[None,:]
    )

最后一个表达式是维基百科页面上的等式:

That last expression is this equation from the wikipedia page:

这篇关于具有旋转矩阵的不精确度,可将向量对准轴的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆