如何使用加速度计检测iPhone在空间中的移动?

时间:2010-04-20 11:43:13

标签: iphone drawing accelerometer

我正在尝试创建一个应用程序来检测您使用加速度计使用iPhone制作的形状。 例如,如果您用手拿着iPhone绘制一个圆圈,该应用程序将能够在屏幕上重绘它。 这也适用于正方形,甚至更复杂的形状。 我见过这样做的唯一应用示例是AirPaint(http://vimeo.com/2276713),但它似乎无法实时完成。

我的第一个尝试是对加速度计的X和Y参数应用低通滤波器,并使指针移动到这些值,与屏幕的大小成比例。 但这显然没有用,我的准确度非常低,如果我摇动设备,它也会使指针移动......

有关于此的任何想法? 您认为加速度计数据是否应该这样做?或者我应该考虑使用其他数据,例如指南针?

提前致谢!

4 个答案:

答案 0 :(得分:10)

好的,我找到了似乎有效的东西,但我仍然有一些问题。 以下是我的工作方式(承认设备是垂直的):

1 - 我有我的默认x,y和z值 2 - 我使用低通滤波器从这些数据中提取重力矢量 3 - 我从每个x,y和z中减去归一化的重力矢量,得到运动加速度 4 - 然后,我将这个加速度值与时间相结合,所以我得到了速度 5 - 我再次将这个速度与时间相结合,并找到一个位置。

以下所有代码都在加速度计中:didAccelerate:我的控制器的委托。 我试图根据我发现的位置移动球。 这是我的代码:

NSTimeInterval interval = 0;
NSDate *now = [NSDate date];
if (previousDate != nil)
{
    interval = [now timeIntervalSinceDate:previousDate];
}
previousDate = now;

//Isolating gravity vector
gravity.x = currentAcceleration.x * kFileringFactor + gravity.x * (1.0 - kFileringFactor);
gravity.y = currentAcceleration.y * kFileringFactor + gravity.y * (1.0 - kFileringFactor);
gravity.z = currentAcceleration.z * kFileringFactor + gravity.z * (1.0 - kFileringFactor);
float gravityNorm = sqrt(gravity.x * gravity.x + gravity.y * gravity.y + gravity.z * gravity.z);

//Removing gravity vector from initial acceleration
filteredAcceleration.x = acceleration.x - gravity.x / gravityNorm;
filteredAcceleration.y = acceleration.y - gravity.y / gravityNorm;
filteredAcceleration.z = acceleration.z - gravity.z / gravityNorm;

//Calculating velocity related to time interval
velocity.x = velocity.x + filteredAcceleration.x * interval;
velocity.y = velocity.y + filteredAcceleration.y * interval;
velocity.z = velocity.z + filteredAcceleration.z * interval;

//Finding position
position.x = position.x + velocity.x * interval * 160;
position.y = position.y + velocity.y * interval * 230;

如果我执行此操作,我会得到相当好的值,我的意思是我可以根据我的动作看到加速度变为正值或负值。 但是当我试图将这个位置应用到我的球视图中时,我可以看到它正在移动,但是在一个方向上比另一个方向更有利。这意味着,例如,如果我用我的设备绘制圆圈,我将看到球描述朝向屏幕左上角的曲线。 类似的东西:http://img685.imageshack.us/i/capturedcran20100422133.png/

您对发生的事情有什么想法吗? 提前谢谢!

答案 1 :(得分:7)

问题是你无法将加速度两次整合到位置。不知道初始位置和速度。还记得你在学习集成时在学校添加的+ C术语吗?当你到达位置时它是一个ct + k术语。这很重要。那是在你考虑到你要获得的加速度数据被量化和平均之前,所以你实际上并没有集成设备的实际加速度。当两次集成时,这些错误最终会很大。

仔细观察AirPaint演示,你会发现这种情况正好发生,渲染的形状与移动的形状明显不同。

即使是具有一些位置和速度感应功能的设备(例如Wiimote)也无法进行手势识别。这是一个棘手的问题,人们为了解决这些问题而向AILive这样的公司付出了很多钱。

话虽如此,如果他们的大规模特征不同,你可以很容易地区分某些类型的手势。如果设备已经在六个角度范围中的每一个中接收到加速度,则可以检测到圆(例如)。您可以通过空中滑动iphone并摇动它来检测。

要说明圆形和正方形之间的区别会更加困难。

答案 2 :(得分:2)

您需要查看加速度与速度和速度的关系。我的脑子里现在只有一个小屁,但我确信它是不可或缺的......你想要在时间上加速加速。维基百科应该帮助你掌握数学知识,我相信有一个好的图书馆可以帮助你。

请记住,虽然加速度计不够完美,也不够快。真的突然的动作可能不会那么好。但是为了轻轻地在空中画画,它应该可以正常工作。

答案 3 :(得分:2)

好像你在用瞬时加速度减法之前归一化你的重力矢量。这将保持相对方向,但删除任何相对比例。我测试的最新设备(当然不是一个Idevice)以大约-9.8的速度返回重力,这可能被校准为m / s。假设没有其他加速度,如果你要将其标准化然后从过滤后的通道中减去它,你最终会得到当前加速度-8.8而不是0.0f;

2个选项: - 你可以在滤波器通过后减去重力矢量 - 捕获初始加速度矢量长度,标准化加速度和重力矢量,用加速点和重力法线缩放加速度矢量。

还值得记住考虑设备的方向。