49

我想构建一个应用程序,使用 Gyro+Accelerometer 计算 iPhone 行驶的准确距离(不是长距离)。这里不需要GPS。

我应该如何解决这个问题?

4

7 回答 7

83

这个问题背后的基本微积分在表达式中

在此处输入图像描述

(以及 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];

包含在时间 0、dt、2*dt、3*dt、... (n-1)*dt 处从测量开始到结束的 x 加速度值。

要找到总位移,您只需执行

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

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

于 2011-07-11T08:41:17.887 回答
47

您可以通过两次积分线性加速度来获得位置,但误差很可怕。在实践中是没有用的。

这是23:20的原因(Google Tech Talk)的解释。我强烈推荐这个视频。

类似的问题:


更新(2013 年 2 月 24 日):@Simon 是的,如果您对运动有更多了解,例如一个人走路并且传感器在他的脚上,那么您可以做更多。这些被称为

     特定领域的假设

如果假设不成立并且实施起来非常麻烦,它们就会惨遭破坏。不过,如果它们有效,您可以做一些有趣的事情。请参阅我在室内定位时的答案Android 加速度计精度(惯性导航)中的链接。

于 2011-07-11T10:03:49.497 回答
5

您应该使用简单 iPhone 运动检测中描述的 Core Motion 接口。特别是所有旋转都可以非常准确地跟踪。如果你打算做一些与线性运动相关的事情,这是非常困难的事情。查看使用 Core Motion 从加速度计数据中获取位移

于 2011-07-11T08:30:48.837 回答
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);

    }
}
于 2015-05-19T05:50:23.190 回答
0

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

也看看这里:http: //www.freescale.com/files/sensors/doc/app_note/AN3397.pdf pag:3

于 2014-05-07T19:28:31.940 回答
0

纳维森斯

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

这里是索赔 - Navisens 正在申请专利的技术以独特的方式处理加速度计和陀螺仪数据来定位您的手机。

试用了演示应用程序,一旦设置了初始位置和方向,该应用程序主要用于在没有定位服务或 WiFi 的情况下绘制运动。

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

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

注意:这不是开源的

于 2019-12-17T15:21:18.107 回答
-1

这是答案。之前有人问过。

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

于 2011-07-11T08:08:52.410 回答