如何从旋转向量中获取欧拉角(Sensor.TYPE_ROTATION_VECTOR) [英] How to get the euler-angles from the rotation vector (Sensor.TYPE_ROTATION_VECTOR)

查看:201
本文介绍了如何从旋转向量中获取欧拉角(Sensor.TYPE_ROTATION_VECTOR)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

它们是无单位的,逆时针为正.

<块引用>

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

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

<块引用>

旋转向量的三个元素等于unit四元数的最后三个分量 <cos(θ/2), xsin(θ/2), ysin(θ/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 是冗余信息(也是
设置方程 ||q||= 1 并求解 q0.现在所有 q0-3 都是已知的.
此外,我的 android 4.4.2 在 value[4] 内没有第四个估计的标题精度(以弧度为单位),所以我评估 event.accuracy:

for (SensorEvent e : currentEvent) {如果(e!= null){字符串 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



**问:** 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 到 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] 是一个很好的起点.

I rotated my android device in x direction (from -180 degree to 180 degree), see image below.
And I assume only Rotation vector x value is changed. Y and z maybe have some noise, but it should be not much difference among the values.

However, I receive this. Kindly see

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

I suspect my sensor has some problem.

Any idea? Thank you very much.

Jimmy

解决方案

Your sensor is fine.
Well, the rotation vector entries cannot simply be related to the rotation angle around a particular axis. The SensorEvent structure constitutes of timestamp, sensor, accuracy and values. Depending on the vector the float[] of values vary in size 1-5.
The rotation vectors values are based on unit quaternions, all together forming a vector representing the orientation of this world frame relative to your smartphone fixed frame above They are unitless and positive counter-clockwise.

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).

If the vector would be a Rotation-Matrix one could write it as
v_body = R_rot_vec * v_world (<--)
pushing the world vector into a smartphone fixed description.
Furthermore about the vector:

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)>.

Q: So what to do with it?
Depending on your Euler-angles convention (possible 24 sequences, valid 12 ones) you could calculate the corresponding angles u := [ψ,θ,φ] by e.g. applying
the 123 sequence:

If you already have the rotation matrix entries get euler like so:

the 321 sequence:

with q1-3 always being the values[0-2] (Dont get confused by u_ijk as ref(Diebel) uses different conventions comp. to the standard)

But wait, your linked table only does have 3 values, which is similar to what I get. This is oneSensorEvent of mine, the last three are printed from values[]

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

4q - 3 values = 1q unknown. The first q0 is redundant info (also the
Set the equation ||q|| = 1 and solve for q0. Now all q0-3 are known.
Furthermore my android 4.4.2 does not have the fourth estimated heading Accuracy (in radians) inside value[4], so I evaluate the 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);
    }
}

Put those equations into code and you will get things sorted.

Here is a short conversion helper, converting Quats. using either XYZ or ZYX. It can be run from shell github. (BSD-licensed)
The relevant part for 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;
}

Here some examples applying quats to euls:



**Q:** What do the sequence ijk stand for?
Take two coordinate-frames A and B superposing each other(all axis within each other) and start rotating frame B through i-axis having angle `psi`, then j-axis having angle `theta` and last z-axis having `phi`. It could also be α, β, γ for i,j,k. *I don't pick up the numbers as they are confusing (Diebel vs other papers).*

R(psi,theta,phi) = R_z(phi)R_y(theta)R_x(psi) (<--)

The trick is elementary rotations are applied from right to left, although we read the sequence from left to right. Those are the three elementary rotations youre going through to go from

A to B: *v_B = R(psi,theta,phi) v_A*



**Q:** So how to get the euler angles/quats turn from [0°,0°,0°] to eg. [0°,90°,0°]?
First align both frames from the pictures, respective the known device frame B to the "invisible" worldframe A. Your done superposing when the angles all get to [0°,0°,0°]. Just figure out where is north, south and east where you are sitting right now and point the devices frame B into those directions. Now when you rotate around y-axis counter-clockwise 90° you will have the desired [0°,90°,0°], when converting the quaternion.
*Julian*

*kinematics source: [Source Diebel(Stanford)][11] with solid info on the mechanics background (careful: for Diebel XYZ is denoted u_321 (1,2,3) while ZYX is u_123 (3,2,1)), and [this][12] is a good starting point.

这篇关于如何从旋转向量中获取欧拉角(Sensor.TYPE_ROTATION_VECTOR)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆