go-kalmanfilter icon indicating copy to clipboard operation
go-kalmanfilter copied to clipboard

How to smoothen out sensor readings with this lib?

Open kramer65 opened this issue 5 years ago • 0 comments

For a robotics project I'm building an autonomous boat which moves in a grid with x and y readings. These location sensor readings are a little noisy however, and as far as I understand, a Kalman filter is built specifically to smoothen out noise from sensor readings and get an estimation of the next value. Your lib seems to be perfect to do this.

I pasted some noisy readings below (every item also has a datetime object, but I left them out for clarity).

// X     Y
{399, 293},
{403, 299},
{409, 308},
{416, 315},
{418, 318},
{420, 323},
{429, 326},  // <== Noise in X
{423, 328},
{429, 334},
{431, 337},
{433, 342},
{434, 352},  // <== Noise in Y
{434, 349},
{433, 350},
{431, 350},
{430, 349},
{428, 347},
{427, 345},
{425, 341},
{429, 338},  // <== Noise in X
{431, 328},  // <== Noise in X
{410, 313},
{406, 306},
{402, 299},
{397, 291},
{391, 294},  // <== Noise in Y
{376, 270},
{372, 272},
{351, 248},
{336, 244},
{327, 236},
{307, 220}

So from the example code in the readme and my sensor readings I created the following code:

package main

import (
  "fmt"
  "time"
  "github.com/shantanubhadoria/go-kalmanfilter/kalmanfilter"
)

func getStateSensorReading(readings [][]int, i int) int {
	return readings[i][0]
}

func getDeltaSensorReading(readings [][]int, i int) int {
	return readings[i][0] - readings[i-1][0]
}

func main() {
	readings := [][]int{
		{399, 293},
		{403, 299},
		{409, 308},
		{416, 315},
		{418, 318},
		{420, 323},
		{429, 326},  // <== Noise in X
		{423, 328},
		{429, 334},
		{431, 337},
		{433, 342},
		{434, 352},  // <== Noise in Y
		{434, 349},
		{433, 350},
		{431, 350},
		{430, 349},
		{428, 347},
		{427, 345},
		{425, 341},
		{429, 338},  // <== Noise in X
		{431, 328},  // <== Noise in X
		{410, 313},
		{406, 306},
		{402, 299},
		{397, 291},
		{391, 294},  // <== Noise in Y
		{376, 270},
		{372, 272},
		{351, 248},
		{336, 244},
		{327, 236},
		{307, 220},
	}

	myFilterData := new(kalmanfilter.FilterData)

	var oldTime time.Time = time.Now()
	i := 1
	for i < len(readings) {
		stateReading := float64(getStateSensorReading(readings, i)) // in units X
		deltaReading := float64(getDeltaSensorReading(readings, i)) // in unit X per nanosecond

		fmt.Println(stateReading, deltaReading)  // Prints out correct values

		var newTime time.Time = time.Now()
		var duration time.Duration = newTime.Sub(oldTime)
		oldTime = newTime
		newState := myFilterData.Update(stateReading, deltaReading, float64(duration/time.Nanosecond))
		fmt.Println(newState)  // Only Prints out NaN
		fmt.Println(myFilterData)

		i++
	}
}

With this code I only attempt to smoothen out the sensor readings for X. Unfortunately newState is only NaN (as you can see in the comments in the code).

Would anybody know how I can smoothen out the sensor readings and get estimations for the next sensor reading? I obviously need to do the same for Y. Would I simply copy the same logic as for Y, or can I combine X and Y somehow?

kramer65 avatar May 29 '19 19:05 kramer65