- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在研究平面运动的模拟。现在,我使用欧拉角将“ body 框架”转换为“世界框架”并且效果很好。
最近我了解了四元数及其相对于旋转矩阵(万向节锁)的优势,并尝试使用模拟器中的偏航/俯仰/滚动角度来实现它。
如果我理解正确的话,四元数代表两件事。它有一个 x, y, 和 z 组件,代表将发生旋转的轴。它还有一个 w 分量,表示围绕该轴发生的旋转量。简而言之,一个 vector 和一个 float 。四元数可以表示为 4 元素 vector :
q=[w,x,y,z]
要计算结果(完全旋转后),方程使用:
p'=qpq'
地点:
p=[0,x,y,z]-方向 vector
q=[w,x,y,z]-旋转
q'=[w,-x,-y,-z]
使用 wikipedia我通过围绕 3 个轴 (q) 旋转来创建四元数:
Quaterniond toQuaternion(double yaw, double pitch, double roll) // yaw (Z), pitch (Y), roll (X)
{
//Degree to radius:
yaw = yaw * M_PI / 180;
pitch = pitch * M_PI / 180;
roll = roll * M_PI / 180;
// Abbreviations for the various angular functions
double cy = cos(yaw * 0.5);
double sy = sin(yaw * 0.5);
double cp = cos(pitch * 0.5);
double sp = sin(pitch * 0.5);
double cr = cos(roll * 0.5);
double sr = sin(roll * 0.5);
Quaterniond q;
q.w = cy * cp * cr + sy * sp * sr;
q.x = cy * cp * sr - sy * sp * cr;
q.y = sy * cp * sr + cy * sp * cr;
q.z = sy * cp * cr - cy * sp * sr;
return q;
}
定义平面方向(航向) vector :
p = [0,1,0,0]
计算 Hamilton product :
p'=qpq'
q'= [w, -qx, -qy, -qz]
p' = (H(H(q, p), q')
Quaterniond HamiltonProduct(Quaterniond u, Quaterniond v)
{
Quaterniond result;
result.w = u.w*v.w - u.x*v.x - u.y*v.y - u.z*v.z;
result.x = u.w*v.x + u.x*v.w + u.y*v.z - u.z*v.y;
result.y = u.w*v.y - u.x*v.z + u.y*v.w + u.z*v.x;
result.z = u.w*v.z + u.x*v.y - u.y*v.x + u.z*v.w;
return result;
}
我的结果将是一个 vector :
v=[p'x,p'y,p'z]
它工作正常但与欧拉角旋转(万向节锁定)相同。是因为我在这里也使用了欧拉角吗?如果不绕 3 个轴旋转,我真的不知道它应该如何工作。我应该分别绕每个轴旋转吗?
对于理解这个问题的任何建议和帮助,我将不胜感激。
<强>1。我的应用程序基于数据流,这意味着每 1 毫秒检查一次是否有新数据(平面的新方向)。
示例:
在开始时 pitch/roll/yaw = 0,在 1ms 偏航改变 10 度后,应用程序读取 pitch=0,roll=0,偏航 = 10。在接下来的 1 毫秒后,偏航再次改变 20 度。因此输入数据将如下所示:pitch=0, roll=0, yaw = 30。
<强>2。创建方向四元数 - p
在开始时,我定义了我的飞机的方向(头部)在 X 轴上。所以我本地的方向是v=[1,0,0]四元数 (my p) 是p=[0,1,0,0]
Vector3 LocalDirection, GlobalDirection; //head
Quaterniond p,P,q, Q, pq; //P = p', Q=q'
LocalDirection.x = 1;
LocalDirection.y = 0;
LocalDirection.z = 0;
p.w = 0;
p.x = direction.x;
p.y = direction.y;
p.z = direction.z;
<强>3。创建旋转
在每 1 毫秒 之后,我检查来自数据流的旋转角度 (Euler),并使用 toQuaternion 计算 q
q = toQuaternion(yaw, pitch, roll); // create quaternion after rotation
Q.w = q.w;
Q.x = -q.x;
Q.y = -q.y;
Q.z = -q.z;
<强>4。计算“世界方向”
使用 Hamilton 积 我计算旋转后的四元数,这是我的全局方向:
pq = HamiltonProduct(q, p);
P = HamiltonProduct(pq, Q);
GlobalDirection.x = P.x;
GlobalDirection.y = P.y;
GlobalDirection.z = P.z;
<强>5。每 1 毫秒
重复 3-4 次最佳答案
您的模拟似乎每帧都使用欧拉角来旋转对象。然后将这些角度转换为四元数。这不会解决万向节锁定问题。
当您将欧拉角添加到欧拉角时,万向节锁随时可能发生。从本地空间到世界空间时,仅仅解决这个问题是不够的。您还需要您的模拟在帧之间使用四元数。
基本上每次您的对象改变其旋转时,将当前旋转转换为四元数,乘以新的旋转增量,并将结果转换回欧拉角或您用来存储旋转的任何值。
我建议重写您的应用程序以仅使用四元数。每当用户进行输入或您的游戏的某些其他逻辑想要旋转某些内容时,您会立即将该输入转换为四元数并将其输入模拟。
有了 toQuaternion
和 HamiltonProduct
,您就拥有了所需的所有工具。
EDIT 作为对您解释应用程序工作原理的编辑的回应。
At the begging pitch/roll/yaw = 0, after 1ms yaw is changed by 10 degree so application reads pitch=0, roll=0, yaw = 10. After next 1ms yaw is changed again by 20 degrees. So input data will look like this: pitch=0, roll=0, yaw = 30.
这就是万向节锁定发生的地方。在计算旋转后您转换为四元数。那是错的。您需要在这第一步中使用四元数。不要在 1ms yaw 改变 10 度后,应用程序读取 pitch=0,roll=0,yaw = 10
,执行此操作:
澄清一下:您的第 2、3 和 4 步没问题。问题出在第 1 步。
旁注,这是:
It has an x, y, and z component, which represents the axis about which a rotation will occur. It also has a w component, which represents the amount of rotation which will occur about this axis
不完全正确。四元数的分量不是直接的轴和角度,它们是 sin(angle/2) * axis
和 cos(angle/2)
(这是你的 toQuaternion
方法产生)。这很重要,因为它为您提供了构成 4D sphere 的漂亮单位四元数。表面上的每个点(表面空间?)代表 3D 空间中的旋转,完美地允许在任意两个旋转之间进行平滑插值。
关于c++ - 从欧拉角到四元数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56576403/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!