Как я могу получить направление движения с помощью акселерометра?

Я разрабатываю приложение для Android, и я хотел бы знать, возможно ли определить направление движения с одной фиксированной осью. Например, я хочу поместить мой телефон на стол и определить направление, когда я его перемещаю (влево, вправо, вверх и вниз). Расстояние не обязательно, я просто хочу знать точное направление.

Спасибо!

Ответы

Ответ 1

Да.

Используя 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 и создаст список из нескольких событий истории, чтобы я мог обнаруживать движение со временем и не подвергался влиянию небольших движений в противоположном направлении, которые часто возникают при принятии акселерометров на таком тонком уровне. Вам также необходимо будет измерить количество времени, которое прошло, чтобы подсчитать точную меру движения, как это предлагается в ваших комментариях.

Ответ 2

Из того, что я прочитал, с датчиками можно обнаружить только ускорения и ориентацию телефона. Таким образом, вы можете легко обнаружить начало движения (и в каком направлении) и остановку движения, так как скорость изменяется, поэтому происходит ускорение (когда остановка ускорения происходит против направления скорости).

Если телефон движется с постоянной скоростью, акселерометры будут давать нулевые значения (линейное ускорение, которое вычитает гравитацию). Поэтому, чтобы узнать, движется ли телефон, вы должны вычислить скорость в каждый момент времени,

V(t)=V(t0)+a*dt

в котором:

  • V(t0) - известная скорость в предыдущий момент,
  • V(t) - скорость в текущий момент времени,
  • a - ускорение (учитывайте ускорение в предыдущий момент или среднее ускорение между предыдущим и текущим моментом).

Проблема заключается в том, что из-за неопределенности значений датчиков вы можете в итоге суммировать небольшие ошибки в каждый момент времени, что приведет к ошибочным значениям скорости. Вероятно, вам придется настроить фильтр нижних частот на значения.