0
$\begingroup$

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?

Result coming now enter image description here

Desired result enter image description here

  1. 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.

  2. Problem that I want to solve is build a android app that uses accelerometer data to detect faults on railway tracks.

  3. 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.

  4. 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.

$\endgroup$
12
  • 1
    $\begingroup$ "values beyond 1.57 g " is NOT jerk . Jerk is the time derivative of acceleration. Please clarify what you want to do. $\endgroup$
    – Hilmar
    Sep 5, 2022 at 14:39
  • $\begingroup$ Please edit your question to define what you mean by "multiple jerks instead of one". Do you mean one event that has a duration longer than one accelerometer sample? Or do you mean that the acceleration is undergoing a strong oscillation, with a non-monotonic change in acceleration reading? $\endgroup$
    – TimWescott
    Sep 5, 2022 at 16:25
  • $\begingroup$ Note on @Hilmar's comment: one g has the units $\mathrm{m / s^2}$. Jerk is the time derivative of acceleration, so it has the units $\mathrm{m / s^3}$, or perhaps $\mathrm{g / s}$. $\endgroup$
    – TimWescott
    Sep 5, 2022 at 16:27
  • $\begingroup$ What you need is a differentiator (that will get you instantaneous jerk) and then you need to smooth that noisy instantaneous jerk out a little with a gentle LPF. $\endgroup$ Sep 5, 2022 at 18:55
  • 1
    $\begingroup$ @gladi8er: you were very clearly asked to edit the question, and given guidance as to what information is missing. Until you do that we can't answer, and you should not expect much activity. $\endgroup$
    – TimWescott
    Nov 2, 2022 at 14:21

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.