Skip to content

Commit 5555e97

Browse files
Adding code to get x and y traj working with precomputed
1 parent 14807f7 commit 5555e97

File tree

15 files changed

+308
-335
lines changed

15 files changed

+308
-335
lines changed

experiments/crazyflie/config_overrides/crazyflie_stab.yaml renamed to experiments/crazyflie/config_overrides/crazyflie_track.yaml

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,15 @@ task_config:
2626
randomized_init: False
2727
randomized_inertial_prop: False
2828

29-
task: stabilization
29+
task: traj_tracking
3030
task_info:
31-
stabilization_goal: [0.5, -0.5, 2]
32-
stabilization_goal_tolerance: 0.0
31+
trajectory_type: figure8
32+
num_cycles: 1
33+
trajectory_plane: 'xz'
34+
trajectory_position_offset: [0, 1]
35+
trajectory_scale: 1
36+
proj_point: [0, 0, 0.5]
37+
proj_normal: [0, 1, 1]
3338

3439
inertial_prop:
3540
M: 0.03775
@@ -43,8 +48,8 @@ task_config:
4348
upper_bounds:
4449
- 0.75
4550
- 0.5
46-
- 1
47-
- 1
51+
- 0.75
52+
- 0.5
4853
- 2
4954
- 1
5055
- 0.2
@@ -56,8 +61,8 @@ task_config:
5661
lower_bounds:
5762
- -0.75
5863
- -0.5
59-
- -1
60-
- -1
64+
- -0.75
65+
- -0.5
6166
- 0
6267
- -1
6368
- -0.2

experiments/crazyflie/config_overrides/nl_mpsc.yaml

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,18 @@ safety_filter: nl_mpsc
22
sf_config:
33
# LQR controller parameters
44
r_lin:
5-
- 90
5+
- 2
66
q_lin:
7-
- 0.001
8-
- 0.06
9-
- 0.001
10-
- 0.06
11-
- 0.00025
12-
- 80
13-
- 0.00001
14-
- 0.00001
15-
- 0.75
16-
- 1
17-
- 1
18-
- 1
7+
- 0.008
8+
- 1.85
9+
- 0.008
10+
- 1.85
1911

2012
# MPC Parameters
2113
horizon: 10
2214
warmstart: True
2315
integration_algo: rk4
24-
use_terminal_set: True
16+
use_terminal_set: False
2517

2618
# Prior info
2719
prior_info:

experiments/crazyflie/crazyflie_experiment.py

Lines changed: 112 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import numpy as np
1111
from scipy.io import savemat
1212

13-
from experiments.crazyflie.crazyflie_utils import gen_traj
13+
from experiments.crazyflie.crazyflie_utils import gen_traj, gen_input_traj
1414
from safe_control_gym.envs.benchmark_env import Task
1515
from safe_control_gym.safety_filters.mpsc.mpsc_utils import Cost_Function, get_discrete_derivative
1616
from safe_control_gym.utils.configuration import ConfigFactory
@@ -27,12 +27,18 @@
2727
print('Module \'cffirmware\' available:', FIRMWARE_INSTALLED)
2828

2929

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]])
3334

35+
B = np.array([[ 0.003886, 0.01169],
36+
[ 0.4229, -0.06055],
37+
[-0.001915, -0.0006503],
38+
[ 0.01223, 0.4419]])
3439

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='.'):
3642
'''The main function creating, running, and closing an environment over N episodes. '''
3743

3844
# Define arguments.
@@ -58,23 +64,24 @@ def run(gui=False, plot=True, training=False, certify=False, traj='sine', curr_p
5864
actions_uncert = []
5965
actions_cert = []
6066

61-
errors = []
62-
6367
# Create environment.
6468
firmware_wrapper = make('firmware', env_func_500, FIRMWARE_FREQ, CTRL_FREQ)
6569
obs, info = firmware_wrapper.reset()
6670
env = firmware_wrapper.env
6771

6872
# Create trajectory.
6973
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]])
7178

7279
# Setup controller.
7380
ctrl = make(config.algo,
7481
env_func,
7582
**config.algo_config)
7683
ctrl.gain = lqr_gain
77-
ctrl.model.U_EQ = 0
84+
ctrl.model.U_EQ = np.array([[0, 0]]).T
7885

7986
ctrl.env.X_GOAL = full_trajectory
8087
ctrl.env.TASK = Task.TRAJ_TRACKING
@@ -88,9 +95,10 @@ def run(gui=False, plot=True, training=False, certify=False, traj='sine', curr_p
8895
if training is True:
8996
safety_filter.learn(env=env)
9097
safety_filter.save(path=f'{curr_path}/models/mpsc_parameters/{config.safety_filter}_crazyflie_{task}.pkl')
91-
1 / 0
98+
1/0
9299
else:
93100
safety_filter.load(path=f'{curr_path}/models/mpsc_parameters/{config.safety_filter}_crazyflie_{task}.pkl')
101+
safety_filter.env.X_GOAL = full_trajectory
94102

95103
if config.sf_config.cost_function == Cost_Function.PRECOMPUTED_COST:
96104
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
101109
states.append(env.state)
102110
action = env.U_GOAL
103111
successes = 0
104-
estimated_vel = []
105-
bad_estimated_vel = []
106-
prev_vel = 0
107-
prev_x = 0
108-
alpha = 0.3
112+
109113
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))
111116
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)
114119
actions_uncert.append(new_act)
115120
if certify is True:
116121
certified_action, success = safety_filter.certify_action(curr_obs, new_act, info)
117122
if success:
118123
successes += 1
119124
new_act = certified_action
120125
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]
123127
vel = [0, 0, 0]
124128
acc = [0, 0, 0]
125129
yaw = 0
@@ -131,15 +135,6 @@ def run(gui=False, plot=True, training=False, certify=False, traj='sine', curr_p
131135

132136
# Step the environment.
133137
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))
143138

144139
states.append(obs)
145140
if obs[4] < 0.05:
@@ -154,29 +149,18 @@ def run(gui=False, plot=True, training=False, certify=False, traj='sine', curr_p
154149
actions_uncert = np.array(actions_uncert)
155150
print('Number of Max Inputs: ', np.sum(np.abs(actions_uncert) == 0.25))
156151
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)
159153

160154
# Close the environment
161155
env.close()
162156
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}')
165157
print('NUM ERRORS POS: ', np.sum(np.abs(states[:, 0]) >= 0.75))
166158
print('NUM ERRORS VEL: ', np.sum(np.abs(states[:, 1]) >= 0.5))
167159
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))
180164

181165
if plot:
182166
plt.plot(states[:, 0], label='x')
@@ -190,16 +174,92 @@ def run(gui=False, plot=True, training=False, certify=False, traj='sine', curr_p
190174
plt.legend()
191175
plt.show()
192176

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()
199245

200246
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()
202261

203262

204263
if __name__ == '__main__':
205264
run()
265+
# identify_system()

experiments/crazyflie/crazyflie_utils.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,24 @@ def plot_traj(CTRL_FREQ, TEST=0, CERTIFIED=False, COST_FUNCTION='one_step', M=2)
8080
plt.show()
8181

8282

83+
def gen_input_traj(CTRL_FREQ, EPISODE_LEN_SEC, num_channels=1, plot=False):
84+
num_freqs = 20
85+
86+
input_traj = []
87+
for _ in range(num_channels):
88+
freqs = np.power(np.random.rand(num_freqs+1)*2, 2)
89+
freqs = np.linspace(freqs[:-1], freqs[1:], CTRL_FREQ * EPISODE_LEN_SEC, axis=1).flatten()
90+
x = np.linspace(0, 12*np.pi, num_freqs * CTRL_FREQ * EPISODE_LEN_SEC)
91+
traj = np.sin(np.multiply(x, freqs))
92+
input_traj.append(traj*0.25)
93+
94+
if plot:
95+
plt.plot(traj)
96+
plt.show()
97+
98+
return np.array(input_traj)
99+
100+
83101
def gen_traj(CTRL_FREQ, EPISODE_LEN_SEC, plot=False):
84102
CTRL_DT = 1.0 / CTRL_FREQ
85103

@@ -133,6 +151,7 @@ def get_max_chatter(CERTIFIED, COST_FUNCTION, M):
133151
M = 10
134152

135153
# gen_traj(CTRL_FREQ=25, EPISODE_LEN_SEC=20, plot=True)
136-
plot_traj(CTRL_FREQ=25, TEST=TEST, CERTIFIED=CERTIFIED, COST_FUNCTION=COST_FUNCTION, M=M)
154+
gen_input_traj(CTRL_FREQ=25, EPISODE_LEN_SEC=20, plot=True)
155+
# plot_traj(CTRL_FREQ=25, TEST=TEST, CERTIFIED=CERTIFIED, COST_FUNCTION=COST_FUNCTION, M=M)
137156
# get_max_chatter(CERTIFIED=CERTIFIED, COST_FUNCTION=COST_FUNCTION, M=M)
138157
# calc_error(CTRL_FREQ=25, EPISODE_LEN_SEC=20, TEST=TEST, CERTIFIED=CERTIFIED, COST_FUNCTION=COST_FUNCTION, M=M)
-188 Bytes
Binary file not shown.
-1.33 KB
Binary file not shown.
1.22 KB
Binary file not shown.
-4.97 KB
Binary file not shown.
313 KB
Binary file not shown.
1.07 MB
Binary file not shown.

0 commit comments

Comments
 (0)