如何找到陀螺仪和加速度计的距离?

时间:2011-07-11 08:03:04

标签: iphone accelerometer distance gyroscope

我想构建一个应用程序,使用陀螺+加速度计计算iPhone(非长距离)行进的精确距离。这里不需要GPS。

我该如何解决这个问题?

7 个答案:

答案 0 :(得分:78)

此问题背后的基本演算在表达式

enter image description here

(以及y和z中位移的类似表达式)和基本几何是毕达哥拉斯定理

enter image description here

因此,一旦你的加速度计信号通过一个低通滤波器并在采样间隔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);

此时不需要陀螺仪,但如果您正在测量线性距离,则可以使用陀螺仪读数来控制设备的旋转不会太大。如果旋转太强,请让用户重新进行测量。

答案 1 :(得分:43)

通过将线性加速度积分两次得到位置,但错误很可怕。它在实践中毫无用处。

这是an explanation why (Google Tech Talk) 23:20。我强烈推荐这个视频。

类似的问题:


更新(2013年2月24日):@西蒙是的,如果您对运动有更多了解,例如行走的人和传感器在他的脚上,那么您可以做更多事情。这些被称为

域特定假设

如果假设不成立并且实施起来非常麻烦,那么它们会惨遭打破。然而,如果他们工作,你可以做有趣的事情。在室内定位中查看我的回答Android accelerometer accuracy (Inertial navigation)中的链接。

答案 2 :(得分:5)

您应该使用Simple iPhone motion detect中描述的Core Motion界面。特别是可以非常精确地跟踪所有旋转。如果你计划做一些与线性运动有关的事情,这是非常困难的事情。看看Getting displacement from accelerometer data with Core Motion

答案 3 :(得分:1)

我对此采取了一个裂缝并且放弃了(深夜,似乎没有到达任何地方)。这是针对Unity3d项目的。

如果有人想从我离开的地方继续学习,我很乐意详细说明这些内容的作用。

基本上在一些结果是假阳性之后,我想我会尝试使用低通滤波器对其进行滤波,然后尝试通过找到趋势去除反弹,然后(acc_x [i-1] + acc_x [I])/ 2。

看起来假阳性仍然来自倾斜,我试图将其移除..

如果此代码有用或引导您到某个地方,请告诉我们!

using UnityEngine;
using System.Collections.Generic;

/// <summary>
/// rbi.noli@gmail.com
/// </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);

    }
}

答案 4 :(得分:0)

这是answer。有人问过。

有一个名为RangeFinder的应用程序做同样的事情(在App Store中可用)。

答案 5 :(得分:0)

(acc_x [i-1] + acc_x [i])/ 2是低通滤波器,它是两个时间测量值之间的平均值

另见:http://www.freescale.com/files/sensors/doc/app_note/AN3397.pdf pag:3

答案 6 :(得分:0)

Navisens

https://navisens.com/#how-work

在此提出索赔-Navisens正在申请专利的技术以独特的方式处理加速度计和陀螺仪数据,从而找到您的手机。

试用了该演示应用程序,该应用程序主要用于在设置了初始位置和方向后使用定位服务或WiFi映射移动情况。

iOS SDK-https://github.com/navisens/iOS-SDK

Android SDK-https://github.com/navisens/Android-SDK

注意:这不是开源的