Я хочу создать приложение, которое вычисляет точное расстояние, пройденное iPhone (не большое расстояние) с помощью гироскопа + акселерометра. Здесь нет необходимости в GPS.
Как мне подойти к этой проблеме?
Я хочу создать приложение, которое вычисляет точное расстояние, пройденное iPhone (не большое расстояние) с помощью гироскопа + акселерометра. Здесь нет необходимости в GPS.
Как мне подойти к этой проблеме?
Основным исчислением этой проблемы является выражение
(и аналогичные выражения для смещений по y и z) и базовой геометрии есть теорема Пифагора
Итак, как только вы передадите сигналы акселерометра через фильтр нижних частот и закодированы во времени с интервалом выборки dt, вы можете найти смещение в x как (pardon my C...)
float dx=0.0f;
float vx=0.0f;
for (int i=1; i<n; i++)
{
vx+=(acceleration_x[i-1] + acceleration_x[i])/2.0f*dt;
dx+=vx*dt;
}
и аналогично для dy и dz. Здесь
float acceleration_x[n];
содержит значения ускорения x от начала до конца измерения в моменты времени 0, dt, 2 * dt, 3 * dt,... (n-1) * dt.
Чтобы найти полное смещение, вы просто делаете
dl=sqrt(dx*dx + dy*dy + dz*dz);
Гироскоп для этого не нужен, но если вы измеряете линейные расстояния, вы можете использовать показания гироскопа для управления тем, что вращение устройства не было слишком большим. Если вращение было слишком сильным, попросите пользователя повторить измерение.
Вы получаете позицию, дважды интегрируя линейное ускорение, но ошибка ужасна. На практике это бесполезно.
Вот объяснение почему (Google Tech Talk) в 23:20. Я настоятельно рекомендую это видео.
Похожие вопросы:
Какова реальная точность телефонных акселерометров при использовании для позиционирования?
как рассчитать движение телефона в вертикальном направлении от отдыха?
Как использовать Accelerometer для измерения расстояния для разработки приложений Android
Обновление (24 февраля 2013 г.): @Simon Да, если вы знаете больше о движении, например, человек, идущий, и датчик находится на ноге, тогда вы можете сделать гораздо больше. Они называются
допущения, специфичные для домена.
Они терпят неудачу, если предположения не выполняются и могут быть довольно громоздкими для реализации. Тем не менее, если они работают, вы можете делать забавные вещи. См. Ссылки в моем ответе Точность акселерометра Android (инерциальная навигация) при помещении в помещении.
Вы должны использовать интерфейс Core Motion, как описано в Простой обнаружение движения iPhone. Особенно можно отслеживать все повороты очень точно. Если вы планируете сделать что-то, связанное с линейными движениями, это очень сложно. Посмотрите перемещение данных акселерометра с помощью Core Motion.
Я сделал трещину и сдался (поздно ночью, похоже, никуда не денутся). Это для проекта Unity3d.
Если кто-то захочет забрать меня, я бы с удовольствием рассказал о том, что делает все это.
В основном после того, что оказалось ложным срабатыванием, я подумал, что попытаюсь отфильтровать его с использованием фильтра нижних частот, а затем попытаться удалить отскоки, найдя тренд, затем (acc_x [i-1] + acc_x [I])/2.
Похоже, что ложный результат все еще исходит от наклона, который я попытался удалить..
Если этот код полезен или ведет вас куда-нибудь, пожалуйста, дайте мне знать!
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// [email protected]
/// </summary>
public class AccelerometerInput : MonoBehaviour
{
Transform myTransform;
Gyroscope gyro;
GyroCam gyroCam;
void Awake()
{
gyroCam= FindObjectOfType<GyroCam> ();
myTransform = transform;
if (SystemInfo.supportsGyroscope) {
gyro = Input.gyro;
gyro.enabled = true;
}
}
bool shouldBeInitialized = false;
void Update ()
{
transform.Translate (GetAccelerometer ());// * Time.deltaTime * speed);
//GetComponent<Rigidbody> ().AddForce (GetAccelerometer ());
}
public float speed = 10.0F;
public Vector3 dir;
public float f;
Vector3 GetAccelerometer()
{
dir = Input.acceleration;
dir.x *= gyro.attitude.x;
dir.z *= gyro.attitude.z;
if (Mathf.Abs (dir.x) < .001f)
dir.x = 0;
dir.y = 0;
if (Mathf.Abs (dir.z) < .001f)
dir.z = 0;
RecordPointsForFilter (dir);
//print ("Direction : " + dir.ToString("F7"));
return TestPointsForVelocity();
}
Vector3[] points = new Vector3[20];
int index;
void RecordPointsForFilter(Vector3 recentPoint)
{
if (index >= 20)
index = 0;
points [index] = EvaluateTrend (recentPoint);;
index++;
}
//try to remove bounces
float xTrend = 0;
float zTrend = 0;
float lastTrendyX = 0;
float lastTrendyZ = 0;
Vector3 EvaluateTrend(Vector3 recentPoint)
{
//if the last few points were positive, and this point is negative, don't pass it along
//accumulate points into a trend
if (recentPoint.x > 0)
xTrend += .01f;
else
xTrend -= .1f;
if (recentPoint.z > 0)
zTrend += .1f;
else
zTrend -= .1f;
//if point matches trend, keep it
if (xTrend > 0) {
if (recentPoint.x > 0)
lastTrendyX = recentPoint.x;
} else // xTrend < 0
if (recentPoint.x < 0)
lastTrendyX = recentPoint.x;
if (zTrend > 0) {
if (recentPoint.z > 0)
lastTrendyZ = recentPoint.z;
} else // xTrend < 0
if (recentPoint.z < 0)
lastTrendyZ = recentPoint.z;
return new Vector3( lastTrendyX, 0, lastTrendyZ);
}
Vector3 TestPointsForVelocity()
{
float x = 0;
float z = 0;
float xAcc = 0;
float zAcc = 0;
int successfulHits = 0;
for(int i = 0; i < points.Length; i++)
{
if(points[i]!=null)
{
successfulHits ++;
xAcc += points[i].x;
zAcc += points[i].z;
}
}
x = xAcc / successfulHits;
z = zAcc / successfulHits;
return new Vector3 (x, 0, z);
}
}
Вот ответ . Кто-то спросил раньше.
Существует приложение под названием RangeFinder, которое делает то же самое (доступно в App Store).
(acc_x [i-1] + acc_x [i])/2 - фильтр нижних частот, это среднее значение между двумя измерениями во времени
также смотрите здесь: http://www.freescale.com/files/sensors/doc/app_note/AN3397.pdf pag: 3