Как обнаружить движение iPhone в пространстве с помощью акселерометра?
Я пытаюсь создать приложение, которое будет определять, какую форму вы создали с помощью iPhone с помощью акселерометра.
В качестве примера, если вы нарисуете круг своей рукой с iPhone, приложение сможет перерисовать его на экране.
Это может также работать с квадратами или даже более сложными формами.
Единственный пример приложения, который я видел, это AirPaint (http://vimeo.com/2276713), но он, похоже, не в состоянии делать это в режиме реального времени.
Моя первая попытка - применить фильтр низких частот по параметрам X и Y с акселерометра и сделать указатель перемещаться к этим значениям пропорционально размеру экрана.
Но этого явно недостаточно, у меня очень низкая точность, и если я встряхну это устройство, это также заставляет стрелку двигаться...
Есть идеи об этом?
Считаете ли вы, что данные акселерометра достаточно для этого? Или я должен использовать другие данные, такие как компас?
Спасибо заранее!
Ответы
Ответ 1
OK Я нашел что-то, что работает, но у меня все еще есть проблемы.
Вот как я продолжаю (допустив, что устройство держится вертикально):
1 - У меня есть значения по умолчанию x, y и z.
2 - Я извлекаю гравитационный вектор из этих данных с использованием фильтра нижних частот.
3 - Я вычитаю нормированный вектор силы тяжести от каждого x, y и z и получаю ускорение движения.
4 - Затем я интегрирую это значение ускорения по времени, поэтому получаю скорость.
5 - Я снова интегрирую эту скорость по времени и найду позицию.
Весь приведенный ниже код находится в акселерометре: didAccelerate: делегат моего контроллера.
Я пытаюсь заставить мяч двигаться в соответствии с позицией, которую я нашел.
Вот мой код:
NSTimeInterval interval = 0;
NSDate *now = [NSDate date];
if (previousDate != nil)
{
interval = [now timeIntervalSinceDate:previousDate];
}
previousDate = now;
//Isolating gravity vector
gravity.x = currentAcceleration.x * kFileringFactor + gravity.x * (1.0 - kFileringFactor);
gravity.y = currentAcceleration.y * kFileringFactor + gravity.y * (1.0 - kFileringFactor);
gravity.z = currentAcceleration.z * kFileringFactor + gravity.z * (1.0 - kFileringFactor);
float gravityNorm = sqrt(gravity.x * gravity.x + gravity.y * gravity.y + gravity.z * gravity.z);
//Removing gravity vector from initial acceleration
filteredAcceleration.x = acceleration.x - gravity.x / gravityNorm;
filteredAcceleration.y = acceleration.y - gravity.y / gravityNorm;
filteredAcceleration.z = acceleration.z - gravity.z / gravityNorm;
//Calculating velocity related to time interval
velocity.x = velocity.x + filteredAcceleration.x * interval;
velocity.y = velocity.y + filteredAcceleration.y * interval;
velocity.z = velocity.z + filteredAcceleration.z * interval;
//Finding position
position.x = position.x + velocity.x * interval * 160;
position.y = position.y + velocity.y * interval * 230;
Если я выполняю это, я получаю неплохие значения, я имею в виду, что я могу видеть, что ускорение переходит в положительные или отрицательные значения в соответствии с движениями, которые я делаю.
Но когда я пытаюсь применить эту позицию к моему взгляду на мяч, я вижу, что он движется, но с проницательностью идти больше в одном направлении, чем другой. Это означает, что, например, если я рисую круги с помощью своего устройства, я увижу шар, описывающий кривые в верхнем левом углу экрана.
Что-то вроде этого: http://img685.imageshack.us/i/capturedcran20100422133.png/
Есть ли у вас какие-либо идеи о том, что происходит?
Спасибо заранее!
Ответ 2
Проблема заключается в том, что вы не можете дважды интегрировать ускорение, чтобы получить позицию. Не зная начального положения и скорости. Помните + C термин, который вы добавили в школу, когда узнаете об интеграции? Ну, к тому времени, когда вы доберетесь до позиции, это ct + k term. И это важно. Прежде чем вы учесть, что данные ускорения, которые вы получаете, квантуются и усредняются, поэтому вы фактически не интегрируете фактическое ускорение устройства. Эти ошибки будут большими, если они будут объединены дважды.
Следите за демонстрацией AirPaint, и вы увидите, как это происходит, визуализированные фигуры значительно отличаются от перемещенных фигур.
Даже устройства, у которых есть определенное положение и скорость (например, Wiimote), возникают проблемы с распознаванием жестов. Трудная проблема заключается в том, что люди платят хорошие деньги (например, таким компаниям, как AILive), чтобы решить их.
Сказав это, вы, вероятно, можете легко отличить определенные типы жестов, если их масштабные характеристики различны. Круг может быть обнаружен, если устройство получает ускорения в каждом из шести угловых диапазонов (например). Вы можете обнаружить, как прокручивать iphone по воздуху и встряхивать его.
Говорить разницу между кругом и квадратом будет намного сложнее.
Ответ 3
Вам нужно посмотреть, как ускорение относится к скорости и скорости к положению. На мой взгляд, сейчас у меня очень странный пердит, но я уверен, что это интеграл... вы хотите перевести ускорение по времени. Википедия должна помочь вам в математике, и я уверен, что где-то есть хорошая библиотека, которая может помочь вам.
Просто помните, что акселерометры не идеальны и опробованы достаточно быстро. На самом деле внезапные движения не могут быть подняты так хорошо. Но для того, чтобы осторожно рисовать в воздухе, он должен работать нормально.
Ответ 4
Похоже, вы нормализуете свой гравитационный вектор до вычитания с мгновенным ускорением. Это сохранит относительную ориентацию, но удалит относительную шкалу. Последнее устройство, которое я тестировал (по общему признанию, не Idevice), возвратило гравитацию примерно на -9,8, которое, вероятно, откалибровано до м/с. Предполагая, что нет другого ускорения, если бы вы нормализировали это, то вычтите его из фильтрованного прохода, вы закончите с текущим ускорением -8.8 вместо 0.0f;
2 варианта:
-Вы можете просто вычесть вектор силы тяжести после прохождения фильтра
-Захватить начальную длину вектора ускорения, нормализовать ускорение и гравитационные векторы, масштабировать вектор ускорения на точку нормалей ускорения и силы тяжести.
Также стоит помнить о том, чтобы учитывать ориентацию устройства.