我嘗試使用來自SensorEvent.values的Z軸數據,但它未檢測到我的手機在XY平面中的旋轉,即,圍繞Z軸。如何使用Android中的加速度計測量手機在XY平面中的傾斜度
我用這個作爲座標軸的參考。這是對的嗎?
我如何衡量運動使用加速計值?
這些遊戲做類似的事情:Extreme Skater,塗鴉跳躍。
PS:我的手機方向將是風景。
我嘗試使用來自SensorEvent.values的Z軸數據,但它未檢測到我的手機在XY平面中的旋轉,即,圍繞Z軸。如何使用Android中的加速度計測量手機在XY平面中的傾斜度
我用這個作爲座標軸的參考。這是對的嗎?
我如何衡量運動使用加速計值?
這些遊戲做類似的事情:Extreme Skater,塗鴉跳躍。
PS:我的手機方向將是風景。
本質上,這裏有兩種情況:設備平放而不平整。這裏的平面意味着設備屏幕表面與世界xy平面之間的角度(我稱之爲傾角)小於25度或大於155度。想想手機平躺或從桌面上稍微傾斜一點。
首先你需要規範化加速度計矢量。
也就是說,如果g是由加速度傳感器事件值返回的矢量。在代碼
float[] g = new float[3];
g = event.values.clone();
double norm_Of_g = Math.sqrt(g[0] * g[0] + g[1] * g[1] + g[2] * g[2]);
// Normalize the accelerometer vector
g[0] = g[0]/norm_Of_g
g[1] = g[1]/norm_Of_g
g[2] = g[2]/norm_Of_g
然後傾斜可以被計算爲
int inclination = (int) Math.round(Math.toDegrees(Math.acos(g[2])));
因此
if (inclination < 25 || inclination > 155)
{
// device is flat
}
else
{
// device is not flat
}
敷設在平的情況下,必須使用一個指南針看到多少設備從起始位置旋轉。
對於不平坦的情況下,旋轉(傾斜)被計算爲遵循
int rotation = (int) Math.round(Math.toDegrees(Math.atan2(g[0], g[1])));
現在旋轉= 0表示該裝置處於正常位置。這是對大多數手機沒有任何傾斜的畫像,也可能是平板電腦的風景。因此,如果按上圖所示持有手機並開始旋轉,則旋轉會發生變化,手機處於橫向時,旋轉角度將爲90°或-90,具體取決於旋轉方向。
這款加速度計足以檢查手機是否平坦,因爲還原效果非常好。
對於任何到這裏的人來說,不僅要檢查手機是否平坦,而且手機的旋轉是什麼,可以通過Rotation Vector Motion Sensor來實現。
private double pitch, tilt, azimuth;
@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);
pitch = Math.atan2(sinP, cosP) * (180/Math.PI);
//Calculate Tilt in degrees (-90 to 90)
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);
azimuth = Math.atan2(sinA, cosA) * (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;
}
那就要檢查一下,如果手機是平的,你可以簡單地用一個公差值比較tilt
和pitch
值。例如
public boolean flatEnough(double degreeTolerance) {
return tilt <= degreeTolerance && tilt >= -degreeTolerance && pitch <= degreeTolerance && pitch >= -degreeTolerance;
}
這樣做的好處是您可以檢查手機是否處於任何特定的旋轉狀態。
值得注意的是,應用的方向不會影響音高,傾斜度和方位角的值。
太棒了!通常人們建議使用Sensor.TYPE_MAGNETIC_FIELD來完成此任務,但是您簡化了解決方案;順便提一下,加速計是保證在Android上出現的唯一傳感器。 – southerton
我可以問你「acc矢量的標準化?」的數學是什麼?你爲什麼要做atan(g [1]/g [0])(或atan(y/x))來獲得度數? ? @Hoan Nguyen –
@AndreaBaccega我忘了我爲什麼需要規範化或根本沒有需要,只是我需要爲其他事情做些事情。 atan(y/x)只是簡單的三角計算。要找到旋轉,首先需要將重力投影到xy平面。現在,如果沒有旋轉,則此投影向量將具有座標(0,1)(假設歸一化)。如果設備旋轉,該矢量是相同的,但座標變化,此矢量與設備y座標之間的角度僅爲tan(y/x)。 –