LoginSignup
53
46

More than 5 years have passed since last update.

回転行列⇔角度の変換

Last updated at Posted at 2013-10-02

カメラキャリブレーションにおいて外部パラメータである回転行列(Rotation Matrix)を扱う時,
3 * 3の行列で表したい時と,各軸(x軸,y軸,z軸)に対する角度で表したい時がある.

この時の相互変換行列のメモ.間違っていても責めないでください.
(回転行列⇒角度の場合は一意に求まらない場合があるので,多少の注意は必要.)

ただし,今回は右手座標系において,各軸に対する変換は以下のように定めており,
回転行列R = Rz * Rx * Ryとする.(掛け合わせる順序が変わると式が変わる.)
x, y, zは各軸の回転角(ラジアン)とする.

  • x軸周りの回転行列
Rx = ( 1, 0, 0,
     0, cos(x), -sin(x),
     0, sin(x), cos(x) )
  • y軸周りの回転行列
Ry = ( cos(y), 0, sin(y),
     0, 1, 0,
     -sin(y), 0, cos(y) )
  • z軸周りの回転行列
Rz = ( cos(z), -sin(z), 0,
     sin(z), cos(z), 0,
     0, 0, 1 )
  • 回転行列(Rz * Rx * Ry)
R = cos(y)cos(z) - sin(x)sin(y)sin(z), -cos(x)sin(z), sin(y)cos(z) + sin(x)cos(y)sin(z),
      cos(y)sin(z) + sin(x)sin(y)cos(z), cos(x)cos(z), sin(z)sin(y) - sin(z)cos(y)cos(z),
      -cos(x)sin(y), sin(x), cos(x)cos(y)

なので,
角度⇒回転行列

void computeMatrixFromAngles(
     cv::Mat & R,
     double x,
     double y,
     double z){

  R.row(0).col(0) = cos(y)*cos(z) - sin(x)*sin(y)*sin(z);
  R.row(0).col(1) = -cos(x)*sin(z);
  R.row(0).col(2) = sin(y)*cos(z) + sin(x)*cos(y)*sin(z);
  R.row(1).col(0) = cos(y)*sin(z) + sin(x)*sin(y)*cos(z);
  R.row(1).col(1) = cos(x)*cos(z);
  R.row(1).col(2) = sin(y)*sin(z) - sin(x)*cos(y)*cos(z);
  R.row(2).col(0) = - cos(x)*sin(y);
  R.row(2).col(1) = sin(x);
  R.row(2).col(2) = cos(x)*cos(y);
}

回転行列⇒角度

void computeAnglesFromMatrix(
                 cv::Mat R,
                 double & angle_x,
                 double & angle_y,
                 double & angle_z
                 ){

  double threshold = 0.001;

  if(abs(R.at<double>(2,1) - 1.0) < threshold){ // R(2,1) = sin(x) = 1の時
    angle_x = PI / 2;
    angle_y = 0;
    angle_z = atan2(R.at<double>(1,0), R.at<double>(0,0));
  }else if(abs(R.at<double>(2,1) + 1.0) < threshold){ // R(2,1) = sin(x) = -1の時
    angle_x = - PI / 2;
    angle_y = 0;
    angle_z = atan2(R.at<double>(1,0), R.at<double>(0,0));
  }else{
    angle_x = asin(R.at<double>(2,1));
    angle_y = atan2(-R.at<double>(2,0), R.at<double>(2,2));
    angle_z = atan2(-R.at<double>(0,1), R.at<double>(1,1));
  }
}

参考サイト
+ http://d.hatena.ne.jp/It_lives_vainly/20070829/1188384519
(↑のサイトは回転行列の表現がちょっと間違ってる?)

53
46
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
53
46