¿Cómo puedo encontrar la distancia recorrida con un giroscopio y un acelerómetro?

Quiero construir una aplicación que calcule la distancia precisa viajada por iPhone (no de larga distancia) usando Gyro + Acelerómetro. No hay necesidad de GPS aquí.

¿Cómo debería abordar este problema?

El cálculo básico detrás de este problema está en la expresión

enter image description here

(y expresiones similares para desplazamientos en y y z) y la geometría básica es el teorema de Pitágoras

enter image description here

Entonces, una vez que tienes las señales del acelerómetro pasadas a través de un filtro de paso bajo y se agrupan en el tiempo con el intervalo de muestreo dt, puedes encontrar el desplazamiento en x como ( perdona mi C … )

float dx=0.0f; float vx=0.0f; for (int i=1; i 

y de manera similar para dy y dz. aquí

 float acceleration_x[n]; 

contiene valores de x-acceleration desde el inicio hasta el final de la medición en los momentos 0, dt, 2 * dt, 3 * dt, ... (n-1) * dt.

Para encontrar el desplazamiento total, simplemente hazlo

 dl=sqrt(dx*dx + dy*dy + dz*dz); 

El giroscopio no es necesario para esto, pero si está midiendo distancias lineales, puede usar la lectura del giroscopio para controlar que la rotación del dispositivo no sea demasiado grande. Si la rotación fue demasiado fuerte, haga que el usuario vuelva a hacer la medición.

Obtienes posición integrando la aceleración lineal dos veces, pero el error es horrible. Es inútil en la práctica.

Aquí hay una explicación de por qué (Google Tech Talk) a las 23:20. Recomiendo este video.

Preguntas similares:

  • rastrear pequeños movimientos del iphone sin GPS

  • ¿Cuál es la precisión del mundo real de los acelerómetros telefónicos cuando se utilizan para posicionar?

  • cómo calcular el movimiento del teléfono en la dirección vertical desde el descanso?

  • iOS: Precisión del movimiento en el espacio 3D

  • Cómo usar el acelerómetro para medir la distancia para el desarrollo de aplicaciones de Android

  • Distancia movida por Acelerómetro


Actualización (24 de febrero de 2013): @Simon Sí, si sabe más sobre el movimiento, por ejemplo, una persona que camina y el sensor está en su pie, entonces puede hacer mucho más. Estos se llaman

supuestos específicos de dominio .

Se rompen miserablemente si las suposiciones no se cumplen y pueden ser bastante engorrosas de implementar. Sin embargo, si funcionan, puedes hacer cosas divertidas. Ver los enlaces en mi respuesta Android acelerómetro precisión (navegación inercial) en el posicionamiento en interiores.

Debe usar la interfaz Core Motion como se describe en Simple iPhone motion detect . Especialmente todas las rotaciones se pueden rastrear con mucha precisión. Si planeas hacer algo relacionado con los movimientos lineales, esto es algo muy difícil. Eche un vistazo a Obtener desplazamiento de los datos del acelerómetro con Core Motion .

Tomé una grieta en esto y me di por vencido (tarde en la noche, no parecía llegar a ningún lado). Esto es para un proyecto de Unity3d.

Si alguien quiere continuar donde lo dejé, me complacería detallar qué hace todo esto.

Básicamente después de algo de lo que resultaron ser falsos positivos, pensé en intentar filtrar esto usando un filtro de paso bajo, luego intenté eliminar los rebotes buscando una tendencia, luego (acc_x [i-1] + acc_x [i] ) / 2.

Parece que el falso positivo todavía proviene de la inclinación, que intenté eliminar …

Si este código es útil o lo lleva a algún lado, ¡por favor hágamelo saber!

 using UnityEngine; using System.Collections.Generic; ///  /// rbi.noli@gmail.com ///  public class AccelerometerInput : MonoBehaviour { Transform myTransform; Gyroscope gyro; GyroCam gyroCam; void Awake() { gyroCam= FindObjectOfType (); myTransform = transform; if (SystemInfo.supportsGyroscope) { gyro = Input.gyro; gyro.enabled = true; } } bool shouldBeInitialized = false; void Update () { transform.Translate (GetAccelerometer ());// * Time.deltaTime * speed); //GetComponent ().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); } } 

Aquí está la respuesta . Alguien preguntó antes.

Hay una aplicación llamada RangeFinder haciendo lo mismo (disponible en App Store).

(acc_x [i-1] + acc_x [i]) / 2 es un filtro de paso bajo, es el valor medio entre dos medidas en el tiempo

también mira aquí: http://www.freescale.com/files/sensors/doc/app_note/AN3397.pdf pag: 3