外参数获取推导(求坐标系转换矩阵方法)

问题:假如已知两个坐标系如图(粗的代表摄像头坐标系,细的代表世界坐标系),如图红色为x轴,绿色为y轴,蓝色为z。
如何得到外参数(坐标系变换矩阵:包括旋转和平移)?
在这里插入图片描述
外参数矩阵(extrinsic) world->camera变换T12表示为[R12|t12]

1. 观察变换推导法

步骤:(1)求旋转矩阵R12
(2)求平移t12
1)求旋转矩阵R12:很显然,世界坐标系轴绕z轴逆时针旋转90度就能对应上上图的角度。
2)求平移t12
求由摄像头坐标系到世界坐标系的平移的关键是知道两个坐标系原点的坐标。
t=摄像头原点在世界坐标系上的坐标-世界坐标系原点的坐标
上图中摄像头原点在世界坐标系上的坐标为(0,0,2)
世界坐标系原点的坐标为(0,0,0)
t12=(0,0,2)-(0,0,0)
因此world->camera变换T12表示为[R12|t12]

因此可以得到坐标点之间的关系:
设同一个点P在世界坐标系下表示为P0(x0,y0,z0),在摄像头坐标系下表示为P1(x1,y1,z1)。
任意一点满足方程
P 0 = R 12 ∗ P 1 + t 12 P_{0}=R_{12}*P_{1}+t_{12} P0=R12P1+t12
或者表示为
P 1 = R 12 − 1 ∗ ( P 0 − t 12 ) P_{1}=R_{12}^{-1}*(P_{0}-t_{12}) P1=R121(P0t12)
如下面程序段所示:

  Eigen::Vector3d PInWorld={1,2,3};
  cout<<"PinWorld"<<endl<<PInWorld<<endl;
  Eigen::Vector3d PInCam=R12.inverse()*(PInWorld-t12);

2线性变换求旋转矩阵法

设同一个点P在世界坐标系下表示为P0(x0,y0,z0),在摄像头坐标系下表示为P1(x1,y1,z1)。
要分解了来求
步骤:(1)先求旋转矩阵R
   (2)再求平移t

2.1先求旋转矩阵R12

不考虑平移,我们可以发现一下有以下规律
世界->摄像头
x0=-y1,y0=x1,z1=z0

P在在世界坐标系的值为x0的坐标对应摄像头坐标系下值为-y1
P在在世界坐标系的值为y0的坐标对应摄像头坐标系下值为x1
P在在世界坐标系的值为z0的坐标对应摄像头坐标系下值为z1

!不考虑平移!
P 0 = R 12 ∗ P 1 P_{0}=R_{12}*P_{1} P0=R12P1
用矩阵形式表示为
[ x 0 y 0 z 0 ] = [ 0 − 1 0 1 0 0 0 1 0 ] ⋅ [ x 1 y 1 z 1 ] \begin{bmatrix} x_{0}\\ y_{0}\\ z_{0} \end{bmatrix}=\begin{bmatrix} 0 &amp; -1 &amp; 0\\ 1&amp; 0 &amp; 0\\ 0 &amp; 1 &amp; 0 \end{bmatrix}\cdot \begin{bmatrix} x_{1}\\ y_{1}\\ z_{1} \end{bmatrix} x0y0z0=010101000x1y1z1
可以得到旋转矩阵R12为
R 12 = [ 0 − 1 0 1 0 0 0 1 0 ] R_{12}=\begin{bmatrix} 0 &amp;-1 &amp;0\\ 1&amp; 0 &amp; 0\\ 0 &amp; 1 &amp; 0 \end{bmatrix} R12=010101000

2.2再求平移t12

求由摄像头坐标系到世界坐标系的平移的关键是知道两个坐标系原点的坐标。
t=摄像头原点在世界坐标系上的坐标-世界坐标系原点的坐标
上图中摄像头原点在世界坐标系上的坐标为(0,0,2)
世界坐标系原点的坐标为(0,0,0)
t12=(0,0,2)-(0,0,0)

3.实验程序

对应以上推导的程序如下

#include <ros/ros.h>
#include <visualization_msgs/Marker.h>
#include<time.h>
#include <unistd.h>
#include<iostream>
#include<eigen3/Eigen/Core>
#include<eigen3/Eigen/Geometry>
#include <tf/transform_broadcaster.h>
using namespace std;
using namespace Eigen;

int main( int argc, char** argv )
{

  ros::init(argc, argv, "tfshow");
  cout<<"start program"<<endl;
  //    //1.p1 world position
  double p1yaw=0;
  double p1x=0;
  double p1y=0;
  Eigen::AngleAxisd rotzp1(p1yaw*M_PI/180, Eigen::Vector3d::UnitZ());
  Eigen::Vector3d  t1= Eigen::Vector3d(p1x,p1y, 0);
  Eigen::Quaterniond q1=Eigen::Quaterniond(rotzp1);
  //cout<<"q1.vec()"<<q1.vec()<<endl;
  cout<<"p1 eular angle"<<(180/M_PI)*q1.matrix().eulerAngles(0,1,2)<<endl;

  //2. t12 value
  double t12yaw=90;
  double t12x=0;
  double t12y=0;
  double t12z=2;

  Eigen::AngleAxisd rott12(t12yaw*M_PI/180, Eigen::Vector3d::UnitZ());
  Eigen::Vector3d  t12= Eigen::Vector3d(t12x,t12y, t12z);
  Eigen::Quaterniond q12=Eigen::Quaterniond(rott12);
  cout<<"t12 rotation eular angle "<<(180/M_PI)*q12.matrix().eulerAngles(0,1,2)<<endl;
   Eigen::Matrix3d R12=rott12.matrix();
   cout<<"R12="<<R12<<endl;


  //    3.calculate p2 world positon
  Eigen::Quaterniond q2=q1*q12;
  // cout<<" q2 vector " <<q2.vec()<<endl;
  Eigen::Vector3d t2=t1+q1.toRotationMatrix()*t12;
  cout<<"t2="<<t2<<endl;
  cout<<"t2 eular angle "<<(180/M_PI)*q2.matrix().eulerAngles(0,1,2)<<endl;


  tf::TransformBroadcaster br;
  tf::Transform transform;
  transform.setOrigin( tf::Vector3(t12(0),t12(1), t12(2)));

  tf::Quaternion q(q12.x(),q12.y(),q12.z(),q12.w());
  transform.setRotation(q);

  //P1 in world
  Eigen::Vector3d PInWorld={1,2,3};
  cout<<"PinWorld"<<endl<<PInWorld<<endl;
  Eigen::Vector3d PInCam=R12.inverse()*(PInWorld-t12);
  cout<<"PInCam"<<endl<<PInCam<<endl;
  int k=0;
  while(k<100)
  {
      br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", "camera"));
      k++;
      sleep(1);
  }
  return 0;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值