李羣的求導,附帶matlab代碼

李羣資料:

https://en.wikipedia.org/wiki/3D_rotation_group     

http://www.ethaneade.com/latex2html/lie_groups/lie_groups.html

http://www.ethaneade.com/latex2html/lie_groups/lie_groups.html

https://github.com/ankurhanda/gvnn

https://books.google.co.jp/books?id=Xq8qEvZske0C&pg=PA109&lpg=PA109&dq=Special+euclidean+group+by+cuda&source=bl&ots=Jxd6k5Joxy&sig=oJQhMa9KIIPQ9VYRrIjCdY0nQaU&hl=zh-CN&sa=X&ved=2ahUKEwjL757U2czfAhVFjLwKHaYaDBYQ6AEwAHoECAcQAQ#v=onepage&q&f=false

 

https://en.wikipedia.org/wiki/3D_rotation_group

 

     擾動法: 

                                                           SE3(\delta\theta+\theta)!=SE3(\delta\theta)SE3(\theta)   

     因此擾動法的導數可以理解爲對0處的導數,容易求解,

                                                                               \frac{\partial SE3(0)}{\partial \theta }         

     此時0處的導數容易計算: 

                                                                                \frac{\partial SE3(0)}{\partial \theta }                                              

      只是最終求解出\delta\theta以後:

                                                                      \acute{\theta}=se3(SE3(\delta\theta)SE3(\theta))

     而不是簡單相加,這就是Dynamic Fusion裏面的都是在0處進行Taylor展開。

 

     最近在做SMPL相關的工作,SMPL中每個關節的旋轉角度採用李代數來表達,其中李代數到李羣的轉換與羅德里格斯變換相同,可以表達爲R(v\theta)=cos\theta I+(1-cos\theta)vv$^T+sin(\theta)v$^\wedge。而其中微分模型中,SO(3)的微分寫作: 

                                                   exp(\varphi^\wedge+\delta^\wedge) =exp(J_l \delta^\wedge)exp(\varphi^\wedge);\; \; \; \varphi=v\theta 

具體證明參考BCH公式:  https://en.wikipedia.org/wiki/Baker-Campbell-Hausdorff_formula 

其中爲左雅各比矩陣,

                                                     J_l=\frac{sin\theta}{\theta}I+(1-\frac{sin\theta}{\theta})vv^T+\frac{1-cos\theta}{\theta}v^\wedge   

所以可以根據泰勒展開可以得到SO3矩陣對於每個李代數中分量的導數: 

                                           \frac{\partial exp(\varphi ^\wedge)}{\partial \varphi_i} = \frac{(exp(J_l\delta)-I)exp(\varphi)}{\delta} =(\frac{ J_l\partial\varphi}{\partial \varphi_i})^\wedge exp(\varphi)=(J_l(i))^\wedge exp(\varphi) 

其中

                                                                     J_l(i)=J_l\times Vec(i)   

其中

                              Vec(0)=\begin{pmatrix} 1\\ 0\\ 0 \end{pmatrix}            Vec(1)=\begin{pmatrix} 0\\ 1\\ 0 \end{pmatrix}          Vec(2)=\begin{pmatrix} 0\\ 0\\ 1 \end{pmatrix}   

 

 

 

 根據實際運算中我們也可以通過微小擾動法求得, 

                                           \frac{\partial exp(\varphi ^\wedge)}{\partial \varphi_i} =\mathop{lim}\limits_{\delta_i \mapsto=0}\, \frac{exp(\varphi^\wedge+vec(\delta_i))-exp(\varphi^\wedge-vec(\delta_i)}{\delta_i}

根據微小擾動方法得的結果通常與導數法有一定差別,是由於步長選擇和數值計算截斷誤差造成的,由於兩種誤差來源互相沖突,因此步長的選擇有一個合適的範圍,通常我們認爲解析法計算的結果較數值擾動法爲準確,在這種情況下,可以採用Matlab進行實驗求出最佳的步長範圍: 

                                                                                       圖1  數值計算誤差與step

計算結果證明步長大約等於EPS的10的十次方倍到十一次方倍可以得到最小計算誤差,大概爲10^-10左右。 在Matlab中EPS通常爲2.2204e-16 。

 

 

附錄1: 羅德里格斯的matlab實現

%{
%     羅德里格斯變換    %     輸入:1*3的羅德里格斯向量  %     輸出3*3矩陣  爲旋轉矩陣
%   參考文獻:
%   新浪微博:http://blog.sina.com.cn/s/blog_5fb3f125010100hp.html
%   CSDN空間:http://blog.csdn.net/bugrunner/article/details/7359100
%   維基百科:http://en.wikipedia.org/wiki/Rodrigues'_rotation_formula  
%}

function Rotation_matrix=Rodrigues2Rotation(rod)
r = rod;
theta=norm(r);
% r = r/theta ; 
%% 
% rx=[  0    -r(3)  r(2) ; 
%      r(3)    0   -r(1) ;
%     -r(2)   r(1)   0  ]; %% 

% Rotation_matrix = eye(3,3)+sin(theta)/theta*rx+(1-cos(theta))/theta^2*rx*rx;

one_r = r./theta;
Rotation_matrix=cos(theta)*eye(3,3)+(1-cos(theta))*(one_r*one_r')+sin(theta)*[0 -one_r(3)  one_r(2);one_r(3) 0 -one_r(1); -one_r(2) one_r(1) 0] ; 
% 下面這種辦法也可以:
%{
rx=[0 -r(3)  r(2);r(3) 0 -r(1); -r(2) r(1) 0];
R2=eye(3,3)+sin(theta)/theta*rx+(1-cos(theta))/theta^2*rx*rx;
(R-R')/2-sin(theta)*[0   -one_r(3)  one_r(2);one_r(3)  0  -one_r(1);-one_r(2) one_r(1)   0 ]
 Rx=(R-R')/2;
%}

 

附錄2: 數值導數計算方法: 

function matrix = diff_rod(vec , i , delta_rank)
delta = eps*10^delta_rank ;
vec1 = vec ;
'vec2 = vec ;
vec1(i) = vec(i) - delta ;
vec2(i) = vec(i) + delta ;
matrix = (Rodrigues2Rotation(vec2) - Rodrigues2Rotation(vec1) ) / (delta*2.0) ; %
end

附錄3:解析法計算SO(3)導數

function matrix = deriviive( vec , i )
matrix_l = Jaccobi_l(vec) ; 
vec_l = matrix_l(:,i) ; %%% 
matrix =  skew_matrix(vec_l) * Rodrigues2Rotation( vec ) ; %%  

function skew_mat = skew_matrix(vec_n)
skew_mat=[     0        -vec_n(3)    vec_n(2) ;
            vec_n(3)        0       -vec_n(1) ;
           -vec_n(2)     vec_n(1)      0      ];
       
function J_l = Jaccobi_l(vec)
theta  = norm(vec);
vec_n  = vec / theta ;

rx=[     0        -vec_n(3)    vec_n(2) ;
      vec_n(3)        0       -vec_n(1) ;
     -vec_n(2)     vec_n(1)      0      ];

J_l = sin(theta)/theta*eye(3)+( 1-sin(theta)/theta )*(vec_n*vec_n') + (1-cos(theta))/theta * rx ;
% J_l = inv(J_l) ; 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


function matrix = i_matrix(i)
if i ==1
        matrix=[ 0  0   0 ;
                      0  0  -1 ;
                      0  1   0];
else
    if i==2
        matrix=[ 0   0  1;
                 0   0  0;
                -1   0  0];
    else
        matrix=[ 0  -1  0 ;
                1   0  0 ;
                0   0  0] ; 
    end
end

 

其中M_i寫作如下: J_l

                                                                M_i=\begin{matrix} 0 & 0 & 0 \\ 0 & 0 & -1 \\ 0 & 1& 0 \end{matrix} ;\: \: \:\: \: \: if\: i=1

                                                                M_i=\begin{matrix} 0 & 0 & 1 \\ 0 & 0 & 0\\ -1 & 0& 0 \end{matrix} ;\: \: \:\: \: \: if\: i=2     

                                                                M_i=\begin{matrix} 0 & -1 & 0 \\ 1 & 0& 0\\ 0& 0& 0 \end{matrix} ;\: \: \:\: \: \: if\: i=3

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章