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

#android #math #accelerometer

#Android #математика #акселерометр

Вопрос:

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

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

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

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

Комментарии:

1. @Ignacio Что? Постоянное ускорение означает, что скорость увеличивается линейно.

2. У вас есть какое-либо рабочее решение, можете ли вы указать мне на это или поделиться кодом.

3. Привет, ты когда-нибудь думал закрыть этот вопрос?

4. В вашем телефоне используются датчики размером в половину горошины, которые стоят около 2 долларов и были изготовлены путем травления крошечных кусочков металла в форме грубых пружин и грузиков. Достаточно знать, в какую сторону вы держите телефон и встряхивается ли он. Из этого никогда не получится достойный пакет инерциальных датчиков. Поверьте мне, ошибки накапливаются так быстро, что это безнадежная проблема для решения. (Источник: я отвечал за встроенную прошивку для этого на телефоне Amazon Fire, когда работал в Amazon.)

5. Я только что нашел это превосходное видео, объясняющее, почему это сложно: youtube.com/watch?v=C7JQ7Rpwn2k#t=23m20s

Ответ №1:

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

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

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

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

Комментарии:

1. На случай, если никто не заметил, V1 = a * t!

Ответ №2:

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

Комментарии:

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

2. Датчик TYPE_LINEAR_ACCELERATION даст вам ускорение с отфильтрованной силой тяжести, так что это приятно. TYPE_ROTATION_VECTOR задаст вам ориентацию устройства в виде кватерниона, который можно легко преобразовать в матрицу вращения 3×3. В каждом временном срезе используйте матрицу вращения, чтобы преобразовать ускорение в вектор в трехмерном пространстве. Интегрируйте это со временем, чтобы получить ускорение (другой вектор), и интегрируйте это , чтобы получить положение относительно начальной позиции. (Все это предполагает, что начальная скорость была равна нулю.) Затем отправляйтесь в паб и выпейте пинту пива, потому что с дешевыми датчиками все безнадежно.

Ответ №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);
}
  

Наслаждайся!

Ответ №4:

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

Ответ №5:

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

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

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

Комментарии:

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

Ответ №6:

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

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

Комментарии:

1. Sensor Fusion может отфильтровать это для вас. Просто используйте датчик TYPE_LINEAR_ACCELERATION.

Ответ №7:

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

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

Комментарии:

1. Зависит от типа неточностей. Вы могли бы откалибровать линейную ошибку, нет?

Ответ №8:

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

Комментарии:

1. Да, скорость равна 0 «при запуске приложения». Я калибрую его с этого момента.

2. «Стоять на месте» на самом деле должно быть легко обнаружить. Если входные данные с акселерометра (используйте TYPE_LINEAR_ACCELERATION) очень постоянны, телефон, вероятно, не обрабатывается.