如何从旋转向量中获取欧拉角(Sensor.TYPE_ROTATION_VECTOR)

Posted

技术标签:

【中文标题】如何从旋转向量中获取欧拉角(Sensor.TYPE_ROTATION_VECTOR)【英文标题】:How to get the euler-angles from the rotation vector (Sensor.TYPE_ROTATION_VECTOR) 【发布时间】:2015-07-28 12:47:19 【问题描述】:

我在 x 方向(从 -180 度到 180 度)旋转了我的 android 设备,见下图。 我假设只有旋转矢量 x 值被改变。 Y 和 z 可能有一些噪音,但应该不会相差太大。

但是,我收到了这个。请看

https://docs.google.com/spreadsheets/d/1ZLoSKI8XNjI1v4exaXxsuMtzP0qWTP5Uu4C3YTwnsKo/edit?usp=sharing

我怀疑我的传感器有问题。

有什么想法吗?非常感谢。

吉米

【问题讨论】:

我还注意到文档与设备的实际移动不符。显然所有设备都错误地旋转。 你如何获得这些值?通过使用 getOrientation? 我刚刚看到这个视频:youtube.com/watch?v=C7JQ7Rpwn2k#t=2307,它很好地解释了这些概念。特别是,您可能不想使用欧拉角,而是使用旋转矩阵。 【参考方案1】:

您的传感器很好。好吧,旋转矢量条目不能简单地与围绕特定轴的旋转角度相关。 SensorEvent 结构由时间戳、传感器、精度和值组成。根据向量,values 的 float[] 的大小在 1-5 之间变化。 旋转向量值基于单位四元数,共同形成一个向量,表示这个世界框架相对于您的智能手机固定框架的方向更多 它们是无单位的,逆时针为正。

手机的方向由将东-北-上坐标与手机坐标对齐所需的旋转来表示。也就是说,对世界坐标系 (X,Y,Z) 应用旋转会使它们与手机坐标 (x,y,z) 对齐。

如果向量是旋转矩阵,则可以将其写为v_body = R_rot_vec * v_world (<--)将世界向量推入智能手机的固定描述中。 进一步关于向量:

旋转向量的三个元素等于unit四元数的最后三个分量sin(θ/2), y em>sin(θ/2), z*sin(θ/2)>.

问:那该怎么办呢? 根据您的欧拉角约定(可能有 24 个序列,有效的 12 个),您可以通过例如计算相应的角度 u := [ψ,θ,φ]应用123 序列: 如果您已经有旋转矩阵条目,请像这样获取欧拉: 321 序列: q1-3 始终是 values[0-2] (不要被 u_ijk 混淆,因为 ref(Diebel) 使用不同的约定比较标准)但是等等,您的链接表只有 3 个值,这与我得到的相似。这是我的一个SensorEvent,后三个是从values[]打印出来的

timestamp      sensortype accuracy values[0]    values[1]   values[2]
23191581386897 11         -75      -0.0036907701 -0.014922042 0.9932963

4q - 3 个值 = 1q 未知。第一个 q0 是冗余信息(doku 也表示它应该在values[3] 下,取决于您的 API 级别)。所以我们可以使用范数(=length)从其他三个计算q0。 设置方程 ||q|| = 1 并求解 q0。现在所有 q0-3 都是已知的。 此外,我的 android 4.4.2 在value[4] 内没有第四个估计的标题精度(以弧度为单位),所以我评估了event.accuracy

for (SensorEvent e : currentEvent) 
    if (e != null) 
        String toMsg = "";
        for(int i = 0; i < e.values.length;i++) 
            toMsg += " " + String.valueOf(e.values[i]);
        
        iBinder.msgString(String.valueOf(e.timestamp) + " "+String.valueOf(e.sensor.getType()) + " " + String.valueOf(e.accuracy) + toMsg, 0);
    

将这些方程式放入代码中,您就会得到排序。 这是一个简短的转换助手,用于转换 Quats。使用 XYZ 或 ZYX。它可以从 shell github 运行。 (BSD 许可) XYZ的相关部分

/*quaternation to euler in XYZ (seq:123)*/
double* quat2eulerxyz(double* q) 
  /*euler-angles*/
  double psi = atan2( -2.*(q[2]*q[3] - q[0]*q[1]) , q[0]*q[0] - q[1]*q[1]- q[2]*q[2] + q[3]*q[3] ); 
  double theta = asin( 2.*(q[1]*q[3] + q[0]*q[2]) );
  double phi = atan2( 2.*(-q[1]*q[2] + q[0]*q[3]) , q[0]*q[0] + q[1]*q[1] - q[2]*q[2] - q[3]*q[3] );   
  /*save var. by simply pushing them back into the array and return*/
  q[1] = psi; 
  q[2] = theta;
  q[3] = phi;
  return q;

以下是一些将 quats 应用于 euls 的示例:

**问:** 序列 ijk 代表什么? 取两个相互重叠的坐标系 A 和 B(所有轴都在彼此内)并开始通过角度为 `psi` 的 i 轴旋转坐标系 B,然后通过角度为 `theta` 的 j 轴和最后一个 z 轴有`phi`。对于 i、j、k,它也可以是 α、β、γ。 *我没有选择这些数字,因为它们令人困惑(Diebel 与其他论文)。*
R(psi,theta,phi) = R_z(phi)R_y(theta)R_x(psi) (<--)

诀窍是从右到左应用基本旋转,尽管我们从左到右读取序列。 这就是你要经历的三个基本轮换

A to B: *v_B = R(psi,theta,phi) v_A*
**Q:** 那么如何让欧拉角/quats 从 [0°,0°,0°] 转向例如。 [0°,90°,0°]?首先将图片中的两个帧对齐,分别将已知的设备帧 B 与“不可见”的世界帧 A 对齐。当角度都达到 [0°,0 时,您就完成了叠加°,0°]。只需弄清楚你现在坐的北、南和东在哪里,然后将设备框架 B 指向这些方向。现在,当您围绕 y 轴逆时针旋转 90° 时,您将在转换四元数时获得所需的 [0°,90°,0°]。 *朱利安* *运动学来源:[Source Diebel(Stanford)][11] 提供有关力学背景的可靠信息(注意:Diebel XYZ 表示为 u_321 (1,2,3) 而 ZYX 表示为 u_123 (3,2,1)), [this][12] 是一个很好的起点。

【讨论】:

你能看看这个答案吗? ***.com/questions/34997669/…

以上是关于如何从旋转向量中获取欧拉角(Sensor.TYPE_ROTATION_VECTOR)的主要内容,如果未能解决你的问题,请参考以下文章

旋转矩阵旋转向量欧拉角四元数的关系

unity3d 欧拉角怎么转换为方向向量

欧拉角的详解

3D计算机图形学变换矩阵欧拉角四元数

VR-四元素、欧拉角转换条件

3D计算机图形学变换矩阵欧拉角四元数