Dlib姿态估计——旋转矩阵与欧拉角互转

来源:互联网 发布:symbian3软件 编辑:程序博客网 时间:2024/06/18 05:08

原文地址:https://www.learnopencv.com/rotation-matrix-to-euler-angles/

简介

        在这篇文章中,我将分享将一个3×3旋转矩阵转换成欧拉角的代码,反之亦然。3D旋转矩阵可以让你的头旋转。 我知道这是一个坏的双关语,但真相有时可能是非常小的!
        一个旋转矩阵有三个自由度,数学家已经行使了他们的创造自由,以每个想象的方式来表示3D旋转——或使用三个数字、或使用四个数字、或使用一个3×3矩阵。 还有很多不同的方式用三个数字表示一个旋转或用四个数字的一些方法来表示旋转。
        例如,3D中的旋转可以表示为三个角度,可以将其表示在X、Y、Z三个轴上。但是,这三个角度也可以表示到Z,Y和X轴上(表示方法不同)。这些角度被称为欧拉角或Tait–Bryan角。在原始欧拉角公式中,通过围绕Z,X轴和再对Z轴(或者对于Y-X-Y或Z-Y-Z)的连续旋转来描述旋转。当旋转被指定为围绕三个不同的轴(例如X-Y-Z)的旋转时,它们应该被称为泰特—布赖恩(Tait-Bryan)角,但是流行的术语仍然是欧拉角,所以我们也将它们称为欧拉角。有六种可以用Tait-Bryan角度描述旋转的方法——X-Y-Z,X-Z-Y,Y-Z-X,Y-X-Z,Z-X-Y,Z-Y-X。现在你在想,选择很简单。 让我们选择X-Y-Z。 对 么? 答案是错误的。 行业标准是Z-Y-X,因为它对应于yaw偏航,pitch俯仰和roll滚转。
这里写图片描述
yaw偏航角
这里写图片描述
pitch俯仰角
这里写图片描述
roll滚转角
这里写图片描述

        定义旋转矩阵时还有其他的含糊之处。给定一个点xyz,你可以把这个点想象成一个行向量[xyz]或一个列向量[xyz]T。如果使用行向量,则必须对3×3旋转矩阵进行右乘;如果使用列向量表示,则用3×3旋转矩阵左乘该列向量。这两个旋转矩阵是不一样的(它们是彼此的转置)。

        我的观点是没有标准的方法来将旋转矩阵转换成欧拉角。所以,我决定(几乎)与MATLAB实现的rotm2euler.m一致。唯一的区别是他们返回的欧拉角z轴是第一个和x轴是最后一个(Z-Y-X)。我的代码先返回x(X-Y-Z)。

欧拉角->旋转矩阵

        对于3D旋转的最简单的方法是以轴角形式思考。任何旋转都可以由一个旋转轴来定义,一个角度可以描述旋转的量。比方说,你想旋转一个点或一个参考框架绕x轴旋转θx度。与该旋转对应的旋转矩阵由下式给出:

Rx=1000cos(θx)sin(θx)0sin(θx)(cosθx)

        θyθz关于y和z轴的旋转可以写成:

Ry=cos(θy)0sin(θy)010sin(θy)0(cosθy)

Rz=cos(θz)sin(θz)0sin(θz)(cosθz)0001

        关于任意轴的旋转R可以用关于Z,Y和最后X轴的连续旋转来写,使用下面显示的矩阵乘法。

R=RzRyRx

        在这个公式中,θxθyθz是欧拉角。给定这三个角度,首先找到RxRyRz,然后将它们相乘得到R,就可以很容易地找到旋转矩阵。

C++代码

// Calculates rotation matrix given euler angles.Mat eulerAnglesToRotationMatrix(Vec3f &theta){    // Calculate rotation about x axis    Mat R_x = (Mat_<double>(3,3) <<               1,       0,              0,               0,       cos(theta[0]),   -sin(theta[0]),               0,       sin(theta[0]),   cos(theta[0])               );    // Calculate rotation about y axis    Mat R_y = (Mat_<double>(3,3) <<               cos(theta[1]),    0,      sin(theta[1]),               0,               1,      0,               -sin(theta[1]),   0,      cos(theta[1])               );    // Calculate rotation about z axis    Mat R_z = (Mat_<double>(3,3) <<               cos(theta[2]),    -sin(theta[2]),      0,               sin(theta[2]),    cos(theta[2]),       0,               0,               0,                  1);    // Combined rotation matrix    Mat R = R_z * R_y * R_x;    return R;}

在OpenCV中将旋转矩阵转换为欧拉角

        将旋转矩阵转换成欧拉角是有点棘手的。该解决方案在大多数情况下不是唯一的。使用上一节中的代码,可以验证与欧拉角[0.1920,2.3736,1.170](或[11,136,64])(度))和[2.9496,0.76792.0246](或[169,44,116](度))实际上是相同的,尽管欧拉角看起来非常地不同。下面的代码显示了给定旋转矩阵的欧拉角的一种方法。下面代码的输出应该与MATLAB的rotm2euler.m的输出完全匹配,但是x和z的顺序是交换的(Z-Y-X)。

C++

// Checks if a matrix is a valid rotation matrix.bool isRotationMatrix(Mat &R){    Mat Rt;    transpose(R, Rt);    Mat shouldBeIdentity = Rt * R;    Mat I = Mat::eye(3,3, shouldBeIdentity.type());    return  norm(I, shouldBeIdentity) < 1e-6;}// Calculates rotation matrix to euler angles// The result is the same as MATLAB except the order// of the euler angles ( x and z are swapped ).Vec3f rotationMatrixToEulerAngles(Mat &R){    assert(isRotationMatrix(R));    float sy = sqrt(R.at<double>(0,0) * R.at<double>(0,0) +  R.at<double>(1,0) * R.at<double>(1,0) );    bool singular = sy < 1e-6; // If    float x, y, z;    if (!singular)    {        x = atan2(R.at<double>(2,1) , R.at<double>(2,2));        y = atan2(-R.at<double>(2,0), sy);        z = atan2(R.at<double>(1,0), R.at<double>(0,0));    }    else    {        x = atan2(-R.at<double>(1,2), R.at<double>(1,1));        y = atan2(-R.at<double>(2,0), sy);        z = 0;    }    return Vec3f(x, y, z);}
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 乔家大院暂停运营 篮坛之氪金无敌 笔画 为躲末日住地窖9年 中行分行被罚五千万 龙城 2019中文字字幕122页 历史 公务员 社保个人账户 个人所得税税率表 个人简历 时尚 流浪在诸天世界 创造与魔法 沈浪苏若雪 谈恋爱不如上清华 触不可及 总裁爹地惹不起 蚀骨危情 上海 思维导图 将军在上 他在沙发上疯狂要我 龙王大人在上 穹顶之上人间武库 男士发型 母丁香 万古第一龙 一部影院 新城礼美 一道本道不卡免费高清 孤芳自赏杨小壮 成语大全 成语 yy4484福利片 日本v韩国免费中文版 福克斯 qq飞车 绕口令