4、二维旋转矩阵:旋转矩阵的推导、旋转矩阵的性质(正交性)

好,咱们今天聊聊二维旋转矩阵。这东西看着简单,但它是整个坐标变换的基石。我当年刚入行时,觉得不就是个旋转嘛,有啥好讲的?结果在调试一个机械臂的视觉抓取时,因为旋转方向搞反了,抓了三次都抓空,还被领导调侃说「你这机器人是在练太极吧」……从那以后,我对旋转矩阵就格外上心。

4.1 旋转矩阵的推导

先问个问题:一个点 P 在二维平面上,绕原点逆时针旋转 θ 角度后,新坐标怎么算?

假设原始坐标为 (x, y),用极坐标表示:

x = r * cos(α)
y = r * sin(α)

旋转 θ 后,新角度变成 α + θ,新坐标为:

x' = r * cos(α + θ)
y' = r * sin(α + θ)

用三角恒等式展开:

x' = r * (cosα * cosθ - sinα * sinθ) = x * cosθ - y * sinθ
y' = r * (sinα * cosθ + cosα * sinθ) = x * sinθ + y * cosθ

写成矩阵形式,就是:

[x']   [cosθ  -sinθ] [x]
[y'] = [sinθ   cosθ] [y]

这个 2×2 矩阵,就是二维旋转矩阵 R(θ)。

核心公式:

R(θ) = [[cosθ, -sinθ], [sinθ, cosθ]]

注意:这是逆时针旋转。顺时针的话,把 θ 换成 -θ 即可。

我个人习惯把旋转矩阵记成「上正下负」——第一行是 cosθ 和 -sinθ,第二行是 sinθ 和 cosθ。你想想看,这个结构其实很对称,对角线都是 cosθ,反对角线是 ±sinθ。

4.2 旋转矩阵的性质(正交性)

旋转矩阵有个非常重要的性质——正交性。说白了就是:R^T * R = I,也就是旋转矩阵的转置等于它的逆。

为什么会这样?我们来验证一下:

R(θ) = [[cosθ, -sinθ], [sinθ, cosθ]]

R^T(θ) = [[cosθ, sinθ], [-sinθ, cosθ]]

R^T * R = [[cosθ, sinθ], [-sinθ, cosθ]] * [[cosθ, -sinθ], [sinθ, cosθ]]
        = [[cos²θ + sin²θ, -cosθ*sinθ + sinθ*cosθ],
           [-sinθ*cosθ + cosθ*sinθ, sin²θ + cos²θ]]
        = [[1, 0], [0, 1]] = I

完美!这就是正交矩阵。

实用技巧:

正交性意味着:旋转矩阵的逆就是它的转置。在代码里,求逆矩阵很费时,但转置就是交换一下元素位置,几乎零成本。我在做实时仿真时,经常利用这个性质来加速计算。

正交性还带来两个推论:

  • 行列式为 ±1:对于旋转矩阵,行列式恒等于 +1。这保证了旋转不改变面积(或者说,不改变向量的「尺度」)。
  • 列向量是单位正交基:旋转矩阵的每一列都是单位向量,且两两正交。说白了,旋转矩阵就是把原来的坐标系「掰」成了另一个坐标系,但坐标轴之间还是垂直的,长度也没变。

避坑指南:

我曾经在写一个仿真程序时,手动构造了一个「旋转矩阵」,结果行列式算出来是 0.98。仿真跑了半小时,发现物体越转越小,最后缩成了一个点……检查了半天,原来是手抖把 sinθ 写成了 sin(θ/2)。记住:旋转矩阵的行列式必须严格等于 1,否则你的物体就会「缩水」或「膨胀」。

4.3 知识体系图

下面这张图,把二维旋转矩阵的核心逻辑串起来了:

二维旋转矩阵 极坐标表示 三角恒等式展开 矩阵形式 R(θ) 正交性 R^T R = I 行列式 det = +1 列向量单位正交 旋转矩阵 = 保长、保角、保面积

4.4 代码示例:验证正交性

光说不练假把式。咱们用 Python 验证一下:

import numpy as np

def rotation_matrix_2d(theta):
    """生成二维旋转矩阵(逆时针)"""
    c = np.cos(theta)
    s = np.sin(theta)
    return np.array([[c, -s], [s, c]])

theta = np.pi / 4  # 45度
R = rotation_matrix_2d(theta)

print("旋转矩阵 R:")
print(R)

print("\nR^T * R:")
print(R.T @ R)

print("\n行列式 det(R):")
print(np.linalg.det(R))

# 验证正交性
I = np.eye(2)
if np.allclose(R.T @ R, I):
    print("\n✅ 正交性验证通过!")
else:
    print("\n❌ 正交性验证失败!")

输出结果:

旋转矩阵 R:
[[ 0.70710678 -0.70710678]
 [ 0.70710678  0.70710678]]

R^T * R:
[[1. 0.]
 [0. 1.]]

行列式 det(R):
1.0

✅ 正交性验证通过!

嗯,完美。你看,R^T * R 就是单位矩阵,行列式也是 1。这就是旋转矩阵的「身份证」——只要满足这两个条件,它就是一个合法的旋转。

4.5 实际应用中的小坑

最后分享一个我踩过的坑。有一次做仿真,需要让一个物体连续旋转。我每次更新时都重新计算 R(θ),然后乘上当前坐标。结果发现物体在旋转过程中会「漂移」——位置越来越偏。

排查了半天,发现是浮点数精度问题。每次计算 cosθ 和 sinθ 都有微小误差,累积起来就不可忽视了。解决方案是:用四元数或者累积旋转矩阵,而不是每次都从角度重新算。当然,这是后话了,咱们后面章节会详细讲。

本章小结:

  • 二维旋转矩阵 R(θ) = [[cosθ, -sinθ], [sinθ, cosθ]]
  • 逆时针旋转用正 θ,顺时针用负 θ
  • 正交性:R^T = R^{-1},行列式 = 1
  • 旋转矩阵保长度、保角度、保面积

好了,二维旋转矩阵就聊到这儿。记住它的推导过程和正交性,后面三维旋转、齐次坐标变换都离不开这个基础。

可可精品资料库