如何使用加速度计获取运动方向?

20

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


一些关于加速度计的帖子:http://www.anddev.org/advanced-tutorials-f21/accessing-the-accelerometer-t499.html#p1987 http://developer.android.com/reference/android/hardware/SensorEvent.html#values - Niko
2个回答

27

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

您可能需要微调加速度计事件接收速率和考虑指示方向改变的增量值的阈值。

这是一个简单的代码示例:

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,并创建一个多事件历史记录列表,以便我可以检测随时间变化的移动,并不受在进行如此细微级别的加速度计测量时发生的反方向轻微运动的影响。您还需要测量经过的时间来帮助计算准确的运动度量,就像评论中建议的那样。


你好Louth!感谢您的回复。我已经测试了类似的代码,问题在于手机移动时的变化。由于我需要准确性,所以我使用了一个“xChange”约为0.3。即使运动是从左到右的“恒定”的,值也会多次改变。通过分析加速度计的值,我意识到有时在运动后,加速度计会生成相反方向的等效值,这会导致变化。我需要获得与旧式鼠标(带球)至少相似的准确方向。您有什么建议吗? - Marcos Passos
欢迎Marcos。您应该更新您的问题,因为试图使您的手机像鼠标一样运行与检测方向不同。我不确定加速度计是否设计用于您想要做的那种事情。由于它测量加速度,您可能无法实现您所寻求的精细移动检测。 - Louth
我已经更新了我的答案以考虑您的评论。请更新您的问题并考虑接受此答案。 - Louth
@Louth,你可以看一下这个问题吗? - Skizo-ozᴉʞS ツ
我应该使用哪些传感器来模拟平面坐标上的鼠标移动(dx,dy)?我已经尝试了加速度计,但移动与手机旋转相关,而不是手机在平面上的移动。 - Michał Ziobro
@MichałZiobro 我认为最好使用TYPE_LINEAR_ACCELERATION传感器,因为它排除了重力的影响。 - Ehsan Shadi

1
根据我所了解的,使用传感器只能检测加速度和手机方向。因此,您可以轻松地检测运动的开始(以及方向)和停止,因为速度正在改变,所以有加速度(当停止时,加速度与速度方向相反)。
如果手机以恒定速度移动,则加速计将提供零值(线性加速度减去重力)。因此,为了知道手机是否在移动,您应该通过计算每个瞬间的速度来确定。
V(t)=V(t-1)+a*dt

其中:

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

问题在于由于传感器值的不确定性,您可能会在每个瞬间累加小误差,这将导致错误的速度值。可能需要将低通滤波器调整到这些值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接