FFT を使用したパワースペ​クトル密度推定(PS​D)について

42 views (last 30 days)
拓也 矢田
拓也 矢田 on 22 Feb 2024
Commented: 拓也 矢田 on 6 Mar 2024
現在、立っている状態での重心動揺の信号におけるPSDを算出するためにFFTの解析をかけております。
指定した周波数帯域のPSDを取得するためにはどうすればよろしいでしょうか?指定する周波数帯域は、0-0.3Hz, 0.3-1.0Hz, 1.0-3.0Hzです。
現在のコードでは、0-0.3Hz帯域でとても大きい値が出てしまっており、原因が分からず質問させていただきました。
下記がコードとなります。
fs = 1000.00;
N = length(time);
fft_COP_X = fft(filt_COP_X);
fft_COP_Y = fft(filt_COP_Y);
fft_COP_X = fft_COP_X(1:N/2+1);
p_fft_COP_X = (1/(fs*N)) * abs(fft_COP_X).^2;
p_fft_COP_X(2:end-1) = 2*p_fft_COP_X(2:end-1);
freq = 0:fs/length(time):fs/2;
fft_COP_Y = fft_COP_Y(1:N/2+1);
p_fft_COP_Y = (1/(fs*N)) * abs(fft_COP_Y).^2;
p_fft_COP_Y(2:end-1) = 2*p_fft_COP_Y(2:end-1);
freq = 0:fs/length(time):fs/2;
Plow_fft_COP_X = sum(p_fft_COP_X(1:10));%0-0.3Hz 低周波数帯域 Power
Pmedium_fft_COP_X = sum(p_fft_COP_X(10:32));%0.3-1.0Hz 中周波数帯域 Power
Phigh_fft_COP_X = sum(p_fft_COP_X(32:92));%1.0-3.0Hz 高周波数帯域 Power
Plow_fft_COP_Y = sum(p_fft_COP_Y(1:10));%0-0.3Hz 低周波数帯域 Power
Pmedium_fft_COP_Y = sum(p_fft_COP_Y(10:32));%0.3-1.0Hz 中周波数帯域 Power
Phigh_fft_COP_Y = sum(p_fft_COP_Y(32:92));%1.0-3.0Hz 高周波数帯域 Power
ご教示いただけると幸いです。宜しくお願い致します。

Accepted Answer

covao
covao on 1 Mar 2024
Edited: covao on 2 Mar 2024
ご質問のコードを参考に、特定の周波数帯域でのパワースペクトル密度を算出しています。
(生成AIを用いています)
  • 周波数帯域の配列インデックスをfind関数を用いて設定しています。
  • 周波数帯域のパワースペクトル密度を平均値で算出
  • FFTに窓関数を設定していませんが、波形によっては検討が必要な場合もあります。
% Define the sampling frequency and time vector
fs = 1000.0;
t = 0:1/fs:20;
% Generate the signals (combination of 0.15Hz, 0.65Hz, and 2Hz)
filt_COP_X = sin(2*pi*0.15*t) + 0.5*sin(2*pi*0.65*t) + 0.2*sin(2*pi*2*t);
% Perform FFT analysis
N = length(filt_COP_X);
fft_COP_X = fft(filt_COP_X);
fft_COP_X = fft_COP_X(1:floor(N/2)+1);
p_fft_COP_X = (1/(fs*N)) * abs(fft_COP_X).^2;
p_fft_COP_X(2:end-1) = 2*p_fft_COP_X(2:end-1);
freq = linspace(0, fs/2, length(p_fft_COP_X));
% Calculate indices corresponding to specified frequency bands
idx_low = find(freq >= 0 & freq <= 0.3);
idx_medium = find(freq > 0.3 & freq <= 1.0);
idx_high = find(freq > 1.0 & freq <= 3.0);
% Calculate power in each frequency band
Plow_fft_COP_X = mean(p_fft_COP_X(idx_low));
Pmedium_fft_COP_X = mean(p_fft_COP_X(idx_medium));
Phigh_fft_COP_X = mean(p_fft_COP_X(idx_high));
% Output the results
disp(['PSD X: Low=', num2str(Plow_fft_COP_X), ', Mid=', num2str(Pmedium_fft_COP_X), ', High=', num2str(Phigh_fft_COP_X)] );
PSD X: Low=1.4286, Mid=0.17856, High=0.0099974
% Plot the power spectrum and original signals
figure;
% Original Signals
subplot(2, 1, 1);
plot(t, filt_COP_X);
title('Original Signal COP X');
xlabel('Time (s)');
ylabel('Amplitude');
grid on;
% Power Spectrum
subplot(2, 1, 2);
plot(freq, p_fft_COP_X);
title('Power Spectrum COP X');
xlabel('Frequency (Hz)');
ylabel('Power');
xlim([0, 3]); % Display up to 3Hz
grid on;
  5 Comments
Morio Nishigaki
Morio Nishigaki on 5 Mar 2024
データの切り出し方により、0Hz成分が出力されてしまうことはあり得ます。例えばサイン波で0~540度までの1.5波分を切り出してしまったとすると、プラス側の0Hz成分が多いので、FFTの出力には0Hz成分が出てきます(本来の時間切り出しなしのサイン波では0Hz成分がないにもかからわず)。
簡単に0Hz成分を除去したい場合は、信号Sのとき、S0 = S - mean(S); で求めたS0を使うとよいと思います。
質問の意図から外れていたらすみません。
拓也 矢田
拓也 矢田 on 6 Mar 2024
お忙しいところ、ご対応いただきありがとうございました。S0 = S - mean(S); で求めたS0を用いることによって、解決しました。大変勉強になりました。ありがとうございました。

Sign in to comment.

More Answers (0)

Categories

Find more on ビッグ データの処理 in Help Center and File Exchange

Products


Release

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!