标签: quaternions

欧拉角到四元数然后四元数到欧拉角

我正在使用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)

c++ math rotation quaternions euler-angles

13
推荐指数
3
解决办法
4万
查看次数

两个四元数之间的差异

解决了


我正在我的引擎中制作一个3D门户系统(比如Portal游戏).每个门户都有自己的方向保存在四元数中.要在其中一个门户中渲染虚拟场景,我需要计算两个四元数之间的差异,结果用于旋转虚拟场景.

当在左墙上创建第一个门户,在右墙上创建第二个门户时,从一个到另一个的旋转将仅在一个轴上进行,但是例如当第一个门户将在地板上创建时,第二个门户将在地板上创建在右侧墙上,从一个轴到另一个轴的旋转可能在两个轴上,这就是问题,因为旋转出错了.

我认为问题的存在是因为例如X轴和Z轴的方向一起存储在一个四元数中,我需要它单独地进行手工乘法X*Z(或Z*X),但是如何只使用一个四元数(差值四元数)?或者还有其他方法来纠正旋转场景吗?

编辑:

这张照片上有两个门户P1和P2,箭头显示它们是如何旋转的.在我看P1时,我会看到P2的内容.要找到我需要旋转主场景的旋转,就像这张图片中的虚拟场景,我正在做以下事情:

  1. 从四元数P2到四元数P1的区别
  2. 在Y轴上旋转180度(门户网站向上)
  3. 使用结果旋转虚拟场景

上述方法仅在差异仅在一个轴上发生时才有效.当一个门户在地板上或在天花板上时,这将不起作用,因为差异四元数是在多个轴上构建的.正如所建议的那样,我试图将P1的四元数乘以P2的四元数,反过来但这不起作用.

在此输入图像描述

编辑2:

要找到从P2到P1的差异,我正在做以下事情:

Quat q1 = P1->getOrientation();
Quat q2 = P2->getOrientation();

Quat diff = Quat::diff(q2, q1);  // q2 * diff = q1 //
Run Code Online (Sandbox Code Playgroud)

这是Quat :: diff函数:

GE::Quat GE::Quat::diff(const Quat &a, const Quat &b)
{
    Quat inv = a;
    inv.inverse();
    return inv * b;
}
Run Code Online (Sandbox Code Playgroud)

逆:

void GE::Quat::inverse()
{
    Quat q = (*this);
    q.conjugate();
    (*this) = q / Quat::dot((*this), (*this)); …
Run Code Online (Sandbox Code Playgroud)

math portal-system rotation quaternions

13
推荐指数
2
解决办法
4万
查看次数

限制相机间距

当我只有相机四元数时,如何才能有效地限制相机间距?我是否必须转换为欧拉角然后再转换为四元数或者还有其他方法吗?

math 3d camera quaternions

12
推荐指数
1
解决办法
1569
查看次数

四元数 - >欧拉角 - >旋转矩阵故障(GLM)

我正在编写一个程序来加载包含场景描述的文件,然后使用OpenGL显示它.我正在使用GLM进行所有数学运算.场景文件中的旋转以四元数格式存储.我的场景管理系统以欧拉角的形式对物体进行旋转,然后在绘制时将这些角度转换为旋转矩阵.

因此,我的加载过程采用四元数旋转,将它们转换为欧拉角以存储在我的对象类中,然后将这些欧拉角转换为旋转矩阵以进行绘制.我正在使用glm :: eulerAngles和glm :: eulerAngleYXZ函数来执行这两个操作.

但是,我的结果不正确.例如,如果我理解正确,四元数{0.500 -0.500 0.500 0.500}(即WXYZ)应该描述从+ Z轴到+ Y轴的箭头旋转.但是,当我运行程序时,我得到的箭头指向+ X轴.

我认为我对四元数的理解存在一些缺陷,但我可以跳过中间的欧拉角形式来得到我预期的结果.通过使用glm :: toMat4将四元数直接转换为旋转矩阵,我得到一个将我的+ Z箭头指向+ Y的旋转.

考虑到两种方法看起来既简单又正确,我无法协调这两种不同的输出.为了简化我的问题,为什么这两个看似等效的方法会产生不同的结果:

glm::quat q(.5, -.5, .5, .5);
glm::vec3 euler = glm::eulerAngles(q) * 3.14159f / 180.f; // eulerAngleYXZ takes radians but eulerAngles returns degrees
glm::mat4 transform1 = glm::eulerAngleYXZ(euler.y, euler.x, euler.z);
// transform1 rotates a +Z arrow so that it points at +X

glm::quat q(.5, -.5, .5, .5);
glm::mat4 transform2 = glm::toMat4(q);
// transform2 rotates a +Z arrow so that it points at +Y
Run Code Online (Sandbox Code Playgroud)

c++ math quaternions euler-angles glm-math

12
推荐指数
2
解决办法
1万
查看次数

欧拉角与四元数 - 由内部存储和呈现给用户之间的张力引起的问题?

四元数可以说是在内部表示对象旋转的合适选择.它们简单有效地插入并明确表示单个方向.

但是,在用户界面中显示四元数通常是不合适的 - 欧拉角通常对用户来说更为熟悉,并且它们的值更直观和可预测.

欧拉角在代码级别上变得复杂 - 它们需要存储旋转顺序,并且使用该顺序和相关联的角度组成实际方向(无论是矩阵还是四元数)是麻烦的,至少可以说是麻烦的.

使用四元数表示最方便地执行可靠的插值 - 这是否意味着我们必须在Euler表示和四元数表示之间不断转换?这在绩效方面是否可行?

我们可以将方向存储为四元数并将它们转换为仅显示给用户吗?这可能是不可能的,因为对于任何给定的方向,只有一个四元数表示,但有许多欧拉表示.我们如何"选择"与最初定义该方向的Euler表示相对应的Euler表示?这似乎是一项不可能完成的任务 - 我们在转换为四元数时已经有效地丢失了信息.

我们可以存储为欧拉角,然后根据需要转换为四元数吗?这可能是不可扩展的 - 从欧拉角到四元数的转换,插值,然后再转换回来可能是相对昂贵的代码.

我们可以简单地存储两种表示并使用最适合任何给定情况的表示吗?在存储器方面的大量成本(想象具有大约60个骨骼的骨架的动画曲线)并保持这些值同步可能是昂贵的,或者至少是麻烦的.

有没有人看到,使用或者解决这个问题的任何聪明的解决方案?当然上面的三个选项不仅仅是一个吗?是否有任何其他的问题领域类似这样已经解决了吗?

3d user-interface animation quaternions euler-angles

11
推荐指数
1
解决办法
1万
查看次数

从四元数到OpenGL旋转

我有一个对象,我想通过键旋转.物体应偏航,俯仰和滚动.在尝试了很多之后,我发现它glRotate有其局限性并且不可能用这个函数实现类似的东西.

我研究了一下,发现了基于四元数的旋转.也可以通过旋转矩阵旋转,但几乎每个人都将四元数描述为有史以来最好的.

我已经阅读了关于四元数并且相当理解它们的内容,但是如何在我的OpenGL程序中实现它们仍然是一个谜.有谁知道一个小例子?不是如何实现四元数类,而是如何使用它.我不知道如何把事情放在一起.

c++ opengl linear-algebra quaternions

11
推荐指数
2
解决办法
4691
查看次数

Three.js Object3d柱面旋转以对齐矢量

我搜索得很远,但似乎无法想象这个非常基本的东西.我已经在一年或两年前看过stackoverflow和其他地方的其他例子,但他们无法使用最新版本的Three.js.

这是我正在研究的版本:http://medschoolgunners.com/sandbox/3d/.

我试图让灰色圆锥与未标记的红色矢量完全对齐.IE浏览器.我希望锥体的尖端与矢量精确对齐,并从该方向的原点指出.

这是我现在的代码:

    //FUNCTION TO CREATE A CYLINDER
function create_cylinder(radiusTop,radiusBottom, height, segmentsRadius, segmentsHeight, openEnded, color)
{
var material = new THREE.MeshLambertMaterial({
    color: color, //0x0000ff
    opacity: 0.2
});
var cylinder = new THREE.Mesh(new THREE.CylinderGeometry(radiusTop,radiusBottom, height, segmentsRadius, segmentsHeight, openEnded), material);

cylinder.overdraw = true;

return cylinder;
}

//ALIGN THE CYLINDER TO A GIVEN VECTOR
var alignVector=new THREE.Vector3(-50,50,50); //the vector to be aligned with

var newcylinder = create_cylinder(0.1, 10, 40, 50, 50, false, "0x0ff0f0");  // the object to be …
Run Code Online (Sandbox Code Playgroud)

javascript rotation quaternions three.js

11
推荐指数
3
解决办法
2万
查看次数

使用cv :: Mat进行高效的C++四元数乘法

我想乘以2个四元数,它们存储在cv :: Mat结构中.我希望功能尽可能高效.到目前为止,我有以下代码:

/** Quaternion multiplication
 *
 */
void multiplyQuaternion(const Mat& q1,const Mat& q2, Mat& q)
{
    // First quaternion q1 (x1 y1 z1 r1)
    const float x1=q1.at<float>(0);
    const float y1=q1.at<float>(1);
    const float z1=q1.at<float>(2);
    const float r1=q1.at<float>(3);

    // Second quaternion q2 (x2 y2 z2 r2)
    const float x2=q2.at<float>(0);
    const float y2=q2.at<float>(1);
    const float z2=q2.at<float>(2);
    const float r2=q2.at<float>(3);


    q.at<float>(0)=x1*r2 + r1*x2 + y1*z2 - z1*y2;   // x component
    q.at<float>(1)=r1*y2 - x1*z2 + y1*r2 + z1*x2;   // y component
    q.at<float>(2)=r1*z2 …
Run Code Online (Sandbox Code Playgroud)

c++ opencv quaternions

11
推荐指数
1
解决办法
6590
查看次数

"看着"具有四元数的对象

所以我目前正在尝试创建一个函数,它将采用两个3D点A和B,并为我提供四元数,表示点A要求"看"点B所需的旋转(这样点A的局部Z轴通过B点,如果你愿意).

我最初发现这篇文章,其中最重要的答案似乎为我提供了一个很好的起点.我继续实现以下代码; 而不是假设默认(0,0,-1)方向,正如原始答案所示,我尝试提取表示相机实际方向的单位向量.

void Camera::LookAt(sf::Vector3<float> Target)
{
    ///Derived from pseudocode found here:
    ///https://stackoverflow.com/questions/13014973/quaternion-rotate-to

    //Get the normalized vector from the camera position to Target
    sf::Vector3<float> VectorTo(Target.x - m_Position.x,
                                Target.y - m_Position.y,
                                Target.z - m_Position.z);
    //Get the length of VectorTo
    float VectorLength = sqrt(VectorTo.x*VectorTo.x +
                              VectorTo.y*VectorTo.y +
                              VectorTo.z*VectorTo.z);
    //Normalize VectorTo
    VectorTo.x /= VectorLength;
    VectorTo.y /= VectorLength;
    VectorTo.z /= VectorLength;

    //Straight-ahead vector
    sf::Vector3<float> LocalVector = m_Orientation.MultVect(sf::Vector3<float>(0, 0, -1));

    //Get the cross product as the axis of rotation
    sf::Vector3<float> Axis(VectorTo.y*LocalVector.z - VectorTo.z*LocalVector.y, …
Run Code Online (Sandbox Code Playgroud)

c++ opengl rotation quaternions sfml

11
推荐指数
1
解决办法
5611
查看次数

态度变化 - 角度和轴问题 - 四元数学

我有一个应用程序,当用户在对象周围走动时记录角度,同时将设备(最好)指向对象的中心.角度会根据用户的命令重置 - 因此参考态度会重置.

使用欧拉角产生万向节锁,所以我目前使用四元数并以这种方式计算角度:

double angleFromLastPosition = acos(fromLastPositionAttitude.quaternion.w) * 2.0f;
Run Code Online (Sandbox Code Playgroud)

这样可以提供良好的精度,并且它可以很好地工作,因为设备的俯仰和偏航不会改变.换句话说,当角度显示360度时,我最终在与圆的开始相同的位置.

问题1:如果设备的偏航和俯仰稍微改变(用户不直接指向物体的中心),angleFromLastPosition也是如此.我理解这一部分,因为我的角度公式只显示了3D空间中两个设备态度之间的角度.

场景:

  • 我标记了旋转姿态的开始,并在指向中心的同时开始围绕物体旋转
  • 我停下来,比如45度,并通过指向更高或更低来改变设备的音高.角度相应地改变.
  • 我希望看到的是:即使俯仰或偏航发生变化,角度仍保持在45度.

问题1是,如何仅使用四元数计算设备的滚动,并忽略其他两个轴的变化(至少在某个合理的度数范围内).

问题2:如果我旋转一点然后完全冻结设备(在三脚架上没有任何振动),angleFromLastPosition以大约10-20秒的1度漂移,并且看起来不是线性的.换句话说,它首先快速漂移,然后大幅减速.有时我根本没有漂移 - 如果设备静止,角度是坚如磐石的.这让我迷失了解正在发生的事情.

问题2,这里发生了什么,我该如何处理漂移?

我经历了不少文章和教程,目前四元数学已经超出了我的范围,希望有人能够提供一些提示,链接或几行代码.

rotation quaternions ios gyroscope core-motion

11
推荐指数
1
解决办法
2786
查看次数