旋转矢量传感器值到方位角、横滚和俯仰
Rotation Vector Sensor Values to Azimuth, Roll, and Pitch
我正在尝试将使用旋转矢量传感器类型返回的 5 个值转换为滚动、方位角和俯仰角。
我使用的代码如下。
@Override
public void onSensorChanged(SensorEvent event) {
double[] g = convertFloatsToDoubles(event.values.clone());
double norm = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2] + g[3] * g[3]);
g[0] /= norm;
g[1] /= norm;
g[2] /= norm;
g[3] /= norm;
double xAng = (2 * Math.acos(g[0])) * (180 / Math.PI);
double yAng = (2 * Math.acos(g[1])) * (180 / Math.PI);
double zAng = (2 * Math.acos(g[2])) * (180 / Math.PI);
}
private double[] convertFloatsToDoubles(float[] input)
{
if (input == null)
return null;
double[] output = new double[input.length];
for (int i = 0; i < input.length; i++)
output[i] = input[i];
return output;
}
问题是变量 xAng
和 yAng
返回的值似乎限制在 80 - 280 之间。
至于 zAng
(我认为是方位角),它像指南针一样工作,但当它 returns 0 时,它似乎偏离磁南约 12 度。
我假设我在使用的数学上做错了,但我不确定到底是什么。
Sensor.TYPE_ROTATION_VECTOR
的值定义为 here 为:
values[0]: x*sin(θ/2)
values[1]: y*sin(θ/2)
values[2]: z*sin(θ/2)
values[3]: cos(θ/2)
values[4]: estimated heading Accuracy (in radians) (-1 if unavailable)
以防它能帮助任何想要完成相同任务的人。数学处理完全错误。
以下 onSensorChanged
已更新,因此 returns 以度为单位的正确值。
@Override
public void onSensorChanged(SensorEvent event) {
//Get Rotation Vector Sensor Values
double[] g = convertFloatsToDoubles(event.values.clone());
//Normalise
double norm = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2] + g[3] * g[3]);
g[0] /= norm;
g[1] /= norm;
g[2] /= norm;
g[3] /= norm;
//Set values to commonly known quaternion letter representatives
double x = g[0];
double y = g[1];
double z = g[2];
double w = g[3];
//Calculate Pitch in degrees (-180 to 180)
double sinP = 2.0 * (w * x + y * z);
double cosP = 1.0 - 2.0 * (x * x + y * y);
double pitch = Math.atan2(sinP, cosP) * (180 / Math.PI);
//Calculate Tilt in degrees (-90 to 90)
double tilt;
double sinT = 2.0 * (w * y - z * x);
if (Math.abs(sinT) >= 1)
tilt = Math.copySign(Math.PI / 2, sinT) * (180 / Math.PI);
else
tilt = Math.asin(sinT) * (180 / Math.PI);
//Calculate Azimuth in degrees (0 to 360; 0 = North, 90 = East, 180 = South, 270 = West)
double sinA = 2.0 * (w * z + x * y);
double cosA = 1.0 - 2.0 * (y * y + z * z);
double azimuth = Math.atan2(sinA, cosA) * (180 / Math.PI);
}
我正在尝试将使用旋转矢量传感器类型返回的 5 个值转换为滚动、方位角和俯仰角。
我使用的代码如下。
@Override
public void onSensorChanged(SensorEvent event) {
double[] g = convertFloatsToDoubles(event.values.clone());
double norm = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2] + g[3] * g[3]);
g[0] /= norm;
g[1] /= norm;
g[2] /= norm;
g[3] /= norm;
double xAng = (2 * Math.acos(g[0])) * (180 / Math.PI);
double yAng = (2 * Math.acos(g[1])) * (180 / Math.PI);
double zAng = (2 * Math.acos(g[2])) * (180 / Math.PI);
}
private double[] convertFloatsToDoubles(float[] input)
{
if (input == null)
return null;
double[] output = new double[input.length];
for (int i = 0; i < input.length; i++)
output[i] = input[i];
return output;
}
问题是变量 xAng
和 yAng
返回的值似乎限制在 80 - 280 之间。
至于 zAng
(我认为是方位角),它像指南针一样工作,但当它 returns 0 时,它似乎偏离磁南约 12 度。
我假设我在使用的数学上做错了,但我不确定到底是什么。
Sensor.TYPE_ROTATION_VECTOR
的值定义为 here 为:
values[0]: x*sin(θ/2)
values[1]: y*sin(θ/2)
values[2]: z*sin(θ/2)
values[3]: cos(θ/2)
values[4]: estimated heading Accuracy (in radians) (-1 if unavailable)
以防它能帮助任何想要完成相同任务的人。数学处理完全错误。
以下 onSensorChanged
已更新,因此 returns 以度为单位的正确值。
@Override
public void onSensorChanged(SensorEvent event) {
//Get Rotation Vector Sensor Values
double[] g = convertFloatsToDoubles(event.values.clone());
//Normalise
double norm = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2] + g[3] * g[3]);
g[0] /= norm;
g[1] /= norm;
g[2] /= norm;
g[3] /= norm;
//Set values to commonly known quaternion letter representatives
double x = g[0];
double y = g[1];
double z = g[2];
double w = g[3];
//Calculate Pitch in degrees (-180 to 180)
double sinP = 2.0 * (w * x + y * z);
double cosP = 1.0 - 2.0 * (x * x + y * y);
double pitch = Math.atan2(sinP, cosP) * (180 / Math.PI);
//Calculate Tilt in degrees (-90 to 90)
double tilt;
double sinT = 2.0 * (w * y - z * x);
if (Math.abs(sinT) >= 1)
tilt = Math.copySign(Math.PI / 2, sinT) * (180 / Math.PI);
else
tilt = Math.asin(sinT) * (180 / Math.PI);
//Calculate Azimuth in degrees (0 to 360; 0 = North, 90 = East, 180 = South, 270 = West)
double sinA = 2.0 * (w * z + x * y);
double cosA = 1.0 - 2.0 * (y * y + z * z);
double azimuth = Math.atan2(sinA, cosA) * (180 / Math.PI);
}