数学基础(上):向量与矩阵运算、坐标变换与齐次变换矩阵、旋转矩阵与欧拉角、四元数基础

各位同学,欢迎来到轨迹规划的第一站。说实话,很多初学者一上来就啃算法,结果被各种坐标系绕晕了。我当年刚入行时也踩过这个坑——明明代码逻辑没问题,机器人就是走不对位置。后来才发现,是数学基础没打牢。

这一章,咱们就把这些「地基」夯实。你想想看,轨迹规划说白了就是让机器人知道:我在哪、要去哪、怎么去。这三个问题,全得靠数学语言来描述。

核心观点:轨迹规划的本质,是在不同坐标系之间反复做「翻译」。向量、矩阵、齐次变换、旋转表示法,就是这套翻译系统的语法和词汇。

2.1 向量与矩阵运算——机器人的「语言」

先聊向量。我习惯把向量理解成「带箭头的一段位移」。在三维空间里,一个位置点可以用向量 [x, y, z]^T 表示。但注意,向量本身不绑定坐标系——它只是一个数学对象。

矩阵呢?说白了就是「批量处理向量的工具」。比如你要把空间里100个点同时旋转,用矩阵乘法一行代码搞定。我在做机械臂逆解时,经常用矩阵来组织多个关节的位姿数据。

这里有个关键运算,大家务必烂熟于心:

// 向量点积:判断两个方向是否一致
double dot = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;

// 向量叉积:求垂直于两个向量的新方向
Vector3 cross = new Vector3(
    v1.y * v2.z - v1.z * v2.y,
    v1.z * v2.x - v1.x * v2.z,
    v1.x * v2.y - v1.y * v2.x
);

// 矩阵乘法:组合变换
Matrix4x4 result = matA * matB;  // 注意顺序!先B后A

我的习惯:写代码时,我会把向量运算封装成静态工具类。比如 VectorUtils.Dot()MatrixUtils.Multiply()。这样主逻辑里看起来清爽,调试时也容易定位问题。

2.2 坐标变换与齐次变换矩阵——从A系到B系

好,现在进入重头戏。为什么需要坐标变换?举个例子:你让机械臂去抓桌上的杯子。杯子的坐标是在「世界坐标系」下定义的,但机械臂末端执行器是在「工具坐标系」下运动的。你得把杯子的坐标换算到工具坐标系里,机械臂才知道怎么动。

齐次变换矩阵 T 就是干这个的。它长这样:

T = | R   t |
    | 0   1 |

其中 R 是3x3旋转矩阵,t 是3x1平移向量。用4x4矩阵的好处是:旋转和平移可以写在一个矩阵里,一次乘法搞定

我曾经在AGV导航项目里吃过亏——忘了齐次矩阵的乘法顺序。记住:T_AB * v_B = v_A,意思是「把B系下的向量变换到A系」。如果你写反了,机器人会往反方向跑。

避坑指南:我曾经调试一个视觉抓取程序,发现机械臂总是差5厘米。查了两天,最后发现是齐次矩阵的平移向量单位搞错了——毫米和米混用了。所以,务必在代码里统一单位,我习惯在矩阵类里加一个 UnitType 枚举。

2.3 旋转矩阵与欧拉角——绕来绕去的学问

旋转矩阵 R 是正交矩阵,行列式为+1。它描述了一个坐标系相对于另一个坐标系的朝向。但直接用9个参数表示旋转,太冗余了。所以工程上常用欧拉角。

欧拉角就是三个角度:绕X轴转(滚转Roll)、绕Y轴转(俯仰Pitch)、绕Z轴转(偏航Yaw)。但这里有个大坑——万向锁。当Pitch接近±90°时,Roll和Yaw会变得无法区分。我在做无人机姿态控制时遇到过这个问题,飞控突然乱转,吓得我赶紧切了手动模式。

所以,我的建议是:

  • 人机交互时用欧拉角(直观,好理解)
  • 内部计算时用旋转矩阵或四元数(避免万向锁)

欧拉角转旋转矩阵的公式(ZYX顺序):

R = Rz(yaw) * Ry(pitch) * Rx(roll)

其中:
Rz(yaw)   = | cos(yaw)  -sin(yaw)  0 |
            | sin(yaw)   cos(yaw)  0 |
            | 0          0         1 |

Ry(pitch) = | cos(pitch)  0  sin(pitch) |
            | 0           1  0          |
            | -sin(pitch) 0  cos(pitch) |

Rx(roll)  = | 1  0          0         |
            | 0  cos(roll)  -sin(roll)|
            | 0  sin(roll)  cos(roll) |

重要:旋转矩阵的乘法顺序不可交换。先绕X转再绕Y转,和先绕Y转再绕X转,结果完全不同。我习惯在代码注释里写明「当前使用的是ZYX顺序,外旋」。这样半年后回来看代码,自己还能看懂。

2.4 四元数基础——旋转的「瑞士军刀」

四元数,听起来玄乎,其实就是一个四维向量 [w, x, y, z]。它表示绕某个轴旋转某个角度。为什么用它?三个理由:

  1. 无万向锁——这是最大的优势
  2. 插值平滑——做轨迹规划时,用四元数球面插值(Slerp)能得到非常平滑的旋转过渡
  3. 计算高效——比旋转矩阵少用4个浮点数

四元数乘法对应旋转的复合:

// 四元数乘法(哈密顿积)
Quaternion q = q1 * q2;  // 先应用q2,再应用q1

// 用四元数旋转向量
Vector3 v_rotated = q * v * q.conjugate();

// 球面线性插值
Quaternion q_slerp = Quaternion.Slerp(q_start, q_end, t);  // t从0到1

我记得第一次用四元数做机械臂轨迹规划时,发现末端执行器的姿态变化特别丝滑。相比之下,用欧拉角做插值,中间会突然「跳一下」。嗯,这就是四元数的魅力。

实用技巧:调试四元数时,我习惯把它转成「轴角」形式打印出来——axis = [x, y, z] / sin(theta/2)angle = 2 * acos(w)。这样一眼就能看出旋转轴和角度,比看四个数字直观多了。

知识体系总览

下面这张图,把本章的核心逻辑串起来了。你可以把它当作一个「导航图」——学完每个知识点后,回来看看它在整个体系中的位置。

数学基础(上)知识体系 轨迹规划数学基础 向量与矩阵运算 坐标变换与齐次矩阵 旋转矩阵与欧拉角 四元数基础 点积·叉积·矩阵乘法 T = [R|t] · 坐标系变换链 万向锁 · ZYX顺序 无万向锁 · Slerp插值 核心:用数学语言描述「位置 + 姿态」

好了,这一章的内容就到这里。向量和矩阵是基本功,齐次变换是核心工具,旋转表示法各有优劣。我个人建议:先吃透齐次变换矩阵,再根据场景选旋转表示法。做轨迹规划时,大部分时间你都在跟4x4矩阵打交道。

下一章,咱们会继续深入数学基础,聊聊微分运动学、雅可比矩阵这些更「动态」的东西。到时候你会发现,今天学的这些静态变换,是理解一切运动的基础。


专注资料整理