检测iPhone被碰撞的情况

11

我想要检测iPhone是否被撞击过... 最好监听陀螺仪/加速度计,并判断它移动的速度或者是否突然停止移动。

事实上,如果设备移动了然后突然停止,怎么判断呢?

这个答案很好,但是相反的iOS:从加速度计输出准确确定碰撞的能量 - 它平滑了运动,而我想要检测的是突然的运动。

另外,3GS手机是否同时具有陀螺仪和加速度计?

使用代码更新

根据苹果文档http://developer.apple.com/library/iOS/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/MotionEvents/MotionEvents.html#//apple_ref/doc/uid/TP40009541-CH4-SW26

从加速度数据中分离瞬时运动 如果您正在使用加速度计数据来仅检测设备的瞬时运动,则需要能够将运动的突然变化与重力的恒定影响隔离开来。您可以使用高通滤波器来做到这一点。

清单4-6显示了简化的高通滤波器计算。上一个事件中的加速度值存储在类的accelX、accelY和accelZ成员变量中。此示例计算低通滤波器值,然后从当前值中减去它以获得仅瞬时运动的分量。

清单4-6 从加速度数据获取瞬时运动部分

define kFilteringFactor 0.1

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    // Subtract the low-pass value from the current value to get a simplified high-pass filter
    accelX = acceleration.x - ( (acceleration.x * kFilteringFactor) + (accelX * (1.0 - kFilteringFactor)) );
    accelY = acceleration.y - ( (acceleration.y * kFilteringFactor) + (accelY * (1.0 - kFilteringFactor)) );
    accelZ = acceleration.z - ( (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor)) );

   // Use the acceleration data.
}

我该如何使用加速度数据来判断是否检测到瞬时运动?


注意:此示例已被弃用,因为iOS使用CoreMotion框架。 - TimM
5个回答

4
我使用了以下代码:
#define kUpdateFrequency    100.0
#define kFilteringFactor    0.1
float accelZ;
int spikeZCount = 0; 

[[UIAccelerometer sharedAccelerometer] setUpdateInterval:1.0 / kUpdateFrequency];
    [[UIAccelerometer sharedAccelerometer] setDelegate:self];

- (void) accelerometer: (UIAccelerometer *) accelerometer didAccelerate: (UIAcceleration *) acceleration 
{
    accelZ = acceleration.z - ( (acceleration.z * kFilteringFactor) + (accelZ * (1.0 - kFilteringFactor)) );

    if (accelZ > 0.0f)
    {
        if (spikeZCount > 9)
        {
            //  NSLog(@"SPIKE!");
            [[UIAccelerometer sharedAccelerometer] setDelegate:nil];

            [self isBumped];
        }
        else
        {
            spikeZCount++;
            //  NSLog(@"spikeZCount %i",spikeZCount);
        }
    }
    else
    {
        // NSLog(@"spikeZCount Reset");
        spikeZCount = 0;
    }
}

1
为什么你只使用acceleration.z? - Michael
我有同样的问题。 - ßiansor Å. Ålmerol

4

从之前的答案中,我进行了一些概括,得出了以下结果,它可以很好地工作:

// Isolate Instantaneous Motion from Acceleration Data
// (using a simplified high-pass filter)
CMAcceleration acceleration = accelerometerData.acceleration;
float prevAccelX = w_self.accelX;
float prevAccelY = w_self.accelY;
float prevAccelZ = w_self.accelZ;
w_self.accelX = acceleration.x - ( (acceleration.x * kFilteringFactor) +
                                   (w_self.accelX * (1.0 - kFilteringFactor)) );
w_self.accelY = acceleration.y - ( (acceleration.y * kFilteringFactor) +
                                   (w_self.accelY * (1.0 - kFilteringFactor)) );
w_self.accelZ = acceleration.z - ( (acceleration.z * kFilteringFactor) +  
                                   (w_self.accelZ * (1.0 - kFilteringFactor)) );

// Compute the derivative (which represents change in acceleration).
float deltaX = ABS((w_self.accelX - prevAccelX));
float deltaY = ABS((w_self.accelY - prevAccelY));
float deltaZ = ABS((w_self.accelZ - prevAccelZ));

// Check if the derivative exceeds some sensitivity threshold
// (Bigger value indicates stronger bump)
float sensitivityThreshold = 1.0;
float bumpVectorLength = sqrtf(deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ);
if ( bumpVectorLength > sensitivityThreshold ) {
    NSLog( @"BUMP:  |%.3f, %.3f, %.3f| = %.3f", deltaX, deltaY, deltaZ, bumpVectorLength);
}

2
w_self.accelX/Y/Z是什么的引用? - Jude Michael Murphy
@JudeMichaelMurphy w_self 是对 self 的弱引用(用于实现 accelerometer:didAccelerate: 代理方法的对象)。w_self.accelX 是上一次调用代理方法时计算出的加速度 x 分量的值。(w_self.accelYw_self.accelZ 同理) - Chris
@Chris 这适用于确定道路质量吗? - ßiansor Å. Ålmerol
1
@ßiansorÅ.Ålmerol 这很可能取决于您对道路质量的定义。也许可以采用某种变体。也许测量颠簸的频率(即颠簸发生的频率)可能有效,但我怀疑这不能单独使用。 - Chris

4
适当的方法是在传感器融合后使用高通滤波器和线性加速度。请查看Android的Sensor.TYPE_LINEAR_ACCELERATION这里。据我所知,iPhone没有传感器融合。正如Kay所指出的那样,Core Motion提供了传感器融合,请参见下面的评论。如果您有兴趣,这里有一个关于传感器融合的优秀视频video on sensor fusion,从32:10开始。一个有点混乱的解决方法是使用高通滤波器并使用加速度计数据而不进行传感器融合。如果您将手机撞到某物上,陀螺仪数据也可能会出现峰值,但根据我的经验,加速度计更好,因为它们可以检测到突然的速度变化。这很混乱,因为您可以通过快速旋转手机来欺骗它。

1
iPhone自2010年7月(iOS 4.0)起就拥有传感器融合技术。该框架名为Core Motion。 - Kay
@Kay 谢谢,我不知道!你能提供一个链接吗,明确说明它具有传感器融合功能吗?我也很想知道它是如何实现的(卡尔曼滤波器?)。 - Ali
2
http://developer.apple.com/library/iOS/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/MotionEvents/MotionEvents.html#//apple_ref/doc/uid/TP40009541-CH4-SW26我认为这不是卡尔曼滤波器,因为使用自己实现的卡尔曼滤波器并进行设备特定校准时结果更好(这可能会在其他设备上运行应用程序时导致问题)。苹果的滤波器可能是一种补充或平衡滤波器。 - Kay

2

0

这取决于不同的情况:

  1. 手机是否在空中自由落下(或被扔掉),即您不再握住它。
  2. 如果自由落体,我猜这取决于手机撞击障碍物时的入射角。如果手机恰好落在其中一面上,则陀螺仪不会报告旋转。但这将很难确定。
  3. 您所撞击的材料的弹性。

我同意Ali关于加速度的回答,但不适用于投掷。但无论如何,请记住,一个鼓励用户扔iPhone的应用程序将很难获得应用商店的批准,-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接