1. 程式人生 > >文章標題Eigen的矩陣運算使用

文章標題Eigen的矩陣運算使用

  在ROS的Cmake中使用Eigen庫進行矩陣和向量的運算和很方便。下面逐步新增他的使用方法。
  
1 配置
  首先要在CmakeLists.txt中先進行設定:
由於Eigen是ros以外的庫,所以要單獨的使用
  find_package(Eigen REQUIRED)
同時Eigen依賴cmake_modules。所以還要
  find_package(catkin REQUIRED COMPONENTS
  cmake_modules)。

2 認識一些標頭檔案
Eigen庫分為 核心模組和額外模組兩部分,每個模組都有一個用這個模組所相對應的標頭檔案,Eigen和Dense標頭檔案方便的同時包含了幾個標頭檔案以供使用。下面做簡單介紹:
——Core
有關矩陣和陣列的類,有基本的線性代數(包含 三角形 和 自伴乘積 相關),還有相應對陣列的操作。
——Geometry
幾何學的類,有關轉換、平移、進位制、2D旋轉、3D旋轉(四元組和角軸相關)
——LU
邏輯單元的類,有關求逆,求行列式,LU分解解算器(FullPivLU,PartialPivLU)
——Cholesky
包含LLT和LDLT的喬里斯基因式分解法。
(小科普:Cholesky分解是把一個對稱正定的矩陣表示成一個下三角矩陣L和其轉置的乘積的分解)
——Householder
豪斯霍爾德變換,這個模組供幾個線性代數模組使用。
(Householder transform: 維基百科 )
——SVD
奇異值分解,最小二乘解算器解決奇異值分解。
——QR
QR分解求解,三種方法:HouseholderQR、ColPivHouseholderQR、FullPivHouseholderQR
——Eigenvalues
特徵值和特徵向量分解的方法:EigenSolver、SelfAdjointEigenSolver、ComplexEigenSolver
——Sparse
稀疏矩陣相關類,對於稀疏矩陣的儲存及相關基本線性代數
——Dense
包含: Core、Gelometry、LU、Cholesky、SVD、QR和Eigenvalues模組(標頭檔案)
——Eigen
包含上述所有的模組(標頭檔案)

3 矩陣簡單操作
Eigen提供了兩種密集的物件Matrix(矩陣)和Vector(向量)。
這兩者是通過矩陣模板類和一維或二維的陣列模板類來實現的。
這兩者有幾點不同:
——Matrix型別變數加減法,若行列數不相等,則不能做加減;
Array型別的可以加減一個常數(各個元素分別加減該常數)。
——Matrix與Array型別變數做乘法也會有不同,Matrix是矩陣相乘,Array是對應元素相乘。
——但兩者可以相互轉換,方法為 .array() 和 .matrix()。
3.1 定義
定義矩陣時,預設沒有初始化,必須自己初始化。
Eigen的矩陣型別,一般是Matrix後面跟型別符號來表示,比如說:
——’ d ’ 代表 double,矩陣儲存的是double型的資料
——’ f ’ 代表float,矩陣儲存的是float型別資料
——’ c ‘代表complex,矩陣存數的是複數型別資料
——’ i ‘代表int,矩陣儲存的是整數型別
相應關係為:
這裡寫圖片描述


3.2 初始化

m1=MatrixXf::Zero(3,4);     // 將矩陣3行4列初始化為0
m2=MatrixXf::Ones(3,3);     // 將矩陣3行3列初始化為1
v1=Vector3f::Ones();        // 將3行的縱向量初始化為1

cout<<"m1=\n"<<m1<<endl;
cout<<"m2=\n"<<m2<<endl;
cout<<"v1=\n"<<v1<<endl;

執行結果為:
這裡寫圖片描述

3.3 訪問
直接就同陣列的訪問方式一樣,但是不是方括號,而是圓括號:

MatrixXf m3(2,3);
m3<<1,2,3,4,5,6;
cout<<"m3_1\n"<<m3<<endl;
// 為了美觀點,更像個矩陣,可以換行寫
m3<<1.3,4,-8,
    0,0.9,2;
cout<<"m3_2=\n"<<m3<<endl;
// 將第2行第3列的值改為99
m3(1,2)=99;
cout<<"m3_3=\n"<<m3<<endl;

當然,同陣列一樣,第一行第一列的下標為(0,0)
輸出結果:
這裡寫圖片描述

4 矩陣的運算
——置0
——置1
——隨機矩陣
——單位陣
——求逆
——轉置
——數乘矩陣
——向量求模值


<span style="white-space:pre"> </span>MatrixXf m1(3,3);
// 矩陣全部元素置0
m1.setZero();
cout<<"m1_1=\n"<<m1<<endl;
// 矩陣全部元素置1 ( 這裡行列值不填,預設定義時候的行列,
// 若填寫,則矩陣也會更改為填寫的行列值 )
m1.setOnes(2,2);
cout<<"m1_2=\n"<<m1<<endl;
// 隨機生成一個矩陣
m1.setRandom();
cout<<"m1_3=\n"<<m1<<endl;
// 置單位矩陣
m1.setIdentity(3,3);
cout<<"m1_4=\n"<<m1<<endl;
m1<< 1 , 2 , 3 ,
5 , 9 ,10 ,
7 , 0 ,1 ;
// 矩陣求逆
m1.inverse();
cout<<"m1_5=\n"<<m1<<endl;
// 矩陣轉置
m1.transpose();
cout<<"m1_6=\n"<<m1<<endl;
// 數 * 矩陣 ( 數 / 矩陣 )
m1 = 2.6 * m1 ;
cout<<"m1_7=\n"<<m1<<endl;
//求向量模值 norm()