Как рассчитать расстояние на основе ускорения телефона
Я хочу создать что-то вроде этого, но с помощью телефона Android: http://www.youtube.com/watch?v=WOt9mb5QqRs
Я уже построил приложение, которое отправляет сенсорную информацию через сокет (все еще ищу хорошую реализацию веб-сокета для Android). Я намерен использовать эту информацию для взаимодействия с веб-приложением, поэтому, например, я смогу перемещать изображение в зависимости от движения телефона. Проблема в том, что я пытался рассчитать расстояние на основе данных акселерометра, но результаты действительно плохие. Интересно, может ли кто-нибудь помочь мне с правильным уравнением, но, прежде всего, возможно ли это сделать?
До сих пор я использую следующие уравнения:
velocity = acceleration * time;
distance = velocity * time + (acceleration * time^2) / 2;
затем я перевожу расстояние от метров в секунду до пикселей на основе разрешения экрана монитора.
это рассчитывается с помощью JavaScript в браузере каждый раз, когда я получаю данные датчика, что каждые ~80 мс.
2 ответа
Основы просты. В аналоговом мире вы используете непрерывную математику, которая:
velocity = integrate(acceleration)
distance = integrate(velocity)
а в цифровом мире это даже проще, вы используете дискретную математику, где интеграция становится суммированием:
velocity = sum(acceleration)
distance = sum(velocity)
Просто продолжайте складывать все значения ускорения, которые вы прочитали, и в итоге вы получите расстояние.
Большая проблема с этим заключается в том, что на планете Земля происходит постоянное ускорение вниз примерно на 10 м / с / с из-за силы тяжести. Выяснить, какая часть вашего вектора является гравитацией, является трудной частью.
Кстати, гравитация - это то, как акселерометры могут определять наклон. Поэтому, как бы вы это ни делали, если вы не можете рассчитать наклон независимо от акселерометров (например, с помощью гироскопов), ваш код будет в основном измерять наклон вместо расстояния.
ХА! Я только что понял из моего последнего заявления, что многие приложения для iPhone не будут работать в космосе:-P
Дополнительный ответ:
Исходя из "комментария", опубликованного ОП (в качестве ответа ниже или выше этого ответа), мне кажется, что мне нужно дать дополнительные пояснения. Реализация действительно очень проста, так что люди, не знакомые с математикой, подумают, что она должна быть более сложной, чем эта. Псевдокод выглядит следующим образом:
// 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
}
Расстояние всегда измеряется от того места, где программа запускается впервые, если вы не сбросили переменную расстояния на ноль. Акселерометр должен постоянно считываться (предпочтительно с той скоростью, с которой сам акселерометр измеряет силы), а значения скорости и расстояния обновляются соответствующим образом. Если вы хотите узнать расстояние от начальной точки, просто прочитайте переменную расстояния.
Несколько вещей: любое количество наклона, независимо от того, насколько оно незначительно, добавит дрейфа. Это означает, что всегда будет небольшое количество постоянного ускорения в одном или другом направлении, если сам угол наклона не отслеживается постоянно. Даже атомные подводные лодки, оснащенные высокоточными акселерометрами и гироскопами, потому что GPS не работает под водой, должны периодически всплывать на поверхность и синхронизироваться с GPS, чтобы исправить этот дрейф.
Во-вторых, акселерометр измеряет силу, а не движение. Любая сила измеряется. Я упомянул гравитацию, но он также измеряет удары, вызванные трением со столом, ваш пульс, как ваше сердцебиение, а дыхание заставляет вашу руку слегка дрожать, что угодно. Хорошей новостью является то, что в долгосрочной перспективе все эти силы будут усреднены, и формула все еще будет верна. Но в краткосрочной перспективе это означает, что ваше чтение будет шумным. Есть много хитростей, которые люди придумали, чтобы минимизировать этот шум, используя такие вещи, как фильтры Вейнера и Калмана.
В-третьих, как вы могли заметить, показания акселерометра не постоянны. Я не просто имею в виду, что значения меняются каждый раз, когда вы их читаете, это очевидно, но это также меняет значения между чтениями. Каждое пропущенное нами значение влияет на нашу точность, поэтому важно читать значения как можно чаще. Хорошие новости заключаются в том, что в конечном итоге все эти ошибки, вызванные отсутствующими значениями, должны усредняться, поскольку они в основном вызваны резкими движениями или вибрациями, и наша формула снова остается верной. Но это снова означает, что в краткосрочной перспективе это добавляет шум в нашу систему. Если вы используете хороший проникающий фильтр, такой как фильтр Калмана, он должен быть в состоянии учесть это, но более слабые фильтры могут нуждаться в некоторой помощи. Один из способов сделать это - усреднить каждое ускоренное чтение с предыдущим чтением. Обратите внимание, что это должно быть предыдущее "реальное" чтение, а не предыдущее усредненное чтение.
Больше точности, чем это, относится к области инерциальных измерительных единиц (IMU) и инерциального наведения, а также к множеству математических матриц с векторными и матричными характеристиками. Хотя есть проекты с открытым исходным кодом, которые делают это (менее 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.