In the previous article, some basic operations were briefly introduced. To return to the previous content, you can refer to the link:
Basic instructions for using zEigen library_Daily Yixue's blog-CSDN blog_eigen library
The main content of this chapter is to continue to extend the use of Eigen library and update it in real time. Eigen library is widely used in SLAM, so you need to be familiar with this library.
1. Assignment operation
First of all, how to assign a value to the applied matrix object in the simplest way?
1. When defining objects
//这里以动态的矩阵模板为例子
MatrixXi a { // 创建 2x2 matrix
{1, 2}, // first row
{3, 4} // second row
};
Matrix<int, 1, 5> c = {1, 2, 3, 4, 5};
2. <<Operation
Similar to input stream
Matrix3f m;
m << 1, 2, 3,
4, 5, 6,
7, 8, 9;
3. (,) assignment
Note that this is different from the array, it uses [] index
Eigen::MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
The two main types used here are multidimensional 2 and 3.
2. Matrix and vector operations
Eigen provides matrix/vector arithmetic by overloading common C++ arithmetic operators (such as +, -, *) or through special methods (such as dot(), cross(), etc.) Operation. For the Matrix class (matrices and vectors), operators are only overloaded to support linear algebra operations. For example, matrix1
*
matrix2
means matrix-matrix product, and vector
+
scalar(一个数)
is not allowed.
1. Addition and subtraction
To perform addition and subtraction operations, first the matrix types must be the same, and the matrix sizes must also be the same to perform the operation.
- Binary operator + such as
a+b
- Binary operators - such as
a-b
- Unary operators - such as
-a
- Compound operator += such as
a+=b
- Compound operator -= e.g.
a-=b
#include <iostream>
#include <Eigen/Dense>
int main()
{
Eigen::Matrix2d a;
a << 1, 2,
3, 4;
Eigen::MatrixXd b(2,2);
b << 2, 3,
1, 4;
std::cout << "a + b =\n" << a + b << std::endl;
std::cout << "a - b =\n" << a - b << std::endl;
std::cout << "Doing a += b;" << std::endl;
a += b;
std::cout << "Now a =\n" << a << std::endl;
Eigen::Vector3d v(1,2,3);
Eigen::Vector3d w(1,0,0);
std::cout << "-v + w - v =\n" << -v + w - v << std::endl;
}
Output:
a + b = 3 5 4 8 a - b = -1 -1 2 0 Doing a += b; Now a = 3 5 4 8 -v + w - v = -1 -4 -6
2. Scalar multiplication and division
- Binary operator * such as
matrix*scalar
- Binary operator * such as
scalar*matrix
- Binary operator / e.g.
matrix/scalar
- Compound operator *= such as
matrix*=scalar
- Compound operator /= e.g.
matrix/=scalar
#include <iostream>
#include <Eigen/Dense>
int main()
{
Eigen::Matrix2d a;
a << 1, 2,
3, 4;
Eigen::Vector3d v(1,2,3);
std::cout << "a * 2.5 =\n" << a * 2.5 << std::endl;
std::cout << "0.1 * v =\n" << 0.1 * v << std::endl;
std::cout << "Doing v *= 2;" << std::endl;
v *= 2;
std::cout << "Now v =\n" << v << std::endl;
}
Output:
a * 2.5 = 2.5 5 7.5 10 0.1 * v = 0.1 0.2 0.3 Doing v *= 2; Now v = 2 4 6
3. Transposition and conjugation
The transpose, conjugate and adjoint (i.e. the transpose of the conjugate) of the matrix a, the member functions are: transpose(), conjugate() and adjoint() respectively. For real-number matrix conjugate conjugate operations are actually empty operations, which are actually accompanied by transposes.
MatrixXcf a = MatrixXcf::Random(2,2);
cout << "Here is the matrix a\n" << a << endl;
cout << "Here is the matrix a^T\n" << a.transpose() << endl;
cout << "Here is the conjugate of a\n" << a.conjugate() << endl;
cout << "Here is the matrix a^*\n" << a.adjoint() << endl;
//输出
ere is the matrix a
(-0.211,0.68) (-0.605,0.823)
(0.597,0.566) (0.536,-0.33)
Here is the matrix a^T
(-0.211,0.68) (0.597,0.566)
(-0.605,0.823) (0.536,-0.33)
Here is the conjugate of a
(-0.211,-0.68) (-0.605,-0.823)
(0.597,-0.566) (0.536,0.33)
Here is the matrix a^*
(-0.211,-0.68) (0.597,-0.566)
(-0.605,-0.823) (0.536,0.33)
This official improvement prohibits the use of a=a.transpose(), which will cause an alias problem! The problem is described as follows:
Matrix2i a; a << 1, 2, 3, 4;
cout << "Here is the matrix a:\n" << a << endl;
a = a.transpose(); // !!! do NOT do this !!!
cout << "and the result of the aliasing effect:\n" << a << endl;
//输出
Here is the matrix a:
1 2
3 4
and the result of the aliasing effect:
1 2
2 4
I accidentally write it like this when actually writing code. Eigen gave a function to transpose in place:transposePlace()
This way we don’t need to assign the value to the original variable for transposition.
MatrixXf a(2,3); a << 1, 2, 3, 4, 5, 6;
cout << "Here is the initial matrix a:\n" << a << endl;
a.transposeInPlace();
cout << "and after being transposed:\n" << a << endl;
//输出
Here is the initial matrix a:
1 2 3
4 5 6
and after being transposed:
1 4
2 5
3 6
4. Matrix-matrix and matrix*vector multiplication
The * symbol can be used to complete the relationship between matrices. Vectors are actually matrix attributes, so they are also processed implicitly relative to matrices. Generally there are two situations:
- Binary operator * such as
a*b
- Composite operator*= as in
a*=b
(this multiplies on the right:a*=b
is equivalent toa = a*b
) a>
#include <iostream>
#include <Eigen/Dense>
int main()
{
Eigen::Matrix2d mat;
mat << 1, 2,
3, 4;
Eigen::Vector2d u(-1,1), v(2,0);
std::cout << "Here is mat*mat:\n" << mat*mat << std::endl;
std::cout << "Here is mat*u:\n" << mat*u << std::endl;
std::cout << "Here is u^T*mat:\n" << u.transpose()*mat << std::endl;
std::cout << "Here is u^T*v:\n" << u.transpose()*v << std::endl;
std::cout << "Here is u*v^T:\n" << u*v.transpose() << std::endl;
std::cout << "Let's multiply mat by itself" << std::endl;
mat = mat*mat;
std::cout << "Now mat is mat:\n" << mat << std::endl;
//输出
Here is mat*mat:
7 10
15 22
Here is mat*u:
1
1
Here is u^T*mat:
2 2
Here is u^T*v:
-2
Here is u*v^T:
-2 -0
2 0
Let's multiply mat by itself
Now mat is mat:
7 10
15 22
Note that the official website prompts us to use m=m*m operation, and there will be no alias problem. Eigen helps us change it to:
tmp=m*m;
m=tmp;
5. Dot product and cross product
For dot and cross products, you needdot() and cross() a> method. Of course, the dot product can also be used to obtain a 1x1 matrix like u.adjoint()*v.
#include <iostream>
#include <Eigen/Dense>
int main()
{
Eigen::Vector3d v(1,2,3);
Eigen::Vector3d w(0,1,2);
std::cout << "Dot product: " << v.dot(w) << std::endl;
double dp = v.adjoint()*w; // automatic conversion of the inner product to a scalar
std::cout << "Dot product via a matrix product: " << dp << std::endl;
std::cout << "Cross product:\n" << v.cross(w) << std::endl;
}
//输出
Dot product: 8
Dot product via a matrix product: 8
Cross product:
1
-2
1
The official website reminds that cross product can only use vectors of size 3.
6. Basic arithmetic induction operations
Eigen also provides sum (sum()), total product (prod()), maximum value (maxCoeff()) and minimum value (minCoeff())
#include <iostream>
#include <Eigen/Dense>
using namespace std;
int main()
{
Eigen::Matrix2d mat;
mat << 1, 2,
3, 4;
cout << "Here is mat.sum(): " << mat.sum() << endl;
cout << "Here is mat.prod(): " << mat.prod() << endl;
cout << "Here is mat.mean(): " << mat.mean() << endl;
cout << "Here is mat.minCoeff(): " << mat.minCoeff() << endl;
cout << "Here is mat.maxCoeff(): " << mat.maxCoeff() << endl;
cout << "Here is mat.trace(): " << mat.trace() << endl;
}
//输出
Here is mat.sum(): 10
Here is mat.prod(): 24
Here is mat.mean(): 2.5
Here is mat.minCoeff(): 1
Here is mat.maxCoeff(): 4
Here is mat.trace(): 5
We can find the maximum and minimum values and also find its coordinates:
std::ptrdiff_t i, j;
float minOfM = m.minCoeff(&i,&j);
RowVector4i v = RowVector4i::Random();
int maxOfV = v.maxCoeff(&i);