分析加速度计数据特征并设计滤波器


14

我有大约32秒的基本行驶场景25MPH正常道路上的加速度计数据,还有大约7个坑洼和一段崎rough不平的道路。加速度计用双面胶带安装在我的汽车仪表板上。

问题:我获得了来自加速度计的所有嘈杂数据,我需要采取一种简单的方法来检测是否发生了坑洞事件。以下是时域和FFT的几个数据图。加速度计在GForce中进行测量

基本上,我希望我的arduino能够非常准确地知道发生了坑洞,并且没有使用研究生水平的数学和技术。

以100hz采样的加速度计在Z轴上具有一个简单的50HZ RC低通滤波器

Here is the CSV data for the 32 seconds of accelerometer readings TIME, GFORCE format:

http://hamiltoncomputer.us/50HZLPFDATA.CSV

更新:这是加速度计1000HZ的RAW全带宽,可以在Arduino上以最高采样率进行采样。直接CSV文件下载:大约112秒的数据

http://hamiltoncomputer.us/RAWUNFILTEREDFULLBANDWIDTH500HZ.csv

黑色轨迹为未经过滤的RAW加速度计原始数据:蓝色轨迹由带阻滤波器根据FFT,2HZ和12HZ支配的极限频率进行过滤。

http://img213.imageshack.us/img213/194/rollout.png

坑洞事件在时域中如下所示: 在此处输入图片说明

不确定FFT中10到​​15HZ的分量是什么,是实际的坑洼,还是车轮相对于道路的车轮跳动,还是汽车的共振频率?

FFT:

快速傅立叶变换

似乎是实际的坑洞事件,这是HPF @ 13HZ坑洞的主要特征似乎增强了

http://img69.imageshack.us/img69/8663/hpf13potholefft.png

我希望能够实时检测和计数坑洼

我认为悬挂应该比10到13 HZ慢很多,这会引起晕车,这是违反直觉的

更新:

根据AngryEE的建议,我使用了加速度计1000HZ的全部带宽以及在arduino上可以获得的最大采样率。

FFT:

FFT未过滤的数据全带宽

以下是坑洼事件及其周围一些颠簸和道路噪音的数据样本:

未归档的数据事件

添加了二极管包络检测器电路,输出看起来相同...加速计始终输出0至3.3V电压,而不是负电压... 在此处输入图片说明

更新:

在许多路试中,我在Z轴上的车中从未超过1.6G的最高45 MPH,我使用rand()生成伪随机Gforce加速。

我的想法是,如果我可以查看1到3秒的数据窗口,可以计算Z轴的位移,但是我担心加速度计的漂移以及积分误差。我不需要在这里甚至达到90%的精度,> 70%的精度就可以了,但是如果我一次只观察一到三秒钟的位移,那可以实时进行吗?这样,我可以看到位移是否大于1英寸,2英寸,5英寸。位移越大,凹凸或坑洼越粗糙:

您能否检查我是否做对了,我基本上在桌面上进行设置,使用rand()生成从-1.6到1.6 G的随机加速度,以模拟的50HZ采样率捕获3秒的数据

如果像运行* nix一样,我正在使用Windows.h中的Sleep()进行20ms延迟,50HZ采样率

我只是想看看代码是否适合您,我还没有做环形缓冲区,我对如何实现它有点困惑:注释掉的代码来自我正在为此工作的类,但我还不了解100%。循环缓冲区将允许连续移动数据窗口吗?

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <ctime> // USED BY RAND
#include <windows.h> // Used for delay


using namespace std;



#define SAMPLE_RATE   0.020 // Sample rate in Milliseconds
#define GRAVITYFT_SEC 32 // Gravity velocity 32 feet/sec
#define INCH_FOOT     12 // 12 inches in foot, from velocity to inch displacement calculation










int main(int argc, char *argv[])
{
    srand((unsigned)time(0)); // SEED RAND() for simulation of Geforce Readings

    // SIMULATING ACCELERATION READINGS INTO A CIRCULAR BUFFER

   // circular_buffer Acceleration; // Create a new Circular buffer for Acceleration

   // cb_init(&Acceleration, 150, 4); // Sampling @ 50HZ, 3 seconds of data = 150, size is float data of 4 bytes

    //Simulate a sample run of Acceleration data using Rand()

    // WE WILL BE SIMULATING "RANDOM" GEFORCE RATINGS using the rand() function constraining to -1.6 to 1.6 GFORCE 
    // These ratings are consistent with our road tests of apparently random vibration and Geforce readings not exceeding about 1.6 G's

    float Gforce[150]; // Random Geforce for 3 second window of data
    float velocity[150]; // Hold velocity information
    float displacement[150]; // Hold Displacement information


    float LO = -1.6; // Low GForce limit recorded from 6 road tests at different speeds
    float HI = 1.6; // High GForce limit recorded from 6 road tests at different speeds

    for(int i = 0; i < 150; i++) // 3 Second iwndow of random acceleration data
    {  
            Gforce[i] = LO + (float)rand()/((float)RAND_MAX/(HI-LO)); // Borrowed from Stackexchange : http://stackoverflow.com/questions/686353/c-random-float
            if( i == 0) // Initial values @ first Acceleration
            {
                velocity[i] = Gforce[i] * SAMPLE_RATE * GRAVITYFT_SEC; // Initial velocity
                displacement[i] = velocity[i] * SAMPLE_RATE * INCH_FOOT; // Initial Displacement
            }
            else
            {
                velocity[i] = velocity[i-1] + (Gforce[i] * SAMPLE_RATE * GRAVITYFT_SEC); // Calculate running velocity into buffer
                displacement[i] = displacement[i-1] +(velocity[i] * SAMPLE_RATE * INCH_FOOT); // Calculate running displacement into buffer
            }
            //cout << endl << Gforce[i]; // Debugging
            //cb_push_back(&Acceleration, &Gforce[i]);                   // Push the GeForce into the circular buffer


            Sleep(SAMPLE_RATE*1000); // 20mS delay simulates 50HZ sampling rate Sleep() expects number in mS already so * 1000

    }
    // PRINT RESULTS
    for (int j = 0; j < 150; j++)
            {
                cout << setprecision (3) << Gforce[j] << "\t\t" << velocity[j] << "\t\t" << displacement[j] << endl;
            }

    // READ THE BUFFER





    //cb_free(&Acceleration); // Pervent Memory leaks

    system("PAUSE");
    return EXIT_SUCCESS;
}

样品运行:

    GFORCE          FT/SEC          Inch Displacement Z axis

-0.882          -0.565          -0.136
0.199           -0.437          -0.24
-1.32           -1.29           -0.549
0.928           -0.691          -0.715
0.6             -0.307          -0.788
1.47            0.635           -0.636
0.849           1.18            -0.353
-0.247          1.02            -0.108
1.29            1.85            0.335
0.298           2.04            0.824
-1.04           1.37            1.15
1.1             2.08            1.65
1.52            3.05            2.38
0.078           3.1             3.12
-0.0125         3.09            3.87
1.24            3.88            4.8
0.845           4.42            5.86
0.25            4.58            6.96
0.0463          4.61            8.06
1.37            5.49            9.38
-0.15           5.39            10.7
0.947           6               12.1
1.18            6.75            13.7
-0.791          6.25            15.2
-1.43           5.33            16.5
-1.58           4.32            17.5
1.52            5.29            18.8
-0.208          5.16            20.1
1.36            6.03            21.5
-0.294          5.84            22.9
1.22            6.62            24.5
1.14            7.35            26.3
1.01            8               28.2
0.284           8.18            30.1
1.18            8.93            32.3
-1.43           8.02            34.2
-0.167          7.91            36.1
1.14            8.64            38.2
-1.4            7.74            40
-1.49           6.79            41.7
-0.926          6.2             43.2
-0.575          5.83            44.6
0.978           6.46            46.1
-0.909          5.87            47.5
1.46            6.81            49.2
0.353           7.04            50.8
-1.12           6.32            52.4
-1.12           5.6             53.7
-0.141          5.51            55
0.463           5.8             56.4
-1.1            5.1             57.6
0.591           5.48            59
0.0912          5.54            60.3
-0.47           5.23            61.5
-0.437          4.96            62.7
0.734           5.42            64
-0.343          5.21            65.3
0.836           5.74            66.7
-1.11           5.03            67.9
-0.771          4.54            69
-0.783          4.04            69.9
-0.501          3.72            70.8
-0.569          3.35            71.6
0.765           3.84            72.5
0.568           4.21            73.5
-1.45           3.28            74.3
0.391           3.53            75.2
0.339           3.75            76.1
0.797           4.26            77.1
1.3             5.09            78.3
0.237           5.24            79.6
1.52            6.21            81.1
0.314           6.41            82.6
0.369           6.65            84.2
-0.598          6.26            85.7
-0.905          5.68            87.1
-0.732          5.22            88.3
-1.47           4.27            89.4
0.828           4.8             90.5
0.261           4.97            91.7
0.0473          5               92.9
1.53            5.98            94.3
1.24            6.77            96
-0.0228         6.76            97.6
-0.0453         6.73            99.2
-1.07           6.04            101
-0.345          5.82            102
0.652           6.24            104
1.37            7.12            105
1.15            7.85            107
0.0238          7.87            109
1.43            8.79            111
1.08            9.48            113
1.53            10.5            116
-0.709          10              118
-0.811          9.48            121
-1.06           8.8             123
-1.22           8.02            125
-1.4            7.13            126
0.129           7.21            128
0.199           7.34            130
-0.182          7.22            132
0.135           7.31            133
0.885           7.87            135
0.678           8.31            137
0.922           8.9             139
-1.54           7.91            141
-1.16           7.16            143
-0.632          6.76            145
1.3             7.59            146
-0.67           7.16            148
0.124           7.24            150
-1.19           6.48            151
-0.728          6.01            153
1.22            6.79            154
-1.33           5.94            156
-0.402          5.69            157
-0.532          5.35            159
1.27            6.16            160
0.323           6.37            162
0.428           6.64            163
0.414           6.91            165
-0.614          6.51            166
1.37            7.39            168
0.449           7.68            170
0.55            8.03            172
1.33            8.88            174
-1.2            8.11            176
-0.641          7.7             178
-1.59           6.69            179
1.02            7.34            181
-0.86           6.79            183
-1.55           5.79            184
-0.515          5.46            186
0.352           5.69            187
0.824           6.22            188
1.14            6.94            190
-1.03           6.29            192
-1.13           5.56            193
0.139           5.65            194
0.293           5.84            196
1.08            6.53            197
-1.23           5.75            199
-1.1            5.04            200
-1.17           4.29            201
-0.8            3.78            202
-0.905          3.2             203
-0.0769         3.15            203
-0.323          2.95            204
-0.0186         2.93            205
Press any key to continue . . .

3
非常详细的写作。但是:编辑此内容以陈述一个特定的相对狭窄的问题将有助于获得有针对性的答案。
Anindo Ghosh

写了一个一般性的具体问题,我需要一种方法来从原始的嘈杂的加速度计信号中检测出一个坑洞。提取有用的功能或检测方法,使像arduino这样的微控制器可以实时检测到坑洼事件
zacharoni16 2013年

由于坑洞事件的发生速度要慢于与坑洞无关的振动,因此您应该对它进行LPF处理,并增强靠近坑洞的良好撞击感。移动平均滤波器可能能够做到这一点。为了使生活更轻松,您还可以考虑在LPF之前使用测量的abs值,因为您的坑洼似乎甚至具有单个包的特征,该包的包络振幅由汽车的振动频率调制而成。
Chintalagiri Shashank

更新信息,谢谢,我将研究移动平均线,悬浮共振似乎在12.5HZ左右???我会假设硬件中的LPF会有一个截止点
zacharoni16

提供一个很好的示例CSV文件或其他内容。您说上面的数据可用的地方似乎不能用作链接。
Olin Lathrop

Answers:


13

看起来可以通过相当直接的过滤来解决。这是您的原始数据:

要了解单个事件在此处适用的详细信息级别上发生了什么,这太多了。这只是从第二十六到第二十八的数据:

我本来以为可以通过低通滤波器,但这是行不通的,因为那里没有低频信号。高频信号的幅度反而上升。这是叠加在原件上的低通:

注意,这不是在坑坑洼洼的情况下很好地遵循信号的“平均值”。如果我们从原始信号中减去该平均值,则在事件期间,与该平均值相比,我们留下的偏移要高得多。换句话说,我们真正想要的是一个高通滤波器。我们将通过从原始信号中减去低通来实现此目的,因为这是我们到达的方式,但是在生产系统中,您将通过显式高通滤波来实现。无论如何,这是经过高通滤波的原始图像:

现在,这指出了一种检测事件的明显方法。事件期间的信号幅度比其他情况要大得多。我们可以通过计算RMS并应用一些低通滤波来检测到这一点:

放大整个数据,我们看到:

尽管我不知道该数据应该显示的是什么,但是这清楚地标识了数据中的五个事件。更仔细地查看事件,您会发现每个事件在峰值前后大约1秒都有一个低谷。这意味着如果仅对RMS信号进行阈值处理(因为现在还不够好),则可以做更多的事情。例如,一种简单的算法(无论哪种方式都在1秒内寻找相对于最低点的点的高度)应进一步降低背景噪声。关于同一件事的另一种说法是,区分该信号以寻找1秒内的上升。然后,通过双重峰检测到坑洼事件,这意味着高峰跟随低峰。

解决这个问题的另一种方法是使RMS信号带通。它已经被低通滤波了,但是由于您正在寻找陡峭斜率的突发事件,因此降低一些低频频率也应该可以减少背景噪声。

有很多方法可以从此处细化信号,但是希望我已经展示了如何获得至少第一遍有用的结果。

添加:

我很好奇寻找峰顶两侧的倾角效果如何,所以我尝试了一下。我使用了一个非线性滤波器,该滤波器从上一个图的RMS开始。每个点的值是它高于前一秒的最低点和下一秒的最低点的最小值。结果看起来不错:

5个峰中的最低峰比最高背景噪声高3倍以上。当然,这是假设这5个颠簸代表您要检测的事件,其余的则不是。

添加以回应评论:

我在时域中做了滤波器,所以我不直接知道频率响应。对于低通滤波器,我将输入信号与COS ^ 2滤波器内核进行卷积。如果我没记错的话,内核的半径(从中心到边缘的距离)为几百毫秒。我尝试了该值,直到情节看起来不错为止。为了对RMS进行低通滤波,我使用了相同的滤波内核,但是这次的半径约为1秒钟。我不记得了。进行实验,直到获得良好的结果。

非线性滤波器未检测到双峰。正如我所说,我发现了当前点与所有点中最低点之间的差值,以及1秒后所有点中的最低点之间的差值。然后我取了这两个中的最小值。

我使用的软件是为此目的而破解的程序。我已经有了读取和写入CSV文件的各种例程,因此我只需要编写过滤代码即可,这非常简单。其余的工作是由我已有的用于处理和绘制CSV文件的程序完成的。


哇,这是非常令人兴奋的结果,您可以用一种实用的方式来解释事情,我很高兴回到家开始从事这项工作!我很好奇您在HPF中使用了什么截止频率,而RMS信号的LPF截止看起来很完美。另外,您用来检测双峰的非线性滤波器是在matlab还是在设计应用程序中进行的?我也想尝试在硬件中进行设计,您得到的5个峰与我击中的5个坑坑是一致的,好结果!我有matlab,也一直在使用SciDavis
zacharoni16

@zach:我将尝试更新我的答案以解决您的一些问题。不幸的是,我的答案已转换为社区Wiki,因此我正在等待一个首先解决该问题的Mod。当您花时间在某件东西上时,这种CW东西真的很烂,然后突然您不再拥有它。
Olin Lathrop

@OlinLathrop编辑时将其转换回去。完成编辑后,您应该标记我将其还原。我现在会这样做,但是如果您不得不再次标记,请不要感到惊讶。关于抱怨CW的注意事项,我们必须每4-6个月还原一次CW,我想您是在谈论一种情况非常狭窄的情况,其中有如此多的编辑并且用户不希望成为CW,并且与应对Tony或其他情况相比,这是理想的标志,易于切割。:)
Kortuk

1
@Andrew:正如我在回答的最后一段中所说的,我有各种固定程序,可操纵CSV文件和库例程,从而使它们易于读写。在上面添加过滤代码既快速又容易。大多数过滤器只是多次执行的几行代码。像我上面所做的那样,对于一次关闭测试,由于一切都立即完成,因此无需有效使用处理器。例如,我在需要时调用COS函数,而不是建立表。
Olin Lathrop

1
@OlinLathrop我看到了您在答案中提到的内容,但我不知道您是否设置了一些自定义脚本,也许是matlab或运行它的东西,或者您做了什么。您能分享您的做法吗?听起来很迷人。您是使用固定图形库查看输出,只是在Excel中转​​储和绘图,还是使用gnuplot / octave或...?
akohlsmith

2

边缘检测坑可能会带来麻烦。汽车的振动包络是答案所在,因为传感器看到的实际振动频率要高得多。我会选择RMS到DC,它在大约15Hz或更高的频率下响应,并通过低通。


刚刚进行了另一次测试,其传感器带宽为1000HZ,并以与Arduino串行连接一样快的速度进行了采样。得到相似的结果。与2HZ和13HZ的主要频率相比,任何超过17HZ的频率都会很快消失,我仍然不知道9到13.5HZ的来源。加速度计安装在仪表板上,悬架在9HZ到13HZ时显然不会移动,否则我会疯狂地跳来跳去。我不确定您对RMS to DC的含义吗?
zacharoni16年

您的加速度计以某种方式连接到汽车。即使您用某种方式将东西用螺栓固定在起落架上,螺栓也可以抑制和放大频率。汽车是足以使事物以许多不同频率振动的足够复杂的野兽。有一些电路(可能还有数学算法)将交流信号转换为直流均方根值。搜索应该找到一个。通过将高频振动转化为振幅,可以帮助您生成信号的包络。
Chintalagiri Shashank

半波整流器(二极管)呢?但这会将一切转换为正峰值,坑洼事件拉-G还是没有问题?
zacharoni16

我不希望这会成为问题。您的振动幅度似乎足够高,可以起到主要作用。但是,考虑到您的信号,我建议进行全波整流,以免遗漏较小的坑洞。
Chintalagiri Shashank

Shashack添加了上面发布的信封电路,输出根本没有太大变化。我选择的RC时间常数大约为2mS,我以2mS的速度采样500次采样/秒加速度计的电压始终在0到3.3V之间,但...永远不会为负,所以二极管将不起作用?
zacharoni16

2

我建议不要尝试为“典型”坑洼提出一个内核,而不是寻找一个频域滤波器或一个阈值,并对其进行运行关联。它将被认为是模板匹配技术,并且似乎很适合微控制器平台。

请快速访问http://scribblethink.org/Work/nvisionInterface/vi95_lewis.pdf,以及DOBBS,STEVEN E.,NEIL M. SCHMITT和HALUK S. OZEMEK。“使用微型计算机上的实时相关性通过模板匹配进行QRS检测。” 临床工程杂志9.3(1984):197-212。

如果您在更强大的平台上,建议您旋转小波。


谢谢:),这似乎很难做到,还是我错过了什么?
zacharoni16

比简单的过滤器更难,但是完成后它更有可能实现您想要的效果!无论如何,请不要尝试在微控制器上实现它,直到您使其在Matlab或R之类的工具上工作
Scott Seidman

为了实时运行“滤波器”,您应该将其作为卷积处理,而不是在每个时间步均进行频域乘法。互相关(模板匹配的主要方法)将具有相同的精确运算,只是脉冲响应的时间尺度不会像卷积中那样倒置,我们将这种脉冲响应称为“模板” 。现在,您只需要弄清楚该模板是什么。
Scott Seidman

感谢您提供此答案,由于它似乎超出了我目前的技能水平,因此我将不得不做更多的研究和研究来实现它。我非常感谢您的努力
zacharoni16

2

另一种方法是计算信号的移动方差,以查看坑洼是否真的突出。这是一个用于移动方差滤波器的matlab函数,宽度为N个点-巧妙地(如果必须自己说的话)使用卷积进行计算

function y=movingvar(X,N)
% y=movingvar(X,N)
% Calculates N-point moving variance of  Vector X
% Highly recommend that N be odd (no error checking)
% Note: first and last N/2 points will be unreliable.
% Output will be a column vector.


X=X(:);
XSQR=X.*X;
convsig=ones(1,N);
y=(conv(convsig,XSQR)-(conv(convsig,X).^2)/N)/(N-1);

y=y(ceil(N/2):length(X)+floor(N/2));

这类似于标准差计算吗?
zacharoni16 2013年

是的,刚刚平方数
Scott Seidman

1

我最初的想法是,低通滤波器可能是错误使用的滤波器类型。坑洞本质上是一个高频事件,例如阶跃函数或方波。仅查看经过50Hz滤波的数据,我就认为您正在丢失有关坑洞的信息-看起来就像是相同的花键,对于坑洞事件没有明显区别。我将首先使用高通滤波器,然后使用频率高得多的低通滤波器。如果您的加速度计已经过低通滤波,则可以完全避免使用低通滤波器。

一旦获得了高通滤波后的数据,我认为一个适当地设置了阈值的简单比较器将挑选出由坑洼引起的加速度数据中的峰值,并让您对其进行计数。


我将取下RC 50HZ滤波器,然后加速度计将使用默认的500HZ或1000HZ LPF,该LPF应当足够高以产生机械振动。我将采样率从100HZ增加到1000HZ,并发布更多数据。感谢您的见解
zacharoni16 2013年

我使用了加速度计的全部带宽并进行了更快的采样,似乎正在获得相似的数据:(这令人困惑如何过滤和隔离坑洼和撞击事件
zacharoni16 2013年

我说过要使用高通滤波器,而不是低通滤波器。我希望看到未过滤数据的FFT。
AngryEE 2013年

加速度计具有内置的1000HZ LPF,我无法更改。我将尽快发布未过滤数据的FFT
zacharoni16

您无需更改它-您想要的高频率来自于遇到坑洼时的突然加速,而不是正常行驶时的轻微摇摆。您的信号似乎具有低频振动和几个主要的瞬时尖峰。您希望高频捕获快速的瞬态尖峰,但您想要拒绝恒定的低频。因此,您可能应该过滤掉50Hz或100Hz以下的所有内容。
AngryEE
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.