Я хочу создать приложение, которое вычисляет точное расстояние, пройденное iPhone (не большое расстояние), используя гироскоп + акселерометр. GPS здесь не нужен.
Как мне подойти к этой проблеме?
Я хочу создать приложение, которое вычисляет точное расстояние, пройденное iPhone (не большое расстояние), используя гироскоп + акселерометр. GPS здесь не нужен.
Как мне подойти к этой проблеме?
Основное исчисление этой проблемы находится в выражении
(и аналогичные выражения для перемещений по y и z), а основная геометрия - это теорема Пифагора
Итак, после того как вы пропустили сигналы акселерометра через фильтр нижних частот и объединили их по времени с интервалом дискретизации dt, вы можете найти смещение по x как (простите за 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. Я очень рекомендую это видео.
Похожие вопросы:
Какова реальная точность телефонных акселерометров при использовании для позиционирования?
как рассчитать движение телефона в вертикальном направлении из состояния покоя?
Как использовать акселерометр для измерения расстояния при разработке приложений для 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);
}
}
(acc_x[i-1]+acc_x[i])/2 — фильтр нижних частот, это среднее значение между двумя измерениями во времени.
также посмотрите здесь: http://www.freescale.com/files/sensors/doc/app_note/AN3397.pdf стр. :3
Нависенс.
https://navisens.com/#how-work
Здесь претензия - запатентованная технология Navisens обрабатывает данные акселерометра и гироскопа уникальным способом для определения местоположения вашего телефона.
Опробовали демонстрационное приложение, которое работает в основном для картографирования перемещений без служб определения местоположения или Wi-Fi после установки исходного местоположения и направления.
iOS SDK — https://github.com/navisens/iOS-SDK
Android SDK — https://github.com/navisens/Android-SDK
Примечание. Это не открытый исходный код
Вот ответ а>. Кто-то спрашивал раньше.
Существует приложение под названием RangeFinder, делающее то же самое (доступно в App Store).