高博课程编程作业之计算小萝卜的坐标

题目如下

下面我们来练习如何使用 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

posted @ 2018-03-06 19:30  feifanren  阅读(1828)  评论(0编辑  收藏  举报