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

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

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

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

velocity = acceleration * time;

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

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

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


person Demian    schedule 01.12.2010    source источник


Ответы (2)


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

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
comment
Хорошо, теперь я могу прокомментировать, это не имеет никакого смысла, как эта скорость (изначально равная 0) равна ускорению ?? как насчет времени? ускорение 9 м / с² означает, что телефон достигнет этой скорости за одну секунду, но я измеряю скорость каждые ~ 80 мс. - person Demian; 02.12.2010
comment
Так работает физика. Возможно, вы забыли, что скорость - это просто интеграл ускорения. Когда время становится дискретным, интегрирование становится суммированием. - person slebetman; 02.12.2010
comment
Суммирование значений, которые являются дискретными по времени и по значению, - это не то же самое, что интегрирование. Вы должны учитывать время / интервал между значениями ускорения. - person brutella; 11.01.2011
comment
@slebetman: вы говорите, что ускоряетесь с 0 до 9 м / с2 за 0-80 мс. Но чтобы рассчитать расстояние, которое вы проделываете - v = 9 * 0,80, d = v * 0,80. v - конечная скорость на 80 мс. И вы рассчитываете расстояние, умножая конечную скорость на 80 мс. - person Ashwin; 17.10.2012
comment
@Ashwin: Да, для одного интервала чтения нужно вычислить среднюю скорость. Но для достаточно большого количества показаний (например, непрерывного считывания показаний акселерометра) простое суммирование ускорений быстро сводится к сумме средних скоростей. Вы можете попробовать это самостоятельно с приведенными выше данными и посмотреть, как это повлияет на расчеты расстояния. - person slebetman; 17.10.2012
comment
@slebetman: не должно ли это быть более точным - stackoverflow.com/questions/12926459/. Я все еще не получаю ответа: P. Но я надеюсь, что это логично. - person Ashwin; 17.10.2012
comment
@Ashwin: Я настоятельно рекомендую попробовать мой метод в качестве теста, чтобы увидеть, соответствует ли расчет реальной длине. Затем сравните его со своим кодом. То есть удалите форму 0.5 из вашего кода и попробуйте снова. - person slebetman; 17.10.2012
comment
@slebetman: Я пробовал удалить 0.5 (до сих пор не понимаю, зачем это делать). Тем не менее, значения I значительно ниже фактических значений, хотя они увеличились из-за удаления 0,5. - person Ashwin; 17.10.2012
comment
+1 очень понятно объяснил ответ, спасибо. не забывайте, что при суммировании значений вы должны умножить на дельту времени с момента последней выборки, то есть v + = a * (t (n) - t (n-1)). также не забудьте преобразовать метку времени из наносекунд в секунды! - person Mr. Bungle; 27.05.2013
comment
Я сомневаюсь, что эта простая формула работает; по крайней мере, в мобильном приложении. У меня есть приложение на основе акселерометра, я интегрировал ускорение, но так и не получил правильного ответа. Я не видел в магазинах приложений ни одного приложения, которое могло бы это сделать, и полагаю, что это будет не так просто. - person Amir; 10.04.2016
comment
@Amir Эта формула действительно проста и наивна в работе. В нем слишком много предположений, что делает его непрактичным. - person Derek 朕會功夫; 30.03.2017

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


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

person kek    schedule 01.12.2010
comment
Это правильный ответ. приведенный выше ответ неверен. Он говорит, что вы ускоряетесь с 0 до 9 м / с2 за 0-80 мс. Но для расчета расстояния он находится. v = 9 * 0,80, d = v * 0,80. v - конечная скорость на 80 мс. И он вычисляет расстояние, умножая конечную скорость на 80 мс. - person Ashwin; 17.10.2012
comment
@Ashwin Я знаю, что это очень старый, но он прав! Посмотрите суммы Римана. Приведенный выше ответ неверен, потому что он касается случая непрерывного ускорения, а не дискретно измеряемых интервалов, как в случае с телефоном. Ваше здоровье. - person Simon O'Hanlon; 04.03.2013