android - 如何从旋转矢量 (Sensor.TYPE_ROTATION_VECTOR) 获取欧拉角

标签 android rotation orientation quaternions gyroscope

我在 x 方向(从 -180 度到 180 度)旋转了我的 android 设备,请参见下图。 enter image description here
我假设只有旋转向量 x 值发生了变化。 Y 和 z 可能有一些噪音,但应该相差不大。

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

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

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

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

吉米

最佳答案

你的传感器没问题。
嗯,旋转矢量条目不能简单地与围绕特定轴的旋转角度相关。 SensorEvent结构由时间戳、传感器、精度和值组成。 values 的 float[] 取决于向量大小在 1-5 之间变化。
旋转向量值基于单位四元数,它们一起形成一个向量,表示这个世界坐标系相对于您上方智能手机固定坐标系的方向 enter image description here 它们无量纲且逆时针为正。

The orientation of the phone is represented by the rotation necessary to align the East-North-Up coordinates with the phone's coordinates. That is, applying the rotation to the world frame (X,Y,Z) would align them with the phone coordinates (x,y,z).

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

The three elements of the rotation vector are equal to the last three components of a unit quaternion <cos(θ/2), xsin(θ/2), ysin(θ/2), z*sin(θ/2)>.

问:那该怎么办呢?
根据您的欧拉角约定(可能的 24 个序列,有效的 12 个),您可以通过例如计算相应的角度 u := [ψ,θ,φ]应用
123 序列:
enter image description here
如果你已经有了旋转矩阵条目,像这样获取欧拉:
123 seq euler angles
321序列:
321 seq euler angles
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 级别)。所以我们可以使用范数(=长度)从其他三个计算出 q0。
unit-norm
设置方程||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 的示例: enter image description here



**问:**序列ijk代表什么?
将两个坐标系 A 和 B 相互叠加(所有轴都在彼此内)并开始旋转坐标系 B 通过具有角度 `psi` 的 i 轴,然后是具有角度 `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] 是一个很好的起点。

关于android - 如何从旋转矢量 (Sensor.TYPE_ROTATION_VECTOR) 获取欧拉角,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30279065/

相关文章:

android - Qt:链接到 FFmpeg 的 android 上对 atof、log2 和 log2f 的 undefined reference

用于旋转 3D 立方体的 Android 方向传感器

cocoa - NSView 内容的动画旋转

android - 旋转后 TextView 被剪切

ios - Dismiss 后父 UIViewController 不会改变方向

android 方向 - Intent 问题(相机)

android - 在 android 中向自定义图库 View 添加描述

android - 更新了 Android Google Maps V2 限制

android - packageAndLaunchActivityFromManifest 失败 appium 错误

css - 是否可以使背景从屏幕的左下角到右上角重复?