假设您有所有 3 个维度的加速度读数,即 X、Y 和 Z。您如何使用手机向左或向右倾斜的读数推断?读数每 20 毫秒生成一次。
我实际上想要从读数中推断倾斜的逻辑。倾斜需要平滑。
假设您有所有 3 个维度的加速度读数,即 X、Y 和 Z。您如何使用手机向左或向右倾斜的读数推断?读数每 20 毫秒生成一次。
我实际上想要从读数中推断倾斜的逻辑。倾斜需要平滑。
可以以不同的方式检测倾斜。您可以考虑 1 轴、2 轴或 3 轴。取决于你想要它的准确程度,以及你对数学打架的感觉。
如果你只使用一个轴,那就很简单了。认为手机是完全水平的,然后像这样移动它:
只使用一个轴,比如说轴 x 就足够了,因为您可以准确地检测到该轴位置的变化,因为即使是任何微小的运动都会对轴产生变化。但是,如果您的应用程序只读取该轴,并且用户的手机几乎是垂直的,那么即使将手机旋转一个很大的角度,x 轴的差异也会非常小。无论如何,对于只需要粗分辨率的应用,可以使用单轴。
参考基本三角学,重力矢量在 x 轴上的投影产生的输出加速度等于加速度计 x 轴与地平线之间夹角的正弦值。这意味着有了轴的值(这些是加速度值),您可以计算设备所在的角度。
这意味着传感器给您的值是 = 到 9,8 * 角度的正弦值,因此通过数学运算可以得到实际角度。
但别担心,你甚至不必这样做。由于这些值或多或少是成比例的,如下表所示,您可以直接使用传感器的值,而不必太在意角度代表什么,如果您不需要它非常准确,由于该值的变化意味着角度的比例变化,因此通过一些测试,您会发现变化应该有多大才能与您相关。
所以,如果你在一段时间内取值,并相互比较,你可以算出旋转有多大。为了这,
我希望这对你来说已经足够好了。当然,您可以找到一些库或代码片段来帮助您解决这个问题,但我认为,正如您所说,了解从读数中推断倾斜的逻辑是件好事
图片取自本文,如果您想提高精度并考虑倾斜 2 o 3 轴,我建议您阅读。
commonsware Sensor Monitor 应用程序在这方面做得很好。它将传感器读数转换为每个传感器读数的 X、Y、Z 值,因此很容易从那里确定设备的移动方式。
https://github.com/commonsguy/cw-omnibus/tree/master/Sensor/Monitor
另一个值得注意的项目(来自Commonsware book):
有四个标准延迟周期,在 SensorManager 类中定义为常量:
- SENSOR_DELAY_NORMAL,这是大多数应用程序用于广泛更改的方法,例如检测屏幕从纵向旋转到横向
- SENSOR_DELAY_UI,适用于您希望根据传感器读数持续更新 UI 的非游戏情况
- SENSOR_DELAY_GAME,比 SENSOR_DELAY_UI 更快(延迟更少),以尝试驱动更高的帧速率
- SENSOR_DELAY_FASTEST,它是传感器读数的“消防软管”,没有延迟
您可以使用加速度计和磁场传感器来完成此操作。您可以在 OnSensorChanged 方法中调用此方法来检测手机是否向上倾斜。这目前仅适用于水平握持手机的情况。查看实际的博客文章以获得更完整的解决方案。
http://www.ahotbrew.com/how-to-detect-forward-and-backward-tilt/
public boolean isTiltUpward()
{
if (mGravity != null && mGeomagnetic != null)
{
float R[] = new float[9];
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
if (success)
{
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
/*
* If the roll is positive, you're in reverse landscape (landscape right), and if the roll is negative you're in landscape (landscape left)
*
* Similarly, you can use the pitch to differentiate between portrait and reverse portrait.
* If the pitch is positive, you're in reverse portrait, and if the pitch is negative you're in portrait.
*
* orientation -> azimut, pitch and roll
*
*
*/
pitch = orientation[1];
roll = orientation[2];
inclineGravity = mGravity.clone();
double norm_Of_g = Math.sqrt(inclineGravity[0] * inclineGravity[0] + inclineGravity[1] * inclineGravity[1] + inclineGravity[2] * inclineGravity[2]);
// Normalize the accelerometer vector
inclineGravity[0] = (float) (inclineGravity[0] / norm_Of_g);
inclineGravity[1] = (float) (inclineGravity[1] / norm_Of_g);
inclineGravity[2] = (float) (inclineGravity[2] / norm_Of_g);
//Checks if device is flat on ground or not
int inclination = (int) Math.round(Math.toDegrees(Math.acos(inclineGravity[2])));
/*
* Float obj1 = new Float("10.2");
* Float obj2 = new Float("10.20");
* int retval = obj1.compareTo(obj2);
*
* if(retval > 0) {
* System.out.println("obj1 is greater than obj2");
* }
* else if(retval < 0) {
* System.out.println("obj1 is less than obj2");
* }
* else {
* System.out.println("obj1 is equal to obj2");
* }
*/
Float objPitch = new Float(pitch);
Float objZero = new Float(0.0);
Float objZeroPointTwo = new Float(0.2);
Float objZeroPointTwoNegative = new Float(-0.2);
int objPitchZeroResult = objPitch.compareTo(objZero);
int objPitchZeroPointTwoResult = objZeroPointTwo.compareTo(objPitch);
int objPitchZeroPointTwoNegativeResult = objPitch.compareTo(objZeroPointTwoNegative);
if (roll < 0 && ((objPitchZeroResult > 0 && objPitchZeroPointTwoResult > 0) || (objPitchZeroResult < 0 && objPitchZeroPointTwoNegativeResult > 0)) && (inclination > 30 && inclination < 40))
{
return true;
}
else
{
return false;
}
}
}
return false;
}
这是你要找的吗?
public class AccelerometerHandler implements SensorEventListener
{
float accelX;
float accelY;
float accelZ;
public AccelerometerHandler(Context paramContext)
{
SensorManager localSensorManager = (SensorManager)paramContext.getSystemService("sensor");
if (localSensorManager.getSensorList(1).size() != 0)
localSensorManager.registerListener(this, (Sensor)localSensorManager.getSensorList(1).get(0), 1);
}
public float getAccelX()
{
return this.accelX;
}
public float getAccelY()
{
return this.accelY;
}
public float getAccelZ()
{
return this.accelZ;
}
public void onAccuracyChanged(Sensor paramSensor, int paramInt)
{
}
public void onSensorChanged(SensorEvent paramSensorEvent)
{
this.accelX = paramSensorEvent.values[0];
this.accelY = paramSensorEvent.values[1];
this.accelZ = paramSensorEvent.values[2];
}
}