参考下面的代码,我从Game_Rotation_Vector传感器事件中得到4个数字,我想要实现的是获得手机的轴角旋转。
例如。如果我逆时针旋转手机屏幕90度,我想从传感器数据中获得实际值90deg。
任何人都可以提供将4个游戏旋转矢量值转换为3个轴角度值的代码吗?
答案 0 :(得分:0)
将值放入单位四元数like so:
sensors_event_t.data[0] = rot_axis.x*sin(theta/2);
sensors_event_t.data[1] = rot_axis.y*sin(theta/2);
sensors_event_t.data[2] = rot_axis.z*sin(theta/2);
sensors_event_t.data[3] = cos(theta/2)
所以反过来就是:
double theta = Math.acos(vals[3])*2;
double sinv = Math.sin(theta/2);
double xa = vals[0]/sinv;
double ya = vals[1]/sinv;
double za = vals[2]/sinv;
但 xa,xy和xz不是角度,它们是轴的坐标,如文档中所述。我不确定你想要的是什么,你可能最好直接用单位四元数来实现你未说明的目标。
使用unit quaternion的原因是为了避免gimble lock,基本上你不能用三个角度,滚动/俯仰/偏航来描述每个可能的旋转,例如在一定的俯仰角和偏航角你可能会失去滚动的能力。
因此,使用此方法的一种方法是转换为旋转矩阵:
if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
// convert the rotation-vector to a 4x4 matrix. the matrix
// is interpreted by Open GL as the inverse of the
// rotation-vector, which is what we want.
SensorManager.getRotationMatrixFromVector(
mRotationMatrix , event.values);
}
答案 1 :(得分:0)
所以我们知道旋转矢量数据是一个单位四元数。
幸运的是,维基百科上有一个关于四元数转换的页面。
https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
提供了两个例子。一个用C ++编写,一个用Python编写。我会在这里添加它们。
C ++:
static void toEulerAngle(const Quaterniond& q, double& roll, double& pitch, double& yaw)
{
// roll (x-axis rotation)
double sinr = +2.0 * (q.w() * q.x() + q.y() * q.z());
double cosr = +1.0 - 2.0 * (q.x() * q.x() + q.y() * q.y());
roll = atan2(sinr, cosr);
// pitch (y-axis rotation)
double sinp = +2.0 * (q.w() * q.y() - q.z() * q.x());
if (fabs(sinp) >= 1)
pitch = copysign(M_PI / 2, sinp); // use 90 degrees if out of range
else
pitch = asin(sinp);
// yaw (z-axis rotation)
double siny = +2.0 * (q.w() * q.z() + q.x() * q.y());
double cosy = +1.0 - 2.0 * (q.y() * q.y() + q.z() * q.z());
yaw = atan2(siny, cosy);
}
的Python:
import math
def quaternion_to_euler_angle(w, x, y, z):
ysqr = y * y
t0 = +2.0 * (w * x + y * z)
t1 = +1.0 - 2.0 * (x * x + ysqr)
X = math.degrees(math.atan2(t0, t1))
t2 = +2.0 * (w * y - z * x)
t2 = +1.0 if t2 > +1.0 else t2
t2 = -1.0 if t2 < -1.0 else t2
Y = math.degrees(math.asin(t2))
t3 = +2.0 * (w * z + x * y)
t4 = +1.0 - 2.0 * (ysqr + z * z)
Z = math.degrees(math.atan2(t3, t4))
return X, Y, Z
请注意,在Android的单位四元数中,旋转矢量的标量分量是最后一个变量(四个中的变量)。在这些代码片段中,它是第一个变量。
我希望这有帮助!