Как найти скорость, используя только акселерометры?

Используя только телефон (Android), встроенный в акселерометр, как бы я мог найти его скорость?

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

У меня есть приличный фон в физике и в математике, поэтому у меня не должно быть никаких проблем с концепциями.

Как мне это сделать?

Ответ 1

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

Ответ 2

Это будет зависеть от того, что такое ускорение и как долго. Легкое, длительное ускорение может быть измеримым, но любое внезапное увеличение ускорения, за которым следует постоянная скорость, сделает ваши измерения довольно сложными и подвержен ошибкам.

Предполагая постоянное ускорение, формула чрезвычайно проста: a = (V1-V0)/t. Итак, зная время и ускорение и полагая V0 = 0, тогда V1 = a * t

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

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

Ответ 3

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

У меня была схожая проблема с твоей, и я решил сделать свое решение после того, как не нашел его в режиме онлайн. Мне нужен был простой "наклон" вход для управления игрой, чтобы это решение, вероятно, НЕ работало для более сложных задач, однако я решил поделиться им в случае, если другие ищут что-то подобное.

ПРИМЕЧАНИЕ: Здесь я вставлял весь свой код, и он может использоваться для любых целей.

В основном, что я делаю в своем коде, нужно искать датчик акселерометра. Если не найдено, отклон. Наклон будет отключен. Если присутствует датчик акселерометра, я ищу датчик магнитного поля, и если он присутствует, я получаю свой угол наклона рекомендуемым путем, комбинируя данные акселерометра и магнитного поля.

public TiltSensor(Context c) {
    man = (SensorManager) c.getSystemService(Context.SENSOR_SERVICE);
    mag_sensor = man.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    acc_sensor = man.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    has_mag = man.registerListener(this, mag_sensor, delay);
    has_acc = man.registerListener(this, acc_sensor, delay);
    if (has_acc) {
        tiltAvailble = true;
        if (has_mag) {
            Log.d("TiltCalc", "Using accelerometer + compass.");
        }
        else {
            Log.d("TiltCalc", "Using only accelerometer.");
        }
    }
    else {
        tiltAvailble = false;
        Log.d("TiltCalc", "No acceptable hardware found, tilt not available.");
        //No use in having listeners registered
        pause();
    }
}

Если бы присутствовал только датчик акселерометра, я возвращаюсь к накоплению ускорения, которое непрерывно затухает (умножается на 0,99), чтобы удалить любой дрейф. Для моих простых задач наклона это отлично работает.

@Override
public void onSensorChanged(SensorEvent e) {
    final float[] vals = e.values;
    final int type = e.sensor.getType();
    switch (type) {
        case (Sensor.TYPE_ACCELEROMETER): {
            needsRecalc = true;
            if (!has_mag) {
                System.arraycopy(accelerometer, 0, old_acc, 0, 3);
            }
            System.arraycopy(vals, 0, accelerometer, 0, 3);
            if (!has_mag) {
                for (int i = 0; i < 3; i++) {
                    //Accumulate changes
                    final float sensitivity = 0.08f;
                    dampened_acc[i] += (accelerometer[i] - old_acc[i]) * sensitivity;
                    //Even out drift over time
                    dampened_acc[i] *= 0.99;
                }
            }
        }
            break;
        case (Sensor.TYPE_MAGNETIC_FIELD): {
            needsRecalc = true;
            System.arraycopy(vals, 0, magnetic_field, 0, 3);
        }
            break;
    }
}

В заключение я просто повторю, что это, вероятно, не является "правильным", он просто работает как простой вход в игру. Чтобы использовать этот код, я просто делаю что-то вроде следующего (да, магические константы плохие mkay):

Ship ship = mShipLayer.getShip();
mTiltSensor.getTilt(vals);
float deltaY = -vals[1] * 2;//1 is the index of the axis we are after
float offset = ((deltaY - (deltaY / 1.5f)));
if (null != ship) {
    ship.setOffset(offset);
}

Enjoi!

Ответ 4

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

Ответ 5

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

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

Одним из полезных приложений может быть использование акселерометров в сочетании с гироскопами или магнитным компасом для заполнения отсутствующих данных из GPS. Каждый раз, когда GPS дает хорошее исправление, reset начальные условия положения, скорости и ориентации и акселерометры будут предоставлять данные до следующего действительного GPS-исправления.

Ответ 6

Гравитация уничтожит все ваши измерения. Телефон в состоянии покоя испытывает высокое постоянное ускорение (да, UP). Акселерометр не может различать ускорение и гравитацию (технически, они одинаковые), поэтому через несколько секунд он достигнет чрезвычайно высоких скоростей. Если вы никогда не слегка наклоняете акселерометр, вы можете просто вычесть постоянное гравитационное притяжение с оси z (или какая бы ни была ось направлена ​​вверх/вниз), но это маловероятно.

В принципе, вам нужно использовать сложную систему гироскопа/магнитометра и акселерометра для вычисления точного направления силы тяжести, а затем вычесть ускорение.

Ответ 7

v = Интеграл (a)?

В общем, хотя, я думаю, неточности в акселерометрах сделают это довольно жестким.

Ответ 8

Если телефон находится в режиме ожидания, у вас есть ускорение ZERO, поэтому ваша скорость равна 0. Вероятно, вы должны найти данные о местоположении из GPS и получить соответствующие отсчеты времени и вычислить скорость с течением времени.