In: Computer Science
LOOK over code Python
The task aims to develop a Kalman filter that is able to hit the moving target (the pink box) in as many situations as possible. However, there are some limitations: IT IS NOT PERMITTED TO CHANGE THE PRODEIL AND TARGET CODE IT IS ALSO NOT ALLOWED TO CHANGE THE GAME LOOP, OTHER THAN WHAT HAS BEEN COMMENTS SHALL BE CHANGED WHEN THE Kalman CLASS IS IMPLEMENTED
I have made the callman class, but my question is; why doesent i hit the pink box as often? How can I change that?
code below
#
# Kalmanfilter task
#
# Please note that only the code in the Kalman class can be
changed. This is the code to be submitted
# It is therefore important that NO OTHER CODE IS CHANGED !!!
#
'''
import pygame as pg
from random import random,randint
import numpy as np
from numpy.linalg import norm
fps = 0.0
class Projectile():
def __init__(self, background, kalman=None):
self.background = background
self.rect = pg.Rect((800,700),(16,16))
self.px = self.rect.x
self.py = self.rect.y
self.dx = 0.0
self.kalm = kalman
def move(self,goal):
if self.kalm:
goal = self.kalm.calc_next(goal)
deltax = np.array(float(goal) - self.px)
#print(delta2)
mag_delta = norm(deltax)#* 500.0
np.divide(deltax,mag_delta,deltax)
self.dx += deltax
#if self.dx:
#self.dx /= norm(self.dx) * 50
self.px += self.dx /50.0
self.py += -0.5
try:
self.rect.x = int(self.px)
except:
pass
try:
self.rect.y = int(self.py)
except:
pass
class Target():
def __init__(self, background, width):
self.background = background
self.rect = pg.Rect(self.background.get_width()//2-width//2,
50, width, 32)
self.dx = 1 if random() > 0.5 else -1
def move(self):
self.rect.x += self.dx
if self.rect.x < 300 or self.rect.x >
self.background.get_width()-300:
self.dx *= -1
def noisy_x_pos(self):
pos = self.rect.x
center = self.rect.width//2
noise = np.random.normal(0,1,1)[0]
return pos + center + noise*300.0
#
# Here is the Kalman filter you are going to develop
#
class Kalman():
'''
State vector is X=(x,v)
assuming that the target is moving at constant velocity and there
is no noise in the motion of the target (just the
measurement)
Motion is X_(k+1)=F X_k
Measurement is z_k=H X_k+noise
'''
def __init__(self,noise=300.,ignorance=10.):
self.R=np.matrix([[noise**2]])#covariance matrix of the measurement
(only one value measured so 1X1 matrix)
self.F=np.matrix([[1,1],[0,1]])#transition matrix from current
state to the next
self.H=np.matrix([[1,0]])#measurement matrix
self.x=np.matrix([[0],[0]])#initial guess at zero with zero
velocity (would work better if assumed at centre, but would then
need to know width of background)
self.P=ignorance*np.matrix([[noise**2,noise**2],[noise**2,2*noise**2]])#Initial
guess of error covariance. rule of ignorance says better
convergence with large initial P. can tweak this to see if can get
better convergence
def calc_next(self, zi):
z=np.matrix([[zi]])#turn the observation into a matrix so that we
can do matrix algebra
x_init=self.F*self.x#predicted state estimate
P_init=self.F*self.P*self.F.T#predicted error covariance
y=z-self.H*x_init# measurement residual
K=P_init*self.H.T*np.linalg.inv(self.R+self.H*P_init*self.H.T)#Kalman
gain
self.x=x_init+K*y#updated state estimate
self.P=(np.identity(2)-K*self.H)*P_init#updated covariance
estimate
return self.x[0,0]#return only the x, not velocity
pg.init()
w,h = 1600,800
background = pg.display.set_mode((w,h))
surf = pg.surfarray.pixels3d(background)
running = True
clock = pg.time.Clock()
kalman_score = 0
reg_score = 0
iters = 0
while running:
target = Target(background, 32)
missile = Projectile(background)
k_miss = Projectile(background,Kalman()) #comment on this line when
Kalman is implemented
last_x_pos = target.noisy_x_pos
noisy_draw = np.zeros((w,20))
trial = True
iters += 1
while trial:
# Sets a maximum frame rate of 300. If you want to increase
this, this is a possible change
clock.tick(300)
fps = clock.get_fps()
for e in pg.event.get():
if e.type == pg.QUIT:
running = False
background.fill(0x448844)
surf[:,0:20,0] = noisy_draw
last_x_pos = target.noisy_x_pos()
# print(last_x_pos)
target.move()
missile.move(last_x_pos)
k_miss.move(last_x_pos) #comment in this line when Kalman is
implemented
pg.draw.rect(background, (255, 200, 0), missile.rect)
pg.draw.rect(background, (0, 200, 255), k_miss.rect) #comment in
this line when Kalman is implemented
pg.draw.rect(background, (255, 200, 255), target.rect)
noisy_draw[int(last_x_pos):int(last_x_pos)+20,:] = 255
noisy_draw -= 1
np.clip(noisy_draw, 0, 255, noisy_draw)
coll = missile.rect.colliderect(target.rect)
k_coll = k_miss.rect.colliderect(target.rect) #comment in this line
when Kalman is implemented
if coll:
reg_score += 1
if k_coll: #comment in this line when Kalman is
implemented
kalman_score += 1
oob = missile.rect.y < 20
if oob or coll or k_coll: # or k_coll #change this check so that
k_coll is also included when kalman is implemented
trial = False
pg.display.flip()
print('kalman score: ', round(kalman_score/iters,2)) #comment in
this line when Kalman is implemented
print('regular score: ', round(reg_score/iters,2))
pg.quit()
'''
#
# Kalmanfilter task
#
# Please note that only the code in the Kalman class can be
changed. This is the code to be submitted
# It is therefore important that NO OTHER CODE IS CHANGED !!!
#
'''
import pygame as pg
from random import random,randint
import numpy as np
from numpy.linalg import norm
fps = 0.0
class Projectile():
def __init__(self, background, kalman=None):
self.background = background
self.rect = pg.Rect((800,700),(16,16))
self.px = self.rect.x
self.py = self.rect.y
self.dx = 0.0
self.kalm = kalman
def move(self,goal):
if self.kalm:
goal = self.kalm.calc_next(goal)
deltax = np.array(float(goal) - self.px)
#print(delta2)
mag_delta = norm(deltax)#* 500.0
np.divide(deltax,mag_delta,deltax)
self.dx += deltax
#if self.dx:
#self.dx /= norm(self.dx) * 50
self.px += self.dx /50.0
self.py += -0.5
try:
self.rect.x = int(self.px)
except:
pass
try:
self.rect.y = int(self.py)
except:
pass
class Target():
def __init__(self, background, width):
self.background = background
self.rect = pg.Rect(self.background.get_width()//2-width//2,
50, width, 32)
self.dx = 1 if random() > 0.5 else -1
def move(self):
self.rect.x += self.dx
if self.rect.x < 300 or self.rect.x >
self.background.get_width()-300:
self.dx *= -1
def noisy_x_pos(self):
pos = self.rect.x
center = self.rect.width//2
noise = np.random.normal(0,1,1)[0]
return pos + center + noise*300.0
#
# Here is the Kalman filter you are going to develop
#
class Kalman():
def __init__(self):
pass
def calc_next(self, zi):
pass
pg.init()
w,h = 1600,800
background = pg.display.set_mode((w,h))
surf = pg.surfarray.pixels3d(background)
running = True
clock = pg.time.Clock()
kalman_score = 0
reg_score = 0
iters = 0
while running:
target = Target(background, 32)
missile = Projectile(background)
#k_miss = Projectile(background,Kalman()) #comment on this line
when Kalman is implemented
last_x_pos = target.noisy_x_pos
noisy_draw = np.zeros((w,20))
trial = True
iters += 1
while trial:
# Sets a maximum frame rate of 300. If you want to increase
this, this is a possible change
clock.tick(300)
fps = clock.get_fps()
for e in pg.event.get():
if e.type == pg.QUIT:
running = False
background.fill(0x448844)
surf[:,0:20,0] = noisy_draw
last_x_pos = target.noisy_x_pos()
# print(last_x_pos)
target.move()
missile.move(last_x_pos)
#k_miss.move(last_x_pos) #comment in this line when Kalman is
implemented
pg.draw.rect(background, (255, 200, 0), missile.rect)
#pg.draw.rect(background, (0, 200, 255), k_miss.rect) #comment in
this line when Kalman is implemented
pg.draw.rect(background, (255, 200, 255), target.rect)
noisy_draw[int(last_x_pos):int(last_x_pos)+20,:] = 255
noisy_draw -= 1
np.clip(noisy_draw, 0, 255, noisy_draw)
coll = missile.rect.colliderect(target.rect)
#k_coll = k_miss.rect.colliderect(target.rect) #comment in this
line when Kalman is implemented
if coll:
reg_score += 1
# if k_coll: #comment in this line when Kalman is
implemented
# kalman_score += 1
oob = missile.rect.y < 20
if oob or coll: # or k_coll #change this check so that k_coll is
also included when kalman is implemented
trial = False
pg.display.flip()
#print('kalman score: ', round(kalman_score/iters,2)) #comment
in this line when Kalman is implemented
print('regular score: ', round(reg_score/iters,2))
pg.quit()