【发布时间】: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 相同的方向。
我已经设法实现了这一点,尽管通过可视化结果,很明显它们不是平行的。
## 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