李羣資料:
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://en.wikipedia.org/wiki/3D_rotation_group
擾動法:
因此擾動法的導數可以理解爲對0處的導數,容易求解,
此時0處的導數容易計算:
只是最終求解出以後:
而不是簡單相加,這就是Dynamic Fusion裏面的都是在0處進行Taylor展開。
最近在做SMPL相關的工作,SMPL中每個關節的旋轉角度採用李代數來表達,其中李代數到李羣的轉換與羅德里格斯變換相同,可以表達爲。而其中微分模型中,SO(3)的微分寫作:
具體證明參考BCH公式: https://en.wikipedia.org/wiki/Baker-Campbell-Hausdorff_formula
其中爲左雅各比矩陣,
所以可以根據泰勒展開可以得到SO3矩陣對於每個李代數中分量的導數:
其中
其中
根據實際運算中我們也可以通過微小擾動法求得,
根據微小擾動方法得的結果通常與導數法有一定差別,是由於步長選擇和數值計算截斷誤差造成的,由於兩種誤差來源互相沖突,因此步長的選擇有一個合適的範圍,通常我們認爲解析法計算的結果較數值擾動法爲準確,在這種情況下,可以採用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
其中寫作如下: