【问题标题】:iOS: Accurately determining energy of a bump from accelerometer outputiOS:从加速度计输出准确确定颠簸的能量
【发布时间】:2015-11-03 16:30:42
【问题描述】:

我正在创建一个音叉应用程序,您可以在其中将 iPhone 拍到另一只手的手掌或柔软的表面上以设置音叉。

所以我想检测每个“颠簸”中包含的能量

(编辑:删除了大量的 gumpf)

谁能帮我破解这个?

【问题讨论】:

标签: ios math accelerometer detect bump


【解决方案1】:

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

您使用标准方法以可能的最大频率 (100Hz) 触发回调,其中将包含瞬时加速度 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(
                         V.x * V.x  +
                         V.y * V.y  +
                         V.z * V.z
                         );
    }

    // 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;
    }
}

【讨论】:

  • 注意:这通常会输出一个介于 0 和 0.9 之间的值,用于敲击我的手掌。但是,在空中挥舞它会达到 1.5。
  • 我正在尝试使用此代码,但是我收到 DOUBLE_EMPTY 错误。你能解释一下 DOUBLE_EMPTY 是什么吗?谢谢
  • DOUBLE_EMPTY 是表示变量为空的值。使用类似 DBL_MAX 的东西,即:#define DOUBLE_EMPTY DBL_MAX
  • @Pi 你能解释一下你的代码在做什么吗,我正在尝试你的代码来检测道路颠簸,但我遇到了一些困难。请你帮帮我。
  • @Pi 你能帮我在我的应用程序中编码这个算法吗? open-sci.net/wiki/sealappexamplepotholes
【解决方案2】:

首先,你提出的问题:

A) 只需校准即可。站立加速度是重力的稳定拉力,任何突然的偏差都是由于撞击物体而增加的加速度。您还必须跟踪陀螺仪报告的方向变化,这样您就可以忽略重力突然转向新方向的情况。

B) 对加速度进行积分以获得速度的变化。手机质量的平方乘以二,就是能量(在静止框架中)。

C) 这个基本上是无法解决的。从理论上讲,如果情况是灵活的,则撞击产生的加速度将倾向于呈现为具有特征形状的尖峰状曲线,因此如果您有几个不在峰值上的点,您可以估计整个形状.但我怀疑设备太僵硬,采样太稀疏。对此您无能为力,除非硬件会为您集成加速功能,我对此表示怀疑(我不了解 iPhone)。

但无论如何,能源可能不是最好的衡量标准;用枕头敲击它可以传递与用锤子敲击它一样多的能量,但你不会期望音叉发出响亮的声音。峰值加速度可能会更好,但这仍然依赖于来自加速度计的良好数据。

你能用麦克风吗?试着记录它敲击膝盖时听到的声音,寻找普通声音中不存在的特征,比如,我不知道,大的低频幅度,宽频谱,甚至可能是案子。它可能仍然会对环境中的巨响做出一点反应,但那是相当现实的。

【讨论】:

  • 抱歉重新设计我的问题,让这个回答不再存在。我这样做是为了为将来搜索此内容的任何人创建更好的资源(通过更简洁的方式)。感谢您的回答!
【解决方案3】:

您需要的是卡尔曼滤波器。谷歌那句话;写一篇文章超出了诸如此类的互联网论坛的范围。有关于卡尔曼滤波器的书籍和书籍。

一个问题:iphone 界面并不是真正为您的需要而构建的。正是因为这个问题,我的雇主不得不与 Apple 合作以访问和处理内部结构。不,我不能说他们做了什么或项目是什么。

关于平放时的加速度计读数:它应该记录 1G 向上,而不是向下。没有办法感知重力。 (牛顿 POV:没有重力屏蔽之类的东西。相对论 POV:重力是一种虚构的力。)加速度计没有感应重力。它正在感应地球或桌子将加速度计向上推。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-01
    • 1970-01-01
    相关资源
    最近更新 更多