简体   繁体   English

偏航,俯仰和滚动到glm ::旋转

[英]Yaw, Pitch and roll to glm::rotate

I've been trying to figure out this for hours now and I simply cannot come up with a solution for this: What I'm trying to achieve is transforming an orientation vector into 3 glm::rotation calls. 我一直试图弄清楚这几个小时,我根本无法想出一个解决方案:我想要实现的是将方向向量转换为3个glm::rotation调用。

I have a cylinder positioned at (0, 0, 0) with a certain radius and height. 我有一个位于(0, 0, 0)的圆柱体,具有一定的半径和高度。 With the Leap Motion SDK I'm performing tool tracking that gives me the tip position and a direction vector (that is expressed as a unit vector pointing in the same direction as the tip): 使用Leap Motion SDK我正在执行工具跟踪,它给出了尖端位置和方向向量(表示为指向与尖端相同方向的单位向量):

在此输入图像描述 Source: https://developer.leapmotion.com/documentation/skeletal/java/api/Leap.Pointable.html 资料来源: https//developer.leapmotion.com/documentation/skeletal/java/api/Leap.Pointable.html

Furthermore, yaw , pitch and roll can be extracted form that vector using the following SDK functions: 此外,可以使用以下SDK函数从该向量中提取yawpitchroll

/// The yaw angle in radians.
///
/// Yaw is the angle between the negative z-axis and the projection of
/// the vector onto the x-z plane. In other words, yaw represents rotation
/// around the y-axis. If the vector points to the right of the negative z-axis,
/// then the returned angle is between 0 and pi radians (180 degrees);
/// if it points to the left, the angle is between 0 and -pi radians.
///
/// \image html images/Math_Yaw_Angle.png
///
/// @returns The angle of this vector to the right or left of the negative z-axis.
float yaw() const 
{
  return std::atan2(x, -z);
}

/// The pitch angle in radians.
///
/// Pitch is the angle between the negative z-axis and the projection of
/// the vector onto the y-z plane. In other words, pitch represents rotation
/// around the x-axis.
/// If the vector points upward, the returned angle is between 0 and pi radians
/// (180 degrees); if it points downward, the angle is between 0 and -pi radians.
///
/// \image html images/Math_Pitch_Angle.png
///
/// @returns The angle of this vector above or below the horizon (x-z plane).
float pitch() const {
  return std::atan2(y, -z);
}

/// The roll angle in radians.
///
/// Roll is the angle between the negative y-axis and the projection of
/// the vector onto the x-y plane. In other words, roll represents rotation
/// around the z-axis. If the vector points to the left of the negative y-axis,
/// then the returned angle is between 0 and pi radians (180 degrees);
/// if it points to the right, the angle is between 0 and -pi radians.
///
/// \image html images/Math_Roll_Angle.png
///
/// Use this function to get roll angle of the plane to which this vector is a
/// normal. For example, if this vector represents the normal to the palm,
/// then this function returns the tilt or roll of the palm plane compared
/// to the horizontal (x-z) plane.
///
/// @returns The angle of this vector to the right or left of the y-axis.
float roll() const {
  return std::atan2(x, -y);
}

In my OpenGL rendering loop, I'm extracting the tip position as well as the direction vector every frame. 在我的OpenGL渲染循环中,我每帧提取尖端位置以及方向向量。 I'm passing the model matrix as a uniform variable to my shaders in the following way: 我将模型矩阵作为统一变量传递给我的着色器,方法如下:

cylinder->ResetModelMatrix(); // Set model matrix to identity
glm::vec3 translation = glm::vec3(toolTipPosition.x, toolTipPosition.y, toolTipPosition.z);
cylinder->TranslateModel(translation);
cylinderProgram->SetUniform("modelMatrix", cylinder->GetModelMatrix());

With only the translation, this works nicely and looks something like this (with the cylinder always pointing up): 只有翻译,这很好用,看起来像这样(圆柱总是朝上): 在此输入图像描述

The problem occurs when I'm trying to rotate the cylinder according to the Leap's tool orientation. 当我试图根据Leap的工具方向旋转圆柱体时会出现问题。 I have the following code: 我有以下代码:

yaw = toolDirection.yaw() * Leap::RAD_TO_DEG;
// similarly for pitch and roll

cylinder->Rotate(yaw, glm::vec3(0.0f, 1.0f, 0.0f));
// pitch around (1, 0, 0) and roll around (0, 0, 1)

However, I'm not getting the proper orientations and the cylinder is "flickering" and jumping between a lot of orientations when I try to apply this. 然而,当我试图应用它时,我没有得到正确的方向并且圆柱体“闪烁”并且在许多方向之间跳跃。


The important transformation functions are located in an interface from which my cylinder class is inheriting... 重要的转换函数位于我的柱面类继承的接口中...

void Drawable::ResetModelMatrix()
{
    this->modelMatrix = glm::mat4(1.0f);
}

void Drawable::TranslateModel(glm::vec3 translationVector)
{
    this->modelMatrix = glm::translate(this->modelMatrix, translationVector);
}

void Drawable::RotateModel(float angle_in_degrees, glm::vec3 axisOfRotation)
{
    this->modelMatrix = glm::rotate(this->modelMatrix, angle_in_degrees, axisOfRotation);
}

void Drawable::ScaleModel(glm::vec3 scalingVector)
{
    this->modelMatrix = glm::scale(this->modelMatrix, scalingVector);
}

...with modelMatrix beeing a member variable. ...使用modelMatrix成为成员变量。

I've scanned a lot of similar questions on the topic of rotation in OpenGL and in general, but I'm not really sure what's exactly the problem with my code here. 我已经在OpenGL和一般情况下扫描了许多关于旋转主题的类似问题,但我不确定我的代码究竟是什么问题。

I guess that there is some misunderstanding of what we have and what we want to get. 我想对我们拥有的和我们想要得到的东西存在一些误解。

The case is that, the direction vector does not uniquely determines the orientation of the body in space. 情况是,方向矢量不能唯一地确定身体在空间中的方向。 To make this statement clear, let's get a closer look at how can the rotations be represented in 3D space. 为了使这个陈述清楚,让我们仔细看看如何在3D空间中表示旋转。

Rotations about the origin have three degrees of freedom. 关于原点的旋转具有三个自由度。 This means, that you need three independent parameters to uniquely specify the orientation of a body. 这意味着,您需要三个独立参数来唯一地指定正文的方向。 Exactly three, no more no less. 正好三个,不多也不少。 There is no matter what are they as far as none of them can't be expressed it terms of other. 无论他们是什么,只要他们都不能表达其他的条款。 A 3D rotation can be specified in a number of ways. 可以通过多种方式指定3D旋转。 The most usual methods are: 最常用的方法是:

  • Euler angles. 欧拉角。 Three independent parameters. 三个独立的参数。
  • Tait–Bryan angles (yaw, pitch, and roll). Tait-Bryan角度(偏航,俯仰和滚转)。 Also three independent parameters. 还有三个独立的参数。 Do not confuse with Euler angles, they are not the same! 不要与欧拉角混淆,它们不一样!
  • Axis–angle representation. 轴角表示。 Specifies a rotation by a unit vector and an angle. 通过单位矢量和角度指定旋转。 You could argue, that there are four parameters for this case. 你可以说,这种情况有四个参数。 However it is not true, because these parameters are not independent. 但事实并非如此,因为这些参数并不是独立的。 Indeed, there is a constraint on the length of the unit vector. 实际上,单位矢量的长度存在约束。 Or you can treat this as the length of the vector doesn't effect the rotation. 或者您可以将其视为向量的长度不会影响旋转。 Thus, again, there are three independent parameters. 因此,再次有三个独立的参数。
  • Orientation quaternion. 方位四元数。 The same as the previous method, four parameters, that are dependent. 与前一个方法相同,四个参数依赖。 Generally, orientation quaternion can be treated as a way to encode axis–angle representation. 通常,可以将方向四元数视为编码轴角度表示的方式。 The length of a quaternion does not effect the rotation and usually quaternion is assumed to have a unit length. 四元数的长度不会影响旋转,通常假定四元数具有单位长度。 Thus, we have four parameters and one constraint that means that we have three independent degrees of freedom. 因此,我们有四个参数和一个约束,这意味着我们有三个独立的自由度。

Let's get a closer look to your problem. 让我们仔细看看你的问题。 You have a direction vector and you want to use it to determine orientation of the cylinder. 你有一个方向向量,你想用它来确定圆柱的方向。 Essentially, you have only two independent parameters, because the length of the direction vector does not matter (let it be a unit vector for simplicity). 基本上,您只有两个独立的参数,因为方向向量的长度无关紧要(为简单起见,它是一个单位向量)。 So you can't just get the rotation from a direction vector, because there would be one arbitrary parameter. 所以你不能只从方向向量得到旋转,因为会有一个任意参数。

It is just impossible to get three unknown independent parameters from the input that contain only two independent parameters. 只能从输入中获得三个未知的独立参数,这些参数只包含两个独立参数。 There is a need for some additional constraint. 需要一些额外的约束。 Usually it is an Up-vector . 通常它是向上矢量 The additional constraint transforms the three unknown independent parameters into dependent parameters. 附加约束将三个未知的独立参数转换为相关参数。

I'd advise you to use glm::orientation function that builds an orientation matrix from the input of a direction vector and an up-vector. 我建议你使用glm :: orientation函数,它从方向向量和向上向量的输入构建方向矩阵。

As for yaw, pitch and roll angles, that you get from the specified SDK functions. 至于从指定的SDK函数获得的偏航,俯仰和滚转角度。 This functions doesn't not work in a way you are trying to use them. 此功能不会以您尝试使用它们的方式工作。 You should specify an up-vector. 您应该指定向上矢量。 For example, let's consider, that the up-vector is the direction of the y axle. 例如,让我们考虑一下,向上矢量是y轴的方向。 This means, that the roll angle would be always zero. 这意味着,侧倾角始终为零。 You should calculate the yaw angle, just as you do it before. 您应该像以前一样计算偏航角度。 So: 所以:

float yaw = std::atan2(x, -z);

The pitch angle would be std::atan2(y, -z) , but in rotated frame, not in the original. 俯仰角度为std :: atan2(y,-z) ,但在旋转的框架中,不在原始角度。 You should consider the pitch angle as an arc-tangent of the ratio of the direction vector projection length onto the xz plane and its projection onto y axle. 您应该将俯仰角视为方向矢量投影长度与xz平面的比率及其在y轴上的投影的反正切。 I mean: 我的意思是:

float projectionLength = std::sqrt(x * x + z * z);
float pitch = std::atan2(y, projectionLength);

When you are constructing the transform matrix, you should first apply the rotation appropriate to the pitch angle, then the rotation appropriate to the yaw rotation and then the translation. 在构造变换矩阵时,应首先应用适合于俯仰角度的旋转,然后应用适合于偏航旋转的旋转,然后应用平移。

See this for more information about the Tait–Bryan angles 请参阅有关泰特-布赖恩角度的更多信息

Also, you should be aware of the fact, that rotations are not commutative. 此外,您应该意识到旋转不是可交换的事实。 This means that you should perform rotations in a strict sequence. 这意味着您应该按严格的顺序执行旋转。 There are six possibilities of choosing the rotation axes for Tait–Bryan angles, that are called as conventions. 选择Tait-Bryan角度的旋转轴有六种可能性,称为约定。 These conventions depend on the axes about which the rotations are carried out. 这些约定取决于进行旋转的轴。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM