I want to detect jerk from accelerator data i.e. values beyond 1.57 m/s^2, but due to the high frequency nature of the sensor (400 values per second), it gives multiple jerks instead of one. How can I solve this?
I do not need more jerk updates as it gives many false positives. If accelerometer value breaches 1.57m/s^2 and comes back below it I consider that a jerk.
Problem that I want to solve is build a android app that uses accelerometer data to detect faults on railway tracks.
I am resorting to someone's advise and doing bandpass filtering and then Hilbert transform on the data then use find peaks function , is this correct approach if so how to proceed further ; if not do suggest one.
Multiple peaks is what i mean i.e. multiple local maximas instead of one.
EDIT Updates
I am building a mobile based real time accelerometer Oscillation Monitoring System.
The csv of all data contains x,y,z accelerometer value,jerk time in UTC,latitude , longitude of real time train journey: https://drive.google.com/file/d/1k47ScyTRr7tr9ZCbSPfHdYApCy53s0E7/view?usp=sharing
The plots are in form of html which are exported from plotly kindly download them and them open on remote machine.
Plot of raw accelerometer data :https://drive.google.com/file/d/1cuJhjrpvvvN1BIDIxn_tBeo2Yyn4Blab/view?usp=sharing
The first step,is a bandpass filter between 0.3 to 12 Hz (Plot):
https://drive.google.com/file/d/1_3ZjAHwFcCrV3nBGvRXxY9eWh2QwpWIS/view?usp=sharing
Code:
def bandpass(signal):
fs = 380
lowcut = 0.3
highercut = 12.0
nyq = 0.5 * fs
low = lowcut/nyq
high = highercut/nyq
order = 2
b , a = scipy.signal.butter(order,[low,high],'bandpass',analog=False)
y = scipy.signal.filtfilt(b,a,signal,axis=0)
return(y)
Followed by an envelope detector,of which I have compared RMS and Hilbert(Plot): https://drive.google.com/file/d/19cL8kZuh5hvB0AW5zKAKZy0uTBlaMVJS/view?usp=sharing
Code:
Hilbert
def hilbert_transform(x, N=None, axis=-1):
x = np.asarray(x)
if np.iscomplexobj(x):
raise ValueError("x must be real.")
if N is None:
N = x.shape[axis]
if N <= 0:
raise ValueError("N must be positive.")
Xf = fft(x, N, axis=axis)
h = np.zeros(N, dtype=Xf.dtype)
if N % 2 == 0:
h[0] = h[N // 2] = 1
h[1:N // 2] = 2
else:
h[0] = 1
h[1:(N + 1) // 2] = 2
if x.ndim > 1:
print("Hello World")
ind = [np.newaxis] * x.ndim
ind[axis] = slice(None)
h = h[tuple(ind)]
x = ifft(Xf * h, axis=axis)
return x
Windowed RMS
def window_rms(a, window_size):
a2 = np.power(a,2)
window = np.ones(window_size)/float(window_size)
return np.sqrt(np.convolve(a2, window, 'valid'))
I need to build a jerk detector, by merging the envelope of several peaks caused by an event (Any value above 1.57 m/s^2 is considered a peak).
Last part is where I am getting stuck.
I have tried peak detection of scipy , have not got right result.
Code
plt.rcParams["figure.figsize"] = (20,12)
# plt.plot(x)
# For zooming
# plt.ylim(4500, 5000)
plt.plot(envelope2)
plt.axhline(1.57)
peaks, _ = find_peaks(envelope2, prominence =1.57) # BEST!
plt.plot(peaks, envelope2[peaks], "xr")
plt.legend(['RMS'], loc='upper left')
plt.show()
Used zero crossing
Code
zero_crosses_rate = np.nonzero(np.diff(envelope > 1.57))[0]
print(zero_crosses_rate,envelope[zero_crosses_rate])
# printing original list
print("The original list : " + str(zero_crosses_rate))
# Using list slicing
# Separating odd and even index elements
odd = zero_crosses_rate[::2]
even = zero_crosses_rate[1::2]
# print result
print(odd)
print(envelope2[odd])
print(even)
print(envelope2[even])
print("even bigger then odd that is considered jerk")
Also use modified Zscore , same could not understand, so could not work with it.
All in all consider me a lay man willing to follow guidance and learn with open mind seeking help.