I have time series with accelerometer data which I want to integrate to velocity and position time series. This is done using FFT, but the two methods in Matlab and Python give me different results.
Matlab Code:
nsamples = length(acc(:,1));
domega = 2*pi/(dt*nsamples);
acchat = fft(acc);
% Make frequency array:
Omega = zeros(nsamples,1);
% Create Omega:
if even(nsamples)
nh = nsamples/2;
Omega(1:nh+1) = domega*(0:nh);
Omega(nh+2:nsamples) = domega*(-nh+1:-1);
else
nh = (nsamples-1)/2;
Omega(1:nh+1) = domega*(0:nh);
Omega(nh+2:nsamples) = domega*(-nh:-1);
end
% High-pass filter:
n_low=floor(2*pi*f_low/domega);
acchat(1:n_low)=0;
acchat(nsamples-n_low+1:nsamples)=0;
% Multiply by omega^2:
acchat(2:nsamples) = -acchat(2:nsamples) ./ Omega(2:nsamples).^2;
% Inverse Fourier transform:
pos = real(ifft(acchat));
% --- End of function ---
Python Code:
import numpy as np
def acc2velpos(acc, dt):
n = len(acc)
freq = np.fft.fftfreq(n, d=dt)
omegas = 2 * np.pi * freq
omegas = omegas[1:]
# Fast Fourier Transform of Acceleration
accfft = np.array(np.fft.fft(acc, axis=0))
# Integrating the Fast Fourier Transform
velfft = -accfft[1:] / (omegas * 1j)
posfft = accfft[1:] / ((omegas * 1j) ** 2)
velfft = np.array([0] + list(velfft))
posfft = np.array([0] + list(posfft))
# Inverse Fast Fourier Transform back to time domain
vel = np.real(np.fft.ifft(velfft, axis=0))
pos = np.real(np.fft.ifft(posfft, axis=0))
return vel, pos
The two codes should generally give the exact same results, but when I plot a comparison this is what I get
Acceleration to Velocity
Acceleration to Position
Any idea why the Python results are not identical to Matlab results in Position? It is crucial for me to have the same results as I am using these acceleration measurements from experiments to identify the motion of a barge.
I also have a second version in Python where I try to include the filter which is in the Matlab code. This also gives different results, much like the one without a filter in Python.
def acc2vel2(acc, dt, flow):
nsamples = len(acc)
domega = (2*np.pi) / (dt*nsamples)
acchat = np.fft.fft(acc)
# Make Freq. Array
Omega = np.zeros(nsamples)
# Create Omega:
if nsamples % 2 == 0:
nh = int(nsamples/2)
Omega[:nh] = domega * np.array(range(0, nh))
Omega[nh:] = domega * np.array(range(-nh-1, -1))
else:
nh = int((nsamples - 1)/2)
Omega[:nh] = domega * np.array(range(0, nh))
Omega[nh:] = domega * np.array(range(-nh-2, -1))
# High-pass filter
n_low = int(np.floor((2*np.pi*flow)/domega))
acchat[:n_low - 1] = 0
acchat[nsamples - n_low:] = 0
# Divide by omega
acchat[1:] = -acchat[1:] / Omega[1:]
# Inverse FFT
vel = np.imag(np.fft.ifft(acchat))
return vel
This still gives a little bit different than the Matlab code. Suggestions?

