-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEKF_old.py
123 lines (98 loc) · 3.9 KB
/
EKF_old.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
"""# **Class: Extended Kalman Filter**
Theoretical Non Linear Kalman
"""
import torch
from filing_paths import path_model
import sys
sys.path.insert(1, path_model)
from model import getJacobian
if torch.cuda.is_available():
cuda0 = torch.device("cuda:0") # you can continue going on here, like cuda:1 cuda:2....etc.
torch.set_default_tensor_type('torch.cuda.FloatTensor')
else:
cuda0 = torch.device("cpu")
print("Running on the CPU")
class ExtendedKalmanFilter:
def __init__(self, SystemModel, mode='full'):
self.f = SystemModel.f
self.m = SystemModel.m
# Has to be transformed because of EKF non-linearity
self.Q = SystemModel.Q
self.h = SystemModel.h
self.n = SystemModel.n
# Has to be transofrmed because of EKF non-linearity
self.R = SystemModel.R
self.T = SystemModel.T
self.T_test = SystemModel.T_test
# Pre allocate KG array
self.KG_array = torch.zeros((self.T_test,self.m,self.n))
# Full knowledge about the model or partial? (Should be made more elegant)
if(mode == 'full'):
self.fString = 'ModAcc'
self.hString = 'ObsAcc'
elif(mode == 'partial'):
self.fString = 'ModInacc'
self.hString = 'ObsInacc'
# Predict
def Predict(self):
# Predict the 1-st moment of x
self.m1x_prior = torch.squeeze(self.f(self.m1x_posterior))
# Compute the Jacobians
self.UpdateJacobians(getJacobian(self.m1x_posterior,self.fString), getJacobian(self.m1x_prior, self.hString))
# Predict the 2-nd moment of x
self.m2x_prior = torch.matmul(self.F, self.m2x_posterior)
self.m2x_prior = torch.matmul(self.m2x_prior, self.F_T) + self.Q
# Predict the 1-st moment of y
self.m1y = torch.squeeze(self.h(self.m1x_prior))
# Predict the 2-nd moment of y
self.m2y = torch.matmul(self.H, self.m2x_prior)
self.m2y = torch.matmul(self.m2y, self.H_T) + self.R
# Compute the Kalman Gain
def KGain(self):
self.KG = torch.matmul(self.m2x_prior, self.H_T)
self.KG = torch.matmul(self.KG, torch.inverse(self.m2y))
#Save KalmanGain
self.KG_array[self.i] = self.KG
self.i += 1
# Innovation
def Innovation(self, y):
self.dy = y - self.m1y
# Compute Posterior
def Correct(self):
# Compute the 1-st posterior moment
self.m1x_posterior = self.m1x_prior + torch.matmul(self.KG, self.dy)
# Compute the 2-nd posterior moment
self.m2x_posterior = torch.matmul(self.m2y, torch.transpose(self.KG, 0, 1))
self.m2x_posterior = self.m2x_prior - torch.matmul(self.KG, self.m2x_posterior)
def Update(self, y):
self.Predict()
self.KGain()
self.Innovation(y)
self.Correct()
return self.m1x_posterior, self.m2x_posterior
def InitSequence(self, m1x_0, m2x_0):
self.m1x_0 = m1x_0
self.m2x_0 = m2x_0
#########################
def UpdateJacobians(self, F, H):
self.F = F
self.F_T = torch.transpose(F,0,1)
self.H = H
self.H_T = torch.transpose(H,0,1)
#print(self.H,self.F,'\n')
### Generate Sequence ###
#########################
def GenerateSequence(self, y, T):
# Pre allocate an array for predicted state and variance
self.x = torch.empty(size=[self.m, T])
self.sigma = torch.empty(size=[self.m, self.m, T])
# Pre allocate KG array
self.KG_array = torch.zeros((T,self.m,self.n))
self.i = 0 # Index for KG_array alocation
self.m1x_posterior = torch.squeeze(self.m1x_0)
self.m2x_posterior = torch.squeeze(self.m2x_0)
for t in range(0, T):
yt = torch.squeeze(y[:, t])
xt,sigmat = self.Update(yt)
self.x[:, t] = torch.squeeze(xt)
self.sigma[:, :, t] = torch.squeeze(sigmat)