Is there an adaptive algorithm for filtering gyroscope noise?
My app currently has a startup dialog to calibrate gyroscope, where it asks user to put the phone on the table for 5 seconds, and records min/max values of gyro data collected in these 5 seconds, then the app discards all values between that min/max, that's technically a high-pass filter.
The adaptive algorithm would determine these min/max values automatically over time, without any dialogs.
Something like storing last 100 values, and finding min/max of these values, but how do I know which values represent movement, and which are zero movement + noise?
I've looked into Kalman filter, but it's for a combined gyroscope + accelerometer sensors.
The gyroscope in my phone is not only noisy, but also has shifted zero coordinate, so when the phone is lying perfectly still, the gyroscope reports constant small rotation.
The main functions of the Gyroscope Sensor for all the applications are Angular velocity sensing, angle sensing, and control mechanisms.
Full-scale range (dps): This parameter defines the measurement range of the gyroscope in degrees per second (dps). When the applied angular velocity is beyond the full-scale range, the gyroscope output signal will be saturated.
Gyro sensors, also known as angular rate sensors or angular velocity sensors, are devices that sense angular velocity. In simple terms, angular velocity is the change in rotational angle per unit of time.
Description. Use the Gyroscope block measure rotational speed around X, Y, and Z axes of the device. This data is acquired from the gyroscope sensor of the device. For any positive axis on the device, clockwise rotation outputs negative values, and counterclockwise rotation outputs positive values.
If I understand correctly, a very simple heuristic such as finding the mean of the data and defining a threshold that signifies true movement should both combat the offset zero coordinate and give pretty accurate peak recognition.
// Initialize starting mean and threshold
mean = 0
dataCount = 0
thresholdDelta = 0.1
def findPeaks(data) {
mean = updateMean(data)
for point in data {
if (point > mean + thresholdDelta) || (point < mean - thresholdDelta) {
peaks.append(point)
}
}
max = peaks.max()
min = peaks.min()
thresholdDelta = updateThreshold(max, min, mean)
return {max, min}
}
def updateThreshold(max, min) {
// 1 will make threshold equal the average peak value, 0 will make threshold equal mean
weight = 0.5
newThreshold = (weight * (max - min)) / 2
return newThreshold
}
def updateMean(data) {
newMean = (sum(data) + (dataCount * mean)) / (dataCount + data.size)
dataCount += data.size
return newMean
}
Here we have a threshold and mean that will update over time to become more accurate to present data.
If you have peaks that vary quite strongly (say your largest of peaks can be quadruple the smallest) you would want to set your threshold weight accordingly (for our example, 0.25 would just catch the smallest of your peaks, in theory.)
Edit:
I think doing things like averaging your thresholds would probably make it more resistant to decay from small peaks.
thresholdCount = 0
def updateThreshold(max, min) {
// 1 will make threshold equal the average peak value, 0 will make threshold equal mean
weight = 0.5
newThreshold = (weight * (max - min)) / 2
averagedThreshold = (newThreshold + (thresholdCount * thresholdDelta)) / (thresholdCount + 1)
return averagedThreshold
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With