三维向量的旋转?

87 投票
11 回答
166206 浏览
提问于 2025-04-16 22:08

我有两个向量,都是Python的列表,还有一个角度。例如:

v = [3, 5, 0]
axis = [4, 4, 1]
theta = 1.2  # In radians.

有什么简单的方法可以得到当我围绕axis向量旋转v向量后得到的结果向量吗?

旋转的方向应该是逆时针的,假设有一个观察者,他的视线正对着axis向量。这种旋转方式被称为右手法则

11 个回答

57

这是一个简单的一行代码,使用了numpy和scipy的函数。

我们用到以下内容:

a 是沿着 axis 的单位向量,也就是 a = axis/norm(axis)
A = I × a 是与 a 相关的反对称矩阵,也就是单位矩阵和 a 的叉乘

那么 M = exp(θ A) 就是旋转矩阵。

from numpy import cross, eye, dot
from scipy.linalg import expm, norm

def M(axis, theta):
    return expm(cross(eye(3), axis/norm(axis)*theta))

v, axis, theta = [3,5,0], [4,4,1], 1.2
M0 = M(axis, theta)

print(dot(M0,v))
# [ 2.74911638  4.77180932  1.91629719]

expm (代码在这里) 计算指数的泰勒级数:
\sum_{k=0}^{20} \frac{1}{k!} (θ A)^k ,这个计算比较耗时,但可读性强且安全。如果你需要进行少量旋转但有很多向量,这种方法是个不错的选择。

134

使用 欧拉-罗德里格斯公式

import numpy as np
import math

def rotation_matrix(axis, theta):
    """
    Return the rotation matrix associated with counterclockwise rotation about
    the given axis by theta radians.
    """
    axis = np.asarray(axis)
    axis = axis / math.sqrt(np.dot(axis, axis))
    a = math.cos(theta / 2.0)
    b, c, d = -axis * math.sin(theta / 2.0)
    aa, bb, cc, dd = 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 np.array([[aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac)],
                     [2 * (bc - ad), aa + cc - bb - dd, 2 * (cd + ab)],
                     [2 * (bd + ac), 2 * (cd - ab), aa + dd - bb - cc]])

v = [3, 5, 0]
axis = [4, 4, 1]
theta = 1.2 

print(np.dot(rotation_matrix(axis, theta), v)) 
# [ 2.74911638  4.77180932  1.91629719]
13

你可以看看这个链接:http://vpython.org/contents/docs/visual/VisualIntro.html

这里有一个叫做 vector 的类,它里面有一个方法 A.rotate(theta,B)。如果你不想直接在 A 上调用这个方法,它还提供了一个辅助函数 rotate(A,theta,B)

更多信息可以查看这个链接:http://vpython.org/contents/docs/visual/vector.html

撰写回答