-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathodometry.py
More file actions
123 lines (90 loc) · 4.16 KB
/
odometry.py
File metadata and controls
123 lines (90 loc) · 4.16 KB
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
"""
Contains kalman filter functions that take in raw data and output filtered data.
Originally translated from MATLAB. Math used is explained in great detail at:
https://home.wlu.edu/~levys/kalman_tutorial/
"""
import numpy as np
def kalman_retro(raw_state):
"""Kalman filter that is used to retroactively filter previously collected
raw data. Input raw_state is a 5x1 matrix of raw x, y, yaw, velocity, and time step data.
Returns kalman state, which is a 4x1 matrix of filtered x, y, x_dot, and y_dot data.
"""
eye4 = np.matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
raw_state = np.matrix(raw_state)
rows = raw_state.shape[0]
x_pos = raw_state[:,0]
y_pos = raw_state[:,1]
yaw = raw_state[:,2] #We need to change this to be front encoder position (bike_state.data[2])
v = raw_state[:,3]
t_step = raw_state[:,4]
v_0 = v.item(0)
yaw_0 = yaw.item(0) #Need to change this to be front encoder position
x_dot_0 = v_0*np.cos(yaw_0)
y_dot_0 = v_0*np.sin(yaw_0)
s_current = np.matrix([[x_pos.item(0)], [y_pos.item(0)], [x_dot_0], [y_dot_0]])
P_current = eye4
R = np.matrix([[6.25, 0, 0, 0], [0, 6.25, 0, 0], [0,0,100,0], [0,0,0,100]])
C = eye4
kalman_state = np.matrix(np.zeros((4,rows), dtype=float))
for i in range(rows):
#This will change to reflect new prediction model
A = np.matrix([[1, 0 , t_step.item(i)/1000., 0], [0, 1, 0, t_step.item(i)/1000.], [0, 0, 1, 0], [0, 0, 0, 1]])
kalman_state[:, i] = s_current
s_new = A*s_current
#Values for trust -- 1 means trust GPS completely, but we will be estimating heading -- so will be different
P_new = A*P_current*A.T + (np.matrix([[.0001, 0, 0 ,0], [0, .0001, 0, 0], [0,0,.0001,0], [0,0,0,.0001]]))
x_actual = raw_state.item(i, 0)
y_actual = raw_state.item(i, 1)
psi_actual = raw_state.item(i, 2)
v_actual = raw_state.item(i, 3)
x_dot_actual = v_actual*np.cos(psi_actual)
y_dot_actual = v_actual*np.sin(psi_actual)
z = np.matrix([[x_actual], [y_actual], [x_dot_actual], [y_dot_actual]])
G = P_new*C.T*((C*P_new*C.T + R).I)
s_new = s_new + G*(z - C*s_new)
P_new = (eye4 - G*C)*P_new
s_current = s_new
P_current = P_new
return kalman_state.T
def kalman_real_time(raw_state, s_current, P_current):
"""
Kalman filter that can be run in real time. Input raw_state is a 5x1
matrix of raw x, y, yaw, velocity, and time step data. s_current is
the kalman state, usually taken from the previous call to this
function, and P_current is the observation, also taken from previous
call to function.
Returns the new s and P after filter has been run, which can be used
in the next call to the function as its s_current and P_current. The
first entry of the tuple is the Kalman state, as a row matrix (x, y,
x_dot, y_dot). The second entry of the tuple is the prediction
error, as a 4x4 square matrix.
"""
#4x4 identity matrix
eye4 = np.matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
#make sure raw_state is a matrix
raw_state = np.matrix(raw_state)
x_pos = raw_state[:,0]
y_pos = raw_state[:,1]
yaw = raw_state[:,2]
v = raw_state[:,3]
t_step = raw_state[:,4]
v_0 = v.item(0) # initial velocity
yaw_0 = yaw.item(0) #initial yaw
x_dot_0 = v_0*np.cos(yaw_0)
y_dot_0 = v_0*np.sin(yaw_0)
A = np.matrix([[1, 0 , t_step/1000., 0], [0, 1, 0, t_step/1000.], [0, 0, 1, 0], [0, 0, 0, 1]])
C = eye4
R = 4*eye4
s_new = A*s_current
P_new = A*P_current*A.T + eye4
x_actual = raw_state.item(0)
y_actual = raw_state.item(1)
psi_actual = raw_state.item(2)
v_actual = raw_state.item(3)
x_dot_actual = v_actual*np.cos(psi_actual)
y_dot_actual = v_actual*np.sin(psi_actual)
z = np.matrix([[x_actual], [y_actual], [x_dot_actual], [y_dot_actual]])
G = P_new*C.T*((C*P_new*C.T + R).I)
s_new = s_new + G*(z - C*s_new)
P_new = (eye4 - G*C)*P_new
return (s_new, P_new)