Как найти расстояние, пройденное гироскопом и акселерометром?

Я хочу создать приложение, которое вычисляет точное расстояние, пройденное iPhone (не большое расстояние) с помощью гироскопа + акселерометра. Здесь нет необходимости в GPS.

Как мне подойти к этой проблеме?

Ответ 1

Основным исчислением этой проблемы является выражение

enter image description here

(и аналогичные выражения для смещений по y и z) и базовой геометрии есть теорема Пифагора

enter image description here

Итак, как только вы передадите сигналы акселерометра через фильтр нижних частот и закодированы во времени с интервалом выборки 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);

Гироскоп для этого не нужен, но если вы измеряете линейные расстояния, вы можете использовать показания гироскопа для управления тем, что вращение устройства не было слишком большим. Если вращение было слишком сильным, попросите пользователя повторить измерение.

Ответ 2

Вы получаете позицию, дважды интегрируя линейное ускорение, но ошибка ужасна. На практике это бесполезно.

Вот объяснение почему (Google Tech Talk) в 23:20. Я настоятельно рекомендую это видео.

Похожие вопросы:


Обновление (24 февраля 2013 г.): @Simon Да, если вы знаете больше о движении, например, человек, идущий, и датчик находится на ноге, тогда вы можете сделать гораздо больше. Они называются

    допущения, специфичные для домена.

Они терпят неудачу, если предположения не выполняются и могут быть довольно громоздкими для реализации. Тем не менее, если они работают, вы можете делать забавные вещи. См. Ссылки в моем ответе Точность акселерометра Android (инерциальная навигация) при помещении в помещении.

Ответ 3

Вы должны использовать интерфейс Core Motion, как описано в Простой обнаружение движения iPhone. Особенно можно отслеживать все повороты очень точно. Если вы планируете сделать что-то, связанное с линейными движениями, это очень сложно. Посмотрите перемещение данных акселерометра с помощью Core Motion.

Ответ 4

Я сделал трещину и сдался (поздно ночью, похоже, никуда не денутся). Это для проекта 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);

    }
}

Ответ 5

Вот ответ . Кто-то спросил раньше.

Существует приложение под названием RangeFinder, которое делает то же самое (доступно в App Store).