Я разрабатываю приложение для Android, и я хотел бы знать, возможно ли определить направление движения с одной фиксированной осью. Например, я хочу положить свой телефон на стол и определить направление, когда я его двигаю (влево, вправо, вверх и вниз). Расстояние не обязательно, я просто хочу знать точное направление.
Как узнать направление движения с помощью акселерометра?
Ответы (2)
да.
Используя 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
и создал список нескольких событий истории, чтобы я мог обнаруживать движение с течением времени и не подвергаться влиянию небольших движений в противоположном направлении, которые часто случаются при измерениях акселерометра при такой скорости. прекрасный уровень. Вам также нужно будет измерить количество прошедшего времени, чтобы помочь рассчитать точную меру движения, как это предлагается в ваших комментариях.
Из того, что я читал, с помощью датчиков можно определить только ускорение и ориентацию телефона. Таким образом, вы можете легко определить начало движения (и в каком направлении) и остановку движения, поскольку скорость меняется, поэтому есть ускорение (когда останавливающееся ускорение направлено против направления скорости).
Если телефон движется с постоянной скоростью, акселерометры будут давать нулевые значения (линейное ускорение, за вычетом силы тяжести). Таким образом, чтобы узнать, движется ли телефон, вы должны вычислить скорость в каждый момент времени с помощью
V(t)=V(t-1)+a*dt
в котором:
V(t-1)
— известная скорость в предыдущий момент,V(t)
- скорость в текущий момент,a
- это ускорение (учитывайте ускорение в предыдущий момент или среднее ускорение между предыдущим и текущим моментом).
Проблема в том, что из-за неопределенности значений датчиков вы можете суммировать небольшие ошибки в каждый момент времени, что приведет к ошибочным значениям скорости. Вероятно, вам придется настроить фильтр нижних частот на значения.