Search code examples
pythontkinterkalman-filter

Python Kalman filter for mouse position isn't working as expected


I started using python with Jupyter notebook, so for learning purpose I implemented Kalman filter following this YouTube tutorial. I first use my Kalman filter with static data, I guess it was working so I tried to extend that code to apply filter on mouse coordinate but it is behaving really weired. Can anyone help me to fix?

I expect to have this kind of result but I am getting something like the screenshot.

here is the code -

import numpy as np
import pandas as pd
from tkinter import * 

### True Value: What should be the actual value if there was no error in measurements

### Estimates : It is the predicted value. 
#### Error in Estimate: Error in the predicted value

### Measurements : It is the actual value measured with sensor
#### Error in Measurements: Error in the measured value 

#### initializing variables



true_x,true_y = 0,0 # True Mouse location 

Est_x,Est_y = 0,0  # Initial Estimate   
Err_est_x,Err_est_y = 5,5 # Error in Initial Estimate

M_x,M_y = 0,0 # Initial Measurements
Err_msr_x,Err_msr_y = 5,5 # Error in Initial Measurements

kg_x,kg_y = 0,0 # Kalman Gain 
  

def getKG(Err_est, Err_msr):
    return Err_est/(Err_est+Err_msr)


def getEst(EST_prev, kg, Msr):
    return EST_prev+kg*(Msr-EST_prev)


def getE_est(kg, Err_est):
    return (1-kg)*Err_est


def updateKal(val, kg, Est, Err_est, Err_msr):
    kg = getKG(Err_est, Err_msr)
    Est = getEst(Est, kg, val)
    Err_est = getE_est(kg, Err_est)
    return kg, Est, Err_est



kg_x,Est_x,Err_est_x = updateKal(true_x,kg_x,Est_x,Err_est_x,Err_msr_x)
kg_y,Est_y,Err_est_y = updateKal(true_y,kg_y,Est_y,Err_est_y,Err_msr_y)
    

def activate_paint(e):
    global lastx, lasty
    global true_x, true_y
    cv.bind('<B1-Motion>', paint)
    lastx, lasty = e.x, e.y
    true_x, true_y = e.x, e.y
    Est_x, Est_y = e.x, e.y


def paint(e):
    global lastx, lasty
    global true_x, true_y
    global kg_x, Est_x, Err_est_x
    global kg_y, Est_y, Err_est_y
    global firstval

    x, y = e.x, e.y

    kg_x, Est_x, Err_est_x = updateKal(x, kg_x, Est_x, Err_est_x, 0.5)
    kg_y, Est_y, Err_est_y = updateKal(y, kg_y, Est_y, Err_est_y, 0.5)

    cv.create_line((lastx, lasty, x, y),  fill='blue',width=1)
    cv.create_line((true_x,true_y, Est_x, Est_y),  fill='green',width=2) 

    lastx, lasty = x, y
    true_x, true_y = Est_x, Est_y


root = Tk()

lastx, lasty = None, None 

cv = Canvas(root, width=640, height=480, bg='white')
 
cv.bind('<1>', activate_paint)
cv.pack(expand=YES, fill=BOTH)

root.mainloop()
 

red one is Kalman and blue is actual

enter image description here

Edit : updated with code suggested by@Lho enter image description here


Solution

  • I didn't run your code, but your variables Err_est_x and Err_est_y are only getting smaller? You must increase these variables after each call of updateCall like this:

    # in method paint()
    #
    kg_x, Est_x, Err_est_x = updateKal(x, kg_x, Est_x, Err_est_x, 0.5)
    kg_y, Est_y, Err_est_y = updateKal(y, kg_y, Est_y, Err_est_y, 0.5)
    Err_est_x = 1.1 * Err_est_x + 0.1 # new code
    Err_est_y = 1.1 * Err_est_y + 0.1 # new code
    

    Explanation: If your estimated error is low, the information of a new noisy measurment is also low [1]. This is also visible in your visualisation: Initially, the red kalman estimate is 'very fast' because your estimated error is high. But when your estimated error is getting smaller, your red kalman estimate is 'slowing done'.

    Please note that I didn't run your code, so the chosen values (1.1 and 0.1) may be to high or too small. Increase/reduce both numbers to increase/reduce the 'speed' of your red kalman estimate.

    [1] For example, if your estimated error is 0, the information gain of a new measurment is also 0.