是否存在将旋转的四元数表示转换为欧拉角表示的现有算法?欧拉表示的旋转顺序是已知的,并且可以是六个排列中的任何一个(即xyz,xzy,yxz,yzx,zxy,zyx).我已经看到了固定旋转顺序的算法(通常是NASA标题,银行,滚动惯例),但不是任意旋转顺序.
此外,因为存在单个方向的多个欧拉角表示,所以该结果将是模糊的.这是可以接受的(因为方向仍然有效,它可能不是用户期望看到的方向),但是如果存在一个采用旋转限制的算法(即自由度数和考虑到每个自由度的限制,并在给定这些约束条件下产生"最明智的"欧拉表示.
我有一种感觉,这个问题(或类似的东西)可能存在于IK或刚体动力学领域.
解决:我刚刚意识到我可能不清楚我是通过遵循图形宝石的Ken Shoemake的算法来解决这个问题的.当时我确实回答了我自己的问题,但是我发现它可能并不清楚我这样做了.有关详细信息,请参阅下面的答案.
只是为了澄清 - 我知道如何从四元数转换为所谓的' Tait-Bryan '表示 - 我称之为'NASA'约定.这是zxy的旋转顺序(假设'Z'轴向上)的惯例.我需要一个适用于所有轮换订单的算法.
那么,解决方案可能是采用zxy顺序转换,并从其中获得其他五个转换以获得其他旋转顺序.我想我希望有一个更"全面"的解决方案.无论如何,我很惊讶我找不到现有的解决方案.
另外,这也许应该是一个单独的问题,任何转换(假设已知的旋转顺序,当然)将选择一个欧拉表示,但实际上有很多.例如,给定yxz的旋转顺序,两个表示(0,0,180)和(180,180,0)是等价的(并且将产生相同的四元数).有没有办法用限制自由度来约束解决方案?就像你在IK和僵硬的身体动力学中做的那样?即,在上述示例中,如果关于Z轴仅存在一个自由度,则可以忽略第二表示.
我已经找到了一篇可能是这个pdf算法的论文,但我必须承认,我发现逻辑和数学有点难以理解.当然还有其他解决方案吗?任意轮换顺序真的如此罕见吗?当然,每个允许骨架动画和四元数插值(即Maya,Max,Blender等)的主要3D包必须解决这个问题吗?
我正在研究2自由度(俯仰和滚动)的运动模拟器.我正在从游戏中读取变换矩阵,我需要获得角度并发送到硬件来驱动电机.由于欧拉角有奇点,我不能真正使用它们.它的行为如下:

什么时候应该这样:

我准备了在线示例以更好地显示问题:
// Get euler angles from model matrix
var mat = model.matrix;
mat.transpose();
var e = new THREE.Euler();
e.setFromRotationMatrix(mat, 'XZY');
var v = e.toVector3();
var pitch = -v.z;
var roll = -v.x;
Run Code Online (Sandbox Code Playgroud)
http://jsfiddle.net/qajro0ny/3/
据我了解,这里有两个问题.
我已经读过关于万向节锁甚至实现了euler过滤器,但是没有按预期工作.关于万向节锁的大多数建议是使用四元数,但我不能用四元数驱动物理运动(或者我可以?).
轴顺序在这里并不重要,因为更改它只会将奇点从一个轴移动到另一个轴.
我需要以其他方式处理这个问题.
我尝试用矩阵乘以轴向量,然后使用十字和点积来获得角度,但这也失败了.我认为还应该进行轴重投,以实现这一目标,但我无法弄明白.但有些事情告诉我,这是正确的方法.它是这样的:http://jsfiddle.net/qajro0ny/53/
然后我提出了不同的想法.我知道以前的位置,所以可能会做以下事情:
所以我试过了......它奏效了!在任何方向上都没有奇点,在俯仰,滚转和偏航方面完美的360度旋转.完美的解决方案!除了......它不是.帧没有同步,所以经过一段时间的角度远离他们应该是什么.我一直在考虑某种同步机制,但我认为这不是正确的方法.
它看起来像这样:http://jsfiddle.net/qajro0ny/52/
和相同的逻辑,但直接与矩阵:http://jsfiddle.net/qajro0ny/54/
我搜索了网页的高低,我已经阅读了几十篇论文和其他问题/帖子,我简直无法相信没有什么能真正起作用.
我可能不理解或遗漏某些东西,所以这里是我发现和尝试的一切:
链接:http://pastebin.com/3G0dYLvu
代码:http://pastebin.com/PiZKwE2t(我把它们放在一起,所以它很乱)
我一定是错过了什么,或者我是从错误的角度看这个.
我正在使用单个对象的两个图像,该对象从其第一个图像开始特定程度.
我已经计算了每个图像的POSE,并使用Rodergues()将旋转矢量转换为Matrix.现在我如何计算并查看它从第一个位置旋转了多少?
我尝试了很多方法,但答案并非接近
编辑:我的相机是固定的只有物体在移动.
我很难将设备运动(传感器融合)映射到SceneKit节点旋转.问题的前提如下,
我有球体,并且相机定位在球体内部,使得球体的几何中心和相机节点的中心重合.我想要实现的是当我围绕一个点物理旋转时,运动也需要准确地映射到相机上.
实施细节如下:
我有一个节点,一个球体作为几何,并且是一个子节点.我正在使用传感器融合来获得姿态四元数,然后将它们转换为欧拉角.代码是:
- (SCNVector3)eulerAnglesFromCMQuaternion:(CMQuaternion) {
GLKQuaternion gq1 = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(90), 1, 0, 0);
GLKQuaternion gq2 = GLKQuaternionMake(q.x, q.y, q.z, q.w);
GLKQuaternion qp = GLKQuaternionMultiply(gq1, gq2);
CMQuaternion rq = {.x = qp.x, .y = qp.y, .z = qp.z, .w = qp.w};
CGFloat roll = atan2(-rq.x*rq.z - rq.w*rq.y, .5 - rq.y*rq.y - rq.z*rq.z);
CGFloat pitch = asin(-2*(rq.y*rq.z + rq.w*rq.x));
CGFloat yaw = atan2(rq.x*rq.y - rq.w*rq.z, .5 - rq.x*rq.x - rq.z*rq.z);
return SCNVector3Make(roll, pitch, yaw);
}
Run Code Online (Sandbox Code Playgroud)
转换方程式来自 3D Math Primer for Graphics …
我正试图获得FaceDetector检测到的Face的Euler角度.
这是我用来输出到Logcat的东西:
Log.v("debug", " X: " + face.pose(Face.EULER_X) + " Y: " + face.pose(Face.EULER_Y) + " Z: " + face.pose(Face.EULER_Z) );
Run Code Online (Sandbox Code Playgroud)
但无论面部处于什么角度,它总是为所有三个返回0.0.有什么想法吗?
我正在寻找一种方法将方向矢量(X,Y,Z)转换为欧拉角(航向,俯仰,坡度).我知道方向矢量本身不足以获得倾斜角度,因此还有另一个所谓的向上矢量.
有方向向量(X,Y,Z)和向上向量(X,Y,Z)我如何将其转换为欧拉角?
因此,我编写了一个面向新程序员的基于四元数的3D相机,因此它们非常容易集成并开始使用.
在我开发它时,首先我将用户输入作为欧拉角,然后根据该帧的输入生成一个四元数.然后,我将拍摄相机的四元数并将其乘以我们为输入生成的四元数,理论上应该简单地将输入旋转添加到相机旋转的当前状态,事情就会变得既肥胖又快乐.让我们称之为:积累四元数,因为我们只存储和添加四元数.
但是我注意到这个方法存在问题.我使用的越多,即使我只是在一个欧拉角上旋转,比如Yaw,在一些迭代中,它会开始流血到另一个,Pitch说.这很轻微,但相当不可接受.
所以我做了一些更多的研究,并发现一篇文章说明积累欧拉角更好,所以相机将它的当前旋转存储为欧拉角,并且输入只是每帧添加到它们.然后我从每个帧生成一个四元数,然后用它来生成我的旋转矩阵.这解决了旋转出血问题进入不正确的轴.
那么任何Stackoverflow成员都能对这个问题有所了解吗?这是一种正确的做事方式吗?
我正在开发一个应用程序,我需要纠正从移动相机平台拍摄的图像.平台测量滚动角,俯仰角和偏航角,我希望通过这种信息的某种变换使图像看起来像是从正上方拍摄的.
换句话说,我想要一个平躺在地面上的完美广场,从远处拍摄一些相机方向,进行转换,以便广场在之后完全对称.
我一直试图通过OpenCV(C++)和Matlab来做到这一点,但我似乎缺少一些关于如何完成的基本信息.
在Matlab中,我尝试了以下内容:
%% Transform perspective
img = imread('my_favourite_image.jpg');
R = R_z(yaw_angle)*R_y(pitch_angle)*R_x(roll_angle);
tform = projective2d(R);
outputImage = imwarp(img,tform);
figure(1), imshow(outputImage);
Run Code Online (Sandbox Code Playgroud)
其中R_z/y/x是标准旋转矩阵(用度数实现).
对于某些偏航旋转,一切正常:
R = R_z(10)*R_y(0)*R_x(0);
Run Code Online (Sandbox Code Playgroud)
结果如下:

如果我尝试围绕X轴或Y轴旋转相同数量的图像,我会得到如下结果:
R = R_z(10)*R_y(0)*R_x(10);
Run Code Online (Sandbox Code Playgroud)

但是,如果我旋转10度,除以一些巨大的数字,它开始看起来不错.但话说回来,这是一个没有研究价值的结果:
R = R_z(10)*R_y(0)*R_x(10/1000);
Run Code Online (Sandbox Code Playgroud)

有人可以帮助我理解为什么围绕X轴或Y轴旋转会使转换变得疯狂吗?有没有办法解决这个问题而不用一些随机数和其他魔术技巧?这可能是某些可以使用某种Euler参数解决的东西吗?任何帮助将非常感谢!
更新:完整设置和测量
为了完整性,添加了完整的测试代码和初始图像,以及平台Euler角度:
码:
%% Transform perspective
function [] = main()
img = imread('some_image.jpg');
R = R_z(0)*R_y(0)*R_x(10);
tform = projective2d(R);
outputImage = imwarp(img,tform);
figure(1), imshow(outputImage);
end
%% Matrix for Yaw-rotation about the Z-axis
function [R] = R_z(psi)
R = [cosd(psi) -sind(psi) 0;
sind(psi) cosd(psi) 0; …Run Code Online (Sandbox Code Playgroud) 在试图回答另一个SO问题时,出现了如何计算尺寸> 3的欧拉角的问题.该RSpincalc软件包具有直接的DCM2EA功能,可将3d旋转矩阵转换为Euler或Tait-Bryan角度,但这仅处理3维的特定情况.关于欧拉角的维基百科页面简要讨论了将欧拉角扩展到更高维度的问题,并引用了一篇意大利语论文,该论文显然将该方法推广到更大数量的维度.不幸的是,我的意大利语和我的数学都没有完全掌握这篇论文并创建一个可用的R函数.
至少可以说,我在这个答案中使用的当前方法有点麻烦.我使用Ryacas包来创建一个符号矩阵,它是一系列旋转的复合,用于任意数量的维度.然后可以针对已知的旋转矩阵迭代地求解,以找到所需的角度.它有效,但一旦维数为5或更多,它就变得越来越慢.
是否有更好的方法来实现这一目标,无论是通过意大利报纸中的方法实施还是其他方式?
我正在使用lib glm(http://glm.g-truc.net/)进行测试四元数,但我遇到了问题; 当我将欧拉角转换为四元数然后立即将四元数转换为欧拉角时,我的结果与我的初始欧拉角完全不同.这是正常的吗?可能是因为轮换不是交际?
代码测试:
#include <glm\quaternion.hpp>
#include <math.h>
#define PI M_PI
#define RADTODEG(x) ( (x) * 180.0 / PI )
#define DEGTORAD(x) ( (x) * PI / 180.0 )
int main( void )
{
float RotX = 90.f;
float RotY = 180.f;
float RotZ = -270.f;
if ( RotX || RotY || RotZ )
{
std::cout << "Init: x= " << RotX << ", y= " << RotY << ", z= " << RotZ << "\n";
glm::quat key_quat(glm::detail::tvec3<float>(DEGTORAD( …Run Code Online (Sandbox Code Playgroud) euler-angles ×10
math ×6
quaternions ×4
c++ ×3
3d ×2
geometry ×2
opencv ×2
rotation ×2
android ×1
animation ×1
core-motion ×1
matlab ×1
matrix ×1
objective-c ×1
r ×1
scenekit ×1