【发布时间】:2015-09-14 07:24:12
【问题描述】:
我正在研究具有 2 DOF(俯仰和滚动)的运动模拟器。我正在从游戏中读取变换矩阵,我需要获取角度并发送到硬件以驱动电机。 由于欧拉角有奇点,我不能真正使用它们。它的行为如下:
(来源:gfycat.com)
什么时候应该是这样的:
(来源:gfycat.com)
我准备了在线示例以更好地说明问题:
// 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;
http://jsfiddle.net/qajro0ny/3/
据我了解,这里有两个问题。
- 模拟器上没有偏航轴。
- 即使有偏航轴,电机也不会像计算机图形那样运行,即它们需要时间才能到达目标位置。
我已经阅读了有关万向节锁的信息,甚至实现了欧拉过滤器,但这并没有按预期工作。 大多数关于云台锁定的建议是使用四元数,但我不能用四元数驱动物理电机(或者我可以吗?)。
轴顺序在这里并不重要,因为改变它只会将奇点从一个轴移动到另一个轴。
我需要以其他方式处理这个问题。
我尝试将轴向量乘以矩阵,然后使用叉积和点积来获得角度,但这也失败了。我认为还应该涉及到轴重投影才能做到这一点,但我无法弄清楚。但有件事告诉我,这是正确的做法。是这样的:http://jsfiddle.net/qajro0ny/53/
然后我想出了不同的想法。我知道以前的职位,所以也许做以下事情:
- 将矩阵转换为四元数
- 计算当前和前一个四元数之间的差异
- 将得到的四元数转换为欧拉角
- 将这些角度添加到静态俯仰、横滚和偏航变量中。
所以我尝试了,并且......它成功了!任何方向都没有奇点,俯仰、滚动和偏航的完美 360 度旋转。完美的解决方案!除了......它不是。帧没有同步,所以过了一会儿,角度偏离了它们应该的样子。我一直在考虑某种同步机制,但我认为这不是正确的方法。
看起来像这样:http://jsfiddle.net/qajro0ny/52/
同样的逻辑,但直接使用矩阵:http://jsfiddle.net/qajro0ny/54/
我在网上到处搜索,我已经阅读了几十篇论文和其他问题/帖子,我简直不敢相信没有什么真正适合我的案例。
我可能不明白或错过了什么,所以这里是我找到并尝试过的所有内容:
链接:http://pastebin.com/3G0dYLvu
代码:http://pastebin.com/PiZKwE2t(我把它们放在一起,所以很乱)
我一定是遗漏了什么,或者我从错误的角度看这个。
【问题讨论】:
标签: c++ math matrix 3d euler-angles