題目如下
下面我們來練習如何使用 Eigen/Geometry 計算一個具體的例子。
設有小蘿卜 1 一號和小蘿卜二號位於世界坐標系中。小蘿卜一號的位姿為: q 1 = [0.55, 0.3, 0.2, 0.2], t 1 =
[0.7, 1.1, 0.2] T (q 的第一項為實部)
。這里的 q 和 t 表達的是 T cw ,也就是世界到相機的變換關系。小蘿卜
二號的位姿為 q 2 = [−0.1, 0.3, −0.7, 0.2], t 2 = [−0.1, 0.4, 0.8] T 。現在,小蘿卜一號看到某個點在自身的坐
標系下,坐標為 p 1 = [0.5, −0.1, 0.2] T ,求該向量在小蘿卜二號坐標系下的坐標。請編程實現此事,並提交
你的程序。
提示:
1. 四元數在使用前需要歸一化。
2. 請注意 Eigen 在使用四元數時的虛部和實部順序。
3. 參考答案為 p 2 = [1.08228, 0.663509, 0.686957] T 。你可以用它驗證程序是否正確。
1)用四元數的方法計算
整體思路是由 p1,q1, t1 計算點在世界坐標下的坐標pw
先把四元數歸一化,題目給出的表達是Tcw,是世界到相機的變換關系,所以要先把q1轉化為相機到世界的變換,也就是q1的逆可以表達相反的變換
對於單位四元數,其逆和共軛就是同一個量,而四元數的共軛是把虛部取成相反數,所以在歸一化的時候把q1的虛部取為相反數就行了。
pw = q1wc * (p1 - t1)
然后計算pw在蘿卜二號坐標系的坐標
p2 = pw * q2 + t2
代碼如下
1 //writed by zhang ning 2018/3/5 20:11 2 //本程序用來求解位姿變換問題 3 #include <iostream> 4 #include <cmath> 5 using namespace std; 6 7 #include <Eigen/Core> 8 #include <Eigen/Dense> 9 // Eigen 幾何模塊 10 #include <Eigen/Geometry> 11 12 int main( int argc, char** argv) 13 { 14 Eigen::Vector3d p1,t1,t2; 15 p1 << 0.5,-0.1,0.2; 16 t1 << 0.7,1.1,0.2; 17 t2 << -0.1,0.4,0.8; 18 // 四元數Eigen::Quaterniond 的正確初始化順序為Eigen::Quaterniond(w,x,y,z) 19 // 而 coeffs的順序是(x,y,z,w),w 為實部,前三者為虛部 20 // 因為要表示相反的旋轉,故輸入為q1的共軛,即實部不變,虛部變為相反數 21 Eigen::Quaterniond q1 = Eigen::Quaterniond(0.55,-0.3,-0.2,-0.2).normalized(); 22 cout << q1.coeffs().transpose() << endl; 23 24 25 Eigen::Quaterniond q2 = Eigen::Quaterniond(-0.1,0.3,-0.7,0.2).normalized(); 26 cout << q2.coeffs().transpose() << endl; 27 28 Eigen::Vector3d pw = q1*(p1-t1); //數學上是qpq-1 29 Eigen::Vector3d p2 = q2*pw + t2; 30 31 cout << p2 << endl; 32 33 return 0; 34 }
2)用變換矩陣的方法
同樣的思路,先求出兩個變換矩陣T1和T2 ,p1和T1 的逆矩陣相乘得到 pw, 然后再和T2相乘得到 p2
p2 = T2 * T1.inverse() * p1
代碼如下
1 //writed by zhang ning 2018/3/5 20:11 2 //本程序用來求解位姿變換問題 3 #include <iostream> 4 #include <cmath> 5 using namespace std; 6 7 #include <Eigen/Core> 8 #include <Eigen/Dense> 9 // Eigen 幾何模塊 10 #include <Eigen/Geometry> 11 //下面這段程序是用變換矩陣來計算的,可以得到相同的計算結果 12 13 int main( int argc, char** argv) 14 { 15 Eigen::Vector3d p1,t1,t2; 16 p1 << 0.5,-0.1,0.2; 17 t1 << 0.7,1.1,0.2; 18 t2 << -0.1,0.4,0.8; 19 Eigen::Quaterniond q1 = Eigen::Quaterniond(0.55,0.3,0.2,0.2).normalized(); 20 21 Eigen::Isometry3d T1 = Eigen::Isometry3d::Identity(); 22 T1.rotate ( q1 ); 23 T1.pretranslate ( t1 ); 24 cout << "Transform matrix = \n" << T1.matrix() << endl; 25 26 Eigen::Quaterniond q2 = Eigen::Quaterniond(-0.1,0.3,-0.7,0.2).normalized(); 27 28 Eigen::Isometry3d T2 = Eigen::Isometry3d::Identity(); 29 T2.rotate ( q2 ); 30 T2.pretranslate ( t2 ); 31 cout << "Transform matrix = \n" << T2.matrix() << endl; 32 33 Eigen::Vector3d p2 = T2*T1.inverse()*p1; 34 cout << p2 << endl; 35 36 return 0; 37 }
CMakeLists.txt文件內容如下
1 cmake_minimum_required( VERSION 2.8 ) 2 3 project( geometry ) 4 5 # 設置編譯模式 6 set( CMAKE_BUILD_TYPE "Debug" ) 7 8 # 添加頭文件 9 include_directories( "/usr/include/eigen3") 10 11 add_executable( useGeometry useGeometry.cpp )
相關源碼可以在我的github倉庫中下載,
項目地址:https://github.com/feifanrensheng/useGeometry