13 Define state vector [x, y, v, psi]
14 [x-position, y-position, speed (scalar), yaw (heading)]
15 Speed used instead of velocity since it can be assumed that a car will be traveling in the forward or backward direction in relation to its
16 orientation. For example, a car is not going to travel sideways.
18 self.
x = np.zeros((4, 1))
21 State covariance P matrix
22 How uncertain the filter is about each part of the state
23 Diagonals contain covariances of each measurement, off-diagonals show uncertainty in correlation between measurements
24 So for example, if speed is wrong, then position is probably wrong as well.
25 Small values in P mean the filter is more confident, large values in P mean more uncertainty
27 self.
P = np.diag([10, 10, 1, 0.1])
30 Process noise Q matrix
31 Represents uncertainty in the model
32 Increase if motion is unpredictable or filter is too "confident"
33 Slow/unresponsive filter? Increase Q values
35 This Q matrix controls acceleration and yaw rate
37 self.
Q = np.diag([1.0, 0.05])
40 Measurement noise R matrix
41 Based on sensor specs, increase if measurements are noisy
42 Noisy output? Increase R values
44 self.
R_gps = np.diag([25, 25])
45 self.
R_yaw = np.array([[0.05]])
47 def predict(self, u, dt):
48 a, omega = u.flatten()
49 x, y, v, psi = self.
x.flatten()
57 x_new = x + v * np.cos(psi) * dt
58 y_new = y + v * np.sin(psi) * dt
62 self.
x = np.array([[x_new], [y_new], [v_new], [psi_new]])
66 State Transition Jacobian F captures how turning affects position
67 Control Jacobian B captures how acceleration and yaw rate affect state
70 [1, 0, np.cos(psi) * dt, -v * np.sin(psi) * dt],
71 [0, 1, np.sin(psi) * dt, v * np.cos(psi) * dt],
85 self.
P = F @ self.
P @ F.T + B @ (self.
Q * dt) @ B.T
87 def update_gps(self, z):
97 S = H @ self.
P @ H.T + self.
R_gps
98 K = self.
P @ H.T @ np.linalg.inv(S)
100 self.
x = self.
x + K @ y
102 self.
P = (I - K @ H) @ self.
P @ (I - K @ H).T + K @ self.
R_gps @ K.T
104 def update_yaw(self, yaw_meas):
105 H = np.array([[0, 0, 0, 1]])
107 z = np.array([[yaw_meas]])
112 S = H @ self.
P @ H.T + self.
R_yaw
113 K = self.
P @ H.T @ np.linalg.inv(S)
115 self.
x = self.
x + K @ y
117 self.
P = (I - K @ H) @ self.
P @ (I - K @ H).T + K @ self.
R_yaw @ K.T
121 def normalize_angle(self, angle):
122 return (angle + np.pi) % (2 * np.pi) - np.pi