线性代数定义:向量空间(列空间/行空间)的维数。
高斯消元法:主元(pivot)的数量。
行列式视角:满秩 <=> 行列式 != 0(对于方阵)。
数值视角:线性无关的行/列的最大数量。
几何视角:变换后的空间的维度。
SLAM上下文:为什么
rank() == 2意味着共面点?因为 (3x3) 矩阵points3 * points3.transpose()表示点的散布。如果点处于二维平面,其散布矩阵的秩为 2(一个维度退化)。
协方差矩阵的秩=2,就是分布在平面上。
1. 严谨的数学定义(抓本质)
矩阵的秩,指的是矩阵中线性无关的行(或列)向量的最大数目。
如果是 3×3的矩阵,秩最大是 3(称为满秩)。
如果秩是 2,说明虽然它有3行,但其中一行可以用另外两行线性组合出来,是“冗余”信息。
2. 几何直觉(结合SLAM理解)
把矩阵看作一个“空间变换器”:
秩 = 3:它能将一个三维立方体变换成一个三维体(体积不为零)。
秩 = 2:它将三维空间“拍扁”成一个平面(体积为零)。
秩 = 1:它将三维空间压成一条线。
3. 代码实锤:为什么用rankTest.rank() == 2来判断平面?
这正是你代码中最关键的一步:
cpp
Eigen::Matrix3d planarTest = points3 * points3.transpose(); // (3x3) // 如果 rankTest.rank() == 2,说明是平面场景
points3是所有 3D 点组成的 3×N 矩阵。planarTest是这个点集的协方差矩阵(未中心化)。如果所有点共面,那么这些点在三维空间中只分布在二维平面上,没有撑起一个“立体”。因此,这个矩阵的秩必定是2(零空间对应平面法向量方向)。
如果点是随机分布在三维空间(非共面),这个矩阵的秩就是3。
4. 秩在求解线性方程中的“致命”意义
秩直接决定了方程 Ax=b 有没有解、有多少解:
满秩(秩 = 未知数个数):解唯一(或者最小二乘解稳定)。
秩亏(秩 < 未知数个数):方程欠定,解不唯一,存在零空间(Nullspace)。
在MLPnP中的体现:正因为平面场景下矩阵秩亏为 2,旋转矩阵第三列无法通过线性方程直接解出(自由度消失),所以代码才专门
if (planar)将未知数colsA从 12 降为 9,并利用叉积tmp.col(0) = tmp.col(1).cross(tmp.col(2))强行补全旋转矩阵。
💎 一句话总结
矩阵的秩 = 矩阵撑起的空间维度。
秩大 = 信息丰富,约束强。
秩小 = 信息冗余,数据退化(比如共面),此时必须像代码里那样降维处理,否则数学上算不出稳定的解。