我有2个3D点,我想绕Y轴旋转:

  • A=(x1,y1,z1)
  • B=(x2,y2,z2)

而且,我还有另外两个3D点,它们将用作提取旋转Angular 约束的参考.

  • C=(x‘1,y’1,z‘1)
  • D=(x‘2,y’2,z‘2)

我想绕Y轴旋转点A和B,使得线段AB(z1—z2)的高度与线段CD(z'1—z'2)的高度相同.

(编辑:根据 comments ,下面的数字似乎不清楚.下图表示XZ平面上的3D点投影.其意图是示出点A和B的投影,点A和B将绕Y轴旋转,使得线段AB的高度(h = z1—z2)将等于线段CD的高度(h ′ = z ′ 1—z ′ 2)).

Visual representation

而且,线段AB将总是足够长,使得解总是存在.

为了做到这一点,我首先写下了沿着Y轴旋转点A和B并将它们设置为等于点C和D的方程.(我只对等式的最后一行感兴趣,以保留高度约束):

Rotation along Y equation

使用最后一行,我可以提取以下方程组:

System of equations

然后,为了求解这个方程组并求出Angular θ,我从第一个方程中减go 第二个方程,得到以下结果:

Equation 1 - Equation 2

在(z ′ 1—z ′ 2)= 0的情况下,可以容易地求解方程,并且可以如下计算Angular :

enter image description here

然而,我遇到了困难的情况下,(z'1—z'2)不为零.

I tried to solve for the case where (z'1-z'2) is non-zero by dividing the first equation by the second equation: case 2 method

然后,通过将方程的两边乘以分母,我就能够分离出一边的Angular θ,并计算arctan2,得到θ,如下所示:

Solution case 2

我理解,通过使用这个方法,我假设z'2为非零,以便有一个解.我也明白,我可以用方程组中的方程2除以方程1,我会得到分母,z '1,我会假设它也是非零的.

因此,我开发了一个Python函数,它使用上面的公式计算θ,并返回旋转矩阵,然后将其用于沿Y轴旋转A和B:

def get_rot_y(current_points, reference_points):
    (x1, y1, z1) = current_points[:, 0]
    (x2, y2, z2) = current_points[:, 1]
    (xp1, yp1, zp1) = reference_points[:, 0]
    (xp2, yp2, zp2) = reference_points[:, 1]

    if ((zp1-zp2) == 0):
        th = np.arctan2((z2-z1), (x2-x1))
    else:
        th = np.arctan2((-z1 + (zp1*z2 / zp2)), (-x1 + (zp1*x2 / zp2)))
    rot_y = np.array([
        [np.cos(th), 0, np.sin(th)],
        [0, 1, 0],
        [-np.sin(th), 0, np.cos(th)],
    ])
    return rot_y

然后,我测试了高度(z'1—z'2)为非零的情况下的函数:

A = np.array([1450, 0.5, -1545])
B = np.array([6000, 0.7, -1650])

C = np.array([1500, 0, -1500])
D = np.array([5600, 0, -1600])

current_height = A[2] - B[2]
desired_height = C[2] - D[2]

current_points = np.array([A, B]).T
reference_points = np.array([C, D]).T

rot_y = get_rot_y(current_points=current_points, reference_points=reference_points)
transfomed_points = rot_y @ current_points

transformed_height = transfomed_points[2,0] - transfomed_points[2,1]
print(f"current_height= {current_height}")
print(f"desired_height= {desired_height}")
print(f"transformed_height= {transformed_height}")

但是,当我执行代码时,我会得到以下输出:

current_height= 105.0
desired_height= 100
transformed_height= 102.95657644356697

如上所述,变换后的点的高度不等于期望的高度.

我做错了什么?对于我的问题,有没有一个解析解可以应用于(z'1—z'2)非零的情况?

推荐答案

预期Angular 为arcsin(h/L),其中h为预期高度(z差),L为投影到xz平面的节段长度.该平面中的电流角为atan2(z2—z1,x2—x1).所以,只要旋转(围绕y轴),以预期—电流Angular .

但要注意两件事.

首先,如果你不小心,arsin可能会给出错误的象限.

第二,你(和我)正在使用的公式找到从x到z的逆时针Angular ,就像你的图表中所画的那样(通常对x—y图做的那样,因为正z轴将不在你的图中).但是,绕y轴的正旋转将是顺时针旋转(因为对于右手坐标系,正y轴将进入您的图形).这在下面的代码中通过简单地反转Angular 变化来考虑.

import numpy as np

def rot_y( theta ):
    '''Right-handed rotation about the y axis'''
    return np.array( [ [  np.cos( theta ), 0, np.sin( theta ) ],
                       [      0          , 1,     0           ],
                       [ -np.sin( theta ), 0, np.cos( theta ) ] ] )


A = np.array( [ 1450, 0.5, -1545 ] )
B = np.array( [ 6000, 0.7, -1650 ] )

C = np.array( [ 1500,   0, -1500 ] )
D = np.array( [ 5600,   0, -1600 ] )

# Angle COUNTER-CLOCKWISE from X-AXIS (from x toward z)
current_angle = np.arctan2( B[2]-A[2], B[0]-A[0] )
desired_angle = np.arcsin ( ( D[2]-C[2] ) / np.sqrt( (B[0]-A[0])**2 + (B[2]-A[2])**2 ) )
if D[0]-C[0] < 0: desired_angle = np.pi - desired_angle       # Get correct quadrant for arcsin
theta = desired_angle - current_angle

# Note that a positive rotation about the y axis will go CLOCKWISE (i.e. from z toward x) ...
# ... so we need to reverse it
theta = -theta
R = rot_y( theta )

# Rotate about its centre
centre = ( A + B ) / 2
AP = centre + R @ ( A - centre ).T
BP = centre + R @ ( B - centre ).T

print( f"current_height = {(B[2]-A[2])}")
print( f"desired_height = {(D[2]-C[2])}")
print( f"transformed_height = {(BP[2]-AP[2])}" )

输出:

current_height = -105.0
desired_height = -100
transformed_height = -100.0

Python相关问答推荐

acme错误-Veritas错误:模块收件箱没有属性linear_util'

删除最后一个pip安装的包

Python 约束无法解决n皇后之谜

使用setuptools pyproject.toml和自定义目录树构建PyPi包

有没有一种方法可以从python的pussompy比较结果中提取文本?

如果条件不满足,我如何获得掩码的第一个索引并获得None?

pandas:排序多级列

python中字符串的条件替换

在Python中计算连续天数

基于另一列的GROUP-BY聚合将列添加到Polars LazyFrame

使用Openpyxl从Excel中的折线图更改图表样式

numpy数组和数组标量之间的不同行为

删除特定列后的所有列

遍历列表列表,然后创建数据帧

将相应的值从第2列合并到第1列(Pandas )

递归链表反转与打印语句挂起

Match-Case构造中的对象可调用性测试

两个名称相同但值不同的 Select 都会产生相同的值(discord.py)

try 在单个WITH_COLUMNS_SEQ操作中链接表达式时,使用Polars数据帧时出现ComputeError

对当前的鼹鼠进行编码,并且我的按键获得了注册