简体   繁体   English

3D 中的相对旋转

[英]relative rotation in 3D

I have an object (XYZ-coordinate system where Z is up) that rotates from t0 to t1 with the corresponding rotation matrices:我有一个 object (Z 向上的 XYZ 坐标系),它使用相应的旋转矩阵从 t0 旋转到 t1:

import numpy as np
from scipy.spatial.transform import Rotation as R
r_0 = np.array([[-0.02659679, -0.00281247,  0.99964229],
                [ 0.76308514, -0.64603356,  0.01848528],
                [ 0.64575048,  0.76330382,  0.01932857]])

r_1 = np.array([[ 0.05114056, -0.03815443,  0.99796237],
               [-0.30594799,  0.95062582,  0.05202294],
               [-0.95067369, -0.30798506,  0.03694226]])

# Calculate the relative rotation matrix from t0 to t1
rot_mat_rel = np.matmul(np.transpose(r_0), r_1)
r = R.from_maxtrix(rot_mat_rel)
# Obtain angles
print(r.as_euler('xyz', degrees=True)

# Result
array([  -1.52028392,   -1.55242217, -148.10677483])

The problem is, that the relative angles look wrong to me but I can't find my mistake.问题是,相对角度对我来说看起来不对,但我找不到我的错误。 What I wanted to know is how much the object rotated along x, y and z.我想知道的是 object 沿 x、y 和 z 旋转了多少。

Edit: Code to for plots: https://codeshare.io/GA9zK8编辑:绘图代码: https://codeshare.io/GA9zK8

You can use matrix_from_euler_xyz from this tutorial to check your results.您可以使用本教程中的matrix_from_euler_xyz来检查您的结果。

(You might need to run pip3 install pytransform3d in your terminal where you are running your python code from, or !pip3 install pytransform3d from Jupyter Notebook if you are using that.) (您可能需要在运行 python 代码的终端中运行pip3 install pytransform3d ,或者如果您正在使用 Jupyter Notebook 中的!pip3 install pytransform3d 。)

Preparing the data:准备数据:

import numpy as np
from scipy.spatial.transform import Rotation as R
r_0 = np.array([[-0.02659679, -0.00281247,  0.99964229],
                [ 0.76308514, -0.64603356,  0.01848528],
                [ 0.64575048,  0.76330382,  0.01932857]])

r_1 = np.array([[ 0.05114056, -0.03815443,  0.99796237],
                [-0.30594799,  0.95062582,  0.05202294],
                [-0.95067369, -0.30798506,  0.03694226]])

# Calculate the relative rotation matrix from t0 to t1
rot_mat_rel = np.matmul(np.transpose(r_0), r_1)
r = R.from_matrix(rot_mat_rel)

Let's plot what the rotation r means in practice:让我们 plot 旋转r在实践中的含义:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from pytransform3d.rotations import *

ax = plot_basis(R=np.eye(3), ax_s=1)

p = np.array([0, 0, 0])

R = matrix_from_euler_xyz(r.as_euler('xyz'))
plot_basis(ax, R, p, alpha = 0.5)

plt.show()

We obtain this plot:我们得到这个 plot:

在此处输入图像描述

You can check if this is what you expected or not.您可以检查这是否是您所期望的。

Check the rotation matrix which the pytransform3d module calculated from Euler angles r :检查pytransform3d模块从欧拉角r计算的旋转矩阵:

matrix_from_euler_xyz(r.as_euler('xyz'))

Giving ouput:给出输出:

array([[-0.84872253, -0.52814402,  0.02709157],
       [ 0.52754172, -0.84911505, -0.02652111],
       [ 0.03701082, -0.00821713,  0.99928108]])

which is exactly the traspose of np.matmul(np.transpose(r_0), r_1) :这正是np.matmul(np.transpose(r_0), r_1)的转置:

array([[-0.84872253,  0.52754172,  0.03701082],
       [-0.52814402, -0.84911505, -0.00821714],
       [ 0.02709157, -0.02652111,  0.99928109]])

Which seems a good sign & may be a good starting point for checking your math.这似乎是一个好兆头,可能是检查数学的一个很好的起点。

As I don't see what you would expect to get, I suggest you experiment with plotting your results with the tools outlined here, and check step by step that what you have is what you have expected to have.由于我看不到您期望得到什么,我建议您尝试使用此处概述的工具绘制结果,并逐步检查您所拥有的就是您所期望的。

I'm probably a bit late and zabop's answer already points to the right direction.我可能有点晚了,zabop 的回答已经指向了正确的方向。 I just want to clarify two things.我只想澄清两件事。

There are several ambiguities when we work with transformations that can make things more confusing.当我们使用可能使事情变得更加混乱的转换时,有几个模棱两可。 The two things that might make the code here a bit confusing are:可能使这里的代码有点混乱的两件事是:

I'm starting from your example above:我从你上面的例子开始:

import numpy as np
r_0 = np.array([[-0.02659679, -0.00281247,  0.99964229],
                [ 0.76308514, -0.64603356,  0.01848528],
                [ 0.64575048,  0.76330382,  0.01932857]])
r_1 = np.array([[ 0.05114056, -0.03815443,  0.99796237],
                [-0.30594799,  0.95062582,  0.05202294],
                [-0.95067369, -0.30798506,  0.03694226]])

The way I would calculate a rotation matrix that rotates r_0 to r_1 is the following (different from your code:):我计算将r_0旋转到r_1的旋转矩阵的方式如下(与您的代码不同:):

r0_to_r1 = r_1.dot(r_0.T)
r0_to_r1

Result:结果:

array([[ 0.99635252,  0.08212126,  0.0231898 ],
       [ 0.05746796, -0.84663889,  0.52905579],
       [ 0.06308011, -0.52579339, -0.84827012]])

I use the extrinsic convention for concatenation of rotation matrices, that is, r_1 is applied after r_0.T .我使用外部约定来连接旋转矩阵,即r_1r_0.T之后应用。 (If r_0 and r_1 were real numbers, we would write r_1 - r_0 to obtain a number that transforms r_0 to r_1 .) (如果r_0r_1是实数,我们将编写r_1 - r_0以获得将r_0转换为r_1的数字。)

You can verify that r0_to_r1 rotates from r_0 to r_1 :您可以验证r0_to_r1r_0旋转到r_1

from numpy.testing import assert_array_almost_equal
# verify correctness: apply r0_to_r1 after r_0
assert_array_almost_equal(r_1, r0_to_r1.dot(r_0))
# would raise an error if test fails

Anyway, the intrinsic convention would also work:无论如何,内在约定也可以工作:

r0_to_r1_intrinsic = r_0.T.dot(r_1)
assert_array_almost_equal(r_1, r_0.dot(r0_to_r1_intrinsic))

Since zabop introduced pytransform3d, I would also like to clarify that scipy uses active rotation matrices and the rotation matrix that pytransform3d.rotations.euler_xyz_from_matrix produces is a passive rotation matrix.由于zabop引入了pytransform3d,我还要澄清scipy使用主动旋转矩阵,而pytransform3d.rotations.euler_xyz_from_matrix产生的旋转矩阵是被动旋转矩阵。 This wasn't documented so clearly in previous versions.这在以前的版本中没有如此清楚地记录。 You can transform an active rotation matrix to a passive rotation matrix and vice versa with the matrix transpose.您可以使用矩阵转置将主动旋转矩阵转换为被动旋转矩阵,反之亦然。 Both pytransform3d's function and scipy's Rotation.to_euler("xyz", ...) use the intrinsic concatenation convention . pytransform3d 的 function 和 scipy 的Rotation.to_euler("xyz", ...)都使用内部连接约定

from scipy.spatial.transform import Rotation as R
r = R.from_matrix(r0_to_r1)
euler_xyz_intrinsic_active_degrees = r.as_euler('xyz', degrees=True)
euler_xyz_intrinsic_active_degrees

Result: array([-148.20762964, -3.6166255, 3.30106818])结果: array([-148.20762964, -3.6166255, 3.30106818])

You can obtain the same result with pytransform3d (note that we obtain the passive rotation matrix by .T ):您可以使用 pytransform3d 获得相同的结果(请注意,我们通过.T获得被动旋转矩阵):

import pytransform3d.rotations as pr
euler_xyz_intrinsic_active_radians = pr.euler_xyz_from_matrix(r0_to_r1.T)
np.rad2deg(euler_xyz_intrinsic_active_radians)

Result: array([-148.20762951, -3.61662542, 3.30106799])结果: array([-148.20762951, -3.61662542, 3.30106799])

You can also obtain the rotation matrix from euler angles with pytransform3d (note that we obtain the active rotation matrix by .T ):您还可以使用 pytransform3d 从欧拉角获取旋转矩阵(请注意,我们通过.T获取活动旋转矩阵):

r0_to_r1_from_euler = pr.matrix_from_euler_xyz(euler_xyz_intrinsic_active_radians).T
r0_to_r1_from_euler

Result:结果:

array([[ 0.99635251,  0.08212125,  0.0231898 ],
       [ 0.05746796, -0.84663889,  0.52905579],
       [ 0.06308011, -0.52579339, -0.84827013]])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM