Rotation#
- class scipy.spatial.transform.Rotation(quat, normalize=True, copy=True, scalar_first=False)[source]#
三维空间中的旋转。
此类提供了一个接口,用于通过以下方式初始化和表示旋转:
四元数 (Quaternions)
旋转矩阵 (Rotation Matrices)
旋转向量 (Rotation Vectors)
修正罗德里格参数 (Modified Rodrigues Parameters)
欧拉角 (Euler Angles)
达文波特角 (Davenport Angles,广义欧拉角)
支持以下旋转运算:
应用于向量
旋转合成
旋转求逆
旋转索引
Rotation实例可以包含单个旋转变换或具有多个前导维度的旋转。例如,可以拥有 (N, M, K) 个旋转的 N 维数组。当应用于其他旋转或向量时,遵循标准的广播规则。支持旋转内部索引,以访问
Rotation实例中存储的旋转子集。要创建
Rotation对象,请使用from_...方法(见下文示例)。不应直接实例化Rotation(...)。- 参数:
- quatarray_like, shape (…, 4)
表示旋转的四元数。
- normalizebool, optional
如果为 True,则使用奇异值分解对旋转矩阵进行正交归一化。如果为 False,则不对旋转矩阵进行正交性或右手性的检查。
- copybool,可选
如果为 True,则复制输入矩阵。如果为 False,则使用对输入矩阵的引用。如果 normalize 为 True,则无论 copy 的值如何,都会复制输入矩阵。
- scalar_firstbool, 可选
如果
True,则期望 quat 采用标量在前 (scalar-first) 的格式,否则期望采用标量在后 (scalar-last) 的格式。默认为False。
- 属性:
单个该实例是否表示单个旋转。
方法
__len__()此对象中包含的旋转数量。
from_quat(quat, *[, scalar_first])通过四元数初始化。
from_matrix(matrix, *[, assume_valid])通过旋转矩阵初始化。
from_rotvec(rotvec[, degrees])通过旋转向量初始化。
from_mrp(mrp)通过修正罗德里格参数 (MRP) 初始化。
from_euler(seq, angles[, degrees])通过欧拉角初始化。
from_davenport(axes, order, angles[, degrees])通过达文波特角初始化。
as_quat([canonical, scalar_first])表示为四元数。
表示为旋转矩阵。
as_rotvec([degrees])表示为旋转向量。
as_mrp()表示为修正罗德里格参数 (MRP)。
as_euler(seq[, degrees, suppress_warnings])表示为欧拉角。
as_davenport(axes, order[, degrees, ...])表示为达文波特角。
concatenate(rotations)将一系列
Rotation对象拼接成单个对象。apply(vectors[, inverse])将此旋转应用于一组向量。
__mul__(other)将此旋转与其他旋转进行合成。
__pow__(n[, modulus])将此旋转与其自身合成 n 次。
inv()此旋转求逆。
获取旋转的大小。
approx_equal(other[, atol, degrees])确定另一个旋转是否与当前旋转近似相等。
mean([weights, axis])获取旋转的平均值。
reduce([left, right, return_indices])利用提供的旋转组简化此旋转。
create_group(group[, axis])创建一个三维旋转组。
__getitem__(indexer)从对象中提取给定索引处的旋转。
identity([num, shape])获取单位旋转 (Identity Rotation)。
random([num, rng, shape, random_state])生成在球面上均匀分布的旋转。
align_vectors(a, b[, weights, ...])估计一个旋转以最优地对齐两组向量。
另请参阅
附注
在 1.2.0 版本中添加。
数组 API 标准支持
Rotation除了 NumPy 之外,还对符合 Python Array API 标准的后端提供了实验性支持。请考虑通过设置环境变量SCIPY_ARRAY_API=1并提供 CuPy、PyTorch、JAX 或 Dask 数组作为数组参数来测试这些功能。支持后端和设备(或其他功能)的以下组合。库
CPU
GPU
NumPy
✅
不适用
CuPy
不适用
✅
PyTorch
✅
✅
JAX
✅
✅
Dask
⛔
不适用
方法
as_davenport、apply和align_vectors在 cupy<14.* 中不受支持。有关更多信息,请参阅 对数组 API 标准的支持。
示例
>>> from scipy.spatial.transform import Rotation as R >>> import numpy as np
Rotation实例可以使用上述任何格式初始化,并转换为其他任何格式。基础对象独立于初始化时使用的表示形式。考虑绕 z 轴逆时针旋转 90 度。这对应于以下四元数(采用标量在后格式)
>>> r = R.from_quat([0, 0, np.sin(np.pi/4), np.cos(np.pi/4)])
该旋转可以用其他任何格式表示
>>> r.as_matrix() array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) >>> r.as_rotvec() array([0. , 0. , 1.57079633]) >>> r.as_euler('zyx', degrees=True) array([90., 0., 0.])
同样的旋转可以使用旋转矩阵进行初始化
>>> r = R.from_matrix([[0, -1, 0], ... [1, 0, 0], ... [0, 0, 1]])
其他格式的表示
>>> r.as_quat() array([0. , 0. , 0.70710678, 0.70710678]) >>> r.as_rotvec() array([0. , 0. , 1.57079633]) >>> r.as_euler('zyx', degrees=True) array([90., 0., 0.])
对应于此旋转的旋转向量由下式给出
>>> r = R.from_rotvec(np.pi/2 * np.array([0, 0, 1]))
其他格式的表示
>>> r.as_quat() array([0. , 0. , 0.70710678, 0.70710678]) >>> r.as_matrix() array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) >>> r.as_euler('zyx', degrees=True) array([90., 0., 0.])
from_euler方法在其支持的输入格式范围方面非常灵活。此处我们初始化绕单轴的单个旋转>>> r = R.from_euler('z', 90, degrees=True)
同样,该对象独立于表示形式,可以转换为任何其他格式
>>> r.as_quat() array([0. , 0. , 0.70710678, 0.70710678]) >>> r.as_matrix() array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) >>> r.as_rotvec() array([0. , 0. , 1.57079633])
还可以使用任何
from_...函数在单个实例中初始化多个旋转。此处我们使用from_euler方法初始化一组 3 个旋转>>> r = R.from_euler('zyx', [ ... [90, 0, 0], ... [0, 45, 0], ... [45, 60, 30]], degrees=True)
其他表示形式现在也返回一组 3 个旋转。例如
>>> r.as_quat() array([[0. , 0. , 0.70710678, 0.70710678], [0. , 0.38268343, 0. , 0.92387953], [0.39190384, 0.36042341, 0.43967974, 0.72331741]])
将上述旋转应用于向量
>>> v = [1, 2, 3] >>> r.apply(v) array([[-2. , 1. , 3. ], [ 2.82842712, 2. , 1.41421356], [ 2.24452282, 0.78093109, 2.89002836]])
Rotation实例可以像 ND 数组一样进行索引和切片>>> r.as_quat() array([[0. , 0. , 0.70710678, 0.70710678], [0. , 0.38268343, 0. , 0.92387953], [0.39190384, 0.36042341, 0.43967974, 0.72331741]]) >>> p = r[0] >>> p.as_matrix() array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) >>> q = r[1:3] >>> q.as_quat() array([[0. , 0.38268343, 0. , 0.92387953], [0.39190384, 0.36042341, 0.43967974, 0.72331741]])
事实上,它可以转换为 numpy.array
>>> r_array = np.asarray(r) >>> r_array.shape (3,) >>> r_array[0].as_matrix() array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]])
可以使用
*运算符组合多个旋转>>> r1 = R.from_euler('z', 90, degrees=True) >>> r2 = R.from_rotvec([np.pi/4, 0, 0]) >>> v = [1, 2, 3] >>> r2.apply(r1.apply(v)) array([-2. , -1.41421356, 2.82842712]) >>> r3 = r2 * r1 # Note the order >>> r3.apply(v) array([-2. , -1.41421356, 2.82842712])
可以使用
**运算符将旋转与其自身组合>>> p = R.from_rotvec([1, 0, 0]) >>> q = p ** 2 >>> q.as_rotvec() array([2., 0., 0.])
最后,也可以对旋转求逆
>>> r1 = R.from_euler('z', [[90], [45]], degrees=True) >>> r2 = r1.inv() >>> r2.as_euler('zyx', degrees=True) array([[-90., 0., 0.], [-45., 0., 0.]])
以下函数可用于通过显示旋转如何变换标准 x、y、z 坐标轴来使用 Matplotlib 绘制旋转
>>> import matplotlib.pyplot as plt
>>> def plot_rotated_axes(ax, r, name=None, offset=(0, 0, 0), scale=1): ... colors = ("#FF6666", "#005533", "#1199EE") # Colorblind-safe RGB ... loc = np.array([offset, offset]) ... for i, (axis, c) in enumerate(zip((ax.xaxis, ax.yaxis, ax.zaxis), ... colors)): ... axlabel = axis.axis_name ... axis.set_label_text(axlabel) ... axis.label.set_color(c) ... axis.line.set_color(c) ... axis.set_tick_params(colors=c) ... line = np.zeros((2, 3)) ... line[1, i] = scale ... line_rot = r.apply(line) ... line_plot = line_rot + loc ... ax.plot(line_plot[:, 0], line_plot[:, 1], line_plot[:, 2], c) ... text_loc = line[1]*1.2 ... text_loc_rot = r.apply(text_loc) ... text_plot = text_loc_rot + loc[0] ... ax.text(*text_plot, axlabel.upper(), color=c, ... va="center", ha="center") ... ax.text(*offset, name, color="k", va="center", ha="center", ... bbox={"fc": "w", "alpha": 0.8, "boxstyle": "circle"})
创建三个旋转 - 单位旋转以及使用内禀 (intrinsic) 和外禀 (extrinsic) 约定的两个欧拉旋转
>>> r0 = R.identity() >>> r1 = R.from_euler("ZYX", [90, -30, 0], degrees=True) # intrinsic >>> r2 = R.from_euler("zyx", [90, -30, 0], degrees=True) # extrinsic
将所有三个旋转添加到同一绘图中
>>> ax = plt.figure().add_subplot(projection="3d", proj_type="ortho") >>> plot_rotated_axes(ax, r0, name="r0", offset=(0, 0, 0)) >>> plot_rotated_axes(ax, r1, name="r1", offset=(3, 0, 0)) >>> plot_rotated_axes(ax, r2, name="r2", offset=(6, 0, 0)) >>> _ = ax.annotate( ... "r0: Identity Rotation\n" ... "r1: Intrinsic Euler Rotation (ZYX)\n" ... "r2: Extrinsic Euler Rotation (zyx)", ... xy=(0.6, 0.7), xycoords="axes fraction", ha="left" ... ) >>> ax.set(xlim=(-1.25, 7.25), ylim=(-1.25, 1.25), zlim=(-1.25, 1.25)) >>> ax.set(xticks=range(-1, 8), yticks=[-1, 0, 1], zticks=[-1, 0, 1]) >>> ax.set_aspect("equal", adjustable="box") >>> ax.figure.set_size_inches(6, 5) >>> plt.tight_layout()
显示绘图
>>> plt.show()
这些示例概述了
Rotation类并突出了主要功能。有关支持的输入和输出格式范围的更详尽示例,请查阅各个方法的示例。