李群李代數(第一次會暈)


  • 三維旋轉矩陣構成特殊正交群,SO(3),變換矩陣構成了特殊歐式群SE(3).

$${\rm{SO(3) = \{ R}} \in {{\rm{R}}^{3 \times 3}}\left| {R{R^T} = I,\det (R) = I} \right.{\rm{\} }}$$

\[{\rm{SE(3) = }}\left\{ {{\rm{T = }}\left[ {\begin{array}{*{20}{c}}
R&t\\
0&1
\end{array}} \right] \in {{\rm{R}}^{4 \times 4}}\left| {R \in SO(3),t \in {R^3}} \right.} \right\}\]

  • 從上面看群是一種集合加上一種運算的代數結構。什么集合,何種運算不知道。把集合記作A,運算記作$ \bullet $,群記為$G = (A, \bullet )$,群應滿足以下四個特性(封結幺逆):
  1. 封閉性:$\forall {a_1},{a_2} \in A,\;\;\;\;\;{a_1} \bullet {a_2} \in A$
  2. 結合律:

    \[\forall {a_1},{a_2},{a_3} \in A,\;\;\;\;\;({a_1} \bullet {a_2}) \bullet {a_3} = {a_1} \bullet ({a_2} \bullet {a_3})\]

  3. 幺元:$\exists {a_0} \in A,s.t\;\forall a \in A,{a_0} \bullet a = a \bullet {a_0} = a$
  4. 逆:$\forall a \in A,\;\;\;\exists {a^{{\rm{ - }}1}} \in A,s.t\;a \bullet {a^{_{{\rm{ - }}1}}} = a$
  • 李群是指具有連續光滑性質的群,像一般的整數離散群不具有連續性,SO(3), SE(3)在實數空間上是連續的,表示一個位置變換到另一個位置,路徑是連續的。但是群的概念只定義了乘法,沒有加法。
  • 李代數的引出:

    李代數由一個集合V、一個數域F和一個二元運算[ ,](李括號)組成。稱(V,F,[ , ])為一個李代數,記為g.

    在實際應用中我們估計相機的位置和姿態時,由於干擾,不可能沒有誤差,那么產生誤差需要矯正,我們會用補償量$\Delta R,\Delta T$去補償誤差。然而群的定義對加法沒有封閉性,比如兩個旋轉或變換矩陣相加后不再表示一個旋轉或變換矩陣,失去了原有的意義,於是李代數的提出為此問題提供了解決思路,把SE(3)空間的T映射為李代數se(3),它由向量組成,我們在中學數學就知道,向量相加還表示為一個向量(例如平行四邊形原則),李代數對加法具有封閉性(加完之后還是向量)。這樣可以通過李代數求導間接對變換矩陣T進行求導。在優化相機位姿時,每次迭代更新一個位姿的增量δ,使目標函數最小,那么這個δ就是通過對T微分得到的。它們對於某時刻的R(t)(李群空間),存在一個三維向量$\phi {\rm{ = (}}{\phi _1}{\rm{,}}{\phi _2}{\rm{,}}{\phi _3}{\rm{)}}$的李代數空間來描述R在t時刻的導數。

\[\mathop R\limits^ \bullet (t) = \phi {(t)^ \wedge }R(t) = \left[ {\begin{array}{*{20}{c}}
0&{ - {\phi _3}}&{{\phi _2}}\\
{{\phi _3}}&0&{ - {\phi _1}}\\
{ - {\phi _2}}&{{\phi _1}}&0
\end{array}} \right]R(t)\]

  • 指數映射:向量$\phi {\rm{ = (}}{\phi _1}{\rm{,}}{\phi _2}{\rm{,}}{\phi _3}{\rm{)}}$反映了R的導數性質,它們之間的微分關系可以描述為:李代數so(3)對應李群SO(3) 在原點附近的正切空間。換句話說,李代數so(3)是三維向量$\phi {\rm{ = (}}{\phi _1}{\rm{,}}{\phi _2}{\rm{,}}{\phi _3}{\rm{)}}$的集合,每個$\phi (i)$的反對稱矩陣都$\phi (i)$^可以表示SO(3)上旋轉矩陣$R(i)$的導數,R和$\phi $呢又呈現一個指數映射關系:$R(t) = \exp (\phi _0^ \wedge t)$,$\exp ({\phi ^ \wedge }) = \exp (\theta {{\rm{a}}^ \wedge }) = \sum\limits_{n = 0}^\infty {\frac{1}{{n!}}} {(\theta {{\rm{a}}^ \wedge })^n}$經過泰勒展開后變為$\exp (\theta {{\rm{a}}^ \wedge }) = \cos \theta I + (1 - \cos \theta )a{a^T} + \sin \theta {a^ \wedge }$又回到了羅德里格斯。對於三維旋轉和變換的關系圖如下;

  • 李代數求導與擾動模型:

   以SO(3)為例,當李代數的so(3)做加法時,在李群SO(3)是否對應為兩個矩陣的乘積,$\exp (\phi _1^ \wedge )\exp (\phi _2^ \wedge ) = \exp ({({\phi _1} + {\phi _2})^ \wedge })$?$\ln (\exp (A)\exp (B)) = A{\rm{ + }}B$?答案是對矩陣運算都不成立,BCH公式給出了近似解:

\[\ln {(\exp (A\phi _1^ \wedge )\exp (\phi _2^ \wedge ))^ \vee } \approx \left\{ {\begin{array}{*{20}{c}}
{{J_l}{{({\phi _2})}^{ - 1}}{\phi _1} + {\phi _2},{\phi _1}\min }\\
{{J_r}{{({\phi _1})}^{ - 1}}{\phi _2} + {\phi _1},{\phi _2}\min }
\end{array}} \right.\]

  以下標為l的左乘模型來說,意思是,我們對一個旋轉矩陣R2 (李代數${\phi _2}$)左乘一個微小旋轉矩陣R1 (李代數${\phi _1}$ ),看成是李代數 ${\phi _2}$加上一項

\[{J_l}{({\phi _2})^{ - 1}}{\phi _1}\]

  右乘模型同理。式中有一個近似的雅可比Jl,再通俗的形象一下就是,假定對一個旋轉R(李代數$\phi $)產生的漂移進行矯正,左乘一個$\Delta R$ (李代數$\Delta \phi $),在李群上的結果為$\Delta R \bullet R$

用BCH近似為

\[{J_l}{(\phi )^{ - 1}}\Delta \phi {\rm{ + }}\phi \]

  合起來就是$\exp (\Delta {\phi ^ \wedge })\exp ({\phi ^ \wedge }) = \exp ({(\phi + {J_l}(\phi )\Delta \phi )^ \wedge })$,然而上面剛剛說到在李代數上加法是封閉的,可以進行加法運算,一個

\[\phi {\rm{ + }}\Delta \phi \]

  可以近似為李群上帶左右雅可比的乘法:$\exp ({(\phi + \Delta \phi )^ \wedge }) = \exp ({({J_l}\Delta \phi )^ \wedge })\exp ({\phi ^ \wedge }) = \exp ({\phi ^ \wedge })\exp ({({J_r}\Delta \phi )^ \wedge })$

  • 求導運算1

  空間中有一向量p,然后我們對其進行了R的旋轉變換變為Rp,求旋轉之后Rp對旋轉R的導數,$\frac{{\partial (Rp)}}{{\partial R}}$ ,但是沒有加法,無法按照導數定義計算,因此轉為李代數計算。

 

$$\frac{{\partial (Rp)}}{{\partial R}}{\rm{ = }}\frac{{\partial (\exp ({\phi ^ \wedge })p)}}{{\partial \phi }} = - {(Rp)^ \wedge }{J_l}$$

  結果中有一個雅可比,在應用中不太好處理,又出現了擾動模型來替代,思路是對R進行一次擾動$\Delta R$(左乘形式),看結果相對擾動的變化率。 $\Delta R$對應的李代數為 $\varphi $,$\frac{{\partial (Rp)}}{{\partial \varphi }}{\rm{ = }} - {(Rp)^ \wedge }$,這樣就沒有了雅可比,對實際應用更加合理。

  •  實現才是硬道理:
 1 #include<iostream>
 2 #include<cmath>
 3 #include<Eigen/Core>
 4 #include<Eigen/Geometry>
 5 #include"sophus/se3.h"
 6 #include"sophus/so3.h"
 7 
 8 using namespace std;
 9 using namespace Eigen;
10 
11 int main(int argc,char **argv)
12 {
13     // 沿Z軸轉90度的旋轉矩陣用旋轉向量表示
14     Eigen::Matrix3d R = Eigen::AngleAxisd(M_PI/2, Eigen::Vector3d(0,0,1)).toRotationMatrix();
15     
16     Sophus::SO3 SO3_R(R);               // Sophus::SO(3)可以直接從旋轉矩陣構造
17     Sophus::SO3 SO3_v( 0, 0, M_PI/2 );  // 亦可從旋轉向量構造
18     Eigen::Quaterniond q(R);            // 或者四元數
19     Sophus::SO3 SO3_q( q );
20     // 上述表達方式都是等價的
21    
22     cout<<"SO(3)由矩陣構造:\n "<<SO3_R.matrix()<<endl;
23     cout<<"SO(3)由向量構造: \n"<<SO3_v.matrix()<<endl;
24     cout<<"SO(3)由四元數構造:\n"<<SO3_q.matrix()<<endl;
25     
26     // 使用對數映射獲得它的李代數
27     Eigen::Vector3d so3 = SO3_R.log();
28     cout<<"SO(3)的李代數so(3) =SO3_R.log()為: "<<so3.transpose()<<endl;
29     // hat 為向量到反對稱矩陣
30     cout<<"so(3)李代數向量對應的反對稱矩陣: \n"<<Sophus::SO3::hat(so3)<<endl;
31     // 相對的,vee為反對稱矩陣到向量
32     cout<<"so(3)反對稱矩陣對應的李代數向量: \n "<<Sophus::SO3::vee( Sophus::SO3::hat(so3) ).transpose()<<endl;
33     // transpose純粹是為了輸出美觀一些
34     
35     // 增量擾動模型的更新
36     Eigen::Vector3d update_so3(1e-4, 0, 0); //假設更新量為這么多
37     Sophus::SO3 SO3_updated = Sophus::SO3::exp(update_so3)*SO3_R;
38     cout<<"更新后的SO(3) =δ×R為 \n"<<SO3_updated.matrix()<<endl;
39     
40     cout<<"***********SE(3)的操作*************"<<endl;
41     // 對SE(3)操作大同小異
42     Eigen::Vector3d t(1,0,0);           // 沿X軸平移1
43     Sophus::SE3 SE3_Rt(R, t);           // 從R,t構造SE(3)
44     Sophus::SE3 SE3_qt(q,t);            // 從q,t構造SE(3)
45     cout<<"SE3由矩陣旋轉+平移構造( R,t)= "<<endl<<SE3_Rt.matrix()<<endl;
46     cout<<"SE3由四元數q,t= "<<endl<<SE3_qt.matrix()<<endl;
47     // 李代數se(3) 是一個六維向量,方便起見先typedef一下
48     typedef Eigen::Matrix<double,6,1> Vector6d;
49     Vector6d se3 = SE3_Rt.log();
50     cout<<"SE(3)對應的李代數se(3) =\n "<<se3.transpose()<<endl;
51     // 觀察輸出,會發現在Sophus中,se(3)的平移在前,旋轉在后.
52     // 同樣的,有hat和vee兩個算符
53     cout<<"se(3)對應的反對稱矩陣 = "<<endl<<Sophus::SE3::hat(se3)<<endl;
54     cout<<"反對稱矩陣對應的李代數向量 = "<<Sophus::SE3::vee( Sophus::SE3::hat(se3) ).transpose()<<endl;
55     
56     // se(3)的擾動
57     Vector6d update_se3; //更新量
58     update_se3.setZero();//六維更新量
59     update_se3(0,0) = 1e-4d;//改變其中一個量來產生觀測
60     Sophus::SE3 SE3_updated = Sophus::SE3::exp(update_se3)*SE3_Rt;
61     cout<<"更新后的SE(3) = "<<endl<<SE3_updated.matrix()<<endl;
62     
63 return 0;
64 }

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM