Path: blob/master/apps/interactive-calibration/rotationConverters.cpp
16337 views
// This file is part of OpenCV project.1// It is subject to the license terms in the LICENSE file found in the top-level directory2// of this distribution and at http://opencv.org/license.html.34#include "rotationConverters.hpp"56#include <cmath>78#include <opencv2/calib3d.hpp>9#include <opencv2/core.hpp>1011#define CALIB_PI 3.1415926535897932384612#define CALIB_PI_2 1.570796326794896619231314void calib::Euler(const cv::Mat& src, cv::Mat& dst, int argType)15{16if((src.rows == 3) && (src.cols == 3))17{18//convert rotation matrix to 3 angles (pitch, yaw, roll)19dst = cv::Mat(3, 1, CV_64F);20double pitch, yaw, roll;2122if(src.at<double>(0,2) < -0.998)23{24pitch = -atan2(src.at<double>(1,0), src.at<double>(1,1));25yaw = -CALIB_PI_2;26roll = 0.;27}28else if(src.at<double>(0,2) > 0.998)29{30pitch = atan2(src.at<double>(1,0), src.at<double>(1,1));31yaw = CALIB_PI_2;32roll = 0.;33}34else35{36pitch = atan2(-src.at<double>(1,2), src.at<double>(2,2));37yaw = asin(src.at<double>(0,2));38roll = atan2(-src.at<double>(0,1), src.at<double>(0,0));39}4041if(argType == CALIB_DEGREES)42{43pitch *= 180./CALIB_PI;44yaw *= 180./CALIB_PI;45roll *= 180./CALIB_PI;46}47else if(argType != CALIB_RADIANS)48CV_Error(cv::Error::StsBadFlag, "Invalid argument type");4950dst.at<double>(0,0) = pitch;51dst.at<double>(1,0) = yaw;52dst.at<double>(2,0) = roll;53}54else if( (src.cols == 1 && src.rows == 3) ||55(src.cols == 3 && src.rows == 1 ) )56{57//convert vector which contains 3 angles (pitch, yaw, roll) to rotation matrix58double pitch, yaw, roll;59if(src.cols == 1 && src.rows == 3)60{61pitch = src.at<double>(0,0);62yaw = src.at<double>(1,0);63roll = src.at<double>(2,0);64}65else{66pitch = src.at<double>(0,0);67yaw = src.at<double>(0,1);68roll = src.at<double>(0,2);69}7071if(argType == CALIB_DEGREES)72{73pitch *= CALIB_PI / 180.;74yaw *= CALIB_PI / 180.;75roll *= CALIB_PI / 180.;76}77else if(argType != CALIB_RADIANS)78CV_Error(cv::Error::StsBadFlag, "Invalid argument type");7980dst = cv::Mat(3, 3, CV_64F);81cv::Mat M(3, 3, CV_64F);82cv::Mat i = cv::Mat::eye(3, 3, CV_64F);83i.copyTo(dst);84i.copyTo(M);8586double* pR = dst.ptr<double>();87pR[4] = cos(pitch);88pR[7] = sin(pitch);89pR[8] = pR[4];90pR[5] = -pR[7];9192double* pM = M.ptr<double>();93pM[0] = cos(yaw);94pM[2] = sin(yaw);95pM[8] = pM[0];96pM[6] = -pM[2];9798dst *= M;99i.copyTo(M);100pM[0] = cos(roll);101pM[3] = sin(roll);102pM[4] = pM[0];103pM[1] = -pM[3];104105dst *= M;106}107else108CV_Error(cv::Error::StsBadFlag, "Input matrix must be 1x3, 3x1 or 3x3" );109}110111void calib::RodriguesToEuler(const cv::Mat& src, cv::Mat& dst, int argType)112{113CV_Assert((src.cols == 1 && src.rows == 3) || (src.cols == 3 && src.rows == 1));114cv::Mat R;115cv::Rodrigues(src, R);116Euler(R, dst, argType);117}118119void calib::EulerToRodrigues(const cv::Mat& src, cv::Mat& dst, int argType)120{121CV_Assert((src.cols == 1 && src.rows == 3) || (src.cols == 3 && src.rows == 1));122cv::Mat R;123Euler(src, R, argType);124cv::Rodrigues(R, dst);125}126127128