【问题标题】:How can I get the direction of movement using an accelerometer?如何使用加速度计获得运动方向?
【发布时间】:2012-05-15 15:19:55
【问题描述】:

我正在开发一个 Android 应用程序,我想知道是否可以在固定一个轴的情况下检测运动方向。例如,我想将手机放在桌子上并在移动时检测方向(左、右、上、下)。距离不是必须的,我只想知道准确的方向。

【问题讨论】:

标签: android physics accelerometer direction


【解决方案1】:

是的。

使用SensorEventListener.onSensorChanged(SensorEvent event),您可以确定沿 X 和 Y 轴提供的值。您需要记录这些值,然后将它们与您在后续调用 onSensorChanged 方法时收到的任何新值进行比较,以获得增量值。如果一个轴上的 delta 值为正,则设备向一侧移动,如果其为负,则向相反方向移动。

您可能需要微调接收加速度计事件的速率和您认为 delta 值指示方向变化的阈值。

这是我正在谈论的快速代码示例:

public class AccelerometerExample extends Activity implements SensorEventListener {
    TextView textView;
    StringBuilder builder = new StringBuilder();

    float [] history = new float[2];
    String [] direction = {"NONE","NONE"};

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        textView = new TextView(this);
        setContentView(textView);

        SensorManager manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        Sensor accelerometer = manager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
        manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {

        float xChange = history[0] - event.values[0];
        float yChange = history[1] - event.values[1];

        history[0] = event.values[0];
        history[1] = event.values[1];

        if (xChange > 2){
          direction[0] = "LEFT";
        }
        else if (xChange < -2){
          direction[0] = "RIGHT";
        }

        if (yChange > 2){
          direction[1] = "DOWN";
        }
        else if (yChange < -2){
          direction[1] = "UP";
        }

        builder.setLength(0);
        builder.append("x: ");
        builder.append(direction[0]);
        builder.append(" y: ");
        builder.append(direction[1]);

        textView.setText(builder.toString());
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // nothing to do here
    }
}

此代码只会为您提供手机移动的 X 轴和 Y 轴上的大致方向。要提供更精细的方向确定(例如,尝试模拟计算机鼠标的移动),您可以发现手机的加速度计不适合用途。

为了尝试这个,我首先将传感器延迟设置为SensorManager.SENSOR_DELAY_FAST,并创建一个包含多个历史事件的列表,这样我就可以随着时间的推移检测运动,而不会受到拍摄时经常发生的相反方向的轻微运动的影响加速度计测量如此精细。您还需要测量经过的时间量,以帮助计算您的 cmets 中建议的准确运动测量值。

【讨论】:

  • 劳斯你好!感谢您的回复。我已经测试过类似的代码,问题是手机移动时的变化。由于我需要准确性,我使用大约 0.3 的“xChange”。即使从左到右的运动是“恒定的”,该值也会发生多次变化。分析加速度计的值,我意识到有时在运动之后,加速度计会产生相反方向的等效值并导致变化。我至少需要以类似于老式鼠标(带球体)的精度来获得方向。你有什么建议吗?
  • 欢迎马科斯。您应该更新您的问题,因为试图让您的手机像鼠标一样工作与检测方向不同。我不确定加速度计是为您想做的事情而设计的。当它测量加速度时,您可能无法实现所需的细粒度运动检测。
  • 我已更新我的答案以考虑您的 cmets。请更新您的问题并考虑接受此答案。
  • @Louth 你能看一下这个question吗?
  • 我应该使用哪些传感器来模拟鼠标在所需平面坐标上的移动(dx、dy)。我试过加速度计,但运动与手机旋转有关,而不是手机在飞机上的运动
【解决方案2】:

据我了解,使用传感器只能检测加速度和手机方向。所以你可以很容易地检测到运动的开始(以及在哪个方向)和运动的停止,因为速度在变化,所以有加速度(当停止加速度时与速度方向相反)。

如果手机以恒定速度移动,加速度计将给出零值(减去重力的线性加速度)。因此,为了知道手机是否在移动,您应该计算每个瞬间的速度,通过

V(t)=V(t-1)+a*dt

其中:

  • V(t-1) 是前一时刻的已知速度,
  • V(t) 是当前时刻的速度,
  • a 是加速度(考虑前一瞬间的加速度或 前一时刻和当前时刻之间的平均加速度)。

问题在于,由于传感器值的不确定性,您最终可能会在每个瞬间汇总小误差,这将导致错误的速度值。可能您必须将低通滤波器调整为这些值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多