0%

高级初始化

本章介绍矩阵初始化的一些高级方法,包括逗号初始化和一些特殊矩阵(单位矩阵、零矩阵)初始化

逗号初始化

  • 系数初始化顺序:从左上角开始,按从左到右,从上到下的顺序排列

  • 必须预先规定好矩阵/向量/数组的大小,否则会报错

  • 初始化列表的元素除了数值外,也可以是向量或矩阵,常用来连接几个向量或矩阵,同样必须预先规定好大小:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
RowVectorXd vec1(3);
vec1 << 1, 2, 3;
cout << "vec1 = " << vec1 << endl;

RowVectorXd vec2(4);
vec2 << 1, 4, 9, 16;
cout << "vec2 = " << vec2 << endl;

RowVectorXd joined(7);
joined << vec1, vec2;
cout << "joined = " << joined << endl;
}

输出:

1
2
3
vec1 = 1 2 3
vec2 = 1 4 9 16
joined = 1 2 3 1 4 9 16
  • 可以用同样的方法按块结构初始化矩阵:
1
2
3
4
5
6
7
8
int main()
{
MatrixXf matA(2, 2);
matA << 1, 2, 3, 4;
MatrixXf matB(4, 4);
matB << matA, matA/10, matA/10, matA;
cout << matB << endl;
}

输出:

1
2
3
4
  1   2 0.1 0.2
3 4 0.3 0.4
0.1 0.2 1 2
0.3 0.4 3 4
  • 逗号初始化也可以用来为块表达式赋值:
1
2
3
4
5
6
7
8
int main()
{
Matrix3f m;
m.row(0) << 1, 2, 3;
m.block(1,0,2,2) << 4, 5, 7, 8;
m.col(2).tail(2) << 6, 9;
cout << m;
}

输出:

1
2
3
1 2 3
4 5 6
7 8 9

特殊矩阵与数组

参考手册 Quick Reference Guide - Predefined Matrices

Zero()

初始化所有系数为0,共有三种形式:

  • Zero() : 不接收任何变量,仅用于固定大小的对象;
  • Zero(size) : 接收一个变量,仅用于一维动态大小的对象;
  • Zero(rows,cols) : 接收两个变量,仅用于二维动态大小的对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
cout << "A fixed-size array:\n";
Array33f a1 = Array33f::Zero();
cout << a1 << "\n\n";

cout << "A one-dimensional dynamic-size array:\n";
ArrayXf a2 = ArrayXf::Zero(3);
cout << a2 << "\n\n";

cout << "A two-dimensional dynamic-size array:\n";
ArrayXXf a3 = ArrayXXf::Zero(3, 4);
cout << a3 << "\n";
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
A fixed-size array:
0 0 0
0 0 0
0 0 0

A one-dimensional dynamic-size array:
0
0
0

A two-dimensional dynamic-size array:
0 0 0 0
0 0 0 0
0 0 0 0

Ones()

初始化所有系数为1,三种形式与 Zero() 相同

Random()

初始化所有系数为随机数,三种形式与 Zero() 相同

Constant(value)

初始化所有系数为value,同样三种形式:

  • Constant(value)
  • Constant(size,value)
  • Constant(rows,cols,value)

Identity()

返回单位矩阵,仅用于 Matrix 类,包括 Identity()Identity(rows,cols)

LinSpaced(size, low, high)

仅用于向量或一维数组,返回一个指定大小的向量,其系数在参数 lowhigh 之间等距分布

1
2
3
4
5
6
7
8
9
10
int main()
{
ArrayXXf table(10, 4);
table.col(0) = ArrayXf::LinSpaced(10, 0, 90);
table.col(1) = M_PI / 180 * table.col(0);
table.col(2) = table.col(1).sin();
table.col(3) = table.col(1).cos();
cout << " Degrees Radians Sine Cosine\n";
cout << table << std::endl;
}

输出:

1
2
3
4
5
6
7
8
9
10
11
Degrees   Radians      Sine    Cosine
0 0 0 1
10 0.175 0.174 0.985
20 0.349 0.342 0.94
30 0.524 0.5 0.866
40 0.698 0.643 0.766
50 0.873 0.766 0.643
60 1.05 0.866 0.5
70 1.22 0.94 0.342
80 1.4 0.985 0.174
90 1.57 1 -4.37e-08

从这些例子可以看出,上述方法都会返回一个矩阵或数组再赋值给变量(或表达式),方便起见,Eigen还定义了一些函数来方便地执行这些操作,例如 setZero() MatrixBase::setIdentity() DenseBase::setLinSpaced() 等。下面这个例程展示了如何使用静态方法、逗号初始化和 setXxx() 函数来初始化矩阵:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const int size = 6;
MatrixXd mat1(size, size);
mat1.topLeftCorner(size/2, size/2) = MatrixXd::Zero(size/2, size/2);
mat1.topRightCorner(size/2, size/2) = MatrixXd::Identity(size/2, size/2);
mat1.bottomLeftCorner(size/2, size/2) = MatrixXd::Identity(size/2, size/2);
mat1.bottomRightCorner(size/2, size/2) = MatrixXd::Zero(size/2, size/2);
std::cout << mat1 << std::endl << std::endl;

MatrixXd mat2(size, size);
mat2.topLeftCorner(size/2, size/2).setZero();
mat2.topRightCorner(size/2, size/2).setIdentity();
mat2.bottomLeftCorner(size/2, size/2).setIdentity();
mat2.bottomRightCorner(size/2, size/2).setZero();
std::cout << mat2 << std::endl << std::endl;

MatrixXd mat3(size, size);
mat3 << MatrixXd::Zero(size/2, size/2), MatrixXd::Identity(size/2, size/2),
MatrixXd::Identity(size/2, size/2), MatrixXd::Zero(size/2, size/2);
std::cout << mat3 << std::endl;

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0

0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0

0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0

除此之外,Eigen还定义了一些用于生成基向量的方法:

  • Vector3f::UnitX() : (1, 0, 0)
  • Vector3f::UnitY() : (0, 1, 0)
  • Vector3f::UnitZ() : (0, 0, 1)
  • VectorXf::Unit(size,i) :
    • 例如 :VectorXf::Unit(4,1) == Vector4f(0,1,0,0) == Vector4f::UnitY()

用作临时对象

无论是逗号初始化程序还是上面介绍的几种类内静态方法,都可以用作表达式中的临时对象。

逗号初始化程序用作临时对象时,需要调用 finished() 方法获取实际的矩阵对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
MatrixXd m = MatrixXd::Random(3,3);
m = (m + MatrixXd::Constant(3,3,1.2)) * 50;
cout << "m =" << endl << m << endl;
VectorXd v(3);
v << 1, 2, 3;
cout << "m * v =" << endl << m * v << endl;
MatrixXf mat = MatrixXf::Random(2, 3);
cout << "mat =\n" << mat << endl;
mat = (MatrixXf(2,2) << 0, 1, 1, 0).finished() * mat;
cout << "mat =\n" << mat << endl;
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
m =
10 55.9 14.7
23.2 63.3 77.9
85.6 31.9 77.9
m * v =
166
383
383
mat =
-1 0.511 0.0655
-0.737 -0.0827 -0.562
mat =
-0.737 -0.0827 -0.562
-1 0.511 0.0655