假设您在所有3个维度(即X,Y和Z)中都有加速度读数。您如何使用读数来推断手机是向左还是向右倾斜?读数每20ms生成一次。
我实际上想要从读数推断出倾斜的逻辑。倾斜需要平稳。
答案 0 :(得分:21)
可以通过某种不同的方式检测倾斜。您可以考虑1轴,2轴或3轴。取决于你想要它的准确程度,以及你对数学战斗的感觉。
如果只使用一个轴,则非常简单。认为手机是完全水平的,你可以这样移动:
只使用一个轴,比如x轴,就足够了,因为你可以准确地检测到该轴位置的变化,因为即使是任何小的运动都会对轴进行改变。 但是,如果您的应用程序仅读取该轴,并且用户使手机几乎垂直,那么即使将手机旋转大角度,x轴的差异也会非常小。 无论如何,对于只需要粗分辨率的应用,可以使用单轴。
参考基本三角学,重力矢量在x轴上的投影产生的输出加速度等于加速度计x轴和地平线之间角度的正弦。 这意味着具有轴的值(这些是加速度值),您可以计算设备的角度。
这意味着传感器给你的值是=到角度的9,8 *正弦,所以做数学就可以得到实际的角度。
但不要担心,你甚至不必这样做。由于这些值或多或少是成比例的,如下表所示,您可以直接使用传感器的值,而不必过多关注角度代表什么,如果您不需要它准确得多,因为该值的变化意味着角度的比例变化,所以通过一些测试,您将发现变化应该有多大才能与您相关。
因此,如果你在一段时间内取值并相互比较,你就可以计算出旋转的大小。为此,
我希望这对你来说已经足够了。当然,您可以找到一些库或代码片段来帮助您解决这个问题,但我认为,如果您知道从读数中推断出倾斜的逻辑,我认为这很好
这些照片是从this article拍摄的,如果你想提高精度并考虑2 o 3轴的倾斜,我建议您阅读
答案 1 :(得分:0)
commonsware传感器监视器应用程序做得非常好。它将传感器读数转换为每个传感器读数上的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,这是传感器读数的“消防”,没有延迟
醇>
答案 2 :(得分:0)
您可以使用加速度计和磁场传感器来完成此任务。您可以在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;
}
答案 3 :(得分:-1)
这是你要找的吗?
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];
}
}