Основы просты. В аналоговом мире вы используете непрерывную математику, которая:
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
}
Расстояние всегда измеряется от того места, где программное обеспечение сначала запускается, если вы не сбросите переменную расстояния на ноль. Показания акселерометра должны постоянно считываться (желательно со скоростью, с которой сам акселерометр измеряет силы), а значения скорости и расстояния обновляются соответствующим образом. Если вы хотите узнать расстояние от начальной точки, просто прочтите переменную расстояния.
Несколько вещей: любой наклон, даже самый небольшой, добавит сноса. Это означает, что всегда будет небольшое постоянное ускорение в одном или другом направлении, если только сам угол наклона не будет постоянно отслеживаться. Даже атомные подводные лодки, оснащенные высокоточными акселерометрами и гироскопами, поскольку 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
), вы должны получить обратно показания ускорения.
person
slebetman
schedule
01.12.2010