iOS:准确地确定加速计输出的碰撞能量

我正在创build一个音叉应用程序,在那里您可以将iPhone拍到另一只手的手掌上,或者在柔软的表面上进行设置,以便设置叉子。

所以我想检测每个“凹凸”所包含的能量,

(编辑:删除了一吨gumpf)

谁能帮我破解这个吗?

感谢freenode的#math频道的一个向导(感谢Igor),我有一个非常好的工作解决scheme。

您可以使用标准方法以最大频率(100Hz)触发callback,这将包含瞬时加速度x,y,z值。

我会让代码自己说话,好的代码应该总是为自己说话。

typedef struct { double x,y,z; } vec_d3; #define RECENT_COUNT 10 #define SMOOTH_IP( x, x_new, fac ) x = fac * x + ( 1. - fac ) * x_new - (void) accelerometer: (UIAccelerometer *) accelerometer didAccelerate: (UIAcceleration *) acceleration { // smooth incoming acceleration values static vec_d3 smooth = { DOUBLE_EMPTY, 0, 0 }; { if ( smooth.x == DOUBLE_EMPTY ) { smooth.x = acceleration.x; smooth.y = acceleration.y; smooth.z = acceleration.z; return; } SMOOTH_IP( smooth.x, acceleration.x, 0.9 ); SMOOTH_IP( smooth.y, acceleration.y, 0.9 ); SMOOTH_IP( smooth.z, acceleration.z, 0.9 ); } // keep track of last k smoothed acceleration values static vec_d3 recent[ RECENT_COUNT ]; { static int ptr = 0; static BOOL gotEnoughData = NO; recent[ ptr ] = smooth; ptr++; if ( ptr == RECENT_COUNT ) { ptr = 0; gotEnoughData = YES; } // return if array not filled yet if ( ! gotEnoughData ) return; } // get the resultant variation in acceleration over the whole array double variation; { vec_d3 min = smooth, max = smooth; for ( int i=0; i < RECENT_COUNT; i++ ) { min.x = MIN( min.x, recent[ i ].x ); min.y = MIN( min.y, recent[ i ].y ); min.z = MIN( min.z, recent[ i ].z ); max.x = MAX( max.x, recent[ i ].x ); max.y = MAX( max.y, recent[ i ].y ); max.z = MAX( max.z, recent[ i ].z ); } vec_d3 V = (vec_d3) { .x = max.x - min.x, .y = max.y - min.y, .z = max.z - min.z }; variation = sqrt( Vx * Vx + Vy * Vy + Vz * Vz ); } // smooth it static double var_smoothed = DOUBLE_EMPTY; { if ( var_smoothed == DOUBLE_EMPTY ) { var_smoothed = variation; return; } SMOOTH_IP( var_smoothed, variation, 0.9 ); } // see if it's just passed a peak { static double varSmoothed_last = DOUBLE_EMPTY; if ( varSmoothed_last == DOUBLE_EMPTY ) { varSmoothed_last = var_smoothed; return; } static double varSmoothed_preLast = DOUBLE_EMPTY; if ( varSmoothed_preLast == DOUBLE_EMPTY ) { varSmoothed_preLast = varSmoothed_last; varSmoothed_last = var_smoothed; return; } #define THRESHOLD_IMPULSE .15 if ( varSmoothed_last > varSmoothed_preLast && varSmoothed_last > var_smoothed && varSmoothed_last > THRESHOLD_IMPULSE ) { LOG ( @"PotPeak @ %f", varSmoothed_last ); // hit a peak at imp_last [self peakedWithImpulse: varSmoothed_last ]; } varSmoothed_preLast = varSmoothed_last; varSmoothed_last = var_smoothed; } } 

首先,你问的问题:

A)只需校准。 站立加速度是重力的稳定拉力,任何突然的偏差都是由于撞击而增加的加速度。 您还必须跟踪陀螺仪报告的方位变化 ,以便您可以忽视重力突然转向一个新的方向。

B)积分加速度以获得速度变化。 这个平方,电话的质量乘以二分之一就是能量(在静止的框架中)。

C)这个基本上是无法解决的。 从理论上讲,如果情况是灵活的,冲击的加速度往往会呈现为具有特征形状的尖峰状曲线,因此,如果您有一对不在峰顶的点,则可以估计整个形状。 但是我怀疑这个设备太僵硬了,采样太稀疏了。 没有什么可以做这件事的,除非硬件会为你整合加速,我怀疑(我不认识iPhone)。

但是,无论如何,能源可能不是最好的措施; 你可以用一把榔头用枕头敲打它,但是你不会指望音叉响得很响。 峰值加速度可能会更好,但仍然依赖于加速计的良好数据。

你可以使用麦克风吗? 尝试logging当你敲击膝盖时听到的东西,并寻找普通声音中不存在的特征,例如,我不知道,大的低频振幅,宽频谱,甚至是特征谐振案件。 它可能仍然会对环境中的巨大噪音做出一些响应,但这是相当现实的。

你想要的是卡尔曼滤波器。 Google那句话; 写一个超出了这样的互联网论坛的范围。 有卡尔曼滤波器的书籍和书籍。

一个问题:iphone界面并不是真正为你所需要的而构build的。 我的雇主不得不与苹果公司一起工作,正因为这个问题,才能进入内部。 不,我不能说他们做了什么或者是什么项目。

关于加速度计读数持平时:应该注册1G,而不是下降。 没有办法来感觉重力。 (牛顿POV:没有重力盾这样的东西,相对论POV:重力是一个虚构的力量。)加速度计不感觉重力。 它感应着地球或桌子向上推动加速计。