非线性系统 - 计算两个正弦波之间的相移 - 傅立叶和希尔伯特

时间:2016-12-12 12:34:21

标签: matlab fft phase

编辑:根据建议使用的xcorr函数得到的结果为零,这个数据更可能代表一个非线性系统,而不是我原先想到的。在这种情况下,ab的表达式被简化,并不一定完全与实际数据进行比较。此外,相移d的值不能再被认为是常数。

我有两个原始数据阵列,它们对应于同一(已知)频率随时间推移的两个正弦信号,其中一个相移了未知量的增量d。这些信号可以描述为:

a = A*sin(wt)
b = B*sin(wt+d)

w = 2*pi*fA, B的幅度分别为ab

这里的目标是评估给定信号随时间的相移。这可以是瞬时值或多个循环的平均值(与循环总数相比较小,即在f = 150Hz时,10秒测试相当于1500个循环)。

我知道有很多方法可用于评估此类问题,而且许多其他用户已经就此问题提出/回答了问题。下面的方法包含原始帖子的链接和我已实现的代码。我目前遇到的问题是:

  1. 如何在评估相位后解释相移(对于我的情况,相移通常被引用为在多个周期内保持相当稳定的时间点的单个正数)。
  2. 不同方法之间的价值差异
  3. 我还有其他方法吗?
  4. 我的数据ab的大小均为[1 x 399],涵盖20个周期。这只是预期数据的一小部分,我用它来测试不同的方法。期望至少10度的相移是合理的,尽管不确切地知道:

    傅立叶变换

    来源:How do I calculate the phase shift between two sinusoidal signals?

    fft_a = fft(a);
    fft_a = fft_a(2:end);       %Drop the first point
    angle_a = angle(fft_a);     %Angle the result
    
    fft_b = fft(b);
    fft_b = fft_b(2:end);       %Drop the first point
    angle_b = angle(fft_b);     %Angle the result
    
    ps1 = rad2deg(abs(angle_a - angle_b));     %Phase shift calculation
    

    使用此方法 - 我可以做些什么来消除开头/结尾的尖峰?我是否需要将变换设置为执行超过一定数量的点?

    然后我如何绘制相移与时间的关系,因为这个结果现在肯定在频域?

    希尔伯特变换

    来源:Identifying phase shift between signals

    ha = hilbert(a);                 %Hilbert transform
    hb = hilbert(b);
    
    ps2 = rad2deg(angle(hb./ha));    %Phase shift calculation
    

    这里随着时间的推移产生的相移既是负的也是正的,并且似乎像波形一样振荡。它的形状相当一致但又一次,我不知道如何解释结果。取相移的abs值后,结果现在在0到30度之间变化。

    图表:Hilbert Phase Shift Time Plot

    对于这两种方法,我如何使用结果将相移称为在一组周期内的单个值?取mean似乎不是一个确切的方法。

    为了快速计算我使用的相移:

    ps3 = rad2deg(acos(dot(a,b)/(norm(a)*norm(b))))    %Norm product method
    
    ps3 =
    
        11.8289
    

    我对这种类型的分析相当新,在Matlab上有点新手,所以任何更正/指导都会非常感激。

    编辑:了解这是一个非线性系统,可以使用哪些方法来最好地评估相移?

2 个答案:

答案 0 :(得分:3)

如何进行互相关?

使用互相关,您应该在移位中找到绝对最大值,因为当您移动正确数量的两个信号中的一个时,两个将变为相同。

d

它应该适用于常量<div id="loginPanel"> <div class="text"> <p class="loginText">Welcome</p> <p class="loginText">Log-in to place your order</p> </div> <form method="post" action="http://coreprint.net/aspire/Login,loginForm.sdirect" id="loginForm"> <div style="display:none;" id="loginFormhidden"> <input type="hidden" name="formids" value="If_0,If_2,username,password,loginButton,If_4" /> <input type="hidden" name="seedids" value="" /> <input type="hidden" name="submitmode" value="" /> <input type="hidden" name="submitname" value="" /> <input type="hidden" name="If_0" value="F" /> <input type="hidden" name="If_2" value="F" /> <input type="hidden" name="If_4" value="F" /> <input type="hidden" name="Hidden" id="Hidden" value="X" /> </div> <table> <tr> <td>Username</td> <td><input type="text" name="username" value="" id="username" size="30" /></td> </tr> <tr> <td>Password</td> <td><input type="password" name="password" value="" id="password" size="30" /></td> </tr> </table> <a href="javascript:tapestry.form.submit('loginForm', 'loginButton');" id="loginButton" class="bLink"> <img src="images/submit.png" alt="submit"> </a> <input type="submit" style="width:0;height:0;border:0"/> </form> </div> ,我不确定是否为变量。

答案 1 :(得分:0)

我的意思是:

clc

% Noiseless example data
x = 0:0.1:40*pi;

p1 = deg2rad(+5.74);
p2 = deg2rad(-4.28);

y = sin(x + p1);
z = sin(x + p2);

input = rad2deg(p1 - p2) % display injected phase difference


% Retrieve values using no assumptions 

options = optimset('TolX'   , 0,...
                   'TolFun' , 0, ...
                   'display', 'off');

p1 = fminsearch(@(q) sum( (y - sin(x + q)).^2 ), 0, options);
p2 = fminsearch(@(q) sum( (z - sin(x + q)).^2 ), 0, options);

computed = rad2deg(p1 - p2) % display computed phase difference

对于此示例,输出为:

input =
    1.002000000000000e+001
computed =
    1.002000000000000e+001

但是,正如所指出的,这种方法相当简单,当噪声发挥作用时,准确度会比其他方法下降得快得多。