如何使用Android中的加速度计测量手机在XY平面中的倾斜度

时间:2012-06-24 07:04:21

标签: android accelerometer plane tilt

我尝试使用来自SensorEvent.values的Z轴数据,但它没有检测到我的手机在XY平面上的旋转,即。围绕Z轴。

我用这个作为坐标轴的参考。这是对的吗?

axes

如何使用加速度计值测量该运动?

这些游戏做类似的事情:Extreme Skater,Doodle Jump。

PS:我的手机定位将是风景。

3 个答案:

答案 0 :(得分:62)

基本上,这里有2种情况:设备平放而不平坦。这里平坦意味着设备屏幕的表面与世界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取决于旋转方向。

答案 1 :(得分:3)

加速度计足以检查手机是否平坦,因为Hoan非常好地展示了。

对于到达这里的人来说,不仅要检查手机是否平放,还要检查手机的旋转情况,还可以通过Rotation Vector Motion Sensor来实现。

Mivel  két  igazság  sose  mondhat  ellent  egymásnak,  a  Szentírás  bölcs  értelmezőinek  a  feladata,  hogy  megtalálják  a  szöveg  azon  értelmezését,  ami  egyezik  azokkal  a  fizikai  következtetésekkel,  melyekben  már  biztosak  vagyunk  érzéki  tapasztalataink  és  a  szükséges  kísérletek  által.

然后,要检查手机是否持平,您只需将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

这样做的好处是你可以检查手机是否被保持在任何特定的轮换状态。

值得注意的是,应用程序的方向不会影响俯仰,倾斜和方位角的值。

答案 2 :(得分:2)

努力摆脱@Dan的完美回应

他错过了@ davy307指出的一小部分信息。

初始化加速度计时,必须将其定义为 Sensor.TYPE_ROTATION_VECTOR ,否则它将不具有第3个旋转向量,并抛出ArrayIndexOutOfBounds异常。

mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);

否则,这是一个完美的解决方案……感激!