Как рассчитать расстояние, основанное на ускорении телефона

Я хочу создать что-то вроде этого, но используя Android-телефон: http://www.youtube.com/watch?v=WOt9mb5QqRs

Я уже создал приложение, которое отправляет информацию о датчике через сокет (все еще ищет хорошую реализацию websocket для android). Я намерен использовать эту информацию для взаимодействия с веб-приложением, поэтому, например, я смогу переместить изображение на основе движения телефона. Проблема в том, что я пытался рассчитать расстояние по данным акселерометра, но результаты действительно плохие. Интересно, может ли кто-нибудь помочь мне с правильным уравнением, но в первую очередь, можно ли это сделать?

До сих пор я использую следующие уравнения:

velocity = acceleration * time;

distance = velocity * time + (acceleration * time^2) / 2;

тогда я переводю расстояние от метров в секунду до пикселей на основе разрешения экрана монитора.

который рассчитывается с помощью javascript в браузере каждый раз, когда я получаю данные датчиков, каждый раз ~ 80 мс.

Ответ 1

Основы просты. В аналоговом мире вы используете непрерывную математику, которая:

velocity = integrate(acceleration)
distance = integrate(velocity)

а в цифровом мире это еще проще, вы используете дискретную математику, где интеграция становится суммированием:

velocity = sum(acceleration)
distance = sum(velocity)

Просто добавляйте все значения ускорения, которые вы читаете, и в конечном итоге получаете расстояние.

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

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


ХА! Я только что понял из своего последнего утверждения, что многие приложения для iPhone не будут работать в космосе: -P


Дополнительный ответ:

Основываясь на "комментарии", опубликованном OP (в качестве ответа ниже или выше этого ответа), похоже, мне нужно предоставить дополнительные объяснения. Реализация действительно очень проста, что люди, не знакомые с математикой, подумают, что это должно быть сложнее, чем это. Псевдокод выглядит следующим образом:

// Set distance to zero at start-up:
var distance_X = 0
var velocity_X = 0

function update_acceleration_X (acceleration_X) {
    velocity_X = velocity_X + acceleration_X
    distance_X = distance_X + velocity_X
}

// To use the distance value just read the distance_X variable:
function get_distance_X_and_reset () {
    x = distance_X
    distance_X = 0
    return x
}

Расстояние всегда измеряется от того места, где программное обеспечение запускается, если вы не reset изменяете расстояние до нуля. Акселерометр должен постоянно считываться (предпочтительно с той скоростью, при которой сам акселерометр измеряет силы), и соответственно изменяются значения скорости и расстояния. Когда вы хотите узнать расстояние от начальной точки, просто прочитайте переменную расстояния.

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

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

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

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

В этих статьях Sparkfun есть несколько хороших ссылок внизу и некоторый ссылочный код:

http://www.sparkfun.com/products/9268

http://www.sparkfun.com/products/8454

Надеюсь, все это поможет. И если у кого-нибудь есть ссылки на любую статью, которая может помочь прокомментировать.


Пример

Конечно, если вам нужны реальные единицы, вам нужно масштабировать для частоты дискретизации. Например, ускорение со скоростью 9 м/с в течение 80 мс означает, что ваша скорость равна (9m/s/s * 0.08s) = 0.72m/s. Вышеупомянутый псевдокод упрощается, если вы не заботитесь об устройствах. Конечные значения по-прежнему будут представлять собой расстояние в виде числа, которое просто так, что число мало связано с какой-либо единицей измерения реального мира. Вы можете просто применить функцию масштабирования в конце, откалиброванном до вашего пиксельного значения. Во всяком случае, вот пример с реальными единицами, чтобы выяснить, что происходит:

given the following acceleration readings:
9m/s/s
3m/s/s
0m/s/s
0m/s/s
0m/s/s
-5m/s/s
-7m/s/s

assuming an 80ms sample rate
we can derive the following velocities:
0.72m/s (what you get from accelerating 9m/s for 80ms)
0.96m/s
0.96m/s
0.96m/s
0.96m/s
0.56m/s
0m/s

from that we can derive the following distances:
57.6mm (what you get from moving at 0.72m/s for 80ms)
134.4mm
211.2mm
288mm
364.8mm
409.6mm

Теперь, если вы берете производные расстояния и делаете обратный расчет в соответствии с обычным (v = (s2-s1)/t и a = (v2-v1)/t), вы должны вернуть показания ускорения.

Ответ 2

Макс. скорость = время * ускорение.
Средняя скорость = Максимальная скорость /2.
Расстояние пройдено = Средняя скорость * время.


пройденное расстояние = время * время * ускорение/2.