我正在研究用于计算弹簧质量系统(地震计)的自由周期振荡和阻尼比的一些信号。我使用Python作为主要的处理程序。我需要做的是导入此信号,解析信号并找到下降沿,然后从每个振荡的顶部返回一个峰值列表作为列表,以便我可以计算阻尼比。一旦我确定了数据集中振荡的位置,自由周期的计算就相当简单。
我大部分时间都处于挂起状态,如何解析列表,识别下降沿,然后捕获每个Z0..Zn元素。一旦我知道下降沿的位置,就可以相当容易地使用FFT计算振荡频率,但是如果我处理整个文件,那么在释放之前系统激励的大量能量有时会迫使算法开出表示近DC偏移的超低频率,而不是实际振荡。 (尤其是在阻尼比较高的情况下,可能只有四到五个可测量的篮板)。
有没有人对如何解决这个问题有所了解?现在,下面的代码使用屏幕截图中信号的任意指定值。但是我需要让代码计算这些值。此外,我还没有确定如何创建我的峰值列表来计算阻尼比h。我们非常欢迎您帮助我们共同解决这个问题。由于我有如此小的Stackoverflow声誉,我已将我的信号包含在以下链接的示例屏幕截图中: (男孩,我希望这有效!) 第谷的样本信号 - >
##########################################################
import os, sys, csv
from scipy import signal
from scipy.integrate import simps
import pylab as plt
import numpy as np
import scipy as sp
#
# code goes here that imports the data from the csv file into lists.
# One of those lists is called laser, a time-history list in counts from an analog-digital-converter
# sample rate is 130.28 samples / second.
#
#
# Find the period of the observed signal
#
delta = 0.00767 # Calculated elsewhere in code, represents 130.28 samples/sec
# laser is a list with about 20,000 elements representing time-history data from a laser position sensor
# The release of the mass and system response occurs starting at sample number 2400 in this particular instance.
sense = signal.detrend(laser[2400:(2400+8192)]) # Remove the mean of the signal
N = len(sense)
W = np.fft.fft(sense)
freq = np.fft.fftfreq(len(sense),delta) # First value represents the number of samples and delta is the sample rate
#
# Take the sample with the largest amplitude as our center frequency.
# This only works if the signal is heavily sinusoidal and stationary
# in nature, like our calibration data.
#
idx = np.where(abs(W)==max(np.abs(W)))[0][-1]
Frequency = abs(freq[idx]) # Frequency in Hz
period = 1/(Frequency*delta) # represents the number of samples for one cycle of the test signal.
#
# create an axis representing time.
#
dt = [] # Create an x axis that represents elapsed time in seconds. delta = seconds per sample, i represents sample count
for i in range(0,len(sensor)):
dt.append(i*delta)
#
# At this point, we know the frequency interval, the delta, and we have the arrays
# for signal and laser. We can now discriminate out the peaks of each rebound and use them to process the damping ratio of either the 'undamped' system or the damping ratio of the 'electrically damped' system.
#
print 'Frequency calcuated to ',Frequency,' Hz.'
答案 0 :(得分:1)
这是一个有点不同寻常的想法,我认为它可能相当强大,并且不需要大量的启发式和猜测。您拥有的数据质量非常高,并且符合已知的曲线,因此这里有很多帮助。在这里,我假设"好的部分"您的曲线的形式为:
V = a * exp(-γ * t) * cos(2 * π * f * t + φ) + V0 # [Eq1]
V
:电压t
:时间γ
:阻尼常数f
:频率a
:起始幅度φ
:开始阶段V0
:DC offset 首先,calculate the derivative numerically。由于数据质量很高,噪音不会对事物造成太大影响。
电压导数V_deriv
具有与原始数据相同的形式:相同的频率和阻尼常数,但具有不同的相位ψ
和幅度b
,
V_deriv = b * exp(-γ * t) * cos(2 * π * f * t + ψ) # [Eq2]
好处是会自动消除你的DC偏移。
替代方案:此步骤并非完全需要 - 偏移是曲线拟合的一个相对较小的复杂因素,因为您可以通过平均值始终提供对偏移的良好猜测整条曲线。如果您不使用衍生产品,权衡就是获得更好的信噪比。
现在考虑导数的曲线(如果跳过最后一步,则考虑原始曲线)。从最右边的数据点开始,然后向左跟随曲线尽可能多的振荡,直到达到幅度大于某个幅度阈值A
的振荡。您希望找到包含一个具有良好信噪比的振荡的曲线部分。
如何确定幅度阈值很难说。这取决于您的传感器有多好。我建议将此作为稍后调整的参数。
现在你已经捕获了一个振荡,你可以做很多简单的事情:估计频率f
和阻尼常数γ
。使用这些初始估计值,您可以执行此振荡右侧所有数据的nonlinear curve fit (包括振荡本身)。
如果您使用衍生物,您所适合的功能是 [Eq2] ;如果您使用原始曲线,则 [Eq1] (但它们是无论如何都是相同的功能,所以相当有争议。)
为什么需要这些初步估算?对于适合衰减波的非线性曲线,对参数进行良好的初始猜测至关重要,尤其是频率和阻尼常数。其他参数相对不太重要(至少这是我的经验),但在这里,你可以如何获得其他参与以防万一:
0
;如果您从最小值开始,则为π
。1
。曲线拟合在这一点上应该非常好 - 你可以说因为discrepancy between your curve and the fit非常低。现在的诀窍是尝试将曲线的域增加到左侧。
如果你保持在正弦曲线区域内,曲线拟合应该保持相当好(你如何判断"善良"需要一些实验)。但是,一旦达到曲线的平坦区域,错误就会开始急剧增加,参数也会开始偏离。这可用于确定" good"数据结束。
你不必逐点做到这一点 - 效率很低。 binary search在这里应该可以很好地工作(可能是"片面的"变体)。
您不必遵循这个确切的程序,但基本要点是您可以从最右边开始对一小部分数据进行一些分析,然后逐渐增加时域直到你发现错误变得越来越大而不是更小,直到你应该这样做。
此外,您还可以结合不同的启发式方法,看看它们是否相互一致。如果他们不这样做,那么它可能是一个相当粗略的数据点,需要一些人工干预。
请注意,我在上面概述的算法的一个特殊优势是,您将获得所需的结果(阻尼常数和频率)作为过程的一部分,以及不确定性估计。
我忽略了大部分血腥的数学和算法细节,以便提供一般概述,但如果需要,我可以提供更多细节。