-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
276 lines (238 loc) · 13.2 KB
/
main.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
from utilsKalman.util import Util
import matplotlib.pyplot as plt
import numpy as np
from kalmanFilter.kalmanFilterImplementation import MissileTrackerKalmanFilter
import streamlit as st
import numpy as np
import os
import re
# Constant Acceleration
def experiment1(delta_t, time_steps, initial_position, initial_velocity, H, initial_state, initial_covariance,
measurement_noise_multiplier=1, process_noise_multiplier=1, acceleration_multiplier=1, normal_run=False):
"""
Simulates and plots a trajectory with constant acceleration using a Kalman filter.
Args:
delta_t (float): Time interval between steps.
time_steps (int): Number of time steps to simulate.
initial_position (np.ndarray): Initial position vector.
initial_velocity (np.ndarray): Initial velocity vector.
H (np.ndarray): Measurement matrix.
initial_state (np.ndarray): Initial state estimate.
initial_covariance (np.ndarray): Initial covariance estimate.
measurement_noise_multiplier (float, optional): Multiplier for measurement noise. Defaults to 1.
process_noise_multiplier (float, optional): Multiplier for process noise. Defaults to 1.
acceleration_multiplier (float, optional): Multiplier for constant acceleration. Defaults to 1.
normal_run (bool, optional): If True, shows the plot. Defaults to False.
Returns:
None
"""
measurement_noise_cov = np.diag([0.05, 0.05, 0.05, 0.02, 0.02, 0.02])*measurement_noise_multiplier
process_noise_cov = np.diag([0.02, 0.02, 0.02, 0.01, 0.01, 0.01])*process_noise_multiplier
constant_acceleration = np.array([0.1, 0.1, -0.01])*acceleration_multiplier
T = 0.01
eta = int(T / delta_t)
kalman_filter = MissileTrackerKalmanFilter(delta_t, H, process_noise_cov, measurement_noise_cov, initial_state, initial_covariance)
true_positions, estimated_positions, errors = Util.simulate_trajectory(
time_steps, delta_t, eta, initial_position, initial_velocity, constant_acceleration, kalman_filter
)
fig=Util.plot_trajectory(true_positions, estimated_positions, errors)
st.pyplot(fig)
# Variable Acceleration
def experiment2(delta_t, time_steps, initial_position, initial_velocity, H, initial_state, initial_covariance,
measurement_noise_multiplier=1, process_noise_multiplier=1, acceleration_multiplier=1, normal_run=False):
"""
Simulates and plots a trajectory with variable acceleration using a Kalman filter.
Args:
delta_t (float): Time interval between steps.
time_steps (int): Number of time steps to simulate.
initial_position (np.ndarray): Initial position vector.
initial_velocity (np.ndarray): Initial velocity vector.
H (np.ndarray): Measurement matrix.
initial_state (np.ndarray): Initial state estimate.
initial_covariance (np.ndarray): Initial covariance estimate.
measurement_noise_multiplier (float, optional): Multiplier for measurement noise. Defaults to 1.
process_noise_multiplier (float, optional): Multiplier for process noise. Defaults to 1.
acceleration_multiplier (float, optional): Multiplier for variable acceleration. Defaults to 1.
normal_run (bool, optional): If True, shows the plot. Defaults to False.
Returns:
None
"""
measurement_noise_cov = np.diag([0.1, 0.1, 0.1, 0.05, 0.05, 0.05]) * measurement_noise_multiplier
process_noise_cov = np.diag([0.05, 0.05, 0.05, 0.02, 0.02, 0.02]) * process_noise_multiplier
variable_acceleration = lambda t: np.array([0.1 * np.sin(t), 0.1 * np.cos(t), -0.02 * t]) * acceleration_multiplier
T = 0.02
kalman_filter = MissileTrackerKalmanFilter(delta_t, H, process_noise_cov, measurement_noise_cov, initial_state, initial_covariance)
true_positions, estimated_positions, errors = Util.simulate_trajectory(
time_steps, delta_t, int(T / delta_t), initial_position, initial_velocity, variable_acceleration, kalman_filter
)
fig=Util.plot_trajectory(true_positions, estimated_positions, errors)
st.pyplot(fig)
# Streamlit app
def streamlit():
"""
Streamlit-based interface for running Kalman filter experiments with adjustable parameters.
Allows the user to select between constant and variable acceleration experiments, adjusting
simulation parameters such as delta time, time steps, noise multipliers, and acceleration
multiplier via sliders.
Returns:
None
"""
st.sidebar.title("Kalman Filter Experiments")
page = st.sidebar.selectbox("Constant Acceleration", ["Constant Acceleration", "Variable Acceleration"])
if page == "Constant Acceleration":
delta_t = st.sidebar.slider("Delta Time", min_value=0.001, max_value=0.01, value=0.001, step=0.001)
elif page == "Variable Acceleration":
delta_t = st.sidebar.slider("Delta Time", min_value=0.001, max_value=0.02, value=0.001, step=0.001)
time_steps = st.sidebar.slider("Time Steps", min_value=10, max_value=100, value=50, step=1)
initial_position = np.array([0, 0, 0])
initial_velocity = np.array([10, 10, 10])
H = np.eye(6)
initial_state = np.hstack([initial_position, initial_velocity])
initial_covariance = np.eye(6)
measurement_noise_multiplier = st.sidebar.slider("Measurement Noise Multiplier", min_value=0.1, max_value=2.0, value=1.0, step=0.1)
process_noise_multiplier = st.sidebar.slider("Process Noise Multiplier", min_value=0.1, max_value=2.0, value=1.0, step=0.1)
acceleration_multiplier = st.sidebar.slider("Acceleration Multiplier", min_value=0.1, max_value=2.0, value=1.0, step=0.1)
st.title(f"{page}")
if page == "Constant Acceleration":
experiment1(delta_t, time_steps, initial_position, initial_velocity, H, initial_state, initial_covariance,measurement_noise_multiplier, process_noise_multiplier, acceleration_multiplier)
elif page == "Variable Acceleration":
experiment2(delta_t, time_steps, initial_position, initial_velocity, H, initial_state, initial_covariance,measurement_noise_multiplier, process_noise_multiplier, acceleration_multiplier)
def normal_run():
"""
Runs multiple Kalman filter experiments with different noise levels, acceleration types,
and time intervals.
Experiments include:
- Constant acceleration with varying process and measurement noise.
- Time-dependent acceleration with varying noise.
- Different time step (delta_t) values to observe performance impact.
Results are displayed for each configuration and can be saved for analysis.
Returns:
None
"""
# Default initial conditions
initial_position = np.array([0, 0, 0])
initial_velocity = np.array([10, 10, 10])
H = np.eye(6)
initial_state = np.hstack([initial_position, initial_velocity])
initial_covariance = np.eye(6)
time_steps = 50
# Experiment configurations
delta_t_values = [0.001, 0.005, 0.01] # Different time intervals
noise_multipliers = [(0.5, 0.5),(1, 1), (2, 2)] # Different levels of process and measurement noise
acceleration_types = [
("Constant", np.array([0.1, 0.1, -0.01])),
("Time-dependent", lambda t: np.array([0.1 * np.sin(t), 0.1 * np.cos(t), -0.01 * t]))
]
for delta_t in delta_t_values:
for (proc_noise_mult, meas_noise_mult) in noise_multipliers:
for acc_type, acceleration in acceleration_types:
# Create Kalman filter with adjusted noise
process_noise_cov = np.diag([0.02, 0.02, 0.02, 0.01, 0.01, 0.01]) * proc_noise_mult
measurement_noise_cov = np.diag([0.05, 0.05, 0.05, 0.02, 0.02, 0.02]) * meas_noise_mult
# Instantiate Kalman filter
kalman_filter = MissileTrackerKalmanFilter(
delta_t, H, process_noise_cov, measurement_noise_cov, initial_state, initial_covariance
)
# Run simulation based on acceleration type
if acc_type == "Constant":
true_positions, estimated_positions, errors = Util.simulate_trajectory(
time_steps, delta_t, int(0.01 / delta_t), initial_position, initial_velocity, acceleration, kalman_filter
)
elif acc_type == "Time-dependent":
true_positions, estimated_positions, errors = Util.simulate_trajectory(
time_steps, delta_t, int(0.02 / delta_t), initial_position, initial_velocity, acceleration, kalman_filter
)
# Plot and display results
title = f"Experiment: Δt={delta_t}, Proc Noise Mult={proc_noise_mult}, Meas Noise Mult={meas_noise_mult}, Accel={acc_type}"
print(title)
fig = Util.plot_trajectory(true_positions, estimated_positions, errors, normal_run=False)
# add parameter values in plt
plt.suptitle(title)
# save fig
save_name = re.sub(r'[<>:"/\\|?*]', "", title)
save_name = save_name.replace(" ", "_").replace("Δ", "delta").replace("=", "_").replace(",", "_").replace(".", "_") + ".png"
os.makedirs("results", exist_ok=True)
fig.savefig(os.path.join("results", save_name))
# create plots when only delta_t is varied
errors=[]
delta_t_values = [0.001, 0.005, 0.01, 0.05, 0.1]
for delta_t in delta_t_values:
kalman_filter = MissileTrackerKalmanFilter(
delta_t, H, np.diag([0.02, 0.02, 0.02, 0.01, 0.01, 0.01]), np.diag([0.05, 0.05, 0.05, 0.02, 0.02, 0.02]),
initial_state, initial_covariance
)
true_positions, estimated_positions, error = Util.simulate_trajectory(
time_steps, delta_t, int(0.2 / delta_t), initial_position, initial_velocity, np.array([0.1, 0.1, -0.01]), kalman_filter
)
rmse_error = np.sqrt(np.mean(np.square(error)))
errors.append(rmse_error)
fig, ax = plt.subplots(2, 2, figsize=(12, 10))
# Create line plot of errors and delta_t
ax[0][0].plot(delta_t_values, errors)
ax[0][0].set_title("Errors vs Delta_t")
ax[0][0].set_xlabel("Delta_t")
ax[0][0].set_ylabel("RMSE Error")
ax[0][0].legend(["RMSE Error"])
noise_multipliers = [0.5, 1, 2, 5, 10]
errors = []
for noise_mult in noise_multipliers:
kalman_filter = MissileTrackerKalmanFilter(
0.001, H, np.diag([0.02, 0.02, 0.02, 0.01, 0.01, 0.01]) * noise_mult,
np.diag([0.05, 0.05, 0.05, 0.02, 0.02, 0.02]) * noise_mult,
initial_state, initial_covariance
)
true_positions, estimated_positions, error = Util.simulate_trajectory(
time_steps, 0.001, int(0.2 / 0.001), initial_position, initial_velocity, np.array([0.1, 0.1, -0.01]), kalman_filter
)
rmse_error = np.sqrt(np.mean(np.square(error)))
errors.append(rmse_error)
# Create line plot of errors and noise multiplier
ax[0][1].plot(noise_multipliers, errors)
ax[0][1].set_title("Errors vs Noise Multiplier")
ax[0][1].set_xlabel("Noise Multiplier")
ax[0][1].set_ylabel("RMSE Error")
ax[0][1].legend(["RMSE Error"])
acceleration_multipliers_constant = [0.5, 1, 2, 5, 10]
errors = []
for acc_mult in acceleration_multipliers_constant:
kalman_filter = MissileTrackerKalmanFilter(
0.001, H, np.diag([0.02, 0.02, 0.02, 0.01, 0.01, 0.01]),
np.diag([0.05, 0.05, 0.05, 0.02, 0.02, 0.02]),
initial_state, initial_covariance
)
true_positions, estimated_positions, error = Util.simulate_trajectory(
time_steps, 0.001, int(0.2 / 0.001), initial_position, initial_velocity, np.array([0.1, 0.1, -0.01]) * acc_mult, kalman_filter
)
rmse_error = np.sqrt(np.mean(np.square(error)))
errors.append(rmse_error)
# Create line plot of errors and acceleration multiplier (constant)
ax[1][0].plot(acceleration_multipliers_constant, errors)
ax[1][0].set_title("Errors vs Constant Acceleration")
ax[1][0].set_xlabel("Acceleration Multiplier")
ax[1][0].set_ylabel("RMSE Error")
ax[1][0].legend(["RMSE Error"])
acceleration_multipliers_time_dependent = [0.5, 1, 2, 5, 10]
errors = []
for acc_mult in acceleration_multipliers_time_dependent:
kalman_filter = MissileTrackerKalmanFilter(
0.001, H, np.diag([0.02, 0.02, 0.02, 0.01, 0.01, 0.01]),
np.diag([0.05, 0.05, 0.05, 0.02, 0.02, 0.02]),
initial_state, initial_covariance
)
true_positions, estimated_positions, error = Util.simulate_trajectory(
time_steps, 0.001, int(0.2 / 0.001), initial_position, initial_velocity,
lambda t: np.array([0.1 * np.sin(t), 0.1 * np.cos(t), -0.01 * t]) * acc_mult, kalman_filter
)
rmse_error = np.sqrt(np.mean(np.square(error)))
errors.append(rmse_error)
# Create line plot of errors and acceleration multiplier (time-dependent)
ax[1][1].plot(acceleration_multipliers_time_dependent, errors)
ax[1][1].set_title("Errors vs Time-dependent Acceleration")
ax[1][1].set_xlabel("Acceleration Multiplier")
ax[1][1].set_ylabel("RMSE Error")
ax[1][1].legend(["RMSE Error"])
plt.tight_layout()
plt.show()
if __name__ == '__main__':
# streamlit()
normal_run()