forked from bitcraze/crazyflie-lib-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparameters.py
More file actions
347 lines (308 loc) · 15.3 KB
/
parameters.py
File metadata and controls
347 lines (308 loc) · 15.3 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
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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
import numpy as np
from scipy.linalg import expm
from load_world import load_world
def discretize_linear_system(A, B, dt):
"""
Performs exact discretization of a continuous-time linear system.
Given a continuous-time linear system defined by:
dx/dt = A * x + B * u
This function computes the equivalent discrete-time system:
x[k+1] = Ad * x[k] + Bd * u[k]
Args:
A (np.array): The continuous-time state matrix (n x n).
B (np.array): The continuous-time input matrix (n x m).
dt (float): The discretization time step.
Returns:
tuple: A tuple containing:
- Ad (np.array): The discrete-time state matrix.
- Bd (np.array): The discrete-time input matrix.
"""
n = A.shape[0] # Number of states
m = B.shape[1] # Number of inputs
# Construct the augmented matrix for computing Ad and Bd simultaneously
# The augmented matrix M is structured as:
# M = [ A B ]
# [ 0 0 ]
# where 0 is an (m x n) zero matrix for the top block and (m x m) for the bottom block.
# Note: The bottom-right zero matrix is m x m because the input part of the augmented
# matrix has 'm' columns corresponding to 'u'.
##############3original########################
augmented_matrix = np.block([
[A, B],
[np.zeros((m, n)), np.zeros((m, m))]
])
# Compute the matrix exponential of M * delta_t
# exp(M * delta_t) = [ exp(A*delta_t) Integral(exp(A*tau) * B dtau) ]
# [ 0 I ]
#
# However, a common numerical method actually uses:
# exp(M * delta_t) = [ Ad Bd ]
# [ 0 I ]
# where M = [A, B; 0, 0] and the bottom-right identity matrix 'I' refers to input part.
# For a general solution, the augmented matrix should be:
# M_aug = [ A B ]
# [ 0 0 ]
# where the bottom-left 0 is m x n and the bottom-right 0 is m x m.
# Then expm(M_aug * dt) will yield:
# [ exp(A*dt) integral(exp(A*t)B dt from 0 to dt) ]
# [ 0 I ]
# The actual implementation for Bd from expm([A, B; 0, 0]) yields
# exp(M*dt) = [ Ad Bd ]
# [ 0 I_m] where I_m is the identity matrix of size m.
# The scipy.linalg.expm function works this way, extracting Ad and Bd from the top blocks.
result_exp = expm(augmented_matrix * dt)
# Extract Ad and Bd from the result_exp
Ad = result_exp[0:n, 0:n]
Bd = result_exp[0:n, n:n+m]
# ##############new########################
# Ad = np.eye(n) + A * dt
# Bd = B * dt
return Ad, Bd
def load_parameters():
"""
Load parameters for the quadcopter simulation.
This function sets up the parameters for dynamic programming, MPC, and simulation.
It returns dictionaries containing these parameters.
The parameters include:
- Dynamic programming parameters (N, Delta_t, T)
- MPC parameters (J, delta_t)
- Simulation parameters (mass, simulation_steps_per_input, dt_sim)
:return: dp_params, mpc_params, sim_params
"""
# ================================== Most Important Parameters ==================================
# Parameters used for Debugging:
# N = 20 # Number of time steps in the dynamic programming horizon
# M_a = 10 # Number of actions in the dynamic programming planner
# world_file = "worlds/ra_30" # File containing the world definition; implicitly defines the number of states in the DP planner
# samples_for_each_state_action_pair = 10 # Number of samples for each state-action pair during the kernel computation
# Parameters used for final paper:
N = 40 # Number of time steps in the dynamic programming horizon
M_a = 100 # Number of actions in the dynamic programming planner
world_file = "worlds/ra_50" # File containing the world definition; implicitly defines the number of states in the DP planner
samples_for_each_state_action_pair = 200 # Number of samples for each state-action pair during the kernel computation
Sigma_dt = np.zeros((12, 12)) # Process noise covariance matrix for simulation
Sigma_dt[0:2, 0:2] = 5e-4 * np.eye(2) # Process noise for position
# ================================== Quadcopter Parameters ==================================
# Updated based on cf21x_sys_eq.urdf specifications
m = 0.027 # Mass of the quadcopter in kg (from URDF)
kD = 0.1735 # Drag coefficient (keeping original)
Ixx = 1.7e-5 # Moment of inertia around the x-axis in kg*m^2 (from URDF)
Iyy = 1.7e-5 # Moment of inertia around the y-axis in kg*m^2 (from URDF)
Izz = 2.9e-5 # Moment of inertia around the z-axis in kg*m^2 (from URDF)
g = 9.81 # Gravitational acceleration in m/s^2
T_max = 0.027 * 9.81 * 2.25 # Maximum thrust in N (mass * g * thrust2weight ratio from URDF)
tau_x_max = 0.0084 # 0.1 # Maximum torque around the x-axis in N*m (estimated based on motor arm length)
tau_y_max = 0.0084# 0.1 # Maximum torque around the y-axis in N*m
tau_z_max = 0.0018 # 0.05 # Maximum torque around the z-axis in N*m
# A =
# [ 0 I3 0 0 ]
# [ 0 -kD/m*I3 A1 0 ]
# [ 0 0 0 I3 ]
# [ 0 0 0 0 ]
I3 = np.eye(3)
Z3 = np.zeros((3, 3))
# A_c = np.block([
# [Z3, I3, Z3, Z3],
# [Z3, -(kD/m) * I3,
# # A1 block starts here
# np.array([
# [0, g, 0],
# [-g, 0, 0],
# [0, 0, 0]
# ]), # A1 block ends here
# Z3],
# [Z3, Z3, Z3, I3],
# [Z3, Z3, Z3, Z3]
# ])
# # B =
# # [ 0 ]
# # [ B1 ]
# # [ 0 ]
# # [ B2 ]
# Z_3x4 = np.zeros((3, 4))
# I_3x4= np.zeros((3, 4))
# I_3x4[1:4,1:4] = np.eye(3)
# B_c = np.block([
# [Z_3x4],
# # B1 block starts here
# [np.array([
# [0, 0, 0, 0],
# [0, 0, 0, 0],
# [(1/m) * T_max, 0, 0, 0]
# ])], # B1 block ends here
# [Z_3x4],
# # B2 block starts here
# [np.array([
# [0, (1/Ixx) * tau_x_max, 0, 0],
# [0, 0, (1/Iyy) * tau_y_max, 0],
# [0, 0, 0, (1/Izz) * tau_z_max]
# ])] # B2 block ends here
# ])
Z_3x4 = np.zeros((3, 4))
I_3x4= np.zeros((3, 4))
I_3x4[0:3,1:4] = np.eye(3)
A_c = np.block([
[Z3, I3, Z3],
[Z3, -(kD/m) * I3,
# A1 block starts here
np.array([
[0, g, 0],
[-g, 0, 0],
[0, 0, 0]
]) # A1 block ends here
],
[Z3, Z3, Z3]
])
# B =
# [ 0 ]
# [ B1 ]
# [ 0 ]
# [ B2 ]
B_c = np.block([
[Z_3x4],
# B1 block starts here
[np.array([
[0, 0, 0, 0],
[0, 0, 0, 0],
[(1/m) * T_max, 0, 0, 0]
])], # B1 block ends here
[I_3x4]
])
# ================================== Compressor Parameters ==================================
# safe_set, target_set = load_world(world_file) # Load the safe and target sets from the world
safe_set, target_set = [[]], [[]]
hypercube_size = np.array([.1,.1]) # Size of the hypercube in each dimension
com_params = {
'safe_set': safe_set, # Safe set for the compressor
'target_set': target_set, # Target set for the compressor
'hypercube_size': hypercube_size, # Size of the hypercube in each dimension
}
# ================================== Model Predictive Control Parameters ==================================
# J and delta_t must match fly_LQR usage: delta_t == MPC_PLANNING_INTERVAL, J == mpc_horizon (RL_DECISION_INTERVAL/delta_t)
J = 20 # Number of steps in the MPC/LQT prediction horizon
delta_t = 0.025 # Time step duration for the MPC in seconds (must equal MPC_PLANNING_INTERVAL in RL_smpc_config / fly_LQR)
A_delta_t, B_delta_t = discretize_linear_system(A_c, B_c, delta_t)
MPC_Q = np.zeros((9, 9)) # Q Matrix of the MPC objective
MPC_Q[0:3, 0:3] = 1*np.eye(3)
MPC_Q[3:, 3:] = 1 * np.eye(6)
MPC_Q[8:9, 8:9] = 1 * np.eye(1)
MPC_R = 0.01*np.eye(4) # R Matrix of the MPC objective
A_ineq = np.array([#[-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#[ 1,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#[ 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#[ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#[ 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#[ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
])
b_ineq = np.array( [#0,0, # x limits
#0,0, # y limits
#.5,.5, # z limits
1,1, # vx limits (relaxed for better performance)
1,1, # vy limits (relaxed for better performance)
1,1, # vz limits (relaxed to prevent saturation)
0.5,0.5, # roll angle limits (reduced for stability)
0.5,0.5, # pitch angle limits (reduced for stability)
0.2,0.2, # yaw angle limits
6,6, # roll rate limits (reduced for stability)
6,6, # pitch rate limits (reduced for stability)
6,6,]) # yaw rate limits (reduced for stability)
A_ineq = np.array([
[ 0, 0, 0,-1, 0, 0, 0, 0, 0],
[ 0, 0, 0, 1, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0,-1, 0, 0, 0, 0],
[ 0, 0, 0, 0, 1, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0,-1, 0, 0, 0],
[ 0, 0, 0, 0, 0, 1, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0,-1, 0, 0],
[ 0, 0, 0, 0, 0, 0, 1, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0,-1, 0],
[ 0, 0, 0, 0, 0, 0, 0, 1, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0,-1],
[ 0, 0, 0, 0, 0, 0, 0, 0, 1],
])
b_ineq = np.array( [#0,0, # x limits
#0,0, # y limits
#.5,.5, # z limits
1,1, # vx limits (relaxed for better performance)
1,1, # vy limits (relaxed for better performance)
1,1, # vz limits (relaxed to prevent saturation)
0.5,0.5, # roll angle limits (reduced for stability)
0.5,0.5, # pitch angle limits (reduced for stability)
0.2,0.2
]) # yaw rate limits (reduced for stability)
u_ss_thrust = m * g / T_max # Steady-state thrust input
Au_ineq = np.array([[ 1, 0, 0, 0],
[-1, 0, 0, 0],
[ 0, 1, 0, 0],
[ 0,-1, 0, 0],
[ 0, 0, 1, 0],
[ 0, 0,-1, 0],
[ 0, 0, 0, 1],
[ 0, 0, 0,-1]])
bu_ineq = np.array([1-u_ss_thrust,u_ss_thrust, #[1-u_ss_thrust, u_ss_thrust, # Thrust limits
6, 6, # Roll torque limits (reduced for smaller drone)
6, 6, # Pitch torque limits (reduced for smaller drone)
6, 6]) # Yaw torque limits (reduced for smaller drone)
# Terminal constraint for the velocity, angle and angular velocity
r_underline = np.array([
# 0, # Terminal z position constraint
# 0, 0, 0, # Terminal velocity constraints (vx, vy, vz)
0, 0, 0 # Terminal angular velocity constraints (roll rate, pitch rate, yaw rate)
])
mpc_params = {
'J': J, # Execution horizon of MPC
'delta_t': delta_t, # Time step duration for the MPC in seconds
'A': A_delta_t, # Discretized state matrix for MPC
'B': B_delta_t, # Discretized input matrix for MPC
'MPC_Q': MPC_Q, # Q Matrix of the MPC objective
'MPC_R': MPC_R, # R Matrix of the MPC objective
'A_ineq': A_ineq, # State constraint matrix for MPC
'b_ineq': b_ineq, # Right hand side of the state constraint for time-steps 0,...,N-1
'A_ineq_u': Au_ineq, # Input constraint matrix for MPC
'bu_ineq': bu_ineq, # Right hand side of the input constraint for time-steps 0,...,N-1
'r_underline': r_underline, # Terminal constraint for the velocity, angle and angular velocity
}
# ================================== Dynamic Programming Parameters ==================================
Delta_t = J*delta_t # seconds, total time for every command execution
x_lower_0 = np.zeros((9,), dtype=np.float32) # Initial state for the dynamic programming planner
dp_params = {
'N': N, # Number of time steps in the dynamic programming horizon
'Delta_t': Delta_t, # Time step for dynamic programming
'T': N*Delta_t, # Total time for the mission in seconds
'command_type': 'reference_and_Q', # Type of command space
'INCLUDE_VELOCITY_IN_PLANNER': True, # Whether to include velocity in the planner
'samples_for_each_state_action_pair': samples_for_each_state_action_pair, #100, # Number of samples for each state-action pair during the kernel computation
'M_a': M_a, #50, # Number of actions in the dynamic programming planner
'x_lower_0': x_lower_0, # Initial state for the dynamic programming planner in the lower subspace
'LOAD_LAST_KERNEL': False, # Whether to load the last computed kernel
}
# ================================== Simulation Parameters ==================================
simulation_steps_per_input = 10 # Number of simulation steps per control input
dt_sim = mpc_params['delta_t'] / simulation_steps_per_input
A_dt, B_dt = discretize_linear_system(A_c, B_c, dt_sim)
sim_params = {
'simulation_steps_per_input': simulation_steps_per_input, # Number of simulation steps per control input
'dt_sim': dt_sim, # Total simulation time in seconds
'A': A_dt, # Discretized state matrix for simulation
'B': B_dt, # Discretized input matrix for simulation
'Sigma': Sigma_dt, # Process noise covariance matrix for simulation
}
return com_params, dp_params, mpc_params, sim_params