我想制作一个应用程序,使用陀螺仪和加速度计计算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加速度值,每隔dt时间间隔采集一次,时间点分别为0, dt, 2*dt, 3*dt, ... (n-1)*dt。
要计算总位移,只需要执行以下操作:
dl=sqrt(dx*dx + dy*dy + dz*dz);
对于这个问题,陀螺仪并非必需品,但如果你要测量线性距离,你可以使用陀螺仪数据来控制设备的旋转幅度是否过大。如果旋转幅度太大,则让用户重新进行测量。
你可以通过两次线性加速度积分来获取位置,但是误差非常大,在实践中没有用处。
这里是一个解释 (Google Tech Talk),在23:20的时候。我强烈推荐这个视频。
类似的问题:
更新(2013年2月24日):@Simon 是的,如果您对运动有更多了解,例如一个人走路,传感器在他的脚上,那么您可以做更多的事情。这些被称为
领域特定假设。
如果这些假设不成立,则它们会失败并且实现起来可能非常麻烦。尽管如此,如果它们有效,则可以做一些有趣的事情。请参阅我的答案中的链接Android加速度计准确性(惯性导航)用于室内定位。
您应该像Simple iPhone motion detect中描述的那样使用Core Motion接口。特别是所有旋转都可以非常精确地跟踪。如果您计划做与线性运动相关的事情,这将是非常困难的。请参阅Getting displacement from accelerometer data with Core Motion。
我尝试过这个并放弃了(夜里晚了,似乎没有进展)。 这是为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);
}
}
(acc_x[i-1]+acc_x[i])/2 是一个低通滤波器,它是在时间内两个测量值之间的平均值
还可以看这里:http://www.freescale.com/files/sensors/doc/app_note/AN3397.pdf 第3页
Navisens。
https://navisens.com/#how-work
这里是声明 - Navisens 的专利技术以独特的方式处理加速度计和陀螺仪数据,以定位您的手机。