7
7
from pathlib import Path
8
8
import casadi as ca
9
9
import cyecca .lie as lie
10
- from cyecca .lie .group_so3 import so3 , SO3Quat , SO3EulerB321
11
- from cyecca .lie .group_se23 import SE23Quat , se23 , SE23LieGroupElement , SE23LieAlgebraElement
10
+ from cyecca .lie .group_so3 import so3 , SO3Quat , SO3EulerB321 , SO3Dcm
11
+ from cyecca .models .bezier import derive_dcm_to_quat
12
+ from cyecca .lie .group_se23 import (
13
+ SE23Quat ,
14
+ se23 ,
15
+ SE23LieGroupElement ,
16
+ SE23LieAlgebraElement ,
17
+ )
12
18
from cyecca .symbolic import SERIES
13
19
14
20
print ('python: ' , sys .executable )
@@ -65,7 +71,6 @@ def derive_se23_error():
65
71
# actual attitude, expressed as quaternion
66
72
q_wb = ca .SX .sym ('q_wb' , 4 )
67
73
R_wb = SO3Quat .elem (q_wb ).to_Matrix ()
68
- p_b = R_wb .T @ p_w
69
74
v_w = R_wb @ v_b
70
75
X = SE23Quat .elem (ca .vertcat (p_w , v_w , q_wb ))
71
76
@@ -100,12 +105,12 @@ def derive_so3_attitude_control():
100
105
101
106
# INPUT CONSTANTS
102
107
# -------------------------------
103
- kp = ca .SX .sym ('kp' , 3 )
108
+ kp = ca .SX .sym ("kp" , 3 )
104
109
105
110
# INPUT VARIABLES
106
111
# -------------------------------
107
- q = ca .SX .sym ('q' , 4 ) # actual quat
108
- q_r = ca .SX .sym (' q_r' , 4 ) # quat setpoint
112
+ q = ca .SX .sym ("q" , 4 ) # actual quat
113
+ q_r = ca .SX .sym (" q_r" , 4 ) # quat setpoint
109
114
110
115
# CALC
111
116
# -------------------------------
@@ -115,20 +120,15 @@ def derive_so3_attitude_control():
115
120
# Lie algebra
116
121
e = (X .inverse () * X_r ).log () # angular velocity to get to desired att in 1 sec
117
122
118
- omega = so3 .elem (e .param ).left_jacobian () @ ca .diag (kp ) @ e .param # elementwise
123
+ omega = so3 .elem (e .param ).left_jacobian () @ ca .diag (kp ) @ e .param # elementwise
119
124
120
125
# FUNCTION
121
126
# -------------------------------
122
127
f_attitude_control = ca .Function (
123
- "so3_attitude_control" ,
124
- [kp , q , q_r ],
125
- [omega ],
126
- ["kp" , "q" , "q_r" ],
127
- ["omega" ])
128
+ "so3_attitude_control" , [kp , q , q_r ], [omega ], ["kp" , "q" , "q_r" ], ["omega" ]
129
+ )
128
130
129
- return {
130
- "so3_attitude_control" : f_attitude_control
131
- }
131
+ return {"so3_attitude_control" : f_attitude_control }
132
132
133
133
134
134
def derive_outerloop_control ():
@@ -150,19 +150,26 @@ def derive_outerloop_control():
150
150
#outputs: thrust force, angular errors
151
151
zeta = ca .SX .sym ('zeta' , 9 )
152
152
at_w = ca .SX .sym ('at_w' , 3 )
153
- qc_wb = SO3Quat .elem (ca .SX .sym ('qc_wb' , 4 )) # camera orientation
154
153
q_wb = SO3Quat .elem (ca .SX .sym ('q_wb' , 4 ))
155
154
z_i = ca .SX .sym ('z_i' ) # z velocity error integral
156
155
dt = ca .SX .sym ('dt' ) # time step
157
156
158
157
# CALC
159
158
# -------------------------------
160
159
# get control input
161
- K_se23 = ca .diag (ca .vertcat (kp_pos , kp_pos , kp_pos , kp_vel , kp_vel , kp_vel , kp ))
160
+ K_se23 = ca .DM ([[- 2.77504 , 0 , 0 , 0.42856 , 0 , 0 , 0 , 0.339818 , 0 ],
161
+ [0 , - 2.77504 , 0 , 0 , 0.42856 , 0 , - 0.339818 , 0 , 0 ],
162
+ [0 , 0 , - 2.78649 , 0 , 0 , 0.485281 , 0 , 0 , 0 ],
163
+ [0.42856 , 0 , 0 , - 1.95071 , 0 , 0 , 0 , - 2.2064 , 0 ],
164
+ [0 , 0.42856 , 0 , 0 , - 1.95071 , 0 , 2.2064 , 0 , 0 ],
165
+ [0 , 0 , 0.485281 , 0 , 0 , - 2.95551 , 0 , 0 , 0 ],
166
+ [0 , - 0.339818 , 0 , 0 , 2.2064 , 0 , - 6.8016 , 0 , 0 ],
167
+ [0.339818 , 0 , 0 , - 2.2064 , 0 , 0 , 0 , - 6.8016 , 0 ],
168
+ [0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 2.82843 ]])
162
169
u_zeta = se23 .elem (zeta ).left_jacobian ()@K_se23 @zeta
163
170
164
171
# attitude control
165
- u_omega = u_zeta [6 :]
172
+ u_omega = - u_zeta [6 :]
166
173
167
174
# position control
168
175
u_v = u_zeta [0 :3 ]
@@ -178,7 +185,7 @@ def derive_outerloop_control():
178
185
179
186
# normalized thrust vector
180
187
p_norm_max = 0.3 * m * g
181
- p_term = u_v + u_a + m * at_w
188
+ p_term = q_wb @ u_v + q_wb @ u_a + m * at_w
182
189
p_norm = ca .norm_2 (p_term )
183
190
p_term = ca .if_else (p_norm > p_norm_max , p_norm_max * p_term / p_norm , p_term )
184
191
@@ -192,17 +199,17 @@ def derive_outerloop_control():
192
199
193
200
# thrust
194
201
nT = ca .norm_2 (T )
195
-
202
+
196
203
# body up is aligned with thrust
197
- zB = ca .if_else (nT > 1e-3 , T / nT , zW )
204
+ zB = ca .if_else (nT > 1e-3 , T / nT , zW )
198
205
199
206
# point y using desired camera direction
200
- ec = SO3EulerB321 .from_Quat (qc_wb )
201
- yt = ec .param [0 ]
202
- xC = ca .vertcat (ca . cos ( yt ), ca . sin ( yt ) , 0 )
207
+ # ec = SO3EulerB321.from_Quat(qc_wb)
208
+ # yt = ec.param[0]
209
+ xC = ca .vertcat (1 , 0 , 0 )
203
210
yB = ca .cross (zB , xC )
204
211
nyB = ca .norm_2 (yB )
205
- yB = ca .if_else (nyB > 1e-3 , yB / nyB , xW )
212
+ yB = ca .if_else (nyB > 1e-3 , yB / nyB , xW )
206
213
207
214
# point x using cross product of unit vectors
208
215
xB = ca .cross (yB , zB )
@@ -216,27 +223,25 @@ def derive_outerloop_control():
216
223
# deisred euler angles
217
224
# note using euler angles as set point is not problematic
218
225
# using Lie group approach for control
219
- qr_wb = SO3Quat .from_Matrix (Rd_wb )
226
+ q_sp = SO3Quat .from_Matrix (Rd_wb )
220
227
221
228
# FUNCTION
222
229
# -------------------------------
223
230
f_get_u = ca .Function (
224
- "se23_position_control" ,
225
- [thrust_trim , kp , zeta , at_w , qc_wb .param , q_wb .param , z_i , dt ], [nT , qr_wb .param , z_i_2 ],
226
-
227
- ['thrust_trim' , 'kp' , 'zeta' , 'at_w' , 'qc_wb' , 'q_wb' , 'z_i' , 'dt' ],
228
- ['nT' , 'qr_wb' , 'z_i_2' ])
231
+ "se23_control" ,
232
+ [thrust_trim , kp , zeta , at_w , q_wb .param , z_i , dt ],
233
+ [nT , z_i_2 , u_omega , q_sp .param ],
234
+ ["thrust_trim" , "kp" , "zeta" , "at_w" , "q_wb" , "z_i" , "dt" ],
235
+ ["nT" , "z_i_2" , "u_omega" , "q_sp" ],
236
+ )
229
237
230
238
f_se23_attitude_control = ca .Function (
231
- "se23_attitude_control" ,
232
- [kp , zeta ],
233
- [u_omega ],
234
- ['kp' , "zeta" ],
235
- ["omega" ])
236
-
239
+ "se23_attitude_control" , [kp , zeta ], [u_omega ], ["kp" , "zeta" ], ["omega" ]
240
+ )
241
+
237
242
return {
238
- "se23_position_control" : f_get_u ,
239
- "se23_attitude_control" : f_se23_attitude_control
243
+ "se23_control" : f_get_u ,
244
+ "se23_attitude_control" : f_se23_attitude_control ,
240
245
}
241
246
242
247
def generate_code (eqs : dict , filename , dest_dir : str , ** kwargs ):
@@ -268,7 +273,7 @@ def generate_code(eqs: dict, filename, dest_dir: str, **kwargs):
268
273
269
274
if __name__ == "__main__" :
270
275
parser = argparse .ArgumentParser ()
271
- parser .add_argument (' dest_dir' )
276
+ parser .add_argument (" dest_dir" )
272
277
args = parser .parse_args ()
273
278
274
279
print ("generating casadi equations in {:s}" .format (args .dest_dir ))
@@ -278,7 +283,7 @@ def generate_code(eqs: dict, filename, dest_dir: str, **kwargs):
278
283
eqs .update (derive_se23_error ())
279
284
280
285
for name , eq in eqs .items ():
281
- print (' eq: ' , name )
286
+ print (" eq: " , name )
282
287
283
288
generate_code (eqs , filename = "rdd2_loglinear.c" , dest_dir = args .dest_dir )
284
289
print ("complete" )
0 commit comments