10
10
import numpy as np
11
11
from scipy .io import savemat
12
12
13
- from experiments .crazyflie .crazyflie_utils import gen_traj
13
+ from experiments .crazyflie .crazyflie_utils import gen_traj , gen_input_traj
14
14
from safe_control_gym .envs .benchmark_env import Task
15
15
from safe_control_gym .safety_filters .mpsc .mpsc_utils import Cost_Function , get_discrete_derivative
16
16
from safe_control_gym .utils .configuration import ConfigFactory
27
27
print ('Module \' cffirmware\' available:' , FIRMWARE_INSTALLED )
28
28
29
29
30
- A = np .array ([[0.9987 , 0.02872 ],
31
- [0.006117 , 0.8535 ]])
32
- B = np .array ([[0.02309 , 0.2854 ]]).T
30
+ A = np .array ([[ 1 , 0.03659 , 7.598e-07 , - 0.006083 ],
31
+ [- 5.858e-06 , 0.7886 , 5.132e-06 , 0.03174 ],
32
+ [ 3.259e-06 , 0.0009138 , 1 , 0.03899 ],
33
+ [- 1.735e-05 , - 0.006111 , - 9.836e-06 , 0.7786 ]])
33
34
35
+ B = np .array ([[ 0.003886 , 0.01169 ],
36
+ [ 0.4229 , - 0.06055 ],
37
+ [- 0.001915 , - 0.0006503 ],
38
+ [ 0.01223 , 0.4419 ]])
34
39
35
- def run (gui = False , plot = True , training = False , certify = False , traj = 'sine' , curr_path = '.' ):
40
+
41
+ def run (gui = False , plot = True , training = False , certify = True , curr_path = '.' ):
36
42
'''The main function creating, running, and closing an environment over N episodes. '''
37
43
38
44
# Define arguments.
@@ -58,23 +64,24 @@ def run(gui=False, plot=True, training=False, certify=False, traj='sine', curr_p
58
64
actions_uncert = []
59
65
actions_cert = []
60
66
61
- errors = []
62
-
63
67
# Create environment.
64
68
firmware_wrapper = make ('firmware' , env_func_500 , FIRMWARE_FREQ , CTRL_FREQ )
65
69
obs , info = firmware_wrapper .reset ()
66
70
env = firmware_wrapper .env
67
71
68
72
# Create trajectory.
69
73
full_trajectory = gen_traj (CTRL_FREQ , env .EPISODE_LEN_SEC )
70
- lqr_gain = 0.05 * np .array ([[4 , 0.1 ]])
74
+ full_trajectory = np .hstack ((full_trajectory , full_trajectory ))
75
+
76
+ lqr_gain = 0.05 * np .array ([[4 , 0.1 , 0 , 0 ],
77
+ [0 , 0 , 4 , 0.1 ]])
71
78
72
79
# Setup controller.
73
80
ctrl = make (config .algo ,
74
81
env_func ,
75
82
** config .algo_config )
76
83
ctrl .gain = lqr_gain
77
- ctrl .model .U_EQ = 0
84
+ ctrl .model .U_EQ = np . array ([[ 0 , 0 ]]). T
78
85
79
86
ctrl .env .X_GOAL = full_trajectory
80
87
ctrl .env .TASK = Task .TRAJ_TRACKING
@@ -88,9 +95,10 @@ def run(gui=False, plot=True, training=False, certify=False, traj='sine', curr_p
88
95
if training is True :
89
96
safety_filter .learn (env = env )
90
97
safety_filter .save (path = f'{ curr_path } /models/mpsc_parameters/{ config .safety_filter } _crazyflie_{ task } .pkl' )
91
- 1 / 0
98
+ 1 / 0
92
99
else :
93
100
safety_filter .load (path = f'{ curr_path } /models/mpsc_parameters/{ config .safety_filter } _crazyflie_{ task } .pkl' )
101
+ safety_filter .env .X_GOAL = full_trajectory
94
102
95
103
if config .sf_config .cost_function == Cost_Function .PRECOMPUTED_COST :
96
104
safety_filter .cost_function .uncertified_controller = ctrl
@@ -101,25 +109,21 @@ def run(gui=False, plot=True, training=False, certify=False, traj='sine', curr_p
101
109
states .append (env .state )
102
110
action = env .U_GOAL
103
111
successes = 0
104
- estimated_vel = []
105
- bad_estimated_vel = []
106
- prev_vel = 0
107
- prev_x = 0
108
- alpha = 0.3
112
+
109
113
for i in range (CTRL_FREQ * env .EPISODE_LEN_SEC ):
110
- curr_obs = np .atleast_2d (np .array ([obs [0 ], obs [1 ]])).T
114
+ curr_obs = np .atleast_2d (obs [0 :4 ]).T
115
+ curr_obs = curr_obs .reshape ((4 , 1 ))
111
116
info ['current_step' ] = i
112
- new_act = ctrl .select_action (curr_obs , info )[ 0 ]
113
- new_act = np .clip (new_act , - 0.25 , 0.25 )
117
+ new_act = ctrl .select_action (curr_obs , info )
118
+ new_act = np .clip (new_act , np . array ([[ - 0.25 , - 0.25 ]]). T , np . array ([[ 0.25 , 0.25 ]]). T )
114
119
actions_uncert .append (new_act )
115
120
if certify is True :
116
121
certified_action , success = safety_filter .certify_action (curr_obs , new_act , info )
117
122
if success :
118
123
successes += 1
119
124
new_act = certified_action
120
125
actions_cert .append (new_act )
121
- next_state = A @ curr_obs + B * new_act
122
- pos = [(new_act + curr_obs [0 ])[0 ], 0 , 1 ]
126
+ pos = [(new_act [0 ] + curr_obs [0 ])[0 ], (new_act [1 ] + curr_obs [2 ])[0 ], 1 ]
123
127
vel = [0 , 0 , 0 ]
124
128
acc = [0 , 0 , 0 ]
125
129
yaw = 0
@@ -131,15 +135,6 @@ def run(gui=False, plot=True, training=False, certify=False, traj='sine', curr_p
131
135
132
136
# Step the environment.
133
137
obs , _ , _ , info , action = firmware_wrapper .step (curr_time , action )
134
- x_obs = obs [0 ] + np .random .normal (0.0 , 0.001 )
135
- est_vel = (x_obs - prev_x ) / CTRL_DT
136
- bad_estimated_vel .append (est_vel )
137
- prev_vel = (1 - alpha ) * prev_vel + alpha * est_vel
138
- prev_x = x_obs
139
- estimated_vel .append (prev_vel )
140
- obs [0 ] = x_obs
141
- obs [1 ] = prev_vel
142
- errors .append (np .squeeze (np .array ([obs [0 ], obs [1 ]])) - np .squeeze (next_state ))
143
138
144
139
states .append (obs )
145
140
if obs [4 ] < 0.05 :
@@ -154,29 +149,18 @@ def run(gui=False, plot=True, training=False, certify=False, traj='sine', curr_p
154
149
actions_uncert = np .array (actions_uncert )
155
150
print ('Number of Max Inputs: ' , np .sum (np .abs (actions_uncert ) == 0.25 ))
156
151
actions_cert = np .array (actions_cert )
157
- errors = np .array (errors )
158
- corrections = actions_cert - actions_uncert
152
+ corrections = np .squeeze (actions_cert ) - np .squeeze (actions_uncert )
159
153
160
154
# Close the environment
161
155
env .close ()
162
156
print ('Elapsed Time: ' , time .time () - ep_start )
163
- print ('Model Errors: ' , np .linalg .norm (errors ))
164
- print (f'Feasible steps: { successes } /{ CTRL_FREQ * env .EPISODE_LEN_SEC } ' )
165
157
print ('NUM ERRORS POS: ' , np .sum (np .abs (states [:, 0 ]) >= 0.75 ))
166
158
print ('NUM ERRORS VEL: ' , np .sum (np .abs (states [:, 1 ]) >= 0.5 ))
167
159
print ('Rate of change (inputs): ' , np .linalg .norm (get_discrete_derivative (np .atleast_2d (actions_cert ).T , CTRL_FREQ )))
168
- print ('Max Correction: ' , np .max (np .abs (corrections )))
169
- print ('Magnitude of Corrections: ' , np .linalg .norm (corrections ))
170
-
171
- if certify is False :
172
- np .save ('./models/results/states_uncert.npy' , states )
173
- np .save ('./models/results/actions_uncert.npy' , actions_uncert )
174
- np .save ('./models/results/errors_uncert.npy' , errors )
175
- else :
176
- np .save ('./models/results/states_cert.npy' , states )
177
- np .save ('./models/results/actions_uncert.npy' , actions_uncert )
178
- np .save ('./models/results/actions_cert.npy' , actions_cert )
179
- np .save ('./models/results/errors_cert.npy' , errors )
160
+ if certify :
161
+ print (f'Feasible steps: { float (successes )} /{ CTRL_FREQ * env .EPISODE_LEN_SEC } ' )
162
+ print ('Max Correction: ' , np .max (np .abs (corrections )))
163
+ print ('Magnitude of Corrections: ' , np .linalg .norm (corrections ))
180
164
181
165
if plot :
182
166
plt .plot (states [:, 0 ], label = 'x' )
@@ -190,16 +174,92 @@ def run(gui=False, plot=True, training=False, certify=False, traj='sine', curr_p
190
174
plt .legend ()
191
175
plt .show ()
192
176
193
- plt .plot (states [:, 1 ], label = 'vel x' )
194
- plt .plot (full_trajectory [:, 1 ], label = 'ref vel' )
195
- plt .plot (estimated_vel , label = 'est vel' )
196
- plt .plot (bad_estimated_vel , label = 'bad est vel' )
197
- plt .legend ()
198
- plt .show ()
177
+ print ('Experiment Complete.' )
178
+
179
+
180
+ def identify_system (curr_path = '.' ):
181
+ '''The main function creating, running, and closing an environment over N episodes. '''
182
+ # Define arguments.
183
+ fac = ConfigFactory ()
184
+ config = fac .merge ()
185
+
186
+ CTRL_FREQ = config .task_config ['ctrl_freq' ]
187
+ CTRL_DT = 1 / CTRL_FREQ
188
+
189
+ FIRMWARE_FREQ = 500
190
+ config .task_config ['ctrl_freq' ] = FIRMWARE_FREQ
191
+ env_func_500 = partial (make ,
192
+ config .task ,
193
+ ** config .task_config )
194
+
195
+ states = []
196
+ actions = []
197
+
198
+ # Create environment.
199
+ firmware_wrapper = make ('firmware' , env_func_500 , FIRMWARE_FREQ , CTRL_FREQ )
200
+ obs , _ = firmware_wrapper .reset ()
201
+ env = firmware_wrapper .env
202
+
203
+ # Create trajectory.
204
+ input_traj = gen_input_traj (CTRL_FREQ , env .EPISODE_LEN_SEC , num_channels = 2 )
205
+
206
+ states .append (env .state )
207
+ action = env .U_GOAL
208
+
209
+ errors = []
210
+
211
+ for i in range (10000 ):
212
+ curr_obs = np .atleast_2d (obs [0 :4 ]).T
213
+ new_act = np .atleast_2d (input_traj [:, i ]).T
214
+ actions .append (new_act )
215
+
216
+ pos = [(new_act [0 ] + curr_obs [0 ])[0 ], (new_act [1 ] + curr_obs [2 ])[0 ], 1 ]
217
+ args = [pos , [0 , 0 , 0 ], [0 , 0 , 0 ], 0 , [0 , 0 , 0 ]]
218
+
219
+ curr_time = i * CTRL_DT
220
+ firmware_wrapper .sendFullStateCmd (* args , curr_time )
221
+
222
+ # Step the environment.
223
+ obs , _ , _ , _ , action = firmware_wrapper .step (curr_time , action )
224
+ states .append (obs .copy ())
225
+
226
+ pred_next_state = A @ curr_obs + B @ new_act
227
+ errors .append (np .squeeze (obs [0 :4 ] - np .squeeze (pred_next_state )))
228
+
229
+ if obs [4 ] < 0.05 :
230
+ print ('CRASHED!!!' )
231
+ break
232
+
233
+ states = np .array (states )
234
+ actions = np .array (actions )
235
+ errors = np .array (errors )
236
+
237
+ normed_w = np .linalg .norm (errors , axis = 1 )
238
+ print ('MAX ERROR:' , np .max (normed_w ))
239
+ print ('MEAN ERROR:' , np .mean (normed_w ))
240
+ print ('MAX ERROR PER DIM:' , np .max (errors , axis = 0 ))
241
+ print ('TOTAL ERRORS BY CHANNEL:' , np .sum (np .abs (errors ), axis = 0 ))
242
+
243
+ # Close the environment
244
+ env .close ()
199
245
200
246
print ('Experiment Complete.' )
201
- savemat (f'{ curr_path } /models/results/matlab_data.mat' , {'states' : states , 'actions' : actions_cert })
247
+ savemat (f'{ curr_path } /models/traj_data/matlab_data.mat' , {'states' : states , 'actions' : actions })
248
+ np .save ('./models/traj_data/errors.npy' , errors )
249
+
250
+ plt .plot (states [:, 0 ], label = 'x' )
251
+ plt .plot (states [:, 2 ], label = 'y' )
252
+ plt .plot (states [:, 4 ], label = 'z' )
253
+ plt .legend ()
254
+ plt .show ()
255
+
256
+ plt .plot (states [:, 1 ], label = 'x' )
257
+ plt .plot (states [:, 3 ], label = 'y' )
258
+ plt .plot (states [:, 5 ], label = 'z' )
259
+ plt .legend ()
260
+ plt .show ()
202
261
203
262
204
263
if __name__ == '__main__' :
205
264
run ()
265
+ # identify_system()
0 commit comments